Projects: Inital support for saving and loading projects #22

Merged
cody merged 17 commits from topic/jb/project-files into main 2025-04-05 19:56:33 +00:00
6 changed files with 82 additions and 18 deletions
Showing only changes of commit aae57e47e4 - Show all commits

View File

@ -4,7 +4,7 @@ use crate::{gui::{self, main_tab::MainTab, MutexTIMManager, VRAM_HEIGHT, VRAM_WI
use super::FileTab; use super::FileTab;
use rfd::FileDialog; use rfd::FileDialog;
use slint::SharedString; use slint::SharedString;
use tim_tool::logic::{project::{Job, Project}, tim::types::Encoding}; use tim_tool::logic::{project::{Job, PaletteRect, Project}, tim::types::Encoding};
use tool_helper::Error; use tool_helper::Error;
pub(super) fn on_browse_file(tim_manager: MutexTIMManager) -> impl FnMut(&mut FileTab, &MainWindow) -> Result<(), Error> + 'static { pub(super) fn on_browse_file(tim_manager: MutexTIMManager) -> impl FnMut(&mut FileTab, &MainWindow) -> Result<(), Error> + 'static {
@ -34,7 +34,7 @@ pub(super) fn on_browse_file(tim_manager: MutexTIMManager) -> impl FnMut(&mut Fi
}; };
} }
pub(super) fn on_update_palette_size(tim_manager: MutexTIMManager) -> impl FnMut(&mut FileTab, &MainWindow, u32, u32) -> Result<(), Error> + 'static { 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> { 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)?); file_tab.update_palette(tim_manager.lock().expect("VRAM already locked").change_unadded_tim_palette_size(width, height)?);
Ok(()) Ok(())
@ -93,7 +93,12 @@ pub(super) fn on_save_project_clicked(tim_manager: MutexTIMManager) -> impl FnMu
let prev_job = std::mem::replace(&mut cur_job, None); let prev_job = std::mem::replace(&mut cur_job, None);
if let Some(tim) = tim { if let Some(tim) = tim {
cur_job = Some(Job::new(file_name, tim.get_path())); let mut job = Job::new(file_name, tim.get_path(), (vram.x as u16, vram.y as u16));
if let Some((width, height)) = tim.get_palette_size() {
job.add_palette(PaletteRect::new(0, 0, width, height));
}
cur_job = Some(job);
} }
prev_job prev_job
} }

View File

