191 lines
8.0 KiB
Rust
191 lines
8.0 KiB
Rust
use std::{fs::File, io::Write, path::PathBuf};
|
|
|
|
use crate::{gui::{self, main_tab::{MainTab, NewVRAMImageInfo}, MutexTIMManager, VRAM_HEIGHT, VRAM_WIDTH}, MainWindow};
|
|
use super::FileTab;
|
|
use rfd::FileDialog;
|
|
use slint::SharedString;
|
|
use tim_tool::logic::{project::{ImagePosition, Job, PaletteRect, Project}, tim::types::Encoding};
|
|
use tool_helper::Error;
|
|
|
|
pub(super) fn on_browse_file(tim_manager: MutexTIMManager) -> impl FnMut(&mut FileTab, &MainWindow) -> Result<(), Error> + 'static {
|
|
return move |file_tab, main_window| -> Result<(), Error> {
|
|
let file = FileDialog::new()
|
|
.add_filter("PNG image (.png)", &["png"])
|
|
.set_title("PNG image file")
|
|
.pick_file();
|
|
|
|
if let Some(file) = file {
|
|
if let Some(file_path) = file.to_str() {
|
|
main_window.set_file_tab_browse_path(SharedString::from(file_path));
|
|
}
|
|
|
|
let file_name = if let Some(name) = file.file_name() {Some(name.to_string_lossy().to_string())} else {None};
|
|
|
|
let (image, palette) = tim_manager.lock().expect("VRAM already locked").load_unadded_tim(&file)?;
|
|
|
|
let img_size = image.size();
|
|
if img_size.width > VRAM_WIDTH as u32 || img_size.height > VRAM_HEIGHT as u32 {
|
|
return Err(Error::from_text(format!("Image size ({}; {}) is to big for VRAM ({}, {})", img_size.width, img_size.height, VRAM_WIDTH, VRAM_HEIGHT)));
|
|
}
|
|
return file_tab.update_new_loaded_file(file_name, image, palette);
|
|
}
|
|
|
|
Ok(())
|
|
};
|
|
}
|
|
|
|
pub(super) fn on_update_palette_size(tim_manager: MutexTIMManager) -> impl FnMut(&mut FileTab, &MainWindow, u16, u16) -> Result<(), Error> + 'static {
|
|
return move |file_tab, _main_window, width, height| -> Result<(), Error> {
|
|
file_tab.update_palette(tim_manager.lock().expect("VRAM already locked").change_unadded_tim_palette_size(width, height)?);
|
|
Ok(())
|
|
};
|
|
}
|
|
|
|
pub(super) fn on_add_image(tim_manager: MutexTIMManager) -> impl FnMut(&mut FileTab, &mut MainTab, &MainWindow) -> Result<(), Error> + 'static {
|
|
return move |file_tab, main_tab, main_window| {
|
|
let file_name = file_tab.get_file_name();
|
|
let encoding = file_tab.get_encoding()?;
|
|
|
|
add_unadded_tim(main_tab, tim_manager.clone(), &file_name, encoding)?;
|
|
|
|
file_tab.clear_load();
|
|
main_window.invoke_change_to_main();
|
|
Ok(())
|
|
};
|
|
}
|
|
|
|
pub(super) fn on_load_project_clicked(tim_manager: MutexTIMManager) -> impl FnMut(&mut FileTab, &MainWindow) -> Result<(), Error> + 'static {
|
|
move |_file_tab, main_window| {
|
|
let open_location = main_window.get_project_widget_open_project_path();
|
|
if open_location.is_empty() {
|
|
return Err(Error::from_str("Please specify location for project file to open"));
|
|
}
|
|
|
|
let file_content = tool_helper::read_file_to_string(&PathBuf::from(open_location.as_str()))?;
|
|
let new_project = match serde_json::from_str::<Project>(&file_content) {
|
|
Ok(project) => project,
|
|
Err(error) => {
|
|
return Err(Error::from_error(error));
|
|
}
|
|
};
|
|
|
|
for job in new_project.jobs {
|
|
let (_, _) = tim_manager.lock().expect("VRAM already locked").load_unadded_tim(&job.file_path)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub(super) fn on_save_project_clicked(tim_manager: MutexTIMManager) -> impl FnMut(&mut FileTab, &MainTab, &MainWindow) -> Result<(), Error> + 'static {
|
|
move |_file_tab, main_tab, main_window| {
|
|
let save_location = main_window.get_project_widget_save_project_path();
|
|
if save_location.is_empty() {
|
|
return Err(Error::from_str("Please specify save location for project file"));
|
|
}
|
|
|
|
let tim_info = tim_manager.lock().expect("VRAM already locked").clone_added_tims();
|
|
let vram_info = main_tab.clone_vram_info();
|
|
|
|
if tim_info.len() != vram_info.len() {
|
|
return Err(Error::from_str("TIM and VRAM info not in sync! Please close program"));
|
|
}
|
|
|
|
let mut cur_job:Option<Job> = None;
|
|
let mut cur_palette:Option<PaletteRect> = None;
|
|
let mut project = Project::new(tim_info.into_iter().zip(vram_info.into_iter()).filter_map(|(tim, (file_name, vram))| {
|
|
if vram.is_palette {
|
|
let cur_palette = std::mem::replace(&mut cur_palette, None);
|
|
if let Some(mut cur_palette) = cur_palette {
|
|
cur_palette.pos = ImagePosition::new(vram.x as u16, vram.y as u16);
|
|
if let Some(cur_job) = &mut cur_job {
|
|
cur_job.palette_rect = cur_palette;
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
else {
|
|
// We are done with the old job
|
|
let prev_job = std::mem::replace(&mut cur_job, None);
|
|
|
|
if let Some(tim) = tim {
|
|
if let Some((width, height)) = tim.get_palette_size() {
|
|
cur_palette = Some(PaletteRect::new(0, 0, width, height));
|
|
}
|
|
cur_job = Some(Job::new(file_name, tim.get_path(), (vram.x as u16, vram.y as u16), Encoding::from_str(vram.encoding_str.as_str())));
|
|
}
|
|
prev_job
|
|
}
|
|
}).collect());
|
|
if let Some(cur_job) = cur_job {
|
|
project.jobs.push(cur_job);
|
|
}
|
|
|
|
let json_content = match serde_json::to_string(&project) {
|
|
Ok(json_content) => json_content,
|
|
Err(error) => {
|
|
return Err(Error::from_error(error));
|
|
}
|
|
};
|
|
|
|
let mut file = File::create(save_location)?;
|
|
file.write_all(json_content.as_bytes())?;
|
|
|
|
gui::display_information("Saving project", "Project saved successfully");
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub(super) fn on_browse_open_project_clicked() -> impl FnMut(&mut FileTab, &MainWindow) -> Result<(), Error> + 'static {
|
|
move |_file_tab, main_window| {
|
|
let file_path = create_project_file_dialog()
|
|
.set_title("Save location for TIM project file")
|
|
.pick_file();
|
|
|
|
if let Some(file_path) = file_path {
|
|
if let Some(file_path) = file_path.to_str() {
|
|
main_window.set_project_widget_open_project_path(SharedString::from(file_path));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub(super) fn on_browse_save_project_clicked() -> impl FnMut(&mut FileTab, &MainWindow) -> Result<(), Error> + 'static {
|
|
move |_file_tab, main_window| {
|
|
let file_path = create_project_file_dialog()
|
|
.set_title("Save location for TIM project file")
|
|
.save_file();
|
|
|
|
if let Some(file_path) = file_path {
|
|
if let Some(file_path) = file_path.to_str() {
|
|
main_window.set_project_widget_save_project_path(SharedString::from(file_path));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn add_unadded_tim(main_tab: &mut MainTab, tim_manager: MutexTIMManager, file_name: &String, encoding: Encoding) -> Result<(), Error> {
|
|
let mut tim_mgr = tim_manager.lock().expect("VRAM already locked");
|
|
let (image, palette_image) = tim_mgr.get_converted_unadded_tim_image(encoding)?;
|
|
let (full_image, _) = tim_mgr.get_converted_unadded_tim_image(Encoding::FullColor)?;
|
|
let image = NewVRAMImageInfo::new(image, 0, 0, encoding);
|
|
let palette_image = if let Some(palette_image) = palette_image { Some(NewVRAMImageInfo::new(palette_image, 0, 0, Encoding::FullColor)) } else { None };
|
|
|
|
let images_created = main_tab.add_new_vram_file(file_name, full_image, image, palette_image);
|
|
if let Err(error) = tim_mgr.add_unadded_tim(images_created) {
|
|
main_tab.pop_vram_files(images_created);
|
|
return Err(error);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn create_project_file_dialog() -> FileDialog {
|
|
FileDialog::new()
|
|
.add_filter("TIM project file (.tim_project)", &["tim_project"])
|
|
.add_filter("JSON file (.json; .jsn)", &["json", "jsn"])
|
|
.add_filter("All", &["*"])
|
|
} |