forked from 1b-agent/opencadstudio-upstream
Add hatch editing option stages and appearance association workflows
This commit is contained in:
1 parent
7d0c059b30
commit
c947e1ce50
4 files changed
+220
-11
No files matched your search
@@ -4456,6 +4456,31 @@ impl OpenCADStudio {
|
|||||||
.push_error(crate::t!("HATCHEDIT: hatch entity not found.").as_ref());
|
.push_error(crate::t!("HATCHEDIT: hatch entity not found.").as_ref());
|
||||||
} else {
|
} else {
|
||||||
use crate::command::HatchEditOperation;
|
use crate::command::HatchEditOperation;
|
||||||
|
if matches!(&operation,HatchEditOperation::BeginAssociate) {
|
||||||
|
let associative=matches!(self.tabs[i].scene.document.get_entity(handle),Some(acadrust::EntityType::Hatch(h)) if h.is_associative);
|
||||||
|
if associative {
|
||||||
|
self.command_line.push_info("HATCHEDIT: hatch is already associative.");
|
||||||
|
self.tabs[i].active_cmd=None;
|
||||||
|
}else{
|
||||||
|
let command=crate::modules::draw::draw::hatchedit::HatcheditCommand::for_association(handle,name,scale,angle);
|
||||||
|
self.tabs[i].scene.deselect_all();
|
||||||
|
self.command_line.push_info(&command.prompt());
|
||||||
|
self.tabs[i].active_cmd=Some(Box::new(command));
|
||||||
|
}
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
|
if let HatchEditOperation::DrawOrderBoundary{above}=&operation {
|
||||||
|
let references:Vec<_>=match self.tabs[i].scene.document.get_entity(handle) {
|
||||||
|
Some(acadrust::EntityType::Hatch(h))=>h.paths.iter().flat_map(|p|p.boundary_handles.iter())
|
||||||
|
.filter(|h|self.tabs[i].scene.document.get_entity(**h).is_some()).map(|h|format!("{:X}",h.value())).collect(),
|
||||||
|
_=>Vec::new(),
|
||||||
|
};
|
||||||
|
self.tabs[i].active_cmd=None;
|
||||||
|
if references.is_empty(){self.command_line.push_info("HATCHEDIT: no associated boundary objects.");return Task::none();}
|
||||||
|
self.tabs[i].scene.deselect_all();self.tabs[i].scene.select_entity(handle,false);
|
||||||
|
let command=format!("DRAWORDER {} {}",if *above{"ABOVE"}else{"UNDER"},references.join(" "));
|
||||||
|
return self.dispatch_view(&command,i).unwrap_or_else(Task::none);
|
||||||
|
}
|
||||||
if matches!(
|
if matches!(
|
||||||
&operation,
|
&operation,
|
||||||
HatchEditOperation::DrawOrderFront | HatchEditOperation::DrawOrderBack
|
HatchEditOperation::DrawOrderFront | HatchEditOperation::DrawOrderBack
|
||||||
@@ -4472,6 +4497,22 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
self.push_undo_snapshot(i, "HATCHEDIT");
|
self.push_undo_snapshot(i, "HATCHEDIT");
|
||||||
match operation {
|
match operation {
|
||||||
|
HatchEditOperation::Appearance { color, layer, transparency } => {
|
||||||
|
let layer=layer.map(|name|if name=="."{self.tabs[i].active_layer.clone()}else{name});
|
||||||
|
if layer.as_ref().is_some_and(|name|self.tabs[i].scene.document.layers.get(name).is_none()) {
|
||||||
|
self.discard_last_undo_entry(i);
|
||||||
|
self.command_line.push_error("HATCHEDIT: layer not found.");
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
|
if let Some(entity)=self.tabs[i].scene.document.get_entity_mut(handle) {
|
||||||
|
let common=entity.common_mut();
|
||||||
|
if let Some(value)=color {common.color=value;common.color_name=None;common.color_book_handle=None;}
|
||||||
|
if let Some(value)=layer {common.layer=value;}
|
||||||
|
if let Some(value)=transparency {common.transparency=value;}
|
||||||
|
}
|
||||||
|
self.tabs[i].scene.bump_entities(&[(handle,crate::scene::ChangeKind::Modified)]);
|
||||||
|
self.refresh_properties();
|
||||||
|
}
|
||||||
HatchEditOperation::Update {
|
HatchEditOperation::Update {
|
||||||
origin,
|
origin,
|
||||||
disassociate,
|
disassociate,
|
||||||
@@ -4591,7 +4632,25 @@ impl OpenCADStudio {
|
|||||||
.scene
|
.scene
|
||||||
.edit_hatch_boundary_handles(handle, &handles, false);
|
.edit_hatch_boundary_handles(handle, &handles, false);
|
||||||
}
|
}
|
||||||
HatchEditOperation::RecreateBoundary => {
|
HatchEditOperation::AssociateBoundaries(handles) => {
|
||||||
|
let plane=match self.tabs[i].scene.document.get_entity(handle) {
|
||||||
|
Some(acadrust::EntityType::Hatch(h))=>{
|
||||||
|
let storage=crate::entities::curve::ocs_plane(h.normal,h.elevation);
|
||||||
|
crate::command::WorkingPlane::new(glam::DVec3::from_array(storage.origin),glam::DVec3::from_array(storage.x_axis),glam::DVec3::from_array(storage.y_axis))
|
||||||
|
},
|
||||||
|
_=>self.tabs[i].ucs_xform().working_plane(),
|
||||||
|
};
|
||||||
|
let mut sources=self.tabs[i].scene.boundary_sources_on_plane(plane,1e-6);
|
||||||
|
sources.retain(|h,_|handles.contains(h)&&*h!=handle);
|
||||||
|
if crate::scene::boundary_faces(&sources,1e-6).is_empty() {
|
||||||
|
self.discard_last_undo_entry(i);
|
||||||
|
self.command_line.push_error("HATCHEDIT: selected objects do not form a closed boundary.");
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
|
let valid_handles:Vec<_>=sources.keys().copied().collect();
|
||||||
|
self.tabs[i].scene.edit_hatch_boundary_handles(handle,&valid_handles,true);
|
||||||
|
}
|
||||||
|
HatchEditOperation::RecreateBoundary { associate } => {
|
||||||
let source = self.tabs[i].scene.document.get_entity(handle).cloned();
|
let source = self.tabs[i].scene.document.get_entity(handle).cloned();
|
||||||
if let Some(acadrust::EntityType::Hatch(source)) = source {
|
if let Some(acadrust::EntityType::Hatch(source)) = source {
|
||||||
let storage = crate::entities::curve::ocs_plane(
|
let storage = crate::entities::curve::ocs_plane(
|
||||||
@@ -4611,7 +4670,7 @@ impl OpenCADStudio {
|
|||||||
handles.push(boundary);
|
handles.push(boundary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(acadrust::EntityType::Hatch(hatch)) =
|
if associate { if let Some(acadrust::EntityType::Hatch(hatch)) =
|
||||||
self.tabs[i].scene.document.get_entity_mut(handle)
|
self.tabs[i].scene.document.get_entity_mut(handle)
|
||||||
{
|
{
|
||||||
for (path, boundary) in
|
for (path, boundary) in
|
||||||
@@ -4621,7 +4680,7 @@ impl OpenCADStudio {
|
|||||||
path.flags.set_external(true);
|
path.flags.set_external(true);
|
||||||
}
|
}
|
||||||
hatch.is_associative = !handles.is_empty();
|
hatch.is_associative = !handles.is_empty();
|
||||||
}
|
} }
|
||||||
self.tabs[i].scene.bump_entities(&[(
|
self.tabs[i].scene.bump_entities(&[(
|
||||||
handle,
|
handle,
|
||||||
crate::scene::ChangeKind::Modified,
|
crate::scene::ChangeKind::Modified,
|
||||||
@@ -4650,7 +4709,9 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
HatchEditOperation::DrawOrderFront
|
HatchEditOperation::DrawOrderFront
|
||||||
| HatchEditOperation::DrawOrderBack => unreachable!(),
|
| HatchEditOperation::DrawOrderBack
|
||||||
|
| HatchEditOperation::DrawOrderBoundary {..}
|
||||||
|
| HatchEditOperation::BeginAssociate => unreachable!(),
|
||||||
}
|
}
|
||||||
self.tabs[i].dirty = true;
|
self.tabs[i].dirty = true;
|
||||||
self.command_line
|
self.command_line
|
||||||
|
|||||||
@@ -808,7 +808,7 @@ impl OpenCADStudio {
|
|||||||
scale,
|
scale,
|
||||||
angle,
|
angle,
|
||||||
annotative,
|
annotative,
|
||||||
);
|
).with_appearance(entity,self.tabs[i].scene.document.header.current_entity_color);
|
||||||
self.command_line.push_info(&cmd.prompt());
|
self.command_line.push_info(&cmd.prompt());
|
||||||
self.tabs[i].active_cmd = Some(Box::new(cmd));
|
self.tabs[i].active_cmd = Some(Box::new(cmd));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+9
-1
@@ -13,13 +13,21 @@ use glam::DVec3;
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum HatchEditOperation {
|
pub enum HatchEditOperation {
|
||||||
|
Appearance {
|
||||||
|
color: Option<acadrust::types::Color>,
|
||||||
|
layer: Option<String>,
|
||||||
|
transparency: Option<acadrust::types::Transparency>,
|
||||||
|
},
|
||||||
Update {
|
Update {
|
||||||
origin: Option<(f64, f64)>,
|
origin: Option<(f64, f64)>,
|
||||||
disassociate: bool,
|
disassociate: bool,
|
||||||
style: Option<acadrust::entities::HatchStyleType>,
|
style: Option<acadrust::entities::HatchStyleType>,
|
||||||
annotative: Option<bool>,
|
annotative: Option<bool>,
|
||||||
},
|
},
|
||||||
RecreateBoundary,
|
RecreateBoundary { associate: bool },
|
||||||
|
BeginAssociate,
|
||||||
|
AssociateBoundaries(Vec<Handle>),
|
||||||
|
DrawOrderBoundary { above: bool },
|
||||||
Separate,
|
Separate,
|
||||||
AddBoundaries(Vec<Handle>),
|
AddBoundaries(Vec<Handle>),
|
||||||
RemoveBoundaries(Vec<Handle>),
|
RemoveBoundaries(Vec<Handle>),
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ pub struct HatcheditCommand {
|
|||||||
style: Option<acadrust::entities::HatchStyleType>,
|
style: Option<acadrust::entities::HatchStyleType>,
|
||||||
annotative: Option<bool>,
|
annotative: Option<bool>,
|
||||||
annotative_current: bool,
|
annotative_current: bool,
|
||||||
|
input: Option<&'static str>,
|
||||||
|
boundary_selection: Vec<Handle>,
|
||||||
|
source_appearance: Option<(acadrust::types::Color,String,acadrust::types::Transparency)>,
|
||||||
|
current_color: acadrust::types::Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HatcheditCommand {
|
impl HatcheditCommand {
|
||||||
@@ -42,6 +46,10 @@ impl HatcheditCommand {
|
|||||||
style: None,
|
style: None,
|
||||||
annotative: None,
|
annotative: None,
|
||||||
annotative_current: false,
|
annotative_current: false,
|
||||||
|
input: None,
|
||||||
|
boundary_selection: Vec::new(),
|
||||||
|
source_appearance: None,
|
||||||
|
current_color: acadrust::types::Color::ByLayer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,6 +72,10 @@ impl HatcheditCommand {
|
|||||||
style: None,
|
style: None,
|
||||||
annotative: None,
|
annotative: None,
|
||||||
annotative_current: annotative,
|
annotative_current: annotative,
|
||||||
|
input: None,
|
||||||
|
boundary_selection: Vec::new(),
|
||||||
|
source_appearance: None,
|
||||||
|
current_color: acadrust::types::Color::ByLayer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +98,15 @@ impl HatcheditCommand {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn for_association(handle:Handle,name:String,scale:f32,angle:f32)->Self {
|
||||||
|
let mut command=Self::with_handle(handle,name,scale,angle,false);
|
||||||
|
command.input=Some("associate-select");command
|
||||||
|
}
|
||||||
|
pub fn with_appearance(mut self,entity:Option<&acadrust::EntityType>,current_color:acadrust::types::Color)->Self {
|
||||||
|
self.source_appearance=entity.map(|e|{let c=e.common();(c.color,c.layer.clone(),c.transparency)});
|
||||||
|
self.current_color=current_color;self
|
||||||
|
}
|
||||||
|
|
||||||
fn update_operation(&self) -> HatchEditOperation {
|
fn update_operation(&self) -> HatchEditOperation {
|
||||||
HatchEditOperation::Update {
|
HatchEditOperation::Update {
|
||||||
origin: self.origin,
|
origin: self.origin,
|
||||||
@@ -102,6 +123,42 @@ impl CadCommand for HatcheditCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prompt(&self) -> String {
|
fn prompt(&self) -> String {
|
||||||
|
if let Some(input)=self.input {
|
||||||
|
if let Some((color,layer,transparency))=&self.source_appearance {
|
||||||
|
match input {
|
||||||
|
"color"=>return format!("New color [Truecolor/. (for use current)] <{color:?}>:"),
|
||||||
|
"layer"=>return format!("Specify layer or [. (for use current)] <{layer}>:"),
|
||||||
|
"transparency"=>return format!("Specify transparency (0-90) or ByLayer/ByBlock <{}>:",match transparency {
|
||||||
|
acadrust::types::Transparency::ByLayer=>"ByLayer".into(),
|
||||||
|
acadrust::types::Transparency::ByBlock=>"ByBlock".into(),
|
||||||
|
value=>format!("{:.0}",value.as_percent()*100.0),
|
||||||
|
}),
|
||||||
|
_=>{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let HatcheditStep::EditOptions{name,scale,angle,..}=&self.step {
|
||||||
|
match input {
|
||||||
|
"pattern"=>return format!("Enter a pattern name or [Solid] <{name}>:"),
|
||||||
|
"scale"=>return format!("Specify a scale for the pattern <{scale:.4}>:"),
|
||||||
|
"angle"=>return format!("Specify an angle for the pattern <{angle:.4}>:"),
|
||||||
|
_=>{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match input {
|
||||||
|
"pattern"=>"Enter a pattern name or [Solid]:",
|
||||||
|
"scale"=>"Specify a scale for the pattern:",
|
||||||
|
"angle"=>"Specify an angle for the pattern:",
|
||||||
|
"color"=>"New color [Truecolor] <ByLayer>:",
|
||||||
|
"truecolor"=>"Specify RGB color (red,green,blue):",
|
||||||
|
"layer"=>"Specify layer or [. (for use current)]:",
|
||||||
|
"transparency"=>"Specify transparency value (0-90) or ByLayer/ByBlock:",
|
||||||
|
"draworder"=>"Enter draw order [do Not change/send to Back/bring to Front/send beHind boundary/bring in front of bounDary] <do Not change>:",
|
||||||
|
"boundary-type"=>"Enter type of boundary object [Polyline] <Polyline>:",
|
||||||
|
"boundary-associate"=>"Reassociate hatch with new boundary? [Yes/No] <No>:",
|
||||||
|
"associate-select"=>"Select boundary objects:",
|
||||||
|
_=>"Specify value:",
|
||||||
|
}.into();
|
||||||
|
}
|
||||||
match &self.step {
|
match &self.step {
|
||||||
HatcheditStep::PickHatch => t!("HATCHEDIT Select hatch:").into_owned(),
|
HatcheditStep::PickHatch => t!("HATCHEDIT Select hatch:").into_owned(),
|
||||||
HatcheditStep::EditOptions {
|
HatcheditStep::EditOptions {
|
||||||
@@ -110,7 +167,7 @@ impl CadCommand for HatcheditCommand {
|
|||||||
let scale = format!("{scale:.4}");
|
let scale = format!("{scale:.4}");
|
||||||
let angle = format!("{angle:.1}");
|
let angle = format!("{angle:.1}");
|
||||||
t!(
|
t!(
|
||||||
"HATCHEDIT Pattern:%{name} Scale:%{scale} Angle:%{angle} [P pattern / S scale / A angle / O x,y / D disassociate / Y style / N annotative / R recreate / E separate / + handles / - handles | Enter]:",
|
"HATCHEDIT Pattern:%{name} Scale:%{scale} Angle:%{angle} [Properties/COlor/LAyer/Transparency/DRaw order/Disassociate/Annotative/Recreate/Separate] <Properties>:",
|
||||||
name = name,
|
name = name,
|
||||||
scale = scale,
|
scale = scale,
|
||||||
angle = angle
|
angle = angle
|
||||||
@@ -123,6 +180,10 @@ impl CadCommand for HatcheditCommand {
|
|||||||
fn needs_entity_pick(&self) -> bool {
|
fn needs_entity_pick(&self) -> bool {
|
||||||
matches!(self.step, HatcheditStep::PickHatch)
|
matches!(self.step, HatcheditStep::PickHatch)
|
||||||
}
|
}
|
||||||
|
fn is_selection_gathering(&self)->bool {self.input==Some("associate-select")}
|
||||||
|
fn on_selection_complete(&mut self,handles:Vec<Handle>)->CmdResult {
|
||||||
|
self.boundary_selection=handles;CmdResult::NeedPoint
|
||||||
|
}
|
||||||
|
|
||||||
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
|
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
|
||||||
if handle.is_null() {
|
if handle.is_null() {
|
||||||
@@ -140,14 +201,21 @@ impl CadCommand for HatcheditCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn wants_text_input(&self) -> bool {
|
fn wants_text_input(&self) -> bool {
|
||||||
matches!(self.step, HatcheditStep::EditOptions { .. })
|
matches!(self.step, HatcheditStep::EditOptions { .. })&&!self.is_selection_gathering()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn options(&self) -> Vec<crate::command::CmdOption> {
|
fn options(&self) -> Vec<crate::command::CmdOption> {
|
||||||
|
if self.input.is_some() {return Vec::new();}
|
||||||
if !matches!(self.step, HatcheditStep::EditOptions { .. }) {
|
if !matches!(self.step, HatcheditStep::EditOptions { .. }) {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
vec![
|
vec![
|
||||||
|
crate::command::CmdOption::new("Properties", "P"),
|
||||||
|
crate::command::CmdOption::new("Color", "CO"),
|
||||||
|
crate::command::CmdOption::new("Layer", "LA"),
|
||||||
|
crate::command::CmdOption::new("Transparency", "T"),
|
||||||
|
crate::command::CmdOption::new("Draw order", "DR"),
|
||||||
|
crate::command::CmdOption::new("Associate", "AS"),
|
||||||
crate::command::CmdOption::new("Disassociate", "D"),
|
crate::command::CmdOption::new("Disassociate", "D"),
|
||||||
crate::command::CmdOption::new("Annotative", "N"),
|
crate::command::CmdOption::new("Annotative", "N"),
|
||||||
crate::command::CmdOption::new("Recreate boundary", "R"),
|
crate::command::CmdOption::new("Recreate boundary", "R"),
|
||||||
@@ -159,6 +227,62 @@ impl CadCommand for HatcheditCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
|
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
|
||||||
|
let keyword=text.trim().to_ascii_uppercase();
|
||||||
|
if let Some(input)=self.input {
|
||||||
|
use acadrust::types::{Color,Transparency};
|
||||||
|
let appearance=|color,layer,transparency|HatchEditOperation::Appearance{color,layer,transparency};
|
||||||
|
match input {
|
||||||
|
"color"=>{
|
||||||
|
if matches!(keyword.as_str(),"T"|"TRUECOLOR") {self.input=Some("truecolor");return Some(CmdResult::NeedPoint);}
|
||||||
|
let color=match keyword.as_str(){"."=>Some(self.current_color),"BYLAYER"=>Some(Color::ByLayer),"BYBLOCK"=>Some(Color::ByBlock),
|
||||||
|
"RED"=>Some(Color::Index(1)),"YELLOW"=>Some(Color::Index(2)),"GREEN"=>Some(Color::Index(3)),
|
||||||
|
"CYAN"=>Some(Color::Index(4)),"BLUE"=>Some(Color::Index(5)),"MAGENTA"=>Some(Color::Index(6)),"WHITE"=>Some(Color::Index(7)),
|
||||||
|
n=>n.parse::<i16>().ok().filter(|v|(0..=256).contains(v)).map(Color::from_index)};
|
||||||
|
return Some(color.and_then(|v|self.apply_result(appearance(Some(v),None,None))).unwrap_or(CmdResult::NeedPoint));
|
||||||
|
}
|
||||||
|
"truecolor"=>{
|
||||||
|
let rgb:Option<Vec<u8>>=keyword.split(',').map(|s|s.trim().parse().ok()).collect();
|
||||||
|
if let Some(rgb)=rgb.filter(|rgb|rgb.len()==3) {return self.apply_result(appearance(Some(Color::from_rgb(rgb[0],rgb[1],rgb[2])),None,None));}
|
||||||
|
}
|
||||||
|
"layer"=>if !text.trim().is_empty(){return self.apply_result(appearance(None,Some(text.trim().to_owned()),None));},
|
||||||
|
"transparency"=>{
|
||||||
|
let value=match keyword.as_str(){"BYLAYER"=>Some(Transparency::BY_LAYER),"BYBLOCK"=>Some(Transparency::BY_BLOCK),
|
||||||
|
n=>n.parse::<u8>().ok().filter(|v|*v<=90).map(|v|Transparency::from_percent(v as f64 / 100.0))};
|
||||||
|
if let Some(value)=value{return self.apply_result(appearance(None,None,Some(value)));}
|
||||||
|
}
|
||||||
|
"draworder"=>return match keyword.as_str(){"F"|"FRONT"=>self.apply_result(HatchEditOperation::DrawOrderFront),
|
||||||
|
"H"|"BEHIND"=>self.apply_result(HatchEditOperation::DrawOrderBoundary{above:false}),
|
||||||
|
"D"=>self.apply_result(HatchEditOperation::DrawOrderBoundary{above:true}),
|
||||||
|
"B"|"BACK"=>self.apply_result(HatchEditOperation::DrawOrderBack),"N"|"NOT"=>Some(CmdResult::Cancel),_=>Some(CmdResult::NeedPoint)},
|
||||||
|
"boundary-type"=>if matches!(keyword.as_str(),"P"|"POLYLINE"){self.input=Some("boundary-associate");},
|
||||||
|
"boundary-associate"=>return match keyword.as_str(){
|
||||||
|
"Y"|"YES"=>self.apply_result(HatchEditOperation::RecreateBoundary{associate:true}),
|
||||||
|
"N"|"NO"=>self.apply_result(HatchEditOperation::RecreateBoundary{associate:false}),
|
||||||
|
_=>Some(CmdResult::NeedPoint),
|
||||||
|
},
|
||||||
|
"pattern"=>{
|
||||||
|
if crate::scene::model::hatch_patterns::find(&keyword).is_some() {
|
||||||
|
if let HatcheditStep::EditOptions{name,..}=&mut self.step{*name=keyword.clone();}
|
||||||
|
if keyword=="SOLID" {return self.apply_result(self.update_operation());}
|
||||||
|
self.input=Some("scale");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"scale"|"angle"=>if let Ok(value)=keyword.parse::<f32>() {if value.is_finite()&&(input=="angle"||value>0.0){
|
||||||
|
if let HatcheditStep::EditOptions{scale,angle,..}=&mut self.step{if input=="scale"{*scale=value;}else{*angle=value;}}
|
||||||
|
if input=="scale"{self.input=Some("angle");}else{return self.apply_result(self.update_operation());}
|
||||||
|
}},
|
||||||
|
_=>{},
|
||||||
|
}
|
||||||
|
return Some(CmdResult::NeedPoint);
|
||||||
|
}
|
||||||
|
let next=match keyword.as_str(){"P"|"PROPERTIES"=>Some("pattern"),"CO"|"COLOR"=>Some("color"),"LA"|"LAYER"=>Some("layer"),
|
||||||
|
"T"|"TRANSPARENCY"=>Some("transparency"),"DR"|"DRAW"|"DRAW ORDER"=>Some("draworder"),
|
||||||
|
"B"|"BOUNDARY"|"R"|"RECREATE"=>Some("boundary-type"),_=>None};
|
||||||
|
if let Some(input)=next {self.input=Some(input);return Some(CmdResult::NeedPoint);}
|
||||||
|
if matches!(keyword.as_str(),"AS"|"ASSOCIATE"){return self.apply_result(HatchEditOperation::BeginAssociate);}
|
||||||
|
if matches!(keyword.as_str(),"DI"|"DISASSOCIATE"){
|
||||||
|
self.disassociate=true;return self.apply_result(self.update_operation());
|
||||||
|
}
|
||||||
let (_handle, name, scale, angle) = match &mut self.step {
|
let (_handle, name, scale, angle) = match &mut self.step {
|
||||||
HatcheditStep::EditOptions {
|
HatcheditStep::EditOptions {
|
||||||
handle,
|
handle,
|
||||||
@@ -236,7 +360,7 @@ impl CadCommand for HatcheditCommand {
|
|||||||
return Some(CmdResult::NeedPoint);
|
return Some(CmdResult::NeedPoint);
|
||||||
}
|
}
|
||||||
if text == "R" || text == "RECREATE" {
|
if text == "R" || text == "RECREATE" {
|
||||||
return self.apply_result(HatchEditOperation::RecreateBoundary);
|
self.input=Some("boundary-type");return Some(CmdResult::NeedPoint);
|
||||||
}
|
}
|
||||||
if text == "E" || text == "SEPARATE" {
|
if text == "E" || text == "SEPARATE" {
|
||||||
return self.apply_result(HatchEditOperation::Separate);
|
return self.apply_result(HatchEditOperation::Separate);
|
||||||
@@ -273,8 +397,24 @@ impl CadCommand for HatcheditCommand {
|
|||||||
CmdResult::NeedPoint
|
CmdResult::NeedPoint
|
||||||
}
|
}
|
||||||
fn on_enter(&mut self) -> CmdResult {
|
fn on_enter(&mut self) -> CmdResult {
|
||||||
// Enter without text → apply current settings
|
match self.input {
|
||||||
self.apply_result(self.update_operation()).unwrap_or(CmdResult::Cancel)
|
None if matches!(self.step,HatcheditStep::EditOptions{..})=>{
|
||||||
|
self.input=Some("pattern");CmdResult::NeedPoint
|
||||||
|
}
|
||||||
|
Some("pattern")=>{
|
||||||
|
if matches!(&self.step,HatcheditStep::EditOptions{name,..} if name.eq_ignore_ascii_case("SOLID")) {
|
||||||
|
self.apply_result(self.update_operation()).unwrap_or(CmdResult::Cancel)
|
||||||
|
}else{self.input=Some("scale");CmdResult::NeedPoint}
|
||||||
|
}
|
||||||
|
Some("scale")=>{self.input=Some("angle");CmdResult::NeedPoint}
|
||||||
|
Some("angle")=>self.apply_result(self.update_operation()).unwrap_or(CmdResult::Cancel),
|
||||||
|
Some("boundary-type")=>{self.input=Some("boundary-associate");CmdResult::NeedPoint},
|
||||||
|
Some("boundary-associate")=>self.apply_result(HatchEditOperation::RecreateBoundary{associate:false}).unwrap_or(CmdResult::Cancel),
|
||||||
|
Some("associate-select")=>if self.boundary_selection.is_empty(){CmdResult::Cancel}else{
|
||||||
|
self.apply_result(HatchEditOperation::AssociateBoundaries(self.boundary_selection.clone())).unwrap_or(CmdResult::Cancel)
|
||||||
|
},
|
||||||
|
_=>CmdResult::Cancel,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn on_escape(&mut self) -> CmdResult {
|
fn on_escape(&mut self) -> CmdResult {
|
||||||
CmdResult::Cancel
|
CmdResult::Cancel
|
||||||
|
|||||||
Reference in new issue
Block a user