A tool window for sketch Offset, with a typed Distance, Flip and Chain (#731)
Sketch Offset gets its own tool window with a typed Distance, Flip and Chain, as a variant of the sketch modify window.
This commit is contained in:
1 parent
1a0100cdd9
commit
beca7eb126
10 files changed
+239
-69
No files matched your search
@@ -357,7 +357,6 @@ fn mode(id: &str) -> Option<Mode> {
|
||||
"sketch.text" => Mode::Points(1),
|
||||
"sketch.edit_text" => Mode::Entities(1),
|
||||
"sketch.blend_curve" => Mode::Points(2),
|
||||
"sketch.offset" => Mode::Entities(1),
|
||||
"sketch.fillet" | "sketch.chamfer.equal_distance" | "sketch.chamfer.distance_angle" | "sketch.chamfer.two_distance" => Mode::Entities(1),
|
||||
"sketch.constraint.curvature" | "sketch.circle.two_tangent" => Mode::Entities(2),
|
||||
"sketch.circle.three_tangent" => Mode::Entities(3),
|
||||
@@ -415,7 +414,6 @@ pub fn hint(id: &str) -> Option<String> {
|
||||
"sketch.text" => "Text: click where the text starts",
|
||||
"sketch.edit_text" => "Edit Text: click a letter interior or outline",
|
||||
"sketch.blend_curve" => "Blend curve: click the ends of two curves",
|
||||
"sketch.offset" => "Offset: click a curve (its chain is offset), then the side and distance",
|
||||
"sketch.fillet" => "Fillet: click the corner of two lines",
|
||||
"sketch.chamfer.equal_distance" | "sketch.chamfer.distance_angle" | "sketch.chamfer.two_distance" => {
|
||||
"Chamfer: click the corner of two lines"
|
||||
@@ -709,30 +707,6 @@ pub fn on_click(app: &mut SolveApp, tool: &mut Tool, proj: &Proj, pos: Pos2) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if cmd == "sketch.offset" && !tool.picks.is_empty() {
|
||||
// Dense derived fit nodes must not snap a nearby side click back
|
||||
// onto the source, reducing a deliberate offset to zero.
|
||||
let state = app.session.world_state();
|
||||
let side = active_sketch(app).and_then(|sid| state.sketch(sid)).and_then(|ss| {
|
||||
let (o, d) = proj.ray(pos);
|
||||
ss.plane.intersect_ray(o, d).map(|p| ss.plane.to_local(p))
|
||||
});
|
||||
if let Some(p) = side {
|
||||
offset_side(app, tool, p);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if cmd == "sketch.offset" {
|
||||
if let Some(sid) = active_sketch(app)
|
||||
&& let Some(id) = hits.iter().find_map(|hit| match hit {
|
||||
Hit::SketchCurve { sketch, id, .. } if *sketch == sid => Some(id.clone()),
|
||||
_ => None,
|
||||
})
|
||||
{
|
||||
tool.picks.push(id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if cmd == "sketch.edit_text" {
|
||||
let selection = hits.first().and_then(|hit| match hit {
|
||||
Hit::SketchCurve { sketch, id, .. } if Some(*sketch) == active_sketch(app) => {
|
||||
@@ -961,30 +935,6 @@ pub fn finish(app: &mut SolveApp, tool: &mut Tool) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Offset: the second click sets the side and distance.
|
||||
fn offset_side(app: &mut SolveApp, tool: &mut Tool, p: Vec2) -> bool {
|
||||
if tool.cmd != "sketch.offset" || tool.picks.is_empty() {
|
||||
return false;
|
||||
}
|
||||
let st = app.session.world_state();
|
||||
let d = active_sketch(app)
|
||||
.and_then(|s| st.sketch(s))
|
||||
.and_then(|ss| {
|
||||
let curve = ss.sketch.curve_index(&tool.picks[0])?;
|
||||
if let Some(shape) = ss.sketch.shape(curve) {
|
||||
Some(shape.dist(p))
|
||||
} else {
|
||||
ss.sketch.exact_segs(curve)?.iter().map(|s| s.point_at(s.closest_param(p)).dist(p)).min_by(f64::total_cmp)
|
||||
}
|
||||
})
|
||||
.unwrap_or(0.0);
|
||||
if d > 1e-6 {
|
||||
let _ = app.run("sketch.offset", json!({"curves": [tool.picks[0]], "distance": d, "side": xy(p)}));
|
||||
}
|
||||
tool.picks.clear();
|
||||
true
|
||||
}
|
||||
|
||||
/// Rubber band for point tools and pick markers.
|
||||
pub fn preview(app: &SolveApp, t: &Tool, painter: &egui::Painter, proj: &Proj) {
|
||||
let Some(sid) = active_sketch(app) else { return };
|
||||
|
||||
Reference in new issue
Block a user