summaryrefslogtreecommitdiff
path: root/engine-ocean/Game/Systems/UI/uisystem.cpp
diff options
context:
space:
mode:
authorjjesswan <jessica_wan@brown.edu>2024-04-22 21:56:26 -0400
committerjjesswan <jessica_wan@brown.edu>2024-04-22 21:56:26 -0400
commita556b45abf18f1bd509daaf63b66b7d55e9fd291 (patch)
treebc9b8a2d184c12aee236e7f9f276a34b84ca552d /engine-ocean/Game/Systems/UI/uisystem.cpp
parentcd7c76017a12bb548036571c1ff13e551369d06d (diff)
add engine version
Diffstat (limited to 'engine-ocean/Game/Systems/UI/uisystem.cpp')
-rw-r--r--engine-ocean/Game/Systems/UI/uisystem.cpp383
1 files changed, 383 insertions, 0 deletions
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);
+ }
+ }
+ }
+}