renderling/transform/
cpu.rs1use std::sync::{Arc, RwLock};
4
5use craballoc::{runtime::IsRuntime, slab::SlabAllocator, value::Hybrid};
6use crabslab::Id;
7use glam::{Mat4, Quat, Vec3};
8
9use super::shader::TransformDescriptor;
10
11#[derive(Clone, Debug)]
13pub struct Transform {
14 pub(crate) descriptor: Hybrid<TransformDescriptor>,
15}
16
17impl From<&Transform> for Transform {
18 fn from(value: &Transform) -> Self {
19 value.clone()
20 }
21}
22
23impl Transform {
24 pub(crate) fn new(slab: &SlabAllocator<impl IsRuntime>) -> Self {
26 let descriptor = slab.new_value(TransformDescriptor::default());
27 Self { descriptor }
28 }
29
30 pub fn id(&self) -> Id<TransformDescriptor> {
32 self.descriptor.id()
33 }
34
35 pub fn descriptor(&self) -> TransformDescriptor {
37 self.descriptor.get()
38 }
39
40 pub fn set_descriptor(&self, descriptor: TransformDescriptor) -> &Self {
42 self.descriptor.set(descriptor);
43 self
44 }
45
46 pub fn with_descriptor(self, descriptor: TransformDescriptor) -> Self {
48 self.set_descriptor(descriptor);
49 self
50 }
51
52 pub fn as_mat4(&self) -> Mat4 {
54 self.descriptor().into()
55 }
56
57 pub fn translation(&self) -> Vec3 {
59 self.descriptor.get().translation
60 }
61
62 pub fn modify_translation<T: 'static>(&self, f: impl FnOnce(&mut Vec3) -> T) -> T {
69 self.descriptor.modify(|t| f(&mut t.translation))
70 }
71
72 pub fn set_translation(&self, translation: impl Into<Vec3>) -> &Self {
78 self.descriptor
79 .modify(|t| t.translation = translation.into());
80 self
81 }
82
83 pub fn with_translation(self, translation: impl Into<Vec3>) -> Self {
89 self.set_translation(translation);
90 self
91 }
92
93 pub fn rotation(&self) -> Quat {
95 self.descriptor.get().rotation
96 }
97
98 pub fn modify_rotation<T: 'static>(&self, f: impl FnOnce(&mut Quat) -> T) -> T {
105 self.descriptor.modify(|t| f(&mut t.rotation))
106 }
107
108 pub fn set_rotation(&self, rotation: impl Into<Quat>) -> &Self {
114 self.descriptor.modify(|t| t.rotation = rotation.into());
115 self
116 }
117
118 pub fn with_rotation(self, rotation: impl Into<Quat>) -> Self {
124 self.set_rotation(rotation);
125 self
126 }
127
128 pub fn scale(&self) -> Vec3 {
130 self.descriptor.get().scale
131 }
132
133 pub fn modify_scale<T: 'static>(&self, f: impl FnOnce(&mut Vec3) -> T) -> T {
140 self.descriptor.modify(|t| f(&mut t.scale))
141 }
142
143 pub fn set_scale(&self, scale: impl Into<Vec3>) -> &Self {
149 self.descriptor.modify(|t| t.scale = scale.into());
150 self
151 }
152
153 pub fn with_scale(self, scale: impl Into<Vec3>) -> Self {
159 self.set_scale(scale);
160 self
161 }
162}
163
164#[derive(Clone)]
171pub struct NestedTransform {
172 pub(crate) global_transform: Transform,
173 local_transform: Arc<RwLock<TransformDescriptor>>,
174 children: Arc<RwLock<Vec<NestedTransform>>>,
175 parent: Arc<RwLock<Option<NestedTransform>>>,
176}
177
178impl core::fmt::Debug for NestedTransform {
179 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
180 let children = self
181 .children
182 .read()
183 .unwrap()
184 .iter()
185 .map(|nt| nt.global_transform.id())
186 .collect::<Vec<_>>();
187 let parent = self
188 .parent
189 .read()
190 .unwrap()
191 .as_ref()
192 .map(|nt| nt.global_transform.id());
193 f.debug_struct("NestedTransform")
194 .field("local_transform", &self.local_transform)
195 .field("children", &children)
196 .field("parent", &parent)
197 .finish()
198 }
199}
200
201impl From<&NestedTransform> for Transform {
202 fn from(value: &NestedTransform) -> Self {
203 value.global_transform.clone()
204 }
205}
206
207impl From<NestedTransform> for Transform {
208 fn from(value: NestedTransform) -> Self {
209 value.global_transform
210 }
211}
212
213impl NestedTransform {
214 pub(crate) fn new(slab: &SlabAllocator<impl IsRuntime>) -> Self {
216 let nested = NestedTransform {
217 local_transform: Arc::new(RwLock::new(TransformDescriptor::default())),
218 global_transform: Transform::new(slab),
219 children: Default::default(),
220 parent: Default::default(),
221 };
222 nested.mark_dirty();
223 nested
224 }
225
226 pub fn local_translation(&self) -> Vec3 {
228 self.local_transform
229 .read()
230 .expect("local_transform read")
231 .translation
232 }
233
234 pub fn modify_local_translation<T>(&self, f: impl FnOnce(&mut Vec3) -> T) -> T {
241 let t = {
242 let mut local_transform = self.local_transform.write().expect("local_transform write");
243 f(&mut local_transform.translation)
244 };
245 self.mark_dirty();
246 t
247 }
248
249 pub fn set_local_translation(&self, translation: impl Into<Vec3>) -> &Self {
255 self.local_transform
256 .write()
257 .expect("local_transform write")
258 .translation = translation.into();
259 self.mark_dirty();
260 self
261 }
262
263 pub fn with_local_translation(self, translation: impl Into<Vec3>) -> Self {
269 self.set_local_translation(translation);
270 self
271 }
272
273 pub fn local_rotation(&self) -> Quat {
275 self.local_transform
276 .read()
277 .expect("local_transform read")
278 .rotation
279 }
280
281 pub fn modify_local_rotation<T>(&self, f: impl FnOnce(&mut Quat) -> T) -> T {
288 let t = {
289 let mut local_transform = self.local_transform.write().expect("local_transform write");
290 f(&mut local_transform.rotation)
291 };
292 self.mark_dirty();
293 t
294 }
295
296 pub fn set_local_rotation(&self, rotation: impl Into<Quat>) -> &Self {
302 self.local_transform
303 .write()
304 .expect("local_transform write")
305 .rotation = rotation.into();
306 self.mark_dirty();
307 self
308 }
309
310 pub fn with_local_rotation(self, rotation: impl Into<Quat>) -> Self {
316 self.set_local_rotation(rotation);
317 self
318 }
319
320 pub fn local_scale(&self) -> Vec3 {
322 self.local_transform
323 .read()
324 .expect("local_transform read")
325 .scale
326 }
327
328 pub fn modify_local_scale<T>(&self, f: impl FnOnce(&mut Vec3) -> T) -> T {
335 let t = {
336 let mut local_transform = self.local_transform.write().expect("local_transform write");
337 f(&mut local_transform.scale)
338 };
339 self.mark_dirty();
340 t
341 }
342
343 pub fn set_local_scale(&self, scale: impl Into<Vec3>) -> &Self {
349 self.local_transform
350 .write()
351 .expect("local_transform write")
352 .scale = scale.into();
353 self.mark_dirty();
354 self
355 }
356
357 pub fn with_local_scale(self, scale: impl Into<Vec3>) -> Self {
363 self.set_local_scale(scale);
364 self
365 }
366
367 pub fn global_id(&self) -> Id<TransformDescriptor> {
371 self.global_transform.id()
372 }
373
374 pub fn global_descriptor(&self) -> TransformDescriptor {
378 let maybe_parent_guard = self.parent.read().expect("parent read");
379 let transform = self.local_descriptor();
380 let parent_transform = maybe_parent_guard
381 .as_ref()
382 .map(|parent| parent.global_descriptor())
383 .unwrap_or_default();
384 TransformDescriptor::from(Mat4::from(parent_transform) * Mat4::from(transform))
385 }
386
387 pub fn local_descriptor(&self) -> TransformDescriptor {
389 *self.local_transform.read().expect("local_transform read")
390 }
391
392 fn mark_dirty(&self) {
393 self.global_transform
394 .descriptor
395 .set(self.global_descriptor());
396 for child in self.children.read().expect("children read").iter() {
397 child.mark_dirty();
398 }
399 }
400
401 pub fn hierarchy(&self) -> Vec<TransformDescriptor> {
405 let mut transforms = vec![];
406 if let Some(parent) = self.parent() {
407 transforms.extend(parent.hierarchy());
408 }
409 transforms.push(self.local_descriptor());
410 transforms
411 }
412
413 pub fn add_child(&self, node: &NestedTransform) {
414 *node.parent.write().expect("parent write") = Some(self.clone());
415 node.mark_dirty();
416 self.children
417 .write()
418 .expect("children write")
419 .push(node.clone());
420 }
421
422 pub fn remove_child(&self, node: &NestedTransform) {
423 self.children
424 .write()
425 .expect("children write")
426 .retain_mut(|child| {
427 if child.global_transform.id() == node.global_transform.id() {
428 node.mark_dirty();
429 let _ = node.parent.write().expect("parent write").take();
430 false
431 } else {
432 true
433 }
434 });
435 }
436
437 pub fn parent(&self) -> Option<NestedTransform> {
439 self.parent.read().expect("parent read").clone()
440 }
441}