veloren_voxygen/ui/
img_ids.rs

1use super::{Graphic, SampleStrat, Transform};
2use common::{
3    assets::{self, AssetExt, DotVox, Error},
4    figure::Segment,
5};
6use std::sync::Arc;
7use vek::*;
8
9pub enum BlankGraphic {}
10pub enum ImageGraphic {}
11
12pub trait GraphicCreator<'a> {
13    type Specifier;
14    fn new_graphic(specifier: Self::Specifier) -> Result<Graphic, Error>;
15}
16impl GraphicCreator<'_> for BlankGraphic {
17    type Specifier = ();
18
19    fn new_graphic(_: ()) -> Result<Graphic, Error> { Ok(Graphic::Blank) }
20}
21impl<'a> GraphicCreator<'a> for ImageGraphic {
22    type Specifier = &'a str;
23
24    fn new_graphic(specifier: Self::Specifier) -> Result<Graphic, Error> {
25        let image = assets::Image::load(specifier)?.read().to_image();
26        Ok(Graphic::Image(image, None))
27    }
28}
29
30pub enum VoxelGraphic {}
31// TODO: Are these unneeded now that we have PixArtGraphic?
32pub enum VoxelSsGraphic {}
33pub enum VoxelSs4Graphic {}
34pub enum VoxelSs9Graphic {}
35
36pub enum VoxelPixArtGraphic {}
37
38fn load_segment(specifier: &str) -> Result<Arc<Segment>, Error> {
39    let dot_vox = DotVox::load(specifier)?;
40    let seg = Segment::from_vox_model_index(&dot_vox.read().0, 0, None);
41    Ok(Arc::new(seg))
42}
43
44impl<'a> GraphicCreator<'a> for VoxelGraphic {
45    type Specifier = &'a str;
46
47    fn new_graphic(specifier: Self::Specifier) -> Result<Graphic, Error> {
48        Ok(Graphic::Voxel(
49            load_segment(specifier)?,
50            Transform {
51                ori: Quaternion::rotation_x(-std::f32::consts::PI / 2.0),
52                ..Default::default()
53            },
54            SampleStrat::None,
55        ))
56    }
57}
58impl<'a> GraphicCreator<'a> for VoxelSsGraphic {
59    type Specifier = (&'a str, u8);
60
61    fn new_graphic(specifier: Self::Specifier) -> Result<Graphic, Error> {
62        Ok(Graphic::Voxel(
63            load_segment(specifier.0)?,
64            Transform {
65                ori: Quaternion::rotation_x(-std::f32::consts::PI / 2.0),
66                ..Default::default()
67            },
68            SampleStrat::SuperSampling(specifier.1),
69        ))
70    }
71}
72impl<'a> GraphicCreator<'a> for VoxelSs4Graphic {
73    type Specifier = &'a str;
74
75    fn new_graphic(specifier: Self::Specifier) -> Result<Graphic, Error> {
76        Ok(Graphic::Voxel(
77            load_segment(specifier)?,
78            Transform {
79                ori: Quaternion::rotation_x(-std::f32::consts::PI / 2.0),
80                ..Default::default()
81            },
82            SampleStrat::SuperSampling(4),
83        ))
84    }
85}
86impl<'a> GraphicCreator<'a> for VoxelSs9Graphic {
87    type Specifier = &'a str;
88
89    fn new_graphic(specifier: Self::Specifier) -> Result<Graphic, Error> {
90        Ok(Graphic::Voxel(
91            load_segment(specifier)?,
92            Transform {
93                ori: Quaternion::rotation_x(-std::f32::consts::PI / 2.0),
94                ..Default::default()
95            },
96            SampleStrat::SuperSampling(9),
97        ))
98    }
99}
100impl<'a> GraphicCreator<'a> for VoxelPixArtGraphic {
101    type Specifier = &'a str;
102
103    fn new_graphic(specifier: Self::Specifier) -> Result<Graphic, Error> {
104        Ok(Graphic::Voxel(
105            load_segment(specifier)?,
106            Transform {
107                ori: Quaternion::rotation_x(-std::f32::consts::PI / 2.0),
108                ..Default::default()
109            },
110            SampleStrat::PixelCoverage,
111        ))
112    }
113}
114
115pub struct Rotations {
116    pub none: conrod_core::image::Id,
117    pub cw90: conrod_core::image::Id,
118    pub cw180: conrod_core::image::Id,
119    pub cw270: conrod_core::image::Id,
120    pub source_north: conrod_core::image::Id,
121    pub target_north: conrod_core::image::Id,
122    pub target_player: conrod_core::image::Id,
123}
124
125/// This macro will automatically load all specified assets, get the
126/// corresponding ImgIds and create a struct with all of them.
127///
128/// Example usage:
129/// ```ignore
130/// use veloren_voxygen::{
131///     image_ids,
132///     ui::img_ids::{BlankGraphic, ImageGraphic, VoxelGraphic},
133/// };
134///
135/// image_ids! {
136///     pub struct Imgs {
137///         <VoxelGraphic>
138///         button1: "specifier1",
139///         button2: "specifier2",
140///
141///         <ImageGraphic>
142///         background: "background",
143///
144///         <BlankGraphic>
145///         blank: (),
146///     }
147/// }
148/// ```
149#[macro_export]
150macro_rules! image_ids {
151    ($($v:vis struct $Ids:ident { $( <$T:ty> $( $name:ident: $specifier:expr ),* $(,)? )* })*) => {
152        $(
153            $v struct $Ids {
154                $($( $v $name: conrod_core::image::Id, )*)*
155            }
156
157            impl $Ids {
158                pub fn load(ui: &mut $crate::ui::Ui) -> Result<Self, common::assets::Error> {
159                    use $crate::ui::img_ids::GraphicCreator;
160                    Ok(Self {
161                        $($( $name: ui.add_graphic(<$T as GraphicCreator>::new_graphic($specifier)?), )*)*
162                    })
163                }
164            }
165        )*
166    };
167}
168#[macro_export]
169macro_rules! image_ids_ice {
170    ($($v:vis struct $Ids:ident { $( <$T:ty> $( $(#[$($attribute:tt)*])? $name:ident: $specifier:expr ),* $(,)? )* })*) => {
171        $(
172            $v struct $Ids {
173                $($( $(#[$($attribute)*])? $v $name: $crate::ui::GraphicId, )*)*
174            }
175
176            impl $Ids {
177                pub fn load(ui: &mut $crate::ui::ice::IcedUi) -> Result<Self, common::assets::Error> {
178                    use $crate::ui::img_ids::GraphicCreator;
179                    Ok(Self {
180                        $($( $(#[$($attribute)*])? $name: ui.add_graphic(<$T as GraphicCreator>::new_graphic($specifier)?), )*)*
181                    })
182                }
183            }
184        )*
185    };
186}
187
188// TODO: combine with the img_ids macro above using a marker for specific fields
189// that should be `Rotations` instead of `widget::Id`
190#[macro_export]
191macro_rules! rotation_image_ids {
192    ($($v:vis struct $Ids:ident { $( <$T:ty> $( $name:ident: $specifier:expr ),* $(,)? )* })*) => {
193        $(
194            $v struct $Ids {
195                $($( $v $name: $crate::ui::img_ids::Rotations, )*)*
196            }
197
198            impl $Ids {
199                pub fn load(ui: &mut $crate::ui::Ui) -> Result<Self, common::assets::Error> {
200                    use $crate::ui::img_ids::GraphicCreator;
201                    Ok(Self {
202                        $($( $name: ui.add_graphic_with_rotations(<$T as GraphicCreator>::new_graphic($specifier)?), )*)*
203                    })
204                }
205            }
206        )*
207    };
208}