diff options
author | Luo Jinghua <sunmoon1997@gmail.com> | 2011-12-01 10:48:26 +0800 |
---|---|---|
committer | Luo Jinghua <sunmoon1997@gmail.com> | 2011-12-01 10:48:26 +0800 |
commit | 43ccf2982c7f3d5ce3b8865c5adede78b6e70f53 (patch) | |
tree | 2041da45fc68c612e98fa7796d8ffc5a7a37c62f | |
parent | beb70190397335fb31386e6a470d45f195152f0b (diff) |
SexyAppFramework: Added a Interface for gamepad
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) |