///|
struct RawFrame {
filename : String?
frame : Rect
rotated : Bool
trimmed : Bool
spriteSourceSize : Rect
sourceSize : Size
duration : Int
} derive(Debug, Eq, ToJson, FromJson)
///|
struct RawFrameTag {
name : String
from : Int
to : Int
direction : String
} derive(Debug, Eq, ToJson, FromJson)
///|
struct RawSliceKey {
frame : Int
bounds : Rect
center : Rect?
pivot : Point?
} derive(Debug, Eq, ToJson, FromJson)
///|
struct RawSlice {
name : String
color : String?
keys : Array[RawSliceKey]
} derive(Debug, Eq, ToJson, FromJson)
///|
struct RawMeta {
image : String
size : Size
frameTags : Array[RawFrameTag]?
slices : Array[RawSlice]?
} derive(Debug, Eq, ToJson, FromJson)
///|
struct RawAsepriteSheet {
frames : Array[RawFrame]
meta : RawMeta
} derive(Debug, Eq, ToJson, FromJson)
///|
struct RawObjectAsepriteSheet {
frames : Map[String, RawFrame]
meta : RawMeta
} derive(Debug, Eq, ToJson, FromJson)
///|
pub fn Direction::from_string(text : String) -> Direction {
match text {
"reverse" => Reverse
"pingpong" => PingPong
_ => Forward
}
}
///|
fn normalize_tag(tag : RawFrameTag) -> FrameTag {
{
name: tag.name,
from: tag.from,
to: tag.to,
direction: Direction::from_string(tag.direction),
}
}
///|
fn normalize_slice(slice : RawSlice) -> Slice {
let keys : Array[SliceKey] = slice.keys.map(fn(key) {
{
frame: key.frame,
bounds: key.bounds,
center: key.center,
pivot: key.pivot,
}
})
let first : SliceKey = match keys.get(0) {
Some(key) => key
None =>
{
frame: 0,
bounds: { x: 0, y: 0, w: 0, h: 0 },
center: None,
pivot: None,
}
}
{
name: slice.name,
color: slice.color,
bounds: first.bounds,
center: first.center,
pivot: first.pivot,
keys,
}
}
///|
fn normalize_frame(frame : RawFrame, fallback_name : String) -> SourceFrame {
{
filename: match frame.filename {
Some(name) => name
None => fallback_name
},
frame: frame.frame,
rotated: frame.rotated,
trimmed: frame.trimmed,
sprite_source_size: frame.spriteSourceSize,
source_size: frame.sourceSize,
duration: frame.duration,
boxes: [],
}
}
///|
fn RawAsepriteSheet::normalize(self : RawAsepriteSheet) -> SpriteSheet {
{
image: self.meta.image,
size: self.meta.size,
frames: self.frames.map(fn(frame) {
let name = match frame.filename {
Some(name) => name
None => ""
}
normalize_frame(frame, name)
}),
tags: self.meta.frameTags.unwrap_or([]).map(normalize_tag),
slices: self.meta.slices.unwrap_or([]).map(normalize_slice),
}
}
///|
fn RawObjectAsepriteSheet::normalize(
self : RawObjectAsepriteSheet,
) -> SpriteSheet {
let entries = self.frames.to_array()
entries.sort_by(fn(a, b) { a.0.compare(b.0) })
{
image: self.meta.image,
size: self.meta.size,
frames: entries.map(fn(entry) { normalize_frame(entry.1, entry.0) }),
tags: self.meta.frameTags.unwrap_or([]).map(normalize_tag),
slices: self.meta.slices.unwrap_or([]).map(normalize_slice),
}
}
///|
pub fn parse_aseprite_json(text : String) -> SpriteSheet raise {
let value = @json.parse(text)
try {
let raw : RawAsepriteSheet = @json.from_json(value)
raw.normalize()
} catch {
_ => {
let raw : RawObjectAsepriteSheet = @json.from_json(value)
raw.normalize()
}
}
}