Complete wipeout workflow and editing

This commit is contained in:
ramox81 2026-08-20 17:56:11 +03:00
commit b7819481f0
14 changed files with 513 additions and 339 deletions

View file

@ -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.",
"WIPEOUT Polyline: select a straight, closed, planar 2D polyline with at least 3 non-intersecting vertices.",
);
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);

View file

@ -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));

View file

@ -515,6 +515,10 @@ inventory::submit!(crate::command::CommandRegistration {
"TEXTQLTY",
"SORTENTS",
"XCLIPFRAME",
"WIPEOUTFRAME",
"FRAMES0",
"FRAMES1",
"FRAMES2",
"HALOGAP",
"TRACEWID",
"SKETCHINC",

View file

@ -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 WIPEOUTFRAME 0", i),
"FRAMES1" => return self.dispatch_styleprops("SETVAR WIPEOUTFRAME 1", i),
"FRAMES2" => return self.dispatch_styleprops("SETVAR WIPEOUTFRAME 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" => {
@ -920,6 +923,7 @@ impl OpenCADStudio {
| "TEXTQLTY"
| "SORTENTS"
| "XCLIPFRAME"
| "WIPEOUTFRAME"
| "HALOGAP"
| "TRACEWID"
| "SKETCHINC"
@ -948,6 +952,48 @@ impl OpenCADStudio {
"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)",
);
} else {
if name == "WIPEOUTFRAME" {
match &value {
Some(value) => match value.parse::<i16>() {
Ok(mode @ 0..=2) => {
self.push_undo_snapshot(i, "WIPEOUTFRAME");
crate::modules::draw::draw::wipeout::set_wipeout_frame_mode(
&mut self.tabs[i].scene.document,
mode,
);
let changes: Vec<_> = self.tabs[i]
.scene
.document
.entities()
.filter_map(|entity| {
matches!(entity, acadrust::EntityType::Wipeout(_))
.then_some((
entity.common().handle,
crate::scene::ChangeKind::Modified,
))
})
.collect();
self.tabs[i].scene.bump_entities(&changes);
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("WIPEOUTFRAME = {mode}"));
}
_ => self.command_line.push_error(
"SETVAR: WIPEOUTFRAME requires 0, 1, or 2.",
),
},
None => {
let mode = crate::modules::draw::draw::wipeout::wipeout_frame_mode(
&self.tabs[i].scene.document,
);
self.command_line.push_output(crate::tf!(
"Enter new value for WIPEOUTFRAME <{mode}>:"
).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),

View file

@ -168,7 +168,21 @@ 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);
let hide_mask_frames =
crate::modules::draw::draw::wipeout::wipeout_frame_mode(&scene.document) == 2;
if hide_mask_frames {
let mask_handles: std::collections::HashSet<String> = scene
.document
.entities()
.filter_map(|entity| {
matches!(entity, acadrust::EntityType::Wipeout(_))
.then_some(entity.common().handle.value().to_string())
})
.collect();
paper_wires.retain(|wire| !mask_handles.contains(&wire.name));
model_wires.retain(|wire| !mask_handles.contains(&wire.name));
}
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 +198,19 @@ 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();
if hide_mask_frames {
let mask_handles: std::collections::HashSet<String> = scene
.document
.entities()
.filter_map(|entity| {
matches!(entity, acadrust::EntityType::Wipeout(_))
.then_some(entity.common().handle.value().to_string())
})
.collect();
model_pattern_wires.retain(|wire| !mask_handles.contains(&wire.name));
}
let (wires, hatches, wipeouts, splits) = if paper_space_last {
let splits = crate::io::pdf_export::PlotGroupSplits {