#include "fmt/format.h" #include "imgui.h" #include "aurora/gfx.h" #include "dusk/hotkeys.h" #include "dusk/settings.h" #include "ImGuiConsole.hpp" #include "ImGuiMenuTools.hpp" #include "d/actor/d_a_alink.h" #include "d/actor/d_a_horse.h" #include "d/d_com_inf_game.h" #include "dusk/dusk.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; } ImGui::Separator(); auto& collisionView = getTransientSettings().collisionView; if (ImGui::BeginMenu("Collision View")) { ImGui::Checkbox("Enable Terrain view", &collisionView.enableTerrainView); ImGui::Checkbox("Enable wireframe view", &collisionView.enableWireframe); ImGui::SliderFloat("Opacity##terrain", &collisionView.terrainViewOpacity, 0.0f, 100.0f); ImGui::SliderFloat("Draw Range", &collisionView.drawRange, 0.0f, 1000.0f); ImGui::Separator(); ImGui::Checkbox("Enable Attack Collider view", &collisionView.enableAtView); ImGui::Checkbox("Enable Target Collider view", &collisionView.enableTgView); ImGui::Checkbox("Enable Push Collider view", &collisionView.enableCoView); ImGui::SliderFloat("Opacity##colliders", &collisionView.colliderViewOpacity, 0.0f, 100.0f); ImGui::EndMenu(); } 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); 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() { if (!ImGuiConsole::CheckMenuViewToggle(ImGuiKey_F3, m_showDebugOverlay)) { return; } ImGuiIO& io = ImGui::GetIO(); ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; if (m_debugOverlayCorner != -1) { SetOverlayWindowLocation(m_debugOverlayCorner); windowFlags |= ImGuiWindowFlags_NoMove; } 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; ImGuiStringViewText(fmt::format(FMT_STRING("Backend: {}\n"), backend_name(aurora_get_backend()))); if (hasPrevious) { ImGui::Separator(); } hasPrevious = true; const auto& stats = lastFrameAuroraStats; ImGuiStringViewText( fmt::format(FMT_STRING("Queued pipelines: {}\n"), stats.queuedPipelines)); ImGuiStringViewText( fmt::format(FMT_STRING("Done pipelines: {}\n"), stats.createdPipelines)); ImGuiStringViewText( fmt::format(FMT_STRING("Draw call count: {}\n"), stats.drawCallCount)); ImGuiStringViewText(fmt::format(FMT_STRING("Merged draw calls: {}\n"), stats.mergedDrawCallCount)); ImGuiStringViewText(fmt::format(FMT_STRING("Vertex size: {}\n"), BytesToString(stats.lastVertSize))); ImGuiStringViewText(fmt::format(FMT_STRING("Uniform size: {}\n"), BytesToString(stats.lastUniformSize))); ImGuiStringViewText(fmt::format(FMT_STRING("Index size: {}\n"), BytesToString(stats.lastIndexSize))); ImGuiStringViewText(fmt::format(FMT_STRING("Storage size: {}\n"), BytesToString(stats.lastStorageSize))); ImGuiStringViewText(fmt::format(FMT_STRING("Tex upload size: {}\n"), BytesToString(stats.lastTextureUploadSize))); ImGuiStringViewText(fmt::format( FMT_STRING("Total: {}\n"), BytesToString(stats.lastVertSize + stats.lastUniformSize + stats.lastIndexSize + stats.lastStorageSize + stats.lastTextureUploadSize))); // TODO: persist to config ShowCornerContextMenu(m_debugOverlayCorner, m_cameraOverlayCorner); } ImGui::End(); } void ImGuiMenuTools::ShowPlayerInfo() { if (!m_showPlayerInfo) { return; } ImGuiIO& io = ImGui::GetIO(); ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize; ImGui::SetNextWindowBgAlpha(0.65f); if (ImGui::Begin("Player Info", &m_showPlayerInfo, windowFlags)) { daAlink_c* player = (daAlink_c*)dComIfGp_getPlayer(0); daHorse_c* horse = dComIfGp_getHorseActor(); ImGui::Text("Link"); ImGuiStringViewText( player != nullptr ? fmt::format("Position: {: .2f}, {: .2f}, {: .2f}\n", player->current.pos.x, player->current.pos.y, player->current.pos.z) : "Position: ?, ?, ?\n" ); ImGuiStringViewText( player != nullptr ? fmt::format("Angle: {0}\n", player->shape_angle.y) : "Angle: ?\n" ); ImGuiStringViewText( player != nullptr ? fmt::format("Speed: {0}\n", player->speedF) : "Speed: ?\n" ); ImGui::Separator(); ImGui::Text("Epona"); ImGuiStringViewText( horse != nullptr ? fmt::format("Position: {: .2f}, {: .2f}, {: .2f}\n", horse->current.pos.x, horse->current.pos.y, horse->current.pos.z) : "Position: ?, ?, ?\n" ); ImGuiStringViewText( horse != nullptr ? fmt::format("Angle: {0}\n", horse->shape_angle.y) : "Angle: ?\n" ); ImGuiStringViewText( horse != nullptr ? fmt::format("Speed: {0}\n", horse->speedF) : "Speed: ?\n" ); } ImGui::End(); } }