mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 08:29:14 +00:00
Effects: a fill's 3D Revolve tells the plug-in effect before it which fill it sits on
The per-item Revolve loop passed a copy of each fill or stroke to the geometry context, which finds the item by identity in the object's appearance, so a plug-in effect before the Revolve was told it sat on the object. Each copy now keeps its original item beside it.
This commit is contained in:
@@ -620,15 +620,17 @@ fn art(doc: Option<&Document>, n: &Node, expand: bool) -> Option<Node> {
|
||||
let path = geometry(&path, &n.appearance.effects, &ctx);
|
||||
remaining = crate::without_geometry(&remaining);
|
||||
// The object's Transform effects, applied to the path above, transform the items' raster
|
||||
// effects too.
|
||||
let mut items: Vec<AppearanceItem> = n.appearance.items.iter().filter(|i| crate::paints(i)).cloned().collect();
|
||||
// effects too. Each copy keeps its item beside it, which plug-in effects are told they sit
|
||||
// on.
|
||||
let originals: Vec<&AppearanceItem> = n.appearance.items.iter().filter(|i| crate::paints(i)).collect();
|
||||
let mut items: Vec<AppearanceItem> = originals.iter().map(|i| (*i).clone()).collect();
|
||||
crate::raster::follow_paints(&mut items, &n.appearance.effects);
|
||||
// Every item's shadow goes behind every item's art.
|
||||
let mut shadows = vec![];
|
||||
for item in &items {
|
||||
for (original, item) in originals.into_iter().zip(&items) {
|
||||
if let Some(index) = item.effects().iter().position(|e| e.visible && is_revolve(&e.id)) {
|
||||
let fx = item.effects().get(index)?;
|
||||
let p = geometry(&path, item.effects().get(..index)?, &ctx.item(item));
|
||||
let p = geometry(&path, item.effects().get(..index)?, &ctx.item(original));
|
||||
let expand = expand && !item.effects().iter().skip(index + 1).any(|e| e.visible && is_geometry(&e.id));
|
||||
let mut art = object_surface(n, &p, fx, item, expand, &mut copies)?;
|
||||
art.appearance.effects = item.effects().iter().skip(index + 1).filter(|e| !is_revolve(&e.id)).cloned().collect();
|
||||
|
||||
@@ -329,6 +329,29 @@ fn expanding_a_fill_gives_its_plug_in_effect_the_fill_it_sits_on() {
|
||||
assert_eq!(clip.path_data().unwrap().bounds(), triangle().bounds(), "the triangle the canvas fills");
|
||||
}
|
||||
|
||||
/// A plug-in effect on a fill, before the fill's own 3D Revolve, is given the fill it sits on
|
||||
/// (`_context.item`), so the fill revolves the shape the plug-in returns for it.
|
||||
#[test]
|
||||
fn a_fills_revolve_gives_the_plug_in_effect_before_it_the_fill_it_sits_on() {
|
||||
let mut s = session();
|
||||
let id = rect(&mut s, 10.0, "#ff0000");
|
||||
let tri = json!({"objects": [{"path": triangle()}]}).to_string();
|
||||
let on_fill = tpl::when_given(&tpl::manifest("test.engine.revolvefill", "effect", "{}"), tpl::Given::Params, r#""item":{"fill":0}"#, &tri);
|
||||
install_wat(&mut s, &on_fill);
|
||||
let fill = node(&s, id).appearance.items.iter().position(|i| i.is_fill()).unwrap();
|
||||
run(&mut s, "effect.apply", json!({"ids": [id.0], "effect": "plugin.test.engine.revolvefill", "item": fill}));
|
||||
run(&mut s, "effect.apply", json!({"ids": [id.0], "effect": "threeD.revolve", "item": fill}));
|
||||
let n = node(&s, id);
|
||||
// The same object with the triangle as its path and only the Revolve on its fill.
|
||||
let mut expected = n.clone();
|
||||
if let vectorcraft_doc::NodeKind::Path { path, .. } = &mut expected.kind {
|
||||
*path = triangle();
|
||||
}
|
||||
expected.appearance.items[fill].effects_mut().retain(|e| e.id == "threeD.revolve");
|
||||
let art = vectorcraft_render::effects::revolve_art(&n).unwrap();
|
||||
assert_eq!(art, vectorcraft_render::effects::revolve_art(&expected).unwrap(), "the fill revolves the triangle");
|
||||
}
|
||||
|
||||
/// The manifest of a test live effect `id` that declares `paintOutput` (at `api` 2), or that
|
||||
/// doesn't (`paints` off).
|
||||
fn painting(id: &str, paints: bool) -> String {
|
||||
|
||||
Reference in New Issue
Block a user