GRIM/EMI: Add Joystick/gamepad support

This commit is contained in:
Ingo van Lil 2014-12-31 13:01:21 +01:00 committed by Christian Krause
parent c0ccf26b05
commit 3d39e63da7
8 changed files with 198 additions and 9 deletions

View file

@ -0,0 +1,48 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 "common/scummsys.h"
#if defined(SDL_BACKEND)
#include "resvm-sdl-events.h"
bool ResVmSdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
event.type = Common::EVENT_JOYBUTTON_DOWN;
event.joystick.button = ev.jbutton.button;
return true;
}
bool ResVmSdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
event.type = Common::EVENT_JOYBUTTON_UP;
event.joystick.button = ev.jbutton.button;
return true;
}
bool ResVmSdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
event.type = Common::EVENT_JOYAXIS_MOTION;
event.joystick.axis = ev.jaxis.axis;
event.joystick.position = ev.jaxis.value;
return true;
}
#endif

View file

@ -0,0 +1,38 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 BACKEND_EVENTS_RESVM_SDL
#define BACKEND_EVENTS_RESVM_SDL
#include "sdl-events.h"
/**
* Custom event source for ResidualVM with true joystick support.
*/
class ResVmSdlEventSource : public SdlEventSource {
protected:
bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event);
bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event);
bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event);
};
#endif

View file

@ -55,6 +55,7 @@ endif
ifdef SDL_BACKEND
MODULE_OBJS += \
events/sdl/sdl-events.o \
events/sdl/resvm-sdl-events.o \
graphics/sdl/sdl-graphics.o \
graphics/surfacesdl/surfacesdl-graphics.o \
mixer/doublebuffersdl/doublebuffersdl-mixer.o \

View file

