diff --git a/Cargo.lock b/Cargo.lock index 793d401..9a2db48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -494,6 +500,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.9.0" @@ -788,6 +800,15 @@ dependencies = [ "windows 0.54.0", ] +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -1071,6 +1092,25 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1535,6 +1575,18 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "image" +version = "0.25.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", + "png", +] + [[package]] name = "indexmap" version = "2.7.0" @@ -1663,6 +1715,7 @@ dependencies = [ "egui-winit", "egui_extras", "gilrs", + "image", "itertools", "num-derive", "num-traits", @@ -1827,6 +1880,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "naga" version = "22.1.0" @@ -2354,6 +2417,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "png" +version = "0.17.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67582bd5b65bdff614270e2ea89a1cf15bef71245cc1e5f7ea126977144211d" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "polling" version = "3.7.4" @@ -2711,6 +2787,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "slab" version = "0.4.9" diff --git a/Cargo.toml b/Cargo.toml index 71e98b2..7189cb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ egui_extras = "0.29" egui-winit = "0.29" egui-wgpu = { version = "0.29", features = ["winit"] } gilrs = "0.11" +image = { version = "0.25", default-features = false, features = ["png"] } itertools = "0.13" num-derive = "0.4" num-traits = "0.2" diff --git a/assets/lemur-256x256.png b/assets/lemur-256x256.png new file mode 100644 index 0000000..d0d12ff Binary files /dev/null and b/assets/lemur-256x256.png differ diff --git a/src/app.rs b/src/app.rs index 052cf32..8f04ce1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,8 +2,8 @@ use std::{collections::HashSet, num::NonZero, sync::Arc, thread, time::Duration} use egui::{ ahash::{HashMap, HashMapExt}, - Context, FontData, FontDefinitions, FontFamily, TextWrapMode, ViewportBuilder, ViewportCommand, - ViewportId, ViewportInfo, + Context, FontData, FontDefinitions, FontFamily, IconData, TextWrapMode, ViewportBuilder, + ViewportCommand, ViewportId, ViewportInfo, }; use gilrs::{EventType, Gilrs}; use winit::{ @@ -20,7 +20,19 @@ use crate::{ window::{AppWindow, GameWindow, InputWindow}, }; +fn load_icon() -> anyhow::Result { + let bytes = include_bytes!("../assets/lemur-256x256.png"); + let img = image::load_from_memory_with_format(bytes, image::ImageFormat::Png)?; + let rgba = img.into_rgba8(); + Ok(IconData { + width: rgba.width(), + height: rgba.height(), + rgba: rgba.into_vec(), + }) +} + pub struct Application { + icon: Option>, client: EmulatorClient, proxy: EventLoopProxy, mappings: MappingProvider, @@ -31,6 +43,7 @@ pub struct Application { impl Application { pub fn new(client: EmulatorClient, proxy: EventLoopProxy) -> Self { + let icon = load_icon().ok().map(Arc::new); let mappings = MappingProvider::new(); let controllers = ControllerManager::new(client.clone(), &mappings); { @@ -39,6 +52,7 @@ impl Application { thread::spawn(|| process_gamepad_input(mappings, proxy)); } Self { + icon, client, proxy, mappings, @@ -53,15 +67,17 @@ impl Application { if self.viewports.contains_key(&viewport_id) { return; } - self.viewports - .insert(viewport_id, Viewport::new(event_loop, window)); + self.viewports.insert( + viewport_id, + Viewport::new(event_loop, self.icon.clone(), window), + ); } } impl ApplicationHandler for Application { fn resumed(&mut self, event_loop: &ActiveEventLoop) { let app = GameWindow::new(self.client.clone(), self.proxy.clone(), SimId::Player1); - let wrapper = Viewport::new(event_loop, Box::new(app)); + let wrapper = Viewport::new(event_loop, self.icon.clone(), Box::new(app)); self.focused = Some(wrapper.id()); self.viewports.insert(wrapper.id(), wrapper); } @@ -192,7 +208,11 @@ struct Viewport { app: Box, } impl Viewport { - pub fn new(event_loop: &ActiveEventLoop, mut app: Box) -> Self { + pub fn new( + event_loop: &ActiveEventLoop, + icon: Option>, + mut app: Box, + ) -> Self { let mut painter = egui_wgpu::winit::Painter::new( egui_wgpu::WgpuConfiguration { present_mode: wgpu::PresentMode::AutoNoVsync, @@ -222,7 +242,10 @@ impl Viewport { }); let mut info = ViewportInfo::default(); - let builder = app.initial_viewport(); + let mut builder = app.initial_viewport(); + if let Some(icon) = icon { + builder = builder.with_icon(icon); + } let (window, state) = create_window_and_state(&ctx, event_loop, &builder, &mut painter); egui_winit::update_viewport_info(&mut info, &ctx, &window, true);