///|
fn parse_sprite_sheet_root(json : Json, source_length~ : Int) -> SpriteSheet {
let frames = parse_frames(json_field(json, "frames"))
{ frames, meta: parse_meta(json_field(json, "meta")), source_length }
}
///|
fn parse_frames(value : Json?) -> Array[FrameInfo] {
match value {
Some(Array(items)) => parse_frame_array(items)
Some(Object(_)) => parse_frame_object(value)
_ => []
}
}
///|
fn parse_frame_array(items : Array[Json]) -> Array[FrameInfo] {
let frames : Array[FrameInfo] = []
for i, item in items {
match item {
Object(_) =>
frames.push(
parse_frame_item(
item,
i,
json_string_value(
json_field(item, "filename"),
default="frame_\{i}",
),
),
)
_ => ()
}
}
frames
}
///|
fn parse_frame_object(value : Json?) -> Array[FrameInfo] {
let frames : Array[FrameInfo] = []
let pairs = json_object_pairs(value)
for i, pair in pairs {
let (name, item) = pair
match item {
Object(_) => frames.push(parse_frame_item(item, i, name))
_ => ()
}
}
frames
}
///|
fn parse_frame_item(json : Json, index : Int, name : String) -> FrameInfo {
FrameInfo::new(
name,
index,
json_rect_value(json_field(json, "frame")),
json_int_value(json_field(json, "duration"), default=100),
rotated=json_bool_value(json_field(json, "rotated")),
trimmed=json_bool_value(json_field(json, "trimmed")),
sprite_source_size=json_rect_value(json_field(json, "spriteSourceSize")),
source_size=json_size_value(json_field(json, "sourceSize")),
)
}
///|
fn parse_meta(value : Json?) -> SpriteSheetMeta {
match value {
Some(meta) =>
match meta {
Object(_) =>
{
app: json_string_value(json_field(meta, "app")),
version: json_string_value(json_field(meta, "version")),
image: json_string_value(json_field(meta, "image")),
format: json_string_value(json_field(meta, "format")),
scale: json_string_value(json_field(meta, "scale"), default="1"),
size: json_size_value(json_field(meta, "size")),
frame_tags: parse_frame_tags(json_array_field(meta, "frameTags")),
layers: parse_layers(json_array_field(meta, "layers")),
slices: parse_slices(json_array_field(meta, "slices")),
}
_ => SpriteSheetMeta::empty()
}
_ => SpriteSheetMeta::empty()
}
}
///|
fn parse_frame_tags(items : Array[Json]) -> Array[FrameTag] {
let out : Array[FrameTag] = []
for item in items {
match item {
Object(_) =>
out.push(
FrameTag::new(
json_string_value(json_field(item, "name")),
json_int_value(json_field(item, "from")),
json_int_value(json_field(item, "to")),
direction=TagDirection::from_string(
json_string_value(
json_field(item, "direction"),
default="forward",
),
),
color=json_string_value(json_field(item, "color")),
user_data=json_string_value(json_field(item, "data")),
),
)
_ => ()
}
}
out
}
///|
fn parse_layers(items : Array[Json]) -> Array[LayerInfo] {
let out : Array[LayerInfo] = []
for item in items {
match item {
Object(_) =>
out.push(
LayerInfo::new(
json_string_value(json_field(item, "name")),
opacity=json_int_value(json_field(item, "opacity"), default=255),
blend_mode=json_string_value(
json_field(item, "blendMode"),
default="normal",
),
visible=json_bool_value(json_field(item, "visible"), default=true),
),
)
_ => ()
}
}
out
}
///|
fn parse_slices(items : Array[Json]) -> Array[SliceInfo] {
let out : Array[SliceInfo] = []
for item in items {
match item {
Object(_) =>
out.push(
SliceInfo::new(
json_string_value(json_field(item, "name")),
parse_slice_keys(json_array_field(item, "keys")),
color=json_string_value(json_field(item, "color")),
),
)
_ => ()
}
}
out
}
///|
fn parse_slice_keys(items : Array[Json]) -> Array[SliceKey] {
let out : Array[SliceKey] = []
for item in items {
match item {
Object(_) => out.push(parse_slice_key(item))
_ => ()
}
}
out
}
///|
fn parse_slice_key(json : Json) -> SliceKey {
let center = json_rect_value(json_field(json, "center"))
let pivot_json = json_field(json, "pivot")
let pivot = match pivot_json {
Some(pivot_value) =>
match pivot_value {
Object(_) =>
Point::new(
json_int_value(json_field(pivot_value, "x")),
json_int_value(json_field(pivot_value, "y")),
)
_ => Point::new(0, 0)
}
_ => Point::new(0, 0)
}
SliceKey::new(
json_int_value(json_field(json, "frame")),
json_rect_value(json_field(json, "bounds")),
center~,
pivot~,
has_center=json_field(json, "center") != None,
has_pivot=json_field(json, "pivot") != None,
)
}
///|
pub fn infer_frame_rate(sheet : SpriteSheet) -> Int {
if sheet.frames.length() == 0 {
0
} else {
let total = sheet.duration_ms()
if total <= 0 {
0
} else {
sheet.frames.length() * 1000 / total
}
}
}
///|
pub fn sheet_uses_trimmed_frames(sheet : SpriteSheet) -> Bool {
for frame in sheet.frames {
if frame.trimmed {
return true
}
}
false
}
///|
pub fn sheet_has_rotated_frames(sheet : SpriteSheet) -> Bool {
for frame in sheet.frames {
if frame.rotated {
return true
}
}
false
}
///|
pub fn collect_frame_names(sheet : SpriteSheet) -> Array[String] {
let names : Array[String] = []
for frame in sheet.frames {
names.push(frame.name)
}
names
}
///|
pub fn collect_tag_names(sheet : SpriteSheet) -> Array[String] {
let names : Array[String] = []
for tag in sheet.meta.frame_tags {
names.push(tag.name)
}
names
}
///|
pub fn collect_slice_names(sheet : SpriteSheet) -> Array[String] {
let names : Array[String] = []
for slice in sheet.meta.slices {
names.push(slice.name)
}
names
}