From 5385b7ede71f0f8437faeab504a516e07567d8b0 Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Thu, 8 Jul 2021 21:34:18 +0200 Subject: [PATCH] Refactor Widget loading. --- src/Controller.cpp | 27 ++++++------ src/Controller.h | 10 +++-- src/Entity.cpp | 10 +++-- src/Entity.h | 12 +++++- src/GLBucket.cpp | 2 - src/JsonParser.cpp | 100 +++++++++++++++++---------------------------- src/JsonParser.h | 16 ++++---- src/Menu.cpp | 7 +++- src/Model.h | 7 ---- src/Screen.cpp | 13 ++++-- src/Screen.h | 12 ++++-- src/Widget.cpp | 24 ++++++----- src/Widget.h | 16 +++++++- src/World.cpp | 44 +++++++++++++++++--- src/main.cpp | 7 ++-- 15 files changed, 176 insertions(+), 131 deletions(-) diff --git a/src/Controller.cpp b/src/Controller.cpp index 9f4f331..681cf22 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -61,8 +61,8 @@ Controller::Controller() : m_gameWindow(std::unique_ptr(new Window)) Controller::~Controller() { - for (auto it = m_shaderPrograms.begin(); it != m_shaderPrograms.end(); it++) { - delete *it; + for (auto program : m_shaderPrograms) { + delete program; } delete m_world; @@ -72,6 +72,12 @@ Controller::~Controller() delete m_gameEventHandler; } +Controller &Controller::instance() +{ + static Controller s_instance; + return s_instance; +} + void Controller::run() { updateExposure(getShaderProgramByName("postProcessingProgram")); @@ -212,22 +218,17 @@ void Controller::updateExposure(ShaderProgram *shaderProgram) ShaderProgram *Controller::getShaderProgramByName(const std::string &name) { - for (auto it = m_shaderPrograms.begin(); it != m_shaderPrograms.end(); it++) { - if ((*it)->getUniqueName() == name) { - return *it; - } - } - std::cout << "[Warning] ShaderProgram could not be found by name \"" << name << "\"" << std::endl; - return nullptr; + return getShaderProgramByName(name, m_shaderPrograms); } -ShaderProgram *Controller::getShaderProgramByName(std::vector shaderPrograms, const std::string &name) +ShaderProgram *Controller::getShaderProgramByName(const std::string &name, std::vector shaderPrograms) { - for (auto it = shaderPrograms.begin(); it != shaderPrograms.end(); it++) { - if ((*it)->getUniqueName() == name) { - return *it; + for (auto program : shaderPrograms) { + if (program->getUniqueName() == name) { + return program; } } + std::cout << "[Warning] ShaderProgram could not be found by name \"" << name << "\"" << std::endl; return nullptr; } diff --git a/src/Controller.h b/src/Controller.h index 988471b..d813c69 100644 --- a/src/Controller.h +++ b/src/Controller.h @@ -19,24 +19,26 @@ class Handler; class Controller { public: - Controller(); ~Controller(); + static Controller &instance(); + void run(); void setMaxFps(uint16_t fps); - static ShaderProgram *getShaderProgramByName(std::vector shaderPrograms, const std::string &name); + ShaderProgram *getShaderProgramByName(const std::string &name); + static ShaderProgram *getShaderProgramByName(const std::string &name, std::vector shaderPrograms); void updateExposure(ShaderProgram *shaderProgram); private: + Controller(); + void limit_framerate(); void updateWindowDimensions(); - ShaderProgram *getShaderProgramByName(const std::string &name); - void renderImGui(World *world, glm::vec3 *lightColor, bool *rotateEntity, bool *rotateLightSource, ShaderProgram *postProcessingProgram, float *intensity, bool *drawShadows); diff --git a/src/Entity.cpp b/src/Entity.cpp index ac6d88d..2be56cd 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -9,9 +9,13 @@ uint32_t Entity::s_idCounter = 0; -Entity::Entity(const std::string &name, Model *model, ShaderProgram *shaderProgram) - : m_uniqueName(name), m_model(model), m_shaderProgram(shaderProgram), m_id(s_idCounter++) -{} +Entity::Entity(Prototype prototype, Model *model, ShaderProgram *shaderProgram) + : m_uniqueName(prototype.name), m_model(model), m_shaderProgram(shaderProgram), m_id(s_idCounter++) +{ + setPosition(prototype.position); + setRotation(prototype.rotation); + setScale(prototype.scale); +} void Entity::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) { diff --git a/src/Entity.h b/src/Entity.h index bf38b7b..9035540 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -12,7 +12,17 @@ class Model; class Entity { public: - Entity(const std::string &name, Model *model, ShaderProgram *shaderProgram); + struct Prototype + { + std::string name; + std::string modelName; + std::string shaderProgramName; + glm::vec3 position; + glm::vec3 rotation; + float scale; + }; + + Entity(Prototype prototype, Model *model, ShaderProgram *shaderProgram); ~Entity() = default; void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition); diff --git a/src/GLBucket.cpp b/src/GLBucket.cpp index 24cb33e..762ddde 100644 --- a/src/GLBucket.cpp +++ b/src/GLBucket.cpp @@ -1,7 +1,5 @@ #include "GLBucket.h" -#include - std::unique_ptr GLBucket::s_instance = std::unique_ptr(new GLBucket); GLBucket &GLBucket::instance() diff --git a/src/JsonParser.cpp b/src/JsonParser.cpp index 5e9a921..1dfdbbf 100644 --- a/src/JsonParser.cpp +++ b/src/JsonParser.cpp @@ -48,67 +48,43 @@ std::vector JsonParser::getModelPrototypes() const return modelPrototypes; } -std::vector JsonParser::getEntities(std::vector &models, std::vector shaderPrograms) +std::vector JsonParser::getEntityPrototypes() const { - std::vector temp_entities; + std::vector entityPrototypes; const Json::Value entitiesJson = m_root["entities"]; for (unsigned int index = 0; index < entitiesJson.size(); index++) { - std::string entity_name = entitiesJson[index]["unique_name"].asString(); - std::string entity_model = entitiesJson[index]["model"].asString(); - std::string entity_shaderProgram = entitiesJson[index]["shaderProgram"].asString(); - glm::vec3 entitiy_position = {}, entity_rotation = {}; - float entity_scale = 1.0f; - - ShaderProgram *shaderProgram = nullptr; - for (auto it = shaderPrograms.begin(); it != shaderPrograms.end(); it++) { - if ((*it)->getUniqueName() == entity_shaderProgram) { - shaderProgram = *it; - } - } - if (!shaderProgram) - std::cout << "[Warning] ShaderProgram could not be found by name \"" << entity_shaderProgram << "\"" - << std::endl; - - Model *current_model = nullptr; - for (auto it = models.begin(); it != models.end(); it++) { - if ((*it)->getUniqueName() == entity_model) { - current_model = *it; - } - } - if (!current_model) { - // Apply fallback model (first model in vector) - current_model = models[0]; - std::cout << "[Warning] Model could not be found by unique name \"" << entity_model << "\"" << std::endl; - } + std::string entityName = entitiesJson[index]["unique_name"].asString(); + std::string entityModel = entitiesJson[index]["model"].asString(); + std::string entityShaderProgram = entitiesJson[index]["shaderProgram"].asString(); + glm::vec3 entitiyPosition = {}, entityRotation = {}; + float entityScale = 1.0f; const Json::Value positionJson = entitiesJson[index]["position"]; const Json::Value rotationJson = entitiesJson[index]["rotation"]; const Json::Value scaleJson = entitiesJson[index]["scale"]; if (!positionJson.empty()) { - entitiy_position.x = positionJson[0].asFloat(); - entitiy_position.y = positionJson[1].asFloat(); - entitiy_position.z = positionJson[2].asFloat(); + entitiyPosition.x = positionJson[0].asFloat(); + entitiyPosition.y = positionJson[1].asFloat(); + entitiyPosition.z = positionJson[2].asFloat(); } if (!rotationJson.empty()) { - entity_rotation.s = rotationJson[0].asFloat(); - entity_rotation.t = rotationJson[1].asFloat(); - entity_rotation.p = rotationJson[2].asFloat(); + entityRotation.s = rotationJson[0].asFloat(); + entityRotation.t = rotationJson[1].asFloat(); + entityRotation.p = rotationJson[2].asFloat(); } if (!scaleJson.empty()) { - entity_scale = scaleJson.asFloat(); + entityScale = scaleJson.asFloat(); } - Entity *current_entity = new Entity(entity_name, current_model, shaderProgram); - current_entity->setPosition(entitiy_position); - current_entity->setRotation(entity_rotation); - current_entity->setScale(entity_scale); - temp_entities.push_back(current_entity); - std::cout << "Loaded Entity \"" << entity_name << "\" with model \"" << entity_model << "\"" << std::endl; + Entity::Prototype prototype{entityName, entityModel, entityShaderProgram, + entitiyPosition, entityRotation, entityScale}; + + entityPrototypes.push_back(prototype); } - return temp_entities; + return entityPrototypes; } std::vector JsonParser::getShaderPrograms() @@ -215,49 +191,47 @@ std::vector JsonParser::getLights(ShaderProgram *shaderProgram) return temp_lights; } -std::vector JsonParser::getScreens(ShaderProgram *menuProgram, FrameBuffer *framebuffer) +std::vector JsonParser::getScreenPrototypes() const { - std::vector temp_screens; + std::vector screenPrototypes; const Json::Value loadingScreenJson = m_root["loadingScreen"]; const Json::Value mainMenuScreenJson = m_root["mainMenuScreen"]; std::string name; - Screen *screen; name = "loadingScreen"; - screen = new Screen(name, getWidgetsFromScreen(loadingScreenJson), framebuffer, menuProgram); - temp_screens.push_back(screen); + Screen::Prototype loadingScreen = Screen::Prototype{name, getWidgetPrototypesFromScreen(loadingScreenJson)}; + screenPrototypes.push_back(loadingScreen); name = "mainMenuScreen"; - screen = new Screen(name, getWidgetsFromScreen(mainMenuScreenJson), framebuffer, menuProgram); - temp_screens.push_back(screen); + Screen::Prototype mainMenuScreen = Screen::Prototype{name, getWidgetPrototypesFromScreen(mainMenuScreenJson)}; + screenPrototypes.push_back(mainMenuScreen); - return temp_screens; + return screenPrototypes; } -std::vector JsonParser::getWidgetsFromScreen(const Json::Value &screenJson) +std::vector JsonParser::getWidgetPrototypesFromScreen(const Json::Value &screenJson) const { - std::vector temp_widgets; + std::vector widgetPrototypes; // Iterate over widgets - unsigned int index = 0; - for (; index < screenJson.size(); index++) { + for (unsigned int index = 0; index < screenJson.size(); index++) { const Json::Value currentWidgetJson = screenJson[index]; const Json::Value currentWidgetTextureJson = currentWidgetJson["texture"]; const Json::Value currentWidgetPosition = currentWidgetJson["position"]; const Json::Value currentWidgetDimensions = currentWidgetJson["dimensions"]; std::string name = currentWidgetJson["unique_name"].asString(); + glm::vec2 position(currentWidgetPosition[0].asFloat(), currentWidgetPosition[1].asFloat()); + glm::vec2 dimensions(currentWidgetDimensions[0].asFloat(), currentWidgetDimensions[1].asFloat()); + uint16_t callBackId = currentWidgetJson["callbackId"].asUInt(); Texture::Prototype texturePrototype{currentWidgetTextureJson.asString(), TextureType::Diffuse}; - Texture *currentWidgetTexture = new Texture(texturePrototype); - currentWidgetTexture->initializeOnGPU(); - Widget *currentWidget = - new Widget(name, currentWidgetTexture, currentWidgetPosition[0].asFloat(), - currentWidgetPosition[1].asFloat(), currentWidgetDimensions[0].asFloat(), - currentWidgetDimensions[1].asFloat(), currentWidgetJson["callbackId"].asUInt()); - temp_widgets.push_back(currentWidget); + + Widget::Prototype widgetPrototype{name, position, dimensions, texturePrototype, callBackId}; + + widgetPrototypes.push_back(widgetPrototype); } - return temp_widgets; + return widgetPrototypes; } Skybox *JsonParser::getSkybox(Model *cubeModel, ShaderProgram *skyboxProgram) diff --git a/src/JsonParser.h b/src/JsonParser.h index c78ece0..e08c058 100644 --- a/src/JsonParser.h +++ b/src/JsonParser.h @@ -1,12 +1,14 @@ #pragma once -#include "Model.h" - #include #include #include -class Entity; +#include "Entity.h" +#include "Model.h" +#include "Screen.h" +#include "Widget.h" + class Light; class Screen; class Skybox; @@ -21,15 +23,15 @@ public: ~JsonParser(); std::vector getModelPrototypes() const; - std::vector getEntities(std::vector &models, std::vector shaderPrograms); - std::vector getLights(ShaderProgram *shaderProgram); - std::vector getScreens(ShaderProgram *menuProgram, FrameBuffer *framebuffer); + std::vector getEntityPrototypes() const; + std::vector getLights(ShaderProgram *shaderProgram); // should be under entities too + std::vector getScreenPrototypes() const; Skybox *getSkybox(Model *cubeModel, ShaderProgram *skyboxProgram); std::vector getShaderPrograms(); private: - std::vector getWidgetsFromScreen(const Json::Value &screenJson); + std::vector getWidgetPrototypesFromScreen(const Json::Value &screenJson) const; Json::Value m_root; Json::CharReaderBuilder m_rbuilder; diff --git a/src/Menu.cpp b/src/Menu.cpp index ab5a15f..612e47a 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -14,7 +14,12 @@ Menu::Menu(FrameBuffer *p_framebuffer, ShaderProgram *p_shaderProgram) : m_frameBuffer(p_framebuffer), m_shaderProgram(p_shaderProgram) { JsonParser screenParser("data/screens.json"); - m_screens = screenParser.getScreens(m_shaderProgram, m_frameBuffer); + std::vector screenPrototypes = screenParser.getScreenPrototypes(); + + for (auto &prototype : screenPrototypes) { + auto currentScreen = new Screen(prototype, p_framebuffer, p_shaderProgram); + m_screens.push_back(currentScreen); + } } Menu::~Menu() diff --git a/src/Model.h b/src/Model.h index 47bc666..002d1d4 100644 --- a/src/Model.h +++ b/src/Model.h @@ -9,13 +9,6 @@ class ShaderProgram; class Mesh; class Texture; -struct MeshPrototype -{ - std::vector textureIds; - std::vector meshVertices; - std::vector meshIndices; -}; - class Model { public: diff --git a/src/Screen.cpp b/src/Screen.cpp index 7f78456..e3ee9fd 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -8,11 +8,16 @@ uint32_t Screen::s_idCounter = 0; -Screen::Screen(const std::string &name, std::vector widgets, FrameBuffer *framebuffer, - ShaderProgram *shaderProgram) - : m_uniqueName(name), m_frameBuffer(framebuffer), m_shaderProgram(shaderProgram), m_widgets(widgets) +Screen::Screen(Prototype prototype, FrameBuffer *framebuffer, ShaderProgram *shaderProgram) + : m_uniqueName(prototype.name), m_frameBuffer(framebuffer), m_shaderProgram(shaderProgram), m_id(s_idCounter++) { - m_id = s_idCounter++; + for (auto &prototype : prototype.widgetPrototypes) { + Texture *currentTexture = new Texture(prototype.texturePrototype); + currentTexture->initializeOnGPU(); + + Widget *currentWidget = new Widget(prototype, currentTexture); + m_widgets.push_back(currentWidget); + } } Screen::~Screen() diff --git a/src/Screen.h b/src/Screen.h index a2337fc..72f8b15 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -4,8 +4,9 @@ #include #include +#include "Widget.h" + class Menu; -class Widget; class FrameBuffer; class ShaderProgram; class Texture; @@ -13,8 +14,13 @@ class Texture; class Screen { public: - Screen(const std::string &name, std::vector widgets, FrameBuffer *framebuffer, - ShaderProgram *shaderProgram); + struct Prototype + { + std::string name; + std::vector widgetPrototypes; + }; + + Screen(Prototype prototype, FrameBuffer *framebuffer, ShaderProgram *shaderProgram); ~Screen(); void addWidget(Widget *widget); diff --git a/src/Widget.cpp b/src/Widget.cpp index 150c329..a8002a4 100644 --- a/src/Widget.cpp +++ b/src/Widget.cpp @@ -7,23 +7,24 @@ #include -Widget::Widget(std::string &name, Texture *texture, float p_x, float p_y, float p_w, float p_h, uint16_t callbackId) - : m_posX(p_x), m_posY(p_y), m_width(p_w), m_height(p_h), m_uniqueName(name), m_callbackId(callbackId) +Widget::Widget(Prototype prototype, Texture *texture) + : m_position(prototype.position), m_dimensions(prototype.dimensions), m_uniqueName(prototype.name), + m_callbackId(prototype.callBackId) { m_widgetTextures.push_back(texture); double widgetVerticesData[12] = { - 2 * (m_posX + m_width) - 1.0f, - 2 * (m_posY)-1.0f, + 2 * (m_position.x + m_dimensions.x) - 1.0f, + 2 * (m_position.y) - 1.0f, 0.0f, // Bottom right - 2 * (m_posX)-1.0f, - 2 * (m_posY + m_height) - 1.0f, + 2 * (m_position.x) - 1.0f, + 2 * (m_position.y + m_dimensions.y) - 1.0f, 0.0f, // Top left - 2 * (m_posX)-1.0f, - 2 * (m_posY)-1.0f, + 2 * (m_position.x) - 1.0f, + 2 * (m_position.y) - 1.0f, 0.0f, // Bottom left - 2 * (m_posX + m_width) - 1.0f, - 2 * (m_posY + m_height) - 1.0f, + 2 * (m_position.x + m_dimensions.x) - 1.0f, + 2 * (m_position.y + m_dimensions.y) - 1.0f, 0.0f // Top right }; @@ -70,7 +71,8 @@ bool Widget::isHovered(Window *window) double yrel = -ypos / height + 1; bool isHovered = false; - if (xrel >= m_posX && xrel <= m_posX + m_width && yrel >= m_posY && yrel <= m_posY + m_height) + if (xrel >= m_position.x && xrel <= m_position.x + m_dimensions.x && yrel >= m_position.y && + yrel <= m_position.y + m_dimensions.x) isHovered = true; return isHovered; diff --git a/src/Widget.h b/src/Widget.h index 7b0076c..d62555f 100644 --- a/src/Widget.h +++ b/src/Widget.h @@ -1,7 +1,9 @@ #pragma once +#include "Texture.h" #include "definitions/models.h" +#include #include #include @@ -14,7 +16,16 @@ class Mesh; class Widget { public: - Widget(std::string &name, Texture *texture, float x, float y, float w, float h, uint16_t callbackId); + struct Prototype + { + std::string name; + glm::vec2 position; + glm::vec2 dimensions; + Texture::Prototype texturePrototype; + uint16_t callBackId; // TODO: will be removed... + }; + + Widget(Prototype prototype, Texture *texture); ~Widget(); void draw(ShaderProgram *shaderProgram); @@ -25,7 +36,8 @@ public: bool isHovered(Window *window); private: - double m_posX, m_posY, m_width, m_height; + glm::vec2 m_position; + glm::vec2 m_dimensions; std::string m_uniqueName; diff --git a/src/World.cpp b/src/World.cpp index b4a82e4..313440a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -13,8 +13,8 @@ #include World::World(std::vector shaderPrograms) - : m_shaderProgram(Controller::getShaderProgramByName(shaderPrograms, "defaultProgram")), - m_depthMapDirectionalFBO(DepthMapType::Normal, SHADOW_RES) + : m_depthMapDirectionalFBO(DepthMapType::Normal, SHADOW_RES), + m_shaderProgram(Controller::getShaderProgramByName("defaultProgram", shaderPrograms)) { // Create 4 depthMaps for (int i = 0; i < 4; i++) { @@ -37,13 +37,13 @@ World::World(std::vector shaderPrograms) for (auto &prototype : modelPrototypes) { auto loadModel = [=, &mutex]() { - Model *current_model = new Model(prototype); + Model *currentModel = new Model(prototype); std::cout << "Loaded Model \"" << prototype.modelName << "\" from \"" << prototype.modelPath << "\"" << std::endl; std::lock_guard lock(mutex); - m_models.push_back(current_model); + m_models.push_back(currentModel); }; futures.push_back(std::async(std::launch::async, loadModel)); @@ -53,9 +53,41 @@ World::World(std::vector shaderPrograms) for (auto &model : m_models) model->initializeOnGPU(); - m_entities = modelParser.getEntities(m_models, shaderPrograms); + std::vector entityPrototypes = modelParser.getEntityPrototypes(); + + std::vector entities; + { + for (auto &prototype : entityPrototypes) { + // Get model + Model *currentModel = getModelByName(prototype.modelName); + + if (!currentModel) { + // Apply fallback model (first model in vector) + currentModel = m_models[0]; + std::cout << "[Warning] Model could not be found by name \"" << prototype.modelName << "\"" + << std::endl; + } + + // Get shaderprogram + ShaderProgram *currentProgram = + Controller::getShaderProgramByName(prototype.shaderProgramName, shaderPrograms); + + if (!currentProgram) { + currentProgram = Controller::getShaderProgramByName("basic", shaderPrograms); + } + + Entity *currentEntity = new Entity(prototype, currentModel, currentProgram); + + std::cout << "Loaded Entity \"" << prototype.name << "\" with model \"" << prototype.modelName << "\"" + << std::endl; + + entities.push_back(currentEntity); + } + } + + m_entities = entities; m_skybox = modelParser.getSkybox(getModelByName("cube"), - Controller::getShaderProgramByName(shaderPrograms, "skyboxProgram")); + Controller::getShaderProgramByName("skyboxProgram", shaderPrograms)); JsonParser lightParser("data/lights.json"); m_lights = lightParser.getLights(m_shaderProgram); diff --git a/src/main.cpp b/src/main.cpp index 696f34f..297a6a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,17 +13,16 @@ int main(int argc, char **argv) #endif // Create controller - Controller *mainController = new Controller(); + Controller &controller = Controller::instance(); const char *fps_env = std::getenv("MAXFPS"); if (fps_env) { uint16_t maxfps = std::stoul(fps_env); - mainController->setMaxFps(maxfps); + controller.setMaxFps(maxfps); std::cout << "[Warning] Default max FPS overridden with " << maxfps << " by environment." << std::endl; } - mainController->run(); + controller.run(); - delete mainController; return 0; }