summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2011-12-01 10:48:26 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2011-12-01 10:48:26 +0800
commit43ccf2982c7f3d5ce3b8865c5adede78b6e70f53 (patch)
tree2041da45fc68c612e98fa7796d8ffc5a7a37c62f
parentbeb70190397335fb31386e6a470d45f195152f0b (diff)
SexyAppFramework: Added a Interface for gamepad
-rw-r--r--osframework/source/SexyAppFramework/GamepadInputInterface.cpp239
-rw-r--r--osframework/source/SexyAppFramework/GamepadInputInterface.h42
-rw-r--r--osframework/source/SexyAppFramework/SConscript6
3 files changed, 285 insertions, 2 deletions
diff --git a/osframework/source/SexyAppFramework/GamepadInputInterface.cpp b/osframework/source/SexyAppFramework/GamepadInputInterface.cpp
new file mode 100644
index 0000000..d1fd7b9
--- /dev/null
+++ b/osframework/source/SexyAppFramework/GamepadInputInterface.cpp
@@ -0,0 +1,239 @@
+#include "GamepadInputInterface.h"
+
+#include <math.h>
+
+using namespace Sexy;
+
+GamepadInputInterface::GamepadInputInterface(InputManager* theManager)
+ : InputInterface(theManager)
+{
+}
+
+GamepadInputInterface::~GamepadInputInterface()
+{
+}
+
+GamepadInputInterface::DevState& GamepadInputInterface::GetState(int subid)
+{
+ DevStateMap::iterator it = mDevStateMap.find(subid);
+ if (it != mDevStateMap.end())
+ return it->second;
+
+ DevState state;
+
+ state.mX = 0;
+ state.mY = 0;
+ state.mHatX = 0;
+ state.mHatY = 0;
+ mDevStateMap[subid] = state;
+ return mDevStateMap[subid];
+}
+
+void GamepadInputInterface::PostResetEvents()
+{
+ DevStateMap::iterator it = mDevStateMap.begin();
+
+ Event kevt;
+ kevt.type = EVENT_KEY_UP;
+ kevt.id = mId;
+ kevt.flags |= EVENT_FLAGS_KEY_CODE;
+
+ for (; it != mDevStateMap.end(); ++it)
+ {
+ DevState& state = it->second;
+
+ ButtonStateMap::iterator bit = state.mButtons.begin();
+ for (; bit != state.mButtons.end(); ++bit)
+ {
+ if (bit->second)
+ {
+ kevt.u.key.keyCode = bit->first;
+ PostEvent(kevt, it->first);
+ }
+ }
+ }
+}
+
+void GamepadInputInterface::ResetStates()
+{
+ PostResetEvents();
+ mDevStateMap.clear();
+}
+
+bool GamepadInputInterface::HandleAxisChanged(float lx, float x, float flat,
+ bool vertical, int subid,
+ const Event& ref)
+{
+ int ix = 0, ilx = 0;
+
+ if (fabs(x) <= flat)
+ ix = 0;
+ else if (x > flat)
+ ix = 1;
+ else
+ ix = -1;
+
+ if (fabs(lx) <= flat)
+ ilx = 0;
+ else if (lx > flat)
+ ilx = 1;
+ else
+ ilx = -1;
+
+ if (ix == ilx)
+ return false;
+
+ Event evt = ref;
+ evt.flags |= EVENT_FLAGS_KEY_CODE;
+
+ KeyCode keyCodes[2];
+ if (!vertical)
+ {
+ keyCodes[0] = KEYCODE_GAMEPAD_LEFT;
+ keyCodes[1] = KEYCODE_GAMEPAD_RIGHT;
+ }
+ else
+ {
+ keyCodes[0] = KEYCODE_GAMEPAD_UP;
+ keyCodes[1] = KEYCODE_GAMEPAD_DOWN;
+ }
+
+ KeyCode keyCode = KEYCODE_UNKNOWN;
+ if (ilx + ix == 1)
+ {
+ keyCode = keyCodes[1];
+ evt.u.key.keyCode = keyCode;
+ if (ix == 1)
+ {
+ evt.type = EVENT_KEY_DOWN;
+ UpdateState(evt, subid);
+ PostEvent(evt, subid);
+ }
+ else
+ {
+ evt.type = EVENT_KEY_UP;
+ UpdateState(evt, subid);
+ PostEvent(evt, subid);
+ }
+ }
+ else if (ilx + ix == -1)
+ {
+ keyCode = keyCodes[0];
+ evt.u.key.keyCode = keyCode;
+ if (ix == -1)
+ {
+ evt.type = EVENT_KEY_DOWN;
+ UpdateState(evt, subid);
+ PostEvent(evt, subid);
+ }
+ else
+ {
+ evt.type = EVENT_KEY_UP;
+ UpdateState(evt, subid);
+ PostEvent(evt, subid);
+ }
+ }
+ else if (ix == 1 && ilx == -1)
+ {
+ keyCode = keyCodes[1];
+ evt.u.key.keyCode = keyCode;
+ evt.type = EVENT_KEY_UP;
+ UpdateState(evt, subid);
+ PostEvent(evt, subid);
+
+ keyCode = keyCodes[0];
+ evt.u.key.keyCode = keyCode;
+ evt.type = EVENT_KEY_DOWN;
+ UpdateState(evt, subid);
+ PostEvent(evt, subid);
+ }
+ else if (ix == -1 && ilx == 1)
+ {
+ keyCode = keyCodes[0];
+ evt.u.key.keyCode = keyCode;
+ evt.type = EVENT_KEY_UP;
+ UpdateState(evt, subid);
+ PostEvent(evt, subid);
+
+ keyCode = keyCodes[1];
+ evt.u.key.keyCode = keyCode;
+ evt.type = EVENT_KEY_DOWN;
+ UpdateState(evt, subid);
+ PostEvent(evt, subid);
+ }
+
+ return true;
+}
+
+void GamepadInputInterface::UpdateState(Event& event, int subid)
+{
+ if (event.type != EVENT_KEY_DOWN && event.type != EVENT_KEY_UP &&
+ event.type != EVENT_AXIS_MOVED)
+ return;
+
+ DevState& state = GetState(subid);
+ if (event.type == EVENT_KEY_DOWN)
+ {
+ state.mButtons[KeyCode(event.u.key.keyCode)] = true;
+ return;
+ }
+ else if (event.type == EVENT_KEY_UP)
+ {
+ state.mButtons[KeyCode(event.u.key.keyCode)] = false;
+ return;
+ }
+
+ Axis axis = Axis(event.u.axis.axis);
+ AxisValueMap::iterator it = state.mAxes.find(axis);
+
+ if (it == state.mAxes.end())
+ {
+ state.mAxes[axis] = 0.0f;
+ it = state.mAxes.find(axis);
+ }
+
+ float curValue = event.u.axis.value;
+ state.mAxes[axis] = curValue;
+
+ if (axis != AXIS_X && axis != AXIS_Y &&
+ axis != AXIS_HAT0X && axis != AXIS_HAT0Y)
+ return;
+
+ float flat = event.u.axis.flat;
+ float x = axis == AXIS_X ? state.mX : state.mHatX;
+ float y = axis == AXIS_Y ? state.mY : state.mHatY;
+ float lx = x;
+ float ly = y;
+
+ if (axis == AXIS_X)
+ {
+ x = event.u.axis.value;
+ if (HandleAxisChanged(lx, x, flat, false, subid, event))
+ state.mX = x;
+ }
+ if (axis == AXIS_HAT0X)
+ {
+ x = event.u.axis.value;
+ if (HandleAxisChanged(lx, x, flat, false, subid, event))
+ state.mHatX = x;
+ }
+ else if (axis == AXIS_Y)
+ {
+ y = event.u.axis.value;
+ if (HandleAxisChanged(ly, y, flat, true, subid, event))
+ state.mY = y;
+ }
+ else if (axis == AXIS_HAT0Y)
+ {
+ y = event.u.axis.value;
+ if (HandleAxisChanged(ly, y, flat, true, subid, event))
+ state.mHatY = y;
+ }
+}
+
+void GamepadInputInterface::Update()
+{
+ InputInterface::Update();
+
+ // todo: handle repeat here.
+}
diff --git a/osframework/source/SexyAppFramework/GamepadInputInterface.h b/osframework/source/SexyAppFramework/GamepadInputInterface.h
new file mode 100644
index 0000000..9fa0708
--- /dev/null
+++ b/osframework/source/SexyAppFramework/GamepadInputInterface.h
@@ -0,0 +1,42 @@
+#ifndef __GAMEPAD_INPUT_INTERFACE_H__
+#define __GAMEPAD_INPUT_INTERFACE_H__
+
+#include "InputInterface.h"
+#include "KeyCodes.h"
+
+namespace Sexy {
+
+ // This is not neccessary a real gamepad
+ class GamepadInputInterface : public InputInterface {
+ public:
+ GamepadInputInterface(InputManager* theManager);
+ ~GamepadInputInterface();
+
+ virtual void PostResetEvents();
+ virtual void ResetStates();
+ virtual void UpdateState(Event& event, int subid = 0);
+ virtual void Update();
+
+ protected:
+ struct DevState;
+ bool HandleAxisChanged(float lx, float x, float flat,
+ bool vertical, int subid,
+ const Event& ref);
+ DevState& GetState(int subid);
+
+ protected:
+ typedef std::map<Axis, float> AxisValueMap;
+ typedef std::map<KeyCode, bool> ButtonStateMap;
+ struct DevState {
+ AxisValueMap mAxes;
+ ButtonStateMap mButtons;
+
+ float mX, mY;
+ float mHatX, mHatY;
+ };
+ typedef std::map<int, DevState> DevStateMap;
+ DevStateMap mDevStateMap;
+ };
+};
+
+#endif
diff --git a/osframework/source/SexyAppFramework/SConscript b/osframework/source/SexyAppFramework/SConscript
index dbe8131..b9ac190 100644
--- a/osframework/source/SexyAppFramework/SConscript
+++ b/osframework/source/SexyAppFramework/SConscript
@@ -36,7 +36,8 @@ srcs = ["Buffer.cpp", "ButtonWidget.cpp", "Checkbox.cpp",
'AndroidLogListener.cpp', 'DefaultLogListener.cpp', 'SexyLog.cpp',
'SexyLogListener.cpp', 'SexyLogManager.cpp', 'SelectableWidget.cpp',
'SexySocket.cpp', 'SimpleUdpLogListener.cpp', 'TcpLogListener.cpp',
- 'MultiplexLogListener.cpp', 'SexyServiceManager.cpp']
+ 'MultiplexLogListener.cpp', 'SexyServiceManager.cpp',
+ 'GamepadInputInterface.cpp']
### uniconv
srcs += map(lambda f:os.path.join ('uniconv', f),
@@ -314,7 +315,8 @@ headers = ['FlashWidget.h', 'Font.h', 'ImageFont.h', 'SexyVector.h',
'NativeFont.h', 'SexyThread.h', 'XMLWriter.h',
'SexyI18n.h', 'SexyLang.h', 'SexyTimer.h', 'Find.h',
'TextLayout.h', 'SexyString.h', 'SelectableWidget.h',
- 'SexySocket.h', 'SexyServiceManager.h'
+ 'SexySocket.h', 'SexyServiceManager.h',
+ 'GamepadInputInterface.h'
]
sexyapp_sdk = env.Install (header_dir, headers)