Merge remote-tracking branch 'upstream/main' into text-layer-name-follow-3233

This commit is contained in:
vangel76
2026-11-08 04:42:27 +01:00
104 changed files with 6694 additions and 1263 deletions
+5
View File
@@ -345,6 +345,7 @@ fn warning(s: &mut Session, p: &Value) -> Result<Value> {
footage: None,
property_overrides: &[],
media_overrides: &[],
reads: None,
};
Ok(json!({"effect": uid, "warning": effectcraft_effects::warning(g, &mut |pr| ctx.value(layer, pr))}))
}
@@ -378,6 +379,7 @@ fn pick_color(s: &mut Session, p: &Value) -> Result<Value> {
footage: None,
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let mut r = effectcraft_render::Renderer::new(&s.project, &*s.footage, effectcraft_render::RenderOpts::default());
r.expr = s.expr.as_deref();
@@ -515,6 +517,7 @@ impl CryptoProbe {
footage: None,
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let params = effectcraft_effects::flatten_params(g, &mut |pr| ctx.value(layer, pr));
let aux = r.layer_aux(&ctx, layer).ok_or(NO_CRYPTO)?;
@@ -586,6 +589,7 @@ fn probe_key<'a>(s: &'a Session, p: &Value, cmd: &str) -> Result<(ProbeKey, Tick
footage: None,
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let frame = probe_frame(&ctx, layer, pos);
let o = s.render_opts(Default::default());
@@ -780,6 +784,7 @@ fn crypto_hit(s: &Session, p: &Value, cmd: &str) -> Result<Hit> {
footage: None,
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let selection = effectcraft_effects::flatten_params(g, &mut |pr| ctx.value(layer, pr)).s("selection").to_string();
let driven = prop.expr.as_ref().is_some_and(|e| e.enabled);
+1
View File
@@ -249,6 +249,7 @@ pub(crate) fn parent_fixes(s: &Session, cid: ItemId, ids: &[LayerId], parent: Op
footage: Some(s.footage.as_ref()),
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let space = |id: Option<LayerId>| -> effectcraft_geom::Mat3 {
id.and_then(|i| comp.layer(i)).filter(|l| !l.is_3d()).map(|l| ectx.layer_to_comp(l).0).unwrap_or(effectcraft_geom::Mat3::IDENTITY)
+1
View File
@@ -194,6 +194,7 @@ fn freeze(s: &mut Session, p: &Value, last: bool) -> Result<Value> {
footage: Some(s.footage.as_ref()),
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let now: Vec<(effectcraft_project::LayerId, f64)> = comp
.layers
+4
View File
@@ -73,6 +73,8 @@ struct PathInfo {
span: (f64, f64),
}
/// Reads a mask or shape path at the current time and returns its comp-space vertices, value, expression reference and layer name.
/// Errors when the property is missing, is not a path or has no vertices.
fn info(s: &Session, cid: ItemId, lid: LayerId, uid: Uid, cmd: &str) -> Result<PathInfo> {
let comp = s.project.comp(cid).ok_or(EngineError::NoComp)?;
let layer = comp.layer(lid).ok_or(EngineError::NoComp)?;
@@ -87,6 +89,7 @@ fn info(s: &Session, cid: ItemId, lid: LayerId, uid: Uid, cmd: &str) -> Result<P
footage: Some(s.footage.as_ref()),
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let KV::Path(path) = ctx.value(layer, pr) else { return Err(bad(cmd, "that property is not a path")) };
if path.vertices.is_empty() {
@@ -165,6 +168,7 @@ fn pin_targets(s: &Session, p: &Value, cmd: &str) -> Result<Option<(ItemId, Vec<
footage: Some(s.footage.as_ref()),
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let mut out = vec![];
for (_, lid, uid) in pins {
+3
View File
@@ -1380,6 +1380,8 @@ fn convert_expr_to_keys(s: &mut Session, p: &Value) -> Result<Value> {
convert_one_expr(s, cid, lid, uid)
}
/// Replaces the expression on one property with keyframes sampled from its evaluated values.
/// Returns the number of properties converted.
fn convert_one_expr(s: &mut Session, cid: ItemId, lid: LayerId, uid: Uid) -> Result<Value> {
let comp = s.project.comp(cid).ok_or(EngineError::NoComp)?.clone();
let layer = comp.layer(lid).ok_or(EngineError::NoComp)?.clone();
@@ -1397,6 +1399,7 @@ fn convert_one_expr(s: &mut Session, cid: ItemId, lid: LayerId, uid: Uid) -> Res
footage: Some(s.footage.as_ref()),
property_overrides: &[],
media_overrides: &[],
reads: None,
};
keys.push(Keyframe::new(layer.layer_time(t), ctx.value(&layer, &pr)));
t += fd;
+11 -2
View File
@@ -39,8 +39,17 @@ pub fn puppet_eval(s: &Session, cid: ItemId, lid: LayerId, fx_uid: Uid, t: Tick)
let fx = layer.effects()?;
let index = fx.groups().position(|g| g.uid == fx_uid)?;
let g = fx.groups().nth(index)?;
let ctx =
EvalCtx { project: &s.project, comp_id: cid, comp, time: t, expr: s.expr.as_deref(), footage: None, property_overrides: &[], media_overrides: &[] };
let ctx = EvalCtx {
project: &s.project,
comp_id: cid,
comp,
time: t,
expr: s.expr.as_deref(),
footage: None,
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let mut r = Renderer::new(&s.project, &*s.footage, RenderOpts::default());
r.expr = s.expr.as_deref();
r.cache = Some(&s.layer_cache);
+2
View File
@@ -47,6 +47,7 @@ impl Env {
fn of(s: &Session, cid: ItemId) -> Env {
Env { time: s.time_of(cid), expr: s.expr.clone(), footage: s.footage.clone() }
}
/// The evaluation context of `comp` in `proj` at the session's current time.
fn ctx<'a>(&'a self, proj: &'a Project, cid: ItemId, comp: &'a Comp) -> EvalCtx<'a> {
EvalCtx {
project: proj,
@@ -57,6 +58,7 @@ impl Env {
footage: Some(self.footage.as_ref()),
property_overrides: &[],
media_overrides: &[],
reads: None,
}
}
}
+23 -4
View File
@@ -418,14 +418,24 @@ fn set_view_camera(s: &mut Session, p: &Value) -> Result<Value> {
Ok(json!({"view": v.id()}))
}
/// Returns the active comp's 3D view state, with the comp size, for the 3D view commands.
fn get_3d(s: &mut Session, p: &Value) -> Result<Value> {
let cid = comp_id(s, p)?;
let comp = s.project.comp(cid).ok_or(EngineError::NoComp)?;
let (w, h) = (comp.width as f64, comp.height as f64);
let vs = s.state.views3d.get(&cid).cloned().unwrap_or_default();
let t = s.state.times.get(&cid).copied().unwrap_or(Tick::ZERO);
let ctx =
EvalCtx { project: &s.project, comp_id: cid, comp, time: t, expr: s.expr.as_deref(), footage: None, property_overrides: &[], media_overrides: &[] };
let ctx = EvalCtx {
project: &s.project,
comp_id: cid,
comp,
time: t,
expr: s.expr.as_deref(),
footage: None,
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let cam = vs.override_camera(w, h).unwrap_or_else(|| camera::active_camera(&ctx));
let f = cam.forward();
let lights: Vec<Value> = comp
@@ -567,8 +577,17 @@ fn auto_orient(s: &mut Session, p: &Value) -> Result<Value> {
/// through each layer's world matrix; cameras and lights contribute their position).
fn layer_points(s: &Session, cid: ItemId, ids: &[LayerId], t: Tick) -> Vec<Vec3> {
let Some(comp) = s.project.comp(cid) else { return vec![] };
let ctx =
EvalCtx { project: &s.project, comp_id: cid, comp, time: t, expr: s.expr.as_deref(), footage: None, property_overrides: &[], media_overrides: &[] };
let ctx = EvalCtx {
project: &s.project,
comp_id: cid,
comp,
time: t,
expr: s.expr.as_deref(),
footage: None,
property_overrides: &[],
media_overrides: &[],
reads: None,
};
let mut out = vec![];
for l in comp.layers.iter().filter(|l| ids.contains(&l.id)) {
let m = ctx.world_matrix(l);