1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
| extends Control
# 必须要有一个control子集包含卡片列表 @onready var control = get_child(0)
# 获取卡片列表 var card_list = func() -> Array[Node]:return control.get_children(false)
# 卡片有多少 var card_len = func() -> int:return len(card_list.call())
############### EXPORT ###############
# 滑动方向(不要运行时更改此变量) @export_enum("Horizontal","Vertical") var slide_direction = 0
# Card的间隔(至少为80) @export var card_separation : float = 80.0
# 明度变化 @export var dynamic_brightness : bool = false
# 缩放变化 @export var dynamic_scale : bool = false
######################################
# 界面基准位置 var interface_center : Callable = func() -> Vector2:return size / 2
func _ready(): control.connect("child_entered_tree",func(node : Node): if !card_list.call().is_empty() and node is Control: if slide_direction == 0: node.position.x = current_card.position.x + (node.size.x + card_separation) * (card_len.call()-1) else: node.position.y = current_card.position.y + (node.size.y + card_separation) * (card_len.call()-1) ) connect("child_exiting_tree",func(node : Node):) await Engine.get_main_loop().process_frame await Engine.get_main_loop().process_frame current_card.connect("gui_input", func(event : InputEvent): if event is InputEventScreenTouch and event.is_pressed(): var wheel = FortuneWheel.new() print(wheel.spin_batch([0.6,0.3,0.1],5)) )
# 当前卡片变化信号 signal current_card_changed(current_card : Node) # 当前card var current_card : Node: set(v): current_card = v if current_card != v: current_card_changed.emit(current_card)
# 插值目标值 var target_x : float var target_y : float func _process(delta): var node_x_arr : Array var node_y_arr : Array # [位置,Node] if slide_direction == 0: for node in card_list.call(): node_x_arr.append([node.global_position.x + node.size.x / 2.0,node]) else: for node in card_list.call(): node_y_arr.append([node.global_position.y + node.size.y / 2.0,node]) # 筛选最近的卡片 并实时赋值当前选中的卡片current_card if slide_direction == 0: node_x_arr.sort_custom( func(a,b): if abs(a[0] - interface_center.call().x) < abs(b[0] - interface_center.call().x): return true return false ) current_card = node_x_arr[0][1] else: node_y_arr.sort_custom( func(a,b): if abs(a[0] - interface_center.call().y) < abs(b[0] - interface_center.call().y): return true return false ) current_card = node_y_arr[0][1] ##### 特效区 ##### if slide_direction == 0: for item in node_x_arr: # 生成动态基准参考值 var s_value : float = 1.0 - percentage(0.0,card_separation * 10.,abs(item[0] - interface_center.call().x)) if s_value >= 0.95: s_value = roundf(s_value) # 控制明度 if dynamic_brightness: item[1].modulate.r = clampf(s_value,0.3,1.0) item[1].modulate.g = clampf(s_value,0.3,1.0) item[1].modulate.b = clampf(s_value,0.3,1.0) # 控制缩放 if dynamic_scale: item[1].scale.x = clampf(s_value,0.8,1.0) item[1].scale.y = clampf(s_value,0.8,1.0) else: for item in node_y_arr: # 生成动态基准参考值 var s_value : float = 1.0 - percentage(0.0,card_separation * 10.,abs(item[0] - interface_center.call().y)) if s_value >= 0.95: s_value = roundf(s_value) # 控制明度 if dynamic_brightness: item[1].modulate.r = clampf(s_value,0.3,1.0) item[1].modulate.g = clampf(s_value,0.3,1.0) item[1].modulate.b = clampf(s_value,0.3,1.0) # 控制缩放 if dynamic_scale: item[1].scale.x = clampf(s_value,0.8,1.0) item[1].scale.y = clampf(s_value,0.8,1.0)
## 最终插值 if !Input.is_action_pressed("mouse_left"): if slide_direction == 0: target_x = (-current_card.position.x) + (interface_center.call().x) - (card_separation * 1.5) control.position.x = lerp(control.position.x, target_x,0.4) else: target_y = (-current_card.position.y) + (interface_center.call().y) - (card_separation * 1.) control.position.y = lerp(control.position.y, target_y,0.4)
func _gui_input(event): if event is InputEventScreenDrag: if slide_direction == 0: var velocity : float = percentage(0.0,card_separation,abs(current_card.global_position.x + current_card.size.x / 2.0 - interface_center.call().x)) / 4 velocity = clampf(velocity,0.4,1.0) control.position.x += (event.relative.x * velocity) * 2 else: var velocity : float = percentage(0.0,card_separation,abs(current_card.global_position.y + current_card.size.y / 2.0 - interface_center.call().y)) / 4 velocity = clampf(velocity,0.4,1.0) control.position.y += (event.relative.y * velocity) * 2 pass
static func percentage(min : float,max : float,value : float) -> float: return float(value - min) / float(max - min)
|