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