diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Samples/SampleFramework/platform/src | |
| download | physx-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')
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; +} + |