extends Control signal os_finished @onready var os_pausing_timer = %OSTimer as Timer @onready var os_label = %OSLabel as DialogueLabel @onready var os_contaner = %PanelContainer as PanelContainer var os_tween: Tween # 保证每次 pop_os 后都会有一次 os_finished 信号 var os_finish_emit_lock := Mutex.new() var os_finished_not_emitted := false func _ready() -> void: if Engine.is_editor_hint(): # 显示 os 效果 os_contaner.modulate.a = 1.0 os_label.text = "os 测试文本" return os_contaner.modulate.a = 0.0 os_label.text = "" os_pausing_timer.timeout.connect(_on_os_line_timeout) func pop_os(lines := []) -> void: if os_tween: os_tween.kill() os_finish_emit_lock.lock() if os_finished_not_emitted: os_finished.emit() os_finished_not_emitted = true os_finish_emit_lock.unlock() SceneManager.lock_player() # os_finished 必然发送,防止 tween 被 kill,保证一定 unlock if os_finished.is_connected(SceneManager.unlock_player): SceneManager.unlock_player() else: os_finished.connect(SceneManager.unlock_player, CONNECT_ONE_SHOT) os_tween = create_tween() os_label.text = "" os_tween.tween_property(os_contaner, "modulate:a", 1.0, 0.2) for line in lines: # os_pausing_timer 启动最小时长 0.01 秒 var duration = max(GlobalConfigManager.config.os_wait_time, 0.01) os_tween.tween_callback(_os_load_line.bind(line, duration)) os_tween.tween_property(os_contaner, "modulate:a", 0.0, 0.2) os_tween.tween_callback(func(): os_finish_emit_lock.lock() if os_finished_not_emitted: os_finished_not_emitted = false os_finished.emit() os_finish_emit_lock.unlock() ) # os 结束 await os_finished func _os_load_line(line: DialogueLine, duration: float): os_label.dialogue_line = line os_label.type_out() if os_label.finished_typing.is_connected(os_pausing_timer.start): os_label.finished_typing.disconnect(os_pausing_timer.start) os_label.finished_typing.connect(os_pausing_timer.start.bind(duration), CONNECT_ONE_SHOT) os_tween.pause() func _on_os_line_timeout(naturally := true): if not naturally: if os_label.is_typing: os_label.skip_typing() return if os_tween and os_tween.is_valid(): os_tween.play() func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("interact"): if os_pausing_timer and os_pausing_timer.time_left > 0: get_viewport().set_input_as_handled() _on_os_line_timeout(false)