Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
InputEngine.cpp
Go to the documentation of this file.
1/*
2 This source file is part of Rigs of Rods
3 Copyright 2005-2012 Pierre-Michel Ricordel
4 Copyright 2007-2012 Thomas Fischer
5 Copyright 2013-2023 Petr Ohlidal
6
7 For more information, see http://www.rigsofrods.org/
8
9 Rigs of Rods is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 3, as
11 published by the Free Software Foundation.
12
13 Rigs of Rods is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "InputEngine.h"
23
24#include "Actor.h"
25#include "AppContext.h"
26#include "Console.h"
27#include "ContentManager.h"
28#include "GUIManager.h"
29#include "Language.h"
30
31#include <regex>
32
33using namespace RoR;
34
35const char* mOISDeviceType[6] = {"Unknown Device", "Keyboard", "Mouse", "JoyStick", "Tablet", "Other Device"};
36
38 // Common: generic
39 {"COMMON_ACCELERATE_SIMULATION", EV_COMMON_ACCELERATE_SIMULATION, "Keyboard CTRL+EQUALS", _LC("InputEvent", "accelerate the simulation")},
40 {"COMMON_DECELERATE_SIMULATION", EV_COMMON_DECELERATE_SIMULATION, "Keyboard SHIFT+EQUALS", _LC("InputEvent", "decelerate the simulation")},
41 {"COMMON_RESET_SIMULATION_PACE", EV_COMMON_RESET_SIMULATION_PACE, "Keyboard BACKSLASH", _LC("InputEvent", "reset the simulation pace")},
42 {"COMMON_OUTPUT_POSITION", EV_COMMON_OUTPUT_POSITION, "Keyboard H", _LC("InputEvent", "write current position to log (you can open the logfile and reuse the position)")},
43 {"COMMON_QUIT_GAME", EV_COMMON_QUIT_GAME, "Keyboard EXPL+ESCAPE", _LC("InputEvent", "exit the game")},
44 {"COMMON_QUICKLOAD", EV_COMMON_QUICKLOAD, "Keyboard MULTIPLY", _LC("InputEvent", "quickload scene")},
45 {"COMMON_QUICKSAVE", EV_COMMON_QUICKSAVE, "Keyboard DIVIDE", _LC("InputEvent", "quicksave scene")},
46 {"COMMON_SCREENSHOT", EV_COMMON_SCREENSHOT, "Keyboard EXPL+SYSRQ", _LC("InputEvent", "take a screenshot")},
47 {"COMMON_SCREENSHOT_BIG", EV_COMMON_SCREENSHOT_BIG, "Keyboard EXPL+CTRL+SYSRQ", _LC("InputEvent", "take a big screenshot (3 times the screen size)")},
48 {"COMMON_TOGGLE_MAT_DEBUG", EV_COMMON_TOGGLE_MAT_DEBUG, "", _LC("InputEvent", "debug purpose - dont use")},
49 {"COMMON_TOGGLE_PHYSICS", EV_COMMON_TOGGLE_PHYSICS, "Keyboard EXPL+J", _LC("InputEvent", "enable or disable physics")},
50 {"COMMON_FOV_LESS", EV_COMMON_FOV_LESS, "Keyboard EXPL+NUMPAD7", _LC("InputEvent", "decreases the current FOV value")},
51 {"COMMON_FOV_MORE", EV_COMMON_FOV_MORE, "Keyboard EXPL+CTRL+NUMPAD7", _LC("InputEvent", "increase the current FOV value")},
52 {"COMMON_FOV_RESET", EV_COMMON_FOV_RESET, "Keyboard EXPL+SHIFT+NUMPAD7", _LC("InputEvent", "reset the FOV value")},
53 {"COMMON_SAVE_TERRAIN", EV_COMMON_SAVE_TERRAIN, "Keyboard EXPL+ALT+SHIF+CTRL+M",_LC("InputEvent", "save the currently loaded terrain to a mesh file")},
54 {"COMMON_TOGGLE_TERRAIN_EDITOR", EV_COMMON_TOGGLE_TERRAIN_EDITOR, "Keyboard EXPL+SHIFT+Y", _LC("InputEvent", "toggle terrain editor")},
55 {"COMMON_FULLSCREEN_TOGGLE", EV_COMMON_FULLSCREEN_TOGGLE, "Keyboard EXPL+ALT+RETURN", _LC("InputEvent", "toggle between windowed and fullscreen mode")},
56
57 // Comon: actor interaction
58 {"COMMON_ENTER_OR_EXIT_TRUCK", EV_COMMON_ENTER_OR_EXIT_TRUCK, "Keyboard RETURN", _LC("InputEvent", "enter or exit a truck")},
59 {"COMMON_ENTER_NEXT_TRUCK", EV_COMMON_ENTER_NEXT_TRUCK, "Keyboard EXPL+CTRL+RBRACKET", _LC("InputEvent", "enter next truck")},
60 {"COMMON_ENTER_PREVIOUS_TRUCK", EV_COMMON_ENTER_PREVIOUS_TRUCK, "Keyboard EXPL+CTRL+LBRACKET", _LC("InputEvent", "enter previous truck")},
61 {"COMMON_REMOVE_CURRENT_TRUCK", EV_COMMON_REMOVE_CURRENT_TRUCK, "Keyboard EXPL+CTRL+DELETE", _LC("InputEvent", "remove current truck")},
62 {"COMMON_TRUCK_REMOVE", EV_COMMON_TRUCK_REMOVE, "Keyboard EXPL+CTRL+SHIFT+DELETE",_LC("InputEvent", "delete current truck")},
63 {"COMMON_RESPAWN_LAST_TRUCK", EV_COMMON_RESPAWN_LAST_TRUCK, "Keyboard EXPL+CTRL+PERIOD", _LC("InputEvent", "respawn last truck")},
64 {"COMMON_GET_NEW_VEHICLE", EV_COMMON_GET_NEW_VEHICLE, "Keyboard EXPL+CTRL+G", _LC("InputEvent", "get new vehicle")},
65 {"COMMON_PRESSURE_LESS", EV_COMMON_PRESSURE_LESS, "Keyboard LBRACKET", _LC("InputEvent", "decrease tire pressure (note: only very few trucks support this)")},
66 {"COMMON_PRESSURE_MORE", EV_COMMON_PRESSURE_MORE, "Keyboard RBRACKET", _LC("InputEvent", "increase tire pressure (note: only very few trucks support this)")},
67 {"COMMON_LOCK", EV_COMMON_LOCK, "Keyboard EXPL+L", _LC("InputEvent", "connect hook node to a node in close proximity")},
68 {"COMMON_AUTOLOCK", EV_COMMON_AUTOLOCK, "Keyboard EXPL+ALT+L", _LC("InputEvent", "unlock autolock hook node")},
69 {"COMMON_ROPELOCK", EV_COMMON_ROPELOCK, "Keyboard EXPL+CTRL+L", _LC("InputEvent", "connect a rope to a node in close proximity")},
70 {"COMMON_REPAIR_TRUCK", EV_COMMON_REPAIR_TRUCK, "Keyboard BACK", _LC("InputEvent", "repair truck")},
71 {"COMMON_LIVE_REPAIR_MODE", EV_COMMON_LIVE_REPAIR_MODE, "Keyboard ALT+BACK", _LC("InputEvent", "toggle truck interactive repair mode")},
72 {"COMMON_RESCUE_TRUCK", EV_COMMON_RESCUE_TRUCK, "Keyboard EXPL+R", _LC("InputEvent", "teleport to rescue truck")},
73 {"COMMON_RESET_TRUCK", EV_COMMON_RESET_TRUCK, "Keyboard I", _LC("InputEvent", "reset truck to original starting position")},
74 {"COMMON_TOGGLE_RESET_MODE", EV_COMMON_TOGGLE_RESET_MODE, "Keyboard EXPL+APOSTROPHE", _LC("InputEvent", "toggle reset mode")},
75 {"COMMON_SECURE_LOAD", EV_COMMON_SECURE_LOAD, "Keyboard O", _LC("InputEvent", "tie a load to the truck")},
76 {"COMMON_TOGGLE_TRUCK_BEACONS", EV_COMMON_TOGGLE_TRUCK_BEACONS, "Keyboard M", _LC("InputEvent", "toggle truck beacons")},
77 {"COMMON_TOGGLE_TRUCK_LOW_BEAMS", EV_COMMON_TOGGLE_TRUCK_LOW_BEAMS, "Keyboard EXPL+N", _LC("InputEvent", "toggle truck low beams")},
78 {"COMMON_CYCLE_TRUCK_LIGHTS", EV_COMMON_CYCLE_TRUCK_LIGHTS, "Keyboard EXPL+CTRL+N", _LC("InputEvent", "cycle between light modes")},
79 {"COMMON_TOGGLE_TRUCK_HIGH_BEAMS",EV_COMMON_TOGGLE_TRUCK_HIGH_BEAMS,"Keyboard EXPL+SHIFT+N", _LC("InputEvent", "toggle truck high beams")},
80 {"COMMON_TOGGLE_TRUCK_FOG_LIGHTS",EV_COMMON_TOGGLE_TRUCK_FOG_LIGHTS,"Keyboard EXPL+ALT+N", _LC("InputEvent", "toggle truck fog lights")},
81 {"COMMON_TOGGLE_CUSTOM_PARTICLES",EV_COMMON_TOGGLE_CUSTOM_PARTICLES,"Keyboard G", _LC("InputEvent", "toggle particle cannon")},
82 {"COMMON_TOGGLE_REPLAY_MODE", EV_COMMON_TOGGLE_REPLAY_MODE, "Keyboard EXPL+CTRL+J", _LC("InputEvent", "enable or disable replay mode")},
83 {"COMMON_REPLAY_FORWARD", EV_COMMON_REPLAY_FORWARD, "Keyboard EXPL+RIGHT", _LC("InputEvent", "more replay forward")},
84 {"COMMON_REPLAY_BACKWARD", EV_COMMON_REPLAY_BACKWARD, "Keyboard EXPL+LEFT", _LC("InputEvent", "more replay backward")},
85 {"COMMON_REPLAY_FAST_FORWARD", EV_COMMON_REPLAY_FAST_FORWARD, "Keyboard EXPL+SHIFT+RIGHT", _LC("InputEvent", "move replay fast forward")},
86 {"COMMON_REPLAY_FAST_BACKWARD", EV_COMMON_REPLAY_FAST_BACKWARD, "Keyboard EXPL+SHIFT+LEFT", _LC("InputEvent", "move replay fast backward")},
87
88 // Common: UI
89 {"COMMON_CONSOLE_TOGGLE", EV_COMMON_CONSOLE_TOGGLE, "Keyboard EXPL+GRAVE", _LC("InputEvent", "show / hide the console")},
90 {"COMMON_ENTER_CHATMODE", EV_COMMON_ENTER_CHATMODE, "Keyboard EXPL+Y", _LC("InputEvent", "enter the chat")},
91 {"COMMON_SEND_CHAT", EV_COMMON_SEND_CHAT, "Keyboard RETURN", _LC("InputEvent", "sends the entered text")},
92 {"COMMON_HIDE_GUI", EV_COMMON_HIDE_GUI, "Keyboard EXPL+U", _LC("InputEvent", "hide all GUI elements")},
93 {"COMMON_TOGGLE_DASHBOARD", EV_COMMON_TOGGLE_DASHBOARD, "Keyboard EXPL+CTRL+U", _LC("InputEvent", "display or hide the dashboard overlay")},
94 {"COMMON_TOGGLE_DEBUG_VIEW", EV_COMMON_TOGGLE_DEBUG_VIEW, "Keyboard EXPL+K", _LC("InputEvent", "toggle debug view")},
95 {"COMMON_CYCLE_DEBUG_VIEWS", EV_COMMON_CYCLE_DEBUG_VIEWS, "Keyboard EXPL+CTRL+K", _LC("InputEvent", "cycle debug views")},
96 {"COMMON_TRUCK_INFO", EV_COMMON_TRUCK_INFO, "Keyboard EXPL+T", _LC("InputEvent", "toggle truck HUD")},
97 {"COMMON_TRUCK_DESCRIPTION", EV_COMMON_TRUCK_DESCRIPTION, "Keyboard EXPL+CTRL+T", _LC("InputEvent", "toggle truck description")},
98 {"COMMON_NETCHATDISPLAY", EV_COMMON_NETCHATDISPLAY, "Keyboard EXPL+SHIFT+U", _LC("InputEvent", "display or hide net chat")},
99 {"COMMON_NETCHATMODE", EV_COMMON_NETCHATMODE, "Keyboard EXPL+CTRL+U", _LC("InputEvent", "toggle between net chat display modes")},
100 {"COMMON_TOGGLE_STATS", EV_COMMON_TOGGLE_STATS, "Keyboard EXPL+F", _LC("InputEvent", "toggle Ogre statistics (FPS etc.)")},
101
102 // Common: savegames
103 {"COMMON_QUICKSAVE_01", EV_COMMON_QUICKSAVE_01, "Keyboard EXPL+ALT+CTRL+1", _LC("InputEvent", "save scene in slot 01")},
104 {"COMMON_QUICKSAVE_02", EV_COMMON_QUICKSAVE_02, "Keyboard EXPL+ALT+CTRL+2", _LC("InputEvent", "save scene in slot 02")},
105 {"COMMON_QUICKSAVE_03", EV_COMMON_QUICKSAVE_03, "Keyboard EXPL+ALT+CTRL+3", _LC("InputEvent", "save scene in slot 03")},
106 {"COMMON_QUICKSAVE_04", EV_COMMON_QUICKSAVE_04, "Keyboard EXPL+ALT+CTRL+4", _LC("InputEvent", "save scene in slot 04")},
107 {"COMMON_QUICKSAVE_05", EV_COMMON_QUICKSAVE_05, "Keyboard EXPL+ALT+CTRL+5", _LC("InputEvent", "save scene in slot 05")},
108 {"COMMON_QUICKSAVE_06", EV_COMMON_QUICKSAVE_06, "Keyboard EXPL+ALT+CTRL+6", _LC("InputEvent", "save scene in slot 06")},
109 {"COMMON_QUICKSAVE_07", EV_COMMON_QUICKSAVE_07, "Keyboard EXPL+ALT+CTRL+7", _LC("InputEvent", "save scene in slot 07")},
110 {"COMMON_QUICKSAVE_08", EV_COMMON_QUICKSAVE_08, "Keyboard EXPL+ALT+CTRL+8", _LC("InputEvent", "save scene in slot 08")},
111 {"COMMON_QUICKSAVE_09", EV_COMMON_QUICKSAVE_09, "Keyboard EXPL+ALT+CTRL+9", _LC("InputEvent", "save scene in slot 09")},
112 {"COMMON_QUICKSAVE_10", EV_COMMON_QUICKSAVE_10, "Keyboard EXPL+ALT+CTRL+0", _LC("InputEvent", "save scene in slot 10")},
113
114 {"COMMON_QUICKLOAD_01", EV_COMMON_QUICKLOAD_01, "Keyboard EXPL+ALT+1", _LC("InputEvent", "load scene from slot 01")},
115 {"COMMON_QUICKLOAD_02", EV_COMMON_QUICKLOAD_02, "Keyboard EXPL+ALT+2", _LC("InputEvent", "load scene from slot 02")},
116 {"COMMON_QUICKLOAD_03", EV_COMMON_QUICKLOAD_03, "Keyboard EXPL+ALT+3", _LC("InputEvent", "load scene from slot 03")},
117 {"COMMON_QUICKLOAD_04", EV_COMMON_QUICKLOAD_04, "Keyboard EXPL+ALT+4", _LC("InputEvent", "load scene from slot 04")},
118 {"COMMON_QUICKLOAD_05", EV_COMMON_QUICKLOAD_05, "Keyboard EXPL+ALT+5", _LC("InputEvent", "load scene from slot 05")},
119 {"COMMON_QUICKLOAD_06", EV_COMMON_QUICKLOAD_06, "Keyboard EXPL+ALT+6", _LC("InputEvent", "load scene from slot 06")},
120 {"COMMON_QUICKLOAD_07", EV_COMMON_QUICKLOAD_07, "Keyboard EXPL+ALT+7", _LC("InputEvent", "load scene from slot 07")},
121 {"COMMON_QUICKLOAD_08", EV_COMMON_QUICKLOAD_08, "Keyboard EXPL+ALT+8", _LC("InputEvent", "load scene from slot 08")},
122 {"COMMON_QUICKLOAD_09", EV_COMMON_QUICKLOAD_09, "Keyboard EXPL+ALT+9", _LC("InputEvent", "load scene from slot 09")},
123 {"COMMON_QUICKLOAD_10", EV_COMMON_QUICKLOAD_10, "Keyboard EXPL+ALT+0", _LC("InputEvent", "load scene from slot 10")},
124
125 // Truck: generic
126 {"TRUCK_ACCELERATE", EV_TRUCK_ACCELERATE, "Keyboard UP", _LC("InputEvent", "accelerate the truck")},
127 {"TRUCK_ACCELERATE_MODIFIER_25", EV_TRUCK_ACCELERATE_MODIFIER_25, "Keyboard ALT+UP", _LC("InputEvent", "accelerate with 25 percent pedal input")},
128 {"TRUCK_ACCELERATE_MODIFIER_50", EV_TRUCK_ACCELERATE_MODIFIER_50, "Keyboard CTRL+UP", _LC("InputEvent", "accelerate with 50 percent pedal input")},
129 {"TRUCK_BLINK_LEFT", EV_TRUCK_BLINK_LEFT, "Keyboard EXPL+COMMA", _LC("InputEvent", "toggle left direction indicator (blinker)")},
130 {"TRUCK_BLINK_RIGHT", EV_TRUCK_BLINK_RIGHT, "Keyboard EXPL+PERIOD", _LC("InputEvent", "toggle right direction indicator (blinker)")},
131 {"TRUCK_BLINK_WARN", EV_TRUCK_BLINK_WARN, "Keyboard EXPL+MINUS", _LC("InputEvent", "toggle all direction indicators")},
132 {"TRUCK_BRAKE", EV_TRUCK_BRAKE, "Keyboard DOWN", _LC("InputEvent", "brake")},
133 {"TRUCK_BRAKE_MODIFIER_25", EV_TRUCK_BRAKE_MODIFIER_25, "Keyboard ALT+DOWN", _LC("InputEvent", "brake with 25 percent pedal input")},
134 {"TRUCK_BRAKE_MODIFIER_50", EV_TRUCK_BRAKE_MODIFIER_50, "Keyboard CTRL+DOWN", _LC("InputEvent", "brake with 50 percent pedal input")},
135 {"TRUCK_HORN", EV_TRUCK_HORN, "Keyboard H", _LC("InputEvent", "truck horn")},
136 {"TRUCK_LIGHTTOGGLE1", EV_TRUCK_LIGHTTOGGLE01, "Keyboard EXPL+CTRL+1", _LC("InputEvent", "toggle custom light 1")},
137 {"TRUCK_LIGHTTOGGLE2", EV_TRUCK_LIGHTTOGGLE02, "Keyboard EXPL+CTRL+2", _LC("InputEvent", "toggle custom light 2")},
138 {"TRUCK_LIGHTTOGGLE3", EV_TRUCK_LIGHTTOGGLE03, "Keyboard EXPL+CTRL+3", _LC("InputEvent", "toggle custom light 3")},
139 {"TRUCK_LIGHTTOGGLE4", EV_TRUCK_LIGHTTOGGLE04, "Keyboard EXPL+CTRL+4", _LC("InputEvent", "toggle custom light 4")},
140 {"TRUCK_LIGHTTOGGLE5", EV_TRUCK_LIGHTTOGGLE05, "Keyboard EXPL+CTRL+5", _LC("InputEvent", "toggle custom light 5")},
141 {"TRUCK_LIGHTTOGGLE6", EV_TRUCK_LIGHTTOGGLE06, "Keyboard EXPL+CTRL+6", _LC("InputEvent", "toggle custom light 6")},
142 {"TRUCK_LIGHTTOGGLE7", EV_TRUCK_LIGHTTOGGLE07, "Keyboard EXPL+CTRL+7", _LC("InputEvent", "toggle custom light 7")},
143 {"TRUCK_LIGHTTOGGLE8", EV_TRUCK_LIGHTTOGGLE08, "Keyboard EXPL+CTRL+8", _LC("InputEvent", "toggle custom light 8")},
144 {"TRUCK_LIGHTTOGGLE9", EV_TRUCK_LIGHTTOGGLE09, "Keyboard EXPL+CTRL+9", _LC("InputEvent", "toggle custom light 9")},
145 {"TRUCK_LIGHTTOGGLE10", EV_TRUCK_LIGHTTOGGLE10, "Keyboard EXPL+CTRL+0", _LC("InputEvent", "toggle custom light 10")},
146 {"TRUCK_PARKING_BRAKE", EV_TRUCK_PARKING_BRAKE, "Keyboard P", _LC("InputEvent", "toggle parking brake")},
147 {"TRUCK_TRAILER_PARKING_BRAKE", EV_TRUCK_TRAILER_PARKING_BRAKE, "Keyboard EXPL+CTRL+P", _LC("InputEvent", "toggle trailer parking brake")},
148 {"TRUCK_ANTILOCK_BRAKE", EV_TRUCK_ANTILOCK_BRAKE, "Keyboard EXPL+SHIFT+B", _LC("InputEvent", "toggle antilock brake")},
149 {"TRUCK_TOGGLE_VIDEOCAMERA", EV_TRUCK_TOGGLE_VIDEOCAMERA, "Keyboard EXPL+CTRL+V", _LC("InputEvent", "toggle videocamera")},
150 {"TRUCK_TRACTION_CONTROL", EV_TRUCK_TRACTION_CONTROL, "Keyboard EXPL+SHIFT+T", _LC("InputEvent", "toggle traction control")},
151 {"TRUCK_CRUISE_CONTROL", EV_TRUCK_CRUISE_CONTROL, "Keyboard EXPL+SPACE", _LC("InputEvent", "toggle cruise control")},
152 {"TRUCK_CRUISE_CONTROL_READJUST", EV_TRUCK_CRUISE_CONTROL_READJUST, "Keyboard EXPL+CTRL+SPACE", _LC("InputEvent", "match target speed / rpm with current truck speed / rpm")},
153 {"TRUCK_CRUISE_CONTROL_ACCL", EV_TRUCK_CRUISE_CONTROL_ACCL, "Keyboard EXPL+CTRL+R", _LC("InputEvent", "increase target speed / rpm")},
154 {"TRUCK_CRUISE_CONTROL_DECL", EV_TRUCK_CRUISE_CONTROL_DECL, "Keyboard EXPL+CTRL+F", _LC("InputEvent", "decrease target speed / rpm")},
155 {"TRUCK_STARTER", EV_TRUCK_STARTER, "Keyboard S", _LC("InputEvent", "hold to start the engine")},
156 {"TRUCK_STEER_LEFT", EV_TRUCK_STEER_LEFT, "Keyboard LEFT", _LC("InputEvent", "steer left")},
157 {"TRUCK_STEER_RIGHT", EV_TRUCK_STEER_RIGHT, "Keyboard RIGHT", _LC("InputEvent", "steer right")},
158 {"TRUCK_TOGGLE_CONTACT", EV_TRUCK_TOGGLE_CONTACT, "Keyboard X", _LC("InputEvent", "toggle ignition")},
159 {"TRUCK_TOGGLE_FORWARDCOMMANDS", EV_TRUCK_TOGGLE_FORWARDCOMMANDS, "Keyboard EXPL+CTRL+SHIFT+F", _LC("InputEvent", "toggle forwardcommands")},
160 {"TRUCK_TOGGLE_IMPORTCOMMANDS", EV_TRUCK_TOGGLE_IMPORTCOMMANDS, "Keyboard EXPL+CTRL+SHIFT+I", _LC("InputEvent", "toggle importcommands")},
161 {"TRUCK_TOGGLE_PHYSICS", EV_TRUCK_TOGGLE_PHYSICS, "Keyboard END", _LC("InputEvent", "toggle physics")},
162 {"TRUCK_TOGGLE_INTER_AXLE_DIFF", EV_TRUCK_TOGGLE_INTER_AXLE_DIFF, "Keyboard EXPL+ALT+W", _LC("InputEvent", "cycle between available inter axle differential modes")},
163 {"TRUCK_TOGGLE_INTER_WHEEL_DIFF", EV_TRUCK_TOGGLE_INTER_WHEEL_DIFF, "Keyboard EXPL+W", _LC("InputEvent", "cycle between available inter wheel differential modes")},
164 {"TRUCK_TOGGLE_TCASE_4WD_MODE", EV_TRUCK_TOGGLE_TCASE_4WD_MODE, "Keyboard EXPL+CTRL+W", _LC("InputEvent", "toggle transfer case mode")},
165 {"TRUCK_TOGGLE_TCASE_GEAR_RATIO", EV_TRUCK_TOGGLE_TCASE_GEAR_RATIO, "Keyboard EXPL+SHIFT+W", _LC("InputEvent", "toggle transfer case gear ratio")},
166 {"TRUCK_LEFT_MIRROR_LEFT", EV_TRUCK_LEFT_MIRROR_LEFT, "Keyboard EXPL+SEMICOLON", _LC("InputEvent", "move left mirror to the left")},
167 {"TRUCK_LEFT_MIRROR_RIGHT", EV_TRUCK_LEFT_MIRROR_RIGHT, "Keyboard EXPL+CTRL+SEMICOLON", _LC("InputEvent", "move left mirror to the right")},
168 {"TRUCK_RIGHT_MIRROR_LEFT", EV_TRUCK_RIGHT_MIRROR_LEFT, "Keyboard EXPL+COLON", _LC("InputEvent", "more right mirror to the left")},
169 {"TRUCK_RIGHT_MIRROR_RIGHT", EV_TRUCK_RIGHT_MIRROR_RIGHT, "Keyboard EXPL+CTRL+COLON", _LC("InputEvent", "move right mirror to the right")},
170
171 // Truck: transmission
172 {"TRUCK_AUTOSHIFT_DOWN", EV_TRUCK_AUTOSHIFT_DOWN, "Keyboard PGDOWN", _LC("InputEvent", "shift automatic transmission one gear down")},
173 {"TRUCK_AUTOSHIFT_UP", EV_TRUCK_AUTOSHIFT_UP, "Keyboard PGUP", _LC("InputEvent", "shift automatic transmission one gear up")},
174 {"TRUCK_MANUAL_CLUTCH", EV_TRUCK_MANUAL_CLUTCH, "Keyboard LSHIFT", _LC("InputEvent", "manual clutch (for manual transmission)")},
175 {"TRUCK_MANUAL_CLUTCH_MODIFIER_25",EV_TRUCK_MANUAL_CLUTCH_MODIFIER_25,"Keyboard ALT+LSHIFT", _LC("InputEvent", "manual clutch with 25 percent pedal input")},
176 {"TRUCK_MANUAL_CLUTCH_MODIFIER_50",EV_TRUCK_MANUAL_CLUTCH_MODIFIER_50,"Keyboard CTRL+LSHIFT", _LC("InputEvent", "manual clutch with 50 percent pedal input")},
177 {"TRUCK_SHIFT_DOWN", EV_TRUCK_SHIFT_DOWN, "Keyboard Z", _LC("InputEvent", "shift one gear down in manual transmission mode")},
178 {"TRUCK_SHIFT_NEUTRAL", EV_TRUCK_SHIFT_NEUTRAL, "Keyboard D", _LC("InputEvent", "shift to neutral gear in manual transmission mode")},
179 {"TRUCK_SHIFT_UP", EV_TRUCK_SHIFT_UP, "Keyboard A", _LC("InputEvent", "shift one gear up in manual transmission mode")},
180 {"TRUCK_SHIFT_GEAR_REVERSE", EV_TRUCK_SHIFT_GEAR_REVERSE, "", _LC("InputEvent", "shift directly to reverse gear")},
181 {"TRUCK_SHIFT_GEAR1", EV_TRUCK_SHIFT_GEAR01, "", _LC("InputEvent", "shift directly to first gear")},
182 {"TRUCK_SHIFT_GEAR2", EV_TRUCK_SHIFT_GEAR02, "", _LC("InputEvent", "shift directly to second gear")},
183 {"TRUCK_SHIFT_GEAR3", EV_TRUCK_SHIFT_GEAR03, "", _LC("InputEvent", "shift directly to third gear")},
184 {"TRUCK_SHIFT_GEAR4", EV_TRUCK_SHIFT_GEAR04, "", _LC("InputEvent", "shift directly to fourth gear")},
185 {"TRUCK_SHIFT_GEAR5", EV_TRUCK_SHIFT_GEAR05, "", _LC("InputEvent", "shift directly to 5th gear")},
186 {"TRUCK_SHIFT_GEAR6", EV_TRUCK_SHIFT_GEAR06, "", _LC("InputEvent", "shift directly to 6th gear")},
187 {"TRUCK_SHIFT_GEAR7", EV_TRUCK_SHIFT_GEAR07, "", _LC("InputEvent", "shift directly to 7th gear")},
188 {"TRUCK_SHIFT_GEAR8", EV_TRUCK_SHIFT_GEAR08, "", _LC("InputEvent", "shift directly to 8th gear")},
189 {"TRUCK_SHIFT_GEAR9", EV_TRUCK_SHIFT_GEAR09, "", _LC("InputEvent", "shift directly to 9th gear")},
190 {"TRUCK_SHIFT_GEAR10", EV_TRUCK_SHIFT_GEAR10, "", _LC("InputEvent", "shift directly to 10th gear")},
191 {"TRUCK_SHIFT_GEAR11", EV_TRUCK_SHIFT_GEAR11, "", _LC("InputEvent", "shift directly to 11th gear")},
192 {"TRUCK_SHIFT_GEAR12", EV_TRUCK_SHIFT_GEAR12, "", _LC("InputEvent", "shift directly to 12th gear")},
193 {"TRUCK_SHIFT_GEAR13", EV_TRUCK_SHIFT_GEAR13, "", _LC("InputEvent", "shift directly to 13th gear")},
194 {"TRUCK_SHIFT_GEAR14", EV_TRUCK_SHIFT_GEAR14, "", _LC("InputEvent", "shift directly to 14th gear")},
195 {"TRUCK_SHIFT_GEAR15", EV_TRUCK_SHIFT_GEAR15, "", _LC("InputEvent", "shift directly to 15th gear")},
196 {"TRUCK_SHIFT_GEAR16", EV_TRUCK_SHIFT_GEAR16, "", _LC("InputEvent", "shift directly to 16th gear")},
197 {"TRUCK_SHIFT_GEAR17", EV_TRUCK_SHIFT_GEAR17, "", _LC("InputEvent", "shift directly to 17th gear")},
198 {"TRUCK_SHIFT_GEAR18", EV_TRUCK_SHIFT_GEAR18, "", _LC("InputEvent", "shift directly to 18th gear")},
199 {"TRUCK_SHIFT_LOWRANGE", EV_TRUCK_SHIFT_LOWRANGE, "", _LC("InputEvent", "sets low range (1-6) for H-shaft")},
200 {"TRUCK_SHIFT_MIDRANGE", EV_TRUCK_SHIFT_MIDRANGE, "", _LC("InputEvent", "sets middle range (7-12) for H-shaft")},
201 {"TRUCK_SHIFT_HIGHRANGE", EV_TRUCK_SHIFT_HIGHRANGE, "", _LC("InputEvent", "sets high range (13-18) for H-shaft")},
202 {"TRUCK_CYCLE_GEAR_RANGES", EV_TRUCK_CYCLE_GEAR_RANGES, "", _LC("InputEvent", "cycle through gear ranges") },
203 {"TRUCK_SWITCH_SHIFT_MODES", EV_TRUCK_SWITCH_SHIFT_MODES, "Keyboard Q", _LC("InputEvent", "toggle between transmission modes")},
204
205 // Airplane
206 {"AIRPLANE_STEER_RIGHT", EV_AIRPLANE_STEER_RIGHT, "Keyboard RIGHT", _LC("InputEvent", "steer right")},
207 {"AIRPLANE_BRAKE", EV_AIRPLANE_BRAKE, "Keyboard B", _LC("InputEvent", "normal brake for an aircraft")},
208 {"AIRPLANE_ELEVATOR_DOWN", EV_AIRPLANE_ELEVATOR_DOWN, "Keyboard DOWN", _LC("InputEvent", "pull the elevator down in an aircraft.")},
209 {"AIRPLANE_ELEVATOR_UP", EV_AIRPLANE_ELEVATOR_UP, "Keyboard UP", _LC("InputEvent", "pull the elevator up in an aircraft.")},
210 {"AIRPLANE_FLAPS_FULL", EV_AIRPLANE_FLAPS_FULL, "Keyboard CTRL+2", _LC("InputEvent", "full flaps in an aircraft.")},
211 {"AIRPLANE_FLAPS_LESS", EV_AIRPLANE_FLAPS_LESS, "Keyboard EXPL+1", _LC("InputEvent", "one step less flaps.")},
212 {"AIRPLANE_FLAPS_MORE", EV_AIRPLANE_FLAPS_MORE, "Keyboard EXPL+2", _LC("InputEvent", "one step more flaps.")},
213 {"AIRPLANE_FLAPS_NONE", EV_AIRPLANE_FLAPS_NONE, "Keyboard CTRL+1", _LC("InputEvent", "no flaps.")},
214 {"AIRPLANE_PARKING_BRAKE", EV_AIRPLANE_PARKING_BRAKE, "Keyboard P", _LC("InputEvent", "airplane parking brake.")},
215 {"AIRPLANE_REVERSE", EV_AIRPLANE_REVERSE, "Keyboard R", _LC("InputEvent", "reverse the turboprops")},
216 {"AIRPLANE_RUDDER_LEFT", EV_AIRPLANE_RUDDER_LEFT, "Keyboard Z", _LC("InputEvent", "rudder left")},
217 {"AIRPLANE_RUDDER_RIGHT", EV_AIRPLANE_RUDDER_RIGHT, "Keyboard X", _LC("InputEvent", "rudder right")},
218 {"AIRPLANE_STEER_LEFT", EV_AIRPLANE_STEER_LEFT, "Keyboard LEFT", _LC("InputEvent", "steer left")},
219 {"AIRPLANE_STEER_RIGHT", EV_AIRPLANE_STEER_RIGHT, "Keyboard RIGHT", _LC("InputEvent", "steer right")},
220 {"AIRPLANE_THROTTLE_AXIS", EV_AIRPLANE_THROTTLE_AXIS, "None", _LC("InputEvent", "throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider)")},
221 {"AIRPLANE_THROTTLE_DOWN", EV_AIRPLANE_THROTTLE_DOWN, "Keyboard EXPL+PGDOWN", _LC("InputEvent", "decreases the airplane thrust")},
222 {"AIRPLANE_THROTTLE_FULL", EV_AIRPLANE_THROTTLE_FULL, "Keyboard CTRL+PGUP", _LC("InputEvent", "full thrust")},
223 {"AIRPLANE_THROTTLE_NO", EV_AIRPLANE_THROTTLE_NO, "Keyboard CTRL+PGDOWN", _LC("InputEvent", "no thrust")},
224 {"AIRPLANE_THROTTLE_UP", EV_AIRPLANE_THROTTLE_UP, "Keyboard EXPL+PGUP", _LC("InputEvent", "increase the airplane thrust")},
225 {"AIRPLANE_TOGGLE_ENGINES", EV_AIRPLANE_TOGGLE_ENGINES, "Keyboard CTRL+HOME", _LC("InputEvent", "switch all engines on / off")},
226 {"AIRPLANE_AIRBRAKES_NONE", EV_AIRPLANE_AIRBRAKES_NONE, "Keyboard CTRL+3", _LC("InputEvent", "no airbrakes")},
227 {"AIRPLANE_AIRBRAKES_FULL", EV_AIRPLANE_AIRBRAKES_FULL, "Keyboard CTRL+4", _LC("InputEvent", "full airbrakes")},
228 {"AIRPLANE_AIRBRAKES_LESS", EV_AIRPLANE_AIRBRAKES_LESS, "Keyboard EXPL+3", _LC("InputEvent", "less airbrakes")},
229 {"AIRPLANE_AIRBRAKES_MORE", EV_AIRPLANE_AIRBRAKES_MORE, "Keyboard EXPL+4", _LC("InputEvent", "more airbrakes")},
230 {"AIRPLANE_THROTTLE", EV_AIRPLANE_THROTTLE, "", _LC("InputEvent", "airplane throttle")},
231
232 // Boat
233 {"BOAT_CENTER_RUDDER", EV_BOAT_CENTER_RUDDER, "Keyboard PGDOWN", _LC("InputEvent", "center the rudder")},
234 {"BOAT_REVERSE", EV_BOAT_REVERSE, "Keyboard PGUP", _LC("InputEvent", "no thrust")},
235 {"BOAT_STEER_LEFT", EV_BOAT_STEER_LEFT, "Keyboard LEFT", _LC("InputEvent", "steer left a step")},
236 {"BOAT_STEER_LEFT_AXIS", EV_BOAT_STEER_LEFT_AXIS, "None", _LC("InputEvent", "steer left (analog value!)")},
237 {"BOAT_STEER_RIGHT", EV_BOAT_STEER_RIGHT, "Keyboard RIGHT", _LC("InputEvent", "steer right a step")},
238 {"BOAT_STEER_RIGHT_AXIS", EV_BOAT_STEER_RIGHT_AXIS, "None", _LC("InputEvent", "steer right (analog value!)")},
239 {"BOAT_THROTTLE_AXIS", EV_BOAT_THROTTLE_AXIS, "None", _LC("InputEvent", "throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider)")},
240 {"BOAT_THROTTLE_DOWN", EV_BOAT_THROTTLE_DOWN, "Keyboard DOWN", _LC("InputEvent", "decrease throttle")},
241 {"BOAT_THROTTLE_UP", EV_BOAT_THROTTLE_UP, "Keyboard UP", _LC("InputEvent", "increase throttle")},
242
243 // Commands
244 {"COMMANDS_01", EV_COMMANDS_01, "Keyboard EXPL+F1", _LC("InputEvent", "Command 1")},
245 {"COMMANDS_02", EV_COMMANDS_02, "Keyboard EXPL+F2", _LC("InputEvent", "Command 2")},
246 {"COMMANDS_03", EV_COMMANDS_03, "Keyboard EXPL+F3", _LC("InputEvent", "Command 3")},
247 {"COMMANDS_04", EV_COMMANDS_04, "Keyboard EXPL+F4", _LC("InputEvent", "Command 4")},
248 {"COMMANDS_05", EV_COMMANDS_05, "Keyboard EXPL+F5", _LC("InputEvent", "Command 5")},
249 {"COMMANDS_06", EV_COMMANDS_06, "Keyboard EXPL+F6", _LC("InputEvent", "Command 6")},
250 {"COMMANDS_07", EV_COMMANDS_07, "Keyboard EXPL+F7", _LC("InputEvent", "Command 7")},
251 {"COMMANDS_08", EV_COMMANDS_08, "Keyboard EXPL+F8", _LC("InputEvent", "Command 8")},
252 {"COMMANDS_09", EV_COMMANDS_09, "Keyboard EXPL+F9", _LC("InputEvent", "Command 9")},
253 {"COMMANDS_10", EV_COMMANDS_10, "Keyboard EXPL+F10", _LC("InputEvent", "Command 10")},
254 {"COMMANDS_11", EV_COMMANDS_11, "Keyboard EXPL+F11", _LC("InputEvent", "Command 11")},
255 {"COMMANDS_12", EV_COMMANDS_12, "Keyboard EXPL+F12", _LC("InputEvent", "Command 12")},
256 {"COMMANDS_13", EV_COMMANDS_13, "Keyboard EXPL+CTRL+F1", _LC("InputEvent", "Command 13")},
257 {"COMMANDS_14", EV_COMMANDS_14, "Keyboard EXPL+CTRL+F2", _LC("InputEvent", "Command 14")},
258 {"COMMANDS_15", EV_COMMANDS_15, "Keyboard EXPL+CTRL+F3", _LC("InputEvent", "Command 15")},
259 {"COMMANDS_16", EV_COMMANDS_16, "Keyboard EXPL+CTRL+F4", _LC("InputEvent", "Command 16")},
260 {"COMMANDS_17", EV_COMMANDS_17, "Keyboard EXPL+CTRL+F5", _LC("InputEvent", "Command 17")},
261 {"COMMANDS_18", EV_COMMANDS_18, "Keyboard EXPL+CTRL+F6", _LC("InputEvent", "Command 18")},
262 {"COMMANDS_19", EV_COMMANDS_19, "Keyboard EXPL+CTRL+F7", _LC("InputEvent", "Command 19")},
263 {"COMMANDS_20", EV_COMMANDS_20, "Keyboard EXPL+CTRL+F8", _LC("InputEvent", "Command 20")},
264 {"COMMANDS_21", EV_COMMANDS_21, "Keyboard EXPL+CTRL+F9", _LC("InputEvent", "Command 21")},
265 {"COMMANDS_22", EV_COMMANDS_22, "Keyboard EXPL+CTRL+F10", _LC("InputEvent", "Command 22")},
266 {"COMMANDS_23", EV_COMMANDS_23, "Keyboard EXPL+CTRL+F11", _LC("InputEvent", "Command 23")},
267 {"COMMANDS_24", EV_COMMANDS_24, "Keyboard EXPL+CTRL+F12", _LC("InputEvent", "Command 24")},
268 {"COMMANDS_25", EV_COMMANDS_25, "Keyboard EXPL+SHIFT+F1", _LC("InputEvent", "Command 25")},
269 {"COMMANDS_26", EV_COMMANDS_26, "Keyboard EXPL+SHIFT+F2", _LC("InputEvent", "Command 26")},
270 {"COMMANDS_27", EV_COMMANDS_27, "Keyboard EXPL+SHIFT+F3", _LC("InputEvent", "Command 27")},
271 {"COMMANDS_28", EV_COMMANDS_28, "Keyboard EXPL+SHIFT+F4", _LC("InputEvent", "Command 28")},
272 {"COMMANDS_29", EV_COMMANDS_29, "Keyboard EXPL+SHIFT+F5", _LC("InputEvent", "Command 29")},
273 {"COMMANDS_30", EV_COMMANDS_30, "Keyboard EXPL+SHIFT+F6", _LC("InputEvent", "Command 30")},
274 {"COMMANDS_31", EV_COMMANDS_31, "Keyboard EXPL+SHIFT+F7", _LC("InputEvent", "Command 31")},
275 {"COMMANDS_32", EV_COMMANDS_32, "Keyboard EXPL+SHIFT+F8", _LC("InputEvent", "Command 32")},
276 {"COMMANDS_33", EV_COMMANDS_33, "Keyboard EXPL+SHIFT+F9", _LC("InputEvent", "Command 33")},
277 {"COMMANDS_34", EV_COMMANDS_34, "Keyboard EXPL+SHIFT+F10", _LC("InputEvent", "Command 34")},
278 {"COMMANDS_35", EV_COMMANDS_35, "Keyboard EXPL+SHIFT+F11", _LC("InputEvent", "Command 35")},
279 {"COMMANDS_36", EV_COMMANDS_36, "Keyboard EXPL+SHIFT+F12", _LC("InputEvent", "Command 36")},
280 {"COMMANDS_37", EV_COMMANDS_37, "Keyboard EXPL+ALT+F1", _LC("InputEvent", "Command 37")},
281 {"COMMANDS_38", EV_COMMANDS_38, "Keyboard EXPL+ALT+F2", _LC("InputEvent", "Command 38")},
282 {"COMMANDS_39", EV_COMMANDS_39, "Keyboard EXPL+ALT+F3", _LC("InputEvent", "Command 39")},
283 {"COMMANDS_40", EV_COMMANDS_40, "Keyboard EXPL+ALT+F4", _LC("InputEvent", "Command 40")},
284 {"COMMANDS_41", EV_COMMANDS_41, "Keyboard EXPL+ALT+F5", _LC("InputEvent", "Command 41")},
285 {"COMMANDS_42", EV_COMMANDS_42, "Keyboard EXPL+ALT+F6", _LC("InputEvent", "Command 42")},
286 {"COMMANDS_43", EV_COMMANDS_43, "Keyboard EXPL+ALT+F7", _LC("InputEvent", "Command 43")},
287 {"COMMANDS_44", EV_COMMANDS_44, "Keyboard EXPL+ALT+F8", _LC("InputEvent", "Command 44")},
288 {"COMMANDS_45", EV_COMMANDS_45, "Keyboard EXPL+ALT+F9", _LC("InputEvent", "Command 45")},
289 {"COMMANDS_46", EV_COMMANDS_46, "Keyboard EXPL+ALT+F10", _LC("InputEvent", "Command 46")},
290 {"COMMANDS_47", EV_COMMANDS_47, "Keyboard EXPL+ALT+F11", _LC("InputEvent", "Command 47")},
291 {"COMMANDS_48", EV_COMMANDS_48, "Keyboard EXPL+ALT+F12", _LC("InputEvent", "Command 48")},
292 {"COMMANDS_49", EV_COMMANDS_49, "Keyboard EXPL+CTRL+SHIFT+F1", _LC("InputEvent", "Command 49")},
293 {"COMMANDS_50", EV_COMMANDS_50, "Keyboard EXPL+CTRL+SHIFT+F2", _LC("InputEvent", "Command 50")},
294 {"COMMANDS_51", EV_COMMANDS_51, "Keyboard EXPL+CTRL+SHIFT+F3", _LC("InputEvent", "Command 51")},
295 {"COMMANDS_52", EV_COMMANDS_52, "Keyboard EXPL+CTRL+SHIFT+F4", _LC("InputEvent", "Command 52")},
296 {"COMMANDS_53", EV_COMMANDS_53, "Keyboard EXPL+CTRL+SHIFT+F5", _LC("InputEvent", "Command 53")},
297 {"COMMANDS_54", EV_COMMANDS_54, "Keyboard EXPL+CTRL+SHIFT+F6", _LC("InputEvent", "Command 54")},
298 {"COMMANDS_55", EV_COMMANDS_55, "Keyboard EXPL+CTRL+SHIFT+F7", _LC("InputEvent", "Command 55")},
299 {"COMMANDS_56", EV_COMMANDS_56, "Keyboard EXPL+CTRL+SHIFT+F8", _LC("InputEvent", "Command 56")},
300 {"COMMANDS_57", EV_COMMANDS_57, "Keyboard EXPL+CTRL+SHIFT+F9", _LC("InputEvent", "Command 57")},
301 {"COMMANDS_58", EV_COMMANDS_58, "Keyboard EXPL+CTRL+SHIFT+F10", _LC("InputEvent", "Command 58")},
302 {"COMMANDS_59", EV_COMMANDS_59, "Keyboard EXPL+CTRL+SHIFT+F11", _LC("InputEvent", "Command 59")},
303 {"COMMANDS_60", EV_COMMANDS_60, "Keyboard EXPL+CTRL+SHIFT+F12", _LC("InputEvent", "Command 60")},
304 {"COMMANDS_61", EV_COMMANDS_61, "Keyboard EXPL+CTRL+ALT+F1", _LC("InputEvent", "Command 61")},
305 {"COMMANDS_62", EV_COMMANDS_62, "Keyboard EXPL+CTRL+ALT+F2", _LC("InputEvent", "Command 62")},
306 {"COMMANDS_63", EV_COMMANDS_63, "Keyboard EXPL+CTRL+ALT+F3", _LC("InputEvent", "Command 63")},
307 {"COMMANDS_64", EV_COMMANDS_64, "Keyboard EXPL+CTRL+ALT+F4", _LC("InputEvent", "Command 64")},
308 {"COMMANDS_65", EV_COMMANDS_65, "Keyboard EXPL+CTRL+ALT+F5", _LC("InputEvent", "Command 65")},
309 {"COMMANDS_66", EV_COMMANDS_66, "Keyboard EXPL+CTRL+ALT+F6", _LC("InputEvent", "Command 66")},
310 {"COMMANDS_67", EV_COMMANDS_67, "Keyboard EXPL+CTRL+ALT+F7", _LC("InputEvent", "Command 67")},
311 {"COMMANDS_68", EV_COMMANDS_68, "Keyboard EXPL+CTRL+ALT+F8", _LC("InputEvent", "Command 68")},
312 {"COMMANDS_69", EV_COMMANDS_69, "Keyboard EXPL+CTRL+ALT+F9", _LC("InputEvent", "Command 69")},
313 {"COMMANDS_70", EV_COMMANDS_70, "Keyboard EXPL+CTRL+ALT+F10", _LC("InputEvent", "Command 70")},
314 {"COMMANDS_71", EV_COMMANDS_71, "Keyboard EXPL+CTRL+ALT+F11", _LC("InputEvent", "Command 71")},
315 {"COMMANDS_72", EV_COMMANDS_72, "Keyboard EXPL+CTRL+ALT+F12", _LC("InputEvent", "Command 72")},
316 {"COMMANDS_73", EV_COMMANDS_73, "Keyboard EXPL+CTRL+SHIFT+ALT+F1",_LC("InputEvent", "Command 73")},
317 {"COMMANDS_74", EV_COMMANDS_74, "Keyboard EXPL+CTRL+SHIFT+ALT+F2",_LC("InputEvent", "Command 74")},
318 {"COMMANDS_75", EV_COMMANDS_75, "Keyboard EXPL+CTRL+SHIFT+ALT+F3",_LC("InputEvent", "Command 75")},
319 {"COMMANDS_76", EV_COMMANDS_76, "Keyboard EXPL+CTRL+SHIFT+ALT+F4",_LC("InputEvent", "Command 76")},
320 {"COMMANDS_77", EV_COMMANDS_77, "Keyboard EXPL+CTRL+SHIFT+ALT+F5",_LC("InputEvent", "Command 77")},
321 {"COMMANDS_78", EV_COMMANDS_78, "Keyboard EXPL+CTRL+SHIFT+ALT+F6",_LC("InputEvent", "Command 78")},
322 {"COMMANDS_79", EV_COMMANDS_79, "Keyboard EXPL+CTRL+SHIFT+ALT+F7",_LC("InputEvent", "Command 79")},
323 {"COMMANDS_80", EV_COMMANDS_80, "Keyboard EXPL+CTRL+SHIFT+ALT+F8",_LC("InputEvent", "Command 80")},
324 {"COMMANDS_81", EV_COMMANDS_81, "Keyboard EXPL+CTRL+SHIFT+ALT+F9",_LC("InputEvent", "Command 81")},
325 {"COMMANDS_82", EV_COMMANDS_82, "Keyboard EXPL+CTRL+SHIFT+ALT+F10",_LC("InputEvent", "Command 82")},
326 {"COMMANDS_83", EV_COMMANDS_83, "Keyboard EXPL+CTRL+SHIFT+ALT+F11",_LC("InputEvent", "Command 83")},
327 {"COMMANDS_84", EV_COMMANDS_84, "Keyboard EXPL+CTRL+SHIFT+ALT+F12",_LC("InputEvent", "Command 84")},
328
329 // Character
330 {"CHARACTER_BACKWARDS", EV_CHARACTER_BACKWARDS, "Keyboard S", _LC("InputEvent", "step backwards with the character")},
331 {"CHARACTER_FORWARD", EV_CHARACTER_FORWARD, "Keyboard W", _LC("InputEvent", "step forward with the character")},
332 {"CHARACTER_JUMP", EV_CHARACTER_JUMP, "Keyboard SPACE", _LC("InputEvent", "let the character jump")},
333 {"CHARACTER_LEFT", EV_CHARACTER_LEFT, "Keyboard LEFT", _LC("InputEvent", "rotate character left")},
334 {"CHARACTER_RIGHT", EV_CHARACTER_RIGHT, "Keyboard RIGHT", _LC("InputEvent", "rotate character right")},
335 {"CHARACTER_RUN", EV_CHARACTER_RUN, "Keyboard SHIFT+W", _LC("InputEvent", "let the character run")},
336 {"CHARACTER_SIDESTEP_LEFT", EV_CHARACTER_SIDESTEP_LEFT, "Keyboard A", _LC("InputEvent", "sidestep to the left")},
337 {"CHARACTER_SIDESTEP_RIGHT", EV_CHARACTER_SIDESTEP_RIGHT, "Keyboard D", _LC("InputEvent", "sidestep to the right")},
338 {"CHARACTER_ROT_UP", EV_CHARACTER_ROT_UP, "Keyboard UP", _LC("InputEvent", "rotate view up")},
339 {"CHARACTER_ROT_DOWN", EV_CHARACTER_ROT_DOWN, "Keyboard DOWN", _LC("InputEvent", "rotate view down")},
340
341 // Camera
342 {"CAMERA_CHANGE", EV_CAMERA_CHANGE, "Keyboard EXPL+C", _LC("InputEvent", "change camera mode")},
343 {"CAMERA_LOOKBACK", EV_CAMERA_LOOKBACK, "Keyboard NUMPAD1", _LC("InputEvent", "look back (toggles between normal and lookback)")},
344 {"CAMERA_RESET", EV_CAMERA_RESET, "Keyboard NUMPAD5", _LC("InputEvent", "reset the camera position")},
345 {"CAMERA_ROTATE_DOWN", EV_CAMERA_ROTATE_DOWN, "Keyboard NUMPAD2", _LC("InputEvent", "rotate camera down")},
346 {"CAMERA_ROTATE_LEFT", EV_CAMERA_ROTATE_LEFT, "Keyboard NUMPAD4", _LC("InputEvent", "rotate camera left")},
347 {"CAMERA_ROTATE_RIGHT", EV_CAMERA_ROTATE_RIGHT, "Keyboard NUMPAD6", _LC("InputEvent", "rotate camera right")},
348 {"CAMERA_ROTATE_UP", EV_CAMERA_ROTATE_UP, "Keyboard NUMPAD8", _LC("InputEvent", "rotate camera up")},
349 {"CAMERA_ZOOM_IN", EV_CAMERA_ZOOM_IN, "Keyboard EXPL+NUMPAD9", _LC("InputEvent", "zoom camera in")},
350 {"CAMERA_ZOOM_IN_FAST", EV_CAMERA_ZOOM_IN_FAST, "Keyboard SHIFT+NUMPAD9", _LC("InputEvent", "zoom camera in faster")},
351 {"CAMERA_ZOOM_OUT", EV_CAMERA_ZOOM_OUT, "Keyboard EXPL+NUMPAD3", _LC("InputEvent", "zoom camera out")},
352 {"CAMERA_ZOOM_OUT_FAST", EV_CAMERA_ZOOM_OUT_FAST, "Keyboard SHIFT+NUMPAD3", _LC("InputEvent", "zoom camera out faster")},
353 {"CAMERA_FREE_MODE_FIX", EV_CAMERA_FREE_MODE_FIX, "Keyboard EXPL+ALT+C", _LC("InputEvent", "fix the camera to a position")},
354 {"CAMERA_FREE_MODE", EV_CAMERA_FREE_MODE, "Keyboard EXPL+SHIFT+C", _LC("InputEvent", "enable / disable free camera mode")},
355 {"CAMERA_UP", EV_CAMERA_UP, "Keyboard Q", _LC("InputEvent", "move camera up")},
356 {"CAMERA_DOWN", EV_CAMERA_DOWN, "Keyboard Z", _LC("InputEvent", "move camera down")},
357
358 // Sky
359 {"SKY_DECREASE_TIME", EV_SKY_DECREASE_TIME, "Keyboard EXPL+SUBTRACT", _LC("InputEvent", "decrease day-time")},
360 {"SKY_DECREASE_TIME_FAST", EV_SKY_DECREASE_TIME_FAST, "Keyboard SHIFT+SUBTRACT", _LC("InputEvent", "decrease day-time a lot faster")},
361 {"SKY_INCREASE_TIME", EV_SKY_INCREASE_TIME, "Keyboard EXPL+ADD", _LC("InputEvent", "increase day-time")},
362 {"SKY_INCREASE_TIME_FAST", EV_SKY_INCREASE_TIME_FAST, "Keyboard SHIFT+ADD", _LC("InputEvent", "increase day-time a lot faster")},
363
364 // Grass
365 {"GRASS_LESS", EV_GRASS_LESS, "", _LC("InputEvent", "EXPERIMENTAL: remove some grass")},
366 {"GRASS_MORE", EV_GRASS_MORE, "", _LC("InputEvent", "EXPERIMENTAL: add some grass")},
367 {"GRASS_MOST", EV_GRASS_MOST, "", _LC("InputEvent", "EXPERIMENTAL: set maximum amount of grass")},
368 {"GRASS_NONE", EV_GRASS_NONE, "", _LC("InputEvent", "EXPERIMENTAL: remove grass completely")},
369 {"GRASS_SAVE", EV_GRASS_SAVE, "", _LC("InputEvent", "EXPERIMENTAL: save changes to the grass density image")},
370
371 // Survey map
372 {"SURVEY_MAP_TOGGLE_ICONS", EV_SURVEY_MAP_TOGGLE_ICONS, "Keyboard EXPL+CTRL+SHIFT+ALT+TAB",_LC("InputEvent", "toggle map icons")},
373 {"SURVEY_MAP_TOGGLE", EV_SURVEY_MAP_TOGGLE, "Keyboard EXPL+CTRL+SHIFT+TAB", _LC("InputEvent", "toggle map")},
374 {"SURVEY_MAP_CYCLE", EV_SURVEY_MAP_CYCLE, "Keyboard EXPL+TAB", _LC("InputEvent", "cycle map modes")},
375 {"SURVEY_MAP_ZOOM_IN", EV_SURVEY_MAP_ZOOM_IN, "Keyboard EXPL+CTRL+TAB", _LC("InputEvent", "zoom in")},
376 {"SURVEY_MAP_ZOOM_OUT", EV_SURVEY_MAP_ZOOM_OUT, "Keyboard EXPL+SHIFT+TAB", _LC("InputEvent", "zoom out")},
377
378 // Menu
379 {"MENU_DOWN", EV_MENU_DOWN, "Keyboard DOWN", _LC("InputEvent", "select next element in current category")},
380 {"MENU_LEFT", EV_MENU_LEFT, "Keyboard LEFT", _LC("InputEvent", "select previous category")},
381 {"MENU_RIGHT", EV_MENU_RIGHT, "Keyboard RIGHT", _LC("InputEvent", "select next category")},
382 {"MENU_SELECT", EV_MENU_SELECT, "Keyboard EXPL+RETURN", _LC("InputEvent", "select focussed item and close menu")},
383 {"MENU_UP", EV_MENU_UP, "Keyboard UP", _LC("InputEvent", "select previous element in current category")},
384
385 // Truck editing
386 {"TRUCKEDIT_RELOAD", EV_TRUCKEDIT_RELOAD, "Keyboard EXPL+SHIFT+CTRL+R", _LC("InputEvent", "reload truck")},
387
388 // Road editing
389 {"ROAD_EDITOR_POINT_INSERT", EV_ROAD_EDITOR_POINT_INSERT, "Keyboard EXPL+INSERT", _LC("InputEvent", "insert road point") },
390 {"ROAD_EDITOR_POINT_GOTO", EV_ROAD_EDITOR_POINT_GOTO, "Keyboard EXPL+G", _LC("InputEvent", "go to road point") },
391 {"ROAD_EDITOR_POINT_SET_POS", EV_ROAD_EDITOR_POINT_SET_POS, "Keyboard EXPL+M", _LC("InputEvent", "set road point position") },
392 {"ROAD_EDITOR_POINT_DELETE", EV_ROAD_EDITOR_POINT_DELETE, "Keyboard EXPL+DELETE", _LC("InputEvent", "delete road point") },
393 {"ROAD_EDITOR_REBUILD_MESH", EV_ROAD_EDITOR_REBUILD_MESH, "Keyboard EXPL+B", _LC("InputEvent", "regenerate road mesh") },
394
395 // The end, DO NOT MODIFY
396 {"", -1, "", ""},
397};
398
399#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
400#define strnlen(str,len) strlen(str)
401#endif
402
403//Use this define to signify OIS will be used as a DLL
404//(so that dll import/export macros are in effect)
405#define OIS_DYNAMIC_LIB
406#include <OIS.h>
407
408#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
409#include <X11/Xlib.h>
410//#include <linux/LinuxMouse.h>
411#endif
412
413using namespace std;
414using namespace Ogre;
415using namespace OIS;
416
417const std::string InputEngine::DEFAULT_MAPFILE = "input.map";
418
420 free_joysticks(0)
421 , mForceFeedback(0)
422 , mInputManager(0)
423 , mKeyboard(0)
424 , mMouse(0)
425 , uniqueCounter(0)
426{
427 for (int i = 0; i < MAX_JOYSTICKS; i++)
428 mJoy[i] = 0;
429
430 LOG("*** Loading OIS ***");
431
432 initAllKeys();
433 setup();
434 windowResized(App::GetAppContext()->GetRenderWindow());
435}
436
441
443{
444 if (mInputManager)
445 {
446 LOG("*** Terminating OIS ***");
447 if (mMouse)
448 {
449 mInputManager->destroyInputObject(mMouse);
450 mMouse = 0;
451 }
452 if (mKeyboard)
453 {
454 mInputManager->destroyInputObject(mKeyboard);
455 mKeyboard = 0;
456 }
457 if (mJoy)
458 {
459 for (int i = 0; i < MAX_JOYSTICKS; i++)
460 {
461 if (!mJoy[i])
462 continue;
463 mInputManager->destroyInputObject(mJoy[i]);
464 mJoy[i] = 0;
465 }
466 }
467
468 OIS::InputManager::destroyInputSystem(mInputManager);
469 mInputManager = 0;
470 }
471}
472
474{
475 size_t hWnd = 0;
476 App::GetAppContext()->GetRenderWindow()->getCustomAttribute("WINDOW", &hWnd);
477
478 LOG("*** Initializing OIS ***");
479
480 //try to delete old ones first (linux can only handle one at a time)
481 destroy();
482
483 ParamList pl;
484 pl.insert(OIS::ParamList::value_type("WINDOW", TOSTRING(hWnd)));
485 if (App::io_input_grab_mode->getEnum<IoInputGrabMode>() != RoR::IoInputGrabMode::ALL)
486 {
487#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
488 pl.insert(OIS::ParamList::value_type("x11_mouse_hide", "true"));
489 pl.insert(OIS::ParamList::value_type("XAutoRepeatOn", "false"));
490 pl.insert(OIS::ParamList::value_type("x11_mouse_grab", "false"));
491 pl.insert(OIS::ParamList::value_type("x11_keyboard_grab", "false"));
492#else
493 pl.insert(OIS::ParamList::value_type("w32_mouse", "DISCL_FOREGROUND"));
494 pl.insert(OIS::ParamList::value_type("w32_mouse", "DISCL_NONEXCLUSIVE"));
495 pl.insert(OIS::ParamList::value_type("w32_keyboard", "DISCL_FOREGROUND"));
496 pl.insert(OIS::ParamList::value_type("w32_keyboard", "DISCL_NONEXCLUSIVE"));
497#endif // LINUX
498 }
499
500#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
501 if (App::io_input_grab_mode->getEnum<IoInputGrabMode>() != IoInputGrabMode::ALL)
502 {
503 ShowCursor(FALSE);
504 }
505 else
506 {
507 ShowCursor(TRUE); // To make `MSG_APP_REINIT_INPUT_REQUESTED` work correctly
508 }
509#endif
510
511 mInputManager = OIS::InputManager::createInputSystem(pl);
512
513 //Print debugging information
514 unsigned int v = mInputManager->getVersionNumber();
515 LOG("OIS Version: " + TOSTRING(v>>16) + String(".") + TOSTRING((v>>8) & 0x000000FF) + String(".") + TOSTRING(v & 0x000000FF));
516 LOG("+ Release Name: " + mInputManager->getVersionName());
517 LOG("+ Manager: " + mInputManager->inputSystemName());
518 LOG("+ Total Keyboards: " + TOSTRING(mInputManager->getNumberOfDevices(OISKeyboard)));
519 LOG("+ Total Mice: " + TOSTRING(mInputManager->getNumberOfDevices(OISMouse)));
520 LOG("+ Total JoySticks: " + TOSTRING(mInputManager->getNumberOfDevices(OISJoyStick)));
521
522 //List all devices
523 OIS::DeviceList deviceList = mInputManager->listFreeDevices();
524 for (OIS::DeviceList::iterator i = deviceList.begin(); i != deviceList.end(); ++i)
525 LOG("* Device: " + String(mOISDeviceType[i->first]) + String(" Vendor: ") + i->second);
526
527 //Create all devices (We only catch joystick exceptions here, as, most people have Key/Mouse)
528 mKeyboard = 0;
529
530 try
531 {
532 mKeyboard = static_cast<Keyboard*>(mInputManager->createInputObject(OISKeyboard, true));
533 mKeyboard->setTextTranslation(OIS::Keyboard::Unicode);
534 }
535 catch (OIS::Exception& ex)
536 {
537 LOG(String("Exception raised on keyboard creation: ") + String(ex.eText));
538 }
539
540
541 try
542 {
543 //This demo uses at most 10 joysticks - use old way to create (i.e. disregard vendor)
544 int numSticks = std::min(mInputManager->getNumberOfDevices(OISJoyStick), 10);
545 free_joysticks = 0;
546 for (int i = 0; i < numSticks; ++i)
547 {
548 mJoy[i] = (JoyStick*)mInputManager->createInputObject(OISJoyStick, true);
550 //create force feedback too
551 //here, we take the first device we can get, but we could take a device index
552 if (!mForceFeedback)
553 mForceFeedback = (OIS::ForceFeedback*)mJoy[i]->queryInterface(OIS::Interface::ForceFeedback);
554
555 LOG("Creating Joystick " + TOSTRING(i + 1) + " (" + mJoy[i]->vendor() + ")");
556 LOG("* Axes: " + TOSTRING(mJoy[i]->getNumberOfComponents(OIS_Axis)));
557 LOG("* Sliders: " + TOSTRING(mJoy[i]->getNumberOfComponents(OIS_Slider)));
558 LOG("* POV/HATs: " + TOSTRING(mJoy[i]->getNumberOfComponents(OIS_POV)));
559 LOG("* Buttons: " + TOSTRING(mJoy[i]->getNumberOfComponents(OIS_Button)));
560 LOG("* Vector3: " + TOSTRING(mJoy[i]->getNumberOfComponents(OIS_Vector3)));
561 }
562 }
563 catch (OIS::Exception& ex)
564 {
565 LOG(String("Exception raised on joystick creation: ") + String(ex.eText));
566 }
567
568 try
569 {
570 mMouse = static_cast<Mouse*>(mInputManager->createInputObject(OISMouse, true));
571 }
572 catch (OIS::Exception& ex)
573 {
574 LOG(String("Exception raised on mouse creation: ") + String(ex.eText));
575 }
576
577
578 if (free_joysticks)
579 {
580 for (int i = 0; i < free_joysticks; i++)
581 joyState[i] = mJoy[i]->getJoyStickState();
582 }
583
584 // set the mouse to the middle of the screen, hackish!
585#if _WIN32
586 // under linux, this will not work and the cursor will never reach (0,0)
587 if (mMouse && RoR::App::GetAppContext()->GetRenderWindow())
588 {
589 OIS::MouseState& mutableMouseState = const_cast<OIS::MouseState &>(mMouse->getMouseState());
590 mutableMouseState.X.abs = RoR::App::GetAppContext()->GetRenderWindow()->getWidth() * 0.5f;
591 mutableMouseState.Y.abs = RoR::App::GetAppContext()->GetRenderWindow()->getHeight() * 0.5f;
592 }
593#endif // _WIN32
594
595 // load default mappings
596 this->loadConfigFile(-1);
597
598 // then load device (+OS) specific mappings
599 for (int i = 0; i < free_joysticks; ++i)
600 {
601 this->loadConfigFile(i);
602 }
604}
605
607{
608 // When window regains focus, OIS sends a fake LMB-down event, which is never followed by a LMB-up event.
609 // See commentary in `resetKeysAndMouseButtons()`
610 // To work around, we keep internal button states and pay attention not to get them polluted by OIS.
611 // -----------------------------------------------------------------------------------------------------
612
613 mouseState.width = (int)App::GetAppContext()->GetRenderWindow()->getWidth();
614 mouseState.height = (int)App::GetAppContext()->GetRenderWindow()->getHeight();
615
616 return mouseState;
617}
618
619String InputEngine::getKeyNameForKeyCode(OIS::KeyCode keycode)
620{
621 if (keycode == KC_LSHIFT || keycode == KC_RSHIFT)
622 return "SHIFT";
623 if (keycode == KC_LCONTROL || keycode == KC_RCONTROL)
624 return "CTRL";
625 if (keycode == KC_LMENU || keycode == KC_RMENU)
626 return "ALT";
627 for (allit = allkeys.begin(); allit != allkeys.end(); allit++)
628 {
629 if (allit->second == keycode)
630 return allit->first;
631 }
632 return "unknown";
633}
634
636{
637 mKeyboard->capture();
638 mMouse->capture();
639
640 for (int i = 0; i < free_joysticks; i++)
641 {
642 if (mJoy[i])
643 {
644 mJoy[i]->capture();
645 }
646 }
647
649}
650
651void InputEngine::windowResized(Ogre::RenderWindow* rw)
652{
653 //update mouse area
654 unsigned int width, height, depth;
655 int left, top;
656 rw->getMetrics(width, height, depth, left, top);
657 const OIS::MouseState& ms = mMouse->getMouseState();
658 ms.width = width;
659 ms.height = height;
660}
661
662void InputEngine::SetKeyboardListener(OIS::KeyListener* keyboard_listener)
663{
664 ROR_ASSERT(mKeyboard != nullptr);
665 mKeyboard->setEventCallback(keyboard_listener);
666}
667
668void InputEngine::SetMouseListener(OIS::MouseListener* mouse_listener)
669{
670 ROR_ASSERT(mMouse != nullptr);
671 mMouse->setEventCallback(mouse_listener);
672}
673
674void InputEngine::SetJoystickListener(OIS::JoyStickListener* obj)
675{
676 for (int i = 0; i < free_joysticks; i++)
677 {
678 mJoy[i]->setEventCallback(obj);
679 }
680}
681
682/* --- Joystick Events ------------------------------------------ */
683void InputEngine::ProcessJoystickEvent(const OIS::JoyStickEvent& arg)
684{
685 int i = arg.device->getID();
686 if (i < 0 || i >= MAX_JOYSTICKS)
687 i = 0;
688 joyState[i] = arg.state;
689}
690
691/* --- Key Events ------------------------------------------ */
692void InputEngine::ProcessKeyPress(const OIS::KeyEvent& arg)
693{
694 keyState[arg.key] = 1;
695}
696
697void InputEngine::ProcessKeyRelease(const OIS::KeyEvent& arg)
698{
699 keyState[arg.key] = 0;
700}
701
702/* --- Mouse Events ------------------------------------------ */
703void InputEngine::processMouseMotionEvent(const OIS::MouseEvent& arg)
704{
705 // Only pick position info; button info may be dirty, see commentary in `getMouseState()`
706 mouseState.X = arg.state.X;
707 mouseState.Y = arg.state.Y;
708 mouseState.Z = arg.state.Z;
709}
710
711void InputEngine::processMousePressEvent(const OIS::MouseEvent& arg, OIS::MouseButtonID _id)
712{
713 // Skip false 'LMB press' event after restoring window focus; see commentary in `resetKeysAndMouseButtons()`.
714 if (_id == OIS::MB_Left)
715 {
717 {
718 return;
719 }
721 }
722
723 // Only update the one particular button, OIS's persistent state may be dirty, see commentary in `getMouseState()`
724 BitMask_t btnmask = 1 << _id;
725 BITMASK_SET_1(mouseState.buttons, btnmask);
726}
727
728void InputEngine::processMouseReleaseEvent(const OIS::MouseEvent& arg, OIS::MouseButtonID _id)
729{
730 // Only update the one particular button, OIS's persistent state may be dirty, see commentary in `getMouseState()`
731 BitMask_t btnmask = 1 << _id;
732 BITMASK_SET_0(mouseState.buttons, btnmask);
733}
734
735/* --- Custom Methods ------------------------------------------ */
737{
738 for (std::map<int, bool>::iterator iter = keyState.begin(); iter != keyState.end(); ++iter)
739 {
740 iter->second = false;
741 }
742
743 // OIS WORKAROUND: After a window focus is restored for the 2nd+ time, OIS delivers a fabricated 'LMB pressed' event,
744 // without ever sending matching 'LMB released', see analysis: https://github.com/RigsOfRods/rigs-of-rods/pull/3184#issuecomment-2380397463
745 // This has a very prominent negative effect, see https://github.com/RigsOfRods/rigs-of-rods/issues/2468
746 // There's no way to recognize the event as fake, we must track number of frames and LMB presses since last reset.
749
750 // Reset internal button states; see commentary in `getMouseState()`
751 mouseState.buttons = 0;
752}
753
755{
756 event_values_simulated[eventID] = value;
757}
758
760{
761 event_states_supressed[eventID] = supress;
762}
763
765{
766 return (getEventValue(eventID) > 0.5f);
767}
768
769bool InputEngine::getEventBoolValueBounce(int eventID, float time)
770{
771 if (event_times[eventID] > 0)
772 return false;
773 else
774 {
775 bool res = getEventBoolValue(eventID);
776 if (res)
777 event_times[eventID] = time;
778 return res;
779 }
780}
781
783{
784 return event_times[eventID];
785}
786
788{
789 for (std::map<int, float>::iterator it = event_times.begin(); it != event_times.end(); it++)
790 {
791 if (it->second > 0)
792 it->second -= dt;
793 //else
794 // erase element?
795 }
796}
797
798float InputEngine::deadZone(float axisValue, float dz)
799{
800 // no deadzone?
801 if (dz < 0.0001f)
802 return axisValue;
803
804 // check for deadzone
805 if (fabs(axisValue) < dz)
806 // dead zone case
807 return 0.0f;
808 else
809 // non-deadzone, remap the remaining part
810 return (axisValue - dz) * (1.0f / (1.0f - dz));
811}
812
813float InputEngine::axisLinearity(float axisValue, float linearity)
814{
815 return (axisValue * linearity);
816}
817
818float InputEngine::logval(float val)
819{
820 if (val > 0)
821 return log10(1.0 / (1.1 - val)) / 1.0;
822 if (val == 0)
823 return 0;
824 return -log10(1.0 / (1.1 + val)) / 1.0;
825}
826
828{
829 std::vector<event_trigger_t>& t_vec = events[eventID];
830 if (t_vec.size() > 0)
831 {
832 // TODO: handle multiple mappings for one event code - currently we only check the first one.
833 return this->composeEventCommandString(t_vec[0]);
834 }
835 return "";
836}
837
839{
840 std::string result = regex_replace(App::GetInputEngine()->getEventCommand(eventID).c_str(), std::regex("EXPL\\+"), "");
841 return result;
842}
843
845{
846 return this->composeEventCommandString(evt);
847}
848
850{
851 std::vector<event_trigger_t>& t_vec = events[eventID];
852 if (t_vec.size() > 0)
853 {
854 // TODO: handle multiple mappings for one event code - currently we only check the first one.
855 return this->composeEventConfigString(t_vec[0]);
856 }
857 return "";
858}
859
861{
862 for (int i = 0; i < EV_MODE_LAST; i++)
863 {
864 if (eventInfo[i].eventID == eventID)
865 {
866 return eventInfo[i].defaultKey;
867 }
868 }
869 return "";
870}
871
873{
874 switch (trig.eventtype)
875 {
876 case ET_Keyboard:
878 return trig.configline; // Configline contains the key/button
879
880 case ET_JoystickPov:
881 return fmt::format("{} {}", trig.joystickPovNumber, trig.configline); // Configline contains the direction - display it.
882
884 return fmt::format("X {}", trig.joystickSliderNumber); // Must show axis separately. Configline contains just the options.
885
887 return fmt::format("Y {}", trig.joystickSliderNumber); // Must show axis separately. Configline contains just the options.
888
889 default: // Joystick axes
890 return fmt::format("{}", trig.joystickAxisNumber); // Configline contains just the options.
891 }
892}
893
895{
896 switch (trig.eventtype)
897 {
898 case ET_Keyboard:
900 case ET_JoystickPov:
901 return this->composeEventCommandString(trig);
902
903 // Sliders: Include redundant X/Y and options.
905 return fmt::format("X {} {}", trig.joystickSliderNumber, trig.configline); // Configline contains just the options.
907 return fmt::format("Y {} {}", trig.joystickSliderNumber, trig.configline); // Configline contains just the options.
908
909 // Joystick axes and sliders - include options.
910 default:
911 return fmt::format("{} {}", trig.joystickAxisNumber, trig.configline); // Configline contains just the options.
912 }
913}
914
916{
917 std::vector<event_trigger_t> t_vec = events[eventID];
918 if (t_vec.size() > 0)
919 {
920 if (t_vec[0].eventtype != ET_NONE) // TODO: handle multiple mappings for one event code - currently we only check the first one.
921 return true;
922 }
923 return false;
924}
925
927{
928 std::vector<event_trigger_t> t_vec = events[eventID];
929 for (std::vector<event_trigger_t>::iterator i = t_vec.begin(); i != t_vec.end(); i++)
930 {
931 event_trigger_t t = *i;
932 if (t.eventtype == ET_Keyboard)
933 return t.keyCode;
934 }
935 return -1;
936}
937
939{
940 std::vector<event_trigger_t> t_vec = events[eventID];
941 if (t_vec.size() > 0)
942 {
943 //loop through all eventtypes, because we want to find a analog device wether it is the first device or not
944 //this means a analog device is always preferred over a digital one
945 for (unsigned int i = 0; i < t_vec.size(); i++)
946 {
947 if ((t_vec[i].eventtype == ET_MouseAxisX
948 || t_vec[i].eventtype == ET_MouseAxisY
949 || t_vec[i].eventtype == ET_MouseAxisZ
950 || t_vec[i].eventtype == ET_JoystickAxisAbs
951 || t_vec[i].eventtype == ET_JoystickAxisRel
952 || t_vec[i].eventtype == ET_JoystickSliderX
953 || t_vec[i].eventtype == ET_JoystickSliderY)
954 //check if value comes from analog device
955 //this way, only valid events (e.g. joystick mapped, but unplugged) are recognized as analog events
956 && getEventValue(eventID, true, InputSourceType::IST_ANALOG) != 0.0)
957 {
958 return true;
959 }
960 }
961 }
962 return false;
963}
964
965float InputEngine::getEventValue(int eventID, bool pure, InputSourceType valueSource /*= InputSourceType::IST_ANY*/)
966{
967 const float simulatedValue = event_values_simulated[eventID];
968 if (simulatedValue != 0.f)
969 return simulatedValue;
970
971 if (event_states_supressed[eventID])
972 return 0.f;
973
974 float returnValue = 0;
975 std::vector<event_trigger_t> t_vec = events[eventID];
976 float value = 0;
977 for (std::vector<event_trigger_t>::iterator i = t_vec.begin(); i != t_vec.end(); i++)
978 {
979 event_trigger_t t = *i;
980
981 if (valueSource == InputSourceType::IST_DIGITAL || valueSource == InputSourceType::IST_ANY)
982 {
983 switch (t.eventtype)
984 {
985 case ET_NONE:
986 break;
987 case ET_Keyboard:
988 if (!keyState[t.keyCode])
989 break;
990
991 // only use explicite mapping, if two keys with different modifiers exist, i.e. F1 and SHIFT+F1.
992 // check for modificators
993 if (t.explicite)
994 {
995 if (t.ctrl != (keyState[KC_LCONTROL] || keyState[KC_RCONTROL]))
996 break;
997 if (t.shift != (keyState[KC_LSHIFT] || keyState[KC_RSHIFT]))
998 break;
999 if (t.alt != (keyState[KC_LMENU] || keyState[KC_RMENU]))
1000 break;
1001 }
1002 else
1003 {
1004 if (t.ctrl && !(keyState[KC_LCONTROL] || keyState[KC_RCONTROL]))
1005 break;
1006 if (t.shift && !(keyState[KC_LSHIFT] || keyState[KC_RSHIFT]))
1007 break;
1008 if (t.alt && !(keyState[KC_LMENU] || keyState[KC_RMENU]))
1009 break;
1010 }
1011 value = 1;
1012 break;
1013 case ET_MouseButton:
1014 //if (t.mouseButtonNumber == 0)
1015 // TODO: FIXME
1016 value = mouseState.buttonDown(MB_Left);
1017 break;
1018 case ET_JoystickButton:
1019 {
1021 {
1022 value = 0;
1023 continue;
1024 }
1025 if (t.joystickButtonNumber >= (int)mJoy[t.joystickNumber]->getNumberOfComponents(OIS_Button))
1026 {
1027#ifndef NOOGRE
1028 LOG("*** Joystick has not enough buttons for mapping: need button "+TOSTRING(t.joystickButtonNumber) + ", availabe buttons: "+TOSTRING(mJoy[t.joystickNumber]->getNumberOfComponents(OIS_Button)));
1029#endif
1030 value = 0;
1031 continue;
1032 }
1033 value = joyState[t.joystickNumber].mButtons[t.joystickButtonNumber];
1034 }
1035 break;
1036 case ET_JoystickPov:
1037 {
1039 {
1040 value = 0;
1041 continue;
1042 }
1043 if (t.joystickPovNumber >= (int)mJoy[t.joystickNumber]->getNumberOfComponents(OIS_POV))
1044 {
1045#ifndef NOOGRE
1046 LOG("*** Joystick has not enough POVs for mapping: need POV "+TOSTRING(t.joystickPovNumber) + ", availabe POVs: "+TOSTRING(mJoy[t.joystickNumber]->getNumberOfComponents(OIS_POV)));
1047#endif
1048 value = 0;
1049 continue;
1050 }
1052 value = 1;
1053 else
1054 value = 0;
1055 }
1056 break;
1057 }
1058 }
1059 if (valueSource == InputSourceType::IST_ANALOG || valueSource == InputSourceType::IST_ANY)
1060 {
1061 switch (t.eventtype)
1062 {
1063 case ET_MouseAxisX:
1064 value = mouseState.X.abs / 32767;
1065 break;
1066 case ET_MouseAxisY:
1067 value = mouseState.Y.abs / 32767;
1068 break;
1069 case ET_MouseAxisZ:
1070 value = mouseState.Z.abs / 32767;
1071 break;
1072
1073 case ET_JoystickAxisRel:
1074 case ET_JoystickAxisAbs:
1075 {
1077 {
1078 value = 0;
1079 continue;
1080 }
1081 if (t.joystickAxisNumber >= (int)joyState[t.joystickNumber].mAxes.size())
1082 {
1083#ifndef NOOGRE
1084 LOG("*** Joystick has not enough axis for mapping: need axe "+TOSTRING(t.joystickAxisNumber) + ", availabe axis: "+TOSTRING(joyState[t.joystickNumber].mAxes.size()));
1085#endif
1086 value = 0;
1087 continue;
1088 }
1089 Axis axe = joyState[t.joystickNumber].mAxes[t.joystickAxisNumber];
1090
1092 {
1093 value = (float)axe.rel / (float)mJoy[t.joystickNumber]->MAX_AXIS;
1094 }
1095 else
1096 {
1097 value = (float)axe.abs / (float)mJoy[t.joystickNumber]->MAX_AXIS;
1098 switch (t.joystickAxisRegion)
1099 {
1100 case 0:
1101 // normal case, full axis used
1102 value = (value + 1) / 2;
1103 break;
1104 case -1:
1105 // lower range used
1106 if (value > 0)
1107 value = 0;
1108 else
1109 value = -value;
1110 break;
1111 case 1:
1112 // upper range used
1113 if (value < 0)
1114 value = 0;
1115 break;
1116 }
1117
1118 if (t.joystickAxisHalf)
1119 {
1120 // XXX: TODO: write this
1121 //float a = (double)((value+1.0)/2.0);
1122 //float b = (double)(1.0-(value+1.0)/2.0);
1123 //LOG("half: "+TOSTRING(value)+" / "+TOSTRING(a)+" / "+TOSTRING(b));
1124 //no dead zone in half axis
1125 value = (1.0 + value) / 2.0;
1126 if (t.joystickAxisReverse)
1127 value = 1.0 - value;
1128 if (!pure)
1129 value = axisLinearity(value, t.joystickAxisLinearity);
1130 }
1131 else
1132 {
1133 //LOG("not half: "+TOSTRING(value)+" / "+TOSTRING(deadZone(value, t.joystickAxisDeadzone)) +" / "+TOSTRING(t.joystickAxisDeadzone) );
1134 if (t.joystickAxisReverse)
1135 value = 1 - value;
1136 if (!pure)
1137 // no deadzone when using oure value
1138 value = deadZone(value, t.joystickAxisDeadzone);
1139 if (!pure)
1140 value = axisLinearity(value, t.joystickAxisLinearity);
1141 }
1142 // digital mapping of analog axis
1144 if (value >= 0.5)
1145 value = 1;
1146 else
1147 value = 0;
1148 }
1149 }
1150 break;
1151 case ET_JoystickSliderX:
1152 case ET_JoystickSliderY:
1153 {
1155 {
1156 value = 0;
1157 continue;
1158 }
1160 value = (float)joyState[t.joystickNumber].mSliders[t.joystickSliderNumber].abX / (float)mJoy[t.joystickNumber]->MAX_AXIS;
1161 else if (t.eventtype == ET_JoystickSliderY)
1162 value = (float)joyState[t.joystickNumber].mSliders[t.joystickSliderNumber].abY / (float)mJoy[t.joystickNumber]->MAX_AXIS;
1163 value = (value + 1) / 2; // full axis
1165 value = 1.0 - value; // reversed
1166 }
1167 break;
1168 }
1169 }
1170 // only return if grater zero, otherwise check all other bombinations
1171 if (value > returnValue)
1172 returnValue = value;
1173 }
1174 return returnValue;
1175}
1176
1177bool InputEngine::isKeyDown(OIS::KeyCode key)
1178{
1179 if (!mKeyboard)
1180 return false;
1181 return this->mKeyboard->isKeyDown(key);
1182}
1183
1185{
1186 return this->keyState[mod];
1187}
1188
1189bool InputEngine::isKeyDownValueBounce(OIS::KeyCode mod, float time)
1190{
1191 if (event_times[-mod] > 0)
1192 return false;
1193 else
1194 {
1195 bool res = isKeyDown(mod);
1196 if (res)
1197 event_times[-mod] = time;
1198 return res;
1199 }
1200}
1201
1203{
1204 switch (evt.eventtype)
1205 {
1206 case ET_NONE:
1207 return "None";
1208 case ET_Keyboard:
1209 return "Keyboard";
1210 case ET_MouseButton:
1211 case ET_MouseAxisX:
1212 case ET_MouseAxisY:
1213 case ET_MouseAxisZ:
1214 return "Mouse";
1215 case ET_JoystickButton:
1216 case ET_JoystickAxisAbs:
1217 case ET_JoystickAxisRel:
1218 case ET_JoystickPov:
1219 case ET_JoystickSliderX:
1220 case ET_JoystickSliderY:
1221 return "Joystick: " + getJoyVendor(evt.joystickNumber);
1222 }
1223 return "unknown";
1224}
1225
1226// static
1228{
1229 switch (type)
1230 {
1231 case ET_NONE: return "None";
1232 case ET_Keyboard: return "Keyboard";
1233 case ET_MouseButton: return "MouseButton";
1234 case ET_MouseAxisX: return "MouseAxisX";
1235 case ET_MouseAxisY: return "MouseAxisY";
1236 case ET_MouseAxisZ: return "MouseAxisZ";
1237 case ET_JoystickButton: return "JoystickButton";
1238 case ET_JoystickAxisAbs:
1239 case ET_JoystickAxisRel: return "JoystickAxis"; // Default is 'abs', 'rel' is created by option RELATIVE.
1240 case ET_JoystickPov: return "JoystickPov";
1241 case ET_JoystickSliderX:
1242 case ET_JoystickSliderY: return "JoystickSlider"; // Axis is given by special parameter.
1243 default: return "unknown";
1244 }
1245}
1246
1248{
1249 this->addEvent(eventID);
1250 events[eventID].push_back(t);
1251}
1252
1253void InputEngine::addEvent(int eventID)
1254{
1255 uniqueCounter++;
1256
1257 if (eventID == -1)
1258 //unknown event, discard
1259 return;
1260 if (events.find(eventID) == events.end())
1261 {
1262 events[eventID] = std::vector<event_trigger_t>();
1263 event_values_simulated[eventID] = 0.f;
1264 event_states_supressed[eventID] = false;
1265 }
1266}
1267
1268void InputEngine::addEventDefault(int eventID, int deviceID /*= -1*/)
1269{
1270 if (eventID == -1)
1271 //unknown event, discard
1272 return;
1273
1274 std::string line = fmt::format("{} {}", this->eventIDToName(eventID), this->getEventDefaultConfig(eventID));
1275 this->processLine(line.c_str(), deviceID);
1276}
1277
1279{
1280 if (eventID == -1)
1281 //unknown event, discard
1282 return;
1283 if (events.find(eventID) == events.end())
1284 {
1285 events[eventID] = std::vector<event_trigger_t>();
1286 events[eventID].clear();
1287 }
1288 events[eventID].push_back(t);
1289}
1290
1291void InputEngine::eraseEvent(int eventID, const event_trigger_t* t)
1292{
1293 if (events.find(eventID) != events.end())
1294 {
1295 TriggerVec& triggers = events[eventID];
1296 for (size_t i = 0; i < triggers.size(); i++)
1297 {
1298 if (t == &triggers[i])
1299 {
1300 triggers.erase(triggers.begin() + i);
1301 return;
1302 }
1303 }
1304 }
1305}
1306
1308{
1309 if (events.find(eventID) != events.end())
1310 {
1311 events[eventID].clear();
1312 }
1313}
1314
1316{
1317 for (auto& ev_pair: events)
1318 {
1319 if (ev_pair.second.size() > 0)
1320 {
1321 auto itor = ev_pair.second.begin();
1322 while (itor != ev_pair.second.end())
1323 {
1324 if (itor->configDeviceID == deviceID)
1325 itor = ev_pair.second.erase(itor);
1326 else
1327 itor++;
1328 }
1329 }
1330 }
1331}
1332
1334{
1335 events.clear(); // remove all bindings
1336 this->resetKeysAndMouseButtons(); // reset input states
1337}
1338
1339bool InputEngine::processLine(const char* line, int deviceID)
1340{
1341 static String cur_comment = "";
1342
1343 char eventName[256] = "", evtype[256] = "";
1344 const char delimiters[] = "+";
1345 size_t linelen = strnlen(line, 1024);
1346 enum eventtypes eventtype = ET_NONE;
1347
1348 int joyNo = 0;
1349 float defaultDeadzone = 0.1f;
1350 float defaultLinearity = 1.0f;
1351 if (line[0] == ';' || linelen < 5)
1352 {
1353 cur_comment += line;;
1354 return false;
1355 }
1356 sscanf(line, "%s %s", eventName, evtype);
1357 if (strnlen(eventName, 255) == 0 || strnlen(evtype, 255) == 0)
1358 return false;
1359
1360 if (!strncmp(evtype, "Keyboard", 8))
1361 eventtype = ET_Keyboard;
1362 else if (!strncmp(evtype, "MouseButton", 10))
1363 eventtype = ET_MouseButton;
1364 else if (!strncmp(evtype, "MouseAxisX", 9))
1365 eventtype = ET_MouseAxisX;
1366 else if (!strncmp(evtype, "MouseAxisY", 9))
1367 eventtype = ET_MouseAxisY;
1368 else if (!strncmp(evtype, "MouseAxisZ", 9))
1369 eventtype = ET_MouseAxisZ;
1370 else if (!strncmp(evtype, "JoystickButton", 14))
1371 eventtype = ET_JoystickButton;
1372 else if (!strncmp(evtype, "JoystickAxis", 12))
1373 eventtype = ET_JoystickAxisAbs;
1374 //else if (!strncmp(evtype, "JoystickAxis", 250)) eventtype = ET_JoystickAxisRel;
1375 else if (!strncmp(evtype, "JoystickPov", 11))
1376 eventtype = ET_JoystickPov;
1377 else if (!strncmp(evtype, "JoystickSlider", 14))
1378 eventtype = ET_JoystickSliderX;
1379 else if (!strncmp(evtype, "JoystickSliderX", 15))
1380 eventtype = ET_JoystickSliderX;
1381 else if (!strncmp(evtype, "JoystickSliderY", 15))
1382 eventtype = ET_JoystickSliderY;
1383 else if (!strncmp(evtype, "None", 4))
1384 eventtype = ET_NONE;
1385
1386 switch (eventtype)
1387 {
1388 case ET_Keyboard:
1389 {
1390 bool alt = false;
1391 bool shift = false;
1392 bool ctrl = false;
1393 bool expl = false;
1394
1395 char* keycode = 0;
1396 char keycodes[256] = {};
1397 char keycodes_work[256] = {};
1398
1399 OIS::KeyCode key = KC_UNASSIGNED;
1400
1401 sscanf(line, "%s %s %s", eventName, evtype, keycodes);
1402 // separate all keys and construct the key combination
1403 //LOG("try to add key: " + String(eventName)+","+ String(evtype)+","+String(keycodes));
1404 strncpy(keycodes_work, keycodes, 255);
1405 keycodes_work[255] = '\0';
1406 char* token = strtok(keycodes_work, delimiters);
1407
1408 while (token != NULL)
1409 {
1410 if (strncmp(token, "SHIFT", 5) == 0)
1411 shift = true;
1412 else if (strncmp(token, "CTRL", 4) == 0)
1413 ctrl = true;
1414 else if (strncmp(token, "ALT", 3) == 0)
1415 alt = true;
1416 else if (strncmp(token, "EXPL", 4) == 0)
1417 expl = true;
1418 keycode = token;
1419 token = strtok(NULL, delimiters);
1420 }
1421
1422 allit = allkeys.find(keycode);
1423 if (allit == allkeys.end())
1424 {
1425#ifndef NOOGRE
1426 LOG("unknown key: " + string(keycodes));
1427#endif
1428 key = KC_UNASSIGNED;
1429 }
1430 else
1431 {
1432 //LOG("found key: " + string(keycode) + " = " + TOSTRING((int)key));
1433 key = allit->second;
1434 }
1435 int eventID = resolveEventName(String(eventName));
1436 if (eventID == -1)
1437 {
1438 LOG("Error while processing input config: Unknown Event: "+String(eventName));
1439 return false;
1440 }
1441 event_trigger_t t_key = newEvent();
1442 t_key.configDeviceID = deviceID;
1443 t_key.eventtype = ET_Keyboard;
1444 t_key.shift = shift;
1445 t_key.ctrl = ctrl;
1446 t_key.alt = alt;
1447 t_key.keyCode = key;
1448 t_key.explicite = expl;
1449
1450 strncpy(t_key.configline, keycodes, 128);
1451 strncpy(t_key.group, getEventGroup(eventName).c_str(), 128);
1452 strncpy(t_key.tmp_eventname, eventName, 128);
1453
1454 strncpy(t_key.comments, cur_comment.c_str(), 1024);
1455 addEvent(eventID, t_key);
1456
1457 return true;
1458 }
1459 case ET_JoystickButton:
1460 {
1461 int buttonNo = 0;
1462 char tmp2[256] = {};
1463 sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &buttonNo, tmp2);
1464 event_trigger_t t_joy = newEvent();
1465 t_joy.configDeviceID = deviceID;
1466 int eventID = resolveEventName(String(eventName));
1467 if (eventID == -1)
1468 return false;
1470 t_joy.joystickNumber = (deviceID == -1 ? joyNo : deviceID);
1471 t_joy.joystickButtonNumber = buttonNo;
1472 if (!strcmp(tmp2, "!NEW!"))
1473 {
1474 strncpy(t_joy.configline, tmp2, 128);
1475 }
1476 else
1477 {
1478 char tmp[256] = {};
1479 sprintf(tmp, "%d", buttonNo);
1480 strncpy(t_joy.configline, tmp, 128);
1481 }
1482 strncpy(t_joy.group, getEventGroup(eventName).c_str(), 128);
1483 strncpy(t_joy.tmp_eventname, eventName, 128);
1484 strncpy(t_joy.comments, cur_comment.c_str(), 1024);
1485 cur_comment = "";
1486 addEvent(eventID, t_joy);
1487 return true;
1488 }
1489 case ET_JoystickAxisRel:
1490 case ET_JoystickAxisAbs:
1491 {
1492 int axisNo = 0;
1493 char options[256] = {};
1494 sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &axisNo, options);
1495 int eventID = resolveEventName(String(eventName));
1496 if (eventID == -1)
1497 return false;
1498
1499 bool half = false;
1500 bool reverse = false;
1501 bool linear = false;
1502 bool relative = false;
1503 bool usedigital = false;
1504 float deadzone = defaultDeadzone;
1505 float linearity = defaultLinearity;
1506 int jAxisRegion = 0;
1507 // 0 = all
1508 // -1 = lower
1509 // 1 = upper
1510 char tmp[256] = {};
1511 strcpy(tmp, options);
1512 tmp[255] = '\0';
1513 char* token = strtok(tmp, delimiters);
1514 while (token != NULL)
1515 {
1516 if (strncmp(token, "HALF", 4) == 0)
1517 half = true;
1518 else if (strncmp(token, "REVERSE", 7) == 0)
1519 reverse = true;
1520 else if (strncmp(token, "LINEAR", 6) == 0)
1521 linear = true;
1522 else if (strncmp(token, "UPPER", 5) == 0)
1523 jAxisRegion = 1;
1524 else if (strncmp(token, "LOWER", 5) == 0)
1525 jAxisRegion = -1;
1526 else if (strncmp(token, "RELATIVE", 8) == 0)
1527 relative = true;
1528 else if (strncmp(token, "DIGITAL", 7) == 0)
1529 usedigital = true;
1530 else if (strncmp(token, "DEADZONE", 8) == 0 && strnlen(token, 250) > 9)
1531 {
1532 char tmp2[256] = {};
1533 strcpy(tmp2, token + 9);
1534 deadzone = atof(tmp2);
1535 //LOG("got deadzone: " + TOSTRING(deadzone)+", "+String(tmp2));
1536 }
1537 else if (strncmp(token, "LINEARITY", 9) == 0 && strnlen(token, 250) > 10)
1538 {
1539 char tmp2[256] = {};
1540 strcpy(tmp2, token + 10);
1541 linearity = atof(tmp2);
1542 }
1543 token = strtok(NULL, delimiters);
1544 }
1545
1546 if (relative)
1547 eventtype = ET_JoystickAxisRel;
1548
1549 event_trigger_t t_joy = newEvent();
1550 t_joy.configDeviceID = deviceID;
1551 t_joy.eventtype = eventtype;
1552 t_joy.joystickAxisRegion = jAxisRegion;
1553 t_joy.joystickAxisUseDigital = usedigital;
1554 t_joy.joystickAxisDeadzone = deadzone;
1555 t_joy.joystickAxisHalf = half;
1556 t_joy.joystickAxisLinearity = linearity;
1557 t_joy.joystickAxisReverse = reverse;
1558 t_joy.joystickAxisNumber = axisNo;
1559 t_joy.joystickNumber = (deviceID == -1 ? joyNo : deviceID);
1560 strncpy(t_joy.configline, options, 128);
1561 strncpy(t_joy.group, getEventGroup(eventName).c_str(), 128);
1562 strncpy(t_joy.tmp_eventname, eventName, 128);
1563 strncpy(t_joy.comments, cur_comment.c_str(), 1024);
1564 cur_comment = "";
1565 addEvent(eventID, t_joy);
1566 //LOG("added axis: " + TOSTRING(axisNo));
1567 return true;
1568 }
1569 case ET_NONE:
1570 {
1571 int eventID = resolveEventName(String(eventName));
1572 if (eventID == -1)
1573 return false;
1574 // Insert event with no trigger
1575 addEvent(eventID);
1576 return true;
1577 }
1578 case ET_MouseButton:
1579 case ET_MouseAxisX:
1580 case ET_MouseAxisY:
1581 case ET_MouseAxisZ:
1582 // no mouse support D:
1583 return false;
1584 case ET_JoystickPov:
1585 {
1586 int povNumber = 0;
1587 char dir[256] = {};
1588 sscanf(line, "%s %s %d %d %s", eventName, evtype, &joyNo, &povNumber, dir);
1589 int eventID = resolveEventName(String(eventName));
1590 if (eventID == -1)
1591 return false;
1592
1593 int direction = OIS::Pov::Centered;
1594 if (!strcmp(dir, "North"))
1595 direction = OIS::Pov::North;
1596 if (!strcmp(dir, "South"))
1597 direction = OIS::Pov::South;
1598 if (!strcmp(dir, "East"))
1599 direction = OIS::Pov::East;
1600 if (!strcmp(dir, "West"))
1601 direction = OIS::Pov::West;
1602 if (!strcmp(dir, "NorthEast"))
1603 direction = OIS::Pov::NorthEast;
1604 if (!strcmp(dir, "SouthEast"))
1605 direction = OIS::Pov::SouthEast;
1606 if (!strcmp(dir, "NorthWest"))
1607 direction = OIS::Pov::NorthWest;
1608 if (!strcmp(dir, "SouthWest"))
1609 direction = OIS::Pov::SouthWest;
1610
1611 event_trigger_t t_pov = newEvent();
1612 t_pov.configDeviceID = deviceID;
1613 t_pov.eventtype = eventtype;
1614 t_pov.joystickNumber = (deviceID == -1 ? joyNo : deviceID);
1615 t_pov.joystickPovNumber = povNumber;
1616 t_pov.joystickPovDirection = direction;
1617
1618 strncpy(t_pov.group, getEventGroup(eventName).c_str(), 128);
1619 strncpy(t_pov.tmp_eventname, eventName, 128);
1620 strncpy(t_pov.comments, cur_comment.c_str(), 1024);
1621 strncpy(t_pov.configline, dir, 128);
1622 cur_comment = "";
1623 addEvent(eventID, t_pov);
1624 //LOG("added axis: " + TOSTRING(axisNo));
1625 return true;
1626 }
1627 case ET_JoystickSliderX:
1628 case ET_JoystickSliderY:
1629 {
1630 int sliderNumber = 0;
1631 char options[256] = {};
1632 char type;
1633 sscanf(line, "%s %s %d %c %d %s", eventName, evtype, &joyNo, &type, &sliderNumber, options);
1634 int eventID = resolveEventName(String(eventName));
1635 if (eventID == -1)
1636 return false;
1637
1638 bool reverse = false;
1639 char tmp[256] = {};
1640 strncpy(tmp, options, 255);
1641 tmp[255] = '\0';
1642 char* token = strtok(tmp, delimiters);
1643 while (token != NULL)
1644 {
1645 if (strncmp(token, "REVERSE", 7) == 0)
1646 reverse = true;
1647
1648 token = strtok(NULL, delimiters);
1649 }
1650
1651 event_trigger_t t_slider = newEvent();
1652 t_slider.configDeviceID = deviceID;
1653
1654 if (type == 'Y' || type == 'y')
1655 eventtype = ET_JoystickSliderY;
1656 else if (type == 'X' || type == 'x')
1657 eventtype = ET_JoystickSliderX;
1658
1659 t_slider.eventtype = eventtype;
1660 t_slider.joystickNumber = (deviceID == -1 ? joyNo : deviceID);
1661 t_slider.joystickSliderNumber = sliderNumber;
1662 t_slider.joystickSliderReverse = reverse;
1663 // TODO: add region support to sliders!
1664 t_slider.joystickSliderRegion = 0;
1665 strncpy(t_slider.configline, options, 128);
1666 strncpy(t_slider.group, getEventGroup(eventName).c_str(), 128);
1667 strncpy(t_slider.tmp_eventname, eventName, 128);
1668 strncpy(t_slider.comments, cur_comment.c_str(), 1024);
1669 cur_comment = "";
1670 addEvent(eventID, t_slider);
1671 //LOG("added axis: " + TOSTRING(axisNo));
1672 return true;
1673 }
1674 default:
1675 return false;
1676 }
1677}
1678
1679int InputEngine::getCurrentJoyButton(int& joystickNumber, int& button)
1680{
1681 for (int j = 0; j < free_joysticks; j++)
1682 {
1683 for (int i = 0; i < (int)joyState[j].mButtons.size(); i++)
1684 {
1685 if (joyState[j].mButtons[i])
1686 {
1687 joystickNumber = j;
1688 button = i;
1689 return 1;
1690 }
1691 }
1692 }
1693 return 0;
1694}
1695
1696int InputEngine::getCurrentPovValue(int& joystickNumber, int& pov, int& povdir)
1697{
1698 for (int j = 0; j < free_joysticks; j++)
1699 {
1700 for (int i = 0; i < MAX_JOYSTICK_POVS; i++)
1701 {
1702 if (joyState[j].mPOV[i].direction != Pov::Centered)
1703 {
1704 joystickNumber = j;
1705 pov = i;
1706 povdir = joyState[j].mPOV[i].direction;
1707 return 1;
1708 }
1709 }
1710 }
1711 return 0;
1712}
1713
1715{
1716 OIS::MouseState const& mstate = mMouse->getMouseState();
1717 Ogre::Vector2 res;
1718 res.x = static_cast<float>(mstate.X.abs) / static_cast<float>(mstate.width);
1719 res.y = static_cast<float>(mstate.Y.abs) / static_cast<float>(mstate.height);
1720 return res;
1721}
1722
1724{
1725 event_trigger_t res;
1726 memset(&res, 0, sizeof(event_trigger_t));
1727 return res;
1728}
1729
1730int InputEngine::getJoyComponentCount(OIS::ComponentType type, int joystickNumber)
1731{
1732 if (joystickNumber > free_joysticks || !mJoy[joystickNumber])
1733 return 0;
1734 return mJoy[joystickNumber]->getNumberOfComponents(type);
1735}
1736
1737std::string InputEngine::getJoyVendor(int joystickNumber)
1738{
1739 if (joystickNumber > free_joysticks || !mJoy[joystickNumber])
1740 return "unknown";
1741 return mJoy[joystickNumber]->vendor();
1742}
1743
1744JoyStickState* InputEngine::getCurrentJoyState(int joystickNumber)
1745{
1746 if (joystickNumber > free_joysticks)
1747 return 0;
1748 return &joyState[joystickNumber];
1749}
1750
1752{
1753 std::map<int, bool>::iterator i;
1754 int keyCounter = 0;
1755 int modCounter = 0;
1756
1757 // list all modificators first
1758 for (i = keyState.begin(); i != keyState.end(); i++)
1759 {
1760 if (i->second)
1761 {
1762 if (i->first != KC_LSHIFT && i->first != KC_RSHIFT && i->first != KC_LCONTROL && i->first != KC_RCONTROL && i->first != KC_LMENU && i->first != KC_RMENU)
1763 continue;
1764 modCounter++;
1765 String keyName = getKeyNameForKeyCode((OIS::KeyCode)i->first);
1766 if (*combo == "")
1767 *combo = keyName;
1768 else
1769 *combo = *combo + "+" + keyName;
1770 }
1771 }
1772
1773 // now list all keys
1774 for (i = keyState.begin(); i != keyState.end(); i++)
1775 {
1776 if (i->second)
1777 {
1778 if (i->first == KC_LSHIFT || i->first == KC_RSHIFT || i->first == KC_LCONTROL || i->first == KC_RCONTROL || i->first == KC_LMENU || i->first == KC_RMENU)
1779 continue;
1780 String keyName = getKeyNameForKeyCode((OIS::KeyCode)i->first);
1781 if (*combo == "")
1782 *combo = keyName;
1783 else
1784 *combo = *combo + "+" + keyName;
1785 keyCounter++;
1786 }
1787 }
1788
1789 //
1790 if (modCounter > 0 && keyCounter == 0)
1791 {
1792 return -modCounter;
1793 }
1794 else if (keyCounter == 0 && modCounter == 0)
1795 {
1796 *combo = _L("(Please press a key)");
1797 return 0;
1798 }
1799 return keyCounter;
1800}
1801
1802String InputEngine::getEventGroup(String eventName)
1803{
1804 const char delimiters[] = "_";
1805 char tmp[256] = {};
1806 strncpy(tmp, eventName.c_str(), 255);
1807 tmp[255] = '\0';
1808 char* token = strtok(tmp, delimiters);
1809 while (token != NULL)
1810 {
1811 return String(token);
1812 }
1813 return "";
1814}
1815
1817{
1819 return false;
1820 bool isSlider = (t->eventtype == ET_JoystickSliderX || t->eventtype == ET_JoystickSliderY);
1821 strcpy(t->configline, "");
1822
1823 if (isSlider)
1824 {
1825 if (t->joystickSliderReverse && !strlen(t->configline))
1826 strcat(t->configline, "REVERSE");
1827 else if (t->joystickSliderReverse && strlen(t->configline))
1828 strcat(t->configline, "+REVERSE");
1829
1830 if (t->joystickSliderRegion == 1 && !strlen(t->configline))
1831 strcat(t->configline, "UPPER");
1832 else if (t->joystickSliderRegion == 1 && strlen(t->configline))
1833 strcat(t->configline, "+UPPER");
1834 else if (t->joystickSliderRegion == -1 && !strlen(t->configline))
1835 strcat(t->configline, "LOWER");
1836 else if (t->joystickSliderRegion == -1 && strlen(t->configline))
1837 strcat(t->configline, "+LOWER");
1838
1839 // is this is a slider, ignore the rest
1840 return true;
1841 }
1842
1843 if (t->joystickAxisReverse && !strlen(t->configline))
1844 strcat(t->configline, "REVERSE");
1845 else if (t->joystickAxisReverse && strlen(t->configline))
1846 strcat(t->configline, "+REVERSE");
1847
1848 if (t->joystickAxisRegion == 1 && !strlen(t->configline))
1849 strcat(t->configline, "UPPER");
1850 else if (t->joystickAxisRegion == 1 && strlen(t->configline))
1851 strcat(t->configline, "+UPPER");
1852 else if (t->joystickAxisRegion == -1 && !strlen(t->configline))
1853 strcat(t->configline, "LOWER");
1854 else if (t->joystickAxisRegion == -1 && strlen(t->configline))
1855 strcat(t->configline, "+LOWER");
1856
1857 if (fabs(t->joystickAxisDeadzone - 0.1) > 0.0001f)
1858 {
1859 char tmp[256] = {};
1860 sprintf(tmp, "DEADZONE=%0.2f", t->joystickAxisDeadzone);
1861 if (strlen(t->configline))
1862 {
1863 strcat(t->configline, "+");
1864 strcat(t->configline, tmp);
1865 }
1866 else
1867 strcat(t->configline, tmp);
1868 }
1869 if (fabs(1.0f - t->joystickAxisLinearity) > 0.01f)
1870 {
1871 char tmp[256] = {};
1872 sprintf(tmp, "LINEARITY=%0.2f", t->joystickAxisLinearity);
1873 if (strlen(t->configline))
1874 {
1875 strcat(t->configline, "+");
1876 strcat(t->configline, tmp);
1877 }
1878 else
1879 strcat(t->configline, tmp);
1880 }
1881 return true;
1882}
1883
1885{
1886 for (int i = 0; i < EV_MODE_LAST; i++)
1887 {
1888 if (events.find(eventInfo[i].eventID) == events.end())
1889 {
1890 // not existing, insert default
1891
1892 char tmp[256] = "";
1893 sprintf(tmp, "%s %s", eventInfo[i].name.c_str(), eventInfo[i].defaultKey.c_str());
1894
1896 }
1897 }
1898}
1899
1900// Loads config file specific to a device and OS (or default config if deviceID is -1).
1902{
1903 String fileName;
1904 if (deviceID == -1)
1905 {
1906 fileName = DEFAULT_MAPFILE;
1907 }
1908 else
1909 {
1910 ROR_ASSERT(deviceID < free_joysticks);
1911
1912 String deviceStr = mJoy[deviceID]->vendor();
1913
1914 // care about unsuitable chars
1915 String repl = "\\/ #@?!$%^&*()+=-><.:'|\";";
1916 for (unsigned int c = 0; c < repl.size(); c++)
1917 {
1918 deviceStr = StringUtil::replaceAll(deviceStr, repl.substr(c, 1), "_");
1919 }
1920
1921 // Look for OS-specific device mapping
1922 String osSpecificMapFile;
1923#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
1924 osSpecificMapFile = deviceStr + ".windows.map";
1925#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
1926 osSpecificMapFile = deviceStr + ".linux.map";
1927#endif
1928 if (osSpecificMapFile != "" &&
1929 ResourceGroupManager::getSingleton().resourceExists(RGN_CONFIG, osSpecificMapFile))
1930 {
1931 fileName = osSpecificMapFile;
1932 }
1933 else
1934 {
1935 // Load generic device mapping
1936 fileName = deviceStr + ".map";
1937 }
1938
1939 m_loaded_configs[deviceID] = fileName;
1940 }
1941
1942 return this->loadMapping(fileName, deviceID);
1943}
1944
1946{
1947 ROR_ASSERT(deviceID < free_joysticks);
1948
1949 if (deviceID == -1)
1950 return this->saveMapping(DEFAULT_MAPFILE, deviceID);
1951 else
1952 return this->saveMapping(m_loaded_configs[deviceID], deviceID);
1953}
1954
1955std::string const& InputEngine::getLoadedConfigFile(int deviceID /*= -1*/)
1956{
1957 ROR_ASSERT(deviceID < free_joysticks);
1958 if (deviceID == -1)
1959 return DEFAULT_MAPFILE;
1960 else
1961 return m_loaded_configs[deviceID];
1962}
1963
1964bool InputEngine::loadMapping(String fileName, int deviceID)
1965{
1966 char line[1025] = "";
1967 int oldState = uniqueCounter;
1968
1969 LOG(" * Loading input mapping " + fileName);
1970 {
1971 DataStreamPtr ds;
1972 try
1973 {
1974 ds = ResourceGroupManager::getSingleton().openResource(fileName, RGN_CONFIG);
1975 }
1976 catch (...)
1977 {
1978 return false;
1979 }
1980 while (!ds->eof())
1981 {
1982 size_t size = 1024;
1983 if (ds->tell() + size >= ds->size())
1984 size = ds->size() - ds->tell();
1985 if (ds->tell() >= ds->size())
1986 break;
1987 size_t readnum = ds->readLine(line, size);
1988 if (readnum > 5)
1989 processLine(line, deviceID);
1990 }
1991 }
1992
1993 int newEvents = uniqueCounter - oldState;
1994 LOG(" * Input map successfully loaded: " + TOSTRING(newEvents) + " entries");
1995 return true;
1996}
1997
1998bool InputEngine::saveMapping(String fileName, int deviceID)
1999{
2000 const int COL1_WIDTH = 34; // total 35
2001 const int COL2_WIDTH = 19; // total 20
2002
2003 try
2004 {
2005 // Open file for writing (overwrite existing).
2006 Ogre::DataStreamPtr ds = Ogre::ResourceGroupManager::getSingleton().createResource(
2007 fileName, RGN_CONFIG, /*overwrite:*/true);
2008
2009 // Loop events and filter by device.
2010 for (auto& ev_pair: events)
2011 {
2012 for (event_trigger_t& ev: ev_pair.second)
2013 {
2014 if (ev.configDeviceID == deviceID)
2015 {
2016 // We found a matching event - compose config line and write it.
2017
2018 string conf_string = this->composeEventConfigString(ev);
2019 switch (ev.eventtype)
2020 {
2021 case ET_JoystickButton:
2022 case ET_JoystickAxisAbs:
2023 case ET_JoystickAxisRel:
2024 case ET_JoystickPov:
2025 case ET_JoystickSliderX:
2026 case ET_JoystickSliderY:
2027 conf_string = fmt::format("0 {}", conf_string); // Dummy device number (unused)
2028 break;
2029 default:;
2030 }
2031
2032 std::string line = fmt::format("{:<{}} {:<{}} {}\n", // padding: ("{:<{}}", "abc", 10) writes "abc "
2033 this->eventIDToName(ev_pair.first), COL1_WIDTH,
2034 this->getEventTypeName(ev.eventtype), COL2_WIDTH,
2035 conf_string);
2036 ds->write(line.c_str(), line.size());
2037 }
2038 }
2039 }
2040 return true; // Closes `ds`
2041 }
2042 catch (Ogre::Exception& e) // Already logged by OGRE
2043 {
2045 fmt::format("Failed to write '{}', {}", fileName, e.getDescription()));
2046 return false;
2047 }
2048}
2049
2051{
2052 int i = 0;
2053 while (i != EV_MODE_LAST)
2054 {
2055 if (eventInfo[i].name == eventName)
2056 return eventInfo[i].eventID;
2057 i++;
2058 }
2059 LOG("unknown event (ignored): " + eventName);
2060 return -1;
2061}
2062
2064{
2065 int i = 0;
2066 while (i != EV_MODE_LAST)
2067 {
2068 if (eventInfo[i].eventID == eventID)
2069 return eventInfo[i].name;
2070 i++;
2071 }
2072 return "unknown";
2073}
2074
2076{
2077 int i = 0;
2078 while (i != EV_MODE_LAST)
2079 {
2080 if (eventInfo[i].eventID == eventID)
2081 return eventInfo[i].description;
2082 i++;
2083 }
2084 return "unknown";
2085}
2086
2088{
2089 allkeys["0"] = KC_0;
2090 allkeys["1"] = KC_1;
2091 allkeys["2"] = KC_2;
2092 allkeys["3"] = KC_3;
2093 allkeys["4"] = KC_4;
2094 allkeys["5"] = KC_5;
2095 allkeys["6"] = KC_6;
2096 allkeys["7"] = KC_7;
2097 allkeys["8"] = KC_8;
2098 allkeys["9"] = KC_9;
2099 allkeys["A"] = KC_A;
2100 allkeys["ABNT_C1"] = KC_ABNT_C1;
2101 allkeys["ABNT_C2"] = KC_ABNT_C2;
2102 allkeys["ADD"] = KC_ADD;
2103 allkeys["APOSTROPHE"] = KC_APOSTROPHE;
2104 allkeys["APPS"] = KC_APPS;
2105 allkeys["AT"] = KC_AT;
2106 allkeys["AX"] = KC_AX;
2107 allkeys["B"] = KC_B;
2108 allkeys["BACK"] = KC_BACK;
2109 allkeys["BACKSLASH"] = KC_BACKSLASH;
2110 allkeys["C"] = KC_C;
2111 allkeys["CALCULATOR"] = KC_CALCULATOR;
2112 allkeys["CAPITAL"] = KC_CAPITAL;
2113 allkeys["COLON"] = KC_COLON;
2114 allkeys["COMMA"] = KC_COMMA;
2115 allkeys["CONVERT"] = KC_CONVERT;
2116 allkeys["D"] = KC_D;
2117 allkeys["DECIMAL"] = KC_DECIMAL;
2118 allkeys["DELETE"] = KC_DELETE;
2119 allkeys["DIVIDE"] = KC_DIVIDE;
2120 allkeys["DOWN"] = KC_DOWN;
2121 allkeys["E"] = KC_E;
2122 allkeys["END"] = KC_END;
2123 allkeys["EQUALS"] = KC_EQUALS;
2124 allkeys["ESCAPE"] = KC_ESCAPE;
2125 allkeys["F"] = KC_F;
2126 allkeys["F1"] = KC_F1;
2127 allkeys["F10"] = KC_F10;
2128 allkeys["F11"] = KC_F11;
2129 allkeys["F12"] = KC_F12;
2130 allkeys["F13"] = KC_F13;
2131 allkeys["F14"] = KC_F14;
2132 allkeys["F15"] = KC_F15;
2133 allkeys["F2"] = KC_F2;
2134 allkeys["F3"] = KC_F3;
2135 allkeys["F4"] = KC_F4;
2136 allkeys["F5"] = KC_F5;
2137 allkeys["F6"] = KC_F6;
2138 allkeys["F7"] = KC_F7;
2139 allkeys["F8"] = KC_F8;
2140 allkeys["F9"] = KC_F9;
2141 allkeys["G"] = KC_G;
2142 allkeys["GRAVE"] = KC_GRAVE;
2143 allkeys["H"] = KC_H;
2144 allkeys["HOME"] = KC_HOME;
2145 allkeys["I"] = KC_I;
2146 allkeys["INSERT"] = KC_INSERT;
2147 allkeys["J"] = KC_J;
2148 allkeys["K"] = KC_K;
2149 allkeys["KANA"] = KC_KANA;
2150 allkeys["KANJI"] = KC_KANJI;
2151 allkeys["L"] = KC_L;
2152 allkeys["LBRACKET"] = KC_LBRACKET;
2153 allkeys["LCONTROL"] = KC_LCONTROL;
2154 allkeys["LEFT"] = KC_LEFT;
2155 allkeys["LMENU"] = KC_LMENU;
2156 allkeys["LSHIFT"] = KC_LSHIFT;
2157 allkeys["LWIN"] = KC_LWIN;
2158 allkeys["M"] = KC_M;
2159 allkeys["MAIL"] = KC_MAIL;
2160 allkeys["MEDIASELECT"] = KC_MEDIASELECT;
2161 allkeys["MEDIASTOP"] = KC_MEDIASTOP;
2162 allkeys["MINUS"] = KC_MINUS;
2163 allkeys["MULTIPLY"] = KC_MULTIPLY;
2164 allkeys["MUTE"] = KC_MUTE;
2165 allkeys["MYCOMPUTER"] = KC_MYCOMPUTER;
2166 allkeys["N"] = KC_N;
2167 allkeys["NEXTTRACK"] = KC_NEXTTRACK;
2168 allkeys["NOCONVERT"] = KC_NOCONVERT;
2169 allkeys["NUMLOCK"] = KC_NUMLOCK;
2170 allkeys["NUMPAD0"] = KC_NUMPAD0;
2171 allkeys["NUMPAD1"] = KC_NUMPAD1;
2172 allkeys["NUMPAD2"] = KC_NUMPAD2;
2173 allkeys["NUMPAD3"] = KC_NUMPAD3;
2174 allkeys["NUMPAD4"] = KC_NUMPAD4;
2175 allkeys["NUMPAD5"] = KC_NUMPAD5;
2176 allkeys["NUMPAD6"] = KC_NUMPAD6;
2177 allkeys["NUMPAD7"] = KC_NUMPAD7;
2178 allkeys["NUMPAD8"] = KC_NUMPAD8;
2179 allkeys["NUMPAD9"] = KC_NUMPAD9;
2180 allkeys["NUMPADCOMMA"] = KC_NUMPADCOMMA;
2181 allkeys["NUMPADENTER"] = KC_NUMPADENTER;
2182 allkeys["NUMPADEQUALS"] = KC_NUMPADEQUALS;
2183 allkeys["O"] = KC_O;
2184 allkeys["OEM_102"] = KC_OEM_102;
2185 allkeys["P"] = KC_P;
2186 allkeys["PAUSE"] = KC_PAUSE;
2187 allkeys["PERIOD"] = KC_PERIOD;
2188 allkeys["PGDOWN"] = KC_PGDOWN;
2189 allkeys["PGUP"] = KC_PGUP;
2190 allkeys["PLAYPAUSE"] = KC_PLAYPAUSE;
2191 allkeys["POWER"] = KC_POWER;
2192 allkeys["PREVTRACK"] = KC_PREVTRACK;
2193 allkeys["Q"] = KC_Q;
2194 allkeys["R"] = KC_R;
2195 allkeys["RBRACKET"] = KC_RBRACKET;
2196 allkeys["RCONTROL"] = KC_RCONTROL;
2197 allkeys["RETURN"] = KC_RETURN;
2198 allkeys["RIGHT"] = KC_RIGHT;
2199 allkeys["RMENU"] = KC_RMENU;
2200 allkeys["RSHIFT"] = KC_RSHIFT;
2201 allkeys["RWIN"] = KC_RWIN;
2202 allkeys["S"] = KC_S;
2203 allkeys["SCROLL"] = KC_SCROLL;
2204 allkeys["SEMICOLON"] = KC_SEMICOLON;
2205 allkeys["SLASH"] = KC_SLASH;
2206 allkeys["SLEEP"] = KC_SLEEP;
2207 allkeys["SPACE"] = KC_SPACE;
2208 allkeys["STOP"] = KC_STOP;
2209 allkeys["SUBTRACT"] = KC_SUBTRACT;
2210 allkeys["SYSRQ"] = KC_SYSRQ;
2211 allkeys["T"] = KC_T;
2212 allkeys["TAB"] = KC_TAB;
2213 allkeys["U"] = KC_U;
2214 allkeys["UNDERLINE"] = KC_UNDERLINE;
2215 allkeys["UNLABELED"] = KC_UNLABELED;
2216 allkeys["UP"] = KC_UP;
2217 allkeys["V"] = KC_V;
2218 allkeys["VOLUMEDOWN"] = KC_VOLUMEDOWN;
2219 allkeys["VOLUMEUP"] = KC_VOLUMEUP;
2220 allkeys["W"] = KC_W;
2221 allkeys["WAKE"] = KC_WAKE;
2222 allkeys["WEBBACK"] = KC_WEBBACK;
2223 allkeys["WEBFAVORITES"] = KC_WEBFAVORITES;
2224 allkeys["WEBFORWARD"] = KC_WEBFORWARD;
2225 allkeys["WEBHOME"] = KC_WEBHOME;
2226 allkeys["WEBREFRESH"] = KC_WEBREFRESH;
2227 allkeys["WEBSEARCH"] = KC_WEBSEARCH;
2228 allkeys["WEBSTOP"] = KC_WEBSTOP;
2229 allkeys["X"] = KC_X;
2230 allkeys["Y"] = KC_Y;
2231 allkeys["YEN"] = KC_YEN;
2232 allkeys["Z"] = KC_Z;
2233}
2234
2236{
2237 std::map<int, std::vector<event_trigger_t>>::iterator it = events.find(eventID);
2238
2239 if (it == events.end())
2240 return String();
2241 if (it->second.empty())
2242 return String();
2243
2244 std::vector<event_trigger_t>::iterator it2 = it->second.begin();
2245 return getKeyNameForKeyCode((OIS::KeyCode)it2->keyCode);
2246}
2247
2248Ogre::String InputEngine::getModifierKeyName(OIS::KeyCode key)
2249{
2250 switch (key)
2251 {
2252 case OIS::KC_LMENU: return _LC("ModifierKey", "Left Alt");
2253 case OIS::KC_LSHIFT: return _LC("ModifierKey", "Left Shift");
2254 case OIS::KC_LCONTROL: return _LC("ModifierKey", "Left Ctrl");
2255
2256 case OIS::KC_RMENU: return _LC("ModifierKey", "Right Alt");
2257 case OIS::KC_RSHIFT: return _LC("ModifierKey", "Right Shift");
2258 case OIS::KC_RCONTROL: return _LC("ModifierKey", "Right Ctrl");
2259
2260 default: return "";
2261 }
2262}
System integration layer; inspired by OgreBites::ApplicationContext.
#define ROR_ASSERT(_EXPR)
Definition Application.h:40
#define RGN_CONFIG
Definition Application.h:49
#define TOSTRING(x)
Definition Application.h:57
void LOG(const char *msg)
Legacy alias - formerly a macro.
#define BITMASK_SET_0(VAR, FLAGS)
Definition BitFlags.h:16
#define BITMASK_SET_1(VAR, FLAGS)
Definition BitFlags.h:17
uint32_t BitMask_t
Definition BitFlags.h:7
#define _L
#define strnlen(str, len)
const char * mOISDeviceType[6]
InputEvent eventInfo[]
Handles controller inputs from player.
#define MAX_JOYSTICK_POVS
Definition InputEngine.h:40
#define MAX_JOYSTICKS
Definition InputEngine.h:39
#define _LC(ctx, str)
Definition Language.h:38
Ogre::RenderWindow * GetRenderWindow()
Definition AppContext.h:67
@ CONSOLE_MSGTYPE_INFO
Generic message.
Definition Console.h:60
void putMessage(MessageArea area, MessageType type, std::string const &msg, std::string icon="")
Definition Console.cpp:103
@ CONSOLE_SYSTEM_ERROR
Definition Console.h:52
Ogre::String getEventConfig(int eventID)
std::map< std::string, OIS::KeyCode > allkeys
std::string getEventCommandTrimmed(int eventID)
Omits 'EXPL' modifier.
std::string composeEventCommandString(event_trigger_t const &trig)
float getEventBounceTime(int eventID)
std::string m_loaded_configs[MAX_JOYSTICKS]
int getCurrentJoyButton(int &joystickNumber, int &button)
void clearEventsByDevice(int deviceID)
Clears all bindings with given deviceID (-1 is no exception).
std::string composeEventConfigString(event_trigger_t const &trig)
Ogre::String getTriggerCommand(event_trigger_t const &evt)
std::map< std::string, OIS::KeyCode >::iterator allit
Ogre::String getDeviceName(event_trigger_t const &evt)
static const char * getEventTypeName(eventtypes type)
Enum to string helper.
int getCurrentPovValue(int &joystickNumber, int &pov, int &povdir)
bool isKeyDown(OIS::KeyCode mod)
Asks OIS directly.
static int resolveEventName(Ogre::String eventName)
std::map< int, float > event_values_simulated
float axisLinearity(float axisValue, float linearity)
std::map< int, bool > event_states_supressed
void SetKeyboardListener(OIS::KeyListener *obj)
std::map< int, float > event_times
static Ogre::String eventIDToDescription(int eventID)
void ProcessKeyRelease(const OIS::KeyEvent &arg)
int getKeboardKeyForCommand(int eventID)
Returns -1 if not Keyboard.
std::string const & getLoadedConfigFile(int deviceID=-1)
Returns filename from loadConfigFile() call.
int getJoyComponentCount(OIS::ComponentType type, int joystickNumber)
void clearEvents(int eventID)
Clears all bindings for given event.
void updateEvent(int eventID, const event_trigger_t &t)
bool loadMapping(Ogre::String fileName, int deviceID)
std::string getEventGroup(Ogre::String eventName)
void processMouseMotionEvent(const OIS::MouseEvent &arg)
void addEventDefault(int eventID, int deviceID=-1)
Adds a new trigger with builtin value for this event.
bool getEventBoolValue(int eventID)
Ogre::String getModifierKeyName(OIS::KeyCode key)
bool isEventDefined(int eventID)
OIS::Mouse * mMouse
void SetJoystickListener(OIS::JoyStickListener *obj)
bool loadConfigFile(int deviceID=-1)
Loads config file specific to a device and OS (or default config if deviceID is -1).
OIS::MouseState mouseState
bool saveConfigFile(int deviceID=-1)
Wites events with matching deviceID to loaded file with matching deviceID (or default file if deviceI...
bool saveMapping(Ogre::String fileName, int deviceID)
int getCurrentKeyCombo(Ogre::String *combo)
Returns number of non-modifier keys pressed (or modifier count as negative number).
OIS::JoyStickState joyState[MAX_JOYSTICKS]
void updateKeyBounces(float dt)
OIS::ForceFeedback * mForceFeedback
event_trigger_t newEvent()
size_t m_oisworkaround_frames_since_reset
size_t m_oisworkaround_lmbdowns_since_reset
OIS::MouseState getMouseState()
std::string getKeyNameForKeyCode(OIS::KeyCode keycode)
bool isKeyDownValueBounce(OIS::KeyCode mod, float time=0.2f)
void clearAllEvents()
Purges all configured bindings.
static Ogre::String eventIDToName(int eventID)
bool isKeyDownEffective(OIS::KeyCode mod)
Reads RoR internal buffer.
static const std::string DEFAULT_MAPFILE
= "input.map";
void ProcessJoystickEvent(const OIS::JoyStickEvent &arg)
void windowResized(Ogre::RenderWindow *rw)
void processMouseReleaseEvent(const OIS::MouseEvent &arg, OIS::MouseButtonID _id)
bool processLine(const char *line, int deviceID=-1)
void resetKeysAndMouseButtons()
void ProcessKeyPress(const OIS::KeyEvent &arg)
OIS::JoyStick * mJoy[MAX_JOYSTICKS]
float deadZone(float axis, float dz)
Ogre::String getEventDefaultConfig(int eventID)
void setEventSimulatedValue(events eventID, float value)
Ogre::String getKeyForCommand(int eventID)
void addEvent(int eventID, event_trigger_t &t)
Registers new trigger for this event.
void setEventStatusSupressed(events eventID, bool supress)
std::map< int, bool > keyState
Ogre::String getEventCommand(int eventID)
float logval(float val)
void eraseEvent(int eventID, const event_trigger_t *t)
OIS::Keyboard * mKeyboard
OIS::InputManager * mInputManager
std::vector< event_trigger_t > TriggerVec
Ogre::Vector2 getMouseNormalizedScreenPos()
Returns XY position in range from 0 (top/left) to 1 (bottom/right)
bool updateConfigline(event_trigger_t *t)
std::map< int, std::vector< event_trigger_t > > events
void SetMouseListener(OIS::MouseListener *obj)
static const int BUILTIN_MAPPING_DEVICEID
virtual device ID for builtin defaults
bool getEventBoolValueBounce(int eventID, float time=0.2f)
float getEventValue(int eventID, bool pure=false, InputSourceType valueSource=InputSourceType::IST_ANY)
valueSource: IST_ANY=digital and analog devices, IST_DIGITAL=only digital, IST_ANALOG=only analog
int free_joysticks
Number of detected game controllers.
bool isEventAnalog(int eventID)
std::string getJoyVendor(int joystickNumber)
OIS::JoyStickState * getCurrentJoyState(int joystickNumber)
void processMousePressEvent(const OIS::MouseEvent &arg, OIS::MouseButtonID _id)
InputSourceType
Definition InputEngine.h:67
eventtypes
Definition InputEngine.h:50
@ ET_MouseButton
Definition InputEngine.h:53
@ ET_JoystickAxisRel
Definition InputEngine.h:59
@ ET_MouseAxisX
Definition InputEngine.h:54
@ ET_JoystickPov
Definition InputEngine.h:60
@ ET_JoystickAxisAbs
Definition InputEngine.h:58
@ ET_JoystickSliderX
Definition InputEngine.h:61
@ ET_MouseAxisZ
Definition InputEngine.h:56
@ ET_JoystickSliderY
Definition InputEngine.h:62
@ ET_JoystickButton
Definition InputEngine.h:57
@ ET_Keyboard
Definition InputEngine.h:52
@ ET_NONE
Definition InputEngine.h:51
@ ET_MouseAxisY
Definition InputEngine.h:55
@ EV_BOAT_CENTER_RUDDER
center the rudder
@ EV_TRUCK_ACCELERATE
accelerate the truck
@ EV_AIRPLANE_THROTTLE
Definition InputEngine.h:93
@ EV_COMMON_TOGGLE_RESET_MODE
toggle truck reset truck mode (soft vs. hard)
@ EV_COMMANDS_01
Command 1.
@ EV_COMMANDS_73
Command 73.
@ EV_CAMERA_DOWN
@ EV_COMMON_REPLAY_BACKWARD
@ EV_COMMON_QUICKSAVE_08
@ EV_COMMANDS_62
Command 62.
@ EV_COMMON_ROPELOCK
connect hook node to a node in close proximity
@ EV_COMMANDS_10
Command 10.
@ EV_COMMANDS_66
Command 66.
@ EV_COMMANDS_43
Command 43.
@ EV_TRUCK_LIGHTTOGGLE02
toggle custom light 2
@ EV_TRUCK_TOGGLE_PHYSICS
toggle physics simulation
@ EV_MENU_RIGHT
select next category
@ EV_COMMON_ENTER_CHATMODE
enter the chat mode
@ EV_COMMON_FOV_MORE
increases the current FOV value
@ EV_TRUCK_HORN
truck horn
@ EV_COMMANDS_28
Command 28.
@ EV_TRUCK_MANUAL_CLUTCH_MODIFIER_50
manual clutch with 50 percent pedal input
@ EV_TRUCK_SHIFT_GEAR01
shift directly into this gear
@ EV_COMMON_SCREENSHOT_BIG
take a BIG screenshot
@ EV_TRUCK_SHIFT_MIDRANGE
select middle range (7-12) for H-shaft
@ EV_AIRPLANE_THROTTLE_FULL
full thrust
Definition InputEngine.h:96
@ EV_CAMERA_ZOOM_IN_FAST
zoom camera in faster
@ EV_TRUCK_TOGGLE_VIDEOCAMERA
toggle videocamera update
@ EV_AIRPLANE_THROTTLE_UP
increase the airplane thrust
Definition InputEngine.h:98
@ EV_CAMERA_ROTATE_LEFT
rotate camera left
@ EV_COMMANDS_46
Command 46.
@ EV_TRUCK_TOGGLE_TCASE_GEAR_RATIO
toggle the transfer case gear ratio
@ EV_COMMANDS_47
Command 47.
@ EV_COMMON_REPLAY_FORWARD
@ EV_TRUCK_SHIFT_GEAR10
shift directly into this gear
@ EV_AIRPLANE_BRAKE
normal brake for an aircraft.
Definition InputEngine.h:80
@ EV_CHARACTER_ROT_UP
@ EV_COMMON_QUICKSAVE
quicksave scene to the disk
@ EV_COMMON_TOGGLE_MAT_DEBUG
debug purpose - dont use (currently not used)
@ EV_SURVEY_MAP_CYCLE
cycle overview-map mode
@ EV_COMMON_QUICKSAVE_05
@ EV_COMMON_LOCK
connect hook node to a node in close proximity
@ EV_TRUCK_BLINK_RIGHT
toggle right direction indicator (blinker)
@ EV_COMMANDS_65
Command 65.
@ EV_COMMON_FOV_LESS
decreases the current FOV value
@ EV_AIRPLANE_THROTTLE_AXIS
throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider)
Definition InputEngine.h:94
@ EV_COMMANDS_29
Command 29.
@ EV_TRUCK_TOGGLE_INTER_AXLE_DIFF
toggle the inter axle differential mode
@ EV_MENU_UP
select previous element in current category
@ EV_TRUCK_LEFT_MIRROR_LEFT
@ EV_TRUCK_LIGHTTOGGLE04
toggle custom light 4
@ EV_BOAT_THROTTLE_UP
increase throttle
@ EV_COMMANDS_25
Command 25.
@ EV_COMMON_ACCELERATE_SIMULATION
accelerate the simulation speed
@ EV_TRUCK_LIGHTTOGGLE08
toggle custom light 8
@ EV_TRUCK_SHIFT_HIGHRANGE
select high range (13-18) for H-shaft
@ EV_COMMANDS_53
Command 53.
@ EV_AIRPLANE_STEER_RIGHT
steer right
Definition InputEngine.h:92
@ EV_TRUCK_SHIFT_GEAR15
shift directly into this gear
@ EV_COMMON_QUICKLOAD_10
@ EV_AIRPLANE_AIRBRAKES_LESS
Definition InputEngine.h:77
@ EV_COMMON_OUTPUT_POSITION
write current position to log (you can open the logfile and reuse the position)
@ EV_COMMON_TOGGLE_TRUCK_FOG_LIGHTS
toggle truck fog lights (on/off); doesn't need low beams, doesn't use 't' lights.
@ EV_CAMERA_ZOOM_OUT_FAST
zoom camera out faster
@ EV_TRUCK_SHIFT_GEAR13
shift directly into this gear
@ EV_COMMON_QUICKLOAD_07
@ EV_SKY_INCREASE_TIME
increase day-time
@ EV_TRUCK_SHIFT_LOWRANGE
select low range (1-6) for H-shaft
@ EV_COMMANDS_34
Command 34.
@ EV_CAMERA_ROTATE_DOWN
rotate camera down
@ EV_AIRPLANE_PARKING_BRAKE
airplane parking brake.
Definition InputEngine.h:87
@ EV_BOAT_STEER_LEFT_AXIS
steer left (analog value!)
@ EV_COMMANDS_15
Command 15.
@ EV_TRUCK_MANUAL_CLUTCH_MODIFIER_25
manual clutch with 25 percent pedal input
@ EV_GRASS_MOST
EXPERIMENTAL: set maximum amount of grass.
@ EV_COMMON_REMOVE_CURRENT_TRUCK
remove current truck
@ EV_COMMANDS_84
Command 84.
@ EV_COMMANDS_82
Command 82.
@ EV_CAMERA_RESET
reset the camera position
@ EV_COMMANDS_44
Command 44.
@ EV_TRUCK_SHIFT_GEAR17
shift directly into this gear
@ EV_COMMANDS_40
Command 40.
@ EV_TRUCK_BLINK_LEFT
toggle left direction indicator (blinker)
@ EV_COMMON_QUICKLOAD_04
@ EV_ROAD_EDITOR_POINT_SET_POS
@ EV_COMMON_QUICKLOAD_02
@ EV_COMMON_TOGGLE_TRUCK_HIGH_BEAMS
toggle truck high beams (on/off); doesn't need low beams, doesn't use 't' lights.
@ EV_CAMERA_ZOOM_OUT
zoom camera out
@ EV_TRUCK_AUTOSHIFT_UP
shift automatic transmission one gear up
@ EV_AIRPLANE_REVERSE
reverse the turboprops
Definition InputEngine.h:88
@ EV_TRUCK_ACCELERATE_MODIFIER_50
accelerate with 50 percent pedal input
@ EV_MENU_LEFT
select previous category
@ EV_COMMON_QUICKSAVE_07
@ EV_TRUCK_PARKING_BRAKE
toggle parking brake
@ EV_COMMANDS_42
Command 42.
@ EV_BOAT_THROTTLE_DOWN
decrease throttle
@ EV_TRUCK_SHIFT_GEAR16
shift directly into this gear
@ EV_TRUCK_LIGHTTOGGLE05
toggle custom light 5
@ EV_SURVEY_MAP_ZOOM_OUT
decrease survey map scale
@ EV_GRASS_NONE
EXPERIMENTAL: remove grass completely.
@ EV_COMMON_QUICKLOAD_03
@ EV_TRUCK_MANUAL_CLUTCH
manual clutch (for manual transmission)
@ EV_AIRPLANE_FLAPS_MORE
one step more flaps.
Definition InputEngine.h:85
@ EV_COMMANDS_63
Command 63.
@ EV_TRUCK_SHIFT_UP
shift one gear up in manual transmission mode
@ EV_ROAD_EDITOR_REBUILD_MESH
@ EV_AIRPLANE_TOGGLE_ENGINES
switch all engines on / off
Definition InputEngine.h:99
@ EV_BOAT_THROTTLE_AXIS
throttle axis. Only use this if you have fitting hardware :) (i.e. a Slider)
@ EV_COMMON_DECELERATE_SIMULATION
decelerate the simulation speed
@ EV_BOAT_STEER_RIGHT_AXIS
steer right (analog value!)
@ EV_COMMON_NETCHATDISPLAY
@ EV_CHARACTER_SIDESTEP_LEFT
sidestep to the left
@ EV_COMMON_QUICKLOAD_09
@ EV_COMMANDS_41
Command 41.
@ EV_COMMON_CONSOLE_TOGGLE
show / hide the console
@ EV_TRUCK_TOGGLE_CONTACT
toggle ignition
@ EV_COMMON_TOGGLE_PHYSICS
toggle physics on/off
@ EV_COMMANDS_12
Command 12.
@ EV_AIRPLANE_RUDDER_RIGHT
rudder right
Definition InputEngine.h:90
@ EV_TRUCK_LIGHTTOGGLE07
toggle custom light 7
@ EV_COMMON_QUICKSAVE_09
@ EV_COMMON_PRESSURE_LESS
decrease tire pressure (note: only very few trucks support this)
@ EV_TRUCK_TRACTION_CONTROL
toggle antilockbrake system
@ EV_COMMON_PRESSURE_MORE
increase tire pressure (note: only very few trucks support this)
@ EV_GRASS_SAVE
EXPERIMENTAL: save changes to the grass density image.
@ EV_AIRPLANE_FLAPS_NONE
no flaps.
Definition InputEngine.h:86
@ EV_COMMANDS_71
Command 71.
@ EV_COMMON_QUICKSAVE_06
@ EV_CHARACTER_RUN
let the character run
@ EV_COMMANDS_72
Command 72.
@ EV_BOAT_STEER_RIGHT
steer right a step
@ EV_COMMON_QUICKLOAD
quickload scene from the disk
@ EV_COMMANDS_23
Command 23.
@ EV_COMMANDS_04
Command 4.
@ EV_CHARACTER_RIGHT
rotate character right
@ EV_TRUCK_CRUISE_CONTROL_READJUST
match target speed / rpm with current truck speed / rpm
@ EV_AIRPLANE_ELEVATOR_DOWN
pull the elevator down in an aircraft.
Definition InputEngine.h:81
@ EV_COMMON_CYCLE_DEBUG_VIEWS
cycle debug view mode
@ EV_TRUCK_LIGHTTOGGLE10
toggle custom light 10
@ EV_CHARACTER_FORWARD
step forward with the character
@ EV_TRUCK_BLINK_WARN
toggle all direction indicators
@ EV_TRUCK_RIGHT_MIRROR_LEFT
@ EV_COMMON_RESET_SIMULATION_PACE
reset the simulation speed
@ EV_COMMANDS_17
Command 17.
@ EV_COMMANDS_52
Command 52.
@ EV_COMMON_TRUCK_INFO
toggle truck HUD
@ EV_COMMON_HIDE_GUI
hide all GUI elements
@ EV_TRUCK_CRUISE_CONTROL_DECL
decrease target speed / rpm
@ EV_COMMON_QUICKSAVE_01
@ EV_COMMANDS_70
Command 70.
@ EV_CAMERA_ROTATE_UP
rotate camera up
@ EV_COMMON_REPLAY_FAST_FORWARD
@ EV_COMMON_SCREENSHOT
take a screenshot
@ EV_COMMON_RESCUE_TRUCK
teleport to rescue truck
@ EV_COMMON_TOGGLE_DASHBOARD
display or hide the dashboard overlay
@ EV_TRUCK_AUTOSHIFT_DOWN
shift automatic transmission one gear down
@ EV_COMMANDS_51
Command 51.
@ EV_AIRPLANE_FLAPS_FULL
full flaps in an aircraft.
Definition InputEngine.h:83
@ EV_COMMON_QUICKLOAD_06
@ EV_CAMERA_ZOOM_IN
zoom camera in
@ EV_COMMANDS_50
Command 50.
@ EV_AIRPLANE_FLAPS_LESS
one step less flaps.
Definition InputEngine.h:84
@ EV_COMMANDS_08
Command 8.
@ EV_TRUCK_SHIFT_GEAR12
shift directly into this gear
@ EV_COMMON_SEND_CHAT
send the chat text
@ EV_COMMON_TOGGLE_STATS
toggle Ogre statistics (FPS etc.)
@ EV_COMMON_QUICKSAVE_02
@ EV_AIRPLANE_AIRBRAKES_MORE
Definition InputEngine.h:78
@ EV_CHARACTER_LEFT
rotate character left
@ EV_COMMANDS_48
Command 48.
@ EV_COMMON_SECURE_LOAD
tie a load to the truck
@ EV_COMMANDS_68
Command 68.
@ EV_COMMON_QUIT_GAME
exit the game
@ EV_COMMON_QUICKSAVE_10
@ EV_COMMANDS_77
Command 77.
@ EV_COMMANDS_83
Command 83.
@ EV_COMMON_QUICKLOAD_05
@ EV_COMMANDS_09
Command 9.
@ EV_TRUCK_TRAILER_PARKING_BRAKE
toggle trailer parking brake
@ EV_COMMANDS_79
Command 79.
@ EV_CHARACTER_JUMP
let the character jump
@ EV_SKY_DECREASE_TIME_FAST
decrease day-time a lot faster
@ EV_TRUCK_SHIFT_GEAR14
shift directly into this gear
@ EV_COMMANDS_45
Command 45.
@ EV_COMMANDS_59
Command 59.
@ EV_TRUCK_SHIFT_GEAR11
shift directly into this gear
@ EV_SURVEY_MAP_TOGGLE_ICONS
toggle map icons
@ EV_COMMON_NETCHATMODE
@ EV_AIRPLANE_THROTTLE_DOWN
decreases the airplane thrust
Definition InputEngine.h:95
@ EV_AIRPLANE_ELEVATOR_UP
pull the elevator up in an aircraft.
Definition InputEngine.h:82
@ EV_TRUCK_SHIFT_NEUTRAL
shift to neutral gear in manual transmission mode
@ EV_COMMON_QUICKSAVE_03
@ EV_COMMON_REPLAY_FAST_BACKWARD
@ EV_COMMON_GET_NEW_VEHICLE
get new vehicle
@ EV_MODE_LAST
@ EV_TRUCK_SWITCH_SHIFT_MODES
toggle between transmission modes
@ EV_SKY_DECREASE_TIME
decrease day-time
@ EV_TRUCK_STEER_LEFT
steer left
@ EV_COMMON_TRUCK_DESCRIPTION
toggle truck description
@ EV_SKY_INCREASE_TIME_FAST
increase day-time a lot faster
@ EV_GRASS_MORE
EXPERIMENTAL: add some grass.
@ EV_BOAT_STEER_LEFT
steer left a step
@ EV_COMMON_RESET_TRUCK
reset truck to original starting position
@ EV_COMMANDS_03
Command 3.
@ EV_COMMANDS_11
Command 11.
@ EV_COMMON_REPAIR_TRUCK
repair truck to original condition
@ EV_BOAT_REVERSE
no thrust
@ EV_COMMON_TOGGLE_TRUCK_BEACONS
toggle truck beacons
@ EV_COMMANDS_22
Command 22.
@ EV_COMMANDS_56
Command 56.
@ EV_COMMANDS_21
Command 21.
@ EV_COMMON_ENTER_PREVIOUS_TRUCK
enter previous truck
@ EV_CAMERA_UP
@ EV_COMMANDS_24
Command 24.
@ EV_COMMANDS_60
Command 50.
@ EV_COMMANDS_55
Command 55.
@ EV_COMMON_TOGGLE_REPLAY_MODE
toggle replay mode
@ EV_COMMON_QUICKLOAD_08
@ EV_COMMANDS_02
Command 2.
@ EV_TRUCK_BRAKE
brake
@ EV_TRUCK_SHIFT_GEAR_REVERSE
shift directly into this gear
@ EV_GRASS_LESS
EXPERIMENTAL: remove some grass.
@ EV_TRUCK_CYCLE_GEAR_RANGES
cycle through the ranges
@ EV_TRUCK_RIGHT_MIRROR_RIGHT
@ EV_COMMANDS_32
Command 32.
@ EV_COMMON_FOV_RESET
reset the FOV value
@ EV_COMMON_ENTER_NEXT_TRUCK
enter next truck
@ EV_COMMANDS_64
Command 64.
@ EV_TRUCK_LIGHTTOGGLE06
toggle custom light 6
@ EV_TRUCK_SHIFT_GEAR08
shift directly into this gear
@ EV_COMMANDS_74
Command 74.
@ EV_TRUCK_TOGGLE_FORWARDCOMMANDS
toggle forwardcommands
@ EV_COMMANDS_19
Command 19.
@ EV_COMMON_SAVE_TERRAIN
save terrain mesh to file
@ EV_COMMANDS_76
Command 76.
@ EV_CAMERA_FREE_MODE
@ EV_CAMERA_LOOKBACK
look back (toggles between normal and lookback)
@ EV_COMMANDS_49
Command 49.
@ EV_COMMANDS_06
Command 6.
@ EV_COMMANDS_05
Command 5.
@ EV_AIRPLANE_THROTTLE_NO
no thrust
Definition InputEngine.h:97
@ EV_TRUCK_SHIFT_GEAR07
shift directly into this gear
@ EV_ROAD_EDITOR_POINT_INSERT
@ EV_AIRPLANE_AIRBRAKES_NONE
Definition InputEngine.h:79
@ EV_COMMANDS_67
Command 67.
@ EV_TRUCK_CRUISE_CONTROL
toggle cruise control
@ EV_COMMON_FULLSCREEN_TOGGLE
@ EV_SURVEY_MAP_TOGGLE
toggle overview-map mode
@ EV_COMMANDS_78
Command 78.
@ EV_TRUCK_TOGGLE_TCASE_4WD_MODE
toggle the transfer case 4wd mode
@ EV_COMMON_CYCLE_TRUCK_LIGHTS
cycle truck front light mode (off -> running light -> low beams -> off).
@ EV_COMMANDS_54
Command 54.
@ EV_CHARACTER_ROT_DOWN
@ EV_TRUCK_STEER_RIGHT
steer right
@ EV_COMMON_TOGGLE_TRUCK_LOW_BEAMS
toggle truck low beams (on/off); also toggles running lights.
@ EV_TRUCK_SHIFT_GEAR06
shift directly into this gear
@ EV_COMMON_QUICKLOAD_01
@ EV_TRUCK_STARTER
hold to start the engine
@ EV_TRUCK_LIGHTTOGGLE09
toggle custom light 9
@ EV_COMMANDS_20
Command 20.
@ EV_COMMANDS_31
Command 31.
@ EV_AIRPLANE_STEER_LEFT
steer left
Definition InputEngine.h:91
@ EV_COMMANDS_16
Command 16.
@ EV_TRUCK_SHIFT_GEAR05
shift directly into this gear
@ EV_COMMON_AUTOLOCK
unlock autolock hook node
@ EV_AIRPLANE_RUDDER_LEFT
rudder left
Definition InputEngine.h:89
@ EV_CHARACTER_SIDESTEP_RIGHT
sidestep to the right
@ EV_TRUCK_SHIFT_GEAR04
shift directly into this gear
@ EV_MENU_SELECT
select focussed item and close menu
@ EV_TRUCK_SHIFT_DOWN
shift one gear down in manual transmission mode
@ EV_COMMON_LIVE_REPAIR_MODE
toggles live repair and recovery mode, controlled by keyboard
@ EV_TRUCK_SHIFT_GEAR18
shift directly into this gear
@ EV_COMMON_TOGGLE_CUSTOM_PARTICLES
toggle particle cannon
@ EV_CAMERA_ROTATE_RIGHT
rotate camera right
@ EV_SURVEY_MAP_ZOOM_IN
increase survey map scale
@ EV_COMMON_QUICKSAVE_04
@ EV_COMMON_RESPAWN_LAST_TRUCK
respawn last truck
@ EV_COMMANDS_26
Command 26.
@ EV_COMMANDS_81
Command 81.
@ EV_ROAD_EDITOR_POINT_GOTO
@ EV_COMMANDS_39
Command 39.
@ EV_COMMANDS_36
Command 36.
@ EV_COMMANDS_69
Command 69.
@ EV_TRUCK_SHIFT_GEAR09
shift directly into this gear
@ EV_COMMANDS_57
Command 57.
@ EV_MENU_DOWN
select next element in current category
@ EV_CHARACTER_BACKWARDS
step backwards with the character
@ EV_COMMANDS_61
Command 61.
@ EV_COMMANDS_18
Command 18.
@ EV_COMMANDS_38
Command 38.
@ EV_TRUCK_ANTILOCK_BRAKE
toggle antilockbrake system
@ EV_TRUCK_TOGGLE_IMPORTCOMMANDS
toggle importcommands
@ EV_ROAD_EDITOR_POINT_DELETE
@ EV_CAMERA_CHANGE
change camera mode
@ EV_TRUCK_CRUISE_CONTROL_ACCL
increase target speed / rpm
@ EV_COMMANDS_07
Command 7.
@ EV_TRUCK_LIGHTTOGGLE01
toggle custom light 1
@ EV_TRUCK_BRAKE_MODIFIER_25
brake with 25 percent pedal input
@ EV_COMMON_ENTER_OR_EXIT_TRUCK
enter or exit a truck
@ EV_COMMANDS_80
Command 80.
@ EV_COMMANDS_13
Command 13.
@ EV_COMMON_TOGGLE_TERRAIN_EDITOR
toggle terrain editor
@ EV_COMMANDS_75
Command 75.
@ EV_COMMANDS_33
Command 33.
@ EV_TRUCK_LIGHTTOGGLE03
toggle custom light 3
@ EV_TRUCK_LEFT_MIRROR_RIGHT
@ EV_TRUCK_BRAKE_MODIFIER_50
brake with 50 percent pedal input
@ EV_TRUCK_TOGGLE_INTER_WHEEL_DIFF
toggle the inter wheel differential mode
@ EV_COMMANDS_14
Command 14.
@ EV_AIRPLANE_AIRBRAKES_FULL
Definition InputEngine.h:76
@ EV_TRUCKEDIT_RELOAD
@ EV_COMMON_TRUCK_REMOVE
@ EV_COMMANDS_37
Command 37.
@ EV_COMMANDS_35
Command 35.
@ EV_TRUCK_SHIFT_GEAR03
shift directly into this gear
@ EV_COMMANDS_27
Command 27.
@ EV_CAMERA_FREE_MODE_FIX
@ EV_COMMON_TOGGLE_DEBUG_VIEW
toggle debug view mode
@ EV_COMMANDS_58
Command 58.
@ EV_TRUCK_ACCELERATE_MODIFIER_25
accelerate with 25 percent pedal input
@ EV_TRUCK_SHIFT_GEAR02
shift directly into this gear
@ EV_COMMANDS_30
Command 30.
AppContext * GetAppContext()
InputEngine * GetInputEngine()
Console * GetConsole()
CVar * io_input_grab_mode
Ogre::String defaultKey
Ogre::String name
std::string description
int configDeviceID
For which device (which config file) was this binding defined?
char configline[256]
Mixed use: keyboard=key, joyButton=buttonNum, POV=direction, joyAxes=options.
enum eventtypes eventtype