1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-06-08 17:42:05 +00:00

wip replacing input handling system; compiles and runs but is broken

This commit is contained in:
fgenesis 2020-08-11 12:04:15 +02:00
parent 36059deae0
commit af711f00b5
55 changed files with 1984 additions and 2074 deletions

View file

@ -291,10 +291,10 @@ void AnimationEditor::applyState()
addAction(ACTION_SWIMLEFT, KEY_J, -1);
addAction(ACTION_SWIMRIGHT, KEY_K, -1);
addAction(ACTION_SWIMUP, KEY_UP, -1);
addAction(ACTION_SWIMDOWN, KEY_DOWN, -1);
addAction(ACTION_SWIMLEFT, KEY_J);
addAction(ACTION_SWIMRIGHT, KEY_K);
addAction(ACTION_SWIMUP, KEY_UP);
addAction(ACTION_SWIMDOWN, KEY_DOWN);
@ -537,7 +537,7 @@ void AnimationEditor::redo()
}
}
void AnimationEditor::action(int id, int state, int source, InputDevice device)
void AnimationEditor::action(int id, int state, int source, InputDeviceType device)
{
if (editingBone && state)
{
@ -726,14 +726,14 @@ void AnimationEditor::update(float dt)
if (editingStrip)
{
if (isActing(ACTION_SWIMLEFT, -1))
if (isActing(ACTION_SWIMLEFT))
moveBoneStripPoint(Vector(-dt, 0));
if (isActing(ACTION_SWIMRIGHT, -1))
if (isActing(ACTION_SWIMRIGHT))
moveBoneStripPoint(Vector(dt, 0));
if (isActing(ACTION_SWIMUP, -1))
if (isActing(ACTION_SWIMUP))
moveBoneStripPoint(Vector(0, -dt));
if (isActing(ACTION_SWIMDOWN, -1))
if (isActing(ACTION_SWIMDOWN))
moveBoneStripPoint(Vector(0, dt));
}
int spd = 1;

View file

@ -113,7 +113,7 @@ public:
std::vector<KeyframeWidget*> keyframeWidgets;
void action(int id, int state, int source, InputDevice device);
void action(int id, int state, int source, InputDeviceType device);
void rebuildKeyframeWidgets();

View file

@ -89,7 +89,7 @@ void AquariaGuiElement::setFocus(bool v)
if (v)
{
currentFocus = this;
if (dsq->getInputMode() == INPUT_JOYSTICK || dsq->getInputMode() == INPUT_KEYBOARD)
if (dsq->getInputMode() == INP_DEV_JOYSTICK || dsq->getInputMode() == INP_DEV_KEYBOARD)
core->setMousePosition(getGuiPosition());
AquariaGuiElement *gui=0, *guiThis = (AquariaGuiElement*)this;
@ -162,49 +162,13 @@ void AquariaGuiElement::UpdateGlobalFocus(float dt)
Direction AquariaGuiElement::GetDirection()
{
Direction dir = DIR_NONE;
// This joystick code is already supposed to send ACTION_MENU*.
// Actually some places depend on the actions to be sent,
// So checking this here might work for a few cases,
// but others will break.
// I'll leave this in here for now -- fg
/*Vector p;
for(size_t i = 0; i < core->getNumJoysticks(); ++i)
if(Joystick *j = core->getJoystick(i))
if(j->isEnabled())
{
p = core->getJoystick(i)->position;
if(!p.isLength2DIn(0.4f))
break;
}
if (!p.isLength2DIn(0.4f))
StateObject *obj = dsq->getTopStateObject(); // usually Game...
if (obj)
{
if (fabsf(p.x) > fabsf(p.y))
{
if (p.x > 0)
dir = DIR_RIGHT;
else
dir = DIR_LEFT;
}
else
{
if (p.y > 0)
dir = DIR_DOWN;
else
dir = DIR_UP;
}
}
else*/
{
StateObject *obj = dsq->getTopStateObject(); // usually Game...
if (obj)
{
if (obj->isActing(ACTION_MENULEFT, -1)) dir = DIR_LEFT;
else if (obj->isActing(ACTION_MENURIGHT, -1)) dir = DIR_RIGHT;
else if (obj->isActing(ACTION_MENUUP, -1)) dir = DIR_UP;
else if (obj->isActing(ACTION_MENUDOWN, -1)) dir = DIR_DOWN;
}
if (obj->isActing(ACTION_MENULEFT)) dir = DIR_LEFT;
else if (obj->isActing(ACTION_MENURIGHT)) dir = DIR_RIGHT;
else if (obj->isActing(ACTION_MENUUP)) dir = DIR_UP;
else if (obj->isActing(ACTION_MENUDOWN)) dir = DIR_DOWN;
}
return dir;
}
@ -343,9 +307,6 @@ void AquariaGuiQuad::onUpdate(float dt)
Quad::onUpdate(dt);
}
// Joystick input threshold at which we start sliding (0.0-1.0); must be
// less than updateMovement() threshold.
const float SLIDER_JOY_THRESHOLD = 0.39f;
// Initial delay before repeating for slider input (seconds).
const float SLIDER_REPEAT_DELAY = 0.4f;
// Scale factor for delay as repeats continue.
@ -382,26 +343,10 @@ bool AquariaSlider::doSliderInput(float dt)
float inputAmount; // How much to adjust by?
// disabled the jaxis threshold check;
// ACTION_MENU* should be sent automatically when above the threshold -- fg
/*Vector jpos;
for(size_t i = 0; i < core->getNumJoysticks(); ++i)
if(Joystick *j = core->getJoystick(i))
if(j->isEnabled())
{
jpos = core->getJoystick(i)->position;
if(fabsf(jpos.x) > SLIDER_JOY_THRESHOLD)
break;
}*/
StateObject *obj = dsq->getTopStateObject();
/*if (jpos.x <= -SLIDER_JOY_THRESHOLD)
if (obj && obj->isActing(ACTION_MENULEFT))
inputAmount = -0.1f;
else if (jpos.x >= SLIDER_JOY_THRESHOLD)
inputAmount = +0.1f;
else*/ if (obj && obj->isActing(ACTION_MENULEFT, -1))
inputAmount = -0.1f;
else if (obj && obj->isActing(ACTION_MENURIGHT, -1))
else if (obj && obj->isActing(ACTION_MENURIGHT))
inputAmount = +0.1f;
else
inputAmount = 0;
@ -484,27 +429,81 @@ bool AquariaCheckBox::isGuiVisible()
AquariaKeyConfig *AquariaKeyConfig::waitingForInput = 0;
enum KeyMapResult
{
KMR_NONE,
KMR_ASSIGNED,
KMR_CLEARED,
KMR_CANCELLED
};
AquariaKeyConfig::AquariaKeyConfig(const std::string &actionInputName, InputSetType inputSetType, int inputIdx)
// created on the stack while waiting for keys to be pressed
class InputSniffer : public IInputMapper
{
public:
InputSniffer(InputDeviceType dev) : _dev(dev), _res(KMR_NONE) {}
virtual void input(const RawInput *inp)
{
if(_res != KMR_NONE)
return;
if(inp->src.deviceType == INP_DEV_KEYBOARD && inp->src.ctrlType == INP_CTRL_BUTTON && inp->u.pressed)
{
switch(inp->src.ctrlID)
{
case KEY_ESCAPE: _res = KMR_CANCELLED; return;
case KEY_BACKSPACE:
case KEY_DELETE: _res = KMR_CLEARED; return;
}
}
// TODO controllerfixup: check if input is "interesting" enough
if(inp->src.deviceType == _dev)
{
_res = KMR_ASSIGNED;
stored = *inp;
}
}
KeyMapResult get(RawInput *inp) const
{
if(_res == KMR_ASSIGNED)
*inp = stored;
return _res;
}
RawInput stored;
InputDeviceType _dev;
KeyMapResult _res;
};
static KeyMapResult waitForInput(RawInput *raw, InputDeviceType dev)
{
InputSniffer sniff(dev);
KeyMapResult km;
for(;;)
{
km = sniff.get(raw);
if(km != KMR_NONE)
break;
dsq->run(0.1f, true);
}
return km;
}
AquariaKeyConfig::AquariaKeyConfig(const std::string &actionInputName, InputDeviceType dev, unsigned slot)
: AquariaGuiElement(), RenderObject()
, actionInputName(actionInputName)
, inputSetType(inputSetType)
, inputIdx(inputIdx)
, inputDevType(dev)
, inputSlot(slot)
, inputField(ActionInput::GetField(dev, slot))
, actionSetIndex(0)
, rejectJoyAxis(false)
{
bg = new Quad();
bg2 = new Quad();
if (inputSetType == INPUTSET_OTHER)
{
bg->setWidthHeight(40, 20);
bg2->setWidthHeight(40, 20);
}
else
{
bg->setWidthHeight(90, 20);
bg2->setWidthHeight(90, 20);
}
bg->setWidthHeight(90, 20);
bg2->setWidthHeight(90, 20);
bg->color = Vector(0.5f, 0.5f, 0.5f);
bg->alphaMod = 0;
@ -516,7 +515,6 @@ AquariaKeyConfig::AquariaKeyConfig(const std::string &actionInputName, InputSetT
addChild(bg2, PM_POINTER);
keyConfigFont = new TTFText(&dsq->fontArialSmallest);
keyConfigFont->setAlign(ALIGN_CENTER);
@ -589,342 +587,29 @@ void AquariaKeyConfig::onUpdate(float dt)
inLoop = true;
unsigned int *k = 0;
ActionInput &ai = as.ensureActionInput(actionInputName);
ActionInput *ai = 0;
bool used = false;
if (inputSetType != INPUTSET_OTHER)
{
ai = as.getActionInputByName(actionInputName);
if (!ai)
{
exit_error("Could not find actionInput: " + actionInputName);
}
switch(inputSetType)
{
case INPUTSET_KEY:
k = &ai->data.single.key[inputIdx];
break;
case INPUTSET_MOUSE:
k = &ai->data.single.mse[inputIdx];
break;
case INPUTSET_JOY:
k = &ai->data.single.joy[inputIdx];
break;
case INPUTSET_NONE:
case INPUTSET_OTHER:
k = 0;
break;
}
used = k && *k;
}
if (inputSetType == INPUTSET_OTHER)
{
if (actionInputName == "s1ax")
k = &as.joycfg.s1ax;
else if (actionInputName == "s1ay")
k = &as.joycfg.s1ay;
else if (actionInputName == "s2ax")
k = &as.joycfg.s2ax;
else if (actionInputName == "s2ay")
k = &as.joycfg.s2ay;
used = k && int(*k) >= 0;
}
bool used = ai.hasEntry(inputSlot);
if(used)
bg2->alphaMod = 0.3f;
else
bg2->alphaMod = 0;
if (waitingForInput == this)
if (waitingForInput != this)
keyConfigFont->setText(ai.prettyPrintField(inputField, as.joystickID));
else
{
std::string s;
s.reserve(6);
s = "_";
for (int i = 0; i < int(dsq->game->getTimer(5)); i++)
const int tm = int(dsq->game->getTimer(5));
for (int i = 0; i < tm; i++)
{
s += "_";
}
keyConfigFont->setText(s);
}
else
{
if (inputSetType != INPUTSET_OTHER)
{
keyConfigFont->setText(getInputCodeToUserString(*k, as.joystickID));
}
else
{
if(*k >= 0)
{
std::ostringstream os;
os << (*k);
keyConfigFont->setText(os.str());
}
else
{
keyConfigFont->setText(getInputCodeToUserString(0, as.joystickID));
}
}
}
if (waitingForInput == this)
{
switch(inputSetType)
{
case INPUTSET_OTHER:
{
if (k)
{
int ac = -1;
bool clear = false;
bool abort = false;
for (int i = 0; i < KEY_MAXARRAY; i++)
{
if (core->getKeyState(i))
{
if(i == KEY_BACKSPACE || i == KEY_DELETE)
clear = true;
else if (i == KEY_ESCAPE)
abort = true;
else
{
switch(i)
{
#define K(k) case k: ac = i-k; break
K(KEY_0);
K(KEY_1);
K(KEY_2);
K(KEY_3);
K(KEY_4);
K(KEY_5);
K(KEY_6);
K(KEY_7);
K(KEY_8);
K(KEY_9);
#undef K
}
}
while (dsq->game->getKeyState(i))
{
dsq->run(0.1f, true);
}
}
}
if(ac < 0)
{
Joystick *j = core->getJoystick(as.joystickID);
if(j)
for(int i = 0; i < MAX_JOYSTICK_AXIS; ++i)
{
float ax = j->getAxisUncalibrated(i);
if(fabsf(ax) > JOY_AXIS_THRESHOLD)
{
ac = i;
while (fabsf(j->getAxisUncalibrated(i)) > JOY_AXIS_THRESHOLD)
dsq->run(0.1f, true);
break;
}
}
}
if(ac >= 0 || abort || clear)
{
toggleEnterKey(0);
waitingForInput = 0;
AquariaGuiElement::canDirMoveGlobal = true;
if(!abort)
{
if(clear || ac == *k)
*k = -1;
else
*k = ac;
}
}
}
}
break;
case INPUTSET_KEY:
{
for (int i = 0; i < KEY_MAXARRAY; i++)
{
if (core->getKeyState(i))
{
if(*k == i) // clear key if pressed again
*k = 0;
else if(i != KEY_ESCAPE)
{
if (i == KEY_DELETE || i == KEY_BACKSPACE)
*k = 0;
else
*k = i;
}
while (dsq->game->getKeyState(i))
{
dsq->run(0.1f, true);
}
toggleEnterKey(0);
waitingForInput = 0;
AquariaGuiElement::canDirMoveGlobal = true;
break;
}
}
}
break;
case INPUTSET_MOUSE:
{
bool clear = false;
bool abort = false;
unsigned int ac = 0;
if (core->getKeyState(KEY_DELETE) || core->getKeyState(KEY_BACKSPACE))
{
while(core->getKeyState(KEY_DELETE) || core->getKeyState(KEY_BACKSPACE))
dsq->run(0.1f, true);
clear = true;
}
else if(core->getKeyState(KEY_ESCAPE))
{
while(core->getKeyState(KEY_ESCAPE))
dsq->run(0.1f, true);
abort = true;
}
else if(dsq->mouse.rawButtonMask)
{
MouseButtons btns = dsq->mouse.buttons;
while(dsq->mouse.rawButtonMask)
dsq->run(0.1f, true);
if(btns.left)
ac = MOUSE_BUTTON_LEFT;
else if(btns.right)
ac = MOUSE_BUTTON_RIGHT;
else if(btns.middle)
ac = MOUSE_BUTTON_MIDDLE;
else
{
for(unsigned i = 0; i < mouseExtraButtons; ++i)
if(btns.extra[i])
{
ac = MOUSE_BUTTON_EXTRA_START+i;
break;
}
}
}
if(ac || clear || abort)
{
toggleEnterKey(0);
waitingForInput = 0;
AquariaGuiElement::canDirMoveGlobal = true;
if(!abort)
{
if(clear || *k == ac) // clear key if pressed again
*k = 0;
else
*k = ac;
}
}
}
break;
case INPUTSET_JOY:
{
size_t ac = 0;
bool clear = false;
bool abort = false;
if (core->getKeyState(KEY_DELETE) || core->getKeyState(KEY_BACKSPACE))
{
clear = true;
}
else if(core->getKeyState(KEY_ESCAPE))
{
abort = true;
while(core->getKeyState(KEY_ESCAPE))
dsq->run(0.1f, true);
}
else
{
Joystick *j = core->getJoystick(as.joystickID);
if(j)
{
for (size_t i = 0; i < MAX_JOYSTICK_BTN; i++)
if (j->getButton(i))
{
ac = JOY_BUTTON_0 + i;
while (j->getButton(i))
dsq->run(0.1f, true); // skip recursion check; we're already in the menu so this would always warn
break;
}
if(!ac)
for(size_t i = 0; i < MAX_JOYSTICK_AXIS; ++i)
{
float ax = j->getAxisUncalibrated(i);
if(fabsf(ax) > JOY_AXIS_THRESHOLD)
{
ac = (ax < 0.0f ? JOY_AXIS_0_NEG : JOY_AXIS_0_POS) + i;
while (fabsf(j->getAxisUncalibrated(i)) > JOY_AXIS_THRESHOLD)
dsq->run(0.1f, true);
break;
}
}
if(!ac)
for(size_t i = 0; i < MAX_JOYSTICK_HATS; ++i)
{
JoyHatDirection hd = j->getHat(i);
if(hd != JOY_HAT_DIR_CENTERED)
{
ac = joyHatToActionButton(i, hd);
while (j->getHat(i) != JOY_HAT_DIR_CENTERED)
dsq->run(0.1f, true);
break;
}
}
}
else
clear = true;
}
if(abort || ac || clear)
{
toggleEnterKey(0);
waitingForInput = 0;
AquariaGuiElement::canDirMoveGlobal = true;
if(rejectJoyAxis && (
(ac >= JOY_AXIS_0_POS && ac < JOY_AXIS_END_POS)
|| (ac >= JOY_AXIS_0_NEG && ac < JOY_AXIS_END_NEG)
))
{
dsq->sound->playSfx("denied");
abort = true;
}
if(!abort)
{
if(clear || *k == ac) // clear key if pressed again
*k = 0;
else
*k = ac;
}
}
}
break;
case INPUTSET_NONE:
break;
}
}
Vector p = bg->getWorldPosition();
@ -938,7 +623,7 @@ void AquariaKeyConfig::onUpdate(float dt)
toggleEnterKey(-1);
}
// FIXME controllerfixup: don't rely on mouse emulation here?
if (!keyDown && (core->mouse.buttons.left || core->mouse.buttons.right))
{
keyDown = true;
@ -958,6 +643,19 @@ void AquariaKeyConfig::onUpdate(float dt)
waitingForInput = this;
toggleEnterKey(1);
AquariaGuiElement::canDirMoveGlobal = false;
RawInput raw;
switch(waitForInput(&raw, inputDevType))
{
case KMR_ASSIGNED:
ai.ImportField(raw, inputField);
break;
case KMR_CLEARED:
ai.clearEntry(inputField);
break;
case KMR_CANCELLED:
break;
}
}
}
}
@ -1218,7 +916,7 @@ void AquariaButton::goDown()
buttonlabel->position = Vector(0, 7);
}
void AquariaButton::action(int actionID, int state, int source, InputDevice device)
void AquariaButton::action(int actionID, int state, int source, InputDeviceType device)
{
if(actionID == ACTION_PRIMARY)
{

View file

@ -87,7 +87,7 @@ public:
bool useQuad(const std::string &tex);
void useGlow(const std::string &tex, int w, int h);
void useSound(const std::string &tex);
virtual void action(int actionID, int state, int source, InputDevice device) {}
virtual void action(int actionID, int state, int source, InputDeviceType device) {}
virtual bool isCursorInMenuItem();
Vector getGuiPosition();
@ -166,7 +166,8 @@ protected:
class AquariaKeyConfig : public AquariaGuiElement, public RenderObject
{
public:
AquariaKeyConfig(const std::string &actionInputName, InputSetType type, int idx);
// field goes from 0 to INP_NUMFIELDS-1
AquariaKeyConfig(const std::string &actionInputName, InputDeviceType type, unsigned field);
void destroy();
Vector getGuiPosition();
@ -186,8 +187,8 @@ protected:
std::string actionInputName;
InputSetType inputSetType;
int inputIdx;
const InputDeviceType inputDevType;
const unsigned inputSlot, inputField;
TTFText *keyConfigFont;
Quad *bg, *bg2;
size_t actionSetIndex;
@ -267,7 +268,7 @@ public:
protected:
virtual void action(int actionID, int state, int source, InputDevice device);
virtual void action(int actionID, int state, int source, InputDeviceType device);
virtual void onUpdate(float dt);
virtual void onToggleHighlight(bool on);

View file

@ -128,34 +128,32 @@ void Avatar::bindInput()
ActionMapper::clearActions();
ActionMapper::clearCreatedEvents();
for(size_t i = 0; i < dsq->user.control.actionSets.size(); ++i)
const NamedAction actions[] =
{
const ActionSet& as = dsq->user.control.actionSets[i];
int sourceID = (int)i;
{ "PrimaryAction", ACTION_PRIMARY},
{ "SecondaryAction", ACTION_SECONDARY},
as.importAction(this, "PrimaryAction", ACTION_PRIMARY, sourceID);
as.importAction(this, "SecondaryAction", ACTION_SECONDARY, sourceID);
{ "SwimUp", ACTION_SWIMUP},
{ "SwimDown", ACTION_SWIMDOWN},
{ "SwimLeft", ACTION_SWIMLEFT},
{ "SwimRight", ACTION_SWIMRIGHT},
as.importAction(this, "SwimUp", ACTION_SWIMUP, sourceID);
as.importAction(this, "SwimDown", ACTION_SWIMDOWN, sourceID);
as.importAction(this, "SwimLeft", ACTION_SWIMLEFT, sourceID);
as.importAction(this, "SwimRight", ACTION_SWIMRIGHT, sourceID);
{ "SongSlot1", ACTION_SONGSLOT1},
{ "SongSlot2", ACTION_SONGSLOT2},
{ "SongSlot3", ACTION_SONGSLOT3},
{ "SongSlot4", ACTION_SONGSLOT4},
{ "SongSlot5", ACTION_SONGSLOT5},
{ "SongSlot6", ACTION_SONGSLOT6},
{ "SongSlot7", ACTION_SONGSLOT7},
{ "SongSlot8", ACTION_SONGSLOT8},
{ "SongSlot9", ACTION_SONGSLOT9},
{ "SongSlot10", ACTION_SONGSLOT10},
as.importAction(this, "SongSlot1", ACTION_SONGSLOT1, sourceID);
as.importAction(this, "SongSlot2", ACTION_SONGSLOT2, sourceID);
as.importAction(this, "SongSlot3", ACTION_SONGSLOT3, sourceID);
as.importAction(this, "SongSlot4", ACTION_SONGSLOT4, sourceID);
as.importAction(this, "SongSlot5", ACTION_SONGSLOT5, sourceID);
as.importAction(this, "SongSlot6", ACTION_SONGSLOT6, sourceID);
as.importAction(this, "SongSlot7", ACTION_SONGSLOT7, sourceID);
as.importAction(this, "SongSlot8", ACTION_SONGSLOT8, sourceID);
as.importAction(this, "SongSlot9", ACTION_SONGSLOT9, sourceID);
as.importAction(this, "SongSlot10", ACTION_SONGSLOT10, sourceID);
as.importAction(this, "Revert", ACTION_REVERT, sourceID);
as.importAction(this, "Look", ACTION_LOOK, sourceID);
as.importAction(this, "Roll", ACTION_ROLL, sourceID);
}
{ "Revert", ACTION_REVERT},
{ "Look", ACTION_LOOK},
{ "Roll", ACTION_ROLL}
};
ImportInput(actions);
}
// note: z is set to 1.0 when we want the aim to be used as the shot direction
@ -163,31 +161,22 @@ void Avatar::bindInput()
Vector Avatar::getAim()
{
Vector d;
if (dsq->getInputMode() == INPUT_JOYSTICK)
float z = 1;
if (dsq->getInputMode() == INP_DEV_JOYSTICK)
{
for(size_t i = 0; i < core->getNumJoysticks(); ++i)
if(Joystick *j = core->getJoystick(i))
if(j->isEnabled() && !j->rightStick.isZero())
{
d = j->rightStick * 300;
d.z = 1;
break;
}
d = dsq->playerInput.getStick2();
if(d.isZero())
for(size_t i = 0; i < core->getNumJoysticks(); ++i)
if(Joystick *j = core->getJoystick(i))
if(j->isEnabled() && !j->position.isZero())
{
d = j->position * 300;
break;
}
{
d = dsq->playerInput.getStick1();
z = 0;
}
d *= 300;
d.z = z;
}
else
{
d = dsq->getGameCursorPosition() - position;
d.z = 1;
}
d.z = z;
if (d.isZero())
d = getForwardAim();
@ -209,7 +198,7 @@ void Avatar::onAnimationKeyPassed(int key)
Entity::onAnimationKeyPassed(key);
}
Vector randCirclePos(Vector position, int radius)
static Vector randCirclePos(Vector position, int radius)
{
float a = ((rand()%360)*(2*PI))/360.0f;
return position + Vector(sinf(a), cosf(a))*radius;
@ -1100,7 +1089,7 @@ void Avatar::onDamage(DamageData &d)
if (healthWillBe<=0)
t = 2;
dsq->rumble(d.damage, d.damage, 0.4f, _lastActionSourceID, _lastActionInputDevice);
dsq->rumble(d.damage, d.damage, 0.4f);
if (d.damage > 0)
{
//dsq->shakeCamera(5, t);
@ -1312,12 +1301,12 @@ void Avatar::clearTargets()
}
}
void Avatar::openSingingInterface(InputDevice device)
void Avatar::openSingingInterface(InputDeviceType device)
{
if (!singing && health > 0 && !isEntityDead() && !blockSinging)
{
//core->mouse.position = Vector(400,300);
if (device != INPUT_MOUSE)
if (device != INP_DEV_MOUSE)
{
core->centerMouse();
//core->setMousePosition(Vector(400,300));
@ -1340,7 +1329,7 @@ void Avatar::openSingingInterface(InputDevice device)
dsq->game->songLineRender->clear();
if (device == INPUT_JOYSTICK)
if (device == INP_DEV_JOYSTICK)
{
core->setMousePosition(core->center);
}
@ -1730,7 +1719,7 @@ void Avatar::updateSingingInterface(float dt)
{
if (songIcons.size()>0 && songIcons[0]->alpha.x > 0)
{
if (dsq->getInputMode() != INPUT_JOYSTICK && !core->mouse.change.isZero())
if (dsq->getInputMode() != INP_DEV_JOYSTICK && !core->mouse.change.isZero())
{
if (dsq->game->songLineRender && songIcons[0]->alpha.x == 1)
{
@ -1756,9 +1745,10 @@ void Avatar::updateSingingInterface(float dt)
}
else
{
if (dsq->getInputMode() == INPUT_JOYSTICK)
if (dsq->getInputMode() == INP_DEV_JOYSTICK)
{
Vector d;
/* // FIXME controllerfixup
for(size_t i = 0; i < core->getNumJoysticks(); ++i)
if(Joystick *j = core->getJoystick(i))
if(j->isEnabled())
@ -1767,6 +1757,7 @@ void Avatar::updateSingingInterface(float dt)
if(!d.isZero())
break;
}
*/
if (d.isLength2DIn(JOYSTICK_NOTE_THRESHOLD))
{
@ -1948,7 +1939,7 @@ void Avatar::updateTargets(float dt, bool override)
break;
}
}
if ((dsq->getInputMode() == INPUT_MOUSE || dsq->getInputMode() == INPUT_KEYBOARD) && !(wasDown && core->mouse.buttons.right))
if ((dsq->getInputMode() == INP_DEV_MOUSE || dsq->getInputMode() == INP_DEV_KEYBOARD) && !(wasDown && core->mouse.buttons.right))
{
wasDown = false;
float mod = 1;
@ -2108,11 +2099,11 @@ void Avatar::updateTargetQuads(float dt)
targetQuads[i]->position = cursorpos;
if (dsq->continuity.form == FORM_ENERGY && isInputEnabled())
{
if (dsq->getInputMode() == INPUT_JOYSTICK && targetQuads[i]->isRunning())
if (dsq->getInputMode() == INP_DEV_JOYSTICK && targetQuads[i]->isRunning())
{
targetQuads[i]->stop();
}
else if (dsq->getInputMode() != INPUT_JOYSTICK && !targetQuads[i]->isRunning())
else if (dsq->getInputMode() != INP_DEV_JOYSTICK && !targetQuads[i]->isRunning())
{
targetQuads[i]->start();
}
@ -2147,7 +2138,7 @@ bool Avatar::fireAtNearestValidEntity(const std::string &shot)
p = boneLeftArm->getWorldPosition();
//&& !dsq->game->isObstructed(TileVector(position))
/*
if (dsq->inputMode == INPUT_MOUSE && state.lockedToWall )
if (dsq->inputMode == INP_DEV_MOUSE && state.lockedToWall )
dir = dsq->getGameCursorPosition() - p;
else
*/
@ -2168,7 +2159,7 @@ bool Avatar::fireAtNearestValidEntity(const std::string &shot)
/*
if (target)
{
if (dsq->inputMode != INPUT_JOYSTICK && vel.isLength2DIn(50))
if (dsq->inputMode != INP_DEV_JOYSTICK && vel.isLength2DIn(50))
{
}
else
@ -2189,7 +2180,7 @@ bool Avatar::fireAtNearestValidEntity(const std::string &shot)
bool clearTargets = false;
// allow autoAim if desired
if ((dsq->getInputMode() == INPUT_JOYSTICK && !aimAt) || dsq->user.control.autoAim)
if ((dsq->getInputMode() == INP_DEV_JOYSTICK && !aimAt) || dsq->user.control.autoAim)
{
if (targets.empty())
{
@ -2252,7 +2243,7 @@ bool Avatar::fireAtNearestValidEntity(const std::string &shot)
}
else
{
//if (!dir.isLength2DIn(2) || dsq->inputMode == INPUT_JOYSTICK)
//if (!dir.isLength2DIn(2) || dsq->inputMode == INP_DEV_JOYSTICK)
if (true)
{
s = dsq->game->fireShot(shot, this);
@ -2998,12 +2989,12 @@ bool Avatar::isMouseInputEnabled()
return true;
}
void Avatar::rmbd(int source, InputDevice device)
void Avatar::rmbd(int source, InputDeviceType device)
{
if (!isMouseInputEnabled() || isEntityDead()) return;
if (dsq->continuity.form == FORM_NORMAL )
{
if (device == INPUT_MOUSE)
if (device == INP_DEV_MOUSE)
{
Vector diff = getVectorToCursorFromScreenCentre();
if (diff.getSquaredLength2D() < sqr(openSingingInterfaceRadius))
@ -3020,7 +3011,7 @@ void Avatar::rmbd(int source, InputDevice device)
}
}
void Avatar::rmbu(int source, InputDevice device)
void Avatar::rmbu(int source, InputDeviceType device)
{
if (!isMouseInputEnabled() || isEntityDead()) return;
@ -3168,7 +3159,7 @@ void Avatar::onUpdateBoneLock()
rotateToVec(wallNormal, 0.01f);
}
void Avatar::lmbd(int source, InputDevice device)
void Avatar::lmbd(int source, InputDeviceType device)
{
if (!isMouseInputEnabled()) return;
@ -3210,7 +3201,7 @@ void Avatar::fallOffWall()
}
}
void Avatar::lmbu(int source, InputDevice device)
void Avatar::lmbu(int source, InputDeviceType device)
{
if (!isMouseInputEnabled()) return;
@ -3886,8 +3877,6 @@ Avatar::Avatar() : Entity(), ActionMapper()
blockBackFlip = false;
elementEffectMult = 1;
_lastActionSourceID = 9999;
_lastActionInputDevice = INPUT_NODEVICE;
}
void Avatar::revert()
@ -4056,11 +4045,11 @@ void Avatar::startBurst()
{
if (!riding && canBurst() && (joystickMove || getVectorToCursor().getSquaredLength2D() > sqr(BURST_DISTANCE))
&& getState() != STATE_PUSH && (!skeletalSprite.getCurrentAnimation() || (skeletalSprite.getCurrentAnimation()->name != "spin"))
&& _isUnderWater && !isActing(ACTION_ROLL, -1))
&& _isUnderWater && !isActing(ACTION_ROLL))
{
if (!bursting && burst == 1)
{
dsq->rumble(0.2f, 0.2f, 0.2f, _lastActionSourceID, _lastActionInputDevice);
dsq->rumble(0.2f, 0.2f, 0.2f);
if (dsq->continuity.form != FORM_BEAST)
wakeEmitter.start();
dsq->game->playBurstSound(pushingOffWallEffect>0);
@ -4133,7 +4122,7 @@ void Avatar::startWallBurst(bool useCursor)
{
lastBurstType = BURST_WALL;
dsq->rumble(0.22f, 0.22f, 0.2f, _lastActionSourceID, _lastActionInputDevice);
dsq->rumble(0.22f, 0.22f, 0.2f);
bittenEntities.clear();
if (useCursor)
{
@ -4171,10 +4160,10 @@ void Avatar::startWallBurst(bool useCursor)
bool Avatar::isActionAndGetDir(Vector& dir)
{
bool dL = isActing(ACTION_SWIMLEFT, -1);
bool dR = isActing(ACTION_SWIMRIGHT, -1);
bool dU = isActing(ACTION_SWIMUP, -1);
bool dD = isActing(ACTION_SWIMDOWN, -1);
bool dL = isActing(ACTION_SWIMLEFT);
bool dR = isActing(ACTION_SWIMRIGHT);
bool dU = isActing(ACTION_SWIMUP);
bool dD = isActing(ACTION_SWIMDOWN);
Vector a;
if (dL)
a += Vector(-1,0);
@ -4198,7 +4187,8 @@ Vector Avatar::getFakeCursorPosition()
if(isActionAndGetDir(dir))
return dir * 350;
for(size_t i = 0; i < core->getNumJoysticks(); ++i)
// FIXME controllerfixup
/*for(size_t i = 0; i < core->getNumJoysticks(); ++i)
if(Joystick *j = core->getJoystick(i))
if(j->isEnabled())
{
@ -4209,7 +4199,7 @@ Vector Avatar::getFakeCursorPosition()
const float distance = minMouse + ((axisInput - JOYSTICK_LOW_THRESHOLD) * axisMult);
return (j->position * (distance / axisInput));
}
}
}*/
return dir;
}
@ -4220,7 +4210,7 @@ Vector Avatar::getVectorToCursorFromScreenCentre()
return getVectorToCursor();
else
{
if (dsq->getInputMode() != INPUT_MOUSE)
if (dsq->getInputMode() != INP_DEV_MOUSE)
return getFakeCursorPosition();
return (core->mouse.position+offset) - Vector(400,300);
}
@ -4232,21 +4222,18 @@ Vector Avatar::getVectorToCursor(bool trueMouse)
Vector pos = dsq->getGameCursorPosition();
if (!trueMouse && dsq->getInputMode() != INPUT_MOUSE)
if (!trueMouse && dsq->getInputMode() != INP_DEV_MOUSE)
return getFakeCursorPosition();
return pos - (position+offset);
//return core->mouse.position - Vector(400,300);
}
void Avatar::action(int id, int state, int source, InputDevice device)
void Avatar::action(int id, int state, int source, InputDeviceType device)
{
if(dsq->game->isIgnoreAction((AquariaActions)id))
return;
_lastActionSourceID = source;
_lastActionInputDevice = device;
if (id == ACTION_PRIMARY) { if (state) lmbd(source, device); else lmbu(source, device); }
if (id == ACTION_SECONDARY) { if (state) rmbd(source, device); else rmbu(source, device); }
@ -4313,7 +4300,7 @@ void Avatar::action(int id, int state, int source, InputDevice device)
// done for wall bursts, but the movement there is fast
// enough that people probably won't notice, so I skipped
// that. Sorry about the ugliness. --achurch
if (device != INPUT_MOUSE)
if (device != INP_DEV_MOUSE)
skeletalSprite.transitionAnimate("swim", ANIM_TRANSITION, -1);
}
}
@ -4515,7 +4502,7 @@ void Avatar::splash(bool down)
//dsq->postProcessingFx.disable(FXT_RADIALBLUR);
if (_isUnderWater && core->afterEffectManager)
core->afterEffectManager->addEffect(new ShockEffect(Vector(core->width/2, core->height/2),core->screenCenter,0.08f,0.05f,22,0.2f, 1.2f));
dsq->rumble(0.7f, 0.7f, 0.2f, _lastActionSourceID, _lastActionInputDevice);
dsq->rumble(0.7f, 0.7f, 0.2f);
plungeEmitter.start();
core->sound->playSfx("GoUnder");
@ -4992,13 +4979,13 @@ void Avatar::updateRoll(float dt)
stopRoll();
}
}
const bool rollact = isActing(ACTION_ROLL, -1);
const bool rollact = isActing(ACTION_ROLL);
if (!_isUnderWater && rollact)
{
stopRoll();
}
if (!core->mouse.buttons.left && dsq->getInputMode() == INPUT_MOUSE && !rollact)
if (!core->mouse.buttons.left && dsq->getInputMode() == INP_DEV_MOUSE && !rollact)
{
if (rolling)
stopRoll();
@ -5390,7 +5377,7 @@ void Avatar::onUpdate(float dt)
}
}
if (!dsq->game->isPaused() && isActing(ACTION_LOOK, -1) && !dsq->game->avatar->isSinging() && dsq->game->avatar->isInputEnabled() && !dsq->game->isInGameMenu())
if (!dsq->game->isPaused() && isActing(ACTION_LOOK) && !dsq->game->avatar->isSinging() && dsq->game->avatar->isInputEnabled() && !dsq->game->isInGameMenu())
{
looking = 1;
}
@ -5790,7 +5777,7 @@ void Avatar::onUpdate(float dt)
// revert stuff
float revertGrace = 0.4f;
static bool revertButtonsAreDown = false;
if (inputEnabled && (dsq->getInputMode() == INPUT_KEYBOARD || dsq->getInputMode() == INPUT_MOUSE) && (!pathToActivate && !entityToActivate))
if (inputEnabled && (dsq->getInputMode() == INP_DEV_KEYBOARD || dsq->getInputMode() == INP_DEV_MOUSE) && (!pathToActivate && !entityToActivate))
{
if (dsq->continuity.form != FORM_NORMAL && (core->mouse.pure_buttons.left && core->mouse.pure_buttons.right) && getVectorToCursor(true).isLength2DIn(minMouse))
{
@ -6133,11 +6120,11 @@ void Avatar::onUpdate(float dt)
float len = 0;
if (dsq->isMiniMapCursorOkay() && !isActing(ACTION_ROLL, -1) &&
if (dsq->isMiniMapCursorOkay() && !isActing(ACTION_ROLL) &&
_isUnderWater && !riding && !boneLock.on &&
(movingOn || ((dsq->getInputMode() == INPUT_JOYSTICK || dsq->getInputMode()== INPUT_KEYBOARD) || (core->mouse.buttons.left || bursting))))
(movingOn || ((dsq->getInputMode() == INP_DEV_JOYSTICK || dsq->getInputMode()== INP_DEV_KEYBOARD) || (/*core->mouse.buttons.left ||*/ bursting))))
{
const bool isMouse = dsq->getInputMode() == INPUT_MOUSE;
const bool isMouse = dsq->getInputMode() == INP_DEV_MOUSE;
if (isMouse || !this->singing)
{
addVec = getVectorToCursorFromScreenCentre();//getVectorToCursor();
@ -6145,7 +6132,7 @@ void Avatar::onUpdate(float dt)
if (isMouse)
{
static Vector lastAddVec;
if (!isActing(ACTION_PRIMARY, -1) && bursting)
if (!isActing(ACTION_PRIMARY) && bursting)
{
addVec = lastAddVec;
}
@ -6158,7 +6145,7 @@ void Avatar::onUpdate(float dt)
if (addVec.isLength2DIn(minMouse))
{
if (dsq->getInputMode() == INPUT_JOYSTICK)
if (dsq->getInputMode() == INP_DEV_JOYSTICK)
addVec = Vector(0,0,0);
}
@ -6187,7 +6174,7 @@ void Avatar::onUpdate(float dt)
// For joystick/keyboard control, don't stop unless
// the Swim (primary action) button is pressed with
// no movement input. --achurch
if ((isMouse || isActing(ACTION_PRIMARY, -1))
if ((isMouse || isActing(ACTION_PRIMARY))
&& addVec.isLength2DIn(STOP_DISTANCE))
{
vel *= 0.9f;
@ -6275,14 +6262,14 @@ void Avatar::onUpdate(float dt)
// here for roll key?
// seems like this isn't reached
//if (isActing("roll"))
if (isActing(ACTION_ROLL, -1))
if (isActing(ACTION_ROLL))
{
//debugLog("here");
}
else
{
float t = 0;
if (dsq->getInputMode() == INPUT_KEYBOARD)
if (dsq->getInputMode() == INP_DEV_KEYBOARD)
t = 0.1f;
rotateToVec(addVec, t);
}

View file

@ -138,7 +138,7 @@ public:
Avatar();
virtual ~Avatar();
void destroy();
void action(int actionID, int state, int source, InputDevice device);
void action(int actionID, int state, int source, InputDeviceType device);
AvatarState state;
float burst, burstTimer;
float burstDelay;
@ -179,7 +179,7 @@ public:
void startBurstCommon();
void openSingingInterface(InputDevice device);
void openSingingInterface(InputDeviceType device);
void closeSingingInterface();
void updateSingingInterface(float dt);
@ -331,9 +331,6 @@ public:
bool blockBackFlip;
int getLastActionSourceID() const { return _lastActionSourceID; }
InputDevice getLastActionInputDevice() const { return _lastActionInputDevice; }
protected:
void setSongIconPositions();
@ -440,11 +437,11 @@ protected:
Quad *glow;
bool swimming;
void lmbd(int source, InputDevice device);
void lmbu(int source, InputDevice device);
void lmbd(int source, InputDeviceType device);
void lmbu(int source, InputDeviceType device);
void rmbd(int source, InputDevice device);
void rmbu(int source, InputDevice device);
void rmbd(int source, InputDeviceType device);
void rmbu(int source, InputDeviceType device);
bool charging;
@ -467,10 +464,6 @@ protected:
int _collisionAvoidRange;
float _collisionAvoidMod;
int _lastActionSourceID;
InputDevice _lastActionInputDevice;
};
#endif

View file

@ -193,7 +193,7 @@ DSQ::DSQ(const std::string& fileSystem, const std::string& extraDataDir)
subbox = 0;
modSelectorScr = 0;
blackout = 0;
lastInputMode = INPUT_MOUSE;
lastInputMode = INP_DEV_MOUSE;
overlay = 0;
recentSaveSlot = -1;
arialFontData = 0;
@ -249,24 +249,26 @@ void DSQ::onWindowResize(int w, int h)
screenTransition->reloadDevice();
}
void DSQ::rumble(float leftMotor, float rightMotor, float time, int source, InputDevice device)
void DSQ::rumble(float leftMotor, float rightMotor, float time, int playerID /* = -1 */)
{
if (device == INPUT_JOYSTICK)
{
if(source < 0)
for(size_t i = 0; i < user.control.actionSets.size(); ++i)
{
const ActionSet& as = user.control.actionSets[i];
if(Joystick *j = core->getJoystick(as.joystickID))
j->rumble(leftMotor, rightMotor, time);
}
else if(source < (int)user.control.actionSets.size())
if(lastInputMode != INP_DEV_JOYSTICK)
return;
/* // FIXME controllerfixup
if(source < 0)
for(size_t i = 0; i < user.control.actionSets.size(); ++i)
{
const ActionSet& as = user.control.actionSets[source];
const ActionSet& as = user.control.actionSets[i];
if(Joystick *j = core->getJoystick(as.joystickID))
j->rumble(leftMotor, rightMotor, time);
}
else if(source < (int)user.control.actionSets.size())
{
const ActionSet& as = user.control.actionSets[source];
if(Joystick *j = core->getJoystick(as.joystickID))
j->rumble(leftMotor, rightMotor, time);
}
*/
}
void DSQ::newGame()
@ -502,7 +504,6 @@ void DSQ::debugMenu()
if (core->getShiftState())
{
core->frameOutputMode = false;
dsq->game->togglePause(true);
std::string s = dsq->getUserInputString(stringbank.get(2012), "");
stringToUpper(s);
@ -630,32 +631,6 @@ void DSQ::debugMenu()
is >> read >> nm;
dsq->continuity.setCostume(nm);
}
else if (c == 'R')
{
dsq->demo.toggleRecord(true);
}
else if (c == 'P')
{
dsq->demo.togglePlayback(true);
}
else if (c == 'T')
{
if (dsq->demo.frames.size()> 0)
{
dsq->game->avatar->position = dsq->demo.frames[0].avatarPos;
dsq->game->avatar->rotation.z = dsq->demo.frames[0].rot;
}
}
else if (c == 'U')
{
dsq->demo.renderFramesToDisk();
}
else if (c == 'K')
{
dsq->demo.clearRecordedFrames();
}
else if (c == 'H')
{
std::ostringstream os;
@ -1684,21 +1659,21 @@ void DSQ::toggleVersionLabel(bool on)
versionLabel->alpha.interpolateTo(a, 1);
}
void DSQ::setInputMode(InputDevice mode)
void DSQ::setInputMode(InputDeviceType mode)
{
lastInputMode = mode;
switch(mode)
{
case INPUT_JOYSTICK:
case INP_DEV_JOYSTICK:
core->joystickAsMouse = true;
break;
case INPUT_MOUSE:
case INP_DEV_MOUSE:
setMousePosition(core->mouse.position);
core->joystickAsMouse = false;
break;
case INPUT_KEYBOARD:
case INP_DEV_KEYBOARD:
break;
case INPUT_NODEVICE:
case INP_DEV_NODEVICE:
break;
}
}
@ -3665,7 +3640,7 @@ void DSQ::watch(float t, int canQuit)
}
}
void DSQ::action(int id, int state, int source, InputDevice device)
void DSQ::action(int id, int state, int source, InputDeviceType device)
{
Core::action(id, state, source, device);
@ -3693,10 +3668,8 @@ void DSQ::action(int id, int state, int source, InputDevice device)
void DSQ::bindInput()
{
clearActions();
almb.clear();
armb.clear();
addAction(ACTION_ESC, KEY_ESCAPE, -1);
addAction(ACTION_ESC, KEY_ESCAPE);
addAction(MakeFunctionEvent(DSQ, onSwitchScreenMode), KEY_RETURN, 1);
if (isDeveloperKeys())
@ -3709,19 +3682,15 @@ void DSQ::bindInput()
addAction(MakeFunctionEvent(DSQ, debugMenu), KEY_BACKSPACE, 0);
//addAction(MakeFunctionEvent(DSQ, takeScreenshotKey ), KEY_P, 0);
for(size_t i = 0; i < dsq->user.control.actionSets.size(); ++i)
const NamedAction actions[] =
{
ActionSet& as = dsq->user.control.actionSets[i];
int sourceID = (int)i;
{ "Escape", ACTION_ESC },
{ "Screenshot", ACTION_SCREENSHOT }
};
ImportInput(actions);
as.importAction(this, "Escape", ACTION_ESC, sourceID);
as.importAction(this, "Screenshot", ACTION_SCREENSHOT, sourceID);
if(ActionInput *a = as.getActionInputByName("PrimaryAction"))
almb.push_back(a);
if(ActionInput *a = as.getActionInputByName("SecondaryAction"))
armb.push_back(a);
}
if(game)
game->bindInput();
}
void DSQ::jiggleCursor()
@ -3731,13 +3700,15 @@ void DSQ::jiggleCursor()
SDL_ShowCursor(SDL_DISABLE);
}
#if 0 // FIXME controllerfixup
void DSQ::updateActionButtons()
{
// HACK: not optimal
#if 0
// This must be done *before* Core::updateActionButtons()
// for LMB/RMB emulation to work properly -- fg
if (/*inputMode != INPUT_KEYBOARD &&*/ game->isActive())
if (/*inputMode != INP_DEV_KEYBOARD &&*/ game->isActive())
{
for(size_t i = 0; i < almb.size(); ++i)
if (ActionMapper::getKeyState(almb[i]->data.single.key[0]) || ActionMapper::getKeyState(almb[i]->data.single.key[1]))
@ -3768,9 +3739,11 @@ void DSQ::updateActionButtons()
break;
}
}
#endif
Core::updateActionButtons();
}
#endif
static float skipSfxVol = 1.0;
void DSQ::onUpdate(float dt)
@ -3828,7 +3801,7 @@ void DSQ::onUpdate(float dt)
if (dsq->game && watchForQuit && isNested())
{
if (dsq->game->isActing(ACTION_ESC, -1))
if (dsq->game->isActing(ACTION_ESC))
{
watchQuitFlag = true;
quitNestedMain();
@ -3851,11 +3824,10 @@ void DSQ::onUpdate(float dt)
subtitlePlayer.update(dt);
demo.update(dt);
#if 0 //KILL
if (joystickEnabled)
{
if (dsq->getInputMode() != INPUT_JOYSTICK)
if (dsq->getInputMode() != INP_DEV_JOYSTICK)
{
const float thresh = JOY_AXIS_THRESHOLD;
for(size_t i = 0; i < getNumJoysticks(); ++i)
@ -3864,39 +3836,29 @@ void DSQ::onUpdate(float dt)
if (j->anyButton() || !j->position.isLength2DIn(thresh) || !j->rightStick.isLength2DIn(thresh))
{
//debugLog("setting joystick input mode");
dsq->setInputMode(INPUT_JOYSTICK);
dsq->setInputMode(INP_DEV_JOYSTICK);
}
}
else if (dsq->getInputMode() != INPUT_MOUSE)
else if (dsq->getInputMode() != INP_DEV_MOUSE)
{
if ((!core->mouse.change.isLength2DIn(5) || (core->getMouseButtonState(0) || core->getMouseButtonState(1))) /*&& !core->joystick.anyButton()*/)
if ((!mouse.change.isLength2DIn(5) || (getKeyState(MOUSE_BUTTON_LEFT) || getKeyState(MOUSE_BUTTON_RIGHT)) /*&& !core->joystick.anyButton()*/)
{
//debugLog("setting mouse input mode");
dsq->setInputMode(INPUT_MOUSE);
setInputMode(INP_DEV_MOUSE);
}
}
}
if (dsq->game->avatar)
{
if (dsq->game->avatar->isActing(ACTION_SWIMUP, -1) ||
dsq->game->avatar->isActing(ACTION_SWIMDOWN, -1) ||
dsq->game->avatar->isActing(ACTION_SWIMLEFT, -1) ||
dsq->game->avatar->isActing(ACTION_SWIMRIGHT, -1))
{
dsq->setInputMode(INPUT_KEYBOARD);
}
}
// check the actual values, since mouse.buttons.left might be overwritten by keys
int cb = 0;
int cb = MOUSE_BUTTON_LEFT;
if (user.control.flipInputButtons)
cb = 1;
cb = MOUSE_BUTTON_RIGHT;
if (dsq->getInputMode() == INPUT_KEYBOARD && (core->getMouseButtonState(cb)))
if (dsq->getInputMode() == INP_DEV_KEYBOARD && getKeyState(cb))
{
dsq->setInputMode(INPUT_MOUSE);
dsq->setInputMode(INP_DEV_MOUSE);
}
#endif
if (isDeveloperKeys() && cmDebug && cmDebug->alpha == 1 && fpsText)
@ -3935,16 +3897,18 @@ void DSQ::onUpdate(float dt)
os << "inputMode: ";
switch(dsq->getInputMode())
{
case INPUT_MOUSE:
case INP_DEV_MOUSE:
os << "mouse";
break;
case INPUT_JOYSTICK:
case INP_DEV_JOYSTICK:
os << "joystick";
break;
case INPUT_KEYBOARD:
case INP_DEV_KEYBOARD:
os << "keyboard";
break;
case INP_DEV_NODEVICE:
os << "nodevice";
break;
case INPUT_NODEVICE:
break;
}
os << std::endl;
Bone *b = dsq->game->avatar->skeletalSprite.getBoneByIdx(1);
@ -3964,7 +3928,7 @@ void DSQ::onUpdate(float dt)
os << std::endl;
os << "globalScale: " << core->globalScale.x << std::endl;
os << "mousePos:(" << core->mouse.position.x << ", " << core->mouse.position.y << ") mouseChange:(" << core->mouse.change.x << ", " << core->mouse.change.y << ")\n";
for(size_t i = 0; i < getNumJoysticks(); ++i)
/*for(size_t i = 0; i < getNumJoysticks(); ++i)
if(Joystick *j = getJoystick(i))
{
os << "J[" << i << "," << (j->isEnabled() ? " on" : "off") << "]:[";
@ -3974,7 +3938,7 @@ void DSQ::onUpdate(float dt)
else
os << '-';
os << "], (" << j->position.x << ", " << j->position.y << "), ("<< j->rightStick.x << ", " << j->rightStick.y << ")\n";
}
}*/ // FIXME controllerfixup
os << "altState: " << core->getKeyState(KEY_LALT) << " | " << core->getKeyState(KEY_RALT) << " mb: " << mouse.buttons.left << mouse.buttons.middle << mouse.buttons.right << std::endl;
os << "PMFree: " << particleManager->getFree() << " Active: " << particleManager->getNumActive() << std::endl;
os << "cameraPos: (" << dsq->cameraPos.x << ", " << dsq->cameraPos.y << ")" << std::endl;
@ -4226,17 +4190,6 @@ void DSQ::modifyDt(float &dt)
gameSpeed.update(dt);
dt *= gameSpeed.x;
if (frameOutputMode)
{
dt = 1.0f/60.0f;
doScreenshot = true;
}
if (dsq->demo.mode == Demo::DEMOMODE_RECORD)
{
dt = 1.0f/60.0f;
}
}
void DSQ::removeElement(Element *element)
@ -4485,48 +4438,12 @@ void DSQ::fixupJoysticks()
if(Joystick *j = getJoystick(i))
j->setEnabled(false);
// Re-enable joysticks that are in use
for(size_t i = 0; i < user.control.actionSets.size(); ++i)
{
ActionSet& as = user.control.actionSets[i];
as.updateJoystick();
}
// HACK: why here? kinda dirty, but the joystick ID needs to be propagated
importActionButtons();
}
void DSQ::initActionButtons()
{
clearActionButtons();
std::vector<int> allkeys;
// Don't need joysticks keys for this
for(int i = 0; i < MOUSE_BUTTON_EXTRA_END; ++i)
allkeys.push_back(i);
// create sentinel
ActionButtonStatus *allbtn = new ActionButtonStatus;
allbtn->importQuery(&allkeys[0], allkeys.size());
actionStatus.push_back(allbtn);
// create the rest
for(size_t i = 0; i < user.control.actionSets.size(); ++i)
actionStatus.push_back(new ActionButtonStatus);
importActionButtons();
}
void DSQ::importActionButtons()
{
assert(user.control.actionSets.size()+1 == actionStatus.size());
// ignore sentinel
for(size_t i = 1; i < actionStatus.size(); ++i)
{
const ActionSet& as = user.control.actionSets[i-1];
ActionButtonStatus *abs = actionStatus[i];
abs->import(as);
}
}
void DSQ::loadStringBank()
@ -4547,34 +4464,23 @@ void DSQ::loadStringBank()
stringbank.load(fname);
if (mod.isActive()) {
// FIXME (after controllerfixup) load mod stringbanks HERE, not up there
fname = localisePath(mod.getPath() + "stringbank.txt", mod.getPath());
stringbank.load(fname);
}
}
InputDevice DSQ::getInputMode() const
InputDeviceType DSQ::getInputMode() const
{
return lastInputMode;
}
InputDevice DSQ::getInputMode(int source) const
{
assert(source >= 0 && size_t(source) < _inputModes.size());
return _inputModes[source];
}
InputDevice DSQ::getInputModeSafe(int source) const
{
return source < 0 ? lastInputMode :
(size_t(source) < _inputModes.size() ? _inputModes[source] : INPUT_NODEVICE);
}
bool DSQ::useMouseInput() const
{
return lastInputMode == INPUT_MOUSE;
return lastInputMode == INP_DEV_MOUSE;
}
bool DSQ::useJoystickInput() const
{
return lastInputMode == INPUT_JOYSTICK;
return lastInputMode == INP_DEV_JOYSTICK;
}

View file

@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Continuity.h"
#include "SubtitlePlayer.h"
#include "StringBank.h"
#include "GameInput.h"
#include "TTFFont.h"
#define AQUARIA_BUILD_MAPVIS
@ -133,42 +133,6 @@ extern GameplayVariables *vars;
#include "UserSettings.h"
struct DemoFrame
{
float t;
Vector avatarPos, vel, vel2;
Mouse mouse;
float rot;
};
class Demo
{
public:
enum {
DEMOMODE_NONE = -1,
DEMOMODE_RECORD = 0,
DEMOMODE_PLAYBACK = 1
};
Demo();
void toggleRecord(bool on);
void togglePlayback(bool on);
void renderFramesToDisk();
void clearRecordedFrames();
void update(float dt);
bool getQuitKey();
void save(const std::string &name);
void load(const std::string &name);
unsigned int frame;
float time;
float timeDiff;
std::vector <DemoFrame> frames;
int mode;
};
enum NagType
{
NAG_TOTITLE = 0,
@ -208,7 +172,7 @@ public:
void nag(NagType type);
void action(int id, int state, int source, InputDevice device);
void action(int id, int state, int source, InputDeviceType device);
void title(bool fadeMusic=true);
@ -343,18 +307,16 @@ public:
InterpolatedVector gameSpeed;
GameInput playerInput;
private:
InputDevice lastInputMode; // really don't want to expose this one
std::vector<InputDevice> _inputModes; // index: FIXME ADD INFO
InputDeviceType lastInputMode; // really don't want to expose this one
public:
void setInputMode(InputDevice mode);
InputDevice getInputMode() const;
InputDevice getInputMode(int source) const;
InputDevice getInputModeSafe(int source) const;
void setInputMode(InputDeviceType mode);
InputDeviceType getInputMode() const;
bool useMouseInput() const;
bool useJoystickInput() const;
void rumble(float leftMotor, float rightMotor, float time, int source, InputDevice device);
void rumble(float leftMotor, float rightMotor, float time, int playerID = -1);
void vision(std::string folder, int num, bool ignoreMusic = false);
void run(float runTime = -1, bool skipRecurseCheck = false); // same as Core::run() but with recursion check
@ -394,8 +356,6 @@ public:
std::string returnToScene;
Demo demo;
DebugFont *fpsText, *cmDebug;
#ifdef AQUARIA_BUILD_CONSOLE
DebugFont *console;
@ -492,8 +452,6 @@ protected:
bool _canSkipCutscene;
bool skippingCutscene;
std::vector<ActionInput*> almb, armb;
void recreateBlackBars();
bool watchQuitFlag, watchForQuit;
@ -550,12 +508,10 @@ protected:
virtual void onJoystickAdded(int deviceID);
virtual void onJoystickRemoved(int instanceID);
virtual void updateActionButtons();
//virtual void updateActionButtons();
public:
void fixupJoysticks();
void initActionButtons();
void importActionButtons();
};
extern DSQ *dsq;

View file

@ -1303,13 +1303,13 @@ bool Entity::updateCurrents(float dt)
dist.normalize2D();
float v = dist.x;
float scale = 0.2f;
if (getEntityType() == ET_AVATAR)
if (getEntityType() == ET_AVATAR) // FIXME (after controllerfixup) should be moved to avatar update
{
Avatar *a = dsq->game->avatar;
if (v < 0)
dsq->rumble((-v)*scale, (1.0f+v)*scale, 0.2f, a->getLastActionSourceID(), a->getLastActionInputDevice());
dsq->rumble((-v)*scale, (1.0f+v)*scale, 0.2f);
else
dsq->rumble((1.0f-v)*scale, (v)*scale, 0.1f, a->getLastActionSourceID(), a->getLastActionInputDevice());
dsq->rumble((1.0f-v)*scale, (v)*scale, 0.1f);
}
}
}

View file

@ -2511,10 +2511,10 @@ float Game::getHalfTimer(float mod)
void Game::toggleHelpScreen()
{
action(ACTION_TOGGLEHELPSCREEN, 0, -1, INPUT_NODEVICE);
action(ACTION_TOGGLEHELPSCREEN, 0, -1, INP_DEV_NODEVICE);
}
void Game::action(int id, int state, int source, InputDevice device)
void Game::action(int id, int state, int source, InputDeviceType device)
{
for (size_t i = 0; i < paths.size(); i++)
{
@ -2557,16 +2557,6 @@ void Game::action(int id, int state, int source, InputDevice device)
{
if (id == ACTION_TOGGLEGRID && !state) toggleGridRender();
}
// Forward these to Lua scripts (because digital swim movement should be seen as menu movement as well)
if(id == ACTION_SWIMLEFT)
action(ACTION_MENULEFT, state, source, device);
else if(id == ACTION_SWIMRIGHT)
action(ACTION_MENURIGHT, state, source, device);
else if(id == ACTION_SWIMUP)
action(ACTION_MENUUP, state, source, device);
else if(id == ACTION_SWIMDOWN)
action(ACTION_MENUDOWN, state, source, device);
}
void Game::toggleWorldMap()
@ -3219,69 +3209,62 @@ void Game::bindInput()
ActionMapper::clearActions();
//ActionMapper::clearCreatedEvents();
addAction(ACTION_ESC, KEY_ESCAPE, -1);
addAction(ACTION_ESC, KEY_ESCAPE);
#ifdef AQUARIA_BUILD_SCENEEDITOR
if (dsq->canOpenEditor())
{
addAction(ACTION_TOGGLESCENEEDITOR, KEY_TAB, -1);
addAction(ACTION_TOGGLESCENEEDITOR, KEY_TAB);
}
#endif
if (dsq->canOpenEditor())
{
//addAction(MakeFunctionEvent(Game, toggleMiniMapRender), KEY_M, 0);
addAction(ACTION_TOGGLEGRID, KEY_F9, -1);
addAction(ACTION_TOGGLEGRID, KEY_F9);
}
for(size_t i = 0; i < dsq->user.control.actionSets.size(); ++i)
const NamedAction actions[] =
{
const ActionSet& as = dsq->user.control.actionSets[i];
int sourceID = (int)i;
{ "PrimaryAction", ACTION_PRIMARY},
{ "SecondaryAction", ACTION_SECONDARY},
as.importAction(this, "PrimaryAction", ACTION_PRIMARY, sourceID);
as.importAction(this, "SecondaryAction", ACTION_SECONDARY, sourceID);
as.importAction(this, "Escape", ACTION_ESC, sourceID);
as.importAction(this, "WorldMap", ACTION_TOGGLEWORLDMAP, sourceID);
as.importAction(this, "ToggleHelp", ACTION_TOGGLEHELPSCREEN, sourceID);
{ "Escape", ACTION_ESC},
{ "WorldMap", ACTION_TOGGLEWORLDMAP},
{ "ToggleHelp", ACTION_TOGGLEHELPSCREEN},
// used for scrolling help text
as.importAction(this, "SwimUp", ACTION_SWIMUP, sourceID);
as.importAction(this, "SwimDown", ACTION_SWIMDOWN, sourceID);
as.importAction(this, "SwimLeft", ACTION_SWIMLEFT, sourceID);
as.importAction(this, "SwimRight", ACTION_SWIMRIGHT, sourceID);
{ "SwimUp", ACTION_SWIMUP},
{ "SwimDown", ACTION_SWIMDOWN},
{ "SwimLeft", ACTION_SWIMLEFT},
{ "SwimRight", ACTION_SWIMRIGHT},
as.importAction(this, "MenuUp", ACTION_MENUUP, sourceID);
as.importAction(this, "MenuDown", ACTION_MENUDOWN, sourceID);
as.importAction(this, "MenuLeft", ACTION_MENULEFT, sourceID);
as.importAction(this, "MenuRight", ACTION_MENURIGHT, sourceID);
as.importAction(this, "PrevPage", ACTION_PREVPAGE, sourceID);
as.importAction(this, "NextPage", ACTION_NEXTPAGE, sourceID);
as.importAction(this, "CookFood", ACTION_COOKFOOD, sourceID);
as.importAction(this, "FoodLeft", ACTION_FOODLEFT, sourceID);
as.importAction(this, "FoodRight", ACTION_FOODRIGHT, sourceID);
as.importAction(this, "FoodDrop", ACTION_FOODDROP, sourceID);
{ "PrevPage", ACTION_PREVPAGE},
{ "NextPage", ACTION_NEXTPAGE},
{ "CookFood", ACTION_COOKFOOD},
{ "FoodLeft", ACTION_FOODLEFT},
{ "FoodRight", ACTION_FOODRIGHT},
{ "FoodDrop", ACTION_FOODDROP},
// To capture quick song keys via script
as.importAction(this, "SongSlot1", ACTION_SONGSLOT1, sourceID);
as.importAction(this, "SongSlot2", ACTION_SONGSLOT2, sourceID);
as.importAction(this, "SongSlot3", ACTION_SONGSLOT3, sourceID);
as.importAction(this, "SongSlot4", ACTION_SONGSLOT4, sourceID);
as.importAction(this, "SongSlot5", ACTION_SONGSLOT5, sourceID);
as.importAction(this, "SongSlot6", ACTION_SONGSLOT6, sourceID);
as.importAction(this, "SongSlot7", ACTION_SONGSLOT7, sourceID);
as.importAction(this, "SongSlot8", ACTION_SONGSLOT8, sourceID);
as.importAction(this, "SongSlot9", ACTION_SONGSLOT9, sourceID);
as.importAction(this, "SongSlot10", ACTION_SONGSLOT10, sourceID);
{ "SongSlot1", ACTION_SONGSLOT1},
{ "SongSlot2", ACTION_SONGSLOT2},
{ "SongSlot3", ACTION_SONGSLOT3},
{ "SongSlot4", ACTION_SONGSLOT4},
{ "SongSlot5", ACTION_SONGSLOT5},
{ "SongSlot6", ACTION_SONGSLOT6},
{ "SongSlot7", ACTION_SONGSLOT7},
{ "SongSlot8", ACTION_SONGSLOT8},
{ "SongSlot9", ACTION_SONGSLOT9},
{ "SongSlot10", ACTION_SONGSLOT10},
as.importAction(this, "Revert", ACTION_REVERT, sourceID);
{ "Revert", ACTION_REVERT},
as.importAction(this, "Look", ACTION_LOOK, sourceID);
as.importAction(this, "Roll", ACTION_ROLL, sourceID);
}
{ "Look", ACTION_LOOK},
{ "Roll", ACTION_ROLL}
};
ImportInput(actions);
if (avatar)
avatar->bindInput();
@ -3776,7 +3759,7 @@ bool Game::updateMusic()
return false;
}
void Game::onPressEscape(int source, InputDevice device)
void Game::onPressEscape(int source, InputDeviceType device)
{
if (dsq->isInCutscene())
{
@ -4240,13 +4223,13 @@ void Game::updateCursor(float dt)
{
bool rotate = false;
if (dsq->getInputMode() == INPUT_MOUSE)
if (dsq->getInputMode() == INP_DEV_MOUSE)
{
dsq->cursor->offset.stop();
dsq->cursor->offset = Vector(0,0);
//debugLog("offset lerp stop in mouse!");
}
else if (dsq->getInputMode() == INPUT_JOYSTICK)
else if (dsq->getInputMode() == INP_DEV_JOYSTICK)
{
if (!dsq->game->isPaused() || dsq->game->isInGameMenu() || !dsq->game->avatar->isInputEnabled())
{
@ -4279,7 +4262,7 @@ void Game::updateCursor(float dt)
// Don't show the cursor in keyboard/joystick mode if it's not
// already visible (this keeps the cursor from appearing for an
// instant during map fadeout).
if (dsq->getInputMode() == INPUT_MOUSE || isSceneEditorActive() || dsq->game->isPaused())
if (dsq->getInputMode() == INP_DEV_MOUSE || isSceneEditorActive() || dsq->game->isPaused())
dsq->cursor->alphaMod = 0.5;
/*
@ -4290,7 +4273,7 @@ void Game::updateCursor(float dt)
else if (avatar)
{
//Vector v = avatar->getVectorToCursorFromScreenCentre();
if (dsq->getInputMode() == INPUT_JOYSTICK)// && !avatar->isSinging() && !dsq->game->isInGameMenu() && !dsq->game->isPaused())
if (dsq->getInputMode() == INP_DEV_JOYSTICK)// && !avatar->isSinging() && !dsq->game->isInGameMenu() && !dsq->game->isPaused())
{
dsq->cursor->alphaMod = 0;
if (!avatar->isSinging())
@ -4518,7 +4501,7 @@ void Game::update(float dt)
if (inHelpScreen)
{
const float helpTextScrollSpeed = 400.0f;
if (isActing(ACTION_SWIMDOWN, -1))
if (isActing(ACTION_SWIMDOWN))
{
helpText->offset.stop();
helpText->offset.y -= helpTextScrollSpeed * dt;
@ -4527,7 +4510,7 @@ void Game::update(float dt)
helpText->offset.y = -helpText->getHeight() + core->getVirtualHeight();
}
}
if (isActing(ACTION_SWIMUP, -1))
if (isActing(ACTION_SWIMUP))
{
helpText->offset.stop();
helpText->offset.y += helpTextScrollSpeed * dt;
@ -5027,8 +5010,6 @@ void Game::removeState()
dsq->overlay->alpha.interpolateTo(1, fadeTime);
dsq->run(fadeTime);
dsq->rumble(0,0,0,-1, INPUT_JOYSTICK);
dsq->sound->clearFadingSfx();

View file

@ -176,7 +176,7 @@ public:
void toggleWorldMap();
void action(int id, int state, int source, InputDevice device);
void action(int id, int state, int source, InputDeviceType device);
InGameMenu *getInGameMenu() { return themenu; }
@ -508,7 +508,7 @@ protected:
float deathTimer;
void onPressEscape(int source, InputDevice device);
void onPressEscape(int source, InputDeviceType device);
bool paused;
bool worldPaused;
@ -540,7 +540,7 @@ private:
static unsigned char grid[MAX_GRID][MAX_GRID];
};
extern Game *game;
extern Game *game; // FIXME: dupe of dsq->game, kill this
// INLINE FUNCTIONS

View file

@ -142,7 +142,9 @@ enum AquariaActions
ACTION_LOOK ,
ACTION_TOGGLEHELPSCREEN,
ACTION_PLACE_AVATAR,
ACTION_SCREENSHOT
ACTION_SCREENSHOT,
ACTION_SIZE // for array bounds
};
enum AuraType

41
Aquaria/GameInput.cpp Normal file
View file

@ -0,0 +1,41 @@
#include "GameInput.h"
#include "GameKeys.h"
#include "Joystick.h"
#include <assert.h>
// we use the game actions and 2 analog sticks (where 1 stick is 2 axes)
GameInput::GameInput() : GameControlState(ACTION_SIZE, 2+2)
{
memset(&_emuActions[0], 0, sizeof(_emuActions));
}
Vector GameInput::getStick1() const
{
return Vector(axes[0], axes[1]);
}
Vector GameInput::getStick2() const
{
return Vector(axes[2], axes[3]);
}
void GameInput::update()
{
Vector dir = getStick1();
// Menu input is fired by sufficient analog input or normal dpad input
emulateAction(ACTION_MENULEFT, dir.x > JOY_AXIS_THRESHOLD || buttons[ACTION_SWIMLEFT]);
emulateAction(ACTION_MENURIGHT, dir.x < -JOY_AXIS_THRESHOLD || buttons[ACTION_SWIMRIGHT]);
emulateAction(ACTION_MENUDOWN, dir.y > JOY_AXIS_THRESHOLD || buttons[ACTION_SWIMDOWN]);
emulateAction(ACTION_MENUUP, dir.y < -JOY_AXIS_THRESHOLD || buttons[ACTION_SWIMUP]);
}
void GameInput::emulateAction(unsigned ac, bool on)
{
assert(ac < sizeof(_emuActions));
if(_emuActions[ac] != on)
{
_emuActions[ac] = on;
IInputMapper::ForwardAction(ac, on, -1, INP_DEV_NODEVICE);
}
}

21
Aquaria/GameInput.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef GAMEINPUT_H
#define GAMEINPUT_H
#include "Vector.h"
#include "InputMapper.h"
#include "GameEnums.h"
class GameInput : public GameControlState
{
public:
GameInput();
void update();
Vector getStick1() const;
Vector getStick2() const;
private:
void emulateAction(unsigned ac, bool on);
bool _emuActions[ACTION_SIZE];
};
#endif

View file

@ -91,7 +91,7 @@ public:
Vector getAvatarWorldMapPosition();
Vector getWorldToTile(WorldMapTile *tile, Vector position, bool fromCenter, bool tilePos);
void setProperTileColor(WorldMapTile *tile);
void action(int id, int state, int source, InputDevice device);
void action(int id, int state, int source, InputDeviceType device);
GemMover* addGem(GemData *gemData);
void bindInput();
void createGemHint(const std::string &gfx);

View file

@ -646,7 +646,7 @@ void FoodSlot::onUpdate(float dt)
{
if (!themenu->recipeMenu.on)
{
if (dsq->getInputMode() == INPUT_MOUSE)
if (dsq->getInputMode() == INP_DEV_MOUSE)
{
Vector diff = core->mouse.position - getWorldPosition();
position += diff;
@ -925,32 +925,25 @@ InGameMenu::~InGameMenu()
void InGameMenu::bindInput()
{
addAction(ACTION_ESC, KEY_ESCAPE, -1);
addAction(ACTION_ESC, KEY_ESCAPE);
for(size_t i = 0; i < dsq->user.control.actionSets.size(); ++i)
const NamedAction actions[] =
{
const ActionSet& as = dsq->user.control.actionSets[i];
int sourceID = (int)i;
{ "PrimaryAction", ACTION_PRIMARY},
{ "SecondaryAction", ACTION_SECONDARY},
as.importAction(this, "PrimaryAction", ACTION_PRIMARY, sourceID);
as.importAction(this, "SecondaryAction", ACTION_SECONDARY, sourceID);
{ "Escape", ACTION_ESC},
{ "WorldMap", ACTION_TOGGLEWORLDMAP},
{ "ToggleHelp", ACTION_TOGGLEHELPSCREEN},
as.importAction(this, "Escape", ACTION_ESC, sourceID);
as.importAction(this, "WorldMap", ACTION_TOGGLEWORLDMAP, sourceID);
as.importAction(this, "ToggleHelp", ACTION_TOGGLEHELPSCREEN, sourceID);
as.importAction(this, "PrevPage", ACTION_PREVPAGE, sourceID);
as.importAction(this, "NextPage", ACTION_NEXTPAGE, sourceID);
as.importAction(this, "CookFood", ACTION_COOKFOOD, sourceID);
as.importAction(this, "FoodLeft", ACTION_FOODLEFT, sourceID);
as.importAction(this, "FoodRight", ACTION_FOODRIGHT, sourceID);
as.importAction(this, "FoodDrop", ACTION_FOODDROP, sourceID);
as.importAction(this, "MenuUp", ACTION_MENUUP, sourceID);
as.importAction(this, "MenuDown", ACTION_MENUDOWN, sourceID);
as.importAction(this, "MenuLeft", ACTION_MENULEFT, sourceID);
as.importAction(this, "MenuRight", ACTION_MENURIGHT, sourceID);
}
{ "PrevPage", ACTION_PREVPAGE},
{ "NextPage", ACTION_NEXTPAGE},
{ "CookFood", ACTION_COOKFOOD},
{ "FoodLeft", ACTION_FOODLEFT},
{ "FoodRight", ACTION_FOODRIGHT},
{ "FoodDrop", ACTION_FOODDROP}
};
ImportInput(actions);
}
void InGameMenu::reset()
@ -981,7 +974,7 @@ void InGameMenu::onContinuityReset()
lastOptionsMenuPage = MENUPAGE_NONE;
}
void InGameMenu::action(int id, int state, int source, InputDevice device)
void InGameMenu::action(int id, int state, int source, InputDeviceType device)
{
if(game->isIgnoreAction((AquariaActions)id))
return;
@ -1532,25 +1525,25 @@ void InGameMenu::addKeyConfigLine(RenderObject *group, const std::string &label,
group->addChild(lb, PM_POINTER);
x += KEYCONFIG_FIRST_COL_DISTANCE;
AquariaKeyConfig *m = new AquariaKeyConfig(actionInputName, INPUTSET_MOUSE, 0);
AquariaKeyConfig *m = new AquariaKeyConfig(actionInputName, INP_DEV_MOUSE, 0);
m->position = Vector(x,y);
group->addChild(m, PM_POINTER);
keyConfigs.push_back(m);
x += KEYCONFIG_COL_DISTANCE;
AquariaKeyConfig *k1 = new AquariaKeyConfig(actionInputName, INPUTSET_KEY, 0);
AquariaKeyConfig *k1 = new AquariaKeyConfig(actionInputName, INP_DEV_KEYBOARD, 0);
k1->position = Vector(x,y);
group->addChild(k1, PM_POINTER);
keyConfigs.push_back(k1);
x += KEYCONFIG_COL_DISTANCE;
AquariaKeyConfig *k2 = new AquariaKeyConfig(actionInputName, INPUTSET_KEY, 1);
AquariaKeyConfig *k2 = new AquariaKeyConfig(actionInputName, INP_DEV_KEYBOARD, 1);
k2->position = Vector(x,y);
group->addChild(k2, PM_POINTER);
keyConfigs.push_back(k2);
x += KEYCONFIG_COL_DISTANCE;
AquariaKeyConfig *j1 = new AquariaKeyConfig(actionInputName, INPUTSET_JOY, 0);
AquariaKeyConfig *j1 = new AquariaKeyConfig(actionInputName, INP_DEV_JOYSTICK, 0);
j1->position = Vector(x,y);
group->addChild(j1, PM_POINTER);
keyConfigs.push_back(j1);
@ -1567,6 +1560,7 @@ void InGameMenu::addKeyConfigLine(RenderObject *group, const std::string &label,
k2->setDirMove(DIR_LEFT, k1);
}
/* FIXME controllerfixup
AquariaKeyConfig *InGameMenu::addAxesConfigLine(RenderObject *group, const std::string &label, const std::string &actionInputName, int offx, int y)
{
TTFText *lb = new TTFText(&dsq->fontArialSmallest);
@ -1584,7 +1578,7 @@ AquariaKeyConfig *InGameMenu::addAxesConfigLine(RenderObject *group, const std::
return i1;
}
*/
void InGameMenu::switchToSongMenu()
{
@ -2152,7 +2146,7 @@ void InGameMenu::create()
addKeyConfigLine(kk, SB(2127), "Look", offx, y+=yi);
y+=yi+yi/2;
AquariaKeyConfig* s1x = addAxesConfigLine(kk, SB(2117), "s1ax", offx, y);
/*AquariaKeyConfig* s1x = addAxesConfigLine(kk, SB(2117), "s1ax", offx, y);
AquariaKeyConfig* s1y = addAxesConfigLine(kk, SB(2118), "s1ay", offx+130, y);
AquariaKeyConfig* s2x = addAxesConfigLine(kk, SB(2119), "s2ax", offx+260, y);
AquariaKeyConfig* s2y = addAxesConfigLine(kk, SB(2120), "s2ay", offx+380, y);
@ -2167,7 +2161,7 @@ void InGameMenu::create()
s2x->setDirMove(DIR_RIGHT, s2y);
s2y->setDirMove(DIR_LEFT, s2x);
s2y->setDirMove(DIR_RIGHT, s2y);
s2y->setDirMove(DIR_RIGHT, s2y);*/ // FIXME controllerfixup
}
// PART 2
@ -4263,10 +4257,10 @@ void InGameMenu::updateJoystickText()
if(j)
{
joystickNameText->setText(j->getName());
int numb = j->getNumButtons();
for(int i = 0; i < numb; ++i)
/*int numb = j->getNumButtons();
for(int i = 0; i < numb; ++i) // FIXME controllerfixup
if(j->getButton(i))
jbt << i << " ";
jbt << i << " ";*/
}
else if(as.joystickID == ACTIONSET_REASSIGN_JOYSTICK)
{

View file

@ -88,7 +88,7 @@ public:
void onContinuityReset();
void bindInput();
virtual void action(int actionID, int state, int source, InputDevice device);
virtual void action(int actionID, int state, int source, InputDeviceType device);
void refreshFoodSlots(bool effects);

View file

@ -413,7 +413,7 @@ void MiniMapRender::onUpdate(float dt)
{
doubleClickDelay = 0;
if (!core->isStateJumpPending())
dsq->game->action(ACTION_TOGGLEMENU, 1, -1, INPUT_NODEVICE);
dsq->game->action(ACTION_TOGGLEMENU, 1, -1, INP_DEV_NODEVICE);
btn = true;
}
break;

View file

@ -119,7 +119,7 @@ void ModSelectorScreen::onUpdate(float dt)
}
}
if(!AquariaGuiElement::currentFocus && dsq->getInputMode() == INPUT_JOYSTICK)
if(!AquariaGuiElement::currentFocus && dsq->getInputMode() == INP_DEV_JOYSTICK)
{
AquariaGuiElement *closest = AquariaGuiElement::getClosestGuiElement(core->mouse.position);
if(closest)

View file

@ -166,7 +166,7 @@ public:
void setSubText(const std::string& s);
virtual void action(int actionID, int state, int source, InputDevice device) {}
virtual void action(int actionID, int state, int source, InputDeviceType device) {}
protected:
virtual void onUpdate(float dt);

View file

@ -637,7 +637,7 @@ void Path::update(float dt)
}
}
bool Path::action(int id, int state, int source, InputDevice device)
bool Path::action(int id, int state, int source, InputDeviceType device)
{
if (hasScript())
{

View file

@ -91,7 +91,7 @@ public:
void addNode(size_t idx);
void update(float dt);
void setActive(bool v);
bool action(int id, int state, int source, InputDevice device);
bool action(int id, int state, int source, InputDeviceType device);
void setEmitter(const std::string& name);
PathNode *getPathNode(size_t idx);

View file

@ -577,37 +577,37 @@ void SceneEditor::init()
addAction(ACTION_ZOOMIN, KEY_PGUP, -1);
addAction(ACTION_ZOOMOUT, KEY_PGDN, -1);
addAction(ACTION_ZOOMIN, KEY_PGUP);
addAction(ACTION_ZOOMOUT, KEY_PGDN);
addAction(ACTION_CAMLEFT, KEY_A, -1);
addAction(ACTION_CAMRIGHT, KEY_D, -1);
addAction(ACTION_CAMUP, KEY_W, -1);
addAction(ACTION_CAMDOWN, KEY_S, -1);
addAction(ACTION_CAMLEFT, KEY_A);
addAction(ACTION_CAMRIGHT, KEY_D);
addAction(ACTION_CAMUP, KEY_W);
addAction(ACTION_CAMDOWN, KEY_S);
addAction(ACTION_BGLAYEREND, KEY_0, -1);
addAction(ACTION_BGLAYEREND, KEY_0);
addAction(ACTION_BGLAYER1, KEY_1, -1);
addAction(ACTION_BGLAYER2, KEY_2, -1);
addAction(ACTION_BGLAYER3, KEY_3, -1);
addAction(ACTION_BGLAYER4, KEY_4, -1);
addAction(ACTION_BGLAYER5, KEY_5, -1);
addAction(ACTION_BGLAYER6, KEY_6, -1);
addAction(ACTION_BGLAYER7, KEY_7, -1);
addAction(ACTION_BGLAYER8, KEY_8, -1);
addAction(ACTION_BGLAYER9, KEY_9, -1);
addAction(ACTION_BGLAYER1, KEY_1);
addAction(ACTION_BGLAYER2, KEY_2);
addAction(ACTION_BGLAYER3, KEY_3);
addAction(ACTION_BGLAYER4, KEY_4);
addAction(ACTION_BGLAYER5, KEY_5);
addAction(ACTION_BGLAYER6, KEY_6);
addAction(ACTION_BGLAYER7, KEY_7);
addAction(ACTION_BGLAYER8, KEY_8);
addAction(ACTION_BGLAYER9, KEY_9);
addAction(ACTION_BGLAYER10, KEY_B, -1);
addAction(ACTION_BGLAYER11, KEY_N, -1);
addAction(ACTION_BGLAYER12, KEY_M, -1);
addAction(ACTION_BGLAYER10, KEY_B);
addAction(ACTION_BGLAYER11, KEY_N);
addAction(ACTION_BGLAYER12, KEY_M);
addAction(ACTION_BGLAYER13, KEY_J, -1);
addAction(ACTION_BGLAYER13, KEY_J);
addAction(ACTION_BGLAYER14, KEY_COMMA, -1);
addAction(ACTION_BGLAYER15, KEY_PERIOD, -1);
addAction(ACTION_BGLAYER16, KEY_SLASH, -1);
addAction(ACTION_BGLAYER14, KEY_COMMA);
addAction(ACTION_BGLAYER15, KEY_PERIOD);
addAction(ACTION_BGLAYER16, KEY_SLASH);
addAction(ACTION_MULTISELECT, KEY_LALT, -1);
addAction(ACTION_MULTISELECT, KEY_LALT);
placer = new Quad;
dsq->game->addRenderObject(placer, LR_HUD);
@ -1845,7 +1845,7 @@ void SceneEditor::removeEntity()
void SceneEditor::placeAvatar()
{
dsq->game->avatar->position = dsq->getGameCursorPosition();
dsq->game->action(ACTION_PLACE_AVATAR, 0, -1, INPUT_NODEVICE);
dsq->game->action(ACTION_PLACE_AVATAR, 0, -1, INP_DEV_NODEVICE);
}
void SceneEditor::scaleElementUp()
@ -1952,7 +1952,7 @@ void SceneEditor::updateMultiSelect()
}
}
void SceneEditor::action(int id, int state, int source, InputDevice device)
void SceneEditor::action(int id, int state, int source, InputDeviceType device)
{
if (core->getCtrlState() && editingElement)
{
@ -2788,11 +2788,11 @@ void SceneEditor::update(float dt)
{
case ET_ELEMENTS:
editingEntity = 0;
if (isActing(ACTION_MULTISELECT, -1) || !selectedElements.empty())
if (isActing(ACTION_MULTISELECT) || !selectedElements.empty())
{
editingElement = 0;
}
if (state == ES_SELECTING && !isActing(ACTION_MULTISELECT, -1))
if (state == ES_SELECTING && !isActing(ACTION_MULTISELECT))
editingElement = this->getElementAtCursor();
if (editingElement)
@ -2825,13 +2825,13 @@ void SceneEditor::update(float dt)
int camSpeed = 500/zoom.x;
if (core->getShiftState())
camSpeed = 5000/zoom.x;
if (isActing(ACTION_CAMLEFT, -1))
if (isActing(ACTION_CAMLEFT))
dsq->cameraPos.x -= dt*camSpeed;
if (isActing(ACTION_CAMRIGHT, -1))
if (isActing(ACTION_CAMRIGHT))
dsq->cameraPos.x += dt*camSpeed;
if (isActing(ACTION_CAMUP, -1))
if (isActing(ACTION_CAMUP))
dsq->cameraPos.y -= dt*camSpeed;
if (isActing(ACTION_CAMDOWN, -1))
if (isActing(ACTION_CAMDOWN))
dsq->cameraPos.y += dt*camSpeed;
if (core->mouse.buttons.middle && !core->mouse.change.isZero())
{
@ -2841,9 +2841,9 @@ void SceneEditor::update(float dt)
float spd = 0.5;
const Vector oldZoom = zoom;
if (isActing(ACTION_ZOOMOUT, -1))
if (isActing(ACTION_ZOOMOUT))
zoom /= (1 + spd*dt);
else if (isActing(ACTION_ZOOMIN, -1))
else if (isActing(ACTION_ZOOMIN))
zoom *= (1 + spd*dt);
else if (core->mouse.scrollWheelChange < 0)
{

View file

@ -89,7 +89,7 @@ public:
void flipElementVert();
void deleteSelectedElement();
void deleteElement(int selectedIdx);
virtual void action(int id, int state, int source, InputDevice device);
virtual void action(int id, int state, int source, InputDeviceType device);
void scaleElementUp();
void scaleElementDown();
void scaleElement1();

View file

@ -2081,7 +2081,7 @@ luaFunc(sendAction)
int state = lua_tointeger(L, 2);
int mask = lua_tointeger(L, 3);
int source = lua_tointeger(L, 4);
InputDevice device = (InputDevice)lua_tointeger(L, 5);
InputDeviceType device = (InputDeviceType)lua_tointeger(L, 5);
if(!mask)
mask = -1;
if(mask & 1)
@ -2117,12 +2117,8 @@ luaFunc(shakeCamera)
luaFunc(rumble)
{
int source = lua_tointeger(L, 4) - 1;
Avatar *a = dsq->game->avatar;
InputDevice device = (InputDevice)lua_tointeger(L, 5);
if(device == INPUT_NODEVICE) // default: use avatar status
device = a ? a->getLastActionInputDevice() : INPUT_NODEVICE;
dsq->rumble(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3), source, device);
int playerID = lua_tointeger(L, 4) - 1;
dsq->rumble(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3), playerID);
luaReturnNil();
}
@ -5014,24 +5010,24 @@ luaFunc(screenFadeGo)
luaFunc(isEscapeKey)
{
int source = lua_tointeger(L, 1) - 1;
bool isDown = dsq->game->isActing(ACTION_ESC, source);
int playerID = lua_tointeger(L, 1) - 1; // FIXME controllerfixup
bool isDown = dsq->game->isActing(ACTION_ESC);
luaReturnBool(isDown);
}
luaFunc(isLeftMouse)
{
int source = lua_tointeger(L, 1) - 1;
bool isDown = (source < 0 && core->mouse.buttons.left)
|| (dsq->game->avatar && dsq->game->avatar->isActing(ACTION_PRIMARY, source));
int playerID = lua_tointeger(L, 1) - 1; // FIXME controllerfixup
bool isDown = (playerID < 0 && core->mouse.buttons.left)
|| (dsq->game->avatar && dsq->game->avatar->isActing(ACTION_PRIMARY));
luaReturnBool(isDown);
}
luaFunc(isRightMouse)
{
int source = lua_tointeger(L, 1) - 1;
bool isDown = (source < 0 && core->mouse.buttons.right)
|| (dsq->game->avatar && dsq->game->avatar->isActing(ACTION_SECONDARY, source));
int playerID = lua_tointeger(L, 1) - 1; // FIXME controllerfixup
bool isDown = (playerID < 0 && core->mouse.buttons.right)
|| (dsq->game->avatar && dsq->game->avatar->isActing(ACTION_SECONDARY));
luaReturnBool(isDown);
}
@ -8395,32 +8391,33 @@ luaFunc(disableInput)
luaFunc(getInputMode)
{
int source = lua_tointeger(L, 1);
luaReturnInt(dsq->getInputModeSafe(source - 1));
//int playerID = lua_tointeger(L, 1) - 1; // FIXME controllerfixup?
luaReturnInt(dsq->getInputMode());
}
static Joystick *_getJoystick(lua_State *L, int idx = 1)
// FIXME: repair for controllerfixup
/*static Joystick *_getJoystick(lua_State *L, int idx = 1)
{
int source = lua_tointeger(L, idx) - 1;
if(source < 0)
return core->getJoystick(0); // HACK: FIXME: do something sensible instead
return core->getJoystickForSourceID(source);
}
}*/
luaFunc(getJoystickAxisLeft)
{
Vector v;
if(Joystick *j = _getJoystick(L))
v = j->position;
//if(Joystick *j = _getJoystick(L))
// v = j->position;
luaReturnVec2(v.x, v.y);
}
luaFunc(getJoystickAxisRight)
{
Vector v;
if(Joystick *j = _getJoystick(L))
v = j->rightStick;
//if(Joystick *j = _getJoystick(L))
// v = j->rightStick;
luaReturnVec2(v.x, v.y);
}
@ -11449,9 +11446,9 @@ static const struct {
luaConstant(TILE_SIZE),
luaConstant(INPUT_MOUSE),
luaConstant(INPUT_JOYSTICK),
luaConstant(INPUT_KEYBOARD),
luaConstant(INP_DEV_MOUSE),
luaConstant(INP_DEV_JOYSTICK),
luaConstant(INP_DEV_KEYBOARD),
luaConstant(ANIMLAYER_FLOURISH),
luaConstant(ANIMLAYER_OVERRIDE),

View file

@ -135,8 +135,6 @@ GameOver::GameOver() : StateObject()
void GameOver::applyState()
{
const bool frameOutputGameOver = false;
core->sound->fadeMusic(SFT_OUT, 1);
@ -147,12 +145,6 @@ void GameOver::applyState()
core->sound->playSfx("Death");
if (frameOutputGameOver)
{
dsq->fpsText->alpha = 0;
core->frameOutputMode = true;
}
Quad *q = new Quad;
{
q->color = 0;
@ -248,13 +240,6 @@ void GameOver::applyState()
}
else
dsq->title();
if (frameOutputGameOver)
core->frameOutputMode = false;
}
void GameOver::removeState()

View file

@ -218,7 +218,7 @@ void UserSettings::save()
{
XMLElement *xml_action = doc.NewElement("Action");
const ActionInput& ai = as.inputSet[i];
xml_action->SetAttribute("name", ai.name.c_str());
xml_action->SetAttribute("name", ai.getName().c_str());
xml_action->SetAttribute("input", ai.toString().c_str());
xml_actionSet->InsertEndChild(xml_action);
@ -280,30 +280,30 @@ void UserSettings::save()
static void ensureDefaultActions(ActionSet& as)
{
as.clearActions();
as.addActionInput("PrimaryAction");
as.addActionInput("SecondaryAction");
as.addActionInput("SwimUp");
as.addActionInput("SwimDown");
as.addActionInput("SwimLeft");
as.addActionInput("SwimRight");
as.addActionInput("Roll");
as.addActionInput("Revert");
as.addActionInput("WorldMap");
as.addActionInput("Escape");
as.addActionInput("PrevPage");
as.addActionInput("NextPage");
as.addActionInput("CookFood");
as.addActionInput("FoodLeft");
as.addActionInput("FoodRight");
as.addActionInput("FoodDrop");
as.addActionInput("Look");
as.addActionInput("ToggleHelp");
as.addActionInput("Screenshot");
as.ensureActionInput("PrimaryAction");
as.ensureActionInput("SecondaryAction");
as.ensureActionInput("SwimUp");
as.ensureActionInput("SwimDown");
as.ensureActionInput("SwimLeft");
as.ensureActionInput("SwimRight");
as.ensureActionInput("Roll");
as.ensureActionInput("Revert");
as.ensureActionInput("WorldMap");
as.ensureActionInput("Escape");
as.ensureActionInput("PrevPage");
as.ensureActionInput("NextPage");
as.ensureActionInput("CookFood");
as.ensureActionInput("FoodLeft");
as.ensureActionInput("FoodRight");
as.ensureActionInput("FoodDrop");
as.ensureActionInput("Look");
as.ensureActionInput("ToggleHelp");
as.ensureActionInput("Screenshot");
for(int i = 1; i <= 10; ++i)
{
std::ostringstream os;
os << "SongSlot" << i;
as.addActionInput(os.str());
as.ensureActionInput(os.str());
}
}
@ -505,8 +505,8 @@ void UserSettings::load(bool doApply, const std::string &overrideFile)
const char *input = xml_action->Attribute("input");
if (name && *name && input && *input)
{
ActionInput *ai = as.addActionInput(name);
ai->fromString(input);
ActionInput& ai = as.ensureActionInput(name);
ai.fromString(input);
}
}
}
@ -584,30 +584,10 @@ void UserSettings::apply()
dsq->loops.updateVolume();
for(size_t i = 0; i < control.actionSets.size(); ++i)
{
ActionSet& as = control.actionSets[i];
Joystick *j = core->getJoystick(as.joystickID);
if(j)
{
j->s1ax = as.joycfg.s1ax;
j->s1ay = as.joycfg.s1ay;
j->s2ax = as.joycfg.s2ax;
j->s2ay = as.joycfg.s2ay;
j->deadZone1 = as.joycfg.s1dead;
j->deadZone2 = as.joycfg.s2dead;
}
}
dsq->initActionButtons();
dsq->fixupJoysticks();
core->debugLogActive = system.debugLogOn;
if (dsq->game)
{
dsq->game->bindInput();
}
dsq->bindInput();
core->settings.prebufferSounds = audio.prebuffer;

View file

@ -794,21 +794,19 @@ void WorldMapRender::bindInput()
clearActions();
clearCreatedEvents();
addAction(ACTION_TOGGLEWORLDMAPEDITOR, KEY_TAB, -1);
addAction(ACTION_TOGGLEWORLDMAPEDITOR, KEY_TAB);
for(size_t i = 0; i < dsq->user.control.actionSets.size(); ++i)
const NamedAction actions[] =
{
const ActionSet& as = dsq->user.control.actionSets[i];
int sourceID = (int)i;
{ "PrimaryAction", ACTION_PRIMARY },
{ "SecondaryAction", ACTION_SECONDARY },
as.importAction(this, "PrimaryAction", ACTION_PRIMARY, sourceID);
as.importAction(this, "SecondaryAction", ACTION_SECONDARY, sourceID);
as.importAction(this, "SwimLeft", ACTION_SWIMLEFT, sourceID);
as.importAction(this, "SwimRight", ACTION_SWIMRIGHT, sourceID);
as.importAction(this, "SwimUp", ACTION_SWIMUP, sourceID);
as.importAction(this, "SwimDown", ACTION_SWIMDOWN, sourceID);
}
{ "SwimLeft", ACTION_SWIMLEFT },
{ "SwimRight", ACTION_SWIMRIGHT },
{ "SwimUp", ACTION_SWIMUP },
{ "SwimDown", ACTION_SWIMDOWN }
};
ImportInput(actions);
}
void WorldMapRender::destroy()
@ -992,15 +990,15 @@ void WorldMapRender::onUpdate(float dt)
{
float scrollSpeed = 2.0f;
float amt = (400*dt)/scale.x;
if (isActing(ACTION_SWIMLEFT, -1))
if (isActing(ACTION_SWIMLEFT))
{
internalOffset += Vector(amt, 0);
}
if (isActing(ACTION_SWIMRIGHT, -1))
if (isActing(ACTION_SWIMRIGHT))
{
internalOffset += Vector(-amt, 0);
}
if (isActing(ACTION_SWIMDOWN, -1))
if (isActing(ACTION_SWIMDOWN))
{
if (core->getShiftState())
{
@ -1012,7 +1010,7 @@ void WorldMapRender::onUpdate(float dt)
internalOffset += Vector(0, -amt);
}
}
if (isActing(ACTION_SWIMUP, -1))
if (isActing(ACTION_SWIMUP))
{
if (core->getShiftState())
{
@ -1024,10 +1022,10 @@ void WorldMapRender::onUpdate(float dt)
internalOffset += Vector(0, amt);
}
}
#if 0 // FIXME controllerfixup
if (core->joystickEnabled)
{
if (isActing(ACTION_SECONDARY, -1))
if (isActing(ACTION_SECONDARY))
{
Vector jpos;
for(size_t i = 0; i < core->getNumJoysticks(); ++i)
@ -1061,6 +1059,7 @@ void WorldMapRender::onUpdate(float dt)
internalOffset += jpos * (-400*dt / scale.x);
}
}
#endif
}
if (activeTile && activeTile->layer == 1)
@ -1501,7 +1500,7 @@ void WorldMapRender::updateEditor()
areaLabel->setText(os.str());
}
void WorldMapRender::action (int id, int state, int source, InputDevice device)
void WorldMapRender::action (int id, int state, int source, InputDeviceType device)
{
if (isOn())
{

View file

@ -26,267 +26,267 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GameKeyNames.h"
#include "StringBank.h"
static std::string inputcode2string(int k)
{
if(k <= 0)
return std::string();
if(k < KEY_MAXARRAY)
{
// Returns KEY_* or NULL
const std::string& str = getKeyNameFromInputCode(k);
if(str.length())
return str;
// fallback
std::ostringstream os;
os << "K:" << k;
return os.str();
}
if(k >= JOY_BUTTON_0 && k < JOY_BUTTON_END)
{
std::ostringstream os;
os << "JB:" << (k - JOY_BUTTON_0);
return os.str();
}
if(k >= JOY_AXIS_0_POS && k < JOY_AXIS_END_POS)
{
std::ostringstream os;
os << "AX:+" << (k - JOY_AXIS_0_POS);
return os.str();
}
if(k >= JOY_AXIS_0_NEG && k < JOY_AXIS_END_NEG)
{
std::ostringstream os;
os << "AX:-" << (k - JOY_AXIS_0_NEG);
return os.str();
}
if(k >= JOY_HAT_BEGIN && k < JOY_HAT_END)
{
if(k >= JOY_HAT_0_LEFT && k < JOY_HAT_END_LEFT)
{
std::ostringstream os;
os << "HL" << (k - JOY_HAT_0_LEFT);
return os.str();
}
else if(k >= JOY_HAT_0_RIGHT && k < JOY_HAT_END_RIGHT)
{
std::ostringstream os;
os << "HR" << (k - JOY_HAT_0_RIGHT);
return os.str();
}
else if(k >= JOY_HAT_0_UP && k < JOY_HAT_END_UP)
{
std::ostringstream os;
os << "HU" << (k - JOY_HAT_0_UP);
return os.str();
}
else if(k >= JOY_HAT_0_DOWN && k < JOY_HAT_END_DOWN)
{
std::ostringstream os;
os << "HD" << (k - JOY_HAT_0_DOWN);
return os.str();
}
}
switch(k)
{
case MOUSE_BUTTON_LEFT:
return "LMB";
case MOUSE_BUTTON_RIGHT:
return "RMB";
case MOUSE_BUTTON_MIDDLE:
return "MMB";
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();
}
}
return std::string();
}
static const char *jaxisname(int joystickID, int axis)
static const char *jaxisname(int joystickID, unsigned axis)
{
Joystick *j = core->getJoystick(joystickID);
return j ? j->getAxisName(axis) : NULL;
const char *s = j ? j->getAxisName(axis - 1) : NULL;
return s && *s ? s : NULL;
}
static const char *jbtnname(int joystickID, int btn)
static const char *jbtnname(int joystickID, unsigned btn)
{
Joystick *j = core->getJoystick(joystickID);
return j ? j->getButtonName(btn) : NULL;
const char *s = j ? j->getButtonName(btn - 1) : NULL;
return s && *s ? s : NULL;
}
std::string getInputCodeToString(int k)
struct JoyHatDir
{
std::string s = inputcode2string(k);
return s.empty() ? "0" : s;
char c, pretty;
int x, y;
};
static const JoyHatDir s_joyhat[] =
{
{ 'u', '^', 0, -1 },
{ 'd', 'v', 0, 1 },
{ 'l', '<', -1, 0 },
{ 'r', '>', 0, 1 },
{ 0, 0, 0, 0 }, // terminator
};
static std::string num2str(unsigned x)
{
std::ostringstream os;
os << x;
return os.str();
}
std::string getInputCodeToUserString(unsigned int k, size_t joystickID)
static std::string getMouseButtonToString(unsigned b)
{
const char *pretty = NULL, *tail = NULL;
static const char *buf[] = { "LMB", "MMB", "RMB" };
if(b && b < 4) // 1 2 3
return buf[b-1];
return num2str(b);
}
static const char *getRawSDLKeyName(unsigned k)
{
const char *s = NULL;
#ifdef BBGE_BUILD_SDL2
s = SDL_GetScancodeName((SDL_Scancode)k);
#else
s = SDL_GetKeyName((SDLKey)k);
#endif
return s && *s ? s : NULL;
}
static const char *getPrettySDLKeyName(unsigned k)
{
const char *s;
#ifdef BBGE_BUILD_SDL2
// 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...
if(k && k < KEY_MAXARRAY)
{
#ifdef BBGE_BUILD_SDL2
pretty = SDL_GetScancodeName((SDL_Scancode)k);
const SDL_Keycode kcode = SDL_GetKeyFromScancode((SDL_Scancode)k);
if(kcode != SDLK_UNKNOWN)
pretty = SDL_GetKeyName(kcode);
const SDL_Keycode kcode = SDL_GetKeyFromScancode((SDL_Scancode)k);
if(kcode == SDLK_UNKNOWN)
s = SDL_GetScancodeName((SDL_Scancode)k);
else
s = SDL_GetKeyName(kcode);
#else
pretty = SDL_GetKeyName((SDLKey)k);
s = SDL_GetKeyName((SDLKey)k);
#endif
}
if(k >= JOY_AXIS_0_POS && k < JOY_AXIS_END_POS)
{
pretty = jaxisname(joystickID, k - JOY_AXIS_0_POS);
tail = "(+)";
}
else if(k >= JOY_AXIS_0_NEG && k < JOY_AXIS_END_NEG)
{
pretty = jaxisname(joystickID, k - JOY_AXIS_0_NEG);
tail = "(-)";
}
else if(k >= JOY_BUTTON_0 && k < JOY_BUTTON_END)
pretty = jbtnname(joystickID, k - JOY_BUTTON_0);
std::string s;
if(pretty && *pretty)
{
s = pretty;
if(tail)
s += tail;
return s;
}
if(k >= JOY_HAT_BEGIN && k < JOY_HAT_END)
{
if(k >= JOY_HAT_0_LEFT && k < JOY_HAT_END_LEFT)
{
std::ostringstream os;
os << "H" << (k - JOY_HAT_0_LEFT) << "<";
return os.str();
}
else if(k >= JOY_HAT_0_RIGHT && k < JOY_HAT_END_RIGHT)
{
std::ostringstream os;
os << "H" << (k - JOY_HAT_0_RIGHT) << ">";
return os.str();
}
else if(k >= JOY_HAT_0_UP && k < JOY_HAT_END_UP)
{
std::ostringstream os;
os << "H" << (k - JOY_HAT_0_UP) << "^";
return os.str();
}
else if(k >= JOY_HAT_0_DOWN && k < JOY_HAT_END_DOWN)
{
std::ostringstream os;
os << "H" << (k - JOY_HAT_0_DOWN) << "v";
return os.str();
}
}
s = inputcode2string(k);
return s.empty() ? stringbank.get(SB_BBGE_NO_KEY) : s;
return s && *s ? s : NULL;
}
static int checkInp(const char *s, int category, int limit, StringBankIndexBBGE errid)
static unsigned getKeyCodeFromSDLName(const char *s)
{
const int k = atoi(s);
if(!k)
return 0;
if(k < limit)
return k + category;
#ifdef BBGE_BUILD_SDL2
return SDL_GetScancodeFromName(s);
#endif
return SDL_GetKeyFromName(s);
}
static std::string getKeyToString(unsigned k)
{
assert(k < KEY_MAXARRAY);
const char *s = getLegacyKeyNameFromInputCode(k);
if(s)
return s;
s = getRawSDLKeyName(k);
if(s)
return s;
return num2str(k);
}
static std::string getJoystickDataToString(const ActionInput::JoyData& jd)
{
std::ostringstream os;
switch(jd.ctrlType)
{
case INP_CTRL_BUTTON:
os << jd.ctrlID;
break;
case INP_CTRL_AXIS:
os << 'A' << ((jd.x < 0 || jd.y < 0) ? '-' : '+') << jd.ctrlID;
break;
case INP_CTRL_HAT:
os << 'H';
for(const JoyHatDir *hd = &s_joyhat[0]; hd->c; ++hd)
if(jd.x == hd->x && jd.y == hd->y)
{
os << hd->c << jd.ctrlID;
break;
}
break;
}
return os.str();
}
static std::string getJoystickDataToPrettyString(const ActionInput::JoyData& jd, int joystickID)
{
if(!jd.ctrlID)
return std::string();
std::ostringstream os;
os << stringbank.get(errid) << k;
errorLog(os.str());
return 0;
static const char *axislabels[] = { "(-)", "", "(+)" };
switch(jd.ctrlType)
{
case INP_CTRL_BUTTON:
{
const char *s = jbtnname(joystickID, jd.ctrlID);
if(s)
os << s;
else
os << jd.ctrlID;
}
break;
case INP_CTRL_AXIS:
{
const char *s = jaxisname(joystickID, jd.ctrlID);
if(s)
os << s;
else
os << "A:" << jd.ctrlID;
os << axislabels[jd.x + 1] << axislabels[jd.y + 1];
}
break;
case INP_CTRL_HAT:
{
os << "H:" << jd.ctrlID << ":";
for(const JoyHatDir *hd = &s_joyhat[0]; hd->c; ++hd)
if(jd.x == hd->x && jd.y == hd->y)
{
os << hd->pretty;
break;
}
}
break;
}
return os.str();
}
int getStringToInputCode(const std::string& s)
static unsigned getMouseButtonFromString_Legacy(const std::string& s)
{
int k = 0;
if(s == "LMB")
k = MOUSE_BUTTON_LEFT;
return MOUSE_BUTTON_LEFT;
else if(s == "RMB")
k = MOUSE_BUTTON_RIGHT;
return 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, SB_BBGE_INVALID_KEY_ID);
else if(!strncmp(s.c_str(), "JB:", 3))
k = checkInp(s.c_str() + 3, JOY_BUTTON_0, JOY_BUTTON_END, SB_BBGE_INVALID_JOY_BTN);
else if(!strncmp(s.c_str(), "MB:", 3))
k = checkInp(s.c_str() + 3, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_EXTRA_END, SB_BBGE_INVALID_MOUSE_BTN);
else if(s.length() > 4 && !strncmp(s.c_str(), "AX:", 3))
{
switch(s[3])
{
case '+':
k = checkInp(s.c_str() + 4, JOY_AXIS_0_POS, JOY_AXIS_END_POS, SB_BBGE_INVALID_JOY_AXIS_POS);
break;
case '-':
k = checkInp(s.c_str() + 4, JOY_AXIS_0_NEG, JOY_AXIS_END_NEG, SB_BBGE_INVALID_JOY_AXIS_NEG);
break;
default:
return 0;
}
}
else if(s.length() > 2 && s[0] == 'H') // joystick hat
{
JoyHatDirection hd;
switch(s[1])
{
case 'L': hd = JOY_HAT_DIR_LEFT; break;
case 'R': hd = JOY_HAT_DIR_RIGHT; break;
case 'U': hd = JOY_HAT_DIR_UP; break;
case 'D': hd = JOY_HAT_DIR_DOWN; break;
default: return 0;
}
unsigned hatID = atoi(s.c_str() + 2);
return joyHatToActionButton(hatID, hd);
}
else
{
// Maybe we're upgrading from an old config?
// This handles KEY_* and some old mouse/joystick names.
k = getInputCodeFromKeyName(s.c_str());
}
return MOUSE_BUTTON_MIDDLE;
// Non-configurable keys
if(k == KEY_ESCAPE)
return getLegacyInputCodeFromKeyName(s.c_str());
}
static unsigned getMouseButtonFromString(const std::string& s)
{
if(s.empty() || s == "0")
return 0;
if(k < ACTION_BUTTON_ENUM_SIZE)
unsigned k = getMouseButtonFromString_Legacy(s);
switch(k)
{
case MOUSE_BUTTON_LEFT: return 1;
case MOUSE_BUTTON_RIGHT: return 2;
case MOUSE_BUTTON_MIDDLE: return 3;
default: ;
}
return atoi(s.c_str());
}
static unsigned getKeyFromString(const std::string& s)
{
if(s.empty() || s == "0")
return 0;
unsigned k = getLegacyInputCodeFromKeyName(s.c_str()); // fallback
if(k)
return k;
k = getKeyCodeFromSDLName(s.c_str());
if(k)
return k;
std::ostringstream os;
os << "ActionButton out of range: [" << s << "] = " << k;
errorLog(os.str());
return 0;
return atoi(s.c_str());
}
ActionInput::ActionInput()
static ActionInput::JoyData getJostickDataFromString(const std::string& s)
{
for (int i = 0; i < INP_COMBINED_SIZE; i++)
data.all[i] = 0;
ActionInput::JoyData jd;
if(s.length() && s != "0")
{
switch(s[0])
{
case 'A': // axis
{
jd.ctrlType = INP_CTRL_AXIS;
int ax = atoi(s.c_str() + 1);
jd.ctrlID = ax < 0 ? -ax : ax;
jd.x = ax < 0 ? -1 : 1;
}
break;
case 'H': // hat
jd.ctrlType = INP_CTRL_HAT;
if(s.length() > 1)
for(const JoyHatDir *hd = &s_joyhat[0]; hd->c; ++hd)
if(hd->c == s[1])
{
jd.x = hd->x;
jd.y = hd->y;
jd.ctrlID = atoi(s.c_str() + 2);
break;
}
break;
default: // button
jd.ctrlType = INP_CTRL_BUTTON;
jd.ctrlID = atoi(s.c_str() + 1);
}
}
return jd;
}
ActionInput::JoyData::JoyData()
{
memset(this, 0, sizeof(*this));
}
ActionInput::ActionInput(const std::string& name_)
: name(name_)
{
for (int i = 0; i < INP_MSESIZE; i++)
mse[i] = 0;
for (int i = 0; i < INP_KEYSIZE; i++)
key[i] = 0;
// joy[] inited by its own ctor
}
std::string ActionInput::toString() const
@ -295,15 +295,15 @@ std::string ActionInput::toString() const
for (int i = 0; i < INP_MSESIZE; i++)
{
os << getInputCodeToString(data.single.mse[i]) << " ";
os << getMouseButtonToString(mse[i]) << " ";
}
for (int i = 0; i < INP_KEYSIZE; i++)
{
os << getInputCodeToString(data.single.key[i]) << " ";
os << getKeyToString(key[i]) << " ";
}
for (int i = 0; i < INP_JOYSIZE; i++)
{
os << getInputCodeToString(data.single.joy[i]) << " ";
os << getJoystickDataToString(joy[i]) << " ";
}
return os.str();
@ -316,17 +316,231 @@ void ActionInput::fromString(const std::string &read)
for (int i = 0; i < INP_MSESIZE; i++)
{
is >> str;
data.single.mse[i] = getStringToInputCode(str);
mse[i] = getMouseButtonFromString(str);
}
for (int i = 0; i < INP_KEYSIZE; i++)
{
is >> str;
data.single.key[i] = getStringToInputCode(str);
key[i] = getKeyFromString(str);
}
for (int i = 0; i < INP_JOYSIZE; i++)
{
is >> str;
data.single.joy[i] = getStringToInputCode(str);
joy[i] = getJostickDataFromString(str);
}
}
struct TypeAndSlot
{
InputDeviceType type;
unsigned slot;
};
static TypeAndSlot getTypeAndSlot(unsigned field)
{
TypeAndSlot ts;
if(field < INP_MSESIZE)
{
ts.type = INP_DEV_MOUSE;
ts.slot = field;
}
else if(field < INP_MSESIZE + INP_KEYSIZE)
{
ts.type = INP_DEV_KEYBOARD;
ts.slot = field - INP_MSESIZE;
}
else if(field < INP_MSESIZE + INP_KEYSIZE + INP_JOYSIZE)
{
ts.type = INP_DEV_JOYSTICK;
ts.slot = field - (INP_MSESIZE + INP_KEYSIZE);
}
else
{
assert(false);
ts.type = InputDeviceType(-1);
ts.slot = unsigned(-1);
}
return ts;
}
unsigned ActionInput::GetField(InputDeviceType dev, unsigned slot)
{
unsigned base = 0;
switch(dev)
{
case INP_DEV_MOUSE:
base = 0;
assert(slot < INP_MSESIZE);
break;
case INP_DEV_KEYBOARD:
base = INP_MSESIZE;
assert(slot < INP_KEYSIZE);
break;
case INP_DEV_JOYSTICK:
base = INP_MSESIZE+INP_KEYSIZE;
assert(slot < INP_JOYSIZE);
break;
default:
assert(false);
}
return base + slot;
}
std::string ActionInput::prettyPrintField(unsigned field, int joystickID /* = -1 */) const
{
TypeAndSlot ts = getTypeAndSlot(field);
switch(ts.type)
{
case INP_DEV_MOUSE:
return getMouseButtonToString(mse[field]);
case INP_DEV_KEYBOARD:
{
unsigned k = key[ts.slot];
const char *s = getPrettySDLKeyName(k);
if(s)
return s;
return getKeyToString(k);
}
case INP_DEV_JOYSTICK:
{
const JoyData& jd = joy[ts.slot];
return getJoystickDataToPrettyString(jd, joystickID);
}
}
assert(false);
return std::string();
}
bool ActionInput::ImportField(const RawInput& inp, unsigned field)
{
TypeAndSlot ts = getTypeAndSlot(field);
return ts.type == inp.src.deviceType && Import(inp, ts.slot);
}
bool ActionInput::Import(const RawInput& inp, unsigned slot)
{
switch(inp.src.deviceType)
{
case INP_DEV_MOUSE:
{
if(slot >= INP_MSESIZE)
return false;
if(inp.src.ctrlID == INP_CTRL_BUTTON)
{
mse[slot] = inp.src.ctrlID + 1;
return true;
}
}
break;
case INP_DEV_KEYBOARD:
{
if(slot >= INP_KEYSIZE)
return false;
if(inp.src.ctrlID == INP_CTRL_BUTTON)
{
key[slot] = inp.src.ctrlID;
return true;
}
}
break;
case INP_DEV_JOYSTICK:
{
if(slot >= INP_JOYSIZE)
return false;
JoyData jd;
InputControlType t = inp.src.ctrlType;
if(t == INP_CTRL_BUTTON || t == INP_CTRL_AXIS || t == INP_CTRL_HAT)
{
jd.ctrlType = t;
jd.ctrlID = inp.src.ctrlID + 1;
jd.x = inp.u.ivec.x;
jd.y = inp.u.ivec.y;
if(t == INP_CTRL_AXIS)
jd.x = inp.u.axis < 0 ? -1 : 1;
return true;
}
}
break;
}
return false;
}
bool ActionInput::Export(RawInput& inp, unsigned field) const
{
TypeAndSlot ts = getTypeAndSlot(field);
inp.src.deviceType = ts.type;
inp.src.ctrlType = INP_CTRL_BUTTON;
inp.u.pressed = 1;
switch(ts.type)
{
case INP_DEV_MOUSE:
{
unsigned m = mse[ts.slot];
if(!m)
return false;
inp.src.ctrlID = m - 1;
return true;
}
case INP_DEV_KEYBOARD:
{
unsigned k = key[ts.slot];
if(!k)
return false;
inp.src.ctrlID = k;
}
case INP_DEV_JOYSTICK:
{
const JoyData& jd = joy[field - (INP_MSESIZE + INP_KEYSIZE)];
if(!jd.ctrlID)
return false;
inp.src.ctrlType = jd.ctrlType;
inp.src.ctrlID = jd.ctrlID - 1;
inp.u.ivec.x = jd.x;
inp.u.ivec.y = jd.y;
if(jd.ctrlType == INP_CTRL_AXIS)
inp.u.axis = jd.x < 0 ? -1 : 1;
return true;
}
}
assert(false);
return false;
}
bool ActionInput::hasEntry(unsigned field) const
{
TypeAndSlot ts = getTypeAndSlot(field);
switch(ts.type)
{
case INP_DEV_MOUSE:
return mse[ts.slot];
case INP_DEV_KEYBOARD:
return key[ts.slot];
case INP_DEV_JOYSTICK:
return joy[ts.slot].ctrlID;
}
return false;
}
void ActionInput::clearEntry(unsigned field)
{
TypeAndSlot ts = getTypeAndSlot(field);
switch(ts.type)
{
case INP_DEV_MOUSE:
mse[ts.slot] = 0;
break;
case INP_DEV_KEYBOARD:
key[ts.slot] = 0;
break;
case INP_DEV_JOYSTICK:
joy[ts.slot].ctrlID = 0;
break;
}
}

View file

@ -22,56 +22,60 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ACTIONINPUT_H
#include <string>
#include "InputSystem.h"
// Slots for each input/key type
enum ActionInputSize
{
INP_MSESIZE = 1,
INP_KEYSIZE = 2,
INP_JOYSIZE = 1,
INP_COMBINED_SIZE = INP_MSESIZE + INP_KEYSIZE + INP_JOYSIZE
INP_NUMFIELDS = INP_MSESIZE + INP_KEYSIZE + INP_JOYSIZE
};
std::string getInputCodeToString(int k);
std::string getInputCodeToUserString(unsigned int k, size_t joystickID);
int getStringToInputCode(const std::string& s);
// Mapping for one input action ("Cook", "SwimLeft", etc)
class ActionInput
{
public:
ActionInput();
std::string name;
union
public: // only public because some static funcs in the cpp file need this. Don't use elsewhere!
struct JoyData
{
struct
{
unsigned int mse[INP_MSESIZE];
unsigned int key[INP_KEYSIZE];
unsigned int joy[INP_JOYSIZE];
} single;
int all[INP_COMBINED_SIZE];
} data;
JoyData();
InputControlType ctrlType;
unsigned ctrlID; // 0 = not set, otherwise actual id + 1
int x, y; // each [-1..+1]: (x,y) for hat direction, (x) for axis direction
};
inline const std::string& getName() const { return name; }
private:
unsigned mse[INP_MSESIZE]; // stores button+1, 0 = not set
unsigned key[INP_KEYSIZE]; // 0 = no key
JoyData joy[INP_JOYSIZE];
std::string name;
public:
ActionInput(const std::string& name_);
// indexing:
// slot -> per-category (start at 0 for each INP_*)
// field: absolute, [0 ..INP_NUMFIELDS)
static unsigned GetField(InputDeviceType dev, unsigned slot);
bool Import(const RawInput& inp, unsigned slot); // autodetects type, slot is per-category
bool ImportField(const RawInput& inp, unsigned field); // returns false if field and type of inp don't match
bool Export(RawInput& inp, unsigned field) const; // returns false if no mapping present
// for checking whether a key/button/etc is configured
bool hasEntry(unsigned field) const;
void clearEntry(unsigned field);
// for config (de-)serialization
std::string toString() const;
void fromString(const std::string &read);
};
enum InputSetType
{
INPUTSET_NONE = 0,
INPUTSET_KEY = 1,
INPUTSET_JOY = 2,
INPUTSET_MOUSE = 3,
INPUTSET_OTHER = 4
};
enum InputDevice
{
INPUT_NODEVICE = 0,
INPUT_MOUSE,
INPUT_JOYSTICK,
INPUT_KEYBOARD
// for the UI (field is in [0..INP_COMBINED_SIZE])
std::string prettyPrintField(unsigned field, int joystickID = -1) const;
};
#endif

View file

@ -18,76 +18,70 @@ See the GNU General Public License for more details.
#include "ActionMapper.h"
#include "Core.h"
typedef std::vector<unsigned> ButtonList;
InputDevice getDeviceForActionbutton(int k)
// TODO: clean this up, make single vector of tagged unions, sorted by key
struct LegacyActionData
{
if(k <= KEY_MAXARRAY)
return INPUT_KEYBOARD;
if(k < MOUSE_BUTTON_EXTRA_END)
return INPUT_MOUSE;
return INPUT_JOYSTICK;
}
LegacyActionData()
: id(-1), state(-1)
, event(0)
{
}
int id; // -1 if no associated event
int state; // -1, 0, or 1
Event *event;
ButtonList buttonList;
};
enum ActionState
{
ACSTATE_ACTIVE = 0x1, // action is active right now (button is held down)
ACSTATE_ACCEPTED = 0x2 // handle that action when it comes in
};
ActionMapper::ActionMapper()
{
cleared = false;
inputEnabled = true;
inUpdate = false;
//memset(keyStatus, 0, sizeof(keyStatus));
InputMapper::RegisterActionMapper(this);
}
ActionMapper::~ActionMapper()
{
InputMapper::UnregisterActionMapper(this);
clearCreatedEvents();
}
ActionData *ActionMapper::getActionDataByIDAndSource(int actionID, int source)
LegacyActionData *ActionMapper::getActionDataByID(int actionID)
{
for (ActionDataSet::iterator i = actionData.begin(); i != actionData.end(); ++i)
{
if (i->id == actionID && i->source == source)
if (i->id == actionID)
return &(*i);
}
return 0;
}
bool ActionMapper::isActing(int actionID, int source)
bool ActionMapper::isActing(unsigned actionID) const
{
if(source < 0)
{
for (ActionDataSet::iterator i = actionData.begin(); i != actionData.end(); ++i)
{
ActionData& ad = *i;
if(ad.id == actionID)
for (ButtonList::iterator ii = ad.buttonList.begin(); ii != ad.buttonList.end(); ++ii)
if (getKeyState(*ii, source))
return true;
}
return false;
}
ActionData *ad = getActionDataByIDAndSource(actionID, source);
if (ad)
{
ButtonList::iterator i = ad->buttonList.begin();
for (; i != ad->buttonList.end(); i++)
{
if (getKeyState(*i, source))
return true;
}
}
return false;
return actionID < _activeActions.size() ? _activeActions[actionID] : false;
}
void ActionMapper::addAction(int actionID, int k, int source)
void ActionMapper::addAction(unsigned actionID, unsigned k)
{
ActionData *ad = getActionDataByIDAndSource(actionID, source);
assert(k);
if(!k)
return;
LegacyActionData *ad = getActionDataByID(actionID);
if (!ad)
{
ActionData data;
LegacyActionData data;
data.id = actionID;
data.source = source;
actionData.push_back(data);
ad = &actionData.back();
}
@ -96,19 +90,16 @@ void ActionMapper::addAction(int actionID, int k, int source)
{
if(std::find(ad->buttonList.begin(), ad->buttonList.end(), k) == ad->buttonList.end())
ad->buttonList.push_back(k);
//keyStatus[k] = core->getKeyState(k);
}
}
void ActionMapper::addAction(Event *event, int k, int state)
void ActionMapper::addAction(Event *event, unsigned k, int state)
{
ActionData data;
LegacyActionData data;
data.event = event;
data.state = state;
data.buttonList.push_back(k);
actionData.push_back(data);
//keyStatus[k] = core->getKeyState(k);
}
Event* ActionMapper::addCreatedEvent(Event *event)
@ -141,89 +132,77 @@ void ActionMapper::disableInput()
inputEnabled = false;
}
/*
bool ActionMapper::pollAction(int actionID, int source)
{
if(source < 0)
{
for (ActionDataSet::iterator i = actionData.begin(); i != actionData.end(); i++)
if(i->id == actionID && _pollActionData(*i))
return true;
return false;
}
ActionData *ad = getActionDataByIDAndSource(actionID, source);
return ad && _pollActionData(*ad);
}
bool ActionMapper::_pollActionData(const ActionData& ad)
{
const ButtonList& blist = ad.buttonList;
for (ButtonList::const_iterator j = blist.begin(); j != blist.end(); j++)
if (getKeyState((*j)))
return true;
return false;
}
*/
void ActionMapper::onUpdate (float dt)
{
if (inUpdate)
return;
inUpdate = true;
cleared = false;
for (ActionDataSet::iterator i = actionData.begin(); i != actionData.end(); ++i)
if(inputEnabled && !inUpdate)
{
for (ButtonList::iterator j = i->buttonList.begin(); j != i->buttonList.end(); j++)
{
const int k = (*j);
const ActionData *ad = &(*i);
const bool keyChanged = isKeyChanged(k, ad->source);
inUpdate = true;
updateDirectInput();
updateActions();
inUpdate = false;
}
if (keyChanged)
_actionChanges.clear();
_inputChanges.clear();
}
void ActionMapper::updateActions()
{
// Trigger queued events and propagate changes
for(size_t i = 0; i < _actionChanges.size(); ++i)
{
const ActionUpdate& am = _actionChanges[i];
if(am.id >= _activeActions.size())
_activeActions.resize(am.id);
_activeActions[am.id] = am.state;
action(am.id, am.state, am.playerID, am.device);
}
}
void ActionMapper::updateDirectInput()
{
cleared = false;
for(size_t q = 0; q < _inputChanges.size(); ++q)
{
int ik = _inputChanges[q];
bool keyState;
unsigned k;
if(ik < 0)
{
keyState = false;
k = -ik;
}
else
{
keyState = true;
k = ik;
}
for (ActionDataSet::iterator i = actionData.begin(); i != actionData.end(); ++i)
{
const LegacyActionData& ad = (*i);
for (ButtonList::const_iterator j = ad.buttonList.begin(); j != ad.buttonList.end(); j++)
{
bool keyState = getKeyState(k, ad->source);
if (inputEnabled)
if(k == (*j))
{
if (ad->event)
if (ad.event)
{
if (ad->state==-1 || keyState == !!ad->state)
if (ad.state==-1 || keyState == !!ad.state)
{
ad->event->act();
ad.event->act();
}
}
else
{
action(ad->id, keyState, ad->source, getDeviceForActionbutton(k));
action(ad.id, keyState, -1, INP_DEV_NODEVICE);
}
if (core->loopDone) goto out;
if (core->loopDone || cleared)
return;
}
if (cleared) { cleared = false; goto out; } // actionData has been cleared, stop iteration
}
}
}
out:
inUpdate = false;
}
bool ActionMapper::getKeyState(int k, int sourceID)
{
if(sourceID < 0)
return getKeyState(k);
return core->getActionStatus(sourceID)->getKeyState(k);
}
bool ActionMapper::getKeyState(int k)
{
// all including sentinel
const int m = core->getMaxActionStatusIndex();
for(int i = -1; i <= m; ++i)
if(core->getActionStatus(i)->getKeyState(k))
return true;
return false;
}
void ActionMapper::clearActions()
@ -232,19 +211,47 @@ void ActionMapper::clearActions()
actionData.clear();
}
bool ActionMapper::isKeyChanged(int k, int sourceID)
void ActionMapper::recvAction(unsigned actionID, bool keyState, int playerID, InputDeviceType device)
{
if(sourceID < 0)
return isKeyChanged(k);
return core->getActionStatus(sourceID)->isKeyChanged(k);
if(!inputEnabled)
return;
// enqueue change for later
// Since the update order isn't actually *defined* anywhere but it'm almost sure there
// will be subtle bugs if things aren't updated in the "right" order
// (aka as it happened to be, so far),
// use a queue so that the code can keep believing it's polling changes, while in fact
// under the hood it's a push-based system.
// Pushing every change to a queue also ensures we can't miss a button press that
// lasts shorter than one frame.
ActionUpdate am;
am.id = actionID;
am.state = keyState;
am.playerID = playerID;
am.device = device;
_actionChanges.push_back(am);
}
bool ActionMapper::isKeyChanged(int k)
void ActionMapper::recvDirectInput(unsigned k, bool keyState)
{
// all including sentinel
const int m = core->getMaxActionStatusIndex();
for(int i = -1; i <= m; ++i)
if(core->getActionStatus(i)->isKeyChanged(k))
return true;
return false;
if(!inputEnabled)
return;
_inputChanges.push_back(keyState ? (int)k : -(int)k);
}
void ActionMapper::ImportInput(const NamedAction *actions, size_t N)
{
// FIXME controllerfixup
InputMapper *im = NULL;
ActionSet as;
/*
for(size_t i = 0; i < dsq->user.control.actionSets.size(); ++i)
{
const ActionSet& as = dsq->user.control.actionSets[i];
*/
for(size_t i = 0; i < N; ++i)
as.importAction(im, actions[i].name, actions[i].actionID);
}

View file

@ -24,43 +24,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Base.h"
#include "ActionInput.h"
InputDevice getDeviceForActionbutton(int k);
class Event;
class ActionMapper;
#include "ActionStatus.h"
#include "ActionSet.h"
#include "Joystick.h"
typedef std::vector<int> ButtonList;
struct ActionData
{
ActionData()
: id(-1), state(-1), source(-1)
, event(0)
{
}
int id, state, source;
Event *event;
ButtonList buttonList;
};
struct LegacyActionData;
class ActionMapper
{
public:
struct NamedAction // for importing
{
const char * const name;
unsigned actionID;
};
// funcs
ActionMapper();
virtual ~ActionMapper();
void addAction(Event *event, int k, int state=-1);
void addAction(int actionID, int k, int source);
// Overridden to react to events (both legacy and input-mapped)
virtual void action(int actionID, int state, int playerID, InputDeviceType device) = 0;
bool isActing(int actionID, int source);
virtual void action(int actionID, int state, int source, InputDevice device) = 0;
// Legacy actions -- binds keys directly to actions.
// This bypasses the input mapper and checks for keys directly!
void addAction(Event *event, unsigned k, int state = -1);
void addAction(unsigned actionID, unsigned k);
bool isActing(unsigned actionID) const;
void clearActions();
@ -69,7 +62,7 @@ public:
// vars
typedef std::vector<ActionData> ActionDataSet;
typedef std::vector<LegacyActionData> ActionDataSet;
ActionDataSet actionData;
bool cleared;
@ -80,22 +73,41 @@ public:
Event *addCreatedEvent(Event *event);
void clearCreatedEvents();
//bool pollAction(int actionID, int source);
bool getKeyState(int k);
bool getKeyState(int k, int sourceID);
ActionData *getActionDataByIDAndSource(int actionID, int source);
// called by InputMapper whenever stuff happens
void recvAction(unsigned actionID, bool state, int playerID, InputDeviceType device);
void recvDirectInput(unsigned k, bool state);
protected:
template<size_t N> static void ImportInput(const NamedAction (&a)[N])
{
ImportInput(&a[0], N);
}
static void ImportInput(const NamedAction *actions, size_t N);
std::vector<Event*>createdEvents;
std::vector<Event*> createdEvents;
bool inUpdate;
bool inputEnabled;
void onUpdate (float dt);
private:
bool isKeyChanged(int k);
bool isKeyChanged(int k, int sourceID);
//bool _pollActionData(const ActionData& ad);
void updateDirectInput();
void updateActions();
LegacyActionData *getActionDataByID(int actionID);
struct ActionUpdate
{
unsigned id;
int playerID;
bool state;
InputDeviceType device;
};
std::vector<ActionUpdate> _actionChanges;
std::vector<int> _inputChanges; // >0: pressed, <0: released
bool inUpdate;
std::vector<unsigned char> _activeActions;
};
#endif

View file

@ -33,7 +33,6 @@ JoystickConfig::JoystickConfig()
ActionSet::ActionSet()
{
inputMode = INPUT_NODEVICE;
enabled = true;
joystickID = ACTIONSET_REASSIGN_JOYSTICK;
}
@ -132,11 +131,11 @@ void ActionSet::updateJoystick()
j->setEnabled(true);
}
ActionInput *ActionSet::getActionInputByName(const std::string &name)
const ActionInput *ActionSet::getActionInputByName(const std::string &name) const
{
for (ActionInputSet::iterator i = inputSet.begin(); i != inputSet.end(); i++)
for (ActionInputSet::const_iterator i = inputSet.begin(); i != inputSet.end(); i++)
{
if (nocasecmp((*i).name, name) == 0)
if (nocasecmp(i->getName(), name) == 0)
{
return &(*i);
}
@ -144,52 +143,34 @@ ActionInput *ActionSet::getActionInputByName(const std::string &name)
return 0;
}
void ActionSet::importAction(ActionMapper *mapper, const std::string &name, int actionID, int sourceID) const
void ActionSet::importAction(InputMapper *mapper, const std::string &name, unsigned actionID) const
{
if (!enabled) return;
if (!mapper) return;
for (size_t i = 0; i < inputSet.size(); i++)
const ActionInput *ac = getActionInputByName(name);
if(!ac)
{
const ActionInput *actionInput = &inputSet[i];
if (actionInput->name == name)
{
for (int i = 0; i < INP_COMBINED_SIZE; i++)
if (actionInput->data.all[i])
mapper->addAction(actionID, actionInput->data.all[i], sourceID);
return;
}
errorLog("ActionSet::importAction: Undefined action name: " + name);
return;
}
RawInput raw;
for(unsigned i = 0; i < INP_NUMFIELDS; ++i)
if(ac->Export(raw, i))
if(!mapper->addMapping(InputMapper::TO_BUTTON, raw, actionID))
errorLog("Failed to map action: " + name);
}
void ActionSet::importAction(ActionMapper *mapper, const std::string &name, Event *event, int state) const
ActionInput& ActionSet::ensureActionInput(const std::string &name)
{
if (!enabled) return;
if (!mapper) return;
for (ActionInputSet::iterator i = inputSet.begin(); i != inputSet.end(); i++)
if (nocasecmp(i->getName(), name) == 0)
return *i;
for (size_t i = 0; i < inputSet.size(); i++)
{
const ActionInput *actionInput = &inputSet[i];
if (actionInput->name == name)
{
for (int i = 0; i < INP_COMBINED_SIZE; i++)
if (actionInput->data.all[i])
mapper->addAction(event, actionInput->data.all[i], state);
return;
}
}
}
ActionInput *ActionSet::addActionInput(const std::string &name)
{
ActionInput *a = getActionInputByName(name);
if(a)
return a;
ActionInput newa;
newa.name = name;
ActionInput newa(name);
inputSet.push_back(newa);
return &inputSet.back();
return inputSet.back();
}
/*

View file

@ -27,9 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "ActionInput.h"
typedef std::vector<ActionInput> ActionInputSet;
class ActionMapper;
class InputMapper;
class Event;
const int ACTIONSET_REASSIGN_JOYSTICK = -2;
@ -41,14 +39,16 @@ struct JoystickConfig
float s1dead, s2dead;
};
// One ActionSet is a serializable configuration of input mappings.
class ActionSet
{
typedef std::vector<ActionInput> ActionInputSet;
public:
ActionSet();
// import this ActionSet into ActionMapper
void importAction(ActionMapper *mapper, const std::string &name, Event *event, int state) const;
void importAction(ActionMapper *mapper, const std::string &name, int actionID, int sourceID) const;
// import this ActionSet into InputMapper. Should be called via ActionMapper::ImportInput() only!
void importAction(InputMapper *mapper, const std::string &name, unsigned actionID) const;
void clearActions();
int assignJoystickByName(bool force); // -1 if no such joystick found
void assignJoystickIdx(int idx, bool updateValues);
@ -56,11 +56,10 @@ public:
// note: this only ENABLES joysticks if they are needed, but never disables any
void updateJoystick();
ActionInput *addActionInput(const std::string &name);
ActionInput *getActionInputByName(const std::string &name);
ActionInput& ensureActionInput(const std::string &name);
const ActionInput *getActionInputByName(const std::string &name) const;
InputDevice inputMode;
size_t joystickID; // >= 0: use that, -1 = no joystick, or ACTIONSET_REASSIGN_JOYSTICK
int joystickID; // >= 0: use that, -1 = no joystick, or ACTIONSET_REASSIGN_JOYSTICK
// --- Saved in config ---
ActionInputSet inputSet;

View file

@ -1,150 +0,0 @@
#include "ActionStatus.h"
#include "Core.h"
#include "ActionSet.h"
ActionButtonStatus::ActionButtonStatus()
: joystickID(-1)
{
memset(status, 0, sizeof(status));
memset(changed, 0, sizeof(changed));
}
void ActionButtonStatus::import(const ActionSet& as)
{
joystickID = as.joystickID;
unsigned char found[ACTION_BUTTON_ENUM_SIZE];
memset(found, 0, sizeof(found));
for(size_t i = 0; i < as.inputSet.size(); ++i)
{
const ActionInput& inp = as.inputSet[i];
for(int j = 0; j < INP_COMBINED_SIZE; ++j)
if(unsigned(inp.data.all[j]) < ACTION_BUTTON_ENUM_SIZE)
found[inp.data.all[j]] = 1;
}
toQuery.clear();
for(int k = 1; k < sizeof(found); ++k) // ignore [0]
if(found[k])
toQuery.push_back(k);
memset(status, 0, sizeof(status));
memset(changed, 0, sizeof(changed));
update();
}
void ActionButtonStatus::importQuery(const int *pKeys, size_t num)
{
unsigned char found[ACTION_BUTTON_ENUM_SIZE];
memset(found, 0, sizeof(found));
for(size_t i = 0; i < num; ++i)
if(unsigned(pKeys[i]) < ACTION_BUTTON_ENUM_SIZE)
found[pKeys[i]] = 1;
toQuery.clear();
for(int k = 1; k < sizeof(found); ++k) // ignore [0]
if(found[k])
toQuery.push_back(k);
memset(status, 0, sizeof(status));
memset(changed, 0, sizeof(changed));
update();
}
void ActionButtonStatus::update()
{
_queryAllStatus();
}
void ActionButtonStatus::_queryAllStatus()
{
// k==0 is always 0
for(size_t i = 0; i < toQuery.size(); ++i)
{
const int k = toQuery[i];
bool state = _queryStatus(k);
changed[k] = !!status[k] != state;
status[k] = state;
}
}
bool ActionButtonStatus::_queryStatus(int k) const
{
if (k > 0 && k < KEY_MAXARRAY)
return core->getKeyState(k);
if (k == MOUSE_BUTTON_LEFT)
return core->mouse.buttons.left == DOWN;
if (k == MOUSE_BUTTON_RIGHT)
return core->mouse.buttons.right == DOWN;
if (k == MOUSE_BUTTON_MIDDLE)
return core->mouse.buttons.middle == DOWN;
if (k >= MOUSE_BUTTON_EXTRA_START && k < MOUSE_BUTTON_EXTRA_END)
return core->mouse.buttons.extra[k - MOUSE_BUTTON_EXTRA_START];
// --- joystick from here ---
Joystick *j = core->getJoystick(joystickID);
if(!j || !j->isEnabled())
return false;
if (k >= JOY_BUTTON_0 && k < JOY_BUTTON_END)
return j->getButton(k - JOY_BUTTON_0);
if (k >= JOY_AXIS_0_POS && k < JOY_AXIS_END_POS)
{
float ax = j->getAxisUncalibrated(k - JOY_AXIS_0_POS);
return ax > JOY_AXIS_THRESHOLD;
}
if (k >= JOY_AXIS_0_NEG && k < JOY_AXIS_END_NEG)
{
float ax = j->getAxisUncalibrated(k - JOY_AXIS_0_NEG);
return ax < -JOY_AXIS_THRESHOLD;
}
if(k >= JOY_HAT_BEGIN && k < JOY_HAT_END)
{
if (k >= JOY_HAT_0_LEFT && k < JOY_HAT_END_LEFT)
return j->getHat(k - JOY_HAT_0_LEFT);
if (k >= JOY_HAT_0_RIGHT && k < JOY_HAT_END_RIGHT)
return j->getHat(k - JOY_HAT_0_RIGHT);
if (k >= JOY_HAT_0_UP && k < JOY_HAT_END_UP)
return j->getHat(k - JOY_HAT_0_UP);
if (k >= JOY_HAT_0_DOWN && k < JOY_HAT_END_DOWN)
return j->getHat(k - JOY_HAT_0_DOWN);
}
return false;
}
ActionButtonType joyHatToActionButton(unsigned hatID, JoyHatDirection dir)
{
unsigned ret = 0;
if(hatID < MAX_JOYSTICK_HATS)
{
if(dir & JOY_HAT_DIR_LEFT)
ret = JOY_HAT_0_LEFT;
else if(dir & JOY_HAT_DIR_RIGHT)
ret = JOY_HAT_0_RIGHT;
else if(dir & JOY_HAT_DIR_UP)
ret = JOY_HAT_0_UP;
else if(dir & JOY_HAT_DIR_DOWN)
ret = JOY_HAT_0_DOWN;
if(ret)
ret += hatID;
}
return (ActionButtonType)ret;
}

View file

@ -1,70 +0,0 @@
#ifndef ACTIONSTATUS_H
#define ACTIONSTATUS_H
#include "GameKeys.h"
#include "Joystick.h"
class ActionSet;
const unsigned mouseExtraButtons = 8;
// *_END is non-inclusive!
enum ActionButtonType
{
MOUSE_BUTTON_LEFT = KEY_MAXARRAY + 1,
MOUSE_BUTTON_RIGHT,
MOUSE_BUTTON_MIDDLE,
MOUSE_BUTTON_EXTRA_START,
MOUSE_BUTTON_EXTRA_END = MOUSE_BUTTON_EXTRA_START + mouseExtraButtons,
JOY_BUTTON_0 = MOUSE_BUTTON_EXTRA_END,
JOY_BUTTON_END = JOY_BUTTON_0 + MAX_JOYSTICK_BTN,
JOY_AXIS_0_POS = JOY_BUTTON_END,
JOY_AXIS_END_POS = JOY_AXIS_0_POS + MAX_JOYSTICK_AXIS,
JOY_AXIS_0_NEG = JOY_AXIS_END_POS,
JOY_AXIS_END_NEG = JOY_AXIS_0_NEG + MAX_JOYSTICK_AXIS,
JOY_HAT_BEGIN = JOY_AXIS_END_NEG,
JOY_HAT_0_LEFT = JOY_HAT_BEGIN,
JOY_HAT_END_LEFT = JOY_HAT_0_LEFT + MAX_JOYSTICK_HATS,
JOY_HAT_0_RIGHT = JOY_HAT_END_LEFT,
JOY_HAT_END_RIGHT = JOY_HAT_0_RIGHT + MAX_JOYSTICK_HATS,
JOY_HAT_0_UP = JOY_HAT_END_RIGHT,
JOY_HAT_END_UP = JOY_HAT_0_UP + MAX_JOYSTICK_HATS,
JOY_HAT_0_DOWN = JOY_HAT_END_UP,
JOY_HAT_END_DOWN = JOY_HAT_0_DOWN + MAX_JOYSTICK_HATS,
JOY_HAT_END = JOY_HAT_END_DOWN,
ACTION_BUTTON_ENUM_SIZE = JOY_HAT_END
};
ActionButtonType joyHatToActionButton(unsigned hatID, JoyHatDirection dir);
class ActionButtonStatus
{
public:
ActionButtonStatus();
void update();
inline bool getKeyState(int k) const { return !!status[k]; }
inline bool isKeyChanged(int k) { return !!changed[k]; }
void import(const ActionSet& as);
void importQuery(const int *pKeys, size_t num);
inline const std::vector<int>& getToQuery() const {return toQuery; }
inline int getJoystickID() const { return joystickID; }
private:
void _queryAllStatus();
bool _queryStatus(int k) const;
int joystickID;
unsigned char status[ACTION_BUTTON_ENUM_SIZE];
unsigned char changed[ACTION_BUTTON_ENUM_SIZE];
std::vector<int> toQuery;
};
#endif

View file

@ -360,8 +360,6 @@ Core::Core(const std::string &filesystem, const std::string& extraDataDir, int n
mouseCircle = 0;
overrideStartLayer = 0;
overrideEndLayer = 0;
frameOutputMode = false;
updateMouse = true;
particlesPaused = false;
joystickAsMouse = false;
currentLayerPass = 0;
@ -384,11 +382,6 @@ Core::Core(const std::string &filesystem, const std::string& extraDataDir, int n
loopDone = false;
core = this;
for (int i = 0; i < KEY_MAXARRAY; i++)
{
keys[i] = 0;
}
globalResolutionScale = globalScale = Vector(1,1,1);
initRenderObjectLayers(numRenderLayers);
@ -476,8 +469,6 @@ std::string Core::getUserDataFolder()
Core::~Core()
{
clearActionButtons();
if (particleManager)
{
delete particleManager;
@ -534,7 +525,7 @@ void Core::init()
{
setupFileAccess();
unsigned sdlflags = SDL_INIT_EVERYTHING;
unsigned sdlflags = SDL_INIT_EVERYTHING & ~SDL_INIT_TIMER;
quitNestedMainFlag = false;
#ifdef BBGE_BUILD_SDL2
@ -587,27 +578,9 @@ Vector Core::getGamePosition(const Vector &v)
return cameraPos + (v * invGlobalScale);
}
bool Core::getMouseButtonState(int m)
bool Core::getKeyState(unsigned k) const
{
int mcode=m;
switch(m)
{
case 0: mcode=1; break;
case 1: mcode=3; break;
case 2: mcode=2; break;
}
Uint8 mousestate = SDL_GetMouseState(0,0);
return mousestate & SDL_BUTTON(mcode);
return false;
}
bool Core::getKeyState(int k)
{
assert(k < KEY_MAXARRAY);
return k > 0 && k < KEY_MAXARRAY ? keys[k] : 0;
return rawInput.isKeyPressed(k);
}
void Core::initJoystickLibrary()
@ -652,12 +625,6 @@ void Core::detectJoysticks()
bool Core::initInputLibrary()
{
core->mouse.position = Vector(getWindowWidth()/2, getWindowHeight()/2);
for (int i = 0; i < KEY_MAXARRAY; i++)
{
keys[i] = 0;
}
return true;
}
@ -1255,6 +1222,10 @@ bool Core::doMouseConstraint()
void Core::onEvent(const SDL_Event& event)
{
const bool focus = window->hasFocus();
if(focus)
InputSystem::handleSDLEvent(&event);
switch (event.type)
{
case SDL_KEYDOWN:
@ -1263,37 +1234,12 @@ void Core::onEvent(const SDL_Event& event)
{
setInputGrab(!grabInput);
}
else if (focus)
{
#ifdef BBGE_BUILD_SDL2
unsigned kidx = event.key.keysym.scancode;
#else
unsigned kidx = event.key.keysym.sym;
#endif
if(kidx < KEY_MAXARRAY)
keys[kidx] = 1;
}
}
break;
case SDL_KEYUP:
{
if (focus)
{
#ifdef BBGE_BUILD_SDL2
unsigned kidx = event.key.keysym.scancode;
#else
unsigned kidx = event.key.keysym.sym;
#endif
if(kidx < KEY_MAXARRAY)
keys[kidx] = 0;
}
}
break;
case SDL_MOUSEMOTION:
{
if (focus && updateMouse)
if (focus)
{
mouse.lastPosition = mouse.position;
@ -1309,19 +1255,6 @@ void Core::onEvent(const SDL_Event& event)
break;
#ifdef BBGE_BUILD_SDL2
case SDL_MOUSEWHEEL:
{
if (focus && updateMouse)
{
if (event.wheel.y > 0)
mouse.scrollWheelChange = 1;
else if (event.wheel.y < 0)
mouse.scrollWheelChange = -1;
}
}
break;
case SDL_JOYDEVICEADDED:
onJoystickAdded(event.jdevice.which);
break;
@ -1329,82 +1262,12 @@ void Core::onEvent(const SDL_Event& event)
case SDL_JOYDEVICEREMOVED:
onJoystickRemoved(event.jdevice.which);
break;
#else
case SDL_MOUSEBUTTONDOWN:
{
if (focus && updateMouse)
{
switch(event.button.button)
{
case 4:
mouse.scrollWheelChange = 1;
break;
case 5:
mouse.scrollWheelChange = -1;
break;
}
}
}
break;
case SDL_MOUSEBUTTONUP:
{
if (focus && updateMouse)
{
switch(event.button.button)
{
case 4:
mouse.scrollWheelChange = 1;
break;
case 5:
mouse.scrollWheelChange = -1;
break;
}
}
}
break;
#endif
}
}
void Core::pollEvents(float dt)
{
bool warpMouse=false;
if (updateMouse)
{
int x, y;
unsigned mousestate = SDL_GetMouseState(&x,&y);
if (mouse.buttonsEnabled)
{
mouse.buttons.left = mousestate & SDL_BUTTON(1)?DOWN:UP;
mouse.buttons.right = mousestate & SDL_BUTTON(3)?DOWN:UP;
mouse.buttons.middle = mousestate & SDL_BUTTON(2)?DOWN:UP;
for(unsigned i = 0; i < mouseExtraButtons; ++i)
mouse.buttons.extra[i] = mousestate & SDL_BUTTON(3+i)?DOWN:UP;
mouse.pure_buttons = mouse.buttons;
mouse.rawButtonMask = mousestate;
if (flipMouseButtons)
{
std::swap(mouse.buttons.left, mouse.buttons.right);
}
}
else
{
mouse.buttons.left = mouse.buttons.right = mouse.buttons.middle = UP;
}
mouse.scrollWheelChange = 0;
mouse.change = Vector(0,0);
}
window->handleInput();
for(size_t i = 0; i < joysticks.size(); ++i)
@ -1412,8 +1275,8 @@ void Core::pollEvents(float dt)
joysticks[i]->update(dt);
// all input done; update button states
updateActionButtons();
//updateActionButtons();
rawInput.update();
}
#define _VLN(x, y, x2, y2) glVertex2f(x, y); glVertex2f(x2, y2);
@ -2442,11 +2305,9 @@ void Core::onJoystickAdded(int deviceID)
if(!joysticks[i])
{
joysticks[i] = j;
goto done;
return;
}
joysticks.push_back(j);
done:
;
}
void Core::onJoystickRemoved(int instanceID)
@ -2467,26 +2328,6 @@ Joystick *Core::getJoystick(size_t idx)
return i < joysticks.size() ? joysticks[i] : NULL;
}
void Core::updateActionButtons()
{
for(size_t i = 0; i < actionStatus.size(); ++i)
actionStatus[i]->update();
}
void Core::clearActionButtons()
{
for(size_t i = 0; i < actionStatus.size(); ++i)
delete actionStatus[i];
actionStatus.clear();
}
Joystick *Core::getJoystickForSourceID(int sourceID)
{
if(unsigned(sourceID+1) < (unsigned)actionStatus.size())
return getJoystick(actionStatus[sourceID+1]->getJoystickID());
return NULL;
}
#include <png.h>
bool Core::pngSave(const char *filename, unsigned width, unsigned height, unsigned char *data)

View file

@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "DarkLayer.h"
#include "GameKeys.h"
#include "InputMapperRaw.h"
class ParticleEffect;
class Joystick;
@ -81,7 +82,6 @@ struct MouseButtons
}
ButtonState left, right, middle;
ButtonState extra[mouseExtraButtons];
};
struct Mouse
@ -96,7 +96,7 @@ struct Mouse
MouseButtons pure_buttons;
unsigned rawButtonMask;
Vector change;
bool buttonsEnabled;
bool buttonsEnabled; //KILL
int scrollWheelChange;
};
@ -273,7 +273,7 @@ public:
void setMouseConstraint(bool on);
void setMouseConstraintCircle(const Vector& pos, float mouseCircle);
virtual void action(int id, int state, int source, InputDevice device){}
virtual void action(int id, int state, int playerID, InputDeviceType device) {}
bool exists(const std::string &file);
@ -372,11 +372,10 @@ public:
void clearRenderObjects();
bool getKeyState(int k);
bool getMouseButtonState(int m);
bool getKeyState(unsigned k) const;
bool isKeyChanged(unsigned k) const;
int currentLayerPass;
int keys[KEY_MAXARRAY];
virtual void debugLog(const std::string &s);
virtual void errorLog(const std::string &s);
void messageBox(const std::string &title, const std::string &msg);
@ -404,12 +403,9 @@ public:
int flipMouseButtons;
FrameBuffer frameBuffer;
void updateRenderObjects(float dt);
bool joystickAsMouse;
bool joystickAsMouse; //KILL?
virtual void prepScreen(bool t){}
bool updateMouse;
bool frameOutputMode;
int overrideStartLayer, overrideEndLayer;
ParticleEffect* createParticleEffect(const std::string &name, const Vector &position, int layer, float rotz=0);
@ -536,20 +532,13 @@ protected:
void setupFileAccess();
std::string _extraDataDir;
std::vector<ActionButtonStatus*> actionStatus; // contains at least 1 element (the sentinel)
virtual void updateActionButtons();
void clearActionButtons();
InputMapperRaw rawInput;
public:
// inclusive!
inline int getMaxActionStatusIndex() const { return int(actionStatus.size()) - 2; }
// pass -1 for is a sentinel that captures all input
inline ActionButtonStatus *getActionStatus(size_t idx) { return actionStatus[idx + 1]; }
Joystick *getJoystick(size_t idx); // warning: may return NULL/contain holes
// not the actual number of joysticks!
size_t getNumJoysticks() const { return joysticks.size(); }
Joystick *getJoystickForSourceID(int sourceID);
private:
std::vector<Joystick*> joysticks;
};

View file

@ -64,7 +64,7 @@ void EventPtr::call()
}
if (actionMapperCallback)
{
actionMapperCallback->action(actionValue, stateToCall, -1, INPUT_NODEVICE);
actionMapperCallback->action(actionValue, stateToCall, -1, INP_DEV_NODEVICE);
}
}

View file

@ -1,12 +1,12 @@
#include "GameKeyNames.h"
#include "ActionStatus.h"
#include "GameKeys.h"
#include <stdio.h>
#include <map>
typedef std::map<std::string, int> InputCodeMap;
InputCodeMap inputCodeMap;
static std::string keyNames[ACTION_BUTTON_ENUM_SIZE];
static InputCodeMap inputCodeMap;
static const char *keyNames[ACTION_BUTTON_ENUM_SIZE];
static void initInputCodeMap()
{
@ -101,38 +101,31 @@ static void initInputCodeMap()
K(KEY_RBRACKET)
K(KEY_TILDE)
K(MOUSE_BUTTON_LEFT)
K(MOUSE_BUTTON_RIGHT)
K(MOUSE_BUTTON_MIDDLE)
#undef K
for (int jb = JOY_BUTTON_0; jb < JOY_BUTTON_END; jb++)
{
char buf[32];
sprintf(buf, "JOY_BUTTON_%d", jb - JOY_BUTTON_0);
inputCodeMap[buf] = jb;
}
// ----------------------
for(size_t i = 0; i < ACTION_BUTTON_ENUM_SIZE; ++i)
keyNames[i] = NULL;
// Can just use pointers to the strings in the map; they'll stay where they are in memory
for(InputCodeMap::iterator it = inputCodeMap.begin(); it != inputCodeMap.end(); ++it)
keyNames[it->second] = it->first;
keyNames[it->second] = it->first.c_str();
}
int getInputCodeFromKeyName(const char *name)
unsigned getLegacyInputCodeFromKeyName(const std::string& name)
{
if(inputCodeMap.empty())
initInputCodeMap();
return inputCodeMap[name];
}
const std::string& getKeyNameFromInputCode(int k)
const char *getLegacyKeyNameFromInputCode(unsigned k)
{
if(inputCodeMap.empty())
initInputCodeMap();
return keyNames[k];
}
struct KeyNameInitializer
{
KeyNameInitializer() { initInputCodeMap(); }
};
static KeyNameInitializer s_kinit;

View file

@ -3,7 +3,7 @@
#include <string>
int getInputCodeFromKeyName(const char *name);
const std::string& getKeyNameFromInputCode(int k);
unsigned getLegacyInputCodeFromKeyName(const std::string& name);
const char *getLegacyKeyNameFromInputCode(unsigned k);
#endif

View file

@ -241,4 +241,17 @@
#endif // BBGE_BUILD_SDL2
// Extra symbolic names that the engine may use when referencing keys
// For use with ActionMapper::addAction()
// (also see GameKeyNames.cpp)
enum ActionButtonType
{
MOUSE_BUTTON_LEFT = KEY_MAXARRAY + 1,
MOUSE_BUTTON_RIGHT,
MOUSE_BUTTON_MIDDLE,
ACTION_BUTTON_ENUM_SIZE
};
#endif // BBGE_GAME_KEYS_H

267
BBGE/InputMapper.cpp Normal file
View file

@ -0,0 +1,267 @@
#include "InputMapper.h"
#include "InputSystem.h"
#include "ActionMapper.h"
#include <assert.h>
#include <math.h>
#include <algorithm>
std::vector<ActionMapper*> IInputMapper::s_actionmappers;
GameControlState::GameControlState(size_t numbuttons, size_t numaxes)
: buttons(numbuttons), axes(numaxes)
, mouseX(0), mouseY(0), wheelDelta(0)
, lastDevice(INP_DEV_NODEVICE)
{
}
void GameControlState::clear()
{
std::fill(axes.begin(), axes.end(), 0.0f);
std::fill(buttons.begin(), buttons.end(), 0);
}
// -----------------
void IInputMapper::RegisterActionMapper(ActionMapper *mapper)
{
s_actionmappers.push_back(mapper);
}
void IInputMapper::UnregisterActionMapper(ActionMapper *mapper)
{
s_actionmappers.erase(std::remove(s_actionmappers.begin(), s_actionmappers.end(), mapper), s_actionmappers.end());
}
void IInputMapper::ForwardAction(unsigned idx, bool state, int playerID, InputDeviceType dev)
{
const size_t N = s_actionmappers.size();
for(size_t i = 0; i < N; ++i)
s_actionmappers[i]->recvAction(idx, state, playerID, dev);
}
void IInputMapper::ForwardDirectInput(unsigned k, bool state)
{
const size_t N = s_actionmappers.size();
for(size_t i = 0; i < N; ++i)
s_actionmappers[i]->recvDirectInput(k, state);
}
// ------------------
IInputMapper::IInputMapper()
{
InputSystem::addMapper(this);
}
IInputMapper::~IInputMapper()
{
InputSystem::addMapper(this);
}
// ------------------
InputMapper::InputMapper(int playerID)
: acceptMouse(true), acceptMouseID(-1), playerID(playerID)
{
}
InputMapper::~InputMapper()
{
InputSystem::removeMapper(this);
}
static float rescale(float t, float lower, float upper, float rangeMin, float rangeMax)
{
if(upper == lower)
return rangeMin;
return (((t - lower) / (upper - lower)) * (rangeMax - rangeMin)) + rangeMin;
}
static float clamp(float x, float a, float b)
{
return std::max(a, std::min(x, b));
}
static float rescaleClamp(float t, float lower, float upper, float rangeMin, float rangeMax)
{
return clamp(rescale(t, lower, upper, rangeMin, rangeMax), std::min(rangeMin, rangeMax), std::max(rangeMin, rangeMax));
}
unsigned char InputMapper::MapToButton(const Mapping& m)
{
assert(m.buttonOrAxis > 0);
switch(m.raw.src.ctrlType)
{
case INP_CTRL_BUTTON:
return m.raw.u.pressed;
case INP_CTRL_AXIS: // when axis is beyond threshold, register as button press
return m.val.axis > 0
? m.raw.u.axis > m.val.axis
: m.raw.u.axis < m.val.axis;
case INP_CTRL_HAT:
return !memcmp(&m.raw.u.ivec, &m.val.ivec, sizeof(m.raw.u.ivec));
default:
;
}
return 0;
}
float InputMapper::MapToAxis(const Mapping& m)
{
assert(m.buttonOrAxis < 0);
switch(m.raw.src.ctrlType)
{
case INP_CTRL_BUTTON:
return m.raw.u.pressed ? m.val.axis : 0.0f;
case INP_CTRL_WHEEL:
return m.raw.u.axis * m.val.axis;
case INP_CTRL_AXIS:
return m.raw.u.axis < 0
? rescaleClamp(m.raw.u.axis, m.val.axis, 1.0f, 0.0f, 1.0f)
: rescaleClamp(m.raw.u.axis, -m.val.axis, -1.0f, 0.0f, -1.0f);
case INP_CTRL_HAT: // hat to axis; one hat direction should be 0
return m.val.axis * m.raw.u.ivec.x + m.val.axis * m.raw.u.ivec.y;
default:
;
}
return 0.0f;
}
void InputMapper::accumulate(GameControlState *ctrl)
{
ctrl->wheelDelta = wheelDelta;
ctrl->mouseX = mouseX;
ctrl->mouseY = mouseY;
// walk over all inputs, check the values, apply to state
const size_t N = mappings.size();
for(size_t i = 0; i < N; ++i)
{
const Mapping& m = mappings[i];
if(m.buttonOrAxis > 0)
ctrl->buttons[m.buttonOrAxis - 1] += MapToButton(m);
if(m.buttonOrAxis < 0)
ctrl->axes[-m.buttonOrAxis - 1] += MapToAxis(m);
ctrl->lastDevice = m.raw.src.deviceType;
}
wheelDelta = 0;
}
// TODO controllerfixup: need "follow-up" mapping
// means "axis A -> mapped axis 0 ==> if mapped axis 0 > thresh -> trigger action
// same for buttons: ACTION_SWIMLEFT -> ACTION_MENULEFT
void InputMapper::input(const RawInput *inp)
{
size_t N = mappings.size();
if(inp->src.deviceType == INP_DEV_MOUSE && acceptMouse && (acceptMouseID < 0 || inp->src.deviceID == acceptMouseID))
{
switch(inp->src.ctrlType)
{
case INP_CTRL_POSITION:
mouseX = inp->u.ivec.x;
mouseY = inp->u.ivec.y;
break;
case INP_CTRL_WHEEL:
wheelDelta += inp->u.axis; // accumulate deltas until fetched
break;
}
}
for(size_t i = 0; i < N; ++i)
{
Mapping& m = mappings[i];
if(!memcmp(&m.raw.src, &inp->src, sizeof(m.raw.src)))
{
memcpy(&m.raw.u, &inp->u, sizeof(m.raw.u)); // store raw inputs if source matches
if(m.buttonOrAxis > 0) // Mapped to an action?
{
unsigned char state = MapToButton(m); // Does this count as a button press?
if(m.buttonState != state) // Did it actually change? (filter Axis movements that don't actually "release" the button)
ForwardAction(m.buttonOrAxis - 1, state, playerID, inp->src.deviceType);
}
}
}
}
// don't trigger if we just released a button or wiggled an analog stick by 1/10th millimeter.
bool InputMapper::CleanupForMapping(InputControlType c, InputMapper::MapType mt, InputValue& val)
{
switch(c)
{
case INP_CTRL_BUTTON:
if(!val.pressed)
return false;
val.pressed = 1;
return true;
case INP_CTRL_AXIS:
//if(fabsf(val.axis) < 0.6f)
// return false;
if(mt == TO_AXIS && val.axis < 0)
val.axis = -val.axis;
return true;
case INP_CTRL_HAT:
if(!!val.ivec.x + !!val.ivec.y != 1) // exactly one hat axis, not centered, not diagonal
return false;
if(mt == TO_AXIS)
{
// make sure the axis goes in the right direction
if(val.ivec.x < 0)
val.ivec.x = -val.ivec.x;
if(val.ivec.y < 0)
val.ivec.y = -val.ivec.y;
}
return true;
case INP_CTRL_POSITION:
return false;
case INP_CTRL_WHEEL:
if(!val.axis)
return false;
if(mt == TO_AXIS && val.axis < 0)
val.axis = -val.axis;
}
return false;
}
bool InputMapper::addMapping(MapType mt, const RawInput& inp, unsigned targetID)
{
Mapping m;
m.buttonOrAxis = 1 + (mt == TO_BUTTON ? int(targetID) : -int(targetID));
m.raw = inp;
m.val = inp.u;
if(!CleanupForMapping(inp.src.ctrlType, mt, m.val))
return false;
mappings.push_back(m);
return true;
}
void InputMapper::clearMapping()
{
mappings.clear();
}

89
BBGE/InputMapper.h Normal file
View file

@ -0,0 +1,89 @@
#ifndef BBGE_INPUTMAPPER_H
#define BBGE_INPUTMAPPER_H
#include "InputSystem.h"
#include <vector>
class ActionMapper;
// This is what the engine sees to handle the current state.
// Changes are not tracked here!
struct GameControlState
{
GameControlState(size_t numbuttons, size_t numaxes);
int mouseX, mouseY;
float wheelDelta;
InputDeviceType lastDevice;
std::vector<unsigned char> buttons; // actually bool
std::vector<float> axes; // uncalibrated floats, -1 .. +1
void clear(); // Call before InputMapper::accumulate()
};
class IInputMapper
{
public:
IInputMapper();
virtual void input(const RawInput *inp) = 0;
// Called by ActionMapper ctor/dtor to register itself
static void RegisterActionMapper(ActionMapper *mapper);
static void UnregisterActionMapper(ActionMapper *mapper);
// Forward actions to all registered input mappers
static void ForwardAction(unsigned idx, bool state, int playerID, InputDeviceType dev);
static void ForwardDirectInput(unsigned k, bool state);
protected:
virtual ~IInputMapper();
private:
// shared between all InputMapper instances
static std::vector<ActionMapper*> s_actionmappers;
};
// Maps raw device input to player input.
// One mapper per player.
class InputMapper : public IInputMapper
{
public:
InputMapper(int playerID);
~InputMapper();
bool acceptMouse;
int acceptMouseID; // -1: accept all, otherwise: that id
// raw data go in
virtual void input(const RawInput *inp);
// output: apply changes to ctrl
void accumulate(GameControlState *ctrl);
enum MapType
{
TO_BUTTON,
TO_AXIS
};
bool addMapping(MapType mt, const RawInput& inp, unsigned targetID);
void clearMapping();
private:
struct Mapping
{
RawInput raw; // last input that came in, also contains src to check for
int buttonOrAxis;
InputValue val; // used as min. axis value to trigger, deadzone, hat direction, etc
unsigned char buttonState; // for buttons: consider this pressed?
};
const int playerID;
const GameControlState *target;
float wheelDelta;
int mouseX, mouseY;
std::vector<Mapping> mappings;
static unsigned char MapToButton(const InputMapper::Mapping& m);
static float MapToAxis(const InputMapper::Mapping& m);
static bool CleanupForMapping(InputControlType c, InputMapper::MapType mt, InputValue& val); // modifies val, returns whether acceptable
};
#endif

60
BBGE/InputMapperRaw.cpp Normal file
View file

@ -0,0 +1,60 @@
#include "InputMapperRaw.h"
#include <assert.h>
InputMapperRaw::InputMapperRaw()
{
memset(&keyState[0], 0, sizeof(keyState));
}
InputMapperRaw::~InputMapperRaw()
{
}
void InputMapperRaw::input(const RawInput *inp)
{
if(inp->src.ctrlType != INP_CTRL_BUTTON)
return;
unsigned idx = inp->src.ctrlID;
switch(inp->src.deviceType)
{
case INP_DEV_MOUSE:
if(idx > 2)
return; // only want left, middle, right button
idx += MOUSE_BUTTON_LEFT;
// fall through
case INP_DEV_KEYBOARD:
break; // all good
default: // not interested in joystick etc buttons, those are only used via InputMapper
return;
}
// record change as soon as a change event comes in,
// so we don't lose button presses that are shorter than 1 frame.
unsigned char ch = !!inp->u.pressed;
keyChanged[idx] |= (keyState[idx] != ch) << 1; // bit 1 becomes bit 0 in next frame
keyState[idx] |= ch;
}
void InputMapperRaw::update()
{
// make sure that the change bit lives for at least 1 frame
for(size_t i = 0; i < sizeof(keyChanged); ++i)
keyChanged[i] >>= 1;
}
bool InputMapperRaw::isKeyPressed(unsigned k) const
{
assert(k < sizeof(keyState));
return k < sizeof(keyState) ? !!keyState[k] : false;
}
bool InputMapperRaw::isKeyChanged(unsigned k) const
{
assert(k < sizeof(keyChanged));
return k < sizeof(keyChanged) ? !!keyChanged[k] : false;
}

27
BBGE/InputMapperRaw.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef BBGE_INPUTMAPPERRAW_H
#define BBGE_INPUTMAPPERRAW_H
#include "InputMapper.h"
#include "GameKeys.h"
// Legacy mapper: Raw keys to game actions. Required by e.g. editor.
// Used by legacy parts of ActionMapper.
class InputMapperRaw : public IInputMapper
{
public:
InputMapperRaw();
virtual ~InputMapperRaw();
virtual void input(const RawInput *inp);
void update();
bool isKeyPressed(unsigned k) const;
bool isKeyChanged(unsigned k) const;
private:
// actually bools
unsigned char keyState[ACTION_BUTTON_ENUM_SIZE];
unsigned char keyChanged[ACTION_BUTTON_ENUM_SIZE];
};
#endif

28
BBGE/InputSystem.cpp Normal file
View file

@ -0,0 +1,28 @@
#include "InputSystem.h"
#include "InputMapper.h"
#include <vector>
#include <algorithm>
namespace InputSystem {
static std::vector<IInputMapper*> s_mappers;
void handleRawInput(const RawInput *inp)
{
size_t N = s_mappers.size();
for(size_t i = 0; i < N; ++i)
s_mappers[i]->input(inp);
}
void addMapper(IInputMapper *mapper)
{
removeMapper(mapper);
s_mappers.push_back(mapper);
}
void removeMapper(IInputMapper *mapper)
{
s_mappers.erase(std::remove(s_mappers.begin(), s_mappers.end(), mapper), s_mappers.end());
}
} // end namespace InputSystem

55
BBGE/InputSystem.h Normal file
View file

@ -0,0 +1,55 @@
#ifndef BBGE_INPUTSYSTEM_H
#define BBGE_INPUTSYSTEM_H
enum InputDeviceType
{
INP_DEV_NODEVICE,
INP_DEV_KEYBOARD,
INP_DEV_MOUSE,
INP_DEV_JOYSTICK,
};
enum InputControlType
{
INP_CTRL_BUTTON, // keyboard key or joystick button
INP_CTRL_AXIS, // joystick axis
INP_CTRL_HAT, // "digital axis"
INP_CTRL_WHEEL, // no absolute position, only knows relative changes
INP_CTRL_POSITION, // only absolute position
};
struct InputSource
{
InputDeviceType deviceType;
unsigned deviceID;
InputControlType ctrlType;
unsigned ctrlID;
};
union InputValue
{
float axis; // abs. axis value or wheel delta
unsigned pressed; // used as bool
// TODO constrollerfixup: add uchar .hat, SDL uses a bitmask!
struct { int x, y; } ivec; // -1, 0, +1 as hat values, window coords, etc
};
struct RawInput
{
InputSource src;
InputValue u;
};
union SDL_Event;
class IInputMapper;
namespace InputSystem
{
void handleSDLEvent(const SDL_Event *ev);
void handleRawInput(const RawInput *inp);
void addMapper(IInputMapper *mapper);
void removeMapper(IInputMapper *mapper);
};
#endif

156
BBGE/InputSystemSDL.cpp Normal file
View file

@ -0,0 +1,156 @@
#include "InputSystem.h"
#include <SDL.h>
#if SDL_VERSION_ATLEAST(2,0,0)
#define USESDL2
#endif
void InputSystem::handleSDLEvent(const SDL_Event *ev)
{
RawInput raw;
switch(ev->type)
{
case SDL_MOUSEMOTION:
{
raw.src.deviceType = INP_DEV_MOUSE;
raw.src.deviceID = ev->motion.which;
raw.src.ctrlType = INP_CTRL_POSITION;
raw.src.ctrlID = ev->motion.which;
raw.u.ivec.x = ev->motion.x;
raw.u.ivec.y = ev->motion.y;
}
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
raw.src.deviceType = INP_DEV_MOUSE;
raw.src.deviceID = ev->button.which;
#ifndef USESDL2
// SDL1 uses buttons 4 and 5 as wheel
unsigned b = ev->button.button;
if(b == 4 || b == 5)
{
raw.src.ctrlType = INP_CTRL_WHEEL;
raw.src.ctrlID = 0;
int dir = b == 4 ? 1 : -1;
raw.u.axis = dir;
break;
}
#endif
raw.src.ctrlType = INP_CTRL_BUTTON;
raw.src.ctrlID = ev->button.which;
raw.u.pressed = ev->button.state;
}
break;
#ifdef USESDL2
case SDL_MOUSEWHEEL:
{
raw.src.deviceType = INP_DEV_MOUSE;
raw.src.deviceID = ev->wheel.which;
raw.src.ctrlType = INP_CTRL_WHEEL;
raw.src.ctrlID = ev->wheel.which;
raw.u.axis = ev->button.state;
}
break;
#endif
case SDL_KEYDOWN:
case SDL_KEYUP:
{
#ifdef USESDL2
unsigned kidx = ev->key.keysym.scancode;
#else
unsigned kidx= event.key.keysym.sym;
#endif
raw.src.deviceType = INP_DEV_KEYBOARD;
raw.src.deviceID = 0; // SDL doesn't seem to support multiple keyboards
raw.src.ctrlType = INP_CTRL_BUTTON;
raw.src.ctrlID = kidx;
raw.u.pressed = ev->key.state;
}
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
{
raw.src.deviceType = INP_DEV_KEYBOARD;
raw.src.deviceID = ev->jbutton.which;
raw.src.ctrlType = INP_CTRL_BUTTON;
raw.src.ctrlID = ev->jbutton.button;
raw.u.pressed = ev->jbutton.state;
}
case SDL_JOYAXISMOTION:
{
raw.src.deviceType = INP_DEV_JOYSTICK;
raw.src.deviceID = ev->jaxis.which;
raw.src.ctrlType = INP_CTRL_AXIS;
raw.src.ctrlID = ev->jaxis.axis;
raw.u.axis = ev->jaxis.value / 32768.0f;
}
break;
case SDL_JOYHATMOTION:
{
raw.src.deviceType = INP_DEV_JOYSTICK;
raw.src.deviceID = ev->jhat.which;
raw.src.ctrlType = INP_CTRL_HAT;
raw.src.ctrlID = ev->jhat.hat;
int x, y;
switch(ev->jhat.value)
{
case SDL_HAT_CENTERED: x = 0; y = 0; break;
case SDL_HAT_UP: x = 0; y = -1; break;
case SDL_HAT_DOWN: x = 0; y = +1; break;
case SDL_HAT_LEFT: x = -1; y = 0; break;
case SDL_HAT_RIGHT: x = +1; y = 0; break;
case SDL_HAT_LEFTUP: x = -1; y = -1; break;
case SDL_HAT_LEFTDOWN: x = -1; y = +1; break;
case SDL_HAT_RIGHTUP: x = +1; y = -1; break;
case SDL_HAT_RIGHTDOWN: x = +1; y = +1; break;
}
raw.u.ivec.x = (signed short)x;
raw.u.ivec.y = (signed short)y;
}
break;
case SDL_CONTROLLERAXISMOTION:
{
raw.src.deviceType = INP_DEV_JOYSTICK;
raw.src.deviceID = ev->caxis.which;
raw.src.ctrlType = INP_CTRL_AXIS;
raw.src.ctrlID = ev->caxis.axis;
raw.u.axis = ev->caxis.value / float(0x7fff);
}
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
{
raw.src.deviceType = INP_DEV_JOYSTICK;
raw.src.deviceID = ev->cbutton.which;
raw.src.ctrlType = INP_CTRL_BUTTON;
raw.src.ctrlID = ev->cbutton.button;
raw.u.pressed = ev->cbutton.state;
}
break;
/*case SDL_WINDOWEVENT:
switch(ev->window.event)
{
case SDL_WINDOWEVENT_RESIZED:
s_winSizeXInv = 1.0f / (float)ev->window.data1;
s_winSizeYInv = 1.0f / (float)ev->window.data2;
break;
}*/
// fall through
default:
return;
}
handleRawInput(&raw);
}

