Frontend: Add settings window
This commit is contained in:
parent
57c4101ff4
commit
36b7690056
|
@ -22,8 +22,8 @@ void Settings::SetDefaults()
|
|||
|
||||
bios_path = "scph1001.bin";
|
||||
|
||||
memory_card_a_filename = "memory_card_a.mcd";
|
||||
memory_card_b_filename.clear();
|
||||
memory_card_a_path = "memory_card_a.mcd";
|
||||
memory_card_b_path.clear();
|
||||
}
|
||||
|
||||
void Settings::Load(const char* filename)
|
||||
|
@ -46,8 +46,8 @@ void Settings::Load(const char* filename)
|
|||
|
||||
bios_path = ini.GetValue("BIOS", "Path", "scph1001.bin");
|
||||
|
||||
memory_card_a_filename = ini.GetValue("MemoryCard", "CardAPath", "memory_card_a.mcd");
|
||||
memory_card_b_filename = ini.GetValue("MemoryCard", "CardBPath", "");
|
||||
memory_card_a_path = ini.GetValue("MemoryCard", "CardAPath", "memory_card_a.mcd");
|
||||
memory_card_b_path = ini.GetValue("MemoryCard", "CardBPath", "");
|
||||
}
|
||||
|
||||
bool Settings::Save(const char* filename) const
|
||||
|
@ -67,13 +67,13 @@ bool Settings::Save(const char* filename) const
|
|||
|
||||
ini.SetValue("BIOS", "Path", bios_path.c_str());
|
||||
|
||||
if (!memory_card_a_filename.empty())
|
||||
ini.SetValue("MemoryCard", "CardAPath", memory_card_a_filename.c_str());
|
||||
if (!memory_card_a_path.empty())
|
||||
ini.SetValue("MemoryCard", "CardAPath", memory_card_a_path.c_str());
|
||||
else
|
||||
ini.DeleteValue("MemoryCard", "CardAPath", nullptr);
|
||||
|
||||
if (!memory_card_b_filename.empty())
|
||||
ini.SetValue("MemoryCard", "CardBPath", memory_card_b_filename.c_str());
|
||||
if (!memory_card_b_path.empty())
|
||||
ini.SetValue("MemoryCard", "CardBPath", memory_card_b_path.c_str());
|
||||
else
|
||||
ini.DeleteValue("MemoryCard", "CardBPath", nullptr);
|
||||
|
||||
|
@ -82,6 +82,8 @@ bool Settings::Save(const char* filename) const
|
|||
}
|
||||
|
||||
static std::array<const char*, 3> s_gpu_renderer_names = {{"D3D11", "OpenGL", "Software"}};
|
||||
static std::array<const char*, 3> s_gpu_renderer_display_names = {
|
||||
{"Hardware (D3D11)", "Hardware (OpenGL)", "Software"}};
|
||||
|
||||
std::optional<Settings::GPURenderer> Settings::ParseRendererName(const char* str)
|
||||
{
|
||||
|
@ -101,3 +103,8 @@ const char* Settings::GetRendererName(GPURenderer renderer)
|
|||
{
|
||||
return s_gpu_renderer_names[static_cast<int>(renderer)];
|
||||
}
|
||||
|
||||
const char* Settings::GetRendererDisplayName(GPURenderer renderer)
|
||||
{
|
||||
return s_gpu_renderer_display_names[static_cast<int>(renderer)];
|
||||
}
|
||||
|
|
|
@ -8,12 +8,14 @@ struct Settings
|
|||
{
|
||||
HardwareD3D11,
|
||||
HardwareOpenGL,
|
||||
Software
|
||||
Software,
|
||||
Count
|
||||
};
|
||||
|
||||
Settings();
|
||||
|
||||
bool start_paused = false;
|
||||
bool speed_limiter_enabled = true;
|
||||
|
||||
GPURenderer gpu_renderer = GPURenderer::Software;
|
||||
u32 gpu_resolution_scale = 1;
|
||||
|
@ -21,6 +23,7 @@ struct Settings
|
|||
bool gpu_vsync = true;
|
||||
bool gpu_true_color = false;
|
||||
bool display_linear_filtering = true;
|
||||
bool display_fullscreen = false;
|
||||
|
||||
struct DebugSettings
|
||||
{
|
||||
|
@ -38,8 +41,8 @@ struct Settings
|
|||
// TODO: Controllers, memory cards, etc.
|
||||
|
||||
std::string bios_path;
|
||||
std::string memory_card_a_filename;
|
||||
std::string memory_card_b_filename;
|
||||
std::string memory_card_a_path;
|
||||
std::string memory_card_b_path;
|
||||
|
||||
void SetDefaults();
|
||||
void Load(const char* filename);
|
||||
|
@ -47,4 +50,5 @@ struct Settings
|
|||
|
||||
static std::optional<GPURenderer> ParseRendererName(const char* str);
|
||||
static const char* GetRendererName(GPURenderer renderer);
|
||||
static const char* GetRendererDisplayName(GPURenderer renderer);
|
||||
};
|
||||
|
|
|
@ -376,16 +376,16 @@ void System::UpdateMemoryCards()
|
|||
m_pad->SetMemoryCard(0, nullptr);
|
||||
m_pad->SetMemoryCard(1, nullptr);
|
||||
|
||||
if (!m_settings.memory_card_a_filename.empty())
|
||||
if (!m_settings.memory_card_a_path.empty())
|
||||
{
|
||||
std::shared_ptr<MemoryCard> card = MemoryCard::Open(this, m_settings.memory_card_a_filename);
|
||||
std::shared_ptr<MemoryCard> card = MemoryCard::Open(this, m_settings.memory_card_a_path);
|
||||
if (card)
|
||||
m_pad->SetMemoryCard(0, std::move(card));
|
||||
}
|
||||
|
||||
if (!m_settings.memory_card_b_filename.empty())
|
||||
if (!m_settings.memory_card_b_path.empty())
|
||||
{
|
||||
std::shared_ptr<MemoryCard> card = MemoryCard::Open(this, m_settings.memory_card_b_filename);
|
||||
std::shared_ptr<MemoryCard> card = MemoryCard::Open(this, m_settings.memory_card_b_path);
|
||||
if (card)
|
||||
m_pad->SetMemoryCard(1, std::move(card));
|
||||
}
|
||||
|
|
|
@ -21,14 +21,10 @@
|
|||
#include <cinttypes>
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_sdl.h>
|
||||
#include <imgui_stdlib.h>
|
||||
#include <nfd.h>
|
||||
Log_SetChannel(SDLHostInterface);
|
||||
|
||||
static constexpr std::array<std::pair<Settings::GPURenderer, const char*>, 3> s_gpu_renderer_names = {
|
||||
{{Settings::GPURenderer::HardwareD3D11, "Hardware (Direct3D 11)"},
|
||||
{Settings::GPURenderer::HardwareOpenGL, "Hardware (OpenGL)"},
|
||||
{Settings::GPURenderer::Software, "Software"}}};
|
||||
|
||||
SDLHostInterface::SDLHostInterface() = default;
|
||||
|
||||
SDLHostInterface::~SDLHostInterface()
|
||||
|
@ -111,7 +107,8 @@ bool SDLHostInterface::CreateAudioStream()
|
|||
|
||||
void SDLHostInterface::UpdateAudioVisualSync()
|
||||
{
|
||||
const bool speed_limiter_enabled = m_speed_limiter_enabled && !m_speed_limiter_temp_disabled;
|
||||
const bool speed_limiter_enabled =
|
||||
!m_system || (m_system->GetSettings().speed_limiter_enabled && !m_speed_limiter_temp_disabled);
|
||||
const bool audio_sync_enabled = speed_limiter_enabled;
|
||||
const bool vsync_enabled = !m_system || (speed_limiter_enabled && m_system->GetSettings().gpu_vsync);
|
||||
Log_InfoPrintf("Syncing to %s%s", audio_sync_enabled ? "audio" : "",
|
||||
|
@ -182,6 +179,8 @@ void SDLHostInterface::ResetPerformanceCounters()
|
|||
m_fps_timer.Reset();
|
||||
}
|
||||
|
||||
void SDLHostInterface::SwitchGPURenderer() {}
|
||||
|
||||
void SDLHostInterface::ShutdownSystem()
|
||||
{
|
||||
m_system.reset();
|
||||
|
@ -518,9 +517,10 @@ void SDLHostInterface::HandleSDLKeyEvent(const SDL_Event* event)
|
|||
{
|
||||
if (pressed && !repeat && m_system)
|
||||
{
|
||||
m_speed_limiter_enabled = !m_speed_limiter_enabled;
|
||||
m_system->GetSettings().speed_limiter_enabled = !m_system->GetSettings().speed_limiter_enabled;
|
||||
UpdateAudioVisualSync();
|
||||
AddOSDMessage(m_speed_limiter_enabled ? "Speed limiter enabled." : "Speed limiter disabled.");
|
||||
AddOSDMessage(m_system->GetSettings().speed_limiter_enabled ? "Speed limiter enabled." :
|
||||
"Speed limiter disabled.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -558,6 +558,9 @@ void SDLHostInterface::DrawImGui()
|
|||
else
|
||||
DrawPoweredOffWindow();
|
||||
|
||||
if (m_settings_window_open)
|
||||
DrawSettingsWindow();
|
||||
|
||||
if (m_about_window_open)
|
||||
DrawAboutWindow();
|
||||
|
||||
|
@ -637,8 +640,11 @@ void SDLHostInterface::DrawMainMenuBar()
|
|||
|
||||
if (ImGui::BeginMenu("Settings"))
|
||||
{
|
||||
if (ImGui::MenuItem("Enable Speed Limiter", nullptr, &m_speed_limiter_enabled, system_enabled))
|
||||
Settings& settings = m_system ? m_system->GetSettings() : m_settings;
|
||||
if (ImGui::MenuItem("Enable Speed Limiter", nullptr, &settings.speed_limiter_enabled, system_enabled))
|
||||
{
|
||||
UpdateAudioVisualSync();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
|
@ -652,11 +658,12 @@ void SDLHostInterface::DrawMainMenuBar()
|
|||
if (ImGui::BeginMenu("Renderer"))
|
||||
{
|
||||
const Settings::GPURenderer current = m_system->GetSettings().gpu_renderer;
|
||||
for (const auto& it : s_gpu_renderer_names)
|
||||
for (u32 i = 0; i < static_cast<u32>(Settings::GPURenderer::Count); i++)
|
||||
{
|
||||
if (ImGui::MenuItem(it.second, nullptr, current == it.first))
|
||||
if (ImGui::MenuItem(Settings::GetRendererDisplayName(static_cast<Settings::GPURenderer>(i)), nullptr,
|
||||
i == static_cast<u32>(current)))
|
||||
{
|
||||
m_system->GetSettings().gpu_renderer = it.first;
|
||||
m_system->GetSettings().gpu_renderer = static_cast<Settings::GPURenderer>(i);
|
||||
m_system->RecreateGPU();
|
||||
}
|
||||
}
|
||||
|
@ -810,7 +817,8 @@ void SDLHostInterface::DrawPoweredOffWindow()
|
|||
ImGui::NewLine();
|
||||
|
||||
ImGui::SetCursorPosX(button_left);
|
||||
ImGui::Button("Settings", button_size);
|
||||
if (ImGui::Button("Settings", button_size))
|
||||
m_settings_window_open = true;
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::SetCursorPosX(button_left);
|
||||
|
@ -825,11 +833,178 @@ void SDLHostInterface::DrawPoweredOffWindow()
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
static bool DrawSettingsSectionHeader(const char* title)
|
||||
{
|
||||
return ImGui::CollapsingHeader(title, ImGuiTreeNodeFlags_DefaultOpen /* | ImGuiTreeNodeFlags_Leaf*/);
|
||||
}
|
||||
|
||||
void SDLHostInterface::DrawSettingsWindow()
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x * 0.5f, ImGui::GetIO().DisplaySize.y * 0.5f),
|
||||
ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
|
||||
ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
|
||||
|
||||
if (!ImGui::Begin("Settings", &m_settings_window_open, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
Settings& settings = m_system ? m_system->GetSettings() : m_settings;
|
||||
bool settings_changed = false;
|
||||
bool gpu_settings_changed = false;
|
||||
|
||||
if (ImGui::BeginTabBar("SettingsTabBar", 0))
|
||||
{
|
||||
const float indent = 150.0f;
|
||||
|
||||
if (ImGui::BeginTabItem("General"))
|
||||
{
|
||||
ImGui::Text("Region:");
|
||||
ImGui::SameLine(indent);
|
||||
static int region = 0;
|
||||
ImGui::Combo("##region", ®ion, "NTSC-U (US)\0NTSC-J (Japan)\0PAL (Europe, Australia)");
|
||||
|
||||
ImGui::Text("BIOS Path:");
|
||||
ImGui::SameLine(indent);
|
||||
DrawFileChooser("##bios_path", &settings.bios_path);
|
||||
|
||||
ImGui::Checkbox("Enable Speed Limiter", &settings.speed_limiter_enabled);
|
||||
|
||||
ImGui::Checkbox("Pause On Start", &settings.start_paused);
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Memory Cards"))
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (!DrawSettingsSectionHeader(TinyString::FromFormat("Card %c", 'A' + i)))
|
||||
continue;
|
||||
|
||||
ImGui::Text("Card %c", 'A' + i);
|
||||
|
||||
ImGui::Text("Path:");
|
||||
ImGui::SameLine(indent);
|
||||
|
||||
std::string* path_ptr = (i == 0) ? &settings.memory_card_a_path : &settings.memory_card_b_path;
|
||||
if (DrawFileChooser(TinyString::FromFormat("##memcard_%c_path", 'a' + i), path_ptr))
|
||||
{
|
||||
settings_changed = true;
|
||||
if (m_system)
|
||||
m_system->UpdateMemoryCards();
|
||||
}
|
||||
|
||||
if (ImGui::Button("Eject"))
|
||||
{
|
||||
path_ptr->clear();
|
||||
settings_changed = true;
|
||||
if (m_system)
|
||||
m_system->UpdateMemoryCards();
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("GPU"))
|
||||
{
|
||||
if (DrawSettingsSectionHeader("Basic"))
|
||||
{
|
||||
ImGui::Text("Renderer:");
|
||||
ImGui::SameLine(indent);
|
||||
|
||||
int gpu_renderer = static_cast<int>(settings.gpu_renderer);
|
||||
if (ImGui::Combo(
|
||||
"##gpu_renderer", &gpu_renderer,
|
||||
[](void*, int index, const char** out_text) {
|
||||
*out_text = Settings::GetRendererDisplayName(static_cast<Settings::GPURenderer>(index));
|
||||
return true;
|
||||
},
|
||||
nullptr, static_cast<int>(Settings::GPURenderer::Count)))
|
||||
{
|
||||
settings.gpu_renderer = static_cast<Settings::GPURenderer>(gpu_renderer);
|
||||
SwitchGPURenderer();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
if (DrawSettingsSectionHeader("Display Output"))
|
||||
{
|
||||
ImGui::Checkbox("Fullscreen", &settings.display_fullscreen);
|
||||
if (ImGui::Checkbox("VSync", &settings.gpu_vsync))
|
||||
UpdateAudioVisualSync();
|
||||
ImGui::Checkbox("Linear Filtering", &settings.display_linear_filtering);
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
if (DrawSettingsSectionHeader("Enhancements"))
|
||||
{
|
||||
ImGui::Text("Resolution Scale:");
|
||||
ImGui::SameLine(indent);
|
||||
|
||||
static constexpr std::array<const char*, 16> resolutions = {{
|
||||
"1x (1024x512)",
|
||||
"2x (2048x1024)",
|
||||
"3x (3072x1536)",
|
||||
"4x (4096x2048)",
|
||||
"5x (5120x2560)",
|
||||
"6x (6144x3072)",
|
||||
"7x (7168x3584)",
|
||||
"8x (8192x4096)",
|
||||
"9x (9216x4608)",
|
||||
"10x (10240x5120)",
|
||||
"11x (11264x5632)",
|
||||
"12x (12288x6144)",
|
||||
"13x (13312x6656)",
|
||||
"14x (14336x7168)",
|
||||
"15x (15360x7680)",
|
||||
"16x (16384x8192)",
|
||||
}};
|
||||
|
||||
int current_resolution_index = static_cast<int>(settings.gpu_resolution_scale) - 1;
|
||||
if (ImGui::Combo("##gpu_resolution_scale", ¤t_resolution_index, resolutions.data(),
|
||||
static_cast<int>(resolutions.size())))
|
||||
{
|
||||
settings.gpu_resolution_scale = static_cast<u32>(current_resolution_index + 1);
|
||||
gpu_settings_changed = true;
|
||||
}
|
||||
|
||||
ImGui::Checkbox("True 24-bit Color (disables dithering)", &settings.gpu_true_color);
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
const auto window_size = ImGui::GetWindowSize();
|
||||
ImGui::SetCursorPosX(window_size.x - 50.0f);
|
||||
ImGui::SetCursorPosY(window_size.y - 30.0f);
|
||||
if (ImGui::Button("Close"))
|
||||
m_settings_window_open = false;
|
||||
|
||||
ImGui::End();
|
||||
|
||||
if (settings_changed)
|
||||
{
|
||||
// TODO: Save to file
|
||||
}
|
||||
if (gpu_settings_changed && m_system)
|
||||
m_system->GetGPU()->UpdateSettings();
|
||||
}
|
||||
|
||||
void SDLHostInterface::DrawAboutWindow()
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x * 0.5f, ImGui::GetIO().DisplaySize.y * 0.5f),
|
||||
ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
if (!ImGui::Begin("About DuckStation", &m_about_window_open))
|
||||
ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
if (!ImGui::Begin("About DuckStation", &m_about_window_open, ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
|
@ -903,6 +1078,26 @@ void SDLHostInterface::DrawDebugWindows()
|
|||
m_system->GetMDEC()->DrawDebugStateWindow();
|
||||
}
|
||||
|
||||
bool SDLHostInterface::DrawFileChooser(const char* label, std::string* path, const char* filter /* = nullptr */)
|
||||
{
|
||||
ImGui::SetNextItemWidth(ImGui::CalcItemWidth() - 50.0f);
|
||||
bool result = ImGui::InputText(label, path);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetNextItemWidth(50.0f);
|
||||
if (ImGui::Button("..."))
|
||||
{
|
||||
nfdchar_t* out_path = nullptr;
|
||||
if (NFD_OpenDialog(filter, path->c_str(), &out_path) == NFD_OKAY)
|
||||
{
|
||||
path->assign(out_path);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SDLHostInterface::AddOSDMessage(const char* message, float duration /*= 2.0f*/)
|
||||
{
|
||||
OSDMessage msg;
|
||||
|
|
|
@ -68,6 +68,7 @@ private:
|
|||
bool InitializeSystem(const char* filename = nullptr, const char* exp1_filename = nullptr);
|
||||
void ConnectDevices();
|
||||
void ResetPerformanceCounters();
|
||||
void SwitchGPURenderer();
|
||||
void ShutdownSystem();
|
||||
|
||||
// We only pass mouse input through if it's grabbed
|
||||
|
@ -92,10 +93,12 @@ private:
|
|||
|
||||
void DrawMainMenuBar();
|
||||
void DrawPoweredOffWindow();
|
||||
void DrawSettingsWindow();
|
||||
void DrawAboutWindow();
|
||||
void DrawOSDMessages();
|
||||
void DrawDebugMenu();
|
||||
void DrawDebugWindows();
|
||||
bool DrawFileChooser(const char* label, std::string* path, const char* filter = nullptr);
|
||||
|
||||
SDL_Window* m_window = nullptr;
|
||||
std::unique_ptr<HostDisplay> m_display;
|
||||
|
@ -120,7 +123,7 @@ private:
|
|||
bool m_quit_request = false;
|
||||
bool m_frame_step_request = false;
|
||||
bool m_focus_main_menu_bar = false;
|
||||
bool m_settings_window_open = false;
|
||||
bool m_about_window_open = false;
|
||||
bool m_speed_limiter_enabled = true;
|
||||
bool m_speed_limiter_temp_disabled = false;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue