xiandie/scene/ux/inspector_balloon.gd

104 lines
2.9 KiB
GDScript

class_name InspectorBalloon
extends MarginContainer
signal quitted(is_manually: bool)
@export var prop_title_to_content_wait_time := 3.0
@export var auto_quit_time := 5.0
@onready var character_label = %CharacterLabel as RichTextLabel
@onready var content_label = %ContentLabel as RichTextLabel
enum { DISPLAYING_NONE, DISPLAYING_TITLE, DISPLAYING_CONTENT }
var _display_mutex := Mutex.new()
var _displaying_status := DISPLAYING_NONE
var _pending_content := ""
var _balloon_tween: Tween
func _ready() -> void:
character_label.text = ""
content_label.text = ""
func show_prop_balloon(obtain_str: String, prop_title: String, content: String) -> void:
_display_mutex.lock()
if _balloon_tween and _balloon_tween.is_running():
_balloon_tween.kill()
_balloon_tween = create_tween()
show()
_pending_content = content
obtain_str = "[color=orange]" + obtain_str + "[/color]"
_displaying_status = DISPLAYING_TITLE
character_label.show()
character_label.text = obtain_str
content_label.text = prop_title
if not _pending_content.is_empty():
_balloon_tween.tween_interval(prop_title_to_content_wait_time)
_balloon_tween.tween_callback(_display_content)
else:
_balloon_tween.tween_interval(auto_quit_time)
_balloon_tween.tween_callback(_finished.bind(false))
_display_mutex.unlock()
func _display_content() -> void:
_display_mutex.lock()
if _balloon_tween and _balloon_tween.is_running():
_balloon_tween.kill()
show()
_displaying_status = DISPLAYING_CONTENT
character_label.hide()
content_label.text = _pending_content
_pending_content = ""
_balloon_tween = create_tween()
_balloon_tween.tween_interval(auto_quit_time)
_balloon_tween.tween_callback(_finished.bind(false))
_display_mutex.unlock()
func show_prop_content(content: String) -> void:
_pending_content = content
_display_content()
func _finished(manually: bool) -> void:
_display_mutex.lock()
character_label.text = ""
content_label.text = ""
_displaying_status = DISPLAYING_NONE
hide()
quitted.emit(manually)
_display_mutex.unlock()
func _input(event: InputEvent) -> void:
if _displaying_status == DISPLAYING_NONE:
return
if event.is_action_pressed("interact") or event.is_action_pressed("cancel"):
get_viewport().set_input_as_handled()
_display_mutex.lock()
if _balloon_tween and _balloon_tween.is_running():
_balloon_tween.kill()
if _displaying_status == DISPLAYING_TITLE:
if not _pending_content.is_empty():
_display_content()
else:
# 如果没有文本,直接退出
_finished(true)
elif _displaying_status == DISPLAYING_CONTENT:
_finished(true)
_display_mutex.unlock()
# 不释放 quitted 结束 balloon
func kill_without_signal() -> void:
_display_mutex.lock()
if _balloon_tween and _balloon_tween.is_running():
_balloon_tween.kill()
character_label.text = ""
content_label.text = ""
_displaying_status = DISPLAYING_NONE
hide()
_display_mutex.unlock()