Complete SUBTRACT behavior

This commit is contained in:
ramox81 committed 2026-09-07 13:58:31 +03:00
1 parent 5857ffa2bd
commit 04a9a1b0a0
10 files changed
+562 -69

No files matched your search

+80 -9
View File
@@ -25,16 +25,20 @@ impl BoolOp {
enum SubtractStep {
Bases,
Cutters,
ConvertMeshes,
}
pub struct SubtractCommand {
step: SubtractStep,
bases: Vec<Handle>,
cutters: Vec<Handle>,
selected: Vec<Handle>,
bases_have_mesh: bool,
selected_has_mesh: bool,
}
impl SubtractCommand {
pub fn new(bases: Vec<Handle>) -> Self {
pub fn new(bases: Vec<Handle>, bases_have_mesh: bool) -> Self {
let step = if bases.is_empty() {
SubtractStep::Bases
} else {
@@ -43,7 +47,18 @@ impl SubtractCommand {
Self {
step,
bases,
cutters: Vec::new(),
selected: Vec::new(),
bases_have_mesh,
selected_has_mesh: false,
}
}
fn finish(&mut self, convert_meshes: bool) -> CmdResult {
CmdResult::SolidSubtract {
bases: std::mem::take(&mut self.bases),
cutters: std::mem::take(&mut self.cutters),
convert_meshes,
}
}
}
@@ -55,11 +70,26 @@ impl CadCommand for SubtractCommand {
fn prompt(&self) -> String {
match self.step {
SubtractStep::Bases => crate::t!("SUBTRACT Select base solids, then press Enter:")
SubtractStep::Bases => crate::t!("SUBTRACT Select base Solids, Regions, Surfaces, or Meshes, then press Enter:")
.into_owned(),
SubtractStep::Cutters => {
crate::t!("SUBTRACT Select solids to subtract, then press Enter:").into_owned()
crate::t!("SUBTRACT Select Solids, Regions, Surfaces, or Meshes to subtract, then press Enter:").into_owned()
}
SubtractStep::ConvertMeshes => crate::t!(
"SUBTRACT Convert selected closed Mesh objects to solids? [Yes/No] <Yes>:"
)
.into_owned(),
}
}
fn options(&self) -> Vec<crate::command::CmdOption> {
if matches!(self.step, SubtractStep::ConvertMeshes) {
vec![
crate::command::CmdOption::new(crate::t!("Yes").as_ref(), "Y"),
crate::command::CmdOption::new(crate::t!("No").as_ref(), "N"),
]
} else {
Vec::new()
}
}
@@ -68,31 +98,72 @@ impl CadCommand for SubtractCommand {
}
fn on_enter(&mut self) -> CmdResult {
if matches!(self.step, SubtractStep::ConvertMeshes) {
return self.finish(true);
}
if self.selected.is_empty() {
return CmdResult::NeedPoint;
}
match self.step {
SubtractStep::Bases => {
self.bases = std::mem::take(&mut self.selected);
self.bases_have_mesh = self.selected_has_mesh;
self.selected_has_mesh = false;
self.step = SubtractStep::Cutters;
CmdResult::DeselectAndContinue
}
SubtractStep::Cutters => CmdResult::SolidSubtract {
bases: std::mem::take(&mut self.bases),
cutters: std::mem::take(&mut self.selected),
},
SubtractStep::Cutters => {
self.cutters = std::mem::take(&mut self.selected);
if self.bases_have_mesh || self.selected_has_mesh {
self.step = SubtractStep::ConvertMeshes;
CmdResult::NeedPoint
} else {
self.finish(false)
}
}
SubtractStep::ConvertMeshes => unreachable!(),
}
}
fn wants_text_input(&self) -> bool {
matches!(self.step, SubtractStep::ConvertMeshes)
}
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
if !matches!(self.step, SubtractStep::ConvertMeshes) {
return None;
}
Some(match text.trim().to_ascii_lowercase().as_str() {
"" | "y" | "yes" => self.finish(true),
"n" | "no" => self.finish(false),
_ => CmdResult::NeedPoint,
})
}
fn is_selection_gathering(&self) -> bool {
true
!matches!(self.step, SubtractStep::ConvertMeshes)
}
fn inject_selection_entities(&mut self, entities: Vec<SelectionEntity>) {
self.selected_has_mesh = entities.iter().any(|entity| {
matches!(
entity.entity,
EntityType::Mesh(_) | EntityType::PolygonMesh(_) | EntityType::PolyfaceMesh(_)
)
});
self.selected = entities
.into_iter()
.filter_map(|entity| {
matches!(entity.entity, EntityType::Solid3D(_)).then_some(entity.handle)
matches!(
entity.entity,
EntityType::Solid3D(_)
| EntityType::Region(_)
| EntityType::Surface(_)
| EntityType::Mesh(_)
| EntityType::PolygonMesh(_)
| EntityType::PolyfaceMesh(_)
)
.then_some(entity.handle)
})
.collect();
}