Files
Sprout-Farm/GlobalScript/Toast.gd
2025-06-23 16:09:04 +08:00

153 lines
4.8 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Toast.gd - 合并的Toast系统
extends Node
# Toast节点缓存
var toast_container: Control
func _ready():
# 延迟创建Toast容器避免在节点初始化期间添加子节点的冲突
setup_toast_container.call_deferred()
func setup_toast_container():
# 防止重复创建
if toast_container and is_instance_valid(toast_container):
return
# 创建一个CanvasLayer来确保Toast始终在最顶层
var canvas_layer = CanvasLayer.new()
canvas_layer.name = "ToastCanvasLayer"
canvas_layer.layer = 100 # 设置一个很高的层级值
# 创建一个容器来放置所有Toast
toast_container = Control.new()
toast_container.name = "ToastContainer"
toast_container.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
toast_container.mouse_filter = Control.MOUSE_FILTER_IGNORE
# 将容器添加到CanvasLayer中
canvas_layer.add_child(toast_container)
# 尝试添加到main/UI节点如果失败则添加到根节点
var ui_node = get_node_or_null("/root/main/UI")
if ui_node:
ui_node.add_child.call_deferred(canvas_layer)
print("Toast容器已添加到 main/UI 节点")
else:
# 如果没有UI节点直接添加到根节点
get_tree().root.add_child.call_deferred(canvas_layer)
print("Toast容器已添加到根节点")
func show(text: String,
color: Color = Color.WHITE,
duration: float = 2.0,
fade_duration: float = 0.5) -> void:
# 确保容器存在且有效
if not toast_container or not is_instance_valid(toast_container) or not toast_container.get_parent():
setup_toast_container.call_deferred()
# 等待容器设置完成
await get_tree().process_frame
await get_tree().process_frame # 额外等待一帧确保完成
# 再次检查容器是否有效
if not toast_container or not is_instance_valid(toast_container):
print("警告Toast容器初始化失败无法显示Toast")
return
# 创建Toast UI
var toast_panel = create_toast_ui(text, color)
toast_container.add_child(toast_panel)
# 显示动画和自动消失
show_toast_animation(toast_panel, duration, fade_duration)
func create_toast_ui(text: String, color: Color) -> PanelContainer:
# 创建主容器
var panel = PanelContainer.new()
panel.name = "Toast_" + str(Time.get_ticks_msec())
# 设置样式
var style_box = StyleBoxFlat.new()
style_box.bg_color = Color(0, 0, 0, 0.8) # 半透明黑色背景
style_box.corner_radius_top_left = 8
style_box.corner_radius_top_right = 8
style_box.corner_radius_bottom_left = 8
style_box.corner_radius_bottom_right = 8
style_box.content_margin_top = 12
style_box.content_margin_bottom = 12
style_box.content_margin_left = 16
style_box.content_margin_right = 16
panel.add_theme_stylebox_override("panel", style_box)
# 创建文本标签
var label = Label.new()
label.text = text
label.modulate = color
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
# 设置字体大小
label.add_theme_font_size_override("font_size", 16)
panel.add_child(label)
# 定位Toast屏幕中央偏下
position_toast(panel)
return panel
func position_toast(toast_panel: PanelContainer):
# 设置位置为屏幕中央偏下
toast_panel.set_anchors_and_offsets_preset(Control.PRESET_CENTER)
toast_panel.position.y += 100 # 向下偏移
# 调整现有Toast的位置避免重叠
var existing_toasts = []
for child in toast_container.get_children():
if child != toast_panel and child is PanelContainer:
existing_toasts.append(child)
# 向上堆叠
for i in range(existing_toasts.size()):
var existing_toast = existing_toasts[existing_toasts.size() - 1 - i]
var tween = create_tween()
tween.tween_property(existing_toast, "position:y",
existing_toast.position.y - 60, 0.3)
func show_toast_animation(toast_panel: PanelContainer, duration: float, fade_duration: float):
# 初始状态:完全透明并稍微向上
toast_panel.modulate.a = 0.0
toast_panel.position.y += 20
# 淡入动画
var fade_in_tween = create_tween()
fade_in_tween.parallel().tween_property(toast_panel, "modulate:a", 1.0, 0.3)
fade_in_tween.parallel().tween_property(toast_panel, "position:y",
toast_panel.position.y - 20, 0.3)
fade_in_tween.set_ease(Tween.EASE_OUT)
# 等待显示时间
await get_tree().create_timer(duration).timeout
# 淡出动画
var fade_out_tween = create_tween()
fade_out_tween.tween_property(toast_panel, "modulate:a", 0.0, fade_duration)
await fade_out_tween.finished
# 移除节点
toast_panel.queue_free()
# 便捷方法
func show_success(text: String, duration: float = 2.0):
show(text, Color.GREEN, duration)
func show_error(text: String, duration: float = 3.0):
show(text, Color.RED, duration)
func show_warning(text: String, duration: float = 2.5):
show(text, Color.YELLOW, duration)
func show_info(text: String, duration: float = 2.0):
show(text, Color.CYAN, duration)