127 lines
3.2 KiB
GDScript
127 lines
3.2 KiB
GDScript
extends Node2D
|
|
|
|
# Dialogue system for Godot 4.x
|
|
# Handles displaying dialogue with animations and text reveal
|
|
|
|
# Signals
|
|
signal dialogue_started()
|
|
signal dialogue_completed()
|
|
|
|
# Configuration
|
|
@export var text_reveal_speed: float = 0.05 # seconds per character
|
|
@export var show_animation_duration: float = 0.3 # seconds
|
|
@export var hide_animation_duration: float = 0.2 # seconds
|
|
|
|
# Private variables
|
|
@onready var dialogue_box = $PanelContainer
|
|
@onready var text_label: Label = $PanelContainer/Label
|
|
var timer: Timer = null
|
|
var current_text: String = ""
|
|
var current_duration: float = 0.0
|
|
var text_index: int = 0
|
|
var is_showing: bool = false
|
|
var is_revealing: bool = false
|
|
|
|
func _ready():
|
|
# Initialize the dialogue system
|
|
pass
|
|
|
|
func trigger_dialogue(text: String, duration: float = 3.0) -> void:
|
|
"""Trigger dialogue with specified text and duration"""
|
|
if is_showing:
|
|
return
|
|
|
|
current_text = text
|
|
current_duration = duration
|
|
text_index = 0
|
|
is_showing = true
|
|
is_revealing = false
|
|
|
|
# Show the dialogue box with animation
|
|
show_dialogue_box()
|
|
|
|
# Start revealing text after a short delay to allow animation to complete
|
|
await get_tree().create_timer(show_animation_duration)
|
|
|
|
# Start revealing text immediately
|
|
start_text_reveal()
|
|
|
|
func show_dialogue_box():
|
|
"""Show dialogue box with animation"""
|
|
dialogue_box.visible = true
|
|
|
|
# Animate in using Tween
|
|
var tween = create_tween()
|
|
tween.set_ease(Tween.EASE_OUT)
|
|
tween.set_trans(Tween.TRANS_SINE)
|
|
tween.tween_property(dialogue_box, "modulate:a", 1.0, show_animation_duration)
|
|
|
|
# Emit signal when animation completes
|
|
await tween.finished
|
|
emit_signal("dialogue_started")
|
|
|
|
func hide_dialogue_box():
|
|
"""Hide dialogue box with animation"""
|
|
# Animate out using Tween
|
|
var tween = create_tween()
|
|
tween.set_ease(Tween.EASE_IN)
|
|
tween.set_trans(Tween.TRANS_SINE)
|
|
tween.tween_property(dialogue_box, "modulate:a", 0.0, hide_animation_duration)
|
|
|
|
# Wait for animation to complete
|
|
await tween.finished
|
|
|
|
dialogue_box.visible = false
|
|
is_showing = false
|
|
is_revealing = false
|
|
emit_signal("dialogue_completed")
|
|
|
|
func start_text_reveal():
|
|
"""Start revealing text character by character"""
|
|
if is_revealing:
|
|
return
|
|
|
|
is_revealing = true
|
|
text_label.text = ""
|
|
text_index = 0
|
|
|
|
# If duration is 0 or negative, don't auto-hide
|
|
if current_duration <= 0:
|
|
# Just reveal all text immediately
|
|
text_label.text = current_text
|
|
is_revealing = false
|
|
return
|
|
|
|
# Start timer for automatic hiding
|
|
timer = Timer.new()
|
|
timer.wait_time = current_duration
|
|
timer.one_shot = true
|
|
|
|
timer.connect("timeout", self._on_dialogue_timeout)
|
|
add_child(timer)
|
|
timer.start()
|
|
|
|
# Start the character-by-character reveal
|
|
reveal_next_character()
|
|
|
|
func reveal_next_character():
|
|
"""Reveal the next character in the text"""
|
|
if text_index >= current_text.length():
|
|
# Finished revealing all characters
|
|
is_revealing = false
|
|
return
|
|
|
|
# Add the next character to the text label
|
|
text_label.text += current_text[text_index]
|
|
text_index += 1
|
|
|
|
# Schedule next character reveal
|
|
|
|
await get_tree().create_timer(text_reveal_speed).timeout
|
|
reveal_next_character()
|
|
|
|
func _on_dialogue_timeout():
|
|
"""Handle dialogue timeout"""
|
|
if is_showing and not is_revealing:
|
|
hide_dialogue_box()
|