1use euclid::Transform3D;
6
7use crate::{FrameUpdateEvent, HitTestId, HitTestSource};
8
9#[derive(Clone, Copy, Debug)]
10#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
11pub struct ClipPlanes {
12 pub near: f32,
13 pub far: f32,
14 update: bool,
16}
17
18impl Default for ClipPlanes {
19 fn default() -> Self {
20 ClipPlanes {
21 near: 0.1,
22 far: 1000.,
23 update: false,
24 }
25 }
26}
27
28impl ClipPlanes {
29 pub fn update(&mut self, near: f32, far: f32) {
30 self.near = near;
31 self.far = far;
32 self.update = true;
33 }
34
35 pub fn recently_updated(&mut self) -> bool {
37 if self.update {
38 self.update = false;
39 true
40 } else {
41 false
42 }
43 }
44}
45
46#[derive(Clone, Debug, Default)]
47#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
48pub struct HitTestList {
50 tests: Vec<HitTestSource>,
51 uncommitted_tests: Vec<HitTestSource>,
52}
53
54impl HitTestList {
55 pub fn request_hit_test(&mut self, source: HitTestSource) {
56 self.uncommitted_tests.push(source)
57 }
58
59 pub fn commit_tests(&mut self) -> Vec<FrameUpdateEvent> {
60 let mut events = vec![];
61 for test in self.uncommitted_tests.drain(..) {
62 events.push(FrameUpdateEvent::HitTestSourceAdded(test.id));
63 self.tests.push(test);
64 }
65 events
66 }
67
68 pub fn tests(&self) -> &[HitTestSource] {
69 &self.tests
70 }
71
72 pub fn cancel_hit_test(&mut self, id: HitTestId) {
73 self.tests.retain(|s| s.id != id);
74 self.uncommitted_tests.retain(|s| s.id != id);
75 }
76}
77
78#[inline]
79pub fn fov_to_projection_matrix<T, U>(
81 left: f32,
82 right: f32,
83 top: f32,
84 bottom: f32,
85 clip_planes: ClipPlanes,
86) -> Transform3D<f32, T, U> {
87 let near = clip_planes.near;
88 let left = left.tan() * near;
90 let right = right.tan() * near;
91 let top = top.tan() * near;
92 let bottom = bottom.tan() * near;
93
94 frustum_to_projection_matrix(left, right, top, bottom, clip_planes)
95}
96
97#[inline]
98pub fn frustum_to_projection_matrix<T, U>(
100 left: f32,
101 right: f32,
102 top: f32,
103 bottom: f32,
104 clip_planes: ClipPlanes,
105) -> Transform3D<f32, T, U> {
106 let near = clip_planes.near;
107 let far = clip_planes.far;
108
109 let w = right - left;
110 let h = top - bottom;
111 let d = far - near;
112
113 Transform3D::new(
115 2. * near / w,
116 0.,
117 0.,
118 0.,
119 0.,
120 2. * near / h,
121 0.,
122 0.,
123 (right + left) / w,
124 (top + bottom) / h,
125 -(far + near) / d,
126 -1.,
127 0.,
128 0.,
129 -2. * far * near / d,
130 0.,
131 )
132}