keybindings.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 816 行 · 第 1/2 页
CPP
816 行
#include "StdAfx.h"
// CKeyBindings.cpp: implementation of the CKeyBindings class.
//
//////////////////////////////////////////////////////////////////////
#include "KeyBindings.h"
#include <stdio.h>
#include <cctype>
#include "SDL_keysym.h"
#include "KeyCodes.h"
#include "KeySet.h"
#include "KeyAutoBinder.h"
#include "Sim/Units/UnitDef.h"
#include "Sim/Units/UnitDefHandler.h"
#include "System/Platform/errorhandler.h"
#include "System/FileSystem/FileHandler.h"
#include "System/FileSystem/SimpleParser.h"
#include "System/LogOutput.h"
CKeyBindings* keyBindings = NULL;
static const struct DefaultBinding {
const char* key;
const char* action;
}
defaultBindings[] = {
{ "esc", "quitwarn" },
{ "Shift+esc", "quit" },
{ "Any+pause", "pause" },
{ "Any+b", "debug" },
{ "Any+o", "singlestep" },
{ "Any+c", "controlunit" },
{ "Any+h", "sharedialog" },
{ "Any+l", "togglelos" },
{ "Any+;", "toggleradarandjammer" },
{ "Any+tab", "toggleoverview" },
{ "Any+j", "mouse2" },
{ "Any+backspace", "mousestate" },
{ "Any+i", "gameinfo" },
{ "Any+enter", "chat" },
{ "Ctrl+enter", "chatall" },
{ "Ctrl+enter", "chatswitchall" },
{ "Alt+enter", "chatally" },
{ "Alt+enter", "chatswitchally" },
{ "Shift+enter", "chatspec" },
{ "Shift+enter", "chatswitchspec" },
{ "Any+tab", "edit_complete" },
{ "Any+backspace", "edit_backspace" },
{ "Any+delete", "edit_delete" },
{ "Any+home", "edit_home" },
{ "Alt+left", "edit_home" },
{ "Any+end", "edit_end" },
{ "Alt+right", "edit_end" },
{ "Any+up", "edit_prev_line" },
{ "Any+down", "edit_next_line" },
{ "Any+left", "edit_prev_char" },
{ "Any+right", "edit_next_char" },
{ "Ctrl+left", "edit_prev_word" },
{ "Ctrl+right", "edit_next_word" },
{ "Any+enter", "edit_return" },
{ "Any+escape", "edit_escape" },
{ "Ctrl+v", "pastetext" },
{ "Any+home", "increaseViewRadius" },
{ "Any+end", "decreaseViewRadius" },
{ "Ctrl+insert", "hotbind" },
{ "Ctrl+delete", "hotunbind" },
{ "Any+insert", "speedup" },
{ "Any+delete", "slowdown" },
{ "Any+=", "speedup" },
{ "Any++", "speedup" },
{ "Any+-", "slowdown" },
{ "Any+numpad+", "speedup" },
{ "Any+numpad-", "slowdown" },
{ ",", "prevmenu" },
{ ".", "nextmenu" },
{ "Shift+,", "decguiopacity" },
{ "Shift+.", "incguiopacity" },
{ "1", "specteam 0" },
{ "2", "specteam 1" },
{ "3", "specteam 2" },
{ "4", "specteam 3" },
{ "5", "specteam 4" },
{ "6", "specteam 5" },
{ "7", "specteam 6" },
{ "8", "specteam 7" },
{ "9", "specteam 8" },
{ "0", "specteam 9" },
{ "Ctrl+1", "specteam 10" },
{ "Ctrl+2", "specteam 11" },
{ "Ctrl+3", "specteam 12" },
{ "Ctrl+4", "specteam 13" },
{ "Ctrl+5", "specteam 14" },
{ "Ctrl+6", "specteam 15" },
{ "Ctrl+7", "specteam 16" },
{ "Ctrl+8", "specteam 17" },
{ "Ctrl+9", "specteam 18" },
{ "Ctrl+0", "specteam 19" },
{ "Any+0", "group0" },
{ "Any+1", "group1" },
{ "Any+2", "group2" },
{ "Any+3", "group3" },
{ "Any+4", "group4" },
{ "Any+5", "group5" },
{ "Any+6", "group6" },
{ "Any+7", "group7" },
{ "Any+8", "group8" },
{ "Any+9", "group9" },
{ "Any+c", "controlunit" },
{ "[", "buildfacing inc" },
{ "Shift+[", "buildfacing inc" },
{ "]", "buildfacing dec" },
{ "Shift+]", "buildfacing dec" },
{ "Any+z", "buildspacing inc" },
{ "Any+x", "buildspacing dec" },
{ "d", "dgun" },
{ "Shift+d", "dgun" },
{ "Ctrl+d", "selfd" },
{ "Ctrl+Shift+d", "selfd queued" },
{ "s", "stop" },
{ "Shift+s", "stop" },
{ "w", "wait" },
{ "Shift+w", "wait queued" },
{ "m", "move" },
{ "Shift+m", "move" },
{ "a", "attack" },
{ "Shift+a", "attack" },
{ "Alt+a", "areaattack" },
{ "Alt+Shift+a", "areaattack" },
{ "f", "fight" },
{ "Shift+f", "fight" },
{ "p", "patrol" },
{ "Shift+p", "patrol" },
{ "g", "guard" },
{ "Shift+g", "guard" },
{ "e", "reclaim" },
{ "Shift+e", "reclaim" },
{ "r", "repair" },
{ "Shift+r", "repair" },
{ "l", "loadunits" },
{ "Shift+l", "loadunits" },
{ "u", "unloadunits" },
{ "Shift+u", "unloadunits" },
{ "k", "cloak" },
{ "Shift+k", "cloak" },
{ "x", "onoff" },
{ "Shift+x", "onoff" },
{ "q", "groupselect" },
{ "q", "groupadd" },
{ "Ctrl+q", "aiselect" },
{ "Shift+q", "groupclear" },
{ "Ctrl+t", "trackmode" },
{ "Any+t", "track" },
{ "Ctrl+f1", "viewfps" },
{ "Ctrl+f2", "viewta" },
{ "Ctrl+f3", "viewtw" },
{ "Ctrl+f4", "viewrot" },
{ "Ctrl+f5", "viewfree" },
{ "Any+f1", "showElevation" },
{ "Any+f2", "ShowPathMap" },
{ "Any+f3", "LastMsgPos" },
{ "Any+f4", "ShowMetalMap" },
{ "Any+f5", "hideinterface" },
{ "Any+f6", "NoSound" },
{ "Any+f7", "dynamicSky" },
{ "Ctrl+Shift+f8", "savegame" },
{ "Any+f9", "showhealthbars" },
{ "Ctrl+Shift+f10", "createvideo" },
{ "Any+f11", "screenshot" },
{ "Any+f12", "screenshot" },
// NOTE: Up bindings are currently converted to press bindings
// (see KeySet.cpp / DISALLOW_RELEASE_BINDINGS)
{ "Any+`", "drawinmap" },
{ "Up+Any+`", "drawinmap" },
{ "Any+\\", "drawinmap" },
{ "Up+Any+\\", "drawinmap" },
{ "Any+0xa7", "drawinmap" },
{ "Up+Any+0xa7", "drawinmap" },
{ "Any+up", "moveforward" },
{ "Up+Any+up", "moveforward" },
{ "Any+down", "moveback" },
{ "Up+Any+down", "moveback" },
{ "Any+right", "moveright" },
{ "Up+Any+right", "moveright" },
{ "Any+left", "moveleft" },
{ "Up+Any+left", "moveleft" },
{ "Any+pageup", "moveup" },
{ "Up+Any+pageup", "moveup" },
{ "Any+pagedown", "movedown" },
{ "Up+Any+pagedown", "movedown" },
{ "Any+ctrl", "moveslow" },
{ "Up+Any+ctrl", "moveslow" },
{ "Any+shift", "movefast" },
{ "Up+Any+shift", "movefast" }
};
/******************************************************************************/
//
// CKeyBindings::Action
//
CKeyBindings::Action::Action(const string& line)
{
rawline = line;
command = "";
extra = "";
vector<string> words = CSimpleParser::Tokenize(line, 1);
if (words.size() > 0) {
command = StringToLower(words[0]);
}
if (words.size() > 1) {
extra = words[1];
}
}
/******************************************************************************/
//
// CKeyBindings
//
CKeyBindings::CKeyBindings()
{
debug = 0;
fakeMetaKey = -1;
userCommand = true;
statefulCommands.insert("drawinmap");
statefulCommands.insert("moveforward");
statefulCommands.insert("moveback");
statefulCommands.insert("moveright");
statefulCommands.insert("moveleft");
statefulCommands.insert("moveup");
statefulCommands.insert("movedown");
statefulCommands.insert("moveslow");
statefulCommands.insert("movefast");
}
CKeyBindings::~CKeyBindings()
{
}
/******************************************************************************/
const CKeyBindings::ActionList&
CKeyBindings::GetActionList(const CKeySet& ks) const
{
static const ActionList empty;
const ActionList* alPtr = NULL;
if (ks.AnyMod()) {
KeyMap::const_iterator it = bindings.find(ks);
if (it == bindings.end()) {
alPtr = ∅
} else {
alPtr = &(it->second);
}
}
else {
// have to check for an AnyMod keyset as well as the normal one
CKeySet anyMod = ks;
anyMod.SetAnyBit();
KeyMap::const_iterator nit = bindings.find(ks);
KeyMap::const_iterator ait = bindings.find(anyMod);
const bool haveNormal = (nit != bindings.end());
const bool haveAnyMod = (ait != bindings.end());
if (!haveNormal && !haveAnyMod) {
alPtr = ∅
}
else if (haveNormal && !haveAnyMod) {
alPtr = &(nit->second);
}
else if (!haveNormal && haveAnyMod) {
alPtr = &(ait->second);
}
else {
// combine the two lists (normal first)
static ActionList merged;
merged = nit->second;
const ActionList& aal = ait->second;
for (int i = 0; i < (int)aal.size(); ++i) {
merged.push_back(aal[i]);
}
alPtr = &merged;
}
}
if (debug > 0) {
char buf[256];
SNPRINTF(buf, sizeof(buf), "GetAction: %s (0x%03X)",
ks.GetString(false).c_str(), ks.Key());
if (alPtr == &empty) {
strncat(buf, " EMPTY", sizeof(buf));
logOutput.Print("%s", buf);
}
else {
logOutput.Print("%s", buf);
const ActionList& al = *alPtr;
for (int i = 0; i < (int)al.size(); ++i) {
SNPRINTF(buf, sizeof(buf), " %s \"%s\"",
al[i].command.c_str(), al[i].rawline.c_str());
logOutput.Print("%s", buf);
}
}
}
return *alPtr;
}
const CKeyBindings::HotkeyList&
CKeyBindings::GetHotkeys(const string& action) const
{
ActionMap::const_iterator it = hotkeys.find(action);
if (it == hotkeys.end()) {
static HotkeyList empty;
return empty;
}
const HotkeyList& hl = it->second;
return hl;
}
/******************************************************************************/
bool CKeyBindings::Bind(const string& keystr, const string& line)
{
CKeySet ks;
if (!ParseKeySet(keystr, ks)) {
logOutput.Print("Bind: could not parse key: %s\n", keystr.c_str());
return false;
}
Action action(line);
action.boundWith = keystr;
if (action.command.empty()) {
logOutput.Print("Bind: empty action: %s\n", line.c_str());
return false;
}
// Try to be safe, force AnyMod mode for stateful commands
if (statefulCommands.find(action.command) != statefulCommands.end()) {
ks.SetAnyBit();
}
KeyMap::iterator it = bindings.find(ks);
if (it == bindings.end()) {
// new entry, push it
ActionList& al = bindings[ks];
al.push_back(action);
} else {
if (it->first != ks) {
// not a match, push it
ActionList& al = it->second;
al.push_back(action);
}
else {
// an exact keyset match, check the command
ActionList& al = it->second;
int i;
for (i = 0; i < (int)al.size(); i++) {
if (action.command == al[i].command) {
break;
}
}
if (i == (int)al.size()) {
// not a match, push it
al.push_back(action);
}
}
}
return true;
}
bool CKeyBindings::UnBind(const string& keystr, const string& command)
{
CKeySet ks;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?