use crate::FrameUpdateEvent;
use crate::HitTestId;
use crate::HitTestSource;
use euclid::Transform3D;
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
pub struct ClipPlanes {
pub near: f32,
pub far: f32,
update: bool,
}
impl Default for ClipPlanes {
fn default() -> Self {
ClipPlanes {
near: 0.1,
far: 1000.,
update: false,
}
}
}
impl ClipPlanes {
pub fn update(&mut self, near: f32, far: f32) {
self.near = near;
self.far = far;
self.update = true;
}
pub fn recently_updated(&mut self) -> bool {
if self.update {
self.update = false;
true
} else {
false
}
}
}
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
pub struct HitTestList {
tests: Vec<HitTestSource>,
uncommitted_tests: Vec<HitTestSource>,
}
impl HitTestList {
pub fn request_hit_test(&mut self, source: HitTestSource) {
self.uncommitted_tests.push(source)
}
pub fn commit_tests(&mut self) -> Vec<FrameUpdateEvent> {
let mut events = vec![];
for test in self.uncommitted_tests.drain(..) {
events.push(FrameUpdateEvent::HitTestSourceAdded(test.id));
self.tests.push(test);
}
events
}
pub fn tests(&self) -> &[HitTestSource] {
&self.tests
}
pub fn cancel_hit_test(&mut self, id: HitTestId) {
self.tests.retain(|s| s.id != id);
self.uncommitted_tests.retain(|s| s.id != id);
}
}
#[inline]
pub fn fov_to_projection_matrix<T, U>(
left: f32,
right: f32,
top: f32,
bottom: f32,
clip_planes: ClipPlanes,
) -> Transform3D<f32, T, U> {
let near = clip_planes.near;
let left = left.tan() * near;
let right = right.tan() * near;
let top = top.tan() * near;
let bottom = bottom.tan() * near;
frustum_to_projection_matrix(left, right, top, bottom, clip_planes)
}
#[inline]
pub fn frustum_to_projection_matrix<T, U>(
left: f32,
right: f32,
top: f32,
bottom: f32,
clip_planes: ClipPlanes,
) -> Transform3D<f32, T, U> {
let near = clip_planes.near;
let far = clip_planes.far;
let w = right - left;
let h = top - bottom;
let d = far - near;
Transform3D::new(
2. * near / w,
0.,
0.,
0.,
0.,
2. * near / h,
0.,
0.,
(right + left) / w,
(top + bottom) / h,
-(far + near) / d,
-1.,
0.,
0.,
-2. * far * near / d,
0.,
)
}