mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-12-30 15:50:05 -06:00
Implemented mock reddog window manager
Requires micross.ttf font in game root and ENABLE_IM_FONT_ATLAS_SNAPSHOT undefined, not currently in the font atlas.
This commit is contained in:
@@ -163,7 +163,14 @@ set(SWA_PATCHES_CXX_SOURCES
|
||||
"patches/video_patches.cpp"
|
||||
)
|
||||
|
||||
set(SWA_UI_CXX_SOURCES
|
||||
set(SWA_UI_CXX_SOURCES
|
||||
"ui/reddog/windows/counter_window.cpp"
|
||||
"ui/reddog/windows/exports_window.cpp"
|
||||
"ui/reddog/windows/view_window.cpp"
|
||||
"ui/reddog/windows/window_list.cpp"
|
||||
"ui/reddog/reddog_controls.cpp"
|
||||
"ui/reddog/reddog_manager.cpp"
|
||||
"ui/reddog/reddog_window.cpp"
|
||||
"ui/achievement_menu.cpp"
|
||||
"ui/achievement_overlay.cpp"
|
||||
"ui/installer_wizard.cpp"
|
||||
@@ -453,6 +460,22 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/co
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/kbm.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/kbm.dds" ARRAY_NAME "g_kbm" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fade.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fade.dds" ARRAY_NAME "g_select_fade" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fill.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fill.dds" ARRAY_NAME "g_select_fill" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_close_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_close_1.dds" ARRAY_NAME "g_button_close_1")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_close_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_close_2.dds" ARRAY_NAME "g_button_close_2")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_minimum_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_minimum_1.dds" ARRAY_NAME "g_button_minimum_1")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_minimum_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_minimum_2.dds" ARRAY_NAME "g_button_minimum_2")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_pin_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_pin_1.dds" ARRAY_NAME "g_button_pin_1")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_pin_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_pin_2.dds" ARRAY_NAME "g_button_pin_2")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/checkbox_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/checkbox_1.dds" ARRAY_NAME "g_checkbox_1")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/checkbox_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/checkbox_2.dds" ARRAY_NAME "g_checkbox_2")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/debug_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/debug_icon.dds" ARRAY_NAME "g_debug_icon")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/common_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/common_icon.dds" ARRAY_NAME "g_common_icon")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor.bmp" ARRAY_NAME "g_mouse_cursor")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor_h.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor_h.bmp" ARRAY_NAME "g_mouse_cursor_h")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor_slant_l.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor_slant_l.bmp" ARRAY_NAME "g_mouse_cursor_slant_l")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor_slant_r.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor_slant_r.bmp" ARRAY_NAME "g_mouse_cursor_slant_r")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor_v.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor_v.bmp" ARRAY_NAME "g_mouse_cursor_v")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/title_bar.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/title_bar.dds" ARRAY_NAME "g_title_bar")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/arrow_circle.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/arrow_circle.dds" ARRAY_NAME "g_arrow_circle" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_001.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_001.dds" ARRAY_NAME "g_install_001" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_002.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_002.dds" ARRAY_NAME "g_install_002" COMPRESSION_TYPE "zstd")
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <res/font/im_font_atlas.dds.h>
|
||||
#include <shader/shader_cache.h>
|
||||
#include <SWA.h>
|
||||
#include <ui/reddog/reddog_manager.h>
|
||||
#include <ui/achievement_menu.h>
|
||||
#include <ui/achievement_overlay.h>
|
||||
#include <ui/button_guide.h>
|
||||
@@ -1186,9 +1187,16 @@ static void CreateImGuiBackend()
|
||||
AchievementMenu::Init();
|
||||
AchievementOverlay::Init();
|
||||
ButtonGuide::Init();
|
||||
InstallerWizard::Init();
|
||||
MessageWindow::Init();
|
||||
OptionsMenu::Init();
|
||||
InstallerWizard::Init();
|
||||
|
||||
#if !_DEBUG
|
||||
if (Config::Debug)
|
||||
#endif
|
||||
{
|
||||
Reddog::Manager::Init();
|
||||
}
|
||||
|
||||
ImGui_ImplSDL2_InitForOther(GameWindow::s_pWindow);
|
||||
|
||||
@@ -1943,82 +1951,58 @@ static double g_applicationValues[PROFILER_VALUE_COUNT];
|
||||
static Profiler g_presentProfiler;
|
||||
static Profiler g_renderDirectorProfiler;
|
||||
|
||||
static bool g_profilerVisible;
|
||||
static bool g_profilerWasToggled;
|
||||
|
||||
static void DrawProfiler()
|
||||
void Video::DrawCounter()
|
||||
{
|
||||
bool toggleProfiler = SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_F1] != 0;
|
||||
g_applicationValues[g_profilerValueIndex] = App::s_deltaTime * 1000.0;
|
||||
|
||||
if (!g_profilerWasToggled && toggleProfiler)
|
||||
g_profilerVisible = !g_profilerVisible;
|
||||
const double applicationAvg = std::accumulate(g_applicationValues, g_applicationValues + PROFILER_VALUE_COUNT, 0.0) / PROFILER_VALUE_COUNT;
|
||||
double presentAvg = g_presentProfiler.UpdateAndReturnAverage();
|
||||
double renderDirectorAvg = g_renderDirectorProfiler.UpdateAndReturnAverage();
|
||||
|
||||
g_profilerWasToggled = toggleProfiler;
|
||||
|
||||
if (!g_profilerVisible)
|
||||
return;
|
||||
|
||||
ImFont* font = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
|
||||
float defaultScale = font->Scale;
|
||||
font->Scale = ImGui::GetDefaultFont()->FontSize / font->FontSize;
|
||||
ImGui::PushFont(font);
|
||||
|
||||
if (ImGui::Begin("Profiler", &g_profilerVisible))
|
||||
if (ImPlot::BeginPlot("Frame Time"))
|
||||
{
|
||||
g_applicationValues[g_profilerValueIndex] = App::s_deltaTime * 1000.0;
|
||||
|
||||
const double applicationAvg = std::accumulate(g_applicationValues, g_applicationValues + PROFILER_VALUE_COUNT, 0.0) / PROFILER_VALUE_COUNT;
|
||||
double presentAvg = g_presentProfiler.UpdateAndReturnAverage();
|
||||
double renderDirectorAvg = g_renderDirectorProfiler.UpdateAndReturnAverage();
|
||||
|
||||
if (ImPlot::BeginPlot("Frame Time"))
|
||||
{
|
||||
ImPlot::SetupAxisLimits(ImAxis_Y1, 0.0, 20.0);
|
||||
ImPlot::SetupAxis(ImAxis_Y1, "ms", ImPlotAxisFlags_None);
|
||||
ImPlot::PlotLine<double>("Application", g_applicationValues, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
|
||||
ImPlot::PlotLine<double>("Present", g_presentProfiler.values, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
|
||||
ImPlot::PlotLine<double>("Render Director", g_renderDirectorProfiler.values, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
|
||||
g_profilerValueIndex = (g_profilerValueIndex + 1) % PROFILER_VALUE_COUNT;
|
||||
|
||||
ImGui::Text("Current Application: %g ms (%g FPS)", App::s_deltaTime * 1000.0, 1.0 / App::s_deltaTime);
|
||||
ImGui::Text("Current Present: %g ms (%g FPS)", g_presentProfiler.value.load(), 1000.0 / g_presentProfiler.value.load());
|
||||
ImGui::Text("Current Render Director: %g ms (%g FPS)", g_renderDirectorProfiler.value.load(), 1000.0 / g_renderDirectorProfiler.value.load());
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Text("Average Application: %g ms (%g FPS)", applicationAvg, 1000.0 / applicationAvg);
|
||||
ImGui::Text("Average Present: %g ms (%g FPS)", presentAvg, 1000.0 / presentAvg);
|
||||
ImGui::Text("Average Render Director: %g ms (%g FPS)", renderDirectorAvg, 1000.0 / renderDirectorAvg);
|
||||
ImGui::NewLine();
|
||||
|
||||
O1HeapDiagnostics diagnostics, physicalDiagnostics;
|
||||
{
|
||||
std::lock_guard lock(g_userHeap.mutex);
|
||||
diagnostics = o1heapGetDiagnostics(g_userHeap.heap);
|
||||
}
|
||||
{
|
||||
std::lock_guard lock(g_userHeap.physicalMutex);
|
||||
physicalDiagnostics = o1heapGetDiagnostics(g_userHeap.physicalHeap);
|
||||
}
|
||||
|
||||
ImGui::Text("Heap Allocated: %d MB", int32_t(diagnostics.allocated / (1024 * 1024)));
|
||||
ImGui::Text("Physical Heap Allocated: %d MB", int32_t(physicalDiagnostics.allocated / (1024 * 1024)));
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Text("Present Wait: %s", g_capabilities.presentWait ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Triangle Fan: %s", g_capabilities.triangleFan ? "Supported" : "Unsupported");
|
||||
ImGui::NewLine();
|
||||
|
||||
const char* sdlVideoDriver = SDL_GetCurrentVideoDriver();
|
||||
if (sdlVideoDriver != nullptr)
|
||||
ImGui::Text("SDL Video Driver: %s", sdlVideoDriver);
|
||||
ImPlot::SetupAxisLimits(ImAxis_Y1, 0.0, 20.0);
|
||||
ImPlot::SetupAxis(ImAxis_Y1, "ms", ImPlotAxisFlags_None);
|
||||
ImPlot::PlotLine<double>("Application", g_applicationValues, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
|
||||
ImPlot::PlotLine<double>("Present", g_presentProfiler.values, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
|
||||
ImPlot::PlotLine<double>("Render Director", g_renderDirectorProfiler.values, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
ImGui::PopFont();
|
||||
font->Scale = defaultScale;
|
||||
g_profilerValueIndex = (g_profilerValueIndex + 1) % PROFILER_VALUE_COUNT;
|
||||
|
||||
ImGui::Text("Current Application: %g ms (%g FPS)", App::s_deltaTime * 1000.0, 1.0 / App::s_deltaTime);
|
||||
ImGui::Text("Current Present: %g ms (%g FPS)", g_presentProfiler.value.load(), 1000.0 / g_presentProfiler.value.load());
|
||||
ImGui::Text("Current Render Director: %g ms (%g FPS)", g_renderDirectorProfiler.value.load(), 1000.0 / g_renderDirectorProfiler.value.load());
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Text("Average Application: %g ms (%g FPS)", applicationAvg, 1000.0 / applicationAvg);
|
||||
ImGui::Text("Average Present: %g ms (%g FPS)", presentAvg, 1000.0 / presentAvg);
|
||||
ImGui::Text("Average Render Director: %g ms (%g FPS)", renderDirectorAvg, 1000.0 / renderDirectorAvg);
|
||||
ImGui::NewLine();
|
||||
|
||||
O1HeapDiagnostics diagnostics, physicalDiagnostics;
|
||||
{
|
||||
std::lock_guard lock(g_userHeap.mutex);
|
||||
diagnostics = o1heapGetDiagnostics(g_userHeap.heap);
|
||||
}
|
||||
{
|
||||
std::lock_guard lock(g_userHeap.physicalMutex);
|
||||
physicalDiagnostics = o1heapGetDiagnostics(g_userHeap.physicalHeap);
|
||||
}
|
||||
|
||||
ImGui::Text("Heap Allocated: %d MB", int32_t(diagnostics.allocated / (1024 * 1024)));
|
||||
ImGui::Text("Physical Heap Allocated: %d MB", int32_t(physicalDiagnostics.allocated / (1024 * 1024)));
|
||||
ImGui::NewLine();
|
||||
|
||||
auto capabilities = g_device->getCapabilities();
|
||||
ImGui::Text("Present Wait: %s", capabilities.presentWait ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Triangle Fan: %s", capabilities.triangleFan ? "Supported" : "Unsupported");
|
||||
ImGui::NewLine();
|
||||
|
||||
const char* sdlVideoDriver = SDL_GetCurrentVideoDriver();
|
||||
if (sdlVideoDriver != nullptr)
|
||||
ImGui::Text("SDL Video Driver: %s", sdlVideoDriver);
|
||||
}
|
||||
|
||||
static void DrawImGui()
|
||||
@@ -2052,7 +2036,12 @@ static void DrawImGui()
|
||||
ButtonGuide::Draw();
|
||||
Fader::Draw();
|
||||
|
||||
DrawProfiler();
|
||||
#if !_DEBUG
|
||||
if (Config::Debug)
|
||||
#endif
|
||||
{
|
||||
Reddog::Manager::Draw();
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ struct Video
|
||||
static void Present();
|
||||
static void StartPipelinePrecompilation();
|
||||
static void WaitForGPU();
|
||||
static void DrawCounter();
|
||||
};
|
||||
|
||||
struct GuestSamplerState
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
#pragma comment(lib, "dwmapi.lib")
|
||||
#endif
|
||||
|
||||
#include <res/images/reddog/mouse_cursor.bmp.h>
|
||||
#include <res/images/reddog/mouse_cursor_h.bmp.h>
|
||||
#include <res/images/reddog/mouse_cursor_slant_l.bmp.h>
|
||||
#include <res/images/reddog/mouse_cursor_slant_r.bmp.h>
|
||||
#include <res/images/reddog/mouse_cursor_v.bmp.h>
|
||||
#include <res/images/game_icon.bmp.h>
|
||||
#include <res/images/game_icon_night.bmp.h>
|
||||
|
||||
@@ -105,7 +110,7 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
|
||||
GameWindow::s_isFocused = true;
|
||||
|
||||
if (GameWindow::IsFullscreen())
|
||||
SDL_ShowCursor(GameWindow::s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
SDL_ShowCursor(GameWindow::s_isCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -146,7 +151,7 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
|
||||
if (event->type == SDL_CONTROLLERBUTTONDOWN || event->type == SDL_CONTROLLERBUTTONUP || event->type == SDL_CONTROLLERAXISMOTION)
|
||||
{
|
||||
// Hide mouse cursor when controller input is detected.
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL_ShowCursor(GameWindow::s_isCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
}
|
||||
else if (event->type == SDL_MOUSEMOTION)
|
||||
{
|
||||
@@ -264,23 +269,23 @@ void GameWindow::Update()
|
||||
s_isChangingDisplay = false;
|
||||
}
|
||||
|
||||
SDL_Surface* GameWindow::GetIconSurface(void* pIconBmp, size_t iconSize)
|
||||
SDL_Surface* GameWindow::CreateSurface(void* pBitmapData, size_t bitmapSize)
|
||||
{
|
||||
auto rw = SDL_RWFromMem(pIconBmp, iconSize);
|
||||
auto rw = SDL_RWFromMem(pBitmapData, bitmapSize);
|
||||
auto surface = SDL_LoadBMP_RW(rw, 1);
|
||||
|
||||
if (!surface)
|
||||
LOGF_ERROR("Failed to load icon: {}", SDL_GetError());
|
||||
LOGF_ERROR("Failed to create surface: {}", SDL_GetError());
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
void GameWindow::SetIcon(void* pIconBmp, size_t iconSize)
|
||||
{
|
||||
if (auto icon = GetIconSurface(pIconBmp, iconSize))
|
||||
if (auto surface = CreateSurface(pIconBmp, iconSize))
|
||||
{
|
||||
SDL_SetWindowIcon(s_pWindow, icon);
|
||||
SDL_FreeSurface(icon);
|
||||
SDL_SetWindowIcon(s_pWindow, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +301,69 @@ void GameWindow::SetIcon(bool isNight)
|
||||
}
|
||||
}
|
||||
|
||||
void GameWindow::SetCursor(ECursorType cursorType)
|
||||
{
|
||||
if (s_currentCursor == cursorType)
|
||||
return;
|
||||
|
||||
s_currentCursor = cursorType;
|
||||
|
||||
uint8_t* pBitmapData;
|
||||
size_t bitmapSize;
|
||||
int x, y;
|
||||
|
||||
switch (cursorType)
|
||||
{
|
||||
case ECursorType::DebugDefault:
|
||||
pBitmapData = g_mouse_cursor;
|
||||
bitmapSize = sizeof(g_mouse_cursor);
|
||||
x = 0;
|
||||
y = 0;
|
||||
break;
|
||||
|
||||
case ECursorType::DebugHorizontal:
|
||||
pBitmapData = g_mouse_cursor_h;
|
||||
bitmapSize = sizeof(g_mouse_cursor_h);
|
||||
x = 15;
|
||||
y = 15;
|
||||
break;
|
||||
|
||||
case ECursorType::DebugVertical:
|
||||
pBitmapData = g_mouse_cursor_v;
|
||||
bitmapSize = sizeof(g_mouse_cursor_v);
|
||||
x = 15;
|
||||
y = 15;
|
||||
break;
|
||||
|
||||
case ECursorType::DebugLeftDiagonal:
|
||||
pBitmapData = g_mouse_cursor_slant_l;
|
||||
bitmapSize = sizeof(g_mouse_cursor_slant_l);
|
||||
x = 16;
|
||||
y = 15;
|
||||
break;
|
||||
|
||||
case ECursorType::DebugRightDiagonal:
|
||||
pBitmapData = g_mouse_cursor_slant_r;
|
||||
bitmapSize = sizeof(g_mouse_cursor_slant_r);
|
||||
x = 16;
|
||||
y = 15;
|
||||
break;
|
||||
|
||||
default:
|
||||
SDL_SetCursor(SDL_GetDefaultCursor());
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto surface = CreateSurface(pBitmapData, bitmapSize))
|
||||
{
|
||||
if (auto cursor = SDL_CreateColorCursor(surface, x, y))
|
||||
{
|
||||
SDL_SetCursor(cursor);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* GameWindow::GetTitle()
|
||||
{
|
||||
return Config::Language == ELanguage::Japanese
|
||||
@@ -338,7 +406,7 @@ bool GameWindow::SetFullscreen(bool isEnabled)
|
||||
if (isEnabled)
|
||||
{
|
||||
SDL_SetWindowFullscreen(s_pWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
SDL_ShowCursor(s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
SDL_ShowCursor(s_isCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -352,13 +420,13 @@ bool GameWindow::SetFullscreen(bool isEnabled)
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
void GameWindow::SetFullscreenCursorVisibility(bool isVisible)
|
||||
void GameWindow::SetCursorVisibility(bool isVisible)
|
||||
{
|
||||
s_isFullscreenCursorVisible = isVisible;
|
||||
s_isCursorVisible = isVisible;
|
||||
|
||||
if (IsFullscreen())
|
||||
{
|
||||
SDL_ShowCursor(s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
SDL_ShowCursor(s_isCursorVisible ? SDL_ENABLE : SDL_DISABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -9,6 +9,16 @@
|
||||
#define MIN_WIDTH 640
|
||||
#define MIN_HEIGHT 480
|
||||
|
||||
enum class ECursorType
|
||||
{
|
||||
Default,
|
||||
DebugDefault,
|
||||
DebugHorizontal,
|
||||
DebugVertical,
|
||||
DebugLeftDiagonal,
|
||||
DebugRightDiagonal
|
||||
};
|
||||
|
||||
class GameWindow
|
||||
{
|
||||
public:
|
||||
@@ -22,18 +32,21 @@ public:
|
||||
|
||||
static inline bool s_isFocused;
|
||||
static inline bool s_isIconNight;
|
||||
static inline bool s_isFullscreenCursorVisible;
|
||||
static inline bool s_isCursorVisible;
|
||||
static inline bool s_isChangingDisplay;
|
||||
|
||||
static SDL_Surface* GetIconSurface(void* pIconBmp, size_t iconSize);
|
||||
static inline ECursorType s_currentCursor;
|
||||
|
||||
static SDL_Surface* CreateSurface(void* pBitmapData, size_t bitmapSize);
|
||||
static void SetIcon(void* pIconBmp, size_t iconSize);
|
||||
static void SetIcon(bool isNight = false);
|
||||
static void SetCursor(ECursorType cursorType = ECursorType::Default);
|
||||
static const char* GetTitle();
|
||||
static void SetTitle(const char* title = nullptr);
|
||||
static void SetTitleBarColour();
|
||||
static bool IsFullscreen();
|
||||
static bool SetFullscreen(bool isEnabled);
|
||||
static void SetFullscreenCursorVisibility(bool isVisible);
|
||||
static void SetCursorVisibility(bool isVisible);
|
||||
static bool IsMaximised();
|
||||
static EWindowState SetMaximised(bool isEnabled);
|
||||
static SDL_Rect GetDimensions();
|
||||
|
||||
@@ -1557,7 +1557,7 @@ bool InstallerWizard::Run(std::filesystem::path installPath, bool skipGame)
|
||||
g_currentPage = g_firstPage;
|
||||
}
|
||||
|
||||
GameWindow::SetFullscreenCursorVisibility(true);
|
||||
GameWindow::SetCursorVisibility(true);
|
||||
s_isVisible = true;
|
||||
|
||||
while (s_isVisible)
|
||||
@@ -1569,7 +1569,7 @@ bool InstallerWizard::Run(std::filesystem::path installPath, bool skipGame)
|
||||
Video::Present();
|
||||
}
|
||||
|
||||
GameWindow::SetFullscreenCursorVisibility(false);
|
||||
GameWindow::SetCursorVisibility(false);
|
||||
NFD_Quit();
|
||||
|
||||
InstallerWizard::Shutdown();
|
||||
|
||||
59
UnleashedRecomp/ui/reddog/reddog_controls.cpp
Normal file
59
UnleashedRecomp/ui/reddog/reddog_controls.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "reddog_controls.h"
|
||||
#include <gpu/video.h>
|
||||
|
||||
#include <res/images/reddog/checkbox_1.dds.h>
|
||||
#include <res/images/reddog/checkbox_2.dds.h>
|
||||
|
||||
constexpr float CHECKBOX_SIZE = 16.0f;
|
||||
|
||||
static std::unique_ptr<GuestTexture> g_upCheckbox1;
|
||||
static std::unique_ptr<GuestTexture> g_upCheckbox2;
|
||||
|
||||
void Reddog::InitControlsResources()
|
||||
{
|
||||
g_upCheckbox1 = LoadTexture(g_checkbox_1, sizeof(g_checkbox_1));
|
||||
g_upCheckbox2 = LoadTexture(g_checkbox_2, sizeof(g_checkbox_2));
|
||||
}
|
||||
|
||||
bool Reddog::Checkbox(const char* label, bool* v)
|
||||
{
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
auto& ctx = *GImGui;
|
||||
auto& style = ctx.Style;
|
||||
auto id = window->GetID(label);
|
||||
auto labelSize = ImGui::CalcTextSize(label, nullptr, true);
|
||||
auto pos = window->DC.CursorPos;
|
||||
|
||||
ImVec2 size = { CHECKBOX_SIZE, CHECKBOX_SIZE };
|
||||
ImRect checkBoundingBox(pos, ImVec2(pos.x + size.x, pos.y + size.y));
|
||||
ImRect totalBoundingBox(pos, ImVec2(pos.x + size.x + (labelSize.x > 0.0f ? style.ItemInnerSpacing.x + labelSize.x : 0.0f), pos.y + size.y));
|
||||
|
||||
ImGui::ItemSize(totalBoundingBox, style.FramePadding.y);
|
||||
|
||||
if (!ImGui::ItemAdd(totalBoundingBox, id))
|
||||
return false;
|
||||
|
||||
bool isHovered, isHeld;
|
||||
bool isPressed = ImGui::ButtonBehavior(checkBoundingBox, id, &isHovered, &isHeld);
|
||||
|
||||
if (isPressed)
|
||||
{
|
||||
*v = !*v;
|
||||
ImGui::MarkItemEdited(id);
|
||||
}
|
||||
|
||||
auto texture = *v
|
||||
? g_upCheckbox2.get()
|
||||
: g_upCheckbox1.get();
|
||||
|
||||
window->DrawList->AddImage(texture, checkBoundingBox.Min, checkBoundingBox.Max);
|
||||
|
||||
if (labelSize.x > 0.0f)
|
||||
ImGui::RenderText({ checkBoundingBox.Max.x + style.ItemInnerSpacing.x, checkBoundingBox.Min.y + style.FramePadding.y }, label);
|
||||
|
||||
return isPressed;
|
||||
}
|
||||
7
UnleashedRecomp/ui/reddog/reddog_controls.h
Normal file
7
UnleashedRecomp/ui/reddog/reddog_controls.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace Reddog
|
||||
{
|
||||
void InitControlsResources();
|
||||
bool Checkbox(const char* label, bool* v);
|
||||
}
|
||||
146
UnleashedRecomp/ui/reddog/reddog_manager.cpp
Normal file
146
UnleashedRecomp/ui/reddog/reddog_manager.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include "reddog_manager.h"
|
||||
#include <gpu/video.h>
|
||||
#include <ui/reddog/windows/window_list.h>
|
||||
#include <ui/reddog/reddog_controls.h>
|
||||
#include <ui/game_window.h>
|
||||
#include <ui/imgui_utils.h>
|
||||
|
||||
#include <res/images/reddog/debug_icon.dds.h>
|
||||
|
||||
static std::unique_ptr<GuestTexture> g_upDebugIcon;
|
||||
|
||||
static ImVec2 g_debugIconPosOrig;
|
||||
static ImVec2 g_debugIconPos = { 0, 0 };
|
||||
|
||||
static bool g_isDebugIconClicked = false;
|
||||
static bool g_isDraggingDebugIcon = false;
|
||||
static bool g_isReddogToggled = false;
|
||||
static bool g_isWindowListVisible = false;
|
||||
|
||||
void Reddog::Manager::Init()
|
||||
{
|
||||
g_upDebugIcon = LoadTexture(g_debug_icon, sizeof(g_debug_icon));
|
||||
|
||||
Reddog::InitControlsResources();
|
||||
Reddog::InitWindowResources();
|
||||
}
|
||||
|
||||
void Reddog::Manager::Draw()
|
||||
{
|
||||
bool isReddogToggled = SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_F1] != 0;
|
||||
|
||||
if (!g_isReddogToggled && isReddogToggled)
|
||||
{
|
||||
s_isVisible = !s_isVisible;
|
||||
|
||||
if (!s_isVisible)
|
||||
{
|
||||
g_debugIconPos = { 0, 0 };
|
||||
GameWindow::SetCursor(ECursorType::Default);
|
||||
GameWindow::SetCursorVisibility(false);
|
||||
}
|
||||
}
|
||||
|
||||
g_isReddogToggled = isReddogToggled;
|
||||
|
||||
if (!s_isVisible)
|
||||
return;
|
||||
|
||||
if (GameWindow::s_currentCursor == ECursorType::Default)
|
||||
{
|
||||
GameWindow::SetCursor(ECursorType::DebugDefault);
|
||||
GameWindow::SetCursorVisibility(true);
|
||||
}
|
||||
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
auto& res = ImGui::GetIO().DisplaySize;
|
||||
|
||||
auto debugIconSize = Scale(32);
|
||||
ImVec2 debugIconMin = g_debugIconPos;
|
||||
ImVec2 debugIconMax = { g_debugIconPos.x + debugIconSize, g_debugIconPos.y + debugIconSize };
|
||||
|
||||
drawList->AddImage(g_upDebugIcon.get(), debugIconMin, debugIconMax);
|
||||
|
||||
if (ImGui::IsMouseHoveringRect(debugIconMin, debugIconMax, false) && ImGui::IsMouseClicked(0))
|
||||
{
|
||||
g_debugIconPosOrig = g_debugIconPos;
|
||||
g_isDraggingDebugIcon = true;
|
||||
}
|
||||
|
||||
g_isDebugIconClicked = false;
|
||||
|
||||
if (g_isDraggingDebugIcon && ImGui::IsMouseDown(0))
|
||||
{
|
||||
auto& delta = ImGui::GetIO().MouseDelta;
|
||||
g_debugIconPos.x += delta.x;
|
||||
g_debugIconPos.y += delta.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_isDraggingDebugIcon &&
|
||||
g_debugIconPos.x == g_debugIconPosOrig.x &&
|
||||
g_debugIconPos.y == g_debugIconPosOrig.y)
|
||||
{
|
||||
g_isDebugIconClicked = true;
|
||||
g_isWindowListVisible = !g_isWindowListVisible;
|
||||
}
|
||||
|
||||
g_isDraggingDebugIcon = false;
|
||||
}
|
||||
|
||||
if (auto pWindowList = GetWindow<WindowList>(WINDOW_LIST_NAME))
|
||||
{
|
||||
if (!g_isDebugIconClicked && !pWindowList->IsFocused)
|
||||
pWindowList->IsVisible = g_isWindowListVisible = false;
|
||||
|
||||
pWindowList->IsVisible = g_isWindowListVisible;
|
||||
|
||||
if (pWindowList->ImWindow)
|
||||
{
|
||||
if (debugIconMin.x > res.x / 2)
|
||||
{
|
||||
pWindowList->ImWindow->Pos.x = debugIconMax.x - pWindowList->ImWindow->Size.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
pWindowList->ImWindow->Pos.x = debugIconMin.x;
|
||||
}
|
||||
|
||||
if (debugIconMin.y > res.y / 2)
|
||||
{
|
||||
pWindowList->ImWindow->Pos.y = debugIconMin.y - pWindowList->ImWindow->Size.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
pWindowList->ImWindow->Pos.y = debugIconMin.y + debugIconSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& pWindow : Reddog::GetWindows())
|
||||
{
|
||||
auto pTrueWindow = (Reddog::Window*)pWindow;
|
||||
|
||||
if (!pTrueWindow->IsVisible)
|
||||
continue;
|
||||
|
||||
pWindow->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
Reddog::Window* Reddog::Manager::GetWindow(const char* pName)
|
||||
{
|
||||
for (auto pWindow : Reddog::GetWindows())
|
||||
{
|
||||
if (strcmp(pWindow->GetName(), pName) == 0)
|
||||
return (Reddog::Window*)pWindow;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Reddog::Manager::GetWindow(const char* pName)
|
||||
{
|
||||
return (T*)Reddog::Manager::GetWindow(pName);
|
||||
}
|
||||
20
UnleashedRecomp/ui/reddog/reddog_manager.h
Normal file
20
UnleashedRecomp/ui/reddog/reddog_manager.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <ui/reddog/reddog_window.h>
|
||||
|
||||
namespace Reddog
|
||||
{
|
||||
class Manager
|
||||
{
|
||||
public:
|
||||
static inline bool s_isVisible = false;
|
||||
|
||||
static void Init();
|
||||
static void Draw();
|
||||
|
||||
static Window* GetWindow(const char* pName);
|
||||
|
||||
template<typename T>
|
||||
static T* GetWindow(const char* pName);
|
||||
};
|
||||
}
|
||||
364
UnleashedRecomp/ui/reddog/reddog_window.cpp
Normal file
364
UnleashedRecomp/ui/reddog/reddog_window.cpp
Normal file
@@ -0,0 +1,364 @@
|
||||
#include "reddog_window.h"
|
||||
|
||||
#include <gpu/imgui/imgui_snapshot.h>
|
||||
#include <gpu/video.h>
|
||||
#include <ui/reddog/reddog_manager.h>
|
||||
#include <ui/game_window.h>
|
||||
#include <ui/imgui_utils.h>
|
||||
|
||||
#include <res/images/debug_menu/button_close_1.dds.h>
|
||||
#include <res/images/debug_menu/button_close_2.dds.h>
|
||||
#include <res/images/debug_menu/button_minimum_1.dds.h>
|
||||
#include <res/images/debug_menu/button_minimum_2.dds.h>
|
||||
#include <res/images/debug_menu/button_pin_1.dds.h>
|
||||
#include <res/images/debug_menu/button_pin_2.dds.h>
|
||||
#include <res/images/debug_menu/common_icon.dds.h>
|
||||
#include <res/images/debug_menu/title_bar.dds.h>
|
||||
|
||||
constexpr float MIN_WINDOW_SIZE = 21.0f;
|
||||
|
||||
static std::unique_ptr<GuestTexture> g_upButtonClose1;
|
||||
static std::unique_ptr<GuestTexture> g_upButtonClose2;
|
||||
static std::unique_ptr<GuestTexture> g_upButtonMinimum1;
|
||||
static std::unique_ptr<GuestTexture> g_upButtonMinimum2;
|
||||
static std::unique_ptr<GuestTexture> g_upButtonPin1;
|
||||
static std::unique_ptr<GuestTexture> g_upButtonPin2;
|
||||
static std::unique_ptr<GuestTexture> g_upCommonIcon;
|
||||
static std::unique_ptr<GuestTexture> g_upTitleBar;
|
||||
static std::unique_ptr<GuestTexture> g_upWindowFrame;
|
||||
|
||||
ImFont* g_font;
|
||||
float g_defaultFontScale;
|
||||
|
||||
ImGuiStyle g_defaultStyle;
|
||||
|
||||
static std::vector<Reddog::IWindow*>& Reddog::GetWindows()
|
||||
{
|
||||
static std::vector<Reddog::IWindow*> g_windows;
|
||||
return g_windows;
|
||||
}
|
||||
|
||||
void Reddog::InitWindowResources()
|
||||
{
|
||||
g_font = ImFontAtlasSnapshot::GetFont("micross.ttf");
|
||||
g_defaultFontScale = g_font->Scale;
|
||||
|
||||
auto& style = ImGui::GetStyle();
|
||||
g_defaultStyle = style;
|
||||
|
||||
g_upButtonClose1 = LoadTexture(g_button_close_1, sizeof(g_button_close_1));
|
||||
g_upButtonClose2 = LoadTexture(g_button_close_2, sizeof(g_button_close_2));
|
||||
g_upButtonMinimum1 = LoadTexture(g_button_minimum_1, sizeof(g_button_minimum_1));
|
||||
g_upButtonMinimum2 = LoadTexture(g_button_minimum_2, sizeof(g_button_minimum_2));
|
||||
g_upButtonPin1 = LoadTexture(g_button_pin_1, sizeof(g_button_pin_1));
|
||||
g_upButtonPin2 = LoadTexture(g_button_pin_2, sizeof(g_button_pin_2));
|
||||
g_upCommonIcon = LoadTexture(g_common_icon, sizeof(g_common_icon));
|
||||
g_upTitleBar = LoadTexture(g_title_bar, sizeof(g_title_bar));
|
||||
}
|
||||
|
||||
void Reddog::Window::BeginStyle()
|
||||
{
|
||||
g_font->Scale = ImGui::GetDefaultFont()->FontSize / g_font->FontSize;
|
||||
ImGui::PushFont(g_font);
|
||||
|
||||
UpdateStyle();
|
||||
}
|
||||
|
||||
void Reddog::Window::UpdateStyle()
|
||||
{
|
||||
auto& style = ImGui::GetStyle();
|
||||
|
||||
style.WindowMinSize = { 0, MIN_WINDOW_SIZE };
|
||||
|
||||
auto colBg = IsFocused
|
||||
? ImU32ToImVec4(ActiveColour)
|
||||
: ImU32ToImVec4(InactiveColour);
|
||||
|
||||
auto colBlack = ImVec4(0, 0, 0, 1);
|
||||
auto colTrans = ImVec4(0, 0, 0, 0);
|
||||
auto colWhite = ImVec4(1, 1, 1, 1);
|
||||
|
||||
style.Colors[ImGuiCol_Border] = colTrans;
|
||||
style.Colors[ImGuiCol_Button] = colTrans;
|
||||
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.8f, 0.788f, 0.741f, 1);
|
||||
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.722f, 0.714f, 0.667f, 1);
|
||||
style.Colors[ImGuiCol_CheckMark] = colBlack;
|
||||
style.Colors[ImGuiCol_ChildBg] = colBg;
|
||||
style.Colors[ImGuiCol_FrameBg] = colBg;
|
||||
style.Colors[ImGuiCol_PopupBg] = colBg;
|
||||
style.Colors[ImGuiCol_ResizeGrip] = colTrans;
|
||||
style.Colors[ImGuiCol_ResizeGripActive] = colTrans;
|
||||
style.Colors[ImGuiCol_ResizeGripHovered] = colTrans;
|
||||
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.6f, 0.6f, 0.6f, 1);
|
||||
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(1, 0.6f, 0, 1);
|
||||
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(1, 0.6f, 0, 1);
|
||||
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(1, 0.6f, 0, 1);
|
||||
style.Colors[ImGuiCol_SeparatorActive] = colTrans;
|
||||
style.Colors[ImGuiCol_SeparatorHovered] = colTrans;
|
||||
style.Colors[ImGuiCol_SliderGrab] = colWhite;
|
||||
style.Colors[ImGuiCol_Tab] = ImVec4(0.467f, 0.467f, 0.467f, 1);
|
||||
style.Colors[ImGuiCol_TabActive] = ImVec4(0.6f, 0.6f, 0.6f, 1);
|
||||
style.Colors[ImGuiCol_TabHovered] = ImVec4(0.667f, 0.667f, 0.667f, 1);
|
||||
style.Colors[ImGuiCol_Text] = colBlack;
|
||||
style.Colors[ImGuiCol_WindowBg] = colBg;
|
||||
}
|
||||
|
||||
void Reddog::Window::EndStyle()
|
||||
{
|
||||
ImGui::PopFont();
|
||||
g_font->Scale = g_defaultFontScale;
|
||||
|
||||
ImGui::GetStyle() = g_defaultStyle;
|
||||
}
|
||||
|
||||
void Reddog::Window::CreateWindowGrips()
|
||||
{
|
||||
if (!ImWindow || !IsFocused)
|
||||
return;
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
auto windowPos = ImWindow->Pos;
|
||||
auto windowSize = ImWindow->Size;
|
||||
|
||||
constexpr float resizeMargin = 5.0f;
|
||||
|
||||
ImRect grips[6] =
|
||||
{
|
||||
// Corners
|
||||
ImRect(windowPos.x, windowPos.y + windowSize.y - resizeMargin, windowPos.x + resizeMargin, windowPos.y + windowSize.y), // Bottom left
|
||||
ImRect(windowPos.x + windowSize.x - resizeMargin, windowPos.y + windowSize.y - resizeMargin, windowPos.x + windowSize.x, windowPos.y + windowSize.y), // Bottom right
|
||||
|
||||
// Edges
|
||||
ImRect(windowPos.x + resizeMargin, windowPos.y, windowPos.x + windowSize.x - resizeMargin, windowPos.y + resizeMargin), // Top
|
||||
ImRect(windowPos.x + resizeMargin, windowPos.y + windowSize.y - resizeMargin, windowPos.x + windowSize.x - resizeMargin, windowPos.y + windowSize.y), // Bottom
|
||||
ImRect(windowPos.x, windowPos.y + resizeMargin, windowPos.x + resizeMargin, windowPos.y + windowSize.y - resizeMargin), // Left
|
||||
ImRect(windowPos.x + windowSize.x - resizeMargin, windowPos.y + resizeMargin, windowPos.x + windowSize.x, windowPos.y + windowSize.y - resizeMargin) // Right
|
||||
};
|
||||
|
||||
auto hoveredGrip = -1;
|
||||
|
||||
for (int i = 0; i < IM_ARRAYSIZE(grips); i++)
|
||||
{
|
||||
auto& grip = grips[i];
|
||||
|
||||
if (ImGui::IsMouseHoveringRect(grip.Min, grip.Max))
|
||||
hoveredGrip = i;
|
||||
}
|
||||
|
||||
if (hoveredGrip < 0)
|
||||
{
|
||||
GameWindow::SetCursor(ECursorType::DebugDefault);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hoveredGrip == 0)
|
||||
{
|
||||
GameWindow::SetCursor(ECursorType::DebugRightDiagonal);
|
||||
}
|
||||
else if (hoveredGrip == 1)
|
||||
{
|
||||
GameWindow::SetCursor(ECursorType::DebugLeftDiagonal);
|
||||
}
|
||||
else if (hoveredGrip == 2 || hoveredGrip == 3)
|
||||
{
|
||||
GameWindow::SetCursor(ECursorType::DebugVertical);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameWindow::SetCursor(ECursorType::DebugHorizontal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reddog::Window::DrawFrame()
|
||||
{
|
||||
if (!ImWindow)
|
||||
return;
|
||||
|
||||
if ((Flags & eWindowFlags_NoResize) == 0)
|
||||
CreateWindowGrips();
|
||||
|
||||
UpdateStyle();
|
||||
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
auto windowPos = ImWindow->Pos;
|
||||
auto windowSize = ImWindow->Size;
|
||||
auto isFocused = ImGui::IsWindowFocused();
|
||||
auto hasTitleBar = (Flags & eWindowFlags_NoTitleBar) == 0;
|
||||
|
||||
float titleBarHeight = hasTitleBar ? 20.0f : 0.0f;
|
||||
|
||||
ImVec2 windowMin = { windowPos.x, windowPos.y + titleBarHeight };
|
||||
ImVec2 windowMax = { windowPos.x + windowSize.x, windowPos.y + windowSize.y };
|
||||
|
||||
drawList->AddRectFilled(windowMin, windowMax, isFocused ? ActiveColour : InactiveColour);
|
||||
drawList->AddLine(windowMin, { windowMax.x, windowMin.y }, IM_COL32(170, 170, 170, 255)); // Outer top line.
|
||||
drawList->AddLine({ windowMin.x + 1, windowMin.y + 1 }, { windowMin.x + 1, windowMax.y }, IM_COL32(153, 153, 153, 255)); // Outer left line.
|
||||
drawList->AddLine({ windowMin.x, windowMax.y - 2 }, { windowMax.x, windowMax.y - 2 }, IM_COL32(51, 51, 51, 255)); // Outer bottom line.
|
||||
drawList->AddLine({ windowMax.x - 2, windowMin.y + 1 }, { windowMax.x - 2, windowMax.y }, IM_COL32(85, 85, 85, 255)); // Outer right line.
|
||||
drawList->AddLine({ windowMin.x + 2, windowMin.y + 1 }, { windowMax.x - 2, windowMin.y + 1 }, IM_COL32(51, 51, 51, 255)); // Inner top line.
|
||||
drawList->AddLine({ windowMin.x + 2, windowMin.y + 2 }, { windowMin.x + 2, windowMax.y - 2 }, IM_COL32(85, 85, 85, 255)); // Inner left line.
|
||||
drawList->AddLine({ windowMin.x + 3, windowMax.y - 3 }, { windowMax.x - 2, windowMax.y - 3 }, IM_COL32(170, 170, 170, 255)); // Inner bottom line.
|
||||
drawList->AddLine({ windowMax.x - 3, windowMin.y + 2 }, { windowMax.x - 3, windowMax.y - 3 }, IM_COL32(153, 153, 153, 255)); // Inner right line.
|
||||
|
||||
// Close window if unfocused whilst unpinned (yes it works like this in SU preview).
|
||||
if (!IsPinned && !isFocused && m_pIsVisible)
|
||||
*m_pIsVisible = !*m_pIsVisible;
|
||||
|
||||
if (hasTitleBar)
|
||||
{
|
||||
auto height = titleBarHeight;
|
||||
auto left = PIXELS_TO_UV_COORDS(32, 32, 0, 0, 3, 32);
|
||||
auto centre = PIXELS_TO_UV_COORDS(32, 32, 3, 0, 26, 32);
|
||||
auto right = PIXELS_TO_UV_COORDS(32, 32, 29, 0, 3, 32);
|
||||
|
||||
auto col = isFocused
|
||||
? IM_COL32(245, 245, 245, 255)
|
||||
: IM_COL32(246, 226, 202, 255);
|
||||
|
||||
drawList->AddImage(g_upTitleBar.get(), { windowPos.x, windowPos.y }, { windowPos.x + 3, windowPos.y + height }, GET_UV_COORDS(left), col);
|
||||
drawList->AddImage(g_upTitleBar.get(), { windowPos.x + 3, windowPos.y }, { windowPos.x + windowSize.x - 3, windowPos.y + height }, GET_UV_COORDS(centre), col);
|
||||
drawList->AddImage(g_upTitleBar.get(), { windowPos.x + windowSize.x - 3, windowPos.y }, { windowPos.x + windowSize.x, windowPos.y + height }, GET_UV_COORDS(right), col);
|
||||
|
||||
auto cmnSize = 16.0f;
|
||||
|
||||
ImVec2 cmnIconMin = { windowPos.x + 9, windowPos.y + 2 };
|
||||
ImVec2 cmnIconMax = { cmnIconMin.x + cmnSize, cmnIconMin.y + cmnSize };
|
||||
|
||||
drawList->AddImage(g_upCommonIcon.get(), cmnIconMin, cmnIconMax, { 0, 0 }, { 1, 1 }, IM_COL32(255, 255, 255, 255));
|
||||
drawList->AddText({ cmnIconMax.x + 5, windowPos.y + 4 }, IM_COL32(255, 255, 255, 255), Name);
|
||||
|
||||
ImVec2 closeButtonMin = { windowPos.x + windowSize.x - cmnSize - 4, windowPos.y + 3 };
|
||||
ImVec2 closeButtonMax = { closeButtonMin.x + cmnSize, closeButtonMin.y + cmnSize };
|
||||
|
||||
ImGui::SetCursorScreenPos(closeButtonMin);
|
||||
ImGui::InvisibleButton("##CloseButton", { cmnSize, cmnSize });
|
||||
bool isCloseButtonActive = ImGui::IsItemActive();
|
||||
|
||||
if (isCloseButtonActive)
|
||||
{
|
||||
drawList->AddImage(g_upButtonClose2.get(), closeButtonMin, closeButtonMax);
|
||||
m_isCloseButtonPressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawList->AddImage(g_upButtonClose1.get(), closeButtonMin, closeButtonMax);
|
||||
|
||||
if (m_isCloseButtonPressed && m_pIsVisible)
|
||||
{
|
||||
*m_pIsVisible = !*m_pIsVisible;
|
||||
m_isCloseButtonPressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImVec2 minimumButtonMin = { closeButtonMin.x - cmnSize - 4, windowPos.y + 3 };
|
||||
ImVec2 minimumButtonMax = { minimumButtonMin.x + cmnSize, minimumButtonMin.y + cmnSize };
|
||||
|
||||
ImGui::SetCursorScreenPos(minimumButtonMin);
|
||||
ImGui::InvisibleButton("##MinimumButton", { cmnSize, cmnSize });
|
||||
bool isMinimumButtonActive = ImGui::IsItemActive();
|
||||
|
||||
if (isMinimumButtonActive)
|
||||
{
|
||||
drawList->AddImage(g_upButtonMinimum2.get(), minimumButtonMin, minimumButtonMax);
|
||||
m_isMinimumButtonPressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawList->AddImage(g_upButtonMinimum1.get(), minimumButtonMin, minimumButtonMax);
|
||||
|
||||
if (m_isMinimumButtonPressed)
|
||||
{
|
||||
IsMinimum = !IsMinimum;
|
||||
|
||||
if (IsMinimum)
|
||||
{
|
||||
m_preMinimumWindowSize = windowSize;
|
||||
ImGui::SetWindowSize(ImWindow, { windowSize.x, MIN_WINDOW_SIZE });
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::SetWindowSize(ImWindow, { windowSize.x, m_preMinimumWindowSize.y });
|
||||
}
|
||||
|
||||
m_isMinimumButtonPressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImVec2 pinButtonMin = { minimumButtonMin.x - cmnSize - 4, windowPos.y + 3 };
|
||||
ImVec2 pinButtonMax = { pinButtonMin.x + cmnSize, pinButtonMin.y + cmnSize };
|
||||
|
||||
ImGui::SetCursorScreenPos(pinButtonMin);
|
||||
ImGui::InvisibleButton("##PinButton", { cmnSize, cmnSize });
|
||||
bool isPinButtonActive = ImGui::IsItemActive();
|
||||
|
||||
if (isPinButtonActive)
|
||||
{
|
||||
drawList->AddImage(g_upButtonPin2.get(), pinButtonMin, pinButtonMax);
|
||||
m_isPinButtonPressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawList->AddImage(g_upButtonPin1.get(), pinButtonMin, pinButtonMax);
|
||||
|
||||
if (m_isPinButtonPressed)
|
||||
{
|
||||
IsPinned = !IsPinned;
|
||||
m_isPinButtonPressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reddog::Window::SetVisible(bool isVisible)
|
||||
{
|
||||
IsVisible = m_isSetVisible = isVisible;
|
||||
}
|
||||
|
||||
bool Reddog::Window::Begin(bool* pIsVisible)
|
||||
{
|
||||
if (pIsVisible)
|
||||
{
|
||||
m_pIsVisible = pIsVisible;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pIsVisible = &IsVisible;
|
||||
}
|
||||
|
||||
BeginStyle();
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints({ m_minWidth, m_minHeight }, { m_maxWidth, m_maxHeight });
|
||||
|
||||
auto flags = REDDOG_IMGUI_FLAGS;
|
||||
|
||||
if ((Flags & eWindowFlags_NoResize) != 0)
|
||||
flags |= ImGuiWindowFlags_NoResize;
|
||||
|
||||
bool result = ImGui::Begin(Name, m_pIsVisible, flags);
|
||||
|
||||
if (result && *m_pIsVisible)
|
||||
{
|
||||
ImWindow = ImGui::GetCurrentWindow();
|
||||
IsFocused = ImGui::IsWindowFocused();
|
||||
|
||||
if (m_isSetVisible)
|
||||
{
|
||||
ImGui::SetWindowFocus();
|
||||
m_isSetVisible = false;
|
||||
}
|
||||
|
||||
DrawFrame();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Reddog::Window::End()
|
||||
{
|
||||
ImGui::End();
|
||||
EndStyle();
|
||||
}
|
||||
87
UnleashedRecomp/ui/reddog/reddog_window.h
Normal file
87
UnleashedRecomp/ui/reddog/reddog_window.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#define REDDOG_IMGUI_FLAGS ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBackground
|
||||
|
||||
namespace Reddog
|
||||
{
|
||||
enum EWindowFlags : uint32_t
|
||||
{
|
||||
eWindowFlags_None = 0,
|
||||
eWindowFlags_NoTitleBar = 1 << 0,
|
||||
eWindowFlags_NoResize = 1 << 1,
|
||||
eWindowFlags_NoListEntry = 1 << 2
|
||||
};
|
||||
|
||||
class IWindow
|
||||
{
|
||||
public:
|
||||
virtual ~IWindow() = default;
|
||||
virtual const char* GetName() = 0;
|
||||
virtual void Draw() = 0;
|
||||
};
|
||||
|
||||
extern std::vector<IWindow*>& GetWindows();
|
||||
|
||||
class Window : public IWindow
|
||||
{
|
||||
private:
|
||||
bool* m_pIsVisible{ nullptr };
|
||||
|
||||
bool m_isSetVisible{};
|
||||
bool m_isCloseButtonPressed{};
|
||||
bool m_isMinimumButtonPressed{};
|
||||
bool m_isPinButtonPressed{};
|
||||
|
||||
ImVec2 m_preMinimumWindowSize{};
|
||||
|
||||
void BeginStyle();
|
||||
void UpdateStyle();
|
||||
void EndStyle();
|
||||
void CreateWindowGrips();
|
||||
void DrawFrame();
|
||||
|
||||
protected:
|
||||
float m_minWidth{ 175.0f };
|
||||
float m_minHeight{};
|
||||
float m_maxWidth{ FLT_MAX };
|
||||
float m_maxHeight{ FLT_MAX };
|
||||
|
||||
public:
|
||||
const char* Name{ "(null)" };
|
||||
EWindowFlags Flags{ eWindowFlags_None };
|
||||
bool IsFocused{ true };
|
||||
bool IsMinimum{};
|
||||
bool IsPinned{ true };
|
||||
bool IsVisible{};
|
||||
ImGuiWindow* ImWindow{ nullptr };
|
||||
ImU32 ActiveColour{ IM_COL32(232, 231, 255, 255) };
|
||||
ImU32 InactiveColour{ IM_COL32(193, 192, 181, 255) };
|
||||
|
||||
Window()
|
||||
{
|
||||
GetWindows().push_back(this);
|
||||
}
|
||||
|
||||
Window(const char* pName, EWindowFlags flags = eWindowFlags_None) : Name(pName), Flags(flags)
|
||||
{
|
||||
GetWindows().push_back(this);
|
||||
}
|
||||
|
||||
const char* GetName() override
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
void Draw() override
|
||||
{
|
||||
Begin();
|
||||
End();
|
||||
}
|
||||
|
||||
void SetVisible(bool isVisible = true);
|
||||
bool Begin(bool* pIsVisible = nullptr);
|
||||
void End();
|
||||
};
|
||||
|
||||
void InitWindowResources();
|
||||
}
|
||||
13
UnleashedRecomp/ui/reddog/windows/counter_window.cpp
Normal file
13
UnleashedRecomp/ui/reddog/windows/counter_window.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "counter_window.h"
|
||||
#include <gpu/video.h>
|
||||
|
||||
static CounterWindow g_window;
|
||||
|
||||
void CounterWindow::Draw()
|
||||
{
|
||||
if (Begin())
|
||||
{
|
||||
Video::DrawCounter();
|
||||
}
|
||||
End();
|
||||
}
|
||||
17
UnleashedRecomp/ui/reddog/windows/counter_window.h
Normal file
17
UnleashedRecomp/ui/reddog/windows/counter_window.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <ui/reddog/reddog_window.h>
|
||||
|
||||
class CounterWindow : public Reddog::Window
|
||||
{
|
||||
public:
|
||||
CounterWindow() : Window()
|
||||
{
|
||||
Name = "Counter";
|
||||
|
||||
m_minWidth = 215;
|
||||
m_minHeight = 328;
|
||||
}
|
||||
|
||||
void Draw() override;
|
||||
};
|
||||
19
UnleashedRecomp/ui/reddog/windows/exports_window.cpp
Normal file
19
UnleashedRecomp/ui/reddog/windows/exports_window.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "exports_window.h"
|
||||
#include <ui/reddog/reddog_controls.h>
|
||||
#include <user/config.h>
|
||||
|
||||
static ExportsWindow g_window{ "Exports" };
|
||||
|
||||
void ExportsWindow::Draw()
|
||||
{
|
||||
if (Begin())
|
||||
{
|
||||
ImGui::TextColored({ 1, 0, 0, 1 }, "For testing purposes only, use Hedge Mod Manager to toggle these.");
|
||||
Reddog::Checkbox("Allow Cancelling Unleash", &Config::AllowCancellingUnleash.Value);
|
||||
Reddog::Checkbox("Fix Unleash Out of Control Drain", &Config::FixUnleashOutOfControlDrain.Value);
|
||||
Reddog::Checkbox("Homing Attack on Boost", &Config::HomingAttackOnBoost.Value);
|
||||
Reddog::Checkbox("Save Score at Checkpoints", &Config::SaveScoreAtCheckpoints.Value);
|
||||
Reddog::Checkbox("Skip Intro Logos", &Config::SkipIntroLogos.Value);
|
||||
}
|
||||
End();
|
||||
}
|
||||
11
UnleashedRecomp/ui/reddog/windows/exports_window.h
Normal file
11
UnleashedRecomp/ui/reddog/windows/exports_window.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <ui/reddog/reddog_window.h>
|
||||
|
||||
class ExportsWindow : public Reddog::Window
|
||||
{
|
||||
public:
|
||||
using Reddog::Window::Window;
|
||||
|
||||
void Draw() override;
|
||||
};
|
||||
14
UnleashedRecomp/ui/reddog/windows/view_window.cpp
Normal file
14
UnleashedRecomp/ui/reddog/windows/view_window.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "view_window.h"
|
||||
#include <kernel/memory.h>
|
||||
#include <ui/reddog/reddog_controls.h>
|
||||
|
||||
static ViewWindow g_window{ "View" };
|
||||
|
||||
void ViewWindow::Draw()
|
||||
{
|
||||
if (Begin())
|
||||
{
|
||||
Reddog::Checkbox("Render HUD", (bool*)g_memory.Translate(0x8328BB26));
|
||||
}
|
||||
End();
|
||||
}
|
||||
11
UnleashedRecomp/ui/reddog/windows/view_window.h
Normal file
11
UnleashedRecomp/ui/reddog/windows/view_window.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <ui/reddog/reddog_window.h>
|
||||
|
||||
class ViewWindow : public Reddog::Window
|
||||
{
|
||||
public:
|
||||
using Reddog::Window::Window;
|
||||
|
||||
void Draw() override;
|
||||
};
|
||||
21
UnleashedRecomp/ui/reddog/windows/window_list.cpp
Normal file
21
UnleashedRecomp/ui/reddog/windows/window_list.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "window_list.h"
|
||||
|
||||
static WindowList g_window;
|
||||
|
||||
void WindowList::Draw()
|
||||
{
|
||||
if (Begin())
|
||||
{
|
||||
for (auto& pWindow : Reddog::GetWindows())
|
||||
{
|
||||
auto pTrueWindow = (Reddog::Window*)pWindow;
|
||||
|
||||
if ((pTrueWindow->Flags & Reddog::eWindowFlags_NoListEntry) != 0)
|
||||
continue;
|
||||
|
||||
if (ImGui::Button(pTrueWindow->Name, { 190, 26 }))
|
||||
pTrueWindow->SetVisible();
|
||||
}
|
||||
}
|
||||
End();
|
||||
}
|
||||
20
UnleashedRecomp/ui/reddog/windows/window_list.h
Normal file
20
UnleashedRecomp/ui/reddog/windows/window_list.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <ui/reddog/reddog_window.h>
|
||||
|
||||
#define WINDOW_LIST_NAME "##WindowList"
|
||||
|
||||
class WindowList : public Reddog::Window
|
||||
{
|
||||
public:
|
||||
WindowList() : Window()
|
||||
{
|
||||
Name = WINDOW_LIST_NAME;
|
||||
Flags = (Reddog::EWindowFlags)(Reddog::eWindowFlags_NoTitleBar | Reddog::eWindowFlags_NoResize | Reddog::eWindowFlags_NoListEntry);
|
||||
ActiveColour = InactiveColour = IM_COL32_WHITE;
|
||||
|
||||
m_minWidth = m_minHeight = 0;
|
||||
}
|
||||
|
||||
void Draw() override;
|
||||
};
|
||||
@@ -596,6 +596,7 @@ public:
|
||||
CONFIG_DEFINE_LOCALISED("System", bool, ControlTutorial, true);
|
||||
CONFIG_DEFINE_LOCALISED("System", bool, AchievementNotifications, true);
|
||||
CONFIG_DEFINE_ENUM_LOCALISED("System", ETimeOfDayTransition, TimeOfDayTransition, ETimeOfDayTransition::Xbox);
|
||||
CONFIG_DEFINE("System", bool, Debug, false);
|
||||
|
||||
CONFIG_DEFINE_LOCALISED("Input", bool, InvertCameraX, false);
|
||||
CONFIG_DEFINE_LOCALISED("Input", bool, InvertCameraY, false);
|
||||
|
||||
Submodule UnleashedRecompResources updated: 2817764f59...775f0bb026
Submodule tools/PowerRecomp updated: 7fb8af1bad...de2840970f
Reference in New Issue
Block a user