Broad pass over the command set: integrate missing commands, wire previously-unreachable ribbon/menu buttons, and correct name/behaviour mismatches. Every UI command token now resolves (real handler where the infrastructure exists, an honest "not yet implemented" status otherwise). New commands: - Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER (DCE/CENTERMARK) - Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST - Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner), FINDNONPURGEABLE Behaviour fixes: - LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64 (correct at large coordinates) - ATTEDIT/ATE unified so the alias and the ribbon button open the interactive editor; -ATTEDIT is the command-line form - Linear/aligned/radius/diameter dimensions gain a text override (Text) and text angle (Angle) option - INSERT gains Scale/Rotate options; COPY gains an Array option - LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides - UNDO accepts a step count Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE, EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/ DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling (CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points (CUI/ALIASEDIT). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
111 lines
3.9 KiB
Rust
111 lines
3.9 KiB
Rust
// 2D solid tool — interactive command.
|
|
//
|
|
// Command: SOLID (reachable as SO / SOLID2D — the bare SOLID verb currently
|
|
// toggles the shaded display) — pick three or four corner points and commit a
|
|
// filled triangle or quadrilateral. Points are taken in the order picked: the
|
|
// third point is the corner diagonally opposite the second, so a four-point
|
|
// solid is entered in a Z pattern (entering the corners in ring order yields
|
|
// the classic bow-tie fill). Enter after the third point commits a triangle.
|
|
|
|
use acadrust::entities::Solid;
|
|
use acadrust::types::Vector3;
|
|
use acadrust::EntityType;
|
|
|
|
use crate::command::{CadCommand, CmdResult};
|
|
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
|
use crate::scene::model::wire_model::WireModel;
|
|
use glam::DVec3;
|
|
|
|
// ── Ribbon definition ─────────────────────────────────────────────────────
|
|
|
|
#[allow(dead_code)] // ribbon definition ready for wiring; command works via the command line
|
|
pub fn tool() -> ToolDef {
|
|
ToolDef {
|
|
id: "SOLID2D",
|
|
label: "2D Solid",
|
|
icon: IconKind::Svg(include_bytes!("../../../../assets/icons/line.svg")),
|
|
event: ModuleEvent::Command("SOLID2D".to_string()),
|
|
}
|
|
}
|
|
|
|
// ── Command implementation ────────────────────────────────────────────────
|
|
|
|
pub struct Solid2dCommand {
|
|
/// Corner points picked so far (3 → triangle, 4 → quadrilateral).
|
|
points: Vec<DVec3>,
|
|
}
|
|
|
|
impl Solid2dCommand {
|
|
pub fn new() -> Self {
|
|
Self { points: Vec::new() }
|
|
}
|
|
|
|
fn v3(p: DVec3) -> Vector3 {
|
|
Vector3::new(p.x, p.y, p.z)
|
|
}
|
|
}
|
|
|
|
impl CadCommand for Solid2dCommand {
|
|
fn name(&self) -> &'static str {
|
|
"SOLID"
|
|
}
|
|
|
|
fn prompt(&self) -> String {
|
|
match self.points.len() {
|
|
0 => "SOLID Specify first point:".to_string(),
|
|
1 => "SOLID Specify second point:".to_string(),
|
|
2 => "SOLID Specify third point:".to_string(),
|
|
_ => "SOLID Specify fourth point [Enter = triangle]:".to_string(),
|
|
}
|
|
}
|
|
|
|
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
|
self.points.push(pt);
|
|
if self.points.len() == 4 {
|
|
let p = &self.points;
|
|
let solid = Solid::new(
|
|
Self::v3(p[0]),
|
|
Self::v3(p[1]),
|
|
Self::v3(p[2]),
|
|
Self::v3(p[3]),
|
|
);
|
|
CmdResult::CommitAndExit(EntityType::Solid(solid))
|
|
} else {
|
|
CmdResult::NeedPoint
|
|
}
|
|
}
|
|
|
|
fn on_enter(&mut self) -> CmdResult {
|
|
if self.points.len() == 3 {
|
|
let p = &self.points;
|
|
let solid = Solid::triangle(Self::v3(p[0]), Self::v3(p[1]), Self::v3(p[2]));
|
|
CmdResult::CommitAndExit(EntityType::Solid(solid))
|
|
} else {
|
|
CmdResult::Cancel
|
|
}
|
|
}
|
|
|
|
fn on_escape(&mut self) -> CmdResult {
|
|
CmdResult::Cancel
|
|
}
|
|
|
|
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
|
if self.points.is_empty() {
|
|
return None;
|
|
}
|
|
// Outline the corners picked so far plus the cursor, closed back to the
|
|
// first point, as a rubber-band hint.
|
|
let mut pts: Vec<[f64; 3]> = self.points.iter().map(|p| [p.x, p.y, p.z]).collect();
|
|
pts.push([pt.x, pt.y, pt.z]);
|
|
pts.push([self.points[0].x, self.points[0].y, self.points[0].z]);
|
|
Some(WireModel::solid_f64(
|
|
"rubber_band".to_string(),
|
|
pts,
|
|
WireModel::CYAN,
|
|
false,
|
|
))
|
|
}
|
|
}
|
|
|
|
// ── Autocomplete registry ─────────────────────────────────
|
|
inventory::submit!(crate::command::CommandRegistration { names: &["SO", "SOLID2D"] }); // Solid2dCommand
|