/*
* 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
#include
#include
#include
using IntfPtr = BASE_NS::shared_ptr;
using IntfWeakPtr = BASE_NS::weak_ptr;
using namespace SCENE_NS;
SCENE_NS::TonemapType ToNative(ToneMapJS::ToneMappingType typeI)
{
SCENE_NS::TonemapType type;
switch (typeI) {
case ToneMapJS::ToneMappingType::ACES:
type = SCENE_NS::TonemapType::ACES;
break;
case ToneMapJS::ToneMappingType::ACES_2020:
type = SCENE_NS::TonemapType::ACES_2020;
break;
case ToneMapJS::ToneMappingType::FILMIC:
type = SCENE_NS::TonemapType::FILMIC;
break;
default:
// default from lowlev..
type = SCENE_NS::TonemapType::ACES;
break;
}
return type;
}
ToneMapJS::ToneMappingType ToJs(SCENE_NS::TonemapType typeI)
{
ToneMapJS::ToneMappingType type;
switch (typeI) {
case SCENE_NS::TonemapType::ACES:
type = ToneMapJS::ToneMappingType::ACES;
break;
case SCENE_NS::TonemapType::ACES_2020:
type = ToneMapJS::ToneMappingType::ACES_2020;
break;
case SCENE_NS::TonemapType::FILMIC:
type = ToneMapJS::ToneMappingType ::FILMIC;
break;
default:
// default from lowlev..
type = ToneMapJS::ToneMappingType ::ACES;
break;
}
return type;
}
SCENE_NS::TonemapType ToneMapJS::ToNativeType(uint32_t typeI)
{
return ToNative(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;
NapiApi::MyInstanceState::GetInstance(env, (void**)&mis);
if (mis) {
mis->StoreCtor("ToneMappingSettings", func);
}
NapiApi::Object exp(env, exports);
napi_value eType, 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_V("ToneMapJS::Dispose");
DisposeNative(nullptr);
return {};
}
void ToneMapJS::DisposeNative(void*)
{
if (!disposed_) {
disposed_ = true;
LOG_V("ToneMapJS::DisposeNative");
UnsetNativeObject();
}
}
void ToneMapJS::UnbindFromNative()
{
// We don't use a property proxy, so update members manually.
if (auto toneMap = GetNativeObject()) {
type_ = ToJs(toneMap->Type()->GetValue());
exposure_ = toneMap->Exposure()->GetValue();
}
UnsetNativeObject();
}
void ToneMapJS::BindToNative(SCENE_NS::ITonemap::Ptr native)
{
SetNativeObject(interface_pointer_cast(native), PtrType::WEAK);
if (auto toneMap = GetNativeObject()) {
toneMap->Type()->SetValue(ToNative(type_));
toneMap->Exposure()->SetValue(exposure_);
}
}
void* ToneMapJS::GetInstanceImpl(uint32_t id)
{
if (id == ToneMapJS::ID)
return this;
return nullptr;
}
void ToneMapJS::Finalize(napi_env env)
{
DisposeNative(nullptr);
BaseObject::Finalize(env);
}
ToneMapJS::ToneMapJS(napi_env e, napi_callback_info i)
: BaseObject(e, i), type_(DEFAULT_TYPE), exposure_(DEFAULT_EXPOSURE)
{
LOG_V("ToneMapJS ++");
auto tonemap = GetNativeObject();
if (!tonemap) {
LOG_E("Cannot finish creating a tonemap: Native tonemap object missing");
assert(false);
return;
}
// We accept 0 and 1 arg calls. If we get 0, do nothing so original tonemap stays unchanged.
NapiApi::FunctionContext ctx(e, i);
if (!ctx) {
if (ctx.ArgCount() != 0) {
LOG_E("Cannot finish creating a tonemap: Invalid args given");
assert(false);
}
return;
}
NapiApi::Object toneMapArgs = ctx.Arg<0>();
exposure_ = toneMapArgs.Get("exposure").valueOrDefault(exposure_);
type_ = static_cast(toneMapArgs.Get("type").valueOrDefault(type_));
tonemap->Type()->SetValue(ToNative(type_));
tonemap->Exposure()->SetValue(exposure_);
tonemap->Enabled()->SetValue(true);
}
ToneMapJS::~ToneMapJS()
{
LOG_V("ToneMapJS --");
DisposeNative(nullptr);
if (!GetNativeObject()) {
return;
}
}
napi_value ToneMapJS::GetType(NapiApi::FunctionContext<>& ctx)
{
if (auto toneMap = interface_cast(GetNativeObject())) {
type_ = ToJs(toneMap->Type()->GetValue());
}
return ctx.GetNumber(static_cast(type_));
}
void ToneMapJS::SetType(NapiApi::FunctionContext& ctx)
{
const auto nativeType = ToNativeType(ctx.Arg<0>());
type_ = ToJs(nativeType);
if (auto toneMap = interface_cast(GetNativeObject())) {
toneMap->Type()->SetValue(nativeType);
}
}
napi_value ToneMapJS::GetExposure(NapiApi::FunctionContext<>& ctx)
{
if (auto toneMap = interface_cast(GetNativeObject())) {
exposure_ = toneMap->Exposure()->GetValue();
}
return ctx.GetNumber(exposure_);
}
void ToneMapJS::SetExposure(NapiApi::FunctionContext& ctx)
{
exposure_ = ctx.Arg<0>();
if (auto toneMap = interface_cast(GetNativeObject())) {
toneMap->Exposure()->SetValue(exposure_);
}
}