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 "ecs.h"
17
18 #include <algorithm>
19 #include <random>
20 #include <scene/ext/util.h>
21
22 #include <3d/ecs/components/environment_component.h>
23 #include <3d/ecs/components/render_configuration_component.h>
24 #include <3d/ecs/systems/intf_render_preprocessor_system.h>
25 #include <3d/implementation_uids.h>
26 #include <3d/util/intf_scene_util.h>
27 #include <core/ecs/intf_system_graph_loader.h>
28 #include <render/datastore/intf_render_data_store.h>
29
30 #include "ecs_object.h"
31 #include "internal_scene.h"
32
SCENE_BEGIN_NAMESPACE()33 SCENE_BEGIN_NAMESPACE()
34
35 template<typename Manager>
36 Manager* Ecs::GetCoreManager()
37 {
38 auto m = CORE_NS::GetManager<Manager>(*ecs);
39 if (m) {
40 components_[m->GetName()] = m;
41 }
42 return m;
43 }
44
Initialize(const BASE_NS::shared_ptr<IInternalScene> & scene,const SceneOptions & opts)45 bool Ecs::Initialize(const BASE_NS::shared_ptr<IInternalScene>& scene, const SceneOptions& opts)
46 {
47 using namespace CORE_NS;
48 scene_ = scene;
49 auto& context = scene->GetRenderContext();
50 auto& engine = context.GetEngine();
51
52 ecs = engine.CreateEcs();
53 ecs->SetRenderMode(CORE_NS::IEcs::RENDER_ALWAYS);
54
55 if (!opts.systemGraphUri.empty()) {
56 auto* factory = GetInstance<ISystemGraphLoaderFactory>(UID_SYSTEM_GRAPH_LOADER);
57 auto systemGraphLoader = factory->Create(engine.GetFileManager());
58 if (systemGraphLoader->Load(opts.systemGraphUri, *ecs).success) {
59 CORE_LOG_D("Using custom system graph: %s", opts.systemGraphUri.c_str());
60 }
61 }
62
63 ecs->Initialize();
64
65 animationComponentManager = GetCoreManager<CORE3D_NS::IAnimationComponentManager>();
66 animationStateComponentManager = GetCoreManager<CORE3D_NS::IAnimationStateComponentManager>();
67 cameraComponentManager = GetCoreManager<CORE3D_NS::ICameraComponentManager>();
68 envComponentManager = GetCoreManager<CORE3D_NS::IEnvironmentComponentManager>();
69 layerComponentManager = GetCoreManager<CORE3D_NS::ILayerComponentManager>();
70 lightComponentManager = GetCoreManager<CORE3D_NS::ILightComponentManager>();
71 materialComponentManager = GetCoreManager<CORE3D_NS::IMaterialComponentManager>();
72 meshComponentManager = GetCoreManager<CORE3D_NS::IMeshComponentManager>();
73 nameComponentManager = GetCoreManager<CORE3D_NS::INameComponentManager>();
74 nodeComponentManager = GetCoreManager<CORE3D_NS::INodeComponentManager>();
75 renderMeshComponentManager = GetCoreManager<CORE3D_NS::IRenderMeshComponentManager>();
76 rhComponentManager = GetCoreManager<CORE3D_NS::IRenderHandleComponentManager>();
77 transformComponentManager = GetCoreManager<CORE3D_NS::ITransformComponentManager>();
78 uriComponentManager = GetCoreManager<CORE3D_NS::IUriComponentManager>();
79 renderConfigComponentManager = GetCoreManager<CORE3D_NS::IRenderConfigurationComponentManager>();
80 postProcessComponentManager = GetCoreManager<CORE3D_NS::IPostProcessComponentManager>();
81 localMatrixComponentManager = GetCoreManager<CORE3D_NS::ILocalMatrixComponentManager>();
82 worldMatrixComponentManager = GetCoreManager<CORE3D_NS::IWorldMatrixComponentManager>();
83 textComponentManager = GetCoreManager<TEXT3D_NS::ITextComponentManager>();
84 morphComponentManager = GetCoreManager<CORE3D_NS::IMorphComponentManager>();
85
86 if (animationComponentManager) {
87 animationQuery.reset(new CORE_NS::ComponentQuery());
88 animationQuery->SetEcsListenersEnabled(true);
89 const ComponentQuery::Operation operations[] = { { *nodeComponentManager, ComponentQuery::Operation::OPTIONAL },
90 { *nameComponentManager, ComponentQuery::Operation::OPTIONAL } };
91 animationQuery->SetupQuery(*animationComponentManager, operations);
92 }
93
94 if (meshComponentManager) {
95 meshQuery.reset(new CORE_NS::ComponentQuery());
96 meshQuery->SetEcsListenersEnabled(true);
97 const ComponentQuery::Operation operations[] = { { *nodeComponentManager, ComponentQuery::Operation::OPTIONAL },
98 { *nameComponentManager, ComponentQuery::Operation::OPTIONAL } };
99 meshQuery->SetupQuery(*meshComponentManager, operations);
100 }
101
102 if (materialComponentManager) {
103 materialQuery.reset(new CORE_NS::ComponentQuery());
104 materialQuery->SetEcsListenersEnabled(true);
105 const ComponentQuery::Operation operations[] = { { *nodeComponentManager, ComponentQuery::Operation::OPTIONAL },
106 { *nameComponentManager, ComponentQuery::Operation::OPTIONAL },
107 { *uriComponentManager, ComponentQuery::Operation::OPTIONAL } };
108 materialQuery->SetupQuery(*materialComponentManager, operations);
109 }
110 nodeSystem = GetSystem<CORE3D_NS::INodeSystem>(*ecs);
111 picking = GetInstance<CORE3D_NS::IPicking>(*context.GetInterface<IClassRegister>(), CORE3D_NS::UID_PICKING);
112
113 entityOwnerComponentManager =
114 static_cast<IEntityOwnerComponentManager*>(ecs->CreateComponentManager(ENTITY_OWNER_COMPONENT_TYPE_INFO));
115
116 if (!entityOwnerComponentManager || !nodeSystem || !picking) {
117 return false;
118 }
119
120 components_[entityOwnerComponentManager->GetName()] = entityOwnerComponentManager;
121
122 if (!EcsListener::Initialize(*this)) {
123 CORE_LOG_E("failed to initialize ecs listener");
124 return false;
125 }
126
127 return true;
128 }
129
Uninitialize()130 void Ecs::Uninitialize()
131 {
132 EcsListener::Uninitialize();
133 nodeSystem->RemoveListener(*this);
134 animationComponentManager = {};
135 cameraComponentManager = {};
136 envComponentManager = {};
137 layerComponentManager = {};
138 lightComponentManager = {};
139 materialComponentManager = {};
140 meshComponentManager = {};
141 nameComponentManager = {};
142 nodeComponentManager = {};
143 renderMeshComponentManager = {};
144 rhComponentManager = {};
145 transformComponentManager = {};
146 uriComponentManager = {};
147 renderConfigComponentManager = {};
148 morphComponentManager = {};
149 meshQuery.reset();
150 materialQuery.reset();
151 animationQuery.reset();
152 rootEntity_ = {};
153 nodeSystem = {};
154 picking = {};
155 components_.clear();
156 if (ecs) {
157 ecs->Uninitialize();
158 ecs.reset();
159 }
160 }
161
FindComponent(BASE_NS::string_view name) const162 CORE_NS::IComponentManager* Ecs::FindComponent(BASE_NS::string_view name) const
163 {
164 auto it = components_.find(name);
165 return it != components_.end() ? it->second : nullptr;
166 }
167
FindNode(BASE_NS::string_view path)168 CORE3D_NS::ISceneNode* Ecs::FindNode(BASE_NS::string_view path)
169 {
170 if (path.empty() || path == "/") {
171 return GetNode(rootEntity_);
172 }
173 CORE3D_NS::ISceneNode* node = &nodeSystem->GetRootNode();
174 BASE_NS::string_view p = FirstSegment(path);
175 while (node && !path.empty()) {
176 node = node->GetChild(p);
177 path.remove_prefix(p.size() + 1);
178 p = FirstSegment(path);
179 }
180 return node;
181 }
182
FindNodeParent(BASE_NS::string_view path)183 CORE3D_NS::ISceneNode* Ecs::FindNodeParent(BASE_NS::string_view path)
184 {
185 return FindNode(NormalisePath(ParentPath(path)));
186 }
187
GetPath(const CORE3D_NS::ISceneNode * node) const188 BASE_NS::string Ecs::GetPath(const CORE3D_NS::ISceneNode* node) const
189 {
190 BASE_NS::string path;
191 while (node && node->GetParent()) {
192 path = "/" + node->GetName() + path;
193 node = node->GetParent();
194 }
195 return path;
196 }
197
GetPath(CORE_NS::Entity ent) const198 BASE_NS::string Ecs::GetPath(CORE_NS::Entity ent) const
199 {
200 return GetPath(nodeSystem->GetNode(ent));
201 }
202
IsNodeEntity(CORE_NS::Entity ent) const203 bool Ecs::IsNodeEntity(CORE_NS::Entity ent) const
204 {
205 return nodeSystem->GetNode(ent) != nullptr;
206 }
207
GetRootEntity() const208 CORE_NS::Entity Ecs::GetRootEntity() const
209 {
210 return rootEntity_;
211 }
212
GetParent(CORE_NS::Entity ent) const213 CORE_NS::Entity Ecs::GetParent(CORE_NS::Entity ent) const
214 {
215 if (auto n = nodeComponentManager->Read(ent)) {
216 return n->parent;
217 }
218 return {};
219 }
220
GetEcsObject(CORE_NS::Entity ent)221 IEcsObject::Ptr Ecs::GetEcsObject(CORE_NS::Entity ent)
222 {
223 if (auto obj = FindEcsObject(ent)) {
224 return obj;
225 }
226
227 auto& r = META_NS::GetObjectRegistry();
228 auto md = r.Create<META_NS::IMetadata>(META_NS::ClassId::Object);
229 md->AddProperty(META_NS::ConstructProperty<IInternalScene::Ptr>("Scene", scene_.lock()));
230 md->AddProperty(META_NS::ConstructProperty<CORE_NS::Entity>("Entity", ent));
231 auto obj = r.Create<IEcsObject>(ClassId::EcsObject, md);
232 if (obj) {
233 RegisterEcsObject(obj);
234 }
235
236 return obj;
237 }
238
RemoveEcsObject(const IEcsObject::ConstPtr & obj)239 void Ecs::RemoveEcsObject(const IEcsObject::ConstPtr& obj)
240 {
241 DeregisterEcsObject(obj);
242 }
243
RemoveEntity(CORE_NS::Entity ent)244 bool Ecs::RemoveEntity(CORE_NS::Entity ent)
245 {
246 bool res = CORE_NS::EntityUtil::IsValid(ent);
247 if (res) {
248 DeregisterEcsObject(ent);
249 ecs->GetEntityManager().Destroy(ent);
250 }
251 return res;
252 }
253
CreateUnnamedRootNode()254 bool Ecs::CreateUnnamedRootNode()
255 {
256 if (CORE_NS::EntityUtil::IsValid(rootEntity_)) {
257 return false;
258 }
259
260 BASE_NS::vector<CORE_NS::Entity> children;
261 for (auto&& c : nodeSystem->GetRootNode().GetChildren()) {
262 children.push_back(c->GetEntity());
263 }
264
265 auto root = nodeSystem->CreateNode();
266 rootEntity_ = root->GetEntity();
267 root->SetParent(nodeSystem->GetRootNode());
268
269 for (auto&& n : children) {
270 if (auto root = GetNode(rootEntity_)) {
271 if (auto child = GetNode(n)) {
272 child->SetParent(*root);
273 }
274 }
275 }
276
277 AddDefaultComponents(rootEntity_);
278 return true;
279 }
280
SetNodeName(CORE_NS::Entity ent,BASE_NS::string_view name)281 bool Ecs::SetNodeName(CORE_NS::Entity ent, BASE_NS::string_view name)
282 {
283 auto n = nodeSystem->GetNode(ent);
284 if (n) {
285 n->SetName(name);
286 }
287 return n != nullptr;
288 }
289
SetNodeParentAndName(CORE_NS::Entity ent,BASE_NS::string_view name,CORE3D_NS::ISceneNode * parent)290 bool Ecs::SetNodeParentAndName(CORE_NS::Entity ent, BASE_NS::string_view name, CORE3D_NS::ISceneNode* parent)
291 {
292 auto n = nodeSystem->GetNode(ent);
293 if (n) {
294 n->SetName(name);
295 if (parent) {
296 parent->AddChild(*n);
297 }
298 }
299 return n != nullptr;
300 }
301
GetNode(CORE_NS::Entity ent)302 CORE3D_NS::ISceneNode* Ecs::GetNode(CORE_NS::Entity ent)
303 {
304 return nodeSystem->GetNode(ent);
305 }
GetNode(CORE_NS::Entity ent) const306 const CORE3D_NS::ISceneNode* Ecs::GetNode(CORE_NS::Entity ent) const
307 {
308 return nodeSystem->GetNode(ent);
309 }
310
GetRenderHandleEntity(const RENDER_NS::RenderHandleReference & handle)311 CORE_NS::EntityReference Ecs::GetRenderHandleEntity(const RENDER_NS::RenderHandleReference& handle)
312 {
313 CORE_NS::EntityReference ent;
314 if (handle && rhComponentManager) {
315 ent = CORE3D_NS::GetOrCreateEntityReference(ecs->GetEntityManager(), *rhComponentManager, handle);
316 }
317 return ent;
318 }
319
AddDefaultComponents(CORE_NS::Entity ent) const320 void Ecs::AddDefaultComponents(CORE_NS::Entity ent) const
321 {
322 auto create = [&](auto* component) {
323 if (component) {
324 if (!component->HasComponent(ent)) {
325 component->Create(ent);
326 }
327 }
328 };
329 create(nameComponentManager);
330 create(nodeComponentManager);
331 create(transformComponentManager);
332 create(localMatrixComponentManager);
333 create(worldMatrixComponentManager);
334 }
335
ListenNodeChanges(bool enabled)336 void Ecs::ListenNodeChanges(bool enabled)
337 {
338 if (enabled) {
339 nodeSystem->AddListener(*this);
340 } else {
341 nodeSystem->RemoveListener(*this);
342 }
343 }
344
OnChildChanged(const CORE3D_NS::ISceneNode & parent,CORE3D_NS::INodeSystem::SceneNodeListener::EventType type,const CORE3D_NS::ISceneNode & child,size_t index)345 void Ecs::OnChildChanged(const CORE3D_NS::ISceneNode& parent, CORE3D_NS::INodeSystem::SceneNodeListener::EventType type,
346 const CORE3D_NS::ISceneNode& child, size_t index)
347 {
348 if (auto i = interface_pointer_cast<IOnNodeChanged>(scene_)) {
349 META_NS::ContainerChangeType cchange {};
350 if (type == CORE3D_NS::INodeSystem::SceneNodeListener::EventType::ADDED) {
351 cchange = META_NS::ContainerChangeType::ADDED;
352 } else if (type == CORE3D_NS::INodeSystem::SceneNodeListener::EventType::REMOVED) {
353 cchange = META_NS::ContainerChangeType::REMOVED;
354 } else {
355 // invalid event
356 return;
357 }
358 i->OnChildChanged(cchange, parent.GetEntity(), child.GetEntity(), index);
359 }
360 }
361
CheckDeactivatedAncestry(CORE_NS::Entity start,CORE_NS::Entity node,std::set<CORE_NS::Entity> & entities) const362 bool Ecs::CheckDeactivatedAncestry(
363 CORE_NS::Entity start, CORE_NS::Entity node, std::set<CORE_NS::Entity>& entities) const
364 {
365 if (start == node) {
366 return true;
367 }
368 if (CORE_NS::EntityUtil::IsValid(node)) {
369 if (auto n = nodeComponentManager->Read(node)) {
370 auto ret = CheckDeactivatedAncestry(start, n->parent, entities);
371 if (ret) {
372 entities.insert(node);
373 }
374 return ret;
375 }
376 }
377 return false;
378 }
379
GetDeactivatedChildren(CORE_NS::Entity ent) const380 std::set<CORE_NS::Entity> Ecs::GetDeactivatedChildren(CORE_NS::Entity ent) const
381 {
382 std::set<CORE_NS::Entity> entities;
383
384 if (nodeComponentManager->HasComponent(ent)) {
385 auto& entMan = ecs->GetEntityManager();
386 auto it = entMan.Begin(CORE_NS::IEntityManager::IteratorType::DEACTIVATED);
387 auto end = entMan.End(CORE_NS::IEntityManager::IteratorType::DEACTIVATED);
388
389 BASE_NS::vector<CORE_NS::Entity> nodes;
390 for (; it && !it->Compare(end); it->Next()) {
391 auto e = it->Get();
392 if (nodeComponentManager->HasComponent(e)) {
393 nodes.push_back(e);
394 }
395 }
396 for (auto&& n : nodes) {
397 CheckDeactivatedAncestry(ent, n, entities);
398 }
399 }
400 return entities;
401 }
402
ReactivateNodes(CORE_NS::Entity ent)403 void Ecs::ReactivateNodes(CORE_NS::Entity ent)
404 {
405 auto& entMan = ecs->GetEntityManager();
406
407 std::set<CORE_NS::Entity> reactivate = GetDeactivatedChildren(ent);
408 reactivate.insert(ent);
409
410 for (auto&& n : reactivate) {
411 entMan.SetActive(n, true);
412 }
413 }
414
SetNodesActive(CORE_NS::Entity ent,bool enabled)415 void Ecs::SetNodesActive(CORE_NS::Entity ent, bool enabled)
416 {
417 if (!enabled) {
418 auto decents = GetNodeDescendants(ent);
419 for (auto&& ent : decents) {
420 ecs->GetEntityManager().SetActive(ent, false);
421 }
422 } else {
423 ReactivateNodes(ent);
424 }
425 }
426
GetNodeDescendants(CORE_NS::Entity ent,BASE_NS::vector<CORE_NS::Entity> & entities) const427 void Ecs::GetNodeDescendants(CORE_NS::Entity ent, BASE_NS::vector<CORE_NS::Entity>& entities) const
428 {
429 auto& entMan = ecs->GetEntityManager();
430 if (entMan.IsAlive(ent)) {
431 if (auto n = GetNode(ent)) {
432 for (auto&& c : n->GetChildren()) {
433 GetNodeDescendants(c->GetEntity(), entities);
434 }
435 }
436 } else {
437 for (auto&& e : GetDeactivatedChildren(ent)) {
438 entities.push_back(e);
439 }
440 }
441 entities.push_back(ent);
442 }
443
GetNodeDescendants(CORE_NS::Entity ent) const444 BASE_NS::vector<CORE_NS::Entity> Ecs::GetNodeDescendants(CORE_NS::Entity ent) const
445 {
446 BASE_NS::vector<CORE_NS::Entity> entities;
447 GetNodeDescendants(ent, entities);
448 return entities;
449 }
450
CopyExternalAsChild(const IEcsObject & parent,const IEcsObject & extChild)451 CORE_NS::Entity CopyExternalAsChild(const IEcsObject& parent, const IEcsObject& extChild)
452 {
453 IInternalScene::Ptr localScene = parent.GetScene();
454 IInternalScene::Ptr extScene = extChild.GetScene();
455 if (!localScene || !extScene) {
456 return {};
457 }
458
459 auto& util = localScene->GetGraphicsContext().GetSceneUtil();
460
461 auto ent = util.Clone(*localScene->GetEcsContext().GetNativeEcs(), parent.GetEntity(),
462 *extScene->GetEcsContext().GetNativeEcs(), extChild.GetEntity());
463
464 if (CORE_NS::EntityUtil::IsValid(ent)) {
465 if (auto i = interface_pointer_cast<IOnNodeChanged>(localScene)) {
466 size_t index(-1);
467 if (auto nodeSystem =
468 CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(*localScene->GetEcsContext().GetNativeEcs())) {
469 if (auto parentNode = nodeSystem->GetNode(parent.GetEntity())) {
470 auto children = parentNode->GetChildren();
471 for (auto childIndex = 0; childIndex < children.size(); ++childIndex) {
472 if (children[childIndex]->GetEntity() == ent) {
473 index = childIndex;
474 break;
475 }
476 }
477 }
478 } else {
479 CORE_LOG_W("Failed to resolve imported child index, NodeSystem not found");
480 }
481
482 i->OnChildChanged(META_NS::ContainerChangeType::ADDED, parent.GetEntity(), ent, index);
483 }
484 }
485
486 return ent;
487 }
488
ReparentOldRoot(IInternalScene::Ptr scene,const IEcsObject & parent,const BASE_NS::vector<CORE_NS::Entity> & entities)489 static CORE_NS::Entity ReparentOldRoot(
490 IInternalScene::Ptr scene, const IEcsObject& parent, const BASE_NS::vector<CORE_NS::Entity>& entities)
491 {
492 auto nodeSystem = CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(*scene->GetEcsContext().GetNativeEcs());
493 if (!nodeSystem) {
494 return {};
495 }
496 auto& root = nodeSystem->GetRootNode();
497 CORE3D_NS::ISceneNode* node = nullptr;
498 for (auto&& v : root.GetChildren()) {
499 if (std::find(entities.begin(), entities.end(), v->GetEntity()) != entities.end()) {
500 node = v;
501 break;
502 }
503 }
504 if (node) {
505 if (auto parentNode = nodeSystem->GetNode(parent.GetEntity())) {
506 parentNode->AddChild(*node);
507 } else {
508 CORE_LOG_W("Invalid parent when import scene");
509 }
510 } else {
511 CORE_LOG_W("Failed to find old root when import scene");
512 }
513 return node ? node->GetEntity() : CORE_NS::Entity {};
514 }
515
CopyExternalAsChild(const IEcsObject & parent,const IScene & scene,BASE_NS::vector<CORE_NS::Entity> & imported)516 CORE_NS::Entity CopyExternalAsChild(
517 const IEcsObject& parent, const IScene& scene, BASE_NS::vector<CORE_NS::Entity>& imported)
518 {
519 IInternalScene::Ptr localScene = parent.GetScene();
520 IInternalScene::Ptr extScene = scene.GetInternalScene();
521 if (!localScene || !extScene) {
522 return {};
523 }
524
525 auto& util = localScene->GetGraphicsContext().GetSceneUtil();
526 imported = util.Clone(*localScene->GetEcsContext().GetNativeEcs(), *extScene->GetEcsContext().GetNativeEcs());
527 return ReparentOldRoot(localScene, parent, imported);
528 }
529
530 SCENE_END_NAMESPACE()
531