diff --git a/Core/KeyMap.h b/Core/KeyMap.h index f8f9aa2f57..b88c0e675e 100644 --- a/Core/KeyMap.h +++ b/Core/KeyMap.h @@ -76,6 +76,7 @@ enum { }; const float AXIS_BIND_THRESHOLD = 0.75f; +const float AXIS_BIND_RELEASE_THRESHOLD = 0.35f; // Used during mapping only to detect a "key-up" reliably. const float AXIS_BIND_THRESHOLD_MOUSE = 0.01f; struct MappedAnalogAxis { diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 2113cc8079..b6d4424172 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -111,7 +111,7 @@ void SingleControlMapper::Refresh() { float itemH = 55.0f; float leftColumnWidth = 200; - float rightColumnWidth = 250; // TODO: Should be flexible somehow. Maybe we need to implement Measure. + float rightColumnWidth = 350; // TODO: Should be flexible somehow. Maybe we need to implement Measure. LinearLayout *root = Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); root->SetSpacing(3.0f); @@ -330,26 +330,39 @@ void KeyMappingNewKeyDialog::CreatePopupContents(UI::ViewGroup *parent) { std::string pspButtonName = KeyMap::GetPspButtonName(this->pspBtn_); - parent->Add(new TextView(std::string(km->T("Map a new key for")) + " " + mc->T(pspButtonName), new LinearLayoutParams(Margins(10,0)))); + parent->Add(new TextView(std::string(km->T("Map a new key for")) + " " + mc->T(pspButtonName), new LinearLayoutParams(Margins(10, 0)))); + parent->Add(new TextView(std::string(mapping_.ToVisualString()), new LinearLayoutParams(Margins(10, 0)))); + SetVRAppMode(VRAppMode::VR_CONTROLLER_MAPPING_MODE); } bool KeyMappingNewKeyDialog::key(const KeyInput &key) { - if (mapped_ || time_now_d() < delayUntil_) - return false; + if (time_now_d() < delayUntil_) + return true; if (key.flags & KEY_DOWN) { if (key.keyCode == NKCODE_EXT_MOUSEBUTTON_1) { + // Don't map return true; } - // Only map analog values to this mapping. - if (pspBtn_ == VIRTKEY_SPEED_ANALOG && !UI::IsEscapeKey(key)) - return true; - mapped_ = true; - MultiInputMapping kdf(InputMapping(key.deviceId, key.keyCode)); + if (pspBtn_ == VIRTKEY_SPEED_ANALOG && !UI::IsEscapeKey(key)) { + // Only map analog values to this mapping. + return true; + } + + InputMapping newMapping(key.deviceId, key.keyCode); + + if (!(key.flags & KEY_IS_REPEAT)) { + if (!mapping_.mappings.contains(newMapping)) { + mapping_.mappings.push_back(newMapping); + RecreateViews(); + } + } + } + if (key.flags & KEY_UP) { + if (callback_) + callback_(mapping_); TriggerFinish(DR_YES); - if (callback_ && pspBtn_ != VIRTKEY_SPEED_ANALOG) - callback_(kdf); } return true; } @@ -389,10 +402,11 @@ bool KeyMappingNewMouseKeyDialog::key(const KeyInput &key) { static bool IgnoreAxisForMapping(int axis) { switch (axis) { - // Ignore the accelerometer for mapping for now. case JOYSTICK_AXIS_ACCELEROMETER_X: case JOYSTICK_AXIS_ACCELEROMETER_Y: case JOYSTICK_AXIS_ACCELEROMETER_Z: + // Ignore the accelerometer for mapping for now. + // We use tilt control for these. return true; default: @@ -400,27 +414,35 @@ static bool IgnoreAxisForMapping(int axis) { } } - void KeyMappingNewKeyDialog::axis(const AxisInput &axis) { - if (mapped_ || time_now_d() < delayUntil_) + if (time_now_d() < delayUntil_) return; if (IgnoreAxisForMapping(axis.axisId)) return; if (axis.value > AXIS_BIND_THRESHOLD) { - mapped_ = true; - MultiInputMapping kdf(InputMapping(axis.deviceId, axis.axisId, 1)); - TriggerFinish(DR_YES); - if (callback_) - callback_(kdf); - } - - if (axis.value < -AXIS_BIND_THRESHOLD) { - mapped_ = true; - MultiInputMapping kdf(InputMapping(axis.deviceId, axis.axisId, -1)); - TriggerFinish(DR_YES); - if (callback_) - callback_(kdf); + InputMapping mapping(axis.deviceId, axis.axisId, 1); + triggeredAxes_.insert(mapping); + if (!mapping_.mappings.contains(mapping)) { + mapping_.mappings.push_back(mapping); + RecreateViews(); + } + } else if (axis.value < -AXIS_BIND_THRESHOLD) { + InputMapping mapping(axis.deviceId, axis.axisId, -1); + triggeredAxes_.insert(mapping); + if (!mapping_.mappings.contains(mapping)) { + mapping_.mappings.push_back(mapping); + RecreateViews(); + } + } else if (fabsf(axis.value) < AXIS_BIND_RELEASE_THRESHOLD) { + InputMapping neg(axis.deviceId, axis.axisId, -1); + InputMapping pos(axis.deviceId, axis.axisId, 1); + if (triggeredAxes_.find(neg) != triggeredAxes_.end() || triggeredAxes_.find(pos) != triggeredAxes_.end()) { + // "Key-up" the axis. + TriggerFinish(DR_YES); + if (callback_) + callback_(mapping_); + } } } diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index d02eef8e88..d988e255db 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -76,7 +77,12 @@ protected: private: int pspBtn_; std::function callback_; - bool mapped_ = false; // Prevent double registrations + + KeyMap::MultiInputMapping mapping_; + + // We need to do our own detection for axis "keyup" here. + std::set triggeredAxes_; + double delayUntil_ = 0.0f; };