diff --git a/CMakeLists.txt b/CMakeLists.txt index 817a788..0a12fbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8) SET(VERSION_MAJOR 1) -SET(VERSION_MINOR 0) +SET(VERSION_MINOR 1) # choose source file file(GLOB LIB_SRC_LIST src/input.cpp src/keybindings.cpp src/textbuffer.cpp) diff --git a/src/input.cpp b/src/input.cpp index 4f0091c..1407eb1 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -14,8 +14,9 @@ Input::Input(sf::Window *w) : m_closeRequested(false), m_mouseGrabbed(false) { - m_heldkeys = std::vector(); - m_actions = std::vector(); + m_heldKeys = std::vector(); + m_heldMouseButtons = std::vector(); + m_actions = std::vector(); m_window->setKeyRepeatEnabled(false); } @@ -43,93 +44,119 @@ void Input::updateEvents(){ kb = m_keybindings[m_current_context]; m_actions.clear(); - int action; + Action action; - /* event-parsing loop */ + /* event-parsing loop */ while(m_window->pollEvent(event)) { -// std::cout << event.type << std::endl; switch(event.type){ - case sf::Event::Closed: - m_closeRequested = true; - break; - case sf::Event::TextEntered: - c = (char) event.text.unicode; - sf::Utf32::encodeAnsi(event.text.unicode,std::back_inserter(m_buffer)); -// std::cout << << std::endl; -// m_buffer.push_back('\u9190'); - break; - case sf::Event::KeyPressed: - action = kb.getPressedAction(event.key.code); - if(action != -1) - m_actions.push_back(action); - m_heldkeys.push_back(event.key.code); - break; - case sf::Event::KeyReleased: - action = kb.getReleasedAction(event.key.code); - if(action != -1) - m_actions.push_back(action); - releaseHeldKeys(event.key.code); - break; - case sf::Event::MouseButtonPressed: - action = kb.getPressedAction(sf::Keyboard::KeyCount + event.mouseButton.button); - if(action != -1) - m_actions.push_back(action); - m_heldkeys.push_back((sf::Keyboard::Key) (sf::Keyboard::KeyCount + event.mouseButton.button)); - break; - case sf::Event::MouseButtonReleased: - action = kb.getReleasedAction(sf::Keyboard::KeyCount + event.mouseButton.button); - if(action != -1) - m_actions.push_back(action); - releaseHeldKeys((sf::Keyboard::Key) (sf::Keyboard::KeyCount + event.mouseButton.button)); - break; - case sf::Event::MouseWheelScrolled: - if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel) - m_delta_vertical_scroll = event.mouseWheelScroll.delta; - break; - case sf::Event::MouseMoved: - m_mouse_position = sf::Mouse::getPosition(*m_window); - break; - case sf::Event::MouseEntered: - // action MouseEntered - break; - case sf::Event::MouseLeft: - //action MouseLeft - break; - case sf::Event::Resized: - m_hasBeenResized = true; - if(m_mouseGrabbed) - m_last_mouse_position = sf::Vector2i(m_window->getSize())/2; - break; + case sf::Event::Closed: + m_closeRequested = true; + break; + case sf::Event::Resized: + m_hasBeenResized = true; + break; + case sf::Event::LostFocus: + m_mouseWasGrabbed = m_mouseGrabbed; + m_mouseGrabbed = false; + break; + case sf::Event::GainedFocus: + m_mouseGrabbed = m_mouseWasGrabbed; + break; + case sf::Event::TextEntered: + c = (char) event.text.unicode; + sf::Utf32::encodeAnsi(event.text.unicode,std::back_inserter(m_buffer)); + break; + case sf::Event::KeyPressed: + action = kb.getPressedAction(input::KEYBOARD,event.key.code); + if(!action.isNull()) + m_actions.push_back(action); + m_heldKeys.push_back(event.key.code); + break; + case sf::Event::KeyReleased: + action = kb.getReleasedAction(input::KEYBOARD,event.key.code); + if(!action.isNull()) + m_actions.push_back(action); + releaseHeldKeys(event.key.code); + break; + case sf::Event::MouseWheelScrolled: + if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel) + m_delta_vertical_scroll = event.mouseWheelScroll.delta; + break; + case sf::Event::MouseButtonPressed: + action = kb.getPressedAction(input::MOUSE,event.mouseButton.button); + if(!action.isNull()) + m_actions.push_back(action); + m_heldMouseButtons.push_back(event.mouseButton.button); + break; + case sf::Event::MouseButtonReleased: + action = kb.getReleasedAction(input::MOUSE,event.mouseButton.button); + if(!action.isNull()) + m_actions.push_back(action); + releaseHeldMouseButton(event.mouseButton.button); + break; + case sf::Event::MouseMoved: + m_mouse_position = sf::Mouse::getPosition(*m_window); + break; + case sf::Event::MouseEntered: + // action MouseEntered + break; + case sf::Event::MouseLeft: + if(m_mouseGrabbed) + sf::Mouse::setPosition(m_last_mouse_position,*m_window); + break; + case sf::Event::JoystickButtonPressed: + action = kb.getPressedAction(input::CONTROLLER,event.joystickButton.button); + if(!action.isNull()){ + action.controller_id = event.joystickButton.joystickId; + m_actions.push_back(action); + } + m_heldJoystickButtons[action.controller_id].push_back(event.joystickButton.button); + break; + case sf::Event::JoystickButtonReleased: + action = kb.getReleasedAction(input::CONTROLLER, event.joystickButton.button); + if(!action.isNull()){ + action.controller_id = event.joystickButton.joystickId; + m_actions.push_back(action); + } + releaseHeldJoystickButton(event.joystickButton.button,action.controller_id); + break; + case sf::Event::JoystickMoved: + break; + case sf::Event::JoystickConnected: + m_heldJoystickButtons[event.joystickConnect.joystickId] = std::vector(); + break; + case sf::Event::JoystickDisconnected: + m_heldJoystickButtons.erase(event.joystickConnect.joystickId); + break; } } if(m_mouseGrabbed) sf::Mouse::setPosition(m_last_mouse_position, *m_window); - for (auto key: m_heldkeys) + + for (auto key: m_heldKeys) + m_actions.push_back(kb.getHoldAction(input::KEYBOARD,key)); + + for (auto button: m_heldMouseButtons) + m_actions.push_back(kb.getHoldAction(input::MOUSE,button)); + + for (auto heldJoystickButton : m_heldJoystickButtons) { - m_actions.push_back(kb.getHoldAction(key)); - } + for (auto button: heldJoystickButton.second) + { + action = kb.getHoldAction(input::CONTROLLER,button); + action.controller_id = heldJoystickButton.first; + m_actions.push_back(action); + } + } } -std::vector Input::getActions() +std::vector Input::getActions() { return m_actions; } /* context-related functions */ - -//void Input::addContext(Context context) -//{ -// m_contexts.push_back(context); -//} -//std::string Input::getCurrentContext() -//{ -// return m_current_context; -//} -//void Input::setCurrentContext(std::string context_name){ -// m_current_context = context_name; -//} - void Input::updateKeyBindings(){ m_keybindings.clear(); for (auto iter= m_contexts.begin(); iter != m_contexts.end(); ++iter) @@ -155,13 +182,25 @@ bool Input::isKeyPressed(int key) const return sf::Keyboard::isKeyPressed((sf::Keyboard::Key) key); } -void Input::releaseHeldKeys(sf::Keyboard::Key keycode){ - for(auto iter = m_heldkeys.begin();iter < m_heldkeys.end();) - iter = *iter == keycode ? m_heldkeys.erase(iter) : iter+1; +void Input::releaseHeldKeys(int keycode) +{ + for(auto iter = m_heldKeys.begin();iter < m_heldKeys.end();) + iter = *iter == keycode ? m_heldKeys.erase(iter) : iter+1; +} + +void Input::releaseHeldMouseButton(int buttoncode) +{ + for(auto iter = m_heldMouseButtons.begin();itergetSize())/2; } +std::vector Input::getControllersConnected() const{ + std::vector v; + for(auto &controller : m_heldJoystickButtons) + v.push_back(controller.first); + return v; +} + +float Input::getAxisPosition(int device_id, int axis_id) +{ + return sf::Joystick::getAxisPosition(device_id, (sf::Joystick::Axis) axis_id); +} + std::wstring Input::getText() { return m_buffer; @@ -194,12 +245,12 @@ std::wstring Input::getText() void Input::test() { - KeyBindings kb = m_keybindings[m_current_context]; +/* KeyBindings kb = m_keybindings[m_current_context]; int action; - action = kb.getPressedAction(sf::Keyboard::I); + action = kb.getPressedAction(sf::Keyboard::I); if (action != NO_ACTION) std::cerr << action << std::endl; action = kb.getPressedAction(sf::Keyboard::O); if (action != NO_ACTION) - std::cerr << action << std::endl; + std::cerr << action << std::endl;*/ } diff --git a/src/input.h b/src/input.h index 6627ed8..187e7d6 100644 --- a/src/input.h +++ b/src/input.h @@ -7,6 +7,7 @@ #include "keybindings.h" #include #include +#include #include #include "textbuffer.h" #include "glm/vec2.hpp" @@ -20,7 +21,7 @@ private: /* general action-mapping variables */ IKeysMap m_keysmap; - std::vector m_actions; + std::vector m_actions; int nb_actions; /* context-related variables */ @@ -28,15 +29,23 @@ private: std::vector m_contexts; std::unordered_map m_keybindings; - /* keyboard-related variables */ - std::vector m_heldkeys; - void releaseHeldKeys(sf::Keyboard::Key keycode); + /* keyboard */ + std::vector m_heldKeys; + void releaseHeldKeys(int keycode); - /* mouse-related variables */ + /* mouse */ sf::Vector2i m_mouse_position; sf::Vector2i m_last_mouse_position; float m_delta_vertical_scroll; bool m_mouseGrabbed; + bool m_mouseWasGrabbed; + std::vector m_heldMouseButtons; + void releaseHeldMouseButton(int buttoncode); + + /* joystick */ + std::map> m_joystick_position; + std::map> m_heldJoystickButtons; + void releaseHeldJoystickButton(int buttoncode, int controller_id); /* text-related variable */ std::wstring m_buffer; @@ -47,10 +56,10 @@ public: /* general action-mapping functions */ void setKeysMap(IKeysMap km); //set bindings void updateEvents(); //handle the input and put the associated event in the file - std::vector getActions(); //get the first action in the file of event + std::vector getActions(); //get the first action in the file of event /* context-related functions */ - void addContext(Context context){m_contexts.push_back(context);} + void addContext(Context context){m_contexts.push_back(context); updateKeyBindings();} std::string getCurrentContext(){return m_current_context;} void setCurrentContext(std::string context_name){m_current_context = context_name;} void updateKeyBindings(); @@ -63,9 +72,7 @@ public: bool isKeyPressed(int key) const; /* mouse-related function */ - //sf::Vector2i getPosition() const; glm::vec2 getPosition() const; - //sf::Vector2i getDeltaPosition() const; glm::vec2 getDeltaPosition() const; float getDeltaVerticalScroll() const; @@ -74,6 +81,10 @@ public: void toggleMouseGrab() { setMouseGrabbed(!m_mouseGrabbed); } bool isMouseGrabbed() const { return m_mouseGrabbed; } + /* joystick-related function */ + std::vector getControllersConnected() const; + float getAxisPosition(int device_id, int axis_id); + /* text-related function */ std::wstring getText(); diff --git a/src/keybindings.cpp b/src/keybindings.cpp index 9b2f0c8..9821065 100644 --- a/src/keybindings.cpp +++ b/src/keybindings.cpp @@ -15,13 +15,17 @@ IKeysMap::IKeysMap() } -std::vector IKeysMap::getBindings(int action) const { +std::vector IKeysMap::getBindings(Action action) const { std::vector bindings; for (auto binding : keys) - if (binding.action == action) bindings.push_back(binding); + if (binding.action.action == action.action) bindings.push_back(binding); return bindings; } +Action Action::getNull(){ + return {NO_ACTION,input::NONE}; +} + /* Implementation of KeyBindings class * @author: Thomas Brandého * @info: This class map a list of action with the associated keys, for a quick access in-game. @@ -34,7 +38,8 @@ KeyBindings::KeyBindings() KeyBindings::KeyBindings(const Context &context, const IKeysMap &keysmap) { - for (int action : context.getActions()){ + init_map_bindings(); + for (Action action : context.getActions()){ for (Binding binding : keysmap.getBindings(action)){ switch(binding.type){ case IKeysMap::PRESSED: @@ -55,75 +60,64 @@ KeyBindings::KeyBindings(const Context &context, const IKeysMap &keysmap) } - - - - - - - - - - - - - - - - - - - - - - - - -int KeyBindings::getPressedAction(int key) const +Action KeyBindings::getPressedAction(input::Source src, int key) const { - return bindings_pressed.count(key) == 1? bindings_pressed.at(key) : -1; + if (bindings_pressed.at(src).count(key)) + return {bindings_pressed.at(src).at(key),src}; + else + return Action::getNull(); } -int KeyBindings::getReleasedAction(int key) const +Action KeyBindings::getReleasedAction(input::Source src, int key) const { - return bindings_released.count(key) == 1? bindings_released.at(key) : -1; + if(bindings_released.at(src).count(key)) + return {bindings_released.at(src).at(key),src}; + else + return Action::getNull(); } -int KeyBindings::getHoldAction(int key) const +Action KeyBindings::getHoldAction(input::Source src, int key) const { - return bindings_hold.count(key) == 1? bindings_hold.at(key) : -1; + if(bindings_hold.at(src).count(key)) + return {bindings_hold.at(src).at(key),src}; + else + return Action::getNull(); } - - -void KeyBindings::setPressedAction(int key, int action) +void KeyBindings::setPressedAction(int key, Action action) { - bindings_pressed[key]=action; + bindings_pressed[action.source][key]=action.action; } -void KeyBindings::setReleasedAction(int key, int action) +void KeyBindings::setReleasedAction(int key, Action action) { - bindings_released[key]=action; + bindings_released[action.source][key]=action.action; } -void KeyBindings::setHoldAction(int key, int action) +void KeyBindings::setHoldAction(int key, Action action) { - bindings_hold[key]=action; + bindings_hold[action.source][key]=action.action; } +void KeyBindings::init_map_bindings(){ + for(int i = 0; i < input::SOURCE_COUNT;i++){ + bindings_pressed[i] = std::unordered_map(); + bindings_released[i] = std::unordered_map(); + bindings_hold[i] = std::unordered_map(); + } +} /* Implementation of Context class * @author: Thomas Brandého * @info: This class contains a list of actions available in a given situation (context). */ -Context::Context(std::string _name, std::vector _actions): name(_name), actions(_actions) +Context::Context(std::string _name, std::vector _actions): name(_name), actions(_actions) { - } std::string Context::getName() { return name; } -std::vector Context::getActions() const +std::vector Context::getActions() const { return actions; } diff --git a/src/keybindings.h b/src/keybindings.h index 5a1b7b0..e8e4814 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -12,47 +12,64 @@ #define NO_KEY -1 #define NO_ACTION -1 +namespace input{ +enum Source{NONE=-1,KEYBOARD,MOUSE,CONTROLLER,SOURCE_COUNT}; +} + +struct Action { + int action; + input::Source source; + int controller_id; + static Action getNull(); + bool isNull(){ + return (action == NO_ACTION) && (source == input::NONE); + } + friend bool operator ==(const Action& action1, const Action& action2){ + return (action1.action == action2.action) && (action1.source == action2.source); + } +}; + struct Binding{ - int action; + Action action; int key; int type; }; -//write a function to add new Binding? class IKeysMap{ public: enum {PRESSED, RELEASED, HOLD}; IKeysMap(); - std::vector getBindings(int action) const; + std::vector getBindings(Action action) const; protected: std::vector keys; }; class Context { public: - Context(std::string name, std::vector actions); + Context(std::string name, std::vector actions); std::string getName(); - std::vector getActions() const; + std::vector getActions() const; private: std::string name; - std::vector actions; + std::vector actions; }; class KeyBindings { public: KeyBindings(); KeyBindings(const Context &context, const IKeysMap &keysmap); - int getPressedAction(int key) const; - int getReleasedAction(int key) const; - int getHoldAction(int key) const; + Action getPressedAction(input::Source src,int key) const; + Action getReleasedAction(input::Source src,int key) const; + Action getHoldAction(input::Source src,int key) const; private: - std::unordered_map bindings_pressed; - std::unordered_map bindings_released; - std::unordered_map bindings_hold; - void setPressedAction(int key, int action); - void setReleasedAction(int key, int action); - void setHoldAction(int key, int action); + std::unordered_map> bindings_pressed; + std::unordered_map> bindings_released; + std::unordered_map> bindings_hold; + void setPressedAction(int key, Action action); + void setReleasedAction(int key, Action action); + void setHoldAction(int key, Action action); + void init_map_bindings(); }; #endif diff --git a/src/main.cpp b/src/main.cpp index 3761319..9d0caaa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,23 +1,55 @@ #include #include #include "input.h" -//#include "keybindings.h" using namespace std; +class TestKeysMap : public IKeysMap { +public: + enum{LEFT_CLICK,RIGHT_CLICK,MIDDLE_CLICK,ACTION}; + TestKeysMap(){ + keys.push_back ({{LEFT_CLICK,input::MOUSE},sf::Mouse::Left,PRESSED} ); + keys.push_back ({{RIGHT_CLICK,input::MOUSE},sf::Mouse::Right,PRESSED} ); + keys.push_back ({{ACTION,input::CONTROLLER},sf::Joystick::X,PRESSED} ); + } + + static std::vector getTestContext() + { + return + { + {LEFT_CLICK,input::MOUSE}, + {RIGHT_CLICK,input::MOUSE}, + {ACTION,input::CONTROLLER} + }; + } +}; + + int main() { cerr << "Hello World!"<< endl; sf::Window* window= new sf::Window(sf::VideoMode(400,200),"testSparrowInput"); Input myInput(window); - enum {ACTION_1,ACTION_2}; - std::vector myvector; - myvector.push_back(ACTION_1); - myvector.push_back(ACTION_2); - while(!myInput.isCloseRequested()) - myInput.updateEvents(); -// IKeysMap* keymap = new IKeysMap("test", 1); + Context context = Context("test",TestKeysMap::getTestContext()); + myInput.setKeysMap(TestKeysMap()); + myInput.addContext(context); + myInput.setCurrentContext("test"); + + while(!myInput.isCloseRequested()) + { + myInput.updateEvents(); + for (Action action : myInput.getActions()) + { + if (action.action == TestKeysMap::ACTION && action.source == input::CONTROLLER && action.controller_id == 0){ + std::cout << "Controllers connected: " << myInput.getControllersConnected().size(); +// for(auto controller : myInput.getControllersConnected()) + // std::cout << controller << " "; + std::cout << std::endl; + } + } + } + /* IKeysMap* keymap = new IKeysMap("test", 1); // keymap->setKeyBinding(ACTION_2,0,sf::Keyboard::Z); // keymap->setTypeAction(ACTION_2,KeysMap::RELEASED); @@ -51,7 +83,7 @@ int main() // while (action = myInput.getAction() != NO_ACTION) // cout << "test " << action << endl; // window->display(); -// } +// }*/ cerr << "Successfully ended" << endl; return 0; }