Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126501
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
101 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/input/allegro/allegro-joystick.cpp b/util/input/allegro/allegro-joystick.cpp
new file mode 100644
index 00000000..09e95ba1
--- /dev/null
+++ b/util/input/allegro/allegro-joystick.cpp
@@ -0,0 +1,56 @@
+#ifdef USE_ALLEGRO
+
+#include <allegro.h>
+#include "allegro-joystick.h"
+
+void AllegroJoystick::poll(){
+ ::poll_joystick();
+}
+
+JoystickInput AllegroJoystick::readAll(){
+ JoystickInput input;
+ JOYSTICK_INFO * info = &joy[0];
+ switch(info->num_buttons > 4 ? 4 : info->num_buttons){
+ case 4: input.button4 = info->button[3].b;
+ case 3: input.button3 = info->button[2].b;
+ case 2: input.button2 = info->button[1].b;
+ case 1: input.button1 = info->button[0].b;
+ case 0: {
+ break;
+ }
+ }
+
+ for (int stick = 0; stick < info->num_sticks; stick++){
+ JOYSTICK_STICK_INFO * this_stick = &info->stick[stick];
+ if (this_stick->num_axis > 0){
+ int position = this_stick->axis[0].pos;
+ if (position < 0){
+ input.left = true;
+ } else if (position > 0){
+ input.right = true;
+ }
+ }
+ if (this_stick->num_axis > 1){
+ int position = this_stick->axis[1].pos;
+ if (position < 0){
+ input.up = true;
+ } else if (position > 0){
+ input.down = true;
+ }
+ }
+ }
+
+ return input;
+}
+
+AllegroJoystick::~AllegroJoystick(){
+}
+
+AllegroJoystick::AllegroJoystick(){
+}
+
+int AllegroJoystick::getDeviceId() const {
+ return 0;
+}
+
+#endif
diff --git a/util/input/allegro/allegro-joystick.h b/util/input/allegro/allegro-joystick.h
new file mode 100644
index 00000000..bbecff48
--- /dev/null
+++ b/util/input/allegro/allegro-joystick.h
@@ -0,0 +1,19 @@
+#ifndef _paintown_allegro_joystick_h
+#define _paintown_allegro_joystick_h
+
+#include "../joystick.h"
+
+class AllegroJoystick: public Joystick {
+public:
+ virtual void poll();
+ virtual JoystickInput readAll();
+ virtual int getDeviceId() const;
+
+ virtual ~AllegroJoystick();
+
+ friend class Joystick;
+protected:
+ AllegroJoystick();
+};
+
+#endif
diff --git a/util/input/allegro/keyboard.cpp b/util/input/allegro/keyboard.cpp
new file mode 100644
index 00000000..5ac4dbe3
--- /dev/null
+++ b/util/input/allegro/keyboard.cpp
@@ -0,0 +1,317 @@
+#include <allegro.h>
+#ifdef WINDOWS
+#include <winalleg.h>
+#endif
+#include "../keyboard.h"
+#include "util/thread.h"
+#include "util/funcs.h"
+#include "globals.h"
+#include <iostream>
+#include <vector>
+#include <map>
+
+using namespace std;
+
+const int Keyboard::Key_A = ::KEY_A;
+const int Keyboard::Key_B = ::KEY_B;
+const int Keyboard::Key_C = ::KEY_C;
+const int Keyboard::Key_D = ::KEY_D;
+const int Keyboard::Key_E = ::KEY_E;
+const int Keyboard::Key_F = ::KEY_F;
+const int Keyboard::Key_G = ::KEY_G;
+const int Keyboard::Key_H = ::KEY_H;
+const int Keyboard::Key_I = ::KEY_I;
+const int Keyboard::Key_J = ::KEY_J;
+const int Keyboard::Key_K = ::KEY_K;
+const int Keyboard::Key_L = ::KEY_L;
+const int Keyboard::Key_M = ::KEY_M;
+const int Keyboard::Key_N = ::KEY_N;
+const int Keyboard::Key_O = ::KEY_O;
+const int Keyboard::Key_P = ::KEY_P;
+const int Keyboard::Key_Q = ::KEY_Q;
+const int Keyboard::Key_R = ::KEY_R;
+const int Keyboard::Key_S = ::KEY_S;
+const int Keyboard::Key_T = ::KEY_T;
+const int Keyboard::Key_U = ::KEY_U;
+const int Keyboard::Key_V = ::KEY_V;
+const int Keyboard::Key_W = ::KEY_W;
+const int Keyboard::Key_X = ::KEY_X;
+const int Keyboard::Key_Y = ::KEY_Y;
+const int Keyboard::Key_Z = ::KEY_Z;
+const int Keyboard::Key_0 = ::KEY_0;
+const int Keyboard::Key_1 = ::KEY_1;
+const int Keyboard::Key_2 = ::KEY_2;
+const int Keyboard::Key_3 = ::KEY_3;
+const int Keyboard::Key_4 = ::KEY_4;
+const int Keyboard::Key_5 = ::KEY_5;
+const int Keyboard::Key_6 = ::KEY_6;
+const int Keyboard::Key_7 = ::KEY_7;
+const int Keyboard::Key_8 = ::KEY_8;
+const int Keyboard::Key_9 = ::KEY_9;
+const int Keyboard::Key_0_PAD = ::KEY_0_PAD;
+const int Keyboard::Key_1_PAD = ::KEY_1_PAD;
+const int Keyboard::Key_2_PAD = ::KEY_2_PAD;
+const int Keyboard::Key_3_PAD = ::KEY_3_PAD;
+const int Keyboard::Key_4_PAD = ::KEY_4_PAD;
+const int Keyboard::Key_5_PAD = ::KEY_5_PAD;
+const int Keyboard::Key_6_PAD = ::KEY_6_PAD;
+const int Keyboard::Key_7_PAD = ::KEY_7_PAD;
+const int Keyboard::Key_8_PAD = ::KEY_8_PAD;
+const int Keyboard::Key_9_PAD = ::KEY_9_PAD;
+const int Keyboard::Key_F1 = ::KEY_F1;
+const int Keyboard::Key_F2 = ::KEY_F2;
+const int Keyboard::Key_F3 = ::KEY_F3;
+const int Keyboard::Key_F4 = ::KEY_F4;
+const int Keyboard::Key_F5 = ::KEY_F5;
+const int Keyboard::Key_F6 = ::KEY_F6;
+const int Keyboard::Key_F7 = ::KEY_F7;
+const int Keyboard::Key_F8 = ::KEY_F8;
+const int Keyboard::Key_F9 = ::KEY_F9;
+const int Keyboard::Key_F10 = ::KEY_F10;
+const int Keyboard::Key_F11 = ::KEY_F11;
+const int Keyboard::Key_F12 = ::KEY_F12;
+const int Keyboard::Key_ESC = ::KEY_ESC;
+const int Keyboard::Key_TILDE = ::KEY_TILDE;
+const int Keyboard::Key_MINUS = ::KEY_MINUS;
+const int Keyboard::Key_EQUALS = ::KEY_EQUALS;
+const int Keyboard::Key_BACKSPACE = ::KEY_BACKSPACE;
+const int Keyboard::Key_TAB = ::KEY_TAB;
+const int Keyboard::Key_OPENBRACE = ::KEY_OPENBRACE;
+const int Keyboard::Key_CLOSEBRACE = ::KEY_CLOSEBRACE;
+const int Keyboard::Key_ENTER = ::KEY_ENTER;
+const int Keyboard::Key_COLON = ::KEY_COLON;
+const int Keyboard::Key_QUOTE = ::KEY_QUOTE;
+const int Keyboard::Key_BACKSLASH = ::KEY_BACKSLASH;
+const int Keyboard::Key_BACKSLASH2 = ::KEY_BACKSLASH2;
+const int Keyboard::Key_COMMA = ::KEY_COMMA;
+const int Keyboard::Key_STOP = ::KEY_STOP;
+const int Keyboard::Key_SLASH = ::KEY_SLASH;
+const int Keyboard::Key_SPACE = ::KEY_SPACE;
+const int Keyboard::Key_INSERT = ::KEY_INSERT;
+const int Keyboard::Key_DEL = ::KEY_DEL;
+const int Keyboard::Key_HOME = ::KEY_HOME;
+const int Keyboard::Key_END = ::KEY_END;
+const int Keyboard::Key_PGUP = ::KEY_PGUP;
+const int Keyboard::Key_PGDN = ::KEY_PGDN;
+const int Keyboard::Key_LEFT = ::KEY_LEFT;
+const int Keyboard::Key_RIGHT = ::KEY_RIGHT;
+const int Keyboard::Key_UP = ::KEY_UP;
+const int Keyboard::Key_DOWN = ::KEY_DOWN;
+const int Keyboard::Key_SLASH_PAD = ::KEY_SLASH_PAD;
+const int Keyboard::Key_ASTERISK = ::KEY_ASTERISK;
+const int Keyboard::Key_MINUS_PAD = ::KEY_MINUS_PAD;
+const int Keyboard::Key_PLUS_PAD = ::KEY_PLUS_PAD;
+const int Keyboard::Key_DEL_PAD = ::KEY_DEL_PAD;
+const int Keyboard::Key_ENTER_PAD = ::KEY_ENTER_PAD;
+const int Keyboard::Key_PRTSCR = ::KEY_PRTSCR;
+const int Keyboard::Key_PAUSE = ::KEY_PAUSE;
+const int Keyboard::Key_ABNT_C1 = ::KEY_ABNT_C1;
+const int Keyboard::Key_YEN = ::KEY_YEN;
+const int Keyboard::Key_KANA = ::KEY_KANA;
+const int Keyboard::Key_CONVERT = ::KEY_CONVERT;
+const int Keyboard::Key_NOCONVERT = ::KEY_NOCONVERT;
+const int Keyboard::Key_AT = ::KEY_AT;
+const int Keyboard::Key_CIRCUMFLEX = ::KEY_CIRCUMFLEX;
+const int Keyboard::Key_COLON2 = ::KEY_COLON2;
+const int Keyboard::Key_KANJI = ::KEY_KANJI;
+const int Keyboard::Key_EQUALS_PAD = ::KEY_EQUALS_PAD;
+const int Keyboard::Key_BACKQUOTE = ::KEY_BACKQUOTE;
+const int Keyboard::Key_SEMICOLON = ::KEY_SEMICOLON;
+const int Keyboard::Key_COMMAND = ::KEY_COMMAND;
+
+/*
+const int Keyboard::Key_UNKNOWN1 = ::KEY_UNKNOWN1;
+const int Keyboard::Key_UNKNOWN2 = ::KEY_UNKNOWN2;
+const int Keyboard::Key_UNKNOWN3 = ::KEY_UNKNOWN3;
+const int Keyboard::Key_UNKNOWN4 = ::KEY_UNKNOWN4;
+const int Keyboard::Key_UNKNOWN5 = ::KEY_UNKNOWN5;
+const int Keyboard::Key_UNKNOWN6 = ::KEY_UNKNOWN6;
+const int Keyboard::Key_UNKNOWN7 = ::KEY_UNKNOWN7;
+const int Keyboard::Key_UNKNOWN8 = ::KEY_UNKNOWN8;
+*/
+
+const int Keyboard::Key_MODIFIERS = ::KEY_MODIFIERS;
+const int Keyboard::Key_LSHIFT = ::KEY_LSHIFT;
+const int Keyboard::Key_RSHIFT = ::KEY_RSHIFT;
+const int Keyboard::Key_LCONTROL = ::KEY_LCONTROL;
+const int Keyboard::Key_RCONTROL = ::KEY_RCONTROL;
+const int Keyboard::Key_ALT = ::KEY_ALT;
+const int Keyboard::Key_ALTGR = ::KEY_ALTGR;
+const int Keyboard::Key_LWIN = ::KEY_LWIN;
+const int Keyboard::Key_RWIN = ::KEY_RWIN;
+const int Keyboard::Key_MENU = ::KEY_MENU;
+const int Keyboard::Key_SCRLOCK = ::KEY_SCRLOCK;
+const int Keyboard::Key_NUMLOCK = ::KEY_NUMLOCK;
+const int Keyboard::Key_CAPSLOCK = ::KEY_CAPSLOCK;
+
+static Util::Thread::Lock keyboardData;
+
+static vector<Keyboard::KeyData> stolenKeys;
+static int steal_keys(int unicode, int * scancode){
+ // Global::debug(0) << "Steal key " << unicode << " " << *scancode << endl;
+ Util::Thread::acquireLock(&keyboardData);
+ stolenKeys.push_back(Keyboard::KeyData(*scancode, unicode, true));
+ Util::Thread::releaseLock(&keyboardData);
+ return unicode;
+}
+
+static map<int, bool> stolenPresses;
+static void steal_scancode(int scancode){
+ Util::Thread::acquireLock(&keyboardData);
+ if (scancode & 0x80){
+ stolenPresses[scancode & 0x7f] = false;
+ } else {
+ stolenPresses[scancode & 0x7f] = true;
+ }
+ Util::Thread::releaseLock(&keyboardData);
+}
+
+Keyboard::Keyboard():
+enableBuffer(false){
+ /*
+ for ( int q = 0; q < KEY_MAX; q++ ){
+ my_keys[ q ] = 0;
+ }
+ */
+ setAllDelay( 0 );
+
+ Util::Thread::initializeLock(&keyboardData);
+ ::keyboard_ucallback = steal_keys;
+ ::keyboard_lowlevel_callback = steal_scancode;
+}
+
+/* KEY_MAX is defined in allegro at
+ * allegro/include/allegro/keyboard.h
+ */
+void Keyboard::poll(){
+ buffer.clear();
+
+ // keyState.clear();
+ Util::Thread::acquireLock(&keyboardData);
+ for (vector<KeyData>::iterator it = stolenKeys.begin(); it != stolenKeys.end(); it++){
+ const KeyData & data = *it;
+ keyState[data.key] = data;
+ }
+ stolenKeys.clear();
+
+ for (map<int, bool>::iterator it = stolenPresses.begin(); it != stolenPresses.end(); it++){
+ int key = it->first;
+ bool pressed = it->second;
+ keyState[key].enabled = pressed;
+
+ if (pressed){
+ press(key, keyState[key].unicode);
+ } else {
+ release(key);
+ }
+ }
+ stolenPresses.clear();
+ Util::Thread::releaseLock(&keyboardData);
+
+ /*
+ ::poll_keyboard();
+ keyState.clear();
+ while (::keypressed()){
+ int unicode;
+ int key = ::ureadkey(&unicode);
+ keyState[key] = KeyData(key, unicode, true);
+ }
+ */
+
+#if 0
+ for ( int q = 0; q < KEY_MAX; q++ ){
+ // my_keys[ q ] = key[ q ];
+ if ( key[ q ] ){
+ /* my_keys[ q ] becomes negative so that the key
+ * can be pressed the first time without having
+ * to wait for a delay
+ */
+ if ( my_keys[ q ] <= 0 ){
+ my_keys[ q ] -= 1;
+ } else {
+ my_keys[ q ] += 1;
+ }
+ // printf( "Key %d = %d\n", q, my_keys[ q ] );
+ } else {
+ my_keys[ q ] = 0;
+ }
+ }
+#endif
+}
+
+#if 0
+std::vector<Keyboard::KeyData> Keyboard::readData(){
+ std::vector<Keyboard::KeyData> out;
+ /* TODO */
+ return out;
+}
+
+std::vector<Keyboard::unicode_t> Keyboard::readText(){
+ std::vector<Keyboard::unicode_t> out;
+ /* TODO */
+ return out;
+}
+#endif
+
+void Keyboard::readKeys( vector< int > & all_keys ){
+
+ for (std::map<KeyType, KeyData>::iterator it = keyState.begin(); it != keyState.end(); it++){
+ KeyType key = it->first;
+ const KeyData & data = it->second;
+ if (data.enabled){
+ all_keys.push_back(key);
+ }
+ }
+
+/*
+ for ( map<int,int>::const_iterator it = my_keys.begin(); it != my_keys.end(); it++ ){
+ const int & key = it->first;
+ const int & delay = it->second;
+ if ( delay != 0 ){
+ Global::debug( 6 ) << "Key " << key << " delay " << delay << " key_delay " << key_delay[ key ] << endl;
+ }
+ if ( delay < 0 ){
+ all_keys.push_back( key );
+ my_keys[ key ] = 1;
+ } else if ( delay > key_delay[ key ] ){
+ all_keys.push_back( key );
+ my_keys[ key ] = 1;
+ }
+ }
+ */
+}
+
+/*
+int Keyboard::readKey(){
+ return ::readkey() >> 8;
+}
+*/
+
+void Keyboard::wait(){
+ clear();
+ poll();
+ while ( keypressed() ){
+ poll();
+ Util::rest( 1 );
+ }
+}
+
+bool Keyboard::keypressed(){
+ return ::keypressed();
+ /*
+ for ( map<int,int>::const_iterator it = my_keys.begin(); it != my_keys.end(); it++ ){
+ const int & n = (*it).second;
+ if ( n < 0 || n > key_delay[ it->first ] ){
+ return true;
+ }
+ }
+ return false;
+ */
+}
+
+void Keyboard::clear(){
+ ::clear_keybuf();
+ buffer.clear();
+ keyState.clear();
+ // my_keys.clear();
+}
diff --git a/util/input/input-manager.cpp b/util/input/input-manager.cpp
new file mode 100644
index 00000000..031b3bc9
--- /dev/null
+++ b/util/input/input-manager.cpp
@@ -0,0 +1,236 @@
+#include "input-manager.h"
+#include "configuration.h"
+/* FIXME: break this dependancy */
+#include "paintown-engine/object/object.h"
+#include "joystick.h"
+#include "util/events.h"
+#include "globals.h"
+#include "util/debug.h"
+#include <stdlib.h>
+#include <vector>
+
+using namespace std;
+
+InputManager * InputManager::manager = 0;
+
+InputManager::InputManager():
+capture(0),
+joystick(NULL){
+ manager = this;
+ if (Configuration::isJoystickEnabled()){
+ joystick = Joystick::create();
+ }
+}
+
+InputManager::~InputManager(){
+ delete joystick;
+}
+
+bool InputManager::anyInput(){
+ if (manager == 0){
+ Global::debug(0) << "*BUG* Input manager not set up" << endl;
+ exit(0);
+ }
+
+ return manager->_anyInput();
+}
+
+bool InputManager::_anyInput(){
+ if (keyboard.keypressed()){
+ return true;
+ }
+
+ if (joystick){
+ JoystickInput all_joystick = joystick->readAll();
+ if (all_joystick.pressed()){
+ return true;
+ }
+ }
+
+ return false;
+}
+
+vector<Input::PaintownInput> InputManager::getInput(const Configuration & configuration, const int facing){
+ if (manager == 0){
+ Global::debug(0) << "*BUG* Input manager not set up" << endl;
+ exit(0);
+ }
+
+ return manager->_getInput(configuration, facing);
+}
+
+/*
+void InputManager::enableBufferInput(){
+ manager->bufferKeys = true;
+}
+
+void InputManager::disableBufferInput(){
+ manager->bufferKeys = false;
+}
+*/
+
+void InputManager::waitForClear(){
+ manager->keyboard.clear();
+ while (anyInput()){
+ poll();
+ Util::rest(1);
+ }
+}
+
+void InputManager::waitForKeys(int key1, int key2){
+ InputMap<int> wait;
+ wait.set(key1, 0, false, 1);
+ wait.set(key2, 0, false, 1);
+ InputManager::waitForRelease(wait, 1);
+ InputManager::waitForPress(wait, 1);
+ InputManager::waitForRelease(wait, 1);
+}
+
+void InputManager::waitForKeys(int key){
+ InputMap<int> wait;
+ wait.set(key, 0, false, 1);
+ InputManager::waitForRelease(wait, 1);
+ InputManager::waitForPress(wait, 1);
+ InputManager::waitForRelease(wait, 1);
+}
+
+/* these mappings should agree with configuration.cpp:defaultJoystick1Keys,
+ * but otherwise they are completely arbitrary
+ */
+static Input::PaintownInput convertJoystickKey(const Joystick::Key key, const int facing){
+ switch (key){
+ case Joystick::Up : return Input::Up;
+ case Joystick::Down : return Input::Down;
+ case Joystick::Left : {
+ if (facing == Paintown::Object::FACING_RIGHT){
+ return Input::Back;
+ } else {
+ return Input::Forward;
+ }
+ }
+ case Joystick::Right : {
+ if (facing == Paintown::Object::FACING_RIGHT){
+ return Input::Forward;
+ } else {
+ return Input::Back;
+ }
+ }
+ case Joystick::Button1 : return Input::Attack1;
+ case Joystick::Button2 : return Input::Attack2;
+ case Joystick::Button3 : return Input::Attack3;
+ case Joystick::Button4 : return Input::Jump;
+ default : return Input::Unknown;
+ }
+}
+
+static vector<Input::PaintownInput> convertJoystick(const Configuration & configuration, JoystickInput input, const int facing){
+ vector<Input::PaintownInput> all;
+
+ if (input.up){
+ all.push_back(convertJoystickKey(configuration.getJoystickUp(), facing));
+ }
+
+ if (input.right){
+ all.push_back(convertJoystickKey(configuration.getJoystickRight(), facing));
+ }
+
+ if (input.left){
+ all.push_back(convertJoystickKey(configuration.getJoystickLeft(), facing));
+ }
+
+ if (input.down){
+ all.push_back(convertJoystickKey(configuration.getJoystickDown(), facing));
+ }
+
+ if (input.button1){
+ all.push_back(convertJoystickKey(configuration.getJoystickAttack1(), facing));
+ }
+
+ if (input.button2){
+ all.push_back(convertJoystickKey(configuration.getJoystickAttack2(), facing));
+ }
+
+ if (input.button3){
+ all.push_back(convertJoystickKey(configuration.getJoystickAttack3(), facing));
+ }
+
+ if (input.button4){
+ all.push_back(convertJoystickKey(configuration.getJoystickJump(), facing));
+ }
+
+ return all;
+}
+
+void InputManager::poll(){
+ if (manager == 0){
+ Global::debug(0) << "*BUG* Input manager not set up" << endl;
+ exit(0);
+ }
+
+ return manager->_poll();
+}
+
+int InputManager::readKey(){
+ return manager->_readKey();
+}
+
+int InputManager::_readKey(){
+ std::vector<int> keys;
+ do{
+ keyboard.readKeys(keys);
+ if (keys.size() == 0){
+ Util::rest(1);
+ poll();
+ }
+ } while (keys.size() == 0);
+ return keys.front();
+}
+
+void InputManager::_poll(){
+ /* FIXME: not sure if its a good idea to put the event manager here */
+ Util::EventManager eventManager;
+ /*
+ if (bufferKeys){
+ eventManager.enableKeyBuffer();
+ }
+ */
+ eventManager.run(keyboard, joystick);
+
+ // keyboard.poll();
+ /*
+ if (joystick != NULL){
+ joystick->poll();
+ }
+ */
+
+ // const vector<Util::EventManager::KeyType> & keys = eventManager.getBufferedKeys();
+ // bufferedKeys.insert(bufferedKeys.end(), keys.begin(), keys.end());
+}
+
+vector<Input::PaintownInput> InputManager::_getInput(const Configuration & configuration, const int facing){
+
+ InputMap<Input::PaintownInput> input;
+
+ enum Input::PaintownInput all[] = {Input::Forward, Input::Back, Input::Up, Input::Down, Input::Attack1, Input::Attack2, Input::Attack3, Input::Jump, Input::Grab};
+ for (unsigned int i = 0; i < sizeof(all) / sizeof(Input::PaintownInput); i++){
+ input.set(configuration.getKey(all[i], facing), 0, false, all[i]);
+ input.set(configuration.getJoystickKey(all[i], facing), 0, false, all[i]);
+ }
+
+ InputMap<Input::PaintownInput>::Output state = InputManager::getMap(input);
+ return InputMap<Input::PaintownInput>::getAllPressed(state);
+
+ /*
+ vector<int> all_keys;
+ keyboard.readKeys( all_keys );
+
+ vector<Input::PaintownInput> real_input = Input::convertKeyboard(configuration, facing, all_keys);
+
+ if (joystick != NULL){
+ vector<Input::PaintownInput> joystick_keys = convertJoystick(configuration, joystick->readAll(), facing);
+ real_input.insert(real_input.begin(), joystick_keys.begin(), joystick_keys.end());
+ }
+
+ return real_input;
+ */
+}
diff --git a/util/input/input-manager.h b/util/input/input-manager.h
new file mode 100644
index 00000000..97a32fb8
--- /dev/null
+++ b/util/input/input-manager.h
@@ -0,0 +1,285 @@
+#ifndef _paintown_input_manager
+#define _paintown_input_manager
+
+#include <vector>
+#include <algorithm>
+#include "input.h"
+#include "input-map.h"
+#include "util/funcs.h"
+#include "keyboard.h"
+#include "exceptions/exception.h"
+
+class Configuration;
+class Joystick;
+
+template <class Output>
+class InputHandler{
+public:
+ InputHandler(){
+ }
+
+ virtual ~InputHandler(){
+ }
+
+ virtual void press(const Output & out, Keyboard::unicode_t unicode) = 0;
+ virtual void release(const Output & out, Keyboard::unicode_t unicode) = 0;
+};
+
+/* handles keyboard/joystick/whatever input during the game */
+class InputManager{
+public:
+ /* main has one instance of this and thats it.
+ * should the janitor have the reference instead?
+ */
+ friend int paintown_main(int, char**);
+ friend int main(int, char **);
+
+ /* returns true if any input device is activated (keys pressed, joystick button */
+ static bool anyInput();
+
+ static std::vector<Input::PaintownInput> getInput(const Configuration & configuration, const int facing);
+ static void poll();
+ /*
+ static void enableBufferInput();
+ static void disableBufferInput();
+ */
+ static void waitForKeys(int key1, int key2);
+ static void waitForKeys(int key1);
+ static int readKey();
+ static void waitForClear();
+
+ /*
+ template <class X>
+ static void observeKeyboard(InputMap<X> & input){
+ manager->keyboard.addObserver(InputMap<X>::observeKey, &input);
+ }
+
+ template <class X>
+ static void unObserveKeyboard(InputMap<X> & input){
+ manager->keyboard.removeObserver(InputMap<X>::observeKey, &input);
+ }
+ */
+
+ static std::vector<Keyboard::unicode_t> readText(){
+ return manager->keyboard.readText();
+ }
+
+ template <typename X>
+ static std::vector<Keyboard::unicode_t> readText(InputMap<X> & input, typename InputMap<X>::Output & output){
+ return manager->_readText(input, output);
+ }
+
+ template <typename X>
+ static typename InputMap<X>::Output getMap(InputMap<X> & input){
+ if (manager){
+ return manager->_getMap(input);
+ }
+ /* just crash hard.. who cares */
+ throw Exception::Base(__FILE__, __LINE__);
+ /* make the compiler happy about returning something */
+ return *(typename InputMap<X>::Output*)1;
+ }
+
+ template <typename X>
+ static typename std::vector<typename InputMap<X>::InputEvent> getEvents(InputMap<X> & input){
+ return manager->_getEvents(input);
+ }
+
+ template <typename X>
+ static void handleEvents(InputMap<X> & input, InputHandler<X> & handler){
+ typename std::vector<typename InputMap<X>::InputEvent> events = getEvents(input);
+ for (typename std::vector<typename InputMap<X>::InputEvent>::iterator it = events.begin(); it != events.end(); it++){
+ const typename InputMap<X>::InputEvent & event = *it;
+ if (event.enabled){
+ handler.press(event.out, event.unicode);
+ } else {
+ handler.release(event.out, event.unicode);
+ }
+ }
+ }
+
+ template <typename X>
+ static bool pressed(InputMap<X> & input, X out){
+ if (manager){
+ return manager->_pressed(input, out);
+ }
+ return false;
+ }
+
+ /* wait for a key to be released
+ * really this waits for all inputs that would result in `out'
+ * being generated to stop.
+ */
+ template <typename X>
+ static void waitForRelease(InputMap<X> & input, X out){
+ while (InputManager::pressed(input, out)){
+ Util::rest(1);
+ InputManager::poll();
+ }
+ }
+
+ template <typename X>
+ static void waitForPress(InputMap<X> & input, X out){
+ while (!InputManager::pressed(input, out)){
+ Util::rest(1);
+ InputManager::poll();
+ }
+ }
+
+ template <typename X>
+ static void captureInput(InputMap<X> & input){
+ manager->_captureInput(input);
+ }
+
+ template <typename X>
+ static void releaseInput(InputMap<X> & input){
+ manager->_releaseInput(input);
+ }
+
+protected:
+ InputManager();
+ virtual ~InputManager();
+
+ virtual bool _anyInput();
+
+ virtual int _readKey();
+
+ virtual std::vector<Input::PaintownInput> _getInput(const Configuration & configuration, const int facing);
+
+ template <typename X>
+ void _captureInput(InputMap<X> & input){
+ capture = (void*) &input;
+ }
+
+ template <typename X>
+ void _releaseInput(InputMap<X> & input){
+ if (capture == (void*) &input){
+ capture = 0;
+ }
+ }
+
+ template <typename X>
+ std::vector<Keyboard::unicode_t> _readText(InputMap<X> & input, typename InputMap<X>::Output & output){
+ std::vector<Keyboard::unicode_t> text;
+ std::vector<Keyboard::KeyData> all = keyboard.readData();
+ for (std::vector<Keyboard::KeyData>::iterator it = all.begin(); it != all.end(); it++){
+ const Keyboard::KeyData & data = *it;
+ KeyState<X> * state = input.getState(data.key);
+ if (state != NULL && output[state->out]){
+ text.push_back(data.unicode);
+ }
+ }
+
+ return text;
+ }
+
+ void removeDuplicates(std::vector<int> & storage){
+ std::vector<int> output;
+ int last = -1;
+ for (std::vector<int>::iterator it = storage.begin(); it != storage.end(); it++){
+ if (*it != last){
+ output.push_back(*it);
+ last = *it;
+ }
+ }
+ storage = output;
+ }
+
+ template <typename X>
+ typename std::vector<typename InputMap<X>::InputEvent> _getEvents(InputMap<X> & input){
+ std::vector<typename InputMap<X>::InputEvent> events;
+ if (capture != NULL && capture != &input){
+ return events;
+ }
+
+ const std::vector<typename Keyboard::KeyData> & buffer = keyboard.getBufferedKeys();
+ for (std::vector<Keyboard::KeyData>::const_iterator it = buffer.begin(); it != buffer.end(); it++){
+ const Keyboard::KeyData & data = *it;
+ KeyState<X> * state = input.getState(data.key);
+ if (state != NULL){
+ events.push_back(typename InputMap<X>::InputEvent(state->out, data.unicode, data.enabled));
+ }
+ }
+
+ if (joystick){
+ const std::vector<typename Joystick::Event> & joystickEvents = joystick->getEvents();
+ for (std::vector<Joystick::Event>::const_iterator it = joystickEvents.begin(); it != joystickEvents.end(); it++){
+ Joystick::Event event = *it;
+ JoystickState<X> * state = input.getJoystickState(event);
+ if (state != NULL){
+ events.push_back(typename InputMap<X>::InputEvent(state->out, -1, true));
+ }
+ }
+ }
+
+ return events;
+ }
+
+ template <typename X>
+ typename InputMap<X>::Output _getMap(InputMap<X> & input){
+ typename InputMap<X>::Output output;
+
+ if (capture != 0 && capture != &input){
+ return output;
+ }
+
+ std::vector<int> all_keys;
+ keyboard.readKeys(all_keys);
+ keyboard.readBufferedKeys(all_keys);
+ // all_keys.insert(all_keys.end(), bufferedKeys.begin(), bufferedKeys.end());
+ // all_keys.insert(all_keys.end(), keyboard.currentKeys().begin(), keyboard.currentKeys.end());
+ std::sort(all_keys.begin(), all_keys.end());
+ removeDuplicates(all_keys);
+ // std::unique(all_keys.begin(), all_keys.end());
+ // bufferedKeys.clear();
+
+ input.read(all_keys, &output);
+
+ if (joystick != NULL){
+ JoystickInput all_joystick = joystick->readAll();
+ input.read(all_joystick, &output);
+ }
+
+ /* just bumps an internal counter */
+ input.update();
+
+ return output;
+ }
+
+ template <typename X>
+ bool _pressed(InputMap<X> & input, X result){
+
+ if (capture != 0 && capture != &input){
+ return false;
+ }
+
+ std::vector<int> all_keys;
+ keyboard.readKeys(all_keys);
+ // all_keys.insert(all_keys.end(), bufferedKeys.begin(), bufferedKeys.end());
+ std::sort(all_keys.begin(), all_keys.end());
+ removeDuplicates(all_keys);
+ // bufferedKeys.clear();
+ bool out = false;
+
+ out = input.pressed(all_keys, result);
+
+ if (joystick != NULL){
+ JoystickInput all_joystick = joystick->readAll();
+ out |= input.pressed(all_joystick, result);
+ }
+
+ return out;
+ }
+
+ virtual void _poll();
+
+private:
+ static InputManager * manager;
+ void * capture;
+ Joystick * joystick;
+ Keyboard keyboard;
+ // std::vector<int> bufferedKeys;
+ // bool bufferKeys;
+};
+
+#endif
diff --git a/util/input/input-map.h b/util/input/input-map.h
new file mode 100644
index 00000000..bd76d826
--- /dev/null
+++ b/util/input/input-map.h
@@ -0,0 +1,300 @@
+#ifndef _paintown_input_map_h
+#define _paintown_input_map_h
+
+#include <map>
+#include <vector>
+#include "joystick.h"
+#include "keyboard.h"
+#include "globals.h"
+#include <iostream>
+
+template <typename X>
+struct KeyState{
+ KeyState(unsigned int delay, bool block, X out, unsigned int last_read):
+ delay(delay),
+ block(block),
+ out(out),
+ pressed(false),
+ last_read(0),
+ seen(0){
+ }
+
+ unsigned int delay;
+ bool block;
+ X out;
+ bool pressed;
+ unsigned int last_read;
+ unsigned int seen;
+};
+
+/* cant typedef a template'd struct so we have to copy/paste the definition
+ */
+template <typename X>
+struct JoystickState{
+ JoystickState(unsigned int delay, bool block, X out, unsigned int last_read):
+ delay(delay),
+ block(block),
+ out(out),
+ pressed(false),
+ last_read(0),
+ seen(0){
+ }
+
+ unsigned int delay;
+ bool block;
+ X out;
+ bool pressed;
+ unsigned int last_read;
+ unsigned int seen;
+};
+
+/* maps a raw input device (keyboard, joystick, etc.) to some user-defined type
+ * the template parameter, X, is that user-defined type
+ */
+template <typename X>
+class InputMap{
+public:
+ typedef std::map<X, bool> Output;
+
+ struct InputEvent{
+ InputEvent(const X & out, Keyboard::unicode_t unicode, bool enabled):
+ out(out),
+ unicode(unicode),
+ enabled(enabled){
+ }
+
+ InputEvent(const InputEvent & input):
+ out(input.out),
+ unicode(input.unicode),
+ enabled(input.enabled){
+ }
+
+ InputEvent(){
+ }
+
+ bool operator[](const X & is) const {
+ return this->out == is;
+ }
+
+ X out;
+ Keyboard::unicode_t unicode;
+ bool enabled;
+ };
+
+ InputMap():
+ last_read(0){
+ }
+
+ InputMap(const InputMap & copy){
+ for (typename std::map<Keyboard::KeyType, KeyState<X>* >::const_iterator it = copy.key_states.begin(); it != copy.key_states.end(); it++){
+ key_states[(*it).first] = new KeyState<X>(*(*it).second);
+ }
+ for (typename std::map<typename Joystick::Key, JoystickState<X>* >::const_iterator it = copy.joy_states.begin(); it != copy.joy_states.end(); it++){
+ joy_states[(*it).first] = new JoystickState<X>(*(*it).second);
+ }
+ last_read = copy.last_read;
+ }
+
+ InputMap & operator=(const InputMap & copy){
+ for (typename std::map<Keyboard::KeyType, KeyState<X>* >::const_iterator it = copy.key_states.begin(); it != copy.key_states.end(); it++){
+ key_states[(*it).first] = new KeyState<X>(*(*it).second);
+ }
+ for (typename std::map<typename Joystick::Key, JoystickState<X>* >::const_iterator it = copy.joy_states.begin(); it != copy.joy_states.end(); it++){
+ joy_states[(*it).first] = new JoystickState<X>(*(*it).second);
+ }
+ last_read = copy.last_read;
+ return *this;
+ }
+
+ virtual ~InputMap(){
+ for (typename std::map<Keyboard::KeyType, KeyState<X>*>::iterator it = key_states.begin(); it != key_states.end(); it++){
+ delete (*it).second;
+ }
+
+ for (typename std::map<typename Joystick::Key, JoystickState<X>* >::iterator it = joy_states.begin(); it != joy_states.end(); it++){
+ delete (*it).second;
+ }
+ }
+
+ /* key: the keyboard key to recognize, something like KEY_A
+ * delay: time before successive keys are recognized (if held down)
+ * block: if true then the key must be released before it will
+ * be recognized again. false allows repetition.
+ * out: user defined value to set if this key is pressed
+ */
+ void set(Keyboard::KeyType key, int delay, bool block, X out){
+ key_states[key] = new KeyState<X>(delay, block, out, last_read);
+ }
+
+ /* change an existing key */
+ void update(Keyboard::KeyType key, int delay, bool block, X out){
+ if (key_states[key] != 0){
+ key_states[key]->delay = delay;
+ key_states[key]->block = block;
+ key_states[key]->out = out;
+ }
+ }
+
+ /* mostly the same stuff but for joysticks.
+ */
+ void set(typename Joystick::Key key, int delay, bool block, X out){
+ joy_states[key] = new JoystickState<X>(delay, block, out, last_read);
+ }
+
+ static std::vector<X> getAllPressed(const Output & output){
+ std::vector<X> out;
+
+ for (typename Output::const_iterator it = output.begin(); it != output.end(); it++){
+ if ((*it).second){
+ out.push_back((*it).first);
+ }
+ }
+
+ return out;
+ }
+
+ /*
+ static void observeKey(const Keyboard::KeyData & data, void * self){
+ InputMap<X> * me = (InputMap<X>*) self;
+
+ KeyState<X> * state = state = getState(data.key);
+ if (state != NULL){
+ events.push_back(InputEvent(state->out, data.unicode, data.enabled));
+ }
+ }
+ */
+
+ bool pressed(const std::vector<int> & keys, X out){
+ for (std::vector<int>::const_iterator it = keys.begin(); it != keys.end(); it++){
+ Keyboard::KeyType key = *it;
+ KeyState<X> * state = key_states[key];
+ if (state != 0){
+ if (state->out == out){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ virtual KeyState<X> * getState(int key){
+ return key_states[key];
+ }
+
+ virtual JoystickState<X> * getJoystickState(Joystick::Key key){
+ return joy_states[key];
+ }
+
+ void read(const std::vector<int> & keys, Output * output){
+ for (std::vector<int>::const_iterator it = keys.begin(); it != keys.end(); it++){
+ Keyboard::KeyType key = *it;
+ KeyState<X> * state = getState(key);
+ if (state != NULL){
+ bool use = false;
+ // Global::debug(0) << "read " << key << " last read is " << state->last_read << " my last read is " << last_read << std::endl;
+ if (state->block){
+ if (last_read - state->last_read > 1){
+ use = true;
+ }
+ } else if (last_read - state->last_read > 1 || state->seen >= state->delay){
+ use = true;
+ state->seen = 0;
+ } else {
+ state->seen += 1;
+ }
+
+ state->last_read = last_read;
+
+ // state->last_read = last_read;
+
+ (*output)[state->out] = use;
+ }
+ }
+ }
+
+ /* called by the input manager when the map is read */
+ void update(){
+ last_read += 1;
+ }
+
+ void read(const JoystickInput & joystick, Output * output){
+#define do_joy(field, key) if (joystick.field){\
+ JoystickState<X> * state = joy_states[Joystick::key];\
+ doJoyState(state, output);\
+}
+
+ do_joy(down, Down);
+ do_joy(up, Up);
+ do_joy(left, Left);
+ do_joy(right, Right);
+ do_joy(button1, Button1);
+ do_joy(button2, Button2);
+ do_joy(button3, Button3);
+ do_joy(button4, Button4);
+ /*
+ if (joystick.up){
+ JoystickState<X> * state = joy_states[Joystick::Up];
+ doJoyState(state);
+ }
+
+ if (joystick.down){
+ JoystickState<X> * state = joy_states[Joystick::Down];
+ doJoyState(state);
+ }
+ */
+#undef do_joy
+
+ }
+
+ bool pressed(const JoystickInput & joystick, X out){
+#define do_joy(field, key) if (joystick.field){\
+ JoystickState<X> * state = joy_states[Joystick::key];\
+ if (state != 0 && state->out == out){\
+ return true;\
+ }\
+}
+
+ do_joy(down, Down);
+ do_joy(up, Up);
+ do_joy(left, Left);
+ do_joy(right, Right);
+ do_joy(button1, Button1);
+ do_joy(button2, Button2);
+ do_joy(button3, Button3);
+ do_joy(button4, Button4);
+
+
+#undef do_joy
+ return false;
+ }
+
+protected:
+ void doJoyState(JoystickState<X> * state, Output * output){
+ if (state != 0){
+ bool use = false;
+ if (state->block){
+ if (last_read - state->last_read > 1){
+ use = true;
+ }
+ } else if (last_read - state->last_read > 1 || state->seen >= state->delay){
+ use = true;
+ state->seen = 0;
+ } else {
+ state->seen += 1;
+ }
+
+ state->last_read = last_read;
+
+ // state->last_read = last_read;
+
+ (*output)[state->out] = use;
+ }
+ }
+
+private:
+ std::map<Keyboard::KeyType, KeyState<X>* > key_states;
+ std::map<typename Joystick::Key, JoystickState<X>* > joy_states;
+ unsigned int last_read;
+};
+
+#endif
diff --git a/util/input/input.cpp b/util/input/input.cpp
new file mode 100644
index 00000000..cbc02f14
--- /dev/null
+++ b/util/input/input.cpp
@@ -0,0 +1,48 @@
+#include "input.h"
+#include "configuration.h"
+#include "paintown-engine/object/object.h"
+#include <vector>
+
+using namespace std;
+
+static Input::PaintownInput convertKey(const Configuration & configuration, const int facing, const int key){
+ if (key == configuration.getRight()){
+ switch (facing){
+ case Paintown::Object::FACING_LEFT : return Input::Back;
+ case Paintown::Object::FACING_RIGHT : return Input::Forward;
+ }
+ } else if (key == configuration.getLeft()){
+ switch (facing){
+ case Paintown::Object::FACING_LEFT : return Input::Forward;
+ case Paintown::Object::FACING_RIGHT : return Input::Back;
+ }
+ } else if (key == configuration.getJump()){
+ return Input::Jump;
+ } else if (key == configuration.getUp()){
+ return Input::Up;
+ } else if (key == configuration.getDown()){
+ return Input::Down;
+ } else if (key == configuration.getAttack1()){
+ return Input::Attack1;
+ } else if (key == configuration.getAttack2()){
+ return Input::Attack2;
+ } else if (key == configuration.getAttack3()){
+ return Input::Attack3;
+ }
+
+ return Input::Unknown;
+}
+
+vector<Input::PaintownInput> Input::convertKeyboard(const Configuration & configuration, int facing, const vector<int> & keys){
+ vector<Input::PaintownInput> all;
+
+ for (vector<int>::const_iterator it = keys.begin(); it != keys.end(); it++){
+ Input::PaintownInput in = convertKey(configuration, facing, *it);
+ if (in != Unknown){
+ all.push_back(in);
+ }
+
+ }
+
+ return all;
+}
diff --git a/util/input/input.h b/util/input/input.h
new file mode 100644
index 00000000..ed0c990a
--- /dev/null
+++ b/util/input/input.h
@@ -0,0 +1,32 @@
+#ifndef _paintown_input_h
+#define _paintown_input_h
+
+#include <vector>
+#include "joystick.h"
+
+class Configuration;
+
+class Input{
+public:
+ /* don't change these numbers, but you can add to them */
+ enum PaintownInput{
+ Unknown = -1,
+ Forward = 0,
+ Back = 1,
+ Up = 2,
+ Down = 3,
+ Attack1 = 4,
+ Attack2 = 5,
+ Attack3 = 6,
+ Jump = 7,
+ Grab = 8,
+ Attack4 = 9,
+ Attack5 = 10,
+ Attack6 = 11,
+ };
+
+ /* TODO: remove this method.. useless now. */
+ static std::vector<PaintownInput> convertKeyboard(const Configuration & configuration,int facing, const std::vector<int> & keys);
+};
+
+#endif
diff --git a/util/input/joystick.cpp b/util/input/joystick.cpp
new file mode 100644
index 00000000..363d22a6
--- /dev/null
+++ b/util/input/joystick.cpp
@@ -0,0 +1,82 @@
+#include <stdlib.h>
+#include "joystick.h"
+
+/*
+#ifdef LINUX
+#include "linux_joystick.h"
+#endif
+*/
+
+#ifdef USE_ALLEGRO
+#include "allegro/allegro-joystick.h"
+#endif
+#ifdef USE_SDL
+#ifdef WII
+#include "wii/joystick.h"
+#include "sdl/joystick.h"
+#elif MINPSPW
+#include "psp/joystick.h"
+#else
+#include "sdl/joystick.h"
+#endif
+#endif
+
+Joystick * Joystick::create(){
+#ifdef USE_ALLEGRO
+ return new AllegroJoystick();
+#endif
+#ifdef USE_SDL
+#ifdef WII
+ return new SDLJoystick();
+ // return new WiiJoystick();
+#elif MINPSPW
+ return new PSPJoystick();
+#else
+ return new SDLJoystick();
+#endif
+#endif
+/*
+#ifdef LINUX
+ return new LinuxJoystick();
+#endif
+ return NULL;
+*/
+}
+
+Joystick::Joystick(){
+}
+
+Joystick::~Joystick(){
+}
+
+bool Joystick::pressed(){
+ JoystickInput input = readAll();
+ return input.up || input.down || input.left || input.right ||
+ input.button1 || input.button2 || input.button3 || input.button4 ||
+ input.quit;
+}
+
+const char * Joystick::keyToName(Key key){
+ switch (key){
+ case Invalid : return "Invalid";
+ case Up : return "Up";
+ case Down : return "Down";
+ case Left : return "Left";
+ case Right : return "Right";
+ case Button1 : return "Button1";
+ case Button2 : return "Button2";
+ case Button3 : return "Button3";
+ case Button4 : return "Button4";
+ case Quit: return "Quit";
+ }
+ return "Unknown";
+}
+
+void Joystick::pressButton(int button){
+}
+
+void Joystick::releaseButton(int button){
+}
+
+void Joystick::axisMotion(int axis, int motion){
+}
diff --git a/util/input/joystick.h b/util/input/joystick.h
new file mode 100644
index 00000000..f08324ed
--- /dev/null
+++ b/util/input/joystick.h
@@ -0,0 +1,91 @@
+#ifndef _paintown_joystick_h
+#define _paintown_joystick_h
+
+#include <vector>
+
+struct JoystickInput{
+ JoystickInput():
+ left(false),
+ right(false),
+ up(false),
+ down(false),
+ button1(false),
+ button2(false),
+ button3(false),
+ button4(false),
+ quit(false){
+ }
+
+ JoystickInput(const JoystickInput & copy):
+ left(copy.left),
+ right(copy.right),
+ up(copy.up),
+ down(copy.down),
+ button1(copy.button1),
+ button2(copy.button2),
+ button3(copy.button3),
+ button4(copy.button4),
+ quit(copy.quit){
+ }
+
+ /* true if something is pressed */
+ bool pressed(){
+ return left || right || up || down ||
+ button1 || button2 || button3 || button4 ||
+ quit;
+ }
+
+ bool left;
+ bool right;
+ bool up;
+ bool down;
+ bool button1;
+ bool button2;
+ bool button3;
+ bool button4;
+ bool quit;
+};
+
+class Joystick{
+public:
+ virtual void poll() = 0;
+ virtual JoystickInput readAll() = 0;
+ virtual bool pressed();
+ virtual ~Joystick();
+
+ virtual int getDeviceId() const = 0;
+ virtual void pressButton(int button);
+ virtual void releaseButton(int button);
+ virtual void axisMotion(int axis, int motion);
+
+ static Joystick * create();
+
+ enum Key{
+ Invalid = -1,
+ Up = 0,
+ Down,
+ Left,
+ Right,
+ Button1,
+ Button2,
+ Button3,
+ Button4,
+ Quit,
+ };
+
+ typedef Key Event;
+
+ virtual inline const std::vector<Event> & getEvents() const {
+ return events;
+ }
+
+ static const char * keyToName(Key key);
+
+protected:
+
+ std::vector<Event> events;
+
+ Joystick();
+};
+
+#endif
diff --git a/util/input/keyboard.cpp b/util/input/keyboard.cpp
new file mode 100644
index 00000000..2da26fe4
--- /dev/null
+++ b/util/input/keyboard.cpp
@@ -0,0 +1,400 @@
+#ifdef USE_ALLEGRO
+#include "allegro/keyboard.cpp"
+#endif
+#ifdef USE_SDL
+#include "sdl/keyboard.cpp"
+#endif
+
+bool Keyboard::isNumber( int key ){
+ return key == Key_0 ||
+ key == Key_1 ||
+ key == Key_2 ||
+ key == Key_3 ||
+ key == Key_4 ||
+ key == Key_5 ||
+ key == Key_6 ||
+ key == Key_7 ||
+ key == Key_8 ||
+ key == Key_9;
+}
+
+bool Keyboard::isChar( int key ){
+ return key == Key_A ||
+ key == Key_B ||
+ key == Key_C ||
+ key == Key_D ||
+ key == Key_E ||
+ key == Key_F ||
+ key == Key_G ||
+ key == Key_H ||
+ key == Key_I ||
+ key == Key_J ||
+ key == Key_K ||
+ key == Key_L ||
+ key == Key_M ||
+ key == Key_N ||
+ key == Key_O ||
+ key == Key_P ||
+ key == Key_Q ||
+ key == Key_R ||
+ key == Key_S ||
+ key == Key_T ||
+ key == Key_U ||
+ key == Key_V ||
+ key == Key_W ||
+ key == Key_X ||
+ key == Key_Y ||
+ key == Key_Z ||
+ key == Key_MINUS;
+}
+
+bool Keyboard::isAlpha( int key ){
+ return isNumber( key ) || isChar( key );
+}
+
+
+const char * Keyboard::keyToName( int key ){
+ switch ( key ){
+ case Keyboard::Key_A : return "A";
+ case Keyboard::Key_B : return "B";
+ case Keyboard::Key_C : return "C";
+ case Keyboard::Key_D : return "D";
+ case Keyboard::Key_E : return "E";
+ case Keyboard::Key_F : return "F";
+ case Keyboard::Key_G : return "G";
+ case Keyboard::Key_H : return "H";
+ case Keyboard::Key_I : return "I";
+ case Keyboard::Key_J : return "J";
+ case Keyboard::Key_K : return "K";
+ case Keyboard::Key_L : return "L";
+ case Keyboard::Key_M : return "M";
+ case Keyboard::Key_N : return "N";
+ case Keyboard::Key_O : return "O";
+ case Keyboard::Key_P : return "P";
+ case Keyboard::Key_Q : return "Q";
+ case Keyboard::Key_R : return "R";
+ case Keyboard::Key_S : return "S";
+ case Keyboard::Key_T : return "T";
+ case Keyboard::Key_U : return "U";
+ case Keyboard::Key_V : return "V";
+ case Keyboard::Key_W : return "W";
+ case Keyboard::Key_X : return "X";
+ case Keyboard::Key_Y : return "Y";
+ case Keyboard::Key_Z : return "Z";
+ case Keyboard::Key_0 : return "0";
+ case Keyboard::Key_1 : return "1";
+ case Keyboard::Key_2 : return "2";
+ case Keyboard::Key_3 : return "3";
+ case Keyboard::Key_4 : return "4";
+ case Keyboard::Key_5 : return "5";
+ case Keyboard::Key_6 : return "6";
+ case Keyboard::Key_7 : return "7";
+ case Keyboard::Key_8 : return "8";
+ case Keyboard::Key_9 : return "9";
+ case Keyboard::Key_0_PAD : return "0_PAD";
+ case Keyboard::Key_1_PAD : return "1_PAD";
+ case Keyboard::Key_2_PAD : return "2_PAD";
+ case Keyboard::Key_3_PAD : return "3_PAD";
+ case Keyboard::Key_4_PAD : return "4_PAD";
+ case Keyboard::Key_5_PAD : return "5_PAD";
+ case Keyboard::Key_6_PAD : return "6_PAD";
+ case Keyboard::Key_7_PAD : return "7_PAD";
+ case Keyboard::Key_8_PAD : return "8_PAD";
+ case Keyboard::Key_9_PAD : return "9_PAD";
+ case Keyboard::Key_F1 : return "F1";
+ case Keyboard::Key_F2 : return "F2";
+ case Keyboard::Key_F3 : return "F3";
+ case Keyboard::Key_F4 : return "F4";
+ case Keyboard::Key_F5 : return "F5";
+ case Keyboard::Key_F6 : return "F6";
+ case Keyboard::Key_F7 : return "F7";
+ case Keyboard::Key_F8 : return "F8";
+ case Keyboard::Key_F9 : return "F9";
+ case Keyboard::Key_F10 : return "F10";
+ case Keyboard::Key_F11 : return "F11";
+ case Keyboard::Key_F12 : return "F12";
+ case Keyboard::Key_ESC : return "ESC";
+ case Keyboard::Key_TILDE : return "~";
+ case Keyboard::Key_MINUS : return "-";
+ case Keyboard::Key_EQUALS : return "=";
+ case Keyboard::Key_BACKSPACE : return "BACKSPACE";
+ case Keyboard::Key_TAB : return "TAB";
+ case Keyboard::Key_OPENBRACE : return "OPENBRACE";
+ case Keyboard::Key_CLOSEBRACE : return "CLOSEBRACE";
+ case Keyboard::Key_ENTER : return "ENTER";
+ case Keyboard::Key_COLON : return "COLON";
+ case Keyboard::Key_QUOTE : return "QUOTE";
+ case Keyboard::Key_BACKSLASH : return "BACKSLASH";
+ case Keyboard::Key_BACKSLASH2 : return "BACKSLASH2";
+ case Keyboard::Key_COMMA : return "COMMA";
+ case Keyboard::Key_STOP : return ".";
+ case Keyboard::Key_SLASH : return "SLASH";
+ case Keyboard::Key_SPACE : return "SPACE";
+ case Keyboard::Key_INSERT : return "INSERT";
+ case Keyboard::Key_DEL : return "DEL";
+ case Keyboard::Key_HOME : return "HOME";
+ case Keyboard::Key_END : return "END";
+ case Keyboard::Key_PGUP : return "PGUP";
+ case Keyboard::Key_PGDN : return "PGDN";
+ case Keyboard::Key_LEFT : return "LEFT";
+ case Keyboard::Key_RIGHT : return "RIGHT";
+ case Keyboard::Key_UP : return "UP";
+ case Keyboard::Key_DOWN : return "DOWN";
+ case Keyboard::Key_SLASH_PAD : return "SLASH_PAD";
+ case Keyboard::Key_ASTERISK : return "ASTERISK";
+ case Keyboard::Key_MINUS_PAD : return "MINUS_PAD";
+ case Keyboard::Key_PLUS_PAD : return "PLUS_PAD";
+ case Keyboard::Key_DEL_PAD : return "DEL_PAD";
+ case Keyboard::Key_ENTER_PAD : return "ENTER_PAD";
+ case Keyboard::Key_PRTSCR : return "PRTSCR";
+ case Keyboard::Key_PAUSE : return "PAUSE";
+ case Keyboard::Key_ABNT_C1 : return "ABNT_C1";
+ case Keyboard::Key_YEN : return "YEN";
+ case Keyboard::Key_KANA : return "KANA";
+ case Keyboard::Key_CONVERT : return "CONVERT";
+ case Keyboard::Key_NOCONVERT : return "NOCONVERT";
+ case Keyboard::Key_AT : return "AT";
+ case Keyboard::Key_CIRCUMFLEX : return "CIRCUMFLEX";
+ case Keyboard::Key_COLON2 : return "COLON2";
+ case Keyboard::Key_KANJI : return "KANJI";
+ case Keyboard::Key_EQUALS_PAD : return "EQUALS_PAD";
+ case Keyboard::Key_BACKQUOTE : return "BACKQUOTE";
+ case Keyboard::Key_SEMICOLON : return "SEMICOLON";
+ case Keyboard::Key_COMMAND : return "COMMAND";
+ /*
+ case Keyboard::Key_UNKNOWN1 : return "UNKNOWN1";
+ case Keyboard::Key_UNKNOWN2 : return "UNKNOWN2";
+ case Keyboard::Key_UNKNOWN3 : return "UNKNOWN3";
+ case Keyboard::Key_UNKNOWN4 : return "UNKNOWN4";
+ case Keyboard::Key_UNKNOWN5 : return "UNKNOWN5";
+ case Keyboard::Key_UNKNOWN6 : return "UNKNOWN6";
+ case Keyboard::Key_UNKNOWN7 : return "UNKNOWN7";
+ case Keyboard::Key_UNKNOWN8 : return "UNKNOWN8";
+ */
+ // case Keyboard::Key_MODIFIERS : return "MODIFIERS";
+ case Keyboard::Key_LSHIFT : return "LSHIFT";
+ case Keyboard::Key_RSHIFT : return "RSHIFT";
+ case Keyboard::Key_LCONTROL : return "LCONTROL";
+ case Keyboard::Key_RCONTROL : return "RCONTROL";
+ case Keyboard::Key_ALT : return "ALT";
+ case Keyboard::Key_ALTGR : return "ALTGR";
+ case Keyboard::Key_LWIN : return "LWIN";
+ case Keyboard::Key_RWIN : return "RWIN";
+ case Keyboard::Key_MENU : return "MENU";
+ case Keyboard::Key_SCRLOCK : return "SCRLOCK";
+ case Keyboard::Key_NUMLOCK : return "NUMLOCK";
+ case Keyboard::Key_CAPSLOCK : return "CAPSLOCK";
+ default : return "Unknown key";
+ }
+}
+
+void Keyboard::setDelay( const int key, const int delay ){
+ key_delay[ key ] = delay;
+}
+
+void Keyboard::setAllDelay( const int delay ){
+ setDelay( Key_A, delay );
+ setDelay( Key_B, delay );
+ setDelay( Key_C, delay );
+ setDelay( Key_D, delay );
+ setDelay( Key_E, delay );
+ setDelay( Key_F, delay );
+ setDelay( Key_G, delay );
+ setDelay( Key_H, delay );
+ setDelay( Key_I, delay );
+ setDelay( Key_J, delay );
+ setDelay( Key_K, delay );
+ setDelay( Key_L, delay );
+ setDelay( Key_M, delay );
+ setDelay( Key_N, delay );
+ setDelay( Key_O, delay );
+ setDelay( Key_P, delay );
+ setDelay( Key_Q, delay );
+ setDelay( Key_R, delay );
+ setDelay( Key_S, delay );
+ setDelay( Key_T, delay );
+ setDelay( Key_U, delay );
+ setDelay( Key_V, delay );
+ setDelay( Key_W, delay );
+ setDelay( Key_X, delay );
+ setDelay( Key_Y, delay );
+ setDelay( Key_Z, delay );
+ setDelay( Key_0, delay );
+ setDelay( Key_1, delay );
+ setDelay( Key_2, delay );
+ setDelay( Key_3, delay );
+ setDelay( Key_4, delay );
+ setDelay( Key_5, delay );
+ setDelay( Key_6, delay );
+ setDelay( Key_7, delay );
+ setDelay( Key_8, delay );
+ setDelay( Key_9, delay );
+ setDelay( Key_0_PAD, delay );
+ setDelay( Key_1_PAD, delay );
+ setDelay( Key_2_PAD, delay );
+ setDelay( Key_3_PAD, delay );
+ setDelay( Key_4_PAD, delay );
+ setDelay( Key_5_PAD, delay );
+ setDelay( Key_6_PAD, delay );
+ setDelay( Key_7_PAD, delay );
+ setDelay( Key_8_PAD, delay );
+ setDelay( Key_9_PAD, delay );
+ setDelay( Key_F1, delay );
+ setDelay( Key_F2, delay );
+ setDelay( Key_F3, delay );
+ setDelay( Key_F4, delay );
+ setDelay( Key_F5, delay );
+ setDelay( Key_F6, delay );
+ setDelay( Key_F7, delay );
+ setDelay( Key_F8, delay );
+ setDelay( Key_F9, delay );
+ setDelay( Key_F10, delay );
+ setDelay( Key_F11, delay );
+ setDelay( Key_F12, delay );
+ setDelay( Key_ESC, delay );
+ setDelay( Key_TILDE, delay );
+ setDelay( Key_MINUS, delay );
+ setDelay( Key_EQUALS, delay );
+ setDelay( Key_BACKSPACE, delay );
+ setDelay( Key_TAB, delay );
+ setDelay( Key_OPENBRACE, delay );
+ setDelay( Key_CLOSEBRACE, delay );
+ setDelay( Key_ENTER, delay );
+ setDelay( Key_COLON, delay );
+ setDelay( Key_QUOTE, delay );
+ setDelay( Key_BACKSLASH, delay );
+ setDelay( Key_BACKSLASH2, delay );
+ setDelay( Key_COMMA, delay );
+ setDelay( Key_STOP, delay );
+ setDelay( Key_SLASH, delay );
+ setDelay( Key_SPACE, delay );
+ setDelay( Key_INSERT, delay );
+ setDelay( Key_DEL, delay );
+ setDelay( Key_HOME, delay );
+ setDelay( Key_END, delay );
+ setDelay( Key_PGUP, delay );
+ setDelay( Key_PGDN, delay );
+ setDelay( Key_LEFT, delay );
+ setDelay( Key_RIGHT, delay );
+ setDelay( Key_UP, delay );
+ setDelay( Key_DOWN, delay );
+ setDelay( Key_SLASH_PAD, delay );
+ setDelay( Key_ASTERISK, delay );
+ setDelay( Key_MINUS_PAD, delay );
+ setDelay( Key_PLUS_PAD, delay );
+ setDelay( Key_DEL_PAD, delay );
+ setDelay( Key_ENTER_PAD, delay );
+ setDelay( Key_PRTSCR, delay );
+ setDelay( Key_PAUSE, delay );
+ setDelay( Key_ABNT_C1, delay );
+ setDelay( Key_YEN, delay );
+ setDelay( Key_KANA, delay );
+ setDelay( Key_CONVERT, delay );
+ setDelay( Key_NOCONVERT, delay );
+ setDelay( Key_AT, delay );
+ setDelay( Key_CIRCUMFLEX, delay );
+ setDelay( Key_COLON2, delay );
+ setDelay( Key_KANJI, delay );
+ setDelay( Key_EQUALS_PAD, delay );
+ setDelay( Key_BACKQUOTE, delay );
+ setDelay( Key_SEMICOLON, delay );
+ setDelay( Key_COMMAND, delay );
+ /*
+ setDelay( Key_UNKNOWN1, delay );
+ setDelay( Key_UNKNOWN2, delay );
+ setDelay( Key_UNKNOWN3, delay );
+ setDelay( Key_UNKNOWN4, delay );
+ setDelay( Key_UNKNOWN5, delay );
+ setDelay( Key_UNKNOWN6, delay );
+ setDelay( Key_UNKNOWN7, delay );
+ setDelay( Key_UNKNOWN8, delay );
+ */
+ setDelay( Key_MODIFIERS, delay );
+ setDelay( Key_LSHIFT, delay );
+ setDelay( Key_RSHIFT, delay );
+ setDelay( Key_LCONTROL, delay );
+ setDelay( Key_RCONTROL, delay );
+ setDelay( Key_ALT, delay );
+ setDelay( Key_ALTGR, delay );
+ setDelay( Key_LWIN, delay );
+ setDelay( Key_RWIN, delay );
+ setDelay( Key_MENU, delay );
+ setDelay( Key_SCRLOCK, delay );
+ setDelay( Key_NUMLOCK, delay );
+ setDelay( Key_CAPSLOCK, delay );
+}
+
+void Keyboard::press(KeyType key, unicode_t unicode){
+ keyState[key].key = key;
+ keyState[key].unicode = unicode;
+ keyState[key].enabled = true;
+ // if (enableBuffer){
+ buffer.push_back(keyState[key]);
+ // }
+ /*
+ KeyData data(key, unicode, true);
+ for (std::vector<Observer>::iterator it = observers.begin(); it != observers.end(); it++){
+ Observer observer = (*it);
+ observer.callback(data, observer.extra);
+ }
+ */
+}
+
+void Keyboard::release(KeyType key){
+ keyState[key].enabled = false;
+ buffer.push_back(keyState[key]);
+ /*
+ KeyData data(key, 0, false);
+ for (std::vector<Observer>::iterator it = observers.begin(); it != observers.end(); it++){
+ Observer observer = (*it);
+ observer.callback(data, observer.extra);
+ }
+ */
+}
+
+void Keyboard::readBufferedKeys(std::vector<int> & keys){
+ for (std::vector<KeyData>::iterator it = buffer.begin(); it != buffer.end(); it++){
+ const KeyData & data = *it;
+ keys.push_back(data.key);
+ }
+}
+
+std::vector<Keyboard::KeyData> Keyboard::readData(){
+ std::vector<Keyboard::KeyData> out;
+ for (std::map<KeyType, KeyData>::iterator it = keyState.begin(); it != keyState.end(); it++){
+ KeyType key = it->first;
+ const KeyData & data = it->second;
+ if (data.enabled){
+ out.push_back(data);
+ }
+ }
+ return out;
+}
+
+std::vector<Keyboard::unicode_t> Keyboard::readText(){
+ std::vector<Keyboard::unicode_t> out;
+ for (std::map<KeyType, KeyData>::iterator it = keyState.begin(); it != keyState.end(); it++){
+ KeyType key = it->first;
+ const KeyData & data = it->second;
+ if (data.enabled){
+ out.push_back(data.unicode);
+ }
+ }
+ return out;
+}
+
+/*
+void Keyboard::addObserver(ObserverCallback observer, void * data){
+ observers.push_back(Observer(observer, data));
+}
+
+void Keyboard::removeObserver(ObserverCallback observer, void * data){
+ for (std::vector<Observer>::iterator it = observers.begin(); it != observers.end(); it++){
+ const Observer & what = *it;
+ if (what.callback == observer && what.extra == data){
+ observers.erase(it);
+ break;
+ }
+ }
+}
+*/
diff --git a/util/input/keyboard.h b/util/input/keyboard.h
new file mode 100644
index 00000000..a9ec1735
--- /dev/null
+++ b/util/input/keyboard.h
@@ -0,0 +1,261 @@
+#ifndef _paintown_keyboard_h
+#define _paintown_keyboard_h
+
+#include <map>
+#include <vector>
+#include <stdint.h>
+
+/* handles allegro key[] array better than keypressed()
+ * and readkey()
+ */
+class Keyboard{
+private:
+ Keyboard();
+public:
+ friend class InputManager;
+
+ typedef const int KeyType;
+ typedef uint32_t unicode_t;
+
+ struct KeyData{
+ KeyData():
+ key(-1),
+ unicode(-1),
+ enabled(false){
+ }
+
+ KeyData(int key, unicode_t unicode, bool enabled):
+ key(key),
+ unicode(unicode),
+ enabled(enabled){
+ }
+
+ int key;
+ /* Converted to a unicode character in UTF-32 */
+ unicode_t unicode;
+ /* whether the key is being pressed */
+ bool enabled;
+ };
+
+ /*
+ typedef void (*ObserverCallback)(const KeyData & data, void * extra);
+ struct Observer{
+ Observer():
+ callback(NULL),
+ extra(NULL){
+ }
+
+ Observer(ObserverCallback callback, void * extra):
+ callback(callback),
+ extra(extra){
+ }
+
+ ObserverCallback callback;
+ void * extra;
+ };
+ */
+
+ /* poll:
+ * Put the keys in Allegro's key[] array into our map of int -> bool
+ */
+ void poll();
+
+ /* wait for all keys to be released */
+ void wait();
+
+ /* []:
+ * Extract a boolean value given a key number
+ */
+#if 0
+ inline bool operator[] ( const int i ){
+
+ /* if the key has been pressed for the first time return true */
+ if ( my_keys[ i ] < 0 ){
+ my_keys[ i ] = 1;
+ return true;
+ }
+
+ bool b = my_keys[ i ] > key_delay[ i ];
+ if ( b ){
+ my_keys[ i ] = 1;
+ }
+ return b;
+ }
+#endif
+
+ /* keypressed:
+ * Returns true if a key is pressed
+ */
+ bool keypressed();
+
+ /* readKeys:
+ * Store all pressed keys in a user supplied vector
+ */
+ void readKeys(std::vector< int > & all_keys);
+ void readBufferedKeys(std::vector<int> & keys);
+ std::vector<KeyData> readData();
+ std::vector<unicode_t> readText();
+
+ // int readKey();
+ void clear();
+
+ void setDelay( const int key, const int delay );
+ void setAllDelay( const int delay );
+
+ inline const std::vector<KeyData> & getBufferedKeys() const {
+ return buffer;
+ }
+
+ static const char * keyToName( int key );
+ static bool isNumber( int key );
+ static bool isChar( int key );
+ static bool isAlpha( int key );
+
+ static KeyType Key_A;
+ static KeyType Key_B;
+ static KeyType Key_C;
+ static KeyType Key_D;
+ static KeyType Key_E;
+ static KeyType Key_F;
+ static KeyType Key_G;
+ static KeyType Key_H;
+ static KeyType Key_I;
+ static KeyType Key_J;
+ static KeyType Key_K;
+ static KeyType Key_L;
+ static KeyType Key_M;
+ static KeyType Key_N;
+ static KeyType Key_O;
+ static KeyType Key_P;
+ static KeyType Key_Q;
+ static KeyType Key_R;
+ static KeyType Key_S;
+ static KeyType Key_T;
+ static KeyType Key_U;
+ static KeyType Key_V;
+ static KeyType Key_W;
+ static KeyType Key_X;
+ static KeyType Key_Y;
+ static KeyType Key_Z;
+ static KeyType Key_0;
+ static KeyType Key_1;
+ static KeyType Key_2;
+ static KeyType Key_3;
+ static KeyType Key_4;
+ static KeyType Key_5;
+ static KeyType Key_6;
+ static KeyType Key_7;
+ static KeyType Key_8;
+ static KeyType Key_9;
+ static KeyType Key_0_PAD;
+ static KeyType Key_1_PAD;
+ static KeyType Key_2_PAD;
+ static KeyType Key_3_PAD;
+ static KeyType Key_4_PAD;
+ static KeyType Key_5_PAD;
+ static KeyType Key_6_PAD;
+ static KeyType Key_7_PAD;
+ static KeyType Key_8_PAD;
+ static KeyType Key_9_PAD;
+ static KeyType Key_F1;
+ static KeyType Key_F2;
+ static KeyType Key_F3;
+ static KeyType Key_F4;
+ static KeyType Key_F5;
+ static KeyType Key_F6;
+ static KeyType Key_F7;
+ static KeyType Key_F8;
+ static KeyType Key_F9;
+ static KeyType Key_F10;
+ static KeyType Key_F11;
+ static KeyType Key_F12;
+ static KeyType Key_ESC;
+ static KeyType Key_TILDE;
+ static KeyType Key_MINUS;
+ static KeyType Key_EQUALS;
+ static KeyType Key_BACKSPACE;
+ static KeyType Key_TAB;
+ static KeyType Key_OPENBRACE;
+ static KeyType Key_CLOSEBRACE;
+ static KeyType Key_ENTER;
+ static KeyType Key_COLON;
+ static KeyType Key_QUOTE;
+ static KeyType Key_BACKSLASH;
+ static KeyType Key_BACKSLASH2;
+ static KeyType Key_COMMA;
+ static KeyType Key_STOP;
+ static KeyType Key_SLASH;
+ static KeyType Key_SPACE;
+ static KeyType Key_INSERT;
+ static KeyType Key_DEL;
+ static KeyType Key_HOME;
+ static KeyType Key_END;
+ static KeyType Key_PGUP;
+ static KeyType Key_PGDN;
+ static KeyType Key_LEFT;
+ static KeyType Key_RIGHT;
+ static KeyType Key_UP;
+ static KeyType Key_DOWN;
+ static KeyType Key_SLASH_PAD;
+ static KeyType Key_ASTERISK;
+ static KeyType Key_MINUS_PAD;
+ static KeyType Key_PLUS_PAD;
+ static KeyType Key_DEL_PAD;
+ static KeyType Key_ENTER_PAD;
+ static KeyType Key_PRTSCR;
+ static KeyType Key_PAUSE;
+ static KeyType Key_ABNT_C1;
+ static KeyType Key_YEN;
+ static KeyType Key_KANA;
+ static KeyType Key_CONVERT;
+ static KeyType Key_NOCONVERT;
+ static KeyType Key_AT;
+ static KeyType Key_CIRCUMFLEX;
+ static KeyType Key_COLON2;
+ static KeyType Key_KANJI;
+ static KeyType Key_EQUALS_PAD;
+ static KeyType Key_BACKQUOTE;
+ static KeyType Key_SEMICOLON;
+ static KeyType Key_COMMAND;
+ /*
+ static KeyType Key_UNKNOWN1;
+ static KeyType Key_UNKNOWN2;
+ static KeyType Key_UNKNOWN3;
+ static KeyType Key_UNKNOWN4;
+ static KeyType Key_UNKNOWN5;
+ static KeyType Key_UNKNOWN6;
+ static KeyType Key_UNKNOWN7;
+ static KeyType Key_UNKNOWN8;
+ */
+ static KeyType Key_MODIFIERS;
+ static KeyType Key_LSHIFT;
+ static KeyType Key_RSHIFT;
+ static KeyType Key_LCONTROL;
+ static KeyType Key_RCONTROL;
+ static KeyType Key_ALT;
+ static KeyType Key_ALTGR;
+ static KeyType Key_LWIN;
+ static KeyType Key_RWIN;
+ static KeyType Key_MENU;
+ static KeyType Key_SCRLOCK;
+ static KeyType Key_NUMLOCK;
+ static KeyType Key_CAPSLOCK;
+
+ void press(KeyType key, unicode_t unicode);
+ void release(KeyType key);
+ /*
+ virtual void addObserver(ObserverCallback observer, void * extra);
+ virtual void removeObserver(ObserverCallback observer, void * extra);
+ */
+
+protected:
+ // std::map<int,int> my_keys;
+ std::map<int,int> key_delay;
+ // std::vector<Observer> observers;
+
+ std::map<KeyType, KeyData> keyState;
+ std::vector<KeyData> buffer;
+ bool enableBuffer;
+};
+
+#endif
diff --git a/util/input/linux_joystick.cpp b/util/input/linux_joystick.cpp
new file mode 100644
index 00000000..ef26c57f
--- /dev/null
+++ b/util/input/linux_joystick.cpp
@@ -0,0 +1,406 @@
+#ifdef LINUX
+
+/* based on
+ * jstest.c Version 1.2
+ *
+ * Copyright (c) 1996-1999 Vojtech Pavlik
+ *
+ * Sponsored by SuSE
+ */
+
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <iostream>
+#include <sstream>
+
+#include <linux/input.h>
+#include <linux/joystick.h>
+
+#include "linux_joystick.h"
+#include "util/debug.h"
+
+using namespace std;
+
+static const char *axis_names[ABS_MAX + 1] = {
+"X", "Y", "Z", "Rx", "Ry", "Rz", "Throttle", "Rudder",
+"Wheel", "Gas", "Brake", "?", "?", "?", "?", "?",
+"Hat0X", "Hat0Y", "Hat1X", "Hat1Y", "Hat2X", "Hat2Y", "Hat3X", "Hat3Y",
+"?", "?", "?", "?", "?", "?", "?",
+};
+
+static const char *button_names[KEY_MAX - BTN_MISC + 1] = {
+"Btn0", "Btn1", "Btn2", "Btn3", "Btn4", "Btn5", "Btn6", "Btn7", "Btn8", "Btn9", "?", "?", "?", "?", "?", "?",
+"LeftBtn", "RightBtn", "MiddleBtn", "SideBtn", "ExtraBtn", "ForwardBtn", "BackBtn", "TaskBtn", "?", "?", "?", "?", "?", "?", "?", "?",
+"Trigger", "ThumbBtn", "ThumbBtn2", "TopBtn", "TopBtn2", "PinkieBtn", "BaseBtn", "BaseBtn2", "BaseBtn3", "BaseBtn4", "BaseBtn5", "BaseBtn6", "BtnDead",
+"BtnA", "BtnB", "BtnC", "BtnX", "BtnY", "BtnZ", "BtnTL", "BtnTR", "BtnTL2", "BtnTR2", "BtnSelect", "BtnStart", "BtnMode", "BtnThumbL", "BtnThumbR", "?",
+"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
+"WheelBtn", "Gear up",
+};
+
+/* tries to open one /dev/input/jsX and return an open file descriptor */
+static int read_joystick(){
+ for (int num = 0; num < 100; num++){
+ ostringstream name;
+ name << "/dev/input/js" << num;
+ const char * cname = name.str().c_str();
+ int fd = open(cname, O_RDONLY);
+ if (fd >= 0){
+ return fd;
+ }
+ }
+ return -1;
+}
+
+LinuxJoystick::LinuxJoystick():
+button(0),
+axis(0){
+ file = read_joystick();
+ if (file == -1){
+ Global::debug(0) << "Could not open joystick" << endl;
+ } else {
+ Global::debug(1) << "Opened joystick " << endl;
+
+ /* grab useful info */
+ ioctl(file, JSIOCGVERSION, &version);
+ ioctl(file, JSIOCGAXES, &axes);
+ ioctl(file, JSIOCGBUTTONS, &buttons);
+ ioctl(file, JSIOCGNAME(NAME_LENGTH), name);
+ ioctl(file, JSIOCGAXMAP, axmap);
+ ioctl(file, JSIOCGBTNMAP, btnmap);
+
+ /* put joystick in nonblocking mode */
+ fcntl(file, F_SETFL, O_NONBLOCK);
+
+ axis = new int[axes];
+ memset(axis, 0, sizeof(int) * axes);
+ button = new char[buttons];
+ memset(button, 0, sizeof(char) * buttons);
+
+ Global::debug(1) << "Joystick axis: " << (int)axes << " buttons: " << (int)buttons << endl;
+ }
+}
+
+LinuxJoystick::~LinuxJoystick(){
+ delete[] axis;
+ delete[] button;
+ if (file != -1){
+ close(file);
+ }
+}
+
+void LinuxJoystick::poll(){
+
+ struct js_event js;
+
+ if (file == -1){
+ return;
+ }
+
+ /* from an email by Vojtech Pavlik:
+ * "if you #include <linux/joystick.h>, the struct is defined in such a way
+ * that gcc doesn't add padding."
+ */
+ int bytes = read(file, &js, sizeof(struct js_event));
+ if (bytes == sizeof(struct js_event)){
+ Global::debug(4) << "Event: type " << (int)js.type << " time " << (int)js.time << " number " << (int)js.number << " value " << (int)js.value << endl;
+
+ if (errno != EAGAIN) {
+ perror("joystick: error reading");
+ return;
+ }
+
+ switch (js.type & ~JS_EVENT_INIT) {
+ case JS_EVENT_BUTTON:
+ button[js.number] = js.value;
+ break;
+ case JS_EVENT_AXIS:
+ axis[js.number] = js.value;
+ break;
+ }
+ }
+}
+
+bool LinuxJoystick::pressed(){
+ if (file == -1){
+ return false;
+ }
+
+ for (int i = 0; i < axes; i++){
+ if (axis[i]){
+ return true;
+ }
+ }
+ for (int i = 0; i < buttons; i++){
+ if (button[i]){
+ return true;
+ }
+ }
+ return false;
+}
+
+JoystickInput LinuxJoystick::readAll(){
+ JoystickInput input;
+ if (file == -1){
+ return input;
+ }
+ if (axes > 0){
+ if (axis[0] < 0){
+ input.left = true;
+ }
+ if (axis[0] > 0){
+ input.right = true;
+ }
+ if (axes > 1){
+ if (axis[1] < 0){
+ input.up = true;
+ }
+ if (axis[1] > 0){
+ input.down = true;
+ }
+ }
+ }
+
+ if (buttons > 0 && button[0]){
+ input.button1 = true;
+ }
+ if (buttons > 1 && button[1]){
+ input.button2 = true;
+ }
+ if (buttons > 2 && button[2]){
+ input.button3 = true;
+ }
+ if (buttons > 3 && button[3]){
+ input.button4 = true;
+ }
+
+ Global::debug(1) << "joystick input up " << input.up
+ << " down " << input.down
+ << " left " << input.left
+ << " right " << input.right
+ << " button1 " << input.button1
+ << " button2 " << input.button2
+ << " button3 " << input.button3
+ << " button4 " << input.button4
+ << endl;
+ return input;
+}
+
+#if 0
+int main (int argc, char **argv)
+{
+ int fd, i;
+ unsigned char axes = 2;
+ unsigned char buttons = 2;
+ int version = 0x000800;
+ char name[NAME_LENGTH] = "Unknown";
+ uint16_t btnmap[KEY_MAX - BTN_MISC + 1];
+ uint8_t axmap[ABS_MAX + 1];
+
+ if (argc < 2 || argc > 3 || !strcmp("--help", argv[1])) {
+ puts("");
+ puts("Usage: jstest [<mode>] <device>");
+ puts("");
+ puts("Modes:");
+ puts(" --normal One-line mode showing immediate status");
+ puts(" --old Same as --normal, using 0.x interface");
+ puts(" --event Prints events as they come in");
+ puts(" --nonblock Same as --event, in nonblocking mode");
+ puts(" --select Same as --event, using select() call");
+ puts("");
+ return 1;
+ }
+ if ((fd = open(argv[argc - 1], O_RDONLY)) < 0) {
+ perror("jstest");
+ return 1;
+ }
+
+ ioctl(fd, JSIOCGVERSION, &version);
+ ioctl(fd, JSIOCGAXES, &axes);
+ ioctl(fd, JSIOCGBUTTONS, &buttons);
+ ioctl(fd, JSIOCGNAME(NAME_LENGTH), name);
+ ioctl(fd, JSIOCGAXMAP, axmap);
+ ioctl(fd, JSIOCGBTNMAP, btnmap);
+
+
+ printf("Driver version is %d.%d.%d.\n",
+ version >> 16, (version >> 8) & 0xff, version & 0xff);
+
+ printf("Joystick (%s) has %d axes (", name, axes);
+ for (i = 0; i < axes; i++)
+ printf("%s%s", i > 0 ? ", " : "", axis_names[axmap[i]]);
+ puts(")");
+
+ printf("and %d buttons (", buttons);
+ for (i = 0; i < buttons; i++)
+ printf("%s%s", i > 0 ? ", " : "", button_names[btnmap[i] - BTN_MISC]);
+ puts(").");
+
+ printf("Testing ... (interrupt to exit)\n");
+
+/*
+ * Old (0.x) interface.
+ */
+
+ if ((argc == 2 && version < 0x010000) || !strcmp("--old", argv[1])) {
+
+ struct JS_DATA_TYPE js;
+
+ while (1) {
+
+ if (read(fd, &js, JS_RETURN) != JS_RETURN) {
+ perror("\njstest: error reading");
+ return 1;
+ }
+
+ printf("Axes: X:%3d Y:%3d Buttons: A:%s B:%s\r",
+ js.x, js.y, (js.buttons & 1) ? "on " : "off", (js.buttons & 2) ? "on " : "off");
+
+ fflush(stdout);
+
+ usleep(10000);
+ }
+ }
+
+/*
+ * Event interface, single line readout.
+ */
+
+ if (argc == 2 || !strcmp("--normal", argv[1])) {
+
+ int *axis;
+ char *button;
+ int i;
+ struct js_event js;
+
+ axis = calloc(axes, sizeof(int));
+ button = calloc(buttons, sizeof(char));
+
+ while (1) {
+ if (read(fd, &js, sizeof(struct js_event)) != sizeof(struct js_event)) {
+ perror("\njstest: error reading");
+ return 1;
+ }
+
+ switch(js.type & ~JS_EVENT_INIT) {
+ case JS_EVENT_BUTTON:
+ button[js.number] = js.value;
+ break;
+ case JS_EVENT_AXIS:
+ axis[js.number] = js.value;
+ break;
+ }
+
+ printf("\r");
+
+ if (axes) {
+ printf("Axes: ");
+ for (i = 0; i < axes; i++)
+ printf("%2d:%6d ", i, axis[i]);
+ }
+
+ if (buttons) {
+ printf("Buttons: ");
+ for (i = 0; i < buttons; i++)
+ printf("%2d:%s ", i, button[i] ? "on " : "off");
+ }
+
+ fflush(stdout);
+ }
+ }
+
+
+/*
+ * Event interface, events being printed.
+ */
+
+ if (!strcmp("--event", argv[1])) {
+
+ struct js_event js;
+
+ while (1) {
+ if (read(fd, &js, sizeof(struct js_event)) != sizeof(struct js_event)) {
+ perror("\njstest: error reading");
+ return 1;
+ }
+
+ printf("Event: type %d, time %d, number %d, value %d\n",
+ js.type, js.time, js.number, js.value);
+
+ fflush(stdout);
+ }
+ }
+
+/*
+ * Reading in nonblocking mode.
+ */
+
+ if (!strcmp("--nonblock", argv[1])) {
+
+ struct js_event js;
+
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+
+ while (1) {
+
+ while (read(fd, &js, sizeof(struct js_event)) == sizeof(struct js_event)) {
+ printf("Event: type %d, time %d, number %d, value %d\n",
+ js.type, js.time, js.number, js.value);
+ }
+
+ if (errno != EAGAIN) {
+ perror("\njstest: error reading");
+ return 1;
+ }
+
+ usleep(10000);
+ }
+ }
+
+/*
+ * Using select() on joystick fd.
+ */
+
+ if (!strcmp("--select", argv[1])) {
+
+ struct js_event js;
+ struct timeval tv;
+ fd_set set;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ while (1) {
+
+ FD_ZERO(&set);
+ FD_SET(fd, &set);
+
+ if (select(fd+1, &set, NULL, NULL, &tv)) {
+
+ if (read(fd, &js, sizeof(struct js_event)) != sizeof(struct js_event)) {
+ perror("\njstest: error reading");
+ return 1;
+ }
+
+ printf("Event: type %d, time %d, number %d, value %d\n",
+ js.type, js.time, js.number, js.value);
+
+ }
+
+ }
+ }
+
+ printf("jstest: unknown mode: %s\n", argv[1]);
+ return -1;
+}
+#endif
+
+#endif
diff --git a/util/input/linux_joystick.h b/util/input/linux_joystick.h
new file mode 100644
index 00000000..8c528628
--- /dev/null
+++ b/util/input/linux_joystick.h
@@ -0,0 +1,36 @@
+#ifdef LINUX
+
+#include "joystick.h"
+
+#include <stdint.h>
+#include <vector>
+#include <linux/input.h>
+#include <linux/joystick.h>
+
+#define NAME_LENGTH 1024
+
+class LinuxJoystick: public Joystick {
+public:
+ virtual void poll();
+ virtual JoystickInput readAll();
+ virtual bool pressed();
+
+ virtual ~LinuxJoystick();
+
+ friend class Joystick;
+protected:
+ LinuxJoystick();
+
+ /* file descriptor for /dev/input/jsX */
+ int file;
+ char name[NAME_LENGTH];
+ unsigned char axes;
+ unsigned char buttons;
+ int version;
+ uint16_t btnmap[KEY_MAX - BTN_MISC + 1];
+ uint8_t axmap[ABS_MAX + 1];
+ char * button;
+ int * axis;
+};
+
+#endif
diff --git a/util/input/psp/joystick.cpp b/util/input/psp/joystick.cpp
new file mode 100644
index 00000000..5008175a
--- /dev/null
+++ b/util/input/psp/joystick.cpp
@@ -0,0 +1,54 @@
+#ifdef MINPSPW
+
+#include "joystick.h"
+
+void PSPJoystick::poll(){
+ sceCtrlPeekBufferPositive(&joystick, 1);
+}
+
+int PSPJoystick::getDeviceId() const {
+ /* FIXME */
+ return 0;
+}
+
+JoystickInput PSPJoystick::readAll(){
+ JoystickInput input;
+ if(joystick.Buttons != 0){
+ if(joystick.Buttons & PSP_CTRL_START){
+ //input.button7 = true;
+ } else if(joystick.Buttons & PSP_CTRL_SELECT){
+ //input.button8 = true;
+ } else if(joystick.Buttons & PSP_CTRL_SQUARE){
+ input.button1 = true;
+ } else if(joystick.Buttons & PSP_CTRL_CROSS){
+ input.button2 = true;
+ } else if(joystick.Buttons & PSP_CTRL_TRIANGLE){
+ input.button3 = true;
+ } else if(joystick.Buttons & PSP_CTRL_CIRCLE){
+ input.button4 = true;
+ } else if(joystick.Buttons & PSP_CTRL_RTRIGGER){
+ } else if(joystick.Buttons & PSP_CTRL_LTRIGGER){
+ } else if(joystick.Buttons & PSP_CTRL_LEFT){
+ input.left = true;
+ } else if(joystick.Buttons & PSP_CTRL_RIGHT){
+ input.right = true;
+ } else if(joystick.Buttons & PSP_CTRL_DOWN){
+ input.down = true;
+ } else if(joystick.Buttons & PSP_CTRL_UP){
+ input.up = true;
+ }
+ }
+
+ return input;
+}
+
+PSPJoystick::~PSPJoystick(){
+ // no cleanup required
+}
+
+PSPJoystick::PSPJoystick(){
+ sceCtrlSetSamplingCycle(0);
+ sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
+}
+
+#endif
diff --git a/util/input/psp/joystick.h b/util/input/psp/joystick.h
new file mode 100644
index 00000000..c08770a3
--- /dev/null
+++ b/util/input/psp/joystick.h
@@ -0,0 +1,27 @@
+#ifndef _paintown_psp_joystick_h
+#define _paintown_psp_joystick_h
+
+#ifdef MINPSPW
+
+#include "../joystick.h"
+
+#include <pspctrl.h>
+
+class PSPJoystick: public Joystick {
+public:
+ virtual void poll();
+ virtual JoystickInput readAll();
+ virtual int getDeviceId() const;
+
+ virtual ~PSPJoystick();
+
+ friend class Joystick;
+protected:
+ PSPJoystick();
+ // joystick
+ SceCtrlData joystick;
+};
+
+#endif
+
+#endif
diff --git a/util/input/sdl/joystick.cpp b/util/input/sdl/joystick.cpp
new file mode 100644
index 00000000..a3711b82
--- /dev/null
+++ b/util/input/sdl/joystick.cpp
@@ -0,0 +1,142 @@
+#ifdef USE_SDL
+
+#include <SDL.h>
+#include "joystick.h"
+
+void SDLJoystick::poll(){
+ events.clear();
+}
+
+static bool read_button(SDL_Joystick * joystick, int button){
+ return SDL_JoystickGetButton(joystick, button);
+}
+
+JoystickInput SDLJoystick::readAll(){
+ JoystickInput input;
+ if (joystick){
+ int buttons = SDL_JoystickNumButtons(joystick);
+ switch (buttons > 5 ? 5 : buttons){
+ case 5: input.quit = read_button(joystick, 4);
+ case 4: input.button4 = read_button(joystick, 3);
+ case 3: input.button3 = read_button(joystick, 2);
+ case 2: input.button2 = read_button(joystick, 1);
+ case 1: input.button1 = read_button(joystick, 0);
+ case 0: {
+ break;
+ }
+ }
+ }
+
+ int axis = SDL_JoystickNumAxes(joystick);
+ if (axis > 0){
+ int position = SDL_JoystickGetAxis(joystick, 0);
+ if (position < 0){
+ input.left = true;
+ } else if (position > 0){
+ input.right = true;
+ }
+ }
+
+ if (axis > 1){
+ int position = SDL_JoystickGetAxis(joystick, 1);
+ if (position < 0){
+ input.up = true;
+ } else if (position > 0){
+ input.down = true;
+ }
+ }
+
+ int hats = SDL_JoystickNumHats(joystick);
+ if (hats > 0){
+ int hat = SDL_JoystickGetHat(joystick, 0);
+ if ((hat & SDL_HAT_UP) == SDL_HAT_UP){
+ input.up = true;
+ }
+ if ((hat & SDL_HAT_DOWN) == SDL_HAT_DOWN){
+ input.down = true;
+ }
+ if ((hat & SDL_HAT_LEFT) == SDL_HAT_LEFT){
+ input.left = true;
+ }
+ if ((hat & SDL_HAT_RIGHT) == SDL_HAT_RIGHT){
+ input.right = true;
+ }
+ if ((hat & SDL_HAT_RIGHTUP) == SDL_HAT_RIGHTUP){
+ input.right = true;
+ input.up = true;
+ }
+ if ((hat & SDL_HAT_RIGHTDOWN) == SDL_HAT_RIGHTDOWN){
+ input.right = true;
+ input.down = true;
+ }
+ if ((hat & SDL_HAT_LEFTDOWN) == SDL_HAT_LEFTDOWN){
+ input.left = true;
+ input.down = true;
+ }
+ if ((hat & SDL_HAT_LEFTUP) == SDL_HAT_LEFTUP){
+ input.left = true;
+ input.up = true;
+ }
+ }
+
+ return input;
+}
+
+SDLJoystick::~SDLJoystick(){
+ if (joystick){
+ SDL_JoystickClose(joystick);
+ }
+}
+
+SDLJoystick::SDLJoystick():
+joystick(NULL){
+ if (SDL_NumJoysticks() > 0){
+ joystick = SDL_JoystickOpen(0);
+ }
+}
+
+void SDLJoystick::pressButton(int button){
+ if (joystick){
+ Event event = Invalid;
+ switch (button){
+ case 0: event = Button1; break;
+ case 1: event = Button2; break;
+ case 2: event = Button3; break;
+ case 3: event = Button4; break;
+ case 4: event = Quit; break;
+ default: break;
+ }
+ events.push_back(event);
+ }
+}
+
+void SDLJoystick::releaseButton(int button){
+}
+
+void SDLJoystick::axisMotion(int axis, int motion){
+ if (joystick){
+ if (axis == 0){
+ if (motion < 0){
+ events.push_back(Left);
+ } else if (motion > 0){
+ events.push_back(Right);
+ }
+ } else if (axis == 1){
+ if (motion < 0){
+ events.push_back(Up);
+ } else if (motion > 0){
+ events.push_back(Down);
+ }
+ }
+ }
+}
+
+int SDLJoystick::getDeviceId() const {
+ if (joystick){
+ return SDL_JoystickIndex(joystick);
+ }
+
+ return -1;
+}
+
+#endif
diff --git a/util/input/sdl/joystick.h b/util/input/sdl/joystick.h
new file mode 100644
index 00000000..cf4c3d32
--- /dev/null
+++ b/util/input/sdl/joystick.h
@@ -0,0 +1,28 @@
+#ifndef _paintown_sdl_joystick_h
+#define _paintown_sdl_joystick_h
+
+#ifdef USE_SDL
+
+#include <SDL.h>
+#include "../joystick.h"
+
+class SDLJoystick: public Joystick {
+public:
+ virtual void poll();
+ virtual JoystickInput readAll();
+ virtual int getDeviceId() const;
+ virtual void pressButton(int button);
+ virtual void releaseButton(int button);
+ virtual void axisMotion(int axis, int motion);
+
+ virtual ~SDLJoystick();
+
+ friend class Joystick;
+protected:
+ SDLJoystick();
+ SDL_Joystick * joystick;
+};
+
+#endif
+
+#endif
diff --git a/util/input/sdl/keyboard.cpp b/util/input/sdl/keyboard.cpp
new file mode 100644
index 00000000..f720e801
--- /dev/null
+++ b/util/input/sdl/keyboard.cpp
@@ -0,0 +1,196 @@
+#include <SDL.h>
+#include "../keyboard.h"
+#include "../input-manager.h"
+#include "util/funcs.h"
+
+Keyboard::Keyboard():
+enableBuffer(false){
+}
+
+void Keyboard::poll(){
+ buffer.clear();
+ SDL_PumpEvents();
+}
+
+void Keyboard::wait(){
+ while (keypressed()){
+ Util::rest(1);
+ poll();
+ }
+}
+
+bool Keyboard::keypressed(){
+ int keys = 0;
+ Uint8 * state = SDL_GetKeyState(&keys);
+ for (int i = 0; i < keys; i++){
+ if (i != SDLK_NUMLOCK && state[i] == 1){
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#if 0
+void Keyboard::readKeys( std::vector<int> & all_keys ){
+ int keys = 0;
+ Uint8 * state = SDL_GetKeyState(&keys);
+ /* FIXME: the mapping between SDLK_* and our keyboard values are not 1-1 so
+ * use a function here that returns the right mapping.
+ */
+ for (int i = 0; i < keys; i++){
+ if (i != SDLK_NUMLOCK && state[i] == 1){
+ all_keys.push_back(i);
+ }
+ }
+}
+#endif
+
+void Keyboard::readKeys(std::vector<int> & all_keys){
+ for (std::map<KeyType, KeyData>::iterator it = keyState.begin(); it != keyState.end(); it++){
+ KeyType key = it->first;
+ const KeyData & data = it->second;
+ if (data.enabled){
+ all_keys.push_back(key);
+ }
+ }
+}
+
+/*
+int Keyboard::readKey(){
+ std::vector<int> keys;
+ do{
+ readKeys(keys);
+ Util::rest(1);
+ InputManager::poll();
+ poll();
+ } while (keys.size() == 0);
+ return keys.front();
+}
+*/
+
+void Keyboard::clear(){
+ buffer.clear();
+ keyState.clear();
+}
+
+Keyboard::KeyType Keyboard::Key_A = SDLK_a;
+Keyboard::KeyType Keyboard::Key_B = SDLK_b;
+Keyboard::KeyType Keyboard::Key_C = SDLK_c;
+Keyboard::KeyType Keyboard::Key_D = SDLK_d;
+Keyboard::KeyType Keyboard::Key_E = SDLK_e;
+Keyboard::KeyType Keyboard::Key_F = SDLK_f;
+Keyboard::KeyType Keyboard::Key_G = SDLK_g;
+Keyboard::KeyType Keyboard::Key_H = SDLK_h;
+Keyboard::KeyType Keyboard::Key_I = SDLK_i;
+Keyboard::KeyType Keyboard::Key_J = SDLK_j;
+Keyboard::KeyType Keyboard::Key_K = SDLK_k;
+Keyboard::KeyType Keyboard::Key_L = SDLK_l;
+Keyboard::KeyType Keyboard::Key_M = SDLK_m;
+Keyboard::KeyType Keyboard::Key_N = SDLK_n;
+Keyboard::KeyType Keyboard::Key_O = SDLK_o;
+Keyboard::KeyType Keyboard::Key_P = SDLK_p;
+Keyboard::KeyType Keyboard::Key_Q = SDLK_q;
+Keyboard::KeyType Keyboard::Key_R = SDLK_r;
+Keyboard::KeyType Keyboard::Key_S = SDLK_s;
+Keyboard::KeyType Keyboard::Key_T = SDLK_t;
+Keyboard::KeyType Keyboard::Key_U = SDLK_u;
+Keyboard::KeyType Keyboard::Key_V = SDLK_v;
+Keyboard::KeyType Keyboard::Key_W = SDLK_w;
+Keyboard::KeyType Keyboard::Key_X = SDLK_x;
+Keyboard::KeyType Keyboard::Key_Y = SDLK_y;
+Keyboard::KeyType Keyboard::Key_Z = SDLK_z;
+Keyboard::KeyType Keyboard::Key_0 = SDLK_0;
+Keyboard::KeyType Keyboard::Key_1 = SDLK_1;
+Keyboard::KeyType Keyboard::Key_2 = SDLK_2;
+Keyboard::KeyType Keyboard::Key_3 = SDLK_3;
+Keyboard::KeyType Keyboard::Key_4 = SDLK_4;
+Keyboard::KeyType Keyboard::Key_5 = SDLK_5;
+Keyboard::KeyType Keyboard::Key_6 = SDLK_6;
+Keyboard::KeyType Keyboard::Key_7 = SDLK_7;
+Keyboard::KeyType Keyboard::Key_8 = SDLK_8;
+Keyboard::KeyType Keyboard::Key_9 = SDLK_9;
+Keyboard::KeyType Keyboard::Key_0_PAD = SDLK_KP0;
+Keyboard::KeyType Keyboard::Key_1_PAD = SDLK_KP1;
+Keyboard::KeyType Keyboard::Key_2_PAD = SDLK_KP2;
+Keyboard::KeyType Keyboard::Key_3_PAD = SDLK_KP3;
+Keyboard::KeyType Keyboard::Key_4_PAD = SDLK_KP4;
+Keyboard::KeyType Keyboard::Key_5_PAD = SDLK_KP5;
+Keyboard::KeyType Keyboard::Key_6_PAD = SDLK_KP6;
+Keyboard::KeyType Keyboard::Key_7_PAD = SDLK_KP7;
+Keyboard::KeyType Keyboard::Key_8_PAD = SDLK_KP8;
+Keyboard::KeyType Keyboard::Key_9_PAD = SDLK_KP9;
+Keyboard::KeyType Keyboard::Key_F1 = SDLK_F1;
+Keyboard::KeyType Keyboard::Key_F2 = SDLK_F2;
+Keyboard::KeyType Keyboard::Key_F3 = SDLK_F3;
+Keyboard::KeyType Keyboard::Key_F4 = SDLK_F4;
+Keyboard::KeyType Keyboard::Key_F5 = SDLK_F5;
+Keyboard::KeyType Keyboard::Key_F6 = SDLK_F6;
+Keyboard::KeyType Keyboard::Key_F7 = SDLK_F7;
+Keyboard::KeyType Keyboard::Key_F8 = SDLK_F8;
+Keyboard::KeyType Keyboard::Key_F9 = SDLK_F9;
+Keyboard::KeyType Keyboard::Key_F10 = SDLK_F10;
+Keyboard::KeyType Keyboard::Key_F11 = SDLK_F11;
+Keyboard::KeyType Keyboard::Key_F12 = SDLK_F12;
+Keyboard::KeyType Keyboard::Key_ESC = SDLK_ESCAPE;
+Keyboard::KeyType Keyboard::Key_TILDE = SDLK_BACKQUOTE;
+Keyboard::KeyType Keyboard::Key_MINUS = SDLK_MINUS;
+Keyboard::KeyType Keyboard::Key_EQUALS = SDLK_EQUALS;
+Keyboard::KeyType Keyboard::Key_BACKSPACE = SDLK_BACKSPACE;
+Keyboard::KeyType Keyboard::Key_TAB = SDLK_TAB;
+Keyboard::KeyType Keyboard::Key_OPENBRACE = SDLK_LEFTBRACKET;
+Keyboard::KeyType Keyboard::Key_CLOSEBRACE = SDLK_RIGHTBRACKET;
+Keyboard::KeyType Keyboard::Key_ENTER = SDLK_RETURN;
+Keyboard::KeyType Keyboard::Key_COLON = SDLK_COLON;
+Keyboard::KeyType Keyboard::Key_QUOTE = SDLK_QUOTEDBL;
+Keyboard::KeyType Keyboard::Key_BACKSLASH = SDLK_BACKSLASH;
+Keyboard::KeyType Keyboard::Key_BACKSLASH2 = 999; /* FIXME */
+Keyboard::KeyType Keyboard::Key_COMMA = SDLK_COMMA;
+Keyboard::KeyType Keyboard::Key_STOP = SDLK_PERIOD;
+Keyboard::KeyType Keyboard::Key_SLASH = SDLK_SLASH;
+Keyboard::KeyType Keyboard::Key_SPACE = SDLK_SPACE;
+Keyboard::KeyType Keyboard::Key_INSERT = SDLK_INSERT;
+Keyboard::KeyType Keyboard::Key_DEL = SDLK_DELETE;
+Keyboard::KeyType Keyboard::Key_HOME = SDLK_HOME;
+Keyboard::KeyType Keyboard::Key_END = SDLK_END;
+Keyboard::KeyType Keyboard::Key_PGUP = SDLK_PAGEUP;
+Keyboard::KeyType Keyboard::Key_PGDN = SDLK_PAGEDOWN;
+Keyboard::KeyType Keyboard::Key_LEFT = SDLK_LEFT;
+Keyboard::KeyType Keyboard::Key_RIGHT = SDLK_RIGHT;
+Keyboard::KeyType Keyboard::Key_UP = SDLK_UP;
+Keyboard::KeyType Keyboard::Key_DOWN = SDLK_DOWN;
+Keyboard::KeyType Keyboard::Key_SLASH_PAD = SDLK_KP_DIVIDE;
+Keyboard::KeyType Keyboard::Key_ASTERISK = SDLK_ASTERISK;
+Keyboard::KeyType Keyboard::Key_MINUS_PAD = SDLK_KP_MINUS;
+Keyboard::KeyType Keyboard::Key_PLUS_PAD = SDLK_KP_PLUS;
+Keyboard::KeyType Keyboard::Key_DEL_PAD = 1000; /* FIXME */
+Keyboard::KeyType Keyboard::Key_ENTER_PAD = SDLK_KP_ENTER;
+Keyboard::KeyType Keyboard::Key_PRTSCR = SDLK_PRINT;
+Keyboard::KeyType Keyboard::Key_PAUSE = SDLK_PAUSE;
+Keyboard::KeyType Keyboard::Key_ABNT_C1 = 1001; /* FIXME */
+Keyboard::KeyType Keyboard::Key_YEN = 1002;
+Keyboard::KeyType Keyboard::Key_KANA = 1003;
+Keyboard::KeyType Keyboard::Key_CONVERT = 1004;
+Keyboard::KeyType Keyboard::Key_NOCONVERT = 1005;
+Keyboard::KeyType Keyboard::Key_AT = SDLK_AT;
+Keyboard::KeyType Keyboard::Key_CIRCUMFLEX = SDLK_CARET;
+Keyboard::KeyType Keyboard::Key_COLON2 = 1006;
+Keyboard::KeyType Keyboard::Key_KANJI = 1007;
+Keyboard::KeyType Keyboard::Key_EQUALS_PAD = SDLK_KP_EQUALS;
+Keyboard::KeyType Keyboard::Key_BACKQUOTE = 1008;
+Keyboard::KeyType Keyboard::Key_SEMICOLON = SDLK_SEMICOLON;
+Keyboard::KeyType Keyboard::Key_COMMAND = 1009;
+
+Keyboard::KeyType Keyboard::Key_MODIFIERS = 1010;
+Keyboard::KeyType Keyboard::Key_LSHIFT = SDLK_LSHIFT;
+Keyboard::KeyType Keyboard::Key_RSHIFT = SDLK_RSHIFT;
+Keyboard::KeyType Keyboard::Key_LCONTROL = SDLK_LCTRL;
+Keyboard::KeyType Keyboard::Key_RCONTROL = SDLK_RCTRL;
+Keyboard::KeyType Keyboard::Key_ALT = SDLK_LALT;
+Keyboard::KeyType Keyboard::Key_ALTGR = SDLK_RALT;
+Keyboard::KeyType Keyboard::Key_LWIN = SDLK_LMETA;
+Keyboard::KeyType Keyboard::Key_RWIN = SDLK_RMETA;
+Keyboard::KeyType Keyboard::Key_MENU = SDLK_HELP;
+Keyboard::KeyType Keyboard::Key_SCRLOCK = SDLK_SCROLLOCK;
+Keyboard::KeyType Keyboard::Key_NUMLOCK = SDLK_NUMLOCK;
+Keyboard::KeyType Keyboard::Key_CAPSLOCK = SDLK_CAPSLOCK;
diff --git a/util/input/text-input.cpp b/util/input/text-input.cpp
new file mode 100644
index 00000000..52ba653f
--- /dev/null
+++ b/util/input/text-input.cpp
@@ -0,0 +1,207 @@
+#include "input-map.h"
+#include "text-input.h"
+#include "input-manager.h"
+#include <string.h>
+#include <sstream>
+#include <string>
+
+using namespace std;
+
+static const int Shift = 198;
+static const int Control = 199;
+static const int Backspace = 200;
+
+TextInput::TextInput(const string & start):
+InputMap<unsigned char>(),
+blockingKeys(false),
+enabled(false),
+handle(201){
+ const int delay = 100;
+ /*
+ set(Keyboard::Key_TILDE, delay * 2, false, Toggle);
+ set(Keyboard::Key_ESC, delay, false, Esc);
+ set(Keyboard::Key_ENTER, 0, false, Enter);
+ */
+
+ // set(Keyboard::Key_LCONTROL, 0, false, Control);
+ set(Keyboard::Key_BACKSPACE, delay, false, Backspace);
+ /*
+ set(Keyboard::Key_LSHIFT, 0, false, Shift);
+ set(Keyboard::Key_RSHIFT, 0, false, Shift);
+ */
+
+ text.str(start);
+ text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
+ text.clear();
+}
+
+int TextInput::nextHandle(){
+ int i = handle;
+ handle += 1;
+ return i;
+}
+
+void TextInput::addBlockingHandle(int key, callback function, void * data){
+ int handle = nextHandle();
+ set(key, 1, true, handle);
+ callbacks[handle] = Callback(function, data);
+}
+
+void TextInput::addHandle(int key, int delay, callback function, void * data){
+ int handle = nextHandle();
+ set(key, delay, false, handle);
+ callbacks[handle] = Callback(function, data);
+}
+
+bool TextInput::doInput(){
+ bool modified = false;
+ /* TODO: ensure these codes are consistent across platforms. So far
+ * they seem to work in windows xp and linux (ubuntu)
+ */
+ const Keyboard::unicode_t control_u = 21;
+ const Keyboard::unicode_t control_w = 23;
+
+ if (enabled){
+ vector<InputEvent> events = InputManager::getEvents(*this);
+
+ /* the order of reading input is arbitrary right now. I'm not
+ * sure it matters what order things are done in, but probably
+ * a few corner cases exist. When they come up please document them.
+ */
+
+ for (vector<InputEvent>::iterator it = events.begin(); it != events.end(); it++){
+ InputEvent event = *it;
+
+ if (event.enabled){
+ if (event.out == Backspace){
+ backspace();
+ modified = true;
+ }
+
+ if (callbacks.find(event.out) != callbacks.end()){
+ Callback & callback = callbacks[event.out];
+ callback.function(callback.data);
+ }
+
+ if (event.unicode == control_u){
+ clearInput();
+ modified = true;
+ }
+ if (event.unicode == control_w){
+ deleteLastWord();
+ modified = true;
+ }
+
+ /* FIXME: whats the maximum unicode value? */
+ if (event.unicode >= 32 && event.unicode < 0xffffff){
+ this->text << (unsigned char) event.unicode;
+ modified = true;
+ }
+ }
+ }
+ }
+
+ return modified;
+}
+
+void TextInput::enable(){
+ InputManager::captureInput(*this);
+ enabled = true;
+}
+
+void TextInput::disable(){
+ InputManager::releaseInput(*this);
+ enabled = false;
+}
+
+string TextInput::getText(){
+ return text.str();
+}
+
+/*
+void TextInput::clear(){
+ text.str("");
+ text.clear();
+}
+*/
+
+void TextInput::setText(const std::string & text){
+ this->text.str(text);
+ this->text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
+ this->text.clear();
+}
+
+void TextInput::clearInput(){
+ text.str(string());
+ text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
+ text.clear();
+}
+
+void TextInput::backspace(){
+ string now = text.str();
+ now = now.substr(0, now.size()-1);
+ text.str(now);
+ text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
+ text.clear();
+}
+
+void TextInput::deleteLastWord(){
+ string now = text.str();
+ // Global::debug(0) << "Delete last word '" << now << "'" << endl;
+
+ if (now.size() > 0){
+ if (now.at(now.size() - 1) != ' '){
+ int here = now.size() - 1;
+ while (here > 0 && now.at(here) != ' '){
+ here -= 1;
+ }
+ if (now.at(here) == ' '){
+ here += 1;
+ }
+ now.erase(here);
+ } else {
+ int here = now.size() - 1;
+ while (here > 0 && now.at(here) == ' '){
+ here -= 1;
+ }
+ if (here > 0){
+ while (here > 0 && now.at(here) != ' '){
+ here -= 1;
+ }
+ if (now.at(here) == ' '){
+ here += 1;
+ }
+ }
+ now.erase(here);
+ }
+ text.str(now);
+ text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
+ text.clear();
+ }
+
+ /*
+ size_t get = now.rfind(" ");
+ if (get != string::npos){
+ Global::debug(0) << "get " << get << " size " << now.size() << endl;
+ if (get == now.size() - 1){
+ get = now.find_last_not_of(' ');
+ get = now.rfind(' ', get);
+ if (get != string::npos){
+ get = 0;
+ }
+ now.erase(get + 1);
+ } else {
+ now = now.substr(0, get + 1);
+ }
+ text.str(now);
+ text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
+ text.clear();
+ } else {
+ clearInput();
+ }
+ */
+}
+
+TextInput::~TextInput(){
+ disable();
+}
diff --git a/util/input/text-input.h b/util/input/text-input.h
new file mode 100644
index 00000000..d37dabff
--- /dev/null
+++ b/util/input/text-input.h
@@ -0,0 +1,81 @@
+#ifndef _paintown_text_input_h
+#define _paintown_text_input_h
+
+#include "input-map.h"
+#include <sstream>
+#include <string>
+#include <map>
+
+typedef void (*callback)(void * arg);
+
+struct Callback{
+ Callback():
+ function(0),
+ data(0){
+ }
+
+ Callback(callback function, void * data):
+ function(function),
+ data(data){
+ }
+
+ callback function;
+ void * data;
+};
+
+class TextInput: public InputMap<unsigned char> {
+public:
+ TextInput(const std::string & start = "");
+
+ /* returns true if the text was modified */
+ bool doInput();
+ void enable();
+ void disable();
+
+ void addHandle(int key, int delay, callback function, void * data);
+ void addBlockingHandle(int key, callback function, void * data);
+
+ inline void setBlockingKeys(){
+ blockingKeys = true;
+ }
+
+ std::string getText();
+ void setText(const std::string & text);
+
+ void clearInput();
+ // void clear();
+
+ bool isEnabled() const {
+ return enabled;
+ }
+
+ void backspace();
+ void deleteLastWord();
+
+ virtual KeyState<unsigned char> * getState(int key){
+ KeyState<unsigned char> * state = InputMap<unsigned char>::getState(key);
+ if (state == NULL){
+ if (blockingKeys){
+ set(key, 0, true, key);
+ } else {
+ set(key, 10, false, key);
+ }
+ state = InputMap<unsigned char>::getState(key);
+ }
+ return state;
+ }
+
+ virtual ~TextInput();
+
+protected:
+ int nextHandle();
+
+ std::ostringstream text;
+ /* whether key repeat is on or off */
+ bool blockingKeys;
+ bool enabled;
+ std::map<int, Callback> callbacks;
+ int handle;
+};
+
+#endif
diff --git a/util/input/wii/joystick.cpp b/util/input/wii/joystick.cpp
new file mode 100644
index 00000000..256110b3
--- /dev/null
+++ b/util/input/wii/joystick.cpp
@@ -0,0 +1,139 @@
+#ifdef WII
+
+#include "joystick.h"
+
+#include <ogc/pad.h>
+#include <wiiuse/wpad.h>
+
+void WiiJoystick::poll(){
+ PAD_ScanPads();
+ WPAD_ScanPads();
+}
+
+JoystickInput WiiJoystick::readAll(){
+ JoystickInput input;
+ // Number passed should be a port 1-4 I believe same with gc pad this can be modified later for multiplayer
+
+ // Wii data
+ WPADData * wpad;
+ wpad = WPAD_Data(0);
+
+ // Gamecube
+ u16 gcheld = PAD_ButtonsHeld(0);
+
+ // Wii controller
+ if (wpad->exp.type == WPAD_EXP_CLASSIC){
+ // Classic controller
+ if(wpad->btns_h & WPAD_CLASSIC_BUTTON_UP){
+ input.up = true;
+ }
+ if(wpad->btns_h & WPAD_CLASSIC_BUTTON_DOWN){
+ input.down = true;
+ }
+ if(wpad->btns_h & WPAD_CLASSIC_BUTTON_LEFT){
+ input.left = true;
+ }
+ if(wpad->btns_h & WPAD_CLASSIC_BUTTON_RIGHT){
+ input.right = true;
+ }
+ } else if (wpad->exp.type == WPAD_EXP_NUNCHUK){
+ // With nunchuck
+ if(wpad->exp.nunchuk.js.pos.y >= 0xB0){
+ input.up = true;
+ }
+ if(wpad->exp.nunchuk.js.pos.y <= 0x40){
+ input.down = true;
+ }
+ if(wpad->exp.nunchuk.js.pos.x <= 0x40){
+ input.left = true;
+ }
+ if(wpad->exp.nunchuk.js.pos.x >= 0xB0){
+ input.right = true;
+ }
+ } else {
+ // No attachment
+ if(wpad->btns_h & WPAD_BUTTON_UP){
+ if(wpad->ir.valid){
+ input.up = true;
+ } else {
+ input.left = true;
+ }
+ }
+ if(wpad->btns_h & WPAD_BUTTON_DOWN){
+ if(wpad->ir.valid){
+ input.down = true;
+ } else {
+ input.right = true;
+ }
+ }
+ if(wpad->btns_h & WPAD_BUTTON_LEFT){
+ if(wpad->ir.valid){
+ input.left = true;
+ } else {
+ input.down = true;
+ }
+ }
+ if(wpad->btns_h & WPAD_BUTTON_RIGHT){
+ if(wpad->ir.valid){
+ input.right = true;
+ } else {
+ input.up = true;
+ }
+ }
+ }
+
+ // Gamecube controller
+ if(gcheld & PAD_BUTTON_UP){
+ input.up = true;
+ }
+ if(gcheld & PAD_BUTTON_DOWN){
+ input.down = true;
+ }
+ if(gcheld & PAD_BUTTON_LEFT){
+ input.left = true;
+ }
+ if(gcheld & PAD_BUTTON_RIGHT){
+ input.right = true;
+ }
+
+ // Check all input buttons
+ if (wpad->btns_h & WPAD_CLASSIC_BUTTON_X || wpad->btns_h & WPAD_BUTTON_1 || gcheld & PAD_BUTTON_X){
+ input.button1 = true;
+ }
+ if (wpad->btns_h & WPAD_CLASSIC_BUTTON_Y || wpad->btns_h & WPAD_BUTTON_2 || gcheld & PAD_BUTTON_Y){
+ input.button2 = true;
+ }
+ if (wpad->btns_h & WPAD_CLASSIC_BUTTON_A || wpad->btns_h & WPAD_BUTTON_A || gcheld & PAD_BUTTON_A){
+ input.button3 = true;
+ }
+ if (wpad->btns_h & WPAD_CLASSIC_BUTTON_B || wpad->btns_h & WPAD_BUTTON_B || gcheld & PAD_BUTTON_B){
+ input.button4 = true;
+ }
+ if (wpad->btns_h & WPAD_CLASSIC_BUTTON_PLUS || wpad->btns_h & WPAD_BUTTON_PLUS || gcheld & PAD_BUTTON_START){
+ // enter
+ }
+ if (wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME || wpad->btns_h & WPAD_BUTTON_HOME || gcheld & PAD_BUTTON_MENU){
+ // esc
+ }
+ if (wpad->btns_h & WPAD_CLASSIC_BUTTON_MINUS || wpad->btns_h & WPAD_BUTTON_MINUS){
+ // ?
+ }
+
+ return input;
+}
+
+int WiiJoystick::getDeviceId() const {
+ /* FIXME! Figure out the device id */
+ return 0;
+}
+
+WiiJoystick::~WiiJoystick(){
+ WPAD_Shutdown();
+}
+
+WiiJoystick::WiiJoystick(){
+ WPAD_Init();
+ PAD_Init();
+}
+
+#endif
diff --git a/util/input/wii/joystick.h b/util/input/wii/joystick.h
new file mode 100644
index 00000000..6c3a9ca5
--- /dev/null
+++ b/util/input/wii/joystick.h
@@ -0,0 +1,23 @@
+#ifndef _paintown_wii_joystick_h
+#define _paintown_wii_joystick_h
+
+#ifdef WII
+
+#include "../joystick.h"
+
+class WiiJoystick: public Joystick {
+public:
+ virtual void poll();
+ virtual JoystickInput readAll();
+ virtual int getDeviceId() const;
+
+ virtual ~WiiJoystick();
+
+ friend class Joystick;
+protected:
+ WiiJoystick();
+};
+
+#endif
+
+#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 11:48 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68869
Default Alt Text
(101 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline