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