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, With), TraverseUp, ChildOf>, Without, )>, camera_query: Query<( &Camera, &Transform, Traverse<(With, With), TraverseUp, ChildOf>, With, )>, target_window_query: Query<( &Window, With, Without, )>, mut dear_imgui_context: Single, ) -> 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() }