# TypewriterLogic.gd - 打字机效果辅助类

## 1. 目标

`TypewriterLogic` 是一个 GDScript 辅助类，用于给 `Label` 节点添加逐字显示（打字机）效果。它封装了动画逻辑和状态，旨在简化打字机效果的实现和代码复用。该类使用 `class_name TypewriterLogic` 注册，方便在其他脚本中进行类型提示和引用。

## 2. 使用方法

**a. 引入与实例化:**

```gdscript
# 预加载类 (如果 TypewriterLogic.gd 在 res://scripts/ 目录下)
const TypewriterLogicClass = preload("res://scripts/TypewriterLogic.gd") # 确保路径正确

# 获取 Label 节点
@onready var dialogue_label: Label = $Path/To/Your/LabelNode

# 声明实例变量
var typewriter: TypewriterLogic

func _ready():
	# 确保 Label 节点有效
	if not is_instance_valid(dialogue_label):
		printerr("Error: Dialogue Label node not found or invalid.")
		return

	# 创建实例，传入 Label 和打字速度
	# TypewriterLogic 是 class_name，可以直接用作类型
	typewriter = TypewriterLogicClass.new(dialogue_label, 25.0) # 25.0 是打字速度 (字符/秒)
	
	# (可选) 连接信号，以在打字自然完成时执行操作
	if typewriter != null and typewriter.has_signal("finished"): # 检查实例和信号是否存在
		typewriter.finished.connect(_on_typing_naturally_finished)

func _on_typing_naturally_finished():
	print("打字效果已自然播放完毕！")
	# 在这里可以添加例如显示“继续”图标、启用下一页按钮等逻辑
```

**b. 控制效果:**

```gdscript
# 开始播放打字效果
func display_message(new_text: String):
	if typewriter != null:
		typewriter.start_typing(new_text)

# 如果正在打字，立即显示全部文本 (跳过动画)
func skip_current_typing_animation():
	if typewriter != null and typewriter.is_typing():
		typewriter.skip_typing()
		# 注意：skip_typing() 默认不发出 finished 信号。
		# 如果跳过后需要执行与自然完成相同的逻辑，可以在这里手动调用：
		# _on_typing_naturally_finished() 
		# 或者根据需求处理不同的逻辑

# 强制停止当前的打字效果 (例如，UI关闭或切换时)
func stop_current_typing_immediately():
	if typewriter != null:
		typewriter.stop_typing()

# 检查是否正在打字
func check_if_typing():
	if typewriter != null and typewriter.is_typing():
		print("打字机正在工作中...")
	else:
		print("打字机当前空闲。")

```

## 3. API 详解

*   **`TypewriterLogic.new(target_label: Label, typing_speed: float = 20.0)`**
	*   **构造函数 (`_init`)**: 创建 `TypewriterLogic` 的一个新实例。
	*   `target_label`: (必需) `Label` 类型的节点，打字效果将应用于此节点。如果无效，将打印错误。
	*   `typing_speed`: (可选) `float` 类型，表示打字速度，单位为“字符/秒”。默认值为 `20.0`。如果速度小于或等于0，文本将立即完全显示。

*   **`start_typing(full_text: String)`**
	*   **方法**: 开始在关联的 `Label` 上播放指定文本的打字动画。
	*   `full_text`: `String` 类型，要显示的完整文本。
	*   如果先前有动画正在播放，会先停止旧动画。
	*   如果 `full_text` 为空字符串，或者 `typing_speed` 设置为0或负数，文本会立即完全显示，并发出 `finished` 信号。

*   **`skip_typing()`**
	*   **方法**: 如果当前正在进行打字动画，则立即停止动画并将 `Label` 的文本设置为完整内容。
	*   如果当前没有在打字，则此方法不执行任何操作。
	*   **注意**: 此方法**不会**发出 `finished` 信号，因为它表示的是非自然完成。如果需要在跳过时执行特定逻辑，应在调用此方法后手动处理。

*   **`stop_typing()`**
	*   **方法**: 立即停止任何正在进行的打字动画。`Label` 的 `visible_characters` 将停留在被停止时的状态。
	*   此方法主要用于对话框提前关闭或需要中断效果的场景。
	*   **注意**: 此方法**不会**发出 `finished` 信号。

*   **`is_typing() -> bool`**
	*   **方法**: 返回一个布尔值，`true` 表示当前正在进行打字动画，`false` 则表示没有。

*   **`finished`**
	*   **信号**: 当打字动画**自然**完成（即，所有字符都已按设定速度逐个显示完毕）时发出。
	*   也会在调用 `start_typing` 时，如果提供的文本为空或打字速度无效（≤0），导致文本立即显示完全时发出。
	*   通过 `skip_typing()` 或 `stop_typing()` 中断动画**不会**触发此信号。

## 4. 注意事项

*   **有效 `Label`**: `TypewriterLogic` 必须与一个有效的 `Label` 节点关联才能工作。构造时会检查 `Label` 的有效性。
*   **Tween 管理**: 内部使用 `Tween` 来实现动画效果。`Tween` 实例由 `TypewriterLogic` 创建并附加到 `target_label` 节点上运行。`TypewriterLogic` 负责管理这些 `Tween` 的生命周期（创建、停止、清理）。
*   **`class_name`**: `TypewriterLogic` 使用 `class_name TypewriterLogic` 声明，这意味着你可以在其他 GDScript 文件中直接使用 `TypewriterLogic` 作为类型提示，例如 `var typewriter: TypewriterLogic`。
*   **信号连接**: 连接到 `finished` 信号时，请确保 `TypewriterLogic` 实例已成功创建。
*   **错误处理**: 类内部包含对无效 `Label` 的基本错误打印，但更健壮的错误处理（如游戏崩溃或替代行为）应由调用方代码根据具体需求实现。
```
