mirror of https://github.com/Leinnan/rpack.git
Frames JSON
This commit is contained in:
parent
7e62334e54
commit
8b51af05cd
|
|
@ -885,6 +885,16 @@ dependencies = [
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "egui_json_tree"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6c549dbaae5f70f0d4a9ec068617d24051a4e74f8611298e484bf76a09f06d0"
|
||||||
|
dependencies = [
|
||||||
|
"egui",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ehttp"
|
name = "ehttp"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
|
@ -1423,6 +1433,12 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni"
|
name = "jni"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
|
|
@ -2173,11 +2189,13 @@ dependencies = [
|
||||||
"eframe",
|
"eframe",
|
||||||
"egui",
|
"egui",
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
|
"egui_json_tree",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"image",
|
"image",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"texture_packer",
|
"texture_packer",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
|
|
@ -2220,6 +2238,12 @@ dependencies = [
|
||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
|
@ -2253,24 +2277,35 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.163"
|
version = "1.0.193"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
|
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.163"
|
version = "1.0.193"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
|
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.39",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.108"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_repr"
|
name = "serde_repr"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ eframe = { version = "0.24.1", default-features = false, features = [
|
||||||
"persistence", # Enable restoring app state when restarting the app.
|
"persistence", # Enable restoring app state when restarting the app.
|
||||||
] }
|
] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
serde_json = "1"
|
||||||
|
egui_json_tree = "0.2"
|
||||||
|
|
||||||
# You only need serde if you want app persistence:
|
# You only need serde if you want app persistence:
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
|
||||||
96
src/app.rs
96
src/app.rs
|
|
@ -3,9 +3,8 @@ use std::{collections::HashMap, io::Cursor};
|
||||||
use egui::{CollapsingHeader, Color32, DroppedFile, FontFamily, FontId, Image, RichText};
|
use egui::{CollapsingHeader, Color32, DroppedFile, FontFamily, FontId, Image, RichText};
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
|
|
||||||
use texture_packer::{
|
use serde_json::Value;
|
||||||
importer::ImageImporter, texture::Texture, TexturePacker, TexturePackerConfig,
|
use texture_packer::{importer::ImageImporter, TexturePacker, TexturePackerConfig};
|
||||||
};
|
|
||||||
pub const MY_ACCENT_COLOR32: Color32 = Color32::from_rgb(230, 102, 1);
|
pub const MY_ACCENT_COLOR32: Color32 = Color32::from_rgb(230, 102, 1);
|
||||||
pub const TOP_SIDE_MARGIN: f32 = 10.0;
|
pub const TOP_SIDE_MARGIN: f32 = 10.0;
|
||||||
pub const HEADER_HEIGHT: f32 = 45.0;
|
pub const HEADER_HEIGHT: f32 = 45.0;
|
||||||
|
|
@ -16,9 +15,77 @@ pub const GIT_HASH: &str = env!("GIT_HASH");
|
||||||
pub struct Spritesheet {
|
pub struct Spritesheet {
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
pub frames: HashMap<String, texture_packer::Frame<String>>,
|
pub frames: HashMap<String, texture_packer::Frame<String>>,
|
||||||
|
pub frames_json: Value,
|
||||||
pub size: (u32, u32),
|
pub size: (u32, u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Boundaries and properties of a packed texture.
|
||||||
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct SerializableFrame {
|
||||||
|
/// Key used to uniquely identify this frame.
|
||||||
|
pub key: String,
|
||||||
|
/// Rectangle describing the texture coordinates and size.
|
||||||
|
pub frame: SerializableRect,
|
||||||
|
/// True if the texture was rotated during packing.
|
||||||
|
/// If it was rotated, it was rotated 90 degrees clockwise.
|
||||||
|
pub rotated: bool,
|
||||||
|
/// True if the texture was trimmed during packing.
|
||||||
|
pub trimmed: bool,
|
||||||
|
|
||||||
|
// (x, y) is the trimmed frame position at original image
|
||||||
|
// (w, h) is original image size
|
||||||
|
//
|
||||||
|
// w
|
||||||
|
// +--------------+
|
||||||
|
// | (x, y) |
|
||||||
|
// | ^ |
|
||||||
|
// | | |
|
||||||
|
// | ********* |
|
||||||
|
// | * * | h
|
||||||
|
// | * * |
|
||||||
|
// | ********* |
|
||||||
|
// | |
|
||||||
|
// +--------------+
|
||||||
|
/// Source texture size before any trimming.
|
||||||
|
pub source: SerializableRect,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<texture_packer::Frame<String>> for SerializableFrame {
|
||||||
|
fn from(value: texture_packer::Frame<String>) -> Self {
|
||||||
|
SerializableFrame {
|
||||||
|
key: value.key,
|
||||||
|
frame: value.frame.into(),
|
||||||
|
rotated: value.rotated,
|
||||||
|
trimmed: value.trimmed,
|
||||||
|
source: value.source.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defines a rectangle in pixels with the origin at the top-left of the texture atlas.
|
||||||
|
#[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct SerializableRect {
|
||||||
|
/// Horizontal position the rectangle begins at.
|
||||||
|
pub x: u32,
|
||||||
|
/// Vertical position the rectangle begins at.
|
||||||
|
pub y: u32,
|
||||||
|
/// Width of the rectangle.
|
||||||
|
pub w: u32,
|
||||||
|
/// Height of the rectangle.
|
||||||
|
pub h: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<texture_packer::Rect> for SerializableRect {
|
||||||
|
fn from(value: texture_packer::Rect) -> Self {
|
||||||
|
SerializableRect {
|
||||||
|
h: value.h,
|
||||||
|
w: value.w,
|
||||||
|
x: value.x,
|
||||||
|
y: value.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(default)] // if we add new fields, give them default values when deserializing old state
|
#[serde(default)] // if we add new fields, give them default values when deserializing old state
|
||||||
|
|
@ -105,15 +172,25 @@ impl TemplateApp {
|
||||||
println!(" {:7} : {:?}", name, frame.frame);
|
println!(" {:7} : {:?}", name, frame.frame);
|
||||||
}
|
}
|
||||||
let mut out_vec = vec![];
|
let mut out_vec = vec![];
|
||||||
let exporter = texture_packer::exporter::ImageExporter::export(&packer).unwrap();
|
let exported_image = texture_packer::exporter::ImageExporter::export(&packer).unwrap();
|
||||||
exporter
|
let mut img = image::DynamicImage::new_rgba8(self.config.max_width, self.config.max_height);
|
||||||
.write_to(&mut Cursor::new(&mut out_vec), image::ImageFormat::Png)
|
image::imageops::overlay(&mut img, &exported_image, 0, 0);
|
||||||
|
|
||||||
|
img.write_to(&mut Cursor::new(&mut out_vec), image::ImageFormat::Png)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let frames_info: Vec<SerializableFrame> = packer
|
||||||
|
.get_frames()
|
||||||
|
.values()
|
||||||
|
.map(|v| -> SerializableFrame { (*v).clone().into() })
|
||||||
|
.collect();
|
||||||
|
let frames_string = serde_json::to_string_pretty(&frames_info).unwrap();
|
||||||
|
let frames_json = serde_json::from_str(&frames_string).unwrap();
|
||||||
self.data = Some(Spritesheet {
|
self.data = Some(Spritesheet {
|
||||||
data: out_vec.clone(),
|
data: out_vec.clone(),
|
||||||
frames: packer.get_frames().clone(),
|
frames: packer.get_frames().clone(),
|
||||||
size: (packer.width(), packer.height()),
|
size: (img.width(), img.height()),
|
||||||
|
frames_json,
|
||||||
});
|
});
|
||||||
let id = format!("bytes://output_{}.png", self.counter);
|
let id = format!("bytes://output_{}.png", self.counter);
|
||||||
self.image = None;
|
self.image = None;
|
||||||
|
|
@ -300,6 +377,7 @@ impl eframe::App for TemplateApp {
|
||||||
});
|
});
|
||||||
ui.with_layout(egui::Layout::top_down_justified(egui::Align::Min), |ui|{
|
ui.with_layout(egui::Layout::top_down_justified(egui::Align::Min), |ui|{
|
||||||
|
|
||||||
|
egui::ScrollArea::vertical().auto_shrink(false).show(ui, |ui| {
|
||||||
if let Some(image) = &self.image {
|
if let Some(image) = &self.image {
|
||||||
ui.horizontal_top(|ui|{
|
ui.horizontal_top(|ui|{
|
||||||
let data = &self.data.clone().unwrap();
|
let data = &self.data.clone().unwrap();
|
||||||
|
|
@ -308,11 +386,13 @@ impl eframe::App for TemplateApp {
|
||||||
CollapsingHeader::new("Preview")
|
CollapsingHeader::new("Preview")
|
||||||
.default_open(true)
|
.default_open(true)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
|
ui.label(RichText::new("Frames JSON").strong());
|
||||||
|
egui_json_tree::JsonTree::new("simple-tree", &self.data.clone().unwrap().frames_json).show(ui);
|
||||||
|
ui.label(RichText::new("Spritesheet").strong());
|
||||||
ui.add(image.clone());
|
ui.add(image.clone());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
egui::ScrollArea::vertical().auto_shrink(false).show(ui, |ui| {
|
|
||||||
let mut index_to_remove : Option<usize> = None;
|
let mut index_to_remove : Option<usize> = None;
|
||||||
for (i, file) in self.dropped_files.iter().enumerate() {
|
for (i, file) in self.dropped_files.iter().enumerate() {
|
||||||
let mut info = if let Some(path) = &file.path {
|
let mut info = if let Some(path) = &file.path {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue