• 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_object.h"
17 
18 #include <scene/ext/intf_ecs_context.h>
19 #include <scene/ext/util.h>
20 
21 #include <3d/ecs/components/name_component.h>
22 #include <core/property_tools/property_data.h>
23 
24 #include <meta/api/engine/util.h>
25 #include <meta/api/make_callback.h>
26 
SCENE_BEGIN_NAMESPACE()27 SCENE_BEGIN_NAMESPACE()
28 
29 bool EcsObject::Build(const META_NS::IMetadata::Ptr& d)
30 {
31     if (Super::Build(d)) {
32         auto s = GetInterfaceBuildArg<IInternalScene>(d, "Scene");
33         auto ent = GetBuildArg<CORE_NS::Entity>(d, "Entity");
34 
35         if (s && CORE_NS::EntityUtil::IsValid(ent)) {
36             valueManager_ =
37                 META_NS::GetObjectRegistry().Create<META_NS::IEngineValueManager>(META_NS::ClassId::EngineValueManager);
38             valueManager_->SetNotificationQueue(s->GetAppTaskQueue());
39             scene_ = s;
40             entity_ = ent;
41 
42             if (auto m = static_cast<CORE3D_NS::INameComponentManager*>(
43                     s->GetEcsContext().FindComponent<CORE3D_NS::NameComponent>())) {
44                 if (auto s = m->Read(entity_)) {
45                     name_ = s->name;
46                 }
47             }
48         }
49     }
50     return valueManager_ != nullptr && CORE_NS::EntityUtil::IsValid(entity_);
51 }
52 
GetName() const53 BASE_NS::string EcsObject::GetName() const
54 {
55     std::shared_lock lock { mutex_ };
56     return name_;
57 }
58 
SetName(const BASE_NS::string & name)59 bool EcsObject::SetName(const BASE_NS::string& name)
60 {
61     if (auto s = GetScene()) {
62         if (auto m = static_cast<CORE3D_NS::INameComponentManager*>(
63                 s->GetEcsContext().FindComponent<CORE3D_NS::NameComponent>())) {
64             if (auto s = m->Write(entity_)) {
65                 s->name = name;
66 
67                 std::unique_lock lock { mutex_ };
68                 name_ = name;
69 
70                 return true;
71             }
72         }
73     }
74     return false;
75 }
76 
GetPath() const77 BASE_NS::string EcsObject::GetPath() const
78 {
79     if (auto s = GetScene()) {
80         return s->GetEcsContext().GetPath(entity_);
81     }
82     return "";
83 }
84 
GetScene() const85 IInternalScene::Ptr EcsObject::GetScene() const
86 {
87     return scene_.lock();
88 }
89 
GetEntity() const90 CORE_NS::Entity EcsObject::GetEntity() const
91 {
92     return entity_;
93 }
94 
GetEngineValueManager()95 META_NS::IEngineValueManager::Ptr EcsObject::GetEngineValueManager()
96 {
97     return valueManager_;
98 }
99 
AddEngineProperty(META_NS::IMetadata & object,const META_NS::IEngineValue::Ptr & v)100 bool EcsObject::AddEngineProperty(META_NS::IMetadata& object, const META_NS::IEngineValue::Ptr& v)
101 {
102     auto prop = object.GetProperty(v->GetName());
103     if (prop) {
104         META_NS::SetEngineValueToProperty(prop, v);
105     } else {
106         prop = valueManager_->ConstructProperty(v->GetName());
107         if (prop) {
108             object.AddProperty(prop);
109         } else {
110             CORE_LOG_E("Failed to add %s", v->GetName().c_str());
111             return false;
112         }
113     }
114     if (prop) {
115         prop->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this] {
116             if (auto scene = scene_.lock()) {
117                 scene->SchedulePropertyUpdate(GetSelf<IEcsObject>());
118             }
119         }));
120     }
121     return true;
122 }
123 
AddAllProperties(META_NS::IMetadata & object,CORE_NS::IComponentManager * m)124 void EcsObject::AddAllProperties(META_NS::IMetadata& object, CORE_NS::IComponentManager* m)
125 {
126     BASE_NS::string name { m->GetName() };
127     BASE_NS::vector<META_NS::IEngineValue::Ptr> values;
128     META_NS::AddEngineValuesRecursively(
129         valueManager_, META_NS::EnginePropertyHandle { m, entity_ }, META_NS::EngineValueOptions { name, &values });
130     for (auto&& v : values) {
131         AddEngineProperty(object, v);
132     }
133 }
134 
AddAllComponentProperties(META_NS::IMetadata & object)135 void EcsObject::AddAllComponentProperties(META_NS::IMetadata& object)
136 {
137     BASE_NS::vector<CORE_NS::IComponentManager*> managers;
138     if (auto s = GetScene()) {
139         s->GetEcsContext().GetNativeEcs()->GetComponents(entity_, managers);
140         for (auto m : managers) {
141             AddAllProperties(object, m);
142         }
143     }
144 }
145 
AddAllEngineProperties(const META_NS::IMetadata::Ptr & object,BASE_NS::string_view cv)146 Future<bool> EcsObject::AddAllEngineProperties(const META_NS::IMetadata::Ptr& object, BASE_NS::string_view cv)
147 {
148     if (auto scene = scene_.lock()) {
149         return scene->AddTask([=, me = BASE_NS::weak_ptr(GetSelf()), component = BASE_NS::string(cv)] {
150             if (auto self = me.lock()) {
151                 if (component.empty()) {
152                     AddAllComponentProperties(*object);
153                     return true;
154                 }
155                 if (auto s = GetScene()) {
156                     if (auto m = s->GetEcsContext().FindComponent(ComponentName(component))) {
157                         AddAllProperties(*object, m);
158                         return true;
159                     }
160                 }
161             }
162             return false;
163         });
164     }
165     return {};
166 }
167 
AttachEnginePropertyImpl(META_NS::EnginePropertyHandle handle,const BASE_NS::string & component,const META_NS::IProperty::Ptr & p,BASE_NS::string_view path)168 bool EcsObject::AttachEnginePropertyImpl(META_NS::EnginePropertyHandle handle, const BASE_NS::string& component,
169     const META_NS::IProperty::Ptr& p, BASE_NS::string_view path)
170 {
171     BASE_NS::vector<META_NS::IEngineValue::Ptr> values;
172     if (valueManager_->ConstructValue(
173         handle, FullPropertyName(path), META_NS::EngineValueOptions { component, &values })) {
174         if (!values.empty()) {
175             auto ret = META_NS::SetEngineValueToProperty(p, values.front());
176             if (ret) {
177                 p->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this] {
178                     if (auto scene = scene_.lock()) {
179                         scene->SchedulePropertyUpdate(GetSelf<IEcsObject>());
180                     }
181                 }));
182             }
183             return ret;
184         }
185         // this most likely means we don't have registered access type for the property, lets continue anyhow for now
186         return true;
187     }
188     return false;
189 }
190 
GetPropertyHandle(BASE_NS::string_view component) const191 META_NS::EnginePropertyHandle EcsObject::GetPropertyHandle(BASE_NS::string_view component) const
192 {
193     if (auto s = GetScene()) {
194         if (auto m = s->GetEcsContext().FindComponent(component)) {
195             return { m, entity_ };
196         }
197     }
198     return {};
199 }
200 
AttachEngineProperty(const META_NS::IProperty::Ptr & p,BASE_NS::string_view pv)201 Future<bool> EcsObject::AttachEngineProperty(const META_NS::IProperty::Ptr& p, BASE_NS::string_view pv)
202 {
203     if (auto scene = scene_.lock()) {
204         return scene->AddTask([=, me = BASE_NS::weak_ptr(GetSelf()), path = BASE_NS::string(pv)] {
205             if (auto self = me.lock()) {
206                 auto component = ComponentName(path);
207                 if (auto handle = GetPropertyHandle(component)) {
208                     return AttachEnginePropertyImpl(handle, BASE_NS::string(component), p, path);
209                 }
210             }
211             return false;
212         });
213     }
214     return {};
215 }
216 
CreateEngineProperty(BASE_NS::string_view pv)217 Future<META_NS::IProperty::Ptr> EcsObject::CreateEngineProperty(BASE_NS::string_view pv)
218 {
219     if (auto scene = scene_.lock()) {
220         return scene->AddTask([=, me = BASE_NS::weak_ptr(GetSelf()), path = BASE_NS::string(pv)] {
221             if (auto self = me.lock()) {
222                 auto component = ComponentName(path);
223                 if (auto handle = GetPropertyHandle(component)) {
224                     auto name = FullPropertyName(path);
225                     if (valueManager_->ConstructValue(
226                         handle, name, META_NS::EngineValueOptions { BASE_NS::string(component) })) {
227                         if (auto p = valueManager_->ConstructProperty(path)) {
228                             p->OnChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([this] {
229                                 if (auto scene = scene_.lock()) {
230                                     scene->SchedulePropertyUpdate(GetSelf<IEcsObject>());
231                                 }
232                             }));
233                             return p;
234                         }
235                     }
236                 }
237             }
238             return META_NS::IProperty::Ptr {};
239         });
240     }
241     return {};
242 }
243 
SyncProperties()244 void EcsObject::SyncProperties()
245 {
246     valueManager_->Sync(META_NS::EngineSyncDirection::TO_ENGINE);
247 }
248 
OnEntityEvent(CORE_NS::IEcs::EntityListener::EventType type)249 void EcsObject::OnEntityEvent(CORE_NS::IEcs::EntityListener::EventType type)
250 {
251     if (type == CORE_NS::IEcs::EntityListener::EventType::CREATED) {
252     }
253     if (type == CORE_NS::IEcs::EntityListener::EventType::DESTROYED) {
254         valueManager_->RemoveAll();
255     }
256 }
257 
OnComponentEvent(CORE_NS::IEcs::ComponentListener::EventType type,const CORE_NS::IComponentManager & component)258 void EcsObject::OnComponentEvent(
259     CORE_NS::IEcs::ComponentListener::EventType type, const CORE_NS::IComponentManager& component)
260 {
261     if (type == CORE_NS::IEcs::ComponentListener::EventType::MODIFIED) {
262         valueManager_->Sync(META_NS::EngineSyncDirection::AUTO);
263     }
264 }
265 
266 SCENE_END_NAMESPACE()
267