• 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     aabbMin_.reset();
45     aabbMax_.reset();
46     parentMesh_.Reset();
47     scene_.Reset();
48 }
49 
Finalize(napi_env env)50 void SubMeshJS::Finalize(napi_env env)
51 {
52     DisposeNative(GetJsWrapper<SceneJS>(scene_.GetObject()));
53     BaseObject::Finalize(env);
54 }
55 
Dispose(NapiApi::FunctionContext<> & ctx)56 napi_value SubMeshJS::Dispose(NapiApi::FunctionContext<>& ctx)
57 {
58     // Dispose of the native object. (makes the js object invalid)
59     if (TrueRootObject* instance = GetThisRootObject(ctx)) {
60         // see if we have "scenejs" as ext (prefer one given as argument)
61         napi_status stat;
62         SceneJS* ptr { nullptr };
63         NapiApi::FunctionContext<NapiApi::Object> args(ctx);
64         if (args) {
65             if (NapiApi::Object obj = args.Arg<0>()) {
66                 if (napi_value ext = obj.Get("SceneJS")) {
67                     stat = napi_get_value_external(ctx.GetEnv(), ext, (void**)&ptr);
68                 }
69             }
70         }
71         if (!ptr) {
72             ptr = GetJsWrapper<SceneJS>(scene_.GetObject());
73         }
74         SetNativeObject(nullptr, true);
75         instance->DisposeNative(ptr);
76     }
77     return ctx.GetUndefined();
78 }
Init(napi_env env,napi_value exports)79 void SubMeshJS::Init(napi_env env, napi_value exports)
80 {
81     BASE_NS::vector<napi_property_descriptor> node_props;
82 
83     using namespace NapiApi;
84     node_props.push_back(GetSetProperty<BASE_NS::string, SubMeshJS, &SubMeshJS::GetName, &SubMeshJS::SetName>("name"));
85     node_props.push_back(GetProperty<Object, SubMeshJS, &SubMeshJS::GetAABB>("aabb"));
86     node_props.push_back(
87         GetSetProperty<Object, SubMeshJS, &SubMeshJS::GetMaterial, &SubMeshJS::SetMaterial>("material"));
88 
89     node_props.push_back(MakeTROMethod<FunctionContext<>, SubMeshJS, &SubMeshJS::Dispose>("destroy"));
90 
91     napi_value func;
92     auto status = napi_define_class(env, "SubMesh", NAPI_AUTO_LENGTH, BaseObject::ctor<SubMeshJS>(), nullptr,
93         node_props.size(), node_props.data(), &func);
94 
95     NapiApi::MyInstanceState* mis;
96     GetInstanceData(env, (void**)&mis);
97     mis->StoreCtor("SubMesh", func);
98 }
99 
SubMeshJS(napi_env e,napi_callback_info i)100 SubMeshJS::SubMeshJS(napi_env e, napi_callback_info i) : BaseObject<SubMeshJS>(e, i)
101 {
102     LOG_V("SubMeshJS ++ ");
103     NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object, uint32_t> fromJs(e, i);
104     if (!fromJs) {
105         // okay internal create. we will receive the object after.
106         return;
107     }
108     scene_ = fromJs.Arg<0>().valueOrDefault();
109     parentMesh_ = fromJs.Arg<1>().valueOrDefault();
110     indexInParent_ = fromJs.Arg<2>().valueOrDefault(); // 2: idx
111     if (!GetNativeMeta<SCENE_NS::IScene>(scene_.GetObject())) {
112         LOG_F("INVALID SCENE!");
113     }
114     {
115         // add the dispose hook to scene. (so that the geometry node is disposed when scene is disposed)
116         NapiApi::Object meJs(fromJs.This());
117         NapiApi::Object scene = fromJs.Arg<0>();
118         if (auto sceneJS = GetJsWrapper<SceneJS>(scene)) {
119             sceneJS->StrongDisposeHook(reinterpret_cast<uintptr_t>(&scene_), meJs);
120         }
121     }
122 }
~SubMeshJS()123 SubMeshJS::~SubMeshJS()
124 {
125     LOG_V("SubMeshJS -- %p", this);
126 }
127 
GetAABB(NapiApi::FunctionContext<> & ctx)128 napi_value SubMeshJS::GetAABB(NapiApi::FunctionContext<>& ctx)
129 {
130     auto node = interface_pointer_cast<SCENE_NS::ISubMesh>(GetThisNativeObject(ctx));
131     if (!node) {
132         // return undefined.. as no actual node.
133         return ctx.GetUndefined();
134     }
135     BASE_NS::Math::Vec3 aabmin;
136     BASE_NS::Math::Vec3 aabmax;
137     aabmin = node->AABBMin()->GetValue();
138     aabmax = node->AABBMax()->GetValue();
139     NapiApi::Env env(ctx.Env());
140     NapiApi::Object res(env);
141 
142     NapiApi::Object min(env);
143     min.Set("x", NapiApi::Value<float> { env, aabmin.x });
144     min.Set("y", NapiApi::Value<float> { env, aabmin.y });
145     min.Set("z", NapiApi::Value<float> { env, aabmin.z });
146     res.Set("aabbMin", min);
147 
148     NapiApi::Object max(env);
149     max.Set("x", NapiApi::Value<float> { env, aabmax.x });
150     max.Set("y", NapiApi::Value<float> { env, aabmax.y });
151     max.Set("z", NapiApi::Value<float> { env, aabmax.z });
152     res.Set("aabbMax", max);
153     return res.ToNapiValue();
154 }
155 
GetName(NapiApi::FunctionContext<> & ctx)156 napi_value SubMeshJS::GetName(NapiApi::FunctionContext<>& ctx)
157 {
158     BASE_NS::string name;
159     if (auto node = interface_pointer_cast<META_NS::INamed>(GetThisNativeObject(ctx))) {
160         name = node->Name()->GetValue();
161     }
162     return ctx.GetString(name);
163 }
SetName(NapiApi::FunctionContext<BASE_NS::string> & ctx)164 void SubMeshJS::SetName(NapiApi::FunctionContext<BASE_NS::string>& ctx)
165 {
166     if (auto node = interface_pointer_cast<META_NS::INamed>(GetThisNativeObject(ctx))) {
167         BASE_NS::string name = ctx.Arg<0>();
168         node->Name()->SetValue(name);
169     }
170 }
171 
GetMaterial(NapiApi::FunctionContext<> & ctx)172 napi_value SubMeshJS::GetMaterial(NapiApi::FunctionContext<>& ctx)
173 {
174     auto sm = interface_pointer_cast<SCENE_NS::ISubMesh>(GetThisNativeObject(ctx));
175     if (!sm) {
176         // return undefined..
177         return ctx.GetUndefined();
178     }
179     META_NS::IObject::Ptr obj;
180     auto material = sm->Material()->GetValue();
181     obj = interface_pointer_cast<META_NS::IObject>(material);
182     if (auto cached = FetchJsObj(obj)) {
183         // always return the same js object.
184         return cached.ToNapiValue();
185     }
186 
187     // No jswrapper for this material , so create it.
188     NapiApi::Env env(ctx.Env());
189     NapiApi::Object argJS(env);
190     napi_value args[] = { scene_.GetValue(), argJS.ToNapiValue() };
191     if (!GetNativeMeta<SCENE_NS::IScene>(scene_.GetObject())) {
192         LOG_F("INVALID SCENE!");
193     }
194     auto argc = BASE_NS::countof(args);
195     auto argv = args;
196     return CreateFromNativeInstance(env, obj, true, argc, argv).ToNapiValue();
197 }
198 
SetMaterial(NapiApi::FunctionContext<NapiApi::Object> & ctx)199 void SubMeshJS::SetMaterial(NapiApi::FunctionContext<NapiApi::Object>& ctx)
200 {
201     auto sm = interface_pointer_cast<SCENE_NS::ISubMesh>(GetThisNativeObject(ctx));
202     if (!sm) {
203         return;
204     }
205     NapiApi::Object obj = ctx.Arg<0>();
206     auto new_material = GetNativeMeta<SCENE_NS::IMaterial>(obj);
207     if (new_material) {
208         auto cur = sm->Material()->GetValue();
209         if (cur != new_material) {
210             sm->Material()->SetValue(new_material);
211         }
212     }
213     UpdateParentMesh();
214 }
215 
UpdateParentMesh()216 void SubMeshJS::UpdateParentMesh()
217 {
218     auto success = false;
219     if (auto self = interface_pointer_cast<SCENE_NS::ISubMesh>(GetNativeObject())) {
220         if (auto mesh = GetJsWrapper<MeshJS>(parentMesh_.GetObject())) {
221             success = mesh->UpdateSubmesh(indexInParent_, self);
222         }
223     }
224     if (!success) {
225         LOG_E("Unable to update submesh change to scene");
226     }
227 }
228