@ -42,8 +42,9 @@
#else
#include "backends/audiocd/sdl/sdl-audiocd.h"
#endif
#include "backends/events/sdl/sdl-events.h"
// ResidualVM:
// #include "backends/events/sdl/sdl-events.h"
#include "backends/events/sdl/resvm-sdl-events.h"
#include "backends/mutex/sdl/sdl-mutex.h"
#include "backends/timer/sdl/sdl-timer.h"
#include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
@ -156,7 +157,7 @@ void OSystem_SDL::initBackend() {
// Create the default event source, in case a custom backend
// manager didn't provide one yet.
if (_eventSource == 0)
_eventSource = new SdlEventSource();
_eventSource = new ResVmSdlEventSource(); // ResidualVm: was SdlEventSource
if (_graphicsManager == 0) {
if (_graphicsManager == 0) {

View file

@ -87,8 +87,29 @@ enum EventType {
,
EVENT_VIRTUAL_KEYBOARD = 20
#endif
/* START of ResidualVM-specific code */
,
EVENT_JOYAXIS_MOTION = 23,
EVENT_JOYBUTTON_DOWN = 24,
EVENT_JOYBUTTON_UP = 25
};
const int16 JOYAXIS_MIN = -32768;
const int16 JOYAXIS_MAX = 32767;
/**
* Data structure for joystick events
*/
struct JoystickState {
/** The axis for EVENT_JOYAXIS_MOTION events */
byte axis;
/** The new axis position for EVENT_JOYAXIS_MOTION events */
int16 position;
/** The button index for EVENT_JOYBUTTON_DOWN/UP events */
byte button;
};
/* END of ResidualVM-specific code */
typedef uint32 CustomEventType;
/**
* Data structure for an event. A pointer to an instance of Event
@ -127,6 +148,14 @@ struct Event {
*/
Common::Point relMouse;
/**
* Joystick data; only valid for joystick events (EVENT_JOYAXIS_MOTION,
* EVENT_JOYBUTTON_DOWN and EVENT_JOYBUTTON_UP).
*
* This field is ResidualVM specific
*/
JoystickState joystick;
Event() : type(EVENT_INVALID), synthetic(false) {
#ifdef ENABLE_KEYMAPPER
customType = 0;

View file

@ -119,6 +119,10 @@ GrimEngine::GrimEngine(OSystem *syst, uint32 gameFlags, GrimGameType gameType, C
_controlsEnabled[i] = false;
_controlsState[i] = false;
}
_joyAxisPosition = new float[NUM_JOY_AXES];
for (int i = 0; i < NUM_JOY_AXES; i++) {
_joyAxisPosition[i] = 0;
}
_speechMode = TextAndVoice;
_textSpeed = 7;
_mode = _previousMode = NormalMode;
@ -171,6 +175,7 @@ GrimEngine::GrimEngine(OSystem *syst, uint32 gameFlags, GrimGameType gameType, C
GrimEngine::~GrimEngine() {
delete[] _controlsEnabled;
delete[] _controlsState;
delete[] _joyAxisPosition;
clearPools();
@ -816,6 +821,10 @@ void GrimEngine::mainLoop() {
}
}
}
if (type == Common::EVENT_JOYAXIS_MOTION)
handleJoyAxis(event.joystick.axis, event.joystick.position);
if (type == Common::EVENT_JOYBUTTON_DOWN || type == Common::EVENT_JOYBUTTON_UP)
handleJoyButton(type, event.joystick.button);
}
if (_mode != PauseMode) {
@ -1250,6 +1259,10 @@ void GrimEngine::setTextSpeed(int speed) {
}
float GrimEngine::getControlAxis(int num) {
int idx = num - KEYCODE_AXIS_JOY1_X;
if (idx >= 0 && idx < NUM_JOY_AXES) {
return _joyAxisPosition[idx];
}
return 0;
}

View file

@ -193,6 +193,8 @@ protected:
void handleControls(Common::EventType type, const Common::KeyState &key);
void handleChars(Common::EventType type, const Common::KeyState &key);
void handleJoyAxis(byte axis, int16 position);
void handleJoyButton(Common::EventType type, byte button);
void handleExit();
void handlePause();
void handleUserPaint();
@ -243,6 +245,7 @@ protected:
bool *_controlsEnabled;
bool *_controlsState;
float *_joyAxisPosition;
bool _changeHardwareState;
bool _changeFullscreenState;
@ -336,6 +339,9 @@ enum {
KEYCODE_EXTRA_LAST
};
#define NUM_JOY_AXES (KEYCODE_AXIS_JOY1_V - KEYCODE_AXIS_JOY1_X + 1)
#define NUM_JOY_BUTTONS (KEYCODE_JOY1_B20 - KEYCODE_JOY1_B1 + 1)
extern const ControlDescriptor controls[];
} // end of namespace Grim

View file

@ -203,7 +203,7 @@ const ControlDescriptor controls[] = {
{ "KEY_JOY2_B8", KEYCODE_JOY2_B8 },
{ "KEY_JOY2_B9", KEYCODE_JOY2_B9 },
{ "KEY_JOY2_B10", KEYCODE_JOY2_B10 },
{ "KEY_JOY2_HLEFT", KEYCODE_JOY1_HLEFT },
{ "KEY_JOY2_HLEFT", KEYCODE_JOY2_HLEFT },
{ "KEY_JOY2_HUP", KEYCODE_JOY2_HUP },
{ "KEY_JOY2_HRIGHT", KEYCODE_JOY2_HRIGHT },
{ "KEY_JOY2_HDOWN", KEYCODE_JOY2_HDOWN },
@ -262,8 +262,8 @@ const ControlDescriptor controls[] = {
{ "KEY_JOY2_LMUSHROOM", KEYCODE_JOY2_B15 },
{ "KEY_JOY2_RMUSHROOM", KEYCODE_JOY2_B16 },
// tell EMI there is no joystick selected
{ "joy_selected", -1 },
// tell EMI that the joystick can be used
{ "joy_selected", 1 },
{ nullptr, 0 }
};
@ -316,9 +316,6 @@ void GrimEngine::handleControls(Common::EventType operation, const Common::KeySt
if (!LuaBase::instance()->callback("buttonHandler", objects)) {
error("handleControls: invalid keys handler");
}
// if (!LuaBase::instance()->callback("axisHandler", objects)) {
// error("handleControls: invalid joystick handler");
// }
if (operation == Common::EVENT_KEYDOWN)
_controlsState[key.keycode] = true;
@ -326,5 +323,61 @@ void GrimEngine::handleControls(Common::EventType operation, const Common::KeySt
_controlsState[key.keycode] = false;
}
void GrimEngine::handleJoyAxis(byte axis, int16 position) {
if (axis > NUM_JOY_AXES)
return;
int keycode = KEYCODE_AXIS_JOY1_X + axis;
if (!_controlsEnabled[keycode])
return;
float fpos;
if (position < Common::JOYAXIS_MIN / 2) {
fpos = -1;
} else if (position > Common::JOYAXIS_MAX / 2) {
fpos = 1;
} else {
fpos = 0;
}
if (abs(fpos - _joyAxisPosition[axis]) > 0.1) {
LuaObjects objects;
objects.add(keycode);
objects.add(fpos);
if (!LuaBase::instance()->callback("axisHandler", objects)) {
error("handleJoyAxis: invalid joystick handler");
}
_joyAxisPosition[axis] = fpos;
}
}
void GrimEngine::handleJoyButton(Common::EventType operation, byte button) {
if (button > NUM_JOY_BUTTONS)
return;
int keycode = KEYCODE_JOY1_B1 + button;
if (!_controlsEnabled[keycode])
return;
LuaObjects objects;
objects.add(keycode);
if (operation == Common::EVENT_JOYBUTTON_DOWN) {
objects.add(1);
objects.add(1);
} else if (operation == Common::EVENT_JOYBUTTON_UP) {
objects.addNil();
objects.add(0);
}
objects.add(0);
if (!LuaBase::instance()->callback("buttonHandler", objects)) {
error("handleControls: invalid keys handler");
}
if (operation == Common::EVENT_JOYBUTTON_DOWN)
_controlsState[keycode] = true;
else if (operation == Common::EVENT_JOYBUTTON_UP)
_controlsState[keycode] = false;
}
} // end of namespace Grim