Created
October 14, 2022 17:56
-
-
Save Hexlord/c0b40095fac77faf06dc10d7128e6459 to your computer and use it in GitHub Desktop.
cref implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This class is at least 32 bytes long. | |
template<typename... Ts> | |
class cref { | |
public: | |
using TPrimaryType = Meta::TParameterPackFirstType<Ts...>; | |
cref() { | |
Clear(); | |
} | |
cref(entity_view InEntity) { | |
WorldPtr = (ecs_world_t *)ecs_get_world(InEntity.world().c_ptr()); | |
EntityId = InEntity.id(); | |
Record = ecs_record_find(WorldPtr, EntityId); | |
TableRecords = Array::RepeatStatic<ecs_table_record_t *, sizeof...(Ts)>(nullptr); | |
#if SE_VERBOSE_DEBUG | |
ECSIndex = Impl::ECSMeta.Index; | |
#endif | |
} | |
cref(const cref &Other) { | |
WorldPtr = Other.WorldPtr; | |
EntityId = Other.EntityId; | |
Record = Other.Record; | |
TableRecords = Other.TableRecords; | |
#if SE_VERBOSE_DEBUG | |
ECSIndex = Other.ECSIndex; | |
#endif | |
} | |
cref &operator=(entity_view InEntity) { | |
var NewWorldPtr = (ecs_world_t *)ecs_get_world(InEntity.world().c_ptr()); | |
if(!WorldPtr || EntityId != InEntity.id()) { | |
WorldPtr = NewWorldPtr; | |
EntityId = InEntity.id(); | |
Record = ecs_record_find(WorldPtr, EntityId); | |
#if SE_VERBOSE_DEBUG | |
ECSIndex = Impl::ECSMeta.Index; | |
#endif | |
} else { | |
VerboseCheckf(ECSIndex == Impl::ECSMeta.Index, "Ref persisted from another world"); | |
} | |
return *this; | |
} | |
cref &operator=(const cref &Other) { | |
WorldPtr = Other.WorldPtr; | |
EntityId = Other.EntityId; | |
Record = Other.Record; | |
TableRecords = Other.TableRecords; | |
#if SE_VERBOSE_DEBUG | |
ECSIndex = Other.ECSIndex; | |
#endif | |
return *this; | |
} | |
static cref FormKey(entity_id InEntityId) { | |
cref<Ts...> Result; | |
Result.EntityId = InEntityId; | |
return Result; | |
} | |
bool operator==(const cref &Other) const { | |
return EntityId == Other.EntityId; | |
} | |
bool operator!=(const cref &Other) const { | |
return !operator==(Other); | |
} | |
template<typename T> | |
requires(Meta::ParameterPackContains<T, Ts...>) | |
operator const T *() const { | |
if(!WorldPtr) { | |
return nullptr; | |
} | |
VerboseCheckf(ECSIndex == Impl::ECSMeta.Index, "Ref persisted from another world"); | |
Impl::AssertNoMutations(); | |
var ECS = ecs(WorldPtr); | |
var Component = SE::Component<T>(); | |
AssertReadAccess(EntityId, Component); | |
return (T *)ecs_record_get_mut_cached_id(WorldPtr, Record, Component, &TableRecords[Meta::ParameterPackTypeIndex<T, Ts...>]); | |
} | |
template<typename T> | |
requires(Meta::ParameterPackContains<T, Ts...>) | |
operator T *() const { | |
if(!WorldPtr) { | |
return nullptr; | |
} | |
VerboseCheckf(ECSIndex == Impl::ECSMeta.Index, "Ref persisted from another world"); | |
Impl::AssertNoMutations(); | |
var ECS = ecs(WorldPtr); | |
var Component = SE::Component<T>(); | |
if constexpr(Meta::IsConst<T>) { | |
AssertReadAccess(EntityId, Component); | |
} else { | |
AssertWriteAccess(EntityId, Component); | |
} | |
return (T *)ecs_record_get_mut_cached_id(WorldPtr, Record, Component, &TableRecords[Meta::ParameterPackTypeIndex<T, Ts...>]); | |
} | |
TPrimaryType *operator*() const { | |
return operator TPrimaryType *(); | |
} | |
TPrimaryType *operator->() const { | |
if(!WorldPtr) { | |
return nullptr; | |
} | |
VerboseCheckf(ECSIndex == Impl::ECSMeta.Index, "Ref persisted from another world"); | |
var ECS = ecs(WorldPtr); | |
var Component = SE::Component<TPrimaryType>(); | |
if constexpr(Meta::IsConst<TPrimaryType>) { | |
AssertReadAccess(EntityId, Component); | |
} else { | |
AssertWriteAccess(EntityId, Component); | |
} | |
return (TPrimaryType *)ecs_record_get_mut_cached_id(WorldPtr, Record, Component, &TableRecords.First()); | |
} | |
entity_view entity() const { | |
VerboseCheckf(!WorldPtr || ECSIndex == Impl::ECSMeta.Index, "Ref persisted from another world"); | |
return flecs::entity_view(WorldPtr, EntityId); | |
} | |
operator entity_view() const { | |
VerboseCheckf(!WorldPtr || ECSIndex == Impl::ECSMeta.Index, "Ref persisted from another world"); | |
return flecs::entity_view(WorldPtr, EntityId); | |
} | |
void Clear() { | |
WorldPtr = nullptr; | |
EntityId = 0; | |
Record = nullptr; | |
TableRecords = Array::RepeatStatic<ecs_table_record_t *, sizeof...(Ts)>(nullptr); | |
#if SE_VERBOSE_DEBUG | |
ECSIndex = 0u; | |
#endif | |
} | |
hash ComputeHash() const { | |
return EntityId; | |
} | |
flecs::world_t *WorldPtr; | |
entity_id EntityId; | |
ecs_record_t *Record; | |
mutable TStaticArray<ecs_table_record_t *, sizeof...(Ts)> TableRecords; | |
private: | |
#if SE_VERBOSE_DEBUG | |
uint32 ECSIndex; | |
#endif | |
void AssertReadAccess(entity_id Entity, entity_id Id) const { | |
if constexpr(SE_VERBOSE_DEBUG) { | |
if(Entity) { | |
Impl::Mutations.AssertArbitraryReadAccess(entity_view(WorldPtr, Entity), Id); | |
} | |
} | |
} | |
void AssertWriteAccess(entity_id Entity, entity_id Id) const { | |
if constexpr(SE_VERBOSE_DEBUG) { | |
if(Entity) { | |
Impl::Mutations.AssertArbitraryWriteAccess(entity_view(WorldPtr, Entity), Id); | |
} | |
} | |
} | |
}; | |
template<typename... Ts> | |
inline bool IsSet(const cref<Ts...> &Ref) { | |
return Ref.WorldPtr; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment