@@ -1030,6 +1030,23 @@ pub fn vpeol_3d_camera_mode_selector(
10301030#[ cfg_attr( feature = "bevy_reflect" , derive( bevy:: reflect:: Reflect ) ) ]
10311031pub struct Vpeol3dPosition ( pub Vec3 ) ;
10321032
1033+ /// Add this to an entity with [`Vpeol3dPosition`] to force it to be on a specific plane while
1034+ /// editing.
1035+ ///
1036+ /// This is useful for 2D games that use 3D graphics but don't want to allow free positioning of
1037+ /// entities on all axes.
1038+ ///
1039+ /// Note that this is not a [`YoleckComponent`]. Do not add it with
1040+ /// [`insert_on_init_during_editor`](YoleckEntityType::with). The best way to add it is by using
1041+ /// [`insert_on_init_during_editor`](YoleckEntityType::insert_on_init_during_editor) which also
1042+ /// allows setting the data.
1043+ #[ derive( Component ) ]
1044+ pub struct Vpeol3dSnapToPlane {
1045+ pub normal : Dir3 ,
1046+ /// Offset of the plane from the origin of axes
1047+ pub offset : f32 ,
1048+ }
1049+
10331050#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
10341051pub enum Vpeol3dTranslationGizmoMode {
10351052 World ,
@@ -1113,7 +1130,12 @@ impl CommonDragPlane {
11131130
11141131fn vpeol_3d_edit_transform_group (
11151132 mut ui : ResMut < YoleckUi > ,
1116- position_edit : YoleckEdit < ( Entity , & mut Vpeol3dPosition , Option < & VpeolDragPlane > ) > ,
1133+ position_edit : YoleckEdit < (
1134+ Entity ,
1135+ & mut Vpeol3dPosition ,
1136+ Option < & VpeolDragPlane > ,
1137+ Option < & Vpeol3dSnapToPlane > ,
1138+ ) > ,
11171139 rotation_edit : YoleckEdit < & mut Vpeol3dRotation > ,
11181140 scale_edit : YoleckEdit < & mut Vpeol3dScale > ,
11191141 global_drag_plane : Res < VpeolDragPlane > ,
@@ -1136,7 +1158,12 @@ fn vpeol_3d_edit_transform_group(
11361158
11371159fn vpeol_3d_edit_position_impl (
11381160 ui : & mut egui:: Ui ,
1139- mut edit : YoleckEdit < ( Entity , & mut Vpeol3dPosition , Option < & VpeolDragPlane > ) > ,
1161+ mut edit : YoleckEdit < (
1162+ Entity ,
1163+ & mut Vpeol3dPosition ,
1164+ Option < & VpeolDragPlane > ,
1165+ Option < & Vpeol3dSnapToPlane > ,
1166+ ) > ,
11401167 global_drag_plane : & VpeolDragPlane ,
11411168 passed_data : & YoleckPassedData ,
11421169) {
@@ -1149,7 +1176,7 @@ fn vpeol_3d_edit_position_impl(
11491176
11501177 let mut common_drag_plane = CommonDragPlane :: NotDecidedYet ;
11511178
1152- for ( entity, position, drag_plane) in edit. iter_matching ( ) {
1179+ for ( entity, position, drag_plane, _ ) in edit. iter_matching ( ) {
11531180 let VpeolDragPlane ( drag_plane) = drag_plane. unwrap_or ( global_drag_plane) ;
11541181 common_drag_plane. consider ( * drag_plane. normal ) ;
11551182
@@ -1180,8 +1207,12 @@ fn vpeol_3d_edit_position_impl(
11801207 } ) ;
11811208
11821209 if transition. is_finite ( ) && transition != Vec3 :: ZERO {
1183- for ( _, mut position, _) in edit. iter_matching_mut ( ) {
1210+ for ( _, mut position, _, snap ) in edit. iter_matching_mut ( ) {
11841211 position. 0 += transition;
1212+ if let Some ( snap) = snap {
1213+ let displacement = position. 0 . project_onto ( * snap. normal ) ;
1214+ position. 0 += snap. offset * snap. normal - displacement;
1215+ }
11851216 }
11861217 }
11871218}
0 commit comments