forked from 1b-agent/opencadstudio-upstream
feat(pedit): convert prompt, join, fit/spline/decurve; join fixes (#263)
PEDIT reworked around a mode machine: - Picking a line/arc asks "Object is not a polyline. Turn it into one? [Yes/No] <Y>" — Yes converts in place (arc keeps its bulge) and editing continues on the result. Pickfirst: an already-selected polyline skips the select step, a selected line/arc goes straight to the convert prompt. - Join gathers with the normal selection system (single picks AND window/crossing boxes) and merges through the JOIN machinery. - Fit replaces every segment with a classic equal-parameter BIARC: two arcs per segment meeting tangentially at an inserted knee, both segments at a vertex sharing that vertex's tangent — the whole run is tangent-continuous (verified: zero tangent jump on L/closed/zigzag/S shapes). Spline resamples the vertex frame as a uniform cubic B-spline (8 samples per span); Decurve straightens every bulge. - Earlier hardening kept: undo snapshot before the mutation, immediate repaint, polyline-only pick validation. - Vertex editing lives on grips, so no Edit-vertex submode; instead the vertex grip hover menu gains Break — a closed polyline opens at the vertex, an open one splits into two (interior vertices only), handled driver-side as an entity replacement. JOIN itself: segs_of now emits one segment per span of an OPEN polyline (bulges kept), so polylines merge with their neighbours — PEDIT Join's set always contains the target polyline and used to abort every time; plain JOIN had the same gap. JOIN also honours pickfirst: launched with two or more objects selected it joins them immediately. Closes #263 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b32a9b4083
commit
e7eb84b514
7 files changed
+705
-112
No files matched your search
+51
-18
@@ -1277,25 +1277,58 @@ impl OpenCADStudio {
|
||||
self.restore_pre_cmd_tangent();
|
||||
}
|
||||
CmdResult::PeditOp { handle, op } => {
|
||||
use crate::modules::draw::modify::pedit::apply_pedit;
|
||||
let changed = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.get_entity_mut(handle)
|
||||
.map(|e| apply_pedit(e, &op))
|
||||
.unwrap_or(false);
|
||||
if changed {
|
||||
self.push_undo_snapshot(i, "PEDIT");
|
||||
self.tabs[i].dirty = true;
|
||||
self.command_line.push_output("PEDIT: applied.");
|
||||
self.refresh_properties();
|
||||
} else {
|
||||
self.command_line
|
||||
.push_error("PEDIT: operation not applicable to this entity.");
|
||||
use crate::modules::draw::modify::pedit::{
|
||||
apply_pedit, convert_to_polyline, PeditOp,
|
||||
};
|
||||
match &op {
|
||||
// The convert replaces the entity (new handle).
|
||||
PeditOp::ConvertToPolyline => {
|
||||
let converted = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.get_entity(handle)
|
||||
.and_then(convert_to_polyline);
|
||||
match converted {
|
||||
Some(pl) => {
|
||||
return self.apply_cmd_result(CmdResult::ReplaceEntity(
|
||||
handle,
|
||||
vec![pl],
|
||||
));
|
||||
}
|
||||
None => self
|
||||
.command_line
|
||||
.push_error("PEDIT: cannot convert this entity."),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Snapshot BEFORE the mutation — an after-the-fact
|
||||
// snapshot records the changed state and undo no-ops.
|
||||
self.push_undo_snapshot(i, "PEDIT");
|
||||
let changed = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.get_entity_mut(handle)
|
||||
.map(|e| apply_pedit(e, &op))
|
||||
.unwrap_or(false);
|
||||
if changed {
|
||||
self.tabs[i].dirty = true;
|
||||
// Repaint immediately (wide-band fill included).
|
||||
self.tabs[i].scene.mark_entity_dirty(handle);
|
||||
self.tabs[i].scene.refresh_fill_model(handle);
|
||||
self.tabs[i].scene.bump_geometry_no_blocks();
|
||||
self.command_line.push_output("PEDIT: applied.");
|
||||
self.refresh_properties();
|
||||
} else {
|
||||
let _ = self.tabs[i].history.undo_stack.pop();
|
||||
self.command_line
|
||||
.push_error("PEDIT: operation not applicable to this entity.");
|
||||
}
|
||||
}
|
||||
}
|
||||
let prompt = self.tabs[i].active_cmd.as_ref().map(|c| c.prompt());
|
||||
if let Some(p) = prompt {
|
||||
self.command_line.push_info(&p);
|
||||
}
|
||||
// Keep command active — user may apply more ops
|
||||
self.command_line
|
||||
.push_info("PEDIT Enter option [C=Close O=Open W=Width X=Exit]:");
|
||||
}
|
||||
CmdResult::JoinEntities(handles) => {
|
||||
use crate::modules::draw::modify::join::join_entities;
|
||||
|
||||
Reference in new issue
Block a user