• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "SubMeshJS.h"
17 
18 #include <meta/api/make_callback.h>
19 #include <meta/interface/intf_task_queue.h>
20 #include <meta/interface/intf_task_queue_registry.h>
21 #include <scene/interface/intf_camera.h>
22 #include <scene/interface/intf_scene.h>
23 #include <scene/interface/intf_mesh.h>
24 
25 #include "MeshJS.h"
26 #include "SceneJS.h"
GetInstanceImpl(uint32_t id)27 void* SubMeshJS::GetInstanceImpl(uint32_t id)
28 {
29     if (id == SubMeshJS::ID)
30         return this;
31     // no id will match
32     return nullptr;
33 }
DisposeNative(void * scn)34 void SubMeshJS::DisposeNative(void* scn)
35 {
36     if (disposed_) {
37         return;
38     }
39     disposed_ = true;
40     LOG_V("SubMeshJS::DisposeNative");
41     if (auto* sceneJS = static_cast<SceneJS*>(scn)) {
42         sceneJS->ReleaseStrongDispose(reinterpret_cast<uintptr_t>(&scene_));
43     }
44 
45     aabbMin_.reset();
46     aabbMax_.reset();
47     parentMesh_.Reset();
48     scene_.Reset();
49 }
50 
Finalize(napi_env env)51 void SubMeshJS::Finalize(napi_env env)
52 {
53     DisposeNative(scene_.GetObject().GetJsWrapper<SceneJS>());
54     BaseObject::Finalize(env);
55 }
56 
Dispose(NapiApi::FunctionContext<> & ctx)57 napi_value SubMeshJS::Dispose(NapiApi::FunctionContext<>& ctx)
58 {
59     // Dispose of the native object. (makes the js object invalid)
60     if (TrueRootObject* instance = ctx.This().GetRoot()) {
61         // see if we have "scenejs" as ext (prefer one given as argument)
62         napi_status stat;
63         SceneJS* ptr { nullptr };
64         NapiApi::FunctionContext<NapiApi::Object> args(ctx);
65         if (args) {
66             if (NapiApi::Object obj = args.Arg<0>()) {
67                 if (napi_value ext = obj.Get("SceneJS")) {
68                     stat = napi_get_value_external(ctx.GetEnv(), ext, (void**)&ptr);
69                 }
70             }
71         }
72         if (!ptr) {
73             ptr = scene_.GetObject().GetJsWrapper<SceneJS>();
74         }
75         UnsetNativeObject();
76         instance->DisposeNative(ptr);
77     }
78     return ctx.GetUndefined();
79 }
Init(napi_env env,napi_value exports)80 void SubMeshJS::Init(napi_env env, napi_value exports)
81 {
82     BASE_NS::vector<napi_property_descriptor> node_props;
83 
84     using namespace NapiApi;
85     node_props.push_back(GetSetProperty<BASE_NS::string, SubMeshJS, &SubMeshJS::GetName, &SubMeshJS::SetName>("name"));
86     node_props.push_back(GetProperty<Object, SubMeshJS, &SubMeshJS::GetAABB>("aabb"));
87     node_props.push_back(
88         GetSetProperty<Object, SubMeshJS, &SubMeshJS::GetMaterial, &SubMeshJS::SetMaterial>("material"));
89 
90     node_props.push_back(MakeTROMethod<FunctionContext<>, SubMeshJS, &SubMeshJS::Dispose>("destroy"));
91 
92     napi_value func;
93     auto status = napi_define_class(env, "SubMesh", NAPI_AUTO_LENGTH, BaseObject::ctor<SubMeshJS>(), nullptr,
94         node_props.size(), node_props.data(), &func);
95 
96     NapiApi::MyInstanceState* mis;
97     NapiApi::MyInstanceState::GetInstance(env, (void**)&mis);
98     if (mis) {
99         mis->StoreCtor("SubMesh", func);
100     }
101 }
102 
SubMeshJS(napi_env e,napi_callback_info i)103 SubMeshJS::SubMeshJS(napi_env e, napi_callback_info i) : BaseObject(e, i)
104 {
105     LOG_V("SubMeshJS ++ ");
106     NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object, uint32_t> fromJs(e, i);
107     if (!fromJs) {
108         // okay internal create. we will receive the object after.
109         return;
110     }
111     scene_ = fromJs.Arg<0>().valueOrDefault();
112     parentMesh_ = fromJs.Arg<1>().valueOrDefault();
113     indexInParent_ = fromJs.Arg<2>().valueOrDefault(); // 2: arg num
114     if (!scene_.GetObject().GetNative<SCENE_NS::IScene>()) {
115         LOG_F("INVALID SCENE!");
116     }
117     {
118         // add the dispose hook to scene. (so that the geometry node is disposed when scene is disposed)
119         NapiApi::Object meJs(fromJs.This());
120         NapiApi::Object scene = fromJs.Arg<0>();
121         if (const auto sceneJS = scene.GetJsWrapper<SceneJS>()) {
122             sceneJS->StrongDisposeHook(reinterpret_cast<uintptr_t>(&scene_), meJs);
123         }
124     }
125 }
~SubMeshJS()126 SubMeshJS::~SubMeshJS()
127 {
128     LOG_V("SubMeshJS --");
129 }
130 
GetAABB(NapiApi::FunctionContext<> & ctx)131 napi_value SubMeshJS::GetAABB(NapiApi::FunctionContext<>& ctx)
132 {
133     auto node = ctx.This().GetNative<SCENE_NS::ISubMesh>();
134     if (!node) {
135         // return undefined.. as no actual node.
136         return ctx.GetUndefined();
137     }
138     BASE_NS::Math::Vec3 aabmin;
139     BASE_NS::Math::Vec3 aabmax;
140     aabmin = node->AABBMin()->GetValue();
141     aabmax = node->AABBMax()->GetValue();
142     NapiApi::Env env(ctx.Env());
143     NapiApi::Object res(env);
144 
145     NapiApi::Object min(env);
146     min.Set("x", NapiApi::Value<float> { env, aabmin.x });
147     min.Set("y", NapiApi::Value<float> { env, aabmin.y });
148     min.Set("z", NapiApi::Value<float> { env, aabmin.z });
149     res.Set("aabbMin", min);
150 
151     NapiApi::Object max(env);
152     max.Set("x", NapiApi::Value<float> { env, aabmax.x });
153     max.Set("y", NapiApi::Value<float> { env, aabmax.y });
154     max.Set("z", NapiApi::Value<float> { env, aabmax.z });
155     res.Set("aabbMax", max);
156     return res.ToNapiValue();
157 }
158 
GetName(NapiApi::FunctionContext<> & ctx)159 napi_value SubMeshJS::GetName(NapiApi::FunctionContext<>& ctx)
160 {
161     BASE_NS::string name;
162     if (auto node = ctx.This().GetNative<META_NS::INamed>()) {
163         name = node->Name()->GetValue();
164     }
165     return ctx.GetString(name);
166 }
SetName(NapiApi::FunctionContext<BASE_NS::string> & ctx)167 void SubMeshJS::SetName(NapiApi::FunctionContext<BASE_NS::string>& ctx)
168 {
169     if (auto node = ctx.This().GetNative<META_NS::INamed>()) {
170         BASE_NS::string name = ctx.Arg<0>();
171         node->Name()->SetValue(name);
172     }
173 }
174 
GetMaterial(NapiApi::FunctionContext<> & ctx)175 napi_value SubMeshJS::GetMaterial(NapiApi::FunctionContext<>& ctx)
176 {
177     auto sm = ctx.This().GetNative<SCENE_NS::ISubMesh>();
178     if (!sm) {
179         return ctx.GetUndefined();
180     }
181     META_NS::IObject::Ptr obj;
182     auto material = sm->Material()->GetValue();
183 
184     NapiApi::Env env(ctx.Env());
185     NapiApi::Object argJS(env);
186     napi_value args[] = { scene_.GetValue(), argJS.ToNapiValue() };
187     if (!scene_.GetObject().GetNative<SCENE_NS::IScene>()) {
188         LOG_F("INVALID SCENE!");
189     }
190     return CreateFromNativeInstance(env, material, PtrType::STRONG, args).ToNapiValue();
191 }
192 
SetMaterial(NapiApi::FunctionContext<NapiApi::Object> & ctx)193 void SubMeshJS::SetMaterial(NapiApi::FunctionContext<NapiApi::Object>& ctx)
194 {
195     auto sm = ctx.This().GetNative<SCENE_NS::ISubMesh>();
196     if (!sm) {
197         return;
198     }
199     NapiApi::Object obj = ctx.Arg<0>();
200     auto new_material = obj.GetNative<SCENE_NS::IMaterial>();
201     if (new_material) {
202         auto cur = sm->Material()->GetValue();
203         if (cur != new_material) {
204             sm->Material()->SetValue(new_material);
205         }
206     }
207 }
208