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 "SceneComponentJS.h"
17
18 #include <meta/api/make_callback.h>
19 #include <meta/interface/intf_metadata.h>
20 #include <meta/interface/intf_task_queue.h>
21 #include <meta/interface/intf_task_queue_registry.h>
22 #include <meta/interface/property/property_events.h>
23 #include <scene/interface/intf_node.h>
24 #include <scene/interface/intf_scene.h>
25 #include <scene/ext/intf_component.h>
26 #include <scene/ext/util.h>
27
28 #include <render/intf_render_context.h>
29
30 using namespace SCENE_NS;
31
Init(napi_env env,napi_value exports)32 void SceneComponentJS::Init(napi_env env, napi_value exports)
33 {
34 using namespace NapiApi;
35
36 BASE_NS::vector<napi_property_descriptor> props;
37
38 napi_value func;
39 auto status = napi_define_class(env, "SceneComponent", NAPI_AUTO_LENGTH, BaseObject::ctor<SceneComponentJS>(),
40 nullptr, props.size(), props.data(), &func);
41
42 NapiApi::MyInstanceState* mis;
43 GetInstanceData(env, (void**)&mis);
44 mis->StoreCtor("SceneComponent", func);
45 }
46
Dispose(NapiApi::FunctionContext<> & ctx)47 napi_value SceneComponentJS::Dispose(NapiApi::FunctionContext<>& ctx)
48 {
49 LOG_V("SceneComponentJS::Dispose");
50 DisposeNative(nullptr);
51 return {};
52 }
DisposeNative(void *)53 void SceneComponentJS::DisposeNative(void*)
54 {
55 if (!disposed_) {
56 disposed_ = true;
57 LOG_V("SceneComponentJS::DisposeNative");
58
59 if (!jsProps_.IsEmpty()) {
60 NapiApi::Object inp = jsProps_.GetObject();
61 for (auto&& v : proxies_) {
62 inp.DeleteProperty(v.first);
63 }
64 proxies_.clear();
65 }
66 jsProps_.Reset();
67
68 SetNativeObject(nullptr, false);
69 SetNativeObject(nullptr, true);
70
71 scene_.Reset();
72 }
73 }
74
GetInstanceImpl(uint32_t id)75 void* SceneComponentJS::GetInstanceImpl(uint32_t id)
76 {
77 if (id == SceneComponentJS::ID) {
78 return this;
79 }
80 return nullptr;
81 }
Finalize(napi_env env)82 void SceneComponentJS::Finalize(napi_env env)
83 {
84 DisposeNative(nullptr);
85 BaseObject<SceneComponentJS>::Finalize(env);
86 }
SceneComponentJS(napi_env e,napi_callback_info i)87 SceneComponentJS::SceneComponentJS(napi_env e, napi_callback_info i) : BaseObject<SceneComponentJS>(e, i)
88 {
89 LOG_V("SceneComponentJS ++");
90 NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
91 if (!fromJs) {
92 return;
93 }
94 scene_ = { NapiApi::Object(fromJs.Arg<0>()) };
95 NapiApi::Object node = fromJs.Arg<1>();
96 META_NS::IObject::Ptr native = GetNativeObjectParam<META_NS::IObject>(node);
97
98 NapiApi::Object meJs(fromJs.This());
99
100 BASE_NS::string name = native->GetName();
101 meJs.Set("name", name);
102 AddProperties(meJs, native);
103
104 SetNativeObject(native, false);
105 }
~SceneComponentJS()106 SceneComponentJS::~SceneComponentJS()
107 {
108 LOG_V("SceneComponentJS --");
109 DisposeNative(nullptr);
110 }
111
AddProperties(NapiApi::Object meJs,const META_NS::IObject::Ptr & obj)112 void SceneComponentJS::AddProperties(NapiApi::Object meJs, const META_NS::IObject::Ptr& obj)
113 {
114 auto comp = interface_cast<SCENE_NS::IComponent>(obj);
115 auto meta = interface_cast<META_NS::IMetadata>(obj);
116 if (!comp || !meta) {
117 return;
118 }
119 comp->PopulateAllProperties();
120
121 NapiApi::Object jsProps(meJs.GetEnv());
122 BASE_NS::vector<napi_property_descriptor> napi_descs;
123 for (auto&& p : meta->GetProperties()) {
124 if (auto proxy = PropertyToProxy(scene_.GetObject(), jsProps, p)) {
125 auto res = proxies_.insert_or_assign(SCENE_NS::PropertyName(p->GetName()), proxy);
126 napi_descs.push_back(CreateProxyDesc(res.first->first.c_str(), BASE_NS::move(proxy)));
127 }
128 }
129
130 if (!napi_descs.empty()) {
131 napi_define_properties(jsProps.GetEnv(), jsProps.ToNapiValue(), napi_descs.size(), napi_descs.data());
132 }
133
134 jsProps_ = NapiApi::StrongRef(jsProps);
135 meJs.Set("properties", jsProps_.GetValue());
136 }
137