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