diff options
author | Garrett Brown <themagnificentmrb@gmail.com> | 2018-02-07 12:55:19 -0800 |
---|---|---|
committer | Garrett Brown <themagnificentmrb@gmail.com> | 2018-02-07 18:10:15 -0800 |
commit | e3d779530102e11a39d2f69d36db338242ebe40d (patch) | |
tree | d9b69553a8a3e77da7110eb10696cbe8d5f96c85 | |
parent | 589e5505480fec62ee774126edb9d18d6bf0ada0 (diff) |
Mouse: Implement rotation and reflection of pointer motion
-rw-r--r-- | xbmc/input/InputTranslator.h | 6 | ||||
-rw-r--r-- | xbmc/input/joysticks/generic/ButtonMapping.cpp | 14 | ||||
-rw-r--r-- | xbmc/input/joysticks/generic/ButtonMapping.h | 3 | ||||
-rw-r--r-- | xbmc/input/mouse/generic/MouseInputHandling.cpp | 271 | ||||
-rw-r--r-- | xbmc/input/mouse/generic/MouseInputHandling.h | 14 | ||||
-rw-r--r-- | xbmc/input/mouse/interfaces/IMouseDriverHandler.h | 3 | ||||
-rw-r--r-- | xbmc/input/mouse/interfaces/IMouseInputHandler.h | 3 |
7 files changed, 302 insertions, 12 deletions
diff --git a/xbmc/input/InputTranslator.h b/xbmc/input/InputTranslator.h index b9e0b3c275..d3e02a984a 100644 --- a/xbmc/input/InputTranslator.h +++ b/xbmc/input/InputTranslator.h @@ -31,6 +31,9 @@ namespace INPUT /*! * \brief Get the closest cardinal direction to the given vector * + * This function assumes a right-handed cartesian coordinate system; postive + * X is right, positive Y is up. + * * Ties are resolved in the clockwise direction: (0.5, 0.5) will resolve to * RIGHT. * @@ -46,6 +49,9 @@ namespace INPUT * \brief Get the closest cardinal or intercardinal direction to the given * vector * + * This function assumes a right-handed cartesian coordinate system; postive + * X is right, positive Y is up. + * * Ties are resolved in the clockwise direction. * * \param x The x component of the vector diff --git a/xbmc/input/joysticks/generic/ButtonMapping.cpp b/xbmc/input/joysticks/generic/ButtonMapping.cpp index 2540e0ba2c..3f5af89d60 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.cpp +++ b/xbmc/input/joysticks/generic/ButtonMapping.cpp @@ -287,8 +287,6 @@ CPointerDetector::CPointerDetector(CButtonMapping* buttonMapping) : bool CPointerDetector::OnMotion(int x, int y) { - using namespace INPUT; - if (!m_bStarted) { m_bStarted = true; @@ -302,7 +300,7 @@ bool CPointerDetector::OnMotion(int x, int y) int dx = x - m_startX; int dy = y - m_startY; - INTERCARDINAL_DIRECTION dir = CInputTranslator::VectorToIntercardinalDirection(static_cast<float>(dx), static_cast<float>(dy)); + INPUT::INTERCARDINAL_DIRECTION dir = GetPointerDirection(dx, dy); CDriverPrimitive primitive(static_cast<RELATIVE_POINTER_DIRECTION>(dir)); if (primitive.IsValid()) @@ -315,6 +313,16 @@ bool CPointerDetector::OnMotion(int x, int y) return true; } +KODI::INPUT::INTERCARDINAL_DIRECTION CPointerDetector::GetPointerDirection(int x, int y) +{ + using namespace INPUT; + + // Translate from left-handed coordinate system to right-handed coordinate system + y *= -1; + + return CInputTranslator::VectorToIntercardinalDirection(static_cast<float>(x), static_cast<float>(y)); +} + // --- CButtonMapping ---------------------------------------------------------- CButtonMapping::CButtonMapping(IButtonMapper* buttonMapper, IButtonMap* buttonMap, IKeymap* keymap) : diff --git a/xbmc/input/joysticks/generic/ButtonMapping.h b/xbmc/input/joysticks/generic/ButtonMapping.h index 7ce0c6419a..e0eebd00dc 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.h +++ b/xbmc/input/joysticks/generic/ButtonMapping.h @@ -293,6 +293,9 @@ namespace JOYSTICK bool OnMotion(int x, int y); private: + // Utility function + static INPUT::INTERCARDINAL_DIRECTION GetPointerDirection(int x, int y); + static const unsigned int MIN_FRAME_COUNT = 10; // State variables diff --git a/xbmc/input/mouse/generic/MouseInputHandling.cpp b/xbmc/input/mouse/generic/MouseInputHandling.cpp index 66e81fea4f..f78307c617 100644 --- a/xbmc/input/mouse/generic/MouseInputHandling.cpp +++ b/xbmc/input/mouse/generic/MouseInputHandling.cpp @@ -28,9 +28,7 @@ using namespace MOUSE; CMouseInputHandling::CMouseInputHandling(IMouseInputHandler* handler, JOYSTICK::IButtonMap* buttonMap) : m_handler(handler), - m_buttonMap(buttonMap), - m_x(0), - m_y(0) + m_buttonMap(buttonMap) { } @@ -38,21 +36,69 @@ bool CMouseInputHandling::OnPosition(int x, int y) { using namespace JOYSTICK; + if (!m_bHasPosition) + { + m_bHasPosition = true; + m_x = x; + m_y = y; + return true; + } + int dx = x - m_x; int dy = y - m_y; bool bHandled = false; - //! @todo Handle axis mapping - + // Get direction of motion POINTER_DIRECTION dir = GetPointerDirection(dx, dy); CDriverPrimitive source(dir); if (source.IsValid()) { + // Get pointer in direction of motion PointerName pointerName; if (m_buttonMap->GetFeature(source, pointerName)) + { + // Get orthogonal direction of motion + POINTER_DIRECTION dirCCW = GetOrthogonalDirectionCCW(dir); + + // Get mapped directions of motion for rotation and reflection + CDriverPrimitive target; + CDriverPrimitive targetCCW; + + if (m_buttonMap->GetRelativePointer(pointerName, dir, target)) + m_buttonMap->GetRelativePointer(pointerName, dirCCW, targetCCW); + + if (target.IsValid()) + { + // Invert y to right-handed cartesian system + dy *= -1; + + // Perform rotation + int rotation[2][2] = { {1, 0}, {0, 1} }; + + GetRotation(dir, target.PointerDirection(), rotation); + + dx = rotation[0][0] * dx + rotation[0][1] * dy; + dy = rotation[1][0] * dx + rotation[1][1] * dy; + + if (targetCCW.IsValid()) + { + // Perform reflection + int reflection[2][2] = { {1, 0}, {0, 1} }; + + GetReflectionCCW(target.PointerDirection(), targetCCW.PointerDirection(), reflection); + + dx = reflection[0][0] * dx + reflection[0][1] * dy; + dy = reflection[1][0] * dx + reflection[1][1] * dy; + } + + // Invert y back to left-handed coordinate system + dy *= -1; + } + bHandled = m_handler->OnMotion(pointerName, dx, dy); + } } m_x = x; @@ -87,5 +133,218 @@ POINTER_DIRECTION CMouseInputHandling::GetPointerDirection(int x, int y) { using namespace INPUT; - return CInputTranslator::VectorToCardinalDirection(static_cast<float>(x), static_cast<float>(y)); + return CInputTranslator::VectorToCardinalDirection(static_cast<float>(x), static_cast<float>(-y)); +} + +POINTER_DIRECTION CMouseInputHandling::GetOrthogonalDirectionCCW(POINTER_DIRECTION direction) +{ + switch (direction) + { + case POINTER_DIRECTION::RIGHT: return POINTER_DIRECTION::UP; + case POINTER_DIRECTION::UP: return POINTER_DIRECTION::LEFT; + case POINTER_DIRECTION::LEFT: return POINTER_DIRECTION::DOWN; + case POINTER_DIRECTION::DOWN: return POINTER_DIRECTION::RIGHT; + default: + break; + } + + return POINTER_DIRECTION::NONE; +} + +void CMouseInputHandling::GetRotation(POINTER_DIRECTION source, POINTER_DIRECTION target, int (&rotation)[2][2]) +{ + switch (source) + { + case POINTER_DIRECTION::RIGHT: + { + switch (target) + { + case POINTER_DIRECTION::UP: + GetRotation(90, rotation); + break; + case POINTER_DIRECTION::LEFT: + GetRotation(180, rotation); + break; + case POINTER_DIRECTION::DOWN: + GetRotation(270, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::UP: + { + switch (target) + { + case POINTER_DIRECTION::LEFT: + GetRotation(90, rotation); + break; + case POINTER_DIRECTION::DOWN: + GetRotation(180, rotation); + break; + case POINTER_DIRECTION::RIGHT: + GetRotation(270, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::LEFT: + { + switch (target) + { + case POINTER_DIRECTION::DOWN: + GetRotation(90, rotation); + break; + case POINTER_DIRECTION::RIGHT: + GetRotation(180, rotation); + break; + case POINTER_DIRECTION::UP: + GetRotation(270, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::DOWN: + { + switch (target) + { + case POINTER_DIRECTION::RIGHT: + GetRotation(90, rotation); + break; + case POINTER_DIRECTION::UP: + GetRotation(180, rotation); + break; + case POINTER_DIRECTION::LEFT: + GetRotation(270, rotation); + break; + default: + break; + } + break; + } + default: + break; + } +} + +void CMouseInputHandling::GetRotation(int deg, int (&rotation)[2][2]) +{ + switch (deg) + { + case 90: + { + rotation[0][0] = 0; + rotation[0][1] = -1; + rotation[1][0] = 1; + rotation[1][1] = 0; + break; + } + case 180: + { + rotation[0][0] = -1; + rotation[0][1] = 0; + rotation[1][0] = 0; + rotation[1][1] = -1; + break; + } + case 270: + { + rotation[0][0] = 0; + rotation[0][1] = 1; + rotation[1][0] = -1; + rotation[1][1] = 0; + break; + } + default: + break; + } +} + +void CMouseInputHandling::GetReflectionCCW(POINTER_DIRECTION source, POINTER_DIRECTION target, int (&rotation)[2][2]) +{ + switch (source) + { + case POINTER_DIRECTION::RIGHT: + { + switch (target) + { + case POINTER_DIRECTION::DOWN: + GetReflection(0, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::UP: + { + switch (target) + { + case POINTER_DIRECTION::RIGHT: + GetReflection(90, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::LEFT: + { + switch (target) + { + case POINTER_DIRECTION::UP: + GetReflection(180, rotation); + break; + default: + break; + } + break; + } + case POINTER_DIRECTION::DOWN: + { + switch (target) + { + case POINTER_DIRECTION::LEFT: + GetReflection(270, rotation); + break; + default: + break; + } + break; + } + default: + break; + } +} + +void CMouseInputHandling::GetReflection(int deg, int (&reflection)[2][2]) +{ + switch (deg) + { + case 0: + case 180: + { + reflection[0][0] = 1; + reflection[0][1] = 0; + reflection[1][0] = 0; + reflection[1][1] = -1; + break; + } + case 90: + case 270: + { + reflection[0][0] = -1; + reflection[0][1] = 0; + reflection[1][0] = 0; + reflection[1][1] = 1; + break; + } + default: + break; + } } diff --git a/xbmc/input/mouse/generic/MouseInputHandling.h b/xbmc/input/mouse/generic/MouseInputHandling.h index e0c708715c..6d84261641 100644 --- a/xbmc/input/mouse/generic/MouseInputHandling.h +++ b/xbmc/input/mouse/generic/MouseInputHandling.h @@ -50,16 +50,24 @@ namespace MOUSE void OnButtonRelease(BUTTON_ID button) override; private: - // Utility function + // Utility functions static POINTER_DIRECTION GetPointerDirection(int x, int y); + static POINTER_DIRECTION GetOrthogonalDirectionCCW(POINTER_DIRECTION direction); + + static void GetRotation(POINTER_DIRECTION source, POINTER_DIRECTION target, int (&rotation)[2][2]); + static void GetRotation(int deg, int (&rotation)[2][2]); + + static void GetReflectionCCW(POINTER_DIRECTION source, POINTER_DIRECTION target, int (&reflection)[2][2]); + static void GetReflection(int deg, int (&reflection)[2][2]); // Construction parameters IMouseInputHandler* const m_handler; JOYSTICK::IButtonMap* const m_buttonMap; // Mouse parameters - int m_x; - int m_y; + bool m_bHasPosition = false; + int m_x = 0; + int m_y = 0; }; } } diff --git a/xbmc/input/mouse/interfaces/IMouseDriverHandler.h b/xbmc/input/mouse/interfaces/IMouseDriverHandler.h index 72ddd0eb11..2ca0c103cc 100644 --- a/xbmc/input/mouse/interfaces/IMouseDriverHandler.h +++ b/xbmc/input/mouse/interfaces/IMouseDriverHandler.h @@ -40,6 +40,9 @@ namespace MOUSE * \param x The new x coordinate of the pointer * \param y The new y coordinate of the pointer * + * The mouse uses a left-handed (graphics) cartesian coordinate system. + * Positive X is right, positive Y is down. + * * \return True if the event was handled, false otherwise */ virtual bool OnPosition(int x, int y) = 0; diff --git a/xbmc/input/mouse/interfaces/IMouseInputHandler.h b/xbmc/input/mouse/interfaces/IMouseInputHandler.h index 925591e08c..82c820f83a 100644 --- a/xbmc/input/mouse/interfaces/IMouseInputHandler.h +++ b/xbmc/input/mouse/interfaces/IMouseInputHandler.h @@ -50,6 +50,9 @@ namespace MOUSE * \param dx The relative x coordinate of motion * \param dy The relative y coordinate of motion * + * The mouse uses a left-handed (graphics) cartesian coordinate system. + * Positive X is right, positive Y is down. + * * \return True if the event was handled, otherwise false */ virtual bool OnMotion(const PointerName& relpointer, int dx, int dy) = 0; |