From e6bbce64b73e6abf7dafb4308f8a6ae8e5e42a88 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 8 May 2019 19:35:18 +0200 Subject: [PATCH 01/12] build 190504. pantograph compressor start method, door control mode support, impulse type battery switch support, disconnect ai logic tweak --- Driver.cpp | 91 +++++++++++++++++++-------------------- McZapkie/MOVER.h | 5 ++- McZapkie/Mover.cpp | 95 +++++++++++++++++++++++++++-------------- Train.cpp | 64 +++++++++++++++++---------- Train.h | 1 + command.cpp | 1 + command.h | 1 + driverkeyboardinput.cpp | 1 + drivermouseinput.cpp | 3 ++ translation.cpp | 3 ++ translation.h | 1 + version.h | 2 +- 12 files changed, 163 insertions(+), 105 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 04198d18..15275845 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -4176,6 +4176,7 @@ TController::UpdateSituation(double dt) { // HACK: activate route scanning if an idling vehicle is activated by a human user if( ( OrderCurrentGet() == Wait_for_orders ) && ( false == AIControllFlag ) + && ( false == iEngineActive ) && ( true == mvControlling->Battery ) ) { OrderNext( Prepare_engine ); } @@ -5004,54 +5005,50 @@ TController::UpdateSituation(double dt) { // jeśli dociskanie w celu odczepienia // 3. faza odczepiania. SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2 - if( ( mvControlling->MainCtrlPowerPos() > 0 ) - || ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) { - // jeśli jazda - WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); - TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI - int d; // numer sprzęgu, który sprawdzamy albo odczepiamy - int n = iVehicleCount; // ile wagonów ma zostać - do - { // szukanie pojazdu do odczepienia - d = p->DirectionGet() > 0 ? - end::front : - end::rear; // numer sprzęgu od strony czoła składu - // if (p->MoverParameters->Couplers[d].CouplerType==Articulated) - // //jeśli sprzęg typu wózek (za mało) - if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany - // if (p->GetTrack()->) //a nie stoi na torze warsztatowym - // (ustalić po czym poznać taki tor) - ++n; // to liczymy człony jako jeden - p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać - // GBH p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował - BrakeLevelSet(gbh_RP); - if (n) - { // jeśli jeszcze nie koniec - p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy - if (!p) - iVehicleCount = -2, - n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone - } - } while (n--); - if( ( p == nullptr ) - || ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) { - // no target, or already just virtual coupling - WriteLog( mvOccupied->Name + " didn't find anything to disconnect." ); - iVehicleCount = -2; // odczepiono, co było do odczepienia - } else if ( p->Dettach(d) == coupling::faux ) { - // tylko jeśli odepnie - WriteLog( mvOccupied->Name + " odczepiony." ); - iVehicleCount = -2; - } // a jak nie, to dociskać dalej - } - if (iVehicleCount >= 0) // zmieni się po odczepieniu - if (!mvOccupied->DecLocalBrakeLevel(1)) - { // dociśnij sklad - WriteLog( mvOccupied->Name + " dociskanie..." ); - // mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę - // Ready=true; //zamiast sprawdzenia odhamowania całego składu - IncSpeed(); // dla (Ready)==false nie ruszy + if( iVehicleCount >= 0 ) { + // zmieni się po odczepieniu + WriteLog( mvOccupied->Name + " dociskanie..." ); + while( mvOccupied->DecLocalBrakeLevel( 1 ) ) { // dociśnij sklad + ; } + IncSpeed(); + } + WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); + TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI + int d; // numer sprzęgu, który sprawdzamy albo odczepiamy + int n = iVehicleCount; // ile wagonów ma zostać + do + { // szukanie pojazdu do odczepienia + d = p->DirectionGet() > 0 ? + end::front : + end::rear; // numer sprzęgu od strony czoła składu + // if (p->MoverParameters->Couplers[d].CouplerType==Articulated) + // //jeśli sprzęg typu wózek (za mało) + if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany + // if (p->GetTrack()->) //a nie stoi na torze warsztatowym + // (ustalić po czym poznać taki tor) + ++n; // to liczymy człony jako jeden + p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać + // GBH p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował + BrakeLevelSet(gbh_RP); + if (n) + { // jeśli jeszcze nie koniec + p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy + if (!p) + iVehicleCount = -2, + n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone + } + } while (n--); + if( ( p == nullptr ) + || ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) { + // no target, or already just virtual coupling + WriteLog( mvOccupied->Name + " didn't find anything to disconnect." ); + iVehicleCount = -2; // odczepiono, co było do odczepienia + } else if ( p->Dettach(d) == coupling::faux ) { + // tylko jeśli odepnie + WriteLog( mvOccupied->Name + " odczepiony." ); + iVehicleCount = -2; + } // a jak nie, to dociskać dalej } if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress)) { // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 6902be65..9092074c 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -766,6 +766,7 @@ private: // ld inputs bool lock_enabled { true }; bool step_enabled { true }; + bool remote_only { false }; // door ignores local control signals // internal data int permit_preset { -1 }; // curent position of preset selection switch // vehicle parts @@ -1162,6 +1163,7 @@ public: bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere) bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure start_t CompressorStart{ start_t::manual }; // whether the compressor is started manually, or another way + start_t PantographCompressorStart{ start_t::manual }; // TODO converter parameters, for when we start cleaning up mover parameters start_t ConverterStart{ start_t::manual }; // whether converter is started manually, or by other means float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met @@ -1344,8 +1346,6 @@ public: bool PantRearUp = false; bool PantFrontSP = true; //dzwiek patykow 'Winger 010304 bool PantRearSP = true; - int PantFrontStart = 0; //stan patykow 'Winger 160204 - int PantRearStart = 0; double PantFrontVolt = 0.0; //pantograf pod napieciem? 'Winger 160404 double PantRearVolt = 0.0; // TODO: move these switch types where they belong, cabin definition @@ -1553,6 +1553,7 @@ public: bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist ); bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist ); bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist ); + bool ChangeDoorControlMode( bool const State, range_t const Notify = range_t::consist ); bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist ); bool LockDoors( bool const State, range_t const Notify = range_t::consist ); bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 74783d83..67c43ee4 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -653,11 +653,18 @@ void TMoverParameters::UpdatePantVolume(double dt) { // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak // check the pantograph compressor while at it - if( PantCompFlag ) { - if( ( false == Battery ) - && ( false == ConverterFlag ) ) { - PantCompFlag = false; - } + if( ( PantPress < 4.2 ) + && ( ( PantographCompressorStart == start_t::automatic ) + || ( PantographCompressorStart == start_t::manualwithautofallback ) ) + && ( ( true == PantRearUp ) + || ( true == PantFrontUp ) ) ) { + // automatic start if the pressure is too low + PantCompFlag = true; + } + if( ( true == PantCompFlag ) + && ( false == Battery ) + && ( false == ConverterFlag ) ) { + PantCompFlag = false; } if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący @@ -5916,7 +5923,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify ) if( PantFrontUp != State ) { PantFrontUp = State; if( State == true ) { - PantFrontStart = 0; if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( @@ -5927,7 +5933,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify ) } } else { - PantFrontStart = 1; if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( @@ -5969,7 +5974,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify ) if( PantRearUp != State ) { PantRearUp = State; if( State == true ) { - PantRearStart = 0; if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( @@ -5980,7 +5984,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify ) } } else { - PantRearStart = 1; if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( @@ -6913,12 +6916,7 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c bool const initialstate { Doors.instances[Door].open_permit }; - if( ( false == Doors.permit_presets.empty() ) // HACK: for cases where preset switch is used before battery - || ( ( true == Battery ) - && ( false == Doors.is_locked ) ) ) { - - Doors.instances[ Door ].open_permit = State; - } + Doors.instances[ Door ].open_permit = State; if( Notify != range_t::local ) { @@ -6937,6 +6935,34 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c return ( Doors.instances[ Door ].open_permit != initialstate ); } +bool TMoverParameters::ChangeDoorControlMode( bool const State, range_t const Notify ) { + + auto const initialstate { Doors.remote_only }; + + Doors.remote_only = State; + if( Notify != range_t::local ) { + // wysłanie wyłączenia do pozostałych? + SendCtrlToNext( + "DoorMode", + ( State == true ? + 1 : + 0 ), + CabNo, + ( Notify == range_t::unit ? + coupling::control | coupling::permanent : + coupling::control ) ); + } + + if( true == State ) { + // when door are put in remote control mode they're automatically open + // TBD, TODO: make it dependant on config switch? + OperateDoors( side::left, true ); + OperateDoors( side::right, true ); + } + + return ( Doors.step_enabled != initialstate ); +} + bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) { auto &door { Doors.instances[ Door ] }; @@ -7044,15 +7070,17 @@ TMoverParameters::update_doors( double const Deltatime ) { // NBMX Obsluga drzwi, MC: zuniwersalnione auto const localopencontrol { - ( Doors.open_control == control_t::passenger ) - || ( Doors.open_control == control_t::mixed ) }; + ( false == Doors.remote_only ) + && ( ( Doors.open_control == control_t::passenger ) + || ( Doors.open_control == control_t::mixed ) ) }; auto const remoteopencontrol { ( Doors.open_control == control_t::driver ) || ( Doors.open_control == control_t::conductor ) || ( Doors.open_control == control_t::mixed ) }; auto const localclosecontrol { - ( Doors.close_control == control_t::passenger ) - || ( Doors.close_control == control_t::mixed ) }; + ( false == Doors.remote_only ) + && ( ( Doors.close_control == control_t::passenger ) + || ( Doors.close_control == control_t::mixed ) ) }; auto const remoteclosecontrol { ( Doors.close_control == control_t::driver ) || ( Doors.close_control == control_t::conductor ) @@ -7080,7 +7108,7 @@ TMoverParameters::update_doors( double const Deltatime ) { && ( door.step_position <= 0.f ); door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); - door.remote_open = door.remote_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); + door.remote_open = ( door.remote_open || Doors.remote_only ) && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); door.local_close = door.local_close && ( false == door.is_closed ); door.remote_close = door.remote_close && ( false == door.is_closed ); @@ -8732,6 +8760,14 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { lookup->second : start_t::manual; } + // pantograph compressor + { + auto lookup = starts.find( extract_value( "PantCompressorStart", line ) ); + PantographCompressorStart = + lookup != starts.end() ? + lookup->second : + start_t::manual; + } // fuel pump { auto lookup = starts.find( extract_value( "FuelStart", line ) ); @@ -10046,6 +10082,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C false ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } + else if( Command == "DoorMode" ) { + Doors.remote_only = ( + CValue1 == 1 ? + true : + false ); + OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + } else if( Command == "DepartureSignal" ) { DepartureSignal = ( CValue1 == 1 ? @@ -10062,12 +10105,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C if ((CValue1 == 1)) { PantFrontUp = true; - PantFrontStart = 0; } else if ((CValue1 == 0)) { PantFrontUp = false; - PantFrontStart = 1; } } else @@ -10077,24 +10118,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) { PantFrontUp = true; - PantFrontStart = 0; } else { PantRearUp = true; - PantRearStart = 0; } else if ((CValue1 == 0)) if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) { PantFrontUp = false; - PantFrontStart = 1; } else { PantRearUp = false; - PantRearStart = 1; } } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); @@ -10107,12 +10144,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C if ((CValue1 == 1)) { PantRearUp = true; - PantRearStart = 0; } else if ((CValue1 == 0)) { PantRearUp = false; - PantRearStart = 1; } } else @@ -10123,24 +10158,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) { PantRearUp = true; - PantRearStart = 0; } else { PantFrontUp = true; - PantFrontStart = 0; } else if ((CValue1 == 0)) if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) { PantRearUp = false; - PantRearStart = 1; } else { PantFrontUp = false; - PantFrontStart = 1; } } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); diff --git a/Train.cpp b/Train.cpp index 53aef0c1..a52d36b9 100644 --- a/Train.cpp +++ b/Train.cpp @@ -327,6 +327,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::dooropenall, &TTrain::OnCommand_dooropenall }, { user_command::doorcloseall, &TTrain::OnCommand_doorcloseall }, { user_command::doorsteptoggle, &TTrain::OnCommand_doorsteptoggle }, + { user_command::doormodetoggle, &TTrain::OnCommand_doormodetoggle }, { user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease }, { user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect }, { user_command::departureannounce, &TTrain::OnCommand_departureannounce }, @@ -778,7 +779,7 @@ void TTrain::OnCommand_mastercontrollerincrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { // on press or hold if( ( Train->ggJointCtrl.SubModel != nullptr ) - && ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { + && ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) { OnCommand_independentbrakedecrease( Train, Command ); } else { @@ -798,7 +799,7 @@ void TTrain::OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { // on press or hold if( ( Train->ggJointCtrl.SubModel != nullptr ) - && ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { + && ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) { OnCommand_independentbrakedecreasefast( Train, Command ); } else { @@ -1722,10 +1723,11 @@ void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Co } } +// TODO: replace battery with a two-state device, update switch code accordingly void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) { - if( Command.action == GLFW_PRESS ) { - // only reacting to press, so the switch doesn't flip back and forth if key is held down + if( Command.action != GLFW_REPEAT ) { + // keep the switch from flipping back and forth if key is held down if( false == Train->mvOccupied->Battery ) { // turn on OnCommand_batteryenable( Train, Command ); @@ -1739,16 +1741,13 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) { - if( true == Train->mvOccupied->Battery ) { return; } // already on - if( Command.action == GLFW_PRESS ) { - // ignore repeats - // wyłącznik jest też w SN61, ewentualnie załączać prąd na stałe z poziomu FIZ + // visual feedback + Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch ); + + if( true == Train->mvOccupied->Battery ) { return; } // already on + if( Train->mvOccupied->BatterySwitch( true ) ) { - // bateria potrzebna np. do zapalenia świateł - if( Train->ggBatteryButton.SubModel ) { - Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch ); - } // side-effects if( Train->mvOccupied->LightsPosNo > 0 ) { Train->SetLights(); @@ -1760,19 +1759,23 @@ void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command } } } + else if( Command.action == GLFW_RELEASE ) { + if( Train->ggBatteryButton.type() == TGaugeType::push ) { + // return the switch to neutral position + Train->ggBatteryButton.UpdateValue( 0.5f ); + } + } } void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) { - - if( false == Train->mvOccupied->Battery ) { return; } // already off - + // TBD, TODO: ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora if( Command.action == GLFW_PRESS ) { - // ignore repeats + // visual feedback + Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch ); + + if( false == Train->mvOccupied->Battery ) { return; } // already off + if( Train->mvOccupied->BatterySwitch( false ) ) { - // ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora - if( Train->ggBatteryButton.SubModel ) { - Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch ); - } // side-effects if( false == Train->mvControlled->ConverterFlag ) { // if there's no (low voltage) power source left, drop pantographs @@ -1781,6 +1784,12 @@ void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Comman } } } + else if( Command.action == GLFW_RELEASE ) { + if( Train->ggBatteryButton.type() == TGaugeType::push ) { + // return the switch to neutral position + Train->ggBatteryButton.UpdateValue( 0.5f ); + } + } } void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &Command ) { @@ -4725,6 +4734,13 @@ void TTrain::OnCommand_doorsteptoggle( TTrain *Train, command_data const &Comman } } +void TTrain::OnCommand_doormodetoggle( TTrain *Train, command_data const &Command ) { + + if( Command.action == GLFW_PRESS ) { + Train->mvOccupied->ChangeDoorControlMode( false == Train->mvOccupied->Doors.remote_only ); + } +} + void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) { if( ( true == FreeFlyModeFlag ) @@ -7456,9 +7472,10 @@ void TTrain::clear_cab_controls() void TTrain::set_cab_controls( int const Cab ) { // switches // battery - if( true == mvOccupied->Battery ) { - ggBatteryButton.PutValue( 1.f ); - } + ggBatteryButton.PutValue( + ( ggBatteryButton.type() == TGaugeType::push ? 0.5f : + mvOccupied->Battery ? 1.f : + 0.f ) ); // motor connectors ggStLinOffButton.PutValue( ( mvControlled->StLinSwitchOff ? @@ -8026,6 +8043,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con } // TODO: move viable dedicated gauges to the automatic array std::unordered_map const autoboolgauges = { + { "doormode_sw:", &mvOccupied->Doors.remote_only }, { "doorstep_sw:", &mvOccupied->Doors.step_enabled }, { "coolingfans_sw:", &mvControlled->RVentForceOn } }; diff --git a/Train.h b/Train.h index 208cea21..11f9098a 100644 --- a/Train.h +++ b/Train.h @@ -329,6 +329,7 @@ class TTrain static void OnCommand_dooropenall( TTrain *Train, command_data const &Command ); static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command ); static void OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command ); + static void OnCommand_doormodetoggle( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command ); static void OnCommand_departureannounce( TTrain *Train, command_data const &Command ); diff --git a/command.cpp b/command.cpp index 25eeac6c..ea77daed 100644 --- a/command.cpp +++ b/command.cpp @@ -154,6 +154,7 @@ commanddescription_sequence Commands_descriptions = { { "doorcloseright", command_target::vehicle }, { "doorcloseall", command_target::vehicle }, { "doorsteptoggle", command_target::vehicle }, + { "doormodetoggle", command_target::vehicle }, { "departureannounce", command_target::vehicle }, { "doorlocktoggle", command_target::vehicle }, { "pantographcompressorvalvetoggle", command_target::vehicle }, diff --git a/command.h b/command.h index 9e321ffe..76f87aea 100644 --- a/command.h +++ b/command.h @@ -147,6 +147,7 @@ enum class user_command { doorcloseright, doorcloseall, doorsteptoggle, + doormodetoggle, departureannounce, doorlocktoggle, pantographcompressorvalvetoggle, diff --git a/driverkeyboardinput.cpp b/driverkeyboardinput.cpp index 1b530384..3d8d3a08 100644 --- a/driverkeyboardinput.cpp +++ b/driverkeyboardinput.cpp @@ -156,6 +156,7 @@ driverkeyboard_input::default_bindings() { // doorcloseright, { user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control }, // doorsteptoggle, + { user_command::doormodetoggle, GLFW_KEY_SLASH | keymodifier::shift | keymodifier::control }, { user_command::departureannounce, GLFW_KEY_SLASH }, { user_command::doorlocktoggle, GLFW_KEY_S | keymodifier::control }, { user_command::pantographcompressorvalvetoggle, GLFW_KEY_V | keymodifier::control }, diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index e74cc17c..4d5b3130 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -633,6 +633,9 @@ drivermouse_input::default_bindings() { { "doorstep_sw:", { user_command::doorsteptoggle, user_command::none } }, + { "doormode_sw:", { + user_command::doormodetoggle, + user_command::none } }, { "departure_signal_bt:", { user_command::departureannounce, user_command::none } }, diff --git a/translation.cpp b/translation.cpp index cd7d56bc..fe0df205 100644 --- a/translation.cpp +++ b/translation.cpp @@ -131,6 +131,7 @@ init() { "all doors (open)", "all doors (close)", "doorstep", + "door control mode", "departure signal", "upper headlight", "left headlight", @@ -296,6 +297,7 @@ init() { "drzwi (otworz)", "drzwi (zamknij)", "stopien drzwi", + "tryb sterowania drzwiami", "sygnal odjazdu", "reflektor gorny", "reflektor lewy", @@ -414,6 +416,7 @@ init() { "doorallon_sw:", "dooralloff_sw:", "doorstep_sw:", + "doormode_sw:", "departure_signal_bt:", "upperlight_sw:", "leftlight_sw:", diff --git a/translation.h b/translation.h index 18edda94..71bec11c 100644 --- a/translation.h +++ b/translation.h @@ -120,6 +120,7 @@ enum string { cab_doorallon_sw, cab_dooralloff_sw, cab_doorstep_sw, + cab_doormode_sw, cab_departure_signal_bt, cab_upperlight_sw, cab_leftlight_sw, diff --git a/version.h b/version.h index 7bcb12d5..5ee96a7f 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 430 +#define VERSION_MINOR 504 #define VERSION_REVISION 0 From 9185030b4be2243d38971c535a7e810b04d214f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 7 May 2019 22:33:15 +0200 Subject: [PATCH 02/12] Autoreturn for MHZ_K8P --- Train.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Train.cpp b/Train.cpp index a52d36b9..e78c333d 100644 --- a/Train.cpp +++ b/Train.cpp @@ -646,7 +646,8 @@ void TTrain::zero_charging_train_brake() { && ( DynamicObject->Controller != AIdriver ) && ( Global.iFeedbackMode < 3 ) && ( ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) - || ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57 ) ) ) { + || (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57) + || (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P)) ) { // Odskakiwanie hamulce EP set_train_brake( 0 ); } From 2db964ea402b806f5d84916ca3b1a2f26a56b425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Wed, 8 May 2019 21:44:19 +0200 Subject: [PATCH 03/12] Additionl 0 position for EIM EMUs, configurable Elf controller, first try of speedcontrol for EN57A --- Driver.cpp | 24 ++++++++--------- McZapkie/MOVER.h | 2 ++ McZapkie/Mover.cpp | 65 ++++++++++++++++++++++++++++++++++------------ 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 15275845..f4561e68 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2844,20 +2844,20 @@ bool TController::IncBrake() bool TController::IncBrakeEIM() { // zwiększenie hamowania bool OK = false; - switch (mvControlling->EIMCtrlType) + switch (mvOccupied->EIMCtrlType) { case 0: - OK = mvControlling->IncLocalBrakeLevel(1); + OK = mvOccupied->IncLocalBrakeLevel(1); break; case 1: - OK = mvControlling->MainCtrlPos > 0; + OK = mvOccupied->MainCtrlPos > 0; if (OK) - mvControlling->MainCtrlPos = 0; + mvOccupied->MainCtrlPos = 0; break; case 2: - OK = mvControlling->MainCtrlPos > 1; + OK = mvOccupied->MainCtrlPos > 1; if (OK) - mvControlling->MainCtrlPos = 1; + mvOccupied->MainCtrlPos = 1; break; } return OK; @@ -2936,20 +2936,20 @@ bool TController::DecBrake() bool TController::DecBrakeEIM() { // zmniejszenie siły hamowania bool OK = false; - switch (mvControlling->EIMCtrlType) + switch (mvOccupied->EIMCtrlType) { case 0: - OK = mvControlling->DecLocalBrakeLevel(1); + OK = mvOccupied->DecLocalBrakeLevel(1); break; case 1: - OK = mvControlling->MainCtrlPos < 2; + OK = mvOccupied->MainCtrlPos < 2; if (OK) - mvControlling->MainCtrlPos = 2; + mvOccupied->MainCtrlPos = 2; break; case 2: - OK = mvControlling->MainCtrlPos < 3; + OK = mvOccupied->MainCtrlPos < 3; if (OK) - mvControlling->MainCtrlPos = 3; + mvOccupied->MainCtrlPos = 3; break; } return OK; diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 9092074c..a286f238 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -1312,6 +1312,8 @@ public: double eim_localbrake = 0; /*nastawa hamowania dodatkowego pneumatycznego lokomotywy*/ int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/ bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/ + int SpeedCtrlAutoTurnOffFlag = 0; /*czy tempomat sam się wyłącza*/ + bool EIMCtrlAdditionalZeros = false; /*czy ma dodatkowe zero jazdy i zero hamowania */ double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/ double eimv[21]; static std::vector const eimv_labels; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 67c43ee4..93f048f6 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2001,6 +2001,10 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) ScndCtrlActualPos = Round(Vel); else ScndCtrlActualPos = Round(Vel * 0.5); + if ((EIMCtrlType == 0)&&(SpeedCtrlAutoTurnOffFlag == 1)) + { + MainCtrlActualPos = MainCtrlPos; + } SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo); } @@ -6018,6 +6022,13 @@ void TMoverParameters::CheckEIMIC(double dt) { case 0: eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : (double)MainCtrlPos / (double)MainCtrlPosNo); + if (EIMCtrlAdditionalZeros) + { + if (eimic > 0.001) + eimic = std::max(0.002, eimic * (double)MainCtrlPosNo / ((double)MainCtrlPosNo - 1.0) - 1.0 / ((double)MainCtrlPosNo - 1.0)); + if (eimic < -0.001) + eimic = std::min(-0.002, eimic * (double)LocalBrakePosNo / ((double)LocalBrakePosNo - 1.0) + 1.0 / ((double)LocalBrakePosNo - 1.0)); + } break; case 1: switch (MainCtrlPos) @@ -6068,23 +6079,34 @@ void TMoverParameters::CheckEIMIC(double dt) } break; case 2: - switch (MainCtrlPos) + if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay)) { - case 0: - case 1: - eimic -= clamp(1.0 + eimic, 0.0, dt*0.15); //odejmuj do -1 - if (eimic > 0) eimic = 0; - break; - case 2: - eimic -= clamp(0.0 + eimic, 0.0, dt*0.15); //odejmuj do 0 - break; - case 3: - eimic += clamp(0.0 - eimic, 0.0, dt*0.15); //dodawaj do 0 - break; - case 4: - eimic += clamp(1.0 - eimic, 0.0, dt*0.15); //dodawaj do 1 - if (eimic < 0) eimic = 0; - break; + double delta = (MainCtrlActualPos == MainCtrlPos ? dt*CtrlDelay : 0.01); + switch (MainCtrlPos) + { + case 0: + case 1: + eimic -= clamp(1.0 + eimic, 0.0, delta); //odejmuj do -1 + if (eimic > 0) eimic = 0; + break; + case 2: + eimic -= clamp(0.0 + eimic, 0.0, delta); //odejmuj do 0 + break; + case 3: + eimic += clamp(0.0 - eimic, 0.0, delta); //dodawaj do 0 + break; + case 4: + eimic += clamp(1.0 - eimic, 0.0, delta); //dodawaj do 1 + if (eimic < 0) eimic = 0; + break; + } + } + if (MainCtrlActualPos == MainCtrlPos) + LastRelayTime += dt; + else + { + LastRelayTime = 0; + MainCtrlActualPos = MainCtrlPos; } break; case 3: @@ -6108,6 +6130,15 @@ void TMoverParameters::CheckSpeedCtrl() eimicSpeedCtrl = clamp(0.5 * (ScndCtrlActualPos * 2 - Vel), -1.0, 1.0); else eimicSpeedCtrl = 1; + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) + { + DecScndCtrl(1); + if (CabNo == 0) + { + SendCtrlToNext("ScndCtrl", ScndCtrlPos, 1); + SendCtrlToNext("ScndCtrl", ScndCtrlPos, -1); + } + } } // ************************************************************************************************* @@ -8708,6 +8739,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { extract_value( EIMCtrlType, "EIMCtrlType", line, "" ); clamp( EIMCtrlType, 0, 3 ); LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes"); + EIMCtrlAdditionalZeros = (extract_value("EIMCtrlAddZeros", line) == "Yes"); extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR @@ -8730,6 +8762,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { (extract_value("SpeedCtrlType", line) == "Time") ? true : false; + extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", line, ""); // converter { From bbdc67c9b298a62413d9178cb64d2f38fd3a1908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Thu, 9 May 2019 19:39:23 +0200 Subject: [PATCH 04/12] Fixed speedcontrol for EN57A --- McZapkie/Mover.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 93f048f6..fb83ef35 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1691,7 +1691,9 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) else { ++MainCtrlPos; OK = true; - } + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) + DecScndCtrl(2); + } break; } @@ -1853,6 +1855,8 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) { MainCtrlPos--; OK = true; + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) + DecScndCtrl(2); } else if (CtrlSpeed > 1) OK = (DecMainCtrl(1) && DecMainCtrl(2)); // CtrlSpeed-1); @@ -1994,7 +1998,7 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) if (LastRelayTime > CtrlDelay) LastRelayTime = 0; - if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1)) + if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1) && (MainCtrlPos>0)) { // NOTE: round() already adds 0.5, are the ones added here as well correct? if ((Vmax < 250)) @@ -6130,15 +6134,6 @@ void TMoverParameters::CheckSpeedCtrl() eimicSpeedCtrl = clamp(0.5 * (ScndCtrlActualPos * 2 - Vel), -1.0, 1.0); else eimicSpeedCtrl = 1; - if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) - { - DecScndCtrl(1); - if (CabNo == 0) - { - SendCtrlToNext("ScndCtrl", ScndCtrlPos, 1); - SendCtrlToNext("ScndCtrl", ScndCtrlPos, -1); - } - } } // ************************************************************************************************* From bddb0575bf5376e64cc9fab9140210c31c5fc400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 11 May 2019 13:46:07 +0200 Subject: [PATCH 05/12] Changed turbo modulation, AI can drive DMUs with constant speed --- Driver.cpp | 16 ++++++++++++++++ DynObj.cpp | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Driver.cpp b/Driver.cpp index f4561e68..fdc7b3c2 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3510,6 +3510,22 @@ void TController::SetTimeControllers() mvOccupied->ScndCtrlPos = 1; } } + //5. Check Main Controller in Dizels + if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->hydro_TC)) + { + int MaxPos = mvControlling->MainCtrlPosNo; + int MinPos = MaxPos; + for (int i = MaxPos; (i > 1) && (mvControlling->RList[i].Mn > 0); i--) MinPos = i; + if ((MaxPos > MinPos)&&(mvControlling->MainCtrlPos>0)&&(AccDesired>0)) + { + double Factor = 5 * (mvControlling->Vmax) / (mvControlling->Vmax + mvControlling->Vel); + int DesiredPos = MinPos + (MaxPos - MinPos)*(VelDesired > mvControlling->Vel ? (VelDesired - mvControlling->Vel) / Factor : 0); + if (DesiredPos > MaxPos) DesiredPos = MaxPos; + if (DesiredPos < MinPos) DesiredPos = MinPos; + while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1); + while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1); + } + } }; void TController::CheckTimeControllers() diff --git a/DynObj.cpp b/DynObj.cpp index 4f39db3a..6008549d 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -6624,7 +6624,8 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub // youBy - przenioslem, bo diesel tez moze miec turbo if( Vehicle.TurboTest > 0 ) { // udawanie turbo: - auto const goalpitch { std::max( 0.025, ( engine_volume + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; + auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax : 0 }; + auto const goalpitch { std::max( 0.025, ( engine_volume + pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; auto const goalvolume { ( ( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ? std::max( 0.0, ( engine_turbo_pitch + engine_turbo.m_amplitudeoffset ) * engine_turbo.m_amplitudefactor ) : From 0b79e7d1b9f7b0bd8b56451e63a85af18742cc48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 12 May 2019 13:35:20 +0200 Subject: [PATCH 06/12] Small fix for AI driving DieselEngine - better cruising in SN61 too --- Driver.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index fdc7b3c2..82af9898 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3511,7 +3511,7 @@ void TController::SetTimeControllers() } } //5. Check Main Controller in Dizels - if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->hydro_TC)) + if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->Vmax>30)) { int MaxPos = mvControlling->MainCtrlPosNo; int MinPos = MaxPos; @@ -3522,8 +3522,12 @@ void TController::SetTimeControllers() int DesiredPos = MinPos + (MaxPos - MinPos)*(VelDesired > mvControlling->Vel ? (VelDesired - mvControlling->Vel) / Factor : 0); if (DesiredPos > MaxPos) DesiredPos = MaxPos; if (DesiredPos < MinPos) DesiredPos = MinPos; - while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1); - while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1); + if (!mvControlling->SlippingWheels) + { + while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1); + if (mvControlling->Vel>mvControlling->dizel_minVelfullengage) + while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1); + } } } }; From 448472c84ac12d5cfcf98f2e695bc529de1929dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 12 May 2019 19:04:30 +0200 Subject: [PATCH 07/12] Another change in turbocharger sound, added rpm in engine ui panel. --- DynObj.cpp | 2 +- driveruipanels.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index 6008549d..e8ad81bd 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -6625,7 +6625,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub if( Vehicle.TurboTest > 0 ) { // udawanie turbo: auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax : 0 }; - auto const goalpitch { std::max( 0.025, ( engine_volume + pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; + auto const goalpitch { std::max( 0.025, ( engine_volume * pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; auto const goalvolume { ( ( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ? std::max( 0.0, ( engine_turbo_pitch + engine_turbo.m_amplitudeoffset ) * engine_turbo.m_amplitudefactor ) : diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 8efa947d..b278f53f 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -717,7 +717,8 @@ debug_panel::update_section_engine( std::vector &Output ) { std::string parameterstext = "param value"; std::vector< std::pair > const paramvalues { - { "efill: ", mover.dizel_fill }, + { " rpm: ", mover.enrot * 60.0 }, + { "efill: ", mover.dizel_fill }, { "etorq: ", mover.dizel_Torque }, { "creal: ", mover.dizel_engage }, { "cdesi: ", mover.dizel_engagestate }, From 1626224dc804f576d1300f15ef30211983653f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 12 May 2019 23:38:40 +0200 Subject: [PATCH 08/12] departure/arrival time in timetable can be a fraction of minute --- Driver.cpp | 2 +- driveruipanels.cpp | 2 +- mtable.cpp | 24 ++++++++++++------------ mtable.h | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 82af9898..52a62e7b 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1024,7 +1024,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN if (TrainParams->StationIndex < TrainParams->StationCount) { // jeśli są dalsze stacje, czekamy do godziny odjazdu - if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute)) { + if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute + simulation::Time.data().wSecond*0.0167 )) { // z dalszą akcją czekamy do godziny odjazdu IsAtPassengerStop = false; // przy jakim dystansie (stanie licznika) ma przesunąć na następny postój diff --git a/driveruipanels.cpp b/driveruipanels.cpp index b278f53f..03d44f38 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -353,7 +353,7 @@ timetable_panel::update() { ( owner->iStationStart < table->StationIndex ) && ( i < table->StationIndex ) && ( ( tableline->Ah < 0 ) // pass-through, always valid - || ( time.wHour * 60 + time.wMinute >= tableline->Dh * 60 + tableline->Dm ) ) ); + || ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ); auto traveltime = " " + ( i < 2 ? "" : diff --git a/mtable.cpp b/mtable.cpp index 6aed55d0..3d207cdb 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -52,7 +52,7 @@ bool TTrainParameters::IsStop() const bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) { - return UpdateMTable( Time.data().wHour, Time.data().wMinute, NewName ); + return UpdateMTable( Time.data().wHour, Time.data().wMinute + Time.data().wSecond * 0.0167, NewName ); } bool TTrainParameters::UpdateMTable(double hh, double mm, std::string const &NewName) @@ -358,12 +358,12 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) if (s.find(hrsd) != std::string::npos) { record->Ah = atoi( s.substr(0, s.find(hrsd)).c_str()); // godzina przyjazdu - record->Am = atoi(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta przyjazdu + record->Am = atof(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta przyjazdu } else { record->Ah = TimeTable[StationCount - 1].Ah; // godzina z poprzedniej pozycji - record->Am = atoi(s.c_str()); // bo tylko minuty podane + record->Am = atof(s.c_str()); // bo tylko minuty podane } } do @@ -408,12 +408,12 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) if (s.find(hrsd) != std::string::npos) { record->Dh = atoi(s.substr(0, s.find(hrsd)).c_str()); // godzina odjazdu - record->Dm = atoi(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta odjazdu + record->Dm = atof(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta odjazdu } else { record->Dh = TimeTable[StationCount - 1].Dh; // godzina z poprzedniej pozycji - record->Dm = atoi(s.c_str()); // bo tylko minuty podane + record->Dm = atof(s.c_str()); // bo tylko minuty podane } } else @@ -475,20 +475,20 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) if( timeoffset != 0 ) // jeżeli jest przesunięcie rozkładu { long i_end = StationCount + 1; - int adjustedtime; // do zwiększania czasu + float adjustedtime; // do zwiększania czasu for (auto i = 1; i < i_end; ++i) // bez with, bo ciężko się przenosi na C++ { if ((TimeTable[i].Ah >= 0)) { - adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty - TimeTable[i].Am = adjustedtime % 60; - TimeTable[i].Ah = (adjustedtime / 60) % 24; + adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24.0 * 60.0 ); // nowe minuty + TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.0; + TimeTable[i].Ah = int((adjustedtime) / 60) % 24; } if ((TimeTable[i].Dh >= 0)) { - adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty - TimeTable[i].Dm = adjustedtime % 60; - TimeTable[i].Dh = (adjustedtime / 60) % 24; + adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24.0 * 60.0 ); // nowe minuty + TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.0; + TimeTable[i].Dh = int((adjustedtime) / 60) % 24; } } } diff --git a/mtable.h b/mtable.h index 78816aaa..17191ff1 100644 --- a/mtable.h +++ b/mtable.h @@ -32,9 +32,9 @@ struct TMTableLine std::string StationWare; // typ i wyposazenie stacji, oddz. przecinkami} int TrackNo; // ilosc torow szlakowych int Ah; - int Am; // godz. i min. przyjazdu, -1 gdy bez postoju + double Am; // godz. i min. przyjazdu, -1 gdy bez postoju int Dh; - int Dm; // godz. i min. odjazdu + double Dm; // godz. i min. odjazdu double tm; // czas jazdy do tej stacji w min. (z kolumny) TMTableLine() { From 9cdce2d346e13f218b8badbdb7abdd3ece47e1df Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 14 May 2019 20:15:01 +0200 Subject: [PATCH 09/12] build 190514. partial usage of utf8 in the ui, timetable panel appeaance improvements --- Driver.cpp | 9 ++- driveruipanels.cpp | 134 ++++++++++++++++++++++++---------- driveruipanels.h | 4 +- mtable.cpp | 8 +- mtable.h | 10 +-- simulationstateserializer.cpp | 2 +- uilayer.cpp | 9 ++- utilities.cpp | 20 ++++- utilities.h | 1 + version.h | 2 +- 10 files changed, 144 insertions(+), 55 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 52a62e7b..5fc4ee24 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -6595,17 +6595,18 @@ std::string TController::NextStop() const // dodać godzinę odjazdu if (!TrainParams) return ""; // tu nie powinno nigdy wejść - std::string nextstop = asNextStop; + std::string nextstop = Bezogonkow( asNextStop, true ); TMTableLine *t = TrainParams->TimeTable + TrainParams->StationIndex; if( t->Ah >= 0 ) { // przyjazd - nextstop += " przyj." + std::to_string( t->Ah ) + ":" - + ( t->Am < 10 ? "0" : "" ) + std::to_string( t->Am ); + nextstop += " przyj." + std::to_string( t->Ah ) + ":" + + to_minutes_str( t->Am, true, 3 ); + } if( t->Dh >= 0 ) { // jeśli jest godzina odjazdu nextstop += " odj." + std::to_string( t->Dh ) + ":" - + ( t->Dm < 10 ? "0" : "" ) + std::to_string( t->Dm ); + + to_minutes_str( t->Dm, true, 3 ); } return nextstop; }; diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 03d44f38..6a482e81 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -229,6 +229,7 @@ timetable_panel::update() { if( false == is_open ) { return; } text_lines.clear(); + m_tablelines.clear(); auto const *train { simulation::Train }; auto const *controlled { ( train ? train->Dynamic() : nullptr ) }; @@ -239,7 +240,7 @@ timetable_panel::update() { std::snprintf( m_buffer.data(), m_buffer.size(), locale::strings[ locale::string::driver_timetable_header ].c_str(), - 40, 40, + 37, 37, locale::strings[ locale::string::driver_timetable_name ].c_str(), time.wHour, time.wMinute, @@ -274,7 +275,7 @@ timetable_panel::update() { } { // next station - auto const nextstation = Bezogonkow( owner->NextStop(), true ); + auto const nextstation = owner->NextStop(); if( false == nextstation.empty() ) { // jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania auto textline = " -> " + nextstation; @@ -317,67 +318,126 @@ timetable_panel::update() { } else { + auto const loadingcolor { glm::vec4( 164.0f / 255.0f, 84.0f / 255.0f, 84.0f / 255.0f, 1.f ) }; + auto const waitcolor { glm::vec4( 164.0f / 255.0f, 132.0f / 255.0f, 84.0f / 255.0f, 1.f ) }; auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) }; // header - text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor ); + m_tablelines.emplace_back( u8"┌─────┬────────────────────────────────────┬─────────┬─────┐", Global.UITextColor ); TMTableLine const *tableline; for( int i = owner->iStationStart; i <= table->StationCount; ++i ) { // wyświetlenie pozycji z rozkładu tableline = table->TimeTable + i; // linijka rozkładu - std::string vmax = - " " - + to_string( tableline->vmax, 0 ); - vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej - std::string const station = ( + bool vmaxchange { true }; + if( i > owner->iStationStart ) { + auto const *previoustableline { tableline - 1 }; + if( tableline->vmax == previoustableline->vmax ) { + vmaxchange = false; + } + } + std::string vmax { " " }; + if( true == vmaxchange ) { + vmax += to_string( tableline->vmax, 0 ); + vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej + } + auto const station { ( Bezogonkow( tableline->StationName, true ) + " " ) - .substr( 0, 34 ); - std::string const location = ( + .substr( 0, 34 ) }; + auto const location { ( ( tableline->km > 0.0 ? to_string( tableline->km, 2 ) : "" ) + " " ) - .substr( 0, 34 - tableline->StationWare.size() ); - std::string const arrival = ( + .substr( 0, 34 - tableline->StationWare.size() ) }; + auto const arrival { ( tableline->Ah >= 0 ? - to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Am ) ).substr( 1, 2 ) : - " | " ); - std::string const departure = ( + to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Am, true, 3 ) : + u8" │ " ) }; + auto const departure { ( tableline->Dh >= 0 ? - to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Dm ) ).substr( 1, 2 ) : - " | " ); - auto const candeparture = ( + to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Dm, true, 3 ) : + u8" │ " ) }; + auto const candeparture { ( ( owner->iStationStart < table->StationIndex ) && ( i < table->StationIndex ) && ( ( tableline->Ah < 0 ) // pass-through, always valid - || ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ); - auto traveltime = - " " - + ( i < 2 ? "" : - tableline->Ah >= 0 ? to_string( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), 0 ) : - to_string( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), 0 ) ); - traveltime = traveltime.substr( traveltime.size() - 3, 3 ); // z wyrównaniem do prawej - - text_lines.emplace_back( - ( "| " + vmax + " | " + station + " | " + arrival + " | " + traveltime + " |" ), - ( candeparture ? - readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono - Global.UITextColor ) ); - text_lines.emplace_back( - ( "| | " + location + tableline->StationWare + " | " + departure + " | |" ), - ( candeparture ? - readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono - Global.UITextColor ) ); + || ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ) }; + auto const loadchangeinprogress { ( ( static_cast( std::ceil( -1.0 * owner->fStopTime ) ) ) > 0 ) }; + auto const isatpassengerstop { ( true == owner->IsAtPassengerStop ) && ( vehicle->MoverParameters->Vel < 1.0 ) }; + auto const traveltime { ( + i < 2 ? " " : + tableline->Ah >= 0 ? to_minutes_str( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), false, 3 ) : + to_minutes_str( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), false, 3 ) ) }; + auto const linecolor { ( + ( i != owner->iStationStart ) ? Global.UITextColor : + loadchangeinprogress ? loadingcolor : + candeparture ? readycolor : // czas minął i odjazd był, to nazwa stacji będzie na zielono + isatpassengerstop ? waitcolor : + Global.UITextColor ) }; + m_tablelines.emplace_back( + ( u8"│ " + vmax + u8" │ " + station + u8" │ " + arrival + u8" │ " + traveltime + u8" │" ), + linecolor ); + m_tablelines.emplace_back( + ( u8"│ │ " + location + tableline->StationWare + u8" │ " + departure + u8" │ │" ), + linecolor ); // divider/footer - text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor ); + if( i < table->StationCount ) { + auto const *nexttableline { tableline + 1 }; + if( tableline->vmax == nexttableline->vmax ) { + m_tablelines.emplace_back( u8"│ ├────────────────────────────────────┼─────────┼─────┤", Global.UITextColor ); + } + else { + m_tablelines.emplace_back( u8"├─────┼────────────────────────────────────┼─────────┼─────┤", Global.UITextColor ); + } + } + else { + m_tablelines.emplace_back( u8"└─────┴────────────────────────────────────┴─────────┴─────┘", Global.UITextColor ); + } } } } // is_expanded } +void +timetable_panel::render() { + + if( false == is_open ) { return; } + if( true == text_lines.empty() ) { return; } + + auto flags = + ImGuiWindowFlags_NoFocusOnAppearing + | ImGuiWindowFlags_NoCollapse + | ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 ); + + if( size.x > 0 ) { + ImGui::SetNextWindowSize( ImVec2( size.x, size.y ) ); + } + if( size_min.x > 0 ) { + ImGui::SetNextWindowSizeConstraints( ImVec2( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) ); + } + auto const panelname { ( + title.empty() ? + name : + title ) + + "###" + name }; + if( true == ImGui::Begin( panelname.c_str(), &is_open, flags ) ) { + for( auto const &line : text_lines ) { + ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() ); + } + if( is_expanded ) { + ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 1, 0 ) ); + for( auto const &line : m_tablelines ) { + ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() ); + } + ImGui::PopStyleVar(); + } + } + ImGui::End(); +} + void debug_panel::update() { diff --git a/driveruipanels.h b/driveruipanels.h index 28363796..7c075562 100644 --- a/driveruipanels.h +++ b/driveruipanels.h @@ -50,12 +50,14 @@ public: : ui_panel( Name, Isopen ) {} void update() override; + void render() override; bool is_expanded{ false }; private: - // members +// members std::array m_buffer; + std::vector m_tablelines; }; class debug_panel : public ui_panel { diff --git a/mtable.cpp b/mtable.cpp index 3d207cdb..957a4f8d 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -480,14 +480,14 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) { if ((TimeTable[i].Ah >= 0)) { - adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24.0 * 60.0 ); // nowe minuty - TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.0; + adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty + TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.f; TimeTable[i].Ah = int((adjustedtime) / 60) % 24; } if ((TimeTable[i].Dh >= 0)) { - adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24.0 * 60.0 ); // nowe minuty - TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.0; + adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty + TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.f; TimeTable[i].Dh = int((adjustedtime) / 60) % 24; } } diff --git a/mtable.h b/mtable.h index 17191ff1..b0bea8bd 100644 --- a/mtable.h +++ b/mtable.h @@ -24,18 +24,18 @@ static char const *hrsd = "."; struct TMTableLine { - double km; // kilometraz linii - double vmax; // predkosc rozkladowa przed przystankiem + float km; // kilometraz linii + float vmax; // predkosc rozkladowa przed przystankiem // StationName:string[32]; //nazwa stacji ('_' zamiast spacji) // StationWare:string[32]; //typ i wyposazenie stacji, oddz. przecinkami} std::string StationName; // nazwa stacji ('_' zamiast spacji) std::string StationWare; // typ i wyposazenie stacji, oddz. przecinkami} int TrackNo; // ilosc torow szlakowych int Ah; - double Am; // godz. i min. przyjazdu, -1 gdy bez postoju + float Am; // godz. i min. przyjazdu, -1 gdy bez postoju int Dh; - double Dm; // godz. i min. odjazdu - double tm; // czas jazdy do tej stacji w min. (z kolumny) + float Dm; // godz. i min. odjazdu + float tm; // czas jazdy do tej stacji w min. (z kolumny) TMTableLine() { km = 0; diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index e28992a0..10f20e2e 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -179,7 +179,7 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch Global.fFogEnd = clamp( Random( std::min( fograngestart, fograngeend ), std::max( fograngestart, fograngeend ) ), - 100.0, 2000.0 ); + 10.0, 2000.0 ); } std::string token { Input.getToken() }; diff --git a/uilayer.cpp b/uilayer.cpp index 6ad6929f..c5aea330 100644 --- a/uilayer.cpp +++ b/uilayer.cpp @@ -74,8 +74,15 @@ ui_layer::init( GLFWwindow *Window ) { IMGUI_CHECKVERSION(); ImGui::CreateContext(); + + static ImWchar const glyphranges[] = { + 0x0020, 0x00FF, // ascii + extension + 0x2070, 0x2079, // superscript + 0x2500, 0x256C, // box drawings + 0, + }; m_imguiio = &ImGui::GetIO(); -// m_imguiio->Fonts->AddFontFromFileTTF( "c:/windows/fonts/lucon.ttf", 13.0f ); + m_imguiio->Fonts->AddFontFromFileTTF( "fonts/dejavusansmono.ttf", 13.0f, nullptr, &glyphranges[ 0 ] ); ImGui_ImplGlfw_InitForOpenGL( m_window, false ); #ifdef EU07_USEIMGUIIMPLOPENGL2 diff --git a/utilities.cpp b/utilities.cpp index 971b034d..4c9953b1 100644 --- a/utilities.cpp +++ b/utilities.cpp @@ -1,4 +1,4 @@ -/* +/* 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 @@ -246,6 +246,24 @@ std::string to_hex_str( int const Value, int const Width ) return converter.str(); }; +char * const fractionlabels[] = { " ", u8"¹", u8"²", u8"³", u8"⁴", u8"⁵", u8"⁶", u8"⁷", u8"⁸", u8"⁹" }; + +std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width ) { + + float minutesintegral; + auto const minutesfractional { std::modf( Minutes, &minutesintegral ) }; + auto const width { Width - 1 }; + auto minutes = ( + std::string( width - 1, ' ' ) + + ( Leadingzero ? + to_string( 100 + minutesintegral ).substr( 1, 2 ) : + to_string( minutesintegral, 0 ) ) ); + return ( + minutes.substr( minutes.size() - width, width ) + + fractionlabels[ static_cast( std::floor( minutesfractional * 10 + 0.1 ) ) ] ); +} + + int stol_def(const std::string &str, const int &DefaultValue) { int result { DefaultValue }; diff --git a/utilities.h b/utilities.h index 400f12df..1c930f7a 100644 --- a/utilities.h +++ b/utilities.h @@ -107,6 +107,7 @@ std::string to_string(double Value); std::string to_string(double Value, int precision); std::string to_string(double Value, int precision, int width); std::string to_hex_str( int const Value, int const width = 4 ); +std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width ); inline std::string to_string(bool Value) { diff --git a/version.h b/version.h index 5ee96a7f..f3ad8c74 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 504 +#define VERSION_MINOR 514 #define VERSION_REVISION 0 From a7393bac953899bb0f1f69426c507fca40a52bde Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 22 May 2019 16:29:00 +0200 Subject: [PATCH 10/12] controlled vehicle lookup enhancement --- DynObj.cpp | 46 ++++++++++++++++++++++++---------------------- Train.cpp | 25 ++++--------------------- 2 files changed, 28 insertions(+), 43 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index e8ad81bd..6f2f3eaf 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -6120,30 +6120,32 @@ TDynamicObject * TDynamicObject::ControlledFind() // problematyczna może być kwestia wybranej kabiny (w silnikowym...) // jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno jeździć dobrze // również hamowanie wykonuje się zaworem w członie, a nie w silnikowym... - TDynamicObject *d = this; // zaczynamy od aktualnego - if( ( d->MoverParameters->TrainType == dt_EZT ) - || ( d->MoverParameters->TrainType == dt_DMU ) ) { - // na razie dotyczy to EZT - if( ( d->NextConnected() != nullptr ) - && ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) { - // gdy jest człon od sprzęgu 1, a sprzęg łączony warsztatowo (powiedzmy) - if( ( d->MoverParameters->Power < 1.0 ) - && ( d->NextConnected()->MoverParameters->Power > 1.0 ) ) { - // my nie mamy mocy, ale ten drugi ma - d = d->NextConnected(); // będziemy sterować tym z mocą - } - } - else if( ( d->PrevConnected() != nullptr ) - && ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) { - // gdy jest człon od sprzęgu 0, a sprzęg łączony warsztatowo (powiedzmy) - if( ( d->MoverParameters->Power < 1.0 ) - && ( d->PrevConnected()->MoverParameters->Power > 1.0 ) ) { - // my nie mamy mocy, ale ten drugi ma - d = d->PrevConnected(); // będziemy sterować tym z mocą - } + if( MoverParameters->Power > 1.0 ) { return this; } + + auto const couplingtype { ( + ( MoverParameters->TrainType == dt_EZT ) + || ( MoverParameters->TrainType == dt_DMU ) ) ? + coupling::permanent : + coupling::control + }; + // try first to look towards the rear + auto *d = this; // zaczynamy od aktualnego + + while( ( d = d->NextC( couplingtype ) ) != nullptr ) { + if( d->MoverParameters->Power > 1.0 ) { + return d; } } - return d; + // if we didn't yet find a suitable vehicle try in the other direction + d = this; // zaczynamy od aktualnego + + while( ( d = d->PrevC( couplingtype ) ) != nullptr ) { + if( d->MoverParameters->Power > 1.0 ) { + return d; + } + } + // if we still don't have a match give up + return this; }; //--------------------------------------------------------------------------- diff --git a/Train.cpp b/Train.cpp index e78c333d..fa4135a5 100644 --- a/Train.cpp +++ b/Train.cpp @@ -7128,28 +7128,11 @@ void TTrain::DynamicSet(TDynamicObject *d) // jeździć dobrze // również hamowanie wykonuje się zaworem w członie, a nie w silnikowym... DynamicObject = d; // jedyne miejsce zmiany - mvOccupied = mvControlled = d ? DynamicObject->MoverParameters : NULL; // albo silnikowy w EZT - if (!DynamicObject) - return; - // TODO: leverage code already present in TDynamicObject::ControlledFind() - if( ( d->MoverParameters->TrainType == dt_EZT ) - || ( d->MoverParameters->TrainType == dt_DMU ) ) { + mvOccupied = mvControlled = ( d ? DynamicObject->MoverParameters : nullptr ); // albo silnikowy w EZT - if( ( d->NextConnected() != nullptr ) - && ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) { - if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 1 ].Connected->Power > 1.0 ) ) { - // my nie mamy mocy, ale ten drugi ma - mvControlled = DynamicObject->NextConnected()->MoverParameters; // będziemy sterować tym z mocą - } - } - else if( ( d->PrevConnected() != nullptr ) - && ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) { - if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 0 ].Connected->Power > 1.0 ) ) { - // my nie mamy mocy, ale ten drugi ma - mvControlled = DynamicObject->PrevConnected()->MoverParameters; // będziemy sterować tym z mocą - } - } - } + if( DynamicObject == nullptr ) { return; } + + mvControlled = DynamicObject->ControlledFind()->MoverParameters; mvSecond = NULL; // gdyby się nic nie znalazło if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo if (mvOccupied->Couplers[1].Connected ? From 06f099dca18ff80542ad9de4e36d854a03510940 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 22 May 2019 20:51:11 +0200 Subject: [PATCH 11/12] build 190522. minor ai logic tweaks, impulse type heating switch support --- Driver.cpp | 19 ++++++++++++------- Driver.h | 6 +++++- Train.cpp | 23 +++++++++++++++++++---- version.h | 2 +- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 5fc4ee24..46369124 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2127,11 +2127,12 @@ bool TController::CheckVehicles(TOrders user) while (p) { // HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi... - if( ( p != pVehicle ) - && ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 ) - && ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) { - // NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly - p->MoverParameters->BatterySwitch( true ); + if( p != pVehicle ) { + if( ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 ) + && ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) { + // NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly + p->MoverParameters->BatterySwitch( true ); + } // enable heating and converter in carriages with can be heated if( p->MoverParameters->HeatingPower > 0 ) { p->MoverParameters->HeatingAllow = true; @@ -2730,8 +2731,12 @@ bool TController::IncBrake() // NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself // TODO: add easier ways to access front/rear coupler taking into account vehicle's direction standalone = - ( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) ) - && ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) ) ); + ( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) + || ( ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) + && ( vehicle->MoverParameters->Couplers[ end::front ].Connected->Power > 1 ) ) ) + && ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) + || ( ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) + && ( vehicle->MoverParameters->Couplers[ end::rear ].Connected->Power > 1 ) ) ) ); vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła) } } diff --git a/Driver.h b/Driver.h index 2b0a8053..96067b79 100644 --- a/Driver.h +++ b/Driver.h @@ -201,6 +201,10 @@ public: inline TMoverParameters const *Controlling() const { return mvControlling; } + inline + TMoverParameters const *Occupied() const { + return mvOccupied; + } void DirectionInitial(); void DirectionChange(); inline @@ -251,6 +255,7 @@ public: bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami + double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller private: bool Psyche = false; int HelperState = 0; //stan pomocnika maszynisty @@ -318,7 +323,6 @@ private: double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca double BrakeChargingCooldown {}; // prevents the ai from trying to charge the train brake too frequently - double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller double LastReactionTime = 0.0; double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations diff --git a/Train.cpp b/Train.cpp index fa4135a5..6166f457 100644 --- a/Train.cpp +++ b/Train.cpp @@ -4140,7 +4140,7 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command } if( Command.action == GLFW_PRESS ) { - // only reacting to press, so the switch doesn't flip back and forth if key is held down + // ignore repeats so the switch doesn't flip back and forth if key is held down if( false == Train->mvControlled->HeatingAllow ) { // turn on OnCommand_heatingenable( Train, Command ); @@ -4150,6 +4150,14 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command OnCommand_heatingdisable( Train, Command ); } } + else if( Command.action == GLFW_RELEASE ) { + + if( Train->ggTrainHeatingButton.type() == TGaugeType::push ) { + // impulse switch + // visual feedback + Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch ); + } + } } void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) { @@ -4168,7 +4176,11 @@ void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Comman Train->mvControlled->HeatingAllow = false; // visual feedback - Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch ); + Train->ggTrainHeatingButton.UpdateValue( + ( Train->ggTrainHeatingButton.type() == TGaugeType::push ? + 1.0 : + 0.0 ), + Train->dsbSwitch ); } } @@ -7637,8 +7649,11 @@ void TTrain::set_cab_controls( int const Cab ) { 1.f : 0.f ); // heating - if( true == mvControlled->Heating ) { - ggTrainHeatingButton.PutValue( 1.f ); + if( ggTrainHeatingButton.type() != TGaugeType::push ) { + ggTrainHeatingButton.PutValue( + mvControlled->Heating ? + 1.f : + 0.f ); } // brake acting time if( ggBrakeProfileCtrl.SubModel != nullptr ) { diff --git a/version.h b/version.h index f3ad8c74..5424911c 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 514 +#define VERSION_MINOR 522 #define VERSION_REVISION 0 From 39596c76ba260a25f6f06e8aa8f5fb67401a8da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Wed, 22 May 2019 19:42:52 +0200 Subject: [PATCH 12/12] Parameters of DieselEngine for Python dictionary --- Train.cpp | 47 +++++++++++++++++++++++++++++++++++------------ Train.h | 1 + 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Train.cpp b/Train.cpp index 6166f457..1870279e 100644 --- a/Train.cpp +++ b/Train.cpp @@ -389,8 +389,11 @@ TTrain::TTrain() { bHeat[ i ] = false; } for( int i = 0; i < 9; ++i ) - for( int j = 0; j < 10; ++j ) - fEIMParams[ i ][ j ] = 0.0; + for (int j = 0; j < 10; ++j) + { + fEIMParams[i][j] = 0.0; + fDieselParams[i][j] = 0.0; + } for( int i = 0; i < 20; ++i ) for( int j = 0; j < 3; ++j ) @@ -493,6 +496,7 @@ dictionary_source *TTrain::GetTrainState() { // induction motor state data char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" }; char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" }; + char const *TXTD[ 10 ] = { "enrot", "nrot", "fill_des", "fill_real", "clutch_des", "clutch_real", "water_temp", "oil_press", "res1", "res2" }; char const *TXTP[ 3 ] = { "bc", "bp", "sp" }; for( int j = 0; j < 10; ++j ) dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] ); @@ -500,6 +504,9 @@ dictionary_source *TTrain::GetTrainState() { for( int j = 0; j < 10; ++j ) dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] ); + for (int j = 0; j < 10; ++j) + dict->insert(("diesel_param_" + std::to_string(i + 1) + "_" + std::string(TXTD[j])), fDieselParams[i + 1][j]); + dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_ms" ), bMains[ i ] ); dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_cv" ), fCntVol[ i ] ); dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pf" ), bPants[ i ][ 0 ] ); @@ -5319,6 +5326,27 @@ bool TTrain::Update( double const Deltatime ) in++; iPowerNo = in; } + if ((in < 8) && (p->MoverParameters->EngineType==TEngineType::DieselEngine)) + { + fDieselParams[1 + in][0] = p->MoverParameters->enrot*60; + fDieselParams[1 + in][1] = p->MoverParameters->nrot; + fDieselParams[1 + in][2] = p->MoverParameters->RList[p->MoverParameters->MainCtrlPos].R; + fDieselParams[1 + in][3] = p->MoverParameters->dizel_fill; + fDieselParams[1 + in][4] = p->MoverParameters->RList[p->MoverParameters->MainCtrlPos].Mn; + fDieselParams[1 + in][5] = p->MoverParameters->dizel_engage; + fDieselParams[1 + in][6] = p->MoverParameters->dizel_heat.Twy; + fDieselParams[1 + in][7] = p->MoverParameters->OilPump.pressure; + //fDieselParams[1 + in][8] = p->MoverParameters-> + //fDieselParams[1 + in][9] = p->MoverParameters-> + bMains[in] = p->MoverParameters->Mains; + fCntVol[in] = p->MoverParameters->BatteryVoltage; + bFuse[in] = p->MoverParameters->FuseFlag; + bBatt[in] = p->MoverParameters->Battery; + bConv[in] = p->MoverParameters->ConverterFlag; + bHeat[in] = p->MoverParameters->Heating; + in++; + iPowerNo = in; + } // p = p->NextC(4); //prev if ((kier ? p->NextC(128) : p->PrevC(128)) != (kier ? p->NextC(4) : p->PrevC(4))) iUnitNo++; @@ -5361,16 +5389,11 @@ bool TTrain::Update( double const Deltatime ) for (int i = in; i < 8; i++) { - fEIMParams[1 + i][0] = 0; - fEIMParams[1 + i][1] = 0; - fEIMParams[1 + i][2] = 0; - fEIMParams[1 + i][3] = 0; - fEIMParams[1 + i][4] = 0; - fEIMParams[1 + i][5] = 0; - fEIMParams[1 + i][6] = 0; - fEIMParams[1 + i][7] = 0; - fEIMParams[1 + i][8] = 0; - fEIMParams[1 + i][9] = 0; + for (int j = 0; j <= 9; j++) + { + fEIMParams[1 + i][j] = 0; + fDieselParams[1 + i][j] = 0; + } } #ifdef _WIN32 if (Global.iFeedbackMode == 4) { diff --git a/Train.h b/Train.h index 11f9098a..27a8c43e 100644 --- a/Train.h +++ b/Train.h @@ -675,6 +675,7 @@ private: float fPress[20][3]; // cisnienia dla wszystkich czlonow static std::vector const fPress_labels; float fEIMParams[9][10]; // parametry dla silnikow asynchronicznych + float fDieselParams[9][10]; // parametry dla silnikow asynchronicznych int RadioChannel() const { return iRadioChannel; }; // plays provided sound from position of the radio void radio_message( sound_source *Message, int const Channel );