From 00d439bc0217289da8ff62dbf608072a6c7fd93a Mon Sep 17 00:00:00 2001 From: RobDavenport Date: Wed, 24 Apr 2024 00:53:53 +0900 Subject: [PATCH] image loading --- gamercade_app/src/app.rs | 19 ++++++-- .../src/local_directory/image_cache.rs | 41 ++++++++++++++--- gamercade_app/src/local_directory/mod.rs | 45 +++++++++---------- gamercade_app/src/main.rs | 3 +- 4 files changed, 74 insertions(+), 34 deletions(-) diff --git a/gamercade_app/src/app.rs b/gamercade_app/src/app.rs index edb4ff2..888c7dc 100644 --- a/gamercade_app/src/app.rs +++ b/gamercade_app/src/app.rs @@ -1,16 +1,15 @@ -use eframe::egui::{self, Ui}; +use eframe::egui::{self, Context, Ui}; use gamercade_interface::{platform::FrontPageRequest, CRC}; use crate::{ local_directory::LocalDirectory, modes::{AppMode, ArcadeModeView, LibraryModeView, SettingsModeView}, task_manager::{ - AuthState, GameResponse, HttpResponse, PlatformRequest, PlatformResponse, SuperTaskManager, - TaskNotification, + AuthState, AuthorRequest, GameResponse, HttpResponse, PlatformRequest, PlatformResponse, + SuperTaskManager, TagRequest, TaskNotification, }, }; -#[derive(Default)] pub struct App { directory: LocalDirectory, @@ -67,6 +66,16 @@ impl eframe::App for App { } impl App { + pub fn new(ctx: &Context) -> Self { + Self { + directory: LocalDirectory::new(ctx), + tasks: Default::default(), + auth_state: Default::default(), + active_mode: Default::default(), + modes: Default::default(), + } + } + fn handle_notifications(&mut self) { while let Ok(notification) = self.tasks.events.try_recv() { match notification { @@ -94,6 +103,8 @@ impl App { self.tasks .platform .send(PlatformRequest::EditableGames(session.clone())); + self.tasks.tags.send(TagRequest::Initialize); + self.tasks.author.send(AuthorRequest::Initialize); } } } diff --git a/gamercade_app/src/local_directory/image_cache.rs b/gamercade_app/src/local_directory/image_cache.rs index b28a69e..cb829f0 100644 --- a/gamercade_app/src/local_directory/image_cache.rs +++ b/gamercade_app/src/local_directory/image_cache.rs @@ -1,4 +1,7 @@ -use eframe::egui::{self, ImageSource, TextureHandle}; +use std::fs; + +use eframe::egui::{self, ColorImage, Context, ImageSource, TextureHandle, TextureOptions}; +use image::GenericImageView; use nohash_hasher::IntMap; use crate::GAME_DIR; @@ -12,17 +15,43 @@ impl ImageCache { &egui::include_image!("../../default-logo.png") } - pub fn new() -> Self { - std::fs::create_dir(GAME_DIR).unwrap(); - let dir = std::fs::read_dir(GAME_DIR).unwrap(); + pub fn new(ctx: &Context) -> Self { + // Create the dir if it doesn't exist + match fs::metadata(GAME_DIR).map(|meta| meta.is_dir()) { + Ok(true) => (), + _ => fs::create_dir(GAME_DIR).unwrap(), + } + let dir = fs::read_dir(GAME_DIR).unwrap(); let mut games = IntMap::default(); + // Parses all of the images on disk into memory/gpu for file in dir.into_iter() { if let Ok(path) = file.map(|file| file.path()) { if let Some(extension) = path.extension() { - if extension == "png" { - // TODO: Load the image and push it into the map + let game_id = path.file_name().and_then(|filename| { + filename + .to_str() + .and_then(|filename| filename.parse::().ok()) + }); + + if extension == "png" && game_id.is_some() { + if let Ok(bytes) = fs::read(path.clone()) { + if let Ok(image) = image::load_from_memory(&bytes) { + let dimensions = + [image.dimensions().0 as usize, image.dimensions().1 as usize]; + + let handle = ctx.load_texture( + path.to_str().unwrap(), + ColorImage::from_rgba_unmultiplied( + dimensions, + image.as_bytes(), + ), + TextureOptions::default(), + ); + games.insert(game_id.unwrap(), handle); + } + } } } } diff --git a/gamercade_app/src/local_directory/mod.rs b/gamercade_app/src/local_directory/mod.rs index 3e2c198..15102e8 100644 --- a/gamercade_app/src/local_directory/mod.rs +++ b/gamercade_app/src/local_directory/mod.rs @@ -1,5 +1,6 @@ use std::hash::{BuildHasher, BuildHasherDefault, Hash}; +use eframe::egui::Context; use nohash_hasher::{IntMap, NoHashHasher}; use rusqlite::{types::FromSql, Connection, Row, Statement}; @@ -42,6 +43,27 @@ pub struct Dictionary { } impl LocalDirectory { + pub fn new(ctx: &Context) -> Self { + let db = Connection::open(LOCAL_DB_PATH).unwrap(); + + let mut output = Self { + tags: TagDictionary::new(&db), + users: UserDictionary::new(&db), + permission_levels: PermissionLevelDictionary::new(&db), + game_footprint: GameFootprintDictionary::new(&db), + db, + cached_games: Vec::new(), + cache_dirty: true, + images: ImageCache::new(ctx), + }; + + upsert_games_table(&output.db); + + output.sync_games_cache(); + + output + } + pub fn upsert_tags(&mut self, tags: &[(TagId, Tag)], clear_db: bool) { if clear_db { self.db @@ -156,26 +178,3 @@ impl IsDictionary for Dictionary { &self.map } } - -impl Default for LocalDirectory { - fn default() -> Self { - let db = Connection::open(LOCAL_DB_PATH).unwrap(); - - let mut output = Self { - tags: TagDictionary::new(&db), - users: UserDictionary::new(&db), - permission_levels: PermissionLevelDictionary::new(&db), - game_footprint: GameFootprintDictionary::new(&db), - db, - cached_games: Vec::new(), - cache_dirty: true, - images: ImageCache::new(), - }; - - upsert_games_table(&output.db); - - output.sync_games_cache(); - - output - } -} diff --git a/gamercade_app/src/main.rs b/gamercade_app/src/main.rs index c7994c3..e285be8 100644 --- a/gamercade_app/src/main.rs +++ b/gamercade_app/src/main.rs @@ -31,7 +31,8 @@ async fn main() -> Result<(), eframe::Error> { options, Box::new(|cc| { egui_extras::install_image_loaders(&cc.egui_ctx); - Box::::default() + + Box::new(app::App::new(&cc.egui_ctx)) }), ) }