18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (C) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci#include "EnvironmentJS.h"
168bf80f4bSopenharmony_ci
178bf80f4bSopenharmony_ci#include <meta/api/make_callback.h>
188bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue.h>
198bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue_registry.h>
208bf80f4bSopenharmony_ci#include <meta/interface/property/property_events.h>
218bf80f4bSopenharmony_ci#include <scene_plugin/api/camera.h> // for the classid..
228bf80f4bSopenharmony_ci#include <scene_plugin/api/node_uid.h>
238bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_ecs_scene.h>
248bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_node.h>
258bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_scene.h>
268bf80f4bSopenharmony_ci
278bf80f4bSopenharmony_ci#include <render/intf_render_context.h>
288bf80f4bSopenharmony_ci
298bf80f4bSopenharmony_ci#include "SceneJS.h"
308bf80f4bSopenharmony_ciusing namespace SCENE_NS;
318bf80f4bSopenharmony_ci
328bf80f4bSopenharmony_civoid EnvironmentJS::Init(napi_env env, napi_value exports)
338bf80f4bSopenharmony_ci{
348bf80f4bSopenharmony_ci    using namespace NapiApi;
358bf80f4bSopenharmony_ci
368bf80f4bSopenharmony_ci    BASE_NS::vector<napi_property_descriptor> node_props;
378bf80f4bSopenharmony_ci    SceneResourceImpl::GetPropertyDescs(node_props);
388bf80f4bSopenharmony_ci    // clang-format off
398bf80f4bSopenharmony_ci
408bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<uint32_t, EnvironmentJS, &EnvironmentJS::GetBackgroundType,
418bf80f4bSopenharmony_ci        &EnvironmentJS::SetBackgroundType>("backgroundType"));
428bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<Object, EnvironmentJS, &EnvironmentJS::GetEnvironmentImage,
438bf80f4bSopenharmony_ci        &EnvironmentJS::SetEnvironmentImage>("environmentImage"));
448bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<Object, EnvironmentJS, &EnvironmentJS::GetRadianceImage,
458bf80f4bSopenharmony_ci        &EnvironmentJS::SetRadianceImage>("radianceImage"));
468bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<NapiApi::Array, EnvironmentJS, &EnvironmentJS::GetIrradianceCoefficients,
478bf80f4bSopenharmony_ci        &EnvironmentJS::SetIrradianceCoefficients>("irradianceCoefficients"));
488bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<Object, EnvironmentJS, &EnvironmentJS::GetIndirectDiffuseFactor,
498bf80f4bSopenharmony_ci        &EnvironmentJS::SetIndirectDiffuseFactor>("indirectDiffuseFactor"));
508bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<Object, EnvironmentJS, &EnvironmentJS::GetIndirectSpecularFactor,
518bf80f4bSopenharmony_ci        &EnvironmentJS::SetIndirectSpecularFactor>("indirectSpecularFactor"));
528bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<Object, EnvironmentJS, &EnvironmentJS::GetEnvironmentMapFactor,
538bf80f4bSopenharmony_ci        &EnvironmentJS::SetEnvironmentMapFactor>("environmentMapFactor"));
548bf80f4bSopenharmony_ci
558bf80f4bSopenharmony_ci    // clang-format on
568bf80f4bSopenharmony_ci
578bf80f4bSopenharmony_ci    napi_value func;
588bf80f4bSopenharmony_ci    auto status = napi_define_class(env, "Environment", NAPI_AUTO_LENGTH, BaseObject::ctor<EnvironmentJS>(), nullptr,
598bf80f4bSopenharmony_ci        node_props.size(), node_props.data(), &func);
608bf80f4bSopenharmony_ci
618bf80f4bSopenharmony_ci    NapiApi::MyInstanceState* mis;
628bf80f4bSopenharmony_ci    napi_get_instance_data(env, (void**)&mis);
638bf80f4bSopenharmony_ci    mis->StoreCtor("Environment", func);
648bf80f4bSopenharmony_ci
658bf80f4bSopenharmony_ci    NapiApi::Object exp(env, exports);
668bf80f4bSopenharmony_ci
678bf80f4bSopenharmony_ci    napi_value eType;
688bf80f4bSopenharmony_ci    napi_value v;
698bf80f4bSopenharmony_ci    napi_create_object(env, &eType);
708bf80f4bSopenharmony_ci#define DECL_ENUM(enu, x)                                      \
718bf80f4bSopenharmony_ci    napi_create_uint32(env, EnvironmentBackgroundType::x, &v); \
728bf80f4bSopenharmony_ci    napi_set_named_property(env, enu, #x, v)
738bf80f4bSopenharmony_ci
748bf80f4bSopenharmony_ci    DECL_ENUM(eType, BACKGROUND_NONE);
758bf80f4bSopenharmony_ci    DECL_ENUM(eType, BACKGROUND_IMAGE);
768bf80f4bSopenharmony_ci    DECL_ENUM(eType, BACKGROUND_CUBEMAP);
778bf80f4bSopenharmony_ci    DECL_ENUM(eType, BACKGROUND_EQUIRECTANGULAR);
788bf80f4bSopenharmony_ci#undef DECL_ENUM
798bf80f4bSopenharmony_ci    exp.Set("EnvironmentBackgroundType", eType);
808bf80f4bSopenharmony_ci}
818bf80f4bSopenharmony_ci
828bf80f4bSopenharmony_cinapi_value EnvironmentJS::Dispose(NapiApi::FunctionContext<>& ctx)
838bf80f4bSopenharmony_ci{
848bf80f4bSopenharmony_ci    LOG_F("EnvironmentJS::Dispose");
858bf80f4bSopenharmony_ci    DisposeNative();
868bf80f4bSopenharmony_ci    return {};
878bf80f4bSopenharmony_ci}
888bf80f4bSopenharmony_civoid EnvironmentJS::DisposeNative()
898bf80f4bSopenharmony_ci{
908bf80f4bSopenharmony_ci    if (!disposed_) {
918bf80f4bSopenharmony_ci        CORE_LOG_F("EnvironmentJS::DisposeNative");
928bf80f4bSopenharmony_ci        disposed_ = true;
938bf80f4bSopenharmony_ci        NapiApi::Object obj = scene_.GetObject();
948bf80f4bSopenharmony_ci        auto* tro = obj.Native<TrueRootObject>();
958bf80f4bSopenharmony_ci        if (tro) {
968bf80f4bSopenharmony_ci            SceneJS* sceneJS = ((SceneJS*)tro->GetInstanceImpl(SceneJS::ID));
978bf80f4bSopenharmony_ci            if (sceneJS) {
988bf80f4bSopenharmony_ci                sceneJS->ReleaseStrongDispose((uintptr_t)&scene_);
998bf80f4bSopenharmony_ci            }
1008bf80f4bSopenharmony_ci        }
1018bf80f4bSopenharmony_ci
1028bf80f4bSopenharmony_ci        diffuseFactor_.reset();
1038bf80f4bSopenharmony_ci        specularFactor_.reset();
1048bf80f4bSopenharmony_ci        environmentFactor_.reset();
1058bf80f4bSopenharmony_ci        if (auto env = interface_pointer_cast<IEnvironment>(GetNativeObject())) {
1068bf80f4bSopenharmony_ci            // reset the native object refs
1078bf80f4bSopenharmony_ci            SetNativeObject(nullptr, false);
1088bf80f4bSopenharmony_ci            SetNativeObject(nullptr, true);
1098bf80f4bSopenharmony_ci            diffuseFactor_.reset();
1108bf80f4bSopenharmony_ci            specularFactor_.reset();
1118bf80f4bSopenharmony_ci            environmentFactor_.reset();
1128bf80f4bSopenharmony_ci
1138bf80f4bSopenharmony_ci            NapiApi::Object sceneJS = scene_.GetObject();
1148bf80f4bSopenharmony_ci            if (sceneJS) {
1158bf80f4bSopenharmony_ci                napi_value null;
1168bf80f4bSopenharmony_ci                napi_get_null(sceneJS.GetEnv(), &null);
1178bf80f4bSopenharmony_ci                sceneJS.Set("environment", null);
1188bf80f4bSopenharmony_ci
1198bf80f4bSopenharmony_ci                scene_.Reset();
1208bf80f4bSopenharmony_ci                auto* tro = sceneJS.Native<TrueRootObject>();
1218bf80f4bSopenharmony_ci                IScene::Ptr scene = interface_pointer_cast<IScene>(tro->GetNativeObject());
1228bf80f4bSopenharmony_ci                ExecSyncTask([s = BASE_NS::move(scene), e = BASE_NS::move(env)]() {
1238bf80f4bSopenharmony_ci                    auto en = interface_pointer_cast<SCENE_NS::INode>(e);
1248bf80f4bSopenharmony_ci                    s->ReleaseNode(en);
1258bf80f4bSopenharmony_ci                    en.reset();
1268bf80f4bSopenharmony_ci                    return META_NS::IAny::Ptr {};
1278bf80f4bSopenharmony_ci                });
1288bf80f4bSopenharmony_ci            }
1298bf80f4bSopenharmony_ci        }
1308bf80f4bSopenharmony_ci    }
1318bf80f4bSopenharmony_ci    scene_.Reset();
1328bf80f4bSopenharmony_ci}
1338bf80f4bSopenharmony_civoid* EnvironmentJS::GetInstanceImpl(uint32_t id)
1348bf80f4bSopenharmony_ci{
1358bf80f4bSopenharmony_ci    if (id == EnvironmentJS::ID) {
1368bf80f4bSopenharmony_ci        return this;
1378bf80f4bSopenharmony_ci    }
1388bf80f4bSopenharmony_ci    return SceneResourceImpl::GetInstanceImpl(id);
1398bf80f4bSopenharmony_ci}
1408bf80f4bSopenharmony_civoid EnvironmentJS::Finalize(napi_env env)
1418bf80f4bSopenharmony_ci{
1428bf80f4bSopenharmony_ci    // hmm.. do i need to do something BEFORE the object gets deleted..
1438bf80f4bSopenharmony_ci    DisposeNative();
1448bf80f4bSopenharmony_ci    BaseObject<EnvironmentJS>::Finalize(env);
1458bf80f4bSopenharmony_ci}
1468bf80f4bSopenharmony_ci
1478bf80f4bSopenharmony_ciEnvironmentJS::EnvironmentJS(napi_env e, napi_callback_info i)
1488bf80f4bSopenharmony_ci    : BaseObject<EnvironmentJS>(e, i), SceneResourceImpl(SceneResourceImpl::ENVIRONMENT)
1498bf80f4bSopenharmony_ci{
1508bf80f4bSopenharmony_ci    LOG_F("EnvironmentJS ++");
1518bf80f4bSopenharmony_ci    NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
1528bf80f4bSopenharmony_ci    if (!fromJs) {
1538bf80f4bSopenharmony_ci        // no arguments. so internal create.
1548bf80f4bSopenharmony_ci        // expecting caller to finish
1558bf80f4bSopenharmony_ci        return;
1568bf80f4bSopenharmony_ci    }
1578bf80f4bSopenharmony_ci
1588bf80f4bSopenharmony_ci    scene_ = { fromJs, fromJs.Arg<0>() };
1598bf80f4bSopenharmony_ci    if (!GetNativeMeta<SCENE_NS::IScene>(scene_.GetObject())) {
1608bf80f4bSopenharmony_ci        CORE_LOG_F("INVALID SCENE!");
1618bf80f4bSopenharmony_ci    }
1628bf80f4bSopenharmony_ci
1638bf80f4bSopenharmony_ci    NapiApi::Object meJs(e, fromJs.This());
1648bf80f4bSopenharmony_ci    auto* tro = scene_.GetObject().Native<TrueRootObject>();
1658bf80f4bSopenharmony_ci    auto* sceneJS = ((SceneJS*)tro->GetInstanceImpl(SceneJS::ID));
1668bf80f4bSopenharmony_ci    sceneJS->StrongDisposeHook((uintptr_t)&scene_, meJs);
1678bf80f4bSopenharmony_ci
1688bf80f4bSopenharmony_ci    IScene::Ptr scene = interface_pointer_cast<IScene>(tro->GetNativeObject());
1698bf80f4bSopenharmony_ci
1708bf80f4bSopenharmony_ci    NapiApi::Value<BASE_NS::string> name;
1718bf80f4bSopenharmony_ci    NapiApi::Object args = fromJs.Arg<1>();
1728bf80f4bSopenharmony_ci    if (auto prm = args.Get("name")) {
1738bf80f4bSopenharmony_ci        name = NapiApi::Value<BASE_NS::string>(e, prm);
1748bf80f4bSopenharmony_ci    }
1758bf80f4bSopenharmony_ci
1768bf80f4bSopenharmony_ci    BASE_NS::string nameS = name;
1778bf80f4bSopenharmony_ci    if (nameS.empty()) {
1788bf80f4bSopenharmony_ci        // create "unique" name
1798bf80f4bSopenharmony_ci        nameS = BASE_NS::to_string((uint64_t)this);
1808bf80f4bSopenharmony_ci    }
1818bf80f4bSopenharmony_ci    IEnvironment::Ptr env = GetNativeMeta<IEnvironment>(meJs);
1828bf80f4bSopenharmony_ci    // Construct native object (if needed)
1838bf80f4bSopenharmony_ci
1848bf80f4bSopenharmony_ci    if (!env) {
1858bf80f4bSopenharmony_ci        ExecSyncTask([&env, scene, nameS]() {
1868bf80f4bSopenharmony_ci            BASE_NS::string_view n = nameS; /*nodepath actually*/
1878bf80f4bSopenharmony_ci            env = scene->CreateNode<SCENE_NS::IEnvironment>(nameS);
1888bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
1898bf80f4bSopenharmony_ci        });
1908bf80f4bSopenharmony_ci    }
1918bf80f4bSopenharmony_ci
1928bf80f4bSopenharmony_ci    // process constructor args
1938bf80f4bSopenharmony_ci    // weak ref, due to being owned by the scene.
1948bf80f4bSopenharmony_ci    SetNativeObject(interface_pointer_cast<META_NS::IObject>(env), false);
1958bf80f4bSopenharmony_ci    StoreJsObj(interface_pointer_cast<META_NS::IObject>(env), meJs);
1968bf80f4bSopenharmony_ci    env.reset();
1978bf80f4bSopenharmony_ci
1988bf80f4bSopenharmony_ci    if (name) {
1998bf80f4bSopenharmony_ci        // set the name of the object. if we were given one
2008bf80f4bSopenharmony_ci        meJs.Set("name", name);
2018bf80f4bSopenharmony_ci    }
2028bf80f4bSopenharmony_ci}
2038bf80f4bSopenharmony_ci
2048bf80f4bSopenharmony_ciEnvironmentJS::~EnvironmentJS()
2058bf80f4bSopenharmony_ci{
2068bf80f4bSopenharmony_ci    LOG_F("EnvironmentJS --");
2078bf80f4bSopenharmony_ci    DisposeNative();
2088bf80f4bSopenharmony_ci    if (!GetNativeObject()) {
2098bf80f4bSopenharmony_ci        return;
2108bf80f4bSopenharmony_ci    }
2118bf80f4bSopenharmony_ci}
2128bf80f4bSopenharmony_ci
2138bf80f4bSopenharmony_cinapi_value EnvironmentJS::GetBackgroundType(NapiApi::FunctionContext<>& ctx)
2148bf80f4bSopenharmony_ci{
2158bf80f4bSopenharmony_ci    uint32_t typeI = 0;
2168bf80f4bSopenharmony_ci    if (auto env = interface_cast<IEnvironment>(GetNativeObject())) {
2178bf80f4bSopenharmony_ci        ExecSyncTask([env, &typeI]() {
2188bf80f4bSopenharmony_ci            typeI = env->Background()->GetValue();
2198bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2208bf80f4bSopenharmony_ci        });
2218bf80f4bSopenharmony_ci    }
2228bf80f4bSopenharmony_ci    return NapiApi::Value(ctx, (uint32_t)typeI);
2238bf80f4bSopenharmony_ci}
2248bf80f4bSopenharmony_ci
2258bf80f4bSopenharmony_civoid EnvironmentJS::SetBackgroundType(NapiApi::FunctionContext<uint32_t>& ctx)
2268bf80f4bSopenharmony_ci{
2278bf80f4bSopenharmony_ci    if (auto env = interface_cast<IEnvironment>(GetNativeObject())) {
2288bf80f4bSopenharmony_ci        uint32_t typeI = ctx.Arg<0>();
2298bf80f4bSopenharmony_ci        auto typeE = static_cast<EnvironmentBackgroundType>(typeI);
2308bf80f4bSopenharmony_ci        IEnvironment::BackgroundType type;
2318bf80f4bSopenharmony_ci        switch (typeE) {
2328bf80f4bSopenharmony_ci            case EnvironmentBackgroundType::BACKGROUND_NONE:
2338bf80f4bSopenharmony_ci                type = IEnvironment::BackgroundType::NONE;
2348bf80f4bSopenharmony_ci                break;
2358bf80f4bSopenharmony_ci            case EnvironmentBackgroundType::BACKGROUND_IMAGE:
2368bf80f4bSopenharmony_ci                type = IEnvironment::BackgroundType::IMAGE;
2378bf80f4bSopenharmony_ci                break;
2388bf80f4bSopenharmony_ci            case EnvironmentBackgroundType::BACKGROUND_CUBEMAP:
2398bf80f4bSopenharmony_ci                type = IEnvironment::BackgroundType::CUBEMAP;
2408bf80f4bSopenharmony_ci                break;
2418bf80f4bSopenharmony_ci            case EnvironmentBackgroundType::BACKGROUND_EQUIRECTANGULAR:
2428bf80f4bSopenharmony_ci                type = IEnvironment::BackgroundType::EQUIRECTANGULAR;
2438bf80f4bSopenharmony_ci                break;
2448bf80f4bSopenharmony_ci            default:
2458bf80f4bSopenharmony_ci                type = IEnvironment::BackgroundType::NONE;
2468bf80f4bSopenharmony_ci                break;
2478bf80f4bSopenharmony_ci        }
2488bf80f4bSopenharmony_ci        ExecSyncTask([env, &type]() {
2498bf80f4bSopenharmony_ci            env->Background()->SetValue(type);
2508bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2518bf80f4bSopenharmony_ci        });
2528bf80f4bSopenharmony_ci    }
2538bf80f4bSopenharmony_ci}
2548bf80f4bSopenharmony_cinapi_value EnvironmentJS::GetEnvironmentImage(NapiApi::FunctionContext<>& ctx)
2558bf80f4bSopenharmony_ci{
2568bf80f4bSopenharmony_ci    if (auto environment = interface_cast<SCENE_NS::IEnvironment>(GetNativeObject())) {
2578bf80f4bSopenharmony_ci        SCENE_NS::IBitmap::Ptr image;
2588bf80f4bSopenharmony_ci        ExecSyncTask([environment, &image]() {
2598bf80f4bSopenharmony_ci            image = environment->EnvironmentImage()->GetValue();
2608bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2618bf80f4bSopenharmony_ci        });
2628bf80f4bSopenharmony_ci        auto obj = interface_pointer_cast<META_NS::IObject>(image);
2638bf80f4bSopenharmony_ci
2648bf80f4bSopenharmony_ci        if (auto cached = FetchJsObj(obj)) {
2658bf80f4bSopenharmony_ci            return cached;
2668bf80f4bSopenharmony_ci        }
2678bf80f4bSopenharmony_ci
2688bf80f4bSopenharmony_ci        napi_value args[] = { scene_.GetValue(), NapiApi::Object(ctx) };
2698bf80f4bSopenharmony_ci        return CreateFromNativeInstance(ctx, obj, false, BASE_NS::countof(args), args);
2708bf80f4bSopenharmony_ci    }
2718bf80f4bSopenharmony_ci    return ctx.GetNull();
2728bf80f4bSopenharmony_ci}
2738bf80f4bSopenharmony_ci
2748bf80f4bSopenharmony_civoid EnvironmentJS::SetEnvironmentImage(NapiApi::FunctionContext<NapiApi::Object>& ctx)
2758bf80f4bSopenharmony_ci{
2768bf80f4bSopenharmony_ci    NapiApi::Object imageJS = ctx.Arg<0>();
2778bf80f4bSopenharmony_ci    SCENE_NS::IBitmap::Ptr image;
2788bf80f4bSopenharmony_ci    if (auto nat = imageJS.Native<TrueRootObject>()) {
2798bf80f4bSopenharmony_ci        image = interface_pointer_cast<SCENE_NS::IBitmap>(nat->GetNativeObject());
2808bf80f4bSopenharmony_ci    }
2818bf80f4bSopenharmony_ci    if (auto environment = interface_cast<SCENE_NS::IEnvironment>(GetNativeObject())) {
2828bf80f4bSopenharmony_ci        ExecSyncTask([environment, image]() {
2838bf80f4bSopenharmony_ci            environment->EnvironmentImage()->SetValue(image);
2848bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2858bf80f4bSopenharmony_ci        });
2868bf80f4bSopenharmony_ci    }
2878bf80f4bSopenharmony_ci}
2888bf80f4bSopenharmony_ci
2898bf80f4bSopenharmony_cinapi_value EnvironmentJS::GetRadianceImage(NapiApi::FunctionContext<>& ctx)
2908bf80f4bSopenharmony_ci{
2918bf80f4bSopenharmony_ci    if (auto environment = interface_cast<SCENE_NS::IEnvironment>(GetNativeObject())) {
2928bf80f4bSopenharmony_ci        SCENE_NS::IBitmap::Ptr image;
2938bf80f4bSopenharmony_ci        ExecSyncTask([environment, &image]() {
2948bf80f4bSopenharmony_ci            image = environment->RadianceImage()->GetValue();
2958bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2968bf80f4bSopenharmony_ci        });
2978bf80f4bSopenharmony_ci        auto obj = interface_pointer_cast<META_NS::IObject>(image);
2988bf80f4bSopenharmony_ci
2998bf80f4bSopenharmony_ci        if (auto cached = FetchJsObj(obj)) {
3008bf80f4bSopenharmony_ci            return cached;
3018bf80f4bSopenharmony_ci        }
3028bf80f4bSopenharmony_ci
3038bf80f4bSopenharmony_ci        napi_value args[] = { scene_.GetValue(), NapiApi::Object(ctx) };
3048bf80f4bSopenharmony_ci        return CreateFromNativeInstance(ctx, obj, false, BASE_NS::countof(args), args);
3058bf80f4bSopenharmony_ci    }
3068bf80f4bSopenharmony_ci    return ctx.GetNull();
3078bf80f4bSopenharmony_ci}
3088bf80f4bSopenharmony_ci
3098bf80f4bSopenharmony_civoid EnvironmentJS::SetRadianceImage(NapiApi::FunctionContext<NapiApi::Object>& ctx)
3108bf80f4bSopenharmony_ci{
3118bf80f4bSopenharmony_ci    NapiApi::Object imageJS = ctx.Arg<0>();
3128bf80f4bSopenharmony_ci    SCENE_NS::IBitmap::Ptr image;
3138bf80f4bSopenharmony_ci    if (auto nat = imageJS.Native<TrueRootObject>()) {
3148bf80f4bSopenharmony_ci        image = interface_pointer_cast<SCENE_NS::IBitmap>(nat->GetNativeObject());
3158bf80f4bSopenharmony_ci    }
3168bf80f4bSopenharmony_ci    if (auto environment = interface_cast<SCENE_NS::IEnvironment>(GetNativeObject())) {
3178bf80f4bSopenharmony_ci        ExecSyncTask([environment, image]() {
3188bf80f4bSopenharmony_ci            environment->RadianceImage()->SetValue(image);
3198bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
3208bf80f4bSopenharmony_ci        });
3218bf80f4bSopenharmony_ci    }
3228bf80f4bSopenharmony_ci}
3238bf80f4bSopenharmony_cinapi_value EnvironmentJS::GetIrradianceCoefficients(NapiApi::FunctionContext<>& ctx)
3248bf80f4bSopenharmony_ci{
3258bf80f4bSopenharmony_ci    BASE_NS::vector<BASE_NS::Math::Vec3> coeffs;
3268bf80f4bSopenharmony_ci    if (auto environment = interface_cast<SCENE_NS::IEnvironment>(GetNativeObject())) {
3278bf80f4bSopenharmony_ci        ExecSyncTask([environment, &coeffs]() {
3288bf80f4bSopenharmony_ci            coeffs = environment->IrradianceCoefficients()->GetValue();
3298bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
3308bf80f4bSopenharmony_ci        });
3318bf80f4bSopenharmony_ci    }
3328bf80f4bSopenharmony_ci    NapiApi::Array res(ctx, 9); // array size 9
3338bf80f4bSopenharmony_ci    size_t index = 0;
3348bf80f4bSopenharmony_ci    for (auto& v : coeffs) {
3358bf80f4bSopenharmony_ci        NapiApi::Object vec(ctx);
3368bf80f4bSopenharmony_ci        vec.Set("x", NapiApi::Value<float>(ctx, v.x));
3378bf80f4bSopenharmony_ci        vec.Set("y", NapiApi::Value<float>(ctx, v.y));
3388bf80f4bSopenharmony_ci        vec.Set("z", NapiApi::Value<float>(ctx, v.z));
3398bf80f4bSopenharmony_ci        res.Set(index++, vec);
3408bf80f4bSopenharmony_ci    }
3418bf80f4bSopenharmony_ci    return res;
3428bf80f4bSopenharmony_ci}
3438bf80f4bSopenharmony_civoid EnvironmentJS::SetIrradianceCoefficients(NapiApi::FunctionContext<NapiApi::Array>& ctx)
3448bf80f4bSopenharmony_ci{
3458bf80f4bSopenharmony_ci    NapiApi::Array coeffJS = ctx.Arg<0>();
3468bf80f4bSopenharmony_ci    if (coeffJS.Count() != 9) { // array size 9
3478bf80f4bSopenharmony_ci        // not enough elements in array
3488bf80f4bSopenharmony_ci        return;
3498bf80f4bSopenharmony_ci    }
3508bf80f4bSopenharmony_ci    BASE_NS::vector<BASE_NS::Math::Vec3> coeffs;
3518bf80f4bSopenharmony_ci    for (auto i = 0; i < coeffJS.Count(); i++) {
3528bf80f4bSopenharmony_ci        NapiApi::Object obj = coeffJS.Get<NapiApi::Object>(i);
3538bf80f4bSopenharmony_ci        if (!obj) {
3548bf80f4bSopenharmony_ci            // not an object in array
3558bf80f4bSopenharmony_ci            return;
3568bf80f4bSopenharmony_ci        }
3578bf80f4bSopenharmony_ci        auto x = obj.Get<float>("x");
3588bf80f4bSopenharmony_ci        auto y = obj.Get<float>("y");
3598bf80f4bSopenharmony_ci        auto z = obj.Get<float>("z");
3608bf80f4bSopenharmony_ci        if (!x || !y || !z) {
3618bf80f4bSopenharmony_ci            // invalid kind of object.
3628bf80f4bSopenharmony_ci            return;
3638bf80f4bSopenharmony_ci        }
3648bf80f4bSopenharmony_ci        coeffs.emplace_back((float)x, (float)y, (float)z);
3658bf80f4bSopenharmony_ci    }
3668bf80f4bSopenharmony_ci
3678bf80f4bSopenharmony_ci    if (auto environment = interface_cast<SCENE_NS::IEnvironment>(GetNativeObject())) {
3688bf80f4bSopenharmony_ci        ExecSyncTask([environment, &coeffs]() {
3698bf80f4bSopenharmony_ci            environment->IrradianceCoefficients()->SetValue(coeffs);
3708bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
3718bf80f4bSopenharmony_ci        });
3728bf80f4bSopenharmony_ci    }
3738bf80f4bSopenharmony_ci}
3748bf80f4bSopenharmony_ci
3758bf80f4bSopenharmony_cinapi_value EnvironmentJS::GetIndirectDiffuseFactor(NapiApi::FunctionContext<>& ctx)
3768bf80f4bSopenharmony_ci{
3778bf80f4bSopenharmony_ci    auto node = interface_pointer_cast<SCENE_NS::IEnvironment>(GetThisNativeObject(ctx));
3788bf80f4bSopenharmony_ci    if (!node) {
3798bf80f4bSopenharmony_ci        return ctx.GetUndefined();
3808bf80f4bSopenharmony_ci    }
3818bf80f4bSopenharmony_ci    if (diffuseFactor_ == nullptr) {
3828bf80f4bSopenharmony_ci        diffuseFactor_ = BASE_NS::make_unique<Vec4Proxy>(ctx, node->IndirectDiffuseFactor());
3838bf80f4bSopenharmony_ci    }
3848bf80f4bSopenharmony_ci    return *diffuseFactor_;
3858bf80f4bSopenharmony_ci}
3868bf80f4bSopenharmony_ci
3878bf80f4bSopenharmony_civoid EnvironmentJS::SetIndirectDiffuseFactor(NapiApi::FunctionContext<NapiApi::Object>& ctx)
3888bf80f4bSopenharmony_ci{
3898bf80f4bSopenharmony_ci    auto node = interface_pointer_cast<SCENE_NS::IEnvironment>(GetThisNativeObject(ctx));
3908bf80f4bSopenharmony_ci    if (!node) {
3918bf80f4bSopenharmony_ci        return;
3928bf80f4bSopenharmony_ci    }
3938bf80f4bSopenharmony_ci    NapiApi::Object obj = ctx.Arg<0>();
3948bf80f4bSopenharmony_ci    if (diffuseFactor_ == nullptr) {
3958bf80f4bSopenharmony_ci        diffuseFactor_ = BASE_NS::make_unique<Vec4Proxy>(ctx, node->IndirectDiffuseFactor());
3968bf80f4bSopenharmony_ci    }
3978bf80f4bSopenharmony_ci    diffuseFactor_->SetValue(obj);
3988bf80f4bSopenharmony_ci}
3998bf80f4bSopenharmony_ci
4008bf80f4bSopenharmony_cinapi_value EnvironmentJS::GetIndirectSpecularFactor(NapiApi::FunctionContext<>& ctx)
4018bf80f4bSopenharmony_ci{
4028bf80f4bSopenharmony_ci    auto node = interface_pointer_cast<SCENE_NS::IEnvironment>(GetThisNativeObject(ctx));
4038bf80f4bSopenharmony_ci    if (!node) {
4048bf80f4bSopenharmony_ci        return ctx.GetUndefined();
4058bf80f4bSopenharmony_ci    }
4068bf80f4bSopenharmony_ci    if (specularFactor_ == nullptr) {
4078bf80f4bSopenharmony_ci        specularFactor_ = BASE_NS::make_unique<Vec4Proxy>(ctx, node->IndirectSpecularFactor());
4088bf80f4bSopenharmony_ci    }
4098bf80f4bSopenharmony_ci    return *specularFactor_;
4108bf80f4bSopenharmony_ci}
4118bf80f4bSopenharmony_ci
4128bf80f4bSopenharmony_civoid EnvironmentJS::SetIndirectSpecularFactor(NapiApi::FunctionContext<NapiApi::Object>& ctx)
4138bf80f4bSopenharmony_ci{
4148bf80f4bSopenharmony_ci    auto node = interface_pointer_cast<SCENE_NS::IEnvironment>(GetThisNativeObject(ctx));
4158bf80f4bSopenharmony_ci    if (!node) {
4168bf80f4bSopenharmony_ci        return;
4178bf80f4bSopenharmony_ci    }
4188bf80f4bSopenharmony_ci    NapiApi::Object obj = ctx.Arg<0>();
4198bf80f4bSopenharmony_ci    if (specularFactor_ == nullptr) {
4208bf80f4bSopenharmony_ci        specularFactor_ = BASE_NS::make_unique<Vec4Proxy>(ctx, node->IndirectSpecularFactor());
4218bf80f4bSopenharmony_ci    }
4228bf80f4bSopenharmony_ci    specularFactor_->SetValue(obj);
4238bf80f4bSopenharmony_ci}
4248bf80f4bSopenharmony_ci
4258bf80f4bSopenharmony_cinapi_value EnvironmentJS::GetEnvironmentMapFactor(NapiApi::FunctionContext<>& ctx)
4268bf80f4bSopenharmony_ci{
4278bf80f4bSopenharmony_ci    auto node = interface_pointer_cast<SCENE_NS::IEnvironment>(GetThisNativeObject(ctx));
4288bf80f4bSopenharmony_ci    if (!node) {
4298bf80f4bSopenharmony_ci        return ctx.GetUndefined();
4308bf80f4bSopenharmony_ci    }
4318bf80f4bSopenharmony_ci    if (environmentFactor_ == nullptr) {
4328bf80f4bSopenharmony_ci        environmentFactor_ = BASE_NS::make_unique<Vec4Proxy>(ctx, node->EnvMapFactor());
4338bf80f4bSopenharmony_ci    }
4348bf80f4bSopenharmony_ci    return *environmentFactor_;
4358bf80f4bSopenharmony_ci}
4368bf80f4bSopenharmony_ci
4378bf80f4bSopenharmony_civoid EnvironmentJS::SetEnvironmentMapFactor(NapiApi::FunctionContext<NapiApi::Object>& ctx)
4388bf80f4bSopenharmony_ci{
4398bf80f4bSopenharmony_ci    auto node = interface_pointer_cast<SCENE_NS::IEnvironment>(GetThisNativeObject(ctx));
4408bf80f4bSopenharmony_ci    if (!node) {
4418bf80f4bSopenharmony_ci        return;
4428bf80f4bSopenharmony_ci    }
4438bf80f4bSopenharmony_ci    NapiApi::Object obj = ctx.Arg<0>();
4448bf80f4bSopenharmony_ci    if (environmentFactor_ == nullptr) {
4458bf80f4bSopenharmony_ci        environmentFactor_ = BASE_NS::make_unique<Vec4Proxy>(ctx, node->EnvMapFactor());
4468bf80f4bSopenharmony_ci    }
4478bf80f4bSopenharmony_ci    environmentFactor_->SetValue(obj);
4488bf80f4bSopenharmony_ci}
449