163 changes: 163 additions & 0 deletions src/client/joystick_controller.h
Original file line number Diff line number Diff line change
@@ -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
85 changes: 85 additions & 0 deletions src/client/keys.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
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 KEYS_HEADER
#define KEYS_HEADER

#include<list>

class KeyType {
public:
enum T {
// Player movement
FORWARD,
BACKWARD,
LEFT,
RIGHT,
JUMP,
SPECIAL1,
SNEAK,
AUTORUN,

ESC,

// Other
DROP,
INVENTORY,
CHAT,
CMD,
CONSOLE,
MINIMAP,
FREEMOVE,
FASTMOVE,
NOCLIP,
CINEMATIC,
SCREENSHOT,
TOGGLE_HUD,
TOGGLE_CHAT,
TOGGLE_FORCE_FOG_OFF,
TOGGLE_UPDATE_CAMERA,
TOGGLE_DEBUG,
TOGGLE_PROFILER,
CAMERA_MODE,
INCREASE_VIEWING_RANGE,
DECREASE_VIEWING_RANGE,
RANGESELECT,

QUICKTUNE_NEXT,
QUICKTUNE_PREV,
QUICKTUNE_INC,
QUICKTUNE_DEC,

DEBUG_STACKS,

// joystick specific keys
MOUSE_L,
MOUSE_R,
SCROLL_UP,
SCROLL_DOWN,

// Fake keycode for array size and internal checks
INTERNAL_ENUM_COUNT

};
};

typedef KeyType::T GameKeyType;


#endif
4 changes: 3 additions & 1 deletion src/content_cao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,9 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
PlayerControl controls = player->getPlayerControl();

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;

f32 new_speed = player->local_animation_speed;
Expand Down
3 changes: 3 additions & 0 deletions src/defaultsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ void set_default_settings(Settings *settings)
settings->setDefault("free_move", "false");
settings->setDefault("noclip", "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("camera_smoothing", "0");
settings->setDefault("cinematic_camera_smoothing", "0.7");
Expand Down
410 changes: 227 additions & 183 deletions src/game.cpp

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#include "irrlichttypes_extrabloated.h"
#include <string>
#include "client/keys.h"
#include "client/joystick_controller.h"
#include "keycode.h"
#include <list>

Expand Down Expand Up @@ -134,6 +136,8 @@ class InputHandler
virtual void step(float dtime) {}

virtual void clear() {}

JoystickController joystick;
};

