/* * Copyright (C) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ToneMapJS.h" #include #include #include #include #include //for the classid... #include #include #include #include #include #include #include "PostProcJS.h" using IntfPtr = BASE_NS::shared_ptr; using IntfWeakPtr = BASE_NS::weak_ptr; using namespace SCENE_NS; SCENE_NS::ITonemap::TonemapType ConvertTo(ToneMapJS::ToneMappingType typeI) { SCENE_NS::ITonemap::TonemapType type; switch (typeI) { case ToneMapJS::ToneMappingType::ACES: type = SCENE_NS::ITonemap::TonemapType::ACES; break; case ToneMapJS::ToneMappingType::ACES_2020: type = SCENE_NS::ITonemap::TonemapType::ACES_2020; break; case ToneMapJS::ToneMappingType::FILMIC: type = SCENE_NS::ITonemap::TonemapType::FILMIC; break; default: // default from lowlev.. type = ITonemap::TonemapType::ACES; break; } return type; } ToneMapJS::ToneMappingType ConvertFrom(SCENE_NS::ITonemap::TonemapType typeI) { ToneMapJS::ToneMappingType type; switch (typeI) { case SCENE_NS::ITonemap::TonemapType::ACES: type = ToneMapJS::ToneMappingType::ACES; break; case SCENE_NS::ITonemap::TonemapType::ACES_2020: type = ToneMapJS::ToneMappingType::ACES_2020; break; case SCENE_NS::ITonemap::TonemapType::FILMIC: type = ToneMapJS::ToneMappingType ::FILMIC; break; default: // default from lowlev.. type = ToneMapJS::ToneMappingType ::ACES; break; } return type; } SCENE_NS::ITonemap::TonemapType ConvertTo(uint32_t typeI) { return ConvertTo(static_cast(typeI)); } void ToneMapJS::Init(napi_env env, napi_value exports) { using namespace NapiApi; BASE_NS::vector node_props; // clang-format off node_props.emplace_back(GetSetProperty("type")); node_props.emplace_back(GetSetProperty("exposure")); node_props.push_back(MakeTROMethod, ToneMapJS, &ToneMapJS::Dispose>("destroy")); // clang-format on napi_value func; auto status = napi_define_class(env, "ToneMappingSettings", NAPI_AUTO_LENGTH, BaseObject::ctor(), nullptr, node_props.size(), node_props.data(), &func); NapiApi::MyInstanceState* mis; napi_get_instance_data(env, (void**)&mis); mis->StoreCtor("ToneMappingSettings", func); NapiApi::Object exp(env, exports); napi_value eType; napi_value v; napi_create_object(env, &eType); #define DECL_ENUM(enu, x) \ napi_create_uint32(env, ToneMappingType::x, &v); \ napi_set_named_property(env, enu, #x, v); DECL_ENUM(eType, ACES); DECL_ENUM(eType, ACES_2020); DECL_ENUM(eType, FILMIC); #undef DECL_ENUM exp.Set("ToneMappingType", eType); } napi_value ToneMapJS::Dispose(NapiApi::FunctionContext<>& ctx) { LOG_F("ToneMapJS::Dispose"); DisposeNative(); return {}; } void ToneMapJS::DisposeNative() { if (!disposed_) { disposed_ = true; LOG_F("ToneMapJS::DisposeNative"); if (auto tmp = interface_pointer_cast(GetNativeObject())) { // reset the native object refs SetNativeObject(nullptr, false); SetNativeObject(nullptr, true); ExecSyncTask([scn = BASE_NS::move(tmp)]() { return META_NS::IAny::Ptr {}; }); } } } void* ToneMapJS::GetInstanceImpl(uint32_t id) { if (id == ToneMapJS::ID) { return this; } return nullptr; } void ToneMapJS::Finalize(napi_env env) { // hmm.. do i need to do something BEFORE the object gets deleted.. DisposeNative(); BaseObject::Finalize(env); } ToneMapJS::ToneMapJS(napi_env e, napi_callback_info i) : BaseObject(e, i) { LOG_F("ToneMapJS ++"); NapiApi::FunctionContext fromJs(e, i); if (!fromJs) { // no arguments. so internal create. // expecting caller to finish return; } // postprocess that we bind to.. NapiApi::Object postProcJS = fromJs.Arg<0>(); auto postproc = GetNativeMeta(postProcJS); NapiApi::Object toneMapArgs = fromJs.Arg<1>(); // now, based on parameters, initialize the object // so it is a tonemap float exposure = toneMapArgs.Get("exposure").valueOrDefault(0.7); SCENE_NS::ITonemap::TonemapType type = ConvertTo(toneMapArgs.Get("type").valueOrDefault(ToneMappingType::ACES)); auto tonemap = GetNativeObjectParam(toneMapArgs); ExecSyncTask([&tonemap, exposure, type, postproc]() -> META_NS::IAny::Ptr { if (!tonemap) { tonemap = META_NS::GetObjectRegistry().Create(SCENE_NS::ClassId::Tonemap); } tonemap->Type()->SetValue(type); tonemap->Exposure()->SetValue(exposure); tonemap->Enabled()->SetValue(true); postproc->Tonemap()->SetValue(tonemap); return {}; }); auto obj = interface_pointer_cast(tonemap); // process constructor args.. NapiApi::Object meJs(e, fromJs.This()); // weak ref, due to the ToneMap class being owned by the postprocess. SetNativeObject(obj, false); StoreJsObj(obj, meJs); } ToneMapJS::~ToneMapJS() { LOG_F("ToneMapJS --"); DisposeNative(); if (!GetNativeObject()) { return; } } napi_value ToneMapJS::GetType(NapiApi::FunctionContext<>& ctx) { SCENE_NS::ITonemap::TonemapType type = SCENE_NS::ITonemap::TonemapType::ACES; // default if (auto toneMap = interface_cast(GetNativeObject())) { ExecSyncTask([toneMap, &type]() { type = toneMap->Type()->GetValue(); return META_NS::IAny::Ptr {}; }); } auto typeI = ConvertFrom(type); napi_value value; napi_status status = napi_create_uint32(ctx, static_cast(typeI), &value); return value; } void ToneMapJS::SetType(NapiApi::FunctionContext& ctx) { auto type = ConvertTo(ctx.Arg<0>()); if (auto toneMap = interface_cast(GetNativeObject())) { ExecSyncTask([toneMap, type]() { toneMap->Type()->SetValue(type); return META_NS::IAny::Ptr {}; }); } } napi_value ToneMapJS::GetExposure(NapiApi::FunctionContext<>& ctx) { float exp = 0.0; if (auto toneMap = interface_cast(GetNativeObject())) { ExecSyncTask([toneMap, &exp]() { exp = toneMap->Exposure()->GetValue(); return META_NS::IAny::Ptr {}; }); } napi_value value; napi_status status = napi_create_double(ctx, exp, &value); return value; } void ToneMapJS::SetExposure(NapiApi::FunctionContext& ctx) { float exp = ctx.Arg<0>(); if (auto toneMap = interface_cast(GetNativeObject())) { ExecSyncTask([toneMap, exp]() { toneMap->Exposure()->SetValue(exp); return META_NS::IAny::Ptr {}; }); } }