@ -60,7 +60,7 @@ impl FileTab {
let (cloned_object, cloned_main_window, mut function) = (object.clone(), main_window.clone(), callbacks::on_update_palette_size(tim_manager.clone())); let (cloned_object, cloned_main_window, mut function) = (object.clone(), main_window.clone(), callbacks::on_update_palette_size(tim_manager.clone()));
main_window.borrow().on_file_tab_update_palette_size(move |width, height| { main_window.borrow().on_file_tab_update_palette_size(move |width, height| {
if let Err(error) = function(&mut cloned_object.borrow_mut(), &cloned_main_window.borrow(), width as u32, height as u32) { if let Err(error) = function(&mut cloned_object.borrow_mut(), &cloned_main_window.borrow(), width as u16, height as u16) {
display_error("Updating palette failed", &error.to_string()); display_error("Updating palette failed", &error.to_string());
} }
}); });

View File

@ -1,19 +1,68 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Job { struct ImagePosition {
name: String, pub x: u16,
file_path: PathBuf, pub y: u16,
} }
impl Job { impl std::default::Default for ImagePosition {
pub fn new(name: String, file_path: PathBuf) -> Job { fn default() -> Self {
Job{name, file_path} ImagePosition{x: 0, y: 0}
} }
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct ImageSize {
pub width: u16,
pub height: u16,
}
impl std::default::Default for ImageSize {
fn default() -> Self {
ImageSize{width: 0, height: 0}
}
}
#[derive(Serialize, Deserialize)]
pub struct PaletteRect {
pos: ImagePosition,
size: ImageSize,
}
impl PaletteRect {
pub fn new(x: u16, y: u16, width: u16, height: u16) -> PaletteRect {
PaletteRect{pos: ImagePosition{x, y}, size: ImageSize{width, height}}
}
}
impl std::default::Default for PaletteRect {
fn default() -> Self {
PaletteRect{pos: ImagePosition::default(), size: ImageSize::default()}
}
}
#[derive(Serialize, Deserialize)]
pub struct Job {
name: String,
file_path: PathBuf,
image_pos: ImagePosition,
palette_rect: PaletteRect,
}
impl Job {
pub fn new(name: String, file_path: PathBuf, image_pos: (u16, u16)) -> Job {
Job{name, file_path, image_pos: ImagePosition{x: image_pos.0, y: image_pos.1}, palette_rect: PaletteRect::default()}
}
pub fn add_palette(&mut self, palette_rect: PaletteRect) -> &mut Self {
self.palette_rect = palette_rect;
self
}
}
#[derive(Serialize, Deserialize)]
pub struct Project { pub struct Project {
jobs: Vec<Job> jobs: Vec<Job>
} }

View File

@ -75,7 +75,7 @@ impl TIMInfo {
} }
} }
pub fn change_palette_size(&mut self, width: u32, height: u32) -> Result<Option<slint::Image>, Error> { pub fn change_palette_size(&mut self, width: u16, height: u16) -> Result<Option<slint::Image>, Error> {
if let Some(palette) = &mut self.palette { if let Some(palette) = &mut self.palette {
if width == 0 || height == 0 { if width == 0 || height == 0 {
return Err(Error::from_text(format!("{}px x {}px is not a valid size for palette", width, height))); return Err(Error::from_text(format!("{}px x {}px is not a valid size for palette", width, height)));
@ -119,6 +119,16 @@ impl TIMInfo {
}) })
} }
pub fn get_palette_size(&self) -> Option<(u16, u16)> {
if let Some(palette_info) = &self.palette {
Some((palette_info.width, palette_info.height))
}
else {
None
}
}
pub fn get_path(&self) -> std::path::PathBuf { pub fn get_path(&self) -> std::path::PathBuf {
self.path.clone() self.path.clone()
} }
@ -127,8 +137,8 @@ impl TIMInfo {
#[derive(Clone)] #[derive(Clone)]
struct PaletteInfo { struct PaletteInfo {
data: Vec<Rgba8Pixel>, data: Vec<Rgba8Pixel>,
width: u32, width: u16,
height: u32, height: u16,
} }
impl PaletteInfo { impl PaletteInfo {
@ -138,7 +148,7 @@ impl PaletteInfo {
} }
pub fn get_image(&self) -> slint::Image { pub fn get_image(&self) -> slint::Image {
let mut image_data = SharedPixelBuffer::new(self.width, self.height); let mut image_data = SharedPixelBuffer::new(self.width as u32, self.height as u32);
let dst_pixels = image_data.make_mut_slice(); let dst_pixels = image_data.make_mut_slice();
for (idx, byte) in dst_pixels.iter_mut().enumerate() { for (idx, byte) in dst_pixels.iter_mut().enumerate() {

View File

@ -60,7 +60,7 @@ impl TIMManager {
} }
} }
pub fn change_unadded_tim_palette_size(&mut self, width: u32, height: u32) -> Result<Option<Image>, Error> { pub fn change_unadded_tim_palette_size(&mut self, width: u16, height: u16) -> Result<Option<Image>, Error> {
if let Some(unadded_tim) = &mut self.unadded_tim { if let Some(unadded_tim) = &mut self.unadded_tim {
unadded_tim.change_palette_size(width, height) unadded_tim.change_palette_size(width, height)
} }

View File

@ -11,7 +11,7 @@ struct VRAMInfo {
y: int, y: int,
encoding_str: string, encoding_str: string,
palette_count: int, palette_count: int,
is_palette: bool, is_palette: bool, // < Can we combine the palette into this, instead of having it separate?
} }
struct VRAMData { struct VRAMData {