feat(blocks): wire Rotate and Flip actions and saved reference grips

Author Rotate actions against Rotation parameters and Flip actions against Flip
parameters through the existing palette, BACTION selection flow and native
evaluation graph. Keep markers selectable and editable in BEDIT.

Rotation grips accept a new direction at the original radius. Flip grips toggle
immediately. Evaluate both from immutable definition geometry in Test Block and
independent drawing references, preserving per-INSERT angle/state caches across
DWG/DXF saves and COPY. Undo/redo includes the native state and representation.
Accept parameter names containing spaces at the action parameter prompt.

332 block regressions pass (6 existing opt-in checks ignored), including native
binding/marker roundtrips, composed rotation/flip, repeated reversible toggles,
COPY isolation, viewport mouse interactions, history and saved-reference reopen.
Custom base modes, constrained/chained evaluation and parameter-target actions
remain unsupported; Rotate currently binds Rotation parameters.
This commit is contained in:
Karim Jerbi committed 2026-10-17 09:15:37 +01:00
1 parent f67f2cf4f5
commit de7ed432fb
11 files changed
+922 -98

No files matched your search

+11 -5
View File
@@ -196,6 +196,8 @@ fn catalog(
lookup_error: Option<&'static str>,
move_error: Option<&'static str>,
scale_error: Option<&'static str>,
rotate_error: Option<&'static str>,
flip_action_error: Option<&'static str>,
) -> Element<'static, Message> {
let (entries, unavailable) = match tab {
Tab::Parameters => (
@@ -217,8 +219,8 @@ fn catalog(
let orientation_error = if *label=="Flip" {flip_error} else {point_error};
let single=tab==Tab::Parameters&&matches!(*label,"Lookup"|"Basepoint");
let lookup_action=tab==Tab::Actions&&*label=="Lookup";
let geometry_action=tab==Tab::Actions&&matches!(*label,"Move"|"Scale");
let action_error=if *label=="Scale" {scale_error}else{move_error};
let geometry_action=tab==Tab::Actions&&matches!(*label,"Move"|"Scale"|"Rotate"|"Flip");
let action_error=match *label {"Scale"=>scale_error,"Rotate"=>rotate_error,"Flip"=>flip_action_error,_=>move_error};
let enabled = (geometry_action&&action_error.is_none())||(single&&point_error.is_none())||(lookup_action&&lookup_error.is_none())||(orientation && orientation_error.is_none()) || (visibility && visibility_error.is_none()) || ((point || distance) && point_error.is_none());
let base = if enabled {
icons::semantic(icon, 28.0)
@@ -264,7 +266,7 @@ fn catalog(
} else if single {
crate::t!(point_error.unwrap_or(if *label=="Basepoint" {"Place or relocate the dynamic block insertion anchor."}else{"Place a Lookup parameter, then use the Lookup action to edit its property table."})).into_owned()
} else if geometry_action {
crate::t!(action_error.unwrap_or("Select a parameter endpoint, select the objects it controls, then place the action marker. Test it using the parameter grip in Test Block.")).into_owned()
crate::t!(action_error.unwrap_or("Select a parameter endpoint, select the objects it controls, then place the action marker. Use the reference parameter grip in the drawing or Test Block.")).into_owned()
} else if lookup_action {
crate::t!(lookup_error.unwrap_or("Create or edit property Lookup tables for this block.")).into_owned()
} else {
@@ -282,7 +284,7 @@ fn catalog(
} else if single {
container(entry).id(if *label=="Lookup" {"authoring-tool-lookup"}else{"authoring-tool-basepoint"}).into()
} else if geometry_action {
container(entry).id(if *label=="Move" {"authoring-tool-move-action"}else{"authoring-tool-scale-action"}).into()
container(entry).id(match *label {"Move"=>"authoring-tool-move-action","Scale"=>"authoring-tool-scale-action","Rotate"=>"authoring-tool-rotate-action",_=>"authoring-tool-flip-action"}).into()
} else if lookup_action {
container(entry).id("authoring-tool-lookup-table").into()
} else {
@@ -401,6 +403,8 @@ pub fn view(
lookup_error: Option<&'static str>,
move_error: Option<&'static str>,
scale_error: Option<&'static str>,
rotate_error: Option<&'static str>,
flip_action_error: Option<&'static str>,
) -> Element<'static, Message> {
let tabs = column(Tab::ALL.into_iter().map(|category| {
let label = category.label();
@@ -457,7 +461,9 @@ pub fn view(
flip_error,
lookup_error,
move_error,
scale_error
scale_error,
rotate_error,
flip_action_error
))
.width(Fill)
.height(Fill),