summaryrefslogtreecommitdiffstats
path: root/xbmc/input/joysticks/generic/InputHandling.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/input/joysticks/generic/InputHandling.cpp')
-rw-r--r--xbmc/input/joysticks/generic/InputHandling.cpp179
1 files changed, 179 insertions, 0 deletions
diff --git a/xbmc/input/joysticks/generic/InputHandling.cpp b/xbmc/input/joysticks/generic/InputHandling.cpp
new file mode 100644
index 0000000..f6cae6d
--- /dev/null
+++ b/xbmc/input/joysticks/generic/InputHandling.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2014-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "InputHandling.h"
+
+#include "input/joysticks/DriverPrimitive.h"
+#include "input/joysticks/JoystickUtils.h"
+#include "input/joysticks/dialogs/GUIDialogNewJoystick.h"
+#include "input/joysticks/interfaces/IButtonMap.h"
+#include "input/joysticks/interfaces/IInputHandler.h"
+#include "utils/log.h"
+
+#include <array>
+#include <cmath>
+#include <tuple>
+
+using namespace KODI;
+using namespace JOYSTICK;
+
+CGUIDialogNewJoystick* const CInputHandling::m_dialog = new CGUIDialogNewJoystick;
+
+CInputHandling::CInputHandling(IInputHandler* handler, IButtonMap* buttonMap)
+ : m_handler(handler), m_buttonMap(buttonMap)
+{
+}
+
+CInputHandling::~CInputHandling(void) = default;
+
+bool CInputHandling::OnButtonMotion(unsigned int buttonIndex, bool bPressed)
+{
+ return OnDigitalMotion(CDriverPrimitive(PRIMITIVE_TYPE::BUTTON, buttonIndex), bPressed);
+}
+
+bool CInputHandling::OnHatMotion(unsigned int hatIndex, HAT_STATE state)
+{
+ bool bHandled = false;
+
+ bHandled |=
+ OnDigitalMotion(CDriverPrimitive(hatIndex, HAT_DIRECTION::UP), state & HAT_DIRECTION::UP);
+ bHandled |= OnDigitalMotion(CDriverPrimitive(hatIndex, HAT_DIRECTION::RIGHT),
+ state & HAT_DIRECTION::RIGHT);
+ bHandled |=
+ OnDigitalMotion(CDriverPrimitive(hatIndex, HAT_DIRECTION::DOWN), state & HAT_DIRECTION::DOWN);
+ bHandled |=
+ OnDigitalMotion(CDriverPrimitive(hatIndex, HAT_DIRECTION::LEFT), state & HAT_DIRECTION::LEFT);
+
+ return bHandled;
+}
+
+bool CInputHandling::OnAxisMotion(unsigned int axisIndex,
+ float position,
+ int center,
+ unsigned int range)
+{
+ bool bHandled = false;
+
+ if (center != 0)
+ {
+ float translatedPostion = std::min((position - center) / range, 1.0f);
+
+ // Calculate the direction the trigger travels from the center point
+ SEMIAXIS_DIRECTION dir;
+ if (center > 0)
+ dir = SEMIAXIS_DIRECTION::NEGATIVE;
+ else
+ dir = SEMIAXIS_DIRECTION::POSITIVE;
+
+ CDriverPrimitive offsetSemiaxis(axisIndex, center, dir, range);
+
+ bHandled = OnAnalogMotion(offsetSemiaxis, translatedPostion);
+ }
+ else
+ {
+ CDriverPrimitive positiveSemiaxis(axisIndex, 0, SEMIAXIS_DIRECTION::POSITIVE, 1);
+ CDriverPrimitive negativeSemiaxis(axisIndex, 0, SEMIAXIS_DIRECTION::NEGATIVE, 1);
+
+ bHandled |= OnAnalogMotion(positiveSemiaxis, position > 0.0f ? position : 0.0f);
+ bHandled |= OnAnalogMotion(negativeSemiaxis, position < 0.0f ? -position : 0.0f);
+ }
+
+ return bHandled;
+}
+
+void CInputHandling::OnInputFrame(void)
+{
+ // Handle driver input
+ for (auto& it : m_features)
+ it.second->ProcessMotions();
+
+ // Handle higher-level controller input
+ m_handler->OnInputFrame();
+}
+
+bool CInputHandling::OnDigitalMotion(const CDriverPrimitive& source, bool bPressed)
+{
+ bool bHandled = false;
+
+ FeatureName featureName;
+ if (m_buttonMap->GetFeature(source, featureName))
+ {
+ auto it = m_features.find(featureName);
+ if (it == m_features.end())
+ {
+ FeaturePtr feature(CreateFeature(featureName));
+ if (feature)
+ std::tie(it, std::ignore) = m_features.insert({featureName, std::move(feature)});
+ }
+
+ if (it != m_features.end())
+ bHandled = it->second->OnDigitalMotion(source, bPressed);
+ }
+ else if (bPressed)
+ {
+ // If button didn't resolve to a feature, check if the button map is empty
+ // and ask the user if they would like to start mapping the controller
+ if (m_buttonMap->IsEmpty())
+ {
+ CLog::Log(LOGDEBUG, "Empty button map detected for {}", m_buttonMap->ControllerID());
+ m_dialog->ShowAsync();
+ }
+ }
+
+ return bHandled;
+}
+
+bool CInputHandling::OnAnalogMotion(const CDriverPrimitive& source, float magnitude)
+{
+ bool bHandled = false;
+
+ FeatureName featureName;
+ if (m_buttonMap->GetFeature(source, featureName))
+ {
+ auto it = m_features.find(featureName);
+ if (it == m_features.end())
+ {
+ FeaturePtr feature(CreateFeature(featureName));
+ if (feature)
+ std::tie(it, std::ignore) = m_features.insert({featureName, std::move(feature)});
+ }
+
+ if (it != m_features.end())
+ bHandled = it->second->OnAnalogMotion(source, magnitude);
+ }
+
+ return bHandled;
+}
+
+CJoystickFeature* CInputHandling::CreateFeature(const FeatureName& featureName)
+{
+ CJoystickFeature* feature = nullptr;
+
+ switch (m_buttonMap->GetFeatureType(featureName))
+ {
+ case FEATURE_TYPE::SCALAR:
+ {
+ feature = new CScalarFeature(featureName, m_handler, m_buttonMap);
+ break;
+ }
+ case FEATURE_TYPE::ANALOG_STICK:
+ {
+ feature = new CAnalogStick(featureName, m_handler, m_buttonMap);
+ break;
+ }
+ case FEATURE_TYPE::ACCELEROMETER:
+ {
+ feature = new CAccelerometer(featureName, m_handler, m_buttonMap);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return feature;
+}