#pragma once #include "engine_api.h" #include "log.hpp" #include #include #include #include #include #include namespace engine { /* forward declarations */ class Scene; class Component { }; struct Transform { // Scale, rotate (XYZ), translate glm::vec3 position{ 0.0f }; glm::quat rotation{}; glm::vec3 scale{ 1.0f }; }; class Object { public: Object(const std::string& name, Object* parent, Scene* scene); Object(const Object&) = delete; Object& operator=(const Object&) = delete; ~Object(); /* methods */ Object* getChild(const std::string& name); std::vector getChildren(); Object* createChild(const std::string& name); bool deleteChild(const std::string& name); void printTree(int level = 0); // Returns the component of type T // Returns nullptr if the component is not found. template T* getComponent(); template T* createComponent(); template bool deleteComponent(); /* public member variables */ const std::string name; Object* const parent; Scene* const scene; Transform transform; private: static int s_next_id; int m_id = s_next_id; // If nullptr, this is the root object std::list> m_children{}; std::list> m_components{}; }; /* implementation of template functions */ template T* Object::getComponent() { for (const auto& component : m_components) { T* derived = dynamic_cast(component.get()); if (derived != nullptr) { return derived; } } return nullptr; } template T* Object::createComponent() { if (std::is_base_of::value == false) { ERROR("Object::createComponent(): attempt to create a component with a non-component class"); return nullptr; } if (getComponent() != nullptr) { ERROR("Object::createComponent(): attempt to create a component that already exists on an object"); return nullptr; } m_components.emplace_back(std::make_unique(this)); return dynamic_cast(m_components.back().get()); } template bool Object::deleteComponent() { for (auto itr = m_components.begin(); itr != m_components.end(); ++itr) { if (dynamic_cast((*itr).get()) != nullptr) { m_components.erase(itr); return true; } } return false; } }