feat: add battlepass slider and quest list tabs to lobby HUD
This commit is contained in:
+142
-1
@@ -12,6 +12,8 @@ extends Control
|
||||
@onready var avatar_display = %AvatarDisplay
|
||||
@onready var lobby_settings_btn = %SettingsBtn
|
||||
@onready var quit_btn = %QuitBtn
|
||||
@onready var chat_toggle_btn = get_node_or_null("%BubbleBtn")
|
||||
@onready var chat_panel_container = $MainMenuPanel/MainMargin/MainHBox/LeftCol/ChatPanel
|
||||
|
||||
# Main Menu 3D Preview
|
||||
@onready var character_root = %CharacterRoot
|
||||
@@ -158,6 +160,29 @@ var _friend_suggest_list: ItemList
|
||||
# var server_option: OptionButton
|
||||
# var server_ip_input: LineEdit
|
||||
|
||||
# =============================================================================
|
||||
# Menu Button Animation (ROOM / PLAY hover + press juice)
|
||||
# =============================================================================
|
||||
@export_group("Menu Button Animation")
|
||||
@export var menu_btn_hover_scale: float = 1.06
|
||||
@export var menu_btn_press_scale: float = 0.94
|
||||
@export var menu_btn_hover_duration: float = 0.15
|
||||
@export var menu_btn_press_duration: float = 0.08
|
||||
@export var menu_btn_release_duration: float = 0.2
|
||||
@export var menu_btn_hover_trans: Tween.TransitionType = Tween.TRANS_BACK
|
||||
@export var menu_btn_hover_ease: Tween.EaseType = Tween.EASE_OUT
|
||||
@export var menu_btn_hover_brighten: float = 1.08
|
||||
|
||||
@export_group("Card Fan Idle Animation")
|
||||
@export var card_fan_idle_enabled: bool = true
|
||||
@export var card_fan_jump_height: float = 14.0
|
||||
@export var card_fan_jump_duration: float = 0.35
|
||||
@export var card_fan_jump_stagger: float = 0.15
|
||||
@export var card_fan_cycle_pause: float = 14.0
|
||||
|
||||
var _button_tweens: Dictionary = {}
|
||||
var _card_fan_tweens: Dictionary = {}
|
||||
|
||||
|
||||
func _ready():
|
||||
chat = LobbyChat.new(self)
|
||||
@@ -182,7 +207,10 @@ func _ready():
|
||||
|
||||
# Initial UI update
|
||||
_sync_room_profile_card()
|
||||
|
||||
|
||||
# ROOM / PLAY button hover, press, and card-fan idle animation
|
||||
_setup_menu_button_animations()
|
||||
|
||||
# Connect Social / Friend UI
|
||||
var global_chat_tab_btn = get_node_or_null("%GlobalChatTabBtn")
|
||||
if global_chat_tab_btn:
|
||||
@@ -401,6 +429,119 @@ func _connect_slot_signals(slot: Control, i: int):
|
||||
if right_btn:
|
||||
right_btn.pressed.connect(func(): LobbyManager.cycle_character(1))
|
||||
|
||||
# =============================================================================
|
||||
# Menu Button Animation (ROOM / PLAY)
|
||||
# =============================================================================
|
||||
|
||||
func _setup_menu_button_animations() -> void:
|
||||
for btn in [browse_rooms_btn, create_room_btn]:
|
||||
if not btn:
|
||||
continue
|
||||
btn.pivot_offset = btn.size / 2.0
|
||||
btn.mouse_entered.connect(_on_menu_btn_mouse_entered.bind(btn))
|
||||
btn.mouse_exited.connect(_on_menu_btn_mouse_exited.bind(btn))
|
||||
btn.button_down.connect(_on_menu_btn_down.bind(btn))
|
||||
btn.button_up.connect(_on_menu_btn_up.bind(btn))
|
||||
|
||||
_start_card_fan_idle(get_node_or_null("MainMenuPanel/MainMargin/MainHBox/RightCol/BottomRightPanel/RoomBtnRoot"))
|
||||
_start_card_fan_idle(get_node_or_null("MainMenuPanel/MainMargin/MainHBox/RightCol/BottomRightPanel/PlayBtnRoot"))
|
||||
|
||||
if chat_toggle_btn:
|
||||
chat_toggle_btn.pressed.connect(_on_chat_toggle_pressed)
|
||||
|
||||
|
||||
func _on_chat_toggle_pressed() -> void:
|
||||
if chat_panel_container:
|
||||
chat_panel_container.visible = not chat_panel_container.visible
|
||||
|
||||
|
||||
func _kill_button_tween(btn: Control) -> void:
|
||||
if _button_tweens.has(btn) and is_instance_valid(_button_tweens[btn]):
|
||||
_button_tweens[btn].kill()
|
||||
|
||||
|
||||
func _tween_button_scale(btn: Control, target_scale: float, duration: float, use_overshoot: bool = false) -> void:
|
||||
_kill_button_tween(btn)
|
||||
var tween := create_tween()
|
||||
if use_overshoot:
|
||||
tween.set_trans(menu_btn_hover_trans).set_ease(menu_btn_hover_ease)
|
||||
else:
|
||||
tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
|
||||
tween.tween_property(btn, "scale", Vector2(target_scale, target_scale), duration)
|
||||
_button_tweens[btn] = tween
|
||||
|
||||
|
||||
func _on_menu_btn_mouse_entered(btn: Control) -> void:
|
||||
if btn.disabled:
|
||||
return
|
||||
_tween_button_scale(btn, menu_btn_hover_scale, menu_btn_hover_duration, true)
|
||||
btn.self_modulate = Color(menu_btn_hover_brighten, menu_btn_hover_brighten, menu_btn_hover_brighten, 1.0)
|
||||
|
||||
|
||||
func _on_menu_btn_mouse_exited(btn: Control) -> void:
|
||||
_tween_button_scale(btn, 1.0, menu_btn_release_duration)
|
||||
btn.self_modulate = Color.WHITE
|
||||
|
||||
|
||||
func _on_menu_btn_down(btn: Control) -> void:
|
||||
_tween_button_scale(btn, menu_btn_press_scale, menu_btn_press_duration)
|
||||
|
||||
|
||||
func _on_menu_btn_up(btn: Control) -> void:
|
||||
var target := menu_btn_hover_scale if btn.get_global_rect().has_point(get_global_mouse_position()) else 1.0
|
||||
_tween_button_scale(btn, target, menu_btn_release_duration, true)
|
||||
|
||||
|
||||
func _start_card_fan_idle(root: Control) -> void:
|
||||
if not root or not card_fan_idle_enabled:
|
||||
return
|
||||
|
||||
# find_child (recursive) instead of a direct get_node_or_null so this still
|
||||
# finds the cards even if they end up nested under a layout wrapper (e.g. a
|
||||
# PanelContainer) instead of being direct children of root.
|
||||
var cards: Array[Control] = []
|
||||
for card_name in ["CardLeft", "CardRight"]:
|
||||
var card := root.find_child(card_name, true, false) as Control
|
||||
if card:
|
||||
cards.append(card)
|
||||
if cards.is_empty():
|
||||
return
|
||||
|
||||
if _card_fan_tweens.has(root):
|
||||
for old_tween in _card_fan_tweens[root]:
|
||||
if is_instance_valid(old_tween):
|
||||
old_tween.kill()
|
||||
|
||||
# Sequential "leapfrog" jump: each card jumps in turn, staggered by
|
||||
# card_fan_jump_stagger, then the whole row pauses before looping.
|
||||
var cycle_total: float = cards.size() * card_fan_jump_stagger + card_fan_cycle_pause
|
||||
var tweens: Array[Tween] = []
|
||||
for i in cards.size():
|
||||
var card := cards[i]
|
||||
var start_y := card.position.y
|
||||
var lead_in: float = i * card_fan_jump_stagger
|
||||
var trailing: float = cycle_total - lead_in - card_fan_jump_duration
|
||||
var tween := create_tween().set_loops()
|
||||
if lead_in > 0.0:
|
||||
tween.tween_interval(lead_in)
|
||||
tween.tween_property(card, "position:y", start_y - card_fan_jump_height, card_fan_jump_duration * 0.5).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
|
||||
tween.tween_property(card, "position:y", start_y, card_fan_jump_duration * 0.5).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT)
|
||||
if trailing > 0.0:
|
||||
tween.tween_interval(trailing)
|
||||
tweens.append(tween)
|
||||
_card_fan_tweens[root] = tweens
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
for tween in _button_tweens.values():
|
||||
if is_instance_valid(tween):
|
||||
tween.kill()
|
||||
for tweens in _card_fan_tweens.values():
|
||||
for tween in tweens:
|
||||
if is_instance_valid(tween):
|
||||
tween.kill()
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Panel Management
|
||||
# =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user