mirror of
https://github.com/Theaninova/mhlib.git
synced 2026-01-20 08:52:57 +00:00
134 lines
4.3 KiB
Rust
134 lines
4.3 KiB
Rust
use crate::formats::sprites::{CropMode, RenderMode, Sprites};
|
|
use godot::builtin::{GodotString, Rect2, StringName, ToVariant, Vector2};
|
|
use godot::engine::utilities::printerr;
|
|
use godot::engine::{
|
|
load, AtlasTexture, ImageTexture, PlaceholderTexture2D, ResourceLoader, SpriteFrames,
|
|
};
|
|
use godot::obj::{Gd, Share};
|
|
use godot::prelude::GodotClass;
|
|
|
|
const FPS: f64 = 15.0;
|
|
const SPRITE_EXTENSIONS: &[&str] = &["bmp", "rle"];
|
|
|
|
pub fn load_sprite_frames(sprites: Vec<Sprites>, path: GodotString) -> Gd<SpriteFrames> {
|
|
let dir = path
|
|
.to_string()
|
|
.strip_suffix("/sprites.txt")
|
|
.unwrap()
|
|
.to_string();
|
|
let mut sprite_frames = SpriteFrames::new();
|
|
for sprite in sprites.into_iter() {
|
|
if let RenderMode::FlipX = sprite.render_mode {
|
|
continue;
|
|
}
|
|
sprite_frames.add_animation(StringName::from(&sprite.name));
|
|
sprite_frames.set_animation_speed(StringName::from(&sprite.name), FPS);
|
|
|
|
match select_from_extensions(&dir, &sprite.file_name) {
|
|
Some((path, "rle")) => extract_rle_frames(&mut sprite_frames, &sprite, path),
|
|
Some((path, "bmp")) => extract_bitmap_frames(&mut sprite_frames, &sprite, path),
|
|
Some(_) | None => {
|
|
printerr(
|
|
format!("Missing sprite '{}'", sprite.file_name).to_variant(),
|
|
&[],
|
|
);
|
|
let texture = PlaceholderTexture2D::new();
|
|
sprite_frames.add_frame(
|
|
StringName::from(&sprite.name),
|
|
texture.upcast(),
|
|
60.0 / FPS,
|
|
0,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
sprite_frames
|
|
}
|
|
|
|
/// Loads an RLE file as SpriteFrames and extracts
|
|
/// its frames into `sprite_frames`
|
|
fn extract_rle_frames(sprite_frames: &mut SpriteFrames, sprite: &Sprites, path: String) {
|
|
let frames: Gd<SpriteFrames> = load(path);
|
|
for frame_idx in 0..frames.get_frame_count("default".into()) {
|
|
sprite_frames.add_frame(
|
|
StringName::from(&sprite.name),
|
|
frames
|
|
.get_frame_texture("default".into(), frame_idx)
|
|
.unwrap(),
|
|
60.0 / FPS,
|
|
0,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Loads a bitmap and extracts its frames into `sprite_frames`
|
|
/// creates an atlas if there are multiple frames.
|
|
fn extract_bitmap_frames(sprite_frames: &mut SpriteFrames, sprite: &Sprites, path: String) {
|
|
let texture: Gd<ImageTexture> = load(path);
|
|
|
|
let frame_count = if let Some(CropMode::FrameCount(frame_count)) = sprite.frames {
|
|
frame_count
|
|
} else {
|
|
1
|
|
};
|
|
|
|
if frame_count > 1 {
|
|
let height = texture.get_height();
|
|
let width = texture.get_width();
|
|
let frame_height = height / frame_count as i64;
|
|
|
|
for i in 0..frame_count as i64 {
|
|
let mut atlas = AtlasTexture::new();
|
|
atlas.set_atlas(texture.share().upcast());
|
|
atlas.set_region(Rect2 {
|
|
position: Vector2 {
|
|
x: 0.0,
|
|
y: (i * frame_height) as f32,
|
|
},
|
|
size: Vector2 {
|
|
x: width as f32,
|
|
y: frame_height as f32,
|
|
},
|
|
});
|
|
|
|
sprite_frames.add_frame(
|
|
StringName::from(&sprite.name),
|
|
atlas.upcast(),
|
|
60.0 / FPS,
|
|
0,
|
|
);
|
|
}
|
|
} else {
|
|
sprite_frames.add_frame(
|
|
StringName::from(&sprite.name),
|
|
texture.upcast(),
|
|
60.0 / FPS,
|
|
0,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Selects the extension based on which file exists
|
|
fn select_from_extensions(dir: &str, file_name: &str) -> Option<(String, &'static str)> {
|
|
SPRITE_EXTENSIONS
|
|
.iter()
|
|
.map(|ext| {
|
|
(
|
|
format!("{}/sprites/{}.{}", dir, file_name.to_lowercase(), ext),
|
|
*ext,
|
|
)
|
|
})
|
|
.find(|(path, ext)| {
|
|
ResourceLoader::singleton().exists(
|
|
path.clone().into(),
|
|
match *ext {
|
|
"rle" => SpriteFrames::CLASS_NAME.to_string(),
|
|
"bmp" => ImageTexture::CLASS_NAME.to_string(),
|
|
_ => panic!(),
|
|
}
|
|
.into(),
|
|
)
|
|
})
|
|
}
|