From 1e33a9049c8fe7a1d69a133fda936fb9b358e131 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Fri, 29 May 2026 01:46:33 +0300 Subject: [PATCH] feat(grip): complete standard grip-shape vocabulary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Existing entity grip definitions already followed the conventional CAD layout: square at vertices / endpoints, diamond at curve centres / midpoints, triangle for directional control. Round out the supported shape vocabulary with the two missing standards so future entities (polyline straight-segment stretch grips, dimension parameter grips, …) can pick the right marker without inventing ad-hoc visuals: - `GripShape::Rectangle` — direction-aware mid-segment stretch handle (wider-than-tall box). - `GripShape::Circle` — parametric control (radius / dimension value). New `rectangle_grip` / `circle_grip` helpers in `entities::common` mirror the existing `square_grip` / `diamond_grip` / `triangle_grip` constructors. `SelectionCanvas::draw` renders the two new variants; the previously-used Square / Diamond / Triangle paths are unchanged. Both new variants carry `#[allow(dead_code)]` until an entity adopts them. --- src/entities/common.rs | 20 ++++++++++++++++++++ src/scene/object.rs | 13 ++++++++++++- src/ui/overlay.rs | 11 +++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/entities/common.rs b/src/entities/common.rs index 8148ed480..c9f98d3ec 100644 --- a/src/entities/common.rs +++ b/src/entities/common.rs @@ -148,6 +148,26 @@ pub fn triangle_grip(id: usize, world: Vec3) -> GripDef { } } +#[allow(dead_code)] +pub fn rectangle_grip(id: usize, world: Vec3) -> GripDef { + GripDef { + id, + world, + is_midpoint: true, + shape: GripShape::Rectangle, + } +} + +#[allow(dead_code)] +pub fn circle_grip(id: usize, world: Vec3) -> GripDef { + GripDef { + id, + world, + is_midpoint: false, + shape: GripShape::Circle, + } +} + pub fn edit_prop(label: &'static str, field: &'static str, value: f64) -> Property { Property { label: label.into(), diff --git a/src/scene/object.rs b/src/scene/object.rs index eda343a20..e71f2eeb4 100644 --- a/src/scene/object.rs +++ b/src/scene/object.rs @@ -51,12 +51,23 @@ pub struct PropSection { // ── Grip types ───────────────────────────────────────────────────────────── -/// Describes one grip point for an entity. +/// Visual marker shape for a grip point. The complete vocabulary used +/// across entity types: +/// * `Square` — vertex / endpoint that moves a single point. +/// * `Rectangle` — direction-aware mid-segment stretch (polyline +/// straight segments, dimension extension lines). +/// * `Diamond` — midpoint of a curve / centre of a closed shape (drags +/// the whole shape or stretches the midpoint). +/// * `Triangle` — directional control (rotate / add vertex / continue). +/// * `Circle` — parametric control (radius / dimension value). #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[allow(dead_code)] pub enum GripShape { Square, + Rectangle, Diamond, Triangle, + Circle, } /// Describes one grip point for an entity. diff --git a/src/ui/overlay.rs b/src/ui/overlay.rs index f20835cb8..3d6897c3a 100644 --- a/src/ui/overlay.rs +++ b/src/ui/overlay.rs @@ -423,6 +423,16 @@ impl canvas::Program for SelectionCanvas { Point::new(sp.x - h, sp.y - h), Size::new(h * 2.0, h * 2.0), ), + GripShape::Rectangle => { + // Wider-than-tall box — direction-aware mid-segment + // stretch handle. + let w = h * 1.4; + let t = h * 0.7; + canvas::Path::rectangle( + Point::new(sp.x - w, sp.y - t), + Size::new(w * 2.0, t * 2.0), + ) + } GripShape::Diamond => canvas::Path::new(|b| { b.move_to(Point::new(sp.x, sp.y - h)); b.line_to(Point::new(sp.x + h, sp.y)); @@ -436,6 +446,7 @@ impl canvas::Program for SelectionCanvas { b.line_to(Point::new(sp.x - h, sp.y + h)); b.close(); }), + GripShape::Circle => canvas::Path::circle(sp, h), }; if grip.is_hot {