Add: windows mvp - transparent bugs not fixed

This commit is contained in:
DaZuo0122
2026-02-12 22:58:33 +08:00
commit 61825f647d
147 changed files with 28498 additions and 0 deletions

View 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");
}
}