Table of Contents
src / beginning / chapters / chapters.gd
Attached Scenes
Code
extends Control
signal focused(idx: int)
signal selected(idx: int)
signal ui_backed
@export var grab_focus_first : bool : set = set_grab_focus_first
@export var play_opening := false : set = set_play_opening
@export var current_plate : Plate = Plate.ROOT
@export var shown : bool = false
enum Plate { ROOT, MENU }
const ICON_OFFSET := 164
const INITIAL_CHAPTERS_X := 815
var focused_chapter_idx : int = 0
var selected_chapter_idx : int = -1
func _ready() -> void:
if get_parent() == get_tree().root:
%AnimationPlayer.play('opening')
FocusHelper.set_neighbors_h(%ChaptersContainer.get_children())
for chapter in %ChaptersContainer.get_children():
chapter.focus_entered.connect(_on_chapater_focused.bind(chapter))
load_focused_chapter_to_menu()
func setup_from_account_resource() -> void:
if not Current.account: return
var numbers = Current.account.chapters.map(func(c): return c.number)
for chapter in %ChaptersContainer.get_children():
var number = int(str(chapter.name)[-1])
if number == 0: continue
if not numbers.has(number): chapter.hide()
func _input(event: InputEvent) -> void:
if not (shown && current_plate == Plate.ROOT): return
if event.is_action_pressed("ui_back"):
go_back()
elif event.is_action_pressed("ui_accept"):
go_foward()
func go_back() -> void:
shown = false
%AnimationPlayer.play("RESET")
ui_backed.emit()
func go_foward() -> void:
current_plate = Plate.MENU
selected.emit(focused_chapter_idx)
func set_grab_focus_first(val: bool) -> void:
FocusHelper.grab_first(%ChaptersContainer, val)
func set_play_opening(val: bool) -> void:
if val: %AnimationPlayer.play("opening")
func focus_pin_to(idx: int) -> void:
var anim_name = "focus_pin_to_chapter_%s" % idx
if shown: %AnimationPlayer.play(anim_name)
else: %AnimationPlayer.queue(anim_name)
func zoom_pin_to(idx: int) -> void:
var anim_name = "zoom_pin_to_chapter_%s" % idx
%AnimationPlayer.play(anim_name)
func force_focus_return():
var target = get_chapter(focused_chapter_idx)
if not FocusHelper.is_focuesed(target):
target.focus_returned()
func load_focused_chapter_to_menu():
var chapter = get_chapter(focused_chapter_idx)
%Menu.chapter_resource = chapter.resource
func get_chapter(idx: int) -> Node:
return %ChaptersContainer.get_child(idx)
func set_chapters_animation_offset() -> void:
var current_pos = %ChaptersContainer.position
var anim = %ChaptersAnimationPlayer.get_animation('selected')
var track_idx = anim.find_track('.:position', Animation.TrackType.TYPE_VALUE)
anim.track_set_key_value(track_idx, 0, current_pos)
var pos = anim.track_get_key_value(track_idx, 1)
pos.x = current_pos.x
anim.track_set_key_value(track_idx, 1, pos)
anim = %ChaptersAnimationPlayer.get_animation('unselected')
track_idx = anim.find_track('.:position', Animation.TrackType.TYPE_VALUE)
pos = anim.track_get_key_value(track_idx, 0)
pos.x = current_pos.x
anim.track_set_key_value(track_idx, 0, pos)
anim.track_set_key_value(track_idx, 1, current_pos)
func _on_chapater_focused(chapter: Node) -> void:
var idx = int(str(chapter.name)[-1])
focused_chapter_idx = idx
%ChaptersContainer.position.x = INITIAL_CHAPTERS_X - (ICON_OFFSET * idx)
focus_pin_to(idx)
load_focused_chapter_to_menu()
focused.emit(idx)
func _on_animation_player_animation_finished(_anim_name: StringName) -> void:
if current_plate == Plate.ROOT:
force_focus_return()
func _on_selected(idx: int) -> void:
%Menu.grab_focus_first = true
selected_chapter_idx = idx
zoom_pin_to(idx)
get_chapter(idx).selected()
set_chapters_animation_offset()
%ChaptersAnimationPlayer.play("selected")
current_plate = Plate.MENU
func _on_menu_ui_backed() -> void:
if current_plate == Plate.MENU:
(func(): current_plate = Plate.ROOT).call_deferred()
get_chapter(selected_chapter_idx).unselected()
%ChaptersAnimationPlayer.play("unselected")
selected_chapter_idx = -1
force_focus_return()