feat: improved menu cursor navigation

- Left side of the empty menu screen is no longer a huge invisible back button. Instead, each parent menu can be clicked individually to navigate to it. Clicking empty space now correctly closes the menu.
- Submenus can now also be clicked to navigate to them.
- Moving cursor towards a submenu will not cause other items in current menu to be selected if cursor moves through them.

ref #217
This commit is contained in:
tomasklaen
2023-05-17 21:06:17 +02:00
parent 78b5d9e59f
commit 10768d212d
4 changed files with 187 additions and 72 deletions

View File

@@ -319,6 +319,8 @@ cursor = {
on_wheel_down = nil,
on_wheel_up = nil,
allow_dragging = false,
history = {}, -- {x, y}[] history
history_size = 10,
-- Called at the beginning of each render
reset_handlers = function()
cursor.on_primary_down, cursor.on_primary_up = nil, nil
@@ -355,6 +357,17 @@ cursor = {
cursor.autohide_timer:kill()
cursor.autohide_timer:resume()
end
end,
-- Calculates distance in which cursor reaches rectangle if it continues moving in the same path.
-- Returns `nil` if cursor is not moving towards the rectangle.
direction_to_rectangle_distance = function(rect)
if cursor.hidden or not cursor.history[1] then
return false
end
local prev_x, prev_y = cursor.history[1][1], cursor.history[1][2]
local end_x, end_y = cursor.x + (cursor.x - prev_x) * 1e10, cursor.y + (cursor.y - prev_y) * 1e10
return get_ray_to_rectangle_distance(cursor.x, cursor.y, end_x, end_y, rect)
end
}
state = {
@@ -541,18 +554,24 @@ function update_cursor_position(x, y)
else x, y = INFINITY, INFINITY end
end
-- add 0.5 to be in the middle of the pixel
-- Add 0.5 to be in the middle of the pixel
cursor.x, cursor.y = (x + 0.5) / display.scale_x, (y + 0.5) / display.scale_y
if old_x ~= cursor.x or old_y ~= cursor.y then
Elements:update_proximities()
if cursor.x == INFINITY or cursor.y == INFINITY then
cursor.hidden = true
cursor.hidden, cursor.history = true, {}
Elements:trigger('global_mouse_leave')
elseif cursor.hidden then
cursor.hidden = false
cursor.hidden, cursor.history = false, {}
Elements:trigger('global_mouse_enter')
else
-- Update cursor history
for i = 1, cursor.history_size - 1, 1 do
cursor.history[i] = cursor.history[i + 1]
end
cursor.history[cursor.history_size] = {x, y}
end
Elements:proximity_trigger('mouse_move')