Integrate standalone FSUI into Panda SDL frontend
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "audio/dsp_core.hpp"
|
||||
#include "frontend_settings.hpp"
|
||||
@@ -110,6 +111,15 @@ struct EmulatorConfig {
|
||||
|
||||
static constexpr size_t maxRecentGames = 8;
|
||||
std::vector<std::filesystem::path> recentlyPlayed;
|
||||
std::vector<std::filesystem::path> fsuiGameListPaths;
|
||||
std::vector<std::filesystem::path> fsuiGameListRecursivePaths;
|
||||
std::filesystem::path fsuiCoversPath = "";
|
||||
int fsuiDefaultGameView = 0;
|
||||
int fsuiGameSort = 0;
|
||||
bool fsuiGameSortReverse = false;
|
||||
std::string fsuiTheme = "Dark";
|
||||
std::string fsuiPromptIconPack = "Auto";
|
||||
std::filesystem::path fsuiBackgroundImagePath = "";
|
||||
|
||||
// Frontend window settings
|
||||
struct WindowSettings {
|
||||
|
||||
@@ -126,6 +126,7 @@ class Emulator {
|
||||
ServiceManager& getServiceManager() { return kernel.getServiceManager(); }
|
||||
LuaManager& getLua() { return lua; }
|
||||
AudioDeviceInterface& getAudioDevice() { return audioDevice; }
|
||||
const std::optional<std::filesystem::path>& getROMPath() const { return romPath; }
|
||||
|
||||
RendererType getRendererType() const { return config.rendererType; }
|
||||
Renderer* getRenderer() { return gpu.getRenderer(); }
|
||||
|
||||
@@ -28,6 +28,7 @@ struct FrontendSettings {
|
||||
WindowIcon icon = WindowIcon::Rpog;
|
||||
std::string language = "en";
|
||||
bool showImGuiDebugPanel = true;
|
||||
bool enableFullscreenUI = false;
|
||||
#ifdef IMGUI_FRONTEND
|
||||
bool stretchImGuiOutputToWindow = true;
|
||||
#else
|
||||
@@ -39,4 +40,5 @@ struct FrontendSettings {
|
||||
|
||||
static WindowIcon iconFromString(std::string inString);
|
||||
static const char* iconToString(WindowIcon icon);
|
||||
static bool defaultFullscreenUIEnabled();
|
||||
};
|
||||
|
||||
@@ -4,10 +4,17 @@
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "emulator.hpp"
|
||||
#include "fsui/backend_sdl.hpp"
|
||||
#include "fsui/fsui.hpp"
|
||||
#include "panda_sdl/panda_fsui.hpp"
|
||||
|
||||
struct ImFont;
|
||||
|
||||
class ImGuiLayer {
|
||||
public:
|
||||
@@ -30,13 +37,24 @@ class ImGuiLayer {
|
||||
void showPauseMenuFromController();
|
||||
|
||||
private:
|
||||
bool useFullscreenUI();
|
||||
void drawDebugPanel();
|
||||
void drawPausePanel();
|
||||
void drawSettingsPanel();
|
||||
void drawClassicPausePanel();
|
||||
void drawClassicSettingsPanel();
|
||||
void drawSettingsGeneralSection(bool& reloadSettings);
|
||||
void drawSettingsWindowSection(bool& reloadSettings);
|
||||
void drawSettingsUISection(bool& reloadSettings);
|
||||
void drawSettingsGraphicsSection(bool& reloadSettings);
|
||||
void drawSettingsAudioSection(bool& reloadSettings);
|
||||
void drawSettingsBatterySection(bool& reloadSettings);
|
||||
void drawSettingsSDSection(bool& reloadSettings);
|
||||
|
||||
SDL_Window* window = nullptr;
|
||||
SDL_GLContext glContext = nullptr;
|
||||
Emulator& emu;
|
||||
fsui::FontStack fontStack;
|
||||
fsui::SdlImGuiBackend imguiBackend;
|
||||
PandaFsuiAdapter fsuiAdapter;
|
||||
|
||||
bool showDebug = true;
|
||||
bool showPauseMenu = false;
|
||||
@@ -44,6 +62,7 @@ class ImGuiLayer {
|
||||
bool isPaused = false;
|
||||
bool captureKeyboard = false;
|
||||
bool captureMouse = false;
|
||||
bool fullscreenSelectorMode = false;
|
||||
|
||||
std::function<void(bool)> onPauseChange;
|
||||
std::function<void(bool)> onVsyncChange;
|
||||
|
||||
92
include/panda_sdl/panda_fsui.hpp
Normal file
92
include/panda_sdl/panda_fsui.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef IMGUI_FRONTEND
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "fsui/fsui.hpp"
|
||||
|
||||
class Emulator;
|
||||
|
||||
class PandaFsuiAdapter {
|
||||
public:
|
||||
enum class ClassicUiRequest {
|
||||
None,
|
||||
Return,
|
||||
OpenSettings,
|
||||
};
|
||||
|
||||
PandaFsuiAdapter(SDL_Window* window, Emulator& emu);
|
||||
|
||||
bool initialize(const fsui::FontStack& fonts);
|
||||
void shutdown(bool clear_state);
|
||||
void render();
|
||||
void consumeCommands();
|
||||
|
||||
void setSelectorMode(bool selector_mode);
|
||||
bool isSelectorMode() const;
|
||||
bool hasActiveWindow() const;
|
||||
void openPauseMenu();
|
||||
void returnToPreviousWindow();
|
||||
void returnToMainWindow();
|
||||
void switchToSettings();
|
||||
|
||||
std::optional<std::filesystem::path> consumeLaunchPath();
|
||||
bool consumeCloseSelector();
|
||||
ClassicUiRequest consumeClassicUiRequest();
|
||||
|
||||
void setPauseCallback(std::function<void(bool)> callback);
|
||||
void setVsyncCallback(std::function<void(bool)> callback);
|
||||
void setExitToSelectorCallback(std::function<void()> callback);
|
||||
|
||||
private:
|
||||
struct ParsedMetadata;
|
||||
struct LanguageOption;
|
||||
|
||||
void syncUiStateFromConfig();
|
||||
void persistUiState(bool reload);
|
||||
void seedGameListPathsIfNeeded();
|
||||
std::vector<std::filesystem::path> currentScanRoots() const;
|
||||
bool hasSupportedExtension(const std::filesystem::path& path) const;
|
||||
std::vector<fsui::GameEntry> buildGameList();
|
||||
std::vector<fsui::SettingsPageDescriptor> buildSettingsPages(fsui::SettingsScope scope);
|
||||
fsui::CurrentGameInfo buildCurrentGameInfo();
|
||||
std::vector<fsui::MenuItemDescriptor> buildLandingItems();
|
||||
std::vector<fsui::MenuItemDescriptor> buildStartItems();
|
||||
std::vector<fsui::MenuItemDescriptor> buildExitItems();
|
||||
std::vector<fsui::MenuItemDescriptor> buildPauseItems();
|
||||
std::vector<fsui::MenuItemDescriptor> buildGameLaunchOptions(const fsui::GameEntry& entry);
|
||||
|
||||
std::optional<ParsedMetadata> readMetadataForPath(const std::filesystem::path& path) const;
|
||||
fsui::GameEntry buildGameListEntry(const std::filesystem::directory_entry& entry) const;
|
||||
std::filesystem::path defaultCoverDirectory() const;
|
||||
std::filesystem::path findCoverPath(const std::filesystem::path& rom_path, const std::string& title_id) const;
|
||||
std::string currentGameTitle() const;
|
||||
std::string currentGameSubtitle() const;
|
||||
std::string formatPercent(float value) const;
|
||||
std::string formatInteger(int value) const;
|
||||
std::string formatTitleId(std::uint64_t program_id) const;
|
||||
void openFileAndLaunch();
|
||||
void requestLaunchPath(const std::filesystem::path& path);
|
||||
void requestClassicUi(bool open_settings);
|
||||
void openUnsupportedPrompt(std::string title, std::string message) const;
|
||||
|
||||
SDL_Window* window = nullptr;
|
||||
Emulator& emu;
|
||||
fsui::UiContext fsuiContext;
|
||||
fsui::UiState uiState;
|
||||
std::vector<fsui::GameEntry> cachedGameList;
|
||||
std::optional<std::filesystem::path> pendingLaunchPath;
|
||||
bool closeSelectorRequested = false;
|
||||
ClassicUiRequest pendingClassicUiRequest = ClassicUiRequest::None;
|
||||
std::function<void(bool)> onPauseChange;
|
||||
std::function<void(bool)> onVsyncChange;
|
||||
std::function<void()> onExitToSelector;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user