Major reworking of key configuration internals.
VControl no longer uses a custom configuration format; instead, control bindings are read in from the standard resource system. Menu controls are specified in menu.key in the content; flight controls are now copied from uqm.key to flight.cfg instead of from starcon.key to uqm.key. This change permits significant streamlining of the VControl code itself, and allows more fine-grained control over what the key configuration code iself does. This update thus closes both Bug #949 and Bug #961. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2705 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
Changes towards version 0.7:
|
||||
- Major refactoring of input configuration to use the resource system
|
||||
instead of custom files (bugs #961 and #949) - Michael
|
||||
- Added ability to remove entries from ALists - Michael
|
||||
- Cleaned up FRAME, CONTEXT, and FONT abstraction layers - Michael
|
||||
- Added Input Frames to pause code to stop infinite loops - Michael
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# Keyboard control definitions for the menus. Most keys can be
|
||||
# described in a straightforward manner; consult the name table in
|
||||
# src/sc2code/libs/input/sdl/keynames.c for the names of unusual keys.
|
||||
# Most keys can be named by just the symbol they produce.
|
||||
|
||||
# Menu controls. Both sets of arrow keys, basically. Paging controls
|
||||
# moving quickly through the file lists in Super Melee. Zooming
|
||||
# controls zoom controls in the starmap. "Cancel" is also used to get
|
||||
# you into menu mode to begin with. There is a "menu.Special" command
|
||||
# currently unused by the game. It seems to have been originally used
|
||||
# to call up details on starships in the Super Melee selection screen.
|
||||
|
||||
# Arrow key controls...
|
||||
menu.up.1 = key Up
|
||||
menu.down.1 = key Down
|
||||
menu.right.1 = key Right
|
||||
menu.left.1 = key Left
|
||||
menu.pageup.1 = key PageUp
|
||||
menu.pagedown.1 = key PageDown
|
||||
menu.home.1 = key Home
|
||||
menu.end.1 = key End
|
||||
menu.zoomin.1 = key PageUp
|
||||
menu.zoomout.1 = key PageDown
|
||||
menu.select.1 = key Return
|
||||
menu.select.2 = key RightControl
|
||||
menu.cancel.1 = key Space
|
||||
menu.cancel.2 = key RightShift
|
||||
|
||||
# ... and the number pad. Note that zoom controls on the starmap are
|
||||
# different from the paging controls in Super Melee.
|
||||
menu.up.2 = key Keypad-8
|
||||
menu.down.2 = key Keypad-2
|
||||
menu.left.2 = key Keypad-4
|
||||
menu.right.2 = key Keypad-6
|
||||
menu.pageup.2 = key Keypad-9
|
||||
menu.pagedown.2 = key Keypad-3
|
||||
menu.home.2 = key Keypad-7
|
||||
menu.end.2 = key Keypad-1
|
||||
menu.zoomin.2 = key Keypad-+
|
||||
menu.zoomout.2 = key Keypad--
|
||||
menu.select.3 = key Keypad-Enter
|
||||
menu.cancel.3 = key Keypad-0
|
||||
|
||||
# System utility keys.
|
||||
menu.delete.1 = key Delete
|
||||
menu.delete.2 = key Keypad-.
|
||||
menu.backspace.1 = key Backspace
|
||||
menu.editcancel.1 = key Escape
|
||||
menu.search.1 = key /
|
||||
menu.next.1 = key Tab
|
||||
menu.pause.1 = key Pause
|
||||
menu.pause.2 = key F1
|
||||
menu.exit.1 = key F10
|
||||
menu.special.1 = key LeftAlt
|
||||
menu.special.2 = key RightAlt
|
||||
|
||||
# Joystick controls, for both port 1 and 2.
|
||||
|
||||
menu.up.3 = joystick 0 axis 1 negative
|
||||
menu.down.3 = joystick 0 axis 1 positive
|
||||
menu.left.3 = joystick 0 axis 0 negative
|
||||
menu.right.3 = joystick 0 axis 0 positive
|
||||
|
||||
menu.up.4 = joystick 0 hat 0 up
|
||||
menu.down.4 = joystick 0 hat 0 down
|
||||
menu.left.4 = joystick 0 hat 0 left
|
||||
menu.right.4 = joystick 0 hat 0 right
|
||||
|
||||
menu.cancel.4 = joystick 0 button 1
|
||||
menu.select.4 = joystick 0 button 0
|
||||
|
||||
menu.up.5 = joystick 1 axis 1 negative
|
||||
menu.down.5 = joystick 1 axis 1 positive
|
||||
menu.left.5 = joystick 1 axis 0 negative
|
||||
menu.right.5 = joystick 1 axis 0 positive
|
||||
|
||||
menu.up.6 = joystick 1 hat 0 up
|
||||
menu.down.6 = joystick 1 hat 0 down
|
||||
menu.left.6 = joystick 1 hat 0 left
|
||||
menu.right.6 = joystick 1 hat 0 right
|
||||
|
||||
menu.cancel.5 = joystick 1 button 1
|
||||
menu.select.5 = joystick 1 button 0
|
||||
@@ -1,182 +0,0 @@
|
||||
# Default UQM input configuration file.
|
||||
|
||||
# This is a VCONTROL version 4 config file (UQM 0.5.3 or later).
|
||||
version 4
|
||||
|
||||
# Keyboard control definitions follow this point. Most keys can be
|
||||
# described in a straightforward manner; consult the name table in
|
||||
# src/sc2code/libs/input/sdl/keynames.c for the names of unusual keys.
|
||||
# Most keys can be named by just the symbol they produce.
|
||||
|
||||
# Menu controls. Both sets of arrow keys, basically. Paging controls
|
||||
# moving quickly through the file lists in Super Melee. Zooming
|
||||
# controls zoom controls in the starmap. "Cancel" is also used to get
|
||||
# you into menu mode to begin with. There is a "Menu-Special" command
|
||||
# currently unused by the game. It seems to have been originally used
|
||||
# to call up details on starships in the Super Melee selection screen.
|
||||
|
||||
# Arrow key controls...
|
||||
Menu-Up: key Up
|
||||
Menu-Down: key Down
|
||||
Menu-Right: key Right
|
||||
Menu-Left: key Left
|
||||
Menu-Page-Up: key PageUp
|
||||
Menu-Page-Down: key PageDown
|
||||
Menu-Home: key Home
|
||||
Menu-End: key End
|
||||
Menu-Zoom-In: key PageUp
|
||||
Menu-Zoom-Out: key PageDown
|
||||
Menu-Select: key Return
|
||||
Menu-Select: key RightControl
|
||||
Menu-Cancel: key Space
|
||||
Menu-Cancel: key RightShift
|
||||
|
||||
# ... and the number pad. Note that zoom controls on the starmap are
|
||||
# different from the paging controls in Super Melee.
|
||||
Menu-Up: key Keypad-8
|
||||
Menu-Down: key Keypad-2
|
||||
Menu-Left: key Keypad-4
|
||||
Menu-Right: key Keypad-6
|
||||
Menu-Page-Up: key Keypad-9
|
||||
Menu-Page-Down: key Keypad-3
|
||||
Menu-Home: key Keypad-7
|
||||
Menu-End: key Keypad-1
|
||||
Menu-Zoom-In: key Keypad-+
|
||||
Menu-Zoom-Out: key Keypad--
|
||||
Menu-Select: key Keypad-Enter
|
||||
Menu-Cancel: key Keypad-0
|
||||
Menu-Delete: key Keypad-.
|
||||
|
||||
# System utility keys.
|
||||
Menu-Delete: key Delete
|
||||
Menu-Backspace: key Backspace
|
||||
Menu-Edit-Cancel: key Escape
|
||||
Menu-Search: key /
|
||||
Menu-Next: key Tab
|
||||
Pause: key Pause
|
||||
Pause: key F1
|
||||
Exit: key F10
|
||||
|
||||
|
||||
|
||||
# Arrow-key controls. This is the default for the bottom player in
|
||||
# Super Melee and the player in the full game. Again, the player has
|
||||
# the option of using either the number pad or the arrow keys.
|
||||
|
||||
Template-1-Up: key Up
|
||||
Template-1-Down: key Down
|
||||
Template-1-Left: key Left
|
||||
Template-1-Right: key Right
|
||||
Template-1-Weapon: key RightControl
|
||||
Template-1-Special: key RightShift
|
||||
|
||||
Template-1-Up: key Keypad-8
|
||||
Template-1-Down: key Keypad-2
|
||||
Template-1-Left: key Keypad-4
|
||||
Template-1-Right: key Keypad-6
|
||||
Template-1-Weapon: key Keypad-Enter
|
||||
Template-1-Special: key Keypad-0
|
||||
|
||||
Template-1-Escape: key Escape
|
||||
|
||||
# WASD for Player 2's default flight controls. We add the key 'd' to
|
||||
# let him move down in the super-melee ship selection.
|
||||
|
||||
Template-2-Up: key w
|
||||
Template-2-Down: key s
|
||||
Template-2-Left: key a
|
||||
Template-2-Right: key d
|
||||
Template-2-Weapon: key v
|
||||
Template-2-Special: key b
|
||||
Template-2-Escape: key Escape
|
||||
|
||||
# Control Scheme 3: Variant Arrow keys with brackets for firing.
|
||||
|
||||
Template-3-Up: key Keypad-8
|
||||
Template-3-Down: key Keypad-2
|
||||
Template-3-Left: key Keypad-4
|
||||
Template-3-Right: key Keypad-6
|
||||
Template-3-Up: key Up
|
||||
Template-3-Down: key Down
|
||||
Template-3-Left: key Left
|
||||
Template-3-Right: key Right
|
||||
Template-3-Weapon: key ]
|
||||
Template-3-Special: key [
|
||||
Template-3-Escape: key Escape
|
||||
|
||||
# Control Scheme 4: Shifted WASD keys.
|
||||
|
||||
Template-4-Up: key e
|
||||
Template-4-Down: key d
|
||||
Template-4-Left: key s
|
||||
Template-4-Right: key f
|
||||
Template-4-Weapon: key q
|
||||
Template-4-Special: key a
|
||||
Template-4-Escape: key Escape
|
||||
|
||||
# This is a sample joystick configuration. This is intended to work
|
||||
# primarily under WinXP with a USB analog/digital gamepad. The
|
||||
# digital aspect of the gamepad happens to present itself to the
|
||||
# system as a POV hat. This configuration allows either the digital
|
||||
# or analog stick to be used simultaneously. More importantly, it
|
||||
# gives us a chance to give examples for all of the various input types
|
||||
# that UQM can handle.
|
||||
|
||||
joystick 0 threshold 10000 # How far to move before it counts; 0-30000
|
||||
|
||||
Template-5-Up: joystick 0 axis 1 negative
|
||||
Template-5-Down: joystick 0 axis 1 positive
|
||||
Template-5-Left: joystick 0 axis 0 negative
|
||||
Template-5-Right: joystick 0 axis 0 positive
|
||||
|
||||
Template-5-Up: joystick 0 hat 0 up
|
||||
Template-5-Down: joystick 0 hat 0 down
|
||||
Template-5-Left: joystick 0 hat 0 left
|
||||
Template-5-Right: joystick 0 hat 0 right
|
||||
|
||||
Template-5-Weapon: joystick 0 button 0
|
||||
Template-5-Special: joystick 0 button 1
|
||||
Template-5-Escape: key Escape
|
||||
|
||||
Menu-Up: joystick 0 axis 1 negative
|
||||
Menu-Down: joystick 0 axis 1 positive
|
||||
Menu-Left: joystick 0 axis 0 negative
|
||||
Menu-Right: joystick 0 axis 0 positive
|
||||
|
||||
Menu-Up: joystick 0 hat 0 up
|
||||
Menu-Down: joystick 0 hat 0 down
|
||||
Menu-Left: joystick 0 hat 0 left
|
||||
Menu-Right: joystick 0 hat 0 right
|
||||
|
||||
Menu-Cancel: joystick 0 button 1
|
||||
Menu-Select: joystick 0 button 0
|
||||
|
||||
joystick 1 threshold 10000 # How far to move before it counts; 0-30000
|
||||
|
||||
Template-6-Up: joystick 1 axis 1 negative
|
||||
Template-6-Down: joystick 1 axis 1 positive
|
||||
Template-6-Left: joystick 1 axis 0 negative
|
||||
Template-6-Right: joystick 1 axis 0 positive
|
||||
|
||||
Template-6-Up: joystick 1 hat 0 up
|
||||
Template-6-Down: joystick 1 hat 0 down
|
||||
Template-6-Left: joystick 1 hat 0 left
|
||||
Template-6-Right: joystick 1 hat 0 right
|
||||
|
||||
Template-6-Weapon: joystick 1 button 0
|
||||
Template-6-Special: joystick 1 button 1
|
||||
|
||||
Template-6-Escape: key Escape
|
||||
|
||||
Menu-Up: joystick 1 axis 1 negative
|
||||
Menu-Down: joystick 1 axis 1 positive
|
||||
Menu-Left: joystick 1 axis 0 negative
|
||||
Menu-Right: joystick 1 axis 0 positive
|
||||
|
||||
Menu-Up: joystick 1 hat 0 up
|
||||
Menu-Down: joystick 1 hat 0 down
|
||||
Menu-Left: joystick 1 hat 0 left
|
||||
Menu-Right: joystick 1 hat 0 right
|
||||
|
||||
Menu-Cancel: joystick 1 button 1
|
||||
Menu-Select: joystick 1 button 0
|
||||
@@ -0,0 +1,71 @@
|
||||
keys.1.name = Arrows
|
||||
keys.1.up.1 = key Up
|
||||
keys.1.down.1 = key Down
|
||||
keys.1.left.1 = key Left
|
||||
keys.1.right.1 = key Right
|
||||
keys.1.weapon.1 = key RightControl
|
||||
keys.1.special.1 = key RightShift
|
||||
keys.1.up.2 = key Keypad-8
|
||||
keys.1.down.2 = key Keypad-2
|
||||
keys.1.left.2 = key Keypad-4
|
||||
keys.1.right.2 = key Keypad-6
|
||||
keys.1.weapon.2 = key Keypad-Enter
|
||||
keys.1.special.2 = key Keypad-0
|
||||
keys.1.escape.1 = key Escape
|
||||
|
||||
keys.2.name = WASD
|
||||
keys.2.up.1 = key w
|
||||
keys.2.down.1 = key s
|
||||
keys.2.left.1 = key a
|
||||
keys.2.right.1 = key d
|
||||
keys.2.weapon.1 = key v
|
||||
keys.2.special.1 = key b
|
||||
keys.2.escape.1 = key Escape
|
||||
|
||||
keys.3.name = Arrows (2)
|
||||
keys.3.up.1 = key Up
|
||||
keys.3.down.1 = key Down
|
||||
keys.3.left.1 = key Left
|
||||
keys.3.right.1 = key Right
|
||||
keys.3.up.2 = key Keypad-8
|
||||
keys.3.down.2 = key Keypad-2
|
||||
keys.3.left.2 = key Keypad-4
|
||||
keys.3.right.2 = key Keypad-6
|
||||
keys.3.weapon.1 = key ]
|
||||
keys.3.special.1 = key [
|
||||
keys.3.escape.1 = key Escape
|
||||
|
||||
keys.4.name = ESDF
|
||||
keys.4.up.1 = key e
|
||||
keys.4.down.1 = key d
|
||||
keys.4.left.1 = key s
|
||||
keys.4.right.1 = key f
|
||||
keys.4.weapon.1 = key q
|
||||
keys.4.special.1 = key a
|
||||
keys.4.escape.1 = key Escape
|
||||
|
||||
keys.5.name = Joystick 1
|
||||
keys.5.up.1 = joystick 0 axis 1 negative
|
||||
keys.5.down.1 = joystick 0 axis 1 positive
|
||||
keys.5.left.1 = joystick 0 axis 0 negative
|
||||
keys.5.right.1 = joystick 0 axis 0 positive
|
||||
keys.5.up.2 = joystick 0 hat 0 up
|
||||
keys.5.down.2 = joystick 0 hat 0 down
|
||||
keys.5.left.2 = joystick 0 hat 0 left
|
||||
keys.5.right.2 = joystick 0 hat 0 right
|
||||
keys.5.weapon.1 = joystick 0 button 0
|
||||
keys.5.special.1 = joystick 0 button 1
|
||||
keys.5.escape.1 = key Escape
|
||||
|
||||
keys.6.name = Joystick 2
|
||||
keys.6.up.1 = joystick 1 axis 1 negative
|
||||
keys.6.down.1 = joystick 1 axis 1 positive
|
||||
keys.6.left.1 = joystick 1 axis 0 negative
|
||||
keys.6.right.1 = joystick 1 axis 0 positive
|
||||
keys.6.up.2 = joystick 1 hat 0 up
|
||||
keys.6.down.2 = joystick 1 hat 0 down
|
||||
keys.6.left.2 = joystick 1 hat 0 left
|
||||
keys.6.right.2 = joystick 1 hat 0 right
|
||||
keys.6.weapon.1 = joystick 1 button 0
|
||||
keys.6.special.1 = joystick 1 button 1
|
||||
keys.6.escape.1 = key Escape
|
||||
@@ -44,88 +44,124 @@ static BOOLEAN InputInitialized = FALSE;
|
||||
|
||||
static BOOLEAN _in_character_mode = FALSE;
|
||||
|
||||
#define VCONTROL_VERSION 4
|
||||
static const char *menu_res_names[] = {
|
||||
"pause",
|
||||
"exit",
|
||||
"abort",
|
||||
"debug",
|
||||
"up",
|
||||
"down",
|
||||
"left",
|
||||
"right",
|
||||
"select",
|
||||
"cancel",
|
||||
"special",
|
||||
"pageup",
|
||||
"pagedown",
|
||||
"home",
|
||||
"end",
|
||||
"zoomin",
|
||||
"zoomout",
|
||||
"delete",
|
||||
"backspace",
|
||||
"editcancel",
|
||||
"search",
|
||||
"next",
|
||||
NULL
|
||||
};
|
||||
|
||||
static VControl_NameBinding control_names[] = {
|
||||
{ "Menu-Up", (int *)&ImmediateInputState.menu[KEY_MENU_UP] },
|
||||
{ "Menu-Down", (int *)&ImmediateInputState.menu[KEY_MENU_DOWN] },
|
||||
{ "Menu-Left", (int *)&ImmediateInputState.menu[KEY_MENU_LEFT] },
|
||||
{ "Menu-Right", (int *)&ImmediateInputState.menu[KEY_MENU_RIGHT] },
|
||||
{ "Menu-Select", (int *)&ImmediateInputState.menu[KEY_MENU_SELECT] },
|
||||
{ "Menu-Cancel", (int *)&ImmediateInputState.menu[KEY_MENU_CANCEL] },
|
||||
{ "Menu-Special", (int *)&ImmediateInputState.menu[KEY_MENU_SPECIAL] },
|
||||
{ "Menu-Page-Up", (int *)&ImmediateInputState.menu[KEY_MENU_PAGE_UP] },
|
||||
{ "Menu-Page-Down", (int *)&ImmediateInputState.menu[KEY_MENU_PAGE_DOWN] },
|
||||
{ "Menu-Home", (int *)&ImmediateInputState.menu[KEY_MENU_HOME] },
|
||||
{ "Menu-End", (int *)&ImmediateInputState.menu[KEY_MENU_END] },
|
||||
{ "Menu-Zoom-In", (int *)&ImmediateInputState.menu[KEY_MENU_ZOOM_IN] },
|
||||
{ "Menu-Zoom-Out", (int *)&ImmediateInputState.menu[KEY_MENU_ZOOM_OUT] },
|
||||
{ "Menu-Delete", (int *)&ImmediateInputState.menu[KEY_MENU_DELETE] },
|
||||
{ "Menu-Backspace", (int *)&ImmediateInputState.menu[KEY_MENU_BACKSPACE] },
|
||||
{ "Menu-Edit-Cancel", (int *)&ImmediateInputState.menu[KEY_MENU_EDIT_CANCEL] },
|
||||
{ "Menu-Search", (int *)&ImmediateInputState.menu[KEY_MENU_SEARCH] },
|
||||
{ "Menu-Next", (int *)&ImmediateInputState.menu[KEY_MENU_NEXT] },
|
||||
{ "Template-1-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_UP] },
|
||||
{ "Template-1-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_DOWN] },
|
||||
{ "Template-1-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_LEFT] },
|
||||
{ "Template-1-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_RIGHT] },
|
||||
{ "Template-1-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_WEAPON] },
|
||||
{ "Template-1-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_SPECIAL] },
|
||||
{ "Template-1-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_ESCAPE] },
|
||||
{ "Template-2-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_UP] },
|
||||
{ "Template-2-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_DOWN] },
|
||||
{ "Template-2-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_LEFT] },
|
||||
{ "Template-2-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_RIGHT] },
|
||||
{ "Template-2-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_WEAPON] },
|
||||
{ "Template-2-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_SPECIAL] },
|
||||
{ "Template-2-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_ESCAPE] },
|
||||
{ "Template-3-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_UP] },
|
||||
{ "Template-3-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_DOWN] },
|
||||
{ "Template-3-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_LEFT] },
|
||||
{ "Template-3-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_RIGHT] },
|
||||
{ "Template-3-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_WEAPON] },
|
||||
{ "Template-3-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_SPECIAL] },
|
||||
{ "Template-3-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_ESCAPE] },
|
||||
{ "Template-4-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_UP] },
|
||||
{ "Template-4-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_DOWN] },
|
||||
{ "Template-4-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_LEFT] },
|
||||
{ "Template-4-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_RIGHT] },
|
||||
{ "Template-4-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_WEAPON] },
|
||||
{ "Template-4-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_SPECIAL] },
|
||||
{ "Template-4-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_ESCAPE] },
|
||||
{ "Template-5-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_UP] },
|
||||
{ "Template-5-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_DOWN] },
|
||||
{ "Template-5-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_LEFT] },
|
||||
{ "Template-5-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_RIGHT] },
|
||||
{ "Template-5-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_WEAPON] },
|
||||
{ "Template-5-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_SPECIAL] },
|
||||
{ "Template-5-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_ESCAPE] },
|
||||
{ "Template-6-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_UP] },
|
||||
{ "Template-6-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_DOWN] },
|
||||
{ "Template-6-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_LEFT] },
|
||||
{ "Template-6-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_RIGHT] },
|
||||
{ "Template-6-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_WEAPON] },
|
||||
{ "Template-6-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_SPECIAL] },
|
||||
{ "Template-6-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_ESCAPE] },
|
||||
{ "Pause", (int *)&ImmediateInputState.menu[KEY_PAUSE] },
|
||||
{ "Exit", (int *)&ImmediateInputState.menu[KEY_EXIT] },
|
||||
{ "Abort", (int *)&ImmediateInputState.menu[KEY_ABORT] },
|
||||
{ "Debug", (int *)&ImmediateInputState.menu[KEY_DEBUG] },
|
||||
{ "Illegal", NULL}};
|
||||
static const char *flight_res_names[] = {
|
||||
"up",
|
||||
"down",
|
||||
"left",
|
||||
"right",
|
||||
"weapon",
|
||||
"special",
|
||||
"escape",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
register_menu_controls (int index)
|
||||
{
|
||||
int i;
|
||||
char buf[40];
|
||||
buf[39] = '\0';
|
||||
|
||||
i = 1;
|
||||
while (TRUE)
|
||||
{
|
||||
VCONTROL_GESTURE g;
|
||||
snprintf (buf, 39, "menu.%s.%d", menu_res_names[index], i);
|
||||
if (!res_HasKey (buf))
|
||||
break;
|
||||
VControl_ParseGesture (&g, res_GetString (buf));
|
||||
VControl_AddGestureBinding (&g, (int *)&ImmediateInputState.menu[index]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static VCONTROL_GESTURE controls[NUM_TEMPLATES][NUM_KEYS][2];
|
||||
|
||||
static void
|
||||
register_flight_controls (void)
|
||||
{
|
||||
int i, j, k;
|
||||
char buf[40];
|
||||
|
||||
buf[39] = '\0';
|
||||
|
||||
for (i = 0; i < NUM_TEMPLATES; i++)
|
||||
{
|
||||
/* Copy in name */
|
||||
snprintf (buf, 39, "keys.%d.name", i+1);
|
||||
if (res_HasKey (buf))
|
||||
{
|
||||
strncpy (input_templates[i].name, res_GetString (buf), 29);
|
||||
input_templates[i].name[29] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
input_templates[i].name[0] = '\0';
|
||||
}
|
||||
for (j = 0; j < NUM_KEYS; j++)
|
||||
{
|
||||
for (k = 0; k < 2; k++)
|
||||
{
|
||||
VCONTROL_GESTURE *g = &controls[i][j][k];
|
||||
snprintf (buf, 39, "keys.%d.%s.%d", i+1, flight_res_names[j], k+1);
|
||||
if (!res_HasKey (buf))
|
||||
{
|
||||
g->type = VCONTROL_NONE;
|
||||
continue;
|
||||
}
|
||||
VControl_ParseGesture (g, res_GetString (buf));
|
||||
VControl_AddGestureBinding (g, (int *)&ImmediateInputState.key[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
initKeyConfig (void)
|
||||
{
|
||||
uio_Stream *fp;
|
||||
int i, errors;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; ++i)
|
||||
/* First, load in the menu keys */
|
||||
res_LoadFilename (contentDir, "menu.key");
|
||||
for (i = 0; i < NUM_MENU_KEYS; i++)
|
||||
{
|
||||
if ((fp = res_OpenResFile (configDir, "keys.cfg", "rt")) == NULL)
|
||||
if (!menu_res_names[i])
|
||||
break;
|
||||
register_menu_controls (i);
|
||||
}
|
||||
|
||||
fp = res_OpenResFile (configDir, "flight.cfg", "rt");
|
||||
if (!fp)
|
||||
{
|
||||
if (copyFile (contentDir, "starcon.key",
|
||||
configDir, "keys.cfg") == -1)
|
||||
if (copyFile (contentDir, "uqm.key",
|
||||
configDir, "flight.cfg") == -1)
|
||||
{
|
||||
log_add (log_Fatal, "Error: Could not copy default key config "
|
||||
"to user config dir: %s.", strerror (errno));
|
||||
@@ -134,60 +170,19 @@ initKeyConfig (void)
|
||||
log_add (log_Info, "Copying default key config file to user "
|
||||
"config dir.");
|
||||
|
||||
if ((fp = res_OpenResFile (configDir, "keys.cfg", "rt")) == NULL)
|
||||
if ((fp = res_OpenResFile (configDir, "flight.cfg", "rt")) == NULL)
|
||||
{
|
||||
log_add (log_Fatal, "Error: Could not open keys.cfg");
|
||||
log_add (log_Fatal, "Error: Could not open flight.cfg");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
errors = VControl_ReadConfiguration (fp);
|
||||
res_LoadFile (fp);
|
||||
res_CloseResFile (fp);
|
||||
|
||||
if (errors || (VControl_GetConfigFileVersion () != VCONTROL_VERSION))
|
||||
{
|
||||
bool do_rename = false;
|
||||
if (errors)
|
||||
log_add (log_Warning, "%d errors encountered in key configuration file.", errors);
|
||||
|
||||
if (VControl_GetValidCount () == 0)
|
||||
{
|
||||
log_add (log_Error, "\nI didn't understand a single line in your configuration file.");
|
||||
log_add (log_Error, "This is likely because you're still using a 0.2 era or earlier keys.cfg.");
|
||||
do_rename = true;
|
||||
}
|
||||
if (VControl_GetConfigFileVersion () != VCONTROL_VERSION)
|
||||
{
|
||||
log_add (log_Error, "\nThe control scheme for UQM has changed since you last updated keys.cfg.");
|
||||
log_add (log_Error, "(I'm using control scheme version %d, while your config file appears to be\nfor version %d.)", VCONTROL_VERSION, VControl_GetConfigFileVersion ());
|
||||
do_rename = true;
|
||||
}
|
||||
|
||||
if (do_rename)
|
||||
{
|
||||
log_add (log_Error, "\nRenaming keys.cfg to keys.old and retrying.");
|
||||
|
||||
if (fileExists2 (configDir, "keys.old"))
|
||||
uio_unlink (configDir, "keys.old");
|
||||
if ((uio_rename (configDir, "keys.cfg", configDir, "keys.old")) == -1)
|
||||
{
|
||||
log_add (log_Fatal, "Error: Renaming failed!");
|
||||
log_add (log_Fatal, "You must delete keys.cfg manually before you can run the game.");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
log_add (log_Fatal, "\nRepair your keys.cfg file to continue.");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
register_flight_controls ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
log_add (log_Fatal, "Error: Something went wrong and we were looping again and again so aborting.");
|
||||
log_add (log_Fatal, "Possible cause is your content dir not being up-to-date.");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -239,7 +234,6 @@ TFB_InitInput (int driver, int flags)
|
||||
|
||||
/* Prepare the Virtual Controller system. */
|
||||
VControl_Init ();
|
||||
VControl_RegisterNameTable (control_names);
|
||||
|
||||
initKeyConfig ();
|
||||
|
||||
@@ -387,32 +381,23 @@ FlushInput (void)
|
||||
void
|
||||
InterrogateInputState (int template, int control, int index, char *buffer, int maxlen)
|
||||
{
|
||||
int i;
|
||||
VCONTROL_GESTURE g;
|
||||
VCONTROL_GESTURE *g = &controls[template][control][index];
|
||||
|
||||
VControl_StartIter (&ImmediateInputState.key[template][control]);
|
||||
i = 0;
|
||||
while (VControl_NextBinding (&g))
|
||||
{
|
||||
if (i++ < index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (g.type)
|
||||
switch (g->type)
|
||||
{
|
||||
case VCONTROL_KEY:
|
||||
snprintf (buffer, maxlen, "%s", VControl_code2name (g.gesture.key));
|
||||
snprintf (buffer, maxlen, "%s", VControl_code2name (g->gesture.key));
|
||||
buffer[maxlen-1] = 0;
|
||||
break;
|
||||
case VCONTROL_JOYBUTTON:
|
||||
snprintf (buffer, maxlen, "[J%d B%d]", g.gesture.button.port, g.gesture.button.index + 1);
|
||||
snprintf (buffer, maxlen, "[J%d B%d]", g->gesture.button.port, g->gesture.button.index + 1);
|
||||
buffer[maxlen-1] = 0;
|
||||
break;
|
||||
case VCONTROL_JOYAXIS:
|
||||
snprintf (buffer, maxlen, "[J%d A%d %c]", g.gesture.axis.port, g.gesture.axis.index, g.gesture.axis.polarity > 0 ? '+' : '-');
|
||||
snprintf (buffer, maxlen, "[J%d A%d %c]", g->gesture.axis.port, g->gesture.axis.index, g->gesture.axis.polarity > 0 ? '+' : '-');
|
||||
break;
|
||||
case VCONTROL_JOYHAT:
|
||||
snprintf (buffer, maxlen, "[J%d H%d %d]", g.gesture.hat.port, g.gesture.hat.index, g.gesture.hat.dir);
|
||||
snprintf (buffer, maxlen, "[J%d H%d %d]", g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir);
|
||||
break;
|
||||
default:
|
||||
/* Something we don't handle yet */
|
||||
@@ -420,29 +405,21 @@ InterrogateInputState (int template, int control, int index, char *buffer, int m
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* There aren't that many bindings, so return blank string */
|
||||
buffer[0] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
RemoveInputState (int template, int control, int index)
|
||||
{
|
||||
int i;
|
||||
VCONTROL_GESTURE g;
|
||||
VCONTROL_GESTURE *g = &controls[template][control][index];
|
||||
char keybuf[40];
|
||||
keybuf[39] = '\0';
|
||||
|
||||
VControl_RemoveGestureBinding (g, (int *)&ImmediateInputState.key[template][control]);
|
||||
g->type = VCONTROL_NONE;
|
||||
|
||||
snprintf (keybuf, 39, "keys.%d.%s.%d", template+1, flight_res_names[control], index+1);
|
||||
res_Remove (keybuf);
|
||||
|
||||
VControl_StartIter (&ImmediateInputState.key[template][control]);
|
||||
i = 0;
|
||||
while (VControl_NextBinding (&g))
|
||||
{
|
||||
if (i++ < index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
VControl_RemoveGestureBinding (&g, &ImmediateInputState.key[template][control]);
|
||||
return;
|
||||
}
|
||||
/* No such gesture! */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -450,6 +427,8 @@ void
|
||||
RebindInputState (int template, int control, int index)
|
||||
{
|
||||
VCONTROL_GESTURE g;
|
||||
char keybuf[40], valbuf[40];
|
||||
keybuf[39] = valbuf[39] = '\0';
|
||||
|
||||
/* Remove the old binding on this spot */
|
||||
RemoveInputState (template, control, index);
|
||||
@@ -462,7 +441,11 @@ RebindInputState (int template, int control, int index)
|
||||
}
|
||||
|
||||
/* And now, add the new binding. */
|
||||
VControl_AddGestureBinding (&g, &ImmediateInputState.key[template][control]);
|
||||
VControl_AddGestureBinding (&g, (int *)&ImmediateInputState.key[template][control]);
|
||||
controls[template][control][index] = g;
|
||||
snprintf (keybuf, 39, "keys.%d.%s.%d", template+1, flight_res_names[control], index+1);
|
||||
VControl_DumpGesture (valbuf, 39, &g);
|
||||
res_PutString (keybuf, valbuf);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -473,7 +456,7 @@ SaveKeyConfiguration (uio_DirHandle *path, const char *fname)
|
||||
f = res_OpenResFile (path, fname, "wb");
|
||||
if (f)
|
||||
{
|
||||
VControl_Dump (f);
|
||||
res_SaveFile (f, "keys.");
|
||||
res_CloseResFile (f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,16 +71,6 @@ static int num_sdl_keys = 0;
|
||||
static keybinding **bindings = NULL;
|
||||
|
||||
static keypool *pool;
|
||||
static VControl_NameBinding *nametable;
|
||||
|
||||
/* Statistics variables - set by VControl_ReadConfiguration */
|
||||
|
||||
static int version, errors, validlines;
|
||||
|
||||
/* Iterator temp variables */
|
||||
|
||||
static int *iter_target;
|
||||
static int iter_device, iter_index;
|
||||
|
||||
/* Last interesting event */
|
||||
static int event_ready;
|
||||
@@ -243,30 +233,16 @@ key_uninit (void)
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
}
|
||||
|
||||
static void
|
||||
name_init (void)
|
||||
{
|
||||
nametable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
name_uninit (void)
|
||||
{
|
||||
nametable = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
VControl_Init (void)
|
||||
{
|
||||
key_init ();
|
||||
name_init ();
|
||||
}
|
||||
|
||||
void
|
||||
VControl_Uninit (void)
|
||||
{
|
||||
key_uninit ();
|
||||
name_uninit ();
|
||||
}
|
||||
|
||||
int
|
||||
@@ -413,8 +389,6 @@ event2gesture (SDL_Event *e, VCONTROL_GESTURE *g)
|
||||
g->type = VCONTROL_KEY;
|
||||
g->gesture.key = e->key.keysym.sym;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_JOYSTICK
|
||||
case SDL_JOYAXISMOTION:
|
||||
g->type = VCONTROL_JOYAXIS;
|
||||
g->gesture.axis.port = e->jaxis.which;
|
||||
@@ -432,7 +406,6 @@ event2gesture (SDL_Event *e, VCONTROL_GESTURE *g)
|
||||
g->gesture.button.port = e->jbutton.which;
|
||||
g->gesture.button.index = e->jbutton.button;
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
|
||||
default:
|
||||
g->type = VCONTROL_NONE;
|
||||
@@ -450,17 +423,24 @@ VControl_AddGestureBinding (VCONTROL_GESTURE *g, int *target)
|
||||
result = VControl_AddKeyBinding (g->gesture.key, target);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_JOYSTICK
|
||||
case VCONTROL_JOYAXIS:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
result = VControl_AddJoyAxisBinding (g->gesture.axis.port, g->gesture.axis.index, (g->gesture.axis.polarity < 0) ? -1 : 1, target);
|
||||
break;
|
||||
#endif
|
||||
case VCONTROL_JOYHAT:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
result = VControl_AddJoyHatBinding (g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir, target);
|
||||
break;
|
||||
#endif
|
||||
case VCONTROL_JOYBUTTON:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
result = VControl_AddJoyButtonBinding (g->gesture.button.port, g->gesture.button.index, target);
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
case VCONTROL_NONE:
|
||||
/* Do nothing */
|
||||
break;
|
||||
|
||||
default:
|
||||
log_add (log_Warning, "VControl_AddGestureBinding didn't understand argument gesture");
|
||||
@@ -479,18 +459,23 @@ VControl_RemoveGestureBinding (VCONTROL_GESTURE *g, int *target)
|
||||
VControl_RemoveKeyBinding (g->gesture.key, target);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_JOYSTICK
|
||||
case VCONTROL_JOYAXIS:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
VControl_RemoveJoyAxisBinding (g->gesture.axis.port, g->gesture.axis.index, (g->gesture.axis.polarity < 0) ? -1 : 1, target);
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
case VCONTROL_JOYHAT:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
VControl_RemoveJoyHatBinding (g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir, target);
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
case VCONTROL_JOYBUTTON:
|
||||
#ifdef HAVE_JOYSTICK
|
||||
VControl_RemoveJoyButtonBinding (g->gesture.button.port, g->gesture.button.index, target);
|
||||
break;
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
|
||||
case VCONTROL_NONE:
|
||||
break;
|
||||
default:
|
||||
log_add (log_Warning, "VControl_RemoveGestureBinding didn't understand argument gesture");
|
||||
break;
|
||||
@@ -948,299 +933,6 @@ VControl_HandleEvent (const SDL_Event *e)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VControl_RegisterNameTable (VControl_NameBinding *table)
|
||||
{
|
||||
nametable = table;
|
||||
}
|
||||
|
||||
static char *
|
||||
target2name (int *target)
|
||||
{
|
||||
VControl_NameBinding *b = nametable;
|
||||
while (b->target)
|
||||
{
|
||||
if (target == b->target)
|
||||
{
|
||||
return b->name;
|
||||
}
|
||||
++b;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int *
|
||||
name2target (char *name)
|
||||
{
|
||||
VControl_NameBinding *b = nametable;
|
||||
while (b->target)
|
||||
{
|
||||
if (!stricmp (name, b->name))
|
||||
{
|
||||
return b->target;
|
||||
}
|
||||
++b;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_keybindings (uio_Stream *out, keybinding *kb, char *name)
|
||||
{
|
||||
while (kb != NULL)
|
||||
{
|
||||
char *targetname = target2name (kb->target);
|
||||
WriteResFile (targetname, 1, strlen (targetname), out);
|
||||
PutResFileChar (':', out);
|
||||
PutResFileChar (' ', out);
|
||||
WriteResFile (name, 1, strlen (name), out);
|
||||
PutResFileNewline (out);
|
||||
|
||||
kb = kb->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VControl_Dump (uio_Stream *out)
|
||||
{
|
||||
int i;
|
||||
char namebuffer[64];
|
||||
|
||||
sprintf (namebuffer, "version %d", version);
|
||||
WriteResFile (namebuffer, 1, strlen (namebuffer), out);
|
||||
PutResFileNewline (out);
|
||||
|
||||
/* Print out keyboard bindings */
|
||||
for (i = 0; i < num_sdl_keys; i++)
|
||||
{
|
||||
keybinding *kb = bindings[i];
|
||||
if (kb != NULL)
|
||||
{
|
||||
sprintf (namebuffer, "key %s", VControl_code2name (i));
|
||||
dump_keybindings (out, kb, namebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_JOYSTICK
|
||||
/* Print out joystick bindings */
|
||||
for (i = 0; i < joycount; i++)
|
||||
{
|
||||
if (joysticks[i].stick)
|
||||
{
|
||||
int j;
|
||||
|
||||
sprintf (namebuffer, "joystick %d threshold %d", i, joysticks[i].threshold);
|
||||
WriteResFile (namebuffer, 1, strlen (namebuffer), out);
|
||||
PutResFileNewline (out);
|
||||
|
||||
for (j = 0; j < joysticks[i].numaxes; j++)
|
||||
{
|
||||
sprintf (namebuffer, "joystick %d axis %d negative", i, j);
|
||||
dump_keybindings (out, joysticks[i].axes[j].neg, namebuffer);
|
||||
sprintf (namebuffer, "joystick %d axis %d positive", i, j);
|
||||
dump_keybindings (out, joysticks[i].axes[j].pos, namebuffer);
|
||||
}
|
||||
for (j = 0; j < joysticks[i].numbuttons; j++)
|
||||
{
|
||||
keybinding *kb = joysticks[i].buttons[j];
|
||||
if (kb != NULL)
|
||||
{
|
||||
sprintf (namebuffer, "joystick %d button %d", i, j);
|
||||
dump_keybindings (out, kb, namebuffer);
|
||||
}
|
||||
}
|
||||
for (j = 0; j < joysticks[i].numhats; j++)
|
||||
{
|
||||
sprintf (namebuffer, "joystick %d hat %d left", i, j);
|
||||
dump_keybindings (out, joysticks[i].hats[j].left, namebuffer);
|
||||
sprintf (namebuffer, "joystick %d hat %d right", i, j);
|
||||
dump_keybindings (out, joysticks[i].hats[j].right, namebuffer);
|
||||
sprintf (namebuffer, "joystick %d hat %d up", i, j);
|
||||
dump_keybindings (out, joysticks[i].hats[j].up, namebuffer);
|
||||
sprintf (namebuffer, "joystick %d hat %d down", i, j);
|
||||
dump_keybindings (out, joysticks[i].hats[j].down, namebuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
|
||||
#ifdef VCONTROL_DEBUG
|
||||
/* Print out allocation data */
|
||||
{
|
||||
keypool bp = pool;
|
||||
i = 0;
|
||||
while (bp != NULL)
|
||||
{
|
||||
fprintf (out, "# Internal Debug: Chunk #%i: %d slots remaining.\n", i, bp->remaining);
|
||||
i++;
|
||||
bp = bp->next;
|
||||
}
|
||||
fprintf (out, "# Internal Debug: %d chunks allocated.\n", i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Iterator routines. iter_target holds the target keybinding.
|
||||
iter_device is -1 for the keyboard, otherwise it is joystick
|
||||
#(iter_device/3). (iter_device%3) gives whether we're checking the
|
||||
joystick's axes (0), buttons (1), or hats (2). */
|
||||
|
||||
static int *iter_target;
|
||||
static int iter_device, iter_index;
|
||||
|
||||
void
|
||||
VControl_StartIter (int *target)
|
||||
{
|
||||
iter_target = target;
|
||||
iter_device = -1;
|
||||
iter_index = 0;
|
||||
}
|
||||
|
||||
void
|
||||
VControl_StartIterByName (char *targetname)
|
||||
{
|
||||
VControl_StartIter (name2target (targetname));
|
||||
}
|
||||
|
||||
int
|
||||
VControl_NextBinding (VCONTROL_GESTURE *gesture)
|
||||
{
|
||||
if ((gesture == NULL) || (iter_target == NULL)
|
||||
|| iter_device >= (joycount * 3))
|
||||
return 0;
|
||||
while (iter_device < (joycount * 3))
|
||||
{
|
||||
if (iter_device == -1) /* keyboard */
|
||||
{
|
||||
keybinding *kb = bindings[iter_index];
|
||||
int done = 0;
|
||||
while (kb != NULL)
|
||||
{
|
||||
if (kb->target == iter_target)
|
||||
{
|
||||
gesture->type = VCONTROL_KEY;
|
||||
gesture->gesture.key = iter_index;
|
||||
done = 1;
|
||||
}
|
||||
kb = kb->next;
|
||||
}
|
||||
if (++iter_index == num_sdl_keys)
|
||||
{
|
||||
iter_device = 0;
|
||||
iter_index = 0;
|
||||
}
|
||||
if (done) return 1;
|
||||
}
|
||||
#ifdef HAVE_JOYSTICK
|
||||
else
|
||||
{
|
||||
int i = iter_device / 3;
|
||||
int t = iter_device % 3;
|
||||
if (!joysticks[i].stick) /* Joystick wasn't opened; this binding is dead */
|
||||
{
|
||||
iter_device++;
|
||||
iter_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int done = 0;
|
||||
switch (t)
|
||||
{
|
||||
case 0: { /* Axes */
|
||||
int axis = iter_index / 2;
|
||||
int dir = iter_index % 2;
|
||||
if (axis >= joysticks[i].numaxes)
|
||||
{
|
||||
iter_device++;
|
||||
iter_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
keybinding *kb = (dir) ? joysticks[i].axes[axis].pos : joysticks[i].axes[axis].neg;
|
||||
while (kb != NULL)
|
||||
{
|
||||
if (kb->target == iter_target)
|
||||
{
|
||||
done = 1;
|
||||
gesture->type = VCONTROL_JOYAXIS;
|
||||
gesture->gesture.axis.port = i;
|
||||
gesture->gesture.axis.index = axis;
|
||||
gesture->gesture.axis.polarity = (dir) ? 1 : -1;
|
||||
}
|
||||
kb = kb->next;
|
||||
}
|
||||
iter_index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: { /* Buttons */
|
||||
keybinding *kb = joysticks[i].buttons[iter_index];
|
||||
if (iter_index >= joysticks[i].numbuttons)
|
||||
{
|
||||
iter_device++;
|
||||
iter_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (kb != NULL)
|
||||
{
|
||||
if (kb->target == iter_target)
|
||||
{
|
||||
gesture->type = VCONTROL_JOYBUTTON;
|
||||
gesture->gesture.button.port = i;
|
||||
gesture->gesture.button.index = iter_index;
|
||||
done = 1;
|
||||
}
|
||||
kb = kb->next;
|
||||
}
|
||||
iter_index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: { /* Hats */
|
||||
int hat = iter_index / 4;
|
||||
int hatd = iter_index % 4;
|
||||
if (hat >= joysticks[i].numhats)
|
||||
{
|
||||
iter_device++;
|
||||
iter_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
keybinding *kb;
|
||||
Uint8 targetdir;
|
||||
switch (hatd)
|
||||
{
|
||||
case 0: kb = joysticks[i].hats[hat].left; targetdir = SDL_HAT_LEFT; break;
|
||||
case 1: kb = joysticks[i].hats[hat].right; targetdir = SDL_HAT_RIGHT; break;
|
||||
case 2: kb = joysticks[i].hats[hat].up; targetdir = SDL_HAT_UP; break;
|
||||
default: kb = joysticks[i].hats[hat].down; targetdir = SDL_HAT_DOWN; break;
|
||||
}
|
||||
while (kb != NULL)
|
||||
{
|
||||
if (kb->target == iter_target)
|
||||
{
|
||||
done = 1;
|
||||
gesture->type = VCONTROL_JOYHAT;
|
||||
gesture->gesture.hat.port = i;
|
||||
gesture->gesture.hat.index = hat;
|
||||
gesture->gesture.hat.dir = targetdir;
|
||||
}
|
||||
kb = kb->next;
|
||||
}
|
||||
iter_index++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (done) return 1;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tracking the last interesting event */
|
||||
|
||||
void
|
||||
@@ -1337,43 +1029,6 @@ next_token (parse_state *state)
|
||||
state->index = base+index;
|
||||
}
|
||||
|
||||
static void
|
||||
next_line (parse_state *state, uio_Stream *in)
|
||||
{
|
||||
int i, ch = 0;
|
||||
state->linenum++;
|
||||
for (i = 0; i < LINE_SIZE-1; i++)
|
||||
{
|
||||
if (uio_feof (in))
|
||||
{
|
||||
break;
|
||||
}
|
||||
ch = uio_fgetc (in);
|
||||
if (ch == '#' || ch == '\n' || ch == EOF)
|
||||
{
|
||||
/* If this line is blank or all commented, include some
|
||||
* whitespace. This lets us detect EOF as a completely
|
||||
* blank line. */
|
||||
if (i==0)
|
||||
{
|
||||
state->line[i] = '\n';
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
state->line[i] = ch;
|
||||
}
|
||||
state->line[i] = '\0';
|
||||
/* Skip to end of line */
|
||||
while (ch != '\n' && !uio_feof (in))
|
||||
{
|
||||
ch = uio_fgetc (in);
|
||||
}
|
||||
state->token[0] = 0;
|
||||
state->index = 0;
|
||||
state->error = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
expected_error (parse_state *state, char *expected)
|
||||
{
|
||||
@@ -1406,45 +1061,6 @@ consume_keyname (parse_state *state)
|
||||
return keysym;
|
||||
}
|
||||
|
||||
static int *
|
||||
consume_idname (parse_state *state)
|
||||
{
|
||||
int *result = NULL;
|
||||
int index = 0;
|
||||
while (state->token[index])
|
||||
{
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
log_add (log_Debug, "VControl: Can't happen: blank token to consume_idname (line %d)",
|
||||
state->linenum);
|
||||
state->error = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index--;
|
||||
if (state->token[index] != ':')
|
||||
{
|
||||
expected_error (state, ":");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->token[index] = 0; /* remove trailing colon */
|
||||
|
||||
result = name2target (state->token);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
log_add (log_Warning, "VControl: Illegal command type '%s' on config file line %d",
|
||||
state->token, state->linenum);
|
||||
state->error = 1;
|
||||
}
|
||||
next_token (state);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
consume_num (parse_state *state)
|
||||
{
|
||||
@@ -1484,7 +1100,6 @@ static Uint8
|
||||
consume_dir (parse_state *state)
|
||||
{
|
||||
Uint8 result = 0;
|
||||
#ifdef HAVE_JOYSTICK
|
||||
if (!stricmp (state->token, "left"))
|
||||
{
|
||||
result = SDL_HAT_LEFT;
|
||||
@@ -1505,7 +1120,6 @@ consume_dir (parse_state *state)
|
||||
{
|
||||
expected_error (state, "left', 'right', 'up' or 'down");
|
||||
}
|
||||
#endif /* HAVE_JOYSTICK */
|
||||
next_token (state);
|
||||
return result;
|
||||
}
|
||||
@@ -1586,6 +1200,7 @@ parse_gesture (parse_state *state, VCONTROL_GESTURE *gesture)
|
||||
gesture->type = VCONTROL_KEY;
|
||||
gesture->gesture.key = keysym;
|
||||
}
|
||||
}
|
||||
else if (!stricmp (state->token, "joystick"))
|
||||
{
|
||||
parse_joybinding (state, gesture);
|
||||
@@ -1594,22 +1209,6 @@ parse_gesture (parse_state *state, VCONTROL_GESTURE *gesture)
|
||||
{
|
||||
expected_error (state, "key' or 'joystick");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_binding (parse_state *state)
|
||||
{
|
||||
int *target = consume_idname (state);
|
||||
if (!state->error)
|
||||
{
|
||||
VCONTROL_GESTURE g;
|
||||
parse_gesture (state, &g);
|
||||
if (g.type != VCONTROL_NONE)
|
||||
{
|
||||
VControl_AddGestureBinding (&g, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1624,6 +1223,8 @@ VControl_ParseGesture (VCONTROL_GESTURE *g, const char *spec)
|
||||
|
||||
next_token (&ps);
|
||||
parse_gesture (&ps, g);
|
||||
if (ps.error)
|
||||
printf ("Error parsing %s\n", spec);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1648,133 +1249,3 @@ VControl_DumpGesture (char *buf, int n, VCONTROL_GESTURE *g)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_config_line (parse_state *state)
|
||||
{
|
||||
state->error = 0;
|
||||
next_token (state);
|
||||
if (!state->token[0])
|
||||
{
|
||||
/* Blank line, skip it */
|
||||
return;
|
||||
}
|
||||
if (!stricmp (state->token, "joystick"))
|
||||
{
|
||||
int sticknum, threshold = 0;
|
||||
consume (state, "joystick");
|
||||
sticknum = consume_num (state);
|
||||
if (!state->error) consume (state, "threshold");
|
||||
if (!state->error) threshold = consume_num (state);
|
||||
if (!state->error)
|
||||
{
|
||||
if (VControl_SetJoyThreshold (sticknum, threshold))
|
||||
{
|
||||
// Don't count this as an error
|
||||
// state->error = 1;
|
||||
}
|
||||
}
|
||||
if (!state->error)
|
||||
{
|
||||
validlines++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!stricmp (state->token, "version"))
|
||||
{
|
||||
consume (state, "version");
|
||||
version = consume_num (state);
|
||||
if (!state->error)
|
||||
{
|
||||
validlines++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Otherwise, it must be a binding */
|
||||
parse_binding (state);
|
||||
if (!state->error)
|
||||
{
|
||||
validlines++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
VControl_ReadConfiguration (uio_Stream *in)
|
||||
{
|
||||
parse_state ps;
|
||||
if (!in)
|
||||
{
|
||||
log_add (log_Warning, "VControl: Invalid configuration file stream");
|
||||
return 1;
|
||||
}
|
||||
ps.linenum = 0;
|
||||
errors = version = validlines = 0;
|
||||
while (1)
|
||||
{
|
||||
next_line (&ps, in);
|
||||
if (!ps.line[0])
|
||||
break;
|
||||
parse_config_line (&ps);
|
||||
if (ps.error)
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
int
|
||||
VControl_GetErrorCount (void)
|
||||
{
|
||||
return errors;
|
||||
}
|
||||
|
||||
int
|
||||
VControl_GetValidCount (void)
|
||||
{
|
||||
return validlines;
|
||||
}
|
||||
|
||||
int
|
||||
VControl_GetConfigFileVersion (void)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
void
|
||||
VControl_SetConfigFileVersion (int v)
|
||||
{
|
||||
version = v;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This was kinda handy for proving (lack of) buffer overrun
|
||||
* vulnerabilities, but there's no real need for it otherwise. */
|
||||
void
|
||||
VControl_TokenizeFile (FILE *in)
|
||||
{
|
||||
parse_state ps;
|
||||
if (!in)
|
||||
{
|
||||
log_add (log_Warning, "VControl: Invalid configuration file stream");
|
||||
return;
|
||||
}
|
||||
ps.linenum = 0;
|
||||
while (1)
|
||||
{
|
||||
_next_line (&ps, in);
|
||||
if (!ps.line[0])
|
||||
break;
|
||||
printf ("%3d:", ps.linenum);
|
||||
while (1)
|
||||
{
|
||||
_next_token (&ps);
|
||||
if (!ps.token[0])
|
||||
break;
|
||||
printf (" \"%s\"", ps.token);
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#define _VCONTROL_H_
|
||||
|
||||
#include "port.h"
|
||||
#include "libs/uio.h"
|
||||
#include SDL_INCLUDE(SDL.h)
|
||||
|
||||
/* Initialization routines */
|
||||
@@ -80,45 +79,10 @@ void VControl_ProcessJoyHat (int port, int which, Uint8 value);
|
||||
/* Force the input into the blank state. For preventing "sticky" keys. */
|
||||
void VControl_ResetInput (void);
|
||||
|
||||
/* Name control. To provide a table of names and bindings, declare
|
||||
* a persistent, unchanging array of VControl_NameBinding and end it
|
||||
* with a {0, 0} entry. Pass this array to VControl_RegisterNameTable.
|
||||
* Only one name table may be registered at a time; subsequent calls
|
||||
* replace the previous values. */
|
||||
|
||||
typedef struct vcontrol_namebinding {
|
||||
char *name;
|
||||
int *target;
|
||||
} VControl_NameBinding;
|
||||
|
||||
void VControl_RegisterNameTable (VControl_NameBinding *table);
|
||||
|
||||
/* Version number control */
|
||||
int VControl_GetConfigFileVersion (void);
|
||||
void VControl_SetConfigFileVersion (int v);
|
||||
|
||||
/* Translate between gestures and string representations thereof. */
|
||||
void VControl_ParseGesture (VCONTROL_GESTURE *g, const char *spec);
|
||||
int VControl_DumpGesture (char *buf, int n, VCONTROL_GESTURE *g);
|
||||
|
||||
/* Dump a configuration file corresponding to the current bindings and names. */
|
||||
void VControl_Dump (uio_Stream *out);
|
||||
void VControl_SaveFilename (uio_DirHandle *path, const char *fname);
|
||||
|
||||
/* Read a configuration file. Returns number of errors encountered. */
|
||||
int VControl_ReadConfiguration (uio_Stream *in);
|
||||
int VControl_GetErrorCount (void);
|
||||
int VControl_GetValidCount (void);
|
||||
|
||||
|
||||
/* Iterator control. Start an iteration with StartIter or
|
||||
StartIterByName; then call NextBindingName until it returns 0.
|
||||
Produces gestures. */
|
||||
|
||||
void VControl_StartIter (int *target);
|
||||
void VControl_StartIterByName (char *targetname);
|
||||
int VControl_NextBinding (VCONTROL_GESTURE *gesture);
|
||||
|
||||
/* Tracking the "last interesting gesture." Used to poll to find new
|
||||
control keys. */
|
||||
|
||||
|
||||
@@ -1360,13 +1360,13 @@ SetGlobalOptions (GLOBALOPTS *opts)
|
||||
SetMusicVolume (musicVolume);
|
||||
SetSpeechVolume (speechVolumeScale);
|
||||
|
||||
res_PutString ("config.keys.1.name", input_templates[0].name);
|
||||
res_PutString ("config.keys.2.name", input_templates[1].name);
|
||||
res_PutString ("config.keys.3.name", input_templates[2].name);
|
||||
res_PutString ("config.keys.4.name", input_templates[3].name);
|
||||
res_PutString ("config.keys.5.name", input_templates[4].name);
|
||||
res_PutString ("config.keys.6.name", input_templates[5].name);
|
||||
res_PutString ("keys.1.name", input_templates[0].name);
|
||||
res_PutString ("keys.2.name", input_templates[1].name);
|
||||
res_PutString ("keys.3.name", input_templates[2].name);
|
||||
res_PutString ("keys.4.name", input_templates[3].name);
|
||||
res_PutString ("keys.5.name", input_templates[4].name);
|
||||
res_PutString ("keys.6.name", input_templates[5].name);
|
||||
|
||||
res_SaveFilename (configDir, "uqm.cfg", "config.");
|
||||
SaveKeyConfiguration (configDir, "keys.cfg");
|
||||
SaveKeyConfiguration (configDir, "flight.cfg");
|
||||
}
|
||||
|
||||
+2
-16
@@ -369,12 +369,7 @@ main (int argc, char *argv[])
|
||||
&options.speechVolumeScale, "speech volume");
|
||||
}
|
||||
|
||||
{ /* init control template names */
|
||||
static const char* defaultNames[] =
|
||||
{
|
||||
"Arrows", "WASD", "Arrows (2)",
|
||||
"ESDF", "Joystick 1", "Joystick 2"
|
||||
};
|
||||
{ /* remove old control template names */
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; ++i)
|
||||
@@ -384,16 +379,7 @@ main (int argc, char *argv[])
|
||||
snprintf(cfgkey, sizeof(cfgkey), "config.keys.%d.name", i + 1);
|
||||
cfgkey[sizeof(cfgkey) - 1] = '\0';
|
||||
|
||||
if (res_HasKey (cfgkey))
|
||||
{
|
||||
strncpy (input_templates[i].name, res_GetString (cfgkey), 30);
|
||||
input_templates[i].name[29] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (input_templates[i].name, defaultNames[i]);
|
||||
res_PutString (cfgkey, input_templates[i].name);
|
||||
}
|
||||
res_Remove (cfgkey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user