cad-editor/src/scene/object.rs

98 lines
3.5 KiB
Rust
Raw Normal View History

2026-03-22 14:56:27 +03:00
// Shared value types used by the dispatch and grip systems.
use acadrust::types::{Color as AcadColor, LineWeight};
use glam::Vec3;
/// The kind of value held by a property row.
#[derive(Clone, Debug, PartialEq)]
pub enum PropValue {
/// Read-only display text.
ReadOnly(String),
/// Editable numeric/text field.
EditText(String),
/// Layer name — rendered as a combo_box.
LayerChoice(String),
/// Generic string choice rendered as a combo_box.
Choice {
selected: String,
options: Vec<String>,
},
/// ACI/RGB/ByLayer/ByBlock color — rendered as a color picker.
ColorChoice(AcadColor),
/// Color varies across the current multi-selection.
ColorVaries,
/// Line weight — rendered as a combo_box.
LwChoice(LineWeight),
/// Lineweight varies across the current multi-selection.
LwVaries,
/// Linetype name — rendered as a combo_box.
LinetypeChoice(String),
/// Boolean flag — rendered as a toggle button (e.g. Invisible).
BoolToggle { field: &'static str, value: bool },
/// Hatch pattern name — rendered as a combo_box from the catalog.
HatchPatternChoice(String),
}
/// A single property row in the Properties panel.
#[derive(Clone, Debug, PartialEq)]
pub struct Property {
pub label: String,
/// Stable field identifier used in `PropGeomInput` / `PropGeomCommit` messages.
pub field: &'static str,
pub value: PropValue,
}
/// A named section of properties (e.g. "General", "Geometry").
#[derive(Clone, Debug, PartialEq)]
pub struct PropSection {
pub title: String,
pub props: Vec<Property>,
}
// ── Grip types ─────────────────────────────────────────────────────────────
refactor(grip): square-only marker set + oriented stretch handles Phase 1 of bringing the grip vocabulary in line with the standard CAD convention: drop the per-position-type shape encoding (Diamond for translate, Circle for parameter) and use a plain square for every endpoint / vertex / centre grip. The behavioural midpoint vs vertex distinction stays — it lives on `GripDef::is_midpoint` and drives `Translate` vs `Absolute` in the grip-edit dispatcher — only the marker shape collapses. - `GripShape` keeps `Square`, `Rectangle`, `Triangle`. Diamond / Circle are gone. - `GripDef` gains `dir: Option<[f32; 2]>` — a world-XY direction vector consumed by `Rectangle` to orient the box along its segment. - `entities::common` exposes `square_grip`, `center_grip` (same square marker, flagged as translate), `rectangle_grip(id, world, dir)` for oriented mid-segment handles, and a kept-for-Phase-2 `triangle_grip`. - `overlay::GripMarker` / `grips_to_screen[_paper]` thread `dir` through to the canvas painter; the Rectangle path rotates the box around the grip centre using the world-XY direction (flipping the sin for screen-Y). Every existing `diamond_grip(id, w)` call becomes `center_grip(id, w)` — the visual change is square-replacing-diamond at line midpoints / arc midpoints / circle centres / ellipse centres / viewport / hatch loop centroids / dimension grips / image corners / multileader / ray / underlay / ole2frame / solid3d. `LwPolyline` grows a stretch handle on every segment (straight or arc), drawn as the new oriented rectangle. The grip-edit path translates both segment endpoints for straight segments and adjusts the arc bulge from the new midpoint for arc segments.
2026-05-29 02:07:34 +03:00
/// Visual marker shape for a grip point. The complete vocabulary that
/// matches the standard CAD grip conventions:
/// * `Square` — endpoint / vertex / centre. Drag → moves a single
/// point or translates the entity.
/// * `Rectangle` — direction-aware mid-segment stretch handle.
/// Drawn as a small box rotated along `dir` (the in-plane segment
/// direction in world XY). Used for polyline / wipeout / image /
/// dimension segment midpoints.
/// * `Triangle` — directional indicator (Phase 2: dynamic-block
/// parameters, dimension reverse-arrow flips, multi-functional
/// hover popups).
2026-03-22 14:56:27 +03:00
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(dead_code)]
2026-03-22 14:56:27 +03:00
pub enum GripShape {
Square,
Rectangle,
2026-03-22 14:56:27 +03:00
Triangle,
}
/// Describes one grip point for an entity.
#[derive(Clone, Debug)]
pub struct GripDef {
/// Object-local identifier (stable index, unique per object instance).
pub id: usize,
/// World-space position of the grip.
pub world: Vec3,
refactor(grip): square-only marker set + oriented stretch handles Phase 1 of bringing the grip vocabulary in line with the standard CAD convention: drop the per-position-type shape encoding (Diamond for translate, Circle for parameter) and use a plain square for every endpoint / vertex / centre grip. The behavioural midpoint vs vertex distinction stays — it lives on `GripDef::is_midpoint` and drives `Translate` vs `Absolute` in the grip-edit dispatcher — only the marker shape collapses. - `GripShape` keeps `Square`, `Rectangle`, `Triangle`. Diamond / Circle are gone. - `GripDef` gains `dir: Option<[f32; 2]>` — a world-XY direction vector consumed by `Rectangle` to orient the box along its segment. - `entities::common` exposes `square_grip`, `center_grip` (same square marker, flagged as translate), `rectangle_grip(id, world, dir)` for oriented mid-segment handles, and a kept-for-Phase-2 `triangle_grip`. - `overlay::GripMarker` / `grips_to_screen[_paper]` thread `dir` through to the canvas painter; the Rectangle path rotates the box around the grip centre using the world-XY direction (flipping the sin for screen-Y). Every existing `diamond_grip(id, w)` call becomes `center_grip(id, w)` — the visual change is square-replacing-diamond at line midpoints / arc midpoints / circle centres / ellipse centres / viewport / hatch loop centroids / dimension grips / image corners / multileader / ray / underlay / ole2frame / solid3d. `LwPolyline` grows a stretch handle on every segment (straight or arc), drawn as the new oriented rectangle. The grip-edit path translates both segment endpoints for straight segments and adjusts the arc bulge from the new midpoint for arc segments.
2026-05-29 02:07:34 +03:00
/// `true` → midpoint / centre grip (drags the whole shape).
/// `false` → endpoint / vertex grip (moves a single point).
2026-03-22 14:56:27 +03:00
pub is_midpoint: bool,
/// Visual marker shape for the grip.
pub shape: GripShape,
refactor(grip): square-only marker set + oriented stretch handles Phase 1 of bringing the grip vocabulary in line with the standard CAD convention: drop the per-position-type shape encoding (Diamond for translate, Circle for parameter) and use a plain square for every endpoint / vertex / centre grip. The behavioural midpoint vs vertex distinction stays — it lives on `GripDef::is_midpoint` and drives `Translate` vs `Absolute` in the grip-edit dispatcher — only the marker shape collapses. - `GripShape` keeps `Square`, `Rectangle`, `Triangle`. Diamond / Circle are gone. - `GripDef` gains `dir: Option<[f32; 2]>` — a world-XY direction vector consumed by `Rectangle` to orient the box along its segment. - `entities::common` exposes `square_grip`, `center_grip` (same square marker, flagged as translate), `rectangle_grip(id, world, dir)` for oriented mid-segment handles, and a kept-for-Phase-2 `triangle_grip`. - `overlay::GripMarker` / `grips_to_screen[_paper]` thread `dir` through to the canvas painter; the Rectangle path rotates the box around the grip centre using the world-XY direction (flipping the sin for screen-Y). Every existing `diamond_grip(id, w)` call becomes `center_grip(id, w)` — the visual change is square-replacing-diamond at line midpoints / arc midpoints / circle centres / ellipse centres / viewport / hatch loop centroids / dimension grips / image corners / multileader / ray / underlay / ole2frame / solid3d. `LwPolyline` grows a stretch handle on every segment (straight or arc), drawn as the new oriented rectangle. The grip-edit path translates both segment endpoints for straight segments and adjusts the arc bulge from the new midpoint for arc segments.
2026-05-29 02:07:34 +03:00
/// World-XY direction vector used to orient a `Rectangle` grip
/// along its segment. `None` for shapes that don't need rotation
/// (Square, Triangle in non-directional contexts).
pub dir: Option<[f32; 2]>,
2026-03-22 14:56:27 +03:00
}
/// How to apply a grip drag result.
#[derive(Clone, Debug)]
pub enum GripApply {
/// Move a specific vertex to this absolute world position.
Absolute(Vec3),
/// Translate the whole object by this delta vector.
Translate(Vec3),
}