Fix collision detection for node drag-and-drop onto a wire (#2910)
* refactor * check if the wire is inside the node itself
This commit is contained in:
parent
7ee0d9a724
commit
30e5567ff2
|
|
@ -19,12 +19,15 @@ use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
|
||||||
use crate::messages::tool::common_functionality::graph_modification_utils::{self, get_clip_mode};
|
use crate::messages::tool::common_functionality::graph_modification_utils::{self, get_clip_mode};
|
||||||
use crate::messages::tool::tool_messages::tool_prelude::{Key, MouseMotion};
|
use crate::messages::tool::tool_messages::tool_prelude::{Key, MouseMotion};
|
||||||
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
|
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
|
||||||
|
use bezier_rs::Subpath;
|
||||||
use glam::{DAffine2, DVec2, IVec2};
|
use glam::{DAffine2, DVec2, IVec2};
|
||||||
use graph_craft::document::value::TaggedValue;
|
use graph_craft::document::value::TaggedValue;
|
||||||
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput};
|
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput};
|
||||||
use graph_craft::proto::GraphErrors;
|
use graph_craft::proto::GraphErrors;
|
||||||
use graphene_std::math::math_ext::QuadExt;
|
use graphene_std::math::math_ext::QuadExt;
|
||||||
|
use graphene_std::vector::misc::subpath_to_kurbo_bezpath;
|
||||||
use graphene_std::*;
|
use graphene_std::*;
|
||||||
|
use kurbo::{Line, Point};
|
||||||
use renderer::Quad;
|
use renderer::Quad;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
|
@ -1242,9 +1245,37 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||||
}
|
}
|
||||||
log::debug!("preferences.graph_wire_style: {:?}", preferences.graph_wire_style);
|
log::debug!("preferences.graph_wire_style: {:?}", preferences.graph_wire_style);
|
||||||
let (wire, is_stack) = network_interface.vector_wire_from_input(&input, preferences.graph_wire_style, selection_network_path)?;
|
let (wire, is_stack) = network_interface.vector_wire_from_input(&input, preferences.graph_wire_style, selection_network_path)?;
|
||||||
wire.rectangle_intersections_exist(bounding_box[0], bounding_box[1]).then_some((input, is_stack))
|
|
||||||
|
let bbox_rect = kurbo::Rect::new(bounding_box[0].x, bounding_box[0].y, bounding_box[1].x, bounding_box[1].y);
|
||||||
|
|
||||||
|
let p1 = DVec2::new(bbox_rect.x0, bbox_rect.y0);
|
||||||
|
let p2 = DVec2::new(bbox_rect.x1, bbox_rect.y0);
|
||||||
|
let p3 = DVec2::new(bbox_rect.x1, bbox_rect.y1);
|
||||||
|
let p4 = DVec2::new(bbox_rect.x0, bbox_rect.y1);
|
||||||
|
let ps = [p1, p2, p3, p4];
|
||||||
|
|
||||||
|
let inside = wire.is_inside_subpath(&Subpath::from_anchors_linear(ps, true), None, None);
|
||||||
|
|
||||||
|
let wire = subpath_to_kurbo_bezpath(wire);
|
||||||
|
|
||||||
|
let intersect = wire.segments().any(|segment| {
|
||||||
|
let rect = kurbo::Rect::new(bounding_box[0].x, bounding_box[0].y, bounding_box[1].x, bounding_box[1].y);
|
||||||
|
|
||||||
|
let top_line = Line::new(Point::new(rect.x0, rect.y0), Point::new(rect.x1, rect.y0));
|
||||||
|
let bottom_line = Line::new(Point::new(rect.x0, rect.y1), Point::new(rect.x1, rect.y1));
|
||||||
|
let left_line = Line::new(Point::new(rect.x0, rect.y0), Point::new(rect.x0, rect.y1));
|
||||||
|
let right_line = Line::new(Point::new(rect.x1, rect.y0), Point::new(rect.x1, rect.y1));
|
||||||
|
|
||||||
|
!segment.intersect_line(top_line).is_empty()
|
||||||
|
|| !segment.intersect_line(bottom_line).is_empty()
|
||||||
|
|| !segment.intersect_line(left_line).is_empty()
|
||||||
|
|| !segment.intersect_line(right_line).is_empty()
|
||||||
|
});
|
||||||
|
|
||||||
|
(intersect || inside).then_some((input, is_stack))
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Prioritize vertical thick lines and cancel if there are multiple potential wires
|
// Prioritize vertical thick lines and cancel if there are multiple potential wires
|
||||||
let mut node_wires = Vec::new();
|
let mut node_wires = Vec::new();
|
||||||
let mut stack_wires = Vec::new();
|
let mut stack_wires = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use bezier_rs::BezierHandles;
|
use bezier_rs::{BezierHandles, ManipulatorGroup, Subpath};
|
||||||
use dyn_any::DynAny;
|
use dyn_any::DynAny;
|
||||||
use glam::DVec2;
|
use glam::DVec2;
|
||||||
use kurbo::{CubicBez, Line, PathSeg, Point, QuadBez};
|
use kurbo::{BezPath, CubicBez, Line, PathSeg, Point, QuadBez};
|
||||||
|
|
||||||
|
use super::PointId;
|
||||||
|
|
||||||
/// Represents different ways of calculating the centroid.
|
/// Represents different ways of calculating the centroid.
|
||||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
|
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
|
||||||
|
|
@ -131,3 +133,39 @@ pub fn handles_to_segment(start: DVec2, handles: BezierHandles, end: DVec2) -> P
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn subpath_to_kurbo_bezpath(subpath: Subpath<PointId>) -> BezPath {
|
||||||
|
let maniputor_groups = subpath.manipulator_groups();
|
||||||
|
let closed = subpath.closed();
|
||||||
|
bezpath_from_manipulator_groups(maniputor_groups, closed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bezpath_from_manipulator_groups(manipulator_groups: &[ManipulatorGroup<PointId>], closed: bool) -> BezPath {
|
||||||
|
let mut bezpath = kurbo::BezPath::new();
|
||||||
|
let mut out_handle;
|
||||||
|
|
||||||
|
let Some(first) = manipulator_groups.first() else { return bezpath };
|
||||||
|
bezpath.move_to(dvec2_to_point(first.anchor));
|
||||||
|
out_handle = first.out_handle;
|
||||||
|
|
||||||
|
for manipulator in manipulator_groups.iter().skip(1) {
|
||||||
|
match (out_handle, manipulator.in_handle) {
|
||||||
|
(Some(handle_start), Some(handle_end)) => bezpath.curve_to(dvec2_to_point(handle_start), dvec2_to_point(handle_end), dvec2_to_point(manipulator.anchor)),
|
||||||
|
(None, None) => bezpath.line_to(dvec2_to_point(manipulator.anchor)),
|
||||||
|
(None, Some(handle)) => bezpath.quad_to(dvec2_to_point(handle), dvec2_to_point(manipulator.anchor)),
|
||||||
|
(Some(handle), None) => bezpath.quad_to(dvec2_to_point(handle), dvec2_to_point(manipulator.anchor)),
|
||||||
|
}
|
||||||
|
out_handle = manipulator.out_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if closed {
|
||||||
|
match (out_handle, first.in_handle) {
|
||||||
|
(Some(handle_start), Some(handle_end)) => bezpath.curve_to(dvec2_to_point(handle_start), dvec2_to_point(handle_end), dvec2_to_point(first.anchor)),
|
||||||
|
(None, None) => bezpath.line_to(dvec2_to_point(first.anchor)),
|
||||||
|
(None, Some(handle)) => bezpath.quad_to(dvec2_to_point(handle), dvec2_to_point(first.anchor)),
|
||||||
|
(Some(handle), None) => bezpath.quad_to(dvec2_to_point(handle), dvec2_to_point(first.anchor)),
|
||||||
|
}
|
||||||
|
bezpath.close_path();
|
||||||
|
}
|
||||||
|
bezpath
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue