Merge branch 'joystick' into 'master'

Joystick

See merge request !1
This commit is contained in:
Thomas Brandého 2017-02-16 17:04:14 +01:00
commit d21013f7bc
6 changed files with 263 additions and 158 deletions

View File

@ -2,7 +2,7 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
SET(VERSION_MAJOR 1) SET(VERSION_MAJOR 1)
SET(VERSION_MINOR 0) SET(VERSION_MINOR 1)
# choose source file # choose source file
file(GLOB LIB_SRC_LIST src/input.cpp src/keybindings.cpp src/textbuffer.cpp) file(GLOB LIB_SRC_LIST src/input.cpp src/keybindings.cpp src/textbuffer.cpp)

View File

@ -14,8 +14,9 @@ Input::Input(sf::Window *w) :
m_closeRequested(false), m_closeRequested(false),
m_mouseGrabbed(false) m_mouseGrabbed(false)
{ {
m_heldkeys = std::vector<sf::Keyboard::Key>(); m_heldKeys = std::vector<int>();
m_actions = std::vector<int>(); m_heldMouseButtons = std::vector<int>();
m_actions = std::vector<Action>();
m_window->setKeyRepeatEnabled(false); m_window->setKeyRepeatEnabled(false);
} }
@ -43,93 +44,119 @@ void Input::updateEvents(){
kb = m_keybindings[m_current_context]; kb = m_keybindings[m_current_context];
m_actions.clear(); m_actions.clear();
int action; Action action;
/* event-parsing loop */ /* event-parsing loop */
while(m_window->pollEvent(event)) while(m_window->pollEvent(event))
{ {
// std::cout << event.type << std::endl;
switch(event.type){ switch(event.type){
case sf::Event::Closed: case sf::Event::Closed:
m_closeRequested = true; m_closeRequested = true;
break; break;
case sf::Event::TextEntered: case sf::Event::Resized:
c = (char) event.text.unicode; m_hasBeenResized = true;
sf::Utf32::encodeAnsi(event.text.unicode,std::back_inserter(m_buffer)); break;
// std::cout << << std::endl; case sf::Event::LostFocus:
// m_buffer.push_back('\u9190'); m_mouseWasGrabbed = m_mouseGrabbed;
break; m_mouseGrabbed = false;
case sf::Event::KeyPressed: break;
action = kb.getPressedAction(event.key.code); case sf::Event::GainedFocus:
if(action != -1) m_mouseGrabbed = m_mouseWasGrabbed;
m_actions.push_back(action); break;
m_heldkeys.push_back(event.key.code); case sf::Event::TextEntered:
break; c = (char) event.text.unicode;
case sf::Event::KeyReleased: sf::Utf32::encodeAnsi(event.text.unicode,std::back_inserter(m_buffer));
action = kb.getReleasedAction(event.key.code); break;
if(action != -1) case sf::Event::KeyPressed:
m_actions.push_back(action); action = kb.getPressedAction(input::KEYBOARD,event.key.code);
releaseHeldKeys(event.key.code); if(!action.isNull())
break; m_actions.push_back(action);
case sf::Event::MouseButtonPressed: m_heldKeys.push_back(event.key.code);
action = kb.getPressedAction(sf::Keyboard::KeyCount + event.mouseButton.button); break;
if(action != -1) case sf::Event::KeyReleased:
m_actions.push_back(action); action = kb.getReleasedAction(input::KEYBOARD,event.key.code);
m_heldkeys.push_back((sf::Keyboard::Key) (sf::Keyboard::KeyCount + event.mouseButton.button)); if(!action.isNull())
break; m_actions.push_back(action);
case sf::Event::MouseButtonReleased: releaseHeldKeys(event.key.code);
action = kb.getReleasedAction(sf::Keyboard::KeyCount + event.mouseButton.button); break;
if(action != -1) case sf::Event::MouseWheelScrolled:
m_actions.push_back(action); if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel)
releaseHeldKeys((sf::Keyboard::Key) (sf::Keyboard::KeyCount + event.mouseButton.button)); m_delta_vertical_scroll = event.mouseWheelScroll.delta;
break; break;
case sf::Event::MouseWheelScrolled: case sf::Event::MouseButtonPressed:
if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel) action = kb.getPressedAction(input::MOUSE,event.mouseButton.button);
m_delta_vertical_scroll = event.mouseWheelScroll.delta; if(!action.isNull())
break; m_actions.push_back(action);
case sf::Event::MouseMoved: m_heldMouseButtons.push_back(event.mouseButton.button);
m_mouse_position = sf::Mouse::getPosition(*m_window); break;
break; case sf::Event::MouseButtonReleased:
case sf::Event::MouseEntered: action = kb.getReleasedAction(input::MOUSE,event.mouseButton.button);
// action MouseEntered if(!action.isNull())
break; m_actions.push_back(action);
case sf::Event::MouseLeft: releaseHeldMouseButton(event.mouseButton.button);
//action MouseLeft break;
break; case sf::Event::MouseMoved:
case sf::Event::Resized: m_mouse_position = sf::Mouse::getPosition(*m_window);
m_hasBeenResized = true; break;
if(m_mouseGrabbed) case sf::Event::MouseEntered:
m_last_mouse_position = sf::Vector2i(m_window->getSize())/2; // action MouseEntered
break; 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<int>();
break;
case sf::Event::JoystickDisconnected:
m_heldJoystickButtons.erase(event.joystickConnect.joystickId);
break;
} }
} }
if(m_mouseGrabbed) if(m_mouseGrabbed)
sf::Mouse::setPosition(m_last_mouse_position, *m_window); 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<int> Input::getActions() std::vector<Action> Input::getActions()
{ {
return m_actions; return m_actions;
} }
/* context-related functions */ /* 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(){ void Input::updateKeyBindings(){
m_keybindings.clear(); m_keybindings.clear();
for (auto iter= m_contexts.begin(); iter != m_contexts.end(); ++iter) 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); return sf::Keyboard::isKeyPressed((sf::Keyboard::Key) key);
} }
void Input::releaseHeldKeys(sf::Keyboard::Key keycode){ void Input::releaseHeldKeys(int keycode)
for(auto iter = m_heldkeys.begin();iter < m_heldkeys.end();) {
iter = *iter == keycode ? m_heldkeys.erase(iter) : iter+1; 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();iter<m_heldMouseButtons.end();)
iter = *iter == buttoncode ? m_heldMouseButtons.erase(iter) : iter+1;
}
void Input::releaseHeldJoystickButton(int buttoncode,int controller_id)
{
for(auto iter = m_heldJoystickButtons[controller_id].begin();iter<m_heldJoystickButtons[controller_id].end();)
iter = *iter == buttoncode ? m_heldJoystickButtons[controller_id].erase(iter) : iter+1;
} }
/* mouse-related functions */ /* mouse-related functions */
glm::vec2 Input::getPosition() const glm::vec2 Input::getPosition() const
{ {
return glm::vec2(m_mouse_position.x,m_mouse_position.y); return glm::vec2(m_mouse_position.x,m_mouse_position.y);
@ -185,6 +224,18 @@ void Input::setMouseGrabbed(bool isGrabbed)
m_last_mouse_position = sf::Vector2i(m_window->getSize())/2; m_last_mouse_position = sf::Vector2i(m_window->getSize())/2;
} }
std::vector<int> Input::getControllersConnected() const{
std::vector<int> 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() std::wstring Input::getText()
{ {
return m_buffer; return m_buffer;
@ -194,12 +245,12 @@ std::wstring Input::getText()
void Input::test() void Input::test()
{ {
KeyBindings kb = m_keybindings[m_current_context]; /* KeyBindings kb = m_keybindings[m_current_context];
int action; int action;
action = kb.getPressedAction(sf::Keyboard::I); action = kb.getPressedAction(sf::Keyboard::I);
if (action != NO_ACTION) if (action != NO_ACTION)
std::cerr << action << std::endl; std::cerr << action << std::endl;
action = kb.getPressedAction(sf::Keyboard::O); action = kb.getPressedAction(sf::Keyboard::O);
if (action != NO_ACTION) if (action != NO_ACTION)
std::cerr << action << std::endl; std::cerr << action << std::endl;*/
} }

View File

@ -7,6 +7,7 @@
#include "keybindings.h" #include "keybindings.h"
#include <queue> #include <queue>
#include <vector> #include <vector>
#include <map>
#include <unordered_map> #include <unordered_map>
#include "textbuffer.h" #include "textbuffer.h"
#include "glm/vec2.hpp" #include "glm/vec2.hpp"
@ -20,7 +21,7 @@ private:
/* general action-mapping variables */ /* general action-mapping variables */
IKeysMap m_keysmap; IKeysMap m_keysmap;
std::vector<int> m_actions; std::vector<Action> m_actions;
int nb_actions; int nb_actions;
/* context-related variables */ /* context-related variables */
@ -28,15 +29,23 @@ private:
std::vector<Context> m_contexts; std::vector<Context> m_contexts;
std::unordered_map<std::string,KeyBindings> m_keybindings; std::unordered_map<std::string,KeyBindings> m_keybindings;
/* keyboard-related variables */ /* keyboard */
std::vector<sf::Keyboard::Key> m_heldkeys; std::vector<int> m_heldKeys;
void releaseHeldKeys(sf::Keyboard::Key keycode); void releaseHeldKeys(int keycode);
/* mouse-related variables */ /* mouse */
sf::Vector2i m_mouse_position; sf::Vector2i m_mouse_position;
sf::Vector2i m_last_mouse_position; sf::Vector2i m_last_mouse_position;
float m_delta_vertical_scroll; float m_delta_vertical_scroll;
bool m_mouseGrabbed; bool m_mouseGrabbed;
bool m_mouseWasGrabbed;
std::vector<int> m_heldMouseButtons;
void releaseHeldMouseButton(int buttoncode);
/* joystick */
std::map<int,std::map<int,float>> m_joystick_position;
std::map<int,std::vector<int>> m_heldJoystickButtons;
void releaseHeldJoystickButton(int buttoncode, int controller_id);
/* text-related variable */ /* text-related variable */
std::wstring m_buffer; std::wstring m_buffer;
@ -47,10 +56,10 @@ public:
/* general action-mapping functions */ /* general action-mapping functions */
void setKeysMap(IKeysMap km); //set bindings void setKeysMap(IKeysMap km); //set bindings
void updateEvents(); //handle the input and put the associated event in the file void updateEvents(); //handle the input and put the associated event in the file
std::vector<int> getActions(); //get the first action in the file of event std::vector<Action> getActions(); //get the first action in the file of event
/* context-related functions */ /* 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;} std::string getCurrentContext(){return m_current_context;}
void setCurrentContext(std::string context_name){m_current_context = context_name;} void setCurrentContext(std::string context_name){m_current_context = context_name;}
void updateKeyBindings(); void updateKeyBindings();
@ -63,9 +72,7 @@ public:
bool isKeyPressed(int key) const; bool isKeyPressed(int key) const;
/* mouse-related function */ /* mouse-related function */
//sf::Vector2i getPosition() const;
glm::vec2 getPosition() const; glm::vec2 getPosition() const;
//sf::Vector2i getDeltaPosition() const;
glm::vec2 getDeltaPosition() const; glm::vec2 getDeltaPosition() const;
float getDeltaVerticalScroll() const; float getDeltaVerticalScroll() const;
@ -74,6 +81,10 @@ public:
void toggleMouseGrab() { setMouseGrabbed(!m_mouseGrabbed); } void toggleMouseGrab() { setMouseGrabbed(!m_mouseGrabbed); }
bool isMouseGrabbed() const { return m_mouseGrabbed; } bool isMouseGrabbed() const { return m_mouseGrabbed; }
/* joystick-related function */
std::vector<int> getControllersConnected() const;
float getAxisPosition(int device_id, int axis_id);
/* text-related function */ /* text-related function */
std::wstring getText(); std::wstring getText();

View File

@ -15,13 +15,17 @@ IKeysMap::IKeysMap()
} }
std::vector<Binding> IKeysMap::getBindings(int action) const { std::vector<Binding> IKeysMap::getBindings(Action action) const {
std::vector<Binding> bindings; std::vector<Binding> bindings;
for (auto binding : keys) for (auto binding : keys)
if (binding.action == action) bindings.push_back(binding); if (binding.action.action == action.action) bindings.push_back(binding);
return bindings; return bindings;
} }
Action Action::getNull(){
return {NO_ACTION,input::NONE};
}
/* Implementation of KeyBindings class /* Implementation of KeyBindings class
* @author: Thomas Brandého * @author: Thomas Brandého
* @info: This class map a list of action with the associated keys, for a quick access in-game. * @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) 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)){ for (Binding binding : keysmap.getBindings(action)){
switch(binding.type){ switch(binding.type){
case IKeysMap::PRESSED: case IKeysMap::PRESSED:
@ -55,75 +60,64 @@ KeyBindings::KeyBindings(const Context &context, const IKeysMap &keysmap)
} }
Action KeyBindings::getPressedAction(input::Source src, int key) const
int KeyBindings::getPressedAction(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, Action action)
void KeyBindings::setPressedAction(int key, int 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<int,int>();
bindings_released[i] = std::unordered_map<int,int>();
bindings_hold[i] = std::unordered_map<int,int>();
}
}
/* Implementation of Context class /* Implementation of Context class
* @author: Thomas Brandého * @author: Thomas Brandého
* @info: This class contains a list of actions available in a given situation (context). * @info: This class contains a list of actions available in a given situation (context).
*/ */
Context::Context(std::string _name, std::vector<int> _actions): name(_name), actions(_actions) Context::Context(std::string _name, std::vector<Action> _actions): name(_name), actions(_actions)
{ {
} }
std::string Context::getName() std::string Context::getName()
{ {
return name; return name;
} }
std::vector<int> Context::getActions() const std::vector<Action> Context::getActions() const
{ {
return actions; return actions;
} }

View File

@ -12,47 +12,64 @@
#define NO_KEY -1 #define NO_KEY -1
#define NO_ACTION -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{ struct Binding{
int action; Action action;
int key; int key;
int type; int type;
}; };
//write a function to add new Binding?
class IKeysMap{ class IKeysMap{
public: public:
enum {PRESSED, RELEASED, HOLD}; enum {PRESSED, RELEASED, HOLD};
IKeysMap(); IKeysMap();
std::vector<Binding> getBindings(int action) const; std::vector<Binding> getBindings(Action action) const;
protected: protected:
std::vector<Binding> keys; std::vector<Binding> keys;
}; };
class Context { class Context {
public: public:
Context(std::string name, std::vector<int> actions); Context(std::string name, std::vector<Action> actions);
std::string getName(); std::string getName();
std::vector<int> getActions() const; std::vector<Action> getActions() const;
private: private:
std::string name; std::string name;
std::vector<int> actions; std::vector<Action> actions;
}; };
class KeyBindings { class KeyBindings {
public: public:
KeyBindings(); KeyBindings();
KeyBindings(const Context &context, const IKeysMap &keysmap); KeyBindings(const Context &context, const IKeysMap &keysmap);
int getPressedAction(int key) const; Action getPressedAction(input::Source src,int key) const;
int getReleasedAction(int key) const; Action getReleasedAction(input::Source src,int key) const;
int getHoldAction(int key) const; Action getHoldAction(input::Source src,int key) const;
private: private:
std::unordered_map<int,int> bindings_pressed; std::unordered_map<int,std::unordered_map<int,int>> bindings_pressed;
std::unordered_map<int,int> bindings_released; std::unordered_map<int,std::unordered_map<int,int>> bindings_released;
std::unordered_map<int,int> bindings_hold; std::unordered_map<int,std::unordered_map<int,int>> bindings_hold;
void setPressedAction(int key, int action); void setPressedAction(int key, Action action);
void setReleasedAction(int key, int action); void setReleasedAction(int key, Action action);
void setHoldAction(int key, int action); void setHoldAction(int key, Action action);
void init_map_bindings();
}; };
#endif #endif

