mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 05:27:08 -06:00
instance3d: a dedicated 3D Layer Instance effect, and the copy is cached
CC Composite stays After Effects-pure: its Layer parameter is gone, so parameter indices match AE again (scripts and expressions that address parameters by index). The model reference lives in its own effect, ec.3d.instance3d (3D Channel, CPU, one layer parameter), which replaces the layer's pixels with the referenced layer's render — alpha included. A referenced model's solo render is now hashed into the owner's cache key instead of declining the entry (Bflat, review of #2410): the layer, its animated values and transform, the mesh item, the comp camera and lights, draft 3D, the renderer setting and the in/out gate. Covered by a render test: the copy is cached, served on the second render, and re-rendered when the camera pans or the model leaves its in/out range.
This commit is contained in:
@@ -27,9 +27,9 @@ fn create(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
if op == "instance3d" {
|
||||
// After Effects' Create 3D Layer Instance (Layer ▸ Create): 3D model layers take
|
||||
// no masks or effects, so a comp-sized solid goes at the top of the layer stack
|
||||
// with CC Composite referencing the model — a 2D copy of its render, through the
|
||||
// comp's camera, that 2D effects can be applied to. The model is switched off,
|
||||
// as After Effects does (back on to keep its shadow).
|
||||
// with a 3D Layer Instance effect referencing the model — a 2D copy of its render,
|
||||
// through the comp's camera, that 2D effects can be applied to. The model is switched
|
||||
// off, as After Effects does (back on to keep its shadow).
|
||||
let comp = s.project.comp(cid).ok_or(EngineError::NoComp)?.clone();
|
||||
let mut eligible = vec![];
|
||||
for lid in &lids {
|
||||
@@ -55,9 +55,9 @@ fn create(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
// A soloed source keeps its Solo switch with video off, and any_solo hides
|
||||
// the non-soloed copy: the copy takes the Solo over to stay visible.
|
||||
l.switches.solo = src.switches.solo;
|
||||
// CC Composite referencing the 3D layer: the solid shows its render (the 2D
|
||||
// copy).
|
||||
let fx = effectcraft_effects::find("ec.channel.cccomposite").ok_or_else(|| bad("layer.create", "the CC Composite effect is missing"))?;
|
||||
// A 3D Layer Instance effect referencing the 3D layer: the solid shows its
|
||||
// render (the 2D copy).
|
||||
let fx = effectcraft_effects::find("ec.3d.instance3d").ok_or_else(|| bad("layer.create", "the 3D Layer Instance effect is missing"))?;
|
||||
let mut g = effectcraft_effects::instantiate(fx, &mut Ids(&mut proj.next_id), fx.name, [comp.width as f64, comp.height as f64]);
|
||||
if let Some(pr) = g.get_mut("layer") {
|
||||
pr.value = KV::Layer(Some(lid.0));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Create 3D Layer Instance (Layer ▸ Create): a comp-sized solid at the top of the layer stack
|
||||
//! with CC Composite referencing the selected 3D model layer — a 2D copy of its render that 2D
|
||||
//! effects can be applied to (behaviour, pixels, undo/redo, serde).
|
||||
//! with a 3D Layer Instance effect referencing the selected 3D model layer — a 2D copy of its
|
||||
//! render that 2D effects can be applied to (behaviour, pixels, undo/redo, serde).
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -97,9 +97,9 @@ fn instance3d_creates_a_2d_copy_of_the_model() {
|
||||
let l = layer_in(&s, comp, solid);
|
||||
assert_eq!(l.name, "Triangle Instance");
|
||||
assert_eq!(s.active_comp().unwrap().layers[0].id.0, solid, "at the top of the layer stack");
|
||||
// CC Composite referencing the 3D layer.
|
||||
// A 3D Layer Instance effect referencing the 3D layer.
|
||||
let g = l.effects().unwrap().groups().next().unwrap().clone();
|
||||
assert!(matches!(&g.kind, GroupKind::Effect { effect } if effect == "ec.channel.cccomposite"), "{:?}", g.kind);
|
||||
assert!(matches!(&g.kind, GroupKind::Effect { effect } if effect == "ec.3d.instance3d"), "{:?}", g.kind);
|
||||
assert_eq!(g.get("layer").unwrap().value, KV::Layer(Some(model)));
|
||||
// The model is switched off, the copy selected.
|
||||
assert!(!layer_in(&s, comp, model).switches.video, "the referenced 3D layer is off, as After Effects does");
|
||||
|
||||
Reference in New Issue
Block a user