Files

131 lines
4.9 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## VERTICAL SLICE - NOT FOR PRODUCTION
## 悬停预承诺呈现域件(BoardView 拆件——单一变化原因=悬停反馈语义):
## 三语义光标、目标格边框、BFS 路径预览、chord 双击首遇锚的唯一承载(自 board_view 收编 11 函数族)。
## 无 class_name(类名缓存面纪律)——经宿主 board_view preload 引用;构造=引用束注入
## (cells/minesweeper/diggable 共享引用+格命中换算/壳级光标写入/hover_forbidden 与 chord 发射注入 Callable——
## 输入经宿主三入站口委托,禁反向持宿主引用);_r0 出生展开区成员留宿主。
extends RefCounted
const COL_HL_TARGET := UiKit.GOLD # 悬停目标格边框(金)
const COL_SEAL := UiKit.SEAL_BLACK # 封印黑(与宿主 :658 双侧服役——各自 alias UiKit 单源)
const CURSOR_DIG := Input.CURSOR_CROSS # 挖——镐形自绘纹理载体
const CURSOR_MOVE_SEM := Input.CURSOR_ARROW # 移动——箭头(命名避开 Control.CURSOR_MOVE 原生成员遮蔽)
const CHORD_WINDOW_MS := 350
var _cells := {} # 共享引用(宿主容器同对象——rebuild 只 clear 不重绑)
var _minesweeper = null # 排雷玩法 只读查询引用(宿主 rebuild 重绑时同拍回写本成员)
var _diggable := {} # 共享引用(可挖域——呼吸微光作用集同源)
var _cb_cell_at: Callable # 格命中换算(宿主 _cell_at——整图公式单点留宿主)
var _cb_cursor: Callable # 壳级光标写入(宿主 mouse_default_cursor_shape 单点)
var _cb_forbidden: Callable # hover_forbidden 信号发射(首遇 toast 去重归组合根)
var _cb_chord: Callable # chord_attempted 信号发射(chord 肌肉记忆提示锚)
var _hover := Vector2i(-9, -9)
var _last_click := {"cell": Vector2i(-9, -9), "ms": -100000}
func _init(bundle: Dictionary) -> void:
_cells = bundle["cells"]
_minesweeper = bundle["minesweeper"]
_diggable = bundle["diggable"]
_cb_cell_at = bundle["cell_at"]
_cb_cursor = bundle["cursor"]
_cb_forbidden = bundle["forbidden"]
_cb_chord = bundle["chord"]
func _hover_at(pos: Vector2) -> void:
var c: Vector2i = _cb_cell_at.call(pos)
if c.x < 0:
if _hover.x >= 0:
_on_cell_unhover(_hover)
elif c != _hover:
if _hover.x >= 0:
_on_cell_unhover(_hover)
_on_cell_hover(c)
func _on_shell_mouse_exited() -> void:
if _hover.x >= 0:
_on_cell_unhover(_hover)
# chord 肌肉记忆首遇锚:同格双左击快开尝试(350ms 窗)——每 run 一次提示由组合根去重
func _detect_chord(c: Vector2i) -> void:
var now := Time.get_ticks_msec()
if _last_click.cell == c and now - int(_last_click.ms) <= CHORD_WINDOW_MS:
_cb_chord.call(c)
_last_click.ms = -100000
return
_last_click = {"cell": c, "ms": now}
func _on_cell_hover(c: Vector2i) -> void:
_hover = c
_apply_hover_visuals(c)
func _on_cell_unhover(c: Vector2i) -> void:
if _hover == c:
_hover = Vector2i(-9, -9)
_clear_hover_visuals(c)
func _refresh_hover_after_paint() -> void:
# 状态随 refresh 变化后光标/边框语义需重算(悬停格四格态可能已变)
if _hover.x >= 0 and _cells.has(_hover):
_apply_hover_visuals(_hover)
func _apply_hover_visuals(c: Vector2i) -> void:
if _minesweeper == null or not _cells.has(c):
return
_clear_hover_visuals(c)
var u: Node2D = _cells[c]
var revealed: bool = _minesweeper.is_revealed(c)
var seal: bool = _minesweeper.has_seal(c)
var adjacent: bool = _diggable.has(c)
if revealed:
u.face.hl_visible = true
u.face.hl_color = COL_HL_TARGET # 移动目标格边框(金)
_set_cursor_shape(c, CURSOR_MOVE_SEM)
_show_path_preview(c)
elif adjacent:
u.face.hl_visible = true
u.face.hl_color = COL_HL_TARGET # 挖掘目标格边框(相邻封印格同此——左键直接挖)
_set_cursor_shape(c, CURSOR_DIG)
elif seal:
u.face.hl_visible = true
u.face.hl_color = COL_SEAL # 已承诺封印标记(封印黑;无交互可供)
_set_cursor_shape(c, Input.CURSOR_FORBIDDEN)
else:
u.face.hl_visible = true
u.face.hl_color = UiKit.RED_FORBID # 不可及域灰禁框(禁止光标+首遇 toast 双通道)
_set_cursor_shape(c, Input.CURSOR_FORBIDDEN)
_cb_forbidden.call(c)
func _clear_hover_visuals(c: Vector2i) -> void:
if not _cells.has(c):
return
_cells[c].face.hl_visible = false
_hide_path_preview()
func _set_cursor_shape(c: Vector2i, shape: int) -> void:
_cb_cursor.call(shape) # 壳级光标(悬停格语义决定——单格悬停恒一)
func _show_path_preview(c: Vector2i) -> void:
# 合法性指示:悬停已开格 → BFS 路径蓝细线点迹(compute_move_path 只读面)
if _minesweeper == null:
return
var path: Array[Variant] = _minesweeper.compute_move_path(c)
for pc in path:
if _cells.has(pc):
_cells[pc].face.dot_visible = true
func _hide_path_preview() -> void:
for c in _cells:
_cells[c].face.dot_visible = false