mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-01 05:58:19 -06:00
Effects: EXtractoR picks layers and channels of multi-layer EXRs (#295)
EXtractoR's Red, Green, Blue and Alpha are text parameters naming
channels, and Effect Controls drew nothing for text parameters: there
was no way to choose a layer or channel. And a multi-layer OpenEXR file
whose colour is only in named layers (`diffuse.R`, Blender's
`ViewLayer.Combined.R`) didn't import at all: the image decoder wants an
unnamed RGB layer ("does not contain non-deep rgb channels").
- Effect Controls: EXtractoR gets a Layer popup listing the footage's
OpenEXR layers. Picking one sets red, green, blue and alpha to its
channels in one undo step, as After Effects' EXtractoR dialog does (a
one-channel layer such as depth goes in all three colours). Red /
Green / Blue / Alpha are popups of the layer's own R, G, B, A, every
channel of the file, and (none). The lists are read only while open,
so playing an EXR sequence doesn't parse files on the UI thread.
- `layer.channels {layer}` lists a layer's EXR layers and channels and
what each layer shows in red, green, blue and alpha, for agents.
- Media: an EXR without an unnamed RGB layer imports and shows its
colour layer (one named combined, beauty or rgba first); its channels
stay available to EXtractoR and the 3D Channel effects.
- Raster: AuxChannels::layers / layer_rgba and split_channel.
Test: extractor_shows_the_chosen_layer_and_channels_of_a_layered_exr
(host: a layered EXR written with the exr crate imports, layer.channels,
EXtractoR renders spec and depth; it failed to import before),
extractor_offers_the_exr_layers_and_channels (UI: Layer popup, one undo
step, channel popup), layered_exr_without_an_unnamed_rgb_layer_imports
(media).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a6c72acf94
commit
27cabcb36b
@@ -415,9 +415,36 @@ fn list(_: &mut Session, p: &Value) -> Result<Value> {
|
||||
Ok(json!(v))
|
||||
}
|
||||
|
||||
impl Session {
|
||||
/// The named channels of layer `lid` in the active comp at the current time: its
|
||||
/// multi-layer OpenEXR footage's layers and channels (`diffuse.R`, `depth.Z`, …), which
|
||||
/// EXtractoR and the 3D Channel effects read. `None` for other layers.
|
||||
pub fn layer_channels(&self, lid: LayerId) -> Option<std::sync::Arc<effectcraft_raster::AuxChannels>> {
|
||||
let layer = self.active_comp()?.layer(lid)?;
|
||||
let effectcraft_project::LayerSource::Footage { item } = layer.source else { return None };
|
||||
let effectcraft_project::ItemKind::Footage(f) = &self.project.item(item)?.kind else { return None };
|
||||
self.footage.aux(item, f, layer.layer_time(self.time()))
|
||||
}
|
||||
}
|
||||
|
||||
/// `layer.channels`: the layers and channels of a layer's multi-layer OpenEXR footage, and
|
||||
/// what each layer shows in red, green, blue and alpha (EXtractoR's popups).
|
||||
fn channels(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let (_, lid) = super::layer_p(s, p, "layer.channels")?;
|
||||
let Some(aux) = s.layer_channels(lid) else { return Ok(json!({"channels": [], "layers": []})) };
|
||||
let layers: Vec<Value> = aux.layers().into_iter().map(|l| json!({"name": l, "rgba": aux.layer_rgba(l)})).collect();
|
||||
Ok(json!({"channels": aux.names(), "layers": layers}))
|
||||
}
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
vec![
|
||||
cmd!("effect.apply", "Apply Effect", [], None, "{effect: id|name (e.g. Gaussian Blur), layers?}", has_layers, apply),
|
||||
crate::query!(
|
||||
"layer.channels",
|
||||
"Layer Channels",
|
||||
"{layer?} → {channels: [name], layers: [{name, rgba: [r, g, b, a channel]}]} — a multi-layer OpenEXR layer's channels (EXtractoR's red / green / blue / alpha take these names)",
|
||||
channels
|
||||
),
|
||||
cmd!(
|
||||
"effect.pickColor",
|
||||
"Pick Effect Colour",
|
||||
|
||||
Reference in New Issue
Block a user