///|
pub struct CatalogInput {
key : String
sheet : SpriteSheet
} derive(Debug, Eq, ToJson, FromJson)
///|
pub struct CatalogEntry {
key : String
image : String
frame_count : Int
animation_count : Int
slice_count : Int
duration : Int
valid : Bool
} derive(Debug, Eq, ToJson, FromJson)
///|
pub struct AssetCatalog {
entries : Array[CatalogEntry]
} derive(Debug, Eq, ToJson, FromJson)
///|
pub fn catalog_entry(key : String, sheet : SpriteSheet) -> CatalogEntry {
let metrics = sheet_metrics(sheet)
let machine = build_machine(sheet)
{
key,
image: metrics.image,
frame_count: metrics.frame_count,
animation_count: machine.clips.length(),
slice_count: metrics.slice_count,
duration: metrics.total_duration,
valid: sheet_is_valid(sheet),
}
}
///|
pub fn catalog_from_sheets(inputs : Array[CatalogInput]) -> AssetCatalog {
{ entries: inputs.map(fn(input) { catalog_entry(input.key, input.sheet) }) }
}
///|
pub fn AssetCatalog::empty() -> AssetCatalog {
{ entries: [] }
}
///|
pub fn AssetCatalog::add(
self : AssetCatalog,
key : String,
sheet : SpriteSheet,
) -> AssetCatalog {
let entries = self.entries.copy()
entries.push(catalog_entry(key, sheet))
{ entries, }
}
///|
pub fn AssetCatalog::find(self : AssetCatalog, key : String) -> CatalogEntry? {
match self.entries.search_by(fn(entry) { entry.key == key }) {
Some(index) => Some(self.entries[index])
None => None
}
}
///|
pub fn AssetCatalog::remove(self : AssetCatalog, key : String) -> AssetCatalog {
{ entries: self.entries.filter(fn(entry) { entry.key != key }) }
}
///|
pub fn AssetCatalog::total_frames(self : AssetCatalog) -> Int {
self.entries.fold(init=0, (total, entry) => total + entry.frame_count)
}
///|
pub fn AssetCatalog::total_animations(self : AssetCatalog) -> Int {
self.entries.fold(init=0, (total, entry) => total + entry.animation_count)
}
///|
pub fn AssetCatalog::total_duration(self : AssetCatalog) -> Int {
self.entries.fold(init=0, (total, entry) => total + entry.duration)
}
///|
pub fn AssetCatalog::valid_count(self : AssetCatalog) -> Int {
self.entries.fold(init=0, (total, entry) => {
if entry.valid {
total + 1
} else {
total
}
})
}
///|
pub fn AssetCatalog::invalid_count(self : AssetCatalog) -> Int {
self.entries.length() - self.valid_count()
}
///|
pub fn AssetCatalog::duplicate_keys(self : AssetCatalog) -> Array[String] {
let duplicates : Array[String] = []
for i in 0.. Array[String] {
self.entries.map(fn(entry) { entry.key })
}
///|
pub fn AssetCatalog::images(self : AssetCatalog) -> Array[String] {
self.entries.map(fn(entry) { entry.image })
}
///|
pub fn AssetCatalog::filter_valid(self : AssetCatalog) -> AssetCatalog {
{ entries: self.entries.filter(fn(entry) { entry.valid }) }
}
///|
pub fn AssetCatalog::filter_invalid(self : AssetCatalog) -> AssetCatalog {
{ entries: self.entries.filter(fn(entry) { !entry.valid }) }
}
///|
pub fn AssetCatalog::filter_prefix(
self : AssetCatalog,
prefix : String,
) -> AssetCatalog {
{ entries: self.entries.filter(fn(entry) { entry.key.has_prefix(prefix) }) }
}
///|
pub fn AssetCatalog::sort_by_frames(self : AssetCatalog) -> AssetCatalog {
let entries = self.entries.copy()
entries.sort_by(fn(left, right) {
right.frame_count.compare(left.frame_count)
})
{ entries, }
}
///|
pub fn AssetCatalog::sort_by_key(self : AssetCatalog) -> AssetCatalog {
let entries = self.entries.copy()
entries.sort_by(fn(left, right) { left.key.compare(right.key) })
{ entries, }
}
///|
pub fn AssetCatalog::merge(
self : AssetCatalog,
other : AssetCatalog,
) -> AssetCatalog {
let entries = self.entries.copy()
for entry in other.entries {
entries.push(entry)
}
{ entries, }
}
///|
pub fn AssetCatalog::to_json_string(
self : AssetCatalog,
indent? : Int = 2,
) -> String {
self.to_json().stringify(indent~)
}
///|
pub fn AssetCatalog::summary(self : AssetCatalog) -> String {
"\{self.entries.length()} assets, \{self.total_frames()} frames, \{self.total_animations()} animations, \{self.valid_count()} valid"
}
///|
pub fn AssetCatalog::has_key(self : AssetCatalog, key : String) -> Bool {
self.find(key) is Some(_)
}
///|
pub fn AssetCatalog::has_invalid(self : AssetCatalog) -> Bool {
self.invalid_count() > 0
}
///|
pub fn AssetCatalog::is_unique(self : AssetCatalog) -> Bool {
self.duplicate_keys().length() == 0
}
///|
pub fn AssetCatalog::entry_count(self : AssetCatalog) -> Int {
self.entries.length()
}
///|
pub fn AssetCatalog::average_frames(self : AssetCatalog) -> Double {
if self.entries.length() == 0 {
0.0
} else {
self.total_frames().to_double() / self.entries.length().to_double()
}
}
///|
pub fn AssetCatalog::largest_entry(self : AssetCatalog) -> CatalogEntry? {
match self.entries.get(0) {
None => None
Some(first) => {
let mut result = first
for entry in self.entries[1:] {
if entry.frame_count > result.frame_count {
result = entry
}
}
Some(result)
}
}
}
///|
pub fn catalog_json(inputs : Array[CatalogInput], indent? : Int = 2) -> String {
catalog_from_sheets(inputs).to_json_string(indent~)
}
///|
pub fn catalog_validate(catalog : AssetCatalog) -> Bool {
catalog.is_unique() && !catalog.has_invalid()
}