use std::str::FromStr;
use crate::{
Atlas, AtlasOptions, Error, Export, ExportOptions, Font, Image, Limits, Lint, LintOptions,
Palette, PreviewOptions, Result, Sprite, Tilemap, Tileset,
};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Animation {
pub(crate) name: String,
pub(crate) frames: Vec<Frame>,
pub(crate) looping: bool,
}
impl Animation {
pub fn name(&self) -> &str {
&self.name
}
pub fn frames(&self) -> &[Frame] {
&self.frames
}
pub fn looping(&self) -> bool {
self.looping
}
pub fn total_ticks(&self) -> u64 {
self.frames.iter().map(|f| f.ticks as u64).sum()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Frame {
pub(crate) sprite: String,
pub(crate) ticks: u32,
pub(crate) flip_x: bool,
pub(crate) flip_y: bool,
}
impl Frame {
pub fn sprite(&self) -> &str {
&self.sprite
}
pub fn flip_x(&self) -> bool {
self.flip_x
}
pub fn flip_y(&self) -> bool {
self.flip_y
}
pub fn ticks(&self) -> u32 {
self.ticks
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Group {
pub(crate) name: String,
pub(crate) members: Vec<String>,
}
impl Group {
pub fn name(&self) -> &str {
&self.name
}
pub fn members(&self) -> &[String] {
&self.members
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Document {
pub(crate) palettes: Vec<Palette>,
pub(crate) sprites: Vec<Sprite>,
pub(crate) frame_sprites: Vec<Sprite>,
pub(crate) animations: Vec<Animation>,
pub(crate) tilesets: Vec<Tileset>,
pub(crate) tilemaps: Vec<Tilemap>,
pub(crate) fonts: Vec<Font>,
pub(crate) groups: Vec<Group>,
pub(crate) sources: crate::lint::Sources,
}
impl Document {
pub fn parse(text: &str) -> Result<Self> {
Self::parse_with(text, &Limits::default())
}
pub fn parse_with(text: &str, limits: &Limits) -> Result<Self> {
Self::finish(crate::text::parse(text, limits, None))
}
pub fn parse_with_loader(
text: &str,
limits: &Limits,
loader: &mut dyn FnMut(&str) -> Result<String>,
) -> Result<Self> {
Self::finish(crate::text::parse(text, limits, Some(loader)))
}
fn finish((document, mut errors): (Self, Vec<Error>)) -> Result<Self> {
if errors.is_empty() {
return Ok(document);
}
Err(errors.swap_remove(0))
}
pub fn palettes(&self) -> &[Palette] {
&self.palettes
}
pub fn palette(&self, name: &str) -> Option<&Palette> {
self.palettes.iter().find(|p| p.name == name)
}
pub fn sprites(&self) -> &[Sprite] {
&self.sprites
}
pub fn sprite(&self, name: &str) -> Option<&Sprite> {
self.sprites
.iter()
.chain(&self.frame_sprites)
.find(|s| s.name == name)
}
pub fn frame_sprites(&self) -> &[Sprite] {
&self.frame_sprites
}
pub fn animations(&self) -> &[Animation] {
&self.animations
}
pub fn animation(&self, name: &str) -> Option<&Animation> {
self.animations.iter().find(|a| a.name == name)
}
pub fn tilesets(&self) -> &[Tileset] {
&self.tilesets
}
pub fn tileset(&self, name: &str) -> Option<&Tileset> {
self.tilesets.iter().find(|t| t.name == name)
}
pub fn tilemaps(&self) -> &[Tilemap] {
&self.tilemaps
}
pub fn tilemap(&self, name: &str) -> Option<&Tilemap> {
self.tilemaps.iter().find(|t| t.name == name)
}
pub fn fonts(&self) -> &[Font] {
&self.fonts
}
pub fn font(&self, name: &str) -> Option<&Font> {
self.fonts.iter().find(|f| f.name == name)
}
pub fn groups(&self) -> &[Group] {
&self.groups
}
pub fn group(&self, name: &str) -> Option<&Group> {
self.groups.iter().find(|g| g.name == name)
}
pub fn atlas(&self, options: &AtlasOptions) -> Result<Atlas> {
self.atlas_with(options, &Limits::default())
}
pub fn atlas_with(&self, options: &AtlasOptions, limits: &Limits) -> Result<Atlas> {
crate::atlas::build(self, options, limits)
}
pub fn export(&self, options: &ExportOptions) -> Result<Export> {
self.export_with(options, &Limits::default())
}
pub fn export_with(&self, options: &ExportOptions, limits: &Limits) -> Result<Export> {
crate::export::build(self, options, limits)
}
pub fn lint(&self, options: &LintOptions) -> Lint {
self.lint_with(options, &Limits::default())
}
pub fn lint_with(&self, options: &LintOptions, limits: &Limits) -> Lint {
crate::lint::run(self, options, limits)
}
pub fn preview(&self, options: &PreviewOptions) -> Result<Image> {
self.preview_with(options, &Limits::default())
}
pub fn preview_with(&self, options: &PreviewOptions, limits: &Limits) -> Result<Image> {
crate::preview::sheet(self, options, limits)
}
}
impl FromStr for Document {
type Err = Error;
fn from_str(text: &str) -> Result<Self> {
Self::parse(text)
}
}
pub fn check(text: &str, limits: &Limits) -> Vec<Error> {
crate::text::parse(text, limits, None).1
}
pub fn check_with_loader(
text: &str,
limits: &Limits,
loader: &mut dyn FnMut(&str) -> Result<String>,
) -> Vec<Error> {
crate::text::parse(text, limits, Some(loader)).1
}