/* * 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 "SubMeshJS.h" #include #include #include #include #include #include #include "MeshJS.h" #include "SceneJS.h" void* SubMeshJS::GetInstanceImpl(uint32_t id) { if (id == SubMeshJS::ID) return this; // no id will match return nullptr; } void SubMeshJS::DisposeNative(void* scn) { if (disposed_) { return; } disposed_ = true; LOG_V("SubMeshJS::DisposeNative"); if (auto* sceneJS = static_cast(scn)) { sceneJS->ReleaseStrongDispose(reinterpret_cast(&scene_)); } aabbMin_.reset(); aabbMax_.reset(); parentMesh_.Reset(); scene_.Reset(); } void SubMeshJS::Finalize(napi_env env) { DisposeNative(scene_.GetObject().GetJsWrapper()); BaseObject::Finalize(env); } napi_value SubMeshJS::Dispose(NapiApi::FunctionContext<>& ctx) { // Dispose of the native object. (makes the js object invalid) if (TrueRootObject* instance = ctx.This().GetRoot()) { // see if we have "scenejs" as ext (prefer one given as argument) napi_status stat; SceneJS* ptr { nullptr }; NapiApi::FunctionContext args(ctx); if (args) { if (NapiApi::Object obj = args.Arg<0>()) { if (napi_value ext = obj.Get("SceneJS")) { stat = napi_get_value_external(ctx.GetEnv(), ext, (void**)&ptr); } } } if (!ptr) { ptr = scene_.GetObject().GetJsWrapper(); } UnsetNativeObject(); instance->DisposeNative(ptr); } return ctx.GetUndefined(); } void SubMeshJS::Init(napi_env env, napi_value exports) { BASE_NS::vector node_props; using namespace NapiApi; node_props.push_back(GetSetProperty("name")); node_props.push_back(GetProperty("aabb")); node_props.push_back( GetSetProperty("material")); node_props.push_back(MakeTROMethod, SubMeshJS, &SubMeshJS::Dispose>("destroy")); napi_value func; auto status = napi_define_class(env, "SubMesh", 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("SubMesh", func); } } SubMeshJS::SubMeshJS(napi_env e, napi_callback_info i) : BaseObject(e, i) { LOG_V("SubMeshJS ++ "); NapiApi::FunctionContext fromJs(e, i); if (!fromJs) { // okay internal create. we will receive the object after. return; } scene_ = fromJs.Arg<0>().valueOrDefault(); parentMesh_ = fromJs.Arg<1>().valueOrDefault(); indexInParent_ = fromJs.Arg<2>().valueOrDefault(); // 2: arg num if (!scene_.GetObject().GetNative()) { LOG_F("INVALID SCENE!"); } { // add the dispose hook to scene. (so that the geometry node is disposed when scene is disposed) NapiApi::Object meJs(fromJs.This()); NapiApi::Object scene = fromJs.Arg<0>(); if (const auto sceneJS = scene.GetJsWrapper()) { sceneJS->StrongDisposeHook(reinterpret_cast(&scene_), meJs); } } } SubMeshJS::~SubMeshJS() { LOG_V("SubMeshJS --"); } napi_value SubMeshJS::GetAABB(NapiApi::FunctionContext<>& ctx) { auto node = ctx.This().GetNative(); if (!node) { // return undefined.. as no actual node. return ctx.GetUndefined(); } BASE_NS::Math::Vec3 aabmin; BASE_NS::Math::Vec3 aabmax; aabmin = node->AABBMin()->GetValue(); aabmax = node->AABBMax()->GetValue(); NapiApi::Env env(ctx.Env()); NapiApi::Object res(env); NapiApi::Object min(env); min.Set("x", NapiApi::Value { env, aabmin.x }); min.Set("y", NapiApi::Value { env, aabmin.y }); min.Set("z", NapiApi::Value { env, aabmin.z }); res.Set("aabbMin", min); NapiApi::Object max(env); max.Set("x", NapiApi::Value { env, aabmax.x }); max.Set("y", NapiApi::Value { env, aabmax.y }); max.Set("z", NapiApi::Value { env, aabmax.z }); res.Set("aabbMax", max); return res.ToNapiValue(); } napi_value SubMeshJS::GetName(NapiApi::FunctionContext<>& ctx) { BASE_NS::string name; if (auto node = ctx.This().GetNative()) { name = node->Name()->GetValue(); } return ctx.GetString(name); } void SubMeshJS::SetName(NapiApi::FunctionContext& ctx) { if (auto node = ctx.This().GetNative()) { BASE_NS::string name = ctx.Arg<0>(); node->Name()->SetValue(name); } } napi_value SubMeshJS::GetMaterial(NapiApi::FunctionContext<>& ctx) { auto sm = ctx.This().GetNative(); if (!sm) { return ctx.GetUndefined(); } META_NS::IObject::Ptr obj; auto material = sm->Material()->GetValue(); NapiApi::Env env(ctx.Env()); NapiApi::Object argJS(env); napi_value args[] = { scene_.GetValue(), argJS.ToNapiValue() }; if (!scene_.GetObject().GetNative()) { LOG_F("INVALID SCENE!"); } return CreateFromNativeInstance(env, material, PtrType::STRONG, args).ToNapiValue(); } void SubMeshJS::SetMaterial(NapiApi::FunctionContext& ctx) { auto sm = ctx.This().GetNative(); if (!sm) { return; } NapiApi::Object obj = ctx.Arg<0>(); auto new_material = obj.GetNative(); if (new_material) { auto cur = sm->Material()->GetValue(); if (cur != new_material) { sm->Material()->SetValue(new_material); } } }