From 78e0ac5a9513962fd8f0856cf15c4f22cd461101 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 10 Dec 2025 20:03:41 +0300 Subject: [PATCH 1/4] add 'onmouseenter', 'onmouseleave' ui events --- src/graphics/ui/GUI.cpp | 22 ++++++++++++++++++++++ src/graphics/ui/GUI.hpp | 2 ++ src/graphics/ui/elements/UINode.cpp | 4 ++++ src/graphics/ui/elements/UINode.hpp | 7 ++++++- src/graphics/ui/gui_xml.cpp | 2 ++ 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 22ae5b908..82f798fe4 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -144,6 +144,28 @@ void GUI::actMouse(float delta, const CursorState& cursor) { } } this->hover = hover; + auto node = hover; + while (node) { + if (mouseOver.find(hover) != mouseOver.end()) { + break; + } + mouseOver.insert(node); + node->setMouseOver(true); + auto parent = node->getParent(); + if (parent) { + node = parent->shared_from_this(); + } + } + + for (auto it = mouseOver.begin(); it != mouseOver.end(); ) { + auto node = *it; + if (node->isInside(cursor.pos)) { + ++it; + continue; + } + node->setMouseOver(false); + it = mouseOver.erase(it); + } if (input.jclicked(Mousecode::BUTTON_1)) { if (pressed == nullptr && this->hover) { diff --git a/src/graphics/ui/GUI.hpp b/src/graphics/ui/GUI.hpp index 16d8e358c..8a12c3cd4 100644 --- a/src/graphics/ui/GUI.hpp +++ b/src/graphics/ui/GUI.hpp @@ -2,6 +2,7 @@ #include "delegates.hpp" +#include #include #include #include @@ -80,6 +81,7 @@ namespace gui { std::unique_ptr uicamera; std::shared_ptr menu; std::queue postRunnables; + std::set> mouseOver; PageLoaderFunc pagesLoader; diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index cbcb1c909..f4b4c5cb8 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -52,6 +52,10 @@ void UINode::setHover(bool flag) { return; } hover = flag; + actions.notify(flag ? UIAction::MOUSE_ENTER : UIAction::MOUSE_LEAVE, gui); +} + +void UINode::setMouseOver(bool flag) { actions.notify(flag ? UIAction::MOUSE_OVER : UIAction::MOUSE_OUT, gui); } diff --git a/src/graphics/ui/elements/UINode.hpp b/src/graphics/ui/elements/UINode.hpp index cbd43b380..f1c378fa1 100644 --- a/src/graphics/ui/elements/UINode.hpp +++ b/src/graphics/ui/elements/UINode.hpp @@ -59,7 +59,9 @@ namespace gui { DEFOCUS, RIGHT_CLICK, MOUSE_OVER, - MOUSE_OUT + MOUSE_OUT, + MOUSE_ENTER, + MOUSE_LEAVE, }; using ActionsSet = TaggedCallbacksSet; @@ -170,8 +172,11 @@ namespace gui { virtual void setHover(bool flag); bool isHover() const; + void setMouseOver(bool flag); + virtual void setParent(UINode* node); UINode* getParent() const; + std::shared_ptr getParentShared() const; /// @brief Set element color (doesn't affect inner elements). /// Also replaces hover color to avoid adding extra properties diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 6011373fb..967fd6bca 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -186,6 +186,8 @@ static void read_uinode( register_action(node, reader, element, "ondoubleclick", UIAction::DOUBLE_CLICK); register_action(node, reader, element, "onmouseover", UIAction::MOUSE_OVER); register_action(node, reader, element, "onmouseout", UIAction::MOUSE_OUT); + register_action(node, reader, element, "onmouseenter", UIAction::MOUSE_ENTER); + register_action(node, reader, element, "onmouseleave", UIAction::MOUSE_LEAVE); } static void read_container_impl( From 79e4a28b4dbde7fc51b851e64d248576cb74ab20 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 10 Dec 2025 20:49:50 +0300 Subject: [PATCH 2/4] update uinode hover semantics --- src/graphics/ui/GUI.cpp | 2 +- src/graphics/ui/elements/UINode.cpp | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 82f798fe4..48408a5a7 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -135,7 +135,7 @@ void GUI::actMouse(float delta, const CursorState& cursor) { if (this->hover && this->hover != hover) { this->hover->setHover(false); } - if (hover) { + if (hover && hover != this->hover) { hover->setHover(true); int scroll = input.getScroll(); diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index f4b4c5cb8..117d394f5 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -48,14 +48,11 @@ void UINode::setAlign(Align align) { } void UINode::setHover(bool flag) { - if (hover == flag) { - return; - } - hover = flag; actions.notify(flag ? UIAction::MOUSE_ENTER : UIAction::MOUSE_LEAVE, gui); } void UINode::setMouseOver(bool flag) { + hover = flag; actions.notify(flag ? UIAction::MOUSE_OVER : UIAction::MOUSE_OUT, gui); } From 89be2a1837ebdfab4ba968bfde6de1cb5d31b975 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 10 Dec 2025 20:51:24 +0300 Subject: [PATCH 3/4] rename UINode::setHover to UINode::setMouseEnter --- src/graphics/ui/GUI.cpp | 6 +++--- src/graphics/ui/elements/UINode.cpp | 2 +- src/graphics/ui/elements/UINode.hpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 48408a5a7..5fa617bda 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -133,10 +133,10 @@ void GUI::actMouse(float delta, const CursorState& cursor) { auto hover = container->getAt(cursor.pos); if (this->hover && this->hover != hover) { - this->hover->setHover(false); + this->hover->setMouseEnter(false); } if (hover && hover != this->hover) { - hover->setHover(true); + hover->setMouseEnter(true); int scroll = input.getScroll(); if (scroll) { @@ -241,7 +241,7 @@ void GUI::act(float delta, const glm::uvec2& vp) { actMouse(delta, cursor); } else { if (hover) { - hover->setHover(false); + hover->setMouseEnter(false); hover = nullptr; } } diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index 117d394f5..465ff26e4 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -47,7 +47,7 @@ void UINode::setAlign(Align align) { this->align = align; } -void UINode::setHover(bool flag) { +void UINode::setMouseEnter(bool flag) { actions.notify(flag ? UIAction::MOUSE_ENTER : UIAction::MOUSE_LEAVE, gui); } diff --git a/src/graphics/ui/elements/UINode.hpp b/src/graphics/ui/elements/UINode.hpp index f1c378fa1..fb699a737 100644 --- a/src/graphics/ui/elements/UINode.hpp +++ b/src/graphics/ui/elements/UINode.hpp @@ -169,7 +169,7 @@ namespace gui { virtual void setAlign(Align align); Align getAlign() const; - virtual void setHover(bool flag); + virtual void setMouseEnter(bool flag); bool isHover() const; void setMouseOver(bool flag); From 320870e8715ed09a2f6afd7d50ac835ec1c115d5 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 10 Dec 2025 20:58:54 +0300 Subject: [PATCH 4/4] update doc/*/xml-ui-layouts.md --- doc/en/xml-ui-layouts.md | 7 +++++-- doc/ru/xml-ui-layouts.md | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/en/xml-ui-layouts.md b/doc/en/xml-ui-layouts.md index 6a739d168..c238d24f6 100644 --- a/doc/en/xml-ui-layouts.md +++ b/doc/en/xml-ui-layouts.md @@ -42,8 +42,11 @@ Examples: - `ondoubleclick` - lua function called when you double click on an element. - `onfocus` - lua function called when focusing on an element. - `ondefocus` - lua function called when the element loses focus. -- `onmouseover` - lua function called when the cursor enters an element. -- `onmouseover` - lua function called when the cursor exits an element. +- `onmouseenter` - lua function called when the cursor enters an element. +- `onmouseleave` - lua function called when the cursor leaves an element. +- `onmouseover` - lua function called when the cursor hovers over an element. +- `onmouseout` - lua function called when the cursor exits an element. + onmouseenter and onmouseleave do not respect the elements hierarchy. - `tooltip` - tooltip text - `tooltip-delay` - tooltip show-up delay - `gravity` - automatic positioning of the element in the container. (Does not work in automatic containers like panel). Values: *top-left, top-center, top-right, center-left, center-center, center-right, bottom-left, bottom-center, bottom-right*. diff --git a/doc/ru/xml-ui-layouts.md b/doc/ru/xml-ui-layouts.md index 3c5d1acc1..d1255007c 100644 --- a/doc/ru/xml-ui-layouts.md +++ b/doc/ru/xml-ui-layouts.md @@ -46,8 +46,11 @@ - `ondoubleclick` - lua функция вызываемая при двойном нажатии на элемент. - `onfocus` - lua функция вызываемая при фокусировке на элемент. - `ondefocus` - lua функция вызываемая при потере фокуса элеметом. -- `onmouseover` - lua функция вызываемая при входе курсора в элемент. -- `onmouseover` - lua функция вызываемая при выходе курсора из элемента. +- `onmouseenter` - lua функция вызываемая при входе курсора в элемент. +- `onmouseleave` - lua функция вызываемая при выходе курсора из элемента. +- `onmouseover` - lua функция вызываемая при наведении курсора на элемент. +- `onmouseout` - lua функция вызываемая при выходе курсора из элемента. + onmouseenter и onmouseleave не учитывают иерархию элементов. - `tooltip` - текст всплывающей подсказки - `tooltip-delay` - задержка появления всплывающей подсказки - `gravity` - автоматическое позиционирование элемента в контейнере. (Не работает в автоматических контейнерах, как panel). Значения: *top-left, top-center, top-right, center-left, center-center, center-right, bottom-left, bottom-center, bottom-right*.