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 <scene_plugin/api/mesh_uid.h>
16 #include <scene_plugin/interface/intf_mesh.h>
17
18 #include <meta/ext/concrete_base_object.h>
19
20 #include "bind_templates.inl"
21 #include "intf_multi_mesh_initialization.h"
22 #include "node_impl.h"
23 #include "task_utils.h"
24
25 using SCENE_NS::MakeTask;
26 namespace {
27
28 class MultiMeshImpl : public META_NS::ObjectFwd<MultiMeshImpl, SCENE_NS::ClassId::MultiMeshProxy,
29 META_NS::ClassId::Object, SCENE_NS::IMultiMeshProxy, IMultimeshInitilization> {
30 META_IMPLEMENT_INTERFACE_PROPERTY(
31 SCENE_NS::IMultiMeshProxy, SCENE_NS::IMaterial::Ptr, MaterialOverride, {}, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
32 // META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(
33 // SCENE_NS::IMultiMeshProxy, BASE_NS::string, MaterialOverrideUri, {}, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
34 META_IMPLEMENT_INTERFACE_PROPERTY(
35 SCENE_NS::IMultiMeshProxy, SCENE_NS::IMesh::Ptr, Mesh, {}, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
36 META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IMultiMeshProxy, size_t, VisibleInstanceCount, 0u)
37 META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(SCENE_NS::IMultiMeshProxy, BASE_NS::Math::Vec4, CustomData)
38 META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(SCENE_NS::IMultiMeshProxy, BASE_NS::Math::Mat4X4, Transforms)
39
40 void SetInstanceCount(size_t count) override
41 {
42 // post to engine
43 if (auto sh = sceneHolder_.lock()) {
44 sh->QueueEngineTask(MakeTask(
__anonac8615180202(auto selfObject) 45 [count](auto selfObject) {
46 if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) {
47 if (auto sceneHolder = self->sceneHolder_.lock()) {
48 CORE_NS::Entity mm;
49 mm.id = self->handle_;
50 sceneHolder->SetInstanceCountMultimeshArray(mm, count);
51 }
52 }
53 return false;
54 },
55 GetSelf()),
56 false);
57 }
58
59 // Make sure that array properties are in sync
60 auto size = META_ACCESS_PROPERTY(CustomData)->GetSize();
61 assert(size == META_ACCESS_PROPERTY(Transforms)->GetSize());
62 do {
63 if (count > size) {
64 META_ACCESS_PROPERTY(CustomData)->AddValue({ 1.f, 1.f, 1.f, 1.f });
65 META_ACCESS_PROPERTY(Transforms)->AddValue(BASE_NS::Math::IDENTITY_4X4);
66 } else if (count < size) {
67 META_ACCESS_PROPERTY(CustomData)->RemoveAt(size - 1);
68 META_ACCESS_PROPERTY(Transforms)->RemoveAt(size - 1);
69 }
70 size = META_ACCESS_PROPERTY(CustomData)->GetSize();
71 } while (size != count);
72 }
73
74 SceneHolder::WeakPtr sceneHolder_;
75 uint64_t handle_ {};
76 BASE_NS::vector<CORE_NS::Entity> overridenMaterials_;
77
Initialize(SceneHolder::Ptr sceneHolder,size_t instanceCount,CORE_NS::Entity baseComponent)78 void Initialize(SceneHolder::Ptr sceneHolder, size_t instanceCount, CORE_NS::Entity baseComponent) override
79 {
80 sceneHolder_ = sceneHolder;
81 if (auto sh = sceneHolder) {
82 sh->QueueEngineTask(MakeTask(
83 [baseComponent](auto sceneHolder, auto self) {
84 auto entity = sceneHolder->CreateMultiMeshInstance(baseComponent);
85 static_cast<MultiMeshImpl*>(self.get())->handle_ = entity.id;
86
87 return false;
88 },
89 sceneHolder_, GetSelf()),
90 false);
91 }
92 SetInstanceCount(instanceCount);
93 }
94
Build(const IMetadata::Ptr & data)95 bool Build(const IMetadata::Ptr& data) override
96 {
97 // subscribe mesh changes
98 Mesh()->OnChanged()->AddHandler(
99 META_NS::MakeCallback<META_NS::IOnChanged>([weak = BASE_NS::weak_ptr(GetSelf())]() {
100 if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) {
101 if (auto sh = self->sceneHolder_.lock()) {
102 sh->QueueEngineTask(MakeTask([weak]() {
103 if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) {
104 auto mesh = interface_pointer_cast<INodeEcsInterfacePrivate>(self->Mesh()->GetValue());
105 if (!mesh || !mesh->EcsObject()) {
106 return false; // Not sure if user should be able to reset ecs mesh by
107 // setting the property as null
108 }
109 if (auto sceneHolder = self->sceneHolder_.lock()) {
110 CORE_NS::Entity mm;
111 mm.id = self->handle_;
112 sceneHolder->SetMeshMultimeshArray(mm, mesh->EcsObject()->GetEntity());
113 }
114 }
115 return false;
116 }),
117 false);
118 }
119 }
120 }),
121 reinterpret_cast<uint64_t>(this));
122
123 // subscribe material changes
124 MaterialOverride()->OnChanged()->AddHandler(
125 META_NS::MakeCallback<META_NS::IOnChanged>([weak = BASE_NS::weak_ptr(GetSelf())]() {
126 if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) {
127 if (auto sh = self->sceneHolder_.lock()) {
128 sh->QueueEngineTask(
129 MakeTask(
130 [](auto selfObject) {
131 if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) {
132 if (auto sceneHolder = self->sceneHolder_.lock()) {
133 CORE_NS::Entity mm;
134 mm.id = self->handle_;
135 auto material = interface_pointer_cast<INodeEcsInterfacePrivate>(
136 self->MaterialOverride()->GetValue());
137 if (!material || !material->EcsObject()) {
138 if (!self->overridenMaterials_.empty()) {
139 sceneHolder->ResetOverrideMaterialMultimeshArray(
140 mm, self->overridenMaterials_);
141 }
142 } else {
143 auto backup = sceneHolder->SetOverrideMaterialMultimeshArray(
144 mm, material->EcsObject()->GetEntity());
145 if (self->overridenMaterials_.empty()) {
146 self->overridenMaterials_ =
147 backup; // store backup only for the first change
148 }
149 }
150 }
151 }
152 return false;
153 },
154 weak),
155 false);
156 }
157 }
158 }),
159 reinterpret_cast<uint64_t>(this));
160
161 // subscribe visible count changes
162 VisibleInstanceCount()->OnChanged()->AddHandler(
163 META_NS::MakeCallback<META_NS::IOnChanged>([weak = BASE_NS::weak_ptr(GetSelf())]() {
164 if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) {
165 auto count = self->VisibleInstanceCount()->GetValue();
166 if (auto sh = self->sceneHolder_.lock()) {
167 sh->QueueEngineTask(MakeTask(
168 [count](auto selfObject) {
169 if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) {
170 if (auto sceneHolder = self->sceneHolder_.lock()) {
171 CORE_NS::Entity mm;
172 mm.id = self->handle_;
173 sceneHolder->SetVisibleCountMultimeshArray(mm, count);
174 }
175 }
176 return false;
177 },
178 weak),
179 false);
180 }
181 }
182 }),
183 reinterpret_cast<uint64_t>(this));
184
185 //todo
186 // subscribe CustomData changes, write only
187 /*CustomData()->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IMetaArrayProperty::
188 OnChangedType>([weak = BASE_NS::weak_ptr(GetSelf())](
189 META::ArrayChangeNotification::ConstPtr ptr) {
190 if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) {
191 for (auto& ref : ptr->Changes) {
192 if (ref.Type == META::ArrayChangeNotification::MODIFIED ||
193 ref.Type == META::ArrayChangeNotification::ADDED) {
194 auto ix = ref.Begin;
195 auto data = self->CustomData()->Get(ix);
196 if (auto sh = self->sceneHolder_.lock()) {
197 sh->QueueEngineTask(
198 MakeTask(
199 [data, ix](auto selfObject) {
200 if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) {
201 if (auto sceneHolder = self->sceneHolder_.lock()) {
202 CORE_NS::Entity mm;
203 mm.id = self->handle_;
204 sceneHolder->SetCustomData(mm, ix, { data.x, data.y, data.z, data.w });
205 }
206 }
207 return false;
208 },
209 weak),
210 false);
211 }
212 }
213 }
214 }
215 }),
216 reinterpret_cast<uint64_t>(this));*/
217
218 //todo
219 // subscribe Transformation changes, write only
220 /*
221 Transforms()->OnChanged()->AddHandler(
222 META_NS::MakeCallback<META_NS::IMetaArrayProperty::OnChangedType>(
223 [weak = BASE_NS::weak_ptr(GetSelf())](META::ArrayChangeNotification::ConstPtr ptr) {
224 if (auto self = static_pointer_cast<MultiMeshImpl>(weak.lock())) {
225 for (auto& ref : ptr->Changes) {
226 if (ref.Type == META::ArrayChangeNotification::MODIFIED ||
227 ref.Type == META::ArrayChangeNotification::ADDED) {
228 auto ix = ref.Begin;
229 auto data = self->Transforms()->Get(ix);
230 if (auto sh = self->sceneHolder_.lock()) {
231 sh->QueueEngineTask(
232 MakeTask(
233 [data, ix](auto selfObject) {
234 if (auto self = static_pointer_cast<MultiMeshImpl>(selfObject)) {
235 if (auto sceneHolder = self->sceneHolder_.lock()) {
236 CORE_NS::Entity mm;
237 mm.id = self->handle_;
238 sceneHolder->SetTransformation(mm, ix, data);
239 }
240 }
241 return false;
242 },
243 weak),
244 false);
245 }
246 }
247 }
248 }
249 }),
250 reinterpret_cast<uint64_t>(this));
251 */
252 return true;
253 }
254 };
255 } // namespace
SCENE_BEGIN_NAMESPACE()256 SCENE_BEGIN_NAMESPACE()
257 void RegisterMultiMeshImpl()
258 {
259 META_NS::GetObjectRegistry().RegisterObjectType<MultiMeshImpl>();
260 }
UnregisterMultiMeshImpl()261 void UnregisterMultiMeshImpl()
262 {
263 META_NS::GetObjectRegistry().UnregisterObjectType<MultiMeshImpl>();
264 }
265
266 SCENE_END_NAMESPACE()