View File

@ -1,23 +1,55 @@
#include <iostream> #include <iostream>
#include <SFML/Window.hpp> #include <SFML/Window.hpp>
#include "input.h" #include "input.h"
//#include "keybindings.h"
using namespace std; 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<Action> getTestContext()
{
return
{
{LEFT_CLICK,input::MOUSE},
{RIGHT_CLICK,input::MOUSE},
{ACTION,input::CONTROLLER}
};
}
};
int main() int main()
{ {
cerr << "Hello World!"<< endl; cerr << "Hello World!"<< endl;
sf::Window* window= new sf::Window(sf::VideoMode(400,200),"testSparrowInput"); sf::Window* window= new sf::Window(sf::VideoMode(400,200),"testSparrowInput");
Input myInput(window); Input myInput(window);
enum {ACTION_1,ACTION_2};
std::vector<int> 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->setKeyBinding(ACTION_2,0,sf::Keyboard::Z);
// keymap->setTypeAction(ACTION_2,KeysMap::RELEASED); // keymap->setTypeAction(ACTION_2,KeysMap::RELEASED);
@ -51,7 +83,7 @@ int main()
// while (action = myInput.getAction() != NO_ACTION) // while (action = myInput.getAction() != NO_ACTION)
// cout << "test " << action << endl; // cout << "test " << action << endl;
// window->display(); // window->display();
// } // }*/
cerr << "Successfully ended" << endl; cerr << "Successfully ended" << endl;
return 0; return 0;
} }