From 953db093d9146c72ce2c30fdb90d7c3a33b3d12f Mon Sep 17 00:00:00 2001 From: Alonna <145865677+alcole2@users.noreply.github.com> Date: Fri, 14 Aug 2026 09:01:22 -0400 Subject: [PATCH 1/5] Adding language bookmarks TOC (table of contents), EN, and ES bookmark tabs have been added to the storybook menu to allow players to filter quests by language and still search through a single mixed list. I updated quest.gd and individual .tres quest files with ISO 639 language codes ("en" and "es") so the storybook can categorize the quests by this. Selecting a bookmark compares each quest's ISO code with it and filters the master _all_quests array, making a new list with only the matching language quests to show on the page. I also had to update func _on_left_button_pressed() to get players back to the table of contents or previous pages whenever they flip past page 0. --- .../menus/storybook/components/storybook.gd | 112 ++++++++++++++++-- scenes/menus/storybook/storybook.tscn | 27 ++++- 2 files changed, 127 insertions(+), 12 deletions(-) diff --git a/scenes/menus/storybook/components/storybook.gd b/scenes/menus/storybook/components/storybook.gd index 8c7ee482b..63b9fadaa 100644 --- a/scenes/menus/storybook/components/storybook.gd +++ b/scenes/menus/storybook/components/storybook.gd @@ -26,6 +26,10 @@ 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 _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 +39,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 +60,18 @@ 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.duplicate() + + # 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) + _populate_quest_lists() @@ -206,16 +227,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) @@ -271,3 +297,69 @@ 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: + quests = _all_quests.duplicate() + _reset_storybook_list_view() + + +func _filter_quests_by_language(lang_code: String) -> void: + 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 == "": + quests = _all_quests.duplicate() + else: + 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 diff --git a/scenes/menus/storybook/storybook.tscn b/scenes/menus/storybook/storybook.tscn index df23484ee..f25ed30a0 100644 --- a/scenes/menus/storybook/storybook.tscn +++ b/scenes/menus/storybook/storybook.tscn @@ -1,7 +1,6 @@ [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="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 +23,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 = [ExtResource("5_ywp77")] [node name="ColorRect" type="ColorRect" parent="." unique_id=1792675940] modulate = Color(0, 0, 0, 0.70000005) @@ -158,6 +157,30 @@ text = "Back" icon = ExtResource("5_m2ghf") flat = true +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/CenterContainer/StoryBookContent" unique_id=1654245298] +layout_mode = 0 +offset_left = -158.0 +offset_top = -297.0 +offset_right = 412.0 +offset_bottom = -222.0 + +[node name="TOCBookmark" type="Button" parent="VBoxContainer/CenterContainer/StoryBookContent/HBoxContainer" unique_id=460814141] +unique_name_in_owner = true +layout_mode = 2 +text = "TOC" + +[node name="ENBookmark" type="Button" parent="VBoxContainer/CenterContainer/StoryBookContent/HBoxContainer" unique_id=399694213] +unique_name_in_owner = true +layout_mode = 2 +text = "EN +" + +[node name="ESBookmark" type="Button" parent="VBoxContainer/CenterContainer/StoryBookContent/HBoxContainer" unique_id=278781945] +unique_name_in_owner = true +layout_mode = 2 +text = "ES +" + [node name="MarginContainer" type="MarginContainer" parent="VBoxContainer" unique_id=1971907031] layout_mode = 2 theme_override_constants/margin_right = 8 From aa79b6dbd0f0b32cdd4a99a7305ff53c8a1dd0bf Mon Sep 17 00:00:00 2001 From: Alonna <145865677+alcole2@users.noreply.github.com> Date: Fri, 14 Aug 2026 10:50:19 -0400 Subject: [PATCH 2/5] Comment correction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel Quiñones --- scenes/menus/storybook/components/storybook.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/menus/storybook/components/storybook.gd b/scenes/menus/storybook/components/storybook.gd index 63b9fadaa..5ee57cd4a 100644 --- a/scenes/menus/storybook/components/storybook.gd +++ b/scenes/menus/storybook/components/storybook.gd @@ -39,7 +39,7 @@ var _current_tab_index: int = 0 # 0: TOC, 1: EN, 2: ES @onready var animated_book: AnimatedSprite2D = %AnimatedSprite2D @onready var ui_container: Control = %StoryBookContent -#Bookmark button references +# Bookmark button references @onready var toc_bookmark_button: Button = %TOCBookmark @onready var en_bookmark_button: Button = %ENBookmark @onready var es_bookmark_button: Button = %ESBookmark From 214502d81aebc7936e09284570e11be252c9af62 Mon Sep 17 00:00:00 2001 From: Alonna <145865677+alcole2@users.noreply.github.com> Date: Fri, 14 Aug 2026 11:34:58 -0400 Subject: [PATCH 3/5] Updated storybook_test.gd with quests of multiple languages I added two Spanish and one French quests. The questss that aren't in English are also put into seperate lists for their respective language. They are actually assigned a language in the loop that appends them to the array so they can be filtered by the bookmarks. --- .../storybook/components/storybook_test.gd | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) 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 From 6b2ecec2bb323b57ff375397c88ef71b2dc614e5 Mon Sep 17 00:00:00 2001 From: Alonna <145865677+alcole2@users.noreply.github.com> Date: Mon, 17 Aug 2026 08:16:33 -0400 Subject: [PATCH 4/5] Hide empty language bookmarks and detach tabs from page fade - Hide unused language tabs by evaluating `_all_quests` on ready. This prevents players from clicking into empty quest lists when there aren't any any quests for that specific language. - Remove all language tabs if all quests share the same language. _all_quests is inspected during _update_bookmark_visibility() to count unique language codes. If only one code exists in the array, the function sets the visibility of the language filter buttons to false. - Reparent `BookmarkContainer` outside `%StoryBookContent`. This keeps the tab buttons on the screen instead of fading in and out during page flip animations. --- .../menus/storybook/components/storybook.gd | 20 ++++++++ scenes/menus/storybook/storybook.tscn | 50 +++++++++---------- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/scenes/menus/storybook/components/storybook.gd b/scenes/menus/storybook/components/storybook.gd index 5ee57cd4a..0aa12981d 100644 --- a/scenes/menus/storybook/components/storybook.gd +++ b/scenes/menus/storybook/components/storybook.gd @@ -72,6 +72,7 @@ func _ready() -> void: if es_bookmark_button: es_bookmark_button.pressed.connect(_on_es_bookmark_pressed) + _update_bookmark_visibility() _populate_quest_lists() @@ -363,3 +364,22 @@ func _switch_bookmark_tab(target_tab_index: int, lang_code: String) -> void: # 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/storybook.tscn b/scenes/menus/storybook/storybook.tscn index f25ed30a0..6d44f3fcf 100644 --- a/scenes/menus/storybook/storybook.tscn +++ b/scenes/menus/storybook/storybook.tscn @@ -1,6 +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="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"] @@ -23,7 +24,7 @@ region = Rect2(576, 576, 64, 64) [node name="Storybook" type="CanvasLayer" unique_id=438542807] script = ExtResource("1_gw8hn") -quests = [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) @@ -157,30 +158,6 @@ text = "Back" icon = ExtResource("5_m2ghf") flat = true -[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/CenterContainer/StoryBookContent" unique_id=1654245298] -layout_mode = 0 -offset_left = -158.0 -offset_top = -297.0 -offset_right = 412.0 -offset_bottom = -222.0 - -[node name="TOCBookmark" type="Button" parent="VBoxContainer/CenterContainer/StoryBookContent/HBoxContainer" unique_id=460814141] -unique_name_in_owner = true -layout_mode = 2 -text = "TOC" - -[node name="ENBookmark" type="Button" parent="VBoxContainer/CenterContainer/StoryBookContent/HBoxContainer" unique_id=399694213] -unique_name_in_owner = true -layout_mode = 2 -text = "EN -" - -[node name="ESBookmark" type="Button" parent="VBoxContainer/CenterContainer/StoryBookContent/HBoxContainer" unique_id=278781945] -unique_name_in_owner = true -layout_mode = 2 -text = "ES -" - [node name="MarginContainer" type="MarginContainer" parent="VBoxContainer" unique_id=1971907031] layout_mode = 2 theme_override_constants/margin_right = 8 @@ -248,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"] From fd9e327ea710e2ccd99211d84d5a8c06df845eeb Mon Sep 17 00:00:00 2001 From: Alonna <145865677+alcole2@users.noreply.github.com> Date: Mon, 17 Aug 2026 10:31:01 -0400 Subject: [PATCH 5/5] Use internal filtered array and preserve exported quests - Introduced `_filtered_quests` property to represent the active quest view (TOC or language). - Replaced `quests.duplicate()` calls in initialization and filtering functions with direct assignments and array references. - Updated UI generation (`_populate_quest_lists`, `_create_quest_button`) and page visibility functions to use `_filtered_quests`. --- .../menus/storybook/components/storybook.gd | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/scenes/menus/storybook/components/storybook.gd b/scenes/menus/storybook/components/storybook.gd index 0aa12981d..1d3dc2bdc 100644 --- a/scenes/menus/storybook/components/storybook.gd +++ b/scenes/menus/storybook/components/storybook.gd @@ -28,6 +28,8 @@ 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 @@ -62,7 +64,8 @@ func _ready() -> void: animated_book.animation_finished.connect(_on_animation_finished) # Saving a copy of all quests - _all_quests = quests.duplicate() + _all_quests = quests + _filtered_quests = quests # Connecting the bookmark buttons if toc_bookmark_button: @@ -96,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: @@ -120,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" @@ -154,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): @@ -190,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 @@ -255,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() @@ -313,12 +316,14 @@ func _on_es_bookmark_pressed() -> void: func _show_table_of_contents() -> void: - quests = _all_quests.duplicate() + _filtered_quests = _all_quests _reset_storybook_list_view() func _filter_quests_by_language(lang_code: String) -> void: - quests = _all_quests.filter(func(quest: Quest) -> bool: return quest.language == lang_code) + _filtered_quests = _all_quests.filter( + func(quest: Quest) -> bool: return quest.language == lang_code + ) _reset_storybook_list_view() @@ -351,9 +356,11 @@ func _switch_bookmark_tab(target_tab_index: int, lang_code: String) -> void: # Filter quests array if lang_code == "": - quests = _all_quests.duplicate() + _filtered_quests = _all_quests else: - quests = _all_quests.filter(func(quest: Quest) -> bool: return quest.language == lang_code) + _filtered_quests = _all_quests.filter( + func(quest: Quest) -> bool: return quest.language == lang_code + ) # Reset page counters and reload UI _current_list_page = 0