1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
use dear_imguizmo::GuizmoExt;
use crate::camera::{Active as ActiveCamera, Camera};
use crate::data_types::dimens::Dimens3;
use crate::ecs::pair::ChildOf;
use crate::ecs::query::term::{Traverse, TraverseUp, With, Without};
use crate::ecs::sole::Single;
use crate::ecs::Query;
use crate::projection::ClipVolume as ProjectionClipVolume;
use crate::scene::{Active as ActiveScene, Scene};
use crate::transform::Transform;
use crate::ui::dear_imgui::{
Context as DearImguiContext,
TargetWindow as DearImguiTargetWindow,
};
use crate::vector::Vec3;
use crate::windowing::window::{Closed as WindowClosed, Window};
pub fn show(
subject_query: Query<(
&mut Transform,
Traverse<(With<Scene>, With<ActiveScene>), TraverseUp, ChildOf>,
Without<ActiveCamera>,
)>,
camera_query: Query<(
&Camera,
&Transform,
Traverse<(With<Scene>, With<ActiveScene>), TraverseUp, ChildOf>,
With<ActiveCamera>,
)>,
target_window_query: Query<(
&Window,
With<DearImguiTargetWindow>,
Without<WindowClosed>,
)>,
mut dear_imgui_context: Single<DearImguiContext>,
) -> Result<(), crate::Error>
{
let dear_imgui_context = dear_imgui_context.get_mut()?;
let Some(frame) = dear_imgui_context.frame() else {
return Ok(());
};
let Some((camera, camera_world_pos)) = camera_query.iter().next() else {
return Ok(());
};
let Some((target_window,)) = target_window_query.iter().next() else {
return Ok(());
};
let gizmo = frame.guizmo();
let [display_width, display_height] = frame.io().display_size();
gizmo.set_rect(0.0, 0.0, display_width, display_height);
// The widgets should appear under dear imgui windows
gizmo.set_drawlist_background();
let col_major_view = flatten_matrix(
camera
.to_view_matrix(camera_world_pos.position)
.to_column_major(),
);
let col_major_projection = flatten_matrix(
camera
.projection
.to_matrix_rh(target_window.inner_size, ProjectionClipVolume::NegOneToOne)
.to_column_major(),
);
for (subject_index, (mut subject_transform,)) in subject_query.iter().enumerate() {
let subject_index = match i32::try_from(subject_index) {
Ok(subject_index) => subject_index,
Err(err) => {
tracing::error!("Invalid subject index {subject_index}: {err}");
break;
}
};
// No rotation
let rotation = [0.0, 0.0, 0.0];
let mut col_major_model_mat = dear_imguizmo::recompose_matrix(
&subject_transform.position.into(),
&rotation,
&subject_transform.scale.into(),
);
let _id_token = gizmo.push_id(subject_index);
let used = gizmo
.manipulate_config(
&col_major_view,
&col_major_projection,
&mut col_major_model_mat,
)
.operation(
dear_imguizmo::Operation::TRANSLATE | dear_imguizmo::Operation::SCALE,
)
.mode(dear_imguizmo::Mode::World)
.build();
if used {
let (translation, _rotation, scale) =
dear_imguizmo::decompose_matrix(&col_major_model_mat);
subject_transform.position = Vec3::from(translation);
subject_transform.scale = Dimens3::from(scale);
}
}
Ok(())
}
fn flatten_matrix(mat: [[f32; 4]; 4]) -> [f32; 4 * 4]
{
let flattened = mat.as_flattened();
let Some(flattened) = flattened.as_array::<{ 4 * 4 }>() else {
unreachable!();
};
flattened.clone()
}
|