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