View file

@ -39,21 +39,7 @@ Joystick::Joystick()
debugLog("Failed to init haptic subsystem");
# endif
sdl_joy = NULL;
buttonBitmask = 0;
deadZone1 = 0.3f;
deadZone2 = 0.3f;
clearRumbleTime= 0;
numJoyAxes = 0;
numHats = 0;
numButtons = 0;
clearAxes();
s1ax = 0;
s1ay = 1;
s2ax = 4;
s2ay = 3;
enabled = false;
}
@ -80,7 +66,6 @@ const char *Joystick::getGUID() const
bool Joystick::init(int stick)
{
stickIndex = stick;
numJoyAxes = 0;
#ifdef BBGE_BUILD_SDL2
if (SDL_IsGameController(stick))
@ -119,10 +104,7 @@ bool Joystick::init(int stick)
guid = &guidbuf[0];
debugLog(std::string("Initialized Joystick [") + name + "], GUID [" + guid + "]");
if (sdl_controller)
{
debugLog("Joystick is a Game Controller");
numJoyAxes = SDL_CONTROLLER_AXIS_MAX;
}
if (sdl_haptic)
debugLog("Joystick has force feedback support");
instanceID = SDL_JoystickInstanceID(sdl_joy);
@ -133,14 +115,11 @@ bool Joystick::init(int stick)
instanceID = SDL_JoystickIndex(sdl_joy);
#endif
if(!numJoyAxes)
numJoyAxes = SDL_JoystickNumAxes(sdl_joy);
if(numJoyAxes > MAX_JOYSTICK_AXIS)
numJoyAxes = MAX_JOYSTICK_AXIS;
numHats = SDL_JoystickNumHats(sdl_joy);
numButtons = SDL_JoystickNumButtons(sdl_joy);
std::ostringstream os;
os << "Joystick has " << SDL_JoystickNumAxes(sdl_joy) << " axes, "
<< SDL_JoystickNumButtons(sdl_joy) << " buttons, "
<< SDL_JoystickNumHats(sdl_joy) << " hats.";
debugLog(os.str());
return true;
}
@ -171,14 +150,6 @@ void Joystick::shutdown()
SDL_JoystickClose(sdl_joy);
sdl_joy = 0;
}
numJoyAxes = 0;
clearAxes();
}
void Joystick::clearAxes()
{
memset(axisRaw, 0, sizeof(axisRaw));
}
void Joystick::rumble(float leftMotor, float rightMotor, float time)
@ -204,7 +175,7 @@ void Joystick::rumble(float leftMotor, float rightMotor, float time)
}
}
void Joystick::calibrate(Vector &calvec, float deadZone)
void Joystick::Calibrate(Vector &calvec, float deadZone)
{
if (calvec.isLength2DIn(deadZone))
{
@ -244,20 +215,6 @@ void Joystick::update(float dt)
shutdown();
return;
}
if (sdl_controller)
{
for(unsigned i = 0; i < numJoyAxes; ++i)
{
Sint16 ax = SDL_GameControllerGetAxis(sdl_controller, (SDL_GameControllerAxis)i);
axisRaw[i] = float(ax)/32768.0f;
}
position.x = axisRaw[SDL_CONTROLLER_AXIS_LEFTX];
position.y = axisRaw[SDL_CONTROLLER_AXIS_LEFTY];
rightStick.x = axisRaw[SDL_CONTROLLER_AXIS_RIGHTX];
rightStick.y = axisRaw[SDL_CONTROLLER_AXIS_RIGHTY];
}
else
#else
if (!SDL_JoystickOpened(stickIndex))
{
@ -266,38 +223,6 @@ void Joystick::update(float dt)
return;
}
#endif
// Note: this connects with the else above when the SDL2 path is compiled!
{
for(unsigned i = 0; i < numJoyAxes; ++i)
{
Sint16 ax = SDL_JoystickGetAxis(sdl_joy, i);
axisRaw[i] = float(ax)/32768.0f;
}
position.x = s1ax >= 0 ? axisRaw[s1ax] : 0.0f;
position.y = s1ay >= 0 ? axisRaw[s1ay] : 0.0f;
rightStick.x = s2ax >= 0 ? axisRaw[s2ax] : 0.0f;
rightStick.y = s2ay >= 0 ? axisRaw[s2ay] : 0.0f;
}
calibrate(position, deadZone1);
calibrate(rightStick, deadZone2);
buttonBitmask = 0;
#ifdef BBGE_BUILD_SDL2
if (sdl_controller)
{
for (unsigned i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++)
buttonBitmask |= !!SDL_GameControllerGetButton(sdl_controller, (SDL_GameControllerButton)i) << i;
}
else
#endif
{
for (unsigned i = 0; i < numButtons; i++)
buttonBitmask |= !!SDL_JoystickGetButton(sdl_joy, i) << i;
//for (unsigned i = 0; i < numHats; i++)
}
}
if (clearRumbleTime >= 0)
@ -310,60 +235,8 @@ void Joystick::update(float dt)
}
}
bool Joystick::anyButton() const
{
return !!buttonBitmask;;
}
unsigned Joystick::getNumAxes() const
{
#ifdef BBGE_BUILD_SDL2
return sdl_controller ? SDL_CONTROLLER_AXIS_MAX : numJoyAxes;
#else
return numJoyAxes;
#endif
}
unsigned Joystick::getNumButtons() const
{
return numButtons;
}
unsigned Joystick::getNumHats() const
{
return numHats;
}
float Joystick::getAxisUncalibrated(unsigned id) const
{
return id < MAX_JOYSTICK_AXIS ? axisRaw[id] : 0.0f;
}
JoyHatDirection Joystick::getHat(unsigned id) const
{
unsigned dir = SDL_JoystickGetHat(sdl_joy, id);
unsigned ret = JOY_HAT_DIR_CENTERED;
switch(dir)
{
case SDL_HAT_UP: ret = JOY_HAT_DIR_UP; break;
case SDL_HAT_DOWN: ret = JOY_HAT_DIR_DOWN; break;
case SDL_HAT_LEFT: ret = JOY_HAT_DIR_LEFT; break;
case SDL_HAT_RIGHT: ret = JOY_HAT_DIR_RIGHT; break;
case SDL_HAT_LEFTUP: ret = JOY_HAT_DIR_UP | JOY_HAT_DIR_LEFT; break;
case SDL_HAT_RIGHTUP: ret = JOY_HAT_DIR_UP | JOY_HAT_DIR_RIGHT; break;
case SDL_HAT_LEFTDOWN: ret = JOY_HAT_DIR_DOWN | JOY_HAT_DIR_LEFT; break;
case SDL_HAT_RIGHTDOWN: ret = JOY_HAT_DIR_DOWN | JOY_HAT_DIR_RIGHT; break;
default: ;
}
return (JoyHatDirection)ret;
}
const char *Joystick::getAxisName(unsigned axis) const
{
if(axis >= numJoyAxes)
return NULL;
#ifdef BBGE_BUILD_SDL2
if(sdl_controller)
return SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)axis);

