1
0
forked from 0ad/0ad

# Various hotkey fixes and cleanups.

Support ctrl for removing entities from selection.
Move big screenshot hotkey to shift+F2.
Increase mouse wheel rotation speed.
Fix HotkeyIsPressed when a more specific hotkey was matched instead.
Support multiple hotkeys with the same binding.
Use hotkeys instead of raw key events in GUI.
Delete some obsolete hotkey definitions.
Remove unused broken EntitySelection toggle method.

This was SVN commit r8546.
This commit is contained in:
Ykkrosh 2010-11-07 20:42:52 +00:00
parent a13836bd68
commit e43eb0c18b
10 changed files with 194 additions and 213 deletions

View File

@ -77,7 +77,7 @@ view.rotate.x.min = 20
view.rotate.x.max = 60
view.rotate.x.default = 30
view.rotate.y.speed = 2.0
view.rotate.y.speed.wheel = 0.1
view.rotate.y.speed.wheel = 0.45
view.rotate.y.default = 0.0
view.drag.speed = 0.5
view.zoom.speed = 256.0
@ -98,53 +98,42 @@ view.rotate.y.smoothness = 0.3
; See keys.txt for the list of key names.
; > SYSTEM SETTINGS
hotkey.exit = "Alt+F4", "Ctrl+Break" ; Exit to desktop.
hotkey.leave = Escape ;End current game or Exit.
hotkey.pause = Pause ; Pause/unpause game.
hotkey.screenshot = F2 ; Take PNG screenshot.
hotkey.bigscreenshot = "Ctrl+Alt+F2" ; Take large BMP screenshot.
hotkey.togglefullscreen = "Alt+Return" ; Toggle fullscreen/windowed mode
hotkey.screenshot.watermark = "K" ; Toggle product/company watermark for official
hotkey.wireframe = "Alt+W" ; Toggle wireframe mode.
hotkey.archive.abort = "Alt+F4" ; Prematurely terminate the archive builder process.
hotkey.exit = "Alt+F4", "Ctrl+Break" ; Exit to desktop
hotkey.leave = Escape ; End current game or Exit
hotkey.pause = Pause ; Pause/unpause game
hotkey.screenshot = F2 ; Take PNG screenshot
hotkey.bigscreenshot = "Shift+F2" ; Take large BMP screenshot
hotkey.togglefullscreen = "Alt+Return" ; Toggle fullscreen/windowed mode
hotkey.screenshot.watermark = "K" ; Toggle product/company watermark for official screenshots
hotkey.wireframe = "Alt+W" ; Toggle wireframe mode
; > CAMERA SETTINGS
hotkey.camera.reset = "H" ; Reset camera rotation to default.
hotkey.camera.follow = "F" ; Follow the first unit in the selection
hotkey.camera.reset.origin = "Ctrl+H" ; Reset camera to origin.
hotkey.camera.zoom.in = Plus, Equals, NumPlus ; Zoom camera in.
hotkey.camera.zoom.out = Minus, NumMinus ; Zoom camera out.
hotkey.camera.zoom.wheel.in = WheelUp ; Zoom camera in (wheel speed).
hotkey.camera.zoom.wheel.out = WheelDown ; Zoom camera out (wheel speed).
hotkey.camera.rotate.wheel.cw = "Shift+WheelUp"
hotkey.camera.rotate.wheel.ccw = "Shift+WheelDown"
hotkey.camera.rotate.cw = "Ctrl+LeftArrow", "Ctrl+A", Q
hotkey.camera.rotate.ccw = "Ctrl+RightArrow", "Ctrl+D", E
hotkey.camera.rotate.up = "Ctrl+UpArrow", "Ctrl+W"
hotkey.camera.rotate.down = "Ctrl+DownArrow", "Ctrl+S"
hotkey.camera.pan = MouseMiddle, ForwardSlash ; Scroll by moving mouse.
hotkey.camera.pan.keyboard = "~Shift+~Ctrl" ; = holding neither Ctrl nor Shift
hotkey.camera.left = A, LeftArrow ; Scroll or rotate left.
hotkey.camera.right = D, RightArrow ; Scroll or rotate right.
hotkey.camera.up = W, UpArrow ; Scroll or rotate up/forwards.
hotkey.camera.down = S, DownArrow ; Scroll or rotate down/backwards.
;camera.cinema.add = "L"
;camera.cinema.delete = "U"
;camera.cinema.delete.all = "R"
;camera.cinema.write = "O"
camera.cinema.queue = "I"
hotkey.camera.reset = "H" ; Reset camera rotation to default.
hotkey.camera.follow = "F" ; Follow the first unit in the selection
hotkey.camera.zoom.in = Plus, Equals, NumPlus ; Zoom camera in (continuous control)
hotkey.camera.zoom.out = Minus, NumMinus ; Zoom camera out (continuous control)
hotkey.camera.zoom.wheel.in = WheelUp ; Zoom camera in (stepped control)
hotkey.camera.zoom.wheel.out = WheelDown ; Zoom camera out (stepped control)
hotkey.camera.rotate.up = "Ctrl+UpArrow", "Ctrl+W" ; Rotate camera to look upwards
hotkey.camera.rotate.down = "Ctrl+DownArrow", "Ctrl+S" ; Rotate camera to look downwards
hotkey.camera.rotate.cw = "Ctrl+LeftArrow", "Ctrl+A", Q ; Rotate camera clockwise around terrain
hotkey.camera.rotate.ccw = "Ctrl+RightArrow", "Ctrl+D", E ; Rotate camera anticlockwise around terrain
hotkey.camera.rotate.wheel.cw = "Shift+WheelUp" ; Rotate camera clockwise around terrain (stepped control)
hotkey.camera.rotate.wheel.ccw = "Shift+WheelDown" ; Rotate camera clockwise around terrain (stepped control)
hotkey.camera.pan = MouseMiddle, ForwardSlash ; Enable scrolling by moving mouse
hotkey.camera.left = A, LeftArrow ; Scroll or rotate left
hotkey.camera.right = D, RightArrow ; Scroll or rotate right
hotkey.camera.up = W, UpArrow ; Scroll or rotate up/forwards
hotkey.camera.down = S, DownArrow ; Scroll or rotate down/backwards
; > CONSOLE SETTINGS
hotkey.console.toggle = BackQuote, F9 ; Open/close console.
hotkey.console.copy = "Ctrl+C" ; Copy from console to clipboard.
hotkey.console.paste = Insert, "Ctrl+V" ; Paste clipboard to console.
hotkey.console.toggle = BackQuote, F9 ; Open/close console
hotkey.console.copy = "Ctrl+C" ; Copy from console to clipboard
hotkey.console.paste = "Ctrl+V" ; Paste clipboard to console
; > ENTITY SELECTION
hotkey.selection.add = Shift ; Add units to selection.
hotkey.selection.remove = Ctrl ; Remove units from selection.
hotkey.selection.add = Shift ; Add units to selection
hotkey.selection.remove = Ctrl ; Remove units from selection
hotkey.selection.group.0 = 0
hotkey.selection.group.1 = 1
hotkey.selection.group.2 = 2
@ -155,70 +144,30 @@ hotkey.selection.group.6 = 6
hotkey.selection.group.7 = 7
hotkey.selection.group.8 = 8
hotkey.selection.group.9 = 9
hotkey.selection.group.add = Shift ; +group: Add units to group.
hotkey.selection.group.save = Ctrl ; +group: Save units to group.
hotkey.selection.group.snap = Alt ; +group: Check up on group.
hotkey.selection.snap = Home ; Centre view on selection.
hotkey.highlightall = O ; Show selection circle for all units on screen.
hotkey.killUnit = Delete
hotkey.selection.group.add = Shift ; +group: Add units to group
hotkey.selection.group.save = Ctrl ; +group: Save units to group
hotkey.selection.group.snap = Alt ; +group: Check up on group
hotkey.selection.snap = Home ; Centre view on selection
; > CONTEXT CURSOR
hotkey.contextorder.next = LeftBracket ; Cycle right through orders (context cursors).
hotkey.contextorder.previous = RightBracket ; Cycle left through orders (context cursors).
; > TESTING KEYS
hotkey.orbital.toggle = V ; Enable/disable ball arena.
hotkey.orbital.cheat = "LeftCtrl+Backslash" ; Freeze ball.
hotkey.dudemachine.random = "Ctrl+ForwardSlash" ; Create random Dude.
; > SESSION CONTROLS
hotkey.session.kill = Delete ; Destroy selected units
hotkey.session.garrison = Ctrl ; Modifier to garrison when clicking on building
hotkey.session.queue = Shift ; Modifier to queue unit orders instead of replacing
hotkey.session.batchtrain = Shift ; Modifier to train units in batches
hotkey.session.deselectgroup = Ctrl ; Modifier to deselect units when clicking group icon, instead of selecting
hotkey.session.rotate.cw = RightBracket ; Rotate building placement preview clockwise
hotkey.session.rotate.ccw = LeftBracket ; Rotate building placement preview anticlockwise
; > OVERLAY KEYS
hotkey.fps.toggle = "Shift+F" ; Toggle frame counter.
hotkey.session.statuspane.toggle = "Shift+S" ; Toggle Status Orb.
hotkey.session.minimap.toggle = "Shift+M" ; Toggle Map Orb.
hotkey.resourcepool.toggle = "Shift+R" ; Toggle Resource Pool.
hotkey.grouppane.toggle = "Shift+G" ; Toggle Group Pane.
hotkey.teamtray.toggle = "Shift+T" ; Toggle Team Tray.
hotkey.session.ShowPlayersList = "Shift+P" ; Toggle Players List
hotkey.session.devcommands.toggle = "Shift+D"
; > SESSION ORIENTATION KEYS
hotkey.session.gui.flip = "Alt+G" ; Toggle GUI to top/bottom/left/right of screen.
hotkey.session.gui.toggle = "G" ; Toggle visibility of session GUI.
; (TEMPORARY)
hotkey.alwayson.toggle = "Shift+X" ; Toggle always ons (Exit Button, End Game Button).
; > SUBMENU KEYS
hotkey.menu.toggle = "F10" ; Toggle in-game menu.
hotkey.menu.resign = "Alt+X" ; End current game session and return to main menu.
hotkey.fps.toggle = "Shift+F" ; Toggle frame counter
hotkey.session.devcommands.toggle = "Shift+D" ; Toggle developer commands panel
hotkey.session.gui.toggle = "G" ; Toggle visibility of session GUI
hotkey.menu.toggle = "F10" ; Toggle in-game menu
; > HOTKEYS ONLY
hotkey.chat = Return ; Toggles chat window
hotkey.onlinehelp = "F1" ; Enable/disable online manual entry for current selection.
hotkey.music.toggle = "M" ; Enable/disable music.
hotkey.audio.toggle = "Ctrl+A" ; Enable/disable sound.
hotkey.chat = Return ; Toggle chat window
; > PROFILER
hotkey.profile.toggle = "F11" ; Enable/disable real-time profiler
hotkey.profile.save = "Shift+F11" ; Save current profiler data to "logs/profile.txt"
hotkey.profile.toggle = "F11" ; Enable/disable real-time profiler
hotkey.profile.save = "Shift+F11" ; Save current profiler data to logs/profile.txt
; UNMAPPED KEY/MOUSE REFERENCE:
; LMB ; select unit
; RMB ; issue order to selected units
; LMB-drag ; bandbox units
; LMB-doubleclick ; select all units of this type on screen
; LMB-tripleclick ; select all units of this type on map
; shift+mouse select ; add to selection
; ctrl+mouse select ; remove from selection
; #=(1...0) ; select group #, pressing again centres view
; shift+# ; add group # to selection
; ctrl+# ; save selection as group #
; alt+# (hold down) ; snap view to group # (while alt is held down)
; mouse on map edge ; scroll in this direction

