Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var elders: Array[Elder]

@onready var interact_area: InteractArea = %InteractArea
@onready var talk_behavior: TalkBehavior = %TalkBehavior
@onready var loom_offering_animation_player: AnimationPlayer = %LoomOfferingAnimationPlayer
@onready var loom_offering_animation: LoomOfferingAnimation = %LoomOfferingAnimation


func _find_elder(quest: Quest) -> Elder:
Expand Down Expand Up @@ -90,8 +90,8 @@ func on_offering_succeeded() -> void:
if load_error != OK:
push_error("Failed to start loading %s: %s" % [cutscene_path, error_string(load_error)])

loom_offering_animation_player.play(&"loom_offering")
await loom_offering_animation_player.animation_finished
loom_offering_animation.play_loom_animation()
await loom_offering_animation.animation_finished
GameState.quest.inventory.clear_inventory()

if load_error != OK:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# SPDX-FileCopyrightText: The Threadbare Authors
# SPDX-License-Identifier: MPL-2.0
@tool
class_name LoomOfferingAnimation
extends Node2D

signal animation_finished

const WORLD_IMAGINATION = preload("uid://6bf8rum68wq3")
const WORLD_MEMORY = preload("uid://5wscjc8yqqts")
const WORLD_SPIRIT = preload("uid://cepg1o3ihp055")

## The time in seconds it takes for the animation to finish, determines the speed of threads
@export var animation_time: float = 5.0
## Number of threads in the animation for the in-editor preview
@export var debug_thread_count: int = 6

@export_tool_button("Play") var play_animation: Callable = play_loom_animation_debug

@onready var animation_path: Path2D = %AnimationPath
@onready var loom_offering_sound: AudioStreamPlayer2D = $LoomOfferingSound


func play_loom_animation() -> void:
_loom_animation_play(GameState.quest.inventory.items)


## Only used for the in-editor preview
func play_loom_animation_debug() -> void:
var debug_items: Array[InventoryItem]
# TODO: InventoryItem needs a utility function to obtain all types except NONE.
var item_types := InventoryItem.COLORS_PER_TYPE.keys()
for i in range(debug_thread_count):
var item := InventoryItem.new()
item.type = item_types.pick_random()
debug_items.append(item)
_loom_animation_play(debug_items)


func _loom_animation_play(thread_list: Array[InventoryItem]) -> void:
if thread_list.is_empty():
animation_finished.emit()
return

var separation := 1.0 / thread_list.size()

# Time it takes for all threads to loop
var loop_time := animation_time * 0.7

loom_offering_sound.play()

var counter: int = 0
for thread in thread_list:
var path_follow := PathFollow2D.new()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent! Yes I see you need one PathFollow2D per thread.

path_follow.rotates = false
var sprite := Sprite2D.new()

sprite.texture = thread.get_world_texture()
path_follow.add_child(sprite)

animation_path.add_child(path_follow)

# Starting point for each thread
path_follow.progress_ratio = counter * separation

# Time variation between threads
var time_variation := loop_time / (2.0 * thread_list.size())

var tween := path_follow.create_tween()

# The first thread is the last to end
if counter == 0:
tween.finished.connect(_on_animation_finished)

# Animation Start
tween.tween_property(sprite, "scale", Vector2(0, 0), 0)

tween.tween_property(sprite, "scale", Vector2(1, 1), 0.5)
# Loop around
tween.parallel().tween_property(
path_follow, "progress_ratio", 2.0, loop_time - time_variation * counter

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, so when counter is zero this property is tweened by loop_time seconds. That's why the first thread in the for loop is the one emitting animation_finished.

)

# Animation end
(
tween
. tween_property(sprite, "global_position", animation_path.global_position, 0.25)
. set_ease(Tween.EASE_OUT)
)
tween.parallel().tween_property(sprite, "modulate", Color(0, 0, 0, 0), 0.5)
tween.parallel().tween_property(sprite, "scale", Vector2(3, 3), 0.5)
tween.tween_callback(_thread_free.bind(sprite))
counter += 1


# Remove thread once animation finishes
func _thread_free(thread: Sprite2D) -> void:
thread.queue_free()


func _on_animation_finished() -> void:
animation_finished.emit()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://byu17bpk0v5n7
Loading