View file

@ -11,20 +11,6 @@
#include "Vector.h"
#define MAX_JOYSTICK_BTN 32
#define MAX_JOYSTICK_AXIS 32
#define MAX_JOYSTICK_HATS 8
enum JoyHatDirection // bitmask
{
JOY_HAT_DIR_CENTERED = 0,
JOY_HAT_DIR_UP = 1,
JOY_HAT_DIR_DOWN = 2,
JOY_HAT_DIR_LEFT = 4,
JOY_HAT_DIR_RIGHT = 8
};
const static float JOY_AXIS_THRESHOLD = 0.6f;
class Joystick
@ -40,19 +26,8 @@ public:
//Ranges from 0 to 1 (full speed).
void rumble(float leftMotor, float rightMotor, float time);
void update(float dt);
Vector position;
float deadZone1, deadZone2;
float clearRumbleTime;
void calibrate(Vector &vec, float dead);
bool anyButton() const;
bool getButton(size_t id) const { return !!(buttonBitmask & (1u << id)); }
float getAxisUncalibrated(unsigned id) const;
JoyHatDirection getHat(unsigned id) const;
unsigned getNumAxes() const;
unsigned getNumButtons() const;
unsigned getNumHats() const;
static void Calibrate(Vector &vec, float dead);
int getIndex() const { return stickIndex; }
int getInstanceID() const { return instanceID; }
inline bool isEnabled() const { return enabled; }
@ -63,19 +38,12 @@ public:
const char *getName() const;
const char *getGUID() const;
Vector rightStick;
int s1ax, s1ay, s2ax, s2ay;
private:
void clearAxes();
float clearRumbleTime;
bool enabled;
int stickIndex;
int instanceID;
unsigned buttonBitmask;
unsigned numJoyAxes, numHats, numButtons;
SDL_Joystick *sdl_joy;
float axisRaw[MAX_JOYSTICK_AXIS];
std::string name;
std::string guid;

