use super::*;
use crate::components::{Camera3D, Transform};
use framing::CameraPose;
const GLIDE_SECS: f32 = 0.25;
pub(super) struct CameraGlide {
pub(super) from: CameraPose,
pub(super) to: CameraPose,
pub(super) start: std::time::Instant,
}
impl EditorHook {
pub(super) fn selection_bounds(&self, world: &World) -> Option<([f32; 3], [f32; 3])> {
let index = world.resource::<crate::ecs::PickIndex>();
let boxes = self.selection.iter().filter_map(|name| {
let id = crate::ecs::asset_id::lookup(name)?;
if let Some(e) = index.and_then(|i| i.entries.iter().find(|e| e.asset_id == id)) {
return Some((e.bb_min, e.bb_max));
}
let entity = billboard_drive::entity_by_name(world, name)?;
Some(framing::pad_point(world.get::<Transform>(entity)?.position))
});
framing::union_bounds(boxes)
}
pub(super) fn frame_selection(&mut self, vp: [f32; 2], world: &World) {
let Some((mn, mx)) = self.selection_bounds(world) else {
return;
};
let Some(cam) = world.query::<Camera3D>().next() else {
return;
};
let aspect = if vp[1] > 0.0 { vp[0] / vp[1] } else { 1.0 };
let current = CameraPose {
position: cam.position,
yaw: cam.yaw,
pitch: cam.pitch,
};
let (center, radius) = framing::bounding_sphere(mn, mx);
let to = framing::frame_pose(
¤t,
center,
radius,
cam.fov_y_degrees.to_radians(),
aspect,
);
self.start_glide(current, to);
}
pub(super) fn start_glide(&mut self, from: CameraPose, to: CameraPose) {
self.glide = Some(CameraGlide {
from,
to,
start: std::time::Instant::now(),
});
}
pub(super) fn drive_glide(&mut self, input: &FrameInput, world: &mut World) {
let Some(glide) = &self.glide else {
return;
};
let steered = input.forward
|| input.backward
|| input.left
|| input.right
|| input.mouse_dx != 0.0
|| input.mouse_dy != 0.0;
if steered {
self.end_glide();
return;
}
let t = glide.start.elapsed().as_secs_f32() / GLIDE_SECS;
let pose = framing::lerp_pose(&glide.from, &glide.to, framing::ease(t));
if let Some(cam) = world.query_mut::<Camera3D>().next() {
cam.position = pose.position;
cam.yaw = pose.yaw;
cam.pitch = pose.pitch;
cam.view_matrix =
concinnity_core::gfx::camera::view_matrix(pose.position, pose.yaw, pose.pitch);
}
if t >= 1.0 {
self.end_glide();
}
}
pub(super) fn end_glide(&mut self) {
self.glide = None;
self.fly_clock = None;
}
}