glacier_texture/
enums.rs

1use binrw::{BinRead, BinWrite};
2use bitfield_struct::bitfield;
3use directxtex::{DXGI_FORMAT, TEX_DIMENSION};
4use serde::{Deserialize, Serialize};
5use thiserror::Error;
6
7#[derive(BinRead, BinWrite, Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Default)]
8#[brw(repr = u16)]
9pub enum TextureType
10{
11    Colour = 0,
12    #[default]
13    Normal = 1,
14    Height = 2,
15    CompoundNormal = 3,
16    Billboard = 4,
17    Projection = 6,
18    Emission = 16,
19    //UNKNOWN64 = 64, //unused
20
21    //UNKNOWN128 = 128, //unused in H2, H3
22    Cubemap = 256, //uses ascolormap and ascubemap
23    UNKNOWN512 = 512, //asheightmap
24    //UNKNOWN1024 = 1024, //unused
25}
26
27#[derive(BinRead, BinWrite, Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Default)]
28#[brw(repr = u8)]
29pub enum InterpretAs
30{
31    Colour = 0,
32    #[default]
33    Normal = 1,
34    Height = 2,
35    CompoundNormal = 3,
36    Billboard = 4,
37    Cubemap = 6,
38    Emission = 16, //This is an assumption
39    Volume = 64, //This as well
40}
41
42
43#[derive(BinRead, BinWrite, Serialize, Deserialize, Debug, Copy)]
44#[brw(repr = u16)]
45#[derive(Clone, PartialEq, Hash, Eq)]
46pub enum RenderFormat
47{
48    R16G16B16A16 = 0x0A,
49    R8G8B8A8 = 0x1C,
50    R8G8 = 0x34,
51    A8 = 0x42,
52    BC1 = 0x49,
53    BC2 = 0x4C,
54    BC3 = 0x4F,
55    BC4 = 0x52,
56    BC5 = 0x55,
57    BC7 = 0x5A,
58}
59
60impl RenderFormat {
61    pub fn is_compressed(&self) -> bool {
62        matches!(self, RenderFormat::BC1|
63            RenderFormat::BC2|
64            RenderFormat::BC3|
65            RenderFormat::BC4|
66            RenderFormat::BC5|
67            RenderFormat::BC7)
68    }
69
70    pub fn num_channels(&self) -> usize {
71        match self {
72            RenderFormat::A8 | RenderFormat::BC4 => 1,
73            RenderFormat::R8G8 | RenderFormat::BC5 => 2,
74            RenderFormat::BC1 | //assume DXT1a
75            RenderFormat::R16G16B16A16 |
76            RenderFormat::R8G8B8A8 |
77            RenderFormat::BC2 |
78            RenderFormat::BC3 |
79            RenderFormat::BC7 => 4,
80        }
81    }
82}
83
84impl From<RenderFormat> for DXGI_FORMAT {
85    fn from(value: RenderFormat) -> Self {
86        match value {
87            RenderFormat::R16G16B16A16 => { DXGI_FORMAT::DXGI_FORMAT_R16G16B16A16_FLOAT } // has to be float
88            RenderFormat::R8G8B8A8 => { DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM }
89            RenderFormat::R8G8 => { DXGI_FORMAT::DXGI_FORMAT_R8G8_UNORM }
90            RenderFormat::A8 => { DXGI_FORMAT::DXGI_FORMAT_A8_UNORM }
91            RenderFormat::BC1 => { DXGI_FORMAT::DXGI_FORMAT_BC1_UNORM }
92            RenderFormat::BC2 => { DXGI_FORMAT::DXGI_FORMAT_BC2_UNORM }
93            RenderFormat::BC3 => { DXGI_FORMAT::DXGI_FORMAT_BC3_UNORM }
94            RenderFormat::BC4 => { DXGI_FORMAT::DXGI_FORMAT_BC4_UNORM }
95            RenderFormat::BC5 => { DXGI_FORMAT::DXGI_FORMAT_BC5_UNORM }
96            RenderFormat::BC7 => { DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM }
97        }
98    }
99}
100
101#[derive(Debug, Error)]
102#[error("Unsupported DXGI_FORMAT")]
103pub struct UnsupportedFormatError;
104
105impl TryFrom<DXGI_FORMAT> for RenderFormat {
106    type Error = UnsupportedFormatError;
107
108    fn try_from(value: DXGI_FORMAT) -> Result<Self, Self::Error> {
109        match value {
110            DXGI_FORMAT::DXGI_FORMAT_R16G16B16A16_UNORM => Ok(RenderFormat::R16G16B16A16),
111            DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM => Ok(RenderFormat::R8G8B8A8),
112            DXGI_FORMAT::DXGI_FORMAT_R8G8_UNORM => Ok(RenderFormat::R8G8),
113            DXGI_FORMAT::DXGI_FORMAT_A8_UNORM => Ok(RenderFormat::A8),
114            DXGI_FORMAT::DXGI_FORMAT_BC1_UNORM => Ok(RenderFormat::BC1),
115            DXGI_FORMAT::DXGI_FORMAT_BC2_UNORM => Ok(RenderFormat::BC2),
116            DXGI_FORMAT::DXGI_FORMAT_BC3_UNORM => Ok(RenderFormat::BC3),
117            DXGI_FORMAT::DXGI_FORMAT_BC4_UNORM => Ok(RenderFormat::BC4),
118            DXGI_FORMAT::DXGI_FORMAT_BC5_UNORM => Ok(RenderFormat::BC5),
119            DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM => Ok(RenderFormat::BC7),
120            _ => Err(UnsupportedFormatError),
121        }
122    }
123}
124
125#[derive(BinRead, BinWrite, Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Default)]
126#[brw(repr = u8)]
127pub enum Dimensions
128{
129    #[default]
130    _2D = 0,
131    Cube = 1,
132    Volume = 2,
133}
134
135impl From<Dimensions> for TEX_DIMENSION {
136    fn from(val: Dimensions) -> Self {
137        match val {
138            Dimensions::_2D => { TEX_DIMENSION::TEX_DIMENSION_TEXTURE2D }
139            Dimensions::Cube => { TEX_DIMENSION::TEX_DIMENSION_TEXTURE3D }
140            Dimensions::Volume => { TEX_DIMENSION::TEX_DIMENSION_TEXTURE2D }
141        }
142    }
143}
144
145#[bitfield(u32)]
146#[derive(BinRead, BinWrite, Serialize, Deserialize)]
147//#[brw(repr = u32)]
148//most of these are unused...
149pub(crate) struct TextureFlagsInner
150{
151    /* 0x1 */ pub(crate) swizzled: bool,
152    /* 0x2 */ pub(crate) deferred: bool,           //Only used on 4x4 textures
153    /* 0x4 */ pub(crate) memory_read_xbox_360: bool,
154    /* 0x8 */ pub(crate) unknown1: bool,           //Does not affect the texture in-game. Usually not enabled on non-normal/color types, or uncompressed formats
155    /* 0x10 */pub(crate) atlas: bool,              //Only used on atlas textures
156    /* 0x20 */pub(crate) ddsc_encoded: bool,
157    /* 0x40 */pub(crate) unknown3: bool,           //Not enabling this will corrupt most textures
158
159    #[bits(25)]
160    __: u32,
161}
162
163pub struct TextureFlags{
164    ///inner "real" flags bitfield. Wrapped because it is likely to change over time.
165    /// Wrapping the struct makes it possible to #\[deprecated\] old getters and setters
166    pub(crate) inner: TextureFlagsInner
167}
168
169/// Flags set in the texture files.
170/// The "unstable" flags are not found in any production texture file. Use at your own risk
171/// The other flags should not crash the game, but can also result in corrupted textures, use with caution
172impl TextureFlags{
173
174    pub fn deferred(&self) -> bool { self.inner.deferred() }
175    pub fn unknown1(&self) -> bool { self.inner.unknown1() }
176    pub fn atlas(&self) -> bool { self.inner.atlas() }
177    pub fn unknown3(&self) -> bool { self.inner.unknown3() }
178
179    pub fn set_deferred(&mut self, value: bool) {
180        self.inner.set_deferred(value)
181    }
182    pub fn set_unknown1(&mut self, value: bool) {
183        self.inner.set_unknown1(value)
184    }
185    pub fn set_unknown3(&mut self, value: bool) {
186        self.inner.set_unknown3(value)
187    }
188
189    pub fn set_atlas(&mut self, value: bool) {
190    self.inner.set_atlas(value)
191    }
192    pub fn with_deferred(&self, value: bool) -> Self{
193        Self{
194            inner: self.inner.with_deferred(value)
195        }
196    }
197    pub fn with_unknown1(&mut self, value: bool) -> Self{
198        Self{
199            inner: self.inner.with_unknown1(value)
200        }
201    }
202    pub fn with_atlas(&mut self, value: bool) -> Self{
203        Self{
204            inner: self.inner.with_atlas(value)
205        }
206    }
207    pub fn with_unknown3(&mut self, value: bool) -> Self{
208        Self{
209            inner: self.inner.with_unknown3(value)
210        }
211    }
212
213    #[cfg(feature = "unstable")]
214    pub fn swizzled(&self) -> bool { self.inner.swizzled() }
215
216    #[cfg(feature = "unstable")]
217    pub fn memory_read_xbox_360(&self) -> bool { self.inner.memory_read_xbox_360() }
218
219    #[cfg(feature = "unstable")]
220    pub fn ddsc_encoded(&self) -> bool { self.inner.ddsc_encoded() }
221
222    #[cfg(feature = "unstable")]
223    pub fn set_swizzled(&mut self, value: bool) {
224        self.inner.set_swizzled(value)
225    }
226
227    #[cfg(feature = "unstable")]
228    pub fn set_memory_read_xbox_360(&mut self, value: bool) {
229        self.inner.set_memory_read_xbox_360(value)
230    }
231
232    #[cfg(feature = "unstable")]
233    pub fn set_ddsc_encoded(&mut self, value: bool) {
234        self.inner.set_ddsc_encoded(value)
235    }
236
237    #[cfg(feature = "unstable")]
238    pub fn with_swizzled(&self, value: bool) -> Self {
239        Self {
240            inner: self.inner.with_swizzled(value),
241        }
242    }
243
244    #[cfg(feature = "unstable")]
245    pub fn with_memory_read_xbox_360(&self, value: bool) -> Self {
246        Self {
247            inner: self.inner.with_memory_read_xbox_360(value),
248        }
249    }
250
251    #[cfg(feature = "unstable")]
252    pub fn with_ddsc_encoded(&self, value: bool) -> Self {
253        Self {
254            inner: self.inner.with_ddsc_encoded(value),
255        }
256    }
257}