mirror of https://github.com/minetest/minetest.git
Merge 6ec32dee84
into d767ab0890
This commit is contained in:
commit
70854e5b4b
|
@ -150,6 +150,25 @@ enable_hotbar_mouse_wheel (Hotbar: Enable mouse wheel for selection) bool true
|
||||||
# Requires: keyboard_mouse
|
# Requires: keyboard_mouse
|
||||||
invert_hotbar_mouse_wheel (Hotbar: Invert mouse wheel direction) bool false
|
invert_hotbar_mouse_wheel (Hotbar: Invert mouse wheel direction) bool false
|
||||||
|
|
||||||
|
[*Gamepads]
|
||||||
|
|
||||||
|
# Enable joysticks. Requires a restart to take effect
|
||||||
|
enable_joysticks (Enable joysticks) bool true
|
||||||
|
|
||||||
|
# The identifier of the joystick to use
|
||||||
|
joystick_id (Joystick ID) int 0 0 255
|
||||||
|
|
||||||
|
# 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 0.001
|
||||||
|
|
||||||
|
# The dead zone of the joystick
|
||||||
|
joystick_deadzone (Joystick dead zone) int 8000 0 65535
|
||||||
|
|
||||||
|
# The sensitivity of the joystick axes for moving the
|
||||||
|
# in-game view frustum around.
|
||||||
|
joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170.0 0.001
|
||||||
|
|
||||||
[*Touchscreen]
|
[*Touchscreen]
|
||||||
|
|
||||||
# Enables touchscreen mode, allowing you to play the game with a touchscreen.
|
# Enables touchscreen mode, allowing you to play the game with a touchscreen.
|
||||||
|
@ -2222,29 +2241,6 @@ enable_remote_media_server (Connect to external media server) bool true
|
||||||
serverlist_file (Serverlist file) string favoriteservers.json
|
serverlist_file (Serverlist file) string favoriteservers.json
|
||||||
|
|
||||||
|
|
||||||
[*Gamepads]
|
|
||||||
|
|
||||||
# Enable joysticks. Requires a restart to take effect
|
|
||||||
enable_joysticks (Enable joysticks) bool false
|
|
||||||
|
|
||||||
# The identifier of the joystick to use
|
|
||||||
joystick_id (Joystick ID) int 0 0 255
|
|
||||||
|
|
||||||
# The type of joystick
|
|
||||||
joystick_type (Joystick type) enum auto auto,generic,xbox,dragonrise_gamecube
|
|
||||||
|
|
||||||
# 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 0.001
|
|
||||||
|
|
||||||
# The dead zone of the joystick
|
|
||||||
joystick_deadzone (Joystick dead zone) int 2048 0 65535
|
|
||||||
|
|
||||||
# The sensitivity of the joystick axes for moving the
|
|
||||||
# in-game view frustum around.
|
|
||||||
joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170.0 0.001
|
|
||||||
|
|
||||||
|
|
||||||
[*Hide: Temporary Settings]
|
[*Hide: Temporary Settings]
|
||||||
|
|
||||||
# Path to texture directory. All textures are first searched from here.
|
# Path to texture directory. All textures are first searched from here.
|
||||||
|
|
|
@ -3171,7 +3171,7 @@
|
||||||
|
|
||||||
# The dead zone of the joystick
|
# The dead zone of the joystick
|
||||||
# type: int min: 0 max: 65535
|
# type: int min: 0 max: 65535
|
||||||
# joystick_deadzone = 2048
|
# joystick_deadzone = 8000
|
||||||
|
|
||||||
# The sensitivity of the joystick axes for moving the
|
# The sensitivity of the joystick axes for moving the
|
||||||
# in-game view frustum around.
|
# in-game view frustum around.
|
||||||
|
|
|
@ -54,9 +54,9 @@ set(client_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiscalingfilter.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/guiscalingfilter.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hud.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/hud.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/imagefilters.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/imagefilters.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/inputhandler.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/input/inputhandler.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/joystick_controller.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/input/gamepad_controller.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/keycode.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/input/keycode.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/localplayer.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/localplayer.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mapblock_mesh.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/mapblock_mesh.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
|
||||||
|
|
|
@ -306,22 +306,7 @@ void ClientLauncher::init_input()
|
||||||
input = new RealInputHandler(receiver);
|
input = new RealInputHandler(receiver);
|
||||||
|
|
||||||
if (g_settings->getBool("enable_joysticks")) {
|
if (g_settings->getBool("enable_joysticks")) {
|
||||||
irr::core::array<irr::SJoystickInfo> infos;
|
input->joystick.connectToJoystick();
|
||||||
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 (m_rendering_engine->get_raw_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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
#include "client/inputhandler.h"
|
#include "client/input/inputhandler.h"
|
||||||
#include "gameparams.h"
|
#include "gameparams.h"
|
||||||
|
|
||||||
class RenderingEngine;
|
class RenderingEngine;
|
||||||
|
|
|
@ -26,10 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "client/clientevent.h"
|
#include "client/clientevent.h"
|
||||||
#include "client/gameui.h"
|
#include "client/gameui.h"
|
||||||
#include "client/inputhandler.h"
|
#include "client/input/inputhandler.h"
|
||||||
#include "client/texturepaths.h"
|
#include "client/texturepaths.h"
|
||||||
#include "client/keys.h"
|
#include "client/input/keys.h"
|
||||||
#include "client/joystick_controller.h"
|
#include "client/input/gamepad_controller.h"
|
||||||
#include "client/mapblock_mesh.h"
|
#include "client/mapblock_mesh.h"
|
||||||
#include "client/sound.h"
|
#include "client/sound.h"
|
||||||
#include "clientmap.h"
|
#include "clientmap.h"
|
||||||
|
@ -1185,6 +1185,14 @@ void Game::run()
|
||||||
|
|
||||||
m_game_ui->clearInfoText();
|
m_game_ui->clearInfoText();
|
||||||
|
|
||||||
|
input->joystick.update(dtime, isMenuActive());
|
||||||
|
if (isMenuActive()) {
|
||||||
|
v2f32 look = input->joystick.getLookRotation();
|
||||||
|
|
||||||
|
auto cursor = device->getCursorControl();
|
||||||
|
cursor->setPosition(cursor->getPosition() + v2s32(-1000 * dtime * look.X, 1000 * dtime * look.Y));
|
||||||
|
}
|
||||||
|
|
||||||
updateProfilers(stats, draw_times, dtime);
|
updateProfilers(stats, draw_times, dtime);
|
||||||
processUserInput(dtime);
|
processUserInput(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
|
||||||
|
@ -1983,7 +1991,8 @@ void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
|
||||||
void Game::processUserInput(f32 dtime)
|
void Game::processUserInput(f32 dtime)
|
||||||
{
|
{
|
||||||
// Reset input if window not active or some menu is active
|
// Reset input if window not active or some menu is active
|
||||||
if (!device->isWindowActive() || isMenuActive() || guienv->hasFocus(gui_chat_console)) {
|
input->isInMenu = !device->isWindowActive() || isMenuActive() || guienv->hasFocus(gui_chat_console);
|
||||||
|
if (input->isInMenu) {
|
||||||
if (m_game_focused) {
|
if (m_game_focused) {
|
||||||
m_game_focused = false;
|
m_game_focused = false;
|
||||||
infostream << "Game lost focus" << std::endl;
|
infostream << "Game lost focus" << std::endl;
|
||||||
|
@ -2663,8 +2672,10 @@ void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
|
||||||
if (m_cache_enable_joysticks) {
|
if (m_cache_enable_joysticks) {
|
||||||
f32 sens_scale = getSensitivityScaleFactor();
|
f32 sens_scale = getSensitivityScaleFactor();
|
||||||
f32 c = m_cache_joystick_frustum_sensitivity * dtime * sens_scale;
|
f32 c = m_cache_joystick_frustum_sensitivity * dtime * sens_scale;
|
||||||
cam->camera_yaw -= input->joystick.getAxisWithoutDead(JA_FRUSTUM_HORIZONTAL) * c;
|
|
||||||
cam->camera_pitch += input->joystick.getAxisWithoutDead(JA_FRUSTUM_VERTICAL) * c;
|
auto look_rotation = input->joystick.getLookRotation() * c;
|
||||||
|
cam->camera_yaw += look_rotation.X;
|
||||||
|
cam->camera_pitch += look_rotation.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
cam->camera_pitch = rangelim(cam->camera_pitch, -89.5, 89.5);
|
cam->camera_pitch = rangelim(cam->camera_pitch, -89.5, 89.5);
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2016 est31, <MTest31@outlook.com>
|
||||||
|
Copyright (C) 2022 rubenwardy
|
||||||
|
|
||||||
|
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 "gamepad_controller.h"
|
||||||
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#include "keys.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "porting.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
#include "util/numeric.h"
|
||||||
|
|
||||||
|
|
||||||
|
class GamepadInputButton : public GamepadInput
|
||||||
|
{
|
||||||
|
SDL_GameControllerButton button;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GamepadInputButton(SDL_GameControllerButton button): button(button) {}
|
||||||
|
|
||||||
|
~GamepadInputButton() override = default;
|
||||||
|
bool operator()(SDL_GameController *gameController) const override {
|
||||||
|
return SDL_GameControllerGetButton(gameController, button);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GamepadInputAxis : public GamepadInput
|
||||||
|
{
|
||||||
|
SDL_GameControllerAxis axis;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GamepadInputAxis(SDL_GameControllerAxis axis): axis(axis) {}
|
||||||
|
|
||||||
|
~GamepadInputAxis() override = default;
|
||||||
|
bool operator()(SDL_GameController *gameController) const override {
|
||||||
|
return SDL_GameControllerGetAxis(gameController, axis) > 9000;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define BTN(button) std::make_unique<GamepadInputButton>(button)
|
||||||
|
#define AXIS(axis) std::make_unique<GamepadInputAxis>(axis)
|
||||||
|
|
||||||
|
|
||||||
|
GamepadController::GamepadController() :
|
||||||
|
doubling_dtime(std::max(g_settings->getFloat("repeat_joystick_button_time"), 0.001f))
|
||||||
|
{
|
||||||
|
for (float &i : m_past_pressed_time) {
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
clear();
|
||||||
|
|
||||||
|
m_layout.axes_deadzone = g_settings->getU16("joystick_deadzone");
|
||||||
|
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_BACK), KeyType::ESC );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_START), KeyType::ESC );
|
||||||
|
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_A), KeyType::JUMP );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_B), KeyType::ESC );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_X), KeyType::AUX1 );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_Y), KeyType::INVENTORY );
|
||||||
|
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_LEFTSTICK), KeyType::AUX1 );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_RIGHTSTICK), KeyType::SNEAK );
|
||||||
|
|
||||||
|
m_button_bindings.emplace_back( AXIS(SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_TRIGGERRIGHT), KeyType::DIG );
|
||||||
|
m_button_bindings.emplace_back( AXIS(SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_TRIGGERLEFT), KeyType::PLACE );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_LEFTSHOULDER), KeyType::HOTBAR_PREV );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), KeyType::HOTBAR_NEXT );
|
||||||
|
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_UP), KeyType::ZOOM );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_LEFT), KeyType::DROP );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_RIGHT), KeyType::SCREENSHOT );
|
||||||
|
m_button_bindings.emplace_back( BTN(SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_DPAD_DOWN), KeyType::FREEMOVE );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GamepadController::connectToJoystick()
|
||||||
|
{
|
||||||
|
s32 id = g_settings->getS32("joystick_id");
|
||||||
|
|
||||||
|
int joystick_count = SDL_NumJoysticks();
|
||||||
|
|
||||||
|
if (id < 0 || id >= joystick_count) {
|
||||||
|
id = 0;
|
||||||
|
|
||||||
|
for (int joystick_id = 0; joystick_id < joystick_count; joystick_id++) {
|
||||||
|
if (SDL_IsGameController(joystick_id)) {
|
||||||
|
id = joystick_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_joystick_id = id;
|
||||||
|
|
||||||
|
if (gameController)
|
||||||
|
SDL_GameControllerClose(gameController);
|
||||||
|
gameController = SDL_GameControllerOpen(m_joystick_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamepadController::update(float dtime, bool is_in_gui)
|
||||||
|
{
|
||||||
|
if (!gameController)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_internal_time = porting::getTimeMs() / 1000.f;
|
||||||
|
|
||||||
|
std::bitset<KeyType::INTERNAL_ENUM_COUNT> keys_pressed;
|
||||||
|
|
||||||
|
for (const auto &pair : m_button_bindings) {
|
||||||
|
if ((*pair.first)(gameController)) {
|
||||||
|
keys_pressed.set(pair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then update the values
|
||||||
|
|
||||||
|
for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
|
||||||
|
if (keys_pressed[i]) {
|
||||||
|
if (!m_past_keys_pressed[i] &&
|
||||||
|
m_past_pressed_time[i] < m_internal_time - doubling_dtime) {
|
||||||
|
m_past_keys_pressed[i] = true;
|
||||||
|
m_past_pressed_time[i] = m_internal_time;
|
||||||
|
}
|
||||||
|
} else if (m_keys_down[i]) {
|
||||||
|
m_keys_released[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keys_pressed[i] && !(m_keys_down[i]))
|
||||||
|
m_keys_pressed[i] = true;
|
||||||
|
|
||||||
|
m_keys_down[i] = keys_pressed[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GamepadController::handleEvent(const irr::SEvent::SJoystickEvent &ev)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamepadController::clear()
|
||||||
|
{
|
||||||
|
m_keys_pressed.reset();
|
||||||
|
m_keys_down.reset();
|
||||||
|
m_past_keys_pressed.reset();
|
||||||
|
m_keys_released.reset();
|
||||||
|
memset(m_axes_vals, 0, sizeof(m_axes_vals));
|
||||||
|
}
|
||||||
|
|
||||||
|
float GamepadController::getAxisWithoutDead(GamepadAxis axis)
|
||||||
|
{
|
||||||
|
SDL_GameControllerAxis sdlAxis;
|
||||||
|
switch (axis) {
|
||||||
|
case JA_SIDEWARD_MOVE:
|
||||||
|
sdlAxis = SDL_CONTROLLER_AXIS_LEFTX;
|
||||||
|
break;
|
||||||
|
case JA_FORWARD_MOVE:
|
||||||
|
sdlAxis = SDL_CONTROLLER_AXIS_LEFTY;
|
||||||
|
break;
|
||||||
|
case JA_FRUSTUM_HORIZONTAL:
|
||||||
|
sdlAxis = SDL_CONTROLLER_AXIS_RIGHTX;
|
||||||
|
break;
|
||||||
|
case JA_FRUSTUM_VERTICAL:
|
||||||
|
sdlAxis = SDL_CONTROLLER_AXIS_RIGHTY;
|
||||||
|
break;
|
||||||
|
case JA_COUNT:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 v = SDL_GameControllerGetAxis(gameController, sdlAxis);
|
||||||
|
if (abs(v) < m_layout.axes_deadzone)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
v += (v < 0 ? m_layout.axes_deadzone : -m_layout.axes_deadzone);
|
||||||
|
|
||||||
|
return (float)v / ((float)(INT16_MAX - m_layout.axes_deadzone));
|
||||||
|
}
|
||||||
|
|
||||||
|
float GamepadController::getMovementDirection()
|
||||||
|
{
|
||||||
|
return atan2(getAxisWithoutDead(JA_SIDEWARD_MOVE), -getAxisWithoutDead(JA_FORWARD_MOVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
float GamepadController::getMovementSpeed()
|
||||||
|
{
|
||||||
|
float speed = sqrt(pow(getAxisWithoutDead(JA_FORWARD_MOVE), 2) + pow(getAxisWithoutDead(JA_SIDEWARD_MOVE), 2));
|
||||||
|
if (speed > 1.0f)
|
||||||
|
speed = 1.0f;
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2f32 GamepadController::getLookRotation()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
-getAxisWithoutDead(JA_FRUSTUM_HORIZONTAL),
|
||||||
|
getAxisWithoutDead(JA_FRUSTUM_VERTICAL),
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Minetest
|
Minetest
|
||||||
Copyright (C) 2016 est31, <MTest31@outlook.com>
|
Copyright (C) 2016 est31, <MTest31@outlook.com>
|
||||||
|
Copyright (C) 2022 rubenwardy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -23,8 +24,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
enum JoystickAxis {
|
#include <SDL2/SDL_gamecontroller.h>
|
||||||
|
|
||||||
|
|
||||||
|
enum GamepadAxis
|
||||||
|
{
|
||||||
JA_SIDEWARD_MOVE,
|
JA_SIDEWARD_MOVE,
|
||||||
JA_FORWARD_MOVE,
|
JA_FORWARD_MOVE,
|
||||||
|
|
||||||
|
@ -35,77 +41,29 @@ enum JoystickAxis {
|
||||||
JA_COUNT,
|
JA_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JoystickAxisLayout {
|
|
||||||
u16 axis_id;
|
|
||||||
// -1 if to invert, 1 if to keep it.
|
|
||||||
int invert;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
struct GamepadLayout
|
||||||
struct JoystickCombination {
|
|
||||||
|
|
||||||
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const=0;
|
|
||||||
|
|
||||||
GameKeyType key;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct JoystickButtonCmb : public JoystickCombination {
|
|
||||||
|
|
||||||
JoystickButtonCmb() = default;
|
|
||||||
|
|
||||||
JoystickButtonCmb(GameKeyType key, u32 filter_mask, u32 compare_mask) :
|
|
||||||
filter_mask(filter_mask),
|
|
||||||
compare_mask(compare_mask)
|
|
||||||
{
|
{
|
||||||
this->key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~JoystickButtonCmb() = default;
|
|
||||||
|
|
||||||
virtual bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const;
|
|
||||||
|
|
||||||
u32 filter_mask;
|
|
||||||
u32 compare_mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct JoystickAxisCmb : public JoystickCombination {
|
|
||||||
|
|
||||||
JoystickAxisCmb() = default;
|
|
||||||
|
|
||||||
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 ~JoystickAxisCmb() = default;
|
|
||||||
|
|
||||||
bool isTriggered(const irr::SEvent::SJoystickEvent &ev) const override;
|
|
||||||
|
|
||||||
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_deadzone;
|
s16 axes_deadzone;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JoystickController {
|
|
||||||
|
|
||||||
|
class GamepadInput
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
JoystickController();
|
virtual ~GamepadInput() = default;
|
||||||
|
virtual bool operator()(SDL_GameController *gameController) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
void onJoystickConnect(const std::vector<irr::SJoystickInfo> &joystick_infos);
|
|
||||||
|
|
||||||
|
class GamepadController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GamepadController();
|
||||||
|
|
||||||
|
void connectToJoystick();
|
||||||
|
|
||||||
|
void update(float dtime, bool is_in_gui);
|
||||||
bool handleEvent(const irr::SEvent::SJoystickEvent &ev);
|
bool handleEvent(const irr::SEvent::SJoystickEvent &ev);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
@ -126,6 +84,7 @@ public:
|
||||||
{
|
{
|
||||||
return m_keys_released[b];
|
return m_keys_released[b];
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearWasKeyReleased(GameKeyType b)
|
void clearWasKeyReleased(GameKeyType b)
|
||||||
{
|
{
|
||||||
m_keys_released[b] = false;
|
m_keys_released[b] = false;
|
||||||
|
@ -135,6 +94,7 @@ public:
|
||||||
{
|
{
|
||||||
return m_keys_pressed[b];
|
return m_keys_pressed[b];
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearWasKeyPressed(GameKeyType b)
|
void clearWasKeyPressed(GameKeyType b)
|
||||||
{
|
{
|
||||||
m_keys_pressed[b] = false;
|
m_keys_pressed[b] = false;
|
||||||
|
@ -145,22 +105,19 @@ public:
|
||||||
return m_keys_down[b];
|
return m_keys_down[b];
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 getAxis(JoystickAxis axis)
|
|
||||||
{
|
|
||||||
return m_axes_vals[axis];
|
|
||||||
}
|
|
||||||
|
|
||||||
float getAxisWithoutDead(JoystickAxis axis);
|
|
||||||
|
|
||||||
float getMovementDirection();
|
float getMovementDirection();
|
||||||
float getMovementSpeed();
|
float getMovementSpeed();
|
||||||
|
v2f32 getLookRotation();
|
||||||
f32 doubling_dtime;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setLayoutFromControllerName(const std::string &name);
|
|
||||||
|
|
||||||
JoystickLayout m_layout;
|
float getAxisWithoutDead(GamepadAxis axis);
|
||||||
|
|
||||||
|
f32 doubling_dtime;
|
||||||
|
SDL_GameController *gameController = nullptr;
|
||||||
|
|
||||||
|
GamepadLayout m_layout;
|
||||||
|
std::vector<std::pair<std::unique_ptr<GamepadInput>, KeyType::T>> m_button_bindings;
|
||||||
|
|
||||||
s16 m_axes_vals[JA_COUNT];
|
s16 m_axes_vals[JA_COUNT];
|
||||||
|
|
|
@ -201,6 +201,10 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
|
||||||
*/
|
*/
|
||||||
float RealInputHandler::getMovementSpeed()
|
float RealInputHandler::getMovementSpeed()
|
||||||
{
|
{
|
||||||
|
if (isInMenu) {
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
bool f = m_receiver->IsKeyDown(keycache.key[KeyType::FORWARD]),
|
bool f = m_receiver->IsKeyDown(keycache.key[KeyType::FORWARD]),
|
||||||
b = m_receiver->IsKeyDown(keycache.key[KeyType::BACKWARD]),
|
b = m_receiver->IsKeyDown(keycache.key[KeyType::BACKWARD]),
|
||||||
l = m_receiver->IsKeyDown(keycache.key[KeyType::LEFT]),
|
l = m_receiver->IsKeyDown(keycache.key[KeyType::LEFT]),
|
|
@ -20,10 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
#include "joystick_controller.h"
|
#include "gamepad_controller.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
#include "renderingengine.h"
|
#include "client/renderingengine.h"
|
||||||
|
|
||||||
class InputHandler;
|
class InputHandler;
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ public:
|
||||||
keyWasReleased.clear();
|
keyWasReleased.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
JoystickController *joystick = nullptr;
|
GamepadController *joystick = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
s32 mouse_wheel = 0;
|
s32 mouse_wheel = 0;
|
||||||
|
@ -263,8 +263,9 @@ public:
|
||||||
virtual void clear() {}
|
virtual void clear() {}
|
||||||
virtual void releaseAllKeys() {}
|
virtual void releaseAllKeys() {}
|
||||||
|
|
||||||
JoystickController joystick;
|
GamepadController joystick;
|
||||||
KeyCache keycache;
|
KeyCache keycache;
|
||||||
|
bool isInMenu = false;
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
Separated input handler
|
Separated input handler
|
|
@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
#include "Keycodes.h"
|
#include "Keycodes.h"
|
||||||
#include <IEventReceiver.h>
|
#include "IEventReceiver.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class UnknownKeycode : public BaseException
|
class UnknownKeycode : public BaseException
|
|
@ -1,332 +0,0 @@
|
||||||
/*
|
|
||||||
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"
|
|
||||||
#include "porting.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
#include "util/numeric.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 < -thresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
// spares many characters
|
|
||||||
#define JLO_B_PB(A, B, C) jlo.button_keys.emplace_back(A, B, C)
|
|
||||||
#define JLO_A_PB(A, B, C, D) jlo.axis_keys.emplace_back(A, B, C, D)
|
|
||||||
|
|
||||||
JoystickLayout create_default_layout()
|
|
||||||
{
|
|
||||||
JoystickLayout jlo;
|
|
||||||
|
|
||||||
jlo.axes_deadzone = g_settings->getU16("joystick_deadzone");
|
|
||||||
|
|
||||||
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::DIG, fb | 1 << 4, 1 << 4);
|
|
||||||
JLO_B_PB(KeyType::PLACE, fb | 1 << 5, 1 << 5);
|
|
||||||
|
|
||||||
// Accessible without any modifier pressed
|
|
||||||
JLO_B_PB(KeyType::JUMP, bm | 1 << 0, 1 << 0);
|
|
||||||
JLO_B_PB(KeyType::AUX1, 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::HOTBAR_PREV, bm | 1 << 4, fb | 1 << 4);
|
|
||||||
JLO_B_PB(KeyType::HOTBAR_NEXT, 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, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone);
|
|
||||||
|
|
||||||
// Scroll buttons
|
|
||||||
JLO_A_PB(KeyType::HOTBAR_PREV, 2, -1, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, jlo.axes_deadzone);
|
|
||||||
|
|
||||||
return jlo;
|
|
||||||
}
|
|
||||||
|
|
||||||
JoystickLayout create_xbox_layout()
|
|
||||||
{
|
|
||||||
JoystickLayout jlo;
|
|
||||||
|
|
||||||
jlo.axes_deadzone = 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::AUX1, 1 << 2, 1 << 2); // X/blue
|
|
||||||
JLO_B_PB(KeyType::INVENTORY, 1 << 3, 1 << 3); // Y/yellow
|
|
||||||
|
|
||||||
// Analog Sticks
|
|
||||||
JLO_B_PB(KeyType::AUX1, 1 << 11, 1 << 11); // left
|
|
||||||
JLO_B_PB(KeyType::SNEAK, 1 << 12, 1 << 12); // right
|
|
||||||
|
|
||||||
// Triggers
|
|
||||||
JLO_B_PB(KeyType::DIG, 1 << 6, 1 << 6); // lt
|
|
||||||
JLO_B_PB(KeyType::PLACE, 1 << 7, 1 << 7); // rt
|
|
||||||
JLO_B_PB(KeyType::HOTBAR_PREV, 1 << 4, 1 << 4); // lb
|
|
||||||
JLO_B_PB(KeyType::HOTBAR_NEXT, 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, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone);
|
|
||||||
|
|
||||||
return jlo;
|
|
||||||
}
|
|
||||||
|
|
||||||
JoystickLayout create_dragonrise_gamecube_layout()
|
|
||||||
{
|
|
||||||
JoystickLayout jlo;
|
|
||||||
|
|
||||||
jlo.axes_deadzone = 7000;
|
|
||||||
|
|
||||||
const JoystickAxisLayout axes[JA_COUNT] = {
|
|
||||||
// Control Stick
|
|
||||||
{0, 1}, // JA_SIDEWARD_MOVE
|
|
||||||
{1, 1}, // JA_FORWARD_MOVE
|
|
||||||
|
|
||||||
// C-Stick
|
|
||||||
{3, 1}, // JA_FRUSTUM_HORIZONTAL
|
|
||||||
{4, 1}, // JA_FRUSTUM_VERTICAL
|
|
||||||
};
|
|
||||||
memcpy(jlo.axes, axes, sizeof(jlo.axes));
|
|
||||||
|
|
||||||
// The center button
|
|
||||||
JLO_B_PB(KeyType::ESC, 1 << 9, 1 << 9); // Start/Pause Button
|
|
||||||
|
|
||||||
// Front right buttons
|
|
||||||
JLO_B_PB(KeyType::JUMP, 1 << 2, 1 << 2); // A Button
|
|
||||||
JLO_B_PB(KeyType::SNEAK, 1 << 3, 1 << 3); // B Button
|
|
||||||
JLO_B_PB(KeyType::DROP, 1 << 0, 1 << 0); // Y Button
|
|
||||||
JLO_B_PB(KeyType::AUX1, 1 << 1, 1 << 1); // X Button
|
|
||||||
|
|
||||||
// Triggers
|
|
||||||
JLO_B_PB(KeyType::DIG, 1 << 4, 1 << 4); // L Trigger
|
|
||||||
JLO_B_PB(KeyType::PLACE, 1 << 5, 1 << 5); // R Trigger
|
|
||||||
JLO_B_PB(KeyType::INVENTORY, 1 << 6, 1 << 6); // Z Button
|
|
||||||
|
|
||||||
// D-Pad
|
|
||||||
JLO_A_PB(KeyType::HOTBAR_PREV, 5, 1, jlo.axes_deadzone); // left
|
|
||||||
JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, jlo.axes_deadzone); // right
|
|
||||||
// Axis are hard to actuate independently, best to leave up and down unused.
|
|
||||||
//JLO_A_PB(0, 6, 1, jlo.axes_deadzone); // up
|
|
||||||
//JLO_A_PB(0, 6, -1, jlo.axes_deadzone); // down
|
|
||||||
|
|
||||||
// Movements tied to Control Stick, important for vessels
|
|
||||||
JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::FORWARD, 1, 1, jlo.axes_deadzone);
|
|
||||||
JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone);
|
|
||||||
|
|
||||||
return jlo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
JoystickController::JoystickController()
|
|
||||||
{
|
|
||||||
doubling_dtime = std::max(g_settings->getFloat("repeat_joystick_button_time"), 0.001f);
|
|
||||||
for (float &i : m_past_pressed_time) {
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
m_layout.axes_deadzone = 0;
|
|
||||||
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 >= (s32)joystick_infos.size()) {
|
|
||||||
// TODO: auto detection
|
|
||||||
id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id >= 0 && id < (s32)joystick_infos.size()) {
|
|
||||||
if (layout.empty() || layout == "auto")
|
|
||||||
setLayoutFromControllerName(joystick_infos[id].Name.c_str());
|
|
||||||
else
|
|
||||||
setLayoutFromControllerName(layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Irrlicht restriction.
|
|
||||||
m_joystick_id = rangelim(id, 0, UINT8_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JoystickController::setLayoutFromControllerName(const std::string &name)
|
|
||||||
{
|
|
||||||
if (lowercase(name).find("xbox") != std::string::npos) {
|
|
||||||
m_layout = create_xbox_layout();
|
|
||||||
} else if (lowercase(name).find("dragonrise_gamecube") != std::string::npos) {
|
|
||||||
m_layout = create_dragonrise_gamecube_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 = porting::getTimeMs() / 1000.f;
|
|
||||||
|
|
||||||
std::bitset<KeyType::INTERNAL_ENUM_COUNT> keys_pressed;
|
|
||||||
|
|
||||||
// First generate a list of keys pressed
|
|
||||||
|
|
||||||
for (const auto &button_key : m_layout.button_keys) {
|
|
||||||
if (button_key.isTriggered(ev)) {
|
|
||||||
keys_pressed.set(button_key.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &axis_key : m_layout.axis_keys) {
|
|
||||||
if (axis_key.isTriggered(ev)) {
|
|
||||||
keys_pressed.set(axis_key.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then update the values
|
|
||||||
|
|
||||||
for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) {
|
|
||||||
if (keys_pressed[i]) {
|
|
||||||
if (!m_past_keys_pressed[i] &&
|
|
||||||
m_past_pressed_time[i] < m_internal_time - doubling_dtime) {
|
|
||||||
m_past_keys_pressed[i] = true;
|
|
||||||
m_past_pressed_time[i] = m_internal_time;
|
|
||||||
}
|
|
||||||
} else if (m_keys_down[i]) {
|
|
||||||
m_keys_released[i] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keys_pressed[i] && !(m_keys_down[i]))
|
|
||||||
m_keys_pressed[i] = true;
|
|
||||||
|
|
||||||
m_keys_down[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_keys_pressed.reset();
|
|
||||||
m_keys_down.reset();
|
|
||||||
m_past_keys_pressed.reset();
|
|
||||||
m_keys_released.reset();
|
|
||||||
memset(m_axes_vals, 0, sizeof(m_axes_vals));
|
|
||||||
}
|
|
||||||
|
|
||||||
float JoystickController::getAxisWithoutDead(JoystickAxis axis)
|
|
||||||
{
|
|
||||||
s16 v = m_axes_vals[axis];
|
|
||||||
|
|
||||||
if (abs(v) < m_layout.axes_deadzone)
|
|
||||||
return 0.0f;
|
|
||||||
|
|
||||||
v += (v < 0 ? m_layout.axes_deadzone : -m_layout.axes_deadzone);
|
|
||||||
|
|
||||||
return (float)v / ((float)(INT16_MAX - m_layout.axes_deadzone));
|
|
||||||
}
|
|
||||||
|
|
||||||
float JoystickController::getMovementDirection()
|
|
||||||
{
|
|
||||||
return std::atan2(getAxisWithoutDead(JA_SIDEWARD_MOVE),
|
|
||||||
-getAxisWithoutDead(JA_FORWARD_MOVE));
|
|
||||||
}
|
|
||||||
|
|
||||||
float JoystickController::getMovementSpeed()
|
|
||||||
{
|
|
||||||
float speed = std::sqrt(std::pow(getAxisWithoutDead(JA_FORWARD_MOVE), 2) +
|
|
||||||
std::pow(getAxisWithoutDead(JA_SIDEWARD_MOVE), 2));
|
|
||||||
if (speed > 1.0f)
|
|
||||||
speed = 1.0f;
|
|
||||||
return speed;
|
|
||||||
}
|
|
|
@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "renderingengine.h"
|
#include "renderingengine.h"
|
||||||
#include "render/core.h"
|
#include "render/core.h"
|
||||||
#include "render/factory.h"
|
#include "render/factory.h"
|
||||||
#include "inputhandler.h"
|
#include "client/input/inputhandler.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "../gui/guiSkin.h"
|
#include "../gui/guiSkin.h"
|
||||||
|
|
|
@ -315,12 +315,11 @@ void set_default_settings()
|
||||||
settings->setDefault("autojump", "false");
|
settings->setDefault("autojump", "false");
|
||||||
#endif
|
#endif
|
||||||
settings->setDefault("continuous_forward", "false");
|
settings->setDefault("continuous_forward", "false");
|
||||||
settings->setDefault("enable_joysticks", "false");
|
settings->setDefault("enable_joysticks", "true");
|
||||||
settings->setDefault("joystick_id", "0");
|
settings->setDefault("joystick_id", "0");
|
||||||
settings->setDefault("joystick_type", "auto");
|
|
||||||
settings->setDefault("repeat_joystick_button_time", "0.17");
|
settings->setDefault("repeat_joystick_button_time", "0.17");
|
||||||
settings->setDefault("joystick_frustum_sensitivity", "170");
|
settings->setDefault("joystick_frustum_sensitivity", "170");
|
||||||
settings->setDefault("joystick_deadzone", "2048");
|
settings->setDefault("joystick_deadzone", "8000");
|
||||||
|
|
||||||
// Main menu
|
// Main menu
|
||||||
settings->setDefault("main_menu_path", "");
|
settings->setDefault("main_menu_path", "");
|
||||||
|
|
|
@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "client/client.h"
|
#include "client/client.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
#include "client/keycode.h"
|
#include "client/input/keycode.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "client/texturesource.h"
|
#include "client/texturesource.h"
|
||||||
|
|
|
@ -117,7 +117,7 @@ void MenuMusicFetcher::addThePaths(const std::string &name,
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/** GUIEngine */
|
/** GUIEngine */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
GUIEngine::GUIEngine(JoystickController *joystick,
|
GUIEngine::GUIEngine(GamepadController *joystick,
|
||||||
gui::IGUIElement *parent,
|
gui::IGUIElement *parent,
|
||||||
RenderingEngine *rendering_engine,
|
RenderingEngine *rendering_engine,
|
||||||
IMenuManager *menumgr,
|
IMenuManager *menumgr,
|
||||||
|
|
|
@ -140,7 +140,7 @@ public:
|
||||||
* @param smgr scene manager to add scene elements to
|
* @param smgr scene manager to add scene elements to
|
||||||
* @param data struct to transfer data to main game handling
|
* @param data struct to transfer data to main game handling
|
||||||
*/
|
*/
|
||||||
GUIEngine(JoystickController *joystick,
|
GUIEngine(GamepadController *joystick,
|
||||||
gui::IGUIElement *parent,
|
gui::IGUIElement *parent,
|
||||||
RenderingEngine *rendering_engine,
|
RenderingEngine *rendering_engine,
|
||||||
IMenuManager *menumgr,
|
IMenuManager *menumgr,
|
||||||
|
|
|
@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "guiFormSpecMenu.h"
|
#include "guiFormSpecMenu.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "client/keycode.h"
|
#include "client/input/keycode.h"
|
||||||
#include "util/strfnd.h"
|
#include "util/strfnd.h"
|
||||||
#include <IGUIButton.h>
|
#include <IGUIButton.h>
|
||||||
#include <IGUICheckBox.h>
|
#include <IGUICheckBox.h>
|
||||||
|
@ -101,7 +101,7 @@ inline u32 clamp_u8(s32 value)
|
||||||
return (u32) MYMIN(MYMAX(value, 0), 255);
|
return (u32) MYMIN(MYMAX(value, 0), 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUIFormSpecMenu::GUIFormSpecMenu(JoystickController *joystick,
|
GUIFormSpecMenu::GUIFormSpecMenu(GamepadController *joystick,
|
||||||
gui::IGUIElement *parent, s32 id, IMenuManager *menumgr,
|
gui::IGUIElement *parent, s32 id, IMenuManager *menumgr,
|
||||||
Client *client, gui::IGUIEnvironment *guienv, ISimpleTextureSource *tsrc,
|
Client *client, gui::IGUIEnvironment *guienv, ISimpleTextureSource *tsrc,
|
||||||
ISoundManager *sound_manager, IFormSource *fsrc, TextDest *tdst,
|
ISoundManager *sound_manager, IFormSource *fsrc, TextDest *tdst,
|
||||||
|
@ -135,7 +135,7 @@ GUIFormSpecMenu::~GUIFormSpecMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client,
|
void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client,
|
||||||
gui::IGUIEnvironment *guienv, JoystickController *joystick, IFormSource *fs_src,
|
gui::IGUIEnvironment *guienv, GamepadController *joystick, IFormSource *fs_src,
|
||||||
TextDest *txt_dest, const std::string &formspecPrepend, ISoundManager *sound_manager)
|
TextDest *txt_dest, const std::string &formspecPrepend, ISoundManager *sound_manager)
|
||||||
{
|
{
|
||||||
if (cur_formspec && cur_formspec->getReferenceCount() == 1) {
|
if (cur_formspec && cur_formspec->getReferenceCount() == 1) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "guiScrollBar.h"
|
#include "guiScrollBar.h"
|
||||||
#include "guiTable.h"
|
#include "guiTable.h"
|
||||||
#include "network/networkprotocol.h"
|
#include "network/networkprotocol.h"
|
||||||
#include "client/joystick_controller.h"
|
#include "client/input/gamepad_controller.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/enriched_string.h"
|
#include "util/enriched_string.h"
|
||||||
#include "StyleSpec.h"
|
#include "StyleSpec.h"
|
||||||
|
@ -166,7 +166,7 @@ class GUIFormSpecMenu : public GUIModalMenu
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GUIFormSpecMenu(JoystickController *joystick,
|
GUIFormSpecMenu(GamepadController *joystick,
|
||||||
gui::IGUIElement* parent, s32 id,
|
gui::IGUIElement* parent, s32 id,
|
||||||
IMenuManager *menumgr,
|
IMenuManager *menumgr,
|
||||||
Client *client,
|
Client *client,
|
||||||
|
@ -181,7 +181,7 @@ public:
|
||||||
~GUIFormSpecMenu();
|
~GUIFormSpecMenu();
|
||||||
|
|
||||||
static void create(GUIFormSpecMenu *&cur_formspec, Client *client,
|
static void create(GUIFormSpecMenu *&cur_formspec, Client *client,
|
||||||
gui::IGUIEnvironment *guienv, JoystickController *joystick, IFormSource *fs_src,
|
gui::IGUIEnvironment *guienv, GamepadController *joystick, IFormSource *fs_src,
|
||||||
TextDest *txt_dest, const std::string &formspecPrepend,
|
TextDest *txt_dest, const std::string &formspecPrepend,
|
||||||
ISoundManager *sound_manager);
|
ISoundManager *sound_manager);
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ private:
|
||||||
std::string m_last_formname;
|
std::string m_last_formname;
|
||||||
u16 m_formspec_version = 1;
|
u16 m_formspec_version = 1;
|
||||||
std::optional<std::string> m_focused_element = std::nullopt;
|
std::optional<std::string> m_focused_element = std::nullopt;
|
||||||
JoystickController *m_joystick;
|
GamepadController *m_joystick;
|
||||||
bool m_show_debug = false;
|
bool m_show_debug = false;
|
||||||
|
|
||||||
struct parserData {
|
struct parserData {
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
#include "modalMenu.h"
|
#include "modalMenu.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "client/keycode.h"
|
#include "client/input/keycode.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "client/guiscalingfilter.h"
|
#include "client/guiscalingfilter.h"
|
||||||
#include "client/keycode.h"
|
#include "client/input/keycode.h"
|
||||||
#include "client/renderingengine.h"
|
#include "client/renderingengine.h"
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include <ISceneCollisionManager.h>
|
#include <ISceneCollisionManager.h>
|
||||||
|
|
|
@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "client/keycode.h"
|
#include "client/input/keycode.h"
|
||||||
|
|
||||||
class TestKeycode : public TestBase {
|
class TestKeycode : public TestBase {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue