mirror of https://github.com/Leinnan/rpack.git
View settings
This commit is contained in:
parent
63b57ce3eb
commit
e20442ad14
10
README.md
10
README.md
|
|
@ -111,6 +111,11 @@ Example:
|
|||
"key": "tiles/agents/spaceAstronauts_004"
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"app": "rpack",
|
||||
"app_version": "0.3.0",
|
||||
"format_version": 1
|
||||
},
|
||||
"size": [
|
||||
512,
|
||||
512
|
||||
|
|
@ -148,11 +153,6 @@ Example:
|
|||
"size": 512,
|
||||
"texture_padding": 2,
|
||||
"border_padding": 2,
|
||||
"metadata": {
|
||||
"app": "rpack",
|
||||
"app_version": "0.3.0",
|
||||
"format_version": 1
|
||||
},
|
||||
"size": [
|
||||
512,
|
||||
512
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ use crossbeam::queue::SegQueue;
|
|||
use egui::containers::menu::MenuButton;
|
||||
use egui::{
|
||||
util::undoer::Undoer, Button, Color32, FontFamily, FontId, Frame, Image, Label, Layout,
|
||||
RichText, Sense, Slider, Ui,
|
||||
RichText, Slider, Ui,
|
||||
};
|
||||
use egui::{Grid, Vec2};
|
||||
use egui::{Checkbox, Grid, Vec2};
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
use once_cell::sync::Lazy;
|
||||
use rpack_cli::TilemapGenerationConfig;
|
||||
|
|
@ -14,6 +14,7 @@ use rpack_cli::{
|
|||
use texture_packer::{Rect, TexturePackerConfig};
|
||||
|
||||
use crate::helpers::DroppedFileHelper;
|
||||
use crate::view_settings::ViewSettings;
|
||||
static INPUT_QUEUE: Lazy<SegQueue<AppImageAction>> = Lazy::new(SegQueue::new);
|
||||
pub const MY_ACCENT_COLOR32: Color32 = Color32::from_rgb(230, 102, 1);
|
||||
pub const GIT_HASH: &str = env!("GIT_HASH");
|
||||
|
|
@ -71,6 +72,8 @@ pub struct Application {
|
|||
last_error: Option<SpritesheetError>,
|
||||
undoer: Undoer<ApplicationData>,
|
||||
last_editor_paths: Vec<String>,
|
||||
view_settings: ViewSettings,
|
||||
show_modal: bool,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize, Default, Clone, PartialEq)]
|
||||
|
|
@ -113,6 +116,8 @@ impl Default for Application {
|
|||
output: SpriteSheetState::Empty,
|
||||
last_error: None,
|
||||
last_editor_paths: Vec::new(),
|
||||
view_settings: Default::default(),
|
||||
show_modal: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -203,8 +208,14 @@ impl Application {
|
|||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let view_settings: ViewSettings = if let Some(storage) = cc.storage {
|
||||
eframe::get_value(storage, "view_settings").unwrap_or_default()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
let mut app = Self {
|
||||
last_editor_paths,
|
||||
view_settings,
|
||||
..Default::default()
|
||||
};
|
||||
cc.egui_ctx.include_bytes("bytes://image.png", ICON_DATA);
|
||||
|
|
@ -356,6 +367,7 @@ impl eframe::App for Application {
|
|||
/// Called by the framework to save state before shutdown.
|
||||
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
||||
eframe::set_value(storage, eframe::APP_KEY, &self.last_editor_paths);
|
||||
eframe::set_value(storage, "view_settings", &self.view_settings);
|
||||
}
|
||||
/// Called each time the UI needs repainting, which may be many times per second.
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
|
|
@ -453,6 +465,39 @@ impl eframe::App for Application {
|
|||
self.build_atlas(ctx);
|
||||
}
|
||||
}
|
||||
if self.show_modal {
|
||||
let mut should_close = false;
|
||||
|
||||
should_close |= egui::Modal::new("VisualSettings".into())
|
||||
.frame(egui::Frame::menu(&ctx.style()).inner_margin(10.0))
|
||||
.show(ctx, |ui| {
|
||||
ui.style_mut().interaction.selectable_labels = false;
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.heading("Settings");
|
||||
ui.add_space(15.0);
|
||||
Grid::new("settings_grid")
|
||||
.num_columns(2)
|
||||
.striped(true)
|
||||
.show(ui, |ui| {
|
||||
ui.add(Label::new("Max Preview size"));
|
||||
ui.add(Slider::new(
|
||||
&mut self.view_settings.preview_max_size,
|
||||
256.0..=1024.0,
|
||||
));
|
||||
ui.end_row();
|
||||
ui.add(Label::new("Display JSON"));
|
||||
ui.add(Checkbox::new(&mut self.view_settings.display_json, ""));
|
||||
ui.end_row();
|
||||
});
|
||||
ui.add_space(10.0);
|
||||
should_close |= ui.button("Close").clicked();
|
||||
});
|
||||
})
|
||||
.should_close();
|
||||
if should_close {
|
||||
self.show_modal = false;
|
||||
}
|
||||
}
|
||||
egui::TopBottomPanel::top("topPanel")
|
||||
.frame(egui::Frame::canvas(&ctx.style()))
|
||||
.show(ctx, |ui| {
|
||||
|
|
@ -552,7 +597,12 @@ impl eframe::App for Application {
|
|||
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||
puffin::profile_scope!("bottom_panel");
|
||||
ui.add_space(5.0);
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_space(5.0);
|
||||
if ui.button("🛠").on_hover_text("Visual settings").clicked() {
|
||||
self.show_modal = true;
|
||||
}
|
||||
ui.add_space(5.0);
|
||||
ui.add_enabled_ui(self.undoer.has_undo(&self.data), |ui| {
|
||||
if ui.button("⮪").on_hover_text("Go back").clicked() {
|
||||
|
|
@ -582,10 +632,11 @@ impl eframe::App for Application {
|
|||
.max_width(400.0)
|
||||
.frame(egui::Frame::canvas(&ctx.style()).inner_margin(10))
|
||||
.show_animated(ctx, !self.data.image_data.is_empty(), |ui| {
|
||||
egui::ScrollArea::vertical()
|
||||
.id_salt("rightPanel_scroll")
|
||||
.show(ui, |ui| {
|
||||
ui.add_enabled_ui(!self.output.is_building(), |ui| {
|
||||
ui.with_layout(
|
||||
Layout::top_down(egui::Align::Min).with_cross_justify(true),
|
||||
|ui| {
|
||||
ui.style_mut().interaction.selectable_labels = false;
|
||||
{
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||
puffin::profile_scope!("right_panel");
|
||||
let mut changed = false;
|
||||
|
|
@ -674,36 +725,20 @@ impl eframe::App for Application {
|
|||
}
|
||||
}
|
||||
});
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
ui.add_space(10.0);
|
||||
|
||||
// changed |= ui.checkbox(&mut
|
||||
// self.data.settings., "Force Max Dimensions").changed();
|
||||
// ui.checkbox(&mut self.config.allow_rotation, "Allow Rotation")
|
||||
// .on_hover_text("True to allow rotation of the input images. Default value is `true`. Images rotated will be rotated 90 degrees clockwise.");
|
||||
// ui.checkbox(&mut self.data.config.texture_outlines, "Texture Outlines")
|
||||
// .on_hover_text("Draw the red line on the edge of the each frames. Useful for debugging.");
|
||||
|
||||
ui.add_space(10.0);
|
||||
});
|
||||
if changed {
|
||||
INPUT_QUEUE.push(AppImageAction::RebuildAtlas);
|
||||
}
|
||||
ui.separator();
|
||||
{
|
||||
ui.style_mut().interaction.selectable_labels = false;
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||
puffin::profile_scope!("image_list");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.heading("Images");
|
||||
ui.with_layout(
|
||||
Layout::right_to_left(egui::Align::Center),
|
||||
|ui| {
|
||||
}
|
||||
Grid::new("ImgesHeader")
|
||||
.num_columns(2)
|
||||
.spacing([50.0, 10.0])
|
||||
.show(ui, |ui| {
|
||||
ui.menu_button("🖼", |ui| {
|
||||
if !self.data.image_data.is_empty()
|
||||
&& ui
|
||||
.add(egui::Button::new("🗙").frame(false))
|
||||
.on_hover_text("Remove all images")
|
||||
.add(
|
||||
egui::Button::new("Remove all images").frame(false),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
INPUT_QUEUE.push(AppImageAction::Clear);
|
||||
|
|
@ -711,83 +746,33 @@ impl eframe::App for Application {
|
|||
ui.add_space(10.0);
|
||||
|
||||
if ui
|
||||
.add(egui::Button::new("⊞").frame(false))
|
||||
.on_hover_text("Add more images")
|
||||
.add(egui::Button::new("Add more images").frame(false))
|
||||
.clicked()
|
||||
{
|
||||
self.read_files();
|
||||
}
|
||||
if ui.available_width() > 15.0 {
|
||||
ui.add_space(ui.available_width() - 10.0);
|
||||
}
|
||||
},
|
||||
)
|
||||
});
|
||||
let length = self.data.image_data.len();
|
||||
let text_height =
|
||||
egui::TextStyle::Body.resolve(ui.style()).size * 1.5;
|
||||
ui.heading("Images");
|
||||
});
|
||||
|
||||
ui.add_enabled_ui(!self.output.is_building(), |ui| {
|
||||
ui.separator();
|
||||
{
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||
puffin::profile_scope!("image_list");
|
||||
|
||||
let length = self.data.image_data.len();
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.vscroll(true)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||
.column(Column::remainder().at_least(50.0))
|
||||
.column(Column::exact(70.0))
|
||||
.column(Column::auto().at_most(150.0).at_least(30.0))
|
||||
.column(Column::auto())
|
||||
.column(Column::remainder().at_least(50.0))
|
||||
.sense(egui::Sense::click());
|
||||
table
|
||||
.header(text_height, |mut row| {
|
||||
row.col(|col| {
|
||||
col.vertical_centered_justified(|ui| {
|
||||
ui.add(
|
||||
egui::Label::new("Name")
|
||||
.wrap_mode(egui::TextWrapMode::Truncate)
|
||||
.selectable(false), // .sense(Sense::click()),
|
||||
)
|
||||
});
|
||||
});
|
||||
row.col(|col| {
|
||||
col.vertical_centered_justified(|ui| {
|
||||
ui.add(
|
||||
egui::Label::new("Preview")
|
||||
.wrap_mode(egui::TextWrapMode::Truncate)
|
||||
.selectable(false),
|
||||
)
|
||||
});
|
||||
});
|
||||
row.col(|col| {
|
||||
col.vertical_centered_justified(|ui| {
|
||||
ui.add(
|
||||
egui::Label::new("Dimensions")
|
||||
.wrap_mode(egui::TextWrapMode::Truncate)
|
||||
.selectable(false)
|
||||
.sense(Sense::click()),
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
row.col(|col| {
|
||||
col.vertical_centered_justified(|ui| {
|
||||
ui.add(
|
||||
egui::Label::new("")
|
||||
.wrap_mode(egui::TextWrapMode::Truncate)
|
||||
.selectable(false),
|
||||
)
|
||||
});
|
||||
});
|
||||
})
|
||||
.body(|body| {
|
||||
table.body(|body| {
|
||||
body.rows(64.0, length, |mut row| {
|
||||
let index = row.index();
|
||||
let file = &self.data.image_data[index];
|
||||
row.col(|ui| {
|
||||
ui.add(
|
||||
Label::new(file.id())
|
||||
.selectable(false)
|
||||
.wrap_mode(egui::TextWrapMode::Truncate),
|
||||
);
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
ui.add_sized(
|
||||
|
|
@ -797,32 +782,37 @@ impl eframe::App for Application {
|
|||
file.path.as_str()
|
||||
))
|
||||
.corner_radius(5u8),
|
||||
);
|
||||
)
|
||||
.on_hover_text(format!(
|
||||
"{}x{}",
|
||||
file.width, file.height
|
||||
));
|
||||
});
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.add(
|
||||
Label::new(format!(
|
||||
"{}x{}",
|
||||
file.width, file.height
|
||||
))
|
||||
.selectable(false),
|
||||
Label::new(file.id())
|
||||
.selectable(false)
|
||||
.wrap_mode(egui::TextWrapMode::Truncate),
|
||||
);
|
||||
});
|
||||
row.col(|ui| {
|
||||
})
|
||||
.1
|
||||
.context_menu(
|
||||
|ui| {
|
||||
if ui
|
||||
.add(Button::new("🗙").frame(false))
|
||||
.on_hover_text("Remove")
|
||||
.add(Button::new("Remove").frame(false))
|
||||
.clicked()
|
||||
{
|
||||
INPUT_QUEUE.push(AppImageAction::Remove(index));
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
egui::CentralPanel::default()
|
||||
.frame(Frame::central_panel(&ctx.style()).inner_margin(16i8))
|
||||
|
|
@ -908,19 +898,17 @@ impl eframe::App for Application {
|
|||
let SpriteSheetState::Ok(data) = &self.output else {
|
||||
return;
|
||||
};
|
||||
ui.add(Image::from_uri("bytes://output.png").bg_fill(Color32::from_black_alpha(200)).max_size(Vec2::new(512.0,512.0)));
|
||||
ui.separator();
|
||||
ui.add_space(10.0);
|
||||
ui.horizontal(|ui|{
|
||||
ui.label(format!(
|
||||
ui.add(Image::from_uri("bytes://output.png").bg_fill(Color32::from_black_alpha(200)).max_size(Vec2::splat(self.view_settings.preview_max_size))).on_hover_text(format!(
|
||||
"{} sprites\nsize: {}x{}",
|
||||
data.atlas_asset.frames.len(),
|
||||
data.atlas_asset.size[0],
|
||||
data.atlas_asset.size[1]
|
||||
));
|
||||
ui.separator();
|
||||
ui.add_space(10.0);
|
||||
ui.horizontal(|ui|{
|
||||
if self.view_settings.display_json {
|
||||
ui.vertical_centered_justified(|ui|{
|
||||
|
||||
ui.add_space(10.0);
|
||||
if ui
|
||||
.add(egui::Button::new("Copy JSON to Clipboard"))
|
||||
|
|
@ -936,6 +924,7 @@ impl eframe::App for Application {
|
|||
)
|
||||
.show(ui);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,5 +3,6 @@
|
|||
mod app;
|
||||
mod fonts;
|
||||
mod helpers;
|
||||
mod view_settings;
|
||||
pub use app::Application;
|
||||
pub use app::ICON_DATA;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ViewSettings {
|
||||
pub preview_max_size: f32,
|
||||
pub display_json: bool,
|
||||
}
|
||||
|
||||
impl Default for ViewSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
preview_max_size: 512.0,
|
||||
display_json: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue