mirror of
https://github.com/SpaceManiac/SpacemanDMM.git
synced 2025-12-23 05:36:47 +00:00
Add example for detecting duplicate icon states
This commit is contained in:
parent
e895de76b8
commit
b94cd6e41c
3 changed files with 109 additions and 6 deletions
|
|
@ -36,14 +36,14 @@ pub struct State {
|
|||
pub frames: Frames,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Dirs {
|
||||
One,
|
||||
Four,
|
||||
Eight,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Frames {
|
||||
/// Without an explicit setting, only one frame
|
||||
One,
|
||||
|
|
@ -71,6 +71,12 @@ impl Metadata {
|
|||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn num_sprites(&self) -> usize {
|
||||
self.dirs.len() * self.frames.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Dirs {
|
||||
pub fn len(self) -> usize {
|
||||
match self {
|
||||
|
|
|
|||
|
|
@ -67,8 +67,11 @@ impl IconFile {
|
|||
None if icon_state == "" => 0,
|
||||
None => return None,
|
||||
};
|
||||
let state = &self.metadata.states[state_index];
|
||||
let index = self.index_of_state(&self.metadata.states[state_index], dir, 0);
|
||||
Some(self.rect_of_index(index))
|
||||
}
|
||||
|
||||
pub fn index_of_state(&self, state: &State, dir: i32, frame: u32) -> u32 {
|
||||
let dir_idx = match (state.dirs, dir) {
|
||||
(Dirs::One, _) => 0,
|
||||
(Dirs::Eight, NORTHWEST) => 7,
|
||||
|
|
@ -81,15 +84,18 @@ impl IconFile {
|
|||
(_, _) => 0,
|
||||
};
|
||||
|
||||
let icon_index = state.offset as u32 + dir_idx;
|
||||
state.offset as u32 + dir_idx + frame * state.dirs.len() as u32
|
||||
}
|
||||
|
||||
pub fn rect_of_index(&self, icon_index: u32) -> Rect {
|
||||
let icon_count = self.image.width / self.metadata.width;
|
||||
let (icon_x, icon_y) = (icon_index % icon_count, icon_index / icon_count);
|
||||
Some((
|
||||
(
|
||||
icon_x * self.metadata.width,
|
||||
icon_y * self.metadata.height,
|
||||
self.metadata.width,
|
||||
self.metadata.height,
|
||||
))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
91
src/tools/examples/duplicate_icon_states.rs
Normal file
91
src/tools/examples/duplicate_icon_states.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
extern crate dreammaker as dm;
|
||||
extern crate dmm_tools;
|
||||
extern crate walkdir;
|
||||
extern crate ndarray;
|
||||
|
||||
use std::path::Path;
|
||||
use std::collections::HashMap;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
use dmm_tools::dmi::*;
|
||||
use ndarray::s;
|
||||
|
||||
fn is_visible(entry: &DirEntry) -> bool {
|
||||
entry
|
||||
.path()
|
||||
.file_name()
|
||||
.unwrap_or("".as_ref())
|
||||
.to_str()
|
||||
.map(|s| !s.starts_with("."))
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
fn files_with_extension<F: FnMut(&Path)>(ext: &str, mut f: F) {
|
||||
let dir = match std::env::var_os("TEST_DME") {
|
||||
Some(dme) => Path::new(&dme).parent().unwrap().to_owned(),
|
||||
None => {
|
||||
println!("Set TEST_DME to check .{} files", ext);
|
||||
return;
|
||||
}
|
||||
};
|
||||
for entry in WalkDir::new(dir).into_iter().filter_entry(is_visible) {
|
||||
let entry = entry.unwrap();
|
||||
if entry.file_type().is_file() && entry.path().extension() == Some(ext.as_ref()) {
|
||||
let path = entry.path();
|
||||
f(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn all_same(icon_file: &IconFile, states: &[&State]) -> bool {
|
||||
let (first, rest) = states.split_first().unwrap();
|
||||
let first_start_index = icon_file.index_of_state(first, 0, 0);
|
||||
for state in rest {
|
||||
if state.dirs != first.dirs || state.frames != first.frames {
|
||||
return false;
|
||||
}
|
||||
let start_index = icon_file.index_of_state(state, 0, 0);
|
||||
for i in 0..state.num_sprites() as u32 {
|
||||
let rect1 = icon_file.rect_of_index(first_start_index + i);
|
||||
let rect2 = icon_file.rect_of_index(start_index + i);
|
||||
let slice1 = icon_file.image.data.slice(s![
|
||||
rect1.1 as isize..(rect1.1 + rect1.3) as isize,
|
||||
rect1.0 as isize..(rect1.0 + rect1.2) as isize,
|
||||
..
|
||||
]);
|
||||
let slice2 = icon_file.image.data.slice(s![
|
||||
rect2.1 as isize..(rect2.1 + rect2.3) as isize,
|
||||
rect2.0 as isize..(rect2.0 + rect2.2) as isize,
|
||||
..
|
||||
]);
|
||||
if slice1 != slice2 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
files_with_extension("dmi", |path| {
|
||||
let icon_file = IconFile::from_file(path).unwrap();
|
||||
let mut counts = HashMap::<_, Vec<_>>::new();
|
||||
for state in icon_file.metadata.states.iter() {
|
||||
let mut name = format!("{:?}", state.name);
|
||||
if state.movement {
|
||||
name.push_str(" (movement)");
|
||||
}
|
||||
counts.entry(name).or_default().push(state);
|
||||
}
|
||||
let mut name = false;
|
||||
for (k, v) in counts {
|
||||
if v.len() > 1 {
|
||||
if !name {
|
||||
println!("{}", path.display());
|
||||
name = true;
|
||||
}
|
||||
let star = if all_same(&icon_file, &v) { "*" } else { " " };
|
||||
println!(" {} {}x {}", star, v.len(), k);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue