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 if loc.x > self.size.x || loc.y > self.size.y {
90 return None;
91 }
92
93 let idx = loc.y as usize * self.size.x as usize + loc.x as usize;
94
95 if (idx as u16) >= self.size.x * self.size.y {
96 return None;
97 }
98
99 Some(idx.min((self.size.x as usize * self.size.y as usize) - 1))
100 }
101
102 pub fn clear(&mut self) {
104 *self = Self::new(self.size);
105 }
106
107 pub fn diff<'a>(&self, other: &'a Buffer) -> Vec<(Vec2, &'a Cell)> {
109 assert!(self.size == other.size);
110
111 let mut res = vec![];
112 let mut skip = 0;
113
114 for y in 0..self.size.y {
115 for x in 0..self.size.x {
116 if skip > 0 {
117 skip -= 1;
118 continue;
119 }
120
121 let old = self.get((x, y));
122 let new = other.get((x, y));
123
124 if old != new {
125 let new = new.expect("new should be in bounds");
126 skip = new.width().saturating_sub(1) as usize;
127 res.push((vec2(x, y), new))
128 }
129 }
130 }
131
132 res
133 }
134
135 pub fn shrink(&mut self) {
137 let mut max_whitespace_x = 0;
138 let mut max_whitespace_y = 0;
139 for x in (0..self.size.x).rev() {
140 for y in (0..self.size.y).rev() {
141 if !self
142 .get((x, y))
143 .expect("Cell should be in bounds")
144 .is_empty()
145 {
146 max_whitespace_x = x.max(max_whitespace_x);
147 max_whitespace_y = y.max(max_whitespace_y);
148 }
149 }
150 }
151
152 self.resize(vec2(max_whitespace_x + 1, max_whitespace_y + 1));
153 }
154
155 pub fn resize(&mut self, new_size: impl Into<Vec2>) {
157 let new_size = new_size.into();
158 if self.size == new_size {
159 return;
160 }
161
162 let mut new_elements = vec![];
163
164 for y in 0..new_size.y {
165 for x in 0..new_size.x {
166 new_elements.push(self.get((x, y)).expect("Cell should be in bounds").clone());
167 }
168 }
169
170 self.size = new_size;
171 self.cells = new_elements;
172 }
173
174 pub fn sized_element<R: Render>(item: R) -> Self {
177 let mut buff = Buffer::new((100, 100));
178 render!(buff, vec2(0, 0) => [ item ]);
179 buff.shrink();
180 buff
181 }
182}
183
184impl Render for Buffer {
185 fn render(&self, loc: Vec2, buffer: &mut Buffer) -> Vec2 {
186 for x in 0..self.size.x {
187 if x + loc.x >= buffer.size.x {
188 break;
189 }
190
191 for y in 0..self.size.y {
192 if y + loc.y >= buffer.size.y {
193 break;
194 }
195
196 let dest = vec2(x + loc.x, y + loc.y);
197
198 buffer.set(
199 dest,
200 self.get(vec2(x, y))
201 .expect("Cell should be in bounds")
202 .clone(),
203 );
204 }
205 }
206 vec2(loc.x + buffer.size().x, loc.y + buffer.size().y)
207 }
208}