2023-11-26 01:02:03 +02:00
|
|
|
@tool
|
|
|
|
|
2023-11-28 00:46:05 +02:00
|
|
|
extends Node3D
|
2023-11-16 20:23:17 +02:00
|
|
|
class_name Button3D
|
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
signal on_button_down()
|
|
|
|
signal on_button_up()
|
2024-04-10 01:21:38 +03:00
|
|
|
signal on_toggled(active: bool)
|
2023-11-22 02:44:07 +02:00
|
|
|
|
2024-03-07 15:21:31 +02:00
|
|
|
const IconFont = preload ("res://assets/icons/icons.tres")
|
2024-03-07 16:49:33 +02:00
|
|
|
const ECHO_WAIT_INITIAL = 0.5
|
|
|
|
const ECHO_WAIT_REPEAT = 0.1
|
2023-11-26 01:02:03 +02:00
|
|
|
|
2024-03-21 14:29:10 +02:00
|
|
|
@onready var body: StaticBody3D = $Body
|
2023-11-28 00:46:05 +02:00
|
|
|
@onready var label_node: Label3D = $Body/Label
|
|
|
|
@onready var finger_area: Area3D = $FingerArea
|
|
|
|
|
|
|
|
@export var focusable: bool = true:
|
|
|
|
set(value):
|
|
|
|
focusable = value
|
2023-11-28 15:20:38 +02:00
|
|
|
if value == false:
|
|
|
|
add_to_group("ui_focus_stop")
|
2023-11-28 00:46:05 +02:00
|
|
|
else:
|
2023-11-28 15:20:38 +02:00
|
|
|
remove_from_group("ui_focus_stop")
|
2023-11-26 01:02:03 +02:00
|
|
|
|
2023-11-28 00:46:05 +02:00
|
|
|
@export var font_size: int = 10:
|
|
|
|
set(value):
|
|
|
|
font_size = value
|
2024-03-21 14:29:10 +02:00
|
|
|
if !is_inside_tree()||icon: return
|
|
|
|
label_node.font_size = font_size
|
|
|
|
|
2023-11-26 01:02:03 +02:00
|
|
|
@export var label: String = "":
|
|
|
|
set(value):
|
2023-11-26 04:06:31 +02:00
|
|
|
label = value
|
2024-03-21 14:29:10 +02:00
|
|
|
if !is_inside_tree(): return
|
|
|
|
label_node.text = label
|
|
|
|
|
2023-11-26 01:02:03 +02:00
|
|
|
@export var icon: bool = false:
|
|
|
|
set(value):
|
|
|
|
icon = value
|
2024-03-21 14:29:10 +02:00
|
|
|
if !is_inside_tree(): return
|
|
|
|
|
|
|
|
if icon:
|
2023-11-26 04:06:31 +02:00
|
|
|
label_node.font = IconFont
|
2024-01-23 19:02:41 +02:00
|
|
|
label_node.font_size = 36
|
2023-11-26 04:06:31 +02:00
|
|
|
label_node.width = 1000
|
|
|
|
label_node.autowrap_mode = TextServer.AUTOWRAP_OFF
|
2023-11-28 00:46:05 +02:00
|
|
|
else:
|
|
|
|
label_node.font = null
|
|
|
|
label_node.font_size = font_size
|
|
|
|
label_node.width = 50
|
|
|
|
label_node.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
2024-03-21 14:29:10 +02:00
|
|
|
|
2023-11-16 20:23:17 +02:00
|
|
|
@export var toggleable: bool = false
|
|
|
|
@export var disabled: bool = false
|
2024-03-07 16:49:33 +02:00
|
|
|
@export var echo: bool = false
|
2023-11-18 15:27:42 +02:00
|
|
|
@export var initial_active: bool = false
|
2024-01-23 18:48:13 +02:00
|
|
|
|
2023-11-28 00:46:05 +02:00
|
|
|
var active: bool = false:
|
2023-11-16 20:23:17 +02:00
|
|
|
set(value):
|
2024-04-10 14:23:17 +03:00
|
|
|
if active == value:
|
|
|
|
return
|
|
|
|
|
|
|
|
on_toggled.emit(value)
|
2024-03-21 14:29:10 +02:00
|
|
|
active = value
|
|
|
|
if !is_inside_tree(): return
|
|
|
|
update_animation(1.0 if active else 0.0)
|
|
|
|
|
2024-03-07 16:49:33 +02:00
|
|
|
var echo_timer: Timer = null
|
2023-11-16 20:23:17 +02:00
|
|
|
|
2023-11-18 15:27:42 +02:00
|
|
|
func _ready():
|
|
|
|
if initial_active:
|
|
|
|
active = true
|
2023-11-28 00:46:05 +02:00
|
|
|
|
2024-04-11 17:51:30 +03:00
|
|
|
Update.props(self, ["active", "external_value", "icon", "label", "font_size", "disabled"])
|
2024-03-21 14:29:10 +02:00
|
|
|
|
2024-03-07 16:49:33 +02:00
|
|
|
if echo:
|
|
|
|
echo_timer = Timer.new()
|
|
|
|
echo_timer.wait_time = ECHO_WAIT_INITIAL
|
|
|
|
echo_timer.one_shot = false
|
|
|
|
|
|
|
|
echo_timer.timeout.connect(func():
|
|
|
|
echo_timer.stop()
|
|
|
|
echo_timer.wait_time=ECHO_WAIT_REPEAT
|
|
|
|
echo_timer.start()
|
|
|
|
on_button_down.emit()
|
|
|
|
)
|
|
|
|
|
|
|
|
add_child(echo_timer)
|
|
|
|
|
2024-03-21 14:29:10 +02:00
|
|
|
func update_animation(value: float):
|
|
|
|
var tween = create_tween()
|
|
|
|
tween.set_parallel(true)
|
2023-11-28 00:46:05 +02:00
|
|
|
|
2024-03-21 14:29:10 +02:00
|
|
|
tween.tween_property(body, "scale:y", lerpf(1.0, 0.5, value), 0.2)
|
|
|
|
tween.tween_property(body, "position:y", lerpf(0.01, 0.005, value), 0.2)
|
2023-11-26 01:02:03 +02:00
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
func _on_press_down(event):
|
2023-11-16 20:23:17 +02:00
|
|
|
if disabled:
|
2023-11-22 02:44:07 +02:00
|
|
|
event.bubbling = false
|
2023-11-16 20:23:17 +02:00
|
|
|
return
|
|
|
|
|
2023-11-23 04:41:13 +02:00
|
|
|
AudioPlayer.play_effect("click")
|
|
|
|
|
2023-11-28 00:46:05 +02:00
|
|
|
if toggleable:
|
2023-11-16 20:23:17 +02:00
|
|
|
return
|
2023-11-22 02:44:07 +02:00
|
|
|
|
2024-03-07 16:49:33 +02:00
|
|
|
if echo:
|
|
|
|
echo_timer.start()
|
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
active = true
|
|
|
|
on_button_down.emit()
|
2023-11-16 20:23:17 +02:00
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
func _on_press_up(event):
|
2023-11-16 20:23:17 +02:00
|
|
|
if disabled:
|
2023-11-22 02:44:07 +02:00
|
|
|
event.bubbling = false
|
2023-11-16 20:23:17 +02:00
|
|
|
return
|
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
if toggleable:
|
|
|
|
active = !active
|
2023-11-23 04:41:13 +02:00
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
if active:
|
|
|
|
on_button_down.emit()
|
|
|
|
else:
|
|
|
|
on_button_up.emit()
|
|
|
|
else:
|
2024-03-07 16:49:33 +02:00
|
|
|
if echo:
|
|
|
|
echo_timer.stop()
|
|
|
|
echo_timer.wait_time = ECHO_WAIT_INITIAL
|
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
active = false
|
|
|
|
on_button_up.emit()
|
2023-11-28 00:46:05 +02:00
|
|
|
|
|
|
|
func _on_touch_enter(event: EventTouch):
|
2024-03-07 15:21:31 +02:00
|
|
|
if event.target != finger_area:
|
|
|
|
return
|
2023-11-28 00:46:05 +02:00
|
|
|
|
2024-03-21 17:19:09 +02:00
|
|
|
if disabled:
|
|
|
|
event.bubbling = false
|
|
|
|
return
|
|
|
|
|
|
|
|
AudioPlayer.play_effect("click")
|
2023-11-28 00:46:05 +02:00
|
|
|
|
|
|
|
if toggleable:
|
|
|
|
active = !active
|
|
|
|
if active:
|
|
|
|
on_button_down.emit()
|
2024-03-21 17:19:09 +02:00
|
|
|
else:
|
|
|
|
on_button_up.emit()
|
2023-11-28 00:46:05 +02:00
|
|
|
|
2024-03-21 17:19:09 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
active = true
|
|
|
|
on_button_down.emit()
|
|
|
|
|
|
|
|
_touch_change(event)
|
|
|
|
|
|
|
|
func _on_touch_move(event: EventTouch):
|
2023-11-28 00:46:05 +02:00
|
|
|
if disabled:
|
|
|
|
event.bubbling = false
|
|
|
|
return
|
|
|
|
|
2024-03-21 17:19:09 +02:00
|
|
|
if toggleable:
|
|
|
|
return
|
|
|
|
|
|
|
|
_touch_change(event)
|
|
|
|
|
|
|
|
func _on_touch_leave(event: EventTouch):
|
|
|
|
if disabled:
|
|
|
|
event.bubbling = false
|
|
|
|
return
|
|
|
|
|
|
|
|
if toggleable:
|
|
|
|
return
|
|
|
|
|
|
|
|
active = false
|
|
|
|
on_button_up.emit()
|
|
|
|
|
|
|
|
func _touch_change(event: EventTouch):
|
|
|
|
|
2023-11-28 00:46:05 +02:00
|
|
|
var pos = Vector3(0, 1, 0)
|
|
|
|
for finger in event.fingers:
|
|
|
|
var finger_pos = to_local(finger.area.global_position)
|
|
|
|
if pos.y > finger_pos.y:
|
|
|
|
pos = finger_pos
|
|
|
|
|
2024-03-07 15:21:31 +02:00
|
|
|
var button_height = 0.2
|
|
|
|
var button_center = 0.1
|
2023-11-28 00:46:05 +02:00
|
|
|
|
|
|
|
var percent = clamp((button_center + button_height / 2 - pos.y) / (button_height / 2), 0, 1)
|
|
|
|
|
2024-03-21 14:29:10 +02:00
|
|
|
update_animation(percent)
|