1pub mod color;
17pub mod framebuffer;
18pub mod geometry;
19pub mod painter;
20
21pub use color::Rgba;
22pub use framebuffer::{DirtyRegion, FrameBuffer, BYTES_PER_PIXEL, TILE_SIZE};
23pub use geometry::{BracketSides, TilePos, TileRect};
24pub use painter::{Frame, LabelValue, Painter, Ui};
25
26use crate::tilemap::Tilemap;
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum BlendMode {
31 Normal,
33 Additive,
35 Multiply,
37}
38
39#[derive(Debug, Clone)]
44pub struct MapLayer {
45 pub tilemap: Tilemap,
47 pub visible: bool,
50 pub opacity: f32,
52 pub scroll_factor: (f32, f32),
58 pub blend_mode: BlendMode,
60 pub z_index: i32,
62 pub no_animation: bool,
65 pub level: i32,
70}
71
72impl MapLayer {
73 pub fn new(tilemap: Tilemap, z_index: i32) -> Self {
78 Self {
79 tilemap,
80 visible: true,
81 opacity: 1.0,
82 scroll_factor: (1.0, 1.0),
83 blend_mode: BlendMode::Normal,
84 z_index,
85 no_animation: false,
86 level: 0,
87 }
88 }
89}
90
91#[derive(Debug, Clone)]
93pub struct MapRenderState {
94 pub layers: Vec<MapLayer>,
97 pub background_color: (u8, u8, u8, u8),
100}
101
102impl MapRenderState {
103 pub fn new() -> Self {
105 Self {
106 layers: Vec::new(),
107 background_color: (0, 0, 0, 255),
108 }
109 }
110
111 pub fn add_layer(&mut self, layer: MapLayer) {
113 self.layers.push(layer);
114 }
115
116 pub fn visible_layer_count(&self) -> usize {
118 self.layers.iter().filter(|l| l.visible).count()
119 }
120}
121
122impl Default for MapRenderState {
123 fn default() -> Self {
124 Self::new()
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use crate::tilemap::Tilemap;
132
133 fn make_tilemap(w: u16, h: u16) -> Tilemap {
134 Tilemap::new(w, h)
135 }
136
137 #[test]
138 fn blend_mode_equality() {
139 assert_eq!(BlendMode::Normal, BlendMode::Normal);
140 assert_ne!(BlendMode::Normal, BlendMode::Additive);
141 assert_ne!(BlendMode::Additive, BlendMode::Multiply);
142 }
143
144 #[test]
145 fn map_layer_defaults() {
146 let tm = make_tilemap(10, 10);
147 let layer = MapLayer::new(tm, 0);
148 assert!(layer.visible);
149 assert!((layer.opacity - 1.0).abs() < f32::EPSILON);
150 assert_eq!(layer.scroll_factor, (1.0, 1.0));
151 assert_eq!(layer.blend_mode, BlendMode::Normal);
152 assert_eq!(layer.z_index, 0);
153 assert_eq!(layer.level, 0);
154 }
155
156 #[test]
157 fn map_layer_custom() {
158 let tm = make_tilemap(8, 8);
159 let layer = MapLayer {
160 tilemap: tm,
161 visible: false,
162 opacity: 0.5,
163 scroll_factor: (0.5, 0.5),
164 blend_mode: BlendMode::Additive,
165 z_index: 5,
166 no_animation: false,
167 level: 1,
168 };
169 assert!(!layer.visible);
170 assert!((layer.opacity - 0.5).abs() < f32::EPSILON);
171 assert_eq!(layer.scroll_factor, (0.5, 0.5));
172 assert_eq!(layer.blend_mode, BlendMode::Additive);
173 assert_eq!(layer.z_index, 5);
174 assert_eq!(layer.level, 1);
175 }
176
177 #[test]
178 fn map_render_state_default() {
179 let state = MapRenderState::default();
180 assert!(state.layers.is_empty());
181 assert_eq!(state.background_color, (0, 0, 0, 255));
182 }
183
184 #[test]
185 fn map_render_state_add_layer() {
186 let mut state = MapRenderState::new();
187 let tm = make_tilemap(32, 32);
188 state.add_layer(MapLayer::new(tm, 0));
189 assert_eq!(state.layers.len(), 1);
190 }
191
192 #[test]
193 fn visible_layer_count() {
194 let mut state = MapRenderState::new();
195 assert_eq!(state.visible_layer_count(), 0);
196
197 let mut l1 = MapLayer::new(make_tilemap(4, 4), 0);
198 l1.visible = true;
199 state.add_layer(l1);
200
201 let mut l2 = MapLayer::new(make_tilemap(4, 4), 1);
202 l2.visible = false;
203 state.add_layer(l2);
204
205 let mut l3 = MapLayer::new(make_tilemap(4, 4), 2);
206 l3.visible = true;
207 state.add_layer(l3);
208
209 assert_eq!(state.visible_layer_count(), 2);
210 }
211
212 #[test]
213 fn map_render_state_background_color() {
214 let state = MapRenderState {
215 layers: vec![],
216 background_color: (0x12, 0x34, 0x56, 0xFF),
217 };
218 assert_eq!(state.background_color, (0x12, 0x34, 0x56, 0xFF));
219 }
220
221 #[test]
222 fn layer_clone_independent() {
223 let tm = make_tilemap(4, 4);
224 let mut l1 = MapLayer::new(tm, 0);
225 l1.opacity = 0.7;
226 let l2 = l1.clone();
227 assert!((l2.opacity - 0.7).abs() < f32::EPSILON);
228 assert_eq!(l2.tilemap.width, 4);
230 }
231}