diff --git a/res/scripts/hud.lua b/res/scripts/hud.lua
index 3bdb4d634..365d02e43 100644
--- a/res/scripts/hud.lua
+++ b/res/scripts/hud.lua
@@ -130,10 +130,11 @@ function on_hud_open()
local name = "misc/moon"
local frame = gui.create_frame(name, name, {128, 128})
frame:add("")
- frame.color = {255, 0, 0, 255}
input.add_callback('key:y', function ()
- gui.set_active_frame(name)
+ gui.set_active_frame(name, function()
+ return input.get_mouse_pos()
+ end)
end)
end
diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp
index 1efc1e1f8..6dcb19d90 100644
--- a/src/graphics/ui/GUI.cpp
+++ b/src/graphics/ui/GUI.cpp
@@ -123,13 +123,18 @@ void GUI::updateTooltip(float delta) {
/// @brief Mouse related input and logic handling
void GUI::actMouse(Frame& frame, float delta, const CursorState& cursor) {
- auto& state = frame.getState();
-
float mouseDelta = glm::length(cursor.delta);
doubleClicked = false;
doubleClickTimer += delta + mouseDelta * 0.1f;
- auto hover = frame.getAt(cursor.pos);
+ auto cursorPos = cursor.pos;
+ if (cursorLocator) {
+ cursorPos = cursorLocator();
+ if (activeFrame) {
+ cursorPos.y += activeFrame->getPos().y;
+ }
+ }
+ auto hover = frame.getAt(cursorPos);
if (this->hover && this->hover != hover) {
this->hover->setMouseEnter(false);
}
@@ -166,7 +171,7 @@ void GUI::actMouse(Frame& frame, float delta, const CursorState& cursor) {
for (auto it = mouseOver.begin(); it != mouseOver.end(); ) {
auto mouseOverNode = it->lock();
if (mouseOverNode) {
- if (mouseOverNode->isInside(cursor.pos)) {
+ if (mouseOverNode->isInside(cursorPos)) {
++it;
continue;
}
@@ -179,10 +184,10 @@ void GUI::actMouse(Frame& frame, float delta, const CursorState& cursor) {
if (pressed == nullptr && this->hover) {
pressed = hover;
if (doubleClickTimer < doubleClickDelay) {
- pressed->doubleClick(cursor.pos.x, cursor.pos.y);
+ pressed->doubleClick(cursorPos.x, cursorPos.y);
doubleClicked = true;
} else {
- pressed->click(cursor.pos.x, cursor.pos.y);
+ pressed->click(cursorPos.x, cursorPos.y);
}
doubleClickTimer = 0.0f;
if (focus && focus != pressed) {
@@ -199,7 +204,7 @@ void GUI::actMouse(Frame& frame, float delta, const CursorState& cursor) {
focus = nullptr;
}
} else if (!input.clicked(Mousecode::BUTTON_1) && pressed) {
- pressed->mouseRelease(cursor.pos.x, cursor.pos.y);
+ pressed->mouseRelease(cursorPos.x, cursorPos.y);
pressed = nullptr;
}
@@ -354,7 +359,8 @@ void GUI::addFrame(std::shared_ptr frame) {
frames[id] = std::move(frame);
}
-void GUI::setActiveFrame(const std::string& id) {
+void GUI::setActiveFrame(const std::string& id, vec2supplier cursorLocator) {
+ this->cursorLocator = std::move(cursorLocator);
if (id.empty()) {
activeFrame = nullptr;
return;
diff --git a/src/graphics/ui/GUI.hpp b/src/graphics/ui/GUI.hpp
index ee3fc1cd5..7d120c9cc 100644
--- a/src/graphics/ui/GUI.hpp
+++ b/src/graphics/ui/GUI.hpp
@@ -83,6 +83,7 @@ namespace gui {
std::queue postRunnables;
std::vector> mouseOver;
std::unordered_map> frames;
+ vec2supplier cursorLocator;
float tooltipTimer = 0.0f;
float doubleClickTimer = 0.0f;
@@ -129,7 +130,9 @@ namespace gui {
void addFrame(std::shared_ptr frame);
- void setActiveFrame(const std::string& id);
+ void setActiveFrame(
+ const std::string& id, vec2supplier cursorLocator = nullptr
+ );
std::shared_ptr getActiveFrame() const;
diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp
index 0d6292d7a..60f894bda 100644
--- a/src/logic/scripting/lua/libs/libgui.cpp
+++ b/src/logic/scripting/lua/libs/libgui.cpp
@@ -1175,8 +1175,22 @@ static int l_set_active_frame(lua::State* L) {
return 0;
}
std::string id = lua::require_string(L, 1);
+ vec2supplier cursorLocator = nullptr;
+ if (lua::isfunction(L, 2)) {
+ auto lambda = lua::create_lambda(L);
+ cursorLocator = [lambda]() -> glm::vec2 {
+ auto table = lambda({});
+ if (!table.isList()) {
+ throw std::runtime_error("invalid value returned from locator");
+ }
+ glm::vec2 pos {};
+ table.at(0).get(pos.x);
+ table.at(1).get(pos.y);
+ return pos;
+ };
+ }
auto& gui = engine->getGUI();
- gui.setActiveFrame(id);
+ gui.setActiveFrame(id, std::move(cursorLocator));
return 0;
}