improve controller remapping

stop input repeats during remapping
This commit is contained in:
Thomas Jentzsch 2019-08-10 13:56:32 +02:00
parent 2c07c2918a
commit ce10108660
7 changed files with 47 additions and 17 deletions

View File

@ -165,6 +165,8 @@ class Dialog : public GuiObject
void setSize(uInt32 w, uInt32 h, uInt32 max_w, uInt32 max_h); void setSize(uInt32 w, uInt32 h, uInt32 max_w, uInt32 max_h);
void positionAt(uInt32 pos); void positionAt(uInt32 pos);
virtual bool repeatEnabled() { return true; }
private: private:
void buildCurrentFocusList(int tabID = -1); void buildCurrentFocusList(int tabID = -1);
bool handleNavEvent(Event::Type e); bool handleNavEvent(Event::Type e);

View File

@ -280,11 +280,11 @@ void DialogContainer::handleJoyBtnEvent(int stick, int button, bool pressed)
// Send the event to the dialog box on the top of the stack // Send the event to the dialog box on the top of the stack
Dialog* activeDialog = myDialogStack.top(); Dialog* activeDialog = myDialogStack.top();
if(pressed) if(pressed && myButtonRepeatTime < myTime) // prevent pending repeats after enabling repeat again
{ {
myCurrentButtonDown.stick = stick; myCurrentButtonDown.stick = stick;
myCurrentButtonDown.button = button; myCurrentButtonDown.button = button;
myButtonRepeatTime = myTime + kRepeatInitialDelay; myButtonRepeatTime = myTime + (activeDialog->repeatEnabled() ? kRepeatInitialDelay : kRepeatNone);
activeDialog->handleJoyDown(stick, button); activeDialog->handleJoyDown(stick, button);
} }
@ -292,8 +292,10 @@ void DialogContainer::handleJoyBtnEvent(int stick, int button, bool pressed)
{ {
// Only stop firing events if it's the current button // Only stop firing events if it's the current button
if(stick == myCurrentButtonDown.stick) if(stick == myCurrentButtonDown.stick)
{
myCurrentButtonDown.stick = myCurrentButtonDown.button = -1; myCurrentButtonDown.stick = myCurrentButtonDown.button = -1;
myButtonRepeatTime = 0;
}
activeDialog->handleJoyUp(stick, button); activeDialog->handleJoyUp(stick, button);
} }
} }
@ -304,22 +306,26 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value, int but
if(myDialogStack.empty()) if(myDialogStack.empty())
return; return;
// Send the event to the dialog box on the top of the stack
Dialog* activeDialog = myDialogStack.top();
// Only stop firing events if it's the current stick // Only stop firing events if it's the current stick
if(myCurrentAxisDown.stick == stick && value == 0) if(myCurrentAxisDown.stick == stick && value == 0)
{ {
cerr << "handleJoyAxisEvent 0" << endl; cerr << "handleJoyAxisEvent 0" << endl;
myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1; myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
myAxisRepeatTime = 0;
} }
else if(value != 0) // never repeat the 'off' event else if(value != 0 && myAxisRepeatTime < myTime) // never repeat the 'off' event; prevent pending repeats after enabling repeat again
{ {
cerr << "handleJoyAxisEvent repeat" << endl; cerr << "handleJoyAxisEvent repeat" << endl;
// Now account for repeated axis events (press and hold) // Now account for repeated axis events (press and hold)
myCurrentAxisDown.stick = stick; myCurrentAxisDown.stick = stick;
myCurrentAxisDown.axis = axis; myCurrentAxisDown.axis = axis;
myCurrentAxisDown.value = value; myCurrentAxisDown.value = value;
myAxisRepeatTime = myTime + kRepeatInitialDelay; myAxisRepeatTime = myTime + (activeDialog->repeatEnabled() ? kRepeatInitialDelay : kRepeatNone);
} }
myDialogStack.top()->handleJoyAxis(stick, axis, value, button); activeDialog->handleJoyAxis(stick, axis, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -328,20 +334,25 @@ void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHat value, int bu
if(myDialogStack.empty()) if(myDialogStack.empty())
return; return;
// Send the event to the dialog box on the top of the stack
Dialog* activeDialog = myDialogStack.top();
// Only stop firing events if it's the current stick // Only stop firing events if it's the current stick
if(myCurrentHatDown.stick == stick && value == JoyHat::CENTER) if(myCurrentHatDown.stick == stick && value == JoyHat::CENTER)
{ {
myCurrentHatDown.stick = myCurrentHatDown.hat = -1; myCurrentHatDown.stick = myCurrentHatDown.hat = -1;
myHatRepeatTime = 0;
} }
else if(value != JoyHat::CENTER) // never repeat the 'center' direction else if(value != JoyHat::CENTER && myHatRepeatTime < myTime) // never repeat the 'center' direction; prevent pending repeats after enabling repeat again
{ {
// Now account for repeated hat events (press and hold) // Now account for repeated hat events (press and hold)
myCurrentHatDown.stick = stick; myCurrentHatDown.stick = stick;
myCurrentHatDown.hat = hat; myCurrentHatDown.hat = hat;
myCurrentHatDown.value = value; myCurrentHatDown.value = value;
myHatRepeatTime = myTime + kRepeatInitialDelay; myHatRepeatTime = myTime + (activeDialog->repeatEnabled() ? kRepeatInitialDelay : kRepeatNone);
//myHatRepeatTime = myTime + kRepeatInitialDelay;
} }
myDialogStack.top()->handleJoyHat(stick, hat, value, button); activeDialog->handleJoyHat(stick, hat, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -176,7 +176,8 @@ class DialogContainer
enum { enum {
kDoubleClickDelay = 500, kDoubleClickDelay = 500,
kRepeatInitialDelay = 400, kRepeatInitialDelay = 400,
kRepeatSustainDelay = 50 kRepeatSustainDelay = 50,
kRepeatNone = 1 << 24 // loooong
}; };
// Indicates the most current time (in milliseconds) as set by updateTime() // Indicates the most current time (in milliseconds) as set by updateTime()

View File

@ -270,7 +270,6 @@ bool EventMappingWidget::handleKeyDown(StellaKey key, StellaMod mod)
myLastKey = key; myLastKey = key;
} }
myMod |= mod; myMod |= mod;
cerr << myMod << ", " << myLastKey << " | " << mod << ", " << key << endl;
} }
return true; return true;
} }
@ -329,9 +328,15 @@ void EventMappingWidget::handleJoyUp(int stick, int button)
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode); Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
cerr << "remap button stop" << endl; cerr << "remap button stop" << endl;
// This maps solo button presses only // map either button/hat, solo button or button/axis combinations
if (eh.addJoyMapping(event, myEventMode, stick, button)) if(myLastHat != -1)
stopRemapping(); {
if(eh.addJoyHatMapping(event, myEventMode, stick, button, myLastHat, JoyHat(myLastValue)))
stopRemapping();
}
else
if (eh.addJoyMapping(event, myEventMode, stick, button, JoyAxis(myLastAxis), myLastValue))
stopRemapping();
} }
} }
} }
@ -349,7 +354,7 @@ void EventMappingWidget::handleJoyAxis(int stick, int axis, int value, int butto
// Detect the first axis event that represents 'on' // Detect the first axis event that represents 'on'
if((myLastStick == -1 || myLastStick == stick) && myLastAxis == -1 && value != 0) if((myLastStick == -1 || myLastStick == stick) && myLastAxis == -1 && value != 0)
{ {
cerr << "remap start" << endl; cerr << "remap axis start" << endl;
myLastStick = stick; myLastStick = stick;
myLastAxis = axis; myLastAxis = axis;
myLastValue = value; myLastValue = value;
@ -361,7 +366,7 @@ void EventMappingWidget::handleJoyAxis(int stick, int axis, int value, int butto
EventHandler& eh = instance().eventHandler(); EventHandler& eh = instance().eventHandler();
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode); Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
cerr << "remap stop" << endl; cerr << "remap axis stop" << endl;
if (eh.addJoyMapping(event, myEventMode, stick, myLastButton, JoyAxis(axis), myLastValue)) if (eh.addJoyMapping(event, myEventMode, stick, myLastButton, JoyAxis(axis), myLastValue))
stopRemapping(); stopRemapping();
} }

View File

@ -33,7 +33,6 @@ class InputDialog;
#include "Command.hxx" #include "Command.hxx"
#include "bspf.hxx" #include "bspf.hxx"
class EventMappingWidget : public Widget, public CommandSender class EventMappingWidget : public Widget, public CommandSender
{ {
friend class InputDialog; friend class InputDialog;
@ -74,6 +73,8 @@ class EventMappingWidget : public Widget, public CommandSender
void resetRemapping(); void resetRemapping();
void stopRemapping(); void stopRemapping();
bool isRemapping() { return myRemapStatus; }
void drawKeyMapping(); void drawKeyMapping();
void enableButtons(bool state); void enableButtons(bool state);

View File

@ -444,6 +444,12 @@ void InputDialog::setDefaults()
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool InputDialog::repeatEnabled()
{
return !myEmulEventMapper->isRemapping() && !myMenuEventMapper->isRemapping();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::handleKeyDown(StellaKey key, StellaMod mod) void InputDialog::handleKeyDown(StellaKey key, StellaMod mod)
{ {

View File

@ -42,6 +42,10 @@ class InputDialog : public Dialog
const GUI::Font& font, int max_w, int max_h); const GUI::Font& font, int max_w, int max_h);
virtual ~InputDialog(); virtual ~InputDialog();
protected:
// disable repeat during and directly after mapping events
bool repeatEnabled() override;
private: private:
void handleKeyDown(StellaKey key, StellaMod mod) override; void handleKeyDown(StellaKey key, StellaMod mod) override;
void handleKeyUp(StellaKey key, StellaMod mod) override; void handleKeyUp(StellaKey key, StellaMod mod) override;