Files
Kalulu/sources/gardens/gardens.gd
T
2025-09-05 15:55:48 +02:00

729 lines
29 KiB
GDScript

class_name Gardens
extends Control
signal minigame_layout_opened()
const KALULU := preload("res://sources/minigames/base/kalulu.gd")
const GARDEN_SCENE: PackedScene = preload("res://resources/gardens/garden.tscn")
const LOOK_AND_LEARN_SCENE: PackedScene = preload("res://sources/look_and_learn/look_and_learn.tscn")
const FLOWER_FVX: PackedScene = preload("res://sources/gardens/flower_particle.tscn")
const GARDEN_SIZE: int = 2400
static var transition_data: Dictionary = {}
@export_category("Layout")
@export var gardens_layout: GardensLayout:
set = set_gardens_layout
@export var starting_garden: int = -1
@export_category("Colors")
@export var unlocked_color: Color = Color("1c2662") #blue
@export var locked_color: Color = Color("1d2229") #black
@export_group("Minigames")
@export var minigames_scenes: Array[PackedScene] = []
@export var minigames_icons: Array[Texture] = []
var lessons: Dictionary = {}
var points: Array[Array] = []
var is_scrolling: bool = false
var scroll_beginning_garden: int = 0
var scroll_tween: Tween
var is_locked: bool = false
var in_minigame_selection: bool = false
var current_lesson_number: int = -1
var current_garden: Garden
var current_button_global_position: Vector2 = Vector2.ZERO
var current_button: LessonButton
@onready var garden_parent: HBoxContainer = %GardenParent
@onready var locked_line: Line2D = $ScrollContainer/LockedLine
@onready var unlocked_line: Line2D = $ScrollContainer/UnlockedLine
@onready var line_particles: GPUParticles2D = %LineParticles
@onready var line_audio_stream_player: AudioStreamPlayer2D = %LineAudioStreamPlayer
@onready var scroll_container: ScrollContainer = $ScrollContainer
@onready var parallax_background: ParallaxBackground = %ParallaxBackground
@onready var minigame_selection: Control = %MinigameSelection
@onready var lesson_button: LessonButton = %LessonButton
@onready var lesson_button_particles: GPUParticles2D = %LessonButtonParticles
@onready var back_button: TextureButton = %BackButton
@onready var right_audio_stream_player: AudioStreamPlayer = $RightAudioStreamPlayer
@onready var left_audio_stream_player: AudioStreamPlayer = $LeftAudioStreamPlayer
@onready var feedback_audio_stream_player: AudioStreamPlayer = $FeedBackAudioStreamPlayer
@onready var feedback_audio_stream_player2: AudioStreamPlayer = $FeedBackAudioStreamPlayer2
@onready var minigame_layout_1: MinigameLayout = %MinigameBackground1
@onready var minigame_layout_2: MinigameLayout = %MinigameBackground2
@onready var minigame_layout_3: MinigameLayout = %MinigameBackground3
@onready var minigame_background: TextureRect = %MinigameBackground
@onready var minigame_background_center: TextureRect = %MinigameBackgroundCenter
@onready var lock: Control = %Lock
@onready var kalulu: KALULU = %Kalulu
@onready var kalulu_button: CanvasItem = %KaluluButton
@onready var intro_speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path("gardens_screen", "intro"))
@onready var help_few_plants_speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path("gardens_screen", "help_few_plants"))
@onready var help_many_plants_speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path("gardens_screen", "help_many_plants"))
func _ready() -> void:
# Gets the lessons of the current language pack
Database.db.query("SELECT Grapheme, Phoneme, LessonNb, GPID FROM Lessons
INNER JOIN GPsInLessons ON GPsInLessons.LessonID = Lessons.ID
INNER JOIN GPs ON GPsInLessons.GPID = GPs.ID
ORDER BY LessonNb")
for element: Dictionary in Database.db.query_result:
if not lessons.has(element.LessonNb):
lessons[element.LessonNb] = []
var lesson_array: Array = lessons[element.LessonNb]
lesson_array.append({grapheme = element.Grapheme, phoneme = element.Phoneme, gp_id = element.GPID})
# Loads the layout
if not gardens_layout:
gardens_layout = load("res://resources/gardens/gardens_layout.tres")
else:
set_gardens_layout(gardens_layout)
# Setups the lessons
_set_up_lessons()
# If there is no data, skips the rest
if not UserDataManager.student_progression:
await OpeningCurtain.open()
return
await get_tree().process_frame
_lock()
# Transition variables #
# The maximum unlocked lesson by the player
var max_unlocked_lesson: int = UserDataManager.student_progression.get_max_unlocked_lesson_index() + 1
# Defines if the last played minigame or lookandlearn is of the last available lesson
var is_current_lesson: bool = transition_data and transition_data.current_lesson_number == max_unlocked_lesson
# Defines if a look and learn was just completed
var is_look_and_learn_completed: bool = transition_data.has("look_and_learn_completed") and transition_data.look_and_learn_completed
# Defines if a minigame was just completed
var is_minigame_completed: bool = transition_data.has("minigame_completed") and transition_data.minigame_completed
# Defines if the minigame or lookandlearn cleared is for the first time
var is_first_clear: bool = transition_data and transition_data.has("first_clear") and transition_data.first_clear
# Defines if a new lesson has been unlocked by the player, setups to play the right animation
var new_lesson_unlocked: bool = transition_data and transition_data.current_lesson_number == UserDataManager.student_progression.get_max_unlocked_lesson_index() and transition_data.has("minigame_completed") and transition_data.minigame_completed and UserDataManager.student_progression.is_lesson_completed(transition_data.current_lesson_number as int)
#region Progression
# Loads the progression of the player without the newly unlocked stuff from the transition data
var lesson_ind: int = 1
# Go through each garden
for garden_control: Garden in garden_parent.get_children():
# Handles the lesson buttons and calculate the progression of the garden
for index: int in range(garden_control.lesson_button_controls.size()):
var button: LessonButton = garden_control.lesson_button_controls[index]
if not lesson_ind in lessons:
button.disabled = true
continue
# Adds the max progression of the look and learn
garden_control.max_progression += 2.0
if UserDataManager.student_progression.unlocks[lesson_ind]["look_and_learn"] >= StudentProgression.Status.Unlocked:
match UserDataManager.student_progression.unlocks[lesson_ind]["look_and_learn"]:
StudentProgression.Status.Unlocked:
garden_control.current_progression += 1.0
StudentProgression.Status.Completed:
garden_control.current_progression += 2.0
button.disabled = false
else:
button.disabled = true
# If we just unlocked the new lesson, leave the button disabled
if new_lesson_unlocked and lesson_ind == max_unlocked_lesson:
button.disabled = true
# Remove the completion if the look and learn was just completed for the first time
if is_look_and_learn_completed and is_first_clear:
garden_control.current_progression -= 1
if not(new_lesson_unlocked and lesson_ind == max_unlocked_lesson - 1):
button.completed = UserDataManager.student_progression.is_lesson_completed(lesson_ind)
# Handles progression of the minigames
for game_index: int in range(3):
garden_control.max_progression += 2.0
match UserDataManager.student_progression.unlocks[lesson_ind]["games"][game_index]:
StudentProgression.Status.Unlocked:
garden_control.current_progression += 1.0
StudentProgression.Status.Completed:
garden_control.current_progression += 2.0
# Remove the completion if the minigame was just completed for the first time
if lesson_ind == max_unlocked_lesson and is_first_clear and is_minigame_completed and transition_data.has("minigame_number") and transition_data.minigame_number == game_index:
garden_control.current_progression -= 1
lesson_ind += 1
# Handles the flowers
var total_flowers: float = garden_control.get_progress_ratio() * garden_control.flower_controls.size() * 3.0
var flower_ind: int = 0
while total_flowers > 0 and flower_ind < garden_control.flower_controls.size():
if total_flowers >= 3.0:
garden_control.flowers_sizes[flower_ind] = Garden.FlowerSizes.LARGE
total_flowers -= 3.0
elif total_flowers >= 2.0:
garden_control.flowers_sizes[flower_ind] = Garden.FlowerSizes.MEDIUM
total_flowers -= 2.0
elif total_flowers >= 1.0:
garden_control.flowers_sizes[flower_ind] = Garden.FlowerSizes.SMALL
total_flowers -= 1.0
flower_ind += 1
garden_control.update_flowers()
# Handles the path
var curve: Curve2D = Curve2D.new()
var max_lesson: int = UserDataManager.student_progression.get_max_unlocked_lesson_index()
if not new_lesson_unlocked:
max_lesson += 1
for index: int in range(max_lesson):
curve.add_point(points[index][0] as Vector2, points[index][1] as Vector2, points[index][2] as Vector2)
unlocked_line.points = curve.get_baked_points()
line_particles.global_position = unlocked_line.points[unlocked_line.points.size()-1]
#endregion
#region Scroll
# Scrolls to the right garden
if not transition_data:
if starting_garden == -1:
lesson_ind = 1
for garden_ind: int in range(garden_parent.get_child_count()):
var garden_control: Garden = garden_parent.get_child(garden_ind)
if starting_garden != -1:
break
if not lesson_ind in lessons:
break
for index: int in range(garden_control.lesson_button_controls.size()):
if not lesson_ind in lessons:
break
if UserDataManager.student_progression:
var unlock: Dictionary = UserDataManager.student_progression.unlocks[lesson_ind]
var look_and_learn_unlocked: bool = unlock["look_and_learn"] == StudentProgression.Status.Unlocked
var exercise_unlock_1: bool = unlock["games"][0] == StudentProgression.Status.Unlocked
var exercise_unlock_2: bool = unlock["games"][1] == StudentProgression.Status.Unlocked
var exercise_unlock_3: bool = unlock["games"][2] == StudentProgression.Status.Unlocked
if look_and_learn_unlocked or exercise_unlock_1 or exercise_unlock_2 or exercise_unlock_3:
starting_garden = garden_ind
break
else:
if transition_data.has("current_garden_index"):
starting_garden = transition_data.current_garden_index
else:
Logger.error("Gardens: initialisation: transition_data exists but does not contains the needed current_garden_index")
starting_garden = 0
scroll_container.scroll_horizontal = GARDEN_SIZE * starting_garden
scroll_beginning_garden = int(float(scroll_container.scroll_horizontal) / GARDEN_SIZE)
current_garden = garden_parent.get_child(starting_garden)
#endregion
await OpeningCurtain.open()
MusicManager.play(MusicManager.Track.Garden)
# Handles all the animation played when entering the gardens
if transition_data:
# Wait for the next frame to avoid glittering
await get_tree().process_frame
#region Flowers animation
# Play the flowers animation if needed
if is_current_lesson and is_first_clear:
# Wait a bit before any action to smooth the animations
await get_tree().create_timer(1).timeout
# Calculate the progression of the garden
current_garden.current_progression += 1
var unlocks_ratio: float = current_garden.current_progression / current_garden.max_progression
var total_flowers: float = unlocks_ratio * current_garden.flower_controls.size() * 3.0
var flower_ind: int = 0
while total_flowers > 0 and flower_ind < current_garden.flower_controls.size():
var play_animation: bool = false
if total_flowers >= 3.0 and current_garden.flowers_sizes[flower_ind] != Garden.FlowerSizes.LARGE:
current_garden.flowers_sizes[flower_ind] = Garden.FlowerSizes.LARGE
total_flowers -= 3.0
play_animation = true
elif total_flowers >= 2.0 and current_garden.flowers_sizes[flower_ind] != Garden.FlowerSizes.MEDIUM:
current_garden.flowers_sizes[flower_ind] = Garden.FlowerSizes.MEDIUM
total_flowers -= 2.0
play_animation = true
elif total_flowers >= 1.0 and current_garden.flowers_sizes[flower_ind] != Garden.FlowerSizes.SMALL:
current_garden.flowers_sizes[flower_ind] = Garden.FlowerSizes.SMALL
total_flowers -= 1.0
play_animation = true
if play_animation:
var fvfx: FlowerVFX = FLOWER_FVX.instantiate()
current_garden.flower_controls[flower_ind].add_child(fvfx)
fvfx.anchor_bottom = 0.5
fvfx.anchor_top = 0.5
fvfx.anchor_left = 0.5
fvfx.anchor_right = 0.5
fvfx.play()
await get_tree().create_timer(0.5).timeout
current_garden.update_flowers()
flower_ind += 1
#endregion
# Wait a bit before any action to smooth the animations
await get_tree().create_timer(1).timeout
# Re-open the minigames layout
await _open_minigames_layout(_get_current_lesson_button(transition_data.current_lesson_number as int), transition_data.current_lesson_number as int)
#region New lesson unlocked
if new_lesson_unlocked:
# Close the layout
await get_tree().create_timer(2).timeout
await _close_minigames_layout()
# Path towards the next lesson
lesson_ind = 1
var last_lesson_button: LessonButton
var new_lesson_button: LessonButton
var is_last_lesson_of_garden: bool = false
for garden_control: Garden in garden_parent.get_children():
for index: int in range(garden_control.lesson_button_controls.size()):
if lesson_ind == max_lesson + 1:
new_lesson_button = garden_control.lesson_button_controls[index]
if lesson_ind == max_lesson:
last_lesson_button = garden_control.lesson_button_controls[index]
if index == garden_control.lesson_button_controls.size() -1:
is_last_lesson_of_garden = true
if last_lesson_button and new_lesson_button:
break
lesson_ind += 1
if last_lesson_button and new_lesson_button:
break
# Play an animation on the completed lesson
if last_lesson_button:
last_lesson_button.completed = true
await last_lesson_button.right()
# Fill in the path towards the next lesson
var animation_curve: Curve2D = Curve2D.new()
for index: int in range(max_lesson-1, max_lesson + 1):
animation_curve.add_point(points[index][0] as Vector2, points[index][1] as Vector2, points[index][2] as Vector2)
# Check if we need to scroll to the next garden
if is_last_lesson_of_garden:
scroll_beginning_garden = int(float(scroll_container.scroll_horizontal) / GARDEN_SIZE)
var target_scroll: int = scroll_beginning_garden * GARDEN_SIZE + GARDEN_SIZE
var tween: Tween = create_tween()
tween.set_ease(Tween.EASE_IN_OUT)
tween.tween_property(scroll_container, "scroll_horizontal", target_scroll, 4)
scroll_beginning_garden = int(float(target_scroll) / GARDEN_SIZE)
current_garden = garden_parent.get_child(scroll_beginning_garden)
line_audio_stream_player.pitch_scale = 0.95
var baked_points: PackedVector2Array = animation_curve.get_baked_points()
for point: Vector2 in baked_points:
if not line_audio_stream_player.playing:
line_audio_stream_player.pitch_scale += 0.05
line_audio_stream_player.play()
unlocked_line.add_point(point)
line_particles.position = point
await get_tree().create_timer(0.01).timeout
# Enable the next lesson button
if new_lesson_button:
new_lesson_button.disabled = false
#endregion
# Unlock the interface
_unlock()
# Empty the transition data
transition_data = {}
# Play the tutorial if needed
if not UserDataManager.is_speech_played("gardens"):
kalulu_button.hide()
await kalulu.play_kalulu_speech(intro_speech)
kalulu_button.show()
UserDataManager.mark_speech_as_played("gardens")
static func compute_lessons_distribution(total_lessons: int, garden_layouts: Array[GardenLayout]) -> Array[int]:
Logger.trace("Gardens: compute_lessons_distribution: total_lessons = %s, garden_layouts count = %s" % [str(total_lessons), str(garden_layouts.size())])
var distribution: Array[int] = []
var lessons_left: int = total_lessons
var gardens_left: int = garden_layouts.size()
for layout_index: int in range(garden_layouts.size()):
var max_lessons: int = garden_layouts[layout_index].lesson_buttons.size()
var lessons_for_garden: int = 0
if gardens_left > 0:
lessons_for_garden = int(ceili(float(lessons_left) / float(gardens_left)))
lessons_for_garden = min(lessons_for_garden, max_lessons)
if lessons_for_garden > lessons_left:
lessons_for_garden = lessons_left
distribution.append(lessons_for_garden)
lessons_left -= lessons_for_garden
gardens_left -= 1
return distribution
func _process(_delta: float) -> void:
locked_line.position.x = - scroll_container.scroll_horizontal
unlocked_line.position.x = - scroll_container.scroll_horizontal
parallax_background.scroll_offset.x = - scroll_container.scroll_horizontal
func _open_minigames_layout(button: LessonButton, lesson_ind: int) -> void:
if in_minigame_selection or not UserDataManager.student_progression:
return
feedback_audio_stream_player2.pitch_scale = 1.1
feedback_audio_stream_player2.play()
in_minigame_selection = true
# Gets the correct exercises for the lesson
var exercises: Array[int] = Database.get_exercise_for_lesson(lesson_ind)
if not exercises or exercises.size() < 3:
return
# Sets the variables for the current garden and lesson
current_lesson_number = lesson_ind
if button:
#button_global_position = button.global_position
current_button = button
current_button.show_placeholder(true)
current_button_global_position = button.global_position
# Gets the current lesson unlocks
var lesson_unlocks: Dictionary = UserDataManager.student_progression.unlocks[current_lesson_number]
var are_minigames_locked: bool = lesson_unlocks["games"][0] == StudentProgression.Status.Locked and lesson_unlocks["games"][1] == StudentProgression.Status.Locked and lesson_unlocks["games"][2] == StudentProgression.Status.Locked
# Deactivate the mouse filters on the buttons behind the layout
for l_button: LessonButton in current_garden.lesson_button_controls:
l_button.mouse_filter = Control.MOUSE_FILTER_IGNORE
# Background
if are_minigames_locked:
minigame_background_center.modulate = locked_color
else:
minigame_background_center.modulate = current_garden.color
# Lesson button
_handle_lesson_button(current_lesson_number, lesson_unlocks["look_and_learn"] as StudentProgression.Status, current_garden.color)
# Minigames
_fill_minigame_choice(minigame_layout_1, exercises[0], lesson_unlocks["games"][0] as StudentProgression.Status, 0)
_fill_minigame_choice(minigame_layout_2, exercises[1], lesson_unlocks["games"][1] as StudentProgression.Status, 1)
_fill_minigame_choice(minigame_layout_3, exercises[2], lesson_unlocks["games"][2] as StudentProgression.Status, 2)
# Animations
minigame_selection.visible = true
back_button.visible = false
kalulu_button.visible = false
line_particles.visible = false
minigame_background.size = 300.0 * Vector2.ONE
minigame_background.global_position = current_button_global_position
minigame_background.visible = true
minigame_background_center.size = 300.0 * Vector2.ONE
minigame_background_center.global_position = current_button_global_position
minigame_background_center.visible = true
var tween: Tween = create_tween().set_parallel(true).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
tween.tween_property(minigame_background_center, "scale", (1800.0 / 300.0) * Vector2.ONE, 0.25)
tween.tween_property(minigame_background_center, "global_position", Vector2(380.0, 0), 0.25)
tween.tween_property(minigame_background, "scale", (1800.0 / 300.0) * Vector2.ONE, 0.25)
tween.tween_property(minigame_background, "global_position", Vector2(380.0, 0), 0.25)
tween.chain().tween_property(minigame_selection, "modulate:a", 1.0, 0.25)
await tween.finished
minigame_layout_opened.emit()
func _handle_lesson_button(lesson: int, status: StudentProgression.Status, color: Color) -> void:
lesson_button.text = lessons[lesson][0].grapheme
lesson_button.completed_color = color
lesson_button.disabled = status == StudentProgression.Status.Locked
lesson_button.completed = status == StudentProgression.Status.Completed
lesson_button_particles.emitting = status == StudentProgression.Status.Unlocked
if status == StudentProgression.Status.Completed:
if transition_data and transition_data.has("look_and_learn_completed") and transition_data.look_and_learn_completed:
await minigame_layout_opened
lesson_button.right()
func _fill_minigame_choice(layout: MinigameLayout, exercise_type: int, status: StudentProgression.Status, minigame_number: int) -> void:
layout.icon.texture = minigames_icons[exercise_type-1]
layout.is_disabled = status == StudentProgression.Status.Locked
if status == StudentProgression.Status.Completed:
if transition_data and transition_data.has("minigame_completed") and transition_data.minigame_completed and transition_data.has("minigame_number") and transition_data.minigame_number == minigame_number and transition_data.has("first_clear") and transition_data.first_clear:
layout.self_modulate = unlocked_color
await minigame_layout_opened
create_tween().tween_property(layout, "self_modulate:a", 0, 0.5)
layout.right()
else:
layout.self_modulate.a = 0
elif status == StudentProgression.Status.Locked:
layout.self_modulate = locked_color
else:
layout.self_modulate = unlocked_color
layout.pressed.connect(_on_minigame_button_pressed.bind(minigames_scenes[exercise_type-1], minigame_number))
func _close_minigames_layout() -> void:
if not in_minigame_selection:
return
in_minigame_selection = false
feedback_audio_stream_player2.pitch_scale = 0.75
feedback_audio_stream_player2.play()
var tween: Tween = create_tween().set_parallel(true).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
tween.tween_property(minigame_selection, "modulate:a", 0.0, 0.25)
var other_tween: Tween = tween.chain()
other_tween.tween_property(minigame_background_center, "scale", Vector2.ONE, 0.25)
other_tween.tween_property(minigame_background_center, "global_position", current_button_global_position, 0.25)
other_tween.tween_property(minigame_background, "scale", Vector2.ONE, 0.25)
other_tween.tween_property(minigame_background, "global_position", current_button_global_position, 0.25)
await tween.finished
if current_button:
current_button.show_placeholder(false)
minigame_selection.visible = false
minigame_background.visible = false
minigame_background_center.visible = false
back_button.visible = true
kalulu_button.visible = true
line_particles.visible = true
for button: LessonButton in current_garden.lesson_button_controls:
button.mouse_filter = Control.MOUSE_FILTER_STOP
minigame_layout_1.pressed.disconnect(_on_minigame_button_pressed)
minigame_layout_2.pressed.disconnect(_on_minigame_button_pressed)
minigame_layout_3.pressed.disconnect(_on_minigame_button_pressed)
func _set_up_lessons() -> void:
var lesson_ind: int = 1
for garden_ind: int in range(garden_parent.get_child_count()):
var garden_control: Garden = garden_parent.get_child(garden_ind)
var button_count: int = garden_control.garden_layout.lesson_buttons.size()
for index: int in range(button_count):
if not lesson_ind in lessons:
break
garden_control.set_lesson_label(index, lessons[lesson_ind][0].grapheme as String)
garden_control.lesson_button_controls[index].pressed.connect(_on_garden_lesson_button_pressed.bind(garden_control.lesson_button_controls[index], lesson_ind))
lesson_ind += 1
func set_gardens_layout(p_gardens_layout: GardensLayout) -> void:
gardens_layout = p_gardens_layout
add_gardens()
if garden_parent:
await get_tree().process_frame
set_up_path()
func add_gardens() -> void:
if not garden_parent:
return
# Removes old gardens
for child: Node in garden_parent.get_children():
child.free()
var distribution: Array[int] = compute_lessons_distribution(lessons.size(), gardens_layout.gardens)
var garden_index: int = 0
for layout_index: int in range(gardens_layout.gardens.size()):
var garden_layout: GardenLayout = gardens_layout.gardens[layout_index]
var garden: Garden = GARDEN_SCENE.instantiate()
garden_parent.add_child(garden)
garden.garden_index = garden_index
garden_index += 1
var lessons_for_garden: int = distribution[layout_index]
garden_layout.lesson_buttons.resize(lessons_for_garden)
garden.garden_layout = garden_layout
func set_up_path() -> void:
if not garden_parent:
return
points = []
var curve: Curve2D = Curve2D.new()
for index: int in range(gardens_layout.gardens.size()):
if index >= garden_parent.get_child_count():
break
var garden_layout: GardenLayout = gardens_layout.gardens[index]
var garden_control: Garden = garden_parent.get_child(index)
for button: GardenLayout.GardenLayoutLessonButton in garden_layout.lesson_buttons:
var point_position: Vector2 = garden_parent.position + garden_control.position + Vector2(button.position)
point_position += garden_control.get_button_size() / 2
var point_in_position: Vector2 = Vector2.ZERO
if curve.point_count > 1:
point_in_position = curve.get_point_position(curve.point_count - 1) + curve.get_point_out(curve.point_count - 1) - point_position
curve.add_point(point_position, point_in_position, button.path_out_position)
points.append([point_position, point_in_position, button.path_out_position])
locked_line.points = curve.get_baked_points()
func _lock() -> void:
is_locked = true
lock.visible = true
func _unlock() -> void:
is_locked = false
lock.visible = false
func _get_current_lesson_button(lesson: int) -> LessonButton:
var lesson_ind: int = 1
for garden_control: Garden in garden_parent.get_children():
for index: int in range(garden_control.lesson_button_controls.size()):
if lesson_ind == lesson:
return garden_control.lesson_button_controls[index]
lesson_ind += 1
return null
func _on_garden_lesson_button_pressed(button: LessonButton, lesson_ind: int) -> void:
_open_minigames_layout(button, lesson_ind)
func _on_lesson_button_pressed() -> void:
if is_locked:
return
feedback_audio_stream_player.play()
await OpeningCurtain.close()
LookAndLearn.transition_data = {
current_button_global_position = current_button_global_position,
current_lesson_number = current_lesson_number,
current_garden_index = current_garden.garden_index,
look_and_learn_completed = false
}
get_tree().change_scene_to_packed(LOOK_AND_LEARN_SCENE)
func _on_minigame_button_pressed(minigame_scene: PackedScene, minigame_number: int) -> void:
if is_locked:
return
feedback_audio_stream_player.play()
await OpeningCurtain.close()
Minigame.transition_data = {
current_button_global_position = current_button_global_position,
current_lesson_number = current_lesson_number,
current_garden_index = current_garden.garden_index,
minigame_number = minigame_number,
minigame_completed = false
}
get_tree().change_scene_to_packed(minigame_scene)
func _on_scroll_container_gui_input(event: InputEvent) -> void:
if in_minigame_selection:
return
if event.is_action_pressed("left_click"):
is_scrolling = true
scroll_beginning_garden = int(float(scroll_container.scroll_horizontal) / GARDEN_SIZE)
if scroll_tween:
scroll_tween.stop()
scroll_tween = null
elif event.is_action_released("left_click"):
is_scrolling = false
var shift_value: int = scroll_container.scroll_horizontal - scroll_beginning_garden * GARDEN_SIZE
var target_scroll: int = scroll_beginning_garden * GARDEN_SIZE
var is_garden_changed: bool = false
if shift_value < - 400:
target_scroll -= GARDEN_SIZE
is_garden_changed = true
left_audio_stream_player.play()
elif shift_value > 400:
target_scroll += GARDEN_SIZE
is_garden_changed = true
right_audio_stream_player.play()
scroll_tween = create_tween()
scroll_tween.set_ease(Tween.EASE_OUT)
scroll_tween.set_trans(Tween.TRANS_SPRING)
scroll_tween.tween_property(scroll_container, "scroll_horizontal", target_scroll, 1)
if is_garden_changed:
current_garden = garden_parent.get_child(int(float(target_scroll) / GARDEN_SIZE))
current_garden.pop_animation()
await scroll_tween.finished
scroll_beginning_garden = int(float(scroll_container.scroll_horizontal) / GARDEN_SIZE)
if is_scrolling and event is InputEventMouseMotion:
var motion_event: InputEventMouseMotion = event
scroll_container.scroll_horizontal -= int(motion_event.relative.x)
func _on_back_button_pressed() -> void:
await OpeningCurtain.close()
get_tree().change_scene_to_file("res://sources/menus/brain/brain.tscn")
func _on_area_2d_input_event(_viewport: Node, event: InputEvent, _shape_idx: int) -> void:
if is_locked:
return
if event.is_action_pressed("left_click") and in_minigame_selection:
_close_minigames_layout()
func _on_kalulu_button_pressed() -> void:
kalulu_button.hide()
if current_garden.get_progress_ratio() > 0.75:
await kalulu.play_kalulu_speech(help_many_plants_speech)
else:
await kalulu.play_kalulu_speech(help_few_plants_speech)
kalulu_button.show()