summaryrefslogtreecommitdiff
path: root/rust/crates/commands/src/timeline/track
diff options
context:
space:
mode:
Diffstat (limited to 'rust/crates/commands/src/timeline/track')
-rw-r--r--rust/crates/commands/src/timeline/track/add_track.rs69
-rw-r--r--rust/crates/commands/src/timeline/track/mod.rs9
-rw-r--r--rust/crates/commands/src/timeline/track/remove_track.rs43
-rw-r--r--rust/crates/commands/src/timeline/track/toggle_track_mute.rs49
-rw-r--r--rust/crates/commands/src/timeline/track/toggle_track_visibility.rs54
5 files changed, 224 insertions, 0 deletions
diff --git a/rust/crates/commands/src/timeline/track/add_track.rs b/rust/crates/commands/src/timeline/track/add_track.rs
new file mode 100644
index 00000000..d6e9bbae
--- /dev/null
+++ b/rust/crates/commands/src/timeline/track/add_track.rs
@@ -0,0 +1,69 @@
+use scene::{Project, SceneTracks};
+use timeline::placement::{build_empty_track, get_default_insert_index_for_track};
+use timeline::TrackType;
+use uuid::Uuid;
+
+use crate::command::{Command, CommandError, CommandResult};
+use crate::project_ext::active_scene_mut;
+
+pub struct AddTrackCommand {
+ track_type: TrackType,
+ index: Option<usize>,
+ track_id: String,
+ saved_state: Option<SceneTracks>,
+}
+
+impl AddTrackCommand {
+ pub fn new(track_type: TrackType, index: Option<usize>) -> Self {
+ Self {
+ track_type,
+ index,
+ track_id: Uuid::new_v4().to_string(),
+ saved_state: None,
+ }
+ }
+
+ pub fn track_id(&self) -> &str {
+ &self.track_id
+ }
+}
+
+impl Command for AddTrackCommand {
+ fn execute(
+ &mut self,
+ project: &mut Project,
+ ) -> Result<Option<CommandResult>, CommandError> {
+ let Some(scene) = active_scene_mut(project) else {
+ return Ok(None);
+ };
+
+ self.saved_state = Some(scene.tracks.clone());
+
+ let insert_index = self.index.unwrap_or_else(|| {
+ get_default_insert_index_for_track(&scene.tracks, self.track_type)
+ });
+
+ let new_track = build_empty_track(&self.track_id, self.track_type, None);
+ if self.track_type == TrackType::Audio {
+ let audio_insert_index = insert_index
+ .saturating_sub(scene.tracks.overlay.len() + 1);
+ scene
+ .tracks
+ .audio
+ .insert(audio_insert_index.min(scene.tracks.audio.len()), new_track);
+ } else {
+ let overlay_insert_index = insert_index.min(scene.tracks.overlay.len());
+ scene.tracks.overlay.insert(overlay_insert_index, new_track);
+ }
+ Ok(None)
+ }
+
+ fn undo(&mut self, project: &mut Project) {
+ let Some(saved) = &self.saved_state else {
+ return;
+ };
+ if let Some(scene) = active_scene_mut(project) {
+ scene.tracks = saved.clone();
+ }
+ }
+}
diff --git a/rust/crates/commands/src/timeline/track/mod.rs b/rust/crates/commands/src/timeline/track/mod.rs
new file mode 100644
index 00000000..c133a12d
--- /dev/null
+++ b/rust/crates/commands/src/timeline/track/mod.rs
@@ -0,0 +1,9 @@
+pub mod add_track;
+pub mod remove_track;
+pub mod toggle_track_mute;
+pub mod toggle_track_visibility;
+
+pub use add_track::AddTrackCommand;
+pub use remove_track::RemoveTrackCommand;
+pub use toggle_track_mute::ToggleTrackMuteCommand;
+pub use toggle_track_visibility::ToggleTrackVisibilityCommand;
diff --git a/rust/crates/commands/src/timeline/track/remove_track.rs b/rust/crates/commands/src/timeline/track/remove_track.rs
new file mode 100644
index 00000000..5a79b4ae
--- /dev/null
+++ b/rust/crates/commands/src/timeline/track/remove_track.rs
@@ -0,0 +1,43 @@
+use scene::{Project, SceneTracks};
+
+use crate::command::{Command, CommandError, CommandResult};
+use crate::project_ext::active_scene_mut;
+
+pub struct RemoveTrackCommand {
+ track_id: String,
+ saved_state: Option<SceneTracks>,
+}
+
+impl RemoveTrackCommand {
+ pub fn new(track_id: impl Into<String>) -> Self {
+ Self {
+ track_id: track_id.into(),
+ saved_state: None,
+ }
+ }
+}
+
+impl Command for RemoveTrackCommand {
+ fn execute(
+ &mut self,
+ project: &mut Project,
+ ) -> Result<Option<CommandResult>, CommandError> {
+ let Some(scene) = active_scene_mut(project) else {
+ return Ok(None);
+ };
+
+ self.saved_state = Some(scene.tracks.clone());
+ scene.tracks.overlay.retain(|track| track.id() != self.track_id);
+ scene.tracks.audio.retain(|track| track.id() != self.track_id);
+ Ok(None)
+ }
+
+ fn undo(&mut self, project: &mut Project) {
+ let Some(saved) = &self.saved_state else {
+ return;
+ };
+ if let Some(scene) = active_scene_mut(project) {
+ scene.tracks = saved.clone();
+ }
+ }
+}
diff --git a/rust/crates/commands/src/timeline/track/toggle_track_mute.rs b/rust/crates/commands/src/timeline/track/toggle_track_mute.rs
new file mode 100644
index 00000000..afaaf3f3
--- /dev/null
+++ b/rust/crates/commands/src/timeline/track/toggle_track_mute.rs
@@ -0,0 +1,49 @@
+use scene::{Project, SceneTracks, Track};
+
+use crate::command::{Command, CommandError, CommandResult};
+use crate::project_ext::active_scene_mut;
+use crate::tracks::find_track_mut;
+
+pub struct ToggleTrackMuteCommand {
+ track_id: String,
+ saved_state: Option<SceneTracks>,
+}
+
+impl ToggleTrackMuteCommand {
+ pub fn new(track_id: impl Into<String>) -> Self {
+ Self {
+ track_id: track_id.into(),
+ saved_state: None,
+ }
+ }
+}
+
+impl Command for ToggleTrackMuteCommand {
+ fn execute(
+ &mut self,
+ project: &mut Project,
+ ) -> Result<Option<CommandResult>, CommandError> {
+ let Some(scene) = active_scene_mut(project) else {
+ return Ok(None);
+ };
+
+ self.saved_state = Some(scene.tracks.clone());
+
+ match find_track_mut(&mut scene.tracks, &self.track_id) {
+ Some(Track::Video { muted, .. }) | Some(Track::Audio { muted, .. }) => {
+ *muted = !*muted;
+ }
+ _ => {}
+ }
+ Ok(None)
+ }
+
+ fn undo(&mut self, project: &mut Project) {
+ let Some(saved) = &self.saved_state else {
+ return;
+ };
+ if let Some(scene) = active_scene_mut(project) {
+ scene.tracks = saved.clone();
+ }
+ }
+}
diff --git a/rust/crates/commands/src/timeline/track/toggle_track_visibility.rs b/rust/crates/commands/src/timeline/track/toggle_track_visibility.rs
new file mode 100644
index 00000000..79000a73
--- /dev/null
+++ b/rust/crates/commands/src/timeline/track/toggle_track_visibility.rs
@@ -0,0 +1,54 @@
+use scene::{Project, SceneTracks, Track};
+
+use crate::command::{Command, CommandError, CommandResult};
+use crate::project_ext::active_scene_mut;
+use crate::tracks::find_track_mut;
+
+pub struct ToggleTrackVisibilityCommand {
+ track_id: String,
+ saved_state: Option<SceneTracks>,
+}
+
+impl ToggleTrackVisibilityCommand {
+ pub fn new(track_id: impl Into<String>) -> Self {
+ Self {
+ track_id: track_id.into(),
+ saved_state: None,
+ }
+ }
+}
+
+impl Command for ToggleTrackVisibilityCommand {
+ fn execute(
+ &mut self,
+ project: &mut Project,
+ ) -> Result<Option<CommandResult>, CommandError> {
+ let Some(scene) = active_scene_mut(project) else {
+ return Ok(None);
+ };
+
+ self.saved_state = Some(scene.tracks.clone());
+
+ match find_track_mut(&mut scene.tracks, &self.track_id) {
+ Some(
+ Track::Video { hidden, .. }
+ | Track::Text { hidden, .. }
+ | Track::Graphic { hidden, .. }
+ | Track::Effect { hidden, .. },
+ ) => {
+ *hidden = !*hidden;
+ }
+ _ => {}
+ }
+ Ok(None)
+ }
+
+ fn undo(&mut self, project: &mut Project) {
+ let Some(saved) = &self.saved_state else {
+ return;
+ };
+ if let Some(scene) = active_scene_mut(project) {
+ scene.tracks = saved.clone();
+ }
+ }
+}