1
1
use bevy:: {
2
- ecs:: query:: QueryFilter ,
2
+ ecs:: { query:: QueryFilter , system :: RunSystemOnce } ,
3
3
prelude:: * ,
4
4
render:: { camera:: CameraProjection , view:: RenderLayers } ,
5
5
} ;
6
6
7
7
use bevy_editor_pls_core:: editor_window:: { EditorWindow , EditorWindowContext } ;
8
8
use bevy_inspector_egui:: { bevy_inspector:: hierarchy:: SelectedEntities , egui} ;
9
- use egui_gizmo:: GizmoMode ;
9
+ use transform_gizmo_bevy:: { EnumSet , GizmoMode } ;
10
+ use transform_gizmo_bevy:: GizmoTarget ;
10
11
11
12
use crate :: {
12
13
cameras:: { ActiveEditorCamera , CameraWindow , EditorCamera , EDITOR_RENDER_LAYER } ,
@@ -15,14 +16,15 @@ use crate::{
15
16
16
17
pub struct GizmoState {
17
18
pub camera_gizmo_active : bool ,
18
- pub gizmo_mode : GizmoMode ,
19
+ /// TODO: Take these settings into account
20
+ pub gizmo_mode : EnumSet < GizmoMode > ,
19
21
}
20
22
21
23
impl Default for GizmoState {
22
24
fn default ( ) -> Self {
23
25
Self {
24
26
camera_gizmo_active : true ,
25
- gizmo_mode : GizmoMode :: Translate ,
27
+ gizmo_mode : GizmoMode :: all_translate ( ) ,
26
28
}
27
29
}
28
30
}
@@ -42,10 +44,62 @@ impl EditorWindow for GizmoWindow {
42
44
let gizmo_state = cx. state :: < GizmoWindow > ( ) . unwrap ( ) ;
43
45
44
46
if gizmo_state. camera_gizmo_active {
45
- if let ( Some ( hierarchy_state) , Some ( _camera_state) ) =
46
- ( cx. state :: < HierarchyWindow > ( ) , cx. state :: < CameraWindow > ( ) )
47
- {
48
- draw_gizmo ( ui, world, & hierarchy_state. selected , gizmo_state. gizmo_mode ) ;
47
+ // if let (Some(hierarchy_state), Some(_camera_state)) =
48
+ // (cx.state::<HierarchyWindow>(), cx.state::<CameraWindow>())
49
+ // {
50
+ // draw_gizmo(ui, world, &hierarchy_state.selected, gizmo_state.gizmo_mode);
51
+ // }
52
+
53
+ /// Before [hydrate_gizmos] and [deconstruct_gizmos] are run, this system resets the state of all entities that have a [EntityShouldShowGizmo] component.
54
+ /// Then, according to selection logic some entities are marked as focussed, and [hydrate_gizmos] and [deconstruct_gizmos] is run to sync the gizmo state with the selection state.
55
+ fn reset_gizmos_selected_state (
56
+ mut commands : Commands ,
57
+ entities : Query < Entity , With < EntityShouldShowGizmo > > ,
58
+ ) {
59
+ for entity in entities. iter ( ) {
60
+ commands. entity ( entity) . remove :: < EntityShouldShowGizmo > ( ) ;
61
+ }
62
+ }
63
+
64
+ /// Takes all entities marked with [EntityShouldShowGizmo] and adds the [GizmoTarget] component to them.
65
+ fn hydrate_gizmos (
66
+ mut commands : Commands ,
67
+ entities : Query < Entity , ( With < EntityShouldShowGizmo > , Without < GizmoTarget > ) > ,
68
+ ) {
69
+ for entity in entities. iter ( ) {
70
+ trace ! ( "Hydrating a gizmo on entity {:?} because it is selected" , entity) ;
71
+ // TODO: Maybe change the exact gizmo target instance instead of using default? should this load from some config?
72
+ commands. entity ( entity) . insert ( GizmoTarget :: default ( ) ) ;
73
+ }
74
+ }
75
+
76
+ /// Takes all entities that should have their [GizmoTarget] removed because they are no longer selected.
77
+ fn deconstruct_gizmos (
78
+ mut commands : Commands ,
79
+ entities : Query < Entity , ( With < GizmoTarget > , Without < EntityShouldShowGizmo > ) > ,
80
+ ) {
81
+ for entity in entities. iter ( ) {
82
+ commands. entity ( entity) . remove :: < GizmoTarget > ( ) ;
83
+ debug ! (
84
+ "Removing GizmoTarget from entity {:?} because it has lost focus" ,
85
+ entity
86
+ ) ;
87
+ }
88
+ }
89
+
90
+ if let Some ( hierarchy_state) = cx. state :: < HierarchyWindow > ( ) {
91
+ // here should assign the `EntityShouldShowGizmo` component, which is later synced
92
+ // with the actual gizmo ui system
93
+
94
+ world. run_system_once ( reset_gizmos_selected_state) ;
95
+
96
+ let selected_entities = hierarchy_state. selected . iter ( ) ;
97
+ for entity in selected_entities {
98
+ world. entity_mut ( entity) . insert ( EntityShouldShowGizmo ) ;
99
+ }
100
+
101
+ world. run_system_once ( hydrate_gizmos) ;
102
+ world. run_system_once ( deconstruct_gizmos) ;
49
103
}
50
104
}
51
105
}
@@ -93,9 +147,15 @@ struct GizmoMarkerConfig {
93
147
camera_material : Handle < StandardMaterial > ,
94
148
}
95
149
150
+ /// can somebody document what this does? is it a duplicate of [EntityShouldShowGizmo]?
96
151
#[ derive( Component ) ]
97
152
struct HasGizmoMarker ;
98
153
154
+ /// When on an entity, this entity should be controllable using some sort of user gizmo.
155
+ /// Currently uses [transform_gizmo_bevy], and puts the [GizmoTarget] on the entity.
156
+ #[ derive( Component ) ]
157
+ struct EntityShouldShowGizmo ;
158
+
99
159
type GizmoMarkerQuery < ' w , ' s , T , F = ( ) > =
100
160
Query < ' w , ' s , Entity , ( With < T > , Without < HasGizmoMarker > , F ) > ;
101
161
@@ -166,55 +226,59 @@ fn add_gizmo_markers(
166
226
}
167
227
}
168
228
169
- fn draw_gizmo (
170
- ui : & mut egui:: Ui ,
171
- world : & mut World ,
172
- selected_entities : & SelectedEntities ,
173
- gizmo_mode : GizmoMode ,
174
- ) {
175
- let Ok ( ( cam_transform , projection ) ) = world
176
- . query_filtered :: < ( & GlobalTransform , & Projection ) , With < ActiveEditorCamera > > ( )
177
- . get_single ( world )
178
- else {
179
- return ;
180
- } ;
181
- let view_matrix = Mat4 :: from ( cam_transform . affine ( ) . inverse ( ) ) ;
182
- let projection_matrix = projection . get_projection_matrix ( ) ;
183
-
184
- if selected_entities . len ( ) != 1 {
185
- return ;
186
- }
229
+ // fn draw_gizmo(
230
+ // ui: &mut egui::Ui,
231
+ // world: &mut World,
232
+ // selected_entities: &SelectedEntities,
233
+ // gizmo_mode: GizmoMode,
234
+ // ) {
235
+ // for entity in selected_entities.iter() {
236
+ // world.entity_mut(entity).insert(transform_gizmo_bevy::GizmoTarget::default());
237
+ // info!("Inserted GizmoTarget to entity: {:?}", entity);
238
+ // }
239
+ // // let Ok((cam_transform, projection)) = world
240
+ // // .query_filtered::<(&GlobalTransform, &Projection), With<ActiveEditorCamera>>()
241
+ // // .get_single(world)
242
+ // // else {
243
+ // // return;
244
+ // // };
245
+ // // let view_matrix = Mat4::from(cam_transform.affine().inverse()) ;
246
+ // // let projection_matrix = projection.get_projection_matrix();
187
247
188
- for selected in selected_entities. iter ( ) {
189
- let Some ( global_transform) = world. get :: < GlobalTransform > ( selected) else {
190
- continue ;
191
- } ;
192
- let model_matrix = global_transform. compute_matrix ( ) ;
193
-
194
- let Some ( result) = egui_gizmo:: Gizmo :: new ( selected)
195
- . model_matrix ( model_matrix. into ( ) )
196
- . view_matrix ( view_matrix. into ( ) )
197
- . projection_matrix ( projection_matrix. into ( ) )
198
- . orientation ( egui_gizmo:: GizmoOrientation :: Local )
199
- . mode ( gizmo_mode)
200
- . interact ( ui)
201
- else {
202
- continue ;
203
- } ;
204
-
205
- let global_affine = global_transform. affine ( ) ;
206
-
207
- let mut transform = world. get_mut :: < Transform > ( selected) . unwrap ( ) ;
208
-
209
- let parent_affine = global_affine * transform. compute_affine ( ) . inverse ( ) ;
210
- let inverse_parent_transform = GlobalTransform :: from ( parent_affine. inverse ( ) ) ;
211
-
212
- let global_transform = Transform {
213
- translation : result. translation . into ( ) ,
214
- rotation : result. rotation . into ( ) ,
215
- scale : result. scale . into ( ) ,
216
- } ;
217
-
218
- * transform = ( inverse_parent_transform * global_transform) . into ( ) ;
219
- }
220
- }
248
+ // // if selected_entities.len() != 1 {
249
+ // // return;
250
+ // // }
251
+
252
+ // // for selected in selected_entities.iter() {
253
+ // // // let Some(global_transform) = world.get::<GlobalTransform>(selected) else {
254
+ // // // continue;
255
+ // // // };
256
+ // // // let model_matrix = global_transform.compute_matrix();
257
+
258
+ // // // let Some(result) = transform_gizmo_bevy::Gizmo::new(selected)
259
+ // // // .model_matrix(model_matrix.into())
260
+ // // // .view_matrix(view_matrix.into())
261
+ // // // .projection_matrix(projection_matrix.into())
262
+ // // // .orientation(transform_gizmo_bevy::GizmoOrientation::Local)
263
+ // // // .mode(gizmo_mode)
264
+ // // // .interact(ui)
265
+ // // // else {
266
+ // // // continue;
267
+ // // // };
268
+
269
+ // // // let global_affine = global_transform.affine();
270
+
271
+ // // // let mut transform = world.get_mut::<Transform>(selected).unwrap();
272
+
273
+ // // // let parent_affine = global_affine * transform.compute_affine().inverse();
274
+ // // // let inverse_parent_transform = GlobalTransform::from(parent_affine.inverse());
275
+
276
+ // // // let global_transform = Transform {
277
+ // // // translation: result.translation.into(),
278
+ // // // rotation: result.rotation.into(),
279
+ // // // scale: result.scale.into(),
280
+ // // // };
281
+
282
+ // // // *transform = (inverse_parent_transform * global_transform).into();
283
+ // // }
284
+ // }
0 commit comments