aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubenwardy <rubenwardy@gmail.com>2017-04-02 23:00:34 +0100
committerAuke Kok <sofar+github@foo-projects.org>2017-04-06 20:58:52 -0700
commitbce0d458d8cda70c10d78ea9ec476474f0a6f01a (patch)
tree529062ce8f0e7b7fd8f5bd94608af3e36a7860d6
parent351cc2e79a7d78f7ec97ff9b33e4f0bad4042b19 (diff)
downloadminetest-bce0d458d8cda70c10d78ea9ec476474f0a6f01a.tar.gz
minetest-bce0d458d8cda70c10d78ea9ec476474f0a6f01a.tar.bz2
minetest-bce0d458d8cda70c10d78ea9ec476474f0a6f01a.zip
Add Joystick type detection and Xbox controller support
* Add joystick type detection (with joystick_type setting to override it) * Fix multiple joysticks from interfering with each other by only reading from one (add joystick_id setting) * Add support for Xbox controllers
-rw-r--r--builtin/settingtypes.txt6
-rw-r--r--minetest.conf.example9
-rw-r--r--src/client/clientlauncher.cpp51
-rw-r--r--src/client/clientlauncher.h1
-rw-r--r--src/client/joystick_controller.cpp104
-rw-r--r--src/client/joystick_controller.h9
-rw-r--r--src/defaultsettings.cpp2
-rw-r--r--src/game.h1
8 files changed, 146 insertions, 37 deletions
diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt
index dc3164e44..d95f8cf41 100644
--- a/builtin/settingtypes.txt
+++ b/builtin/settingtypes.txt
@@ -107,6 +107,12 @@ continuous_forward (Continuous forward) bool false
# Enable Joysticks
enable_joysticks (Enable Joysticks) bool false
+# The identifier of the joystick to use
+joystick_id (Joystick ID) int 0
+
+# The type of joystick
+joystick_type (Joystick Type) enum auto auto,generic,xbox
+
# The time in seconds it takes between repeated events
# when holding down a joystick button combination.
repeat_joystick_button_time (Joystick button repetition interval) float 0.17
diff --git a/minetest.conf.example b/minetest.conf.example
index 292a645e3..cfc66f168 100644
--- a/minetest.conf.example
+++ b/minetest.conf.example
@@ -87,6 +87,14 @@
# type: bool
# enable_joysticks = false
+# The identifier of the joystick to use
+# type: int
+# joystick_id = 0
+
+# The type of joystick
+# type: enum values: auto,generic,xbox
+# joystick_type = auto
+
# The time in seconds it takes between repeated events
# when holding down a joystick button combination.
# type: float
@@ -1786,4 +1794,3 @@ server_side_occlusion_culling = true
# Print the engine's profiling data in regular intervals (in seconds). 0 = disable. Useful for developers.
# type: int
# profiler_print_interval = 0
-
diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp
index 3ec7be7d9..249f6727a 100644
--- a/src/client/clientlauncher.cpp
+++ b/src/client/clientlauncher.cpp
@@ -127,10 +127,7 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args)
device->setResizable(true);
- if (random_input)
- input = new RandomInputHandler();
- else
- input = new RealInputHandler(device, receiver);
+ init_input();
smgr = device->getSceneManager();
smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
@@ -337,6 +334,33 @@ bool ClientLauncher::init_engine()
return device != NULL;
}
+void ClientLauncher::init_input()
+{
+ if (random_input)
+ input = new RandomInputHandler();
+ else
+ input = new RealInputHandler(device, receiver);
+
+ if (g_settings->getBool("enable_joysticks")) {
+ irr::core::array<irr::SJoystickInfo> infos;
+ std::vector<irr::SJoystickInfo> joystick_infos;
+
+ // Make sure this is called maximum once per
+ // irrlicht device, otherwise it will give you
+ // multiple events for the same joystick.
+ if (device->activateJoysticks(infos)) {
+ infostream << "Joystick support enabled" << std::endl;
+ joystick_infos.reserve(infos.size());
+ for (u32 i = 0; i < infos.size(); i++) {
+ joystick_infos.push_back(infos[i]);
+ }
+ input->joystick.onJoystickConnect(joystick_infos);
+ } else {
+ errorstream << "Could not activate joystick support." << std::endl;
+ }
+ }
+}
+
bool ClientLauncher::launch_game(std::string &error_message,
bool reconnect_requested, GameParams &game_params,
const Settings &cmd_args)
@@ -566,25 +590,8 @@ bool ClientLauncher::create_engine_device()
device = createDeviceEx(params);
- if (device) {
- if (g_settings->getBool("enable_joysticks")) {
- irr::core::array<irr::SJoystickInfo> infos;
- std::vector<irr::SJoystickInfo> joystick_infos;
- // Make sure this is called maximum once per
- // irrlicht device, otherwise it will give you
- // multiple events for the same joystick.
- if (device->activateJoysticks(infos)) {
- infostream << "Joystick support enabled" << std::endl;
- joystick_infos.reserve(infos.size());
- for (u32 i = 0; i < infos.size(); i++) {
- joystick_infos.push_back(infos[i]);
- }
- } else {
- errorstream << "Could not activate joystick support." << std::endl;
- }
- }
+ if (device)
porting::initIrrlicht(device);
- }
return device != NULL;
}
diff --git a/src/client/clientlauncher.h b/src/client/clientlauncher.h
index b10bbebc9..ab22d7aaa 100644
--- a/src/client/clientlauncher.h
+++ b/src/client/clientlauncher.h
@@ -91,6 +91,7 @@ public:
protected:
void init_args(GameParams &game_params, const Settings &cmd_args);
bool init_engine();
+ void init_input();
bool launch_game(std::string &error_message, bool reconnect_requested,
GameParams &game_params, const Settings &cmd_args);
diff --git a/src/client/joystick_controller.cpp b/src/client/joystick_controller.cpp
index ef8d18ab0..311cd22fb 100644
--- a/src/client/joystick_controller.cpp
+++ b/src/client/joystick_controller.cpp
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "keys.h"
#include "settings.h"
#include "gettime.h"
+#include "../util/string.h"
bool JoystickButtonCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
{
@@ -42,7 +43,7 @@ bool JoystickAxisCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
#define JLO_B_PB(A, B, C) jlo.button_keys.push_back(JoystickButtonCmb(A, B, C))
#define JLO_A_PB(A, B, C, D) jlo.axis_keys.push_back(JoystickAxisCmb(A, B, C, D))
-static JoystickLayout create_default_layout()
+JoystickLayout create_default_layout()
{
JoystickLayout jlo;
@@ -103,11 +104,59 @@ static JoystickLayout create_default_layout()
return jlo;
}
-static const JoystickLayout default_layout = create_default_layout();
+JoystickLayout create_xbox_layout()
+{
+ JoystickLayout jlo;
+
+ jlo.axes_dead_border = 7000;
+
+ const JoystickAxisLayout axes[JA_COUNT] = {
+ {0, 1}, // JA_SIDEWARD_MOVE
+ {1, 1}, // JA_FORWARD_MOVE
+ {2, 1}, // JA_FRUSTUM_HORIZONTAL
+ {3, 1}, // JA_FRUSTUM_VERTICAL
+ };
+ memcpy(jlo.axes, axes, sizeof(jlo.axes));
+
+ // The back button means "ESC".
+ JLO_B_PB(KeyType::ESC, 1 << 8, 1 << 8); // back
+ JLO_B_PB(KeyType::ESC, 1 << 9, 1 << 9); // start
+
+ // 4 Buttons
+ JLO_B_PB(KeyType::JUMP, 1 << 0, 1 << 0); // A/green
+ JLO_B_PB(KeyType::ESC, 1 << 1, 1 << 1); // B/red
+ JLO_B_PB(KeyType::SPECIAL1, 1 << 2, 1 << 2); // X/blue
+ JLO_B_PB(KeyType::INVENTORY, 1 << 3, 1 << 3); // Y/yellow
+
+ // Analog Sticks
+ JLO_B_PB(KeyType::SPECIAL1, 1 << 11, 1 << 11); // left
+ JLO_B_PB(KeyType::SNEAK, 1 << 12, 1 << 12); // right
+
+ // Triggers
+ JLO_B_PB(KeyType::MOUSE_L, 1 << 6, 1 << 6); // lt
+ JLO_B_PB(KeyType::MOUSE_R, 1 << 7, 1 << 7); // rt
+ JLO_B_PB(KeyType::SCROLL_UP, 1 << 4, 1 << 4); // lb
+ JLO_B_PB(KeyType::SCROLL_DOWN, 1 << 5, 1 << 5); // rb
+
+ // D-PAD
+ JLO_B_PB(KeyType::ZOOM, 1 << 15, 1 << 15); // up
+ JLO_B_PB(KeyType::DROP, 1 << 13, 1 << 13); // left
+ JLO_B_PB(KeyType::SCREENSHOT, 1 << 14, 1 << 14); // right
+ JLO_B_PB(KeyType::FREEMOVE, 1 << 16, 1 << 16); // down
+
+ // Movement buttons, important for vessels
+ JLO_A_PB(KeyType::FORWARD, 1, 1, 1024);
+ JLO_A_PB(KeyType::BACKWARD, 1, -1, 1024);
+ JLO_A_PB(KeyType::LEFT, 0, 1, 1024);
+ JLO_A_PB(KeyType::RIGHT, 0, -1, 1024);
+
+ return jlo;
+}
JoystickController::JoystickController()
{
- m_layout = &default_layout;
+ m_joystick_id = 0;
+
doubling_dtime = g_settings->getFloat("repeat_joystick_button_time");
for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
@@ -116,23 +165,54 @@ JoystickController::JoystickController()
clear();
}
+void JoystickController::onJoystickConnect(const std::vector<irr::SJoystickInfo> &joystick_infos)
+{
+ s32 id = g_settings->getS32("joystick_id");
+ std::string layout = g_settings->get("joystick_type");
+
+ if (id < 0 || id >= joystick_infos.size()) {
+ // TODO: auto detection
+ id = 0;
+ }
+
+ if (id >= 0 && id < joystick_infos.size()) {
+ if (layout.empty() || layout == "auto")
+ setLayoutFromControllerName(joystick_infos[id].Name.c_str());
+ else
+ setLayoutFromControllerName(layout);
+ }
+
+ m_joystick_id = id;
+}
+
+void JoystickController::setLayoutFromControllerName(std::string name) {
+ if (lowercase(name).find("xbox") >= 0) {
+ m_layout = create_xbox_layout();
+ } else {
+ m_layout = create_default_layout();
+ }
+}
+
bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
{
+ if (ev.Joystick != m_joystick_id)
+ return false;
+
m_internal_time = getTimeMs() / 1000.f;
std::bitset<KeyType::INTERNAL_ENUM_COUNT> keys_pressed;
// First generate a list of keys pressed
- for (size_t i = 0; i < m_layout->button_keys.size(); i++) {
- if (m_layout->button_keys[i].isTriggered(ev)) {
- keys_pressed.set(m_layout->button_keys[i].key);
+ for (size_t i = 0; i < m_layout.button_keys.size(); i++) {
+ if (m_layout.button_keys[i].isTriggered(ev)) {
+ keys_pressed.set(m_layout.button_keys[i].key);
}
}
- for (size_t i = 0; i < m_layout->axis_keys.size(); i++) {
- if (m_layout->axis_keys[i].isTriggered(ev)) {
- keys_pressed.set(m_layout->axis_keys[i].key);
+ for (size_t i = 0; i < m_layout.axis_keys.size(); i++) {
+ if (m_layout.axis_keys[i].isTriggered(ev)) {
+ keys_pressed.set(m_layout.axis_keys[i].key);
}
}
@@ -153,7 +233,7 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
}
for (size_t i = 0; i < JA_COUNT; i++) {
- const JoystickAxisLayout &ax_la = m_layout->axes[i];
+ const JoystickAxisLayout &ax_la = m_layout.axes[i];
m_axes_vals[i] = ax_la.invert * ev.Axis[ax_la.axis_id];
}
@@ -172,8 +252,8 @@ void JoystickController::clear()
s16 JoystickController::getAxisWithoutDead(JoystickAxis axis)
{
s16 v = m_axes_vals[axis];
- if (((v > 0) && (v < m_layout->axes_dead_border)) ||
- ((v < 0) && (v > -m_layout->axes_dead_border)))
+ if (((v > 0) && (v < m_layout.axes_dead_border)) ||
+ ((v < 0) && (v > -m_layout.axes_dead_border)))
return 0;
return v;
}
diff --git a/src/client/joystick_controller.h b/src/client/joystick_controller.h
index ed0ee4068..867a0c3f2 100644
--- a/src/client/joystick_controller.h
+++ b/src/client/joystick_controller.h
@@ -98,6 +98,9 @@ class JoystickController {
public:
JoystickController();
+
+ void onJoystickConnect(const std::vector<irr::SJoystickInfo> &joystick_infos);
+
bool handleEvent(const irr::SEvent::SJoystickEvent &ev);
void clear();
@@ -146,10 +149,14 @@ public:
f32 doubling_dtime;
private:
- const JoystickLayout *m_layout;
+ void setLayoutFromControllerName(std::string name);
+
+ JoystickLayout m_layout;
s16 m_axes_vals[JA_COUNT];
+ u8 m_joystick_id;
+
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_pressed_keys;
f32 m_internal_time;
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 4b50b991b..3f4ce6337 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -203,6 +203,8 @@ void set_default_settings(Settings *settings)
settings->setDefault("always_fly_fast", "true");
settings->setDefault("continuous_forward", "false");
settings->setDefault("enable_joysticks", "false");
+ settings->setDefault("joystick_id", "0");
+ settings->setDefault("joystick_type", "");
settings->setDefault("repeat_joystick_button_time", "0.17");
settings->setDefault("joystick_frustum_sensitivity", "170");
diff --git a/src/game.h b/src/game.h
index 19992ce3d..eaedca165 100644
--- a/src/game.h
+++ b/src/game.h
@@ -171,4 +171,3 @@ void the_game(bool *kill,
bool simple_singleplayer_mode);
#endif
-