forked from 1b-agent/opencadstudio-upstream
feat(draw): Arc Continue command; 3-Point default
Arc ribbon default + icon + dropdown order set to 3-Point. New ARC_CONT: tangent-continuing arc from the last line/arc endpoint, pick end only; Ctrl flips direction. Exit anchor recorded on commit (disambiguated by last pick) so chaining continues from the correct end. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
b808fc2f86
commit
c4fcfacb18
10 files changed
+212
-13
No files matched your search
@@ -11,10 +11,12 @@ impl OpenCADStudio {
|
||||
/// lives in exactly one place. No-op when no command is active.
|
||||
pub(super) fn feed_command(&mut self, input: StepInput) -> Task<Message> {
|
||||
let i = self.active_tab;
|
||||
let ctrl = self.ctrl_down;
|
||||
let result: Option<CmdResult> = {
|
||||
let Some(cmd) = self.tabs[i].active_cmd.as_mut() else {
|
||||
return Task::none();
|
||||
};
|
||||
cmd.set_ctrl(ctrl);
|
||||
match input {
|
||||
StepInput::Point(p) => Some(cmd.on_point(p)),
|
||||
StepInput::Text(s) => cmd.on_text_input(&s),
|
||||
@@ -284,6 +286,9 @@ impl OpenCADStudio {
|
||||
&path,
|
||||
);
|
||||
}
|
||||
// Record where this draw ended so ARC_CONT can continue from it
|
||||
// (before `entity` is moved into commit_entity).
|
||||
self.update_cont_anchor(&entity);
|
||||
let label = self.history_label_from_active_cmd(i, "ENTITY");
|
||||
self.push_undo_snapshot(i, label);
|
||||
self.commit_entity(entity);
|
||||
|
||||
@@ -292,6 +292,31 @@ impl OpenCADStudio {
|
||||
self.command_line.push_info(&new_cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
|
||||
}
|
||||
"ARC_CONT" => {
|
||||
use crate::modules::draw::draw::arc::{continue_anchor, ArcContCommand};
|
||||
// Prefer the anchor recorded when the last line/arc was drawn (it
|
||||
// knows the true drawing-end tangent); otherwise fall back to the
|
||||
// last line/arc found in the document (e.g. after a file load).
|
||||
let seed = self.cont_anchor.or_else(|| {
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.entities()
|
||||
.filter_map(|e| continue_anchor(e, None))
|
||||
.last()
|
||||
});
|
||||
match seed {
|
||||
Some((s, tangent)) => {
|
||||
let new_cmd = ArcContCommand::new(s, tangent);
|
||||
self.command_line.push_info(&new_cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
|
||||
}
|
||||
None => {
|
||||
self.command_line
|
||||
.push_info("ARC Continue No previous line or arc to continue.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"RECT" | "RECTANG" | "REC" => {
|
||||
use crate::modules::draw::draw::shapes::RectCommand;
|
||||
|
||||
@@ -392,6 +392,10 @@ pub(super) struct OpenCADStudio {
|
||||
show_layout_tabs: bool,
|
||||
/// Last point committed by a drawing command — used as ortho/polar base.
|
||||
last_point: Option<glam::Vec3>,
|
||||
/// Endpoint + unit exit-tangent of the most recently drawn line/arc, so
|
||||
/// `ARC_CONT` (Arc → Continue) can start tangentially from where drawing
|
||||
/// ended. `None` once a non-line/arc entity is committed.
|
||||
cont_anchor: Option<(glam::DVec3, glam::DVec3)>,
|
||||
/// OS window Id for the floating Layer Properties Manager (None when closed).
|
||||
/// OS window Id of the primary application window.
|
||||
main_window: Option<window::Id>,
|
||||
@@ -2150,6 +2154,7 @@ impl OpenCADStudio {
|
||||
clipboard_deps: ClipboardDeps::default(),
|
||||
shift_down: false,
|
||||
ctrl_down: false,
|
||||
cont_anchor: None,
|
||||
mtext_editor: None,
|
||||
text_inline: None,
|
||||
layout_context_menu: None,
|
||||
|
||||
@@ -198,6 +198,26 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
/// Push the live Ctrl state into tab `i`'s active command before it builds a
|
||||
/// preview/commit (arc-direction flip on `ARC_CONT`, etc.).
|
||||
pub(in crate::app) fn push_ctrl_to_cmd(&mut self, i: usize) {
|
||||
let ctrl = self.ctrl_down;
|
||||
if let Some(c) = self.tabs[i].active_cmd.as_mut() {
|
||||
c.set_ctrl(ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
/// Cache the endpoint + exit tangent of a just-committed line/arc so a
|
||||
/// following `ARC_CONT` starts tangentially from where drawing ended. Set to
|
||||
/// `None` for any other entity kind. Uses `last_point` (the final pick) to
|
||||
/// pick the endpoint the pen actually finished on.
|
||||
pub(in crate::app) fn update_cont_anchor(&mut self, entity: &acadrust::EntityType) {
|
||||
let last = self
|
||||
.last_point
|
||||
.map(|v| glam::DVec3::new(v.x as f64, v.y as f64, v.z as f64));
|
||||
self.cont_anchor = crate::modules::draw::draw::arc::continue_anchor(entity, last);
|
||||
}
|
||||
|
||||
pub(in crate::app) fn dyn_resolve_point(&self) -> Option<glam::Vec3> {
|
||||
use crate::app::document::DynComponent;
|
||||
let i = self.active_tab;
|
||||
|
||||
@@ -1751,8 +1751,17 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
Message::SetModifiers { shift, ctrl } => {
|
||||
let ctrl_changed = self.ctrl_down != ctrl;
|
||||
self.shift_down = shift;
|
||||
self.ctrl_down = ctrl;
|
||||
// A live command may key its preview off Ctrl (arc-direction
|
||||
// flip). Rebuild it at the current cursor so the flip shows
|
||||
// without waiting for the next mouse move.
|
||||
let i = self.active_tab;
|
||||
if ctrl_changed && self.tabs[i].active_cmd.is_some() {
|
||||
let p = self.tabs[i].last_cursor_screen;
|
||||
return Task::done(Message::ViewportMove(p));
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
|
||||
@@ -1090,9 +1090,11 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
||||
s.screen.y += tile_b.y;
|
||||
}
|
||||
|
||||
// Give the command the current UCS before it builds its
|
||||
// rubber-band preview (and, by persistence, its commit).
|
||||
// Give the command the current UCS + Ctrl state before it
|
||||
// builds its rubber-band preview (and, by persistence, its
|
||||
// commit).
|
||||
self.push_ucs_to_cmd(i);
|
||||
self.push_ctrl_to_cmd(i);
|
||||
let mut previews = if needs_structure {
|
||||
let mut p = self.tabs[i]
|
||||
.active_cmd
|
||||
|
||||
Reference in new issue
Block a user