M3.8: stub burn-down

Implement 20 formerly disabled menu stubs: Look at Selected/All Layers
(2D viewer fit, 3D view cameras, active camera), Switch View Layout (1/2/4
views in the viewer) and Share View Options, Create Camera from 3D View,
Add Output Module (every module encodes the item's frames), Pre-render
(queue + Import & Replace Usage post-render action), Save Current Preview,
RotoBezier / Convert To Bezier Path, Group / Ungroup Shapes, Set First
Vertex, Free Transform Points, mask Motion Blur (sub-frame mask samples),
Feather Falloff (smooth/linear), Hide Locked Masks, and workspace
save / save as / edit. Tests incl. undo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas
2026-10-02 09:16:42 -04:00
co-authored by Claude Opus 5.5
parent c4100bcf80
commit 799b5b39ed
26 changed files with 1546 additions and 68 deletions
+37
View File
@@ -401,6 +401,37 @@ pub struct RenderQueueItem {
/// Resolved path of the last render (first file for sequences).
#[serde(default)]
pub last_output: Option<String>,
/// Further Output Modules (Composition ▸ Add Output Module): the same frames are encoded
/// once per module.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub extra_outputs: Vec<OutputModule>,
/// Post-Render Action of the first output module.
#[serde(default, skip_serializing_if = "PostRenderAction::is_none")]
pub post_render: PostRenderAction,
}
/// What happens after an item renders (Output Module ▸ Post-Render Action).
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum PostRenderAction {
#[default]
None,
/// Import the rendered file into the project.
Import,
/// Import it and replace every use of the rendered composition (Composition ▸ Pre-render).
ImportAndReplace,
}
impl PostRenderAction {
pub fn is_none(&self) -> bool {
*self == PostRenderAction::None
}
pub fn label(self) -> &'static str {
match self {
PostRenderAction::None => "None",
PostRenderAction::Import => "Import",
PostRenderAction::ImportAndReplace => "Import & Replace Usage",
}
}
}
impl RenderQueueItem {
@@ -415,8 +446,14 @@ impl RenderQueueItem {
started: None,
render_time: None,
last_output: None,
extra_outputs: vec![],
post_render: PostRenderAction::None,
}
}
/// Every output module, the first one first.
pub fn output_modules(&self) -> impl Iterator<Item = &OutputModule> {
std::iter::once(&self.output).chain(self.extra_outputs.iter())
}
/// Will be rendered by the next Render.
pub fn is_queued(&self) -> bool {
self.render && matches!(self.status, RenderStatus::Queued)