engine/include/object.hpp

144 lines
3.6 KiB
C++
Raw Normal View History

2022-09-02 11:06:59 +00:00
#pragma once
2022-09-07 09:02:01 +00:00
#include "engine_api.h"
2022-09-02 23:02:09 +00:00
2022-09-02 11:06:59 +00:00
#include <glm/mat4x4.hpp>
#include "transform.hpp"
2022-09-02 11:06:59 +00:00
#include <list>
#include <vector>
#include <string>
#include <memory>
#include <stdexcept>
2022-10-02 15:34:51 +00:00
namespace engine {
class Window;
class Input;
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
class ResourceManager;
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
class SceneRoot;
class Component;
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
namespace components {
class Transform;
class Camera;
class Renderer;
class UI;
class CustomComponent;
}
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
struct GameIO {
engine::Window* const win;
engine::Input* const input;
ResourceManager* const resMan;
};
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
// This object lives until it is deleted by its parent(s) or finally when the "Scene" is destroyed.
// Therefore it is safe to return raw pointers
class ENGINE_API Object {
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
public:
Object(std::string name, Object* parent, SceneRoot& root, struct GameIO things);
Object(const Object&) = delete;
Object& operator=(const Object&) = delete;
~Object();
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
engine::Window& win;
engine::Input& inp;
ResourceManager& res;
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
SceneRoot& root;
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
std::string getName();
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
Object* getParent();
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
Object* getChild(std::string name);
std::vector<Object*> getChildren();
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
Object* createChild(std::string name);
void deleteChild(std::string name);
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
void printTree(int level = 0);
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
// Returns the component of type T
// Returns nullptr if the component is not found.
template<class T> T* getComponent();
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
// returns the component added
template<class T> T* createComponent();
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
template<class T> void deleteComponent();
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
struct CompList {
std::vector<std::pair<components::Camera*, glm::mat4>> cameras;
std::vector<std::pair<components::Renderer*, glm::mat4>> renderers;
std::vector<std::pair<components::UI*, glm::mat4>> uis;
std::vector<std::pair<components::CustomComponent*, glm::mat4>> customs;
};
2022-10-06 10:30:44 +00:00
// Adds to the provided vector all components of this object and of its children recursively.
// Ignores 'Transform'
void getAllSubComponents(struct CompList& compList, glm::mat4 t);
2022-10-06 10:30:44 +00:00
Transform transform;
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
private:
static int s_object_count;
int m_id = s_object_count;
std::string m_name;
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
std::list<std::unique_ptr<Object>> m_children{};
std::list<std::unique_ptr<Component>> m_components{};
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
// If nullptr, this is the root object
Object* const m_parent;
struct GameIO m_gameIO;
2022-09-02 11:06:59 +00:00
2022-10-06 10:30:44 +00:00
};
// implementation of template functions
template<class T> T* Object::getComponent()
{
if (std::is_base_of<Component, T>::value == false) {
throw std::runtime_error("getComponent() error: specified type is not a subclass of 'Component'");
}
for (const auto& component : m_components) {
T* derived = dynamic_cast<T*>(component.get());
if (derived != nullptr) {
return derived;
}
2022-09-02 11:06:59 +00:00
}
2022-10-06 10:30:44 +00:00
return nullptr;
2022-09-02 11:06:59 +00:00
}
2022-10-06 10:30:44 +00:00
template <class T> T* Object::createComponent()
{
if (std::is_base_of<Component, T>::value == false) {
throw std::runtime_error("addComponent() error: specified type is not a subclass of 'Component'");
}
if (getComponent<T>() != nullptr) {
throw std::runtime_error("addComponent() error: attempt to add component of a type already present");
}
m_components.emplace_back(std::make_unique<T>(this));
return dynamic_cast<T*>(m_components.back().get());
2022-09-02 11:06:59 +00:00
}
2022-10-06 10:30:44 +00:00
template<class T> void Object::deleteComponent()
{
if (std::is_base_of<Component, T>::value == false) {
throw std::runtime_error("deleteComponent() error: specified type is not a subclass of 'Component'");
}
for (auto itr = m_components.begin(); itr != m_components.end(); ++itr) {
if (dynamic_cast<T*>((*itr).get()) != nullptr) {
m_components.erase(itr);
return;
}
2022-09-02 11:06:59 +00:00
}
2022-10-06 10:30:44 +00:00
throw std::runtime_error("deleteComponent() error: attempt to delete component that is not present.");
2022-09-02 11:06:59 +00:00
}
2022-10-06 10:30:44 +00:00
}