From 73ccc4054a57f247783f953400b70b0772777ae2 Mon Sep 17 00:00:00 2001 From: Simon Gellis Date: Sat, 6 Sep 2025 22:15:56 -0400 Subject: [PATCH] Pass window to file picker --- src/app.rs | 12 +++++++++--- src/window.rs | 15 +++++++++++---- src/window/game.rs | 22 ++++++++++++++++------ src/window/profile.rs | 20 +++++++++++++++----- src/window/vip/bgmap.rs | 6 +++--- src/window/vip/chardata.rs | 6 +++--- src/window/vip/framebuffer.rs | 6 +++--- src/window/vip/object.rs | 6 +++--- src/window/vip/world.rs | 6 +++--- 9 files changed, 66 insertions(+), 33 deletions(-) diff --git a/src/app.rs b/src/app.rs index 0ad3ee1..a6ff2cb 100644 --- a/src/app.rs +++ b/src/app.rs @@ -24,8 +24,8 @@ use crate::{ persistence::Persistence, window::{ AboutWindow, AppWindow, BgMapWindow, CharacterDataWindow, FrameBufferWindow, GameWindow, - GdbServerWindow, HotkeysWindow, InputWindow, ObjectWindow, ProfileWindow, RegisterWindow, - TerminalWindow, WorldWindow, + GdbServerWindow, HotkeysWindow, InitArgs, InputWindow, ObjectWindow, ProfileWindow, + RegisterWindow, TerminalWindow, WorldWindow, }, }; @@ -423,7 +423,13 @@ impl Viewport { let (window, state) = create_window_and_state(&ctx, event_loop, &builder, &mut painter); egui_winit::update_viewport_info(&mut info, &ctx, &window, true); - app.on_init(&ctx, painter.render_state().as_ref().unwrap()); + let render_state = painter.render_state(); + let args = InitArgs { + ctx: &ctx, + window: &window, + render_state: render_state.as_ref().unwrap(), + }; + app.on_init(args); Self { painter, ctx, diff --git a/src/window.rs b/src/window.rs index 237f262..36012e1 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + pub use about::AboutWindow; use egui::{Context, ViewportBuilder, ViewportId}; pub use game::GameWindow; @@ -9,7 +11,7 @@ pub use terminal::TerminalWindow; pub use vip::{ BgMapWindow, CharacterDataWindow, FrameBufferWindow, ObjectWindow, RegisterWindow, WorldWindow, }; -use winit::event::KeyEvent; +use winit::{event::KeyEvent, window::Window}; use crate::emulator::SimId; @@ -31,9 +33,8 @@ pub trait AppWindow { } fn initial_viewport(&self) -> ViewportBuilder; fn show(&mut self, ctx: &Context); - fn on_init(&mut self, ctx: &Context, render_state: &egui_wgpu::RenderState) { - let _ = ctx; - let _ = render_state; + fn on_init(&mut self, args: InitArgs) { + let _ = args; } fn on_destroy(&mut self) {} fn handle_key_event(&mut self, event: &KeyEvent) -> bool { @@ -45,3 +46,9 @@ pub trait AppWindow { false } } + +pub struct InitArgs<'a> { + pub ctx: &'a Context, + pub window: &'a Arc, + pub render_state: &'a egui_wgpu::RenderState, +} diff --git a/src/window/game.rs b/src/window/game.rs index 76407c5..0addf83 100644 --- a/src/window/game.rs +++ b/src/window/game.rs @@ -1,10 +1,14 @@ -use std::{sync::mpsc, time::Duration}; +use std::{ + sync::{Arc, mpsc}, + time::Duration, +}; use crate::{ app::UserEvent, emulator::{EmulatorClient, EmulatorCommand, EmulatorState, SimId, SimState}, input::{Command, ShortcutProvider}, persistence::Persistence, + window::InitArgs, }; use anyhow::Context as _; use egui::{ @@ -47,6 +51,7 @@ pub struct GameWindow { screen: Option, messages: Option>, color_picker: Option, + window: Option>, } impl GameWindow { @@ -73,6 +78,7 @@ impl GameWindow { screen: None, messages: None, color_picker: None, + window: None, } } @@ -300,10 +306,13 @@ impl GameWindow { self.client .send_command(EmulatorCommand::Screenshot(self.sim_id, tx)); let bytes = rx.await.context("Could not take screenshot")?; - let file = rfd::FileDialog::new() + let mut file_dialog = rfd::FileDialog::new() .add_filter("PNG images", &["png"]) - .set_file_name("screenshot.png") - .save_file(); + .set_file_name("screenshot.png"); + if let Some(window) = self.window.as_ref() { + file_dialog = file_dialog.set_parent(window); + } + let file = file_dialog.save_file(); let Some(path) = file else { return Ok(None); }; @@ -547,8 +556,8 @@ impl AppWindow for GameWindow { self.toasts.show(ctx); } - fn on_init(&mut self, _ctx: &Context, render_state: &egui_wgpu::RenderState) { - let (screen, sink) = GameScreen::init(render_state); + fn on_init(&mut self, args: InitArgs) { + let (screen, sink) = GameScreen::init(args.render_state); let (message_sink, message_source) = mpsc::channel(); self.client.send_command(EmulatorCommand::ConnectToSim( self.sim_id, @@ -557,6 +566,7 @@ impl AppWindow for GameWindow { )); self.screen = Some(screen); self.messages = Some(message_source); + self.window = Some(args.window.clone()); } fn on_destroy(&mut self) { diff --git a/src/window/profile.rs b/src/window/profile.rs index e5ffb00..5b1c0d5 100644 --- a/src/window/profile.rs +++ b/src/window/profile.rs @@ -1,13 +1,14 @@ -use std::{fs, time::Duration}; +use std::{fs, sync::Arc, time::Duration}; use anyhow::Result; use egui::{Button, CentralPanel, Checkbox, Label, ViewportBuilder, ViewportId}; use egui_notify::{Anchor, Toast, Toasts}; +use winit::window::Window; use crate::{ emulator::{EmulatorClient, EmulatorCommand, EmulatorState, SimId}, profiler::{Profiler, ProfilerStatus}, - window::AppWindow, + window::{AppWindow, InitArgs}, }; pub struct ProfileWindow { @@ -15,6 +16,7 @@ pub struct ProfileWindow { client: EmulatorClient, profiler: Profiler, toasts: Toasts, + window: Option>, } impl ProfileWindow { @@ -27,6 +29,7 @@ impl ProfileWindow { .with_anchor(Anchor::BottomLeft) .with_margin((10.0, 10.0).into()) .reverse(true), + window: None, } } @@ -59,10 +62,13 @@ impl ProfileWindow { fn try_finish_recording(&mut self) -> Result> { let bytes_receiver = self.profiler.finish_recording(); - let file = rfd::FileDialog::new() + let mut file_dialog = rfd::FileDialog::new() .add_filter("Profiler files", &["json"]) - .set_file_name("profile.json") - .save_file(); + .set_file_name("profile.json"); + if let Some(window) = self.window.as_ref() { + file_dialog = file_dialog.set_parent(window); + } + let file = file_dialog.save_file(); if let Some(path) = file { let bytes = pollster::block_on(bytes_receiver)?; let _ = fs::remove_file(&path); @@ -160,4 +166,8 @@ impl AppWindow for ProfileWindow { }); self.toasts.show(ctx); } + + fn on_init(&mut self, args: InitArgs) { + self.window = Some(args.window.clone()); + } } diff --git a/src/window/vip/bgmap.rs b/src/window/vip/bgmap.rs index 6d1c71d..de2d856 100644 --- a/src/window/vip/bgmap.rs +++ b/src/window/vip/bgmap.rs @@ -11,7 +11,7 @@ use crate::{ images::{ImageBuffer, ImageParams, ImageProcessor, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryView}, window::{ - AppWindow, + AppWindow, InitArgs, utils::{NumberEdit, UiExt}, }, }; @@ -187,8 +187,8 @@ impl AppWindow for BgMapWindow { .with_inner_size((640.0, 480.0)) } - fn on_init(&mut self, ctx: &Context, _render_state: &egui_wgpu::RenderState) { - ctx.add_texture_loader(self.loader.clone()); + fn on_init(&mut self, args: InitArgs) { + args.ctx.add_texture_loader(self.loader.clone()); } fn show(&mut self, ctx: &Context) { diff --git a/src/window/vip/chardata.rs b/src/window/vip/chardata.rs index 46b5019..334b487 100644 --- a/src/window/vip/chardata.rs +++ b/src/window/vip/chardata.rs @@ -12,7 +12,7 @@ use crate::{ images::{ImageBuffer, ImageParams, ImageProcessor, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryView}, window::{ - AppWindow, + AppWindow, InitArgs, utils::{NumberEdit, UiExt as _}, }, }; @@ -251,8 +251,8 @@ impl AppWindow for CharacterDataWindow { .with_inner_size((640.0, 480.0)) } - fn on_init(&mut self, ctx: &Context, _render_state: &egui_wgpu::RenderState) { - ctx.add_texture_loader(self.loader.clone()); + fn on_init(&mut self, args: InitArgs) { + args.ctx.add_texture_loader(self.loader.clone()); } fn show(&mut self, ctx: &Context) { diff --git a/src/window/vip/framebuffer.rs b/src/window/vip/framebuffer.rs index e453eb4..a079d7b 100644 --- a/src/window/vip/framebuffer.rs +++ b/src/window/vip/framebuffer.rs @@ -11,7 +11,7 @@ use crate::{ images::{ImageBuffer, ImageParams, ImageProcessor, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryView}, window::{ - AppWindow, + AppWindow, InitArgs, utils::{NumberEdit, UiExt as _}, }, }; @@ -153,8 +153,8 @@ impl AppWindow for FrameBufferWindow { .with_inner_size((640.0, 480.0)) } - fn on_init(&mut self, ctx: &Context, _render_state: &egui_wgpu::RenderState) { - ctx.add_texture_loader(self.loader.clone()); + fn on_init(&mut self, args: InitArgs) { + args.ctx.add_texture_loader(self.loader.clone()); } fn show(&mut self, ctx: &Context) { diff --git a/src/window/vip/object.rs b/src/window/vip/object.rs index 190cfea..4ecfb48 100644 --- a/src/window/vip/object.rs +++ b/src/window/vip/object.rs @@ -11,7 +11,7 @@ use crate::{ images::{ImageBuffer, ImageParams, ImageProcessor, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryView}, window::{ - AppWindow, + AppWindow, InitArgs, utils::{NumberEdit, UiExt as _}, }, }; @@ -208,8 +208,8 @@ impl AppWindow for ObjectWindow { .with_inner_size((640.0, 500.0)) } - fn on_init(&mut self, ctx: &Context, _render_state: &egui_wgpu::RenderState) { - ctx.add_texture_loader(self.loader.clone()); + fn on_init(&mut self, args: InitArgs) { + args.ctx.add_texture_loader(self.loader.clone()); } fn show(&mut self, ctx: &Context) { diff --git a/src/window/vip/world.rs b/src/window/vip/world.rs index a5a4f4b..c97e49f 100644 --- a/src/window/vip/world.rs +++ b/src/window/vip/world.rs @@ -17,7 +17,7 @@ use crate::{ images::{ImageBuffer, ImageParams, ImageProcessor, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryRef, MemoryView}, window::{ - AppWindow, + AppWindow, InitArgs, utils::{NumberEdit, UiExt as _}, }, }; @@ -523,8 +523,8 @@ impl AppWindow for WorldWindow { .with_inner_size((640.0, 520.0)) } - fn on_init(&mut self, ctx: &Context, _render_state: &egui_wgpu::RenderState) { - ctx.add_texture_loader(self.loader.clone()); + fn on_init(&mut self, args: InitArgs) { + args.ctx.add_texture_loader(self.loader.clone()); } fn show(&mut self, ctx: &Context) {