aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Brown <themagnificentmrb@gmail.com>2018-02-07 12:55:19 -0800
committerGarrett Brown <themagnificentmrb@gmail.com>2018-02-07 18:10:15 -0800
commite3d779530102e11a39d2f69d36db338242ebe40d (patch)
treed9b69553a8a3e77da7110eb10696cbe8d5f96c85
parent589e5505480fec62ee774126edb9d18d6bf0ada0 (diff)
Mouse: Implement rotation and reflection of pointer motion
-rw-r--r--xbmc/input/InputTranslator.h6
-rw-r--r--xbmc/input/joysticks/generic/ButtonMapping.cpp14
-rw-r--r--xbmc/input/joysticks/generic/ButtonMapping.h3
-rw-r--r--xbmc/input/mouse/generic/MouseInputHandling.cpp271
-rw-r--r--xbmc/input/mouse/generic/MouseInputHandling.h14
-rw-r--r--xbmc/input/mouse/interfaces/IMouseDriverHandler.h3
-rw-r--r--xbmc/input/mouse/interfaces/IMouseInputHandler.h3
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;