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 "GeometryJS.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/ext/intf_internal_scene.h>
21 #include <scene/interface/intf_camera.h>
22 #include <scene/interface/intf_mesh.h>
23 #include <scene/interface/intf_mesh_resource.h>
24 #include <scene/interface/intf_scene.h>
25
26 #include "MeshResourceJS.h"
27 #include "ParamParsing.h"
28 #include "SceneJS.h"
29 #include "geometry_definition/GeometryDefinition.h"
30
GetInstanceImpl(uint32_t id)31 void* GeometryJS::GetInstanceImpl(uint32_t id)
32 {
33 if (id == GeometryJS::ID)
34 return this;
35 return NodeImpl::GetInstanceImpl(id);
36 }
37
DisposeNative(void * scn)38 void GeometryJS::DisposeNative(void* scn)
39 {
40 if (disposed_) {
41 return;
42 }
43 LOG_V("GeometryJS::DisposeNative");
44 disposed_ = true;
45
46 SceneJS* sceneJS = static_cast<SceneJS*>(scn);
47 if (sceneJS) {
48 sceneJS->ReleaseDispose(reinterpret_cast<uintptr_t>(&scene_));
49 }
50
51 if (auto node = interface_pointer_cast<SCENE_NS::INode>(GetNativeObject())) {
52 if (!IsAttached()) {
53 if (auto access = interface_pointer_cast<SCENE_NS::IMeshAccess>(node)) {
54 access->SetMesh(nullptr).Wait();
55 }
56 if (auto scene = node->GetScene()) {
57 scene->RemoveNode(BASE_NS::move(node)).Wait();
58 }
59 }
60 UnsetNativeObject();
61 }
62 scene_.Reset();
63 }
Init(napi_env env,napi_value exports)64 void GeometryJS::Init(napi_env env, napi_value exports)
65 {
66 BASE_NS::vector<napi_property_descriptor> node_props;
67 NodeImpl::GetPropertyDescs(node_props);
68
69 using namespace NapiApi;
70 node_props.push_back(GetProperty<Object, GeometryJS, &GeometryJS::GetMesh>("mesh"));
71 node_props.push_back(GetProperty<Object, GeometryJS, &GeometryJS::GetMorpher>("morpher"));
72
73 napi_value func;
74 auto status = napi_define_class(env, "Geometry", NAPI_AUTO_LENGTH, BaseObject::ctor<GeometryJS>(), nullptr,
75 node_props.size(), node_props.data(), &func);
76
77 NapiApi::MyInstanceState* mis;
78 NapiApi::MyInstanceState::GetInstance(env, (void**)&mis);
79 if (mis) {
80 mis->StoreCtor("Geometry", func);
81 }
82 }
83
GeometryJS(napi_env e,napi_callback_info i)84 GeometryJS::GeometryJS(napi_env e, napi_callback_info i) : BaseObject(e, i), NodeImpl(NodeImpl::GEOMETRY)
85 {
86 LOG_V("GeometryJS ++ ");
87
88 if (auto ctx = NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> { e, i }) {
89 Construct(e, ctx.This(), ctx.Arg<0>(), ctx.Arg<1>());
90 } else {
91 LOG_E("Bad args given for GeometryJS constructor");
92 return;
93 }
94 }
~GeometryJS()95 GeometryJS::~GeometryJS()
96 {
97 LOG_V("GeometryJS -- ");
98 }
99
Finalize(napi_env env)100 void GeometryJS::Finalize(napi_env env)
101 {
102 DisposeNative(scene_.GetObject().GetJsWrapper<SceneJS>());
103 BaseObject::Finalize(env);
104 }
105
Construct(napi_env env,NapiApi::Object meJs,NapiApi::Object scene,NapiApi::Object sceneNodeParameters)106 void GeometryJS::Construct(
107 napi_env env, NapiApi::Object meJs, NapiApi::Object scene, NapiApi::Object sceneNodeParameters)
108 {
109 if (!scene.GetNative<SCENE_NS::IScene>()) {
110 LOG_W("Can't construct GeometryJS: Scene has gone missing");
111 return;
112 }
113 scene_ = NapiApi::WeakRef { env, scene.ToNapiValue() };
114
115 // Add the dispose hook to scene so that the Geometry node is disposed when scene is disposed.
116 if (const auto sceneJS = scene.GetJsWrapper<SceneJS>()) {
117 sceneJS->DisposeHook(reinterpret_cast<uintptr_t>(&scene_), meJs);
118 }
119
120 if (const auto name = ExtractName(sceneNodeParameters); !name.empty()) {
121 meJs.Set("name", name);
122 }
123 }
124
GetMesh(NapiApi::FunctionContext<> & ctx)125 napi_value GeometryJS::GetMesh(NapiApi::FunctionContext<>& ctx)
126 {
127 if (!validateSceneRef()) {
128 return ctx.GetUndefined();
129 }
130
131 META_NS::IObject::Ptr mesh = GetNativeObject();
132 if (!interface_cast<SCENE_NS::IMesh>(mesh)) {
133 mesh = nullptr;
134 }
135
136 if (!mesh) {
137 // no mesh.
138 return ctx.GetNull();
139 }
140
141 NapiApi::Env env(ctx.Env());
142 NapiApi::Object argJS(env);
143 napi_value args[] = { scene_.GetValue(), argJS.ToNapiValue() };
144 return CreateFromNativeInstance(env, "Mesh", mesh, PtrType::WEAK, args, "_JSWMesh").ToNapiValue();
145 }
146
GetMorpher(NapiApi::FunctionContext<> & ctx)147 napi_value GeometryJS::GetMorpher(NapiApi::FunctionContext<>& ctx)
148 {
149 if (!validateSceneRef()) {
150 return ctx.GetUndefined();
151 }
152
153 META_NS::IObject::Ptr node = GetNativeObject();
154 auto access = interface_cast<SCENE_NS::IMorphAccess>(node);
155
156 if (!access || !access->Morpher()) {
157 // no morpher.
158 return ctx.GetNull();
159 }
160
161 SCENE_NS::IMorpher::Ptr morpher = META_NS::GetValue(access->Morpher());
162 NapiApi::Env env(ctx.Env());
163 NapiApi::Object argJS(env);
164 napi_value args[] = { scene_.GetValue(), argJS.ToNapiValue() };
165 return CreateFromNativeInstance(env, "Morpher", morpher, PtrType::WEAK, args, "_JSWMorpher")
166 .ToNapiValue();
167 }
168