//-------------------------------------------------------------------------------------- // File: SimpleSample11.cpp // // Starting point for new Direct3D 11 Win32 desktop samples. For a more minimal starting // point, use the EmptyProject11 sample instead. // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- #include "DXUT.h" #include "DXUTgui.h" #include "DXUTmisc.h" #include "DXUTCamera.h" #include "DXUTSettingsDlg.h" #include "SDKmisc.h" #include "SDKmesh.h" #include "resource.h" #include #include #include #include #pragma warning( disable : 4100 ) #include #include #include #include #ifdef GFESDKDEMO_BUILD_C #include "GfeSDKWrapper.h" #else #include "GfeSDKWrapper.hpp" using namespace GfeSDK; #endif #include #include "Splash.h" using namespace DirectX; void TRACE(const char* format, ...) { char buffer[512]; va_list argptr; va_start(argptr, format); vsprintf_s(buffer, sizeof(buffer) / sizeof(buffer[0]), format, argptr); va_end(argptr); OutputDebugStringA(buffer); } //-------------------------------------------------------------------------------------- // Global variables //-------------------------------------------------------------------------------------- CModelViewerCamera g_Camera; // A model viewing camera CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs CDXUTTextHelper* g_pTxtHelper = nullptr; CDXUTDialog g_HUD; // dialog for standard controls CDXUTDialog g_SampleUI; // dialog for sample specific controls XMMATRIX g_mCenterMesh; CDXUTSDKMesh g_Mesh11; // Direct3D 11 resources ID3D11VertexShader* g_pVertexShader11 = nullptr; ID3D11PixelShader* g_pPixelShader11 = nullptr; ID3D11InputLayout* g_pLayout11 = nullptr; ID3D11SamplerState* g_pSamLinear = nullptr; //-------------------------------------------------------------------------------------- // Constant buffers //-------------------------------------------------------------------------------------- #pragma pack(push,1) struct CB_VS_PER_OBJECT { XMFLOAT4X4 m_mWorldViewProjection; XMFLOAT4X4 m_mWorld; XMFLOAT4 m_MaterialAmbientColor; XMFLOAT4 m_MaterialDiffuseColor; }; struct CB_VS_PER_FRAME { XMFLOAT3 m_vLightDir; float m_fTime; XMFLOAT4 m_LightDiffuse; }; #pragma pack(pop) ID3D11Buffer* g_pcbVSPerObject11 = nullptr; ID3D11Buffer* g_pcbVSPerFrame11 = nullptr; enum class AppState { Init, LoadResources, Main }; // Highlights struct HighlightsDataHolder { std::string id; bool isScreenshot; int startDelta; int endDelta; std::vector namePairs; std::map namePairsData; }; struct HighlightsData { std::string gameName; std::string defaultLocale; std::vector highlightsData; std::vector highlights; }; GfeSdkWrapper g_highlights; std::string g_targetPath; int g_targetPid = 0; NVGSDK_HighlightSignificance g_sigFilter = NVGSDK_HIGHLIGHT_SIGNIFICANCE_NONE; NVGSDK_HighlightType g_tagFilter = NVGSDK_HIGHLIGHT_TYPE_NONE; std::wstring_convert> g_converter; HighlightsData g_highlightsConfig; char const* GROUP1_ID = "GROUP1"; char const* GROUP2_ID = "GROUP2"; class SettingsManager { public: enum class BackgroundColor { Default, Red, Blue, }; SettingsManager(const std::wstring& configPath) : m_color(BackgroundColor::Default), m_configPath(configPath) { LoadConfig(); } std::array GetBackgroundColorArray() const { switch (m_color) { case BackgroundColor::Red: return { 0.25f, 0.10f, 0.10f, 0.55f }; case BackgroundColor::Blue: return { 0.10f, 0.10f, 0.25f, 0.55f }; case BackgroundColor::Default: default: return { 0.0f, 0.25f, 0.25f, 0.55f }; } } std::string GetBackgroundColorString() const { switch (m_color) { case BackgroundColor::Red: return "Red"; case BackgroundColor::Blue: return "Blue"; case BackgroundColor::Default: default: return "Default"; } } void ToggleBackgroundColor() { switch (m_color) { case BackgroundColor::Default: m_color = BackgroundColor::Red; break; case BackgroundColor::Red: m_color = BackgroundColor::Blue; break; case BackgroundColor::Blue: m_color = BackgroundColor::Default; break; default: m_color = BackgroundColor::Default; } SaveConfig(); } void SaveConfig() { Json::Value root; root["Background"] = GetBackgroundColorString(); std::ofstream f(m_configPath); if (!f.good()) { TRACE("Cannot open config file for saving!"); return; } f << root; } void LoadConfig() { std::ifstream f(m_configPath); if (!f.good()) { return; } Json::Value root; std::string errs; Json::CharReaderBuilder builder; if (!Json::parseFromStream(builder, f, &root, &errs)) { TRACE("FAILED to read json file\n"); return; } m_color = BackgroundColorFromString(root["Background"].asString()); } private: static BackgroundColor BackgroundColorFromString(const std::string& c) { if (c == "Red") return BackgroundColor::Red; if (c == "Blue") return BackgroundColor::Blue; if (c == "Default") return BackgroundColor::Default; return BackgroundColor::Default; } const std::wstring m_configPath; BackgroundColor m_color; }; std::unique_ptr g_settingsManager; AppState g_state = AppState::Init; //-------------------------------------------------------------------------------------- // Forward declarations //-------------------------------------------------------------------------------------- LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext); void CALLBACK OnKeyboard(UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext); void CALLBACK OnGUIEvent(UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext); void CALLBACK OnFrameMove(double fTime, float fElapsedTime, void* pUserContext); bool CALLBACK ModifyDeviceSettings(DXUTDeviceSettings* pDeviceSettings, void* pUserContext); bool CALLBACK IsD3D11DeviceAcceptable(const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo, DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext); HRESULT CALLBACK OnD3D11CreateDevice(ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext); HRESULT CALLBACK OnD3D11ResizedSwapChain(ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext); void CALLBACK OnD3D11ReleasingSwapChain(void* pUserContext); void CALLBACK OnD3D11DestroyDevice(void* pUserContext); void CALLBACK OnD3D11FrameRender(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext); void CALLBACK OnQuit(void* pUserContext); void InitApp(); void RenderText(); void RenderLoadingText(); static std::string WideToUtf8(std::wstring const& wideStr); //-------------------------------------------------------------------------------------- // Entry point to the program. Initializes everything and goes into a message processing // loop. Idle time is used to render the scene. //-------------------------------------------------------------------------------------- int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { std::wstring exeName; bool link = false; LPWSTR *szArgList; int argCount; szArgList = CommandLineToArgvW(GetCommandLine(), &argCount); if (!szArgList) { TRACE("FAILED to read command line\n"); return -1; } exeName = PathFindFileName(szArgList[0]); for (int i = 0; i < argCount; i++) { if (std::wstring(szArgList[i]) == L"-link" || std::wstring(szArgList[i]) == L"/link") { link = true; } } LocalFree(szArgList); if (link) { // Try to find another instance of the app already running, to link to it. DWORD myPid = GetCurrentProcessId(); PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (Process32FirstW(snapshot, &entry) == TRUE) { while (Process32NextW(snapshot, &entry) == TRUE) { if (exeName == entry.szExeFile && entry.th32ProcessID != myPid) { // Found the target to link to HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); if (hProcess == NULL) { TRACE("Could not open target process"); continue; } wchar_t szTargetFileName[MAX_PATH]; if (GetModuleFileNameExW(hProcess, NULL, szTargetFileName, MAX_PATH) > 0) { TRACE("Found process to link to!"); g_targetPath = WideToUtf8(szTargetFileName); g_targetPid = entry.th32ProcessID; } else { TRACE("Unable to get target path from process handle"); } CloseHandle(hProcess); } } } CloseHandle(snapshot); if (g_targetPath.empty() || g_targetPid == 0) { MessageBox(NULL, L"-link passed but cannot find target process", L"Error", MB_OK); return -1; } } // Enable run-time memory check for debug builds. #ifdef _DEBUG _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif if (ShowSplash(hInstance, IDT_TIMER1, IDB_BITMAP1) == 1) { HideSplash(); return 0; } // DXUT will create and use the best device // that is available on the system depending on which D3D callbacks are set below // Set DXUT callbacks DXUTSetCallbackMsgProc(MsgProc); DXUTSetCallbackKeyboard(OnKeyboard); DXUTSetCallbackFrameMove(OnFrameMove); DXUTSetCallbackDeviceChanging(ModifyDeviceSettings); DXUTSetCallbackD3D11DeviceAcceptable(IsD3D11DeviceAcceptable); DXUTSetCallbackD3D11DeviceCreated(OnD3D11CreateDevice); DXUTSetCallbackD3D11SwapChainResized(OnD3D11ResizedSwapChain); DXUTSetCallbackD3D11SwapChainReleasing(OnD3D11ReleasingSwapChain); DXUTSetCallbackD3D11DeviceDestroyed(OnD3D11DestroyDevice); DXUTSetCallbackD3D11FrameRender(OnD3D11FrameRender); DXUTSetCallbackQuit(OnQuit); InitApp(); DXUTInit(true, true, nullptr); // Parse the command line, show msgboxes on error, no extra command line params DXUTSetCursorSettings(true, true); DXUTCreateWindow(L"SimpleSample11"); // Only require 10-level hardware, change to D3D_FEATURE_LEVEL_11_0 to require 11-class hardware // Switch to D3D_FEATURE_LEVEL_9_x for 10level9 hardware DXUTCreateDevice(D3D_FEATURE_LEVEL_10_0, true, 1280, 1024); HideSplash(); DXUTMainLoop(); // Enter into the DXUT render loop return DXUTGetExitCode(); } void ToggleSignificanceBit(NVGSDK_HighlightSignificance bit) { g_sigFilter = static_cast(g_sigFilter ^ bit); } void ToggleTagBit(NVGSDK_HighlightType bit) { g_tagFilter = static_cast(g_tagFilter ^ bit); } void HandleOpsNotification() { g_settingsManager->LoadConfig(); } std::wstring HK(wchar_t const* str, uint16_t hk_) { uint8_t hk = (0xff & hk_); std::wstring ret = std::wstring(str) + L" ["; if (hk >= VK_F1 && hk <= VK_F12) { ret += L"F" + std::to_wstring(hk - 0x6f); } else if (hk >= VK_NUMPAD0 && hk <= VK_NUMPAD9) { ret += L"N" + std::to_wstring(hk - 0x5f); } else { ret += (wchar_t)hk; } return ret + L"]"; } //-------------------------------------------------------------------------------------- // Initialize the app //-------------------------------------------------------------------------------------- void InitApp() { g_HUD.Init(&g_DialogResourceManager); g_SampleUI.Init(&g_DialogResourceManager); g_HUD.SetCallback(OnGUIEvent); InitGfeSdkWrapper(&g_highlights); // Find the path to the executable wchar_t path[MAX_PATH] = { 0 }; GetModuleFileNameW(NULL, path, MAX_PATH); PathRemoveFileSpecW(path); const std::wstring pathStr(path); g_settingsManager.reset(new SettingsManager(pathStr + L"/settings.json")); // Load highlights config Json::Value jsonHighlightsConfig; { std::ifstream inFile(pathStr + L"/highlights_config.json"); if (!inFile.good()) { inFile = std::ifstream(pathStr + L"/../highlights_config.json"); if (!inFile.good()) { inFile = std::ifstream(pathStr + L"/../../highlights_config.json"); } } std::string errs; Json::CharReaderBuilder builder; if (!Json::parseFromStream(builder, inFile, &jsonHighlightsConfig, &errs)) { TRACE("FAILED to read json file\n"); } } // Store the json data in the highlights data structure g_highlightsConfig.gameName = jsonHighlightsConfig["gameName"].asString(); g_highlightsConfig.defaultLocale = jsonHighlightsConfig["defaultLocale"].asString(); g_highlightsConfig.highlightsData.resize(jsonHighlightsConfig["highlights"].size()); g_highlightsConfig.highlights.resize(jsonHighlightsConfig["highlights"].size()); for (unsigned int i = 0; i < jsonHighlightsConfig["highlights"].size(); ++i) { Json::Value const& def = jsonHighlightsConfig["highlights"].get(i, Json::Value()); g_highlightsConfig.highlightsData[i].id = def["id"].asString(); g_highlightsConfig.highlightsData[i].isScreenshot = !def.isMember("startDelta"); g_highlightsConfig.highlightsData[i].startDelta = g_highlightsConfig.highlightsData[i].isScreenshot ? 0 : def["startDelta"].asInt(); g_highlightsConfig.highlightsData[i].endDelta = g_highlightsConfig.highlightsData[i].isScreenshot ? 0 : def["endDelta"].asInt(); for (auto it = def["name"].begin(); it != def["name"].end(); ++it) { g_highlightsConfig.highlightsData[i].namePairsData[it.key().asString()] = it->asString(); } for (auto it = g_highlightsConfig.highlightsData[i].namePairsData.begin(); it != g_highlightsConfig.highlightsData[i].namePairsData.end(); ++it) { g_highlightsConfig.highlightsData[i].namePairs.push_back({ &it->first[0],&it->second[0] }); } g_highlightsConfig.highlights[i].id = g_highlightsConfig.highlightsData[i].id.c_str(); g_highlightsConfig.highlights[i].userInterest = def["userInterest"].asBool(); g_highlightsConfig.highlights[i].significance = static_cast(def["significance"].asInt()); g_highlightsConfig.highlights[i].highlightTags = static_cast(def["highlightTags"].asInt()); g_highlightsConfig.highlights[i].nameTable = g_highlightsConfig.highlightsData[i].namePairs.empty() ? nullptr : &g_highlightsConfig.highlightsData[i].namePairs[0]; g_highlightsConfig.highlights[i].nameTableSize = g_highlightsConfig.highlightsData[i].namePairs.size(); } int iY = 10; int const PAD = 26; int const WIDTH = 240; int const X = -80; uint16_t hk = 0x30; g_HUD.AddButtonCallback([]() {DXUTToggleFullScreen(); }, HK(L"Toggle full screen", hk).c_str(), X, iY, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() { g_settingsManager->ToggleBackgroundColor(); }, HK(L"Toggle background color", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() {g_highlights.OnRequestLanguage(); }, HK(L"Get Overlay Language", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() {g_highlights.OnRequestUserSettings(); }, HK(L"Get User Settings", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); iY += 10; int iY_groups = iY; int const GROUP1_X = X - WIDTH - 10; int const GROUP2_X = X; hk = 0x40; g_HUD.AddButtonCallback([]() {g_highlights.OnOpenGroup(GROUP1_ID); }, HK(L"Open Group 1", hk).c_str(), GROUP1_X, iY += PAD, WIDTH, 23, ++hk); for (size_t i = 0; i < g_highlightsConfig.highlightsData.size(); ++i) { HighlightsDataHolder const& holder = g_highlightsConfig.highlightsData[i]; if (!holder.isScreenshot) { std::wstring text = std::wstring(L"VIDEO: ") + g_converter.from_bytes(holder.id); g_HUD.AddButtonCallback([holder]() { g_highlights.OnSaveVideo(holder.id.c_str(), GROUP1_ID, holder.startDelta, holder.endDelta); }, HK(text.c_str(), hk).c_str(), GROUP1_X, iY += PAD, WIDTH, 23, ++hk); } else { std::wstring text = std::wstring(L"SCREENSHOT: ") + g_converter.from_bytes(holder.id); g_HUD.AddButtonCallback([holder]() { g_highlights.OnSaveScreenshot(holder.id.c_str(), GROUP1_ID); }, HK(text.c_str(), hk).c_str(), GROUP1_X, iY += PAD, WIDTH, 23, ++hk); } } g_HUD.AddButtonCallback([]() {g_highlights.OnOpenSummary(&std::vector({ GROUP1_ID })[0], 1, g_sigFilter, g_tagFilter); }, HK(L"Open Group1 Summary", hk).c_str(), GROUP1_X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() {g_highlights.OnGetNumHighlights(GROUP1_ID, g_sigFilter, g_tagFilter); }, HK(L"GetNumHighlights in Group1", hk).c_str(), GROUP1_X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() {g_highlights.OnCloseGroup(GROUP1_ID, false); }, HK(L"Close Group 1", hk).c_str(), GROUP1_X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() {g_highlights.OnCloseGroup(GROUP1_ID, true); }, HK(L"Destroy Group 1", hk).c_str(), GROUP1_X, iY += PAD, WIDTH, 23, ++hk); hk = 0x4d; iY = iY_groups; g_HUD.AddButtonCallback([]() {g_highlights.OnOpenGroup(GROUP2_ID); }, HK(L"Open Group 2", hk).c_str(), GROUP2_X, iY += PAD, WIDTH, 23, ++hk); for (size_t i = 0; i < g_highlightsConfig.highlightsData.size(); ++i) { HighlightsDataHolder const& holder = g_highlightsConfig.highlightsData[i]; if (!holder.isScreenshot) { std::wstring text = std::wstring(L"VIDEO: ") + g_converter.from_bytes(holder.id); g_HUD.AddButtonCallback([holder]() { g_highlights.OnSaveVideo(holder.id.c_str(), GROUP2_ID, holder.startDelta, holder.endDelta); }, HK(text.c_str(), hk).c_str(), GROUP2_X, iY += PAD, WIDTH, 23, ++hk); } else { std::wstring text = std::wstring(L"SCREENSHOT: ") + g_converter.from_bytes(holder.id); g_HUD.AddButtonCallback([holder]() { g_highlights.OnSaveScreenshot(holder.id.c_str(), GROUP2_ID); }, HK(text.c_str(), hk).c_str(), GROUP2_X, iY += PAD, WIDTH, 23, ++hk); } } g_HUD.AddButtonCallback([]() {g_highlights.OnOpenSummary(&std::vector({ GROUP2_ID })[0], 1, g_sigFilter, g_tagFilter); }, HK(L"Open Group2 Summary", hk).c_str(), GROUP2_X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() {g_highlights.OnGetNumHighlights(GROUP2_ID, g_sigFilter, g_tagFilter); }, HK(L"GetNumHighlights in Group2", hk).c_str(), GROUP2_X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() {g_highlights.OnCloseGroup(GROUP2_ID, false); }, HK(L"Close Group 2", hk).c_str(), GROUP2_X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback([]() {g_highlights.OnCloseGroup(GROUP2_ID, true); }, HK(L"Destroy Group 2", hk).c_str(), GROUP2_X, iY += PAD, WIDTH, 23, ++hk); hk = 0x59; iY += 10; g_HUD.AddButtonCallback([]() {g_highlights.OnOpenSummary(&std::vector({ GROUP1_ID, GROUP2_ID })[0], 2, g_sigFilter, g_tagFilter); }, HK(L"Open GroupSummary 1 + 2", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); hk = 0x6f; iY += 20; g_HUD.AddButtonCallback([]() {g_sigFilter = NVGSDK_HIGHLIGHT_SIGNIFICANCE_NONE; }, HK(L"Clear Significance Filter", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleSignificanceBit, NVGSDK_HIGHLIGHT_SIGNIFICANCE_EXTREMELY_BAD), HK(L"Toggle ExtremelyBad", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleSignificanceBit, NVGSDK_HIGHLIGHT_SIGNIFICANCE_VERY_BAD), HK(L"Toggle VeryBad", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleSignificanceBit, NVGSDK_HIGHLIGHT_SIGNIFICANCE_BAD), HK(L"Toggle Bad", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleSignificanceBit, NVGSDK_HIGHLIGHT_SIGNIFICANCE_NEUTRAL), HK(L"Toggle Neutral", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleSignificanceBit, NVGSDK_HIGHLIGHT_SIGNIFICANCE_GOOD), HK(L"Toggle Good", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleSignificanceBit, NVGSDK_HIGHLIGHT_SIGNIFICANCE_VERY_GOOD), HK(L"Toggle VeryGood", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleSignificanceBit, NVGSDK_HIGHLIGHT_SIGNIFICANCE_EXTREMELY_GOOD), HK(L"Toggle ExtremelyGood", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); hk = 0x5f; iY += 10; g_HUD.AddButtonCallback([]() {g_tagFilter = NVGSDK_HIGHLIGHT_TYPE_NONE; }, HK(L"Clear Tag Filter", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleTagBit, NVGSDK_HIGHLIGHT_TYPE_MILESTONE), HK(L"Toggle Milestone", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleTagBit, NVGSDK_HIGHLIGHT_TYPE_ACHIEVEMENT), HK(L"Toggle Achievement", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleTagBit, NVGSDK_HIGHLIGHT_TYPE_INCIDENT), HK(L"Toggle Incident", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleTagBit, NVGSDK_HIGHLIGHT_TYPE_STATE_CHANGE), HK(L"Toggle StateChange", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_HUD.AddButtonCallback(std::bind(ToggleTagBit, NVGSDK_HIGHLIGHT_TYPE_UNANNOUNCED), HK(L"Toggle Unannounced", hk).c_str(), X, iY += PAD, WIDTH, 23, ++hk); g_SampleUI.SetCallback(OnGUIEvent); iY = 10; } //-------------------------------------------------------------------------------------- // Render the help and statistics text. //-------------------------------------------------------------------------------------- void RenderText() { UINT nBackBufferHeight = DXUTGetDXGIBackBufferSurfaceDesc()->Height; g_pTxtHelper->Begin(); g_pTxtHelper->SetInsertionPos(2, 50); g_pTxtHelper->SetForegroundColor(Colors::White); g_pTxtHelper->DrawTextLine(DXUTGetFrameStats(DXUTIsVsyncEnabled())); g_pTxtHelper->DrawTextLine(DXUTGetDeviceStats()); // Settings g_pTxtHelper->DrawFormattedTextLine(L"Background color: %S", g_settingsManager->GetBackgroundColorString().c_str()); // Highlights g_pTxtHelper->SetForegroundColor(Colors::White); g_pTxtHelper->SetInsertionPos(2, 5); g_pTxtHelper->DrawFormattedTextLine(L"Highlights Permission: %s", g_highlights.GetCurrentPermissionStr()); g_pTxtHelper->DrawFormattedTextLine(L"Last Overlay Event: %s", g_highlights.GetLastOverlayEvent()); g_pTxtHelper->DrawFormattedTextLine(L"Last Result: %s", g_highlights.GetLastResult()); g_pTxtHelper->SetInsertionPos(500, 5); g_pTxtHelper->DrawFormattedTextLine(L"Last Query: %s", g_highlights.GetLastQueryResult()); g_pTxtHelper->SetInsertionPos(700, 5); g_pTxtHelper->DrawFormattedTextLine(L"Significance Filter: 0x%08x", g_sigFilter); g_pTxtHelper->DrawFormattedTextLine(L"Tag Filter: 0x%08x", g_tagFilter); g_pTxtHelper->End(); } //-------------------------------------------------------------------------------------- // Render the loading text //-------------------------------------------------------------------------------------- void RenderLoadingText() { UINT nBackBufferHeight = DXUTGetDXGIBackBufferSurfaceDesc()->Height; g_pTxtHelper->Begin(); g_pTxtHelper->SetInsertionPos(nBackBufferHeight / 2, 300); g_pTxtHelper->SetForegroundColor(Colors::White); g_pTxtHelper->DrawTextLine(L"LOADING..."); g_pTxtHelper->End(); } std::string WideToUtf8(std::wstring const& wideStr) { int length = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, NULL, 0, NULL, NULL); if (length <= 0) { throw std::runtime_error("WideCharToMultiByte failed"); } std::unique_ptr outputData(new char[length]); length = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, &outputData.get()[0], length, NULL, NULL); if (length <= 0) { throw std::runtime_error("WideCharToMultiByte failed"); } return std::string(&outputData.get()[0]); } //-------------------------------------------------------------------------------------- // Reject any D3D11 devices that aren't acceptable by returning false //-------------------------------------------------------------------------------------- bool CALLBACK IsD3D11DeviceAcceptable(const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo, DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext) { return true; } //-------------------------------------------------------------------------------------- // Create any D3D11 resources that aren't dependant on the back buffer //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnD3D11CreateDevice(ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext) { HRESULT hr; auto pd3dImmediateContext = DXUTGetD3D11DeviceContext(); V_RETURN(g_DialogResourceManager.OnD3D11CreateDevice(pd3dDevice, pd3dImmediateContext)); g_pTxtHelper = new CDXUTTextHelper(pd3dDevice, pd3dImmediateContext, &g_DialogResourceManager, 15); XMVECTORF32 vCenter = { 0.25767413f, -28.503521f, 111.00689f }; FLOAT fObjectRadius = 378.15607f; g_mCenterMesh = XMMatrixTranslation(-vCenter.f[0], -vCenter.f[1], -vCenter.f[2]); XMMATRIX m = XMMatrixRotationY(XM_PI); g_mCenterMesh *= m; m = XMMatrixRotationX(XM_PI / 2.0f); g_mCenterMesh *= m; // Read the HLSL file // You should use the lowest possible shader profile for your shader to enable various feature levels. These // shaders are simple enough to work well within the lowest possible profile, and will run on all feature levels DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; #ifdef _DEBUG // Disable optimizations to further improve shader debugging dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION; #endif ID3DBlob* pVertexShaderBuffer = nullptr; V_RETURN(DXUTCompileFromFile(L"SimpleSample.hlsl", nullptr, "RenderSceneVS", "vs_4_0_level_9_1", dwShaderFlags, 0, &pVertexShaderBuffer)); ID3DBlob* pPixelShaderBuffer = nullptr; V_RETURN(DXUTCompileFromFile(L"SimpleSample.hlsl", nullptr, "RenderScenePS", "ps_4_0_level_9_1", dwShaderFlags, 0, &pPixelShaderBuffer)); // Create the shaders V_RETURN(pd3dDevice->CreateVertexShader(pVertexShaderBuffer->GetBufferPointer(), pVertexShaderBuffer->GetBufferSize(), nullptr, &g_pVertexShader11)); DXUT_SetDebugName(g_pVertexShader11, "RenderSceneVS"); V_RETURN(pd3dDevice->CreatePixelShader(pPixelShaderBuffer->GetBufferPointer(), pPixelShaderBuffer->GetBufferSize(), nullptr, &g_pPixelShader11)); DXUT_SetDebugName(g_pPixelShader11, "RenderScenePS"); // Create a layout for the object data const D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; V_RETURN(pd3dDevice->CreateInputLayout(layout, ARRAYSIZE(layout), pVertexShaderBuffer->GetBufferPointer(), pVertexShaderBuffer->GetBufferSize(), &g_pLayout11)); DXUT_SetDebugName(g_pLayout11, "Primary"); // Load the mesh V_RETURN(g_Mesh11.Create(pd3dDevice, L"tiny\\tiny.sdkmesh")); // No longer need the shader blobs SAFE_RELEASE(pVertexShaderBuffer); SAFE_RELEASE(pPixelShaderBuffer); // Create state objects D3D11_SAMPLER_DESC samDesc; ZeroMemory(&samDesc, sizeof(samDesc)); samDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; samDesc.AddressU = samDesc.AddressV = samDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; samDesc.MaxAnisotropy = 1; samDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; samDesc.MaxLOD = D3D11_FLOAT32_MAX; V_RETURN(pd3dDevice->CreateSamplerState(&samDesc, &g_pSamLinear)); DXUT_SetDebugName(g_pSamLinear, "Linear"); // Create constant buffers D3D11_BUFFER_DESC cbDesc; ZeroMemory(&cbDesc, sizeof(cbDesc)); cbDesc.Usage = D3D11_USAGE_DYNAMIC; cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; cbDesc.ByteWidth = sizeof(CB_VS_PER_OBJECT); V_RETURN(pd3dDevice->CreateBuffer(&cbDesc, nullptr, &g_pcbVSPerObject11)); DXUT_SetDebugName(g_pcbVSPerObject11, "CB_VS_PER_OBJECT"); cbDesc.ByteWidth = sizeof(CB_VS_PER_FRAME); V_RETURN(pd3dDevice->CreateBuffer(&cbDesc, nullptr, &g_pcbVSPerFrame11)); DXUT_SetDebugName(g_pcbVSPerFrame11, "CB_VS_PER_FRAME"); // Create other render resources here // Setup the camera's view parameters static const XMVECTORF32 s_vecEye = { 0.0f, 0.0f, -100.0f }; static const XMVECTORF32 s_vecAt = { 0.0f, 0.0f, -0.0f }; g_Camera.SetViewParams(s_vecEye, s_vecAt); g_Camera.SetRadius(fObjectRadius * 3.0f, fObjectRadius * 0.5f, fObjectRadius * 10.0f); return S_OK; } //-------------------------------------------------------------------------------------- // Create any D3D11 resources that depend on the back buffer //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnD3D11ResizedSwapChain(ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext) { HRESULT hr; V_RETURN(g_DialogResourceManager.OnD3D11ResizedSwapChain(pd3dDevice, pBackBufferSurfaceDesc)); // Setup the camera's projection parameters float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height; g_Camera.SetProjParams(XM_PI / 4, fAspectRatio, 2.0f, 10000.0f); g_Camera.SetWindow(pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height); g_Camera.SetButtonMasks(MOUSE_LEFT_BUTTON, MOUSE_WHEEL, MOUSE_MIDDLE_BUTTON); g_HUD.SetLocation(pBackBufferSurfaceDesc->Width - 170, 0); g_HUD.SetSize(170, 170); g_SampleUI.SetLocation(pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 300); g_SampleUI.SetSize(170, 300); return S_OK; } static DWORD LastFrameTime = 0; DWORD FPSLimit = 60; //-------------------------------------------------------------------------------------- // Render the scene using the D3D11 device //-------------------------------------------------------------------------------------- void CALLBACK OnD3D11FrameRender(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext) { // Limit FPS DWORD currentTime = timeGetTime(); if ((currentTime - LastFrameTime) < (1000 / FPSLimit)) { Sleep(currentTime - LastFrameTime); } LastFrameTime = currentTime; g_highlights.OnTick(); switch (g_state) { case AppState::Init: g_state = AppState::LoadResources; return; case AppState::LoadResources: RenderLoadingText(); g_highlights.Init(g_highlightsConfig.gameName.c_str(), g_highlightsConfig.defaultLocale.c_str(), &g_highlightsConfig.highlights[0], g_highlightsConfig.highlights.size(), g_targetPath.c_str(), g_targetPid); g_state = AppState::Main; return; case AppState::Main: { auto pRTV = DXUTGetD3D11RenderTargetView(); pd3dImmediateContext->ClearRenderTargetView(pRTV, g_settingsManager->GetBackgroundColorArray().data()); // Clear the depth stencil auto pDSV = DXUTGetD3D11DepthStencilView(); pd3dImmediateContext->ClearDepthStencilView(pDSV, D3D11_CLEAR_DEPTH, 1.0, 0); // Slowly rotate world XMMATRIX rotMatrix = XMMatrixRotationRollPitchYaw(0.0f, 0.001f, 0.001f); g_mCenterMesh = g_mCenterMesh * rotMatrix; // Get the projection & view matrix from the camera class XMMATRIX mWorld = g_mCenterMesh * g_Camera.GetWorldMatrix(); XMMATRIX mView = g_Camera.GetViewMatrix(); XMMATRIX mProj = g_Camera.GetProjMatrix(); XMMATRIX mWorldViewProjection = mWorld * mView * mProj; // Set the constant buffers HRESULT hr; D3D11_MAPPED_SUBRESOURCE MappedResource; V(pd3dImmediateContext->Map(g_pcbVSPerFrame11, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource)); auto pVSPerFrame = reinterpret_cast(MappedResource.pData); pVSPerFrame->m_vLightDir = XMFLOAT3(0, 0.707f, -0.707f); pVSPerFrame->m_fTime = (float)fTime; pVSPerFrame->m_LightDiffuse = XMFLOAT4(1.f, 1.f, 1.f, 1.f); pd3dImmediateContext->Unmap(g_pcbVSPerFrame11, 0); pd3dImmediateContext->VSSetConstantBuffers(1, 1, &g_pcbVSPerFrame11); V(pd3dImmediateContext->Map(g_pcbVSPerObject11, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource)); auto pVSPerObject = reinterpret_cast(MappedResource.pData); XMStoreFloat4x4(&pVSPerObject->m_mWorldViewProjection, XMMatrixTranspose(mWorldViewProjection)); XMStoreFloat4x4(&pVSPerObject->m_mWorld, XMMatrixTranspose(mWorld)); pVSPerObject->m_MaterialAmbientColor = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f); pVSPerObject->m_MaterialDiffuseColor = XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f); pd3dImmediateContext->Unmap(g_pcbVSPerObject11, 0); pd3dImmediateContext->VSSetConstantBuffers(0, 1, &g_pcbVSPerObject11); //Get the mesh //IA setup pd3dImmediateContext->IASetInputLayout(g_pLayout11); UINT Strides[1]; UINT Offsets[1]; ID3D11Buffer* pVB[1]; pVB[0] = g_Mesh11.GetVB11(0, 0); Strides[0] = (UINT)g_Mesh11.GetVertexStride(0, 0); Offsets[0] = 0; pd3dImmediateContext->IASetVertexBuffers(0, 1, pVB, Strides, Offsets); pd3dImmediateContext->IASetIndexBuffer(g_Mesh11.GetIB11(0), g_Mesh11.GetIBFormat11(0), 0); // Set render resources pd3dImmediateContext->IASetInputLayout(g_pLayout11); pd3dImmediateContext->VSSetShader(g_pVertexShader11, nullptr, 0); pd3dImmediateContext->PSSetShader(g_pPixelShader11, nullptr, 0); pd3dImmediateContext->PSSetSamplers(0, 1, &g_pSamLinear); // Render objects here... SDKMESH_SUBSET* pSubset = NULL; D3D11_PRIMITIVE_TOPOLOGY PrimType; for (UINT subset = 0; subset < g_Mesh11.GetNumSubsets(0); ++subset) { // Get the subset pSubset = g_Mesh11.GetSubset(0, subset); PrimType = CDXUTSDKMesh::GetPrimitiveType11((SDKMESH_PRIMITIVE_TYPE)pSubset->PrimitiveType); pd3dImmediateContext->IASetPrimitiveTopology(PrimType); // TODO: D3D11 - material loading ID3D11ShaderResourceView* pDiffuseRV = g_Mesh11.GetMaterial(pSubset->MaterialID)->pDiffuseRV11; pd3dImmediateContext->PSSetShaderResources(0, 1, &pDiffuseRV); pd3dImmediateContext->DrawIndexed((UINT)pSubset->IndexCount, 0, (UINT)pSubset->VertexStart); } DXUT_BeginPerfEvent(DXUT_PERFEVENTCOLOR, L"HUD / Stats"); g_HUD.OnRender(fElapsedTime); g_SampleUI.OnRender(fElapsedTime); RenderText(); DXUT_EndPerfEvent(); static ULONGLONG timefirst = GetTickCount64(); if (GetTickCount64() - timefirst > 5000) { OutputDebugString(DXUTGetFrameStats(DXUTIsVsyncEnabled())); OutputDebugString(L"\n"); timefirst = GetTickCount64(); } return; } } } void CALLBACK OnQuit(void* pUserContext) { g_highlights.DeInit(); PostQuitMessage(0); } //-------------------------------------------------------------------------------------- // Release D3D11 resources created in OnD3D11ResizedSwapChain //-------------------------------------------------------------------------------------- void CALLBACK OnD3D11ReleasingSwapChain(void* pUserContext) { g_DialogResourceManager.OnD3D11ReleasingSwapChain(); } //-------------------------------------------------------------------------------------- // Release D3D11 resources created in OnD3D11CreateDevice //-------------------------------------------------------------------------------------- void CALLBACK OnD3D11DestroyDevice(void* pUserContext) { g_DialogResourceManager.OnD3D11DestroyDevice(); DXUTGetGlobalResourceCache().OnDestroyDevice(); SAFE_DELETE(g_pTxtHelper); g_Mesh11.Destroy(); SAFE_RELEASE(g_pVertexShader11); SAFE_RELEASE(g_pPixelShader11); SAFE_RELEASE(g_pLayout11); SAFE_RELEASE(g_pSamLinear); // Delete additional render resources here... SAFE_RELEASE(g_pcbVSPerObject11); SAFE_RELEASE(g_pcbVSPerFrame11); } //-------------------------------------------------------------------------------------- // Called right before creating a D3D device, allowing the app to modify the device settings as needed //-------------------------------------------------------------------------------------- bool CALLBACK ModifyDeviceSettings(DXUTDeviceSettings* pDeviceSettings, void* pUserContext) { return true; } //-------------------------------------------------------------------------------------- // Handle updates to the scene. This is called regardless of which D3D API is used //-------------------------------------------------------------------------------------- void CALLBACK OnFrameMove(double fTime, float fElapsedTime, void* pUserContext) { // Update the camera's position based on user input g_Camera.FrameMove(fElapsedTime); } //-------------------------------------------------------------------------------------- // Handle messages to the application //-------------------------------------------------------------------------------------- LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext) { // Pass messages to dialog resource manager calls so GUI state is updated correctly *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; // Give the dialogs a chance to handle the message first *pbNoFurtherProcessing = g_HUD.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; *pbNoFurtherProcessing = g_SampleUI.MsgProc(hWnd, uMsg, wParam, lParam); if (*pbNoFurtherProcessing) return 0; // Pass all remaining windows messages to camera so it can respond to user input g_Camera.HandleMessages(hWnd, uMsg, wParam, lParam); return 0; } //-------------------------------------------------------------------------------------- // Handle key presses //-------------------------------------------------------------------------------------- void CALLBACK OnKeyboard(UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext) { } //-------------------------------------------------------------------------------------- // Handles the GUI events //-------------------------------------------------------------------------------------- void CALLBACK OnGUIEvent(UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext) { void* pUserData = pControl->GetUserData(); if (pUserData) { std::function* fn = reinterpret_cast*>(pUserData); (*fn)(); } }