From 16c06bf9aff64c6bf57674738d85fd8afd593574 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Tue, 10 Dec 2024 01:25:02 +0200 Subject: [PATCH] Change the frame where the audio plays at --- src/Classes/Frame.gd | 16 +++++++++----- src/Classes/Layers/AudioLayer.gd | 6 +++++- src/UI/Timeline/CelButton.gd | 5 ++++- src/UI/Timeline/LayerButton.gd | 12 ++++++----- src/UI/Timeline/LayerProperties.gd | 18 ++++++++++++++++ src/UI/Timeline/LayerProperties.tscn | 32 ++++++++++++++++++++++------ 6 files changed, 71 insertions(+), 18 deletions(-) diff --git a/src/Classes/Frame.gd b/src/Classes/Frame.gd index 52994988c..21ef3ff9b 100644 --- a/src/Classes/Frame.gd +++ b/src/Classes/Frame.gd @@ -19,9 +19,15 @@ func get_duration_in_seconds(fps: float) -> float: func position_in_seconds(project: Project, start_from := 0) -> float: var pos := 0.0 - for i in range(start_from, project.frames.size()): - var frame := project.frames[i] - if frame == self: - break - pos += frame.get_duration_in_seconds(project.fps) + var index := project.frames.find(self) + if index > start_from: + for i in range(start_from, index): + var frame := project.frames[i] + pos += frame.get_duration_in_seconds(project.fps) + else: + if start_from >= project.frames.size(): + return -1.0 + for i in range(start_from, index, -1): + var frame := project.frames[i] + pos -= frame.get_duration_in_seconds(project.fps) return pos diff --git a/src/Classes/Layers/AudioLayer.gd b/src/Classes/Layers/AudioLayer.gd index 7d872ff60..5f25d848a 100644 --- a/src/Classes/Layers/AudioLayer.gd +++ b/src/Classes/Layers/AudioLayer.gd @@ -7,7 +7,11 @@ var audio: AudioStream: set(value): audio = value audio_changed.emit() -var playback_position := 0.0 ## Measured in seconds. +var playback_position := 0.0: ## Measured in seconds. + get(): + var frame := project.frames[playback_frame] + return frame.position_in_seconds(project) +var playback_frame := 0 func _init(_project: Project, _name := "") -> void: diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index 50e0bcd48..3da27b0d2 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -407,7 +407,10 @@ func _is_playing_audio() -> void: var frame_class := Global.current_project.frames[frame] var layer_class := Global.current_project.layers[layer] as AudioLayer var audio_length := layer_class.audio.get_length() - if frame_class.position_in_seconds(Global.current_project) < audio_length: + var frame_pos := frame_class.position_in_seconds( + Global.current_project, layer_class.playback_frame + ) + if frame_pos >= 0 and frame_pos < audio_length: cel_texture.texture = preload("res://assets/graphics/misc/musical_note.png") else: cel_texture.texture = null diff --git a/src/UI/Timeline/LayerButton.gd b/src/UI/Timeline/LayerButton.gd index 008cb4483..910d8beb8 100644 --- a/src/UI/Timeline/LayerButton.gd +++ b/src/UI/Timeline/LayerButton.gd @@ -67,8 +67,10 @@ func _ready() -> void: func _on_cel_switched() -> void: z_index = 1 if button_pressed else 0 - if not animation_running or Global.current_project.current_frame == 0: - _play_audio() + var layer := Global.current_project.layers[layer_index] + if layer is AudioLayer: + if not animation_running or Global.current_project.current_frame == layer.playback_frame: + _play_audio() func _on_animation_started(_dir: bool) -> void: @@ -85,13 +87,13 @@ func _on_animation_finished() -> void: func _play_audio() -> void: if not is_instance_valid(audio_player): return - var layer := Global.current_project.layers[layer_index] + var layer := Global.current_project.layers[layer_index] as AudioLayer if not layer.visible: return var audio_length := audio_player.stream.get_length() var frame := Global.current_project.frames[Global.current_project.current_frame] - var frame_pos := frame.position_in_seconds(Global.current_project) - if frame_pos < audio_length: + var frame_pos := frame.position_in_seconds(Global.current_project, layer.playback_frame) + if frame_pos >= 0 and frame_pos < audio_length: audio_player.play(frame_pos) else: audio_player.stop() diff --git a/src/UI/Timeline/LayerProperties.gd b/src/UI/Timeline/LayerProperties.gd index fd4dfd229..a62ca34cb 100644 --- a/src/UI/Timeline/LayerProperties.gd +++ b/src/UI/Timeline/LayerProperties.gd @@ -4,9 +4,11 @@ signal layer_property_changed var layer_indices: PackedInt32Array +@onready var grid_container: GridContainer = $GridContainer @onready var name_line_edit := $GridContainer/NameLineEdit as LineEdit @onready var opacity_slider := $GridContainer/OpacitySlider as ValueSlider @onready var blend_modes_button := $GridContainer/BlendModeOptionButton as OptionButton +@onready var play_at_frame_slider := $GridContainer/PlayAtFrameSlider as ValueSlider @onready var user_data_text_edit := $GridContainer/UserDataTextEdit as TextEdit @onready var tileset_option_button := $GridContainer/TilesetOptionButton as OptionButton @@ -23,8 +25,15 @@ func _on_visibility_changed() -> void: opacity_slider.value = first_layer.opacity * 100.0 var blend_mode_index := blend_modes_button.get_item_index(first_layer.blend_mode) blend_modes_button.selected = blend_mode_index + if first_layer is AudioLayer: + play_at_frame_slider.value = first_layer.playback_frame + 1 + play_at_frame_slider.max_value = project.frames.size() user_data_text_edit.text = first_layer.user_data + for child in grid_container.get_children(): + if not child.is_in_group(&"AllLayers"): + child.visible = first_layer is not AudioLayer get_tree().set_group(&"TilemapLayers", "visible", first_layer is LayerTileMap) + get_tree().set_group(&"AudioLayers", "visible", first_layer is AudioLayer) tileset_option_button.clear() if first_layer is LayerTileMap: for i in project.tilesets.size(): @@ -149,3 +158,12 @@ func _on_tileset_option_button_item_selected(index: int) -> void: project.undo_redo.add_undo_method(Global.canvas.draw_layers) project.undo_redo.add_undo_method(func(): Global.cel_switched.emit()) project.undo_redo.commit_action() + + +func _on_play_at_frame_slider_value_changed(value: float) -> void: + if layer_indices.size() == 0: + return + for layer_index in layer_indices: + var layer := Global.current_project.layers[layer_index] + if layer is AudioLayer: + layer.playback_frame = value - 1 diff --git a/src/UI/Timeline/LayerProperties.tscn b/src/UI/Timeline/LayerProperties.tscn index 74ac0b682..27dfe24fe 100644 --- a/src/UI/Timeline/LayerProperties.tscn +++ b/src/UI/Timeline/LayerProperties.tscn @@ -5,22 +5,22 @@ [node name="LayerProperties" type="AcceptDialog"] title = "Layer properties" -size = Vector2i(300, 208) +size = Vector2i(300, 235) script = ExtResource("1_54q1t") [node name="GridContainer" type="GridContainer" parent="."] offset_left = 8.0 offset_top = 8.0 offset_right = 292.0 -offset_bottom = 159.0 +offset_bottom = 186.0 columns = 2 -[node name="NameLabel" type="Label" parent="GridContainer"] +[node name="NameLabel" type="Label" parent="GridContainer" groups=["AllLayers"]] layout_mode = 2 size_flags_horizontal = 3 text = "Name:" -[node name="NameLineEdit" type="LineEdit" parent="GridContainer"] +[node name="NameLineEdit" type="LineEdit" parent="GridContainer" groups=["AllLayers"]] layout_mode = 2 size_flags_horizontal = 3 @@ -52,13 +52,32 @@ layout_mode = 2 size_flags_horizontal = 3 mouse_default_cursor_shape = 2 -[node name="UserDataLabel" type="Label" parent="GridContainer"] +[node name="PlayAtFrameLabel" type="Label" parent="GridContainer" groups=["AudioLayers"]] +layout_mode = 2 +text = "Play at frame:" + +[node name="PlayAtFrameSlider" type="TextureProgressBar" parent="GridContainer" groups=["AudioLayers"]] +layout_mode = 2 +focus_mode = 2 +mouse_default_cursor_shape = 2 +theme_type_variation = &"ValueSlider" +min_value = 1.0 +value = 1.0 +allow_greater = true +nine_patch_stretch = true +stretch_margin_left = 3 +stretch_margin_top = 3 +stretch_margin_right = 3 +stretch_margin_bottom = 3 +script = ExtResource("2_bwpwc") + +[node name="UserDataLabel" type="Label" parent="GridContainer" groups=["AllLayers"]] layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 0 text = "User data:" -[node name="UserDataTextEdit" type="TextEdit" parent="GridContainer"] +[node name="UserDataTextEdit" type="TextEdit" parent="GridContainer" groups=["AllLayers"]] layout_mode = 2 size_flags_horizontal = 3 scroll_fit_content_height = true @@ -77,5 +96,6 @@ mouse_default_cursor_shape = 2 [connection signal="text_changed" from="GridContainer/NameLineEdit" to="." method="_on_name_line_edit_text_changed"] [connection signal="value_changed" from="GridContainer/OpacitySlider" to="." method="_on_opacity_slider_value_changed"] [connection signal="item_selected" from="GridContainer/BlendModeOptionButton" to="." method="_on_blend_mode_option_button_item_selected"] +[connection signal="value_changed" from="GridContainer/PlayAtFrameSlider" to="." method="_on_play_at_frame_slider_value_changed"] [connection signal="text_changed" from="GridContainer/UserDataTextEdit" to="." method="_on_user_data_text_edit_text_changed"] [connection signal="item_selected" from="GridContainer/TilesetOptionButton" to="." method="_on_tileset_option_button_item_selected"]