1use std;
4use glium;
5use image;
6use log;
7
8pub const CROSSHAIR_PNG_FILE_BYTES : &[u8; 101] =
11 include_bytes!("../crosshair.png");
12pub const CROSSHAIR_INVERSE_PNG_FILE_BYTES : &[u8; 95] =
15 include_bytes!("../crosshair-inverse.png");
16pub const TILESET_EASCII_ACORN_8X8_PNG_FILE_BYTES : &[u8; 2538] =
17 include_bytes!("../tileset_eascii_acorn-bbc-micro_8x8.png");
18pub const TILESET_EASCII_ACORN_8X8_INVERSE_PNG_FILE_BYTES : &[u8; 2526] =
19 include_bytes!("../tileset_eascii_acorn-bbc-micro_8x8-inverse.png");
20pub const TILESET_EASCII_ACORN_16X16_PNG_FILE_BYTES : &[u8; 3427] =
21 include_bytes!("../tileset_eascii_acorn-bbc-micro_16x16.png");
22pub const TILESET_EASCII_ACORN_16X16_INVERSE_PNG_FILE_BYTES : &[u8; 3427] =
23 include_bytes!("../tileset_eascii_acorn-bbc-micro_16x16-inverse.png");
24pub const POINTER_HAND_PNG_FILE_BYTES_OFFSET : (&[u8; 183], [i16; 2]) =
25 (include_bytes!("../pointer-hand.png"), [3, -10]);
26
27#[derive(Debug)]
28pub enum LoadError {
29 IoError (std::io::Error),
30 ImageError (image::ImageError),
31 TextureCreationError (glium::texture::TextureCreationError)
32}
33
34pub fn texture2d_with_mipmaps_from_bytes (
36 glium_facade : &dyn glium::backend::Facade,
37 bytes : &[u8],
38 image_format : image::ImageFormat,
39 mipmaps : glium::texture::MipmapsOption
40) -> Result <glium::Texture2d, LoadError> {
41 let img = image::load_from_memory_with_format (bytes, image_format)?.to_rgba8();
42 let img_dimensions = img.dimensions();
43 log::debug!(dimensions:?=img_dimensions; "texture load bytes");
44 let raw_image_2d = glium::texture::RawImage2d::from_raw_rgba_reversed (
45 img.into_raw().as_slice(), img_dimensions);
46
47 glium::Texture2d::with_mipmaps (glium_facade, raw_image_2d, mipmaps)
48 .map_err (Into::into)
49}
50
51pub fn texture2d_with_mipmaps_from_file (
53 glium_facade : &dyn glium::backend::Facade,
54 filepath : &'static str,
55 image_format : image::ImageFormat,
56 mipmaps : glium::texture::MipmapsOption
57) -> Result <glium::Texture2d, LoadError> {
58 log::debug!(filepath:?; "texture load file");
59 let bytes = std::fs::read (filepath)?;
60 texture2d_with_mipmaps_from_bytes (
61 glium_facade, bytes.as_slice(), image_format, mipmaps)
62}
63
64pub fn texture2darray_with_mipmaps_from_bytes (
67 glium_facade : &dyn glium::backend::Facade,
68 bytes_slices : &[&[u8]],
69 image_format : image::ImageFormat,
70 mipmaps : glium::texture::MipmapsOption
71) -> Result <glium::texture::Texture2dArray, LoadError> {
72 let raw_images = {
73 let mut v = Vec::with_capacity (bytes_slices.len());
74 for bytes in bytes_slices {
75 let img = image::load_from_memory_with_format (bytes, image_format)?.to_rgba8();
76 let img_dimensions = img.dimensions();
77 log::debug!(dimensions:?=img_dimensions; "texture array load bytes");
78 let raw_image_2d = glium::texture::RawImage2d::from_raw_rgba_reversed (
79 img.into_raw().as_slice(), img_dimensions);
80 v.push (raw_image_2d);
81 }
82 v
83 };
84
85 glium::texture::Texture2dArray::with_mipmaps (glium_facade, raw_images, mipmaps)
86 .map_err (Into::into)
87}
88
89pub fn texture2darray_with_mipmaps_from_files (
91 glium_facade : &dyn glium::backend::Facade,
92 filepaths : &[&'static str],
93 image_format : image::ImageFormat,
94 mipmaps : glium::texture::MipmapsOption
95) -> Result <glium::texture::Texture2dArray, LoadError> {
96 if filepaths.is_empty() {
97 return Err (std::io::Error::new (std::io::ErrorKind::InvalidInput,
98 "no input paths provided").into())
99 }
100
101 let bytes = {
102 let mut v = Vec::with_capacity (filepaths.len());
103 v.resize_with (filepaths.len(), Default::default);
104 for (i, filepath) in filepaths.iter().enumerate() {
105 log::debug!(filepath:?; "texture load file");
106 v[i] = std::fs::read (filepath)?;
107 }
108 v
109 };
110
111 let bytes_vec = {
112 let mut v = Vec::with_capacity (filepaths.len());
113 for bytes in bytes.iter() {
114 v.push (bytes.as_slice());
115 }
116 v
117 };
118
119 let texture2darray = texture2darray_with_mipmaps_from_bytes (
120 glium_facade, &bytes_vec, image_format, mipmaps)?;
121 Ok (texture2darray)
123}
124
125impl std::fmt::Display for LoadError {
129 fn fmt (&self, f : &mut std::fmt::Formatter) -> std::fmt::Result {
130 match self {
131 LoadError::IoError (err) => write!(f, "I/O error: {err}"),
132 LoadError::ImageError (err) => err.fmt (f),
133 LoadError::TextureCreationError (err) => err.fmt (f)
134 }
135 }
136}
137
138impl std::error::Error for LoadError {
139 fn source (&self) -> Option <&(dyn std::error::Error + 'static)> {
140 match self {
141 LoadError::IoError (err) => err.source(),
142 LoadError::ImageError (err) => err.source(),
143 LoadError::TextureCreationError (err) => err.source()
144 }
145 }
146}
147
148impl From <std::io::Error> for LoadError {
149 fn from (err : std::io::Error) -> Self {
150 LoadError::IoError (err)
151 }
152}
153
154impl From <image::ImageError> for LoadError {
155 fn from (err : image::ImageError) -> Self {
156 LoadError::ImageError (err)
157 }
158}
159
160impl From <glium::texture::TextureCreationError> for LoadError {
161 fn from (err : glium::texture::TextureCreationError) -> Self {
162 LoadError::TextureCreationError (err)
163 }
164}