From 63751836242363762d2d53fd0df4e0d3f5d47db2 Mon Sep 17 00:00:00 2001 From: Jaby Date: Thu, 6 Mar 2025 19:58:13 +0100 Subject: [PATCH 1/5] Display size of image --- src/Tools/tim_tool/src/gui/file_tab.rs | 3 ++ src/Tools/tim_tool/ui/app-window.slint | 2 ++ src/Tools/tim_tool/ui/tab/file-tab.slint | 46 ++++++++++++++++-------- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/Tools/tim_tool/src/gui/file_tab.rs b/src/Tools/tim_tool/src/gui/file_tab.rs index 4bf68e6f..2f5118fe 100644 --- a/src/Tools/tim_tool/src/gui/file_tab.rs +++ b/src/Tools/tim_tool/src/gui/file_tab.rs @@ -25,8 +25,11 @@ impl FileTab { self.update_palette(palette); let main_window = self.main_window.borrow(); + let image_size = image.size(); main_window.set_file_tab_image_data(image); + main_window.set_file_tab_image_width(image_size.width as i32); + main_window.set_file_tab_image_height(image_size.height as i32); if let Some(file_name) = file_name { main_window.set_file_tab_image_name(file_name.into()); } diff --git a/src/Tools/tim_tool/ui/app-window.slint b/src/Tools/tim_tool/ui/app-window.slint index 4e00ab32..fa4d9faa 100644 --- a/src/Tools/tim_tool/ui/app-window.slint +++ b/src/Tools/tim_tool/ui/app-window.slint @@ -15,6 +15,8 @@ export component MainWindow inherits Window { // Convert Image values in-out property file_tab-browse_path <=> file_tab.conv-image_path; in-out property file_tab-image_data <=> file_tab.conv-image_data; + in-out property file_tab-image_width <=> file_tab.conv-image_width; + in-out property file_tab-image_height <=> file_tab.conv-image_height; in-out property file_tab-palette_data <=> file_tab.conv-palette_data; in-out property file_tab-palette_width <=> file_tab.conv-palette_width; in-out property file_tab-palette_height <=> file_tab.conv-palette_height; diff --git a/src/Tools/tim_tool/ui/tab/file-tab.slint b/src/Tools/tim_tool/ui/tab/file-tab.slint index 958b7070..76562557 100644 --- a/src/Tools/tim_tool/ui/tab/file-tab.slint +++ b/src/Tools/tim_tool/ui/tab/file-tab.slint @@ -15,6 +15,8 @@ component ConvertImageWidget inherits Rectangle { in-out property image_path; in-out property image_name; in-out property image_data; + in-out property image-width; + in-out property image-height; in-out property palette_data; in-out property palette_width: 0; in-out property palette_height: 0; @@ -59,18 +61,32 @@ component ConvertImageWidget inherits Rectangle { padding: 4px; HorizontalLayout { alignment: center; - Rectangle { - width: 256px + 2*4px; // < Because of border - height: 256px + 2*4px; // < Because of border - background: #404040; - border-color: #808080; - border-width: 4px; - Image { - width: 256px; - height: 256px; - source: root.image_data; - image-fit: contain; - image-rendering: pixelated; + VerticalLayout { + Rectangle { + width: 256px + 2*4px; // < Because of border + height: 256px + 2*4px; // < Because of border + background: #404040; + border-color: #808080; + border-width: 4px; + Image { + width: 256px; + height: 256px; + source: root.image_data; + image-fit: contain; + image-rendering: pixelated; + } + } + VerticalLayout { + alignment: center; + Text { + text: "Width: " + root.image-width; + } + } + VerticalLayout { + alignment: center; + Text { + text: "Height: " + root.image-height; + } } } Rectangle { @@ -172,17 +188,17 @@ component ConvertImageWidget inherits Rectangle { } export component FileTab inherits Rectangle { - // TODO: Names are messed up here! in-out property conv-image_path; in-out property conv-image_name; in-out property conv-image_data; + in-out property conv-image_width; + in-out property conv-image_height; in-out property conv-palette_data; in-out property conv-palette_width; in-out property conv-palette_height; in-out property conv-palette_enable; in-out property conv-enable_view; - in-out property state; callback conv-image_update_palette_size(int, int); callback conv-image_browse_clicked; @@ -220,6 +236,8 @@ export component FileTab inherits Rectangle { if root.state == State.ConvertImage : ConvertImageWidget { image_path <=> root.conv-image_path; image_data <=> root.conv-image_data; + image-width <=> root.conv-image_width; + image-height <=> root.conv-image_height; palette_data <=> root.conv-palette_data; palette_width <=> root.conv-palette_width; palette_height <=> root.conv-palette_height; From 454fa43492a8be5a6e9beefad9a2be29b3f4ba7e Mon Sep 17 00:00:00 2001 From: Jaby Date: Thu, 6 Mar 2025 20:52:23 +0100 Subject: [PATCH 2/5] Add combobox for encoding type --- src/Tools/tim_tool/src/gui/file_tab.rs | 47 +++++++++++++-- src/Tools/tim_tool/src/main.rs | 2 +- src/Tools/tim_tool/ui/app-window.slint | 1 + src/Tools/tim_tool/ui/tab/file-tab.slint | 73 ++++++++++++++---------- 4 files changed, 87 insertions(+), 36 deletions(-) diff --git a/src/Tools/tim_tool/src/gui/file_tab.rs b/src/Tools/tim_tool/src/gui/file_tab.rs index 2f5118fe..649b287d 100644 --- a/src/Tools/tim_tool/src/gui/file_tab.rs +++ b/src/Tools/tim_tool/src/gui/file_tab.rs @@ -1,27 +1,63 @@ use crate::MainWindow; use super::{GUIElements, GUIElementsRef, MainWindowRef, display_error}; -use slint::Image; +use slint::{Image, SharedString}; +use std::rc::Rc; use tool_helper::Error; pub struct FileTab { - main_window: MainWindowRef + main_window: MainWindowRef, + encoding_options: Rc> } impl FileTab { + fn update_encoding_options(&self, width: u32, height: u32, has_palette: bool) -> Result<(), Error> { + self.encoding_options.clear(); + + if has_palette { + let has_4bit = width%4 == 0; + let has_8bit = width%2 == 0; + + if !has_4bit && !has_8bit { + return Err(Error::from_text(format!("Image width must be multiple of 2 and or 4 ({}/{})", width, height))); + } + + if has_4bit { + self.encoding_options.push(SharedString::from(format!("4 bit ({}/{})", width/4, height))); + } + + if has_8bit { + self.encoding_options.push(SharedString::from(format!("8 bit ({}/{})", width/2, height))); + } + Ok(()) + } + + else { + self.encoding_options.push(SharedString::from(format!("16 bit ({}/{})", width, height))); + Ok(()) + } + } + pub fn new(main_window: MainWindowRef) -> FileTab { - FileTab{main_window} + let encoding_options = Rc::new(slint::VecModel::from(Vec::::new())); + + main_window.borrow().set_file_tab_encoding_options(encoding_options.clone().into()); + FileTab{main_window, encoding_options} } pub fn clear_load(&self) { let main_window = self.main_window.borrow(); + self.encoding_options.clear(); main_window.set_file_tab_browse_path("".into()); main_window.set_file_tab_image_data(Image::default()); + main_window.set_file_tab_palette_data(Image::default()); main_window.set_file_tab_image_name("".into()); main_window.set_file_tab_enable(false); } - pub fn update_new_loaded_file(&self, file_name: Option, image: Image, palette: Option) { + pub fn update_new_loaded_file(&self, file_name: Option, image: Image, palette: Option) -> Result<(), Error> { + let has_palette = palette.is_some(); + self.update_palette(palette); let main_window = self.main_window.borrow(); @@ -37,7 +73,10 @@ impl FileTab { else { main_window.set_file_tab_image_name("".into()); } + + self.update_encoding_options(image_size.width, image_size.height, has_palette)?; main_window.set_file_tab_enable(true); + Ok(()) } pub fn update_palette(&self, palette: Option) { diff --git a/src/Tools/tim_tool/src/main.rs b/src/Tools/tim_tool/src/main.rs index d351734e..51155b7b 100644 --- a/src/Tools/tim_tool/src/main.rs +++ b/src/Tools/tim_tool/src/main.rs @@ -72,7 +72,7 @@ fn setup_file_tab(gui_elements_ref: Rc>, logic_ref: Rc 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))); } - file_tab.update_new_loaded_file(file_name, image, palette); + return file_tab.update_new_loaded_file(file_name, image, palette); } Ok(()) diff --git a/src/Tools/tim_tool/ui/app-window.slint b/src/Tools/tim_tool/ui/app-window.slint index fa4d9faa..96f833a6 100644 --- a/src/Tools/tim_tool/ui/app-window.slint +++ b/src/Tools/tim_tool/ui/app-window.slint @@ -13,6 +13,7 @@ export component MainWindow inherits Window { callback move_vram_image <=> main_tab.move_vram_image; // Convert Image values + in-out property file_tab-encoding_options <=> file_tab.conv-encoding_options; in-out property file_tab-browse_path <=> file_tab.conv-image_path; in-out property file_tab-image_data <=> file_tab.conv-image_data; in-out property file_tab-image_width <=> file_tab.conv-image_width; diff --git a/src/Tools/tim_tool/ui/tab/file-tab.slint b/src/Tools/tim_tool/ui/tab/file-tab.slint index 76562557..f7a5c20c 100644 --- a/src/Tools/tim_tool/ui/tab/file-tab.slint +++ b/src/Tools/tim_tool/ui/tab/file-tab.slint @@ -1,4 +1,4 @@ -import { Button, TabWidget, LineEdit, GroupBox } from "std-widgets.slint"; +import { Button, TabWidget, LineEdit, GroupBox, ComboBox } from "std-widgets.slint"; export enum State { Project, @@ -12,16 +12,17 @@ component ProjectWidget inherits Rectangle { } component ConvertImageWidget inherits Rectangle { - in-out property image_path; - in-out property image_name; - in-out property image_data; - in-out property image-width; - in-out property image-height; - in-out property palette_data; - in-out property palette_width: 0; - in-out property palette_height: 0; - in-out property enable_view: false; - in-out property palette_visible: false; + in-out property <[string]> encoding_options: []; + in-out property image_path; + in-out property image_name; + in-out property image_data; + in-out property image-width; + in-out property image-height; + in-out property palette_data; + in-out property palette_width: 0; + in-out property palette_height: 0; + in-out property enable_view: false; + in-out property palette_visible: false; callback browse_clicked(); callback add_clicked(); @@ -88,6 +89,13 @@ component ConvertImageWidget inherits Rectangle { text: "Height: " + root.image-height; } } + VerticalLayout { + alignment: center; + ComboBox { + model: root.encoding_options; + enabled: root.enable_view; + } + } } Rectangle { // Fake padding because the padding setting for the HorizontalLayout would not work @@ -188,16 +196,17 @@ component ConvertImageWidget inherits Rectangle { } export component FileTab inherits Rectangle { - in-out property conv-image_path; - in-out property conv-image_name; - in-out property conv-image_data; - in-out property conv-image_width; - in-out property conv-image_height; - in-out property conv-palette_data; - in-out property conv-palette_width; - in-out property conv-palette_height; - in-out property conv-palette_enable; - in-out property conv-enable_view; + in-out property <[string]> conv-encoding_options; + in-out property conv-image_path; + in-out property conv-image_name; + in-out property conv-image_data; + in-out property conv-image_width; + in-out property conv-image_height; + in-out property conv-palette_data; + in-out property conv-palette_width; + in-out property conv-palette_height; + in-out property conv-palette_enable; + in-out property conv-enable_view; in-out property state; callback conv-image_update_palette_size(int, int); @@ -233,17 +242,19 @@ export component FileTab inherits Rectangle { alignment: start; if root.state == State.Project : ProjectWidget { } + if root.state == State.ConvertImage : ConvertImageWidget { - image_path <=> root.conv-image_path; - image_data <=> root.conv-image_data; - image-width <=> root.conv-image_width; - image-height <=> root.conv-image_height; - palette_data <=> root.conv-palette_data; - palette_width <=> root.conv-palette_width; - palette_height <=> root.conv-palette_height; - palette_visible <=> root.conv-palette_enable; - image_name <=> root.conv-image_name; - enable_view <=> root.conv-enable_view; + encoding_options <=> root.conv-encoding_options; + image_path <=> root.conv-image_path; + image_data <=> root.conv-image_data; + image-width <=> root.conv-image_width; + image-height <=> root.conv-image_height; + palette_data <=> root.conv-palette_data; + palette_width <=> root.conv-palette_width; + palette_height <=> root.conv-palette_height; + palette_visible <=> root.conv-palette_enable; + image_name <=> root.conv-image_name; + enable_view <=> root.conv-enable_view; update_palette_size(width, height) => { root.conv-image_update_palette_size(width, height); From 8ead2a205dc4e736dea83d71e50466cd5c5b5f00 Mon Sep 17 00:00:00 2001 From: Jaby Date: Thu, 6 Mar 2025 21:56:52 +0100 Subject: [PATCH 3/5] Support scaling image depended on encoding --- src/Tools/tim_tool/src/gui/file_tab.rs | 31 +++++++++++++++-- src/Tools/tim_tool/src/logic/mod.rs | 10 +++--- src/Tools/tim_tool/src/logic/tim.rs | 30 +++++++++++++++-- src/Tools/tim_tool/src/main.rs | 3 +- src/Tools/tim_tool/ui/app-window.slint | 1 + src/Tools/tim_tool/ui/tab/file-tab.slint | 42 ++++++++++++++---------- 6 files changed, 89 insertions(+), 28 deletions(-) diff --git a/src/Tools/tim_tool/src/gui/file_tab.rs b/src/Tools/tim_tool/src/gui/file_tab.rs index 649b287d..df6461da 100644 --- a/src/Tools/tim_tool/src/gui/file_tab.rs +++ b/src/Tools/tim_tool/src/gui/file_tab.rs @@ -2,6 +2,7 @@ use crate::MainWindow; use super::{GUIElements, GUIElementsRef, MainWindowRef, display_error}; use slint::{Image, SharedString}; use std::rc::Rc; +use tim_tool::logic::tim::Encoding; use tool_helper::Error; pub struct FileTab { @@ -10,6 +11,10 @@ pub struct FileTab { } impl FileTab { + const FOUR_BIT_NAME:&str = "4 bit"; + const EIGHT_BIT_NAME:&str = "8 bit"; + const FULL_COLOR_NAME:&str = "Full color"; + fn update_encoding_options(&self, width: u32, height: u32, has_palette: bool) -> Result<(), Error> { self.encoding_options.clear(); @@ -22,17 +27,17 @@ impl FileTab { } if has_4bit { - self.encoding_options.push(SharedString::from(format!("4 bit ({}/{})", width/4, height))); + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::FOUR_BIT_NAME, width/4, height))); } if has_8bit { - self.encoding_options.push(SharedString::from(format!("8 bit ({}/{})", width/2, height))); + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::EIGHT_BIT_NAME, width/2, height))); } Ok(()) } else { - self.encoding_options.push(SharedString::from(format!("16 bit ({}/{})", width, height))); + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::FULL_COLOR_NAME, width, height))); Ok(()) } } @@ -102,6 +107,26 @@ impl FileTab { self.main_window.borrow().get_file_tab_image_name().to_string() } + pub fn get_encoding(&self) -> Result { + let selected_encoding = self.main_window.borrow().get_file_tab_selected_encoding(); + + if selected_encoding.starts_with(Self::FOUR_BIT_NAME) { + Ok(Encoding::FourBit) + } + + else if selected_encoding.starts_with(Self::EIGHT_BIT_NAME) { + Ok(Encoding::EightBit) + } + + else if selected_encoding.starts_with(Self::FULL_COLOR_NAME) { + Ok(Encoding::FullColor) + } + + else { + Err(Error::from_str("Failed to obtain encoding")) + } + } + pub fn on_browse_file(&self, gui_elements: GUIElementsRef, mut function: impl FnMut(&mut GUIElements, &MainWindow) -> Result<(), Error> + 'static) { let main_window_cloned = self.main_window.clone(); let gui_cloned = gui_elements.clone(); diff --git a/src/Tools/tim_tool/src/logic/mod.rs b/src/Tools/tim_tool/src/logic/mod.rs index fd5fc7b3..71fbe9fc 100644 --- a/src/Tools/tim_tool/src/logic/mod.rs +++ b/src/Tools/tim_tool/src/logic/mod.rs @@ -2,7 +2,7 @@ pub mod tim; use std::path::PathBuf; use slint::Image; -use tim::TIMInfo; +use tim::{Encoding, TIMInfo}; use tool_helper::Error; pub struct Logic { @@ -16,18 +16,18 @@ impl Logic { pub fn set_unadded_tim(&mut self, path: &PathBuf) -> Result<(Image, Option), Error> { let tim_info = TIMInfo::from_image(path)?; - let image = tim_info.get_slint_images(); + let image = tim_info.get_slint_images(Encoding::FullColor); self.unadded_tim = Some(tim_info); Ok(image) } - pub fn add_unadded_tim_as(&mut self, _name: &String) -> Result<(Image, Option), Error> { + pub fn add_unadded_tim_as(&mut self, _name: &String, encoding: Encoding) -> Result<(Image, Option), Error> { if let Some(unadded_tim) = &self.unadded_tim { - let image = unadded_tim.get_slint_images(); + let (image, palette) = unadded_tim.get_slint_images(encoding); self.unadded_tim = None; - Ok(image) + Ok((image, palette)) } else { diff --git a/src/Tools/tim_tool/src/logic/tim.rs b/src/Tools/tim_tool/src/logic/tim.rs index 15a1f6b0..7cdf8d3b 100644 --- a/src/Tools/tim_tool/src/logic/tim.rs +++ b/src/Tools/tim_tool/src/logic/tim.rs @@ -2,6 +2,12 @@ use std::{fs::File, path::PathBuf}; use slint::{Rgba8Pixel, SharedPixelBuffer}; use tool_helper::Error; +pub enum Encoding { + FourBit, + EightBit, + FullColor, +} + pub struct TIMInfo { image_data: SharedPixelBuffer, palette: Option, @@ -86,8 +92,28 @@ impl TIMInfo { } } - pub fn get_slint_images(&self) -> (slint::Image, Option) { - (slint::Image::from_rgba8_premultiplied(self.image_data.clone()), if let Some(palette) = &self.palette { + pub fn get_slint_images(&self, encoding: Encoding) -> (slint::Image, Option) { + fn scaled_copy(src: &SharedPixelBuffer, factor: u32) -> SharedPixelBuffer { + let mut image_data = SharedPixelBuffer::::new(src.width()/factor, src.height()); + let mut dst_pixel = image_data.make_mut_slice(); + let src_pixel = src.as_slice(); + + for (idx, pixel) in src_pixel.into_iter().enumerate() { + if idx%factor as usize == 0 { + dst_pixel[0] = *pixel; + dst_pixel = &mut dst_pixel[1..]; + } + } + image_data + } + + let image_data = match encoding { + Encoding::FourBit => scaled_copy(&self.image_data, 4), + Encoding::EightBit => scaled_copy(&self.image_data, 2), + Encoding::FullColor => self.image_data.clone() + }; + + (slint::Image::from_rgba8_premultiplied(image_data), if let Some(palette) = &self.palette { Some(palette.get_image()) } else { None diff --git a/src/Tools/tim_tool/src/main.rs b/src/Tools/tim_tool/src/main.rs index 51155b7b..da21920a 100644 --- a/src/Tools/tim_tool/src/main.rs +++ b/src/Tools/tim_tool/src/main.rs @@ -84,7 +84,8 @@ fn setup_file_tab(gui_elements_ref: Rc>, logic_ref: Rc file_tab.conv-palette_width; in-out property file_tab-palette_height <=> file_tab.conv-palette_height; in-out property file_tab-palette_visible <=> file_tab.conv-palette_enable; + in-out property file_tab-selected_encoding <=> file_tab.conv-selected_encoding; in-out property file_tab-image_name <=> file_tab.conv-image_name; in-out property file_tab-enable <=> file_tab.conv-enable_view; callback file_tab-update_palette_size <=> file_tab.conv-image_update_palette_size; diff --git a/src/Tools/tim_tool/ui/tab/file-tab.slint b/src/Tools/tim_tool/ui/tab/file-tab.slint index f7a5c20c..2c2c7442 100644 --- a/src/Tools/tim_tool/ui/tab/file-tab.slint +++ b/src/Tools/tim_tool/ui/tab/file-tab.slint @@ -19,10 +19,11 @@ component ConvertImageWidget inherits Rectangle { in-out property image-width; in-out property image-height; in-out property palette_data; - in-out property palette_width: 0; - in-out property palette_height: 0; - in-out property enable_view: false; - in-out property palette_visible: false; + in-out property palette_width: 0; + in-out property palette_height: 0; + in-out property selected_encoding; + in-out property enable_view: false; + in-out property palette_visible: false; callback browse_clicked(); callback add_clicked(); @@ -92,8 +93,13 @@ component ConvertImageWidget inherits Rectangle { VerticalLayout { alignment: center; ComboBox { - model: root.encoding_options; - enabled: root.enable_view; + model: root.encoding_options; + enabled: root.enable_view; + current-value: root.encoding_options[0]; + + selected(current-value) => { + root.selected_encoding = current-value; + } } } } @@ -205,6 +211,7 @@ export component FileTab inherits Rectangle { in-out property conv-palette_data; in-out property conv-palette_width; in-out property conv-palette_height; + in-out property conv-selected_encoding; in-out property conv-palette_enable; in-out property conv-enable_view; @@ -244,17 +251,18 @@ export component FileTab inherits Rectangle { } if root.state == State.ConvertImage : ConvertImageWidget { - encoding_options <=> root.conv-encoding_options; - image_path <=> root.conv-image_path; - image_data <=> root.conv-image_data; - image-width <=> root.conv-image_width; - image-height <=> root.conv-image_height; - palette_data <=> root.conv-palette_data; - palette_width <=> root.conv-palette_width; - palette_height <=> root.conv-palette_height; - palette_visible <=> root.conv-palette_enable; - image_name <=> root.conv-image_name; - enable_view <=> root.conv-enable_view; + encoding_options <=> root.conv-encoding_options; + image_path <=> root.conv-image_path; + image_data <=> root.conv-image_data; + image-width <=> root.conv-image_width; + image-height <=> root.conv-image_height; + palette_data <=> root.conv-palette_data; + palette_width <=> root.conv-palette_width; + palette_height <=> root.conv-palette_height; + palette_visible <=> root.conv-palette_enable; + selected_encoding <=> root.conv-selected_encoding; + image_name <=> root.conv-image_name; + enable_view <=> root.conv-enable_view; update_palette_size(width, height) => { root.conv-image_update_palette_size(width, height); From 72b97ad7d3d2c7c9842a96d5adbfffd834f8cdb4 Mon Sep 17 00:00:00 2001 From: Jaby Date: Thu, 6 Mar 2025 22:02:30 +0100 Subject: [PATCH 4/5] Fix default selection --- src/Tools/tim_tool/src/gui/file_tab.rs | 18 ++++++++++++------ src/Tools/tim_tool/ui/tab/file-tab.slint | 5 ++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Tools/tim_tool/src/gui/file_tab.rs b/src/Tools/tim_tool/src/gui/file_tab.rs index df6461da..9c7635f9 100644 --- a/src/Tools/tim_tool/src/gui/file_tab.rs +++ b/src/Tools/tim_tool/src/gui/file_tab.rs @@ -15,12 +15,13 @@ impl FileTab { const EIGHT_BIT_NAME:&str = "8 bit"; const FULL_COLOR_NAME:&str = "Full color"; - fn update_encoding_options(&self, width: u32, height: u32, has_palette: bool) -> Result<(), Error> { + fn update_encoding_options(&self, width: u32, height: u32, has_palette: bool) -> Result<&str, Error> { self.encoding_options.clear(); if has_palette { - let has_4bit = width%4 == 0; - let has_8bit = width%2 == 0; + let mut selected_str = Self::EIGHT_BIT_NAME; + let has_4bit = width%4 == 0; + let has_8bit = width%2 == 0; if !has_4bit && !has_8bit { return Err(Error::from_text(format!("Image width must be multiple of 2 and or 4 ({}/{})", width, height))); @@ -28,17 +29,18 @@ impl FileTab { if has_4bit { self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::FOUR_BIT_NAME, width/4, height))); + selected_str = Self::FOUR_BIT_NAME; } if has_8bit { self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::EIGHT_BIT_NAME, width/2, height))); } - Ok(()) + Ok(selected_str) } else { self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::FULL_COLOR_NAME, width, height))); - Ok(()) + Ok(Self::FULL_COLOR_NAME) } } @@ -55,7 +57,11 @@ impl FileTab { self.encoding_options.clear(); main_window.set_file_tab_browse_path("".into()); main_window.set_file_tab_image_data(Image::default()); + main_window.set_file_tab_image_width(0); + main_window.set_file_tab_image_height(0); main_window.set_file_tab_palette_data(Image::default()); + main_window.set_file_tab_palette_width(0); + main_window.set_file_tab_palette_height(0); main_window.set_file_tab_image_name("".into()); main_window.set_file_tab_enable(false); } @@ -79,7 +85,7 @@ impl FileTab { main_window.set_file_tab_image_name("".into()); } - self.update_encoding_options(image_size.width, image_size.height, has_palette)?; + main_window.set_file_tab_selected_encoding(SharedString::from(self.update_encoding_options(image_size.width, image_size.height, has_palette)?)); main_window.set_file_tab_enable(true); Ok(()) } diff --git a/src/Tools/tim_tool/ui/tab/file-tab.slint b/src/Tools/tim_tool/ui/tab/file-tab.slint index 2c2c7442..a9a9e078 100644 --- a/src/Tools/tim_tool/ui/tab/file-tab.slint +++ b/src/Tools/tim_tool/ui/tab/file-tab.slint @@ -93,9 +93,8 @@ component ConvertImageWidget inherits Rectangle { VerticalLayout { alignment: center; ComboBox { - model: root.encoding_options; - enabled: root.enable_view; - current-value: root.encoding_options[0]; + model: root.encoding_options; + enabled: root.enable_view; selected(current-value) => { root.selected_encoding = current-value; From 62289bc07e205429730a3aecc48f6d9127e76f89 Mon Sep 17 00:00:00 2001 From: Jaby Date: Thu, 6 Mar 2025 22:21:56 +0100 Subject: [PATCH 5/5] Display encoding on main screen --- src/Tools/tim_tool/src/gui/file_tab.rs | 22 ++++++++------------ src/Tools/tim_tool/src/gui/main_tab.rs | 15 ++++++++------ src/Tools/tim_tool/src/logic/tim.rs | 15 ++++++++++++++ src/Tools/tim_tool/src/main.rs | 2 +- src/Tools/tim_tool/ui/tab/main-tab.slint | 26 ++++++++++++++---------- 5 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/Tools/tim_tool/src/gui/file_tab.rs b/src/Tools/tim_tool/src/gui/file_tab.rs index 9c7635f9..d076e654 100644 --- a/src/Tools/tim_tool/src/gui/file_tab.rs +++ b/src/Tools/tim_tool/src/gui/file_tab.rs @@ -11,15 +11,11 @@ pub struct FileTab { } impl FileTab { - const FOUR_BIT_NAME:&str = "4 bit"; - const EIGHT_BIT_NAME:&str = "8 bit"; - const FULL_COLOR_NAME:&str = "Full color"; - fn update_encoding_options(&self, width: u32, height: u32, has_palette: bool) -> Result<&str, Error> { self.encoding_options.clear(); if has_palette { - let mut selected_str = Self::EIGHT_BIT_NAME; + let mut selected_str = Encoding::EightBit.to_str(); let has_4bit = width%4 == 0; let has_8bit = width%2 == 0; @@ -28,19 +24,19 @@ impl FileTab { } if has_4bit { - self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::FOUR_BIT_NAME, width/4, height))); - selected_str = Self::FOUR_BIT_NAME; + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Encoding::FourBit.to_str(), width/4, height))); + selected_str = Encoding::FourBit.to_str(); } if has_8bit { - self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::EIGHT_BIT_NAME, width/2, height))); + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Encoding::EightBit.to_str(), width/2, height))); } Ok(selected_str) } else { - self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Self::FULL_COLOR_NAME, width, height))); - Ok(Self::FULL_COLOR_NAME) + self.encoding_options.push(SharedString::from(format!("{} ({}/{})", Encoding::FullColor.to_str(), width, height))); + Ok(Encoding::FullColor.to_str()) } } @@ -116,15 +112,15 @@ impl FileTab { pub fn get_encoding(&self) -> Result { let selected_encoding = self.main_window.borrow().get_file_tab_selected_encoding(); - if selected_encoding.starts_with(Self::FOUR_BIT_NAME) { + if selected_encoding.starts_with(Encoding::FourBit.to_str()) { Ok(Encoding::FourBit) } - else if selected_encoding.starts_with(Self::EIGHT_BIT_NAME) { + else if selected_encoding.starts_with(Encoding::EightBit.to_str()) { Ok(Encoding::EightBit) } - else if selected_encoding.starts_with(Self::FULL_COLOR_NAME) { + else if selected_encoding.starts_with(Encoding::FullColor.to_str()) { Ok(Encoding::FullColor) } diff --git a/src/Tools/tim_tool/src/gui/main_tab.rs b/src/Tools/tim_tool/src/gui/main_tab.rs index 84db3017..4e2b5c32 100644 --- a/src/Tools/tim_tool/src/gui/main_tab.rs +++ b/src/Tools/tim_tool/src/gui/main_tab.rs @@ -1,7 +1,8 @@ use crate::{gui::{VRAM_HEIGHT, VRAM_WIDTH}, MainWindow, VRAMImage}; use super::{GUIElementsRef, MainWindowRef}; -use slint::Model; +use slint::{Model, SharedString}; +use tim_tool::logic::tim::Encoding; use std::{rc::Rc, sync::{Arc, Mutex}}; struct VRAM { @@ -26,13 +27,15 @@ impl MainTab { MainTab{main_window, vram: Arc::new(Mutex::new(VRAM{file_list: vram_file_list, image_list: vram_image_list}))} } - pub fn add_new_vram_file(&mut self, file_name: &String, image: slint::Image, image_palette: Option) { + pub fn add_new_vram_file(&mut self, file_name: &String, image: slint::Image, encoding: Encoding, image_palette: Option) { let vram_data = self.vram.lock().expect("VRAM already locked"); - let add_new_image = |file_name: &String, image: slint::Image, palette_count: i32, is_palette: bool| { - let vram_image = VRAMImage{ + let add_new_image = |file_name: &String, image: slint::Image, encoding: Encoding, palette_count: i32, is_palette: bool| { + let encoding_str = if is_palette {""} else {encoding.to_str()}; + let vram_image = VRAMImage{ img: image, x: 0, y: 0, + encoding_str: SharedString::from(encoding_str), palette_count, is_palette, }; @@ -41,10 +44,10 @@ impl MainTab { vram_data.image_list.push(vram_image); }; - add_new_image(file_name, image, if image_palette.is_some() {1} else {0}, false); + add_new_image(file_name, image, encoding, if image_palette.is_some() {1} else {0}, false); if let Some(image_palette) = image_palette { let file_name = " => ".to_owned() + file_name.as_str() + " (Palette)"; - add_new_image(&file_name, image_palette, 0, true); + add_new_image(&file_name, image_palette, encoding, 0, true); } } diff --git a/src/Tools/tim_tool/src/logic/tim.rs b/src/Tools/tim_tool/src/logic/tim.rs index 7cdf8d3b..6f176afc 100644 --- a/src/Tools/tim_tool/src/logic/tim.rs +++ b/src/Tools/tim_tool/src/logic/tim.rs @@ -2,12 +2,27 @@ use std::{fs::File, path::PathBuf}; use slint::{Rgba8Pixel, SharedPixelBuffer}; use tool_helper::Error; +#[derive(Clone, Copy)] pub enum Encoding { FourBit, EightBit, FullColor, } +impl Encoding { + const FOUR_BIT_NAME:&str = "4 bit"; + const EIGHT_BIT_NAME:&str = "8 bit"; + const FULL_COLOR_NAME:&str = "Full color"; + + pub const fn to_str(&self) -> &str { + match self { + Encoding::FourBit => Self::FOUR_BIT_NAME, + Encoding::EightBit => Self::EIGHT_BIT_NAME, + Encoding::FullColor => Self::FULL_COLOR_NAME, + } + } +} + pub struct TIMInfo { image_data: SharedPixelBuffer, palette: Option, diff --git a/src/Tools/tim_tool/src/main.rs b/src/Tools/tim_tool/src/main.rs index da21920a..496e4767 100644 --- a/src/Tools/tim_tool/src/main.rs +++ b/src/Tools/tim_tool/src/main.rs @@ -87,7 +87,7 @@ fn setup_file_tab(gui_elements_ref: Rc>, logic_ref: Rc { - cur_sel_x.text = root.vram_images[current-item].x; - cur_sel_y.text = root.vram_images[current-item].y; - cur_sel_img.source = root.vram_images[current-item].img; - cur_sel_img.visible = true; + cur_sel_x.text = root.vram_images[current-item].x; + cur_sel_y.text = root.vram_images[current-item].y; + cur_sel_img.source = root.vram_images[current-item].img; + encoding_text.encoding_str = root.vram_images[current-item].encoding_str; + cur_sel_img.visible = true; } } HorizontalLayout { @@ -232,9 +236,9 @@ export component MainTab inherits Rectangle { } } } - ComboBox { - model: ["4-bit", "16-bit", "24-bit"]; - current-value: "4-bit"; + encoding_text := Text { + in-out property encoding_str; + text: "Encoding: " + encoding_str; } } }