• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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