1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "MeshJS.h"
16
17 #include <meta/api/make_callback.h>
18 #include <meta/interface/intf_task_queue.h>
19 #include <meta/interface/intf_task_queue_registry.h>
20 #include <scene/interface/intf_camera.h>
21 #include <scene/interface/intf_mesh.h>
22 #include <scene/interface/intf_scene.h>
23
24 #include "SceneJS.h"
GetInstanceImpl(uint32_t id)25 void* MeshJS::GetInstanceImpl(uint32_t id)
26 {
27 if (id == MeshJS::ID)
28 return this;
29 return SceneResourceImpl::GetInstanceImpl(id);
30 }
DisposeNative(void * scn)31 void MeshJS::DisposeNative(void* scn)
32 {
33 if (disposed_) {
34 return;
35 }
36 disposed_ = true;
37 LOG_V("MeshJS::DisposeNative");
38 if (auto* sceneJS = static_cast<SceneJS*>(scn)) {
39 sceneJS->ReleaseStrongDispose(reinterpret_cast<uintptr_t>(&scene_));
40 }
41
42 subs_.clear();
43 scene_.Reset();
44 }
Init(napi_env env,napi_value exports)45 void MeshJS::Init(napi_env env, napi_value exports)
46 {
47 BASE_NS::vector<napi_property_descriptor> node_props;
48 SceneResourceImpl::GetPropertyDescs(node_props);
49
50 using namespace NapiApi;
51 node_props.push_back(GetProperty<Object, MeshJS, &MeshJS::GetSubmesh>("subMeshes"));
52 node_props.push_back(GetProperty<Object, MeshJS, &MeshJS::GetAABB>("aabb"));
53 node_props.push_back(
54 GetSetProperty<Object, MeshJS, &MeshJS::GetMaterialOverride, &MeshJS::SetMaterialOverride>("materialOverride"));
55
56 napi_value func;
57 auto status = napi_define_class(env, "Mesh", NAPI_AUTO_LENGTH, BaseObject::ctor<MeshJS>(), nullptr,
58 node_props.size(), node_props.data(), &func);
59
60 NapiApi::MyInstanceState* mis;
61 NapiApi::MyInstanceState::GetInstance(env, (void**)&mis);
62 if (mis) {
63 mis->StoreCtor("Mesh", func);
64 }
65 }
66
MeshJS(napi_env e,napi_callback_info i)67 MeshJS::MeshJS(napi_env e, napi_callback_info i) : BaseObject(e, i), SceneResourceImpl(SceneResourceImpl::MESH)
68 {
69 NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
70 if (!fromJs) {
71 // okay internal create. we will receive the object after.
72 return;
73 }
74 scene_ = fromJs.Arg<0>().valueOrDefault();
75 if (!scene_.GetObject().GetNative<SCENE_NS::IScene>()) {
76 LOG_F("INVALID SCENE!");
77 }
78 {
79 // add the dispose hook to scene. (so that the geometry node is disposed when scene is disposed)
80 NapiApi::Object meJs(fromJs.This());
81 NapiApi::Object scene = fromJs.Arg<0>();
82 if (const auto sceneJS = scene.GetJsWrapper<SceneJS>()) {
83 sceneJS->StrongDisposeHook(reinterpret_cast<uintptr_t>(&scene_), meJs);
84 }
85 }
86 }
~MeshJS()87 MeshJS::~MeshJS()
88 {
89 LOG_V("MeshJS -- ");
90 }
Finalize(napi_env env)91 void MeshJS::Finalize(napi_env env)
92 {
93 DisposeNative(scene_.GetObject().GetJsWrapper<SceneJS>());
94 BaseObject::Finalize(env);
95 }
96
GetSubmesh(NapiApi::FunctionContext<> & ctx)97 napi_value MeshJS::GetSubmesh(NapiApi::FunctionContext<>& ctx)
98 {
99 if (!validateSceneRef()) {
100 return ctx.GetUndefined();
101 }
102 auto node = ctx.This().GetNative<SCENE_NS::IMesh>();
103 if (!node) {
104 // return undefined.. as no actual node.
105 return ctx.GetUndefined();
106 }
107
108 subs_ = node->SubMeshes()->GetValue();
109
110 NapiApi::Env env(ctx.Env());
111 napi_value tmp;
112 auto status = napi_create_array_with_length(env, subs_.size(), &tmp);
113 uint32_t i = 0;
114 for (const auto& subMesh : subs_) {
115 napi_value args[] = { scene_.GetValue(), ctx.This().ToNapiValue(), env.GetNumber(i) };
116 auto val = CreateFromNativeInstance(ctx.Env(), subMesh, PtrType::STRONG, args);
117 status = napi_set_element(ctx.Env(), tmp, i++, val.ToNapiValue());
118 }
119
120 return tmp;
121 }
122
GetAABB(NapiApi::FunctionContext<> & ctx)123 napi_value MeshJS::GetAABB(NapiApi::FunctionContext<>& ctx)
124 {
125 if (!validateSceneRef()) {
126 return ctx.GetUndefined();
127 }
128 auto node = ctx.This().GetNative<SCENE_NS::IMesh>();
129 if (!node) {
130 // return undefined.. as no actual node.
131 return ctx.GetUndefined();
132 }
133 BASE_NS::Math::Vec3 aabmin;
134 BASE_NS::Math::Vec3 aabmax;
135 aabmin = node->AABBMin()->GetValue();
136 aabmax = node->AABBMax()->GetValue();
137 NapiApi::Env env(ctx.Env());
138 NapiApi::Object res(env);
139
140 NapiApi::Object min(env);
141 min.Set("x", NapiApi::Value<float> { env, aabmin.x });
142 min.Set("y", NapiApi::Value<float> { env, aabmin.y });
143 min.Set("z", NapiApi::Value<float> { env, aabmin.z });
144 res.Set("aabbMin", min);
145
146 NapiApi::Object max(env);
147 max.Set("x", NapiApi::Value<float> { env, aabmax.x });
148 max.Set("y", NapiApi::Value<float> { env, aabmax.y });
149 max.Set("z", NapiApi::Value<float> { env, aabmax.z });
150 res.Set("aabbMax", max);
151 return res.ToNapiValue();
152 }
153
GetMaterialOverride(NapiApi::FunctionContext<> & ctx)154 napi_value MeshJS::GetMaterialOverride(NapiApi::FunctionContext<>& ctx)
155 {
156 if (!validateSceneRef()) {
157 return ctx.GetUndefined();
158 }
159 return ctx.GetUndefined();
160 }
161
SetMaterialOverride(NapiApi::FunctionContext<NapiApi::Object> & ctx)162 void MeshJS::SetMaterialOverride(NapiApi::FunctionContext<NapiApi::Object>& ctx)
163 {
164 if (!validateSceneRef()) {
165 return;
166 }
167 auto sm = ctx.This().GetNative<SCENE_NS::IMesh>();
168 if (!sm) {
169 return;
170 }
171 NapiApi::Object obj = ctx.Arg<0>();
172 auto new_material = obj.GetNative<SCENE_NS::IMaterial>();
173 SCENE_NS::SetMaterialForAllSubMeshes(sm, new_material);
174 }
175