diff --git a/ChangeLog b/ChangeLog
index 1896fad6f0..dbf386cbad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@
BZFlag 2.4.27
-------------
+* Improved joystick support - Joshua Bodine
* Cleaned up and updated the Xcode project file - Joshua Bodine
* Fixed yet another SDL2 window management regression on macOS - Joshua Bodine
* Remove non-SDL2 platform code and add SDL2 controller rumble support
diff --git a/MSVC/build/bzflag.vcxproj b/MSVC/build/bzflag.vcxproj
index d430a3cc2b..a26d646af6 100644
--- a/MSVC/build/bzflag.vcxproj
+++ b/MSVC/build/bzflag.vcxproj
@@ -335,6 +335,8 @@ copy "$(BZ_DEPS)\licenses\*" "..\..\bin_$(Configuration)_$(Platform)\licenses\"<
+
+
@@ -939,12 +941,14 @@ copy "$(BZ_DEPS)\licenses\*" "..\..\bin_$(Configuration)_$(Platform)\licenses\"<
+
+
diff --git a/MSVC/build/bzflag.vcxproj.filters b/MSVC/build/bzflag.vcxproj.filters
index d9baef2184..a06801f43c 100644
--- a/MSVC/build/bzflag.vcxproj.filters
+++ b/MSVC/build/bzflag.vcxproj.filters
@@ -265,6 +265,12 @@
Header Files
+
+ Source Files
+
+
+ Source Files
+
@@ -531,6 +537,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
diff --git a/Xcode/BZFlag.xcodeproj/project.pbxproj b/Xcode/BZFlag.xcodeproj/project.pbxproj
index 6cb7689536..9077b62707 100644
--- a/Xcode/BZFlag.xcodeproj/project.pbxproj
+++ b/Xcode/BZFlag.xcodeproj/project.pbxproj
@@ -410,6 +410,8 @@
0394E966167B2D00007F4035 /* wwzones.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0394E93D167B2A9E007F4035 /* wwzones.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
0397B73B1BC1D639001C04D2 /* CustomZoneSample.bzw in Resources */ = {isa = PBXBuildFile; fileRef = C353B1E81AE2489900C5AED5 /* CustomZoneSample.bzw */; };
0397B73C1BC1E72B001C04D2 /* flagStay.bzw in Resources */ = {isa = PBXBuildFile; fileRef = C353B1E91AE2490D00C5AED5 /* flagStay.bzw */; };
+ 03AD0A172481A06E00207E3E /* JoystickTestMenu.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 03AD0A162481A06E00207E3E /* JoystickTestMenu.cxx */; };
+ 03AD0A1A2481B2D600207E3E /* HUDuiJSTestLabel.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 03AD0A192481B2D600207E3E /* HUDuiJSTestLabel.cxx */; };
03C5E82B1670A98C005A26C4 /* FontManager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 035542FD166C846F008806E9 /* FontManager.cxx */; };
03C5E82C1670A98C005A26C4 /* ImageFont.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 035542FE166C846F008806E9 /* ImageFont.cxx */; };
03C5E82D1670A98C005A26C4 /* TextureFont.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 03554302166C846F008806E9 /* TextureFont.cxx */; };
@@ -1775,6 +1777,10 @@
0394E93D167B2A9E007F4035 /* wwzones.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = wwzones.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
039708A11DD7991D00C9215C /* SDLMain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLMain.h; sourceTree = ""; };
039708A21DD7991D00C9215C /* SDLMain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLMain.m; sourceTree = ""; };
+ 03AD0A152481A06E00207E3E /* JoystickTestMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JoystickTestMenu.h; sourceTree = ""; };
+ 03AD0A162481A06E00207E3E /* JoystickTestMenu.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JoystickTestMenu.cxx; sourceTree = ""; };
+ 03AD0A182481B2D500207E3E /* HUDuiJSTestLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HUDuiJSTestLabel.h; sourceTree = ""; };
+ 03AD0A192481B2D600207E3E /* HUDuiJSTestLabel.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HUDuiJSTestLabel.cxx; sourceTree = ""; };
03C338C71AFB5AFC00E8F655 /* SDL2Display.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDL2Display.cxx; sourceTree = ""; };
03C338C81AFB5AFC00E8F655 /* SDL2Display.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL2Display.h; sourceTree = ""; };
03C338C91AFB5AFC00E8F655 /* SDL2Visual.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDL2Visual.cxx; sourceTree = ""; };
@@ -2529,6 +2535,8 @@
0355435A166C846F008806E9 /* HUDuiControl.h */,
0355435B166C846F008806E9 /* HUDuiDefaultKey.cxx */,
0355435C166C846F008806E9 /* HUDuiDefaultKey.h */,
+ 03AD0A192481B2D600207E3E /* HUDuiJSTestLabel.cxx */,
+ 03AD0A182481B2D500207E3E /* HUDuiJSTestLabel.h */,
0355435D166C846F008806E9 /* HUDuiLabel.cxx */,
0355435E166C846F008806E9 /* HUDuiLabel.h */,
0355435F166C846F008806E9 /* HUDuiList.cxx */,
@@ -2541,6 +2549,8 @@
03554366166C846F008806E9 /* InputMenu.h */,
03554367166C846F008806E9 /* JoinMenu.cxx */,
03554368166C846F008806E9 /* JoinMenu.h */,
+ 03AD0A162481A06E00207E3E /* JoystickTestMenu.cxx */,
+ 03AD0A152481A06E00207E3E /* JoystickTestMenu.h */,
03554369166C846F008806E9 /* KeyboardMapMenu.cxx */,
0355436A166C846F008806E9 /* KeyboardMapMenu.h */,
0355436B166C846F008806E9 /* LocalCommand.cxx */,
@@ -5571,6 +5581,7 @@
03C8EE6F167AC26A00BB07A5 /* callbacks.cxx in Sources */,
03C8EE71167AC26A00BB07A5 /* clientCommands.cxx in Sources */,
03C8EE72167AC26A00BB07A5 /* clientConfig.cxx in Sources */,
+ 03AD0A1A2481B2D600207E3E /* HUDuiJSTestLabel.cxx in Sources */,
03C8EE75167AC26A00BB07A5 /* CommandsImplementation.cxx in Sources */,
03C8EE76167AC26A00BB07A5 /* ComposeDefaultKey.cxx in Sources */,
03C8EE78167AC26A00BB07A5 /* ControlPanel.cxx in Sources */,
@@ -5647,6 +5658,7 @@
03C8EF01167AC26A00BB07A5 /* TrackMarks.cxx in Sources */,
03C8EF03167AC26A00BB07A5 /* Weapon.cxx in Sources */,
03C8EF05167AC26A00BB07A5 /* WeatherRenderer.cxx in Sources */,
+ 03AD0A172481A06E00207E3E /* JoystickTestMenu.cxx in Sources */,
03C8EF07167AC26A00BB07A5 /* World.cxx in Sources */,
03C8EF09167AC26A00BB07A5 /* WorldBuilder.cxx in Sources */,
03C8EF0B167AC26A00BB07A5 /* WorldPlayer.cxx in Sources */,
diff --git a/include/BzfJoystick.h b/include/BzfJoystick.h
index ab29e540cd..91c3ae869a 100644
--- a/include/BzfJoystick.h
+++ b/include/BzfJoystick.h
@@ -29,7 +29,7 @@ class BzfJoystick
virtual void initJoystick(const char* joystickName);
virtual bool joystick() const;
- virtual void getJoy(int& x, int& y);
+ virtual void getJoy(float& x, float& y);
virtual int getNumHats();
virtual void getJoyHat(int hat, float &hatX, float &hatY);
virtual unsigned long getJoyButtons();
diff --git a/src/bzflag/HUDuiJSTestLabel.cxx b/src/bzflag/HUDuiJSTestLabel.cxx
new file mode 100644
index 0000000000..b64a5dfb0e
--- /dev/null
+++ b/src/bzflag/HUDuiJSTestLabel.cxx
@@ -0,0 +1,107 @@
+/* bzflag
+ * Copyright (c) 1993-2020 Tim Riker
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the license found in the file
+ * named COPYING that should have accompanied this file.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+// interface headers
+#include "HUDuiJSTestLabel.h"
+
+// system headers
+#include
+
+// common implementation headers
+#include "TextureManager.h"
+#include "OpenGLTexture.h"
+#include "playing.h"
+
+//
+// HUDuiJSTestLabel
+//
+
+HUDuiJSTestLabel::HUDuiJSTestLabel() : HUDuiLabel(), width(0), height(0)
+{
+ OpenGLGStateBuilder builder(gstate);
+ builder.setBlending();
+ builder.enableTexture(false);
+ gstate = builder.getState();
+}
+
+void HUDuiJSTestLabel::setSize(float newWidth, float newHeight)
+{
+ width = newWidth;
+ height = newHeight;
+}
+
+void HUDuiJSTestLabel::doRender()
+{
+ gstate.setState();
+
+ // scale elements from a relative screen height of 800 pixels
+#define BZ_SCALE_JS_TEST_ELEMS(x) std::ceil(float(x) * height / 800.0f)
+
+ // appearance constants
+ const float backgroundColor[] = { 0.0f, 0.0f, 0.0f, 0.75f };
+
+ const auto realCursorThickness = BZ_SCALE_JS_TEST_ELEMS(2);
+ const auto realCursorLength = BZ_SCALE_JS_TEST_ELEMS(40.0f);
+ const float realCursorColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+ const auto modifiedCursorLength = BZ_SCALE_JS_TEST_ELEMS(20.0f);
+ const float modifiedCursorColor[] = { 0.5f, 0.5f, 0.5f, 1.0f };
+
+ // draw the background
+ const auto rangeLimit = float(BZDB.evalInt("jsRangeMax")) / 100.0f;
+ glColor4fv(backgroundColor);
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex2f(getX() + (1.0f - rangeLimit) / 2.0f * width, getY() + (1.0f + rangeLimit) / 2.0f * height);
+ glVertex2f(getX() + (1.0f - rangeLimit) / 2.0f * width, getY() + (1.0f - rangeLimit) / 2.0f * height);
+ glVertex2f(getX() + (1.0f + rangeLimit) / 2.0f * width, getY() + (1.0f - rangeLimit) / 2.0f * height);
+ glVertex2f(getX() + (1.0f + rangeLimit) / 2.0f * width, getY() + (1.0f + rangeLimit) / 2.0f * height);
+ glEnd();
+
+ // draw the real cursor
+ float jsx, jsy;
+ mainWindow->getJoyPosition(jsx, jsy);
+ jsx *= BZDB.evalInt("jsInvertAxes") % 2 == 1 ? -1.0f : 1.0f; // invert axes as required
+ jsy *= BZDB.evalInt("jsInvertAxes") > 1 ? -1.0f : 1.0f;
+ auto jsxTransformed = ((1.0f + jsx) / 2.0f) * width;
+ auto jsyTransformed = ((1.0f - jsy) / 2.0f) * height;
+ glPushAttrib(GL_LINE_BIT);
+ glLineWidth(realCursorThickness);
+ glColor4fv(realCursorColor);
+ glBegin(GL_LINES);
+ glVertex2f(getX() + jsxTransformed - realCursorLength / 2.0f, getY() + jsyTransformed);
+ glVertex2f(getX() + jsxTransformed + realCursorLength / 2.0f, getY() + jsyTransformed);
+ glVertex2f(getX() + jsxTransformed, getY() + jsyTransformed - realCursorLength / 2.0f);
+ glVertex2f(getX() + jsxTransformed, getY() + jsyTransformed + realCursorLength / 2.0f);
+ glEnd();
+ glPopAttrib();
+
+ // draw the modified cursor
+ mainWindow->getJoyPosition(jsx, jsy);
+ applyJSModifiers(jsx, jsy);
+ jsxTransformed = ((1.0f + jsx) / 2.0f) * width;
+ jsyTransformed = ((1.0f - jsy) / 2.0f) * height;
+ glColor4fv(modifiedCursorColor);
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex2f(getX() + jsxTransformed, getY() + jsyTransformed - modifiedCursorLength / 2.0f);
+ glVertex2f(getX() + jsxTransformed + modifiedCursorLength / 2.0f, getY() + jsyTransformed);
+ glVertex2f(getX() + jsxTransformed, getY() + jsyTransformed + modifiedCursorLength / 2.0f);
+ glVertex2f(getX() + jsxTransformed - modifiedCursorLength / 2.0f, getY() + jsyTransformed);
+ glEnd();
+}
+
+// Local Variables: ***
+// mode: C++ ***
+// tab-width: 4 ***
+// c-basic-offset: 4 ***
+// indent-tabs-mode: nil ***
+// End: ***
+// ex: shiftwidth=4 tabstop=4
diff --git a/src/bzflag/HUDuiJSTestLabel.h b/src/bzflag/HUDuiJSTestLabel.h
new file mode 100644
index 0000000000..45fbb8ed22
--- /dev/null
+++ b/src/bzflag/HUDuiJSTestLabel.h
@@ -0,0 +1,48 @@
+/* bzflag
+ * Copyright (c) 1993-2020 Tim Riker
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the license found in the file
+ * named COPYING that should have accompanied this file.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * HUDuiJSTestLabel:
+ * User interface classes and functions for the joystick range test
+ */
+
+#ifndef __HUDUIJSTESTLABEL_H__
+#define __HUDUIJSTESTLABEL_H__
+
+#include "HUDuiLabel.h"
+#include "OpenGLGState.h"
+
+class HUDuiJSTestLabel : public HUDuiLabel
+{
+public:
+ HUDuiJSTestLabel();
+ ~HUDuiJSTestLabel() { };
+
+ void setSize(float newWidth, float newHeight);
+
+protected:
+ void doRender();
+
+private:
+ float width, height;
+ OpenGLGState gstate;
+};
+
+#endif // __HUDUIJSTESTLABEL_H__
+
+// Local Variables: ***
+// mode: C++ ***
+// tab-width: 4 ***
+// c-basic-offset: 4 ***
+// indent-tabs-mode: nil ***
+// End: ***
+// ex: shiftwidth=4 tabstop=4
diff --git a/src/bzflag/InputMenu.cxx b/src/bzflag/InputMenu.cxx
index 35d236def7..1e3afaa7ab 100644
--- a/src/bzflag/InputMenu.cxx
+++ b/src/bzflag/InputMenu.cxx
@@ -24,7 +24,7 @@
#include "playing.h"
#include "HUDui.h"
-InputMenu::InputMenu() : keyboardMapMenu(NULL)
+InputMenu::InputMenu() : keyboardMapMenu(nullptr), joystickTestMenu(nullptr)
{
std::string currentJoystickDevice = BZDB.get("joystickname");
// cache font face ID
@@ -43,12 +43,13 @@ InputMenu::InputMenu() : keyboardMapMenu(NULL)
listHUD.push_back(keyMapping);
HUDuiList* option;
+ std::vector* options;
activeInput = new HUDuiList;
activeInput->setFontFace(fontFace);
activeInput->setLabel("Active input device:");
activeInput->setCallback(callback, "A");
- std::vector* options = &activeInput->getList();
+ options = &activeInput->getList();
options->push_back("Auto");
options->push_back(LocalPlayer::getInputMethodName(LocalPlayer::Keyboard));
options->push_back(LocalPlayer::getInputMethodName(LocalPlayer::Mouse));
@@ -57,10 +58,9 @@ InputMenu::InputMenu() : keyboardMapMenu(NULL)
listHUD.push_back(activeInput);
option = new HUDuiList;
- options = &option->getList();
// set joystick Device
option->setFontFace(fontFace);
- option->setLabel("Joystick device:");
+ option->setLabel("Joystick Device:");
option->setCallback(callback, "J");
options = &option->getList();
options->push_back(std::string("Off"));
@@ -72,7 +72,7 @@ InputMenu::InputMenu() : keyboardMapMenu(NULL)
joystickDevices.erase(joystickDevices.begin(), joystickDevices.end());
for (i = 0; i < (int)options->size(); i++)
{
- if ((*options)[i].compare(currentJoystickDevice) == 0)
+ if ((*options)[i].compare(0, 1, currentJoystickDevice, 0, 1) == 0)
{
option->setIndex(i);
break;
@@ -81,18 +81,6 @@ InputMenu::InputMenu() : keyboardMapMenu(NULL)
option->update();
listHUD.push_back(option);
- option = new HUDuiList;
- // force feedback
- option->setFontFace(fontFace);
- option->setLabel("Rumble:");
- option->setCallback(callback, "F");
- options = &option->getList();
- options->push_back(std::string("Off"));
- options->push_back(std::string("On"));
- option->setIndex(BZDB.isTrue("rumble") ? 1 : 0);
- option->update();
- listHUD.push_back(option);
-
option = new HUDuiList;
// axis settings
jsx = option;
@@ -107,18 +95,93 @@ InputMenu::InputMenu() : keyboardMapMenu(NULL)
option->setCallback(callback, "Y");
listHUD.push_back(option);
fillJSOptions();
+
+ option = new HUDuiList;
+ // joystick range settings
+ option->setFontFace(fontFace);
+ option->setLabel("Joystick Range Limit:");
+ option->setCallback(callback, "T");
+ options = &option->getList();
+ char percentText[5];
+ for(i = 25; i <= 100; ++i)
+ {
+ snprintf(percentText, 5, "%i%%", i);
+ options->push_back(percentText);
+ }
+ for (i = 0; i < (int)options->size(); i++)
+ {
+ std::string currentOption = (*options)[i];
+ if (BZDB.get("jsRangeMax") + "%" == currentOption)
+ option->setIndex(i);
+ }
+ option->update();
+ listHUD.push_back(option);
+ option = new HUDuiList;
+ option->setFontFace(fontFace);
+ option->setLabel("Joystick Dead Zone:");
+ option->setCallback(callback, "B");
+ options = &option->getList();
+ for(i = 0; i <= 20; ++i)
+ {
+ snprintf(percentText, 5, "%i%%", i);
+ options->push_back(percentText);
+ }
+ for (i = 0; i < (int)options->size(); i++)
+ {
+ std::string currentOption = (*options)[i];
+ if (BZDB.get("jsRangeMin") + "%" == currentOption)
+ option->setIndex(i);
+ }
+ option->update();
+ listHUD.push_back(option);
option = new HUDuiList;
option->setFontFace(fontFace);
- option->setLabel("Invert Joystick Axes:");
- option->setCallback(callback, "I");
+ option->setLabel("Stretch Joystick Range Corners:");
+ option->setCallback(callback, "S");
options = &option->getList();
options->push_back(std::string("No"));
- options->push_back(std::string("X"));
- options->push_back(std::string("Y"));
- options->push_back(std::string("X and Y"));
- option->setIndex(BZDB.evalInt("jsInvertAxes"));
+ options->push_back(std::string("Yes"));
+ option->setIndex(BZDB.isTrue("jsStretchCorners") ? 1 : 0);
+ option->update();
+ listHUD.push_back(option);
+ option = new HUDuiList;
+ option->setFontFace(fontFace);
+ option->setLabel("Joystick Ramp Type:");
+ option->setCallback(callback, "R");
+ options = &option->getList();
+ options->push_back(std::string("Linear"));
+ options->push_back(std::string("Exponential (Squared)"));
+ options->push_back(std::string("Exponential (Cubed)"));
+ if(BZDB.get("jsRampType") == "squared")
+ option->setIndex(1);
+ else if(BZDB.get("jsRampType") == "cubed")
+ option->setIndex(2);
+ else
+ option->setIndex(0);
+ option->update();
+ listHUD.push_back(option);
+
+ option = new HUDuiList;
+ // force feedback
+ option->setFontFace(fontFace);
+ option->setLabel("Force Feedback:");
+ option->setCallback(callback, "F");
+ options = &option->getList();
+ options->push_back(std::string("None"));
+ options->push_back(std::string("Rumble"));
+ options->push_back(std::string("Directional"));
+ for (i = 0; i < (int)options->size(); i++)
+ {
+ std::string currentOption = (*options)[i];
+ if (BZDB.get("forceFeedback") == currentOption)
+ option->setIndex(i);
+ }
option->update();
listHUD.push_back(option);
+ joystickTest = new HUDuiLabel;
+ joystickTest->setFontFace(fontFace);
+ joystickTest->setLabel("Test Joystick Range");
+ listHUD.push_back(joystickTest);
option = new HUDuiList;
// confine mouse
@@ -165,6 +228,7 @@ InputMenu::InputMenu() : keyboardMapMenu(NULL)
InputMenu::~InputMenu()
{
delete keyboardMapMenu;
+ delete joystickTestMenu;
}
void InputMenu::fillJSOptions()
@@ -173,38 +237,63 @@ void InputMenu::fillJSOptions()
std::vector* yoptions = &jsy->getList();
std::vector joystickAxes;
getMainWindow()->getJoyDeviceAxes(joystickAxes);
- if (joystickAxes.empty())
+ const auto xAxisInverted = BZDB.evalInt("jsInvertAxes") % 2 == 1;
+ const auto yAxisInverted = BZDB.evalInt("jsInvertAxes") > 1;
+
+ xoptions->clear();
+ yoptions->clear();
+
+ if(joystickAxes.empty())
joystickAxes.push_back("N/A");
int i;
for (i = 0; i < (int)joystickAxes.size(); i++)
{
xoptions->push_back(joystickAxes[i]);
yoptions->push_back(joystickAxes[i]);
+ if(joystickAxes[i] != "N/A")
+ {
+ xoptions->push_back(joystickAxes[i] + " (Inverted)");
+ yoptions->push_back(joystickAxes[i] + " (Inverted)");
+ }
}
bool found = false;
for (i = 0; i < (int)xoptions->size(); i++)
{
+ bool currentOptionInverted = false;
std::string currentOption = (*xoptions)[i];
- if (BZDB.get("jsXAxis") == currentOption)
+
+ // could also be inverted
+ if(currentOption.length() >= 12
+ && currentOption.substr(currentOption.length() - 10, std::string::npos) == "(Inverted)")
+ {
+ currentOption = currentOption.substr(0, currentOption.length() - 11);
+ currentOptionInverted = true;
+ }
+
+ if (BZDB.get("jsXAxis") == currentOption && currentOptionInverted == xAxisInverted)
{
jsx->setIndex(i);
found = true;
}
}
if (!found)
- {
- // If there are at least two axes, use the first one for X
- if (xoptions->size() > 2)
- jsx->setIndex(1);
- else
- jsx->setIndex(0);
- }
+ jsx->setIndex(0);
jsx->update();
found = false;
for (i = 0; i < (int)yoptions->size(); i++)
{
+ bool currentOptionInverted = false;
std::string currentOption = (*yoptions)[i];
- if (BZDB.get("jsYAxis") == currentOption)
+
+ // could also be inverted
+ if(currentOption.length() >= 12
+ && currentOption.substr(currentOption.length() - 10, std::string::npos) == "(Inverted)")
+ {
+ currentOption = currentOption.substr(0, currentOption.length() - 11);
+ currentOptionInverted = true;
+ }
+
+ if (BZDB.get("jsYAxis") == currentOption && currentOptionInverted == yAxisInverted)
{
jsy->setIndex(i);
found = true;
@@ -212,7 +301,6 @@ void InputMenu::fillJSOptions()
}
if (!found)
{
- // If there are at least two axes, use the second one for Y
if (yoptions->size() > 2)
jsy->setIndex(2);
else
@@ -229,6 +317,11 @@ void InputMenu::execute()
if (!keyboardMapMenu) keyboardMapMenu = new KeyboardMapMenu;
HUDDialogStack::get()->push(keyboardMapMenu);
}
+ else if (_focus == joystickTest)
+ {
+ if (!joystickTestMenu) joystickTestMenu = new JoystickTestMenu;
+ HUDDialogStack::get()->push(joystickTestMenu);
+ }
}
void InputMenu::callback(HUDuiControl* w, const void* data)
@@ -251,15 +344,73 @@ void InputMenu::callback(HUDuiControl* w, const void* data)
/* Joystick x-axis */
case 'X':
- BZDB.set("jsXAxis", selectedOption);
- getMainWindow()->setJoyXAxis(selectedOption);
+ {
+ auto selectedAxis = selectedOption;
+ auto xAxisInverted = false;
+ const auto oldInvertAxes = BZDB.evalInt("jsInvertAxes");
+
+ if(selectedOption.length() >= 12
+ && selectedOption.substr(selectedOption.length() - 10, std::string::npos) == "(Inverted)")
+ {
+ selectedAxis = selectedAxis.substr(0, selectedAxis.length() - 11);
+ xAxisInverted = true;
+ }
+
+ BZDB.set("jsXAxis", selectedAxis);
+ getMainWindow()->setJoyXAxis(selectedAxis);
+
+ if(xAxisInverted) // X axis inversion needs to be enabled
+ {
+ if(oldInvertAxes % 2 != 1) // it wasn't already enabled
+ {
+ BZDB.setInt("jsInvertAxes", oldInvertAxes == 2 ? 3 : 1); // preserve the Y enabled value
+ }
+ }
+ else // X axis inversion needs to be disabled
+ {
+ if(oldInvertAxes % 2 == 1) // it was enabled previously
+ {
+ BZDB.setInt("jsInvertAxes", oldInvertAxes == 3 ? 2 : 0); // preserve the Y enabled value
+ }
+ }
+
break;
+ }
/* Joystick y-axis */
case 'Y':
- BZDB.set("jsYAxis", selectedOption);
- getMainWindow()->setJoyYAxis(selectedOption);
+ {
+ auto selectedAxis = selectedOption;
+ auto yAxisInverted = false;
+ const auto oldInvertAxes = BZDB.evalInt("jsInvertAxes");
+
+ if(selectedOption.length() >= 12
+ && selectedOption.substr(selectedOption.length() - 10, std::string::npos) == "(Inverted)")
+ {
+ selectedAxis = selectedAxis.substr(0, selectedAxis.length() - 11);
+ yAxisInverted = true;
+ }
+
+ BZDB.set("jsYAxis", selectedAxis);
+ getMainWindow()->setJoyYAxis(selectedAxis);
+
+ if(yAxisInverted) // Y axis inversion needs to be enabled
+ {
+ if(oldInvertAxes < 2) // it wasn't already enabled
+ {
+ BZDB.setInt("jsInvertAxes", oldInvertAxes == 1 ? 3 : 2); // preserve the X enabled value
+ }
+ }
+ else // Y axis inversion needs to be disabled
+ {
+ if(oldInvertAxes > 1) // it was enabled previously
+ {
+ BZDB.setInt("jsInvertAxes", oldInvertAxes == 3 ? 1 : 0); // preserve the X enabled value
+ }
+ }
+
break;
+ }
/* Joystick axes inversion */
case 'I':
@@ -318,9 +469,34 @@ void InputMenu::callback(HUDuiControl* w, const void* data)
}
break;
- /* Force feedback */
+ /* Force Feedback */
case 'F':
- BZDB.setBool("rumble", listHUD->getIndex() == 1);
+ BZDB.set("forceFeedback", selectedOption);
+ break;
+
+ /* Joystick Range Limit */
+ case 'T':
+ BZDB.set("jsRangeMax", selectedOption.substr(0, selectedOption.length() - 1));
+ break;
+
+ /* Joystick Dead Zone */
+ case 'B':
+ BZDB.set("jsRangeMin", selectedOption.substr(0, selectedOption.length() - 1));
+ break;
+
+ /* Stretch Joystick Range Corners */
+ case 'S':
+ BZDB.setBool("jsStretchCorners", selectedOption == "Yes" ? true : false);
+ break;
+
+ /* Joystick Ramp Type */
+ case 'R':
+ if(selectedOption == "Exponential (Squared)")
+ BZDB.set("jsRampType", "squared");
+ else if(selectedOption == "Exponential (Cubed)")
+ BZDB.set("jsRampType", "cubed");
+ else
+ BZDB.set("jsRampType", "linear");
break;
}
@@ -355,8 +531,8 @@ void InputMenu::resize(int _width, int _height)
{
listHUD[i]->setFontSize(fontSize);
listHUD[i]->setPosition(x, y);
- // Add extra space after Change Key Mapping, Active input device, Invert Joystick Axes, and Mouse Box Size
- if (i == 1 || i == 2 || i == 7 || i == 9)
+ // Add extra space after Change Key Mapping, Active input device, Test Joystick Range, and Mouse Box Size
+ if (i == 1 || i == 2 || i == 11 || i == 13)
y -= 1.75f * h;
else
y -= 1.0f * h;
@@ -375,7 +551,7 @@ void InputMenu::resize(int _width, int _height)
SceneRenderer* renderer = getSceneRenderer();
if (renderer != nullptr)
- ((HUDuiList*)listHUD[9])->setIndex(renderer->getMaxMotionFactor() + 11);
+ ((HUDuiList*)listHUD[13])->setIndex(renderer->getMaxMotionFactor() + 11);
}
diff --git a/src/bzflag/InputMenu.h b/src/bzflag/InputMenu.h
index 37e9eb9fd9..1c3f61991a 100644
--- a/src/bzflag/InputMenu.h
+++ b/src/bzflag/InputMenu.h
@@ -21,6 +21,7 @@
/* local interface headers */
#include "MenuDefaultKey.h"
#include "KeyboardMapMenu.h"
+#include "JoystickTestMenu.h"
#include "HUDuiControl.h"
#include "HUDuiList.h"
#include "HUDuiDefaultKey.h"
@@ -45,11 +46,13 @@ class InputMenu : public HUDDialog
void fillJSOptions();
private:
- HUDuiControl* keyMapping;
- HUDuiList* activeInput;
- HUDuiList* jsx;
- HUDuiList* jsy;
- KeyboardMapMenu* keyboardMapMenu;
+ HUDuiControl* keyMapping;
+ HUDuiList* activeInput;
+ HUDuiList* jsx;
+ HUDuiList* jsy;
+ HUDuiControl* joystickTest;
+ KeyboardMapMenu* keyboardMapMenu;
+ JoystickTestMenu* joystickTestMenu;
};
diff --git a/src/bzflag/JoystickTestMenu.cxx b/src/bzflag/JoystickTestMenu.cxx
new file mode 100644
index 0000000000..d194e8c7a2
--- /dev/null
+++ b/src/bzflag/JoystickTestMenu.cxx
@@ -0,0 +1,87 @@
+/* bzflag
+ * Copyright (c) 1993-2020 Tim Riker
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the license found in the file
+ * named COPYING that should have accompanied this file.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* interface header */
+#include "JoystickTestMenu.h"
+
+/* common implementation headers */
+#include "StateDatabase.h"
+#include "FontManager.h"
+
+/* local implementation headers */
+#include "MainMenu.h"
+#include "HUDDialogStack.h"
+#include "LocalPlayer.h"
+#include "playing.h"
+#include "HUDui.h"
+
+JoystickTestMenu::JoystickTestMenu()
+{
+ std::string currentJoystickDevice = BZDB.get("joystickname");
+ // cache font face ID
+ int fontFace = MainMenu::getFontFace();
+ // add controls
+ std::vector& listHUD = getControls();
+
+ titleLabel = new HUDuiLabel;
+ titleLabel->setFontFace(fontFace);
+ titleLabel->setString("Test Joystick Range");
+ listHUD.push_back(titleLabel);
+
+ // make a fake menu entry to hide offscreen, since something needs to have focus
+ fakeLabel = new HUDuiLabel;
+ fakeLabel->setFontFace(fontFace);
+ fakeLabel->setString("If you can see this, my worst nightmares have come true.");
+ listHUD.push_back(fakeLabel);
+
+ fakeLabel->setPrev(fakeLabel);
+ fakeLabel->setNext(fakeLabel);
+ setFocus(fakeLabel);
+
+ jsTestLabel = new HUDuiJSTestLabel;
+ listHUD.push_back(jsTestLabel);
+}
+
+void JoystickTestMenu::resize(int _width, int _height)
+{
+ HUDDialog::resize(_width, _height);
+
+ // use a big font for title
+ const auto titleFontSize = float(_height) / 15.0f;
+ const auto fontSize = float(_height) / 45.0f;
+ FontManager &fm = FontManager::instance();
+
+ // reposition title
+ titleLabel->setFontSize(titleFontSize);
+ const auto titleWidth = fm.getStrLength(MainMenu::getFontFace(), titleFontSize, titleLabel->getString());
+ const auto titleHeight = fm.getStrHeight(MainMenu::getFontFace(), titleFontSize, " ");
+ titleLabel->setPosition(0.5f * ((float)_width - titleWidth), (float)_height - titleHeight);
+
+ // reposition and resize joystick test area
+ const auto testAreaSize = float(_height) - titleHeight - 0.6f * titleHeight;
+ jsTestLabel->setPosition(0.5f * (float(_width) - testAreaSize),
+ fm.getStrHeight(MainMenu::getFontFace(), fontSize, " "));
+ jsTestLabel->setSize(testAreaSize, testAreaSize);
+
+ // reposition fake label off-screen
+ fakeLabel->setFontSize(fontSize);
+ fakeLabel->setPosition(0, _height * 2.0f);
+}
+
+
+// Local Variables: ***
+// mode: C++ ***
+// tab-width: 4 ***
+// c-basic-offset: 4 ***
+// indent-tabs-mode: nil ***
+// End: ***
+// ex: shiftwidth=4 tabstop=4
diff --git a/src/bzflag/JoystickTestMenu.h b/src/bzflag/JoystickTestMenu.h
new file mode 100644
index 0000000000..63215a92c7
--- /dev/null
+++ b/src/bzflag/JoystickTestMenu.h
@@ -0,0 +1,59 @@
+/* bzflag
+ * Copyright (c) 1993-2020 Tim Riker
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the license found in the file
+ * named COPYING that should have accompanied this file.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __JOYSTICKTESTMENU_H__
+#define __JOYSTICKTESTMENU_H__
+
+#include "common.h"
+
+/* common interface headers */
+#include "HUDDialog.h"
+
+/* local interface headers */
+#include "MenuDefaultKey.h"
+#include "HUDuiControl.h"
+#include "HUDuiList.h"
+#include "HUDuiDefaultKey.h"
+#include "HUDuiJSTestLabel.h"
+
+
+/** this class provides a visual test of the joystick range
+ */
+class JoystickTestMenu : public HUDDialog
+{
+public:
+ JoystickTestMenu();
+ ~JoystickTestMenu() { };
+
+ HUDuiDefaultKey* getDefaultKey()
+ {
+ return MenuDefaultKey::getInstance();
+ }
+ void execute() { };
+ void resize(int width, int height);
+
+private:
+ HUDuiLabel* titleLabel;
+ HUDuiLabel* fakeLabel;
+ HUDuiJSTestLabel* jsTestLabel;
+};
+
+
+#endif /* __JOYSTICKTESTMENU_H__ */
+
+// Local Variables: ***
+// mode: C++ ***
+// tab-width: 4 ***
+// c-basic-offset: 4 ***
+// indent-tabs-mode: nil ***
+// End: ***
+// ex: shiftwidth=4 tabstop=4
diff --git a/src/bzflag/MainWindow.cxx b/src/bzflag/MainWindow.cxx
index e1ef84a4a2..35e84df78d 100644
--- a/src/bzflag/MainWindow.cxx
+++ b/src/bzflag/MainWindow.cxx
@@ -307,16 +307,9 @@ bool MainWindow::haveJoystick() const
return joystick->joystick();
}
-void MainWindow::getJoyPosition(int& mx, int& my) const
-{
- // joystick axes inversion values
- // 0: no inversion
- // 1: invert X
- // 2: invert Y
- // 3: invert both
- joystick->getJoy(mx, my);
- mx = ((width >> 1) * mx * (BZDB.evalInt("jsInvertAxes") % 2 == 1 ? -1 : 1)) / (900);
- my = ((height >> 1) * my * (BZDB.evalInt("jsInvertAxes") > 1 ? -1 : 1)) / (900);
+void MainWindow::getJoyPosition(float& jsx, float& jsy) const
+{
+ joystick->getJoy(jsx, jsy);
}
int MainWindow::getNumHats() const
diff --git a/src/bzflag/MainWindow.h b/src/bzflag/MainWindow.h
index 40f0926d64..b91231d3d3 100644
--- a/src/bzflag/MainWindow.h
+++ b/src/bzflag/MainWindow.h
@@ -97,7 +97,7 @@ class MainWindow
// events instead because it means no round trip to the server
// for these values that we need every frame.
void getMousePosition(int& mx, int& my) const;
- void getJoyPosition(int& mx, int& my) const;
+ void getJoyPosition(float& jsx, float& jsy) const;
int getNumHats() const;
void getJoyHat(int hat, float &hatX, float &hatY) const;
unsigned long getJoyButtonSet() const;
diff --git a/src/bzflag/Makefile.am b/src/bzflag/Makefile.am
index 6e14cacf40..da72a99f72 100644
--- a/src/bzflag/Makefile.am
+++ b/src/bzflag/Makefile.am
@@ -65,6 +65,8 @@ bzflag_SOURCES = \
HUDuiControl.h \
HUDuiDefaultKey.cxx \
HUDuiDefaultKey.h \
+ HUDuiJSTestLabel.cxx \
+ HUDuiJSTestLabel.h \
HUDuiLabel.cxx \
HUDuiLabel.h \
HUDuiList.cxx \
@@ -73,6 +75,8 @@ bzflag_SOURCES = \
HUDuiTextureLabel.h \
HUDuiTypeIn.cxx \
HUDuiTypeIn.h \
+ JoystickTestMenu.cxx \
+ JoystickTestMenu.h \
JoinMenu.cxx \
JoinMenu.h \
InputMenu.cxx \
diff --git a/src/bzflag/defaultBZDB.cxx b/src/bzflag/defaultBZDB.cxx
index ef490f9050..5f7f35e55d 100644
--- a/src/bzflag/defaultBZDB.cxx
+++ b/src/bzflag/defaultBZDB.cxx
@@ -45,6 +45,11 @@ DefaultDBItem defaultDBItems[] =
{ "radarsize", "8", true, StateDatabase::ReadWrite, NULL },
{ "mouseboxsize", "5", true, StateDatabase::ReadWrite, NULL },
{ "mouseClamp", "0", true, StateDatabase::ReadWrite, NULL },
+ { "jsInvertAxes", "0", true, StateDatabase::ReadWrite, NULL },
+ { "jsRangeMax", "100", true, StateDatabase::ReadWrite, NULL },
+ { "jsRangeMin", "5", true, StateDatabase::ReadWrite, NULL },
+ { "jsStretchCorners", "1", true, StateDatabase::ReadWrite, NULL },
+ { "jsRampType", "linear", true, StateDatabase::ReadWrite, NULL },
{ "cpanelfontsize", "0", true, StateDatabase::ReadWrite, NULL },
{ "controlPanelTimestamp", "0", true, StateDatabase::ReadWrite, NULL },
{ "scorefontsize", "0", true, StateDatabase::ReadWrite, NULL },
diff --git a/src/bzflag/playing.cxx b/src/bzflag/playing.cxx
index 18bd15dcc4..73896dfbb3 100644
--- a/src/bzflag/playing.cxx
+++ b/src/bzflag/playing.cxx
@@ -903,6 +903,67 @@ static void doKey(const BzfKeyEvent& key, bool pressed)
doKeyPlaying(key, pressed, haveBinding);
}
+
+void applyJSModifiers(float& jsx, float& jsy)
+{
+ // enforce range setting limits (min 0% to 20%, max 25% to 100%) so the maximum can't be less than the minimum
+ const auto jsRangeMax = std::max(std::min(float(BZDB.evalInt("jsRangeMax")) / 100.0f, 1.0f), 0.25f);
+ const auto jsRangeMin = std::max(std::min(float(BZDB.evalInt("jsRangeMin")) / 100.0f, 0.2f), 0.0f);
+
+ // joystick axes inversion values
+ // 0: no inversion
+ // 1: invert X
+ // 2: invert Y
+ // 3: invert both
+ jsx *= BZDB.evalInt("jsInvertAxes") % 2 == 1 ? -1.0f : 1.0f;
+ jsy *= BZDB.evalInt("jsInvertAxes") > 1 ? -1.0f : 1.0f;
+
+ // scaled radial dead zone and cap
+ const auto jsMagnitude = std::sqrt(jsx * jsx + jsy * jsy);
+ const auto jsRangeMultiplier = jsRangeMax * (jsMagnitude - jsRangeMin) / (jsRangeMax - jsRangeMin) / jsMagnitude;
+
+ // exponential ramp
+ const auto jsRampType = BZDB.get("jsRampType");
+ auto jsRampFactor = jsRangeMultiplier;
+ if(jsRampType == "squared")
+ jsRampFactor = std::pow(jsRangeMultiplier, 2.0f);
+ else if(jsRampType == "cubed")
+ jsRampFactor = std::pow(jsRangeMultiplier, 3.0f);
+
+ // apply both factors
+ if(jsMagnitude < jsRangeMin || isnan(jsRangeMultiplier))
+ jsx = jsy = 0.0f;
+ else
+ {
+ jsx *= jsRampFactor;
+ jsy *= jsRampFactor;
+ }
+
+ // stretch corners
+ if(BZDB.isTrue("jsStretchCorners"))
+ {
+ const auto stretchFactor = (1.0f - float(std::abs(std::abs(atan(jsy / jsx) / M_PI) - 0.25f)) * 4.0f) * jsMagnitude;
+ const auto stretchValue = std::sqrt(2.0f);
+
+ if(! isnan(stretchFactor))
+ {
+ jsx *= (1.0f - stretchFactor) + stretchValue * stretchFactor; // mix based on stretchFactor from 0.0 to 1.0
+ jsy *= (1.0f - stretchFactor) + stretchValue * stretchFactor;
+ }
+ }
+
+ // proportionally scale the coordinates back to the range limit
+ const auto jsxAbs = std::abs(jsx);
+ const auto jsyAbs = std::abs(jsy);
+ if(jsxAbs > jsRangeMax || jsyAbs > jsRangeMax)
+ {
+ const auto jsRangeExcess = (jsxAbs > jsyAbs ? jsxAbs : jsyAbs) / jsRangeMax;
+ jsx /= jsRangeExcess;
+ jsy /= jsRangeExcess;
+ }
+}
+
+
static void doMotion()
{
float rotation = 0.0f, speed = 1.0f;
@@ -926,12 +987,13 @@ static void doMotion()
// determine if joystick motion should be used instead of mouse motion
// when the player bumps the mouse, LocalPlayer::getInputMethod return Mouse;
// make it return Joystick when the user bumps the joystick
+ auto jsx = 0.0f, jsy = 0.0f;
if (mainWindow->haveJoystick())
{
if (myTank->getInputMethod() == LocalPlayer::Joystick)
{
// if we're using the joystick right now, replace mouse coords with joystick coords
- mainWindow->getJoyPosition(mx, my);
+ mainWindow->getJoyPosition(jsx, jsy);
}
else
{
@@ -939,11 +1001,10 @@ static void doMotion()
// see if it's moved and autoswitch
if (BZDB.isTrue("allowInputChange"))
{
- int jx = 0, jy = 0;
- mainWindow->getJoyPosition(jx, jy);
+ mainWindow->getJoyPosition(jsx, jsy);
+
// if we aren't using the joystick, but it's moving, start using it
- if ((jx < -noMotionSize * 2) || (jx > noMotionSize * 2)
- || (jy < -noMotionSize * 2) || (jy > noMotionSize * 2))
+ if(std::sqrt(jsx * jsx + jsy * jsy) > std::min(std::max(float(BZDB.evalInt("jsRangeMin")) / 100.0f, 0.0f), 0.2f))
myTank->setInputMethod(LocalPlayer::Joystick); // joystick motion
} // allowInputChange
} // getInputMethod == Joystick
@@ -977,9 +1038,48 @@ static void doMotion()
speed *= 0.5f;
}
}
- else // both mouse and joystick
+ else if (myTank->getInputMethod() == LocalPlayer::Joystick)
{
+ applyJSModifiers(jsx, jsy);
+ // calculate desired rotation
+ if (keyboardRotation && !devDriving)
+ {
+ rotation = float(keyboardRotation);
+ rotation *= BZDB.eval("displayFOV") / 60.0f;
+ if (BZDB.isTrue("slowKeyboard"))
+ rotation *= 0.5f;
+ }
+ else
+ {
+ rotation = -jsx;
+
+ if (rotation > 1.0f)
+ rotation = 1.0f;
+ if (rotation < -1.0f)
+ rotation = -1.0f;
+ }
+
+ // calculate desired speed
+ if (keyboardSpeed && !devDriving)
+ {
+ speed = float(keyboardSpeed);
+ if (speed < 0.0f)
+ speed *= 0.5f;
+ if (BZDB.isTrue("slowKeyboard"))
+ speed *= 0.5f;
+ }
+ else
+ {
+ speed = -jsy;
+ if (speed > 1.0f)
+ speed = 1.0f;
+ if (speed < -0.5f)
+ speed = -0.5f;
+ }
+ }
+ else // mouse
+ {
// calculate desired rotation
if (keyboardRotation && !devDriving)
{
diff --git a/src/bzflag/playing.h b/src/bzflag/playing.h
index e3a8ab669e..aba6c38d64 100644
--- a/src/bzflag/playing.h
+++ b/src/bzflag/playing.h
@@ -102,6 +102,8 @@ void killGlobalAres();
extern void joinGame();
+extern void applyJSModifiers(float& jsx, float& jsy);
+
extern HUDRenderer *hud;
extern char messageMessage[PlayerIdPLen + MessageLen];
extern ServerLink* serverLink;
diff --git a/src/platform/BzfJoystick.cxx b/src/platform/BzfJoystick.cxx
index 9713369666..cc8038e7e7 100644
--- a/src/platform/BzfJoystick.cxx
+++ b/src/platform/BzfJoystick.cxx
@@ -59,9 +59,9 @@ bool BzfJoystick::joystick() const
return false;
}
-void BzfJoystick::getJoy(int& x, int& y)
+void BzfJoystick::getJoy(float& x, float& y)
{
- x = y = 0;
+ x = y = 0.0f;
}
void BzfJoystick::getJoyDevices(std::vector
diff --git a/src/platform/SDLJoystick.cxx b/src/platform/SDLJoystick.cxx
index 253c1090a8..3e100502ae 100644
--- a/src/platform/SDLJoystick.cxx
+++ b/src/platform/SDLJoystick.cxx
@@ -109,24 +109,16 @@ bool SDLJoystick::joystick() const
return joystickID != nullptr;
}
-void SDLJoystick::getJoy(int& x, int& y)
+void SDLJoystick::getJoy(float& x, float& y)
{
- x = y = 0;
+ x = y = 0.0f;
if (!joystickID)
return;
SDL_JoystickUpdate();
- x = SDL_JoystickGetAxis(joystickID, xAxis);
- y = SDL_JoystickGetAxis(joystickID, yAxis);
-
- x = x * 1000 / 32768;
- y = y * 1000 / 32768;
-
- // ballistic
- x = (x * abs(x)) / 1000;
- y = (y * abs(y)) / 1000;
-
+ x = float(SDL_JoystickGetAxis(joystickID, xAxis)) / 32768.0f;
+ y = float(SDL_JoystickGetAxis(joystickID, yAxis)) / 32768.0f;
}
unsigned long SDLJoystick::getJoyButtons()
diff --git a/src/platform/SDLJoystick.h b/src/platform/SDLJoystick.h
index afc7f9ccee..dd84dfc8c6 100644
--- a/src/platform/SDLJoystick.h
+++ b/src/platform/SDLJoystick.h
@@ -28,7 +28,7 @@ class SDLJoystick : public BzfJoystick
void initJoystick(const char* joystickName);
bool joystick() const;
- void getJoy(int& x, int& y);
+ void getJoy(float& x, float& y);
unsigned long getJoyButtons();
int getNumHats();
void getJoyHat(int hat, float &hatX, float &hatY);