diff options
Diffstat (limited to 'engine-ocean/Game/Systems/UI')
-rw-r--r-- | engine-ocean/Game/Systems/UI/ButtonAction/buttonaction.cpp | 6 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/ButtonAction/buttonaction.h | 13 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/ButtonAction/showwindowaction.cpp | 33 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/ButtonAction/showwindowaction.h | 21 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/UITextures/UIButton.h | 94 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/UITextures/uibutton.cpp | 202 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/UITextures/uidisplay.cpp | 130 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/UITextures/uidisplay.h | 67 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/UITextures/uitexture.cpp | 6 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/UITextures/uitexture.h | 39 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/uielement.cpp | 6 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/uielement.h | 40 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/uisystem.cpp | 383 | ||||
-rw-r--r-- | engine-ocean/Game/Systems/UI/uisystem.h | 89 |
14 files changed, 1129 insertions, 0 deletions
diff --git a/engine-ocean/Game/Systems/UI/ButtonAction/buttonaction.cpp b/engine-ocean/Game/Systems/UI/ButtonAction/buttonaction.cpp new file mode 100644 index 0000000..c7314f6 --- /dev/null +++ b/engine-ocean/Game/Systems/UI/ButtonAction/buttonaction.cpp @@ -0,0 +1,6 @@ +#include "buttonaction.h" + +ButtonAction::ButtonAction() +{ + +} diff --git a/engine-ocean/Game/Systems/UI/ButtonAction/buttonaction.h b/engine-ocean/Game/Systems/UI/ButtonAction/buttonaction.h new file mode 100644 index 0000000..d6c1674 --- /dev/null +++ b/engine-ocean/Game/Systems/UI/ButtonAction/buttonaction.h @@ -0,0 +1,13 @@ +#ifndef BUTTONACTION_H +#define BUTTONACTION_H + + +class ButtonAction +{ +public: + ButtonAction(); + virtual void activate() = 0; + virtual void deactivate() = 0; +}; + +#endif // BUTTONACTION_H diff --git a/engine-ocean/Game/Systems/UI/ButtonAction/showwindowaction.cpp b/engine-ocean/Game/Systems/UI/ButtonAction/showwindowaction.cpp new file mode 100644 index 0000000..e6b9797 --- /dev/null +++ b/engine-ocean/Game/Systems/UI/ButtonAction/showwindowaction.cpp @@ -0,0 +1,33 @@ +#include "showwindowaction.h" +#include "Game/Systems/UI/uisystem.h" +#include <map> + +ShowWindowAction::ShowWindowAction(std::map<std::string, std::shared_ptr<UIScreen>>& all_screens, + std::set<std::string>& shownScreens, + const std::string screenName): + m_screens(all_screens), + m_shownScreens(shownScreens) +{ + m_screenName = screenName; +} + + + +void ShowWindowAction::activate(){ + std::cout << "activated window show!!!" << std::endl; + + // add screen to be rendered, and also set it be the only one active + //m_screens[m_screenName] = m_screen; +// for (auto &screen : m_screens){ +// screen.second->isActive = false; +// } + +// m_screens[m_screenName]->isActive = true; + m_shownScreens.insert(m_screenName); + m_screens[m_screenName]->isActive = true; + +} + +void ShowWindowAction::deactivate(){ + m_shownScreens.erase(m_screenName); +} diff --git a/engine-ocean/Game/Systems/UI/ButtonAction/showwindowaction.h b/engine-ocean/Game/Systems/UI/ButtonAction/showwindowaction.h new file mode 100644 index 0000000..781f093 --- /dev/null +++ b/engine-ocean/Game/Systems/UI/ButtonAction/showwindowaction.h @@ -0,0 +1,21 @@ +#ifndef SHOWWINDOWACTION_H +#define SHOWWINDOWACTION_H +#include "Game/Systems/UI/uisystem.h" +#include <map> +#include "buttonaction.h" + +class ShowWindowAction : public ButtonAction +{ +public: + ShowWindowAction(std::map<std::string, std::shared_ptr<UIScreen>>& screens, + std::set<std::string>& shownScreens, + const std::string screenName); + void activate() override; + void deactivate() override; +private: + std::set<std::string>& m_shownScreens; + std::string m_screenName; + std::map<std::string, std::shared_ptr<UIScreen>>& m_screens; +}; + +#endif // SHOWWINDOWACTION_H diff --git a/engine-ocean/Game/Systems/UI/UITextures/UIButton.h b/engine-ocean/Game/Systems/UI/UITextures/UIButton.h new file mode 100644 index 0000000..8cf02ee --- /dev/null +++ b/engine-ocean/Game/Systems/UI/UITextures/UIButton.h @@ -0,0 +1,94 @@ +#ifndef UIBUTTON_H +#define UIBUTTON_H +#include "Game/Systems/UI/ButtonAction/buttonaction.h" +#include "Game/Systems/UI/UITextures/uidisplay.h" +#include "Graphics/global.h" +#include <GLFW/glfw3.h> +#include <set> +#include "uitexture.h" + +enum CornerPosition { + TOPLEFT, + TOPRIGHT, + BOTTOMLEFT, + BOTTOMRIGHT, + NONE +}; + +class UIButton : public UITexture +{ +public: + UIButton(TextureData tex, glm::vec2 pos, glm::vec2 scale, std::set<std::string>& shownScreens, + bool isCloseButton = false, CornerPosition corner = NONE, AspectRatio ratio = LAND_FIT); + ~UIButton(); + void draw() override; + GLuint getTexID() override; + glm::vec2 getPos() override; + glm::vec2 getScale() override; + float getTextureRatio() override; + AspectRatio getAspectRatio(); + + + + void setWindowPos(int width, int height) override; + glm::vec2 getWindowPos(); + + int getHeight() override; + int getWidth() override; + Bounds2f getBounds() override; + float getTextureScaleAspect() override; + + void addButtonAction(std::shared_ptr<ButtonAction> &action); + bool onButtonPress(); + void setWindowToClose(std::string windowID); + + void setParentDisplay(std::string parent); + std::string getParentDisplay(); + + CornerPosition getCornerPos(); + bool hasCornerPos = false; + void setToCorner(const CornerPosition corner, int width, int height); + + void setTransformationMat(glm::vec2 translation, glm::vec2 scale); + glm::mat4 getTransformationMat(); + + + +private: + glm::mat4 getScaleMatrix(glm::vec2 scale); + int getScreenHeight(); + int getScreenWidth(); + void setTexID(GLuint &newTexID); + + + TextureData m_tex; + glm::vec2 m_pos; + glm::vec2 m_scale; + Bounds2f m_bounds; + glm::vec2 m_windowPos; // width, height + float m_windowHeight = 480.f; + float m_windowWidth = 640.f; + float m_toScreenScale = 1.f; + + int m_screenImageHeight; + int m_screenImageWidth; + float m_tex_aspectRatio = 1.f; + bool m_isCloseButton = false; + std::string m_attachedWindow; + + std::vector<std::shared_ptr<ButtonAction>> m_actions; + std::set<std::string>& m_shownScreens; + + CornerPosition m_cornerPos; + std::string m_parentDisplay; + + glm::mat4 m_transformationMat; + float m_textureAspect = 1.f; + + AspectRatio m_aspectRatio; + + + +}; + +#endif // UIButton_H diff --git a/engine-ocean/Game/Systems/UI/UITextures/uibutton.cpp b/engine-ocean/Game/Systems/UI/UITextures/uibutton.cpp new file mode 100644 index 0000000..031be2f --- /dev/null +++ b/engine-ocean/Game/Systems/UI/UITextures/uibutton.cpp @@ -0,0 +1,202 @@ +#include "UIButton.h" +#include "Game/Systems/UI/UITextures/UIDisplay.h" +#include <set> + +UIButton::UIButton(TextureData tex, glm::vec2 pos, glm::vec2 scale, std::set<std::string>& shownScreens, + bool isCloseButton, CornerPosition corner, AspectRatio ratio): + m_tex(tex), + m_shownScreens(shownScreens), + m_aspectRatio(ratio) +{ + + // set variables + m_isCloseButton = isCloseButton; + m_pos = pos; + m_scale = scale; + m_tex_aspectRatio = static_cast<float>(m_tex.height)/static_cast<float>(m_tex.width); + + setToCorner(corner, 640, 480); + setWindowPos(640, 480); + setTransformationMat(m_pos, scale); + +} +UIButton::~UIButton(){ + glDeleteTextures(1, &m_tex.textureID); +} + + +AspectRatio UIButton::getAspectRatio(){ + return m_aspectRatio; +} + +glm::mat4 UIButton::getScaleMatrix(glm::vec2 scale) { + glm::mat4 M = glm::mat4(1.f); + M[0][0] = scale.x; //* (m_screenImageHeight/m_screenImageWidth); + M[1][1] = scale.y; //* (m_tex_aspectRatio); + M[2][2] = 1.f; + return M; +} + +void UIButton::setTransformationMat(glm::vec2 translation, glm::vec2 scale){ + glm::mat4 transMat = glm::mat4(1.f); + transMat[3] = glm::vec4(translation.x, translation.y, 0.f, 1.f); + glm::mat4 scaleMat = getScaleMatrix(glm::vec2(scale)); + m_transformationMat = transMat*scaleMat; +} + +glm::mat4 UIButton::getTransformationMat(){ + return m_transformationMat; +} + +float UIButton::getTextureRatio(){ + return m_tex_aspectRatio; +} + + +void UIButton::draw(){} + +GLuint UIButton::getTexID(){ + return m_tex.textureID; +} + +glm::vec2 UIButton::getPos(){ + return m_pos; +} + +glm::vec2 UIButton::getScale(){ + return m_scale; +} + +//void UIButton::setTexID(GLuint &newTexID){ +// m_tex.textureID = newTexID; +//} + +void UIButton::setWindowPos(int width, int height){ + m_windowHeight = static_cast<float>(height); + m_windowWidth = static_cast<float>(width); + + // find where on window it is, for bound checking + float xpos = .5f*(m_pos.x + 1.f)*m_windowWidth; + float ypos = (1.f-.5f*(m_pos.y + 1.f))*m_windowHeight; + m_windowPos = glm::vec2(xpos, ypos); + + // set everything according to window dimensions -- this is for bound checking + m_toScreenScale = m_windowHeight*m_scale.y; + m_screenImageHeight = m_toScreenScale; + m_screenImageWidth = m_toScreenScale * m_tex_aspectRatio; + + float windowRatio = m_windowHeight/m_windowWidth; + m_textureAspect = windowRatio / m_tex_aspectRatio; + + // calculate window bounds + glm::vec2 halfDimensions = glm::vec2(m_screenImageWidth, m_screenImageHeight)*.5f; + m_bounds.max = glm::vec2(m_windowPos.x + halfDimensions.x, m_windowPos.y - halfDimensions.y); + m_bounds.min = glm::vec2(m_windowPos.x - halfDimensions.x, m_windowPos.y + halfDimensions.y); +} + +float UIButton::getTextureScaleAspect(){ + return m_textureAspect; +} + +void UIButton::setParentDisplay(std::string parent){ + m_parentDisplay = parent; + +} + +std::string UIButton::getParentDisplay(){ + return m_parentDisplay; + +} + +CornerPosition UIButton::getCornerPos(){ + return m_cornerPos; + +} + +void UIButton::setToCorner(const CornerPosition corner, int width, int height){ + + m_toScreenScale = static_cast<float>(height)*m_scale.y; + m_screenImageHeight = m_toScreenScale; + m_screenImageWidth = m_toScreenScale * m_tex_aspectRatio; + + // in texture space + float xtrans = m_screenImageWidth/(.5f*static_cast<float>(width)); + float ytrans = m_screenImageHeight/(.5f*static_cast<float>(height)); + + // find where window pos should be + switch(corner){ + case TOPLEFT: + m_pos = glm::vec2(-1+xtrans, 1-ytrans); + + break; + case TOPRIGHT: + m_pos = glm::vec2(1-xtrans, 1-ytrans); + + break; + case BOTTOMLEFT: + m_pos = glm::vec2(-1+xtrans, -1+ytrans); + + break; + case BOTTOMRIGHT: + m_pos = glm::vec2(1-xtrans, -1+ytrans); + break; + default: + break; + } +} + +glm::vec2 UIButton::getWindowPos(){ + return m_windowPos; +} + +int UIButton::getHeight(){ + return m_tex.height; +} +int UIButton::getWidth(){ + return m_tex.width; +} + +int UIButton::getScreenHeight(){ + return m_screenImageHeight; +} +int UIButton::getScreenWidth(){ + return m_screenImageWidth; +} + +// remember that origin is top left corner!! +Bounds2f UIButton::getBounds(){ + + return m_bounds; +} + +void UIButton::addButtonAction(std::shared_ptr<ButtonAction> &action){ + m_actions.push_back(action); +} + +//////*/ for close button only +void UIButton::setWindowToClose(std::string windowID){ + if (m_isCloseButton){ + m_attachedWindow = windowID; + } + +} + +bool UIButton::onButtonPress(){ + // if button is a close button, then deactivate everything + if (m_isCloseButton){ + std::cout << "shownWindowSize: " << m_shownScreens.size() << std::endl; + //m_shownScreens.erase(m_attachedWindow); + std::cout << "new shownWindowSize: " << m_shownScreens.size() << std::endl; + std::cout << "CLOSE WINDOW: " << m_attachedWindow << std::endl; + return true; + + + } else { + for (auto &action : m_actions){ + action->activate(); + } + return false; + } + +} + diff --git a/engine-ocean/Game/Systems/UI/UITextures/uidisplay.cpp b/engine-ocean/Game/Systems/UI/UITextures/uidisplay.cpp new file mode 100644 index 0000000..2ddaf62 --- /dev/null +++ b/engine-ocean/Game/Systems/UI/UITextures/uidisplay.cpp @@ -0,0 +1,130 @@ +#include "uidisplay.h" +#include <set> + +UIDisplay::UIDisplay(TextureData tex, glm::vec2 pos, glm::vec2 scale, + std::set<std::string>& shownScreens, + AspectRatio ratio): + m_tex(tex), + m_shownScreens(shownScreens), + m_aspectRatio(ratio) +{ + + m_pos = (pos); + m_scale = (scale); + m_tex_aspectRatio = static_cast<float>(m_tex.height)/static_cast<float>(m_tex.width); + setTransformationMat(pos, scale); +// std::cout << "tex aspect ratio:" << m_tex_aspectRatio << std::endl; + +// std::cout << "aspect ratio w: " << m_tex.width << std::endl; +// std::cout << "aspect ratio h: " << m_tex.height << std::endl; + + + setWindowPos(640, 480); +// std::cout << "screen image height: " << m_screenImageHeight << std::endl; +// std::cout << "screen image width: " << m_screenImageWidth << std::endl; + +} + +UIDisplay::~UIDisplay(){ + glDeleteTextures(1, &m_tex.textureID); +} + +void UIDisplay::draw(){} + +GLuint UIDisplay::getTexID(){ + return m_tex.textureID; +} + +glm::vec2 UIDisplay::getPos(){ + return m_pos; +} + +glm::vec2 UIDisplay::getScale(){ + return m_scale; +} + +AspectRatio UIDisplay::getAspectRatio(){ + return m_aspectRatio; +} + +void UIDisplay::setWindowPos(int width, int height){ + float xpos = .5f*(m_pos.x + 1.f)*static_cast<float>(width); + float ypos = (1.f-.5f*(m_pos.y + 1.f))*static_cast<float>(height); + m_windowPos = glm::vec2(xpos, ypos); + + // set everything according to window dimensions + m_toScreenScale = static_cast<float>(height)*m_scale.y; + m_screenImageHeight = m_toScreenScale; + m_screenImageWidth = m_toScreenScale * m_tex_aspectRatio; + + float windowRatio = static_cast<float>(height)/static_cast<float>(width); + m_textureAspect = windowRatio / m_tex_aspectRatio; +} + +void UIDisplay::setPos(glm::vec2 pos){ + m_pos = pos; + setTransformationMat(m_pos, m_scale); +} +void UIDisplay::setScale(glm::vec2 scale){ + m_scale = scale; + setTransformationMat(m_pos, m_scale); +} + +float UIDisplay::getTextureScaleAspect(){ + return m_textureAspect; +} + +glm::vec2 UIDisplay::getWindowPos(){ + return m_windowPos; +} + +int UIDisplay::getHeight(){ + return m_tex.height; +} +int UIDisplay::getWidth(){ + return m_tex.width; +} + +int UIDisplay::getScreenHeight(){ + return m_screenImageHeight; +} +int UIDisplay::getScreenWidth(){ + return m_screenImageWidth; +} + +glm::mat4 UIDisplay::getScaleMatrix(glm::vec2 scale) { + glm::mat4 M = glm::mat4(1.f); + M[0][0] = scale.x;//* (m_screenImageHeight/m_screenImageWidth); + M[1][1] = scale.y; //* (m_tex_aspectRatio); + M[2][2] = 1.f; + return M; +} + +void UIDisplay::setTransformationMat(glm::vec2 translation, glm::vec2 scale){ + glm::mat4 transMat = glm::mat4(1.f); + transMat[3] = glm::vec4(translation.x, translation.y, 0.f, 1.f); + + glm::mat4 scaleMat = getScaleMatrix(glm::vec2(scale)); + + m_transformationMat = transMat*scaleMat; +} + +glm::mat4 UIDisplay::getTransformationMat(){ + return m_transformationMat; +} + +// remember that origin is top left corner!! +Bounds2f UIDisplay::getBounds(){ + glm::vec2 halfDimensions = glm::vec2(m_screenImageWidth, m_screenImageHeight)*.5f; + m_bounds.max = glm::vec2(m_windowPos.x + halfDimensions.x, m_windowPos.y - halfDimensions.y); + m_bounds.min = glm::vec2(m_windowPos.x - halfDimensions.x, m_windowPos.y + halfDimensions.y); + return m_bounds; +} + +float UIDisplay::getTextureRatio(){ + return m_tex_aspectRatio; +} + + + + diff --git a/engine-ocean/Game/Systems/UI/UITextures/uidisplay.h b/engine-ocean/Game/Systems/UI/UITextures/uidisplay.h new file mode 100644 index 0000000..4b739cc --- /dev/null +++ b/engine-ocean/Game/Systems/UI/UITextures/uidisplay.h @@ -0,0 +1,67 @@ +#ifndef UIDISPLAY_H +#define UIDISPLAY_H +#include "uitexture.h" +#include <set> + + + +class UIDisplay : public UITexture +{ +public: + UIDisplay(TextureData tex, glm::vec2 pos, glm::vec2 scale, std::set<std::string>& shownScreens, + AspectRatio ratio = FIT_SCREEN); + ~UIDisplay(); + void draw() override; + GLuint getTexID() override; + glm::vec2 getPos() override; + glm::vec2 getScale() override; + + void setWindowPos(int width, int height) override; + glm::vec2 getWindowPos(); + + int getHeight() override; + int getWidth() override; + Bounds2f getBounds() override; + float getTextureRatio() override; + float getTextureScaleAspect() override; + void setPos(glm::vec2 pos); + void setScale(glm::vec2 scale); + + AspectRatio getAspectRatio(); + + + // glm::vec2 getCornerPos(CornerPosition corner, glm::vec2 elementDimensions); + void setTransformationMat(glm::vec2 translation, glm::vec2 scale); + glm::mat4 getTransformationMat(); + +private: + int getScreenHeight(); + int getScreenWidth(); + void setTexID(GLuint &newTexID); + glm::mat4 getScaleMatrix(glm::vec2 scale); + + + + TextureData m_tex; + glm::vec2 m_pos; + glm::vec2 m_scale; + Bounds2f m_bounds; + glm::vec2 m_windowPos; // width, height + int m_windowHeight = 480.f; + int m_windowWidth = 640.f; + float m_toScreenScale = 1.f; + + int m_screenImageHeight; + int m_screenImageWidth; + float m_tex_aspectRatio = 1.f; + bool m_isCloseButton = false; + std::string m_attachedWindow; + + std::set<std::string>& m_shownScreens; + glm::mat4 m_transformationMat; + float m_textureAspect = 1.f; + + AspectRatio m_aspectRatio; +}; + +#endif // UIDISPLAY_H diff --git a/engine-ocean/Game/Systems/UI/UITextures/uitexture.cpp b/engine-ocean/Game/Systems/UI/UITextures/uitexture.cpp new file mode 100644 index 0000000..8680baf --- /dev/null +++ b/engine-ocean/Game/Systems/UI/UITextures/uitexture.cpp @@ -0,0 +1,6 @@ +#include "uitexture.h" + +UITexture::UITexture() +{ + +} diff --git a/engine-ocean/Game/Systems/UI/UITextures/uitexture.h b/engine-ocean/Game/Systems/UI/UITextures/uitexture.h new file mode 100644 index 0000000..53e429d --- /dev/null +++ b/engine-ocean/Game/Systems/UI/UITextures/uitexture.h @@ -0,0 +1,39 @@ +#ifndef UITEXTURE_H +#define UITEXTURE_H +#include "Graphics/global.h" +#include <GLFW/glfw3.h> + +struct Bounds2f{ + glm::vec2 min; + glm::vec2 max; +}; + +enum AspectRatio { + LAND_FIT, + LAND_FILL, + PORTRAIT_FIT, + PORTRAIT_FILL, + FIT_SCREEN +}; + +class UITexture +{ +public: + UITexture(); + virtual void draw() = 0; + virtual GLuint getTexID() = 0; + virtual glm::vec2 getPos() = 0; + virtual glm::vec2 getScale() = 0; + virtual int getHeight() = 0; + virtual int getWidth() = 0; + virtual Bounds2f getBounds() = 0; + virtual void setWindowPos(int width, int height) = 0; + virtual float getTextureRatio() = 0; + virtual float getTextureScaleAspect() = 0; + + + + +}; + +#endif // UITEXTURE_H diff --git a/engine-ocean/Game/Systems/UI/uielement.cpp b/engine-ocean/Game/Systems/UI/uielement.cpp new file mode 100644 index 0000000..bb7d91f --- /dev/null +++ b/engine-ocean/Game/Systems/UI/uielement.cpp @@ -0,0 +1,6 @@ +#include "uielement.h" + +UIElement::UIElement() +{ + +} diff --git a/engine-ocean/Game/Systems/UI/uielement.h b/engine-ocean/Game/Systems/UI/uielement.h new file mode 100644 index 0000000..c2c3a2e --- /dev/null +++ b/engine-ocean/Game/Systems/UI/uielement.h @@ -0,0 +1,40 @@ +#ifndef UIELEMENT_H +#define UIELEMENT_H + + +#include "Game/Systems/UI/UITextures/uitexture.h" +#include "Game/TypeMap.h" +#include <memory> +class UIElement +{ +public: + UIElement(); + + template <typename T> + void addComponent(std::unique_ptr<T> &&component){ + m_components.put<T>(std::forward<std::unique_ptr<T>>(component)); + } + + template <typename T> + bool hasComponent(){ + return m_components.contains<T>(); + } + + template <class T> + T* getComponent(){ + auto comp = m_components.find<T>(); + assert(comp != m_components.end()); + return static_cast<T*>(comp->second.get()); + } + + template <class T> + void removeComponent(){ + m_components.remove<T>(); + } + +private: + + TypeMap<std::unique_ptr<UITexture>> m_components; +}; + +#endif // UIELEMENT_H diff --git a/engine-ocean/Game/Systems/UI/uisystem.cpp b/engine-ocean/Game/Systems/UI/uisystem.cpp new file mode 100644 index 0000000..09aff49 --- /dev/null +++ b/engine-ocean/Game/Systems/UI/uisystem.cpp @@ -0,0 +1,383 @@ +#include "uisystem.h" +#include "Game/GameWorld.h" +#include "Game/Systems/UI/ButtonAction/showwindowaction.h" +#include "Game/Systems/UI/UITextures/UIButton.h" +#include "Game/Systems/UI/UITextures/uidisplay.h" +#define GLFW_POINTING_HAND_CURSOR + +UISystem::UISystem(std::shared_ptr<Camera> camera, + std::map<int, Input>& input_map, + std::set<std::string>& shownScreens): + m_camera(camera), + m_input_map(input_map), + m_shownScreens(shownScreens) +{ + + + initializeStartScreen(); + initializeScreenMap(); + //m_pointerCursor = glfwCreateStandardCursor(GLFW_POINTING_HAND_CURSOR); + +} + +UISystem::~UISystem(){ + for (auto &screenID : m_all_screens){ + glDeleteVertexArrays(1, &screenID.second->screenVAOID); + } +} + +void UISystem::initializeScreenMap(){ + initializeProfileScreen(); + initializeInventory(); + initializeScreen(); + + m_shownScreens.insert("home"); + +} + +void UISystem::initializeScreen(){ + std::shared_ptr<UIScreen> home = std::make_shared<UIScreen>(); + home->isActive = true; + home->screenVAOID = Global::graphics.makeVAO(m_quadPos); + m_quad_numVertices = 4; + + float topLevel = .85f; + + makeButtonElement(home, "profileButton", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/profileicon.png", glm::vec2(.85f,topLevel), glm::vec2(.05f), AspectRatio::LAND_FILL); + std::shared_ptr<ButtonAction> showProfile = std::make_shared<ShowWindowAction>(m_all_screens, m_shownScreens, "profile"); + home->screenElements.at("profileButton")->getComponent<UIButton>()->addButtonAction(showProfile); + + makeButtonElement(home, "inventoryButton", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/inventoryicon.png", glm::vec2(.75f, topLevel), glm::vec2(.05f), AspectRatio::LAND_FILL); + std::shared_ptr<ButtonAction> showInv = std::make_shared<ShowWindowAction>(m_all_screens, m_shownScreens, "inventory"); + home->screenElements.at("inventoryButton")->getComponent<UIButton>()->addButtonAction(showInv); + + makeButtonElement(home, "questsButton", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/questicon.png", glm::vec2(.65f, topLevel), glm::vec2(.05f), AspectRatio::LAND_FILL); + makeButtonElement(home, "settingsButton", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/settings_icon.png", glm::vec2(-.85f, topLevel), glm::vec2(.05f), AspectRatio::LAND_FILL); + makeDisplayElement(home, "healthbar", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/healthbar.png", glm::vec2(0.f, -.5f), glm::vec2(.4f), AspectRatio::LAND_FIT); + +// TextureData reflectTex; +// reflectTex.textureID = Global::graphics.getReflectionTexture(); +// reflectTex.width = Global::graphics.REFLECTION_W; +// reflectTex.height = Global::graphics.REFLECTION_H; +// makeDisplayElement(home, "reflection", reflectTex, glm::vec2(.5f, -.5f), glm::vec2(.3f), AspectRatio::LAND_FIT); + +// TextureData refractTex; +// refractTex.textureID = Global::graphics.getRefractionTexture(); +// refractTex.width = Global::graphics.REFRACTION_W; +// refractTex.height = Global::graphics.REFRACTION_H; +// makeDisplayElement(home, "refract", refractTex, glm::vec2(-.5f, -.5f), glm::vec2(.3f), AspectRatio::LAND_FIT); + + + + + home->elementsDepthOrder.push_back("profileButton"); + home->elementsDepthOrder.push_back("inventoryButton"); + home->elementsDepthOrder.push_back("questsButton"); + home->elementsDepthOrder.push_back("settingsButton"); + home->elementsDepthOrder.push_back("healthbar"); + // home->elementsDepthOrder.push_back("reflection"); + // home->elementsDepthOrder.push_back("refract"); + + + + m_all_screens.insert({"home", home}); +} + +void UISystem::initializeProfileScreen(){ + + std::shared_ptr<UIScreen> profile = std::make_shared<UIScreen>(); + profile->isActive = false; + profile->screenVAOID = Global::graphics.makeVAO(m_quadPos); + m_quad_numVertices = 4; + + float topLevel = .85f; + + // eventually should be display, not button + makeDisplayElement(profile, "bg", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/inventory_bg.png", glm::vec2(0.f), glm::vec2(1.0f)); + makeDisplayElement(profile, "profileDisplay", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/mouse_profile.png", glm::vec2(0.f), glm::vec2(1.0f), AspectRatio::LAND_FIT); + makeButtonElement(profile, "closeButton", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/close_icon.png", glm::vec2(0.f), glm::vec2(.05f), AspectRatio::LAND_FILL, true, CornerPosition::TOPRIGHT); + profile->screenElements.at("closeButton")->getComponent<UIButton>()->setWindowToClose("profile"); + + profile->elementsDepthOrder.push_back("bg"); + profile->elementsDepthOrder.push_back("profileDisplay"); + profile->elementsDepthOrder.push_back("closeButton"); + + m_all_screens.insert({"profile", profile}); +} + +void UISystem::initializeInventory(){ + std::shared_ptr<UIScreen> inv = std::make_shared<UIScreen>(); + inv->isActive = false; + inv->screenVAOID = Global::graphics.makeVAO(m_quadPos); + m_quad_numVertices = 4; + + makeDisplayElement(inv, "bg", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/inventory_bg.png", glm::vec2(0.f), glm::vec2(1.0f)); + makeDisplayElement(inv, "inventoryDisplay", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/inventory_page.png", glm::vec2(0.f), glm::vec2(1.0f), AspectRatio::LAND_FIT); + makeButtonElement(inv, "closeButton", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/close_icon.png", glm::vec2(0.f), glm::vec2(.05f), AspectRatio::LAND_FILL, true, CornerPosition::TOPRIGHT); + inv->screenElements.at("closeButton")->getComponent<UIButton>()->setWindowToClose("inventory"); + inv->elementsDepthOrder.push_back("bg"); + inv->elementsDepthOrder.push_back("inventoryDisplay"); + inv->elementsDepthOrder.push_back("closeButton"); + + m_all_screens.insert({"inventory", inv}); +} + +void UISystem::initializeStartScreen(){ + + std::shared_ptr<UIScreen> start = std::make_shared<UIScreen>(); + start->isActive = true; + start->screenVAOID = Global::graphics.makeVAO(m_quadPos); + + float topLevel = .85f; + + // eventually should be display, not button + makeDisplayElement(start, "startDisplay", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/title.png", glm::vec2(0.f), glm::vec2(1.0f), AspectRatio::LAND_FIT); + makeButtonElement(start, "startButton", "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/enterbutton.png", glm::vec2(0.f, -.57f), glm::vec2(.19f), AspectRatio::LAND_FIT, true); + start->screenElements.at("startButton")->getComponent<UIButton>()->setWindowToClose("start"); + + start->elementsDepthOrder.push_back("startDisplay"); + start->elementsDepthOrder.push_back("startButton"); + + m_all_screens.insert({"start", start}); + m_shownScreens.insert("start"); +} + +glm::vec2 UISystem::drawAspect(AspectRatio aspectType, float textureAspect){ + switch(aspectType){ + case FIT_SCREEN: + return glm::vec2(1.f); + break; + case LAND_FIT:case PORTRAIT_FILL: + return glm::vec2(1.f, textureAspect); + break; + case LAND_FILL: case PORTRAIT_FIT: + return glm::vec2(1.f/textureAspect, 1.f); + break; + } +} + + + +void UISystem::makeButtonElement(std::shared_ptr<UIScreen> &screen, + std::string elementName, const char* filename, + const glm::vec2 pos, const glm::vec2 scale, + AspectRatio aspectRatio, + bool isCloseButton, + CornerPosition corner){ + TextureData tex = Global::graphics.loadTextureFromFile(filename); + + std::shared_ptr<UIElement> uiElement = std::make_shared<UIElement>(); + + uiElement->addComponent<UIButton>(std::make_unique<UIButton>(tex, pos, scale, m_shownScreens, isCloseButton, corner, aspectRatio)); + screen->screenElements.insert({elementName, uiElement}); +} + +void UISystem::makeDisplayElement(std::shared_ptr<UIScreen> &screen, + std::string elementName, const char* filename, + const glm::vec2 pos, const glm::vec2 scale, + AspectRatio aspectRatio){ + TextureData tex = Global::graphics.loadTextureFromFile(filename); + + std::shared_ptr<UIElement> uiElement = std::make_shared<UIElement>(); + uiElement->addComponent<UIDisplay>(std::make_unique<UIDisplay>(tex, pos, scale, m_shownScreens, aspectRatio)); + screen->screenElements.insert({elementName, uiElement}); +} + +void UISystem::makeDisplayElement(std::shared_ptr<UIScreen> &screen, + std::string elementName, TextureData &tex, + const glm::vec2 pos, const glm::vec2 scale, + AspectRatio aspectRatio){ + + std::shared_ptr<UIElement> uiElement = std::make_shared<UIElement>(); + uiElement->addComponent<UIDisplay>(std::make_unique<UIDisplay>(tex, pos, scale, m_shownScreens, aspectRatio)); + screen->screenElements.insert({elementName, uiElement}); +} + +void UISystem::renderScreen(){ + // bind shader + Global::graphics.bindShader("ui"); + + // for window resizing + Global::graphics.setCameraData(m_camera); + + // enable alpha blending + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // disable depth testing + glDisable(GL_DEPTH_TEST); + + for (auto &screenID : m_shownScreens){ + // bind quad + glBindVertexArray(m_all_screens[screenID]->screenVAOID); + glEnableVertexAttribArray(0); + + // loop through inventory ui elements + + // loop through ui elements + for (auto &gui: m_all_screens[screenID]->elementsDepthOrder){ + if (m_all_screens[screenID]->screenElements[gui]->hasComponent<UIDisplay>()){ + GLuint texID; + if (gui == "reflection"){ + //std::cout << "rendering reflection" << std::endl; + texID = Global::graphics.getReflectionTexture(); + } else if (gui == "refract"){ + texID = Global::graphics.getRefractionTexture(); + } else { + texID = m_all_screens[screenID]->screenElements[gui]->getComponent<UIDisplay>()->getTexID(); + } + glm::mat4 transMat = m_all_screens[screenID]->screenElements[gui]->getComponent<UIDisplay>()->getTransformationMat(); + float texAspect = m_all_screens[screenID]->screenElements[gui]->getComponent<UIDisplay>()->getTextureScaleAspect(); + AspectRatio ratio = m_all_screens[screenID]->screenElements[gui]->getComponent<UIDisplay>()->getAspectRatio(); + + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_2D, texID); + + glm::vec2 texScale = drawAspect(ratio, texAspect); + + glUniform2f(glGetUniformLocation(Global::graphics.getShaderID("ui"), "textureScale"), texScale.x, texScale.y); + glUniformMatrix4fv(glGetUniformLocation(Global::graphics.getShaderID("ui"), "transform"), 1, GL_FALSE, glm::value_ptr(transMat[0])); + glDrawArrays(GL_TRIANGLE_STRIP, 0, m_quad_numVertices); + } + if (m_all_screens[screenID]->screenElements[gui]->hasComponent<UIButton>()){ + GLuint texID = m_all_screens[screenID]->screenElements[gui]->getComponent<UIButton>()->getTexID(); + glm::mat4 transMat = m_all_screens[screenID]->screenElements[gui]->getComponent<UIButton>()->getTransformationMat(); + float texAspect = m_all_screens[screenID]->screenElements[gui]->getComponent<UIButton>()->getTextureScaleAspect(); + AspectRatio ratio = m_all_screens[screenID]->screenElements[gui]->getComponent<UIButton>()->getAspectRatio(); + + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_2D, texID); + + glm::vec2 texScale = drawAspect(ratio, texAspect); + + glUniform2f(glGetUniformLocation(Global::graphics.getShaderID("ui"), "textureScale"), texScale.x, texScale.y); + glUniformMatrix4fv(glGetUniformLocation(Global::graphics.getShaderID("ui"), "transform"), 1, GL_FALSE, glm::value_ptr(transMat[0])); + glDrawArrays(GL_TRIANGLE_STRIP, 0, m_quad_numVertices); + + + } + + } + glDisableVertexAttribArray(0); + glBindVertexArray(0); + } + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); +} + + + +void UISystem::draw(){ + renderScreen(); +} + +glm::mat4 UISystem::getScaleMatrix(glm::vec2 scale) { + glm::mat4 M = glm::mat4(1.f); + M[0][0] = scale.x * (m_aspectRatio); + M[1][1] = scale.y; + M[2][2] = 0.f; + return M; +} + +glm::mat4 UISystem::makeTransformationMat(glm::vec2 translation, glm::vec2 scale){ + glm::mat4 transMat = glm::mat4(1.f); + transMat[3] = glm::vec4(translation.x, translation.y, 0.f, 1.f); + + glm::mat4 scaleMat = getScaleMatrix(glm::vec2(scale)); + + return transMat*scaleMat; +} + +void UISystem::update(double deltaTime){ + // allow for one more update cycle before deactivating click + if (m_input_map[GLFW_MOUSE_BUTTON_LEFT].isClicked){ + // check if clicked inside gui + // only act on the front-most gui being clicked + std::set<std::string>::iterator it = m_shownScreens.begin(); + while(it != m_shownScreens.end()) { + std::set<std::string>::iterator current = it++; + std::string screenID = *current; + // render all active screens + if (m_all_screens[screenID]->isActive){ + // loop through ui elements + for (auto &gui: m_all_screens[screenID]->screenElements){ + if (gui.second->hasComponent<UIButton>()){ + bool isInside = false; + Bounds2f buttonBounds = gui.second->getComponent<UIButton>()->getBounds(); + isInside = checkInsideGUI(m_mousepos, buttonBounds); + if (isInside){ + bool toClose = gui.second->getComponent<UIButton>()->onButtonPress(); + if (toClose){ + m_shownScreens.erase(current); + + } + } + } + } + } + } + + if (m_input_map[GLFW_MOUSE_BUTTON_LEFT].checkClickTime > 1){ + m_input_map[GLFW_MOUSE_BUTTON_LEFT].isClicked = false; + } else { + m_input_map[GLFW_MOUSE_BUTTON_LEFT].checkClickTime ++; + } + } +} + +bool UISystem::checkInsideGUI(glm::vec2 mouseClickPos, Bounds2f guiBounds){ + if (mouseClickPos.x < guiBounds.max.x + && mouseClickPos.x > guiBounds.min.x + && mouseClickPos.y > guiBounds.max.y + && mouseClickPos.y < guiBounds.min.y){ + return true; + } + + return false; +} + + +void UISystem::scrollEvent(double distance){} + +void UISystem::mousePosEvent(double xpos, double ypos){ + m_mousepos = glm::vec2(xpos, ypos); + + for (auto &screenID : m_shownScreens){ + Global::graphics.bindShader("ui"); + //glUniform1i(glGetUniformLocation(Global::graphics.getShaderID("ui"), "hovering"), false); + // render all active screens + if (m_all_screens[screenID]->isActive){ + // loop through ui elements + for (auto &gui: m_all_screens[screenID]->screenElements){ + if (gui.second->hasComponent<UIButton>()){ + bool isInside; + Bounds2f buttonBounds = gui.second->getComponent<UIButton>()->getBounds(); + isInside = checkInsideGUI(m_mousepos, buttonBounds); + if (isInside){ + //glfwSetCursor(window, m_pointerCursor); + // hover effect + //glUniform1i(glGetUniformLocation(Global::graphics.getShaderID("ui"), "hovering"), true); + } + } + } + } + } +} + +void UISystem::onWindowResize(int width, int height){ + m_windowWidth = width; + m_windowHeight = height; + m_aspectRatio = static_cast<float>(m_windowHeight)/static_cast<float>(m_windowWidth); + + for (auto &screen : m_all_screens){ + // loop through ui elements + for (auto &gui: screen.second->screenElements){ + if (gui.second->hasComponent<UIButton>()){ + gui.second->getComponent<UIButton>()->setWindowPos(width, height); + } + if (gui.second->hasComponent<UIDisplay>()){ + gui.second->getComponent<UIDisplay>()->setWindowPos(width, height); + } + } + } +} diff --git a/engine-ocean/Game/Systems/UI/uisystem.h b/engine-ocean/Game/Systems/UI/uisystem.h new file mode 100644 index 0000000..1094861 --- /dev/null +++ b/engine-ocean/Game/Systems/UI/uisystem.h @@ -0,0 +1,89 @@ +#ifndef UISYSTEM_H +#define UISYSTEM_H +#include "Game/GameWorld.h" +#include "Game/Systems/UI/UITextures/UIButton.h" +#include "Game/Systems/UI/UITextures/uitexture.h" +#include "Game/Systems/UI/uielement.h" +#include "Graphics/global.h" +#include <GLFW/glfw3.h> +#include "Game/Systems/system.h" + +struct UIScreen{ + bool isActive = false; + GLuint screenVAOID; + std::map<std::string, std::shared_ptr<UIElement>> screenElements; + std::vector<std::string> elementsDepthOrder; +}; + + +class UISystem : public System +{ +public: + UISystem(std::shared_ptr<Camera> camera, + std::map<int, Input>& input_map, + std::set<std::string>& shownScreens); + ~UISystem(); + + void draw() override; + void update(double deltaTime) override; + void scrollEvent(double distance) override; + void mousePosEvent(double xpos, double ypos) override; + void onWindowResize(int width, int height); + GLuint makeVAO(std::vector<float> positions); + +private: + + int m_quad_numVertices = 4; + + void initializeScreenMap(); + void initializeScreen(); + void initializeStartScreen(); + void initializeInventory(); + + + void renderScreen(); + glm::mat4 makeTransformationMat(glm::vec2 translation, glm::vec2 scale); + glm::mat4 getScaleMatrix(glm::vec2 scale); + bool checkInsideGUI(glm::vec2 mouseClickPos, Bounds2f guiBounds); + void initializeProfileScreen(); + + + void makeButtonElement(std::shared_ptr<UIScreen> &screen, std::string elementName, const char* filename, const glm::vec2 pos, const glm::vec2 scale, AspectRatio aspectRatio, bool isCloseButton = false, CornerPosition corner = NONE); + void makeDisplayElement(std::shared_ptr<UIScreen> &screen, std::string elementName, const char* filename, const glm::vec2 pos, const glm::vec2 scale, AspectRatio aspectRatio = FIT_SCREEN); + void makeDisplayElement(std::shared_ptr<UIScreen> &screen, std::string elementName, TextureData &tex, const glm::vec2 pos, const glm::vec2 scale, AspectRatio aspectRatio = FIT_SCREEN); + + + + std::shared_ptr<Camera> m_camera; + float m_windowWidth = 640; + float m_windowHeight = 480; + float m_aspectRatio = 480.f/640.f; + + glm::vec2 m_mousepos = glm::vec2(0.f); + std::map<int, Input>& m_input_map; + + std::map<std::string, std::shared_ptr<UIScreen>> m_all_screens; + + GLFWcursor* m_pointerCursor; + + std::shared_ptr<ButtonAction> showProfileAction; + + std::set<std::string>& m_shownScreens; + float m_showStartScreen = true; + + + float dim = 1.0f; + std::vector<float> m_quadPos = { + -1.0f, 1.0f, + -1.0f, -1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f + }; + + glm::vec2 drawAspect(AspectRatio aspectType, float textureAspect); + + + +}; + +#endif // UISYSTEM_H |