use super::context::EditorContext;
use crate::prelude::*;
#[derive(Clone, Copy, PartialEq)]
pub enum CameraView {
Front,
Back,
Right,
Left,
Top,
Bottom,
}
pub fn set_camera_view(world: &mut World, view: CameraView) {
let Some(camera_entity) = world.resources.active_camera else {
return;
};
let Some(pan_orbit) = world.get_pan_orbit_camera_mut(camera_entity) else {
return;
};
let (yaw, pitch) = match view {
CameraView::Front => (0.0, 0.0),
CameraView::Back => (std::f32::consts::PI, 0.0),
CameraView::Right => (std::f32::consts::FRAC_PI_2, 0.0),
CameraView::Left => (-std::f32::consts::FRAC_PI_2, 0.0),
CameraView::Top => (0.0, std::f32::consts::FRAC_PI_2 - 0.001),
CameraView::Bottom => (0.0, -(std::f32::consts::FRAC_PI_2 - 0.001)),
};
pan_orbit.target_yaw = yaw;
pan_orbit.target_pitch = pitch;
}
pub fn focus_on_selection(context: &EditorContext, world: &mut World) {
if context.selection.is_empty() {
return;
}
let mut center = Vec3::zeros();
let mut count = 0u32;
let mut max_radius = 0.0_f32;
for &entity in context.selection.iter() {
let Some(global_transform) = world.get_global_transform(entity) else {
continue;
};
let position = nalgebra_glm::vec3(
global_transform.0.column(3).x,
global_transform.0.column(3).y,
global_transform.0.column(3).z,
);
center += position;
count += 1;
if let Some(bounding) = world.get_bounding_volume(entity) {
max_radius = max_radius.max(bounding.sphere_radius);
}
}
if count == 0 {
return;
}
center /= count as f32;
let mut extent = max_radius;
for &entity in context.selection.iter() {
if let Some(global_transform) = world.get_global_transform(entity) {
let position = nalgebra_glm::vec3(
global_transform.0.column(3).x,
global_transform.0.column(3).y,
global_transform.0.column(3).z,
);
let distance = nalgebra_glm::length(&(position - center));
extent = extent.max(distance);
}
}
let Some(camera_entity) = world.resources.active_camera else {
return;
};
let Some(pan_orbit) = world.get_pan_orbit_camera_mut(camera_entity) else {
return;
};
pan_orbit.target_focus = center;
pan_orbit.target_radius = (extent * 2.5).max(2.0);
}
pub fn toggle_camera_orthographic(world: &mut World) {
use crate::ecs::camera::components::{OrthographicCamera, PerspectiveCamera};
let Some(camera_entity) = world.resources.active_camera else {
return;
};
let camera_distance = world
.get_pan_orbit_camera(camera_entity)
.map(|orbit| orbit.radius)
.unwrap_or(10.0);
let Some(camera) = world.get_camera_mut(camera_entity) else {
return;
};
camera.projection = match &camera.projection {
Projection::Perspective(persp) => {
let half_height = camera_distance * (persp.y_fov_rad * 0.5).tan();
let aspect = persp.aspect_ratio.unwrap_or(16.0 / 9.0);
let half_width = half_height * aspect;
Projection::Orthographic(OrthographicCamera {
x_mag: half_width,
y_mag: half_height,
z_near: persp.z_near,
z_far: persp.z_far.unwrap_or(1000.0),
})
}
Projection::Orthographic(ortho) => Projection::Perspective(PerspectiveCamera {
y_fov_rad: 45.0_f32.to_radians(),
aspect_ratio: None,
z_near: ortho.z_near,
z_far: Some(ortho.z_far),
}),
};
}
pub fn is_mouse_in_selected_viewport(world: &World) -> bool {
if let Some(viewport_rect) = &world.resources.window.active_viewport_rect {
let mouse_pos = world.resources.input.mouse.position;
return viewport_rect.contains(mouse_pos);
}
true
}