mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Rename the nodes 'Length' -> 'Magnitude', 'Flatten Path' -> 'Combine Paths', 'Vec2 Value' -> 'Combine Vec2', and add a new 'Vec2 Value' node (#4349)
* Rename the node 'Length' -> 'Magnitude' * Rename the node 'Flatten Path' -> 'Combine Paths' * Replace the node 'Vec2 Value' with 'Combine Vec2' and add a new 'Vec2 Value' that's actually a vec2 * Update demo artwork
This commit is contained in:
@@ -1623,7 +1623,7 @@ impl Render for List<Vector> {
|
||||
}
|
||||
|
||||
// If this item carries a snapshot of upstream graphic content (e.g. it was produced by Boolean Operation,
|
||||
// Flatten Path, Morph, or any other destructive merge), recurse into that snapshot so the editor can
|
||||
// Combine Paths, Morph, or any other destructive merge), recurse into that snapshot so the editor can
|
||||
// surface the original child layers' click targets.
|
||||
let upstream_nested_layers = self.attribute_cloned_or_default::<List<Graphic>>(ATTR_EDITOR_MERGED_LAYERS, index);
|
||||
if !upstream_nested_layers.is_empty() {
|
||||
|
||||
@@ -5,7 +5,7 @@ use glam::{DVec2, IVec2, UVec2};
|
||||
|
||||
/// Obtains the X or Y component of a vec2.
|
||||
///
|
||||
/// The inverse of this node is "Vec2 Value", which can have either or both its X and Y parameters exposed as graph inputs.
|
||||
/// The inverse of this node is **Combine Vec2**, which composes a vec2 from its X and Y components.
|
||||
#[node_macro::node(name("Extract XY"), category("Math: Vector"))]
|
||||
fn extract_xy<T: Into<DVec2>>(_: impl Ctx, #[implementations(DVec2, IVec2, UVec2)] vector: Item<T>, axis: Item<XY>) -> Item<f64> {
|
||||
let vector = vector.into_element();
|
||||
|
||||
@@ -967,7 +967,7 @@ pub async fn flatten_vector<T: IntoGraphicList>(_: impl Ctx, #[implementations(L
|
||||
// TODO: we stash the pre-flattened list on the output so `List<Vector>::collect_metadata` can recurse into it,
|
||||
// TODO: which conflates render output with editor metadata and forces the pre-compensation dance below.
|
||||
// TODO: The cleaner fix is to drive each layer's metadata from its own Monitor's captured `(Context, List<Graphic>)`,
|
||||
// TODO: at which point this attribute (and the equivalents in Boolean Operation, Solidify Stroke, Flatten Path,
|
||||
// TODO: at which point this attribute (and the equivalents in Boolean Operation, Solidify Stroke, Combine Paths,
|
||||
// TODO: Morph, Rasterize) become unnecessary.
|
||||
if !output.is_empty() {
|
||||
// Item 0 carries a composed transform inherited from the flattened input, but the merged_layers
|
||||
|
||||
@@ -975,8 +975,8 @@ fn percentage_value(_: impl Ctx, _primary: (), percentage: Item<Percentage>) ->
|
||||
|
||||
/// Constructs a two-dimensional vector value which may be set to any XY pair.
|
||||
#[node_macro::node(category("Value"), name("Vec2 Value"))]
|
||||
fn vec2_value(_: impl Ctx, _primary: (), x: Item<f64>, y: Item<f64>) -> Item<DVec2> {
|
||||
Item::new_from_element(DVec2::new(*x.element(), *y.element()))
|
||||
fn vec2_value(_: impl Ctx, _primary: (), #[name("Vec2")] vec2: Item<DVec2>) -> Item<DVec2> {
|
||||
vec2
|
||||
}
|
||||
|
||||
/// Constructs a color value which may be set to any color.
|
||||
@@ -1073,6 +1073,23 @@ fn footprint_value(_: impl Ctx, _primary: (), transform: Item<DAffine2>, #[defau
|
||||
})
|
||||
}
|
||||
|
||||
/// Composes a vec2 from its X and Y components.
|
||||
///
|
||||
/// The inverse of this node is **Split Vec2**, which decomposes a vec2 back into its X and Y components.
|
||||
#[node_macro::node(category("Math: Vector"), name("Combine Vec2"))]
|
||||
fn combine_vec2(
|
||||
_: impl Ctx,
|
||||
_primary: (),
|
||||
/// The X component of the vec2.
|
||||
#[expose]
|
||||
x: Item<f64>,
|
||||
/// The Y component of the vec2.
|
||||
#[expose]
|
||||
y: Item<f64>,
|
||||
) -> Item<DVec2> {
|
||||
Item::new_from_element(DVec2::new(*x.element(), *y.element()))
|
||||
}
|
||||
|
||||
/// The dot product operation (`·`) calculates the degree of similarity of a vec2 pair based on their angles and lengths.
|
||||
///
|
||||
/// Calculated as `‖a‖‖b‖cos(θ)`, it represents the product of their lengths (`‖a‖‖b‖`) scaled by the alignment of their directions (`cos(θ)`).
|
||||
@@ -1152,10 +1169,9 @@ fn angle_to<T: ToPosition, U: ToPosition>(
|
||||
Item::from_parts(result, attributes)
|
||||
}
|
||||
|
||||
// TODO: Rename to "Magnitude"
|
||||
/// The magnitude operator (`‖x‖`) calculates the length of a vec2, which is the distance from the base to the tip of the arrow represented by the vector.
|
||||
#[node_macro::node(category("Math: Vector"))]
|
||||
fn length(_: impl Ctx, vector: Item<DVec2>) -> Item<f64> {
|
||||
fn magnitude(_: impl Ctx, vector: Item<DVec2>) -> Item<f64> {
|
||||
let (vector, attributes) = vector.into_parts();
|
||||
|
||||
Item::from_parts(vector.length(), attributes)
|
||||
@@ -1185,9 +1201,9 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn length_function() {
|
||||
pub fn magnitude_function() {
|
||||
let vector = Item::new_from_element(DVec2::new(3., 4.));
|
||||
assert_eq!(length((), vector).into_element(), 5.);
|
||||
assert_eq!(magnitude((), vector).into_element(), 5.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -321,7 +321,7 @@ mod test {
|
||||
Item::new_from_element(count),
|
||||
)
|
||||
.await;
|
||||
let vector_list = List::new_from_item(vector_nodes::flatten_path(Footprint::default(), List::new_from_element(Graphic::Vector(repeated))).await);
|
||||
let vector_list = List::new_from_item(vector_nodes::combine_paths(Footprint::default(), List::new_from_element(Graphic::Vector(repeated))).await);
|
||||
let vector = vector_list.element(0).unwrap();
|
||||
assert_eq!(vector.region_manipulator_groups().count(), 3);
|
||||
for (index, (_, manipulator_groups)) in vector.region_manipulator_groups().enumerate() {
|
||||
@@ -340,7 +340,7 @@ mod test {
|
||||
Item::new_from_element(1),
|
||||
)
|
||||
.await;
|
||||
let vector_list = List::new_from_item(vector_nodes::flatten_path(Footprint::default(), List::new_from_element(Graphic::Vector(repeated))).await);
|
||||
let vector_list = List::new_from_item(vector_nodes::combine_paths(Footprint::default(), List::new_from_element(Graphic::Vector(repeated))).await);
|
||||
let vector = vector_list.element(0).unwrap();
|
||||
assert_eq!(vector.region_manipulator_groups().count(), 1);
|
||||
|
||||
@@ -362,7 +362,7 @@ mod test {
|
||||
Item::new_from_element(count),
|
||||
)
|
||||
.await;
|
||||
let vector_list = List::new_from_item(vector_nodes::flatten_path(Footprint::default(), List::new_from_element(Graphic::Vector(repeated))).await);
|
||||
let vector_list = List::new_from_item(vector_nodes::combine_paths(Footprint::default(), List::new_from_element(Graphic::Vector(repeated))).await);
|
||||
let vector = vector_list.element(0).unwrap();
|
||||
assert_eq!(vector.region_manipulator_groups().count(), 8);
|
||||
for (index, (_, manipulator_groups)) in vector.region_manipulator_groups().enumerate() {
|
||||
@@ -381,7 +381,7 @@ mod test {
|
||||
Item::new_from_element(8),
|
||||
)
|
||||
.await;
|
||||
let vector_list = List::new_from_item(vector_nodes::flatten_path(Footprint::default(), List::new_from_element(Graphic::Vector(repeated))).await);
|
||||
let vector_list = List::new_from_item(vector_nodes::combine_paths(Footprint::default(), List::new_from_element(Graphic::Vector(repeated))).await);
|
||||
let vector = vector_list.element(0).unwrap();
|
||||
assert_eq!(vector.region_manipulator_groups().count(), 8);
|
||||
|
||||
|
||||
@@ -1560,9 +1560,8 @@ async fn map_points(ctx: impl Ctx + CloneVarArgs + ExtractAll, content: Item<Vec
|
||||
}
|
||||
|
||||
/// Combines every vector path across the input into a single compound path.
|
||||
// TODO: Rename to "Combine Paths" with a document migration
|
||||
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
|
||||
pub async fn flatten_path<T: IntoGraphicList>(_: impl Ctx, #[implementations(List<Graphic>, List<Vector>)] content: T) -> Item<Vector> {
|
||||
pub async fn combine_paths<T: IntoGraphicList>(_: impl Ctx, #[implementations(List<Graphic>, List<Vector>)] content: T) -> Item<Vector> {
|
||||
let graphic_list = content.into_graphic_list();
|
||||
let flattened = graphic_list.clone().into_flattened_list::<Vector>();
|
||||
|
||||
@@ -3597,12 +3596,12 @@ mod test {
|
||||
Item::new_from_element(0),
|
||||
)
|
||||
.await;
|
||||
let flatten_path = List::new_from_item(super::flatten_path(Footprint::default(), List::new_from_element(Graphic::Vector(copy_to_points))).await);
|
||||
let flattened_copy_to_points = flatten_path.element(0).unwrap();
|
||||
let combined = List::new_from_item(super::combine_paths(Footprint::default(), List::new_from_element(Graphic::Vector(copy_to_points))).await);
|
||||
let combined_copy_to_points = combined.element(0).unwrap();
|
||||
|
||||
assert_eq!(flattened_copy_to_points.region_manipulator_groups().count(), expected_points.len());
|
||||
assert_eq!(combined_copy_to_points.region_manipulator_groups().count(), expected_points.len());
|
||||
|
||||
for (index, (_, manipulator_groups)) in flattened_copy_to_points.region_manipulator_groups().enumerate() {
|
||||
for (index, (_, manipulator_groups)) in combined_copy_to_points.region_manipulator_groups().enumerate() {
|
||||
let offset = expected_points[index];
|
||||
let manipulator_groups_anchors = manipulator_groups.iter().map(|manipulators| manipulators.anchor).collect::<Vec<DVec2>>();
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user