mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-11 04:47:14 +00:00
Session::crypto_coverage returns the coverage of one Cryptomatte ID over the layer, read from the probe Session::crypto_probe_job keeps: at most max_side samples on the long side, each at the centre of its cell, or None until the probe is built. It is what the Cryptomatte eyedropper's hover highlight will draw. Tests cover the coverage of an ID from the kept probe and the cost of a highlight with six ranks.
298 lines
9.1 KiB
Rust
298 lines
9.1 KiB
Rust
//! The command registry. Ids follow After Effects' menu structure; every menu item, panel button,
|
|
//! shortcut and viewer/timeline gesture maps to one of these.
|
|
|
|
mod align;
|
|
mod align_data;
|
|
mod anim;
|
|
mod anim_presets;
|
|
pub mod anim_tools;
|
|
mod animation;
|
|
pub(crate) mod app_more;
|
|
mod autotrace;
|
|
mod batch;
|
|
mod blender;
|
|
mod camera_cmds;
|
|
mod comp;
|
|
pub(crate) mod comp_more;
|
|
pub mod content_fill;
|
|
mod create;
|
|
mod edit;
|
|
mod effect;
|
|
pub use effect::{CryptoCoverage, CryptoProbeJob};
|
|
pub(crate) use effect::{CryptoProbeSlot, crypto_coverage, crypto_probe_job, crypto_probe_ready, keep_crypto_probe, kept_crypto_probe};
|
|
pub mod essential;
|
|
pub mod expr_tools;
|
|
mod file;
|
|
pub(crate) mod file_more;
|
|
mod focus;
|
|
pub mod footage_panel;
|
|
pub(crate) mod frame_export;
|
|
mod frontend;
|
|
mod help;
|
|
mod import_project;
|
|
mod key_labels;
|
|
mod key_transform;
|
|
mod keys_more;
|
|
mod layer;
|
|
mod layer_menu;
|
|
mod layer_time;
|
|
pub(crate) mod link;
|
|
mod liquify;
|
|
mod lottie;
|
|
pub mod markers;
|
|
mod mask;
|
|
pub mod mask_interp;
|
|
pub(crate) mod model3d;
|
|
mod nav_more;
|
|
pub mod paint;
|
|
pub mod panels_cmds;
|
|
pub(crate) mod path_nulls;
|
|
mod paths;
|
|
mod project_items;
|
|
pub(crate) mod prop;
|
|
mod prop_groups;
|
|
mod proxy;
|
|
pub mod puppet;
|
|
mod query;
|
|
mod quick_offset;
|
|
mod relink;
|
|
pub(crate) mod relink_moved;
|
|
mod render_queue;
|
|
pub(crate) mod rig3d;
|
|
pub mod roto_cmds;
|
|
mod scene_detect;
|
|
pub mod scripts;
|
|
mod settings;
|
|
pub mod shape_stroke;
|
|
pub mod shape_tool;
|
|
mod stubs;
|
|
mod styles;
|
|
mod text_anim;
|
|
pub mod text_edit;
|
|
mod three_d;
|
|
pub mod time;
|
|
mod timeline;
|
|
mod track;
|
|
mod view;
|
|
pub mod viewer_cmds;
|
|
pub(crate) mod vpe;
|
|
pub(crate) mod vr_editor;
|
|
mod warp_cmds;
|
|
pub(crate) mod watch_folder;
|
|
#[cfg(test)]
|
|
pub(crate) use app_more::report_text as report_text_for_tests;
|
|
pub(crate) use app_more::view_command;
|
|
#[cfg(test)]
|
|
pub(crate) use file::open as open_for_tests;
|
|
#[cfg(test)]
|
|
pub(crate) use keys_more::amplitudes as amplitudes_for_tests;
|
|
#[cfg(test)]
|
|
pub(crate) use mask::split_segment as split_segment_for_tests;
|
|
|
|
use std::sync::OnceLock;
|
|
|
|
use effectcraft_project::{Comp, ItemId, Layer, LayerId};
|
|
use effectcraft_time::Tick;
|
|
use serde_json::Value;
|
|
|
|
use crate::{EngineError, Result, Session};
|
|
|
|
pub type Run = fn(&mut Session, &Value) -> Result<Value>;
|
|
pub type Enabled = fn(&Session) -> std::result::Result<(), String>;
|
|
|
|
/// Metadata + implementation for one command.
|
|
pub struct CommandSpec {
|
|
pub id: &'static str,
|
|
pub label: &'static str,
|
|
/// Menu placement, e.g. `["Layer", "New"]`. Empty = not in menus.
|
|
pub menu: &'static [&'static str],
|
|
/// Default shortcut (egui-style names, `Cmd` = ⌘ on macOS / Ctrl elsewhere).
|
|
pub shortcut: Option<&'static str>,
|
|
/// Further default shortcuts (the menus and tooltips show `shortcut`).
|
|
pub alt_shortcuts: &'static [&'static str],
|
|
/// Parameter description for agents and the MCP schema.
|
|
pub params: &'static str,
|
|
pub enabled: Enabled,
|
|
pub run: Run,
|
|
/// Record in the journal (false for pure queries).
|
|
pub journal: bool,
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! cmd {
|
|
// Several default shortcuts: `["PageDown", "Cmd+ArrowRight"]`.
|
|
($id:literal, $label:literal, [$($m:literal),*], [$sc:literal, $($alt:literal),+], $params:literal, $en:expr, $run:expr) => {
|
|
$crate::commands::CommandSpec { alt_shortcuts: &[$($alt),+], ..$crate::cmd!($id, $label, [$($m),*], Some($sc), $params, $en, $run) }
|
|
};
|
|
($id:literal, $label:literal, [$($m:literal),*], $sc:expr, $params:literal, $en:expr, $run:expr) => {
|
|
$crate::commands::CommandSpec {
|
|
id: $id,
|
|
label: $label,
|
|
menu: &[$($m),*],
|
|
shortcut: $sc,
|
|
alt_shortcuts: &[],
|
|
params: $params,
|
|
enabled: $en,
|
|
run: $run,
|
|
journal: true,
|
|
}
|
|
};
|
|
}
|
|
#[macro_export]
|
|
macro_rules! query {
|
|
($id:literal, $label:literal, $params:literal, $run:expr) => {
|
|
$crate::commands::CommandSpec {
|
|
id: $id,
|
|
label: $label,
|
|
menu: &[],
|
|
shortcut: None,
|
|
alt_shortcuts: &[],
|
|
params: $params,
|
|
enabled: $crate::commands::always,
|
|
run: $run,
|
|
journal: false,
|
|
}
|
|
};
|
|
}
|
|
|
|
mod enabled;
|
|
mod params;
|
|
mod schema;
|
|
|
|
use super::commands;
|
|
pub use enabled::always;
|
|
pub(crate) use enabled::{has_comp, has_keys, has_layers, has_project_selection, not_yet, not_yet_run};
|
|
pub use params::match_path_of;
|
|
pub(crate) use params::{
|
|
b_p, bad, comp_id, f_p, frontend, layer_mut, layer_p, layers_or, layers_p, merge_p, popup_options, resolve_effect_path, resolve_layer, selectable,
|
|
selected_leaf_props, str_p, time_p, unlocked, visible_p,
|
|
};
|
|
pub use schema::{accepted_params, check_params, params_schema};
|
|
|
|
pub fn command_specs() -> &'static [CommandSpec] {
|
|
static SPECS: OnceLock<Vec<CommandSpec>> = OnceLock::new();
|
|
SPECS.get_or_init(|| {
|
|
let mut v = Vec::new();
|
|
v.extend(file::specs());
|
|
v.extend(crate::models::specs());
|
|
v.extend(edit::specs());
|
|
v.extend(comp::specs());
|
|
v.extend(layer::specs());
|
|
v.extend(styles::specs());
|
|
v.extend(three_d::specs());
|
|
v.extend(model3d::specs());
|
|
v.extend(rig3d::specs());
|
|
v.extend(text_anim::specs());
|
|
v.extend(text_edit::specs());
|
|
v.extend(layer_time::specs());
|
|
v.extend(prop::specs());
|
|
v.extend(prop_groups::specs());
|
|
v.extend(project_items::specs());
|
|
v.extend(anim::specs());
|
|
v.extend(anim_tools::specs());
|
|
v.extend(link::specs());
|
|
v.extend(markers::specs());
|
|
v.extend(mask::specs());
|
|
v.extend(paths::specs());
|
|
v.extend(effect::specs());
|
|
v.extend(time::specs());
|
|
v.extend(nav_more::specs());
|
|
v.extend(render_queue::specs());
|
|
v.extend(help::specs());
|
|
v.extend(query::specs());
|
|
v.extend(batch::specs());
|
|
v.extend(layer_menu::specs());
|
|
v.extend(create::specs());
|
|
v.extend(animation::specs());
|
|
v.extend(anim_presets::specs());
|
|
v.extend(view::specs());
|
|
v.extend(viewer_cmds::specs());
|
|
v.extend(shape_stroke::specs());
|
|
v.extend(shape_tool::specs());
|
|
v.extend(focus::specs());
|
|
v.extend(key_labels::specs());
|
|
v.extend(key_transform::specs());
|
|
v.extend(quick_offset::specs());
|
|
v.extend(file_more::specs());
|
|
v.extend(relink::specs());
|
|
v.extend(relink_moved::specs());
|
|
v.extend(lottie::specs());
|
|
v.extend(import_project::specs());
|
|
v.extend(timeline::specs());
|
|
v.extend(comp_more::specs());
|
|
v.extend(frame_export::specs());
|
|
v.extend(watch_folder::specs());
|
|
v.extend(vpe::specs());
|
|
v.extend(path_nulls::specs());
|
|
v.extend(vr_editor::specs());
|
|
v.extend(frontend::specs());
|
|
v.extend(track::specs());
|
|
v.extend(mask_interp::specs());
|
|
v.extend(warp_cmds::specs());
|
|
v.extend(camera_cmds::specs());
|
|
v.extend(roto_cmds::specs());
|
|
v.extend(paint::specs());
|
|
v.extend(puppet::specs());
|
|
v.extend(liquify::specs());
|
|
v.extend(settings::specs());
|
|
v.extend(app_more::specs());
|
|
v.extend(keys_more::specs());
|
|
v.extend(essential::specs());
|
|
v.extend(expr_tools::specs());
|
|
v.extend(proxy::specs());
|
|
v.extend(scripts::specs());
|
|
v.extend(panels_cmds::specs());
|
|
v.extend(footage_panel::specs());
|
|
v.extend(autotrace::specs());
|
|
v.extend(scene_detect::specs());
|
|
v.extend(align_data::specs());
|
|
v.extend(align::specs());
|
|
v.extend(content_fill::specs());
|
|
v.extend(stubs::specs());
|
|
v.extend(crate::storage::specs());
|
|
v.extend(crate::learn::specs());
|
|
v.extend(crate::templates::specs());
|
|
v.extend(crate::preview::specs());
|
|
v
|
|
})
|
|
}
|
|
|
|
/// Set `footage` as the proxy of `item` (File ▸ Create Proxy's post-render action).
|
|
pub(crate) fn proxy_set(s: &mut Session, item: ItemId, footage: effectcraft_project::Footage) -> Result<()> {
|
|
proxy::set_proxy_footage(s, &[item], footage)
|
|
}
|
|
|
|
/// (id, name) of the text animation presets.
|
|
pub fn text_preset_list() -> Vec<(String, String)> {
|
|
text_anim::preset_names()
|
|
}
|
|
|
|
/// (id, name, category) of the built-in animation presets (Transitions…).
|
|
pub fn builtin_preset_list() -> Vec<(String, String, String)> {
|
|
anim_presets::preset_names()
|
|
}
|
|
|
|
pub fn find(id: &str) -> Option<&'static CommandSpec> {
|
|
// Every command execution looks its spec up: index the ~2,000 ids once.
|
|
static INDEX: OnceLock<std::collections::HashMap<&'static str, usize>> = OnceLock::new();
|
|
let index = INDEX.get_or_init(|| {
|
|
let mut m = std::collections::HashMap::new();
|
|
for (i, c) in command_specs().iter().enumerate() {
|
|
m.entry(c.id).or_insert(i);
|
|
}
|
|
m
|
|
});
|
|
index.get(id).map(|&i| &command_specs()[i])
|
|
}
|
|
|
|
/// Font families available to text layers (bundled + scanned system fonts).
|
|
/// Text animation presets: (id, name), for menus.
|
|
pub fn text_presets() -> Vec<(String, String)> {
|
|
commands::text_preset_list()
|
|
}
|
|
|
|
/// Built-in animation presets (Effects & Presets ▸ * Animation Presets): (id, name, category).
|
|
pub fn animation_presets() -> Vec<(String, String, String)> {
|
|
commands::builtin_preset_list()
|
|
}
|