keybindings.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 816 行 · 第 1/2 页
CPP
816 行
if (!ParseKeySet(keystr, ks)) {
logOutput.Print("UnBind: could not parse key: %s\n", keystr.c_str());
return false;
}
bool success = false;
KeyMap::iterator it = bindings.find(ks);
if (it != bindings.end()) {
ActionList& al = it->second;
success = RemoveCommandFromList(al, command);
if (al.size() <= 0) {
bindings.erase(it);
}
}
return success;
}
bool CKeyBindings::UnBindKeyset(const string& keystr)
{
CKeySet ks;
if (!ParseKeySet(keystr, ks)) {
logOutput.Print("UnBindKeyset: could not parse key: %s\n", keystr.c_str());
return false;
}
bool success = false;
KeyMap::iterator it = bindings.find(ks);
if (it != bindings.end()) {
bindings.erase(it);
success = true;
}
return success;
}
bool CKeyBindings::UnBindAction(const string& command)
{
bool success = false;
KeyMap::iterator it = bindings.begin();
while (it != bindings.end()) {
ActionList& al = it->second;
if (RemoveCommandFromList(al, command)) {
success = true;
}
if (al.size() <= 0) {
KeyMap::iterator it_next = it;
it_next++;
bindings.erase(it);
it = it_next;
} else {
it++;
}
}
return success;
}
bool CKeyBindings::SetFakeMetaKey(const string& keystr)
{
CKeySet ks;
if (StringToLower(keystr) == "none") {
fakeMetaKey = -1;
return true;
}
if (!ks.Parse(keystr)) {
logOutput.Print("SetFakeMetaKey: could not parse key: %s\n", keystr.c_str());
return false;
}
fakeMetaKey = ks.Key();
return true;
}
bool CKeyBindings::AddKeySymbol(const string& keysym, const string& code)
{
CKeySet ks;
if (!ks.Parse(code)) {
logOutput.Print("AddKeySymbol: could not parse key: %s\n", code.c_str());
return false;
}
if (!keyCodes->AddKeySymbol(keysym, ks.Key())) {
logOutput.Print("AddKeySymbol: could not add: %s\n", keysym.c_str());
return false;
}
return true;
}
bool CKeyBindings::AddNamedKeySet(const string& name, const string& keystr)
{
CKeySet ks;
if (!ks.Parse(keystr)) {
logOutput.Print("AddNamedKeySet: could not parse keyset: %s\n", keystr.c_str());
return false;
}
if ((ks.Key() < 0) || !CKeyCodes::IsValidLabel(name)) {
logOutput.Print("AddNamedKeySet: bad custom keyset name: %s\n", name.c_str());
return false;
}
namedKeySets[name] = ks;
return true;
}
bool CKeyBindings::RemoveCommandFromList(ActionList& al, const string& command)
{
bool success = false;
for (int i = 0; i < (int)al.size(); ++i) {
if (al[i].command == command) {
success = true;
for (int j = (i + 1); j < (int)al.size(); ++j) {
al[j - 1] = al[j];
}
al.resize(al.size() - 1);
}
}
return success;
}
bool CKeyBindings::ParseKeySet(const string& keystr, CKeySet& ks) const
{
if (keystr[0] != NamedKeySetChar) {
return ks.Parse(keystr);
}
else {
const string keysetName = keystr.substr(1);
NamedKeySetMap::const_iterator it = namedKeySets.find(keysetName);
if (it != namedKeySets.end()) {
ks = it->second;
} else {
return false;
}
}
return true;
}
/******************************************************************************/
void CKeyBindings::LoadDefaults()
{
SetFakeMetaKey("space");
const int count = sizeof(defaultBindings) / sizeof(defaultBindings[0]);
for (int i = 0; i < count; ++i) {
Bind(defaultBindings[i].key, defaultBindings[i].action);
}
}
bool CKeyBindings::Command(const string& line)
{
const vector<string> words = CSimpleParser::Tokenize(line, 2);
if (words.size() <= 0) {
return false;
}
const string command = StringToLower(words[0]);
if (command == "keydebug") {
if (words.size() == 1) {
debug = (debug <= 0) ? 1 : 0;
} else if (words.size() >= 2) {
debug = atoi(words[1].c_str());
}
}
else if ((command == "fakemeta") && (words.size() > 1)) {
if (!SetFakeMetaKey(words[1])) { return false; }
}
else if ((command == "keyset") && (words.size() > 2)) {
if (!AddNamedKeySet(words[1], words[2])) { return false; }
}
else if ((command == "keysym") && (words.size() > 2)) {
if (!AddKeySymbol(words[1], words[2])) { return false; }
}
else if ((command == "bind") && (words.size() > 2)) {
if (!Bind(words[1], words[2])) { return false; }
}
else if ((command == "unbind") && (words.size() > 2)) {
if (!UnBind(words[1], words[2])) { return false; }
}
else if ((command == "unbindaction") && (words.size() > 1)) {
if (!UnBindAction(words[1])) { return false; }
}
else if ((command == "unbindkeyset") && (words.size() > 1)) {
if (!UnBindKeyset(words[1])) { return false; }
}
else if (command == "unbindall") {
bindings.clear();
keyCodes->Reset();
namedKeySets.clear();
typeBindings.clear();
Bind("enter", "chat"); // bare minimum
}
else {
return false;
}
if (userCommand) {
Sanitize();
}
return false;
}
bool CKeyBindings::Load(const string& filename)
{
// inComment = false;
CFileHandler ifs(filename);
CSimpleParser parser(ifs);
userCommand = false; // temporarily disable Sanitize() calls
LoadDefaults();
while (true) {
const string line = parser.GetCleanLine();
if (line.empty()) {
break;
}
if (!Command(line)) {
ParseTypeBind(parser, line);
}
}
Sanitize();
userCommand = true; // re-enable Sanitize() calls
return true;
}
bool CKeyBindings::ParseTypeBind(CSimpleParser& parser, const string& line)
{
BuildTypeBinding btb;
const vector<string> words = parser.Tokenize(line, 2);
if ((words.size() == 3) &&
(words[2] == "{") && (StringToLower(words[0]) == "bindbuildtype")) {
btb.keystr = words[1];
} else {
return false;
}
while (true) {
const string line = parser.GetCleanLine();
if (line.empty()) {
return false;
}
const vector<string> words = parser.Tokenize(line, 1);
if ((words.size() == 1) && (words[0] == "}")) {
break;
}
const string command = StringToLower(words[0]);
if ((command == "req") || (command == "require")) {
if (words.size() > 1) {
btb.reqs.push_back(words[1]);
}
}
else if (command == "sort") {
if (words.size() > 1) {
btb.sorts.push_back(words[1]);
}
}
else if (command == "chords") {
// split them up, tack them on (in order)
const vector<string> chords = parser.Tokenize(line, 0);
for (int i = 1; i < (int)chords.size(); i++) {
btb.chords.push_back(chords[i]);
}
}
}
typeBindings.push_back(btb);
CKeyAutoBinder autoBinder;
if (!autoBinder.BindBuildType(btb.keystr,
btb.reqs, btb.sorts, btb.chords)) {
return false;
}
return true;
}
void CKeyBindings::Sanitize()
{
// FIXME -- do something extra here?
// (seems as though removing the Up states fixed most of the problems)
BuildHotkeyMap();
}
void CKeyBindings::BuildHotkeyMap()
{
hotkeys.clear();
KeyMap::const_iterator kit;
for (kit = bindings.begin(); kit != bindings.end(); ++kit) {
const CKeySet ks = kit->first;
const string keystr = ks.GetString(true);
const ActionList& al = kit->second;
for (int i = 0; i < (int)al.size(); ++i) {
HotkeyList& hl = hotkeys[al[i].command];
int j;
for (j = 0; j < (int)hl.size(); ++j) {
if (hl[j] == keystr) {
break;
}
}
if (j == (int)hl.size()) {
hl.push_back(keystr);
}
}
}
}
/******************************************************************************/
void CKeyBindings::Print() const
{
FileSave(stdout);
}
bool CKeyBindings::Save(const string& filename) const
{
FILE* out = fopen(filename.c_str(), "wt");
if (out == NULL) {
return false;
}
const bool success = FileSave(out);
fclose(out);
return success;
}
bool CKeyBindings::FileSave(FILE* out) const
{
if (out == NULL) {
return false;
}
// clear the defaults
fprintf(out, "\n");
fprintf(out, "unbindall // clear the defaults\n");
fprintf(out, "unbind enter chat // clear the defaults\n");
fprintf(out, "\n");
// save the user defined key symbols
keyCodes->SaveUserKeySymbols(out);
// save the fake meta key (if it has been defined)
if (fakeMetaKey >= 0) {
fprintf(out, "fakemeta %s\n\n", keyCodes->GetName(fakeMetaKey).c_str());
}
// save the named keysets
NamedKeySetMap::const_iterator ks_it;
for (ks_it = namedKeySets.begin(); ks_it != namedKeySets.end(); ++ks_it) {
fprintf(out, "keyset %-15s %s\n",
ks_it->first.c_str(), ks_it->second.GetString(false).c_str());
}
if (!namedKeySets.empty()) {
fprintf(out, "\n");
}
// save the bindings
KeyMap::const_iterator it;
for (it = bindings.begin(); it != bindings.end(); ++it) {
const ActionList& al = it->second;
for (int i = 0; i < (int)al.size(); ++i) {
const Action& action = al[i];
string comment;
if (unitDefHandler && (action.command.find("buildunit_") == 0)) {
const string unitName = action.command.substr(10);
const UnitDef* unitDef = unitDefHandler->GetUnitByName(unitName);
if (unitDef) {
comment = " // " + unitDef->humanName + " :: " + unitDef->tooltip;
}
}
if (comment.empty()) {
fprintf(out, "bind %18s %s\n",
action.boundWith.c_str(),
action.rawline.c_str());
} else {
fprintf(out, "bind %18s %-20s%s\n",
action.boundWith.c_str(),
action.rawline.c_str(), comment.c_str());
}
}
}
return true;
}
/******************************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?