feat: add battlepass slider and quest list tabs to lobby HUD
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
extends ScrollContainer
|
||||
|
||||
const SNAP_DURATION := 0.25
|
||||
const TEX_DEFAULT := preload("res://assets/graphics/gui/lobby/bar_default.svg")
|
||||
const TEX_ACTIVE := preload("res://assets/graphics/gui/lobby/bar_active.svg")
|
||||
|
||||
@export var auto_advance_enabled: bool = true
|
||||
@export var auto_advance_delay: float = 4.0
|
||||
|
||||
@onready var _track: HBoxContainer = $CardMargin/HBoxContainer
|
||||
@onready var _page_dots: Array = get_node_or_null("../PageIndicator").get_children() if get_node_or_null("../PageIndicator") else []
|
||||
|
||||
var _dragging := false
|
||||
var _drag_start_pos := 0.0
|
||||
var _drag_start_scroll := 0
|
||||
var _snap_tween: Tween
|
||||
var _auto_timer: Timer
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_update_indicator()
|
||||
_setup_auto_timer()
|
||||
|
||||
|
||||
func _setup_auto_timer() -> void:
|
||||
_auto_timer = Timer.new()
|
||||
_auto_timer.name = "AutoAdvanceTimer"
|
||||
_auto_timer.one_shot = true
|
||||
_auto_timer.timeout.connect(_on_auto_timer_timeout)
|
||||
add_child(_auto_timer)
|
||||
_restart_auto_timer()
|
||||
|
||||
|
||||
func _restart_auto_timer() -> void:
|
||||
if not auto_advance_enabled or _dragging or _card_count() <= 1:
|
||||
return
|
||||
_auto_timer.stop()
|
||||
_auto_timer.wait_time = auto_advance_delay
|
||||
_auto_timer.start()
|
||||
|
||||
|
||||
func _on_auto_timer_timeout() -> void:
|
||||
if _dragging:
|
||||
return
|
||||
var next_index := (_current_page() + 1) % _card_count()
|
||||
_animate_to_page(next_index)
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if _auto_timer:
|
||||
_auto_timer.stop()
|
||||
if _snap_tween:
|
||||
_snap_tween.kill()
|
||||
|
||||
|
||||
func _gui_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.pressed:
|
||||
_start_drag(event.position.x)
|
||||
elif _dragging:
|
||||
_end_drag()
|
||||
elif event is InputEventMouseMotion and _dragging:
|
||||
_update_drag(event.position.x)
|
||||
elif event is InputEventScreenTouch and event.index == 0:
|
||||
if event.pressed:
|
||||
_start_drag(event.position.x)
|
||||
elif _dragging:
|
||||
_end_drag()
|
||||
elif event is InputEventScreenDrag and event.index == 0 and _dragging:
|
||||
_update_drag(event.position.x)
|
||||
|
||||
|
||||
func _start_drag(x: float) -> void:
|
||||
if _snap_tween:
|
||||
_snap_tween.kill()
|
||||
_auto_timer.stop()
|
||||
_dragging = true
|
||||
_drag_start_pos = x
|
||||
_drag_start_scroll = scroll_horizontal
|
||||
|
||||
|
||||
func _update_drag(x: float) -> void:
|
||||
var delta := _drag_start_pos - x
|
||||
scroll_horizontal = clampi(_drag_start_scroll + int(delta), 0, _max_scroll())
|
||||
_update_indicator()
|
||||
|
||||
|
||||
func _end_drag() -> void:
|
||||
_dragging = false
|
||||
_snap_to_nearest_card()
|
||||
|
||||
|
||||
func _max_scroll() -> int:
|
||||
var bar := get_h_scroll_bar()
|
||||
return maxi(0, int(bar.max_value - bar.page))
|
||||
|
||||
|
||||
func _card_count() -> int:
|
||||
return maxi(1, _track.get_child_count())
|
||||
|
||||
|
||||
func _card_step() -> float:
|
||||
var count := _card_count()
|
||||
if count <= 1:
|
||||
return 0.0
|
||||
return float(_max_scroll()) / float(count - 1)
|
||||
|
||||
|
||||
func _current_page() -> int:
|
||||
var step := _card_step()
|
||||
if step <= 0.0:
|
||||
return 0
|
||||
return clampi(roundi(scroll_horizontal / step), 0, _card_count() - 1)
|
||||
|
||||
|
||||
func _snap_to_nearest_card() -> void:
|
||||
_animate_to_page(_current_page())
|
||||
|
||||
|
||||
func _animate_to_page(target_index: int) -> void:
|
||||
target_index = clampi(target_index, 0, _card_count() - 1)
|
||||
var step := _card_step()
|
||||
var target_scroll := int(round(target_index * step))
|
||||
if _snap_tween:
|
||||
_snap_tween.kill()
|
||||
_snap_tween = create_tween().set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
|
||||
_snap_tween.tween_method(_set_scroll_and_indicator, float(scroll_horizontal), float(target_scroll), SNAP_DURATION)
|
||||
_snap_tween.finished.connect(_restart_auto_timer)
|
||||
|
||||
|
||||
func _set_scroll_and_indicator(value: float) -> void:
|
||||
scroll_horizontal = int(round(value))
|
||||
_update_indicator()
|
||||
|
||||
|
||||
func _update_indicator() -> void:
|
||||
if _page_dots.is_empty():
|
||||
return
|
||||
var active_index := _current_page()
|
||||
for i in _page_dots.size():
|
||||
var dot: TextureRect = _page_dots[i]
|
||||
dot.texture = TEX_ACTIVE if i == active_index else TEX_DEFAULT
|
||||
Reference in New Issue
Block a user