rustdoc
This commit is contained in:
parent
3eacdc2c32
commit
1a440b855a
4 changed files with 45 additions and 33 deletions
|
@ -2,10 +2,9 @@ use plist;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use image::*;
|
use image::DynamicImage;
|
||||||
use image::{DynamicImage, ImageBuffer, imageops};
|
|
||||||
|
|
||||||
// "{1,2}" -> `(1, 2)`
|
/// "{1,2}" -> `(1, 2)`
|
||||||
fn parse_vec(str: &str) -> (i32, i32) {
|
fn parse_vec(str: &str) -> (i32, i32) {
|
||||||
let parts: Vec<&str> = str[1..str.len()-1].split(",").collect();
|
let parts: Vec<&str> = str[1..str.len()-1].split(",").collect();
|
||||||
let a: Vec<i32> = parts
|
let a: Vec<i32> = parts
|
||||||
|
@ -15,7 +14,7 @@ fn parse_vec(str: &str) -> (i32, i32) {
|
||||||
|
|
||||||
return (a[0], a[1])
|
return (a[0], a[1])
|
||||||
}
|
}
|
||||||
// parse_vec, but for float64
|
/// parse_vec, but for float64
|
||||||
fn parse_vec_f32(str: &str) -> (f32, f32) {
|
fn parse_vec_f32(str: &str) -> (f32, f32) {
|
||||||
let parts: Vec<&str> = str[1..str.len()-1].split(",").collect();
|
let parts: Vec<&str> = str[1..str.len()-1].split(",").collect();
|
||||||
let a: Vec<f32> = parts
|
let a: Vec<f32> = parts
|
||||||
|
@ -25,7 +24,7 @@ fn parse_vec_f32(str: &str) -> (f32, f32) {
|
||||||
|
|
||||||
return (a[0], a[1])
|
return (a[0], a[1])
|
||||||
}
|
}
|
||||||
// `"{{1,2},{3,4}}"` -> `{{1, 2}, {3, 4}}`
|
/// `"{{1,2},{3,4}}"` -> `{{1, 2}, {3, 4}}`
|
||||||
fn parse_rect_vecs(str: &str) -> ((i32, i32), (i32, i32)) {
|
fn parse_rect_vecs(str: &str) -> ((i32, i32), (i32, i32)) {
|
||||||
let cleaned_str = str.replace("{", "").replace("}", "");
|
let cleaned_str = str.replace("{", "").replace("}", "");
|
||||||
let parts: Vec<&str> = cleaned_str.split(",").collect();
|
let parts: Vec<&str> = cleaned_str.split(",").collect();
|
||||||
|
@ -37,22 +36,23 @@ fn parse_rect_vecs(str: &str) -> ((i32, i32), (i32, i32)) {
|
||||||
return ((a[0], a[1]), (a[2], a[3]))
|
return ((a[0], a[1]), (a[2], a[3]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents a sprite along with its texture data in a spritesheet.
|
/// Represents a sprite along with its texture data in a spritesheet.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Sprite {
|
pub struct Sprite {
|
||||||
// Whenever rendering the sprite, offset it by this much
|
/// Whenever rendering the sprite, offset it by this much.
|
||||||
pub offset: (f32, f32),
|
pub offset: (f32, f32),
|
||||||
// {left, top}, {width, height}. Controls the cropping
|
/// {left, top}, {width, height}. Controls the cropping.
|
||||||
rect: ((i32, i32), (i32, i32)),
|
pub rect: ((i32, i32), (i32, i32)),
|
||||||
// Whether the texture needs to be counter-rotated 90 degrees counter-clockwise
|
/// Whether the texture needs to be counter-rotated 90 degrees counter-clockwise.
|
||||||
rotated: bool,
|
pub rotated: bool,
|
||||||
size: (i32, i32),
|
/// Size of the sprite.
|
||||||
// Difference between this and `size` is unknown to me
|
pub size: (i32, i32),
|
||||||
source_size: (i32, i32)
|
/// Difference between this and `size` is unknown to me.
|
||||||
|
pub source_size: (i32, i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sprite {
|
impl Sprite {
|
||||||
// Shorthand for initializing a sprite with its .plist representation.
|
/// Shorthand for initializing a sprite with its .plist representation.
|
||||||
fn initialize(obj: plist::Value) -> Sprite {
|
fn initialize(obj: plist::Value) -> Sprite {
|
||||||
let hash = obj.as_dictionary().expect("object must be a dict");
|
let hash = obj.as_dictionary().expect("object must be a dict");
|
||||||
|
|
||||||
|
@ -88,17 +88,17 @@ impl Sprite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents a spritesheet along with its sprites.
|
/// Represents a spritesheet along with its sprites.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Spritesheet {
|
pub struct Spritesheet {
|
||||||
sprites: HashMap<String, Sprite>,
|
pub sprites: HashMap<String, Sprite>,
|
||||||
|
|
||||||
texture_file_name: String,
|
pub texture_file_name: String,
|
||||||
size: (i32, i32)
|
pub size: (i32, i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spritesheet {
|
impl Spritesheet {
|
||||||
// Shorthand for initializing a spritesheet with its .plist representation.
|
/// Shorthand for initializing a spritesheet with its .plist representation.
|
||||||
fn initialize(obj: plist::Value) -> Spritesheet {
|
fn initialize(obj: plist::Value) -> Spritesheet {
|
||||||
let hash = obj.as_dictionary().expect("object must be a dict");
|
let hash = obj.as_dictionary().expect("object must be a dict");
|
||||||
|
|
||||||
|
@ -113,14 +113,14 @@ impl Spritesheet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stores both a spritesheet and its associated `DynamicImage` for easy access.
|
/// Stores both a spritesheet and its associated `DynamicImage` for easy access.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LoadedSpritesheet {
|
pub struct LoadedSpritesheet {
|
||||||
spritesheet: Spritesheet,
|
pub spritesheet: Spritesheet,
|
||||||
texture: DynamicImage
|
pub texture: DynamicImage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads the spritesheet and readies the associated image.
|
/// Loads the spritesheet and readies the associated image.
|
||||||
pub fn load_spritesheet(path: &str) -> LoadedSpritesheet {
|
pub fn load_spritesheet(path: &str) -> LoadedSpritesheet {
|
||||||
return LoadedSpritesheet {
|
return LoadedSpritesheet {
|
||||||
spritesheet: Spritesheet::initialize(plist::from_file(path).expect("could not load plist")),
|
spritesheet: Spritesheet::initialize(plist::from_file(path).expect("could not load plist")),
|
||||||
|
@ -128,7 +128,7 @@ pub fn load_spritesheet(path: &str) -> LoadedSpritesheet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents the metadata of an animation frame's sprite
|
/// Represents the metadata of an animation frame's sprite
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct AnimationSprite {
|
pub struct AnimationSprite {
|
||||||
pub texture: String,
|
pub texture: String,
|
||||||
|
@ -194,7 +194,7 @@ pub fn load_animations(path: &str) -> Animations {
|
||||||
return parsed_animations;
|
return parsed_animations;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trims out a sprite from an image according to a .plist spritesheet.
|
/// 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)> {
|
pub fn get_sprite(spritesheet: Spritesheet, img: DynamicImage, key: String) -> Option<(DynamicImage, Sprite)> {
|
||||||
let sprite = spritesheet.sprites.get(&key);
|
let sprite = spritesheet.sprites.get(&key);
|
||||||
|
|
||||||
|
@ -224,6 +224,7 @@ pub fn get_sprite(spritesheet: Spritesheet, img: DynamicImage, key: String) -> O
|
||||||
unreachable!("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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trims out a sprite from an image according to a LoadedSpritesheet object.
|
||||||
pub fn get_sprite_from_loaded(spritesheet: LoadedSpritesheet, key: String) -> Option<(DynamicImage, Sprite)> {
|
pub fn get_sprite_from_loaded(spritesheet: LoadedSpritesheet, key: String) -> Option<(DynamicImage, Sprite)> {
|
||||||
let texture = spritesheet.texture.clone();
|
let texture = spritesheet.texture.clone();
|
||||||
let sprite = get_sprite(spritesheet.spritesheet.clone(), texture, key);
|
let sprite = get_sprite(spritesheet.spritesheet.clone(), texture, key);
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::{collections::HashMap, sync::LazyLock};
|
||||||
|
|
||||||
use maplit::hashmap;
|
use maplit::hashmap;
|
||||||
|
|
||||||
|
/// Colors used in the game stored as floats from 0 to 1.
|
||||||
pub const COLORS: &'static [[f32; 3]] = &[
|
pub const COLORS: &'static [[f32; 3]] = &[
|
||||||
[125.0 / 255.0, 255.0 / 255.0, 0.0 / 255.0],
|
[125.0 / 255.0, 255.0 / 255.0, 0.0 / 255.0],
|
||||||
[0.0 / 255.0, 255.0 / 255.0, 0.0 / 255.0],
|
[0.0 / 255.0, 255.0 / 255.0, 0.0 / 255.0],
|
||||||
|
@ -47,12 +48,13 @@ pub const COLORS: &'static [[f32; 3]] = &[
|
||||||
[125.0 / 255.0, 125.0 / 255.0, 255.0 / 255.0]
|
[125.0 / 255.0, 125.0 / 255.0, 255.0 / 255.0]
|
||||||
];
|
];
|
||||||
|
|
||||||
// `zany` = uses 2.0 gamemode render system w/ multiple moving parts
|
/// `zany` = uses 2.0 gamemode render system w/ multiple moving parts
|
||||||
pub struct Gamemode {
|
pub struct Gamemode {
|
||||||
pub prefix: String,
|
pub prefix: String,
|
||||||
pub zany: bool
|
pub zany: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gamemodes used in the game. `zany` = uses 2.0 gamemode render system w/ multiple moving parts
|
||||||
pub static GAMEMODES: LazyLock<HashMap<&str, Gamemode>> = LazyLock::new(|| { hashmap! {
|
pub static GAMEMODES: LazyLock<HashMap<&str, Gamemode>> = LazyLock::new(|| { hashmap! {
|
||||||
"cube" => Gamemode { prefix: "player_".to_string(), zany: false },
|
"cube" => Gamemode { prefix: "player_".to_string(), zany: false },
|
||||||
"ship" => Gamemode { prefix: "ship_".to_string(), zany: false },
|
"ship" => Gamemode { prefix: "ship_".to_string(), zany: false },
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
//! # gd-icon-renderer
|
||||||
|
//!
|
||||||
|
//! gd-icon-renderer is a library for rendering Geometry Dash icons.
|
||||||
|
//!
|
||||||
|
//! It uses the [image](https://crates.io/crates/image) crate and [imageproc](https://crates.io/crates/imageproc) crate for image manipulation and [plist](https://crates.io/crates/plist) for parsing plist files.
|
||||||
|
//!
|
||||||
|
//! The main entrypoint is found in the [`renderer`](renderer/index.html) module.
|
||||||
|
|
||||||
#![feature(lazy_cell)]
|
#![feature(lazy_cell)]
|
||||||
|
|
||||||
pub mod assets;
|
pub mod assets;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::cmp;
|
||||||
use crate::assets;
|
use crate::assets;
|
||||||
use crate::assets::{LoadedSpritesheet, Animations, Sprite};
|
use crate::assets::{LoadedSpritesheet, Animations, Sprite};
|
||||||
|
|
||||||
// Internal function to easily transform an image
|
/// Internal function to easily transform an image
|
||||||
fn transform(image: &DynamicImage, color: Option<[f32; 3]>, scale: Option<(f32, f32)>, rotation: Option<f32>) -> DynamicImage {
|
fn transform(image: &DynamicImage, color: Option<[f32; 3]>, scale: Option<(f32, f32)>, rotation: Option<f32>) -> DynamicImage {
|
||||||
let mut transformed_image = image.clone();
|
let mut transformed_image = image.clone();
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ fn transform(image: &DynamicImage, color: Option<[f32; 3]>, scale: Option<(f32,
|
||||||
return transformed_image;
|
return transformed_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mainly for internal use; given an array of images, their sizes and colors, tints and composits them into a single 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<Option<[f32; 3]>>, scales: Vec<Option<(f32, f32)>>, rotations: Vec<Option<f32>>) -> 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)| {
|
let transformed: Vec<DynamicImage> = images.iter().enumerate().map(|(i, img)| {
|
||||||
transform(img, colors[i], scales[i], rotations[i])
|
transform(img, colors[i], scales[i], rotations[i])
|
||||||
|
@ -123,7 +123,7 @@ fn is_black(c: [f32; 3]) -> bool {
|
||||||
c == [0.0, 0.0, 0.0]
|
c == [0.0, 0.0, 0.0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renders out a non-robot/spider icon. You may be looking for `render_icon`.
|
/// Renders out a non-robot/spider icon. You may be looking for `render_icon`.
|
||||||
pub fn render_normal(basename: String, col1: [f32; 3], col2: [f32; 3], glow: bool, game_sheet_02: LoadedSpritesheet, game_sheet_glow: LoadedSpritesheet) -> DynamicImage {
|
pub fn render_normal(basename: String, col1: [f32; 3], col2: [f32; 3], glow: bool, game_sheet_02: LoadedSpritesheet, game_sheet_glow: LoadedSpritesheet) -> DynamicImage {
|
||||||
let glow_col = if is_black(col2) { if is_black(col1) { [1.0, 1.0, 1.0] } else { col1 } } else { col2 };
|
let glow_col = if is_black(col2) { if is_black(col1) { [1.0, 1.0, 1.0] } else { col1 } } else { col2 };
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ 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)
|
(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`.
|
/// 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 {
|
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_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 glow = glow || (is_black(col1) && is_black(col2));
|
||||||
|
@ -228,8 +228,9 @@ pub fn render_zany(basename: String, col1: [f32; 3], col2: [f32; 3], glow: bool,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The main entrypoint for icon rendering; this should be all you need to render out an icon.
|
/// 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`
|
///
|
||||||
|
/// `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 {
|
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");
|
let gamemode = crate::constants::GAMEMODES.get(gamemode_str).expect("invalid gamemode");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue