This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,577 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#include <RendererMemoryMacros.h>
#include <linux/LinuxSamplePlatform.h>
#include <SampleApplication.h>
#include <Cg/cg.h>
#include <stdio.h>
#include <Ps.h>
#include <PsString.h>
//#include <PsFile.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
using namespace SampleFramework;
using SampleRenderer::RendererWindow;
namespace Ps = physx::shdfnd;
// filters OS key auto repeat, otherwise you get repeatedly key released and pressed events
// returns true if the supplied event was a auto repeat one.
// XAutoRepeatOff(m_display); does change the behaviour for the entire display.
// So you see the effect also in other apps while the samples are running, which is bad.
bool LinuxPlatform::filterKeyRepeat(const XEvent& keyReleaseEvent)
{
if(keyReleaseEvent.type == KeyRelease && XEventsQueued(m_display, QueuedAfterReading))
{
XEvent nev;
XPeekEvent(m_display, &nev);
if (nev.type == KeyPress &&
nev.xkey.time == keyReleaseEvent.xkey.time &&
nev.xkey.keycode == keyReleaseEvent.xkey.keycode)
{
// Key wasn't actually released, eat event
XNextEvent(m_display, &nev);
return true;
}
}
return false;
}
SamplePlatform* SampleFramework::createPlatform(SampleRenderer::RendererWindow* _app)
{
printf("Creating linux platform abstraction.\n");
SamplePlatform::setPlatform(new LinuxPlatform(_app));
return SamplePlatform::platform();
}
void* LinuxPlatform::compileProgram(void * context,
const char* assetDir,
const char *programPath,
physx::PxU64 profile,
const char* passString,
const char *entry,
const char **args)
{
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);
return program;
}
static PxI32 errorHandler(Display* d, XErrorEvent* e)
{
printf("Xerror!\n");
return 0;
}
static PxI32 errorHandlerIO(Display* d)
{
printf("X IO error!\n");
return 0;
}
LinuxPlatform::LinuxPlatform(SampleRenderer::RendererWindow* _app)
: SamplePlatform(_app)
, m_display(NULL)
, m_visualInfo(NULL)
, m_hasFocus(false)
, m_hasContentFocus(false)
, m_isFullScreen(false)
, m_screen(0)
, m_mouseCursorPos(0)
, m_recenterMouseCursor(false)
, m_showCursor(true)
{
XInitThreads();
XSetIOErrorHandler(errorHandlerIO);
XSetErrorHandler(errorHandler);
}
void LinuxPlatform::setCWDToEXE(void)
{
char exepath[1024] = {0};
if(getcwd(exepath, 1024))
{
if(chdir(exepath) != 0)
{
printf("LinuxPlatform::setCWDToEXE chdir failed!\n");
}
}
}
void LinuxPlatform::setupRendererDescription(SampleRenderer::RendererDesc& renDesc)
{
renDesc.driver = SampleRenderer::Renderer::DRIVER_OPENGL;
renDesc.windowHandle = 0;
}
void LinuxPlatform::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(windowTitle, " : ");
strcat(windowTitle, SampleRenderer::Renderer::getDriverTypeName(renderer->getDriverType()));
m_app->setTitle(windowTitle);
}
void LinuxPlatform::setMouseCursorRecentering(bool val)
{
if (m_recenterMouseCursor != val)
{
m_recenterMouseCursor = val;
if (m_recenterMouseCursor)
recenterMouseCursor(false);
}
}
bool LinuxPlatform::getMouseCursorRecentering() const
{
return m_recenterMouseCursor;
}
void LinuxPlatform::recenterMouseCursor(bool generateEvent)
{
if (m_recenterMouseCursor && m_hasContentFocus)
{
// returns relative window coordinates, opposed to absolute ones!
// different than on other platforms.
PxI32 x, y, xtmp, ytmp;
PxU32 mtmp;
Window root, child;
XQueryPointer(m_display, m_window, &root, &child, &xtmp, &ytmp, &x, &y, &mtmp);
PxVec2 current(static_cast<PxReal>(x), static_cast<PxReal>(m_windowHeight - y));
PxI32 linuxCenterX = m_windowWidth >> 1;
PxI32 linuxCenterY = m_windowHeight >> 1;
XWarpPointer(m_display, 0, m_window, 0, 0, 0, 0, linuxCenterX, linuxCenterY);
// sync here needed, otherwise the deltas will be (almost) zero
XSync(m_display, false);
if (generateEvent)
{
PxVec2 diff = current - PxVec2(static_cast<PxReal>(linuxCenterX), static_cast<PxReal>(m_windowHeight - linuxCenterY));
getLinuxSampleUserInput().doOnMouseMove(linuxCenterX, m_windowHeight - linuxCenterY, diff.x, diff.y, MOUSE_MOVE);
}
m_mouseCursorPos = current;
}
}
void LinuxPlatform::showCursorInternal(bool show)
{
if(show)
{
XUndefineCursor(m_display, m_window);
}
else
{
Pixmap bm_no;
Colormap cmap;
Cursor no_ptr;
XColor black, dummy;
static char bm_no_data[] = {0, 0, 0, 0, 0, 0, 0, 0};
cmap = DefaultColormap(m_display, DefaultScreen(m_display));
XAllocNamedColor(m_display, cmap, "black", &black, &dummy);
bm_no = XCreateBitmapFromData(m_display, m_window, bm_no_data, 8, 8);
no_ptr = XCreatePixmapCursor(m_display, bm_no, bm_no, &black, &black, 0, 0);
XDefineCursor(m_display, m_window, no_ptr);
XFreeCursor(m_display, no_ptr);
if(bm_no != None)
XFreePixmap(m_display, bm_no);
XFreeColors(m_display, cmap, &black.pixel, 1, 0);
}
}
void LinuxPlatform::showCursor(bool show)
{
if(m_showCursor == show)
return;
m_showCursor = show;
showCursorInternal(show);
}
void LinuxPlatform::doInput()
{
/* do nothing */
}
bool LinuxPlatform::openWindow(physx::PxU32& width, physx::PxU32& height,const char* title, bool fullscreen)
{
Window rootWindow;
GLint attributes[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
Colormap colorMap;
XSetWindowAttributes setWindowAttributes;
XWindowAttributes xWindowAttributes;
XEvent xEvent;
int glxMajor, glxMinor, vmMajor, vmMinor;
XF86VidModeModeInfo** modes;
int modeNum;
int bestMode = 0; // set best mode to current
m_display = XOpenDisplay(NULL);
m_screen = DefaultScreen(m_display);
if(!m_display)
{
printf("Cannot connect to X server!\n");
closeWindow();
return false;
}
XF86VidModeQueryVersion(m_display, &vmMajor, &vmMinor);
printf("XF86 VideoMode extension version %d.%d\n", vmMajor, vmMinor);
glXQueryVersion(m_display, &glxMajor, &glxMinor);
printf("GLX-Version %d.%d\n", glxMajor, glxMinor);
rootWindow = RootWindow(m_display, m_screen);
m_visualInfo = glXChooseVisual(m_display, m_screen, attributes);
if(!m_visualInfo)
{
printf("no appropriate visual found!\n");
closeWindow();
return false;
}
colorMap = XCreateColormap(m_display, rootWindow, m_visualInfo->visual, AllocNone);
setWindowAttributes.colormap = colorMap;
setWindowAttributes.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
m_windowWidth = width;
m_windowHeight = height;
//fullscreen = true;
m_isFullScreen = fullscreen;
int windowFlags = CWColormap | CWEventMask;
if(fullscreen)
{
XF86VidModeGetAllModeLines(m_display, m_screen, &modeNum, &modes);
// save desktop-resolution before switching modes
m_desktopMode = *modes[0];
// look for mode with requested resolution
for (PxU32 i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == width) && (modes[i]->vdisplay == height))
bestMode = i;
}
// switch to fullscreen
XF86VidModeSwitchToMode(m_display, m_screen, modes[bestMode]);
XF86VidModeSetViewPort(m_display, m_screen, 0, 0);
m_windowWidth = modes[bestMode]->hdisplay;
m_windowHeight = modes[bestMode]->vdisplay;
printf("switched to fullscreen resolution %dx%d\n", m_windowWidth, m_windowHeight);
XFree(modes);
setWindowAttributes.override_redirect = True;
windowFlags |= CWBorderPixel | CWOverrideRedirect;
}
m_window = XCreateWindow(m_display, rootWindow, 0, 0, m_windowWidth, m_windowHeight, 0, m_visualInfo->depth, InputOutput, m_visualInfo->visual, windowFlags, &setWindowAttributes);
XMapRaised(m_display, m_window);
XStoreName(m_display, m_window, title);
if(fullscreen)
{
XWarpPointer(m_display, None, m_window, 0, 0, 0, 0, 0, 0);
XGrabKeyboard(m_display, m_window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(m_display, m_window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
}
else
{
m_wmDelete = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
XSetWMProtocols(m_display, m_window, &m_wmDelete, 1);
XMapWindow(m_display, m_window);
}
m_hasContentFocus = true;
m_showCursor = true;
recenterMouseCursor(false);
return true;
}
void LinuxPlatform::initializeOGLDisplay(const SampleRenderer::RendererDesc& desc,
physx::PxU32& width,
physx::PxU32& height)
{
m_glxContext = glXCreateContext(m_display, m_visualInfo, NULL, GL_TRUE);
glXMakeCurrent(m_display, m_window, m_glxContext);
getWindowSize(width, height);
}
void LinuxPlatform::postInitializeOGLDisplay()
{
glewInit();
}
bool LinuxPlatform::closeWindow()
{
if(m_glxContext)
{
glXMakeCurrent(m_display, None, NULL);
glXDestroyContext(m_display, m_glxContext);
m_glxContext = 0;
XDestroyWindow(m_display, m_window);
if(m_isFullScreen)
{
XF86VidModeSwitchToMode(m_display, m_screen, &m_desktopMode);
XF86VidModeSetViewPort(m_display, m_screen, 0, 0);
}
if(m_visualInfo)
XFree(m_visualInfo);
m_visualInfo = NULL;
if(m_display)
XCloseDisplay(m_display);
m_display = NULL;
}
return true;
}
void LinuxPlatform::freeDisplay()
{
}
void LinuxPlatform::getWindowSize(PxU32& width, PxU32& height)
{
if(!m_display)
return;
XWindowAttributes attr;
XGetWindowAttributes(m_display, m_window, &attr);
width = attr.width;
height = attr.height;
}
void LinuxPlatform::setFocus(bool b)
{
m_hasFocus = b;
}
bool LinuxPlatform::hasFocus() const
{
return m_hasContentFocus;
}
void LinuxPlatform::getTitle(char *title, physx::PxU32 maxLength) const
{
if(!m_display)
return;
char* t;
XFetchName(m_display, m_window, &t);
strncpy(title, t, maxLength);
XFree(t);
}
void LinuxPlatform::setTitle(const char *title)
{
// unsafe!
if(m_display && title)
XStoreName(m_display, m_window, title);
}
bool LinuxPlatform::updateWindow()
{
return true;
}
void LinuxPlatform::handleMouseEvent(const XEvent& event)
{
PxU32 x = event.xbutton.x;
PxU32 y = m_windowHeight - event.xbutton.y;
PxVec2 current(static_cast<PxReal>(x), static_cast<PxReal>(y));
setMouseCursorPos(current);
switch (event.type)
{
case ButtonPress:
{
m_linuxSampleUserInput.doOnMouseDown(x, y, event.xbutton.button);
}
break;
case ButtonRelease:
{
m_linuxSampleUserInput.doOnMouseUp(x, y, event.xbutton.button);
}
break;
case MotionNotify:
{
if (!getMouseCursorRecentering())
{
PxVec2 diff = current - getMouseCursorPos();
m_linuxSampleUserInput.doOnMouseMove(x, y, diff.x, diff.y, MOUSE_MOVE);
}
}
break;
}
}
void LinuxPlatform::update()
{
XEvent event;
bool close = false;
if(!m_display || !m_app || !m_app->isOpen())
return;
// handle the events in the queue
while (m_display && !close && m_app->isOpen() && (XPending(m_display) > 0))
{
XNextEvent(m_display, &event);
switch (event.type)
{
case Expose:
if (event.xexpose.count == 0)
{
PxU32 width, height;
getWindowSize(width, height);
m_app->onResize(width, height);
m_windowWidth = width;
m_windowHeight = height;
}
break;
case FocusIn:
m_app->setFocus(true);
break;
case FocusOut:
m_app->setFocus(false);
m_hasContentFocus = false;
break;
case ButtonPress:
// fixes recentering issue: jumping window with first context switch.
if(!m_hasContentFocus)
{
m_hasContentFocus = true;
recenterMouseCursor(false);
}
else
handleMouseEvent(event);
break;
case ButtonRelease:
handleMouseEvent(event);
break;
case MotionNotify:
handleMouseEvent(event);
break;
case KeyPress:
case KeyRelease:
{
// and now some code to filter out the key releases
// which are generated by auto repeat
if(filterKeyRepeat(event))
break;
char keyName;
KeySym keySym;
XLookupString(&event.xkey, &keyName, 1, &keySym, NULL);
bool keyDown = (event.type == KeyPress);
if(keyDown)
m_linuxSampleUserInput.doOnKeyDown(keySym, event.xkey.keycode, keyName);
else
m_linuxSampleUserInput.doOnKeyUp(keySym, event.xkey.keycode, keyName);
}
break;
case ClientMessage:
if((Atom)event.xclient.data.l[0] == m_wmDelete)
close = true;
break;
default:
printf("unhandled event type: %d\n", event.type);
break;
}
}
recenterMouseCursor(true);
if(close)
m_app->close();
}
void LinuxPlatform::swapBuffers()
{
if(m_display)
glXSwapBuffers(m_display, m_window);
}
const char* LinuxPlatform::getPathSeparator()
{
return "/";
}
static bool doesDirectoryExist(const char* path)
{
bool exists = false;
DIR* dir = NULL;
dir = opendir(path);
if(dir)
{
closedir(dir);
exists = true;
}
return exists;
}
bool LinuxPlatform::makeSureDirectoryPathExists(const char* dirPath)
{
bool ok = doesDirectoryExist(dirPath);
if (!ok)
ok = mkdir(dirPath, S_IRWXU|S_IRWXG|S_IRWXO) == 0;
return ok;
}
void LinuxPlatform::showMessage(const char* title, const char* message)
{
printf("%s: %s\n", title, message);
}

View File

@ -0,0 +1,398 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#include <linux/LinuxSampleUserInput.h>
#include <X11/keysym.h>
#include <stdio.h>
static bool gTimeInit=false;
using namespace SampleFramework;
using namespace physx;
LinuxSampleUserInput::LinuxSampleUserInput()
{
// register all user inputs for linux platform
registerUserInput(LINUXKEY_1,"KEY_1", "1");
registerUserInput(LINUXKEY_2,"KEY_2", "2");
registerUserInput(LINUXKEY_3,"KEY_3", "3");
registerUserInput(LINUXKEY_4,"KEY_4", "4");
registerUserInput(LINUXKEY_5,"KEY_5", "5");
registerUserInput(LINUXKEY_6,"KEY_6", "6");
registerUserInput(LINUXKEY_7,"KEY_7", "7");
registerUserInput(LINUXKEY_8,"KEY_8", "8");
registerUserInput(LINUXKEY_9,"KEY_9", "9");
registerUserInput(LINUXKEY_0,"KEY_0", "0");
registerUserInput(LINUXKEY_A,"KEY_A", "A");
registerUserInput(LINUXKEY_B,"KEY_B", "B");
registerUserInput(LINUXKEY_C,"KEY_C", "C");
registerUserInput(LINUXKEY_D,"KEY_D", "D");
registerUserInput(LINUXKEY_E,"KEY_E", "E");
registerUserInput(LINUXKEY_F,"KEY_F", "F");
registerUserInput(LINUXKEY_G,"KEY_G", "G");
registerUserInput(LINUXKEY_H,"KEY_H", "H");
registerUserInput(LINUXKEY_I,"KEY_I", "I");
registerUserInput(LINUXKEY_J,"KEY_J", "J");
registerUserInput(LINUXKEY_K,"KEY_K", "K");
registerUserInput(LINUXKEY_L,"KEY_L", "L");
registerUserInput(LINUXKEY_M,"KEY_M", "M");
registerUserInput(LINUXKEY_N,"KEY_N", "N");
registerUserInput(LINUXKEY_O,"KEY_O", "O");
registerUserInput(LINUXKEY_P,"KEY_P", "P");
registerUserInput(LINUXKEY_Q,"KEY_Q", "Q");
registerUserInput(LINUXKEY_R,"KEY_R", "R");
registerUserInput(LINUXKEY_S,"KEY_S", "S");
registerUserInput(LINUXKEY_T,"KEY_T", "T");
registerUserInput(LINUXKEY_U,"KEY_U", "U");
registerUserInput(LINUXKEY_V,"KEY_V", "V");
registerUserInput(LINUXKEY_W,"KEY_W", "W");
registerUserInput(LINUXKEY_X,"KEY_X", "X");
registerUserInput(LINUXKEY_Y,"KEY_Y", "Y");
registerUserInput(LINUXKEY_Z,"KEY_Z", "Z");
registerUserInput(LINUXKEY_SPACE ,"KEY_SPACE","Space");
registerUserInput(LINUXKEY_RETURN ,"KEY_RETURN","Enter");
registerUserInput(LINUXKEY_SHIFT ,"KEY_SHIFT","Shift");
registerUserInput(LINUXKEY_CONTROL ,"KEY_CONTROL","Control");
registerUserInput(LINUXKEY_ESCAPE ,"KEY_ESCAPE","Escape");
registerUserInput(LINUXKEY_COMMA ,"KEY_COMMA",",");
registerUserInput(LINUXKEY_NUMPAD0 ,"KEY_NUMPAD0","Numpad0");
registerUserInput(LINUXKEY_NUMPAD1 ,"KEY_NUMPAD1","Numpad1");
registerUserInput(LINUXKEY_NUMPAD2 ,"KEY_NUMPAD2","Numpad2");
registerUserInput(LINUXKEY_NUMPAD3 ,"KEY_NUMPAD3","Numpad3");
registerUserInput(LINUXKEY_NUMPAD4 ,"KEY_NUMPAD4","Numpad4");
registerUserInput(LINUXKEY_NUMPAD5 ,"KEY_NUMPAD5","Numpad5");
registerUserInput(LINUXKEY_NUMPAD6 ,"KEY_NUMPAD6","Numpad6");
registerUserInput(LINUXKEY_NUMPAD7 ,"KEY_NUMPAD7","Numpad7");
registerUserInput(LINUXKEY_NUMPAD8 ,"KEY_NUMPAD8","Numpad8");
registerUserInput(LINUXKEY_NUMPAD9 ,"KEY_NUMPAD9","Numpad9");
registerUserInput(LINUXKEY_ADD ,"KEY_ADD","+");
registerUserInput(LINUXKEY_SUBTRACT ,"KEY_SUBTRACT","-");
registerUserInput(LINUXKEY_COMMA ,"KEY_COMMM",", on keypad");
registerUserInput(LINUXKEY_DIVIDE ,"KEY_DIVIDE","/");
registerUserInput(LINUXKEY_F1 ,"KEY_F1","F1");
registerUserInput(LINUXKEY_F2 ,"KEY_F2","F2");
registerUserInput(LINUXKEY_F3 ,"KEY_F3","F3");
registerUserInput(LINUXKEY_F4 ,"KEY_F4","F4");
registerUserInput(LINUXKEY_F5 ,"KEY_F5","F5");
registerUserInput(LINUXKEY_F6 ,"KEY_F6","F6");
registerUserInput(LINUXKEY_F7 ,"KEY_F7","F7");
registerUserInput(LINUXKEY_F8 ,"KEY_F8","F8");
registerUserInput(LINUXKEY_F9 ,"KEY_F9","F9");
registerUserInput(LINUXKEY_F10 ,"KEY_F10","F10");
registerUserInput(LINUXKEY_F11 ,"KEY_F11","F11");
registerUserInput(LINUXKEY_F12 ,"KEY_F12","F12");
registerUserInput(LINUXKEY_TAB ,"KEY_TAB","Tab");
registerUserInput(LINUXKEY_BACKSPACE ,"KEY_BACKSPACE","Backspace");
registerUserInput(LINUXKEY_PRIOR ,"KEY_PRIOR","PgUp");
registerUserInput(LINUXKEY_NEXT ,"KEY_NEXT","PgDn");
registerUserInput(LINUXKEY_UP ,"KEY_UP","Up Arrow");
registerUserInput(LINUXKEY_DOWN ,"KEY_DOWN","Down Arrow");
registerUserInput(LINUXKEY_LEFT ,"KEY_LEFT","Left Arrow");
registerUserInput(LINUXKEY_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");
// scan codes
registerScanCode(SCAN_CODE_UP, 26, LINUXKEY_E, "SCAN_CODE_E");
registerScanCode(SCAN_CODE_DOWN, 54, LINUXKEY_C, "SCAN_CODE_C");
registerScanCode(SCAN_CODE_LEFT, 38, LINUXKEY_A, "SCAN_CODE_A");
registerScanCode(SCAN_CODE_RIGHT, 40, LINUXKEY_D, "SCAN_CODE_D");
registerScanCode(SCAN_CODE_FORWARD, 25, LINUXKEY_W, "SCAN_CODE_W");
registerScanCode(SCAN_CODE_BACKWARD, 39, LINUXKEY_S, "SCAN_CODE_S");
registerScanCode(SCAN_CODE_L, 46, LINUXKEY_L, "SCAN_CODE_L");
registerScanCode(SCAN_CODE_9, 18, LINUXKEY_9, "SCAN_CODE_9");
registerScanCode(SCAN_CODE_0, 19, LINUXKEY_0, "SCAN_CODE_0");
}
void LinuxSampleUserInput::registerScanCode(LinuxSampleUserInputIds scanCodeId, physx::PxU16 scanCode, LinuxSampleUserInputIds nameId, const char* name)
{
const UserInput* ui = getUserInputFromId(nameId);
if(ui)
{
registerUserInput(scanCodeId, name, ui->m_Name);
m_ScanCodesMap[scanCode] = scanCodeId;
}
}
const UserInput* LinuxSampleUserInput::getUserInputFromId(LinuxSampleUserInputIds id) const
{
for (size_t i = mUserInputs.size(); i--;)
{
if(mUserInputs[i].m_Id == id)
{
return &mUserInputs[i];
}
}
return NULL;
}
LinuxSampleUserInput::~LinuxSampleUserInput()
{
m_ScanCodesMap.clear();
m_AnalogStates.clear();
m_DigitalStates.clear();
}
LinuxSampleUserInputIds LinuxSampleUserInput::getInputIdFromMouseButton(const physx::PxU16 b) const
{
if (b == Button1) return MOUSE_BUTTON_LEFT;
else if (b == Button2) return MOUSE_BUTTON_CENTER;
else if (b == Button3) return MOUSE_BUTTON_RIGHT;
else return LINUXKEY_UNKNOWN;
}
LinuxSampleUserInputIds LinuxSampleUserInput::getInputIdFromKeySym(const KeySym keySym) const
{
LinuxSampleUserInputIds id = LINUXKEY_UNKNOWN;
if(keySym >= XK_A && keySym <= XK_Z) id = (LinuxSampleUserInputIds)((keySym - XK_A)+LINUXKEY_A);
else if(keySym >= XK_a && keySym <= XK_z) id = (LinuxSampleUserInputIds)((keySym - XK_a)+LINUXKEY_A);
else if(keySym >= XK_0 && keySym <= XK_9) id = (LinuxSampleUserInputIds)((keySym - XK_0)+LINUXKEY_0);
else if(keySym >= XK_KP_0 && keySym <= XK_KP_9) id = (LinuxSampleUserInputIds)((keySym - XK_KP_0)+LINUXKEY_NUMPAD0);
else if(keySym == XK_Shift_L || keySym == XK_Shift_R) id = LINUXKEY_SHIFT;
else if(keySym == XK_Control_L || keySym == XK_Control_R) id = LINUXKEY_CONTROL;
else if(keySym == XK_space) id = LINUXKEY_SPACE;
else if(keySym == XK_Return) id = LINUXKEY_RETURN;
else if(keySym == XK_Escape) id = LINUXKEY_ESCAPE;
else if(keySym == XK_KP_Separator) id = LINUXKEY_COMMA;
else if(keySym == XK_KP_Divide) id = LINUXKEY_DIVIDE;
else if(keySym == XK_KP_Subtract) id = LINUXKEY_SUBTRACT;
else if(keySym == XK_KP_Add) id = LINUXKEY_ADD;
//
else if(keySym == XK_F1) id = LINUXKEY_F1;
else if(keySym == XK_F2) id = LINUXKEY_F2;
else if(keySym == XK_F3) id = LINUXKEY_F3;
else if(keySym == XK_F4) id = LINUXKEY_F4;
else if(keySym == XK_F5) id = LINUXKEY_F5;
else if(keySym == XK_F6) id = LINUXKEY_F6;
else if(keySym == XK_F7) id = LINUXKEY_F7;
else if(keySym == XK_F8) id = LINUXKEY_F8;
else if(keySym == XK_F9) id = LINUXKEY_F9;
else if(keySym == XK_F10) id = LINUXKEY_F10;
else if(keySym == XK_F11) id = LINUXKEY_F11;
else if(keySym == XK_F12) id = LINUXKEY_F12;
//
else if(keySym == XK_Tab) id = LINUXKEY_TAB;
//
else if(keySym == XK_BackSpace) id = LINUXKEY_BACKSPACE;
else if(keySym == XK_Prior) id = LINUXKEY_PRIOR;
else if(keySym == XK_Next) id = LINUXKEY_NEXT;
//
else if(keySym == XK_Up) id = LINUXKEY_UP;
else if(keySym == XK_Down) id = LINUXKEY_DOWN;
else if(keySym == XK_Left) id = LINUXKEY_LEFT;
else if(keySym == XK_Right) id = LINUXKEY_RIGHT;
return id;
}
void LinuxSampleUserInput::doOnMouseMove(physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, physx::PxU16 button)
{
const std::vector<size_t>* events = getInputEvents(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 LinuxSampleUserInput::doOnMouseDown(physx::PxU32 x, physx::PxU32 y, physx::PxU16 button)
{
const std::vector<size_t>* events = getInputEvents(getInputIdFromMouseButton(button));
if(events)
{
for (size_t i = events->size(); i--;)
{
const InputEvent& ie = mInputEvents[(*events)[i]];
m_DigitalStates[ie.m_Id] = true;
if(getInputEventListener())
{
getInputEventListener()->onPointerInputEvent(ie, x, y, 0, 0, true);
}
}
}
}
void LinuxSampleUserInput::doOnMouseUp(physx::PxU32 x, physx::PxU32 y, physx::PxU16 button)
{
const std::vector<size_t>* events = getInputEvents(getInputIdFromMouseButton(button));
if(events)
{
for (size_t i = events->size(); i--;)
{
const InputEvent& ie = mInputEvents[(*events)[i]];
m_DigitalStates[ie.m_Id] = false;
if(getInputEventListener())
{
getInputEventListener()->onPointerInputEvent(ie, x, y, 0, 0, false);
}
}
}
}
void LinuxSampleUserInput::doOnKeyDown(KeySym keySym, physx::PxU16 keyCode, physx::PxU8 ascii)
{
const std::vector<size_t>* events = NULL;
if(getInputEventListener())
{
//raw ASCII printable characters get sent to the console
if (ascii >= 'a' && ascii <= 'z')
{
getInputEventListener()->onKeyDownEx(static_cast<KeyCode>(ascii - 'a' + KEY_A), ascii);
}
else if (ascii >= 'A' && ascii <= 'Z')
{
getInputEventListener()->onKeyDownEx(static_cast<KeyCode>(ascii - 'A' + KEY_A), ascii);
}
else if (ascii >= '0' && ascii <= '9')
{
getInputEventListener()->onKeyDownEx(static_cast<KeyCode>(ascii - 'A' + KEY_A), ascii);
}
else if (ascii == ' ')
{
getInputEventListener()->onKeyDownEx(static_cast<KeyCode>(ascii - ' ' + KEY_SPACE), ascii);
}
else if (ascii == '.')
{
getInputEventListener()->onKeyDownEx(static_cast<KeyCode>(ascii - '.' + KEY_DECIMAL), ascii);
}
std::map<physx::PxU16, physx::PxU16>::iterator fit = m_ScanCodesMap.find(keyCode);
if(fit != m_ScanCodesMap.end())
{
events = getInputEvents(fit->second);
}
if(!events)
{
LinuxSampleUserInputIds id = getInputIdFromKeySym(keySym);
events = getInputEvents(id);
}
if(!events || !getInputEventListener())
return;
for (size_t i = events->size(); i--;)
{
const InputEvent& ie = mInputEvents[(*events)[i]];
m_DigitalStates[ie.m_Id] = true;
getInputEventListener()->onDigitalInputEvent(ie, true);
}
}
}
void LinuxSampleUserInput::doOnKeyUp( KeySym keySym, physx::PxU16 keyCode, physx::PxU8 ascii)
{
const std::vector<size_t>* events = NULL;
std::map<physx::PxU16, physx::PxU16>::iterator fit = m_ScanCodesMap.find(keyCode);
if(fit != m_ScanCodesMap.end())
{
events = getInputEvents(fit->second);
}
if(!events)
{
LinuxSampleUserInputIds id = getInputIdFromKeySym(keySym);
events = getInputEvents(id);
}
if(!events || !getInputEventListener())
return;
for (size_t i = events->size(); i--;)
{
const InputEvent& ie = mInputEvents[(*events)[i]];
m_DigitalStates[ie.m_Id] = false;
getInputEventListener()->onDigitalInputEvent(ie, false);
}
}
bool LinuxSampleUserInput::getDigitalInputEventState(physx::PxU16 inputEventId ) const
{
std::map<physx::PxU16,bool>::const_iterator fit = m_DigitalStates.find(inputEventId);
if(fit != m_DigitalStates.end())
{
return fit->second;
}
else
{
return false;
}
}
float LinuxSampleUserInput::getAnalogInputEventState(physx::PxU16 inputEventId ) const
{
std::map<physx::PxU16,float>::const_iterator fit = m_AnalogStates.find(inputEventId);
if(fit != m_AnalogStates.end())
{
return fit->second;
}
else
{
return 0.0f;
}
}
void LinuxSampleUserInput::shutdown()
{
m_AnalogStates.clear();
m_DigitalStates.clear();
SampleUserInput::shutdown();
}
void LinuxSampleUserInput::updateInput()
{
SampleUserInput::updateInput();
processGamepads();
}