1use core::slice;
2use std::ops::Deref;
3
4use glam::Vec2;
5use slotmap::{secondary::Iter, SecondaryMap};
6use smallvec::SmallVec;
7
8use crate::{util::face_intersect, BSPTree, Face, NodeIndex, Portal, PortalRef, Side};
9
10#[derive(Copy, Debug, Clone, PartialEq)]
11#[doc(hidden)]
12pub struct ClippedFace {
13 face: Face,
14 pub(crate) sides: [Side; 2],
16 pub(crate) adjacent: [bool; 2],
17
18 pub src: NodeIndex,
19 pub dst: NodeIndex,
20}
21
22impl ClippedFace {
23 pub fn new(
24 vertices: [Vec2; 2],
25 sides: [Side; 2],
26 adjacent: [bool; 2],
27 src: NodeIndex,
28 dst: NodeIndex,
29 ) -> Self {
30 Self {
31 face: Face::new(vertices),
32 sides,
33 adjacent,
34 src,
35 dst,
36 }
37 }
38
39 pub(crate) fn split(&self, p: Vec2, normal: Vec2) -> [Self; 2] {
40 let intersection = face_intersect(self.into_tuple(), p, normal);
41
42 [
44 Self::new(
45 [self.vertices[0], intersection.point],
46 [Side::Front, Side::Front],
47 [self.adjacent[0], false],
48 self.src,
49 self.dst,
50 ),
51 Self::new(
52 [intersection.point, self.vertices[1]],
53 [Side::Front, Side::Front],
54 [false, self.adjacent[1]],
55 self.src,
56 self.dst,
57 ),
58 ]
59 }
60
61 pub fn src(&self) -> NodeIndex {
63 self.src
64 }
65
66 pub fn dst(&self) -> NodeIndex {
68 self.dst
69 }
70
71 pub fn sides(&self) -> [Side; 2] {
73 self.sides
74 }
75
76 pub fn face(&self) -> Face {
78 self.face
79 }
80}
81
82impl Deref for ClippedFace {
83 type Target = Face;
84
85 fn deref(&self) -> &Self::Target {
86 &self.face
87 }
88}
89
90type NodePortals = SmallVec<[PortalRef; 4]>;
91
92#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
95pub struct Portals {
96 inner: SecondaryMap<NodeIndex, NodePortals>,
97 faces: Vec<Face>,
98}
99
100impl Portals {
101 pub fn new() -> Self {
102 Self {
103 inner: SecondaryMap::new(),
104 faces: Vec::new(),
105 }
106 }
107
108 pub fn generate(&mut self, tree: &BSPTree) {
109 self.extend(tree.generate_portals())
110 }
111
112 pub fn push(&mut self, portal: ClippedFace) {
114 let face = self.faces.len();
115 self.faces.push(portal.face);
116
117 assert_ne!(portal.src, portal.dst);
118
119 self.inner
120 .entry(portal.src)
121 .expect("Node was removed")
122 .or_default()
123 .push(PortalRef {
124 dst: portal.dst,
125 src: portal.src,
126 adjacent: portal.adjacent,
127 normal: -portal.normal(),
128 face,
129 });
130 self.inner
131 .entry(portal.dst)
132 .expect("Node was removed")
133 .or_default()
134 .push(PortalRef {
135 dst: portal.src,
136 src: portal.dst,
137 adjacent: portal.adjacent,
138 normal: portal.normal(),
139 face,
140 });
141 }
142
143 pub fn get(&self, index: NodeIndex) -> PortalIter {
144 PortalIter {
145 faces: &self.faces,
146 iter: self
147 .inner
148 .get(index)
149 .map(|val| val.as_ref())
150 .unwrap_or_default()
151 .iter(),
152 }
153 }
154
155 pub fn iter(&self) -> PortalsIter {
156 PortalsIter {
157 faces: &self.faces,
158 inner: self.inner.iter(),
159 }
160 }
161
162 pub fn from_ref(&self, portal: PortalRef) -> Portal {
163 Portal {
164 face: &self.faces[portal.face],
165 portal_ref: portal,
166 }
167 }
168}
169
170#[doc(hidden)]
171pub struct PortalIter<'a> {
172 faces: &'a [Face],
173 iter: slice::Iter<'a, PortalRef>,
174}
175
176impl<'a> Iterator for PortalIter<'a> {
177 type Item = Portal<'a>;
178
179 fn next(&mut self) -> Option<Self::Item> {
180 let portal = self.iter.next()?;
181
182 Some(Portal {
183 face: &self.faces[portal.face],
184 portal_ref: *portal,
185 })
186 }
187}
188
189impl<'a> IntoIterator for &'a Portals {
190 type Item = PortalIter<'a>;
191
192 type IntoIter = PortalsIter<'a>;
193
194 fn into_iter(self) -> Self::IntoIter {
195 self.iter()
196 }
197}
198
199#[doc(hidden)]
200pub struct PortalsIter<'a> {
201 faces: &'a [Face],
202 inner: Iter<'a, NodeIndex, NodePortals>,
203}
204
205impl<'a> Iterator for PortalsIter<'a> {
206 type Item = PortalIter<'a>;
207
208 fn next(&mut self) -> Option<Self::Item> {
209 let (_, portals) = self.inner.next()?;
210 Some(PortalIter {
211 faces: self.faces,
212 iter: portals.iter(),
213 })
214 }
215}
216
217impl Default for Portals {
218 fn default() -> Self {
219 Self::new()
220 }
221}
222
223impl Extend<ClippedFace> for Portals {
224 fn extend<T: IntoIterator<Item = ClippedFace>>(&mut self, iter: T) {
225 let iter = iter.into_iter();
226 let cap = self.inner.len() + iter.size_hint().0;
227
228 self.inner.set_capacity(cap);
229 iter.for_each(|val| self.push(val))
230 }
231}