2011-08-03 20:05:33 +00:00
|
|
|
|
/*
|
|
|
|
|
Copyright (C) 2007, 2010 - Bit-Blot
|
|
|
|
|
|
|
|
|
|
This file is part of Aquaria.
|
|
|
|
|
|
|
|
|
|
Aquaria 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
*/
|
2016-06-30 00:58:55 +00:00
|
|
|
|
|
2011-08-03 20:05:33 +00:00
|
|
|
|
#include "ActionInput.h"
|
2016-06-30 00:58:55 +00:00
|
|
|
|
#include "ActionMapper.h"
|
2016-07-13 03:00:19 +00:00
|
|
|
|
#include "Core.h"
|
2016-07-09 02:18:40 +00:00
|
|
|
|
#include "SDL.h"
|
2017-02-18 21:09:43 +00:00
|
|
|
|
#include "GameKeyNames.h"
|
2016-06-30 00:58:55 +00:00
|
|
|
|
|
|
|
|
|
|
2016-07-13 03:00:19 +00:00
|
|
|
|
static std::string inputcode2string(int k)
|
2016-06-30 00:58:55 +00:00
|
|
|
|
{
|
2016-07-03 13:48:40 +00:00
|
|
|
|
if(k <= 0)
|
|
|
|
|
return std::string();
|
2017-02-05 20:25:06 +00:00
|
|
|
|
if(k < KEY_MAXARRAY)
|
2016-06-30 00:58:55 +00:00
|
|
|
|
{
|
2017-02-18 21:09:43 +00:00
|
|
|
|
// Returns KEY_* or NULL
|
|
|
|
|
const std::string& str = getKeyNameFromInputCode(k);
|
|
|
|
|
if(str.length())
|
|
|
|
|
return str;
|
|
|
|
|
|
|
|
|
|
// fallback
|
|
|
|
|
std::ostringstream os;
|
|
|
|
|
os << "K:" << k;
|
2016-06-30 00:58:55 +00:00
|
|
|
|
return os.str();
|
|
|
|
|
}
|
2016-07-13 03:00:19 +00:00
|
|
|
|
|
2016-06-30 00:58:55 +00:00
|
|
|
|
if(k >= JOY_BUTTON_0 && k < JOY_BUTTON_END)
|
|
|
|
|
{
|
2017-02-18 21:09:43 +00:00
|
|
|
|
std::ostringstream os;
|
2016-06-30 00:58:55 +00:00
|
|
|
|
os << "JB:" << (k - JOY_BUTTON_0);
|
|
|
|
|
return os.str();
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-13 03:00:19 +00:00
|
|
|
|
if(k >= JOY_AXIS_0_POS && k < JOY_AXIS_END_POS)
|
|
|
|
|
{
|
2017-02-18 21:09:43 +00:00
|
|
|
|
std::ostringstream os;
|
2016-07-13 03:00:19 +00:00
|
|
|
|
os << "AX:+" << (k - JOY_AXIS_0_POS);
|
|
|
|
|
return os.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(k >= JOY_AXIS_0_NEG && k < JOY_AXIS_END_NEG)
|
|
|
|
|
{
|
2017-02-18 21:09:43 +00:00
|
|
|
|
std::ostringstream os;
|
2016-07-13 03:00:19 +00:00
|
|
|
|
os << "AX:-" << (k - JOY_AXIS_0_NEG);
|
|
|
|
|
return os.str();
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-30 00:58:55 +00:00
|
|
|
|
switch(k)
|
|
|
|
|
{
|
|
|
|
|
case MOUSE_BUTTON_LEFT:
|
|
|
|
|
return "LMB";
|
|
|
|
|
case MOUSE_BUTTON_RIGHT:
|
|
|
|
|
return "RMB";
|
|
|
|
|
case MOUSE_BUTTON_MIDDLE:
|
|
|
|
|
return "MMB";
|
2016-07-13 03:00:19 +00:00
|
|
|
|
default:
|
|
|
|
|
if(k >= MOUSE_BUTTON_EXTRA_START && k < MOUSE_BUTTON_EXTRA_START+mouseExtraButtons)
|
|
|
|
|
{
|
|
|
|
|
std::ostringstream os;
|
|
|
|
|
os << "MB:" << (k - MOUSE_BUTTON_LEFT);
|
|
|
|
|
return os.str();
|
|
|
|
|
}
|
2016-06-30 00:58:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::string();
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-15 01:22:27 +00:00
|
|
|
|
static const char *jaxisname(int joystickID, int axis)
|
2016-07-13 03:00:19 +00:00
|
|
|
|
{
|
2016-07-15 01:22:27 +00:00
|
|
|
|
Joystick *j = core->getJoystick(joystickID);
|
2016-07-13 03:00:19 +00:00
|
|
|
|
return j ? j->getAxisName(axis) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-15 01:22:27 +00:00
|
|
|
|
static const char *jbtnname(int joystickID, int btn)
|
2016-07-13 03:00:19 +00:00
|
|
|
|
{
|
2016-07-15 01:22:27 +00:00
|
|
|
|
Joystick *j = core->getJoystick(joystickID);
|
2016-07-13 03:00:19 +00:00
|
|
|
|
return j ? j->getButtonName(btn) : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string getInputCodeToString(int k)
|
|
|
|
|
{
|
|
|
|
|
std::string s = inputcode2string(k);
|
2017-02-18 21:09:43 +00:00
|
|
|
|
return s.empty() ? "0" : s;
|
2016-07-13 03:00:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-20 03:51:38 +00:00
|
|
|
|
std::string getInputCodeToUserString(unsigned int k, size_t joystickID)
|
2016-07-13 03:00:19 +00:00
|
|
|
|
{
|
2016-07-17 00:34:34 +00:00
|
|
|
|
const char *pretty = NULL, *tail = NULL;
|
2016-07-13 03:00:19 +00:00
|
|
|
|
|
|
|
|
|
// Special case keyboard input:
|
|
|
|
|
// Return key name for current keyboard layout!
|
|
|
|
|
// It's just confusing to see Y instead of Z with a german keyboard layout...
|
2017-02-19 02:47:21 +00:00
|
|
|
|
if(k && k < KEY_MAXARRAY)
|
2016-07-13 03:00:19 +00:00
|
|
|
|
{
|
2017-02-05 20:25:06 +00:00
|
|
|
|
#ifdef BBGE_BUILD_SDL2
|
2017-02-18 21:09:43 +00:00
|
|
|
|
pretty = SDL_GetScancodeName((SDL_Scancode)k);
|
2016-07-13 03:00:19 +00:00
|
|
|
|
const SDL_Keycode kcode = SDL_GetKeyFromScancode((SDL_Scancode)k);
|
|
|
|
|
if(kcode != SDLK_UNKNOWN)
|
|
|
|
|
pretty = SDL_GetKeyName(kcode);
|
2017-02-05 20:25:06 +00:00
|
|
|
|
#else
|
|
|
|
|
pretty = SDL_GetKeyName((SDLKey)k);
|
|
|
|
|
#endif
|
2016-07-13 03:00:19 +00:00
|
|
|
|
}
|
|
|
|
|
if(k >= JOY_AXIS_0_POS && k < JOY_AXIS_END_POS)
|
2016-07-17 00:34:34 +00:00
|
|
|
|
{
|
2016-07-13 03:00:19 +00:00
|
|
|
|
pretty = jaxisname(joystickID, k - JOY_AXIS_0_POS);
|
2016-07-17 00:34:34 +00:00
|
|
|
|
tail = "(+)";
|
|
|
|
|
}
|
2016-07-13 03:00:19 +00:00
|
|
|
|
else if(k >= JOY_AXIS_0_NEG && k < JOY_AXIS_END_NEG)
|
2016-07-17 00:34:34 +00:00
|
|
|
|
{
|
2016-07-13 03:00:19 +00:00
|
|
|
|
pretty = jaxisname(joystickID, k - JOY_AXIS_0_NEG);
|
2016-07-17 00:34:34 +00:00
|
|
|
|
tail = "(-)";
|
|
|
|
|
}
|
2016-07-13 03:00:19 +00:00
|
|
|
|
else if(k >= JOY_BUTTON_0 && k < JOY_BUTTON_END)
|
|
|
|
|
pretty = jbtnname(joystickID, k - JOY_BUTTON_0);
|
|
|
|
|
|
|
|
|
|
if(pretty && *pretty)
|
2016-07-17 00:34:34 +00:00
|
|
|
|
{
|
|
|
|
|
std::string s = pretty;
|
|
|
|
|
if(tail)
|
|
|
|
|
s += tail;
|
|
|
|
|
return s;
|
|
|
|
|
}
|
2016-07-13 03:00:19 +00:00
|
|
|
|
|
2017-02-18 21:09:43 +00:00
|
|
|
|
std::string s = inputcode2string(k);
|
2017-02-19 02:47:21 +00:00
|
|
|
|
return s.empty() ? "<EFBFBD>" : s; // <20> <20>
|
|
|
|
|
// Actually, <20> looks interesting.
|
|
|
|
|
// It shows up as a box, presumably because the font doesn't have that character.
|
|
|
|
|
// I'll leave this as it is, because those boxes are kinda cool. -- fg
|
2017-02-15 03:34:32 +00:00
|
|
|
|
}
|
2017-02-05 20:25:06 +00:00
|
|
|
|
|
2017-02-27 01:03:08 +00:00
|
|
|
|
static int checkInp(const char *s, int category, int limit, const char *err)
|
|
|
|
|
{
|
|
|
|
|
const int k = atoi(s);
|
|
|
|
|
if(!k)
|
|
|
|
|
return 0;
|
|
|
|
|
if(k < limit)
|
|
|
|
|
return k + category;
|
|
|
|
|
|
|
|
|
|
std::ostringstream os;
|
|
|
|
|
os << err << k;
|
|
|
|
|
errorLog(os.str());
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-30 00:58:55 +00:00
|
|
|
|
int getStringToInputCode(const std::string& s)
|
|
|
|
|
{
|
2017-02-27 01:03:08 +00:00
|
|
|
|
int k = 0;
|
|
|
|
|
|
2016-06-30 00:58:55 +00:00
|
|
|
|
if(s == "LMB")
|
2017-02-27 01:03:08 +00:00
|
|
|
|
k = MOUSE_BUTTON_LEFT;
|
|
|
|
|
else if(s == "RMB")
|
|
|
|
|
k = MOUSE_BUTTON_RIGHT;
|
|
|
|
|
else if(s == "MMB")
|
|
|
|
|
k = MOUSE_BUTTON_MIDDLE;
|
|
|
|
|
else if(!strncmp(s.c_str(), "K:", 2))
|
|
|
|
|
k = checkInp(s.c_str() + 2, 0, KEY_MAXARRAY, "Invalid key id: ");
|
|
|
|
|
else if(!strncmp(s.c_str(), "JB:", 3))
|
|
|
|
|
k = checkInp(s.c_str() + 3, JOY_BUTTON_0, JOY_BUTTON_END, "Invalid joy button value: ");
|
|
|
|
|
else if(!strncmp(s.c_str(), "MB:", 3))
|
|
|
|
|
k = checkInp(s.c_str() + 3, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_EXTRA_END, "Invalid mouse button id: ");
|
|
|
|
|
else if(s.length() > 4 && !strncmp(s.c_str(), "AX:", 3))
|
|
|
|
|
{
|
2016-07-13 03:00:19 +00:00
|
|
|
|
switch(s[3])
|
|
|
|
|
{
|
2017-02-27 01:03:08 +00:00
|
|
|
|
case '+':
|
|
|
|
|
k = checkInp(s.c_str() + 4, JOY_AXIS_0_POS, JOY_AXIS_END_POS, "Invalid joy axis(+): ");
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
k = checkInp(s.c_str() + 4, JOY_AXIS_0_NEG, JOY_AXIS_END_NEG, "Invalid joy axis(-): ");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
2016-07-13 03:00:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-02-27 01:03:08 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Maybe we're upgrading from an old config?
|
|
|
|
|
// This handles KEY_* and some old mouse/joystick names.
|
|
|
|
|
k = getInputCodeFromKeyName(s.c_str());
|
|
|
|
|
}
|
2016-06-30 00:58:55 +00:00
|
|
|
|
|
2017-02-27 01:03:08 +00:00
|
|
|
|
if(k < ACTION_BUTTON_ENUM_SIZE)
|
2017-02-15 03:34:32 +00:00
|
|
|
|
return k;
|
|
|
|
|
|
2017-02-27 01:03:08 +00:00
|
|
|
|
std::ostringstream os;
|
|
|
|
|
os << "ActionButton out of range: [" << s << "] = " << k;
|
|
|
|
|
errorLog(os.str());
|
2017-02-15 03:34:32 +00:00
|
|
|
|
return 0;
|
2016-06-30 00:58:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-08-03 20:05:33 +00:00
|
|
|
|
|
|
|
|
|
ActionInput::ActionInput()
|
|
|
|
|
{
|
2017-02-18 21:09:43 +00:00
|
|
|
|
for (int i = 0; i < INP_COMBINED_SIZE; i++)
|
|
|
|
|
data.all[i] = 0;
|
2011-08-03 20:05:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-07-15 01:22:27 +00:00
|
|
|
|
std::string ActionInput::toString() const
|
2011-08-03 20:05:33 +00:00
|
|
|
|
{
|
|
|
|
|
std::ostringstream os;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < INP_MSESIZE; i++)
|
|
|
|
|
{
|
2017-01-17 10:15:47 +00:00
|
|
|
|
os << getInputCodeToString(data.single.mse[i]) << " ";
|
2011-08-03 20:05:33 +00:00
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < INP_KEYSIZE; i++)
|
|
|
|
|
{
|
2017-01-17 10:15:47 +00:00
|
|
|
|
os << getInputCodeToString(data.single.key[i]) << " ";
|
2011-08-03 20:05:33 +00:00
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < INP_JOYSIZE; i++)
|
|
|
|
|
{
|
2017-01-17 10:15:47 +00:00
|
|
|
|
os << getInputCodeToString(data.single.joy[i]) << " ";
|
2011-08-03 20:05:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return os.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ActionInput::fromString(const std::string &read)
|
|
|
|
|
{
|
|
|
|
|
std::istringstream is(read);
|
|
|
|
|
std::string str;
|
|
|
|
|
for (int i = 0; i < INP_MSESIZE; i++)
|
|
|
|
|
{
|
|
|
|
|
is >> str;
|
2017-01-17 10:15:47 +00:00
|
|
|
|
data.single.mse[i] = getStringToInputCode(str);
|
2011-08-03 20:05:33 +00:00
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < INP_KEYSIZE; i++)
|
|
|
|
|
{
|
|
|
|
|
is >> str;
|
2017-01-17 10:15:47 +00:00
|
|
|
|
data.single.key[i] = getStringToInputCode(str);
|
2011-08-03 20:05:33 +00:00
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < INP_JOYSIZE; i++)
|
|
|
|
|
{
|
|
|
|
|
is >> str;
|
2017-01-17 10:15:47 +00:00
|
|
|
|
data.single.joy[i] = getStringToInputCode(str);
|
2011-08-03 20:05:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|