forked from 1b-agent/opencadstudio-upstream
A lone unlocked point cloud selected in a 3D visual style shows a move gizmo at its insertion point: X/Y/Z arrows and XY/YZ/ZX squares. Dragging an arrow moves the cloud along that axis, a square moves it in that plane; the hovered part is highlighted and each drag is one undo step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
237 lines
8.9 KiB
Rust
237 lines
8.9 KiB
Rust
// Shared value types used by the dispatch and grip systems.
|
|
|
|
use codec::types::{Color as AcadColor, Handle, LineWeight};
|
|
use glam::DVec3;
|
|
|
|
/// The kind of value held by a property row.
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub enum PropValue {
|
|
/// Read-only display text.
|
|
ReadOnly(String),
|
|
/// Read-only display text with a tooltip explaining why it cannot be edited.
|
|
ReadOnlyWithTooltip { value: String, tooltip: String },
|
|
/// Editable numeric field.
|
|
EditText(String),
|
|
/// Editable text that must not be expression-evaluated.
|
|
PlainText(String),
|
|
/// Hyperlink collection summary. The value is display-only in the row;
|
|
/// the adjacent collection button opens the URL/description editor.
|
|
Hyperlink(String),
|
|
/// Layer name — rendered as a combo_box.
|
|
LayerChoice(String),
|
|
/// Generic string choice rendered as a combo_box.
|
|
Choice {
|
|
selected: String,
|
|
options: Vec<String>,
|
|
},
|
|
/// Editable text plus a dropdown of existing options (block reference
|
|
/// Name row): picking an option re-points the reference, submitting a
|
|
/// new name renames the definition.
|
|
EditChoice { value: String, options: Vec<String> },
|
|
/// ACI/RGB/ByLayer/ByBlock color — rendered as a color picker.
|
|
ColorChoice(AcadColor),
|
|
/// Color-book color with its file-provided display name.
|
|
NamedColorChoice { color: AcadColor, name: String },
|
|
/// Color varies across the current multi-selection.
|
|
ColorVaries,
|
|
/// Line weight — rendered as a combo_box.
|
|
LwChoice(LineWeight),
|
|
/// Object-specific line weight routed by field name.
|
|
FieldLwChoice {
|
|
field: &'static str,
|
|
value: LineWeight,
|
|
},
|
|
/// Object-specific lineweight varies across the current selection.
|
|
FieldLwVaries { field: &'static str },
|
|
/// 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 },
|
|
/// A 0-based index navigated with ◀ / ▶ buttons (e.g. a polyline's Current
|
|
/// Vertex). `display` is the label shown between the arrows (e.g. "2 / 7").
|
|
Stepper {
|
|
field: &'static str,
|
|
display: String,
|
|
},
|
|
/// Hatch pattern name — rendered as a combo_box from the catalog.
|
|
HatchPatternChoice(String),
|
|
/// Block attribute value keyed by its (dynamic, runtime) tag — rendered as
|
|
/// an editable text_input. Unlike the other rows the routing key is the
|
|
/// tag carried here, not the row's `&'static str` field.
|
|
AttrText { tag: String, value: String },
|
|
/// A clickable link to one or more entities — the Constraints section's
|
|
/// row for one parametric constraint. Clicking it selects every
|
|
/// entity in `handles` in the viewport. `conflicting` mirrors
|
|
/// `ParametricConstraintSet::conflicts`, tinting the row the same danger
|
|
/// color the constraint's glyph pill already uses. `id` routes the row's
|
|
/// delete action back to that constraint in the active scope.
|
|
EntityLink {
|
|
id: crate::scene::parametric_constraints::ConstraintId,
|
|
handles: Vec<Handle>,
|
|
conflicting: bool,
|
|
},
|
|
/// One row of the document-wide named-parameter table (Parameters
|
|
/// section, shown when nothing is selected). `index` is the row's
|
|
/// position in `ParameterTable::iter()` order — stable across edits to
|
|
/// other rows, used to route `PropParamInput`/`PropParamCommit`/
|
|
/// `PropParamDelete` back to the right parameter without re-keying on a
|
|
/// name that might itself be mid-edit. `resolved` is the live value or
|
|
/// error, recomputed fresh every render (same "cheap enough to rebuild"
|
|
/// approach the old modal's preview column already used).
|
|
ParamRow {
|
|
index: usize,
|
|
name: String,
|
|
formula: String,
|
|
resolved: Result<f64, String>,
|
|
},
|
|
/// The trailing "+ Add parameter" row in the Parameters section.
|
|
ParamAddRow,
|
|
/// The Parameters section's leading header row (no-selection page only):
|
|
/// a global on/off toggle for whether any constraint pill in the
|
|
/// viewport shows its driven value/parameter-name text. Mirrors
|
|
/// `App::show_constraint_values`.
|
|
ParamsVisibilityToggle(bool),
|
|
}
|
|
|
|
/// 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 ─────────────────────────────────────────────────────────────
|
|
|
|
/// 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).
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
#[allow(dead_code)]
|
|
pub enum GripShape {
|
|
Square,
|
|
Rectangle,
|
|
Triangle,
|
|
Circle,
|
|
/// Screen-offset menu selector.
|
|
Dropdown,
|
|
/// Menu selector placed immediately beside its anchor grip.
|
|
DropdownAdjacent,
|
|
/// Move-gizmo arrow along world X (0), Y (1) or Z (2); the grip's world
|
|
/// point is the gizmo centre, the marker sits at the arrow tip.
|
|
GizmoAxis(u8),
|
|
/// Move-gizmo square between two axes: XY (0), YZ (1) or ZX (2).
|
|
GizmoPlane(u8),
|
|
}
|
|
|
|
/// 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, in f64. Entity coordinates can sit at
|
|
/// UTM magnitudes (1e7); casting to f32 before the world-offset subtraction
|
|
/// loses ~1 drawing unit and draws the grip visibly off the wire. Producers
|
|
/// fill this straight from the f64 entity data; the offset is subtracted in
|
|
/// f64 and only then cast for screen-space math.
|
|
pub world: glam::DVec3,
|
|
/// `true` → midpoint / centre grip (drags the whole shape).
|
|
/// `false` → endpoint / vertex grip (moves a single point).
|
|
pub is_midpoint: bool,
|
|
/// Visual marker shape for the grip.
|
|
pub shape: GripShape,
|
|
/// World-space marker direction, projected with the grip position.
|
|
pub dir: Option<glam::DVec3>,
|
|
/// World-space axis that constrains this grip's drag.
|
|
pub axis: Option<glam::DVec3>,
|
|
}
|
|
|
|
/// How to apply a grip drag result.
|
|
#[derive(Clone, Debug)]
|
|
pub enum GripApply {
|
|
/// Move a specific vertex to this absolute world position.
|
|
Absolute(DVec3),
|
|
/// Translate the whole object by this delta vector.
|
|
Translate(DVec3),
|
|
}
|
|
|
|
/// One entry in the hover-popup menu that opens when the cursor dwells
|
|
/// on a grip. The `label` is the user-visible string; `action` is the
|
|
/// operation the entity will perform when the item is committed.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct GripMenuItem {
|
|
pub label: &'static str,
|
|
pub action: GripMenuAction,
|
|
}
|
|
|
|
/// All operations a grip popup menu can dispatch. Entity-specific code
|
|
/// in `apply_grip_menu` decodes these into edits. `Stretch` is the
|
|
/// default no-op-equivalent — picking it just starts the regular
|
|
/// stretch drag, identical to clicking the grip with no popup open.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
#[allow(dead_code)]
|
|
pub enum GripMenuAction {
|
|
Stretch,
|
|
Lengthen,
|
|
Radius,
|
|
ArcLength,
|
|
RectangleWidth,
|
|
RectangleHeight,
|
|
RectangleResize,
|
|
MoveParallel,
|
|
AddVertex,
|
|
RemoveVertex,
|
|
ConvertToArc,
|
|
/// Split the polyline at this vertex (a closed one opens here; an open
|
|
/// one splits into two). Handled by the driver — it replaces the entity.
|
|
BreakVertex,
|
|
ConvertToLine,
|
|
StretchVertex,
|
|
AddLeader,
|
|
RemoveLeader,
|
|
ReverseArrows,
|
|
MoveWithDimLine,
|
|
MoveWithLeader,
|
|
MoveIndependent,
|
|
ResetText,
|
|
RotateText,
|
|
AboveDimLine,
|
|
Center,
|
|
OriginPoint,
|
|
HatchAngle,
|
|
HatchScale,
|
|
HatchPattern,
|
|
TangentDirection,
|
|
AddFitPoint,
|
|
RemoveFitPoint,
|
|
Refit,
|
|
RefineVertices,
|
|
ShowFit,
|
|
ShowControlVertices,
|
|
SectionPlane,
|
|
SectionSlice,
|
|
SectionBoundary,
|
|
SectionVolume,
|
|
MoveWithText,
|
|
StackText,
|
|
UnstackText,
|
|
}
|