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 <core/log.h> 17 18CORE_BEGIN_NAMESPACE() 19namespace { 20constexpr uint32_t MODIFIED = 0x80000000; 21 22// Default initial reservation for 8 components/entities. 23// Will resize as needed. 24constexpr size_t INITIAL_COMPONENT_RESERVE_SIZE = 8; 25 26template<typename Container> 27inline auto ItemOrNull(Container&& v, IComponentManager::ComponentId index) 28{ 29 if (index < v.size()) { 30 return &(v[index]); 31 } 32 return (BASE_NS::remove_reference_t<decltype(v[index])>*)(nullptr); 33} 34 35template<typename EntityMap> 36inline auto ItemId(EntityMap&& entities, Entity entity) 37{ 38 if (EntityUtil::IsValid(entity)) { 39 if (const auto it = entities.find(entity); it != entities.end()) { 40 return it->second; 41 } 42 } 43 return IComponentManager::INVALID_COMPONENT_ID; 44} 45} // namespace 46 47// IPropertyApi 48template<typename ComponentType, typename BaseClass> 49IPropertyHandle* BaseManager<ComponentType, BaseClass>::Create() const 50{ 51 return new BaseComponentHandle(const_cast<BaseManager<ComponentType, BaseClass>*>(this), {}, {}); 52} 53 54template<typename ComponentType, typename BaseClass> 55IPropertyHandle* BaseManager<ComponentType, BaseClass>::Clone(const IPropertyHandle* src) const 56{ 57 if (src->Owner() == this) { 58 auto* h = static_cast<const BaseComponentHandle*>(src); 59 return new BaseComponentHandle(const_cast<BaseManager<ComponentType, BaseClass>*>(this), {}, h->data_); 60 } 61 return nullptr; 62} 63 64template<typename ComponentType, typename BaseClass> 65void BaseManager<ComponentType, BaseClass>::Release(IPropertyHandle* dst) const 66{ 67 if (dst && (dst->Owner() == this)) { 68 // we can only destroy things we "own" (know) 69 auto* handle = static_cast<BaseComponentHandle*>(dst); 70 if (auto id = GetComponentId(handle->entity_); id != IComponentManager::INVALID_COMPONENT_ID) { 71 if (&components_[id] == handle) { 72 // This is one of the components (bound to an entity) so do nothing 73 return; 74 } 75 } 76 delete handle; 77 } 78} 79 80template<typename ComponentType, typename BaseClass> 81uint64_t BaseManager<ComponentType, BaseClass>::Type() const 82{ 83 return typeHash_; 84} 85 86// IComponentManager 87template<typename ComponentType, typename BaseClass> 88BASE_NS::string_view BaseManager<ComponentType, BaseClass>::GetName() const 89{ 90 return name_; 91} 92 93template<typename ComponentType, typename BaseClass> 94BASE_NS::Uid BaseManager<ComponentType, BaseClass>::GetUid() const 95{ 96 return BaseClass::UID; 97} 98 99template<typename ComponentType, typename BaseClass> 100size_t BaseManager<ComponentType, BaseClass>::GetComponentCount() const 101{ 102 return components_.size(); 103} 104 105template<typename ComponentType, typename BaseClass> 106const IPropertyApi& BaseManager<ComponentType, BaseClass>::GetPropertyApi() const 107{ 108 return *this; 109} 110 111template<typename ComponentType, typename BaseClass> 112CORE_NS::Entity BaseManager<ComponentType, BaseClass>::GetEntity(ComponentId index) const 113{ 114 if (index < components_.size()) { 115 return components_[index].entity_; 116 } 117 return CORE_NS::Entity(); 118} 119 120template<typename ComponentType, typename BaseClass> 121uint32_t BaseManager<ComponentType, BaseClass>::GetComponentGeneration(ComponentId index) const 122{ 123 if (index < components_.size()) { 124 return components_[index].generation_; 125 } 126 return 0; 127} 128 129template<typename ComponentType, typename BaseClass> 130bool BaseManager<ComponentType, BaseClass>::HasComponent(CORE_NS::Entity entity) const 131{ 132 return GetComponentId(entity) != IComponentManager::INVALID_COMPONENT_ID; 133} 134 135template<typename ComponentType, typename BaseClass> 136IComponentManager::ComponentId BaseManager<ComponentType, BaseClass>::GetComponentId(CORE_NS::Entity entity) const 137{ 138 if (EntityUtil::IsValid(entity)) { 139 if (auto it = entityComponent_.find(entity); it != entityComponent_.end()) { 140 return it->second; 141 } 142 } 143 return IComponentManager::INVALID_COMPONENT_ID; 144} 145 146template<typename ComponentType, typename BaseClass> 147void BaseManager<ComponentType, BaseClass>::Create(CORE_NS::Entity entity) 148{ 149 if (EntityUtil::IsValid(entity)) { 150 if (auto it = entityComponent_.find(entity); it == entityComponent_.end()) { 151 entityComponent_.insert({ entity, static_cast<ComponentId>(components_.size()) }); 152 const auto oldCapacity = components_.capacity(); 153 components_.emplace_back(this, entity); 154 if (components_.capacity() != oldCapacity) { 155 moved_.reserve(moved_.size() + components_.size()); 156 for (const auto& handle : components_) { 157 moved_.push_back(handle.entity_); 158 } 159 modifiedFlags_ |= CORE_COMPONENT_MANAGER_COMPONENT_MOVED_BIT; 160 } 161 added_.push_back(entity); 162 modifiedFlags_ |= CORE_COMPONENT_MANAGER_COMPONENT_ADDED_BIT; 163 ++generationCounter_; 164 } else { 165 if (auto dst = ScopedHandle<ComponentType>(&components_[it->second]); dst) { 166 *dst = {}; 167 } 168 } 169 } 170} 171 172template<typename ComponentType, typename BaseClass> 173bool BaseManager<ComponentType, BaseClass>::Destroy(CORE_NS::Entity entity) 174{ 175 if (EntityUtil::IsValid(entity)) { 176 if (auto it = entityComponent_.find(entity); it != entityComponent_.end()) { 177 components_[it->second].entity_ = {}; // invalid entity. (marks it as ready for re-use) 178 entityComponent_.erase(it); 179 removed_.push_back(entity); 180 modifiedFlags_ |= CORE_COMPONENT_MANAGER_COMPONENT_REMOVED_BIT; 181 ++generationCounter_; 182 return true; 183 } 184 } 185 return false; 186} 187 188template<typename ComponentType, typename BaseClass> 189void BaseManager<ComponentType, BaseClass>::Gc() 190{ 191 const bool hasRemovedComponents = modifiedFlags_ & CORE_COMPONENT_MANAGER_COMPONENT_REMOVED_BIT; 192 if (!hasRemovedComponents) { 193 return; 194 } 195 ComponentId componentCount = static_cast<ComponentId>(components_.size()); 196 for (ComponentId id = 0; id < componentCount;) { 197 if (EntityUtil::IsValid(components_[id].entity_)) { 198 ++id; 199 continue; 200 } 201 // invalid entity.. if so clean garbage 202 // find last valid and swap with it 203 ComponentId rid = componentCount - 1; 204 while ((rid > id) && !EntityUtil::IsValid(components_[rid].entity_)) { 205 --rid; 206 } 207 if ((rid > id) && EntityUtil::IsValid(components_[rid].entity_)) { 208 moved_.push_back(components_[rid].entity_); 209 // fix the entityComponent_ map (update the component id for the entity) 210 entityComponent_[components_[rid].entity_] = id; 211 components_[id] = BASE_NS::move(components_[rid]); 212 } 213 --componentCount; 214 } 215 if (!moved_.empty()) { 216 modifiedFlags_ |= CORE_COMPONENT_MANAGER_COMPONENT_MOVED_BIT; 217 } 218 if (components_.size() > componentCount) { 219 auto diff = static_cast<typename decltype(components_)::difference_type>(componentCount); 220 components_.erase(components_.cbegin() + diff, components_.cend()); 221 } 222} 223 224template<typename ComponentType, typename BaseClass> 225void BaseManager<ComponentType, BaseClass>::Destroy(BASE_NS::array_view<const CORE_NS::Entity> gcList) 226{ 227 for (const CORE_NS::Entity e : gcList) { 228 Destroy(e); 229 } 230} 231 232template<typename ComponentType, typename BaseClass> 233BASE_NS::vector<CORE_NS::Entity> BaseManager<ComponentType, BaseClass>::GetAddedComponents() 234{ 235 return BASE_NS::move(added_); 236} 237 238template<typename ComponentType, typename BaseClass> 239BASE_NS::vector<CORE_NS::Entity> BaseManager<ComponentType, BaseClass>::GetRemovedComponents() 240{ 241 return BASE_NS::move(removed_); 242} 243 244template<typename ComponentType, typename BaseClass> 245BASE_NS::vector<CORE_NS::Entity> BaseManager<ComponentType, BaseClass>::GetUpdatedComponents() 246{ 247 BASE_NS::vector<CORE_NS::Entity> updated; 248 if (modifiedFlags_ & MODIFIED) { 249 modifiedFlags_ &= ~MODIFIED; 250 updated.reserve(components_.size() / 2U); // 2: approximation for vector reserve size 251 for (auto& handle : components_) { 252 if (handle.dirty_) { 253 handle.dirty_ = false; 254 updated.push_back(handle.entity_); 255 } 256 } 257 } 258 return updated; 259} 260 261template<typename ComponentType, typename BaseClass> 262BASE_NS::vector<CORE_NS::Entity> BaseManager<ComponentType, BaseClass>::GetMovedComponents() 263{ 264 return BASE_NS::move(moved_); 265} 266 267template<typename ComponentType, typename BaseClass> 268CORE_NS::ComponentManagerModifiedFlags BaseManager<ComponentType, BaseClass>::GetModifiedFlags() const 269{ 270 return modifiedFlags_ & ~MODIFIED; 271} 272 273template<typename ComponentType, typename BaseClass> 274void BaseManager<ComponentType, BaseClass>::ClearModifiedFlags() 275{ 276 modifiedFlags_ &= MODIFIED; 277} 278 279template<typename ComponentType, typename BaseClass> 280uint32_t BaseManager<ComponentType, BaseClass>::GetGenerationCounter() const 281{ 282 return generationCounter_; 283} 284 285template<typename ComponentType, typename BaseClass> 286void BaseManager<ComponentType, BaseClass>::SetData(CORE_NS::Entity entity, const IPropertyHandle& dataHandle) 287{ 288 if (!IsMatchingHandle(dataHandle)) { 289 return; 290 } 291 if (const auto src = ScopedHandle<const ComponentType>(&dataHandle); src) { 292 if (const auto it = entityComponent_.find(entity); it != entityComponent_.end()) { 293 if (auto dst = ScopedHandle<ComponentType>(&components_[it->second]); dst) { 294 *dst = *src; 295 } 296 } 297 } 298} 299 300template<typename ComponentType, typename BaseClass> 301const IPropertyHandle* BaseManager<ComponentType, BaseClass>::GetData(CORE_NS::Entity entity) const 302{ 303 return ItemOrNull(components_, ItemId(entityComponent_, entity)); 304} 305 306template<typename ComponentType, typename BaseClass> 307IPropertyHandle* BaseManager<ComponentType, BaseClass>::GetData(CORE_NS::Entity entity) 308{ 309 return ItemOrNull(components_, ItemId(entityComponent_, entity)); 310} 311 312template<typename ComponentType, typename BaseClass> 313void BaseManager<ComponentType, BaseClass>::SetData(ComponentId index, const IPropertyHandle& dataHandle) 314{ 315 if (!IsMatchingHandle(dataHandle)) { 316 // We could verify the metadata here. 317 // And in copy only the matching properties one-by-one also. 318 return; 319 } 320 if (index < components_.size()) { 321 if (const auto src = ScopedHandle<const ComponentType>(&dataHandle); src) { 322 if (auto dst = ScopedHandle<ComponentType>(&components_[index]); dst) { 323 *dst = *src; 324 } 325 } 326 } 327} 328 329template<typename ComponentType, typename BaseClass> 330const IPropertyHandle* BaseManager<ComponentType, BaseClass>::GetData(ComponentId index) const 331{ 332 return ItemOrNull(components_, index); 333} 334 335template<typename ComponentType, typename BaseClass> 336IPropertyHandle* BaseManager<ComponentType, BaseClass>::GetData(ComponentId index) 337{ 338 return ItemOrNull(components_, index); 339} 340 341template<typename ComponentType, typename BaseClass> 342IEcs& BaseManager<ComponentType, BaseClass>::GetEcs() const 343{ 344 return ecs_; 345} 346 347// "base class" 348template<typename ComponentType, typename BaseClass> 349ComponentType BaseManager<ComponentType, BaseClass>::Get(ComponentId index) const 350{ 351 if (auto handle = ScopedHandle<const ComponentType>(ItemOrNull(components_, index))) { 352 return *handle; 353 } 354 return ComponentType {}; 355} 356 357template<typename ComponentType, typename BaseClass> 358ComponentType BaseManager<ComponentType, BaseClass>::Get(CORE_NS::Entity entity) const 359{ 360 if (auto handle = ScopedHandle<const ComponentType>(ItemOrNull(components_, ItemId(entityComponent_, entity)))) { 361 return *handle; 362 } 363 return ComponentType {}; 364} 365 366template<typename ComponentType, typename BaseClass> 367void BaseManager<ComponentType, BaseClass>::Set(ComponentId index, const ComponentType& data) 368{ 369 if (auto handle = ScopedHandle<ComponentType>(ItemOrNull(components_, index))) { 370 *handle = data; 371 } 372} 373 374template<typename ComponentType, typename BaseClass> 375void BaseManager<ComponentType, BaseClass>::Set(CORE_NS::Entity entity, const ComponentType& data) 376{ 377 if (EntityUtil::IsValid(entity)) { 378 if (const auto it = entityComponent_.find(entity); it == entityComponent_.end()) { 379 entityComponent_.insert({ entity, static_cast<ComponentId>(components_.size()) }); 380 const auto oldCapacity = components_.capacity(); 381 components_.emplace_back(this, entity, data).generation_ = 1; 382 if (components_.capacity() != oldCapacity) { 383 moved_.reserve(moved_.size() + components_.size()); 384 for (const auto& handle : components_) { 385 moved_.push_back(handle.entity_); 386 } 387 modifiedFlags_ |= CORE_COMPONENT_MANAGER_COMPONENT_MOVED_BIT; 388 } 389 added_.push_back(entity); 390 modifiedFlags_ |= CORE_COMPONENT_MANAGER_COMPONENT_ADDED_BIT; 391 ++generationCounter_; 392 } else { 393 if (auto handle = ScopedHandle<ComponentType>(&components_[it->second]); handle) { 394 *handle = data; 395 } 396 } 397 } 398} 399 400template<typename ComponentType, typename BaseClass> 401ScopedHandle<const ComponentType> BaseManager<ComponentType, BaseClass>::Read(ComponentId index) const 402{ 403 return ScopedHandle<const ComponentType> { ItemOrNull(components_, index) }; 404} 405 406template<typename ComponentType, typename BaseClass> 407ScopedHandle<const ComponentType> BaseManager<ComponentType, BaseClass>::Read(CORE_NS::Entity entity) const 408{ 409 return ScopedHandle<const ComponentType> { ItemOrNull(components_, ItemId(entityComponent_, entity)) }; 410} 411 412template<typename ComponentType, typename BaseClass> 413ScopedHandle<ComponentType> BaseManager<ComponentType, BaseClass>::Write(ComponentId index) 414{ 415 return ScopedHandle<ComponentType> { ItemOrNull(components_, index) }; 416} 417 418template<typename ComponentType, typename BaseClass> 419ScopedHandle<ComponentType> BaseManager<ComponentType, BaseClass>::Write(CORE_NS::Entity entity) 420{ 421 return ScopedHandle<ComponentType> { ItemOrNull(components_, ItemId(entityComponent_, entity)) }; 422} 423 424// internal 425template<typename ComponentType, typename BaseClass> 426void BaseManager<ComponentType, BaseClass>::Updated(CORE_NS::Entity entity) 427{ 428 CORE_ASSERT_MSG(EntityUtil::IsValid(entity), "Invalid ComponentId, bound to INVALID_ENTITY"); 429 modifiedFlags_ |= CORE_COMPONENT_MANAGER_COMPONENT_UPDATED_BIT | MODIFIED; 430 ++generationCounter_; 431} 432 433template<typename ComponentType, typename BaseClass> 434BaseManager<ComponentType, BaseClass>::BaseManager(IEcs& ecs, const BASE_NS::string_view name) noexcept 435 : BaseManager(ecs, name, INITIAL_COMPONENT_RESERVE_SIZE) 436{} 437 438template<typename ComponentType, typename BaseClass> 439BaseManager<ComponentType, BaseClass>::BaseManager( 440 IEcs& ecs, const BASE_NS::string_view name, const size_t preallocate) noexcept 441 : ecs_(ecs), name_(name), typeHash_(BASE_NS::FNV1aHash(name.data(), name.size())) 442{ 443 if (preallocate) { 444 components_.reserve(preallocate); 445 entityComponent_.reserve(preallocate); 446 } 447} 448 449template<typename ComponentType, typename BaseClass> 450BaseManager<ComponentType, BaseClass>::~BaseManager() 451{ 452 CORE_ASSERT(GetComponentCount() == 0); 453} 454 455template<typename ComponentType, typename BaseClass> 456bool BaseManager<ComponentType, BaseClass>::IsMatchingHandle(const IPropertyHandle& dataHandle) 457{ 458 if (dataHandle.Owner() == this) { 459 return true; 460 } 461 if (dataHandle.Owner() && (dataHandle.Owner()->Type() == typeHash_)) { 462 return true; 463 } 464 return false; 465} 466 467// handle implementation 468template<typename ComponentType, typename BaseClass> 469BaseManager<ComponentType, BaseClass>::BaseComponentHandle::BaseComponentHandle( 470 BaseManager* owner, CORE_NS::Entity entity) noexcept 471 : manager_(owner), entity_(entity) 472{} 473 474template<typename ComponentType, typename BaseClass> 475BaseManager<ComponentType, BaseClass>::BaseComponentHandle::BaseComponentHandle( 476 BaseManager* owner, CORE_NS::Entity entity, const ComponentType& data) noexcept 477 : manager_(owner), entity_(entity), data_(data) 478{} 479 480template<typename ComponentType, typename BaseClass> 481BaseManager<ComponentType, BaseClass>::BaseComponentHandle::BaseComponentHandle(BaseComponentHandle&& other) noexcept 482 : 483#ifndef NDEBUG 484 rLocked_(other.rLocked_.exchange(0U)), 485 wLocked_(BASE_NS::exchange(other.wLocked_, false)), 486#endif 487 manager_(other.manager_), 488 generation_(BASE_NS::exchange(other.generation_, 0U)), 489 entity_(BASE_NS::exchange(other.entity_, {})), 490 data_(BASE_NS::exchange(other.data_, {})) 491{ 492#ifndef NDEBUG 493 CORE_ASSERT((rLocked_ == 0U) && !wLocked_); 494#endif 495} 496 497template<typename ComponentType, typename BaseClass> 498typename BaseManager<ComponentType, BaseClass>::BaseComponentHandle& 499BaseManager<ComponentType, BaseClass>::BaseComponentHandle::operator=(BaseComponentHandle&& other) noexcept 500{ 501 if (this != &other) { 502 CORE_ASSERT(manager_ == other.manager_); 503#ifndef NDEBUG 504 CORE_ASSERT((other.rLocked_ == 0U) && !other.wLocked_); 505 rLocked_ = other.rLocked_.exchange(0U); 506 wLocked_ = BASE_NS::exchange(other.wLocked_, false); 507#endif 508 generation_ = BASE_NS::exchange(other.generation_, 0U); 509 entity_ = BASE_NS::exchange(other.entity_, {}); 510 data_ = BASE_NS::exchange(other.data_, {}); 511 } 512 return *this; 513} 514 515template<typename ComponentType, typename BaseClass> 516const IPropertyApi* BaseManager<ComponentType, BaseClass>::BaseComponentHandle::Owner() const 517{ 518 return manager_; 519} 520 521template<typename ComponentType, typename BaseClass> 522size_t BaseManager<ComponentType, BaseClass>::BaseComponentHandle::Size() const 523{ 524 return sizeof(ComponentType); 525} 526 527template<typename ComponentType, typename BaseClass> 528const void* BaseManager<ComponentType, BaseClass>::BaseComponentHandle::RLock() const 529{ 530 CORE_ASSERT(manager_); 531#ifndef NDEBUG 532 CORE_ASSERT(!wLocked_); 533 ++rLocked_; 534#endif 535 return &data_; 536} 537 538template<typename ComponentType, typename BaseClass> 539void BaseManager<ComponentType, BaseClass>::BaseComponentHandle::RUnlock() const 540{ 541 CORE_ASSERT(manager_); 542#ifndef NDEBUG 543 CORE_ASSERT(rLocked_ > 0U); 544 --rLocked_; 545#endif 546} 547 548template<typename ComponentType, typename BaseClass> 549void* BaseManager<ComponentType, BaseClass>::BaseComponentHandle::WLock() 550{ 551 CORE_ASSERT(manager_); 552#ifndef NDEBUG 553 CORE_ASSERT(rLocked_ <= 1U && !wLocked_); 554 wLocked_ = true; 555#endif 556 return &data_; 557} 558 559template<typename ComponentType, typename BaseClass> 560void BaseManager<ComponentType, BaseClass>::BaseComponentHandle::WUnlock() 561{ 562 CORE_ASSERT(manager_); 563#ifndef NDEBUG 564 CORE_ASSERT(wLocked_); 565 wLocked_ = false; 566#endif 567 // update generation etc.. 568 ++generation_; 569 if (EntityUtil::IsValid(entity_)) { 570 dirty_ = true; 571 manager_->Updated(entity_); 572 } 573} 574CORE_END_NAMESPACE() 575