BubbleBobbleRemake / DuvelEngine / GameObject.cpp
GameObject.cpp
Raw
#include <string>
#include "GameObject.h"
#include "ResourceManager.h"
#include "Renderer.h"
#include <iostream>

#include "Scene.h"

dae::GameObject::~GameObject()
{
	for (auto& pComp : m_pComponents)
	{
		delete pComp;
		pComp = nullptr;
	}

	//std::cout << "bye bye\n";
};

void dae::GameObject::Update(float deltaTime)
{
	if (m_DestroyDelayDuration > 0)
	{
		m_DestroyTimer += deltaTime;
		if (m_DestroyTimer >= m_DestroyDelayDuration) Destroy();
	}

	if (!m_IsActive || m_IsMarkedForDeletion)
		return;

	for (auto& pComp : m_pComponents)
	{
		pComp->Update(deltaTime);
	}

	for (auto& pChild : m_pChildren)
	{
		pChild->Update(deltaTime);
	}
}

void dae::GameObject::FixedUpdate(float deltaTime)
{
	if (!m_IsActive || m_IsMarkedForDeletion)
		return;

	for (auto& pComp : m_pComponents)
	{
		pComp->FixedUpdate(deltaTime);
	}

	for (auto& pChild : m_pChildren)
	{
		pChild->FixedUpdate(deltaTime);
	}
}

void dae::GameObject::LateUpdate(float deltaTime)
{
	if (!m_IsActive || m_IsMarkedForDeletion)
		return;

	for (auto& pComp : m_pComponents)
	{
		pComp->LateUpdate(deltaTime);
	}

	for (auto& pChild : m_pChildren)
	{
		pChild->LateUpdate(deltaTime);
	}
}

void dae::GameObject::Render() const
{
	if (!m_IsActive || m_IsMarkedForDeletion)
		return;

	for (auto& pComp : m_pComponents)
	{
		pComp->Render();
	}

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

void dae::GameObject::SetParent(GameObject* pNewParent)
{
	if (pNewParent == nullptr)
	{
		pNewParent = SceneManager::GetInstance().GetActiveScene()->GetRootGameObject();
	}

	if (m_pParent != nullptr)
	{
		auto it = std::find_if(m_pParent->m_pChildren.begin(), m_pParent->m_pChildren.end(), [this](std::shared_ptr<GameObject> pCurrentChild) {
			return this == pCurrentChild.get();
		});

		if (it != m_pParent->m_pChildren.end())
		{
			m_pOldParentFutureParent.push_back(std::make_pair(m_pParent, pNewParent));
		}
	}
	else
	{
		m_pParent = pNewParent;

		m_pParent->AddChild(this);

		SetActive(m_pParent->m_IsActive);
		SetDirty(true);
	}
}

void dae::GameObject::HandleChangeParent()
{
	for (auto& oldParentFutureParent : m_pOldParentFutureParent)
	{
		GameObject* pOldParent = oldParentFutureParent.first;
		GameObject* pFutureParent = oldParentFutureParent.second;

		auto it = std::find_if(pOldParent->m_pChildren.begin(), pOldParent->m_pChildren.end(), [this](std::shared_ptr<GameObject> pCurrentChild) {
			return this == pCurrentChild.get();
		});

		if (it != pOldParent->m_pChildren.end())
		{
			if (pFutureParent == nullptr)
			{
				m_pParent = pOldParent->GetRootGameObject();
			}
			else
			{
				m_pParent = pFutureParent;
			}

			// move the shared pointer from the old parent to the new parent
			int idx = static_cast<int>(std::distance(pOldParent->m_pChildren.begin(), it));
			m_pParent->m_pChildren.push_back(std::move(pOldParent->m_pChildren[idx]));

			SetActive(m_pParent->IsActive());
			SetDirty(true);

			// Move all null pointers to the end of the container & resize to remove the null pointers
			auto newEnd = std::remove(pOldParent->m_pChildren.begin(), pOldParent->m_pChildren.end(), nullptr);
			pOldParent->m_pChildren.resize(std::distance(pOldParent->m_pChildren.begin(), newEnd));
		}
	}

	m_pOldParentFutureParent.clear();
}

void dae::GameObject::AddChild(GameObject* pChild)
{
	std::shared_ptr<GameObject> pThisShared(pChild);
	m_pChildren.emplace_back(pThisShared);
}

bool dae::GameObject::RemoveChild(GameObject* pChild)
{
	auto it = std::find_if(m_pChildren.begin(), m_pChildren.end(), [&pChild](std::shared_ptr<GameObject> pCurrentChild) {
		return pChild == pCurrentChild.get();
	});

	if (it != m_pChildren.end())
	{
		m_pChildren.erase(it);
		return true;
	}

	//else - child not find in parent
	return false;
}

void dae::GameObject::SetDirty(bool isDirty)
{
	m_Transform.SetDirty(isDirty);
}

void dae::GameObject::SetPosition(float x, float y)
{
	m_Transform.SetPosition(x, y, 0.0f);

	for (auto& pChild : m_pChildren)
	{
		pChild->SetDirty(true);
	}
}

glm::vec3 dae::GameObject::GetPosition() const
{
	return m_Transform.GetPosition();
}

glm::vec3 dae::GameObject::GetWorldPosition()
{
	if (m_Transform.IsDirty())
	{
		m_Transform.SetDirty(false);
		if (m_pParent != nullptr)
		{
			m_Transform.SetCachedPosition(m_pParent->GetWorldPosition());
			return m_Transform.GetCachedPosition() + GetPosition();
		}
		else
		{
			return GetPosition();
		}
	}
	else //if not dirty
	{
		if (m_pParent != nullptr)
		{
			return m_Transform.GetCachedPosition() + GetPosition();
		}
		else
		{
			return GetPosition();
		}
	}
}