diff --git a/src/Makefile.am b/src/Makefile.am
index 618ac65f8..14d036f9d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,6 +46,8 @@ supertuxkart_SOURCES = \
config/stk_config.hpp \
config/user_config.cpp \
config/user_config.hpp \
+ config/device_config.cpp \
+ config/device_config.hpp \
graphics/camera.cpp \
graphics/camera.hpp \
graphics/explosion.cpp \
diff --git a/src/config/device_config.cpp b/src/config/device_config.cpp
new file mode 100644
index 000000000..2ef589f37
--- /dev/null
+++ b/src/config/device_config.cpp
@@ -0,0 +1,267 @@
+#include "config/device_config.hpp"
+
+//==== D E V I C E C O N F I G =================================================
+
+std::string DeviceConfig::getBindingAsString (const PlayerAction action) const
+{
+ std::string returnString = NULL;
+
+ if ((action < PA_COUNT) && (action >= 0))
+ {
+ returnString = Input::getInputAsString(m_bindings[action].type,
+ m_bindings[action].id,
+ m_bindings[action].dir);
+ }
+
+ return returnString;
+}
+
+//------------------------------------------------------------------------------
+
+std::string DeviceConfig::toString ()
+{
+ std::string returnString = "";
+ for (int n = 0; n < PA_COUNT; n++)
+ {
+ returnString = returnString.append(KartActionStrings[n]);
+ returnString = returnString.append(": ");
+ returnString = returnString.append(Input::getInputAsString(m_bindings[n].type,
+ m_bindings[n].id,
+ m_bindings[n].dir));
+ returnString = returnString.append("\n");
+ }
+ return returnString;
+}
+
+//------------------------------------------------------------------------------
+
+void DeviceConfig::setBinding ( const PlayerAction action,
+ const Input::InputType type,
+ const int id,
+ Input::AxisDirection direction )
+{
+ m_bindings[action].type = type;
+ m_bindings[action].id = id;
+ m_bindings[action].dir = direction;
+}
+
+//------------------------------------------------------------------------------
+
+bool DeviceConfig::getBinding ( Input::InputType type,
+ const int id,
+ const int value,
+ PlayerAction* action )
+{
+ bool success = false;
+ int n;
+
+ for (n = 0; ((n < PA_COUNT) && (!success)); n++)
+ {
+ if ((m_bindings[n].type == type) && (m_bindings[n].id == id))
+ {
+
+ if (type == Input::IT_STICKMOTION)
+ {
+ if ((m_bindings[n].dir == Input::AD_POSITIVE) && (value > 0) ||
+ (m_bindings[n].dir == Input::AD_NEGATIVE) && (value < 0))
+ {
+ success = true;
+ *action = (PlayerAction)n;
+ }
+ }
+ else
+ {
+ success = true;
+ *action = (PlayerAction)n;
+ }
+ }
+ } // end for n
+
+ return success;
+}
+
+//------------------------------------------------------------------------------
+
+void DeviceConfig::serialize (std::ofstream& stream)
+{
+ for(int n=0; n\n";
+ }
+}
+
+//------------------------------------------------------------------------------
+
+bool DeviceConfig::deserializeAction(irr::io::IrrXMLReader* xml)
+{
+ bool success = false;
+ int binding_id = -1;
+ int id;
+ Input::InputType type;
+ Input::AxisDirection dir;
+
+ // Never hurts to check ;)
+ if (xml == NULL)
+ {
+ fprintf(stderr, "Error: null pointer (DeviceConfig::deserializeAction)\n");
+ }
+ else
+ {
+ // Read tags from XML
+ const char *name_string = xml->getAttributeValue("name");
+ const char *id_string = xml->getAttributeValue("id");
+ const char *event_string = xml->getAttributeValue("event");
+ const char *dir_string = xml->getAttributeValue("direction");
+
+ // Proceed only if neccesary tags were found
+ if ((name_string != NULL) && (id_string != NULL) &&
+ (event_string != NULL))
+ {
+ // Convert strings to string tags to integer types
+ type = (Input::InputType)atoi(event_string);
+ id = atoi(id_string);
+
+ // Try to determine action # for verbose action name
+ for (int n = 0; ((n < PA_COUNT) && (binding_id == -1)); n++)
+ {
+ if (strcmp(name_string, KartActionStrings[n].c_str()) == 0)
+ binding_id = n;
+ }
+
+ // If action # was found then store the bind
+ if (binding_id != -1)
+ {
+ // If the action is not a stick motion (button or key)
+ if (type != Input::IT_STICKMOTION)
+ {
+ setBinding((PlayerAction)binding_id, type, id);
+ success = true;
+ }
+
+ // If the action is a stick motion & a direction is defined
+ else if (dir_string != NULL)
+ {
+ dir = (Input::AxisDirection)atoi(dir_string);
+ setBinding((PlayerAction)binding_id, type, id, dir);
+ success = true;
+ }
+ else
+ {
+ printf("WARNING: IT_STICKMOTION without direction, ignoring.\n");
+ }
+ } // end if binding_id != -1
+ } // end if name_string != NULL ...
+ } // end if xml == NULL ... else
+
+ return success;
+}
+
+
+// KeyboardConfig & GamepadConfig classes really should be in a separate cpp
+// file but they are so small that we'll just leave them here for now.
+
+//==== K E Y B O A R D C O N F I G =============================================
+
+void KeyboardConfig::serialize (std::ofstream& stream)
+{
+ stream << "\n\n";
+ DeviceConfig::serialize(stream);
+ stream << "\n\n\n";
+}
+
+//------------------------------------------------------------------------------
+
+void KeyboardConfig::setDefaultBinds()
+{
+ setBinding(PA_NITRO, Input::IT_KEYBOARD, KEY_KEY_N);
+ setBinding(PA_ACCEL, Input::IT_KEYBOARD, KEY_UP);
+ setBinding(PA_BRAKE, Input::IT_KEYBOARD, KEY_DOWN);
+ setBinding(PA_LEFT, Input::IT_KEYBOARD, KEY_LEFT);
+ setBinding(PA_RIGHT, Input::IT_KEYBOARD, KEY_RIGHT);
+ setBinding(PA_DRIFT, Input::IT_KEYBOARD, KEY_KEY_V);
+ setBinding(PA_RESCUE, Input::IT_KEYBOARD, KEY_BACK);
+ setBinding(PA_FIRE, Input::IT_KEYBOARD, KEY_SPACE);
+ setBinding(PA_LOOK_BACK, Input::IT_KEYBOARD, KEY_KEY_B);
+}
+
+//------------------------------------------------------------------------------
+
+KeyboardConfig::KeyboardConfig()
+{
+ setDefaultBinds();
+}
+
+//==== G A M E P A D C O N F I G ===============================================
+
+void GamepadConfig::serialize (std::ofstream& stream)
+{
+ stream << "\n\n";
+ DeviceConfig::serialize(stream);
+ stream << "\n\n\n";
+}
+
+//------------------------------------------------------------------------------
+
+void GamepadConfig::setDefaultBinds ()
+{
+ setBinding(PA_LEFT, Input::IT_STICKMOTION, 0, Input::AD_NEGATIVE);
+ setBinding(PA_RIGHT, Input::IT_STICKMOTION, 0, Input::AD_POSITIVE);
+ setBinding(PA_ACCEL, Input::IT_STICKMOTION, 1, Input::AD_NEGATIVE);
+ setBinding(PA_BRAKE, Input::IT_STICKMOTION, 1, Input::AD_POSITIVE);
+ setBinding(PA_FIRE, Input::IT_STICKBUTTON, 0);
+ setBinding(PA_NITRO, Input::IT_STICKBUTTON, 1);
+ setBinding(PA_DRIFT, Input::IT_STICKBUTTON, 2);
+ setBinding(PA_RESCUE, Input::IT_STICKBUTTON, 3);
+ setBinding(PA_LOOK_BACK, Input::IT_STICKBUTTON, 4);
+ //TODO - mappings for clear/enter/leave GA_CLEAR_MAPPING, GA_ENTER, GA_LEAVE?
+}
+
+//------------------------------------------------------------------------------
+
+GamepadConfig::GamepadConfig ( const std::string name,
+ const int axis_count,
+ const int btnCount )
+{
+ m_name = name;
+ m_axis_count = axis_count;
+ m_button_count = btnCount;
+ setDefaultBinds();
+}
+
+//------------------------------------------------------------------------------
+
+GamepadConfig::GamepadConfig(irr::io::IrrXMLReader* xml)
+{
+ const char* name_string = xml->getAttributeValue("name");
+ if(name_string == NULL)
+ {
+ printf("ERROR: Unnamed joystick in config file\n");
+ }
+ else
+ {
+ m_name = name_string;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+std::string GamepadConfig::toString ()
+{
+ std::string returnString = "";
+ returnString = returnString.append(getName());
+ returnString = returnString.append("\n");
+ returnString = returnString.append(DeviceConfig::toString());
+ return returnString;
+}
diff --git a/src/config/device_config.hpp b/src/config/device_config.hpp
new file mode 100644
index 000000000..0bac79f2e
--- /dev/null
+++ b/src/config/device_config.hpp
@@ -0,0 +1,96 @@
+#ifndef DEVICE_CONFIG_HPP
+#define DEVICE_CONFIG_HPP
+
+#include
+#include "input/input.hpp"
+#include
+#include
+#include "io/xml_node.hpp"
+
+
+struct KeyBinding
+{
+
+ Input::InputType type;
+ int id;
+ Input::AxisDirection dir;
+
+};
+
+
+//==== D E V I C E C O N F I G =================================================
+
+class DeviceConfig
+{
+ private:
+
+ KeyBinding m_bindings[PA_COUNT];
+
+ protected:
+
+ public:
+
+ std::string getBindingAsString (const PlayerAction action) const;
+ std::string toString ();
+
+ void serialize (std::ofstream& stream);
+ bool deserializeAction (irr::io::IrrXMLReader* xml);
+
+ void setBinding (const PlayerAction action,
+ const Input::InputType type,
+ const int id,
+ Input::AxisDirection direction = Input::AD_NEUTRAL);
+
+ bool getBinding (Input::InputType type,
+ const int id,
+ const int value,
+ PlayerAction* action);
+
+};
+
+//==== K E Y B O A R D C O N F I G =============================================
+
+class KeyboardConfig : public DeviceConfig
+{
+ private:
+
+ protected:
+
+ public:
+
+ void setDefaultBinds ();
+ void serialize (std::ofstream& stream);
+
+// KeyboardConfig (irr::io::IrrXMLReader* xml);
+ KeyboardConfig ();
+};
+
+
+//==== G A M E P A D C O N F I G ===============================================
+
+class GamepadConfig : public DeviceConfig
+{
+
+ private:
+
+ std::string m_name;
+ int m_axis_count;
+ int m_button_count;
+
+ public:
+
+ std::string toString ();
+ std::string getName() const { return m_name; };
+ int getAxisCount() const { return m_axis_count; };
+ int getButtonCount() const { return m_button_count; };
+ void serialize (std::ofstream& stream);
+ void setDefaultBinds ();
+ GamepadConfig (irr::io::IrrXMLReader* xml);
+ GamepadConfig (const std::string name,
+ const int axis_count,
+ const int btnCount);
+// ~GamepadConfig();
+
+};
+
+#endif
diff --git a/src/input/device_manager.cpp b/src/input/device_manager.cpp
index e047699c8..045b5b3ee 100644
--- a/src/input/device_manager.cpp
+++ b/src/input/device_manager.cpp
@@ -12,7 +12,8 @@
DeviceManager::DeviceManager()
{
- m_keyboard_amount = 0;
+ m_keyboards.push_back(new KeyboardDevice());
+ m_keyboard_amount = m_keyboards.size();
m_gamepad_amount = 0;
m_latest_used_device = NULL;
m_assign_mode = NO_ASSIGN;
@@ -20,24 +21,24 @@ DeviceManager::DeviceManager()
// -----------------------------------------------------------------------------
bool DeviceManager::initGamePadSupport()
{
+ GamepadConfig *gamepadConfig;
+ bool something_new_to_write = true;
+
// Prepare a list of connected joysticks.
std::cout << "====================\nGamePad/Joystick detection and configuration\n====================\n";
irr_driver->getDevice()->activateJoysticks(m_irrlicht_gamepads);
+ const int numSticks = m_irrlicht_gamepads.size();
- const int numSticks = m_irrlicht_gamepads.size();
std::cout << "irrLicht detects " << numSticks << " gamepads" << std::endl;
-
- bool something_new_to_write = false;
-
- // check if it's a new gamepad. If so, add it to the file.
+
for (int i = 0; i < numSticks; i++)
{
std::cout << m_irrlicht_gamepads[i].Name.c_str() << " : "
<< m_irrlicht_gamepads[i].Axes << " axes , "
<< m_irrlicht_gamepads[i].Buttons << " buttons\n";
-
- if(checkForGamePad(i)) something_new_to_write = true;
+ gamepadConfig = getGamepadConfig(i);
+ add(new GamePadDevice(i, m_irrlicht_gamepads[i].Name.c_str(), m_irrlicht_gamepads[i].Axes, m_irrlicht_gamepads[i].Buttons, gamepadConfig));
}
std::cout << "====================\n";
@@ -78,32 +79,36 @@ GamePadDevice* DeviceManager::getGamePadFromIrrID(const int id)
}
// -----------------------------------------------------------------------------
/**
- * Check if we already have a config object for joystick 'irr_id' as reported by irrLicht
- * If yes, 'open' the gamepad. If no, create one. Returns whether a new gamepad was created.
+ * Check if we already have a config object for gamepad 'irr_id' as reported by irrLicht
+ * If yes, return a pointer to the configuration. If no, create one. Returns pointer.
*/
-bool DeviceManager::checkForGamePad(const int irr_id)
+GamepadConfig *DeviceManager::getGamepadConfig(const int irr_id)
{
std::string name = m_irrlicht_gamepads[irr_id].Name.c_str();
+ GamepadConfig *config = NULL;
- std::cout << "trying to find gamepad " << name.c_str() << std::endl;
+ std::cout << "trying to find gamepad configuration" << name.c_str() << std::endl;
- for(unsigned int n=0; n that's the one currently connected\n";
- m_gamepads[n].open(irr_id, m_gamepads[n].m_name, m_irrlicht_gamepads[irr_id].Axes, m_irrlicht_gamepads[irr_id].Buttons);
- return false;
+ config = m_gamepad_configs.get(n);
}
}
- std::cout << "couldn't find this joystick, so creating a new one" << std::endl;
- add(new GamePadDevice(irr_id, m_irrlicht_gamepads[irr_id].Name.c_str(), m_irrlicht_gamepads[irr_id].Axes, m_irrlicht_gamepads[irr_id].Buttons ));
- return true;
+ if (config == NULL)
+ {
+ std::cout << "couldn't find a configuration for this gamepad, creating one" << std::endl;
+ config = new GamepadConfig(m_irrlicht_gamepads[irr_id].Name.c_str(), m_irrlicht_gamepads[irr_id].Axes, m_irrlicht_gamepads[irr_id].Buttons);
+ m_gamepad_configs.push_back(config);
+ }
+ return config;
}
// -----------------------------------------------------------------------------
void DeviceManager::add(KeyboardDevice* d)
@@ -295,8 +300,8 @@ bool DeviceManager::deserialize()
int reading_now = NOTHING;
- KeyboardDevice* keyboard_device;
- GamePadDevice* gamepad_device;
+ KeyboardConfig* keyboard_config = NULL;
+ GamepadConfig* gamepad_config = NULL;
// parse XML file
while(xml && xml->read())
@@ -310,25 +315,27 @@ bool DeviceManager::deserialize()
{
if (strcmp("keyboard", xml->getNodeName()) == 0)
{
- keyboard_device = new KeyboardDevice(xml);
+ keyboard_config = new KeyboardConfig();
reading_now = KEYBOARD;
}
else if (strcmp("gamepad", xml->getNodeName()) == 0)
{
- gamepad_device = new GamePadDevice(xml);
+ gamepad_config = new GamepadConfig(xml);
reading_now = GAMEPAD;
}
else if (strcmp("action", xml->getNodeName()) == 0)
{
if(reading_now == KEYBOARD)
{
- if(!keyboard_device->deserializeAction(xml))
- std::cerr << "Ignoring an ill-formed action in input config\n";
+ if(keyboard_config != NULL)
+ if(!keyboard_config->deserializeAction(xml))
+ std::cerr << "Ignoring an ill-formed action in input config\n";
}
else if(reading_now == GAMEPAD)
{
- if(!gamepad_device->deserializeAction(xml))
- std::cerr << "Ignoring an ill-formed action in input config\n";
+ if(gamepad_config != NULL)
+ if(!gamepad_config->deserializeAction(xml))
+ std::cerr << "Ignoring an ill-formed action in input config\n";
}
else std::cerr << "Warning: An action is placed in an unexpected area in the input config file\n";
}
@@ -339,13 +346,13 @@ bool DeviceManager::deserialize()
{
if (strcmp("keyboard", xml->getNodeName()) == 0)
{
- add(keyboard_device);
+ m_keyboard_configs.push_back(keyboard_config);
reading_now = NOTHING;
}
else if (strcmp("gamepad", xml->getNodeName()) == 0)
{
- add(gamepad_device);
- reading_now = GAMEPAD;
+ m_gamepad_configs.push_back(gamepad_config);
+ reading_now = NOTHING;
}
}
break;
@@ -354,6 +361,15 @@ bool DeviceManager::deserialize()
} // end switch
} // end while
+
+ if (m_keyboard_configs.size() == 0)
+ m_keyboard_configs.push_back(new KeyboardConfig());
+
+ for (int n = 0; n < m_keyboard_configs.size(); n++)
+ printf("%s\n", m_keyboard_configs[n].toString().c_str());
+
+ for (int n = 0; n < m_gamepad_configs.size(); n++)
+ printf("%s\n", m_gamepad_configs[n].toString().c_str());
return true;
}
@@ -377,13 +393,13 @@ void DeviceManager::serialize()
configfile << "\n\n";
- for(unsigned int n=0; n\n";
diff --git a/src/input/device_manager.hpp b/src/input/device_manager.hpp
index a9c47b450..1dd3e4dda 100644
--- a/src/input/device_manager.hpp
+++ b/src/input/device_manager.hpp
@@ -2,6 +2,7 @@
#define DEVICE_MANAGER_HPP
#include "input/input_device.hpp"
+#include "config/device_config.hpp"
#include "utils/ptr_vector.hpp"
enum PlayerAssignMode
@@ -13,8 +14,10 @@ enum PlayerAssignMode
class DeviceManager
{
- ptr_vector m_keyboards;
- ptr_vector m_gamepads;
+ ptr_vector m_keyboards;
+ ptr_vector m_gamepads;
+ ptr_vector m_keyboard_configs;
+ ptr_vector m_gamepad_configs;
core::array m_irrlicht_gamepads;
@@ -60,7 +63,7 @@ public:
/* returns whether a new gamepad was detected */
bool initGamePadSupport();
- bool checkForGamePad(const int sdl_id);
+ GamepadConfig *getGamepadConfig(const int sdl_id);
};
diff --git a/src/input/input_device.cpp b/src/input/input_device.cpp
index 63b162e72..de9ce6310 100644
--- a/src/input/input_device.cpp
+++ b/src/input/input_device.cpp
@@ -1,10 +1,12 @@
#include "states_screens/state_manager.hpp"
+#include "config/device_config.hpp"
#include "input/input.hpp"
#include "input/input_device.hpp"
#include "modes/world.hpp"
#include "race/race_manager.hpp"
+
InputDevice::InputDevice()
{
for(int n=0; ngetBinding(Input::IT_KEYBOARD, key_id, 0, action);
}
// -----------------------------------------------------------------------------
@@ -193,11 +203,15 @@ GamePadDevice::GamePadDevice(irr::io::IrrXMLReader* xml)
* (defaults will be used)
* \param sdlIndex Index of stick.
*/
-GamePadDevice::GamePadDevice(const int irrIndex, const std::string name, const int axis_count, const int btnAmount)
+GamePadDevice::GamePadDevice(const int irrIndex, const std::string name, const int axis_count, const int btnAmount, GamepadConfig *configuration)
{
m_type = DT_GAMEPAD;
m_deadzone = DEADZONE_JOYSTICK;
m_prevAxisDirections = NULL;
+ m_configuration = configuration;
+
+ printf("New Gamepad Created. Assigned the following configuration:\n%s", m_configuration->toString().c_str());
+
open(irrIndex, name, axis_count, btnAmount);
m_name = name;
@@ -365,40 +379,9 @@ bool GamePadDevice::hasBinding(Input::InputType type, const int id, const int va
return false;
}
-
- // find corresponding action and return it
- for(int n=0; n 0)
- {
- *action = (PlayerAction)n;
- return true;
- }
- }
- }// next device
-
- }
- else if(type == Input::IT_STICKBUTTON)
- {
- // find corresponding action and return it
- for(int n=0; ngetBinding(type, id, value, action);
}
// -----------------------------------------------------------------------------
/** Destructor for GamePadDevice.
diff --git a/src/input/input_device.hpp b/src/input/input_device.hpp
index 686990bff..188e10843 100644
--- a/src/input/input_device.hpp
+++ b/src/input/input_device.hpp
@@ -3,6 +3,7 @@
#include
#include "input/input.hpp"
+#include "config/device_config.hpp"
#include
#include
#include "io/xml_node.hpp"
@@ -15,16 +16,6 @@ enum DeviceType
DT_GAMEPAD
};
-struct KeyBinding
-{
- Input::InputType type;
-
- // key for keyboards, axis for gamepads
- int id;
-
- Input::AxisDirection dir; // for gamepads
-};
-
class InputDevice
{
friend class DeviceManager;
@@ -55,7 +46,10 @@ public:
class KeyboardDevice : public InputDevice
{
public:
+ KeyboardConfig *m_configuration;
+
KeyboardDevice();
+ KeyboardDevice(KeyboardConfig *configuration);
KeyboardDevice(irr::io::IrrXMLReader* xml);
/** checks if this key belongs to this belongs. if yes, sets action and returns true; otherwise returns false */
@@ -70,7 +64,9 @@ class GamePadDevice : public InputDevice
{
void resetAxisDirection(const int axis, Input::AxisDirection direction, ActivePlayer* player);
bool m_buttonPressed[SEvent::SJoystickEvent::NUMBER_OF_BUTTONS];
+
public:
+ GamepadConfig *m_configuration;
int m_deadzone;
int m_index;
int m_axis_count;
@@ -88,7 +84,7 @@ public:
void loadDefaults();
- GamePadDevice(const int irrIndex, const std::string name, const int axis_number, const int btnAmount);
+ GamePadDevice(const int irrIndex, const std::string name, const int axis_number, const int btnAmount, GamepadConfig *configuration);
GamePadDevice(irr::io::IrrXMLReader* xml);
bool isButtonPressed(const int i);
diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp
index 4ed7c8422..89f876201 100644
--- a/src/input/input_manager.cpp
+++ b/src/input/input_manager.cpp
@@ -65,7 +65,6 @@ InputManager::InputManager() : m_sensed_input(0), m_mode(BOOTSTRAP),
// could not read config file so use defaults
KeyboardDevice* default_device = new KeyboardDevice();
default_device->loadDefaults();
- m_device_manager->add( default_device );
something_new_to_write = true;
}