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 "SceneResourceImpl.h"
17
18 #include "BaseObjectJS.h"
19 #include "SceneJS.h"
20
21 #include <meta/api/util.h>
22
SceneResourceImpl(SceneResourceType type)23 SceneResourceImpl::SceneResourceImpl(SceneResourceType type) : type_(type)
24 {
25 LOG_V("SceneResourceImpl ++");
26 }
~SceneResourceImpl()27 SceneResourceImpl::~SceneResourceImpl()
28 {
29 LOG_V("SceneResourceImpl --");
30 }
31
RegisterEnums(NapiApi::Object exports)32 void SceneResourceImpl::RegisterEnums(NapiApi::Object exports)
33 {
34 napi_value v;
35 NapiApi::Object SceneResourceType(exports.GetEnv());
36
37 #define DECL_ENUM(enu, x) \
38 { \
39 napi_create_uint32(enu.GetEnv(), SceneResourceType::x, &v); \
40 enu.Set(#x, v); \
41 }
42 DECL_ENUM(SceneResourceType, UNKNOWN);
43 DECL_ENUM(SceneResourceType, NODE);
44 DECL_ENUM(SceneResourceType, ENVIRONMENT);
45 DECL_ENUM(SceneResourceType, MATERIAL);
46 DECL_ENUM(SceneResourceType, MESH);
47 DECL_ENUM(SceneResourceType, ANIMATION);
48 DECL_ENUM(SceneResourceType, SHADER);
49 DECL_ENUM(SceneResourceType, IMAGE);
50 DECL_ENUM(SceneResourceType, MESH_RESOURCE);
51 #undef DECL_ENUM
52
53 exports.Set("SceneResourceType", SceneResourceType);
54 }
55
GetPropertyDescs(BASE_NS::vector<napi_property_descriptor> & props)56 void SceneResourceImpl::GetPropertyDescs(BASE_NS::vector<napi_property_descriptor>& props)
57 {
58 props.push_back(
59 TROGetSetProperty<BASE_NS::string, SceneResourceImpl, &SceneResourceImpl::GetName, &SceneResourceImpl::SetName>(
60 "name"));
61 props.push_back(TROGetProperty<NapiApi::Object, SceneResourceImpl, &SceneResourceImpl::GetUri>("uri"));
62 props.push_back(
63 TROGetProperty<BASE_NS::string, SceneResourceImpl, &SceneResourceImpl::GetObjectType>("resourceType"));
64 props.push_back(
65 MakeTROMethod<NapiApi::FunctionContext<>, SceneResourceImpl, &SceneResourceImpl::Dispose>("destroy"));
66 }
67
GetInstanceImpl(uint32_t id)68 void* SceneResourceImpl::GetInstanceImpl(uint32_t id)
69 {
70 if (id == SceneResourceImpl::ID)
71 return this;
72 return nullptr;
73 }
validateSceneRef()74 bool SceneResourceImpl::validateSceneRef()
75 {
76 if (scene_.GetObject()) {
77 // scene reference still valid.
78 // so resource should still be valid.
79 return true;
80 }
81 // scene reference lost, so the resource should be disposed
82 LOG_V("Scene reference lost.");
83 return false;
84 }
85
Dispose(NapiApi::FunctionContext<> & ctx)86 napi_value SceneResourceImpl::Dispose(NapiApi::FunctionContext<>& ctx)
87 {
88 // Dispose of the native object. (makes the js object invalid)
89 if (TrueRootObject* instance = ctx.This().GetRoot()) {
90 // see if we have "scenejs" as ext (prefer one given as argument)
91 napi_status stat;
92 SceneJS* ptr { nullptr };
93 NapiApi::FunctionContext<NapiApi::Object> args(ctx);
94 if (args) {
95 if (NapiApi::Object obj = args.Arg<0>()) {
96 if (napi_value ext = obj.Get("SceneJS")) {
97 stat = napi_get_value_external(ctx.GetEnv(), ext, (void**)&ptr);
98 }
99 }
100 }
101 if (!ptr) {
102 ptr = scene_.GetObject().GetJsWrapper<SceneJS>();
103 }
104 instance->DisposeNative(ptr);
105 }
106 scene_.Reset();
107 uri_.Reset();
108 return ctx.GetUndefined();
109 }
110
GetObjectType(NapiApi::FunctionContext<> & ctx)111 napi_value SceneResourceImpl::GetObjectType(NapiApi::FunctionContext<>& ctx)
112 {
113 if (!validateSceneRef()) {
114 return ctx.GetUndefined();
115 }
116
117 uint32_t type = -1; // return -1 if the resource does not exist anymore
118 if (ctx.This().GetNative()) {
119 type = type_;
120 }
121 return ctx.GetNumber(type);
122 }
123
GetName(NapiApi::FunctionContext<> & ctx)124 napi_value SceneResourceImpl::GetName(NapiApi::FunctionContext<>& ctx)
125 {
126 if (!validateSceneRef()) {
127 return ctx.GetUndefined();
128 }
129
130 BASE_NS::string name;
131 auto native = ctx.This().GetNative();
132 if (auto named = interface_cast<META_NS::INamed>(native)) {
133 name = META_NS::GetValue(named->Name());
134 } else if (native) {
135 name = native->GetName();
136 }
137 if (name.empty()) {
138 name = name_; // Use cached if we didn't get anything from underlying object
139 }
140 return ctx.GetString(name);
141 }
SetName(NapiApi::FunctionContext<BASE_NS::string> & ctx)142 void SceneResourceImpl::SetName(NapiApi::FunctionContext<BASE_NS::string>& ctx)
143 {
144 if (!validateSceneRef()) {
145 return;
146 }
147 BASE_NS::string name = ctx.Arg<0>();
148 auto object = ctx.This();
149 auto native = object.GetNative();
150 if (auto named = interface_cast<META_NS::INamed>(native)) {
151 META_NS::SetValue(named->Name(), name);
152 } else if (auto objectname = interface_cast<META_NS::IObjectName>(native)) {
153 objectname->SetName(name);
154 } else {
155 // Object does not support naming, store name locally
156 name_ = name;
157 }
158 }
SetUri(NapiApi::StrongRef uri)159 void SceneResourceImpl::SetUri(NapiApi::StrongRef uri)
160 {
161 if (!validateSceneRef()) {
162 return;
163 }
164 uri_ = BASE_NS::move(uri);
165 }
GetUri(NapiApi::FunctionContext<> & ctx)166 napi_value SceneResourceImpl::GetUri(NapiApi::FunctionContext<>& ctx)
167 {
168 if (!validateSceneRef()) {
169 return ctx.GetUndefined();
170 }
171 return uri_.GetValue();
172 }
173