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 "ToneMapJS.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_postprocess.h>
268bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_scene.h>
278bf80f4bSopenharmony_ci
288bf80f4bSopenharmony_ci#include <render/intf_render_context.h>
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_ci#include "PostProcJS.h"
318bf80f4bSopenharmony_ciusing IntfPtr = BASE_NS::shared_ptr<CORE_NS::IInterface>;
328bf80f4bSopenharmony_ciusing IntfWeakPtr = BASE_NS::weak_ptr<CORE_NS::IInterface>;
338bf80f4bSopenharmony_ciusing namespace SCENE_NS;
348bf80f4bSopenharmony_ciSCENE_NS::ITonemap::TonemapType ConvertTo(ToneMapJS::ToneMappingType typeI)
358bf80f4bSopenharmony_ci{
368bf80f4bSopenharmony_ci    SCENE_NS::ITonemap::TonemapType type;
378bf80f4bSopenharmony_ci    switch (typeI) {
388bf80f4bSopenharmony_ci        case ToneMapJS::ToneMappingType::ACES:
398bf80f4bSopenharmony_ci            type = SCENE_NS::ITonemap::TonemapType::ACES;
408bf80f4bSopenharmony_ci            break;
418bf80f4bSopenharmony_ci        case ToneMapJS::ToneMappingType::ACES_2020:
428bf80f4bSopenharmony_ci            type = SCENE_NS::ITonemap::TonemapType::ACES_2020;
438bf80f4bSopenharmony_ci            break;
448bf80f4bSopenharmony_ci        case ToneMapJS::ToneMappingType::FILMIC:
458bf80f4bSopenharmony_ci            type = SCENE_NS::ITonemap::TonemapType::FILMIC;
468bf80f4bSopenharmony_ci            break;
478bf80f4bSopenharmony_ci        default:
488bf80f4bSopenharmony_ci            // default from lowlev..
498bf80f4bSopenharmony_ci            type = ITonemap::TonemapType::ACES;
508bf80f4bSopenharmony_ci            break;
518bf80f4bSopenharmony_ci    }
528bf80f4bSopenharmony_ci    return type;
538bf80f4bSopenharmony_ci}
548bf80f4bSopenharmony_ciToneMapJS::ToneMappingType ConvertFrom(SCENE_NS::ITonemap::TonemapType typeI)
558bf80f4bSopenharmony_ci{
568bf80f4bSopenharmony_ci    ToneMapJS::ToneMappingType type;
578bf80f4bSopenharmony_ci    switch (typeI) {
588bf80f4bSopenharmony_ci        case SCENE_NS::ITonemap::TonemapType::ACES:
598bf80f4bSopenharmony_ci            type = ToneMapJS::ToneMappingType::ACES;
608bf80f4bSopenharmony_ci            break;
618bf80f4bSopenharmony_ci        case SCENE_NS::ITonemap::TonemapType::ACES_2020:
628bf80f4bSopenharmony_ci            type = ToneMapJS::ToneMappingType::ACES_2020;
638bf80f4bSopenharmony_ci            break;
648bf80f4bSopenharmony_ci        case SCENE_NS::ITonemap::TonemapType::FILMIC:
658bf80f4bSopenharmony_ci            type = ToneMapJS::ToneMappingType ::FILMIC;
668bf80f4bSopenharmony_ci            break;
678bf80f4bSopenharmony_ci        default:
688bf80f4bSopenharmony_ci            // default from lowlev..
698bf80f4bSopenharmony_ci            type = ToneMapJS::ToneMappingType ::ACES;
708bf80f4bSopenharmony_ci            break;
718bf80f4bSopenharmony_ci    }
728bf80f4bSopenharmony_ci    return type;
738bf80f4bSopenharmony_ci}
748bf80f4bSopenharmony_ci
758bf80f4bSopenharmony_ciSCENE_NS::ITonemap::TonemapType ConvertTo(uint32_t typeI)
768bf80f4bSopenharmony_ci{
778bf80f4bSopenharmony_ci    return ConvertTo(static_cast<ToneMapJS::ToneMappingType>(typeI));
788bf80f4bSopenharmony_ci}
798bf80f4bSopenharmony_civoid ToneMapJS::Init(napi_env env, napi_value exports)
808bf80f4bSopenharmony_ci{
818bf80f4bSopenharmony_ci    using namespace NapiApi;
828bf80f4bSopenharmony_ci
838bf80f4bSopenharmony_ci    BASE_NS::vector<napi_property_descriptor> node_props;
848bf80f4bSopenharmony_ci    // clang-format off
858bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<uint32_t, ToneMapJS, &ToneMapJS::GetType, &ToneMapJS::SetType>("type"));
868bf80f4bSopenharmony_ci    node_props.emplace_back(GetSetProperty<float, ToneMapJS, &ToneMapJS::GetExposure,
878bf80f4bSopenharmony_ci        &ToneMapJS::SetExposure>("exposure"));
888bf80f4bSopenharmony_ci    node_props.push_back(MakeTROMethod<NapiApi::FunctionContext<>, ToneMapJS, &ToneMapJS::Dispose>("destroy"));
898bf80f4bSopenharmony_ci    // clang-format on
908bf80f4bSopenharmony_ci
918bf80f4bSopenharmony_ci    napi_value func;
928bf80f4bSopenharmony_ci    auto status = napi_define_class(env, "ToneMappingSettings", NAPI_AUTO_LENGTH, BaseObject::ctor<ToneMapJS>(),
938bf80f4bSopenharmony_ci        nullptr, node_props.size(), node_props.data(), &func);
948bf80f4bSopenharmony_ci
958bf80f4bSopenharmony_ci    NapiApi::MyInstanceState* mis;
968bf80f4bSopenharmony_ci    napi_get_instance_data(env, (void**)&mis);
978bf80f4bSopenharmony_ci    mis->StoreCtor("ToneMappingSettings", func);
988bf80f4bSopenharmony_ci
998bf80f4bSopenharmony_ci    NapiApi::Object exp(env, exports);
1008bf80f4bSopenharmony_ci
1018bf80f4bSopenharmony_ci    napi_value eType;
1028bf80f4bSopenharmony_ci    napi_value v;
1038bf80f4bSopenharmony_ci    napi_create_object(env, &eType);
1048bf80f4bSopenharmony_ci#define DECL_ENUM(enu, x)                            \
1058bf80f4bSopenharmony_ci    napi_create_uint32(env, ToneMappingType::x, &v); \
1068bf80f4bSopenharmony_ci    napi_set_named_property(env, enu, #x, v);
1078bf80f4bSopenharmony_ci
1088bf80f4bSopenharmony_ci    DECL_ENUM(eType, ACES);
1098bf80f4bSopenharmony_ci    DECL_ENUM(eType, ACES_2020);
1108bf80f4bSopenharmony_ci    DECL_ENUM(eType, FILMIC);
1118bf80f4bSopenharmony_ci#undef DECL_ENUM
1128bf80f4bSopenharmony_ci    exp.Set("ToneMappingType", eType);
1138bf80f4bSopenharmony_ci}
1148bf80f4bSopenharmony_ci
1158bf80f4bSopenharmony_cinapi_value ToneMapJS::Dispose(NapiApi::FunctionContext<>& ctx)
1168bf80f4bSopenharmony_ci{
1178bf80f4bSopenharmony_ci    LOG_F("ToneMapJS::Dispose");
1188bf80f4bSopenharmony_ci    DisposeNative();
1198bf80f4bSopenharmony_ci    return {};
1208bf80f4bSopenharmony_ci}
1218bf80f4bSopenharmony_civoid ToneMapJS::DisposeNative()
1228bf80f4bSopenharmony_ci{
1238bf80f4bSopenharmony_ci    if (!disposed_) {
1248bf80f4bSopenharmony_ci        disposed_ = true;
1258bf80f4bSopenharmony_ci        LOG_F("ToneMapJS::DisposeNative");
1268bf80f4bSopenharmony_ci        if (auto tmp = interface_pointer_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
1278bf80f4bSopenharmony_ci            // reset the native object refs
1288bf80f4bSopenharmony_ci            SetNativeObject(nullptr, false);
1298bf80f4bSopenharmony_ci            SetNativeObject(nullptr, true);
1308bf80f4bSopenharmony_ci
1318bf80f4bSopenharmony_ci            ExecSyncTask([scn = BASE_NS::move(tmp)]() { return META_NS::IAny::Ptr {}; });
1328bf80f4bSopenharmony_ci        }
1338bf80f4bSopenharmony_ci    }
1348bf80f4bSopenharmony_ci}
1358bf80f4bSopenharmony_civoid* ToneMapJS::GetInstanceImpl(uint32_t id)
1368bf80f4bSopenharmony_ci{
1378bf80f4bSopenharmony_ci    if (id == ToneMapJS::ID) {
1388bf80f4bSopenharmony_ci        return this;
1398bf80f4bSopenharmony_ci    }
1408bf80f4bSopenharmony_ci    return nullptr;
1418bf80f4bSopenharmony_ci}
1428bf80f4bSopenharmony_civoid ToneMapJS::Finalize(napi_env env)
1438bf80f4bSopenharmony_ci{
1448bf80f4bSopenharmony_ci    // hmm.. do i need to do something BEFORE the object gets deleted..
1458bf80f4bSopenharmony_ci    DisposeNative();
1468bf80f4bSopenharmony_ci    BaseObject<ToneMapJS>::Finalize(env);
1478bf80f4bSopenharmony_ci}
1488bf80f4bSopenharmony_ci
1498bf80f4bSopenharmony_ciToneMapJS::ToneMapJS(napi_env e, napi_callback_info i) : BaseObject<ToneMapJS>(e, i)
1508bf80f4bSopenharmony_ci{
1518bf80f4bSopenharmony_ci    LOG_F("ToneMapJS ++");
1528bf80f4bSopenharmony_ci    NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
1538bf80f4bSopenharmony_ci    if (!fromJs) {
1548bf80f4bSopenharmony_ci        // no arguments. so internal create.
1558bf80f4bSopenharmony_ci        // expecting caller to finish
1568bf80f4bSopenharmony_ci        return;
1578bf80f4bSopenharmony_ci    }
1588bf80f4bSopenharmony_ci    // postprocess that we bind to..
1598bf80f4bSopenharmony_ci    NapiApi::Object postProcJS = fromJs.Arg<0>();
1608bf80f4bSopenharmony_ci    auto postproc = GetNativeMeta<SCENE_NS::IPostProcess>(postProcJS);
1618bf80f4bSopenharmony_ci    NapiApi::Object toneMapArgs = fromJs.Arg<1>();
1628bf80f4bSopenharmony_ci    // now, based on parameters, initialize the object
1638bf80f4bSopenharmony_ci    // so it is a tonemap
1648bf80f4bSopenharmony_ci    float exposure = toneMapArgs.Get<float>("exposure").valueOrDefault(0.7);
1658bf80f4bSopenharmony_ci    SCENE_NS::ITonemap::TonemapType type =
1668bf80f4bSopenharmony_ci        ConvertTo(toneMapArgs.Get<uint32_t>("type").valueOrDefault(ToneMappingType::ACES));
1678bf80f4bSopenharmony_ci
1688bf80f4bSopenharmony_ci    auto tonemap = GetNativeObjectParam<SCENE_NS::ITonemap>(toneMapArgs);
1698bf80f4bSopenharmony_ci
1708bf80f4bSopenharmony_ci    ExecSyncTask([&tonemap, exposure, type, postproc]() -> META_NS::IAny::Ptr {
1718bf80f4bSopenharmony_ci        if (!tonemap) {
1728bf80f4bSopenharmony_ci            tonemap = META_NS::GetObjectRegistry().Create<SCENE_NS::ITonemap>(SCENE_NS::ClassId::Tonemap);
1738bf80f4bSopenharmony_ci        }
1748bf80f4bSopenharmony_ci        tonemap->Type()->SetValue(type);
1758bf80f4bSopenharmony_ci        tonemap->Exposure()->SetValue(exposure);
1768bf80f4bSopenharmony_ci        tonemap->Enabled()->SetValue(true);
1778bf80f4bSopenharmony_ci        postproc->Tonemap()->SetValue(tonemap);
1788bf80f4bSopenharmony_ci        return {};
1798bf80f4bSopenharmony_ci    });
1808bf80f4bSopenharmony_ci    auto obj = interface_pointer_cast<META_NS::IObject>(tonemap);
1818bf80f4bSopenharmony_ci    // process constructor args..
1828bf80f4bSopenharmony_ci    NapiApi::Object meJs(e, fromJs.This());
1838bf80f4bSopenharmony_ci    // weak ref, due to the ToneMap class being owned by the postprocess.
1848bf80f4bSopenharmony_ci    SetNativeObject(obj, false);
1858bf80f4bSopenharmony_ci    StoreJsObj(obj, meJs);
1868bf80f4bSopenharmony_ci}
1878bf80f4bSopenharmony_ci
1888bf80f4bSopenharmony_ciToneMapJS::~ToneMapJS()
1898bf80f4bSopenharmony_ci{
1908bf80f4bSopenharmony_ci    LOG_F("ToneMapJS --");
1918bf80f4bSopenharmony_ci    DisposeNative();
1928bf80f4bSopenharmony_ci    if (!GetNativeObject()) {
1938bf80f4bSopenharmony_ci        return;
1948bf80f4bSopenharmony_ci    }
1958bf80f4bSopenharmony_ci}
1968bf80f4bSopenharmony_ci
1978bf80f4bSopenharmony_cinapi_value ToneMapJS::GetType(NapiApi::FunctionContext<>& ctx)
1988bf80f4bSopenharmony_ci{
1998bf80f4bSopenharmony_ci    SCENE_NS::ITonemap::TonemapType type = SCENE_NS::ITonemap::TonemapType::ACES; // default
2008bf80f4bSopenharmony_ci    if (auto toneMap = interface_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
2018bf80f4bSopenharmony_ci        ExecSyncTask([toneMap, &type]() {
2028bf80f4bSopenharmony_ci            type = toneMap->Type()->GetValue();
2038bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2048bf80f4bSopenharmony_ci        });
2058bf80f4bSopenharmony_ci    }
2068bf80f4bSopenharmony_ci
2078bf80f4bSopenharmony_ci    auto typeI = ConvertFrom(type);
2088bf80f4bSopenharmony_ci    napi_value value;
2098bf80f4bSopenharmony_ci    napi_status status = napi_create_uint32(ctx, static_cast<uint32_t>(typeI), &value);
2108bf80f4bSopenharmony_ci    return value;
2118bf80f4bSopenharmony_ci}
2128bf80f4bSopenharmony_civoid ToneMapJS::SetType(NapiApi::FunctionContext<uint32_t>& ctx)
2138bf80f4bSopenharmony_ci{
2148bf80f4bSopenharmony_ci    auto type = ConvertTo(ctx.Arg<0>());
2158bf80f4bSopenharmony_ci
2168bf80f4bSopenharmony_ci    if (auto toneMap = interface_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
2178bf80f4bSopenharmony_ci        ExecSyncTask([toneMap, type]() {
2188bf80f4bSopenharmony_ci            toneMap->Type()->SetValue(type);
2198bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2208bf80f4bSopenharmony_ci        });
2218bf80f4bSopenharmony_ci    }
2228bf80f4bSopenharmony_ci}
2238bf80f4bSopenharmony_ci
2248bf80f4bSopenharmony_cinapi_value ToneMapJS::GetExposure(NapiApi::FunctionContext<>& ctx)
2258bf80f4bSopenharmony_ci{
2268bf80f4bSopenharmony_ci    float exp = 0.0;
2278bf80f4bSopenharmony_ci    if (auto toneMap = interface_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
2288bf80f4bSopenharmony_ci        ExecSyncTask([toneMap, &exp]() {
2298bf80f4bSopenharmony_ci            exp = toneMap->Exposure()->GetValue();
2308bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2318bf80f4bSopenharmony_ci        });
2328bf80f4bSopenharmony_ci    }
2338bf80f4bSopenharmony_ci
2348bf80f4bSopenharmony_ci    napi_value value;
2358bf80f4bSopenharmony_ci    napi_status status = napi_create_double(ctx, exp, &value);
2368bf80f4bSopenharmony_ci    return value;
2378bf80f4bSopenharmony_ci}
2388bf80f4bSopenharmony_ci
2398bf80f4bSopenharmony_civoid ToneMapJS::SetExposure(NapiApi::FunctionContext<float>& ctx)
2408bf80f4bSopenharmony_ci{
2418bf80f4bSopenharmony_ci    float exp = ctx.Arg<0>();
2428bf80f4bSopenharmony_ci    if (auto toneMap = interface_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
2438bf80f4bSopenharmony_ci        ExecSyncTask([toneMap, exp]() {
2448bf80f4bSopenharmony_ci            toneMap->Exposure()->SetValue(exp);
2458bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2468bf80f4bSopenharmony_ci        });
2478bf80f4bSopenharmony_ci    }
2488bf80f4bSopenharmony_ci}
249