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