Skip to content

Instantly share code, notes, and snippets.

@Daikalos
Last active May 21, 2025 06:34
Show Gist options
  • Select an option

  • Save Daikalos/62fcd447a113aab40bde9ec544f852f5 to your computer and use it in GitHub Desktop.

Select an option

Save Daikalos/62fcd447a113aab40bde9ec544f852f5 to your computer and use it in GitHub Desktop.
Example headers for some classes in the component system module
class Component : protected ISerializable
{
public:
Component();
virtual ~Component();
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponent() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponentInChildren() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponentInParent() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC bool HasComponent() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
ComWeakRef<T> AddComponent();
template<typename T> requires (std::is_base_of_v<Component, T>)
bool RemoveComponent();
NODISC virtual const Entity& GetEntity() const;
NODISC virtual Entity& GetEntity();
NODISC bool HasEntity() const;
NODISC const std::string& GetEntityName() const;
NODISC const EntityID& GetEntityID() const;
NODISC const std::string& GetEntityLabel() const;
NODISC const EntityAdmin& GetEntityAdmin() const;
NODISC EntityAdmin& GetEntityAdmin();
NODISC const Scene& GetScene() const;
NODISC Scene& GetScene();
NODISC ComponentID GetID() const noexcept;
NODISC virtual bool IsEnabled() const;
NODISC virtual bool IsInitialized() const;
NODISC const cu::Mat4f& GetMatrix() const;
NODISC const cu::Mat4f& GetInverseMatrix() const;
NODISC const cu::Mat4f& GetLocalMatrix() const;
NODISC const cu::Mat4f& GetLocalInverseMatrix() const;
NODISC const cu::Vector3f& GetPosition() const;
NODISC const cu::Quatf& GetRotation() const;
NODISC const cu::Vector3f& GetScale() const;
NODISC const cu::Vector3f& GetLocalPosition() const;
NODISC const cu::Quatf& GetLocalRotation() const;
NODISC const cu::Vector3f& GetLocalScale() const;
NODISC bool IsPendingAdd() const;
NODISC bool IsPendingRemove() const;
NODISC bool IsMarkedForSave() const;
void SetEnabled(bool aFlag);
void Destroy();
void SetPosition(const cu::Vector3f& aPosition, bool aMovePhysicsActor = true);
void SetRotation(const cu::Quatf& aRotation);
void SetRotationDeg(const cu::Vector3f& aRotation);
void SetScale(const cu::Vector3f& aScale);
void Move(const cu::Vector3f& aDelta);
void Rotate(const cu::Vector3f& aRotation);
void RotateDeg(const cu::Vector3f& aRotation);
void Scale(const cu::Vector3f& aScale);
void SetLocalPosition(const cu::Vector3f& aPosition);
void SetLocalRotation(const cu::Quatf& aRotation);
void SetLocalRotationDeg(const cu::Vector3f& aRotation);
void SetLocalScale(const cu::Vector3f& aScale);
template<class T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> ToWeakRefType() const;
protected:
// Gets called when the component is added to the entity.
virtual void Init();
// Gets called by the scene loader to serialize members
virtual void FromJson(const nlohmann::json& aObject);
// Gets called when all components on an entity have been initialized.
virtual void Awake();
// Gets called after all components on an entity have had Awake() called.
virtual void Start();
virtual void PreUpdate(cu::Timer& aTimer);
virtual void FixedUpdate(cu::Timer& aTimer);
virtual void Update(cu::Timer& aTimer);
virtual void LateUpdate(cu::Timer& aTimer);
virtual void Debug();
// Gets called for each camera to render stuff
virtual void Render();
// Gets called when component or the entity holding the component is destroyed
virtual void OnDestroy();
// Gets called after Awake and before Start if recently added, otherwise is called when SetEnabled is used
virtual void OnEnable();
// Gets called before OnDestroy is called, otherwise is called when SetEnabled is used
virtual void OnDisable();
// Gets called when component is duplicated, aOriginalComponent can be static cast to derived type
virtual void OnDuplicate(const Component& aOriginalComponent);
// Gets called when stuff wants to get saved
virtual void OnSave(nlohmann::json& nlohmann_json_j) const;
// Gets called when stuff wants to get loaded
virtual void OnLoad(const nlohmann::json& nlohmann_json_j);
virtual void OnTransformUpdate() const;
private:
NODISC ComWeakRef<Component> GetComponent(ComponentID aComponentID) const;
NODISC ComWeakRef<Component> GetComponentInChildren(ComponentID aComponentID) const;
NODISC ComWeakRef<Component> GetComponentInParent(ComponentID aComponentID) const;
NODISC bool HasComponent(ComponentID aComponentID);
NODISC ComWeakRef<Component> AddComponent(ComponentID aComponentID);
bool RemoveComponent(ComponentID aComponentID);
void Serialize(nlohmann::json& aObject) const override;
void Deserialize(const nlohmann::json& aObject) override;
NODISC const ComRef* GetRef() const;
void SaveEnabledState();
void CheckEnabledState();
Entity* myParent {nullptr};
ComponentID myID {0};
bool myIsEnabled {true};
bool myPrevEnabled {false}; // used only by entity to check if to enable or disable
bool myPendingAdd {true};
bool myPendingRemove {false};
bool myShouldBeSaved {false};
friend class ComponentManager;
friend class Entity;
friend class EntityAdmin;
friend class SceneHandle;
friend class SaveHandle;
friend class LoadHandle;
template<class T> requires (std::is_base_of_v<Component, T>)
friend class ComponentPool;
template<class T>
friend class ComponentHelper;
};
template<class T> requires (std::is_base_of_v<Component, T>)
class ComponentPool : public ComponentPoolBase
{
public:
ComponentPool(float aPriority = 0.0f);
NODISC const T& Get(std::size_t aComponentIndex) const override;
NODISC T& Get(std::size_t aComponentIndex) override;
NODISC std::size_t GetVersion(std::size_t aComponentIndex) const override;
NODISC bool EqualVersion(std::size_t aComponentIndex, std::size_t aVersion) const override;
NODISC std::string_view GetComponentName() const override;
NODISC bool IsValid(std::size_t aComponentIndex) const override;
NODISC std::size_t Count() const override;
NODISC bool IsEmpty() const override;
template<typename... Args> requires (std::constructible_from<T, Args...>)
NODISC ComRef CreateWithParams(Args&&... someArgs);
NODISC ComRef Create() override;
void Activate(std::size_t aComponentIndex) override;
bool Deactivate(std::size_t aComponentIndex) override;
bool Recycle(std::size_t aComponentIndex, std::size_t aVersion) override;
template<typename Func>
void Sort(Func&& aFunc);
template<typename Func>
void ForEach(Func&& aFunc);
void PreUpdate(cu::Timer& aTimer) override;
void FixedUpdate(cu::Timer& aTimer) override;
void Update(cu::Timer& aTimer) override;
void LateUpdate(cu::Timer& aTimer) override
void Render() override;
private:
cu::FreeVector<T> myComponents;
std::vector<std::size_t> myVersions;
std::vector<std::size_t> myActiveComponents;
std::vector<std::size_t> myAvailableActive;
static constexpr std::string_view ourComponentName = cu::TypeNameClean<T>();
};
template<class T>
class ComWeakRef
{
public:
ComWeakRef();
~ComWeakRef();
template<class U> requires std::derived_from<U, T>
ComWeakRef(const ComWeakRef<U>& aDerived)
: myIndex(aDerived.myIndex)
, myVersion(aDerived.myVersion)
, myOwner(aDerived.myOwner) {}
template<class U> requires std::derived_from<U, T>
NODISC ComWeakRef<U> SafeCast() const;
template<class U>
NODISC ComWeakRef<U> UnsafeCast() const;
NODISC std::size_t GetIndex() const;
NODISC std::size_t GetVersion() const;
NODISC bool IsValid() const;
NODISC const T& Get() const;
NODISC T& Get();
NODISC const T* TryGet() const;
NODISC T* TryGet();
NODISC operator bool() const;
NODISC const T& operator*() const;
NODISC T& operator*();
NODISC const T* operator->() const;
NODISC T* operator->();
NODISC bool operator==(const ComWeakRef& aRight) const;
NODISC bool operator!=(const ComWeakRef& aRight) const;
NODISC bool operator==(const std::nullptr_t& aRight) const;
NODISC bool operator!=(const std::nullptr_t& aRight) const;
void Reset();
private:
ComWeakRef(const ComRef& aComRef);
#ifdef _DEBUG
mutable const T* myDebugComponent {nullptr}; // to quickly view debug information
#endif
std::size_t myIndex;
std::size_t myVersion;
ComponentPoolBase* myOwner = nullptr;
friend class Entity; // only entity & component can create a valid state for this object
friend class Component;
friend class ComponentManager;
template<class U>
friend class ComWeakRef;
};
class Entity : public ISerializable
{
public:
using Parent = Entity*;
using Children = std::vector<Entity*>;
Entity();
Entity(std::string_view aName);
virtual ~Entity();
NODISC bool operator==(const Entity& aRight) const;
NODISC bool operator!=(const Entity& aRight) const;
NODISC operator EntityRef() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponent() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponentWithBase() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponentInChildren() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponentWithBaseInChildren() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponentInParent() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC ComWeakRef<T> GetComponentWithBaseInParent() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC bool HasComponent() const;
template<typename T> requires (std::is_base_of_v<Component, T>)
NODISC bool HasComponentWithBase() const;
template<typename T, typename... Args>
requires (std::is_base_of_v<Component, T> && std::constructible_from<T, Args...>)
ComWeakRef<T> AddComponent(Args&&... someArgs);
template<typename... Ts> requires (std::derived_from<Ts, Component> && ...)
void AddComponents();
template<typename T> requires (std::is_base_of_v<Component, T>)
bool RemoveComponent();
NODISC ComWeakRef<Component> GetComponent(ComponentID aComponentID) const;
NODISC ComWeakRef<Component> GetComponentInChildren(ComponentID aComponentID) const;
NODISC ComWeakRef<Component> GetComponentInParent(ComponentID aComponentID) const;
NODISC bool HasComponent(std::string_view aComponentName) const;
NODISC bool HasComponent(ComponentID aComponentID) const;
ComWeakRef<Component> AddComponent(std::string_view aComponentName);
ComWeakRef<Component> AddComponent(ComponentID aComponentID);
bool RemoveComponent(std::string_view aComponentName);
bool RemoveComponent(ComponentID aComponentID);
void ClearComponents();
Entity& Duplicate(bool aDuplicateChildren = true);
NODISC bool IsComponentsEmpty() const;
NODISC std::size_t ComponentCount() const;
NODISC const std::string& GetName() const noexcept;
NODISC const std::string& GetTag() const noexcept;
NODISC const std::string& GetLabel() const noexcept;
NODISC const std::string& GetGUID() const noexcept;
NODISC const EntityID& GetID() const noexcept;
NODISC float GetLifetime() const noexcept;
NODISC float GetUnscaledLifetime() const noexcept;
NODISC void SetLifetime(float aLifetime, bool aAlsoSetChildren = true);
NODISC void ResetLifetime(bool aAlsoResetChildren = true);
NODISC bool IsAlive() const;
NODISC bool IsPendingDestruction() const;
NODISC bool IsEnabled() const;
NODISC bool IsEnabledSelf() const;
NODISC bool IsInitialized() const;
NODISC bool IsMarkedForSave() const;
NODISC virtual const EntityAdmin& GetEntityAdmin() const;
NODISC virtual EntityAdmin& GetEntityAdmin();
NODISC const Scene& GetScene() const;
NODISC Scene& GetScene();
NODISC virtual EntityRef ToRef() const;
NODISC ActorRef ToActorRef() const;
NODISC bool HasParent() const noexcept;
NODISC bool HasChildren() const noexcept;
NODISC auto GetRoot() const -> const Entity*;
NODISC auto GetParent() const noexcept -> const Parent&;
NODISC auto GetParent() noexcept -> Parent&;
NODISC auto GetChildren() const noexcept -> const Children&;
NODISC bool IsDescendant(const Entity& aEntity) const;
NODISC const Entity* FindParentWithTag(std::string_view aTag) const;
NODISC Entity* FindParentWithTag(std::string_view aTag);
NODISC const Entity* FindChildWithTag(std::string_view aTag) const;
NODISC Entity* FindChildWithTag(std::string_view aTag);
NODISC const cu::Mat4f& GetMatrix() const;
NODISC const cu::Mat4f& GetInverseMatrix() const;
NODISC const cu::Mat4f& GetLocalMatrix() const;
NODISC const cu::Mat4f& GetLocalInverseMatrix() const;
NODISC const cu::Vector3f& GetPosition() const;
NODISC const cu::Quatf& GetRotation() const;
NODISC const cu::Vector3f& GetScale() const;
NODISC const cu::Vector3f& GetLocalPosition() const;
NODISC const cu::Quatf& GetLocalRotation() const;
NODISC const cu::Vector3f& GetLocalScale() const;
NODISC cu::Vector3f LocalToWorld(const cu::Vector3f& aLocalPosition) const;
NODISC cu::Vector3f WorldToLocal(const cu::Vector3f& aWorldPosition) const;
virtual void SetPosition(const cu::Vector3f& aPosition);
virtual void SetRotation(const cu::Quatf& aRotation);
virtual void SetRotationDeg(const cu::Vector3f& aRotation);
virtual void SetScale(const cu::Vector3f& aScale);
virtual void Move(const cu::Vector3f& aDelta);
virtual void Rotate(const cu::Vector3f& aRotation);
virtual void RotateDeg(const cu::Vector3f& aRotation);
virtual void Scale(const cu::Vector3f& aScale);
virtual void SetLocalPosition(const cu::Vector3f& aPosition);
virtual void SetLocalRotation(const cu::Quatf& aRotation);
virtual void SetLocalRotationDeg(const cu::Vector3f& aRotation);
virtual void SetLocalScale(const cu::Vector3f& aScale);
bool SetParent(Entity& aParent, bool aKeepWorldTransform = true);
bool RemoveParent(bool aKeepWorldTransform = true);
bool AddChild(Entity& aChild, bool aChildKeepWorldTransform = true);
bool RemoveChild(Entity& aChild, bool aChildKeepWorldTransform = true);
bool ClearChildren(bool aChildrenKeepWorldTransform = true);
void SetTag(const std::string& aTag);
void SetLabel(const std::string& aLabel);
void Destroy(bool aDestroyChildren = true);
void Destroy(float aDestroyDelay, bool aDestroyChildren = true, bool aRealTime = false);
void SetEnabled(bool aFlag);
void EnableSave(bool aIncludeChildren = true);
protected:
virtual void Init();
virtual void OnDestroy();
virtual void OnSave(nlohmann::json& aObject) const;
virtual void OnLoad(const nlohmann::json& aObject);
/// Attaches child to parent.
///
/// \param Parent: Parent to attach child to
/// \param Child: child to attach to parent
///
static bool Attach(Entity& aParent, Entity& aChild, bool aChildKeepWorldTransform = true);
/// Detaches child from parent.
///
/// \param Parent: Parent to detach child from
/// \param Child: child to detach from parent
///
/// \returns Whether detachment was successful
///
static bool Detach(Entity& aParent, Entity& aChild, bool aChildKeepWorldTransform = true);
void UpdateTransform() const;
void UpdateToLocal() const;
virtual void OnTransformUpdate() const;
std::string myName {"Entity"};
std::string myTag {"Null"};
std::string myLabel {""};
std::string myGUID {""};
EntityID myID {EntityID::NULL_ID};
float myLifetime {0.0f};
float myUnscaledLifetime {0.0f};
float myDestroyDelay {0.0f};
bool myIsAlive {true};
bool myIsPendingDestruction {false};
bool myIsEnabledHierarchy {true};
bool myIsEnabledSelf {true};
bool myUseRealDestroyDelay {false};
Parent myParent {nullptr};
Children myChildren;
cu::Vector3f myLocalPosition;
cu::Quatf myLocalRotation;
cu::Vector3f myLocalScale {1.0f, 1.0f, 1.0f};
mutable cu::Vector3f myPosition;
mutable cu::Quatf myRotation;
mutable cu::Vector3f myScale {1.0f, 1.0f, 1.0f};
mutable cu::Mat4f myLocalMatrix;
mutable cu::Mat4f myLocalInverseMatrix;
mutable cu::Mat4f myMatrix;
mutable cu::Mat4f myInverseMatrix;
mutable bool myUpdateLocalMatrix {true};
mutable bool myUpdateLocalInverseMatrix {true};
mutable bool myUpdateMatrix {true};
mutable bool myUpdateInverseMatrix {true};
mutable bool myUpdatePosition {true};
mutable bool myUpdateRotation {true};
mutable bool myUpdateScale {true};
private:
void Serialize(nlohmann::json& aObject) const override;
void Deserialize(const nlohmann::json& aObject) override;
ComRef& AddComponentImpl(ComRef&& aComRef);
bool RemoveComponentImpl(ComponentID aComponentID);
void DirtyDescendants();
void EnableDescendants();
void DisableDescendants();
std::vector<ComRef> myComponents;
EntityAdmin* myEntityAdmin {nullptr};
bool myShouldBeSaved {false};
friend class EntityAdmin;
friend class Component;
friend class SaveHandle;
friend class LoadHandle;
};
class EntityAdmin final
{
public:
EntityAdmin();
~EntityAdmin();
template<typename T = Entity, typename... Args>
requires (std::is_base_of_v<Entity, T> && std::constructible_from<T, Args...>)
T& AddEntity(Args&&... someArgs);
template<typename T = Entity, typename... Args>
requires (std::is_base_of_v<Entity, T> && std::constructible_from<T, Args...>)
T& AddEntityWithID(EntityID aID, Args&&... someArgs);
template<typename T = Entity, typename... Args>
requires (std::is_base_of_v<Entity, T>&& std::constructible_from<T, Args...>)
T& AddEntityWithGUID(std::string_view aGUID, Args&&... someArgs);
template<typename T = Entity, typename... Args>
requires (std::is_base_of_v<Entity, T> && std::constructible_from<T, Args...>)
T& AddEntity(EntityID aID, std::string_view aGUID, Args&&... someArgs);
template<typename T = Entity> requires (std::is_base_of_v<Entity, T>)
NODISC T* FindEntity(std::string_view aName) const;
template<typename T = Entity> requires (std::is_base_of_v<Entity, T>)
NODISC T* FindEntityWithTag(std::string_view aTag) const;
template<typename T = Entity> requires (std::is_base_of_v<Entity, T>)
NODISC T* FindEntity(EntityID aEntityID) const;
template<typename T = Entity> requires (std::is_base_of_v<Entity, T>)
NODISC T* FindEntityWithGUID(std::string_view aGUID) const;
template<typename T = Entity, typename U>
requires (std::is_base_of_v<Entity, T> && std::is_base_of_v<Component, U>)
void FindEntitiesWithComponent(std::vector<T*>& outEntities) const;
template<typename T> requires (std::is_base_of_v<Component, T>)
bool ExistsEntityWithComponent() const;
NODISC const Entity& GetEntity(std::size_t aIndex) const;
NODISC Entity& GetEntity(std::size_t aIndex);
const Entity* GetRootEntity() const;
Entity* GetRootEntity();
NODISC EntityRef ToRef(const Entity& aEntity) const;
NODISC std::size_t EntityCount() const;
NODISC const Scene& GetScene() const;
NODISC Scene& GetScene();
NODISC bool IsEnabled() const noexcept;
NODISC bool IsInitialized() const noexcept;
NODISC bool IsShutdown() const noexcept;
void SetEnabled(bool aFlag);
void Clear();
private:
using EntityNameMap = std::unordered_multimap<std::size_t, Entity*>;
using EntityGUIDMap = std::unordered_map<std::size_t, Entity*>;
using EntityIDMap = std::unordered_map<EntityID, Entity*, EntityIDHash>;
using EntityPtr = std::unique_ptr<Entity>;
using EntityList = std::vector<EntityPtr>;
void Init();
void Update(cu::Timer& aTimer);
void Shutdown();
void InitEntity(Entity& aEntity, EntityID aID, std::string_view aGUID);
void DestroyEntity(EntityPtr&& aEntity);
void RemovePendingEntities();
NODISC EntityID PeekFreeEntityID() const;
void FindNextFreeEntityID();
void ConsumeEntityID(EntityID aID);
void UpdateTagToEntity(Entity& aEntity, const std::string& aNewTag);
NODISC ActorRef CreateActorRefFromGUID(const std::string& aEntityToRef) const;
NODISC EntityRef CreateEntityRefFromID(const EntityID& aEntityToRef) const;
std::unique_ptr<Entity> myRootObject {nullptr};
EntityList myEntities;
Scene* myScene {nullptr}; // scene this object lives in
bool myEnabled {false};
bool myInitialized {false};
bool myShutdown {false};
std::uint32_t myEntityIndexCounter {1};
std::vector<EntityID> myReusableEntityIDs;
EntityNameMap myNameToEntity;
EntityGUIDMap myGUIDToEntity;
EntityNameMap myTagToEntity;
EntityIDMap myIDToEntity;
mutable std::shared_mutex myMutex;
friend class Entity;
friend class Scene;
friend class World;
friend class SceneHandle;
friend class LoadHandle;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment