Improve spline fit and control vertex grips

This commit is contained in:
ramox81 committed 2026-08-19 11:02:32 +03:00
1 parent 97a6322e2a
commit 0d37d3ff78
13 files changed
+471 -80

No files matched your search

+4
View File
@@ -82,6 +82,10 @@ pub struct GripPopup {
pub anchor: iced::Point,
pub items: Vec<crate::scene::model::object::GripMenuItem>,
pub selected: usize,
/// Click-opened selectors stay visible while the cursor travels from the
/// arrow to the menu. Hover-opened multifunction grips still dismiss by
/// distance as before.
pub pinned: bool,
}
/// Pending follow-up value for grip-menu actions that need a number
+36 -3
View File
@@ -653,7 +653,9 @@ impl OpenCADStudio {
screen: p,
started: iced::time::Instant::now(),
});
self.grip_popup = None;
if !self.grip_popup.as_ref().is_some_and(|popup| popup.pinned) {
self.grip_popup = None;
}
} else if let Some(h) = self.grip_hover.as_mut() {
h.screen = p;
}
@@ -672,12 +674,17 @@ impl OpenCADStudio {
use crate::entities::traits::EntityTypeOps;
let items = e.grip_menu(grip_id);
if !items.is_empty() {
let selected = items
.iter()
.position(|item| item.label.starts_with('✓'))
.unwrap_or(0);
self.grip_popup = Some(crate::app::GripPopup {
handle,
grip_id,
anchor: p,
items,
selected: 0,
selected,
pinned: false,
});
}
}
@@ -685,7 +692,7 @@ impl OpenCADStudio {
}
None => {
self.grip_hover = None;
if let Some(popup) = &self.grip_popup {
if let Some(popup) = self.grip_popup.as_ref().filter(|popup| !popup.pinned) {
let dx = p.x - popup.anchor.x;
let dy = p.y - popup.anchor.y;
if (dx * dx + dy * dy).sqrt() > POPUP_DISMISS_PX {
@@ -2736,6 +2743,32 @@ impl OpenCADStudio {
let Some(&handle) = self.tabs[i].selected_grip_handles.get(grip_index) else {
return Task::none();
};
let grip_shape = self.tabs[i].selected_grips[grip_index].shape;
if grip_shape == crate::scene::model::object::GripShape::Dropdown {
use crate::entities::traits::EntityTypeOps;
let items = self.tabs[i]
.scene
.document
.get_entity(handle)
.map(|entity| entity.grip_menu(grip_id))
.unwrap_or_default();
if !items.is_empty() {
let selected = items
.iter()
.position(|item| item.label.starts_with('✓'))
.unwrap_or(0);
self.grip_popup = Some(crate::app::GripPopup {
handle,
grip_id,
anchor: p_full,
items,
selected,
pinned: true,
});
}
self.grip_hover = None;
return Task::none();
}
// The visibility (lookup) grip opens a state
// dropdown instead of starting a stretch drag.
if grip_id == crate::app::visibility::VIS_GRIP_ID {
+18
View File
@@ -495,6 +495,23 @@ impl OpenCADStudio {
} else {
vec![]
};
let control_polygon = tab.selected_handle.and_then(|handle| {
let spline = match tab.scene.document.get_entity(handle) {
Some(acadrust::EntityType::Spline(spline)) if spline.cv_frame_visible => spline,
_ => return None,
};
let points: Vec<_> = grips
.iter()
.filter(|grip| {
grip.shape == crate::scene::model::object::GripShape::Circle
})
.map(|grip| grip.pos)
.collect();
(points.len() >= 2).then_some((
points,
spline.flags.closed || spline.flags.periodic,
))
});
let grip_clip = if grips.is_empty() {
None
} else {
@@ -688,6 +705,7 @@ impl OpenCADStudio {
snap_ext_base,
snap_ext_base2,
grips,
control_polygon,
grip_clip,
ucs_icons,
ost_points,