OpenGothic
Open source reimplementation of Gothic I and II
Loading...
Searching...
No Matches
keycodec.cpp
Go to the documentation of this file.
1#include "keycodec.h"
2
3#include "gothic.h"
4#include <cstring>
5
6std::initializer_list<KeyCodec::K_Key> KeyCodec::keys = {
7 {Tempest::Event::K_A, 0x1e00},
8 {Tempest::Event::K_B, 0x3000},
9 {Tempest::Event::K_C, 0x2e00},
10 {Tempest::Event::K_D, 0x2000},
11 {Tempest::Event::K_E, 0x1200},
12 {Tempest::Event::K_F, 0x2100},
13 {Tempest::Event::K_G, 0x2200},
14 {Tempest::Event::K_H, 0x2300},
15 {Tempest::Event::K_I, 0x1700},
16 {Tempest::Event::K_J, 0x2400},
17 {Tempest::Event::K_K, 0x2500},
18 {Tempest::Event::K_L, 0x2600},
19 {Tempest::Event::K_M, 0x3200},
20 {Tempest::Event::K_N, 0x3100},
21 {Tempest::Event::K_O, 0x1800},
22 {Tempest::Event::K_P, 0x1900},
23 {Tempest::Event::K_Q, 0x1000},
24 {Tempest::Event::K_R, 0x1300},
25 {Tempest::Event::K_S, 0x1f00},
26 {Tempest::Event::K_T, 0x1400},
27 {Tempest::Event::K_U, 0x1600},
28 {Tempest::Event::K_V, 0x2f00},
29 {Tempest::Event::K_W, 0x1100},
30 {Tempest::Event::K_X, 0x2d00},
31 {Tempest::Event::K_Y, 0x1500},
32 {Tempest::Event::K_Z, 0x2c00},
33
34 {Tempest::Event::K_0, 0x8100},
35 {Tempest::Event::K_1, 0x7800},
36 {Tempest::Event::K_2, 0x7900},
37 {Tempest::Event::K_3, 0x7a00},
38 {Tempest::Event::K_4, 0x7b00},
39 {Tempest::Event::K_5, 0x7c00},
40 {Tempest::Event::K_6, 0x7d00},
41 {Tempest::Event::K_7, 0x7e00},
42 {Tempest::Event::K_8, 0x7f00},
43 {Tempest::Event::K_9, 0x8000},
44
45 {Tempest::Event::K_Up, 0xc800},
46 {Tempest::Event::K_Down, 0xd000},
47 {Tempest::Event::K_Left, 0xcb00},
48 {Tempest::Event::K_Right, 0xcd00},
49
50 {Tempest::Event::K_Back, 0x0e00},
51 {Tempest::Event::K_Tab, 0x0f00},
52 {Tempest::Event::K_Delete, 0xd300},
53 {Tempest::Event::K_Space, 0x3900},
54 {Tempest::Event::K_CapsLock, 0x3A00},
55
56 // Left
57 {Tempest::Event::K_LControl, 0x1d00},
58 {Tempest::Event::K_LShift, 0x2a00},
59 {Tempest::Event::K_LAlt, 0x3800},
60 {Tempest::Event::K_LCommand, 0x4800},
61 // Right
62 {Tempest::Event::K_RControl, 0x9d00},
63 {Tempest::Event::K_RShift, 0x3600},
64 {Tempest::Event::K_RAlt, 0xb800},
65 {Tempest::Event::K_RCommand, 0x4801},
66 };
67
68std::initializer_list<KeyCodec::M_Key> KeyCodec::mkeys = {
69 {Tempest::Event::ButtonLeft, 0x0c02},
70 {Tempest::Event::ButtonMid, 0x0e02},
71 {Tempest::Event::ButtonRight, 0x0d02},
72 {Tempest::Event::ButtonForward, 0x1002},
73 {Tempest::Event::ButtonBack, 0x0f02},
74 };
75
77 allKeys = {
78 &keyEnd,
79 &keyHeal,
80 &keyPotion,
81 &keyLockTarget,
82 &keyParade,
83 &keyActionRight,
84 &keyActionLeft,
85 &keyUp,
86 &keyDown,
87 &keyLeft,
88 &keyRight,
89 &keyStrafeLeft,
90 &keyStrafeRight,
91 &keyAction,
92 &keySlow,
93 &keySMove,
94 &keyWeapon,
95 &keySneak,
96 &keyLook,
97 &keyLookFP,
98 &keyInventory,
99 &keyShowStatus,
100 &keyShowLog,
101 &keyShowMap
102 };
103 Gothic::inst().onSettingsChanged.bind(this,&KeyCodec::setupSettings);
104 setupSettings();
105 }
106
107KeyCodec::Action KeyCodec::tr(Tempest::KeyEvent const& e) const {
108 int32_t code = keyToCode(e.key);
109 if(e.key==Tempest::KeyEvent::K_ESCAPE)
110 return Escape;
111 auto act = implTr(code).action;
112 if(act!=KeyCodec::Idle)
113 return act;
114 if(Tempest::Event::K_0<e.key && e.key<=Tempest::Event::K_9)
115 return Action(Weapon+int(e.key-Tempest::Event::K_0));
116 if(Tempest::Event::K_0==e.key)
117 return Action(Weapon+10);
118 if(e.key==Tempest::Event::K_F8)
119 return K_F8;
120 if(e.key == Tempest::Event::K_K)
121 return K_K;
122 if(e.key == Tempest::Event::K_O)
123 return K_O;
124 return Idle;
125 }
126
127KeyCodec::Action KeyCodec::tr(Tempest::MouseEvent const& e) const {
128 int32_t code = keyToCode(e.button);
129 auto act = implTr(code).action;
130 if(act!=KeyCodec::Idle)
131 return act;
132 return Idle;
133 }
134
135KeyCodec::Mapping KeyCodec::mapping(Tempest::KeyEvent const& e) const {
136 return implTr(keyToCode(e.key)).mapping;
137 }
138
139void KeyCodec::set(std::string_view sec, std::string_view opt, int32_t code) {
140 for(auto i:allKeys) {
141 const bool chg = i->is(code);
142 if(i->k[0]==code)
143 i->k[0] = 0;
144 if(i->k[1]==code)
145 i->k[1] = 0;
146 if(chg) {
147 std::string s;
148 for(auto r:i->k)
149 if(r!=0)
150 s += toCode(r);
151 Gothic::settingsSetS("KEYS",i->key,s);
152 }
153 }
154
155 auto val = std::string(Gothic::settingsGetS(sec, opt));
156 if(val.size()>4)
157 val = val.substr(val.size()-4,4);
158 val += toCode(code);
159 Gothic::settingsSetS(sec, opt, val);
160 }
161
162void KeyCodec::clear(std::string_view sec, std::string_view opt) {
163 Gothic::settingsSetS(sec, opt, "");
164 }
165
166void KeyCodec::setDefaultKeys(std::string_view preset) {
167 if(!Gothic::settingsHasSection(preset)) {
168 if(Gothic::inst().version().game==1) {
169 if(preset=="KEYSDEFAULT0")
170 setDefaultKeysG1(); else
171 setDefaultKeysG1Alt();
172 }
173 return;
174 }
175
176 for(auto i:allKeys) {
177 auto s = Gothic::settingsGetS(preset,i->key);
178 Gothic::settingsSetS("KEYS",i->key,s);
179 *i = setup(i->key);
180 }
181 }
182
183void KeyCodec::setDefaultKeysG1() {
184 for(auto i:allKeys)
185 Gothic::settingsSetS("KEYS",i->key,"");
186
187 Gothic::settingsSetS("KEYS", "keyShowMap", "3200");
188 Gothic::settingsSetS("KEYS", "keyEnd", "0100");
189 Gothic::settingsSetS("KEYS", "keyUp", "c800c700");
190 Gothic::settingsSetS("KEYS", "keyDown", "d000cf00");
191 Gothic::settingsSetS("KEYS", "keyLeft", "cb00d200");
192 Gothic::settingsSetS("KEYS", "keyRight", "cd00c900");
193 Gothic::settingsSetS("KEYS", "keyStrafeLeft", "d300");
194 Gothic::settingsSetS("KEYS", "keyStrafeRight", "d100");
195 Gothic::settingsSetS("KEYS", "keyAction", "1d00");
196 Gothic::settingsSetS("KEYS", "keySlow", "2a00");
197 Gothic::settingsSetS("KEYS", "keySMove", "3800b800");
198 Gothic::settingsSetS("KEYS", "keyWeapon", "3900");
199 Gothic::settingsSetS("KEYS", "keySneak", "1e003700");
200 Gothic::settingsSetS("KEYS", "keyLook", "52001300");
201 Gothic::settingsSetS("KEYS", "keyLookFP", "53002100");
202 Gothic::settingsSetS("KEYS", "keyInventory", "0f000e00");
203 Gothic::settingsSetS("KEYS", "keyShowStatus", "1f003000");
204 Gothic::settingsSetS("KEYS", "keyShowLog", "26003100");
205
206 for(auto i:allKeys) {
207 *i = setup(i->key);
208 }
209 }
210
211void KeyCodec::setDefaultKeysG1Alt() {
212 for(auto i:allKeys)
213 Gothic::settingsSetS("KEYS",i->key,"");
214
215 Gothic::settingsSetS("KEYS", "keyShowMap", "3200");
216 Gothic::settingsSetS("KEYS", "keyEnd", "0100");
217 Gothic::settingsSetS("KEYS", "keyUp", "c8001100");
218 Gothic::settingsSetS("KEYS", "keyDown", "d0001f00");
219 Gothic::settingsSetS("KEYS", "keyLeft", "cb001000");
220 Gothic::settingsSetS("KEYS", "keyRight", "cd001200");
221 Gothic::settingsSetS("KEYS", "keyStrafeLeft", "d3001e00");
222 Gothic::settingsSetS("KEYS", "keyStrafeRight", "d1002000");
223 Gothic::settingsSetS("KEYS", "keyAction", "1d00");
224 Gothic::settingsSetS("KEYS", "keySlow", "2a00");
225 Gothic::settingsSetS("KEYS", "keySMove", "3800b800");
226 Gothic::settingsSetS("KEYS", "keyWeapon", "3900");
227 Gothic::settingsSetS("KEYS", "keySneak", "2d003700");
228 Gothic::settingsSetS("KEYS", "keyLook", "52001300");
229 Gothic::settingsSetS("KEYS", "keyLookFP", "53002100");
230 Gothic::settingsSetS("KEYS", "keyInventory", "0f000e00");
231 Gothic::settingsSetS("KEYS", "keyShowStatus", "3000");
232 Gothic::settingsSetS("KEYS", "keyShowLog", "3100");
233
234 for(auto i:allKeys) {
235 *i = setup(i->key);
236 }
237 }
238
239std::string KeyCodec::toCode(int32_t code) {
240 char ret[5]={};
241 for(int i=0;i<4;++i) {
242 ret[3-i] = "0123456789abcdef"[code%16];
243 code/=16;
244 }
245 return ret;
246 }
247
248KeyCodec::ActionMapping KeyCodec::implTr(int32_t code) const {
249 if(auto m = keyEnd.mapping(code))
250 return { Idle, *m };
251 if(auto m = keyUp.mapping(code))
252 return { Forward, *m };
253 if(auto m = keyDown.mapping(code))
254 return { Back, *m };
255 if(auto m = keyLeft.mapping(code))
256 return { RotateL, *m };
257 if(auto m = keyRight.mapping(code))
258 return { RotateR, *m };
259 if(auto m = keyStrafeLeft.mapping(code))
260 return { Left, *m };
261 if(auto m = keyStrafeRight.mapping(code))
262 return { Right, *m };
263
264 if(auto m = keyAction.mapping(code))
265 return { ActionGeneric, *m };
266 if(auto m = keyActionLeft.mapping(code))
267 return { ActionLeft, *m };
268 if(auto m = keyActionRight.mapping(code))
269 return { ActionRight, *m };
270 if(auto m = keyParade.mapping(code))
271 return { Parade, *m };
272
273 if(auto m = keySlow.mapping(code))
274 return { Walk, *m };
275 if(auto m = keySMove.mapping(code))
276 return { Jump, *m };
277
278 if(auto m = keyWeapon.mapping(code))
279 return { Weapon, *m };
280 if(auto m = keySneak.mapping(code))
281 return { Sneak, *m };
282
283 if(auto m = keyLook.mapping(code))
284 return { LookBack, *m };
285 if(auto m = keyLookFP.mapping(code))
286 return { FirstPerson, *m };
287
288 if(auto m = keyInventory.mapping(code))
289 return { Inventory, *m };
290 if(auto m = keyShowStatus.mapping(code))
291 return { Status, *m };
292 if(auto m = keyShowLog.mapping(code))
293 return { Log, *m };
294 if(auto m = keyShowMap.mapping(code))
295 return { Map, *m };
296 if(auto m = keyHeal.mapping(code))
297 return { Heal, *m };
298 if(auto m = keyPotion.mapping(code))
299 return { Potion, *m };
300
301 // TODO: don't use "Primary" as a placeholder here.
302 return { Idle, Mapping::Primary };
303 }
304
305string_frm<64> KeyCodec::keysStr(std::string_view keys) {
306 int32_t k0 = fetch(keys,0,4);
307 int32_t k1 = fetch(keys,4,8);
308
309 if(k0==0 && k1==0)
310 return "";
311
312 auto k0Str = keyToStr(k0);
313 auto k1Str = keyToStr(k1);
314 if(k0Str.empty() || std::string_view(k0Str)==k1Str){
315 return k1Str;
316 }
317 if(k1Str.empty()){
318 return k0Str;
319 }
320
321 return string_frm<64>(k0Str,", ",k1Str);
322 }
323
324string_frm<64> KeyCodec::keyToStr(int32_t k) {
325 using namespace Tempest;
326
327 for(auto& i:keys)
328 if(k==i.code) {
329 return keyToStr(i.k);
330 }
331 for(auto& i:mkeys)
332 if(k==i.code) {
333 return keyToStr(i.k);
334 }
335 return "";
336 }
337
338string_frm<64> KeyCodec::keyToStr(Tempest::Event::KeyType k) {
339 if(Tempest::Event::K_0<=k && k<=Tempest::Event::K_9) {
340 auto c = char('0' + (k-Tempest::Event::K_0));
341 return string_frm<64>(c);
342 }
343 if(Tempest::Event::K_A<=k && k<=Tempest::Event::K_Z) {
344 auto c = char('A' + (k-Tempest::Event::K_A));
345 return string_frm<64>(c);
346 }
347
348 if(k==Tempest::Event::K_Up) {
349 return "CURSOR UP";
350 }
351 if(k==Tempest::Event::K_Down) {
352 return "CURSOR DOWN";
353 }
354 if(k==Tempest::Event::K_Left) {
355 return "CURSOR LEFT";
356 }
357 if(k==Tempest::Event::K_Right) {
358 return "CURSOR RIGHT";
359 }
360 if(k==Tempest::Event::K_Tab) {
361 return "TAB";
362 }
363 if(k==Tempest::Event::K_Back) {
364 return "BACKSPACE";
365 }
366 if(k==Tempest::Event::K_Space) {
367 return "SPACE";
368 }
369 if(k==Tempest::Event::K_LControl) {
370 return "LEFT CONTROL";
371 }
372 if(k==Tempest::Event::K_RControl) {
373 return "RIGHT CONTROL";
374 }
375 if(k==Tempest::Event::K_Delete) {
376 return "DELETE";
377 }
378 if(k==Tempest::Event::K_LShift) {
379 return "LEFT SHIFT";
380 }
381 if(k==Tempest::Event::K_RShift) {
382 return "RIGHT SHIFT";
383 }
384 if(k==Tempest::Event::K_CapsLock) {
385 return "CAPS LOCK";
386 }
387 if(k==Tempest::Event::K_LAlt) {
388 return "LEFT ALT";
389 }
390 if(k==Tempest::Event::K_RAlt) {
391 return "RIGHT ALT";
392 }
393 if(k==Tempest::Event::K_LCommand) {
394 return "LEFT COMMAND";
395 }
396 if(k==Tempest::Event::K_RCommand) {
397 return "RIGHT COMMAND";
398 }
399
400 return string_frm<64>('?');
401 }
402
403string_frm<64> KeyCodec::keyToStr(Tempest::Event::MouseButton k) {
404 if(k==Tempest::Event::ButtonLeft) {
405 return "MOUSE LEFT";
406 }
407 if(k==Tempest::Event::ButtonMid) {
408 return "MOUSE MID";
409 }
410 if(k==Tempest::Event::ButtonRight) {
411 return "MOUSE RIGHT";
412 }
413 if(k==Tempest::Event::ButtonForward) {
414 return "MOUSE X2";
415 }
416 if(k==Tempest::Event::ButtonBack) {
417 return "MOUSE X1";
418 }
419
420 return string_frm<64>('?');
421 }
422
423int32_t KeyCodec::keyToCode(Tempest::Event::KeyType t) {
424 for(auto& i:keys)
425 if(i.k==t)
426 return i.code;
427 return 0;
428 }
429
430int32_t KeyCodec::keyToCode(Tempest::Event::MouseButton t) {
431 for(auto& i:mkeys)
432 if(i.k==t)
433 return i.code;
434 return 0;
435 }
436
437void KeyCodec::setupSettings() {
438 keyEnd = setup("keyEnd");
439 keyHeal = setup("keyHeal");
440 keyPotion = setup("keyPotion");
441 keyLockTarget = setup("keyLockTarget");
442 keyParade = setup("keyParade");
443 keyActionRight = setup("keyActionRight");
444 keyActionLeft = setup("keyActionLeft");
445 keyUp = setup("keyUp");
446 keyDown = setup("keyDown");
447 keyLeft = setup("keyLeft");
448 keyRight = setup("keyRight");
449 keyStrafeLeft = setup("keyStrafeLeft");
450 keyStrafeRight = setup("keyStrafeRight");
451 keyAction = setup("keyAction");
452 keySlow = setup("keySlow");
453 keySMove = setup("keySMove");
454 keyWeapon = setup("keyWeapon");
455 keySneak = setup("keySneak");
456 keyLook = setup("keyLook");
457 keyLookFP = setup("keyLookFP");
458 keyInventory = setup("keyInventory");
459 keyShowStatus = setup("keyShowStatus");
460 keyShowLog = setup("keyShowLog");
461 keyShowMap = setup("keyShowMap");
462 }
463
464KeyCodec::KeyPair KeyCodec::setup(const char* kp) {
465 auto k = parse(Gothic::settingsGetS("KEYS",kp));
466 k.key = kp;
467 return k;
468 }
469
470KeyCodec::KeyPair KeyCodec::parse(std::string_view kp) {
471 KeyPair p;
472 p.k[0] = fetch(kp,0,4);
473 p.k[1] = fetch(kp,4,8);
474 return p;
475 }
476
477int KeyCodec::fetch(std::string_view keys, size_t s, size_t e) {
478 if(s<keys.size() && e<=keys.size() && s<e) {
479 int val=0;
480 for(size_t i=s;i<e;++i) {
481 char k = keys[i];
482 if('0'<=k && k<='9')
483 val = val*16+(k-'0'); else
484 if('a'<=k && k<='f')
485 val = val*16+(k-'a'+10); else
486 if('A'<=k && k<='F')
487 val = val*16+(k-'A'+10); else
488 return 0; //error
489 }
490 return val;
491 }
492 return 0;
493 }
Tempest::Signal< void()> onSettingsChanged
Definition gothic.h:182
static void settingsSetS(std::string_view sec, std::string_view name, std::string_view val)
Definition gothic.cpp:836
static Gothic & inst()
Definition gothic.cpp:249
static std::string_view settingsGetS(std::string_view sec, std::string_view name)
Definition gothic.cpp:824
static bool settingsHasSection(std::string_view sec)
Definition gothic.cpp:798
static auto keysStr(std::string_view keys) -> string_frm< 64 >
Definition keycodec.cpp:305
void set(std::string_view section, std::string_view key, int32_t code)
Definition keycodec.cpp:139
static int32_t keyToCode(Tempest::Event::KeyType t)
Definition keycodec.cpp:423
static std::string toCode(int32_t scan)
Definition keycodec.cpp:239
void setDefaultKeys(std::string_view preset)
Definition keycodec.cpp:166
void clear(std::string_view section, std::string_view key)
Definition keycodec.cpp:162
@ ActionLeft
Definition keycodec.h:46
@ ActionRight
Definition keycodec.h:47
@ RotateR
Definition keycodec.h:42
@ ActionGeneric
Definition keycodec.h:45
@ LookBack
Definition keycodec.h:34
@ FirstPerson
Definition keycodec.h:35
@ RotateL
Definition keycodec.h:41
@ Inventory
Definition keycodec.h:27
@ Forward
Definition keycodec.h:37
Mapping mapping(Tempest::KeyEvent const &e) const
Gets a mapping out of a key event.
Definition keycodec.cpp:135
Action tr(Tempest::KeyEvent const &e) const
Definition keycodec.cpp:107
Encapsulates an in-game action and a key mapping that caused it to be fired.
Definition keycodec.h:76