mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-10 20:41:25 +00:00
Naming: descriptive names for the CC effects, Lumetri, Mocha, Keylight and Mercury (#3327)
Related to #1365. Display labels only; effect, command, parameter, panel and serialized ids and the AEP/script match-name tables are unchanged. - 69 Cycore CC effects, Key Light, Mocha shape, Lumetri Color/Scopes and the Mercury renderer labels get descriptive names; the old names stay case-insensitive lookup and search aliases. - Backend::parse accepts the new renderer labels, so reported settings round-trip. - Display names are unique per language in every effect catalog (new test). - Warp Stabilizer and Roto Brush keep their names until RFC-0029 settles. - Mapping in docs/feature-naming.md.
This commit is contained in:
1 parent
a41ff5015c
commit
9893eb0d8d
58 files changed
+1321
-820
No files matched your search
@@ -129,18 +129,14 @@ or into the Timeline, between layers and at the time you point to.
|
||||
|
||||
308 built-in effects across its categories, each with its parameter names, order and
|
||||
defaults: blur and sharpen, channel, color correction (Curves, Levels, Hue/Saturation, a full
|
||||
color-grading panel…), distort (Warp, Bulge, Turbulent Displace, CC Power Pin…), generate (Fractal Noise,
|
||||
color-grading panel…), distort (Warp, Bulge, Turbulent Displace, Perspective Pin…), generate (Fractal Noise,
|
||||
Gradient Ramp, Stroke, Write-on, Audio Spectrum…), keying, matte, noise and grain, perspective,
|
||||
**simulation** (CC Particle World, CC Rainfall, Shatter, Card Dance, Caustics, Wave World…),
|
||||
stylize (Glow, CC Glass…), **time** (Echo, Posterize Time, Timewarp, Time Displacement…),
|
||||
**simulation** (Particle Emitter 3D, Rainfall, Shatter, Card Dance, Caustics, Wave World…),
|
||||
stylize (Glow, Glass Relief…), **time** (Echo, Posterize Time, Timewarp, Time Displacement…),
|
||||
**audio** (Reverb, Parametric EQ, Delay, Stereo Mixer…), text, transitions, utility and expression
|
||||
controls. All nine **Layer Styles** (Drop Shadow, Inner/Outer Glow, Bevel and Emboss, Satin,
|
||||
overlays, Stroke) with Global Light. Preview plays audio in sync, with meters and waveforms.
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/images/effectcraft-effects.png" alt="A CC Particle World burst with Glow, and the Effect Controls panel listing the particle system's parameters" width="100%">
|
||||
</p>
|
||||
|
||||
## 3D
|
||||
|
||||
Classic 3D compositing: 3D layers with orientation and material options,
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
//!
|
||||
//! Project: --project F.ecproj (or a positional *.ecproj) | --demo | --empty (default: demo; mcp: empty)
|
||||
//! Saving: --save (back to --project) | --save-as F.ecproj
|
||||
//! GPU: --gpu renders on the GPU compositor (Mercury GPU Acceleration) when an adapter exists;
|
||||
//! the default is the CPU (Mercury Software Only)
|
||||
//! GPU: --gpu renders on the GPU compositor (GPU Acceleration) when an adapter exists;
|
||||
//! the default is the CPU (Software Rendering)
|
||||
//! Bridge: --bridge PORT drives a running `effectcraft --control PORT` instead of a headless session
|
||||
//! Output: --json for one compact JSON document on stdout (errors: {"error": …}, exit 1)
|
||||
//! ```
|
||||
@@ -466,7 +466,7 @@ fn backend(args: &Args, default_demo: bool) -> Result<Backend, Failure> {
|
||||
}
|
||||
|
||||
/// A wired session; `--gpu` attaches the GPU compositor (renders then follow the project's
|
||||
/// renderer setting, Mercury GPU Acceleration by default).
|
||||
/// renderer setting, GPU Acceleration by default).
|
||||
fn session(args: &Args) -> Result<effectcraft_engine::Session, Failure> {
|
||||
let mut s = effectcraft_host::session();
|
||||
if args.flag("--autosave") {
|
||||
@@ -1443,7 +1443,7 @@ fn adv3d_bench_comp(p: &mut effectcraft_engine::project::Project) -> Option<Item
|
||||
/// `bench --gpu`: CPU vs GPU ms/frame for every comp (or `--comp`) at Full and Half. "cold"
|
||||
/// renders everything (no layer cache); "warm" reuses the layer cache (playback / scrubbing of
|
||||
/// unchanged layers: compositing cost); "viewer" is the GPU display path without readback;
|
||||
/// "auto" is Backend::Auto (Mercury GPU Acceleration) choosing per comp from measured times,
|
||||
/// "auto" is Backend::Auto (GPU Acceleration) choosing per comp from measured times,
|
||||
/// warm; "up/dn MB" are the GPU's uploads / readbacks per warm GPU frame.
|
||||
fn bench_gpu(s: &Session, args: &Args) -> Result<(), Failure> {
|
||||
use effectcraft_render::Backend;
|
||||
|
||||
@@ -106,7 +106,7 @@ fn track_matte(qa: &mut Qa) {
|
||||
fn adjustment_layer(qa: &mut Qa, normal: &Img) {
|
||||
// Adjustment layer: Lumetri exposure, inside a feathered, expanded elliptical mask; then Glow.
|
||||
qa.exec("layer.newAdjustment", json!({"name": "Grade"}));
|
||||
let fx = qa.exec("effect.apply", json!({"effect": "Lumetri Color", "layers": ["Grade"]}));
|
||||
let fx = qa.exec("effect.apply", json!({"effect": "Color Grading", "layers": ["Grade"]}));
|
||||
assert_eq!(fx["paths"], json!(["effects/#1"]), "effect.apply answers with the instance path: {fx}");
|
||||
qa.tool("set_property", json!({"layer": "Grade", "path": "effects/#1/basicCorrection/tone/exposure", "value": 2}));
|
||||
let before = qa.frame(None, 0.5);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Blur & Sharpen, batch 2: edge-preserving blurs (Bilateral, Smart), per-channel and map-driven
|
||||
//! blurs (Channel, Compound, CC Vector), bokeh (Camera Lens Blur), radial streaks and small
|
||||
//! utilities (Reduce Interlace Flicker, CC Cross Blur).
|
||||
//! utilities (Reduce Interlace Flicker, Cross Blur).
|
||||
|
||||
use effectcraft_color::luminance;
|
||||
use effectcraft_keyframe::Value;
|
||||
@@ -507,9 +507,9 @@ fn camera_lens_blur(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// CC Radial Fast Blur
|
||||
// Fast Radial Blur
|
||||
|
||||
/// Transparent pixels CC Radial Fast Blur adds on every side of a `w` × `h` buffer with Center
|
||||
/// Transparent pixels Fast Radial Blur adds on every side of a `w` × `h` buffer with Center
|
||||
/// at `c` (buffer pixels) and smear `s`: content `r` from Center streaks out to `r / (1 − s)`,
|
||||
/// so the farthest corner reaches `d · s / (1 − s)` past itself (at most 4096, as the other
|
||||
/// growing effects). Shared with the GPU path so both grow the same way.
|
||||
@@ -562,7 +562,7 @@ fn radial_fast_blur(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// CC Vector Blur
|
||||
// Vector Blur
|
||||
|
||||
fn vector_blur(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let amount = ctx.params.f("amount").max(0.0) * b.scale;
|
||||
@@ -616,7 +616,7 @@ fn vector_blur(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Reduce Interlace Flicker / CC Cross Blur
|
||||
// Reduce Interlace Flicker / Cross Blur
|
||||
|
||||
fn reduce_flicker(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let s = ctx.params.f("softness").max(0.0) * b.scale;
|
||||
@@ -735,7 +735,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.blur.ccradialfast",
|
||||
"CC Radial Fast Blur",
|
||||
"Fast Radial Blur",
|
||||
vec![
|
||||
p("center", "Center", Value::Vec2([0.5, 0.5]), ParamUi::Point),
|
||||
p("amount", "Amount", num(50.0), slider(0.0, 100.0, 0.0, 100.0, 1)),
|
||||
@@ -745,7 +745,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.blur.ccvector",
|
||||
"CC Vector Blur",
|
||||
"Vector Blur",
|
||||
vec![
|
||||
p("type", "Type", Value::Enum(0), popup(&["Natural", "Constant Length", "Perpendicular", "Direction Center", "Direction Fading"])),
|
||||
p("amount", "Amount", num(10.0), slider(0.0, 500.0, 0.0, 100.0, 1)),
|
||||
@@ -765,7 +765,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
},
|
||||
spec(
|
||||
"ec.blur.cccross",
|
||||
"CC Cross Blur",
|
||||
"Cross Blur",
|
||||
vec![
|
||||
p("radiusX", "Radius X", num(10.0), slider(0.0, 500.0, 0.0, 100.0, 1)),
|
||||
p("radiusY", "Radius Y", num(10.0), slider(0.0, 500.0, 0.0, 100.0, 1)),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Blur & Sharpen: CC Radial Blur and Camera-Shake Deblur.
|
||||
//! Blur & Sharpen: Variable Radial Blur and Camera-Shake Deblur.
|
||||
//!
|
||||
//! * **CC Radial Blur** — zoom (straight, fading, centred both ways) and rotational (plain or
|
||||
//! * **Variable Radial Blur** — zoom (straight, fading, centred both ways) and rotational (plain or
|
||||
//! fading) blurs around a centre point, sampled along the ray / arc through each pixel with a
|
||||
//! sample count set by Quality.
|
||||
//! * **Camera-Shake Deblur** — frame-based restoration in the spirit of published video deblurring
|
||||
@@ -22,7 +22,7 @@ fn spec(id: &'static str, name: &'static str, params: Vec<crate::ParamSpec>, ren
|
||||
EffectSpec { id, name, category: "Blur & Sharpen", params, render, gpu: false, float: true }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Radial Blur
|
||||
// ---------------------------------------------------------------- Variable Radial Blur
|
||||
|
||||
pub const RADIAL_TYPES: [&str; 5] = ["Straight Zoom", "Fading Zoom", "Centered", "Rotate", "Rotate Fading"];
|
||||
|
||||
@@ -246,7 +246,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![
|
||||
spec(
|
||||
"ec.blur.ccradial",
|
||||
"CC Radial Blur",
|
||||
"Variable Radial Blur",
|
||||
vec![
|
||||
p("type", "Type", Value::Enum(1), popup(&RADIAL_TYPES)),
|
||||
p("amount", "Amount", num(10.0), slider(-100.0, 100.0, -100.0, 100.0, 1)),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Channel effects, batch 2: layer-to-layer combinations (Blend, Calculations, Compound
|
||||
//! Arithmetic) and CC Composite. Second layers come from layer parameters through the effect
|
||||
//! Arithmetic) and Source Composite. Second layers come from layer parameters through the effect
|
||||
//! host; with no layer chosen the effect uses the layer itself, as After Effects does.
|
||||
|
||||
use effectcraft_color::{BlendMode, blend_pixel, hsl_to_rgb, luminance, rgb_to_hsl};
|
||||
@@ -69,7 +69,7 @@ fn blend(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
|
||||
// ---------------------------------------------------------------- Calculations
|
||||
|
||||
/// Blending modes offered by Calculations / CC Composite (menu order).
|
||||
/// Blending modes offered by Calculations / Source Composite (menu order).
|
||||
const CALC_MODES: [BlendMode; 22] = [
|
||||
BlendMode::Normal,
|
||||
BlendMode::Darken,
|
||||
@@ -150,7 +150,7 @@ fn calculations(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Composite
|
||||
// ---------------------------------------------------------------- Source Composite
|
||||
|
||||
const CC_COMPOSITE_MODES: [&str; 16] = [
|
||||
"In Front",
|
||||
@@ -321,7 +321,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.channel.cccomposite",
|
||||
"CC Composite",
|
||||
"Source Composite",
|
||||
vec![
|
||||
p("opacity", "Opacity", num(100.0), pct()),
|
||||
p("compositeOriginal", "Composite Original", Value::Enum(0), popup(&CC_COMPOSITE_MODES)),
|
||||
|
||||
@@ -878,7 +878,7 @@ fn broadcast_colors(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// CC Toner, CC Color Offset, CC Kernel
|
||||
// Multi-Tone Tint, Channel Offset, Convolution Kernel
|
||||
|
||||
fn cc_toner(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let g = |id: &str| {
|
||||
@@ -1101,7 +1101,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.color.cctoner",
|
||||
"CC Toner",
|
||||
"Multi-Tone Tint",
|
||||
vec![
|
||||
p("tones", "Tones", Value::Enum(1), popup(&["Duotone", "Tritone", "Pentone"])),
|
||||
p("highlights", "Highlights", col(1.0, 1.0, 1.0), ParamUi::Color),
|
||||
@@ -1115,7 +1115,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.color.cccoloroffset",
|
||||
"CC Color Offset",
|
||||
"Channel Offset",
|
||||
vec![
|
||||
p("redPhase", "Red Phase", num(0.0), ParamUi::Angle),
|
||||
p("greenPhase", "Green Phase", num(0.0), ParamUi::Angle),
|
||||
@@ -1124,7 +1124,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
],
|
||||
cc_color_offset,
|
||||
),
|
||||
spec("ec.color.cckernel", "CC Kernel", k_params, cc_kernel),
|
||||
spec("ec.color.cckernel", "Convolution Kernel", k_params, cc_kernel),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Color Correction effects, batch 3: Change Color, Video Limiter, CC Color Neutralizer,
|
||||
//! PS Arbitrary Map and Lumetri Color (Basic Correction, Creative, Curves, Color Wheels,
|
||||
//! Color Correction effects, batch 3: Change Color, Video Limiter, Color Neutralizer,
|
||||
//! PS Arbitrary Map and Color Grading (Basic Correction, Creative, Curves, Color Wheels,
|
||||
//! Vignette).
|
||||
|
||||
use effectcraft_color::{hsl_to_rgb, luminance, rgb_to_hsl};
|
||||
@@ -154,7 +154,7 @@ fn video_limiter(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Color Neutralizer
|
||||
// ---------------------------------------------------------------- Color Neutralizer
|
||||
|
||||
fn color_neutralizer(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let pairs = [("shadowsUnbalance", "shadowsBalance"), ("midtonesUnbalance", "midtonesBalance"), ("highlightsUnbalance", "highlightsBalance")];
|
||||
@@ -225,7 +225,7 @@ fn arbitrary_map(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- Lumetri Color
|
||||
// ---------------------------------------------------------------- Color Grading
|
||||
|
||||
/// Smooth tone-curve adjustment: offsets for shadows/midtones/highlights (each -1..1), with the
|
||||
/// end points fixed.
|
||||
@@ -431,7 +431,7 @@ impl HslKey {
|
||||
}
|
||||
}
|
||||
|
||||
/// Lumetri Color: Basic Correction (input LUT, white balance, HDR range, tone, saturation),
|
||||
/// Color Grading: Basic Correction (input LUT, white balance, HDR range, tone, saturation),
|
||||
/// Creative (look, adjustments), Curves (tone sliders, RGB curves, hue/saturation curves),
|
||||
/// Color Wheels, HSL Secondary (key, refine, correction), Vignette, in that order.
|
||||
fn lumetri(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
@@ -834,7 +834,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.color.cccolorneutralizer",
|
||||
"CC Color Neutralizer",
|
||||
"Color Neutralizer",
|
||||
vec![
|
||||
p("shadowsUnbalance", "Shadows Unbalance", col(0.0, 0.0, 0.0), ParamUi::Color),
|
||||
p("shadowsBalance", "Shadows Balance", col(0.0, 0.0, 0.0), ParamUi::Color),
|
||||
@@ -860,7 +860,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
],
|
||||
arbitrary_map,
|
||||
),
|
||||
spec("ec.color.lumetri", "Lumetri Color", lum, lumetri),
|
||||
spec("ec.color.lumetri", "Color Grading", lum, lumetri),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
//! Display naming must not change file, command or script identities.
|
||||
use crate::{find, instantiate, lookup, name_matches};
|
||||
use effectcraft_project::build::Ids;
|
||||
|
||||
const RENAMED: &[(&str, &str, &str)] = &[
|
||||
("ec.sim.ccballaction", "CC Ball Action", "Ball Grid"),
|
||||
("ec.distort.ccbendit", "CC Bend It", "Two-Point Bend"),
|
||||
("ec.distort.ccbender", "CC Bender", "Flexible Bend"),
|
||||
("ec.distort.ccblobbylize", "CC Blobbylize", "Organic Displacement"),
|
||||
("ec.stylize.ccblockload", "CC Block Load", "Block Reveal"),
|
||||
("ec.sim.ccbubbles", "CC Bubbles", "Bubbles"),
|
||||
("ec.stylize.ccburnfilm", "CC Burn Film", "Film Burn"),
|
||||
("ec.color.cccolorneutralizer", "CC Color Neutralizer", "Color Neutralizer"),
|
||||
("ec.color.cccoloroffset", "CC Color Offset", "Channel Offset"),
|
||||
("ec.channel.cccomposite", "CC Composite", "Source Composite"),
|
||||
("ec.blur.cccross", "CC Cross Blur", "Cross Blur"),
|
||||
("ec.perspective.cccylinder", "CC Cylinder", "Cylinder Wrap"),
|
||||
("ec.sim.ccdrizzle", "CC Drizzle", "Water Ripples"),
|
||||
("ec.perspective.ccenvironment", "CC Environment", "Environment Map"),
|
||||
("ec.distort.ccflomotion", "CC Flo Motion", "Dual Lens Warp"),
|
||||
("ec.time.ccforcemotionblur", "CC Force Motion Blur", "Temporal Motion Blur"),
|
||||
("ec.stylize.ccglass", "CC Glass", "Glass Relief"),
|
||||
("ec.transition.ccglasswipe", "CC Glass Wipe", "Glass Wipe"),
|
||||
("ec.generate.ccgluegun", "CC Glue Gun", "Paint Beads"),
|
||||
("ec.transition.ccgridwipe", "CC Grid Wipe", "Grid Wipe"),
|
||||
("ec.distort.ccgriddler", "CC Griddler", "Tile Grid"),
|
||||
("ec.sim.cchair", "CC Hair", "Surface Fibers"),
|
||||
("ec.stylize.cchextile", "CC HexTile", "Hexagonal Tiles"),
|
||||
("ec.transition.ccimagewipe", "CC Image Wipe", "Luminance Image Wipe"),
|
||||
("ec.transition.ccjaws", "CC Jaws", "Serrated Wipe"),
|
||||
("ec.stylize.cckaleida", "CC Kaleida", "Kaleidoscope"),
|
||||
("ec.color.cckernel", "CC Kernel", "Convolution Kernel"),
|
||||
("ec.distort.cclens", "CC Lens", "Lens Distortion"),
|
||||
("ec.generate.cclightburst", "CC Light Burst 2.5", "Radial Light Burst"),
|
||||
("ec.generate.cclightrays", "CC Light Rays", "Light Rays"),
|
||||
("ec.generate.cclightsweep", "CC Light Sweep", "Light Sweep"),
|
||||
("ec.transition.cclightwipe", "CC Light Wipe", "Light Wipe"),
|
||||
("ec.transition.cclinesweep", "CC Line Sweep", "Line Sweep"),
|
||||
("ec.sim.ccmrmercury", "CC Mr. Mercury", "Liquid Particles"),
|
||||
("ec.stylize.ccmrsmoothie", "CC Mr. Smoothie", "Palette Map"),
|
||||
("ec.utility.ccoverbrights", "CC Overbrights", "Out-of-Range Display"),
|
||||
("ec.distort.ccpageturn", "CC Page Turn", "Page Curl"),
|
||||
("ec.sim.ccparticlesystems2", "CC Particle Systems II", "Particle Emitter 2D"),
|
||||
("ec.sim.ccparticleworld", "CC Particle World", "Particle Emitter 3D"),
|
||||
("ec.sim.ccpixelpolly", "CC Pixel Polly", "Pixel Shatter"),
|
||||
("ec.stylize.ccplastic", "CC Plastic", "Plastic Shading"),
|
||||
("ec.distort.ccpowerpin", "CC Power Pin", "Perspective Pin"),
|
||||
("ec.blur.ccradial", "CC Radial Blur", "Variable Radial Blur"),
|
||||
("ec.blur.ccradialfast", "CC Radial Fast Blur", "Fast Radial Blur"),
|
||||
("ec.transition.ccradialscalewipe", "CC Radial ScaleWipe", "Radial Scale Wipe"),
|
||||
("ec.sim.ccrainfall", "CC Rainfall", "Rainfall"),
|
||||
("ec.stylize.ccrepetile", "CC RepeTile", "Edge Tile Repeat"),
|
||||
("ec.distort.ccripplepulse", "CC Ripple Pulse", "Pulsed Ripple"),
|
||||
("ec.transition.ccscalewipe", "CC Scale Wipe", "Scale Wipe"),
|
||||
("ec.sim.ccscatterize", "CC Scatterize", "Pixel Scatter"),
|
||||
("ec.key.ccsimplewireremoval", "CC Simple Wire Removal", "Line Removal"),
|
||||
("ec.distort.ccslant", "CC Slant", "Slant"),
|
||||
("ec.distort.ccsmear", "CC Smear", "Directional Smear"),
|
||||
("ec.sim.ccsnowfall", "CC Snowfall", "Snowfall"),
|
||||
("ec.perspective.ccsphere", "CC Sphere", "Sphere Wrap"),
|
||||
("ec.distort.ccsplit", "CC Split", "Split Warp"),
|
||||
("ec.distort.ccsplit2", "CC Split 2", "Dual Split Warp"),
|
||||
("ec.perspective.ccspotlight", "CC Spotlight", "Surface Spotlight"),
|
||||
("ec.sim.ccstarburst", "CC Star Burst", "Starfield"),
|
||||
("ec.generate.ccthreads", "CC Threads", "Woven Threads"),
|
||||
("ec.stylize.ccthreshold", "CC Threshold", "Channel Threshold"),
|
||||
("ec.stylize.ccthresholdrgb", "CC Threshold RGB", "RGB Threshold"),
|
||||
("ec.distort.cctiler", "CC Tiler", "Scaled Tiles"),
|
||||
("ec.color.cctoner", "CC Toner", "Multi-Tone Tint"),
|
||||
("ec.transition.cctwister", "CC Twister", "Twist Wipe"),
|
||||
("ec.blur.ccvector", "CC Vector Blur", "Vector Blur"),
|
||||
("ec.stylize.ccvignette", "CC Vignette", "Vignette"),
|
||||
("ec.transition.ccwarpomatic", "CC WarpoMatic", "Warp Dissolve"),
|
||||
("ec.time.ccwidetime", "CC Wide Time", "Temporal Blend"),
|
||||
("ec.color.lumetri", "Lumetri Color", "Color Grading"),
|
||||
("ec.obsolete.mochashape", "Mocha shape", "Tracked Shape Matte"),
|
||||
("ec.keying.keylight", "Key Light", "Screen Color Key"),
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn descriptive_names_keep_every_legacy_lookup_and_search() {
|
||||
for &(id, old, new) in RENAMED {
|
||||
let spec = find(id).unwrap();
|
||||
assert_eq!(spec.name, new, "{id}");
|
||||
for query in [id.to_string(), old.to_string(), old.to_lowercase(), new.to_string()] {
|
||||
assert_eq!(lookup(&query).map(|s| s.id), Some(id), "{query}");
|
||||
}
|
||||
assert!(name_matches(spec, &old.to_lowercase()), "{old}");
|
||||
assert!(name_matches(spec, &new.to_lowercase()), "{new}");
|
||||
}
|
||||
for alias in ["Keylight", "Keylight (1.2)", "Key Light"] {
|
||||
assert_eq!(lookup(alias).map(|s| s.id), Some("ec.keying.keylight"));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn descriptive_display_names_do_not_collide() {
|
||||
let mut names = std::collections::HashSet::new();
|
||||
for spec in crate::registry() {
|
||||
assert!(names.insert(spec.name.to_lowercase()), "duplicate name {}", spec.name);
|
||||
let label = spec.name.to_lowercase();
|
||||
assert!(!label.starts_with("cc "), "{}", spec.name);
|
||||
for mark in ["lumetri", "mercury", "mocha", "keylight"] {
|
||||
assert!(!label.contains(mark), "{}", spec.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_instance_names_and_parameter_data_survive_refresh() {
|
||||
for &(id, old, _) in RENAMED {
|
||||
let spec = find(id).unwrap();
|
||||
for stored in [old.to_string(), format!("{old} 2"), "My custom instance".to_string()] {
|
||||
let mut next = 1;
|
||||
let mut ids = Ids(&mut next);
|
||||
let mut instance = instantiate(spec, &mut ids, &stored, [128.0, 72.0]);
|
||||
let before = serde_json::to_value(&instance).unwrap();
|
||||
crate::migrate::upgrade_instance(spec, &mut instance, &mut ids, [128.0, 72.0]);
|
||||
assert_eq!(instance.name, stored, "{id}: never rewrite a stored instance name");
|
||||
assert_eq!(serde_json::to_value(&instance).unwrap(), before, "{id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Distort effects, batch 2: Turbulent Displace, Displacement Map (self as map), Optics
|
||||
//! Compensation, Magnify, Mesh Warp, Bezier Warp, CC Bend It, CC Lens, CC Page Turn, CC Tiler,
|
||||
//! CC Griddler.
|
||||
//! Compensation, Magnify, Mesh Warp, Bezier Warp, Two-Point Bend, Lens Distortion, Page Curl, Scaled Tiles,
|
||||
//! Tile Grid.
|
||||
//!
|
||||
//! Mesh Warp and Bezier Warp share a grid rasteriser: a (nx+1)×(ny+1) grid of destination points
|
||||
//! and matching source points is split into triangles, bucketed per output row and filled
|
||||
@@ -550,7 +550,7 @@ pub fn bezier_grid(ctx: &EffectCtx, offset: [f64; 2], scale: f64) -> (usize, Vec
|
||||
(n, dest, srcp)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Bend It
|
||||
// ---------------------------------------------------------------- Two-Point Bend
|
||||
|
||||
fn bend_it(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let mut beta = ctx.params.f("bend").to_radians();
|
||||
@@ -606,7 +606,7 @@ fn bend_it(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Lens
|
||||
// ---------------------------------------------------------------- Lens Distortion
|
||||
|
||||
fn cc_lens(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = b.to_px(ctx.params.v2("center"));
|
||||
@@ -629,7 +629,7 @@ fn cc_lens(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Page Turn
|
||||
// ---------------------------------------------------------------- Page Curl
|
||||
|
||||
fn page_turn(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let f = b.to_px(ctx.params.v2("foldPosition"));
|
||||
@@ -679,7 +679,7 @@ fn page_turn(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Tiler / CC Griddler
|
||||
// ---------------------------------------------------------------- Scaled Tiles / Tile Grid
|
||||
|
||||
fn cc_tiler(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let s = (ctx.params.f("scale") / 100.0).max(0.001);
|
||||
@@ -829,7 +829,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccbendit",
|
||||
"CC Bend It",
|
||||
"Two-Point Bend",
|
||||
vec![
|
||||
p("bend", "Bend", num(0.0), ParamUi::Angle),
|
||||
p("start", "Start", pt(0.5, 0.2), ParamUi::Point),
|
||||
@@ -840,7 +840,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.cclens",
|
||||
"CC Lens",
|
||||
"Lens Distortion",
|
||||
vec![
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
p("size", "Size", num(50.0), slider(0.0, 400.0, 0.0, 200.0, 1)),
|
||||
@@ -850,7 +850,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccpageturn",
|
||||
"CC Page Turn",
|
||||
"Page Curl",
|
||||
vec![
|
||||
p("foldPosition", "Fold Position", pt(0.7, 0.7), ParamUi::Point),
|
||||
p("foldDirection", "Fold Direction", num(315.0), ParamUi::Angle),
|
||||
@@ -864,7 +864,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.cctiler",
|
||||
"CC Tiler",
|
||||
"Scaled Tiles",
|
||||
vec![
|
||||
p("scale", "Scale", num(50.0), slider(1.0, 10000.0, 1.0, 200.0, 1)),
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
@@ -874,7 +874,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccgriddler",
|
||||
"CC Griddler",
|
||||
"Tile Grid",
|
||||
vec![
|
||||
p("horizontalScale", "Horizontal Scale", num(100.0), slider(1.0, 1000.0, 1.0, 400.0, 1)),
|
||||
p("verticalScale", "Vertical Scale", num(100.0), slider(1.0, 1000.0, 1.0, 400.0, 1)),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Distort effects, batch 3: CC Bender, CC Blobbylize, CC Power Pin, CC Ripple Pulse, CC Slant,
|
||||
//! CC Smear, CC Split, CC Split 2, Smear and Reshape (mask driven), Twirl (Legacy), Warp (the
|
||||
//! Distort effects, batch 3: Flexible Bend, Organic Displacement, Perspective Pin, Pulsed Ripple, Slant,
|
||||
//! Directional Smear, Split Warp, Dual Split Warp, Smear and Reshape (mask driven), Twirl (Legacy), Warp (the
|
||||
//! fifteen warp styles) and Detail-preserving Upscale.
|
||||
//!
|
||||
//! All warps are inverse mapped: every output pixel finds the source point that lands on it.
|
||||
@@ -59,7 +59,7 @@ fn elastic_exp(i: u32) -> f64 {
|
||||
[1.0, 1.25, 1.5, 2.0, 2.5, 3.0, 3.5, 4.5][(i as usize).min(7)]
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Bender
|
||||
// ---------------------------------------------------------------- Flexible Bend
|
||||
|
||||
fn cc_bender(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let amount = ctx.params.f("amount") / 100.0;
|
||||
@@ -107,7 +107,7 @@ fn norm3(v: [f64; 3]) -> [f64; 3] {
|
||||
[v[0] / l, v[1] / l, v[2] / l]
|
||||
}
|
||||
|
||||
/// f32 normal/dot helpers for the CC Blobbylize lighting pass. The GPU kernel runs in f32;
|
||||
/// f32 normal/dot helpers for the Organic Displacement lighting pass. The GPU kernel runs in f32;
|
||||
/// matching its precision here keeps specular highlights within the CPU/GPU parity tolerance.
|
||||
fn norm3f(v: [f32; 3]) -> [f32; 3] {
|
||||
let l = (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]).sqrt().max(1e-12);
|
||||
@@ -118,7 +118,7 @@ fn dot3f(a: [f32; 3], b: [f32; 3]) -> f32 {
|
||||
a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Blobbylize
|
||||
// ---------------------------------------------------------------- Organic Displacement
|
||||
|
||||
fn cc_blobbylize(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let soft = ctx.params.f("softness").max(0.0) * b.scale;
|
||||
@@ -221,7 +221,7 @@ fn cc_blobbylize(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Power Pin
|
||||
// ---------------------------------------------------------------- Perspective Pin
|
||||
|
||||
fn cc_power_pin(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let (lw, lh) = (ctx.layer_size[0].max(1.0), ctx.layer_size[1].max(1.0));
|
||||
@@ -304,7 +304,7 @@ fn cc_power_pin(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Ripple Pulse
|
||||
// ---------------------------------------------------------------- Pulsed Ripple
|
||||
|
||||
fn cc_ripple_pulse(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let level = ctx.params.f("pulseLevel") / 100.0;
|
||||
@@ -350,7 +350,7 @@ fn cc_ripple_pulse(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Slant
|
||||
// ---------------------------------------------------------------- Slant
|
||||
|
||||
fn cc_slant(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let k = ctx.params.f("slant") / 100.0;
|
||||
@@ -375,7 +375,7 @@ fn cc_slant(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Smear
|
||||
// ---------------------------------------------------------------- Directional Smear
|
||||
|
||||
fn cc_smear(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let reach = ctx.params.f("reach") / 100.0;
|
||||
@@ -403,7 +403,7 @@ fn cc_smear(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
}
|
||||
|
||||
/// The transparent pixels to add on every side of a buffer `size` pixels big (with `offset` and
|
||||
/// `scale`) for CC Smear: it moves pixels by up to Reach × From→To, and they may move out to the
|
||||
/// `scale`) for Directional Smear: it moves pixels by up to Reach × From→To, and they may move out to the
|
||||
/// layer bounds. A text or shape layer's buffer ends at its content while its bounds are
|
||||
/// comp-sized, so the smear was cut off at the content's box (#659).
|
||||
pub fn cc_smear_pad(ctx: &EffectCtx, size: [u32; 2], offset: [f64; 2], scale: f64) -> u32 {
|
||||
@@ -417,7 +417,7 @@ pub fn cc_smear_pad(ctx: &EffectCtx, size: [u32; 2], offset: [f64; 2], scale: f6
|
||||
(moved.min(4096.0) as u32).min(crate::util::layer_cover_pad(ctx, size, offset, scale))
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Split / CC Split 2
|
||||
// ---------------------------------------------------------------- Split Warp / Dual Split Warp
|
||||
|
||||
fn split_impl(ctx: &EffectCtx, mut b: Buf, s1: f64, s2: f64) -> Buf {
|
||||
if s1 == 0.0 && s2 == 0.0 {
|
||||
@@ -913,7 +913,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![
|
||||
spec(
|
||||
"ec.distort.ccbender",
|
||||
"CC Bender",
|
||||
"Flexible Bend",
|
||||
vec![
|
||||
p("amount", "Amount", num(0.0), slider(-200.0, 200.0, -100.0, 100.0, 1)),
|
||||
p("style", "Style", Value::Enum(0), popup(&["Bend", "Marilyn", "Sharp", "Boxer"])),
|
||||
@@ -925,7 +925,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccblobbylize",
|
||||
"CC Blobbylize",
|
||||
"Organic Displacement",
|
||||
vec![
|
||||
p("blobLayer", "Blob Layer", Value::Layer(None), ParamUi::Layer),
|
||||
p("property", "Property", Value::Enum(0), popup(&crate::util::SRC_NAMES[..8])),
|
||||
@@ -947,7 +947,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccpowerpin",
|
||||
"CC Power Pin",
|
||||
"Perspective Pin",
|
||||
vec![
|
||||
p("topLeft", "Top Left", pt(0.0, 0.0), ParamUi::Point),
|
||||
p("topRight", "Top Right", pt(1.0, 0.0), ParamUi::Point),
|
||||
@@ -964,7 +964,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccripplepulse",
|
||||
"CC Ripple Pulse",
|
||||
"Pulsed Ripple",
|
||||
vec![
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
p("pulseLevel", "Pulse Level (animate)", num(0.0), slider(-1000.0, 1000.0, -100.0, 100.0, 1)),
|
||||
@@ -976,7 +976,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccslant",
|
||||
"CC Slant",
|
||||
"Slant",
|
||||
vec![
|
||||
p("slant", "Slant", num(0.0), slider(-1000.0, 1000.0, -100.0, 100.0, 1)),
|
||||
p("stretching", "Stretching", Value::Bool(false), ParamUi::Checkbox),
|
||||
@@ -987,7 +987,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccsmear",
|
||||
"CC Smear",
|
||||
"Directional Smear",
|
||||
vec![
|
||||
p("from", "From", pt(0.35, 0.5), ParamUi::Point),
|
||||
p("to", "To", pt(0.65, 0.5), ParamUi::Point),
|
||||
@@ -998,7 +998,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccsplit",
|
||||
"CC Split",
|
||||
"Split Warp",
|
||||
vec![
|
||||
p("pointA", "Point A", pt(0.25, 0.5), ParamUi::Point),
|
||||
p("pointB", "Point B", pt(0.75, 0.5), ParamUi::Point),
|
||||
@@ -1008,7 +1008,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.distort.ccsplit2",
|
||||
"CC Split 2",
|
||||
"Dual Split Warp",
|
||||
vec![
|
||||
p("pointA", "Point A", pt(0.25, 0.5), ParamUi::Point),
|
||||
p("pointB", "Point B", pt(0.75, 0.5), ParamUi::Point),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Distort: CC Flo Motion, Liquify and Rolling Shutter Repair.
|
||||
//! Distort: Dual Lens Warp, Liquify and Rolling Shutter Repair.
|
||||
//!
|
||||
//! * **CC Flo Motion** — two knots that pull the image toward themselves (positive amount) or
|
||||
//! * **Dual Lens Warp** — two knots that pull the image toward themselves (positive amount) or
|
||||
//! push it away (negative), with a falloff exponent, optional tiling and supersampled
|
||||
//! antialiasing.
|
||||
//! * **Liquify** — brush strokes build a displacement mesh (a grid of layer-space offsets). The
|
||||
@@ -32,7 +32,7 @@ fn spec(id: &'static str, name: &'static str, params: Vec<crate::ParamSpec>, ren
|
||||
EffectSpec { id, name, category: "Distort", params, render, gpu: false, float: true }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Flo Motion
|
||||
// ---------------------------------------------------------------- Dual Lens Warp
|
||||
|
||||
fn flo_motion(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let knots = [(ctx.params.v2("knot1"), ctx.params.f("amount1") / 100.0), (ctx.params.v2("knot2"), ctx.params.f("amount2") / 100.0)];
|
||||
@@ -560,7 +560,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![
|
||||
spec(
|
||||
"ec.distort.ccflomotion",
|
||||
"CC Flo Motion",
|
||||
"Dual Lens Warp",
|
||||
vec![
|
||||
p("knot1", "Knot 1", Value::Vec2([0.25, 0.5]), ParamUi::Point),
|
||||
p("amount1", "Amount 1", num(50.0), slider(-400.0, 100.0, -100.0, 100.0, 1)),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Generate effects, batch 2: Cell Pattern (Worley), Ellipse, Lens Flare, Beam, Radio Waves,
|
||||
//! Advanced Lightning, CC Light Rays, CC Light Burst 2.5, CC Light Sweep.
|
||||
//! Advanced Lightning, Light Rays, Radial Light Burst, Light Sweep.
|
||||
//!
|
||||
//! All designs are original procedural renderings written from the public descriptions of what
|
||||
//! each effect produces.
|
||||
@@ -897,7 +897,7 @@ fn advanced_lightning(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Light Rays / Burst
|
||||
// ---------------------------------------------------------------- Light Rays / Burst
|
||||
|
||||
const RAY_STEPS: usize = 32;
|
||||
|
||||
@@ -1007,7 +1007,7 @@ fn light_burst(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Light Sweep
|
||||
// ---------------------------------------------------------------- Light Sweep
|
||||
|
||||
fn light_sweep(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = b.to_px(ctx.params.v2("center"));
|
||||
@@ -1192,7 +1192,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.generate.cclightrays",
|
||||
"CC Light Rays",
|
||||
"Light Rays",
|
||||
vec![
|
||||
p("intensity", "Intensity", num(100.0), slider(0.0, 600.0, 0.0, 200.0, 1)),
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
@@ -1207,7 +1207,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.generate.cclightburst",
|
||||
"CC Light Burst 2.5",
|
||||
"Radial Light Burst",
|
||||
vec![
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
p("intensity", "Intensity", num(100.0), slider(0.0, 600.0, 0.0, 200.0, 1)),
|
||||
@@ -1220,7 +1220,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.generate.cclightsweep",
|
||||
"CC Light Sweep",
|
||||
"Light Sweep",
|
||||
vec![
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
p("direction", "Direction", num(-30.0), ang()),
|
||||
|
||||
@@ -180,7 +180,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.generate.ccgluegun",
|
||||
"CC Glue Gun",
|
||||
"Paint Beads",
|
||||
vec![
|
||||
p("brushPosition", "Brush Position", pt(0.5, 0.5), ParamUi::Point),
|
||||
p("strokeWidth", "Stroke Width", num(25.0), slider(0.0, 500.0, 0.0, 100.0, 1)),
|
||||
@@ -194,7 +194,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.generate.ccthreads",
|
||||
"CC Threads",
|
||||
"Woven Threads",
|
||||
vec![
|
||||
p("width", "Width", num(50.0), slider(1.0, 1000.0, 1.0, 200.0, 1)),
|
||||
p("height", "Height", num(50.0), slider(1.0, 1000.0, 1.0, 200.0, 1)),
|
||||
|
||||
@@ -317,7 +317,7 @@ fn unmult(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Simple Wire Removal
|
||||
// ---------------------------------------------------------------- Line Removal
|
||||
|
||||
fn wire_removal(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let pa = ctx.params.v2("pointA");
|
||||
@@ -464,7 +464,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.key.ccsimplewireremoval",
|
||||
"CC Simple Wire Removal",
|
||||
"Line Removal",
|
||||
vec![
|
||||
p("pointA", "Point A", Value::Vec2([0.25, 0.25]), ParamUi::Point),
|
||||
p("pointB", "Point B", Value::Vec2([0.75, 0.75]), ParamUi::Point),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Key Light — a full screen-colour keyer with the controls of After Effects' bundled
|
||||
//! Screen Color Key — a full screen-colour keyer with the controls of After Effects' bundled
|
||||
//! "Keylight (1.2)" (that name is a trademark of its vendor, so the effect is registered as
|
||||
//! **Key Light**; `lookup("Keylight (1.2)")` finds it through [`KEYLIGHT_ALIASES`]).
|
||||
//! **Screen Color Key**; `lookup("Keylight (1.2)")` finds it through [`KEYLIGHT_ALIASES`]).
|
||||
//!
|
||||
//! The method is the textbook *screen difference* key, written from the public description of
|
||||
//! the controls:
|
||||
@@ -31,7 +31,7 @@ use crate::util::{Plane, gauss_plane, morph_frac, point_in_poly, premul, unpremu
|
||||
use crate::{Buf, EffectCtx, EffectSpec, col, num, p, popup, slider};
|
||||
|
||||
/// Other names the effect answers to in [`crate::lookup`].
|
||||
pub const KEYLIGHT_ALIASES: &[&str] = &["Keylight (1.2)", "Keylight"];
|
||||
pub const KEYLIGHT_ALIASES: &[&str] = &["Keylight (1.2)", "Keylight", "Key Light"];
|
||||
|
||||
pub const VIEWS: [&str; 11] = [
|
||||
"Source",
|
||||
@@ -463,7 +463,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
let cc = |id: &'static str, name: &'static str| p(id, name, num(0.0), slider(-100.0, 100.0, -100.0, 100.0, 1));
|
||||
vec![EffectSpec {
|
||||
id: "ec.keying.keylight",
|
||||
name: "Key Light",
|
||||
name: "Screen Color Key",
|
||||
category: "Keying",
|
||||
params: vec![
|
||||
p("view", "View", Value::Enum(10), popup(&VIEWS)),
|
||||
@@ -622,7 +622,7 @@ mod tests {
|
||||
let spec = crate::find("ec.keying.keylight").unwrap();
|
||||
let mut next = 1;
|
||||
let mut ids = Ids(&mut next);
|
||||
let mut g = crate::instantiate(spec, &mut ids, "Key Light", [10.0, 10.0]);
|
||||
let mut g = crate::instantiate(spec, &mut ids, "Screen Color Key", [10.0, 10.0]);
|
||||
// Flatten it the way older versions saved it.
|
||||
let mut flat = vec![];
|
||||
g.walk_mut(&mut |p| flat.push(p.clone()));
|
||||
|
||||
@@ -23,6 +23,8 @@ mod color3;
|
||||
mod color_fx;
|
||||
pub mod controls;
|
||||
pub mod crypto_select;
|
||||
#[cfg(test)]
|
||||
mod display_names;
|
||||
mod distort;
|
||||
mod distort2;
|
||||
mod distort3;
|
||||
@@ -36,6 +38,7 @@ mod keying;
|
||||
mod keying2;
|
||||
pub mod keylight;
|
||||
mod matte;
|
||||
|
||||
pub mod migrate;
|
||||
mod misc;
|
||||
pub mod mocha_shape;
|
||||
@@ -560,7 +563,7 @@ pub trait EffectHost: Sync {
|
||||
}
|
||||
/// Parameter `id` (a [`flatten_params`] id such as `birthRate`) of effect `effect_index` in
|
||||
/// the layer's stack (the running effect's [`EffectEnv::effect_index`]) at another **layer
|
||||
/// time**: CC Particle World samples its Birth Rate at every step it simulates (#1373).
|
||||
/// time**: Particle Emitter 3D samples its Birth Rate at every step it simulates (#1373).
|
||||
/// `None` when unavailable.
|
||||
fn param_at(&self, _effect_index: usize, _id: &str, _layer_time: f64) -> Option<Value> {
|
||||
None
|
||||
@@ -776,8 +779,82 @@ pub fn categories() -> Vec<&'static str> {
|
||||
v
|
||||
}
|
||||
|
||||
/// After Effects' third-party display names of effects we register under a generic name.
|
||||
const ALIASES: &[(&str, &[&str])] = &[("ec.keying.keylight", keylight::KEYLIGHT_ALIASES)];
|
||||
/// Legacy display names accepted for saved scripts and searches. Never display these as
|
||||
/// native feature names; stable effect IDs and external format match names stay unchanged.
|
||||
const ALIASES: &[(&str, &[&str])] = &[
|
||||
("ec.sim.ccballaction", &["CC Ball Action"]),
|
||||
("ec.distort.ccbendit", &["CC Bend It"]),
|
||||
("ec.distort.ccbender", &["CC Bender"]),
|
||||
("ec.distort.ccblobbylize", &["CC Blobbylize"]),
|
||||
("ec.stylize.ccblockload", &["CC Block Load"]),
|
||||
("ec.sim.ccbubbles", &["CC Bubbles"]),
|
||||
("ec.stylize.ccburnfilm", &["CC Burn Film"]),
|
||||
("ec.color.cccolorneutralizer", &["CC Color Neutralizer"]),
|
||||
("ec.color.cccoloroffset", &["CC Color Offset"]),
|
||||
("ec.channel.cccomposite", &["CC Composite"]),
|
||||
("ec.blur.cccross", &["CC Cross Blur"]),
|
||||
("ec.perspective.cccylinder", &["CC Cylinder"]),
|
||||
("ec.sim.ccdrizzle", &["CC Drizzle"]),
|
||||
("ec.perspective.ccenvironment", &["CC Environment"]),
|
||||
("ec.distort.ccflomotion", &["CC Flo Motion"]),
|
||||
("ec.time.ccforcemotionblur", &["CC Force Motion Blur"]),
|
||||
("ec.stylize.ccglass", &["CC Glass"]),
|
||||
("ec.transition.ccglasswipe", &["CC Glass Wipe"]),
|
||||
("ec.generate.ccgluegun", &["CC Glue Gun"]),
|
||||
("ec.transition.ccgridwipe", &["CC Grid Wipe"]),
|
||||
("ec.distort.ccgriddler", &["CC Griddler"]),
|
||||
("ec.sim.cchair", &["CC Hair"]),
|
||||
("ec.stylize.cchextile", &["CC HexTile"]),
|
||||
("ec.transition.ccimagewipe", &["CC Image Wipe"]),
|
||||
("ec.transition.ccjaws", &["CC Jaws"]),
|
||||
("ec.stylize.cckaleida", &["CC Kaleida"]),
|
||||
("ec.color.cckernel", &["CC Kernel"]),
|
||||
("ec.distort.cclens", &["CC Lens"]),
|
||||
("ec.generate.cclightburst", &["CC Light Burst 2.5"]),
|
||||
("ec.generate.cclightrays", &["CC Light Rays"]),
|
||||
("ec.generate.cclightsweep", &["CC Light Sweep"]),
|
||||
("ec.transition.cclightwipe", &["CC Light Wipe"]),
|
||||
("ec.transition.cclinesweep", &["CC Line Sweep"]),
|
||||
("ec.sim.ccmrmercury", &["CC Mr. Mercury"]),
|
||||
("ec.stylize.ccmrsmoothie", &["CC Mr. Smoothie"]),
|
||||
("ec.utility.ccoverbrights", &["CC Overbrights"]),
|
||||
("ec.distort.ccpageturn", &["CC Page Turn"]),
|
||||
("ec.sim.ccparticlesystems2", &["CC Particle Systems II"]),
|
||||
("ec.sim.ccparticleworld", &["CC Particle World"]),
|
||||
("ec.sim.ccpixelpolly", &["CC Pixel Polly"]),
|
||||
("ec.stylize.ccplastic", &["CC Plastic"]),
|
||||
("ec.distort.ccpowerpin", &["CC Power Pin"]),
|
||||
("ec.blur.ccradial", &["CC Radial Blur"]),
|
||||
("ec.blur.ccradialfast", &["CC Radial Fast Blur"]),
|
||||
("ec.transition.ccradialscalewipe", &["CC Radial ScaleWipe"]),
|
||||
("ec.sim.ccrainfall", &["CC Rainfall"]),
|
||||
("ec.stylize.ccrepetile", &["CC RepeTile"]),
|
||||
("ec.distort.ccripplepulse", &["CC Ripple Pulse"]),
|
||||
("ec.transition.ccscalewipe", &["CC Scale Wipe"]),
|
||||
("ec.sim.ccscatterize", &["CC Scatterize"]),
|
||||
("ec.key.ccsimplewireremoval", &["CC Simple Wire Removal"]),
|
||||
("ec.distort.ccslant", &["CC Slant"]),
|
||||
("ec.distort.ccsmear", &["CC Smear"]),
|
||||
("ec.sim.ccsnowfall", &["CC Snowfall"]),
|
||||
("ec.perspective.ccsphere", &["CC Sphere"]),
|
||||
("ec.distort.ccsplit", &["CC Split"]),
|
||||
("ec.distort.ccsplit2", &["CC Split 2"]),
|
||||
("ec.perspective.ccspotlight", &["CC Spotlight"]),
|
||||
("ec.sim.ccstarburst", &["CC Star Burst"]),
|
||||
("ec.generate.ccthreads", &["CC Threads"]),
|
||||
("ec.stylize.ccthreshold", &["CC Threshold"]),
|
||||
("ec.stylize.ccthresholdrgb", &["CC Threshold RGB"]),
|
||||
("ec.distort.cctiler", &["CC Tiler"]),
|
||||
("ec.color.cctoner", &["CC Toner"]),
|
||||
("ec.transition.cctwister", &["CC Twister"]),
|
||||
("ec.blur.ccvector", &["CC Vector Blur"]),
|
||||
("ec.stylize.ccvignette", &["CC Vignette"]),
|
||||
("ec.transition.ccwarpomatic", &["CC WarpoMatic"]),
|
||||
("ec.time.ccwidetime", &["CC Wide Time"]),
|
||||
("ec.color.lumetri", &["Lumetri Color"]),
|
||||
("ec.obsolete.mochashape", &["Mocha shape", "mocha shape"]),
|
||||
("ec.keying.keylight", keylight::KEYLIGHT_ALIASES),
|
||||
];
|
||||
|
||||
/// Other names effect `id` answers to (in [`lookup`] and searches).
|
||||
pub fn aliases(id: &str) -> &'static [&'static str] {
|
||||
@@ -861,7 +938,7 @@ pub fn instantiate(spec: &EffectSpec, ids: &mut Ids, instance_name: &str, layer_
|
||||
/// effects without their own table.
|
||||
pub const PARAM_GROUPS: &[(&str, &str)] = &[
|
||||
// Color Correction: Exposure, Levels (Individual Controls), Change to Color, Colorama,
|
||||
// Shadow/Highlight, Lumetri Color.
|
||||
// Shadow/Highlight, Color Grading.
|
||||
("master", "Master"),
|
||||
("rgb", "RGB"),
|
||||
("red", "Red"),
|
||||
@@ -990,7 +1067,7 @@ pub const PARAM_GROUPS: &[(&str, &str)] = &[
|
||||
("particleExploder", "Particle Exploder"),
|
||||
("affects", "Affects"),
|
||||
("options", "Options"),
|
||||
// Keying, Matte, Obsolete (Key Light's groups are in `keylight::GROUPS`).
|
||||
// Keying, Matte, Obsolete (Screen Color Key's groups are in `keylight::GROUPS`).
|
||||
("ultraSettings", "Ultra Settings"),
|
||||
("additionalForeground", "Additional Foreground"),
|
||||
("additionalBackground", "Additional Background"),
|
||||
@@ -1075,7 +1152,7 @@ fn nested_group<'a>(g: &'a mut PropGroup, ids: &mut Ids, path: &str) -> Option<&
|
||||
}
|
||||
|
||||
/// Effects the GPU compositor (`effectcraft-gpu`) implements with the CPU effect's semantics
|
||||
/// (Mercury GPU Acceleration; the Effects & Presets GPU badge). Expression controls are
|
||||
/// (GPU Acceleration; the Effects & Presets GPU badge). Expression controls are
|
||||
/// pass-throughs and count as GPU effects too.
|
||||
pub const GPU_EFFECTS: &[&str] = &[
|
||||
"ec.blur.gaussian",
|
||||
@@ -1495,7 +1572,7 @@ mod tests {
|
||||
assert_eq!(grow_sides(lo, hi, 20, 10), Some([0, 0, 30, 20]));
|
||||
}
|
||||
|
||||
/// #2261: a 20 × 20 layer with CC Radial Fast Blur's Center far away grows to at most 16 Mpx;
|
||||
/// #2261: a 20 × 20 layer with Fast Radial Blur's Center far away grows to at most 16 Mpx;
|
||||
/// big layers may still grow to four times their area, and small pads are untouched.
|
||||
#[test]
|
||||
fn padded_buffers_stay_within_the_budget() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Matte ▸ Mocha shape: renders planar-tracked roto shapes as a matte.
|
||||
//! Matte ▸ Tracked Shape Matte: renders planar-tracked roto shapes as a matte.
|
||||
//!
|
||||
//! Mocha's own clipboard / export formats are not publicly specified, so the effect reads shape
|
||||
//! data in a small documented JSON format of ours (in the hidden `shapeData` parameter, either the
|
||||
@@ -184,7 +184,7 @@ fn mocha_shape(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![EffectSpec {
|
||||
id: "ec.obsolete.mochashape",
|
||||
name: "Mocha shape",
|
||||
name: "Tracked Shape Matte",
|
||||
category: "Matte",
|
||||
params: vec![
|
||||
p("blendMode", "Blend mode", Value::Enum(0), popup(&["Add", "Subtract", "Intersect", "Difference"])),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Perspective effects (batch 2): Bevel Alpha, Bevel Edges, Radial Shadow, CC Cylinder,
|
||||
//! CC Sphere and CC Spotlight.
|
||||
//! Perspective effects (batch 2): Bevel Alpha, Bevel Edges, Radial Shadow, Cylinder Wrap,
|
||||
//! Sphere Wrap and Surface Spotlight.
|
||||
//!
|
||||
//! Angles follow the convention used by Drop Shadow: measured clockwise from "up", so a light
|
||||
//! angle `a` sits in the direction `(sin a, -cos a)` (y grows downwards). 3D vectors use x right,
|
||||
@@ -158,7 +158,7 @@ fn radial_shadow(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
/// Phong-style shading shared by CC Cylinder and CC Sphere.
|
||||
/// Phong-style shading shared by Cylinder Wrap and Sphere Wrap.
|
||||
struct Shading {
|
||||
l: [f64; 3],
|
||||
color: [f32; 4],
|
||||
@@ -451,11 +451,11 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
],
|
||||
radial_shadow,
|
||||
),
|
||||
spec("ec.perspective.cccylinder", "CC Cylinder", cyl, cylinder),
|
||||
spec("ec.perspective.ccsphere", "CC Sphere", sph, sphere),
|
||||
spec("ec.perspective.cccylinder", "Cylinder Wrap", cyl, cylinder),
|
||||
spec("ec.perspective.ccsphere", "Sphere Wrap", sph, sphere),
|
||||
spec(
|
||||
"ec.perspective.ccspotlight",
|
||||
"CC Spotlight",
|
||||
"Surface Spotlight",
|
||||
vec![
|
||||
p("from", "From", pt(0.3, 0.2), ParamUi::Point),
|
||||
p("to", "To", pt(0.5, 0.5), ParamUi::Point),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Perspective effects, batch 2: CC Environment (reflection mapping of an environment layer
|
||||
//! Perspective effects, batch 2: Environment Map (reflection mapping of an environment layer
|
||||
//! onto the layer's luminance/alpha relief) and 3D Glasses (stereo pairs and anaglyphs from a
|
||||
//! left and right view layer).
|
||||
|
||||
@@ -17,7 +17,7 @@ fn spec(id: &'static str, name: &'static str, params: Vec<crate::ParamSpec>, ren
|
||||
EffectSpec { id, name, category: "Perspective", params, render, gpu: false, float: true }
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Environment
|
||||
// ---------------------------------------------------------------- Environment Map
|
||||
|
||||
/// Environment direction (x right, y down, z towards the viewer) → normalised map coordinates.
|
||||
fn env_uv(mapping: u32, r: [f64; 3]) -> (f64, f64) {
|
||||
@@ -194,7 +194,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![
|
||||
spec(
|
||||
"ec.perspective.ccenvironment",
|
||||
"CC Environment",
|
||||
"Environment Map",
|
||||
vec![
|
||||
p("environment", "Environment", Value::Layer(None), ParamUi::Layer),
|
||||
p("mapping", "Mapping", Value::Enum(0), popup(&["Spherical", "Probe", "Vertical Cross"])),
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![
|
||||
spec(
|
||||
"ec.sim.ccrainfall",
|
||||
"CC Rainfall",
|
||||
"Rainfall",
|
||||
vec![
|
||||
p("drops", "Drops", num(5000.0), slider(0.0, 100_000.0, 0.0, 20_000.0, 0)),
|
||||
p("size", "Size", num(1.0), slider(0.0, 50.0, 0.0, 10.0, 2)),
|
||||
@@ -53,7 +53,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccsnowfall",
|
||||
"CC Snowfall",
|
||||
"Snowfall",
|
||||
vec![
|
||||
p("flakes", "Flakes", num(10_000.0), slider(0.0, 200_000.0, 0.0, 50_000.0, 0)),
|
||||
p("size", "Size", num(3.0), slider(0.0, 50.0, 0.0, 20.0, 2)),
|
||||
@@ -79,7 +79,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccbubbles",
|
||||
"CC Bubbles",
|
||||
"Bubbles",
|
||||
vec![
|
||||
p("bubbleAmount", "Bubble Amount", num(100.0), slider(0.0, 10_000.0, 0.0, 1000.0, 0)),
|
||||
p("bubbleSpeed", "Bubble Speed", num(0.5), slider(-10.0, 10.0, -2.0, 2.0, 2)),
|
||||
@@ -93,7 +93,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccdrizzle",
|
||||
"CC Drizzle",
|
||||
"Water Ripples",
|
||||
vec![
|
||||
p("dripRate", "Drip Rate", num(10.0), slider(0.0, 200.0, 0.0, 50.0, 2)),
|
||||
p("longevity", "Longevity (sec)", num(1.0), slider(0.0, 30.0, 0.0, 5.0, 2)),
|
||||
@@ -114,7 +114,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccstarburst",
|
||||
"CC Star Burst",
|
||||
"Starfield",
|
||||
vec![
|
||||
p("scatter", "Scatter", num(100.0), slider(0.0, 1000.0, 0.0, 300.0, 1)),
|
||||
p("speed", "Speed", num(1.0), slider(-10.0, 10.0, -4.0, 4.0, 2)),
|
||||
@@ -127,7 +127,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccparticleworld",
|
||||
"CC Particle World",
|
||||
"Particle Emitter 3D",
|
||||
vec![
|
||||
p("birthRate", "Birth Rate", num(0.5), slider(0.0, 100.0, 0.0, 10.0, 2)),
|
||||
p("longevity", "Longevity (sec)", num(1.0), slider(0.0, 100.0, 0.0, 10.0, 2)),
|
||||
@@ -170,7 +170,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccparticlesystems2",
|
||||
"CC Particle Systems II",
|
||||
"Particle Emitter 2D",
|
||||
vec![
|
||||
p("birthRate", "Birth Rate", num(2.0), slider(0.0, 100.0, 0.0, 20.0, 2)),
|
||||
p("longevity", "Longevity (sec)", num(1.0), slider(0.0, 100.0, 0.0, 10.0, 2)),
|
||||
@@ -198,7 +198,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccmrmercury",
|
||||
"CC Mr. Mercury",
|
||||
"Liquid Particles",
|
||||
vec![
|
||||
p("radiusX", "Radius X", num(50.0), slider(0.0, 2000.0, 0.0, 300.0, 1)),
|
||||
p("radiusY", "Radius Y", num(50.0), slider(0.0, 2000.0, 0.0, 300.0, 1)),
|
||||
|
||||
@@ -79,7 +79,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![
|
||||
spec(
|
||||
"ec.sim.ccballaction",
|
||||
"CC Ball Action",
|
||||
"Ball Grid",
|
||||
vec![
|
||||
p("scatter", "Scatter", num(0.0), slider(0.0, 2000.0, 0.0, 300.0, 1)),
|
||||
p("rotationAxis", "Rotation Axis", Value::Enum(0), popup(&["X Axis", "Y Axis", "Z Axis", "XY Axis", "XZ Axis", "YZ Axis", "XYZ Axis"])),
|
||||
@@ -94,7 +94,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccpixelpolly",
|
||||
"CC Pixel Polly",
|
||||
"Pixel Shatter",
|
||||
vec![
|
||||
p("force", "Force", num(100.0), slider(-1000.0, 1000.0, -300.0, 300.0, 1)),
|
||||
p("gravity", "Gravity", num(1.0), slider(-20.0, 20.0, -5.0, 5.0, 2)),
|
||||
@@ -111,7 +111,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.sim.ccscatterize",
|
||||
"CC Scatterize",
|
||||
"Pixel Scatter",
|
||||
vec![
|
||||
p("scatter", "Scatter", num(0.0), slider(0.0, 1000.0, 0.0, 200.0, 1)),
|
||||
p("rightTwist", "Right Twist", num(0.0), ParamUi::Angle),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Simulation: Particle Playground and CC Hair.
|
||||
//! Simulation: Particle Playground and Surface Fibers.
|
||||
//!
|
||||
//! **Particle Playground** is a deterministic 2D particle system stepped from layer time 0 at
|
||||
//! [`SPS`] steps per second through [`SimCache`] (seeking anywhere gives the same frame as
|
||||
@@ -17,7 +17,7 @@
|
||||
//! being rendered (their pixels are part of the cache key). Particles replace the layer's own
|
||||
//! pixels, as in After Effects.
|
||||
//!
|
||||
//! **CC Hair** grows strands from the layer's opaque pixels (Density per 1 000 px²), each a
|
||||
//! **Surface Fibers** grows strands from the layer's opaque pixels (Density per 1 000 px²), each a
|
||||
//! quadratic curve of Length that droops with Weight, optionally steered and scaled by a hairfall
|
||||
//! map layer (luminance → length, horizontal/vertical gradient → lean), and shades them with a
|
||||
//! Kajiya–Kay-style strand model (diffuse ∝ sin(tangent, light), specular from the half vector).
|
||||
@@ -934,7 +934,7 @@ impl PgPlan {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Hair
|
||||
// ---------------------------------------------------------------- Surface Fibers
|
||||
|
||||
fn cc_hair(ctx: &EffectCtx, b: Buf) -> Buf {
|
||||
let Some(mut plan) = hair_plan(ctx, &b) else { return b };
|
||||
@@ -942,7 +942,7 @@ fn cc_hair(ctx: &EffectCtx, b: Buf) -> Buf {
|
||||
plan.finish(b)
|
||||
}
|
||||
|
||||
/// CC Hair's strands as line sprites (each coloured from its root, see [`Tint::Root`]);
|
||||
/// Surface Fibers's strands as line sprites (each coloured from its root, see [`Tint::Root`]);
|
||||
/// `None` = no hair (the layer passes through).
|
||||
pub(crate) fn hair_plan(ctx: &EffectCtx, b: &Buf) -> Option<SpritePlan> {
|
||||
let pr = ctx.params;
|
||||
@@ -1144,7 +1144,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
spec("ec.sim.particleplayground", "Particle Playground", pg, particle_playground),
|
||||
spec(
|
||||
"ec.sim.cchair",
|
||||
"CC Hair",
|
||||
"Surface Fibers",
|
||||
vec![
|
||||
sp("length", "Length", px(30.0, 200.0)),
|
||||
p("thickness", "Thickness", num(1.0), slider(0.05, 20.0, 0.1, 5.0, 2)),
|
||||
|
||||
@@ -343,7 +343,7 @@ fn brush_strokes(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---- CC Kaleida ----
|
||||
// ---- Kaleidoscope ----
|
||||
|
||||
fn kaleida(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = b.to_px(ctx.params.v2("center"));
|
||||
@@ -368,7 +368,7 @@ fn kaleida(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---- CC RepeTile ----
|
||||
// ---- Edge Tile Repeat ----
|
||||
|
||||
#[inline]
|
||||
fn tile_coord(v: f64, size: f64) -> (i64, f64) {
|
||||
@@ -491,7 +491,7 @@ fn color_emboss(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---- CC Vignette ----
|
||||
// ---- Vignette ----
|
||||
|
||||
fn vignette(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let amt = ctx.params.f("amount") as f32 / 100.0;
|
||||
@@ -523,7 +523,7 @@ fn vignette(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ---- CC Threshold / CC Threshold RGB ----
|
||||
// ---- Channel Threshold / RGB Threshold ----
|
||||
|
||||
fn cc_threshold(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let t = ctx.params.f("threshold") as f32 / 255.0;
|
||||
@@ -669,7 +669,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.stylize.cckaleida",
|
||||
"CC Kaleida",
|
||||
"Kaleidoscope",
|
||||
vec![
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
p("size", "Size", num(100.0), slider(1.0, 1000.0, 1.0, 400.0, 1)),
|
||||
@@ -680,7 +680,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.stylize.ccrepetile",
|
||||
"CC RepeTile",
|
||||
"Edge Tile Repeat",
|
||||
vec![
|
||||
p("expandRight", "Expand Right", num(0.0), slider(0.0, 4000.0, 0.0, 500.0, 0)),
|
||||
p("expandLeft", "Expand Left", num(0.0), slider(0.0, 4000.0, 0.0, 500.0, 0)),
|
||||
@@ -718,7 +718,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.stylize.ccvignette",
|
||||
"CC Vignette",
|
||||
"Vignette",
|
||||
vec![
|
||||
p("amount", "Amount", num(50.0), slider(-100.0, 100.0, -100.0, 100.0, 1)),
|
||||
p("angleOfView", "Angle of View", num(60.0), slider(0.0, 179.0, 0.0, 179.0, 1)),
|
||||
@@ -729,7 +729,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.stylize.ccthreshold",
|
||||
"CC Threshold",
|
||||
"Channel Threshold",
|
||||
vec![
|
||||
p("threshold", "Threshold", num(127.0), thr()),
|
||||
p("channel", "Channel", Value::Enum(0), popup(&["Luminance", "RGB", "Saturation", "Alpha"])),
|
||||
@@ -740,7 +740,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.stylize.ccthresholdrgb",
|
||||
"CC Threshold RGB",
|
||||
"RGB Threshold",
|
||||
vec![
|
||||
p("redThreshold", "Red Threshold", num(127.0), thr()),
|
||||
p("greenThreshold", "Green Threshold", num(127.0), thr()),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Stylize effects, batch 3: CC Block Load, CC Burn Film, CC Glass, CC HexTile, CC Mr. Smoothie
|
||||
//! and CC Plastic.
|
||||
//! Stylize effects, batch 3: Block Reveal, Film Burn, Glass Relief, Hexagonal Tiles, Palette Map
|
||||
//! and Plastic Shading.
|
||||
//!
|
||||
//! Written from the public descriptions of what these effects do (progressive block loading,
|
||||
//! burning film, bump-mapped glass / plastic surfaces lit by an effect light, hexagonal tiling,
|
||||
@@ -27,7 +27,7 @@ fn pt(x: f64, y: f64) -> Value {
|
||||
Value::Vec2([x, y])
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC Block Load
|
||||
// ------------------------------------------------------------------ Block Reveal
|
||||
|
||||
/// Mean colour of every `s`×`s` block (grid of `ceil(w/s)`×`ceil(h/s)`).
|
||||
fn block_means(img: &Image, s: usize) -> (usize, usize, Vec<Px>) {
|
||||
@@ -135,7 +135,7 @@ fn block_load(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC Burn Film
|
||||
// ------------------------------------------------------------------ Film Burn
|
||||
|
||||
fn burn_film(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let burn = (ctx.params.f("burn") / 100.0).clamp(0.0, 1.0) as f32;
|
||||
@@ -180,7 +180,7 @@ fn burn_film(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
|
||||
const BUMP_PROPS: [&str; 6] = ["Red", "Green", "Blue", "Alpha", "Luminance", "Lightness"];
|
||||
|
||||
/// The bump-map layer parameter: CC Glass's Bump Map, CC Plastic's Bump Layer.
|
||||
/// The bump-map layer parameter: Glass Relief's Bump Map, Plastic Shading's Bump Layer.
|
||||
pub fn bump_layer_id(ctx: &EffectCtx) -> &'static str {
|
||||
if ctx.params.get("bumpLayer").is_some() { "bumpLayer" } else { "bumpMap" }
|
||||
}
|
||||
@@ -208,7 +208,7 @@ fn height_field(ctx: &EffectCtx, b: &Buf) -> Plane {
|
||||
pl
|
||||
}
|
||||
|
||||
/// The effect light and surface of CC Glass / CC Plastic (shared with the GPU compositor).
|
||||
/// The effect light and surface of Glass Relief / Plastic Shading (shared with the GPU compositor).
|
||||
pub struct BumpLight {
|
||||
pub intensity: f32,
|
||||
pub color: [f32; 3],
|
||||
@@ -342,7 +342,7 @@ fn plastic(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC HexTile
|
||||
// ------------------------------------------------------------------ Hexagonal Tiles
|
||||
|
||||
/// Axial hex cell (pointy-top) containing (x, y) for circumradius `r`; returns the cell centre
|
||||
/// and integer cell coordinates.
|
||||
@@ -418,7 +418,7 @@ fn hextile(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC Mr. Smoothie
|
||||
// ------------------------------------------------------------------ Palette Map
|
||||
|
||||
const SMOOTHIE_PROPS: [&str; 8] = ["Red", "Green", "Blue", "Alpha", "Luminance", "Lightness", "Hue", "Saturation"];
|
||||
|
||||
@@ -518,7 +518,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![
|
||||
spec(
|
||||
"ec.stylize.ccblockload",
|
||||
"CC Block Load",
|
||||
"Block Reveal",
|
||||
vec![
|
||||
p("completion", "Completion", num(0.0), pct()),
|
||||
p("scanlines", "Scanlines", Value::Bool(true), ParamUi::Checkbox),
|
||||
@@ -530,7 +530,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.stylize.ccburnfilm",
|
||||
"CC Burn Film",
|
||||
"Film Burn",
|
||||
vec![
|
||||
p("burn", "Burn", num(0.0), pct()),
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
@@ -538,10 +538,10 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
],
|
||||
burn_film,
|
||||
),
|
||||
spec("ec.stylize.ccglass", "CC Glass", glass_p, glass),
|
||||
spec("ec.stylize.ccglass", "Glass Relief", glass_p, glass),
|
||||
spec(
|
||||
"ec.stylize.cchextile",
|
||||
"CC HexTile",
|
||||
"Hexagonal Tiles",
|
||||
vec![
|
||||
p("render", "Render", Value::Enum(0), popup(&["Normal", "Mirrored", "Rotated"])),
|
||||
p("radius", "Radius", num(50.0), slider(1.0, 4000.0, 2.0, 500.0, 1)),
|
||||
@@ -553,7 +553,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.stylize.ccmrsmoothie",
|
||||
"CC Mr. Smoothie",
|
||||
"Palette Map",
|
||||
vec![
|
||||
p("flowLayer", "Flow Layer", Value::Layer(None), ParamUi::Layer),
|
||||
p("property", "Property", Value::Enum(4), popup(&SMOOTHIE_PROPS)),
|
||||
@@ -565,7 +565,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
],
|
||||
smoothie,
|
||||
),
|
||||
spec("ec.stylize.ccplastic", "CC Plastic", plastic_p, plastic),
|
||||
spec("ec.stylize.ccplastic", "Plastic Shading", plastic_p, plastic),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//! Time effects (Effect > Time): Echo, Posterize Time, Time Difference, Time Displacement,
|
||||
//! Timewarp, CC Force Motion Blur, CC Wide Time and Pixel Motion Blur.
|
||||
//! Timewarp, Temporal Motion Blur, Temporal Blend and Pixel Motion Blur.
|
||||
//!
|
||||
//! These read the layer at *other* layer times through [`EffectHost::self_at`]: its source with
|
||||
//! its masks and the effects applied before them, as After Effects renders them (SceneYard:
|
||||
//! Echo after CC Particle Systems II echoes the fireworks, not the black solid under them;
|
||||
//! Echo after Particle Emitter 2D echoes the fireworks, not the black solid under them;
|
||||
//! Posterize Time after Turbulent Displace steps the displacement). Timewarp is the exception:
|
||||
//! it retimes the layer's source with its masks and ignores the effects above it (After
|
||||
//! Effects 2026: a red solid with a Gradient Ramp and then Timewarp shows the red solid).
|
||||
@@ -123,7 +123,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.time.ccforcemotionblur",
|
||||
"CC Force Motion Blur",
|
||||
"Temporal Motion Blur",
|
||||
vec![
|
||||
p("motionBlurLevels", "Motion Blur Levels", num(8.0), slider(2.0, 64.0, 2.0, 32.0, 0)),
|
||||
p("overrideShutterAngle", "Override Shutter Angle", Value::Bool(true), ParamUi::Checkbox),
|
||||
@@ -134,7 +134,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.time.ccwidetime",
|
||||
"CC Wide Time",
|
||||
"Temporal Blend",
|
||||
vec![
|
||||
p("forwardSteps", "Forward Steps", num(3.0), slider(0.0, 45.0, 0.0, 15.0, 0)),
|
||||
p("backwardSteps", "Backward Steps", num(3.0), slider(0.0, 45.0, 0.0, 15.0, 0)),
|
||||
@@ -994,7 +994,7 @@ fn matte_image(m: &[f32], like: &Image) -> Image {
|
||||
out
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- CC Force Motion Blur / CC Wide Time / Pixel Motion Blur
|
||||
// ---------------------------------------------------------------- Temporal Motion Blur / Temporal Blend / Pixel Motion Blur
|
||||
|
||||
fn force_motion_blur(ctx: &EffectCtx, b: Buf) -> Buf {
|
||||
let n = ctx.params.f("motionBlurLevels").round().clamp(2.0, 64.0) as usize;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Transition effects (batch 2): Block Dissolve, Gradient Wipe (gradient layer or self), Iris Wipe, Card
|
||||
//! Wipe (3D cards with camera, lighting and jitter), CC Grid Wipe, CC Radial ScaleWipe, CC Scale Wipe and CC Light Wipe.
|
||||
//! Wipe (3D cards with camera, lighting and jitter), Grid Wipe, Radial Scale Wipe, Scale Wipe and Light Wipe.
|
||||
//!
|
||||
//! Every transition is the identity at 0 % completion. Angles are clockwise from "up".
|
||||
|
||||
@@ -595,7 +595,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.transition.ccgridwipe",
|
||||
"CC Grid Wipe",
|
||||
"Grid Wipe",
|
||||
vec![
|
||||
cc_done(),
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
@@ -609,13 +609,13 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.transition.ccradialscalewipe",
|
||||
"CC Radial ScaleWipe",
|
||||
"Radial Scale Wipe",
|
||||
vec![cc_done(), p("center", "Center", pt(0.5, 0.5), ParamUi::Point), p("reverse", "Reverse Transition", Value::Bool(false), ParamUi::Checkbox)],
|
||||
radial_scale_wipe,
|
||||
),
|
||||
spec(
|
||||
"ec.transition.ccscalewipe",
|
||||
"CC Scale Wipe",
|
||||
"Scale Wipe",
|
||||
vec![
|
||||
p("stretch", "Stretch", num(0.0), slider(0.0, 1000.0, 0.0, 50.0, 2)),
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
@@ -625,7 +625,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.transition.cclightwipe",
|
||||
"CC Light Wipe",
|
||||
"Light Wipe",
|
||||
vec![
|
||||
cc_done(),
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Transition effects, batch 2: CC Glass Wipe, CC Image Wipe, CC Jaws, CC Line Sweep,
|
||||
//! CC Twister and CC WarpoMatic.
|
||||
//! Transition effects, batch 2: Glass Wipe, Luminance Image Wipe, Serrated Wipe, Line Sweep,
|
||||
//! Twist Wipe and Warp Dissolve.
|
||||
//!
|
||||
//! Written from the public descriptions of these transitions (gradient-driven wipes with glass
|
||||
//! refraction or warping, jagged "jaws" opening, staggered line sweeps, a ribbon twist that
|
||||
@@ -68,7 +68,7 @@ fn grad(pl: &Plane, x: usize, y: usize) -> (f32, f32) {
|
||||
((pl.get_clamped(xi + 1, yi) - pl.get_clamped(xi - 1, yi)) * 0.5, (pl.get_clamped(xi, yi + 1) - pl.get_clamped(xi, yi - 1)) * 0.5)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC Glass Wipe
|
||||
// ------------------------------------------------------------------ Glass Wipe
|
||||
|
||||
fn glass_wipe(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = completion(ctx);
|
||||
@@ -105,7 +105,7 @@ fn glass_wipe(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC Image Wipe
|
||||
// ------------------------------------------------------------------ Luminance Image Wipe
|
||||
|
||||
fn image_wipe(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = completion(ctx);
|
||||
@@ -132,7 +132,7 @@ fn image_wipe(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC Jaws
|
||||
// ------------------------------------------------------------------ Serrated Wipe
|
||||
|
||||
fn jaws(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = completion(ctx) as f64;
|
||||
@@ -193,7 +193,7 @@ fn jaws(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC Line Sweep
|
||||
// ------------------------------------------------------------------ Line Sweep
|
||||
|
||||
fn line_sweep(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = completion(ctx) as f64;
|
||||
@@ -235,7 +235,7 @@ fn line_sweep(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC Twister
|
||||
// ------------------------------------------------------------------ Twist Wipe
|
||||
|
||||
fn twister(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = completion(ctx) as f64;
|
||||
@@ -283,7 +283,7 @@ fn twister(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
b
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ CC WarpoMatic
|
||||
// ------------------------------------------------------------------ Warp Dissolve
|
||||
|
||||
fn warpomatic(ctx: &EffectCtx, mut b: Buf) -> Buf {
|
||||
let c = completion(ctx);
|
||||
@@ -350,7 +350,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
vec![
|
||||
spec(
|
||||
"ec.transition.ccglasswipe",
|
||||
"CC Glass Wipe",
|
||||
"Glass Wipe",
|
||||
vec![
|
||||
done(),
|
||||
p("layerToReveal", "Layer to Reveal", Value::Layer(None), ParamUi::Layer),
|
||||
@@ -362,7 +362,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.transition.ccimagewipe",
|
||||
"CC Image Wipe",
|
||||
"Luminance Image Wipe",
|
||||
vec![
|
||||
done(),
|
||||
p("borderSoftness", "Border Softness", num(0.0), pct()),
|
||||
@@ -376,7 +376,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.transition.ccjaws",
|
||||
"CC Jaws",
|
||||
"Serrated Wipe",
|
||||
vec![
|
||||
done(),
|
||||
p("center", "Center", pt(0.5, 0.5), ParamUi::Point),
|
||||
@@ -389,7 +389,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.transition.cclinesweep",
|
||||
"CC Line Sweep",
|
||||
"Line Sweep",
|
||||
vec![
|
||||
done(),
|
||||
p("direction", "Direction", num(0.0), ParamUi::Angle),
|
||||
@@ -401,7 +401,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.transition.cctwister",
|
||||
"CC Twister",
|
||||
"Twist Wipe",
|
||||
vec![
|
||||
done(),
|
||||
p("backside", "Backside", Value::Layer(None), ParamUi::Layer),
|
||||
@@ -413,7 +413,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
),
|
||||
spec(
|
||||
"ec.transition.ccwarpomatic",
|
||||
"CC WarpoMatic",
|
||||
"Warp Dissolve",
|
||||
vec![
|
||||
done(),
|
||||
p("layerToReveal", "Layer to Reveal", Value::Layer(None), ParamUi::Layer),
|
||||
|
||||
@@ -365,7 +365,7 @@ pub fn specs() -> Vec<EffectSpec> {
|
||||
spec("ec.utility.growbounds", "Grow Bounds", vec![p("pixels", "Pixels", num(0.0), slider(0.0, 4000.0, 0.0, 500.0, 0))], grow_bounds),
|
||||
spec(
|
||||
"ec.utility.ccoverbrights",
|
||||
"CC Overbrights",
|
||||
"Out-of-Range Display",
|
||||
vec![
|
||||
p("channel", "Channel", Value::Enum(0), popup(&["Max RGB", "Red", "Green", "Blue", "Alpha", "Luminance"])),
|
||||
p("highlightColor", "Highlight Color", col(1.0, 0.0, 0.0), ParamUi::Color),
|
||||
|
||||
@@ -375,7 +375,7 @@ pub(crate) fn job_accel() -> Option<Arc<dyn Accelerator>> {
|
||||
}
|
||||
|
||||
/// Render options of an analysis's input frames: 100 %; with an accelerator, the project's
|
||||
/// renderer (Mercury GPU Acceleration: its GPU effects on the device; Software Only: the CPU).
|
||||
/// renderer (GPU Acceleration: its GPU effects on the device; Software Only: the CPU).
|
||||
pub(crate) fn analysis_opts(accel: Option<&dyn Accelerator>) -> RenderOpts {
|
||||
RenderOpts { scale: 1.0, backend: if accel.is_some() { Backend::Auto } else { Backend::Cpu }, ..Default::default() }
|
||||
}
|
||||
|
||||
@@ -719,8 +719,8 @@ fn project_settings(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
Ok(serde_json::to_value(&s.project.settings).unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Video Rendering and Effects: report or set the renderer (Mercury GPU Acceleration when a GPU
|
||||
/// adapter exists, else Mercury Software Only).
|
||||
/// Video Rendering and Effects: report or set the renderer (GPU Acceleration when a GPU
|
||||
/// adapter exists, else Software Rendering).
|
||||
fn render_backend(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
if let Some(b) = p.get("backend").or_else(|| p.get("renderer")) {
|
||||
let gpu = match b {
|
||||
@@ -748,14 +748,14 @@ pub fn backend_status(s: &Session) -> Value {
|
||||
let gpu = s.project.settings.gpu_acceleration;
|
||||
// Why it renders on the CPU (#262).
|
||||
let why = if !gpu {
|
||||
Some("the project's renderer is Mercury Software Only".to_string())
|
||||
Some("the project's renderer is Software Rendering".to_string())
|
||||
} else if adapter.is_none() {
|
||||
Some(s.accel_note.clone().unwrap_or_else(|| "no GPU compositor is attached".into()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
json!({
|
||||
"renderer": if gpu { "Mercury GPU Acceleration" } else { "Mercury Software Only" },
|
||||
"renderer": if gpu { "GPU Acceleration" } else { "Software Rendering" },
|
||||
"gpuAcceleration": gpu,
|
||||
"adapter": adapter,
|
||||
"active": if gpu && adapter.is_some() { "gpu" } else { "cpu" },
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Commands behind the Progress, Media Browser, Metadata and Lumetri Scopes panels.
|
||||
//! Commands behind the Progress, Media Browser, Metadata and Video Scopes panels.
|
||||
|
||||
use effectcraft_project::ItemId;
|
||||
use effectcraft_raster::Image;
|
||||
@@ -159,7 +159,7 @@ fn project_comment(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
Ok(Value::Null)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- Lumetri Scopes
|
||||
// ---------------------------------------------------------------- Video Scopes
|
||||
|
||||
/// The comp frame the scopes read (the viewer's image: over the comp background), at most
|
||||
/// `max_side` pixels on the long side.
|
||||
@@ -257,7 +257,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
cmd!("project.setProjectComment", "Project Comment", [], None, "{comment}", always, project_comment),
|
||||
query!(
|
||||
"scopes.analyze",
|
||||
"Lumetri Scopes",
|
||||
"Video Scopes",
|
||||
"{comp?, time?|frame?, scope?: waveformRgb|waveformLuma|waveformYc|vectorscopeYuv|vectorscopeHls|histogram|paradeRgb|paradeYuv, standard?: rec601|rec709|rec2020, float?, clamp?, size?}",
|
||||
scopes_analyze
|
||||
),
|
||||
|
||||
@@ -238,7 +238,7 @@ fn showcase_3d(p: &mut Project, solids: ItemId) -> Comp {
|
||||
anim(&mut cam, "cameraOptions/focusDistance", keys(&[(0.0, Value::Scalar(1700.0)), (5.0, Value::Scalar(1900.0)), (10.0, Value::Scalar(1650.0))]));
|
||||
|
||||
// Key light: warm spot casting soft shadows. Fill: cool ambient.
|
||||
let mut key = build::layer(p, &c, "Key Light", LayerSource::Light { kind: effectcraft_project::LightKind::Spot }, (1920, 1080), None);
|
||||
let mut key = build::layer(p, &c, "Screen Color Key", LayerSource::Light { kind: effectcraft_project::LightKind::Spot }, (1920, 1080), None);
|
||||
set(&mut key, "transform/position", Value::Vec3([500.0, -500.0, -700.0]));
|
||||
set(&mut key, "transform/poi", Value::Vec3([960.0, 600.0, 300.0]));
|
||||
set(&mut key, "lightOptions/intensity", Value::Scalar(150.0));
|
||||
|
||||
@@ -259,7 +259,7 @@ pub fn tutorials() -> Vec<Tutorial> {
|
||||
target: Some("menu.Layer"),
|
||||
accepts: &["layer.newLight"],
|
||||
when: Value::Null,
|
||||
show: vec![("layer.newLight", json!({"kind": "Spot", "name": "Key Light"}))],
|
||||
show: vec![("layer.newLight", json!({"kind": "Spot", "name": "Screen Color Key"}))],
|
||||
}),
|
||||
step(S {
|
||||
title: "Add a camera",
|
||||
|
||||
@@ -1263,7 +1263,7 @@ Window
|
||||
Essential Graphics | window.panel {"panel":"essentialGraphics"}
|
||||
Info | window.panel {"panel":"info"} | Cmd+2
|
||||
Learn | help.inAppTutorials
|
||||
Lumetri Scopes | window.panel {"panel":"lumetriScopes"}
|
||||
Video Scopes | window.panel {"panel":"lumetriScopes"}
|
||||
Mask Interpolation | window.panel {"panel":"maskInterpolation"}
|
||||
Media Browser | window.panel {"panel":"mediaBrowser"}
|
||||
Metadata | window.panel {"panel":"metadata"}
|
||||
|
||||
@@ -23,6 +23,25 @@ fn platform_entries(mac: bool) -> Vec<(Vec<String>, MenuEntry)> {
|
||||
out
|
||||
}
|
||||
|
||||
/// Guard the generated display tree, not command IDs, format tokens or dynamic user names.
|
||||
#[test]
|
||||
fn builtin_menu_labels_do_not_reintroduce_vendor_feature_names() {
|
||||
for mac in [true, false] {
|
||||
let entries = platform_entries(mac);
|
||||
for (path, entry) in &entries {
|
||||
for label in path.iter().chain(std::iter::once(&entry.label)) {
|
||||
let folded = label.to_lowercase();
|
||||
assert!(!folded.starts_with("cc "), "{label}");
|
||||
for mark in ["lumetri", "mercury", "mocha", "keylight"] {
|
||||
assert!(!folded.contains(mark), "{label}");
|
||||
}
|
||||
}
|
||||
}
|
||||
let scopes = entries.iter().find(|(_, e)| e.command == "window.panel" && e.params["panel"] == "lumetriScopes").unwrap();
|
||||
assert_eq!(scopes.1.label, "Video Scopes");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn top_level_order_matches_after_effects() {
|
||||
let mac: Vec<String> =
|
||||
|
||||
@@ -439,7 +439,7 @@ const RIGGED: &str = r#"{
|
||||
],
|
||||
"cameras": [{"type": "perspective", "name": "Shot", "perspective": {"yfov": 0.6, "znear": 0.1}}],
|
||||
"extensions": {"KHR_lights_punctual": {"lights": [
|
||||
{"type": "spot", "name": "Key Light", "color": [1, 0.8, 0.6], "intensity": 1.5, "spot": {"innerConeAngle": 0.25, "outerConeAngle": 0.5}},
|
||||
{"type": "spot", "name": "Screen Color Key", "color": [1, 0.8, 0.6], "intensity": 1.5, "spot": {"innerConeAngle": 0.25, "outerConeAngle": 0.5}},
|
||||
{"type": "point", "name": "Fill Light", "intensity": 0.5, "range": 4}
|
||||
]}}
|
||||
}"#;
|
||||
@@ -478,7 +478,7 @@ fn cameras_and_lights_from_model() {
|
||||
let r = s.execute("light.fromModel", json!({})).unwrap();
|
||||
let ls: Vec<Layer> = r["layers"].as_array().unwrap().iter().map(|v| layer_in(&s, cid(&s), v.as_u64().unwrap())).collect();
|
||||
assert_eq!(ls.len(), 2);
|
||||
let key = ls.iter().find(|l| l.name == "Key Light").unwrap();
|
||||
let key = ls.iter().find(|l| l.name == "Screen Color Key").unwrap();
|
||||
assert_eq!(key.source, LayerSource::Light { kind: LightKind::Spot });
|
||||
assert!((key.props.prop("lightOptions/coneAngle").unwrap().value.as_f64() - 1.0f64.to_degrees()).abs() < 1e-6);
|
||||
assert!((key.props.prop("lightOptions/coneFeather").unwrap().value.as_f64() - 50.0).abs() < 1e-6);
|
||||
|
||||
@@ -1221,7 +1221,35 @@ fn render_backend_says_why_it_renders_on_the_cpu() {
|
||||
assert_eq!(why(&mut s), json!("no GPU compositor is attached"));
|
||||
s.accel_note = Some("headless: renders on the CPU unless started with --gpu".into());
|
||||
assert_eq!(why(&mut s), json!("headless: renders on the CPU unless started with --gpu"));
|
||||
assert_eq!(s.execute("render.backend", json!({"backend": "cpu"})).unwrap()["why"], json!("the project's renderer is Mercury Software Only"));
|
||||
assert_eq!(s.execute("render.backend", json!({"backend": "cpu"})).unwrap()["why"], json!("the project's renderer is Software Rendering"));
|
||||
}
|
||||
|
||||
/// Display labels are descriptive; machine-readable settings remain the same.
|
||||
#[test]
|
||||
fn renderer_labels_keep_their_stable_machine_values() {
|
||||
let mut s = Session::default();
|
||||
for (backend, label, gpu) in [("cpu", "Software Rendering", false), ("gpu", "GPU Acceleration", true)] {
|
||||
let status = s.execute("render.backend", json!({"backend": backend})).unwrap();
|
||||
assert_eq!(status["renderer"], json!(label));
|
||||
assert_eq!(status["gpuAcceleration"], json!(gpu));
|
||||
assert_eq!(status["active"], json!("cpu"), "the headless test has no GPU adapter");
|
||||
}
|
||||
}
|
||||
|
||||
/// The label `render.backend` reports is one it accepts back, so a caller can round-trip the
|
||||
/// status instead of guessing the command's own values.
|
||||
#[test]
|
||||
fn renderer_status_labels_round_trip_through_the_command() {
|
||||
let mut s = Session::default();
|
||||
for (backend, label, gpu) in [("cpu", "Software Rendering", false), ("gpu", "GPU Acceleration", true)] {
|
||||
let reported = s.execute("render.backend", json!({"backend": backend})).unwrap()["renderer"].clone();
|
||||
assert_eq!(reported, json!(label));
|
||||
let parsed = effectcraft_render::Backend::parse(reported.as_str().unwrap()).expect("the reported renderer parses back");
|
||||
assert_eq!(parsed == effectcraft_render::Backend::Cpu, !gpu, "{reported}");
|
||||
let again = s.execute("render.backend", json!({"backend": reported})).unwrap();
|
||||
assert_eq!(again["renderer"], reported);
|
||||
assert_eq!(again["gpuAcceleration"], json!(gpu));
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings ▸ GPU Information names what the GPU compositor runs on, or why it is off, and the
|
||||
|
||||
@@ -21,10 +21,13 @@ pub enum Backend {
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
/// The backend `s` names, whatever case it is written in: the project's own values (`cpu`,
|
||||
/// `gpu`, `auto`), the labels Project Settings ▸ Video Rendering and Effects draws
|
||||
/// (`GPU Acceleration`, `Software Rendering`) and the older After Effects wording.
|
||||
pub fn parse(s: &str) -> Option<Backend> {
|
||||
match s.to_ascii_lowercase().as_str() {
|
||||
"cpu" | "software" | "mercury software only" => Some(Backend::Cpu),
|
||||
"gpu" | "mercury gpu acceleration" => Some(Backend::Gpu),
|
||||
"cpu" | "software" | "mercury software only" | "software rendering" => Some(Backend::Cpu),
|
||||
"gpu" | "mercury gpu acceleration" | "gpu acceleration" => Some(Backend::Gpu),
|
||||
"auto" => Some(Backend::Auto),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
+32
-11
@@ -329,7 +329,7 @@ fn card_dance_comp_camera_matches_the_default_view() {
|
||||
assert!(img.get(10, 50)[3] < 0.01);
|
||||
}
|
||||
|
||||
/// A black 2D solid with CC Particle World, under a camera layer panned right by `pan` px.
|
||||
/// A black 2D solid with Particle Emitter 3D, under a camera layer panned right by `pan` px.
|
||||
fn particle_world_scene(pan: f64) -> (Project, ItemId) {
|
||||
let (mut p, cid, comp) = setup();
|
||||
let mut l = solid(&mut p, &comp, [0.0, 0.0, 0.0], 200, 100);
|
||||
@@ -359,7 +359,7 @@ fn particles_x(img: &crate::Image) -> f32 {
|
||||
sx / m
|
||||
}
|
||||
|
||||
/// #397: CC Particle World on a 2D layer is seen through the comp's camera layer, and the layer
|
||||
/// #397: Particle Emitter 3D on a 2D layer is seen through the comp's camera layer, and the layer
|
||||
/// cache notices the camera moving.
|
||||
#[test]
|
||||
fn particle_world_follows_the_comp_camera() {
|
||||
@@ -374,7 +374,7 @@ fn particle_world_follows_the_comp_camera() {
|
||||
assert!(b < a - 20.0, "panning the camera right moves the particles left: {a} -> {b}");
|
||||
}
|
||||
|
||||
/// A black solid with CC Particle World whose Birth Rate is 3 until layer time `cut`, then 0 a
|
||||
/// A black solid with Particle Emitter 3D whose Birth Rate is 3 until layer time `cut`, then 0 a
|
||||
/// frame later (`None`: 3 throughout); the layer starts at comp time `start`, stretched `stretch` %.
|
||||
fn burst_scene(cut: Option<f64>, start: f64, stretch: f64) -> (Project, ItemId) {
|
||||
burst_scene_keys(cut, start, stretch, false)
|
||||
@@ -624,7 +624,7 @@ fn a_text_expression_selector_is_not_served_from_the_disk_cache() {
|
||||
|
||||
/// A Birth Rate expression reading another layer: changing that layer changes the history but
|
||||
/// not the current rate (0) nor this layer's properties, which is all the layer cache key sees.
|
||||
/// CC Particle World layers with expressions therefore aren't layer cached.
|
||||
/// Particle Emitter 3D layers with expressions therefore aren't layer cached.
|
||||
#[test]
|
||||
fn particle_world_with_a_birth_rate_expression_is_not_served_from_the_layer_cache() {
|
||||
let scene = |opacity: f64| {
|
||||
@@ -657,8 +657,8 @@ fn particle_world_with_a_birth_rate_expression_is_not_served_from_the_layer_cach
|
||||
assert!(light(&b) > 1.0 && light(&b) < light(&a), "fewer births: {} vs {}", light(&b), light(&a));
|
||||
}
|
||||
|
||||
/// A grey solid (CC Mr. Mercury shades its blobs from it) with effect `id` (CC Particle Systems
|
||||
/// II, CC Mr. Mercury): Birth Rate `rate`,
|
||||
/// A grey solid (Liquid Particles shades its blobs from it) with effect `id` (CC Particle Systems
|
||||
/// II, Liquid Particles): Birth Rate `rate`,
|
||||
/// or keyed 3 until 0.5 s and 0 a frame later (`None`); Longevity 1 s.
|
||||
fn system_scene(id: &str, rate: Option<f64>) -> (Project, ItemId) {
|
||||
let (mut p, cid, comp) = setup();
|
||||
@@ -677,7 +677,7 @@ fn system_scene(id: &str, rate: Option<f64>) -> (Project, ItemId) {
|
||||
(p, cid)
|
||||
}
|
||||
|
||||
/// #1373 for CC Particle Systems II and CC Mr. Mercury through the renderer: a keyed burst
|
||||
/// #1373 for Particle Emitter 2D and Liquid Particles through the renderer: a keyed burst
|
||||
/// draws as the constant rate during it, still draws after the rate drops to 0 (unlike a rate
|
||||
/// of 0 throughout), and draws as nothing born once Longevity has run out.
|
||||
#[test]
|
||||
@@ -1057,6 +1057,27 @@ fn comp_frame_ends_the_frame_when_the_render_panics() {
|
||||
assert_eq!(a.ends.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
/// The renderer labels Project Settings ▸ Video Rendering and Effects draws parse back as the
|
||||
/// backend they name (in any case), and the older spellings still work.
|
||||
#[test]
|
||||
fn renderer_labels_parse_back_and_keep_the_older_spellings() {
|
||||
use crate::Backend;
|
||||
for (label, backend) in [
|
||||
("GPU Acceleration", Backend::Gpu),
|
||||
("gpu acceleration", Backend::Gpu),
|
||||
("Mercury GPU Acceleration", Backend::Gpu),
|
||||
("gpu", Backend::Gpu),
|
||||
("Software Rendering", Backend::Cpu),
|
||||
("software rendering", Backend::Cpu),
|
||||
("Mercury Software Only", Backend::Cpu),
|
||||
("cpu", Backend::Cpu),
|
||||
("Auto", Backend::Auto),
|
||||
] {
|
||||
assert_eq!(Backend::parse(label), Some(backend), "{label}");
|
||||
}
|
||||
assert_eq!(Backend::parse("Vulkan"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_backend_sends_2d_and_3d_comps_to_the_gpu() {
|
||||
let (mut p, cid, comp) = setup();
|
||||
@@ -1223,11 +1244,11 @@ fn effects_on_text_reach_past_the_text_bounds() {
|
||||
}
|
||||
assert!(
|
||||
painted > 50 && hi.saturating_sub(lo) > 100,
|
||||
"CC Tiler tiles the glyphs across the layer region, not just its text bounds: {painted} painted, x-span {lo}..{hi}"
|
||||
"Scaled Tiles tiles the glyphs across the layer region, not just its text bounds: {painted} painted, x-span {lo}..{hi}"
|
||||
);
|
||||
}
|
||||
|
||||
/// #658: CC Smear drags text glyphs beyond the text layer's own bounds. Pixels smeared past
|
||||
/// #658: Directional Smear drags text glyphs beyond the text layer's own bounds. Pixels smeared past
|
||||
/// the painted rectangle used to fall off its edge, so the liquid trail never appeared.
|
||||
#[test]
|
||||
fn cc_smear_trails_text_past_its_bounds() {
|
||||
@@ -1246,7 +1267,7 @@ fn cc_smear_trails_text_past_its_bounds() {
|
||||
);
|
||||
p.comp_mut(cid).unwrap().layers = vec![l].into();
|
||||
let smeared = right(&render_frame(&p, cid, Tick::ZERO, 1.0));
|
||||
assert!(plain > 40 && smeared > plain + 25, "CC Smear trails the glyphs past the text bounds: right edge {plain} → {smeared}");
|
||||
assert!(plain > 40 && smeared > plain + 25, "Directional Smear trails the glyphs past the text bounds: right edge {plain} → {smeared}");
|
||||
}
|
||||
|
||||
/// A layer parameter pointing at a shape layer sees all of it (in its effect space), and the
|
||||
@@ -1502,7 +1523,7 @@ fn solo_excludes_other_layers_outside_the_soloed_layers_range() {
|
||||
assert_eq!(second.get(100, 50), [0.0, 0.0, 1.0, 1.0], "only B inside its range");
|
||||
}
|
||||
|
||||
/// #1252: a layer blended with a CC Particle World layer, under a camera panned by `pan` px.
|
||||
/// #1252: a layer blended with a Particle Emitter 3D layer, under a camera panned by `pan` px.
|
||||
fn scene_reader_dependency(pan: f64) -> (Project, ItemId) {
|
||||
let (mut p, cid, comp) = setup();
|
||||
let mut source = solid(&mut p, &comp, [0.0, 0.0, 0.0], 200, 100);
|
||||
|
||||
@@ -124,7 +124,7 @@ impl PanelKind {
|
||||
PanelKind::EssentialGraphics => "Essential Graphics",
|
||||
PanelKind::ScriptPanel(_) => "ScriptUI Panel",
|
||||
PanelKind::Viewer(_) => "Composition",
|
||||
PanelKind::LumetriScopes => "Lumetri Scopes",
|
||||
PanelKind::LumetriScopes => "Video Scopes",
|
||||
PanelKind::Footage => "Footage",
|
||||
PanelKind::MediaBrowser => "Media Browser",
|
||||
PanelKind::Metadata => "Metadata",
|
||||
@@ -709,6 +709,16 @@ mod tests {
|
||||
w.apply(action, permissions).unwrap();
|
||||
}
|
||||
|
||||
/// Only the title changes: existing saved workspace layouts still deserialize.
|
||||
#[test]
|
||||
fn scopes_label_is_descriptive_and_its_saved_identity_stays_compatible() {
|
||||
let panel: PanelKind = serde_json::from_str("\"LumetriScopes\"").unwrap();
|
||||
assert_eq!(panel, LumetriScopes);
|
||||
assert_eq!(panel.title(), "Video Scopes");
|
||||
assert_eq!(panel.id(), "LumetriScopes");
|
||||
assert_eq!(serde_json::to_string(&panel).unwrap(), "\"LumetriScopes\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn after_effects_workspaces_exist_with_their_core_panels() {
|
||||
for name in WORKSPACES {
|
||||
|
||||
+28
-13
@@ -1054,7 +1054,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "基本图形"),
|
||||
("window.panel", "Info", "信息"),
|
||||
("help.inAppTutorials", "Learn", "学习"),
|
||||
("window.panel", "Lumetri Scopes", "Lumetri 范围"),
|
||||
("window.panel", "Video Scopes", "视频示波器"),
|
||||
("window.panel", "Mask Interpolation", "蒙版插值"),
|
||||
("window.panel", "Media Browser", "媒体浏览器"),
|
||||
("window.panel", "Metadata", "元数据"),
|
||||
@@ -1690,7 +1690,7 @@ const SWEDISH: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Grundläggande grafik"),
|
||||
("window.panel", "Info", "Info"),
|
||||
("help.inAppTutorials", "Learn", "Lär dig"),
|
||||
("window.panel", "Lumetri Scopes", "Lumetri-scope"),
|
||||
("window.panel", "Video Scopes", "Videoskop"),
|
||||
("window.panel", "Mask Interpolation", "Maskinterpolering"),
|
||||
("window.panel", "Media Browser", "Mediebläddrare"),
|
||||
("window.panel", "Metadata", "Metadata"),
|
||||
@@ -2336,7 +2336,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "基本圖形"),
|
||||
("window.panel", "Info", "資訊"),
|
||||
("help.inAppTutorials", "Learn", "學習"),
|
||||
("window.panel", "Lumetri Scopes", "Lumetri 示波器"),
|
||||
("window.panel", "Video Scopes", "視訊示波器"),
|
||||
("window.panel", "Mask Interpolation", "遮色片插補"),
|
||||
("window.panel", "Media Browser", "媒體瀏覽器"),
|
||||
("window.panel", "Metadata", "中繼資料"),
|
||||
@@ -2975,7 +2975,7 @@ const JAPANESE: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "エッセンシャルグラフィックス"),
|
||||
("window.panel", "Info", "情報"),
|
||||
("help.inAppTutorials", "Learn", "学習"),
|
||||
("window.panel", "Lumetri Scopes", "Lumetriスコープ"),
|
||||
("window.panel", "Video Scopes", "ビデオスコープ"),
|
||||
("window.panel", "Mask Interpolation", "マスク補間"),
|
||||
("window.panel", "Media Browser", "メディアブラウザー"),
|
||||
("window.panel", "Metadata", "メタデータ"),
|
||||
@@ -3617,7 +3617,7 @@ const UKRAINIAN: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Основна графіка"),
|
||||
("window.panel", "Info", "Інформація"),
|
||||
("help.inAppTutorials", "Learn", "Навчання"),
|
||||
("window.panel", "Lumetri Scopes", "Вимірювачі Lumetri"),
|
||||
("window.panel", "Video Scopes", "Відеоскопи"),
|
||||
("window.panel", "Mask Interpolation", "Інтерполяція маски"),
|
||||
("window.panel", "Media Browser", "Браузер медіа"),
|
||||
("window.panel", "Metadata", "Метадані"),
|
||||
@@ -4260,7 +4260,7 @@ const SPANISH: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Gráficos esenciales"),
|
||||
("window.panel", "Info", "Información"),
|
||||
("help.inAppTutorials", "Learn", "Aprender"),
|
||||
("window.panel", "Lumetri Scopes", "Ámbitos de Lumetri"),
|
||||
("window.panel", "Video Scopes", "Monitores de vídeo"),
|
||||
("window.panel", "Mask Interpolation", "Interpolación de máscara"),
|
||||
("window.panel", "Media Browser", "Navegador de medios"),
|
||||
("window.panel", "Metadata", "Metadatos"),
|
||||
@@ -4901,7 +4901,7 @@ const PORTUGUESE: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Gráficos essenciais"),
|
||||
("window.panel", "Info", "Informações"),
|
||||
("help.inAppTutorials", "Learn", "Aprender"),
|
||||
("window.panel", "Lumetri Scopes", "Escopos Lumetri"),
|
||||
("window.panel", "Video Scopes", "Escopos de vídeo"),
|
||||
("window.panel", "Mask Interpolation", "Interpolação de máscara"),
|
||||
("window.panel", "Media Browser", "Navegador de mídia"),
|
||||
("window.panel", "Metadata", "Metadados"),
|
||||
@@ -5544,7 +5544,7 @@ const RUSSIAN: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Основная графика"),
|
||||
("window.panel", "Info", "Информация"),
|
||||
("help.inAppTutorials", "Learn", "Обучение"),
|
||||
("window.panel", "Lumetri Scopes", "Измерители Lumetri"),
|
||||
("window.panel", "Video Scopes", "Видеоскопы"),
|
||||
("window.panel", "Mask Interpolation", "Интерполяция маски"),
|
||||
("window.panel", "Media Browser", "Обозреватель медиа"),
|
||||
("window.panel", "Metadata", "Метаданные"),
|
||||
@@ -6185,7 +6185,7 @@ const FRENCH: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Graphiques essentiels"),
|
||||
("window.panel", "Info", "Informations"),
|
||||
("help.inAppTutorials", "Learn", "Apprentissage"),
|
||||
("window.panel", "Lumetri Scopes", "Oscilloscopes Lumetri"),
|
||||
("window.panel", "Video Scopes", "Oscilloscopes vidéo"),
|
||||
("window.panel", "Mask Interpolation", "Interpolation de masque"),
|
||||
("window.panel", "Media Browser", "Navigateur multimédia"),
|
||||
("window.panel", "Metadata", "Métadonnées"),
|
||||
@@ -6826,7 +6826,7 @@ const GERMAN: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Essential-Grafik"),
|
||||
("window.panel", "Info", "Info"),
|
||||
("help.inAppTutorials", "Learn", "Lernen"),
|
||||
("window.panel", "Lumetri Scopes", "Lumetri-Scopes"),
|
||||
("window.panel", "Video Scopes", "Videoskope"),
|
||||
("window.panel", "Mask Interpolation", "Maskeninterpolation"),
|
||||
("window.panel", "Media Browser", "Medienbrowser"),
|
||||
("window.panel", "Metadata", "Metadaten"),
|
||||
@@ -7464,7 +7464,7 @@ const POLISH: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Essential Graphics"),
|
||||
("window.panel", "Info", "Informacje"),
|
||||
("help.inAppTutorials", "Learn", "Nauka"),
|
||||
("window.panel", "Lumetri Scopes", "Zakresy Lumetri"),
|
||||
("window.panel", "Video Scopes", "Wskaźniki wideo"),
|
||||
("window.panel", "Mask Interpolation", "Interpolacja maski"),
|
||||
("window.panel", "Media Browser", "Przeglądarka multimediów"),
|
||||
("window.panel", "Metadata", "Metadane"),
|
||||
@@ -8106,7 +8106,7 @@ const CZECH: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "Základní grafika"),
|
||||
("window.panel", "Info", "Informace"),
|
||||
("help.inAppTutorials", "Learn", "Výuka"),
|
||||
("window.panel", "Lumetri Scopes", "Měřicí přístroje Lumetri"),
|
||||
("window.panel", "Video Scopes", "Videoskopy"),
|
||||
("window.panel", "Mask Interpolation", "Interpolace masek"),
|
||||
("window.panel", "Media Browser", "Prohlížeč médií"),
|
||||
("window.panel", "Metadata", "Metadata"),
|
||||
@@ -8748,7 +8748,7 @@ const GEORGIAN: &[(&str, &str, &str)] = &[
|
||||
("window.panel", "Essential Graphics", "ძირითადი გრაფიკა"),
|
||||
("window.panel", "Info", "ინფორმაცია"),
|
||||
("help.inAppTutorials", "Learn", "სწავლა"),
|
||||
("window.panel", "Lumetri Scopes", "Lumetri Scopes"),
|
||||
("window.panel", "Video Scopes", "ვიდეოსკოპები"),
|
||||
("window.panel", "Mask Interpolation", "ნიღბის ინტერპოლაცია"),
|
||||
("window.panel", "Media Browser", "მედიის ბრაუზერი"),
|
||||
("window.panel", "Metadata", "მეტამონაცემები"),
|
||||
@@ -8799,6 +8799,21 @@ mod tests {
|
||||
use serde_json::json;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[test]
|
||||
fn renamed_menu_translations_do_not_reintroduce_vendor_names() {
|
||||
for code in CATALOG_CODES {
|
||||
set_current(code);
|
||||
for (id, source) in [("window.panel", "Video Scopes")] {
|
||||
let rendered = command_label(id, source);
|
||||
let label = rendered.to_lowercase();
|
||||
for mark in ["lumetri", "mercury"] {
|
||||
assert!(!label.contains(mark), "{code}: {id} -> {rendered}");
|
||||
}
|
||||
}
|
||||
}
|
||||
set_current("en");
|
||||
}
|
||||
|
||||
/// The four options at the foot of the header's workspace menu say what After Effects says,
|
||||
/// read from its workspace button on 2026-10-31: reset, save over this one, save a copy, then
|
||||
/// edit the list.
|
||||
|
||||
+531
-478
File diff suppressed because it is too large.
Load diff
@@ -708,8 +708,8 @@ const JAPANESE: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "Photoshopファイルを読み込み"),
|
||||
("Interpret Unlabeled Alpha As", "ラベルのないアルファの解釈"),
|
||||
("Join the ArtCraft Discord", "ArtCraftのDiscordに参加"),
|
||||
("Mercury GPU Acceleration ({})", "Mercury GPUアクセラレーション({})"),
|
||||
("Mercury Software Only", "Mercuryソフトウェアのみ"),
|
||||
("GPU Acceleration ({})", "GPUアクセラレーション({})"),
|
||||
("Software Rendering", "ソフトウェアレンダリング"),
|
||||
("OCIO (built-in ACES config)", "OCIO(組み込みACES設定)"),
|
||||
("Off (Final Quality)", "オフ(最終品質)"),
|
||||
("OpenGL (compatibility)", "OpenGL(互換)"),
|
||||
@@ -1118,7 +1118,7 @@ const JAPANESE: &[(&str, &str)] = &[
|
||||
("Script Console", "スクリプトコンソール"),
|
||||
("Essential Graphics", "エッセンシャルグラフィックス"),
|
||||
("ScriptUI Panel", "ScriptUIパネル"),
|
||||
("Lumetri Scopes", "Lumetriスコープ"),
|
||||
("Video Scopes", "ビデオスコープ"),
|
||||
("Media Browser", "メディアブラウザー"),
|
||||
("Content-Aware Fill", "コンテンツに応じた塗りつぶし"),
|
||||
("Create Nulls From Paths", "パスからヌルを作成"),
|
||||
@@ -1318,6 +1318,7 @@ const JAPANESE: &[(&str, &str)] = &[
|
||||
("per second", "毎秒"),
|
||||
("Waveform", "波形"),
|
||||
("steps", "ステップ"),
|
||||
("GPU Acceleration (no GPU: software)", "GPUアクセラレーション(GPUなし:ソフトウェア)"),
|
||||
];
|
||||
|
||||
const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
||||
@@ -1837,8 +1838,8 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "导入 Photoshop 文件"),
|
||||
("Interpret Unlabeled Alpha As", "将未标记的 Alpha 解释为"),
|
||||
("Join the ArtCraft Discord", "加入 ArtCraft Discord"),
|
||||
("Mercury GPU Acceleration ({})", "Mercury GPU 加速({})"),
|
||||
("Mercury Software Only", "仅 Mercury 软件"),
|
||||
("GPU Acceleration ({})", "GPU 加速({})"),
|
||||
("Software Rendering", "软件渲染"),
|
||||
("OCIO (built-in ACES config)", "OCIO(内置 ACES 配置)"),
|
||||
("Off (Final Quality)", "关闭(最终质量)"),
|
||||
("OpenGL (compatibility)", "OpenGL(兼容)"),
|
||||
@@ -2280,7 +2281,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
||||
("Script Console", "脚本控制台"),
|
||||
("Essential Graphics", "基本图形"),
|
||||
("ScriptUI Panel", "ScriptUI 面板"),
|
||||
("Lumetri Scopes", "Lumetri 示波器"),
|
||||
("Video Scopes", "视频示波器"),
|
||||
("Media Browser", "媒体浏览器"),
|
||||
("Content-Aware Fill", "内容识别填充"),
|
||||
("Create Nulls From Paths", "从路径创建空对象"),
|
||||
@@ -2433,6 +2434,7 @@ const SIMPLIFIED_CHINESE: &[(&str, &str)] = &[
|
||||
("Blend Mode", "混合模式"),
|
||||
("Show mesh", "显示网格"),
|
||||
("Record Options...", "记录选项..."),
|
||||
("GPU Acceleration (no GPU: software)", "GPU 加速(无 GPU:软件)"),
|
||||
];
|
||||
|
||||
/// Swedish (`sv`), written from the English source.
|
||||
@@ -2950,8 +2952,8 @@ const SWEDISH: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "Importera Photoshop-fil"),
|
||||
("Interpret Unlabeled Alpha As", "Tolka omärkt alfa som"),
|
||||
("Join the ArtCraft Discord", "Gå med i ArtCraft på Discord"),
|
||||
("Mercury GPU Acceleration ({})", "Mercury GPU-acceleration ({})"),
|
||||
("Mercury Software Only", "Endast Mercury-programvara"),
|
||||
("GPU Acceleration ({})", "GPU-acceleration ({})"),
|
||||
("Software Rendering", "Programvarurendering"),
|
||||
("OCIO (built-in ACES config)", "OCIO (inbyggd ACES-konfiguration)"),
|
||||
("Off (Final Quality)", "Av (slutlig kvalitet)"),
|
||||
("OpenGL (compatibility)", "OpenGL (kompatibilitet)"),
|
||||
@@ -3191,7 +3193,7 @@ const SWEDISH: &[(&str, &str)] = &[
|
||||
("Drop {} files to import", "Släpp {} filer för att importera"),
|
||||
("Effects", "Effekter"),
|
||||
("Label of {}: {}", "Etikett för {}: {}"),
|
||||
("Mercury GPU Acceleration (no GPU: software)", "Mercury GPU-acceleration (ingen GPU: programvara)"),
|
||||
("GPU Acceleration (no GPU: software)", "GPU-acceleration (ingen GPU: programvara)"),
|
||||
("Only one project can be opened per drop; skipped {} more", "Bara ett projekt kan öppnas per släpp; hoppade över {} till"),
|
||||
("Open in Essential Graphics", "Öppna i Grundläggande grafik"),
|
||||
("Original color: click to go back to it", "Originalfärg: klicka för att återgå till den"),
|
||||
@@ -3440,7 +3442,7 @@ const SWEDISH: &[(&str, &str)] = &[
|
||||
("Script Console", "Skriptkonsol"),
|
||||
("Essential Graphics", "Grundläggande grafik"),
|
||||
("ScriptUI Panel", "ScriptUI-panel"),
|
||||
("Lumetri Scopes", "Lumetri-scope"),
|
||||
("Video Scopes", "Videoskop"),
|
||||
("Media Browser", "Mediebläddrare"),
|
||||
("Content-Aware Fill", "Innehållsmedveten fyllning"),
|
||||
("Create Nulls From Paths", "Skapa nullobjekt från banor"),
|
||||
@@ -4608,7 +4610,7 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
||||
("Script Console", "指令碼主控台"),
|
||||
("Essential Graphics", "基本圖形"),
|
||||
("ScriptUI Panel", "ScriptUI 面板"),
|
||||
("Lumetri Scopes", "Lumetri 示波器"),
|
||||
("Video Scopes", "視訊示波器"),
|
||||
("Media Browser", "媒體瀏覽器"),
|
||||
("Content-Aware Fill", "內容感知填色"),
|
||||
("Create Nulls From Paths", "從路徑建立空物件"),
|
||||
@@ -4761,6 +4763,9 @@ const TRADITIONAL_CHINESE: &[(&str, &str)] = &[
|
||||
("Blend Mode", "混合模式"),
|
||||
("Show mesh", "顯示網格"),
|
||||
("Record Options...", "記錄選項..."),
|
||||
("Software Rendering", "軟體算繪"),
|
||||
("GPU Acceleration ({})", "GPU 加速({})"),
|
||||
("GPU Acceleration (no GPU: software)", "GPU 加速(無 GPU:軟體)"),
|
||||
];
|
||||
|
||||
/// Ukrainian (uk): original translations of the same interface rows as the Chinese catalogs.
|
||||
@@ -5301,8 +5306,8 @@ const UKRAINIAN: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "Імпорт файлу Photoshop"),
|
||||
("Interpret Unlabeled Alpha As", "Інтерпретувати непозначену альфу як"),
|
||||
("Join the ArtCraft Discord", "Приєднатися до Discord ArtCraft"),
|
||||
("Mercury GPU Acceleration ({})", "Прискорення Mercury GPU ({})"),
|
||||
("Mercury Software Only", "Лише програмний Mercury"),
|
||||
("GPU Acceleration ({})", "Прискорення GPU ({})"),
|
||||
("Software Rendering", "Програмне відтворення"),
|
||||
("OCIO (built-in ACES config)", "OCIO (вбудована конфігурація ACES)"),
|
||||
("Off (Final Quality)", "Вимкнено (остаточна якість)"),
|
||||
("OpenGL (compatibility)", "OpenGL (сумісність)"),
|
||||
@@ -5348,6 +5353,8 @@ const UKRAINIAN: &[(&str, &str)] = &[
|
||||
("Project", "Проєкт"),
|
||||
("Total Offset", "Загальний зсув"),
|
||||
("Per Layer", "На шар"),
|
||||
("Video Scopes", "Відеоскопи"),
|
||||
("GPU Acceleration (no GPU: software)", "Прискорення GPU (без GPU: програмне)"),
|
||||
];
|
||||
|
||||
// Brazilian Portuguese.
|
||||
@@ -5979,7 +5986,7 @@ const PORTUGUESE: &[(&str, &str)] = &[
|
||||
("Guess", "Adivinhar"),
|
||||
("Import Image Sequence", "Importar sequência de imagens"),
|
||||
("Import PDF / Illustrator File", "Importar arquivo PDF / Illustrator"),
|
||||
("Mercury Software Only", "Apenas software Mercury"),
|
||||
("Software Rendering", "Renderização por software"),
|
||||
("OCIO (built-in ACES config)", "OCIO (config do ACES integrado)"),
|
||||
("Still Duration", "Duração da imagem fixa"),
|
||||
("Straight", "Direto"),
|
||||
@@ -6086,7 +6093,7 @@ const PORTUGUESE: &[(&str, &str)] = &[
|
||||
("Light", "Claro"),
|
||||
("Lines", "Linhas"),
|
||||
("Memory & CPU", "Memória e CPU"),
|
||||
("Mercury GPU Acceleration ({})", "Aceleração de GPU Mercury ({})"),
|
||||
("GPU Acceleration ({})", "Aceleração de GPU ({})"),
|
||||
("Off", "Desativado"),
|
||||
("Options", "Opções"),
|
||||
("Overlay", "Sobrepor"),
|
||||
@@ -6111,6 +6118,8 @@ const PORTUGUESE: &[(&str, &str)] = &[
|
||||
("Video", "Vídeo"),
|
||||
("channel", "canal"),
|
||||
("files", "arquivos"),
|
||||
("Video Scopes", "Escopos de vídeo"),
|
||||
("GPU Acceleration (no GPU: software)", "Aceleração de GPU (sem GPU: software)"),
|
||||
];
|
||||
|
||||
/// Polish (pl): original translations covering every row in the Chinese panel catalogs.
|
||||
@@ -6629,8 +6638,8 @@ const POLISH: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "Importuj plik Photoshopa"),
|
||||
("Interpret Unlabeled Alpha As", "Interpretuj nieoznaczoną alfę jako"),
|
||||
("Join the ArtCraft Discord", "Dołącz do Discorda ArtCraft"),
|
||||
("Mercury GPU Acceleration ({})", "Akceleracja Mercury GPU ({})"),
|
||||
("Mercury Software Only", "Tylko programowy Mercury"),
|
||||
("GPU Acceleration ({})", "Akceleracja GPU ({})"),
|
||||
("Software Rendering", "Renderowanie programowe"),
|
||||
("OCIO (built-in ACES config)", "OCIO (wbudowana konfiguracja ACES)"),
|
||||
("Off (Final Quality)", "Wył. (jakość końcowa)"),
|
||||
("OpenGL (compatibility)", "OpenGL (zgodność)"),
|
||||
@@ -6868,6 +6877,8 @@ const POLISH: &[(&str, &str)] = &[
|
||||
("Resolution:", "Rozdzielczość:"),
|
||||
("Guide Layer", "Warstwa pomocnicza"),
|
||||
("Layer Styles", "Style warstwy"),
|
||||
("Video Scopes", "Wskaźniki wideo"),
|
||||
("GPU Acceleration (no GPU: software)", "Akceleracja GPU (bez GPU: programowa)"),
|
||||
];
|
||||
|
||||
/// Czech (cs): original translations covering every row in the Chinese panel catalogs.
|
||||
@@ -7380,8 +7391,8 @@ const CZECH: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "Importovat soubor Photoshop"),
|
||||
("Interpret Unlabeled Alpha As", "Interpretovat neoznačenou alfu jako"),
|
||||
("Join the ArtCraft Discord", "Připojit se na Discord ArtCraft"),
|
||||
("Mercury GPU Acceleration ({})", "GPU akcelerace Mercury ({})"),
|
||||
("Mercury Software Only", "Pouze softwarové zpracování Mercury"),
|
||||
("GPU Acceleration ({})", "Akcelerace GPU ({})"),
|
||||
("Software Rendering", "Softwarové vykreslování"),
|
||||
("OCIO (built-in ACES config)", "OCIO (vestavěná konfigurace ACES)"),
|
||||
("Off (Final Quality)", "Vypnuto (finální kvalita)"),
|
||||
("OpenGL (compatibility)", "OpenGL (kompatibilita)"),
|
||||
@@ -7432,6 +7443,8 @@ const CZECH: &[(&str, &str)] = &[
|
||||
("Variable fonts only", "Jen proměnná písma"),
|
||||
("Total Offset", "Celkový posun"),
|
||||
("Per Layer", "Na vrstvu"),
|
||||
("Video Scopes", "Videoskopy"),
|
||||
("GPU Acceleration (no GPU: software)", "Akcelerace GPU (bez GPU: software)"),
|
||||
];
|
||||
|
||||
/// Spanish: neutral, tú, sentence case; the same source strings as the Chinese catalogs, in the same
|
||||
@@ -7960,8 +7973,8 @@ const SPANISH: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "Importar archivo de Photoshop"),
|
||||
("Interpret Unlabeled Alpha As", "Interpretar alfa sin etiquetar como"),
|
||||
("Join the ArtCraft Discord", "Únete al Discord de ArtCraft"),
|
||||
("Mercury GPU Acceleration ({})", "Aceleración por GPU Mercury ({})"),
|
||||
("Mercury Software Only", "Solo software Mercury"),
|
||||
("GPU Acceleration ({})", "Aceleración por GPU ({})"),
|
||||
("Software Rendering", "Renderizado por software"),
|
||||
("OCIO (built-in ACES config)", "OCIO (configuración ACES integrada)"),
|
||||
("Off (Final Quality)", "Desactivado (calidad final)"),
|
||||
("OpenGL (compatibility)", "OpenGL (compatibilidad)"),
|
||||
@@ -8002,6 +8015,8 @@ const SPANISH: &[(&str, &str)] = &[
|
||||
("After Effects project", "Proyecto de After Effects"),
|
||||
("Lottie animation", "Animación de Lottie"),
|
||||
("Project", "Proyecto"),
|
||||
("Video Scopes", "Monitores de vídeo"),
|
||||
("GPU Acceleration (no GPU: software)", "Aceleración por GPU (sin GPU: software)"),
|
||||
];
|
||||
|
||||
/// Georgian (ka): every row of the Chinese catalogs, in the same order (the tests keep them in step).
|
||||
@@ -8528,8 +8543,8 @@ const GEORGIAN: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "Photoshop ფაილის იმპორტი"),
|
||||
("Interpret Unlabeled Alpha As", "უცნობი ალფას ინტერპრეტაცია"),
|
||||
("Join the ArtCraft Discord", "შემოგვიერთდით Discord-ზე"),
|
||||
("Mercury GPU Acceleration ({})", "GPU აჩქარება ({})"),
|
||||
("Mercury Software Only", "მხოლოდ Mercury Software"),
|
||||
("GPU Acceleration ({})", "GPU აჩქარება ({})"),
|
||||
("Software Rendering", "პროგრამული რენდერი"),
|
||||
("OCIO (built-in ACES config)", "OCIO (ჩაშენებული ACES კონფიგურაცია)"),
|
||||
("Off (Final Quality)", "გამორთული (საბოლოო ხარისხი)"),
|
||||
("OpenGL (compatibility)", "OpenGL (თავსებადობა)"),
|
||||
@@ -8761,6 +8776,7 @@ const GEORGIAN: &[(&str, &str)] = &[
|
||||
("Total Offset", "ჯამური წანაცვლება"),
|
||||
("Per Layer", "შრიდან შრემდე"),
|
||||
("Track", "ტრეკინგი"),
|
||||
("Video Scopes", "ვიდეოსკოპები"),
|
||||
];
|
||||
|
||||
/// Georgian rows for interface text no other catalog has yet: strings the panels already send
|
||||
@@ -8951,7 +8967,7 @@ const GEORGIAN_PANELS: &[(&str, &str)] = &[
|
||||
("Solid Settings", "სოლიდის პარამეტრები"),
|
||||
("Save as Template", "შაბლონად შენახვა"),
|
||||
("My Custom RGB", "ჩემი მორგებული RGB"),
|
||||
("Mercury GPU Acceleration (no GPU: software)", "Mercury GPU აჩქარება (GPU არ არის: პროგრამული)"),
|
||||
("GPU Acceleration (no GPU: software)", "GPU აჩქარება (GPU არ არის: პროგრამული)"),
|
||||
("Sort by {}, {}", "დალაგება: {}, {}"),
|
||||
("Sort by {}", "დალაგება: {}"),
|
||||
("Label of {}: {}", "{}-ის იარლიყი: {}"),
|
||||
@@ -9510,8 +9526,8 @@ const FRENCH: &[(&str, &str)] = &[
|
||||
("Import Photoshop File", "Importer un fichier Photoshop"),
|
||||
("Interpret Unlabeled Alpha As", "Interpréter l’alpha non étiqueté comme"),
|
||||
("Join the ArtCraft Discord", "Rejoindre le Discord ArtCraft"),
|
||||
("Mercury GPU Acceleration ({})", "Accélération GPU Mercury ({})"),
|
||||
("Mercury Software Only", "Mercury, logiciel uniquement"),
|
||||
("GPU Acceleration ({})", "Accélération GPU ({})"),
|
||||
("Software Rendering", "Rendu logiciel"),
|
||||
("OCIO (built-in ACES config)", "OCIO (configuration ACES intégrée)"),
|
||||
("Off (Final Quality)", "Désactivé (qualité finale)"),
|
||||
("OpenGL (compatibility)", "OpenGL (compatibilité)"),
|
||||
@@ -9926,7 +9942,7 @@ const FRENCH: &[(&str, &str)] = &[
|
||||
("Solid Settings", "Paramètres du solide"),
|
||||
("Save as Template", "Enregistrer en tant que modèle"),
|
||||
("My Custom RGB", "Mon RVB personnalisé"),
|
||||
("Mercury GPU Acceleration (no GPU: software)", "Accélération GPU Mercury (aucun GPU : logiciel)"),
|
||||
("GPU Acceleration (no GPU: software)", "Accélération GPU (aucun GPU : logiciel)"),
|
||||
("Sort by {}, {}", "Trier par {}, {}"),
|
||||
("Sort by {}", "Trier par {}"),
|
||||
("Label of {}: {}", "Étiquette de {} : {}"),
|
||||
@@ -10047,7 +10063,7 @@ const FRENCH: &[(&str, &str)] = &[
|
||||
("Script Console", "Console de scripts"),
|
||||
("Essential Graphics", "Graphiques essentiels"),
|
||||
("ScriptUI Panel", "Panneau ScriptUI"),
|
||||
("Lumetri Scopes", "Scopes Lumetri"),
|
||||
("Video Scopes", "Oscilloscopes vidéo"),
|
||||
("Media Browser", "Explorateur de médias"),
|
||||
("Content-Aware Fill", "Remplissage adapté au contenu"),
|
||||
("Create Nulls From Paths", "Créer des objets nuls à partir de tracés"),
|
||||
@@ -10266,6 +10282,26 @@ const FRENCH: &[(&str, &str)] = &[
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// Check rendered feature labels only. Format names, compatibility tokens and user text
|
||||
/// are not subject to this guard, and a missing translation keeps its English fallback.
|
||||
#[test]
|
||||
fn renamed_panel_labels_do_not_reintroduce_vendor_names() {
|
||||
for language in ["en", "ja", "zh-hans", "zh-hant", "fr", "sv", "ka", "cs", "de", "es", "pl", "pt-br", "ru", "uk"] {
|
||||
set_current(language);
|
||||
for source in ["GPU Acceleration ({})", "GPU Acceleration (no GPU: software)", "Software Rendering", "Video Scopes"] {
|
||||
let rendered = tr(source);
|
||||
assert!(!rendered.is_empty(), "{language}: {source}");
|
||||
let label = rendered.to_lowercase();
|
||||
for mark in ["lumetri", "mercury", "mocha", "keylight"] {
|
||||
assert!(!label.contains(mark), "{language}: {source} -> {rendered}");
|
||||
}
|
||||
}
|
||||
// A real interchange label remains factual, not rewritten or rejected.
|
||||
assert!(!tr("Export Adobe Premiere Pro Project").is_empty());
|
||||
}
|
||||
set_current("en");
|
||||
}
|
||||
|
||||
/// The interface text that has moved into this catalog. Add a panel here when you convert it;
|
||||
/// `every_row_is_used_by_a_converted_panel` then looks for its rows' English sources in it.
|
||||
pub(super) const CONVERTED: &[(&str, &str)] = &[
|
||||
|
||||
@@ -338,11 +338,11 @@ fn interpret_footage_form(s: &effectcraft_engine::Session, proxy: bool, base: &m
|
||||
/// The Project Settings dialog's title and fields.
|
||||
fn project_settings_form(s: &effectcraft_engine::Session) -> (String, Vec<Field>) {
|
||||
let st = &s.project.settings;
|
||||
// The catalogue row is `Mercury GPU Acceleration ({})`, so the value goes through
|
||||
// The catalogue row is `GPU Acceleration ({})`, so the value goes through
|
||||
// tr_args: wrapping the assembled string in tr() would look up the backend's name.
|
||||
let gpu_label = match &s.accel {
|
||||
Some(a) => tr_args("Mercury GPU Acceleration ({})", &[&a.name()]),
|
||||
None => tr("Mercury GPU Acceleration (no GPU: software)").to_string(),
|
||||
Some(a) => tr_args("GPU Acceleration ({})", &[&a.name()]),
|
||||
None => tr("GPU Acceleration (no GPU: software)").to_string(),
|
||||
};
|
||||
let depth = match st.bit_depth.label() {
|
||||
l if l.starts_with("16") => 1,
|
||||
@@ -436,7 +436,7 @@ fn project_settings_form(s: &effectcraft_engine::Session) -> (String, Vec<Field>
|
||||
Field::choice(
|
||||
"renderer",
|
||||
"Video rendering and effects",
|
||||
&[(gpu_label.as_str(), json!("gpu")), ("Mercury Software Only", json!("software"))],
|
||||
&[(gpu_label.as_str(), json!("gpu")), ("Software Rendering", json!("software"))],
|
||||
usize::from(!st.gpu_acceleration),
|
||||
),
|
||||
],
|
||||
@@ -1050,6 +1050,18 @@ pub fn show_view_options(app: &mut EffectcraftApp, ctx: &egui::Context, t: &Toke
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn renderer_form_keeps_descriptive_labels_and_stable_option_values() {
|
||||
crate::i18n::set_current("en");
|
||||
let (_, fields) = project_settings_form(&effectcraft_engine::Session::default());
|
||||
let renderer = fields.iter().find(|field| field.key == "renderer").unwrap();
|
||||
let FieldKind::Choice { options, .. } = &renderer.kind else { panic!("renderer must be a choice") };
|
||||
assert_eq!(
|
||||
options.as_slice(),
|
||||
&[("GPU Acceleration (no GPU: software)".to_string(), json!("gpu")), ("Software Rendering".to_string(), json!("software"))]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn form_params_build_arrays_and_choices() {
|
||||
let f = Form {
|
||||
|
||||
@@ -756,7 +756,7 @@ pub struct UiState {
|
||||
/// Flowchart panel options (layers, effects, solids, direction, root comp).
|
||||
#[serde(default)]
|
||||
pub flowchart: crate::panels::flowchart::FlowOptions,
|
||||
/// Lumetri Scopes panel options.
|
||||
/// Video Scopes panel options.
|
||||
#[serde(default)]
|
||||
pub scopes: crate::panels::scopes_panel::ScopesState,
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ fn harness(panel: Panel, angle: f64) -> (Harness<'static, EffectcraftApp>, u64,
|
||||
s.execute("comp.new", json!({"name": "Angles", "width": 320, "height": 180, "duration": 4})).unwrap();
|
||||
let layer = s.execute("layer.newSolid", json!({"name": "Plate", "color": "#40b080"})).unwrap()["layer"].as_u64().unwrap();
|
||||
let uid = if matches!(panel, Panel::EffectControls) {
|
||||
let fx = s.execute("effect.apply", json!({"layer": layer, "effect": "CC Bend It"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let fx = s.execute("effect.apply", json!({"layer": layer, "effect": "Two-Point Bend"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
s.active_comp().unwrap().layer(LayerId(layer)).unwrap().props.find_group(fx).unwrap().get("bend").unwrap().uid
|
||||
} else {
|
||||
s.active_comp().unwrap().layer(LayerId(layer)).unwrap().props.prop("transform/rotation").unwrap().uid
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! The colour picker every colour input opens: its hex field sets an effect's colour (CC Toner),
|
||||
//! The colour picker every colour input opens: its hex field sets an effect's colour (Multi-Tone Tint),
|
||||
//! the dialogs' colour button stores sRGB (egui's own `color_edit_button_rgba` read the stored
|
||||
//! sRGB values as linear, so mid-grey `#808080` was stored as `#373737`), the square, slider and
|
||||
//! HSB / RGB fields set the colour, and Cancel / Escape / the original swatch restore it.
|
||||
@@ -45,7 +45,7 @@ fn hex_code_sets_an_effect_colour() {
|
||||
let mut s = Session::default();
|
||||
s.execute("comp.new", json!({"name": "Hex", "width": 320, "height": 180, "duration": 4})).unwrap();
|
||||
let layer = s.execute("layer.newSolid", json!({"name": "Plate", "color": "#40b080"})).unwrap()["layer"].as_u64().unwrap();
|
||||
let fx = s.execute("effect.apply", json!({"layer": layer, "effect": "CC Toner"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let fx = s.execute("effect.apply", json!({"layer": layer, "effect": "Multi-Tone Tint"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let uid = s.active_comp().unwrap().layer(LayerId(layer)).unwrap().props.find_group(fx).unwrap().get("midtones").unwrap().uid;
|
||||
s.state.selected_layers = vec![LayerId(layer)];
|
||||
let mut app = EffectcraftApp::new(s);
|
||||
|
||||
@@ -260,14 +260,14 @@ fn the_eyedropper_stays_armed_until_the_viewer_has_a_frame() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Key Light's Screen Colour eyedropper picks from the effect's input: the shown frame is
|
||||
/// Screen Color Key's Screen Colour eyedropper picks from the effect's input: the shown frame is
|
||||
/// already keyed (the default screen colour takes most of a green), so sampling it would miss.
|
||||
#[test]
|
||||
fn keyer_eyedropper_picks_the_screen_from_the_effect_input() {
|
||||
let mut s = Session::default();
|
||||
s.execute("comp.new", json!({"name": "Key", "width": 320, "height": 180, "frameRate": 30, "duration": 1})).unwrap();
|
||||
let screen = s.execute("layer.newSolid", json!({"name": "Screen", "color": "#30b050"})).unwrap()["layer"].as_u64().unwrap();
|
||||
let fx = s.execute("effect.apply", json!({"layers": [screen], "effect": "Key Light"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let fx = s.execute("effect.apply", json!({"layers": [screen], "effect": "Screen Color Key"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let prop = layer(&s, screen).effects().unwrap().groups().find(|g| g.uid == fx).and_then(|g| g.get("screenColour")).map(|p| p.uid).unwrap();
|
||||
s.state.selected_layers = vec![LayerId(screen)];
|
||||
let mut app = EffectcraftApp::new(s);
|
||||
@@ -295,7 +295,7 @@ fn keyer_eyedropper_picks_the_screen_from_the_effect_input() {
|
||||
fn command_clicking_an_effect_twirl_closes_and_opens_its_groups() {
|
||||
let (app, x) = app();
|
||||
let mut h = Harness::builder().with_size(egui::vec2(1600.0, 1000.0)).build_eframe(|_| app);
|
||||
let fx = h.state_mut().session.execute("effect.apply", json!({"layers": [x.small], "effect": "Lumetri Color"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let fx = h.state_mut().session.execute("effect.apply", json!({"layers": [x.small], "effect": "Color Grading"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
// Only this effect open, so its header is on screen.
|
||||
let l = layer(&h.state().session, x.small);
|
||||
let others: Vec<u64> = l.effects().unwrap().groups().map(|g| g.uid).filter(|u| *u != fx).collect();
|
||||
|
||||
@@ -13,7 +13,7 @@ fn rect(h: &Harness<'_, EffectcraftApp>, id: &str) -> Rect {
|
||||
fn drag_to(h: &mut Harness<'_, EffectcraftApp>, p: Pos2) {
|
||||
h.input_mut().events.push(Event::PointerMoved(p));
|
||||
h.input_mut().events.push(Event::PointerButton { pos: p, button: PointerButton::Primary, pressed: true, modifiers: Modifiers::NONE });
|
||||
egui::DragAndDrop::set_payload(&h.ctx, DragPayload::Effect("CC Bend It".into()));
|
||||
egui::DragAndDrop::set_payload(&h.ctx, DragPayload::Effect("Two-Point Bend".into()));
|
||||
h.run_steps(2);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ fn undo(h: &mut Harness<'_, EffectcraftApp>) {
|
||||
|
||||
#[test]
|
||||
fn lumetri_rgb_and_hue_saturation_curve_editors() {
|
||||
let (s0, l, fx) = with_effect("Lumetri Color");
|
||||
let (s0, l, fx) = with_effect("Color Grading");
|
||||
let mut h = harness(s0);
|
||||
only_groups(&mut h, l, fx, &["curves", "rgbCurves", "hueSaturationCurves"]);
|
||||
let pre = format!("effectControls.effect.{fx}.lumetri.rgbCurves");
|
||||
|
||||
@@ -77,12 +77,12 @@ fn position_anchor_and_effect_edits_present_intermediate_pixels() {
|
||||
(None, "transform/position", json!([22, 18, 0]), json!([18, 18, 0])),
|
||||
(None, "transform/anchor", json!([9, 8, 0]), json!([6, 8, 0])),
|
||||
(Some("Gaussian Blur"), "blurriness", json!(3), json!(6)),
|
||||
(Some("CC Radial Fast Blur"), "center", json!([4, 4]), json!([18, 12])),
|
||||
(Some("Fast Radial Blur"), "center", json!([4, 4]), json!([18, 12])),
|
||||
] {
|
||||
let mut session = Session::default();
|
||||
session.execute("comp.new", json!({"width":64,"height":36,"duration":1})).unwrap();
|
||||
let layer = session.execute("layer.newSolid", json!({"color":"#ffffff","width":24,"height":16})).unwrap()["layer"].as_u64().unwrap();
|
||||
if effect == Some("CC Radial Fast Blur") {
|
||||
if effect == Some("Fast Radial Blur") {
|
||||
// A uniform solid is invariant under a radial blur; give the point edit visible detail.
|
||||
session.execute("effect.apply", json!({"layers":[layer],"effect":"Gradient Ramp"})).unwrap();
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ fn nested_groups_keep_indentation_value_alignment_and_effect_gaps_at_fixed_compa
|
||||
let mut s = Session::default();
|
||||
s.execute("comp.new", json!({"width":64,"height":36,"duration":1})).unwrap();
|
||||
s.execute("layer.newSolid", json!({"name":"Plate","color":"#406080"})).unwrap();
|
||||
let fx = s.execute("effect.apply", json!({"effect":"Lumetri Color"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let fx = s.execute("effect.apply", json!({"effect":"Color Grading"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let next = s.execute("effect.apply", json!({"effect":"Checkbox Control"})).unwrap()["effects"][0].as_u64().unwrap();
|
||||
let g = s.active_comp().unwrap().layers[0].props.find_group(fx).unwrap();
|
||||
let basic = g.sub("basicCorrection").unwrap();
|
||||
|
||||
@@ -2370,7 +2370,7 @@ fn command_clicking_a_group_twirl_opens_its_whole_tree() {
|
||||
// twirls open with it, and closed again with it.
|
||||
let mut h = harness();
|
||||
let id = layer_id(&h, "Box");
|
||||
h.state_mut().session.execute("effect.apply", json!({"effect": "Lumetri Color", "layers": [id]})).unwrap();
|
||||
h.state_mut().session.execute("effect.apply", json!({"effect": "Color Grading", "layers": [id]})).unwrap();
|
||||
fn walk(g: &effectcraft_engine::project::PropGroup, out: &mut Vec<u64>) {
|
||||
for sg in g.groups() {
|
||||
out.push(sg.uid);
|
||||
|
||||
+13
-13
@@ -121,7 +121,7 @@ are not rewritten, so an expression that computes an effect point on a shape or
|
||||
other values may need `+ [thisComp.width / 2, thisComp.height / 2]`. Effects that use the layer
|
||||
bounds (edge pinning, wipes, Offset, generators) now cover the whole comp-sized bounds instead of
|
||||
their bottom-right quarter. Tracking data of effects that analyse footage (Warp Stabilizer, 3D
|
||||
Camera Tracker, Mocha shape) is left as it is: footage has a source rectangle, whose effect space
|
||||
Camera Tracker, Tracked Shape Matte) is left as it is: footage has a source rectangle, whose effect space
|
||||
did not change.
|
||||
|
||||
## 4. Rendering
|
||||
@@ -331,7 +331,7 @@ before conversion (a quarter of the conversions; the result differs from convert
|
||||
in blocks where colours clip) and resampled from there, as other frames are from full size.
|
||||
|
||||
**GPU compositor** (`crates/gpu`; Project Settings ▸ Video Rendering and Effects ▸ Mercury GPU
|
||||
Acceleration, the default, or Mercury Software Only; `render.backend`). The CPU renderer is the
|
||||
Acceleration, the default, or Software Rendering; `render.backend`). The CPU renderer is the
|
||||
reference and keeps rendering layer content (sources, masks, CPU effects, layer styles) into the
|
||||
layer cache. The render crate defines an `Accelerator` trait; `effectcraft_gpu::Gpu` implements it
|
||||
on wgpu compute shaders. `RenderOpts::backend` picks `Cpu`, `Gpu` or `Auto` (an accelerator
|
||||
@@ -341,7 +341,7 @@ per comp, output scale and path (readback or viewer display) it averages CPU and
|
||||
(warm-up on both sides, the fastest warm-up frame starting the average, single stalls capped),
|
||||
picks the GPU unless the CPU is clearly faster, and re-measures the other side every 48 frames.
|
||||
Render Queue jobs don't use Auto: every frame of a job renders on the project's renderer (the
|
||||
GPU compositor with Mercury GPU Acceleration), so runs of a render don't differ by timing.
|
||||
GPU compositor with GPU Acceleration), so runs of a render don't differ by timing.
|
||||
Light comps (a few small layers, which the CPU composites only within their bounds) then stay on
|
||||
the CPU instead of paying for full-frame passes and a readback. A GPU frame walks the comp like
|
||||
`draw_comp`: cached layer buffers are uploaded once per buffer, then transformed with the CPU's
|
||||
@@ -370,16 +370,16 @@ Preserve Transparency / blend kernels (a 3D track matte renders solo through the
|
||||
Environment Light Background layers draw their sky in a kernel (`adv_sky`, from
|
||||
`Renderer::sky_draw`) before the rest of the run, in Classic and Advanced 3D comps. Wireframe
|
||||
outlines draw on the GPU from the CPU's pixel list (`Renderer::wireframe_pixels`). GPU effects
|
||||
(`effects::GPU_EFFECTS`, 280 of them: blurs, colour correction, keying incl. Key Light, mattes,
|
||||
channel, stylize, distortion and warps (Warp, Bezier Warp, Smear, Reshape, CC Bend It, CC Page
|
||||
Turn, CC Bender, CC Blobbylize), Cartoon, bevels, shapes, the transitions (CC light family, CC
|
||||
transitions, Block Dissolve), perspective (Radial Shadow, CC Cylinder / Sphere / Spotlight /
|
||||
(`effects::GPU_EFFECTS`, 280 of them: blurs, colour correction, keying incl. Screen Color Key, mattes,
|
||||
channel, stylize, distortion and warps (Warp, Bezier Warp, Smear, Reshape, Two-Point Bend, CC Page
|
||||
Turn, Flexible Bend, Organic Displacement), Cartoon, bevels, shapes, the transitions (CC light family, CC
|
||||
transitions, Block Dissolve), perspective (Radial Shadow, Cylinder Wrap / Sphere / Spotlight /
|
||||
Environment, 3D Glasses), generators, noise, grain, text (Numbers, Timecode), time, 3D Channel (aux channels as an
|
||||
extra texture), Immersive Video, colour management (colour programs from
|
||||
`effects::color_program`, LUTs in a storage buffer) and the simulations' render passes (the
|
||||
simulation stays on the CPU and hands its plan — sprites, pieces, blobs, grids — to a tiled
|
||||
rasteriser; the particle effects too, `gpu::fx_particles`: CC Particle World / Systems II,
|
||||
Particle Playground with its Layer Map frames in one atlas, CC Ball Action, CC Pixel Polly, CC
|
||||
rasteriser; the particle effects too, `gpu::fx_particles`: Particle Emitter 3D / Systems II,
|
||||
Particle Playground with its Layer Map frames in one atlas, Ball Grid, Pixel Shatter, CC
|
||||
Scatterize; plans too large for one item table draw in several passes over the previous one),
|
||||
and the geometry generators (Lightning, Advanced Lightning, Radio Waves, Stroke, Scribble,
|
||||
Vegas, Write-on, Audio Spectrum / Waveform, Basic / Path Text: bolts, strokes, waves, audio
|
||||
@@ -390,7 +390,7 @@ as kernels, in one module per family (`gpu::fx_*` with `shaders/fx_*.wgsl`); con
|
||||
effects run as one chain with one upload and one readback. Statistics that need the whole frame
|
||||
(Auto Levels / Contrast / Color, Equalize, Shadow/Highlight, Color Stabilizer, Remove Grain's
|
||||
noise level) are measured on the CPU from one readback and applied on the GPU; effects reading
|
||||
other frames (Echo, Posterize Time, Time Difference, Time Displacement, CC Force Motion Blur, CC
|
||||
other frames (Echo, Posterize Time, Time Difference, Time Displacement, Temporal Motion Blur, CC
|
||||
Wide Time, Pixel Motion Blur, Timewarp) upload the frames the host renders (`time_frames`) and
|
||||
combine them on the GPU; Time Displacement's per-pixel times and Timewarp's motion vectors
|
||||
(`time_fx::timewarp_plan`) are computed on the CPU. Numbers and Timecode rasterise their glyph
|
||||
@@ -433,12 +433,12 @@ sentinel is implemented here. Browser scope futures are not synchronously awaite
|
||||
forwards shared-device errors, while owned worker devices install their own handlers. On the web
|
||||
(WebGPU) the GPU composites viewer frames; steps that need a readback fall back to the CPU (the
|
||||
Info panel's pixel readout reads GPU frames back asynchronously). **GPU particles**
|
||||
(`effects::psim`, `gpu::particles`): CC Particle World, CC Particle Systems II and Particle
|
||||
(`effects::psim`, `gpu::particles`): Particle Emitter 3D, Particle Emitter 2D and Particle
|
||||
Playground cannons without interacting forces evolve every particle independently, so the GPU
|
||||
backend (reached through `EffectHost::particles` when the GPU compositor is active) simulates one
|
||||
particle per invocation from the CPU's birth schedule and keeps per-key state checkpoints on the
|
||||
GPU, like `SimCache`; the CPU simulation stays the oracle (tests compare ids and positions).
|
||||
CC Particle World, CC Particle Systems II and CC Mr. Mercury sample their Birth Rate at every
|
||||
Particle Emitter 3D, Particle Emitter 2D and Liquid Particles sample their Birth Rate at every
|
||||
step (`EffectHost::param_at`, #1373), so a keyed rate only decides the births of its own time;
|
||||
the rate is left out of the simulation key, and a checkpoint is resumed only with the same rate history (the CPU state's `hist`, the GPU
|
||||
checkpoint's births). The rate's keyframes are read at the step's exact layer time
|
||||
@@ -629,7 +629,7 @@ Unix milliseconds. The layer's Start Time becomes `dataStart + videoStart − fi
|
||||
(`videoStart` given, or the file's creation date on the desktop; reduced to a time of day when
|
||||
the data has no dates).
|
||||
|
||||
**Lumetri Scopes** (`raster::scopes`) are density plots of the viewer frame (rendered over the
|
||||
**Video Scopes** (`raster::scopes`) are density plots of the viewer frame (rendered over the
|
||||
comp background) with BT.601 / BT.709 / BT.2020 luma and colour-difference coefficients.
|
||||
|
||||
## 5. Expressions
|
||||
|
||||
+72
-72
@@ -48,21 +48,21 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Bilateral Blur | `ec.blur.bilateral` | 3 | GPU | 32 | Implemented |
|
||||
| CC Cross Blur | `ec.blur.cccross` | 3 | GPU | 32 | Implemented |
|
||||
| CC Radial Blur | `ec.blur.ccradial` | 4 | GPU | 32 | Implemented |
|
||||
| CC Radial Fast Blur | `ec.blur.ccradialfast` | 3 | GPU | 32 | Implemented |
|
||||
| CC Vector Blur | `ec.blur.ccvector` | 4 | GPU | 32 | Implemented |
|
||||
| Camera Lens Blur | `ec.blur.cameralens` | 16 | GPU | 32 | Implemented |
|
||||
| Camera-Shake Deblur | `ec.blur.camerashakedeblur` | 8 | | 32 | Implemented |
|
||||
| Channel Blur | `ec.blur.channel` | 6 | GPU | 32 | Implemented |
|
||||
| Compound Blur | `ec.blur.compound` | 4 | GPU | 32 | Implemented |
|
||||
| Cross Blur | `ec.blur.cccross` | 3 | GPU | 32 | Implemented |
|
||||
| Directional Blur | `ec.blur.directional` | 2 | GPU | 32 | Implemented |
|
||||
| Fast Box Blur | `ec.blur.fastbox` | 4 | GPU | 32 | Implemented |
|
||||
| Fast Radial Blur | `ec.blur.ccradialfast` | 3 | GPU | 32 | Implemented |
|
||||
| Gaussian Blur | `ec.blur.gaussian` | 3 | GPU | 32 | Implemented |
|
||||
| Radial Blur | `ec.blur.radial` | 4 | GPU | 32 | Implemented |
|
||||
| Sharpen | `ec.blur.sharpen` | 1 | GPU | 32 | Implemented |
|
||||
| Smart Blur | `ec.blur.smart` | 3 | GPU | 32 | Implemented |
|
||||
| Unsharp Mask | `ec.blur.unsharp` | 3 | GPU | 32 | Implemented |
|
||||
| Variable Radial Blur | `ec.blur.ccradial` | 4 | GPU | 32 | Implemented |
|
||||
| Vector Blur | `ec.blur.ccvector` | 4 | GPU | 32 | Implemented |
|
||||
|
||||
## Channel
|
||||
|
||||
@@ -70,7 +70,6 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Arithmetic | `ec.channel.arithmetic` | 5 | GPU | 32 | Implemented |
|
||||
| Blend | `ec.channel.blend` | 4 | GPU | 32 | Implemented |
|
||||
| CC Composite | `ec.channel.cccomposite` | 3 | GPU | 32 | Implemented |
|
||||
| Calculations | `ec.channel.calculations` | 9 | GPU | 32 | Implemented |
|
||||
| Channel Combiner | `ec.channel.combiner` | 6 | GPU | 32 | Implemented |
|
||||
| Compound Arithmetic | `ec.channel.compoundarithmetic` | 6 | GPU | 32 | Implemented |
|
||||
@@ -81,6 +80,7 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Set Matte | `ec.channel.setmatte` | 6 | GPU | 32 | Implemented |
|
||||
| Shift Channels | `ec.channel.shiftchannels` | 4 | GPU | 32 | Implemented |
|
||||
| Solid Composite | `ec.channel.solidcomposite` | 4 | GPU | 32 | Implemented |
|
||||
| Source Composite | `ec.channel.cccomposite` | 3 | GPU | 32 | Implemented |
|
||||
|
||||
## Color Correction
|
||||
|
||||
@@ -92,18 +92,18 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Black & White | `ec.color.blackwhite` | 8 | GPU | 32 | Implemented |
|
||||
| Brightness & Contrast | `ec.color.brightnesscontrast` | 3 | GPU | 32 | Implemented |
|
||||
| Broadcast Colors | `ec.color.broadcast` | 3 | GPU | 32 | Implemented |
|
||||
| CC Color Neutralizer | `ec.color.cccolorneutralizer` | 11 | GPU | 32 | Implemented |
|
||||
| CC Color Offset | `ec.color.cccoloroffset` | 4 | GPU | 32 | Implemented |
|
||||
| CC Kernel | `ec.color.cckernel` | 12 | GPU | 32 | Implemented |
|
||||
| CC Toner | `ec.color.cctoner` | 7 | GPU | 32 | Implemented |
|
||||
| Change Color | `ec.color.changecolor` | 9 | GPU | 32 | Implemented |
|
||||
| Change to Color | `ec.color.changetocolor` | 9 | GPU | 32 | Implemented |
|
||||
| Channel Mixer | `ec.color.channelmixer` | 13 | GPU | 32 | Implemented |
|
||||
| Channel Offset | `ec.color.cccoloroffset` | 4 | GPU | 32 | Implemented |
|
||||
| Color Balance | `ec.color.colorbalance` | 10 | GPU | 32 | Implemented |
|
||||
| Color Balance (HLS) | `ec.color.colorbalancehls` | 3 | GPU | 32 | Implemented |
|
||||
| Color Grading | `ec.color.lumetri` | 66 | GPU | 32 | Implemented |
|
||||
| Color Link | `ec.color.colorlink` | 6 | GPU | 32 | Implemented |
|
||||
| Color Neutralizer | `ec.color.cccolorneutralizer` | 11 | GPU | 32 | Implemented |
|
||||
| Color Stabilizer | `ec.color.colorstabilizer` | 6 | GPU | 32 | Implemented |
|
||||
| Colorama | `ec.color.colorama` | 20 | GPU | 32 | Implemented |
|
||||
| Convolution Kernel | `ec.color.cckernel` | 12 | GPU | 32 | Implemented |
|
||||
| Curves | `ec.color.curves` | 0 | GPU | 32 | Implemented |
|
||||
| Equalize | `ec.color.equalize` | 2 | GPU | 32 | Implemented |
|
||||
| Exposure | `ec.color.exposure` | 14 | GPU | 32 | Implemented |
|
||||
@@ -112,7 +112,7 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Leave Color | `ec.color.leavecolor` | 5 | GPU | 32 | Implemented |
|
||||
| Levels | `ec.color.levels` | 36 | GPU | 32 | Implemented |
|
||||
| Levels (Individual Controls) | `ec.color.levelsic` | 27 | GPU | 32 | Implemented |
|
||||
| Lumetri Color | `ec.color.lumetri` | 66 | GPU | 32 | Implemented |
|
||||
| Multi-Tone Tint | `ec.color.cctoner` | 7 | GPU | 32 | Implemented |
|
||||
| OCIO CDL Transform | `ec.color.ociocdl` | 12 | GPU | 32 | Implemented |
|
||||
| OCIO Color Space Transform | `ec.color.ociocolorspace` | 7 | GPU | 32 | Implemented |
|
||||
| OCIO Display Transform | `ec.color.ociodisplay` | 9 | GPU | 32 | Implemented |
|
||||
@@ -133,40 +133,40 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Bezier Warp | `ec.distort.bezierwarp` | 13 | GPU | 32 | Implemented |
|
||||
| Bulge | `ec.distort.bulge` | 6 | GPU | 32 | Implemented |
|
||||
| CC Bend It | `ec.distort.ccbendit` | 4 | GPU | 32 | Implemented |
|
||||
| CC Bender | `ec.distort.ccbender` | 5 | GPU | 32 | Implemented |
|
||||
| CC Blobbylize | `ec.distort.ccblobbylize` | 15 | GPU | 32 | Implemented |
|
||||
| CC Flo Motion | `ec.distort.ccflomotion` | 7 | GPU | 32 | Implemented |
|
||||
| CC Griddler | `ec.distort.ccgriddler` | 5 | GPU | 32 | Implemented |
|
||||
| CC Lens | `ec.distort.cclens` | 3 | GPU | 32 | Implemented |
|
||||
| CC Page Turn | `ec.distort.ccpageturn` | 7 | GPU | 32 | Implemented |
|
||||
| CC Power Pin | `ec.distort.ccpowerpin` | 10 | GPU | 32 | Implemented |
|
||||
| CC Ripple Pulse | `ec.distort.ccripplepulse` | 5 | GPU | 32 | Implemented |
|
||||
| CC Slant | `ec.distort.ccslant` | 4 | GPU | 32 | Implemented |
|
||||
| CC Smear | `ec.distort.ccsmear` | 4 | GPU | 32 | Implemented |
|
||||
| CC Split | `ec.distort.ccsplit` | 3 | GPU | 32 | Implemented |
|
||||
| CC Split 2 | `ec.distort.ccsplit2` | 4 | GPU | 32 | Implemented |
|
||||
| CC Tiler | `ec.distort.cctiler` | 3 | GPU | 32 | Implemented |
|
||||
| Corner Pin | `ec.distort.cornerpin` | 4 | GPU | 32 | Implemented |
|
||||
| Detail-preserving Upscale | `ec.distort.upscale` | 4 | | 32 | Implemented |
|
||||
| Directional Smear | `ec.distort.ccsmear` | 4 | GPU | 32 | Implemented |
|
||||
| Displacement Map | `ec.distort.displacementmap` | 8 | GPU | 32 | Implemented |
|
||||
| Dual Lens Warp | `ec.distort.ccflomotion` | 7 | GPU | 32 | Implemented |
|
||||
| Dual Split Warp | `ec.distort.ccsplit2` | 4 | GPU | 32 | Implemented |
|
||||
| Flexible Bend | `ec.distort.ccbender` | 5 | GPU | 32 | Implemented |
|
||||
| Lens Distortion | `ec.distort.cclens` | 3 | GPU | 32 | Implemented |
|
||||
| Liquify | `ec.distort.liquify` | 13 | GPU | 32 | Implemented |
|
||||
| Magnify | `ec.distort.magnify` | 10 | GPU | 32 | Implemented |
|
||||
| Mesh Warp | `ec.distort.meshwarp` | 3 | GPU | 32 | Implemented |
|
||||
| Mirror | `ec.distort.mirror` | 2 | GPU | 32 | Implemented |
|
||||
| Offset | `ec.distort.offset` | 2 | GPU | 32 | Implemented |
|
||||
| Optics Compensation | `ec.distort.opticscompensation` | 6 | GPU | 32 | Implemented |
|
||||
| Organic Displacement | `ec.distort.ccblobbylize` | 15 | GPU | 32 | Implemented |
|
||||
| Page Curl | `ec.distort.ccpageturn` | 7 | GPU | 32 | Implemented |
|
||||
| Perspective Pin | `ec.distort.ccpowerpin` | 10 | GPU | 32 | Implemented |
|
||||
| Polar Coordinates | `ec.distort.polar` | 2 | GPU | 32 | Implemented |
|
||||
| Pulsed Ripple | `ec.distort.ccripplepulse` | 5 | GPU | 32 | Implemented |
|
||||
| Puppet | `ec.distort.puppet` | 1 | | 32 | Implemented |
|
||||
| Reshape | `ec.distort.reshape` | 6 | GPU | 32 | Implemented |
|
||||
| Ripple | `ec.distort.ripple` | 7 | GPU | 32 | Implemented |
|
||||
| Rolling Shutter Repair | `ec.distort.rollingshutterrepair` | 5 | | 32 | Implemented |
|
||||
| Scaled Tiles | `ec.distort.cctiler` | 3 | GPU | 32 | Implemented |
|
||||
| Slant | `ec.distort.ccslant` | 4 | GPU | 32 | Implemented |
|
||||
| Smear | `ec.distort.smear` | 8 | GPU | 32 | Implemented |
|
||||
| Spherize | `ec.distort.spherize` | 2 | GPU | 32 | Implemented |
|
||||
| Split Warp | `ec.distort.ccsplit` | 3 | GPU | 32 | Implemented |
|
||||
| Tile Grid | `ec.distort.ccgriddler` | 5 | GPU | 32 | Implemented |
|
||||
| Transform | `ec.distort.transform` | 12 | GPU | 32 | Implemented |
|
||||
| Turbulent Displace | `ec.distort.turbulentdisplace` | 11 | GPU | 32 | Implemented |
|
||||
| Twirl | `ec.distort.twirl` | 3 | GPU | 32 | Implemented |
|
||||
| Twirl (Legacy) | `ec.distort.twirllegacy` | 3 | GPU | 32 | Implemented |
|
||||
| Two-Point Bend | `ec.distort.ccbendit` | 4 | GPU | 32 | Implemented |
|
||||
| Warp | `ec.distort.warp` | 5 | GPU | 32 | Implemented |
|
||||
| Warp Stabilizer | `ec.distort.warpstabilizer` | 20 | | 32 | Implemented |
|
||||
| Wave Warp | `ec.distort.wavewarp` | 7 | GPU | 32 | Implemented |
|
||||
@@ -194,11 +194,6 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Audio Spectrum | `ec.generate.audiospectrum` | 23 | GPU | 32 | Implemented |
|
||||
| Audio Waveform | `ec.generate.audiowaveform` | 17 | GPU | 32 | Implemented |
|
||||
| Beam | `ec.generate.beam` | 11 | GPU | 32 | Implemented |
|
||||
| CC Glue Gun | `ec.generate.ccgluegun` | 7 | GPU | 32 | Implemented |
|
||||
| CC Light Burst 2.5 | `ec.generate.cclightburst` | 6 | GPU | 32 | Implemented |
|
||||
| CC Light Rays | `ec.generate.cclightrays` | 8 | GPU | 32 | Implemented |
|
||||
| CC Light Sweep | `ec.generate.cclightsweep` | 9 | GPU | 32 | Implemented |
|
||||
| CC Threads | `ec.generate.ccthreads` | 8 | GPU | 32 | Implemented |
|
||||
| Cell Pattern | `ec.generate.cellpattern` | 14 | GPU | 32 | Implemented |
|
||||
| Checkerboard | `ec.generate.checkerboard` | 10 | GPU | 32 | Implemented |
|
||||
| Circle | `ec.generate.circle` | 11 | GPU | 32 | Implemented |
|
||||
@@ -209,11 +204,16 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Gradient Ramp | `ec.generate.gradientramp` | 7 | GPU | 32 | Implemented |
|
||||
| Grid | `ec.generate.grid` | 12 | GPU | 32 | Implemented |
|
||||
| Lens Flare | `ec.generate.lensflare` | 4 | GPU | 32 | Implemented |
|
||||
| Light Rays | `ec.generate.cclightrays` | 8 | GPU | 32 | Implemented |
|
||||
| Light Sweep | `ec.generate.cclightsweep` | 9 | GPU | 32 | Implemented |
|
||||
| Paint Beads | `ec.generate.ccgluegun` | 7 | GPU | 32 | Implemented |
|
||||
| Paint Bucket | `ec.generate.paintbucket` | 11 | GPU | 32 | Implemented |
|
||||
| Radial Light Burst | `ec.generate.cclightburst` | 6 | GPU | 32 | Implemented |
|
||||
| Radio Waves | `ec.generate.radiowaves` | 31 | GPU | 32 | Implemented |
|
||||
| Scribble | `ec.generate.scribble` | 25 | GPU | 32 | Implemented |
|
||||
| Stroke | `ec.generate.stroke` | 11 | GPU | 32 | Implemented |
|
||||
| Vegas | `ec.generate.vegas` | 26 | GPU | 32 | Implemented |
|
||||
| Woven Threads | `ec.generate.ccthreads` | 8 | GPU | 32 | Implemented |
|
||||
| Write-on | `ec.generate.writeon` | 10 | GPU | 32 | Implemented |
|
||||
|
||||
## Immersive Video
|
||||
@@ -238,15 +238,15 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Advanced Spill Suppressor | `ec.key.advancedspill` | 8 | GPU | 32 | Implemented |
|
||||
| CC Simple Wire Removal | `ec.key.ccsimplewireremoval` | 7 | GPU | 32 | Implemented |
|
||||
| Color Difference Key | `ec.key.colordifference` | 16 | GPU | 32 | Implemented |
|
||||
| Color Range | `ec.key.colorrange` | 8 | GPU | 32 | Implemented |
|
||||
| Difference Matte | `ec.key.differencematte` | 6 | GPU | 32 | Implemented |
|
||||
| Extract | `ec.key.extract` | 6 | GPU | 32 | Implemented |
|
||||
| Inner/Outer Key | `ec.key.innerouter` | 88 | GPU | 32 | Implemented |
|
||||
| Key Cleaner | `ec.key.keycleaner` | 4 | GPU | 32 | Implemented |
|
||||
| Key Light | `ec.keying.keylight` | 56 | GPU | 32 | Implemented |
|
||||
| Line Removal | `ec.key.ccsimplewireremoval` | 7 | GPU | 32 | Implemented |
|
||||
| Linear Color Key | `ec.key.linearcolor` | 6 | GPU | 32 | Implemented |
|
||||
| Screen Color Key | `ec.keying.keylight` | 56 | GPU | 32 | Implemented |
|
||||
| Screen Key | `ec.key.screen` | 11 | GPU | 32 | Implemented |
|
||||
| Unmult | `ec.key.unmult` | 6 | GPU | 32 | Implemented |
|
||||
|
||||
@@ -255,12 +255,12 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Matte Choker | `ec.matte.mattechoker` | 7 | GPU | 32 | Implemented |
|
||||
| Mocha shape | `ec.obsolete.mochashape` | 6 | | 32 | Implemented |
|
||||
| Object Matte | `ec.matte.objectmatte` | 13 | | 32 | Implemented |
|
||||
| Refine Hard Matte | `ec.matte.refinehard` | 16 | GPU | 32 | Implemented |
|
||||
| Refine Soft Matte | `ec.matte.refinesoft` | 18 | GPU | 32 | Implemented |
|
||||
| Roto Brush & Refine Edge | `ec.matte.rotobrush` | 25 | | 32 | Implemented |
|
||||
| Simple Choker | `ec.matte.simplechoker` | 2 | GPU | 32 | Implemented |
|
||||
| Tracked Shape Matte | `ec.obsolete.mochashape` | 6 | | 32 | Implemented |
|
||||
|
||||
## Noise & Grain
|
||||
|
||||
@@ -308,65 +308,65 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| 3D Glasses | `ec.perspective.3dglasses` | 8 | GPU | 32 | Implemented |
|
||||
| Bevel Alpha | `ec.perspective.bevelalpha` | 4 | GPU | 32 | Implemented |
|
||||
| Bevel Edges | `ec.perspective.beveledges` | 4 | GPU | 32 | Implemented |
|
||||
| CC Cylinder | `ec.perspective.cccylinder` | 15 | GPU | 32 | Implemented |
|
||||
| CC Environment | `ec.perspective.ccenvironment` | 4 | GPU | 32 | Implemented |
|
||||
| CC Sphere | `ec.perspective.ccsphere` | 14 | GPU | 32 | Implemented |
|
||||
| CC Spotlight | `ec.perspective.ccspotlight` | 8 | GPU | 32 | Implemented |
|
||||
| Cylinder Wrap | `ec.perspective.cccylinder` | 15 | GPU | 32 | Implemented |
|
||||
| Drop Shadow | `ec.perspective.dropshadow` | 6 | GPU | 32 | Implemented |
|
||||
| Environment Map | `ec.perspective.ccenvironment` | 4 | GPU | 32 | Implemented |
|
||||
| Radial Shadow | `ec.perspective.radialshadow` | 9 | GPU | 32 | Implemented |
|
||||
| Sphere Wrap | `ec.perspective.ccsphere` | 14 | GPU | 32 | Implemented |
|
||||
| Surface Spotlight | `ec.perspective.ccspotlight` | 8 | GPU | 32 | Implemented |
|
||||
|
||||
## Simulation
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| CC Ball Action | `ec.sim.ccballaction` | 8 | GPU | 32 | Implemented |
|
||||
| CC Bubbles | `ec.sim.ccbubbles` | 7 | GPU | 32 | Implemented |
|
||||
| CC Drizzle | `ec.sim.ccdrizzle` | 14 | GPU | 32 | Implemented |
|
||||
| CC Hair | `ec.sim.cchair` | 20 | GPU | 32 | Implemented |
|
||||
| CC Mr. Mercury | `ec.sim.ccmrmercury` | 23 | GPU | 32 | Implemented |
|
||||
| CC Particle Systems II | `ec.sim.ccparticlesystems2` | 21 | GPU | 32 | Implemented |
|
||||
| CC Particle World | `ec.sim.ccparticleworld` | 36 | GPU | 32 | Implemented |
|
||||
| CC Pixel Polly | `ec.sim.ccpixelpolly` | 10 | GPU | 32 | Implemented |
|
||||
| CC Rainfall | `ec.sim.ccrainfall` | 14 | GPU | 32 | Implemented |
|
||||
| CC Scatterize | `ec.sim.ccscatterize` | 4 | GPU | 32 | Implemented |
|
||||
| CC Snowfall | `ec.sim.ccsnowfall` | 19 | GPU | 32 | Implemented |
|
||||
| CC Star Burst | `ec.sim.ccstarburst` | 6 | GPU | 32 | Implemented |
|
||||
| Ball Grid | `ec.sim.ccballaction` | 8 | GPU | 32 | Implemented |
|
||||
| Bubbles | `ec.sim.ccbubbles` | 7 | GPU | 32 | Implemented |
|
||||
| Card Dance | `ec.sim.carddance` | 53 | GPU | 32 | Implemented |
|
||||
| Caustics | `ec.sim.caustics` | 28 | GPU | 32 | Implemented |
|
||||
| Foam | `ec.sim.foam` | 36 | GPU | 32 | Implemented |
|
||||
| Liquid Particles | `ec.sim.ccmrmercury` | 23 | GPU | 32 | Implemented |
|
||||
| Particle Emitter 2D | `ec.sim.ccparticlesystems2` | 21 | GPU | 32 | Implemented |
|
||||
| Particle Emitter 3D | `ec.sim.ccparticleworld` | 36 | GPU | 32 | Implemented |
|
||||
| Particle Playground | `ec.sim.particleplayground` | 92 | GPU | 32 | Implemented |
|
||||
| Pixel Scatter | `ec.sim.ccscatterize` | 4 | GPU | 32 | Implemented |
|
||||
| Pixel Shatter | `ec.sim.ccpixelpolly` | 10 | GPU | 32 | Implemented |
|
||||
| Rainfall | `ec.sim.ccrainfall` | 14 | GPU | 32 | Implemented |
|
||||
| Shatter | `ec.sim.shatter` | 60 | GPU | 32 | Implemented |
|
||||
| Snowfall | `ec.sim.ccsnowfall` | 19 | GPU | 32 | Implemented |
|
||||
| Starfield | `ec.sim.ccstarburst` | 6 | GPU | 32 | Implemented |
|
||||
| Surface Fibers | `ec.sim.cchair` | 20 | GPU | 32 | Implemented |
|
||||
| Water Ripples | `ec.sim.ccdrizzle` | 14 | GPU | 32 | Implemented |
|
||||
| Wave World | `ec.sim.waveworld` | 35 | GPU | 32 | Implemented |
|
||||
|
||||
## Stylize
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Block Reveal | `ec.stylize.ccblockload` | 5 | GPU | 32 | Implemented |
|
||||
| Brush Strokes | `ec.stylize.brushstrokes` | 7 | GPU | 32 | Implemented |
|
||||
| CC Block Load | `ec.stylize.ccblockload` | 5 | GPU | 32 | Implemented |
|
||||
| CC Burn Film | `ec.stylize.ccburnfilm` | 3 | GPU | 32 | Implemented |
|
||||
| CC Glass | `ec.stylize.ccglass` | 17 | GPU | 32 | Implemented |
|
||||
| CC HexTile | `ec.stylize.cchextile` | 5 | GPU | 32 | Implemented |
|
||||
| CC Kaleida | `ec.stylize.cckaleida` | 4 | GPU | 32 | Implemented |
|
||||
| CC Mr. Smoothie | `ec.stylize.ccmrsmoothie` | 7 | GPU | 32 | Implemented |
|
||||
| CC Plastic | `ec.stylize.ccplastic` | 18 | GPU | 32 | Implemented |
|
||||
| CC RepeTile | `ec.stylize.ccrepetile` | 5 | GPU | 32 | Implemented |
|
||||
| CC Threshold | `ec.stylize.ccthreshold` | 4 | GPU | 32 | Implemented |
|
||||
| CC Threshold RGB | `ec.stylize.ccthresholdrgb` | 7 | GPU | 32 | Implemented |
|
||||
| CC Vignette | `ec.stylize.ccvignette` | 4 | GPU | 32 | Implemented |
|
||||
| Cartoon | `ec.stylize.cartoon` | 12 | GPU | 32 | Implemented |
|
||||
| Channel Threshold | `ec.stylize.ccthreshold` | 4 | GPU | 32 | Implemented |
|
||||
| Color Emboss | `ec.stylize.coloremboss` | 4 | GPU | 32 | Implemented |
|
||||
| Edge Tile Repeat | `ec.stylize.ccrepetile` | 5 | GPU | 32 | Implemented |
|
||||
| Emboss | `ec.stylize.emboss` | 4 | GPU | 32 | Implemented |
|
||||
| Film Burn | `ec.stylize.ccburnfilm` | 3 | GPU | 32 | Implemented |
|
||||
| Find Edges | `ec.stylize.findedges` | 2 | GPU | 32 | Implemented |
|
||||
| Glass Relief | `ec.stylize.ccglass` | 17 | GPU | 32 | Implemented |
|
||||
| Glow | `ec.stylize.glow` | 14 | GPU | 32 | Implemented |
|
||||
| Hexagonal Tiles | `ec.stylize.cchextile` | 5 | GPU | 32 | Implemented |
|
||||
| Kaleidoscope | `ec.stylize.cckaleida` | 4 | GPU | 32 | Implemented |
|
||||
| Mosaic | `ec.stylize.mosaic` | 3 | GPU | 32 | Implemented |
|
||||
| Motion Tile | `ec.stylize.motiontile` | 8 | GPU | 32 | Implemented |
|
||||
| Palette Map | `ec.stylize.ccmrsmoothie` | 7 | GPU | 32 | Implemented |
|
||||
| Plastic Shading | `ec.stylize.ccplastic` | 18 | GPU | 32 | Implemented |
|
||||
| Posterize | `ec.stylize.posterize` | 1 | GPU | 32 | Implemented |
|
||||
| RGB Threshold | `ec.stylize.ccthresholdrgb` | 7 | GPU | 32 | Implemented |
|
||||
| Roughen Edges | `ec.stylize.roughenedges` | 13 | GPU | 32 | Implemented |
|
||||
| Scatter | `ec.stylize.scatter` | 3 | GPU | 32 | Implemented |
|
||||
| Strobe Light | `ec.stylize.strobe` | 7 | GPU | 32 | Implemented |
|
||||
| Texturize | `ec.stylize.texturize` | 4 | GPU | 32 | Implemented |
|
||||
| Threshold | `ec.stylize.threshold` | 1 | GPU | 32 | Implemented |
|
||||
| Vignette | `ec.stylize.ccvignette` | 4 | GPU | 32 | Implemented |
|
||||
|
||||
## Text
|
||||
|
||||
@@ -379,11 +379,11 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| CC Force Motion Blur | `ec.time.ccforcemotionblur` | 4 | GPU | 32 | Implemented |
|
||||
| CC Wide Time | `ec.time.ccwidetime` | 3 | GPU | 32 | Implemented |
|
||||
| Echo | `ec.time.echo` | 5 | GPU | 32 | Implemented |
|
||||
| Pixel Motion Blur | `ec.time.pixelmotionblur` | 4 | GPU | 32 | Implemented |
|
||||
| Posterize Time | `ec.time.posterizetime` | 1 | GPU | 32 | Implemented |
|
||||
| Temporal Blend | `ec.time.ccwidetime` | 3 | GPU | 32 | Implemented |
|
||||
| Temporal Motion Blur | `ec.time.ccforcemotionblur` | 4 | GPU | 32 | Implemented |
|
||||
| Time Difference | `ec.time.timedifference` | 5 | GPU | 32 | Implemented |
|
||||
| Time Displacement | `ec.time.timedisplacement` | 4 | GPU | 32 | Implemented |
|
||||
| Timewarp | `ec.time.timewarp` | 28 | GPU | 32 | Implemented |
|
||||
@@ -393,29 +393,28 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Block Dissolve | `ec.transition.blockdissolve` | 5 | GPU | 32 | Implemented |
|
||||
| CC Glass Wipe | `ec.transition.ccglasswipe` | 5 | GPU | 32 | Implemented |
|
||||
| CC Grid Wipe | `ec.transition.ccgridwipe` | 7 | GPU | 32 | Implemented |
|
||||
| CC Image Wipe | `ec.transition.ccimagewipe` | 7 | GPU | 32 | Implemented |
|
||||
| CC Jaws | `ec.transition.ccjaws` | 6 | GPU | 32 | Implemented |
|
||||
| CC Light Wipe | `ec.transition.cclightwipe` | 8 | GPU | 32 | Implemented |
|
||||
| CC Line Sweep | `ec.transition.cclinesweep` | 5 | GPU | 32 | Implemented |
|
||||
| CC Radial ScaleWipe | `ec.transition.ccradialscalewipe` | 3 | GPU | 32 | Implemented |
|
||||
| CC Scale Wipe | `ec.transition.ccscalewipe` | 3 | GPU | 32 | Implemented |
|
||||
| CC Twister | `ec.transition.cctwister` | 5 | GPU | 32 | Implemented |
|
||||
| CC WarpoMatic | `ec.transition.ccwarpomatic` | 8 | GPU | 32 | Implemented |
|
||||
| Card Wipe | `ec.transition.cardwipe` | 44 | GPU | 32 | Implemented |
|
||||
| Glass Wipe | `ec.transition.ccglasswipe` | 5 | GPU | 32 | Implemented |
|
||||
| Gradient Wipe | `ec.transition.gradientwipe` | 5 | GPU | 32 | Implemented |
|
||||
| Grid Wipe | `ec.transition.ccgridwipe` | 7 | GPU | 32 | Implemented |
|
||||
| Iris Wipe | `ec.transition.iriswipe` | 7 | GPU | 32 | Implemented |
|
||||
| Light Wipe | `ec.transition.cclightwipe` | 8 | GPU | 32 | Implemented |
|
||||
| Line Sweep | `ec.transition.cclinesweep` | 5 | GPU | 32 | Implemented |
|
||||
| Linear Wipe | `ec.transition.linearwipe` | 3 | GPU | 32 | Implemented |
|
||||
| Luminance Image Wipe | `ec.transition.ccimagewipe` | 7 | GPU | 32 | Implemented |
|
||||
| Radial Scale Wipe | `ec.transition.ccradialscalewipe` | 3 | GPU | 32 | Implemented |
|
||||
| Radial Wipe | `ec.transition.radialwipe` | 5 | GPU | 32 | Implemented |
|
||||
| Scale Wipe | `ec.transition.ccscalewipe` | 3 | GPU | 32 | Implemented |
|
||||
| Serrated Wipe | `ec.transition.ccjaws` | 6 | GPU | 32 | Implemented |
|
||||
| Twist Wipe | `ec.transition.cctwister` | 5 | GPU | 32 | Implemented |
|
||||
| Venetian Blinds | `ec.transition.venetian` | 4 | GPU | 32 | Implemented |
|
||||
| Warp Dissolve | `ec.transition.ccwarpomatic` | 8 | GPU | 32 | Implemented |
|
||||
|
||||
## Utility
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Apply Color LUT | `ec.utility.applylut` | 1 | GPU | 32 | Implemented |
|
||||
| CC Overbrights | `ec.utility.ccoverbrights` | 2 | GPU | 32 | Implemented |
|
||||
| Cineon Converter | `ec.utility.cineon` | 7 | GPU | 32 | Implemented |
|
||||
| Color Profile Converter | `ec.utility.colorprofileconverter` | 7 | GPU | 32 | Implemented |
|
||||
| Face Measurements | `ec.utility.facemeasurements` | 14 | | 32 | Implemented |
|
||||
@@ -423,4 +422,5 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
|
||||
| Grow Bounds | `ec.utility.growbounds` | 1 | GPU | 32 | Implemented |
|
||||
| HDR Compander | `ec.utility.hdrcompander` | 3 | GPU | 32 | Implemented |
|
||||
| HDR Highlight Compression | `ec.utility.hdrcompression` | 1 | GPU | 32 | Implemented |
|
||||
| Out-of-Range Display | `ec.utility.ccoverbrights` | 2 | GPU | 32 | Implemented |
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
# Descriptive feature names
|
||||
|
||||
Related to #1365. This is a naming cleanup, not a trademark clearance or a product rename.
|
||||
|
||||
## Naming policy
|
||||
|
||||
Use short, descriptive labels for EffectCraft implementations. Do not reuse a vendor prefix or
|
||||
coined feature name as our branding. Qualify similar effects by what distinguishes them; each
|
||||
English display name remains unique across the registry.
|
||||
|
||||
- Renderer: **GPU Acceleration** / **Software Rendering**.
|
||||
- Panel: **Video Scopes**.
|
||||
- The table below covers the 69 former CC effects plus color grading, the shape matte and keying.
|
||||
|
||||
## Compatibility contract
|
||||
|
||||
Only presentation names change. Effect IDs, command IDs, parameter IDs, enum values, panel IDs,
|
||||
serialized types and AEP import/export match names stay unchanged. Old effect display names
|
||||
remain case-insensitive lookup and search aliases. Existing project instance names, custom names,
|
||||
expressions, animation and values are not rewritten. The UI displays a current label for an exact
|
||||
legacy default name, optionally followed by its numeric instance suffix; all other names stay
|
||||
verbatim. A user-entered name identical to a legacy default cannot be distinguished from it, but
|
||||
its saved value is still retained.
|
||||
|
||||
External format specifications, comparison documents, attribution records and compatibility
|
||||
fixtures may still name the external product or effect they actually describe.
|
||||
|
||||
## Display mapping
|
||||
|
||||
| Stable ID | Previous display name | Current display name |
|
||||
|---|---|---|
|
||||
| `ec.sim.ccballaction` | CC Ball Action | Ball Grid |
|
||||
| `ec.distort.ccbendit` | CC Bend It | Two-Point Bend |
|
||||
| `ec.distort.ccbender` | CC Bender | Flexible Bend |
|
||||
| `ec.distort.ccblobbylize` | CC Blobbylize | Organic Displacement |
|
||||
| `ec.stylize.ccblockload` | CC Block Load | Block Reveal |
|
||||
| `ec.sim.ccbubbles` | CC Bubbles | Bubbles |
|
||||
| `ec.stylize.ccburnfilm` | CC Burn Film | Film Burn |
|
||||
| `ec.color.cccolorneutralizer` | CC Color Neutralizer | Color Neutralizer |
|
||||
| `ec.color.cccoloroffset` | CC Color Offset | Channel Offset |
|
||||
| `ec.channel.cccomposite` | CC Composite | Source Composite |
|
||||
| `ec.blur.cccross` | CC Cross Blur | Cross Blur |
|
||||
| `ec.perspective.cccylinder` | CC Cylinder | Cylinder Wrap |
|
||||
| `ec.sim.ccdrizzle` | CC Drizzle | Water Ripples |
|
||||
| `ec.perspective.ccenvironment` | CC Environment | Environment Map |
|
||||
| `ec.distort.ccflomotion` | CC Flo Motion | Dual Lens Warp |
|
||||
| `ec.time.ccforcemotionblur` | CC Force Motion Blur | Temporal Motion Blur |
|
||||
| `ec.stylize.ccglass` | CC Glass | Glass Relief |
|
||||
| `ec.transition.ccglasswipe` | CC Glass Wipe | Glass Wipe |
|
||||
| `ec.generate.ccgluegun` | CC Glue Gun | Paint Beads |
|
||||
| `ec.transition.ccgridwipe` | CC Grid Wipe | Grid Wipe |
|
||||
| `ec.distort.ccgriddler` | CC Griddler | Tile Grid |
|
||||
| `ec.sim.cchair` | CC Hair | Surface Fibers |
|
||||
| `ec.stylize.cchextile` | CC HexTile | Hexagonal Tiles |
|
||||
| `ec.transition.ccimagewipe` | CC Image Wipe | Luminance Image Wipe |
|
||||
| `ec.transition.ccjaws` | CC Jaws | Serrated Wipe |
|
||||
| `ec.stylize.cckaleida` | CC Kaleida | Kaleidoscope |
|
||||
| `ec.color.cckernel` | CC Kernel | Convolution Kernel |
|
||||
| `ec.distort.cclens` | CC Lens | Lens Distortion |
|
||||
| `ec.generate.cclightburst` | CC Light Burst 2.5 | Radial Light Burst |
|
||||
| `ec.generate.cclightrays` | CC Light Rays | Light Rays |
|
||||
| `ec.generate.cclightsweep` | CC Light Sweep | Light Sweep |
|
||||
| `ec.transition.cclightwipe` | CC Light Wipe | Light Wipe |
|
||||
| `ec.transition.cclinesweep` | CC Line Sweep | Line Sweep |
|
||||
| `ec.sim.ccmrmercury` | CC Mr. Mercury | Liquid Particles |
|
||||
| `ec.stylize.ccmrsmoothie` | CC Mr. Smoothie | Palette Map |
|
||||
| `ec.utility.ccoverbrights` | CC Overbrights | Out-of-Range Display |
|
||||
| `ec.distort.ccpageturn` | CC Page Turn | Page Curl |
|
||||
| `ec.sim.ccparticlesystems2` | CC Particle Systems II | Particle Emitter 2D |
|
||||
| `ec.sim.ccparticleworld` | CC Particle World | Particle Emitter 3D |
|
||||
| `ec.sim.ccpixelpolly` | CC Pixel Polly | Pixel Shatter |
|
||||
| `ec.stylize.ccplastic` | CC Plastic | Plastic Shading |
|
||||
| `ec.distort.ccpowerpin` | CC Power Pin | Perspective Pin |
|
||||
| `ec.blur.ccradial` | CC Radial Blur | Variable Radial Blur |
|
||||
| `ec.blur.ccradialfast` | CC Radial Fast Blur | Fast Radial Blur |
|
||||
| `ec.transition.ccradialscalewipe` | CC Radial ScaleWipe | Radial Scale Wipe |
|
||||
| `ec.sim.ccrainfall` | CC Rainfall | Rainfall |
|
||||
| `ec.stylize.ccrepetile` | CC RepeTile | Edge Tile Repeat |
|
||||
| `ec.distort.ccripplepulse` | CC Ripple Pulse | Pulsed Ripple |
|
||||
| `ec.transition.ccscalewipe` | CC Scale Wipe | Scale Wipe |
|
||||
| `ec.sim.ccscatterize` | CC Scatterize | Pixel Scatter |
|
||||
| `ec.key.ccsimplewireremoval` | CC Simple Wire Removal | Line Removal |
|
||||
| `ec.distort.ccslant` | CC Slant | Slant |
|
||||
| `ec.distort.ccsmear` | CC Smear | Directional Smear |
|
||||
| `ec.sim.ccsnowfall` | CC Snowfall | Snowfall |
|
||||
| `ec.perspective.ccsphere` | CC Sphere | Sphere Wrap |
|
||||
| `ec.distort.ccsplit` | CC Split | Split Warp |
|
||||
| `ec.distort.ccsplit2` | CC Split 2 | Dual Split Warp |
|
||||
| `ec.perspective.ccspotlight` | CC Spotlight | Surface Spotlight |
|
||||
| `ec.sim.ccstarburst` | CC Star Burst | Starfield |
|
||||
| `ec.generate.ccthreads` | CC Threads | Woven Threads |
|
||||
| `ec.stylize.ccthreshold` | CC Threshold | Channel Threshold |
|
||||
| `ec.stylize.ccthresholdrgb` | CC Threshold RGB | RGB Threshold |
|
||||
| `ec.distort.cctiler` | CC Tiler | Scaled Tiles |
|
||||
| `ec.color.cctoner` | CC Toner | Multi-Tone Tint |
|
||||
| `ec.transition.cctwister` | CC Twister | Twist Wipe |
|
||||
| `ec.blur.ccvector` | CC Vector Blur | Vector Blur |
|
||||
| `ec.stylize.ccvignette` | CC Vignette | Vignette |
|
||||
| `ec.transition.ccwarpomatic` | CC WarpoMatic | Warp Dissolve |
|
||||
| `ec.time.ccwidetime` | CC Wide Time | Temporal Blend |
|
||||
| `ec.color.lumetri` | Lumetri Color | Color Grading |
|
||||
| `ec.obsolete.mochashape` | Mocha shape | Tracked Shape Matte |
|
||||
| `ec.keying.keylight` | Key Light | Screen Color Key |
|
||||
|
||||
`Roto Brush & Refine Edge` and `Warp Stabilizer` keep their current names; renaming them is
|
||||
deferred.
|
||||
|
||||
No effect algorithms or formats are changed.
|
||||
+1
-1
@@ -174,7 +174,7 @@ the same futures with `passes::block_on`; they never wait there).
|
||||
- **Render Queue**: `effectcraft_export::export_async` renders each frame in passes (frames
|
||||
with deferred readbacks render one by one instead of in parallel batches) and encodes as
|
||||
before (`Exporter::export_async`). As on the desktop, a job renders every frame on the
|
||||
project's renderer (the worker's GPU with Mercury GPU Acceleration), not on whichever
|
||||
project's renderer (the worker's GPU with GPU Acceleration), not on whichever
|
||||
compositor measured faster, so runs don't differ by timing.
|
||||
- **Analyses** (Warp Stabilizer, 3D Camera Tracker, Track Motion, mask and face tracking, Roto
|
||||
Brush freeze and propagation): their work functions are `async`; started with `wait` inside
|
||||
|
||||
Reference in new issue
Block a user