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