Mana
Loading...
Searching...
No Matches
keyboardconfig.cpp
Go to the documentation of this file.
1/*
2 * Custom keyboard shortcuts configuration
3 * Copyright (C) 2007 Joshua Langley <joshlangley@optusnet.com.au>
4 * Copyright (C) 2008-2009 The Mana Development Team
5 * Copyright (C) 2009-2012 The Mana Developers
6 *
7 * This file is part of The Mana Client.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include "configuration.h"
24#include "keyboardconfig.h"
25
26#include "gui/setup_keyboard.h"
27
28#include "utils/gettext.h"
29#include "utils/stringutils.h"
30
31struct KeyData
32{
33 const char *configField;
34 SDL_Keycode defaultValue;
35 std::string caption;
36};
37
38// keyData must be in same order as enum keyAction.
39static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = {
40 { "MoveUp", SDLK_UP, _("Move Up") },
41 { "MoveDown", SDLK_DOWN, _("Move Down") },
42 { "MoveLeft", SDLK_LEFT, _("Move Left") },
43 { "MoveRight", SDLK_RIGHT, _("Move Right") },
44 { "Attack", SDLK_LCTRL, _("Attack") },
45 { "TargetAttack", SDLK_x, _("Target & Attack") },
46 { "Smilie", SDLK_LALT, _("Smilie") },
47 { "Talk", SDLK_t, _("Talk") },
48 { "Target", SDLK_LSHIFT, _("Stop Attack") },
49 { "TargetClosest", SDLK_a, _("Target Monster") },
50 { "TargetNPC", SDLK_n, _("Target NPC") },
51 { "TargetPlayer", SDLK_q, _("Target Player") },
52 { "Pickup", SDLK_z, _("Pickup") },
53 { "HideWindows", SDLK_h, _("Hide Windows") },
54 { "BeingSit", SDLK_s, _("Sit") },
55 { "Screenshot", SDLK_p, _("Screenshot") },
56 { "Trade", SDLK_r, _("Enable/Disable Trading") },
57 { "Shortcut1", SDLK_1, strprintf(_("Item Shortcut %d"), 1) },
58 { "Shortcut2", SDLK_2, strprintf(_("Item Shortcut %d"), 2) },
59 { "Shortcut3", SDLK_3, strprintf(_("Item Shortcut %d"), 3) },
60 { "Shortcut4", SDLK_4, strprintf(_("Item Shortcut %d"), 4) },
61 { "Shortcut5", SDLK_5, strprintf(_("Item Shortcut %d"), 5) },
62 { "Shortcut6", SDLK_6, strprintf(_("Item Shortcut %d"), 6) },
63 { "Shortcut7", SDLK_7, strprintf(_("Item Shortcut %d"), 7) },
64 { "Shortcut8", SDLK_8, strprintf(_("Item Shortcut %d"), 8) },
65 { "Shortcut9", SDLK_9, strprintf(_("Item Shortcut %d"), 9) },
66 { "Shortcut10", SDLK_0, strprintf(_("Item Shortcut %d"), 10) },
67 { "Shortcut11", SDLK_MINUS, strprintf(_("Item Shortcut %d"), 11) },
68 { "Shortcut12", SDLK_EQUALS, strprintf(_("Item Shortcut %d"), 12) },
69 { "WindowHelp", SDLK_F1, _("Help Window") },
70 { "WindowStatus", SDLK_F2, _("Status Window") },
71 { "WindowInventory", SDLK_F3, _("Inventory Window") },
72 { "WindowEquipment", SDLK_F4, _("Equipment Window") },
73 { "WindowSkill", SDLK_F5, _("Skill Window") },
74 { "WindowQuests", KeyboardConfig::KEY_NO_VALUE, _("Quest Window") },
75 { "WindowMinimap", SDLK_F6, _("Minimap Window") },
76 { "WindowChat", SDLK_F7, _("Chat Window") },
77 { "WindowShortcut", SDLK_F8, _("Item Shortcut Window") },
78 { "WindowSetup", SDLK_F9, _("Setup Window") },
79 { "WindowDebug", SDLK_F10, _("Debug Window") },
80 { "WindowSocial", SDLK_F11, _("Social Window") },
81 { "WindowEmoteBar", SDLK_F12, _("Emote Shortcut Window") },
82 { "WindowOutfit", SDLK_o, _("Outfits Window") },
83 { "WearOutfit", SDLK_RCTRL, _("Wear Outfit") },
84 { "CopyOutfit", SDLK_RALT, _("Copy Outfit") },
85 { "EmoteShortcut1", SDLK_1, strprintf(_("Emote Shortcut %d"), 1) },
86 { "EmoteShortcut2", SDLK_2, strprintf(_("Emote Shortcut %d"), 2) },
87 { "EmoteShortcut3", SDLK_3, strprintf(_("Emote Shortcut %d"), 3) },
88 { "EmoteShortcut4", SDLK_4, strprintf(_("Emote Shortcut %d"), 4) },
89 { "EmoteShortcut5", SDLK_5, strprintf(_("Emote Shortcut %d"), 5) },
90 { "EmoteShortcut6", SDLK_6, strprintf(_("Emote Shortcut %d"), 6) },
91 { "EmoteShortcut7", SDLK_7, strprintf(_("Emote Shortcut %d"), 7) },
92 { "EmoteShortcut8", SDLK_8, strprintf(_("Emote Shortcut %d"), 8) },
93 { "EmoteShortcut9", SDLK_9, strprintf(_("Emote Shortcut %d"), 9) },
94 { "EmoteShortcut10", SDLK_0, strprintf(_("Emote Shortcut %d"), 10) },
95 { "EmoteShortcut11", SDLK_MINUS, strprintf(_("Emote Shortcut %d"), 11) },
96 { "EmoteShortcut12", SDLK_EQUALS, strprintf(_("Emote Shortcut %d"), 12) },
97 { "Chat", SDLK_RETURN, _("Toggle Chat") },
98 { "ChatScrollUp", SDLK_PAGEUP, _("Scroll Chat Up") },
99 { "ChatScrollDown", SDLK_PAGEDOWN, _("Scroll Chat Down") },
100 { "ChatPrevTab", SDLK_LEFTBRACKET, _("Previous Chat Tab") },
101 { "ChatNextTab", SDLK_RIGHTBRACKET, _("Next Chat Tab") },
102 { "OK", SDLK_SPACE, _("Select OK") },
103 { "Quit", SDLK_ESCAPE, _("Quit") },
104 { "IgnoreInput1", SDLK_LGUI, _("Ignore input 1") },
105 { "IgnoreInput2", SDLK_RGUI, _("Ignore input 2") }
106};
107
109{
110 for (int i = 0; i < KEY_TOTAL; i++)
111 {
112 mKey[i].configField = keyData[i].configField;
113 mKey[i].defaultValue = keyData[i].defaultValue;
115 }
117 mEnabled = true;
118
119 retrieve();
120}
121
123{
124 for (auto &key : mKey)
125 {
126 const auto keyIt = config.keys.find(key.configField);
127 if (keyIt != config.keys.end())
128 {
129 key.value = SDL_GetKeyFromName(keyIt->second.c_str());
130
131 if (key.value == SDLK_UNKNOWN)
132 key.value = KEY_NO_VALUE;
133 }
134 else
135 {
136 key.value = key.defaultValue;
137 }
138 }
139}
140
142{
143 config.keys.clear();
144
145 for (auto &key : mKey)
146 {
147 if (key.value == key.defaultValue)
148 continue;
149
150 config.keys[key.configField] = SDL_GetKeyName(key.value);
151 }
152}
153
155{
156 for (auto &key : mKey)
157 key.value = key.defaultValue;
158}
159
161{
166 for (int i = 0; i < KEY_TOTAL; i++)
167 {
168 if (mKey[i].value == KEY_NO_VALUE)
169 continue;
170
171 for (int j = i + 1; j < KEY_TOTAL; j++)
172 {
173 if (mKey[j].value == KEY_NO_VALUE)
174 continue;
175
176 // Allow collisions between shortcut and emote keys
177 if ((i >= KEY_SHORTCUT_1 && i <= KEY_SHORTCUT_12) &&
178 (j >= KEY_EMOTE_1 && j <= KEY_EMOTE_12))
179 continue;
180
181 // Why?
182 if (i == KEY_TOGGLE_CHAT && j == KEY_OK)
183 continue;
184
185 // Ignore keys can collide with anything.
186 if (j == KEY_IGNORE_INPUT_1 || j == KEY_IGNORE_INPUT_2)
187 continue;
188
189 // If the one of the keys is not set, then no conflict can happen.
190 if (mKey[i].value == -1 || mKey[j].value == -1)
191 continue;
192
193 // Finally test to see if a conflict DOES exist.
194 if (mKey[i].value == mKey[j].value)
195 {
196 mBindError = strprintf(_("Conflict \"%s\" and \"%s\" keys. "
197 "Resolve them, or gameplay may result"
198 " in strange behaviour."),
199 keyData[i].caption.c_str(), keyData[j].caption.c_str());
200 return true;
201 }
202 }
203 }
204 mBindError.clear();
205 return false;
206}
207
212
213const std::string &KeyboardConfig::getKeyCaption(int index) const
214{
215 return keyData[index].caption;
216}
217
218int KeyboardConfig::getKeyIndex(SDL_Keycode keyValue) const
219{
220 for (int i = 0; i < KEY_TOTAL; i++)
221 if (keyValue == mKey[i].value)
222 return i;
223
224 return KEY_NO_VALUE;
225}
226
227std::string_view KeyboardConfig::getKeyName(std::string_view configName) const
228{
229 for (auto key : mKey)
230 {
231 if (configName == key.configField)
232 {
233 if (key.value == KEY_NO_VALUE)
234 return {};
235 return SDL_GetKeyName(key.value);
236 }
237 }
238
239 return {};
240}
241
242int KeyboardConfig::getKeyEmoteOffset(SDL_Keycode keyValue) const
243{
244 for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_12; i++)
245 if (keyValue == mKey[i].value)
246 return i - KEY_EMOTE_1;
247
248 return -1;
249}
250
251bool KeyboardConfig::isKeyActive(int index) const
252{
253 if (!mActiveKeys)
254 return false;
255 int scanCode = SDL_GetScancodeFromKey(mKey[index].value);
256 return mActiveKeys[scanCode];
257}
258
260{
261 mActiveKeys = SDL_GetKeyboardState(nullptr);
262}
void store()
Store the key values to config file.
int mNewKeyIndex
Index of new key to be assigned.
void refreshActiveKeys()
Takes a snapshot of all the active keys.
int getKeyEmoteOffset(SDL_Keycode keyValue) const
Get the key function index for an emote by providing the offset value.
void callbackNewKey()
Calls a function back so the key re-assignment(s) can be seen.
void makeDefault()
Make the keys their default values.
int getKeyIndex(SDL_Keycode keyValue) const
Get the key function index by providing the keys value.
std::string mBindError
bool hasConflicts()
Determines if any key assignments are the same as each other.
bool mEnabled
Flag to respond to key input.
std::string_view getKeyName(std::string_view configName) const
Get the key name by providing the keys config name.
const uint8_t * mActiveKeys
Stores a list of all the keys.
void retrieve()
Retrieve the key values from config file.
bool isKeyActive(int index) const
Checks if the key is active, by providing the key function index.
void init()
Initializes the keyboard config explicitly.
KeyFunction mKey[KEY_TOTAL]
Pointer to all the key data.
const std::string & getKeyCaption(int index) const
Get the key caption, providing more meaning to the user.
Setup_Keyboard * mSetupKey
Reference to setup window.
void newKeyCallback(int index)
The callback function when a new key has been pressed.
Config config
Global settings (config.xml)
Definition client.cpp:97
#define _(s)
Definition gettext.h:38
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
std::map< std::string, std::string > keys
std::string caption
SDL_Keycode defaultValue
const char * configField
SDL_Keycode value
The actual value that is used.
int defaultValue
The default key value used.
const char * configField
Field index that is in the config file.