Add: windows mvp - transparent bugs not fixed
This commit is contained in:
123
crates/sprimo-sprite/src/lib.rs
Normal file
123
crates/sprimo-sprite/src/lib.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use thiserror::Error;
|
||||
|
||||
const MANIFEST_FILE: &str = "manifest.json";
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SpriteError {
|
||||
#[error("sprite pack not found: {0}")]
|
||||
PackNotFound(String),
|
||||
#[error("manifest not found: {0}")]
|
||||
ManifestNotFound(PathBuf),
|
||||
#[error("io error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("invalid manifest: {0}")]
|
||||
Parse(#[from] serde_json::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SpritePackManifest {
|
||||
pub id: String,
|
||||
pub version: String,
|
||||
pub image: String,
|
||||
pub frame_width: u32,
|
||||
pub frame_height: u32,
|
||||
pub animations: Vec<AnimationDefinition>,
|
||||
pub anchor: AnchorPoint,
|
||||
#[serde(default)]
|
||||
pub chroma_key_color: Option<String>,
|
||||
#[serde(default)]
|
||||
pub chroma_key_enabled: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AnimationDefinition {
|
||||
pub name: String,
|
||||
pub fps: u16,
|
||||
pub frames: Vec<u32>,
|
||||
pub one_shot: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AnchorPoint {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
pub fn load_manifest(pack_dir: &Path) -> Result<SpritePackManifest, SpriteError> {
|
||||
let manifest_path = pack_dir.join(MANIFEST_FILE);
|
||||
if !manifest_path.exists() {
|
||||
return Err(SpriteError::ManifestNotFound(manifest_path));
|
||||
}
|
||||
|
||||
let raw = fs::read_to_string(&manifest_path)?;
|
||||
let manifest = serde_json::from_str::<SpritePackManifest>(&raw)?;
|
||||
Ok(manifest)
|
||||
}
|
||||
|
||||
pub fn resolve_pack_path(root: &Path, pack_id_or_path: &str) -> Result<PathBuf, SpriteError> {
|
||||
let direct = PathBuf::from(pack_id_or_path);
|
||||
if direct.exists() {
|
||||
return Ok(direct);
|
||||
}
|
||||
|
||||
let candidate = root.join(pack_id_or_path);
|
||||
if candidate.exists() {
|
||||
return Ok(candidate);
|
||||
}
|
||||
|
||||
Err(SpriteError::PackNotFound(pack_id_or_path.to_string()))
|
||||
}
|
||||
|
||||
pub fn load_selected_or_default(
|
||||
root: &Path,
|
||||
selected_pack: &str,
|
||||
default_pack: &str,
|
||||
) -> Result<SpritePackManifest, SpriteError> {
|
||||
let selected = resolve_pack_path(root, selected_pack)
|
||||
.and_then(|path| load_manifest(&path));
|
||||
if let Ok(manifest) = selected {
|
||||
return Ok(manifest);
|
||||
}
|
||||
|
||||
let fallback_path = resolve_pack_path(root, default_pack)?;
|
||||
load_manifest(&fallback_path)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{load_selected_or_default, SpritePackManifest};
|
||||
use std::fs;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn write_manifest(dir: &std::path::Path, id: &str) {
|
||||
let manifest = SpritePackManifest {
|
||||
id: id.to_string(),
|
||||
version: "1".to_string(),
|
||||
image: "atlas.png".to_string(),
|
||||
frame_width: 64,
|
||||
frame_height: 64,
|
||||
animations: vec![],
|
||||
anchor: super::AnchorPoint { x: 0.5, y: 1.0 },
|
||||
chroma_key_color: None,
|
||||
chroma_key_enabled: None,
|
||||
};
|
||||
let encoded = serde_json::to_string_pretty(&manifest).expect("manifest encode");
|
||||
fs::write(dir.join("manifest.json"), encoded).expect("manifest write");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fallback_to_default_pack() {
|
||||
let temp = TempDir::new().expect("tempdir");
|
||||
let root = temp.path();
|
||||
let default_dir = root.join("default");
|
||||
fs::create_dir_all(&default_dir).expect("mkdir");
|
||||
write_manifest(&default_dir, "default");
|
||||
|
||||
let manifest =
|
||||
load_selected_or_default(root, "missing", "default").expect("fallback");
|
||||
assert_eq!(manifest.id, "default");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user