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 ++++++++++++------------ samples/SampleBase/ui/CommonUIController.h | 246 ++--- samples/SampleBase/ui/DamageToolController.cpp | 968 +++++++++--------- samples/SampleBase/ui/DamageToolController.h | 318 +++--- samples/SampleBase/ui/imgui_impl_dx11.cpp | 1166 +++++++++++----------- samples/SampleBase/ui/imgui_impl_dx11.h | 50 +- 6 files changed, 2012 insertions(+), 2012 deletions(-) mode change 100644 => 100755 samples/SampleBase/ui/CommonUIController.cpp mode change 100644 => 100755 samples/SampleBase/ui/CommonUIController.h mode change 100644 => 100755 samples/SampleBase/ui/DamageToolController.cpp mode change 100644 => 100755 samples/SampleBase/ui/DamageToolController.h mode change 100644 => 100755 samples/SampleBase/ui/imgui_impl_dx11.cpp mode change 100644 => 100755 samples/SampleBase/ui/imgui_impl_dx11.h (limited to 'samples/SampleBase/ui') 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 diff --git a/samples/SampleBase/ui/CommonUIController.h b/samples/SampleBase/ui/CommonUIController.h old mode 100644 new mode 100755 index bfee4e9..1720d68 --- a/samples/SampleBase/ui/CommonUIController.h +++ b/samples/SampleBase/ui/CommonUIController.h @@ -1,124 +1,124 @@ -// 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. - - -#ifndef COMMON_UI_CONTROLLER_H -#define COMMON_UI_CONTROLLER_H - -#include "SampleManager.h" -#include -#include -#include -#include -#include - - -class Renderer; -class PhysXController; -class BlastController; - - -class CommonUIController : public ISampleController -{ - public: - CommonUIController(); - virtual ~CommonUIController() {}; - - virtual HRESULT DeviceCreated(ID3D11Device* pDevice); - virtual void DeviceDestroyed(); - virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - virtual void Animate(double fElapsedTimeSeconds); - virtual void Render(ID3D11Device*, ID3D11DeviceContext*, ID3D11RenderTargetView*, ID3D11DepthStencilView*); - - void addDelayedCall(std::function func, const char* message) - { - addDelayedCall("PLEASE WAIT...", message, func); - } - - void addPopupMessage(const char* title, const char* message, float duration = 2.f) - { - addDelayedCall(title, message, [] {}, duration); - } - - private: - void addDelayedCall(const char* title, const char* message, std::function func, float delay = 0.1f); - - void drawUI(); - void drawCodeProfiler(bool*); - - - //////// used controllers //////// - - Renderer& getRenderer() const - { - return getManager()->getRenderer(); - } - - PhysXController& getPhysXController() const - { - return getManager()->getPhysXController(); - } - - BlastController&getBlastController() const - { - return getManager()->getBlastController(); - } - - DamageToolController& getDamageToolController() const - { - return getManager()->getDamageToolController(); - } - - SceneController& getSceneController() const - { - return getManager()->getSceneController(); - } - - SampleController& getSampleController() const - { - return getManager()->getSampleController(); - } - - - //////// internal data //////// - - struct DelayedCall - { - std::function func; - const char* title; - const char* message; - float delay; - float delayTotal; - }; - - std::queue m_delayedCalls; - - float m_dt; - -}; - +// 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. + + +#ifndef COMMON_UI_CONTROLLER_H +#define COMMON_UI_CONTROLLER_H + +#include "SampleManager.h" +#include +#include +#include +#include +#include + + +class Renderer; +class PhysXController; +class BlastController; + + +class CommonUIController : public ISampleController +{ + public: + CommonUIController(); + virtual ~CommonUIController() {}; + + virtual HRESULT DeviceCreated(ID3D11Device* pDevice); + virtual void DeviceDestroyed(); + virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual void Animate(double fElapsedTimeSeconds); + virtual void Render(ID3D11Device*, ID3D11DeviceContext*, ID3D11RenderTargetView*, ID3D11DepthStencilView*); + + void addDelayedCall(std::function func, const char* message) + { + addDelayedCall("PLEASE WAIT...", message, func); + } + + void addPopupMessage(const char* title, const char* message, float duration = 2.f) + { + addDelayedCall(title, message, [] {}, duration); + } + + private: + void addDelayedCall(const char* title, const char* message, std::function func, float delay = 0.1f); + + void drawUI(); + void drawCodeProfiler(bool*); + + + //////// used controllers //////// + + Renderer& getRenderer() const + { + return getManager()->getRenderer(); + } + + PhysXController& getPhysXController() const + { + return getManager()->getPhysXController(); + } + + BlastController&getBlastController() const + { + return getManager()->getBlastController(); + } + + DamageToolController& getDamageToolController() const + { + return getManager()->getDamageToolController(); + } + + SceneController& getSceneController() const + { + return getManager()->getSceneController(); + } + + SampleController& getSampleController() const + { + return getManager()->getSampleController(); + } + + + //////// internal data //////// + + struct DelayedCall + { + std::function func; + const char* title; + const char* message; + float delay; + float delayTotal; + }; + + std::queue m_delayedCalls; + + float m_dt; + +}; + #endif \ No newline at end of file diff --git a/samples/SampleBase/ui/DamageToolController.cpp b/samples/SampleBase/ui/DamageToolController.cpp old mode 100644 new mode 100755 index 1fc0817..b634c7d --- a/samples/SampleBase/ui/DamageToolController.cpp +++ b/samples/SampleBase/ui/DamageToolController.cpp @@ -1,484 +1,484 @@ -// 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 "DamageToolController.h" -#include "RenderUtils.h" -#include "BlastController.h" -#include "Renderer.h" -#include "PhysXController.h" -#include "SampleProfiler.h" - -#include - -#include "NvBlastTkActor.h" -#include "NvBlastTkFamily.h" -#include "NvBlastExtDamageShaders.h" -#include "NvBlastExtPxActor.h" -#include "NvBlastExtPxFamily.h" - -#include "PxRigidDynamic.h" -#include "PxScene.h" - - -using namespace Nv::Blast; -using namespace physx; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Setup -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const DirectX::XMFLOAT4 PICK_POINTER_ACTIVE_COLOR(1.0f, 0.f, 0.f, 0.6f); -static const PxVec3 WEAPON_POSITION_IN_VIEW(0, -7, 23); -static const float SEGMENT_DAMAGE_MAX_DISTANCE = 100.0f; - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -DamageToolController::DamageToolController() - : m_damage(100.0f), m_toolColor(1.0f, 1.0f, 1.0f, 0.4f), - m_toolRenderMaterial(nullptr), m_sphereToolRenderable(nullptr), m_lineToolRenderable(nullptr), - m_explosiveImpulse(100), m_damagerIndex(0), m_stressForceFactor(1.0f), m_isMousePressed(false), m_damageCountWhilePressed(0) -{ - // damage amount calc using NvBlastExtMaterial - auto getDamageAmountFn = [](const float damage, ExtPxActor* actor) - { - const NvBlastExtMaterial* material = actor->getFamily().getMaterial(); - return material ? material->getNormalizedDamage(damage) : 0.f; - }; - - // Damage functions - auto radialDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) - { - const float damage = getDamageAmountFn(m_damage, actor); - if (damage > 0.f) - { - NvBlastExtRadialDamageDesc desc = - { - damage, - { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z }, - damager->radius, - damager->radius * 1.6f - }; - - getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc)); - } - }; - auto sliceDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) - { - const float damage = getDamageAmountFn(m_damage, actor); - if (damage > 0.f) - { - PxVec3 farEnd = data.origin + data.weaponDir * 1000.0f; - PxVec3 farEndPrev = data.origin + data.previousWeaponDir * 1000.0f; - - NvBlastExtTriangleIntersectionDamageDesc desc = - { - damage, - { data.origin.x, data.origin.y, data.origin.z }, - { farEnd.x, farEnd.y, farEnd.z }, - { farEndPrev.x, farEndPrev.y, farEndPrev.z }, - }; - - getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc)); - } - }; - auto capsuleDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) - { - const float damage = getDamageAmountFn(m_damage, actor); - if (damage > 0.f) - { - PxVec3 dir = (data.hitPosition - data.origin).getNormalized(); - PxVec3 farEnd = data.origin + dir * 10000.0f; - - NvBlastExtCapsuleRadialDamageDesc desc = - { - damage, - { data.origin.x, data.origin.y, data.origin.z }, - { farEnd.x, farEnd.y, farEnd.z }, - damager->radius, - damager->radius * 1.6f - }; - - getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc)); - } - }; - auto impulseSpreadDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) - { - const float damage = m_damage; - if (damage > 0.f) - { - PxVec3 impactNormal = -data.hitNormal; - - NvBlastExtImpactSpreadDamageDesc desc = - { - damage, - { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z }, - damager->radius, - damager->radius * 1.6f - }; - - getBlastController().immediateDamage(actor, family, damager->program, &desc); - } - }; - auto shearDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) - { - const float damage = getDamageAmountFn(m_damage, actor); - if (damage > 0.f) - { - PxVec3 impactNormal = -data.hitNormal; - - NvBlastExtShearDamageDesc desc = - { - damage, - { impactNormal.x, impactNormal.y, impactNormal.z }, - { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z }, - damager->radius, - damager->radius * 1.6f - }; - - getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc)); - } - }; - auto stressDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) - { - PxVec3 force = -m_stressForceFactor * data.hitNormal * actor->getPhysXActor().getMass(); - - getBlastController().stressDamage(actor, data.hitPosition, force); - }; - - // Damage Tools: - { - Damager dam; - dam.uiName = "Radial Damage (Falloff)"; - dam.program = NvBlastDamageProgram { NvBlastExtFalloffGraphShader, NvBlastExtFalloffSubgraphShader }; - dam.pointerType = Damager::PointerType::Sphere; - dam.pointerColor = DirectX::XMFLOAT4(1.0f, 1.0f, 1.0f, 0.4f); - dam.executeFunction = radialDamageExecute; - m_damagers.push_back(dam); - } - { - Damager dam; - dam.uiName = "Radial Damage (Cutter)"; - dam.program = NvBlastDamageProgram { NvBlastExtCutterGraphShader, NvBlastExtCutterSubgraphShader }; - dam.pointerType = Damager::PointerType::Sphere; - dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f); - dam.executeFunction = radialDamageExecute; - m_damagers.push_back(dam); - } - - { - Damager dam; - dam.uiName = "Slice Damage"; - dam.program = NvBlastDamageProgram{ NvBlastExtTriangleIntersectionGraphShader, NvBlastExtTriangleIntersectionSubgraphShader }; - dam.pointerType = Damager::PointerType::Line; - dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f); - dam.executeFunction = sliceDamageExecute; - dam.damageWhilePressed = true; - dam.radius = .2f; - dam.radiusLimit = .2f; - m_damagers.push_back(dam); - } - - { - Damager dam; - dam.uiName = "Capsule Damage (Falloff)"; - dam.program = NvBlastDamageProgram{ NvBlastExtCapsuleFalloffGraphShader, NvBlastExtCapsuleFalloffSubgraphShader }; - dam.pointerType = Damager::PointerType::Line; - dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f); - dam.executeFunction = capsuleDamageExecute; - dam.damageWhilePressed = true; - dam.radius = .2f; - dam.radiusLimit = 20.0f; - m_damagers.push_back(dam); - } - - { - Damager dam; - dam.uiName = "Impact Spread Damage"; - dam.program = NvBlastDamageProgram { NvBlastExtImpactSpreadGraphShader, NvBlastExtImpactSpreadSubgraphShader }; - dam.pointerType = Damager::PointerType::Sphere; - dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f); - dam.executeFunction = impulseSpreadDamageExecute; - m_damagers.push_back(dam); - } - - { - Damager dam; - dam.uiName = "Shear Damage"; - dam.program = NvBlastDamageProgram{ NvBlastExtShearGraphShader, NvBlastExtShearSubgraphShader }; - dam.pointerType = Damager::PointerType::Sphere; - dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f); - dam.executeFunction = shearDamageExecute; - m_damagers.push_back(dam); - } - - { - Damager dam; - dam.uiName = "Stress Damage"; - dam.program = { nullptr, nullptr }; - dam.pointerType = Damager::PointerType::Sphere; - dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f); - dam.executeFunction = stressDamageExecute; - m_damagers.push_back(dam); - } - - for (const Damager& d : m_damagers) - { - m_damagerNames.push_back(d.uiName); - } -} - -DamageToolController::~DamageToolController() -{ -} - -void DamageToolController::onSampleStart() -{ - // damage tool pointer - m_toolRenderMaterial = new RenderMaterial(getRenderer().getResourceManager(), "physx_primitive_transparent", "", RenderMaterial::BLEND_ALPHA_BLENDING); - { - IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Sphere); - m_sphereToolRenderable = getRenderer().createRenderable(*mesh, *m_toolRenderMaterial); - } - { - IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Box); - m_lineToolRenderable = getRenderer().createRenderable(*mesh, *m_toolRenderMaterial); - } - - // default tool - m_damagerIndex = 0; - - // start with damage mode by default - setDamageMode(true); -} - -void DamageToolController::onInitialize() -{ -} - - -void DamageToolController::onSampleStop() -{ - getRenderer().removeRenderable(m_sphereToolRenderable); - getRenderer().removeRenderable(m_lineToolRenderable); - SAFE_DELETE(m_toolRenderMaterial); -} - - -void DamageToolController::Animate(double dt) -{ - PROFILER_SCOPED_FUNCTION(); - - m_toolColor = XMFLOAT4Lerp(m_toolColor, m_damagers[m_damagerIndex].pointerColor, dt * 5.0f); - - m_sphereToolRenderable->setHidden(true); - m_lineToolRenderable->setHidden(true); - - // damage mode - if (m_damageMode) - { - const Damager& damager = m_damagers[m_damagerIndex]; - - // ray cast according to camera + mouse ray - PxVec3 eyePos, pickDir; - getPhysXController().getEyePoseAndPickDir(m_lastMousePos.x, m_lastMousePos.y, eyePos, pickDir); - pickDir = pickDir.getNormalized(); - - PxRaycastHit hit; hit.shape = NULL; - PxRaycastBuffer hit1; - getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL); - hit = hit1.block; - - if (hit.shape || (m_prevWasHit && damager.pointerType == Damager::Line)) - { - PxMat44 cameraViewInv = XMMATRIXToPxMat44(getRenderer().getCamera().GetViewMatrix()).inverseRT(); - PxVec3 weaponOrigin = eyePos + cameraViewInv.rotate(WEAPON_POSITION_IN_VIEW); - PxVec3 weaponDir = (hit.position - weaponOrigin).getNormalized(); - - // damage function - auto damageFunction = [&](ExtPxActor* actor, BlastFamily& family) - { - auto t0 = actor->getPhysXActor().getGlobalPose(); - PxTransform t(t0.getInverse()); - Damager::DamageData data; - data.hitNormal = t.rotate(hit.normal); - data.hitPosition = t.transform(hit.position); - data.origin = t.transform(weaponOrigin); - data.weaponDir = t.rotate(weaponDir); - data.previousWeaponDir = t.rotate(m_previousPickDir); - damager.executeFunction(&damager, actor, family, data); - }; - - // should damage? - bool shouldDamage = false; - if (m_isMousePressed) - { - shouldDamage = damager.damageWhilePressed || m_damageCountWhilePressed == 0; - m_damageCountWhilePressed++; - } - else - { - m_damageCountWhilePressed = 0; - } - - // Update tool pointer and do damage with specific overlap - if (damager.pointerType == Damager::Sphere) - { - m_sphereToolRenderable->setHidden(false); - m_sphereToolRenderable->setColor(m_toolColor); - m_sphereToolRenderable->setScale(PxVec3(damager.radius)); - m_sphereToolRenderable->setTransform(PxTransform(hit.position)); - - if (shouldDamage) - { - if (getBlastController().overlap(PxSphereGeometry(damager.radius), PxTransform(hit.position), damageFunction)) - { - m_toolColor = PICK_POINTER_ACTIVE_COLOR; - } - getPhysXController().explodeDelayed(hit.position, damager.radius, m_explosiveImpulse); - } - } - else if (damager.pointerType == Damager::Line) - { - m_lineToolRenderable->setHidden(false); - m_lineToolRenderable->setColor(m_toolColor); - - PxVec3 scale(damager.radius, damager.radius, SEGMENT_DAMAGE_MAX_DISTANCE); - PxVec3 direction = (hit.position - weaponOrigin).getNormalized(); - PxVec3 position = weaponOrigin + direction * SEGMENT_DAMAGE_MAX_DISTANCE; - - m_lineToolRenderable->setScale(scale); - PxTransform t(position, quatLookAt(direction)); - m_lineToolRenderable->setTransform(t); - - if (shouldDamage) - { - if (this->getBlastController().overlap(PxBoxGeometry(scale), t, damageFunction)) - { - m_toolColor = PICK_POINTER_ACTIVE_COLOR; - } - } - } - else - { - PX_ASSERT(false); - } - - m_previousPickDir = weaponDir; - m_prevWasHit = true; - } - else - { - m_prevWasHit = false; - } - } -} - - -LRESULT DamageToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - PROFILER_SCOPED_FUNCTION(); - - if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP) - { - m_lastMousePos.x = (short)LOWORD(lParam) / getRenderer().getScreenWidth(); - m_lastMousePos.y = (short)HIWORD(lParam) / getRenderer().getScreenHeight(); - } - - if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) - { - m_isMousePressed = (uMsg == WM_LBUTTONDOWN); - } - - if (uMsg == WM_MOUSEWHEEL) - { - int delta = int((short)HIWORD(wParam)) / WHEEL_DELTA; - changeDamageRadius(delta * 0.3f); - } - - if (uMsg == WM_KEYDOWN) - { - int iKeyPressed = static_cast(wParam); - if (iKeyPressed == VK_OEM_PLUS) - { - changeDamageRadius(0.2f); - } - else if (iKeyPressed == VK_OEM_MINUS) - { - changeDamageRadius(-0.2f); - } - else if (iKeyPressed >= '1' && iKeyPressed <= '9') - { - m_damagerIndex = PxClamp(iKeyPressed - '1', 0, (uint32_t)m_damagers.size() - 1); - } - else if (iKeyPressed == VK_SPACE) - { - setDamageMode(!isDamageMode()); - } - } - - return 1; -} - -void DamageToolController::drawUI() -{ - ImGui::DragFloat("Damage Amount", &m_damage, 1.0f); - ImGui::DragFloat("Explosive Impulse", &m_explosiveImpulse); - ImGui::DragFloat("Stress Damage Force", &m_stressForceFactor); - - // - - - - - - - - - ImGui::Spacing(); - - // Armory - ImGui::Combo("Damage Profile", (int*)&m_damagerIndex, m_damagerNames.data(), (int)m_damagerNames.size(), -1); - Damager& damager = m_damagers[m_damagerIndex]; - ImGui::DragFloat("Damage Radius (Mouse WH)", &damager.radius); - ImGui::Checkbox("Damage Continuously", &damager.damageWhilePressed); -} - -void DamageToolController::setDamageMode(bool enabled) -{ - m_damageMode = enabled; - - getPhysXController().setDraggingEnabled(!m_damageMode); - - if (!m_damageMode) - { - m_sphereToolRenderable->setHidden(true); - m_lineToolRenderable->setHidden(true); - } -} - -void DamageToolController::changeDamageRadius(float dr) -{ - Damager& damager = m_damagers[m_damagerIndex]; - damager.radius += dr; - damager.radius = PxClamp(damager.radius, 0.05f, damager.radiusLimit); -} +// 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 "DamageToolController.h" +#include "RenderUtils.h" +#include "BlastController.h" +#include "Renderer.h" +#include "PhysXController.h" +#include "SampleProfiler.h" + +#include + +#include "NvBlastTkActor.h" +#include "NvBlastTkFamily.h" +#include "NvBlastExtDamageShaders.h" +#include "NvBlastExtPxActor.h" +#include "NvBlastExtPxFamily.h" + +#include "PxRigidDynamic.h" +#include "PxScene.h" + + +using namespace Nv::Blast; +using namespace physx; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Setup +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const DirectX::XMFLOAT4 PICK_POINTER_ACTIVE_COLOR(1.0f, 0.f, 0.f, 0.6f); +static const PxVec3 WEAPON_POSITION_IN_VIEW(0, -7, 23); +static const float SEGMENT_DAMAGE_MAX_DISTANCE = 100.0f; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +DamageToolController::DamageToolController() + : m_damage(100.0f), m_toolColor(1.0f, 1.0f, 1.0f, 0.4f), + m_toolRenderMaterial(nullptr), m_sphereToolRenderable(nullptr), m_lineToolRenderable(nullptr), + m_explosiveImpulse(100), m_damagerIndex(0), m_stressForceFactor(1.0f), m_isMousePressed(false), m_damageCountWhilePressed(0) +{ + // damage amount calc using NvBlastExtMaterial + auto getDamageAmountFn = [](const float damage, ExtPxActor* actor) + { + const NvBlastExtMaterial* material = actor->getFamily().getMaterial(); + return material ? material->getNormalizedDamage(damage) : 0.f; + }; + + // Damage functions + auto radialDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) + { + const float damage = getDamageAmountFn(m_damage, actor); + if (damage > 0.f) + { + NvBlastExtRadialDamageDesc desc = + { + damage, + { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z }, + damager->radius, + damager->radius * 1.6f + }; + + getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc)); + } + }; + auto sliceDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) + { + const float damage = getDamageAmountFn(m_damage, actor); + if (damage > 0.f) + { + PxVec3 farEnd = data.origin + data.weaponDir * 1000.0f; + PxVec3 farEndPrev = data.origin + data.previousWeaponDir * 1000.0f; + + NvBlastExtTriangleIntersectionDamageDesc desc = + { + damage, + { data.origin.x, data.origin.y, data.origin.z }, + { farEnd.x, farEnd.y, farEnd.z }, + { farEndPrev.x, farEndPrev.y, farEndPrev.z }, + }; + + getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc)); + } + }; + auto capsuleDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) + { + const float damage = getDamageAmountFn(m_damage, actor); + if (damage > 0.f) + { + PxVec3 dir = (data.hitPosition - data.origin).getNormalized(); + PxVec3 farEnd = data.origin + dir * 10000.0f; + + NvBlastExtCapsuleRadialDamageDesc desc = + { + damage, + { data.origin.x, data.origin.y, data.origin.z }, + { farEnd.x, farEnd.y, farEnd.z }, + damager->radius, + damager->radius * 1.6f + }; + + getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc)); + } + }; + auto impulseSpreadDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) + { + const float damage = m_damage; + if (damage > 0.f) + { + PxVec3 impactNormal = -data.hitNormal; + + NvBlastExtImpactSpreadDamageDesc desc = + { + damage, + { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z }, + damager->radius, + damager->radius * 1.6f + }; + + getBlastController().immediateDamage(actor, family, damager->program, &desc); + } + }; + auto shearDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) + { + const float damage = getDamageAmountFn(m_damage, actor); + if (damage > 0.f) + { + PxVec3 impactNormal = -data.hitNormal; + + NvBlastExtShearDamageDesc desc = + { + damage, + { impactNormal.x, impactNormal.y, impactNormal.z }, + { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z }, + damager->radius, + damager->radius * 1.6f + }; + + getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc)); + } + }; + auto stressDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data) + { + PxVec3 force = -m_stressForceFactor * data.hitNormal * actor->getPhysXActor().getMass(); + + getBlastController().stressDamage(actor, data.hitPosition, force); + }; + + // Damage Tools: + { + Damager dam; + dam.uiName = "Radial Damage (Falloff)"; + dam.program = NvBlastDamageProgram { NvBlastExtFalloffGraphShader, NvBlastExtFalloffSubgraphShader }; + dam.pointerType = Damager::PointerType::Sphere; + dam.pointerColor = DirectX::XMFLOAT4(1.0f, 1.0f, 1.0f, 0.4f); + dam.executeFunction = radialDamageExecute; + m_damagers.push_back(dam); + } + { + Damager dam; + dam.uiName = "Radial Damage (Cutter)"; + dam.program = NvBlastDamageProgram { NvBlastExtCutterGraphShader, NvBlastExtCutterSubgraphShader }; + dam.pointerType = Damager::PointerType::Sphere; + dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f); + dam.executeFunction = radialDamageExecute; + m_damagers.push_back(dam); + } + + { + Damager dam; + dam.uiName = "Slice Damage"; + dam.program = NvBlastDamageProgram{ NvBlastExtTriangleIntersectionGraphShader, NvBlastExtTriangleIntersectionSubgraphShader }; + dam.pointerType = Damager::PointerType::Line; + dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f); + dam.executeFunction = sliceDamageExecute; + dam.damageWhilePressed = true; + dam.radius = .2f; + dam.radiusLimit = .2f; + m_damagers.push_back(dam); + } + + { + Damager dam; + dam.uiName = "Capsule Damage (Falloff)"; + dam.program = NvBlastDamageProgram{ NvBlastExtCapsuleFalloffGraphShader, NvBlastExtCapsuleFalloffSubgraphShader }; + dam.pointerType = Damager::PointerType::Line; + dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f); + dam.executeFunction = capsuleDamageExecute; + dam.damageWhilePressed = true; + dam.radius = .2f; + dam.radiusLimit = 20.0f; + m_damagers.push_back(dam); + } + + { + Damager dam; + dam.uiName = "Impact Spread Damage"; + dam.program = NvBlastDamageProgram { NvBlastExtImpactSpreadGraphShader, NvBlastExtImpactSpreadSubgraphShader }; + dam.pointerType = Damager::PointerType::Sphere; + dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f); + dam.executeFunction = impulseSpreadDamageExecute; + m_damagers.push_back(dam); + } + + { + Damager dam; + dam.uiName = "Shear Damage"; + dam.program = NvBlastDamageProgram{ NvBlastExtShearGraphShader, NvBlastExtShearSubgraphShader }; + dam.pointerType = Damager::PointerType::Sphere; + dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f); + dam.executeFunction = shearDamageExecute; + m_damagers.push_back(dam); + } + + { + Damager dam; + dam.uiName = "Stress Damage"; + dam.program = { nullptr, nullptr }; + dam.pointerType = Damager::PointerType::Sphere; + dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f); + dam.executeFunction = stressDamageExecute; + m_damagers.push_back(dam); + } + + for (const Damager& d : m_damagers) + { + m_damagerNames.push_back(d.uiName); + } +} + +DamageToolController::~DamageToolController() +{ +} + +void DamageToolController::onSampleStart() +{ + // damage tool pointer + m_toolRenderMaterial = new RenderMaterial(getRenderer().getResourceManager(), "physx_primitive_transparent", "", RenderMaterial::BLEND_ALPHA_BLENDING); + { + IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Sphere); + m_sphereToolRenderable = getRenderer().createRenderable(*mesh, *m_toolRenderMaterial); + } + { + IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Box); + m_lineToolRenderable = getRenderer().createRenderable(*mesh, *m_toolRenderMaterial); + } + + // default tool + m_damagerIndex = 0; + + // start with damage mode by default + setDamageMode(true); +} + +void DamageToolController::onInitialize() +{ +} + + +void DamageToolController::onSampleStop() +{ + getRenderer().removeRenderable(m_sphereToolRenderable); + getRenderer().removeRenderable(m_lineToolRenderable); + SAFE_DELETE(m_toolRenderMaterial); +} + + +void DamageToolController::Animate(double dt) +{ + PROFILER_SCOPED_FUNCTION(); + + m_toolColor = XMFLOAT4Lerp(m_toolColor, m_damagers[m_damagerIndex].pointerColor, dt * 5.0f); + + m_sphereToolRenderable->setHidden(true); + m_lineToolRenderable->setHidden(true); + + // damage mode + if (m_damageMode) + { + const Damager& damager = m_damagers[m_damagerIndex]; + + // ray cast according to camera + mouse ray + PxVec3 eyePos, pickDir; + getPhysXController().getEyePoseAndPickDir(m_lastMousePos.x, m_lastMousePos.y, eyePos, pickDir); + pickDir = pickDir.getNormalized(); + + PxRaycastHit hit; hit.shape = NULL; + PxRaycastBuffer hit1; + getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL); + hit = hit1.block; + + if (hit.shape || (m_prevWasHit && damager.pointerType == Damager::Line)) + { + PxMat44 cameraViewInv = XMMATRIXToPxMat44(getRenderer().getCamera().GetViewMatrix()).inverseRT(); + PxVec3 weaponOrigin = eyePos + cameraViewInv.rotate(WEAPON_POSITION_IN_VIEW); + PxVec3 weaponDir = (hit.position - weaponOrigin).getNormalized(); + + // damage function + auto damageFunction = [&](ExtPxActor* actor, BlastFamily& family) + { + auto t0 = actor->getPhysXActor().getGlobalPose(); + PxTransform t(t0.getInverse()); + Damager::DamageData data; + data.hitNormal = t.rotate(hit.normal); + data.hitPosition = t.transform(hit.position); + data.origin = t.transform(weaponOrigin); + data.weaponDir = t.rotate(weaponDir); + data.previousWeaponDir = t.rotate(m_previousPickDir); + damager.executeFunction(&damager, actor, family, data); + }; + + // should damage? + bool shouldDamage = false; + if (m_isMousePressed) + { + shouldDamage = damager.damageWhilePressed || m_damageCountWhilePressed == 0; + m_damageCountWhilePressed++; + } + else + { + m_damageCountWhilePressed = 0; + } + + // Update tool pointer and do damage with specific overlap + if (damager.pointerType == Damager::Sphere) + { + m_sphereToolRenderable->setHidden(false); + m_sphereToolRenderable->setColor(m_toolColor); + m_sphereToolRenderable->setScale(PxVec3(damager.radius)); + m_sphereToolRenderable->setTransform(PxTransform(hit.position)); + + if (shouldDamage) + { + if (getBlastController().overlap(PxSphereGeometry(damager.radius), PxTransform(hit.position), damageFunction)) + { + m_toolColor = PICK_POINTER_ACTIVE_COLOR; + } + getPhysXController().explodeDelayed(hit.position, damager.radius, m_explosiveImpulse); + } + } + else if (damager.pointerType == Damager::Line) + { + m_lineToolRenderable->setHidden(false); + m_lineToolRenderable->setColor(m_toolColor); + + PxVec3 scale(damager.radius, damager.radius, SEGMENT_DAMAGE_MAX_DISTANCE); + PxVec3 direction = (hit.position - weaponOrigin).getNormalized(); + PxVec3 position = weaponOrigin + direction * SEGMENT_DAMAGE_MAX_DISTANCE; + + m_lineToolRenderable->setScale(scale); + PxTransform t(position, quatLookAt(direction)); + m_lineToolRenderable->setTransform(t); + + if (shouldDamage) + { + if (this->getBlastController().overlap(PxBoxGeometry(scale), t, damageFunction)) + { + m_toolColor = PICK_POINTER_ACTIVE_COLOR; + } + } + } + else + { + PX_ASSERT(false); + } + + m_previousPickDir = weaponDir; + m_prevWasHit = true; + } + else + { + m_prevWasHit = false; + } + } +} + + +LRESULT DamageToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + PROFILER_SCOPED_FUNCTION(); + + if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP) + { + m_lastMousePos.x = (short)LOWORD(lParam) / getRenderer().getScreenWidth(); + m_lastMousePos.y = (short)HIWORD(lParam) / getRenderer().getScreenHeight(); + } + + if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) + { + m_isMousePressed = (uMsg == WM_LBUTTONDOWN); + } + + if (uMsg == WM_MOUSEWHEEL) + { + int delta = int((short)HIWORD(wParam)) / WHEEL_DELTA; + changeDamageRadius(delta * 0.3f); + } + + if (uMsg == WM_KEYDOWN) + { + int iKeyPressed = static_cast(wParam); + if (iKeyPressed == VK_OEM_PLUS) + { + changeDamageRadius(0.2f); + } + else if (iKeyPressed == VK_OEM_MINUS) + { + changeDamageRadius(-0.2f); + } + else if (iKeyPressed >= '1' && iKeyPressed <= '9') + { + m_damagerIndex = PxClamp(iKeyPressed - '1', 0, (uint32_t)m_damagers.size() - 1); + } + else if (iKeyPressed == VK_SPACE) + { + setDamageMode(!isDamageMode()); + } + } + + return 1; +} + +void DamageToolController::drawUI() +{ + ImGui::DragFloat("Damage Amount", &m_damage, 1.0f); + ImGui::DragFloat("Explosive Impulse", &m_explosiveImpulse); + ImGui::DragFloat("Stress Damage Force", &m_stressForceFactor); + + // - - - - - - - - + ImGui::Spacing(); + + // Armory + ImGui::Combo("Damage Profile", (int*)&m_damagerIndex, m_damagerNames.data(), (int)m_damagerNames.size(), -1); + Damager& damager = m_damagers[m_damagerIndex]; + ImGui::DragFloat("Damage Radius (Mouse WH)", &damager.radius); + ImGui::Checkbox("Damage Continuously", &damager.damageWhilePressed); +} + +void DamageToolController::setDamageMode(bool enabled) +{ + m_damageMode = enabled; + + getPhysXController().setDraggingEnabled(!m_damageMode); + + if (!m_damageMode) + { + m_sphereToolRenderable->setHidden(true); + m_lineToolRenderable->setHidden(true); + } +} + +void DamageToolController::changeDamageRadius(float dr) +{ + Damager& damager = m_damagers[m_damagerIndex]; + damager.radius += dr; + damager.radius = PxClamp(damager.radius, 0.05f, damager.radiusLimit); +} diff --git a/samples/SampleBase/ui/DamageToolController.h b/samples/SampleBase/ui/DamageToolController.h old mode 100644 new mode 100755 index 970bc21..3450734 --- a/samples/SampleBase/ui/DamageToolController.h +++ b/samples/SampleBase/ui/DamageToolController.h @@ -1,160 +1,160 @@ -// 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. - - -#ifndef DAMAGE_TOOL_CONTROLLER_H -#define DAMAGE_TOOL_CONTROLLER_H - -#include "SampleManager.h" -#include "NvBlastTypes.h" -#include -#include -#include "PxVec2.h" -#include "PxVec3.h" - - -class Renderable; -class RenderMaterial; -class BlastFamily; - -namespace Nv -{ -namespace Blast -{ -class ExtPxActor; -} -} - - - -class DamageToolController : public ISampleController -{ -public: - DamageToolController(); - virtual ~DamageToolController(); - - virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - virtual void Animate(double dt); - void drawUI(); - - - virtual void onInitialize(); - virtual void onSampleStart(); - virtual void onSampleStop(); - - bool isDamageMode() const - { - return m_damageMode; - } - -private: - DamageToolController& operator= (DamageToolController&); - - - //////// private methods //////// - - void changeDamageRadius(float dr); - - void setDamageMode(bool enabled); - - - //////// used controllers //////// - - Renderer& getRenderer() const - { - return getManager()->getRenderer(); - } - - PhysXController& getPhysXController() const - { - return getManager()->getPhysXController(); - } - - BlastController& getBlastController() const - { - return getManager()->getBlastController(); - } - - - //////// internal data //////// - - RenderMaterial* m_toolRenderMaterial; - Renderable* m_sphereToolRenderable; - DirectX::XMFLOAT4 m_toolColor; - Renderable* m_lineToolRenderable; - - float m_damage; - float m_explosiveImpulse; - float m_stressForceFactor; - - struct Damager - { - Damager() : damageWhilePressed(false), radius(5.0f), radiusLimit(1000.0f) - { - } - - enum PointerType - { - Sphere, - Line - }; - - struct DamageData - { - physx::PxVec3 origin; - physx::PxVec3 hitPosition; - physx::PxVec3 hitNormal; - physx::PxVec3 weaponDir; - physx::PxVec3 previousWeaponDir; - }; - - typedef std::function ExecuteFn; - - const char* uiName; - NvBlastDamageProgram program; - PointerType pointerType; - DirectX::XMFLOAT4 pointerColor; - float radius; - float radiusLimit; - bool damageWhilePressed; - ExecuteFn executeFunction; - }; - - std::vector m_damagers; - std::vector m_damagerNames; - uint32_t m_damagerIndex; - - bool m_damageMode; - - physx::PxVec2 m_lastMousePos; - bool m_isMousePressed; - uint32_t m_damageCountWhilePressed; - physx::PxVec3 m_previousPickDir; - bool m_prevWasHit; -}; - +// 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. + + +#ifndef DAMAGE_TOOL_CONTROLLER_H +#define DAMAGE_TOOL_CONTROLLER_H + +#include "SampleManager.h" +#include "NvBlastTypes.h" +#include +#include +#include "PxVec2.h" +#include "PxVec3.h" + + +class Renderable; +class RenderMaterial; +class BlastFamily; + +namespace Nv +{ +namespace Blast +{ +class ExtPxActor; +} +} + + + +class DamageToolController : public ISampleController +{ +public: + DamageToolController(); + virtual ~DamageToolController(); + + virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual void Animate(double dt); + void drawUI(); + + + virtual void onInitialize(); + virtual void onSampleStart(); + virtual void onSampleStop(); + + bool isDamageMode() const + { + return m_damageMode; + } + +private: + DamageToolController& operator= (DamageToolController&); + + + //////// private methods //////// + + void changeDamageRadius(float dr); + + void setDamageMode(bool enabled); + + + //////// used controllers //////// + + Renderer& getRenderer() const + { + return getManager()->getRenderer(); + } + + PhysXController& getPhysXController() const + { + return getManager()->getPhysXController(); + } + + BlastController& getBlastController() const + { + return getManager()->getBlastController(); + } + + + //////// internal data //////// + + RenderMaterial* m_toolRenderMaterial; + Renderable* m_sphereToolRenderable; + DirectX::XMFLOAT4 m_toolColor; + Renderable* m_lineToolRenderable; + + float m_damage; + float m_explosiveImpulse; + float m_stressForceFactor; + + struct Damager + { + Damager() : damageWhilePressed(false), radius(5.0f), radiusLimit(1000.0f) + { + } + + enum PointerType + { + Sphere, + Line + }; + + struct DamageData + { + physx::PxVec3 origin; + physx::PxVec3 hitPosition; + physx::PxVec3 hitNormal; + physx::PxVec3 weaponDir; + physx::PxVec3 previousWeaponDir; + }; + + typedef std::function ExecuteFn; + + const char* uiName; + NvBlastDamageProgram program; + PointerType pointerType; + DirectX::XMFLOAT4 pointerColor; + float radius; + float radiusLimit; + bool damageWhilePressed; + ExecuteFn executeFunction; + }; + + std::vector m_damagers; + std::vector m_damagerNames; + uint32_t m_damagerIndex; + + bool m_damageMode; + + physx::PxVec2 m_lastMousePos; + bool m_isMousePressed; + uint32_t m_damageCountWhilePressed; + physx::PxVec3 m_previousPickDir; + bool m_prevWasHit; +}; + #endif \ No newline at end of file diff --git a/samples/SampleBase/ui/imgui_impl_dx11.cpp b/samples/SampleBase/ui/imgui_impl_dx11.cpp old mode 100644 new mode 100755 index 11f66f0..42d0892 --- a/samples/SampleBase/ui/imgui_impl_dx11.cpp +++ b/samples/SampleBase/ui/imgui_impl_dx11.cpp @@ -1,583 +1,583 @@ -// ImGui Win32 + DirectX11 binding -// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. - -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). -// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui - -#include -#include "imgui_impl_dx11.h" - -// DirectX -#include -#include -#define DIRECTINPUT_VERSION 0x0800 -#include - -// Data -static INT64 g_Time = 0; -static INT64 g_TicksPerSecond = 0; - -static HWND g_hWnd = 0; -static ID3D11Device* g_pd3dDevice = NULL; -static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; -static ID3D11Buffer* g_pVB = NULL; -static ID3D11Buffer* g_pIB = NULL; -static ID3D10Blob * g_pVertexShaderBlob = NULL; -static ID3D11VertexShader* g_pVertexShader = NULL; -static ID3D11InputLayout* g_pInputLayout = NULL; -static ID3D11Buffer* g_pVertexConstantBuffer = NULL; -static ID3D10Blob * g_pPixelShaderBlob = NULL; -static ID3D11PixelShader* g_pPixelShader = NULL; -static ID3D11SamplerState* g_pFontSampler = NULL; -static ID3D11ShaderResourceView*g_pFontTextureView = NULL; -static ID3D11RasterizerState* g_pRasterizerState = NULL; -static ID3D11BlendState* g_pBlendState = NULL; -static ID3D11DepthStencilState* g_pDepthStencilState = NULL; -static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; - -struct VERTEX_CONSTANT_BUFFER -{ - float mvp[4][4]; -}; - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) -{ - ID3D11DeviceContext* ctx = g_pd3dDeviceContext; - - // Create and grow vertex/index buffers if needed - if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) - { - if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } - g_VertexBufferSize = draw_data->TotalVtxCount + 5000; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); - desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) - return; - } - if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) - { - if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } - g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - desc.BindFlags = D3D11_BIND_INDEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) - return; - } - - // Copy and convert all vertices into a single contiguous buffer - D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) - return; - if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) - return; - ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; - ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); - vtx_dst += cmd_list->VtxBuffer.size(); - idx_dst += cmd_list->IdxBuffer.size(); - } - ctx->Unmap(g_pVB, 0); - ctx->Unmap(g_pIB, 0); - - // Setup orthographic projection matrix into our constant buffer - { - D3D11_MAPPED_SUBRESOURCE mapped_resource; - if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) - return; - VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; - float L = 0.0f; - float R = ImGui::GetIO().DisplaySize.x; - float B = ImGui::GetIO().DisplaySize.y; - float T = 0.0f; - float mvp[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.5f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, - }; - memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); - ctx->Unmap(g_pVertexConstantBuffer, 0); - } - - // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) - struct BACKUP_DX11_STATE - { - UINT ScissorRectsCount, ViewportsCount; - D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; - D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; - ID3D11RasterizerState* RS; - ID3D11BlendState* BlendState; - FLOAT BlendFactor[4]; - UINT SampleMask; - UINT StencilRef; - ID3D11DepthStencilState* DepthStencilState; - ID3D11ShaderResourceView* PSShaderResource; - ID3D11SamplerState* PSSampler; - ID3D11PixelShader* PS; - ID3D11VertexShader* VS; - UINT PSInstancesCount, VSInstancesCount; - ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation - D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; - ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; - UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; - DXGI_FORMAT IndexBufferFormat; - ID3D11InputLayout* InputLayout; - }; - BACKUP_DX11_STATE old; - old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; - ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); - ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); - ctx->RSGetState(&old.RS); - ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); - ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); - ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); - ctx->PSGetSamplers(0, 1, &old.PSSampler); - old.PSInstancesCount = old.VSInstancesCount = 256; - ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); - ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); - ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); - ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); - ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); - ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); - ctx->IAGetInputLayout(&old.InputLayout); - - // Setup viewport - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = vp.TopLeftY = 0.0f; - ctx->RSSetViewports(1, &vp); - - // Bind shader and vertex buffers - unsigned int stride = sizeof(ImDrawVert); - unsigned int offset = 0; - ctx->IASetInputLayout(g_pInputLayout); - ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ctx->VSSetShader(g_pVertexShader, NULL, 0); - ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - ctx->PSSetShader(g_pPixelShader, NULL, 0); - ctx->PSSetSamplers(0, 1, &g_pFontSampler); - - // Setup render state - const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; - ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); - ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); - ctx->RSSetState(g_pRasterizerState); - - // Render command lists - int vtx_offset = 0; - int idx_offset = 0; - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - ctx->RSSetScissorRects(1, &r); - ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); - } - idx_offset += pcmd->ElemCount; - } - vtx_offset += cmd_list->VtxBuffer.size(); - } - - // Restore modified DX state - ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); - ctx->RSSetViewports(old.ViewportsCount, old.Viewports); - ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); - ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); - ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); - ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); - ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); - ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); - for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); - ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); - ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); - for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); - ctx->IASetPrimitiveTopology(old.PrimitiveTopology); - ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); - ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); - ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); -} - -IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) -{ - ImGuiIO& io = ImGui::GetIO(); - switch (msg) - { - case WM_LBUTTONDOWN: - io.MouseDown[0] = true; - return true; - case WM_LBUTTONUP: - io.MouseDown[0] = false; - return true; - case WM_RBUTTONDOWN: - io.MouseDown[1] = true; - return true; - case WM_RBUTTONUP: - io.MouseDown[1] = false; - return true; - case WM_MBUTTONDOWN: - io.MouseDown[2] = true; - return true; - case WM_MBUTTONUP: - io.MouseDown[2] = false; - return true; - case WM_MOUSEWHEEL: - io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; - return true; - case WM_MOUSEMOVE: - io.MousePos.x = (signed short)(lParam); - io.MousePos.y = (signed short)(lParam >> 16); - return true; - case WM_KEYDOWN: - if (wParam < 256) - io.KeysDown[wParam] = 1; - return true; - case WM_KEYUP: - if (wParam < 256) - io.KeysDown[wParam] = 0; - return true; - case WM_CHAR: - // You can also use ToAscii()+GetKeyboardState() to retrieve characters. - if (wParam > 0 && wParam < 0x10000) - io.AddInputCharacter((unsigned short)wParam); - return true; - } - return 0; -} - -static void ImGui_ImplDX11_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - // Upload texture to graphics system - { - D3D11_TEXTURE2D_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - - ID3D11Texture2D *pTexture = NULL; - D3D11_SUBRESOURCE_DATA subResource; - subResource.pSysMem = pixels; - subResource.SysMemPitch = desc.Width * 4; - subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); - - // Create texture view - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = desc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); - pTexture->Release(); - } - - // Store our identifier - io.Fonts->TexID = (void *)g_pFontTextureView; - - // Create texture sampler - { - D3D11_SAMPLER_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - desc.MipLODBias = 0.f; - desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - desc.MinLOD = 0.f; - desc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); - } -} - -bool ImGui_ImplDX11_CreateDeviceObjects() -{ - if (!g_pd3dDevice) - return false; - if (g_pFontSampler) - ImGui_ImplDX11_InvalidateDeviceObjects(); - - // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) - // If you would like to use this DX11 sample code but remove this dependency you can: - // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [prefered solution] - // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. - // See https://github.com/ocornut/imgui/pull/638 for sources and details. - - // Create the vertex shader - { - static const char* vertexShader = - "cbuffer vertexBuffer : register(b0) \ - {\ - float4x4 ProjectionMatrix; \ - };\ - struct VS_INPUT\ - {\ - float2 pos : POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - \ - struct PS_INPUT\ - {\ - float4 pos : SV_POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - \ - PS_INPUT main(VS_INPUT input)\ - {\ - PS_INPUT output;\ - output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ - output.col = input.col;\ - output.uv = input.uv;\ - return output;\ - }"; - - D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL); - if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! - return false; - if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK) - return false; - - // Create the input layout - D3D11_INPUT_ELEMENT_DESC local_layout[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) - return false; - - // Create the constant buffer - { - D3D11_BUFFER_DESC desc; - desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); - } - } - - // Create the pixel shader - { - static const char* pixelShader = - "struct PS_INPUT\ - {\ - float4 pos : SV_POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - sampler sampler0;\ - Texture2D texture0;\ - \ - float4 main(PS_INPUT input) : SV_Target\ - {\ - float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ - return out_col; \ - }"; - - D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL); - if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! - return false; - if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK) - return false; - } - - // Create the blending setup - { - D3D11_BLEND_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.AlphaToCoverageEnable = false; - desc.RenderTarget[0].BlendEnable = true; - desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; - desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; - desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); - } - - // Create the rasterizer state - { - D3D11_RASTERIZER_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.FillMode = D3D11_FILL_SOLID; - desc.CullMode = D3D11_CULL_NONE; - desc.ScissorEnable = true; - desc.DepthClipEnable = true; - g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); - } - - // Create depth-stencil State - { - D3D11_DEPTH_STENCIL_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.DepthEnable = false; - desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - desc.DepthFunc = D3D11_COMPARISON_ALWAYS; - desc.StencilEnable = false; - desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - desc.BackFace = desc.FrontFace; - g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); - } - - ImGui_ImplDX11_CreateFontsTexture(); - - return true; -} - -void ImGui_ImplDX11_InvalidateDeviceObjects() -{ - if (!g_pd3dDevice) - return; - - if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } - if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = 0; } - if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } - if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } - - if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } - if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } - if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } - if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } - if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } - if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } - if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } - if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } - if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } -} - -bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context) -{ - g_hWnd = (HWND)hwnd; - g_pd3dDevice = device; - g_pd3dDeviceContext = device_context; - - if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) - return false; - if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) - return false; - - ImGuiIO& io = ImGui::GetIO(); - io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime. - io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; - io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; - io.KeyMap[ImGuiKey_UpArrow] = VK_UP; - io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; - io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; - io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; - io.KeyMap[ImGuiKey_Home] = VK_HOME; - io.KeyMap[ImGuiKey_End] = VK_END; - io.KeyMap[ImGuiKey_Delete] = VK_DELETE; - io.KeyMap[ImGuiKey_Backspace] = VK_BACK; - io.KeyMap[ImGuiKey_Enter] = VK_RETURN; - io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; - io.KeyMap[ImGuiKey_A] = 'A'; - io.KeyMap[ImGuiKey_C] = 'C'; - io.KeyMap[ImGuiKey_V] = 'V'; - io.KeyMap[ImGuiKey_X] = 'X'; - io.KeyMap[ImGuiKey_Y] = 'Y'; - io.KeyMap[ImGuiKey_Z] = 'Z'; - - io.RenderDrawListsFn = ImGui_ImplDX11_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. - io.ImeWindowHandle = g_hWnd; - - return true; -} - -void ImGui_ImplDX11_Shutdown() -{ - ImGui_ImplDX11_InvalidateDeviceObjects(); - ImGui::Shutdown(); - g_pd3dDevice = NULL; - g_pd3dDeviceContext = NULL; - g_hWnd = (HWND)0; -} - -void ImGui_ImplDX11_NewFrame() -{ - if (!g_pFontSampler) - ImGui_ImplDX11_CreateDeviceObjects(); - - ImGuiIO& io = ImGui::GetIO(); - - // Setup display size (every frame to accommodate for window resizing) - RECT rect; - GetClientRect(g_hWnd, &rect); - io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); - - // Setup time step - INT64 current_time; - QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); - io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; - g_Time = current_time; - - // Read keyboard modifiers inputs - io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; - io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; - io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; - io.KeySuper = false; - // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events - // io.MousePos : filled by WM_MOUSEMOVE events - // io.MouseDown : filled by WM_*BUTTON* events - // io.MouseWheel : filled by WM_MOUSEWHEEL events - - // Hide OS mouse cursor if ImGui is drawing it - SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW)); - - // Start the frame - ImGui::NewFrame(); -} +// ImGui Win32 + DirectX11 binding +// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include +#include "imgui_impl_dx11.h" + +// DirectX +#include +#include +#define DIRECTINPUT_VERSION 0x0800 +#include + +// Data +static INT64 g_Time = 0; +static INT64 g_TicksPerSecond = 0; + +static HWND g_hWnd = 0; +static ID3D11Device* g_pd3dDevice = NULL; +static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; +static ID3D11Buffer* g_pVB = NULL; +static ID3D11Buffer* g_pIB = NULL; +static ID3D10Blob * g_pVertexShaderBlob = NULL; +static ID3D11VertexShader* g_pVertexShader = NULL; +static ID3D11InputLayout* g_pInputLayout = NULL; +static ID3D11Buffer* g_pVertexConstantBuffer = NULL; +static ID3D10Blob * g_pPixelShaderBlob = NULL; +static ID3D11PixelShader* g_pPixelShader = NULL; +static ID3D11SamplerState* g_pFontSampler = NULL; +static ID3D11ShaderResourceView*g_pFontTextureView = NULL; +static ID3D11RasterizerState* g_pRasterizerState = NULL; +static ID3D11BlendState* g_pBlendState = NULL; +static ID3D11DepthStencilState* g_pDepthStencilState = NULL; +static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; + +struct VERTEX_CONSTANT_BUFFER +{ + float mvp[4][4]; +}; + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) +{ + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + + // Create and grow vertex/index buffers if needed + if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) + { + if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } + g_VertexBufferSize = draw_data->TotalVtxCount + 5000; + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + return; + } + if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) + { + if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } + g_IndexBufferSize = draw_data->TotalIdxCount + 10000; + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) + return; + } + + // Copy and convert all vertices into a single contiguous buffer + D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + return; + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + return; + ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; + ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); + + // Setup orthographic projection matrix into our constant buffer + { + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) + return; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.5f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, + }; + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); + } + + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE + { + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + UINT StencilRef; + ID3D11DepthStencilState* DepthStencilState; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); + + // Bind shader and vertex buffers + unsigned int stride = sizeof(ImDrawVert); + unsigned int offset = 0; + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); + + // Setup render state + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); + ctx->RSSetState(g_pRasterizerState); + + // Render command lists + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } + + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); +} + +IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +{ + ImGuiIO& io = ImGui::GetIO(); + switch (msg) + { + case WM_LBUTTONDOWN: + io.MouseDown[0] = true; + return true; + case WM_LBUTTONUP: + io.MouseDown[0] = false; + return true; + case WM_RBUTTONDOWN: + io.MouseDown[1] = true; + return true; + case WM_RBUTTONUP: + io.MouseDown[1] = false; + return true; + case WM_MBUTTONDOWN: + io.MouseDown[2] = true; + return true; + case WM_MBUTTONUP: + io.MouseDown[2] = false; + return true; + case WM_MOUSEWHEEL: + io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; + return true; + case WM_MOUSEMOVE: + io.MousePos.x = (signed short)(lParam); + io.MousePos.y = (signed short)(lParam >> 16); + return true; + case WM_KEYDOWN: + if (wParam < 256) + io.KeysDown[wParam] = 1; + return true; + case WM_KEYUP: + if (wParam < 256) + io.KeysDown[wParam] = 0; + return true; + case WM_CHAR: + // You can also use ToAscii()+GetKeyboardState() to retrieve characters. + if (wParam > 0 && wParam < 0x10000) + io.AddInputCharacter((unsigned short)wParam); + return true; + } + return 0; +} + +static void ImGui_ImplDX11_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + + // Upload texture to graphics system + { + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + + ID3D11Texture2D *pTexture = NULL; + D3D11_SUBRESOURCE_DATA subResource; + subResource.pSysMem = pixels; + subResource.SysMemPitch = desc.Width * 4; + subResource.SysMemSlicePitch = 0; + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); + + // Create texture view + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + ZeroMemory(&srvDesc, sizeof(srvDesc)); + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = desc.MipLevels; + srvDesc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + pTexture->Release(); + } + + // Store our identifier + io.Fonts->TexID = (void *)g_pFontTextureView; + + // Create texture sampler + { + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); + } +} + +bool ImGui_ImplDX11_CreateDeviceObjects() +{ + if (!g_pd3dDevice) + return false; + if (g_pFontSampler) + ImGui_ImplDX11_InvalidateDeviceObjects(); + + // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) + // If you would like to use this DX11 sample code but remove this dependency you can: + // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [prefered solution] + // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. + // See https://github.com/ocornut/imgui/pull/638 for sources and details. + + // Create the vertex shader + { + static const char* vertexShader = + "cbuffer vertexBuffer : register(b0) \ + {\ + float4x4 ProjectionMatrix; \ + };\ + struct VS_INPUT\ + {\ + float2 pos : POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + \ + struct PS_INPUT\ + {\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + \ + PS_INPUT main(VS_INPUT input)\ + {\ + PS_INPUT output;\ + output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ + output.col = input.col;\ + output.uv = input.uv;\ + return output;\ + }"; + + D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL); + if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! + return false; + if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK) + return false; + + // Create the input layout + D3D11_INPUT_ELEMENT_DESC local_layout[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + return false; + + // Create the constant buffer + { + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); + } + } + + // Create the pixel shader + { + static const char* pixelShader = + "struct PS_INPUT\ + {\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + sampler sampler0;\ + Texture2D texture0;\ + \ + float4 main(PS_INPUT input) : SV_Target\ + {\ + float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ + return out_col; \ + }"; + + D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL); + if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! + return false; + if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK) + return false; + } + + // Create the blending setup + { + D3D11_BLEND_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.AlphaToCoverageEnable = false; + desc.RenderTarget[0].BlendEnable = true; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); + } + + // Create the rasterizer state + { + D3D11_RASTERIZER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.FillMode = D3D11_FILL_SOLID; + desc.CullMode = D3D11_CULL_NONE; + desc.ScissorEnable = true; + desc.DepthClipEnable = true; + g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); + } + + // Create depth-stencil State + { + D3D11_DEPTH_STENCIL_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.DepthEnable = false; + desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + desc.DepthFunc = D3D11_COMPARISON_ALWAYS; + desc.StencilEnable = false; + desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + desc.BackFace = desc.FrontFace; + g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); + } + + ImGui_ImplDX11_CreateFontsTexture(); + + return true; +} + +void ImGui_ImplDX11_InvalidateDeviceObjects() +{ + if (!g_pd3dDevice) + return; + + if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } + if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = 0; } + if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } + if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } + + if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } + if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } + if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } + if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } + if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } + if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } + if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } + if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } + if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } +} + +bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context) +{ + g_hWnd = (HWND)hwnd; + g_pd3dDevice = device; + g_pd3dDeviceContext = device_context; + + if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) + return false; + if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) + return false; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime. + io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = VK_UP; + io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; + io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; + io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; + io.KeyMap[ImGuiKey_Home] = VK_HOME; + io.KeyMap[ImGuiKey_End] = VK_END; + io.KeyMap[ImGuiKey_Delete] = VK_DELETE; + io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Enter] = VK_RETURN; + io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; + io.KeyMap[ImGuiKey_A] = 'A'; + io.KeyMap[ImGuiKey_C] = 'C'; + io.KeyMap[ImGuiKey_V] = 'V'; + io.KeyMap[ImGuiKey_X] = 'X'; + io.KeyMap[ImGuiKey_Y] = 'Y'; + io.KeyMap[ImGuiKey_Z] = 'Z'; + + io.RenderDrawListsFn = ImGui_ImplDX11_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.ImeWindowHandle = g_hWnd; + + return true; +} + +void ImGui_ImplDX11_Shutdown() +{ + ImGui_ImplDX11_InvalidateDeviceObjects(); + ImGui::Shutdown(); + g_pd3dDevice = NULL; + g_pd3dDeviceContext = NULL; + g_hWnd = (HWND)0; +} + +void ImGui_ImplDX11_NewFrame() +{ + if (!g_pFontSampler) + ImGui_ImplDX11_CreateDeviceObjects(); + + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + RECT rect; + GetClientRect(g_hWnd, &rect); + io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); + + // Setup time step + INT64 current_time; + QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); + io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; + g_Time = current_time; + + // Read keyboard modifiers inputs + io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; + io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; + io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; + io.KeySuper = false; + // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events + // io.MousePos : filled by WM_MOUSEMOVE events + // io.MouseDown : filled by WM_*BUTTON* events + // io.MouseWheel : filled by WM_MOUSEWHEEL events + + // Hide OS mouse cursor if ImGui is drawing it + SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW)); + + // Start the frame + ImGui::NewFrame(); +} diff --git a/samples/SampleBase/ui/imgui_impl_dx11.h b/samples/SampleBase/ui/imgui_impl_dx11.h old mode 100644 new mode 100755 index 7d6f710..771f5a5 --- a/samples/SampleBase/ui/imgui_impl_dx11.h +++ b/samples/SampleBase/ui/imgui_impl_dx11.h @@ -1,25 +1,25 @@ -// ImGui Win32 + DirectX11 binding -// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. - -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). -// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui - -struct ID3D11Device; -struct ID3D11DeviceContext; - -IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context); -IMGUI_API void ImGui_ImplDX11_Shutdown(); -IMGUI_API void ImGui_ImplDX11_NewFrame(); - -// Use if you want to reset your rendering device without losing ImGui state. -IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects(); -IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects(); - -// Handler for Win32 messages, update mouse/keyboard data. -// You may or not need this for your implementation, but it can serve as reference for handling inputs. -// Commented out to avoid dragging dependencies on types. You can copy the extern declaration in your code. -/* -IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -*/ +// ImGui Win32 + DirectX11 binding +// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct ID3D11Device; +struct ID3D11DeviceContext; + +IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context); +IMGUI_API void ImGui_ImplDX11_Shutdown(); +IMGUI_API void ImGui_ImplDX11_NewFrame(); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects(); + +// Handler for Win32 messages, update mouse/keyboard data. +// You may or not need this for your implementation, but it can serve as reference for handling inputs. +// Commented out to avoid dragging dependencies on types. You can copy the extern declaration in your code. +/* +IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +*/ -- cgit v1.2.3