Refactor game controls bindings
This introduces abstractions for a game key (`wxGameKey`), a game control (`wxGameControl`) and a common global handler for in-game user input processing (`wxGameControlState`). User configuration is changed from a vector to a map of `wxGameControl` to a set of `wxUserInput`, which simplifies input configuration updates. User input processing for in-game controls is now unified between keyboard and joypad input, and is much faster in general since access to game control state is now always logarithmic rather than linear. This comes at the expense of slightly slower user input configuration updates. However, in the worst case scenario, this is still done in O(log(n)). This removes all uses of `wxJoyKeyBinding`. However, some uses of the key, mod, joy triplets remain and will be cleaned up in follow-up PRs. Issue: #745
This commit is contained in:
parent
3f2d3c139d
commit
51473a7c53
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-11-24 21:24+0000\n"
|
"POT-Creation-Date: 2022-07-23 17:25-0700\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -21,51 +21,51 @@ msgstr ""
|
||||||
msgid "visualboyadvance-m"
|
msgid "visualboyadvance-m"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:442
|
#: wxvbam.cpp:446
|
||||||
msgid "Could not create main window"
|
msgid "Could not create main window"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:513
|
#: wxvbam.cpp:517
|
||||||
msgid "Save built-in XRC file and exit"
|
msgid "Save built-in XRC file and exit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:516
|
#: wxvbam.cpp:520
|
||||||
msgid "Save built-in vba-over.ini and exit"
|
msgid "Save built-in vba-over.ini and exit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:519
|
#: wxvbam.cpp:523
|
||||||
msgid "Print configuration path and exit"
|
msgid "Print configuration path and exit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:522
|
#: wxvbam.cpp:526
|
||||||
msgid "Start in full-screen mode"
|
msgid "Start in full-screen mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:525
|
#: wxvbam.cpp:529
|
||||||
msgid "Set a configuration file"
|
msgid "Set a configuration file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:529
|
#: wxvbam.cpp:533
|
||||||
msgid "Delete shared link state first, if it exists"
|
msgid "Delete shared link state first, if it exists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:536
|
#: wxvbam.cpp:540
|
||||||
msgid "List all settable options and exit"
|
msgid "List all settable options and exit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:539
|
#: wxvbam.cpp:543
|
||||||
msgid "ROM file"
|
msgid "ROM file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:541
|
#: wxvbam.cpp:545
|
||||||
msgid "<config>=<value>"
|
msgid "<config>=<value>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:572
|
#: wxvbam.cpp:576
|
||||||
msgid "Configuration/build error: can't find built-in xrc"
|
msgid "Configuration/build error: can't find built-in xrc"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:580
|
#: wxvbam.cpp:584
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Wrote built-in configuration to %s.\n"
|
"Wrote built-in configuration to %s.\n"
|
||||||
|
@ -74,11 +74,11 @@ msgid ""
|
||||||
"built-in:"
|
"built-in:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:595
|
#: wxvbam.cpp:599
|
||||||
msgid "Configuration is read from, in order:"
|
msgid "Configuration is read from, in order:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:609
|
#: wxvbam.cpp:613
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Wrote built-in override file to %s\n"
|
"Wrote built-in override file to %s\n"
|
||||||
|
@ -86,13 +86,13 @@ msgid ""
|
||||||
"from search path:"
|
"from search path:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:615
|
#: wxvbam.cpp:619
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
"\tbuilt-in"
|
"\tbuilt-in"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:626
|
#: wxvbam.cpp:630
|
||||||
msgid ""
|
msgid ""
|
||||||
"Options set from the command line are saved if any configuration changes are "
|
"Options set from the command line are saved if any configuration changes are "
|
||||||
"made in the user interface.\n"
|
"made in the user interface.\n"
|
||||||
|
@ -101,155 +101,155 @@ msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:647
|
#: wxvbam.cpp:651
|
||||||
msgid ""
|
msgid ""
|
||||||
"The commands available for the Keyboard/* option are:\n"
|
"The commands available for the Keyboard/* option are:\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:659
|
#: wxvbam.cpp:663
|
||||||
msgid "Configuration file not found."
|
msgid "Configuration file not found."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: wxvbam.cpp:692
|
#: wxvbam.cpp:696
|
||||||
msgid "Bad configuration option or multiple ROM files given:\n"
|
msgid "Bad configuration option or multiple ROM files given:\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:80
|
#: guiinit.cpp:83
|
||||||
msgid "Start!"
|
msgid "Start!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:99 xrc/NetLink.xrc:99
|
#: guiinit.cpp:102 xrc/NetLink.xrc:99
|
||||||
msgid "Connect"
|
msgid "Connect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:116
|
#: guiinit.cpp:119
|
||||||
msgid "You must enter a valid host name"
|
msgid "You must enter a valid host name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:117
|
#: guiinit.cpp:120
|
||||||
msgid "Host name invalid"
|
msgid "Host name invalid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:135
|
|
||||||
msgid "Waiting for clients..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: guiinit.cpp:136
|
|
||||||
#, c-format
|
|
||||||
msgid "Server IP address is: %s\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: guiinit.cpp:138
|
#: guiinit.cpp:138
|
||||||
msgid "Waiting for connection..."
|
msgid "Waiting for clients..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:139
|
#: guiinit.cpp:139
|
||||||
#, c-format
|
#, c-format
|
||||||
|
msgid "Server IP address is: %s\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: guiinit.cpp:141
|
||||||
|
msgid "Waiting for connection..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: guiinit.cpp:142
|
||||||
|
#, c-format
|
||||||
msgid "Connecting to %s\n"
|
msgid "Connecting to %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:172
|
#: guiinit.cpp:175
|
||||||
msgid ""
|
msgid ""
|
||||||
"Error occurred.\n"
|
"Error occurred.\n"
|
||||||
"Please try again."
|
"Please try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:239 guiinit.cpp:292
|
#: guiinit.cpp:242 guiinit.cpp:295
|
||||||
msgid "Select cheat file"
|
msgid "Select cheat file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:240
|
#: guiinit.cpp:243
|
||||||
msgid "VBA cheat lists (*.clt)|*.clt|CHT cheat lists (*.cht)|*.cht"
|
msgid "VBA cheat lists (*.clt)|*.clt|CHT cheat lists (*.cht)|*.cht"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:259 panel.cpp:447
|
#: guiinit.cpp:262 panel.cpp:447
|
||||||
msgid "Loaded cheats"
|
msgid "Loaded cheats"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:293
|
#: guiinit.cpp:296
|
||||||
msgid "VBA cheat lists (*.clt)|*.clt"
|
msgid "VBA cheat lists (*.clt)|*.clt"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:311
|
#: guiinit.cpp:314
|
||||||
msgid "Saved cheats"
|
msgid "Saved cheats"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:342 guiinit.cpp:361
|
#: guiinit.cpp:345 guiinit.cpp:364
|
||||||
msgid "Restore old values?"
|
msgid "Restore old values?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:343 guiinit.cpp:362
|
#: guiinit.cpp:346 guiinit.cpp:365
|
||||||
msgid "Removing cheats"
|
msgid "Removing cheats"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:753 xrc/JoyPanel.xrc:364
|
#: guiinit.cpp:756 xrc/JoyPanel.xrc:364
|
||||||
msgid "GameShark"
|
msgid "GameShark"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:754 cmdevents.cpp:675
|
#: guiinit.cpp:757 cmdevents.cpp:675
|
||||||
msgid "GameGenie"
|
msgid "GameGenie"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:756
|
#: guiinit.cpp:759
|
||||||
msgid "Generic Code"
|
msgid "Generic Code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:757
|
#: guiinit.cpp:760
|
||||||
msgid "GameShark Advance"
|
msgid "GameShark Advance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:758
|
#: guiinit.cpp:761
|
||||||
msgid "CodeBreaker Advance"
|
msgid "CodeBreaker Advance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:759
|
#: guiinit.cpp:762
|
||||||
msgid "Flashcart CHT"
|
msgid "Flashcart CHT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:827 guiinit.cpp:1082
|
#: guiinit.cpp:830 guiinit.cpp:1085
|
||||||
msgid "Number cannot be empty"
|
msgid "Number cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:865
|
#: guiinit.cpp:868
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Search produced %d results. Please refine better"
|
msgid "Search produced %d results. Please refine better"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:877
|
#: guiinit.cpp:880
|
||||||
msgid "Search produced no results"
|
msgid "Search produced no results"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:1040
|
#: guiinit.cpp:1043
|
||||||
msgid "8-bit "
|
msgid "8-bit "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:1044
|
#: guiinit.cpp:1047
|
||||||
msgid "16-bit "
|
msgid "16-bit "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:1048
|
#: guiinit.cpp:1051
|
||||||
msgid "32-bit "
|
msgid "32-bit "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:1054
|
#: guiinit.cpp:1057
|
||||||
msgid "signed decimal"
|
msgid "signed decimal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:1058
|
#: guiinit.cpp:1061
|
||||||
msgid "unsigned decimal"
|
msgid "unsigned decimal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:1062
|
#: guiinit.cpp:1065
|
||||||
msgid "unsigned hexadecimal"
|
msgid "unsigned hexadecimal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:1540
|
#: guiinit.cpp:1543
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d frames = %.2f ms"
|
msgid "%d frames = %.2f ms"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:1552
|
#: guiinit.cpp:1555
|
||||||
msgid "Default device"
|
msgid "Default device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -294,62 +294,62 @@ msgstr ""
|
||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:2739
|
#: guiinit.cpp:2740
|
||||||
msgid "Main icon not found"
|
msgid "Main icon not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:2749
|
#: guiinit.cpp:2750
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:2763
|
#: guiinit.cpp:2764
|
||||||
msgid "Main display panel not found"
|
msgid "Main display panel not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:2928
|
#: guiinit.cpp:2929
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Duplicate menu accelerator: %s for %s and %s; keeping first"
|
msgid "Duplicate menu accelerator: %s for %s and %s; keeping first"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:2942
|
#: guiinit.cpp:2943
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Menu accelerator %s for %s overrides default for %s ; keeping menu"
|
msgid "Menu accelerator %s for %s overrides default for %s ; keeping menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:3081
|
#: guiinit.cpp:3082
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Invalid menu item %s; removing"
|
msgid "Invalid menu item %s; removing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:3289
|
#: guiinit.cpp:3290
|
||||||
msgid "Code"
|
msgid "Code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:3298
|
#: guiinit.cpp:3299
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:3372 xrc/CheatAdd.xrc:31
|
#: guiinit.cpp:3373 xrc/CheatAdd.xrc:31
|
||||||
msgid "Address"
|
msgid "Address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:3373
|
#: guiinit.cpp:3374
|
||||||
msgid "Old Value"
|
msgid "Old Value"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:3374
|
#: guiinit.cpp:3375
|
||||||
msgid "New Value"
|
msgid "New Value"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:3895
|
#: guiinit.cpp:3898
|
||||||
msgid "Menu commands"
|
msgid "Menu commands"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:3918
|
#: guiinit.cpp:3921
|
||||||
msgid "Other commands"
|
msgid "Other commands"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: guiinit.cpp:4029
|
#: guiinit.cpp:4032
|
||||||
msgid "JoyBus host invalid; disabling"
|
msgid "JoyBus host invalid; disabling"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -729,7 +729,7 @@ msgstr ""
|
||||||
msgid "Error saving snapshot file %s"
|
msgid "Error saving snapshot file %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cmdevents.cpp:1182 sys.cpp:449
|
#: cmdevents.cpp:1182 sys.cpp:450
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Wrote snapshot %s"
|
msgid "Wrote snapshot %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -855,102 +855,102 @@ msgstr ""
|
||||||
msgid "Network is not supported in local mode."
|
msgid "Network is not supported in local mode."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: opts.cpp:566 opts.cpp:869
|
#: opts.cpp:648 opts.cpp:950
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Invalid value %s for option %s; valid values are %s%s%s"
|
msgid "Invalid value %s for option %s; valid values are %s%s%s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: opts.cpp:583 opts.cpp:881
|
#: opts.cpp:665 opts.cpp:962
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Invalid value %d for option %s; valid values are %d - %d"
|
msgid "Invalid value %d for option %s; valid values are %d - %d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: opts.cpp:590 opts.cpp:599 opts.cpp:889 opts.cpp:897
|
#: opts.cpp:672 opts.cpp:681 opts.cpp:970 opts.cpp:978
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Invalid value %f for option %s; valid values are %f - %f"
|
msgid "Invalid value %f for option %s; valid values are %f - %f"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: opts.cpp:659 opts.cpp:680 opts.cpp:965 opts.cpp:991
|
#: opts.cpp:738 opts.cpp:759 opts.cpp:1046
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Invalid key binding %s for %s"
|
msgid "Invalid key binding %s for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: opts.cpp:852
|
#: opts.cpp:933
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Invalid flag option %s - %s ignored"
|
msgid "Invalid flag option %s - %s ignored"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:124 sys.cpp:180
|
#: sys.cpp:125 sys.cpp:181
|
||||||
msgid "No game in progress to record"
|
msgid "No game in progress to record"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:137
|
#: sys.cpp:138
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Cannot open output file %s"
|
msgid "Cannot open output file %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:144 sys.cpp:164 sys.cpp:310
|
#: sys.cpp:145 sys.cpp:165 sys.cpp:311
|
||||||
msgid "Error writing game recording"
|
msgid "Error writing game recording"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:185
|
#: sys.cpp:186
|
||||||
msgid "Cannot play game recording while recording"
|
msgid "Cannot play game recording while recording"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:198
|
#: sys.cpp:199
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Cannot open recording file %s"
|
msgid "Cannot open recording file %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:205 sys.cpp:215
|
#: sys.cpp:206 sys.cpp:216
|
||||||
msgid "Error reading game recording"
|
msgid "Error reading game recording"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:321
|
#: sys.cpp:322
|
||||||
msgid "Playback ended"
|
msgid "Playback ended"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:340
|
#: sys.cpp:341
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d%%(%d, %d fps)"
|
msgid "%d%%(%d, %d fps)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:348
|
#: sys.cpp:349
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d%%"
|
msgid "%d%%"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:767 xrc/GBPrinter.xrc:65
|
#: sys.cpp:769 xrc/GBPrinter.xrc:65
|
||||||
msgid "&Discard"
|
msgid "&Discard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:801
|
#: sys.cpp:803
|
||||||
msgid "Image files (*.bmp;*.jpg;*.png)|*.bmp;*.jpg;*.png|"
|
msgid "Image files (*.bmp;*.jpg;*.png)|*.bmp;*.jpg;*.png|"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:810
|
#: sys.cpp:812
|
||||||
msgid "Save printer image to"
|
msgid "Save printer image to"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:824 sys.cpp:1007
|
#: sys.cpp:826 sys.cpp:1009
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Wrote printer output to %s"
|
msgid "Wrote printer output to %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:829 sys.cpp:900
|
#: sys.cpp:831 sys.cpp:902
|
||||||
msgid "&Close"
|
msgid "&Close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:895
|
#: sys.cpp:897
|
||||||
msgid "Printed"
|
msgid "Printed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:1197
|
#: sys.cpp:1199
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error opening pseudo tty: %s"
|
msgid "Error opening pseudo tty: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: sys.cpp:1296
|
#: sys.cpp:1298
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error setting up server socket (%d)"
|
msgid "Error setting up server socket (%d)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1046,70 +1046,70 @@ msgstr ""
|
||||||
msgid "Error writing rewind state"
|
msgid "Error writing rewind state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2290
|
#: panel.cpp:2198
|
||||||
msgid "Failed to set glXSwapIntervalEXT"
|
msgid "Failed to set glXSwapIntervalEXT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2299
|
#: panel.cpp:2207
|
||||||
msgid "Failed to set glXSwapIntervalSGI"
|
msgid "Failed to set glXSwapIntervalSGI"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2308
|
#: panel.cpp:2216
|
||||||
msgid "Failed to set glXSwapIntervalMESA"
|
msgid "Failed to set glXSwapIntervalMESA"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2314
|
#: panel.cpp:2222
|
||||||
msgid "No support for wglGetExtensionsStringEXT"
|
msgid "No support for wglGetExtensionsStringEXT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2317
|
#: panel.cpp:2225
|
||||||
msgid "No support for WGL_EXT_swap_control"
|
msgid "No support for WGL_EXT_swap_control"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2326
|
#: panel.cpp:2234
|
||||||
msgid "Failed to set wglSwapIntervalEXT"
|
msgid "Failed to set wglSwapIntervalEXT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2332
|
#: panel.cpp:2240
|
||||||
msgid "No VSYNC available on this platform"
|
msgid "No VSYNC available on this platform"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2428
|
#: panel.cpp:2336
|
||||||
msgid "memory allocation error"
|
msgid "memory allocation error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2431
|
#: panel.cpp:2339
|
||||||
msgid "error initializing codec"
|
msgid "error initializing codec"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2434
|
#: panel.cpp:2342
|
||||||
msgid "error writing to output file"
|
msgid "error writing to output file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2437
|
#: panel.cpp:2345
|
||||||
msgid "can't guess output format from file name"
|
msgid "can't guess output format from file name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2442
|
#: panel.cpp:2350
|
||||||
msgid "programming error; aborting!"
|
msgid "programming error; aborting!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2454 panel.cpp:2483
|
#: panel.cpp:2362 panel.cpp:2391
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Unable to begin recording to %s (%s)"
|
msgid "Unable to begin recording to %s (%s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2511
|
#: panel.cpp:2419
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error in audio/video recording (%s); aborting"
|
msgid "Error in audio/video recording (%s); aborting"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2517
|
#: panel.cpp:2425
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error in audio recording (%s); aborting"
|
msgid "Error in audio recording (%s); aborting"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: panel.cpp:2527
|
#: panel.cpp:2435
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error in video recording (%s); aborting"
|
msgid "Error in video recording (%s); aborting"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1170,14 +1170,14 @@ msgstr ""
|
||||||
msgid "CONTROL"
|
msgid "CONTROL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: widgets/sdljoy.cpp:137
|
#: widgets/sdljoy.cpp:177
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Connected joystick %d: %s"
|
msgid "Connected %s: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: widgets/sdljoy.cpp:152
|
#: widgets/sdljoy.cpp:192
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Disconnected joystick %d"
|
msgid "Disconnected %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: xaudio2.cpp:34
|
#: xaudio2.cpp:34
|
||||||
|
|
|
@ -726,6 +726,7 @@ set(
|
||||||
wayland.cpp
|
wayland.cpp
|
||||||
strutils.cpp
|
strutils.cpp
|
||||||
wxutil.cpp
|
wxutil.cpp
|
||||||
|
widgets/gamecontrol.cpp
|
||||||
widgets/keyedit.cpp
|
widgets/keyedit.cpp
|
||||||
widgets/joyedit.cpp
|
widgets/joyedit.cpp
|
||||||
widgets/userinput.cpp
|
widgets/userinput.cpp
|
||||||
|
@ -759,6 +760,7 @@ set(
|
||||||
wxhead.h
|
wxhead.h
|
||||||
wayland.h
|
wayland.h
|
||||||
wxutil.h
|
wxutil.h
|
||||||
|
widgets/wx/gamecontrol.h
|
||||||
widgets/wx/keyedit.h
|
widgets/wx/keyedit.h
|
||||||
widgets/wx/joyedit.h
|
widgets/wx/joyedit.h
|
||||||
widgets/wx/sdljoy.h
|
widgets/wx/sdljoy.h
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#include <wx/txtstrm.h>
|
#include <wx/txtstrm.h>
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
|
|
||||||
|
#include "opts.h"
|
||||||
|
#include "wx/gamecontrol.h"
|
||||||
|
#include "wx/userinput.h"
|
||||||
#include "../gba/CheatSearch.h"
|
#include "../gba/CheatSearch.h"
|
||||||
|
|
||||||
#if defined(__WXGTK__)
|
#if defined(__WXGTK__)
|
||||||
|
@ -1667,32 +1670,29 @@ public:
|
||||||
bool clear = ev.GetId() == XRCID("Clear");
|
bool clear = ev.GetId() == XRCID("Clear");
|
||||||
|
|
||||||
// For the individual clear buttons, we assume their name is
|
// For the individual clear buttons, we assume their name is
|
||||||
// "Clear" + joynames[i]
|
// "Clear" + control_name
|
||||||
// ClearUp for Up; ClearR for R etc
|
// ClearUp for Up; ClearR for R etc
|
||||||
for (int i = 0; i < NUM_KEYS; ++i) {
|
for (const wxGameKey& game_key : kAllGameKeys) {
|
||||||
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*p, joynames[i], wxJoyKeyTextCtrl);
|
const wxString control_name = GameKeyToString(game_key);
|
||||||
wxString singleClearButton("Clear" + joynames[i]);
|
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*p, control_name, wxJoyKeyTextCtrl);
|
||||||
|
wxString singleClearButton("Clear" + control_name);
|
||||||
if (ev.GetId() == XRCID(singleClearButton.c_str())) {
|
if (ev.GetId() == XRCID(singleClearButton.c_str())) {
|
||||||
tc->SetValue(wxEmptyString);
|
tc->SetValue(wxEmptyString);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < NUM_KEYS; i++) {
|
for (const wxGameKey& game_key : kAllGameKeys) {
|
||||||
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*p, joynames[i], wxJoyKeyTextCtrl);
|
wxJoyKeyTextCtrl* tc =
|
||||||
|
XRCCTRL_D(*p, GameKeyToString(game_key), wxJoyKeyTextCtrl);
|
||||||
|
|
||||||
if (clear)
|
if (clear) {
|
||||||
tc->SetValue(wxEmptyString);
|
tc->SetValue(wxEmptyString);
|
||||||
else {
|
} else {
|
||||||
wxJoyKeyBinding_v a;
|
tc->SetValue(
|
||||||
|
wxUserInput::SpanToString(
|
||||||
if (defkeys_keyboard[i].key)
|
kDefaultBindings.find(
|
||||||
a.push_back(defkeys_keyboard[i]);
|
wxGameControl(0, game_key))->second));
|
||||||
|
|
||||||
for (auto bind : defkeys_joystick[i])
|
|
||||||
a.push_back(bind);
|
|
||||||
|
|
||||||
tc->SetValue(wxJoyKeyTextCtrl::ToString(a));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3835,9 +3835,10 @@ bool MainFrame::BindControls()
|
||||||
cb->SetValidator(wxBoolIntValidator(&gopts.default_stick, i + 1));
|
cb->SetValidator(wxBoolIntValidator(&gopts.default_stick, i + 1));
|
||||||
wxWindow *prev = NULL, *prevp = NULL;
|
wxWindow *prev = NULL, *prevp = NULL;
|
||||||
|
|
||||||
for (int j = 0; j < NUM_KEYS; j++) {
|
for (const wxGameKey& game_key : kAllGameKeys) {
|
||||||
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*w, joynames[j], wxJoyKeyTextCtrl);
|
const wxString control_name = GameKeyToString(game_key);
|
||||||
CheckThrowXRCError(tc, joynames[j]);
|
wxJoyKeyTextCtrl* tc = XRCCTRL_D(*w, control_name, wxJoyKeyTextCtrl);
|
||||||
|
CheckThrowXRCError(tc, control_name);
|
||||||
wxWindow* p = tc->GetParent();
|
wxWindow* p = tc->GetParent();
|
||||||
|
|
||||||
if (p == prevp)
|
if (p == prevp)
|
||||||
|
@ -3845,7 +3846,7 @@ bool MainFrame::BindControls()
|
||||||
|
|
||||||
prev = tc;
|
prev = tc;
|
||||||
prevp = p;
|
prevp = p;
|
||||||
tc->SetValidator(wxJoyKeyValidator(&gopts.joykey_bindings[i][j]));
|
tc->SetValidator(wxJoyKeyValidator(wxGameControl(i, game_key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
JoyPadConfigHandler[i].p = w;
|
JoyPadConfigHandler[i].p = w;
|
||||||
|
@ -3855,8 +3856,9 @@ bool MainFrame::BindControls()
|
||||||
w->Connect(XRCID("Clear"), wxEVT_COMMAND_BUTTON_CLICKED,
|
w->Connect(XRCID("Clear"), wxEVT_COMMAND_BUTTON_CLICKED,
|
||||||
wxCommandEventHandler(JoyPadConfig_t::JoypadConfigButtons),
|
wxCommandEventHandler(JoyPadConfig_t::JoypadConfigButtons),
|
||||||
NULL, &JoyPadConfigHandler[i]);
|
NULL, &JoyPadConfigHandler[i]);
|
||||||
for (int j = 0; j < NUM_KEYS; ++j) {
|
for (const wxGameKey& game_key : kAllGameKeys) {
|
||||||
w->Connect(XRCID(wxString("Clear" + joynames[j]).c_str()),
|
const wxString control_name = GameKeyToString(game_key);
|
||||||
|
w->Connect(XRCID(wxString("Clear" + control_name).c_str()),
|
||||||
wxEVT_COMMAND_BUTTON_CLICKED,
|
wxEVT_COMMAND_BUTTON_CLICKED,
|
||||||
wxCommandEventHandler(JoyPadConfig_t::JoypadConfigButtons),
|
wxCommandEventHandler(JoyPadConfig_t::JoypadConfigButtons),
|
||||||
NULL, &JoyPadConfigHandler[i]);
|
NULL, &JoyPadConfigHandler[i]);
|
||||||
|
|
279
src/wx/opts.cpp
279
src/wx/opts.cpp
|
@ -1,7 +1,11 @@
|
||||||
#include "wxvbam.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <wx/log.h>
|
||||||
#include <wx/display.h>
|
#include <wx/display.h>
|
||||||
|
|
||||||
|
#include "wx/gamecontrol.h"
|
||||||
|
#include "wx/userinput.h"
|
||||||
|
#include "wxvbam.h"
|
||||||
#include "strutils.h"
|
#include "strutils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -13,7 +17,7 @@
|
||||||
-p/--profile=hz
|
-p/--profile=hz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WJKB newWxJoyKeyBinding
|
#define WJKB wxUserInput::FromLegacyKeyModJoy
|
||||||
|
|
||||||
/* not sure how well other compilers support field-init syntax */
|
/* not sure how well other compilers support field-init syntax */
|
||||||
#define STROPT(c, n, d, v) \
|
#define STROPT(c, n, d, v) \
|
||||||
|
@ -131,40 +135,138 @@ const wxAcceleratorEntryUnicode default_accels[] = {
|
||||||
};
|
};
|
||||||
const int num_def_accels = sizeof(default_accels) / sizeof(default_accels[0]);
|
const int num_def_accels = sizeof(default_accels) / sizeof(default_accels[0]);
|
||||||
|
|
||||||
// Note: this must match GUI widget names or GUI won't work
|
const std::map<wxGameControl, std::set<wxUserInput>> kDefaultBindings = {
|
||||||
// This table's order determines tab order as well
|
{ wxGameControl(0, wxGameKey::Up), {
|
||||||
const wxString joynames[NUM_KEYS] = {
|
WJKB(wxT('W')),
|
||||||
wxT("Up"), wxT("Down"), wxT("Left"), wxT("Right"),
|
WJKB(11, WXJB_BUTTON, 1),
|
||||||
wxT("A"), wxT("B"), wxT("L"), wxT("R"),
|
WJKB(1, WXJB_AXIS_MINUS, 1),
|
||||||
wxT("Select"), wxT("Start"),
|
WJKB(3, WXJB_AXIS_MINUS, 1),
|
||||||
wxT("MotionUp"), wxT("MotionDown"), wxT("MotionLeft"), wxT("MotionRight"),
|
}},
|
||||||
wxT("MotionIn"), wxT("MotionOut"), wxT("AutoA"), wxT("AutoB"),
|
{ wxGameControl(0, wxGameKey::Down), {
|
||||||
wxT("Speed"), wxT("Capture"), wxT("GS")
|
WJKB(wxT('S')),
|
||||||
};
|
WJKB(12, WXJB_BUTTON, 1),
|
||||||
|
WJKB(1, WXJB_AXIS_PLUS, 1),
|
||||||
|
WJKB(3, WXJB_AXIS_PLUS, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::Left), {
|
||||||
|
WJKB(wxT('A')),
|
||||||
|
WJKB(13, WXJB_BUTTON, 1),
|
||||||
|
WJKB(0, WXJB_AXIS_MINUS, 1),
|
||||||
|
WJKB(2, WXJB_AXIS_MINUS, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::Right), {
|
||||||
|
WJKB(wxT('D')),
|
||||||
|
WJKB(14, WXJB_BUTTON, 1),
|
||||||
|
WJKB(0, WXJB_AXIS_PLUS, 1),
|
||||||
|
WJKB(2, WXJB_AXIS_PLUS, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::A), {
|
||||||
|
WJKB(wxT('L')),
|
||||||
|
WJKB(0, WXJB_BUTTON, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::B), {
|
||||||
|
WJKB(wxT('K')),
|
||||||
|
WJKB(1, WXJB_BUTTON, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::L), {
|
||||||
|
WJKB(wxT('I')),
|
||||||
|
WJKB(2, WXJB_BUTTON, 1),
|
||||||
|
WJKB(9, WXJB_BUTTON, 1),
|
||||||
|
WJKB(4, WXJB_AXIS_PLUS, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::R), {
|
||||||
|
WJKB(wxT('O')),
|
||||||
|
WJKB(3, WXJB_BUTTON, 1),
|
||||||
|
WJKB(10, WXJB_BUTTON, 1),
|
||||||
|
WJKB(5, WXJB_AXIS_PLUS, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::Select), {
|
||||||
|
WJKB(WXK_BACK),
|
||||||
|
WJKB(4, WXJB_BUTTON, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::Start), {
|
||||||
|
WJKB(WXK_RETURN),
|
||||||
|
WJKB(6, WXJB_BUTTON, 1),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::MotionUp), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::MotionDown), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::MotionLeft), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::MotionRight), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::MotionIn), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::MotionOut), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::AutoA), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::AutoB), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::Speed), {
|
||||||
|
WJKB(WXK_SPACE),
|
||||||
|
}},
|
||||||
|
{ wxGameControl(0, wxGameKey::Capture), {}},
|
||||||
|
{ wxGameControl(0, wxGameKey::Gameshark), {}},
|
||||||
|
|
||||||
wxJoyKeyBinding defkeys_keyboard[NUM_KEYS] = {
|
{ wxGameControl(1, wxGameKey::Up), {}},
|
||||||
WJKB(wxT('W')), WJKB(wxT('S')), WJKB(wxT('A')), WJKB(wxT('D')),
|
{ wxGameControl(1, wxGameKey::Down), {}},
|
||||||
WJKB(wxT('L')), WJKB(wxT('K')), WJKB(wxT('I')), WJKB(wxT('O')),
|
{ wxGameControl(1, wxGameKey::Left), {}},
|
||||||
WJKB(WXK_BACK), WJKB(WXK_RETURN),
|
{ wxGameControl(1, wxGameKey::Right), {}},
|
||||||
WJKB(0), WJKB(0), WJKB(0), WJKB(0),
|
{ wxGameControl(1, wxGameKey::A), {}},
|
||||||
WJKB(0), WJKB(0), WJKB(0), WJKB(0),
|
{ wxGameControl(1, wxGameKey::B), {}},
|
||||||
WJKB(WXK_SPACE), WJKB(0), WJKB(0)
|
{ wxGameControl(1, wxGameKey::L), {}},
|
||||||
};
|
{ wxGameControl(1, wxGameKey::R), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::Select), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::Start), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::MotionUp), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::MotionDown), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::MotionLeft), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::MotionRight), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::MotionIn), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::MotionOut), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::AutoA), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::AutoB), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::Speed), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::Capture), {}},
|
||||||
|
{ wxGameControl(1, wxGameKey::Gameshark), {}},
|
||||||
|
|
||||||
std::vector<std::vector<wxJoyKeyBinding>> defkeys_joystick = {
|
{ wxGameControl(2, wxGameKey::Up), {}},
|
||||||
{ WJKB(11, WXJB_BUTTON, 1), WJKB(1, WXJB_AXIS_MINUS, 1), WJKB(3, WXJB_AXIS_MINUS, 1) },
|
{ wxGameControl(2, wxGameKey::Down), {}},
|
||||||
{ WJKB(12, WXJB_BUTTON, 1), WJKB(1, WXJB_AXIS_PLUS, 1), WJKB(3, WXJB_AXIS_PLUS, 1) },
|
{ wxGameControl(2, wxGameKey::Left), {}},
|
||||||
{ WJKB(13, WXJB_BUTTON, 1), WJKB(0, WXJB_AXIS_MINUS, 1), WJKB(2, WXJB_AXIS_MINUS, 1) },
|
{ wxGameControl(2, wxGameKey::Right), {}},
|
||||||
{ WJKB(14, WXJB_BUTTON, 1), WJKB(0, WXJB_AXIS_PLUS, 1), WJKB(2, WXJB_AXIS_PLUS, 1) },
|
{ wxGameControl(2, wxGameKey::A), {}},
|
||||||
{ WJKB(0, WXJB_BUTTON, 1) },
|
{ wxGameControl(2, wxGameKey::B), {}},
|
||||||
{ WJKB(1, WXJB_BUTTON, 1) },
|
{ wxGameControl(2, wxGameKey::L), {}},
|
||||||
{ WJKB(2, WXJB_BUTTON, 1), WJKB( 9, WXJB_BUTTON, 1), WJKB(4, WXJB_AXIS_PLUS, 1) },
|
{ wxGameControl(2, wxGameKey::R), {}},
|
||||||
{ WJKB(3, WXJB_BUTTON, 1), WJKB(10, WXJB_BUTTON, 1), WJKB(5, WXJB_AXIS_PLUS, 1) },
|
{ wxGameControl(2, wxGameKey::Select), {}},
|
||||||
{ WJKB(4, WXJB_BUTTON, 1) },
|
{ wxGameControl(2, wxGameKey::Start), {}},
|
||||||
{ WJKB(6, WXJB_BUTTON, 1) },
|
{ wxGameControl(2, wxGameKey::MotionUp), {}},
|
||||||
{}, {}, {}, {},
|
{ wxGameControl(2, wxGameKey::MotionDown), {}},
|
||||||
{}, {}, {}, {},
|
{ wxGameControl(2, wxGameKey::MotionLeft), {}},
|
||||||
{}, {}, {}
|
{ wxGameControl(2, wxGameKey::MotionRight), {}},
|
||||||
|
{ wxGameControl(2, wxGameKey::MotionIn), {}},
|
||||||
|
{ wxGameControl(2, wxGameKey::MotionOut), {}},
|
||||||
|
{ wxGameControl(2, wxGameKey::AutoA), {}},
|
||||||
|
{ wxGameControl(2, wxGameKey::AutoB), {}},
|
||||||
|
{ wxGameControl(2, wxGameKey::Speed), {}},
|
||||||
|
{ wxGameControl(2, wxGameKey::Capture), {}},
|
||||||
|
{ wxGameControl(2, wxGameKey::Gameshark), {}},
|
||||||
|
|
||||||
|
{ wxGameControl(3, wxGameKey::Up), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::Down), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::Left), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::Right), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::A), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::B), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::L), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::R), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::Select), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::Start), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::MotionUp), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::MotionDown), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::MotionLeft), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::MotionRight), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::MotionIn), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::MotionOut), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::AutoA), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::AutoB), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::Speed), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::Capture), {}},
|
||||||
|
{ wxGameControl(3, wxGameKey::Gameshark), {}},
|
||||||
};
|
};
|
||||||
|
|
||||||
wxAcceleratorEntry_v sys_accels;
|
wxAcceleratorEntry_v sys_accels;
|
||||||
|
@ -385,19 +487,6 @@ bool opt_lt(const opt_desc& opt1, const opt_desc& opt2)
|
||||||
return wxStrcmp(opt1.opt, opt2.opt) < 0;
|
return wxStrcmp(opt1.opt, opt2.opt) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default input keys
|
|
||||||
void set_default_keys()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < NUM_KEYS; i++) {
|
|
||||||
gopts.joykey_bindings[0][i].clear();
|
|
||||||
|
|
||||||
if (defkeys_keyboard[i].key)
|
|
||||||
gopts.joykey_bindings[0][i].push_back(defkeys_keyboard[i]);
|
|
||||||
for (auto bind : defkeys_joystick[i])
|
|
||||||
gopts.joykey_bindings[0][i].push_back(bind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: simulate MakeInstanceFilename(vbam.ini) using subkeys (Slave%d/*)
|
// FIXME: simulate MakeInstanceFilename(vbam.ini) using subkeys (Slave%d/*)
|
||||||
void load_opts()
|
void load_opts()
|
||||||
{
|
{
|
||||||
|
@ -473,13 +562,7 @@ void load_opts()
|
||||||
|
|
||||||
for (cont = cfg->GetFirstEntry(e, key_idx); cont;
|
for (cont = cfg->GetFirstEntry(e, key_idx); cont;
|
||||||
cont = cfg->GetNextEntry(e, key_idx)) {
|
cont = cfg->GetNextEntry(e, key_idx)) {
|
||||||
int i;
|
if (!StringToGameKey(e)) {
|
||||||
|
|
||||||
for (i = 0; i < NUM_KEYS; i++)
|
|
||||||
if (e == joynames[i])
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (i == NUM_KEYS) {
|
|
||||||
s.append(e);
|
s.append(e);
|
||||||
//wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str());
|
//wxLogWarning(_("Invalid option %s present; removing if possible"), s.c_str());
|
||||||
item_del.push_back(s);
|
item_del.push_back(s);
|
||||||
|
@ -644,23 +727,20 @@ void load_opts()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize game control bindings to populate the configuration map.
|
||||||
|
gopts.game_control_bindings.insert(kDefaultBindings.begin(), kDefaultBindings.end());
|
||||||
|
|
||||||
// joypad is special
|
// joypad is special
|
||||||
set_default_keys();
|
for (auto& iter : gopts.game_control_bindings) {
|
||||||
for (int i = 0; i < 4; i++) {
|
const wxString optname = iter.first.ToString();
|
||||||
for (int j = 0; j < NUM_KEYS; j++) {
|
if (cfg->Read(optname, &s)) {
|
||||||
wxString optname;
|
iter.second = wxUserInput::FromString(s);
|
||||||
optname.Printf(wxT("Joypad/%d/%s"), i + 1, joynames[j].c_str());
|
if (!s.empty() && iter.second.empty()) {
|
||||||
bool gotit = cfg->Read(optname, &s);
|
|
||||||
|
|
||||||
if (gotit) {
|
|
||||||
gopts.joykey_bindings[i][j] = wxJoyKeyTextCtrl::FromString(s);
|
|
||||||
|
|
||||||
if (s.size() && !gopts.joykey_bindings[i][j].size())
|
|
||||||
wxLogWarning(_("Invalid key binding %s for %s"), s.c_str(), optname.c_str());
|
wxLogWarning(_("Invalid key binding %s for %s"), s.c_str(), optname.c_str());
|
||||||
} else {
|
|
||||||
s = wxJoyKeyTextCtrl::ToString(gopts.joykey_bindings[i][j]);
|
|
||||||
cfg->Write(optname, s);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
s = wxUserInput::SpanToString(iter.second);
|
||||||
|
cfg->Write(optname, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,21 +838,23 @@ void update_opts()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for joypad, use ToString comparisons. It may trigger changes
|
// For joypad, compare the wxUserInput sets. Since wxUserInput guarantees a
|
||||||
// even when there are none (e.g. multi-binding ordering changes)
|
// certain ordering, it is possible that the user control in the panel shows
|
||||||
// not worth worrying about
|
// a different ordering than the one that will be eventually saved, but this
|
||||||
for (int i = 0; i < 4; i++) {
|
// is nothing to worry about.
|
||||||
for (int j = 0; j < NUM_KEYS; j++) {
|
bool game_bindings_changed = false;
|
||||||
wxString s, o;
|
for (auto &iter : gopts.game_control_bindings) {
|
||||||
wxString optname;
|
wxString option_name = iter.first.ToString();
|
||||||
optname.Printf(wxT("Joypad/%d/%s"), i + 1, joynames[j].c_str());
|
std::set<wxUserInput> saved_config =
|
||||||
s = wxJoyKeyTextCtrl::ToString(gopts.joykey_bindings[i][j], wxT(','), true);
|
wxUserInput::FromString(cfg->Read(option_name, ""));
|
||||||
cfg->Read(optname, &o);
|
if (saved_config != iter.second) {
|
||||||
|
game_bindings_changed = true;
|
||||||
if (o != s)
|
cfg->Write(option_name, wxUserInput::SpanToString(iter.second));
|
||||||
cfg->Write(optname, s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (game_bindings_changed) {
|
||||||
|
wxGameControlState::Instance().OnGameBindingsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
// for keyboard, first remove any commands that aren't bound at all
|
// for keyboard, first remove any commands that aren't bound at all
|
||||||
if (cfg->HasGroup(wxT("/Keyboard"))) {
|
if (cfg->HasGroup(wxT("/Keyboard"))) {
|
||||||
|
@ -968,33 +1050,20 @@ bool opt_set(const wxString& name, const wxString& val)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (!wxStrncmp(name, wxT("Joypad"), wxStrlen(wxT("Joypad")))) {
|
|
||||||
if (parts[1] < wxT('1') || parts[1] > wxT('4') || parts.size() < 3)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int jno = parts[1][0] - wxT('1');
|
|
||||||
int kno;
|
|
||||||
|
|
||||||
for (kno = 0; kno < NUM_KEYS; kno++)
|
|
||||||
if (!wxStrcmp(joynames[kno], parts[2]))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (kno == NUM_KEYS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (val.empty())
|
|
||||||
gopts.joykey_bindings[jno][kno].clear();
|
|
||||||
else {
|
|
||||||
auto b = wxJoyKeyTextCtrl::FromString(val);
|
|
||||||
|
|
||||||
if (!b.size())
|
|
||||||
wxLogWarning(_("Invalid key binding %s for %s"), val.c_str(), name.c_str());
|
|
||||||
else
|
|
||||||
gopts.joykey_bindings[jno][kno] = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::optional<wxGameControl> game_control =
|
||||||
|
wxGameControl::FromString(name);
|
||||||
|
if (game_control) {
|
||||||
|
if (val.empty()) {
|
||||||
|
gopts.game_control_bindings[game_control.value()].clear();
|
||||||
|
} else {
|
||||||
|
gopts.game_control_bindings[game_control.value()] =
|
||||||
|
wxUserInput::FromString(val);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
#ifndef WX_OPTS_H
|
#ifndef WX_OPTS_H
|
||||||
#define WX_OPTS_H
|
#define WX_OPTS_H
|
||||||
|
|
||||||
#include <vector>
|
#include <map>
|
||||||
|
|
||||||
#define NUM_KEYS 21
|
#include <wx/string.h>
|
||||||
extern const wxString joynames[NUM_KEYS];
|
#include <wx/vidmode.h>
|
||||||
extern wxJoyKeyBinding defkeys_keyboard[NUM_KEYS]; // keyboard defaults
|
|
||||||
|
|
||||||
extern std::vector<std::vector<wxJoyKeyBinding>> defkeys_joystick; // joystick defaults
|
#include "wx/gamecontrol.h"
|
||||||
|
#include "wx/keyedit.h"
|
||||||
|
#include "wx/userinput.h"
|
||||||
|
|
||||||
|
// Forward declaration.
|
||||||
|
class wxFileHistory;
|
||||||
|
|
||||||
|
// Default joystick bindings.
|
||||||
|
extern const std::map<wxGameControl, std::set<wxUserInput>> kDefaultBindings;
|
||||||
|
|
||||||
extern struct opts_t {
|
extern struct opts_t {
|
||||||
opts_t();
|
opts_t();
|
||||||
|
@ -57,7 +64,7 @@ extern struct opts_t {
|
||||||
int statusbar;
|
int statusbar;
|
||||||
|
|
||||||
/// Joypad
|
/// Joypad
|
||||||
wxJoyKeyBinding_v joykey_bindings[4][NUM_KEYS];
|
std::map<wxGameControl, std::set<wxUserInput>> game_control_bindings;
|
||||||
int autofire_rate;
|
int autofire_rate;
|
||||||
int default_stick;
|
int default_stick;
|
||||||
|
|
||||||
|
@ -122,8 +129,6 @@ extern const int num_opts;
|
||||||
extern const wxAcceleratorEntryUnicode default_accels[];
|
extern const wxAcceleratorEntryUnicode default_accels[];
|
||||||
extern const int num_def_accels;
|
extern const int num_def_accels;
|
||||||
|
|
||||||
// call to setup default keys.
|
|
||||||
void set_default_keys();
|
|
||||||
// call to load config (once)
|
// call to load config (once)
|
||||||
// will write defaults for options not present and delete bad opts
|
// will write defaults for options not present and delete bad opts
|
||||||
// will also initialize opts[] array translations
|
// will also initialize opts[] array translations
|
||||||
|
|
115
src/wx/panel.cpp
115
src/wx/panel.cpp
|
@ -24,6 +24,7 @@
|
||||||
#include "drawing.h"
|
#include "drawing.h"
|
||||||
#include "filters.h"
|
#include "filters.h"
|
||||||
#include "wx/joyedit.h"
|
#include "wx/joyedit.h"
|
||||||
|
#include "wx/gamecontrol.h"
|
||||||
#include "wx/userinput.h"
|
#include "wx/userinput.h"
|
||||||
#include "wxvbam.h"
|
#include "wxvbam.h"
|
||||||
#include "wxutil.h"
|
#include "wxutil.h"
|
||||||
|
@ -34,9 +35,6 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// release all buttons currently pressed
|
|
||||||
static void clear_input_press();
|
|
||||||
|
|
||||||
int emulating;
|
int emulating;
|
||||||
|
|
||||||
IMPLEMENT_DYNAMIC_CLASS(GameArea, wxPanel)
|
IMPLEMENT_DYNAMIC_CLASS(GameArea, wxPanel)
|
||||||
|
@ -957,7 +955,7 @@ GameArea::~GameArea()
|
||||||
|
|
||||||
void GameArea::OnKillFocus(wxFocusEvent& ev)
|
void GameArea::OnKillFocus(wxFocusEvent& ev)
|
||||||
{
|
{
|
||||||
clear_input_press();
|
wxGameControlState::Instance().Reset();
|
||||||
ev.Skip();
|
ev.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,7 +975,7 @@ void GameArea::Pause()
|
||||||
// when the game is paused like this, we should not allow any
|
// when the game is paused like this, we should not allow any
|
||||||
// input to remain pressed, because they could be released
|
// input to remain pressed, because they could be released
|
||||||
// outside of the game zone and we would not know about it.
|
// outside of the game zone and we would not know about it.
|
||||||
clear_input_press();
|
wxGameControlState::Instance().Reset();
|
||||||
|
|
||||||
if (loaded != IMAGE_UNKNOWN)
|
if (loaded != IMAGE_UNKNOWN)
|
||||||
soundPause();
|
soundPause();
|
||||||
|
@ -1208,99 +1206,12 @@ void GameArea::OnIdle(wxIdleEvent& event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: keys will get stuck if they are released while window has no focus
|
|
||||||
// can't really do anything about it, except scan for pressed keys on
|
|
||||||
// activate events. Maybe later.
|
|
||||||
|
|
||||||
static uint32_t bmask[NUM_KEYS] = {
|
|
||||||
KEYM_UP, KEYM_DOWN, KEYM_LEFT, KEYM_RIGHT, KEYM_A, KEYM_B, KEYM_L, KEYM_R,
|
|
||||||
KEYM_SELECT, KEYM_START, KEYM_MOTION_UP, KEYM_MOTION_DOWN, KEYM_MOTION_LEFT,
|
|
||||||
KEYM_MOTION_RIGHT, KEYM_MOTION_IN, KEYM_MOTION_OUT, KEYM_AUTO_A, KEYM_AUTO_B, KEYM_SPEED, KEYM_CAPTURE,
|
|
||||||
KEYM_GS
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::set<wxUserInput> keys_pressed;
|
|
||||||
|
|
||||||
static void clear_input_press()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
joypress[i] = 0;
|
|
||||||
}
|
|
||||||
keys_pressed.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct game_key {
|
|
||||||
int player;
|
|
||||||
int key_num;
|
|
||||||
int bind_num;
|
|
||||||
wxJoyKeyBinding_v& b;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Populates |vec| with the game keys currently pressed.
|
|
||||||
static void game_keys_pressed(int key, int mod, int joy, std::vector<game_key>* vec)
|
|
||||||
{
|
|
||||||
for (int player = 0; player < 4; player++)
|
|
||||||
for (int key_num = 0; key_num < NUM_KEYS; key_num++) {
|
|
||||||
wxJoyKeyBinding_v& b = gopts.joykey_bindings[player][key_num];
|
|
||||||
|
|
||||||
for (size_t bind_num = 0; bind_num < b.size(); bind_num++)
|
|
||||||
if (b[bind_num].key == key && b[bind_num].mod == mod && b[bind_num].joy == joy)
|
|
||||||
vec->push_back({player, key_num, (int)bind_num, b});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool process_user_input(bool down, const wxUserInput& user_input)
|
static bool process_user_input(bool down, const wxUserInput& user_input)
|
||||||
{
|
{
|
||||||
int key = user_input.key();
|
|
||||||
int mod = user_input.mod();
|
|
||||||
int joy = user_input.joy();
|
|
||||||
|
|
||||||
std::vector<game_key> game_keys;
|
|
||||||
game_keys_pressed(key, mod, joy, &game_keys);
|
|
||||||
const bool is_game_key = !game_keys.empty();
|
|
||||||
|
|
||||||
// check if key is already pressed
|
|
||||||
auto iter = keys_pressed.find(user_input);
|
|
||||||
if (iter != keys_pressed.end()) {
|
|
||||||
// double press is noop
|
|
||||||
if (down)
|
if (down)
|
||||||
return is_game_key;
|
return wxGameControlState::Instance().OnInputPressed(user_input);
|
||||||
|
else
|
||||||
// if released, forget it
|
return wxGameControlState::Instance().OnInputReleased(user_input);
|
||||||
iter = keys_pressed.erase(iter);
|
|
||||||
} else {
|
|
||||||
// double release is noop
|
|
||||||
if (!down)
|
|
||||||
return is_game_key;
|
|
||||||
|
|
||||||
// otherwise remember it
|
|
||||||
keys_pressed.emplace(user_input);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto&& game_key : game_keys) {
|
|
||||||
if (down) {
|
|
||||||
// press button
|
|
||||||
joypress[game_key.player] |= bmask[game_key.key_num];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// only release if no others pressed
|
|
||||||
size_t bind2;
|
|
||||||
auto b = game_key.b;
|
|
||||||
|
|
||||||
for (bind2 = 0; bind2 < game_key.b.size(); bind2++) {
|
|
||||||
if ((size_t)game_key.bind_num == bind2 || (b[bind2].key == key && b[bind2].mod == mod && b[bind2].joy == joy))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (bind2 == b.size()) {
|
|
||||||
// release button
|
|
||||||
joypress[game_key.player] &= ~bmask[game_key.key_num];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_game_key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_black_background(wxWindow* win) {
|
static void draw_black_background(wxWindow* win) {
|
||||||
|
@ -1356,7 +1267,7 @@ static void process_keyboard_event(const wxKeyEvent& ev, bool down)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process_user_input(down, wxUserInput::FromLegacyJoyKeyBinding({key, mod, 0}))) {
|
if (process_user_input(down, wxUserInput::FromLegacyKeyModJoy(key, mod, 0))) {
|
||||||
wxWakeUpIdle();
|
wxWakeUpIdle();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1403,17 +1314,17 @@ void GameArea::OnSDLJoy(wxJoyEvent& ev)
|
||||||
// mutually exclusive key types unpress their opposite
|
// mutually exclusive key types unpress their opposite
|
||||||
// TODO: Move creation of these "ghost" events to wxJoyPoller.
|
// TODO: Move creation of these "ghost" events to wxJoyPoller.
|
||||||
if (mod == WXJB_AXIS_PLUS) {
|
if (mod == WXJB_AXIS_PLUS) {
|
||||||
process_user_input(false, wxUserInput::FromLegacyJoyKeyBinding({key, WXJB_AXIS_MINUS, joy}));
|
process_user_input(false, wxUserInput::FromLegacyKeyModJoy(key, WXJB_AXIS_MINUS, joy));
|
||||||
process_user_input(ev.control_value() != 0, wxUserInput::FromJoyEvent(ev));
|
process_user_input(ev.control_value() != 0, wxUserInput::FromJoyEvent(ev));
|
||||||
} else if (mod == WXJB_AXIS_MINUS) {
|
} else if (mod == WXJB_AXIS_MINUS) {
|
||||||
process_user_input(false, wxUserInput::FromLegacyJoyKeyBinding({key, WXJB_AXIS_PLUS, joy}));
|
process_user_input(false, wxUserInput::FromLegacyKeyModJoy(key, WXJB_AXIS_PLUS, joy));
|
||||||
process_user_input(ev.control_value() != 0, wxUserInput::FromJoyEvent(ev));
|
process_user_input(ev.control_value() != 0, wxUserInput::FromJoyEvent(ev));
|
||||||
} else if (mod >= WXJB_HAT_FIRST && mod <= WXJB_HAT_LAST) {
|
} else if (mod >= WXJB_HAT_FIRST && mod <= WXJB_HAT_LAST) {
|
||||||
int value = ev.control_value();
|
int value = ev.control_value();
|
||||||
process_user_input(value & SDL_HAT_UP, wxUserInput::FromLegacyJoyKeyBinding({key, WXJB_HAT_N, joy}));
|
process_user_input(value & SDL_HAT_UP, wxUserInput::FromLegacyKeyModJoy(key, WXJB_HAT_N, joy));
|
||||||
process_user_input(value & SDL_HAT_DOWN, wxUserInput::FromLegacyJoyKeyBinding({key, WXJB_HAT_S, joy}));
|
process_user_input(value & SDL_HAT_DOWN, wxUserInput::FromLegacyKeyModJoy(key, WXJB_HAT_S, joy));
|
||||||
process_user_input(value & SDL_HAT_RIGHT, wxUserInput::FromLegacyJoyKeyBinding({key, WXJB_HAT_E, joy}));
|
process_user_input(value & SDL_HAT_RIGHT, wxUserInput::FromLegacyKeyModJoy(key, WXJB_HAT_E, joy));
|
||||||
process_user_input(value & SDL_HAT_LEFT, wxUserInput::FromLegacyJoyKeyBinding({key, WXJB_HAT_W, joy}));
|
process_user_input(value & SDL_HAT_LEFT, wxUserInput::FromLegacyKeyModJoy(key, WXJB_HAT_W, joy));
|
||||||
} else {
|
} else {
|
||||||
process_user_input(ev.control_value() != 0, wxUserInput::FromJoyEvent(ev));
|
process_user_input(ev.control_value() != 0, wxUserInput::FromJoyEvent(ev));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "../common/SoundSDL.h"
|
#include "../common/SoundSDL.h"
|
||||||
|
#include "wx/gamecontrol.h"
|
||||||
#include "wxvbam.h"
|
#include "wxvbam.h"
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include <wx/ffile.h>
|
#include <wx/ffile.h>
|
||||||
|
@ -28,7 +29,7 @@ uint16_t systemGbPalette[24] = {
|
||||||
int RGB_LOW_BITS_MASK;
|
int RGB_LOW_BITS_MASK;
|
||||||
|
|
||||||
// these are local, though.
|
// these are local, though.
|
||||||
int joypress[4], autofire, autohold;
|
int autofire, autohold;
|
||||||
static int sensorx[4], sensory[4], sensorz[4];
|
static int sensorx[4], sensory[4], sensorz[4];
|
||||||
bool pause_next;
|
bool pause_next;
|
||||||
bool turbo;
|
bool turbo;
|
||||||
|
@ -251,7 +252,7 @@ uint32_t systemReadJoypad(int joy)
|
||||||
if (joy < 0 || joy > 3)
|
if (joy < 0 || joy > 3)
|
||||||
joy = gopts.default_stick - 1;
|
joy = gopts.default_stick - 1;
|
||||||
|
|
||||||
uint32_t ret = joypress[joy];
|
uint32_t ret = wxGameControlState::Instance().GetJoypad(joy);
|
||||||
|
|
||||||
if (turbo)
|
if (turbo)
|
||||||
ret |= KEYM_SPEED;
|
ret |= KEYM_SPEED;
|
||||||
|
@ -533,13 +534,14 @@ void systemUpdateSolarSensor()
|
||||||
void systemUpdateMotionSensor()
|
void systemUpdateMotionSensor()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
|
const uint32_t joy_value = wxGameControlState::Instance().GetJoypad(i);
|
||||||
if (!sensorx[i])
|
if (!sensorx[i])
|
||||||
sensorx[i] = 2047;
|
sensorx[i] = 2047;
|
||||||
|
|
||||||
if (!sensory[i])
|
if (!sensory[i])
|
||||||
sensory[i] = 2047;
|
sensory[i] = 2047;
|
||||||
|
|
||||||
if (joypress[i] & KEYM_MOTION_LEFT) {
|
if (joy_value & KEYM_MOTION_LEFT) {
|
||||||
sunBars--;
|
sunBars--;
|
||||||
|
|
||||||
if (sunBars < 1)
|
if (sunBars < 1)
|
||||||
|
@ -552,7 +554,7 @@ void systemUpdateMotionSensor()
|
||||||
|
|
||||||
if (sensorx[i] < 2047)
|
if (sensorx[i] < 2047)
|
||||||
sensorx[i] = 2057;
|
sensorx[i] = 2057;
|
||||||
} else if (joypress[i] & KEYM_MOTION_RIGHT) {
|
} else if (joy_value & KEYM_MOTION_RIGHT) {
|
||||||
sunBars++;
|
sunBars++;
|
||||||
|
|
||||||
if (sunBars > 100)
|
if (sunBars > 100)
|
||||||
|
@ -577,7 +579,7 @@ void systemUpdateMotionSensor()
|
||||||
sensorx[i] = 2047;
|
sensorx[i] = 2047;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joypress[i] & KEYM_MOTION_UP) {
|
if (joy_value & KEYM_MOTION_UP) {
|
||||||
sensory[i] += 3;
|
sensory[i] += 3;
|
||||||
|
|
||||||
if (sensory[i] > 2197)
|
if (sensory[i] > 2197)
|
||||||
|
@ -585,7 +587,7 @@ void systemUpdateMotionSensor()
|
||||||
|
|
||||||
if (sensory[i] < 2047)
|
if (sensory[i] < 2047)
|
||||||
sensory[i] = 2057;
|
sensory[i] = 2057;
|
||||||
} else if (joypress[i] & KEYM_MOTION_DOWN) {
|
} else if (joy_value & KEYM_MOTION_DOWN) {
|
||||||
sensory[i] -= 3;
|
sensory[i] -= 3;
|
||||||
|
|
||||||
if (sensory[i] < 1897)
|
if (sensory[i] < 1897)
|
||||||
|
@ -610,7 +612,7 @@ void systemUpdateMotionSensor()
|
||||||
const int highZ = 1800;
|
const int highZ = 1800;
|
||||||
const int accelZ = 3;
|
const int accelZ = 3;
|
||||||
|
|
||||||
if (joypress[i] & KEYM_MOTION_IN) {
|
if (joy_value & KEYM_MOTION_IN) {
|
||||||
sensorz[i] += accelZ;
|
sensorz[i] += accelZ;
|
||||||
|
|
||||||
if (sensorz[i] > highZ)
|
if (sensorz[i] > highZ)
|
||||||
|
@ -618,7 +620,7 @@ void systemUpdateMotionSensor()
|
||||||
|
|
||||||
if (sensorz[i] < centerZ)
|
if (sensorz[i] < centerZ)
|
||||||
sensorz[i] = centerZ + (accelZ * 300);
|
sensorz[i] = centerZ + (accelZ * 300);
|
||||||
} else if (joypress[i] & KEYM_MOTION_OUT) {
|
} else if (joy_value & KEYM_MOTION_OUT) {
|
||||||
sensorz[i] -= accelZ;
|
sensorz[i] -= accelZ;
|
||||||
|
|
||||||
if (sensorz[i] < lowZ)
|
if (sensorz[i] < lowZ)
|
||||||
|
|
|
@ -0,0 +1,291 @@
|
||||||
|
#include "wx/gamecontrol.h"
|
||||||
|
|
||||||
|
#include "../strutils.h"
|
||||||
|
#include "opts.h"
|
||||||
|
#include "wx/log.h"
|
||||||
|
#include "wxlogdebug.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr uint32_t kBitKeyA = (1 << 0);
|
||||||
|
constexpr uint32_t kBitKeyB = (1 << 1);
|
||||||
|
constexpr uint32_t kBitKeySelect = (1 << 2);
|
||||||
|
constexpr uint32_t kBitKeyStart = (1 << 3);
|
||||||
|
constexpr uint32_t kBitKeyRight = (1 << 4);
|
||||||
|
constexpr uint32_t kBitKeyLeft = (1 << 5);
|
||||||
|
constexpr uint32_t kBitKeyUp = (1 << 6);
|
||||||
|
constexpr uint32_t kBitKeyDown = (1 << 7);
|
||||||
|
constexpr uint32_t kBitKeyR = (1 << 8);
|
||||||
|
constexpr uint32_t kBitKeyL = (1 << 9);
|
||||||
|
constexpr uint32_t kBitKeySpeed = (1 << 10);
|
||||||
|
constexpr uint32_t kBitKeyCapture = (1 << 11);
|
||||||
|
constexpr uint32_t kBitKeyGameShark = (1 << 12);
|
||||||
|
constexpr uint32_t kBitKeyAutoA = (1 << 13);
|
||||||
|
constexpr uint32_t kBitKeyAutoB = (1 << 14);
|
||||||
|
constexpr uint32_t kBitKeyMotionUp = (1 << 15);
|
||||||
|
constexpr uint32_t kBitKeyMotionDown = (1 << 16);
|
||||||
|
constexpr uint32_t kBitKeyMotionLeft = (1 << 17);
|
||||||
|
constexpr uint32_t kBitKeyMotionRight = (1 << 18);
|
||||||
|
constexpr uint32_t kBitKeyMotionIn = (1 << 19);
|
||||||
|
constexpr uint32_t kBitKeyMotionOut = (1 << 20);
|
||||||
|
|
||||||
|
constexpr std::array<uint32_t, kNbGameKeys> kBitMask = {
|
||||||
|
kBitKeyUp,
|
||||||
|
kBitKeyDown,
|
||||||
|
kBitKeyLeft,
|
||||||
|
kBitKeyRight,
|
||||||
|
kBitKeyA,
|
||||||
|
kBitKeyB,
|
||||||
|
kBitKeyL,
|
||||||
|
kBitKeyR,
|
||||||
|
kBitKeySelect,
|
||||||
|
kBitKeyStart,
|
||||||
|
kBitKeyMotionUp,
|
||||||
|
kBitKeyMotionDown,
|
||||||
|
kBitKeyMotionLeft,
|
||||||
|
kBitKeyMotionRight,
|
||||||
|
kBitKeyMotionIn,
|
||||||
|
kBitKeyMotionOut,
|
||||||
|
kBitKeyAutoA,
|
||||||
|
kBitKeyAutoB,
|
||||||
|
kBitKeySpeed,
|
||||||
|
kBitKeyCapture,
|
||||||
|
kBitKeyGameShark,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline int GameKeyToInt(const wxGameKey& game_key) {
|
||||||
|
return static_cast<std::underlying_type<wxGameKey>::type>(
|
||||||
|
game_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if `joypad` is in a valid joypad range.
|
||||||
|
inline bool JoypadInRange(const int& joypad) {
|
||||||
|
constexpr int kMinJoypadIndex = 0;
|
||||||
|
return joypad >= kMinJoypadIndex && joypad < kNbJoypads;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
wxString GameKeyToString(const wxGameKey& game_key) {
|
||||||
|
// Note: this must match GUI widget names or GUI won't work
|
||||||
|
// This array's order determines tab order as well
|
||||||
|
static const std::array<wxString, kNbGameKeys> kGameKeyStrings = {
|
||||||
|
wxT("Up"),
|
||||||
|
wxT("Down"),
|
||||||
|
wxT("Left"),
|
||||||
|
wxT("Right"),
|
||||||
|
wxT("A"),
|
||||||
|
wxT("B"),
|
||||||
|
wxT("L"),
|
||||||
|
wxT("R"),
|
||||||
|
wxT("Select"),
|
||||||
|
wxT("Start"),
|
||||||
|
wxT("MotionUp"),
|
||||||
|
wxT("MotionDown"),
|
||||||
|
wxT("MotionLeft"),
|
||||||
|
wxT("MotionRight"),
|
||||||
|
wxT("MotionIn"),
|
||||||
|
wxT("MotionOut"),
|
||||||
|
wxT("AutoA"),
|
||||||
|
wxT("AutoB"),
|
||||||
|
wxT("Speed"),
|
||||||
|
wxT("Capture"),
|
||||||
|
wxT("GS"),
|
||||||
|
};
|
||||||
|
return kGameKeyStrings[GameKeyToInt(game_key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<wxGameKey> StringToGameKey(const wxString& input) {
|
||||||
|
static const std::map<wxString, wxGameKey> kStringToGameKey = {
|
||||||
|
{ wxT("Up"), wxGameKey::Up },
|
||||||
|
{ wxT("Down"), wxGameKey::Down },
|
||||||
|
{ wxT("Left"), wxGameKey::Left },
|
||||||
|
{ wxT("Right"), wxGameKey::Right },
|
||||||
|
{ wxT("A"), wxGameKey::A },
|
||||||
|
{ wxT("B"), wxGameKey::B },
|
||||||
|
{ wxT("L"), wxGameKey::L },
|
||||||
|
{ wxT("R"), wxGameKey::R },
|
||||||
|
{ wxT("Select"), wxGameKey::Select },
|
||||||
|
{ wxT("Start"), wxGameKey::Start },
|
||||||
|
{ wxT("MotionUp"), wxGameKey::MotionUp },
|
||||||
|
{ wxT("MotionDown"), wxGameKey::MotionDown },
|
||||||
|
{ wxT("MotionLeft"), wxGameKey::MotionLeft },
|
||||||
|
{ wxT("MotionRight"), wxGameKey::MotionRight },
|
||||||
|
{ wxT("MotionIn"), wxGameKey::MotionIn },
|
||||||
|
{ wxT("MotionOut"), wxGameKey::MotionOut },
|
||||||
|
{ wxT("AutoA"), wxGameKey::AutoA },
|
||||||
|
{ wxT("AutoB"), wxGameKey::AutoB },
|
||||||
|
{ wxT("Speed"), wxGameKey::Speed },
|
||||||
|
{ wxT("Capture"), wxGameKey::Capture },
|
||||||
|
{ wxT("GS"), wxGameKey::Gameshark },
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto iter = kStringToGameKey.find(input);
|
||||||
|
if (iter == kStringToGameKey.end()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::optional<wxGameControl> wxGameControl::FromString(const wxString &name) {
|
||||||
|
static const wxString kJoypad(wxT("Joypad"));
|
||||||
|
if (!wxStrncmp(name, kJoypad, kJoypad.size())) {
|
||||||
|
wxLogDebug("Doesn't start with joypad");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto parts = str_split(name, wxT("/"));
|
||||||
|
if (parts.size() != 3) {
|
||||||
|
wxLogDebug("Wrong split size: %d", parts.size());
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int joypad = parts[1][0] - wxT('1');
|
||||||
|
if (!JoypadInRange(joypad)) {
|
||||||
|
wxLogDebug("Wrong joypad index: %d", joypad);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<wxGameKey> game_key = StringToGameKey(parts[2]);
|
||||||
|
if (!game_key) {
|
||||||
|
wxLogDebug("Failed to parse game_key: %s", parts[2]);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxGameControl(joypad, game_key.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGameControl::wxGameControl(int joypad, wxGameKey game_key) :
|
||||||
|
joypad_(joypad),
|
||||||
|
game_key_(game_key),
|
||||||
|
config_string_(wxString::Format(
|
||||||
|
wxT("Joypad/%d/%s"), joypad_ + 1, GameKeyToString(game_key_))) {
|
||||||
|
assert(JoypadInRange(joypad_));
|
||||||
|
}
|
||||||
|
wxGameControl::~wxGameControl() = default;
|
||||||
|
|
||||||
|
bool wxGameControl::operator==(const wxGameControl& other) const {
|
||||||
|
return joypad_ == other.joypad_ && game_key_ == other.game_key_;
|
||||||
|
}
|
||||||
|
bool wxGameControl::operator!=(const wxGameControl& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
bool wxGameControl::operator<(const wxGameControl& other) const {
|
||||||
|
if (joypad_ != other.joypad_) {
|
||||||
|
return joypad_ < other.joypad_;
|
||||||
|
}
|
||||||
|
if (game_key_ != other.game_key_) {
|
||||||
|
return game_key_ < other.game_key_;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool wxGameControl::operator<=(const wxGameControl& other) const {
|
||||||
|
return !(*this > other);
|
||||||
|
}
|
||||||
|
bool wxGameControl::operator>(const wxGameControl& other) const {
|
||||||
|
return other < *this;
|
||||||
|
}
|
||||||
|
bool wxGameControl::operator>=(const wxGameControl& other) const {
|
||||||
|
return !(*this < other);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGameControlState& wxGameControlState::Instance() {
|
||||||
|
static wxGameControlState g_game_control_state;
|
||||||
|
return g_game_control_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGameControlState::wxGameControlState() : joypads_({0, 0, 0, 0}) {}
|
||||||
|
wxGameControlState::~wxGameControlState() = default;
|
||||||
|
|
||||||
|
bool wxGameControlState::OnInputPressed(const wxUserInput& user_input) {
|
||||||
|
assert(user_input);
|
||||||
|
|
||||||
|
const auto& game_keys = input_bindings_.find(user_input);
|
||||||
|
if (game_keys == input_bindings_.end()) {
|
||||||
|
// No associated game control for `user_input`.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = keys_pressed_.find(user_input);
|
||||||
|
if (iter != keys_pressed_.end()) {
|
||||||
|
// Double press is noop.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember the key pressed.
|
||||||
|
keys_pressed_.emplace(user_input);
|
||||||
|
|
||||||
|
// Update all corresponding controls.
|
||||||
|
for (const wxGameControl& game_control : game_keys->second) {
|
||||||
|
active_controls_[game_control].emplace(user_input);
|
||||||
|
joypads_[game_control.joypad_] |=
|
||||||
|
kBitMask[GameKeyToInt(game_control.game_key_)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxGameControlState::OnInputReleased(const wxUserInput& user_input) {
|
||||||
|
assert(user_input);
|
||||||
|
|
||||||
|
const auto& game_keys = input_bindings_.find(user_input);
|
||||||
|
if (game_keys == input_bindings_.end()) {
|
||||||
|
// No associated game control for `user_input`.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = keys_pressed_.find(user_input);
|
||||||
|
if (iter == keys_pressed_.end()) {
|
||||||
|
// Double release is noop.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the key pressed.
|
||||||
|
keys_pressed_.erase(iter);
|
||||||
|
|
||||||
|
// Update all corresponding controls.
|
||||||
|
for (const wxGameControl& game_control : game_keys->second) {
|
||||||
|
auto active_controls = active_controls_.find(game_control);
|
||||||
|
if (active_controls == active_controls_.end()) {
|
||||||
|
// This should never happen.
|
||||||
|
assert(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
active_controls->second.erase(user_input);
|
||||||
|
if (active_controls->second.empty()) {
|
||||||
|
// Actually release control.
|
||||||
|
active_controls_.erase(active_controls);
|
||||||
|
joypads_[game_control.joypad_] &=
|
||||||
|
~kBitMask[GameKeyToInt(game_control.game_key_)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGameControlState::Reset() {
|
||||||
|
active_controls_.clear();
|
||||||
|
keys_pressed_.clear();
|
||||||
|
joypads_.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGameControlState::OnGameBindingsChanged() {
|
||||||
|
// We should reset to ensure no key remains accidentally pressed following a
|
||||||
|
// configuration change.
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
input_bindings_.clear();
|
||||||
|
for (const auto& iter : gopts.game_control_bindings) {
|
||||||
|
for (const auto& user_input : iter.second) {
|
||||||
|
input_bindings_[user_input].emplace(iter.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t wxGameControlState::GetJoypad(int joypad) const {
|
||||||
|
assert(JoypadInRange(joypad));
|
||||||
|
return joypads_[joypad];
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <wx/tokenzr.h>
|
#include <wx/tokenzr.h>
|
||||||
|
|
||||||
|
#include "opts.h"
|
||||||
#include "strutils.h"
|
#include "strutils.h"
|
||||||
#include "wx/userinput.h"
|
#include "wx/userinput.h"
|
||||||
|
|
||||||
|
@ -13,13 +14,6 @@ BEGIN_EVENT_TABLE(wxJoyKeyTextCtrl, wxKeyTextCtrl)
|
||||||
EVT_SDLJOY(wxJoyKeyTextCtrl::OnJoy)
|
EVT_SDLJOY(wxJoyKeyTextCtrl::OnJoy)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
// Initializer for struct wxJoyKeyBinding
|
|
||||||
wxJoyKeyBinding newWxJoyKeyBinding(int key, int mod, int joy)
|
|
||||||
{
|
|
||||||
struct wxJoyKeyBinding tmp = {key, mod, joy};
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wxJoyKeyTextCtrl::DigitalButton(const wxJoyEvent& event)
|
int wxJoyKeyTextCtrl::DigitalButton(const wxJoyEvent& event)
|
||||||
{
|
{
|
||||||
int16_t sdlval = event.control_value();
|
int16_t sdlval = event.control_value();
|
||||||
|
@ -164,25 +158,6 @@ wxString wxJoyKeyTextCtrl::ToString(int mod, int key, int joy, bool isConfig)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString wxJoyKeyTextCtrl::ToString(wxJoyKeyBinding_v keys, wxChar sep, bool isConfig)
|
|
||||||
{
|
|
||||||
wxString ret;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < keys.size(); i++) {
|
|
||||||
if (i > 0)
|
|
||||||
ret += sep;
|
|
||||||
|
|
||||||
wxString key = ToString(keys[i].mod, keys[i].key, keys[i].joy, isConfig);
|
|
||||||
|
|
||||||
if (key.empty())
|
|
||||||
return wxEmptyString;
|
|
||||||
|
|
||||||
ret += key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString wxJoyKeyTextCtrl::FromAccelToString(wxAcceleratorEntry_v keys, wxChar sep, bool isConfig)
|
wxString wxJoyKeyTextCtrl::FromAccelToString(wxAcceleratorEntry_v keys, wxChar sep, bool isConfig)
|
||||||
{
|
{
|
||||||
wxString ret;
|
wxString ret;
|
||||||
|
@ -311,22 +286,6 @@ bool wxJoyKeyTextCtrl::FromString(const wxString& s, int& mod, int& key, int& jo
|
||||||
return ParseString(s, s.size(), mod, key, joy);
|
return ParseString(s, s.size(), mod, key, joy);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxJoyKeyBinding_v wxJoyKeyTextCtrl::FromString(const wxString& s, wxChar sep)
|
|
||||||
{
|
|
||||||
wxJoyKeyBinding_v ret, empty;
|
|
||||||
int mod, key, joy;
|
|
||||||
if (s.size() == 0)
|
|
||||||
return empty;
|
|
||||||
|
|
||||||
for (const auto& token : str_split_with_sep(s, sep)) {
|
|
||||||
if (!ParseString(token, token.size(), mod, key, joy))
|
|
||||||
return empty;
|
|
||||||
wxJoyKeyBinding jb = { key, mod, joy };
|
|
||||||
ret.insert(ret.begin(), jb);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxAcceleratorEntry_v wxJoyKeyTextCtrl::ToAccelFromString(const wxString& s, wxChar sep)
|
wxAcceleratorEntry_v wxJoyKeyTextCtrl::ToAccelFromString(const wxString& s, wxChar sep)
|
||||||
{
|
{
|
||||||
wxAcceleratorEntry_v ret, empty;
|
wxAcceleratorEntry_v ret, empty;
|
||||||
|
@ -346,28 +305,22 @@ IMPLEMENT_CLASS(wxJoyKeyValidator, wxValidator)
|
||||||
|
|
||||||
bool wxJoyKeyValidator::TransferToWindow()
|
bool wxJoyKeyValidator::TransferToWindow()
|
||||||
{
|
{
|
||||||
if (!val)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wxJoyKeyTextCtrl* jk = wxDynamicCast(GetWindow(), wxJoyKeyTextCtrl);
|
wxJoyKeyTextCtrl* jk = wxDynamicCast(GetWindow(), wxJoyKeyTextCtrl);
|
||||||
|
|
||||||
if (!jk)
|
if (!jk)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
jk->SetValue(wxJoyKeyTextCtrl::ToString(*val));
|
jk->SetValue(wxUserInput::SpanToString(gopts.game_control_bindings[val_]));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxJoyKeyValidator::TransferFromWindow()
|
bool wxJoyKeyValidator::TransferFromWindow()
|
||||||
{
|
{
|
||||||
if (!val)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wxJoyKeyTextCtrl* jk = wxDynamicCast(GetWindow(), wxJoyKeyTextCtrl);
|
wxJoyKeyTextCtrl* jk = wxDynamicCast(GetWindow(), wxJoyKeyTextCtrl);
|
||||||
|
|
||||||
if (!jk)
|
if (!jk)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*val = wxJoyKeyTextCtrl::FromString(jk->GetValue());
|
gopts.game_control_bindings[val_] = wxUserInput::FromString(jk->GetValue());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include "wx/userinput.h"
|
#include "wx/userinput.h"
|
||||||
|
|
||||||
|
#include "wx/joyedit.h"
|
||||||
|
#include "wx/sdljoy.h"
|
||||||
#include "wx/string.h"
|
#include "wx/string.h"
|
||||||
#include "wxutil.h"
|
#include "wxutil.h"
|
||||||
|
#include "../../wx/strutils.h"
|
||||||
|
|
||||||
// static
|
// static
|
||||||
wxUserInput wxUserInput::Invalid() {
|
wxUserInput wxUserInput::Invalid() {
|
||||||
|
@ -25,33 +28,47 @@ wxUserInput wxUserInput::FromJoyEvent(const wxJoyEvent& event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
wxUserInput wxUserInput::FromLegacyJoyKeyBinding(const wxJoyKeyBinding& binding) {
|
wxUserInput wxUserInput::FromLegacyKeyModJoy(int key, int mod, int joy) {
|
||||||
return wxUserInput(binding.joy == 0 ? Device::Keyboard : Device::Joystick,
|
return wxUserInput(joy == 0 ? Device::Keyboard : Device::Joystick,
|
||||||
binding.mod,
|
mod,
|
||||||
binding.key,
|
key,
|
||||||
binding.joy);
|
joy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
wxUserInput wxUserInput::FromString(const wxString& string) {
|
std::set<wxUserInput> wxUserInput::FromString(const wxString& string) {
|
||||||
// TODO: Move the implementation here once all callers have been updated.
|
std::set<wxUserInput> user_inputs;
|
||||||
int mod = 0;
|
|
||||||
int key = 0;
|
if (string.empty()) {
|
||||||
int joy = 0;
|
return user_inputs;
|
||||||
if (!wxJoyKeyTextCtrl::FromString(string, mod, key, joy)) {
|
|
||||||
return wxUserInput::Invalid();
|
|
||||||
}
|
|
||||||
return wxUserInput::FromLegacyJoyKeyBinding({key, mod, joy});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString wxUserInput::ToString() {
|
for (const auto& token : str_split_with_sep(string, wxT(","))) {
|
||||||
if (!config_string_.IsNull()) {
|
int mod, key, joy;
|
||||||
return config_string_;
|
if (!wxJoyKeyTextCtrl::ParseString(token, token.size(), mod, key, joy)) {
|
||||||
|
user_inputs.clear();
|
||||||
|
return user_inputs;
|
||||||
|
}
|
||||||
|
user_inputs.emplace(FromLegacyKeyModJoy(key, mod, joy));
|
||||||
|
}
|
||||||
|
return user_inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
wxString wxUserInput::SpanToString(const std::set<wxUserInput>& user_inputs, bool is_config) {
|
||||||
|
wxString config_string;
|
||||||
|
if (user_inputs.empty()) {
|
||||||
|
return config_string;
|
||||||
|
}
|
||||||
|
for (const wxUserInput& user_input : user_inputs) {
|
||||||
|
config_string += user_input.ToString(is_config) + wxT(',');
|
||||||
|
}
|
||||||
|
return config_string.SubString(0, config_string.size() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString wxUserInput::ToString(bool is_config) const {
|
||||||
// TODO: Move the implementation here once all callers have been updated.
|
// TODO: Move the implementation here once all callers have been updated.
|
||||||
config_string_ = wxJoyKeyTextCtrl::ToString(mod_, key_, joy_);
|
return wxJoyKeyTextCtrl::ToString(mod_, key_, joy_, is_config);
|
||||||
return config_string_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxUserInput::operator==(const wxUserInput& other) const {
|
bool wxUserInput::operator==(const wxUserInput& other) const {
|
||||||
|
@ -89,6 +106,7 @@ bool wxUserInput::operator>=(const wxUserInput& other) const {
|
||||||
// Actual underlying constructor.
|
// Actual underlying constructor.
|
||||||
wxUserInput::wxUserInput(Device device, int mod, uint8_t key, unsigned joy) :
|
wxUserInput::wxUserInput(Device device, int mod, uint8_t key, unsigned joy) :
|
||||||
device_(device),
|
device_(device),
|
||||||
|
joystick_(joy == 0 ? wxJoystick::Invalid() : wxJoystick::FromLegacyPlayerIndex(joy)),
|
||||||
mod_(mod),
|
mod_(mod),
|
||||||
key_(key),
|
key_(key),
|
||||||
joy_(joy) {}
|
joy_(joy) {}
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
#ifndef _WX_GAME_CONTROL_H_
|
||||||
|
#define _WX_GAME_CONTROL_H_
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
#include <set>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
#include "wx/userinput.h"
|
||||||
|
|
||||||
|
// Forward declaration.
|
||||||
|
class wxGameControlState;
|
||||||
|
|
||||||
|
// Represents an in-game input.
|
||||||
|
enum class wxGameKey {
|
||||||
|
Up = 0,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
L,
|
||||||
|
R,
|
||||||
|
Select,
|
||||||
|
Start,
|
||||||
|
MotionUp,
|
||||||
|
MotionDown,
|
||||||
|
MotionLeft,
|
||||||
|
MotionRight,
|
||||||
|
MotionIn,
|
||||||
|
MotionOut,
|
||||||
|
AutoA,
|
||||||
|
AutoB,
|
||||||
|
Speed,
|
||||||
|
Capture,
|
||||||
|
Gameshark,
|
||||||
|
Last = Gameshark
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr int kNbGameKeys =
|
||||||
|
static_cast<std::underlying_type<wxGameKey>::type>(wxGameKey::Last) + 1;
|
||||||
|
inline constexpr int kNbJoypads = 4;
|
||||||
|
|
||||||
|
inline constexpr std::array<wxGameKey, kNbGameKeys> kAllGameKeys = {
|
||||||
|
wxGameKey::Up,
|
||||||
|
wxGameKey::Down,
|
||||||
|
wxGameKey::Left,
|
||||||
|
wxGameKey::Right,
|
||||||
|
wxGameKey::A,
|
||||||
|
wxGameKey::B,
|
||||||
|
wxGameKey::L,
|
||||||
|
wxGameKey::R,
|
||||||
|
wxGameKey::Select,
|
||||||
|
wxGameKey::Start,
|
||||||
|
wxGameKey::MotionUp,
|
||||||
|
wxGameKey::MotionDown,
|
||||||
|
wxGameKey::MotionLeft,
|
||||||
|
wxGameKey::MotionRight,
|
||||||
|
wxGameKey::MotionIn,
|
||||||
|
wxGameKey::MotionOut,
|
||||||
|
wxGameKey::AutoA,
|
||||||
|
wxGameKey::AutoB,
|
||||||
|
wxGameKey::Speed,
|
||||||
|
wxGameKey::Capture,
|
||||||
|
wxGameKey::Gameshark,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Conversion utility method. Returns empty string on failure.
|
||||||
|
// This is O(1).
|
||||||
|
wxString GameKeyToString(const wxGameKey& game_key);
|
||||||
|
|
||||||
|
// Conversion utility method. Returns std::nullopt on failure.
|
||||||
|
// This is O(log(kNbGameKeys)).
|
||||||
|
std::optional<wxGameKey> StringToGameKey(const wxString& input);
|
||||||
|
|
||||||
|
// Abstraction for an in-game control, wich is made of a player index (from 0
|
||||||
|
// to 3), and a wxGameKey.
|
||||||
|
class wxGameControl {
|
||||||
|
public:
|
||||||
|
// Converts a string to a wxGameControl. Returns std::nullopt on failure.
|
||||||
|
static std::optional<wxGameControl> FromString(const wxString& name);
|
||||||
|
|
||||||
|
wxGameControl(int joypad, wxGameKey game_key);
|
||||||
|
~wxGameControl();
|
||||||
|
|
||||||
|
wxString ToString() const { return config_string_; };
|
||||||
|
|
||||||
|
bool operator==(const wxGameControl& other) const;
|
||||||
|
bool operator!=(const wxGameControl& other) const;
|
||||||
|
bool operator<(const wxGameControl& other) const;
|
||||||
|
bool operator<=(const wxGameControl& other) const;
|
||||||
|
bool operator>(const wxGameControl& other) const;
|
||||||
|
bool operator>=(const wxGameControl& other) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int joypad_;
|
||||||
|
const wxGameKey game_key_;
|
||||||
|
const wxString config_string_;
|
||||||
|
|
||||||
|
friend class wxGameControlState;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tracks in-game input and computes the joypad value used to send control input
|
||||||
|
// data to the emulator.
|
||||||
|
class wxGameControlState {
|
||||||
|
public:
|
||||||
|
// This is a global singleton.
|
||||||
|
static wxGameControlState& Instance();
|
||||||
|
|
||||||
|
// Disable copy constructor and assignment operator.
|
||||||
|
wxGameControlState(const wxGameControlState&) = delete;
|
||||||
|
wxGameControlState& operator=(const wxGameControlState&) = delete;
|
||||||
|
|
||||||
|
// Processes `user_input` and updates the internal tracking state.
|
||||||
|
// Returns true if `user_input` corresponds to a game input.
|
||||||
|
bool OnInputPressed(const wxUserInput& user_input);
|
||||||
|
bool OnInputReleased(const wxUserInput& user_input);
|
||||||
|
|
||||||
|
// Clears all input.
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
// Recomputes internal bindinds. This is a potentially slow operation and
|
||||||
|
// should only be called when the game input configuration has been changed.
|
||||||
|
void OnGameBindingsChanged();
|
||||||
|
|
||||||
|
uint32_t GetJoypad(int joypad) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxGameControlState();
|
||||||
|
~wxGameControlState();
|
||||||
|
|
||||||
|
std::map<wxUserInput, std::set<wxGameControl>> input_bindings_;
|
||||||
|
std::map<wxGameControl, std::set<wxUserInput>> active_controls_;
|
||||||
|
std::set<wxUserInput> keys_pressed_;
|
||||||
|
std::array<uint32_t, kNbJoypads> joypads_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _WX_GAME_CONTROL_H_
|
|
@ -5,20 +5,10 @@
|
||||||
// The value is the symbolic name of the key pressed
|
// The value is the symbolic name of the key pressed
|
||||||
// Supports manual clearing (bs), multiple keys in widget, automatic tab on key
|
// Supports manual clearing (bs), multiple keys in widget, automatic tab on key
|
||||||
|
|
||||||
|
#include "wx/gamecontrol.h"
|
||||||
#include "wx/keyedit.h"
|
#include "wx/keyedit.h"
|
||||||
#include "wx/sdljoy.h"
|
#include "wx/sdljoy.h"
|
||||||
|
#include "wx/userinput.h"
|
||||||
typedef struct wxJoyKeyBinding {
|
|
||||||
int key; // key code; listed first for easy static init
|
|
||||||
int mod; // modifier flags
|
|
||||||
int joy; // joystick # (starting at 1)
|
|
||||||
// if joy is non-0, key = control number, and mod = control type
|
|
||||||
} wxJoyKeyBinding;
|
|
||||||
|
|
||||||
// Initializer for struct wxJoyKeyBinding
|
|
||||||
wxJoyKeyBinding newWxJoyKeyBinding(int key = 0, int mod = 0, int joy = 0);
|
|
||||||
|
|
||||||
typedef std::vector<wxJoyKeyBinding> wxJoyKeyBinding_v;
|
|
||||||
|
|
||||||
// joystick control types
|
// joystick control types
|
||||||
// mod for joysticks
|
// mod for joysticks
|
||||||
|
@ -52,13 +42,8 @@ public:
|
||||||
static int DigitalButton(const wxJoyEvent& event);
|
static int DigitalButton(const wxJoyEvent& event);
|
||||||
// convert mod+key to accel string, separated by -
|
// convert mod+key to accel string, separated by -
|
||||||
static wxString ToString(int mod, int key, int joy, bool isConfig = false);
|
static wxString ToString(int mod, int key, int joy, bool isConfig = false);
|
||||||
// convert multiple keys, separated by multikey
|
|
||||||
static wxString ToString(wxJoyKeyBinding_v keys, wxChar sep = wxT(','), bool isConfig = false);
|
|
||||||
// parses single key string into mod+key
|
// parses single key string into mod+key
|
||||||
static bool FromString(const wxString& s, int& mod, int& key, int& joy);
|
static bool FromString(const wxString& s, int& mod, int& key, int& joy);
|
||||||
// parse multi-key string into array
|
|
||||||
// returns empty array on parse errors
|
|
||||||
static wxJoyKeyBinding_v FromString(const wxString& s, wxChar sep = wxT(','));
|
|
||||||
// parse a single key in given wxChar array up to given len
|
// parse a single key in given wxChar array up to given len
|
||||||
static bool ParseString(const wxString& s, int len, int& mod, int& key, int& joy);
|
static bool ParseString(const wxString& s, int len, int& mod, int& key, int& joy);
|
||||||
// parse multi-key string into array
|
// parse multi-key string into array
|
||||||
|
@ -77,30 +62,30 @@ protected:
|
||||||
// A simple copy-only validator
|
// A simple copy-only validator
|
||||||
class wxJoyKeyValidator : public wxValidator {
|
class wxJoyKeyValidator : public wxValidator {
|
||||||
public:
|
public:
|
||||||
wxJoyKeyValidator(wxJoyKeyBinding_v* v)
|
wxJoyKeyValidator(const wxGameControl v)
|
||||||
: wxValidator()
|
: wxValidator()
|
||||||
, val(v)
|
, val_(v)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
wxJoyKeyValidator(const wxJoyKeyValidator& v)
|
wxJoyKeyValidator(const wxJoyKeyValidator& v)
|
||||||
: wxValidator()
|
: wxValidator()
|
||||||
, val(v.val)
|
, val_(v.val_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
wxObject* Clone() const
|
wxObject* Clone() const override
|
||||||
{
|
{
|
||||||
return new wxJoyKeyValidator(val);
|
return new wxJoyKeyValidator(val_);
|
||||||
}
|
}
|
||||||
bool TransferToWindow();
|
bool TransferToWindow() override;
|
||||||
bool TransferFromWindow();
|
bool TransferFromWindow() override;
|
||||||
bool Validate(wxWindow* p)
|
bool Validate(wxWindow* p) override
|
||||||
{
|
{
|
||||||
(void)p; // unused params
|
(void)p; // unused params
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxJoyKeyBinding_v* val;
|
const wxGameControl val_;
|
||||||
|
|
||||||
DECLARE_CLASS(wxJoyKeyValidator)
|
DECLARE_CLASS(wxJoyKeyValidator)
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef _WX_USER_INPUT_H_
|
#ifndef _WX_USER_INPUT_H_
|
||||||
#define _WX_USER_INPUT_H_
|
#define _WX_USER_INPUT_H_
|
||||||
|
|
||||||
#include <optional>
|
#include <set>
|
||||||
|
#include <wx/event.h>
|
||||||
|
|
||||||
#include "wx/joyedit.h"
|
|
||||||
#include "wx/sdljoy.h"
|
#include "wx/sdljoy.h"
|
||||||
|
|
||||||
// Abstraction for a user input, which can come from a keyboard or a joystick.
|
// Abstraction for a user input, which can come from a keyboard or a joystick.
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
//
|
//
|
||||||
// TODO: Right now, this class is implemented as a thin wrapper around the key,
|
// TODO: Right now, this class is implemented as a thin wrapper around the key,
|
||||||
// mod and joy user input representation used in many places in the code base.
|
// mod and joy user input representation used in many places in the code base.
|
||||||
// This is to ease a transition away from the wxJoyKeyBinding type, which
|
// This is to ease a transition away from the key, mod, joy triplet, which
|
||||||
// wxUserInput will eventually replace.
|
// wxUserInput will eventually replace.
|
||||||
class wxUserInput {
|
class wxUserInput {
|
||||||
public:
|
public:
|
||||||
|
@ -33,21 +33,25 @@ public:
|
||||||
// Constructor from a wxJoyEvent.
|
// Constructor from a wxJoyEvent.
|
||||||
static wxUserInput FromJoyEvent(const wxJoyEvent& event);
|
static wxUserInput FromJoyEvent(const wxJoyEvent& event);
|
||||||
|
|
||||||
// Constructor from a configuration string. Returns wxUserInput::Invalid()
|
// Constructor from a configuration string. Returns empty set on failure.
|
||||||
// on parsing failure.
|
static std::set<wxUserInput> FromString(const wxString& string);
|
||||||
static wxUserInput FromString(const wxString& string);
|
|
||||||
|
|
||||||
// TODO: Remove this once all uses of wxJoyKeyBinding have been removed.
|
// TODO: Remove this once all uses have been removed.
|
||||||
static wxUserInput FromLegacyJoyKeyBinding(const wxJoyKeyBinding& binding);
|
static wxUserInput FromLegacyKeyModJoy(int key = 0, int mod = 0, int joy = 0);
|
||||||
|
|
||||||
// Converts to a configuration string. Computed on first call, and cached
|
// Converts a set of wxUserInput into a configuration string. This
|
||||||
// for further calls.
|
// recomputes the configuration string every time and should not be used
|
||||||
wxString ToString();
|
// for comparison purposes.
|
||||||
|
// TODO: Replace std::set with std::span when the code base uses C++20.
|
||||||
|
static wxString SpanToString(
|
||||||
|
const std::set<wxUserInput>& user_inputs, bool is_config = false);
|
||||||
|
|
||||||
// TODO: Remove these accessors once all callers have been removed.
|
// Converts to a configuration string.
|
||||||
int mod() const { return mod_; }
|
wxString ToString(bool is_config = false) const;
|
||||||
int key() const { return key_; }
|
|
||||||
int joy() const { return joy_; }
|
wxJoystick joystick() const { return joystick_; }
|
||||||
|
bool is_valid() const { return device_ != Device::Invalid; }
|
||||||
|
operator bool() const { return is_valid(); }
|
||||||
|
|
||||||
bool operator==(const wxUserInput& other) const;
|
bool operator==(const wxUserInput& other) const;
|
||||||
bool operator!=(const wxUserInput& other) const;
|
bool operator!=(const wxUserInput& other) const;
|
||||||
|
@ -59,12 +63,11 @@ public:
|
||||||
private:
|
private:
|
||||||
wxUserInput(Device device, int mod, uint8_t key, unsigned joy);
|
wxUserInput(Device device, int mod, uint8_t key, unsigned joy);
|
||||||
|
|
||||||
Device device_;
|
const Device device_;
|
||||||
int mod_;
|
const wxJoystick joystick_;
|
||||||
uint8_t key_;
|
const int mod_;
|
||||||
unsigned joy_;
|
const uint8_t key_;
|
||||||
|
const unsigned joy_;
|
||||||
wxString config_string_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
// The built-in vba-over.ini
|
// The built-in vba-over.ini
|
||||||
#include "builtin-over.h"
|
#include "builtin-over.h"
|
||||||
|
#include "wx/gamecontrol.h"
|
||||||
#include "wx/userinput.h"
|
#include "wx/userinput.h"
|
||||||
|
|
||||||
IMPLEMENT_APP(wxvbamApp)
|
IMPLEMENT_APP(wxvbamApp)
|
||||||
|
@ -178,8 +179,6 @@ wxString wxvbamApp::GetConfigurationPath()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// use default keys for input.
|
|
||||||
set_default_keys();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return data_path;
|
return data_path;
|
||||||
|
@ -430,6 +429,10 @@ bool wxvbamApp::OnInit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize game bindings here, after defaults bindings, vbam.ini bindings
|
||||||
|
// and command line overrides have been applied.
|
||||||
|
wxGameControlState::Instance().OnGameBindingsChanged();
|
||||||
|
|
||||||
// create the main window
|
// create the main window
|
||||||
int x = windowPositionX;
|
int x = windowPositionX;
|
||||||
int y = windowPositionY;
|
int y = windowPositionY;
|
||||||
|
@ -933,19 +936,12 @@ void MainFrame::SetJoystick()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::set<wxJoystick> needed_joysticks;
|
std::set<wxJoystick> needed_joysticks;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (const auto& iter : gopts.game_control_bindings) {
|
||||||
for (int j = 0; j < NUM_KEYS; j++) {
|
for (const auto& input_iter : iter.second) {
|
||||||
wxJoyKeyBinding_v b = gopts.joykey_bindings[i][j];
|
needed_joysticks.emplace(input_iter.joystick());
|
||||||
for (size_t k = 0; k < b.size(); k++) {
|
|
||||||
int jn = b[k].joy;
|
|
||||||
if (jn) {
|
|
||||||
needed_joysticks.insert(
|
|
||||||
wxJoystick::FromLegacyPlayerIndex(jn));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
joy.PollJoysticks(std::move(needed_joysticks));
|
||||||
}
|
|
||||||
joy.PollJoysticks(needed_joysticks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::StopJoyPollTimer()
|
void MainFrame::StopJoyPollTimer()
|
||||||
|
|
|
@ -805,8 +805,7 @@ void systemStopGamePlayback();
|
||||||
// true if turbo mode (like pressing turbo button constantly)
|
// true if turbo mode (like pressing turbo button constantly)
|
||||||
extern bool turbo;
|
extern bool turbo;
|
||||||
|
|
||||||
// mask of key press flags; see below
|
extern int autofire, autohold;
|
||||||
extern int joypress[4], autofire, autohold;
|
|
||||||
|
|
||||||
// FIXME: these defines should be global to project and used instead of raw numbers
|
// FIXME: these defines should be global to project and used instead of raw numbers
|
||||||
#define KEYM_A (1 << 0)
|
#define KEYM_A (1 << 0)
|
||||||
|
|
Loading…
Reference in New Issue