Skip to content

Commit d393654

Browse files
committed
Fix NaN and guard against other potential NaN bugs breaking the editor
1 parent 8006668 commit d393654

3 files changed

Lines changed: 17 additions & 8 deletions

File tree

editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,8 @@ impl MessageHandler<NavigationMessage, NavigationMessageContext<'_>> for Navigat
343343
let (pos1, pos2) = (pos1.min(pos2), pos1.max(pos2));
344344
let diagonal = pos2 - pos1;
345345

346-
if diagonal.length() < f64::EPSILON * 1000. || viewport.size().into_dvec2() == DVec2::ZERO {
347-
warn!("Cannot center since the viewport size is 0");
346+
if !diagonal.is_finite() || diagonal.length() < f64::EPSILON * 1000. || viewport.size().into_dvec2() == DVec2::ZERO {
347+
warn!("Cannot center since the viewport size is 0 or the bounds are non-finite");
348348
return;
349349
}
350350

editor/src/messages/portfolio/document/utility_types/network_interface.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,8 @@ impl NodeNetworkInterface {
12091209
}
12101210
self.document_metadata.bounding_box_document(layer)
12111211
})
1212+
// Skip any layer bounds containing NaN to avoid poisoning the combined result
1213+
.filter(|[min, max]| min.is_finite() && max.is_finite())
12121214
.reduce(Quad::combine_bounds)
12131215
}
12141216

node-graph/nodes/vector/src/vector_nodes.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use graphic_types::Vector;
1111
use graphic_types::raster_types::{CPU, GPU, Raster};
1212
use graphic_types::{Graphic, IntoGraphicTable};
1313
use kurbo::simplify::{SimplifyOptions, simplify_bezpath};
14-
use kurbo::{Affine, BezPath, DEFAULT_ACCURACY, Line, ParamCurve, PathEl, PathSeg, Shape};
14+
use kurbo::{Affine, BezPath, DEFAULT_ACCURACY, Line, ParamCurve, ParamCurveArclen, PathEl, PathSeg, Shape};
1515
use rand::{Rng, SeedableRng};
1616
use std::collections::hash_map::DefaultHasher;
1717
use vector_types::subpath::{BezierHandles, ManipulatorGroup};
@@ -2187,11 +2187,13 @@ async fn morph<I: IntoGraphicTable + 'n + Send + Clone>(
21872187
// Lerp styles
21882188
let vector_alpha_blending = source_row.alpha_blending.lerp(target_row.alpha_blending, time as f32);
21892189

2190-
// Evaluate the spatial position on the control path for the translation component
2190+
// Evaluate the spatial position on the control path for the translation component.
2191+
// When the segment has zero arc length (e.g., two objects at the same position), inv_arclen
2192+
// produces NaN (0/0), so we fall back to the segment start point to avoid NaN translation.
21912193
let path_position = {
2192-
// Use the original path segment index (not the clamped object index)
21932194
let segment_index = path_segment_index.min(segment_count - 1);
21942195
let segment = control_bezpath.get_seg(segment_index + 1).unwrap();
2196+
let parametric_t = if segment.arclen(DEFAULT_ACCURACY) < f64::EPSILON { 0. } else { parametric_t };
21952197
let point = segment.eval(parametric_t);
21962198
DVec2::new(point.x, point.y)
21972199
};
@@ -2223,9 +2225,14 @@ async fn morph<I: IntoGraphicTable + 'n + Send + Clone>(
22232225
// the row transform (which will be group_transform * lerped_transform after the
22242226
// pipeline's Transform node runs), the lerped_transform cancels out and children
22252227
// get the correct footprint: parent * group_transform * child_transform.
2226-
let lerped_inverse = lerped_transform.inverse();
2227-
for row in graphic_table_content.iter_mut() {
2228-
*row.transform = lerped_inverse * *row.transform;
2228+
// Only pre-compensate if the lerped transform is invertible (non-zero determinant).
2229+
// A zero determinant can occur when interpolated scale passes through zero (e.g., flipped axes),
2230+
// in which case we skip pre-compensation to avoid propagating NaN through upstream_data transforms.
2231+
if lerped_transform.matrix2.determinant().abs() > f64::EPSILON {
2232+
let lerped_inverse = lerped_transform.inverse();
2233+
for row in graphic_table_content.iter_mut() {
2234+
*row.transform = lerped_inverse * *row.transform;
2235+
}
22292236
}
22302237

22312238
let mut vector = Vector {

0 commit comments

Comments
 (0)