feat(frame): complete frame controls
Preserve frame geometry for selection while separating viewport and plot visibility across supported reference entities. Refs #642
This commit is contained in:
commit
44efb8fd53
88 changed files with 1529 additions and 693 deletions
|
|
@ -1014,7 +1014,10 @@ impl OpenCADStudio {
|
|||
self.commit_undo_delta(i, pending);
|
||||
}
|
||||
}
|
||||
CmdResult::WipeoutFromPolyline(handle) => {
|
||||
CmdResult::WipeoutFromPolyline {
|
||||
handle,
|
||||
erase_source,
|
||||
} => {
|
||||
let wipeout = {
|
||||
let scene = &self.tabs[i].scene;
|
||||
scene
|
||||
|
|
@ -1026,16 +1029,23 @@ impl OpenCADStudio {
|
|||
)
|
||||
};
|
||||
if let Some(wipeout) = wipeout {
|
||||
if erase_source {
|
||||
return self.apply_cmd_result(CmdResult::ReplaceMany(
|
||||
vec![(handle, Vec::new())],
|
||||
vec![wipeout],
|
||||
));
|
||||
}
|
||||
return self.apply_cmd_result(CmdResult::CommitAndExit(wipeout));
|
||||
}
|
||||
self.command_line.push_error(
|
||||
"WIPEOUT Polyline: select a closed planar polyline with at least 3 vertices.",
|
||||
crate::t!("WIPEOUT Polyline: select a straight, closed, planar 2D polyline with at least 3 non-intersecting vertices.").as_ref(),
|
||||
);
|
||||
if let Some(prompt) =
|
||||
self.tabs[i].active_cmd.as_ref().map(|command| command.prompt())
|
||||
{
|
||||
self.command_line.push_info(&prompt);
|
||||
}
|
||||
let command =
|
||||
crate::modules::draw::draw::wipeout::WipeoutCommand::new_polyline();
|
||||
self.command_line.push_info(
|
||||
&crate::command::CadCommand::prompt(&command),
|
||||
);
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
}
|
||||
CmdResult::MviewSwitchLayout(layout) => {
|
||||
let task = self.on_layout_switch_preserving_command(layout);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,11 @@ impl OpenCADStudio {
|
|||
let wo_cmd = match args.as_str() {
|
||||
"P" | "POLYLINE" => WipeoutCommand::new_polyline(),
|
||||
"R" | "RECTANGULAR" => WipeoutCommand::new_rectangular(),
|
||||
_ => WipeoutCommand::new_polygonal(),
|
||||
_ => WipeoutCommand::new_polygonal(
|
||||
crate::modules::draw::draw::wipeout::wipeout_frame_mode(
|
||||
&self.tabs[i].scene.document,
|
||||
),
|
||||
),
|
||||
};
|
||||
self.command_line.push_info(&wo_cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(wo_cmd));
|
||||
|
|
|
|||
|
|
@ -514,7 +514,15 @@ inventory::submit!(crate::command::CommandRegistration {
|
|||
"CMLJUST",
|
||||
"TEXTQLTY",
|
||||
"SORTENTS",
|
||||
"FRAME",
|
||||
"IMAGEFRAME",
|
||||
"PDFFRAME",
|
||||
"POINTCLOUDCLIPFRAME",
|
||||
"XCLIPFRAME",
|
||||
"WIPEOUTFRAME",
|
||||
"FRAMES0",
|
||||
"FRAMES1",
|
||||
"FRAMES2",
|
||||
"HALOGAP",
|
||||
"TRACEWID",
|
||||
"SKETCHINC",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ use super::*;
|
|||
impl OpenCADStudio {
|
||||
pub(super) fn dispatch_styleprops(&mut self, cmd: &str, i: usize) -> Option<Task<Message>> {
|
||||
match cmd {
|
||||
"FRAMES0" => return self.dispatch_styleprops("SETVAR FRAME 0", i),
|
||||
"FRAMES1" => return self.dispatch_styleprops("SETVAR FRAME 1", i),
|
||||
"FRAMES2" => return self.dispatch_styleprops("SETVAR FRAME 2", i),
|
||||
// COLOR <ByLayer|ByBlock|1-255|name> — the colour applied to new
|
||||
// objects (CECOLOR). Bare COLOR reports the current value.
|
||||
"COLOR" | "COLOUR" | "CECOLOR" | "DDCOLOR" => {
|
||||
|
|
@ -919,7 +922,12 @@ impl OpenCADStudio {
|
|||
| "CMLJUST"
|
||||
| "TEXTQLTY"
|
||||
| "SORTENTS"
|
||||
| "FRAME"
|
||||
| "IMAGEFRAME"
|
||||
| "PDFFRAME"
|
||||
| "POINTCLOUDCLIPFRAME"
|
||||
| "XCLIPFRAME"
|
||||
| "WIPEOUTFRAME"
|
||||
| "HALOGAP"
|
||||
| "TRACEWID"
|
||||
| "SKETCHINC"
|
||||
|
|
@ -945,9 +953,83 @@ impl OpenCADStudio {
|
|||
let value = it.next().map(|s| s.trim().to_string());
|
||||
if name.is_empty() || name == "?" {
|
||||
self.command_line.push_info(
|
||||
"SETVAR: LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT ZOOMWHEEL ZOOMFACTOR CURSORSIZE PICKBOX CURSORTYPE SNAPANG ATTREQ ATTDIA DIMASSOC ANGBASE ANGDIR | CLAYER CELTYPE TEXTSTYLE (read-only)",
|
||||
"SETVAR: LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT FRAME IMAGEFRAME PDFFRAME WIPEOUTFRAME XCLIPFRAME POINTCLOUDCLIPFRAME ZOOMWHEEL ZOOMFACTOR CURSORSIZE PICKBOX CURSORTYPE SNAPANG ATTREQ ATTDIA DIMASSOC ANGBASE ANGDIR | CLAYER CELTYPE TEXTSTYLE (read-only)",
|
||||
);
|
||||
} else {
|
||||
let frame_kind = crate::scene::frame::kind_for_name(&name);
|
||||
if name == "FRAME" || frame_kind.is_some() {
|
||||
let current = frame_kind.map_or_else(
|
||||
|| crate::scene::frame::master_mode(&self.tabs[i].scene.document),
|
||||
|kind| crate::scene::frame::mode(&self.tabs[i].scene.document, kind),
|
||||
);
|
||||
match &value {
|
||||
Some(value) => match value.parse::<i16>() {
|
||||
Ok(mode @ 0..=2) => {
|
||||
if current != mode {
|
||||
let changed_kinds: Vec<_> = frame_kind.map_or_else(
|
||||
|| {
|
||||
crate::scene::frame::ALL_KINDS
|
||||
.into_iter()
|
||||
.filter(|kind| {
|
||||
crate::scene::frame::mode(
|
||||
&self.tabs[i].scene.document,
|
||||
*kind,
|
||||
) != mode
|
||||
})
|
||||
.collect()
|
||||
},
|
||||
|kind| vec![kind],
|
||||
);
|
||||
self.push_undo_snapshot(i, &name);
|
||||
if let Some(kind) = frame_kind {
|
||||
crate::scene::frame::set_mode(
|
||||
&mut self.tabs[i].scene.document,
|
||||
kind,
|
||||
mode,
|
||||
);
|
||||
} else {
|
||||
crate::scene::frame::set_master_mode(
|
||||
&mut self.tabs[i].scene.document,
|
||||
mode,
|
||||
);
|
||||
}
|
||||
let changes: Vec<_> = self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.entities()
|
||||
.filter_map(|entity| {
|
||||
changed_kinds
|
||||
.iter()
|
||||
.any(|kind| {
|
||||
crate::scene::frame::affected(entity, *kind)
|
||||
})
|
||||
.then_some((
|
||||
entity.common().handle,
|
||||
crate::scene::ChangeKind::Modified,
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
if !changes.is_empty() {
|
||||
self.tabs[i].scene.bump_entities(&changes);
|
||||
}
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
self.command_line
|
||||
.push_output(&format!("{name} = {mode}"));
|
||||
}
|
||||
_ => self.command_line.push_error(
|
||||
crate::tf!("SETVAR: {name} requires 0, 1, or 2.").as_ref(),
|
||||
),
|
||||
},
|
||||
None => {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"Enter new value for {name} <{current}>:"
|
||||
).as_ref());
|
||||
self.pending_setvar = Some(name.clone());
|
||||
}
|
||||
}
|
||||
return Some(self.finish_dispatch(cmd));
|
||||
}
|
||||
// Parse a boolean given as 0/1 or ON/OFF.
|
||||
let parse_bool = |s: &str| match s.to_uppercase().as_str() {
|
||||
"1" | "ON" | "TRUE" => Some(true),
|
||||
|
|
@ -1597,16 +1679,6 @@ impl OpenCADStudio {
|
|||
.map_err(|_| "SETVAR: integer value required.".into()),
|
||||
None => Ok((format!("SORTENTS = {}", h.sort_entities), false)),
|
||||
},
|
||||
"XCLIPFRAME" => match &value {
|
||||
Some(v) => v
|
||||
.parse::<i16>()
|
||||
.map(|x| {
|
||||
h.xclip_frame = x;
|
||||
(format!("XCLIPFRAME = {x}"), true)
|
||||
})
|
||||
.map_err(|_| "SETVAR: integer value required.".into()),
|
||||
None => Ok((format!("XCLIPFRAME = {}", h.xclip_frame), false)),
|
||||
},
|
||||
"HALOGAP" => match &value {
|
||||
Some(v) => v
|
||||
.parse::<i16>()
|
||||
|
|
|
|||
|
|
@ -168,7 +168,9 @@ fn plot_scene_content(
|
|||
Vec<crate::scene::model::hatch_model::HatchModel>,
|
||||
crate::io::pdf_export::PlotGroupSplits,
|
||||
) {
|
||||
let (paper_wires, model_wires) = scene.plot_wire_groups(render_mode_override);
|
||||
let (mut paper_wires, mut model_wires) = scene.plot_wire_groups(render_mode_override);
|
||||
paper_wires.retain(|wire| wire.plot_visible);
|
||||
model_wires.retain(|wire| wire.plot_visible);
|
||||
let paper_hatches = scene.paper_canvas_hatches().as_ref().clone();
|
||||
let paper_wipeouts = scene.paper_canvas_wipeouts().as_ref().clone();
|
||||
if scene.current_layout == "Model" {
|
||||
|
|
@ -184,8 +186,9 @@ fn plot_scene_content(
|
|||
splits,
|
||||
);
|
||||
}
|
||||
let (model_pattern_wires, model_hatches, model_wipeouts) =
|
||||
let (mut model_pattern_wires, model_hatches, model_wipeouts) =
|
||||
scene.viewport_plot_fills();
|
||||
model_pattern_wires.retain(|wire| wire.plot_visible);
|
||||
|
||||
let (wires, hatches, wipeouts, splits) = if paper_space_last {
|
||||
let splits = crate::io::pdf_export::PlotGroupSplits {
|
||||
|
|
|
|||
|
|
@ -2141,6 +2141,8 @@ impl OpenCADStudio {
|
|||
taper_widths: Vec::new(),
|
||||
world_width: 0.0,
|
||||
depth_override: None,
|
||||
display_visible: true,
|
||||
plot_visible: true,
|
||||
fill_is_3d: false,
|
||||
fill_is_2d_solid: false,
|
||||
render_instance: None,
|
||||
|
|
|
|||
Loading…
Reference in a new issue