View file

@ -65,7 +65,7 @@ public:
void removeRenderObject(RenderObject *renderObject);
std::string name;
virtual void action(int actionID, int state, int source, InputDevice device) {}
virtual void action(int actionID, int state, int playerID, InputDeviceType device) {}
protected:
void registerState(StateObject *sb, const std::string &name);

View file

@ -4,17 +4,6 @@
#include <string>
#include <map>
// Some strings used in BBGE
enum StringBankIndexBBGE
{
SB_BBGE_NO_KEY = 2153,
SB_BBGE_INVALID_KEY_ID = 2154,
SB_BBGE_INVALID_JOY_BTN = 2155,
SB_BBGE_INVALID_MOUSE_BTN = 2156,
SB_BBGE_INVALID_JOY_AXIS_POS = 2157,
SB_BBGE_INVALID_JOY_AXIS_NEG = 2158,
};
class StringBank
{
public:

View file

@ -423,10 +423,6 @@
RelativePath="..\..\Aquaria\Damage.h"
>
</File>
<File
RelativePath="..\..\Aquaria\Demo.cpp"
>
</File>
<File
RelativePath="..\..\Aquaria\DSQ.cpp"
>
@ -475,6 +471,14 @@
RelativePath="..\..\Aquaria\GameEnums.h"
>
</File>
<File
RelativePath="..\..\Aquaria\GameInput.cpp"
>
</File>
<File
RelativePath="..\..\Aquaria\GameInput.h"
>
</File>
<File
RelativePath="..\..\Aquaria\GameplayVariables.cpp"
>

View file

@ -333,14 +333,6 @@
RelativePath="..\..\BBGE\ActionSet.h"
>
</File>
<File
RelativePath="..\..\BBGE\ActionStatus.cpp"
>
</File>
<File
RelativePath="..\..\BBGE\ActionStatus.h"
>
</File>
<File
RelativePath="..\..\BBGE\AfterEffect.cpp"
>
@ -461,6 +453,34 @@
RelativePath="..\..\BBGE\Gradient.h"
>
</File>
<File
RelativePath="..\..\BBGE\InputMapper.cpp"
>
</File>
<File
RelativePath="..\..\BBGE\InputMapper.h"
>
</File>
<File
RelativePath="..\..\BBGE\InputMapperRaw.cpp"
>
</File>
<File
RelativePath="..\..\BBGE\InputMapperRaw.h"
>
</File>
<File
RelativePath="..\..\BBGE\InputSystem.cpp"
>
</File>
<File
RelativePath="..\..\BBGE\InputSystem.h"
>
</File>
<File
RelativePath="..\..\BBGE\InputSystemSDL.cpp"
>
</File>
<File
RelativePath="..\..\BBGE\Joystick.cpp"
>