八音盒提示;draggable 优化

This commit is contained in:
cakipaul 2025-07-24 15:52:46 +08:00
parent c5ad2e56c8
commit 85392b08ea
4 changed files with 97 additions and 59 deletions

View File

@ -36,7 +36,8 @@ ui_center_notify_use_prop,按 E 使用道具,,,,,Press E to use item
ui_center_notify_check_note,按 N 查看线索笔记,,,,,Press N to check clue notes ui_center_notify_check_note,按 N 查看线索笔记,,,,,Press N to check clue notes
ui_center_notify_check_bag,按 B 查看重要物品,,,,,Press B to check important items ui_center_notify_check_bag,按 B 查看重要物品,,,,,Press B to check important items
ui_center_notify_right_click_prop,右键点击可检阅道具,,,,,Right-click to examine item ui_center_notify_right_click_prop,右键点击可检阅道具,,,,,Right-click to examine item
ui_left_mouse_shave,按住鼠标拖拽可刮开海报,,,,,Hold and drag mouse to scrape off poster ui_center_notify_drag_to_rotate,按住拖拽可旋转把手,,,,,Hold and drag to rotate the handle
ui_left_mouse_shave,按住拖拽可刮开海报,,,,,Hold and drag to scrape off poster
ui_switch_prop,点击图标可切换道具(或按 Z/C,,,,,Click icon to switch items (or press Z/C) ui_switch_prop,点击图标可切换道具(或按 Z/C,,,,,Click icon to switch items (or press Z/C)
ui_press_shift,按住 Shift 奔跑,,,,,Hold Shift to run ui_press_shift,按住 Shift 奔跑,,,,,Hold Shift to run
ui_boxcat_press_s,按住 S 躲藏,,,,,Hold S to hide ui_boxcat_press_s,按住 S 躲藏,,,,,Hold S to hide

1 keys zh_CN _character _notes _tags zh_SH en
36 ui_center_notify_check_note 按 N 查看线索笔记 Press N to check clue notes
37 ui_center_notify_check_bag 按 B 查看重要物品 Press B to check important items
38 ui_center_notify_right_click_prop 右键点击可检阅道具 Right-click to examine item
39 ui_left_mouse_shave ui_center_notify_drag_to_rotate 按住鼠标拖拽可刮开海报 按住拖拽可旋转把手 Hold and drag mouse to scrape off poster Hold and drag to rotate the handle
40 ui_left_mouse_shave 按住拖拽可刮开海报 Hold and drag to scrape off poster
41 ui_switch_prop 点击图标可切换道具(或按 Z/C) Click icon to switch items (or press Z/C)
42 ui_press_shift 按住 Shift 奔跑 Hold Shift to run
43 ui_boxcat_press_s 按住 S 躲藏 Hold S to hide

View File

@ -46,7 +46,8 @@
按 N 查看线索笔记 [ID:ui_center_notify_check_note] 按 N 查看线索笔记 [ID:ui_center_notify_check_note]
按 B 查看重要物品 [ID:ui_center_notify_check_bag] 按 B 查看重要物品 [ID:ui_center_notify_check_bag]
右键点击可检阅道具 [ID:ui_center_notify_right_click_prop] 右键点击可检阅道具 [ID:ui_center_notify_right_click_prop]
按住鼠标拖拽可刮开海报 [ID:ui_left_mouse_shave] 按住拖拽可旋转把手 [ID:ui_center_notify_drag_to_rotate]
按住拖拽可刮开海报 [ID:ui_left_mouse_shave]
点击图标可切换道具(或按 Z/C [ID:ui_switch_prop] 点击图标可切换道具(或按 Z/C [ID:ui_switch_prop]
按住 Shift 奔跑 [ID:ui_press_shift] 按住 Shift 奔跑 [ID:ui_press_shift]
按住 S 躲藏 [ID:ui_boxcat_press_s] 按住 S 躲藏 [ID:ui_boxcat_press_s]

View File

@ -33,7 +33,27 @@ signal dropped(node: Draggable2D)
sprite.texture = texture sprite.texture = texture
@export var limit_rect := Rect2(Vector2.ZERO, Vector2(564, 316)) @export var limit_rect := Rect2(Vector2.ZERO, Vector2(564, 316))
@onready var sprite = $Sprite2D as Sprite2D @onready var sprite: Sprite2D = $Sprite2D
# Whether the item is currently being held by the player
var holding := false:
set(val):
if holding != val:
holding = val
var touching := false
# 静态变量优化:使用对象引用而非字符串
static var current_focusing_node: Draggable2D = null
static var pending_enter_callables: Array[Callable] = []
# 缓存常量
const OUTLINE_THICKNESS := 1.0
const OUTLINE_TWEEN_DURATION := 0.2
const BUTTON_ALPHA_DURATION := 0.15
# 缓存变量
var _outline_tween: Tween
var _button_tween: Tween
func _ready() -> void: func _ready() -> void:
@ -42,25 +62,18 @@ func _ready() -> void:
if Engine.is_editor_hint(): if Engine.is_editor_hint():
return return
# 初始化隐藏白边 # 初始化隐藏白边
sprite.material.set("shader_parameter/thickness", 0.0) sprite.material.set_shader_parameter("thickness", 0.0)
mouse_entered.connect(_on_mouse_entered)
mouse_exited.connect(_on_mouse_exited)
# 安全检查
# Whether the item is currently being held by the player if has_signal("mouse_entered"):
var holding = false mouse_entered.connect(_on_mouse_entered)
var touching = false mouse_exited.connect(_on_mouse_exited)
else:
static var current_focusing_item = "": printerr("Draggable2D: mouse_entered or mouse_exited signal not found.")
set(val):
current_focusing_item = val
if GlobalConfig.DEBUG:
print("current_focusing_item=", current_focusing_item)
static var pending_enter_callables := [] as Array[Callable]
func is_focused() -> bool: func is_focused() -> bool:
return current_focusing_item == item_name return current_focusing_node == self
func _on_mouse_entered() -> bool: func _on_mouse_entered() -> bool:
@ -69,12 +82,14 @@ func _on_mouse_entered() -> bool:
return false return false
if holding or is_focused(): if holding or is_focused():
return true return true
# 尝试获得 current_focusing_item
if current_focusing_item != "": # 尝试获得 current_focusing_node
if current_focusing_node:
if not pending_enter_callables.has(_on_mouse_entered): if not pending_enter_callables.has(_on_mouse_entered):
pending_enter_callables.append(_on_mouse_entered) pending_enter_callables.append(_on_mouse_entered)
return false return false
current_focusing_item = item_name
current_focusing_node = self
_toggle_outline(true) _toggle_outline(true)
return true return true
@ -82,53 +97,51 @@ func _on_mouse_entered() -> bool:
func _on_mouse_exited() -> void: func _on_mouse_exited() -> void:
touching = false touching = false
pending_enter_callables.erase(_on_mouse_entered) pending_enter_callables.erase(_on_mouse_entered)
# frezzing 不影响 mouse exited # freezing 不影响 mouse exited
if is_focused(): if is_focused() and not holding:
current_focusing_item = "" current_focusing_node = null
for c in pending_enter_callables: while pending_enter_callables.size() > 0:
var c = pending_enter_callables.pop_front()
if c.call(): if c.call():
break break
_toggle_outline(false) _toggle_outline(false)
func _notification(what: int) -> void:
if what == NOTIFICATION_PREDELETE:
if holding:
_drop()
elif touching:
_on_mouse_exited()
func _input(event: InputEvent) -> void: func _input(event: InputEvent) -> void:
if freezing or Engine.is_editor_hint() or not is_visible_in_tree(): if freezing or Engine.is_editor_hint() or not is_visible_in_tree():
return return
if event is InputEventMouseButton: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed: if is_focused() and not holding:
# Trigger the pick action get_viewport().set_input_as_handled()
if touching and not holding: _try_pick.call_deferred()
_try_pick() elif holding:
elif holding: get_viewport().set_input_as_handled()
_drop() _drop()
elif holding and event is InputEventMouseMotion: elif holding and event is InputEventMouseMotion:
_update_pos_to_mouse() _update_pos_to_mouse()
func _update_pos_to_mouse(): func _update_pos_to_mouse() -> void:
# update global position # update global position
global_position = get_global_mouse_position() var target_pos = get_global_mouse_position()
global_position.x = clamp(global_position.x, limit_rect.position.x, limit_rect.end.x) global_position.x = clamp(target_pos.x, limit_rect.position.x, limit_rect.end.x)
global_position.y = clamp(global_position.y, limit_rect.position.y, limit_rect.end.y) global_position.y = clamp(target_pos.y, limit_rect.position.y, limit_rect.end.y)
func _try_pick() -> void: func _try_pick() -> void:
if act_as_button: if act_as_button:
# 作为按钮,发送 picked 信号 # 作为按钮,发送 picked 信号
picked.emit(self) picked.emit(self)
var tween = create_tween() if _button_tween and _button_tween.is_running():
tween.tween_property(sprite.material, "shader_parameter/alpha_ratio", 1.0, 0.15) _button_tween.kill()
_button_tween = create_tween()
_button_tween.tween_property(sprite.material, "shader_parameter/alpha_ratio", 1.0, BUTTON_ALPHA_DURATION)
return return
if current_focusing_item != item_name:
if not is_focused():
return return
# reset rotation # reset rotation
rotation = 0 rotation = 0
_toggle_outline(false) _toggle_outline(false)
@ -139,25 +152,47 @@ func _try_pick() -> void:
func _drop() -> void: func _drop() -> void:
if touching:
_toggle_outline(true)
if holding: if holding:
holding = false holding = false
if not touching:
current_focusing_node = null
# 清空数组前创建副本,避免在迭代时修改数组
var callables_copy = pending_enter_callables.duplicate()
for c in callables_copy:
if c.call():
break
# z_index -= 1 # z_index -= 1
dropped.emit(self) dropped.emit(self)
if is_focused():
_toggle_outline(true)
else:
# not touching but dropped, remove current_focusing_item if any
current_focusing_item = ""
func _toggle_outline(display = true): func _toggle_outline(display: bool) -> void:
var tween = create_tween() # 避免重复创建 tween
if display: if _outline_tween and _outline_tween.is_running():
tween.tween_property(sprite.material, "shader_parameter/thickness", 1.0, 0.2) _outline_tween.kill()
else:
tween.tween_property(sprite.material, "shader_parameter/thickness", 0.0, 0.2) _outline_tween = create_tween()
var target_thickness := OUTLINE_THICKNESS if display else 0.0
_outline_tween.tween_property(
sprite.material, "shader_parameter/thickness", target_thickness, OUTLINE_TWEEN_DURATION
)
func _exit_tree() -> void: func _exit_tree() -> void:
if touching: if touching:
_on_mouse_exited() _on_mouse_exited()
# 清理静态引用,避免内存泄漏
if current_focusing_node == self:
current_focusing_node = null
func force_hold() -> void:
if holding:
return
if not is_focused() and current_focusing_node:
current_focusing_node._drop()
_toggle_outline(false)
current_focusing_node = self
holding = true
picked.emit(self)

View File

@ -291,6 +291,7 @@ func _chechout_stage(s: int, play_sfx := true) -> void:
if play_sfx: if play_sfx:
sfx_open_lid.play() sfx_open_lid.play()
3: 3:
SceneManager.pop_center_notification("ui_center_notify_drag_to_rotate")
box_opened.visible = true box_opened.visible = true
d4.visible = true d4.visible = true
if pic: if pic: