feat(draw): continue paths on initial Enter
Start LINE, PLINE, ARC, and SPLINE from the latest path endpoint when Enter accepts the first point. Fall back to the active UCS origin.\n\nRefs #610
This commit is contained in:
parent
796d7d91d0
commit
dccaf95f49
10 changed files with 175 additions and 12 deletions
|
|
@ -4,6 +4,68 @@ use acadrust::Handle;
|
||||||
use iced::Task;
|
use iced::Task;
|
||||||
|
|
||||||
impl OpenCADStudio {
|
impl OpenCADStudio {
|
||||||
|
/// Point supplied by a bare Enter before LINE/PLINE's first click. Prefer
|
||||||
|
/// the current endpoint of the most recently created path drawable in the
|
||||||
|
/// active space. A loaded drawing has no runtime anchor, so recover its
|
||||||
|
/// newest line/arc/polyline endpoint. An empty space starts at the active
|
||||||
|
/// UCS origin (0,0,0 in user coordinates).
|
||||||
|
fn default_draw_start(&self, i: usize) -> glam::DVec3 {
|
||||||
|
let tab = &self.tabs[i];
|
||||||
|
let endpoint = |entity: &acadrust::EntityType| {
|
||||||
|
let last_grip = match entity {
|
||||||
|
acadrust::EntityType::Line(line) => {
|
||||||
|
return Some(glam::DVec3::new(
|
||||||
|
line.end.x,
|
||||||
|
line.end.y,
|
||||||
|
line.end.z,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
acadrust::EntityType::Arc(_) => Some(2),
|
||||||
|
acadrust::EntityType::LwPolyline(polyline) => {
|
||||||
|
polyline.vertices.len().checked_sub(1)
|
||||||
|
}
|
||||||
|
acadrust::EntityType::Polyline(polyline) => {
|
||||||
|
polyline.vertices.len().checked_sub(1)
|
||||||
|
}
|
||||||
|
acadrust::EntityType::Polyline2D(polyline) => {
|
||||||
|
polyline.vertices.len().checked_sub(1)
|
||||||
|
}
|
||||||
|
acadrust::EntityType::Polyline3D(polyline) => {
|
||||||
|
polyline.vertices.len().checked_sub(1)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}?;
|
||||||
|
crate::scene::view::dispatch::grips(entity)
|
||||||
|
.into_iter()
|
||||||
|
.find(|grip| grip.id == last_grip)
|
||||||
|
.map(|grip| grip.world)
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(handle) = tab.last_draw_anchor {
|
||||||
|
if tab.scene.entity_belongs_to_active_space(handle) {
|
||||||
|
if let Some(point) = tab.scene.document.get_entity(handle).and_then(endpoint) {
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let recovered = tab
|
||||||
|
.scene
|
||||||
|
.document
|
||||||
|
.entities()
|
||||||
|
.filter_map(|entity| {
|
||||||
|
let handle = entity.common().handle;
|
||||||
|
tab.scene
|
||||||
|
.entity_belongs_to_active_space(handle)
|
||||||
|
.then(|| endpoint(entity).map(|point| (handle, point)))
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
.max_by_key(|(handle, _)| handle.value())
|
||||||
|
.map(|(_, point)| point);
|
||||||
|
|
||||||
|
recovered.unwrap_or_else(|| tab.ucs_origin_world())
|
||||||
|
}
|
||||||
|
|
||||||
/// Drop cursor-relative state that was computed in the drawing space being
|
/// Drop cursor-relative state that was computed in the drawing space being
|
||||||
/// left. This is also used by MVIEW, whose command object survives its
|
/// left. This is also used by MVIEW, whose command object survives its
|
||||||
/// intentional paper/model round-trip while its old-space overlays cannot.
|
/// intentional paper/model round-trip while its old-space overlays cannot.
|
||||||
|
|
@ -169,11 +231,31 @@ impl OpenCADStudio {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
|
let default_start = matches!(&input, StepInput::Enter)
|
||||||
|
&& self.tabs[i]
|
||||||
|
.active_cmd
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|command| command.enter_accepts_default_start());
|
||||||
|
let input = if default_start {
|
||||||
|
StepInput::Point(self.default_draw_start(i))
|
||||||
|
} else {
|
||||||
|
input
|
||||||
|
};
|
||||||
if let StepInput::Point(point) = &input {
|
if let StepInput::Point(point) = &input {
|
||||||
if !self.command_point_allowed(i, *point) {
|
if !self.command_point_allowed(i, *point) {
|
||||||
return Task::none();
|
return Task::none();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if default_start {
|
||||||
|
let StepInput::Point(point) = &input else {
|
||||||
|
unreachable!("default command start must be a point");
|
||||||
|
};
|
||||||
|
self.last_point = Some(*point);
|
||||||
|
self.dyn_user_reshaped = false;
|
||||||
|
self.sync_dyn_fields();
|
||||||
|
self.reset_tracking_after_point();
|
||||||
|
self.push_ucs_to_cmd(i);
|
||||||
|
}
|
||||||
let ctrl = self.ctrl_down;
|
let ctrl = self.ctrl_down;
|
||||||
let shift = self.shift_down;
|
let shift = self.shift_down;
|
||||||
let result: Option<CmdResult> = {
|
let result: Option<CmdResult> = {
|
||||||
|
|
@ -1245,6 +1327,15 @@ impl OpenCADStudio {
|
||||||
entity,
|
entity,
|
||||||
finish,
|
finish,
|
||||||
} => {
|
} => {
|
||||||
|
let tracks_draw_anchor = matches!(
|
||||||
|
&entity,
|
||||||
|
acadrust::EntityType::Line(_)
|
||||||
|
| acadrust::EntityType::Arc(_)
|
||||||
|
| acadrust::EntityType::LwPolyline(_)
|
||||||
|
| acadrust::EntityType::Polyline(_)
|
||||||
|
| acadrust::EntityType::Polyline2D(_)
|
||||||
|
| acadrust::EntityType::Polyline3D(_)
|
||||||
|
);
|
||||||
// Replace the live entity's geometry in place, preserving its
|
// Replace the live entity's geometry in place, preserving its
|
||||||
// handle and layer (the fresh entity from the command carries
|
// handle and layer (the fresh entity from the command carries
|
||||||
// defaults — a NULL handle would desync it from the document
|
// defaults — a NULL handle would desync it from the document
|
||||||
|
|
@ -1263,6 +1354,9 @@ impl OpenCADStudio {
|
||||||
.bump_entities(&[(handle, crate::scene::ChangeKind::Modified)]);
|
.bump_entities(&[(handle, crate::scene::ChangeKind::Modified)]);
|
||||||
self.tabs[i].dirty = true;
|
self.tabs[i].dirty = true;
|
||||||
}
|
}
|
||||||
|
if tracks_draw_anchor {
|
||||||
|
self.tabs[i].last_draw_anchor = Some(handle);
|
||||||
|
}
|
||||||
if finish {
|
if finish {
|
||||||
self.finish_live_entity_history(i, handle);
|
self.finish_live_entity_history(i, handle);
|
||||||
self.tabs[i].scene.clear_preview_wire();
|
self.tabs[i].scene.clear_preview_wire();
|
||||||
|
|
@ -1292,6 +1386,12 @@ impl OpenCADStudio {
|
||||||
// document, drop its provisional history entry and keep
|
// document, drop its provisional history entry and keep
|
||||||
// prompting. A later second point creates one fresh entry.
|
// prompting. A later second point creates one fresh entry.
|
||||||
self.tabs[i].scene.erase_entities(&[handle]);
|
self.tabs[i].scene.erase_entities(&[handle]);
|
||||||
|
if self.tabs[i]
|
||||||
|
.last_draw_anchor
|
||||||
|
.is_some_and(|anchor_handle| anchor_handle == handle)
|
||||||
|
{
|
||||||
|
self.tabs[i].last_draw_anchor = None;
|
||||||
|
}
|
||||||
self.discard_last_undo_entry(i);
|
self.discard_last_undo_entry(i);
|
||||||
self.tabs[i].dirty = true;
|
self.tabs[i].dirty = true;
|
||||||
let prompt = self.tabs[i].active_cmd.as_ref().map(|c| c.prompt());
|
let prompt = self.tabs[i].active_cmd.as_ref().map(|c| c.prompt());
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,9 @@ pub(super) struct DocumentTab {
|
||||||
/// "Previous" keyword at any Select objects prompt (#426).
|
/// "Previous" keyword at any Select objects prompt (#426).
|
||||||
pub(super) prev_selection: Vec<acadrust::Handle>,
|
pub(super) prev_selection: Vec<acadrust::Handle>,
|
||||||
pub(super) last_cmd: Option<String>,
|
pub(super) last_cmd: Option<String>,
|
||||||
|
/// Most recently created path drawable. A fresh LINE/PLINE can accept its
|
||||||
|
/// current final endpoint with Enter before the first click.
|
||||||
|
pub(super) last_draw_anchor: Option<Handle>,
|
||||||
pub(super) snap_result: Option<SnapResult>,
|
pub(super) snap_result: Option<SnapResult>,
|
||||||
pub(super) active_grip: Option<GripEdit>,
|
pub(super) active_grip: Option<GripEdit>,
|
||||||
pub(super) selected_grips: Vec<GripDef>,
|
pub(super) selected_grips: Vec<GripDef>,
|
||||||
|
|
@ -437,6 +440,7 @@ impl DocumentTab {
|
||||||
layers: LayerPanel::default(),
|
layers: LayerPanel::default(),
|
||||||
active_cmd: None,
|
active_cmd: None,
|
||||||
last_cmd: None,
|
last_cmd: None,
|
||||||
|
last_draw_anchor: None,
|
||||||
snap_result: None,
|
snap_result: None,
|
||||||
active_grip: None,
|
active_grip: None,
|
||||||
selected_grips: vec![],
|
selected_grips: vec![],
|
||||||
|
|
|
||||||
|
|
@ -1775,6 +1775,16 @@ impl OpenCADStudio {
|
||||||
mut entity: acadrust::EntityType,
|
mut entity: acadrust::EntityType,
|
||||||
) -> Option<Handle> {
|
) -> Option<Handle> {
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
|
let tracks_draw_anchor = self.tabs[i].active_cmd.is_some()
|
||||||
|
&& matches!(
|
||||||
|
&entity,
|
||||||
|
acadrust::EntityType::Line(_)
|
||||||
|
| acadrust::EntityType::Arc(_)
|
||||||
|
| acadrust::EntityType::LwPolyline(_)
|
||||||
|
| acadrust::EntityType::Polyline(_)
|
||||||
|
| acadrust::EntityType::Polyline2D(_)
|
||||||
|
| acadrust::EntityType::Polyline3D(_)
|
||||||
|
);
|
||||||
let layer = &self.tabs[i].active_layer;
|
let layer = &self.tabs[i].active_layer;
|
||||||
if layer != "0" || entity.as_entity().layer().is_empty() {
|
if layer != "0" || entity.as_entity().layer().is_empty() {
|
||||||
entity.as_entity_mut().set_layer(layer.clone());
|
entity.as_entity_mut().set_layer(layer.clone());
|
||||||
|
|
@ -1946,7 +1956,7 @@ impl OpenCADStudio {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if matches!(&entity, acadrust::EntityType::Viewport(_))
|
let new_handle = if matches!(&entity, acadrust::EntityType::Viewport(_))
|
||||||
&& self.tabs[i].scene.current_layout != "Model"
|
&& self.tabs[i].scene.current_layout != "Model"
|
||||||
{
|
{
|
||||||
// Assign a unique viewport ID (max existing id + 1, min 2).
|
// Assign a unique viewport ID (max existing id + 1, min 2).
|
||||||
|
|
@ -1999,7 +2009,14 @@ impl OpenCADStudio {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(self.tabs[i].scene.add_entity(entity))
|
Some(self.tabs[i].scene.add_entity(entity))
|
||||||
|
};
|
||||||
|
|
||||||
|
if tracks_draw_anchor {
|
||||||
|
if let Some(handle) = new_handle {
|
||||||
|
self.tabs[i].last_draw_anchor = Some(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
new_handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -356,11 +356,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
let result = self.tabs[i].active_cmd.as_mut().map(|c| c.on_enter());
|
return self.feed_command(crate::command::StepInput::Enter);
|
||||||
if let Some(r) = result {
|
|
||||||
return self.apply_cmd_result(r);
|
|
||||||
}
|
|
||||||
return Task::none();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OTRACK: while aligned to a tracking ray, a bare distance
|
// OTRACK: while aligned to a tracking ray, a bare distance
|
||||||
|
|
@ -494,11 +490,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||||
}
|
}
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
if self.tabs[i].active_cmd.is_some() {
|
if self.tabs[i].active_cmd.is_some() {
|
||||||
let result = self.tabs[i].active_cmd.as_mut().map(|c| c.on_enter());
|
self.feed_command(crate::command::StepInput::Enter)
|
||||||
if let Some(r) = result {
|
|
||||||
return self.apply_cmd_result(r);
|
|
||||||
}
|
|
||||||
Task::none()
|
|
||||||
} else if let Some(cmd) = self.tabs[i].last_cmd.clone() {
|
} else if let Some(cmd) = self.tabs[i].last_cmd.clone() {
|
||||||
self.dispatch_command(&cmd)
|
self.dispatch_command(&cmd)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ impl OpenCADStudio {
|
||||||
/// point has been committed to the active command. Temporary tracking
|
/// point has been committed to the active command. Temporary tracking
|
||||||
/// points are reset on every input so they don't pile up across a
|
/// points are reset on every input so they don't pile up across a
|
||||||
/// multi-point command and overwhelm the next pick (issue #85).
|
/// multi-point command and overwhelm the next pick (issue #85).
|
||||||
fn reset_tracking_after_point(&mut self) {
|
pub(in crate::app) fn reset_tracking_after_point(&mut self) {
|
||||||
self.snapper.clear_tracking();
|
self.snapper.clear_tracking();
|
||||||
self.otrack_active = None;
|
self.otrack_active = None;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1279,6 +1279,14 @@ pub trait CadCommand: Send {
|
||||||
/// Called when the user presses Enter (finalize / next option).
|
/// Called when the user presses Enter (finalize / next option).
|
||||||
fn on_enter(&mut self) -> CmdResult;
|
fn on_enter(&mut self) -> CmdResult;
|
||||||
|
|
||||||
|
/// Whether a bare Enter should supply the drawing's continuation point as
|
||||||
|
/// this command's first point instead of calling [`Self::on_enter`]. Draw
|
||||||
|
/// commands opt in only while their first point is still unset; later
|
||||||
|
/// Enter presses retain their normal finish/cancel meaning.
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// Called when the user presses Escape (cancel).
|
/// Called when the user presses Escape (cancel).
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
|
|
|
||||||
|
|
@ -369,6 +369,9 @@ impl CadCommand for ArcCommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -467,6 +470,9 @@ impl CadCommand for Arc3PCommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.pts.is_empty()
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -564,6 +570,9 @@ impl CadCommand for ArcSCECommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -664,6 +673,9 @@ impl CadCommand for ArcSCACommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -787,6 +799,9 @@ impl CadCommand for ArcSCLCommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -886,6 +901,9 @@ impl CadCommand for ArcSEACommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -961,6 +979,9 @@ impl CadCommand for ArcSERCommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -1074,6 +1095,9 @@ impl CadCommand for ArcSEDCommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -1160,6 +1184,9 @@ impl CadCommand for ArcCSACommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
@ -1279,6 +1306,9 @@ impl CadCommand for ArcCSLCommand {
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.step == 0
|
||||||
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,10 @@ impl CadCommand for LineCommand {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.points.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -355,6 +355,10 @@ impl CadCommand for PlineCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.vertices.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
match self.live_handle {
|
match self.live_handle {
|
||||||
Some(handle) => CmdResult::FinalizeLiveEntity(handle),
|
Some(handle) => CmdResult::FinalizeLiveEntity(handle),
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,10 @@ impl CadCommand for SplineCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn enter_accepts_default_start(&self) -> bool {
|
||||||
|
self.pts.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
match self.build(false) {
|
match self.build(false) {
|
||||||
Some(e) => CmdResult::CommitAndExit(e),
|
Some(e) => CmdResult::CommitAndExit(e),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue