Sketch: drag points of the active sketch (the solver keeps the constraints, one undo step per drag); closed profiles shaded
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
0f8e4a464b
commit
b511ac6124
2 files changed
+43
-1
No files matched your search
@@ -83,6 +83,8 @@ pub struct Tokens {
|
||||
/// Sketch points: fully constrained, free.
|
||||
pub sketch_point: Color32,
|
||||
pub sketch_point_free: Color32,
|
||||
/// Closed sketch profiles (translucent fill).
|
||||
pub profile_fill: Color32,
|
||||
/// Constraint glyph boxes.
|
||||
pub glyph_bg: Color32,
|
||||
pub glyph_edge: Color32,
|
||||
@@ -165,6 +167,7 @@ impl Tokens {
|
||||
sketch_fixed: Color32::from_rgb(20, 20, 20),
|
||||
sketch_point: Color32::BLACK,
|
||||
sketch_point_free: Color32::from_rgb(30, 90, 200),
|
||||
profile_fill: Color32::from_rgba_unmultiplied_const(255, 196, 120, 70),
|
||||
glyph_bg: Color32::WHITE,
|
||||
glyph_edge: Color32::from_rgb(90, 150, 90),
|
||||
glyph_text: Color32::from_rgb(40, 110, 40),
|
||||
@@ -215,6 +218,7 @@ impl Tokens {
|
||||
t.sketch_fixed = Color32::from_rgb(232, 234, 238);
|
||||
t.sketch_point = Color32::from_rgb(232, 234, 238);
|
||||
t.sketch_point_free = Color32::from_rgb(92, 150, 255);
|
||||
t.profile_fill = Color32::from_rgba_unmultiplied_const(120, 150, 200, 40);
|
||||
t.glyph_bg = Color32::from_rgb(44, 50, 60);
|
||||
t.glyph_edge = Color32::from_rgb(96, 170, 110);
|
||||
t.glyph_text = Color32::from_rgb(150, 220, 160);
|
||||
|
||||
@@ -42,6 +42,9 @@ pub struct ViewportState {
|
||||
pub build_ms: f64,
|
||||
/// The right-click menu, open at this screen position.
|
||||
pub context_menu: Option<Pos2>,
|
||||
/// A sketch point being dragged (its id, and the undo depth when the drag began: the whole
|
||||
/// drag is one undo step).
|
||||
pub point_drag: Option<(String, usize)>,
|
||||
}
|
||||
|
||||
/// Something under the cursor.
|
||||
@@ -214,6 +217,15 @@ fn build_scene(app: &SolveApp) -> GpuScene {
|
||||
for sid in visible_sketches(app) {
|
||||
let Some(ss) = st.sketch(sid) else { continue };
|
||||
let active = s.active_sketch == Some(sid);
|
||||
// Closed profiles are shaded (lifted off a face they may lie on).
|
||||
let lift = ss.plane.normal() * 0.01;
|
||||
for p in &ss.profiles {
|
||||
for tri in p.region.triangulate(0.05) {
|
||||
for q in tri {
|
||||
sc.trans_tri((ss.plane.to_world(q) + lift).to_f32(), [0.0; 3], c4(tk.profile_fill));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (pts, col, cons) in sketch_lines(&ss.sketch, &ss.plane, active, &ss.report.curve_determined) {
|
||||
for w in pts.windows(2) {
|
||||
sc.line(w[0].to_f32(), w[1].to_f32(), sketch_color(&tk, col), if cons { 1.2 } else { 2.0 }, active);
|
||||
@@ -881,8 +893,34 @@ pub fn show(app: &mut SolveApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Dragging a sketch point of the active sketch moves it; the solver keeps the constraints.
|
||||
if app.tool.is_none() && app.dialog.is_none() && app.viewport.nav.is_none() && app.session.active_sketch.is_some() {
|
||||
if resp.drag_started_by(egui::PointerButton::Primary)
|
||||
&& let Some(a) = ui.input(|i| i.pointer.press_origin())
|
||||
&& let Some(Hit::SketchPoint { id, .. }) = pick(app, &proj, a).into_iter().next()
|
||||
{
|
||||
app.viewport.point_drag = Some((id, app.session.undo.len()));
|
||||
}
|
||||
if let Some((id, depth)) = app.viewport.point_drag.clone()
|
||||
&& resp.dragged_by(egui::PointerButton::Primary)
|
||||
&& let Some(p) = hover
|
||||
&& let Some(ss) = app.session.active_sketch.and_then(|sid| app.session.model.state().sketch(sid).cloned())
|
||||
&& let Some(w) = {
|
||||
let (o, d) = proj.ray(p);
|
||||
ss.plane.intersect_ray(o, d)
|
||||
}
|
||||
{
|
||||
let q = ss.plane.to_local(w);
|
||||
if app.session.execute("sketch.move_point", &json!({"point": id, "to": [q.x, q.y]})).is_ok() {
|
||||
app.session.undo.truncate(depth + 1);
|
||||
}
|
||||
}
|
||||
if resp.drag_stopped() {
|
||||
app.viewport.point_drag = None;
|
||||
}
|
||||
}
|
||||
// Box selection: a primary drag on the model when no navigation mode is on.
|
||||
if app.tool.is_none() && app.viewport.nav.is_none() {
|
||||
if app.tool.is_none() && app.viewport.nav.is_none() && app.viewport.point_drag.is_none() {
|
||||
let origin = ui.input(|i| i.pointer.press_origin());
|
||||
if resp.dragged_by(egui::PointerButton::Primary)
|
||||
&& let (Some(a), Some(b)) = (origin, hover)
|
||||
|
||||
Reference in new issue
Block a user