i think 2.0 icons are kinda working

This commit is contained in:
Reid 2023-10-03 21:39:04 -07:00
parent 0f7ecba1ab
commit 4657c177b0
Signed by: reidlab
GPG key ID: 6C9EAA3364F962C8
7 changed files with 522 additions and 34 deletions

331
Cargo.lock generated
View file

@ -2,12 +2,27 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "ab_glyph_rasterizer"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "approx"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
dependencies = [
"num-traits",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -56,6 +71,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "conv"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
dependencies = [
"custom_derive",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
@ -104,6 +128,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "custom_derive"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
[[package]]
name = "deranged"
version = "0.3.8"
@ -165,8 +195,32 @@ name = "gd-icon-renderer"
version = "0.1.0"
dependencies = [
"image",
"imageproc",
"maplit",
"plist",
"rand 0.8.5",
]
[[package]]
name = "getrandom"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [
"cfg-if",
"libc",
"wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
@ -213,6 +267,24 @@ dependencies = [
"tiff",
]
[[package]]
name = "imageproc"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aee993351d466301a29655d628bfc6f5a35a0d062b6160ca0808f425805fd7"
dependencies = [
"approx",
"conv",
"image",
"itertools",
"nalgebra",
"num",
"rand 0.7.3",
"rand_distr",
"rayon",
"rusttype",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@ -223,6 +295,15 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.9"
@ -244,6 +325,12 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libc"
version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]]
name = "line-wrap"
version = "0.1.1"
@ -269,6 +356,16 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "matrixmultiply"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
dependencies = [
"autocfg",
"rawpointer",
]
[[package]]
name = "memchr"
version = "2.6.3"
@ -294,6 +391,55 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "nalgebra"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb2d0de08694bed883320212c18ee3008576bfe8c306f4c3c4a58b4876998be"
dependencies = [
"approx",
"matrixmultiply",
"num-complex",
"num-rational",
"num-traits",
"simba",
"typenum",
]
[[package]]
name = "num"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
@ -304,6 +450,17 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
@ -311,6 +468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits",
]
@ -324,6 +482,21 @@ dependencies = [
"autocfg",
]
[[package]]
name = "owned_ttf_parser"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05e6affeb1632d6ff6a23d2cd40ffed138e82f1532571a26f527c8a284bb2fbb"
dependencies = [
"ttf-parser",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "plist"
version = "1.5.0"
@ -351,6 +524,12 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.67"
@ -387,6 +566,92 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom 0.1.16",
"libc",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core 0.5.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom 0.1.16",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.10",
]
[[package]]
name = "rand_distr"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
dependencies = [
"rand 0.7.3",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "rayon"
version = "1.8.0"
@ -407,6 +672,25 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "rusttype"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff8374aa04134254b7995b63ad3dc41c7f7236f69528b28553da7d72efaa967"
dependencies = [
"ab_glyph_rasterizer",
"owned_ttf_parser",
]
[[package]]
name = "safe_arch"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354"
dependencies = [
"bytemuck",
]
[[package]]
name = "safemem"
version = "0.3.3"
@ -439,6 +723,19 @@ dependencies = [
"syn",
]
[[package]]
name = "simba"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f3fd720c48c53cace224ae62bef1bbff363a70c68c4802a78b5cc6159618176"
dependencies = [
"approx",
"num-complex",
"num-traits",
"paste",
"wide",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
@ -510,18 +807,52 @@ dependencies = [
"time-core",
]
[[package]]
name = "ttf-parser"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "weezl"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
[[package]]
name = "wide"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa469ffa65ef7e0ba0f164183697b89b854253fd31aeb92358b7b6155177d62f"
dependencies = [
"bytemuck",
"safe_arch",
]
[[package]]
name = "zune-inflate"
version = "0.2.54"

View file

@ -5,5 +5,7 @@ edition = "2021"
[dependencies]
image = "0.24.7"
imageproc = "0.23.0"
maplit = "1.0.2"
plist = "1.5.0"
rand = "0.8.5"

View file

@ -1,6 +1,6 @@
# gd-icon-renderer
rust geometryd ash icon redner!!
rust geometryd ash icon redner!! shout out to [gd-icon-renderer](https://github.com/oatmealine/gd-icon-renderer) oat
## usage
@ -8,7 +8,7 @@ Provide your `GJ_GameSheet02-uhd`, `GJ_GameSheetGlow-uhd`, `Robot_AnimDesc2`, an
## todo
- maybe use custom plist parser
- spider + robot support
- make `get_sprite_from_loaded` and `get_sprite` merged into `get_sprite`. i think this needs traits or something
- trim empty alpha space (robtop didnt make the bounds correctly :sob:)
- use custom plist parser. current one takes like 5 seconds to parse an animation file
- change zany anim to argument
- trim empty alpha space (robtop didnt make the bounds correctly :sob:)
- i think theres some slight shifting in the transform to do with rotation. investigate plz. really big on spider 16 for some reason????

View file

@ -128,6 +128,72 @@ pub fn load_spritesheet(path: &str) -> LoadedSpritesheet {
}
}
// Represents the metadata of an animation frame's sprite
#[derive(Clone, Debug)]
pub struct AnimationSprite {
pub texture: String,
pub position: (f32, f32),
pub scale: (f32, f32),
pub rotation: f64,
pub flipped: (bool, bool),
pub z: i32
}
impl AnimationSprite {
fn initialize(obj: plist::Value) -> AnimationSprite {
let hash = obj.as_dictionary().expect("object must be a dict");
let hash_keys = vec!["texture", "position", "scale", "rotation", "flipped", "zValue"];
let isolated: Vec<(&&str, Option<&plist::Value>)> = hash_keys
.iter()
.map(|s| (s, hash.get(s)))
.collect();
let missing: Vec<&(&&str, Option<&plist::Value>)> = isolated
.iter()
.filter(|&&(_, value)| value.is_none())
.collect();
if !missing.is_empty() {
let missing_entries: Vec<&str> = missing.iter().map(|(&key, _)| key).collect();
panic!("missing entries: {:?}", missing_entries);
}
let isolated_hash: HashMap<String, plist::Value> = isolated
.iter()
.map(|&(key, value)| (key.to_string(), value.expect("value is none after checking").clone()))
.collect();
return AnimationSprite {
texture: isolated_hash.get("texture").expect("missing texture").as_string().expect("texture is not a string").to_string(),
position: parse_vec_f32(isolated_hash.get("position").expect("missing position").as_string().expect("position is not a string")),
scale: parse_vec_f32(isolated_hash.get("scale").expect("missing scale").as_string().expect("scale is not a string")),
rotation: isolated_hash.get("rotation").expect("missing rotation").as_string().expect("rotation is not a string").parse::<f64>().expect("couldnt parse rotation as f64"),
flipped: {
let flipped_numbers = parse_vec(isolated_hash.get("flipped").expect("missing flipped").as_string().expect("flipped is not a string"));
(flipped_numbers.0 > 0, flipped_numbers.1 > 0)
},
z: isolated_hash.get("zValue").expect("missing zValue").as_string().expect("zValue is not a string").parse::<i32>().expect("couldnt parse zValue as i32")
}
}
}
pub type Animations = HashMap<String, Vec<AnimationSprite>>;
pub fn load_animations(path: &str) -> Animations {
let loaded_plist: plist::Value = plist::from_file(path).expect("could not load plist");
let animations = loaded_plist.as_dictionary().expect("object must be a dict").get("animationContainer").expect("key `animationContainer` doesnt exist").as_dictionary().expect("`animationContainer` must be a dict");
let mut parsed_animations: Animations = HashMap::new();
for (k, v) in animations.iter() {
parsed_animations.insert(k.clone(), vec![] as Vec<AnimationSprite>);
parsed_animations.get_mut(k.as_str()).expect("this should exist..")
.extend(v.as_dictionary().expect("animation must be a dict")
.iter().map(|(_, v)| AnimationSprite::initialize(v.clone())));
}
return parsed_animations;
}
// Trims out a sprite from an image according to a .plist spritesheet.
pub fn get_sprite(spritesheet: Spritesheet, img: DynamicImage, key: String) -> Option<(DynamicImage, Sprite)> {
let sprite = spritesheet.sprites.get(&key);
@ -155,7 +221,7 @@ pub fn get_sprite(spritesheet: Spritesheet, img: DynamicImage, key: String) -> O
return Some((canvas, sprite.clone()));
}
panic!("The sprite should have been found in the spritesheet or not found at all")
unreachable!("The sprite should have been found in the spritesheet or not found at all")
}
pub fn get_sprite_from_loaded(spritesheet: LoadedSpritesheet, key: String) -> Option<(DynamicImage, Sprite)> {

View file

@ -49,8 +49,8 @@ pub const COLORS: &'static [[f32; 3]] = &[
// `zany` = uses 2.0 gamemode render system w/ multiple moving parts
pub struct Gamemode {
prefix: String,
zany: bool
pub prefix: String,
pub zany: bool
}
pub static GAMEMODES: LazyLock<HashMap<&str, Gamemode>> = LazyLock::new(|| { hashmap! {
@ -59,7 +59,6 @@ pub static GAMEMODES: LazyLock<HashMap<&str, Gamemode>> = LazyLock::new(|| { has
"ball" => Gamemode { prefix: "player_ball_".to_string(), zany: false },
"ufo" => Gamemode { prefix: "bird_".to_string(), zany: false },
"wave" => Gamemode { prefix: "dart_".to_string(), zany: false },
// unimplemented
// "robot" => Gamemode { prefix: "robot_".to_string(), zany: true },
// "spider" => Gamemode { prefix: "spider_".to_string(), zany: true },
"robot" => Gamemode { prefix: "robot_".to_string(), zany: true },
"spider" => Gamemode { prefix: "spider_".to_string(), zany: true }
}});

View file

@ -11,26 +11,21 @@ mod tests {
use renderer::*;
use assets::*;
// not actually used, just for benchmarking
use std::time::Instant;
#[test]
fn it_works() {
let game_sheet_02 = load_spritesheet("assets/GJ_GameSheet02-uhd.plist");
let game_sheet_glow = load_spritesheet("assets/GJ_GameSheetGlow-uhd.plist");
let robot_sheet = load_animations("assets/Robot_AnimDesc2.plist");
let spider_sheet = load_animations("assets/Spider_AnimDesc2.plist");
let start = Instant::now();
let rendered_img = render_normal(
"ship_18".to_string(),
[0.0/255.0, 0.0/255.0, 0.0/255.0],
[0.0/255.0, 0.0/255.0, 0.0/255.0],
true,
game_sheet_02,
game_sheet_glow,
);
let rendered_icon = render_icon("ship", 44, [0.0, 0.0, 0.0], [255.0/255.0, 125.0/255.0, 125.0/255.0], true, game_sheet_02, game_sheet_glow, robot_sheet, spider_sheet);
let end = start.elapsed();
rendered_img.save("rendered_icon.png").expect("saving image failed");
let end = Instant::now();
println!("Time elapsed: {:?}", end.duration_since(start));
println!("time taken to render: {:?}", end);
rendered_icon.save("rendered_icon.png").expect("saving image failed");
}
}

View file

@ -1,13 +1,14 @@
use image::*;
use image::{DynamicImage, imageops};
use imageproc::geometric_transformations::{rotate_about_center, Interpolation};
use std::cmp;
use crate::assets;
use crate::assets::LoadedSpritesheet;
use crate::assets::{LoadedSpritesheet, Animations, Sprite};
// Internal function to easily transform an image
fn transform(image: &DynamicImage, color: Option<[f32; 3]>, scale: Option<(f32, f32)>, rotation: Option<i32>) -> DynamicImage {
fn transform(image: &DynamicImage, color: Option<[f32; 3]>, scale: Option<(f32, f32)>, rotation: Option<f32>) -> DynamicImage {
let mut transformed_image = image.clone();
if let Some(color) = color {
@ -44,22 +45,39 @@ fn transform(image: &DynamicImage, color: Option<[f32; 3]>, scale: Option<(f32,
}
if let Some(rotation) = rotation {
match rotation {
0 => (),
90 => transformed_image = transformed_image.rotate90(),
180 => transformed_image = transformed_image.rotate180(),
270 => transformed_image = transformed_image.rotate270(),
_ => panic!("rotation must be 0, 90, 180, or 270"),
// lets not rotate if we dont need to
if rotation == 0.0 {
return transformed_image;
}
let radians = rotation.to_radians();
let (width, height) = transformed_image.dimensions();
let trig_width = (width as f32 * radians.cos() + height as f32 * radians.sin())
.abs()
.ceil() as u32;
let trig_height = (width as f32 * radians.sin() + height as f32 * radians.cos())
.abs()
.ceil() as u32;
let transform_x = ((trig_width as f32 / 2.0) - (width as f32 / 2.0)).ceil() as u32;
let transform_y = ((trig_height as f32 / 2.0) - (height as f32 / 2.0)).ceil() as u32;
let mut canvas = ImageBuffer::new(cmp::max(trig_width, width), cmp::max(trig_height, height));
canvas.copy_from(&transformed_image, transform_x, transform_y).expect("couldnt copy from img");
canvas = rotate_about_center(&canvas, radians, Interpolation::Bilinear, Rgba([0, 0, 0, 0]));
transformed_image = DynamicImage::ImageRgba8(canvas);
}
return transformed_image;
}
// Mainly for internal use; given an array of images, their sizes and colors, tints and composits them into a single image
pub fn render_layered(images: Vec<DynamicImage>, positions: Vec<Option<(f32, f32)>>, colors: Vec<[f32; 3]>, scales: Vec<Option<(f32, f32)>>, rotations: Vec<Option<i32>>) -> DynamicImage {
pub fn render_layered(images: Vec<DynamicImage>, positions: Vec<Option<(f32, f32)>>, colors: Vec<Option<[f32; 3]>>, scales: Vec<Option<(f32, f32)>>, rotations: Vec<Option<f32>>) -> DynamicImage {
let transformed: Vec<DynamicImage> = images.iter().enumerate().map(|(i, img)| {
transform(img, Some(colors[i]), scales[i], rotations[i])
transform(img, colors[i], scales[i], rotations[i])
}).collect();
let sizes: Vec<(i64, i64)> = transformed.iter().map(|img| {
(img.width() as i64, img.height() as i64)
@ -139,9 +157,86 @@ pub fn render_normal(basename: String, col1: [f32; 3], col2: [f32; 3], glow: boo
.collect(),
colors.iter()
.enumerate()
.filter_map(|(i, color)| layers[i].clone().map(|_| color.unwrap()))
.filter_map(|(i, color)| layers[i].clone().map(|_| color.to_owned()))
.collect(),
vec![None, None, None, None, None],
vec![None, None, None, None, None]
);
}
fn flip(scale: (f32, f32), flipped: (bool, bool)) -> (f32, f32) {
(scale.0 * (if flipped.0 { -1 } else { 1 }) as f32, scale.1 * (if flipped.1 { -1 } else { 1 }) as f32)
}
// Renders out a robot/spider icon. You may be looking for `render_icon`.
pub fn render_zany(basename: String, col1: [f32; 3], col2: [f32; 3], glow: bool, game_sheet_02: LoadedSpritesheet, _game_sheet_glow: LoadedSpritesheet, animations: Animations) -> DynamicImage {
let glow_col = if is_black(col2) { if is_black(col1) { [1.0, 1.0, 1.0] } else { col1 } } else { col2 };
let glow = glow || (is_black(col1) && is_black(col2));
let mut anim = animations.get("Robot_idle_001.png").unwrap_or_else(|| animations.get("Spider_idle_001.png").expect("no animations found")).clone();
anim.sort_by_key(|spr| spr.z);
let mut layers = anim
.iter()
.map(|a| {
let texture_name = a.texture.clone().replace("spider_01", &basename).replace("robot_01", &basename);
let mut names = vec![
texture_name.replace("_001.png", "_2_001.png"),
texture_name.replace("_001.png", "_3_001.png"),
texture_name.clone(),
texture_name.replace("_001.png", "_extra_001.png")
];
let mut colors = vec![
Some(col2),
None,
Some(col1),
None
];
if glow {
names.push(texture_name.replace("_001.png", "_glow_001.png"));
colors.push(Some(glow_col));
}
names.iter().enumerate().map(|(i, v)|
(
assets::get_sprite_from_loaded(game_sheet_02.to_owned().clone(), v.clone()),
a.position,
flip(a.scale, a.flipped),
a.rotation,
glow && i == names.len() - 1,
colors[i]
)
).collect::<Vec<(Option<(DynamicImage, Sprite)>, (f32, f32), (f32, f32), f64, bool, Option<[f32; 3]>)>>()
})
.flatten()
.collect::<Vec<(Option<(DynamicImage, Sprite)>, (f32, f32), (f32, f32), f64, bool, Option<[f32; 3]>)>>();
// put glow b4 everything else
layers.sort_by_key(|t| if t.4 { 0 } else { 1 });
let layers_r = layers.iter()
.filter(|v| v.0.is_some())
.filter_map(|(opt_sprite, pos, scale, rot, glow, color)| opt_sprite.clone().map(|sprite| ((sprite.0, sprite.1), *pos, *scale, *rot, *glow, *color)))
.collect::<Vec<((DynamicImage, Sprite), (f32, f32), (f32, f32), f64, bool, Option<[f32; 3]>)>>();
return render_layered(
layers_r.iter().map(|t| t.0.0.clone()).collect(),
layers_r.iter().map(|t| Some((t.0.1.offset.0 + t.1.0 * 4.0, t.0.1.offset.1 * -1.0 + t.1.1 * -4.0))).collect(),
layers_r.iter().map(|t| t.5).collect(),
layers_r.iter().map(|t| Some(t.2)).collect(),
layers_r.iter().map(|t| Some(t.3 as f32)).collect()
)
}
// The main entrypoint for icon rendering; this should be all you need to render out an icon.
// `gamemode` must be one of `cube`, `ship`, `ball`, `ufo`, `wave`, `robot`, or `spider`
pub fn render_icon(gamemode_str: &str, icon: i32, col1: [f32; 3], col2: [f32; 3], glow: bool, game_sheet_02: LoadedSpritesheet, game_sheet_glow: LoadedSpritesheet, robot_animations: Animations, spider_animations: Animations) -> DynamicImage {
let gamemode = crate::constants::GAMEMODES.get(gamemode_str).expect("invalid gamemode");
if gamemode.zany {
return render_zany(format!("{}{:02}", gamemode.prefix, icon), col1, col2, glow, game_sheet_02, game_sheet_glow, if gamemode_str == "robot" { robot_animations } else { spider_animations })
} else {
return render_normal(format!("{}{:02}", gamemode.prefix, icon), col1, col2, glow, game_sheet_02, game_sheet_glow)
}
}