Files
Destrum/destrum/include/destrum/ObjectModel/GameObject.h
T

178 lines
5.1 KiB
C++

#pragma once
#include <memory>
#include <vector>
#include <algorithm>
#include <destrum/ObjectModel/Component.h>
#include <destrum/ObjectModel/Object.h>
#include <destrum/ObjectModel/ObjectId.h>
#include <destrum/ObjectModel/Transform.h>
class Scene;
class SceneSerializer;
class GameObject final : public Object {
public:
friend class Scene;
friend class SceneSerializer;
friend class Transform;
void Update(float dt);
void LateUpdate(float dt);
void FixedUpdate(float fixedDt);
void Render(const RenderContext& ctx) const;
void Destroy() override;
void CleanupComponents();
void RefreshPhysics();
void RefreshPhysicsInHierarchy();
void SetActive(bool active) {
if (active == m_Active) {
return;
}
m_Active = active;
SetActiveDirty();
RefreshPhysicsInHierarchy();
}
[[nodiscard]] bool IsActive() const { return m_Active; }
[[nodiscard]] ObjectId GetId() const { return m_Id; }
// Use this only while loading a scene.
void SetIdForDeserialization(ObjectId id);
[[nodiscard]] Scene* GetScene() const { return m_Scene; }
[[nodiscard]] std::vector<std::unique_ptr<Component>>& GetComponents() {
return m_Components;
}
[[nodiscard]] const std::vector<std::unique_ptr<Component>>& GetComponents() const {
return m_Components;
}
[[nodiscard]] Transform& GetTransform() { return m_TransformPtr; }
[[nodiscard]] const Transform& GetTransform() const { return m_TransformPtr; }
[[nodiscard]] bool IsActiveInHierarchy();
explicit GameObject(const std::string& name = "GameObject");
~GameObject() override;
GameObject(const GameObject& other) = delete;
GameObject(GameObject&& other) = delete;
GameObject& operator=(const GameObject& other) = delete;
GameObject& operator=(GameObject&& other) = delete;
template <typename TComponent, typename... Args>
requires std::derived_from<TComponent, Component> &&
std::constructible_from<TComponent, GameObject&, Args&&...>
TComponent* AddComponent(Args&&... args) {
auto& addedComponent = m_Components.emplace_back(
std::make_unique<TComponent>(*this, std::forward<Args>(args)...));
if (addedComponent->AffectsPhysics()) {
RefreshPhysics();
}
return static_cast<TComponent*>(addedComponent.get());
}
template <typename TComponent>
[[nodiscard]] TComponent* GetComponent() {
for (const auto& component : m_Components) {
if (component != nullptr && !component->IsBeingDestroyed()) {
if (auto casted = dynamic_cast<TComponent*>(component.get())) {
return casted;
}
}
}
return nullptr;
}
template <typename TComponent>
[[nodiscard]] const TComponent* GetComponent() const {
for (const auto& component : m_Components) {
if (component != nullptr && !component->IsBeingDestroyed()) {
if (auto casted = dynamic_cast<const TComponent*>(component.get())) {
return casted;
}
}
}
return nullptr;
}
template <typename TComponent>
TComponent* DestroyComponent() {
for (const auto& component : m_Components) {
if (component != nullptr && !component->IsBeingDestroyed()) {
if (auto casted = dynamic_cast<TComponent*>(component.get())) {
casted->Destroy();
return casted;
}
}
}
return nullptr;
}
template <typename TComponent>
[[nodiscard]] bool HasComponent() const {
for (const auto& component : m_Components) {
if (component != nullptr && !component->IsBeingDestroyed() &&
dynamic_cast<TComponent*>(component.get())) {
return true;
}
}
return false;
}
template <typename TComponent>
TComponent* GetComponentInChildren() {
return GetComponentInChildrenRecursive<TComponent>(&GetTransform());
}
private:
template <typename TComponent>
static TComponent* GetComponentInChildrenRecursive(Transform* transform) {
if (!transform) return nullptr;
GameObject* owner = transform->GetOwner();
if (owner) {
if (TComponent* comp = owner->GetComponent<TComponent>()) {
return comp;
}
}
for (Transform* child : transform->GetChildren()) {
if (TComponent* found = GetComponentInChildrenRecursive<TComponent>(child)) {
return found;
}
}
return nullptr;
}
void SetScene(Scene* scene) { m_Scene = scene; }
void SetActiveDirty();
void UpdateActiveState();
static ObjectId AllocateId();
inline static ObjectId s_NextId{1};
ObjectId m_Id{InvalidObjectId};
bool m_Active{true};
Scene* m_Scene{};
Transform m_TransformPtr{this};
std::vector<std::unique_ptr<Component>> m_Components{};
bool m_ActiveDirty{true};
bool m_ActiveInHierarchy{true};
};