farmlands/src/model/GameObject.cpp

338 lines
6.1 KiB
C++

/*
* GameObject.cpp
*
* Created on: Nov 30, 2016
* Author: tibi
*/
#include <GameState.h>
#include <model/GameObject.h>
#include <model/Component.h>
#include <model/Transform.h>
#include <iostream>
namespace farmlands {
namespace model {
GameObject::GameObject()
: name("unnamed"),
visible(true),
transform(this),
m_components(),
m_children(),
m_parent(nullptr),
m_enabled(false)
{
}
GameObject* GameObject::clone()
{
GameObject* clone = new GameObject();
clone->visible = visible;
// Clone components
for (auto pair : m_components)
{
Component* compClone = pair.second->clone();
compClone->gameObject = clone;
clone->m_components.emplace(pair.first, compClone);
}
// Clone components
for (auto child : m_children)
clone->addChild(child->clone());
return clone;
}
GameObject::~GameObject()
{
// Delete children
for (auto child : m_children)
{
child->onDestroy();
delete child;
}
// Delete components
for (auto pair : m_components)
{
pair.second->onDestroy();
delete pair.second;
}
}
GameObject* GameObject::instantiate(GameObject* gameObject, std::string name, GameObject* parent)
{
Assert(gameObject != nullptr, "Can't instantiate a null object!");
Assert(parent != nullptr, "Parent cannot be null!");
// Clone object
GameObject* instance = gameObject->clone();
instance->name = name;
parent->addChild(instance);
// Call methods
instance->onCreate();
if (GameState::current().gameInitialized)
instance->onInitialize();
return instance;
}
size_t GameObject::componentsSize() const
{
return m_components.size();
}
GameObject::ComponentIterator GameObject::componentsBegin()
{
return m_components.begin();
}
GameObject::ComponentIterator GameObject::componentsEnd()
{
return m_components.end();
}
void GameObject::addChild(GameObject* obj)
{
m_children.push_back(obj);
obj->m_parent = this;
}
GameObject* GameObject::removeChild(GameObject::ChildrenIterator it)
{
m_children.erase(it);
return *it;
}
GameObject* GameObject::removeChild(GameObject* obj)
{
for (auto it = m_children.begin(); it != m_children.end(); it++)
{
if (*it == obj)
{
m_children.erase(it);
obj->m_parent = nullptr;
return *it;
}
}
return nullptr;
}
void GameObject::destroyChild(GameObject::ChildrenIterator it)
{
delete *it;
m_children.erase(it);
}
void GameObject::destroyChild(GameObject* obj)
{
for (auto it = m_children.begin(); it != m_children.end(); it++)
{
if (*it == obj)
{
delete *it;
m_children.erase(it);
return;
}
}
}
size_t GameObject::childrenSize() const
{
return m_children.size();
}
GameObject::ChildrenIterator GameObject::childrenBegin()
{
return m_children.begin();
}
GameObject::ChildrenIterator GameObject::childrenEnd()
{
return m_children.end();
}
GameObject* GameObject::parent()
{
return m_parent;
}
GameObject::ChildrenIterator GameObject::findByName(std::string name)
{
return findByName(name, childrenBegin());
}
GameObject::ChildrenIterator GameObject::findByName(std::string name, ChildrenIterator begin)
{
for (auto it = begin; it != childrenEnd(); it++)
if ((*it)->name == name)
return it;
return childrenEnd();
}
void GameObject::onCreate()
{
// Enable self
setEnabled(true);
// Call components
for (auto pair : m_components)
pair.second->onCreate();
// Call children
for (auto child : m_children)
child->onCreate();
}
void GameObject::onInitialize()
{
// Call components
for (auto pair : m_components)
pair.second->onInitialize();
// Call children
for (auto child : m_children)
child->onInitialize();
}
bool GameObject::onEvent(SDL_Event& event)
{
bool handled = false;
// Call components
for (auto it = m_components.begin(); it != m_components.end() && !handled; it++)
handled = it->second->onEvent(event);
// Call children
for (auto it = m_children.begin(); it != m_children.end() && !handled; it++)
if ((*it)->m_enabled)
handled = (*it)->onEvent(event);
return handled;
}
void GameObject::onUpdateLogic()
{
// Call components
for (auto pair : m_components)
pair.second->onUpdateLogic();
// Call children
for (auto child : m_children)
if (child->m_enabled)
child->onUpdateLogic();
}
void GameObject::onPreRender()
{
// Call components
for (auto pair : m_components)
pair.second->onPreRender();
// Call children
for (auto child : m_children)
if (child->m_enabled && child->visible)
child->onPreRender();
}
void GameObject::onRender()
{
// Call components
for (auto pair : m_components)
pair.second->onRender();
// Call children
for (auto child : m_children)
if (child->m_enabled && child->visible)
child->onRender();
}
void GameObject::onPostRender()
{
// Call components
for (auto pair : m_components)
pair.second->onPostRender();
// Call children
for (auto child : m_children)
if (child->m_enabled && child->visible)
child->onPostRender();
}
void GameObject::onEnable()
{
// Call components
for (auto pair : m_components)
pair.second->onEnable();
// Call children
for (auto child : m_children)
if (child->enabled())
child->onEnable();
}
void GameObject::onDisable()
{
// Call components
for (auto pair : m_components)
pair.second->onDisable();
// Call children
for (auto child : m_children)
if (child->enabled())
child->onDisable();
}
void GameObject::onDestroy()
{
// Don't call onDestroy on children/components
// because it will be called in the destructor
}
void GameObject::setEnabled(bool enabled)
{
// Don't set again
if (m_enabled == enabled)
return;
m_enabled = enabled;
// If parent is disabled, we are disabled
if (m_parent == nullptr || m_parent->enabled())
{
// Call onEnable/onDisable
if (enabled) onEnable();
else onDisable();
}
}
void GameObject::dumpTree(unsigned level)
{
// Print spaces
for (unsigned i = 0; i < level; i++)
std::cout<<" ";
// Game object info
std::cout << "* GameObject: " << name << "[";
std::cout << ((m_enabled) ? "e" : " ") << "][";
std::cout << ((visible) ? "v" : " ") << "]\n";
// Components
for (auto component : m_components)
component.second->dump(level);
for (auto child : m_children)
child->dumpTree(level + 1);
}
} /* namespace model */
} /* namespace farmlands */