mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Convert path modify to a flip kernel over one default lane
This commit is contained in:
@@ -325,7 +325,9 @@ macro_rules! tagged_value {
|
||||
check_level!(List<Graphic>, Graphic);
|
||||
check_level!(List<Artboard>, Artboard);
|
||||
check_level!(List<Raster<CPU>>, Raster<CPU>);
|
||||
check_level!(List<Vector>, Vector);
|
||||
// One default lane rather than an empty level: an unwired path input
|
||||
// starts from a blank vector, as the legacy path modify synthesized itself.
|
||||
if name == std::any::type_name::<List<Vector>>() { return Ok(leveled_record_value_edge(vec![Vector::default()])); }
|
||||
check_level!(List<String>, String);
|
||||
if name == std::any::type_name::<DocumentNode>() { return Ok(record_value_edge(DocumentNode::default())); }
|
||||
if name == std::any::type_name::<Resource>() { return Ok(record_value_edge(Resource::default())); }
|
||||
|
||||
@@ -1,37 +1,42 @@
|
||||
use core_types::attribute::{Attr, EditorLayerPath, RemoveAttr};
|
||||
use core_types::gpoll::{GraphError, Interrupt};
|
||||
use core_types::list::List;
|
||||
use core_types::uuid::NodeId;
|
||||
use core_types::{ATTR_EDITOR_LAYER_PATH, ATTR_TRANSFORM, Ctx};
|
||||
use core_types::{ATTR_TRANSFORM, Ctx, ExtractIndex, InjectIndex};
|
||||
use glam::DAffine2;
|
||||
use graphic_types::Vector;
|
||||
use vector_types::ATTR_EDITOR_CLICK_TARGET;
|
||||
use vector_types::markers::EditorClickTarget;
|
||||
use vector_types::vector::VectorModification;
|
||||
|
||||
/// Applies a differential modification to a vector path, associating changes made by the Pen and Path tools to indices of edited points and segments.
|
||||
/// The modification applies to the level's first lane only; an unwired input serves one blank lane through the
|
||||
/// `TypeDefault` value form, so a fresh path starts from a default vector.
|
||||
#[node_macro::node(category(""))]
|
||||
fn path_modify(_ctx: impl Ctx, mut vector: List<Vector>, modification: Box<VectorModification>, node_path: Vec<NodeId>) -> List<Vector> {
|
||||
use core_types::list::Item;
|
||||
|
||||
if vector.is_empty() {
|
||||
vector.push(Item::default());
|
||||
fn path_modify<'e>(
|
||||
ctx: impl Ctx + ExtractArena<'e> + ExtractIndex + InjectIndex + Copy,
|
||||
(element, existing): (Vector, Attr<'e, EditorLayerPath>),
|
||||
modification: Box<VectorModification>,
|
||||
node_path: Vec<NodeId>,
|
||||
) -> Result<(Vector, Attr<'e, EditorLayerPath>, RemoveAttr<EditorClickTarget>), Interrupt> {
|
||||
let mut element = element;
|
||||
if ctx.innermost_index() == 0 {
|
||||
modification.apply(&mut element);
|
||||
}
|
||||
modification.apply(vector.element_mut(0).expect("push should give one item"));
|
||||
|
||||
// Drop stale click-target override so hit testing uses the geometry the user is now editing
|
||||
vector.remove_attribute(ATTR_EDITOR_CLICK_TARGET);
|
||||
|
||||
// Set the path to the encapsulating subgraph (drop our own trailing entry from `node_path`),
|
||||
// matching the `path_of_subgraph` proto so editor tools can route data back to the parent layer.
|
||||
let subgraph_path: List<NodeId> = {
|
||||
let len = node_path.len();
|
||||
node_path.into_iter().take(len.saturating_sub(1)).map(Item::new_from_element).collect()
|
||||
let path = match existing.is_empty() {
|
||||
false => existing.to_vec(),
|
||||
true => {
|
||||
let len = node_path.len();
|
||||
node_path.into_iter().take(len.saturating_sub(1)).collect()
|
||||
}
|
||||
};
|
||||
let existing: List<NodeId> = vector.attribute_cloned_or_default(ATTR_EDITOR_LAYER_PATH, 0);
|
||||
vector.set_attribute(ATTR_EDITOR_LAYER_PATH, 0, if existing.is_empty() { subgraph_path } else { existing });
|
||||
|
||||
if vector.len() > 1 {
|
||||
warn!("The path modify ran on {} vector items. Only the first can be modified.", vector.len());
|
||||
}
|
||||
vector
|
||||
let (parked, _) = ctx.arena().alloc(path).ok_or(GraphError {
|
||||
kind: core_types::gpoll::ErrorKind::ArenaExhausted,
|
||||
trace: Vec::new(),
|
||||
})?;
|
||||
Ok((element, Attr(parked.as_slice()), RemoveAttr::new()))
|
||||
}
|
||||
|
||||
/// Applies the vector path's local transformation to its geometry and resets the transform to the identity.
|
||||
|
||||
Reference in New Issue
Block a user