Fix 'Morph' node lerping the target paths to its end point instead of start point (#2754)

* fix lerping the target paths to the point at the end of path instead of the start.

* comment

* append a MoveTo element first if the bezpath is empty

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Priyanshu 2025-06-26 13:14:22 +05:30 committed by GitHub
parent 02afd08c80
commit 86da69e33f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -15,7 +15,7 @@ use crate::vector::{FillId, PointDomain, RegionId};
use crate::{CloneVarArgs, Color, Context, Ctx, ExtractAll, GraphicElement, GraphicGroupTable, OwnedContextImpl}; use crate::{CloneVarArgs, Color, Context, Ctx, ExtractAll, GraphicElement, GraphicGroupTable, OwnedContextImpl};
use bezier_rs::{Join, ManipulatorGroup, Subpath}; use bezier_rs::{Join, ManipulatorGroup, Subpath};
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use kurbo::{Affine, BezPath, DEFAULT_ACCURACY, ParamCurve, PathEl, PathSeg, Point, Shape}; use kurbo::{Affine, BezPath, DEFAULT_ACCURACY, ParamCurve, PathEl, PathSeg, Shape};
use rand::{Rng, SeedableRng}; use rand::{Rng, SeedableRng};
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
use std::f64::consts::PI; use std::f64::consts::PI;
@ -1591,6 +1591,9 @@ async fn morph(_: impl Ctx, source: VectorDataTable, #[expose] target: VectorDat
} }
for segment in new_segments { for segment in new_segments {
if bezpath.elements().is_empty() {
bezpath.move_to(segment.start())
}
bezpath.push(segment.as_path_el()); bezpath.push(segment.as_path_el());
} }
@ -1666,7 +1669,10 @@ async fn morph(_: impl Ctx, source: VectorDataTable, #[expose] target: VectorDat
for mut source_path in source_paths { for mut source_path in source_paths {
source_path.apply_affine(Affine::new(source_transform.to_cols_array())); source_path.apply_affine(Affine::new(source_transform.to_cols_array()));
let end: Point = source_path.elements().last().and_then(|element| element.end_point()).unwrap_or_default(); // Skip if the path has no segments else get the point at the end of the path.
let Some(end) = source_path.segments().last().and_then(|element| Some(element.end())) else {
continue;
};
for element in source_path.elements_mut() { for element in source_path.elements_mut() {
match element { match element {
@ -1690,20 +1696,23 @@ async fn morph(_: impl Ctx, source: VectorDataTable, #[expose] target: VectorDat
for mut target_path in target_paths { for mut target_path in target_paths {
target_path.apply_affine(Affine::new(source_transform.to_cols_array())); target_path.apply_affine(Affine::new(source_transform.to_cols_array()));
let end: Point = target_path.elements().last().and_then(|element| element.end_point()).unwrap_or_default(); // Skip if the path has no segments else get the point at the start of the path.
let Some(start) = target_path.segments().next().and_then(|element| Some(element.start())) else {
continue;
};
for element in target_path.elements_mut() { for element in target_path.elements_mut() {
match element { match element {
PathEl::MoveTo(point) => *point = point.lerp(end, time), PathEl::MoveTo(point) => *point = start.lerp(*point, time),
PathEl::LineTo(point) => *point = point.lerp(end, time), PathEl::LineTo(point) => *point = start.lerp(*point, time),
PathEl::QuadTo(point, point1) => { PathEl::QuadTo(point, point1) => {
*point = point.lerp(end, time); *point = start.lerp(*point, time);
*point1 = point1.lerp(end, time); *point1 = start.lerp(*point1, time);
} }
PathEl::CurveTo(point, point1, point2) => { PathEl::CurveTo(point, point1, point2) => {
*point = point.lerp(end, time); *point = start.lerp(*point, time);
*point1 = point1.lerp(end, time); *point1 = start.lerp(*point1, time);
*point2 = point2.lerp(end, time); *point2 = start.lerp(*point2, time);
} }
PathEl::ClosePath => {} PathEl::ClosePath => {}
} }