178 lines
5.1 KiB
C++
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};
|
|
};
|