18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#include "entity_collection.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <cinttypes> 198bf80f4bSopenharmony_ci#include <PropertyTools/property_data.h> 208bf80f4bSopenharmony_ci 218bf80f4bSopenharmony_ci#include <base/containers/fixed_string.h> 228bf80f4bSopenharmony_ci#include <core/ecs/intf_entity_manager.h> 238bf80f4bSopenharmony_ci#include <core/log.h> 248bf80f4bSopenharmony_ci#include <core/property/intf_property_api.h> 258bf80f4bSopenharmony_ci 268bf80f4bSopenharmony_ci#include "ecs_util.h" 278bf80f4bSopenharmony_ci 288bf80f4bSopenharmony_ciusing namespace BASE_NS; 298bf80f4bSopenharmony_ciusing namespace CORE_NS; 308bf80f4bSopenharmony_ci 318bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE() 328bf80f4bSopenharmony_ci 338bf80f4bSopenharmony_ciEntityCollection::EntityCollection(IEcs& ecs, string_view uri, string_view contextUri) 348bf80f4bSopenharmony_ci : ecs_(ecs), uri_(uri), contextUri_(contextUri) 358bf80f4bSopenharmony_ci{} 368bf80f4bSopenharmony_ci 378bf80f4bSopenharmony_civoid EntityCollection::AddListener(IEntityCollection::IListener& listener) 388bf80f4bSopenharmony_ci{ 398bf80f4bSopenharmony_ci BASE_ASSERT(&listener); 408bf80f4bSopenharmony_ci listeners_.emplace_back(&listener); 418bf80f4bSopenharmony_ci} 428bf80f4bSopenharmony_ci 438bf80f4bSopenharmony_civoid EntityCollection::RemoveListener(IEntityCollection::IListener& listener) 448bf80f4bSopenharmony_ci{ 458bf80f4bSopenharmony_ci BASE_ASSERT(&listener); 468bf80f4bSopenharmony_ci for (size_t i = 0; i < listeners_.size(); ++i) { 478bf80f4bSopenharmony_ci if (&listener == listeners_[i]) { 488bf80f4bSopenharmony_ci listeners_.erase(listeners_.begin() + i); 498bf80f4bSopenharmony_ci return; 508bf80f4bSopenharmony_ci } 518bf80f4bSopenharmony_ci } 528bf80f4bSopenharmony_ci 538bf80f4bSopenharmony_ci // trying to remove a non-existent listener. 548bf80f4bSopenharmony_ci BASE_ASSERT(true); 558bf80f4bSopenharmony_ci} 568bf80f4bSopenharmony_ci 578bf80f4bSopenharmony_ciIEcs& EntityCollection::GetEcs() const 588bf80f4bSopenharmony_ci{ 598bf80f4bSopenharmony_ci return ecs_; 608bf80f4bSopenharmony_ci} 618bf80f4bSopenharmony_ci 628bf80f4bSopenharmony_cistring EntityCollection::GetUri() const 638bf80f4bSopenharmony_ci{ 648bf80f4bSopenharmony_ci return uri_; 658bf80f4bSopenharmony_ci} 668bf80f4bSopenharmony_ci 678bf80f4bSopenharmony_civoid EntityCollection::SetUri(const BASE_NS::string& uri) 688bf80f4bSopenharmony_ci{ 698bf80f4bSopenharmony_ci uri_ = uri; 708bf80f4bSopenharmony_ci} 718bf80f4bSopenharmony_ci 728bf80f4bSopenharmony_cistring EntityCollection::GetContextUri() const 738bf80f4bSopenharmony_ci{ 748bf80f4bSopenharmony_ci return contextUri_; 758bf80f4bSopenharmony_ci} 768bf80f4bSopenharmony_ci 778bf80f4bSopenharmony_cistring EntityCollection::GetSrc() const 788bf80f4bSopenharmony_ci{ 798bf80f4bSopenharmony_ci return src_; 808bf80f4bSopenharmony_ci} 818bf80f4bSopenharmony_ci 828bf80f4bSopenharmony_civoid EntityCollection::SetSrc(string_view src) 838bf80f4bSopenharmony_ci{ 848bf80f4bSopenharmony_ci src_ = src; 858bf80f4bSopenharmony_ci MarkModified(true); 868bf80f4bSopenharmony_ci} 878bf80f4bSopenharmony_ci 888bf80f4bSopenharmony_cistring EntityCollection::GetType() const 898bf80f4bSopenharmony_ci{ 908bf80f4bSopenharmony_ci return type_; 918bf80f4bSopenharmony_ci} 928bf80f4bSopenharmony_ci 938bf80f4bSopenharmony_civoid EntityCollection::SetType(string_view type) 948bf80f4bSopenharmony_ci{ 958bf80f4bSopenharmony_ci type_ = type; 968bf80f4bSopenharmony_ci MarkModified(true); 978bf80f4bSopenharmony_ci} 988bf80f4bSopenharmony_ci 998bf80f4bSopenharmony_cisize_t EntityCollection::GetEntityCount() const 1008bf80f4bSopenharmony_ci{ 1018bf80f4bSopenharmony_ci return entities_.size(); 1028bf80f4bSopenharmony_ci} 1038bf80f4bSopenharmony_ci 1048bf80f4bSopenharmony_ciEntityReference EntityCollection::GetEntity(size_t collectionIndex) const 1058bf80f4bSopenharmony_ci{ 1068bf80f4bSopenharmony_ci BASE_ASSERT(collectionIndex < entities_.size()); 1078bf80f4bSopenharmony_ci if (collectionIndex >= entities_.size()) { 1088bf80f4bSopenharmony_ci return EntityReference {}; 1098bf80f4bSopenharmony_ci } 1108bf80f4bSopenharmony_ci return entities_[collectionIndex]; 1118bf80f4bSopenharmony_ci} 1128bf80f4bSopenharmony_ci 1138bf80f4bSopenharmony_ciEntityReference EntityCollection::GetEntity(string_view localContextId) const 1148bf80f4bSopenharmony_ci{ 1158bf80f4bSopenharmony_ci const auto it = entityIdentifiers_.find(localContextId); 1168bf80f4bSopenharmony_ci if (it != entityIdentifiers_.end()) { 1178bf80f4bSopenharmony_ci return it->second; 1188bf80f4bSopenharmony_ci } 1198bf80f4bSopenharmony_ci const auto itt = namedEntities_.find(localContextId); 1208bf80f4bSopenharmony_ci if (itt != namedEntities_.end()) { 1218bf80f4bSopenharmony_ci return itt->second; 1228bf80f4bSopenharmony_ci } 1238bf80f4bSopenharmony_ci return EntityReference {}; 1248bf80f4bSopenharmony_ci} 1258bf80f4bSopenharmony_ci 1268bf80f4bSopenharmony_ciEntityReference EntityCollection::GetEntityRecursive(string_view localContextId) const 1278bf80f4bSopenharmony_ci{ 1288bf80f4bSopenharmony_ci auto ret = GetEntity(localContextId); 1298bf80f4bSopenharmony_ci 1308bf80f4bSopenharmony_ci if (!CORE_NS::EntityUtil::IsValid(ret)) { 1318bf80f4bSopenharmony_ci for (auto& it : collections_) { 1328bf80f4bSopenharmony_ci ret = it->GetEntityRecursive(localContextId); 1338bf80f4bSopenharmony_ci if (CORE_NS::EntityUtil::IsValid(ret)) { 1348bf80f4bSopenharmony_ci break; 1358bf80f4bSopenharmony_ci } 1368bf80f4bSopenharmony_ci } 1378bf80f4bSopenharmony_ci } 1388bf80f4bSopenharmony_ci 1398bf80f4bSopenharmony_ci return ret; 1408bf80f4bSopenharmony_ci} 1418bf80f4bSopenharmony_ci 1428bf80f4bSopenharmony_civoid EntityCollection::RemoveEntityRecursive(CORE_NS::Entity entity) 1438bf80f4bSopenharmony_ci{ 1448bf80f4bSopenharmony_ci for (auto entityRef = entities_.cbegin(); entityRef != entities_.cend();) { 1458bf80f4bSopenharmony_ci if (entity == *entityRef) { 1468bf80f4bSopenharmony_ci entityRef = entities_.erase(entityRef); 1478bf80f4bSopenharmony_ci } else { 1488bf80f4bSopenharmony_ci entityRef++; 1498bf80f4bSopenharmony_ci } 1508bf80f4bSopenharmony_ci } 1518bf80f4bSopenharmony_ci 1528bf80f4bSopenharmony_ci for (auto entityRef = namedEntities_.cbegin(); entityRef != namedEntities_.cend();) { 1538bf80f4bSopenharmony_ci if (entityRef->second == entity) { 1548bf80f4bSopenharmony_ci entityRef = namedEntities_.erase(entityRef); 1558bf80f4bSopenharmony_ci } else { 1568bf80f4bSopenharmony_ci ++entityRef; 1578bf80f4bSopenharmony_ci } 1588bf80f4bSopenharmony_ci } 1598bf80f4bSopenharmony_ci 1608bf80f4bSopenharmony_ci auto uniqueIdentifier = GetUniqueIdentifier(entity); 1618bf80f4bSopenharmony_ci if (!uniqueIdentifier.empty()) { 1628bf80f4bSopenharmony_ci entityIdentifiers_.erase(uniqueIdentifier); 1638bf80f4bSopenharmony_ci } 1648bf80f4bSopenharmony_ci 1658bf80f4bSopenharmony_ci for (auto& it : collections_) { 1668bf80f4bSopenharmony_ci it->RemoveEntityRecursive(entity); 1678bf80f4bSopenharmony_ci } 1688bf80f4bSopenharmony_ci} 1698bf80f4bSopenharmony_ci 1708bf80f4bSopenharmony_ciarray_view<const EntityReference> EntityCollection::GetEntities() const 1718bf80f4bSopenharmony_ci{ 1728bf80f4bSopenharmony_ci return entities_; 1738bf80f4bSopenharmony_ci} 1748bf80f4bSopenharmony_ci 1758bf80f4bSopenharmony_civoid EntityCollection::AddEntity(EntityReference entity) 1768bf80f4bSopenharmony_ci{ 1778bf80f4bSopenharmony_ci AddEntities({ &entity, 1 }); 1788bf80f4bSopenharmony_ci} 1798bf80f4bSopenharmony_ci 1808bf80f4bSopenharmony_civoid EntityCollection::AddEntities(array_view<const EntityReference> entities) 1818bf80f4bSopenharmony_ci{ 1828bf80f4bSopenharmony_ci entities_.reserve(entities_.size() + entities.size()); 1838bf80f4bSopenharmony_ci for (const auto& entity : entities) { 1848bf80f4bSopenharmony_ci if (entity != Entity {}) { 1858bf80f4bSopenharmony_ci // TODO: make sure that the same entity is not added twice. 1868bf80f4bSopenharmony_ci entities_.emplace_back(entity); 1878bf80f4bSopenharmony_ci } else { 1888bf80f4bSopenharmony_ci CORE_LOG_D("Trying to add null entity reference to a collection"); 1898bf80f4bSopenharmony_ci } 1908bf80f4bSopenharmony_ci } 1918bf80f4bSopenharmony_ci MarkModified(true); 1928bf80f4bSopenharmony_ci} 1938bf80f4bSopenharmony_ci 1948bf80f4bSopenharmony_cibool EntityCollection::RemoveEntity(EntityReference entity) 1958bf80f4bSopenharmony_ci{ 1968bf80f4bSopenharmony_ci for (size_t i = 0; i < entities_.size(); ++i) { 1978bf80f4bSopenharmony_ci if (entities_[i] == entity) { 1988bf80f4bSopenharmony_ci entities_.erase(entities_.begin() + i); 1998bf80f4bSopenharmony_ci 2008bf80f4bSopenharmony_ci // Also remove any related id mappings. 2018bf80f4bSopenharmony_ci for (auto it = namedEntities_.begin(); it != namedEntities_.end(); ++it) { 2028bf80f4bSopenharmony_ci if (it->second == entity) { 2038bf80f4bSopenharmony_ci namedEntities_.erase(it); 2048bf80f4bSopenharmony_ci break; 2058bf80f4bSopenharmony_ci } 2068bf80f4bSopenharmony_ci } 2078bf80f4bSopenharmony_ci 2088bf80f4bSopenharmony_ci auto uniqueIdentifier = GetUniqueIdentifier(entity); 2098bf80f4bSopenharmony_ci if (!uniqueIdentifier.empty()) { 2108bf80f4bSopenharmony_ci entityIdentifiers_.erase(uniqueIdentifier); 2118bf80f4bSopenharmony_ci } 2128bf80f4bSopenharmony_ci 2138bf80f4bSopenharmony_ci // TODO: If this collection is overriding another "template" collection, when removing entities, we 2148bf80f4bSopenharmony_ci // need to remember that and the information about deletion needs to be serialized. Maybe check if 2158bf80f4bSopenharmony_ci // (src_.empty()). However this also needs to work with undo 2168bf80f4bSopenharmony_ci 2178bf80f4bSopenharmony_ci MarkModified(true); 2188bf80f4bSopenharmony_ci return true; 2198bf80f4bSopenharmony_ci } 2208bf80f4bSopenharmony_ci } 2218bf80f4bSopenharmony_ci 2228bf80f4bSopenharmony_ci // Not found. Check the sub-collections. 2238bf80f4bSopenharmony_ci for (auto& collection : collections_) { 2248bf80f4bSopenharmony_ci BASE_ASSERT(collection); 2258bf80f4bSopenharmony_ci if (collection->RemoveEntity(entity)) { 2268bf80f4bSopenharmony_ci MarkModified(true); 2278bf80f4bSopenharmony_ci return true; 2288bf80f4bSopenharmony_ci } 2298bf80f4bSopenharmony_ci } 2308bf80f4bSopenharmony_ci 2318bf80f4bSopenharmony_ci return false; 2328bf80f4bSopenharmony_ci} 2338bf80f4bSopenharmony_ci 2348bf80f4bSopenharmony_civoid EntityCollection::RemoveEntities(array_view<const EntityReference> entities) 2358bf80f4bSopenharmony_ci{ 2368bf80f4bSopenharmony_ci for (auto& entity : entities) { 2378bf80f4bSopenharmony_ci RemoveEntity(entity); 2388bf80f4bSopenharmony_ci } 2398bf80f4bSopenharmony_ci} 2408bf80f4bSopenharmony_ci 2418bf80f4bSopenharmony_civoid EntityCollection::SetId(string_view id, EntityReference entity) 2428bf80f4bSopenharmony_ci{ 2438bf80f4bSopenharmony_ci namedEntities_[id] = entity; 2448bf80f4bSopenharmony_ci} 2458bf80f4bSopenharmony_ci 2468bf80f4bSopenharmony_cistring_view EntityCollection::GetId(Entity entity) const 2478bf80f4bSopenharmony_ci{ 2488bf80f4bSopenharmony_ci for (auto& it : namedEntities_) { 2498bf80f4bSopenharmony_ci if (it.second == entity) { 2508bf80f4bSopenharmony_ci return it.first; 2518bf80f4bSopenharmony_ci } 2528bf80f4bSopenharmony_ci } 2538bf80f4bSopenharmony_ci return {}; 2548bf80f4bSopenharmony_ci} 2558bf80f4bSopenharmony_ci 2568bf80f4bSopenharmony_cistring_view EntityCollection::GetIdRecursive(Entity entity) const 2578bf80f4bSopenharmony_ci{ 2588bf80f4bSopenharmony_ci auto ret = GetId(entity); 2598bf80f4bSopenharmony_ci if (ret.empty()) { 2608bf80f4bSopenharmony_ci for (auto& it : collections_) { 2618bf80f4bSopenharmony_ci ret = it->GetIdRecursive(entity); 2628bf80f4bSopenharmony_ci if (!ret.empty()) { 2638bf80f4bSopenharmony_ci break; 2648bf80f4bSopenharmony_ci } 2658bf80f4bSopenharmony_ci } 2668bf80f4bSopenharmony_ci } 2678bf80f4bSopenharmony_ci return ret; 2688bf80f4bSopenharmony_ci} 2698bf80f4bSopenharmony_ci 2708bf80f4bSopenharmony_civoid EntityCollection::SetUniqueIdentifier(string_view id, EntityReference entity) 2718bf80f4bSopenharmony_ci{ 2728bf80f4bSopenharmony_ci entityIdentifiers_[id] = entity; 2738bf80f4bSopenharmony_ci} 2748bf80f4bSopenharmony_ci 2758bf80f4bSopenharmony_cistring_view EntityCollection::GetUniqueIdentifier(Entity entity) const 2768bf80f4bSopenharmony_ci{ 2778bf80f4bSopenharmony_ci for (auto& it : entityIdentifiers_) { 2788bf80f4bSopenharmony_ci if (it.second == entity) { 2798bf80f4bSopenharmony_ci return it.first; 2808bf80f4bSopenharmony_ci } 2818bf80f4bSopenharmony_ci } 2828bf80f4bSopenharmony_ci return {}; 2838bf80f4bSopenharmony_ci} 2848bf80f4bSopenharmony_ci 2858bf80f4bSopenharmony_cistring_view EntityCollection::GetUniqueIdentifierRecursive(Entity entity) const 2868bf80f4bSopenharmony_ci{ 2878bf80f4bSopenharmony_ci auto ret = GetUniqueIdentifier(entity); 2888bf80f4bSopenharmony_ci if (ret.empty()) { 2898bf80f4bSopenharmony_ci for (auto& it : collections_) { 2908bf80f4bSopenharmony_ci ret = it->GetUniqueIdentifierRecursive(entity); 2918bf80f4bSopenharmony_ci if (!ret.empty()) { 2928bf80f4bSopenharmony_ci break; 2938bf80f4bSopenharmony_ci } 2948bf80f4bSopenharmony_ci } 2958bf80f4bSopenharmony_ci } 2968bf80f4bSopenharmony_ci return ret; 2978bf80f4bSopenharmony_ci} 2988bf80f4bSopenharmony_ci 2998bf80f4bSopenharmony_cisize_t EntityCollection::GetSubCollectionCount() const 3008bf80f4bSopenharmony_ci{ 3018bf80f4bSopenharmony_ci return collections_.size(); 3028bf80f4bSopenharmony_ci} 3038bf80f4bSopenharmony_ci 3048bf80f4bSopenharmony_ciIEntityCollection* EntityCollection::GetSubCollection(size_t index) 3058bf80f4bSopenharmony_ci{ 3068bf80f4bSopenharmony_ci if (index < 0 || index >= collections_.size()) { 3078bf80f4bSopenharmony_ci return nullptr; 3088bf80f4bSopenharmony_ci } 3098bf80f4bSopenharmony_ci return collections_.at(index).get(); 3108bf80f4bSopenharmony_ci} 3118bf80f4bSopenharmony_ci 3128bf80f4bSopenharmony_ciconst IEntityCollection* EntityCollection::GetSubCollection(size_t index) const 3138bf80f4bSopenharmony_ci{ 3148bf80f4bSopenharmony_ci if (index < 0 || index >= collections_.size()) { 3158bf80f4bSopenharmony_ci return nullptr; 3168bf80f4bSopenharmony_ci } 3178bf80f4bSopenharmony_ci return collections_.at(index).get(); 3188bf80f4bSopenharmony_ci} 3198bf80f4bSopenharmony_ci 3208bf80f4bSopenharmony_ciint32_t EntityCollection::GetSubCollectionIndex(string_view uri) const 3218bf80f4bSopenharmony_ci{ 3228bf80f4bSopenharmony_ci for (size_t i = 0; i < collections_.size(); ++i) { 3238bf80f4bSopenharmony_ci BASE_ASSERT(collections_[i]); 3248bf80f4bSopenharmony_ci if (collections_[i]->GetUri() == uri) { 3258bf80f4bSopenharmony_ci return static_cast<int32_t>(i); 3268bf80f4bSopenharmony_ci } 3278bf80f4bSopenharmony_ci } 3288bf80f4bSopenharmony_ci return -1; 3298bf80f4bSopenharmony_ci} 3308bf80f4bSopenharmony_ci 3318bf80f4bSopenharmony_ciint32_t EntityCollection::GetSubCollectionIndexByRoot(Entity entity) const 3328bf80f4bSopenharmony_ci{ 3338bf80f4bSopenharmony_ci if (entity != Entity {}) { 3348bf80f4bSopenharmony_ci for (size_t i = 0; i < collections_.size(); ++i) { 3358bf80f4bSopenharmony_ci BASE_ASSERT(collections_[i]); 3368bf80f4bSopenharmony_ci if (collections_[i]->GetEntity("/") == entity) { 3378bf80f4bSopenharmony_ci return static_cast<int32_t>(i); 3388bf80f4bSopenharmony_ci } 3398bf80f4bSopenharmony_ci } 3408bf80f4bSopenharmony_ci } 3418bf80f4bSopenharmony_ci return -1; 3428bf80f4bSopenharmony_ci} 3438bf80f4bSopenharmony_ci 3448bf80f4bSopenharmony_ciIEntityCollection& EntityCollection::AddSubCollection(string_view uri, string_view contextUri, bool serializable) 3458bf80f4bSopenharmony_ci{ 3468bf80f4bSopenharmony_ci auto collection = EntityCollection::Ptr { new EntityCollection(ecs_, uri, contextUri) }; 3478bf80f4bSopenharmony_ci collection->SetSerialized(serializable); 3488bf80f4bSopenharmony_ci collections_.emplace_back(move(collection)); 3498bf80f4bSopenharmony_ci 3508bf80f4bSopenharmony_ci // listen to changes in subcollection 3518bf80f4bSopenharmony_ci collections_.back()->AddListener(*this); 3528bf80f4bSopenharmony_ci 3538bf80f4bSopenharmony_ci if (serializable) { 3548bf80f4bSopenharmony_ci MarkModified(true); 3558bf80f4bSopenharmony_ci } 3568bf80f4bSopenharmony_ci return *collections_.back(); 3578bf80f4bSopenharmony_ci} 3588bf80f4bSopenharmony_ci 3598bf80f4bSopenharmony_ciIEntityCollection& EntityCollection::AddSubCollectionClone(IEntityCollection& collection, string_view uri) 3608bf80f4bSopenharmony_ci{ 3618bf80f4bSopenharmony_ci // TODO: use just the public api 3628bf80f4bSopenharmony_ci collections_.emplace_back(EntityCollection::Ptr { new EntityCollection(ecs_, uri, collection.GetContextUri()) }); 3638bf80f4bSopenharmony_ci auto& ec = *collections_.back(); 3648bf80f4bSopenharmony_ci static_cast<EntityCollection&>(collection).ClonePrivate(ec); 3658bf80f4bSopenharmony_ci 3668bf80f4bSopenharmony_ci // listen to changes in subcollection 3678bf80f4bSopenharmony_ci ec.AddListener(*this); 3688bf80f4bSopenharmony_ci 3698bf80f4bSopenharmony_ci MarkModified(true); 3708bf80f4bSopenharmony_ci return ec; 3718bf80f4bSopenharmony_ci} 3728bf80f4bSopenharmony_ci 3738bf80f4bSopenharmony_civoid EntityCollection::RemoveSubCollection(size_t index) 3748bf80f4bSopenharmony_ci{ 3758bf80f4bSopenharmony_ci BASE_ASSERT(index < collections_.size()); 3768bf80f4bSopenharmony_ci if (index < collections_.size()) { 3778bf80f4bSopenharmony_ci // stop listening to changes in subcollection 3788bf80f4bSopenharmony_ci auto& ec = collections_.at(index); 3798bf80f4bSopenharmony_ci ec->RemoveListener(*this); 3808bf80f4bSopenharmony_ci 3818bf80f4bSopenharmony_ci collections_.erase(collections_.begin() + index); 3828bf80f4bSopenharmony_ci MarkModified(true); 3838bf80f4bSopenharmony_ci } 3848bf80f4bSopenharmony_ci} 3858bf80f4bSopenharmony_ci 3868bf80f4bSopenharmony_cisize_t EntityCollection::GetEntityCountRecursive(bool includeDestroyed, bool includeNonSerialized) const 3878bf80f4bSopenharmony_ci{ 3888bf80f4bSopenharmony_ci if (!includeDestroyed && IsMarkedDestroyed()) { 3898bf80f4bSopenharmony_ci return 0; 3908bf80f4bSopenharmony_ci } 3918bf80f4bSopenharmony_ci 3928bf80f4bSopenharmony_ci if (!includeNonSerialized && !IsSerialized()) { 3938bf80f4bSopenharmony_ci return 0; 3948bf80f4bSopenharmony_ci } 3958bf80f4bSopenharmony_ci 3968bf80f4bSopenharmony_ci auto size = entities_.size(); 3978bf80f4bSopenharmony_ci for (const auto& collection : collections_) { 3988bf80f4bSopenharmony_ci BASE_ASSERT(collection); 3998bf80f4bSopenharmony_ci size += collection->GetEntityCountRecursive(includeDestroyed, includeNonSerialized); 4008bf80f4bSopenharmony_ci } 4018bf80f4bSopenharmony_ci return size; 4028bf80f4bSopenharmony_ci} 4038bf80f4bSopenharmony_ci 4048bf80f4bSopenharmony_civoid EntityCollection::GetEntitiesRecursive( 4058bf80f4bSopenharmony_ci bool includeDestroyed, vector<EntityReference>& entitiesOut, bool includeNonSerialized) const 4068bf80f4bSopenharmony_ci{ 4078bf80f4bSopenharmony_ci // NOTE: Cloning depends on ordering of entitiesOut. 4088bf80f4bSopenharmony_ci entitiesOut.reserve(entitiesOut.size() + GetEntityCountRecursive(includeDestroyed, includeNonSerialized)); 4098bf80f4bSopenharmony_ci DoGetEntitiesRecursive(includeDestroyed, includeNonSerialized, entitiesOut); 4108bf80f4bSopenharmony_ci} 4118bf80f4bSopenharmony_ci 4128bf80f4bSopenharmony_civoid EntityCollection::DoGetEntitiesRecursive( 4138bf80f4bSopenharmony_ci bool includeDestroyed, bool includeNonSerialized, vector<EntityReference>& entitiesOut) const 4148bf80f4bSopenharmony_ci{ 4158bf80f4bSopenharmony_ci if (!includeDestroyed && IsMarkedDestroyed()) { 4168bf80f4bSopenharmony_ci return; 4178bf80f4bSopenharmony_ci } 4188bf80f4bSopenharmony_ci 4198bf80f4bSopenharmony_ci if (!includeNonSerialized && !IsSerialized()) { 4208bf80f4bSopenharmony_ci return; 4218bf80f4bSopenharmony_ci } 4228bf80f4bSopenharmony_ci 4238bf80f4bSopenharmony_ci entitiesOut.insert(entitiesOut.end(), entities_.begin(), entities_.end()); 4248bf80f4bSopenharmony_ci for (const auto& collection : collections_) { 4258bf80f4bSopenharmony_ci BASE_ASSERT(collection); 4268bf80f4bSopenharmony_ci collection->DoGetEntitiesRecursive(includeDestroyed, includeNonSerialized, entitiesOut); 4278bf80f4bSopenharmony_ci } 4288bf80f4bSopenharmony_ci} 4298bf80f4bSopenharmony_ci 4308bf80f4bSopenharmony_cibool EntityCollection::Contains(Entity entity) const 4318bf80f4bSopenharmony_ci{ 4328bf80f4bSopenharmony_ci for (auto& it : entities_) { 4338bf80f4bSopenharmony_ci if (it == entity) { 4348bf80f4bSopenharmony_ci return true; 4358bf80f4bSopenharmony_ci } 4368bf80f4bSopenharmony_ci } 4378bf80f4bSopenharmony_ci for (const auto& collection : collections_) { 4388bf80f4bSopenharmony_ci if (!collection->IsMarkedDestroyed()) { 4398bf80f4bSopenharmony_ci if (collection->Contains(entity)) { 4408bf80f4bSopenharmony_ci return true; 4418bf80f4bSopenharmony_ci } 4428bf80f4bSopenharmony_ci } 4438bf80f4bSopenharmony_ci } 4448bf80f4bSopenharmony_ci return false; 4458bf80f4bSopenharmony_ci} 4468bf80f4bSopenharmony_ci 4478bf80f4bSopenharmony_cibool EntityCollection::IsExternal(Entity entity) const 4488bf80f4bSopenharmony_ci{ 4498bf80f4bSopenharmony_ci for (auto& it : entities_) { 4508bf80f4bSopenharmony_ci if (it == entity) { 4518bf80f4bSopenharmony_ci return false; 4528bf80f4bSopenharmony_ci } 4538bf80f4bSopenharmony_ci } 4548bf80f4bSopenharmony_ci return true; 4558bf80f4bSopenharmony_ci} 4568bf80f4bSopenharmony_ci 4578bf80f4bSopenharmony_cibool EntityCollection::isSubCollectionRoot(Entity entity) const 4588bf80f4bSopenharmony_ci{ 4598bf80f4bSopenharmony_ci if (entity == Entity {}) { 4608bf80f4bSopenharmony_ci return false; 4618bf80f4bSopenharmony_ci } 4628bf80f4bSopenharmony_ci 4638bf80f4bSopenharmony_ci for (const auto& collection : collections_) { 4648bf80f4bSopenharmony_ci if (collection->GetEntity("/") == entity) { 4658bf80f4bSopenharmony_ci return true; 4668bf80f4bSopenharmony_ci } 4678bf80f4bSopenharmony_ci } 4688bf80f4bSopenharmony_ci 4698bf80f4bSopenharmony_ci return false; 4708bf80f4bSopenharmony_ci} 4718bf80f4bSopenharmony_ci 4728bf80f4bSopenharmony_ciCORE_NS::EntityReference EntityCollection::GetReference(CORE_NS::Entity entity) const 4738bf80f4bSopenharmony_ci{ 4748bf80f4bSopenharmony_ci if (Contains(entity)) { 4758bf80f4bSopenharmony_ci auto ref = GetEcs().GetEntityManager().GetReferenceCounted(entity); 4768bf80f4bSopenharmony_ci 4778bf80f4bSopenharmony_ci // Check that this entity was reference counted already (it should be part of the collection). 4788bf80f4bSopenharmony_ci CORE_ASSERT(ref.GetRefCount() > 1); 4798bf80f4bSopenharmony_ci 4808bf80f4bSopenharmony_ci return ref; 4818bf80f4bSopenharmony_ci } 4828bf80f4bSopenharmony_ci return {}; 4838bf80f4bSopenharmony_ci} 4848bf80f4bSopenharmony_ci 4858bf80f4bSopenharmony_civoid EntityCollection::SetActive(bool active) 4868bf80f4bSopenharmony_ci{ 4878bf80f4bSopenharmony_ci isActive_ = active; 4888bf80f4bSopenharmony_ci const bool effectivelyActive = isActive_ && !isMarkedDestroyed_; 4898bf80f4bSopenharmony_ci 4908bf80f4bSopenharmony_ci auto& em = ecs_.GetEntityManager(); 4918bf80f4bSopenharmony_ci for (auto& entity : entities_) { 4928bf80f4bSopenharmony_ci em.SetActive(entity, effectivelyActive); 4938bf80f4bSopenharmony_ci } 4948bf80f4bSopenharmony_ci 4958bf80f4bSopenharmony_ci for (auto& collection : collections_) { 4968bf80f4bSopenharmony_ci BASE_ASSERT(collection); 4978bf80f4bSopenharmony_ci collection->SetActive(active); 4988bf80f4bSopenharmony_ci } 4998bf80f4bSopenharmony_ci} 5008bf80f4bSopenharmony_ci 5018bf80f4bSopenharmony_cibool EntityCollection::IsActive() const 5028bf80f4bSopenharmony_ci{ 5038bf80f4bSopenharmony_ci return isActive_; 5048bf80f4bSopenharmony_ci} 5058bf80f4bSopenharmony_ci 5068bf80f4bSopenharmony_civoid EntityCollection::MarkDestroyed(bool destroyed) 5078bf80f4bSopenharmony_ci{ 5088bf80f4bSopenharmony_ci MarkModified(true); 5098bf80f4bSopenharmony_ci isMarkedDestroyed_ = destroyed; 5108bf80f4bSopenharmony_ci const bool effectivelyActive = isActive_ && !isMarkedDestroyed_; 5118bf80f4bSopenharmony_ci 5128bf80f4bSopenharmony_ci // Change the active state of entities without changing the active state of the collection itself. 5138bf80f4bSopenharmony_ci auto& em = ecs_.GetEntityManager(); 5148bf80f4bSopenharmony_ci for (auto& entity : entities_) { 5158bf80f4bSopenharmony_ci em.SetActive(entity, effectivelyActive); 5168bf80f4bSopenharmony_ci } 5178bf80f4bSopenharmony_ci 5188bf80f4bSopenharmony_ci for (auto& collection : collections_) { 5198bf80f4bSopenharmony_ci BASE_ASSERT(collection); 5208bf80f4bSopenharmony_ci collection->MarkDestroyed(destroyed); 5218bf80f4bSopenharmony_ci } 5228bf80f4bSopenharmony_ci} 5238bf80f4bSopenharmony_ci 5248bf80f4bSopenharmony_cibool EntityCollection::IsMarkedDestroyed() const 5258bf80f4bSopenharmony_ci{ 5268bf80f4bSopenharmony_ci return isMarkedDestroyed_; 5278bf80f4bSopenharmony_ci} 5288bf80f4bSopenharmony_ci 5298bf80f4bSopenharmony_civoid EntityCollection::MarkModified(bool modified) 5308bf80f4bSopenharmony_ci{ 5318bf80f4bSopenharmony_ci if (!IsSerialized()) { 5328bf80f4bSopenharmony_ci return; 5338bf80f4bSopenharmony_ci } 5348bf80f4bSopenharmony_ci 5358bf80f4bSopenharmony_ci if (isMarkedModified_ != modified) { 5368bf80f4bSopenharmony_ci isMarkedModified_ = modified; 5378bf80f4bSopenharmony_ci for (auto* l : listeners_) { 5388bf80f4bSopenharmony_ci l->ModifiedChanged(*this, modified); 5398bf80f4bSopenharmony_ci } 5408bf80f4bSopenharmony_ci } 5418bf80f4bSopenharmony_ci} 5428bf80f4bSopenharmony_ci 5438bf80f4bSopenharmony_civoid EntityCollection::MarkModified(bool modified, bool recursive) 5448bf80f4bSopenharmony_ci{ 5458bf80f4bSopenharmony_ci if (!IsSerialized()) { 5468bf80f4bSopenharmony_ci return; 5478bf80f4bSopenharmony_ci } 5488bf80f4bSopenharmony_ci 5498bf80f4bSopenharmony_ci if (recursive && !collections_.empty()) { 5508bf80f4bSopenharmony_ci for (auto& c : collections_) { 5518bf80f4bSopenharmony_ci c->MarkModified(modified, true); 5528bf80f4bSopenharmony_ci } 5538bf80f4bSopenharmony_ci } 5548bf80f4bSopenharmony_ci MarkModified(modified); 5558bf80f4bSopenharmony_ci} 5568bf80f4bSopenharmony_ci 5578bf80f4bSopenharmony_cibool EntityCollection::IsMarkedModified() const 5588bf80f4bSopenharmony_ci{ 5598bf80f4bSopenharmony_ci return isMarkedModified_; 5608bf80f4bSopenharmony_ci} 5618bf80f4bSopenharmony_ci 5628bf80f4bSopenharmony_civoid EntityCollection::Clear() 5638bf80f4bSopenharmony_ci{ 5648bf80f4bSopenharmony_ci serializationInfo_.clear(); 5658bf80f4bSopenharmony_ci namedEntities_.clear(); 5668bf80f4bSopenharmony_ci entityIdentifiers_.clear(); 5678bf80f4bSopenharmony_ci entities_.clear(); 5688bf80f4bSopenharmony_ci collections_.clear(); 5698bf80f4bSopenharmony_ci listeners_.clear(); 5708bf80f4bSopenharmony_ci 5718bf80f4bSopenharmony_ci MarkModified(true); 5728bf80f4bSopenharmony_ci} 5738bf80f4bSopenharmony_ci 5748bf80f4bSopenharmony_civoid EntityCollection::CopyContents(IEntityCollection& srcCollection) 5758bf80f4bSopenharmony_ci{ 5768bf80f4bSopenharmony_ci // TODO: use just the public api 5778bf80f4bSopenharmony_ci static_cast<EntityCollection&>(srcCollection).ClonePrivate(*this); 5788bf80f4bSopenharmony_ci MarkModified(true); 5798bf80f4bSopenharmony_ci} 5808bf80f4bSopenharmony_ci 5818bf80f4bSopenharmony_civoid EntityCollection::AddEntityToSubcollection( 5828bf80f4bSopenharmony_ci BASE_NS::string_view collection, BASE_NS::string_view name, CORE_NS::Entity entity, bool makeUnique) 5838bf80f4bSopenharmony_ci{ 5848bf80f4bSopenharmony_ci auto collectionIx = GetSubCollectionIndex(collection); 5858bf80f4bSopenharmony_ci if (collectionIx == -1) { 5868bf80f4bSopenharmony_ci AddSubCollection(collection, {}, !makeUnique); 5878bf80f4bSopenharmony_ci collectionIx = GetSubCollectionCount() - 1; 5888bf80f4bSopenharmony_ci } 5898bf80f4bSopenharmony_ci 5908bf80f4bSopenharmony_ci if (auto targetCollection = GetSubCollection(collectionIx)) { 5918bf80f4bSopenharmony_ci BASE_NS::string postFixed(name.data(), name.size()); 5928bf80f4bSopenharmony_ci if (makeUnique) { 5938bf80f4bSopenharmony_ci postFixed.append(":"); 5948bf80f4bSopenharmony_ci postFixed.append(BASE_NS::to_hex(entity.id)); 5958bf80f4bSopenharmony_ci } 5968bf80f4bSopenharmony_ci if (!CORE_NS::EntityUtil::IsValid(targetCollection->GetEntity(postFixed))) { 5978bf80f4bSopenharmony_ci auto ref = ecs_.GetEntityManager().GetReferenceCounted(entity); 5988bf80f4bSopenharmony_ci targetCollection->AddEntity(ref); 5998bf80f4bSopenharmony_ci targetCollection->SetUniqueIdentifier(postFixed, ref); 6008bf80f4bSopenharmony_ci } 6018bf80f4bSopenharmony_ci } 6028bf80f4bSopenharmony_ci} 6038bf80f4bSopenharmony_ci 6048bf80f4bSopenharmony_cibool EntityCollection::IsSerialized() const 6058bf80f4bSopenharmony_ci{ 6068bf80f4bSopenharmony_ci return isSerialized_; 6078bf80f4bSopenharmony_ci} 6088bf80f4bSopenharmony_ci 6098bf80f4bSopenharmony_civoid EntityCollection::SetSerialized(bool serialize) 6108bf80f4bSopenharmony_ci{ 6118bf80f4bSopenharmony_ci isSerialized_ = serialize; 6128bf80f4bSopenharmony_ci} 6138bf80f4bSopenharmony_ci 6148bf80f4bSopenharmony_ci// TODO: clean up copying. 6158bf80f4bSopenharmony_cinamespace { 6168bf80f4bSopenharmony_civoid CloneEntitiesFromCollection(IEntityCollection& srcCollection, IEntityCollection& dstCollection, 6178bf80f4bSopenharmony_ci IEntityCollection& srcSerializationCollection, IEntityCollection& dstSerializationCollection, 6188bf80f4bSopenharmony_ci array_view<const EntityReference> entities, unordered_map<Entity, Entity>& oldToNew, 6198bf80f4bSopenharmony_ci vector<EntityReference>& clonedOut) 6208bf80f4bSopenharmony_ci{ 6218bf80f4bSopenharmony_ci const size_t entityCount = entities.size(); 6228bf80f4bSopenharmony_ci for (size_t i = 0; i < entityCount; ++i) { 6238bf80f4bSopenharmony_ci auto srcEntity = entities[i]; 6248bf80f4bSopenharmony_ci 6258bf80f4bSopenharmony_ci // Copy the serialization and subcollection info. 6268bf80f4bSopenharmony_ci auto subCollectionIndex = srcCollection.GetSubCollectionIndexByRoot(srcEntity); 6278bf80f4bSopenharmony_ci if (subCollectionIndex >= 0) { 6288bf80f4bSopenharmony_ci auto* srcSubCollection = srcCollection.GetSubCollection(subCollectionIndex); 6298bf80f4bSopenharmony_ci auto& dstSubCollection = 6308bf80f4bSopenharmony_ci dstCollection.AddSubCollection(srcSubCollection->GetUri(), srcSubCollection->GetContextUri()); 6318bf80f4bSopenharmony_ci dstSubCollection.SetSrc(srcSubCollection->GetSrc()); 6328bf80f4bSopenharmony_ci 6338bf80f4bSopenharmony_ci // Recursively copy sub collection. 6348bf80f4bSopenharmony_ci CloneEntitiesFromCollection(*srcSubCollection, dstSubCollection, srcSerializationCollection, 6358bf80f4bSopenharmony_ci dstSerializationCollection, srcSubCollection->GetEntities(), oldToNew, clonedOut); 6368bf80f4bSopenharmony_ci 6378bf80f4bSopenharmony_ci // Need to find the collection roots manually. 6388bf80f4bSopenharmony_ci // TODO: a bit messy that the colelctions are iterated separately. 6398bf80f4bSopenharmony_ci // TODO: no easy way to get the root entity. 6408bf80f4bSopenharmony_ci const size_t collectionCount = srcSubCollection->GetSubCollectionCount(); 6418bf80f4bSopenharmony_ci for (size_t j = 0; j < collectionCount; ++j) { 6428bf80f4bSopenharmony_ci auto* sc = srcSubCollection->GetSubCollection(j); 6438bf80f4bSopenharmony_ci auto root = sc->GetEntity("/"); 6448bf80f4bSopenharmony_ci if (root != Entity {}) { 6458bf80f4bSopenharmony_ci CloneEntitiesFromCollection(*srcSubCollection, dstSubCollection, srcSerializationCollection, 6468bf80f4bSopenharmony_ci dstSerializationCollection, { &root, 1 }, oldToNew, clonedOut); 6478bf80f4bSopenharmony_ci } 6488bf80f4bSopenharmony_ci } 6498bf80f4bSopenharmony_ci 6508bf80f4bSopenharmony_ci } else if (!srcCollection.IsExternal(srcEntity)) { 6518bf80f4bSopenharmony_ci auto dstEntity = CloneEntityReference(srcCollection.GetEcs(), srcEntity, dstCollection.GetEcs()); 6528bf80f4bSopenharmony_ci 6538bf80f4bSopenharmony_ci clonedOut.emplace_back(dstEntity); 6548bf80f4bSopenharmony_ci oldToNew[srcEntity] = dstEntity; 6558bf80f4bSopenharmony_ci 6568bf80f4bSopenharmony_ci dstCollection.AddEntity(dstEntity); 6578bf80f4bSopenharmony_ci auto id = srcCollection.GetId(srcEntity); 6588bf80f4bSopenharmony_ci if (!id.empty()) { 6598bf80f4bSopenharmony_ci dstCollection.SetId(id, dstEntity); 6608bf80f4bSopenharmony_ci } 6618bf80f4bSopenharmony_ci 6628bf80f4bSopenharmony_ci // Note that the root collections contain all the serialization info. 6638bf80f4bSopenharmony_ci for (auto& cm : srcCollection.GetEcs().GetComponentManagers()) { 6648bf80f4bSopenharmony_ci auto* properties = srcSerializationCollection.GetSerializedProperties(srcEntity, cm->GetUid()); 6658bf80f4bSopenharmony_ci if (properties) { 6668bf80f4bSopenharmony_ci dstSerializationCollection.MarkComponentSerialized(dstEntity, cm->GetUid(), true); 6678bf80f4bSopenharmony_ci for (auto& property : *properties) { 6688bf80f4bSopenharmony_ci dstSerializationCollection.MarkPropertySerialized(dstEntity, cm->GetUid(), property, true); 6698bf80f4bSopenharmony_ci } 6708bf80f4bSopenharmony_ci } 6718bf80f4bSopenharmony_ci } 6728bf80f4bSopenharmony_ci } 6738bf80f4bSopenharmony_ci } 6748bf80f4bSopenharmony_ci} 6758bf80f4bSopenharmony_ci} // namespace 6768bf80f4bSopenharmony_ci 6778bf80f4bSopenharmony_civector<EntityReference> EntityCollection::CopyContentsWithSerialization( 6788bf80f4bSopenharmony_ci IEntityCollection& srcCollection, array_view<const EntityReference> entities) 6798bf80f4bSopenharmony_ci{ 6808bf80f4bSopenharmony_ci unordered_map<Entity, Entity> oldToNew; 6818bf80f4bSopenharmony_ci 6828bf80f4bSopenharmony_ci vector<EntityReference> entitiesOut; 6838bf80f4bSopenharmony_ci entitiesOut.reserve(entities.size()); 6848bf80f4bSopenharmony_ci CloneEntitiesFromCollection(srcCollection, *this, srcCollection, *this, entities, oldToNew, entitiesOut); 6858bf80f4bSopenharmony_ci 6868bf80f4bSopenharmony_ci for (auto& entity : entitiesOut) { 6878bf80f4bSopenharmony_ci RewriteEntityReferences(GetEcs(), entity, oldToNew); 6888bf80f4bSopenharmony_ci } 6898bf80f4bSopenharmony_ci return entitiesOut; 6908bf80f4bSopenharmony_ci} 6918bf80f4bSopenharmony_ci 6928bf80f4bSopenharmony_civector<EntityReference> EntityCollection::CopyContentsWithSerialization(IEntityCollection& srcCollection) 6938bf80f4bSopenharmony_ci{ 6948bf80f4bSopenharmony_ci vector<EntityReference> entitiesIn; 6958bf80f4bSopenharmony_ci srcCollection.GetEntitiesRecursive(false, entitiesIn); 6968bf80f4bSopenharmony_ci return CopyContentsWithSerialization(srcCollection, entitiesIn); 6978bf80f4bSopenharmony_ci} 6988bf80f4bSopenharmony_ci 6998bf80f4bSopenharmony_civoid EntityCollection::ClonePrivate(EntityCollection& dst) const 7008bf80f4bSopenharmony_ci{ 7018bf80f4bSopenharmony_ci // Clone all collections recursively. 7028bf80f4bSopenharmony_ci DoCloneRecursive(dst); 7038bf80f4bSopenharmony_ci 7048bf80f4bSopenharmony_ci // 7058bf80f4bSopenharmony_ci // Remap entity properties that are pointing to the src entities to point to cloned ones. 7068bf80f4bSopenharmony_ci // 7078bf80f4bSopenharmony_ci unordered_map<Entity, Entity> oldToNew; 7088bf80f4bSopenharmony_ci 7098bf80f4bSopenharmony_ci vector<EntityReference> sourceEntities; 7108bf80f4bSopenharmony_ci GetEntitiesRecursive(false, sourceEntities); 7118bf80f4bSopenharmony_ci vector<EntityReference> clonedEntities; 7128bf80f4bSopenharmony_ci dst.GetEntitiesRecursive(false, clonedEntities); 7138bf80f4bSopenharmony_ci 7148bf80f4bSopenharmony_ci // NOTE: Assuming the order in GetEntitiesRecursive is consistent. 7158bf80f4bSopenharmony_ci BASE_ASSERT(sourceEntities.size() == clonedEntities.size()); 7168bf80f4bSopenharmony_ci const auto entityCount = sourceEntities.size(); 7178bf80f4bSopenharmony_ci for (size_t i = 0; i < entityCount; ++i) { 7188bf80f4bSopenharmony_ci oldToNew[sourceEntities[i]] = clonedEntities[i]; 7198bf80f4bSopenharmony_ci } 7208bf80f4bSopenharmony_ci for (auto& entity : clonedEntities) { 7218bf80f4bSopenharmony_ci RewriteEntityReferences(dst.GetEcs(), entity, oldToNew); 7228bf80f4bSopenharmony_ci } 7238bf80f4bSopenharmony_ci} 7248bf80f4bSopenharmony_ci 7258bf80f4bSopenharmony_civoid EntityCollection::DoCloneRecursive(EntityCollection& dst) const 7268bf80f4bSopenharmony_ci{ 7278bf80f4bSopenharmony_ci // Clone entities. 7288bf80f4bSopenharmony_ci dst.entities_ = CloneEntityReferences(ecs_, { entities_.data(), entities_.size() }, dst.GetEcs()); 7298bf80f4bSopenharmony_ci 7308bf80f4bSopenharmony_ci // Create id mapping but reference cloned entities instead of the original 7318bf80f4bSopenharmony_ci BASE_ASSERT(entities_.size() == dst.entities_.size()); 7328bf80f4bSopenharmony_ci dst.namedEntities_.clear(); 7338bf80f4bSopenharmony_ci dst.namedEntities_.reserve(namedEntities_.size()); 7348bf80f4bSopenharmony_ci const auto entityCount = entities_.size(); 7358bf80f4bSopenharmony_ci for (const auto& it : namedEntities_) { 7368bf80f4bSopenharmony_ci for (size_t i = 0; i < entityCount; ++i) { 7378bf80f4bSopenharmony_ci if (it.second == entities_[i]) { 7388bf80f4bSopenharmony_ci dst.SetId(it.first, dst.entities_[i]); 7398bf80f4bSopenharmony_ci break; 7408bf80f4bSopenharmony_ci } 7418bf80f4bSopenharmony_ci } 7428bf80f4bSopenharmony_ci } 7438bf80f4bSopenharmony_ci 7448bf80f4bSopenharmony_ci // Recurse. 7458bf80f4bSopenharmony_ci dst.collections_.reserve(collections_.size()); 7468bf80f4bSopenharmony_ci for (auto& collection : collections_) { 7478bf80f4bSopenharmony_ci BASE_ASSERT(collection); 7488bf80f4bSopenharmony_ci 7498bf80f4bSopenharmony_ci if (!collection->IsMarkedDestroyed()) { 7508bf80f4bSopenharmony_ci dst.collections_.emplace_back(EntityCollection::Ptr { 7518bf80f4bSopenharmony_ci new EntityCollection(dst.GetEcs(), collection->GetUri(), collection->GetContextUri()) }); 7528bf80f4bSopenharmony_ci auto& clonedChild = *dst.collections_.back(); 7538bf80f4bSopenharmony_ci collection->DoCloneRecursive(clonedChild); 7548bf80f4bSopenharmony_ci } 7558bf80f4bSopenharmony_ci } 7568bf80f4bSopenharmony_ci} 7578bf80f4bSopenharmony_ci 7588bf80f4bSopenharmony_cinamespace { 7598bf80f4bSopenharmony_ci 7608bf80f4bSopenharmony_cibool SetPropertyDefined(EntityCollection::PropertyList& pl, string_view propertyPath) 7618bf80f4bSopenharmony_ci{ 7628bf80f4bSopenharmony_ci for (const auto& prop : pl) { 7638bf80f4bSopenharmony_ci if (prop == propertyPath) { 7648bf80f4bSopenharmony_ci // Already marked as a property defined by this node. 7658bf80f4bSopenharmony_ci return false; 7668bf80f4bSopenharmony_ci } 7678bf80f4bSopenharmony_ci 7688bf80f4bSopenharmony_ci // check if the property we are trying to set is a sub-property of an already defined property 7698bf80f4bSopenharmony_ci auto len1 = prop.length(); 7708bf80f4bSopenharmony_ci auto len2 = propertyPath.length(); 7718bf80f4bSopenharmony_ci if (len2 > len1) { 7728bf80f4bSopenharmony_ci auto view1 = prop.substr(0, len1); 7738bf80f4bSopenharmony_ci auto view2 = propertyPath.substr(0, len1); 7748bf80f4bSopenharmony_ci if (view1 == view2) { 7758bf80f4bSopenharmony_ci // already defined in a higher level, so no need to define this sub-property 7768bf80f4bSopenharmony_ci return false; 7778bf80f4bSopenharmony_ci } 7788bf80f4bSopenharmony_ci } 7798bf80f4bSopenharmony_ci } 7808bf80f4bSopenharmony_ci pl.push_back(string(propertyPath)); 7818bf80f4bSopenharmony_ci return true; 7828bf80f4bSopenharmony_ci} 7838bf80f4bSopenharmony_cibool SetPropertyUndefined(EntityCollection::PropertyList& pl, string_view propertyPath) 7848bf80f4bSopenharmony_ci{ 7858bf80f4bSopenharmony_ci for (size_t i = 0; i < pl.size(); ++i) { 7868bf80f4bSopenharmony_ci if (pl[i] == propertyPath) { 7878bf80f4bSopenharmony_ci pl.erase(pl.begin() + i); 7888bf80f4bSopenharmony_ci return true; 7898bf80f4bSopenharmony_ci } 7908bf80f4bSopenharmony_ci } 7918bf80f4bSopenharmony_ci return false; 7928bf80f4bSopenharmony_ci} 7938bf80f4bSopenharmony_ci 7948bf80f4bSopenharmony_ci} // namespace 7958bf80f4bSopenharmony_ci 7968bf80f4bSopenharmony_cibool EntityCollection::MarkComponentSerialized(Entity entity, Uid component, bool serialize) 7978bf80f4bSopenharmony_ci{ 7988bf80f4bSopenharmony_ci bool changed = false; 7998bf80f4bSopenharmony_ci const auto entityInfo = serializationInfo_.find(entity); 8008bf80f4bSopenharmony_ci const bool entityFound = (entityInfo != serializationInfo_.end()); 8018bf80f4bSopenharmony_ci if (serialize) { 8028bf80f4bSopenharmony_ci if (!entityFound) { 8038bf80f4bSopenharmony_ci serializationInfo_[entity][component] = {}; 8048bf80f4bSopenharmony_ci changed = true; 8058bf80f4bSopenharmony_ci } else { 8068bf80f4bSopenharmony_ci const auto componentInfo = entityInfo->second.find(component); 8078bf80f4bSopenharmony_ci const bool componentFound = (componentInfo != entityInfo->second.end()); 8088bf80f4bSopenharmony_ci if (!componentFound) { 8098bf80f4bSopenharmony_ci entityInfo->second[component] = {}; 8108bf80f4bSopenharmony_ci changed = true; 8118bf80f4bSopenharmony_ci } 8128bf80f4bSopenharmony_ci } 8138bf80f4bSopenharmony_ci } else { 8148bf80f4bSopenharmony_ci if (entityFound) { 8158bf80f4bSopenharmony_ci entityInfo->second.erase(component); 8168bf80f4bSopenharmony_ci changed = true; 8178bf80f4bSopenharmony_ci } 8188bf80f4bSopenharmony_ci } 8198bf80f4bSopenharmony_ci 8208bf80f4bSopenharmony_ci if (changed) { 8218bf80f4bSopenharmony_ci MarkModified(true); 8228bf80f4bSopenharmony_ci } 8238bf80f4bSopenharmony_ci 8248bf80f4bSopenharmony_ci return changed; 8258bf80f4bSopenharmony_ci} 8268bf80f4bSopenharmony_ci 8278bf80f4bSopenharmony_cibool EntityCollection::MarkAllPropertiesSerialized(Entity entity, Uid component) 8288bf80f4bSopenharmony_ci{ 8298bf80f4bSopenharmony_ci bool changed = false; 8308bf80f4bSopenharmony_ci 8318bf80f4bSopenharmony_ci auto cm = GetEcs().GetComponentManager(component); 8328bf80f4bSopenharmony_ci if (!cm) { 8338bf80f4bSopenharmony_ci CORE_LOG_W("Set modified: Unrecognized component"); 8348bf80f4bSopenharmony_ci return false; 8358bf80f4bSopenharmony_ci } 8368bf80f4bSopenharmony_ci 8378bf80f4bSopenharmony_ci auto info = serializationInfo_.find(entity); 8388bf80f4bSopenharmony_ci if (info == serializationInfo_.end()) { 8398bf80f4bSopenharmony_ci serializationInfo_[entity] = {}; 8408bf80f4bSopenharmony_ci info = serializationInfo_.find(entity); 8418bf80f4bSopenharmony_ci changed = true; 8428bf80f4bSopenharmony_ci } 8438bf80f4bSopenharmony_ci 8448bf80f4bSopenharmony_ci const auto& propertyApi = cm->GetPropertyApi(); 8458bf80f4bSopenharmony_ci const auto propertyCount = propertyApi.PropertyCount(); 8468bf80f4bSopenharmony_ci for (size_t i = 0; i < propertyCount; ++i) { 8478bf80f4bSopenharmony_ci auto* property = propertyApi.MetaData(i); 8488bf80f4bSopenharmony_ci changed = changed | SetPropertyDefined(info->second[component], property->name); 8498bf80f4bSopenharmony_ci } 8508bf80f4bSopenharmony_ci 8518bf80f4bSopenharmony_ci if (changed) { 8528bf80f4bSopenharmony_ci MarkModified(true); 8538bf80f4bSopenharmony_ci } 8548bf80f4bSopenharmony_ci 8558bf80f4bSopenharmony_ci return changed; 8568bf80f4bSopenharmony_ci} 8578bf80f4bSopenharmony_ci 8588bf80f4bSopenharmony_cibool EntityCollection::MarkPropertySerialized(Entity entity, Uid component, string_view propertyPath, bool serialize) 8598bf80f4bSopenharmony_ci{ 8608bf80f4bSopenharmony_ci bool changed = false; 8618bf80f4bSopenharmony_ci 8628bf80f4bSopenharmony_ci auto* cm = GetEcs().GetComponentManager(component); 8638bf80f4bSopenharmony_ci if (cm) { 8648bf80f4bSopenharmony_ci auto info = serializationInfo_.find(entity); 8658bf80f4bSopenharmony_ci if (serialize) { 8668bf80f4bSopenharmony_ci if (info == serializationInfo_.end()) { 8678bf80f4bSopenharmony_ci serializationInfo_[entity][component] = {}; 8688bf80f4bSopenharmony_ci info = serializationInfo_.find(entity); 8698bf80f4bSopenharmony_ci changed = true; 8708bf80f4bSopenharmony_ci } 8718bf80f4bSopenharmony_ci changed = changed | SetPropertyDefined(info->second[component], propertyPath); 8728bf80f4bSopenharmony_ci } else { 8738bf80f4bSopenharmony_ci if (info != serializationInfo_.end()) { 8748bf80f4bSopenharmony_ci changed = changed | SetPropertyUndefined(info->second[component], propertyPath); 8758bf80f4bSopenharmony_ci } 8768bf80f4bSopenharmony_ci } 8778bf80f4bSopenharmony_ci } 8788bf80f4bSopenharmony_ci 8798bf80f4bSopenharmony_ci if (changed) { 8808bf80f4bSopenharmony_ci MarkModified(true); 8818bf80f4bSopenharmony_ci } 8828bf80f4bSopenharmony_ci 8838bf80f4bSopenharmony_ci return changed; 8848bf80f4bSopenharmony_ci} 8858bf80f4bSopenharmony_ci 8868bf80f4bSopenharmony_ciconst IEntityCollection::PropertyList* EntityCollection::GetSerializedProperties(Entity entity, Uid component) const 8878bf80f4bSopenharmony_ci{ 8888bf80f4bSopenharmony_ci const auto info = serializationInfo_.find(entity); 8898bf80f4bSopenharmony_ci if (info != serializationInfo_.end()) { 8908bf80f4bSopenharmony_ci const auto props = info->second.find(component); 8918bf80f4bSopenharmony_ci if (props != info->second.end()) { 8928bf80f4bSopenharmony_ci return &props->second; 8938bf80f4bSopenharmony_ci } 8948bf80f4bSopenharmony_ci } 8958bf80f4bSopenharmony_ci return nullptr; 8968bf80f4bSopenharmony_ci} 8978bf80f4bSopenharmony_ci 8988bf80f4bSopenharmony_cibool EntityCollection::IsPropertySerialized(Entity entity, Uid component, string_view propertyPath) 8998bf80f4bSopenharmony_ci{ 9008bf80f4bSopenharmony_ci auto info = serializationInfo_.find(entity); 9018bf80f4bSopenharmony_ci if (info == serializationInfo_.end()) { 9028bf80f4bSopenharmony_ci return false; 9038bf80f4bSopenharmony_ci } else { 9048bf80f4bSopenharmony_ci const auto props = info->second.find(component); 9058bf80f4bSopenharmony_ci if (props == info->second.end()) { 9068bf80f4bSopenharmony_ci return false; 9078bf80f4bSopenharmony_ci } else { 9088bf80f4bSopenharmony_ci for (auto& prop : props->second) { 9098bf80f4bSopenharmony_ci if (prop == propertyPath) { 9108bf80f4bSopenharmony_ci return true; 9118bf80f4bSopenharmony_ci } 9128bf80f4bSopenharmony_ci } 9138bf80f4bSopenharmony_ci } 9148bf80f4bSopenharmony_ci } 9158bf80f4bSopenharmony_ci return false; 9168bf80f4bSopenharmony_ci} 9178bf80f4bSopenharmony_ci 9188bf80f4bSopenharmony_civoid EntityCollection::Destroy() 9198bf80f4bSopenharmony_ci{ 9208bf80f4bSopenharmony_ci delete this; 9218bf80f4bSopenharmony_ci} 9228bf80f4bSopenharmony_ci 9238bf80f4bSopenharmony_ciEntityCollection::~EntityCollection() 9248bf80f4bSopenharmony_ci{ 9258bf80f4bSopenharmony_ci Clear(); 9268bf80f4bSopenharmony_ci} 9278bf80f4bSopenharmony_ci 9288bf80f4bSopenharmony_civoid EntityCollection::ModifiedChanged(IEntityCollection& entityCollection, bool modified) 9298bf80f4bSopenharmony_ci{ 9308bf80f4bSopenharmony_ci // subcollection changed, propagate modified status 9318bf80f4bSopenharmony_ci if (modified) { 9328bf80f4bSopenharmony_ci MarkModified(modified); 9338bf80f4bSopenharmony_ci } 9348bf80f4bSopenharmony_ci} 9358bf80f4bSopenharmony_ci 9368bf80f4bSopenharmony_ciIEntityCollection::Ptr EntityCollection::CreateNewEntityCollection(string_view uri, string_view contextUri) 9378bf80f4bSopenharmony_ci{ 9388bf80f4bSopenharmony_ci return EntityCollection::Ptr { new EntityCollection(ecs_, uri, contextUri) }; 9398bf80f4bSopenharmony_ci} 9408bf80f4bSopenharmony_ci 9418bf80f4bSopenharmony_ciSCENE_END_NAMESPACE() 942