View File

@ -126,8 +126,8 @@ Right Alt, RightAlt
Left Alt, LeftAlt
Right Meta
Left Meta
Left Super, LeftWin
Right Super, RightWin
Left Super, LeftWin
Right Super, RightWin
Alt Gr, AltGr
Compose

View File

@ -356,7 +356,6 @@ Watch for updates or get involved in the development: http://wildfiregames.com/0
<object name="pgOptionsAudioSoundCheckBox"
style="wheatCrossBox"
type="checkbox"
hotkey="audio.toggle"
size="50%-50 20% 50%+50 25%"
>Mute All
<action on="Load"><![CDATA[

View File

@ -30,15 +30,6 @@ var placementEntity;
var mouseX = 0;
var mouseY = 0;
var mouseIsOverObject = false;
var specialKeyStates = {};
specialKeyStates[SDLK_RSHIFT] = 0;
specialKeyStates[SDLK_LSHIFT] = 0;
specialKeyStates[SDLK_RCTRL] = 0;
specialKeyStates[SDLK_LCTRL] = 0;
specialKeyStates[SDLK_RALT] = 0;
specialKeyStates[SDLK_LALT] = 0;
// (TODO: maybe we should fix the hotkey system to be usable in this situation,
// rather than hardcoding Shift/Ctrl/Alt into this code?)
// Number of pixels the mouse can move before the action is considered a drag
var maxDragDelta = 4;
@ -85,7 +76,7 @@ function findGatherType(gatherer, supply)
function determineAction(x, y, fromMinimap)
{
var selection = g_Selection.toList();
var ctrlPressed = specialKeyStates[SDLK_LCTRL] || specialKeyStates[SDLK_RCTRL];
// No action if there's no selection
if (!selection.length)
return undefined;
@ -135,7 +126,7 @@ function determineAction(x, y, fromMinimap)
var enemyOwned = ((targetState.player != entState.player)? true : false);
var gaiaOwned = ((targetState.player == 0)? true : false);
if (targetState.garrisonHolder && playerOwned && ctrlPressed)
if (targetState.garrisonHolder && playerOwned && Engine.HotkeyIsPressed("session.garrison"))
{
return {"type": "garrison", "cursor": "action-garrison", "target": targets[0]};
}
@ -171,21 +162,6 @@ function determineAction(x, y, fromMinimap)
return {"type": "move"};
}
/*
Selection methods: (not all currently implemented)
- Left-click on entity to select (always chooses the 'closest' one if the mouse is over several).
Includes non-controllable units (e.g. trees, enemy units).
- Double-left-click to select entity plus all of the same type on the screen.
- Triple-left-click to select entity plus all of the same type in the world.
- Left-click-and-drag to select all in region. Only includes controllable units.
- Left-click on empty space to deselect all.
- Hotkeys to select various groups.
- Shift plus left-click on entity to toggle selection of that unit. Only includes controllable.
- Shift plus any other selection method above, to add them to current selection.
*/
var dragStart; // used for remembering mouse coordinates at start of drag operations
@ -263,14 +239,6 @@ function handleInputBeforeGui(ev, hoveredObject)
mouseX = ev.x;
mouseY = ev.y;
break;
case "keydown":
if (ev.keysym.sym in specialKeyStates)
specialKeyStates[ev.keysym.sym] = 1;
break;
case "keyup":
if (ev.keysym.sym in specialKeyStates)
specialKeyStates[ev.keysym.sym] = 0;
break;
}
// Remember whether the mouse is over a GUI object or not
@ -327,14 +295,24 @@ function handleInputBeforeGui(ev, hoveredObject)
if (preferredEntities.length)
ents = preferredEntities;
// If shift is pressed, don't reset the selection, but allow units to be added to the existing selection
var addition = (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT]);
if (!addition)
g_Selection.reset();
// Set Selection
// Remove the bandbox hover highlighting
g_Selection.setHighlightList([]);
g_Selection.addList(ents);
// Update the list of selected units
if (Engine.HotkeyIsPressed("selection.add"))
{
g_Selection.addList(ents);
}
else if (Engine.HotkeyIsPressed("selection.remove"))
{
g_Selection.removeList(ents);
}
else
{
g_Selection.reset();
g_Selection.addList(ents);
}
inputState = INPUT_NORMAL;
return true;
}
@ -373,7 +351,7 @@ function handleInputBeforeGui(ev, hoveredObject)
if (ev.button == SDL_BUTTON_LEFT)
{
// If shift is down, let the player continue placing another of the same building
var queued = (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT]);
var queued = Engine.HotkeyIsPressed("session.queue");
if (tryPlaceBuilding(queued))
{
if (queued)
@ -433,7 +411,7 @@ function handleInputBeforeGui(ev, hoveredObject)
if (ev.button == SDL_BUTTON_LEFT)
{
// If shift is down, let the player continue placing another of the same building
var queued = (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT]);
var queued = Engine.HotkeyIsPressed("session.queue");
if (tryPlaceBuilding(queued))
{
if (queued)
@ -464,8 +442,8 @@ function handleInputBeforeGui(ev, hoveredObject)
case INPUT_BATCHTRAINING:
switch (ev.type)
{
case "keyup":
if (ev.keysym.sym == SDLK_RSHIFT || ev.keysym.sym == SDLK_LSHIFT)
case "hotkeyup":
if (ev.hotkey == "session.batchtrain")
{
flushTrainingQueueBatch();
inputState = INPUT_NORMAL;
@ -513,7 +491,7 @@ function handleInputAfterGui(ev)
// If shift is down, add the order to the unit's order queue instead
// of running it immediately
var queued = (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT]);
var queued = Engine.HotkeyIsPressed("session.queue");
switch (action.type)
{
@ -639,12 +617,20 @@ function handleInputAfterGui(ev)
ents = [ents[0]];
}
// If shift is pressed, don't reset the selection, but allow units to be added to the existing selection
var addition = (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT]);
if (!addition)
// Update the list of selected units
if (Engine.HotkeyIsPressed("selection.add"))
{
g_Selection.addList(ents);
}
else if (Engine.HotkeyIsPressed("selection.remove"))
{
g_Selection.removeList(ents);
}
else
{
g_Selection.reset();
g_Selection.addList(ents);
g_Selection.addList(ents);
}
inputState = INPUT_NORMAL;
return true;
@ -684,24 +670,31 @@ function handleInputAfterGui(ev)
}
break;
case "keydown":
case "hotkeydown":
var rotation_step = Math.PI / 12; // 24 clicks make a full rotation
if (ev.keysym.sym == SDLK_LEFTBRACKET) // rotate anti-clockwise
switch (ev.hotkey)
{
placementAngle = placementAngle - rotation_step;
case "session.rotate.cw":
placementAngle += rotation_step;
Engine.GuiInterfaceCall("SetBuildingPlacementPreview", {
"template": placementEntity,
"x": placementPosition.x,
"z": placementPosition.z,
"angle": placementAngle
});
break;
case "session.rotate.ccw":
placementAngle -= rotation_step;
Engine.GuiInterfaceCall("SetBuildingPlacementPreview", {
"template": placementEntity,
"x": placementPosition.x,
"z": placementPosition.z,
"angle": placementAngle
});
break;
}
else if (ev.keysym.sym == SDLK_RIGHTBRACKET) // rotate clockwise
{
placementAngle = placementAngle + rotation_step;
}
Engine.GuiInterfaceCall("SetBuildingPlacementPreview", {
"template": placementEntity,
"x": placementPosition.x,
"z": placementPosition.z,
"angle": placementAngle
});
break;
@ -725,7 +718,7 @@ function handleMinimapEvent(target)
var selection = g_Selection.toList();
var queued = (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT]);
var queued = Engine.HotkeyIsPressed("session.queue");
switch (action.type)
{
@ -775,7 +768,7 @@ function flushTrainingQueueBatch()
// Called by GUI when user clicks training button
function addToTrainingQueue(entity, trainEntType)
{
if (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT])
if (Engine.HotkeyIsPressed("session.batchtrain"))
{
if (inputState == INPUT_BATCHTRAINING)
{
@ -823,7 +816,7 @@ function removeFromTrainingQueue(entity, id)
// Called by unit selection buttons
function changePrimarySelectionGroup(templateName)
{
if (specialKeyStates[SDLK_RCTRL] || specialKeyStates[SDLK_LCTRL])
if (Engine.HotkeyIsPressed("session.deselectgroup"))
g_Selection.makePrimarySelection(templateName, true);
else
g_Selection.makePrimarySelection(templateName, false);

View File

@ -224,25 +224,6 @@ EntitySelection.prototype.update = function()
}
};
EntitySelection.prototype.toggle = function(ent)
{
if (this.selected[ent])
{
_setHighlight([ent], 0);
_setStatusBars([ent], false);
_setMotionOverlay([ent], false);
delete this.selected[ent];
}
else
{
_setHighlight([ent], 1);
_setStatusBars([ent], true);
_setMotionOverlay([ent], this.motionDebugOverlay);
this.selected[ent] = ent;
}
this.dirty = true;
};
EntitySelection.prototype.addList = function(ents)
{
var selectionSize = this.toList().length;
@ -269,6 +250,27 @@ EntitySelection.prototype.addList = function(ents)
this.dirty = true;
};
EntitySelection.prototype.removeList = function(ents)
{
var removed = [];
for each (var ent in ents)
{
if (this.selected[ent])
{
this.groups.removeEnt(ent);
removed.push(ent);
delete this.selected[ent];
}
}
_setHighlight(removed, 0);
_setStatusBars(removed, false);
_setMotionOverlay(removed, false);
this.dirty = true;
};
EntitySelection.prototype.reset = function()
{
_setHighlight(this.toList(), 0);

View File

@ -75,7 +75,7 @@
</object>
<!-- Delete button Hotkey (For some reason it won't work when the console is visible -->
<object hotkey="killUnit">
<object hotkey="session.kill">
<action on="Press">performCommand(g_Selection.toList()[0], "delete");</action>
</object>

View File

@ -638,17 +638,14 @@ void CGameView::Update(float DeltaTime)
moveForward += m->ViewScrollSpeed * DeltaTime;
}
if (HotkeyIsPressed("camera.pan.keyboard"))
{
if (HotkeyIsPressed("camera.right"))
moveRightward += m->ViewScrollSpeed * DeltaTime;
if (HotkeyIsPressed("camera.left"))
moveRightward -= m->ViewScrollSpeed * DeltaTime;
if (HotkeyIsPressed("camera.up"))
moveForward += m->ViewScrollSpeed * DeltaTime;
if (HotkeyIsPressed("camera.down"))
moveForward -= m->ViewScrollSpeed * DeltaTime;
}
if (HotkeyIsPressed("camera.right"))
moveRightward += m->ViewScrollSpeed * DeltaTime;
if (HotkeyIsPressed("camera.left"))
moveRightward -= m->ViewScrollSpeed * DeltaTime;
if (HotkeyIsPressed("camera.up"))
moveForward += m->ViewScrollSpeed * DeltaTime;
if (HotkeyIsPressed("camera.down"))
moveForward -= m->ViewScrollSpeed * DeltaTime;
if (moveRightward || moveForward)
{

View File

@ -33,6 +33,7 @@
#include "ps/CConsole.h"
#include "ps/Errors.h"
#include "ps/Game.h"
#include "ps/Hotkey.h"
#include "ps/Overlay.h"
#include "ps/Pyrogenesis.h"
#include "ps/GameSetup/Atlas.h"
@ -322,6 +323,11 @@ void CameraFollowFPS(void* UNUSED(cbdata), entity_id_t entityid)
g_Game->GetView()->CameraFollow(entityid, true);
}
bool HotkeyIsPressed_(void* UNUSED(cbdata), std::string hotkeyName)
{
return HotkeyIsPressed(hotkeyName);
}
void SetSimRate(void* UNUSED(cbdata), float rate)
{
g_Game->SetSimRate(rate);
@ -403,6 +409,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
scriptInterface.RegisterFunction<CScriptVal, std::wstring, &LoadMapSettings>("LoadMapSettings");
scriptInterface.RegisterFunction<void, entity_id_t, &CameraFollow>("CameraFollow");
scriptInterface.RegisterFunction<void, entity_id_t, &CameraFollowFPS>("CameraFollowFPS");
scriptInterface.RegisterFunction<bool, std::string, &HotkeyIsPressed_>("HotkeyIsPressed");
// Development/debugging functions
scriptInterface.RegisterFunction<void, float, &SetSimRate>("SetSimRate");

View File

@ -256,12 +256,12 @@ InReaction HotkeyInputHandler( const SDL_Event_* ev )
// -- KEYDOWN SECTION --
const char* closestMapName = NULL;
std::vector<const char*> closestMapNames;
size_t closestMapMatch = 0;
for( std::vector<SHotkeyMapping>::iterator it = g_HotkeyMap[keycode].begin(); it < g_HotkeyMap[keycode].end(); it++ )
{
// If a key has been pressed, and this event triggers on it's release, skip it.
// If a key has been pressed, and this event triggers on its release, skip it.
// Similarly, if the key's been released and the event triggers on a keypress, skip it.
if( it->negated == typeKeyDown )
continue;
@ -298,22 +298,34 @@ InReaction HotkeyInputHandler( const SDL_Event_* ev )
if( accept && !( isCapturable && consoleCapture ) )
{
g_HotkeyStatus[it->name] = true;
if( it->requires.size() >= closestMapMatch )
// Tentatively set status to un-pressed, since it may be overridden by
// a closer match. (The closest matches will be set to pressed later.)
g_HotkeyStatus[it->name] = false;
// Check if this is an equally precise or more precise match
if( it->requires.size() + 1 >= closestMapMatch )
{
// Only if it's a more precise match, and it either isn't capturable or the console won't capture it.
closestMapName = it->name.c_str();
closestMapMatch = it->requires.size() + 1;
// Check if more precise
if( it->requires.size() + 1 > closestMapMatch )
{
// Throw away the old less-precise matches
closestMapNames.clear();
closestMapMatch = it->requires.size() + 1;
}
closestMapNames.push_back(it->name.c_str());
}
}
}
if( closestMapMatch )
for (size_t i = 0; i < closestMapNames.size(); ++i)
{
g_HotkeyStatus[closestMapNames[i]] = true;
SDL_Event hotkeyNotification;
hotkeyNotification.type = SDL_HOTKEYDOWN;
hotkeyNotification.user.data1 = const_cast<char*>(closestMapName);
SDL_PushEvent( &hotkeyNotification );
hotkeyNotification.user.data1 = const_cast<char*>(closestMapNames[i]);
SDL_PushEvent(&hotkeyNotification);
}
// -- KEYUP SECTION --

View File

@ -38,6 +38,28 @@ public:
TS_ASSERT(Line.GetArgInt(1, i) && i == 23);
}
void test_hotkey()
{
CParser Parser;
Parser.InputTaskType( "multikey", "<[~$arg(_negate)]$value_+_>_[~$arg(_negate)]$value" );
std::string str;
CParserLine Line;
TS_ASSERT(Line.ParseString(Parser, "x+yzzy+~w"));
TS_ASSERT_EQUALS((int)Line.GetArgCount(), 4);
TS_ASSERT(Line.GetArgString(0, str) && str == "x");
TS_ASSERT(Line.GetArgString(1, str) && str == "yzzy");
TS_ASSERT(Line.GetArgString(2, str) && str == "_negate");
TS_ASSERT(Line.GetArgString(3, str) && str == "w");
// This fails because '[' isn't a value character (per _IsValueChar).
// I don't know whether that's a feature or a bug.
// TS_ASSERT(Line.ParseString(Parser, "["));
// TS_ASSERT_EQUALS((int)Line.GetArgCount(), 1);
// TS_ASSERT(Line.GetArgString(0, str) && str == "[");
}
void test_optional()
{