diff options
| author | cashmere <cashmere@autistici.org> | 2026-07-28 19:41:16 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-07-28 19:41:16 +0200 |
| commit | f5a82152394fde4d8f740f664ab7737b82861618 (patch) | |
| tree | 5a51b181abead1ce03d2dbfc12b77918d3be0e1b /rust/crates/commands/src/scene | |
| parent | e837e7504379e100ff3b56282577ec67bb88bec9 (diff) | |
| download | opencut-f5a82152394fde4d8f740f664ab7737b82861618.tar.gz | |
feat: GPUI desktop port foundation
- scene crate: full project/scene/element model, serde round-trip
proven against the web SerializedProject shape
- transfer crate: .ocp zip container, cross-compat with web fflate
archives proven in both directions
- storage crate: filesystem project store replacing IndexedDB,
.ocp import/export
- media crate: ffmpeg-next 8 decoder (frames, audio, thumbnails,
waveform summaries)
- playback crate: wall-clock anchored, frame-rounded playback clock
- gpu crate: native texture readback; compositor renders headless
offscreen on Vulkan (spike test)
- flake devshell: rust toolchain, GPUI native deps, ffmpeg dev,
bindgen clang args; GPUI hello-world builds
- port plan in notes/gpui-port.md
Diffstat (limited to 'rust/crates/commands/src/scene')
| -rw-r--r-- | rust/crates/commands/src/scene/create_scene.rs | 46 | ||||
| -rw-r--r-- | rust/crates/commands/src/scene/delete_scene.rs | 61 | ||||
| -rw-r--r-- | rust/crates/commands/src/scene/mod.rs | 15 | ||||
| -rw-r--r-- | rust/crates/commands/src/scene/move_bookmark.rs | 50 | ||||
| -rw-r--r-- | rust/crates/commands/src/scene/remove_bookmark.rs | 54 | ||||
| -rw-r--r-- | rust/crates/commands/src/scene/rename_scene.rs | 58 | ||||
| -rw-r--r-- | rust/crates/commands/src/scene/toggle_bookmark.rs | 48 | ||||
| -rw-r--r-- | rust/crates/commands/src/scene/update_bookmark.rs | 49 |
8 files changed, 381 insertions, 0 deletions
diff --git a/rust/crates/commands/src/scene/create_scene.rs b/rust/crates/commands/src/scene/create_scene.rs new file mode 100644 index 00000000..1f2de02b --- /dev/null +++ b/rust/crates/commands/src/scene/create_scene.rs @@ -0,0 +1,46 @@ +use scene::{Project, Scene}; + +use crate::command::{Command, CommandError, CommandResult}; + +pub struct CreateSceneCommand { + name: String, + is_main: bool, + saved_scenes: Option<Vec<Scene>>, + created_scene_id: Option<String>, +} + +impl CreateSceneCommand { + pub fn new(name: impl Into<String>, is_main: bool) -> Self { + Self { + name: name.into(), + is_main, + saved_scenes: None, + created_scene_id: None, + } + } + + pub fn scene_id(&self) -> Option<&str> { + self.created_scene_id.as_deref() + } +} + +impl Command for CreateSceneCommand { + fn execute( + &mut self, + project: &mut Project, + ) -> Result<Option<CommandResult>, CommandError> { + self.saved_scenes = Some(project.scenes.clone()); + + let created = timeline::scenes::build_default_scene(&self.name, self.is_main); + self.created_scene_id = Some(created.id.clone()); + project.scenes.push(created); + Ok(None) + } + + fn undo(&mut self, project: &mut Project) { + let Some(saved) = &self.saved_scenes else { + return; + }; + project.scenes = saved.clone(); + } +} diff --git a/rust/crates/commands/src/scene/delete_scene.rs b/rust/crates/commands/src/scene/delete_scene.rs new file mode 100644 index 00000000..61763dfd --- /dev/null +++ b/rust/crates/commands/src/scene/delete_scene.rs @@ -0,0 +1,61 @@ +use scene::{Project, Scene}; + +use crate::command::{Command, CommandError, CommandResult}; + +pub struct DeleteSceneCommand { + scene_id: String, + saved_scenes: Option<Vec<Scene>>, + saved_current_scene_id: Option<String>, +} + +impl DeleteSceneCommand { + pub fn new(scene_id: impl Into<String>) -> Self { + Self { + scene_id: scene_id.into(), + saved_scenes: None, + saved_current_scene_id: None, + } + } +} + +impl Command for DeleteSceneCommand { + fn execute( + &mut self, + project: &mut Project, + ) -> Result<Option<CommandResult>, CommandError> { + let Some(deleted) = project.scenes.iter().find(|scene| scene.id == self.scene_id) + else { + return Ok(None); + }; + if deleted.is_main { + return Ok(None); + } + + self.saved_scenes = Some(project.scenes.clone()); + self.saved_current_scene_id = Some(project.current_scene_id.clone()); + + project.scenes.retain(|scene| scene.id != self.scene_id); + + if project.current_scene_id == self.scene_id { + let fallback_id = project + .scenes + .iter() + .find(|scene| scene.is_main) + .map(|scene| scene.id.clone()); + if let Some(fallback_id) = fallback_id { + project.current_scene_id = fallback_id; + } + } + Ok(None) + } + + fn undo(&mut self, project: &mut Project) { + let (Some(saved_scenes), Some(saved_current_scene_id)) = + (&self.saved_scenes, &self.saved_current_scene_id) + else { + return; + }; + project.scenes = saved_scenes.clone(); + project.current_scene_id = saved_current_scene_id.clone(); + } +} diff --git a/rust/crates/commands/src/scene/mod.rs b/rust/crates/commands/src/scene/mod.rs new file mode 100644 index 00000000..10d687c1 --- /dev/null +++ b/rust/crates/commands/src/scene/mod.rs @@ -0,0 +1,15 @@ +pub mod create_scene; +pub mod delete_scene; +pub mod move_bookmark; +pub mod remove_bookmark; +pub mod rename_scene; +pub mod toggle_bookmark; +pub mod update_bookmark; + +pub use create_scene::CreateSceneCommand; +pub use delete_scene::DeleteSceneCommand; +pub use move_bookmark::MoveBookmarkCommand; +pub use remove_bookmark::RemoveBookmarkCommand; +pub use rename_scene::RenameSceneCommand; +pub use toggle_bookmark::ToggleBookmarkCommand; +pub use update_bookmark::UpdateBookmarkCommand; diff --git a/rust/crates/commands/src/scene/move_bookmark.rs b/rust/crates/commands/src/scene/move_bookmark.rs new file mode 100644 index 00000000..dddef11f --- /dev/null +++ b/rust/crates/commands/src/scene/move_bookmark.rs @@ -0,0 +1,50 @@ +use scene::Project; +use time::MediaTime; + +use crate::bookmarks::{get_frame_time, move_bookmark_in_array}; +use crate::command::{Command, CommandError, CommandResult}; +use crate::project_ext::active_scene_mut; + +pub struct MoveBookmarkCommand { + from_time: MediaTime, + to_time: MediaTime, + saved_bookmarks: Option<Vec<scene::Bookmark>>, +} + +impl MoveBookmarkCommand { + pub fn new(from_time: MediaTime, to_time: MediaTime) -> Self { + Self { + from_time, + to_time, + saved_bookmarks: None, + } + } +} + +impl Command for MoveBookmarkCommand { + fn execute( + &mut self, + project: &mut Project, + ) -> Result<Option<CommandResult>, CommandError> { + let fps = project.settings.fps; + let Some(scene) = active_scene_mut(project) else { + return Ok(None); + }; + + self.saved_bookmarks = Some(scene.bookmarks.clone()); + let from_frame_time = get_frame_time(self.from_time, fps); + let to_frame_time = get_frame_time(self.to_time, fps); + scene.bookmarks = + move_bookmark_in_array(&scene.bookmarks, from_frame_time, to_frame_time); + Ok(None) + } + + fn undo(&mut self, project: &mut Project) { + let Some(saved) = &self.saved_bookmarks else { + return; + }; + if let Some(scene) = active_scene_mut(project) { + scene.bookmarks = saved.clone(); + } + } +} diff --git a/rust/crates/commands/src/scene/remove_bookmark.rs b/rust/crates/commands/src/scene/remove_bookmark.rs new file mode 100644 index 00000000..f8fe0c5a --- /dev/null +++ b/rust/crates/commands/src/scene/remove_bookmark.rs @@ -0,0 +1,54 @@ +use scene::Project; +use time::MediaTime; + +use crate::bookmarks::{get_frame_time, remove_bookmark_from_array}; +use crate::command::{Command, CommandError, CommandResult}; +use crate::project_ext::active_scene_mut; + +pub struct RemoveBookmarkCommand { + time: MediaTime, + frame_time: MediaTime, + saved_bookmarks: Option<Vec<scene::Bookmark>>, +} + +impl RemoveBookmarkCommand { + pub fn new(time: MediaTime) -> Self { + Self { + time, + frame_time: MediaTime::ZERO, + saved_bookmarks: None, + } + } +} + +impl Command for RemoveBookmarkCommand { + fn execute( + &mut self, + project: &mut Project, + ) -> Result<Option<CommandResult>, CommandError> { + let fps = project.settings.fps; + let Some(scene) = active_scene_mut(project) else { + return Ok(None); + }; + + self.saved_bookmarks = Some(scene.bookmarks.clone()); + self.frame_time = get_frame_time(self.time, fps); + + let updated = remove_bookmark_from_array(&scene.bookmarks, self.frame_time); + if updated.len() == scene.bookmarks.len() { + return Ok(None); + } + + scene.bookmarks = updated; + Ok(None) + } + + fn undo(&mut self, project: &mut Project) { + let Some(saved) = &self.saved_bookmarks else { + return; + }; + if let Some(scene) = active_scene_mut(project) { + scene.bookmarks = saved.clone(); + } + } +} diff --git a/rust/crates/commands/src/scene/rename_scene.rs b/rust/crates/commands/src/scene/rename_scene.rs new file mode 100644 index 00000000..4876fb9b --- /dev/null +++ b/rust/crates/commands/src/scene/rename_scene.rs @@ -0,0 +1,58 @@ +use scene::Project; + +use crate::command::{Command, CommandError, CommandResult}; + +pub struct RenameSceneCommand { + scene_id: String, + new_name: String, + saved_name: Option<String>, + saved_updated_at: Option<chrono::DateTime<chrono::Utc>>, +} + +impl RenameSceneCommand { + pub fn new(scene_id: impl Into<String>, new_name: impl Into<String>) -> Self { + Self { + scene_id: scene_id.into(), + new_name: new_name.into(), + saved_name: None, + saved_updated_at: None, + } + } +} + +impl Command for RenameSceneCommand { + fn execute( + &mut self, + project: &mut Project, + ) -> Result<Option<CommandResult>, CommandError> { + let Some(scene) = project + .scenes + .iter_mut() + .find(|scene| scene.id == self.scene_id) + else { + return Ok(None); + }; + + self.saved_name = Some(scene.name.clone()); + self.saved_updated_at = Some(scene.updated_at); + scene.name = self.new_name.clone(); + scene.updated_at = chrono::Utc::now(); + Ok(None) + } + + fn undo(&mut self, project: &mut Project) { + let (Some(saved_name), Some(saved_updated_at)) = + (&self.saved_name, self.saved_updated_at) + else { + return; + }; + if let Some(scene) = project + .scenes + .iter_mut() + .find(|scene| scene.id == self.scene_id) + { + scene.name = saved_name.clone(); + scene.updated_at = saved_updated_at; + } + } +} diff --git a/rust/crates/commands/src/scene/toggle_bookmark.rs b/rust/crates/commands/src/scene/toggle_bookmark.rs new file mode 100644 index 00000000..054e1c78 --- /dev/null +++ b/rust/crates/commands/src/scene/toggle_bookmark.rs @@ -0,0 +1,48 @@ +use scene::Project; + +use crate::bookmarks::{get_frame_time, toggle_bookmark_in_array}; +use crate::command::{Command, CommandError, CommandResult}; +use crate::project_ext::active_scene_mut; +use time::MediaTime; + +pub struct ToggleBookmarkCommand { + time: MediaTime, + frame_time: MediaTime, + saved_bookmarks: Option<Vec<scene::Bookmark>>, +} + +impl ToggleBookmarkCommand { + pub fn new(time: MediaTime) -> Self { + Self { + time, + frame_time: MediaTime::ZERO, + saved_bookmarks: None, + } + } +} + +impl Command for ToggleBookmarkCommand { + fn execute( + &mut self, + project: &mut Project, + ) -> Result<Option<CommandResult>, CommandError> { + let fps = project.settings.fps; + let Some(scene) = active_scene_mut(project) else { + return Ok(None); + }; + + self.saved_bookmarks = Some(scene.bookmarks.clone()); + self.frame_time = get_frame_time(self.time, fps); + scene.bookmarks = toggle_bookmark_in_array(&scene.bookmarks, self.frame_time); + Ok(None) + } + + fn undo(&mut self, project: &mut Project) { + let Some(saved) = &self.saved_bookmarks else { + return; + }; + if let Some(scene) = active_scene_mut(project) { + scene.bookmarks = saved.clone(); + } + } +} diff --git a/rust/crates/commands/src/scene/update_bookmark.rs b/rust/crates/commands/src/scene/update_bookmark.rs new file mode 100644 index 00000000..f2c9b94e --- /dev/null +++ b/rust/crates/commands/src/scene/update_bookmark.rs @@ -0,0 +1,49 @@ +use scene::Project; +use time::MediaTime; + +use crate::bookmarks::{BookmarkPatch, get_frame_time, update_bookmark_in_array}; +use crate::command::{Command, CommandError, CommandResult}; +use crate::project_ext::active_scene_mut; + +pub struct UpdateBookmarkCommand { + time: MediaTime, + updates: BookmarkPatch, + saved_bookmarks: Option<Vec<scene::Bookmark>>, +} + +impl UpdateBookmarkCommand { + pub fn new(time: MediaTime, updates: BookmarkPatch) -> Self { + Self { + time, + updates, + saved_bookmarks: None, + } + } +} + +impl Command for UpdateBookmarkCommand { + fn execute( + &mut self, + project: &mut Project, + ) -> Result<Option<CommandResult>, CommandError> { + let fps = project.settings.fps; + let Some(scene) = active_scene_mut(project) else { + return Ok(None); + }; + + self.saved_bookmarks = Some(scene.bookmarks.clone()); + let frame_time = get_frame_time(self.time, fps); + scene.bookmarks = + update_bookmark_in_array(&scene.bookmarks, frame_time, &self.updates); + Ok(None) + } + + fn undo(&mut self, project: &mut Project) { + let Some(saved) = &self.saved_bookmarks else { + return; + }; + if let Some(scene) = active_scene_mut(project) { + scene.bookmarks = saved.clone(); + } + } +} |
