rust/lib-hedgewars-engine/src/render/atlas.rs
author S.D.
Tue, 27 Sep 2022 14:59:03 +0300
changeset 15878 fc3cb23fd26f
parent 15828 44b49f255e31
child 16084 36862a9ec59b
permissions -rw-r--r--
Allow to see rooms of incompatible versions in the lobby For the new clients the room version is shown in a separate column. There is also a hack for previous versions clients: the room vesion specifier is prepended to the room names for rooms of incompatible versions, and the server shows 'incompatible version' error if the client tries to join them.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
     1
use integral_geometry::{Rect, Size};
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
     2
use itertools::Itertools;
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
     3
use std::{
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
     4
    cmp::{max, min, Ordering},
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
     5
    ops::Index,
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
     6
};
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
     7
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
     8
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
     9
struct Fit {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    10
    short_side: u32,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    11
    long_side: u32,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    12
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    13
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    14
impl Fit {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    15
    fn new() -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    16
        Self {
15828
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15759
diff changeset
    17
            short_side: u32::MAX,
44b49f255e31 add type safe power of two sizes
alfadur
parents: 15759
diff changeset
    18
            long_side: u32::MAX,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    19
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    20
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    21
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    22
    fn measure(container: Size, size: Size) -> Option<Self> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    23
        if container.contains(size) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    24
            let x_leftover = container.width - size.width;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    25
            let y_leftover = container.height - size.height;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    26
            Some(Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    27
                short_side: min(x_leftover, y_leftover) as u32,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    28
                long_side: max(x_leftover, y_leftover) as u32,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    29
            })
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    30
        } else {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    31
            None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    32
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    33
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    34
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    35
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    36
#[derive(PartialEq, Eq)]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    37
pub struct UsedSpace {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    38
    used_area: usize,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    39
    total_area: usize,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    40
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    41
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    42
impl UsedSpace {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    43
    const fn new(used_area: usize, total_area: usize) -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    44
        Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    45
            used_area,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    46
            total_area,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    47
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    48
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    49
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    50
    const fn used(&self) -> usize {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    51
        self.used_area
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    52
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    53
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    54
    const fn total(&self) -> usize {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    55
        self.total_area
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    56
    }
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
    57
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
    58
    const fn free(&self) -> usize {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
    59
        self.total_area - self.used_area
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
    60
    }
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    61
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    62
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    63
impl std::fmt::Debug for UsedSpace {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    64
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    65
        write!(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    66
            f,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    67
            "{:.2}%",
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
    68
            self.used() as f32 / self.total() as f32 * 100.0
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    69
        )?;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    70
        Ok(())
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    71
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    72
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    73
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
    74
pub struct Atlas<T> {
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    75
    size: Size,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    76
    free_rects: Vec<Rect>,
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
    77
    used_rects: Vec<(Rect, T)>,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    78
    splits: Vec<Rect>,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    79
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    80
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
    81
impl<T: Copy> Atlas<T> {
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    82
    pub fn new(size: Size) -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    83
        Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    84
            size,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    85
            free_rects: vec![Rect::at_origin(size)],
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    86
            used_rects: vec![],
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    87
            splits: vec![],
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    88
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    89
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    90
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    91
    pub fn size(&self) -> Size {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    92
        self.size
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    93
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    94
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    95
    pub fn used_space(&self) -> UsedSpace {
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
    96
        let used = self.used_rects.iter().map(|(r, _)| r.size().area()).sum();
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    97
        UsedSpace::new(used, self.size.area())
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    98
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
    99
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   100
    fn find_position(&self, size: Size) -> Option<(Rect, Fit)> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   101
        let mut best_rect = Rect::EMPTY;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   102
        let mut best_fit = Fit::new();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   103
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   104
        for rect in &self.free_rects {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   105
            if let Some(fit) = Fit::measure(rect.size(), size) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   106
                if fit < best_fit {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   107
                    best_fit = fit;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   108
                    best_rect = Rect::from_size(rect.top_left(), size);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   109
                }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   110
            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   111
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   112
            if let Some(fit) = Fit::measure(rect.size(), size.transpose()) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   113
                if fit < best_fit {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   114
                    best_fit = fit;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   115
                    best_rect = Rect::from_size(rect.top_left(), size.transpose());
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   116
                }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   117
            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   118
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   119
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   120
        if best_rect == Rect::EMPTY {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   121
            None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   122
        } else {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   123
            Some((best_rect, best_fit))
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   124
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   125
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   126
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   127
    fn split_insert(&mut self, rect: Rect, value: T) {
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   128
        let mut splits = std::mem::replace(&mut self.splits, vec![]);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   129
        let mut buffer = [Rect::EMPTY; 4];
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   130
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   131
        for i in (0..self.free_rects.len()).rev() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   132
            if let Some(count) = split_rect(self.free_rects[i], rect, &mut splits, &mut buffer) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   133
                self.free_rects.swap_remove(i as usize);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   134
                splits.extend_from_slice(&buffer[0..count]);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   135
            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   136
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   137
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   138
        filter_swap_remove(&mut splits, |s| {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   139
            self.free_rects.iter().any(|r| r.contains_rect(s))
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   140
        });
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   141
        self.free_rects.extend(splits.drain(..));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   142
        std::mem::replace(&mut self.splits, splits);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   143
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   144
        self.used_rects.push((rect, value));
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   145
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   146
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   147
    pub fn insert(&mut self, size: Size, value: T) -> Option<Rect> {
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   148
        let (rect, _) = self.find_position(size)?;
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   149
        self.split_insert(rect, value);
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   150
        Some(rect)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   151
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   152
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   153
    pub fn insert_set<Iter>(&mut self, sizes: Iter) -> Vec<(Rect, T)>
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   154
    where
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   155
        Iter: Iterator<Item = (Size, T)>,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   156
    {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   157
        let mut sizes: Vec<_> = sizes.collect();
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   158
        let mut result = Vec::with_capacity(sizes.len());
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   159
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   160
        while let Some((index, (rect, _), value)) = sizes
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   161
            .iter()
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   162
            .enumerate()
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   163
            .filter_map(|(i, (s, v))| self.find_position(*s).map(|res| (i, res, v)))
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   164
            .min_by_key(|(_, (_, fit), _)| fit.clone())
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   165
        {
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   166
            self.split_insert(rect, *value);
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   167
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   168
            result.push((rect, *value));
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   169
            sizes.swap_remove(index);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   170
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   171
        result
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   172
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   173
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   174
    pub fn reset(&mut self) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   175
        self.free_rects.clear();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   176
        self.used_rects.clear();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   177
        self.free_rects.push(Rect::at_origin(self.size));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   178
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   179
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   180
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   181
pub type SpriteIndex = u32;
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   182
pub type SpriteLocation = (u32, Rect);
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   183
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   184
pub struct AtlasCollection {
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   185
    next_index: SpriteIndex,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   186
    texture_size: Size,
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   187
    atlases: Vec<Atlas<SpriteIndex>>,
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   188
    rects: Vec<SpriteLocation>,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   189
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   190
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   191
impl AtlasCollection {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   192
    pub fn new(texture_size: Size) -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   193
        Self {
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   194
            next_index: 0,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   195
            texture_size,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   196
            atlases: vec![],
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   197
            rects: vec![],
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   198
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   199
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   200
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   201
    fn repack(&mut self, size: Size) -> bool {
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   202
        for (atlas_index, atlas) in self.atlases.iter_mut().enumerate() {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   203
            if atlas.used_space().free() >= size.area() {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   204
                let mut temp_atlas = Atlas::new(atlas.size());
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   205
                let sizes = atlas
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   206
                    .used_rects
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   207
                    .iter()
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   208
                    .map(|(r, v)| (r.size(), *v))
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   209
                    .chain(std::iter::once((size, self.next_index)));
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   210
                let inserts = temp_atlas.insert_set(sizes);
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   211
                if inserts.len() > atlas.used_rects.len() {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   212
                    self.rects.push((0, Rect::EMPTY));
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   213
                    for (rect, index) in inserts {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   214
                        self.rects[index as usize] = (atlas_index as u32, rect);
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   215
                    }
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   216
                    std::mem::swap(atlas, &mut temp_atlas);
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   217
                    return true;
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   218
                }
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   219
            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   220
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   221
        false
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   222
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   223
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   224
    #[inline]
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   225
    fn consume_index(&mut self) -> Option<SpriteIndex> {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   226
        let result = Some(self.next_index);
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   227
        self.next_index += 1;
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   228
        result
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   229
    }
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   230
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   231
    pub fn insert_sprite(&mut self, size: Size) -> Option<SpriteIndex> {
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   232
        if !self.texture_size.contains(size) {
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   233
            None
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   234
        } else {
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   235
            let index = self.next_index;
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   236
            if let Some(index_rect) = self
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   237
                .atlases
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   238
                .iter_mut()
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   239
                .enumerate()
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   240
                .find_map(|(i, a)| a.insert(size, index).map(|r| (i as u32, r)))
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   241
            {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   242
                self.rects.push(index_rect);
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   243
            } else if !self.repack(size) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   244
                let mut atlas = Atlas::new(self.texture_size);
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   245
                let rect = atlas.insert(size, index)?;
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   246
                self.atlases.push(atlas);
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   247
                self.rects.push(((self.atlases.len() - 1) as u32, rect))
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   248
            }
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   249
            self.consume_index()
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   250
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   251
    }
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
   252
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   253
    pub fn get_rect(&self, index: SpriteIndex) -> Option<(u32, Rect)> {
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   254
        self.rects.get(index as usize).cloned()
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   255
    }
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   256
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
   257
    pub fn used_space(&self) -> String {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
   258
        self.atlases
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
   259
            .iter()
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
   260
            .enumerate()
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
   261
            .map(|(i, a)| format!("{}: {:?}", i, a.used_space()))
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
   262
            .join("\n")
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15186
diff changeset
   263
    }
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   264
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   265
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   266
impl Index<SpriteIndex> for AtlasCollection {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   267
    type Output = SpriteLocation;
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   268
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   269
    #[inline]
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   270
    fn index(&self, index: SpriteIndex) -> &Self::Output {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   271
        &self.rects[index as usize]
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   272
    }
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   273
}
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   274
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   275
#[inline]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   276
fn filter_swap_remove<T, F>(vec: &mut Vec<T>, predicate: F)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   277
where
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   278
    F: Fn(&T) -> bool,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   279
{
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   280
    let mut i = 0;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   281
    while i < vec.len() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   282
        if predicate(&vec[i]) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   283
            vec.swap_remove(i);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   284
        } else {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   285
            i += 1;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   286
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   287
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   288
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   289
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   290
#[inline]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   291
fn prune_push(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   292
    previous_splits: &mut Vec<Rect>,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   293
    buffer: &mut [Rect; 4],
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   294
    buffer_size: &mut usize,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   295
    rect: Rect,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   296
) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   297
    if !previous_splits.iter().any(|r| r.contains_rect(&rect)) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   298
        filter_swap_remove(previous_splits, |s| rect.contains_rect(s));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   299
        buffer[*buffer_size] = rect;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   300
        *buffer_size += 1;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   301
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   302
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   303
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   304
fn split_rect(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   305
    free_rect: Rect,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   306
    rect: Rect,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   307
    previous_splits: &mut Vec<Rect>,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   308
    buffer: &mut [Rect; 4],
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   309
) -> Option<usize> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   310
    let mut buffer_size = 0usize;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   311
    let split = free_rect.intersects(&rect);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   312
    if split {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   313
        if rect.left() > free_rect.left() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   314
            let trim = free_rect.right() - rect.left() + 1;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   315
            prune_push(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   316
                previous_splits,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   317
                buffer,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   318
                &mut buffer_size,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   319
                free_rect.with_margins(0, -trim, 0, 0),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   320
            );
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   321
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   322
        if rect.right() < free_rect.right() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   323
            let trim = rect.right() - free_rect.left() + 1;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   324
            prune_push(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   325
                previous_splits,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   326
                buffer,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   327
                &mut buffer_size,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   328
                free_rect.with_margins(-trim, 0, 0, 0),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   329
            );
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   330
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   331
        if rect.top() > free_rect.top() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   332
            let trim = free_rect.bottom() - rect.top() + 1;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   333
            prune_push(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   334
                previous_splits,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   335
                buffer,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   336
                &mut buffer_size,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   337
                free_rect.with_margins(0, 0, 0, -trim),
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15286
diff changeset
   338
            );
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   339
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   340
        if rect.bottom() < free_rect.bottom() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   341
            let trim = rect.bottom() - free_rect.top() + 1;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   342
            prune_push(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   343
                previous_splits,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   344
                buffer,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   345
                &mut buffer_size,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   346
                free_rect.with_margins(0, 0, -trim, 0),
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15286
diff changeset
   347
            );
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   348
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   349
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   350
    if split {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   351
        Some(buffer_size)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   352
    } else {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   353
        None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   354
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   355
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   356
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   357
#[cfg(test)]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   358
mod tests {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   359
    use super::Atlas;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   360
    use integral_geometry::{Rect, Size};
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   361
    use itertools::Itertools as _;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   362
    use proptest::prelude::*;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   363
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   364
    #[test]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   365
    fn insert() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   366
        let atlas_size = Size::square(16);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   367
        let mut atlas = Atlas::new(atlas_size);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   368
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   369
        assert_eq!(None, atlas.insert(Size::square(20), ()));
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   370
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   371
        let rect_size = Size::new(11, 3);
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   372
        let rect = atlas.insert(rect_size, ()).unwrap();
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   373
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   374
        assert_eq!(rect, Rect::at_origin(rect_size));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   375
        assert_eq!(2, atlas.free_rects.len());
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   376
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   377
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   378
    #[derive(Debug, Clone)]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   379
    struct TestRect(Size);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   380
    struct TestRectParameters(Size);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   381
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   382
    impl Default for TestRectParameters {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   383
        fn default() -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   384
            Self(Size::square(64))
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   385
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   386
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   387
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   388
    impl Arbitrary for TestRect {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   389
        type Parameters = TestRectParameters;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   390
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   391
        fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   392
            (1..=args.0.width, 1..=args.0.height)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   393
                .prop_map(|(w, h)| TestRect(Size::new(w, h)))
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   394
                .boxed()
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   395
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   396
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   397
        type Strategy = BoxedStrategy<TestRect>;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   398
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   399
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   400
    trait HasSize {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   401
        fn size(&self) -> Size;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   402
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   403
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   404
    impl HasSize for TestRect {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   405
        fn size(&self) -> Size {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   406
            self.0
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   407
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   408
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   409
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   410
    impl HasSize for Rect {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   411
        fn size(&self) -> Size {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   412
            self.size()
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   413
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   414
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   415
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   416
    impl HasSize for (Rect, ()) {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   417
        fn size(&self) -> Size {
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   418
            self.0.size()
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   419
        }
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   420
    }
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   421
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   422
    fn sum_area<S: HasSize>(items: &[S]) -> usize {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   423
        items.iter().map(|s| s.size().area()).sum()
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   424
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   425
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   426
    proptest! {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   427
        #[test]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   428
        fn prop_insert(rects in Vec::<TestRect>::arbitrary()) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   429
            let container = Rect::at_origin(Size::square(2048));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   430
            let mut atlas = Atlas::new(container.size());
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   431
            let inserted: Vec<_> = rects.iter().filter_map(|TestRect(size)| atlas.insert(*size, ())).collect();
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   432
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   433
            let mut inserted_pairs = inserted.iter().cartesian_product(inserted.iter());
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   434
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   435
            assert!(inserted.iter().all(|r| container.contains_rect(r)));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   436
            assert!(inserted_pairs.all(|(r1, r2)| r1 == r2 || r1 != r2 && !r1.intersects(r2)));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   437
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   438
            assert_eq!(inserted.len(), rects.len());
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   439
            assert_eq!(sum_area(&inserted), sum_area(&rects));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   440
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   441
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   442
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   443
    proptest! {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   444
        #[test]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   445
        fn prop_insert_set(rects in Vec::<TestRect>::arbitrary()) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   446
            let container = Rect::at_origin(Size::square(2048));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   447
            let mut atlas = Atlas::new(container.size());
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   448
            let mut set_atlas = Atlas::new(container.size());
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   449
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   450
            let inserted: Vec<_> = rects.iter().filter_map(|TestRect(size)| atlas.insert(*size, ())).collect();
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   451
            let set_inserted: Vec<_> = set_atlas.insert_set(rects.iter().map(|TestRect(size)| (*size, ())));
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   452
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   453
            let mut set_inserted_pairs = set_inserted.iter().cartesian_product(set_inserted.iter());
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   454
15186
9cf0c2f44f0e add a way to reference atlas contents
alfadur
parents: 15120
diff changeset
   455
            assert!(set_inserted_pairs.all(|((r1, _), (r2, _))| r1 == r2 || r1 != r2 && !r1.intersects(r2)));
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   456
            assert!(set_atlas.used_space().used() <= atlas.used_space().used());
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   457
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   458
            assert_eq!(sum_area(&set_inserted), sum_area(&inserted));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   459
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   460
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14743
diff changeset
   461
}