• 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 
29 #include "internal_scene.h"
30 
SCENE_BEGIN_NAMESPACE()31 SCENE_BEGIN_NAMESPACE()
32 
33 static bool SetPreprocesor(CORE3D_NS::IRenderPreprocessorSystem& system, BASE_NS::string_view tag)
34 {
35     BASE_NS::string dataStorePrefix = "renderDataStore: " + tag;
36 
37     auto sceneDataStore = dataStorePrefix + "-RenderDataStoreDefaultScene";
38     auto cameraDataStore = dataStorePrefix + "-RenderDataStoreDefaultCamera";
39     auto lightDataStore = dataStorePrefix + "-RenderDataStoreDefaultLight";
40     auto materialDataStore = dataStorePrefix + "-RenderDataStoreDefaultMaterial";
41     auto morphDataStore = dataStorePrefix + "-RenderDataStoreMorph";
42 
43     if (auto prop = system.GetProperties()) {
44         {
45             CORE_NS::ScopedHandle<CORE3D_NS::IRenderPreprocessorSystem::Properties> p(prop);
46             p->dataStorePrefix = dataStorePrefix;
47             p->dataStoreScene = sceneDataStore;
48             p->dataStoreCamera = cameraDataStore;
49             p->dataStoreLight = lightDataStore;
50             p->dataStoreMaterial = materialDataStore;
51             p->dataStoreMorph = morphDataStore;
52         }
53         system.SetProperties(*prop);
54         return true;
55     }
56     return false;
57 }
58 
InitPreprocesor(const CORE_NS::IEcs & ecs,RENDER_NS::IRenderContext & context)59 static bool InitPreprocesor(const CORE_NS::IEcs& ecs, RENDER_NS::IRenderContext& context)
60 {
61     auto system = CORE_NS::GetSystem<CORE3D_NS::IRenderPreprocessorSystem>(ecs);
62     if (system) {
63         std::random_device rd;
64         std::mt19937_64 gen(rd());
65         return SetPreprocesor(*system,
66             BASE_NS::string(BASE_NS::to_string(uintptr_t(&ecs))) + "_" + BASE_NS::string(BASE_NS::to_string(gen())));
67     }
68     return false;
69 }
70 
71 template<typename Manager>
GetCoreManager()72 Manager* Ecs::GetCoreManager()
73 {
74     auto m = CORE_NS::GetManager<Manager>(*ecs);
75     if (m) {
76         components_[m->GetName()] = m;
77     }
78     return m;
79 }
80 
Initialize(const BASE_NS::shared_ptr<IInternalScene> & scene)81 bool Ecs::Initialize(const BASE_NS::shared_ptr<IInternalScene>& scene)
82 {
83     using namespace CORE_NS;
84     if (!scene) {
85         CORE_LOG_E("invalid scene");
86         return false;
87     }
88     scene_ = scene;
89     auto& context = scene->GetRenderContext();
90     auto& engine = context.GetEngine();
91 
92     ecs = engine.CreateEcs();
93     ecs->SetRenderMode(CORE_NS::IEcs::RENDER_ALWAYS);
94 
95     auto* factory = GetInstance<ISystemGraphLoaderFactory>(UID_SYSTEM_GRAPH_LOADER);
96     auto systemGraphLoader = factory->Create(engine.GetFileManager());
97     // Use default graph.
98     systemGraphLoader->Load(scene->GetSystemGraphUri().c_str(), *ecs);
99 
100     InitPreprocesor(*ecs, context);
101     ecs->Initialize();
102 
103     animationComponentManager = GetCoreManager<CORE3D_NS::IAnimationComponentManager>();
104     animationStateComponentManager = GetCoreManager<CORE3D_NS::IAnimationStateComponentManager>();
105     cameraComponentManager = GetCoreManager<CORE3D_NS::ICameraComponentManager>();
106     envComponentManager = GetCoreManager<CORE3D_NS::IEnvironmentComponentManager>();
107     layerComponentManager = GetCoreManager<CORE3D_NS::ILayerComponentManager>();
108     lightComponentManager = GetCoreManager<CORE3D_NS::ILightComponentManager>();
109     materialComponentManager = GetCoreManager<CORE3D_NS::IMaterialComponentManager>();
110     meshComponentManager = GetCoreManager<CORE3D_NS::IMeshComponentManager>();
111     nameComponentManager = GetCoreManager<CORE3D_NS::INameComponentManager>();
112     nodeComponentManager = GetCoreManager<CORE3D_NS::INodeComponentManager>();
113     renderMeshComponentManager = GetCoreManager<CORE3D_NS::IRenderMeshComponentManager>();
114     rhComponentManager = GetCoreManager<CORE3D_NS::IRenderHandleComponentManager>();
115     transformComponentManager = GetCoreManager<CORE3D_NS::ITransformComponentManager>();
116     uriComponentManager = GetCoreManager<CORE3D_NS::IUriComponentManager>();
117     renderConfigComponentManager = GetCoreManager<CORE3D_NS::IRenderConfigurationComponentManager>();
118     postProcessComponentManager = GetCoreManager<CORE3D_NS::IPostProcessComponentManager>();
119     localMatrixComponentManager = GetCoreManager<CORE3D_NS::ILocalMatrixComponentManager>();
120     worldMatrixComponentManager = GetCoreManager<CORE3D_NS::IWorldMatrixComponentManager>();
121     textComponentManager = GetCoreManager<TEXT3D_NS::ITextComponentManager>();
122     if (animationComponentManager) {
123         animationQuery.reset(new CORE_NS::ComponentQuery());
124         animationQuery->SetEcsListenersEnabled(true);
125         const ComponentQuery::Operation operations[] = {
126             {
127                 *nodeComponentManager, ComponentQuery::Operation::OPTIONAL
128             },
129             {
130                 *nameComponentManager, ComponentQuery::Operation::OPTIONAL
131             }
132         };
133         animationQuery->SetupQuery(*animationComponentManager, operations);
134     }
135 
136     if (meshComponentManager) {
137         meshQuery.reset(new CORE_NS::ComponentQuery());
138         meshQuery->SetEcsListenersEnabled(true);
139         const ComponentQuery::Operation operations[] = {
140             {
141                 *nodeComponentManager, ComponentQuery::Operation::OPTIONAL
142             },
143             {
144                 *nameComponentManager, ComponentQuery::Operation::OPTIONAL
145             }
146         };
147         meshQuery->SetupQuery(*meshComponentManager, operations);
148     }
149 
150     if (materialComponentManager) {
151         materialQuery.reset(new CORE_NS::ComponentQuery());
152         materialQuery->SetEcsListenersEnabled(true);
153         const ComponentQuery::Operation operations[] = {
154             {
155                 *nodeComponentManager, ComponentQuery::Operation::OPTIONAL
156             },
157             {
158                 *nameComponentManager, ComponentQuery::Operation::OPTIONAL
159             },
160             {
161                 *uriComponentManager, ComponentQuery::Operation::OPTIONAL
162             }
163         };
164         materialQuery->SetupQuery(*materialComponentManager, operations);
165     }
166     nodeSystem = GetSystem<CORE3D_NS::INodeSystem>(*ecs);
167     picking = GetInstance<CORE3D_NS::IPicking>(*context.GetInterface<IClassRegister>(), CORE3D_NS::UID_PICKING);
168 
169     entityOwnerComponentManager =
170         static_cast<IEntityOwnerComponentManager*>(ecs->CreateComponentManager(ENTITY_OWNER_COMPONENT_TYPE_INFO));
171     if (!entityOwnerComponentManager) {
172         return false;
173     }
174     components_[entityOwnerComponentManager->GetName()] = entityOwnerComponentManager;
175 
176     if (!EcsListener::Initialize(*this)) {
177         CORE_LOG_E("failed to initialize ecs listener");
178         return false;
179     }
180 
181     return true;
182 }
183 
Uninitialize()184 void Ecs::Uninitialize()
185 {
186     EcsListener::Uninitialize();
187     animationComponentManager = {};
188     cameraComponentManager = {};
189     envComponentManager = {};
190     layerComponentManager = {};
191     lightComponentManager = {};
192     materialComponentManager = {};
193     meshComponentManager = {};
194     nameComponentManager = {};
195     nodeComponentManager = {};
196     renderMeshComponentManager = {};
197     rhComponentManager = {};
198     transformComponentManager = {};
199     uriComponentManager = {};
200     renderConfigComponentManager = {};
201     meshQuery.reset();
202     materialQuery.reset();
203     animationQuery.reset();
204     rootNode_ = {};
205     nodeSystem = {};
206     picking = {};
207     components_.clear();
208     if (ecs) {
209         ecs->Uninitialize();
210         ecs.reset();
211     }
212 }
213 
FindComponent(BASE_NS::string_view name) const214 CORE_NS::IComponentManager* Ecs::FindComponent(BASE_NS::string_view name) const
215 {
216     auto it = components_.find(name);
217     return it != components_.end() ? it->second : nullptr;
218 }
219 
FindNode(BASE_NS::string_view path) const220 const CORE3D_NS::ISceneNode* Ecs::FindNode(BASE_NS::string_view path) const
221 {
222     if (path.empty() || path == "/") {
223         return rootNode_;
224     }
225     const CORE3D_NS::ISceneNode* node = &nodeSystem->GetRootNode();
226     BASE_NS::string_view p = FirstSegment(path);
227     while (node && !path.empty()) {
228         node = node->GetChild(p);
229         path.remove_prefix(p.size() + 1);
230         p = FirstSegment(path);
231     }
232     return node;
233 }
234 
FindNodeParent(BASE_NS::string_view path) const235 const CORE3D_NS::ISceneNode* Ecs::FindNodeParent(BASE_NS::string_view path) const
236 {
237     return FindNode(NormalisePath(ParentPath(path)));
238 }
239 
GetPath(const CORE3D_NS::ISceneNode * node) const240 BASE_NS::string Ecs::GetPath(const CORE3D_NS::ISceneNode* node) const
241 {
242     BASE_NS::string path;
243     while (node && node->GetParent()) {
244         path = "/" + node->GetName() + path;
245         node = node->GetParent();
246     }
247     return path;
248 }
249 
GetPath(CORE_NS::Entity ent) const250 BASE_NS::string Ecs::GetPath(CORE_NS::Entity ent) const
251 {
252     return GetPath(nodeSystem->GetNode(ent));
253 }
254 
IsNodeEntity(CORE_NS::Entity ent) const255 bool Ecs::IsNodeEntity(CORE_NS::Entity ent) const
256 {
257     return nodeSystem->GetNode(ent) != nullptr;
258 }
259 
GetRootEntity() const260 CORE_NS::Entity Ecs::GetRootEntity() const
261 {
262     return rootNode_ ? rootNode_->GetEntity() : CORE_NS::Entity {};
263 }
264 
GetEcsObject(CORE_NS::Entity ent)265 IEcsObject::Ptr Ecs::GetEcsObject(CORE_NS::Entity ent)
266 {
267     if (auto obj = FindEcsObject(ent)) {
268         return obj;
269     }
270 
271     auto& r = META_NS::GetObjectRegistry();
272     auto md = r.Create<META_NS::IMetadata>(META_NS::ClassId::Object);
273     md->AddProperty(META_NS::ConstructProperty<IInternalScene::Ptr>("Scene", scene_.lock()));
274     md->AddProperty(META_NS::ConstructProperty<CORE_NS::Entity>("Entity", ent));
275     auto obj = r.Create<IEcsObject>(ClassId::EcsObject, md);
276     if (obj) {
277         RegisterEcsObject(obj);
278     }
279 
280     return obj;
281 }
282 
RemoveEcsObject(const IEcsObject::ConstPtr & obj)283 void Ecs::RemoveEcsObject(const IEcsObject::ConstPtr& obj)
284 {
285     DeregisterEcsObject(obj);
286 }
287 
RemoveEntity(CORE_NS::Entity ent)288 bool Ecs::RemoveEntity(CORE_NS::Entity ent)
289 {
290     bool res = CORE_NS::EntityUtil::IsValid(ent);
291     if (res) {
292         DeregisterEcsObject(ent);
293         ecs->GetEntityManager().Destroy(ent);
294     }
295     return res;
296 }
297 
CreateUnnamedRootNode()298 bool Ecs::CreateUnnamedRootNode()
299 {
300     if (rootNode_) {
301         return false;
302     }
303     rootNode_ = nodeSystem->CreateNode();
304     for (auto&& c : nodeSystem->GetRootNode().GetChildren()) {
305         if (c != rootNode_) {
306             c->SetParent(*rootNode_);
307         }
308     }
309     rootNode_->SetParent(nodeSystem->GetRootNode());
310     AddDefaultComponents(rootNode_->GetEntity());
311     return true;
312 }
313 
SetNodeParentAndName(CORE_NS::Entity ent,BASE_NS::string_view name,const CORE3D_NS::ISceneNode * parent)314 bool Ecs::SetNodeParentAndName(CORE_NS::Entity ent, BASE_NS::string_view name, const CORE3D_NS::ISceneNode* parent)
315 {
316     auto n = nodeSystem->GetNode(ent);
317     if (n) {
318         if (parent) {
319             n->SetParent(*parent);
320         }
321         n->SetName(name);
322     }
323     return n != nullptr;
324 }
325 
GetNode(CORE_NS::Entity ent)326 CORE3D_NS::ISceneNode* Ecs::GetNode(CORE_NS::Entity ent)
327 {
328     return nodeSystem->GetNode(ent);
329 }
GetNode(CORE_NS::Entity ent) const330 const CORE3D_NS::ISceneNode* Ecs::GetNode(CORE_NS::Entity ent) const
331 {
332     return nodeSystem->GetNode(ent);
333 }
334 
GetEntityReference(CORE_NS::Entity ent)335 CORE_NS::EntityReference Ecs::GetEntityReference(CORE_NS::Entity ent)
336 {
337     return ecs->GetEntityManager().GetReferenceCounted(ent);
338 }
339 
AddDefaultComponents(CORE_NS::Entity ent) const340 void Ecs::AddDefaultComponents(CORE_NS::Entity ent) const
341 {
342     auto create = [&](auto* component) {
343         if (component) {
344             if (!component->HasComponent(ent)) {
345                 component->Create(ent);
346             }
347         }
348     };
349     create(nameComponentManager);
350     create(nodeComponentManager);
351     create(transformComponentManager);
352     create(localMatrixComponentManager);
353     create(worldMatrixComponentManager);
354 }
355 
CopyExternalAsChild(const IEcsObject & parent,const IEcsObject & extChild)356 CORE_NS::Entity CopyExternalAsChild(const IEcsObject& parent, const IEcsObject& extChild)
357 {
358     IInternalScene::Ptr localScene = parent.GetScene();
359     IInternalScene::Ptr extScene = extChild.GetScene();
360     if (!localScene || !extScene) {
361         return {};
362     }
363 
364     auto& util = localScene->GetGraphicsContext().GetSceneUtil();
365 
366     auto ent = util.Clone(*localScene->GetEcsContext().GetNativeEcs(), parent.GetEntity(),
367         *extScene->GetEcsContext().GetNativeEcs(), extChild.GetEntity());
368 
369     return ent;
370 }
371 
ReparentOldRoot(IInternalScene::Ptr scene,const IEcsObject & parent,const BASE_NS::vector<CORE_NS::Entity> & entities)372 static CORE_NS::Entity ReparentOldRoot(
373     IInternalScene::Ptr scene, const IEcsObject& parent, const BASE_NS::vector<CORE_NS::Entity>& entities)
374 {
375     auto nodeSystem = CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(*scene->GetEcsContext().GetNativeEcs());
376     if (!nodeSystem) {
377         return {};
378     }
379     auto& root = nodeSystem->GetRootNode();
380     CORE3D_NS::ISceneNode* node = nullptr;
381     for (auto&& v : root.GetChildren()) {
382         if (std::find(entities.begin(), entities.end(), v->GetEntity()) != entities.end()) {
383             node = v;
384             break;
385         }
386     }
387     if (node) {
388         if (auto parentNode = nodeSystem->GetNode(parent.GetEntity())) {
389             node->SetParent(*parentNode);
390         } else {
391             CORE_LOG_W("Invalid parent when import scene");
392         }
393     } else {
394         CORE_LOG_W("Failed to find old root when import scene");
395     }
396     return node->GetEntity();
397 }
398 
CopyExternalAsChild(const IEcsObject & parent,const IScene & scene)399 CORE_NS::Entity CopyExternalAsChild(const IEcsObject& parent, const IScene& scene)
400 {
401     IInternalScene::Ptr localScene = parent.GetScene();
402     IInternalScene::Ptr extScene = scene.GetInternalScene();
403     if (!localScene || !extScene) {
404         return {};
405     }
406 
407     auto& util = localScene->GetGraphicsContext().GetSceneUtil();
408     auto vec = util.Clone(*localScene->GetEcsContext().GetNativeEcs(), *extScene->GetEcsContext().GetNativeEcs());
409     return ReparentOldRoot(localScene, parent, vec);
410 }
411 
412 SCENE_END_NAMESPACE()
413