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