ascii_forge/renderer/
buffer.rs1use crate::prelude::*;
2
3#[derive(Debug)]
25pub struct Buffer {
26 size: Vec2,
27 cells: Vec<Cell>,
28}
29
30impl AsMut<Buffer> for Buffer {
31 fn as_mut(&mut self) -> &mut Buffer {
32 self
33 }
34}
35
36impl Buffer {
37 pub fn new(size: impl Into<Vec2>) -> Self {
39 let size = size.into();
40 Self {
41 size,
42 cells: vec![Cell::default(); size.x as usize * size.y as usize],
43 }
44 }
45
46 pub fn size(&self) -> Vec2 {
48 self.size
49 }
50
51 pub fn set<C: Into<Cell>>(&mut self, loc: impl Into<Vec2>, cell: C) {
53 let idx = self.index_of(loc);
54
55 let Some(idx) = idx else {
57 return;
58 };
59
60 self.cells[idx] = cell.into();
61 }
62
63 pub fn fill<C: Into<Cell>>(&mut self, cell: C) {
65 let cell = cell.into();
66 for i in 0..self.cells.len() {
67 self.cells[i] = cell.clone()
68 }
69 }
70
71 pub fn get(&self, loc: impl Into<Vec2>) -> Option<&Cell> {
73 let idx = self.index_of(loc)?;
74 self.cells.get(idx)
75 }
76
77 pub fn get_mut(&mut self, loc: impl Into<Vec2>) -> Option<&mut Cell> {
79 let idx = self.index_of(loc)?;
80 self.cells.get_mut(idx)
81 }
82
83 fn index_of(&self, loc: impl Into<Vec2>) -> Option<usize> {
84 let loc = loc.into();
85 let idx = loc.y as usize * self.size.x as usize + loc.x as usize;
86
87 if (idx as u16) >= self.size.x * self.size.y {
88 return None;
89 }
90
91 Some(idx.min((self.size.x as usize * self.size.y as usize) - 1))
92 }
93
94 pub fn clear(&mut self) {
96 *self = Self::new(self.size);
97 }
98
99 pub fn diff<'a>(&self, other: &'a Buffer) -> Vec<(Vec2, &'a Cell)> {
101 assert!(self.size == other.size);
102
103 let mut res = vec![];
104
105 for x in 0..self.size.x {
106 for y in 0..self.size.y {
107 if self.get((x, y)) != other.get((x, y)) {
108 res.push((
109 vec2(x, y),
110 other.get((x, y)).expect("Cell should be in bounds"),
111 ))
112 }
113 }
114 }
115
116 res
117 }
118
119 pub fn shrink(&mut self) {
121 let mut max_whitespace_x = 0;
122 let mut max_whitespace_y = 0;
123 for x in (0..self.size.x).rev() {
124 for y in (0..self.size.y).rev() {
125 if !self
126 .get((x, y))
127 .expect("Cell should be in bounds")
128 .is_empty()
129 {
130 max_whitespace_x = x.max(max_whitespace_x);
131 max_whitespace_y = y.max(max_whitespace_y);
132 }
133 }
134 }
135
136 self.resize(vec2(max_whitespace_x + 1, max_whitespace_y + 1));
137 }
138
139 pub fn resize(&mut self, new_size: impl Into<Vec2>) {
141 let new_size = new_size.into();
142 if self.size == new_size {
143 return;
144 }
145
146 let mut new_elements = vec![];
147
148 for y in 0..new_size.y {
149 for x in 0..new_size.x {
150 new_elements.push(self.get((x, y)).expect("Cell should be in bounds").clone());
151 }
152 }
153
154 self.size = new_size;
155 self.cells = new_elements;
156 }
157
158 pub fn sized_element<R: Render>(item: R) -> Self {
161 let mut buff = Buffer::new((100, 100));
162 render!(buff, vec2(0, 0) => [ item ]);
163 buff.shrink();
164 buff
165 }
166}
167
168impl Render for Buffer {
169 fn render(&self, loc: Vec2, buffer: &mut Buffer) -> Vec2 {
170 for x in 0..self.size.x {
171 if x + loc.x >= buffer.size.x {
172 break;
173 }
174
175 for y in 0..self.size.y {
176 if y + loc.y >= buffer.size.y {
177 break;
178 }
179
180 let dest = vec2(x + loc.x, y + loc.y);
181
182 buffer.set(
183 dest,
184 self.get(vec2(x, y))
185 .expect("Cell should be in bounds")
186 .clone(),
187 );
188 }
189 }
190 vec2(loc.x + buffer.size().x, loc.y + buffer.size().y)
191 }
192}