Big imgui overhaul

This commit is contained in:
Luke Street
2026-04-09 23:09:32 -06:00
parent ed7fa8f2c5
commit 95191036f3
21 changed files with 324 additions and 255 deletions
+1 -1
+1
View File
@@ -2,6 +2,7 @@
#define DUSK_MAIN_H
namespace dusk {
extern bool IsRunning;
extern bool IsShuttingDown;
extern bool IsGameLaunched;
}
+1
View File
@@ -73,6 +73,7 @@ struct UserSettings {
struct {
ConfigVar<std::string> isoPath;
ConfigVar<std::string> graphicsBackend;
ConfigVar<bool> skipPreLaunchUI;
} backend;
};
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

+6
View File
@@ -253,3 +253,9 @@ void dusk::ImGuiMenuTools::ShowAudioDebug() {
ImGui::End();
}
void dusk::ImGuiMenuTools::ShowSaveEditor() {
if (m_showSaveEditor) {
m_saveEditor.draw(m_showSaveEditor);
}
}
+1 -1
View File
@@ -25,7 +25,7 @@ namespace dusk {
windowFlags |= ImGuiWindowFlags_NoMove;
}
ImGui::SetNextWindowBgAlpha(0.65f);
// ImGui::SetNextWindowBgAlpha(0.65f);
if (!ImGui::Begin("Camera Debug", nullptr, windowFlags)) {
ImGui::End();
+96 -34
View File
@@ -200,33 +200,19 @@ namespace dusk {
ImGuiConsole::ImGuiConsole() {}
void ImGuiConsole::InitSettings() {
bool lockAspect = getSettings().video.lockAspectRatio;
if (lockAspect) {
VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH);
} else {
VIUnlockAspectRatio();
}
dusk::audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f);
dusk::audio::SetEnableReverb(getSettings().audio.enableReverb);
}
void ImGuiConsole::UpdateSettings() {
getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind && ImGui::IsKeyDown(ImGuiKey_Tab);
}
void ImGuiConsole::PreDraw() {
ZoneScoped;
if (!m_isLaunchInitialized) {
InitSettings();
if (dusk::IsGameLaunched && !m_isLaunchInitialized) {
m_toasts.emplace_back("Press F1 to toggle menu"s, 5.f);
m_isLaunchInitialized = true;
}
UpdateSettings();
if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)) &&
ImGui::IsKeyPressed(ImGuiKey_R))
{
@@ -237,27 +223,11 @@ namespace dusk {
ImGuiMenuGame::ToggleFullscreen();
}
if (!dusk::IsGameLaunched) {
m_preLaunchWindow.draw();
}
else if (CheckMenuViewToggle(ImGuiKey_F1, m_isHidden)) {
ShowToasts();
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
SDL_HideCursor();
return;
}
bool showMenu = !dusk::IsGameLaunched || !CheckMenuViewToggle(ImGuiKey_F1, m_isHidden);
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange;
// Imgui will re-show cursor.
// TODO: we need to be able to render the menu bar & any overlays separately
// The code currently ties them all together, so hiding the menu hides all windows
if (ImGui::BeginMainMenuBar()) {
if (showMenu && ImGui::BeginMainMenuBar()) {
m_menuGame.draw();
m_menuEnhancements.draw();
// Keep always last
m_menuTools.draw();
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 80.0f * ImGuiScale());
@@ -267,6 +237,34 @@ namespace dusk {
ImGui::EndMainMenuBar();
}
if (!dusk::IsGameLaunched) {
m_preLaunchWindow.draw();
}
m_menuGame.windowControllerConfig();
m_menuGame.windowInputViewer();
if (dusk::IsGameLaunched) {
m_menuTools.ShowDebugOverlay();
m_menuTools.ShowCameraOverlay();
m_menuTools.ShowProcessManager();
m_menuTools.ShowHeapOverlay();
m_menuTools.ShowStubLog();
m_menuTools.ShowMapLoader();
m_menuTools.ShowPlayerInfo();
m_menuTools.ShowAudioDebug();
m_menuTools.ShowSaveEditor();
}
DuskDebugPad(); // temporary, remove later
// Only show cursor when menu or any windows are open
if (showMenu || ImGui::GetIO().MetricsRenderWindows > 0) {
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange;
// Imgui will re-show cursor.
} else {
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
SDL_HideCursor();
}
ShowToasts();
}
@@ -306,6 +304,70 @@ namespace dusk {
}
}
std::string_view backend_id(AuroraBackend backend) {
switch (backend) {
default:
return "auto"sv;
case BACKEND_D3D12:
return "d3d12"sv;
case BACKEND_D3D11:
return "d3d11"sv;
case BACKEND_METAL:
return "metal"sv;
case BACKEND_VULKAN:
return "vulkan"sv;
case BACKEND_OPENGL:
return "opengl"sv;
case BACKEND_OPENGLES:
return "opengles"sv;
case BACKEND_WEBGPU:
return "webgpu"sv;
case BACKEND_NULL:
return "null"sv;
}
}
bool try_parse_backend(std::string_view backend, AuroraBackend& outBackend) {
if (backend == "auto") {
outBackend = BACKEND_AUTO;
return true;
}
if (backend == "d3d11") {
outBackend = BACKEND_D3D11;
return true;
}
if (backend == "d3d12") {
outBackend = BACKEND_D3D12;
return true;
}
if (backend == "metal") {
outBackend = BACKEND_METAL;
return true;
}
if (backend == "vulkan") {
outBackend = BACKEND_VULKAN;
return true;
}
if (backend == "opengl") {
outBackend = BACKEND_OPENGL;
return true;
}
if (backend == "opengles") {
outBackend = BACKEND_OPENGLES;
return true;
}
if (backend == "webgpu") {
outBackend = BACKEND_WEBGPU;
return true;
}
if (backend == "null") {
outBackend = BACKEND_NULL;
return true;
}
return false;
}
void ImGuiConsole::ShowToasts() {
if (m_toasts.empty()) {
return;
+3 -1
View File
@@ -4,6 +4,7 @@
#include <aurora/aurora.h>
#include <deque>
#include <string>
#include <string_view>
#include "ImGuiMenuEnhancements.hpp"
#include "ImGuiMenuGame.hpp"
@@ -15,7 +16,6 @@ namespace dusk {
class ImGuiConsole {
public:
ImGuiConsole();
void InitSettings();
void UpdateSettings();
void PreDraw();
void PostDraw();
@@ -49,6 +49,8 @@ private:
extern ImGuiConsole g_imguiConsole;
std::string_view backend_name(AuroraBackend backend);
std::string_view backend_id(AuroraBackend backend);
bool try_parse_backend(std::string_view backend, AuroraBackend& outBackend);
std::string BytesToString(size_t bytes);
void SetOverlayWindowLocation(int corner);
bool ShowCornerContextMenu(int& corner, int avoidCorner);
+36 -64
View File
@@ -6,6 +6,7 @@
#include <aurora/imgui.h>
#include <cmath>
#include <cstring>
#include <fmt/format.h>
#include <string>
#include "dusk/logging.h"
@@ -33,21 +34,23 @@ bool AssetExists(const std::string& path) {
ImFont* ImGuiEngine::fontNormal;
ImFont* ImGuiEngine::fontLarge;
ImFont* ImGuiEngine::fontExtraLarge;
ImFont* ImGuiEngine::fontMono;
ImTextureID ImGuiEngine::duskIcon = 0;
inline ImFont* CreateFont(float size, bool hasFontFile, const std::string& fontPath) {
ImGuiIO& io = ImGui::GetIO();
inline ImFont* CreateFont(float size, const std::string& fontPath, std::string_view fontName) {
bool fontFileExists = !fontPath.empty() && AssetExists(fontPath);
ImFontConfig fontConfig{};
fontConfig.SizePixels = size;
snprintf(static_cast<char*>(fontConfig.Name), sizeof(fontConfig.Name),
"Noto Mono Regular, %dpx", static_cast<int>(fontConfig.SizePixels));
auto name = fmt::format_to_n(fontConfig.Name, sizeof(fontConfig.Name) - 1, "{}, {}px", fontName,
static_cast<int>(fontConfig.SizePixels));
*name.out = '\0';
const ImGuiIO& io = ImGui::GetIO();
ImFont* outFont =
hasFontFile ?
fontFileExists ?
io.Fonts->AddFontFromFileTTF(fontPath.c_str(), fontConfig.SizePixels, &fontConfig) :
nullptr;
if (outFont == nullptr) {
if (hasFontFile) {
if (fontFileExists) {
DuskLog.warn("Failed to load font '{}': {}", fontPath, SDL_GetError());
}
outFont = io.Fonts->AddFontDefault(&fontConfig);
@@ -56,65 +59,38 @@ inline ImFont* CreateFont(float size, bool hasFontFile, const std::string& font
}
void ImGuiEngine_Initialize(float scale) {
// Round font scale to nearest integer
scale = std::ceilf(scale);
ImGui::GetCurrentContext();
ImGuiIO& io = ImGui::GetIO();
io.Fonts->Clear();
io.FontGlobalScale = scale > 0.0f ? 1.0f / scale : 1.0f;
const std::string fontPath = GetAssetPath("NotoMono-Regular.ttf");
const bool hasFontFile = AssetExists(fontPath);
ImFontConfig fontConfig{};
fontConfig.SizePixels = std::floor(15.f * scale);
snprintf(static_cast<char*>(fontConfig.Name), sizeof(fontConfig.Name),
"Noto Mono Regular, %dpx", static_cast<int>(fontConfig.SizePixels));
ImGuiEngine::fontNormal =
hasFontFile ?
io.Fonts->AddFontFromFileTTF(fontPath.c_str(), fontConfig.SizePixels, &fontConfig) :
nullptr;
if (ImGuiEngine::fontNormal == nullptr) {
if (hasFontFile) {
DuskLog.warn("Failed to load font '{}': {}", fontPath, SDL_GetError());
}
ImGuiEngine::fontNormal = io.Fonts->AddFontDefault(&fontConfig);
}
fontConfig.SizePixels = std::floor(26.f * scale);
#ifdef IMGUI_ENABLE_FREETYPE
fontConfig.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_Bold;
snprintf(static_cast<char*>(fontConfig.Name), sizeof(fontConfig.Name), "Noto Mono Bold, %dpx",
static_cast<int>(fontConfig.SizePixels));
#else
snprintf(static_cast<char*>(fontConfig.Name), sizeof(fontConfig.Name),
"Noto Mono Regular, %dpx", static_cast<int>(fontConfig.SizePixels));
#endif
CreateFont(std::floor(18.f * scale), GetAssetPath("Inter-Regular.ttf"), "Inter Regular");
ImGuiEngine::fontLarge =
hasFontFile ?
io.Fonts->AddFontFromFileTTF(fontPath.c_str(), fontConfig.SizePixels, &fontConfig) :
nullptr;
if (ImGuiEngine::fontLarge == nullptr) {
if (hasFontFile) {
DuskLog.warn("Failed to load font '{}': {}", fontPath, SDL_GetError());
}
ImGuiEngine::fontLarge = io.Fonts->AddFontDefault(&fontConfig);
}
ImGuiEngine::fontExtraLarge = CreateFont(std::floor(40.f * scale), hasFontFile, fontPath);
CreateFont(std::floor(26.f * scale), GetAssetPath("Inter-Regular.ttf"), "Inter Regular");
ImGuiEngine::fontExtraLarge =
CreateFont(std::floor(40.f * scale), GetAssetPath("Inter-Bold.ttf"), "Inter Bold");
ImGuiEngine::fontMono =
CreateFont(std::floor(16.f * scale), GetAssetPath("NotoMono-Regular.ttf"),
"Noto Mono Regular");
auto& style = ImGui::GetStyle();
style = {}; // Reset sizes
style.WindowPadding = ImVec2(15, 15);
style.WindowRounding = 5.0f;
style.FrameBorderSize = 1.f;
style.FramePadding = ImVec2(5, 5);
style.FramePadding = ImVec2(8, 5);
style.FrameRounding = 4.0f;
style.ItemSpacing = ImVec2(12, 8);
style.ItemInnerSpacing = ImVec2(8, 6);
style.IndentSpacing = 25.0f;
style.ScrollbarSize = 15.0f;
style.ScrollbarRounding = 9.0f;
style.GrabMinSize = 5.0f;
style.GrabRounding = 3.0f;
style.GrabMinSize = 20.0f;
style.GrabRounding = 5.0f;
style.PopupBorderSize = 1.f;
style.PopupRounding = 7.0;
style.TabBorderSize = 1.f;
@@ -169,25 +145,23 @@ void ImGuiEngine_Initialize(float scale) {
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
}
Icon GetIcon() {
const std::string iconPath = GetAssetPath("icon.png");
if (!AssetExists(iconPath)) {
Image GetImage(const std::string& path) {
if (!AssetExists(path)) {
return {};
}
SDL_Surface* loadedSurface = SDL_LoadPNG(iconPath.c_str());
SDL_Surface* loadedSurface = SDL_LoadPNG(path.c_str());
if (loadedSurface == nullptr) {
DuskLog.warn("Failed to load icon '{}': {}", iconPath, SDL_GetError());
DuskLog.warn("Failed to load image '{}': {}", path, SDL_GetError());
return {};
}
SDL_Surface* rgbaSurface = SDL_ConvertSurface(loadedSurface, SDL_PIXELFORMAT_RGBA32);
SDL_DestroySurface(loadedSurface);
if (rgbaSurface == nullptr) {
DuskLog.warn("Failed to convert icon '{}': {}", iconPath, SDL_GetError());
DuskLog.warn("Failed to convert image '{}': {}", path, SDL_GetError());
return {};
}
@@ -204,7 +178,7 @@ Icon GetIcon() {
}
SDL_DestroySurface(rgbaSurface);
return Icon{
return Image{
std::move(ptr),
size,
iconWidth,
@@ -213,15 +187,13 @@ Icon GetIcon() {
}
void ImGuiEngine_AddTextures() {
if (ImGuiEngine::duskIcon != 0)
return;
auto icon = GetIcon();
if (icon.data == nullptr || icon.width == 0 || icon.height == 0) {
ImGuiEngine::duskIcon = 0;
return;
if (ImGuiEngine::duskIcon == 0) {
auto icon = GetImage(GetAssetPath("icon.png"));
if (icon.data == nullptr || icon.width == 0 || icon.height == 0) {
ImGuiEngine::duskIcon = 0;
return;
}
ImGuiEngine::duskIcon = aurora_imgui_add_texture(icon.width, icon.height, icon.data.get());
}
ImGuiEngine::duskIcon = aurora_imgui_add_texture(icon.width, icon.height, icon.data.get());
}
} // namespace dusk
+3 -2
View File
@@ -10,17 +10,18 @@ public:
static ImFont* fontNormal;
static ImFont* fontLarge;
static ImFont* fontExtraLarge;
static ImFont* fontMono;
static ImTextureID duskIcon;
};
void ImGuiEngine_Initialize(float scale);
void ImGuiEngine_AddTextures();
struct Icon {
struct Image {
std::unique_ptr<uint8_t[]> data;
size_t size;
uint32_t width;
uint32_t height;
};
Icon GetIcon();
Image GetImage(std::string_view path);
} // namespace dusk
+1 -1
View File
@@ -16,7 +16,7 @@ namespace dusk {
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
ImGui::SetNextWindowBgAlpha(0.65f);
// ImGui::SetNextWindowBgAlpha(0.65f);
if (!ImGui::Begin("Map Loader", &m_showMapLoader, windowFlags)) {
ImGui::End();
+13 -10
View File
@@ -17,6 +17,8 @@
#include <aurora/gfx.h>
#include "dusk/main.h"
namespace dusk {
void ImGuiMenuGame::ToggleFullscreen() {
getSettings().video.enableFullscreen.setValue(!getSettings().video.enableFullscreen);
@@ -28,12 +30,6 @@ namespace dusk {
void ImGuiMenuGame::draw() {
if (ImGui::BeginMenu("Game")) {
if (ImGui::MenuItem("Reset", hotkeys::DO_RESET)) {
JUTGamePad::C3ButtonReset::sResetSwitchPushing = true;
}
ImGui::Separator();
if (ImGui::BeginMenu("Graphics")) {
if (ImGui::MenuItem("Toggle Fullscreen", hotkeys::TOGGLE_FULLSCREEN)) {
ToggleFullscreen();
@@ -113,11 +109,18 @@ namespace dusk {
ImGui::EndMenu();
}
ImGui::Separator();
if (ImGui::MenuItem("Reset", hotkeys::DO_RESET)) {
JUTGamePad::C3ButtonReset::sResetSwitchPushing = true;
}
if (ImGui::MenuItem("Exit")) {
dusk::IsRunning = false;
}
ImGui::EndMenu();
}
windowInputViewer();
windowControllerConfig();
}
static void drawVirtualStick(const char* id, const ImVec2& stick) {
@@ -182,7 +185,7 @@ namespace dusk {
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_AlwaysAutoResize;
ImGui::SetNextWindowBgAlpha(0.65f);
// ImGui::SetNextWindowBgAlpha(0.65f);
if (!ImGui::Begin("Controller Config", &m_showControllerConfig, windowFlags)) {
ImGui::End();
+41 -52
View File
@@ -7,22 +7,22 @@
#include "ImGuiConsole.hpp"
#include "ImGuiMenuTools.hpp"
#include "ImGuiEngine.hpp"
#include "d/actor/d_a_alink.h"
#include "d/actor/d_a_horse.h"
#include "d/d_com_inf_game.h"
#include "dusk/main.h"
#include "dusk/dusk.h"
#include "dusk/main.h"
#include "m_Do/m_Do_main.h"
namespace dusk {
ImGuiMenuTools::ImGuiMenuTools() {}
void ImGuiMenuTools::draw() {
bool isToggleDevelopmentMode = false;
if (ImGui::BeginMenu("Debug")) {
if (ImGui::Checkbox("Development Mode", &m_isDevelopmentMode)) {
isToggleDevelopmentMode = true;
bool developmentMode = mDoMain::developmentMode == 1;
if (ImGui::Checkbox("Development Mode", &developmentMode)) {
mDoMain::developmentMode = developmentMode ? 1 : -1;
}
ImGui::Separator();
@@ -41,40 +41,27 @@ namespace dusk {
ImGui::EndMenu();
}
if (dusk::IsGameLaunched) {
ImGui::MenuItem("Process Management", hotkeys::SHOW_PROCESS_MANAGEMENT, &m_showProcessManagement);
ImGui::MenuItem("Debug Overlay", hotkeys::SHOW_DEBUG_OVERLAY, &m_showDebugOverlay);
ImGui::MenuItem("Heap Viewer", hotkeys::SHOW_HEAP_VIEWER, &m_showHeapOverlay);
ImGui::MenuItem("Stub Log", hotkeys::SHOW_STUB_LOG, &m_showStubLog);
ImGui::MenuItem("Debug Camera", hotkeys::SHOW_CAMERA_DEBUG, &m_showCameraOverlay);
ImGui::MenuItem("Map Loader", nullptr, &m_showMapLoader);
ImGui::MenuItem("Player Info", nullptr, &m_showPlayerInfo);
ImGui::MenuItem("Save Editor", nullptr, &m_showSaveEditor);
ImGui::MenuItem("Audio Debug", hotkeys::SHOW_AUDIO_DEBUG, &m_showAudioDebug);
if (!dusk::IsGameLaunched) {
ImGui::BeginDisabled();
}
ImGui::MenuItem("Process Management", hotkeys::SHOW_PROCESS_MANAGEMENT, &m_showProcessManagement);
ImGui::MenuItem("Debug Overlay", hotkeys::SHOW_DEBUG_OVERLAY, &m_showDebugOverlay);
ImGui::MenuItem("Heap Viewer", hotkeys::SHOW_HEAP_VIEWER, &m_showHeapOverlay);
ImGui::MenuItem("Stub Log", hotkeys::SHOW_STUB_LOG, &m_showStubLog);
ImGui::MenuItem("Debug Camera", hotkeys::SHOW_CAMERA_DEBUG, &m_showCameraOverlay);
ImGui::MenuItem("Map Loader", nullptr, &m_showMapLoader);
ImGui::MenuItem("Player Info", nullptr, &m_showPlayerInfo);
ImGui::MenuItem("Save Editor", nullptr, &m_showSaveEditor);
ImGui::MenuItem("Audio Debug", hotkeys::SHOW_AUDIO_DEBUG, &m_showAudioDebug);
if (!dusk::IsGameLaunched) {
ImGui::EndDisabled();
}
ImGui::MenuItem("OSReport Force", nullptr, &OSReportReallyForceEnable);
ImGui::EndMenu();
}
if (isToggleDevelopmentMode) {
mDoMain::developmentMode = m_isDevelopmentMode ? 1 : -1;
}
ShowDebugOverlay();
ShowCameraOverlay();
ShowProcessManager();
ShowHeapOverlay();
ShowStubLog();
ShowMapLoader();
ShowPlayerInfo();
ShowAudioDebug();
if (m_showSaveEditor) {
m_saveEditor.draw(m_showSaveEditor);
}
DuskDebugPad(); // temporary, remove later
}
void ImGuiMenuTools::ShowDebugOverlay() {
@@ -82,6 +69,8 @@ namespace dusk {
return;
}
ImGui::PushFont(ImGuiEngine::fontMono);
ImGuiIO& io = ImGui::GetIO();
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration |
ImGuiWindowFlags_AlwaysAutoResize |
@@ -94,26 +83,14 @@ namespace dusk {
ImGui::SetNextWindowBgAlpha(0.65f);
if (ImGui::Begin("Debug Overlay", nullptr, windowFlags)) {
bool hasPrevious = false;
if (hasPrevious) {
ImGui::Separator();
}
hasPrevious = true;
ImGuiStringViewText(fmt::format(FMT_STRING("FPS: {:.2f}\n"), io.Framerate));
ImGuiStringViewText(fmt::format(FMT_STRING("Frame usage: {:.1f}%\n"), frameUsagePct));
if (hasPrevious) {
ImGui::Separator();
}
hasPrevious = true;
ImGui::Separator();
ImGuiStringViewText(fmt::format(FMT_STRING("Backend: {}\n"), backend_name(aurora_get_backend())));
if (hasPrevious) {
ImGui::Separator();
}
hasPrevious = true;
ImGui::Separator();
const auto& stats = lastFrameAuroraStats;
@@ -145,6 +122,8 @@ namespace dusk {
ShowCornerContextMenu(m_debugOverlayCorner, m_cameraOverlayCorner);
}
ImGui::End();
ImGui::PopFont();
}
void ImGuiMenuTools::ShowPlayerInfo() {
@@ -152,13 +131,20 @@ namespace dusk {
return;
}
ImGuiIO& io = ImGui::GetIO();
ImGuiWindowFlags windowFlags =
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize;
ImGui::PushFont(ImGuiEngine::fontMono);
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration |
ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoNav;
if (m_playerInfoOverlayCorner != -1) {
SetOverlayWindowLocation(m_playerInfoOverlayCorner);
windowFlags |= ImGuiWindowFlags_NoMove;
}
ImGui::SetNextWindowBgAlpha(0.65f);
if (ImGui::Begin("Player Info", &m_showPlayerInfo, windowFlags)) {
if (ImGui::Begin("Player Info", nullptr, windowFlags)) {
daAlink_c* player = (daAlink_c*)dComIfGp_getPlayer(0);
daHorse_c* horse = dComIfGp_getHorseActor();
@@ -200,8 +186,11 @@ namespace dusk {
? fmt::format("Speed: {0}\n", horse->speedF)
: "Speed: ?\n"
);
ShowCornerContextMenu(m_playerInfoOverlayCorner, m_debugOverlayCorner);
}
ImGui::End();
ImGui::PopFont();
}
}
+2 -1
View File
@@ -22,6 +22,7 @@ namespace dusk {
void ShowMapLoader();
void ShowPlayerInfo();
void ShowAudioDebug();
void ShowSaveEditor();
private:
bool m_showDebugOverlay = false;
@@ -51,8 +52,8 @@ namespace dusk {
bool showInternalNames = false;
} m_mapLoaderInfo;
bool m_isDevelopmentMode = false;
bool m_showPlayerInfo = false;
int m_playerInfoOverlayCorner = 1; // top-right
bool m_showSaveEditor = false;
ImGuiSaveEditor m_saveEditor;
+57 -48
View File
@@ -19,10 +19,7 @@ namespace dusk {
typedef void (ImGuiPreLaunchWindow::*drawFunc)();
drawFunc drawTable[2] = {
&ImGuiPreLaunchWindow::drawMainMenu,
&ImGuiPreLaunchWindow::drawOptions
};
drawFunc drawTable[2] = {&ImGuiPreLaunchWindow::drawMainMenu, &ImGuiPreLaunchWindow::drawOptions};
static constexpr std::array<SDL_DialogFileFilter, 2> skGameDiscFileFilters{{
{"Game Disc Images", "iso;gcm;ciso;gcz;nfs;rvz;wbfs;wia;tgc"},
@@ -47,10 +44,7 @@ void fileDialogCallback(void* userdata, const char* const* filelist, [[maybe_unu
}
}
ImGuiPreLaunchWindow::ImGuiPreLaunchWindow() {
}
ImGuiPreLaunchWindow::ImGuiPreLaunchWindow() = default;
bool ImGuiPreLaunchWindow::isSelectedPathValid() const {
return !m_selectedIsoPath.empty() && SDL_GetPathInfo(m_selectedIsoPath.c_str(), nullptr);
@@ -59,6 +53,7 @@ bool ImGuiPreLaunchWindow::isSelectedPathValid() const {
void ImGuiPreLaunchWindow::draw() {
if (m_IsFirstDraw) {
m_selectedIsoPath = getSettings().backend.isoPath;
m_initialGraphicsBackend = getSettings().backend.graphicsBackend;
m_IsFirstDraw = false;
}
@@ -71,20 +66,23 @@ void ImGuiPreLaunchWindow::draw() {
ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y));
ImGui::SetNextWindowPos(ImVec2(0, 0));
ImGui::SetNextWindowBgAlpha(0.65f);
ImGui::Begin("Pre Launch Window", nullptr, ImGuiWindowFlags_NoDecoration |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus);
ImGui::Begin("Pre Launch Window", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoBringToFrontOnFocus);
const auto& windowSize = ImGui::GetWindowSize();
for (int i = 0; i < 5; i++)
ImGui::NewLine();
float iconSize = 128.f;
float iconSize = 150.f;
ImGui::SameLine(windowSize.x / 2 - iconSize + (iconSize / 2));
if (ImGuiEngine::duskIcon != 0)
ImGui::Image(ImGuiEngine::duskIcon, ImVec2{iconSize, iconSize});
ImGuiTextCenter("Twilit Realm presents");
ImGui::PushFont(ImGuiEngine::fontExtraLarge);
ImGuiTextCenter("Dusk");
ImGui::PopFont();
@@ -96,52 +94,27 @@ void ImGuiPreLaunchWindow::draw() {
void ImGuiPreLaunchWindow::drawMainMenu() {
const auto& windowSize = ImGui::GetWindowSize();
static const char* popopModalLabel = "Skip Pre-Launch UI?";
ImGui::SetCursorPosY(windowSize.y - 200);
ImGui::PushFont(ImGuiEngine::fontLarge);
bool disabled = false;
if (m_selectedIsoPath.empty() || !SDL_GetPathInfo(m_selectedIsoPath.c_str(), nullptr)) {
ImGui::BeginDisabled();
disabled = true;
}
if (ImGuiButtonCenter("Start Game")) {
if (!getSettings().backend.skipPreLaunchUI) {
ImGui::OpenPopup(popopModalLabel);
}else {
if (ImGuiButtonCenter("Select disc image...")) {
SDL_ShowOpenFileDialog(&fileDialogCallback, this, aurora::window::get_sdl_window(),
skGameDiscFileFilters.data(), int(skGameDiscFileFilters.size()),
nullptr, false);
}
} else {
if (ImGuiButtonCenter("Start game")) {
dusk::IsGameLaunched = true;
}
}
if (disabled) {
ImGui::EndDisabled();
}
if (ImGuiButtonCenter("Options")) {
m_CurMenu = 1;
}
ImGui::PopFont();
if (ImGui::BeginPopupModal(popopModalLabel, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Would you like to skip this menu on future launches?");
ImGui::Separator();
if (ImGui::Button("Yes", ImVec2(120, 0))) {
getSettings().backend.skipPreLaunchUI.setValue(true);
config::Save();
ImGui::CloseCurrentPopup();
dusk::IsGameLaunched = true;
}
ImGui::SameLine();
if (ImGui::Button("No", ImVec2(120, 0))) {
ImGui::CloseCurrentPopup();
dusk::IsGameLaunched = true;
}
ImGui::EndPopup();
}
}
void ImGuiPreLaunchWindow::drawOptions() {
@@ -160,12 +133,48 @@ void ImGuiPreLaunchWindow::drawOptions() {
float childWidth = windowSize.x - 400;
ImGui::SetCursorPosX(windowSize.x / 2 - (childWidth / 2));
if (ImGui::BeginChild("OptionsChild", ImVec2(childWidth, endCursorY - cursorY), ImGuiChildFlags_None, ImGuiWindowFlags_NoBackground)) {
if (ImGui::BeginChild("OptionsChild", ImVec2(childWidth, endCursorY - cursorY),
ImGuiChildFlags_None, ImGuiWindowFlags_NoBackground))
{
ImGui::InputText("Game ISO Path", &m_selectedIsoPath, ImGuiInputTextFlags_ReadOnly);
ImGui::SameLine();
if (ImGui::Button("Set")) {
SDL_ShowOpenFileDialog(&fileDialogCallback, this, aurora::window::get_sdl_window(), skGameDiscFileFilters.data(),
int(skGameDiscFileFilters.size()), nullptr, false);
SDL_ShowOpenFileDialog(&fileDialogCallback, this, aurora::window::get_sdl_window(),
skGameDiscFileFilters.data(), int(skGameDiscFileFilters.size()),
nullptr, false);
}
AuroraBackend configuredBackend = BACKEND_AUTO;
const std::string& configuredBackendId = getSettings().backend.graphicsBackend;
if (!try_parse_backend(configuredBackendId, configuredBackend)) {
configuredBackend = BACKEND_AUTO;
}
if (ImGui::BeginCombo("Graphics Backend", backend_name(configuredBackend).data())) {
if (ImGui::Selectable("Auto", configuredBackend == BACKEND_AUTO)) {
getSettings().backend.graphicsBackend.setValue("auto");
config::Save();
}
size_t backendCount = 0;
const AuroraBackend* availableBackends = aurora_get_available_backends(&backendCount);
for (size_t i = 0; i < backendCount; ++i) {
const AuroraBackend backend = availableBackends[i];
const bool isSelected = configuredBackend == backend;
if (ImGui::Selectable(backend_name(backend).data(), isSelected)) {
getSettings().backend.graphicsBackend.setValue(
std::string(backend_id(backend)));
config::Save();
}
if (isSelected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
if (configuredBackendId != m_initialGraphicsBackend) {
ImGui::TextDisabled("Restart Required");
}
ImGui::EndChild();
}
@@ -182,4 +191,4 @@ void ImGuiPreLaunchWindow::drawOptions() {
ImGui::PopFont();
}
}
} // namespace dusk
+2 -1
View File
@@ -5,6 +5,7 @@ class ImGuiPreLaunchWindow {
private:
int m_CurMenu = 0;
bool m_IsFirstDraw = true;
std::string m_initialGraphicsBackend;
bool isSelectedPathValid() const;
@@ -18,4 +19,4 @@ public:
std::string m_selectedIsoPath;
std::string m_errorString;
};
} // namespace dusk
} // namespace dusk
+1 -1
View File
@@ -287,7 +287,7 @@ namespace dusk {
ImGuiWindowFlags windowFlags =
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize;
ImGui::SetNextWindowBgAlpha(0.65f);
// ImGui::SetNextWindowBgAlpha(0.65f);
if (ImGui::Begin("Save Editor", &open, windowFlags)) {
if (ImGui::BeginTabBar("SaveEditorTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
+2
View File
@@ -61,6 +61,7 @@ UserSettings g_userSettings = {
.backend = {
.isoPath {"backend.isoPath", ""},
.graphicsBackend {"backend.graphicsBackend", "auto"},
.skipPreLaunchUI {"backend.skipPreLaunchUI", false}
}
};
@@ -110,6 +111,7 @@ void registerSettings() {
Register(g_userSettings.game.fastSpinner);
Register(g_userSettings.backend.isoPath);
Register(g_userSettings.backend.graphicsBackend);
Register(g_userSettings.backend.skipPreLaunchUI);
}
+57 -38
View File
@@ -61,6 +61,7 @@
#include "SDL3/SDL_filesystem.h"
#include "cxxopts.hpp"
#include "dusk/audio/DuskAudioSystem.h"
#include "dusk/config.hpp"
#include "dusk/imgui/ImGuiConsole.hpp"
#include "tracy/Tracy.hpp"
@@ -83,6 +84,7 @@ const int audioHeapSize = 0x14D800;
#define COPYDATE_PATH "/str/Final/Release/COPYDATE"
#if TARGET_PC
bool dusk::IsRunning = true;
bool dusk::IsShuttingDown = false;
bool dusk::IsGameLaunched = false;
#endif
@@ -122,7 +124,7 @@ const char* configPath;
AuroraWindowSize preLaunchUIWindowSize;
bool launchUILoop() {
while (!dusk::IsGameLaunched) {
while (dusk::IsRunning && !dusk::IsGameLaunched) {
const AuroraEvent* event = aurora_update();
while (event != nullptr && event->type != AURORA_NONE) {
switch (event->type) {
@@ -151,9 +153,7 @@ bool launchUILoop() {
aurora_end_frame();
}
DuskLog.info("Game Launched!");
return true;
return dusk::IsRunning;
}
void main01(void) {
@@ -244,42 +244,52 @@ void main01(void) {
aurora_end_frame();
FrameMark;
} while (true);
} while (dusk::IsRunning);
exit:;
}
static AuroraBackend ParseAuroraBackend(const std::string& value) {
if (value == "auto") {
return BACKEND_AUTO;
}
if (value == "d3d11") {
return BACKEND_D3D11;
}
if (value == "d3d12") {
return BACKEND_D3D12;
}
if (value == "metal") {
return BACKEND_METAL;
}
if (value == "vulkan") {
return BACKEND_VULKAN;
}
if (value == "opengl") {
return BACKEND_OPENGL;
}
if (value == "opengles") {
return BACKEND_OPENGLES;
}
if (value == "webgpu") {
return BACKEND_WEBGPU;
}
if (value == "null") {
return BACKEND_NULL;
static bool IsBackendAvailable(AuroraBackend backend) {
if (backend == BACKEND_AUTO) {
return true;
}
fmt::print(stderr, "Unknown backend: {}", value);
exit(1);
size_t availableBackendCount = 0;
const AuroraBackend* availableBackends = aurora_get_available_backends(&availableBackendCount);
for (size_t i = 0; i < availableBackendCount; ++i) {
if (availableBackends[i] == backend) {
return true;
}
}
return false;
}
static AuroraBackend ResolveDesiredBackend(const cxxopts::ParseResult& parsedArgOptions) {
AuroraBackend desiredBackend = BACKEND_AUTO;
if (parsedArgOptions.count("backend") != 0) {
const std::string backendArg = parsedArgOptions["backend"].as<std::string>();
if (!dusk::try_parse_backend(backendArg, desiredBackend)) {
fmt::print(stderr, "Unknown backend: {}\n", backendArg);
exit(1);
}
} else if (!dusk::try_parse_backend(
static_cast<const std::string&>(dusk::getSettings().backend.graphicsBackend),
desiredBackend))
{
DuskLog.warn("Unknown configured backend '{}', falling back to Auto",
static_cast<const std::string&>(dusk::getSettings().backend.graphicsBackend));
desiredBackend = BACKEND_AUTO;
}
if (!IsBackendAvailable(desiredBackend)) {
DuskLog.warn("Requested backend '{}' is unavailable, falling back to Auto",
dusk::backend_name(desiredBackend));
desiredBackend = BACKEND_AUTO;
}
return desiredBackend;
}
static void aurora_imgui_init_callback(const AuroraWindowSize* size) {
@@ -372,7 +382,7 @@ int game_main(int argc, char* argv[]) {
("l,log-level", "Log level from " + std::to_string(AuroraLogLevel::LOG_DEBUG) + " to " + std::to_string(AuroraLogLevel::LOG_FATAL), cxxopts::value<uint8_t>()->default_value("0"))
("h,help", "Print usage")
("dvd", "Path to DVD image file", cxxopts::value<std::string>()->default_value("game.iso"))
("backend", "Graphics API backend to use (auto, d3d11, d3d12, metal, vulkan, opengl, opengles, webgpu, null)", cxxopts::value<std::string>()->default_value("auto"))
("backend", "Graphics API backend to use (auto, d3d12, metal, vulkan, null)", cxxopts::value<std::string>())
("cvar", "Override configuration variables without modifying config", cxxopts::value<std::vector<std::string>>());
arg_options.parse_positional({"dvd"});
@@ -406,7 +416,7 @@ int game_main(int argc, char* argv[]) {
config.windowPosY = -1;
config.windowWidth = defaultWindowWidth * 2;
config.windowHeight = defaultWindowHeight * 2;
config.desiredBackend = ParseAuroraBackend(parsed_arg_options["backend"].as<std::string>());
config.desiredBackend = ResolveDesiredBackend(parsed_arg_options);
config.logCallback = &aurora_log_callback;
config.logLevel = (AuroraLogLevel)parsed_arg_options["log-level"].as<uint8_t>();
config.mem1Size = 256 * 1024 * 1024;
@@ -420,7 +430,16 @@ int game_main(int argc, char* argv[]) {
VISetWindowTitle(
fmt::format("Dusk {} [{}]", DUSK_WC_DESCRIBE, dusk::backend_name(auroraInfo.backend))
.c_str());
.c_str());
if (dusk::getSettings().video.lockAspectRatio) {
VILockAspectRatio(defaultAspectRatioW, defaultAspectRatioH);
} else {
VIUnlockAspectRatio();
}
dusk::audio::SetMasterVolume(dusk::getSettings().audio.masterVolume / 100.0f);
dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb);
// pre game launch ui main loop
if (!launchUILoop()) {
@@ -431,7 +450,7 @@ int game_main(int argc, char* argv[]) {
std::string dvd_path;
if (parsed_arg_options.count("dvd")) {
dvd_path = parsed_arg_options["dvd"].as<std::string>();
}else {
} else {
dvd_path = dusk::getSettings().backend.isoPath;
if (dvd_path.empty()) {