draw_queue/
lib.rs

1#![deny(missing_docs)]
2
3//! Generic draw queue that keeps item ordering, supposedly minimizing
4//! the sorting time per frame by exploiting temporal coherency.
5
6type IdType = u32;
7struct Id<T>(IdType, std::marker::PhantomData<T>);
8
9/// Iterator over queue objects.
10pub struct QueueIter<'a, T: 'a> {
11    objects: &'a [T],
12    id_iter: std::slice::Iter<'a, Id<T>>,
13}
14
15impl<'a, T> Iterator for QueueIter<'a, T> {
16    type Item = &'a T;
17
18    fn next(&mut self) -> Option<&'a T> {
19        self.id_iter.next().map(|&Id(i, _)|
20            &self.objects[i as usize]
21        )
22    }
23}
24
25/// Generic draw queue.
26pub struct Queue<T> {
27    /// Exposed objects list that can be modified directly with no harm.
28    pub objects: Vec<T>,
29    indices: Vec<Id<T>>,
30}
31
32impl<T> Queue<T> {
33    /// Create an empty queue.
34    pub fn new() -> Queue<T> {
35        Queue {
36            objects: Vec::new(),
37            indices: Vec::new(),
38        }
39    }
40
41    fn is_ready(&self) -> bool {
42        self.objects.len() == self.indices.len()
43    }
44
45    /// Synchronize the indices with objects.
46    pub fn update(&mut self) {
47        let ni = self.indices.len();
48        if self.objects.len() > ni {
49            self.indices.extend((ni.. self.objects.len()).map(|i|
50                Id(i as IdType, std::marker::PhantomData)
51            ));
52        }else
53        if self.objects.len() < ni {
54            let no = self.objects.len();
55            self.indices.retain(|&Id(i, _)| (i as usize) < no);
56        }
57        debug_assert!(self.is_ready());
58    }
59
60    /// Sort the draw queue.
61    pub fn sort<F: Sized + Fn(&T, &T) -> std::cmp::Ordering>(&mut self, fun: F) {
62        self.update();
63        let objects = &self.objects;
64        self.indices.sort_by(|&Id(a, _), &Id(b, _)|
65            fun(&objects[a as usize], &objects[b as usize])
66        );
67    }
68
69    /// Iterate over sorted objects.
70    pub fn iter<'a>(&'a self) -> QueueIter<'a, T> {
71        assert!(self.is_ready());
72        QueueIter {
73            objects: &self.objects,
74            id_iter: self.indices.iter(),
75        }
76    }
77}