diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ac2015..5904ce5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ if(BUILD_WITH_ASSIMP) endif() if(BUILD_GUI_ELEMENTS) - set(GUI ${GUI} button.cpp listbox.cpp textbox.cpp checkbox.cpp slider.cpp) + set(GUI ${GUI} abstractGuiManager.cpp button.cpp listbox.cpp textbox.cpp checkbox.cpp slider.cpp) endif() set(LIB_SRC ${RENDER} ${MATH} ${UTILS} ${GUI} ${ARMATURE} ${ASSET_MANAGER} ${ASSET_READERS} ${ANIM}) diff --git a/abstractGuiManager.cpp b/abstractGuiManager.cpp new file mode 100644 index 0000000..066657a --- /dev/null +++ b/abstractGuiManager.cpp @@ -0,0 +1,255 @@ +#include + +#include "abstractGuiManager.h" +#include "textbox.h" +#include "slider.h" +#include "checkbox.h" +#include "listbox.h" +#include "util.h" + +namespace vb01Gui{ + using namespace std; + using namespace vb01; + + void AbstractGuiManager::update() { + Vector2 cursorPos = getCursorPos(); + + for (Button *b : buttons) { + if (b->isSeparate()) + b->update(); + + bool withinX = (cursorPos.x > b->getPos().x && cursorPos.x < b->getPos().x + b->getSize().x); + bool withinY = (cursorPos.y > b->getPos().y && cursorPos.y < b->getPos().y + b->getSize().y); + + if(withinX && withinY) + b->onMouseOver(); + else + b->onMouseOff(); + } + + for (Listbox *l : listboxes) + l->update(); + + for (Checkbox *c : checkboxes) + c->update(); + + for (Slider *s : sliders) + s->update(); + + if(currentSlider){ + float percentage = (cursorPos.x - currentSlider->getPos().x) / currentSlider->getSize().x; + currentSlider->setValue(percentage * currentSlider->getMaxValue()); + } + + for (Textbox *t : textboxes){ + t->update(); + + if(t->isDeleteCharacters()) + t->deleteCharacter(); + } + } + + void AbstractGuiManager::updateCurrentListbox(Button *b, bool &listboxClicked){ + Listbox *pastListbox = currentListbox; + + for(Listbox *l : listboxes){ + if(b == l->getListboxButton() || b == l->getScrollingButton()){ + currentListbox = l; + listboxClicked = true; + + if(pastListbox && currentListbox != pastListbox){ + if(pastListbox->isCloseable()) + pastListbox->close(); + } + else + currentListbox = (l->isOpen() ? l : nullptr); + + break; + } + } + } + + void AbstractGuiManager::updateCurrentSlider(Button *b){ + for(Slider *s : sliders) + if(b == s->getMovableSliderButton()){ + currentSlider = s; + break; + } + } + + void AbstractGuiManager::updateCurrentTextbox(Button *b, bool &textboxClicked){ + Textbox *pastTextbox = currentTextbox; + + for(Textbox *t : textboxes) + if(b == t->getTextboxButton()){ + currentTextbox = t; + textboxClicked = true; + + if(pastTextbox && currentTextbox != pastTextbox) + pastTextbox->disable(); + else + currentTextbox = (t->isEnabled() ? t : nullptr); + + break; + } + } + + void AbstractGuiManager::findClickedButton(){ + bool textboxClicked = false, listboxClicked = false; + + for (int i = 0; i < buttons.size(); i++) { + Vector2 mousePos = getCursorPos(); + Button *b = buttons[i]; + bool withinX = mousePos.x > b->getPos().x && mousePos.x < b->getPos().x + b->getSize().x; + bool withinY = mousePos.y > b->getPos().y && mousePos.y < b->getPos().y + b->getSize().y; + + if (b->isActive() && withinX && withinY){ + b->onClick(); + updateCurrentListbox(b, listboxClicked); + updateCurrentSlider(b); + updateCurrentTextbox(b, textboxClicked); + } + } + + if(!textboxClicked && currentTextbox){ + currentTextbox->disable(); + currentTextbox = nullptr; + } + + if(!listboxClicked && currentListbox && currentListbox->isCloseable()){ + currentListbox->close(); + currentListbox = nullptr; + } + } + + void AbstractGuiManager::addButton(Button* b) { + buttons.push_back(b); + } + + void AbstractGuiManager::addListbox(Listbox* l) { + listboxes.push_back(l); + buttons.push_back(l->getListboxButton()); + buttons.push_back(l->getScrollingButton()); + } + + void AbstractGuiManager::addCheckbox(Checkbox* c) { + buttons.push_back(c->getCheckboxButton()); + checkboxes.push_back(c); + } + + void AbstractGuiManager::addSlider(Slider* s) { + buttons.push_back(s->getMovableSliderButton()); + buttons.push_back(s->getStaticSliderButton()); + sliders.push_back(s); + } + + void AbstractGuiManager::addTextbox(Textbox* t) { + buttons.push_back(t->getTextboxButton()); + textboxes.push_back(t); + } + + void AbstractGuiManager::removeButton(Button *b) { + for (int i = 0; i < buttons.size(); i++) { + if (b == buttons[i]) { + delete b; + buttons.erase(buttons.begin() + i); + } + } + } + + void AbstractGuiManager::removeButton(string name) { + for (int i = 0; i < buttons.size(); i++) { + if (name == buttons[i]->getName() && buttons[i]->isSeparate()) { + delete buttons[i]; + buttons.erase(buttons.begin() + i); + } + } + } + + void AbstractGuiManager::removeListbox(Listbox *l) { + for (int i = 0; i < listboxes.size(); i++) { + if (l == listboxes[i]) { + removeButton(l->getListboxButton()); + delete l; + listboxes.erase(listboxes.begin() + i); + } + } + } + + void AbstractGuiManager::removeCheckbox(Checkbox *c) { + for (int i = 0; i < checkboxes.size(); i++) { + if (c == checkboxes[i]) { + removeButton(c->getCheckboxButton()); + delete c; + checkboxes.erase(checkboxes.begin() + i); + } + } + } + + void AbstractGuiManager::removeSlider(Slider *s) { + for (int i = 0; i < sliders.size(); i++) { + if (s == sliders[i]) { + removeButton(s->getMovableSliderButton()); + removeButton(s->getStaticSliderButton()); + delete s; + sliders.erase(sliders.begin() + i); + } + } + } + + void AbstractGuiManager::removeTextbox(Textbox* t) { + for (int i = 0; i < textboxes.size(); i++) { + if (t == textboxes[i]) { + removeButton(t->getTextboxButton()); + delete t; + textboxes.erase(textboxes.begin() + i); + } + } + } + + void AbstractGuiManager::removeAllButtons(vector exceptions){ + int targetId = 0; + + while(targetId != buttons.size()){ + if(find(exceptions.begin(), exceptions.end(), buttons[targetId]) == exceptions.end()){ + delete buttons[targetId]; + buttons.erase(buttons.begin() + targetId); + } + else + targetId++; + } + } + + void AbstractGuiManager::removeAllListboxes() { + while (listboxes.size() > 0) { + removeButton(listboxes[listboxes.size() - 1]->getListboxButton()); + delete listboxes[listboxes.size() - 1]; + listboxes.pop_back(); + } + } + + void AbstractGuiManager::removeAllCheckboxes() { + while (checkboxes.size() > 0) { + removeButton(checkboxes[checkboxes.size() - 1]->getCheckboxButton()); + delete checkboxes[checkboxes.size() - 1]; + checkboxes.pop_back(); + } + } + + void AbstractGuiManager::removeAllSliders() { + while (sliders.size() > 0) { + removeButton(sliders[sliders.size() - 1]->getMovableSliderButton()); + removeButton(sliders[sliders.size() - 1]->getStaticSliderButton()); + delete sliders[sliders.size() - 1]; + sliders.pop_back(); + } + } + + void AbstractGuiManager::removeAllTextboxes() { + while (textboxes.size() > 0) { + removeButton(textboxes[textboxes.size() - 1]->getTextboxButton()); + delete textboxes[textboxes.size() - 1]; + textboxes.pop_back(); + } + } +} diff --git a/abstractGuiManager.h b/abstractGuiManager.h new file mode 100644 index 0000000..7833a90 --- /dev/null +++ b/abstractGuiManager.h @@ -0,0 +1,52 @@ +#ifndef ABSTRACT_GUI_MANAGER_H +#define ABSTRACT_GUI_MANAGER_H + +#include +#include + +namespace vb01Gui{ + class Button; + class Listbox; + class Checkbox; + class Slider; + class Textbox; + + class AbstractGuiManager{ + public: + void update(); + void findClickedButton(); + void addButton(vb01Gui::Button*); + void removeButton(vb01Gui::Button*); + void removeButton(std::string); + void addListbox(vb01Gui::Listbox*); + void removeListbox(vb01Gui::Listbox*); + void addCheckbox(vb01Gui::Checkbox*); + void removeCheckbox(vb01Gui::Checkbox*); + void addTextbox(vb01Gui::Textbox*); + void removeTextbox(vb01Gui::Textbox*); + void addSlider(vb01Gui::Slider*); + void removeSlider(vb01Gui::Slider*); + void removeAllButtons(std::vector = std::vector{}); + void removeAllListboxes(); + void removeAllCheckboxes(); + void removeAllSliders(); + void removeAllTextboxes(); + private: + void updateCurrentListbox(vb01Gui::Button*, bool&); + void updateCurrentSlider(vb01Gui::Button*); + void updateCurrentTextbox(vb01Gui::Button*, bool&); + + std::vector buttons; + std::vector listboxes; + std::vector checkboxes; + std::vector sliders; + std::vector textboxes; + vb01Gui::Slider *currentSlider = nullptr; + vb01Gui::Textbox *currentTextbox = nullptr; + vb01Gui::Listbox *currentListbox = nullptr; + protected: + AbstractGuiManager(){} + }; +} + +#endif diff --git a/textbox.cpp b/textbox.cpp index c90846e..6be2b6c 100644 --- a/textbox.cpp +++ b/textbox.cpp @@ -68,6 +68,9 @@ namespace vb01Gui{ lastBlinkTime = getTime(); cursorNode->setVisible(canShowCursor); } + + if(deleteCharacters && canDeleteChar()) + deleteCharacter(); } } diff --git a/textbox.h b/textbox.h index a6d86d1..ce7d18a 100644 --- a/textbox.h +++ b/textbox.h @@ -23,11 +23,13 @@ namespace vb01Gui{ void type(vb01::u32, bool = false); void moveCursor(bool, float); void deleteCharacter(); - void setSlider(Slider *s){this->slider = s;} void setEntry(std::wstring); + void remove(); + inline void setSlider(Slider *s){this->slider = s;} inline bool isEnabled(){return enabled;} inline std::wstring getText(){return text->getText();} - void remove(); + inline void setDeleteCharacters(bool del){this->deleteCharacters = del;} + inline bool isDeleteCharacters(){return deleteCharacters;} private: class TextboxButton : public Button{ public: @@ -44,7 +46,7 @@ namespace vb01Gui{ vb01::Vector2 pos, size; std::wstring entry = L""; std::string fontPath = ""; - bool enabled = false, canShowCursor = false, capitalLeters = false; + bool enabled = false, canShowCursor = false, capitalLeters = false, deleteCharacters = false; vb01::s64 lastBlinkTime = 0, lastDeleteTime = 0, cursorPosOffset = 0; vb01::Quad *cursorRect; vb01::Text *text;