Move everything into namespace

This commit is contained in:
Bailey Harrison 2022-10-06 11:30:44 +01:00
parent c2ec967a89
commit 81031c9c10
33 changed files with 581 additions and 531 deletions

View File

@ -11,7 +11,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/ext.hpp> #include <glm/ext.hpp>
namespace components { namespace engine::components {
class ENGINE_API Camera : public Component { class ENGINE_API Camera : public Component {

View File

@ -5,42 +5,43 @@
namespace engine { namespace engine {
class Window; class Window;
class Input; class Input;
}
class Object; class Object;
class ResourceManager; class ResourceManager;
class ENGINE_API Component { class ENGINE_API Component {
public: public:
enum class TypeEnum {
TRANSFORM,
CAMERA,
RENDERER,
UI,
CUSTOM,
};
Component(Object* parent, TypeEnum type);
Component(const Component&) = delete;
Component& operator=(const Component&) = delete;
virtual ~Component() = 0;
int getID();
TypeEnum getType();
Object& parent;
protected:
engine::Window& win;
engine::Input& inp;
ResourceManager& res;
private:
static int s_next_component_id;
int m_id = s_next_component_id;
TypeEnum m_type;
enum class TypeEnum {
TRANSFORM,
CAMERA,
RENDERER,
UI,
CUSTOM,
}; };
Component(Object* parent, TypeEnum type); }
Component(const Component&) = delete;
Component& operator=(const Component&) = delete;
virtual ~Component() = 0;
int getID();
TypeEnum getType();
Object& parent;
protected:
engine::Window& win;
engine::Input& inp;
ResourceManager& res;
private:
static int s_next_component_id;
int m_id = s_next_component_id;
TypeEnum m_type;
};

View File

@ -6,7 +6,7 @@
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
namespace components { namespace engine::components {
class ENGINE_API CustomComponent : public Component { class ENGINE_API CustomComponent : public Component {

View File

@ -12,7 +12,7 @@
#include <string> #include <string>
#include <memory> #include <memory>
namespace components { namespace engine::components {
class ENGINE_API Renderer : public Component { class ENGINE_API Renderer : public Component {

View File

@ -9,7 +9,7 @@
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
namespace components { namespace engine::components {
class ENGINE_API UI : public Component { class ENGINE_API UI : public Component {

View File

@ -3,7 +3,7 @@
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
namespace gfx { namespace engine {
enum class ShaderType { enum class ShaderType {
VERTEX, VERTEX,

View File

@ -2,7 +2,7 @@
// Keyboard scancodes, taken from SDL_scancode.h // Keyboard scancodes, taken from SDL_scancode.h
namespace inputs { namespace engine::inputs {
enum class Key : int { enum class Key : int {
UNKNOWN = 0, UNKNOWN = 0,

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
namespace inputs { namespace engine::inputs {
enum class MouseButton : int { enum class MouseButton : int {
M_LEFT, M_LEFT,

View File

@ -15,128 +15,130 @@
namespace engine { namespace engine {
class Window; class Window;
class Input; class Input;
}
class ResourceManager;
class SceneRoot; class ResourceManager;
class Component;
namespace components { class SceneRoot;
class Transform; class Component;
class Camera;
class Renderer;
class UI;
class CustomComponent;
}
struct GameIO { namespace components {
engine::Window * const win; class Transform;
engine::Input * const input; class Camera;
ResourceManager * const resMan; class Renderer;
}; class UI;
class CustomComponent;
}
// This object lives until it is deleted by its parent(s) or finally when the "Scene" is destroyed. struct GameIO {
// Therefore it is safe to return raw pointers engine::Window* const win;
class ENGINE_API Object { engine::Input* const input;
ResourceManager* const resMan;
public:
Object(std::string name, Object* parent, SceneRoot& root, struct GameIO things);
Object(const Object&) = delete;
Object& operator=(const Object&) = delete;
~Object();
engine::Window& win;
engine::Input& inp;
ResourceManager& res;
SceneRoot& root;
std::string getName();
Object* getParent();
Object* getChild(std::string name);
std::vector<Object*> getChildren();
Object* createChild(std::string name);
void deleteChild(std::string name);
void printTree(int level = 0);
// Returns the component of type T
// Returns nullptr if the component is not found.
template<class T> T* getComponent();
// returns the component added
template<class T> T* createComponent();
template<class T> void deleteComponent();
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;
}; };
// 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);
Transform transform; // 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 {
private: public:
static int s_object_count; Object(std::string name, Object* parent, SceneRoot& root, struct GameIO things);
int m_id = s_object_count; Object(const Object&) = delete;
std::string m_name; Object& operator=(const Object&) = delete;
~Object();
std::list<std::unique_ptr<Object>> m_children{}; engine::Window& win;
std::list<std::unique_ptr<Component>> m_components{}; engine::Input& inp;
ResourceManager& res;
// If nullptr, this is the root object SceneRoot& root;
Object* const m_parent;
struct GameIO m_gameIO;
}; std::string getName();
// implementation of template functions Object* getParent();
template<class T> T* Object::getComponent() Object* getChild(std::string name);
{ std::vector<Object*> getChildren();
if (std::is_base_of<Component, T>::value == false) {
throw std::runtime_error("getComponent() error: specified type is not a subclass of 'Component'"); Object* createChild(std::string name);
} void deleteChild(std::string name);
for (const auto& component : m_components) {
T* derived = dynamic_cast<T*>(component.get()); void printTree(int level = 0);
if (derived != nullptr) {
return derived; // Returns the component of type T
// Returns nullptr if the component is not found.
template<class T> T* getComponent();
// returns the component added
template<class T> T* createComponent();
template<class T> void deleteComponent();
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;
};
// 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);
Transform transform;
private:
static int s_object_count;
int m_id = s_object_count;
std::string m_name;
std::list<std::unique_ptr<Object>> m_children{};
std::list<std::unique_ptr<Component>> m_components{};
// If nullptr, this is the root object
Object* const m_parent;
struct GameIO m_gameIO;
};
// 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) {
return nullptr; T* derived = dynamic_cast<T*>(component.get());
} if (derived != nullptr) {
return derived;
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());
}
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;
} }
return nullptr;
} }
throw std::runtime_error("deleteComponent() error: attempt to delete component that is not present.");
} 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());
}
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;
}
}
throw std::runtime_error("deleteComponent() error: attempt to delete component that is not present.");
}
}

View File

@ -9,73 +9,77 @@
// Doesn't own resources, only holds weak_ptrs // Doesn't own resources, only holds weak_ptrs
class ENGINE_API ResourceManager { namespace engine {
public: class ENGINE_API ResourceManager {
ResourceManager();
ResourceManager(const ResourceManager&) = delete; public:
ResourceManager& operator=(const ResourceManager&) = delete; ResourceManager();
~ResourceManager() = default; ResourceManager(const ResourceManager&) = delete;
ResourceManager& operator=(const ResourceManager&) = delete;
~ResourceManager() = default;
template <class T>
std::shared_ptr<T> create(const std::string& name);
// creates the resource if it is not in the map or the weak_ptr has expired
template <class T>
std::shared_ptr<T> get(const std::string& name);
std::unique_ptr<std::string> getResourcesListString();
std::vector<std::weak_ptr<Resource>> getAllResourcesOfType(const std::string& type);
std::filesystem::path getFilePath(const std::string& name);
private:
std::filesystem::path m_resourcesPath;
std::unordered_map<std::string, std::weak_ptr<Resource>> m_resources;
};
template <class T> template <class T>
std::shared_ptr<T> create(const std::string& name); std::shared_ptr<T> ResourceManager::create(const std::string& name)
{
if (std::is_base_of<Resource, T>::value == false) {
throw std::runtime_error("ResourceManager::create() error: specified type is not a subclass of 'Resource'");
}
auto resource = std::make_shared<T>(getFilePath(name));
m_resources.emplace(name, std::dynamic_pointer_cast<Resource>(resource));
return resource;
}
// creates the resource if it is not in the map or the weak_ptr has expired
template <class T> template <class T>
std::shared_ptr<T> get(const std::string& name); std::shared_ptr<T> ResourceManager::get(const std::string& name)
{
std::unique_ptr<std::string> getResourcesListString(); if (std::is_base_of<Resource, T>::value == false) {
throw std::runtime_error("ResourceManager::get() error: specified type is not a subclass of 'Resource'");
}
std::vector<std::weak_ptr<Resource>> getAllResourcesOfType(const std::string& type); if (m_resources.contains(name)) {
std::filesystem::path getFilePath(const std::string& name); std::weak_ptr<Resource> res = m_resources.at(name);
private: if (res.expired() == false) {
std::filesystem::path m_resourcesPath; // resource definitely exists
std::unordered_map<std::string, std::weak_ptr<Resource>> m_resources; auto castedSharedPtr = std::dynamic_pointer_cast<T>(res.lock());
if (castedSharedPtr == nullptr) {
}; throw std::runtime_error("error: attempt to get Resource which already exists as another type");
}
template <class T> else {
std::shared_ptr<T> ResourceManager::create(const std::string& name) return castedSharedPtr;
{ }
if (std::is_base_of<Resource, T>::value == false) {
throw std::runtime_error("ResourceManager::create() error: specified type is not a subclass of 'Resource'");
}
auto resource = std::make_shared<T>(getFilePath(name));
m_resources.emplace(name, std::dynamic_pointer_cast<Resource>(resource));
return resource;
}
template <class T>
std::shared_ptr<T> ResourceManager::get(const std::string& name)
{
if (std::is_base_of<Resource, T>::value == false) {
throw std::runtime_error("ResourceManager::get() error: specified type is not a subclass of 'Resource'");
}
if (m_resources.contains(name)) {
std::weak_ptr<Resource> res = m_resources.at(name);
if (res.expired() == false) {
// resource definitely exists
auto castedSharedPtr = std::dynamic_pointer_cast<T>(res.lock());
if (castedSharedPtr == nullptr) {
throw std::runtime_error("error: attempt to get Resource which already exists as another type");
} }
else { else {
return castedSharedPtr; // Resource in map but no longer exists. Delete it.
m_resources.erase(name);
} }
} }
else {
// Resource in map but no longer exists. Delete it. return create<T>(name);
m_resources.erase(name);
}
} }
return create<T>(name);
} }

View File

@ -10,7 +10,7 @@
#include <map> #include <map>
namespace resources { namespace engine::resources {
class ENGINE_API Font : public Resource { class ENGINE_API Font : public Resource {

View File

@ -20,7 +20,7 @@ struct Vertex {
glm::vec2 uv; glm::vec2 uv;
}; };
namespace resources { namespace engine::resources {
class ENGINE_API Mesh : public Resource { class ENGINE_API Mesh : public Resource {

View File

@ -5,20 +5,24 @@
#include <string> #include <string>
#include <filesystem> #include <filesystem>
class ENGINE_API Resource { namespace engine {
public: class ENGINE_API Resource {
Resource(const std::filesystem::path& resPath, const std::string& type);
Resource(const Resource&) = delete;
Resource& operator=(const Resource&) = delete;
virtual ~Resource() = 0;
std::string getType(); public:
Resource(const std::filesystem::path& resPath, const std::string& type);
Resource(const Resource&) = delete;
Resource& operator=(const Resource&) = delete;
virtual ~Resource() = 0;
protected: std::string getType();
std::filesystem::path m_resourcePath;
private: protected:
const std::string m_type; std::filesystem::path m_resourcePath;
}; private:
const std::string m_type;
};
}

View File

@ -11,7 +11,7 @@
#include <string> #include <string>
#include <map> #include <map>
namespace resources { namespace engine::resources {
class ENGINE_API Shader : public Resource { class ENGINE_API Shader : public Resource {
@ -40,7 +40,7 @@ public:
static void invalidate() static void invalidate()
{ {
s_activeProgram = -1; s_activeProgram = std::numeric_limits<GLuint>::max();
} }
private: private:

View File

@ -6,7 +6,7 @@
#include <glad/glad.h> #include <glad/glad.h>
namespace resources { namespace engine::resources {
class ENGINE_API Texture : public Resource { class ENGINE_API Texture : public Resource {

View File

@ -6,24 +6,28 @@
#include <filesystem> #include <filesystem>
// Holds everything you would expect to find in a game scene namespace engine {
class ENGINE_API SceneRoot : public Object {
public: // Holds everything you would expect to find in a game scene
// create a new empty scene class ENGINE_API SceneRoot : public Object {
SceneRoot(struct GameIO things);
SceneRoot(const std::filesystem::path& file, struct GameIO things);
SceneRoot(const SceneRoot&) = delete; public:
SceneRoot& operator=(const SceneRoot&) = delete; // create a new empty scene
~SceneRoot(); SceneRoot(struct GameIO things);
SceneRoot(const std::filesystem::path& file, struct GameIO things);
void updateStuff(); SceneRoot(const SceneRoot&) = delete;
SceneRoot& operator=(const SceneRoot&) = delete;
~SceneRoot();
void activateCam(int id); void updateStuff();
void deactivateCam(int id);
private: void activateCam(int id);
std::vector<int> m_activeCameras{}; void deactivateCam(int id);
}; private:
std::vector<int> m_activeCameras{};
};
}

View File

@ -6,12 +6,16 @@
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <glm/ext/quaternion_float.hpp> #include <glm/ext/quaternion_float.hpp>
struct ENGINE_API Transform { namespace engine {
// Scale, rotate (XYZ), translate struct ENGINE_API Transform {
glm::vec3 position{0.0f}; // Scale, rotate (XYZ), translate
glm::quat rotation{};
glm::vec3 scale{1.0f};
}; glm::vec3 position{ 0.0f };
glm::quat rotation{};
glm::vec3 scale{ 1.0f };
};
}

View File

@ -22,7 +22,7 @@ namespace engine {
class ENGINE_API Window { class ENGINE_API Window {
public: public:
Window(const std::string& title); Window(const std::string& title, bool resizable = true);
Window(const Window&) = delete; Window(const Window&) = delete;
Window& operator=(const Window&) = delete; Window& operator=(const Window&) = delete;
~Window(); ~Window();
@ -52,7 +52,7 @@ namespace engine {
// Returns true if the window should remain open // Returns true if the window should remain open
bool isRunning() const; bool isRunning() const;
void setFullscreen(bool fullscreen, bool exclusive = true); void setFullscreen(bool fullscreen, bool exclusive = false);
void toggleFullscreen(); void toggleFullscreen();
bool isFullscreen() const; bool isFullscreen() const;
@ -139,6 +139,8 @@ namespace engine {
std::string m_title; std::string m_title;
bool m_resizable;
bool m_fullscreen = false; bool m_fullscreen = false;
bool m_justResized = false; bool m_justResized = false;
bool m_keyboardFocus = true; bool m_keyboardFocus = true;

View File

@ -13,7 +13,7 @@ static const std::string VIEW_MAT_UNIFORM = "viewMat";
static const std::string PROJ_MAT_UNIFORM = "projMat"; static const std::string PROJ_MAT_UNIFORM = "projMat";
static const std::string WINDOW_SIZE_UNIFORM = "windowSize"; static const std::string WINDOW_SIZE_UNIFORM = "windowSize";
namespace components { namespace engine::components {
glm::vec4 Camera::s_clearColor{-999.0f, -999.0f, -999.0f, -999.0f}; glm::vec4 Camera::s_clearColor{-999.0f, -999.0f, -999.0f, -999.0f};

View File

@ -4,27 +4,31 @@
#include <iostream> #include <iostream>
int Component::s_next_component_id = 0; namespace engine {
Component::Component(Object* parent, TypeEnum type) : int Component::s_next_component_id = 0;
m_type(type), parent(*parent),
win(parent->win),
inp(parent->inp),
res(parent->res)
{
s_next_component_id++;
}
Component::~Component() Component::Component(Object* parent, TypeEnum type) :
{ m_type(type), parent(*parent),
} win(parent->win),
inp(parent->inp),
res(parent->res)
{
s_next_component_id++;
}
int Component::getID() Component::~Component()
{ {
return m_id; }
}
Component::TypeEnum Component::getType() int Component::getID()
{ {
return m_type; return m_id;
} }
Component::TypeEnum Component::getType()
{
return m_type;
}
}

View File

@ -1,6 +1,6 @@
#include "components/custom.hpp" #include "components/custom.hpp"
namespace components { namespace engine::components {
CustomComponent::CustomComponent(Object* parent) : Component(parent, TypeEnum::CUSTOM) CustomComponent::CustomComponent(Object* parent) : Component(parent, TypeEnum::CUSTOM)
{ {

View File

@ -6,7 +6,7 @@
#include <iostream> #include <iostream>
namespace components { namespace engine::components {
Renderer::Renderer(Object* parent) : Component(parent, TypeEnum::RENDERER) Renderer::Renderer(Object* parent) : Component(parent, TypeEnum::RENDERER)
{ {

View File

@ -4,7 +4,7 @@
#include "resource_manager.hpp" #include "resource_manager.hpp"
#include "resources/texture.hpp" #include "resources/texture.hpp"
namespace components { namespace engine::components {
UI::UI(Object* parent) : Component(parent, TypeEnum::UI) UI::UI(Object* parent) : Component(parent, TypeEnum::UI)
{ {

View File

@ -7,7 +7,7 @@ namespace engine {
Application::Application(const char* appName, const char* appVersion) Application::Application(const char* appName, const char* appVersion)
{ {
m_win = std::make_unique<Window>(appName); m_win = std::make_unique<Window>(appName, true);
m_gfx = std::make_unique<GFXDevice>(appName, appVersion, m_win->getHandle()); m_gfx = std::make_unique<GFXDevice>(appName, appVersion, m_win->getHandle());
} }
@ -34,12 +34,7 @@ namespace engine {
} }
if (m_win->getKeyPress(inputs::Key::F11)) { if (m_win->getKeyPress(inputs::Key::F11)) {
if (m_win->isFullscreen()) { m_win->toggleFullscreen();
m_win->setFullscreen(false);
}
else {
m_win->setFullscreen(true, false); // borderless window
}
} }
if (m_win->getKeyPress(inputs::Key::ESCAPE)) { if (m_win->getKeyPress(inputs::Key::ESCAPE)) {
m_win->setCloseFlag(); m_win->setCloseFlag();

View File

@ -7,127 +7,132 @@
#include <log.hpp> #include <log.hpp>
int Object::s_object_count = 0; namespace engine {
Object::Object(std::string name, Object* parent, SceneRoot& root, struct GameIO things) int Object::s_object_count = 0;
: m_name(name), m_parent(parent), root(root),
m_gameIO(things),
win(*things.win),
inp(*things.input),
res(*things.resMan)
{
s_object_count++;
}
Object::~Object() Object::Object(std::string name, Object* parent, SceneRoot& root, struct GameIO things)
{ : m_name(name), m_parent(parent), root(root),
} m_gameIO(things),
win(*things.win),
inp(*things.input),
res(*things.resMan)
{
s_object_count++;
}
std::string Object::getName() Object::~Object()
{ {
return m_name; }
}
Object* Object::getParent() std::string Object::getName()
{ {
return m_parent; return m_name;
} }
Object* Object::getChild(std::string name) Object* Object::getParent()
{ {
for (const auto& child : m_children) { return m_parent;
if (name == child->getName()) { }
return child.get();
Object* Object::getChild(std::string name)
{
for (const auto& child : m_children) {
if (name == child->getName()) {
return child.get();
}
}
return nullptr;
}
std::vector<Object*> Object::getChildren()
{
std::vector<Object*> newVector{};
for (const auto& child : m_children) {
newVector.push_back(child.get());
}
return newVector;
}
Object* Object::createChild(std::string name)
{
if (getChild(name) != nullptr) {
throw std::runtime_error("Attempt to create child object with existing name");
}
m_children.emplace_back(std::make_unique<Object>(name, this, root, m_gameIO));
return m_children.back().get();
}
void Object::deleteChild(std::string name)
{
for (auto itr = m_children.begin(); itr != m_children.end(); ++itr) {
if ((*itr)->getName() == name) {
m_children.erase(itr);
return;
}
}
throw std::runtime_error("Unable to delete child '" + name + "' as it does not exist");
}
void Object::printTree(int level)
{
std::string buf;
for (int i = 0; i < level; i++) {
if (i + 1 == level) {
buf += "\\_______";
}
else {
buf += " ";
}
}
buf += m_name;
INFO(buf);
for (const auto& child : this->getChildren()) {
child->printTree(level + 1);
} }
} }
return nullptr;
}
std::vector<Object*> Object::getChildren() void Object::getAllSubComponents(struct CompList& compList, glm::mat4 parentTransform)
{ {
std::vector<Object*> newVector{}; using namespace components;
for (const auto& child : m_children) {
newVector.push_back(child.get());
}
return newVector;
}
Object* Object::createChild(std::string name) glm::mat4 objTransform{ 1.0f };
{
if (getChild(name) != nullptr) {
throw std::runtime_error("Attempt to create child object with existing name");
}
m_children.emplace_back(std::make_unique<Object>(name, this, root, m_gameIO));
return m_children.back().get();
}
void Object::deleteChild(std::string name) auto t = transform;
{
for (auto itr = m_children.begin(); itr != m_children.end(); ++itr) { // rotation
if ((*itr)->getName() == name) { objTransform = glm::mat4_cast(t.rotation);
m_children.erase(itr);
return; // position
reinterpret_cast<glm::vec3&>(objTransform[3]) = t.position;
// scale (effectively applied first
objTransform = glm::scale(objTransform, t.scale);
const glm::mat4 newTransform = parentTransform * objTransform;
for (const auto& compUnq : m_components) {
const auto comp = compUnq.get();
switch (comp->getType()) {
case Component::TypeEnum::CAMERA:
compList.cameras.emplace_back(dynamic_cast<Camera*>(comp), newTransform);
break;
case Component::TypeEnum::RENDERER:
compList.renderers.emplace_back(dynamic_cast<Renderer*>(comp), newTransform);
break;
case Component::TypeEnum::UI:
compList.uis.emplace_back(dynamic_cast<UI*>(comp), newTransform);
break;
case Component::TypeEnum::CUSTOM:
compList.customs.emplace_back(dynamic_cast<CustomComponent*>(comp), newTransform);
break;
default:
break;
}
}
for (const auto& child : m_children) {
child->getAllSubComponents(compList, newTransform);
} }
} }
throw std::runtime_error("Unable to delete child '" + name + "' as it does not exist");
}
void Object::printTree(int level) }
{
std::string buf;
for (int i = 0; i < level; i++) {
if (i+1 == level) {
buf += "\\_______";
} else {
buf += " ";
}
}
buf += m_name;
INFO(buf);
for (const auto& child : this->getChildren()) {
child->printTree(level+1);
}
}
void Object::getAllSubComponents(struct CompList& compList, glm::mat4 parentTransform)
{
using namespace components;
glm::mat4 objTransform{1.0f};
auto t = transform;
// rotation
objTransform = glm::mat4_cast(t.rotation);
// position
reinterpret_cast<glm::vec3&>(objTransform[3]) = t.position;
// scale (effectively applied first
objTransform = glm::scale(objTransform, t.scale);
const glm::mat4 newTransform = parentTransform * objTransform;
for (const auto& compUnq : m_components) {
const auto comp = compUnq.get();
switch (comp->getType()) {
case Component::TypeEnum::CAMERA:
compList.cameras.emplace_back(dynamic_cast<Camera*>(comp), newTransform);
break;
case Component::TypeEnum::RENDERER:
compList.renderers.emplace_back(dynamic_cast<Renderer*>(comp), newTransform);
break;
case Component::TypeEnum::UI:
compList.uis.emplace_back(dynamic_cast<UI*>(comp), newTransform);
break;
case Component::TypeEnum::CUSTOM:
compList.customs.emplace_back(dynamic_cast<CustomComponent*>(comp), newTransform);
break;
default:
break;
}
}
for (const auto& child : m_children) {
child->getAllSubComponents(compList, newTransform);
}
}

View File

@ -8,68 +8,73 @@
#include "log.hpp" #include "log.hpp"
ResourceManager::ResourceManager() namespace engine {
{
ResourceManager::ResourceManager()
{
#ifdef _MSC_VER #ifdef _MSC_VER
CHAR exeDirBuf[MAX_PATH + 1]; CHAR exeDirBuf[MAX_PATH + 1];
GetModuleFileNameA(NULL, exeDirBuf, MAX_PATH + 1); GetModuleFileNameA(NULL, exeDirBuf, MAX_PATH + 1);
std::filesystem::path cwd = std::filesystem::path(exeDirBuf).parent_path(); std::filesystem::path cwd = std::filesystem::path(exeDirBuf).parent_path();
(void)_chdir((const char*)std::filesystem::absolute(cwd).c_str()); (void)_chdir((const char*)std::filesystem::absolute(cwd).c_str());
#else #else
std::filesystem::path cwd = std::filesystem::current_path(); std::filesystem::path cwd = std::filesystem::current_path();
#endif #endif
if (std::filesystem::is_directory(cwd / "res")) { if (std::filesystem::is_directory(cwd / "res")) {
m_resourcesPath = cwd / "res"; m_resourcesPath = cwd / "res";
} else { }
m_resourcesPath = cwd.parent_path() / "share" / "sdltest"; else {
} m_resourcesPath = cwd.parent_path() / "share" / "sdltest";
}
if (std::filesystem::is_directory(m_resourcesPath) == false) {
m_resourcesPath = cwd.root_path() / "usr" / "local" / "share" / "sdltest"; if (std::filesystem::is_directory(m_resourcesPath) == false) {
} m_resourcesPath = cwd.root_path() / "usr" / "local" / "share" / "sdltest";
}
if (std::filesystem::is_directory(m_resourcesPath) == false) {
throw std::runtime_error("Unable to determine resources location. CWD: " + cwd.string()); if (std::filesystem::is_directory(m_resourcesPath) == false) {
} throw std::runtime_error("Unable to determine resources location. CWD: " + cwd.string());
}
std::unique_ptr<std::string> ResourceManager::getResourcesListString()
{
auto bufPtr = std::make_unique<std::string>();
std::string& buf = *bufPtr;
int maxLength = 0;
for (const auto& [name, ptr] : m_resources) {
if (name.length() > maxLength)
maxLength = name.length();
}
for (const auto& [name, ptr] : m_resources) {
buf += name;
for (int i = 0; i < (maxLength - name.length() + 4); i++) {
buf += " ";
} }
buf += std::to_string(ptr.use_count()) + "\n";
} }
return bufPtr;
} std::unique_ptr<std::string> ResourceManager::getResourcesListString()
{
auto bufPtr = std::make_unique<std::string>();
std::string& buf = *bufPtr;
int maxLength = 0;
for (const auto& [name, ptr] : m_resources) {
if (name.length() > maxLength)
maxLength = name.length();
}
for (const auto& [name, ptr] : m_resources) {
buf += name;
for (int i = 0; i < (maxLength - name.length() + 4); i++) {
buf += " ";
}
buf += std::to_string(ptr.use_count()) + "\n";
}
return bufPtr;
}
std::vector<std::weak_ptr<Resource>> ResourceManager::getAllResourcesOfType(const std::string& type) std::vector<std::weak_ptr<Resource>> ResourceManager::getAllResourcesOfType(const std::string& type)
{ {
std::vector<std::weak_ptr<Resource>> resources; std::vector<std::weak_ptr<Resource>> resources;
for (const auto& [name, ptr] : m_resources) { for (const auto& [name, ptr] : m_resources) {
if (ptr.expired() == false) { if (ptr.expired() == false) {
if (ptr.lock()->getType() == type) { if (ptr.lock()->getType() == type) {
resources.push_back(ptr); resources.push_back(ptr);
}
} }
} }
return resources;
} }
return resources;
}
// private // private
std::filesystem::path ResourceManager::getFilePath(const std::string& name) std::filesystem::path ResourceManager::getFilePath(const std::string& name)
{ {
return m_resourcesPath / name; return m_resourcesPath / name;
} }
}

View File

@ -3,7 +3,7 @@
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
namespace resources { namespace engine::resources {
Font::Font(const std::filesystem::path& resPath) : Resource(resPath, "font") Font::Font(const std::filesystem::path& resPath) : Resource(resPath, "font")
{ {

View File

@ -1,6 +1,6 @@
#include "resources/mesh.hpp" #include "resources/mesh.hpp"
namespace resources { namespace engine::resources {
struct MeshFileHeader { struct MeshFileHeader {
unsigned int vertex_count; unsigned int vertex_count;

View File

@ -2,19 +2,23 @@
#include <log.hpp> #include <log.hpp>
Resource::Resource(const std::filesystem::path& resPath, const std::string& type) : m_resourcePath(resPath), m_type(type) namespace engine {
{
if (m_type != "mesh")
TRACE("Creating {} resource: {}", type, resPath.filename().string());
}
Resource::~Resource() Resource::Resource(const std::filesystem::path& resPath, const std::string& type) : m_resourcePath(resPath), m_type(type)
{ {
if (m_type != "mesh") if (m_type != "mesh")
TRACE("Destroyed {} resource: {}", m_type, m_resourcePath.filename().string()); TRACE("Creating {} resource: {}", type, resPath.filename().string());
} }
std::string Resource::getType() Resource::~Resource()
{ {
return m_type; if (m_type != "mesh")
} TRACE("Destroyed {} resource: {}", m_type, m_resourcePath.filename().string());
}
std::string Resource::getType()
{
return m_type;
}
}

View File

@ -50,7 +50,7 @@ static GLuint compile(const char *path, GLenum type)
} return handle; } return handle;
} }
namespace resources { namespace engine::resources {
// I've got to do this because of GL's stupid state machine // I've got to do this because of GL's stupid state machine
GLuint Shader::s_activeProgram = 0; GLuint Shader::s_activeProgram = 0;

View File

@ -7,7 +7,7 @@
#include <vector> #include <vector>
namespace resources { namespace engine::resources {
// -1 means invalid / no bind // -1 means invalid / no bind
GLuint Texture::s_binded_texture = -1; GLuint Texture::s_binded_texture = -1;
@ -28,7 +28,7 @@ static bool readPNG(const std::string& path, std::vector<uint8_t>& texbuf, int *
return false; return false;
} }
const size_t size = x * y * n; const size_t size = (size_t)x * (size_t)y * (size_t)n;
texbuf.resize(size); texbuf.resize(size);
memcpy(texbuf.data(), data, size); memcpy(texbuf.data(), data, size);

View File

@ -14,77 +14,81 @@
#include "log.hpp" #include "log.hpp"
SceneRoot::SceneRoot(struct GameIO things) : Object("root", nullptr, *this, things) namespace engine {
{
}
SceneRoot::SceneRoot(const std::filesystem::path& file, struct GameIO things) : SceneRoot(things) SceneRoot::SceneRoot(struct GameIO things) : Object("root", nullptr, *this, things)
{ {
// TODO: make this a resource
//loadFromSceneFile(file);
}
SceneRoot::~SceneRoot()
{
}
// private methods
// public methods
void SceneRoot::updateStuff()
{
using namespace components;
using namespace glm;
struct CompList compList{};
getAllSubComponents(compList, glm::mat4{1.0f});
// update
for (const auto& [c, t] : compList.customs) {
c->onUpdate(t);
} }
// render SceneRoot::SceneRoot(const std::filesystem::path& file, struct GameIO things) : SceneRoot(things)
{
// TODO: make this a resource
//loadFromSceneFile(file);
}
for (const auto& [c, t] : compList.cameras) { SceneRoot::~SceneRoot()
for (int id : m_activeCameras) { {
if (c->getID() == id) { }
c->updateCam(t);
for (const auto& [c, t] : compList.renderers) { // private methods
c->render(t);
// public methods
void SceneRoot::updateStuff()
{
using namespace components;
using namespace glm;
struct CompList compList {};
getAllSubComponents(compList, glm::mat4{ 1.0f });
// update
for (const auto& [c, t] : compList.customs) {
c->onUpdate(t);
}
// render
for (const auto& [c, t] : compList.cameras) {
for (int id : m_activeCameras) {
if (c->getID() == id) {
c->updateCam(t);
for (const auto& [c, t] : compList.renderers) {
c->render(t);
}
break;
} }
}
}
break; for (const auto& [c, t] : compList.uis) {
c->render(t);
}
}
void SceneRoot::activateCam(int id)
{
auto& v = m_activeCameras;
if (std::find(v.begin(), v.end(), id) == v.end()) {
v.push_back(id);
}
}
void SceneRoot::deactivateCam(int id)
{
auto& v = m_activeCameras;
for (auto it = v.begin(); it != v.end(); it++) {
if (*it == id) {
v.erase(it);
} }
} }
} }
for (const auto& [c, t] : compList.uis) { }
c->render(t);
}
}
void SceneRoot::activateCam(int id)
{
auto& v = m_activeCameras;
if (std::find(v.begin(), v.end(), id) == v.end()) {
v.push_back(id);
}
}
void SceneRoot::deactivateCam(int id)
{
auto& v = m_activeCameras;
for (auto it = v.begin(); it != v.end(); it++) {
if (*it == id) {
v.erase(it);
}
}
}

View File

@ -9,7 +9,7 @@ const uint64_t BILLION = 1000000000;
namespace engine { namespace engine {
Window::Window(const std::string& title) : m_title(title) Window::Window(const std::string& title, bool resizable) : m_title(title), m_resizable(resizable)
{ {
// init SDL // init SDL
@ -26,13 +26,23 @@ namespace engine {
m_lastFrameStamp = m_startTime - 1; m_lastFrameStamp = m_startTime - 1;
m_avgFpsStart = m_startTime; m_avgFpsStart = m_startTime;
Uint32 windowFlags = SDL_WINDOW_SHOWN;
#ifdef ENGINE_BUILD_VULKAN
windowFlags |= SDL_WINDOW_VULKAN;
#endif
if (m_resizable) {
windowFlags |= SDL_WINDOW_RESIZABLE;
}
// create the window // create the window
m_handle = SDL_CreateWindow( m_handle = SDL_CreateWindow(
m_title.c_str(), m_title.c_str(),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
static_cast<int>(m_winSize.x), static_cast<int>(m_winSize.x),
static_cast<int>(m_winSize.y), static_cast<int>(m_winSize.y),
SDL_WINDOW_VULKAN | SDL_WINDOW_SHOWN); windowFlags);
if (m_handle == NULL) { if (m_handle == NULL) {
SDL_Quit(); SDL_Quit();
throw std::runtime_error("Unable to create window: " + std::string(SDL_GetError())); throw std::runtime_error("Unable to create window: " + std::string(SDL_GetError()));
@ -278,14 +288,16 @@ namespace engine {
void Window::setFullscreen(bool fullscreen, bool exclusive) void Window::setFullscreen(bool fullscreen, bool exclusive)
{ {
if (SDL_SetWindowFullscreen(m_handle, fullscreen ? (exclusive ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP) : 0) != 0) { if (m_resizable) {
throw std::runtime_error("Unable to set window to fullscreen/windowed"); if (SDL_SetWindowFullscreen(m_handle, fullscreen ? (exclusive ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP) : 0) != 0) {
} throw std::runtime_error("Unable to set window to fullscreen/windowed");
m_fullscreen = fullscreen; }
if (fullscreen) { m_fullscreen = fullscreen;
int width, height; if (fullscreen) {
SDL_GetWindowSize(m_handle, &width, &height); int width, height;
onResize(width, height); SDL_GetWindowSize(m_handle, &width, &height);
onResize(width, height);
}
} }
} }