• 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 #include "LightJS.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_light.h>
21 #include <scene/interface/intf_scene.h>
22 
23 #include "ParamParsing.h"
24 #include "SceneJS.h"
25 
26 using namespace NapiApi;
BaseLight(LightType lt)27 BaseLight::BaseLight(LightType lt) : NodeImpl(NodeImpl::NodeType::LIGHT), lightType_(lt) {}
RegisterEnums(NapiApi::Object exports)28 void BaseLight::RegisterEnums(NapiApi::Object exports)
29 {
30     napi_value v;
31     NapiApi::Object LightType(exports.GetEnv());
32 
33 #define DECL_ENUM(enu, x)                                              \
34     {                                                                  \
35         napi_create_uint32(enu.GetEnv(), BaseLight::LightType::x, &v); \
36         enu.Set(#x, v);                                                \
37     }
38     DECL_ENUM(LightType, DIRECTIONAL);
39     DECL_ENUM(LightType, POINT);
40     DECL_ENUM(LightType, SPOT);
41 #undef DECL_ENUM
42     exports.Set("LightType", LightType);
43 }
44 
Create(napi_env e,napi_callback_info i)45 void BaseLight::Create(napi_env e, napi_callback_info i)
46 {
47     NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
48     if (!fromJs) {
49         // no arguments. so internal create.
50         // expecting caller to finish initialization
51         return;
52     }
53 
54     // java script call.. with arguments
55     scene_ = fromJs.Arg<0>().valueOrDefault();
56     auto scn = scene_.GetObject().GetNative<SCENE_NS::IScene>();
57     if (scn == nullptr) {
58         // hmm..
59         LOG_F("Invalid scene for LightJS!");
60         return;
61     }
62 
63     auto sceneNodeParameters = NapiApi::Object { fromJs.Arg<1>() };
64     NapiApi::Object meJs(fromJs.This());
65     if (const auto name = ExtractName(sceneNodeParameters); !name.empty()) {
66         meJs.Set("name", name);
67     }
68 
69     {
70         // add the dispose hook to scene. (so that the geometry node is disposed when scene is disposed)
71         NapiApi::Object scene = fromJs.Arg<0>();
72         if (const auto sceneJS = scene.GetJsWrapper<SceneJS>()) {
73             sceneJS->StrongDisposeHook(reinterpret_cast<uintptr_t>(&scene_), meJs);
74         }
75     }
76 }
~BaseLight()77 BaseLight::~BaseLight()
78 {
79     colorProxy_.reset();
80 }
Init(const char * class_name,napi_env env,napi_value exports,BASE_NS::vector<napi_property_descriptor> & np,napi_callback ctor)81 void BaseLight::Init(const char* class_name, napi_env env, napi_value exports,
82     BASE_NS::vector<napi_property_descriptor>& np, napi_callback ctor)
83 {
84     NodeImpl::GetPropertyDescs(np);
85 
86     np.push_back(TROGetProperty<float, BaseLight, &BaseLight::GetlightType>("lightType"));
87     np.push_back(TROGetSetProperty<Object, BaseLight, &BaseLight::GetColor, &BaseLight::SetColor>("color"));
88     np.push_back(TROGetSetProperty<float, BaseLight, &BaseLight::GetIntensity, &BaseLight::SetIntensity>("intensity"));
89     np.push_back(TROGetSetProperty<bool, BaseLight, &BaseLight::GetShadowEnabled, &BaseLight::SetShadowEnabled>(
90         "shadowEnabled"));
91     np.push_back(TROGetSetProperty<bool, BaseLight, &BaseLight::GetEnabled, &BaseLight::SetEnabled>("enabled"));
92 
93     napi_value func;
94     auto status = napi_define_class(env, class_name, NAPI_AUTO_LENGTH, ctor, nullptr, np.size(), np.data(), &func);
95 
96     NapiApi::MyInstanceState* mis;
97     NapiApi::MyInstanceState::GetInstance(env, (void**)&mis);
98     if (mis) {
99         mis->StoreCtor(class_name, func);
100     }
101 }
GetInstanceImpl(uint32_t id)102 void* BaseLight::GetInstanceImpl(uint32_t id)
103 {
104     if (id == BaseLight::ID)
105         return this;
106     return NodeImpl::GetInstanceImpl(id);
107 }
108 
DisposeNative(void * scn,BaseObject * tro)109 void BaseLight::DisposeNative(void* scn, BaseObject* tro)
110 {
111     LOG_V("BaseLight::DisposeNative");
112 
113     if (auto* sceneJS = static_cast<SceneJS*>(scn)) {
114         sceneJS->ReleaseStrongDispose(reinterpret_cast<uintptr_t>(&scene_));
115     }
116 
117     colorProxy_.reset();
118     if (auto light = interface_pointer_cast<SCENE_NS::ILight>(tro->GetNativeObject())) {
119         tro->UnsetNativeObject();
120         if (!IsAttached()) {
121             if (auto node = interface_pointer_cast<SCENE_NS::INode>(light)) {
122                 if (auto scene = node->GetScene()) {
123                     scene->RemoveNode(BASE_NS::move(node)).Wait();
124                 }
125             }
126         }
127     }
128     scene_.Reset();
129 }
GetlightType(NapiApi::FunctionContext<> & ctx)130 napi_value BaseLight::GetlightType(NapiApi::FunctionContext<>& ctx)
131 {
132     if (!validateSceneRef()) {
133         return ctx.GetUndefined();
134     }
135 
136     uint32_t type = -1; // return -1 if the object does not exist anymore
137     if (auto node = ctx.This().GetNative<SCENE_NS::ILight>()) {
138         type = lightType_;
139     }
140     return ctx.GetNumber(type);
141 }
142 
GetEnabled(NapiApi::FunctionContext<> & ctx)143 napi_value BaseLight::GetEnabled(NapiApi::FunctionContext<>& ctx)
144 {
145     if (!validateSceneRef()) {
146         return ctx.GetUndefined();
147     }
148     bool enable = false;
149     auto node = ctx.This().GetNative<SCENE_NS::INode>();
150     if (node) {
151         enable = node->Enabled()->GetValue();
152     }
153     return ctx.GetBoolean(enable);
154 }
SetEnabled(NapiApi::FunctionContext<bool> & ctx)155 void BaseLight::SetEnabled(NapiApi::FunctionContext<bool>& ctx)
156 {
157     if (!validateSceneRef()) {
158         return;
159     }
160     bool enabled = ctx.Arg<0>();
161     auto node = ctx.This().GetNative<SCENE_NS::INode>();
162     if (node) {
163         node->Enabled()->SetValue(enabled);
164     }
165 }
166 
GetColor(NapiApi::FunctionContext<> & ctx)167 napi_value BaseLight::GetColor(NapiApi::FunctionContext<>& ctx)
168 {
169     if (!validateSceneRef()) {
170         return ctx.GetUndefined();
171     }
172     auto node = ctx.This().GetNative<SCENE_NS::ILight>();
173     if (!node) {
174         return ctx.GetUndefined();
175     }
176     if (colorProxy_ == nullptr) {
177         colorProxy_ = BASE_NS::make_unique<ColorProxy>(ctx.GetEnv(), node->Color());
178     }
179     return colorProxy_->Value();
180 }
SetColor(NapiApi::FunctionContext<Object> & ctx)181 void BaseLight::SetColor(NapiApi::FunctionContext<Object>& ctx)
182 {
183     if (!validateSceneRef()) {
184         return;
185     }
186     auto node = ctx.This().GetNative<SCENE_NS::ILight>();
187     if (!node) {
188         return;
189     }
190     NapiApi::Object obj = ctx.Arg<0>();
191     if (colorProxy_ == nullptr) {
192         colorProxy_ = BASE_NS::make_unique<ColorProxy>(ctx.GetEnv(), node->Color());
193     }
194     colorProxy_->SetValue(obj);
195 }
196 
GetShadowEnabled(NapiApi::FunctionContext<> & ctx)197 napi_value BaseLight::GetShadowEnabled(NapiApi::FunctionContext<>& ctx)
198 {
199     if (!validateSceneRef()) {
200         return ctx.GetUndefined();
201     }
202     bool enable = false;
203     auto node = ctx.This().GetNative<SCENE_NS::ILight>();
204     if (node) {
205         enable = node->ShadowEnabled()->GetValue();
206     }
207     return ctx.GetBoolean(enable);
208 }
SetShadowEnabled(NapiApi::FunctionContext<bool> & ctx)209 void BaseLight::SetShadowEnabled(NapiApi::FunctionContext<bool>& ctx)
210 {
211     if (!validateSceneRef()) {
212         return;
213     }
214     bool enabled = ctx.Arg<0>();
215     auto node = ctx.This().GetNative<SCENE_NS::ILight>();
216     if (node) {
217         node->ShadowEnabled()->SetValue(enabled);
218     }
219 }
220 
GetIntensity(NapiApi::FunctionContext<> & ctx)221 napi_value BaseLight::GetIntensity(NapiApi::FunctionContext<>& ctx)
222 {
223     if (!validateSceneRef()) {
224         return ctx.GetUndefined();
225     }
226     float intensity = 0.0f;
227     auto node = ctx.This().GetNative<SCENE_NS::ILight>();
228     if (node) {
229         intensity = node->Intensity()->GetValue();
230     }
231     return ctx.GetNumber(intensity);
232 }
SetIntensity(NapiApi::FunctionContext<float> & ctx)233 void BaseLight::SetIntensity(NapiApi::FunctionContext<float>& ctx)
234 {
235     if (!validateSceneRef()) {
236         return;
237     }
238     float intensity = ctx.Arg<0>();
239     auto node = ctx.This().GetNative<SCENE_NS::ILight>();
240     if (node) {
241         node->Intensity()->SetValue(intensity);
242     }
243 }
244 
SpotLightJS(napi_env e,napi_callback_info i)245 SpotLightJS::SpotLightJS(napi_env e, napi_callback_info i)
246     : BaseObject(e, i), BaseLight(BaseLight::LightType::SPOT)
247 {
248     Create(e, i);
249     if (auto light = interface_pointer_cast<SCENE_NS::ILight>(GetNativeObject())) {
250         light->Type()->SetValue(SCENE_NS::LightType::SPOT);
251     }
252 }
Init(napi_env env,napi_value exports)253 void SpotLightJS::Init(napi_env env, napi_value exports)
254 {
255     BASE_NS::vector<napi_property_descriptor> node_props;
256 
257     BaseLight::Init("SpotLight", env, exports, node_props, BaseObject::ctor<SpotLightJS>());
258 }
259 
GetInstanceImpl(uint32_t id)260 void* SpotLightJS::GetInstanceImpl(uint32_t id)
261 {
262     if (id == SpotLightJS::ID)
263         return this;
264     return BaseLight::GetInstanceImpl(id);
265 }
DisposeNative(void * scn)266 void SpotLightJS::DisposeNative(void* scn)
267 {
268     if (disposed_) {
269         return;
270     }
271     BaseLight::DisposeNative(scn, this);
272     disposed_ = true;
273 }
Finalize(napi_env env)274 void SpotLightJS::Finalize(napi_env env)
275 {
276     DisposeNative(scene_.GetObject().GetJsWrapper<SceneJS>());
277     BaseObject::Finalize(env);
278 }
279 
PointLightJS(napi_env e,napi_callback_info i)280 PointLightJS::PointLightJS(napi_env e, napi_callback_info i)
281     : BaseObject(e, i), BaseLight(BaseLight::LightType::POINT)
282 {
283     Create(e, i);
284     if (auto light = interface_pointer_cast<SCENE_NS::ILight>(GetNativeObject())) {
285         light->Type()->SetValue(SCENE_NS::LightType::POINT);
286     }
287 }
GetInstanceImpl(uint32_t id)288 void* PointLightJS::GetInstanceImpl(uint32_t id)
289 {
290     if (id == PointLightJS::ID)
291         return this;
292     return BaseLight::GetInstanceImpl(id);
293 }
DisposeNative(void * scn)294 void PointLightJS::DisposeNative(void* scn)
295 {
296     if (disposed_) {
297         return;
298     }
299     BaseLight::DisposeNative(scn, this);
300     disposed_ = true;
301 }
Finalize(napi_env env)302 void PointLightJS::Finalize(napi_env env)
303 {
304     DisposeNative(scene_.GetObject().GetJsWrapper<SceneJS>());
305     BaseObject::Finalize(env);
306 }
Init(napi_env env,napi_value exports)307 void PointLightJS::Init(napi_env env, napi_value exports)
308 {
309     BASE_NS::vector<napi_property_descriptor> node_props;
310     BaseLight::Init("PointLight", env, exports, node_props, BaseObject::ctor<PointLightJS>());
311 }
312 
DirectionalLightJS(napi_env e,napi_callback_info i)313 DirectionalLightJS::DirectionalLightJS(napi_env e, napi_callback_info i)
314     : BaseObject(e, i), BaseLight(BaseLight::LightType::DIRECTIONAL)
315 {
316     Create(e, i);
317     if (auto light = interface_pointer_cast<SCENE_NS::ILight>(GetNativeObject())) {
318         light->Type()->SetValue(SCENE_NS::LightType::DIRECTIONAL);
319     }
320 }
GetInstanceImpl(uint32_t id)321 void* DirectionalLightJS::GetInstanceImpl(uint32_t id)
322 {
323     if (id == DirectionalLightJS::ID)
324         return this;
325     return BaseLight::GetInstanceImpl(id);
326 }
DisposeNative(void * scn)327 void DirectionalLightJS::DisposeNative(void* scn)
328 {
329     if (disposed_) {
330         return;
331     }
332     BaseLight::DisposeNative(scn, this);
333     disposed_ = true;
334 }
Finalize(napi_env env)335 void DirectionalLightJS::Finalize(napi_env env)
336 {
337     DisposeNative(scene_.GetObject().GetJsWrapper<SceneJS>());
338     BaseObject::Finalize(env);
339 }
340 
Init(napi_env env,napi_value exports)341 void DirectionalLightJS::Init(napi_env env, napi_value exports)
342 {
343     BASE_NS::vector<napi_property_descriptor> node_props;
344     node_props.push_back(
345         GetSetProperty<float, DirectionalLightJS, &DirectionalLightJS::GetNear, &DirectionalLightJS::SetNear>(
346             "nearPlane"));
347     BaseLight::Init("DirectionalLight", env, exports, node_props, BaseObject::ctor<DirectionalLightJS>());
348 }
349 
GetNear(NapiApi::FunctionContext<> & ctx)350 napi_value DirectionalLightJS::GetNear(NapiApi::FunctionContext<>& ctx)
351 {
352     if (!validateSceneRef()) {
353         return ctx.GetUndefined();
354     }
355     float near = 0.0;
356     if (auto light = interface_cast<SCENE_NS::ILight>(GetNativeObject())) {
357         near = light->NearPlane()->GetValue();
358     }
359     return ctx.GetNumber(near);
360 }
361 
SetNear(NapiApi::FunctionContext<float> & ctx)362 void DirectionalLightJS::SetNear(NapiApi::FunctionContext<float>& ctx)
363 {
364     if (!validateSceneRef()) {
365         return;
366     }
367     float near = ctx.Arg<0>();
368     if (auto light = interface_cast<SCENE_NS::ILight>(GetNativeObject())) {
369         light->NearPlane()->SetValue(near);
370     }
371 }
372