From e84f4f53fdcadfd6affe260a5b4b18b51944ca32 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sun, 23 Apr 2017 13:16:28 +0200 Subject: [PATCH] added support for redefinition of keyboard bindings. control for engine cutoff, minor changes to line breaker activation --- EU07.cpp | 1 + Train.cpp | 252 ++++++++++++++++++++++++++-------------------- Train.h | 5 +- command.cpp | 12 +-- command.h | 3 +- keyboardinput.cpp | 94 +++++++++++++++-- keyboardinput.h | 4 +- 7 files changed, 245 insertions(+), 126 deletions(-) diff --git a/EU07.cpp b/EU07.cpp index f36b2573..4fbfa0c9 100644 --- a/EU07.cpp +++ b/EU07.cpp @@ -345,6 +345,7 @@ int main(int argc, char *argv[]) return -1; } + input::Keyboard.init(); input::Gamepad.init(); Global::pWorld = &World; // Ra: wskaźnik potrzebny do usuwania pojazdów diff --git a/Train.cpp b/Train.cpp index fdea2409..70fb0519 100644 --- a/Train.cpp +++ b/Train.cpp @@ -144,7 +144,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::secondcontrollerdecrease, &TTrain::OnCommand_secondcontrollerdecrease }, { user_command::secondcontrollerdecreasefast, &TTrain::OnCommand_secondcontrollerdecreasefast }, { user_command::notchingrelaytoggle, &TTrain::OnCommand_notchingrelaytoggle }, - { user_command::mucurrentindicatorsourcetoggle, &TTrain::OnCommand_mucurrentindicatorsourcetoggle }, + { user_command::mucurrentindicatorothersourceactivate, &TTrain::OnCommand_mucurrentindicatorothersourceactivate }, { user_command::independentbrakeincrease, &TTrain::OnCommand_independentbrakeincrease }, { user_command::independentbrakeincreasefast, &TTrain::OnCommand_independentbrakeincreasefast }, { user_command::independentbrakedecrease, &TTrain::OnCommand_independentbrakedecrease }, @@ -178,6 +178,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::converteroverloadrelayreset, &TTrain::OnCommand_converteroverloadrelayreset }, { user_command::compressortoggle, &TTrain::OnCommand_compressortoggle }, { user_command::motorconnectorsopen, &TTrain::OnCommand_motorconnectorsopen }, + { user_command::motordisconnect, &TTrain::OnCommand_motordisconnect }, { user_command::motoroverloadrelaythresholdtoggle, &TTrain::OnCommand_motoroverloadrelaythresholdtoggle }, { user_command::motoroverloadrelayreset, &TTrain::OnCommand_motoroverloadrelayreset }, { user_command::heatingtoggle, &TTrain::OnCommand_heatingtoggle }, @@ -573,7 +574,7 @@ void TTrain::OnCommand_notchingrelaytoggle( TTrain *Train, command_data const &C } } -void TTrain::OnCommand_mucurrentindicatorsourcetoggle( TTrain *Train, command_data const &Command ) { +void TTrain::OnCommand_mucurrentindicatorothersourceactivate( TTrain *Train, command_data const &Command ) { if( Train->ggNextCurrentButton.SubModel == nullptr ) { if( Command.action == GLFW_PRESS ) { @@ -583,27 +584,24 @@ void TTrain::OnCommand_mucurrentindicatorsourcetoggle( TTrain *Train, command_da } if( Command.action == GLFW_PRESS ) { - // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( false == Train->ShowNextCurrent ) { - // turn on - Train->ShowNextCurrent = true; - // audio feedback - if( Train->ggNextCurrentButton.GetValue() < 0.5 ) { - Train->play_sound( Train->dsbSwitch ); - } - // visual feedback - Train->ggNextCurrentButton.UpdateValue( 1.0 ); + // turn on + Train->ShowNextCurrent = true; + // audio feedback + if( Train->ggNextCurrentButton.GetValue() < 0.5 ) { + Train->play_sound( Train->dsbSwitch ); } - else { - //turn off - Train->ShowNextCurrent = false; - // audio feedback - if( Train->ggNextCurrentButton.GetValue() > 0.5 ) { - Train->play_sound( Train->dsbSwitch ); - } - // visual feedback - Train->ggNextCurrentButton.UpdateValue( 0.0 ); + // visual feedback + Train->ggNextCurrentButton.UpdateValue( 1.0 ); + } + else if( Command.action == GLFW_RELEASE ) { + //turn off + Train->ShowNextCurrent = false; + // audio feedback + if( Train->ggNextCurrentButton.GetValue() > 0.5 ) { + Train->play_sound( Train->dsbSwitch ); } + // visual feedback + Train->ggNextCurrentButton.UpdateValue( 0.0 ); } } @@ -922,7 +920,7 @@ void TTrain::OnCommand_sandboxactivate( TTrain *Train, command_data const &Comma // TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels if( Train->ggSandButton.SubModel == nullptr ) { if( Command.action == GLFW_PRESS ) { - WriteLog( "Wheelspin Brake button is missing, or wasn't defined" ); + WriteLog( "Sandbox activation button is missing, or wasn't defined" ); } return; } @@ -1200,14 +1198,11 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command // audio feedback Train->play_sound( Train->dsbSwitch ); // side-effects -/* - // NOTE: on second thought, don't and let them drop when the pantograph tank pressure drops below threshold if( false == Train->mvControlled->ConverterFlag ) { // if there's no (low voltage) power source left, drop pantographs Train->mvControlled->PantFront( false ); Train->mvControlled->PantRear( false ); } -*/ } } } @@ -1518,117 +1513,123 @@ void TTrain::OnCommand_pantographlowerall( TTrain *Train, command_data const &Co void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Command ) { if( ( Command.action == GLFW_PRESS ) - && ( true == Train->m_linebreakerclosed ) + && ( Train->m_linebreakerstate == 1 ) && ( false == Train->mvControlled->Mains ) && ( Train->ggMainButton.GetValue() < 0.05 ) ) { // crude way to catch cases where the main was knocked out and the user is trying to restart it // because the state of the line breaker isn't changed to match, we need to do it here manually - Train->m_linebreakerclosed = false; + Train->m_linebreakerstate = 0; } // NOTE: we don't have switch type definition for the line breaker switch // so for the time being we have hard coded "impulse" switches for all EMUs // TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz - if( ( true == Train->m_linebreakerclosed ) + if( ( Train->m_linebreakerstate == 1 ) && ( Train->mvControlled->TrainType == dt_EZT ) ) { // a single impulse switch can't open the circuit, only close it return; } - if( Command.action != GLFW_RELEASE ) { // press or hold... - if( false == Train->mvControlled->Mains ) { + if( Train->m_linebreakerstate == 0 ) { // ...to close the circuit - if( false == Train->m_linebreakerclosed ) { - // safety check so we don't close the circuit right after opening - if( Train->ggMainOnButton.SubModel != nullptr ) { + if( Train->ggMainOnButton.SubModel != nullptr ) { + // two separate switches to close and break the circuit + // audio feedback + if( Command.action == GLFW_PRESS ) { + Train->play_sound( Train->dsbSwitch ); + } + // visual feedback + Train->ggMainOnButton.UpdateValue( 1.0 ); + } + else if( Train->ggMainButton.SubModel != nullptr ) { + // single two-state switch + // audio feedback + if( Command.action == GLFW_PRESS ) { + Train->play_sound( Train->dsbSwitch ); + } + // visual feedback + Train->ggMainButton.UpdateValue( 1.0 ); + } + // keep track of period the button is held down, to determine when/if circuit closes + if( ( false == ( Train->mvControlled->EnginePowerSource.PowerType == ElectricSeriesMotor ) || ( Train->mvControlled->EngineType == ElectricInductionMotor ) ) + || ( Train->fHVoltage > 0.0f ) ) { + // prevent the switch from working if there's no power + // TODO: consider whether it makes sense for diesel engines and such + Train->fMainRelayTimer += 0.33f; // Command.time_delta * 5.0; + } + if( Train->mvControlled->Mains != true ) { + // hunter-080812: poprawka + Train->mvControlled->ConverterSwitch( false ); + Train->mvControlled->CompressorSwitch( false ); + } + if( Train->fMainRelayTimer > Train->mvControlled->InitialCtrlDelay ) { + // wlaczanie WSa z opoznieniem + Train->m_linebreakerstate = 2; + // for diesels, we complete the engine start here + // TODO: consider arranging a better way to start the diesel engines + if( Train->mvControlled->EngineType == DieselEngine ) { + if( Train->mvControlled->MainSwitch( true ) ) { + // sound feedback, engine start for diesel vehicle + Train->play_sound( Train->dsbDieselIgnition ); + // side-effects + Train->mvControlled->ConverterSwitch( Train->ggConverterButton.GetValue() > 0.5 ); + Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 ); + } + } + } + } + else if( Train->m_linebreakerstate == 1 ) { + // ...to open the circuit + if( true == Train->mvControlled->MainSwitch( false ) ) { + + Train->m_linebreakerstate = -1; + + if( Train->ggMainOffButton.SubModel != nullptr ) { // two separate switches to close and break the circuit // audio feedback if( Command.action == GLFW_PRESS ) { Train->play_sound( Train->dsbSwitch ); } // visual feedback - Train->ggMainOnButton.UpdateValue( 1.0 ); + Train->ggMainOffButton.UpdateValue( 1.0 ); } else if( Train->ggMainButton.SubModel != nullptr ) { // single two-state switch - // audio feedback - if( Command.action == GLFW_PRESS ) { - Train->play_sound( Train->dsbSwitch ); - } - // visual feedback - Train->ggMainButton.UpdateValue( 1.0 ); - } - // keep track of period the button is held down, to determine when/if circuit closes - Train->fMainRelayTimer += 0.33f; // Command.time_delta * 5.0; - if( Train->mvControlled->Mains != true ) { - // hunter-080812: poprawka - Train->mvControlled->ConverterSwitch( false ); - Train->mvControlled->CompressorSwitch( false ); - } - if( Train->fMainRelayTimer > Train->mvControlled->InitialCtrlDelay ) { - // wlaczanie WSa z opoznieniem - if( Train->mvControlled->MainSwitch( true ) ) { - // sound feedback, engine start for diesel vehicle - if( Train->mvControlled->EngineType == DieselEngine ) { - Train->play_sound( Train->dsbDieselIgnition ); - } - } - } - } - } - else { - // ...to open the circuit - if( true == Train->m_linebreakerclosed ) { - // safety check so we don't open the circuit right after closing - if( Train->mvControlled->MainSwitch( false ) ) { - - if( Train->ggMainOffButton.SubModel != nullptr ) { - // two separate switches to close and break the circuit +/* + // NOTE: we don't have switch type definition for the line breaker switch + // so for the time being we have hard coded "impulse" switches for all EMUs + // TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz + if( Train->mvControlled->TrainType == dt_EZT ) { // audio feedback if( Command.action == GLFW_PRESS ) { Train->play_sound( Train->dsbSwitch ); } // visual feedback - Train->ggMainOffButton.UpdateValue( 1.0 ); + Train->ggMainButton.UpdateValue( 1.0 ); } - else if( Train->ggMainButton.SubModel != nullptr ) { - // single two-state switch -/* - // NOTE: we don't have switch type definition for the line breaker switch - // so for the time being we have hard coded "impulse" switches for all EMUs - // TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz - if( Train->mvControlled->TrainType == dt_EZT ) { - // audio feedback - if( Command.action == GLFW_PRESS ) { - Train->play_sound( Train->dsbSwitch ); - } - // visual feedback - Train->ggMainButton.UpdateValue( 1.0 ); - } - else + else */ - { - // audio feedback - if( Command.action == GLFW_PRESS ) { - Train->play_sound( Train->dsbSwitch ); - } - // visual feedback - Train->ggMainButton.UpdateValue( 0.0 ); + { + // audio feedback + if( Command.action == GLFW_PRESS ) { + Train->play_sound( Train->dsbSwitch ); } + // visual feedback + Train->ggMainButton.UpdateValue( 0.0 ); } } - // play sound immediately when the switch is hit, not after release - if( Train->fMainRelayTimer > 0.0f ) { - Train->play_sound( Train->dsbRelay ); - Train->fMainRelayTimer = 0.0f; - } + } + // play sound immediately when the switch is hit, not after release + if( Train->fMainRelayTimer > 0.0f ) { + Train->play_sound( Train->dsbRelay ); + Train->fMainRelayTimer = 0.0f; } } } else { // release... - if( false == Train->mvControlled->Mains ) { + if( Train->m_linebreakerstate <= 0 ) { // ...after opening circuit, or holding for too short time to close it // hunter-091012: przeniesione z mover.pas, zeby dzwiek sie nie zapetlal, if( Train->fMainRelayTimer > 0.0f ) { @@ -1656,13 +1657,19 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com // visual feedback Train->ggMainButton.UpdateValue( 0.0 ); } - Train->m_linebreakerclosed = false; + // finalize the state of the line breaker + Train->m_linebreakerstate = 0; } else { // ...after closing the circuit - // side-effects - Train->mvControlled->ConverterSwitch( Train->ggConverterButton.GetValue() > 0.5 ); - Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 ); + // we don't need to start the diesel twice, but the other types still need to be launched + if( Train->mvControlled->EngineType != DieselEngine ) { + if( Train->mvControlled->MainSwitch( true ) ) { + // side-effects + Train->mvControlled->ConverterSwitch( Train->ggConverterButton.GetValue() > 0.5 ); + Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 ); + } + } // audio feedback if( Train->ggMainOnButton.GetValue() > 0.5 ) { Train->play_sound( Train->dsbSwitch ); @@ -1685,7 +1692,8 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com Train->ggMainButton.UpdateValue( 0.0 ); } } - Train->m_linebreakerclosed = true; + // finalize the state of the line breaker + Train->m_linebreakerstate = 1; } } } @@ -1710,8 +1718,8 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma // NOTE: this is most likely setup wrong, but the whole thing is smoke and mirrors anyway if( ( Train->mvOccupied->ConvSwitchType != "impulse" ) || ( Train->mvControlled->Mains ) ) { - if( ( true == Train->m_linebreakerclosed ) // won't start if the line breaker button is still held - && ( true == Train->mvControlled->ConverterSwitch( true ) ) ) { + // won't start if the line breaker button is still held + if( true == Train->mvControlled->ConverterSwitch( true ) ) { // side effects // control the compressor, if it's paired with the converter if( Train->mvControlled->CompressorPower == 2 ) { @@ -1752,13 +1760,10 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma Train->mvControlled->ConvOvldFlag = false; } // if there's no (low voltage) power source left, drop pantographs -/* - // NOTE: on second thought, don't and let them drop when the pantograph tank pressure drops below threshold if( false == Train->mvControlled->Battery ) { Train->mvControlled->PantFront( false ); Train->mvControlled->PantRear( false ); } -*/ } } } @@ -1911,6 +1916,23 @@ void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &C } } +void TTrain::OnCommand_motordisconnect( TTrain *Train, command_data const &Command ) { + + if( ( Train->mvControlled->TrainType == dt_EZT ? + ( Train->mvControlled != Train->mvOccupied ) : + ( Train->mvOccupied->ActiveCab != 0 ) ) ) { + // tylko w maszynowym + return; + } + + if( Command.action == GLFW_PRESS ) { + if( true == Train->mvControlled->CutOffEngine() ) { + // sound feedback + Train->play_sound( Train->dsbSwitch ); + } + } +} + void TTrain::OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_PRESS ) { @@ -3106,7 +3128,6 @@ void TTrain::OnKeyDown(int cKey) play_sound( dsbSwitch ); } } -#endif else if( cKey == Global::Keys[ k_FailedEngineCutOff ] ) { // McZapkie-060103: E - wylaczanie sekcji silnikow if (mvControlled->CutOffEngine()) @@ -3114,7 +3135,6 @@ void TTrain::OnKeyDown(int cKey) play_sound( dsbSwitch ); } } -#ifdef EU07_USE_OLD_COMMAND_SYSTEM else if( cKey == Global::Keys[ k_OpenLeft ] ) // NBMX 17-09-2003: otwieranie drzwi { if (mvOccupied->DoorOpenCtrl == 1) @@ -5014,6 +5034,10 @@ bool TTrain::Update( double const Deltatime ) auto lookup = m_commandhandlers.find( commanddata.command ); if( lookup != m_commandhandlers.end() ) { + // debug data + if( commanddata.action != GLFW_RELEASE ) { + WriteLog( mvOccupied->Name + " received command: [" + simulation::Commands_descriptions[ static_cast( commanddata.command ) ].name + "]" ); + } // pass the command to the assigned handler lookup->second( this, commanddata ); } @@ -5033,6 +5057,16 @@ bool TTrain::Update( double const Deltatime ) DWORD stat; double dt = Deltatime; // Timer::GetDeltaTime(); + + // catch cases where the power goes out, and the linebreaker state is left as closed + if( ( m_linebreakerstate == 1 ) + && ( false == mvControlled->Mains ) + && ( ggMainButton.GetValue() < 0.05 ) ) { + // crude way to catch cases where the main was knocked out and the user is trying to restart it + // because the state of the line breaker isn't changed to match, we need to do it here manually + m_linebreakerstate = 0; + } + /* // NOTE: disabled while switch state isn't preserved while moving between compartments // check whether we should raise the pantographs, based on volume in pantograph tank @@ -5907,7 +5941,7 @@ bool TTrain::Update( double const Deltatime ) if (mvControlled->Battery || mvControlled->ConverterFlag) { - btLampkaWylSzybki.Turn( mvControlled->Mains ); + btLampkaWylSzybki.Turn( ( m_linebreakerstate > 0 ? true : false ) ); // hunter-261211: jakis stary kod (i niezgodny z prawda), // zahaszowalem i poprawilem diff --git a/Train.h b/Train.h index 1bce34d6..786883c2 100644 --- a/Train.h +++ b/Train.h @@ -120,7 +120,7 @@ class TTrain static void OnCommand_secondcontrollerdecrease( TTrain *Train, command_data const &Command ); static void OnCommand_secondcontrollerdecreasefast( TTrain *Train, command_data const &Command ); static void OnCommand_notchingrelaytoggle( TTrain *Train, command_data const &Command ); - static void OnCommand_mucurrentindicatorsourcetoggle( TTrain *Train, command_data const &Command ); + static void OnCommand_mucurrentindicatorothersourceactivate( TTrain *Train, command_data const &Command ); static void OnCommand_independentbrakeincrease( TTrain *Train, command_data const &Command ); static void OnCommand_independentbrakeincreasefast( TTrain *Train, command_data const &Command ); static void OnCommand_independentbrakedecrease( TTrain *Train, command_data const &Command ); @@ -154,6 +154,7 @@ class TTrain static void OnCommand_converteroverloadrelayreset( TTrain *Train, command_data const &Command ); static void OnCommand_compressortoggle( TTrain *Train, command_data const &Command ); static void OnCommand_motorconnectorsopen( TTrain *Train, command_data const &Command ); + static void OnCommand_motordisconnect( TTrain *Train, command_data const &Command ); static void OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command_data const &Command ); static void OnCommand_motoroverloadrelayreset( TTrain *Train, command_data const &Command ); static void OnCommand_heatingtoggle( TTrain *Train, command_data const &Command ); @@ -186,7 +187,7 @@ class TTrain TMoverParameters *mvSecond; // drugi człon (ET40, ET41, ET42, ukrotnienia) TMoverParameters *mvThird; // trzeci człon (SN61) // helper variable, to prevent immediate switch between closing and opening line breaker circuit - bool m_linebreakerclosed{ false }; + int m_linebreakerstate{ 0 }; // -1: freshly open, 0: open, 1: closed, 2: freshly closed (and yes this is awful way to go about it) static const commandhandler_map m_commandhandlers; public: // reszta może by?publiczna diff --git a/command.cpp b/command.cpp index 6d75124e..4ad7c4e0 100644 --- a/command.cpp +++ b/command.cpp @@ -27,7 +27,7 @@ commanddescription_sequence Commands_descriptions = { { "secondcontrollerincreasefast", command_target::vehicle }, { "secondcontrollerdecrease", command_target::vehicle }, { "secondcontrollerdecreasefast", command_target::vehicle }, - { "mucurrentindicatorsourcetoggle", command_target::vehicle }, + { "mucurrentindicatorothersourceactivate", command_target::vehicle }, { "independentbrakeincrease", command_target::vehicle }, { "independentbrakeincreasefast", command_target::vehicle }, { "independentbrakedecrease", command_target::vehicle }, @@ -58,7 +58,7 @@ commanddescription_sequence Commands_descriptions = { { "mubrakingindicatortoggle", command_target::vehicle }, { "alerteracknowledge", command_target::vehicle }, { "hornlowactivate", command_target::vehicle }, - { "hornhighctivate", command_target::vehicle }, + { "hornhighactivate", command_target::vehicle }, { "radiotoggle", command_target::vehicle }, /* const int k_FailedEngineCutOff = 35; @@ -111,6 +111,7 @@ const int k_ProgramHelp = 48; { "redmarkertogglerearright", command_target::vehicle }, { "headlightsdimtoggle", command_target::vehicle }, { "motorconnectorsopen", command_target::vehicle }, + { "motordisconnect", command_target::vehicle }, { "interiorlighttoggle", command_target::vehicle }, { "interiorlightdimtoggle", command_target::vehicle }, { "instrumentlighttoggle", command_target::vehicle }, @@ -180,7 +181,7 @@ command_relay::post( user_command const Command, std::uint64_t const Param1, std Param2, Timer::GetDeltaTime() }, static_cast( command.target ) | Recipient ); - +/* #ifdef _DEBUG if( Action != GLFW_RELEASE ) { // key was pressed or is still held @@ -204,13 +205,12 @@ command_relay::post( user_command const Command, std::uint64_t const Param1, std } } } -/* else { // key was released (but we don't log this) - WriteLog( "Key released: " + m_command.name ); + WriteLog( "Key released: " + command.name ); } -*/ #endif +*/ } //--------------------------------------------------------------------------- diff --git a/command.h b/command.h index 2be03a0c..9ba1d725 100644 --- a/command.h +++ b/command.h @@ -22,7 +22,7 @@ enum class user_command { secondcontrollerincreasefast, secondcontrollerdecrease, secondcontrollerdecreasefast, - mucurrentindicatorsourcetoggle, + mucurrentindicatorothersourceactivate, independentbrakeincrease, independentbrakeincreasefast, independentbrakedecrease, @@ -106,6 +106,7 @@ const int k_ProgramHelp = 48; redmarkertogglerearright, headlightsdimtoggle, motorconnectorsopen, + motordisconnect, interiorlighttoggle, interiorlightdimtoggle, instrumentlighttoggle, diff --git a/keyboardinput.cpp b/keyboardinput.cpp index af3e3ef8..2c32b9e4 100644 --- a/keyboardinput.cpp +++ b/keyboardinput.cpp @@ -10,13 +10,93 @@ http://mozilla.org/MPL/2.0/. #include "stdafx.h" #include "keyboardinput.h" #include "logs.h" +#include "parser.h" -void +bool keyboard_input::recall_bindings() { - // TODO: implement + // build helper translation tables + std::unordered_map nametocommandmap; + std::size_t commandid = 0; + for( auto const &description : simulation::Commands_descriptions ) { + nametocommandmap.emplace( + description.name, + static_cast( commandid ) ); + ++commandid; + } + std::unordered_map nametokeymap = { + { "a", GLFW_KEY_A }, { "b", GLFW_KEY_B }, { "c", GLFW_KEY_C }, { "d", GLFW_KEY_D }, { "e", GLFW_KEY_E }, + { "f", GLFW_KEY_F }, { "g", GLFW_KEY_G }, { "h", GLFW_KEY_H }, { "i", GLFW_KEY_I }, { "j", GLFW_KEY_J }, + { "k", GLFW_KEY_K }, { "l", GLFW_KEY_L }, { "m", GLFW_KEY_M }, { "n", GLFW_KEY_N }, { "o", GLFW_KEY_O }, + { "p", GLFW_KEY_P }, { "q", GLFW_KEY_Q }, { "r", GLFW_KEY_R }, { "s", GLFW_KEY_S }, { "t", GLFW_KEY_T }, + { "u", GLFW_KEY_U }, { "v", GLFW_KEY_V }, { "w", GLFW_KEY_W }, { "x", GLFW_KEY_X }, { "y", GLFW_KEY_Y }, { "z", GLFW_KEY_Z }, + { "-", GLFW_KEY_MINUS }, { "=", GLFW_KEY_EQUAL }, { "backspace", GLFW_KEY_BACKSPACE }, + { "[", GLFW_KEY_LEFT_BRACKET }, { "]", GLFW_KEY_RIGHT_BRACKET }, { "\\", GLFW_KEY_BACKSLASH }, + { ";", GLFW_KEY_SEMICOLON }, { "'", GLFW_KEY_APOSTROPHE }, { "enter", GLFW_KEY_ENTER }, + { ",", GLFW_KEY_COMMA }, { ".", GLFW_KEY_PERIOD }, { "/", GLFW_KEY_SLASH }, + { "space", GLFW_KEY_SPACE }, + // numpad block + { "num_/", GLFW_KEY_KP_DIVIDE }, { "num_*", GLFW_KEY_KP_MULTIPLY }, { "num_-", GLFW_KEY_KP_SUBTRACT }, + { "num_7", GLFW_KEY_KP_7 }, { "num_8", GLFW_KEY_KP_8 }, { "num_9", GLFW_KEY_KP_9 }, { "num_+", GLFW_KEY_KP_ADD }, + { "num_4", GLFW_KEY_KP_4 }, { "num_5", GLFW_KEY_KP_5 }, { "num_6", GLFW_KEY_KP_6 }, + { "num_1", GLFW_KEY_KP_1 }, { "num_2", GLFW_KEY_KP_2 }, { "num_3", GLFW_KEY_KP_3 }, { "num_enter", GLFW_KEY_KP_ENTER }, + { "num_0", GLFW_KEY_KP_0 }, { "num_.", GLFW_KEY_KP_DECIMAL } + }; + + cParser bindingparser( "eu07_input-keyboard.ini", cParser::buffer_FILE ); + if( false == bindingparser.ok() ) { + return false; + } + + while( true == bindingparser.getTokens( 1, true, "\n" ) ) { + + std::string bindingentry; + bindingparser >> bindingentry; + cParser entryparser( bindingentry ); + 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 binding{ 0 }; + while( entryparser.getTokens( 1, true, "\n\r\t " ) ) { + + std::string bindingkeyname; + entryparser >> bindingkeyname; + + if( bindingkeyname == "shift" ) { binding |= keymodifier::shift; } + else if( bindingkeyname == "ctrl" ) { binding |= keymodifier::control; } + 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) + binding = keylookup->second | ( binding & 0xffff0000 ); + } + } + + if( ( binding & 0xffff ) != 0 ) { + m_commands.at( static_cast( lookup->second ) ).binding = binding; + } + } + } + } + } bind(); + + return true; } bool @@ -108,7 +188,7 @@ keyboard_input::default_bindings() { { GLFW_KEY_KP_MULTIPLY }, // secondcontrollerdecreasefast { GLFW_KEY_KP_MULTIPLY | keymodifier::shift }, - // mucurrentindicatorsourcetoggle + // mucurrentindicatorothersourceactivate { GLFW_KEY_Z | keymodifier::shift }, // independentbrakeincrease { GLFW_KEY_KP_1 }, @@ -164,7 +244,7 @@ keyboard_input::default_bindings() { { GLFW_KEY_B | keymodifier::shift }, // brakeactingspeeddecrease { GLFW_KEY_B }, - // brakingindicatortoggle + // mubrakingindicatortoggle { GLFW_KEY_L | keymodifier::shift }, // alerteracknowledge { GLFW_KEY_SPACE }, @@ -174,9 +254,6 @@ keyboard_input::default_bindings() { { GLFW_KEY_A | keymodifier::shift }, // radiotoggle { GLFW_KEY_R | keymodifier::control }, -/* -const int k_FailedEngineCutOff = 35; -*/ // viewturn { -1 }, // movevector @@ -261,6 +338,8 @@ const int k_ProgramHelp = 48; { GLFW_KEY_L | keymodifier::control }, // motorconnectorsopen { GLFW_KEY_L }, + // motordisconnect + { GLFW_KEY_E | keymodifier::shift }, // interiorlighttoggle { GLFW_KEY_APOSTROPHE }, // interiorlightdimtoggle @@ -300,6 +379,7 @@ keyboard_input::bind() { } ++commandcode; } + // cache movement key bindings, so we can test them faster in the input loop m_bindingscache.forward = m_commands[ static_cast( user_command::moveforward ) ].binding; m_bindingscache.back = m_commands[ static_cast( user_command::moveback ) ].binding; diff --git a/keyboardinput.h b/keyboardinput.h index 12301797..e2d78708 100644 --- a/keyboardinput.h +++ b/keyboardinput.h @@ -20,7 +20,9 @@ public: keyboard_input() { default_bindings(); } // methods - void + bool + init() { return recall_bindings(); } + bool recall_bindings(); bool key( int const Key, int const Action );