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-11-30 00:46:03 +00:00
|
|
|
#include "log.hpp"
|
2022-09-04 00:31:10 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
#include <glm/mat4x4.hpp>
|
|
|
|
#include <glm/gtc/quaternion.hpp>
|
2022-10-27 22:06:56 +00:00
|
|
|
|
2022-09-02 11:06:59 +00:00
|
|
|
#include <list>
|
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
|
|
|
#include <memory>
|
|
|
|
|
2022-10-02 15:34:51 +00:00
|
|
|
namespace engine {
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
/* forward declarations */
|
|
|
|
class Scene;
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
class Component {
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
};
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
struct Transform {
|
|
|
|
// Scale, rotate (XYZ), translate
|
|
|
|
glm::vec3 position{ 0.0f };
|
|
|
|
glm::quat rotation{};
|
|
|
|
glm::vec3 scale{ 1.0f };
|
|
|
|
};
|
2022-10-27 16:58:30 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
class Object {
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
public:
|
|
|
|
Object(const std::string& name, Object* parent, Scene* scene);
|
|
|
|
Object(const Object&) = delete;
|
|
|
|
Object& operator=(const Object&) = delete;
|
|
|
|
~Object();
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
/* methods */
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
Object* getChild(const std::string& name);
|
2022-10-06 10:30:44 +00:00
|
|
|
std::vector<Object*> getChildren();
|
2022-11-30 00:46:03 +00:00
|
|
|
Object* createChild(const std::string& name);
|
|
|
|
bool deleteChild(const 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();
|
|
|
|
template<class T> T* createComponent();
|
2022-11-30 00:46:03 +00:00
|
|
|
template<class T> bool deleteComponent();
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
/* public member variables */
|
2022-09-04 00:31:10 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
const std::string name;
|
|
|
|
|
|
|
|
Object* const parent;
|
|
|
|
Scene* const scene;
|
2022-09-04 00:31:10 +00:00
|
|
|
|
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:
|
2022-11-30 00:46:03 +00:00
|
|
|
static int s_next_id;
|
|
|
|
int m_id = s_next_id;
|
2022-09-02 11:06:59 +00:00
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
// If nullptr, this is the root object
|
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
|
|
|
};
|
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
/* implementation of template functions */
|
2022-10-06 10:30:44 +00:00
|
|
|
|
|
|
|
template<class T> T* Object::getComponent()
|
|
|
|
{
|
|
|
|
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) {
|
2022-11-30 00:46:03 +00:00
|
|
|
ERROR("Object::createComponent(): attempt to create a component with a non-component class");
|
|
|
|
return nullptr;
|
2022-10-06 10:30:44 +00:00
|
|
|
}
|
|
|
|
if (getComponent<T>() != nullptr) {
|
2022-11-30 00:46:03 +00:00
|
|
|
ERROR("Object::createComponent(): attempt to create a component that already exists on an object");
|
|
|
|
return nullptr;
|
2022-10-06 10:30:44 +00:00
|
|
|
}
|
|
|
|
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
|
|
|
|
2022-11-30 00:46:03 +00:00
|
|
|
template<class T> bool Object::deleteComponent()
|
2022-10-06 10:30:44 +00:00
|
|
|
{
|
|
|
|
for (auto itr = m_components.begin(); itr != m_components.end(); ++itr) {
|
|
|
|
if (dynamic_cast<T*>((*itr).get()) != nullptr) {
|
|
|
|
m_components.erase(itr);
|
2022-11-30 00:46:03 +00:00
|
|
|
return true;
|
2022-10-06 10:30:44 +00:00
|
|
|
}
|
2022-09-02 11:06:59 +00:00
|
|
|
}
|
2022-11-30 00:46:03 +00:00
|
|
|
return false;
|
2022-09-02 11:06:59 +00:00
|
|
|
}
|
2022-10-06 10:30:44 +00:00
|
|
|
|
2022-10-27 22:06:56 +00:00
|
|
|
}
|