#93: drive the research menu with a mouse, and close the hole under it
Two separate faults, both reported on the same ticket. The menu was inert under a mouse. Input reaches the tree as raw events through BuildController._unhandled_input, because a Control that consumes them through the GUI system swallows the drag, and the tree only ever read touch events. That was invisible while the project set emulate_touch_from_mouse and every click arrived as a synthetic touch; with that setting gone, nothing selects and nothing scrolls, and there is no other way to research anything on a desktop. The press and the pan are now the behaviour, with touch and mouse as two ways in to them. Motion pans only while the button is held - a hovering pointer must not drag the tree out from under the reader - and the wheel scrolls, which is the first thing a desktop player reaches for. The panel also still had the buy button's hole in it. That button went away in #83 and nothing moved down into the space, leaving ~180px of dead panel below the readout while the tree above it stayed cramped. The readout moves down 154px and the canvas takes the height: 1190px to 1344px. The test drives clicks through BuildController rather than into the view, since the missing piece was the routing - calling the view directly would have passed against the bug as reported. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
03b1c85569
commit
4883197ef3
5 changed files with 242 additions and 11 deletions
|
|
@ -13,6 +13,14 @@ extends Control
|
|||
# before the menu can act on them, which is the bug that made the formation
|
||||
# editor's drag silently do nothing. Everything in this menu must stay
|
||||
# mouse_filter = IGNORE.
|
||||
#
|
||||
# #93: a mouse is a first-class way to drive this menu, not something
|
||||
# emulation turns into touches. The project used to set
|
||||
# emulate_touch_from_mouse, which made every click arrive here as an
|
||||
# InputEventScreenTouch for free; with that off, a menu that only reads
|
||||
# touch events is simply dead under a mouse - which is what the report was.
|
||||
# So the press and the pan are the behaviour, and touch and mouse are two
|
||||
# ways in to them.
|
||||
|
||||
signal node_picked(id: String)
|
||||
|
||||
|
|
@ -29,6 +37,9 @@ const LOCKED_PULSE: float = 0.5
|
|||
|
||||
@export var node_radius: float = 46.0
|
||||
@export var row_spacing: float = 250.0
|
||||
# One wheel notch: about a third of the default row spacing, so a notch is a
|
||||
# clear step without skipping a whole depth of the tree.
|
||||
const WHEEL_STEP: float = 90.0
|
||||
|
||||
# #83: a second tap on the node already selected buys it. The separate buy
|
||||
# button is gone - it sat at the bottom of the panel, a long way from the node
|
||||
|
|
@ -93,13 +104,43 @@ func _state_color(node: Dictionary) -> Color:
|
|||
# Returns true when the press landed on a node, so the caller knows the
|
||||
# touch was consumed.
|
||||
func handle_touch(event: InputEventScreenTouch) -> bool:
|
||||
return handle_press(event.pressed, event.position)
|
||||
|
||||
|
||||
func handle_drag(event: InputEventScreenDrag) -> bool:
|
||||
return handle_pan(event.relative)
|
||||
|
||||
|
||||
# A left click is the same gesture as a tap. Other buttons are left alone so
|
||||
# they stay available for whatever else wants them.
|
||||
func handle_mouse_button(event: InputEventMouseButton) -> bool:
|
||||
if event.button_index == MOUSE_BUTTON_WHEEL_UP and event.pressed:
|
||||
return handle_pan(Vector2(0.0, WHEEL_STEP))
|
||||
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN and event.pressed:
|
||||
return handle_pan(Vector2(0.0, -WHEEL_STEP))
|
||||
if event.button_index != MOUSE_BUTTON_LEFT:
|
||||
return false
|
||||
return handle_press(event.pressed, event.position)
|
||||
|
||||
|
||||
# Only while the button is held. A touch drag cannot arrive without a finger
|
||||
# on the glass, but the mouse moves across the menu the whole time it is
|
||||
# open, and panning the tree under a hovering pointer would make the menu
|
||||
# impossible to read.
|
||||
func handle_mouse_motion(event: InputEventMouseMotion) -> bool:
|
||||
if not _dragging:
|
||||
return false
|
||||
return handle_pan(event.relative)
|
||||
|
||||
|
||||
func handle_press(pressed: bool, at: Vector2) -> bool:
|
||||
if not visible:
|
||||
return false
|
||||
if not event.pressed:
|
||||
if not pressed:
|
||||
_dragging = false
|
||||
return true
|
||||
_dragging = true
|
||||
var local: Vector2 = event.position - global_position
|
||||
var local: Vector2 = at - global_position
|
||||
for node in GameState.SKILL_TREE:
|
||||
if local.distance_to(node_screen_pos(node)) <= node_radius * 1.25:
|
||||
var confirming: bool = selected_id == node.id
|
||||
|
|
@ -112,12 +153,12 @@ func handle_touch(event: InputEventScreenTouch) -> bool:
|
|||
return false
|
||||
|
||||
|
||||
func handle_drag(event: InputEventScreenDrag) -> bool:
|
||||
func handle_pan(relative: Vector2) -> bool:
|
||||
if not visible:
|
||||
return false
|
||||
# Dragging a finger upward reveals higher research; dragging downward
|
||||
# returns to the root. Clamp hard so the canvas never leaves an empty gap.
|
||||
scroll_y = clampf(scroll_y - event.relative.y, 0.0, _max_scroll())
|
||||
scroll_y = clampf(scroll_y - relative.y, 0.0, _max_scroll())
|
||||
queue_redraw()
|
||||
return true
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue