From 3b44f51a9b09215cf75845cd5269e8601da34655 Mon Sep 17 00:00:00 2001
From: Aloshi <aloshi@aloshi>
Date: Mon, 23 Jul 2012 21:10:05 -0500
Subject: [PATCH] Fixed hats.

---
 src/InputManager.cpp | 52 ++++++++++++++++++++++++++++++++++++--------
 src/InputManager.h   |  1 +
 src/main.cpp         |  1 +
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/src/InputManager.cpp b/src/InputManager.cpp
index 22fc942e2..5086dd39e 100644
--- a/src/InputManager.cpp
+++ b/src/InputManager.cpp
@@ -9,6 +9,7 @@ SDL_Event* InputManager::lastEvent = NULL;
 
 std::map<int, InputManager::InputButton> InputManager::joystickButtonMap, InputManager::joystickAxisPosMap, InputManager::joystickAxisNegMap;
 std::map<int, int> InputManager::axisState;
+InputManager::InputButton InputManager::hatState = InputManager::UNKNOWN;
 
 int InputManager::deadzone = 28000;
 
@@ -85,17 +86,50 @@ void InputManager::processEvent(SDL_Event* event)
 		}else{
 			if(event->type == SDL_JOYHATMOTION)
 			{
-				//no keyUp for hat movement yet, but this should be easily accomplished by
-				//keeping the previous hat movement and checking if it moved from centered to anything else (keyDown) or back to centered (keyUp)
-				keyDown = true;
-				if(event->jhat.value & SDL_HAT_UP)
-					button = UP;
-				if(event->jhat.value & SDL_HAT_DOWN)
-					button = DOWN;
-				if(event->jhat.value & SDL_HAT_LEFT)
+				int hat = event->jhat.value;
+
+				if(hat == 0) //centered
+				{
+					//we need to send a keyUp event for the last hat
+					//keyDown is already false
+					button = hatState;
+				}else{
+					keyDown = true;
+				}
+
+				if(hat & SDL_HAT_LEFT)
 					button = LEFT;
-				if(event->jhat.value & SDL_HAT_RIGHT)
+				if(hat & SDL_HAT_RIGHT)
 					button = RIGHT;
+
+				if(hat & SDL_HAT_UP)
+					button = UP;
+				if(hat & SDL_HAT_DOWN)
+					button = DOWN;
+
+				if(button == hatState && keyDown)
+				{
+					//ignore this hat event since the user most likely just made it a diagonal (but it still is using the old direction)
+					button = UNKNOWN;
+				}else{
+					if(hatState != UNKNOWN && keyDown)
+					{
+						//this will occur if the user went down -> downLeft -> Left or similar
+						button = hatState;
+						keyDown = false;
+						hatState = UNKNOWN;
+						processEvent(event);
+					}else{
+						if(!keyDown)
+							hatState = UNKNOWN;
+						else
+							hatState = button;
+					}
+				}
+
+				if(button != UNKNOWN)
+					std::cout << "hat event, button: " << button << ", keyDown: " << keyDown << "\n";
+
 			}else{
 				if(event->type == SDL_JOYAXISMOTION)
 				{
diff --git a/src/InputManager.h b/src/InputManager.h
index c4d8320c6..61b6fa9ee 100644
--- a/src/InputManager.h
+++ b/src/InputManager.h
@@ -27,6 +27,7 @@ namespace InputManager {
 	extern std::map<int, InputButton> joystickButtonMap;
 	extern std::map<int, InputButton> joystickAxisPosMap, joystickAxisNegMap;
 	extern std::map<int, int> axisState;
+	extern InputButton hatState;
 }
 
 #endif
diff --git a/src/main.cpp b/src/main.cpp
index 28e4ef503..ae3a64c17 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -76,6 +76,7 @@ int main()
 		{
 			switch(event.type)
 			{
+				case SDL_JOYHATMOTION:
 				case SDL_JOYAXISMOTION:
 				case SDL_JOYBUTTONDOWN:
 				case SDL_JOYBUTTONUP: