feat(grip): popup menus for polylines, spline, mline, hatch, leaders, text
Vocabulary added: AddFitPoint, RemoveFitPoint, Refit, RefineVertices, TangentDirection, MoveWithText, StackText, UnstackText. Polyline/Polyline2D/Polyline3D: vertex Add/Remove. MLine: same. Spline: CV Add/Remove plus Refine Vertices (chord-midpoint insertion, weights kept in sync, knots cleared so to_truck rebuilds uniform vec). Hatch: centroid Origin/Angle/Scale (Angle and Scale prompt for value). Leader: vertex Add/Remove (arrow + centroid stay Stretch-only). MultiLeader: vertex Add/Remove Leader; MText location Move-with-Leader / Move-Independent (menu live, structural edits stubbed). Text/MText: Rotate prompts for degrees and sets rotation. Spline, Leader, MultiLeader switched from impl_entity_basics! to manual trait impls so grip_menu can be overridden. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
559cd76369
commit
4b4fe5ca6d
9 changed files with 580 additions and 3 deletions
|
|
@ -73,6 +73,50 @@ impl Grippable for Polyline {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn grip_menu(
|
||||
&self,
|
||||
_grip_id: usize,
|
||||
) -> Vec<crate::scene::object::GripMenuItem> {
|
||||
use crate::scene::object::{GripMenuAction, GripMenuItem};
|
||||
vec![
|
||||
GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch },
|
||||
GripMenuItem { label: "Add Vertex", action: GripMenuAction::AddVertex },
|
||||
GripMenuItem { label: "Remove Vertex", action: GripMenuAction::RemoveVertex },
|
||||
]
|
||||
}
|
||||
|
||||
fn apply_grip_menu(
|
||||
&mut self,
|
||||
grip_id: usize,
|
||||
action: crate::scene::object::GripMenuAction,
|
||||
) {
|
||||
use crate::scene::object::GripMenuAction as A;
|
||||
let n = self.vertices.len();
|
||||
match action {
|
||||
A::AddVertex if grip_id < n => {
|
||||
let i1 = (grip_id + 1) % n;
|
||||
if i1 == 0 && grip_id + 1 == n {
|
||||
return;
|
||||
}
|
||||
let v0 = &self.vertices[grip_id];
|
||||
let v1 = &self.vertices[i1];
|
||||
let mx = (v0.location.x + v1.location.x) * 0.5;
|
||||
let my = (v0.location.y + v1.location.y) * 0.5;
|
||||
let mz = (v0.location.z + v1.location.z) * 0.5;
|
||||
let mut new_v = v0.clone();
|
||||
new_v.location.x = mx;
|
||||
new_v.location.y = my;
|
||||
new_v.location.z = mz;
|
||||
let insert_at = (grip_id + 1).min(self.vertices.len());
|
||||
self.vertices.insert(insert_at, new_v);
|
||||
}
|
||||
A::RemoveVertex if grip_id < n && n > 2 => {
|
||||
self.vertices.remove(grip_id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyEditable for Polyline {
|
||||
|
|
@ -300,6 +344,50 @@ impl Grippable for Polyline2D {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn grip_menu(
|
||||
&self,
|
||||
_grip_id: usize,
|
||||
) -> Vec<crate::scene::object::GripMenuItem> {
|
||||
use crate::scene::object::{GripMenuAction, GripMenuItem};
|
||||
vec![
|
||||
GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch },
|
||||
GripMenuItem { label: "Add Vertex", action: GripMenuAction::AddVertex },
|
||||
GripMenuItem { label: "Remove Vertex", action: GripMenuAction::RemoveVertex },
|
||||
]
|
||||
}
|
||||
|
||||
fn apply_grip_menu(
|
||||
&mut self,
|
||||
grip_id: usize,
|
||||
action: crate::scene::object::GripMenuAction,
|
||||
) {
|
||||
use crate::scene::object::GripMenuAction as A;
|
||||
let n = self.vertices.len();
|
||||
let elev = self.elevation;
|
||||
match action {
|
||||
A::AddVertex if grip_id < n => {
|
||||
let i1 = (grip_id + 1) % n;
|
||||
if i1 == 0 && grip_id + 1 == n {
|
||||
return;
|
||||
}
|
||||
let v0 = &self.vertices[grip_id];
|
||||
let v1 = &self.vertices[i1];
|
||||
let mx = (v0.location.x + v1.location.x) * 0.5;
|
||||
let my = (v0.location.y + v1.location.y) * 0.5;
|
||||
let mut new_v = v0.clone();
|
||||
new_v.location.x = mx;
|
||||
new_v.location.y = my;
|
||||
new_v.location.z = elev;
|
||||
let insert_at = (grip_id + 1).min(self.vertices.len());
|
||||
self.vertices.insert(insert_at, new_v);
|
||||
}
|
||||
A::RemoveVertex if grip_id < n && n > 2 => {
|
||||
self.vertices.remove(grip_id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyEditable for Polyline2D {
|
||||
|
|
@ -473,6 +561,50 @@ impl Grippable for Polyline3D {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn grip_menu(
|
||||
&self,
|
||||
_grip_id: usize,
|
||||
) -> Vec<crate::scene::object::GripMenuItem> {
|
||||
use crate::scene::object::{GripMenuAction, GripMenuItem};
|
||||
vec![
|
||||
GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch },
|
||||
GripMenuItem { label: "Add Vertex", action: GripMenuAction::AddVertex },
|
||||
GripMenuItem { label: "Remove Vertex", action: GripMenuAction::RemoveVertex },
|
||||
]
|
||||
}
|
||||
|
||||
fn apply_grip_menu(
|
||||
&mut self,
|
||||
grip_id: usize,
|
||||
action: crate::scene::object::GripMenuAction,
|
||||
) {
|
||||
use crate::scene::object::GripMenuAction as A;
|
||||
let n = self.vertices.len();
|
||||
match action {
|
||||
A::AddVertex if grip_id < n => {
|
||||
let i1 = (grip_id + 1) % n;
|
||||
if i1 == 0 && grip_id + 1 == n {
|
||||
return;
|
||||
}
|
||||
let v0 = &self.vertices[grip_id];
|
||||
let v1 = &self.vertices[i1];
|
||||
let mx = (v0.position.x + v1.position.x) * 0.5;
|
||||
let my = (v0.position.y + v1.position.y) * 0.5;
|
||||
let mz = (v0.position.z + v1.position.z) * 0.5;
|
||||
let mut new_v = v0.clone();
|
||||
new_v.position.x = mx;
|
||||
new_v.position.y = my;
|
||||
new_v.position.z = mz;
|
||||
let insert_at = (grip_id + 1).min(self.vertices.len());
|
||||
self.vertices.insert(insert_at, new_v);
|
||||
}
|
||||
A::RemoveVertex if grip_id < n && n > 2 => {
|
||||
self.vertices.remove(grip_id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyEditable for Polyline3D {
|
||||
|
|
|
|||
Loading…
Reference in a new issue