diff --git a/src/gui/gui2_button.cpp b/src/gui/gui2_button.cpp index ab6fb2ce38..933b10b35b 100644 --- a/src/gui/gui2_button.cpp +++ b/src/gui/gui2_button.cpp @@ -6,6 +6,7 @@ GuiButton::GuiButton(GuiContainer* owner, string id, string text, func_t func) : GuiElement(owner, id), text(text), func(func) { + intercepts_pointer = true; text_size = -1; back_style = theme->getStyle("button.back"); front_style = theme->getStyle("button.front"); diff --git a/src/gui/gui2_button.h b/src/gui/gui2_button.h index 3ddcfc591d..38de1ea0df 100644 --- a/src/gui/gui2_button.h +++ b/src/gui/gui2_button.h @@ -1,5 +1,4 @@ -#ifndef GUI2_BUTTON_H -#define GUI2_BUTTON_H +#pragma once #include "gui2_element.h" @@ -33,5 +32,3 @@ class GuiButton : public GuiElement string getText() const; string getIcon() const; }; - -#endif//GUI2_BUTTON_H diff --git a/src/gui/gui2_canvas.cpp b/src/gui/gui2_canvas.cpp index f4ad51ed50..dd79090097 100644 --- a/src/gui/gui2_canvas.cpp +++ b/src/gui/gui2_canvas.cpp @@ -25,7 +25,8 @@ void GuiCanvas::render(sp::RenderTarget& renderer) runUpdates(this); updateLayout(window_rect); - drawElements(mouse_position, window_rect, renderer); + GuiElement* hovered = getHoverElement(mouse_position); + drawElements(mouse_position, hovered, window_rect, renderer); if (enable_debug_rendering) { @@ -172,9 +173,6 @@ void GuiCanvas::runUpdates(GuiContainer* parent) element->owner = nullptr; delete element; }else{ - element->hover = element->rect.contains(mouse_position); - element->hover_coordinates = mouse_position; - element->onUpdate(); if (element->isVisible()) runUpdates(element); diff --git a/src/gui/gui2_container.cpp b/src/gui/gui2_container.cpp index 48ca46b184..d059629608 100644 --- a/src/gui/gui2_container.cpp +++ b/src/gui/gui2_container.cpp @@ -11,31 +11,36 @@ GuiContainer::~GuiContainer() } } -void GuiContainer::drawElements(glm::vec2 mouse_position, sp::Rect parent_rect, sp::RenderTarget& renderer) +void GuiContainer::drawElements(glm::vec2 mouse_position, GuiElement* hovered_element, sp::Rect parent_rect, sp::RenderTarget& renderer) { - for(auto it = children.begin(); it != children.end(); ) + for (auto it = children.begin(); it != children.end(); ) { GuiElement* element = *it; if (element->destroyed) { - //Find the owning cancas, as we need to remove ourselves if we are the focus or click element. + // Find the owning canvas, as we need to remove ourselves if we are + // the focus or click element. GuiCanvas* canvas = dynamic_cast(element->getTopLevelContainer()); - if (canvas) - canvas->unfocusElementTree(element); + if (canvas) canvas->unfocusElementTree(element); - //Delete it from our list. + // Delete it from our list. it = children.erase(it); // Free up the memory used by the element. element->owner = nullptr; delete element; - }else{ - element->hover = element->rect.contains(mouse_position); + } + else + { + // Manage this element's hover state. + element->hover = (element == hovered_element); + element->hover_coordinates = (element == hovered_element) ? mouse_position : glm::vec2{-100, -100}; + // Draw the element. if (element->visible) { element->onDraw(renderer); - element->drawElements(mouse_position, element->rect, renderer); + element->drawElements(mouse_position, hovered_element, element->rect, renderer); } it++; @@ -97,6 +102,23 @@ GuiElement* GuiContainer::executeScrollOnElement(glm::vec2 position, float value return nullptr; } +GuiElement* GuiContainer::getHoverElement(glm::vec2 mouse_position) +{ + for (auto it = children.rbegin(); it != children.rend(); it++) + { + GuiElement* element = *it; + + if (element->visible && element->enabled && element->rect.contains(mouse_position)) + { + GuiElement* hovered = element->getHoverElement(mouse_position); + if (hovered) return hovered; + if (element->intercepts_pointer) return element; + } + } + + return nullptr; +} + void GuiContainer::updateLayout(const sp::Rect& rect) { this->rect = rect; diff --git a/src/gui/gui2_container.h b/src/gui/gui2_container.h index 547aabb80c..51411926a8 100644 --- a/src/gui/gui2_container.h +++ b/src/gui/gui2_container.h @@ -1,5 +1,4 @@ -#ifndef GUI2_CONTAINER_H -#define GUI2_CONTAINER_H +#pragma once #include #include @@ -17,6 +16,7 @@ namespace sp { class GuiElement; class GuiLayout; class GuiTheme; + class GuiContainer : sp::NonCopyable { public: @@ -59,10 +59,11 @@ class GuiContainer : sp::NonCopyable virtual void setAttribute(const string& key, const string& value); protected: - virtual void drawElements(glm::vec2 mouse_position, sp::Rect parent_rect, sp::RenderTarget& window); + virtual void drawElements(glm::vec2 mouse_position, GuiElement* hovered_element, sp::Rect parent_rect, sp::RenderTarget& window); virtual void drawDebugElements(sp::Rect parent_rect, sp::RenderTarget& window); GuiElement* getClickElement(sp::io::Pointer::Button button, glm::vec2 position, sp::io::Pointer::ID id); GuiElement* executeScrollOnElement(glm::vec2 position, float value); + GuiElement* getHoverElement(glm::vec2 mouse_position); friend class GuiElement; @@ -70,5 +71,3 @@ class GuiContainer : sp::NonCopyable private: std::unique_ptr layout_manager = nullptr; }; - -#endif//GUI2_CONTAINER_H diff --git a/src/gui/gui2_element.cpp b/src/gui/gui2_element.cpp index 2b4de8a811..dfc1df57bb 100644 --- a/src/gui/gui2_element.cpp +++ b/src/gui/gui2_element.cpp @@ -4,7 +4,7 @@ GuiElement::GuiElement(GuiContainer* owner, const string& id) -: owner(owner), visible(true), enabled(true), hover(false), focus(false), id(id) +: owner(owner), id(id) { owner->children.push_back(this); destroyed = false; diff --git a/src/gui/gui2_element.h b/src/gui/gui2_element.h index bfb364fbb4..cd84f277d2 100644 --- a/src/gui/gui2_element.h +++ b/src/gui/gui2_element.h @@ -1,5 +1,4 @@ -#ifndef GUI2_ELEMENT_H -#define GUI2_ELEMENT_H +#pragma once #include #include "stringImproved.h" @@ -10,24 +9,25 @@ #include "graphics/renderTarget.h" #include "io/textinput.h" - class Layout; + class GuiElement : public GuiContainer { private: bool destroyed; protected: GuiContainer* owner; - bool visible; - bool enabled; - bool hover; + bool visible = true; + bool enabled = true; + bool hover = false; glm::vec2 hover_coordinates; - bool focus; + bool focus = false; + bool intercepts_pointer = false; string id; public: - constexpr static float GuiSizeMatchHeight = -1.0; - constexpr static float GuiSizeMatchWidth = -1.0; - constexpr static float GuiSizeMax = -2.0; + constexpr static float GuiSizeMatchHeight = -1.0f; + constexpr static float GuiSizeMatchWidth = -1.0f; + constexpr static float GuiSizeMax = -2.0f; enum class State { @@ -91,5 +91,3 @@ class GuiElement : public GuiContainer protected: State getState() const; }; - -#endif//GUI2_ELEMENT_H diff --git a/src/gui/gui2_listbox.cpp b/src/gui/gui2_listbox.cpp index 76b4a0028b..04b726f23e 100644 --- a/src/gui/gui2_listbox.cpp +++ b/src/gui/gui2_listbox.cpp @@ -7,6 +7,7 @@ GuiListbox::GuiListbox(GuiContainer* owner, string id, func_t func) : GuiEntryList(owner, id, func), text_size(30), button_height(50), text_alignment(sp::Alignment::Center) { + intercepts_pointer = true; scroll = new GuiScrollbar(this, id + "_SCROLL", 0, 0, 0, [](int value) {}); scroll ->setClickChange(button_height) diff --git a/src/gui/gui2_panel.cpp b/src/gui/gui2_panel.cpp index 48c76516c9..39c519da48 100644 --- a/src/gui/gui2_panel.cpp +++ b/src/gui/gui2_panel.cpp @@ -5,6 +5,7 @@ GuiPanel::GuiPanel(GuiContainer* owner, string id) : GuiElement(owner, id) { + intercepts_pointer = true; style = theme->getStyle("panel"); } diff --git a/src/gui/gui2_panel.h b/src/gui/gui2_panel.h index 5d67d69d85..d9ad6b60c5 100644 --- a/src/gui/gui2_panel.h +++ b/src/gui/gui2_panel.h @@ -1,10 +1,9 @@ -#ifndef GUI2_PANEL_H -#define GUI2_PANEL_H +#pragma once #include "gui2_element.h" - class GuiThemeStyle; + class GuiPanel : public GuiElement { protected: @@ -15,5 +14,3 @@ class GuiPanel : public GuiElement virtual void onDraw(sp::RenderTarget& renderer) override; virtual bool onMouseDown(sp::io::Pointer::Button button, glm::vec2 position, sp::io::Pointer::ID id) override; }; - -#endif//GUI2_PANEL_H diff --git a/src/gui/gui2_progressbar.h b/src/gui/gui2_progressbar.h index 1f862b9a23..62d59d5eb3 100644 --- a/src/gui/gui2_progressbar.h +++ b/src/gui/gui2_progressbar.h @@ -1,10 +1,9 @@ -#ifndef GUI2_PROGRESSBAR_H -#define GUI2_PROGRESSBAR_H +#pragma once #include "gui2_element.h" - class GuiThemeStyle; + class GuiProgressbar : public GuiElement { protected: @@ -28,5 +27,3 @@ class GuiProgressbar : public GuiElement GuiProgressbar* setColor(glm::u8vec4 color); GuiProgressbar* setDrawBackground(bool drawBackground); }; - -#endif//GUI2_PROGRESSBAR_H diff --git a/src/gui/gui2_progressslider.cpp b/src/gui/gui2_progressslider.cpp index fc85155b14..62fb4ccee0 100644 --- a/src/gui/gui2_progressslider.cpp +++ b/src/gui/gui2_progressslider.cpp @@ -5,6 +5,7 @@ GuiProgressSlider::GuiProgressSlider(GuiContainer* owner, string id, float min_value, float max_value, float start_value, func_t func) : GuiProgressbar(owner, id, min_value, max_value, start_value), callback(func) { + intercepts_pointer = true; } bool GuiProgressSlider::onMouseDown(sp::io::Pointer::Button button, glm::vec2 position, sp::io::Pointer::ID id) diff --git a/src/gui/gui2_rotationdial.cpp b/src/gui/gui2_rotationdial.cpp index d58b78fb87..273d9c2dbc 100644 --- a/src/gui/gui2_rotationdial.cpp +++ b/src/gui/gui2_rotationdial.cpp @@ -9,6 +9,7 @@ GuiRotationDial::GuiRotationDial(GuiContainer* owner, string id, float min_value, float max_value, float start_value, float rotation_offset, float ring_thickness, func_t func) : GuiElement(owner, id), min_value(min_value), max_value(max_value), value(start_value), rotation_offset(rotation_offset), ring_thickness(ring_thickness), func(func) { + intercepts_pointer = true; radius = std::min(rect.size.x, rect.size.y) * 0.5f; // Fetch styles diff --git a/src/gui/gui2_scrollbar.cpp b/src/gui/gui2_scrollbar.cpp index 3567dc8405..03f439e03e 100644 --- a/src/gui/gui2_scrollbar.cpp +++ b/src/gui/gui2_scrollbar.cpp @@ -6,6 +6,7 @@ GuiScrollbar::GuiScrollbar(GuiContainer* owner, string id, int min_value, int max_value, int start_value, func_t func) : GuiElement(owner, id), min_value(min_value), max_value(max_value), desired_value(start_value), value_size(1), func(func) { + intercepts_pointer = true; back_style = theme->getStyle("scrollbar.back"); front_style = theme->getStyle("scrollbar.front"); diff --git a/src/gui/gui2_scrollbar.h b/src/gui/gui2_scrollbar.h index b449bc0faa..482ad48b82 100644 --- a/src/gui/gui2_scrollbar.h +++ b/src/gui/gui2_scrollbar.h @@ -1,10 +1,9 @@ -#ifndef GUI2_SCROLLBAR_H -#define GUI2_SCROLLBAR_H +#pragma once #include "gui2_element.h" - class GuiThemeStyle; + class GuiScrollbar : public GuiElement { typedef std::function func_t; @@ -51,5 +50,3 @@ class GuiScrollbar : public GuiElement int getCorrectedMax() const; int getMin() const; }; - -#endif//GUI2_SCROLLBAR_H diff --git a/src/gui/gui2_selector.cpp b/src/gui/gui2_selector.cpp index 3eb375901e..bf8c726e45 100644 --- a/src/gui/gui2_selector.cpp +++ b/src/gui/gui2_selector.cpp @@ -10,6 +10,7 @@ GuiSelector::GuiSelector(GuiContainer* owner, string id, func_t func) : GuiEntryList(owner, id, func) { + intercepts_pointer = true; back_style = theme->getStyle("selector.back"); front_style = theme->getStyle("selector.front"); left = new GuiArrowButton(this, id + "_ARROW_LEFT", 0, [this]() { diff --git a/src/gui/gui2_selector.h b/src/gui/gui2_selector.h index 63cbba511c..b4a0bbbe07 100644 --- a/src/gui/gui2_selector.h +++ b/src/gui/gui2_selector.h @@ -2,7 +2,6 @@ #include "gui2_entrylist.h" - class GuiArrowButton; class GuiThemeStyle; class GuiToggleButton; diff --git a/src/gui/gui2_slider.cpp b/src/gui/gui2_slider.cpp index 2f41247bec..be715237f4 100644 --- a/src/gui/gui2_slider.cpp +++ b/src/gui/gui2_slider.cpp @@ -8,6 +8,7 @@ GuiBasicSlider::GuiBasicSlider(GuiContainer* owner, string id, float min_value, float max_value, float start_value, func_t func) : GuiElement(owner, id), min_value(min_value), max_value(max_value), value(start_value), func(func) { + intercepts_pointer = true; front_style = theme->getStyle("slider.front"); back_style = theme->getStyle("slider.back"); } @@ -229,6 +230,7 @@ GuiSlider* GuiSlider::addOverlay(unsigned int precision, float font_size) GuiSlider2D::GuiSlider2D(GuiContainer* owner, string id, glm::vec2 min_value, glm::vec2 max_value, glm::vec2 start_value, func_t func) : GuiElement(owner, id), min_value(min_value), max_value(max_value), value(start_value), func(func) { + intercepts_pointer = true; front_style = theme->getStyle("slider.front"); back_style = theme->getStyle("slider.back"); } diff --git a/src/gui/gui2_slider.h b/src/gui/gui2_slider.h index b8450ad4fe..2863b70c37 100644 --- a/src/gui/gui2_slider.h +++ b/src/gui/gui2_slider.h @@ -1,10 +1,10 @@ -#ifndef GUI2_SLIDER_H -#define GUI2_SLIDER_H +#pragma once #include "gui2_element.h" #include "gui2_label.h" class GuiThemeStyle; + class GuiBasicSlider : public GuiElement { public: @@ -92,5 +92,3 @@ class GuiSlider2D : public GuiElement GuiSlider2D* setValue(glm::vec2 value); glm::vec2 getValue(); }; - -#endif//GUI2_SLIDER_H diff --git a/src/gui/gui2_textentry.cpp b/src/gui/gui2_textentry.cpp index e78f0bc96b..95491c14e7 100644 --- a/src/gui/gui2_textentry.cpp +++ b/src/gui/gui2_textentry.cpp @@ -6,6 +6,7 @@ GuiTextEntry::GuiTextEntry(GuiContainer* owner, string id, string text) : GuiElement(owner, id), text(text), text_size(30), func(nullptr) { + intercepts_pointer = true; blink_timer.repeat(blink_rate); front_style = theme->getStyle("textentry.front"); back_style = theme->getStyle("textentry.back"); diff --git a/src/gui/gui2_textentry.h b/src/gui/gui2_textentry.h index 1b76772a49..f1b70a0481 100644 --- a/src/gui/gui2_textentry.h +++ b/src/gui/gui2_textentry.h @@ -1,11 +1,10 @@ -#ifndef GUI2_TEXTENTRY_H -#define GUI2_TEXTENTRY_H +#pragma once #include "gui2_element.h" #include "timer.h" - class GuiThemeStyle; + class GuiTextEntry : public GuiElement { public: @@ -64,5 +63,3 @@ class GuiTextEntry : public GuiElement int getTextOffsetForPosition(glm::vec2 position); void runChangeCallback(); }; - -#endif//GUI2_TEXTENTRY_H diff --git a/src/gui/hotkeyBinder.cpp b/src/gui/hotkeyBinder.cpp index 7916b04675..28d784ec77 100644 --- a/src/gui/hotkeyBinder.cpp +++ b/src/gui/hotkeyBinder.cpp @@ -8,6 +8,7 @@ GuiHotkeyBinder::GuiHotkeyBinder(GuiContainer* owner, string id, sp::io::Keybinding* key) : GuiElement(owner, id), key(key) { + intercepts_pointer = true; front_style = theme->getStyle("textentry.front"); back_style = theme->getStyle("textentry.back"); } diff --git a/src/gui/hotkeyBinder.h b/src/gui/hotkeyBinder.h index 06eae49bac..393b7f0851 100644 --- a/src/gui/hotkeyBinder.h +++ b/src/gui/hotkeyBinder.h @@ -1,10 +1,9 @@ -#ifndef HOTKEYBINDER_H -#define HOTKEYBINDER_H +#pragma once #include "gui2_element.h" - class GuiThemeStyle; + class GuiHotkeyBinder : public GuiElement { private: @@ -18,5 +17,3 @@ class GuiHotkeyBinder : public GuiElement virtual bool onMouseDown(sp::io::Pointer::Button button, glm::vec2 position, sp::io::Pointer::ID id) override; virtual void onDraw(sp::RenderTarget& renderer) override; }; - -#endif //HOTKEYBINDER_H diff --git a/src/screenComponents/frequencyCurve.cpp b/src/screenComponents/frequencyCurve.cpp index 8c956c4462..9b34221c09 100644 --- a/src/screenComponents/frequencyCurve.cpp +++ b/src/screenComponents/frequencyCurve.cpp @@ -79,8 +79,8 @@ void GuiFrequencyCurve::onDraw(sp::RenderTarget& renderer) } } -void GuiFrequencyCurve::drawElements(glm::vec2 mouse_position, sp::Rect parent_rect, sp::RenderTarget& window) +void GuiFrequencyCurve::drawElements(glm::vec2 mouse_position, GuiElement* hovered_element, sp::Rect parent_rect, sp::RenderTarget& window) { this->mouse_position = mouse_position; - GuiContainer::drawElements(mouse_position, parent_rect, window); + GuiContainer::drawElements(mouse_position, hovered_element, parent_rect, window); } \ No newline at end of file diff --git a/src/screenComponents/frequencyCurve.h b/src/screenComponents/frequencyCurve.h index 1aca4d9d49..edafd067f0 100644 --- a/src/screenComponents/frequencyCurve.h +++ b/src/screenComponents/frequencyCurve.h @@ -1,5 +1,4 @@ -#ifndef FREQUENCY_CURVE_H -#define FREQUENCY_CURVE_H +#pragma once #include "gui/gui2_panel.h" @@ -15,11 +14,9 @@ class GuiFrequencyCurve : public GuiPanel GuiFrequencyCurve(GuiContainer* owner, string id, bool frequency_is_beam, bool more_damage_is_positive); virtual void onDraw(sp::RenderTarget& target) override; - virtual void drawElements(glm::vec2 mouse_position, sp::Rect parent_rect, sp::RenderTarget& window) override; + virtual void drawElements(glm::vec2 mouse_position, GuiElement* hovered_element, sp::Rect parent_rect, sp::RenderTarget& window) override; GuiFrequencyCurve* setFrequency(int frequency) { this->frequency = frequency; return this; } void setEnemyHasEquipment(bool state) { this->enemy_has_equipment = state; } }; - -#endif//FREQUENCY_CURVE_H