diff --git a/src/app/block_actions.rs b/src/app/block_actions.rs index 86d0dc2bb..096e71f9e 100644 --- a/src/app/block_actions.rs +++ b/src/app/block_actions.rs @@ -242,12 +242,12 @@ impl OpenCADStudio { id: TEST_GRIP_START + index, world, is_midpoint: false, - shape: if p.flip { - crate::scene::model::object::GripShape::Square - } else { - crate::scene::model::object::GripShape::Triangle - }, - dir: None, + shape: crate::scene::model::object::GripShape::Triangle, + dir: actions::grip_direction(&p, value).and_then(|direction| { + (actions::v(transform.apply(actions::native(direction))) + - actions::v(transform.apply(codec::types::Vector3::ZERO))) + .try_normalize() + }), axis: None, }); } @@ -336,12 +336,12 @@ impl OpenCADStudio { id: TEST_GRIP_START + index, world, is_midpoint: false, - shape: if p.flip { - crate::scene::model::object::GripShape::Square - } else { - crate::scene::model::object::GripShape::Triangle - }, - dir: None, + shape: crate::scene::model::object::GripShape::Triangle, + dir: actions::grip_direction(&p, value).and_then(|direction| { + (actions::v(transform.apply(actions::native(direction))) + - actions::v(transform.apply(codec::types::Vector3::ZERO))) + .try_normalize() + }), axis: None, }); } diff --git a/src/app/block_editor_tests.rs b/src/app/block_editor_tests.rs index b23de5435..75316765c 100644 --- a/src/app/block_editor_tests.rs +++ b/src/app/block_editor_tests.rs @@ -270,12 +270,34 @@ fn block_actions_rotate_flip_mouse_grips_authoring_history_and_reopen() { app.tabs[i].scene.selected.insert(insert); app.refresh_properties(); let depth = app.tabs[i].history.undo_stack.len(); + let flip_grip = app.tabs[i] + .selected_grips + .iter() + .find(|g| { + super::block_actions::is_test_grip(g.id) && g.world.distance(flip.reference) < 1e-5 + }) + .unwrap(); + assert_eq!( + flip_grip.shape, + crate::scene::model::object::GripShape::Triangle + ); + assert!(flip_grip.dir.unwrap().distance(glam::DVec3::Y) < 1e-5); click(&mut app, flip.reference); assert!( app.tabs[i].active_cmd.is_none(), "Flip toggles immediately without point input" ); check(&app, insert, -Vector3::UNIT_Y); + app.tabs[i].scene.selected.insert(insert); + app.refresh_properties(); + let flip_grip = app.tabs[i] + .selected_grips + .iter() + .find(|g| { + super::block_actions::is_test_grip(g.id) && g.world.distance(flip.reference) < 1e-5 + }) + .unwrap(); + assert!(flip_grip.dir.unwrap().distance(-glam::DVec3::Y) < 1e-5); assert_eq!(app.tabs[i].history.undo_stack.len(), depth + 1); app.undo_steps(1); check(&app, insert, Vector3::UNIT_Y); diff --git a/src/scene/block_actions.rs b/src/scene/block_actions.rs index 76160baf1..ca01b0c22 100644 --- a/src/scene/block_actions.rs +++ b/src/scene/block_actions.rs @@ -172,6 +172,15 @@ pub(crate) fn grip_position(p: &Parameter, value: Value) -> DVec3 { } } +/// A Flip arrow points across its reflection line and reverses with its state. +pub(crate) fn grip_direction(p: &Parameter, value: Value) -> Option { + let Value::Flip(flipped) = value else { + return None; + }; + let across = DVec3::Z.cross(p.end - p.base).try_normalize()?; + Some(if flipped { -across } else { across }) +} + pub(crate) fn parameters(doc: &CadDocument, definition: Handle, kind: Kind) -> Vec { let Ok(Some(graph)) = authoring::graph(doc, definition) else { return vec![];