diff --git a/lang/english/html/input_config.html b/lang/english/html/input_config.html index d5cce1e5..9c63da99 100644 --- a/lang/english/html/input_config.html +++ b/lang/english/html/input_config.html @@ -162,6 +162,34 @@ div.center-buttons-grid width: min-content; } +div.center-buttons-motion +{ + flow: horizontal; + width: 100%%; + margin-top: 0.4rem; + vertical-align: top; +} + +#horizontalSpacerMotionLeft, +#horizontalSpacerMotionRight +{ + display: inline-block; + width: 100%%; +} + +div.center-buttons-motion .input-row +{ + display: inline-block; + width: min-content; + margin: 0; + vertical-align: top; +} + +div.center-buttons-motion .input-row button +{ + min-width: 4.5rem; +} + button { width: min-content; diff --git a/lang/english/html/input_config_player.html b/lang/english/html/input_config_player.html index ed640558..ccd27329 100644 --- a/lang/english/html/input_config_player.html +++ b/lang/english/html/input_config_player.html @@ -993,9 +993,11 @@ -
-
Motion 1
-
Motion 2
+
+
+
Motion 1
+
Motion 2
+
diff --git a/src/nxemu/user_interface/settings/input_config_player.cpp b/src/nxemu/user_interface/settings/input_config_player.cpp index c532996a..600a2491 100644 --- a/src/nxemu/user_interface/settings/input_config_player.cpp +++ b/src/nxemu/user_interface/settings/input_config_player.cpp @@ -216,7 +216,7 @@ namespace { return m_package->GetBool(key, default_value); } - auto pair = data.find(key); + DataType::const_iterator pair = data.find(key); if (pair == data.end()) { return default_value; @@ -238,7 +238,7 @@ namespace { return m_package->GetInt(key, default_value); } - auto pair = data.find(key); + DataType::const_iterator pair = data.find(key); if (pair == data.end()) { return default_value; @@ -270,7 +270,7 @@ namespace { return m_package->GetString(key, default_value); } - auto pair = data.find(key); + DataType::const_iterator pair = data.find(key); if (pair == data.end()) { return default_value; @@ -304,7 +304,7 @@ namespace std::string result; - for (const auto& pair : data) { + for (const DataType::value_type & pair : data) { std::array key_value{ {pair.first, pair.second} }; for (std::string& part : key_value) { part = Common::ReplaceAll(part, { ESCAPE_CHARACTER }, ESCAPE_CHARACTER_ESCAPE); @@ -492,6 +492,7 @@ InputConfigPlayer::InputConfigPlayer(ISciterUI & sciterUI, InputConfig & config, UpdateControllerAvailableButtons(); UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); + UpdateMotionButtons(); } void InputConfigPlayer::SaveSetting() @@ -522,6 +523,16 @@ bool InputConfigPlayer::OnClick(SCITER_ELEMENT element, SCITER_ELEMENT /*source* continue; } HandleClick(m_buttonMap[i], i, PollingInputType::Button); + return false; + } + for (uint32_t i = 0, n = (uint32_t)NativeMotionValues::NumMotions; i < n; i++) + { + if (!m_motionMap[i].IsValid() || element != m_motionMap[i]) + { + continue; + } + HandleClick(m_motionMap[i], i, PollingInputType::Motion); + return false; } } return false; @@ -552,13 +563,31 @@ bool InputConfigPlayer::OnTimer(SCITER_ELEMENT /*element*/, uint32_t * timerId) { if (timerId == (uint32_t*)TIMER_POLL) { - ParamPackage param(m_operatingSystem.GetNextInput()); - if (param.Has("engine") && IsInputAcceptable(param)) + constexpr int kMaxDrainPerPoll = 64; + int drain = 0; + for (; drain < kMaxDrainPerPoll; ++drain) { + ParamPackage param(m_operatingSystem.GetNextInput()); + if (!param.Has("engine")) + { + break; + } + if (!IsInputAcceptable(param)) + { + continue; + } if (m_pollingType == PollingInputType::Button) { m_emulatedController->SetButtonParam(m_pollingButtonId, param); } + else if (m_pollingType == PollingInputType::Motion) + { + m_emulatedController->SetMotionParam(m_pollingButtonId, param); + } + else + { + continue; + } PollingDone(); return false; } @@ -639,6 +668,9 @@ void InputConfigPlayer::BindControls() m_motionMap[0] = m_page.GetElementByID("buttonMotionLeft"); m_motionMap[1] = m_page.GetElementByID("buttonMotionRight"); + m_motionGroup[0] = m_page.GetElementByID("buttonMotionLeftGroup"); + m_motionGroup[1] = m_page.GetElementByID("buttonMotionRightGroup"); + m_centerButtonsMotion = m_page.GetElementByID("centerButtonsMotion"); m_analogMapButtons[0][0] = m_page.GetElementByID("ButtonLStickUp"); m_analogMapButtons[0][1] = m_page.GetElementByID("ButtonLStickDown"); @@ -687,6 +719,15 @@ void InputConfigPlayer::BindControls() m_sciterUI.AttachHandler(m_buttonMap[i], IID_ICLICKSINK, (IClickSink*)this); } + for (uint32_t i = 0, n = (uint32_t)NativeMotionValues::NumMotions; i < n; i++) + { + if (!m_motionMap[i].IsValid()) + { + continue; + } + m_sciterUI.AttachHandler(m_motionMap[i], IID_ICLICKSINK, (IClickSink*)this); + } + SciterElement comboControllerType = m_page.GetElementByID("comboControllerType"); std::shared_ptr interfacePtr = m_sciterUI.GetElementInterface(comboControllerType, IID_ICOMBOBOX); if (interfacePtr) @@ -1085,7 +1126,7 @@ std::string InputConfigPlayer::AnalogToText(const IParamPackage& param, const st int InputConfigPlayer::GetIndexFromControllerType(NpadStyleIndex type) const { - const auto it = std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), [type](const auto& pair) { return pair.second == type; }); + const std::vector>::const_iterator it = std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), [type](const std::pair& pair) { return pair.second == type; }); if (it == index_controller_type_pairs.end()) { return -1; @@ -1096,7 +1137,7 @@ int InputConfigPlayer::GetIndexFromControllerType(NpadStyleIndex type) const NpadStyleIndex InputConfigPlayer::GetControllerTypeFromIndex(int index) const { - const auto it = std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), [index](const auto& pair) { return pair.first == index; }); + const std::vector>::const_iterator it = std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), [index](const std::pair& pair) { return pair.first == index; }); if (it == index_controller_type_pairs.end()) { return NpadStyleIndex::Fullkey; @@ -1188,6 +1229,7 @@ void InputConfigPlayer::ControllerTypeChanged() UpdateControllerAvailableButtons(); UpdateControllerEnabledButtons(); UpdateControllerButtonNames(); + UpdateMotionButtons(); const NpadStyleIndex type = GetControllerTypeFromIndex(m_comboControllerType->CurrentIndex()); if (m_controllerIndex == NpadIdType::Player1) { @@ -1348,7 +1390,7 @@ void InputConfigPlayer::HandleClick(SciterElement & button, uint32_t buttonId, P void InputConfigPlayer::RefreshStickUi() { - const auto now = std::chrono::steady_clock::now(); + const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); if (m_stickUiThrottleLast != std::chrono::steady_clock::time_point{} && (now - m_stickUiThrottleLast) < std::chrono::milliseconds(50)) { @@ -1748,6 +1790,57 @@ void InputConfigPlayer::UpdateButtonState() m_sciterUI.UpdateWindow(m_page.GetElementHwnd(true)); } +void InputConfigPlayer::UpdateMotionButtons() +{ + if (m_comboControllerType == nullptr) + { + return; + } + + const NpadStyleIndex layout = GetControllerTypeFromIndex(m_comboControllerType->CurrentIndex()); + + bool show_left = false; + bool show_right = false; + bool show_bar = false; + + switch (layout) + { + case NpadStyleIndex::Fullkey: + case NpadStyleIndex::JoyconLeft: + case NpadStyleIndex::Handheld: + show_left = true; + show_bar = true; + break; + case NpadStyleIndex::JoyconRight: + show_right = true; + show_bar = true; + break; + case NpadStyleIndex::GameCube: + break; + case NpadStyleIndex::JoyconDual: + default: + show_left = true; + show_right = true; + show_bar = true; + break; + } + + if (m_motionGroup[0].IsValid()) + { + m_motionGroup[0].SetStyleAttribute("display", show_left ? "" : "none"); + } + if (m_motionGroup[1].IsValid()) + { + m_motionGroup[1].SetStyleAttribute("display", show_right ? "" : "none"); + } + if (m_centerButtonsMotion.IsValid()) + { + m_centerButtonsMotion.SetStyleAttribute("display", show_bar ? "" : "none"); + const char* motion_class = show_bar && show_left != show_right ? "center-buttons-motion single-motion" : "center-buttons-motion"; + m_centerButtonsMotion.SetAttribute("class", motion_class); + } +} + void InputConfigPlayer::UpdateMotionCube() { float size = 15.0f; @@ -1967,6 +2060,7 @@ void InputConfigPlayer::PollingDone() m_pollingType = PollingInputType::None; m_pollingButtonId = 0; UpdateButtonState(); + UpdateUI(); } void InputConfigPlayer::stControllerEventCallback(ControllerTriggerType type, void * user) diff --git a/src/nxemu/user_interface/settings/input_config_player.h b/src/nxemu/user_interface/settings/input_config_player.h index 67e38611..0add6685 100644 --- a/src/nxemu/user_interface/settings/input_config_player.h +++ b/src/nxemu/user_interface/settings/input_config_player.h @@ -62,6 +62,7 @@ private: void UpdateControllerEnabledButtons(); void UpdateControllerButtonNames(); void UpdateButtonState(); + void UpdateMotionButtons(); void UpdateMotionCube(); void UpdateStickDisplay(const SciterElement & svg, NativeAnalogValues analog); void DeadzoneSliderChanged(uint32_t analogId); @@ -84,6 +85,8 @@ private: SciterElement m_connectedController; SciterElement m_buttonMap[22]; SciterElement m_motionMap[2]; + SciterElement m_motionGroup[2]; + SciterElement m_centerButtonsMotion; SciterElement m_analogMapButtons[2][4]; SciterElement m_analogMapModifierButton[2]; SciterElement m_analogMapDeadzoneLabel[2];