use crate::gm_enum::gm_enum;
use crate::prelude::*;
use crate::wad::build::builder::DataBuilder;
use crate::wad::chunk::gm_list_chunk;
use crate::wad::elem::GMElement;
use crate::wad::elem::GMNamedElement;
use crate::wad::elem::background::Tileset;
use crate::wad::elem::font::Font;
use crate::wad::elem::sprite::Sprite;
use crate::wad::elem::string::Strings;
use crate::wad::elem::texture_page::TexturePage;
use crate::wad::elem::validate_identifier;
use crate::wad::parse::reader::DataReader;
use crate::wad::reference::GMRef;
use crate::wad::version::LtsBranch;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct TextureGroupInfos {
pub elems: Vec<TextureGroupInfo>,
pub exists: bool,
}
gm_list_chunk!(TGIN, TextureGroupInfos, TextureGroupInfo, direct);
impl GMNamedElement for TextureGroupInfo {
fn name_ref(&self) -> GMRef<String> {
self.name
}
fn validate_name(&self, gm_strings: &Strings) -> Result<()> {
let name = self.name(gm_strings)?;
for part in name.split_terminator(".png") {
validate_identifier(part)?;
}
Ok(())
}
}
impl GMNamedListChunk for TextureGroupInfos {
fn ref_by_name(&self, name: &str, gm_strings: &Strings) -> Result<GMRef<Self::Element>> {
for (gm_ref, elem) in self.element_refs() {
let elem_name: &String = elem.name.resolve(&gm_strings.elems)?;
if name == elem_name {
return Ok(gm_ref);
}
}
Err(err!("Could not find Texture Group Info with name {name:?}"))
}
}
impl GMElement for TextureGroupInfos {
fn deserialize(reader: &mut DataReader) -> Result<Self> {
reader.read_gms2_chunk_version("TGIN Version")?;
let elems: Vec<TextureGroupInfo> = reader.read_pointer_list()?;
Ok(Self { elems, exists: true })
}
fn serialize(&self, builder: &mut DataBuilder) -> Result<()> {
builder.write_i32(1); builder.write_pointer_list(&self.elems)?;
Ok(())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TextureGroupInfo {
pub name: GMRef<String>,
pub texture_pages: Vec<GMRef<TexturePage>>,
pub sprites: Vec<GMRef<Sprite>>,
pub spine_sprites: Vec<GMRef<Sprite>>,
pub fonts: Vec<GMRef<Font>>,
pub tilesets: Vec<GMRef<Tileset>>,
pub data_2022_9: Option<Data2022_9>,
}
impl GMElement for TextureGroupInfo {
fn deserialize(reader: &mut DataReader) -> Result<Self> {
let name: GMRef<String> = reader.read_gm_string()?;
let data_2022_9: Option<Data2022_9> = reader.deserialize_if_gm_version((2022, 9))?;
let texture_pages_ptr = reader.read_u32()?;
let sprites_ptr = reader.read_u32()?;
let spine_sprites_ptr = if reader.general_info.version < (2023, 1, LtsBranch::PostLts) {
reader.read_u32()?
} else {
0
};
let fonts_ptr = reader.read_u32()?;
let tilesets_ptr = reader.read_u32()?;
reader.assert_pos(texture_pages_ptr, "Texture Pages")?;
let texture_pages: Vec<GMRef<TexturePage>> = reader.read_simple_list()?;
reader.assert_pos(sprites_ptr, "Sprites")?;
let sprites: Vec<GMRef<Sprite>> = reader.read_simple_list()?;
let spine_sprites: Vec<GMRef<Sprite>> =
if reader.general_info.version < (2023, 1, LtsBranch::PostLts) {
reader.assert_pos(spine_sprites_ptr, "Spine Sprites")?;
reader.read_simple_list()?
} else {
Vec::new()
};
reader.assert_pos(fonts_ptr, "Fonts")?;
let fonts: Vec<GMRef<Font>> = reader.read_simple_list()?;
reader.assert_pos(tilesets_ptr, "Tilesets")?;
let tilesets: Vec<GMRef<Tileset>> = reader.read_simple_list()?;
Ok(Self {
name,
texture_pages,
sprites,
spine_sprites,
fonts,
tilesets,
data_2022_9,
})
}
fn serialize(&self, builder: &mut DataBuilder) -> Result<()> {
builder.write_gm_string(self.name)?;
builder.write_if_ver(
&self.data_2022_9,
"Directory, Extension, LoadType",
(2022, 9),
)?;
builder.write_pointer(&self.texture_pages);
builder.write_pointer(&self.sprites);
if builder.version() < (2023, 1, LtsBranch::PostLts) {
builder.write_pointer(&self.spine_sprites);
}
builder.write_pointer(&self.fonts);
builder.write_pointer(&self.tilesets);
builder.resolve_pointer(&self.texture_pages)?;
builder.write_simple_list(&self.texture_pages)?;
builder.resolve_pointer(&self.sprites)?;
builder.write_simple_list(&self.sprites)?;
if builder.version() < (2023, 1, LtsBranch::PostLts) {
builder.resolve_pointer(&self.spine_sprites)?;
builder.write_simple_list(&self.spine_sprites)?;
}
builder.resolve_pointer(&self.fonts)?;
builder.write_simple_list(&self.fonts)?;
builder.resolve_pointer(&self.tilesets)?;
builder.write_simple_list(&self.tilesets)?;
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Data2022_9 {
pub directory: GMRef<String>,
pub extension: GMRef<String>,
pub load_type: LoadType,
}
impl GMElement for Data2022_9 {
fn deserialize(reader: &mut DataReader) -> Result<Self> {
let directory: GMRef<String> = reader.read_gm_string()?;
let extension: GMRef<String> = reader.read_gm_string()?;
let load_type: LoadType = reader.read_enum()?;
Ok(Self { directory, extension, load_type })
}
fn serialize(&self, builder: &mut DataBuilder) -> Result<()> {
builder.write_gm_string(self.directory)?;
builder.write_gm_string(self.extension)?;
builder.write_enum(self.load_type);
Ok(())
}
}
gm_enum!(LoadType {
InFile = 0,
SeparateGroup = 1,
SeparateTextures = 2,
});