1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-06-08 09:31:58 +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_SWIMLEFT, KEY_J);
addAction(ACTION_SWIMRIGHT, KEY_K, -1); addAction(ACTION_SWIMRIGHT, KEY_K);
addAction(ACTION_SWIMUP, KEY_UP, -1); addAction(ACTION_SWIMUP, KEY_UP);
addAction(ACTION_SWIMDOWN, KEY_DOWN, -1); 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) if (editingBone && state)
{ {
@ -726,14 +726,14 @@ void AnimationEditor::update(float dt)
if (editingStrip) if (editingStrip)
{ {
if (isActing(ACTION_SWIMLEFT, -1)) if (isActing(ACTION_SWIMLEFT))
moveBoneStripPoint(Vector(-dt, 0)); moveBoneStripPoint(Vector(-dt, 0));
if (isActing(ACTION_SWIMRIGHT, -1)) if (isActing(ACTION_SWIMRIGHT))
moveBoneStripPoint(Vector(dt, 0)); moveBoneStripPoint(Vector(dt, 0));
if (isActing(ACTION_SWIMUP, -1)) if (isActing(ACTION_SWIMUP))
moveBoneStripPoint(Vector(0, -dt)); moveBoneStripPoint(Vector(0, -dt));
if (isActing(ACTION_SWIMDOWN, -1)) if (isActing(ACTION_SWIMDOWN))
moveBoneStripPoint(Vector(0, dt)); moveBoneStripPoint(Vector(0, dt));
} }
int spd = 1; int spd = 1;

View file

@ -113,7 +113,7 @@ public:
std::vector<KeyframeWidget*> keyframeWidgets; 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(); void rebuildKeyframeWidgets();

View file

@ -89,7 +89,7 @@ void AquariaGuiElement::setFocus(bool v)
if (v) if (v)
{ {
currentFocus = this; 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()); core->setMousePosition(getGuiPosition());
AquariaGuiElement *gui=0, *guiThis = (AquariaGuiElement*)this; AquariaGuiElement *gui=0, *guiThis = (AquariaGuiElement*)this;
@ -162,49 +162,13 @@ void AquariaGuiElement::UpdateGlobalFocus(float dt)
Direction AquariaGuiElement::GetDirection() Direction AquariaGuiElement::GetDirection()
{ {
Direction dir = DIR_NONE; Direction dir = DIR_NONE;
StateObject *obj = dsq->getTopStateObject(); // usually Game...
// This joystick code is already supposed to send ACTION_MENU*. if (obj)
// 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))
{ {
if (fabsf(p.x) > fabsf(p.y)) if (obj->isActing(ACTION_MENULEFT)) dir = DIR_LEFT;
{ else if (obj->isActing(ACTION_MENURIGHT)) dir = DIR_RIGHT;
if (p.x > 0) else if (obj->isActing(ACTION_MENUUP)) dir = DIR_UP;
dir = DIR_RIGHT; else if (obj->isActing(ACTION_MENUDOWN)) dir = DIR_DOWN;
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;
}
} }
return dir; return dir;
} }
@ -343,9 +307,6 @@ void AquariaGuiQuad::onUpdate(float dt)
Quad::onUpdate(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). // Initial delay before repeating for slider input (seconds).
const float SLIDER_REPEAT_DELAY = 0.4f; const float SLIDER_REPEAT_DELAY = 0.4f;
// Scale factor for delay as repeats continue. // Scale factor for delay as repeats continue.
@ -382,26 +343,10 @@ bool AquariaSlider::doSliderInput(float dt)
float inputAmount; // How much to adjust by? 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(); StateObject *obj = dsq->getTopStateObject();
/*if (jpos.x <= -SLIDER_JOY_THRESHOLD) if (obj && obj->isActing(ACTION_MENULEFT))
inputAmount = -0.1f; inputAmount = -0.1f;
else if (jpos.x >= SLIDER_JOY_THRESHOLD) else if (obj && obj->isActing(ACTION_MENURIGHT))
inputAmount = +0.1f;
else*/ if (obj && obj->isActing(ACTION_MENULEFT, -1))
inputAmount = -0.1f;
else if (obj && obj->isActing(ACTION_MENURIGHT, -1))
inputAmount = +0.1f; inputAmount = +0.1f;
else else
inputAmount = 0; inputAmount = 0;
@ -484,27 +429,81 @@ bool AquariaCheckBox::isGuiVisible()
AquariaKeyConfig *AquariaKeyConfig::waitingForInput = 0; 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() : AquariaGuiElement(), RenderObject()
, actionInputName(actionInputName) , actionInputName(actionInputName)
, inputSetType(inputSetType) , inputDevType(dev)
, inputIdx(inputIdx) , inputSlot(slot)
, inputField(ActionInput::GetField(dev, slot))
, actionSetIndex(0) , actionSetIndex(0)
, rejectJoyAxis(false) , rejectJoyAxis(false)
{ {
bg = new Quad(); bg = new Quad();
bg2 = new Quad(); bg2 = new Quad();
if (inputSetType == INPUTSET_OTHER) bg->setWidthHeight(90, 20);
{ bg2->setWidthHeight(90, 20);
bg->setWidthHeight(40, 20);
bg2->setWidthHeight(40, 20);
}
else
{
bg->setWidthHeight(90, 20);
bg2->setWidthHeight(90, 20);
}
bg->color = Vector(0.5f, 0.5f, 0.5f); bg->color = Vector(0.5f, 0.5f, 0.5f);
bg->alphaMod = 0; bg->alphaMod = 0;
@ -516,7 +515,6 @@ AquariaKeyConfig::AquariaKeyConfig(const std::string &actionInputName, InputSetT
addChild(bg2, PM_POINTER); addChild(bg2, PM_POINTER);
keyConfigFont = new TTFText(&dsq->fontArialSmallest); keyConfigFont = new TTFText(&dsq->fontArialSmallest);
keyConfigFont->setAlign(ALIGN_CENTER); keyConfigFont->setAlign(ALIGN_CENTER);
@ -589,342 +587,29 @@ void AquariaKeyConfig::onUpdate(float dt)
inLoop = true; inLoop = true;
unsigned int *k = 0; ActionInput &ai = as.ensureActionInput(actionInputName);
ActionInput *ai = 0; bool used = ai.hasEntry(inputSlot);
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;
}
if(used) if(used)
bg2->alphaMod = 0.3f; bg2->alphaMod = 0.3f;
else else
bg2->alphaMod = 0; bg2->alphaMod = 0;
if (waitingForInput == this) if (waitingForInput != this)
keyConfigFont->setText(ai.prettyPrintField(inputField, as.joystickID));
else
{ {
std::string s; std::string s;
s.reserve(6); s.reserve(6);
s = "_"; 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 += "_"; s += "_";
} }
keyConfigFont->setText(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(); Vector p = bg->getWorldPosition();
@ -938,7 +623,7 @@ void AquariaKeyConfig::onUpdate(float dt)
toggleEnterKey(-1); toggleEnterKey(-1);
} }
// FIXME controllerfixup: don't rely on mouse emulation here?
if (!keyDown && (core->mouse.buttons.left || core->mouse.buttons.right)) if (!keyDown && (core->mouse.buttons.left || core->mouse.buttons.right))
{ {
keyDown = true; keyDown = true;
@ -958,6 +643,19 @@ void AquariaKeyConfig::onUpdate(float dt)
waitingForInput = this; waitingForInput = this;
toggleEnterKey(1); toggleEnterKey(1);
AquariaGuiElement::canDirMoveGlobal = false; 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); 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) if(actionID == ACTION_PRIMARY)
{ {

View file

@ -87,7 +87,7 @@ public:
bool useQuad(const std::string &tex); bool useQuad(const std::string &tex);
void useGlow(const std::string &tex, int w, int h); void useGlow(const std::string &tex, int w, int h);
void useSound(const std::string &tex); 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(); virtual bool isCursorInMenuItem();
Vector getGuiPosition(); Vector getGuiPosition();
@ -166,7 +166,8 @@ protected:
class AquariaKeyConfig : public AquariaGuiElement, public RenderObject class AquariaKeyConfig : public AquariaGuiElement, public RenderObject
{ {
public: 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(); void destroy();
Vector getGuiPosition(); Vector getGuiPosition();
@ -186,8 +187,8 @@ protected:
std::string actionInputName; std::string actionInputName;
InputSetType inputSetType; const InputDeviceType inputDevType;
int inputIdx; const unsigned inputSlot, inputField;
TTFText *keyConfigFont; TTFText *keyConfigFont;
Quad *bg, *bg2; Quad *bg, *bg2;
size_t actionSetIndex; size_t actionSetIndex;
@ -267,7 +268,7 @@ public:
protected: 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 onUpdate(float dt);
virtual void onToggleHighlight(bool on); virtual void onToggleHighlight(bool on);

View file

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

View file

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

View file

@ -193,7 +193,7 @@ DSQ::DSQ(const std::string& fileSystem, const std::string& extraDataDir)
subbox = 0; subbox = 0;
modSelectorScr = 0; modSelectorScr = 0;
blackout = 0; blackout = 0;
lastInputMode = INPUT_MOUSE; lastInputMode = INP_DEV_MOUSE;
overlay = 0; overlay = 0;
recentSaveSlot = -1; recentSaveSlot = -1;
arialFontData = 0; arialFontData = 0;
@ -249,24 +249,26 @@ void DSQ::onWindowResize(int w, int h)
screenTransition->reloadDevice(); 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(lastInputMode != INP_DEV_JOYSTICK)
{ return;
if(source < 0)
for(size_t i = 0; i < user.control.actionSets.size(); ++i) /* // FIXME controllerfixup
{ if(source < 0)
const ActionSet& as = user.control.actionSets[i]; for(size_t i = 0; i < user.control.actionSets.size(); ++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]; const ActionSet& as = user.control.actionSets[i];
if(Joystick *j = core->getJoystick(as.joystickID)) if(Joystick *j = core->getJoystick(as.joystickID))
j->rumble(leftMotor, rightMotor, time); 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() void DSQ::newGame()
@ -502,7 +504,6 @@ void DSQ::debugMenu()
if (core->getShiftState()) if (core->getShiftState())
{ {
core->frameOutputMode = false;
dsq->game->togglePause(true); dsq->game->togglePause(true);
std::string s = dsq->getUserInputString(stringbank.get(2012), ""); std::string s = dsq->getUserInputString(stringbank.get(2012), "");
stringToUpper(s); stringToUpper(s);
@ -630,32 +631,6 @@ void DSQ::debugMenu()
is >> read >> nm; is >> read >> nm;
dsq->continuity.setCostume(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') else if (c == 'H')
{ {
std::ostringstream os; std::ostringstream os;
@ -1684,21 +1659,21 @@ void DSQ::toggleVersionLabel(bool on)
versionLabel->alpha.interpolateTo(a, 1); versionLabel->alpha.interpolateTo(a, 1);
} }
void DSQ::setInputMode(InputDevice mode) void DSQ::setInputMode(InputDeviceType mode)
{ {
lastInputMode = mode; lastInputMode = mode;
switch(mode) switch(mode)
{ {
case INPUT_JOYSTICK: case INP_DEV_JOYSTICK:
core->joystickAsMouse = true; core->joystickAsMouse = true;
break; break;
case INPUT_MOUSE: case INP_DEV_MOUSE:
setMousePosition(core->mouse.position); setMousePosition(core->mouse.position);
core->joystickAsMouse = false; core->joystickAsMouse = false;
break; break;
case INPUT_KEYBOARD: case INP_DEV_KEYBOARD:
break; break;
case INPUT_NODEVICE: case INP_DEV_NODEVICE:
break; 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); Core::action(id, state, source, device);
@ -3693,10 +3668,8 @@ void DSQ::action(int id, int state, int source, InputDevice device)
void DSQ::bindInput() void DSQ::bindInput()
{ {
clearActions(); clearActions();
almb.clear();
armb.clear();
addAction(ACTION_ESC, KEY_ESCAPE, -1); addAction(ACTION_ESC, KEY_ESCAPE);
addAction(MakeFunctionEvent(DSQ, onSwitchScreenMode), KEY_RETURN, 1); addAction(MakeFunctionEvent(DSQ, onSwitchScreenMode), KEY_RETURN, 1);
if (isDeveloperKeys()) if (isDeveloperKeys())
@ -3709,19 +3682,15 @@ void DSQ::bindInput()
addAction(MakeFunctionEvent(DSQ, debugMenu), KEY_BACKSPACE, 0); addAction(MakeFunctionEvent(DSQ, debugMenu), KEY_BACKSPACE, 0);
//addAction(MakeFunctionEvent(DSQ, takeScreenshotKey ), KEY_P, 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]; { "Escape", ACTION_ESC },
int sourceID = (int)i; { "Screenshot", ACTION_SCREENSHOT }
};
ImportInput(actions);
as.importAction(this, "Escape", ACTION_ESC, sourceID); if(game)
as.importAction(this, "Screenshot", ACTION_SCREENSHOT, sourceID); game->bindInput();
if(ActionInput *a = as.getActionInputByName("PrimaryAction"))
almb.push_back(a);
if(ActionInput *a = as.getActionInputByName("SecondaryAction"))
armb.push_back(a);
}
} }
void DSQ::jiggleCursor() void DSQ::jiggleCursor()
@ -3731,13 +3700,15 @@ void DSQ::jiggleCursor()
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
} }
#if 0 // FIXME controllerfixup
void DSQ::updateActionButtons() void DSQ::updateActionButtons()
{ {
// HACK: not optimal // HACK: not optimal
#if 0
// This must be done *before* Core::updateActionButtons() // This must be done *before* Core::updateActionButtons()
// for LMB/RMB emulation to work properly -- fg // 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) 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])) 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; break;
} }
} }
#endif
Core::updateActionButtons(); Core::updateActionButtons();
} }
#endif
static float skipSfxVol = 1.0; static float skipSfxVol = 1.0;
void DSQ::onUpdate(float dt) void DSQ::onUpdate(float dt)
@ -3828,7 +3801,7 @@ void DSQ::onUpdate(float dt)
if (dsq->game && watchForQuit && isNested()) if (dsq->game && watchForQuit && isNested())
{ {
if (dsq->game->isActing(ACTION_ESC, -1)) if (dsq->game->isActing(ACTION_ESC))
{ {
watchQuitFlag = true; watchQuitFlag = true;
quitNestedMain(); quitNestedMain();
@ -3851,11 +3824,10 @@ void DSQ::onUpdate(float dt)
subtitlePlayer.update(dt); subtitlePlayer.update(dt);
demo.update(dt); #if 0 //KILL
if (joystickEnabled) if (joystickEnabled)
{ {
if (dsq->getInputMode() != INPUT_JOYSTICK) if (dsq->getInputMode() != INP_DEV_JOYSTICK)
{ {
const float thresh = JOY_AXIS_THRESHOLD; const float thresh = JOY_AXIS_THRESHOLD;
for(size_t i = 0; i < getNumJoysticks(); ++i) 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)) if (j->anyButton() || !j->position.isLength2DIn(thresh) || !j->rightStick.isLength2DIn(thresh))
{ {
//debugLog("setting joystick input mode"); //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"); //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 // 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) 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) if (isDeveloperKeys() && cmDebug && cmDebug->alpha == 1 && fpsText)
@ -3935,16 +3897,18 @@ void DSQ::onUpdate(float dt)
os << "inputMode: "; os << "inputMode: ";
switch(dsq->getInputMode()) switch(dsq->getInputMode())
{ {
case INPUT_MOUSE: case INP_DEV_MOUSE:
os << "mouse"; os << "mouse";
break; break;
case INPUT_JOYSTICK: case INP_DEV_JOYSTICK:
os << "joystick"; os << "joystick";
break; break;
case INPUT_KEYBOARD: case INP_DEV_KEYBOARD:
os << "keyboard";
break;
case INP_DEV_NODEVICE:
os << "nodevice";
break; break;
case INPUT_NODEVICE:
break;
} }
os << std::endl; os << std::endl;
Bone *b = dsq->game->avatar->skeletalSprite.getBoneByIdx(1); Bone *b = dsq->game->avatar->skeletalSprite.getBoneByIdx(1);
@ -3964,7 +3928,7 @@ void DSQ::onUpdate(float dt)
os << std::endl; os << std::endl;
os << "globalScale: " << core->globalScale.x << 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"; 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)) if(Joystick *j = getJoystick(i))
{ {
os << "J[" << i << "," << (j->isEnabled() ? " on" : "off") << "]:["; os << "J[" << i << "," << (j->isEnabled() ? " on" : "off") << "]:[";
@ -3974,7 +3938,7 @@ void DSQ::onUpdate(float dt)
else else
os << '-'; os << '-';
os << "], (" << j->position.x << ", " << j->position.y << "), ("<< j->rightStick.x << ", " << j->rightStick.y << ")\n"; 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 << "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 << "PMFree: " << particleManager->getFree() << " Active: " << particleManager->getNumActive() << std::endl;
os << "cameraPos: (" << dsq->cameraPos.x << ", " << dsq->cameraPos.y << ")" << std::endl; os << "cameraPos: (" << dsq->cameraPos.x << ", " << dsq->cameraPos.y << ")" << std::endl;
@ -4226,17 +4190,6 @@ void DSQ::modifyDt(float &dt)
gameSpeed.update(dt); gameSpeed.update(dt);
dt *= gameSpeed.x; 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) void DSQ::removeElement(Element *element)
@ -4485,48 +4438,12 @@ void DSQ::fixupJoysticks()
if(Joystick *j = getJoystick(i)) if(Joystick *j = getJoystick(i))
j->setEnabled(false); j->setEnabled(false);
// Re-enable joysticks that are in use
for(size_t i = 0; i < user.control.actionSets.size(); ++i) for(size_t i = 0; i < user.control.actionSets.size(); ++i)
{ {
ActionSet& as = user.control.actionSets[i]; ActionSet& as = user.control.actionSets[i];
as.updateJoystick(); 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() void DSQ::loadStringBank()
@ -4547,34 +4464,23 @@ void DSQ::loadStringBank()
stringbank.load(fname); stringbank.load(fname);
if (mod.isActive()) { if (mod.isActive()) {
// FIXME (after controllerfixup) load mod stringbanks HERE, not up there
fname = localisePath(mod.getPath() + "stringbank.txt", mod.getPath()); fname = localisePath(mod.getPath() + "stringbank.txt", mod.getPath());
stringbank.load(fname); stringbank.load(fname);
} }
} }
InputDevice DSQ::getInputMode() const InputDeviceType DSQ::getInputMode() const
{ {
return lastInputMode; 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 bool DSQ::useMouseInput() const
{ {
return lastInputMode == INPUT_MOUSE; return lastInputMode == INP_DEV_MOUSE;
} }
bool DSQ::useJoystickInput() const 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 "Continuity.h"
#include "SubtitlePlayer.h" #include "SubtitlePlayer.h"
#include "StringBank.h" #include "StringBank.h"
#include "GameInput.h"
#include "TTFFont.h" #include "TTFFont.h"
#define AQUARIA_BUILD_MAPVIS #define AQUARIA_BUILD_MAPVIS
@ -133,42 +133,6 @@ extern GameplayVariables *vars;
#include "UserSettings.h" #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 enum NagType
{ {
NAG_TOTITLE = 0, NAG_TOTITLE = 0,
@ -208,7 +172,7 @@ public:
void nag(NagType type); 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); void title(bool fadeMusic=true);
@ -343,18 +307,16 @@ public:
InterpolatedVector gameSpeed; InterpolatedVector gameSpeed;
GameInput playerInput;
private: private:
InputDevice lastInputMode; // really don't want to expose this one InputDeviceType lastInputMode; // really don't want to expose this one
std::vector<InputDevice> _inputModes; // index: FIXME ADD INFO
public: public:
void setInputMode(InputDevice mode); void setInputMode(InputDeviceType mode);
InputDevice getInputMode() const; InputDeviceType getInputMode() const;
InputDevice getInputMode(int source) const;
InputDevice getInputModeSafe(int source) const;
bool useMouseInput() const; bool useMouseInput() const;
bool useJoystickInput() 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 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 void run(float runTime = -1, bool skipRecurseCheck = false); // same as Core::run() but with recursion check
@ -394,8 +356,6 @@ public:
std::string returnToScene; std::string returnToScene;
Demo demo;
DebugFont *fpsText, *cmDebug; DebugFont *fpsText, *cmDebug;
#ifdef AQUARIA_BUILD_CONSOLE #ifdef AQUARIA_BUILD_CONSOLE
DebugFont *console; DebugFont *console;
@ -492,8 +452,6 @@ protected:
bool _canSkipCutscene; bool _canSkipCutscene;
bool skippingCutscene; bool skippingCutscene;
std::vector<ActionInput*> almb, armb;
void recreateBlackBars(); void recreateBlackBars();
bool watchQuitFlag, watchForQuit; bool watchQuitFlag, watchForQuit;
@ -550,12 +508,10 @@ protected:
virtual void onJoystickAdded(int deviceID); virtual void onJoystickAdded(int deviceID);
virtual void onJoystickRemoved(int instanceID); virtual void onJoystickRemoved(int instanceID);
virtual void updateActionButtons(); //virtual void updateActionButtons();
public: public:
void fixupJoysticks(); void fixupJoysticks();
void initActionButtons();
void importActionButtons();
}; };
extern DSQ *dsq; extern DSQ *dsq;

View file

@ -1303,13 +1303,13 @@ bool Entity::updateCurrents(float dt)
dist.normalize2D(); dist.normalize2D();
float v = dist.x; float v = dist.x;
float scale = 0.2f; 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; Avatar *a = dsq->game->avatar;
if (v < 0) 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 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() 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++) 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(); 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() void Game::toggleWorldMap()
@ -3219,69 +3209,62 @@ void Game::bindInput()
ActionMapper::clearActions(); ActionMapper::clearActions();
//ActionMapper::clearCreatedEvents(); //ActionMapper::clearCreatedEvents();
addAction(ACTION_ESC, KEY_ESCAPE, -1); addAction(ACTION_ESC, KEY_ESCAPE);
#ifdef AQUARIA_BUILD_SCENEEDITOR #ifdef AQUARIA_BUILD_SCENEEDITOR
if (dsq->canOpenEditor()) if (dsq->canOpenEditor())
{ {
addAction(ACTION_TOGGLESCENEEDITOR, KEY_TAB, -1); addAction(ACTION_TOGGLESCENEEDITOR, KEY_TAB);
} }
#endif #endif
if (dsq->canOpenEditor()) if (dsq->canOpenEditor())
{ {
//addAction(MakeFunctionEvent(Game, toggleMiniMapRender), KEY_M, 0); //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]; { "PrimaryAction", ACTION_PRIMARY},
int sourceID = (int)i; { "SecondaryAction", ACTION_SECONDARY},
as.importAction(this, "PrimaryAction", ACTION_PRIMARY, sourceID); { "Escape", ACTION_ESC},
as.importAction(this, "SecondaryAction", ACTION_SECONDARY, sourceID); { "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);
// used for scrolling help text // used for scrolling help text
as.importAction(this, "SwimUp", ACTION_SWIMUP, sourceID); { "SwimUp", ACTION_SWIMUP},
as.importAction(this, "SwimDown", ACTION_SWIMDOWN, sourceID); { "SwimDown", ACTION_SWIMDOWN},
as.importAction(this, "SwimLeft", ACTION_SWIMLEFT, sourceID); { "SwimLeft", ACTION_SWIMLEFT},
as.importAction(this, "SwimRight", ACTION_SWIMRIGHT, sourceID); { "SwimRight", ACTION_SWIMRIGHT},
as.importAction(this, "MenuUp", ACTION_MENUUP, sourceID); { "PrevPage", ACTION_PREVPAGE},
as.importAction(this, "MenuDown", ACTION_MENUDOWN, sourceID); { "NextPage", ACTION_NEXTPAGE},
as.importAction(this, "MenuLeft", ACTION_MENULEFT, sourceID); { "CookFood", ACTION_COOKFOOD},
as.importAction(this, "MenuRight", ACTION_MENURIGHT, sourceID); { "FoodLeft", ACTION_FOODLEFT},
{ "FoodRight", ACTION_FOODRIGHT},
as.importAction(this, "PrevPage", ACTION_PREVPAGE, sourceID); { "FoodDrop", ACTION_FOODDROP},
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);
// To capture quick song keys via script // To capture quick song keys via script
as.importAction(this, "SongSlot1", ACTION_SONGSLOT1, sourceID); { "SongSlot1", ACTION_SONGSLOT1},
as.importAction(this, "SongSlot2", ACTION_SONGSLOT2, sourceID); { "SongSlot2", ACTION_SONGSLOT2},
as.importAction(this, "SongSlot3", ACTION_SONGSLOT3, sourceID); { "SongSlot3", ACTION_SONGSLOT3},
as.importAction(this, "SongSlot4", ACTION_SONGSLOT4, sourceID); { "SongSlot4", ACTION_SONGSLOT4},
as.importAction(this, "SongSlot5", ACTION_SONGSLOT5, sourceID); { "SongSlot5", ACTION_SONGSLOT5},
as.importAction(this, "SongSlot6", ACTION_SONGSLOT6, sourceID); { "SongSlot6", ACTION_SONGSLOT6},
as.importAction(this, "SongSlot7", ACTION_SONGSLOT7, sourceID); { "SongSlot7", ACTION_SONGSLOT7},
as.importAction(this, "SongSlot8", ACTION_SONGSLOT8, sourceID); { "SongSlot8", ACTION_SONGSLOT8},
as.importAction(this, "SongSlot9", ACTION_SONGSLOT9, sourceID); { "SongSlot9", ACTION_SONGSLOT9},
as.importAction(this, "SongSlot10", ACTION_SONGSLOT10, sourceID); { "SongSlot10", ACTION_SONGSLOT10},
as.importAction(this, "Revert", ACTION_REVERT, sourceID); { "Revert", ACTION_REVERT},
as.importAction(this, "Look", ACTION_LOOK, sourceID); { "Look", ACTION_LOOK},
as.importAction(this, "Roll", ACTION_ROLL, sourceID); { "Roll", ACTION_ROLL}
} };
ImportInput(actions);
if (avatar) if (avatar)
avatar->bindInput(); avatar->bindInput();
@ -3776,7 +3759,7 @@ bool Game::updateMusic()
return false; return false;
} }
void Game::onPressEscape(int source, InputDevice device) void Game::onPressEscape(int source, InputDeviceType device)
{ {
if (dsq->isInCutscene()) if (dsq->isInCutscene())
{ {
@ -4240,13 +4223,13 @@ void Game::updateCursor(float dt)
{ {
bool rotate = false; bool rotate = false;
if (dsq->getInputMode() == INPUT_MOUSE) if (dsq->getInputMode() == INP_DEV_MOUSE)
{ {
dsq->cursor->offset.stop(); dsq->cursor->offset.stop();
dsq->cursor->offset = Vector(0,0); dsq->cursor->offset = Vector(0,0);
//debugLog("offset lerp stop in mouse!"); //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()) 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 // Don't show the cursor in keyboard/joystick mode if it's not
// already visible (this keeps the cursor from appearing for an // already visible (this keeps the cursor from appearing for an
// instant during map fadeout). // 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; dsq->cursor->alphaMod = 0.5;
/* /*
@ -4290,7 +4273,7 @@ void Game::updateCursor(float dt)
else if (avatar) else if (avatar)
{ {
//Vector v = avatar->getVectorToCursorFromScreenCentre(); //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; dsq->cursor->alphaMod = 0;
if (!avatar->isSinging()) if (!avatar->isSinging())
@ -4518,7 +4501,7 @@ void Game::update(float dt)
if (inHelpScreen) if (inHelpScreen)
{ {
const float helpTextScrollSpeed = 400.0f; const float helpTextScrollSpeed = 400.0f;
if (isActing(ACTION_SWIMDOWN, -1)) if (isActing(ACTION_SWIMDOWN))
{ {
helpText->offset.stop(); helpText->offset.stop();
helpText->offset.y -= helpTextScrollSpeed * dt; helpText->offset.y -= helpTextScrollSpeed * dt;
@ -4527,7 +4510,7 @@ void Game::update(float dt)
helpText->offset.y = -helpText->getHeight() + core->getVirtualHeight(); helpText->offset.y = -helpText->getHeight() + core->getVirtualHeight();
} }
} }
if (isActing(ACTION_SWIMUP, -1)) if (isActing(ACTION_SWIMUP))
{ {
helpText->offset.stop(); helpText->offset.stop();
helpText->offset.y += helpTextScrollSpeed * dt; helpText->offset.y += helpTextScrollSpeed * dt;
@ -5027,8 +5010,6 @@ void Game::removeState()
dsq->overlay->alpha.interpolateTo(1, fadeTime); dsq->overlay->alpha.interpolateTo(1, fadeTime);
dsq->run(fadeTime); dsq->run(fadeTime);
dsq->rumble(0,0,0,-1, INPUT_JOYSTICK);
dsq->sound->clearFadingSfx(); dsq->sound->clearFadingSfx();

View file

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

View file

@ -142,7 +142,9 @@ enum AquariaActions
ACTION_LOOK , ACTION_LOOK ,
ACTION_TOGGLEHELPSCREEN, ACTION_TOGGLEHELPSCREEN,
ACTION_PLACE_AVATAR, ACTION_PLACE_AVATAR,
ACTION_SCREENSHOT ACTION_SCREENSHOT,
ACTION_SIZE // for array bounds
}; };
enum AuraType 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 getAvatarWorldMapPosition();
Vector getWorldToTile(WorldMapTile *tile, Vector position, bool fromCenter, bool tilePos); Vector getWorldToTile(WorldMapTile *tile, Vector position, bool fromCenter, bool tilePos);
void setProperTileColor(WorldMapTile *tile); 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); GemMover* addGem(GemData *gemData);
void bindInput(); void bindInput();
void createGemHint(const std::string &gfx); void createGemHint(const std::string &gfx);

View file

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

View file

@ -88,7 +88,7 @@ public:
void onContinuityReset(); void onContinuityReset();
void bindInput(); 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); void refreshFoodSlots(bool effects);

View file

@ -413,7 +413,7 @@ void MiniMapRender::onUpdate(float dt)
{ {
doubleClickDelay = 0; doubleClickDelay = 0;
if (!core->isStateJumpPending()) if (!core->isStateJumpPending())
dsq->game->action(ACTION_TOGGLEMENU, 1, -1, INPUT_NODEVICE); dsq->game->action(ACTION_TOGGLEMENU, 1, -1, INP_DEV_NODEVICE);
btn = true; btn = true;
} }
break; 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); AquariaGuiElement *closest = AquariaGuiElement::getClosestGuiElement(core->mouse.position);
if(closest) if(closest)

View file

@ -166,7 +166,7 @@ public:
void setSubText(const std::string& s); 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: protected:
virtual void onUpdate(float dt); 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()) if (hasScript())
{ {

View file

@ -91,7 +91,7 @@ public:
void addNode(size_t idx); void addNode(size_t idx);
void update(float dt); void update(float dt);
void setActive(bool v); 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); void setEmitter(const std::string& name);
PathNode *getPathNode(size_t idx); PathNode *getPathNode(size_t idx);

View file

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

View file

@ -89,7 +89,7 @@ public:
void flipElementVert(); void flipElementVert();
void deleteSelectedElement(); void deleteSelectedElement();
void deleteElement(int selectedIdx); 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 scaleElementUp();
void scaleElementDown(); void scaleElementDown();
void scaleElement1(); void scaleElement1();

View file

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

View file

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

View file

@ -218,7 +218,7 @@ void UserSettings::save()
{ {
XMLElement *xml_action = doc.NewElement("Action"); XMLElement *xml_action = doc.NewElement("Action");
const ActionInput& ai = as.inputSet[i]; 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_action->SetAttribute("input", ai.toString().c_str());
xml_actionSet->InsertEndChild(xml_action); xml_actionSet->InsertEndChild(xml_action);
@ -280,30 +280,30 @@ void UserSettings::save()
static void ensureDefaultActions(ActionSet& as) static void ensureDefaultActions(ActionSet& as)
{ {
as.clearActions(); as.clearActions();
as.addActionInput("PrimaryAction"); as.ensureActionInput("PrimaryAction");
as.addActionInput("SecondaryAction"); as.ensureActionInput("SecondaryAction");
as.addActionInput("SwimUp"); as.ensureActionInput("SwimUp");
as.addActionInput("SwimDown"); as.ensureActionInput("SwimDown");
as.addActionInput("SwimLeft"); as.ensureActionInput("SwimLeft");
as.addActionInput("SwimRight"); as.ensureActionInput("SwimRight");
as.addActionInput("Roll"); as.ensureActionInput("Roll");
as.addActionInput("Revert"); as.ensureActionInput("Revert");
as.addActionInput("WorldMap"); as.ensureActionInput("WorldMap");
as.addActionInput("Escape"); as.ensureActionInput("Escape");
as.addActionInput("PrevPage"); as.ensureActionInput("PrevPage");
as.addActionInput("NextPage"); as.ensureActionInput("NextPage");
as.addActionInput("CookFood"); as.ensureActionInput("CookFood");
as.addActionInput("FoodLeft"); as.ensureActionInput("FoodLeft");
as.addActionInput("FoodRight"); as.ensureActionInput("FoodRight");
as.addActionInput("FoodDrop"); as.ensureActionInput("FoodDrop");
as.addActionInput("Look"); as.ensureActionInput("Look");
as.addActionInput("ToggleHelp"); as.ensureActionInput("ToggleHelp");
as.addActionInput("Screenshot"); as.ensureActionInput("Screenshot");
for(int i = 1; i <= 10; ++i) for(int i = 1; i <= 10; ++i)
{ {
std::ostringstream os; std::ostringstream os;
os << "SongSlot" << i; 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"); const char *input = xml_action->Attribute("input");
if (name && *name && input && *input) if (name && *name && input && *input)
{ {
ActionInput *ai = as.addActionInput(name); ActionInput& ai = as.ensureActionInput(name);
ai->fromString(input); ai.fromString(input);
} }
} }
} }
@ -584,30 +584,10 @@ void UserSettings::apply()
dsq->loops.updateVolume(); 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(); dsq->fixupJoysticks();
core->debugLogActive = system.debugLogOn; core->debugLogActive = system.debugLogOn;
if (dsq->game)
{
dsq->game->bindInput();
}
dsq->bindInput(); dsq->bindInput();
core->settings.prebufferSounds = audio.prebuffer; core->settings.prebufferSounds = audio.prebuffer;

View file

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

View file

@ -26,267 +26,267 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "GameKeyNames.h" #include "GameKeyNames.h"
#include "StringBank.h" #include "StringBank.h"
static const char *jaxisname(int joystickID, unsigned axis)
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)
{ {
Joystick *j = core->getJoystick(joystickID); 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); 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); char c, pretty;
return s.empty() ? "0" : s; 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: // Special case keyboard input:
// Return key name for current keyboard layout! // Return key name for current keyboard layout!
// It's just confusing to see Y instead of Z with a german keyboard layout... // It's just confusing to see Y instead of Z with a german keyboard layout...
if(k && k < KEY_MAXARRAY) const SDL_Keycode kcode = SDL_GetKeyFromScancode((SDL_Scancode)k);
{ if(kcode == SDLK_UNKNOWN)
#ifdef BBGE_BUILD_SDL2 s = SDL_GetScancodeName((SDL_Scancode)k);
pretty = SDL_GetScancodeName((SDL_Scancode)k); else
const SDL_Keycode kcode = SDL_GetKeyFromScancode((SDL_Scancode)k); s = SDL_GetKeyName(kcode);
if(kcode != SDLK_UNKNOWN)
pretty = SDL_GetKeyName(kcode);
#else #else
pretty = SDL_GetKeyName((SDLKey)k); s = SDL_GetKeyName((SDLKey)k);
#endif #endif
} return s && *s ? s : NULL;
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;
} }
static int checkInp(const char *s, int category, int limit, StringBankIndexBBGE errid) static unsigned getKeyCodeFromSDLName(const char *s)
{ {
const int k = atoi(s); #ifdef BBGE_BUILD_SDL2
if(!k) return SDL_GetScancodeFromName(s);
return 0; #endif
if(k < limit) return SDL_GetKeyFromName(s);
return k + category; }
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; std::ostringstream os;
os << stringbank.get(errid) << k; static const char *axislabels[] = { "(-)", "", "(+)" };
errorLog(os.str());
return 0; 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") if(s == "LMB")
k = MOUSE_BUTTON_LEFT; return MOUSE_BUTTON_LEFT;
else if(s == "RMB") else if(s == "RMB")
k = MOUSE_BUTTON_RIGHT; return MOUSE_BUTTON_RIGHT;
else if(s == "MMB") else if(s == "MMB")
k = MOUSE_BUTTON_MIDDLE; return 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());
}
// Non-configurable keys return getLegacyInputCodeFromKeyName(s.c_str());
if(k == KEY_ESCAPE) }
static unsigned getMouseButtonFromString(const std::string& s)
{
if(s.empty() || s == "0")
return 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; return k;
std::ostringstream os; return atoi(s.c_str());
os << "ActionButton out of range: [" << s << "] = " << k;
errorLog(os.str());
return 0;
} }
static ActionInput::JoyData getJostickDataFromString(const std::string& s)
ActionInput::ActionInput()
{ {
for (int i = 0; i < INP_COMBINED_SIZE; i++) ActionInput::JoyData jd;
data.all[i] = 0;
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 std::string ActionInput::toString() const
@ -295,15 +295,15 @@ std::string ActionInput::toString() const
for (int i = 0; i < INP_MSESIZE; i++) 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++) 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++) for (int i = 0; i < INP_JOYSIZE; i++)
{ {
os << getInputCodeToString(data.single.joy[i]) << " "; os << getJoystickDataToString(joy[i]) << " ";
} }
return os.str(); return os.str();
@ -316,17 +316,231 @@ void ActionInput::fromString(const std::string &read)
for (int i = 0; i < INP_MSESIZE; i++) for (int i = 0; i < INP_MSESIZE; i++)
{ {
is >> str; is >> str;
data.single.mse[i] = getStringToInputCode(str); mse[i] = getMouseButtonFromString(str);
} }
for (int i = 0; i < INP_KEYSIZE; i++) for (int i = 0; i < INP_KEYSIZE; i++)
{ {
is >> str; is >> str;
data.single.key[i] = getStringToInputCode(str); key[i] = getKeyFromString(str);
} }
for (int i = 0; i < INP_JOYSIZE; i++) for (int i = 0; i < INP_JOYSIZE; i++)
{ {
is >> str; 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 #define ACTIONINPUT_H
#include <string> #include <string>
#include "InputSystem.h"
// Slots for each input/key type
enum ActionInputSize enum ActionInputSize
{ {
INP_MSESIZE = 1, INP_MSESIZE = 1,
INP_KEYSIZE = 2, INP_KEYSIZE = 2,
INP_JOYSIZE = 1, 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); 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 class ActionInput
{ {
public: public: // only public because some static funcs in the cpp file need this. Don't use elsewhere!
ActionInput(); struct JoyData
std::string name;
union
{ {
struct JoyData();
{ InputControlType ctrlType;
unsigned int mse[INP_MSESIZE]; unsigned ctrlID; // 0 = not set, otherwise actual id + 1
unsigned int key[INP_KEYSIZE]; int x, y; // each [-1..+1]: (x,y) for hat direction, (x) for axis direction
unsigned int joy[INP_JOYSIZE]; };
} single; inline const std::string& getName() const { return name; }
int all[INP_COMBINED_SIZE]; private:
} data; 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; std::string toString() const;
void fromString(const std::string &read); void fromString(const std::string &read);
};
enum InputSetType // for the UI (field is in [0..INP_COMBINED_SIZE])
{ std::string prettyPrintField(unsigned field, int joystickID = -1) const;
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
}; };
#endif #endif

View file

@ -18,76 +18,70 @@ See the GNU General Public License for more details.
#include "ActionMapper.h" #include "ActionMapper.h"
#include "Core.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) LegacyActionData()
return INPUT_KEYBOARD; : id(-1), state(-1)
if(k < MOUSE_BUTTON_EXTRA_END) , event(0)
return INPUT_MOUSE; {
return INPUT_JOYSTICK; }
}
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() ActionMapper::ActionMapper()
{ {
cleared = false; cleared = false;
inputEnabled = true; inputEnabled = true;
inUpdate = false; inUpdate = false;
//memset(keyStatus, 0, sizeof(keyStatus)); InputMapper::RegisterActionMapper(this);
} }
ActionMapper::~ActionMapper() ActionMapper::~ActionMapper()
{ {
InputMapper::UnregisterActionMapper(this);
clearCreatedEvents(); clearCreatedEvents();
} }
ActionData *ActionMapper::getActionDataByIDAndSource(int actionID, int source) LegacyActionData *ActionMapper::getActionDataByID(int actionID)
{ {
for (ActionDataSet::iterator i = actionData.begin(); i != actionData.end(); ++i) for (ActionDataSet::iterator i = actionData.begin(); i != actionData.end(); ++i)
{ {
if (i->id == actionID && i->source == source) if (i->id == actionID)
return &(*i); return &(*i);
} }
return 0; return 0;
} }
bool ActionMapper::isActing(int actionID, int source) bool ActionMapper::isActing(unsigned actionID) const
{ {
if(source < 0) return actionID < _activeActions.size() ? _activeActions[actionID] : false;
{
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;
} }
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) if (!ad)
{ {
ActionData data; LegacyActionData data;
data.id = actionID; data.id = actionID;
data.source = source;
actionData.push_back(data); actionData.push_back(data);
ad = &actionData.back(); 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()) if(std::find(ad->buttonList.begin(), ad->buttonList.end(), k) == ad->buttonList.end())
ad->buttonList.push_back(k); 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.event = event;
data.state = state; data.state = state;
data.buttonList.push_back(k); data.buttonList.push_back(k);
actionData.push_back(data); actionData.push_back(data);
//keyStatus[k] = core->getKeyState(k);
} }
Event* ActionMapper::addCreatedEvent(Event *event) Event* ActionMapper::addCreatedEvent(Event *event)
@ -141,89 +132,77 @@ void ActionMapper::disableInput()
inputEnabled = false; 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) void ActionMapper::onUpdate (float dt)
{ {
if (inUpdate) if(inputEnabled && !inUpdate)
return;
inUpdate = true;
cleared = false;
for (ActionDataSet::iterator i = actionData.begin(); i != actionData.end(); ++i)
{ {
for (ButtonList::iterator j = i->buttonList.begin(); j != i->buttonList.end(); j++) inUpdate = true;
{ updateDirectInput();
const int k = (*j); updateActions();
const ActionData *ad = &(*i); inUpdate = false;
const bool keyChanged = isKeyChanged(k, ad->source); }
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(k == (*j))
if (inputEnabled)
{ {
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 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() void ActionMapper::clearActions()
@ -232,19 +211,47 @@ void ActionMapper::clearActions()
actionData.clear(); actionData.clear();
} }
bool ActionMapper::isKeyChanged(int k, int sourceID) void ActionMapper::recvAction(unsigned actionID, bool keyState, int playerID, InputDeviceType device)
{ {
if(sourceID < 0) if(!inputEnabled)
return isKeyChanged(k); return;
return core->getActionStatus(sourceID)->isKeyChanged(k);
// 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 if(!inputEnabled)
const int m = core->getMaxActionStatusIndex(); return;
for(int i = -1; i <= m; ++i)
if(core->getActionStatus(i)->isKeyChanged(k)) _inputChanges.push_back(keyState ? (int)k : -(int)k);
return true; }
return false;
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 "Base.h"
#include "ActionInput.h" #include "ActionInput.h"
InputDevice getDeviceForActionbutton(int k);
class Event; class Event;
class ActionMapper; class ActionMapper;
#include "ActionStatus.h"
#include "ActionSet.h" #include "ActionSet.h"
#include "Joystick.h" #include "Joystick.h"
typedef std::vector<int> ButtonList; struct LegacyActionData;
struct ActionData
{
ActionData()
: id(-1), state(-1), source(-1)
, event(0)
{
}
int id, state, source;
Event *event;
ButtonList buttonList;
};
class ActionMapper class ActionMapper
{ {
public: public:
struct NamedAction // for importing
{
const char * const name;
unsigned actionID;
};
// funcs // funcs
ActionMapper(); ActionMapper();
virtual ~ActionMapper(); virtual ~ActionMapper();
void addAction(Event *event, int k, int state=-1); // Overridden to react to events (both legacy and input-mapped)
void addAction(int actionID, int k, int source); 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(); void clearActions();
@ -69,7 +62,7 @@ public:
// vars // vars
typedef std::vector<ActionData> ActionDataSet; typedef std::vector<LegacyActionData> ActionDataSet;
ActionDataSet actionData; ActionDataSet actionData;
bool cleared; bool cleared;
@ -80,22 +73,41 @@ public:
Event *addCreatedEvent(Event *event); Event *addCreatedEvent(Event *event);
void clearCreatedEvents(); 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: 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; bool inputEnabled;
void onUpdate (float dt); void onUpdate (float dt);
private: private:
bool isKeyChanged(int k); void updateDirectInput();
bool isKeyChanged(int k, int sourceID); void updateActions();
//bool _pollActionData(const ActionData& ad);
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 #endif

View file

@ -33,7 +33,6 @@ JoystickConfig::JoystickConfig()
ActionSet::ActionSet() ActionSet::ActionSet()
{ {
inputMode = INPUT_NODEVICE;
enabled = true; enabled = true;
joystickID = ACTIONSET_REASSIGN_JOYSTICK; joystickID = ACTIONSET_REASSIGN_JOYSTICK;
} }
@ -132,11 +131,11 @@ void ActionSet::updateJoystick()
j->setEnabled(true); 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); return &(*i);
} }
@ -144,52 +143,34 @@ ActionInput *ActionSet::getActionInputByName(const std::string &name)
return 0; 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 (!enabled) return;
if (!mapper) 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]; errorLog("ActionSet::importAction: Undefined action name: " + name);
if (actionInput->name == name) return;
{
for (int i = 0; i < INP_COMBINED_SIZE; i++)
if (actionInput->data.all[i])
mapper->addAction(actionID, actionInput->data.all[i], sourceID);
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; for (ActionInputSet::iterator i = inputSet.begin(); i != inputSet.end(); i++)
if (!mapper) return; if (nocasecmp(i->getName(), name) == 0)
return *i;
for (size_t i = 0; i < inputSet.size(); i++) ActionInput newa(name);
{
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;
inputSet.push_back(newa); 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" #include "ActionInput.h"
typedef std::vector<ActionInput> ActionInputSet; class InputMapper;
class ActionMapper;
class Event; class Event;
const int ACTIONSET_REASSIGN_JOYSTICK = -2; const int ACTIONSET_REASSIGN_JOYSTICK = -2;
@ -41,14 +39,16 @@ struct JoystickConfig
float s1dead, s2dead; float s1dead, s2dead;
}; };
// One ActionSet is a serializable configuration of input mappings.
class ActionSet class ActionSet
{ {
typedef std::vector<ActionInput> ActionInputSet;
public: public:
ActionSet(); ActionSet();
// import this ActionSet into ActionMapper // import this ActionSet into InputMapper. Should be called via ActionMapper::ImportInput() only!
void importAction(ActionMapper *mapper, const std::string &name, Event *event, int state) const; void importAction(InputMapper *mapper, const std::string &name, unsigned actionID) const;
void importAction(ActionMapper *mapper, const std::string &name, int actionID, int sourceID) const;
void clearActions(); void clearActions();
int assignJoystickByName(bool force); // -1 if no such joystick found int assignJoystickByName(bool force); // -1 if no such joystick found
void assignJoystickIdx(int idx, bool updateValues); void assignJoystickIdx(int idx, bool updateValues);
@ -56,11 +56,10 @@ public:
// note: this only ENABLES joysticks if they are needed, but never disables any // note: this only ENABLES joysticks if they are needed, but never disables any
void updateJoystick(); void updateJoystick();
ActionInput *addActionInput(const std::string &name); ActionInput& ensureActionInput(const std::string &name);
ActionInput *getActionInputByName(const std::string &name); const ActionInput *getActionInputByName(const std::string &name) const;
InputDevice inputMode; int joystickID; // >= 0: use that, -1 = no joystick, or ACTIONSET_REASSIGN_JOYSTICK
size_t joystickID; // >= 0: use that, -1 = no joystick, or ACTIONSET_REASSIGN_JOYSTICK
// --- Saved in config --- // --- Saved in config ---
ActionInputSet inputSet; 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; mouseCircle = 0;
overrideStartLayer = 0; overrideStartLayer = 0;
overrideEndLayer = 0; overrideEndLayer = 0;
frameOutputMode = false;
updateMouse = true;
particlesPaused = false; particlesPaused = false;
joystickAsMouse = false; joystickAsMouse = false;
currentLayerPass = 0; currentLayerPass = 0;
@ -384,11 +382,6 @@ Core::Core(const std::string &filesystem, const std::string& extraDataDir, int n
loopDone = false; loopDone = false;
core = this; core = this;
for (int i = 0; i < KEY_MAXARRAY; i++)
{
keys[i] = 0;
}
globalResolutionScale = globalScale = Vector(1,1,1); globalResolutionScale = globalScale = Vector(1,1,1);
initRenderObjectLayers(numRenderLayers); initRenderObjectLayers(numRenderLayers);
@ -476,8 +469,6 @@ std::string Core::getUserDataFolder()
Core::~Core() Core::~Core()
{ {
clearActionButtons();
if (particleManager) if (particleManager)
{ {
delete particleManager; delete particleManager;
@ -534,7 +525,7 @@ void Core::init()
{ {
setupFileAccess(); setupFileAccess();
unsigned sdlflags = SDL_INIT_EVERYTHING; unsigned sdlflags = SDL_INIT_EVERYTHING & ~SDL_INIT_TIMER;
quitNestedMainFlag = false; quitNestedMainFlag = false;
#ifdef BBGE_BUILD_SDL2 #ifdef BBGE_BUILD_SDL2
@ -587,27 +578,9 @@ Vector Core::getGamePosition(const Vector &v)
return cameraPos + (v * invGlobalScale); return cameraPos + (v * invGlobalScale);
} }
bool Core::getMouseButtonState(int m) bool Core::getKeyState(unsigned k) const
{ {
int mcode=m; return rawInput.isKeyPressed(k);
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;
} }
void Core::initJoystickLibrary() void Core::initJoystickLibrary()
@ -652,12 +625,6 @@ void Core::detectJoysticks()
bool Core::initInputLibrary() bool Core::initInputLibrary()
{ {
core->mouse.position = Vector(getWindowWidth()/2, getWindowHeight()/2); core->mouse.position = Vector(getWindowWidth()/2, getWindowHeight()/2);
for (int i = 0; i < KEY_MAXARRAY; i++)
{
keys[i] = 0;
}
return true; return true;
} }
@ -1255,6 +1222,10 @@ bool Core::doMouseConstraint()
void Core::onEvent(const SDL_Event& event) void Core::onEvent(const SDL_Event& event)
{ {
const bool focus = window->hasFocus(); const bool focus = window->hasFocus();
if(focus)
InputSystem::handleSDLEvent(&event);
switch (event.type) switch (event.type)
{ {
case SDL_KEYDOWN: case SDL_KEYDOWN:
@ -1263,37 +1234,12 @@ void Core::onEvent(const SDL_Event& event)
{ {
setInputGrab(!grabInput); 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; break;
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
{ {
if (focus && updateMouse) if (focus)
{ {
mouse.lastPosition = mouse.position; mouse.lastPosition = mouse.position;
@ -1309,19 +1255,6 @@ void Core::onEvent(const SDL_Event& event)
break; break;
#ifdef BBGE_BUILD_SDL2 #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: case SDL_JOYDEVICEADDED:
onJoystickAdded(event.jdevice.which); onJoystickAdded(event.jdevice.which);
break; break;
@ -1329,82 +1262,12 @@ void Core::onEvent(const SDL_Event& event)
case SDL_JOYDEVICEREMOVED: case SDL_JOYDEVICEREMOVED:
onJoystickRemoved(event.jdevice.which); onJoystickRemoved(event.jdevice.which);
break; 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 #endif
} }
} }
void Core::pollEvents(float dt) 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(); window->handleInput();
for(size_t i = 0; i < joysticks.size(); ++i) for(size_t i = 0; i < joysticks.size(); ++i)
@ -1412,8 +1275,8 @@ void Core::pollEvents(float dt)
joysticks[i]->update(dt); joysticks[i]->update(dt);
// all input done; update button states // all input done; update button states
updateActionButtons(); //updateActionButtons();
rawInput.update();
} }
#define _VLN(x, y, x2, y2) glVertex2f(x, y); glVertex2f(x2, y2); #define _VLN(x, y, x2, y2) glVertex2f(x, y); glVertex2f(x2, y2);
@ -2442,11 +2305,9 @@ void Core::onJoystickAdded(int deviceID)
if(!joysticks[i]) if(!joysticks[i])
{ {
joysticks[i] = j; joysticks[i] = j;
goto done; return;
} }
joysticks.push_back(j); joysticks.push_back(j);
done:
;
} }
void Core::onJoystickRemoved(int instanceID) void Core::onJoystickRemoved(int instanceID)
@ -2467,26 +2328,6 @@ Joystick *Core::getJoystick(size_t idx)
return i < joysticks.size() ? joysticks[i] : NULL; 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> #include <png.h>
bool Core::pngSave(const char *filename, unsigned width, unsigned height, unsigned char *data) 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 "DarkLayer.h"
#include "GameKeys.h" #include "GameKeys.h"
#include "InputMapperRaw.h"
class ParticleEffect; class ParticleEffect;
class Joystick; class Joystick;
@ -81,7 +82,6 @@ struct MouseButtons
} }
ButtonState left, right, middle; ButtonState left, right, middle;
ButtonState extra[mouseExtraButtons];
}; };
struct Mouse struct Mouse
@ -96,7 +96,7 @@ struct Mouse
MouseButtons pure_buttons; MouseButtons pure_buttons;
unsigned rawButtonMask; unsigned rawButtonMask;
Vector change; Vector change;
bool buttonsEnabled; bool buttonsEnabled; //KILL
int scrollWheelChange; int scrollWheelChange;
}; };
@ -273,7 +273,7 @@ public:
void setMouseConstraint(bool on); void setMouseConstraint(bool on);
void setMouseConstraintCircle(const Vector& pos, float mouseCircle); 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); bool exists(const std::string &file);
@ -372,11 +372,10 @@ public:
void clearRenderObjects(); void clearRenderObjects();
bool getKeyState(int k); bool getKeyState(unsigned k) const;
bool getMouseButtonState(int m); bool isKeyChanged(unsigned k) const;
int currentLayerPass; int currentLayerPass;
int keys[KEY_MAXARRAY];
virtual void debugLog(const std::string &s); virtual void debugLog(const std::string &s);
virtual void errorLog(const std::string &s); virtual void errorLog(const std::string &s);
void messageBox(const std::string &title, const std::string &msg); void messageBox(const std::string &title, const std::string &msg);
@ -404,12 +403,9 @@ public:
int flipMouseButtons; int flipMouseButtons;
FrameBuffer frameBuffer; FrameBuffer frameBuffer;
void updateRenderObjects(float dt); void updateRenderObjects(float dt);
bool joystickAsMouse; bool joystickAsMouse; //KILL?
virtual void prepScreen(bool t){} virtual void prepScreen(bool t){}
bool updateMouse;
bool frameOutputMode;
int overrideStartLayer, overrideEndLayer; int overrideStartLayer, overrideEndLayer;
ParticleEffect* createParticleEffect(const std::string &name, const Vector &position, int layer, float rotz=0); ParticleEffect* createParticleEffect(const std::string &name, const Vector &position, int layer, float rotz=0);
@ -536,20 +532,13 @@ protected:
void setupFileAccess(); void setupFileAccess();
std::string _extraDataDir; std::string _extraDataDir;
std::vector<ActionButtonStatus*> actionStatus; // contains at least 1 element (the sentinel) InputMapperRaw rawInput;
virtual void updateActionButtons();
void clearActionButtons();
public: 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 Joystick *getJoystick(size_t idx); // warning: may return NULL/contain holes
// not the actual number of joysticks! // not the actual number of joysticks!
size_t getNumJoysticks() const { return joysticks.size(); } size_t getNumJoysticks() const { return joysticks.size(); }
Joystick *getJoystickForSourceID(int sourceID);
private: private:
std::vector<Joystick*> joysticks; std::vector<Joystick*> joysticks;
}; };

View file

@ -64,7 +64,7 @@ void EventPtr::call()
} }
if (actionMapperCallback) 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 "GameKeyNames.h"
#include "ActionStatus.h" #include "GameKeys.h"
#include <stdio.h> #include <stdio.h>
#include <map> #include <map>
typedef std::map<std::string, int> InputCodeMap; typedef std::map<std::string, int> InputCodeMap;
InputCodeMap inputCodeMap; static InputCodeMap inputCodeMap;
static std::string keyNames[ACTION_BUTTON_ENUM_SIZE]; static const char *keyNames[ACTION_BUTTON_ENUM_SIZE];
static void initInputCodeMap() static void initInputCodeMap()
{ {
@ -101,38 +101,31 @@ static void initInputCodeMap()
K(KEY_RBRACKET) K(KEY_RBRACKET)
K(KEY_TILDE) K(KEY_TILDE)
K(MOUSE_BUTTON_LEFT) K(MOUSE_BUTTON_LEFT)
K(MOUSE_BUTTON_RIGHT) K(MOUSE_BUTTON_RIGHT)
K(MOUSE_BUTTON_MIDDLE) K(MOUSE_BUTTON_MIDDLE)
#undef K #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 // 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) 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]; return inputCodeMap[name];
} }
const std::string& getKeyNameFromInputCode(int k) const char *getLegacyKeyNameFromInputCode(unsigned k)
{ {
if(inputCodeMap.empty())
initInputCodeMap();
return keyNames[k]; return keyNames[k];
} }
struct KeyNameInitializer
{
KeyNameInitializer() { initInputCodeMap(); }
};
static KeyNameInitializer s_kinit;

View file

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

View file

@ -241,4 +241,17 @@
#endif // BBGE_BUILD_SDL2 #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 #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"); debugLog("Failed to init haptic subsystem");
# endif # endif
sdl_joy = NULL; sdl_joy = NULL;
buttonBitmask = 0;
deadZone1 = 0.3f;
deadZone2 = 0.3f;
clearRumbleTime= 0; clearRumbleTime= 0;
numJoyAxes = 0;
numHats = 0;
numButtons = 0;
clearAxes();
s1ax = 0;
s1ay = 1;
s2ax = 4;
s2ay = 3;
enabled = false; enabled = false;
} }
@ -80,7 +66,6 @@ const char *Joystick::getGUID() const
bool Joystick::init(int stick) bool Joystick::init(int stick)
{ {
stickIndex = stick; stickIndex = stick;
numJoyAxes = 0;
#ifdef BBGE_BUILD_SDL2 #ifdef BBGE_BUILD_SDL2
if (SDL_IsGameController(stick)) if (SDL_IsGameController(stick))
@ -119,10 +104,7 @@ bool Joystick::init(int stick)
guid = &guidbuf[0]; guid = &guidbuf[0];
debugLog(std::string("Initialized Joystick [") + name + "], GUID [" + guid + "]"); debugLog(std::string("Initialized Joystick [") + name + "], GUID [" + guid + "]");
if (sdl_controller) if (sdl_controller)
{
debugLog("Joystick is a Game Controller"); debugLog("Joystick is a Game Controller");
numJoyAxes = SDL_CONTROLLER_AXIS_MAX;
}
if (sdl_haptic) if (sdl_haptic)
debugLog("Joystick has force feedback support"); debugLog("Joystick has force feedback support");
instanceID = SDL_JoystickInstanceID(sdl_joy); instanceID = SDL_JoystickInstanceID(sdl_joy);
@ -133,14 +115,11 @@ bool Joystick::init(int stick)
instanceID = SDL_JoystickIndex(sdl_joy); instanceID = SDL_JoystickIndex(sdl_joy);
#endif #endif
if(!numJoyAxes) std::ostringstream os;
numJoyAxes = SDL_JoystickNumAxes(sdl_joy); os << "Joystick has " << SDL_JoystickNumAxes(sdl_joy) << " axes, "
if(numJoyAxes > MAX_JOYSTICK_AXIS) << SDL_JoystickNumButtons(sdl_joy) << " buttons, "
numJoyAxes = MAX_JOYSTICK_AXIS; << SDL_JoystickNumHats(sdl_joy) << " hats.";
debugLog(os.str());
numHats = SDL_JoystickNumHats(sdl_joy);
numButtons = SDL_JoystickNumButtons(sdl_joy);
return true; return true;
} }
@ -171,14 +150,6 @@ void Joystick::shutdown()
SDL_JoystickClose(sdl_joy); SDL_JoystickClose(sdl_joy);
sdl_joy = 0; sdl_joy = 0;
} }
numJoyAxes = 0;
clearAxes();
}
void Joystick::clearAxes()
{
memset(axisRaw, 0, sizeof(axisRaw));
} }
void Joystick::rumble(float leftMotor, float rightMotor, float time) 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)) if (calvec.isLength2DIn(deadZone))
{ {
@ -244,20 +215,6 @@ void Joystick::update(float dt)
shutdown(); shutdown();
return; 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 #else
if (!SDL_JoystickOpened(stickIndex)) if (!SDL_JoystickOpened(stickIndex))
{ {
@ -266,38 +223,6 @@ void Joystick::update(float dt)
return; return;
} }
#endif #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) 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 const char *Joystick::getAxisName(unsigned axis) const
{ {
if(axis >= numJoyAxes)
return NULL;
#ifdef BBGE_BUILD_SDL2 #ifdef BBGE_BUILD_SDL2
if(sdl_controller) if(sdl_controller)
return SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)axis); return SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)axis);

View file

@ -11,20 +11,6 @@
#include "Vector.h" #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; const static float JOY_AXIS_THRESHOLD = 0.6f;
class Joystick class Joystick
@ -40,19 +26,8 @@ public:
//Ranges from 0 to 1 (full speed). //Ranges from 0 to 1 (full speed).
void rumble(float leftMotor, float rightMotor, float time); void rumble(float leftMotor, float rightMotor, float time);
void update(float dt); void update(float dt);
Vector position;
float deadZone1, deadZone2; static void Calibrate(Vector &vec, float dead);
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;
int getIndex() const { return stickIndex; } int getIndex() const { return stickIndex; }
int getInstanceID() const { return instanceID; } int getInstanceID() const { return instanceID; }
inline bool isEnabled() const { return enabled; } inline bool isEnabled() const { return enabled; }
@ -63,19 +38,12 @@ public:
const char *getName() const; const char *getName() const;
const char *getGUID() const; const char *getGUID() const;
Vector rightStick;
int s1ax, s1ay, s2ax, s2ay;
private: private:
void clearAxes(); float clearRumbleTime;
bool enabled; bool enabled;
int stickIndex; int stickIndex;
int instanceID; int instanceID;
unsigned buttonBitmask;
unsigned numJoyAxes, numHats, numButtons;
SDL_Joystick *sdl_joy; SDL_Joystick *sdl_joy;
float axisRaw[MAX_JOYSTICK_AXIS];
std::string name; std::string name;
std::string guid; std::string guid;

View file

@ -65,7 +65,7 @@ public:
void removeRenderObject(RenderObject *renderObject); void removeRenderObject(RenderObject *renderObject);
std::string name; 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: protected:
void registerState(StateObject *sb, const std::string &name); void registerState(StateObject *sb, const std::string &name);

View file

@ -4,17 +4,6 @@
#include <string> #include <string>
#include <map> #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 class StringBank
{ {
public: public:

View file

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

View file

@ -333,14 +333,6 @@
RelativePath="..\..\BBGE\ActionSet.h" RelativePath="..\..\BBGE\ActionSet.h"
> >
</File> </File>
<File
RelativePath="..\..\BBGE\ActionStatus.cpp"
>
</File>
<File
RelativePath="..\..\BBGE\ActionStatus.h"
>
</File>
<File <File
RelativePath="..\..\BBGE\AfterEffect.cpp" RelativePath="..\..\BBGE\AfterEffect.cpp"
> >
@ -461,6 +453,34 @@
RelativePath="..\..\BBGE\Gradient.h" RelativePath="..\..\BBGE\Gradient.h"
> >
</File> </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 <File
RelativePath="..\..\BBGE\Joystick.cpp" RelativePath="..\..\BBGE\Joystick.cpp"
> >