From 82f04dbeb68334510293785bf95c2dccca4726be Mon Sep 17 00:00:00 2001 From: Kai Sterker Date: Sun, 17 Oct 2010 17:34:26 +0200 Subject: [PATCH] UPDATED input mapping. Multiple controls can now be assigned to an action. They are stored in the configuration file as a pipe separated string, i.e. left shift|right shift space left control|right control escape right up down left --- src/base/configuration.cc | 34 ++++++++++++++++++ src/base/configuration.h | 8 +++++ src/input/control_event.cc | 71 ++++++++++++++++++++++---------------- 3 files changed, 83 insertions(+), 30 deletions(-) diff --git a/src/base/configuration.cc b/src/base/configuration.cc index 6838286..9efe4e4 100644 --- a/src/base/configuration.cc +++ b/src/base/configuration.cc @@ -403,3 +403,37 @@ string configuration::create_filename (const string & name) const // add file name to configuration data directory return base::Paths.cfg_data_dir () + name + ".xml"; } + +vector configuration::split_value (const string & values, const char & separator) +{ + string::size_type i, idx, pos = 0; + vector result; + + // split pipe separated list of controls + do + { + idx = values.find (separator, pos); + string value = values.substr (pos, idx - pos); + + // trim whitespace + if ((i = value.find_last_not_of(' ')) != string::npos) + { + // strip back + value.erase (i + 1); + if ((i = value.find_first_not_of(' ')) != string::npos) + { + // strip front + value.erase (0, i); + } + + // found a possibly valid control + result.push_back (value); + } + // else: only whitespace, so we skip it + + pos = idx + 1; + } + while (idx != string::npos); + + return result; +} diff --git a/src/base/configuration.h b/src/base/configuration.h index 57f9512..55a15ab 100644 --- a/src/base/configuration.h +++ b/src/base/configuration.h @@ -323,6 +323,14 @@ namespace base * @return %configuration setting. */ string get_string (const string & section, const string & option, const string & value); + + /** + * Split a string of values into the individual tokens. + * @param values a string of values, delimited by a special character. + * @param separator the delimiting character. Default is a pipe ('|'). + * @return list of individual values, with whitespace trimmed. + */ + static vector split_value (const string & values, const char & separator = '|'); //@} /** diff --git a/src/input/control_event.cc b/src/input/control_event.cc index 9d119ac..4a42809 100644 --- a/src/input/control_event.cc +++ b/src/input/control_event.cc @@ -69,8 +69,8 @@ namespace input keyboard_event::DOWN_KEY, keyboard_event::RIGHT_KEY, keyboard_event::LEFT_KEY, - keyboard_event::LSHIFT_KEY, // run - keyboard_event::SPACE_KEY, // jump + keyboard_event::LSHIFT_KEY, // run + keyboard_event::SPACE_KEY, // jump keyboard_event::LCTRL_KEY, keyboard_event::ESCAPE_KEY }; @@ -86,42 +86,53 @@ namespace input // read setting for each of our controls for (u_int32 i = control_event::UP_BUTTON; i < control_event::NBR_BUTTONS; i++) { - control_event::button_type btn = (control_event::button_type) i; + control_event::button_type btn = (control_event::button_type) i; // get name of control (= config option) key = control_event::name_for_button ((control_event::button_type) btn); - // get mapped control, using given default if not set yet - value = cfg.get_string ("Input", key, keyboard_event::name_for_key (default_key (btn))); - - // setup internal mapping tables - keyboard_event::key_type kt = keyboard_event::key_for_name (value); - if (kt != keyboard_event::UNKNOWN_KEY) - { - map_keyboard_key (kt, (control_event::button_type) btn); - continue; - } - - mouse_event::button_type mb = mouse_event::button_for_name (value); - if (mb != mouse_event::NO_BUTTON) + // get mapped controls, using given default if not set yet + std::string control_list = cfg.get_string ("Input", key, keyboard_event::name_for_key (default_key (btn))); + + std::vector controls = base::configuration::split_value (control_list); + if (controls.empty()) { - map_mouse_button (mb, (control_event::button_type) btn); - continue; + // controls might be empty if there was a configuration error + controls.push_back (keyboard_event::name_for_key (default_key (btn))); } - - joystick_event::button_type jb = joystick_event::button_for_name (value); - if (jb != joystick_event::NO_BUTTON) + + // we're guaranteed to get back at least one value (the default) + for (std::vector::const_iterator value = controls.begin(); value != controls.end(); value++) { - // TODO: get proper joystick number - map_joystick_button (0, jb, (control_event::button_type) btn); - continue; + // setup internal mapping tables + keyboard_event::key_type kt = keyboard_event::key_for_name (*value); + if (kt != keyboard_event::UNKNOWN_KEY) + { + map_keyboard_key (kt, (control_event::button_type) btn); + continue; + } + + mouse_event::button_type mb = mouse_event::button_for_name (*value); + if (mb != mouse_event::NO_BUTTON) + { + map_mouse_button (mb, (control_event::button_type) btn); + continue; + } + + joystick_event::button_type jb = joystick_event::button_for_name (*value); + if (jb != joystick_event::NO_BUTTON) + { + // TODO: get proper joystick number + map_joystick_button (0, jb, (control_event::button_type) btn); + continue; + } + + // invalid control value --> use default, but don't update configuration + fprintf (stderr, "*** control_event::map_controls: unknown control '%s' for action '%s'!\n", value->c_str(), key.c_str()); + kt = default_key (btn); + fprintf (stderr, " substituting default key '%s' instead!\n", keyboard_event::name_for_key (kt).c_str ()); + map_keyboard_key (kt, (control_event::button_type) btn); } - - // invalid control value --> use default, but don't update configuration - fprintf (stderr, "*** control_event::map_controls: unknown control '%s' for action '%s'!\n", value.c_str(), key.c_str()); - kt = default_key (btn); - fprintf (stderr, " substituting default key '%s' instead!\n", keyboard_event::name_for_key (kt).c_str ()); - map_keyboard_key (kt, (control_event::button_type) btn); } }