创建新工程

This commit is contained in:
moyin
2025-12-05 19:00:14 +08:00
commit ff4fa5fffd
227 changed files with 32804 additions and 0 deletions

View File

@@ -0,0 +1,348 @@
extends Node
## UI动画管理器
## 统一管理UI动画效果提升用户体验
# 动画配置
const FADE_DURATION = 0.25
const SLIDE_DURATION = 0.3
const SCALE_DURATION = 0.2
const BOUNCE_DURATION = 0.4
# 缓动类型
enum EaseType {
EASE_IN,
EASE_OUT,
EASE_IN_OUT,
BOUNCE,
ELASTIC
}
## 淡入动画
func fade_in(node: Control, duration: float = FADE_DURATION, ease_type: EaseType = EaseType.EASE_OUT) -> Tween:
"""
淡入动画
@param node: 要动画的节点
@param duration: 动画时长
@param ease_type: 缓动类型
@return: Tween对象
"""
if not node:
return null
node.modulate.a = 0.0
node.show()
var tween = node.create_tween()
tween.set_ease(_get_tween_ease(ease_type))
tween.tween_property(node, "modulate:a", 1.0, duration)
return tween
## 淡出动画
func fade_out(node: Control, duration: float = FADE_DURATION, ease_type: EaseType = EaseType.EASE_IN) -> Tween:
"""
淡出动画
@param node: 要动画的节点
@param duration: 动画时长
@param ease_type: 缓动类型
@return: Tween对象
"""
if not node:
return null
var tween = node.create_tween()
tween.set_ease(_get_tween_ease(ease_type))
tween.tween_property(node, "modulate:a", 0.0, duration)
tween.tween_callback(func(): node.hide())
return tween
## 滑入动画(从左侧)
func slide_in_left(node: Control, duration: float = SLIDE_DURATION, ease_type: EaseType = EaseType.EASE_OUT) -> Tween:
"""
从左侧滑入动画
@param node: 要动画的节点
@param duration: 动画时长
@param ease_type: 缓动类型
@return: Tween对象
"""
if not node:
return null
var original_pos = node.position
node.position.x = -node.size.x
node.show()
var tween = node.create_tween()
tween.set_ease(_get_tween_ease(ease_type))
tween.tween_property(node, "position", original_pos, duration)
return tween
## 滑入动画(从右侧)
func slide_in_right(node: Control, duration: float = SLIDE_DURATION, ease_type: EaseType = EaseType.EASE_OUT) -> Tween:
"""
从右侧滑入动画
@param node: 要动画的节点
@param duration: 动画时长
@param ease_type: 缓动类型
@return: Tween对象
"""
if not node:
return null
var original_pos = node.position
var viewport_width = node.get_viewport().get_visible_rect().size.x
node.position.x = viewport_width
node.show()
var tween = node.create_tween()
tween.set_ease(_get_tween_ease(ease_type))
tween.tween_property(node, "position", original_pos, duration)
return tween
## 滑入动画(从上方)
func slide_in_top(node: Control, duration: float = SLIDE_DURATION, ease_type: EaseType = EaseType.EASE_OUT) -> Tween:
"""
从上方滑入动画
@param node: 要动画的节点
@param duration: 动画时长
@param ease_type: 缓动类型
@return: Tween对象
"""
if not node:
return null
var original_pos = node.position
node.position.y = -node.size.y
node.show()
var tween = node.create_tween()
tween.set_ease(_get_tween_ease(ease_type))
tween.tween_property(node, "position", original_pos, duration)
return tween
## 滑入动画(从下方)
func slide_in_bottom(node: Control, duration: float = SLIDE_DURATION, ease_type: EaseType = EaseType.EASE_OUT) -> Tween:
"""
从下方滑入动画
@param node: 要动画的节点
@param duration: 动画时长
@param ease_type: 缓动类型
@return: Tween对象
"""
if not node:
return null
var original_pos = node.position
var viewport_height = node.get_viewport().get_visible_rect().size.y
node.position.y = viewport_height
node.show()
var tween = node.create_tween()
tween.set_ease(_get_tween_ease(ease_type))
tween.tween_property(node, "position", original_pos, duration)
return tween
## 缩放动画(弹出效果)
func scale_popup(node: Control, duration: float = SCALE_DURATION, ease_type: EaseType = EaseType.BOUNCE) -> Tween:
"""
缩放弹出动画
@param node: 要动画的节点
@param duration: 动画时长
@param ease_type: 缓动类型
@return: Tween对象
"""
if not node:
return null
node.scale = Vector2.ZERO
node.show()
var tween = node.create_tween()
tween.set_ease(_get_tween_ease(ease_type))
tween.tween_property(node, "scale", Vector2.ONE, duration)
return tween
## 按钮点击反馈动画
func button_press_feedback(button: Button, scale_factor: float = 0.95, duration: float = 0.1) -> Tween:
"""
按钮点击反馈动画
@param button: 按钮节点
@param scale_factor: 缩放因子
@param duration: 动画时长
@return: Tween对象
"""
if not button:
return null
var tween = button.create_tween()
tween.tween_property(button, "scale", Vector2.ONE * scale_factor, duration)
tween.tween_property(button, "scale", Vector2.ONE, duration)
return tween
## 摇摆动画(错误提示)
func shake_error(node: Control, intensity: float = 10.0, duration: float = 0.5) -> Tween:
"""
摇摆动画(用于错误提示)
@param node: 要动画的节点
@param intensity: 摇摆强度
@param duration: 动画时长
@return: Tween对象
"""
if not node:
return null
var original_pos = node.position
var tween = node.create_tween()
# 创建摇摆效果
for i in range(4):
var offset = Vector2(randf_range(-intensity, intensity), 0)
tween.tween_property(node, "position", original_pos + offset, duration / 8)
tween.tween_property(node, "position", original_pos, duration / 8)
return tween
## 脉冲动画(强调效果)
func pulse_highlight(node: Control, scale_max: float = 1.1, duration: float = 0.6) -> Tween:
"""
脉冲动画(强调效果)
@param node: 要动画的节点
@param scale_max: 最大缩放
@param duration: 动画时长
@return: Tween对象
"""
if not node:
return null
var tween = node.create_tween()
tween.set_loops() # 无限循环
tween.tween_property(node, "scale", Vector2.ONE * scale_max, duration / 2)
tween.tween_property(node, "scale", Vector2.ONE, duration / 2)
return tween
## 停止脉冲动画
func stop_pulse(node: Control) -> void:
"""
停止脉冲动画并恢复原始缩放
@param node: 节点
"""
if not node:
return
# 停止所有tween
node.get_tree().call_group("tween", "kill")
# 恢复原始缩放
var tween = node.create_tween()
tween.tween_property(node, "scale", Vector2.ONE, 0.2)
## 组合动画:淡入+滑入
func fade_slide_in(node: Control, direction: String = "bottom", duration: float = SLIDE_DURATION) -> Tween:
"""
组合动画:淡入+滑入
@param node: 要动画的节点
@param direction: 滑入方向("left", "right", "top", "bottom"
@param duration: 动画时长
@return: Tween对象
"""
if not node:
return null
# 设置初始状态
node.modulate.a = 0.0
var original_pos = node.position
match direction:
"left":
node.position.x = -node.size.x
"right":
node.position.x = node.get_viewport().get_visible_rect().size.x
"top":
node.position.y = -node.size.y
"bottom":
node.position.y = node.get_viewport().get_visible_rect().size.y
node.show()
# 创建并行动画
var tween = node.create_tween()
tween.set_parallel(true)
tween.tween_property(node, "modulate:a", 1.0, duration)
tween.tween_property(node, "position", original_pos, duration)
return tween
## 获取Tween缓动类型
func _get_tween_ease(ease_type: EaseType) -> Tween.EaseType:
"""
将自定义缓动类型转换为Tween缓动类型
@param ease_type: 自定义缓动类型
@return: Tween缓动类型
"""
match ease_type:
EaseType.EASE_IN:
return Tween.EASE_IN
EaseType.EASE_OUT:
return Tween.EASE_OUT
EaseType.EASE_IN_OUT:
return Tween.EASE_IN_OUT
EaseType.BOUNCE:
return Tween.EASE_OUT # Godot没有内置bounce使用ease_out
EaseType.ELASTIC:
return Tween.EASE_OUT # Godot没有内置elastic使用ease_out
_:
return Tween.EASE_OUT
## 创建加载动画
func create_loading_spinner(parent: Control, size: Vector2 = Vector2(32, 32)) -> Control:
"""
创建加载旋转动画
@param parent: 父节点
@param size: 大小
@return: 旋转节点
"""
var spinner = ColorRect.new()
spinner.size = size
spinner.color = Color.WHITE
# 创建简单的旋转图形
var style = StyleBoxFlat.new()
style.bg_color = Color.TRANSPARENT
style.border_width_top = 3
style.border_width_right = 1
style.border_width_bottom = 1
style.border_width_left = 1
style.border_color = Color.WHITE
style.corner_radius_top_left = size.x / 2
style.corner_radius_top_right = size.x / 2
style.corner_radius_bottom_left = size.x / 2
style.corner_radius_bottom_right = size.x / 2
spinner.add_theme_stylebox_override("panel", style)
parent.add_child(spinner)
# 添加旋转动画
var tween = spinner.create_tween()
tween.set_loops()
tween.tween_property(spinner, "rotation", TAU, 1.0)
return spinner
## 移除加载动画
func remove_loading_spinner(spinner: Control) -> void:
"""
移除加载旋转动画
@param spinner: 旋转节点
"""
if spinner and is_instance_valid(spinner):
spinner.queue_free()