class ChatBackend; /* to avoid having to include chat.h */
Expand Down
2 changes: 2 additions & 0 deletions src/guiEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ void MenuMusicFetcher::fetchSounds(const std::string &name,
/** GUIEngine */
/******************************************************************************/
GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
JoystickController *joystick,
gui::IGUIElement* parent,
IMenuManager *menumgr,
scene::ISceneManager* smgr,
Expand Down Expand Up @@ -187,6 +188,7 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,

/* Create menu */
m_menu = new GUIFormSpecMenu(m_device,
joystick,
m_parent,
-1,
m_menumanager,
Expand Down
3 changes: 2 additions & 1 deletion src/guiEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ class GUIEngine {
* @param smgr scene manager to add scene elements to
* @param data struct to transfer data to main game handling
*/
GUIEngine( irr::IrrlichtDevice* dev,
GUIEngine(irr::IrrlichtDevice* dev,
JoystickController *joystick,
gui::IGUIElement* parent,
IMenuManager *menumgr,
scene::ISceneManager* smgr,
Expand Down
42 changes: 34 additions & 8 deletions src/guiFormSpecMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ static unsigned int font_line_height(gui::IGUIFont *font)
}

GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
JoystickController *joystick,
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
InventoryManager *invmgr, IGameDef *gamedef,
ISimpleTextureSource *tsrc, IFormSource* fsrc, TextDest* tdst,
Expand All @@ -101,6 +102,7 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
m_text_dst(tdst),
m_formspec_version(0),
m_focused_element(""),
m_joystick(joystick),
m_font(NULL),
m_remap_dbl_click(remap_dbl_click)
#ifdef __ANDROID__
Expand Down Expand Up @@ -2490,7 +2492,7 @@ void GUIFormSpecMenu::drawMenu()
Draw static text elements
*/
for (u32 i = 0; i < m_static_texts.size(); i++) {
const StaticTextSpec &spec = m_static_texts[i];
const StaticTextSpec &spec = m_static_texts[i];
core::rect<s32> rect = spec.rect;
if (spec.parent_button && spec.parent_button->isPressed()) {
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
Expand Down Expand Up @@ -3053,6 +3055,25 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
}
#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;
}

Expand Down Expand Up @@ -3114,19 +3135,24 @@ bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event)
return false;
}

void GUIFormSpecMenu::tryClose()
{
if (m_allowclose) {
doPause = false;
acceptInput(quit_mode_cancel);
quitMenu();
} else {
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))) {
if (m_allowclose) {
doPause = false;
acceptInput(quit_mode_cancel);
quitMenu();
} else {
m_text_dst->gotText(L"MenuQuit");
}
tryClose();
return true;
} else if (m_client != NULL && event.KeyInput.PressedDown &&
(kp == getKeySetting("keymap_screenshot"))) {
Expand Down
13 changes: 9 additions & 4 deletions src/guiFormSpecMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "modalMenu.h"
#include "guiTable.h"
#include "network/networkprotocol.h"
#include "client/joystick_controller.h"
#include "util/string.h"

class IGameDef;
Expand Down Expand Up @@ -273,6 +274,7 @@ class GUIFormSpecMenu : public GUIModalMenu

public:
GUIFormSpecMenu(irr::IrrlichtDevice* dev,
JoystickController *joystick,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
InventoryManager *invmgr,
Expand Down Expand Up @@ -428,10 +430,11 @@ class GUIFormSpecMenu : public GUIModalMenu
video::SColor m_default_tooltip_color;

private:
IFormSource *m_form_src;
TextDest *m_text_dst;
unsigned int m_formspec_version;
std::string m_focused_element;
IFormSource *m_form_src;
TextDest *m_text_dst;
unsigned int m_formspec_version;
std::string m_focused_element;
JoystickController *m_joystick;

typedef struct {
bool explicit_size;
Expand Down Expand Up @@ -489,6 +492,8 @@ class GUIFormSpecMenu : public GUIModalMenu
bool parseSizeDirect(parserData* data, std::string element);
void parseScrollBar(parserData* data, std::string element);

void tryClose();

/**
* check if event is part of a double click
* @param event event to evaluate
Expand Down
17 changes: 11 additions & 6 deletions src/localplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,18 +528,23 @@ void LocalPlayer::applyControl(float dtime)
speedH += move_direction;
}
}
if(control.down)
{
if (control.down) {
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));
}
if(control.right)
{
if (control.right) {
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 (free_move) {
Expand Down
10 changes: 9 additions & 1 deletion src/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ struct PlayerControl
RMB = false;
pitch = 0;
yaw = 0;
sidew_move_joystick_axis = .0f;
forw_move_joystick_axis = .0f;
}
PlayerControl(
bool a_up,
Expand All @@ -58,7 +60,9 @@ struct PlayerControl
bool a_LMB,
bool a_RMB,
float a_pitch,
float a_yaw
float a_yaw,
float a_sidew_move_joystick_axis,
float a_forw_move_joystick_axis
)
{
up = a_up;
Expand All @@ -72,6 +76,8 @@ struct PlayerControl
RMB = a_RMB;
pitch = a_pitch;
yaw = a_yaw;
sidew_move_joystick_axis = a_sidew_move_joystick_axis;
forw_move_joystick_axis = a_forw_move_joystick_axis;
}
bool up;
bool down;
Expand All @@ -84,6 +90,8 @@ struct PlayerControl
bool RMB;
float pitch;
float yaw;
float sidew_move_joystick_axis;
float forw_move_joystick_axis;
};

class Map;
Expand Down