Apply and persist hatch origin command choices

This commit is contained in:
ramox81 committed 2026-09-11 12:52:30 +03:00
1 parent a44a13a5ad
commit 67f374c853
5 files changed
+81 -7

No files matched your search

+10
View File
@@ -4524,10 +4524,20 @@ impl OpenCADStudio {
}
HatchEditOperation::Update {
origin,
store_origin,
disassociate,
style,
annotative,
} => {
if store_origin {
if let Some((x, y)) = origin {
if !self.tabs[i].scene.document.set_hatch_origin([x, y]) {
self.discard_last_undo_entry(i);
self.command_line.push_error("HATCHEDIT: cannot store default origin.");
return Task::none();
}
}
}
if let Some(acadrust::EntityType::Hatch(hatch)) =
self.tabs[i].scene.document.get_entity_mut(handle)
{
+3 -3
View File
@@ -775,7 +775,7 @@ impl OpenCADStudio {
selected,
inherited,
plane,
);
).with_origin(self.tabs[i].scene.document.hatch_origin());
self.command_line.push_info(&new_cmd.prompt());
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
self.refresh_area_preview(i);
@@ -808,7 +808,7 @@ impl OpenCADStudio {
scale,
angle,
annotative,
).with_appearance(entity,self.tabs[i].scene.document.header.current_entity_color,self.tabs[i].scene.document.current_entity_transparency());
).with_appearance(entity,self.tabs[i].scene.document.header.current_entity_color,self.tabs[i].scene.document.current_entity_transparency()).with_origin(self.tabs[i].scene.document.hatch_origin());
self.command_line.push_info(&cmd.prompt());
self.tabs[i].active_cmd = Some(Box::new(cmd));
} else {
@@ -816,7 +816,7 @@ impl OpenCADStudio {
.push_error(crate::t!("HATCHEDIT: selected entity is not a hatch.").as_ref());
}
} else {
let cmd = HatcheditCommand::new().with_appearance(None,self.tabs[i].scene.document.header.current_entity_color,self.tabs[i].scene.document.current_entity_transparency());
let cmd = HatcheditCommand::new().with_appearance(None,self.tabs[i].scene.document.header.current_entity_color,self.tabs[i].scene.document.current_entity_transparency()).with_origin(self.tabs[i].scene.document.hatch_origin());
self.command_line.push_info(&cmd.prompt());
self.tabs[i].active_cmd = Some(Box::new(cmd));
}
+1
View File
@@ -20,6 +20,7 @@ pub enum HatchEditOperation {
},
Update {
origin: Option<(f64, f64)>,
store_origin: bool,
disassociate: bool,
style: Option<acadrust::entities::HatchStyleType>,
annotative: Option<bool>,
+16 -1
View File
@@ -196,6 +196,7 @@ pub struct HatchCommand {
pattern_override: Option<(String, HatchPattern)>,
angle_override: Option<f32>,
scale_override: Option<f32>,
default_origin: [f64; 2],
associative: bool,
separate_hatches: bool,
island_style: acadrust::entities::HatchStyleType,
@@ -244,6 +245,7 @@ impl HatchCommand {
pattern_override: None,
angle_override: None,
scale_override: None,
default_origin: [0.0, 0.0],
associative: true,
separate_hatches: false,
island_style: inherited
@@ -257,6 +259,8 @@ impl HatchCommand {
command
}
pub fn with_origin(mut self, origin: [f64; 2]) -> Self { self.default_origin = origin; self }
fn set_object_selection(&mut self, handles: Vec<Handle>) {
let mut segments = Vec::new();
for handle in &handles {
@@ -425,10 +429,21 @@ impl HatchCommand {
dashes: vec![],
}])
});
let (name, pattern) = self
let (name, mut pattern) = self
.pattern_override
.clone()
.unwrap_or_else(|| (pat_name.to_string(), default_pattern));
let angle = self.angle_override.unwrap_or(0.0);
let scale = self.scale_override.unwrap_or(1.0).max(1.0e-6);
if let (HatchPattern::Pattern(families), Some(anchor)) = (&mut pattern, local_boundary.first()) {
let (sin, cos) = (angle as f64).sin_cos();
let dx = self.default_origin[0] - anchor[0] as f64;
let dy = self.default_origin[1] - anchor[1] as f64;
for family in families {
family.x0 += ((dx * cos + dy * sin) / scale as f64) as f32;
family.y0 += ((-dx * sin + dy * cos) / scale as f64) as f32;
}
}
HatchModel {
render_instance: None,
boundary: std::sync::Arc::new(rel),
+51 -3
View File
@@ -28,6 +28,9 @@ pub struct HatcheditCommand {
step: HatcheditStep,
origin: Option<(f64, f64)>,
disassociate: bool,
store_origin: bool,
current_origin: [f64; 2],
origin_plane: cadkernel::space::Plane,
style: Option<acadrust::entities::HatchStyleType>,
annotative: Option<bool>,
annotative_current: bool,
@@ -49,6 +52,9 @@ impl HatcheditCommand {
step: HatcheditStep::PickHatch,
origin: None,
disassociate: false,
store_origin: false,
current_origin: [0.0, 0.0],
origin_plane: cadkernel::space::Plane::from_axes([0.0;3],[1.0,0.0,0.0],[0.0,1.0,0.0]),
style: None,
annotative: None,
annotative_current: false,
@@ -81,6 +87,9 @@ impl HatcheditCommand {
},
origin: None,
disassociate: false,
store_origin: false,
current_origin: [0.0, 0.0],
origin_plane: cadkernel::space::Plane::from_axes([0.0;3],[1.0,0.0,0.0],[0.0,1.0,0.0]),
style: None,
annotative: None,
annotative_current: annotative,
@@ -129,14 +138,20 @@ impl HatcheditCommand {
}
}
pub fn with_appearance(mut self,entity:Option<&acadrust::EntityType>,current_color:acadrust::types::Color,current_transparency:acadrust::types::Transparency)->Self {
if let Some(acadrust::EntityType::Hatch(hatch)) = entity { self.style_current = hatch.style; }
if let Some(acadrust::EntityType::Hatch(hatch)) = entity {
self.style_current = hatch.style;
self.origin_plane = crate::entities::curve::ocs_plane(hatch.normal, hatch.elevation);
}
self.source_appearance=entity.map(|e|{let c=e.common();(c.color,c.layer.clone(),c.transparency)});
self.current_color=current_color;self.current_transparency=current_transparency;self
}
pub fn with_origin(mut self, origin: [f64; 2]) -> Self { self.current_origin = origin; self }
fn update_operation(&self) -> HatchEditOperation {
HatchEditOperation::Update {
origin: self.origin,
store_origin: self.store_origin,
disassociate: self.disassociate,
style: self.style,
annotative: self.annotative,
@@ -181,6 +196,9 @@ impl CadCommand for HatcheditCommand {
}
return match input {
"annotative"=>if self.annotative_current {"Make hatch annotative [Yes/No] <Y>:"} else {"Make hatch annotative [Yes/No] <N>:"},
"origin"=>"[Use current origin/Set new origin] <Use current origin>:",
"origin-point"=>"Select point:",
"origin-store"=>"Store as default origin? [Yes/No] <N>:",
"pattern"=>"Enter a pattern name or [Solid]:",
"scale"=>"Specify a scale for the pattern:",
"angle"=>"Specify an angle for the pattern:",
@@ -205,7 +223,7 @@ impl CadCommand for HatcheditCommand {
let scale = format!("{scale:.4}");
let angle = format!("{angle:.1}");
t!(
"HATCHEDIT Pattern:%{name} Scale:%{scale} Angle:%{angle} [Style/Properties/COlor/LAyer/Transparency/DRaw order/ASsociate/DIsassociate/ANnotative/recreate Boundary/separate Hatches] <Properties>:",
"HATCHEDIT Pattern:%{name} Scale:%{scale} Angle:%{angle} [Style/Origin/Properties/COlor/LAyer/Transparency/DRaw order/ASsociate/DIsassociate/ANnotative/recreate Boundary/separate Hatches] <Properties>:",
name = name,
scale = scale,
angle = angle
@@ -253,6 +271,8 @@ impl CadCommand for HatcheditCommand {
if let Some(input) = self.input {
use crate::command::CmdOption;
return match input {
"origin" => vec![CmdOption::new("Use current origin", "U"), CmdOption::new("Set new origin", "S")],
"origin-store" => vec![CmdOption::new("Yes", "Y"), CmdOption::new("No", "N")],
"style" => vec![CmdOption::new("Ignore", "I"), CmdOption::new("Outer", "O"), CmdOption::new("Normal", "N")],
"draworder" => vec![CmdOption::new("Do not change", "N"), CmdOption::new("Send to back", "B"), CmdOption::new("Bring to front", "F"), CmdOption::new("Behind boundary", "H"), CmdOption::new("In front of boundary", "D")],
"annotative" | "boundary-associate" => vec![CmdOption::new("Yes", "Y"), CmdOption::new("No", "N")],
@@ -267,6 +287,7 @@ impl CadCommand for HatcheditCommand {
}
vec![
crate::command::CmdOption::new("Style", "S"),
crate::command::CmdOption::new("Origin", "O"),
crate::command::CmdOption::new("Properties", "P"),
crate::command::CmdOption::new("Color", "CO"),
crate::command::CmdOption::new("Layer", "LA"),
@@ -287,6 +308,21 @@ impl CadCommand for HatcheditCommand {
use acadrust::types::{Color,Transparency};
let appearance=|color,layer,transparency|HatchEditOperation::Appearance{color,layer,transparency};
match input {
"origin" => match keyword.as_str() {
"U" | "USE" => { self.origin = Some((self.current_origin[0], self.current_origin[1])); return self.apply_result(self.update_operation()); }
"S" | "SET" => { self.input = Some("origin-point"); }
_ => {},
},
"origin-point" => {
let values: Option<Vec<f64>> = text.split(',').map(|s| s.trim().parse().ok()).collect();
if let Some(values) = values.filter(|v| (2..=3).contains(&v.len()) && v.iter().all(|n| n.is_finite())) {
return Some(self.on_point(DVec3::new(values[0], values[1], values.get(2).copied().unwrap_or(0.0))));
}
}
"origin-store" => {
self.store_origin = match keyword.as_str() { "Y" | "YES" => true, "N" | "NO" => false, _ => return Some(CmdResult::NeedPoint) };
return self.apply_result(self.update_operation());
}
"style" => {
self.style = match keyword.as_str() {
"I" | "IGNORE" => Some(acadrust::entities::HatchStyleType::Ignore),
@@ -352,7 +388,7 @@ impl CadCommand for HatcheditCommand {
}
return Some(CmdResult::NeedPoint);
}
let next=match keyword.as_str(){"S"|"STYLE"=>Some("style"),"P"|"PROPERTIES"=>Some("pattern"),"CO"|"COLOR"=>Some("color"),"LA"|"LAYER"=>Some("layer"),
let next=match keyword.as_str(){"O"|"ORIGIN"=>Some("origin"),"S"|"STYLE"=>Some("style"),"P"|"PROPERTIES"=>Some("pattern"),"CO"|"COLOR"=>Some("color"),"LA"|"LAYER"=>Some("layer"),
"AN"|"ANNOTATIVE"=>Some("annotative"),"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);}
@@ -472,6 +508,15 @@ impl CadCommand for HatcheditCommand {
}
fn on_point(&mut self, pt: DVec3) -> CmdResult {
if self.input == Some("origin-point") {
if let Some(point) = self.origin_plane.project(pt.to_array()) {
if point.iter().all(|value| value.is_finite()) {
self.origin = Some((point[0], point[1]));
self.input = Some("origin-store");
}
}
return CmdResult::NeedPoint;
}
if self.input==Some("associate-point") {
if let Some((plane,sources))=&self.association_sources {
let point=plane.to_local(pt);
@@ -488,6 +533,9 @@ impl CadCommand for HatcheditCommand {
None if matches!(self.step,HatcheditStep::EditOptions{..})=>{
self.input=Some("pattern");CmdResult::NeedPoint
}
Some("origin")=>{self.origin=Some((self.current_origin[0],self.current_origin[1]));self.apply_result(self.update_operation()).unwrap_or(CmdResult::Cancel)},
Some("origin-point")=>CmdResult::NeedPoint,
Some("origin-store")=>self.apply_result(self.update_operation()).unwrap_or(CmdResult::Cancel),
Some("style")=>{self.style=Some(self.style_current);self.apply_result(self.update_operation()).unwrap_or(CmdResult::Cancel)},
Some("annotative")=>{self.annotative=Some(self.annotative_current);self.apply_result(self.update_operation()).unwrap_or(CmdResult::Cancel)},
Some("pattern")=>{