diff --git a/scenes/menus/storybook/components/storybook.gd b/scenes/menus/storybook/components/storybook.gd index 8c7ee482b..1d3dc2bdc 100644 --- a/scenes/menus/storybook/components/storybook.gd +++ b/scenes/menus/storybook/components/storybook.gd @@ -26,6 +26,12 @@ var _current_spread_index: int = -1 var _navigation_locked: bool = false var _current_list_page: int = 0 +## A copy of all quests loaded on ready (before filtering) +var _all_quests: Array[Quest] = [] +var _filtered_quests: Array[Quest] = [] + +var _current_tab_index: int = 0 # 0: TOC, 1: EN, 2: ES + @onready var left_quest_list: VBoxContainer = %LeftQuestList @onready var right_quest_list: VBoxContainer = %RightQuestList @@ -35,6 +41,11 @@ var _current_list_page: int = 0 @onready var animated_book: AnimatedSprite2D = %AnimatedSprite2D @onready var ui_container: Control = %StoryBookContent +# Bookmark button references +@onready var toc_bookmark_button: Button = %TOCBookmark +@onready var en_bookmark_button: Button = %ENBookmark +@onready var es_bookmark_button: Button = %ESBookmark + func _fade_out_ui() -> void: var tween := create_tween() @@ -51,6 +62,20 @@ func _fade_in_ui() -> void: func _ready() -> void: animated_book.animation_finished.connect(_on_animation_finished) + + # Saving a copy of all quests + _all_quests = quests + _filtered_quests = quests + + # Connecting the bookmark buttons + if toc_bookmark_button: + toc_bookmark_button.pressed.connect(_on_toc_bookmark_pressed) + if en_bookmark_button: + en_bookmark_button.pressed.connect(_on_en_bookmark_pressed) + if es_bookmark_button: + es_bookmark_button.pressed.connect(_on_es_bookmark_pressed) + + _update_bookmark_visibility() _populate_quest_lists() @@ -74,11 +99,11 @@ func _populate_quest_lists() -> void: var previous_button: Button = null # Building the left page - for i in range(left_start, min(left_end, quests.size())): + for i in range(left_start, min(left_end, _filtered_quests.size())): previous_button = _create_quest_button(i, left_quest_list, previous_button) #Building the right page - for i in range(right_start, min(right_end, quests.size())): + for i in range(right_start, min(right_end, _filtered_quests.size())): previous_button = _create_quest_button(i, right_quest_list, previous_button) # If the right page is empty, add a blank Control spacer so it maintains its width if right_quest_list.get_child_count() == 0: @@ -98,7 +123,7 @@ func _populate_quest_lists() -> void: func _create_quest_button( quest_index: int, parent_container: VBoxContainer, prev_btn: Button ) -> Button: - var quest: Quest = quests[quest_index] + var quest: Quest = _filtered_quests[quest_index] var button := Button.new() button.text = quest.get_title() button.theme_type_variation = "FlatButton" @@ -132,8 +157,8 @@ func _update_page_visibility() -> void: storybook_page.visible = true var quest_index: int = _current_spread_index - 1 - if quest_index >= 0 and quest_index < quests.size(): - var quest: Quest = quests[quest_index] + if quest_index >= 0 and quest_index < _filtered_quests.size(): + var quest: Quest = _filtered_quests[quest_index] storybook_page.quest = quest if storybook_page.play_button and is_instance_valid(storybook_page.play_button): @@ -168,7 +193,7 @@ func _switch_to_page(spread_index: int) -> void: if _navigation_locked: return - var total_spreads: int = quests.size() + 1 + var total_spreads: int = _filtered_quests.size() + 1 if total_spreads <= 1: return @@ -206,16 +231,21 @@ func _on_left_button_pressed() -> void: return # If we are on the main index, turn pages back inside the list - if _current_spread_index == 0 and _current_list_page > 0: - _navigation_locked = true - _current_list_page -= 1 - await _fade_out_ui() - animated_book.play("book_left") - await animated_book.animation_finished - _populate_quest_lists() - _update_page_visibility() - _fade_in_ui() - _navigation_locked = false + if _current_spread_index == 0: + if _current_list_page > 0: + _navigation_locked = true + _current_list_page -= 1 + await _fade_out_ui() + animated_book.play("book_left") + await animated_book.animation_finished + _populate_quest_lists() + _update_page_visibility() + _fade_in_ui() + _navigation_locked = false + return + + # Flipping back from the first page returns to full table of contents + _switch_bookmark_tab(0, "") return _switch_to_page(_current_spread_index - 1) @@ -228,7 +258,7 @@ func _on_right_button_pressed() -> void: # If we are on the main index, check if there are more quests to reveal on a new page if _current_spread_index == 0: var max_visible_so_far: int = (_current_list_page + 1) * quests_per_page * 2 - if quests.size() > max_visible_so_far: + if _filtered_quests.size() > max_visible_so_far: _navigation_locked = true _current_list_page += 1 await _fade_out_ui() @@ -271,3 +301,92 @@ func _on_back_button_pressed() -> void: func reset_focus() -> void: _switch_to_page(0) + + +func _on_toc_bookmark_pressed() -> void: + _switch_bookmark_tab(0, "") + + +func _on_en_bookmark_pressed() -> void: + _switch_bookmark_tab(1, "en") + + +func _on_es_bookmark_pressed() -> void: + _switch_bookmark_tab(2, "es") + + +func _show_table_of_contents() -> void: + _filtered_quests = _all_quests + _reset_storybook_list_view() + + +func _filter_quests_by_language(lang_code: String) -> void: + _filtered_quests = _all_quests.filter( + func(quest: Quest) -> bool: return quest.language == lang_code + ) + _reset_storybook_list_view() + + +func _reset_storybook_list_view() -> void: + _current_list_page = 0 + _current_spread_index = 0 + _populate_quest_lists() + _update_page_visibility() + + +func _switch_bookmark_tab(target_tab_index: int, lang_code: String) -> void: + if _navigation_locked or target_tab_index == _current_tab_index: + return + + _navigation_locked = true + var old_tab_index: int = _current_tab_index + _current_tab_index = target_tab_index + + # Fade out UI + await _fade_out_ui() + + # Flip forward if target > current, otherwise flip backward + if target_tab_index > old_tab_index: + animated_book.play("book_right") + else: + animated_book.play("book_left") + + # Wait for animation to finish before rebuilding list + await animated_book.animation_finished + + # Filter quests array + if lang_code == "": + _filtered_quests = _all_quests + else: + _filtered_quests = _all_quests.filter( + func(quest: Quest) -> bool: return quest.language == lang_code + ) + + # Reset page counters and reload UI + _current_list_page = 0 + _current_spread_index = 0 + _populate_quest_lists() + _update_page_visibility() + + # Fade back in + _fade_in_ui() + _navigation_locked = false + + +func _update_bookmark_visibility() -> void: + var unique_languages := [] + for q in _all_quests: + if q.language != "" and q.language not in unique_languages: + unique_languages.append(q.language) + + # Only show language bookmarks if there is more than 1 language + var show_language_tabs: bool = unique_languages.size() > 1 + + # Check if at least one quest exists for each language + var has_en: bool = _all_quests.any(func(q: Quest) -> bool: return q.language == "en") + var has_es: bool = _all_quests.any(func(q: Quest) -> bool: return q.language == "es") + + if en_bookmark_button: + en_bookmark_button.visible = show_language_tabs and has_en + if es_bookmark_button: + es_bookmark_button.visible = show_language_tabs and has_es diff --git a/scenes/menus/storybook/components/storybook_test.gd b/scenes/menus/storybook/components/storybook_test.gd index b0e5455f7..7ab97c7f5 100644 --- a/scenes/menus/storybook/components/storybook_test.gd +++ b/scenes/menus/storybook/components/storybook_test.gd @@ -7,13 +7,23 @@ const STORYBOOK_SCENE := preload("uid://bhm7fdjvppt8b") @export_range(0, 100, 1, "or_greater") var quests_amount: int = 30 var titles := [ - "Lord of the Needles", + "El Señor de las Agujas", "The Secret of Crochet", - "The Dark Knit", + "El tejido oscurot", "The Needle and the Sorcerer", "Conan the Weaver", "Return to Fray's End", "The Little HushRoom", + "Le Seigneur des Aiguilles", +] + +var spanish_titles := [ + "El Señor de las Agujas", + "El tejido oscurot", +] + +var french_titles := [ + "Le Seigneur des Aiguilles", ] @@ -22,6 +32,14 @@ func _ready() -> void: for i in range(quests_amount): var q := Quest.new() q.title = titles.pick_random() + + if q.title in spanish_titles: + q.language = "es" + elif q.title in french_titles: + q.language = "fr" + else: + q.language = "en" + quests.append(q) var storybook := STORYBOOK_SCENE.instantiate() storybook.quests = quests diff --git a/scenes/menus/storybook/storybook.tscn b/scenes/menus/storybook/storybook.tscn index df23484ee..6d44f3fcf 100644 --- a/scenes/menus/storybook/storybook.tscn +++ b/scenes/menus/storybook/storybook.tscn @@ -1,7 +1,7 @@ [gd_scene format=3 uid="uid://bhm7fdjvppt8b"] [ext_resource type="Script" uid="uid://5bt5um5g1g3p" path="res://scenes/menus/storybook/components/storybook.gd" id="1_gw8hn"] -[ext_resource type="Script" uid="uid://dts1hwdy3phin" path="res://scenes/menus/storybook/components/quest.gd" id="3_21r2o"] +[ext_resource type="Script" uid="uid://dts1hwdy3phin" path="res://scenes/menus/storybook/components/quest.gd" id="2_ofgxb"] [ext_resource type="PackedScene" uid="uid://cgtonist08yxn" path="res://scenes/menus/storybook/components/storybook_page.tscn" id="3_n2i2u"] [ext_resource type="SpriteFrames" uid="uid://dne3cxrhbjuno" path="res://scenes/menus/storybook/components/storybook_animation.tres" id="3_y0b3i"] [ext_resource type="Texture2D" uid="uid://xe25gqovxxpe" path="res://assets/first_party/icons/left_arrow.png" id="5_m2ghf"] @@ -24,7 +24,7 @@ region = Rect2(576, 576, 64, 64) [node name="Storybook" type="CanvasLayer" unique_id=438542807] script = ExtResource("1_gw8hn") -quests = Array[ExtResource("3_21r2o")]([ExtResource("5_ywp77")]) +quests = Array[ExtResource("2_ofgxb")]([ExtResource("5_ywp77")]) [node name="ColorRect" type="ColorRect" parent="." unique_id=1792675940] modulate = Color(0, 0, 0, 0.70000005) @@ -225,5 +225,28 @@ editor_description = "This empty control expands to fill the center of the hbox, layout_mode = 2 size_flags_horizontal = 3 +[node name="BookmarkContainer" type="HBoxContainer" parent="." unique_id=1654245298] +offset_left = 474.0 +offset_top = 14.0 +offset_right = 805.0 +offset_bottom = 89.0 + +[node name="TOCBookmark" type="Button" parent="BookmarkContainer" unique_id=460814141] +unique_name_in_owner = true +layout_mode = 2 +text = "TOC" + +[node name="ENBookmark" type="Button" parent="BookmarkContainer" unique_id=399694213] +unique_name_in_owner = true +layout_mode = 2 +text = "EN +" + +[node name="ESBookmark" type="Button" parent="BookmarkContainer" unique_id=278781945] +unique_name_in_owner = true +layout_mode = 2 +text = "ES +" + [connection signal="selected" from="VBoxContainer/CenterContainer/StoryBookContent/StorybookPage" to="." method="_on_storybook_page_selected"] [connection signal="pressed" from="VBoxContainer/CenterContainer/StoryBookContent/BackButton" to="." method="_on_back_button_pressed"]