BubbleBobbleRemake / DuvelEngine / GameObject.h
GameObject.h
Raw
#pragma once
#include <memory>
#include "Transform.h"
#include "Component.h"
#include <vector>
#include <string>

namespace dae
{
	class Texture2D;

	class GameObject final
	{
	public:
		virtual void Update(float deltaTime);
		virtual void FixedUpdate(float deltaTime);
		virtual void LateUpdate(float deltaTime);
		virtual void Render() const;

		void Destroy(float delay)
		{
			if (delay == 0)
			{
				Destroy();
				return;
			}

			m_DestroyDelayDuration = delay;
		}

		void Destroy()
		{
			m_IsMarkedForDeletion = true;

			for (const auto& pChild : m_pChildren)
			{
				pChild->Destroy();
			}
		}

		template <typename T>
		T* AddComponent(T* pComp);

		template <typename T>
		T* GetComponent();

		template <typename T>
		bool RemoveComponent();

		GameObject* GetParent() const { return m_pParent; };
		GameObject* GetRootGameObject()
		{
			if (m_pParent == nullptr)
			{
				return reinterpret_cast<dae::GameObject*>(this);
			}

			return m_pParent->GetRootGameObject();
		}

		bool RemoveChild(GameObject* pChild);

		void SetDirty(bool isDirty);

		bool IsMarkedForDeletion() const
		{
			return m_IsMarkedForDeletion;
		}

		void SetActive(bool isActive)
		{
			m_IsActive = isActive;
			for (auto& pChild : m_pChildren)
			{
				pChild->SetActive(isActive);
			}
		}

		std::vector<std::shared_ptr<GameObject>>& GetChildren() { return m_pChildren; }

		bool IsActive() { return m_IsActive; }

		void SetPosition(float x, float y);
		glm::vec3 GetPosition() const;
		glm::vec3 GetWorldPosition();

		const std::string& GetName() const
		{
			return m_Name;
		}

		void SetParent(GameObject* pParent);

		void SetName(const std::string& name) { m_Name = name; }

		GameObject() = default;
		virtual ~GameObject();
		GameObject(const GameObject& other) = delete;
		GameObject(GameObject&& other) = delete;
		GameObject& operator=(const GameObject& other) = delete;
		GameObject& operator=(GameObject&& other) = delete;

		void HandleChangeParent();

	private:

		std::string m_Name{ "" };

		bool m_IsActive{ true };
		bool m_IsMarkedForDeletion{ false };

		Transform m_Transform{};
		std::vector<Component*> m_pComponents;

		GameObject* m_pParent = nullptr;
		std::vector<std::shared_ptr<GameObject>> m_pChildren;
		std::vector<std::pair<GameObject*, GameObject*>> m_pOldParentFutureParent;

		void AddChild(GameObject* pChild);

		float m_DestroyDelayDuration{ 0 };
		float m_DestroyTimer{ 0 };
	};

	template <typename T>
	T* GameObject::AddComponent(T* pComp)
	{
		pComp->InitializeGameObject(this);
		pComp->Initialize();
		m_pComponents.push_back(pComp);

		return pComp;
	}

	template<typename T>
	inline T* GameObject::GetComponent()
	{
		//const type_info& typeInfo = typeid(T);
		auto it = std::find_if(m_pComponents.begin(), m_pComponents.end(), [](Component* pComp)	{
			return dynamic_cast<T*>(pComp) != nullptr; //return typeid(*pComp) == typeInfo;
		});

		if (it != m_pComponents.end()) return dynamic_cast<T*>(*it);

		return nullptr;
	}

	template<typename T>
	bool GameObject::RemoveComponent()
	{
		//const type_info& typeInfo = typeid(T);
		auto it = std::find_if(m_pComponents.begin(), m_pComponents.end(), [](Component* pComp)	{
			return dynamic_cast<T*>(pComp) != nullptr; //return typeid(*pComp) == typeInfo;
		});

		if (it != m_pComponents.end())
		{
			delete *it;
			m_pComponents.erase(it);

			return true;
		}
		
		return false;
	}
}