mirror of
https://github.com/moparisthebest/minetest
synced 2024-12-22 15:48:48 -05:00
Initial Gamepad support
Adds initial ingame gamepad support to minetest. Full Formspec support is not implemented yet and can be added by a later change.
This commit is contained in:
parent
1e86c89f36
commit
2060fd9cbe
@ -104,6 +104,17 @@ random_input (Random input) bool false
|
|||||||
# Continuous forward movement (only used for testing).
|
# Continuous forward movement (only used for testing).
|
||||||
continuous_forward (Continuous forward) bool false
|
continuous_forward (Continuous forward) bool false
|
||||||
|
|
||||||
|
# Enable Joysticks
|
||||||
|
enable_joysticks (Enable Joysticks) bool true
|
||||||
|
|
||||||
|
# The time in seconds it takes between repeated events
|
||||||
|
# when holding down a joystick button combination.
|
||||||
|
repeat_joystick_button_time (Joystick button repetition invterval) float 0.17
|
||||||
|
|
||||||
|
# The sensitivity of the joystick axes for moving the
|
||||||
|
# ingame view frustum around.
|
||||||
|
joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170
|
||||||
|
|
||||||
# Key for moving the player forward.
|
# Key for moving the player forward.
|
||||||
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3
|
||||||
keymap_forward (Forward key) key KEY_KEY_W
|
keymap_forward (Forward key) key KEY_KEY_W
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
set(client_SRCS
|
set(client_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/joystick_controller.cpp
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "guiEngine.h"
|
#include "guiEngine.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "fontengine.h"
|
#include "fontengine.h"
|
||||||
|
#include "joystick_controller.h"
|
||||||
#include "clientlauncher.h"
|
#include "clientlauncher.h"
|
||||||
|
|
||||||
/* mainmenumanager.h
|
/* mainmenumanager.h
|
||||||
@ -499,7 +500,8 @@ void ClientLauncher::main_menu(MainMenuData *menudata)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* show main menu */
|
/* show main menu */
|
||||||
GUIEngine mymenu(device, guiroot, &g_menumgr, smgr, menudata, *kill);
|
GUIEngine mymenu(device, &input->joystick, guiroot,
|
||||||
|
&g_menumgr, smgr, menudata, *kill);
|
||||||
|
|
||||||
smgr->clear(); /* leave scene manager in a clean state */
|
smgr->clear(); /* leave scene manager in a clean state */
|
||||||
}
|
}
|
||||||
@ -558,6 +560,22 @@ bool ClientLauncher::create_engine_device()
|
|||||||
device = createDeviceEx(params);
|
device = createDeviceEx(params);
|
||||||
|
|
||||||
if (device) {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
porting::initIrrlicht(device);
|
porting::initIrrlicht(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define INPUT_HANDLER_H
|
#define INPUT_HANDLER_H
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#include "joystick_controller.h"
|
||||||
|
|
||||||
class MyEventReceiver : public IEventReceiver
|
class MyEventReceiver : public IEventReceiver
|
||||||
{
|
{
|
||||||
@ -62,6 +63,14 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) {
|
||||||
|
/* TODO add a check like:
|
||||||
|
if (event.JoystickEvent != joystick_we_listen_for)
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
|
return joystick->handleEvent(event.JoystickEvent);
|
||||||
|
}
|
||||||
// handle mouse events
|
// handle mouse events
|
||||||
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
|
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
|
||||||
if (noMenuActive() == false) {
|
if (noMenuActive() == false) {
|
||||||
@ -172,6 +181,8 @@ public:
|
|||||||
|
|
||||||
s32 mouse_wheel;
|
s32 mouse_wheel;
|
||||||
|
|
||||||
|
JoystickController *joystick;
|
||||||
|
|
||||||
#ifdef HAVE_TOUCHSCREENGUI
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
TouchScreenGUI* m_touchscreengui;
|
TouchScreenGUI* m_touchscreengui;
|
||||||
#endif
|
#endif
|
||||||
@ -202,6 +213,7 @@ public:
|
|||||||
m_receiver(receiver),
|
m_receiver(receiver),
|
||||||
m_mousepos(0,0)
|
m_mousepos(0,0)
|
||||||
{
|
{
|
||||||
|
m_receiver->joystick = &joystick;
|
||||||
}
|
}
|
||||||
virtual bool isKeyDown(const KeyPress &keyCode)
|
virtual bool isKeyDown(const KeyPress &keyCode)
|
||||||
{
|
{
|
||||||
@ -288,6 +300,7 @@ public:
|
|||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
|
joystick.clear();
|
||||||
m_receiver->clearInput();
|
m_receiver->clearInput();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
179
src/client/joystick_controller.cpp
Normal file
179
src/client/joystick_controller.cpp
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2016 est31, <MTest31@outlook.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "joystick_controller.h"
|
||||||
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#include "keys.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "gettime.h"
|
||||||
|
|
||||||
|
bool JoystickButtonCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
|
||||||
|
{
|
||||||
|
u32 buttons = ev.ButtonStates;
|
||||||
|
|
||||||
|
buttons &= filter_mask;
|
||||||
|
return buttons == compare_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JoystickAxisCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const
|
||||||
|
{
|
||||||
|
s16 ax_val = ev.Axis[axis_to_compare];
|
||||||
|
|
||||||
|
return (ax_val * direction < 0) && (thresh * direction > ax_val * direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// spares many characters
|
||||||
|
#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 jlo;
|
||||||
|
|
||||||
|
jlo.axes_dead_border = 1024;
|
||||||
|
|
||||||
|
const JoystickAxisLayout axes[JA_COUNT] = {
|
||||||
|
{0, 1}, // JA_SIDEWARD_MOVE
|
||||||
|
{1, 1}, // JA_FORWARD_MOVE
|
||||||
|
{3, 1}, // JA_FRUSTUM_HORIZONTAL
|
||||||
|
{4, 1}, // JA_FRUSTUM_VERTICAL
|
||||||
|
};
|
||||||
|
memcpy(jlo.axes, axes, sizeof(jlo.axes));
|
||||||
|
|
||||||
|
u32 sb = 1 << 7; // START button mask
|
||||||
|
u32 fb = 1 << 3; // FOUR button mask
|
||||||
|
u32 bm = sb | fb; // Mask for Both Modifiers
|
||||||
|
|
||||||
|
// The back button means "ESC".
|
||||||
|
JLO_B_PB(KeyType::ESC, 1 << 6, 1 << 6);
|
||||||
|
|
||||||
|
// The start button counts as modifier as well as use key.
|
||||||
|
// JLO_B_PB(KeyType::USE, sb, sb));
|
||||||
|
|
||||||
|
// Accessible without start modifier button pressed
|
||||||
|
// regardless whether four is pressed or not
|
||||||
|
JLO_B_PB(KeyType::SNEAK, sb | 1 << 2, 1 << 2);
|
||||||
|
|
||||||
|
// Accessible without four modifier button pressed
|
||||||
|
// regardless whether start is pressed or not
|
||||||
|
JLO_B_PB(KeyType::MOUSE_L, fb | 1 << 4, 1 << 4);
|
||||||
|
JLO_B_PB(KeyType::MOUSE_R, fb | 1 << 5, 1 << 5);
|
||||||
|
|
||||||
|
// Accessible without any modifier pressed
|
||||||
|
JLO_B_PB(KeyType::JUMP, bm | 1 << 0, 1 << 0);
|
||||||
|
JLO_B_PB(KeyType::SPECIAL1, bm | 1 << 1, 1 << 1);
|
||||||
|
|
||||||
|
// Accessible with start button not pressed, but four pressed
|
||||||
|
// TODO find usage for button 0
|
||||||
|
JLO_B_PB(KeyType::DROP, bm | 1 << 1, fb | 1 << 1);
|
||||||
|
JLO_B_PB(KeyType::SCROLL_UP, bm | 1 << 4, fb | 1 << 4);
|
||||||
|
JLO_B_PB(KeyType::SCROLL_DOWN,bm | 1 << 5, fb | 1 << 5);
|
||||||
|
|
||||||
|
// Accessible with start button and four pressed
|
||||||
|
// TODO find usage for buttons 0, 1 and 4, 5
|
||||||
|
|
||||||
|
// Now about the buttons simulated by the axes
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Scroll buttons
|
||||||
|
JLO_A_PB(KeyType::SCROLL_UP, 2, -1, 1024);
|
||||||
|
JLO_A_PB(KeyType::SCROLL_DOWN, 5, -1, 1024);
|
||||||
|
|
||||||
|
return jlo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JoystickLayout default_layout = create_default_layout();
|
||||||
|
|
||||||
|
JoystickController::JoystickController()
|
||||||
|
{
|
||||||
|
m_layout = &default_layout;
|
||||||
|
doubling_dtime = g_settings->getFloat("repeat_joystick_button_time");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
|
||||||
|
m_past_pressed_time[i] = 0;
|
||||||
|
}
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
|
||||||
|
{
|
||||||
|
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->axis_keys.size(); i++) {
|
||||||
|
if (m_layout->axis_keys[i].isTriggered(ev)) {
|
||||||
|
keys_pressed.set(m_layout->axis_keys[i].key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then update the values
|
||||||
|
|
||||||
|
for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
|
||||||
|
if (keys_pressed[i]) {
|
||||||
|
if (!m_past_pressed_keys[i] &&
|
||||||
|
m_past_pressed_time[i] < m_internal_time - doubling_dtime) {
|
||||||
|
m_past_pressed_keys[i] = true;
|
||||||
|
m_past_pressed_time[i] = m_internal_time;
|
||||||
|
}
|
||||||
|
} else if (m_pressed_keys[i]) {
|
||||||
|
m_past_released_keys[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pressed_keys[i] = keys_pressed[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < JA_COUNT; i++) {
|
||||||
|
const JoystickAxisLayout &ax_la = m_layout->axes[i];
|
||||||
|
m_axes_vals[i] = ax_la.invert * ev.Axis[ax_la.axis_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoystickController::clear()
|
||||||
|
{
|
||||||
|
m_pressed_keys.reset();
|
||||||
|
m_past_pressed_keys.reset();
|
||||||
|
m_past_released_keys.reset();
|
||||||
|
memset(m_axes_vals, 0, sizeof(m_axes_vals));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)))
|
||||||
|
return 0;
|
||||||
|
return v;
|
||||||
|
}
|
163
src/client/joystick_controller.h
Normal file
163
src/client/joystick_controller.h
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2016 est31, <MTest31@outlook.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JOYSTICK_HEADER
|
||||||
|
#define JOYSTICK_HEADER
|
||||||
|
|
||||||
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#include "keys.h"
|
||||||
|
#include <bitset>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum JoystickAxis {
|
||||||
|
JA_SIDEWARD_MOVE,
|
||||||
|
JA_FORWARD_MOVE,
|
||||||
|
|
||||||
|
JA_FRUSTUM_HORIZONTAL,
|
||||||
|
JA_FRUSTUM_VERTICAL,
|
||||||
|
|
||||||
|
// To know the count of enum values
|
||||||
|
JA_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JoystickAxisLayout {
|
||||||
|
u16 axis_id;
|
||||||
|
// -1 if to invert, 1 if to keep it.
|
||||||
|
int invert;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct JoystickCombination {
|
||||||
|
|
||||||
|
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const=0;
|
||||||
|
|
||||||
|
GameKeyType key;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JoystickButtonCmb : public JoystickCombination {
|
||||||
|
|
||||||
|
JoystickButtonCmb() {}
|
||||||
|
JoystickButtonCmb(GameKeyType key, u32 filter_mask, u32 compare_mask) :
|
||||||
|
filter_mask(filter_mask),
|
||||||
|
compare_mask(compare_mask)
|
||||||
|
{
|
||||||
|
this->key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const;
|
||||||
|
|
||||||
|
u32 filter_mask;
|
||||||
|
u32 compare_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JoystickAxisCmb : public JoystickCombination {
|
||||||
|
|
||||||
|
JoystickAxisCmb() {}
|
||||||
|
JoystickAxisCmb(GameKeyType key, u16 axis_to_compare, int direction, s16 thresh) :
|
||||||
|
axis_to_compare(axis_to_compare),
|
||||||
|
direction(direction),
|
||||||
|
thresh(thresh)
|
||||||
|
{
|
||||||
|
this->key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const;
|
||||||
|
|
||||||
|
u16 axis_to_compare;
|
||||||
|
|
||||||
|
// if -1, thresh must be smaller than the axis value in order to trigger
|
||||||
|
// if 1, thresh must be bigger than the axis value in order to trigger
|
||||||
|
int direction;
|
||||||
|
s16 thresh;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JoystickLayout {
|
||||||
|
std::vector<JoystickButtonCmb> button_keys;
|
||||||
|
std::vector<JoystickAxisCmb> axis_keys;
|
||||||
|
JoystickAxisLayout axes[JA_COUNT];
|
||||||
|
s16 axes_dead_border;
|
||||||
|
};
|
||||||
|
|
||||||
|
class JoystickController {
|
||||||
|
|
||||||
|
public:
|
||||||
|
JoystickController();
|
||||||
|
bool handleEvent(const irr::SEvent::SJoystickEvent &ev);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
bool wasKeyDown(GameKeyType b)
|
||||||
|
{
|
||||||
|
bool r = m_past_pressed_keys[b];
|
||||||
|
m_past_pressed_keys[b] = false;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
bool getWasKeyDown(GameKeyType b)
|
||||||
|
{
|
||||||
|
return m_past_pressed_keys[b];
|
||||||
|
}
|
||||||
|
void clearWasKeyDown(GameKeyType b)
|
||||||
|
{
|
||||||
|
m_past_pressed_keys[b] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wasKeyReleased(GameKeyType b)
|
||||||
|
{
|
||||||
|
bool r = m_past_released_keys[b];
|
||||||
|
m_past_released_keys[b] = false;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
bool getWasKeyReleased(GameKeyType b)
|
||||||
|
{
|
||||||
|
return m_past_pressed_keys[b];
|
||||||
|
}
|
||||||
|
void clearWasKeyReleased(GameKeyType b)
|
||||||
|
{
|
||||||
|
m_past_pressed_keys[b] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isKeyDown(GameKeyType b)
|
||||||
|
{
|
||||||
|
return m_pressed_keys[b];
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 getAxis(JoystickAxis axis)
|
||||||
|
{
|
||||||
|
return m_axes_vals[axis];
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 getAxisWithoutDead(JoystickAxis axis);
|
||||||
|
|
||||||
|
f32 doubling_dtime;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const JoystickLayout *m_layout;
|
||||||
|
|
||||||
|
s16 m_axes_vals[JA_COUNT];
|
||||||
|
|
||||||
|
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_pressed_keys;
|
||||||
|
|
||||||
|
f32 m_internal_time;
|
||||||
|
|
||||||
|
f32 m_past_pressed_time[KeyType::INTERNAL_ENUM_COUNT];
|
||||||
|
|
||||||
|
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_past_pressed_keys;
|
||||||
|
std::bitset<KeyType::INTERNAL_ENUM_COUNT> m_past_released_keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -67,6 +67,12 @@ public:
|
|||||||
|
|
||||||
DEBUG_STACKS,
|
DEBUG_STACKS,
|
||||||
|
|
||||||
|
// joystick specific keys
|
||||||
|
MOUSE_L,
|
||||||
|
MOUSE_R,
|
||||||
|
SCROLL_UP,
|
||||||
|
SCROLL_DOWN,
|
||||||
|
|
||||||
// Fake keycode for array size and internal checks
|
// Fake keycode for array size and internal checks
|
||||||
INTERNAL_ENUM_COUNT
|
INTERNAL_ENUM_COUNT
|
||||||
|
|
||||||
|
@ -1056,7 +1056,9 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
|
|||||||
PlayerControl controls = player->getPlayerControl();
|
PlayerControl controls = player->getPlayerControl();
|
||||||
|
|
||||||
bool walking = false;
|
bool walking = false;
|
||||||
if(controls.up || controls.down || controls.left || controls.right)
|
if (controls.up || controls.down || controls.left || controls.right ||
|
||||||
|
controls.forw_move_joystick_axis != 0.f ||
|
||||||
|
controls.sidew_move_joystick_axis != 0.f)
|
||||||
walking = true;
|
walking = true;
|
||||||
|
|
||||||
f32 new_speed = player->local_animation_speed;
|
f32 new_speed = player->local_animation_speed;
|
||||||
|
@ -116,6 +116,9 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("free_move", "false");
|
settings->setDefault("free_move", "false");
|
||||||
settings->setDefault("noclip", "false");
|
settings->setDefault("noclip", "false");
|
||||||
settings->setDefault("continuous_forward", "false");
|
settings->setDefault("continuous_forward", "false");
|
||||||
|
settings->setDefault("enable_joysticks", "true");
|
||||||
|
settings->setDefault("repeat_joystick_button_time", "0.17");
|
||||||
|
settings->setDefault("joystick_frustum_sensitivity", "170");
|
||||||
settings->setDefault("cinematic", "false");
|
settings->setDefault("cinematic", "false");
|
||||||
settings->setDefault("camera_smoothing", "0");
|
settings->setDefault("camera_smoothing", "0");
|
||||||
settings->setDefault("cinematic_camera_smoothing", "0.7");
|
settings->setDefault("cinematic_camera_smoothing", "0.7");
|
||||||
|
155
src/game.cpp
155
src/game.cpp
@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "client/tile.h" // For TextureSource
|
#include "client/tile.h" // For TextureSource
|
||||||
#include "client/keys.h"
|
#include "client/keys.h"
|
||||||
|
#include "client/joystick_controller.h"
|
||||||
#include "clientmap.h"
|
#include "clientmap.h"
|
||||||
#include "clouds.h"
|
#include "clouds.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -1108,12 +1109,14 @@ bool nodePlacementPrediction(Client &client,
|
|||||||
static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec,
|
static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec,
|
||||||
InventoryManager *invmgr, IGameDef *gamedef,
|
InventoryManager *invmgr, IGameDef *gamedef,
|
||||||
IWritableTextureSource *tsrc, IrrlichtDevice *device,
|
IWritableTextureSource *tsrc, IrrlichtDevice *device,
|
||||||
|
JoystickController *joystick,
|
||||||
IFormSource *fs_src, TextDest *txt_dest, Client *client)
|
IFormSource *fs_src, TextDest *txt_dest, Client *client)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (*cur_formspec == 0) {
|
if (*cur_formspec == 0) {
|
||||||
*cur_formspec = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr,
|
*cur_formspec = new GUIFormSpecMenu(device, joystick,
|
||||||
invmgr, gamedef, tsrc, fs_src, txt_dest, client);
|
guiroot, -1, &g_menumgr, invmgr, gamedef, tsrc,
|
||||||
|
fs_src, txt_dest, client);
|
||||||
(*cur_formspec)->doPause = false;
|
(*cur_formspec)->doPause = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1138,7 +1141,8 @@ static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec,
|
|||||||
|
|
||||||
static void show_deathscreen(GUIFormSpecMenu **cur_formspec,
|
static void show_deathscreen(GUIFormSpecMenu **cur_formspec,
|
||||||
InventoryManager *invmgr, IGameDef *gamedef,
|
InventoryManager *invmgr, IGameDef *gamedef,
|
||||||
IWritableTextureSource *tsrc, IrrlichtDevice *device, Client *client)
|
IWritableTextureSource *tsrc, IrrlichtDevice *device,
|
||||||
|
JoystickController *joystick, Client *client)
|
||||||
{
|
{
|
||||||
std::string formspec =
|
std::string formspec =
|
||||||
std::string(FORMSPEC_VERSION_STRING) +
|
std::string(FORMSPEC_VERSION_STRING) +
|
||||||
@ -1154,14 +1158,15 @@ static void show_deathscreen(GUIFormSpecMenu **cur_formspec,
|
|||||||
FormspecFormSource *fs_src = new FormspecFormSource(formspec);
|
FormspecFormSource *fs_src = new FormspecFormSource(formspec);
|
||||||
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client);
|
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client);
|
||||||
|
|
||||||
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
|
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device,
|
||||||
|
joystick, fs_src, txt_dst, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
|
static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
|
||||||
InventoryManager *invmgr, IGameDef *gamedef,
|
InventoryManager *invmgr, IGameDef *gamedef,
|
||||||
IWritableTextureSource *tsrc, IrrlichtDevice *device,
|
IWritableTextureSource *tsrc, IrrlichtDevice *device,
|
||||||
bool singleplayermode)
|
JoystickController *joystick, bool singleplayermode)
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
std::string control_text = strgettext("Default Controls:\n"
|
std::string control_text = strgettext("Default Controls:\n"
|
||||||
@ -1226,7 +1231,8 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
|
|||||||
FormspecFormSource *fs_src = new FormspecFormSource(os.str());
|
FormspecFormSource *fs_src = new FormspecFormSource(os.str());
|
||||||
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
|
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
|
||||||
|
|
||||||
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
|
create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device,
|
||||||
|
joystick, fs_src, txt_dst, NULL);
|
||||||
std::string con("btn_continue");
|
std::string con("btn_continue");
|
||||||
(*cur_formspec)->setFocus(con);
|
(*cur_formspec)->setFocus(con);
|
||||||
(*cur_formspec)->doPause = true;
|
(*cur_formspec)->doPause = true;
|
||||||
@ -1574,9 +1580,10 @@ protected:
|
|||||||
void decreaseViewRange(float *statustext_time);
|
void decreaseViewRange(float *statustext_time);
|
||||||
void toggleFullViewRange(float *statustext_time);
|
void toggleFullViewRange(float *statustext_time);
|
||||||
|
|
||||||
void updateCameraDirection(CameraOrientation *cam, VolatileRunFlags *flags);
|
void updateCameraDirection(CameraOrientation *cam, VolatileRunFlags *flags,
|
||||||
|
float dtime);
|
||||||
void updateCameraOrientation(CameraOrientation *cam,
|
void updateCameraOrientation(CameraOrientation *cam,
|
||||||
const VolatileRunFlags &flags);
|
const VolatileRunFlags &flags, float dtime);
|
||||||
void updatePlayerControl(const CameraOrientation &cam);
|
void updatePlayerControl(const CameraOrientation &cam);
|
||||||
void step(f32 *dtime);
|
void step(f32 *dtime);
|
||||||
void processClientEvents(CameraOrientation *cam, float *damage_flash);
|
void processClientEvents(CameraOrientation *cam, float *damage_flash);
|
||||||
@ -1611,34 +1618,39 @@ protected:
|
|||||||
static void settingChangedCallback(const std::string &setting_name, void *data);
|
static void settingChangedCallback(const std::string &setting_name, void *data);
|
||||||
void readSettings();
|
void readSettings();
|
||||||
|
|
||||||
bool getLeftClicked()
|
inline bool getLeftClicked()
|
||||||
{
|
{
|
||||||
return input->getLeftClicked();
|
return input->getLeftClicked() ||
|
||||||
|
input->joystick.getWasKeyDown(KeyType::MOUSE_L);
|
||||||
}
|
}
|
||||||
bool getRightClicked()
|
inline bool getRightClicked()
|
||||||
{
|
{
|
||||||
return input->getRightClicked();
|
return input->getRightClicked() ||
|
||||||
|
input->joystick.getWasKeyDown(KeyType::MOUSE_R);
|
||||||
}
|
}
|
||||||
bool isLeftPressed()
|
inline bool isLeftPressed()
|
||||||
{
|
{
|
||||||
return input->getLeftState();
|
return input->getLeftState() ||
|
||||||
|
input->joystick.isKeyDown(KeyType::MOUSE_L);
|
||||||
}
|
}
|
||||||
bool isRightPressed()
|
inline bool isRightPressed()
|
||||||
{
|
{
|
||||||
return input->getRightState();
|
return input->getRightState() ||
|
||||||
|
input->joystick.isKeyDown(KeyType::MOUSE_R);
|
||||||
}
|
}
|
||||||
bool getLeftReleased()
|
inline bool getLeftReleased()
|
||||||
{
|
{
|
||||||
return input->getLeftReleased();
|
return input->getLeftReleased() ||
|
||||||
|
input->joystick.wasKeyReleased(KeyType::MOUSE_L);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isKeyDown(GameKeyType k)
|
inline bool isKeyDown(GameKeyType k)
|
||||||
{
|
{
|
||||||
return input->isKeyDown(keycache.key[k]);
|
return input->isKeyDown(keycache.key[k]) || input->joystick.isKeyDown(k);
|
||||||
}
|
}
|
||||||
bool wasKeyDown(GameKeyType k)
|
inline bool wasKeyDown(GameKeyType k)
|
||||||
{
|
{
|
||||||
return input->wasKeyDown(keycache.key[k]);
|
return input->wasKeyDown(keycache.key[k]) || input->joystick.wasKeyDown(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
@ -1724,9 +1736,11 @@ private:
|
|||||||
*/
|
*/
|
||||||
bool m_cache_doubletap_jump;
|
bool m_cache_doubletap_jump;
|
||||||
bool m_cache_enable_clouds;
|
bool m_cache_enable_clouds;
|
||||||
|
bool m_cache_enable_joysticks;
|
||||||
bool m_cache_enable_particles;
|
bool m_cache_enable_particles;
|
||||||
bool m_cache_enable_fog;
|
bool m_cache_enable_fog;
|
||||||
f32 m_cache_mouse_sensitivity;
|
f32 m_cache_mouse_sensitivity;
|
||||||
|
f32 m_cache_joystick_frustum_sensitivity;
|
||||||
f32 m_repeat_right_click_time;
|
f32 m_repeat_right_click_time;
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
@ -1762,12 +1776,16 @@ Game::Game() :
|
|||||||
&settingChangedCallback, this);
|
&settingChangedCallback, this);
|
||||||
g_settings->registerChangedCallback("enable_clouds",
|
g_settings->registerChangedCallback("enable_clouds",
|
||||||
&settingChangedCallback, this);
|
&settingChangedCallback, this);
|
||||||
|
g_settings->registerChangedCallback("doubletap_joysticks",
|
||||||
|
&settingChangedCallback, this);
|
||||||
g_settings->registerChangedCallback("enable_particles",
|
g_settings->registerChangedCallback("enable_particles",
|
||||||
&settingChangedCallback, this);
|
&settingChangedCallback, this);
|
||||||
g_settings->registerChangedCallback("enable_fog",
|
g_settings->registerChangedCallback("enable_fog",
|
||||||
&settingChangedCallback, this);
|
&settingChangedCallback, this);
|
||||||
g_settings->registerChangedCallback("mouse_sensitivity",
|
g_settings->registerChangedCallback("mouse_sensitivity",
|
||||||
&settingChangedCallback, this);
|
&settingChangedCallback, this);
|
||||||
|
g_settings->registerChangedCallback("joystick_frustum_sensitivity",
|
||||||
|
&settingChangedCallback, this);
|
||||||
g_settings->registerChangedCallback("repeat_rightclick_time",
|
g_settings->registerChangedCallback("repeat_rightclick_time",
|
||||||
&settingChangedCallback, this);
|
&settingChangedCallback, this);
|
||||||
|
|
||||||
@ -1930,7 +1948,7 @@ void Game::run()
|
|||||||
updateProfilers(runData, stats, draw_times, dtime);
|
updateProfilers(runData, stats, draw_times, dtime);
|
||||||
processUserInput(&flags, &runData, dtime);
|
processUserInput(&flags, &runData, dtime);
|
||||||
// Update camera before player movement to avoid camera lag of one frame
|
// Update camera before player movement to avoid camera lag of one frame
|
||||||
updateCameraDirection(&cam_view_target, &flags);
|
updateCameraDirection(&cam_view_target, &flags, dtime);
|
||||||
float cam_smoothing = 0;
|
float cam_smoothing = 0;
|
||||||
if (g_settings->getBool("cinematic"))
|
if (g_settings->getBool("cinematic"))
|
||||||
cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing");
|
cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing");
|
||||||
@ -2727,7 +2745,8 @@ void Game::processKeyInput(VolatileRunFlags *flags,
|
|||||||
} else if (wasKeyDown(KeyType::ESC) || input->wasKeyDown(CancelKey)) {
|
} else if (wasKeyDown(KeyType::ESC) || input->wasKeyDown(CancelKey)) {
|
||||||
if (!gui_chat_console->isOpenInhibited()) {
|
if (!gui_chat_console->isOpenInhibited()) {
|
||||||
show_pause_menu(¤t_formspec, client, gamedef,
|
show_pause_menu(¤t_formspec, client, gamedef,
|
||||||
texture_src, device, simple_singleplayer_mode);
|
texture_src, device, &input->joystick,
|
||||||
|
simple_singleplayer_mode);
|
||||||
}
|
}
|
||||||
} else if (wasKeyDown(KeyType::CHAT)) {
|
} else if (wasKeyDown(KeyType::CHAT)) {
|
||||||
openConsole(0.2, L"");
|
openConsole(0.2, L"");
|
||||||
@ -2813,12 +2832,21 @@ void Game::processItemSelection(u16 *new_playeritem)
|
|||||||
u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1,
|
u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1,
|
||||||
player->hud_hotbar_itemcount - 1);
|
player->hud_hotbar_itemcount - 1);
|
||||||
|
|
||||||
if (wheel < 0)
|
s32 dir = wheel;
|
||||||
*new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0;
|
|
||||||
else if (wheel > 0)
|
|
||||||
*new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item;
|
|
||||||
// else wheel == 0
|
|
||||||
|
|
||||||
|
if (input->joystick.wasKeyDown(KeyType::SCROLL_DOWN)) {
|
||||||
|
dir = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input->joystick.wasKeyDown(KeyType::SCROLL_UP)) {
|
||||||
|
dir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir < 0)
|
||||||
|
*new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0;
|
||||||
|
else if (dir > 0)
|
||||||
|
*new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item;
|
||||||
|
// else dir == 0
|
||||||
|
|
||||||
/* Item selection using keyboard
|
/* Item selection using keyboard
|
||||||
*/
|
*/
|
||||||
@ -2868,7 +2896,7 @@ void Game::openInventory()
|
|||||||
TextDest *txt_dst = new TextDestPlayerInventory(client);
|
TextDest *txt_dst = new TextDestPlayerInventory(client);
|
||||||
|
|
||||||
create_formspec_menu(¤t_formspec, client, gamedef, texture_src,
|
create_formspec_menu(¤t_formspec, client, gamedef, texture_src,
|
||||||
device, fs_src, txt_dst, client);
|
device, &input->joystick, fs_src, txt_dst, client);
|
||||||
|
|
||||||
InventoryLocation inventoryloc;
|
InventoryLocation inventoryloc;
|
||||||
inventoryloc.setCurrentPlayer();
|
inventoryloc.setCurrentPlayer();
|
||||||
@ -3154,7 +3182,7 @@ void Game::toggleFullViewRange(float *statustext_time)
|
|||||||
|
|
||||||
|
|
||||||
void Game::updateCameraDirection(CameraOrientation *cam,
|
void Game::updateCameraDirection(CameraOrientation *cam,
|
||||||
VolatileRunFlags *flags)
|
VolatileRunFlags *flags, float dtime)
|
||||||
{
|
{
|
||||||
if ((device->isWindowActive() && noMenuActive()) || random_input) {
|
if ((device->isWindowActive() && noMenuActive()) || random_input) {
|
||||||
|
|
||||||
@ -3169,7 +3197,7 @@ void Game::updateCameraDirection(CameraOrientation *cam,
|
|||||||
if (flags->first_loop_after_window_activation)
|
if (flags->first_loop_after_window_activation)
|
||||||
flags->first_loop_after_window_activation = false;
|
flags->first_loop_after_window_activation = false;
|
||||||
else
|
else
|
||||||
updateCameraOrientation(cam, *flags);
|
updateCameraOrientation(cam, *flags, dtime);
|
||||||
|
|
||||||
input->setMousePos((driver->getScreenSize().Width / 2),
|
input->setMousePos((driver->getScreenSize().Width / 2),
|
||||||
(driver->getScreenSize().Height / 2));
|
(driver->getScreenSize().Height / 2));
|
||||||
@ -3187,9 +3215,8 @@ void Game::updateCameraDirection(CameraOrientation *cam,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Game::updateCameraOrientation(CameraOrientation *cam,
|
void Game::updateCameraOrientation(CameraOrientation *cam,
|
||||||
const VolatileRunFlags &flags)
|
const VolatileRunFlags &flags, float dtime)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_TOUCHSCREENGUI
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
if (g_touchscreengui) {
|
if (g_touchscreengui) {
|
||||||
@ -3197,6 +3224,7 @@ void Game::updateCameraOrientation(CameraOrientation *cam,
|
|||||||
cam->camera_pitch = g_touchscreengui->getPitch();
|
cam->camera_pitch = g_touchscreengui->getPitch();
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s32 dx = input->getMousePos().X - (driver->getScreenSize().Width / 2);
|
s32 dx = input->getMousePos().X - (driver->getScreenSize().Width / 2);
|
||||||
s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height / 2);
|
s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height / 2);
|
||||||
|
|
||||||
@ -3212,6 +3240,14 @@ void Game::updateCameraOrientation(CameraOrientation *cam,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (m_cache_enable_joysticks) {
|
||||||
|
f32 c = m_cache_joystick_frustum_sensitivity * (1.f / 32767.f) * dtime;
|
||||||
|
cam->camera_yaw -= input->joystick.getAxisWithoutDead(JA_FRUSTUM_HORIZONTAL) *
|
||||||
|
c;
|
||||||
|
cam->camera_pitch += input->joystick.getAxisWithoutDead(JA_FRUSTUM_VERTICAL) *
|
||||||
|
c;
|
||||||
|
}
|
||||||
|
|
||||||
cam->camera_pitch = rangelim(cam->camera_pitch, -89.5, 89.5);
|
cam->camera_pitch = rangelim(cam->camera_pitch, -89.5, 89.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3220,30 +3256,36 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
|
|||||||
{
|
{
|
||||||
//TimeTaker tt("update player control", NULL, PRECISION_NANO);
|
//TimeTaker tt("update player control", NULL, PRECISION_NANO);
|
||||||
|
|
||||||
|
// DO NOT use the isKeyDown method for the forward, backward, left, right
|
||||||
|
// buttons, as the code that uses the controls needs to be able to
|
||||||
|
// distinguish between the two in order to know when to use joysticks.
|
||||||
|
|
||||||
PlayerControl control(
|
PlayerControl control(
|
||||||
input->isKeyDown(keycache.key[KeyType::FORWARD]),
|
input->isKeyDown(keycache.key[KeyType::FORWARD]),
|
||||||
input->isKeyDown(keycache.key[KeyType::BACKWARD]),
|
input->isKeyDown(keycache.key[KeyType::BACKWARD]),
|
||||||
input->isKeyDown(keycache.key[KeyType::LEFT]),
|
input->isKeyDown(keycache.key[KeyType::LEFT]),
|
||||||
input->isKeyDown(keycache.key[KeyType::RIGHT]),
|
input->isKeyDown(keycache.key[KeyType::RIGHT]),
|
||||||
input->isKeyDown(keycache.key[KeyType::JUMP]),
|
isKeyDown(KeyType::JUMP),
|
||||||
input->isKeyDown(keycache.key[KeyType::SPECIAL1]),
|
isKeyDown(KeyType::SPECIAL1),
|
||||||
input->isKeyDown(keycache.key[KeyType::SNEAK]),
|
isKeyDown(KeyType::SNEAK),
|
||||||
input->getLeftState(),
|
isLeftPressed(),
|
||||||
input->getRightState(),
|
isRightPressed(),
|
||||||
cam.camera_pitch,
|
cam.camera_pitch,
|
||||||
cam.camera_yaw
|
cam.camera_yaw,
|
||||||
|
input->joystick.getAxisWithoutDead(JA_SIDEWARD_MOVE),
|
||||||
|
input->joystick.getAxisWithoutDead(JA_FORWARD_MOVE)
|
||||||
);
|
);
|
||||||
|
|
||||||
u32 keypress_bits =
|
u32 keypress_bits =
|
||||||
( (u32)(input->isKeyDown(keycache.key[KeyType::FORWARD]) & 0x1) << 0) |
|
( (u32)(isKeyDown(KeyType::FORWARD) & 0x1) << 0) |
|
||||||
( (u32)(input->isKeyDown(keycache.key[KeyType::BACKWARD]) & 0x1) << 1) |
|
( (u32)(isKeyDown(KeyType::BACKWARD) & 0x1) << 1) |
|
||||||
( (u32)(input->isKeyDown(keycache.key[KeyType::LEFT]) & 0x1) << 2) |
|
( (u32)(isKeyDown(KeyType::LEFT) & 0x1) << 2) |
|
||||||
( (u32)(input->isKeyDown(keycache.key[KeyType::RIGHT]) & 0x1) << 3) |
|
( (u32)(isKeyDown(KeyType::RIGHT) & 0x1) << 3) |
|
||||||
( (u32)(input->isKeyDown(keycache.key[KeyType::JUMP]) & 0x1) << 4) |
|
( (u32)(isKeyDown(KeyType::JUMP) & 0x1) << 4) |
|
||||||
( (u32)(input->isKeyDown(keycache.key[KeyType::SPECIAL1]) & 0x1) << 5) |
|
( (u32)(isKeyDown(KeyType::SPECIAL1) & 0x1) << 5) |
|
||||||
( (u32)(input->isKeyDown(keycache.key[KeyType::SNEAK]) & 0x1) << 6) |
|
( (u32)(isKeyDown(KeyType::SNEAK) & 0x1) << 6) |
|
||||||
( (u32)(input->getLeftState() & 0x1) << 7) |
|
( (u32)(isLeftPressed() & 0x1) << 7) |
|
||||||
( (u32)(input->getRightState() & 0x1) << 8
|
( (u32)(isRightPressed() & 0x1) << 8
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
@ -3312,7 +3354,7 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash)
|
|||||||
cam->camera_pitch = event.player_force_move.pitch;
|
cam->camera_pitch = event.player_force_move.pitch;
|
||||||
} else if (event.type == CE_DEATHSCREEN) {
|
} else if (event.type == CE_DEATHSCREEN) {
|
||||||
show_deathscreen(¤t_formspec, client, gamedef, texture_src,
|
show_deathscreen(¤t_formspec, client, gamedef, texture_src,
|
||||||
device, client);
|
device, &input->joystick, client);
|
||||||
|
|
||||||
chat_backend->addMessage(L"", L"You died.");
|
chat_backend->addMessage(L"", L"You died.");
|
||||||
|
|
||||||
@ -3328,7 +3370,8 @@ void Game::processClientEvents(CameraOrientation *cam, float *damage_flash)
|
|||||||
new TextDestPlayerInventory(client, *(event.show_formspec.formname));
|
new TextDestPlayerInventory(client, *(event.show_formspec.formname));
|
||||||
|
|
||||||
create_formspec_menu(¤t_formspec, client, gamedef,
|
create_formspec_menu(¤t_formspec, client, gamedef,
|
||||||
texture_src, device, fs_src, txt_dst, client);
|
texture_src, device, &input->joystick,
|
||||||
|
fs_src, txt_dst, client);
|
||||||
|
|
||||||
delete(event.show_formspec.formspec);
|
delete(event.show_formspec.formspec);
|
||||||
delete(event.show_formspec.formname);
|
delete(event.show_formspec.formname);
|
||||||
@ -3723,8 +3766,14 @@ void Game::processPlayerInteraction(GameRunData *runData,
|
|||||||
input->resetLeftClicked();
|
input->resetLeftClicked();
|
||||||
input->resetRightClicked();
|
input->resetRightClicked();
|
||||||
|
|
||||||
|
input->joystick.clearWasKeyDown(KeyType::MOUSE_L);
|
||||||
|
input->joystick.clearWasKeyDown(KeyType::MOUSE_R);
|
||||||
|
|
||||||
input->resetLeftReleased();
|
input->resetLeftReleased();
|
||||||
input->resetRightReleased();
|
input->resetRightReleased();
|
||||||
|
|
||||||
|
input->joystick.clearWasKeyReleased(KeyType::MOUSE_L);
|
||||||
|
input->joystick.clearWasKeyReleased(KeyType::MOUSE_R);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3785,7 +3834,7 @@ void Game::handlePointingAtNode(GameRunData *runData,
|
|||||||
TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client);
|
TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client);
|
||||||
|
|
||||||
create_formspec_menu(¤t_formspec, client, gamedef,
|
create_formspec_menu(¤t_formspec, client, gamedef,
|
||||||
texture_src, device, fs_src, txt_dst, client);
|
texture_src, device, &input->joystick, fs_src, txt_dst, client);
|
||||||
|
|
||||||
current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
|
current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
|
||||||
} else {
|
} else {
|
||||||
@ -4470,9 +4519,11 @@ void Game::readSettings()
|
|||||||
{
|
{
|
||||||
m_cache_doubletap_jump = g_settings->getBool("doubletap_jump");
|
m_cache_doubletap_jump = g_settings->getBool("doubletap_jump");
|
||||||
m_cache_enable_clouds = g_settings->getBool("enable_clouds");
|
m_cache_enable_clouds = g_settings->getBool("enable_clouds");
|
||||||
|
m_cache_enable_joysticks = g_settings->getBool("enable_joysticks");
|
||||||
m_cache_enable_particles = g_settings->getBool("enable_particles");
|
m_cache_enable_particles = g_settings->getBool("enable_particles");
|
||||||
m_cache_enable_fog = g_settings->getBool("enable_fog");
|
m_cache_enable_fog = g_settings->getBool("enable_fog");
|
||||||
m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity");
|
m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity");
|
||||||
|
m_cache_joystick_frustum_sensitivity = g_settings->getFloat("joystick_frustum_sensitivity");
|
||||||
m_repeat_right_click_time = g_settings->getFloat("repeat_rightclick_time");
|
m_repeat_right_click_time = g_settings->getFloat("repeat_rightclick_time");
|
||||||
|
|
||||||
m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0);
|
m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0);
|
||||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "client/keys.h"
|
#include "client/keys.h"
|
||||||
|
#include "client/joystick_controller.h"
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
@ -135,6 +136,8 @@ public:
|
|||||||
virtual void step(float dtime) {}
|
virtual void step(float dtime) {}
|
||||||
|
|
||||||
virtual void clear() {}
|
virtual void clear() {}
|
||||||
|
|
||||||
|
JoystickController joystick;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChatBackend; /* to avoid having to include chat.h */
|
class ChatBackend; /* to avoid having to include chat.h */
|
||||||
|
@ -131,6 +131,7 @@ void MenuMusicFetcher::fetchSounds(const std::string &name,
|
|||||||
/** GUIEngine */
|
/** GUIEngine */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
|
GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
|
||||||
|
JoystickController *joystick,
|
||||||
gui::IGUIElement* parent,
|
gui::IGUIElement* parent,
|
||||||
IMenuManager *menumgr,
|
IMenuManager *menumgr,
|
||||||
scene::ISceneManager* smgr,
|
scene::ISceneManager* smgr,
|
||||||
@ -189,6 +190,7 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
|
|||||||
|
|
||||||
/* Create menu */
|
/* Create menu */
|
||||||
m_menu = new GUIFormSpecMenu(m_device,
|
m_menu = new GUIFormSpecMenu(m_device,
|
||||||
|
joystick,
|
||||||
m_parent,
|
m_parent,
|
||||||
-1,
|
-1,
|
||||||
m_menumanager,
|
m_menumanager,
|
||||||
|
@ -150,6 +150,7 @@ public:
|
|||||||
* @param data struct to transfer data to main game handling
|
* @param data struct to transfer data to main game handling
|
||||||
*/
|
*/
|
||||||
GUIEngine(irr::IrrlichtDevice* dev,
|
GUIEngine(irr::IrrlichtDevice* dev,
|
||||||
|
JoystickController *joystick,
|
||||||
gui::IGUIElement* parent,
|
gui::IGUIElement* parent,
|
||||||
IMenuManager *menumgr,
|
IMenuManager *menumgr,
|
||||||
scene::ISceneManager* smgr,
|
scene::ISceneManager* smgr,
|
||||||
|
@ -79,6 +79,7 @@ static unsigned int font_line_height(gui::IGUIFont *font)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
||||||
|
JoystickController *joystick,
|
||||||
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
|
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
|
||||||
InventoryManager *invmgr, IGameDef *gamedef,
|
InventoryManager *invmgr, IGameDef *gamedef,
|
||||||
ISimpleTextureSource *tsrc, IFormSource* fsrc, TextDest* tdst,
|
ISimpleTextureSource *tsrc, IFormSource* fsrc, TextDest* tdst,
|
||||||
@ -102,6 +103,7 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
|||||||
m_text_dst(tdst),
|
m_text_dst(tdst),
|
||||||
m_formspec_version(0),
|
m_formspec_version(0),
|
||||||
m_focused_element(""),
|
m_focused_element(""),
|
||||||
|
m_joystick(joystick),
|
||||||
m_font(NULL),
|
m_font(NULL),
|
||||||
m_remap_dbl_click(remap_dbl_click)
|
m_remap_dbl_click(remap_dbl_click)
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
@ -3024,6 +3026,25 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) {
|
||||||
|
/* TODO add a check like:
|
||||||
|
if (event.JoystickEvent != joystick_we_listen_for)
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
|
bool handled = m_joystick->handleEvent(event.JoystickEvent);
|
||||||
|
if (handled) {
|
||||||
|
if (m_joystick->wasKeyDown(KeyType::ESC)) {
|
||||||
|
tryClose();
|
||||||
|
} else if (m_joystick->wasKeyDown(KeyType::JUMP)) {
|
||||||
|
if (m_allowclose) {
|
||||||
|
acceptInput(quit_mode_accept);
|
||||||
|
quitMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3085,12 +3106,8 @@ bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
void GUIFormSpecMenu::tryClose()
|
||||||
{
|
{
|
||||||
if (event.EventType==EET_KEY_INPUT_EVENT) {
|
|
||||||
KeyPress kp(event.KeyInput);
|
|
||||||
if (event.KeyInput.PressedDown && ( (kp == EscapeKey) ||
|
|
||||||
(kp == getKeySetting("keymap_inventory")) || (kp == CancelKey))) {
|
|
||||||
if (m_allowclose) {
|
if (m_allowclose) {
|
||||||
doPause = false;
|
doPause = false;
|
||||||
acceptInput(quit_mode_cancel);
|
acceptInput(quit_mode_cancel);
|
||||||
@ -3098,6 +3115,15 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
|||||||
} else {
|
} else {
|
||||||
m_text_dst->gotText(L"MenuQuit");
|
m_text_dst->gotText(L"MenuQuit");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
||||||
|
{
|
||||||
|
if (event.EventType==EET_KEY_INPUT_EVENT) {
|
||||||
|
KeyPress kp(event.KeyInput);
|
||||||
|
if (event.KeyInput.PressedDown && ( (kp == EscapeKey) ||
|
||||||
|
(kp == getKeySetting("keymap_inventory")) || (kp == CancelKey))) {
|
||||||
|
tryClose();
|
||||||
return true;
|
return true;
|
||||||
} else if (m_client != NULL && event.KeyInput.PressedDown &&
|
} else if (m_client != NULL && event.KeyInput.PressedDown &&
|
||||||
(kp == getKeySetting("keymap_screenshot"))) {
|
(kp == getKeySetting("keymap_screenshot"))) {
|
||||||
|
@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "modalMenu.h"
|
#include "modalMenu.h"
|
||||||
#include "guiTable.h"
|
#include "guiTable.h"
|
||||||
#include "network/networkprotocol.h"
|
#include "network/networkprotocol.h"
|
||||||
|
#include "client/joystick_controller.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/enriched_string.h"
|
#include "util/enriched_string.h"
|
||||||
|
|
||||||
@ -278,6 +279,7 @@ class GUIFormSpecMenu : public GUIModalMenu
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
||||||
|
JoystickController *joystick,
|
||||||
gui::IGUIElement* parent, s32 id,
|
gui::IGUIElement* parent, s32 id,
|
||||||
IMenuManager *menumgr,
|
IMenuManager *menumgr,
|
||||||
InventoryManager *invmgr,
|
InventoryManager *invmgr,
|
||||||
@ -437,6 +439,7 @@ private:
|
|||||||
TextDest *m_text_dst;
|
TextDest *m_text_dst;
|
||||||
unsigned int m_formspec_version;
|
unsigned int m_formspec_version;
|
||||||
std::string m_focused_element;
|
std::string m_focused_element;
|
||||||
|
JoystickController *m_joystick;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool explicit_size;
|
bool explicit_size;
|
||||||
@ -494,6 +497,8 @@ private:
|
|||||||
bool parseSizeDirect(parserData* data, std::string element);
|
bool parseSizeDirect(parserData* data, std::string element);
|
||||||
void parseScrollBar(parserData* data, std::string element);
|
void parseScrollBar(parserData* data, std::string element);
|
||||||
|
|
||||||
|
void tryClose();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if event is part of a double click
|
* check if event is part of a double click
|
||||||
* @param event event to evaluate
|
* @param event event to evaluate
|
||||||
|
@ -528,18 +528,23 @@ void LocalPlayer::applyControl(float dtime)
|
|||||||
speedH += move_direction;
|
speedH += move_direction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(control.down)
|
if (control.down) {
|
||||||
{
|
|
||||||
speedH -= move_direction;
|
speedH -= move_direction;
|
||||||
}
|
}
|
||||||
if(control.left)
|
if (!control.up && !control.down) {
|
||||||
{
|
speedH -= move_direction *
|
||||||
|
(control.forw_move_joystick_axis / 32767.f);
|
||||||
|
}
|
||||||
|
if (control.left) {
|
||||||
speedH += move_direction.crossProduct(v3f(0,1,0));
|
speedH += move_direction.crossProduct(v3f(0,1,0));
|
||||||
}
|
}
|
||||||
if(control.right)
|
if (control.right) {
|
||||||
{
|
|
||||||
speedH += move_direction.crossProduct(v3f(0,-1,0));
|
speedH += move_direction.crossProduct(v3f(0,-1,0));
|
||||||
}
|
}
|
||||||
|
if (!control.left && !control.right) {
|
||||||
|
speedH -= move_direction.crossProduct(v3f(0,1,0)) *
|
||||||
|
(control.sidew_move_joystick_axis / 32767.f);
|
||||||
|
}
|
||||||
if(control.jump)
|
if(control.jump)
|
||||||
{
|
{
|
||||||
if (free_move) {
|
if (free_move) {
|
||||||
|
10
src/player.h
10
src/player.h
@ -46,6 +46,8 @@ struct PlayerControl
|
|||||||
RMB = false;
|
RMB = false;
|
||||||
pitch = 0;
|
pitch = 0;
|
||||||
yaw = 0;
|
yaw = 0;
|
||||||
|
sidew_move_joystick_axis = .0f;
|
||||||
|
forw_move_joystick_axis = .0f;
|
||||||
}
|
}
|
||||||
PlayerControl(
|
PlayerControl(
|
||||||
bool a_up,
|
bool a_up,
|
||||||
@ -58,7 +60,9 @@ struct PlayerControl
|
|||||||
bool a_LMB,
|
bool a_LMB,
|
||||||
bool a_RMB,
|
bool a_RMB,
|
||||||
float a_pitch,
|
float a_pitch,
|
||||||
float a_yaw
|
float a_yaw,
|
||||||
|
float a_sidew_move_joystick_axis,
|
||||||
|
float a_forw_move_joystick_axis
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
up = a_up;
|
up = a_up;
|
||||||
@ -72,6 +76,8 @@ struct PlayerControl
|
|||||||
RMB = a_RMB;
|
RMB = a_RMB;
|
||||||
pitch = a_pitch;
|
pitch = a_pitch;
|
||||||
yaw = a_yaw;
|
yaw = a_yaw;
|
||||||
|
sidew_move_joystick_axis = a_sidew_move_joystick_axis;
|
||||||
|
forw_move_joystick_axis = a_forw_move_joystick_axis;
|
||||||
}
|
}
|
||||||
bool up;
|
bool up;
|
||||||
bool down;
|
bool down;
|
||||||
@ -84,6 +90,8 @@ struct PlayerControl
|
|||||||
bool RMB;
|
bool RMB;
|
||||||
float pitch;
|
float pitch;
|
||||||
float yaw;
|
float yaw;
|
||||||
|
float sidew_move_joystick_axis;
|
||||||
|
float forw_move_joystick_axis;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
|
Loading…
Reference in New Issue
Block a user