diff --git a/EvLaunch.cpp b/EvLaunch.cpp index aa41b9e4..39011426 100644 --- a/EvLaunch.cpp +++ b/EvLaunch.cpp @@ -56,12 +56,25 @@ bool TEventLauncher::Load(cParser *parser) dRadius *= dRadius; // do kwadratu, pod warunkiem, że nie jest ujemne parser->getTokens(); // klawisz sterujący *parser >> token; - if (token != "none") - { - if( token.size() == 1 ) + if (token != "none") { + + if( token.size() == 1 ) { + // single char, assigned activation key iKey = vk_to_glfw_key( token[ 0 ] ); - else - iKey = vk_to_glfw_key(stol_def( token, 0 )); // a jak więcej, to jakby numer klawisza jest + } + else { + // this launcher may be activated by radio message + std::map messages { + { "radio_call1", radio_message::call1 }, + { "radio_call3", radio_message::call3 } + }; + auto lookup = messages.find( token ); + iKey = ( + lookup != messages.end() ? + lookup->second : + // a jak więcej, to jakby numer klawisza jest + vk_to_glfw_key( stol_def( token, 0 ) ) ); + } } parser->getTokens(); *parser >> DeltaTime; @@ -139,7 +152,7 @@ bool TEventLauncher::check_activation() { auto bCond { false }; - if( iKey != 0 ) { + if( iKey > 0 ) { if( iKey > 255 ) { // key and modifier auto const modifier = ( iKey & 0xff00 ) >> 8; @@ -203,6 +216,11 @@ bool TEventLauncher::IsGlobal() const { && ( dRadius < 0.0 ) ); // bez ograniczenia zasięgu } +bool TEventLauncher::IsRadioActivated() const { + + return ( iKey < 0 ); +} + // radius() subclass details, calculates node's bounding radius float TEventLauncher::radius_() { diff --git a/EvLaunch.h b/EvLaunch.h index 84512e56..b4006901 100644 --- a/EvLaunch.h +++ b/EvLaunch.h @@ -14,6 +14,12 @@ http://mozilla.org/MPL/2.0/. #include "Classes.h" #include "scenenode.h" +// radio-transmitted event launch messages +enum radio_message { + call3 = -3, + call1 = -1 +}; + class TEventLauncher : public scene::basic_node { public: @@ -27,7 +33,11 @@ public: bool check_activation(); // checks conditions associated with the event. returns: true if the conditions are met bool check_conditions(); + inline + auto key() const { + return iKey; } bool IsGlobal() const; + bool IsRadioActivated() const; // members std::string asEvent1Name; std::string asEvent2Name; diff --git a/Event.cpp b/Event.cpp index ac58a10e..2e7ff1ca 100644 --- a/Event.cpp +++ b/Event.cpp @@ -1034,7 +1034,7 @@ logvalues_event::export_as_text_( std::ostream &Output ) const { void multi_event::init() { - auto const conditiontchecksmemcell { m_conditions.flags & ( flags::text | flags::value_1 | flags::value_2 ) }; + auto const conditiontchecksmemcell { ( m_conditions.flags & ( flags::text | flags::value_1 | flags::value_2 ) ) != 0 }; // not all multi-events have memory cell checks, for the ones which don't we can keep quiet about it init_targets( simulation::Memory, "memory cell", conditiontchecksmemcell ); if( m_ignored ) { @@ -1932,6 +1932,22 @@ event_manager::queue( TEventLauncher *Launcher ) { m_launcherqueue.emplace_back( Launcher ); } +// inserts in the event query events assigned to event launchers capable of receiving specified radio message sent from specified location +void +event_manager::queue_receivers( radio_message const Message, glm::dvec3 const &Location ) { + + for( auto *launcher : m_radiodrivenlaunchers.sequence() ) { + if( ( launcher->key() == Message ) + && ( ( launcher->dRadius < 0 ) + || ( glm::length2( launcher->location() - Location ) < launcher->dRadius ) ) + && ( true == launcher->check_conditions() ) ) { + // NOTE: only execution of event1 is supported for radio messages + // TBD, TODO: consider ability/way to execute event2 + simulation::Events.AddToQuery( launcher->Event1, nullptr ); + } + } +} + // legacy method, updates event queues void event_manager::update() { @@ -2135,32 +2151,39 @@ event_manager::InitEvents() { void event_manager::InitLaunchers() { - for( auto *launcher : m_launchers.sequence() ) { + std::vector *> launchertables { + &m_inputdrivenlaunchers, + &m_radiodrivenlaunchers + }; - if( launcher->iCheckMask != 0 ) { - if( launcher->asMemCellName != "none" ) { - // jeśli jest powiązana komórka pamięci - launcher->MemCell = simulation::Memory.find( launcher->asMemCellName ); - if( launcher->MemCell == nullptr ) { - ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find memcell \"" + launcher->asMemCellName + "\"" ); + for( auto *launchertable : launchertables ) { + for( auto *launcher : launchertable->sequence() ) { + + if( launcher->iCheckMask != 0 ) { + if( launcher->asMemCellName != "none" ) { + // jeśli jest powiązana komórka pamięci + launcher->MemCell = simulation::Memory.find( launcher->asMemCellName ); + if( launcher->MemCell == nullptr ) { + ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find memcell \"" + launcher->asMemCellName + "\"" ); + } + } + else { + launcher->MemCell = nullptr; } } - else { - launcher->MemCell = nullptr; - } - } - if( launcher->asEvent1Name != "none" ) { - launcher->Event1 = simulation::Events.FindEvent( launcher->asEvent1Name ); - if( launcher->Event1 == nullptr ) { - ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find event \"" + launcher->asEvent1Name + "\"" ); + if( launcher->asEvent1Name != "none" ) { + launcher->Event1 = simulation::Events.FindEvent( launcher->asEvent1Name ); + if( launcher->Event1 == nullptr ) { + ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find event \"" + launcher->asEvent1Name + "\"" ); + } } - } - if( launcher->asEvent2Name != "none" ) { - launcher->Event2 = simulation::Events.FindEvent( launcher->asEvent2Name ); - if( launcher->Event2 == nullptr ) { - ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find event \"" + launcher->asEvent2Name + "\"" ); + if( launcher->asEvent2Name != "none" ) { + launcher->Event2 = simulation::Events.FindEvent( launcher->asEvent2Name ); + if( launcher->Event2 == nullptr ) { + ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find event \"" + launcher->asEvent2Name + "\"" ); + } } } } @@ -2176,8 +2199,14 @@ event_manager::export_as_text( std::ostream &Output ) const { event->export_as_text( Output ); } } - Output << "// event launchers\n"; - for( auto const *launcher : m_launchers.sequence() ) { + Output << "// event launchers, basic\n"; + for( auto const *launcher : m_inputdrivenlaunchers.sequence() ) { + if( launcher->group() == null_handle ) { + launcher->export_as_text( Output ); + } + } + Output << "// event launchers, radio driven\n"; + for( auto const *launcher : m_radiodrivenlaunchers.sequence() ) { if( launcher->group() == null_handle ) { launcher->export_as_text( Output ); } diff --git a/Event.h b/Event.h index 59f82d75..ca01c295 100644 --- a/Event.h +++ b/Event.h @@ -559,6 +559,9 @@ public: // adds specified event launcher to the list of global launchers void queue( TEventLauncher *Launcher ); + // inserts in the event query events assigned to event launchers capable of receiving specified radio message sent from specified location + void + queue_receivers( radio_message const Message, glm::dvec3 const &Location ); // legacy method, updates event queues void update(); @@ -569,7 +572,10 @@ public: inline bool insert( TEventLauncher *Launcher ) { - return m_launchers.insert( Launcher ); } + return ( + Launcher->IsRadioActivated() ? + m_radiodrivenlaunchers.insert( Launcher ) : + m_inputdrivenlaunchers.insert( Launcher ) ); } // returns first event in the queue inline basic_event * @@ -609,7 +615,8 @@ private: basic_event *QueryRootEvent { nullptr }; basic_event *m_workevent { nullptr }; event_map m_eventmap; - basic_table m_launchers; + basic_table m_inputdrivenlaunchers; + basic_table m_radiodrivenlaunchers; eventlauncher_sequence m_launcherqueue; }; diff --git a/Train.cpp b/Train.cpp index d04a3622..49bb59c0 100644 --- a/Train.cpp +++ b/Train.cpp @@ -17,6 +17,7 @@ http://mozilla.org/MPL/2.0/. #include "Globals.h" #include "simulation.h" +#include "Event.h" #include "simulationtime.h" #include "Camera.h" #include "Logs.h" @@ -339,6 +340,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::radiochanneldecrease, &TTrain::OnCommand_radiochanneldecrease }, { user_command::radiostopsend, &TTrain::OnCommand_radiostopsend }, { user_command::radiostoptest, &TTrain::OnCommand_radiostoptest }, + { user_command::radiocall3send, &TTrain::OnCommand_radiocall3send }, { user_command::cabchangeforward, &TTrain::OnCommand_cabchangeforward }, { user_command::cabchangebackward, &TTrain::OnCommand_cabchangebackward }, { user_command::generictoggle0, &TTrain::OnCommand_generictoggle }, @@ -5014,6 +5016,7 @@ void TTrain::OnCommand_radiostoptest( TTrain *Train, command_data const &Command if( Command.action == GLFW_PRESS ) { if( ( Train->RadioChannel() == 10 ) + && ( true == Train->mvOccupied->Radio ) && ( Train->mvControlled->Battery || Train->mvControlled->ConverterFlag ) ) { Train->Dynamic()->RadioStop(); } @@ -5026,6 +5029,23 @@ void TTrain::OnCommand_radiostoptest( TTrain *Train, command_data const &Command } } +void TTrain::OnCommand_radiocall3send( TTrain *Train, command_data const &Command ) { + + if( Command.action == GLFW_PRESS ) { + if( ( Train->RadioChannel() != 10 ) + && ( true == Train->mvOccupied->Radio ) + && ( Train->mvControlled->Battery || Train->mvControlled->ConverterFlag ) ) { + simulation::Events.queue_receivers( radio_message::call3, Train->Dynamic()->GetPosition() ); + } + // visual feedback + Train->ggRadioCall3.UpdateValue( 1.0 ); + } + else if( Command.action == GLFW_RELEASE ) { + // visual feedback + Train->ggRadioCall3.UpdateValue( 0.0 ); + } +} + void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_PRESS ) { @@ -6141,6 +6161,7 @@ bool TTrain::Update( double const Deltatime ) ggRadioChannelNext.Update(); ggRadioStop.Update(); ggRadioTest.Update(); + ggRadioCall3.Update(); ggDepartureSignalButton.Update(); ggPantFrontButton.Update(); @@ -7351,6 +7372,7 @@ void TTrain::clear_cab_controls() ggRadioChannelNext.Clear(); ggRadioStop.Clear(); ggRadioTest.Clear(); + ggRadioCall3.Clear(); ggDoorLeftPermitButton.Clear(); ggDoorRightPermitButton.Clear(); ggDoorPermitPresetButton.Clear(); @@ -8037,6 +8059,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "radiochannelnext_sw:", ggRadioChannelNext }, { "radiostop_sw:", ggRadioStop }, { "radiotest_sw:", ggRadioTest }, + { "radiocall3_sw:", ggRadioCall3 }, { "pantfront_sw:", ggPantFrontButton }, { "pantrear_sw:", ggPantRearButton }, { "pantfrontoff_sw:", ggPantFrontButtonOff }, diff --git a/Train.h b/Train.h index 27a8c43e..0c510ef6 100644 --- a/Train.h +++ b/Train.h @@ -341,6 +341,7 @@ class TTrain static void OnCommand_radiochanneldecrease( TTrain *Train, command_data const &Command ); static void OnCommand_radiostopsend( TTrain *Train, command_data const &Command ); static void OnCommand_radiostoptest( TTrain *Train, command_data const &Command ); + static void OnCommand_radiocall3send( TTrain *Train, command_data const &Command ); static void OnCommand_cabchangeforward( TTrain *Train, command_data const &Command ); static void OnCommand_cabchangebackward( TTrain *Train, command_data const &Command ); static void OnCommand_generictoggle( TTrain *Train, command_data const &Command ); @@ -411,6 +412,7 @@ public: // reszta może by?publiczna TGauge ggRadioChannelNext; TGauge ggRadioTest; TGauge ggRadioStop; + TGauge ggRadioCall3; TGauge ggUpperLightButton; TGauge ggLeftLightButton; TGauge ggRightLightButton; diff --git a/command.cpp b/command.cpp index ea77daed..5b27f32f 100644 --- a/command.cpp +++ b/command.cpp @@ -123,6 +123,7 @@ commanddescription_sequence Commands_descriptions = { { "radiochanneldecrease", command_target::vehicle }, { "radiostopsend", command_target::vehicle }, { "radiostoptest", command_target::vehicle }, + { "radiocall3send", command_target::vehicle }, // TBD, TODO: make cab change controls entity-centric { "cabchangeforward", command_target::vehicle }, { "cabchangebackward", command_target::vehicle }, diff --git a/command.h b/command.h index 76f87aea..9a06cd14 100644 --- a/command.h +++ b/command.h @@ -117,6 +117,7 @@ enum class user_command { radiochanneldecrease, radiostopsend, radiostoptest, + radiocall3send, cabchangeforward, cabchangebackward, diff --git a/driverkeyboardinput.cpp b/driverkeyboardinput.cpp index 3d8d3a08..01883f12 100644 --- a/driverkeyboardinput.cpp +++ b/driverkeyboardinput.cpp @@ -128,6 +128,7 @@ driverkeyboard_input::default_bindings() { { user_command::radiochanneldecrease, GLFW_KEY_R }, { user_command::radiostopsend, GLFW_KEY_PAUSE | keymodifier::shift | keymodifier::control }, { user_command::radiostoptest, GLFW_KEY_R | keymodifier::shift | keymodifier::control }, + { user_command::radiocall3send, GLFW_KEY_BACKSPACE }, { user_command::cabchangeforward, GLFW_KEY_HOME }, { user_command::cabchangebackward, GLFW_KEY_END }, // viewturn, diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index 4d5b3130..e4db62b5 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -711,6 +711,9 @@ drivermouse_input::default_bindings() { { "radiotest_sw:", { user_command::radiostoptest, user_command::none } }, + { "radiocall3_sw:", { + user_command::radiocall3send, + user_command::none } }, { "pantfront_sw:", { user_command::pantographtogglefront, user_command::none } }, diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index 10f20e2e..a4d2790a 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -516,7 +516,10 @@ state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratch } else { scene::Groups.insert( scene::Groups.handle(), eventlauncher ); - simulation::Region->insert( eventlauncher ); + if( false == eventlauncher->IsRadioActivated() ) { + // NOTE: radio-activated launchers due to potentially large activation radius are resolved on global level rather than put in a region cell + simulation::Region->insert( eventlauncher ); + } } } else if( nodedata.type == "sound" ) { diff --git a/translation.cpp b/translation.cpp index 631b79a4..0465e7b7 100644 --- a/translation.cpp +++ b/translation.cpp @@ -157,6 +157,7 @@ init() { "radio channel", "radiostop test", "radiostop", + "radio call 3", "pantograph A", "pantograph B", "pantograph A", @@ -323,6 +324,7 @@ init() { "kanal radia", "test radiostopu", "radiostop", + "zew 3", "pantograf A", "pantograf B", "pantograf A", @@ -442,6 +444,7 @@ init() { "radiochannelnext_sw:", "radiotest_sw:", "radiostop_sw:", + "radiocall3_sw:", "pantfront_sw:", "pantrear_sw:", "pantfrontoff_sw:", diff --git a/translation.h b/translation.h index 71bec11c..cb64123b 100644 --- a/translation.h +++ b/translation.h @@ -146,6 +146,7 @@ enum string { cab_radiochannelnext_sw, cab_radiotest_sw, cab_radiostop_sw, + cab_radiocall3_sw, cab_pantfront_sw, cab_pantrear_sw, cab_pantfrontoff_sw, diff --git a/version.h b/version.h index ee544018..67a81d3e 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 614 +#define VERSION_MINOR 701 #define VERSION_REVISION 0