From 7115f60b91b5717d90f643fd692010905c7004db Mon Sep 17 00:00:00 2001 From: Bryan Galdrikian Date: Thu, 31 May 2018 11:36:08 -0700 Subject: Blast 1.1.3. See docs/release_notes.txt. --- samples/SampleBase/ui/CommonUIController.cpp | 1276 +++++++++++++------------- 1 file changed, 638 insertions(+), 638 deletions(-) mode change 100644 => 100755 samples/SampleBase/ui/CommonUIController.cpp (limited to 'samples/SampleBase/ui/CommonUIController.cpp') diff --git a/samples/SampleBase/ui/CommonUIController.cpp b/samples/SampleBase/ui/CommonUIController.cpp old mode 100644 new mode 100755 index 57a8866..5075449 --- a/samples/SampleBase/ui/CommonUIController.cpp +++ b/samples/SampleBase/ui/CommonUIController.cpp @@ -1,639 +1,639 @@ -// This code contains NVIDIA Confidential Information and is disclosed to you -// under a form of NVIDIA software license agreement provided separately to you. -// -// Notice -// NVIDIA Corporation and its licensors retain all intellectual property and -// proprietary rights in and to this software and related documentation and -// any modifications thereto. Any use, reproduction, disclosure, or -// distribution of this software and related documentation without an express -// license agreement from NVIDIA Corporation is strictly prohibited. -// -// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES -// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO -// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, -// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. -// -// Information and code furnished is believed to be accurate and reliable. -// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such -// information or for any infringement of patents or other rights of third parties that may -// result from its use. No license is granted by implication or otherwise under any patent -// or patent rights of NVIDIA Corporation. Details are subject to change without notice. -// This code supersedes and replaces all information previously supplied. -// NVIDIA Corporation products are not authorized for use as critical -// components in life support devices or systems without express written approval of -// NVIDIA Corporation. -// -// Copyright (c) 2008-2018 NVIDIA Corporation. All rights reserved. - - -#include "CommonUIController.h" - -#include "Renderer.h" -#include "BlastController.h" -#include "DamageToolController.h" -#include "SceneController.h" -#include "SampleController.h" -#include "PhysXController.h" -#include "SampleProfiler.h" - -#include "PxVisualizationParameter.h" -#include "PxScene.h" - -#include -#include "imgui_impl_dx11.h" -#include "UIHelpers.h" - -#include -#include - - -inline float memorySizeOutput(const char*& prefix, float value) -{ - for (prefix = "\0\0k\0M\0G\0T\0P\0E"; value >= 1024 && *prefix != 'E'; value /= 1024, prefix += 2); - return value; -} - -CommonUIController::CommonUIController() -{ -} - -HRESULT CommonUIController::DeviceCreated(ID3D11Device* pDevice) -{ - DeviceManager* manager = GetDeviceManager(); - ID3D11DeviceContext* pd3dDeviceContext; - pDevice->GetImmediateContext(&pd3dDeviceContext); - ImGui_ImplDX11_Init(manager->GetHWND(), pDevice, pd3dDeviceContext); - - ImGuiStyle& style = ImGui::GetStyle(); - style.WindowRounding = 8.0f; - style.ScrollbarRounding = 8.0f; - style.FrameRounding = 8.0f; - //style.IndentSpacing = 20; - int mainColor[3] = { 110, 110, 110 }; // previous green one { 50, 110, 30 } - style.Colors[ImGuiCol_TitleBg] = ImColor(mainColor[0], mainColor[1], mainColor[2], 62); - style.Colors[ImGuiCol_TitleBgCollapsed] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52); - style.Colors[ImGuiCol_TitleBgActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 87); - style.Colors[ImGuiCol_Header] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52); - style.Colors[ImGuiCol_HeaderHovered] = ImColor(mainColor[0], mainColor[1], mainColor[2], 92); - style.Colors[ImGuiCol_HeaderActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 72); - style.Colors[ImGuiCol_ScrollbarBg] = ImColor(mainColor[0], mainColor[1], mainColor[2], 12); - style.Colors[ImGuiCol_ScrollbarGrab] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52); - style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImColor(mainColor[0], mainColor[1], mainColor[2], 92); - style.Colors[ImGuiCol_ScrollbarGrabActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 72); - style.Colors[ImGuiCol_Button] = ImColor(40, 100, 80, 30); - style.Colors[ImGuiCol_ButtonHovered] = ImColor(40, 100, 80, 100); - style.Colors[ImGuiCol_ButtonActive] = ImColor(40, 100, 80, 70); - style.Colors[ImGuiCol_PopupBg] = ImColor(10, 23, 18, 230); - style.Colors[ImGuiCol_TextSelectedBg] = ImColor(10, 23, 18, 180); - style.Colors[ImGuiCol_FrameBg] = ImColor(70, 70, 70, 30); - style.Colors[ImGuiCol_FrameBgHovered] = ImColor(70, 70, 70, 70); - style.Colors[ImGuiCol_FrameBgActive] = ImColor(70, 70, 70, 50); - style.Colors[ImGuiCol_ComboBg] = ImColor(20, 20, 20, 252); - - return S_OK; -} - -void CommonUIController::DeviceDestroyed() -{ - ImGui_ImplDX11_Shutdown(); -} - -extern LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -LRESULT CommonUIController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - PX_UNUSED(hWnd); - PX_UNUSED(wParam); - PX_UNUSED(lParam); - - ImGui_ImplDX11_WndProcHandler(hWnd, uMsg, wParam, lParam); - - if (uMsg == WM_KEYDOWN && !ImGui::GetIO().WantCaptureKeyboard) - { - int iKeyPressed = static_cast(wParam); - switch (iKeyPressed) - { - case 'P': - { - getPhysXController().setPaused(!getPhysXController().isPaused()); - break; - } - case 'O': - { - getRenderer().setWireframeMode(!getRenderer().getWireframeMode()); - break; - } - case 'I': - { - getBlastController().debugRenderMode = (BlastFamily::DebugRenderMode)(((int)getBlastController().debugRenderMode + 1) % BlastFamily::DebugRenderMode::DEBUG_RENDER_MODES_COUNT); - break; - } - case VK_F5: - { - getRenderer().reloadShaders(); - break; - } - default: - break; - } - } - - if (ImGui::GetIO().WantCaptureMouse) - return 0; - - return 1; -} - -void CommonUIController::Animate(double fElapsedTimeSeconds) -{ - m_dt = (float)fElapsedTimeSeconds; -} - -void CommonUIController::Render(ID3D11Device*, ID3D11DeviceContext*, ID3D11RenderTargetView*, ID3D11DepthStencilView*) -{ - ImGui_ImplDX11_NewFrame(); - drawUI(); - ImGui::Render(); -} - -void CommonUIController::addDelayedCall(const char* title, const char* message, std::function func, float delay) -{ - DelayedCall call = { func, title, message, delay, delay }; - m_delayedCalls.emplace(call); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// IMGUI UI -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -void CommonUIController::drawUI() -{ - const float padding = 8.0f; - ImGui::SetNextWindowPos(ImVec2(padding, padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/); - ImGui::SetNextWindowSize(ImVec2(420, getRenderer().getScreenHeight() - 2 * padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/); - ImGui::SetNextWindowCollapsed(false, ImGuiSetCond_Once); - ImGui::Begin("New Shiny UI", 0, ImGuiWindowFlags_NoTitleBar); - { - ImGui::PushItemWidth(ImGui::GetWindowSize().x * 0.5f); - - /////////////////////////////////////////////////////////////////////////////////////////// - // Scene - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("Scene")) - { - getSceneController().drawUI(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Blast - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("Blast")) - { - getBlastController().drawUI(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Damage Tool - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("Damage Tool")) - { - getDamageToolController().drawUI(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Stats - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("Stats")) - { - BlastController& blastController = getBlastController(); - - const char* prefix; - float sizeVal; - - // FPS - double averageTime = GetDeviceManager()->GetAverageFrameTime(); - float fps = (averageTime > 0) ? 1.0 / averageTime : 0.0; - float frameMs = 1000.0f / fps; - ImGui::Text("Frame Time %.3f ms (%.1f FPS)", frameMs, fps); - - static PlotLinesInstance<> fpsPlot; - fpsPlot.plot("FPS", frameMs, "ms/frame", 0.0f, 100.0f); - - // Render stats - ImGui::PushStyleColor(ImGuiCol_Text, ImColor(0xFF, 0x3B, 0xD8, 0xFF)); - ImGui::Text("Draw Calls (Opaque/Transparent): %d/%d", getRenderer().getVisibleOpaqueRenderablesCount(), getRenderer().getVisibleTransparentRenderablesCount()); - ImGui::PopStyleColor(); - - // Blast stats - const BlastTimers& timers = blastController.getLastBlastTimers(); - - ImGui::Text("Simulation Time: %.2f ms ", getPhysXController().getLastSimulationTime() * 1000); - ImGui::Text("Actor Count: %d", blastController.getActorCount()); - ImGui::Text("Visible Chunk Count: %d", blastController.getTotalVisibleChunkCount()); - - getManager()->getSceneController().drawStatsUI(); - - sizeVal = memorySizeOutput(prefix, (float)blastController.getFamilySize()); - ImGui::Text("Family Size: %.3g %sB", sizeVal, prefix); - sizeVal = memorySizeOutput(prefix, (float)blastController.getBlastAssetsSize()); - ImGui::Text("Blast asset Data size: %.3g %sB", sizeVal, prefix); - - //ImGui::Text(" Last Blast Extern Time: %8.3f ms", timers.mLastExternalTime * 1000); -// ImGui::Text(" Last Damage Time: %8.3f ms", timers.blastDamage * 1000); -#if NV_PROFILE - ImGui::Text("Last Material Time: %8.3f ms", timers.blastDamageMaterial * 1000); - ImGui::Text("Last Fracture Time: %8.3f ms", timers.blastDamageFracture * 1000); -#endif -// ImGui::Text("Last Physics Split Time: %.3f ms", timers.physicsSplit * 1000); -#if NV_PROFILE - ImGui::Text("Last Island Time: %8.3f ms", timers.blastSplitIsland * 1000); - ImGui::Text("Last Partition Time: %8.3f ms", timers.blastSplitPartition * 1000); - ImGui::Text("Last Visibility Time: %8.3f ms", timers.blastSplitVisibility * 1000); -#endif - -#if NV_PROFILE - // Sample Profiler - static bool s_showProfilerWindow = false; - if (ImGui::Button("Code Profiler")) - { - s_showProfilerWindow = !s_showProfilerWindow; - } - if (s_showProfilerWindow) - { - drawCodeProfiler(&s_showProfilerWindow); - } -#endif - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Application - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("Application")) - { - // Paused - bool isPaused = getPhysXController().isPaused(); - if (ImGui::Checkbox("Pause (P)", &isPaused)) - { - getPhysXController().setPaused(isPaused); - } - - // Reload Shaders - if (ImGui::Button("Reload Shaders (F5)")) - { - getRenderer().reloadShaders(); - } - - // ImGui Test Window (just in case) - static bool s_showTestWindow = false; - if (ImGui::Button("ImGui Test Window")) - { - s_showTestWindow = !s_showTestWindow; - } - if (s_showTestWindow) - { - ImGui::ShowTestWindow(); - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Debug Render - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("Debug Render")) - { - // WireFrame - bool wireFrameEnabled = getRenderer().getWireframeMode(); - if (ImGui::Checkbox("WireFrame (O)", &wireFrameEnabled)) - { - getRenderer().setWireframeMode(wireFrameEnabled); - } - - // - - - - - - - - - ImGui::Spacing(); - - // Blast Debug Render Mode - const char* debugRenderItems[] = - { - "Disabled", // DEBUG_RENDER_DISABLED - "Health Graph", // DEBUG_RENDER_HEALTH_GRAPH - "Centroids", // DEBUG_RENDER_CENTROIDS - "Health Graph + Centroids", // DEBUG_RENDER_HEALTH_GRAPH_CENTROIDS - "Joints", // DEBUG_RENDER_JOINTS - "Stress Graph", // DEBUG_RENDER_STRESS_GRAPH - "Stress Graph + Nodes Impulses", // DEBUG_RENDER_STRESS_GRAPH_NODES_IMPULSES - "Stress Graph + Bonds Impulses" // DEBUG_RENDER_STRESS_GRAPH_BONDS_IMPULSES - }; - ImGui::Combo("Blast Debug Render Mode (I)", (int*)&getBlastController().debugRenderMode, debugRenderItems, IM_ARRAYSIZE(debugRenderItems), -1); - - // Blast Debug Render Scale - ImGui::DragFloat("Blast Debug Render Scale", &getBlastController().debugRenderScale, 0.01f, 0.0f, 10.0f, "%.3f", 4.0f); - - // - - - - - - - - - ImGui::Spacing(); - - // PhysX Debug Render - if (ImGui::TreeNode("PhysX Debug Render")) - { - auto addParam = [&](physx::PxVisualizationParameter::Enum param, const char* uiName) - { - bool enabled = getPhysXController().getPhysXScene().getVisualizationParameter(param) != 0; - if (ImGui::Checkbox(uiName, &enabled)) - { - getPhysXController().getPhysXScene().setVisualizationParameter(param, enabled ? 1.0f : 0.0f); - } - }; - - addParam(PxVisualizationParameter::eSCALE, "Scale"); - addParam(PxVisualizationParameter::eBODY_AXES, "Body Axes"); - addParam(PxVisualizationParameter::eWORLD_AXES, "World Axes"); - addParam(PxVisualizationParameter::eBODY_MASS_AXES, "Body Mass Axes"); - addParam(PxVisualizationParameter::eBODY_LIN_VELOCITY, "Body Lin Velocity"); - addParam(PxVisualizationParameter::eBODY_ANG_VELOCITY, "Body Ang Velocity"); - //addParam(PxVisualizationParameter::eBODY_JOINT_GROUPS, "Body Joint"); - addParam(PxVisualizationParameter::eCONTACT_POINT, "Contact Point"); - addParam(PxVisualizationParameter::eCONTACT_NORMAL, "Contact Normal"); - addParam(PxVisualizationParameter::eCONTACT_ERROR, "Contact Error"); - addParam(PxVisualizationParameter::eCONTACT_FORCE, "Contact Force"); - addParam(PxVisualizationParameter::eACTOR_AXES, "Actor Axes"); - addParam(PxVisualizationParameter::eCOLLISION_AABBS, "Collision AABBs"); - addParam(PxVisualizationParameter::eCOLLISION_SHAPES, "Collision Shapes"); - addParam(PxVisualizationParameter::eCOLLISION_AXES, "Collision Axes"); - addParam(PxVisualizationParameter::eCOLLISION_COMPOUNDS, "Collision Compounds"); - addParam(PxVisualizationParameter::eCOLLISION_FNORMALS, "Collision FNormals"); - addParam(PxVisualizationParameter::eCOLLISION_EDGES, "Collision Edges"); - addParam(PxVisualizationParameter::eCOLLISION_STATIC, "Collision Static"); - addParam(PxVisualizationParameter::eCOLLISION_DYNAMIC, "Collision Dynamic"); - //addParam(PxVisualizationParameter::eDEPRECATED_COLLISION_PAIRS, "Collision Pairs"); - addParam(PxVisualizationParameter::eJOINT_LOCAL_FRAMES, "Joint Local Frames"); - addParam(PxVisualizationParameter::eJOINT_LIMITS, "Joint Limits"); - //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_POSITION, "PS Position"); - //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_VELOCITY, "PS Velocity"); - //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_COLLISION_NORMAL, "PS Collision Normal"); - //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_BOUNDS, "PS Bounds"); - //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_GRID, "PS Grid"); - //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_BROADPHASE_BOUNDS, "PS Broadphase Bounds"); - //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_MAX_MOTION_DISTANCE, "PS Max Motion Distance"); - addParam(PxVisualizationParameter::eCULL_BOX, "Cull Box"); - //addParam(PxVisualizationParameter::eCLOTH_VERTICAL, "Cloth Vertical"); - //addParam(PxVisualizationParameter::eCLOTH_HORIZONTAL, "Cloth Horizontal"); - //addParam(PxVisualizationParameter::eCLOTH_BENDING, "Cloth Bending"); - //addParam(PxVisualizationParameter::eCLOTH_SHEARING, "Cloth Shearing"); - //addParam(PxVisualizationParameter::eCLOTH_VIRTUAL_PARTICLES, "Cloth Virtual Particles"); - addParam(PxVisualizationParameter::eMBP_REGIONS, "MBP Regions"); - - ImGui::TreePop(); - } - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // PhysX - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("PhysX")) - { - // PhysX - getPhysXController().drawUI(); - - // GPU - getSampleController().drawPhysXGpuUI(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Renderer - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("Renderer")) - { - getRenderer().drawUI(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Hints - /////////////////////////////////////////////////////////////////////////////////////////// - if (ImGui::CollapsingHeader("Hints / Help")) - { - ImGui::BulletText("Rotate camera - RMB"); - ImGui::BulletText("Move camera - WASDQE(SHIFT)"); - ImGui::BulletText("Play/Pause - P"); - ImGui::BulletText("Reload shaders - F5"); - ImGui::BulletText("Wireframe - O"); - ImGui::BulletText("Blast Debug Render - I"); - ImGui::BulletText("Apply damage - LMB"); - ImGui::BulletText("Damage radius - +/-/wheel"); - ImGui::BulletText("Damage profile - 1-9"); - ImGui::BulletText("Explosive - X"); - ImGui::BulletText("Throw cube - F"); - ImGui::BulletText("Restart - R"); - } - - ImGui::PopItemWidth(); - } - ImGui::End(); - - /////////////////////////////////////////////////////////////////////////////////////////// - // Mode Text - /////////////////////////////////////////////////////////////////////////////////////////// - { - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4()); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0)); - - const char* text = getDamageToolController().isDamageMode() ? "DAMAGE MODE (PRESS SPACE)" : "DRAG MODE (PRESS SPACE)"; - ImVec2 size = ImGui::CalcTextSize(text); - ImGui::SetNextWindowPos(ImVec2((getRenderer().getScreenWidth() - size.x) / 2, 0)); - ImGui::Begin("Mode Text", 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar); - ImGui::Text(text); - ImGui::End(); - - ImGui::PopStyleVar(); - ImGui::PopStyleColor(); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // FPS - /////////////////////////////////////////////////////////////////////////////////////////// - { - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4()); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - - double averageTime = GetDeviceManager()->GetAverageFrameTime(); - float fps = (averageTime > 0) ? 1.0 / averageTime : 0.0; - static char buf[32]; - std::sprintf(buf, "%.1f FPS", fps); - ImVec2 size = ImGui::CalcTextSize(buf); - - size.x += 20.0; - ImGui::SetNextWindowSize(size); - ImGui::SetNextWindowPos(ImVec2(getRenderer().getScreenWidth() - size.x, 0)); - ImGui::Begin("FPS", 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar); - ImGui::Text(buf); - ImGui::End(); - - ImGui::PopStyleVar(); - ImGui::PopStyleColor(); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Loading overlay - /////////////////////////////////////////////////////////////////////////////////////////// - if (!m_delayedCalls.empty()) - { - DelayedCall& call = m_delayedCalls.front(); - if (call.delay > 0) - { - const int height = 50; - const char* message = call.message; - const float alpha = PxClamp(lerp(0.0f, 1.0f, (call.delayTotal - call.delay) * 10.0f), 0.0f, 1.0f); - - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImColor(0, 0, 0, 200)); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha); - ImGui::SetNextWindowPosCenter(); - ImVec2 size = ImGui::CalcTextSize(message); - int width = std::max(200, size.x) + 50; - ImGui::SetNextWindowSize(ImVec2(width, height)); - ImGui::Begin(call.title, 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar); - ImGui::SetCursorPos(ImVec2((width - size.x) * 0.5f, (height - size.y) * 0.5f)); - ImGui::Text(message); - ImGui::End(); - ImGui::PopStyleVar(); - ImGui::PopStyleColor(); - - call.delay -= PxClamp(m_dt, 0.0f, 0.1f); - } - else - { - call.func(); - m_delayedCalls.pop(); - } - } -} - - -void CommonUIController::drawCodeProfiler(bool* open) -{ - ImGuiWindowFlags window_flags = 0; - const float padding = 8.0f; - const float width = 550; - const float height = 580; - ImGui::SetNextWindowPos(ImVec2(getRenderer().getScreenWidth() - width - padding, padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/); - ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiSetCond_Once); - if (!ImGui::Begin("Code Profiler", open, window_flags)) - { - // Early out if the window is collapsed, as an optimization. - ImGui::End(); - return; - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Control/Main Bar - /////////////////////////////////////////////////////////////////////////////////////////// - { - if (ImGui::Button("Reset")) - { - PROFILER_INIT(); - } - ImGui::SameLine(); - if (ImGui::Button("Dump To File (profile.txt)")) - { - SampleProfilerDumpToFile("profile.txt"); - } - ImGui::SameLine(); - ImGui::Text("Profiler overhead: %2.3f ms", SampleProfilerGetOverhead().count() * 0.001f); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Legend - /////////////////////////////////////////////////////////////////////////////////////////// - { - ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); - ImGui::Text("Legend: name | calls | time | max time"); - ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Stats Tree - /////////////////////////////////////////////////////////////////////////////////////////// - ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); - float plotMS = 0.0f; - float plotMaxMS = 0.0f; - const char* plotName = nullptr; - if (ImGui::TreeNode("Root")) - { - auto treeIt = SampleProfilerCreateTreeIterator(); - if (treeIt) - { - uint32_t depth = 1; - uint32_t openeDepth = 1; - while (!treeIt->isDone()) - { - const auto data = treeIt->data(); - - while (data->depth < depth) - { - ImGui::TreePop(); - depth--; - } - - const uint32_t maxLen = 30; - auto hash = data->hash; - static uint64_t selectedNodeHash = 0; - if (selectedNodeHash == hash) - { - plotMS = data->time.count() * 0.001f; - plotMaxMS = data->maxTime.count() * 0.001f; - plotName = data->name; - } - if (ImGui::TreeNodeEx(data->name, data->hasChilds ? 0 : ImGuiTreeNodeFlags_Leaf, "%-*.*s | %d | %2.3f ms | %2.3f ms", - maxLen, maxLen, data->name, data->calls, data->time.count() * 0.001f, data->maxTime.count() * 0.001f)) - { - depth++; - treeIt->next(); - } - else - { - treeIt->next(); - while (!treeIt->isDone() && treeIt->data()->depth > depth) - treeIt->next(); - } - - if (ImGui::IsItemClicked()) - { - selectedNodeHash = hash; - } - } - - while (depth > 0) - { - ImGui::TreePop(); - depth--; - } - - treeIt->release(); - } - else - { - ImGui::Text("Profiler Is Broken. Begin/End Mismatch."); - } - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Selected Item Plot - /////////////////////////////////////////////////////////////////////////////////////////// - { - ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); - if (plotName) - { - static PlotLinesInstance<> selectedNodePlot; - selectedNodePlot.plot("", plotMS, plotName, 0.0f, plotMaxMS); - } - else - { - ImGui::Text("Select item to plot."); - } - } - - ImGui::End(); +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2018 NVIDIA Corporation. All rights reserved. + + +#include "CommonUIController.h" + +#include "Renderer.h" +#include "BlastController.h" +#include "DamageToolController.h" +#include "SceneController.h" +#include "SampleController.h" +#include "PhysXController.h" +#include "SampleProfiler.h" + +#include "PxVisualizationParameter.h" +#include "PxScene.h" + +#include +#include "imgui_impl_dx11.h" +#include "UIHelpers.h" + +#include +#include + + +inline float memorySizeOutput(const char*& prefix, float value) +{ + for (prefix = "\0\0k\0M\0G\0T\0P\0E"; value >= 1024 && *prefix != 'E'; value /= 1024, prefix += 2); + return value; +} + +CommonUIController::CommonUIController() +{ +} + +HRESULT CommonUIController::DeviceCreated(ID3D11Device* pDevice) +{ + DeviceManager* manager = GetDeviceManager(); + ID3D11DeviceContext* pd3dDeviceContext; + pDevice->GetImmediateContext(&pd3dDeviceContext); + ImGui_ImplDX11_Init(manager->GetHWND(), pDevice, pd3dDeviceContext); + + ImGuiStyle& style = ImGui::GetStyle(); + style.WindowRounding = 8.0f; + style.ScrollbarRounding = 8.0f; + style.FrameRounding = 8.0f; + //style.IndentSpacing = 20; + int mainColor[3] = { 110, 110, 110 }; // previous green one { 50, 110, 30 } + style.Colors[ImGuiCol_TitleBg] = ImColor(mainColor[0], mainColor[1], mainColor[2], 62); + style.Colors[ImGuiCol_TitleBgCollapsed] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52); + style.Colors[ImGuiCol_TitleBgActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 87); + style.Colors[ImGuiCol_Header] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52); + style.Colors[ImGuiCol_HeaderHovered] = ImColor(mainColor[0], mainColor[1], mainColor[2], 92); + style.Colors[ImGuiCol_HeaderActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 72); + style.Colors[ImGuiCol_ScrollbarBg] = ImColor(mainColor[0], mainColor[1], mainColor[2], 12); + style.Colors[ImGuiCol_ScrollbarGrab] = ImColor(mainColor[0], mainColor[1], mainColor[2], 52); + style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImColor(mainColor[0], mainColor[1], mainColor[2], 92); + style.Colors[ImGuiCol_ScrollbarGrabActive] = ImColor(mainColor[0], mainColor[1], mainColor[2], 72); + style.Colors[ImGuiCol_Button] = ImColor(40, 100, 80, 30); + style.Colors[ImGuiCol_ButtonHovered] = ImColor(40, 100, 80, 100); + style.Colors[ImGuiCol_ButtonActive] = ImColor(40, 100, 80, 70); + style.Colors[ImGuiCol_PopupBg] = ImColor(10, 23, 18, 230); + style.Colors[ImGuiCol_TextSelectedBg] = ImColor(10, 23, 18, 180); + style.Colors[ImGuiCol_FrameBg] = ImColor(70, 70, 70, 30); + style.Colors[ImGuiCol_FrameBgHovered] = ImColor(70, 70, 70, 70); + style.Colors[ImGuiCol_FrameBgActive] = ImColor(70, 70, 70, 50); + style.Colors[ImGuiCol_ComboBg] = ImColor(20, 20, 20, 252); + + return S_OK; +} + +void CommonUIController::DeviceDestroyed() +{ + ImGui_ImplDX11_Shutdown(); +} + +extern LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +LRESULT CommonUIController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PX_UNUSED(hWnd); + PX_UNUSED(wParam); + PX_UNUSED(lParam); + + ImGui_ImplDX11_WndProcHandler(hWnd, uMsg, wParam, lParam); + + if (uMsg == WM_KEYDOWN && !ImGui::GetIO().WantCaptureKeyboard) + { + int iKeyPressed = static_cast(wParam); + switch (iKeyPressed) + { + case 'P': + { + getPhysXController().setPaused(!getPhysXController().isPaused()); + break; + } + case 'O': + { + getRenderer().setWireframeMode(!getRenderer().getWireframeMode()); + break; + } + case 'I': + { + getBlastController().debugRenderMode = (BlastFamily::DebugRenderMode)(((int)getBlastController().debugRenderMode + 1) % BlastFamily::DebugRenderMode::DEBUG_RENDER_MODES_COUNT); + break; + } + case VK_F5: + { + getRenderer().reloadShaders(); + break; + } + default: + break; + } + } + + if (ImGui::GetIO().WantCaptureMouse) + return 0; + + return 1; +} + +void CommonUIController::Animate(double fElapsedTimeSeconds) +{ + m_dt = (float)fElapsedTimeSeconds; +} + +void CommonUIController::Render(ID3D11Device*, ID3D11DeviceContext*, ID3D11RenderTargetView*, ID3D11DepthStencilView*) +{ + ImGui_ImplDX11_NewFrame(); + drawUI(); + ImGui::Render(); +} + +void CommonUIController::addDelayedCall(const char* title, const char* message, std::function func, float delay) +{ + DelayedCall call = { func, title, message, delay, delay }; + m_delayedCalls.emplace(call); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// IMGUI UI +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +void CommonUIController::drawUI() +{ + const float padding = 8.0f; + ImGui::SetNextWindowPos(ImVec2(padding, padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/); + ImGui::SetNextWindowSize(ImVec2(420, getRenderer().getScreenHeight() - 2 * padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/); + ImGui::SetNextWindowCollapsed(false, ImGuiSetCond_Once); + ImGui::Begin("New Shiny UI", 0, ImGuiWindowFlags_NoTitleBar); + { + ImGui::PushItemWidth(ImGui::GetWindowSize().x * 0.5f); + + /////////////////////////////////////////////////////////////////////////////////////////// + // Scene + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("Scene")) + { + getSceneController().drawUI(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Blast + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("Blast")) + { + getBlastController().drawUI(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Damage Tool + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("Damage Tool")) + { + getDamageToolController().drawUI(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Stats + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("Stats")) + { + BlastController& blastController = getBlastController(); + + const char* prefix; + float sizeVal; + + // FPS + double averageTime = GetDeviceManager()->GetAverageFrameTime(); + float fps = (averageTime > 0) ? 1.0 / averageTime : 0.0; + float frameMs = 1000.0f / fps; + ImGui::Text("Frame Time %.3f ms (%.1f FPS)", frameMs, fps); + + static PlotLinesInstance<> fpsPlot; + fpsPlot.plot("FPS", frameMs, "ms/frame", 0.0f, 100.0f); + + // Render stats + ImGui::PushStyleColor(ImGuiCol_Text, ImColor(0xFF, 0x3B, 0xD8, 0xFF)); + ImGui::Text("Draw Calls (Opaque/Transparent): %d/%d", getRenderer().getVisibleOpaqueRenderablesCount(), getRenderer().getVisibleTransparentRenderablesCount()); + ImGui::PopStyleColor(); + + // Blast stats + const BlastTimers& timers = blastController.getLastBlastTimers(); + + ImGui::Text("Simulation Time: %.2f ms ", getPhysXController().getLastSimulationTime() * 1000); + ImGui::Text("Actor Count: %d", blastController.getActorCount()); + ImGui::Text("Visible Chunk Count: %d", blastController.getTotalVisibleChunkCount()); + + getManager()->getSceneController().drawStatsUI(); + + sizeVal = memorySizeOutput(prefix, (float)blastController.getFamilySize()); + ImGui::Text("Family Size: %.3g %sB", sizeVal, prefix); + sizeVal = memorySizeOutput(prefix, (float)blastController.getBlastAssetsSize()); + ImGui::Text("Blast asset Data size: %.3g %sB", sizeVal, prefix); + + //ImGui::Text(" Last Blast Extern Time: %8.3f ms", timers.mLastExternalTime * 1000); +// ImGui::Text(" Last Damage Time: %8.3f ms", timers.blastDamage * 1000); +#if NV_PROFILE + ImGui::Text("Last Material Time: %8.3f ms", timers.blastDamageMaterial * 1000); + ImGui::Text("Last Fracture Time: %8.3f ms", timers.blastDamageFracture * 1000); +#endif +// ImGui::Text("Last Physics Split Time: %.3f ms", timers.physicsSplit * 1000); +#if NV_PROFILE + ImGui::Text("Last Island Time: %8.3f ms", timers.blastSplitIsland * 1000); + ImGui::Text("Last Partition Time: %8.3f ms", timers.blastSplitPartition * 1000); + ImGui::Text("Last Visibility Time: %8.3f ms", timers.blastSplitVisibility * 1000); +#endif + +#if NV_PROFILE + // Sample Profiler + static bool s_showProfilerWindow = false; + if (ImGui::Button("Code Profiler")) + { + s_showProfilerWindow = !s_showProfilerWindow; + } + if (s_showProfilerWindow) + { + drawCodeProfiler(&s_showProfilerWindow); + } +#endif + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Application + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("Application")) + { + // Paused + bool isPaused = getPhysXController().isPaused(); + if (ImGui::Checkbox("Pause (P)", &isPaused)) + { + getPhysXController().setPaused(isPaused); + } + + // Reload Shaders + if (ImGui::Button("Reload Shaders (F5)")) + { + getRenderer().reloadShaders(); + } + + // ImGui Test Window (just in case) + static bool s_showTestWindow = false; + if (ImGui::Button("ImGui Test Window")) + { + s_showTestWindow = !s_showTestWindow; + } + if (s_showTestWindow) + { + ImGui::ShowTestWindow(); + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Debug Render + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("Debug Render")) + { + // WireFrame + bool wireFrameEnabled = getRenderer().getWireframeMode(); + if (ImGui::Checkbox("WireFrame (O)", &wireFrameEnabled)) + { + getRenderer().setWireframeMode(wireFrameEnabled); + } + + // - - - - - - - - + ImGui::Spacing(); + + // Blast Debug Render Mode + const char* debugRenderItems[] = + { + "Disabled", // DEBUG_RENDER_DISABLED + "Health Graph", // DEBUG_RENDER_HEALTH_GRAPH + "Centroids", // DEBUG_RENDER_CENTROIDS + "Health Graph + Centroids", // DEBUG_RENDER_HEALTH_GRAPH_CENTROIDS + "Joints", // DEBUG_RENDER_JOINTS + "Stress Graph", // DEBUG_RENDER_STRESS_GRAPH + "Stress Graph + Nodes Impulses", // DEBUG_RENDER_STRESS_GRAPH_NODES_IMPULSES + "Stress Graph + Bonds Impulses" // DEBUG_RENDER_STRESS_GRAPH_BONDS_IMPULSES + }; + ImGui::Combo("Blast Debug Render Mode (I)", (int*)&getBlastController().debugRenderMode, debugRenderItems, IM_ARRAYSIZE(debugRenderItems), -1); + + // Blast Debug Render Scale + ImGui::DragFloat("Blast Debug Render Scale", &getBlastController().debugRenderScale, 0.01f, 0.0f, 10.0f, "%.3f", 4.0f); + + // - - - - - - - - + ImGui::Spacing(); + + // PhysX Debug Render + if (ImGui::TreeNode("PhysX Debug Render")) + { + auto addParam = [&](physx::PxVisualizationParameter::Enum param, const char* uiName) + { + bool enabled = getPhysXController().getPhysXScene().getVisualizationParameter(param) != 0; + if (ImGui::Checkbox(uiName, &enabled)) + { + getPhysXController().getPhysXScene().setVisualizationParameter(param, enabled ? 1.0f : 0.0f); + } + }; + + addParam(PxVisualizationParameter::eSCALE, "Scale"); + addParam(PxVisualizationParameter::eBODY_AXES, "Body Axes"); + addParam(PxVisualizationParameter::eWORLD_AXES, "World Axes"); + addParam(PxVisualizationParameter::eBODY_MASS_AXES, "Body Mass Axes"); + addParam(PxVisualizationParameter::eBODY_LIN_VELOCITY, "Body Lin Velocity"); + addParam(PxVisualizationParameter::eBODY_ANG_VELOCITY, "Body Ang Velocity"); + //addParam(PxVisualizationParameter::eBODY_JOINT_GROUPS, "Body Joint"); + addParam(PxVisualizationParameter::eCONTACT_POINT, "Contact Point"); + addParam(PxVisualizationParameter::eCONTACT_NORMAL, "Contact Normal"); + addParam(PxVisualizationParameter::eCONTACT_ERROR, "Contact Error"); + addParam(PxVisualizationParameter::eCONTACT_FORCE, "Contact Force"); + addParam(PxVisualizationParameter::eACTOR_AXES, "Actor Axes"); + addParam(PxVisualizationParameter::eCOLLISION_AABBS, "Collision AABBs"); + addParam(PxVisualizationParameter::eCOLLISION_SHAPES, "Collision Shapes"); + addParam(PxVisualizationParameter::eCOLLISION_AXES, "Collision Axes"); + addParam(PxVisualizationParameter::eCOLLISION_COMPOUNDS, "Collision Compounds"); + addParam(PxVisualizationParameter::eCOLLISION_FNORMALS, "Collision FNormals"); + addParam(PxVisualizationParameter::eCOLLISION_EDGES, "Collision Edges"); + addParam(PxVisualizationParameter::eCOLLISION_STATIC, "Collision Static"); + addParam(PxVisualizationParameter::eCOLLISION_DYNAMIC, "Collision Dynamic"); + //addParam(PxVisualizationParameter::eDEPRECATED_COLLISION_PAIRS, "Collision Pairs"); + addParam(PxVisualizationParameter::eJOINT_LOCAL_FRAMES, "Joint Local Frames"); + addParam(PxVisualizationParameter::eJOINT_LIMITS, "Joint Limits"); + //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_POSITION, "PS Position"); + //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_VELOCITY, "PS Velocity"); + //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_COLLISION_NORMAL, "PS Collision Normal"); + //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_BOUNDS, "PS Bounds"); + //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_GRID, "PS Grid"); + //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_BROADPHASE_BOUNDS, "PS Broadphase Bounds"); + //addParam(PxVisualizationParameter::ePARTICLE_SYSTEM_MAX_MOTION_DISTANCE, "PS Max Motion Distance"); + addParam(PxVisualizationParameter::eCULL_BOX, "Cull Box"); + //addParam(PxVisualizationParameter::eCLOTH_VERTICAL, "Cloth Vertical"); + //addParam(PxVisualizationParameter::eCLOTH_HORIZONTAL, "Cloth Horizontal"); + //addParam(PxVisualizationParameter::eCLOTH_BENDING, "Cloth Bending"); + //addParam(PxVisualizationParameter::eCLOTH_SHEARING, "Cloth Shearing"); + //addParam(PxVisualizationParameter::eCLOTH_VIRTUAL_PARTICLES, "Cloth Virtual Particles"); + addParam(PxVisualizationParameter::eMBP_REGIONS, "MBP Regions"); + + ImGui::TreePop(); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // PhysX + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("PhysX")) + { + // PhysX + getPhysXController().drawUI(); + + // GPU + getSampleController().drawPhysXGpuUI(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Renderer + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("Renderer")) + { + getRenderer().drawUI(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Hints + /////////////////////////////////////////////////////////////////////////////////////////// + if (ImGui::CollapsingHeader("Hints / Help")) + { + ImGui::BulletText("Rotate camera - RMB"); + ImGui::BulletText("Move camera - WASDQE(SHIFT)"); + ImGui::BulletText("Play/Pause - P"); + ImGui::BulletText("Reload shaders - F5"); + ImGui::BulletText("Wireframe - O"); + ImGui::BulletText("Blast Debug Render - I"); + ImGui::BulletText("Apply damage - LMB"); + ImGui::BulletText("Damage radius - +/-/wheel"); + ImGui::BulletText("Damage profile - 1-9"); + ImGui::BulletText("Explosive - X"); + ImGui::BulletText("Throw cube - F"); + ImGui::BulletText("Restart - R"); + } + + ImGui::PopItemWidth(); + } + ImGui::End(); + + /////////////////////////////////////////////////////////////////////////////////////////// + // Mode Text + /////////////////////////////////////////////////////////////////////////////////////////// + { + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4()); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0)); + + const char* text = getDamageToolController().isDamageMode() ? "DAMAGE MODE (PRESS SPACE)" : "DRAG MODE (PRESS SPACE)"; + ImVec2 size = ImGui::CalcTextSize(text); + ImGui::SetNextWindowPos(ImVec2((getRenderer().getScreenWidth() - size.x) / 2, 0)); + ImGui::Begin("Mode Text", 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar); + ImGui::Text(text); + ImGui::End(); + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // FPS + /////////////////////////////////////////////////////////////////////////////////////////// + { + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4()); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); + + double averageTime = GetDeviceManager()->GetAverageFrameTime(); + float fps = (averageTime > 0) ? 1.0 / averageTime : 0.0; + static char buf[32]; + std::sprintf(buf, "%.1f FPS", fps); + ImVec2 size = ImGui::CalcTextSize(buf); + + size.x += 20.0; + ImGui::SetNextWindowSize(size); + ImGui::SetNextWindowPos(ImVec2(getRenderer().getScreenWidth() - size.x, 0)); + ImGui::Begin("FPS", 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar); + ImGui::Text(buf); + ImGui::End(); + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Loading overlay + /////////////////////////////////////////////////////////////////////////////////////////// + if (!m_delayedCalls.empty()) + { + DelayedCall& call = m_delayedCalls.front(); + if (call.delay > 0) + { + const int height = 50; + const char* message = call.message; + const float alpha = PxClamp(lerp(0.0f, 1.0f, (call.delayTotal - call.delay) * 10.0f), 0.0f, 1.0f); + + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImColor(0, 0, 0, 200)); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha); + ImGui::SetNextWindowPosCenter(); + ImVec2 size = ImGui::CalcTextSize(message); + int width = std::max(200, size.x) + 50; + ImGui::SetNextWindowSize(ImVec2(width, height)); + ImGui::Begin(call.title, 0, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar); + ImGui::SetCursorPos(ImVec2((width - size.x) * 0.5f, (height - size.y) * 0.5f)); + ImGui::Text(message); + ImGui::End(); + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); + + call.delay -= PxClamp(m_dt, 0.0f, 0.1f); + } + else + { + call.func(); + m_delayedCalls.pop(); + } + } +} + + +void CommonUIController::drawCodeProfiler(bool* open) +{ + ImGuiWindowFlags window_flags = 0; + const float padding = 8.0f; + const float width = 550; + const float height = 580; + ImGui::SetNextWindowPos(ImVec2(getRenderer().getScreenWidth() - width - padding, padding), ImGuiSetCond_Once/*ImGuiSetCond_FirstUseEver*/); + ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiSetCond_Once); + if (!ImGui::Begin("Code Profiler", open, window_flags)) + { + // Early out if the window is collapsed, as an optimization. + ImGui::End(); + return; + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Control/Main Bar + /////////////////////////////////////////////////////////////////////////////////////////// + { + if (ImGui::Button("Reset")) + { + PROFILER_INIT(); + } + ImGui::SameLine(); + if (ImGui::Button("Dump To File (profile.txt)")) + { + SampleProfilerDumpToFile("profile.txt"); + } + ImGui::SameLine(); + ImGui::Text("Profiler overhead: %2.3f ms", SampleProfilerGetOverhead().count() * 0.001f); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Legend + /////////////////////////////////////////////////////////////////////////////////////////// + { + ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); + ImGui::Text("Legend: name | calls | time | max time"); + ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Stats Tree + /////////////////////////////////////////////////////////////////////////////////////////// + ImGui::SetNextTreeNodeOpen(true, ImGuiSetCond_Once); + float plotMS = 0.0f; + float plotMaxMS = 0.0f; + const char* plotName = nullptr; + if (ImGui::TreeNode("Root")) + { + auto treeIt = SampleProfilerCreateTreeIterator(); + if (treeIt) + { + uint32_t depth = 1; + uint32_t openeDepth = 1; + while (!treeIt->isDone()) + { + const auto data = treeIt->data(); + + while (data->depth < depth) + { + ImGui::TreePop(); + depth--; + } + + const uint32_t maxLen = 30; + auto hash = data->hash; + static uint64_t selectedNodeHash = 0; + if (selectedNodeHash == hash) + { + plotMS = data->time.count() * 0.001f; + plotMaxMS = data->maxTime.count() * 0.001f; + plotName = data->name; + } + if (ImGui::TreeNodeEx(data->name, data->hasChilds ? 0 : ImGuiTreeNodeFlags_Leaf, "%-*.*s | %d | %2.3f ms | %2.3f ms", + maxLen, maxLen, data->name, data->calls, data->time.count() * 0.001f, data->maxTime.count() * 0.001f)) + { + depth++; + treeIt->next(); + } + else + { + treeIt->next(); + while (!treeIt->isDone() && treeIt->data()->depth > depth) + treeIt->next(); + } + + if (ImGui::IsItemClicked()) + { + selectedNodeHash = hash; + } + } + + while (depth > 0) + { + ImGui::TreePop(); + depth--; + } + + treeIt->release(); + } + else + { + ImGui::Text("Profiler Is Broken. Begin/End Mismatch."); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Selected Item Plot + /////////////////////////////////////////////////////////////////////////////////////////// + { + ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); + if (plotName) + { + static PlotLinesInstance<> selectedNodePlot; + selectedNodePlot.plot("", plotMS, plotName, 0.0f, plotMaxMS); + } + else + { + ImGui::Text("Select item to plot."); + } + } + + ImGui::End(); } \ No newline at end of file -- cgit v1.2.3