diff --git a/Controls/Track.tscn b/Controls/Track.tscn index 2eea1e2..a30b0a4 100644 --- a/Controls/Track.tscn +++ b/Controls/Track.tscn @@ -83,12 +83,11 @@ expand_mode = 2 unique_name_in_owner = true custom_minimum_size = Vector2(256, 0) layout_mode = 2 -size_flags_horizontal = 0 +size_flags_horizontal = 3 size_flags_vertical = 4 theme_override_fonts/font = SubResource("FontVariation_lbdn3") placeholder_text = "Empty Track" context_menu_enabled = false -flat = true draw_control_chars = true caret_blink = true script = ExtResource("4_2nwak") diff --git a/Scripts/Timeline.gd b/Scripts/Timeline.gd index bea4239..5a3c7fa 100644 --- a/Scripts/Timeline.gd +++ b/Scripts/Timeline.gd @@ -37,23 +37,6 @@ func format_time_ms_minutes(ms: float) -> String: var milliseconds = fmod(ms, 1000.0) return "%02d:%02d.%03d" % [minutes, seconds, milliseconds] -func _ready(): - await get_tree().process_frame - queue_redraw() - - for c in track_list.get_children(): - if c is Track: - var track = c as Track - track.on_deleted.connect(_track_deleted) - pass - pass - -func _track_deleted(idx: int): - print("track deleted") - await get_tree().process_frame - queue_redraw() - pass - func get_track_idx_by_y(y: float): var idx = 0 for track in track_list.get_children(): @@ -64,6 +47,8 @@ func get_track_idx_by_y(y: float): return -1 func get_track_by_idx(idx: int) -> Control: + if idx > track_list.get_child_count() - 1: + return null return track_list.get_child(idx) func get_pixels_per_unit() -> float: diff --git a/Scripts/Track.gd b/Scripts/Track.gd index d50366f..fd2fa0b 100644 --- a/Scripts/Track.gd +++ b/Scripts/Track.gd @@ -1,15 +1,19 @@ class_name Track extends Button -signal on_deleted +signal on_deleted(idx: int) signal on_renamed signal on_duplicated func _ready(): var menu: PopupMenu = $PopupMenu menu.add_item("Rename", 0) - menu.add_item("Delete", 1) menu.add_item("Duplicate", 2) + menu.add_item("Delete", 1) + + menu.add_separator() + menu.add_item("Properties") + menu.id_pressed.connect(_on_menu_option) func _on_menu_option(id: int): @@ -23,10 +27,7 @@ func _on_menu_option(id: int): pass func delete(): - queue_free() - var idx = get_index() - print(idx) - on_deleted.emit(idx) + on_deleted.emit(get_index()) pass func rename(): diff --git a/Scripts/TrackLineEdit.gd b/Scripts/TrackLineEdit.gd index fdcb6b0..9e43bbe 100644 --- a/Scripts/TrackLineEdit.gd +++ b/Scripts/TrackLineEdit.gd @@ -4,6 +4,11 @@ func _ready() -> void: text_submitted.connect(submit) func submit(text: String): - caret_column = 0 release_focus() + var owner = get_owner() + + if owner is Control: + var c = owner as Control + c.grab_focus() + pass diff --git a/Scripts/TrackView.gd b/Scripts/TrackView.gd new file mode 100644 index 0000000..67acf49 --- /dev/null +++ b/Scripts/TrackView.gd @@ -0,0 +1,44 @@ +extends Control +class_name TrackView + +@export var controller: Node +@export var track_scene: PackedScene +@onready var track_list: VBoxContainer = %TrackList + +signal track_added(idx: int) +signal track_deleted(idx: int) +signal tracks_updated() + +func _ready() -> void: + pass + +func add_track(idx: int): + track_added.emit(idx) + tracks_updated.emit() + pass + +func delete_track(idx: int): + track_deleted.emit(idx) + _track_deleted(idx) + tracks_updated.emit() + pass + +func _track_added(): + var track = track_scene.instantiate() as Track + track.on_deleted.connect(delete_track) + track_list.add_child(track) + pass + +func _track_duplicated(idx: int): + pass + +func _track_renamed(idx: int): + pass + +func _track_deleted(idx: int): + var track = track_list.get_child(idx) + track.call_deferred("free") + pass + +func get_track_elements() -> Array[Node]: + return track_list.get_children() diff --git a/Scripts/TrackView.gd.uid b/Scripts/TrackView.gd.uid new file mode 100644 index 0000000..2413ef9 --- /dev/null +++ b/Scripts/TrackView.gd.uid @@ -0,0 +1 @@ +uid://y5e28thwmx7e diff --git a/Source/Clip.cs b/Source/Clip.cs new file mode 100644 index 0000000..471bfc5 --- /dev/null +++ b/Source/Clip.cs @@ -0,0 +1,9 @@ +using System; + +namespace AudioEditor; + +public class Clip +{ + public TimeSpan StartTime { get; private set; } + public TimeSpan EndTime { get; private set; } +} \ No newline at end of file diff --git a/Source/Clip.cs.uid b/Source/Clip.cs.uid new file mode 100644 index 0000000..932804b --- /dev/null +++ b/Source/Clip.cs.uid @@ -0,0 +1 @@ +uid://b20juoqt3ac8x diff --git a/Source/Project.cs b/Source/Project.cs new file mode 100644 index 0000000..983c458 --- /dev/null +++ b/Source/Project.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; + +namespace AudioEditor; + +public class Project +{ + public int TrackCount => _tracks.Count; + public void AddTrack() + { + var idx = _tracks.Count; + _tracks.Add(new Track(idx, string.Empty)); + } + + public void DuplicateTrack(int idx) + { + if (idx < 0 && idx > _tracks.Count - 1) + { + return; + } + + var track = _tracks[idx]; + var duplicate = track.Duplicate(); + + _tracks.Add(duplicate); + } + + public void RenameTrack(int idx, string name) + { + if (idx < 0 && idx > _tracks.Count - 1) + { + return; + } + } + + public void DeleteTrack(int idx) + { + if (idx < 0 && idx > _tracks.Count - 1) + { + return; + } + + _tracks.RemoveAt(idx); + } + + private List _tracks = new(); +} \ No newline at end of file diff --git a/Source/Project.cs.uid b/Source/Project.cs.uid new file mode 100644 index 0000000..6a20a1a --- /dev/null +++ b/Source/Project.cs.uid @@ -0,0 +1 @@ +uid://bvgn3tf07jspe diff --git a/Source/ProjectController.cs b/Source/ProjectController.cs index 16870ae..b755626 100644 --- a/Source/ProjectController.cs +++ b/Source/ProjectController.cs @@ -7,6 +7,9 @@ namespace AudioEditor; public partial class ProjectController : Node { [Signal] public delegate void AudioClipDroppedEventHandler(Vector2 atPosition, string path, string clipName, double startTime, double endTime); + [Signal] public delegate void OnTrackAddedEventHandler(int idx); + [Signal] public delegate void OnTrackRenamedEventHandler(int idx, string name); + [Signal] public delegate void OnTrackDuplicatedEventHandler(int idx); [Signal] public delegate void OnTrackDeletedEventHandler(int trackIdx); public override void _Ready() @@ -14,9 +17,28 @@ public partial class ProjectController : Node GetWindow().FilesDropped += FilesDropped; } - public void DeleteTrack(int trackIdx) + public void AddTrack(int idx = 0) { + _project.AddTrack(); + EmitSignal(SignalName.OnTrackAdded, _project.TrackCount - 1); + } + public void DuplicateTrack(int idx) + { + _project.DuplicateTrack(idx); + EmitSignal(SignalName.OnTrackDuplicated, idx); + } + + public void RenameTrack(int idx, string name) + { + _project.RenameTrack(idx, name); + EmitSignal(SignalName.OnTrackRenamed, idx, name); + } + + public void DeleteTrack(int idx) + { + _project.DeleteTrack(idx); + EmitSignal(SignalName.OnTrackDeleted, idx); } public void CreateAudioClipPreview(Control audioClip) @@ -54,4 +76,6 @@ public partial class ProjectController : Node EmitSignal(SignalName.AudioClipDropped, mousePosition, path, fileName, 0, waveformInfo.Length.TotalMilliseconds); } + + private Project _project = new(); } \ No newline at end of file diff --git a/Source/Track.cs b/Source/Track.cs new file mode 100644 index 0000000..2d71658 --- /dev/null +++ b/Source/Track.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; + +namespace AudioEditor; + +public class Track +{ + public int Idx { get; private set; } + public string Name { get; private set; } + + public Track(int idx, string name) + { + Idx = idx; + Name = name; + } + + public Track(int idx, string name, IEnumerable clips) + { + Idx = idx; + Name = name; + _clips = clips.ToList(); + } + + public bool TryAddClip(Clip clip) + { + _clips.Add(clip); + return false; + } + + public Track Duplicate() => new(Idx, Name, _clips); + + private List _clips = new(); +} \ No newline at end of file diff --git a/Source/Track.cs.uid b/Source/Track.cs.uid new file mode 100644 index 0000000..506134a --- /dev/null +++ b/Source/Track.cs.uid @@ -0,0 +1 @@ +uid://dtk58stvxxdyl diff --git a/Views/MainView.tscn b/Views/MainView.tscn index 08cbeb2..68e16e3 100644 --- a/Views/MainView.tscn +++ b/Views/MainView.tscn @@ -188,5 +188,8 @@ mouse_filter = 2 [node name="ProjectController" type="Node" parent="."] script = ExtResource("11_gc3ui") +[connection signal="track_added" from="VBoxContainer/VSplitContainer/HSplitContainer/LeftDock/Tracks" to="ProjectController" method="AddTrack"] +[connection signal="tracks_updated" from="VBoxContainer/VSplitContainer/HSplitContainer/LeftDock/Tracks" to="VBoxContainer/VSplitContainer/HSplitContainer/Timeline" method="queue_redraw"] [connection signal="clip_added" from="VBoxContainer/VSplitContainer/HSplitContainer/Timeline" to="ProjectController" method="CreateAudioClipPreview"] [connection signal="AudioClipDropped" from="ProjectController" to="VBoxContainer/VSplitContainer/HSplitContainer/Timeline" method="clip_dropped"] +[connection signal="OnTrackAdded" from="ProjectController" to="VBoxContainer/VSplitContainer/HSplitContainer/LeftDock/Tracks" method="_track_added" unbinds=1] diff --git a/Views/TrackView.tscn b/Views/TrackView.tscn index acbb93b..2ed1c52 100644 --- a/Views/TrackView.tscn +++ b/Views/TrackView.tscn @@ -1,18 +1,20 @@ -[gd_scene load_steps=3 format=3 uid="uid://bpd6g2b3s7tqa"] +[gd_scene load_steps=4 format=3 uid="uid://bpd6g2b3s7tqa"] +[ext_resource type="Script" uid="uid://y5e28thwmx7e" path="res://Scripts/TrackView.gd" id="1_8piyd"] [ext_resource type="PackedScene" uid="uid://c3kajrpp2ux7" path="res://Controls/Track.tscn" id="1_qr47w"] [ext_resource type="Texture2D" uid="uid://b3mydiolrvqlr" path="res://Assets/Icons/add.svg" id="2_rekuu"] -[node name="Tracks" type="Control"] -clip_children = 1 -custom_minimum_size = Vector2(200, 0) +[node name="TrackView" type="Control"] +clip_children = 2 +custom_minimum_size = Vector2(264, 0) layout_mode = 3 anchors_preset = 9 anchor_bottom = 1.0 grow_vertical = 2 +script = ExtResource("1_8piyd") +track_scene = ExtResource("1_qr47w") [node name="VBoxContainer" type="VBoxContainer" parent="."] -custom_minimum_size = Vector2(128, 0) layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 @@ -22,27 +24,15 @@ grow_vertical = 2 mouse_filter = 2 [node name="TrackList" type="VBoxContainer" parent="VBoxContainer"] -custom_minimum_size = Vector2(128, 0) +unique_name_in_owner = true +clip_children = 1 layout_mode = 2 size_flags_vertical = 3 mouse_filter = 2 -[node name="Track" parent="VBoxContainer/TrackList" instance=ExtResource("1_qr47w")] -layout_mode = 2 - -[node name="Track2" parent="VBoxContainer/TrackList" instance=ExtResource("1_qr47w")] -layout_mode = 2 - -[node name="Track3" parent="VBoxContainer/TrackList" instance=ExtResource("1_qr47w")] -layout_mode = 2 - -[node name="AddTrack" type="MenuButton" parent="VBoxContainer"] +[node name="AddTrack" type="Button" parent="VBoxContainer"] layout_mode = 2 icon = ExtResource("2_rekuu") -flat = false icon_alignment = 1 -item_count = 2 -popup/item_0/text = "Audio Track" -popup/item_0/id = 0 -popup/item_1/text = "Label Track" -popup/item_1/id = 1 + +[connection signal="pressed" from="VBoxContainer/AddTrack" to="." method="add_track" binds= [-1]]