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 loc = loc.into();
54 let idx = self.index_of(loc);
55
56 let Some(idx) = idx else {
58 return;
59 };
60
61 let cell = cell.into();
62
63 for i in 1..cell.width().saturating_sub(1) {
64 self.set(loc + vec2(i, 0), Cell::default());
65 }
66
67 self.cells[idx] = cell;
68 }
69
70 pub fn fill<C: Into<Cell>>(&mut self, cell: C) {
72 let cell = cell.into();
73 for i in 0..self.cells.len() {
74 self.cells[i] = cell.clone()
75 }
76 }
77
78 pub fn get(&self, loc: impl Into<Vec2>) -> Option<&Cell> {
80 let idx = self.index_of(loc)?;
81 self.cells.get(idx)
82 }
83
84 pub fn get_mut(&mut self, loc: impl Into<Vec2>) -> Option<&mut Cell> {
86 let idx = self.index_of(loc)?;
87 self.cells.get_mut(idx)
88 }
89
90 fn index_of(&self, loc: impl Into<Vec2>) -> Option<usize> {
91 let loc = loc.into();
92 let idx = loc.y as usize * self.size.x as usize + loc.x as usize;
93
94 if (idx as u16) >= self.size.x * self.size.y {
95 return None;
96 }
97
98 Some(idx.min((self.size.x as usize * self.size.y as usize) - 1))
99 }
100
101 pub fn clear(&mut self) {
103 *self = Self::new(self.size);
104 }
105
106 pub fn diff<'a>(&self, other: &'a Buffer) -> Vec<(Vec2, &'a Cell)> {
108 assert!(self.size == other.size);
109
110 let mut res = vec![];
111 let mut skip = 0;
112
113 for y in 0..self.size.y {
114 for x in 0..self.size.x {
115 if skip > 0 {
116 skip -= 1;
117 continue;
118 }
119
120 let old = self.get((x, y));
121 let new = other.get((x, y));
122
123 if old != new {
124 let new = new.expect("new should be in bounds");
125 skip = new.width().saturating_sub(1) as usize;
126 res.push((vec2(x, y), new))
127 }
128 }
129 }
130
131 res
132 }
133
134 pub fn shrink(&mut self) {
136 let mut max_whitespace_x = 0;
137 let mut max_whitespace_y = 0;
138 for x in (0..self.size.x).rev() {
139 for y in (0..self.size.y).rev() {
140 if !self
141 .get((x, y))
142 .expect("Cell should be in bounds")
143 .is_empty()
144 {
145 max_whitespace_x = x.max(max_whitespace_x);
146 max_whitespace_y = y.max(max_whitespace_y);
147 }
148 }
149 }
150
151 self.resize(vec2(max_whitespace_x + 1, max_whitespace_y + 1));
152 }
153
154 pub fn resize(&mut self, new_size: impl Into<Vec2>) {
156 let new_size = new_size.into();
157 if self.size == new_size {
158 return;
159 }
160
161 let mut new_elements = vec![];
162
163 for y in 0..new_size.y {
164 for x in 0..new_size.x {
165 new_elements.push(self.get((x, y)).expect("Cell should be in bounds").clone());
166 }
167 }
168
169 self.size = new_size;
170 self.cells = new_elements;
171 }
172
173 pub fn sized_element<R: Render>(item: R) -> Self {
176 let mut buff = Buffer::new((100, 100));
177 render!(buff, vec2(0, 0) => [ item ]);
178 buff.shrink();
179 buff
180 }
181}
182
183impl Render for Buffer {
184 fn render(&self, loc: Vec2, buffer: &mut Buffer) -> Vec2 {
185 for x in 0..self.size.x {
186 if x + loc.x >= buffer.size.x {
187 break;
188 }
189
190 for y in 0..self.size.y {
191 if y + loc.y >= buffer.size.y {
192 break;
193 }
194
195 let dest = vec2(x + loc.x, y + loc.y);
196
197 buffer.set(
198 dest,
199 self.get(vec2(x, y))
200 .expect("Cell should be in bounds")
201 .clone(),
202 );
203 }
204 }
205 vec2(loc.x + buffer.size().x, loc.y + buffer.size().y)
206 }
207}