1 use super::atlas::AtlasCollection; |
1 use super::{atlas::AtlasCollection, gl::Texture2D}; |
2 use crate::render::camera::Camera; |
2 use crate::render::camera::Camera; |
3 |
3 |
4 use integral_geometry::Size; |
4 use integral_geometry::{Rect, Size}; |
5 |
5 |
|
6 use crate::render::atlas::SpriteIndex; |
6 use png::{ColorType, Decoder, DecodingError}; |
7 use png::{ColorType, Decoder, DecodingError}; |
|
8 use std::path::PathBuf; |
7 use std::{ |
9 use std::{ |
|
10 collections::HashMap, |
|
11 ffi::OsString, |
8 fs::{read_dir, File}, |
12 fs::{read_dir, File}, |
9 io, |
13 io, |
10 io::BufReader, |
14 io::BufReader, |
11 path::Path, |
15 path::Path, |
12 }; |
16 }; |
13 |
17 |
14 pub struct GearRenderer { |
18 pub struct GearRenderer { |
15 atlas: AtlasCollection, |
19 atlas: AtlasCollection, |
16 } |
20 } |
17 |
21 |
18 const ATLAS_SIZE: Size = Size::square(1024); |
22 struct SpriteData { |
|
23 size: Size, |
|
24 filename: PathBuf, |
|
25 } |
|
26 |
|
27 const ATLAS_SIZE: Size = Size::square(2024); |
19 |
28 |
20 impl GearRenderer { |
29 impl GearRenderer { |
21 pub fn new() -> Self { |
30 pub fn new() -> Self { |
|
31 let mut lookup = Vec::with_capacity(2048); |
|
32 |
22 let mut atlas = AtlasCollection::new(ATLAS_SIZE); |
33 let mut atlas = AtlasCollection::new(ATLAS_SIZE); |
23 let sprites = load_sprites(Path::new("../../share/hedgewars/Data/Graphics/")) |
34 let mut sprites = load_sprites(Path::new("../../share/hedgewars/Data/Graphics/")) |
24 .expect("Unable to load Graphics"); |
35 .expect("Unable to load Graphics"); |
25 for sprite in &sprites { |
36 let max_size = sprites |
26 atlas.insert_sprite(*sprite); |
37 .iter() |
|
38 .fold(Size::EMPTY, |size, sprite| size.join(sprite.size)); |
|
39 for sprite in sprites.drain(..) { |
|
40 lookup.push((sprite.filename, atlas.insert_sprite(sprite.size).unwrap())); |
27 } |
41 } |
|
42 |
28 println!( |
43 println!( |
29 "Filled atlas with {} sprites:\n{}", |
44 "Filled atlas with {} sprites:\n{}", |
30 sprites.len(), |
45 sprites.len(), |
31 atlas.used_space() |
46 atlas.used_space() |
32 ); |
47 ); |
|
48 |
|
49 let texture = Texture2D::new(max_size, gl::RGBA8, gl::LINEAR); |
|
50 |
|
51 let mut pixels = Vec::with_capacity(max_size.area()).into_boxed_slice(); |
|
52 for (path, sprite_index) in lookup.drain(..) { |
|
53 if let Some((atlas_index, rect)) = atlas.get_rect(sprite_index) { |
|
54 load_sprite_pixels(&path, &mut pixels[..]).expect("Unable to load Graphics"); |
|
55 texture.update(rect, &pixels, 0, gl::RGBA, gl::UNSIGNED_BYTE); |
|
56 } |
|
57 } |
|
58 |
33 Self { atlas } |
59 Self { atlas } |
34 } |
60 } |
35 |
61 |
36 pub fn render(&mut self, camera: &Camera) { |
62 pub fn render(&mut self, camera: &Camera) { |
37 let projection = camera.projection(); |
63 let projection = camera.projection(); |
38 } |
64 } |
39 } |
65 } |
40 |
66 |
41 fn load_sprite(path: &Path) -> io::Result<Size> { |
67 fn load_sprite_pixels(path: &Path, buffer: &mut [u8]) -> io::Result<()> { |
|
68 let decoder = Decoder::new(BufReader::new(File::open(path)?)); |
|
69 let (info, mut reader) = decoder.read_info()?; |
|
70 |
|
71 let size = Size::new(info.width as usize, info.height as usize); |
|
72 reader.next_frame(buffer)?; |
|
73 Ok(()) |
|
74 } |
|
75 |
|
76 fn load_sprite_size(path: &Path) -> io::Result<Size> { |
42 let decoder = Decoder::new(BufReader::new(File::open(path)?)); |
77 let decoder = Decoder::new(BufReader::new(File::open(path)?)); |
43 let (info, mut reader) = decoder.read_info()?; |
78 let (info, mut reader) = decoder.read_info()?; |
44 |
79 |
45 let size = Size::new(info.width as usize, info.height as usize); |
80 let size = Size::new(info.width as usize, info.height as usize); |
46 Ok(size) |
81 Ok(size) |
47 } |
82 } |
48 |
83 |
49 fn load_sprites(path: &Path) -> io::Result<Vec<Size>> { |
84 fn load_sprites(path: &Path) -> io::Result<Vec<SpriteData>> { |
50 let mut result = vec![]; |
85 let mut result = vec![]; |
51 for file in read_dir(path)? { |
86 for file in read_dir(path)? { |
52 let file = file?; |
87 let file = file?; |
53 if let Some(extension) = file.path().extension() { |
88 if let Some(extension) = file.path().extension() { |
54 if extension == "png" { |
89 if extension == "png" { |
55 let sprite = load_sprite(&file.path())?; |
90 let path = file.path(); |
56 result.push(sprite); |
91 let sprite = load_sprite_size(&path)?; |
|
92 result.push(SpriteData { |
|
93 size: sprite, |
|
94 filename: path, |
|
95 }); |
57 } |
96 } |
58 } |
97 } |
59 } |
98 } |
60 Ok(result) |
99 Ok(result) |
61 } |
100 } |