merge: 关卡画面深层节点不可点根修——画布随图自适应+图上命中真实输入回归闸(用户目检 bug 反馈)

This commit is contained in:
DKChan committed 2026-09-28 05:06:44 +08:00
commit 83c11a13a7
2 files changed
+96 -11

No files matched your search

+34 -9
View File
@@ -46,6 +46,7 @@ var _attr_value: Label
var _bonus_row: HBoxContainer
var _bonus_value: Label
var _cand_ids: Array = [] # 本停点候选 id 集(图上命中合法集)
var _content_size := Vector2(620, 240) # 图内容包络(open_choices 按图拟合——画布 min 尺寸随它)
var _hover_id := -1 # 悬停预承诺候选(-1 = 无)
var abandon_btn: Button # 放弃入口(可见性归组合根 set_abandon_available——只在冒险模式开)
var _abandon_armed := false # 二次确认态(首击置位、二击提交、超时/重开回落)
@@ -209,10 +210,31 @@ func open_choices(cands: Array, runner) -> void:
_cand_ids = []
for cand in cands:
_cand_ids.append(_id_of(cand))
_fit_canvas(_runner.nodes())
_refresh_status()
visible = true
# 画布随图自适应(level-map.md Layout:画布宽随层数、高随同层最大节点数——公式与 _layout 同源;
# 2026-09-28 真鼠标点击 bug 根修:固定 620×240 画布下深层节点(L1 Boss 内容 x=802)落在 gui_input
# 命中区外——绘制无裁剪看得见、命中收不到事件。单链关卡层深=节点序,必须先拟合再命中。
func _fit_canvas(nodes: Array) -> void:
if nodes.is_empty():
return
var layer := {}
var slot := {}
_assign_layers(nodes, layer, slot)
var maxl := 0
var maxslot := 0
for k in layer.keys():
maxl = maxi(maxl, int(layer[k]))
for k in slot.keys():
maxslot = maxi(maxslot, int(slot[k]))
_content_size = Vector2(70 + maxl * 122 + NODE_HALF.x + 8.0, 52 + maxslot * 58 + NODE_HALF.y + 8.0)
_content_size = _content_size.max(Vector2(620, 240)) # 下限 = 旧定值画布(小图观感不变)
_canvas.custom_minimum_size = _content_size
# 状态栏刷新(命令式纪律——组合根打开本屏/兑付确认回执后重查;零推送信号订阅)
func _refresh_status() -> void:
if _runner == null:
@@ -249,13 +271,13 @@ func _on_canvas_input(ev: InputEvent) -> void:
if _runner == null or not visible:
return
if ev is InputEventMouseMotion:
var nid := _candidate_at(_canvas.get_local_mouse_position())
var nid := _candidate_at(ev.position) # gui_input 事件坐标 = 接收控件局部坐标(push_input 同成立)
if nid != _hover_id:
_hover_id = nid
_canvas.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND if nid >= 0 else Control.CURSOR_ARROW
_canvas.queue_redraw()
elif ev is InputEventMouseButton and ev.button_index == MOUSE_BUTTON_LEFT and ev.pressed:
var nid2 := _candidate_at(_canvas.get_local_mouse_position())
var nid2 := _candidate_at(ev.position)
if nid2 >= 0:
_submit_choice(nid2)
@@ -349,9 +371,18 @@ func _draw_graph(canvas: Control) -> void:
func _layout(nodes: Array, canvas: Control) -> Dictionary:
# 分层:layer = 入口 BFS 深度;同层 slot 垂直排布
var layer := {}
var slot := {}
_assign_layers(nodes, layer, slot)
var pos := {}
var origin := (canvas.size - _content_size) / 2.0
for node in nodes:
pos[node] = origin + Vector2(70 + int(layer[node]) * 122, 52 + int(slot[node]) * 58)
return pos
# 分层(layout/fit 共享件):layer = 入口 BFS 深度;同层 slot 垂直排布;未达节点兜底排末层
func _assign_layers(nodes: Array, layer: Dictionary, slot: Dictionary) -> void:
var layer_counts := {}
var entry := _entry(nodes)
var queue: Array = []
@@ -369,7 +400,6 @@ func _layout(nodes: Array, canvas: Control) -> Dictionary:
continue
layer[target] = l + 1
queue.append(target)
# 未达节点(理论不可达——校验已拦)兜底排末层
var max_layer := 0
for k in layer.keys():
max_layer = maxi(max_layer, int(layer[k]))
@@ -378,11 +408,6 @@ func _layout(nodes: Array, canvas: Control) -> Dictionary:
layer[node] = max_layer + 1
slot[node] = int(layer_counts.get(layer[node], 0))
layer_counts[layer[node]] = int(layer_counts.get(layer[node], 0)) + 1
var pos := {}
var origin := (canvas.size - Vector2(620, 240)) / 2.0
for node in nodes:
pos[node] = origin + Vector2(70 + int(layer[node]) * 122, 52 + int(slot[node]) * 58)
return pos
func _entry(nodes: Array) -> Dictionary: