mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
Reorganize source files into logical subdirectories
Co-authored-by: Hirek193 <23196899+Hirek193@users.noreply.github.com>
This commit is contained in:
895
input/command.cpp
Normal file
895
input/command.cpp
Normal file
@@ -0,0 +1,895 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "command.h"
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Logs.h"
|
||||
#include "Timer.h"
|
||||
#include "utilities.h"
|
||||
#include "simulation.h"
|
||||
#include "Train.h"
|
||||
|
||||
namespace simulation {
|
||||
|
||||
command_queue Commands;
|
||||
commanddescription_sequence Commands_descriptions = {
|
||||
|
||||
{"aidriverenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"aidriverdisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"jointcontrollerset", command_target::vehicle, command_mode::oneoff},
|
||||
{"mastercontrollerincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"mastercontrollerincreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"mastercontrollerdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"mastercontrollerdecreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"mastercontrollerset", command_target::vehicle, command_mode::oneoff},
|
||||
{"secondcontrollerincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"secondcontrollerincreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"secondcontrollerdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"secondcontrollerdecreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"secondcontrollerset", command_target::vehicle, command_mode::oneoff},
|
||||
{"mucurrentindicatorothersourceactivate", command_target::vehicle, command_mode::oneoff},
|
||||
{"independentbrakeincrease", command_target::vehicle, command_mode::continuous},
|
||||
{"independentbrakeincreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"independentbrakedecrease", command_target::vehicle, command_mode::continuous},
|
||||
{"independentbrakedecreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"independentbrakeset", command_target::vehicle, command_mode::oneoff},
|
||||
{"independentbrakebailoff", command_target::vehicle, command_mode::oneoff},
|
||||
{"universalbrakebutton1", command_target::vehicle, command_mode::oneoff},
|
||||
{"universalbrakebutton2", command_target::vehicle, command_mode::oneoff},
|
||||
{"universalbrakebutton3", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakeincrease", command_target::vehicle, command_mode::continuous},
|
||||
{"trainbrakedecrease", command_target::vehicle, command_mode::continuous},
|
||||
{"trainbrakeset", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakecharging", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakerelease", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakefirstservice", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakeservice", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakefullservice", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakehandleoff", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakeemergency", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakebasepressureincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakebasepressuredecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakebasepressurereset", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakeoperationtoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"manualbrakeincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"manualbrakedecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"alarmchaintoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"alarmchainenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"alarmchaindisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"wheelspinbrakeactivate", command_target::vehicle, command_mode::oneoff},
|
||||
{"sandboxactivate", command_target::vehicle, command_mode::oneoff},
|
||||
{"autosandboxtoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"autosandboxactivate", command_target::vehicle, command_mode::oneoff},
|
||||
{"autosandboxdeactivate", command_target::vehicle, command_mode::oneoff},
|
||||
{"reverserincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"reverserdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"reverserforwardhigh", command_target::vehicle, command_mode::oneoff},
|
||||
{"reverserforward", command_target::vehicle, command_mode::oneoff},
|
||||
{"reverserneutral", command_target::vehicle, command_mode::oneoff},
|
||||
{"reverserbackward", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterpumpbreakertoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterpumpbreakerclose", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterpumpbreakeropen", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterpumptoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterpumpenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterpumpdisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterheaterbreakertoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterheaterbreakerclose", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterheaterbreakeropen", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterheatertoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterheaterenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"waterheaterdisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"watercircuitslinktoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"watercircuitslinkenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"watercircuitslinkdisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"fuelpumptoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"fuelpumpenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"fuelpumpdisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"oilpumptoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"oilpumpenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"oilpumpdisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"linebreakertoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"linebreakeropen", command_target::vehicle, command_mode::oneoff},
|
||||
{"linebreakerclose", command_target::vehicle, command_mode::oneoff},
|
||||
{"convertertoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"converterenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"converterdisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"convertertogglelocal", command_target::vehicle, command_mode::oneoff},
|
||||
{"converteroverloadrelayreset", command_target::vehicle, command_mode::oneoff},
|
||||
{"compressortoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"compressorenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"compressordisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"compressortogglelocal", command_target::vehicle, command_mode::oneoff},
|
||||
{"compressorpresetactivatenext", command_target::vehicle, command_mode::oneoff},
|
||||
{"compressorpresetactivateprevious", command_target::vehicle, command_mode::oneoff},
|
||||
{"compressorpresetactivatedefault", command_target::vehicle, command_mode::oneoff},
|
||||
{"motoroverloadrelaythresholdtoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"motoroverloadrelaythresholdsetlow", command_target::vehicle, command_mode::oneoff},
|
||||
{"motoroverloadrelaythresholdsethigh", command_target::vehicle, command_mode::oneoff},
|
||||
{"motoroverloadrelayreset", command_target::vehicle, command_mode::oneoff},
|
||||
{"universalrelayreset1", command_target::vehicle, command_mode::oneoff},
|
||||
{"universalrelayreset2", command_target::vehicle, command_mode::oneoff},
|
||||
{"universalrelayreset3", command_target::vehicle, command_mode::oneoff},
|
||||
{"notchingrelaytoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"epbrakecontroltoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"epbrakecontrolenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"epbrakecontroldisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakeoperationmodeincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"trainbrakeoperationmodedecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"brakeactingspeedincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"brakeactingspeeddecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"brakeactingspeedsetcargo", command_target::vehicle, command_mode::oneoff},
|
||||
{"brakeactingspeedsetpassenger", command_target::vehicle, command_mode::oneoff},
|
||||
{"brakeactingspeedsetrapid", command_target::vehicle, command_mode::oneoff},
|
||||
{"brakeloadcompensationincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"brakeloadcompensationdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"mubrakingindicatortoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"alerteracknowledge", command_target::vehicle, command_mode::oneoff},
|
||||
{"cabsignalacknowledge", command_target::vehicle, command_mode::oneoff},
|
||||
{"hornlowactivate", command_target::vehicle, command_mode::oneoff},
|
||||
{"hornhighactivate", command_target::vehicle, command_mode::oneoff},
|
||||
{"whistleactivate", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiotoggle", command_target::vehicle, command_mode::oneoff},
|
||||
{"radioenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiodisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiochannelincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiochanneldecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiochannelset", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiostopsend", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiostopenable", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiostopdisable", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiostoptest", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiocall3send", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiovolumeincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiovolumedecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"radiovolumeset", command_target::vehicle, command_mode::oneoff},
|
||||
{"cabchangeforward", command_target::vehicle, command_mode::oneoff},
|
||||
{"cabchangebackward", command_target::vehicle, command_mode::oneoff},
|
||||
{"modernlightdimmerdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"modernlightdimmerincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{ "viewturn", command_target::entity, command_mode::oneoff },
|
||||
{ "movehorizontal", command_target::entity, command_mode::oneoff },
|
||||
{ "movehorizontalfast", command_target::entity, command_mode::oneoff },
|
||||
{ "movevertical", command_target::entity, command_mode::oneoff },
|
||||
{ "moveverticalfast", command_target::entity, command_mode::oneoff },
|
||||
{ "moveleft", command_target::entity, command_mode::oneoff },
|
||||
{ "moveright", command_target::entity, command_mode::oneoff },
|
||||
{ "moveforward", command_target::entity, command_mode::oneoff },
|
||||
{ "moveback", command_target::entity, command_mode::oneoff },
|
||||
{ "moveup", command_target::entity, command_mode::oneoff },
|
||||
{ "movedown", command_target::entity, command_mode::oneoff },
|
||||
{ "nearestcarcouplingincrease", command_target::vehicle, command_mode::oneoff },
|
||||
{ "nearestcarcouplingdisconnect", command_target::vehicle, command_mode::oneoff },
|
||||
{ "nearestcarcoupleradapterattach", command_target::vehicle, command_mode::oneoff },
|
||||
{ "nearestcarcoupleradapterremove", command_target::vehicle, command_mode::oneoff },
|
||||
{ "occupiedcarcouplingdisconnect", command_target::vehicle, command_mode::oneoff },
|
||||
{ "occupiedcarcouplingdisconnectback", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doortoggleleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doortoggleright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorpermitleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorpermitright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorpermitpresetactivatenext", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorpermitpresetactivateprevious", command_target::vehicle, command_mode::oneoff },
|
||||
{ "dooropenleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "dooropenright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "dooropenall", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorcloseleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorcloseright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorcloseall", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorsteptoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doormodetoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "mirrorstoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "departureannounce", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorlocktoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographcompressorvalvetoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographcompressorvalveenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographcompressorvalvedisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographcompressoractivate", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographtogglefront", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographtogglerear", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographraisefront", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographraiserear", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographlowerfront", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographlowerrear", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographlowerall", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographselectnext", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographselectprevious", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographtoggleselected", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographraiseselected", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographlowerselected", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographvalvesupdate", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographvalvesoff", command_target::vehicle, command_mode::oneoff },
|
||||
{ "heatingtoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "heatingenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "heatingdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "lightspresetactivatenext", command_target::vehicle, command_mode::oneoff },
|
||||
{ "lightspresetactivateprevious", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlighttoggleleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightenableleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightdisableleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlighttoggleright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightenableright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightdisableright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlighttoggleupper", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightenableupper", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightdisableupper", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkertoggleleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerenableleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerdisableleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkertoggleright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerenableright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerdisableright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlighttogglerearleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightenablerearleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightdisablerearleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlighttogglerearright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightenablerearright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightdisablerearright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlighttogglerearupper", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightenablerearupper", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightdisablerearupper", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkertogglerearleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerenablerearleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerdisablerearleft", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkertogglerearright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerenablerearright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerdisablerearright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "redmarkerstoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "endsignalstoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightsdimtoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightsdimenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "headlightsdimdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motorconnectorsopen", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motorconnectorsclose", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motordisconnect", command_target::vehicle, command_mode::oneoff },
|
||||
{ "interiorlighttoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "interiorlightenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "interiorlightdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "interiorlightdimtoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "interiorlightdimenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "interiorlightdimdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "compartmentlightstoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "compartmentlightsenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "compartmentlightsdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "instrumentlighttoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "instrumentlightenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "instrumentlightdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "dashboardlighttoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "dashboardlightenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "dashboardlightdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "timetablelighttoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "timetablelightenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "timetablelightdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{"generictoggle0", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle1", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle2", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle3", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle4", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle5", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle6", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle7", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle8", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle9", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle10", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle11", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle12", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle13", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle14", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle15", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle16", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle17", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle18", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle19", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle20", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle21", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle22", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle23", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle24", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle25", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle26", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle27", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle28", command_target::vehicle, command_mode::oneoff},
|
||||
{"generictoggle29", command_target::vehicle, command_mode::oneoff},
|
||||
{ "batterytoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "batteryenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "batterydisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "cabactivationtoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "cabactivationenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "cabactivationdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motorblowerstogglefront", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motorblowerstogglerear", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motorblowersdisableall", command_target::vehicle, command_mode::oneoff },
|
||||
{ "coolingfanstoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "tempomattoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "springbraketoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "springbrakeenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "springbrakedisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "springbrakeshutofftoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "springbrakeshutoffenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "springbrakeshutoffdisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "springbrakerelease", command_target::vehicle },
|
||||
{ "distancecounteractivate", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolincrease", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontroldecrease", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolpowerincrease", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolpowerdecrease", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton0", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton1", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton2", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton3", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton4", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton5", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton6", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton7", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton8", command_target::vehicle, command_mode::oneoff },
|
||||
{ "speedcontrolbutton9", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable1", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable2", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable3", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable4", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable5", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable6", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable7", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable8", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable9", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable10", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable11", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterenable12", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable1", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable2", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable3", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable4", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable5", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable6", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable7", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable8", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable9", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable10", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable11", command_target::vehicle, command_mode::oneoff },
|
||||
{ "inverterdisable12", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle1", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle2", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle3", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle4", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle5", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle6", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle7", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle8", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle9", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle10", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle11", command_target::vehicle, command_mode::oneoff },
|
||||
{ "invertertoggle12", command_target::vehicle, command_mode::oneoff },
|
||||
{ "globalradiostop", command_target::simulation, command_mode::oneoff },
|
||||
{ "timejump", command_target::simulation, command_mode::oneoff },
|
||||
{ "timejumplarge", command_target::simulation, command_mode::oneoff },
|
||||
{ "timejumpsmall", command_target::simulation, command_mode::oneoff },
|
||||
{ "setdatetime", command_target::simulation, command_mode::oneoff },
|
||||
{ "setweather", command_target::simulation, command_mode::oneoff },
|
||||
{ "settemperature", command_target::simulation, command_mode::oneoff },
|
||||
{ "vehiclemoveforwards", command_target::vehicle, command_mode::oneoff },
|
||||
{ "vehiclemovebackwards", command_target::vehicle, command_mode::oneoff },
|
||||
{ "vehicleboost", command_target::vehicle, command_mode::oneoff },
|
||||
{ "debugtoggle", command_target::simulation, command_mode::oneoff },
|
||||
{ "focuspauseset", command_target::simulation, command_mode::oneoff },
|
||||
{ "pausetoggle", command_target::simulation, command_mode::oneoff },
|
||||
{ "entervehicle", command_target::simulation, command_mode::oneoff },
|
||||
{ "resetconsist", command_target::simulation, command_mode::oneoff },
|
||||
{ "fillcompressor", command_target::simulation, command_mode::oneoff },
|
||||
{ "consistreleaser", command_target::simulation, command_mode::oneoff },
|
||||
{ "queueevent", command_target::simulation, command_mode::oneoff },
|
||||
{ "setlight", command_target::simulation, command_mode::oneoff },
|
||||
{ "insertmodel", command_target::simulation, command_mode::oneoff },
|
||||
{ "deletemodel", command_target::simulation, command_mode::oneoff },
|
||||
{ "trainsetmove", command_target::simulation, command_mode::oneoff },
|
||||
{ "consistteleport", command_target::simulation, command_mode::oneoff },
|
||||
{ "pullalarmchain", command_target::simulation, command_mode::oneoff },
|
||||
{ "sendaicommand", command_target::simulation, command_mode::oneoff },
|
||||
{ "spawntrainset", command_target::simulation, command_mode::oneoff },
|
||||
{ "destroytrainset", command_target::simulation, command_mode::oneoff },
|
||||
{ "quitsimulation", command_target::simulation, command_mode::oneoff },
|
||||
{"wiperswitchincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"wiperswitchdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"lightsset", command_target::vehicle, command_mode::oneoff},
|
||||
};
|
||||
|
||||
// Maps of command and coresponding strings
|
||||
std::unordered_map<std::string, user_command> commandMap = {
|
||||
{"aidriverdisable", user_command::aidriverdisable},
|
||||
{"jointcontrollerset", user_command::jointcontrollerset},
|
||||
{"mastercontrollerincrease", user_command::mastercontrollerincrease},
|
||||
{"mastercontrollerincreasefast", user_command::mastercontrollerincreasefast},
|
||||
{"mastercontrollerdecrease", user_command::mastercontrollerdecrease},
|
||||
{"mastercontrollerdecreasefast", user_command::mastercontrollerdecreasefast},
|
||||
{"mastercontrollerset", user_command::mastercontrollerset},
|
||||
{"secondcontrollerincrease", user_command::secondcontrollerincrease},
|
||||
{"secondcontrollerincreasefast", user_command::secondcontrollerincreasefast},
|
||||
{"secondcontrollerdecrease", user_command::secondcontrollerdecrease},
|
||||
{"secondcontrollerdecreasefast", user_command::secondcontrollerdecreasefast},
|
||||
{"secondcontrollerset", user_command::secondcontrollerset},
|
||||
{"mucurrentindicatorothersourceactivate", user_command::mucurrentindicatorothersourceactivate},
|
||||
{"independentbrakeincrease", user_command::independentbrakeincrease},
|
||||
{"independentbrakeincreasefast", user_command::independentbrakeincreasefast},
|
||||
{"independentbrakedecrease", user_command::independentbrakedecrease},
|
||||
{"independentbrakedecreasefast", user_command::independentbrakedecreasefast},
|
||||
{"independentbrakeset", user_command::independentbrakeset},
|
||||
{"independentbrakebailoff", user_command::independentbrakebailoff},
|
||||
{"universalbrakebutton1", user_command::universalbrakebutton1},
|
||||
{"universalbrakebutton2", user_command::universalbrakebutton2},
|
||||
{"universalbrakebutton3", user_command::universalbrakebutton3},
|
||||
{"trainbrakeincrease", user_command::trainbrakeincrease},
|
||||
{"trainbrakedecrease", user_command::trainbrakedecrease},
|
||||
{"trainbrakeset", user_command::trainbrakeset},
|
||||
{"trainbrakecharging", user_command::trainbrakecharging},
|
||||
{"trainbrakerelease", user_command::trainbrakerelease},
|
||||
{"trainbrakefirstservice", user_command::trainbrakefirstservice},
|
||||
{"trainbrakeservice", user_command::trainbrakeservice},
|
||||
{"trainbrakefullservice", user_command::trainbrakefullservice},
|
||||
{"trainbrakehandleoff", user_command::trainbrakehandleoff},
|
||||
{"trainbrakeemergency", user_command::trainbrakeemergency},
|
||||
{"trainbrakebasepressureincrease", user_command::trainbrakebasepressureincrease},
|
||||
{"trainbrakebasepressuredecrease", user_command::trainbrakebasepressuredecrease},
|
||||
{"trainbrakebasepressurereset", user_command::trainbrakebasepressurereset},
|
||||
{"trainbrakeoperationtoggle", user_command::trainbrakeoperationtoggle},
|
||||
{"manualbrakeincrease", user_command::manualbrakeincrease},
|
||||
{"manualbrakedecrease", user_command::manualbrakedecrease},
|
||||
{"alarmchaintoggle", user_command::alarmchaintoggle},
|
||||
{"alarmchainenable", user_command::alarmchainenable},
|
||||
{"alarmchaindisable", user_command::alarmchaindisable},
|
||||
{"wheelspinbrakeactivate", user_command::wheelspinbrakeactivate},
|
||||
{"sandboxactivate", user_command::sandboxactivate},
|
||||
{"autosandboxtoggle", user_command::autosandboxtoggle},
|
||||
{"autosandboxactivate", user_command::autosandboxactivate},
|
||||
{"autosandboxdeactivate", user_command::autosandboxdeactivate},
|
||||
{"reverserincrease", user_command::reverserincrease},
|
||||
{"reverserdecrease", user_command::reverserdecrease},
|
||||
{"reverserforwardhigh", user_command::reverserforwardhigh},
|
||||
{"reverserforward", user_command::reverserforward},
|
||||
{"reverserneutral", user_command::reverserneutral},
|
||||
{"reverserbackward", user_command::reverserbackward},
|
||||
{"waterpumpbreakertoggle", user_command::waterpumpbreakertoggle},
|
||||
{"waterpumpbreakerclose", user_command::waterpumpbreakerclose},
|
||||
{"waterpumpbreakeropen", user_command::waterpumpbreakeropen},
|
||||
{"waterpumptoggle", user_command::waterpumptoggle},
|
||||
{"waterpumpenable", user_command::waterpumpenable},
|
||||
{"waterpumpdisable", user_command::waterpumpdisable},
|
||||
{"waterheaterbreakertoggle", user_command::waterheaterbreakertoggle},
|
||||
{"waterheaterbreakerclose", user_command::waterheaterbreakerclose},
|
||||
{"waterheaterbreakeropen", user_command::waterheaterbreakeropen},
|
||||
{"waterheatertoggle", user_command::waterheatertoggle},
|
||||
{"waterheaterenable", user_command::waterheaterenable},
|
||||
{"waterheaterdisable", user_command::waterheaterdisable},
|
||||
{"watercircuitslinktoggle", user_command::watercircuitslinktoggle},
|
||||
{"watercircuitslinkenable", user_command::watercircuitslinkenable},
|
||||
{"watercircuitslinkdisable", user_command::watercircuitslinkdisable},
|
||||
{"fuelpumptoggle", user_command::fuelpumptoggle},
|
||||
{"fuelpumpenable", user_command::fuelpumpenable},
|
||||
{"fuelpumpdisable", user_command::fuelpumpdisable},
|
||||
{"oilpumptoggle", user_command::oilpumptoggle},
|
||||
{"oilpumpenable", user_command::oilpumpenable},
|
||||
{"oilpumpdisable", user_command::oilpumpdisable},
|
||||
{"linebreakertoggle", user_command::linebreakertoggle},
|
||||
{"linebreakeropen", user_command::linebreakeropen},
|
||||
{"linebreakerclose", user_command::linebreakerclose},
|
||||
{"convertertoggle", user_command::convertertoggle},
|
||||
{"converterenable", user_command::converterenable},
|
||||
{"converterdisable", user_command::converterdisable},
|
||||
{"convertertogglelocal", user_command::convertertogglelocal},
|
||||
{"converteroverloadrelayreset", user_command::converteroverloadrelayreset},
|
||||
{"compressortoggle", user_command::compressortoggle},
|
||||
{"compressorenable", user_command::compressorenable},
|
||||
{"compressordisable", user_command::compressordisable},
|
||||
{"compressortogglelocal", user_command::compressortogglelocal},
|
||||
{"compressorpresetactivatenext", user_command::compressorpresetactivatenext},
|
||||
{"compressorpresetactivateprevious", user_command::compressorpresetactivateprevious},
|
||||
{"compressorpresetactivatedefault", user_command::compressorpresetactivatedefault},
|
||||
{"motoroverloadrelaythresholdtoggle", user_command::motoroverloadrelaythresholdtoggle},
|
||||
{"motoroverloadrelaythresholdsetlow", user_command::motoroverloadrelaythresholdsetlow},
|
||||
{"motoroverloadrelaythresholdsethigh", user_command::motoroverloadrelaythresholdsethigh},
|
||||
{"motoroverloadrelayreset", user_command::motoroverloadrelayreset},
|
||||
{"universalrelayreset1", user_command::universalrelayreset1},
|
||||
{"universalrelayreset2", user_command::universalrelayreset2},
|
||||
{"universalrelayreset3", user_command::universalrelayreset3},
|
||||
{"notchingrelaytoggle", user_command::notchingrelaytoggle},
|
||||
{"epbrakecontroltoggle", user_command::epbrakecontroltoggle},
|
||||
{"epbrakecontrolenable", user_command::epbrakecontrolenable},
|
||||
{"epbrakecontroldisable", user_command::epbrakecontroldisable},
|
||||
{"trainbrakeoperationmodeincrease", user_command::trainbrakeoperationmodeincrease},
|
||||
{"trainbrakeoperationmodedecrease", user_command::trainbrakeoperationmodedecrease},
|
||||
{"brakeactingspeedincrease", user_command::brakeactingspeedincrease},
|
||||
{"brakeactingspeeddecrease", user_command::brakeactingspeeddecrease},
|
||||
{"brakeactingspeedsetcargo", user_command::brakeactingspeedsetcargo},
|
||||
{"brakeactingspeedsetpassenger", user_command::brakeactingspeedsetpassenger},
|
||||
{"brakeactingspeedsetrapid", user_command::brakeactingspeedsetrapid},
|
||||
{"brakeloadcompensationincrease", user_command::brakeloadcompensationincrease},
|
||||
{"brakeloadcompensationdecrease", user_command::brakeloadcompensationdecrease},
|
||||
{"mubrakingindicatortoggle", user_command::mubrakingindicatortoggle},
|
||||
{"alerteracknowledge", user_command::alerteracknowledge},
|
||||
{"cabsignalacknowledge", user_command::cabsignalacknowledge},
|
||||
{"hornlowactivate", user_command::hornlowactivate},
|
||||
{"hornhighactivate", user_command::hornhighactivate},
|
||||
{"whistleactivate", user_command::whistleactivate},
|
||||
{"radiotoggle", user_command::radiotoggle},
|
||||
{"radioenable", user_command::radioenable},
|
||||
{"radiodisable", user_command::radiodisable},
|
||||
{"radiochannelincrease", user_command::radiochannelincrease},
|
||||
{"radiochanneldecrease", user_command::radiochanneldecrease},
|
||||
{"radiochannelset", user_command::radiochannelset},
|
||||
{"radiostopsend", user_command::radiostopsend},
|
||||
{"radiostopenable", user_command::radiostopenable},
|
||||
{"radiostopdisable", user_command::radiostopdisable},
|
||||
{"radiostoptest", user_command::radiostoptest},
|
||||
{"radiocall3send", user_command::radiocall3send},
|
||||
{"radiovolumeincrease", user_command::radiovolumeincrease},
|
||||
{"radiovolumedecrease", user_command::radiovolumedecrease},
|
||||
{"radiovolumeset", user_command::radiovolumeset},
|
||||
{"cabchangeforward", user_command::cabchangeforward},
|
||||
{"cabchangebackward", user_command::cabchangebackward},
|
||||
{"viewturn", user_command::viewturn},
|
||||
{"movehorizontal", user_command::movehorizontal},
|
||||
{"movehorizontalfast", user_command::movehorizontalfast},
|
||||
{"movevertical", user_command::movevertical},
|
||||
{"moveverticalfast", user_command::moveverticalfast},
|
||||
{"moveleft", user_command::moveleft},
|
||||
{"moveright", user_command::moveright},
|
||||
{"moveforward", user_command::moveforward},
|
||||
{"moveback", user_command::moveback},
|
||||
{"moveup", user_command::moveup},
|
||||
{"movedown", user_command::movedown},
|
||||
{"nearestcarcouplingincrease", user_command::nearestcarcouplingincrease},
|
||||
{"nearestcarcouplingdisconnect", user_command::nearestcarcouplingdisconnect},
|
||||
{"nearestcarcoupleradapterattach", user_command::nearestcarcoupleradapterattach},
|
||||
{"nearestcarcoupleradapterremove", user_command::nearestcarcoupleradapterremove},
|
||||
{"occupiedcarcouplingdisconnect", user_command::occupiedcarcouplingdisconnect},
|
||||
{"occupiedcarcouplingdisconnectback", user_command::occupiedcarcouplingdisconnectback},
|
||||
{"doortoggleleft", user_command::doortoggleleft},
|
||||
{"doortoggleright", user_command::doortoggleright},
|
||||
{"doorpermitleft", user_command::doorpermitleft},
|
||||
{"doorpermitright", user_command::doorpermitright},
|
||||
{"doorpermitpresetactivatenext", user_command::doorpermitpresetactivatenext},
|
||||
{"doorpermitpresetactivateprevious", user_command::doorpermitpresetactivateprevious},
|
||||
{"dooropenleft", user_command::dooropenleft},
|
||||
{"dooropenright", user_command::dooropenright},
|
||||
{"dooropenall", user_command::dooropenall},
|
||||
{"doorcloseleft", user_command::doorcloseleft},
|
||||
{"doorcloseright", user_command::doorcloseright},
|
||||
{"doorcloseall", user_command::doorcloseall},
|
||||
{"doorsteptoggle", user_command::doorsteptoggle},
|
||||
{"doormodetoggle", user_command::doormodetoggle},
|
||||
{"mirrorstoggle", user_command::mirrorstoggle},
|
||||
{"departureannounce", user_command::departureannounce},
|
||||
{"doorlocktoggle", user_command::doorlocktoggle},
|
||||
{"pantographcompressorvalvetoggle", user_command::pantographcompressorvalvetoggle},
|
||||
{"pantographcompressorvalveenable", user_command::pantographcompressorvalveenable},
|
||||
{"pantographcompressorvalvedisable", user_command::pantographcompressorvalvedisable},
|
||||
{"pantographcompressoractivate", user_command::pantographcompressoractivate},
|
||||
{"pantographtogglefront", user_command::pantographtogglefront},
|
||||
{"pantographtogglerear", user_command::pantographtogglerear},
|
||||
{"pantographraisefront", user_command::pantographraisefront},
|
||||
{"pantographraiserear", user_command::pantographraiserear},
|
||||
{"pantographlowerfront", user_command::pantographlowerfront},
|
||||
{"pantographlowerrear", user_command::pantographlowerrear},
|
||||
{"pantographlowerall", user_command::pantographlowerall},
|
||||
{"pantographselectnext", user_command::pantographselectnext},
|
||||
{"pantographselectprevious", user_command::pantographselectprevious},
|
||||
{"pantographtoggleselected", user_command::pantographtoggleselected},
|
||||
{"pantographraiseselected", user_command::pantographraiseselected},
|
||||
{"pantographlowerselected", user_command::pantographlowerselected},
|
||||
{"pantographvalvesupdate", user_command::pantographvalvesupdate},
|
||||
{"pantographvalvesoff", user_command::pantographvalvesoff},
|
||||
{"heatingtoggle", user_command::heatingtoggle},
|
||||
{"heatingenable", user_command::heatingenable},
|
||||
{"heatingdisable", user_command::heatingdisable},
|
||||
{"lightspresetactivatenext", user_command::lightspresetactivatenext},
|
||||
{"lightspresetactivateprevious", user_command::lightspresetactivateprevious},
|
||||
{"headlighttoggleleft", user_command::headlighttoggleleft},
|
||||
{"headlightenableleft", user_command::headlightenableleft},
|
||||
{"headlightdisableleft", user_command::headlightdisableleft},
|
||||
{"headlighttoggleright", user_command::headlighttoggleright},
|
||||
{"headlightenableright", user_command::headlightenableright},
|
||||
{"headlightdisableright", user_command::headlightdisableright},
|
||||
{"headlighttoggleupper", user_command::headlighttoggleupper},
|
||||
{"headlightenableupper", user_command::headlightenableupper},
|
||||
{"headlightdisableupper", user_command::headlightdisableupper},
|
||||
{"redmarkertoggleleft", user_command::redmarkertoggleleft},
|
||||
{"redmarkerenableleft", user_command::redmarkerenableleft},
|
||||
{"redmarkerdisableleft", user_command::redmarkerdisableleft},
|
||||
{"redmarkertoggleright", user_command::redmarkertoggleright},
|
||||
{"redmarkerenableright", user_command::redmarkerenableright},
|
||||
{"redmarkerdisableright", user_command::redmarkerdisableright},
|
||||
{"headlighttogglerearleft", user_command::headlighttogglerearleft},
|
||||
{"headlightenablerearleft", user_command::headlightenablerearleft},
|
||||
{"headlightdisablerearleft", user_command::headlightdisablerearleft},
|
||||
{"headlighttogglerearright", user_command::headlighttogglerearright},
|
||||
{"headlightenablerearright", user_command::headlightenablerearright},
|
||||
{"headlightdisablerearright", user_command::headlightdisablerearright},
|
||||
{"headlighttogglerearupper", user_command::headlighttogglerearupper},
|
||||
{"headlightenablerearupper", user_command::headlightenablerearupper},
|
||||
{"headlightdisablerearupper", user_command::headlightdisablerearupper},
|
||||
{"redmarkertogglerearleft", user_command::redmarkertogglerearleft},
|
||||
{"redmarkerenablerearleft", user_command::redmarkerenablerearleft},
|
||||
{"redmarkerdisablerearleft", user_command::redmarkerdisablerearleft},
|
||||
{"redmarkertogglerearright", user_command::redmarkertogglerearright},
|
||||
{"redmarkerenablerearright", user_command::redmarkerenablerearright},
|
||||
{"redmarkerdisablerearright", user_command::redmarkerdisablerearright},
|
||||
{"redmarkerstoggle", user_command::redmarkerstoggle},
|
||||
{"endsignalstoggle", user_command::endsignalstoggle},
|
||||
{"headlightsdimtoggle", user_command::headlightsdimtoggle},
|
||||
{"headlightsdimenable", user_command::headlightsdimenable},
|
||||
{"headlightsdimdisable", user_command::headlightsdimdisable},
|
||||
{"motorconnectorsopen", user_command::motorconnectorsopen},
|
||||
{"motorconnectorsclose", user_command::motorconnectorsclose},
|
||||
{"motordisconnect", user_command::motordisconnect},
|
||||
{"interiorlighttoggle", user_command::interiorlighttoggle},
|
||||
{"interiorlightenable", user_command::interiorlightenable},
|
||||
{"interiorlightdisable", user_command::interiorlightdisable},
|
||||
{"interiorlightdimtoggle", user_command::interiorlightdimtoggle},
|
||||
{"interiorlightdimenable", user_command::interiorlightdimenable},
|
||||
{"interiorlightdimdisable", user_command::interiorlightdimdisable},
|
||||
{"compartmentlightstoggle", user_command::compartmentlightstoggle},
|
||||
{"compartmentlightsenable", user_command::compartmentlightsenable},
|
||||
{"compartmentlightsdisable", user_command::compartmentlightsdisable},
|
||||
{"instrumentlighttoggle", user_command::instrumentlighttoggle},
|
||||
{"instrumentlightenable", user_command::instrumentlightenable},
|
||||
{"instrumentlightdisable", user_command::instrumentlightdisable},
|
||||
{"dashboardlighttoggle", user_command::dashboardlighttoggle},
|
||||
{"dashboardlightenable", user_command::dashboardlightenable},
|
||||
{"dashboardlightdisable", user_command::dashboardlightdisable},
|
||||
{"timetablelighttoggle", user_command::timetablelighttoggle},
|
||||
{"timetablelightenable", user_command::timetablelightenable},
|
||||
{"timetablelightdisable", user_command::timetablelightdisable},
|
||||
{"generictoggle0", user_command::generictoggle0},
|
||||
{"generictoggle1", user_command::generictoggle1},
|
||||
{"generictoggle2", user_command::generictoggle2},
|
||||
{"generictoggle3", user_command::generictoggle3},
|
||||
{"generictoggle4", user_command::generictoggle4},
|
||||
{"generictoggle5", user_command::generictoggle5},
|
||||
{"generictoggle6", user_command::generictoggle6},
|
||||
{"generictoggle7", user_command::generictoggle7},
|
||||
{"generictoggle8", user_command::generictoggle8},
|
||||
{"generictoggle9", user_command::generictoggle9},
|
||||
{"generictoggle10", user_command::generictoggle10},
|
||||
{"generictoggle11", user_command::generictoggle11},
|
||||
{"generictoggle12", user_command::generictoggle12},
|
||||
{"generictoggle13", user_command::generictoggle13},
|
||||
{"generictoggle14", user_command::generictoggle14},
|
||||
{"generictoggle15", user_command::generictoggle15},
|
||||
{"generictoggle16", user_command::generictoggle16},
|
||||
{"generictoggle17", user_command::generictoggle17},
|
||||
{"generictoggle18", user_command::generictoggle18},
|
||||
{"generictoggle19", user_command::generictoggle19},
|
||||
{"generictoggle20", user_command::generictoggle20},
|
||||
{"generictoggle21", user_command::generictoggle21},
|
||||
{"generictoggle22", user_command::generictoggle22},
|
||||
{"generictoggle23", user_command::generictoggle23},
|
||||
{"generictoggle24", user_command::generictoggle24},
|
||||
{"generictoggle25", user_command::generictoggle25},
|
||||
{"generictoggle26", user_command::generictoggle26},
|
||||
{"generictoggle27", user_command::generictoggle27},
|
||||
{"generictoggle28", user_command::generictoggle28},
|
||||
{"generictoggle29", user_command::generictoggle29},
|
||||
|
||||
{"batterytoggle", user_command::batterytoggle},
|
||||
{"batteryenable", user_command::batteryenable},
|
||||
{"batterydisable", user_command::batterydisable},
|
||||
{"cabactivationtoggle", user_command::cabactivationtoggle},
|
||||
{"cabactivationenable", user_command::cabactivationenable},
|
||||
{"cabactivationdisable", user_command::cabactivationdisable},
|
||||
{"motorblowerstogglefront", user_command::motorblowerstogglefront},
|
||||
{"motorblowerstogglerear", user_command::motorblowerstogglerear},
|
||||
{"motorblowersdisableall", user_command::motorblowersdisableall},
|
||||
{"coolingfanstoggle", user_command::coolingfanstoggle},
|
||||
{"tempomattoggle", user_command::tempomattoggle},
|
||||
{"springbraketoggle", user_command::springbraketoggle},
|
||||
{"springbrakeenable", user_command::springbrakeenable},
|
||||
{"springbrakedisable", user_command::springbrakedisable},
|
||||
{"springbrakeshutofftoggle", user_command::springbrakeshutofftoggle},
|
||||
{"springbrakeshutoffenable", user_command::springbrakeshutoffenable},
|
||||
{"springbrakeshutoffdisable", user_command::springbrakeshutoffdisable},
|
||||
{"springbrakerelease", user_command::springbrakerelease},
|
||||
{"distancecounteractivate", user_command::distancecounteractivate},
|
||||
{"speedcontrolincrease", user_command::speedcontrolincrease},
|
||||
{"speedcontroldecrease", user_command::speedcontroldecrease},
|
||||
{"speedcontrolpowerincrease", user_command::speedcontrolpowerincrease},
|
||||
{"speedcontrolpowerdecrease", user_command::speedcontrolpowerdecrease},
|
||||
{"speedcontrolbutton0", user_command::speedcontrolbutton0},
|
||||
{"speedcontrolbutton1", user_command::speedcontrolbutton1},
|
||||
{"speedcontrolbutton2", user_command::speedcontrolbutton2},
|
||||
{"speedcontrolbutton3", user_command::speedcontrolbutton3},
|
||||
{"speedcontrolbutton4", user_command::speedcontrolbutton4},
|
||||
{"speedcontrolbutton5", user_command::speedcontrolbutton5},
|
||||
{"speedcontrolbutton6", user_command::speedcontrolbutton6},
|
||||
{"speedcontrolbutton7", user_command::speedcontrolbutton7},
|
||||
{"speedcontrolbutton8", user_command::speedcontrolbutton8},
|
||||
{"speedcontrolbutton9", user_command::speedcontrolbutton9},
|
||||
{"inverterenable1", user_command::inverterenable1},
|
||||
{"inverterenable2", user_command::inverterenable2},
|
||||
{"inverterenable3", user_command::inverterenable3},
|
||||
{"inverterenable4", user_command::inverterenable4},
|
||||
{"inverterenable5", user_command::inverterenable5},
|
||||
{"inverterenable6", user_command::inverterenable6},
|
||||
{"inverterenable7", user_command::inverterenable7},
|
||||
{"inverterenable8", user_command::inverterenable8},
|
||||
{"inverterenable9", user_command::inverterenable9},
|
||||
{"inverterenable10", user_command::inverterenable10},
|
||||
{"inverterenable11", user_command::inverterenable11},
|
||||
{"inverterenable12", user_command::inverterenable12},
|
||||
{"inverterdisable1", user_command::inverterdisable1},
|
||||
{"inverterdisable2", user_command::inverterdisable2},
|
||||
{"inverterdisable3", user_command::inverterdisable3},
|
||||
{"inverterdisable4", user_command::inverterdisable4},
|
||||
{"inverterdisable5", user_command::inverterdisable5},
|
||||
{"inverterdisable6", user_command::inverterdisable6},
|
||||
{"inverterdisable7", user_command::inverterdisable7},
|
||||
{"inverterdisable8", user_command::inverterdisable8},
|
||||
{"inverterdisable9", user_command::inverterdisable9},
|
||||
{"inverterdisable10", user_command::inverterdisable10},
|
||||
{"inverterdisable11", user_command::inverterdisable11},
|
||||
{"inverterdisable12", user_command::inverterdisable12},
|
||||
{"invertertoggle1", user_command::invertertoggle1},
|
||||
{"invertertoggle2", user_command::invertertoggle2},
|
||||
{"invertertoggle3", user_command::invertertoggle3},
|
||||
{"invertertoggle4", user_command::invertertoggle4},
|
||||
{"invertertoggle5", user_command::invertertoggle5},
|
||||
{"invertertoggle6", user_command::invertertoggle6},
|
||||
{"invertertoggle7", user_command::invertertoggle7},
|
||||
{"invertertoggle8", user_command::invertertoggle8},
|
||||
{"invertertoggle9", user_command::invertertoggle9},
|
||||
{"invertertoggle10", user_command::invertertoggle10},
|
||||
{"invertertoggle11", user_command::invertertoggle11},
|
||||
{"invertertoggle12", user_command::invertertoggle12},
|
||||
{"globalradiostop", user_command::globalradiostop},
|
||||
{"timejump", user_command::timejump},
|
||||
{"timejumplarge", user_command::timejumplarge},
|
||||
{"timejumpsmall", user_command::timejumpsmall},
|
||||
{"setdatetime", user_command::setdatetime},
|
||||
{"setweather", user_command::setweather},
|
||||
{"settemperature", user_command::settemperature},
|
||||
{"vehiclemoveforwards", user_command::vehiclemoveforwards},
|
||||
{"vehiclemovebackwards", user_command::vehiclemovebackwards},
|
||||
{"vehicleboost", user_command::vehicleboost},
|
||||
{"debugtoggle", user_command::debugtoggle},
|
||||
{"focuspauseset", user_command::focuspauseset},
|
||||
{"pausetoggle", user_command::pausetoggle},
|
||||
{"entervehicle", user_command::entervehicle},
|
||||
{"resetconsist", user_command::resetconsist},
|
||||
{"fillcompressor", user_command::fillcompressor},
|
||||
{"consistreleaser", user_command::consistreleaser},
|
||||
{"queueevent", user_command::queueevent},
|
||||
{"setlight", user_command::setlight},
|
||||
{"insertmodel", user_command::insertmodel},
|
||||
{"deletemodel", user_command::deletemodel},
|
||||
{"dynamicmove", user_command::dynamicmove},
|
||||
{"consistteleport", user_command::consistteleport},
|
||||
{"pullalarmchain", user_command::pullalarmchain},
|
||||
{"sendaicommand", user_command::sendaicommand},
|
||||
{"spawntrainset", user_command::spawntrainset},
|
||||
{"destroytrainset", user_command::destroytrainset},
|
||||
{"quitsimulation", user_command::quitsimulation},
|
||||
{"wiperswitchincrease", user_command::wiperswitchincrease},
|
||||
{"wiperswitchdecrease", user_command::wiperswitchdecrease},
|
||||
{"lightsset", user_command::lightsset},
|
||||
{"none", user_command::none}};
|
||||
|
||||
} // namespace simulation
|
||||
|
||||
void command_queue::update()
|
||||
{
|
||||
double delta = Timer::GetDeltaTime();
|
||||
for (auto c : m_active_continuous)
|
||||
{
|
||||
command_data data({c.first, GLFW_REPEAT, 0.0, 0.0, delta, false, glm::vec3()}); // todo: improve
|
||||
auto lookup = m_commands.emplace( c.second, commanddata_sequence() );
|
||||
// recipient stack was either located or created, so we can add to it quite safely
|
||||
lookup.first->second.emplace_back( data );
|
||||
}
|
||||
}
|
||||
|
||||
// posts specified command for specified recipient
|
||||
void
|
||||
command_queue::push( command_data const &Command, uint32_t const Recipient ) {
|
||||
if (is_network_target(Recipient)) {
|
||||
auto lookup = m_intercept_queue.emplace(Recipient, commanddata_sequence());
|
||||
lookup.first->second.emplace_back(Command);
|
||||
} else {
|
||||
push_direct(Command, Recipient);
|
||||
}
|
||||
}
|
||||
|
||||
void command_queue::push_direct(const command_data &Command, const uint32_t Recipient) {
|
||||
auto const &desc = simulation::Commands_descriptions[ static_cast<std::size_t>( Command.command ) ];
|
||||
if (desc.mode == command_mode::continuous)
|
||||
{
|
||||
if (Command.action == GLFW_PRESS)
|
||||
m_active_continuous.emplace(std::make_pair(Command.command, Recipient));
|
||||
else if (Command.action == GLFW_RELEASE)
|
||||
m_active_continuous.erase(std::make_pair(Command.command, Recipient));
|
||||
else if (Command.action == GLFW_REPEAT)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lookup = m_commands.emplace( Recipient, commanddata_sequence() );
|
||||
// recipient stack was either located or created, so we can add to it quite safely
|
||||
lookup.first->second.emplace_back( Command );
|
||||
}
|
||||
|
||||
// retrieves oldest posted command for specified recipient, if any. returns: true on retrieval, false if there's nothing to retrieve
|
||||
bool
|
||||
command_queue::pop( command_data &Command, uint32_t const Recipient ) {
|
||||
|
||||
auto lookup = m_commands.find( Recipient );
|
||||
if( lookup == m_commands.end() ) {
|
||||
// no command stack for this recipient, so no commands
|
||||
return false;
|
||||
}
|
||||
auto &commands = lookup->second;
|
||||
if( true == commands.empty() ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
// we have command stack with command(s) on it, retrieve and pop the first one
|
||||
Command = commands.front();
|
||||
commands.pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool command_queue::is_network_target(uint32_t const Recipient) {
|
||||
const command_target target = (command_target)(Recipient & ~0xffff);
|
||||
|
||||
if (target == command_target::entity)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
command_queue::commands_map command_queue::pop_intercept_queue() {
|
||||
commands_map map(m_intercept_queue);
|
||||
m_intercept_queue.clear();
|
||||
return map;
|
||||
}
|
||||
|
||||
void command_queue::push_commands(const commands_map &commands) {
|
||||
for (auto const &kv : commands)
|
||||
for (command_data const &data : kv.second)
|
||||
push_direct(data, kv.first);
|
||||
}
|
||||
|
||||
void
|
||||
command_relay::post(user_command const Command, double const Param1, double const Param2,
|
||||
int const Action, uint16_t Recipient, glm::vec3 Position, const std::string *Payload) const {
|
||||
|
||||
auto const &command = simulation::Commands_descriptions[ static_cast<std::size_t>( Command ) ];
|
||||
|
||||
if (command.target == command_target::vehicle && Recipient == 0) {
|
||||
// default 0 recipient is currently controlled train
|
||||
if (simulation::Train == nullptr)
|
||||
return;
|
||||
Recipient = simulation::Train->id();
|
||||
}
|
||||
|
||||
if( ( command.target == command_target::vehicle )
|
||||
&& ( true == FreeFlyModeFlag )
|
||||
&& ( ( false == DebugModeFlag )
|
||||
&& ( true == Global.RealisticControlMode ) ) ) {
|
||||
// in realistic control mode don't pass vehicle commands if the user isn't in one, unless we're in debug mode
|
||||
return;
|
||||
}
|
||||
|
||||
if (Position == glm::vec3(0.0f))
|
||||
Position = Global.pCamera.Pos;
|
||||
|
||||
uint32_t combined_recipient = static_cast<uint32_t>( command.target ) | Recipient;
|
||||
command_data commanddata({Command, Action, Param1, Param2, Timer::GetDeltaTime(), FreeFlyModeFlag, Position });
|
||||
if (Payload)
|
||||
commanddata.payload = *Payload;
|
||||
|
||||
simulation::Commands.push(commanddata, combined_recipient);
|
||||
}
|
||||
532
input/command.h
Normal file
532
input/command.h
Normal file
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
|
||||
enum class user_command
|
||||
{
|
||||
|
||||
aidriverenable = 0,
|
||||
aidriverdisable,
|
||||
jointcontrollerset,
|
||||
mastercontrollerincrease,
|
||||
mastercontrollerincreasefast,
|
||||
mastercontrollerdecrease,
|
||||
mastercontrollerdecreasefast,
|
||||
mastercontrollerset,
|
||||
secondcontrollerincrease,
|
||||
secondcontrollerincreasefast,
|
||||
secondcontrollerdecrease,
|
||||
secondcontrollerdecreasefast,
|
||||
secondcontrollerset,
|
||||
mucurrentindicatorothersourceactivate,
|
||||
independentbrakeincrease,
|
||||
independentbrakeincreasefast,
|
||||
independentbrakedecrease,
|
||||
independentbrakedecreasefast,
|
||||
independentbrakeset,
|
||||
independentbrakebailoff,
|
||||
universalbrakebutton1,
|
||||
universalbrakebutton2,
|
||||
universalbrakebutton3,
|
||||
trainbrakeincrease,
|
||||
trainbrakedecrease,
|
||||
trainbrakeset,
|
||||
trainbrakecharging,
|
||||
trainbrakerelease,
|
||||
trainbrakefirstservice,
|
||||
trainbrakeservice,
|
||||
trainbrakefullservice,
|
||||
trainbrakehandleoff,
|
||||
trainbrakeemergency,
|
||||
trainbrakebasepressureincrease,
|
||||
trainbrakebasepressuredecrease,
|
||||
trainbrakebasepressurereset,
|
||||
trainbrakeoperationtoggle,
|
||||
manualbrakeincrease,
|
||||
manualbrakedecrease,
|
||||
alarmchaintoggle,
|
||||
alarmchainenable,
|
||||
alarmchaindisable,
|
||||
wheelspinbrakeactivate,
|
||||
sandboxactivate,
|
||||
autosandboxtoggle,
|
||||
autosandboxactivate,
|
||||
autosandboxdeactivate,
|
||||
reverserincrease,
|
||||
reverserdecrease,
|
||||
reverserforwardhigh,
|
||||
reverserforward,
|
||||
reverserneutral,
|
||||
reverserbackward,
|
||||
waterpumpbreakertoggle,
|
||||
waterpumpbreakerclose,
|
||||
waterpumpbreakeropen,
|
||||
waterpumptoggle,
|
||||
waterpumpenable,
|
||||
waterpumpdisable,
|
||||
waterheaterbreakertoggle,
|
||||
waterheaterbreakerclose,
|
||||
waterheaterbreakeropen,
|
||||
waterheatertoggle,
|
||||
waterheaterenable,
|
||||
waterheaterdisable,
|
||||
watercircuitslinktoggle,
|
||||
watercircuitslinkenable,
|
||||
watercircuitslinkdisable,
|
||||
fuelpumptoggle,
|
||||
fuelpumpenable,
|
||||
fuelpumpdisable,
|
||||
oilpumptoggle,
|
||||
oilpumpenable,
|
||||
oilpumpdisable,
|
||||
linebreakertoggle,
|
||||
linebreakeropen,
|
||||
linebreakerclose,
|
||||
convertertoggle,
|
||||
converterenable,
|
||||
converterdisable,
|
||||
convertertogglelocal,
|
||||
converteroverloadrelayreset,
|
||||
compressortoggle,
|
||||
compressorenable,
|
||||
compressordisable,
|
||||
compressortogglelocal,
|
||||
compressorpresetactivatenext,
|
||||
compressorpresetactivateprevious,
|
||||
compressorpresetactivatedefault,
|
||||
motoroverloadrelaythresholdtoggle,
|
||||
motoroverloadrelaythresholdsetlow,
|
||||
motoroverloadrelaythresholdsethigh,
|
||||
motoroverloadrelayreset,
|
||||
universalrelayreset1,
|
||||
universalrelayreset2,
|
||||
universalrelayreset3,
|
||||
notchingrelaytoggle,
|
||||
epbrakecontroltoggle,
|
||||
epbrakecontrolenable,
|
||||
epbrakecontroldisable,
|
||||
trainbrakeoperationmodeincrease,
|
||||
trainbrakeoperationmodedecrease,
|
||||
brakeactingspeedincrease,
|
||||
brakeactingspeeddecrease,
|
||||
brakeactingspeedsetcargo,
|
||||
brakeactingspeedsetpassenger,
|
||||
brakeactingspeedsetrapid,
|
||||
brakeloadcompensationincrease,
|
||||
brakeloadcompensationdecrease,
|
||||
mubrakingindicatortoggle,
|
||||
alerteracknowledge,
|
||||
cabsignalacknowledge,
|
||||
hornlowactivate,
|
||||
hornhighactivate,
|
||||
whistleactivate,
|
||||
radiotoggle,
|
||||
radioenable,
|
||||
radiodisable,
|
||||
radiochannelincrease,
|
||||
radiochanneldecrease,
|
||||
radiochannelset,
|
||||
radiostopsend,
|
||||
radiostopenable,
|
||||
radiostopdisable,
|
||||
radiostoptest,
|
||||
radiocall3send,
|
||||
radiovolumeincrease,
|
||||
radiovolumedecrease,
|
||||
radiovolumeset,
|
||||
cabchangeforward,
|
||||
cabchangebackward,
|
||||
|
||||
modernlightdimmerdecrease,
|
||||
modernlightdimmerincrease,
|
||||
|
||||
viewturn,
|
||||
movehorizontal,
|
||||
movehorizontalfast,
|
||||
movevertical,
|
||||
moveverticalfast,
|
||||
moveleft,
|
||||
moveright,
|
||||
moveforward,
|
||||
moveback,
|
||||
moveup,
|
||||
movedown,
|
||||
|
||||
nearestcarcouplingincrease,
|
||||
nearestcarcouplingdisconnect,
|
||||
nearestcarcoupleradapterattach,
|
||||
nearestcarcoupleradapterremove,
|
||||
occupiedcarcouplingdisconnect,
|
||||
occupiedcarcouplingdisconnectback,
|
||||
doortoggleleft,
|
||||
doortoggleright,
|
||||
doorpermitleft,
|
||||
doorpermitright,
|
||||
doorpermitpresetactivatenext,
|
||||
doorpermitpresetactivateprevious,
|
||||
dooropenleft,
|
||||
dooropenright,
|
||||
dooropenall,
|
||||
doorcloseleft,
|
||||
doorcloseright,
|
||||
doorcloseall,
|
||||
doorsteptoggle,
|
||||
doormodetoggle,
|
||||
mirrorstoggle,
|
||||
departureannounce,
|
||||
doorlocktoggle,
|
||||
pantographcompressorvalvetoggle,
|
||||
pantographcompressorvalveenable,
|
||||
pantographcompressorvalvedisable,
|
||||
pantographcompressoractivate,
|
||||
pantographtogglefront,
|
||||
pantographtogglerear,
|
||||
pantographraisefront,
|
||||
pantographraiserear,
|
||||
pantographlowerfront,
|
||||
pantographlowerrear,
|
||||
pantographlowerall,
|
||||
pantographselectnext,
|
||||
pantographselectprevious,
|
||||
pantographtoggleselected,
|
||||
pantographraiseselected,
|
||||
pantographlowerselected,
|
||||
pantographvalvesupdate,
|
||||
pantographvalvesoff,
|
||||
heatingtoggle,
|
||||
heatingenable,
|
||||
heatingdisable,
|
||||
lightspresetactivatenext,
|
||||
lightspresetactivateprevious,
|
||||
headlighttoggleleft,
|
||||
headlightenableleft,
|
||||
headlightdisableleft,
|
||||
headlighttoggleright,
|
||||
headlightenableright,
|
||||
headlightdisableright,
|
||||
headlighttoggleupper,
|
||||
headlightenableupper,
|
||||
headlightdisableupper,
|
||||
redmarkertoggleleft,
|
||||
redmarkerenableleft,
|
||||
redmarkerdisableleft,
|
||||
redmarkertoggleright,
|
||||
redmarkerenableright,
|
||||
redmarkerdisableright,
|
||||
headlighttogglerearleft,
|
||||
headlightenablerearleft,
|
||||
headlightdisablerearleft,
|
||||
headlighttogglerearright,
|
||||
headlightenablerearright,
|
||||
headlightdisablerearright,
|
||||
headlighttogglerearupper,
|
||||
headlightenablerearupper,
|
||||
headlightdisablerearupper,
|
||||
redmarkertogglerearleft,
|
||||
redmarkerenablerearleft,
|
||||
redmarkerdisablerearleft,
|
||||
redmarkertogglerearright,
|
||||
redmarkerenablerearright,
|
||||
redmarkerdisablerearright,
|
||||
redmarkerstoggle,
|
||||
endsignalstoggle,
|
||||
headlightsdimtoggle,
|
||||
headlightsdimenable,
|
||||
headlightsdimdisable,
|
||||
motorconnectorsopen,
|
||||
motorconnectorsclose,
|
||||
motordisconnect,
|
||||
interiorlighttoggle,
|
||||
interiorlightenable,
|
||||
interiorlightdisable,
|
||||
interiorlightdimtoggle,
|
||||
interiorlightdimenable,
|
||||
interiorlightdimdisable,
|
||||
compartmentlightstoggle,
|
||||
compartmentlightsenable,
|
||||
compartmentlightsdisable,
|
||||
instrumentlighttoggle,
|
||||
instrumentlightenable,
|
||||
instrumentlightdisable,
|
||||
dashboardlighttoggle,
|
||||
dashboardlightenable,
|
||||
dashboardlightdisable,
|
||||
timetablelighttoggle,
|
||||
timetablelightenable,
|
||||
timetablelightdisable,
|
||||
|
||||
generictoggle0,
|
||||
generictoggle1,
|
||||
generictoggle2,
|
||||
generictoggle3,
|
||||
generictoggle4,
|
||||
generictoggle5,
|
||||
generictoggle6,
|
||||
generictoggle7,
|
||||
generictoggle8,
|
||||
generictoggle9,
|
||||
generictoggle10,
|
||||
generictoggle11,
|
||||
generictoggle12,
|
||||
generictoggle13,
|
||||
generictoggle14,
|
||||
generictoggle15,
|
||||
generictoggle16,
|
||||
generictoggle17,
|
||||
generictoggle18,
|
||||
generictoggle19,
|
||||
generictoggle20,
|
||||
generictoggle21,
|
||||
generictoggle22,
|
||||
generictoggle23,
|
||||
generictoggle24,
|
||||
generictoggle25,
|
||||
generictoggle26,
|
||||
generictoggle27,
|
||||
generictoggle28,
|
||||
generictoggle29,
|
||||
|
||||
batterytoggle,
|
||||
batteryenable,
|
||||
batterydisable,
|
||||
cabactivationtoggle,
|
||||
cabactivationenable,
|
||||
cabactivationdisable,
|
||||
motorblowerstogglefront,
|
||||
motorblowerstogglerear,
|
||||
motorblowersdisableall,
|
||||
coolingfanstoggle,
|
||||
tempomattoggle,
|
||||
springbraketoggle,
|
||||
springbrakeenable,
|
||||
springbrakedisable,
|
||||
springbrakeshutofftoggle,
|
||||
springbrakeshutoffenable,
|
||||
springbrakeshutoffdisable,
|
||||
springbrakerelease,
|
||||
distancecounteractivate,
|
||||
speedcontrolincrease,
|
||||
speedcontroldecrease,
|
||||
speedcontrolpowerincrease,
|
||||
speedcontrolpowerdecrease,
|
||||
speedcontrolbutton0,
|
||||
speedcontrolbutton1,
|
||||
speedcontrolbutton2,
|
||||
speedcontrolbutton3,
|
||||
speedcontrolbutton4,
|
||||
speedcontrolbutton5,
|
||||
speedcontrolbutton6,
|
||||
speedcontrolbutton7,
|
||||
speedcontrolbutton8,
|
||||
speedcontrolbutton9,
|
||||
inverterenable1,
|
||||
inverterenable2,
|
||||
inverterenable3,
|
||||
inverterenable4,
|
||||
inverterenable5,
|
||||
inverterenable6,
|
||||
inverterenable7,
|
||||
inverterenable8,
|
||||
inverterenable9,
|
||||
inverterenable10,
|
||||
inverterenable11,
|
||||
inverterenable12,
|
||||
inverterdisable1,
|
||||
inverterdisable2,
|
||||
inverterdisable3,
|
||||
inverterdisable4,
|
||||
inverterdisable5,
|
||||
inverterdisable6,
|
||||
inverterdisable7,
|
||||
inverterdisable8,
|
||||
inverterdisable9,
|
||||
inverterdisable10,
|
||||
inverterdisable11,
|
||||
inverterdisable12,
|
||||
invertertoggle1,
|
||||
invertertoggle2,
|
||||
invertertoggle3,
|
||||
invertertoggle4,
|
||||
invertertoggle5,
|
||||
invertertoggle6,
|
||||
invertertoggle7,
|
||||
invertertoggle8,
|
||||
invertertoggle9,
|
||||
invertertoggle10,
|
||||
invertertoggle11,
|
||||
invertertoggle12,
|
||||
globalradiostop,
|
||||
timejump,
|
||||
timejumplarge,
|
||||
timejumpsmall,
|
||||
setdatetime,
|
||||
setweather,
|
||||
settemperature,
|
||||
vehiclemoveforwards,
|
||||
vehiclemovebackwards,
|
||||
vehicleboost,
|
||||
debugtoggle,
|
||||
focuspauseset,
|
||||
pausetoggle,
|
||||
entervehicle,
|
||||
resetconsist,
|
||||
fillcompressor,
|
||||
consistreleaser,
|
||||
queueevent,
|
||||
setlight,
|
||||
insertmodel,
|
||||
deletemodel,
|
||||
dynamicmove,
|
||||
consistteleport,
|
||||
pullalarmchain,
|
||||
sendaicommand,
|
||||
spawntrainset,
|
||||
destroytrainset,
|
||||
quitsimulation,
|
||||
wiperswitchincrease,
|
||||
wiperswitchdecrease,
|
||||
lightsset,
|
||||
none = -1
|
||||
};
|
||||
|
||||
enum class command_target {
|
||||
|
||||
userinterface,
|
||||
/*
|
||||
// NOTE: there's no need for consist- and unit-specific commands at this point, but it's a possibility.
|
||||
// since command targets are mutually exclusive these don't reduce ranges for individual vehicles etc
|
||||
consist = 0x4000,
|
||||
unit = 0x8000,
|
||||
*/
|
||||
// values are combined with object id. 0xffff objects of each type should be quite enough ("for everyone")
|
||||
vehicle = 0x10000,
|
||||
signal = 0x20000,
|
||||
entity = 0x40000,
|
||||
simulation = 0x80000
|
||||
};
|
||||
|
||||
enum class command_mode {
|
||||
oneoff,
|
||||
continuous
|
||||
};
|
||||
|
||||
struct command_description {
|
||||
std::string name;
|
||||
command_target target;
|
||||
command_mode mode;
|
||||
};
|
||||
|
||||
struct command_data {
|
||||
|
||||
user_command command;
|
||||
int action; // press, repeat or release
|
||||
double param1;
|
||||
double param2;
|
||||
double time_delta;
|
||||
|
||||
bool freefly;
|
||||
glm::vec3 location;
|
||||
|
||||
std::string payload;
|
||||
};
|
||||
|
||||
// command_queues: collects and holds commands from input sources, for processing by their intended recipients
|
||||
// NOTE: this won't scale well.
|
||||
// TODO: turn it into a dispatcher and build individual command sequences into the items, where they can be examined without lookups
|
||||
|
||||
class command_queue {
|
||||
|
||||
public:
|
||||
// types
|
||||
typedef std::deque<command_data> commanddata_sequence;
|
||||
typedef std::unordered_map<uint32_t, commanddata_sequence> commands_map;
|
||||
// methods
|
||||
// posts specified command for specified recipient into m_intercept_queue
|
||||
void
|
||||
push( command_data const &Command, uint32_t const Recipient );
|
||||
// retrieves oldest posted command for specified recipient, if any. returns: true on retrieval, false if there's nothing to retrieve
|
||||
bool
|
||||
pop( command_data &Command, uint32_t const Recipient );
|
||||
// generates active continuous commands
|
||||
void
|
||||
update();
|
||||
// checks if given command must be scheduled on server
|
||||
bool
|
||||
is_network_target(const uint32_t Recipient);
|
||||
|
||||
// pops commands from intercept queue
|
||||
commands_map pop_intercept_queue();
|
||||
|
||||
// pushes commands into main queue
|
||||
void push_commands(const commands_map &commands);
|
||||
|
||||
private:
|
||||
// members
|
||||
// contains command ready to execution
|
||||
commands_map m_commands;
|
||||
|
||||
// contains intercepted commands to be read by application layer
|
||||
commands_map m_intercept_queue;
|
||||
|
||||
void push_direct( command_data const &Command, uint32_t const Recipient );
|
||||
|
||||
// hash operator for m_active_continuous
|
||||
struct command_set_hash {
|
||||
uint64_t operator() (const std::pair<user_command, uint32_t> &pair) const {
|
||||
return ((uint64_t)pair.first << 32) | ((uint64_t) pair.second);
|
||||
}
|
||||
};
|
||||
|
||||
// currently pressed continuous commands
|
||||
std::unordered_set<std::pair<user_command, uint32_t>, command_set_hash> m_active_continuous;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
void add_to_dequemap(std::unordered_map<A, std::deque<B>> &lhs, const std::unordered_map<A, std::deque<B>> &rhs) {
|
||||
for (auto const &kv : rhs) {
|
||||
auto lookup = lhs.emplace(kv.first, std::deque<B>());
|
||||
for (B const &data : kv.second)
|
||||
lookup.first->second.emplace_back(data);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: simulation should be a (light) wrapper rather than namespace so we could potentially instance it,
|
||||
// but realistically it's not like we're going to run more than one simulation at a time
|
||||
namespace simulation {
|
||||
|
||||
typedef std::vector<command_description> commanddescription_sequence;
|
||||
|
||||
extern command_queue Commands;
|
||||
// TODO: add name to command map, and wrap these two into helper object
|
||||
extern commanddescription_sequence Commands_descriptions;
|
||||
|
||||
extern std::unordered_map<std::string, user_command> commandMap;
|
||||
}
|
||||
|
||||
// command_relay: composite class component, passes specified command to appropriate command stack
|
||||
|
||||
class command_relay {
|
||||
|
||||
public:
|
||||
// methods
|
||||
// posts specified command for the specified recipient
|
||||
void
|
||||
post(user_command const Command, double const Param1, double const Param2,
|
||||
int const Action, uint16_t Recipient, glm::vec3 Position = glm::vec3(0.0f) , const std::string *Payload = nullptr) const;
|
||||
private:
|
||||
// types
|
||||
// members
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
324
input/driverkeyboardinput.cpp
Normal file
324
input/driverkeyboardinput.cpp
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "driverkeyboardinput.h"
|
||||
|
||||
bool
|
||||
driverkeyboard_input::init() {
|
||||
|
||||
default_bindings();
|
||||
recall_bindings();
|
||||
bind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
driverkeyboard_input::default_bindings() {
|
||||
|
||||
m_bindingsetups = {
|
||||
{ user_command::aidriverenable, {GLFW_KEY_Q | keymodifier::shift, ""} },
|
||||
{ user_command::aidriverdisable, {GLFW_KEY_Q, ""} },
|
||||
// jointcontrollerset,
|
||||
{ user_command::mastercontrollerincrease, {GLFW_KEY_KP_ADD, ""} },
|
||||
{ user_command::mastercontrollerincreasefast, {GLFW_KEY_KP_ADD | keymodifier::shift, ""} },
|
||||
{ user_command::mastercontrollerdecrease, {GLFW_KEY_KP_SUBTRACT, ""} },
|
||||
{ user_command::mastercontrollerdecreasefast, {GLFW_KEY_KP_SUBTRACT | keymodifier::shift, ""} },
|
||||
// mastercontrollerset,
|
||||
{ user_command::secondcontrollerincrease, {GLFW_KEY_KP_DIVIDE, ""} },
|
||||
{ user_command::secondcontrollerincreasefast, {GLFW_KEY_KP_DIVIDE | keymodifier::shift, ""} },
|
||||
{ user_command::secondcontrollerdecrease, {GLFW_KEY_KP_MULTIPLY, ""} },
|
||||
{ user_command::secondcontrollerdecreasefast, {GLFW_KEY_KP_MULTIPLY | keymodifier::shift, ""} },
|
||||
// secondcontrollerset,
|
||||
{ user_command::mucurrentindicatorothersourceactivate, {GLFW_KEY_Z | keymodifier::shift, ""} },
|
||||
{ user_command::independentbrakeincrease, {GLFW_KEY_KP_1, ""} },
|
||||
{ user_command::independentbrakeincreasefast, {GLFW_KEY_KP_1 | keymodifier::shift, ""} },
|
||||
{ user_command::independentbrakedecrease, {GLFW_KEY_KP_7, ""} },
|
||||
{ user_command::independentbrakedecreasefast, {GLFW_KEY_KP_7 | keymodifier::shift, ""} },
|
||||
// independentbrakeset,
|
||||
{ user_command::independentbrakebailoff, {GLFW_KEY_KP_4, ""} },
|
||||
// universalbrakebutton1,
|
||||
// universalbrakebutton2,
|
||||
// universalbrakebutton3,
|
||||
{ user_command::trainbrakeincrease, {GLFW_KEY_KP_3, ""} },
|
||||
{ user_command::trainbrakedecrease, {GLFW_KEY_KP_9, ""} },
|
||||
// trainbrakeset,
|
||||
{ user_command::trainbrakecharging, {GLFW_KEY_KP_DECIMAL, ""} },
|
||||
{ user_command::trainbrakerelease, {GLFW_KEY_KP_6, ""} },
|
||||
{ user_command::trainbrakefirstservice, {GLFW_KEY_KP_8, ""} },
|
||||
{ user_command::trainbrakeservice, {GLFW_KEY_KP_5, ""} },
|
||||
{ user_command::trainbrakefullservice, {GLFW_KEY_KP_2, ""} },
|
||||
{ user_command::trainbrakehandleoff, {GLFW_KEY_KP_5 | keymodifier::control, ""} },
|
||||
{ user_command::trainbrakeemergency, {GLFW_KEY_KP_0, ""} },
|
||||
{ user_command::trainbrakebasepressureincrease, {GLFW_KEY_KP_3 | keymodifier::control, ""} },
|
||||
{ user_command::trainbrakebasepressuredecrease, {GLFW_KEY_KP_9 | keymodifier::control, ""} },
|
||||
{ user_command::trainbrakebasepressurereset, {GLFW_KEY_KP_6 | keymodifier::control, ""} },
|
||||
{ user_command::trainbrakeoperationtoggle, {GLFW_KEY_KP_4 | keymodifier::control, ""} },
|
||||
{ user_command::manualbrakeincrease, {GLFW_KEY_KP_1 | keymodifier::control, ""} },
|
||||
{ user_command::manualbrakedecrease, {GLFW_KEY_KP_7 | keymodifier::control, ""} },
|
||||
{ user_command::alarmchaintoggle, {GLFW_KEY_B | keymodifier::shift | keymodifier::control, ""} },
|
||||
// alarmchainenable,
|
||||
// alarmchaindisable,
|
||||
{ user_command::wheelspinbrakeactivate, {GLFW_KEY_KP_ENTER, ""} },
|
||||
{ user_command::sandboxactivate, {GLFW_KEY_S | keymodifier::shift, ""} },
|
||||
// autosandboxtoggle,
|
||||
// autosandboxactivate,
|
||||
// autosandboxdeactivate,
|
||||
{ user_command::reverserincrease, {GLFW_KEY_D, ""} },
|
||||
{ user_command::reverserdecrease, {GLFW_KEY_R, ""} },
|
||||
// reverserforwardhigh,
|
||||
// reverserforward,
|
||||
// reverserneutral,
|
||||
// reverserbackward,
|
||||
{ user_command::waterpumpbreakertoggle, {GLFW_KEY_W | keymodifier::control, ""} },
|
||||
// waterpumpbreakerclose,
|
||||
// waterpumpbreakeropen,
|
||||
{ user_command::waterpumptoggle, {GLFW_KEY_W, ""} },
|
||||
// waterpumpenable,
|
||||
// waterpumpdisable,
|
||||
{ user_command::waterheaterbreakertoggle, {GLFW_KEY_W | keymodifier::control | keymodifier::shift, ""} },
|
||||
// waterheaterbreakerclose,
|
||||
// waterheaterbreakeropen,
|
||||
{ user_command::waterheatertoggle, {GLFW_KEY_W | keymodifier::shift, ""} },
|
||||
// waterheaterenable,
|
||||
// waterheaterdisable,
|
||||
{ user_command::watercircuitslinktoggle, {GLFW_KEY_H | keymodifier::shift, ""} },
|
||||
// watercircuitslinkenable,
|
||||
// watercircuitslinkdisable,
|
||||
{ user_command::fuelpumptoggle, {GLFW_KEY_F, ""} },
|
||||
// fuelpumpenable,
|
||||
// fuelpumpdisable,
|
||||
{ user_command::oilpumptoggle, {GLFW_KEY_F | keymodifier::shift, ""} },
|
||||
// oilpumpenable,
|
||||
// oilpumpdisable,
|
||||
{ user_command::linebreakertoggle, {GLFW_KEY_M, ""} },
|
||||
// linebreakeropen,
|
||||
// linebreakerclose,
|
||||
{ user_command::convertertoggle, {GLFW_KEY_X, ""} },
|
||||
// converterenable,
|
||||
// converterdisable,
|
||||
{ user_command::convertertogglelocal, {GLFW_KEY_X | keymodifier::shift, ""} },
|
||||
{ user_command::converteroverloadrelayreset, {GLFW_KEY_N | keymodifier::control, ""} },
|
||||
{ user_command::compressortoggle, {GLFW_KEY_C, ""} },
|
||||
// compressorenable,
|
||||
// compressordisable,
|
||||
{ user_command::compressortogglelocal, {GLFW_KEY_C | keymodifier::shift, ""} },
|
||||
// compressorpresetactivatenext,
|
||||
// compressorpresetactivateprevious,
|
||||
// compressorpresetactivatedefault,
|
||||
{ user_command::motoroverloadrelaythresholdtoggle, {GLFW_KEY_F | keymodifier::control, ""} },
|
||||
// motoroverloadrelaythresholdsetlow,
|
||||
// motoroverloadrelaythresholdsethigh,
|
||||
{ user_command::motoroverloadrelayreset, {GLFW_KEY_N, ""} },
|
||||
// universalrelayreset1,
|
||||
// universalrelayreset2,
|
||||
// universalrelayreset3,
|
||||
{ user_command::notchingrelaytoggle, {GLFW_KEY_G, ""} },
|
||||
{ user_command::epbrakecontroltoggle, {GLFW_KEY_Z | keymodifier::control, ""} },
|
||||
// epbrakecontrolenable
|
||||
// epbrakecontroldisable
|
||||
{ user_command::trainbrakeoperationmodeincrease, {GLFW_KEY_KP_2 | keymodifier::control, ""} },
|
||||
{ user_command::trainbrakeoperationmodedecrease, {GLFW_KEY_KP_8 | keymodifier::control, ""} },
|
||||
{ user_command::brakeactingspeedincrease, {GLFW_KEY_B | keymodifier::shift, ""} },
|
||||
{ user_command::brakeactingspeeddecrease, {GLFW_KEY_B, ""} },
|
||||
// brakeactingspeedsetcargo,
|
||||
// brakeactingspeedsetpassenger,
|
||||
// brakeactingspeedsetrapid,
|
||||
{ user_command::brakeloadcompensationincrease, {GLFW_KEY_H | keymodifier::shift | keymodifier::control, ""} },
|
||||
{ user_command::brakeloadcompensationdecrease, {GLFW_KEY_H | keymodifier::control, ""} },
|
||||
{ user_command::mubrakingindicatortoggle, {GLFW_KEY_L | keymodifier::shift, ""} },
|
||||
{ user_command::alerteracknowledge, {GLFW_KEY_SPACE, ""} },
|
||||
{ user_command::hornlowactivate, {GLFW_KEY_A, ""} },
|
||||
{ user_command::hornhighactivate, {GLFW_KEY_S, ""} },
|
||||
{ user_command::whistleactivate, {GLFW_KEY_Z, ""} },
|
||||
{ user_command::radiotoggle, {GLFW_KEY_R | keymodifier::control, ""} },
|
||||
// radioenable
|
||||
// radiodisable
|
||||
{ user_command::radiochannelincrease, {GLFW_KEY_EQUAL, ""} },
|
||||
{ user_command::radiochanneldecrease, {GLFW_KEY_MINUS, ""} },
|
||||
// radiochannelset
|
||||
{ user_command::radiostopsend, {GLFW_KEY_PAUSE | keymodifier::shift | keymodifier::control, ""} },
|
||||
// radiostopenable
|
||||
// radiostopdisable
|
||||
{ user_command::radiostoptest, {GLFW_KEY_R | keymodifier::shift | keymodifier::control, ""} },
|
||||
{ user_command::radiocall3send, {GLFW_KEY_BACKSPACE, ""} },
|
||||
// radiovolumeincrease,
|
||||
// radiovolumedecrease,
|
||||
// radiovolumeset,
|
||||
{ user_command::cabchangeforward, {GLFW_KEY_HOME, ""} },
|
||||
{ user_command::cabchangebackward, {GLFW_KEY_END, ""} },
|
||||
// viewturn,
|
||||
// movehorizontal,
|
||||
// movehorizontalfast,
|
||||
// movevertical,
|
||||
// moveverticalfast,
|
||||
{ user_command::moveleft, {GLFW_KEY_LEFT, "Move left"} },
|
||||
{ user_command::moveright, {GLFW_KEY_RIGHT, "Move right"} },
|
||||
{ user_command::moveforward, {GLFW_KEY_UP, "Move forwards"} },
|
||||
{ user_command::moveback, {GLFW_KEY_DOWN, "Move backwards"} },
|
||||
{ user_command::moveup, {GLFW_KEY_PAGE_UP, "Move up"} },
|
||||
{ user_command::movedown, {GLFW_KEY_PAGE_DOWN, "Move down"} },
|
||||
{ user_command::nearestcarcouplingincrease, {GLFW_KEY_INSERT, ""} },
|
||||
{ user_command::nearestcarcouplingdisconnect, {GLFW_KEY_DELETE, ""} },
|
||||
{ user_command::nearestcarcoupleradapterattach, {GLFW_KEY_INSERT | keymodifier::control, ""} },
|
||||
{ user_command::nearestcarcoupleradapterremove, {GLFW_KEY_DELETE | keymodifier::control, ""} },
|
||||
{ user_command::occupiedcarcouplingdisconnect, {GLFW_KEY_DELETE | keymodifier::shift, ""} },
|
||||
{ user_command::doortoggleleft, {GLFW_KEY_COMMA, ""} },
|
||||
{ user_command::doortoggleright, {GLFW_KEY_PERIOD, ""} },
|
||||
{ user_command::doorpermitleft, {GLFW_KEY_COMMA | keymodifier::shift, ""} },
|
||||
{ user_command::doorpermitright, {GLFW_KEY_PERIOD | keymodifier::shift, ""} },
|
||||
{ user_command::doorpermitpresetactivatenext, {GLFW_KEY_PERIOD | keymodifier::shift | keymodifier::control, ""} },
|
||||
{ user_command::doorpermitpresetactivateprevious, {GLFW_KEY_COMMA | keymodifier::shift | keymodifier::control, ""} },
|
||||
// dooropenleft,
|
||||
// dooropenright,
|
||||
{ user_command::dooropenall, {GLFW_KEY_SLASH | keymodifier::shift, ""} },
|
||||
// doorcloseleft,
|
||||
// doorcloseright,
|
||||
{ user_command::doorcloseall, {GLFW_KEY_SLASH | keymodifier::control, ""} },
|
||||
// doorsteptoggle,
|
||||
{ user_command::doormodetoggle, {GLFW_KEY_SLASH | keymodifier::shift | keymodifier::control, ""} },
|
||||
// mirrorstoggle,
|
||||
{ user_command::departureannounce, {GLFW_KEY_SLASH, ""} },
|
||||
{ user_command::doorlocktoggle, {GLFW_KEY_S | keymodifier::control, ""} },
|
||||
{ user_command::pantographcompressorvalvetoggle, {GLFW_KEY_V | keymodifier::control, ""} },
|
||||
// pantographcompressorvalveenable,
|
||||
// pantographcompressorvalvedisable,
|
||||
{ user_command::pantographcompressoractivate, {GLFW_KEY_V | keymodifier::shift, ""} },
|
||||
{ user_command::pantographtogglefront, {GLFW_KEY_P, ""} },
|
||||
{ user_command::pantographtogglerear, {GLFW_KEY_O, ""} },
|
||||
// pantographraisefront,
|
||||
// pantographraiserear,
|
||||
// pantographlowerfront,
|
||||
// pantographlowerrear,
|
||||
{ user_command::pantographlowerall, {GLFW_KEY_P | keymodifier::control, ""} },
|
||||
{ user_command::pantographselectnext, {GLFW_KEY_P | keymodifier::shift, ""} },
|
||||
{ user_command::pantographselectprevious, {GLFW_KEY_O | keymodifier::shift, ""} },
|
||||
{ user_command::pantographtoggleselected, {GLFW_KEY_O | keymodifier::shift | keymodifier::control, ""} },
|
||||
// pantographraiseselected,
|
||||
// pantographlowerselected,
|
||||
// pantographvalvesupdate,
|
||||
// pantographvalvesoff,
|
||||
{ user_command::heatingtoggle, {GLFW_KEY_H, ""} },
|
||||
// heatingenable,
|
||||
// heatingdisable,
|
||||
{ user_command::lightspresetactivatenext, {GLFW_KEY_T | keymodifier::shift, ""} },
|
||||
{ user_command::lightspresetactivateprevious, {GLFW_KEY_T, ""} },
|
||||
{ user_command::headlighttoggleleft, {GLFW_KEY_Y, ""} },
|
||||
// headlightenableleft,
|
||||
// headlightdisableleft,
|
||||
{ user_command::headlighttoggleright, {GLFW_KEY_I, ""} },
|
||||
// headlightenableright,
|
||||
// headlightdisableright,
|
||||
{ user_command::headlighttoggleupper, {GLFW_KEY_U, ""} },
|
||||
// headlightenableupper,
|
||||
// headlightdisableupper,
|
||||
{ user_command::redmarkertoggleleft, {GLFW_KEY_Y | keymodifier::shift, ""} },
|
||||
// redmarkerenableleft,
|
||||
// redmarkerdisableleft,
|
||||
{ user_command::redmarkertoggleright, {GLFW_KEY_I | keymodifier::shift, ""} },
|
||||
// redmarkerenableright,
|
||||
// redmarkerdisableright,
|
||||
{ user_command::headlighttogglerearleft, {GLFW_KEY_Y | keymodifier::control, ""} },
|
||||
// headlightenablerearleft
|
||||
// headlightdisablerearleft
|
||||
{ user_command::headlighttogglerearright, {GLFW_KEY_I | keymodifier::control, ""} },
|
||||
// headlightenablerearright
|
||||
// headlightdisablerearright
|
||||
{ user_command::headlighttogglerearupper, {GLFW_KEY_U | keymodifier::control, ""} },
|
||||
// headlightenablerearupper
|
||||
// headlightdisablerearupper
|
||||
{ user_command::redmarkertogglerearleft, {GLFW_KEY_Y | keymodifier::control | keymodifier::shift, ""} },
|
||||
// redmarkerenablerearleft
|
||||
// redmarkerdisablerearleft
|
||||
{ user_command::redmarkertogglerearright, {GLFW_KEY_I | keymodifier::control | keymodifier::shift, ""} },
|
||||
// redmarkerenablerearright
|
||||
// redmarkerdisablerearright
|
||||
{ user_command::redmarkerstoggle, {GLFW_KEY_E | keymodifier::shift, ""} },
|
||||
{ user_command::endsignalstoggle, {GLFW_KEY_E, ""} },
|
||||
{ user_command::headlightsdimtoggle, {GLFW_KEY_L | keymodifier::control, ""} },
|
||||
// headlightsdimenable,
|
||||
// headlightsdimdisable,
|
||||
{ user_command::motorconnectorsopen, {GLFW_KEY_L, ""} },
|
||||
// motorconnectorsclose,
|
||||
{ user_command::motordisconnect, {GLFW_KEY_E | keymodifier::control, ""} },
|
||||
{ user_command::interiorlighttoggle, {GLFW_KEY_APOSTROPHE, ""} },
|
||||
// interiorlightenable,
|
||||
// interiorlightdisable,
|
||||
{ user_command::interiorlightdimtoggle, {GLFW_KEY_APOSTROPHE | keymodifier::control, ""} },
|
||||
// interiorlightdimenable,
|
||||
// interiorlightdimdisable,
|
||||
// compartmentlightstoggle,
|
||||
// compartmentlightsenable,
|
||||
// compartmentlightsdisable,
|
||||
{ user_command::instrumentlighttoggle, {GLFW_KEY_SEMICOLON, ""} },
|
||||
// instrumentlightenable,
|
||||
// instrumentlightdisable,
|
||||
{ user_command::dashboardlighttoggle, {GLFW_KEY_SEMICOLON | keymodifier::shift, ""} },
|
||||
// dashboardlightenable
|
||||
// dashboardlightdisable
|
||||
{ user_command::timetablelighttoggle, {GLFW_KEY_APOSTROPHE | keymodifier::shift, ""} },
|
||||
// timetablelightenable
|
||||
// timetablelightdisable
|
||||
{ user_command::generictoggle0, {GLFW_KEY_0, ""} },
|
||||
{ user_command::generictoggle1, {GLFW_KEY_1, ""} },
|
||||
{ user_command::generictoggle2, {GLFW_KEY_2, ""} },
|
||||
{ user_command::generictoggle3, {GLFW_KEY_3, ""} },
|
||||
{ user_command::generictoggle4, {GLFW_KEY_4, ""} },
|
||||
{ user_command::generictoggle5, {GLFW_KEY_5, ""} },
|
||||
{ user_command::generictoggle6, {GLFW_KEY_6, ""} },
|
||||
{ user_command::generictoggle7, {GLFW_KEY_7, ""} },
|
||||
{ user_command::generictoggle8, {GLFW_KEY_8, ""} },
|
||||
{ user_command::generictoggle9, {GLFW_KEY_9, ""} },
|
||||
{ user_command::batterytoggle, {GLFW_KEY_J, ""} },
|
||||
// batteryenable,
|
||||
// batterydisable,
|
||||
// cabactivationtoggle,
|
||||
// cabactivationenable,
|
||||
// cabactivationdisable,
|
||||
{ user_command::motorblowerstogglefront, {GLFW_KEY_N | keymodifier::shift, ""} },
|
||||
{ user_command::motorblowerstogglerear, {GLFW_KEY_M | keymodifier::shift, ""} },
|
||||
{ user_command::motorblowersdisableall, {GLFW_KEY_M | keymodifier::control, ""} },
|
||||
// coolingfanstoggle,
|
||||
// tempomattoggle,
|
||||
// springbraketoggle,
|
||||
// springbrakeenable,
|
||||
// springbrakedisable,
|
||||
// springbrakeshutofftoggle,
|
||||
// springbrakeshutoffenable,
|
||||
// springbrakeshutoffdisable,
|
||||
// springbrakerelease,
|
||||
// distancecounteractivate,
|
||||
// speedcontrolincrease,
|
||||
// speedcontroldecrease,
|
||||
// speedcontrolpowerincrease,
|
||||
// speedcontrolpowerdecrease,
|
||||
// speedcontrolbutton0,
|
||||
// speedcontrolbutton1,
|
||||
// speedcontrolbutton2,
|
||||
// speedcontrolbutton3,
|
||||
// speedcontrolbutton4,
|
||||
// speedcontrolbutton5,
|
||||
// speedcontrolbutton6,
|
||||
// speedcontrolbutton7,
|
||||
// speedcontrolbutton8,
|
||||
// speedcontrolbutton9,
|
||||
// admin_timejump,
|
||||
{ user_command::timejumplarge, {GLFW_KEY_F1 | keymodifier::control, "Big time jump (Debug Mode only)"} },
|
||||
{ user_command::timejumpsmall, {GLFW_KEY_F1 | keymodifier::shift, "Small time jump (Debug Mode only)"} },
|
||||
// admin_vehiclemove,
|
||||
{ user_command::vehiclemoveforwards, {GLFW_KEY_LEFT_BRACKET | keymodifier::control, "Move the train forwards (Debug Mode only)"} },
|
||||
{ user_command::vehiclemovebackwards, {GLFW_KEY_RIGHT_BRACKET | keymodifier::control, "Move the train backwards (Debug Mode only)"} },
|
||||
{ user_command::vehicleboost, {GLFW_KEY_TAB | keymodifier::control, "Boost the train (Debug Mode only)"} },
|
||||
{ user_command::debugtoggle, {GLFW_KEY_F12 | keymodifier::control | keymodifier::shift, "Toggle Debug Mode"} },
|
||||
{ user_command::pausetoggle, {GLFW_KEY_ESCAPE, "Pause the game"} }
|
||||
};
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
27
input/driverkeyboardinput.h
Normal file
27
input/driverkeyboardinput.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "keyboardinput.h"
|
||||
|
||||
class driverkeyboard_input : public keyboard_input {
|
||||
|
||||
public:
|
||||
// methods
|
||||
bool
|
||||
init() override;
|
||||
|
||||
protected:
|
||||
// methods
|
||||
void
|
||||
default_bindings();
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
1165
input/drivermouseinput.cpp
Normal file
1165
input/drivermouseinput.cpp
Normal file
File diff suppressed because it is too large
Load Diff
114
input/drivermouseinput.h
Normal file
114
input/drivermouseinput.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include "command.h"
|
||||
|
||||
// virtual slider; value determined by position of the mouse
|
||||
class mouse_slider {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
mouse_slider() = default;
|
||||
// methods
|
||||
void
|
||||
bind( user_command const &Command );
|
||||
void
|
||||
release();
|
||||
void
|
||||
on_move( double const Mousex, double const Mousey );
|
||||
inline
|
||||
user_command
|
||||
command() const {
|
||||
return m_command; }
|
||||
double
|
||||
value() const {
|
||||
return m_value; }
|
||||
|
||||
private:
|
||||
// members
|
||||
user_command m_command { user_command::none };
|
||||
double m_value { 0.0 };
|
||||
double m_valuerange { 0.0 };
|
||||
bool m_analogue { false };
|
||||
bool m_invertrange { false };
|
||||
glm::dvec2 m_cursorposition { 0.0 };
|
||||
};
|
||||
|
||||
class drivermouse_input {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
drivermouse_input() = default;
|
||||
|
||||
// methods
|
||||
bool
|
||||
init();
|
||||
bool
|
||||
recall_bindings();
|
||||
void
|
||||
button( int const Button, int const Action );
|
||||
int
|
||||
button( int const Button ) const;
|
||||
void
|
||||
move( double const Horizontal, double const Vertical );
|
||||
void
|
||||
scroll( double const Xoffset, double const Yoffset );
|
||||
void
|
||||
poll();
|
||||
user_command
|
||||
command() const;
|
||||
// returns pair of bindings associated with specified cab control
|
||||
std::pair<user_command, user_command>
|
||||
bindings( std::string const &Control ) const;
|
||||
|
||||
private:
|
||||
// types
|
||||
struct button_bindings {
|
||||
|
||||
user_command left;
|
||||
user_command right;
|
||||
};
|
||||
|
||||
struct wheel_bindings {
|
||||
|
||||
user_command up;
|
||||
user_command down;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<std::string, button_bindings> buttonbindings_map;
|
||||
|
||||
// methods
|
||||
void
|
||||
default_bindings();
|
||||
// potentially replaces supplied command with a more relevant one
|
||||
user_command
|
||||
adjust_command( user_command Command );
|
||||
|
||||
// members
|
||||
command_relay m_relay;
|
||||
mouse_slider m_slider; // virtual control, when active translates intercepted mouse position to a value
|
||||
buttonbindings_map m_buttonbindings;
|
||||
wheel_bindings m_wheelbindings { user_command::mastercontrollerincrease, user_command::mastercontrollerdecrease }; // commands bound to the scroll wheel
|
||||
user_command m_mousecommandleft { user_command::none }; // last if any command issued with left mouse button
|
||||
user_command m_mousecommandright { user_command::none }; // last if any command issued with right mouse button
|
||||
double m_updaterate { 0.075 };
|
||||
double m_updatedelay { 0.25 };
|
||||
double m_updateaccumulator { 0.0 };
|
||||
bool m_pickmodepanning { false }; // indicates mouse is in view panning mode
|
||||
glm::dvec2 m_cursorposition; // stored last cursor position, used for panning
|
||||
bool m_varyingpollrate { false }; // indicates rate of command repeats is affected by the cursor position
|
||||
glm::dvec2 m_varyingpollrateorigin; // helper, cursor position when the command was initiated
|
||||
std::array<int, GLFW_MOUSE_BUTTON_LAST> m_buttons;
|
||||
bool m_pickwaiting;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
37
input/editorkeyboardinput.cpp
Normal file
37
input/editorkeyboardinput.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "editorkeyboardinput.h"
|
||||
|
||||
bool
|
||||
editorkeyboard_input::init() {
|
||||
|
||||
default_bindings();
|
||||
// TODO: re-enable after mode-specific binding import is in place
|
||||
// return recall_bindings();
|
||||
bind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
editorkeyboard_input::default_bindings() {
|
||||
|
||||
m_bindingsetups = {
|
||||
{ user_command::moveleft, {GLFW_KEY_A, "Move left"} },
|
||||
{ user_command::moveright, {GLFW_KEY_D, "Move right"} },
|
||||
{ user_command::moveforward, {GLFW_KEY_W, "Move forwards"} },
|
||||
{ user_command::moveback, {GLFW_KEY_S, "Move backwards"} },
|
||||
{ user_command::moveup, {GLFW_KEY_E, "Move up"} },
|
||||
{ user_command::movedown, {GLFW_KEY_Q, "Move down"} },
|
||||
};
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
27
input/editorkeyboardinput.h
Normal file
27
input/editorkeyboardinput.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "keyboardinput.h"
|
||||
|
||||
class editorkeyboard_input : public keyboard_input {
|
||||
|
||||
public:
|
||||
// methods
|
||||
bool
|
||||
init() override;
|
||||
|
||||
protected:
|
||||
// methods
|
||||
void
|
||||
default_bindings() override;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
54
input/editormouseinput.cpp
Normal file
54
input/editormouseinput.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "editormouseinput.h"
|
||||
|
||||
bool
|
||||
editormouse_input::init() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
editormouse_input::position( double Horizontal, double Vertical ) {
|
||||
|
||||
if( false == m_pickmodepanning ) {
|
||||
// even if the view panning isn't active we capture the cursor position in case it does get activated
|
||||
m_cursorposition.x = Horizontal;
|
||||
m_cursorposition.y = Vertical;
|
||||
return;
|
||||
}
|
||||
glm::dvec2 cursorposition { Horizontal, Vertical };
|
||||
auto const viewoffset = cursorposition - m_cursorposition;
|
||||
m_relay.post(
|
||||
user_command::viewturn,
|
||||
viewoffset.x,
|
||||
viewoffset.y,
|
||||
GLFW_PRESS,
|
||||
// TODO: pass correct entity id once the missing systems are in place
|
||||
0 );
|
||||
m_cursorposition = cursorposition;
|
||||
}
|
||||
|
||||
void
|
||||
editormouse_input::button( int const Button, int const Action ) {
|
||||
|
||||
// store key state
|
||||
if( Button >= 0 ) {
|
||||
m_buttons[ Button ] = Action;
|
||||
}
|
||||
|
||||
// right button controls panning
|
||||
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
|
||||
m_pickmodepanning = ( Action == GLFW_PRESS );
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
44
input/editormouseinput.h
Normal file
44
input/editormouseinput.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "command.h"
|
||||
|
||||
class editormouse_input {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
editormouse_input() = default;
|
||||
|
||||
// methods
|
||||
bool
|
||||
init();
|
||||
void
|
||||
position( double const Horizontal, double const Vertical );
|
||||
inline
|
||||
glm::dvec2
|
||||
position() const {
|
||||
return m_cursorposition; }
|
||||
void
|
||||
button( int const Button, int const Action );
|
||||
inline
|
||||
int
|
||||
button( int const Button ) const {
|
||||
return m_buttons[ Button ]; }
|
||||
|
||||
private:
|
||||
// members
|
||||
command_relay m_relay;
|
||||
bool m_pickmodepanning { false }; // indicates mouse is in view panning mode
|
||||
glm::dvec2 m_cursorposition { 0.0 }; // stored last cursor position, used for panning
|
||||
std::array<int, GLFW_MOUSE_BUTTON_LAST> m_buttons { GLFW_RELEASE };
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
533
input/gamepadinput.cpp
Normal file
533
input/gamepadinput.cpp
Normal file
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "gamepadinput.h"
|
||||
#include "Logs.h"
|
||||
#include "Timer.h"
|
||||
#include "utilities.h"
|
||||
#include "parser.h"
|
||||
|
||||
glm::vec2 circle_to_square( glm::vec2 const &Point, int const Roundness = 0 ) {
|
||||
|
||||
// Determine the theta angle
|
||||
auto angle = std::atan2( Point.x, Point.y ) + M_PI;
|
||||
|
||||
glm::vec2 squared;
|
||||
// Scale according to which wall we're clamping to
|
||||
// X+ wall
|
||||
if( angle <= M_PI_4 || angle > 7 * M_PI_4 )
|
||||
squared = Point * (float)( 1.0 / std::cos( angle ) );
|
||||
// Y+ wall
|
||||
else if( angle > M_PI_4 && angle <= 3 * M_PI_4 )
|
||||
squared = Point * (float)( 1.0 / std::sin( angle ) );
|
||||
// X- wall
|
||||
else if( angle > 3 * M_PI_4 && angle <= 5 * M_PI_4 )
|
||||
squared = Point * (float)( -1.0 / std::cos( angle ) );
|
||||
// Y- wall
|
||||
else if( angle > 5 * M_PI_4 && angle <= 7 * M_PI_4 )
|
||||
squared = Point * (float)( -1.0 / std::sin( angle ) );
|
||||
|
||||
// Early-out for a perfect square output
|
||||
if( Roundness == 0 )
|
||||
return squared;
|
||||
|
||||
// Find the inner-roundness scaling factor and LERP
|
||||
auto const length = glm::length( Point );
|
||||
auto const factor = std::pow( length, Roundness );
|
||||
return interpolate( Point, squared, (float)factor );
|
||||
}
|
||||
|
||||
bool
|
||||
gamepad_input::init() {
|
||||
|
||||
m_inputaxes.clear();
|
||||
m_inputbuttons.clear();
|
||||
// NOTE: we're only checking for joystick_1 and rely for it to stay connected throughout.
|
||||
// not exactly flexible, but for quick hack it'll do
|
||||
auto const name = glfwGetJoystickName( GLFW_JOYSTICK_1 );
|
||||
if( name != nullptr ) {
|
||||
WriteLog( "Connected gamepad: " + std::string( name ) );
|
||||
m_deviceid = GLFW_JOYSTICK_1;
|
||||
}
|
||||
else {
|
||||
// no joystick,
|
||||
WriteLog( "No gamepad detected" );
|
||||
return false;
|
||||
}
|
||||
|
||||
int count;
|
||||
|
||||
glfwGetJoystickAxes( m_deviceid, &count );
|
||||
m_inputaxes.assign( count, { 0.0f, 0.0f, {} } );
|
||||
|
||||
glfwGetJoystickButtons( m_deviceid, &count );
|
||||
m_inputbuttons.assign( count, { GLFW_RELEASE, -1, user_command::none } );
|
||||
|
||||
recall_bindings();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// checks state of the controls and sends issued commands
|
||||
void
|
||||
gamepad_input::poll() {
|
||||
|
||||
if( m_deviceid == -1 ) {
|
||||
// if there's no gamepad we can skip the rest
|
||||
return;
|
||||
}
|
||||
|
||||
int count;
|
||||
std::size_t idx = 0;
|
||||
// poll button state
|
||||
auto const buttons = glfwGetJoystickButtons( m_deviceid, &count );
|
||||
if( count ) { // safety check in case joystick gets pulled out
|
||||
for( auto &button : m_inputbuttons ) {
|
||||
|
||||
if( button.state != buttons[ idx ] ) {
|
||||
// button pressed or released, both are important
|
||||
on_button(
|
||||
idx,
|
||||
( buttons[ idx ] == 1 ?
|
||||
GLFW_PRESS :
|
||||
GLFW_RELEASE ) );
|
||||
}
|
||||
else {
|
||||
// otherwise we only pass info about button being held down
|
||||
if( button.state == GLFW_PRESS ) {
|
||||
|
||||
on_button(
|
||||
idx,
|
||||
GLFW_REPEAT );
|
||||
}
|
||||
}
|
||||
button.state = buttons[ idx ];
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
// poll axes state
|
||||
idx = 0;
|
||||
auto const axes = glfwGetJoystickAxes( m_deviceid, &count );
|
||||
if( count ) {
|
||||
// safety check in case joystick gets pulled out
|
||||
for( auto &axis : m_inputaxes ) {
|
||||
axis.state = axes[ idx ];
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
process_axes();
|
||||
}
|
||||
|
||||
void
|
||||
gamepad_input::bind( std::vector< std::reference_wrapper<user_command> > &Targets, cParser &Input, std::unordered_map<std::string, user_command> const &Translator, std::string const Point ) {
|
||||
|
||||
for( auto &bindingtarget : Targets ) {
|
||||
// grab command(s) associated with the input pin
|
||||
auto const bindingcommandname{ Input.getToken<std::string>() };
|
||||
if( true == bindingcommandname.empty() ) {
|
||||
// no tokens left, may as well complain...
|
||||
WriteLog( "Gamepad binding for " + Point + " didn't specify associated command(s)" );
|
||||
// ...can't quit outright though, as provided references are likely to be unitialized
|
||||
bindingtarget.get() = user_command::none;
|
||||
continue;
|
||||
}
|
||||
auto const commandlookup = Translator.find( bindingcommandname );
|
||||
if( commandlookup == Translator.end() ) {
|
||||
WriteLog( "Gamepad binding for " + Point + " specified unknown command, \"" + bindingcommandname + "\"" );
|
||||
bindingtarget.get() = user_command::none;
|
||||
}
|
||||
else {
|
||||
bindingtarget.get() = commandlookup->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
bool
|
||||
gamepad_input::recall_bindings() {
|
||||
std::string filePath = "eu07_input-gamepad.ini";
|
||||
|
||||
#ifdef _WIN32
|
||||
if (const char *appdata = std::getenv("APPDATA"))
|
||||
{
|
||||
fs::path appPath = fs::path(appdata) / "MaSzyna" / "eu07_input-gamepad.ini";
|
||||
if (fs::exists(appPath))
|
||||
filePath = appPath.string();
|
||||
}
|
||||
#else
|
||||
if (const char *home = std::getenv("HOME"))
|
||||
{
|
||||
fs::path appPath = fs::path(home) / ".config" / "MaSzyna" / "eu07_input-gamepad.ini";
|
||||
if (fs::exists(appPath))
|
||||
filePath = appPath.string();
|
||||
}
|
||||
#endif
|
||||
|
||||
// bindingparser tworzony zawsze, z wybran¹ œcie¿k¹
|
||||
cParser bindingparser(filePath.c_str(), cParser::buffer_FILE);
|
||||
|
||||
if( false == bindingparser.ok() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// build helper translation tables
|
||||
std::unordered_map<std::string, user_command> nametocommandmap;
|
||||
std::size_t commandid = 0;
|
||||
for( auto const &description : simulation::Commands_descriptions ) {
|
||||
nametocommandmap.emplace(
|
||||
description.name,
|
||||
static_cast<user_command>( commandid ) );
|
||||
++commandid;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, input_type> nametotypemap {
|
||||
{ "3state", input_type::threestate },
|
||||
{ "value", input_type::value },
|
||||
{ "value_invert", input_type::value_invert } };
|
||||
|
||||
// NOTE: to simplify things we expect one entry per line, and whole entry in one line
|
||||
while( true == bindingparser.getTokens( 1, true, "\n\r" ) ) {
|
||||
|
||||
std::string bindingentry;
|
||||
bindingparser >> bindingentry;
|
||||
cParser entryparser( bindingentry );
|
||||
|
||||
if( false == entryparser.getTokens( 1, true, "\n\r\t " ) ) { continue; }
|
||||
|
||||
std::string bindingpoint {};
|
||||
entryparser >> bindingpoint;
|
||||
auto const splitbindingpoint { split_string_and_number( bindingpoint ) };
|
||||
|
||||
if( splitbindingpoint.first == "axis" ) {
|
||||
// one or more sets of: [modeIDX] input type, parameters
|
||||
// [optional] modeIDX associates the set with control mode IDX
|
||||
// input types:
|
||||
// -- range commandname IDX; axis value is passed as paramIDX of commandname
|
||||
// -- 3state commandname commandname; positive axis value issues first commandname, negative value issues second commandname
|
||||
|
||||
auto const axisindex { splitbindingpoint.second };
|
||||
// sanity check, connected gamepad isn't guaranteed to have that many axes
|
||||
if( axisindex >= m_inputaxes.size() ) { continue; }
|
||||
|
||||
int controlmode { -1 }; // unless stated otherwise the set will be associated with the default control mode
|
||||
|
||||
while( true == entryparser.getTokens( 1, true, "\n\r\t " ) ) {
|
||||
|
||||
std::string key {};
|
||||
entryparser >> key;
|
||||
// check for potential mode indicator
|
||||
auto const splitkey { split_string_and_number( key ) };
|
||||
if( splitkey.first == "mode" ) {
|
||||
// indicate we'll be processing specified mode
|
||||
controlmode = splitkey.second;
|
||||
continue;
|
||||
}
|
||||
// if we're still here handle the original key as binding type
|
||||
std::string const bindingtypename { key };
|
||||
auto const typelookup = nametotypemap.find( bindingtypename );
|
||||
if( typelookup == nametotypemap.end() ) {
|
||||
|
||||
WriteLog( "Gamepad binding for " + bindingpoint + " specified unknown control type, \"" + bindingtypename + "\"" );
|
||||
}
|
||||
else {
|
||||
|
||||
std::vector< std::reference_wrapper<user_command> > bindingtargets;
|
||||
auto const bindingtype { typelookup->second };
|
||||
std::get<0>( m_inputaxes[ axisindex ].bindings[ controlmode ] ) = bindingtype;
|
||||
// retrieve regular commands associated with the axis and mode
|
||||
switch( bindingtype ) {
|
||||
case input_type::value:
|
||||
case input_type::value_invert: {
|
||||
bindingtargets.emplace_back( std::ref( std::get<1>( m_inputaxes[ axisindex ].bindings[ controlmode ] ) ) );
|
||||
break;
|
||||
}
|
||||
case input_type::threestate: {
|
||||
bindingtargets.emplace_back( std::ref( std::get<1>( m_inputaxes[ axisindex ].bindings[ controlmode ] ) ) );
|
||||
bindingtargets.emplace_back( std::ref( std::get<2>( m_inputaxes[ axisindex ].bindings[ controlmode ] ) ) );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
bind( bindingtargets, entryparser, nametocommandmap, bindingpoint );
|
||||
// handle potential remaining input type-specific parameters
|
||||
switch( bindingtype ) {
|
||||
case input_type::value:
|
||||
case input_type::value_invert: {
|
||||
auto const paramidxname { entryparser.getToken<std::string>() };
|
||||
auto const paramidx { (
|
||||
// exceptions
|
||||
paramidxname == "y" ? 1 :
|
||||
paramidxname == "2" ? 1 : // human-readable param index starts with 1
|
||||
// default
|
||||
0 ) };
|
||||
std::get<2>( m_inputaxes[ axisindex ].bindings[ controlmode ] ) = static_cast<user_command>( paramidx );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( splitbindingpoint.first == "button" ) {
|
||||
|
||||
auto const buttonindex { splitbindingpoint.second };
|
||||
// sanity check, connected gamepad isn't guaranteed to have that many buttons
|
||||
if( buttonindex >= m_inputbuttons.size() ) { continue; }
|
||||
|
||||
auto const bindingtype { entryparser.getToken<std::string>() };
|
||||
if( bindingtype == "mode" ) {
|
||||
// special case, mode selector
|
||||
if( true == entryparser.getTokens( 1, true, "\n\r\t " ) ) {
|
||||
entryparser >> m_inputbuttons[ buttonindex ].mode;
|
||||
}
|
||||
else {
|
||||
WriteLog( "Gamepad binding for " + bindingpoint + " didn't specify mode index" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// regular button, single bound command
|
||||
std::vector< std::reference_wrapper<user_command> > bindingtargets;
|
||||
bindingtargets.emplace_back( std::ref( m_inputbuttons[ buttonindex ].binding ) );
|
||||
bind( bindingtargets, entryparser, nametocommandmap, bindingpoint );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
gamepad_input::on_button( int const Button, int const Action ) {
|
||||
|
||||
auto const &button { m_inputbuttons[ Button ] };
|
||||
|
||||
if( button.mode >= 0 ) {
|
||||
|
||||
switch( Action ) {
|
||||
case GLFW_PRESS: {
|
||||
for( auto &axis : m_inputaxes ) {
|
||||
axis.accumulator = 0.0f;
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
case GLFW_REPEAT: {
|
||||
m_mode = Button;
|
||||
break;
|
||||
}
|
||||
case GLFW_RELEASE: {
|
||||
if( m_mode == Button ) {
|
||||
m_mode = -1;
|
||||
for( auto &axis : m_inputaxes ) {
|
||||
axis.accumulator = 0.0f;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( button.binding != user_command::none ) {
|
||||
|
||||
m_relay.post(
|
||||
button.binding,
|
||||
0,
|
||||
0,
|
||||
Action,
|
||||
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
|
||||
// TODO: pass correct entity id once the missing systems are in place
|
||||
0 );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gamepad_input::process_axes() {
|
||||
|
||||
input_type inputtype;
|
||||
user_command boundcommand1, boundcommand2;
|
||||
auto binding { std::tie( inputtype, boundcommand1, boundcommand2 ) };
|
||||
|
||||
// since some commands can potentially collect values from two different axes we can't post them directly
|
||||
// instead, we use a small scratchpad to first put these commands together, then post them in their completed state
|
||||
std::unordered_map<user_command, std::tuple< double, double, int > > commands;
|
||||
// HACK: generate movement reset, it'll be eiter overriden by actual movement command, or issued if another control mode was activated
|
||||
commands[ user_command::movehorizontal ] = { 0.0, 0.0, GLFW_PRESS };
|
||||
|
||||
for( auto &axis : m_inputaxes ) {
|
||||
|
||||
if( axis.bindings.empty() ) { continue; }
|
||||
|
||||
auto const lookup { axis.bindings.find( m_mode ) };
|
||||
if( lookup == axis.bindings.end() ) { continue; }
|
||||
|
||||
binding = lookup->second;
|
||||
|
||||
switch( inputtype ) {
|
||||
case input_type::threestate: {
|
||||
// TODO: separate multiplier for each mode, to allow different, customizable sensitivity for each control
|
||||
auto const deltatime { Timer::GetDeltaTime() * 15.0 };
|
||||
if( axis.state >= 0.0f ) {
|
||||
// first bound command selected
|
||||
if( axis.accumulator < 0.0f ) {
|
||||
// we were issuing the other command, post notification that's no longer the case
|
||||
if( boundcommand2 != user_command::none ) {
|
||||
m_relay.post(
|
||||
boundcommand2,
|
||||
0, 0,
|
||||
GLFW_RELEASE,
|
||||
0 );
|
||||
axis.accumulator = 0.0f;
|
||||
}
|
||||
}
|
||||
if( boundcommand1 != user_command::none ) {
|
||||
if( axis.state > m_deadzone ) {
|
||||
axis.accumulator += ( axis.state - m_deadzone ) / ( 1.0 - m_deadzone ) * deltatime;
|
||||
// we're making sure there's always a positive charge left in the accumulator,
|
||||
// to more reliably decect when the stick goes from active to dead zone, below
|
||||
while( axis.accumulator > 1.0f ) {
|
||||
// send commands if the accumulator(s) was filled
|
||||
m_relay.post(
|
||||
boundcommand1,
|
||||
0, 0,
|
||||
GLFW_PRESS,
|
||||
0 );
|
||||
axis.accumulator -= 1.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if the accumulator isn't empty it's an indicator the stick moved from active to neutral zone
|
||||
// indicate it with proper RELEASE command
|
||||
m_relay.post(
|
||||
boundcommand1,
|
||||
0, 0,
|
||||
GLFW_RELEASE,
|
||||
0 );
|
||||
axis.accumulator = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// second bound command selected
|
||||
if( axis.accumulator > 0.0f ) {
|
||||
// we were issuing the other command, post notification that's no longer the case
|
||||
if( boundcommand1 != user_command::none ) {
|
||||
m_relay.post(
|
||||
boundcommand1,
|
||||
0, 0,
|
||||
GLFW_RELEASE,
|
||||
0 );
|
||||
axis.accumulator = 0.0f;
|
||||
}
|
||||
}
|
||||
if( boundcommand1 != user_command::none ) {
|
||||
if( axis.state < -m_deadzone ) {
|
||||
axis.accumulator += ( axis.state + m_deadzone ) / ( 1.0 - m_deadzone ) * deltatime;
|
||||
// we're making sure there's always a positive charge left in the accumulator,
|
||||
// to more reliably decect when the stick goes from active to dead zone, below
|
||||
while( axis.accumulator < -1.0f ) {
|
||||
// send commands if the accumulator(s) was filled
|
||||
m_relay.post(
|
||||
boundcommand2,
|
||||
0, 0,
|
||||
GLFW_PRESS,
|
||||
0 );
|
||||
axis.accumulator += 1.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if the accumulator isn't empty it's an indicator the stick moved from active to neutral zone
|
||||
// indicate it with proper RELEASE command
|
||||
m_relay.post(
|
||||
boundcommand2,
|
||||
0, 0,
|
||||
GLFW_RELEASE,
|
||||
0 );
|
||||
axis.accumulator = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case input_type::value:
|
||||
case input_type::value_invert: {
|
||||
auto &command { commands[ boundcommand1 ] };
|
||||
std::get<int>( command ) = GLFW_PRESS;
|
||||
auto ¶m { (
|
||||
static_cast<int>( boundcommand2 ) == 0 ? // for this type boundcommand2 stores param index
|
||||
std::get<0>( command ) :
|
||||
std::get<1>( command ) ) };
|
||||
param = axis.state;
|
||||
if( std::abs( param ) < m_deadzone ) {
|
||||
param = 0.0;
|
||||
}
|
||||
else {
|
||||
param = (
|
||||
param > 0.0 ?
|
||||
( param - m_deadzone ) / ( 1.0 - m_deadzone ) :
|
||||
( param + m_deadzone ) / ( 1.0 - m_deadzone ) );
|
||||
}
|
||||
if( param != 0.0 ) {
|
||||
if( inputtype == input_type::value_invert ) {
|
||||
param *= -1.0;
|
||||
}
|
||||
}
|
||||
// scale passed value according to command type
|
||||
switch( boundcommand1 ) {
|
||||
case user_command::viewturn: {
|
||||
param *= 10.0 * ( Timer::GetDeltaRenderTime() * 60.0 );
|
||||
break;
|
||||
}
|
||||
case user_command::movehorizontal:
|
||||
case user_command::movehorizontalfast: {
|
||||
// these expect value in -1:1 range
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// commands generally expect their parameter to be in 0:1 range
|
||||
param = param * 0.5 + 0.5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// issue remaining, assembled commands
|
||||
for( auto const &command : commands ) {
|
||||
auto const param1 { std::get<0>( command.second ) };
|
||||
auto const param2 { std::get<1>( command.second ) };
|
||||
auto &lastparams { m_lastcommandparams[ command.first ] };
|
||||
if( ( param1 != 0.0 ) || ( std::get<0>( lastparams ) != 0.0 )
|
||||
|| ( param2 != 0.0 ) || ( std::get<1>( lastparams ) != 0.0 ) ) {
|
||||
m_relay.post(
|
||||
command.first,
|
||||
param1,
|
||||
param2,
|
||||
std::get<2>( command.second ),
|
||||
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
|
||||
// TODO: pass correct entity id once the missing systems are in place
|
||||
0 );
|
||||
lastparams = std::tie( param1, param2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
95
input/gamepadinput.h
Normal file
95
input/gamepadinput.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "command.h"
|
||||
#include "parser.h"
|
||||
|
||||
class gamepad_input {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
gamepad_input() = default;
|
||||
|
||||
// methods
|
||||
// checks state of the controls and sends issued commands
|
||||
bool
|
||||
init();
|
||||
void
|
||||
poll();
|
||||
|
||||
private:
|
||||
// types
|
||||
/*
|
||||
enum gamepad_button {
|
||||
a,
|
||||
b,
|
||||
x,
|
||||
y,
|
||||
left_shoulder,
|
||||
right_shoulder,
|
||||
back,
|
||||
start,
|
||||
left_sticker,
|
||||
right_sticker,
|
||||
dpad_up,
|
||||
dpad_right,
|
||||
dpad_down,
|
||||
dpad_left
|
||||
};
|
||||
enum gamepad_axes {
|
||||
leftstick_x,
|
||||
leftstick_y,
|
||||
rightstick_x,
|
||||
rightstick_y,
|
||||
lefttrigger,
|
||||
righttrigger
|
||||
};
|
||||
*/
|
||||
enum class input_type {
|
||||
threestate, // two commands, mapped to positive and negative axis value respectively; press and release events on state change
|
||||
impulse, // one command; press event when set, release when cleared
|
||||
value, // one command; press event, axis value passed as specified param (stored as second 'user_command')
|
||||
value_invert // the passed value is additionally multiplied by -1
|
||||
};
|
||||
|
||||
struct input_button {
|
||||
unsigned char state; // last polled state
|
||||
int mode; // associated control mode
|
||||
user_command binding; // associated command
|
||||
};
|
||||
|
||||
struct input_axis {
|
||||
float state; // last polled state
|
||||
float accumulator; // multipurpose helper variable
|
||||
std::unordered_map< int, std::tuple< input_type, user_command, user_command > > bindings; // associated commands for respective modes
|
||||
};
|
||||
|
||||
using inputbutton_sequence = std::vector<input_button>;
|
||||
using inputaxis_sequence = std::vector<input_axis>;
|
||||
// methods
|
||||
bool recall_bindings();
|
||||
void bind( std::vector< std::reference_wrapper<user_command> > &Targets, cParser &Input, std::unordered_map<std::string, user_command> const &Translator, std::string const Point );
|
||||
void on_button( int const Button, int const Action );
|
||||
void process_axes();
|
||||
|
||||
// members
|
||||
command_relay m_relay;
|
||||
inputbutton_sequence m_inputbuttons;
|
||||
inputaxis_sequence m_inputaxes;
|
||||
int m_deviceid{ -1 };
|
||||
int m_mode{ -1 }; // currently active control mode
|
||||
float m_deadzone{ 0.15f }; // TODO: allow to configure this
|
||||
// double m_modeaccumulator{ 0.0 }; // used to throttle command input rate for vehicle controls
|
||||
std::unordered_map< user_command, std::tuple<double, double> > m_lastcommandparams; // cached parameters for last issued command of given type
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
480
input/keyboardinput.cpp
Normal file
480
input/keyboardinput.cpp
Normal file
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "keyboardinput.h"
|
||||
#include "Globals.h"
|
||||
#include "Logs.h"
|
||||
#include "parser.h"
|
||||
|
||||
namespace input {
|
||||
|
||||
std::array<char, GLFW_KEY_LAST + 1> keys { GLFW_RELEASE };
|
||||
bool key_alt;
|
||||
bool key_ctrl;
|
||||
bool key_shift;
|
||||
|
||||
}
|
||||
|
||||
std::unordered_map<int, std::string> keyboard_input::keytonamemap =
|
||||
{
|
||||
{ GLFW_KEY_0, "0" },
|
||||
{ GLFW_KEY_1, "1" },
|
||||
{ GLFW_KEY_2, "2" },
|
||||
{ GLFW_KEY_3, "3" },
|
||||
{ GLFW_KEY_4, "4" },
|
||||
{ GLFW_KEY_5, "5" },
|
||||
{ GLFW_KEY_6, "6" },
|
||||
{ GLFW_KEY_7, "7" },
|
||||
{ GLFW_KEY_8, "8" },
|
||||
{ GLFW_KEY_9, "9" },
|
||||
{ GLFW_KEY_MINUS, "-" },
|
||||
{ GLFW_KEY_EQUAL, "=" },
|
||||
{ GLFW_KEY_A, "a" },
|
||||
{ GLFW_KEY_B, "b" },
|
||||
{ GLFW_KEY_C, "c" },
|
||||
{ GLFW_KEY_D, "d" },
|
||||
{ GLFW_KEY_E, "e" },
|
||||
{ GLFW_KEY_F, "f" },
|
||||
{ GLFW_KEY_G, "g" },
|
||||
{ GLFW_KEY_H, "h" },
|
||||
{ GLFW_KEY_I, "i" },
|
||||
{ GLFW_KEY_J, "j" },
|
||||
{ GLFW_KEY_K, "k" },
|
||||
{ GLFW_KEY_L, "l" },
|
||||
{ GLFW_KEY_M, "m" },
|
||||
{ GLFW_KEY_N, "n" },
|
||||
{ GLFW_KEY_O, "o" },
|
||||
{ GLFW_KEY_P, "p" },
|
||||
{ GLFW_KEY_Q, "q" },
|
||||
{ GLFW_KEY_R, "r" },
|
||||
{ GLFW_KEY_S, "s" },
|
||||
{ GLFW_KEY_T, "t" },
|
||||
{ GLFW_KEY_U, "u" },
|
||||
{ GLFW_KEY_V, "v" },
|
||||
{ GLFW_KEY_W, "w" },
|
||||
{ GLFW_KEY_X, "x" },
|
||||
{ GLFW_KEY_Y, "y" },
|
||||
{ GLFW_KEY_Z, "z" },
|
||||
{ GLFW_KEY_MINUS, "-" },
|
||||
{ GLFW_KEY_EQUAL, "=" },
|
||||
{ GLFW_KEY_BACKSPACE, "backspace" },
|
||||
{ GLFW_KEY_LEFT_BRACKET, "[" },
|
||||
{ GLFW_KEY_RIGHT_BRACKET, "]" },
|
||||
{ GLFW_KEY_BACKSLASH, "\\" },
|
||||
{ GLFW_KEY_SEMICOLON, ";" },
|
||||
{ GLFW_KEY_APOSTROPHE, "'" },
|
||||
{ GLFW_KEY_ENTER, "enter" },
|
||||
{ GLFW_KEY_COMMA, "," },
|
||||
{ GLFW_KEY_PERIOD, "." },
|
||||
{ GLFW_KEY_SLASH, "/" },
|
||||
{ GLFW_KEY_SPACE, "space" },
|
||||
{ GLFW_KEY_PAUSE, "pause" },
|
||||
{ GLFW_KEY_INSERT, "insert" },
|
||||
{ GLFW_KEY_DELETE, "delete" },
|
||||
{ GLFW_KEY_HOME, "home" },
|
||||
{ GLFW_KEY_END, "end" },
|
||||
{ GLFW_KEY_KP_DIVIDE, "num_/" },
|
||||
{ GLFW_KEY_KP_MULTIPLY, "num_*" },
|
||||
{ GLFW_KEY_KP_SUBTRACT, "num_-" },
|
||||
{ GLFW_KEY_KP_7, "num_7" },
|
||||
{ GLFW_KEY_KP_8, "num_8" },
|
||||
{ GLFW_KEY_KP_9, "num_9" },
|
||||
{ GLFW_KEY_KP_ADD, "num_+" },
|
||||
{ GLFW_KEY_KP_4, "num_4" },
|
||||
{ GLFW_KEY_KP_5, "num_5" },
|
||||
{ GLFW_KEY_KP_6, "num_6" },
|
||||
{ GLFW_KEY_KP_1, "num_1" },
|
||||
{ GLFW_KEY_KP_2, "num_2" },
|
||||
{ GLFW_KEY_KP_3, "num_3" },
|
||||
{ GLFW_KEY_KP_ENTER, "num_enter" },
|
||||
{ GLFW_KEY_KP_0, "num_0" },
|
||||
{ GLFW_KEY_KP_DECIMAL, "num_." },
|
||||
{ GLFW_KEY_F1, "f1" },
|
||||
{ GLFW_KEY_F2, "f2" },
|
||||
{ GLFW_KEY_F3, "f3" },
|
||||
{ GLFW_KEY_F4, "f4" },
|
||||
{ GLFW_KEY_F5, "f5" },
|
||||
{ GLFW_KEY_F6, "f6" },
|
||||
{ GLFW_KEY_F7, "f7" },
|
||||
{ GLFW_KEY_F8, "f8" },
|
||||
{ GLFW_KEY_F9, "f9" },
|
||||
{ GLFW_KEY_F10, "f10" },
|
||||
{ GLFW_KEY_F11, "f11" },
|
||||
{ GLFW_KEY_F12, "f12" },
|
||||
{ GLFW_KEY_TAB, "tab" },
|
||||
{ GLFW_KEY_ESCAPE, "esc" },
|
||||
{ GLFW_KEY_LEFT, "left" },
|
||||
{ GLFW_KEY_RIGHT, "right" },
|
||||
{ GLFW_KEY_UP, "up" },
|
||||
{ GLFW_KEY_DOWN, "down" },
|
||||
{ GLFW_KEY_PAGE_UP, "page_up" },
|
||||
{ GLFW_KEY_PAGE_DOWN, "page_down" },
|
||||
};
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
bool
|
||||
keyboard_input::recall_bindings() {
|
||||
|
||||
fs::path iniPath;
|
||||
std::string path = "";
|
||||
#ifdef _WIN32
|
||||
if (const char *appdata = std::getenv("APPDATA"))
|
||||
{
|
||||
iniPath = fs::path(appdata) / "MaSzyna" / "eu07_input-keyboard.ini";
|
||||
}
|
||||
#else
|
||||
if (const char *home = std::getenv("HOME"))
|
||||
{
|
||||
iniPath = fs::path(home) / ".config" / "MaSzyna" / "eu07_input-keyboard.ini";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!iniPath.empty() && fs::exists(iniPath))
|
||||
{
|
||||
// Plik istnieje w AppData / ~/.config
|
||||
path = iniPath.string().c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback – plik w folderze symulatora
|
||||
path = "eu07_input-keyboard.ini";
|
||||
}
|
||||
cParser bindingparser(path.c_str(), cParser::buffer_FILE);
|
||||
|
||||
bindingparser.skipComments = false;
|
||||
if( false == bindingparser.ok() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// build helper translation tables
|
||||
std::unordered_map<std::string, user_command> nametocommandmap;
|
||||
std::size_t commandid = 0;
|
||||
for( auto const &description : simulation::Commands_descriptions ) {
|
||||
nametocommandmap.emplace(
|
||||
description.name,
|
||||
static_cast<user_command>( commandid ) );
|
||||
++commandid;
|
||||
}
|
||||
std::unordered_map<std::string, int> nametokeymap;
|
||||
|
||||
for (const std::pair<int, std::string> &key : keytonamemap) {
|
||||
nametokeymap.emplace(key.second, key.first);
|
||||
}
|
||||
|
||||
// NOTE: to simplify things we expect one entry per line, and whole entry in one line
|
||||
while( true == bindingparser.getTokens( 1, true, "\n\r" ) ) {
|
||||
|
||||
std::string bindingentry;
|
||||
bindingparser >> bindingentry;
|
||||
cParser entryparser( bindingentry );
|
||||
entryparser.skipComments = false;
|
||||
if( true == entryparser.getTokens( 1, true, "\n\r\t " ) ) {
|
||||
|
||||
std::string commandname;
|
||||
entryparser >> commandname;
|
||||
|
||||
auto const lookup = nametocommandmap.find( commandname );
|
||||
if( lookup == nametocommandmap.end() ) {
|
||||
|
||||
WriteLog( "Keyboard binding defined for unknown command, \"" + commandname + "\"" );
|
||||
}
|
||||
else {
|
||||
int keycode = 0;
|
||||
std::string description = "";
|
||||
bool descriptionStarted = false;
|
||||
while( entryparser.getTokens( 1, true, "\n\r\t " ) ) {
|
||||
|
||||
std::string bindingkeyname;
|
||||
entryparser >> bindingkeyname;
|
||||
|
||||
// Parse command description, starting with "//".
|
||||
// TODO: At some point, rewind this and add translation keys instead for multilingual support.
|
||||
// This can't be done now as by default this would destroy all command descriptions,
|
||||
// which are used by Starter.
|
||||
// Do this when szczawik's Starter becomes deprecated or implements command descriptions in some other way.
|
||||
if (descriptionStarted) {
|
||||
if (description.size() > 0) {
|
||||
description += " ";
|
||||
}
|
||||
description += bindingkeyname;
|
||||
} else if (bindingkeyname == "//") {
|
||||
descriptionStarted = true;
|
||||
} else {
|
||||
if( bindingkeyname == "shift" ) { keycode |= keymodifier::shift; }
|
||||
else if( bindingkeyname == "ctrl" ) { keycode |= keymodifier::control; }
|
||||
else if( bindingkeyname == "none" ) { keycode = 0; }
|
||||
else {
|
||||
// regular key, convert it to glfw key code
|
||||
auto const keylookup = nametokeymap.find( bindingkeyname );
|
||||
if( keylookup == nametokeymap.end() ) {
|
||||
|
||||
WriteLog( "Keyboard binding included unrecognized key, \"" + bindingkeyname + "\"" );
|
||||
}
|
||||
else {
|
||||
// replace any existing binding, preserve modifiers
|
||||
// (protection from cases where there's more than one key listed in the entry)
|
||||
keycode = keylookup->second | ( keycode & 0xffff0000 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<int, std::string> binding{keycode, description};
|
||||
m_bindingsetups.insert_or_assign(lookup->second, binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void keyboard_input::dump_bindings()
|
||||
{
|
||||
std::fstream stream("eu07_input-keyboard.ini",
|
||||
std::ios_base::binary | std::ios_base::trunc | std::ios_base::out);
|
||||
|
||||
if (!stream.is_open()) {
|
||||
ErrorLog("failed to save keyboard config");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const std::pair<user_command, std::tuple<int, std::string>> &binding : m_bindingsetups) {
|
||||
stream << simulation::Commands_descriptions[static_cast<std::size_t>(binding.first)].name << ' ';
|
||||
|
||||
int keycode = std::get<int>(binding.second);
|
||||
auto it = keytonamemap.find(keycode & 0xFFFF);
|
||||
if (it != keytonamemap.end()) {
|
||||
if (keycode & keymodifier::control)
|
||||
stream << "ctrl ";
|
||||
if (keycode & keymodifier::shift)
|
||||
stream << "shift ";
|
||||
|
||||
stream << it->second;
|
||||
} else {
|
||||
stream << "none";
|
||||
}
|
||||
|
||||
std::string description = std::get<std::string>(binding.second);
|
||||
if (description.size() > 0)
|
||||
stream << " // " << description << "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_input::key( int const Key, int const Action ) {
|
||||
|
||||
bool modifier( false );
|
||||
|
||||
if( ( Key == GLFW_KEY_LEFT_SHIFT ) || ( Key == GLFW_KEY_RIGHT_SHIFT ) ) {
|
||||
// update internal state, but don't bother passing these
|
||||
input::key_shift =
|
||||
( Action == GLFW_RELEASE ?
|
||||
false :
|
||||
true );
|
||||
modifier = true;
|
||||
// whenever shift key is used it may affect currently pressed movement keys, so check and update these
|
||||
}
|
||||
if( ( Key == GLFW_KEY_LEFT_CONTROL ) || ( Key == GLFW_KEY_RIGHT_CONTROL ) ) {
|
||||
// update internal state, but don't bother passing these
|
||||
input::key_ctrl =
|
||||
( Action == GLFW_RELEASE ?
|
||||
false :
|
||||
true );
|
||||
modifier = true;
|
||||
}
|
||||
if( ( Key == GLFW_KEY_LEFT_ALT ) || ( Key == GLFW_KEY_RIGHT_ALT ) ) {
|
||||
// update internal state, but don't bother passing these
|
||||
input::key_alt =
|
||||
( Action == GLFW_RELEASE ?
|
||||
false :
|
||||
true );
|
||||
}
|
||||
|
||||
if( Key == -1 ) { return false; }
|
||||
|
||||
// store key state
|
||||
input::keys[ Key ] = Action;
|
||||
|
||||
if( true == is_movement_key( Key ) ) {
|
||||
// if the received key was one of movement keys, it's been handled and we don't need to bother further
|
||||
return true;
|
||||
}
|
||||
|
||||
// include active modifiers for currently pressed key, except if the key is a modifier itself
|
||||
auto const key =
|
||||
Key
|
||||
| ( modifier ? 0 : ( input::key_shift ? keymodifier::shift : 0 ) )
|
||||
| ( modifier ? 0 : ( input::key_ctrl ? keymodifier::control : 0 ) );
|
||||
|
||||
auto const lookup = m_bindings.find( key );
|
||||
if( lookup == m_bindings.end() ) {
|
||||
// no binding for this key
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: basic keyboard controls don't have any parameters
|
||||
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
|
||||
// TODO: pass correct entity id once the missing systems are in place
|
||||
m_relay.post( lookup->second, 0, 0, Action, 0 );
|
||||
m_command = (
|
||||
Action == GLFW_RELEASE ?
|
||||
user_command::none :
|
||||
lookup->second );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
keyboard_input::key( int const Key ) const {
|
||||
|
||||
return input::keys[ Key ];
|
||||
}
|
||||
|
||||
void
|
||||
keyboard_input::bind() {
|
||||
m_bindings.clear();
|
||||
|
||||
for( auto const &bindingsetup : m_bindingsetups ) {
|
||||
|
||||
m_bindings[ std::get<int>(bindingsetup.second) ] = bindingsetup.first;
|
||||
}
|
||||
|
||||
// cache movement key bindings
|
||||
m_bindingscache.forward = binding( user_command::moveforward );
|
||||
m_bindingscache.back = binding( user_command::moveback );
|
||||
m_bindingscache.left = binding( user_command::moveleft );
|
||||
m_bindingscache.right = binding( user_command::moveright );
|
||||
m_bindingscache.up = binding( user_command::moveup );
|
||||
m_bindingscache.down = binding( user_command::movedown );
|
||||
}
|
||||
|
||||
int
|
||||
keyboard_input::binding( user_command const Command ) const {
|
||||
|
||||
for( auto const &binding : m_bindings ) {
|
||||
if( binding.second == Command ) {
|
||||
return binding.first;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_input::is_movement_key( int const Key ) const {
|
||||
|
||||
bool const ismovementkey =
|
||||
( ( Key == m_bindingscache.forward )
|
||||
|| ( Key == m_bindingscache.back )
|
||||
|| ( Key == m_bindingscache.left )
|
||||
|| ( Key == m_bindingscache.right )
|
||||
|| ( Key == m_bindingscache.up )
|
||||
|| ( Key == m_bindingscache.down ) );
|
||||
|
||||
return ismovementkey;
|
||||
}
|
||||
|
||||
void
|
||||
keyboard_input::poll() {
|
||||
|
||||
glm::vec2 const movementhorizontal {
|
||||
// x-axis
|
||||
( Global.shiftState ? 1.f : (2.0f / 3.0f) ) *
|
||||
( input::keys[ m_bindingscache.left ] != GLFW_RELEASE ? -1.f :
|
||||
input::keys[ m_bindingscache.right ] != GLFW_RELEASE ? 1.f :
|
||||
0.f ),
|
||||
// z-axis
|
||||
( Global.shiftState ? 1.f : (2.0f / 3.0f) ) *
|
||||
( input::keys[ m_bindingscache.forward ] != GLFW_RELEASE ? 1.f :
|
||||
input::keys[ m_bindingscache.back ] != GLFW_RELEASE ? -1.f :
|
||||
0.f ) };
|
||||
|
||||
if( ( movementhorizontal.x != 0.f || movementhorizontal.y != 0.f )
|
||||
|| ( m_movementhorizontal.x != 0.f || m_movementhorizontal.y != 0.f ) ) {
|
||||
m_relay.post(
|
||||
( true == Global.ctrlState ?
|
||||
user_command::movehorizontalfast :
|
||||
user_command::movehorizontal ),
|
||||
movementhorizontal.x,
|
||||
movementhorizontal.y,
|
||||
GLFW_PRESS,
|
||||
0 );
|
||||
}
|
||||
|
||||
m_movementhorizontal = movementhorizontal;
|
||||
|
||||
float const movementvertical {
|
||||
// y-axis
|
||||
( Global.shiftState ? 1.f : (2.0f / 3.0f) ) *
|
||||
( input::keys[ m_bindingscache.up ] != GLFW_RELEASE ? 1.f :
|
||||
input::keys[ m_bindingscache.down ] != GLFW_RELEASE ? -1.f :
|
||||
0.f ) };
|
||||
|
||||
if( ( movementvertical != 0.f )
|
||||
|| ( m_movementvertical != 0.f ) ) {
|
||||
m_relay.post(
|
||||
( true == Global.ctrlState ?
|
||||
user_command::moveverticalfast :
|
||||
user_command::movevertical ),
|
||||
movementvertical,
|
||||
0,
|
||||
GLFW_PRESS,
|
||||
0 );
|
||||
}
|
||||
|
||||
m_movementvertical = movementvertical;
|
||||
}
|
||||
|
||||
std::unordered_map<int, std::string> keytonamemap = {
|
||||
{ GLFW_KEY_0, "0" }, { GLFW_KEY_1, "1" }, { GLFW_KEY_2, "2" }, { GLFW_KEY_3, "3" }, { GLFW_KEY_4, "4" },
|
||||
{ GLFW_KEY_5, "5" }, { GLFW_KEY_6, "6" }, { GLFW_KEY_7, "7" }, { GLFW_KEY_8, "8" }, { GLFW_KEY_9, "9" },
|
||||
{ GLFW_KEY_MINUS, "-" }, { GLFW_KEY_EQUAL, "=" },
|
||||
{ GLFW_KEY_A, "A" }, { GLFW_KEY_B, "B" }, { GLFW_KEY_C, "C" }, { GLFW_KEY_D, "D" }, { GLFW_KEY_E, "E" },
|
||||
{ GLFW_KEY_F, "F" }, { GLFW_KEY_G, "G" }, { GLFW_KEY_H, "H" }, { GLFW_KEY_I, "I" }, { GLFW_KEY_J, "J" },
|
||||
{ GLFW_KEY_K, "K" }, { GLFW_KEY_L, "L" }, { GLFW_KEY_M, "M" }, { GLFW_KEY_N, "N" }, { GLFW_KEY_O, "O" },
|
||||
{ GLFW_KEY_P, "P" }, { GLFW_KEY_Q, "Q" }, { GLFW_KEY_R, "R" }, { GLFW_KEY_S, "S" }, { GLFW_KEY_T, "T" },
|
||||
{ GLFW_KEY_U, "U" }, { GLFW_KEY_V, "V" }, { GLFW_KEY_W, "W" }, { GLFW_KEY_X, "X" }, { GLFW_KEY_Y, "Y" }, { GLFW_KEY_Z, "Z" },
|
||||
{ GLFW_KEY_BACKSPACE, "BACKSPACE" },
|
||||
{ GLFW_KEY_LEFT_BRACKET, "[" }, { GLFW_KEY_RIGHT_BRACKET, "]" }, { GLFW_KEY_BACKSLASH, "\\" },
|
||||
{ GLFW_KEY_SEMICOLON, ";" }, { GLFW_KEY_APOSTROPHE, "'" }, { GLFW_KEY_ENTER, "ENTER" },
|
||||
{ GLFW_KEY_COMMA, "<" }, { GLFW_KEY_PERIOD, ">" }, { GLFW_KEY_SLASH, "/" },
|
||||
{ GLFW_KEY_SPACE, "SPACE" },
|
||||
{ GLFW_KEY_PAUSE, "PAUSE" }, { GLFW_KEY_INSERT, "INSERT" }, { GLFW_KEY_DELETE, "DELETE" }, { GLFW_KEY_HOME, "HOME" }, { GLFW_KEY_END, "END" },
|
||||
// numpad block
|
||||
{ GLFW_KEY_KP_DIVIDE, "NUM /" }, { GLFW_KEY_KP_MULTIPLY, "NUM *" }, { GLFW_KEY_KP_SUBTRACT, "NUM -" },
|
||||
{ GLFW_KEY_KP_7, "NUM 7" }, { GLFW_KEY_KP_8, "NUM 8" }, { GLFW_KEY_KP_9, "NUM 9" }, { GLFW_KEY_KP_ADD, "NUM +" },
|
||||
{ GLFW_KEY_KP_4, "NUM 4" }, { GLFW_KEY_KP_5, "NUM 5" }, { GLFW_KEY_KP_6, "NUM 6" },
|
||||
{ GLFW_KEY_KP_1, "NUM 1" }, { GLFW_KEY_KP_2, "NUM 2" }, { GLFW_KEY_KP_3, "NUM 3" }, { GLFW_KEY_KP_ENTER, "NUM ENTER" },
|
||||
{ GLFW_KEY_KP_0, "NUM 0" }, { GLFW_KEY_KP_DECIMAL, "NUM ." }
|
||||
};
|
||||
|
||||
std::string
|
||||
keyboard_input::binding_hint( user_command const Command ) const {
|
||||
|
||||
if( Command == user_command::none ) { return ""; }
|
||||
|
||||
auto const binding { this->binding( Command ) };
|
||||
if( binding == -1 ) { return ""; }
|
||||
|
||||
auto const lookup { keytonamemap.find( binding & 0xffff ) };
|
||||
if( lookup == keytonamemap.end() ) { return ""; }
|
||||
|
||||
std::string hint;
|
||||
if( ( binding & keymodifier::shift ) != 0 ) {
|
||||
hint += "SHIFT ";
|
||||
}
|
||||
if( ( binding & keymodifier::control ) != 0 ) {
|
||||
hint += "CTRL ";
|
||||
}
|
||||
hint += lookup->second;
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
115
input/keyboardinput.h
Normal file
115
input/keyboardinput.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
#include "command.h"
|
||||
|
||||
namespace input {
|
||||
|
||||
extern std::array<char, GLFW_KEY_LAST + 1> keys;
|
||||
extern bool key_alt;
|
||||
extern bool key_ctrl;
|
||||
extern bool key_shift;
|
||||
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class keymapper_panel;
|
||||
}
|
||||
|
||||
class keyboard_input {
|
||||
friend class ui::keymapper_panel;
|
||||
|
||||
public:
|
||||
// types
|
||||
using bindingsetup_sequence = std::map<user_command, std::tuple<int, std::string>>;
|
||||
|
||||
enum keymodifier : int {
|
||||
|
||||
shift = 0x10000,
|
||||
control = 0x20000
|
||||
};
|
||||
|
||||
// constructors
|
||||
keyboard_input() = default;
|
||||
|
||||
// destructor
|
||||
virtual ~keyboard_input() = default;
|
||||
|
||||
// methods
|
||||
virtual
|
||||
bool
|
||||
init() { return true; }
|
||||
bool
|
||||
key( int const Key, int const Action );
|
||||
int
|
||||
key( int const Key ) const;
|
||||
void
|
||||
poll();
|
||||
inline
|
||||
user_command const
|
||||
command() const {
|
||||
return m_command; }
|
||||
bindingsetup_sequence&
|
||||
bindings() {
|
||||
return m_bindingsetups; }
|
||||
int
|
||||
binding( user_command const Command ) const;
|
||||
std::string
|
||||
binding_hint( user_command const Command ) const;
|
||||
void
|
||||
dump_bindings();
|
||||
|
||||
// members
|
||||
static std::unordered_map<int, std::string> keytonamemap;
|
||||
|
||||
protected:
|
||||
// methods
|
||||
virtual
|
||||
void
|
||||
default_bindings() = 0;
|
||||
bool
|
||||
recall_bindings();
|
||||
void
|
||||
bind();
|
||||
|
||||
// members
|
||||
bindingsetup_sequence m_bindingsetups;
|
||||
|
||||
private:
|
||||
// types
|
||||
using usercommand_map = std::unordered_map<int, user_command>;
|
||||
|
||||
struct bindings_cache {
|
||||
|
||||
int forward { -1 };
|
||||
int back { -1 };
|
||||
int left { -1 };
|
||||
int right { -1 };
|
||||
int up { -1 };
|
||||
int down { -1 };
|
||||
};
|
||||
|
||||
// methods
|
||||
bool
|
||||
is_movement_key( int const Key ) const;
|
||||
|
||||
// members
|
||||
user_command m_command { user_command::none }; // last, if any, issued command
|
||||
usercommand_map m_bindings;
|
||||
command_relay m_relay;
|
||||
bindings_cache m_bindingscache;
|
||||
glm::vec2 m_movementhorizontal { 0.f };
|
||||
float m_movementvertical { 0.f };
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
429
input/messaging.cpp
Normal file
429
input/messaging.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "messaging.h"
|
||||
|
||||
#include "Globals.h"
|
||||
#include "application.h"
|
||||
#include "simulation.h"
|
||||
#include "simulationtime.h"
|
||||
#include "Event.h"
|
||||
#include "DynObj.h"
|
||||
#include "Driver.h"
|
||||
#include "mtable.h"
|
||||
#include "Logs.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C"
|
||||
{
|
||||
GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window );
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace multiplayer {
|
||||
|
||||
std::uint32_t const EU07_MESSAGEHEADER { MAKE_ID4( 'E','U','0','7' ) };
|
||||
|
||||
void
|
||||
Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam) {
|
||||
#ifdef _WIN32
|
||||
// wysłanie komunikatu do sterującego
|
||||
HWND h = FindWindow(ClassName.c_str(), 0); // można by to zapamiętać
|
||||
if (h == 0)
|
||||
h = FindWindow(0, ClassName.c_str()); // można by to zapamiętać
|
||||
SendMessage(h, Msg, wParam, lParam);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
|
||||
{ // odebranie komunikatu z serwera
|
||||
if (pRozkaz->iSygn == EU07_MESSAGEHEADER )
|
||||
switch (pRozkaz->iComm)
|
||||
{
|
||||
case 0: // odesłanie identyfikatora wersji
|
||||
CommLog( Now() + " " + std::to_string(pRozkaz->iComm) + " version" + " rcvd");
|
||||
WyslijString(Global.asVersion, 0); // przedsatwienie się
|
||||
break;
|
||||
case 1: // odesłanie identyfikatora wersji
|
||||
CommLog( Now() + " " + std::to_string(pRozkaz->iComm) + " scenery" + " rcvd");
|
||||
WyslijString(Global.SceneryFile, 1); // nazwa scenerii
|
||||
break;
|
||||
case 2: {
|
||||
// event
|
||||
CommLog( Now() + " " + std::to_string( pRozkaz->iComm ) + " " +
|
||||
std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) + " rcvd" );
|
||||
|
||||
if( Global.iMultiplayer ) {
|
||||
auto *event = simulation::Events.FindEvent( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
|
||||
if( event != nullptr ) {
|
||||
if( ( typeid( *event ) == typeid( multi_event ) )
|
||||
|| ( typeid( *event ) == typeid( lights_event ) )
|
||||
|| ( event->m_sibling != 0 ) ) {
|
||||
// tylko jawne albo niejawne Multiple
|
||||
command_relay relay;
|
||||
relay.post(user_command::queueevent, 0.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &event->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: // rozkaz dla AI
|
||||
if (Global.iMultiplayer)
|
||||
{
|
||||
int i = int(pRozkaz->cString[8]); // długość pierwszego łańcucha (z przodu dwa floaty)
|
||||
CommLog(
|
||||
Now() + " " + to_string(pRozkaz->iComm) + " " +
|
||||
std::string(pRozkaz->cString + 11 + i, (unsigned)(pRozkaz->cString[10 + i])) +
|
||||
" rcvd");
|
||||
// nazwa pojazdu jest druga
|
||||
auto *vehicle = simulation::Vehicles.find( { pRozkaz->cString + 11 + i, (unsigned)pRozkaz->cString[ 10 + i ] } );
|
||||
if( ( vehicle != nullptr )
|
||||
&& ( vehicle->Mechanik != nullptr ) ) {
|
||||
vehicle->Mechanik->PutCommand(
|
||||
{ pRozkaz->cString + 9, static_cast<std::size_t>(i) },
|
||||
pRozkaz->fPar[0], pRozkaz->fPar[1],
|
||||
nullptr,
|
||||
stopExt ); // floaty są z przodu
|
||||
WriteLog("AI command: " + std::string(pRozkaz->cString + 9, i));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4: // badanie zajętości toru
|
||||
{
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
|
||||
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) + " rcvd");
|
||||
|
||||
auto *track = simulation::Paths.find( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
|
||||
if( ( track != nullptr )
|
||||
&& ( track->IsEmpty() ) ) {
|
||||
WyslijWolny( track->name() );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5: // ustawienie parametrów
|
||||
{
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " params " + to_string(*pRozkaz->iPar) + " rcvd");
|
||||
if (*pRozkaz->iPar == 0) // sprawdzenie czasu
|
||||
if (*pRozkaz->iPar & 1) // ustawienie czasu
|
||||
{
|
||||
auto t = pRozkaz->fPar[1];
|
||||
simulation::Time.data().wDay = std::floor(t); // niby nie powinno być dnia, ale...
|
||||
if (Global.fMoveLight >= 0)
|
||||
Global.fMoveLight = t; // trzeba by deklinację Słońca przeliczyć
|
||||
simulation::Time.data().wHour = std::floor(24 * t) - 24.0 * simulation::Time.data().wDay;
|
||||
simulation::Time.data().wMinute = std::floor(60 * 24 * t) - 60.0 * (24.0 * simulation::Time.data().wDay + simulation::Time.data().wHour);
|
||||
simulation::Time.data().wSecond = std::floor( 60 * 60 * 24 * t ) - 60.0 * ( 60.0 * ( 24.0 * simulation::Time.data().wDay + simulation::Time.data().wHour ) + simulation::Time.data().wMinute );
|
||||
}
|
||||
if (*pRozkaz->iPar & 2)
|
||||
{ // ustawienie flag zapauzowania
|
||||
Global.iPause = pRozkaz->fPar[2]; // zakładamy, że wysyłający wie, co robi
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6: // pobranie parametrów ruchu pojazdu
|
||||
if (Global.iMultiplayer) {
|
||||
// Ra 2014-12: to ma działać również dla pojazdów bez obsady
|
||||
CommLog(
|
||||
Now() + " "
|
||||
+ to_string( pRozkaz->iComm ) + " "
|
||||
+ std::string{ pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) }
|
||||
+ " rcvd" );
|
||||
if (pRozkaz->cString[0]) {
|
||||
// jeśli długość nazwy jest niezerowa szukamy pierwszego pojazdu o takiej nazwie i odsyłamy parametry ramką #7
|
||||
auto *vehicle = (
|
||||
pRozkaz->cString[ 1 ] == '*' ?
|
||||
simulation::Train->Dynamic() :
|
||||
simulation::Vehicles.find( std::string{ pRozkaz->cString + 1, (unsigned)pRozkaz->cString[ 0 ] } ) );
|
||||
if( vehicle != nullptr ) {
|
||||
WyslijNamiary( vehicle ); // wysłanie informacji o pojeździe
|
||||
}
|
||||
}
|
||||
else {
|
||||
// dla pustego wysyłamy ramki 6 z nazwami pojazdów AI (jeśli potrzebne wszystkie, to rozpoznać np. "*")
|
||||
simulation::Vehicles.DynamicList();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8: // ponowne wysłanie informacji o zajętych odcinkach toru
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " all busy track" + " rcvd");
|
||||
simulation::Paths.TrackBusyList();
|
||||
break;
|
||||
case 9: // ponowne wysłanie informacji o zajętych odcinkach izolowanych
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " all busy isolated" + " rcvd");
|
||||
simulation::Paths.IsolatedBusyList();
|
||||
break;
|
||||
case 10: // badanie zajętości jednego odcinka izolowanego
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
|
||||
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) + " rcvd");
|
||||
simulation::Paths.IsolatedBusy( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
|
||||
break;
|
||||
case 11: // ustawienie parametrów ruchu pojazdu
|
||||
// Ground.IsolatedBusy(AnsiString(pRozkaz->cString+1,(unsigned)(pRozkaz->cString[0])));
|
||||
break;
|
||||
case 12: // skrocona ramka parametrow pojazdow AI (wszystkich!!)
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " obsadzone" + " rcvd");
|
||||
WyslijObsadzone();
|
||||
// Ground.IsolatedBusy(AnsiString(pRozkaz->cString+1,(unsigned)(pRozkaz->cString[0])));
|
||||
break;
|
||||
case 13: // ramka uszkodzenia i innych stanow pojazdu, np. wylaczenie CA, wlaczenie recznego itd.
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
|
||||
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) +
|
||||
" rcvd");
|
||||
if( pRozkaz->cString[ 1 ] ) // jeśli długość nazwy jest niezerowa
|
||||
{ // szukamy pierwszego pojazdu o takiej nazwie i odsyłamy parametry ramką #13
|
||||
auto *lookup = (
|
||||
pRozkaz->cString[ 2 ] == '*' ?
|
||||
simulation::Train->Dynamic() : // nazwa pojazdu użytkownika
|
||||
simulation::Vehicles.find( std::string( pRozkaz->cString + 2, (unsigned)pRozkaz->cString[ 1 ] ) ) ); // nazwa pojazdu
|
||||
if( lookup == nullptr ) { break; } // nothing found, nothing to do
|
||||
auto *d { lookup };
|
||||
while( d != nullptr ) {
|
||||
d->Damage( pRozkaz->cString[ 0 ] );
|
||||
d = d->Next(); // pozostałe też
|
||||
}
|
||||
d = lookup->Prev();
|
||||
while( d != nullptr ) {
|
||||
d->Damage( pRozkaz->cString[ 0 ] );
|
||||
d = d->Prev(); // w drugą stronę też
|
||||
}
|
||||
WyslijUszkodzenia( lookup->asName, lookup->MoverParameters->EngDmgFlag ); // zwrot informacji o pojeździe
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WyslijEvent(const std::string &e, const std::string &d)
|
||||
{ // Ra: jeszcze do wyczyszczenia
|
||||
#ifdef _WIN32
|
||||
DaneRozkaz r;
|
||||
r.iSygn = EU07_MESSAGEHEADER;
|
||||
r.iComm = 2; // 2 - event
|
||||
size_t i = e.length(), j = d.length();
|
||||
r.cString[0] = char(i);
|
||||
strcpy(r.cString + 1, e.c_str()); // zakończony zerem
|
||||
r.cString[i + 2] = char(j); // licznik po zerze kończącym
|
||||
strcpy(r.cString + 3 + i, d.c_str()); // zakończony zerem
|
||||
COPYDATASTRUCT cData;
|
||||
cData.dwData = EU07_MESSAGEHEADER; // sygnatura
|
||||
cData.cbData = (DWORD)(12 + i + j); // 8+dwa liczniki i dwa zera kończące
|
||||
cData.lpData = &r;
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " " + e + " sent" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WyslijUszkodzenia(const std::string &t, char fl)
|
||||
{ // wysłanie informacji w postaci pojedynczego tekstu
|
||||
#ifdef _WIN32
|
||||
DaneRozkaz r;
|
||||
r.iSygn = EU07_MESSAGEHEADER;
|
||||
r.iComm = 13; // numer komunikatu
|
||||
size_t i = t.length();
|
||||
r.cString[0] = char(fl);
|
||||
r.cString[1] = char(i);
|
||||
strcpy(r.cString + 2, t.c_str()); // z zerem kończącym
|
||||
COPYDATASTRUCT cData;
|
||||
cData.dwData = EU07_MESSAGEHEADER; // sygnatura
|
||||
cData.cbData = (DWORD)(11 + i); // 8+licznik i zero kończące
|
||||
cData.lpData = &r;
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WyslijString(const std::string &t, int n)
|
||||
{ // wysłanie informacji w postaci pojedynczego tekstu
|
||||
#ifdef _WIN32
|
||||
DaneRozkaz r;
|
||||
r.iSygn = EU07_MESSAGEHEADER;
|
||||
r.iComm = n; // numer komunikatu
|
||||
size_t i = t.length();
|
||||
r.cString[0] = char(i);
|
||||
strcpy(r.cString + 1, t.c_str()); // z zerem kończącym
|
||||
COPYDATASTRUCT cData;
|
||||
cData.dwData = EU07_MESSAGEHEADER; // sygnatura
|
||||
cData.cbData = (DWORD)(10 + i); // 8+licznik i zero kończące
|
||||
cData.lpData = &r;
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WyslijWolny(const std::string &t)
|
||||
{ // Ra: jeszcze do wyczyszczenia
|
||||
WyslijString(t, 4); // tor wolny
|
||||
}
|
||||
|
||||
void
|
||||
WyslijNamiary(TDynamicObject const *Vehicle)
|
||||
{ // wysłanie informacji o pojeździe - (float), długość ramki będzie zwiększana w miarę potrzeby
|
||||
#ifdef _WIN32
|
||||
DaneRozkaz r;
|
||||
r.iSygn = EU07_MESSAGEHEADER;
|
||||
r.iComm = 7; // 7 - dane pojazdu
|
||||
int i = 32;
|
||||
size_t j = Vehicle->asName.length();
|
||||
r.iPar[0] = i; // ilość danych liczbowych
|
||||
r.fPar[1] = Global.fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
|
||||
r.fPar[2] = Vehicle->MoverParameters->Loc.X; // pozycja X
|
||||
r.fPar[3] = Vehicle->MoverParameters->Loc.Y; // pozycja Y
|
||||
r.fPar[4] = Vehicle->MoverParameters->Loc.Z; // pozycja Z
|
||||
r.fPar[5] = Vehicle->MoverParameters->V; // prędkość ruchu X
|
||||
r.fPar[6] = Vehicle->MoverParameters->nrot * M_PI *
|
||||
Vehicle->MoverParameters->WheelDiameter; // prędkość obrotowa kóŁ
|
||||
r.fPar[7] = 0; // prędkość ruchu Z
|
||||
r.fPar[8] = Vehicle->MoverParameters->AccS; // przyspieszenie X
|
||||
r.fPar[9] = Vehicle->MoverParameters->AccN; // przyspieszenie Y //na razie nie
|
||||
r.fPar[10] = Vehicle->MoverParameters->AccVert; // przyspieszenie Z
|
||||
r.fPar[11] = Vehicle->MoverParameters->DistCounter; // przejechana odległość w km
|
||||
r.fPar[12] = Vehicle->MoverParameters->PipePress; // ciśnienie w PG
|
||||
r.fPar[13] = Vehicle->MoverParameters->ScndPipePress; // ciśnienie w PZ
|
||||
r.fPar[14] = Vehicle->MoverParameters->BrakePress; // ciśnienie w CH
|
||||
r.fPar[15] = Vehicle->MoverParameters->Compressor; // ciśnienie w ZG
|
||||
r.fPar[16] = Vehicle->MoverParameters->Itot; // Prąd całkowity
|
||||
r.iPar[17] = Vehicle->MoverParameters->MainCtrlPos; // Pozycja NJ
|
||||
r.iPar[18] = Vehicle->MoverParameters->ScndCtrlPos; // Pozycja NB
|
||||
r.iPar[19] = Vehicle->MoverParameters->MainCtrlActualPos; // Pozycja jezdna
|
||||
r.iPar[20] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
|
||||
r.iPar[21] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
|
||||
r.iPar[22] = Vehicle->MoverParameters->ResistorsFlag * 1
|
||||
+ Vehicle->MoverParameters->ConverterFlag * 2
|
||||
+ Vehicle->MoverParameters->CompressorFlag * 4
|
||||
+ Vehicle->MoverParameters->Mains * 8
|
||||
#ifdef EU07_USEOLDDOORCODE
|
||||
+ Vehicle->MoverParameters->DoorLeftOpened * 16
|
||||
+ Vehicle->MoverParameters->DoorRightOpened * 32
|
||||
#else
|
||||
+ ( false == Vehicle->MoverParameters->Doors.instances[side::left].is_closed ) * 16
|
||||
+ ( false == Vehicle->MoverParameters->Doors.instances[side::right].is_closed ) * 32
|
||||
#endif
|
||||
+ Vehicle->MoverParameters->FuseFlag * 64
|
||||
+ Vehicle->MoverParameters->DepartureSignal * 128;
|
||||
// WriteLog("Zapisalem stare");
|
||||
// WriteLog("Mam patykow "+IntToStr(t->DynamicObject->iAnimType[ANIM_PANTS]));
|
||||
for (int p = 0; p < 4; p++)
|
||||
{
|
||||
// WriteLog("Probuje pant "+IntToStr(p));
|
||||
if (p < Vehicle->iAnimType[ANIM_PANTS])
|
||||
{
|
||||
r.fPar[23 + p] = Vehicle->pants[p].fParamPants->PantWys; // stan pantografów 4
|
||||
// WriteLog("Zapisalem pant "+IntToStr(p));
|
||||
}
|
||||
else
|
||||
{
|
||||
r.fPar[23 + p] = -2;
|
||||
// WriteLog("Nie mam pant "+IntToStr(p));
|
||||
}
|
||||
}
|
||||
// WriteLog("Zapisalem pantografy");
|
||||
for (int p = 0; p < 3; p++)
|
||||
r.fPar[27 + p] =
|
||||
Vehicle->MoverParameters->ShowCurrent(p + 1); // amperomierze kolejnych grup
|
||||
// WriteLog("zapisalem prady");
|
||||
r.iPar[30] = Vehicle->MoverParameters->WarningSignal; // trabienie
|
||||
r.fPar[31] = Vehicle->MoverParameters->PantographVoltage; // napiecie WN
|
||||
// WriteLog("Parametry gotowe");
|
||||
i <<= 2; // ilość bajtów
|
||||
r.cString[i] = char(j); // na końcu nazwa, żeby jakoś zidentyfikować
|
||||
strcpy(r.cString + i + 1, Vehicle->asName.c_str()); // zakończony zerem
|
||||
COPYDATASTRUCT cData;
|
||||
cData.dwData = EU07_MESSAGEHEADER; // sygnatura
|
||||
cData.cbData = (DWORD)(10 + i + j); // 8+licznik i zero kończące
|
||||
cData.lpData = &r;
|
||||
// WriteLog("Ramka gotowa");
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
// WriteLog("Ramka poszla!");
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " " + Vehicle->asName + " sent");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WyslijObsadzone()
|
||||
{ // wysłanie informacji o pojeździe
|
||||
#ifdef _WIN32
|
||||
DaneRozkaz2 r;
|
||||
r.iSygn = EU07_MESSAGEHEADER;
|
||||
r.iComm = 12; // kod 12
|
||||
for (int i=0; i<1984; ++i) r.cString[i] = 0;
|
||||
|
||||
// TODO: clean this up, we shouldn't be relying on direct list access
|
||||
auto &vehiclelist = simulation::Vehicles.sequence();
|
||||
|
||||
int i = 0;
|
||||
for( auto *vehicle : vehiclelist ) {
|
||||
if( vehicle->Mechanik ) {
|
||||
strcpy( r.cString + 64 * i, vehicle->asName.c_str() );
|
||||
r.fPar[ 16 * i + 4 ] = vehicle->GetPosition().x;
|
||||
r.fPar[ 16 * i + 5 ] = vehicle->GetPosition().y;
|
||||
r.fPar[ 16 * i + 6 ] = vehicle->GetPosition().z;
|
||||
r.iPar[ 16 * i + 7 ] = static_cast<int>( vehicle->Mechanik->action() );
|
||||
strcpy( r.cString + 64 * i + 32, vehicle->GetTrack()->RemoteIsolatedName().c_str() );
|
||||
strcpy( r.cString + 64 * i + 48, vehicle->Mechanik->TrainName().c_str() );
|
||||
i++;
|
||||
if( i > 30 ) break;
|
||||
}
|
||||
}
|
||||
while (i <= 30)
|
||||
{
|
||||
strcpy(r.cString + 64 * i, "none");
|
||||
r.fPar[16 * i + 4] = 1;
|
||||
r.fPar[16 * i + 5] = 2;
|
||||
r.fPar[16 * i + 6] = 3;
|
||||
r.iPar[16 * i + 7] = 0;
|
||||
strcpy(r.cString + 64 * i + 32, "none");
|
||||
strcpy(r.cString + 64 * i + 48, "none");
|
||||
i++;
|
||||
}
|
||||
|
||||
COPYDATASTRUCT cData;
|
||||
cData.dwData = EU07_MESSAGEHEADER; // sygnatura
|
||||
cData.cbData = 8 + 1984; // 8+licznik i zero kończące
|
||||
cData.lpData = &r;
|
||||
// WriteLog("Ramka gotowa");
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " obsadzone" + " sent");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
WyslijParam(int nr, int fl)
|
||||
{ // wysłanie parametrów symulacji w ramce (nr) z flagami (fl)
|
||||
#ifdef _WIN32
|
||||
DaneRozkaz r;
|
||||
r.iSygn = EU07_MESSAGEHEADER;
|
||||
r.iComm = nr; // zwykle 5
|
||||
r.iPar[0] = fl; // flagi istotności kolejnych parametrów
|
||||
int i = 0; // domyślnie brak danych
|
||||
switch (nr)
|
||||
{ // można tym przesyłać różne zestawy parametrów
|
||||
case 5: // czas i pauza
|
||||
r.fPar[1] = Global.fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
|
||||
r.iPar[2] = Global.iPause; // stan zapauzowania
|
||||
i = 8; // dwa parametry po 4 bajty każdy
|
||||
break;
|
||||
}
|
||||
COPYDATASTRUCT cData;
|
||||
cData.dwData = EU07_MESSAGEHEADER; // sygnatura
|
||||
cData.cbData = 12 + i; // 12+rozmiar danych
|
||||
cData.lpData = &r;
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
#endif
|
||||
}
|
||||
|
||||
} // multiplayer
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
53
input/messaging.h
Normal file
53
input/messaging.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "winheaders.h"
|
||||
|
||||
class TDynamicObject;
|
||||
|
||||
namespace multiplayer {
|
||||
|
||||
struct DaneRozkaz { // struktura komunikacji z EU07.EXE
|
||||
int iSygn; // sygnatura 'EU07'
|
||||
int iComm; // rozkaz/status (kod ramki)
|
||||
union {
|
||||
float fPar[ 62 ];
|
||||
int iPar[ 62 ];
|
||||
char cString[ 248 ]; // upakowane stringi
|
||||
};
|
||||
};
|
||||
|
||||
struct DaneRozkaz2 { // struktura komunikacji z EU07.EXE
|
||||
int iSygn; // sygnatura 'EU07'
|
||||
int iComm; // rozkaz/status (kod ramki)
|
||||
union {
|
||||
float fPar[ 496 ];
|
||||
int iPar[ 496 ];
|
||||
char cString[ 1984 ]; // upakowane stringi
|
||||
};
|
||||
};
|
||||
|
||||
void Navigate( std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
void OnCommandGet( multiplayer::DaneRozkaz *pRozkaz );
|
||||
|
||||
void WyslijEvent( const std::string &e, const std::string &d );
|
||||
void WyslijString( const std::string &t, int n );
|
||||
void WyslijWolny( const std::string &t );
|
||||
void WyslijNamiary( TDynamicObject const *Vehicle );
|
||||
void WyslijParam( int nr, int fl );
|
||||
void WyslijUszkodzenia( const std::string &t, char fl );
|
||||
void WyslijObsadzone(); // -> skladanie wielu pojazdow
|
||||
|
||||
} // multiplayer
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
316
input/zmq_input.cpp
Normal file
316
input/zmq_input.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
#include "stdafx.h"
|
||||
#include "zmq_input.h"
|
||||
#include "Globals.h"
|
||||
#include "Logs.h"
|
||||
#include "simulation.h"
|
||||
#include "simulationtime.h"
|
||||
#include "Train.h"
|
||||
|
||||
zmq_input::zmq_input()
|
||||
{
|
||||
sock.emplace(ctx, zmq::socket_type::router);
|
||||
sock->bind(Global.zmq_address);
|
||||
|
||||
// build helper translation tables
|
||||
std::size_t commandid = 0;
|
||||
for( auto const &description : simulation::Commands_descriptions ) {
|
||||
nametocommandmap.emplace(
|
||||
description.name,
|
||||
static_cast<user_command>( commandid ) );
|
||||
++commandid;
|
||||
}
|
||||
}
|
||||
|
||||
float zmq_input::unpack_float(const zmq::message_t &msg) {
|
||||
if (msg.size() < 4)
|
||||
return 0.0f;
|
||||
|
||||
uint8_t *buf = (uint8_t*)msg.data();
|
||||
uint32_t v = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
||||
return reinterpret_cast<float&>(v);
|
||||
}
|
||||
|
||||
zmq::message_t zmq_input::pack_float(float f) {
|
||||
uint32_t v = reinterpret_cast<uint32_t&>(f);
|
||||
uint8_t buf[4];
|
||||
buf[3] = v;
|
||||
buf[2] = v >> 8;
|
||||
buf[1] = v >> 16;
|
||||
buf[0] = v >> 24;
|
||||
return zmq::message_t(buf, 4);
|
||||
}
|
||||
|
||||
void zmq_input::poll()
|
||||
{
|
||||
zmq::multipart_t multipart;
|
||||
bool ok;
|
||||
while ((ok = multipart.recv(*sock, ZMQ_DONTWAIT))) {
|
||||
if (multipart.size() < 3)
|
||||
continue;
|
||||
|
||||
if (multipart[0].size() != 5)
|
||||
continue;
|
||||
|
||||
uint8_t* buf = (uint8_t*)multipart[0].data();
|
||||
uint32_t peer_id = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4];
|
||||
|
||||
auto peer_it = peers.find(peer_id);
|
||||
if (peer_it == peers.end()) {
|
||||
peer_it = peers.emplace(peer_id, peer_state()).first;
|
||||
peer_it->second.update_interval = 60.0f;
|
||||
peer_it->second.last_update = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
if (multipart[1] == zmq::message_t("REG_SOPI", 8)) {
|
||||
if (multipart.size() < 4)
|
||||
continue;
|
||||
|
||||
peer_it->second.update_interval = unpack_float(multipart[2]);
|
||||
peer_it->second.sopi_list.clear();
|
||||
|
||||
for (size_t i = 3; i < multipart.size(); i++) {
|
||||
std::string chan_name((char*)multipart[i].data(), multipart[i].size());
|
||||
|
||||
auto chan_it = output_fields_map.find(chan_name);
|
||||
if (chan_it != output_fields_map.end())
|
||||
peer_it->second.sopi_list.push_back(chan_it->second);
|
||||
}
|
||||
}
|
||||
if (multipart[1] == zmq::message_t("REG_SIPO", 8)) {
|
||||
peer_it->second.sipo_list.clear();
|
||||
|
||||
for (size_t i = 2; i < multipart.size(); i++) {
|
||||
std::string chan_name((char*)multipart[i].data(), multipart[i].size());
|
||||
|
||||
std::istringstream stream(chan_name);
|
||||
std::string id1, id2;
|
||||
std::getline(stream, id1, '/');
|
||||
std::getline(stream, id2, '/');
|
||||
|
||||
input_type type = input_type::none;
|
||||
user_command cmd1 = user_command::none, cmd2 = user_command::none;
|
||||
|
||||
auto cmd1_it = nametocommandmap.find(id1);
|
||||
if (cmd1_it != nametocommandmap.end())
|
||||
cmd1 = cmd1_it->second;
|
||||
|
||||
if (id2 == "" || id2 == "v")
|
||||
type = input_type::value;
|
||||
else if (id2 == "i")
|
||||
type = input_type::impulse;
|
||||
else {
|
||||
type = input_type::toggle;
|
||||
auto cmd2_it = nametocommandmap.find(id2);
|
||||
if (cmd2_it != nametocommandmap.end())
|
||||
cmd2 = cmd2_it->second;
|
||||
}
|
||||
|
||||
if (cmd1 == user_command::none)
|
||||
type = input_type::none;
|
||||
|
||||
peer_it->second.sipo_list.push_back(std::make_tuple(type, cmd1, cmd2, false));
|
||||
}
|
||||
}
|
||||
if (multipart[1] == zmq::message_t("SIPO_DATA", 9)) {
|
||||
if (peer_it->second.sipo_list.size() != multipart.size() - 2) {
|
||||
zmq::multipart_t msg;
|
||||
|
||||
zmq::message_t addr;
|
||||
addr.copy(multipart[0]);
|
||||
|
||||
msg.add(std::move(addr));
|
||||
msg.addstr("UNCF_SIPO");
|
||||
msg.send(*sock, ZMQ_DONTWAIT);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t i = 1;
|
||||
for (auto &entry : peer_it->second.sipo_list) {
|
||||
i++;
|
||||
|
||||
float value = unpack_float(multipart[i]);
|
||||
input_type type = std::get<0>(entry);
|
||||
|
||||
if (type == input_type::value) {
|
||||
relay.post(std::get<1>(entry), value, 0, GLFW_PRESS, 0);
|
||||
continue;
|
||||
}
|
||||
else if (type == input_type::none)
|
||||
continue;
|
||||
|
||||
bool state = (value > 0.5f);
|
||||
bool changed = (state != std::get<3>(entry));
|
||||
|
||||
if (!changed)
|
||||
continue;
|
||||
|
||||
auto const action { (
|
||||
type != input_type::impulse ?
|
||||
GLFW_PRESS :
|
||||
( state ?
|
||||
GLFW_PRESS :
|
||||
GLFW_RELEASE ) ) };
|
||||
|
||||
auto const command { (
|
||||
type != input_type::toggle ?
|
||||
std::get<1>( entry ) :
|
||||
( state ?
|
||||
std::get<1>( entry ) :
|
||||
std::get<2>( entry ) ) ) };
|
||||
|
||||
std::get<3>(entry) = state;
|
||||
|
||||
relay.post(command, 0, 0, action, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for (auto peer = peers.begin(); peer != peers.end();) {
|
||||
if (std::chrono::duration<float>(now - peer->second.last_update).count() < peer->second.update_interval) {
|
||||
++peer;
|
||||
continue;
|
||||
}
|
||||
|
||||
peer->second.last_update = now;
|
||||
|
||||
if (peer->second.sopi_list.empty()) {
|
||||
++peer;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t peerbuf[5] = { 0, (uint8_t)(peer->first >> 24), (uint8_t)(peer->first >> 16), (uint8_t)(peer->first >> 8), (uint8_t)(peer->first) };
|
||||
zmq::multipart_t msg;
|
||||
|
||||
msg.addmem(peerbuf, sizeof(peerbuf));
|
||||
msg.addstr("SOPI_DATA");
|
||||
|
||||
for (output_fields field : peer->second.sopi_list)
|
||||
msg.add(pack_field(field));
|
||||
|
||||
if (!msg.send(*sock, ZMQ_DONTWAIT))
|
||||
peer = peers.erase(peer);
|
||||
else
|
||||
++peer;
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, zmq_input::output_fields> zmq_input::output_fields_map = {
|
||||
{ "shp", output_fields::shp },
|
||||
{ "alerter", output_fields::alerter },
|
||||
{ "radio_stop", output_fields::radio_stop },
|
||||
{ "motor_resistors", output_fields::motor_resistors },
|
||||
{ "line_breaker", output_fields::line_breaker },
|
||||
{ "motor_overload", output_fields::motor_overload },
|
||||
{ "motor_connectors", output_fields::motor_connectors },
|
||||
{ "wheelslip", output_fields::wheelslip },
|
||||
{ "converter_overload", output_fields::converter_overload },
|
||||
{ "converter_off", output_fields::converter_off },
|
||||
{ "compressor_overload", output_fields::compressor_overload },
|
||||
{ "ventilator_overload", output_fields::ventilator_overload },
|
||||
{ "motor_overload_threshold", output_fields::motor_overload_threshold },
|
||||
{ "train_heating", output_fields::train_heating },
|
||||
{ "cab", output_fields::cab },
|
||||
{ "recorder_braking", output_fields::recorder_braking },
|
||||
{ "recorder_power", output_fields::recorder_power },
|
||||
{ "alerter_sound",output_fields:: alerter_sound },
|
||||
{ "coupled_hv_voltage_relays", output_fields::coupled_hv_voltage_relays },
|
||||
{ "velocity", output_fields::velocity },
|
||||
{ "reservoir_pressure", output_fields::reservoir_pressure },
|
||||
{ "pipe_pressure", output_fields::pipe_pressure },
|
||||
{ "brake_pressure", output_fields::brake_pressure },
|
||||
{ "hv_voltage", output_fields::hv_voltage },
|
||||
{ "hv_current_1", output_fields::hv_current_1 },
|
||||
{ "hv_current_2", output_fields::hv_current_2 },
|
||||
{ "hv_current_3", output_fields::hv_current_3 },
|
||||
{ "lv_voltage", output_fields::lv_voltage },
|
||||
{ "distance", output_fields::distance },
|
||||
{ "radio_channel", output_fields::radio_channel },
|
||||
{ "springbrake_active", output_fields::springbrake_active },
|
||||
{ "time_month_of_era", output_fields::time_month_of_era },
|
||||
{ "time_minute_of_month", output_fields::time_minute_of_month },
|
||||
{ "time_millisecond_of_day", output_fields::time_millisecond_of_day }
|
||||
};
|
||||
|
||||
zmq::message_t zmq_input::pack_field(zmq_input::output_fields f) {
|
||||
const SYSTEMTIME time = simulation::Time.data();
|
||||
|
||||
if (f == output_fields::time_month_of_era)
|
||||
return pack_float((time.wYear - 1) * 12 + time.wMonth - 1);
|
||||
if (f == output_fields::time_minute_of_month)
|
||||
return pack_float((time.wDay - 1) * 1440 + time.wHour * 60 + time.wMinute);
|
||||
if (f == output_fields::time_millisecond_of_day)
|
||||
return pack_float(time.wSecond * 1000 + time.wMilliseconds);
|
||||
|
||||
TTrain *train = simulation::Train;
|
||||
if (!train)
|
||||
return pack_float(0.0f);
|
||||
const TTrain::state_t state = train->get_state();
|
||||
|
||||
if (f == output_fields::shp)
|
||||
return pack_float(state.shp);
|
||||
if (f == output_fields::alerter)
|
||||
return pack_float(state.alerter);
|
||||
if (f == output_fields::radio_stop)
|
||||
return pack_float(state.radio_stop);
|
||||
if (f == output_fields::motor_resistors)
|
||||
return pack_float(state.motor_resistors);
|
||||
if (f == output_fields::line_breaker)
|
||||
return pack_float(state.line_breaker);
|
||||
if (f == output_fields::motor_overload)
|
||||
return pack_float(state.motor_overload);
|
||||
if (f == output_fields::motor_connectors)
|
||||
return pack_float(state.motor_connectors);
|
||||
if (f == output_fields::wheelslip)
|
||||
return pack_float(state.wheelslip);
|
||||
if (f == output_fields::converter_overload)
|
||||
return pack_float(state.converter_overload);
|
||||
if (f == output_fields::converter_off)
|
||||
return pack_float(state.converter_off);
|
||||
if (f == output_fields::compressor_overload)
|
||||
return pack_float(state.compressor_overload);
|
||||
if (f == output_fields::ventilator_overload)
|
||||
return pack_float(state.ventilator_overload);
|
||||
if (f == output_fields::motor_overload_threshold)
|
||||
return pack_float(state.motor_overload_threshold);
|
||||
if (f == output_fields::train_heating)
|
||||
return pack_float(state.train_heating);
|
||||
if (f == output_fields::cab)
|
||||
return pack_float(state.cab);
|
||||
if (f == output_fields::recorder_braking)
|
||||
return pack_float(state.recorder_braking);
|
||||
if (f == output_fields::recorder_power)
|
||||
return pack_float(state.recorder_power);
|
||||
if (f == output_fields::alerter_sound)
|
||||
return pack_float(state.alerter_sound);
|
||||
if (f == output_fields::coupled_hv_voltage_relays)
|
||||
return pack_float(state.coupled_hv_voltage_relays);
|
||||
if (f == output_fields::velocity)
|
||||
return pack_float(state.velocity);
|
||||
if (f == output_fields::reservoir_pressure)
|
||||
return pack_float(state.reservoir_pressure);
|
||||
if (f == output_fields::pipe_pressure)
|
||||
return pack_float(state.pipe_pressure);
|
||||
if (f == output_fields::brake_pressure)
|
||||
return pack_float(state.brake_pressure);
|
||||
if (f == output_fields::hv_voltage)
|
||||
return pack_float(state.hv_voltage);
|
||||
if (f == output_fields::hv_current_1)
|
||||
return pack_float(state.hv_current[0]);
|
||||
if (f == output_fields::hv_current_2)
|
||||
return pack_float(state.hv_current[1]);
|
||||
if (f == output_fields::hv_current_3)
|
||||
return pack_float(state.hv_current[2]);
|
||||
if (f == output_fields::lv_voltage)
|
||||
return pack_float(state.lv_voltage);
|
||||
if (f == output_fields::distance)
|
||||
return pack_float(state.distance);
|
||||
if (f == output_fields::radio_channel)
|
||||
return pack_float(state.radio_channel);
|
||||
if (f == output_fields::springbrake_active)
|
||||
return pack_float(state.springbrake_active);
|
||||
|
||||
return pack_float(0.0f);
|
||||
}
|
||||
77
input/zmq_input.h
Normal file
77
input/zmq_input.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <zmq_addon.hpp>
|
||||
#include "command.h"
|
||||
|
||||
class zmq_input
|
||||
{
|
||||
enum class output_fields {
|
||||
shp,
|
||||
alerter,
|
||||
radio_stop,
|
||||
motor_resistors,
|
||||
line_breaker,
|
||||
motor_overload,
|
||||
motor_connectors,
|
||||
wheelslip,
|
||||
converter_overload,
|
||||
converter_off,
|
||||
compressor_overload,
|
||||
ventilator_overload,
|
||||
motor_overload_threshold,
|
||||
train_heating,
|
||||
cab,
|
||||
recorder_braking,
|
||||
recorder_power,
|
||||
alerter_sound,
|
||||
coupled_hv_voltage_relays,
|
||||
velocity,
|
||||
reservoir_pressure,
|
||||
pipe_pressure,
|
||||
brake_pressure,
|
||||
hv_voltage,
|
||||
hv_current_1,
|
||||
hv_current_2,
|
||||
hv_current_3,
|
||||
lv_voltage,
|
||||
distance,
|
||||
radio_channel,
|
||||
springbrake_active,
|
||||
time_month_of_era,
|
||||
time_minute_of_month,
|
||||
time_millisecond_of_day
|
||||
};
|
||||
|
||||
zmq::context_t ctx;
|
||||
std::optional<zmq::socket_t> sock;
|
||||
|
||||
enum class input_type
|
||||
{
|
||||
none,
|
||||
toggle, // two commands, each mapped to one state; press event on state change
|
||||
impulse, // one command; press event when set, release when cleared
|
||||
value // one command; press event, value of specified byte passed as param1
|
||||
};
|
||||
|
||||
struct peer_state {
|
||||
float update_interval;
|
||||
std::vector<output_fields> sopi_list;
|
||||
std::vector<std::tuple<input_type, user_command, user_command, bool>> sipo_list;;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> last_update;
|
||||
};
|
||||
|
||||
std::map<uint32_t, peer_state> peers;
|
||||
|
||||
float unpack_float(const zmq::message_t &);
|
||||
zmq::message_t pack_float(float f);
|
||||
zmq::message_t pack_field(output_fields f);
|
||||
|
||||
std::unordered_map<std::string, user_command> nametocommandmap;
|
||||
|
||||
static std::unordered_map<std::string, output_fields> output_fields_map;
|
||||
command_relay relay;
|
||||
|
||||
public:
|
||||
zmq_input();
|
||||
void poll();
|
||||
};
|
||||
Reference in New Issue
Block a user