From 218d7860421eb4cfc4d7b833132f4c476935777a Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 27 Jun 2024 21:11:57 -0700 Subject: [PATCH] fix: fix scroll issues --- tetanes/src/nes/action.rs | 52 ++-- tetanes/src/nes/renderer/gui.rs | 6 + tetanes/src/nes/renderer/gui/keybinds.rs | 10 +- tetanes/src/nes/renderer/gui/preferences.rs | 260 ++++++++++---------- tetanes/src/platform.rs | 29 +-- 5 files changed, 186 insertions(+), 171 deletions(-) diff --git a/tetanes/src/nes/action.rs b/tetanes/src/nes/action.rs index 65351b0d..91889af0 100644 --- a/tetanes/src/nes/action.rs +++ b/tetanes/src/nes/action.rs @@ -188,11 +188,11 @@ impl AsRef for Action { Ui::LoadReplay => "Load Replay", }, Action::Menu(menu) => match menu { - Menu::About => "Toggle About Window", - Menu::Keybinds => "Toggle Keybinds Menu", - Menu::PerfStats => "Toggle Performance Stats Window", + Menu::About => "Toggle About", + Menu::Keybinds => "Toggle Keybinds", + Menu::PerfStats => "Toggle Performance Stats", Menu::PpuViewer => "Toggle PPU Viewer", - Menu::Preferences => "Toggle Preferences Menu", + Menu::Preferences => "Toggle Preferences", }, Action::Feature(feature) => match feature { Feature::ToggleReplayRecording => "Toggle Replay Recording", @@ -214,10 +214,10 @@ impl AsRef for Action { Setting::ToggleScreenReader => "Toggle Screen Reader", Setting::ToggleFps => "Toggle FPS", Setting::FastForward => "Fast Forward", - Setting::IncrementScale => "Increment Scale", - Setting::DecrementScale => "Decrement Scale", - Setting::IncrementSpeed => "Increment Speed", - Setting::DecrementSpeed => "Decrement Speed", + Setting::IncrementScale => "Scale Increment", + Setting::DecrementScale => "Scale Decrement", + Setting::IncrementSpeed => "Speed Increment", + Setting::DecrementSpeed => "Speed Increment", }, Action::Deck(deck) => match deck { DeckAction::Reset(kind) => match kind { @@ -236,13 +236,13 @@ impl AsRef for Action { JoypadBtn::Select => "Joypad Select", JoypadBtn::Start => "Joypad Start", }, - DeckAction::ToggleZapperConnected => "Toggle Zapper Connected", + DeckAction::ToggleZapperConnected => "Zapper Gun Toggle", DeckAction::ZapperAim(_) => "Zapper Aim", DeckAction::ZapperAimOffscreen => "Zapper Aim Offscreen (Hold)", DeckAction::ZapperTrigger => "Zapper Trigger", - DeckAction::FourPlayer(FourPlayer::Disabled) => "Disable Four Player Mode", - DeckAction::FourPlayer(FourPlayer::FourScore) => "Enable Four Player (FourScore)", - DeckAction::FourPlayer(FourPlayer::Satellite) => "Enable Four Player (Satellite)", + DeckAction::FourPlayer(FourPlayer::Disabled) => "4-Player Disable", + DeckAction::FourPlayer(FourPlayer::FourScore) => "4-Player Enable (FourScore)", + DeckAction::FourPlayer(FourPlayer::Satellite) => "4-Player Enable (Satellite)", DeckAction::SetSaveSlot(1) => "Set Save Slot 1", DeckAction::SetSaveSlot(2) => "Set Save Slot 2", DeckAction::SetSaveSlot(3) => "Set Save Slot 3", @@ -264,17 +264,17 @@ impl AsRef for Action { }, DeckAction::MapperRevision(rev) => match rev { MapperRevision::Mmc3(mmc3) => match mmc3 { - Mmc3Revision::A => "Set Mapper Rev. to MMC3A", - Mmc3Revision::BC => "Set Mapper Rev. to MMC3B/C", - Mmc3Revision::Acc => "Set Mapper Rev. to MC-ACC", + Mmc3Revision::A => "Set Mapper to MMC3A", + Mmc3Revision::BC => "Set Mapper to MMC3B/C", + Mmc3Revision::Acc => "Set Mapper to MC-ACC", }, MapperRevision::Bf909(bf909) => match bf909 { - Bf909Revision::Bf909x => "Set Mapper Rev. to BF909x", - Bf909Revision::Bf9097 => "Set Mapper Rev. to BF9097", + Bf909Revision::Bf909x => "Set Mapper to BF909x", + Bf909Revision::Bf9097 => "Set Mapper to BF9097", }, }, DeckAction::SetNesRegion(region) => match region { - NesRegion::Auto => "Set Region to Auto-Detect", + NesRegion::Auto => "Set Region to Auto", NesRegion::Ntsc => "Set Region to NTSC", NesRegion::Pal => "Set Region to PAL", NesRegion::Dendy => "Set Region to Dendy", @@ -286,16 +286,16 @@ impl AsRef for Action { }, Action::Debug(debug) => match debug { Debug::Toggle(debugger) => match debugger { - Debugger::Cpu => "Toggle CPU Debugger", - Debugger::Ppu => "Toggle PPU Debugger", - Debugger::Apu => "Toggle APU Debugger", + Debugger::Cpu => "Toggle Debugger", + Debugger::Ppu => "Toggle PPU Viewer", + Debugger::Apu => "Toggle APU Mixer", }, Debug::Step(step) => match step { - DebugStep::Into => "Step Into (CPU Debugger)", - DebugStep::Out => "Step Out (CPU Debugger)", - DebugStep::Over => "Step Over (CPU Debugger)", - DebugStep::Scanline => "Step Scanline (CPU Debugger)", - DebugStep::Frame => "Step Frame (CPU Debugger)", + DebugStep::Into => "Debug Step", + DebugStep::Out => "Debug Step Out", + DebugStep::Over => "Debug Step Over", + DebugStep::Scanline => "Debug Step Scanline", + DebugStep::Frame => "Debug Step Frame", }, }, } diff --git a/tetanes/src/nes/renderer/gui.rs b/tetanes/src/nes/renderer/gui.rs index a2583c0a..891793da 100644 --- a/tetanes/src/nes/renderer/gui.rs +++ b/tetanes/src/nes/renderer/gui.rs @@ -340,6 +340,12 @@ impl Gui { Self::light_theme() }; ctx.set_visuals(theme); + ctx.style_mut(|ctx| { + let scroll = &mut ctx.spacing.scroll; + scroll.floating = false; + scroll.foreground_color = false; + scroll.bar_width = 8.0; + }); const FONT: (&str, &[u8]) = ( "pixeloid-sans", diff --git a/tetanes/src/nes/renderer/gui/keybinds.rs b/tetanes/src/nes/renderer/gui/keybinds.rs index d2c0ad0d..c0e1af06 100644 --- a/tetanes/src/nes/renderer/gui/keybinds.rs +++ b/tetanes/src/nes/renderer/gui/keybinds.rs @@ -246,18 +246,18 @@ impl State { #[cfg(feature = "profiling")] puffin::profile_function!(); + ui.set_min_height(ui.available_height()); + if let Some(player) = player { self.player_gamepad_combo(ui, player, connected_gamepads); ui.separator(); } - ScrollArea::both().show(ui, |ui| { - ui.set_width(ui.available_width()); // Pushes scrollbar to the right of the window - + ScrollArea::both().auto_shrink(false).show(ui, |ui| { let grid = Grid::new("keybind_list") - .num_columns(3) - .spacing([40.0, 6.0]); + .num_columns(4) + .spacing([10.0, 6.0]); grid.show(ui, |ui| { ui.heading("Action"); ui.heading("Binding #1"); diff --git a/tetanes/src/nes/renderer/gui/preferences.rs b/tetanes/src/nes/renderer/gui/preferences.rs index dceec06a..229f589a 100644 --- a/tetanes/src/nes/renderer/gui/preferences.rs +++ b/tetanes/src/nes/renderer/gui/preferences.rs @@ -514,16 +514,18 @@ impl State { puffin::profile_function!(); ui.add_enabled_ui(enabled, |ui| { - ScrollArea::vertical().show(ui, |ui| { - ui.horizontal(|ui| { - ui.selectable_value(&mut self.tab, Tab::Emulation, "Emulation"); - ui.selectable_value(&mut self.tab, Tab::Audio, "Audio"); - ui.selectable_value(&mut self.tab, Tab::Video, "Video"); - ui.selectable_value(&mut self.tab, Tab::Input, "Input"); - }); + ui.set_min_height(ui.available_height()); - ui.separator(); + ui.horizontal(|ui| { + ui.selectable_value(&mut self.tab, Tab::Emulation, "Emulation"); + ui.selectable_value(&mut self.tab, Tab::Audio, "Audio"); + ui.selectable_value(&mut self.tab, Tab::Video, "Video"); + ui.selectable_value(&mut self.tab, Tab::Input, "Input"); + }); + ui.separator(); + + ScrollArea::both().show(ui, |ui| { match self.tab { Tab::Emulation => self.emulation_tab(ui, cfg), Tab::Audio => Self::audio_tab(&self.tx, ui, cfg), @@ -535,70 +537,11 @@ impl State { ui.horizontal(|ui| { if ui.button("Restore Defaults").clicked() { - ui.ctx().memory_mut(|mem| *mem = Default::default()); - - // Inform all cfg updates - let cfg = Config::default(); - let Config { - deck, - emulation, - audio, - renderer, - input, - } = cfg; - let events = [ - ConfigEvent::ActionBindings(input.action_bindings), - ConfigEvent::AlwaysOnTop(renderer.always_on_top), - ConfigEvent::ApuChannelsEnabled(deck.channels_enabled), - ConfigEvent::AudioBuffer(audio.buffer_size), - ConfigEvent::AudioEnabled(audio.enabled), - ConfigEvent::AudioLatency(audio.latency), - ConfigEvent::AutoLoad(emulation.auto_load), - ConfigEvent::AutoSave(emulation.auto_save), - ConfigEvent::AutoSaveInterval(emulation.auto_save_interval), - ConfigEvent::ConcurrentDpad(deck.concurrent_dpad), - ConfigEvent::CycleAccurate(deck.cycle_accurate), - ConfigEvent::DarkTheme(renderer.dark_theme), - ConfigEvent::EmbedViewports(renderer.embed_viewports), - ConfigEvent::FourPlayer(deck.four_player), - ConfigEvent::Fullscreen(renderer.fullscreen), - ConfigEvent::GamepadAssignments(input.gamepad_assignments), - ConfigEvent::GenieCodeClear, - ConfigEvent::HideOverscan(renderer.hide_overscan), - ConfigEvent::MapperRevisions(deck.mapper_revisions), - ConfigEvent::RamState(deck.ram_state), - // Clearing recent roms is handled in a separate button - ConfigEvent::Region(deck.region), - ConfigEvent::RewindEnabled(emulation.rewind), - ConfigEvent::RewindInterval(emulation.rewind_interval), - ConfigEvent::RewindSeconds(emulation.rewind_seconds), - ConfigEvent::RunAhead(emulation.run_ahead), - ConfigEvent::SaveSlot(emulation.save_slot), - ConfigEvent::Shader(renderer.shader), - ConfigEvent::ShowMenubar(renderer.show_menubar), - ConfigEvent::ShowMessages(renderer.show_messages), - ConfigEvent::Speed(emulation.speed), - ConfigEvent::VideoFilter(deck.filter), - ConfigEvent::ZapperConnected(deck.zapper), - ]; - for event in events { - self.tx.event(event); - } + Self::restore_defaults(&self.tx, ui.ctx()); } - if feature!(Storage) { - let data_dir = Config::default_data_dir(); - if ui.button("Clear Save States").clicked() { - match fs::clear_dir(data_dir) { - Ok(_) => self.tx.event(UiEvent::Message(( - MessageType::Info, - "Save States cleared.".to_string(), - ))), - Err(_) => self.tx.event(UiEvent::Message(( - MessageType::Error, - "Failed to clear Save States.".to_string(), - ))), - } - } + + if feature!(Storage) && ui.button("Clear Save States").clicked() { + Self::clear_save_states(&self.tx); } if feature!(Filesystem) && ui.button("Clear Recent ROMs").clicked() { self.tx.event(ConfigEvent::RecentRomsClear); @@ -633,11 +576,10 @@ impl State { .. } = cfg.deck; - ScrollArea::both().show(ui, |ui| { - let grid = Grid::new("emulation_checkboxes") - .num_columns(2) - .spacing([80.0, 6.0]); - grid.show(ui, |ui| { + let grid = Grid::new("emulation_checkboxes") + .num_columns(2) + .spacing([80.0, 6.0]); + grid.show(ui, |ui| { let tx = &self.tx; Preferences::cycle_accurate_checkbox(tx, ui, cycle_accurate, None); @@ -722,66 +664,65 @@ impl State { ui.end_row(); }); - ui.separator(); - - let grid = Grid::new("emulation_preferences") - .num_columns(4) - .spacing([40.0, 6.0]); - grid.show(ui, |ui| { - let tx = &self.tx; + ui.separator(); - ui.strong("Emulation Speed:"); - Preferences::speed_slider(tx, ui, speed); + let grid = Grid::new("emulation_preferences") + .num_columns(4) + .spacing([40.0, 6.0]); + grid.show(ui, |ui| { + let tx = &self.tx; - ui.strong("Run Ahead:") - .on_hover_cursor(CursorIcon::Help) - .on_hover_text("Simulate a number of frames in the future to reduce input lag."); - Preferences::run_ahead_slider(tx, ui, run_ahead); - ui.end_row(); + ui.strong("Emulation Speed:"); + Preferences::speed_slider(tx, ui, speed); - ui.with_layout(Layout::left_to_right(Align::Min), |ui| { - ui.strong("Save Slot:") - .on_hover_cursor(CursorIcon::Help) - .on_hover_text("Select which slot to use when saving or loading game state."); - }); - Grid::new("save_slots") - .num_columns(2) - .spacing([20.0, 6.0]) - .show(ui, |ui| { - Preferences::save_slot_radio(tx, ui, save_slot, cfg, ShowShortcut::No) - }); + ui.strong("Run Ahead:") + .on_hover_cursor(CursorIcon::Help) + .on_hover_text("Simulate a number of frames in the future to reduce input lag."); + Preferences::run_ahead_slider(tx, ui, run_ahead); + ui.end_row(); - ui.with_layout(Layout::left_to_right(Align::Min), |ui| { - ui.strong("Four Player:") - .on_hover_cursor(CursorIcon::Help) - .on_hover_text( - "Some game titles support up to 4 players (requires connected controllers).", - ); + ui.with_layout(Layout::left_to_right(Align::Min), |ui| { + ui.strong("Save Slot:") + .on_hover_cursor(CursorIcon::Help) + .on_hover_text("Select which slot to use when saving or loading game state."); + }); + Grid::new("save_slots") + .num_columns(2) + .spacing([20.0, 6.0]) + .show(ui, |ui| { + Preferences::save_slot_radio(tx, ui, save_slot, cfg, ShowShortcut::No) }); - ui.vertical(|ui| Preferences::four_player_radio(tx, ui, four_player)); - ui.end_row(); - ui.with_layout(Layout::left_to_right(Align::Min), |ui| { - ui.strong("NES Region:") - .on_hover_cursor(CursorIcon::Help) - .on_hover_text("Which regional NES hardware to emulate."); - }); - ui.vertical(|ui| Preferences::nes_region_radio(tx, ui, region)); + ui.with_layout(Layout::left_to_right(Align::Min), |ui| { + ui.strong("Four Player:") + .on_hover_cursor(CursorIcon::Help) + .on_hover_text( + "Some game titles support up to 4 players (requires connected controllers).", + ); + }); + ui.vertical(|ui| Preferences::four_player_radio(tx, ui, four_player)); + ui.end_row(); - ui.with_layout(Layout::left_to_right(Align::Min), |ui| { - ui.strong("RAM State:") - .on_hover_cursor(CursorIcon::Help) - .on_hover_text("What values are read from NES RAM on load."); - }); - ui.vertical(|ui| Preferences::ram_state_radio(tx, ui, ram_state)); - ui.end_row(); + ui.with_layout(Layout::left_to_right(Align::Min), |ui| { + ui.strong("NES Region:") + .on_hover_cursor(CursorIcon::Help) + .on_hover_text("Which regional NES hardware to emulate."); }); + ui.vertical(|ui| Preferences::nes_region_radio(tx, ui, region)); - let grid = Grid::new("genie_codes").num_columns(2).spacing([40.0, 6.0]); - grid.show(ui, |ui| { - self.genie_codes_entry(ui, cfg); - Preferences::genie_codes_list(&self.tx, ui, cfg, false); + ui.with_layout(Layout::left_to_right(Align::Min), |ui| { + ui.strong("RAM State:") + .on_hover_cursor(CursorIcon::Help) + .on_hover_text("What values are read from NES RAM on load."); }); + ui.vertical(|ui| Preferences::ram_state_radio(tx, ui, ram_state)); + ui.end_row(); + }); + + let grid = Grid::new("genie_codes").num_columns(2).spacing([40.0, 6.0]); + grid.show(ui, |ui| { + self.genie_codes_entry(ui, cfg); + Preferences::genie_codes_list(&self.tx, ui, cfg, false); }); } @@ -1028,4 +969,71 @@ impl State { } }); } + + fn restore_defaults(tx: &NesEventProxy, ctx: &Context) { + ctx.memory_mut(|mem| *mem = Default::default()); + + // Inform all cfg updates + let Config { + deck, + emulation, + audio, + renderer, + input, + } = Config::default(); + + let events = [ + ConfigEvent::ActionBindings(input.action_bindings), + ConfigEvent::AlwaysOnTop(renderer.always_on_top), + ConfigEvent::ApuChannelsEnabled(deck.channels_enabled), + ConfigEvent::AudioBuffer(audio.buffer_size), + ConfigEvent::AudioEnabled(audio.enabled), + ConfigEvent::AudioLatency(audio.latency), + ConfigEvent::AutoLoad(emulation.auto_load), + ConfigEvent::AutoSave(emulation.auto_save), + ConfigEvent::AutoSaveInterval(emulation.auto_save_interval), + ConfigEvent::ConcurrentDpad(deck.concurrent_dpad), + ConfigEvent::CycleAccurate(deck.cycle_accurate), + ConfigEvent::DarkTheme(renderer.dark_theme), + ConfigEvent::EmbedViewports(renderer.embed_viewports), + ConfigEvent::FourPlayer(deck.four_player), + ConfigEvent::Fullscreen(renderer.fullscreen), + ConfigEvent::GamepadAssignments(input.gamepad_assignments), + ConfigEvent::GenieCodeClear, + ConfigEvent::HideOverscan(renderer.hide_overscan), + ConfigEvent::MapperRevisions(deck.mapper_revisions), + ConfigEvent::RamState(deck.ram_state), + // Clearing recent roms is handled in a separate button + ConfigEvent::Region(deck.region), + ConfigEvent::RewindEnabled(emulation.rewind), + ConfigEvent::RewindInterval(emulation.rewind_interval), + ConfigEvent::RewindSeconds(emulation.rewind_seconds), + ConfigEvent::RunAhead(emulation.run_ahead), + ConfigEvent::SaveSlot(emulation.save_slot), + ConfigEvent::Shader(renderer.shader), + ConfigEvent::ShowMenubar(renderer.show_menubar), + ConfigEvent::ShowMessages(renderer.show_messages), + ConfigEvent::Speed(emulation.speed), + ConfigEvent::VideoFilter(deck.filter), + ConfigEvent::ZapperConnected(deck.zapper), + ]; + + for event in events { + tx.event(event); + } + } + + fn clear_save_states(tx: &NesEventProxy) { + let data_dir = Config::default_data_dir(); + match fs::clear_dir(data_dir) { + Ok(_) => tx.event(UiEvent::Message(( + MessageType::Info, + "Save States cleared.".to_string(), + ))), + Err(_) => tx.event(UiEvent::Message(( + MessageType::Error, + "Failed to clear Save States.".to_string(), + ))), + } + } } diff --git a/tetanes/src/platform.rs b/tetanes/src/platform.rs index c4278016..59b96c22 100644 --- a/tetanes/src/platform.rs +++ b/tetanes/src/platform.rs @@ -58,17 +58,17 @@ pub mod renderer { #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[must_use] pub enum Feature { - Filesystem, - Storage, - Viewports, - DeferredViewport, - ConstrainedViewport, - Suspend, + AbortOnExit, + AccessKit, Blocking, + ConstrainedViewport, ConsumePaste, - AbortOnExit, + DeferredViewport, + Filesystem, ScreenReader, - AccessKit, + Storage, + Suspend, + Viewports, } /// Checks if the current platform supports a given feature. @@ -77,17 +77,18 @@ macro_rules! feature { ($feature: tt) => {{ use $crate::platform::Feature::*; match $feature { - Suspend => cfg!(target_os = "android"), - Filesystem | Storage | Viewports | Blocking | DeferredViewport => { - cfg!(not(target_arch = "wasm32")) - } - // FIXME: Deadlock thread sleep issue with zbus/async-io on linux when menus are opened - AccessKit => cfg!(any(target_os = "macos", target_os = "windows")), // Wasm should never be able to exit AbortOnExit => cfg!(target_arch = "wasm32"), + // FIXME: Deadlock thread sleep issue with zbus/async-io on linux when menus are opened + AccessKit => cfg!(any(target_os = "macos", target_os = "windows")), + Blocking | DeferredViewport | Filesystem | Viewports => { + cfg!(not(target_arch = "wasm32")) + } ConstrainedViewport | ConsumePaste | ScreenReader => { cfg!(target_arch = "wasm32") } + Storage => true, + Suspend => cfg!(target_os = "android"), } }}; }