aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Samples/SampleFramework/platform/src
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Samples/SampleFramework/platform/src
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Samples/SampleFramework/platform/src')
-rw-r--r--PhysX_3.4/Samples/SampleFramework/platform/src/SamplePlatform.cpp316
-rw-r--r--PhysX_3.4/Samples/SampleFramework/platform/src/SampleUserInput.cpp344
-rw-r--r--PhysX_3.4/Samples/SampleFramework/platform/src/windows/WindowsSamplePlatform.cpp1180
-rw-r--r--PhysX_3.4/Samples/SampleFramework/platform/src/windows/WindowsSampleUserInput.cpp825
4 files changed, 2665 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleFramework/platform/src/SamplePlatform.cpp b/PhysX_3.4/Samples/SampleFramework/platform/src/SamplePlatform.cpp
new file mode 100644
index 00000000..982bedb3
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/platform/src/SamplePlatform.cpp
@@ -0,0 +1,316 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+
+#include <PsString.h>
+#include <SamplePlatform.h>
+
+using namespace SampleFramework;
+using namespace physx;
+
+SamplePlatform* SamplePlatform::m_platform = NULL;
+
+SamplePlatform* SamplePlatform::platform()
+{
+ RENDERER_ASSERT(SamplePlatform::m_platform, "SamplePlatform was not initialized!");
+ if(SamplePlatform::m_platform)
+ {
+ return SamplePlatform::m_platform;
+ }
+ return NULL;
+}
+
+SampleApplication* SamplePlatform::application()
+{
+ return m_sf_app;
+}
+
+bool SamplePlatform::preOpenWindow(void * ptr)
+{
+ return true;
+}
+
+void SamplePlatform::showCursor(bool)
+{
+}
+
+void SamplePlatform::setPlatform(SamplePlatform* ptr)
+{
+ SamplePlatform::m_platform = ptr;
+}
+
+void* SamplePlatform::initializeD3D9()
+{
+ return NULL;
+}
+
+bool SamplePlatform::isD3D9ok()
+{
+ return true;
+}
+
+void* SamplePlatform::initializeD3D11()
+{
+ return NULL;
+}
+
+bool SamplePlatform::isD3D11ok()
+{
+ return true;
+}
+
+void* SamplePlatform::compileProgram(void * context,
+ const char* assetDir,
+ const char *programPath,
+ physx::PxU64 profile,
+ const char* passString,
+ const char *entry,
+ const char **args)
+
+{
+ return NULL;
+}
+
+SamplePlatform::SamplePlatform(SampleRenderer::RendererWindow* _app) : m_app(_app)
+{
+}
+
+SamplePlatform::~SamplePlatform()
+{
+}
+
+bool SamplePlatform::hasFocus() const
+{
+ return true;
+}
+
+void SamplePlatform::setFocus(bool b)
+{
+}
+
+void SamplePlatform::update()
+{
+}
+
+void SamplePlatform::setWindowSize(physx::PxU32 width,
+ physx::PxU32 height)
+{
+}
+
+void SamplePlatform::getTitle(char *title, PxU32 maxLength) const
+{
+}
+
+void SamplePlatform::setTitle(const char *title)
+{
+}
+
+bool SamplePlatform::openWindow(physx::PxU32& width,
+ physx::PxU32& height,
+ const char* title,
+ bool fullscreen)
+{
+ return true;
+}
+
+
+bool SamplePlatform::useWindow(physx::PxU64 hwnd)
+{
+ return false;
+}
+
+
+bool SamplePlatform::isOpen()
+{
+ return true;
+}
+
+bool SamplePlatform::closeWindow()
+{
+ return true;
+}
+
+bool SamplePlatform::updateWindow()
+{
+ return true;
+}
+
+size_t SamplePlatform::getCWD(char* path, size_t len)
+{
+ RENDERER_ASSERT(path && len, "buffer should not be empty!");
+ *path = '\0';
+ return 0;
+}
+void SamplePlatform::setCWDToEXE(void)
+{
+}
+
+void SamplePlatform::popPathSpec(char *path)
+{
+ char *ls = 0;
+ while(*path)
+ {
+ if(*path == '\\' || *path == '/') ls = path;
+ path++;
+ }
+ if(ls) *ls = 0;
+}
+
+void SamplePlatform::preRendererSetup()
+{
+}
+
+void SamplePlatform::postRendererSetup(SampleRenderer::Renderer* renderer)
+{
+ getSampleUserInput()->setRenderer(renderer);
+}
+
+void SamplePlatform::setupRendererDescription(SampleRenderer::RendererDesc& renDesc)
+{
+ renDesc.driver = SampleRenderer::Renderer::DRIVER_OPENGL;
+}
+
+void SamplePlatform::doInput()
+{
+}
+
+void SamplePlatform::postRendererRelease()
+{
+}
+
+void SamplePlatform::initializeOGLDisplay(const SampleRenderer::RendererDesc& desc,
+ physx::PxU32& width,
+ physx::PxU32& height)
+{
+}
+
+void SamplePlatform::showMessage(const char* title, const char* message)
+{
+ shdfnd::printFormatted("%s: %s\n", title, message);
+}
+
+bool SamplePlatform::saveBitmap(const char*, physx::PxU32, physx::PxU32, physx::PxU32, const void*)
+{
+ return false;
+}
+
+void SamplePlatform::initializeCGRuntimeCompiler()
+{
+}
+
+void SamplePlatform::getWindowSize(PxU32& width, PxU32& height)
+{
+}
+
+void SamplePlatform::freeDisplay()
+{
+}
+
+bool SamplePlatform::makeContextCurrent()
+{
+ return true;
+}
+
+void SamplePlatform::swapBuffers()
+{
+}
+
+bool SamplePlatform::isContextValid()
+{
+ return true;
+}
+
+void SamplePlatform::postInitializeOGLDisplay()
+{
+}
+
+void SamplePlatform::setOGLVsync(bool on)
+{
+}
+
+physx::PxU32 SamplePlatform::initializeD3D9Display(void * presentParameters,
+ char* m_deviceName,
+ physx::PxU32& width,
+ physx::PxU32& height,
+ void * m_d3dDevice_out)
+{
+ return 0;
+}
+
+physx::PxU32 SamplePlatform::initializeD3D11Display(void *dxgiSwapChainDesc,
+ char *m_deviceName,
+ physx::PxU32& width,
+ physx::PxU32& height,
+ void *m_d3dDevice_out,
+ void *m_d3dDeviceContext_out,
+ void *m_dxgiSwap_out)
+{
+ return 0;
+}
+
+physx::PxU64 SamplePlatform::getWindowHandle()
+{
+ return 0;
+}
+
+physx::PxU32 SamplePlatform::D3D9Present()
+{
+ return 0;
+}
+
+
+physx::PxU32 SamplePlatform::D3D11Present(bool vsync)
+{
+ return 0;
+}
+
+void SamplePlatform::D3D9BlockUntilNotBusy(void * resource)
+{
+}
+
+void SamplePlatform::D3D9DeviceBlockUntilIdle()
+{
+}
+
+physx::PxU64 SamplePlatform::getD3D9TextureFormat(SampleRenderer::RendererTexture2D::Format format)
+{
+ return 0;
+}
+
+const char* SamplePlatform::getPathSeparator()
+{
+ return "\\";
+}
+
+bool SamplePlatform::makeSureDirectoryPathExists(const char*)
+{
+ return false;
+}
+physx::PxU64 SamplePlatform::getD3D11TextureFormat(SampleRenderer::RendererTexture2D::Format format)
+{
+ return 0;
+}
+
diff --git a/PhysX_3.4/Samples/SampleFramework/platform/src/SampleUserInput.cpp b/PhysX_3.4/Samples/SampleFramework/platform/src/SampleUserInput.cpp
new file mode 100644
index 00000000..4c47b1ec
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/platform/src/SampleUserInput.cpp
@@ -0,0 +1,344 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+
+#include <SampleUserInput.h>
+#include <SamplePlatform.h>
+
+#if defined(RENDERER_LINUX) || defined(RENDERER_PS4)
+#include <stdio.h>
+#endif
+
+using namespace SampleFramework;
+namespace Ps = physx::shdfnd;
+
+// this will prepare the input events vector, its not resize-able
+static const size_t NUM_INPUT_EVENTS = 256;
+
+SampleUserInput::SampleUserInput()
+ : mListener(NULL)
+{
+
+ mUserInputs.reserve(128);
+ mInputEvents.reserve(NUM_INPUT_EVENTS);
+ mInputEventNames.reserve(NUM_INPUT_EVENTS);
+}
+
+SampleUserInput::~SampleUserInput()
+{
+
+ mUserInputs.clear();
+}
+
+void SampleUserInput::registerUserInput(physx::PxU16 id,const char* idName ,const char* name)
+{
+ UserInput ui;
+ ui.m_Id = id;
+ strcpy(ui.m_Name , name);
+ strcpy(ui.m_IdName, idName);
+
+ mUserInputs.push_back(ui);
+}
+
+const InputEvent* SampleUserInput::registerInputEvent(const InputEvent& inputEvent, physx::PxU16 userInputId, const char* name)
+{
+ size_t ieId = 0;
+ const InputEvent* retIe = NULL;
+ std::map<physx::PxU16, std::vector<size_t> >::iterator fit = mInputEventUserInputMap.find(inputEvent.m_Id);
+ if(fit != mInputEventUserInputMap.end())
+ {
+ for (size_t i = mInputEvents.size(); i--;)
+ {
+ if(mInputEvents[i].m_Id == inputEvent.m_Id)
+ {
+ // the analog has a priority
+ if(inputEvent.m_Analog == true)
+ {
+ mInputEvents[i].m_Analog = true;
+ }
+ ieId = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ ieId = mInputEvents.size();
+ if(ieId == NUM_INPUT_EVENTS - 1)
+ {
+ // increase the num input events please
+ PX_ASSERT(0);
+ return NULL;
+ }
+ else
+ {
+ mInputEvents.push_back(inputEvent);
+ mInputEventNames.resize(mInputEventNames.size()+1);
+ Ps::strlcpy(mInputEventNames.back().m_Name, sizeof(mInputEventNames.back().m_Name), name);
+ retIe = &mInputEvents[ieId];
+ PX_ASSERT(mInputEventNames.size() == mInputEvents.size());
+ }
+ }
+
+ bool found = false;
+ size_t uiId = 0;
+ for (size_t i = mUserInputs.size(); i--; )
+ {
+ const UserInput& ui = mUserInputs[i];
+ if(ui.m_Id == userInputId)
+ {
+ uiId = i;
+ found = true;
+ break;
+ }
+ }
+
+ if(found)
+ {
+ mInputEventUserInputMap[inputEvent.m_Id].push_back(uiId);
+ mUserInputInputEventMap[userInputId].push_back(ieId);
+ //if(mUserInputInputEventMap[userInputId].size() > 1)
+ //{
+ // char msg[256];
+ // sprintf(msg,"Key %s used multiple times",mUserInputs[uiId].m_Name);
+ // SampleFramework::SamplePlatform::platform()->showMessage("SampleUserInput warning: ",msg);
+ //}
+ }
+
+ return retIe;
+}
+
+void SampleUserInput::registerInputEvent(const SampleInputMapping& mapping)
+{
+ std::map<physx::PxU16, std::vector<size_t> >::iterator fit = mInputEventUserInputMap.find(mapping.m_InputEventId);
+ if(fit != mInputEventUserInputMap.end())
+ {
+ std::vector<size_t>& userInputVector = fit->second;
+ bool found = false;
+
+ for (size_t i = userInputVector.size(); i--;)
+ {
+ if(userInputVector[i] == mapping.m_UserInputIndex)
+ {
+ found = true;
+ }
+ }
+
+ if(!found)
+ {
+ userInputVector.push_back(mapping.m_UserInputIndex);
+ }
+ }
+ else
+ {
+ mInputEventUserInputMap[mapping.m_InputEventId].push_back(mapping.m_UserInputIndex);
+ }
+
+ fit = mUserInputInputEventMap.find(mapping.m_UserInputId);
+ if(fit != mUserInputInputEventMap.end())
+ {
+ std::vector<size_t>& inputEventVector = fit->second;
+ bool found = false;
+
+ for (size_t i = inputEventVector.size(); i--;)
+ {
+ if(inputEventVector[i] == mapping.m_InputEventIndex)
+ {
+ found = true;
+ }
+ }
+
+ if(!found)
+ {
+ inputEventVector.push_back(mapping.m_InputEventIndex);
+ }
+ }
+ else
+ {
+ mUserInputInputEventMap[mapping.m_UserInputId].push_back(mapping.m_InputEventIndex);
+ }
+}
+
+void SampleUserInput::unregisterInputEvent(physx::PxU16 inputEventId)
+{
+ std::map<physx::PxU16, std::vector<size_t> >::iterator fit = mInputEventUserInputMap.find(inputEventId);
+ if(fit != mInputEventUserInputMap.end())
+ {
+ const std::vector<size_t>& userInputs = fit->second;
+ for (size_t j = userInputs.size(); j--;)
+ {
+ const UserInput& ui = mUserInputs[userInputs[j]];
+ std::map<physx::PxU16, std::vector<size_t> >::iterator uifit = mUserInputInputEventMap.find(ui.m_Id);
+ if(uifit != mUserInputInputEventMap.end())
+ {
+ std::vector<size_t>& inputEvents = uifit->second;
+ for (size_t u = inputEvents.size(); u--;)
+ {
+ if(mInputEvents[inputEvents[u]].m_Id == inputEventId)
+ {
+ inputEvents[u] = inputEvents.back();
+ inputEvents.pop_back();
+ }
+ }
+ }
+ }
+
+ mInputEventUserInputMap.erase(fit);
+ }
+}
+
+void SampleUserInput::updateInput()
+{
+
+}
+
+void SampleUserInput::processGamepads()
+{
+}
+
+const InputEvent* SampleUserInput::getInputEventSlow(physx::PxU16 inputEventId) const
+{
+ for (size_t i = mInputEvents.size(); i--;)
+ {
+ if(mInputEvents[i].m_Id == inputEventId)
+ {
+ return &mInputEvents[i];
+ }
+ }
+
+ return NULL;
+}
+
+const std::vector<size_t>* SampleUserInput::getUserInputs(physx::PxI32 inputEventId) const
+{
+ if(inputEventId < 0)
+ return NULL;
+
+ std::map<physx::PxU16, std::vector<size_t> >::const_iterator fit = mInputEventUserInputMap.find((physx::PxU16)inputEventId);
+ if(fit != mInputEventUserInputMap.end())
+ {
+ return &fit->second;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+const std::vector<size_t>* SampleUserInput::getInputEvents(physx::PxU16 userInputId) const
+{
+ std::map<physx::PxU16, std::vector<size_t> >::const_iterator fit = mUserInputInputEventMap.find(userInputId);
+ if(fit != mUserInputInputEventMap.end())
+ {
+ return &fit->second;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+physx::PxI32 SampleUserInput::translateInputEventNameToId(const char* name, size_t& index) const
+{
+ PX_ASSERT(mInputEvents.size() == mInputEventNames.size());
+ for (size_t i = mInputEventNames.size(); i--;)
+ {
+ if(!strcmp(mInputEventNames[i].m_Name, name))
+ {
+ index = i;
+ return mInputEvents[i].m_Id;
+ }
+ }
+ return -1;
+}
+
+const char* SampleUserInput::translateInputEventIdToName(physx::PxI32 id) const
+{
+ PX_ASSERT(mInputEvents.size() == mInputEventNames.size());
+ for (size_t i = mInputEvents.size(); i--;)
+ {
+ if(mInputEvents[i].m_Id == id)
+ {
+ return mInputEventNames[i].m_Name;
+ }
+ }
+ return NULL;
+}
+
+physx::PxI32 SampleUserInput::translateUserInputNameToId(const char* name, size_t& index) const
+{
+ for (size_t i = mUserInputs.size(); i--;)
+ {
+ if(!strcmp(mUserInputs[i].m_IdName, name))
+ {
+ index = i;
+ return mUserInputs[i].m_Id;
+ }
+ }
+ return -1;
+}
+
+void SampleUserInput::shutdown()
+{
+ mInputEvents.clear();
+ mInputEventNames.clear();
+
+ mUserInputInputEventMap.clear();
+ mInputEventUserInputMap.clear();
+}
+
+physx::PxU16 SampleUserInput::getUserInputKeys(physx::PxU16 inputEventId, const char* names[], physx::PxU16 maxNames, physx::PxU32 inputTypeMask) const
+{
+ physx::PxU16 retVal = 0;
+
+ const std::vector<size_t>* uis = getUserInputs(inputEventId);
+ if(uis)
+ {
+ for (size_t i = uis->size(); i--;)
+ {
+ if(retVal < maxNames)
+ {
+ const UserInput& ie = mUserInputs[(*uis)[i]];
+ InputType it = getInputType(ie);
+ if(it)
+ {
+ if(it & inputTypeMask)
+ {
+ names[retVal] = ie.m_Name;
+ retVal++;
+ }
+ }
+ else
+ {
+ names[retVal] = ie.m_Name;
+ retVal++;
+ }
+ }
+ }
+ }
+
+ return retVal;
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/platform/src/windows/WindowsSamplePlatform.cpp b/PhysX_3.4/Samples/SampleFramework/platform/src/windows/WindowsSamplePlatform.cpp
new file mode 100644
index 00000000..7140be2b
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/platform/src/windows/WindowsSamplePlatform.cpp
@@ -0,0 +1,1180 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+#include <RendererMemoryMacros.h>
+#include <windows/WindowsSamplePlatform.h>
+
+#if defined(RENDERER_ENABLE_CG)
+#include <cg/cg.h>
+#endif
+
+#include <direct.h>
+#include <stdio.h>
+
+#include <PsString.h>
+#include <PxTkFile.h>
+#include <PsUtilities.h>
+
+#if defined(RENDERER_ENABLE_DIRECT3D9)
+ #include <d3d9.h>
+ #include <d3dx9.h>
+ #include <XInput.h>
+#endif
+
+#if defined(RENDERER_ENABLE_DIRECT3D11)
+#pragma warning(push)
+// Disable macro redefinition warnings
+#pragma warning(disable: 4005)
+ #include <d3d11.h>
+#pragma warning(pop)
+#endif
+
+#if defined(RENDERER_ENABLE_OPENGL)
+ #define GLEW_STATIC
+ #include <GL/glew.h>
+ #include <GL/wglew.h>
+
+ #pragma comment(lib, "OpenGL32.lib")
+ #pragma comment(lib, "GLU32.lib")
+#endif
+
+using std::min;
+using std::max;
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#include <atlimage.h>
+#include <Gdiplusimaging.h>
+#pragma warning(pop)
+
+using namespace SampleFramework;
+using SampleRenderer::RendererWindow;
+using namespace physx;
+
+static void setDCPixelFormat(HDC &dc)
+{
+ const PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1,
+ PFD_DRAW_TO_WINDOW |
+ PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER,
+ PFD_TYPE_RGBA,
+ 32,
+ 8, 0, 8, 0, 8, 0,
+ 8,
+ 0,
+ 0,
+ 0, 0, 0, 0,
+ 24,
+ 8,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,
+ 0, 0, 0
+ };
+ int pfindex = ChoosePixelFormat(dc, &pfd);
+ SetPixelFormat(dc, pfindex, &pfd);
+}
+
+static const char *g_windowClassName = "RendererWindow";
+static const DWORD g_windowStyle = WS_OVERLAPPEDWINDOW;
+static const DWORD g_fullscreenStyle = WS_POPUP;
+
+static void handleMouseEvent(UINT msg, LPARAM lParam, HWND hwnd, RendererWindow* window)
+{
+ if (!window || !window->getPlatform())
+ return;
+
+ RECT rect;
+ GetClientRect(hwnd, &rect);
+ PxU32 height = (PxU32)(rect.bottom-rect.top);
+ PxU32 x = (PxU32)LOWORD(lParam);
+ PxU32 y = height-(PxU32)HIWORD(lParam);
+ PxVec2 current(static_cast<PxReal>(x), static_cast<PxReal>(y));
+
+ WindowsPlatform& platform = *((WindowsPlatform*)window->getPlatform());
+ PxVec2 diff = current - platform.getMouseCursorPos();
+ platform.setMouseCursorPos(current);
+
+ switch (msg)
+ {
+ case WM_MOUSEMOVE:
+ if (!SamplePlatform::platform()->getMouseCursorRecentering())
+ {
+ platform.getWindowsSampleUserInput().doOnMouseMove(x, y, diff.x, diff.y, MOUSE_MOVE);
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ SetCapture(hwnd);
+ platform.getWindowsSampleUserInput().doOnMouseButton(x, y, WindowsSampleUserInput::LEFT_MOUSE_BUTTON, true);
+ break;
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ platform.getWindowsSampleUserInput().doOnMouseButton(x, y, WindowsSampleUserInput::LEFT_MOUSE_BUTTON, false);
+ break;
+ case WM_RBUTTONDOWN:
+ SetCapture(hwnd);
+ platform.getWindowsSampleUserInput().doOnMouseButton(x, y, WindowsSampleUserInput::RIGHT_MOUSE_BUTTON, true);
+ break;
+ case WM_RBUTTONUP:
+ ReleaseCapture();
+ platform.getWindowsSampleUserInput().doOnMouseButton(x, y, WindowsSampleUserInput::RIGHT_MOUSE_BUTTON, false);
+ break;
+ case WM_MBUTTONDOWN:
+ SetCapture(hwnd);
+ platform.getWindowsSampleUserInput().doOnMouseButton(x, y, WindowsSampleUserInput::CENTER_MOUSE_BUTTON, true);
+ break;
+ case WM_MBUTTONUP:
+ ReleaseCapture();
+ platform.getWindowsSampleUserInput().doOnMouseButton(x, y, WindowsSampleUserInput::CENTER_MOUSE_BUTTON, false);
+ break;
+ }
+}
+
+static INT_PTR CALLBACK windowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+#if defined(RENDERER_64BIT)
+ RendererWindow* window = (RendererWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#else
+ RendererWindow* window = (RendererWindow*)LongToPtr(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+#endif
+
+ bool customHandle = false;
+
+ if(!customHandle)
+ {
+ switch(msg)
+ {
+ case WM_SETFOCUS:
+ if(window)
+ window->setFocus(true);
+ break;
+
+ case WM_KILLFOCUS:
+ if(window)
+ window->setFocus(false);
+ break;
+
+ case WM_EXITSIZEMOVE:
+ if (window)
+ {
+ ((WindowsPlatform*)window->getPlatform())->recenterMouseCursor(false);
+ }
+ break;
+
+ case WM_CREATE:
+ ::UpdateWindow(hwnd);
+ break;
+
+ case WM_CLOSE:
+ if(window)
+ {
+ window->close();
+ }
+ break;
+
+ case WM_SIZE:
+ if(window)
+ {
+ RECT rect;
+ GetClientRect(hwnd, &rect);
+ PxU32 width = (PxU32)(rect.right-rect.left);
+ PxU32 height = (PxU32)(rect.bottom-rect.top);
+ window->onResize(width, height);
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ handleMouseEvent(WM_MOUSEMOVE, lParam, hwnd, window);
+ break;
+
+ case WM_LBUTTONDOWN:
+ ((WindowsPlatform*)window->getPlatform())->recenterMouseCursor(false);
+ handleMouseEvent(WM_LBUTTONDOWN, lParam, hwnd, window);
+ break;
+
+ case WM_LBUTTONUP:
+ handleMouseEvent(WM_LBUTTONUP, lParam, hwnd, window);
+ break;
+
+ case WM_RBUTTONDOWN:
+ handleMouseEvent(WM_RBUTTONDOWN, lParam, hwnd, window);
+ break;
+
+ case WM_RBUTTONUP:
+ handleMouseEvent(WM_RBUTTONUP, lParam, hwnd, window);
+ break;
+
+ case WM_MBUTTONDOWN:
+ handleMouseEvent(WM_MBUTTONDOWN, lParam, hwnd, window);
+ break;
+
+ case WM_MBUTTONUP:
+ handleMouseEvent(WM_MBUTTONUP, lParam, hwnd, window);
+ break;
+
+ case WM_CHAR:
+ // PT: we need to catch this message to make a difference between lower & upper case characters
+ if(window)
+ {
+ ((WindowsPlatform*)window->getPlatform())->getWindowsSampleUserInput().onKeyDownEx(wParam);
+ }
+ break;
+
+ case WM_SYSKEYDOWN: // For F10 or ALT
+ if (VK_F4 == wParam && (KF_ALTDOWN & HIWORD(lParam)))
+ {
+ if(window)
+ {
+ window->close();
+ break;
+ }
+ }
+ // no break, fall through
+ case WM_KEYDOWN:
+ if(window)
+ {
+ ((WindowsPlatform*)window->getPlatform())->getWindowsSampleUserInput().onKeyDown(wParam, lParam);
+ }
+ break;
+
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ if(window)
+ {
+ ((WindowsPlatform*)window->getPlatform())->getWindowsSampleUserInput().onKeyUp(wParam, lParam);
+ }
+ break;
+
+ case WM_PAINT:
+ ValidateRect(hwnd, 0);
+ break;
+ default:
+ return ::DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ }
+ return 0;
+}
+
+static ATOM registerWindowClass(HINSTANCE hInstance)
+{
+ static ATOM atom = 0;
+ if(!atom)
+ {
+ WNDCLASSEX wcex;
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.style = CS_HREDRAW | CS_VREDRAW;
+ wcex.lpfnWndProc = (WNDPROC)windowProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = sizeof(void*);
+ wcex.hInstance = hInstance;
+ wcex.hIcon = ::LoadIcon(hInstance, "SampleApplicationIcon");
+ wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wcex.lpszMenuName = 0;
+ wcex.lpszClassName = g_windowClassName;
+ wcex.hIconSm = ::LoadIcon(wcex.hInstance, "SampleApplicationIcon");
+ atom = ::RegisterClassEx(&wcex);
+ }
+ return atom;
+}
+
+SamplePlatform* SampleFramework::createPlatform(SampleRenderer::RendererWindow* _app)
+{
+ printf("Creating Windows platform abstraction.\n");
+ SamplePlatform::setPlatform(new WindowsPlatform(_app));
+ return SamplePlatform::platform();
+}
+
+void* WindowsPlatform::initializeD3D9()
+{
+ m_library = 0;
+ if(m_hwnd)
+ {
+#if defined(D3D_DEBUG_INFO)
+#define D3D9_DLL "d3d9d.dll"
+#else
+#define D3D9_DLL "d3d9.dll"
+#endif
+ m_library = LoadLibraryA(D3D9_DLL);
+ RENDERER_ASSERT(m_library, "Could not load " D3D9_DLL ".");
+ if(!m_library)
+ {
+ MessageBoxA(0, "Could not load " D3D9_DLL ". Please install the latest DirectX End User Runtime available at www.microsoft.com/directx.", "Renderer Error.", MB_OK);
+ }
+#undef D3D9_DLL
+ if(m_library)
+ {
+ typedef IDirect3D9* (WINAPI* LPDIRECT3DCREATE9)(UINT SDKVersion);
+ LPDIRECT3DCREATE9 pDirect3DCreate9 = (LPDIRECT3DCREATE9)GetProcAddress(m_library, "Direct3DCreate9");
+ RENDERER_ASSERT(pDirect3DCreate9, "Could not find Direct3DCreate9 function.");
+ if(pDirect3DCreate9)
+ {
+ m_d3d = pDirect3DCreate9(D3D_SDK_VERSION);
+ }
+ }
+ }
+ return m_d3d;
+}
+
+void WindowsPlatform::showCursor(bool show)
+{
+ if(show != m_showCursor)
+ {
+ m_showCursor = show;
+ PxI32 count = ShowCursor(show);
+ PX_ASSERT((m_showCursor && (count == 0)) || (!m_showCursor && (count == -1)));
+ PX_UNUSED(count);
+ }
+}
+
+void* WindowsPlatform::compileProgram(void * context,
+ const char* assetDir,
+ const char *programPath,
+ physx::PxU64 profile,
+ const char* passString,
+ const char *entry,
+ const char **args)
+
+{
+#if defined(RENDERER_ENABLE_CG)
+ char fullpath[1024];
+ Ps::strlcpy(fullpath, 1024, assetDir);
+ Ps::strlcat(fullpath, 1024, "shaders/");
+ Ps::strlcat(fullpath, 1024, programPath);
+ CGprogram program = cgCreateProgramFromFile(static_cast<CGcontext>(context), CG_SOURCE, fullpath, static_cast<CGprofile>(profile), entry, args);
+
+ if (!program)
+ {
+ static bool ignoreErrors = false;
+ if (!ignoreErrors)
+ {
+ const char* compileError = cgGetLastListing(static_cast<CGcontext>(context));
+ int ret = MessageBoxA(0, compileError, "CG cgCreateProgramFromFile Error", MB_ABORTRETRYIGNORE);
+
+ if (ret == IDABORT)
+ {
+ exit(0);
+ }
+ else if (ret == IDIGNORE)
+ {
+ ignoreErrors = true;
+ }
+ else
+ {
+ DebugBreak();
+ }
+ }
+ }
+
+ return program;
+#else
+ return NULL;
+#endif
+}
+
+WindowsPlatform::WindowsPlatform(SampleRenderer::RendererWindow* _app) :
+SamplePlatform(_app),
+m_d3d(NULL),
+m_d3dDevice(NULL),
+m_dxgiFactory(NULL),
+m_dxgiSwap(NULL),
+m_d3d11Device(NULL),
+m_d3d11DeviceContext(NULL),
+m_hwnd(0),
+m_hdc(0),
+m_hrc(0),
+m_library(NULL),
+m_dxgiLibrary(NULL),
+m_d3d11Library(NULL),
+m_ownsWindow(false),
+m_isHandlingMessages(false),
+m_destroyWindow(false),
+m_hasFocus(true),
+m_vsync(false)
+{
+ m_library = 0;
+
+ // adjust ShowCursor display counter to be 0 or -1
+ m_showCursor = true;
+ PxI32 count = ShowCursor(true);
+ while(count != 0)
+ count = ShowCursor(count < 0);
+ strcpy(m_platformName, "windows");
+
+ m_mouseCursorPos = PxVec2(0);
+ m_recenterMouseCursor = false;
+}
+
+WindowsPlatform::~WindowsPlatform()
+{
+ RENDERER_ASSERT(!m_ownsWindow || m_hwnd==0, "RendererWindow was not closed before being destroyed.");
+ if(m_d3d)
+ {
+ m_d3d->Release();
+ }
+ if(m_library)
+ {
+ FreeLibrary(m_library);
+ m_library = 0;
+ }
+ if(m_dxgiLibrary)
+ {
+ FreeLibrary(m_dxgiLibrary);
+ m_dxgiLibrary = 0;
+ }
+ if(m_d3d11Library)
+ {
+ FreeLibrary(m_d3d11Library);
+ m_d3d11Library = 0;
+ }
+}
+
+bool WindowsPlatform::isD3D9ok()
+{
+ if(m_library)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool WindowsPlatform::hasFocus() const
+{
+ return m_hasFocus;
+}
+
+void WindowsPlatform::setFocus(bool b)
+{
+ m_hasFocus = b;
+}
+
+bool WindowsPlatform::isOpen()
+{
+ if(m_hwnd && !m_destroyWindow) return true;
+ return false;
+}
+
+void WindowsPlatform::getTitle(char *title, physx::PxU32 maxLength) const
+{
+ RENDERER_ASSERT(m_hwnd, "Tried to get the title of a window that was not opened.");
+ if(m_hwnd)
+ {
+ GetWindowTextA(m_hwnd, title, maxLength);
+ }
+}
+
+void WindowsPlatform::setTitle(const char *title)
+{
+ RENDERER_ASSERT(m_hwnd, "Tried to set the title of a window that was not opened.");
+ if(m_hwnd)
+ {
+ ::SetWindowTextA(m_hwnd, title);
+ }
+}
+
+void WindowsPlatform::showMessage(const char* title, const char* message)
+{
+ printf("%s: %s\n", title, message);
+}
+
+bool WindowsPlatform::saveBitmap(const char* pFileName, physx::PxU32 width, physx::PxU32 height, physx::PxU32 sizeInBytes, const void* pData)
+{
+ bool bSuccess = false;
+ HBITMAP bitmap = CreateBitmap(width, height, 1, 32, pData);
+ if (bitmap)
+ {
+ CImage image;
+ image.Attach(bitmap, CImage::DIBOR_TOPDOWN);
+ bSuccess = SUCCEEDED(image.Save(pFileName, Gdiplus::ImageFormatBMP));
+ DeleteObject(bitmap);
+ }
+ return bSuccess;
+}
+
+void WindowsPlatform::setMouseCursorRecentering(bool val)
+{
+ if (m_recenterMouseCursor != val)
+ {
+ m_recenterMouseCursor = val;
+ if (m_recenterMouseCursor)
+ recenterMouseCursor(false);
+ }
+}
+
+bool WindowsPlatform::getMouseCursorRecentering() const
+{
+ return m_recenterMouseCursor;
+}
+
+void WindowsPlatform::recenterMouseCursor(bool generateEvent)
+{
+ if (m_recenterMouseCursor && m_app->hasFocus())
+ {
+ RECT rect;
+ GetWindowRect(m_hwnd, (LPRECT)&rect);
+ PxU32 winHeight = (PxU32)(rect.bottom-rect.top);
+ PxU32 winWidth = (PxU32)(rect.right - rect.left);
+
+ POINT winPos;
+ GetCursorPos(&winPos);
+ PxVec2 current(static_cast<PxReal>(winPos.x), winHeight - static_cast<PxReal>(winPos.y));
+
+ PxI32 winCenterX = 0;
+ PxI32 winCenterY = 0;
+ {
+ winCenterX = rect.left + PxI32(winWidth>>1);
+ winCenterY = rect.top + PxI32(winHeight>>1);
+ }
+ SetCursorPos(winCenterX, winCenterY);
+
+ if (generateEvent)
+ {
+ PxVec2 diff = current - PxVec2(static_cast<PxReal>(winCenterX), winHeight - static_cast<PxReal>(winCenterY));
+ getWindowsSampleUserInput().doOnMouseMove(winCenterX, winHeight - winCenterY, diff.x, diff.y, MOUSE_MOVE);
+ }
+
+ m_mouseCursorPos = current;
+ }
+}
+
+void WindowsPlatform::setWindowSize(physx::PxU32 width,
+ physx::PxU32 height)
+{
+ bool fullscreen = false;
+ RENDERER_ASSERT(m_hwnd, "Tried to resize a window that was not opened.");
+ if(m_hwnd)
+ {
+ RECT rect;
+ ::GetWindowRect(m_hwnd, &rect);
+ rect.right = (LONG)(rect.left + width);
+ rect.bottom = (LONG)(rect.top + height);
+ RECT oldrect = rect;
+ DWORD dwstyle = (fullscreen ? g_fullscreenStyle : g_windowStyle);
+ ::AdjustWindowRect(&rect, dwstyle, 0);
+ ::MoveWindow(m_hwnd, (int)oldrect.left, (int)oldrect.top, (int)(rect.right-rect.left), (int)(rect.bottom-rect.top), 1);
+ }
+}
+
+void WindowsPlatform::update()
+{
+ RENDERER_ASSERT(m_hwnd, "Tried to update a window that was not opened.");
+ if(m_app->isOpen())
+ {
+ m_isHandlingMessages = true;
+ MSG msg;
+
+ while(m_app->isOpen() && ::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+ m_isHandlingMessages = false;
+ if(m_hwnd && m_destroyWindow)
+ {
+ if(m_app->onClose())
+ {
+ ::DestroyWindow(m_hwnd);
+ m_hwnd = 0;
+ }
+ m_destroyWindow = false;
+ }
+ recenterMouseCursor(true);
+ }
+}
+
+bool WindowsPlatform::openWindow(physx::PxU32& width,
+ physx::PxU32& height,
+ const char* title,
+ bool fullscreen)
+{
+ bool ok = false;
+ RENDERER_ASSERT(m_hwnd==0, "Attempting to open a window that is already opened");
+ if(m_hwnd==0)
+ {
+ int offset = fullscreen ? 0 : 50;
+
+ registerWindowClass((HINSTANCE)::GetModuleHandle(0));
+ RECT winRect;
+ winRect.left = offset;
+ winRect.top = offset;
+ winRect.right = width + offset;
+ winRect.bottom = height + offset;
+ DWORD dwstyle = (fullscreen ? g_fullscreenStyle : g_windowStyle);
+
+ ::AdjustWindowRect(&winRect, dwstyle, 0);
+
+ // make sure the window fits in the main screen
+ if (!fullscreen)
+ {
+ // check the work area of the primary display
+ RECT screen;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0);
+
+ if (winRect.right > screen.right)
+ {
+ int diff = winRect.right - screen.right;
+ winRect.right -= diff;
+ winRect.left = std::max<int>(0, winRect.left - diff);
+ }
+
+ if (winRect.bottom > screen.bottom)
+ {
+ int diff = winRect.bottom - screen.bottom;
+ winRect.bottom -= diff;
+ winRect.top = std::max<int>(0, winRect.top - diff);
+ }
+ }
+
+ m_hwnd = ::CreateWindowA(g_windowClassName, title, dwstyle,
+ winRect.left, winRect.top,
+ winRect.right - winRect.left, winRect.bottom - winRect.top,
+ 0, 0, 0, 0);
+ RENDERER_ASSERT(m_hwnd, "CreateWindow failed");
+ if(m_hwnd)
+ {
+ ok = true;
+ m_ownsWindow = true;
+ ShowWindow(m_hwnd, SW_SHOWNORMAL);
+ SetFocus(m_hwnd);
+ SetWindowLongPtr(m_hwnd, GWLP_USERDATA, LONG_PTR(m_app));
+ }
+ }
+
+ {
+ RAWINPUTDEVICE rawInputDevice;
+ rawInputDevice.usUsagePage = 1;
+ rawInputDevice.usUsage = 6;
+ rawInputDevice.dwFlags = 0;
+ rawInputDevice.hwndTarget = NULL;
+
+ BOOL status = RegisterRawInputDevices(&rawInputDevice, 1, sizeof(rawInputDevice));
+ if(status!=TRUE)
+ {
+ DWORD err = GetLastError();
+ printf("%d\n", err);
+ }
+ }
+
+ return ok;
+}
+
+bool WindowsPlatform::useWindow(physx::PxU64 hwnd)
+{
+ m_hwnd = reinterpret_cast<HWND>(hwnd);
+ return true;
+}
+
+bool WindowsPlatform::closeWindow()
+{
+ if(m_hwnd)
+ {
+ if(m_isHandlingMessages)
+ {
+ m_destroyWindow = true;
+ }
+ else if(m_app->onClose())
+ {
+ ::DestroyWindow(m_hwnd);
+ m_hwnd = 0;
+ }
+ }
+
+ return true;
+}
+
+size_t WindowsPlatform::getCWD(char* path, size_t len)
+{
+ return ::GetCurrentDirectory((DWORD)len, path);
+}
+void WindowsPlatform::setCWDToEXE(void)
+{
+ char exepath[1024] = {0};
+ GetModuleFileNameA(0, exepath, sizeof(exepath));
+
+ if(exepath[0])
+ {
+ popPathSpec(exepath);
+ (void)_chdir(exepath);
+ }
+}
+
+void WindowsPlatform::setupRendererDescription(SampleRenderer::RendererDesc& renDesc)
+{
+ renDesc.driver = SampleRenderer::Renderer::DRIVER_DIRECT3D11;
+ renDesc.windowHandle = reinterpret_cast<physx::PxU64>(m_hwnd);
+}
+
+void WindowsPlatform::postRendererSetup(SampleRenderer::Renderer* renderer)
+{
+ if(!renderer)
+ {
+ // quit if no renderer was created. Nothing else to do.
+ // error was output in createRenderer.
+ exit(1);
+ }
+ char windowTitle[1024] = {0};
+ m_app->getTitle(windowTitle, 1024);
+ strcat_s(windowTitle, 1024, " : ");
+ strcat_s(windowTitle, 1024, SampleRenderer::Renderer::getDriverTypeName(
+ renderer->getDriverType()));
+ m_app->setTitle(windowTitle);
+}
+
+void WindowsPlatform::doInput()
+{
+ m_windowsSampleUserInput.updateInput();
+}
+
+void WindowsPlatform::initializeOGLDisplay(const SampleRenderer::RendererDesc& desc,
+ physx::PxU32& width,
+ physx::PxU32& height)
+{
+#if defined(RENDERER_ENABLE_OPENGL)
+ m_hwnd = reinterpret_cast<HWND>(desc.windowHandle);
+
+ RENDERER_ASSERT(m_hwnd, "Invalid window handle!");
+ // Get the device context.
+ m_hdc = GetDC(m_hwnd);
+
+ RENDERER_ASSERT(m_hdc, "Invalid device context!");
+ if(m_hdc)
+ {
+ setDCPixelFormat(m_hdc);
+ m_hrc = wglCreateContext(m_hdc);
+ }
+
+ RENDERER_ASSERT(m_hrc, "Invalid render context!");
+ if(m_hrc)
+ {
+ BOOL makeCurrentRet = wglMakeCurrent(m_hdc, m_hrc);
+ RENDERER_ASSERT(m_hrc, "Unable to set current context!");
+ if(!makeCurrentRet)
+ {
+ wglDeleteContext(m_hrc);
+ m_hrc = 0;
+ }
+ }
+#endif
+
+ m_vsync = desc.vsync;
+}
+
+physx::PxU64 WindowsPlatform::getWindowHandle()
+{
+ return reinterpret_cast<physx::PxU64>(m_hwnd);
+}
+
+void WindowsPlatform::getWindowSize(PxU32& width, PxU32& height)
+{
+ if(m_hwnd)
+ {
+ RECT rect;
+ GetClientRect(m_hwnd, &rect);
+ width = (PxU32)(rect.right - rect.left);
+ height = (PxU32)(rect.bottom - rect.top);
+ }
+}
+
+void WindowsPlatform::freeDisplay()
+{
+#if defined(RENDERER_ENABLE_OPENGL)
+ if(m_hrc)
+ {
+ wglMakeCurrent(m_hdc, 0);
+ wglDeleteContext(m_hrc);
+ m_hrc = 0;
+ }
+#endif
+}
+
+bool WindowsPlatform::makeContextCurrent()
+{
+ bool ok = false;
+
+#if defined(RENDERER_ENABLE_OPENGL)
+ if(m_hdc && m_hrc)
+ {
+ if(wglGetCurrentContext()==m_hrc)
+ {
+ ok = true;
+ }
+ else
+ {
+ ok = wglMakeCurrent(m_hdc, m_hrc) ? true : false;
+ }
+ }
+#endif
+
+ return ok;
+}
+
+void WindowsPlatform::swapBuffers()
+{
+ SwapBuffers(m_hdc);
+}
+
+bool WindowsPlatform::isContextValid()
+{
+ if(!m_hdc) return false;
+ if(!m_hrc) return false;
+ return true;
+}
+
+void WindowsPlatform::postInitializeOGLDisplay()
+{
+#if defined(RENDERER_ENABLE_OPENGL)
+ glewInit();
+
+#if defined(GLEW_MX)
+ wglewInit();
+#endif
+
+ if(WGLEW_EXT_swap_control)
+ {
+ wglSwapIntervalEXT(m_vsync ? -1 : 0);
+ }
+#endif
+}
+
+void WindowsPlatform::setOGLVsync(bool on)
+{
+#if defined(RENDERER_ENABLE_OPENGL)
+ m_vsync = on;
+ if(WGLEW_EXT_swap_control)
+ {
+ wglSwapIntervalEXT(m_vsync ? 1 : 0);
+ }
+#endif
+}
+
+physx::PxU32 WindowsPlatform::initializeD3D9Display(void * d3dPresentParameters,
+ char* m_deviceName,
+ physx::PxU32& width,
+ physx::PxU32& height,
+ void * m_d3dDevice_out)
+{
+ D3DPRESENT_PARAMETERS* m_d3dPresentParams = static_cast<D3DPRESENT_PARAMETERS*>(d3dPresentParameters);
+
+ UINT adapter = D3DADAPTER_DEFAULT;
+ D3DDEVTYPE deviceType = D3DDEVTYPE_HAL;
+
+ // check to see if fullscreen is requested...
+ bool fullscreen = false;
+ WINDOWINFO wininfo = {0};
+ if(GetWindowInfo(m_hwnd, &wininfo))
+ {
+ if(wininfo.dwStyle & WS_POPUP)
+ {
+ fullscreen = true;
+ }
+ }
+
+ // search for supported adapter mode.
+ if(fullscreen)
+ {
+ RECT rect = {0};
+ GetWindowRect(m_hwnd, &rect);
+ m_d3dPresentParams->BackBufferFormat = D3DFMT_X8R8G8B8;
+ width = (m_d3dPresentParams->BackBufferWidth = rect.right-rect.left);
+ height = (m_d3dPresentParams->BackBufferHeight = rect.bottom-rect.top);
+
+ bool foundAdapterMode = false;
+ const UINT numAdapterModes = m_d3d->GetAdapterModeCount(0, m_d3dPresentParams->BackBufferFormat);
+ for(UINT i=0; i<numAdapterModes; i++)
+ {
+ D3DDISPLAYMODE mode = {0};
+ m_d3d->EnumAdapterModes(0, m_d3dPresentParams->BackBufferFormat, i, &mode);
+ if(mode.Width == m_d3dPresentParams->BackBufferWidth &&
+ mode.Height == m_d3dPresentParams->BackBufferHeight &&
+ mode.RefreshRate > m_d3dPresentParams->FullScreen_RefreshRateInHz)
+ {
+ m_d3dPresentParams->FullScreen_RefreshRateInHz = mode.RefreshRate;
+ foundAdapterMode = true;
+ }
+ }
+ RENDERER_ASSERT(foundAdapterMode, "Unable to find supported fullscreen Adapter Mode.");
+ if(!foundAdapterMode) fullscreen = false;
+ }
+
+ // enable fullscreen mode.
+ if(fullscreen)
+ {
+ m_d3dPresentParams->Windowed = 0;
+ }
+
+#if defined(RENDERER_ENABLE_NVPERFHUD)
+ // NvPerfHud Support.
+ UINT numAdapters = m_d3d->GetAdapterCount();
+ for(UINT i=0; i<numAdapters; i++)
+ {
+ D3DADAPTER_IDENTIFIER9 identifier;
+ m_d3d->GetAdapterIdentifier(i, 0, &identifier);
+ if(strstr(identifier.Description, "PerfHUD"))
+ {
+ adapter = i;
+ deviceType = D3DDEVTYPE_REF;
+ break;
+ }
+ }
+#endif
+
+ D3DADAPTER_IDENTIFIER9 adapterIdentifier;
+ m_d3d->GetAdapterIdentifier(adapter, 0, &adapterIdentifier);
+ strncpy_s(m_deviceName, 256, adapterIdentifier.Description, 256);
+
+ HRESULT res = m_d3d->CreateDevice( adapter, deviceType,
+ m_hwnd,
+ D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED,
+ m_d3dPresentParams, &m_d3dDevice);
+ *(static_cast<IDirect3DDevice9**>(m_d3dDevice_out)) = m_d3dDevice;
+ return res;
+}
+
+physx::PxU32 WindowsPlatform::D3D9Present()
+{
+ return m_d3dDevice->Present(0, 0, m_hwnd, 0);
+}
+physx::PxU64 WindowsPlatform::getD3D9TextureFormat(SampleRenderer::RendererTexture2D::Format format)
+{
+ D3DFORMAT d3dFormat = D3DFMT_UNKNOWN;
+ switch(format)
+ {
+ case SampleRenderer::RendererTexture2D::FORMAT_B8G8R8A8: d3dFormat = D3DFMT_A8R8G8B8; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_A8: d3dFormat = D3DFMT_A8; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_R32F: d3dFormat = D3DFMT_R32F; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_DXT1: d3dFormat = D3DFMT_DXT1; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_DXT3: d3dFormat = D3DFMT_DXT3; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_DXT5: d3dFormat = D3DFMT_DXT5; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_D16: d3dFormat = D3DFMT_D16; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_D24S8: d3dFormat = D3DFMT_D24S8; break;
+ }
+ return static_cast<physx::PxU64>(d3dFormat);
+}
+
+physx::PxU64 WindowsPlatform::getD3D11TextureFormat(SampleRenderer::RendererTexture2D::Format format)
+{
+#if defined(RENDERER_ENABLE_DIRECT3D11)
+ DXGI_FORMAT dxgiFormat = DXGI_FORMAT_UNKNOWN;
+ switch(format)
+ {
+ case SampleRenderer::RendererTexture2D::FORMAT_B8G8R8A8: dxgiFormat = DXGI_FORMAT_B8G8R8A8_UNORM; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_A8: dxgiFormat = DXGI_FORMAT_A8_UNORM; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_R32F: dxgiFormat = DXGI_FORMAT_R32_FLOAT; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_DXT1: dxgiFormat = DXGI_FORMAT_BC1_UNORM; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_DXT3: dxgiFormat = DXGI_FORMAT_BC2_UNORM; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_DXT5: dxgiFormat = DXGI_FORMAT_BC3_UNORM; break;
+ case SampleRenderer::RendererTexture2D::FORMAT_D16: dxgiFormat = DXGI_FORMAT_R16_TYPELESS; break;
+ }
+#else
+ PxU64 dxgiFormat = 0;
+#endif
+ return static_cast<physx::PxU64>(dxgiFormat);
+}
+
+void* WindowsPlatform::initializeD3D11()
+{
+ m_dxgiLibrary = 0;
+ m_d3d11Library = 0;
+#if defined(RENDERER_ENABLE_DIRECT3D11)
+ if(m_hwnd)
+ {
+#if defined(D3D_DEBUG_INFO)
+#define D3D11_DLL "d3d11d.dll"
+#define DXGI_DLL "dxgid.dll"
+#else
+#define D3D11_DLL "d3d11.dll"
+#define DXGI_DLL "dxgi.dll"
+#endif
+ m_dxgiLibrary = LoadLibraryA(DXGI_DLL);
+ m_d3d11Library = LoadLibraryA(D3D11_DLL);
+ RENDERER_ASSERT(m_dxgiLibrary, "Could not load " DXGI_DLL ".");
+ RENDERER_ASSERT(m_d3d11Library, "Could not load " D3D11_DLL ".");
+ if(!m_dxgiLibrary)
+ {
+ MessageBoxA(0, "Could not load " DXGI_DLL ". Please install the latest DirectX End User Runtime available at www.microsoft.com/directx.", "Renderer Error.", MB_OK);
+ }
+ if(!m_d3d11Library)
+ {
+ MessageBoxA(0, "Could not load " D3D11_DLL ". Please install the latest DirectX End User Runtime available at www.microsoft.com/directx.", "Renderer Error.", MB_OK);
+ }
+#undef D3D11_DLL
+#undef DXGI_DLL
+ if(m_dxgiLibrary)
+ {
+ typedef HRESULT (WINAPI * LPCREATEDXGIFACTORY)(REFIID, void ** );
+ LPCREATEDXGIFACTORY pCreateDXGIFactory = (LPCREATEDXGIFACTORY)GetProcAddress(m_dxgiLibrary, "CreateDXGIFactory1");
+ RENDERER_ASSERT(pCreateDXGIFactory, "Could not find CreateDXGIFactory1 function.");
+ if(pCreateDXGIFactory)
+ {
+ pCreateDXGIFactory(__uuidof(IDXGIFactory1), (void**)(&m_dxgiFactory));
+ }
+ }
+ }
+#endif
+ return m_dxgiFactory;
+}
+
+
+bool WindowsPlatform::isD3D11ok()
+{
+ if(m_dxgiLibrary && m_d3d11Library)
+ {
+ return true;
+ }
+ return false;
+}
+
+physx::PxU32 WindowsPlatform::initializeD3D11Display(void *dxgiSwapChainDesc,
+ char *m_deviceName,
+ physx::PxU32& width,
+ physx::PxU32& height,
+ void *m_d3dDevice_out,
+ void *m_d3dDeviceContext_out,
+ void *m_dxgiSwap_out)
+{
+ HRESULT hr = S_OK;
+
+#if defined(RENDERER_ENABLE_DIRECT3D11)
+ ID3D11Device* pD3D11Device = NULL;
+ ID3D11DeviceContext* pD3D11DeviceContext = NULL;
+ IDXGISwapChain* pSwapChain = NULL;
+ IDXGIFactory1* pDXGIFactory = m_dxgiFactory;
+ DXGI_SWAP_CHAIN_DESC* pSwapChainDesc = static_cast<DXGI_SWAP_CHAIN_DESC*>(dxgiSwapChainDesc);
+
+ hr = pDXGIFactory->MakeWindowAssociation(m_hwnd, 0);
+ pSwapChainDesc->OutputWindow = m_hwnd;
+
+ bool fullscreen = false;
+ WINDOWINFO wininfo = {0};
+ if(GetWindowInfo(m_hwnd, &wininfo))
+ {
+ if(wininfo.dwStyle & WS_POPUP)
+ {
+ fullscreen = true;
+ pSwapChainDesc->Windowed = 0;
+ }
+ }
+
+ PFN_D3D11_CREATE_DEVICE pD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(m_d3d11Library, "D3D11CreateDevice");
+ RENDERER_ASSERT(pD3D11CreateDevice, "Could not find D3D11CreateDeviceAndSwapChain.");
+ if (pD3D11CreateDevice)
+ {
+ UINT i = 0;
+ IDXGIAdapter1* pAdapter = NULL;
+ std::vector<IDXGIAdapter1*> vAdapters;
+ while(pDXGIFactory->EnumAdapters1(i++, &pAdapter) != DXGI_ERROR_NOT_FOUND)
+ {
+ vAdapters.push_back(pAdapter);
+ }
+
+ const D3D_FEATURE_LEVEL supportedFeatureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ //D3D_FEATURE_LEVEL_9_3,
+ //D3D_FEATURE_LEVEL_9_2,
+ //D3D_FEATURE_LEVEL_9_1,
+ };
+
+ D3D11_CREATE_DEVICE_FLAG deviceFlags = (D3D11_CREATE_DEVICE_FLAG)(D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT);
+#if PX_DEBUG
+ deviceFlags = (D3D11_CREATE_DEVICE_FLAG)(deviceFlags | D3D11_CREATE_DEVICE_DEBUG);
+#endif
+ D3D_FEATURE_LEVEL deviceFeatureLevel = D3D_FEATURE_LEVEL_11_0;
+ for (i = 0; i < vAdapters.size(); ++i)
+ {
+ hr = pD3D11CreateDevice(
+ vAdapters[i],
+ D3D_DRIVER_TYPE_UNKNOWN,
+ NULL,
+ deviceFlags,
+ supportedFeatureLevels,
+ PX_ARRAY_SIZE(supportedFeatureLevels),
+ D3D11_SDK_VERSION,
+ &pD3D11Device,
+ &deviceFeatureLevel,
+ &pD3D11DeviceContext);
+
+ if (SUCCEEDED(hr))
+ {
+ // Disable MSAA on sub DX10.1 devices
+ if (deviceFeatureLevel <= D3D_FEATURE_LEVEL_10_0)
+ {
+ pSwapChainDesc->SampleDesc.Count = 1;
+ pSwapChainDesc->SampleDesc.Quality = 0;
+ }
+ hr = pDXGIFactory->CreateSwapChain(pD3D11Device, pSwapChainDesc, &pSwapChain);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ m_dxgiSwap = pSwapChain;
+ m_d3d11Device = pD3D11Device;
+ m_d3d11DeviceContext = pD3D11DeviceContext;
+ *(static_cast<IDXGISwapChain**>(m_dxgiSwap_out)) = m_dxgiSwap;
+ *(static_cast<ID3D11Device**>(m_d3dDevice_out)) = m_d3d11Device;
+ *(static_cast<ID3D11DeviceContext**>(m_d3dDeviceContext_out)) = m_d3d11DeviceContext;
+ break;
+ }
+
+ // If DXGI creation failed but device creation succeeded, we need to release both device and context
+ if (pD3D11Device) pD3D11Device->Release();
+ if (pD3D11DeviceContext) pD3D11DeviceContext->Release();
+ }
+
+ for (i = 0; i < vAdapters.size(); ++i)
+ {
+ vAdapters[i]->Release();
+ }
+ }
+ RENDERER_ASSERT(m_dxgiSwap && m_d3d11Device && m_d3d11DeviceContext, "Unable to create D3D device and swap chain");
+#endif
+
+ return hr;
+}
+
+bool WindowsPlatform::makeSureDirectoryPathExists(const char* dirPath)
+{
+ // [Kai] Currently create the final folder only if the dirPath doesn't exist.
+ // To create all the directories in the specified dirPath, use API
+ // MakeSureDirectoryPathExists() declared in dbghelp.h
+ bool ok = GetFileAttributes(dirPath) != -1;
+ if (!ok)
+ ok = CreateDirectory(dirPath, NULL) != 0;
+ return ok;
+}
+
+physx::PxU32 WindowsPlatform::D3D11Present(bool vsync)
+{
+#if defined(RENDERER_ENABLE_DIRECT3D11)
+ return m_dxgiSwap->Present(vsync ? 1 : 0, 0);
+#else
+ return 0;
+#endif
+}
diff --git a/PhysX_3.4/Samples/SampleFramework/platform/src/windows/WindowsSampleUserInput.cpp b/PhysX_3.4/Samples/SampleFramework/platform/src/windows/WindowsSampleUserInput.cpp
new file mode 100644
index 00000000..9e6c14a9
--- /dev/null
+++ b/PhysX_3.4/Samples/SampleFramework/platform/src/windows/WindowsSampleUserInput.cpp
@@ -0,0 +1,825 @@
+// 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-2016 NVIDIA Corporation. All rights reserved.
+
+#include <windows/WindowsSampleUserInput.h>
+
+#include <foundation/PxAssert.h>
+
+#include <stdio.h>
+#include <direct.h>
+
+static bool gTimeInit=false;
+
+// PT: TODO: share this with PxApplication
+static const unsigned int MAX_GAMEPADS = 4;
+static const unsigned int MAX_GAMEPAD_AXES = 4;
+static XINPUT_STATE m_lastInputState[MAX_GAMEPADS];
+static int m_lastAxisData[MAX_GAMEPADS][MAX_GAMEPAD_AXES];
+
+using namespace SampleFramework;
+using namespace physx;
+
+WindowsSampleUserInput::WindowsSampleUserInput()
+{
+ mXInputLibrary = 0;
+ mpXInputGetState = 0;
+ mpXInputGetCapabilities = 0;
+
+ static const unsigned int xInputLibCount = 4;
+ static const char* xInputLibs[xInputLibCount] = { "xinput1_4.dll" ,
+ "xinput1_3.dll",
+ "xinput1_2.dll",
+ "xinput1_1.dll" };
+ for (unsigned int i = 0; i < xInputLibCount; ++i)
+ {
+ mXInputLibrary = LoadLibraryA(xInputLibs[i]);
+ if(mXInputLibrary)
+ break;
+ }
+ PX_ASSERT(mXInputLibrary && "Could not load XInput library.");
+ if (mXInputLibrary)
+ {
+ mpXInputGetState = (LPXINPUTGETSTATE)GetProcAddress(mXInputLibrary, "XInputGetState");
+ mpXInputGetCapabilities = (LPXINPUTGETCAPABILITIES)GetProcAddress(mXInputLibrary, "XInputGetCapabilities");
+ PX_ASSERT(mpXInputGetState && "Error loading XInputGetState function.");
+ PX_ASSERT(mpXInputGetCapabilities && "Error loading XInputGetCapabilities function.");
+ }
+
+ mGamePadConnected = false;
+ mConnectedPad = 0;
+
+ // register all user inputs for windows platform
+ registerUserInput(WKEY_1,"KEY_1", "1");
+ registerUserInput(WKEY_2,"KEY_2", "2");
+ registerUserInput(WKEY_3,"KEY_3", "3");
+ registerUserInput(WKEY_4,"KEY_4", "4");
+ registerUserInput(WKEY_5,"KEY_5", "5");
+ registerUserInput(WKEY_6,"KEY_6", "6");
+ registerUserInput(WKEY_7,"KEY_7", "7");
+ registerUserInput(WKEY_8,"KEY_8", "8");
+ registerUserInput(WKEY_9,"KEY_9", "9");
+ registerUserInput(WKEY_0,"KEY_0", "0");
+
+ registerUserInput(WKEY_A,"KEY_A", "A");
+ registerUserInput(WKEY_B,"KEY_B", "B");
+ registerUserInput(WKEY_C,"KEY_C", "C");
+ registerUserInput(WKEY_D,"KEY_D", "D");
+ registerUserInput(WKEY_E,"KEY_E", "E");
+ registerUserInput(WKEY_F,"KEY_F", "F");
+ registerUserInput(WKEY_G,"KEY_G", "G");
+ registerUserInput(WKEY_H,"KEY_H", "H");
+ registerUserInput(WKEY_I,"KEY_I", "I");
+ registerUserInput(WKEY_J,"KEY_J", "J");
+ registerUserInput(WKEY_K,"KEY_K", "K");
+ registerUserInput(WKEY_L,"KEY_L", "L");
+ registerUserInput(WKEY_M,"KEY_M", "M");
+ registerUserInput(WKEY_N,"KEY_N", "N");
+ registerUserInput(WKEY_O,"KEY_O", "O");
+ registerUserInput(WKEY_P,"KEY_P", "P");
+ registerUserInput(WKEY_Q,"KEY_Q", "Q");
+ registerUserInput(WKEY_R,"KEY_R", "R");
+ registerUserInput(WKEY_S,"KEY_S", "S");
+ registerUserInput(WKEY_T,"KEY_T", "T");
+ registerUserInput(WKEY_U,"KEY_U", "U");
+ registerUserInput(WKEY_V,"KEY_V", "V");
+ registerUserInput(WKEY_W,"KEY_W", "W");
+ registerUserInput(WKEY_X,"KEY_X", "X");
+ registerUserInput(WKEY_Y,"KEY_Y", "Y");
+ registerUserInput(WKEY_Z,"KEY_Z", "Z");
+
+ registerUserInput(WKEY_SPACE ,"KEY_SPACE","Space");
+ registerUserInput(WKEY_RETURN ,"KEY_RETURN","Enter");
+ registerUserInput(WKEY_SHIFT ,"KEY_SHIFT","Shift");
+ registerUserInput(WKEY_CONTROL ,"KEY_CONTROL","Control");
+ registerUserInput(WKEY_ESCAPE ,"KEY_ESCAPE","Escape");
+ registerUserInput(WKEY_COMMA ,"KEY_COMMA",",");
+ registerUserInput(WKEY_NUMPAD0 ,"KEY_NUMPAD0","Numpad 0");
+ registerUserInput(WKEY_NUMPAD1 ,"KEY_NUMPAD1","Numpad 1");
+ registerUserInput(WKEY_NUMPAD2 ,"KEY_NUMPAD2","Numpad 2");
+ registerUserInput(WKEY_NUMPAD3 ,"KEY_NUMPAD3","Numpad 3");
+ registerUserInput(WKEY_NUMPAD4 ,"KEY_NUMPAD4","Numpad 4");
+ registerUserInput(WKEY_NUMPAD5 ,"KEY_NUMPAD5","Numpad 5");
+ registerUserInput(WKEY_NUMPAD6 ,"KEY_NUMPAD6","Numpad 6");
+ registerUserInput(WKEY_NUMPAD7 ,"KEY_NUMPAD7","Numpad 7");
+ registerUserInput(WKEY_NUMPAD8 ,"KEY_NUMPAD8","Numpad 8");
+ registerUserInput(WKEY_NUMPAD9 ,"KEY_NUMPAD9","Numpad 9");
+ registerUserInput(WKEY_MULTIPLY ,"KEY_MULTIPLY","*");
+ registerUserInput(WKEY_ADD ,"KEY_ADD","+");
+ registerUserInput(WKEY_SEPARATOR ,"KEY_SEPARATOR","Separator");
+ registerUserInput(WKEY_SUBTRACT ,"KEY_SUBTRACT","-");
+ registerUserInput(WKEY_DECIMAL ,"KEY_DECIMAL",".");
+ registerUserInput(WKEY_DIVIDE ,"KEY_DIVIDE","/");
+
+ registerUserInput(WKEY_F1 ,"KEY_F1","F1");
+ registerUserInput(WKEY_F2 ,"KEY_F2","F2");
+ registerUserInput(WKEY_F3 ,"KEY_F3","F3");
+ registerUserInput(WKEY_F4 ,"KEY_F4","F4");
+ registerUserInput(WKEY_F5 ,"KEY_F5","F5");
+ registerUserInput(WKEY_F6 ,"KEY_F6","F6");
+ registerUserInput(WKEY_F7 ,"KEY_F7","F7");
+ registerUserInput(WKEY_F8 ,"KEY_F8","F8");
+ registerUserInput(WKEY_F9 ,"KEY_F9","F9");
+ registerUserInput(WKEY_F10 ,"KEY_F10","F10");
+ registerUserInput(WKEY_F11 ,"KEY_F11","F11");
+ registerUserInput(WKEY_F12 ,"KEY_F12","F12");
+
+ registerUserInput(WKEY_TAB ,"KEY_TAB","Tab");
+ registerUserInput(WKEY_BACKSPACE,"KEY_BACKSPACE","Backspace");
+ registerUserInput(WKEY_PRIOR ,"KEY_PRIOR","PgUp");
+ registerUserInput(WKEY_NEXT ,"KEY_NEXT","PgDn");
+ registerUserInput(WKEY_UP ,"KEY_UP","Up Arrow");
+ registerUserInput(WKEY_DOWN ,"KEY_DOWN","Down Arrow");
+ registerUserInput(WKEY_LEFT ,"KEY_LEFT","Left Arrow");
+ registerUserInput(WKEY_RIGHT ,"KEY_RIGHT","Right Arrow");
+
+ // mouse
+ registerUserInput(MOUSE_BUTTON_LEFT ,"MOUSE_BUTTON_LEFT","Left Mouse Button");
+ registerUserInput(MOUSE_BUTTON_RIGHT ,"MOUSE_BUTTON_RIGHT","Right Mouse Button");
+ registerUserInput(MOUSE_BUTTON_CENTER ,"MOUSE_BUTTON_CENTER","Middle Mouse Button");
+
+ registerUserInput(MOUSE_MOVE,"MOUSE_MOVE", "Mouse Move");
+
+ //assumes the pad naming conventions of xbox
+ registerUserInput(GAMEPAD_DIGI_UP,"GAMEPAD_DIGI_UP", "gpad UP");
+ registerUserInput(GAMEPAD_DIGI_DOWN,"GAMEPAD_DIGI_DOWN", "gpad DOWN");
+ registerUserInput(GAMEPAD_DIGI_LEFT,"GAMEPAD_DIGI_LEFT", "gpad LEFT");
+ registerUserInput(GAMEPAD_DIGI_RIGHT,"GAMEPAD_DIGI_RIGHT", "gpad RIGHT");
+ registerUserInput(GAMEPAD_START ,"GAMEPAD_START", "gpad START");
+ registerUserInput(GAMEPAD_SELECT ,"GAMEPAD_SELECT", "gpad BACK");
+ registerUserInput(GAMEPAD_LEFT_STICK ,"GAMEPAD_LEFT_STICK", "gpad LSTICK");
+ registerUserInput(GAMEPAD_RIGHT_STICK ,"GAMEPAD_RIGHT_STICK", "gpad RSTICK");
+ registerUserInput(GAMEPAD_NORTH ,"GAMEPAD_NORTH", "gpad Y");
+ registerUserInput(GAMEPAD_SOUTH ,"GAMEPAD_SOUTH", "gpad A");
+ registerUserInput(GAMEPAD_WEST ,"GAMEPAD_WEST", "gpad X");
+ registerUserInput(GAMEPAD_EAST ,"GAMEPAD_EAST", "gpad B");
+ registerUserInput(GAMEPAD_LEFT_SHOULDER_TOP ,"GAMEPAD_LEFT_SHOULDER_TOP", "gpad LB");
+ registerUserInput(GAMEPAD_RIGHT_SHOULDER_TOP ,"GAMEPAD_RIGHT_SHOULDER_TOP", "gpad RB");
+ registerUserInput(GAMEPAD_LEFT_SHOULDER_BOT ,"GAMEPAD_LEFT_SHOULDER_BOT", "gpad LT");
+ registerUserInput(GAMEPAD_RIGHT_SHOULDER_BOT ,"GAMEPAD_RIGHT_SHOULDER_BOT", "gpad RT");
+
+ registerUserInput(GAMEPAD_RIGHT_STICK_X,"GAMEPAD_RIGHT_STICK_X", "gpad RSTICK");
+ registerUserInput(GAMEPAD_RIGHT_STICK_Y,"GAMEPAD_RIGHT_STICK_Y", "gpad RSTICK");
+ registerUserInput(GAMEPAD_LEFT_STICK_X,"GAMEPAD_LEFT_STICK_X", "gpad LSTICK");
+ registerUserInput(GAMEPAD_LEFT_STICK_Y,"GAMEPAD_LEFT_STICK_Y", "gpad LSTICK");
+
+ // use scan codes for movement
+ PxU16 vkey = (PxU16) MapVirtualKey(18, MAPVK_VSC_TO_VK);
+ WindowsSampleUserInputIds getId = getKeyCode(vkey);
+ const UserInput* ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_UP,"SCAN_CODE_E", ui->m_Name);
+ mScanCodesMap[18] = SCAN_CODE_UP;
+ }
+
+ vkey = (PxU16)MapVirtualKey(46, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_DOWN,"SCAN_CODE_C", ui->m_Name);
+ mScanCodesMap[46] = SCAN_CODE_DOWN;
+ }
+
+ vkey = (PxU16) MapVirtualKey(30, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_LEFT,"SCAN_CODE_A", ui->m_Name);
+ mScanCodesMap[30] = SCAN_CODE_LEFT;
+ }
+
+ vkey = (PxU16) MapVirtualKey(32, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_RIGHT,"SCAN_CODE_D", ui->m_Name);
+ mScanCodesMap[32] = SCAN_CODE_RIGHT;
+ }
+
+
+ vkey = (PxU16) MapVirtualKey(17, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_FORWARD,"SCAN_CODE_W", ui->m_Name);
+ mScanCodesMap[17] = SCAN_CODE_FORWARD;
+ }
+
+ vkey = (PxU16) MapVirtualKey(31, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_BACKWARD,"SCAN_CODE_S", ui->m_Name);
+ mScanCodesMap[31] = SCAN_CODE_BACKWARD;
+ }
+
+ vkey = (PxU16) MapVirtualKey(42, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_LEFT_SHIFT,"SCAN_CODE_LEFT_SHIFT", ui->m_Name);
+ mScanCodesMap[42] = SCAN_CODE_LEFT_SHIFT;
+ }
+
+ vkey = (PxU16) MapVirtualKey(57, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_SPACE,"SCAN_CODE_SPACE", ui->m_Name);
+ mScanCodesMap[57] = SCAN_CODE_SPACE;
+ }
+
+ vkey =(PxU16) MapVirtualKey(38, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_L,"SCAN_CODE_L", ui->m_Name);
+ mScanCodesMap[38] = SCAN_CODE_L;
+ }
+
+ vkey = (PxU16)MapVirtualKey(10, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_9,"SCAN_CODE_9", ui->m_Name);
+ mScanCodesMap[10] = SCAN_CODE_9;
+ }
+
+ vkey = (PxU16)MapVirtualKey(11, MAPVK_VSC_TO_VK);
+ getId = getKeyCode(vkey);
+ ui = getUserInputFromId(getId);
+ if(ui)
+ {
+ registerUserInput(SCAN_CODE_0,"SCAN_CODE_0", ui->m_Name);
+ mScanCodesMap[11] = SCAN_CODE_0;
+ }
+
+}
+
+const UserInput* WindowsSampleUserInput::getUserInputFromId(WindowsSampleUserInputIds id) const
+{
+ for (size_t i = mUserInputs.size(); i--;)
+ {
+ if(mUserInputs[i].m_Id == id)
+ {
+ return &mUserInputs[i];
+ }
+ }
+
+ return NULL;
+}
+
+WindowsSampleUserInput::~WindowsSampleUserInput()
+{
+ mScanCodesMap.clear();
+ mAnalogStates.clear();
+ mDigitalStates.clear();
+ if (mXInputLibrary)
+ {
+ FreeLibrary(mXInputLibrary);
+ mXInputLibrary = 0;
+ }
+}
+
+WindowsSampleUserInputIds WindowsSampleUserInput::getKeyCode(WPARAM wParam) const
+{
+ WindowsSampleUserInputIds keyCode = WKEY_UNKNOWN;
+ const int keyparam = (int)wParam;
+
+ if(keyparam >= 'A' && keyparam <= 'Z') keyCode = (WindowsSampleUserInputIds)((keyparam - 'A')+WKEY_A);
+ else if(keyparam >= '0' && keyparam <= '9') keyCode = (WindowsSampleUserInputIds)((keyparam - '0')+WKEY_0);
+ else if(keyparam >= VK_NUMPAD0 && keyparam <= VK_DIVIDE) keyCode = (WindowsSampleUserInputIds)((keyparam - VK_NUMPAD0)+WKEY_NUMPAD0);
+ else if(keyparam == VK_SHIFT) keyCode = WKEY_SHIFT;
+ else if(keyparam == VK_CONTROL) keyCode = WKEY_CONTROL;
+ else if(keyparam == VK_SPACE) keyCode = WKEY_SPACE;
+ else if(keyparam == VK_RETURN) keyCode = WKEY_RETURN;
+ else if(keyparam == VK_ESCAPE) keyCode = WKEY_ESCAPE;
+ else if(keyparam == VK_OEM_COMMA) keyCode = WKEY_COMMA;
+ else if(keyparam == VK_OEM_2) keyCode = WKEY_DIVIDE;
+ else if(keyparam == VK_OEM_MINUS) keyCode = WKEY_SUBTRACT;
+ else if(keyparam == VK_OEM_PLUS) keyCode = WKEY_ADD;
+ //
+ else if(keyparam == VK_F1) keyCode = WKEY_F1;
+ else if(keyparam == VK_F2) keyCode = WKEY_F2;
+ else if(keyparam == VK_F3) keyCode = WKEY_F3;
+ else if(keyparam == VK_F4) keyCode = WKEY_F4;
+ else if(keyparam == VK_F5) keyCode = WKEY_F5;
+ else if(keyparam == VK_F6) keyCode = WKEY_F6;
+ else if(keyparam == VK_F7) keyCode = WKEY_F7;
+ else if(keyparam == VK_F8) keyCode = WKEY_F8;
+ else if(keyparam == VK_F9) keyCode = WKEY_F9;
+ else if(keyparam == VK_F10) keyCode = WKEY_F10;
+ else if(keyparam == VK_F11) keyCode = WKEY_F11;
+ else if(keyparam == VK_F12) keyCode = WKEY_F12;
+ //
+ else if(keyparam == VK_TAB) keyCode = WKEY_TAB;
+ else if(keyparam == VK_BACK) keyCode = WKEY_BACKSPACE;
+ //
+ else if(keyparam == VK_PRIOR) keyCode = WKEY_PRIOR;
+ else if(keyparam == VK_NEXT) keyCode = WKEY_NEXT;
+ //
+ else if(keyparam == VK_UP) keyCode = WKEY_UP;
+ else if(keyparam == VK_DOWN) keyCode = WKEY_DOWN;
+ else if(keyparam == VK_LEFT) keyCode = WKEY_LEFT;
+ else if(keyparam == VK_RIGHT) keyCode = WKEY_RIGHT;
+
+ return keyCode;
+}
+
+SampleUserInput::KeyCode WindowsSampleUserInput::getSampleUserInputKeyCode(WPARAM wParam) const
+{
+ SampleUserInput::KeyCode keyCode = KEY_UNKNOWN;
+ const int keyparam = (int)wParam;
+ // PT: TODO: the comment below is of course wrong. You just need to use the proper event code (WM_CHAR)
+ //there are no lowercase virtual key codes!!
+ //if( keyparam >= 'a' && keyparam <= 'z') keyCode = (RendererWindow::KeyCode)((keyparam - 'a')+KEY_A); else
+
+ if(keyparam >= 'A' && keyparam <= 'Z') keyCode = (SampleUserInput::KeyCode)((keyparam - 'A')+KEY_A);
+ else if(keyparam >= '0' && keyparam <= '9') keyCode = (SampleUserInput::KeyCode)((keyparam - '0')+KEY_0);
+ else if(keyparam >= VK_NUMPAD0 && keyparam <= VK_DIVIDE) keyCode = (SampleUserInput::KeyCode)((keyparam - VK_NUMPAD0)+KEY_NUMPAD0);
+ else if(keyparam == VK_SHIFT) keyCode = KEY_SHIFT;
+ else if(keyparam == VK_CONTROL) keyCode = KEY_CONTROL;
+ else if(keyparam == VK_SPACE) keyCode = KEY_SPACE;
+ else if(keyparam == VK_RETURN) keyCode = KEY_RETURN;
+ else if(keyparam == VK_ESCAPE) keyCode = KEY_ESCAPE;
+ else if(keyparam == VK_OEM_COMMA) keyCode = KEY_COMMA;
+ else if(keyparam == VK_OEM_2) keyCode = KEY_DIVIDE;
+ else if(keyparam == VK_OEM_MINUS) keyCode = KEY_SUBTRACT;
+ else if(keyparam == VK_OEM_PLUS) keyCode = KEY_ADD;
+ //
+ else if(keyparam == VK_F1) keyCode = KEY_F1;
+ else if(keyparam == VK_F2) keyCode = KEY_F2;
+ else if(keyparam == VK_F3) keyCode = KEY_F3;
+ else if(keyparam == VK_F4) keyCode = KEY_F4;
+ else if(keyparam == VK_F5) keyCode = KEY_F5;
+ else if(keyparam == VK_F6) keyCode = KEY_F6;
+ else if(keyparam == VK_F7) keyCode = KEY_F7;
+ else if(keyparam == VK_F8) keyCode = KEY_F8;
+ else if(keyparam == VK_F9) keyCode = KEY_F9;
+ else if(keyparam == VK_F10) keyCode = KEY_F10;
+ else if(keyparam == VK_F11) keyCode = KEY_F11;
+ else if(keyparam == VK_F12) keyCode = KEY_F12;
+ //
+ else if(keyparam == VK_TAB) keyCode = KEY_TAB;
+ //
+ else if(keyparam == VK_PRIOR) keyCode = KEY_PRIOR;
+ else if(keyparam == VK_NEXT) keyCode = KEY_NEXT;
+ //
+ else if(keyparam == VK_UP) keyCode = KEY_UP;
+ else if(keyparam == VK_DOWN) keyCode = KEY_DOWN;
+ else if(keyparam == VK_LEFT) keyCode = KEY_LEFT;
+ else if(keyparam == VK_RIGHT) keyCode = KEY_RIGHT;
+
+ return keyCode;
+}
+
+void WindowsSampleUserInput::doOnMouseMove(physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, WindowsSampleUserInputIds button)
+{
+ const std::vector<size_t>* events = getInputEvents((PxU16)button);
+
+ if(events)
+ {
+ for (size_t i = events->size(); i--;)
+ {
+ const InputEvent& ie = mInputEvents[(*events)[i]];
+ if(getInputEventListener())
+ {
+ getInputEventListener()->onPointerInputEvent(ie, x, y, dx, dy, false);
+ }
+ }
+ }
+
+}
+
+void WindowsSampleUserInput::doOnMouseButton(physx::PxU32 x, physx::PxU32 y , MouseButtons button, bool down)
+{
+ WindowsSampleUserInputIds buttonId = WKEY_UNKNOWN;
+ WindowsSampleUserInputIds buttonIdOpposite = WKEY_UNKNOWN;
+ switch (button)
+ {
+ case LEFT_MOUSE_BUTTON:
+ buttonId = MOUSE_BUTTON_LEFT;
+ break;
+ case RIGHT_MOUSE_BUTTON:
+ buttonId = MOUSE_BUTTON_RIGHT;
+ break;
+ case CENTER_MOUSE_BUTTON:
+ buttonId = MOUSE_BUTTON_CENTER;
+ break;
+ }
+
+ const std::vector<size_t>* events = getInputEvents((PxU16)buttonId);
+ if(events)
+ {
+ for (size_t i = events->size(); i--;)
+ {
+ const InputEvent& ie = mInputEvents[(*events)[i]];
+ mDigitalStates[ie.m_Id] = down;
+
+ if(getInputEventListener())
+ {
+ getInputEventListener()->onPointerInputEvent(ie, x, y, 0, 0, down);
+ }
+ }
+ }
+}
+
+void WindowsSampleUserInput::onKeyDownEx(WPARAM wParam)
+{
+ if(getInputEventListener())
+ {
+ KeyCode keyCode = getSampleUserInputKeyCode(wParam);
+
+ getInputEventListener()->onKeyDownEx(keyCode, (PxU32)wParam);
+ }
+}
+
+void WindowsSampleUserInput::onKeyDown(WPARAM wParam, LPARAM lParam)
+{
+ PxU16 scanCode = (lParam >> 16) & 0xFF;
+ const std::vector<size_t>* events = NULL;
+ std::map<physx::PxU16, physx::PxU16>::iterator fit = mScanCodesMap.find(scanCode);
+ if(fit != mScanCodesMap.end())
+ {
+ events = getInputEvents(fit->second);
+ }
+
+ if(!events)
+ {
+ WindowsSampleUserInputIds keyCode = getKeyCode(wParam);
+ events = getInputEvents((PxU16)keyCode);
+ }
+
+ if(!events || !getInputEventListener())
+ return;
+
+ for (size_t i = events->size(); i--;)
+ {
+ const InputEvent& ie = mInputEvents[(*events)[i]];
+ mDigitalStates[ie.m_Id] = true;
+ getInputEventListener()->onDigitalInputEvent(ie, true);
+ }
+}
+
+void WindowsSampleUserInput::onKeyUp(WPARAM wParam, LPARAM lParam)
+{
+ PxU16 scanCode = (lParam >> 16) & 0xFF;
+ const std::vector<size_t>* events = NULL;
+ std::map<physx::PxU16, physx::PxU16>::iterator fit = mScanCodesMap.find(scanCode);
+ if(fit != mScanCodesMap.end())
+ {
+ events = getInputEvents(fit->second);
+ }
+ if(!events)
+ {
+ WindowsSampleUserInputIds keyCode = getKeyCode(wParam);
+ events = getInputEvents((PxU16)keyCode);
+ }
+
+ if(!events || !getInputEventListener())
+ return;
+
+ for (size_t i = events->size(); i--;)
+ {
+ const InputEvent& ie = mInputEvents[(*events)[i]];
+ mDigitalStates[ie.m_Id] = false;
+ getInputEventListener()->onDigitalInputEvent(ie, false);
+ }
+}
+
+void WindowsSampleUserInput::onKeyEvent(const KeyEvent& keyEvent)
+{
+ WindowsSampleUserInputIds keyCode = getKeyCode(keyEvent.m_Param);
+ const std::vector<size_t>* events = getInputEvents((PxU16)keyCode);
+
+ if(!events || !getInputEventListener())
+ return;
+
+ for (size_t i = events->size(); i--;)
+ {
+ const InputEvent& ie = mInputEvents[(*events)[i]];
+
+ if(keyEvent.m_Flags == KEY_EVENT_UP)
+ {
+ mDigitalStates[ie.m_Id] = false;
+ getInputEventListener()->onDigitalInputEvent(ie, false);
+ }
+
+ if(keyEvent.m_Flags == KEY_EVENT_DOWN)
+ {
+ mDigitalStates[ie.m_Id] = true;
+ getInputEventListener()->onDigitalInputEvent(ie, true);
+ }
+ }
+}
+
+bool WindowsSampleUserInput::getDigitalInputEventState(physx::PxU16 inputEventId ) const
+{
+ std::map<physx::PxU16,bool>::const_iterator fit = mDigitalStates.find(inputEventId);
+ if(fit != mDigitalStates.end())
+ {
+ return fit->second;
+ }
+ else
+ {
+ return false;
+ }
+}
+float WindowsSampleUserInput::getAnalogInputEventState(physx::PxU16 inputEventId ) const
+{
+ std::map<physx::PxU16,float>::const_iterator fit = mAnalogStates.find(inputEventId);
+ if(fit != mAnalogStates.end())
+ {
+ return fit->second;
+ }
+ else
+ {
+ return 0.0f;
+ }
+}
+
+void WindowsSampleUserInput::onGamepadAnalogButton(physx::PxU32 buttonIndex,const BYTE oldValue,const BYTE newValue)
+{
+ const std::vector<size_t>* events = getInputEvents((PxU16)buttonIndex);
+
+ if(!events || !getInputEventListener())
+ return;
+
+ bool newUp = false;
+ bool newDown = false;
+ if( !oldValue && newValue )
+ {
+ newUp = true;
+ }
+ else if( oldValue && !newValue )
+ {
+ newDown = true;
+ }
+
+ for (size_t i = events->size(); i--;)
+ {
+ const InputEvent& ie = mInputEvents[(*events)[i]];
+ if(ie.m_Analog)
+ {
+ mAnalogStates[ie.m_Id] = newValue/255.0f;
+ getInputEventListener()->onAnalogInputEvent(ie, newValue/255.0f);
+ }
+ else
+ {
+ if(newUp)
+ {
+ mDigitalStates[ie.m_Id] = true;
+ getInputEventListener()->onDigitalInputEvent(ie, true);
+ }
+ if(newDown)
+ {
+ mDigitalStates[ie.m_Id] = false;
+ getInputEventListener()->onDigitalInputEvent(ie, false);
+ }
+ }
+ }
+
+
+
+}
+
+void WindowsSampleUserInput::onGamepadButton(physx::PxU32 buttonIndex, bool buttonDown)
+{
+ PxU16 userInput = (PxU16) (GAMEPAD_DIGI_UP + buttonIndex);
+
+ const std::vector<size_t>* events = getInputEvents(userInput);
+
+ if(!events || !getInputEventListener())
+ return;
+
+ for (size_t i = 0; i < events->size(); i++)
+ {
+ const InputEvent& ie = mInputEvents[(*events)[i]];
+ mDigitalStates[ie.m_Id] = buttonDown;
+ getInputEventListener()->onDigitalInputEvent(ie, buttonDown);
+ }
+}
+
+void WindowsSampleUserInput::onGamepadAxis(physx::PxU32 axis, physx::PxReal val)
+{
+ PxU16 userInput = (PxU16)(GAMEPAD_RIGHT_STICK_X + axis);
+
+ const std::vector<size_t>* events = getInputEvents(userInput);
+
+ if(!events || !getInputEventListener())
+ return;
+
+ for (size_t i = events->size(); i--;)
+ {
+ const InputEvent& ie = mInputEvents[(*events)[i]];
+ mAnalogStates[ie.m_Id] = val;
+ getInputEventListener()->onAnalogInputEvent(ie, val);
+ }
+
+}
+
+void WindowsSampleUserInput::shutdown()
+{
+ mAnalogStates.clear();
+ mDigitalStates.clear();
+
+ SampleUserInput::shutdown();
+}
+
+void WindowsSampleUserInput::updateInput()
+{
+ SampleUserInput::updateInput();
+
+ processGamepads();
+}
+
+void WindowsSampleUserInput::processGamepads()
+{
+ SampleUserInput::processGamepads();
+
+ if(!gTimeInit)
+ {
+ gTimeInit=true;
+
+ for(PxU32 p=0;p<MAX_GAMEPADS;p++)
+ {
+ memset(&m_lastInputState[p], 0, sizeof(XINPUT_STATE));
+ for(PxU32 i=0;i<MAX_GAMEPAD_AXES;i++)
+ {
+ m_lastAxisData[p][i]=0;
+ }
+ }
+ }
+
+ static PxI32 disConnected[4] = {1, 2, 3, 4};
+
+ if (!hasXInput())
+ return;
+
+ // PT: TODO: share this with PxApplication
+ for(PxU32 p=0;p<MAX_GAMEPADS;p++)
+ {
+ if((--disConnected[p]) == 0)
+ {
+ XINPUT_STATE inputState;
+ DWORD state = mpXInputGetState(p, &inputState);
+ if(state == ERROR_DEVICE_NOT_CONNECTED)
+ {
+ disConnected[p] = 4;
+ if(mGamePadConnected && (mConnectedPad == p))
+ {
+ mGamePadConnected = false;
+ mConnectedPad = 0;
+ for (PxU32 k=0;k<MAX_GAMEPADS;k++)
+ {
+ XINPUT_STATE inputStateDisc;
+ DWORD stateDisc = mpXInputGetState(k, &inputStateDisc);
+ if(stateDisc == ERROR_SUCCESS)
+ {
+ mConnectedPad = k;
+ mGamePadConnected = true;
+ break;
+ }
+ }
+ }
+ }
+ else if(state == ERROR_SUCCESS)
+ {
+ if(!mGamePadConnected)
+ {
+ mGamePadConnected = true;
+ mConnectedPad = p;
+ }
+
+ disConnected[p] = 1; //force to test next time
+ XINPUT_CAPABILITIES caps;
+ mpXInputGetCapabilities(p, XINPUT_FLAG_GAMEPAD, &caps);
+
+ //gamepad
+ {
+ // Process buttons
+ const WORD lastWButtons = m_lastInputState[p].Gamepad.wButtons;
+ const WORD currWButtons = inputState.Gamepad.wButtons;
+
+ const WORD buttonsDown = currWButtons & ~lastWButtons;
+ const WORD buttonsUp = ~currWButtons & lastWButtons;
+ // const WORD buttonsHeld = currWButtons & lastWButtons;
+
+ for(int i=0;i<14;i++)
+ {
+ // order has to match struct GamepadControls
+ static const WORD buttonMasks[]={
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT,
+ XINPUT_GAMEPAD_DPAD_RIGHT,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_BACK,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ };
+
+ if (buttonsDown & buttonMasks[i])
+ onGamepadButton(i, true);
+ else if(buttonsUp & buttonMasks[i])
+ onGamepadButton(i, false);
+ }
+
+ // PT: I think we do the 2 last ones separately because they're listed in GamepadControls but not in buttonMasks...
+ {
+ const BYTE oldTriggerVal = m_lastInputState[p].Gamepad.bRightTrigger;
+ const BYTE newTriggerVal = inputState.Gamepad.bRightTrigger;
+ onGamepadAnalogButton(GAMEPAD_RIGHT_SHOULDER_BOT, oldTriggerVal, newTriggerVal);
+ }
+ {
+ const BYTE oldTriggerVal = m_lastInputState[p].Gamepad.bLeftTrigger;
+ const BYTE newTriggerVal = inputState.Gamepad.bLeftTrigger;
+ onGamepadAnalogButton(GAMEPAD_LEFT_SHOULDER_BOT, oldTriggerVal, newTriggerVal);
+ }
+ }
+
+ // Gamepad
+ const int axisData[] = {inputState.Gamepad.sThumbRX, inputState.Gamepad.sThumbRY, inputState.Gamepad.sThumbLX, inputState.Gamepad.sThumbLY };
+ for(PxU32 i=0;i<MAX_GAMEPAD_AXES;i++)
+ {
+ if(axisData[i] != m_lastAxisData[p][i])
+ {
+ int data = axisData[i];
+ if(abs(data) < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
+ {
+ data = 0;
+ }
+ onGamepadAxis( i, ((float)data)/SHRT_MAX);
+ }
+ m_lastAxisData[p][i] = axisData[i];
+ }
+ m_lastInputState[p] = inputState;
+ }
+ }
+ }
+}
+
+bool WindowsSampleUserInput::gamepadSupported() const
+{
+ return mGamePadConnected;
+}
+
+InputType WindowsSampleUserInput::getInputType(const UserInput& ui) const
+{
+ if(ui.m_Id > WKEY_DEFINITION_START && ui.m_Id < WKEY_DEFINITION_END)
+ {
+ return KEYBOARD_INPUT;
+ }
+
+ if(ui.m_Id > GAMEPAD_DEFINITION_START && ui.m_Id < GAMEPAD_DEFINITION_END)
+ {
+ return GAMEPAD_INPUT;
+ }
+
+ if(ui.m_Id > MOUSE_DEFINITION_START && ui.m_Id < MOUSE_DEFINITION_END)
+ {
+ return MOUSE_INPUT;
+ }
+
+ return UNDEFINED_INPUT;
+}
+