cargo fmt

This commit is contained in:
Hakan committed 2026-05-12 10:36:15 +03:00
1 parent 468cbde5e1
commit ca07268c7c
204 files changed
+13997 -5525

No files matched your search

+52 -14
View File
@@ -16,9 +16,18 @@ use crate::scene::wire_model::WireModel;
enum Step {
Tag,
Prompt { tag: String },
Default { tag: String, prompt: String },
Insertion { tag: String, prompt: String, default: String },
Prompt {
tag: String,
},
Default {
tag: String,
prompt: String,
},
Insertion {
tag: String,
prompt: String,
default: String,
},
}
pub struct AttdefCommand {
@@ -29,18 +38,25 @@ pub struct AttdefCommand {
impl AttdefCommand {
pub fn new() -> Self {
Self { step: Step::Tag, height: 0.2 }
Self {
step: Step::Tag,
height: 0.2,
}
}
}
impl CadCommand for AttdefCommand {
fn name(&self) -> &'static str { "ATTDEF" }
fn name(&self) -> &'static str {
"ATTDEF"
}
fn prompt(&self) -> String {
match &self.step {
Step::Tag => "ATTDEF Enter attribute tag (no spaces):".into(),
Step::Tag => "ATTDEF Enter attribute tag (no spaces):".into(),
Step::Prompt { tag } => format!("ATTDEF Enter prompt for '{tag}' (Enter=use tag):"),
Step::Default { tag, .. } => format!("ATTDEF Enter default value for '{tag}' (Enter=blank):"),
Step::Default { tag, .. } => {
format!("ATTDEF Enter default value for '{tag}' (Enter=blank):")
}
Step::Insertion { tag, .. } => format!("ATTDEF Specify insertion point for '{tag}':"),
}
}
@@ -61,7 +77,11 @@ impl CadCommand for AttdefCommand {
}
Step::Prompt { tag } => {
let tag = tag.clone();
let prompt = if text.trim().is_empty() { tag.clone() } else { text.trim().to_string() };
let prompt = if text.trim().is_empty() {
tag.clone()
} else {
text.trim().to_string()
};
self.step = Step::Default { tag, prompt };
Some(CmdResult::NeedPoint)
}
@@ -69,7 +89,11 @@ impl CadCommand for AttdefCommand {
let tag = tag.clone();
let prompt = prompt.clone();
let default = text.trim().to_string();
self.step = Step::Insertion { tag, prompt, default };
self.step = Step::Insertion {
tag,
prompt,
default,
};
Some(CmdResult::NeedPoint)
}
Step::Insertion { .. } => None,
@@ -77,7 +101,12 @@ impl CadCommand for AttdefCommand {
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
if let Step::Insertion { tag, prompt, default } = &self.step {
if let Step::Insertion {
tag,
prompt,
default,
} = &self.step
{
let mut attdef = AttributeDefinition {
tag: tag.clone(),
prompt: prompt.clone(),
@@ -99,12 +128,19 @@ impl CadCommand for AttdefCommand {
// Treat Enter as empty text input for prompt/default steps.
Step::Prompt { tag } => {
let tag = tag.clone();
self.step = Step::Default { tag: tag.clone(), prompt: tag };
self.step = Step::Default {
tag: tag.clone(),
prompt: tag,
};
CmdResult::NeedPoint
}
Step::Default { tag, prompt } => {
let (tag, prompt) = (tag.clone(), prompt.clone());
self.step = Step::Insertion { tag, prompt, default: String::new() };
self.step = Step::Insertion {
tag,
prompt,
default: String::new(),
};
CmdResult::NeedPoint
}
Step::Insertion { .. } => CmdResult::Cancel,
@@ -120,9 +156,11 @@ impl CadCommand for AttdefCommand {
Some(WireModel {
name: "attdef_preview".into(),
points: vec![
[pt.x - d, pt.y, pt.z], [pt.x + d, pt.y, pt.z],
[pt.x - d, pt.y, pt.z],
[pt.x + d, pt.y, pt.z],
[f32::NAN, 0.0, 0.0],
[pt.x, pt.y, pt.z - d], [pt.x, pt.y, pt.z + d],
[pt.x, pt.y, pt.z - d],
[pt.x, pt.y, pt.z + d],
],
color: WireModel::CYAN,
selected: false,
+14 -5
View File
@@ -39,12 +39,14 @@ impl DonutCommand {
}
impl CadCommand for DonutCommand {
fn name(&self) -> &'static str { "DONUT" }
fn name(&self) -> &'static str {
"DONUT"
}
fn prompt(&self) -> String {
match &self.state {
DonutState::AskInner => "DONUT Specify inside diameter <0>:".into(),
DonutState::AskOuter => "DONUT Specify outside diameter:".into(),
DonutState::AskInner => "DONUT Specify inside diameter <0>:".into(),
DonutState::AskOuter => "DONUT Specify outside diameter:".into(),
DonutState::PlaceCenter => "DONUT Specify center of donut (Enter to exit):".into(),
}
}
@@ -54,7 +56,12 @@ impl CadCommand for DonutCommand {
}
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
let val: f64 = text.trim().replace(',', ".").parse().ok().filter(|&v: &f64| v >= 0.0)?;
let val: f64 = text
.trim()
.replace(',', ".")
.parse()
.ok()
.filter(|&v: &f64| v >= 0.0)?;
match &self.state {
DonutState::AskInner => {
self.inner_r = val / 2.0;
@@ -62,7 +69,9 @@ impl CadCommand for DonutCommand {
Some(CmdResult::NeedPoint)
}
DonutState::AskOuter => {
if val <= 0.0 { return None; }
if val <= 0.0 {
return None;
}
self.outer_r = val / 2.0;
if self.inner_r > self.outer_r {
std::mem::swap(&mut self.inner_r, &mut self.outer_r);
+5 -5
View File
@@ -525,10 +525,10 @@ fn line_wire(from: Vec3, to: Vec3) -> WireModel {
snap_pts: vec![],
tangent_geoms: vec![],
aci: 0,
key_vertices: vec![],
aabb: WireModel::UNBOUNDED_AABB,
plinegen: true,
vp_scissor: None,
fill_tris: vec![],
key_vertices: vec![],
aabb: WireModel::UNBOUNDED_AABB,
plinegen: true,
vp_scissor: None,
fill_tris: vec![],
}
}
+48 -16
View File
@@ -29,23 +29,34 @@ pub struct HatcheditCommand {
impl HatcheditCommand {
pub fn new() -> Self {
Self { step: HatcheditStep::PickHatch }
Self {
step: HatcheditStep::PickHatch,
}
}
pub fn with_handle(handle: Handle, name: String, scale: f32, angle: f32) -> Self {
Self {
step: HatcheditStep::EditOptions { handle, name, scale, angle },
step: HatcheditStep::EditOptions {
handle,
name,
scale,
angle,
},
}
}
}
impl CadCommand for HatcheditCommand {
fn name(&self) -> &'static str { "HATCHEDIT" }
fn name(&self) -> &'static str {
"HATCHEDIT"
}
fn prompt(&self) -> String {
match &self.step {
HatcheditStep::PickHatch => "HATCHEDIT Select hatch:".into(),
HatcheditStep::EditOptions { name, scale, angle, .. } => format!(
HatcheditStep::EditOptions {
name, scale, angle, ..
} => format!(
"HATCHEDIT Pattern:{name} Scale:{scale:.4} Angle:{angle:.1} \
[P <pat> / S <scale> / A <angle> | Enter to apply]:"
),
@@ -57,7 +68,9 @@ impl CadCommand for HatcheditCommand {
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
if handle.is_null() { return CmdResult::NeedPoint; }
if handle.is_null() {
return CmdResult::NeedPoint;
}
// Actual hatch model retrieval happens in commands.rs dispatch.
// Store handle; name/scale/angle filled in by dispatch.
self.step = HatcheditStep::EditOptions {
@@ -75,9 +88,12 @@ impl CadCommand for HatcheditCommand {
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
let (handle, name, scale, angle) = match &mut self.step {
HatcheditStep::EditOptions { handle, name, scale, angle } => {
(*handle, name, scale, angle)
}
HatcheditStep::EditOptions {
handle,
name,
scale,
angle,
} => (*handle, name, scale, angle),
_ => return None,
};
@@ -96,12 +112,16 @@ impl CadCommand for HatcheditCommand {
// Parse option: P/S/A followed by value
if let Some(rest) = text.strip_prefix('P') {
let n = rest.trim().to_string();
if !n.is_empty() { *name = n; }
if !n.is_empty() {
*name = n;
}
return Some(CmdResult::NeedPoint);
}
if let Some(rest) = text.strip_prefix('S') {
if let Ok(v) = rest.trim().replace(',', ".").parse::<f32>() {
if v > 0.0 { *scale = v; }
if v > 0.0 {
*scale = v;
}
}
return Some(CmdResult::NeedPoint);
}
@@ -116,16 +136,28 @@ impl CadCommand for HatcheditCommand {
Some(CmdResult::NeedPoint)
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult { CmdResult::NeedPoint }
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
// Enter without text → apply current settings
let (handle, name, scale, angle) = match &self.step {
HatcheditStep::EditOptions { handle, name, scale, angle } => {
(*handle, name.clone(), *scale, *angle)
}
HatcheditStep::EditOptions {
handle,
name,
scale,
angle,
} => (*handle, name.clone(), *scale, *angle),
_ => return CmdResult::Cancel,
};
CmdResult::HatcheditApply { handle, name, scale, angle }
CmdResult::HatcheditApply {
handle,
name,
scale,
angle,
}
}
fn on_escape(&mut self) -> CmdResult {
CmdResult::Cancel
}
fn on_escape(&mut self) -> CmdResult { CmdResult::Cancel }
}
+34 -10
View File
@@ -23,16 +23,28 @@ pub struct MlineCommand {
impl MlineCommand {
#[allow(dead_code)]
pub fn new() -> Self {
Self { points: vec![], scale: 1.0, waiting_scale: false, style_name: "Standard".into() }
Self {
points: vec![],
scale: 1.0,
waiting_scale: false,
style_name: "Standard".into(),
}
}
pub fn with_style(style_name: impl Into<String>) -> Self {
Self { points: vec![], scale: 1.0, waiting_scale: false, style_name: style_name.into() }
Self {
points: vec![],
scale: 1.0,
waiting_scale: false,
style_name: style_name.into(),
}
}
}
impl CadCommand for MlineCommand {
fn name(&self) -> &'static str { "MLINE" }
fn name(&self) -> &'static str {
"MLINE"
}
fn prompt(&self) -> String {
if self.waiting_scale {
@@ -40,7 +52,10 @@ impl CadCommand for MlineCommand {
} else if self.points.is_empty() {
format!("MLINE Specify start point (scale={:.2}):", self.scale)
} else {
format!("MLINE Specify next point ({} pts, Enter to finish, C to close, S to set scale):", self.points.len())
format!(
"MLINE Specify next point ({} pts, Enter to finish, C to close, S to set scale):",
self.points.len()
)
}
}
@@ -51,7 +66,12 @@ impl CadCommand for MlineCommand {
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
// Waiting for scale value
if self.waiting_scale {
let v: f64 = text.trim().replace(',', ".").parse().ok().filter(|&v: &f64| v > 0.0)?;
let v: f64 = text
.trim()
.replace(',', ".")
.parse()
.ok()
.filter(|&v: &f64| v > 0.0)?;
self.scale = v;
self.waiting_scale = false;
return Some(CmdResult::NeedPoint);
@@ -74,7 +94,9 @@ impl CadCommand for MlineCommand {
// Scale: "S <value>" inline
if let Some(rest) = up.strip_prefix("S ") {
if let Ok(v) = rest.trim().replace(',', ".").parse::<f64>() {
if v > 0.0 { self.scale = v; }
if v > 0.0 {
self.scale = v;
}
return Some(CmdResult::NeedPoint);
}
}
@@ -96,9 +118,10 @@ impl CadCommand for MlineCommand {
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
if self.points.is_empty() { return None; }
let mut pts: Vec<[f32; 3]> =
self.points.iter().map(|p| [p.x, p.y, p.z]).collect();
if self.points.is_empty() {
return None;
}
let mut pts: Vec<[f32; 3]> = self.points.iter().map(|p| [p.x, p.y, p.z]).collect();
pts.push([pt.x, pt.y, pt.z]);
Some(WireModel {
name: "mline_preview".into(),
@@ -121,7 +144,8 @@ impl CadCommand for MlineCommand {
}
fn build_mline(pts: &[Vec3], scale: f64, closed: bool, style_name: &str) -> EntityType {
let verts: Vec<Vector3> = pts.iter()
let verts: Vec<Vector3> = pts
.iter()
.map(|p| Vector3::new(p.x as f64, p.z as f64, p.y as f64))
.collect();
let mut mline = if closed {
+1 -1
View File
@@ -3,8 +3,8 @@ pub mod attdef;
pub mod circle;
pub mod donut;
pub mod ellipse;
pub mod hatchedit;
pub mod hatch;
pub mod hatchedit;
pub mod line;
pub mod mline;
pub mod point;
+13 -3
View File
@@ -130,7 +130,8 @@ fn update_tangent_after_arc(tangent: &mut Option<Vec2>, bulge: f64) {
// the entry tangent rotated by that angle.
let theta = 4.0 * (bulge as f32).atan();
let (sin_t, cos_t) = theta.sin_cos();
*tangent = Some(Vec2::new(t.x * cos_t - t.y * sin_t, t.x * sin_t + t.y * cos_t).normalize_or_zero());
*tangent =
Some(Vec2::new(t.x * cos_t - t.y * sin_t, t.x * sin_t + t.y * cos_t).normalize_or_zero());
}
/// Sample a circular arc defined by bulge into `n` line-segment points.
@@ -169,7 +170,11 @@ fn arc_sample_points(a: Vec3, bulge: f64, b: Vec3, n: usize) -> Vec<[f32; 3]> {
for i in 0..=n {
let t = i as f64 / n as f64;
let angle = start_angle + t * theta;
pts.push([(cx + r * angle.cos()) as f32, (cy + r * angle.sin()) as f32, a.z]);
pts.push([
(cx + r * angle.cos()) as f32,
(cy + r * angle.sin()) as f32,
a.z,
]);
}
pts
}
@@ -308,6 +313,11 @@ impl CadCommand for PlineCommand {
}
}
Some(WireModel::solid("rubber_band".into(), pts, WireModel::CYAN, false))
Some(WireModel::solid(
"rubber_band".into(),
pts,
WireModel::CYAN,
false,
))
}
}
+10 -2
View File
@@ -23,7 +23,12 @@ pub struct ImageCommand {
impl ImageCommand {
pub fn new(file_path: String, pixel_width: u32, pixel_height: u32) -> Self {
Self { file_path, pixel_width, pixel_height, origin: None }
Self {
file_path,
pixel_width,
pixel_height,
origin: None,
}
}
fn aspect(&self) -> f64 {
@@ -61,7 +66,10 @@ impl CadCommand for ImageCommand {
fn prompt(&self) -> String {
if self.origin.is_none() {
format!("IMAGE Specify insertion point ({}): ", short_name(&self.file_path))
format!(
"IMAGE Specify insertion point ({}): ",
short_name(&self.file_path)
)
} else {
"IMAGE Specify width (drag right):".into()
}
+19 -8
View File
@@ -6,7 +6,7 @@
use acadrust::entities::LwPolyline;
use acadrust::types::Vector2;
use acadrust::{EntityType, entities::LwVertex};
use acadrust::{entities::LwVertex, EntityType};
use glam::Vec3;
use crate::command::{CadCommand, CmdResult};
@@ -41,13 +41,21 @@ impl RevCloudCommand {
}
impl CadCommand for RevCloudCommand {
fn name(&self) -> &'static str { "REVCLOUD" }
fn name(&self) -> &'static str {
"REVCLOUD"
}
fn prompt(&self) -> String {
if self.points.is_empty() {
format!("REVCLOUD Specify start point (arc length = {:.2}):", self.arc_length)
format!(
"REVCLOUD Specify start point (arc length = {:.2}):",
self.arc_length
)
} else {
format!("REVCLOUD Specify next point ({} pts, Enter to close):", self.points.len())
format!(
"REVCLOUD Specify next point ({} pts, Enter to close):",
self.points.len()
)
}
}
@@ -65,9 +73,10 @@ impl CadCommand for RevCloudCommand {
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
if self.points.is_empty() { return None; }
let mut preview_pts: Vec<[f32; 3]> =
self.points.iter().map(|p| [p.x, p.y, p.z]).collect();
if self.points.is_empty() {
return None;
}
let mut preview_pts: Vec<[f32; 3]> = self.points.iter().map(|p| [p.x, p.y, p.z]).collect();
preview_pts.push([pt.x, pt.y, pt.z]);
preview_pts.push([self.points[0].x, self.points[0].y, self.points[0].z]);
Some(WireModel {
@@ -101,7 +110,9 @@ fn make_revcloud(pts: &[Vec3], arc_len: f64) -> EntityType {
let p0 = pts[i];
let p1 = pts[(i + 1) % n];
let seg_len = ((p1.x - p0.x).powi(2) + (p1.z - p0.z).powi(2)).sqrt() as f64;
if seg_len < 1e-6 { continue; }
if seg_len < 1e-6 {
continue;
}
// How many full arcs fit?
let num_arcs = ((seg_len / arc_len).round() as usize).max(1);
+34 -26
View File
@@ -37,15 +37,25 @@ enum WipeoutMode {
impl WipeoutCommand {
pub fn new_rectangular() -> Self {
Self { mode: WipeoutMode::Rectangular, first: None, poly_pts: vec![] }
Self {
mode: WipeoutMode::Rectangular,
first: None,
poly_pts: vec![],
}
}
pub fn new_polygonal() -> Self {
Self { mode: WipeoutMode::Polygonal, first: None, poly_pts: vec![] }
Self {
mode: WipeoutMode::Polygonal,
first: None,
poly_pts: vec![],
}
}
}
impl CadCommand for WipeoutCommand {
fn name(&self) -> &'static str { "WIPEOUT" }
fn name(&self) -> &'static str {
"WIPEOUT"
}
fn prompt(&self) -> String {
match &self.mode {
@@ -60,7 +70,10 @@ impl CadCommand for WipeoutCommand {
if self.poly_pts.is_empty() {
"WIPEOUT (Polygon) Specify first point:".into()
} else {
format!("WIPEOUT (Polygon) Specify next point ({} pts, Enter to close):", self.poly_pts.len())
format!(
"WIPEOUT (Polygon) Specify next point ({} pts, Enter to close):",
self.poly_pts.len()
)
}
}
}
@@ -117,15 +130,17 @@ impl CadCommand for WipeoutCommand {
snap_pts: vec![],
tangent_geoms: vec![],
aci: 0,
key_vertices: vec![],
aabb: WireModel::UNBOUNDED_AABB,
plinegen: true,
vp_scissor: None,
fill_tris: vec![],
key_vertices: vec![],
aabb: WireModel::UNBOUNDED_AABB,
plinegen: true,
vp_scissor: None,
fill_tris: vec![],
})
}
WipeoutMode::Polygonal => {
if self.poly_pts.is_empty() { return None; }
if self.poly_pts.is_empty() {
return None;
}
let mut pts: Vec<[f32; 3]> =
self.poly_pts.iter().map(|p| [p.x, p.y, p.z]).collect();
pts.push([pt.x, pt.y, pt.z]);
@@ -141,11 +156,11 @@ impl CadCommand for WipeoutCommand {
snap_pts: vec![],
tangent_geoms: vec![],
aci: 0,
key_vertices: vec![],
aabb: WireModel::UNBOUNDED_AABB,
plinegen: true,
vp_scissor: None,
fill_tris: vec![],
key_vertices: vec![],
aabb: WireModel::UNBOUNDED_AABB,
plinegen: true,
vp_scissor: None,
fill_tris: vec![],
})
}
}
@@ -154,23 +169,16 @@ impl CadCommand for WipeoutCommand {
fn make_rect_wipeout(p1: Vec3, p2: Vec3) -> EntityType {
// Y-up world: X→DXF X, Z→DXF Y, Y→DXF Z
let c1 = Vector3::new(
p1.x.min(p2.x) as f64,
p1.z.min(p2.z) as f64,
p1.y as f64,
);
let c2 = Vector3::new(
p1.x.max(p2.x) as f64,
p1.z.max(p2.z) as f64,
p1.y as f64,
);
let c1 = Vector3::new(p1.x.min(p2.x) as f64, p1.z.min(p2.z) as f64, p1.y as f64);
let c2 = Vector3::new(p1.x.max(p2.x) as f64, p1.z.max(p2.z) as f64, p1.y as f64);
EntityType::Wipeout(Wipeout::from_corners(c1, c2))
}
fn make_poly_wipeout(pts: &[Vec3]) -> EntityType {
use acadrust::types::Vector2;
let z = pts[0].y as f64;
let verts: Vec<Vector2> = pts.iter()
let verts: Vec<Vector2> = pts
.iter()
.map(|p| Vector2::new(p.x as f64, p.z as f64))
.collect();
EntityType::Wipeout(Wipeout::polygonal(&verts, z))