diff --git a/Driver.cpp b/Driver.cpp index 35b9917e..d2098ebc 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3170,10 +3170,24 @@ bool TController::IncSpeed() { // dla 2Ls150 można zmienić tryb pracy, jeśli jest w liniowym i nie daje rady (wymaga zerowania kierunku) // mvControlling->ShuntMode=(OrderList[OrderPos]&Shunt)||(fMass>224000.0); } + if ((mvControlling->SpeedCtrl)&&(mvControlling->Mains)) {// cruise control + auto const SpeedCntrlVel{ ( + (ActualProximityDist > std::max(50.0, fMaxProximityDist)) ? + VelDesired : + min_speed(VelDesired, VelNext)) }; + if (SpeedCntrlVel >= mvControlling->SpeedCtrlUnit.MinVelocity) { + SpeedCntrl(SpeedCntrlVel); + } + else if (SpeedCntrlVel > 0.1) { + SpeedCntrl(0.0); + } + } if (mvControlling->EIMCtrlType > 0) { if (true == Ready) { - DizelPercentage = (mvControlling->Vel > mvControlling->dizel_minVelfullengage ? 100 : 1); + bool max = (mvControlling->Vel > mvControlling->dizel_minVelfullengage) + || (mvControlling->SpeedCtrl && mvControlling->ScndCtrlPos > 0); + DizelPercentage = (max ? 100 : 1); } break; } @@ -3188,11 +3202,12 @@ bool TController::IncSpeed() } } if( false == mvControlling->Mains ) { + SpeedCntrl(0.0); mvControlling->MainSwitch( true ); mvControlling->ConverterSwitch( true ); mvControlling->CompressorSwitch( true ); } - break; + break; } return OK; } @@ -3243,6 +3258,14 @@ bool TController::DecSpeed(bool force) if (mvControlling->EIMCtrlType > 0) { DizelPercentage = 0; + if (force) { + SpeedCntrl(0.0); //wylacz od razu tempomat + mvControlling->DecScndCtrl(2); + } + if ((VelDesired > 0.1) && (mvControlling->SpeedCtrlUnit.MinVelocity > VelDesired)) { + SpeedCntrl(0.0); //wylacz od razu tempomat + mvControlling->DecScndCtrl(2); + } break; } @@ -3257,8 +3280,11 @@ bool TController::DecSpeed(bool force) OK = mvControlling->DecMainCtrl( 1 ); } } - if (force) // przy aktywacji kabiny jest potrzeba natychmiastowego wyzerowania - OK = mvControlling->DecMainCtrl((mvControlling->MainCtrlPowerPos() > 2 ? 2 : 1)); + if (force) { // przy aktywacji kabiny jest potrzeba natychmiastowego wyzerowania + OK = mvControlling->DecMainCtrl((mvControlling->MainCtrlPowerPos() > 2 ? 2 : 1)); + SpeedCntrl(0.0); //wylacz od razu tempomat + mvControlling->DecScndCtrl( 2 ); + } break; } return OK; @@ -3495,6 +3521,22 @@ void TController::SpeedSet() void TController::SpeedCntrl(double DesiredSpeed) { + while (mvControlling->SpeedCtrlUnit.DesiredPower < mvControlling->SpeedCtrlUnit.MaxPower) + { + mvControlling->SpeedCtrlPowerInc(); + } + if (mvControlling->EngineType == TEngineType::DieselEngine) + { + if (DesiredSpeed < 0.1) { + mvControlling->DecScndCtrl(2); + DesiredSpeed = 0; + } + else if (mvControlling->ScndCtrlPos < 1) { + mvControlling->IncScndCtrl(1); + } + mvControlling->RunCommand("SpeedCntrl", DesiredSpeed, mvControlling->CabNo); + } + else if (mvControlling->ScndCtrlPosNo == 1) { mvControlling->IncScndCtrl(1); @@ -3579,8 +3621,13 @@ void TController::SetTimeControllers() { DizelPercentage_Speed = DizelPercentage; //wstepnie procenty - auto MinVel{ std::min(mvControlling->hydro_TC_LockupSpeed, mvControlling->Vmax / 6) }; //minimal velocity - if (VelDesired > MinVel) //more power for faster ride + auto MinVel{ std::min(mvControlling->hydro_TC_LockupSpeed, mvControlling->Vmax / 6) }; //minimal velocity + //when speed controll unit is active - start with the procedure + if ((mvControlling->SpeedCtrl) && (mvControlling->ScndCtrlPos > 0)) { + if ((mvControlling->ScndCtrlPos > 0) && (mvControlling->Vel < 1 + mvControlling->SpeedCtrlUnit.StartVelocity) && (DizelPercentage > 0)) + DizelPercentage_Speed = 101; //keep last position to start + } + else if (VelDesired > MinVel) //more power for faster ride { auto const Factor{ 10 * (mvControlling->Vmax) / (mvControlling->Vmax + 3 * mvControlling->Vel) }; auto DesiredPercentage{ clamp( @@ -3594,7 +3641,7 @@ void TController::SetTimeControllers() } DizelPercentage_Speed = std::round(DesiredPercentage * DizelPercentage); } - else + else //slow acceleration during shunting wth minimal velocity { DizelPercentage_Speed = std::min(DizelPercentage, mvControlling->Vel < 0.99 * VelDesired ? 1 : 0); } @@ -4394,9 +4441,11 @@ TController::UpdateSituation(double dt) { while (p) { // sprawdzenie odhamowania wszystkich połączonych pojazdów auto *vehicle { p->MoverParameters }; + double bp = vehicle->BrakePress - (vehicle->SpeedCtrlUnit.Parking ? vehicle->MaxBrakePress[0] * vehicle->StopBrakeDecc : 0.0); + if (bp < 0) bp = 0; if (Ready) { // bo jak coś nie odhamowane, to dalej nie ma co sprawdzać - if (vehicle->BrakePress >= 0.4) // wg UIC określone sztywno na 0.04 + if (bp >= 0.4) // wg UIC określone sztywno na 0.04 { Ready = false; // nie gotowy // Ra: odluźnianie przeładowanych lokomotyw, ciągniętych na zimno - prowizorka... @@ -4412,8 +4461,8 @@ TController::UpdateSituation(double dt) { } } } - if (fReady < vehicle->BrakePress) - fReady = vehicle->BrakePress; // szukanie najbardziej zahamowanego + if (fReady < bp) + fReady = bp; // szukanie najbardziej zahamowanego if( ( dy = p->VectorFront().y ) != 0.0 ) { // istotne tylko dla pojazdów na pochyleniu // ciężar razy składowa styczna grawitacji diff --git a/DynObj.cpp b/DynObj.cpp index 717463aa..960d2a47 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2831,8 +2831,10 @@ bool TDynamicObject::Update(double dt, double dt1) && (MoverParameters->EngineType == TEngineType::DieselEngine) && (MoverParameters->EIMCtrlType > 0)) { MoverParameters->CheckEIMIC(dt1); - MoverParameters->eimic_real = MoverParameters->eimic; - MoverParameters->SendCtrlToNext("EIMIC", MoverParameters->eimic, MoverParameters->CabNo); + if (MoverParameters->SpeedCtrl) + MoverParameters->CheckSpeedCtrl(dt1); + MoverParameters->eimic_real = std::min(MoverParameters->eimic,MoverParameters->eimicSpeedCtrl); + MoverParameters->SendCtrlToNext("EIMIC", MoverParameters->eimic_real, MoverParameters->CabNo); } if( ( Mechanik->primary() ) && ( MoverParameters->EngineType == TEngineType::ElectricInductionMotor ) ) { @@ -2852,10 +2854,10 @@ bool TDynamicObject::Update(double dt, double dt1) if( ( MoverParameters->Power < 1 ) && ( ctOwner != nullptr ) ) { MoverParameters->MainCtrlPos = ctOwner->Controlling()->MainCtrlPos*MoverParameters->MainCtrlPosNo / std::max(1, ctOwner->Controlling()->MainCtrlPosNo); - MoverParameters->ScndCtrlActualPos = ctOwner->Controlling()->ScndCtrlActualPos; + MoverParameters->SpeedCtrlValue = ctOwner->Controlling()->SpeedCtrlValue; } MoverParameters->CheckEIMIC(dt1); - MoverParameters->CheckSpeedCtrl(); + MoverParameters->CheckSpeedCtrl(dt1); auto eimic = Min0R(MoverParameters->eimic, MoverParameters->eimicSpeedCtrl); MoverParameters->eimic_real = eimic; diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 9856f781..98a16d6b 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -681,7 +681,32 @@ struct neighbour_data { float distance { 10000.f }; // distance to the obstacle // NOTE: legacy value. TBD, TODO: use standard -1 instead? }; - +struct speed_control { + bool IsActive = false; + bool Start = false; + bool ManualStateOverride = true; + bool BrakeIntervention = false; + bool BrakeInterventionBraking = false; + bool BrakeInterventionUnbraking = false; + bool Standby = true; + bool Parking = false; + double InitialPower = 0.3; + double FullPowerVelocity = 3; + double StartVelocity = 3; + double VelocityStep = 5; + double PowerStep = 0.1; + double MinPower = 0.3; + double MaxPower = 1.0; + double MinVelocity = 20; + double MaxVelocity = 120; + double DesiredVelocity = 0; + double DesiredPower = 1.0; + double Offset = -0.5; + double FactorPpos = 0.1; + double FactorPneg = 0.4; + double FactorIpos = 0.04; + double FactorIneg = 0.0; +}; class TMoverParameters { // Ra: wrapper na kod pascalowy, przejmujący jego funkcje Q: 20160824 - juz nie wrapper a klasa bazowa :) @@ -1187,7 +1212,11 @@ public: #endif double MirrorMaxShift { 90.0 }; bool ScndS = false; /*Czy jest bocznikowanie na szeregowej*/ + bool SpeedCtrl = false; /*czy jest tempomat*/ + speed_control SpeedCtrlUnit; /*parametry tempomatu*/ + double SpeedCtrlButtons[10] { 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 }; /*przyciski prędkości*/ double SpeedCtrlDelay = 2; /*opoznienie dzialania tempomatu z wybieralna predkoscia*/ + double SpeedCtrlValue = 0; /*wybrana predkosc jazdy na tempomacie*/ /*--sekcja zmiennych*/ /*--opis konkretnego egzemplarza taboru*/ TLocation Loc { 0.0, 0.0, 0.0 }; //pozycja pojazdów do wyznaczenia odległości pomiędzy sprzęgami @@ -1403,6 +1432,7 @@ public: static std::vector const eimv_labels; double SpeedCtrlTimer = 0; /*zegar dzialania tempomatu z wybieralna predkoscia*/ double eimicSpeedCtrl = 0; /*pozycja sugerowana przez tempomat*/ + double eimicSpeedCtrlIntegral = 0; /*calkowany blad ustawienia predkosci*/ double NewSpeed = 0; /*nowa predkosc do zadania*/ double MED_EPVC_CurrentTime = 0; /*aktualny czas licznika czasu korekcji siły EP*/ @@ -1633,7 +1663,12 @@ public: bool PantRear( bool const State, range_t const Notify = range_t::consist ); //obsluga pantografu tylnego void CheckEIMIC(double dt); //sprawdzenie i zmiana nastawy zintegrowanego nastawnika jazdy/hamowania - void CheckSpeedCtrl(); + void CheckSpeedCtrl(double dt); + void SpeedCtrlButton(int button); + void SpeedCtrlInc(); + void SpeedCtrlDec(); + void SpeedCtrlPowerInc(); + void SpeedCtrlPowerDec(); /*-funkcje typowe dla lokomotywy spalinowej z przekladnia mechaniczna*/ bool dizel_EngageSwitch(double state); @@ -1683,6 +1718,7 @@ private: void LoadFIZ_Security( std::string const &line ); void LoadFIZ_Clima( std::string const &line ); void LoadFIZ_Power( std::string const &Line ); + void LoadFIZ_SpeedControl( std::string const &Line ); void LoadFIZ_Engine( std::string const &Input ); void LoadFIZ_Switches( std::string const &Input ); void LoadFIZ_MotorParamTable( std::string const &Input ); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 253748f0..9dec9d29 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1001,145 +1001,68 @@ double TMoverParameters::PipeRatio(void) // Q: 20160716 // Wykrywanie kolizji // ************************************************************************************************* -void TMoverParameters::CollisionDetect(int const End, double const dt) +void TMoverParameters::CollisionDetect(int CouplerN, double dt) { - if( Neighbours[ End ].vehicle == nullptr ) { return; } // shouldn't normally happen but, eh + double CCF, Vprev, VprevC; + bool VirtualCoupling; - auto &coupler { Couplers[ End ] }; - auto *othervehicle { Neighbours[ End ].vehicle->MoverParameters }; - auto const otherend { Neighbours[ End ].vehicle_end }; - auto &othercoupler { othervehicle->Couplers[ otherend ] }; + CCF = 0; + // with Couplers[CouplerN] do + auto &coupler = Couplers[ CouplerN ]; - auto velocity { V }; - auto othervehiclevelocity { othervehicle->V }; - // calculate collision force and new velocities for involved vehicles - auto const VirtualCoupling { ( coupler.CouplingFlag == coupling::faux ) }; - auto CCF { 0.0 }; - - switch( End ) { - case 0: { + if (coupler.Connected != nullptr) + { + VirtualCoupling = (coupler.CouplingFlag == ctrain_virtual); + Vprev = V; + VprevC = coupler.Connected->V; + switch (CouplerN) + { + case 0: CCF = ComputeCollision( - velocity, othervehiclevelocity, - TotalMass, othervehicle->TotalMass, - ( coupler.beta + othercoupler.beta ) / 2.0, - VirtualCoupling ) - / ( dt ); + V, + coupler.Connected->V, + TotalMass, + coupler.Connected->TotalMass, + (coupler.beta + coupler.Connected->Couplers[coupler.ConnectedNr].beta) / 2.0, + VirtualCoupling) + / (dt); break; // yB: ej ej ej, a po - } - case 1: { + case 1: CCF = ComputeCollision( - othervehiclevelocity, velocity, - othervehicle->TotalMass, TotalMass, - ( coupler.beta + othercoupler.beta ) / 2.0, - VirtualCoupling ) - / ( dt ); - break; + coupler.Connected->V, + V, + coupler.Connected->TotalMass, + TotalMass, + (coupler.beta + coupler.Connected->Couplers[coupler.ConnectedNr].beta) / 2.0, + VirtualCoupling) + / (dt); + break; // czemu tu jest +0.01?? } - default: { - break; - } - } + AccS = AccS + (V - Vprev) / dt; // korekta przyspieszenia o siły wynikające ze zderzeń? + coupler.Connected->AccS += (coupler.Connected->V - VprevC) / dt; + if ((coupler.Dist > 0) && (!VirtualCoupling)) + if (FuzzyLogic(abs(CCF), 5.0 * (coupler.FmaxC + 1.0), p_coupldmg)) + { //! zerwanie sprzegu + if (SetFlag(DamageFlag, dtrain_coupling)) + EventFlag = true; - if( ( coupler.Dist < 0 ) - && ( FuzzyLogic( std::abs( CCF ), 5.0 * ( coupler.FmaxC + 1.0 ), p_coupldmg ) ) ) { - // small chance to smash the coupler if it's hit with excessive force - damage_coupler( End ); - } + if ((coupler.CouplingFlag & ctrain_pneumatic) == ctrain_pneumatic) + AlarmChainFlag = true; // hamowanie nagle - zerwanie przewodow hamulcowych + coupler.CouplingFlag = 0; - auto const safevelocitylimit { 15.0 }; - auto const velocitydifference { - glm::length( - glm::angleAxis( Rot.Rz, glm::dvec3{ 0, 1, 0 } ) * V - - glm::angleAxis( othervehicle->Rot.Rz, glm::dvec3{ 0, 1, 0 } ) * othervehicle->V ) - * 3.6 }; // m/s -> km/h - - if( velocitydifference > safevelocitylimit ) { - // HACK: crude estimation for potential derail, will take place with velocity difference > 15 km/h adjusted for vehicle mass ratio - if( ( false == TestFlag( DamageFlag, dtrain_out ) ) - || ( false == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) ) { - WriteLog( "Bad driving: " + Name + " and " + othervehicle->Name + " collided with velocity " + to_string( velocitydifference, 0 ) + " km/h" ); - } - - if( velocitydifference > safevelocitylimit * ( TotalMass / othervehicle->TotalMass ) ) { - derail( 5 ); - } - if( velocitydifference > safevelocitylimit * ( othervehicle->TotalMass / TotalMass ) ) { - othervehicle->derail( 5 ); - } - } - - // adjust velocity and acceleration of affected vehicles - if( false == TestFlag( DamageFlag, dtrain_out ) ) { - auto const accelerationchange{ ( velocity - V ) / dt }; - // if( accelerationchange / AccS < 1.0 ) { - // HACK: prevent excessive vehicle pinball cases - AccS += accelerationchange; - // AccS = clamp( AccS, -2.0, 2.0 ); - V = velocity; -// } - } - if( false == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) { - auto const othervehicleaccelerationchange{ ( othervehiclevelocity - othervehicle->V ) / dt }; -// if( othervehicleaccelerationchange / othervehicle->AccS < 1.0 ) { - // HACK: prevent excessive vehicle pinball cases - othervehicle->AccS += othervehicleaccelerationchange; - othervehicle->V = othervehiclevelocity; -// } - } -} - -void -TMoverParameters::damage_coupler( int const End ) { - - auto &coupler{ Couplers[ End ] }; - - if( coupler.CouplerType == TCouplerType::Articulated ) { return; } // HACK: don't break articulated couplings no matter what - - if( SetFlag( DamageFlag, dtrain_coupling ) ) - EventFlag = true; - - if( ( coupler.CouplingFlag & coupling::brakehose ) == coupling::brakehose ) { - // hamowanie nagle - zerwanie przewodow hamulcowych - AlarmChainFlag = true; - } - - coupler.CouplingFlag = 0; - - if( coupler.Connected != nullptr ) { - switch( End ) { - // break connection with other vehicle, if there's any - case 0: { - coupler.Connected->Couplers[ end::rear ].CouplingFlag = coupling::faux; - break; + switch (CouplerN) // wyzerowanie flag podlaczenia ale ciagle sa wirtualnie polaczone + { + case 0: + coupler.Connected->Couplers[1].CouplingFlag = 0; + break; + case 1: + coupler.Connected->Couplers[0].CouplingFlag = 0; + break; + } + WriteLog( "Bad driving: " + Name + " broke a coupler" ); } - case 1: { - coupler.Connected->Couplers[ end::front ].CouplingFlag = coupling::faux; - break; - } - default: { - break; - } - } - } - - WriteLog( "Bad driving: " + Name + " broke a coupler" ); -} - -void -TMoverParameters::derail( int const Reason ) { - - if( SetFlag( DamageFlag, dtrain_out ) ) { - - DerailReason = Reason; // TODO: enum derail causes - EventFlag = true; - MainSwitch( false, range_t::local ); - - AccS *= 0.65; - V *= 0.65; - - WriteLog( "Bad driving: " + Name + " derailed" ); } } @@ -1148,7 +1071,7 @@ TMoverParameters::derail( int const Reason ) { // ************************************************************************************************* double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, - TLocation const &NewLoc, TRotation const &NewRot) + const TLocation &NewLoc, TRotation &NewRot) { const double Vepsilon = 1e-5; const double Aepsilon = 1e-3; // ASBSpeed=0.8; @@ -1182,6 +1105,9 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap // TODO: investigate, seems supplied NewRot is always 0 although the code here suggests some actual values are expected Loc = NewLoc; Rot = NewRot; + NewRot.Rx = 0; + NewRot.Ry = 0; + NewRot.Rz = 0; if (dL == 0) // oblicz przesuniecie} { @@ -1310,14 +1236,17 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap // ************************************************************************************************* double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape, - TTrackParam &Track, TLocation const &NewLoc, - TRotation const &NewRot) + TTrackParam &Track, const TLocation &NewLoc, + TRotation &NewRot) { int b; // T_MoverParameters::FastComputeMovement(dt, Shape, Track, NewLoc, NewRot); Loc = NewLoc; Rot = NewRot; + NewRot.Rx = 0.0; + NewRot.Ry = 0.0; + NewRot.Rz = 0.0; if (dL == 0) // oblicz przesuniecie { @@ -1386,11 +1315,10 @@ void TMoverParameters::compute_movement_( double const Deltatime ) { RunInternalCommand(); // automatyczny rozruch - if( EngineType == TEngineType::ElectricSeriesMotor ) { - if( AutoRelayCheck() ) { - SetFlag( SoundFlag, sound::relay ); - } - } + if (EngineType == TEngineType::ElectricSeriesMotor) + + if (AutoRelayCheck()) + SetFlag(SoundFlag, sound::relay); if( ( EngineType == TEngineType::DieselEngine ) || ( EngineType == TEngineType::DieselElectric ) ) { @@ -1402,8 +1330,6 @@ void TMoverParameters::compute_movement_( double const Deltatime ) { // TODO: gather and move current calculations to dedicated method TotalCurrent = 0; - // main circuit - MainsCheck( Deltatime ); // traction motors MotorBlowersCheck( Deltatime ); // uklady hamulcowe: @@ -1445,37 +1371,6 @@ void TMoverParameters::compute_movement_( double const Deltatime ) { PowerCouplersCheck( Deltatime ); } -void TMoverParameters::MainsCheck( double const Deltatime ) { - - // TODO: move other main circuit checks here - - if( MainsInitTime == 0.0 ) { return; } - - if( MainsInitTimeCountdown > 0.0 ) { - MainsInitTimeCountdown -= Deltatime; - } - // TBD, TODO: move voltage calculation to separate method and use also in power coupler state calculation? - auto localvoltage { 0.0 }; - switch( EnginePowerSource.SourceType ) { - case TPowerSource::CurrentCollector: { - localvoltage = - std::max( - localvoltage, - std::max( - PantFrontVolt, - PantRearVolt ) ); - break; - } - default: { - break; - } - } - if( ( localvoltage == 0.0 ) - && ( GetTrainsetVoltage() == 0 ) ) { - MainsInitTimeCountdown = MainsInitTime; - } -} - void TMoverParameters::PowerCouplersCheck( double const Deltatime ) { // TODO: add support for other power sources auto localvoltage { 0.0 }; @@ -1487,13 +1382,7 @@ void TMoverParameters::PowerCouplersCheck( double const Deltatime ) { break; } case TPowerSource::Main: { - // HACK: main circuit can be fed through couplers, so we explicitly check pantograph supply here - localvoltage = ( - true == Mains ? - std::max( - PantFrontVolt, - PantRearVolt ) : - 0.0 ); + localvoltage = ( true == Mains ? Voltage : 0.0 ); break; } default: { @@ -1655,8 +1544,6 @@ void TMoverParameters::HeatingCheck( double const Timestep ) { auto const absrevolutions { std::abs( generator.revolutions ) }; generator.voltage = ( - false == HeatingAllow ? 0.0 : - // TODO: add support for desired voltage selector absrevolutions < generator.revolutions_min ? generator.voltage_min * absrevolutions / generator.revolutions_min : // absrevolutions > generator.revolutions_max ? generator.voltage_max * absrevolutions / generator.revolutions_max : interpolate( @@ -1793,7 +1680,7 @@ void TMoverParameters::OilPumpCheck( double const Timestep ) { OilPump.pressure = std::max( OilPump.pressure_target, - OilPump.pressure - ( enrot > 5.0 ? 0.05 : 0.035 ) * 0.5 * Timestep ); + OilPump.pressure - 0.01 * Timestep ); } OilPump.pressure = clamp( OilPump.pressure, 0.f, 1.5f ); } @@ -1902,7 +1789,10 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) ++MainCtrlPos; OK = true; if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) + { DecScndCtrl(2); + SpeedCtrlUnit.IsActive = false; + } } break; } @@ -2065,8 +1955,10 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) { MainCtrlPos--; OK = true; - if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) { DecScndCtrl(2); + SpeedCtrlUnit.IsActive = false; + } } else if (CtrlSpeed > 1) OK = (DecMainCtrl(1) && DecMainCtrl(2)); // CtrlSpeed-1); @@ -2212,14 +2104,22 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) { // NOTE: round() already adds 0.5, are the ones added here as well correct? if ((Vmax < 250)) - ScndCtrlActualPos = Round(Vel); + SpeedCtrlValue = Round(Vel); else - ScndCtrlActualPos = Round(Vel * 0.5); + SpeedCtrlValue = Round(Vel * 0.5); if ((EIMCtrlType == 0)&&(SpeedCtrlAutoTurnOffFlag == 1)) { MainCtrlActualPos = MainCtrlPos; } - SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo); + SpeedCtrlUnit.IsActive = true; + SendCtrlToNext("SpeedCntrl", SpeedCtrlValue, CabNo); + } + + if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 1) && (EngineType == TEngineType::DieselEngine)) + { + // NOTE: round() already adds 0.5, are the ones added here as well correct? + SpeedCtrlValue = Round(Vel); + SpeedCtrlUnit.IsActive = true; } return OK; @@ -2272,8 +2172,16 @@ bool TMoverParameters::DecScndCtrl(int CtrlSpeed) if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1)) { - ScndCtrlActualPos = 0; - SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo); + SpeedCtrlValue = 0; + SendCtrlToNext("SpeedCntrl", SpeedCtrlValue, CabNo); + SpeedCtrlUnit.IsActive = false; + } + + if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 0) && (EngineType == TEngineType::DieselEngine)) + { + // NOTE: round() already adds 0.5, are the ones added here as well correct? + SpeedCtrlValue = 0; + SpeedCtrlUnit.IsActive = false; } return OK; @@ -2312,7 +2220,7 @@ bool TMoverParameters::CabDeactivisation(void) CabNo = 0; DirAbsolute = ActiveDir * CabNo; DepartureSignal = false; // nie buczeć z nieaktywnej kabiny - SecuritySystem.Status = s_off; // deactivate alerter TODO: make it part of control based cab selection + SecuritySystem.Status = 0; // deactivate alerter TODO: make it part of control based cab selection SendCtrlToNext("CabActivisation", 0, ActiveCab); // CabNo==0! } @@ -2531,9 +2439,8 @@ void TMoverParameters::SecuritySystemCheck(double dt) if ((!Radio)) RadiostopSwitch(false); - if ((SecuritySystem.SystemType > 0) - && (SecuritySystem.Status != s_off) - && (Battery)) // Ra: EZT ma teraz czuwak w rozrządczym + if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0) && + (Battery)) // Ra: EZT ma teraz czuwak w rozrządczym { // CA if( ( SecuritySystem.AwareMinSpeed > 0.0 ? @@ -2561,29 +2468,30 @@ void TMoverParameters::SecuritySystemCheck(double dt) SecuritySystem.EmergencyBrakeDelay) && (SecuritySystem.EmergencyBrakeDelay >= 0)) SetFlag(SecuritySystem.Status, s_CAebrake); - } - // SHP - if( TestFlag( SecuritySystem.SystemType, 2 ) ) { - if( TestFlag( SecuritySystem.Status, s_SHPalarm ) ) { - // jeśli buczy - SecuritySystem.SystemBrakeSHPTimer += dt; - } - if( TestFlag( SecuritySystem.Status, s_active ) ) { - // jeśli świeci albo miga - SecuritySystem.SystemSoundSHPTimer += dt; - if( ( SecuritySystem.VelocityAllowed >= 0 ) && ( Vel > SecuritySystem.VelocityAllowed ) ) { - SetFlag( SecuritySystem.Status, s_SHPebrake ); - } - else if( ( ( SecuritySystem.SoundSignalDelay >= 0 ) && ( SecuritySystem.SystemSoundSHPTimer > SecuritySystem.SoundSignalDelay ) ) - || ( ( SecuritySystem.NextVelocityAllowed >= 0 ) && ( Vel > SecuritySystem.NextVelocityAllowed ) ) ) { - SetFlag( SecuritySystem.Status, s_SHPalarm ); - if( ( SecuritySystem.EmergencyBrakeDelay >= 0 ) && ( SecuritySystem.SystemBrakeSHPTimer > SecuritySystem.EmergencyBrakeDelay ) ) { - SetFlag( SecuritySystem.Status, s_SHPebrake ); - } - } - } - } + // SHP + if (TestFlag(SecuritySystem.SystemType, 2) && + TestFlag(SecuritySystem.Status, s_active)) // jeśli świeci albo miga + SecuritySystem.SystemSoundSHPTimer += dt; + if (TestFlag(SecuritySystem.SystemType, 2) && + TestFlag(SecuritySystem.Status, s_SHPalarm)) // jeśli buczy + SecuritySystem.SystemBrakeSHPTimer += dt; + if (TestFlag(SecuritySystem.SystemType, 2) && TestFlag(SecuritySystem.Status, s_active)) + if ((Vel > SecuritySystem.VelocityAllowed) && (SecuritySystem.VelocityAllowed >= 0)) + SetFlag(SecuritySystem.Status, s_SHPebrake); + else if (((SecuritySystem.SystemSoundSHPTimer > SecuritySystem.SoundSignalDelay) && + (SecuritySystem.SoundSignalDelay >= 0)) || + ((Vel > SecuritySystem.NextVelocityAllowed) && + (SecuritySystem.NextVelocityAllowed >= 0))) + if (!SetFlag(SecuritySystem.Status, + s_SHPalarm)) // juz wlaczony sygnal dzwiekowy} + if ((SecuritySystem.SystemBrakeSHPTimer > + SecuritySystem.EmergencyBrakeDelay) && + (SecuritySystem.EmergencyBrakeDelay >= 0)) + SetFlag(SecuritySystem.Status, s_SHPebrake); + + } // else SystemTimer:=0; + // TEST CA if (TestFlag(SecuritySystem.Status, s_CAtest)) // jeśli świeci albo miga SecuritySystem.SystemBrakeCATestTimer += dt; @@ -2623,8 +2531,8 @@ bool TMoverParameters::BatterySwitch(bool State) SendCtrlToNext("BatterySwitch", 0, CabNo); BS = true; - if ((Battery) && (ActiveCab != 0)) - SecuritySystem.Status |= s_waiting; // aktywacja czuwaka + if ((Battery) && (ActiveCab != 0)) /*|| (TrainType==dt_EZT)*/ + SecuritySystem.Status = (SecuritySystem.Status | s_waiting); // aktywacja czuwaka else SecuritySystem.Status = 0; // wyłączenie czuwaka @@ -3091,7 +2999,6 @@ void TMoverParameters::MainSwitch_( bool const State ) { if( ( false == State ) || ( ( ( ScndCtrlPos == 0 ) || ( EngineType == TEngineType::ElectricInductionMotor ) ) && ( ( ConvOvldFlag == false ) || ( TrainType == dt_EZT ) ) - && ( MainsInitTimeCountdown <= 0.0 ) && ( true == NoVoltRelay ) && ( true == OvervoltageRelay ) && ( LastSwitchingTime > CtrlDelay ) @@ -3925,8 +3832,13 @@ void TMoverParameters::UpdatePipePressure(double dt) if( BrakeCtrlPosNo > 1 ) { - if ((EngineType != TEngineType::ElectricInductionMotor)) - dpLocalValve = LocHandle->GetPF(std::max(LocalBrakePosA, LocalBrakePosAEIM), Hamulec->GetBCP(), ScndPipePress, dt, 0); + if ((EngineType != TEngineType::ElectricInductionMotor)) { + double lbpa = LocalBrakePosA; + if (SpeedCtrlUnit.Parking) { + lbpa = std::max(lbpa, StopBrakeDecc); + } + dpLocalValve = LocHandle->GetPF(std::max(lbpa, LocalBrakePosAEIM), Hamulec->GetBCP(), ScndPipePress, dt, 0); + } else dpLocalValve = LocHandle->GetPF(LocalBrakePosAEIM, Hamulec->GetBCP(), ScndPipePress, dt, 0); @@ -3955,7 +3867,15 @@ void TMoverParameters::UpdatePipePressure(double dt) || ( ( Handle->GetPos( bh_EB ) - 0.5 ) < BrakeCtrlPosR ) || ( ( BrakeHandle != TBrakeHandle::MHZ_EN57 ) && ( BrakeHandle != TBrakeHandle::MHZ_K8P ) ) ) { - dpMainValve = Handle->GetPF( BrakeCtrlPosR, PipePress, temp, dt, EqvtPipePress ); + double pos = BrakeCtrlPosR; + if (SpeedCtrl && SpeedCtrlUnit.BrakeIntervention && !SpeedCtrlUnit.Standby) { + pos = Handle->GetPos(bh_NP); + if (SpeedCtrlUnit.BrakeInterventionBraking) + pos = Handle->GetPos(bh_FB); + if (SpeedCtrlUnit.BrakeInterventionUnbraking) + pos = Handle->GetPos(bh_RP); + } + dpMainValve = Handle->GetPF( pos, PipePress, temp, dt, EqvtPipePress ); } else { dpMainValve = Handle->GetPF( 0, PipePress, temp, dt, EqvtPipePress ); @@ -4308,6 +4228,7 @@ void TMoverParameters::ComputeConstans(void) double BearingF, RollF, HideModifier; double Curvature; // Ra 2014-07: odwrotność promienia + TotalMass = ComputeMass(); TotalMassxg = TotalMass * g; // TotalMass*g BearingF = 2.0 * (DamageFlag && dtrain_bearing); @@ -4358,28 +4279,29 @@ void TMoverParameters::ComputeConstans(void) // Q: 20160713 // Oblicza masę ładunku // ************************************************************************************************* -void TMoverParameters::ComputeMass() +double TMoverParameters::ComputeMass(void) { + double M { 0.0 }; + // TODO: unit weight table, pulled from external data file + if( LoadAmount > 0 ) { + + if (ToLower(LoadQuantity) == "tonns") + M = LoadAmount * 1000; + else if (LoadType.name == "passengers") + M = LoadAmount * 80; + else if (LoadType.name == "luggage") + M = LoadAmount * 100; + else if (LoadType.name == "cars") + M = LoadAmount * 1200; // 800 kilo to miał maluch + else if (LoadType.name == "containers") + M = LoadAmount * 8000; + else if (LoadType.name == "transformers") + M = LoadAmount * 50000; + else + M = LoadAmount * 1000; + } // Ra: na razie tak, ale nie wszędzie masy wirujące się wliczają - TotalMass = Mass + Mred; - - if( LoadAmount == 0 ) { return; } - - // include weight of carried load - auto loadtypeunitweight { 0.f }; - - if( ToLower( LoadQuantity ) == "tonns" ) { - loadtypeunitweight = 1000; - } - else { - auto const lookup { simulation::Weights.find( LoadType.name ) }; - loadtypeunitweight = ( - lookup != simulation::Weights.end() ? - lookup->second : - 1000.f ); // legacy default unit weight value - } - - TotalMass += LoadAmount * loadtypeunitweight; + return Mass + M + Mred; } // ************************************************************************************************* @@ -4421,11 +4343,6 @@ void TMoverParameters::ComputeTotalForce(double dt) { // juz zoptymalizowane: FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // siła oporów ruchu - if( true == TestFlag( DamageFlag, dtrain_out ) ) { - // HACK: crude way to reduce speed after derailment - // TBD, TODO: more accurate approach? - FStand *= 1e20; - } double old_nrot = abs(nrot); nrot = v2n(); // przeliczenie prędkości liniowej na obrotową @@ -4718,13 +4635,15 @@ double TMoverParameters::CouplerForce( int const End, double dt ) { auto &othercoupler { othervehicle->Couplers[ otherend ] }; auto const othervehiclemove { ( othervehicle->dMoveLen * DirPatch( End, otherend ) ) }; - auto const initialdistance { Neighbours[ End ].distance }; // odległość od sprzęgu sąsiada auto const distancedelta { ( End == end::front ? othervehiclemove - dMoveLen : dMoveLen - othervehiclemove ) }; + auto const initialdistance { Neighbours[ End ].distance }; // odległość od sprzęgu sąsiada - auto const newdistance { initialdistance + 10.0 * distancedelta }; + auto const newdistance = + initialdistance + + 10.0 * distancedelta; auto const dV { V - ( othervehicle->V * DirPatch( End, otherend ) ) }; auto const absdV { std::abs( dV ) }; @@ -4754,15 +4673,11 @@ double TMoverParameters::CouplerForce( int const End, double dt ) { } coupler.CheckCollision = false; - coupler.Dist = 0.0; - double CF { 0.0 }; if( ( coupler.CouplingFlag != coupling::faux ) || ( initialdistance < 0 ) ) { - coupler.Dist = clamp( newdistance, -coupler.DmaxB, coupler.DmaxC ); - double BetaAvg = 0; double Fmax = 0; @@ -4777,8 +4692,8 @@ double TMoverParameters::CouplerForce( int const End, double dt ) { Fmax = 0.5 * ( coupler.FmaxC + coupler.FmaxB + othercoupler.FmaxC + othercoupler.FmaxB ) * CouplerTune; } auto const distDelta { std::abs( newdistance ) - std::abs( coupler.Dist ) }; // McZapkie-191103: poprawka na histereze - - if (newdistance > 0) { + coupler.Dist = newdistance; + if (coupler.Dist > 0) { if( distDelta > 0 ) { CF = ( -( coupler.SpringKC + othercoupler.SpringKC ) * coupler.Dist / 2.0 ) * DirF( End ) @@ -4789,25 +4704,12 @@ double TMoverParameters::CouplerForce( int const End, double dt ) { - Fmax * dV * BetaAvg; } // liczenie sily ze sprezystosci sprzegu - if( newdistance > ( coupler.DmaxC + othercoupler.DmaxC ) ) { + if( coupler.Dist > ( coupler.DmaxC + othercoupler.DmaxC ) ) { // zderzenie coupler.CheckCollision = true; } - if( std::abs( CF ) > coupler.FmaxC ) { - // coupler is stretched with excessive force, may break - coupler.stretch_duration += dt; - // give coupler 1 sec of leeway to account for simulation glitches, before checking whether it breaks - // (arbitrary) chance to break grows from 10-100% over 10 sec period - if( ( coupler.stretch_duration > 1.f ) - && ( Random() < ( coupler.stretch_duration * 0.1f * dt ) ) ) { - damage_coupler( End ); - } - } - else { - coupler.stretch_duration = 0.f; - } } - if( newdistance < 0 ) { + if( coupler.Dist < 0 ) { if( distDelta > 0 ) { CF = ( -( coupler.SpringKB + othercoupler.SpringKB ) * coupler.Dist / 2.0 ) * DirF( End ) @@ -4818,7 +4720,7 @@ double TMoverParameters::CouplerForce( int const End, double dt ) { - Fmax * dV * BetaAvg; } // liczenie sily ze sprezystosci zderzaka - if( -newdistance > ( coupler.DmaxB + othercoupler.DmaxB ) ) { + if( -coupler.Dist > ( coupler.DmaxB + othercoupler.DmaxB ) ) { // zderzenie coupler.CheckCollision = true; if( ( coupler.CouplerType == TCouplerType::Automatic ) @@ -4872,12 +4774,9 @@ double TMoverParameters::TractionForce( double dt ) { EngineHeatingRPM ) / 60.0 ); } - // NOTE: fake dizel_fill calculation for the sake of smoke emitter which uses this parameter to determine smoke opacity - dizel_fill = clamp( 0.2 + 0.35 * ( tmp - enrot ), 0.0, 1.0 ); } else { tmp = 0.0; - dizel_fill = 0.0; } if( enrot != tmp ) { @@ -5518,7 +5417,7 @@ double TMoverParameters::TractionForce( double dt ) { switch (ScndCtrlPos) { case 0: NewSpeed = 0; - ScndCtrlActualPos = 0; + SpeedCtrlValue = 0; SpeedCtrlTimer = 10; break; case 1: @@ -5532,7 +5431,7 @@ double TMoverParameters::TractionForce( double dt ) { break; case 2: SpeedCtrlTimer = 10; - ScndCtrlActualPos = NewSpeed; + SpeedCtrlValue = NewSpeed; break; case 3: if (SpeedCtrlTimer > SpeedCtrlDelay) { @@ -5545,7 +5444,7 @@ double TMoverParameters::TractionForce( double dt ) { break; case 4: NewSpeed = Vmax; - ScndCtrlActualPos = Vmax; + SpeedCtrlValue = Vmax; SpeedCtrlTimer = 10; break; } @@ -5564,10 +5463,10 @@ double TMoverParameters::TractionForce( double dt ) { if (SpeedCtrlTimer > SpeedCtrlDelay) { int NewSCAP = (Vmax < 250 ? 1 : 0.5) * (float)ScndCtrlPos / (float)ScndCtrlPosNo * Vmax; - if (NewSCAP != ScndCtrlActualPos) + if (NewSCAP != SpeedCtrlValue) { - ScndCtrlActualPos = NewSCAP; -// SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo); + SpeedCtrlValue = NewSCAP; +// SendCtrlToNext("SpeedCntrl", SpeedCtrlValue, CabNo); } } } @@ -5624,12 +5523,12 @@ double TMoverParameters::TractionForce( double dt ) { eimv[eimv_Fzad] = PosRatio; if ((Flat) && (eimc[eimc_p_F0] * eimv[eimv_Fful] > 0)) PosRatio = Min0R(PosRatio * eimc[eimc_p_F0] / eimv[eimv_Fful], 1); -/* if (ScndCtrlActualPos > 0) //speed control +/* if (SpeedCtrlValue > 0) //speed control if (Vmax < 250) - PosRatio = Min0R(PosRatio, Max0R(-1, 0.5 * (ScndCtrlActualPos - Vel))); + PosRatio = Min0R(PosRatio, Max0R(-1, 0.5 * (SpeedCtrlValue - Vel))); else PosRatio = - Min0R(PosRatio, Max0R(-1, 0.5 * (ScndCtrlActualPos * 2 - Vel))); */ + Min0R(PosRatio, Max0R(-1, 0.5 * (SpeedCtrlValue * 2 - Vel))); */ // PosRatio = 1.0 * (PosRatio * 0 + 1) * PosRatio; // 1 * 1 * PosRatio = PosRatio Hamulec->SetED(0); // (Hamulec as TLSt).SetLBP(LocBrakePress); @@ -5717,19 +5616,25 @@ double TMoverParameters::TractionForce( double dt ) { eimv[eimv_ks] = eimv[eimv_Fr] / eimv[eimv_FMAXMAX]; eimv[eimv_df] = eimv[eimv_ks] * eimc[eimc_s_dfmax]; - eimv[eimv_fp] = DirAbsolute * enrot * eimc[eimc_s_p] + eimv[eimv_df]; // do przemyslenia dzialanie pp z tmpV + eimv[eimv_fp] = DirAbsolute * enrot * eimc[eimc_s_p] + + eimv[eimv_df]; // do przemyslenia dzialanie pp z tmpV // eimv[eimv_U]:=Max0R(eimv[eimv_Uzsmax],Min0R(eimc[eimc_f_cfu]*eimv[eimv_fp],eimv[eimv_Uzsmax])); // eimv[eimv_pole]:=eimv[eimv_U]/(eimv[eimv_fp]*eimc[eimc_s_cfu]); if ((abs(eimv[eimv_fp]) <= eimv[eimv_fkr])) eimv[eimv_pole] = eimc[eimc_f_cfu] / eimc[eimc_s_cfu]; else - eimv[eimv_pole] = eimv[eimv_Uzsmax] / eimc[eimc_s_cfu] / abs(eimv[eimv_fp]); + eimv[eimv_pole] = + eimv[eimv_Uzsmax] / eimc[eimc_s_cfu] / abs(eimv[eimv_fp]); eimv[eimv_U] = eimv[eimv_pole] * eimv[eimv_fp] * eimc[eimc_s_cfu]; - eimv[eimv_Ic] = (eimv[eimv_fp] - DirAbsolute * enrot * eimc[eimc_s_p]) * eimc[eimc_s_dfic] * eimv[eimv_pole]; + eimv[eimv_Ic] = (eimv[eimv_fp] - DirAbsolute * enrot * eimc[eimc_s_p]) * + eimc[eimc_s_dfic] * eimv[eimv_pole]; eimv[eimv_If] = eimv[eimv_Ic] * eimc[eimc_s_icif]; eimv[eimv_M] = eimv[eimv_pole] * eimv[eimv_Ic] * eimc[eimc_s_cim]; - eimv[eimv_Ipoj] = (eimv[eimv_Ic] * NPoweredAxles * eimv[eimv_U]) / (Voltage - eimc[eimc_f_DU]) + eimc[eimc_f_I0]; - eimv[eimv_Pm] = ActiveDir * eimv[eimv_M] * NPoweredAxles * enrot * Pirazy2 / 1000; + eimv[eimv_Ipoj] = (eimv[eimv_Ic] * NPoweredAxles * eimv[eimv_U]) / + (Voltage - eimc[eimc_f_DU]) + + eimc[eimc_f_I0]; + eimv[eimv_Pm] = + ActiveDir * eimv[eimv_M] * NPoweredAxles * enrot * Pirazy2 / 1000; eimv[eimv_Pe] = eimv[eimv_Ipoj] * Voltage / 1000; eimv[eimv_eta] = eimv[eimv_Pm] / eimv[eimv_Pe]; @@ -5750,7 +5655,7 @@ double TMoverParameters::TractionForce( double dt ) { if( ( RlistSize > 0 ) && ( ( std::abs( eimv[ eimv_If ] ) > 1.0 ) - && ( tmpV > 0.1 ) ) ) { + || ( tmpV > 0.1 ) ) ) { int i = 0; while( ( i < RlistSize - 1 ) @@ -6604,15 +6509,106 @@ void TMoverParameters::CheckEIMIC(double dt) eimic = clamp(eimic, -1.0, eimicpowerenabled ? 1.0 : 0.0); } -void TMoverParameters::CheckSpeedCtrl() +void TMoverParameters::CheckSpeedCtrl(double dt) { - if (ScndCtrlActualPos > 0) //speed control - if (Vmax < 250) - eimicSpeedCtrl = clamp(0.5 * (ScndCtrlActualPos - Vel), -1.0, 1.0); - else - eimicSpeedCtrl = clamp(0.5 * (ScndCtrlActualPos * 2 - Vel), -1.0, 1.0); - else + if (MainCtrlPos < MainCtrlPosNo - 2) { + SpeedCtrlUnit.Standby = true; + } + if (MainCtrlPos > MainCtrlPosNo - 1) { + SpeedCtrlUnit.Standby = false; + } + if (SpeedCtrlUnit.IsActive) {//speed control + if (EngineType == TEngineType::DieselEngine) { + if ((!SpeedCtrlUnit.Standby)) { + if (SpeedCtrlUnit.ManualStateOverride) { + if (MainCtrlPos < MainCtrlPosNo - 1) { + eimic = std::min(eimic, 0.0); + eimicSpeedCtrlIntegral = 0.0; + } + else if (eimic > 0.009) eimic = 1.0; + } + double error = (std::max(SpeedCtrlValue + SpeedCtrlUnit.Offset, 0.0) - Vel); + double factorP = error > 0 ? SpeedCtrlUnit.FactorPpos : SpeedCtrlUnit.FactorPneg; + double eSCP = clamp(factorP * error, -1.2, 1.0); //P module + if (eSCP < -1.0) + { + SpeedCtrlUnit.BrakeInterventionBraking = (eSCP < -1.1) && (Vel < hydro_TC_UnlockSpeed); + eSCP = -1.0; + } + SpeedCtrlUnit.BrakeInterventionUnbraking = (eSCP > 0.0) || (Vel == 0.0); + if (abs(eSCP) < 0.999) { + //TODO: check how to disable integral part when braking in smart way + //double factorI = eimicSpeedCtrlIntegral >= 0 ? SpeedCtrlUnit.FactorIpos : SpeedCtrlUnit.FactorIneg; + double factorI = eimicSpeedCtrlIntegral >= 0 ? SpeedCtrlUnit.FactorIpos : SpeedCtrlUnit.FactorIneg; + eimicSpeedCtrlIntegral = clamp(eimicSpeedCtrlIntegral + factorI * eSCP * dt, -1.0 + eSCP, 1.0 - eSCP); + } + else { + eimicSpeedCtrlIntegral = 0; + } + eimicSpeedCtrl = clamp(eimicSpeedCtrlIntegral + eSCP, -SpeedCtrlUnit.DesiredPower, SpeedCtrlUnit.DesiredPower); + if (Vel < SpeedCtrlUnit.FullPowerVelocity) { + eimicSpeedCtrl = std::min(eimicSpeedCtrl, SpeedCtrlUnit.InitialPower); + } + if ((Vel < SpeedCtrlUnit.StartVelocity) && (MainCtrlPos < MainCtrlPosNo)) { + eimicSpeedCtrl = 0; + eimic = 0; + } + } + else { + eimicSpeedCtrl = 1; + eimicSpeedCtrlIntegral = 0; + } + SpeedCtrlUnit.Parking = (Vel == 0.0) & (eimic <= 0); + SendCtrlToNext("SpeedCtrlUnit.Parking", SpeedCtrlUnit.Parking, CabNo); + + } + else { + if (Vmax < 250) + eimicSpeedCtrl = clamp(0.5 * (SpeedCtrlValue - Vel), -1.0, 1.0); + else + eimicSpeedCtrl = clamp(0.5 * (SpeedCtrlValue * 2 - Vel), -1.0, 1.0); + } + } + else { eimicSpeedCtrl = 1; + eimicSpeedCtrlIntegral = 0; + SpeedCtrlUnit.Parking = false; + } +} + +void TMoverParameters::SpeedCtrlButton(int button) +{ + if ((SpeedCtrl) && (ScndCtrlPos > 0)) { + SpeedCtrlValue = SpeedCtrlButtons[button]; + } +} + +void TMoverParameters::SpeedCtrlInc() +{ + if ((SpeedCtrl) && (ScndCtrlPos > 0)) { + SpeedCtrlValue = std::min(SpeedCtrlValue + SpeedCtrlUnit.VelocityStep, SpeedCtrlUnit.MaxVelocity); + } +} + +void TMoverParameters::SpeedCtrlDec() +{ + if ((SpeedCtrl) && (ScndCtrlPos > 0)) { + SpeedCtrlValue = std::max(SpeedCtrlValue - SpeedCtrlUnit.VelocityStep, SpeedCtrlUnit.MinVelocity); + } +} + +void TMoverParameters::SpeedCtrlPowerInc() +{ + if ((SpeedCtrl) && (ScndCtrlPos > 0)) { + SpeedCtrlUnit.DesiredPower = std::min(SpeedCtrlUnit.DesiredPower + SpeedCtrlUnit.PowerStep, SpeedCtrlUnit.MaxPower); + } +} + +void TMoverParameters::SpeedCtrlPowerDec() +{ + if ((SpeedCtrl) && (ScndCtrlPos > 0)) { + SpeedCtrlUnit.DesiredPower = std::max(SpeedCtrlUnit.DesiredPower - SpeedCtrlUnit.PowerStep, SpeedCtrlUnit.MinPower); + } } // ************************************************************************************************* @@ -7390,7 +7386,6 @@ TMoverParameters::AssignLoad( std::string const &Name, float const Amount ) { if( Name == loadattributes.name ) { LoadType = loadattributes; LoadAmount = clamp( Amount, 0.f, MaxLoad ) ; - ComputeMass(); return true; } } @@ -7410,7 +7405,7 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn return true; } - if( Loadname.empty() ) { return ( LoadStatus >= 4 ); } + if( Loadname.empty() ) { return ( LoadStatus >= 4 ); } if( Loadname != LoadType.name ) { return ( LoadStatus >= 4 ); } // test zakończenia załadunku/rozładunku @@ -7433,7 +7428,6 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn if( LoadAmount == 0.f ) { AssignLoad(""); // jak nic nie ma, to nie ma też nazwy } - ComputeMass(); } } else if( LSpeed > 0 ) { @@ -7448,7 +7442,6 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn LoadStatus = 4; // skończony załadunek LoadAmount = std::min( MaxLoad * ( 1.0 + OverLoadFactor ), LoadAmount ); } - ComputeMass(); } } @@ -8621,6 +8614,14 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) continue; } + if (issection("SpeedControl:", inputline)) + { + startBPT = false; + fizlines.emplace("SpeedControl", inputline); + LoadFIZ_SpeedControl(inputline); + continue; + } + if( issection( "Engine:", inputline ) ) { startBPT = false; @@ -9372,16 +9373,6 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { extract_value( StopBrakeDecc, "SBD", line, "" ); - // speed control - extract_value( SpeedCtrlDelay, "SpeedCtrlDelay", line, "" ); - SpeedCtrlTypeTime = - (extract_value("SpeedCtrlType", line) == "Time") ? - true : - false; - extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", line, ""); - - // main circuit - extract_value( MainsInitTime, "MainInitTime", line, "" ); // converter { std::map starts { @@ -9460,9 +9451,9 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { void TMoverParameters::LoadFIZ_Blending(std::string const &line) { extract_value(MED_Vmax, "MED_Vmax", line, to_string(Vmax)); - extract_value(MED_Vmin, "MED_Vmin", line, ""); + extract_value(MED_Vmin, "MED_Vmin", line, "0"); extract_value(MED_Vref, "MED_Vref", line, to_string(Vmax)); - extract_value(MED_amax, "MED_amax", line, ""); + extract_value(MED_amax, "MED_amax", line, "9.81"); extract_value(MED_EPVC, "MED_EPVC", line, ""); extract_value(MED_Ncor, "MED_Ncor", line, ""); @@ -9470,10 +9461,10 @@ void TMoverParameters::LoadFIZ_Blending(std::string const &line) { void TMoverParameters::LoadFIZ_DCEMUED(std::string const &line) { - extract_value(DCEMUED_CC, "CouplerCheck", line, ""); - extract_value(DCEMUED_EP_max_Vel, "EP_max_Vel", line, ""); - extract_value(DCEMUED_EP_min_Im, "EP_min_Im", line, ""); - extract_value(DCEMUED_EP_delay, "EP_delay", line, ""); + extract_value(DCEMUED_CC, "CouplerCheck", line, "0"); + extract_value(DCEMUED_EP_max_Vel, "EP_max_Vel", line, "0"); + extract_value(DCEMUED_EP_min_Im, "EP_min_Im", line, "0"); + extract_value(DCEMUED_EP_delay, "EP_delay", line, "0"); } @@ -9560,6 +9551,51 @@ void TMoverParameters::LoadFIZ_Power( std::string const &Line ) { LoadFIZ_PowerParamsDecode( SystemPowerSource, "", Line ); } +void TMoverParameters::LoadFIZ_SpeedControl(std::string const &Line) { + // speed control + SpeedCtrl = extract_value("SpeedCtrl", Line) == "Yes"; + if ((!SpeedCtrl) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo > 0)) //backward compatibility + SpeedCtrl = true; + extract_value(SpeedCtrlDelay, "SpeedCtrlDelay", Line, ""); + SpeedCtrlTypeTime = + (extract_value("SpeedCtrlType", Line) == "Time") ? + true : + false; + extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", Line, ""); + + auto speedpresets = Split(extract_value("SpeedButtons", Line), '|'); + int speed_no = 0; + for (auto const &speed : speedpresets) { + SpeedCtrlButtons[speed_no++] = std::stod(speed); + if (speed_no > 9) break; + } + SpeedCtrlUnit.ManualStateOverride = + (extract_value("OverrideManual", Line) == "Yes") ? + true : + false; + + SpeedCtrlUnit.BrakeIntervention = + (extract_value("BrakeIntervention", Line) == "Yes") ? + true : + false; + + extract_value(SpeedCtrlUnit.InitialPower, "InitPwr", Line, ""); + extract_value(SpeedCtrlUnit.FullPowerVelocity, "MaxPwrVel", Line, ""); + extract_value(SpeedCtrlUnit.StartVelocity, "StartVel", Line, ""); + extract_value(SpeedCtrlUnit.VelocityStep, "VelStep", Line, ""); + extract_value(SpeedCtrlUnit.PowerStep, "PwrStep", Line, ""); + extract_value(SpeedCtrlUnit.MinPower, "MinPwr", Line, ""); + extract_value(SpeedCtrlUnit.MaxPower, "MaxPwr", Line, ""); + extract_value(SpeedCtrlUnit.MinVelocity, "MinVel", Line, ""); + extract_value(SpeedCtrlUnit.MaxVelocity, "MaxVel", Line, ""); + extract_value(SpeedCtrlUnit.Offset, "Offset", Line, ""); + extract_value(SpeedCtrlUnit.FactorPpos, "kPpos", Line, ""); + extract_value(SpeedCtrlUnit.FactorPneg, "kPneg", Line, ""); + extract_value(SpeedCtrlUnit.FactorIpos, "kIpos", Line, ""); + extract_value(SpeedCtrlUnit.FactorIneg, "kIneg", Line, ""); + +} + void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { EngineType = LoadFIZ_EngineDecode( extract_value( "EngineType", Input ) ); @@ -10731,13 +10767,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C Battery = true; else if ((CValue1 == 0)) Battery = false; - /* - // TBD: makes no sense to activate alerters in entire consist - if ((Battery) && (ActiveCab != 0) ) - SecuritySystem.Status = SecuritySystem.Status | s_waiting; // aktywacja czuwaka + if ((Battery) && (ActiveCab != 0) /*or (TrainType=dt_EZT)*/) + SecuritySystem.Status = SecuritySystem.Status || s_waiting; // aktywacja czuwaka else SecuritySystem.Status = 0; // wyłączenie czuwaka - */ OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } // else if command='EpFuseSwitch' then {NBMX} @@ -11016,8 +11049,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C } else if (Command == "SpeedCntrl") { - if ((EngineType == TEngineType::ElectricInductionMotor)) - ScndCtrlActualPos = static_cast(round(CValue1)); + if ((EngineType == TEngineType::ElectricInductionMotor)||(SpeedCtrl)) + SpeedCtrlValue = static_cast(round(CValue1)); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "SpeedCtrlUnit.Parking") + { + SpeedCtrlUnit.Parking = static_cast(CValue1); OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "SpringBrakeActivate") @@ -11100,9 +11138,3 @@ double TMoverParameters::ShowCurrentP(int AmpN) const return current; } } - -namespace simulation { - -weights_table Weights; - -} // simulation \ No newline at end of file diff --git a/Train.cpp b/Train.cpp index 8f1b16af..174330b9 100644 --- a/Train.cpp +++ b/Train.cpp @@ -17,7 +17,6 @@ http://mozilla.org/MPL/2.0/. #include "Globals.h" #include "simulation.h" -#include "Event.h" #include "simulationtime.h" #include "Camera.h" #include "Logs.h" @@ -202,9 +201,6 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::alarmchaintoggle, &TTrain::OnCommand_alarmchaintoggle }, { user_command::wheelspinbrakeactivate, &TTrain::OnCommand_wheelspinbrakeactivate }, { user_command::sandboxactivate, &TTrain::OnCommand_sandboxactivate }, - { user_command::autosandboxtoggle, &TTrain::OnCommand_autosandboxtoggle }, - { user_command::autosandboxactivate, &TTrain::OnCommand_autosandboxactivate }, - { user_command::autosandboxdeactivate, &TTrain::OnCommand_autosandboxdeactivate }, { user_command::epbrakecontroltoggle, &TTrain::OnCommand_epbrakecontroltoggle }, { user_command::trainbrakeoperationmodeincrease, &TTrain::OnCommand_trainbrakeoperationmodeincrease }, { user_command::trainbrakeoperationmodedecrease, &TTrain::OnCommand_trainbrakeoperationmodedecrease }, @@ -349,7 +345,6 @@ 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 }, @@ -369,7 +364,20 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::springbrakeshutoffenable, &TTrain::OnCommand_springbrakeshutoffenable }, { user_command::springbrakeshutoffdisable, &TTrain::OnCommand_springbrakeshutoffdisable }, { user_command::springbrakerelease, &TTrain::OnCommand_springbrakerelease }, - { user_command::distancecounteractivate, &TTrain::OnCommand_distancecounteractivate } + { user_command::speedcontrolincrease, &TTrain::OnCommand_speedcontrolincrease }, + { user_command::speedcontroldecrease, &TTrain::OnCommand_speedcontroldecrease }, + { user_command::speedcontrolpowerincrease, &TTrain::OnCommand_speedcontrolpowerincrease }, + { user_command::speedcontrolpowerdecrease, &TTrain::OnCommand_speedcontrolpowerdecrease }, + { user_command::speedcontrolbutton0, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton1, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton2, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton3, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton4, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton5, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton6, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton7, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton8, &TTrain::OnCommand_speedcontrolbutton }, + { user_command::speedcontrolbutton9, &TTrain::OnCommand_speedcontrolbutton }, }; std::vector const TTrain::fPress_labels = { @@ -459,33 +467,30 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d) dictionary_source *TTrain::GetTrainState() { - if( ( mvOccupied == nullptr ) - || ( mvControlled == nullptr ) ) { return nullptr; } + auto const *mover = DynamicObject->MoverParameters; + if( mover == nullptr ) { return nullptr; } auto *dict { new dictionary_source }; if( dict == nullptr ) { return nullptr; } dict->insert( "name", DynamicObject->asName ); - dict->insert( "cab", mvOccupied->ActiveCab ); + dict->insert( "cab", mover->ActiveCab ); // basic systems state data dict->insert( "battery", mvControlled->Battery ); dict->insert( "linebreaker", mvControlled->Mains ); - dict->insert( "main_init", ( mvControlled->MainsInitTimeCountdown < mvControlled->MainsInitTime ) && ( mvControlled->MainsInitTimeCountdown > 0.0 ) ); - dict->insert( "main_ready", ( false == mvControlled->Mains ) && ( fHVoltage > 0.0 ) && ( mvControlled->MainsInitTimeCountdown <= 0.0 ) ); dict->insert( "converter", mvControlled->ConverterFlag ); dict->insert( "converter_overload", mvControlled->ConvOvldFlag ); dict->insert( "compress", mvControlled->CompressorFlag ); - dict->insert( "pant_compressor", mvControlled->PantCompFlag ); - dict->insert( "lights_front", mvOccupied->iLights[ end::front ] ); - dict->insert( "lights_rear", mvOccupied->iLights[ end::rear ] ); // reverser - dict->insert( "direction", mvOccupied->ActiveDir ); + dict->insert( "direction", mover->ActiveDir ); // throttle dict->insert( "mainctrl_pos", mvControlled->MainCtrlPos ); dict->insert( "main_ctrl_actual_pos", mvControlled->MainCtrlActualPos ); dict->insert( "scndctrl_pos", mvControlled->ScndCtrlPos ); dict->insert( "scnd_ctrl_actual_pos", mvControlled->ScndCtrlActualPos ); - dict->insert( "new_speed", mvOccupied->NewSpeed); + dict->insert( "new_speed", mover->NewSpeed); + dict->insert( "speedctrl", mover->SpeedCtrlValue); + dict->insert( "speedctrlpower", mover->SpeedCtrlUnit.DesiredPower); // brakes dict->insert( "manual_brake", ( mvOccupied->ManualBrakePos > 0 ) ); bool const bEP = ( mvControlled->LocHandle->GetCP() > 0.2 ) || ( fEIMParams[ 0 ][ 2 ] > 0.01 ); @@ -505,16 +510,15 @@ dictionary_source *TTrain::GetTrainState() { // other controls dict->insert( "ca", TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) ); dict->insert( "shp", TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ); - dict->insert( "distance_counter", m_distancecounter ); dict->insert( "pantpress", std::abs( mvControlled->PantPress ) ); dict->insert( "universal3", InstrumentLightActive ); dict->insert( "radio_channel", iRadioChannel ); dict->insert( "door_lock", mvOccupied->Doors.lock_enabled ); // movement data - dict->insert( "velocity", std::abs( mvOccupied->Vel ) ); - dict->insert( "tractionforce", std::abs( mvOccupied->Ft ) ); - dict->insert( "slipping_wheels", mvOccupied->SlippingWheels ); - dict->insert( "sanding", mvOccupied->SandDose ); + dict->insert( "velocity", std::abs( mover->Vel ) ); + dict->insert( "tractionforce", std::abs( mover->Ft ) ); + dict->insert( "slipping_wheels", mover->SlippingWheels ); + dict->insert( "sanding", mover->SandDose ); // electric current data dict->insert( "traction_voltage", std::abs( mvControlled->RunningTraction.TractionVoltage ) ); dict->insert( "voltage", std::abs( mvControlled->Voltage ) ); @@ -524,7 +528,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", "engine_temp", "retarder_fill" }; + char const *TXTD[ 10 ] = { "enrot", "nrot", "fill_des", "fill_real", "clutch_des", "clutch_real", "water_temp", "oil_press", "retarder_fill", "res2" }; char const *TXTP[ 3 ] = { "bc", "bp", "sp" }; char const *TXTB[ 2 ] = { "spring_active", "spring_shutoff" }; for( int j = 0; j < 10; ++j ) @@ -574,10 +578,7 @@ dictionary_source *TTrain::GetTrainState() { dict->insert( ( "slip_" + caridx ), bSlip[ i ] ); } // ai state data - auto const *driver { ( - DynamicObject->ctOwner != nullptr ? - DynamicObject->ctOwner : - DynamicObject->Mechanik ) }; + auto const *driver = DynamicObject->Mechanik; dict->insert( "velocity_desired", driver->VelDesired ); dict->insert( "velroad", driver->VelRoad ); @@ -590,7 +591,6 @@ dictionary_source *TTrain::GetTrainState() { driver->TrainTimetable()->serialize( dict ); dict->insert( "train_stationstart", driver->iStationStart ); dict->insert( "train_atpassengerstop", driver->IsAtPassengerStop ); - dict->insert( "train_length", driver->fLength ); // world state data dict->insert( "scenario", Global.SceneryFile ); dict->insert( "hours", static_cast( simulation::Time.data().wHour ) ); @@ -620,7 +620,6 @@ TTrain::get_state() const { btLampkaNadmWent.GetValue(), btLampkaWysRozr.GetValue(), btLampkaOgrzewanieSkladu.GetValue(), - static_cast( iCabn ), btHaslerBrakes.GetValue(), btHaslerCurrent.GetValue(), ( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ), @@ -630,8 +629,7 @@ TTrain::get_state() const { static_cast( mvOccupied->PipePress ), static_cast( mvOccupied->BrakePress ), fHVoltage, - { fHCurrent[ ( mvControlled->TrainType & dt_EZT ) ? 0 : 1 ], fHCurrent[ 2 ], fHCurrent[ 3 ] }, - ggLVoltage.GetValue() + { fHCurrent[ ( mvControlled->TrainType & dt_EZT ) ? 0 : 1 ], fHCurrent[ 2 ], fHCurrent[ 3 ] } }; } @@ -998,20 +996,6 @@ void TTrain::OnCommand_tempomattoggle( TTrain *Train, command_data const &Comman } } -void TTrain::OnCommand_distancecounteractivate( TTrain *Train, command_data const &Command ) { - // NOTE: distance meter activation button is presumed to be of impulse type - if( Command.action == GLFW_PRESS ) { - // visual feedback - Train->ggDistanceCounterButton.UpdateValue( 1.0, Train->dsbSwitch ); - // activate or start anew - Train->m_distancecounter = 0.f; - } - else if( Command.action == GLFW_RELEASE ) { - // visual feedback - Train->ggDistanceCounterButton.UpdateValue( 0.0, Train->dsbSwitch ); - } -} - void TTrain::OnCommand_mucurrentindicatorothersourceactivate( TTrain *Train, command_data const &Command ) { if( Train->ggNextCurrentButton.SubModel == nullptr ) { @@ -1552,7 +1536,7 @@ void TTrain::OnCommand_autosandboxactivate(TTrain *Train, command_data const &Co if (Command.action == GLFW_PRESS) { // only reacting to press, so the switch doesn't flip back and forth if key is held down Train->mvOccupied->SandboxAutoAllow(true); - Train->ggAutoSandButton.UpdateValue(1.0, Train->dsbSwitch); + Train->ggAutoSandAllow.UpdateValue(1.0, Train->dsbSwitch); } }; @@ -1560,7 +1544,7 @@ void TTrain::OnCommand_autosandboxdeactivate(TTrain *Train, command_data const & if (Command.action == GLFW_PRESS) { // only reacting to press, so the switch doesn't flip back and forth if key is held down Train->mvOccupied->SandboxAutoAllow(false); - Train->ggAutoSandButton.UpdateValue(0.0, Train->dsbSwitch); + Train->ggAutoSandAllow.UpdateValue(0.0, Train->dsbSwitch); } }; @@ -2200,7 +2184,7 @@ void TTrain::OnCommand_pantographcompressorvalvetoggle( TTrain *Train, command_d if( ( Train->mvControlled->TrainType == dt_EZT ? ( Train->mvControlled != Train->mvOccupied ) : - ( Train->iCabn != 0 ) ) ) { + ( Train->mvOccupied->ActiveCab != 0 ) ) ) { // tylko w maszynowym return; } @@ -2226,7 +2210,7 @@ void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data if( ( Train->mvControlled->TrainType == dt_EZT ? ( Train->mvControlled != Train->mvOccupied ) : - ( Train->iCabn != 0 ) ) ) { + ( Train->mvOccupied->ActiveCab != 0 ) ) ) { // tylko w maszynowym return; } @@ -3378,7 +3362,7 @@ void TTrain::OnCommand_motordisconnect( TTrain *Train, command_data const &Comma if( ( Train->mvControlled->TrainType == dt_EZT ? ( Train->mvControlled != Train->mvOccupied ) : - ( Train->iCabn != 0 ) ) ) { + ( Train->mvOccupied->ActiveCab != 0 ) ) ) { // tylko w maszynowym return; } @@ -3451,7 +3435,7 @@ void TTrain::OnCommand_motoroverloadrelayreset( TTrain *Train, command_data cons void TTrain::OnCommand_lightspresetactivatenext( TTrain *Train, command_data const &Command ) { if( Train->mvOccupied->LightsPosNo == 0 ) { - // no preset selector + // lights are controlled by preset selector return; } if( Command.action != GLFW_PRESS ) { @@ -3462,22 +3446,15 @@ void TTrain::OnCommand_lightspresetactivatenext( TTrain *Train, command_data con if( ( Train->mvOccupied->LightsPos < Train->mvOccupied->LightsPosNo ) || ( true == Train->mvOccupied->LightsWrap ) ) { // active light preset is stored as value in range 1-LigthPosNo - auto const restartcycle { Train->mvOccupied->LightsPos == Train->mvOccupied->LightsPosNo }; Train->mvOccupied->LightsPos = ( - false == restartcycle ? + Train->mvOccupied->LightsPos < Train->mvOccupied->LightsPosNo ? Train->mvOccupied->LightsPos + 1 : 1 ); // wrap mode Train->SetLights(); // visual feedback if( Train->ggLightsButton.SubModel != nullptr ) { - // HACK: skip submodel animation when restarting cycle, since it plays in the 'wrong' direction - if( false == restartcycle ) { - Train->ggLightsButton.UpdateValue( Train->mvOccupied->LightsPos - 1, Train->dsbSwitch ); - } - else { - Train->ggLightsButton.PutValue( Train->mvOccupied->LightsPos - 1 ); - } + Train->ggLightsButton.UpdateValue( Train->mvOccupied->LightsPos - 1, Train->dsbSwitch ); } } } @@ -3485,7 +3462,7 @@ void TTrain::OnCommand_lightspresetactivatenext( TTrain *Train, command_data con void TTrain::OnCommand_lightspresetactivateprevious( TTrain *Train, command_data const &Command ) { if( Train->mvOccupied->LightsPosNo == 0 ) { - // no preset selector + // lights are controlled by preset selector return; } if( Command.action != GLFW_PRESS ) { @@ -3496,33 +3473,29 @@ void TTrain::OnCommand_lightspresetactivateprevious( TTrain *Train, command_data if( ( Train->mvOccupied->LightsPos > 1 ) || ( true == Train->mvOccupied->LightsWrap ) ) { // active light preset is stored as value in range 1-LigthPosNo - auto const restartcycle { Train->mvOccupied->LightsPos == 1 }; Train->mvOccupied->LightsPos = ( - false == restartcycle ? + Train->mvOccupied->LightsPos > 1 ? Train->mvOccupied->LightsPos - 1 : Train->mvOccupied->LightsPosNo ); // wrap mode Train->SetLights(); // visual feedback if( Train->ggLightsButton.SubModel != nullptr ) { - // HACK: skip submodel animation when restarting cycle, since it plays in the 'wrong' direction - if( false == restartcycle ) { - Train->ggLightsButton.UpdateValue( Train->mvOccupied->LightsPos - 1, Train->dsbSwitch ); - } - else { - Train->ggLightsButton.PutValue( Train->mvOccupied->LightsPos - 1 ); - } + Train->ggLightsButton.UpdateValue( Train->mvOccupied->LightsPos - 1, Train->dsbSwitch ); } } } void TTrain::OnCommand_headlighttoggleleft( TTrain *Train, command_data const &Command ) { - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_left ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_left ) == 0 ) { // turn on OnCommand_headlightenableleft( Train, Command ); } @@ -3541,17 +3514,20 @@ void TTrain::OnCommand_headlightenableleft( TTrain *Train, command_data const &C } if( Command.action == GLFW_PRESS ) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); + + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_left ) != 0 ) { return; } // already enabled + + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_left; // visual feedback Train->ggLeftLightButton.UpdateValue( 1.0, Train->dsbSwitch ); - // implementation - auto const vehicleend { Train->cab_to_end() }; - - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_left ) == 0 ) { - Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_left; - } // if the light is controlled by 3-way switch, disable marker light if( Train->ggLeftEndLightButton.SubModel == nullptr ) { - Train->DynamicObject->iLights[ vehicleend ] &= ~light::redmarker_left; + Train->DynamicObject->iLights[ vehicleside ] &= ~light::redmarker_left; } } } @@ -3565,11 +3541,14 @@ void TTrain::OnCommand_headlightdisableleft( TTrain *Train, command_data const & if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - int const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_left ) == 0 ) { return; } // already disabled + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_left ) == 0 ) { return; } // already disabled - Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_left; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_left; // visual feedback Train->ggLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } @@ -3577,11 +3556,14 @@ void TTrain::OnCommand_headlightdisableleft( TTrain *Train, command_data const & void TTrain::OnCommand_headlighttoggleright( TTrain *Train, command_data const &Command ) { - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_right ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_right ) == 0 ) { // turn on OnCommand_headlightenableright( Train, Command ); } @@ -3600,17 +3582,20 @@ void TTrain::OnCommand_headlightenableright( TTrain *Train, command_data const & } if( Command.action == GLFW_PRESS ) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); + + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_right ) != 0 ) { return; } // already enabled + + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_right; // visual feedback Train->ggRightLightButton.UpdateValue( 1.0, Train->dsbSwitch ); - // implementation - auto const vehicleend { Train->cab_to_end() }; - - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_right ) == 0 ) { - Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_right; - } // if the light is controlled by 3-way switch, disable marker light if( Train->ggRightEndLightButton.SubModel == nullptr ) { - Train->DynamicObject->iLights[ vehicleend ] &= ~light::redmarker_right; + Train->DynamicObject->iLights[ vehicleside ] &= ~light::redmarker_right; } } } @@ -3624,11 +3609,14 @@ void TTrain::OnCommand_headlightdisableright( TTrain *Train, command_data const if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_right ) == 0 ) { return; } // already disabled + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_right ) == 0 ) { return; } // already disabled - Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_right; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_right; // visual feedback Train->ggRightLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } @@ -3636,11 +3624,14 @@ void TTrain::OnCommand_headlightdisableright( TTrain *Train, command_data const void TTrain::OnCommand_headlighttoggleupper( TTrain *Train, command_data const &Command ) { - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_upper ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_upper ) == 0 ) { // turn on OnCommand_headlightenableupper( Train, Command ); } @@ -3660,11 +3651,14 @@ void TTrain::OnCommand_headlightenableupper( TTrain *Train, command_data const & if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_upper ) != 0 ) { return; } // already enabled + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_upper ) != 0 ) { return; } // already enabled - Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_upper; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_upper; // visual feedback Train->ggUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch ); } @@ -3679,11 +3673,14 @@ void TTrain::OnCommand_headlightdisableupper( TTrain *Train, command_data const if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_upper ) == 0 ) { return; } // already disabled + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_upper ) == 0 ) { return; } // already disabled - Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_upper; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_upper; // visual feedback Train->ggUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } @@ -3693,9 +3690,12 @@ void TTrain::OnCommand_redmarkertoggleleft( TTrain *Train, command_data const &C if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_left ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) == 0 ) { // turn on OnCommand_redmarkerenableleft( Train, Command ); } @@ -3715,11 +3715,14 @@ void TTrain::OnCommand_redmarkerenableleft( TTrain *Train, command_data const &C if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_left ) != 0 ) { return; } // already enabled + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) != 0 ) { return; } // already enabled - Train->DynamicObject->iLights[ vehicleend ] ^= light::redmarker_left; + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_left; // visual feedback if( Train->ggLeftEndLightButton.SubModel != nullptr ) { Train->ggLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); @@ -3729,7 +3732,7 @@ void TTrain::OnCommand_redmarkerenableleft( TTrain *Train, command_data const &C // this is crude, but for now will do Train->ggLeftLightButton.UpdateValue( -1.0, Train->dsbSwitch ); // if the light is controlled by 3-way switch, disable the headlight - Train->DynamicObject->iLights[ vehicleend ] &= ~light::headlight_left; + Train->DynamicObject->iLights[ vehicleside ] &= ~light::headlight_left; } } } @@ -3743,11 +3746,14 @@ void TTrain::OnCommand_redmarkerdisableleft( TTrain *Train, command_data const & if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_left ) == 0 ) { return; } // already disabled + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) == 0 ) { return; } // already disabled - Train->DynamicObject->iLights[ vehicleend ] ^= light::redmarker_left; + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_left; // visual feedback if( Train->ggLeftEndLightButton.SubModel != nullptr ) { Train->ggLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); @@ -3764,9 +3770,12 @@ void TTrain::OnCommand_redmarkertoggleright( TTrain *Train, command_data const & if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_right ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) == 0 ) { // turn on OnCommand_redmarkerenableright( Train, Command ); } @@ -3786,11 +3795,14 @@ void TTrain::OnCommand_redmarkerenableright( TTrain *Train, command_data const & if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_right ) != 0 ) { return; } // already enabled + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) != 0 ) { return; } // already enabled - Train->DynamicObject->iLights[ vehicleend ] ^= light::redmarker_right; + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_right; // visual feedback if( Train->ggRightEndLightButton.SubModel != nullptr ) { Train->ggRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); @@ -3800,7 +3812,7 @@ void TTrain::OnCommand_redmarkerenableright( TTrain *Train, command_data const & // this is crude, but for now will do Train->ggRightLightButton.UpdateValue( -1.0, Train->dsbSwitch ); // if the light is controlled by 3-way switch, disable the headlight - Train->DynamicObject->iLights[ vehicleend ] &= ~light::headlight_right; + Train->DynamicObject->iLights[ vehicleside ] &= ~light::headlight_right; } } } @@ -3814,11 +3826,14 @@ void TTrain::OnCommand_redmarkerdisableright( TTrain *Train, command_data const if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleend { Train->cab_to_end() }; + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_right ) == 0 ) { return; } // already disabled + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) == 0 ) { return; } // already disabled - Train->DynamicObject->iLights[ vehicleend ] ^= light::redmarker_right; + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_right; // visual feedback if( Train->ggRightEndLightButton.SubModel != nullptr ) { Train->ggRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); @@ -3838,22 +3853,23 @@ void TTrain::OnCommand_headlighttogglerearleft( TTrain *Train, command_data cons return; } + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::rear : + end::front ); + if( Command.action == GLFW_PRESS ) { // NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc - auto const vehicleotherend { ( - Train->cab_to_end() == end::front ? - end::rear : - end::front ) }; // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::headlight_right ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_right ) == 0 ) { // turn on - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_right; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_right; // visual feedback Train->ggRearLeftLightButton.UpdateValue( 1.0, Train->dsbSwitch ); } else { //turn off - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_right; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_right; // visual feedback Train->ggRearLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } @@ -3867,22 +3883,23 @@ void TTrain::OnCommand_headlighttogglerearright( TTrain *Train, command_data con return; } + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::rear : + end::front ); + if( Command.action == GLFW_PRESS ) { // NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc - auto const vehicleotherend { ( - Train->cab_to_end() == end::front ? - end::rear : - end::front ) }; // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::headlight_left ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_left ) == 0 ) { // turn on - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_left; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_left; // visual feedback Train->ggRearRightLightButton.UpdateValue( 1.0, Train->dsbSwitch ); } else { //turn off - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_left; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_left; // visual feedback Train->ggRearRightLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } @@ -3896,21 +3913,22 @@ void TTrain::OnCommand_headlighttogglerearupper( TTrain *Train, command_data con return; } + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::rear : + end::front ); + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - auto const vehicleotherend { ( - Train->cab_to_end() == end::front ? - end::rear : - end::front ) }; - if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::headlight_upper ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_upper ) == 0 ) { // turn on - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_upper; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_upper; // visual feedback Train->ggRearUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch ); } else { //turn off - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_upper; + Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_upper; // visual feedback Train->ggRearUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } @@ -3924,22 +3942,23 @@ void TTrain::OnCommand_redmarkertogglerearleft( TTrain *Train, command_data cons return; } + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::rear : + end::front ); + if( Command.action == GLFW_PRESS ) { // NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc - auto const vehicleotherend { ( - Train->cab_to_end() == end::front ? - end::rear : - end::front ) }; // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::redmarker_right ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) == 0 ) { // turn on - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::redmarker_right; + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_right; // visual feedback Train->ggRearLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); } else { //turn off - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::redmarker_right; + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_right; // visual feedback Train->ggRearLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } @@ -3953,22 +3972,23 @@ void TTrain::OnCommand_redmarkertogglerearright( TTrain *Train, command_data con return; } + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + end::rear : + end::front ); + if( Command.action == GLFW_PRESS ) { // NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc - auto const vehicleotherend { ( - Train->cab_to_end() == end::front ? - end::rear : - end::front ) }; // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::redmarker_left ) == 0 ) { + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) == 0 ) { // turn on - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::redmarker_left; + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_left; // visual feedback Train->ggRearRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); } else { //turn off - Train->DynamicObject->iLights[ vehicleotherend ] ^= light::redmarker_left; + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_left; // visual feedback Train->ggRearRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } @@ -4481,6 +4501,80 @@ void TTrain::OnCommand_springbrakerelease(TTrain *Train, command_data const &Com } }; +void TTrain::OnCommand_speedcontrolincrease(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 + Train->mvOccupied->SpeedCtrlInc(); + // visual feedback + Train->ggSpeedControlIncreaseButton.UpdateValue(1.0, Train->dsbSwitch); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggSpeedControlIncreaseButton.UpdateValue(0.0, Train->dsbSwitch); + } +}; + +void TTrain::OnCommand_speedcontroldecrease(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 + Train->mvOccupied->SpeedCtrlDec(); + // visual feedback + Train->ggSpeedControlDecreaseButton.UpdateValue(1.0, Train->dsbSwitch); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggSpeedControlDecreaseButton.UpdateValue(0.0, Train->dsbSwitch); + } +}; + +void TTrain::OnCommand_speedcontrolpowerincrease(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 + Train->mvOccupied->SpeedCtrlPowerInc(); + // visual feedback + Train->ggSpeedControlPowerIncreaseButton.UpdateValue(1.0, Train->dsbSwitch); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggSpeedControlPowerIncreaseButton.UpdateValue(0.0, Train->dsbSwitch); + } +}; + +void TTrain::OnCommand_speedcontrolpowerdecrease(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 + Train->mvOccupied->SpeedCtrlPowerDec(); + // visual feedback + Train->ggSpeedControlPowerDecreaseButton.UpdateValue(1.0, Train->dsbSwitch); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggSpeedControlPowerDecreaseButton.UpdateValue(0.0, Train->dsbSwitch); + } +}; + +void TTrain::OnCommand_speedcontrolbutton(TTrain *Train, command_data const &Command) { + + auto const itemindex = static_cast(Command.command) - static_cast(user_command::speedcontrolbutton0); + auto &item = Train->ggSpeedCtrlButtons[itemindex]; + + if (Command.action == GLFW_PRESS) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + Train->mvOccupied->SpeedCtrlButton(itemindex); + // visual feedback + Train->ggSpeedCtrlButtons[itemindex].UpdateValue(1.0, Train->dsbSwitch); + } + else if (Command.action == GLFW_RELEASE) { + // release + // visual feedback + Train->ggSpeedCtrlButtons[itemindex].UpdateValue(0.0, Train->dsbSwitch); + } +}; + void TTrain::OnCommand_doorlocktoggle( TTrain *Train, command_data const &Command ) { if( Train->ggDoorSignallingButton.SubModel == nullptr ) { @@ -4514,8 +4608,9 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman if( Command.action == GLFW_PRESS ) { // NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors if( false == ( - ( Train->ggDoorLeftButton.GetDesiredValue() > 0.5 ) - || ( Train->ggDoorLeftOnButton.GetDesiredValue() > 0.5 ) ) ) { + Train->mvOccupied->ActiveCab == 1 ? + Train->mvOccupied->Doors.instances[side::left].is_opening || Train->mvOccupied->Doors.instances[ side::left ].is_open : + Train->mvOccupied->Doors.instances[side::right].is_opening || Train->mvOccupied->Doors.instances[ side::right ].is_open ) ) { // open OnCommand_dooropenleft( Train, Command ); } @@ -4535,8 +4630,9 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman else if( Command.action == GLFW_RELEASE ) { if( true == ( - ( Train->ggDoorLeftButton.GetDesiredValue() > 0.5 ) - || ( Train->ggDoorLeftOnButton.GetDesiredValue() > 0.5 ) ) ) { + Train->mvOccupied->ActiveCab == 1 ? + Train->mvOccupied->Doors.instances[side::left].is_opening || Train->mvOccupied->Doors.instances[ side::left ].is_open : + Train->mvOccupied->Doors.instances[side::right].is_opening || Train->mvOccupied->Doors.instances[ side::right ].is_open ) ) { // open if( ( Train->mvOccupied->Doors.has_autowarning ) && ( Train->mvOccupied->DepartureSignal ) ) { @@ -4584,7 +4680,7 @@ void TTrain::OnCommand_doorpermitleft( TTrain *Train, command_data const &Comman if( Command.action == GLFW_PRESS ) { auto const side { ( - Train->cab_to_end() == end::front ? + Train->mvOccupied->ActiveCab == 1 ? side::left : side::right ) }; @@ -4596,7 +4692,7 @@ void TTrain::OnCommand_doorpermitleft( TTrain *Train, command_data const &Comman } else { // two-state switch - auto const newstate { !( Train->ggDoorLeftPermitButton.GetDesiredValue() > 0.5 ) }; + auto const newstate { !( Train->mvOccupied->Doors.instances[ side ].open_permit ) }; Train->mvOccupied->PermitDoors( side, newstate ); // visual feedback @@ -4620,7 +4716,7 @@ void TTrain::OnCommand_doorpermitright( TTrain *Train, command_data const &Comma if( Command.action == GLFW_PRESS ) { auto const side { ( - Train->cab_to_end() == end::front ? + Train->mvOccupied->ActiveCab == 1 ? side::right : side::left ) }; @@ -4632,7 +4728,7 @@ void TTrain::OnCommand_doorpermitright( TTrain *Train, command_data const &Comma } else { // two-state switch - auto const newstate { !( Train->ggDoorRightPermitButton.GetDesiredValue() > 0.5 ) }; + auto const newstate { !( Train->mvOccupied->Doors.instances[ side ].open_permit ) }; Train->mvOccupied->PermitDoors( side, newstate ); // visual feedback @@ -4686,7 +4782,7 @@ void TTrain::OnCommand_dooropenleft( TTrain *Train, command_data const &Command if( Command.action == GLFW_PRESS ) { Train->mvOccupied->OperateDoors( - ( Train->cab_to_end() == end::front ? + ( Train->mvOccupied->ActiveCab == 1 ? side::left : side::right ), true ); @@ -4732,7 +4828,7 @@ void TTrain::OnCommand_doorcloseleft( TTrain *Train, command_data const &Command else { // TODO: move door opening/closing to the update, so the switch animation doesn't hinge on door working Train->mvOccupied->OperateDoors( - ( Train->cab_to_end() == end::front ? + ( Train->mvOccupied->ActiveCab == 1 ? side::left : side::right ), false ); @@ -4754,7 +4850,7 @@ void TTrain::OnCommand_doorcloseleft( TTrain *Train, command_data const &Command Train->mvOccupied->signal_departure( false ); // now we can actually close the door Train->mvOccupied->OperateDoors( - ( Train->cab_to_end() == end::front ? + ( Train->mvOccupied->ActiveCab == 1 ? side::left : side::right ), false ); @@ -4771,8 +4867,9 @@ void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Comma if( Command.action == GLFW_PRESS ) { // NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors if( false == ( - ( Train->ggDoorRightButton.GetDesiredValue() > 0.5 ) - || ( Train->ggDoorRightOnButton.GetDesiredValue() > 0.5 ) ) ) { + Train->mvOccupied->ActiveCab == 1 ? + Train->mvOccupied->Doors.instances[side::right].is_opening || Train->mvOccupied->Doors.instances[ side::right ].is_open : + Train->mvOccupied->Doors.instances[side::left].is_opening || Train->mvOccupied->Doors.instances[ side::left ].is_open ) ) { // open OnCommand_dooropenright( Train, Command ); } @@ -4792,8 +4889,9 @@ void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Comma else if( Command.action == GLFW_RELEASE ) { if( true == ( - ( Train->ggDoorRightButton.GetDesiredValue() > 0.5 ) - || ( Train->ggDoorRightOnButton.GetDesiredValue() > 0.5 ) ) ) { + Train->mvOccupied->ActiveCab == 1 ? + Train->mvOccupied->Doors.instances[side::right].is_opening || Train->mvOccupied->Doors.instances[ side::right ].is_open : + Train->mvOccupied->Doors.instances[side::left].is_opening || Train->mvOccupied->Doors.instances[ side::left ].is_open ) ) { // open if( ( Train->mvOccupied->Doors.has_autowarning ) && ( Train->mvOccupied->DepartureSignal ) ) { @@ -4851,7 +4949,7 @@ void TTrain::OnCommand_dooropenright( TTrain *Train, command_data const &Command if( Command.action == GLFW_PRESS ) { Train->mvOccupied->OperateDoors( - ( Train->cab_to_end() == end::front ? + ( Train->mvOccupied->ActiveCab == 1 ? side::right : side::left ), true ); @@ -4896,7 +4994,7 @@ void TTrain::OnCommand_doorcloseright( TTrain *Train, command_data const &Comman } else { Train->mvOccupied->OperateDoors( - ( Train->cab_to_end() == end::front ? + ( Train->mvOccupied->ActiveCab == 1 ? side::right : side::left ), false ); @@ -4918,7 +5016,7 @@ void TTrain::OnCommand_doorcloseright( TTrain *Train, command_data const &Comman Train->mvOccupied->signal_departure( false ); // now we can actually close the door Train->mvOccupied->OperateDoors( - ( Train->cab_to_end() == end::front ? + ( Train->mvOccupied->ActiveCab == 1 ? side::right : side::left ), false ); @@ -5271,7 +5369,6 @@ 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(); } @@ -5284,44 +5381,15 @@ 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 ) { - auto const *owner { ( - Train->DynamicObject->ctOwner != nullptr ? - Train->DynamicObject->ctOwner : - Train->DynamicObject->Mechanik ) }; - auto const movedirection { 1 }; - if( false == Train->CabChange( movedirection ) ) { - auto const exitdirection { ( - movedirection > 0 ? - end::front : - end::rear ) }; - if( TestFlag( Train->DynamicObject->MoverParameters->Couplers[ exitdirection ].CouplingFlag, coupling::gangway ) ) { + if( false == Train->CabChange( 1 ) ) { + if( TestFlag( Train->DynamicObject->MoverParameters->Couplers[ end::front ].CouplingFlag, coupling::gangway ) ) { // przejscie do nastepnego pojazdu - Global.changeDynObj = ( - exitdirection == end::front ? - Train->DynamicObject->PrevConnected() : - Train->DynamicObject->NextConnected() ); + Global.changeDynObj = Train->DynamicObject->PrevConnected(); Global.changeDynObj->MoverParameters->ActiveCab = ( - Train->DynamicObject->MoverParameters->Neighbours[ exitdirection ].vehicle_end ? + Train->DynamicObject->MoverParameters->Neighbours[end::front].vehicle_end ? -1 : 1 ); } @@ -5336,25 +5404,12 @@ void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Comm void TTrain::OnCommand_cabchangebackward( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_PRESS ) { - auto const *owner { ( - Train->DynamicObject->ctOwner != nullptr ? - Train->DynamicObject->ctOwner : - Train->DynamicObject->Mechanik ) }; - auto const movedirection { -1 }; - if( false == Train->CabChange( movedirection ) ) { - // current vehicle doesn't extend any farther in this direction, check if we there's one connected we can move to - auto const exitdirection { ( - movedirection > 0 ? - end::front : - end::rear ) }; - if( TestFlag( Train->DynamicObject->MoverParameters->Couplers[ exitdirection ].CouplingFlag, coupling::gangway ) ) { + if( false == Train->CabChange( -1 ) ) { + if( TestFlag( Train->DynamicObject->MoverParameters->Couplers[ end::rear ].CouplingFlag, coupling::gangway ) ) { // przejscie do nastepnego pojazdu - Global.changeDynObj = ( - exitdirection == end::front ? - Train->DynamicObject->PrevConnected() : - Train->DynamicObject->NextConnected() ); + Global.changeDynObj = Train->DynamicObject->NextConnected(); Global.changeDynObj->MoverParameters->ActiveCab = ( - Train->DynamicObject->MoverParameters->Neighbours[ exitdirection ].vehicle_end ? + Train->DynamicObject->MoverParameters->Neighbours[end::rear].vehicle_end ? -1 : 1 ); } @@ -5409,11 +5464,10 @@ bool TTrain::Update( double const Deltatime ) if( ( ggMainButton.GetDesiredValue() > 0.95 ) || ( ggMainOnButton.GetDesiredValue() > 0.95 ) ) { // keep track of period the line breaker button is held down, to determine when/if circuit closes - if( ( mvControlled->MainsInitTimeCountdown <= 0.0 ) - && ( ( fHVoltage > 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) - || ( ( mvControlled->EngineType != TEngineType::ElectricSeriesMotor ) - && ( mvControlled->EngineType != TEngineType::ElectricInductionMotor ) - && ( true == mvControlled->Battery ) ) ) ) { + if( ( fHVoltage > 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) + || ( ( mvControlled->EngineType != TEngineType::ElectricSeriesMotor ) + && ( mvControlled->EngineType != TEngineType::ElectricInductionMotor ) + && ( true == mvControlled->Battery ) ) ) { // prevent the switch from working if there's no power // TODO: consider whether it makes sense for diesel engines and such fMainRelayTimer += Deltatime; @@ -5639,9 +5693,7 @@ bool TTrain::Update( double const Deltatime ) in++; iPowerNo = in; } - if ((in < 8) - && ((p->MoverParameters->EngineType==TEngineType::DieselEngine) - ||(p->MoverParameters->EngineType==TEngineType::DieselElectric))) + if ((in < 8) && (p->MoverParameters->EngineType==TEngineType::DieselEngine)) { fDieselParams[1 + in][0] = p->MoverParameters->enrot*60; fDieselParams[1 + in][1] = p->MoverParameters->nrot; @@ -5651,8 +5703,8 @@ bool TTrain::Update( double const Deltatime ) 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->dizel_heat.Ts; - fDieselParams[1 + in][9] = p->MoverParameters->hydro_R_Fill; + fDieselParams[1 + in][8] = p->MoverParameters->hydro_R_Fill; + //fDieselParams[1 + in][9] = p->MoverParameters-> bMains[in] = p->MoverParameters->Mains; fCntVol[in] = p->MoverParameters->BatteryVoltage; bFuse[in] = p->MoverParameters->FuseFlag; @@ -5762,13 +5814,14 @@ bool TTrain::Update( double const Deltatime ) // youBy - prad w drugim czlonie: galaz lub calosc { - TDynamicObject *tmp { nullptr }; + TDynamicObject *tmp; + tmp = NULL; if (DynamicObject->NextConnected()) - if ((TestFlag(mvControlled->Couplers[end::rear].CouplingFlag, ctrain_controll)) && + if ((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) && (mvOccupied->ActiveCab == 1)) tmp = DynamicObject->NextConnected(); if (DynamicObject->PrevConnected()) - if ((TestFlag(mvControlled->Couplers[end::front].CouplingFlag, ctrain_controll)) && + if ((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) && (mvOccupied->ActiveCab == -1)) tmp = DynamicObject->PrevConnected(); if( tmp ) { @@ -5931,7 +5984,7 @@ bool TTrain::Update( double const Deltatime ) } } // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa - if( mvOccupied->SecuritySystem.Status != s_off ) { + if( mvOccupied->SecuritySystem.Status > 0 ) { if( fBlinkTimer > fCzuwakBlink ) fBlinkTimer = -fCzuwakBlink; else @@ -5957,10 +6010,9 @@ bool TTrain::Update( double const Deltatime ) || (true == mvControlled->Mains) ) ? true : false ) ); + // NOTE: 'off' variant uses the same test, but opposite resulting states btLampkaWylSzybkiOff.Turn( - ( ( ( mvControlled->MainsInitTimeCountdown > 0.0 ) -// || ( fHVoltage == 0.0 ) - || ( m_linebreakerstate == 2 ) + ( ( ( m_linebreakerstate == 2 ) || ( true == mvControlled->Mains ) ) ? false : true ) ); @@ -5978,18 +6030,18 @@ bool TTrain::Update( double const Deltatime ) ( true == mvControlled->ResistorsFlagCheck() ) || ( mvControlled->MainCtrlActualPos == 0 ) ); // do EU04 - btLampkaStyczn.Turn( - mvControlled->StLinFlag ? - false : - mvOccupied->BrakePress < 1.0 ); // mozna prowadzic rozruch - - if( ( ( mvControlled->ActiveCab == 1 ) && ( TestFlag( mvControlled->Couplers[ end::rear ].CouplingFlag, coupling::control ) ) ) - || ( ( mvControlled->ActiveCab == -1 ) && ( TestFlag( mvControlled->Couplers[ end::front ].CouplingFlag, coupling::control ) ) ) ) { - btLampkaUkrotnienie.Turn( true ); + if( mvControlled->StLinFlag ) { + btLampkaStyczn.Turn( false ); } else { - btLampkaUkrotnienie.Turn( false ); + // mozna prowadzic rozruch + btLampkaStyczn.Turn( mvOccupied->BrakePress < 1.0 ); } + if( ( ( TestFlag( mvControlled->Couplers[ end::rear ].CouplingFlag, coupling::control ) ) && ( mvControlled->CabNo == 1 ) ) + || ( ( TestFlag( mvControlled->Couplers[ end::front ].CouplingFlag, coupling::control ) ) && ( mvControlled->CabNo == -1 ) ) ) + btLampkaUkrotnienie.Turn( true ); + else + btLampkaUkrotnienie.Turn( false ); // if // ((TestFlag(mvControlled->BrakeStatus,+b_Rused+b_Ractive)))//Lampka drugiego stopnia hamowania @@ -6076,8 +6128,8 @@ bool TTrain::Update( double const Deltatime ) btLampkaRadioStop.Turn( mvOccupied->Radio && mvOccupied->RadioStopFlag ); btLampkaHamulecReczny.Turn(mvOccupied->ManualBrakePos > 0); // NBMX wrzesien 2003 - drzwi oraz sygnał odjazdu - btLampkaDoorLeft.Turn( DynamicObject->Mechanik->IsAnyDoorOpen[ ( cab_to_end() == end::front ? side::left : side::right ) ] ); - btLampkaDoorRight.Turn( DynamicObject->Mechanik->IsAnyDoorOpen[ ( cab_to_end() == end::front ? side::right : side::left ) ] ); + btLampkaDoorLeft.Turn( DynamicObject->Mechanik->IsAnyDoorOpen[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ] ); + btLampkaDoorRight.Turn( DynamicObject->Mechanik->IsAnyDoorOpen[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ] ); btLampkaDoors.Turn( DynamicObject->Mechanik->IsAnyDoorOpen[ side::right ] || DynamicObject->Mechanik->IsAnyDoorOpen[ side::left ] ); btLampkaBlokadaDrzwi.Turn( mvOccupied->Doors.is_locked ); btLampkaDoorLockOff.Turn( false == mvOccupied->Doors.lock_enabled ); @@ -6108,7 +6160,6 @@ bool TTrain::Update( double const Deltatime ) btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ end::front ].is_active ) && ( mvControlled->MotorBlowers[ end::rear ].is_active ) ); btLampkaCoolingFans.Turn( mvControlled->RventRot > 1.0 ); btLampkaTempomat.Turn( mvControlled->ScndCtrlPos > 0 ); - btLampkaDistanceCounter.Turn( m_distancecounter >= 0.f ); // universal devices state indicators for( auto idx = 0; idx < btUniversals.size(); ++idx ) { btUniversals[ idx ].Turn( ggUniversals[ idx ].GetValue() > 0.5 ); @@ -6173,7 +6224,6 @@ bool TTrain::Update( double const Deltatime ) btLampkaMotorBlowers.Turn( false ); btLampkaCoolingFans.Turn( false ); btLampkaTempomat.Turn( false ); - btLampkaDistanceCounter.Turn( false ); // universal devices state indicators for( auto &universal : btUniversals ) { universal.Turn( false ); @@ -6181,8 +6231,10 @@ bool TTrain::Update( double const Deltatime ) } { // yB - wskazniki drugiego czlonu - TDynamicObject *tmp { nullptr }; //=mvControlled->mvSecond; //Ra 2014-07: trzeba to jeszcze wyjąć z kabiny... + TDynamicObject *tmp; //=mvControlled->mvSecond; //Ra 2014-07: trzeba to + // jeszcze wyjąć z kabiny... // Ra 2014-07: no nie ma potrzeby szukać tego w każdej klatce + tmp = NULL; if ((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) && (mvOccupied->ActiveCab > 0)) tmp = DynamicObject->NextConnected(); @@ -6196,10 +6248,7 @@ bool TTrain::Update( double const Deltatime ) auto const *mover { tmp->MoverParameters }; btLampkaWylSzybkiB.Turn( mover->Mains ); - btLampkaWylSzybkiBOff.Turn( - ( false == mover->Mains ) - && ( mover->MainsInitTimeCountdown <= 0.0 ) - /*&& ( fHVoltage != 0.0 )*/ ); + btLampkaWylSzybkiBOff.Turn( false == mover->Mains ); btLampkaOporyB.Turn(mover->ResistorsFlagCheck()); btLampkaBezoporowaB.Turn( @@ -6261,13 +6310,10 @@ bool TTrain::Update( double const Deltatime ) if( ggJointCtrl.SubModel != nullptr ) { // joint master controller moves forward to adjust power and backward to adjust brakes auto const brakerangemultiplier { - /* NOTE: scaling disabled as it was conflicting with associating sounds with control positions ( mvControlled->CoupledCtrl ? mvControlled->MainCtrlPosNo + mvControlled->ScndCtrlPosNo : mvControlled->MainCtrlPosNo ) - / static_cast(LocalBrakePosNo) - */ - 1 }; + / static_cast(LocalBrakePosNo) }; ggJointCtrl.UpdateValue( ( mvOccupied->LocalBrakePosA > 0.0 ? mvOccupied->LocalBrakePosA * LocalBrakePosNo * -1 * brakerangemultiplier : mvControlled->CoupledCtrl ? double( mvControlled->MainCtrlPos + mvControlled->ScndCtrlPos ) : @@ -6317,7 +6363,6 @@ bool TTrain::Update( double const Deltatime ) ggScndCtrl.Update(); } ggScndCtrlButton.Update(); - ggDistanceCounterButton.Update(); if (ggDirKey.SubModel) { if (mvControlled->TrainType != dt_EZT) ggDirKey.UpdateValue( @@ -6456,7 +6501,6 @@ bool TTrain::Update( double const Deltatime ) ggUniveralBrakeButton3.Update(); ggAntiSlipButton.Update(); ggSandButton.Update(); - ggAutoSandButton.Update(); ggFuseButton.Update(); ggConverterFuseButton.Update(); ggStLinOffButton.Update(); @@ -6466,7 +6510,6 @@ bool TTrain::Update( double const Deltatime ) ggRadioChannelNext.Update(); ggRadioStop.Update(); ggRadioTest.Update(); - ggRadioCall3.Update(); ggDepartureSignalButton.Update(); ggPantFrontButton.Update(); @@ -6507,6 +6550,15 @@ bool TTrain::Update( double const Deltatime ) ggHelperButton.UpdateValue( DynamicObject->Mechanik->HelperState ); } ggHelperButton.Update(); + + ggSpeedControlIncreaseButton.Update(); + ggSpeedControlDecreaseButton.Update(); + ggSpeedControlPowerIncreaseButton.Update(); + ggSpeedControlDecreaseButton.Update(); + for (auto &speedctrlbutton : ggSpeedCtrlButtons) { + speedctrlbutton.Update(); + } + for( auto &universal : ggUniversals ) { universal.Update(); } @@ -6614,7 +6666,7 @@ bool TTrain::Update( double const Deltatime ) && ( false == FreeFlyModeFlag ) ) { // don't bother if we're outside fScreenTimer = 0.f; for( auto const &screen : m_screens ) { - Application.request( { screen.first, GetTrainState(), GfxRenderer->Texture( screen.second ).id } ); + Application.request( { screen.first, GetTrainState(), GfxRenderer.Texture( screen.second ).id } ); } } // sounds @@ -6811,7 +6863,7 @@ TTrain::update_sounds( double const Deltatime ) { } // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa - if (mvOccupied->SecuritySystem.Status != s_off ) { + if (mvOccupied->SecuritySystem.Status > 0) { // hunter-091012: rozdzielenie alarmow if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) { @@ -6854,28 +6906,6 @@ TTrain::update_sounds( double const Deltatime ) { else if( fTachoCount < 1.f ) { dsbHasler.stop(); } - - // power-reliant sounds - if( mvControlled->Battery || mvControlled->ConverterFlag ) { - // distance meter alert - auto const *owner { ( - DynamicObject->ctOwner != nullptr ? - DynamicObject->ctOwner : - DynamicObject->Mechanik ) }; - if( m_distancecounter > owner->fLength ) { - // play assigned sound if the train travelled its full length since meter activation - // TBD: check all combinations of directions and active cab - m_distancecounter = -1.f; // turn off the meter after its task is done - m_distancecounterclear - .pitch( m_distancecounterclear.m_frequencyoffset + m_distancecounterclear.m_frequencyfactor ) - .gain( m_distancecounterclear.m_amplitudeoffset + m_distancecounterclear.m_amplitudefactor ) - .play( sound_flags::exclusive ); - } - } - else { - // stop power-reliant sounds if power is cut - m_distancecounterclear.stop(); - } } void TTrain::update_sounds_runningnoise( sound_source &Sound ) { @@ -6963,14 +6993,6 @@ void TTrain::update_sounds_radio() { } } -void TTrain::add_distance( double const Distance ) { - - auto const meterenabled { ( true == ( m_distancecounter >= 0 ) ) && ( mvControlled->Battery || mvControlled->ConverterFlag ) }; - - if( true == meterenabled ) { m_distancecounter += Distance * Occupied()->ActiveCab; } - else { m_distancecounter = -1.f; } -} - bool TTrain::CabChange(int iDirection) { // McZapkie-090902: zmiana kabiny 1->0->2 i z powrotem if( ( DynamicObject->Mechanik == nullptr ) @@ -7060,12 +7082,6 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName) dsbSlipAlarm.deserialize( parser, sound_type::single ); dsbSlipAlarm.owner( DynamicObject ); } - else if (token == "distancecounter:") - { - // distance meter 'good to go' sound - m_distancecounterclear.deserialize( parser, sound_type::single ); - m_distancecounterclear.owner( DynamicObject ); - } else if (token == "tachoclock:") { // cykanie rejestratora: @@ -7191,7 +7207,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) &dsbSwitch, &dsbPneumaticSwitch, &rsHiss, &rsHissU, &rsHissE, &rsHissX, &rsHissT, &rsSBHiss, &rsSBHissU, &rsFadeSound, &rsRunningNoise, &rsHuntingNoise, - &dsbHasler, &dsbBuzzer, &dsbSlipAlarm, &m_distancecounterclear, &m_radiosound, &m_radiostop + &dsbHasler, &dsbBuzzer, &dsbSlipAlarm, &m_radiosound, &m_radiostop }; for( auto sound : sounds ) { sound->offset( nullvector ); @@ -7421,7 +7437,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) ( substr_path(renderername).empty() ? // supply vehicle folder as path if none is provided DynamicObject->asBaseDir + renderername : renderername ), - GfxRenderer->Material( material ).texture1 ); + GfxRenderer.Material( material ).texture1 ); } // btLampkaUnknown.Init("unknown",mdKabina,false); } while (token != ""); @@ -7451,10 +7467,6 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) if( dsbBuzzer.offset() == nullvector ) { dsbBuzzer.offset( btLampkaCzuwaka.model_offset() ); } - // HACK: alerter is likely to be located somewhere near computer displays - if( m_distancecounterclear.offset() == nullvector ) { - m_distancecounterclear.offset( btLampkaCzuwaka.model_offset() ); - } // radio has two potential items which can provide the position if( m_radiosound.offset() == nullvector ) { m_radiosound.offset( btLampkaRadio.model_offset() ); @@ -7675,7 +7687,6 @@ void TTrain::clear_cab_controls() ggMainCtrlAct.Clear(); ggScndCtrl.Clear(); ggScndCtrlButton.Clear(); - ggDistanceCounterButton.Clear(); ggDirKey.Clear(); ggBrakeCtrl.Clear(); ggLocalBrake.Clear(); @@ -7697,7 +7708,6 @@ void TTrain::clear_cab_controls() ggUniveralBrakeButton2.Clear(); ggUniveralBrakeButton3.Clear(); ggSandButton.Clear(); - ggAutoSandButton.Clear(); ggAntiSlipButton.Clear(); ggHornButton.Clear(); ggHornLowButton.Clear(); @@ -7705,6 +7715,13 @@ void TTrain::clear_cab_controls() ggWhistleButton.Clear(); ggHelperButton.Clear(); ggNextCurrentButton.Clear(); + ggSpeedControlIncreaseButton.Clear(); + ggSpeedControlDecreaseButton.Clear(); + ggSpeedControlPowerIncreaseButton.Clear(); + ggSpeedControlDecreaseButton.Clear(); + for (auto &speedctrlbutton : ggSpeedCtrlButtons) { + speedctrlbutton.Clear(); + } for( auto &universal : ggUniversals ) { universal.Clear(); } @@ -7725,7 +7742,6 @@ void TTrain::clear_cab_controls() ggRadioChannelNext.Clear(); ggRadioStop.Clear(); ggRadioTest.Clear(); - ggRadioCall3.Clear(); ggDoorLeftPermitButton.Clear(); ggDoorRightPermitButton.Clear(); ggDoorPermitPresetButton.Clear(); @@ -7860,7 +7876,6 @@ void TTrain::clear_cab_controls() btLampkaMotorBlowers.Clear(); btLampkaCoolingFans.Clear(); btLampkaTempomat.Clear(); - btLampkaDistanceCounter.Clear(); ggLeftLightButton.Clear(); ggRightLightButton.Clear(); @@ -7994,18 +8009,21 @@ void TTrain::set_cab_controls( int const Cab ) { // lights ggLightsButton.PutValue( mvOccupied->LightsPos - 1 ); - auto const vehicleend { cab_to_end() }; + int const vehicleside = + ( mvOccupied->ActiveCab == 1 ? + end::front : + end::rear ); - if( ( DynamicObject->iLights[ vehicleend ] & light::headlight_left ) != 0 ) { + if( ( DynamicObject->iLights[ vehicleside ] & light::headlight_left ) != 0 ) { ggLeftLightButton.PutValue( 1.f ); } - if( ( DynamicObject->iLights[ vehicleend ] & light::headlight_right ) != 0 ) { + if( ( DynamicObject->iLights[ vehicleside ] & light::headlight_right ) != 0 ) { ggRightLightButton.PutValue( 1.f ); } - if( ( DynamicObject->iLights[ vehicleend ] & light::headlight_upper ) != 0 ) { + if( ( DynamicObject->iLights[ vehicleside ] & light::headlight_upper ) != 0 ) { ggUpperLightButton.PutValue( 1.f ); } - if( ( DynamicObject->iLights[ vehicleend ] & light::redmarker_left ) != 0 ) { + if( ( DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) != 0 ) { if( ggLeftEndLightButton.SubModel != nullptr ) { ggLeftEndLightButton.PutValue( 1.f ); } @@ -8013,7 +8031,7 @@ void TTrain::set_cab_controls( int const Cab ) { ggLeftLightButton.PutValue( -1.f ); } } - if( ( DynamicObject->iLights[ vehicleend ] & light::redmarker_right ) != 0 ) { + if( ( DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) != 0 ) { if( ggRightEndLightButton.SubModel != nullptr ) { ggRightEndLightButton.PutValue( 1.f ); } @@ -8046,15 +8064,15 @@ void TTrain::set_cab_controls( int const Cab ) { 0.f ) ); // doors permits if( ggDoorLeftPermitButton.type() != TGaugeType::push ) { - ggDoorLeftPermitButton.PutValue( mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::left : side::right ) ].open_permit ? 1.f : 0.f ); + ggDoorLeftPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit ? 1.f : 0.f ); } if( ggDoorRightPermitButton.type() != TGaugeType::push ) { - ggDoorRightPermitButton.PutValue( mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::right : side::left ) ].open_permit ? 1.f : 0.f ); + ggDoorRightPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit ? 1.f : 0.f ); } ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset ); // door controls - ggDoorLeftButton.PutValue( mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::left : side::right ) ].is_closed ? 0.f : 1.f ); - ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::right : side::left ) ].is_closed ? 0.f : 1.f ); + ggDoorLeftButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].is_closed ? 0.f : 1.f ); + ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].is_closed ? 0.f : 1.f ); // door lock ggDoorSignallingButton.PutValue( mvOccupied->Doors.lock_enabled ? @@ -8172,14 +8190,7 @@ void TTrain::set_cab_controls( int const Cab ) { 1.f : 0.f ); } - // sandbox - if( ggAutoSandButton.type() != TGaugeType::push ) { - ggAutoSandButton.PutValue( - mvControlled->SandDoseAutoAllow ? - 1.f : - 0.f ); - } - + // we reset all indicators, as they're set during the update pass // TODO: when cleaning up break setting indicator state into a separate function, so we can reuse it } @@ -8222,7 +8233,6 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co { "i-motorblowers:", btLampkaMotorBlowers }, { "i-coolingfans:", btLampkaCoolingFans }, { "i-tempomat:", btLampkaTempomat }, - { "i-distancecounter:", btLampkaDistanceCounter }, { "i-trainheating:", btLampkaOgrzewanieSkladu }, { "i-security_aware:", btLampkaCzuwaka }, { "i-security_cabsignal:", btLampkaSHP }, @@ -8292,9 +8302,9 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co } } // TODO: move viable dedicated lights to the automatic light array - std::unordered_map const autolights = { - { "i-doorpermit_left:", &mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::left : side::right ) ].open_permit }, - { "i-doorpermit_right:", &mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::right : side::left ) ].open_permit }, + std::unordered_map const autolights = { + { "i-doorpermit_left:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit }, + { "i-doorpermit_right:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit }, { "i-doorstep:", &mvOccupied->Doors.step_enabled } }; { @@ -8372,7 +8382,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "universalbrake2_bt:", ggUniveralBrakeButton2 }, { "universalbrake3_bt:", ggUniveralBrakeButton3 }, { "sand_bt:", ggSandButton }, - { "autosandallow_sw:", ggAutoSandButton }, + { "autosandallow_sw:", ggAutoSandAllow }, { "antislip_bt:", ggAntiSlipButton }, { "horn_bt:", ggHornButton }, { "hornlow_bt:", ggHornLowButton }, @@ -8431,7 +8441,6 @@ 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 }, @@ -8452,7 +8461,6 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "cablightdim_sw:", ggCabLightDimButton }, { "battery_sw:", ggBatteryButton }, { "tempomat_sw:", ggScndCtrlButton }, - { "distancecounter_sw:", ggDistanceCounterButton }, { "universal0:", ggUniversals[ 0 ] }, { "universal1:", ggUniversals[ 1 ] }, { "universal2:", ggUniversals[ 2 ] }, @@ -8462,7 +8470,21 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "universal6:", ggUniversals[ 6 ] }, { "universal7:", ggUniversals[ 7 ] }, { "universal8:", ggUniversals[ 8 ] }, - { "universal9:", ggUniversals[ 9 ] } + { "universal9:", ggUniversals[ 9 ] }, + { "speedinc_bt:", ggSpeedControlIncreaseButton }, + { "speeddec_bt:", ggSpeedControlDecreaseButton }, + { "speedctrlpowerinc_bt:", ggSpeedControlPowerIncreaseButton }, + { "speedctrlpowerdec_bt:", ggSpeedControlPowerDecreaseButton }, + { "speedbutton0:", ggSpeedCtrlButtons[ 0 ] }, + { "speedbutton1:", ggSpeedCtrlButtons[ 1 ] }, + { "speedbutton2:", ggSpeedCtrlButtons[ 2 ] }, + { "speedbutton3:", ggSpeedCtrlButtons[ 3 ] }, + { "speedbutton4:", ggSpeedCtrlButtons[ 4 ] }, + { "speedbutton5:", ggSpeedCtrlButtons[ 5 ] }, + { "speedbutton6:", ggSpeedCtrlButtons[ 6 ] }, + { "speedbutton7:", ggSpeedCtrlButtons[ 7 ] }, + { "speedbutton8:", ggSpeedCtrlButtons[ 8 ] }, + { "speedbutton9:", ggSpeedCtrlButtons[ 9 ] } }; { auto lookup = gauges.find( Label ); @@ -8757,18 +8779,6 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con gauge.AssignDouble(&mvControlled->AnPos); m_controlmapper.insert( gauge, "shuntmodepower:" ); } - else if( Label == "heatingvoltage:" ) { - if( mvControlled->HeatingPowerSource.SourceType == TPowerSource::Generator ) { - auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna gałka - gauge.Load( Parser, DynamicObject ); - gauge.AssignDouble( &(mvControlled->HeatingPowerSource.EngineGenerator.voltage) ); - } - } - else if( Label == "heatingcurrent:" ) { - auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna gałka - gauge.Load( Parser, DynamicObject ); - gauge.AssignDouble( &( mvControlled->TotalCurrent ) ); - } else { // failed to match the label diff --git a/Train.h b/Train.h index aa574239..c84afd9e 100644 --- a/Train.h +++ b/Train.h @@ -69,10 +69,8 @@ public: find( TSubModel const *Control ) const; }; -class TTrain { - - friend class drivingaid_panel; - +class TTrain +{ public: // types struct state_t { @@ -90,7 +88,6 @@ class TTrain { std::uint8_t ventilator_overload; std::uint8_t motor_overload_threshold; std::uint8_t train_heating; - std::uint8_t cab; std::uint8_t recorder_braking; std::uint8_t recorder_power; std::uint8_t alerter_sound; @@ -101,15 +98,13 @@ class TTrain { float brake_pressure; float hv_voltage; std::array hv_current; - float lv_voltage; }; -// constructors - TTrain(); // methods bool CabChange(int iDirection); bool ShowNextCurrent; // pokaz przd w podlaczonej lokomotywie (ET41) bool InitializeCab(int NewCabNo, std::string const &asFileName); + TTrain(); // McZapkie-010302 bool Init(TDynamicObject *NewDynamicObject, bool e3d = false); @@ -118,7 +113,6 @@ class TTrain { inline std::string GetLabel( TSubModel const *Control ) const { return m_controlmapper.find( Control ); } void UpdateCab(); bool Update( double const Deltatime ); - void add_distance( double const Distance ); void SetLights(); // McZapkie-310302: ladowanie parametrow z pliku bool LoadMMediaFile(std::string const &asFileName); @@ -157,12 +151,6 @@ class TTrain { void update_sounds( double const Deltatime ); void update_sounds_runningnoise( sound_source &Sound ); void update_sounds_radio(); - inline - end cab_to_end() const { - return ( - iCabn == 2 ? - end::rear : - end::front ); } // command handlers // NOTE: we're currently using universal handlers and static handler map but it may be beneficial to have these implemented on individual class instance basis @@ -362,7 +350,6 @@ 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 ); @@ -373,7 +360,13 @@ class TTrain { static void OnCommand_springbrakeshutoffenable(TTrain *Train, command_data const &Command); static void OnCommand_springbrakeshutoffdisable(TTrain *Train, command_data const &Command); static void OnCommand_springbrakerelease(TTrain *Train, command_data const &Command); - static void OnCommand_distancecounteractivate( TTrain *Train, command_data const &Command ); + static void OnCommand_speedcontrolincrease(TTrain *Train, command_data const &Command); + static void OnCommand_speedcontroldecrease(TTrain *Train, command_data const &Command); + static void OnCommand_speedcontrolpowerincrease(TTrain *Train, command_data const &Command); + static void OnCommand_speedcontrolpowerdecrease(TTrain *Train, command_data const &Command); + static void OnCommand_speedcontrolbutton(TTrain *Train, command_data const &Command); + + // members TDynamicObject *DynamicObject { nullptr }; // przestawia zmiana pojazdu [F5] @@ -436,7 +429,7 @@ public: // reszta może by?publiczna TGauge ggUniveralBrakeButton2; TGauge ggUniveralBrakeButton3; TGauge ggSandButton; // guzik piasecznicy - TGauge ggAutoSandButton; // przełącznik piasecznicy + TGauge ggAutoSandAllow; // przełącznik piasecznicy TGauge ggAntiSlipButton; TGauge ggFuseButton; TGauge ggConverterFuseButton; // hunter-261211: przycisk odblokowania nadmiarowego przetwornic i ogrzewania @@ -447,7 +440,6 @@ public: // reszta może by?publiczna TGauge ggRadioChannelNext; TGauge ggRadioTest; TGauge ggRadioStop; - TGauge ggRadioCall3; TGauge ggUpperLightButton; TGauge ggLeftLightButton; TGauge ggRightLightButton; @@ -480,6 +472,13 @@ public: // reszta może by?publiczna TGauge ggHelperButton; TGauge ggNextCurrentButton; + // yB 191005 - tempomat + TGauge ggSpeedControlIncreaseButton; + TGauge ggSpeedControlDecreaseButton; + TGauge ggSpeedControlPowerIncreaseButton; + TGauge ggSpeedControlPowerDecreaseButton; + std::array ggSpeedCtrlButtons; // NOTE: temporary arrangement until we have dynamically built control table + std::array ggUniversals; // NOTE: temporary arrangement until we have dynamically built control table TGauge ggInstrumentLightButton; @@ -530,8 +529,6 @@ public: // reszta może by?publiczna TGauge ggMotorBlowersRearButton; // rear traction motor fan switch TGauge ggMotorBlowersAllOffButton; // motor fans shutdown switch - TGauge ggDistanceCounterButton; // distance meter activation button - TButton btLampkaPoslizg; TButton btLampkaStyczn; TButton btLampkaNadmPrzetw; @@ -627,7 +624,6 @@ public: // reszta może by?publiczna TButton btLampkaMotorBlowers; TButton btLampkaCoolingFans; TButton btLampkaTempomat; - TButton btLampkaDistanceCounter; TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine // Ra 2013-12: wirtualne "lampki" do odbijania na haslerze w PoKeys @@ -660,7 +656,6 @@ public: // reszta może by?publiczna sound_source m_radiosound { sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // cached template for radio messages std::vector>> m_radiomessages; // list of currently played radio messages sound_source m_radiostop { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; - sound_source m_distancecounterclear { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // distance meter 'good to go' alert /* int iCabLightFlag; // McZapkie:120503: oswietlenie kabiny (0: wyl, 1: przyciemnione, 2: pelne) bool bCabLight; // hunter-091012: czy swiatlo jest zapalone? @@ -668,7 +663,7 @@ public: // reszta może by?publiczna */ // McZapkie: opis kabiny - obszar poruszania sie mechanika oraz zajetosc std::array Cabine; // przedzial maszynowy, kabina 1 (A), kabina 2 (B) - int iCabn { 0 }; // 0: mid, 1: front, 2: rear + int iCabn { 0 }; // McZapkie: do poruszania sie po kabinie Math3D::vector3 pMechSittingPosition; // ABu 180404 Math3D::vector3 MirrorPosition( bool lewe ); @@ -714,7 +709,6 @@ private: float m_mastercontrollerreturndelay { 0.f }; int iRadioChannel { 1 }; // numer aktualnego kana?u radiowego std::vector> m_screens; - float m_distancecounter { -1.f }; // distance traveled since meter was activated or -1 if inactive public: float fPress[20][3]; // cisnienia dla wszystkich czlonow diff --git a/command.cpp b/command.cpp index 2a0ad3e5..faffaa23 100644 --- a/command.cpp +++ b/command.cpp @@ -132,7 +132,6 @@ 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 }, @@ -245,7 +244,20 @@ commanddescription_sequence Commands_descriptions = { { "springbrakeshutoffenable", command_target::vehicle }, { "springbrakeshutoffdisable", command_target::vehicle }, { "springbrakerelease", command_target::vehicle }, - { "distancecounteractivate", command_target::vehicle } + { "speedcontrolincrease", command_target::vehicle }, + { "speedcontroldecrease", command_target::vehicle }, + { "speedcontrolpowerincrease", command_target::vehicle }, + { "speedcontrolpowerdecrease", command_target::vehicle }, + { "speedcontrolbutton0", command_target::vehicle }, + { "speedcontrolbutton1", command_target::vehicle }, + { "speedcontrolbutton2", command_target::vehicle }, + { "speedcontrolbutton3", command_target::vehicle }, + { "speedcontrolbutton4", command_target::vehicle }, + { "speedcontrolbutton5", command_target::vehicle }, + { "speedcontrolbutton6", command_target::vehicle }, + { "speedcontrolbutton7", command_target::vehicle }, + { "speedcontrolbutton8", command_target::vehicle }, + { "speedcontrolbutton9", command_target::vehicle } }; diff --git a/command.h b/command.h index b20b0281..2d26d895 100644 --- a/command.h +++ b/command.h @@ -126,7 +126,6 @@ enum class user_command { radiochanneldecrease, radiostopsend, radiostoptest, - radiocall3send, cabchangeforward, cabchangebackward, @@ -238,8 +237,20 @@ enum class user_command { springbrakeshutoffenable, springbrakeshutoffdisable, springbrakerelease, - distancecounteractivate, - + speedcontrolincrease, + speedcontroldecrease, + speedcontrolpowerincrease, + speedcontrolpowerdecrease, + speedcontrolbutton0, + speedcontrolbutton1, + speedcontrolbutton2, + speedcontrolbutton3, + speedcontrolbutton4, + speedcontrolbutton5, + speedcontrolbutton6, + speedcontrolbutton7, + speedcontrolbutton8, + speedcontrolbutton9, none = -1 }; diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index ca6e56e4..d3e42c76 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -824,7 +824,49 @@ drivermouse_input::default_bindings() { user_command::none } }, { "universal9:", { user_command::generictoggle9, - user_command::none } } + user_command::none } }, + { "speedinc_bt:",{ + user_command::speedcontrolincrease, + user_command::none } }, + { "speeddec_bt:",{ + user_command::speedcontroldecrease, + user_command::none } }, + { "speedctrlpowerinc_bt:",{ + user_command::speedcontrolpowerincrease, + user_command::none } }, + { "speedctrlpowerdec_bt:",{ + user_command::speedcontrolpowerdecrease, + user_command::none } }, + { "speedbutton0:",{ + user_command::speedcontrolbutton0, + user_command::none } }, + { "speedbutton1:",{ + user_command::speedcontrolbutton1, + user_command::none } }, + { "speedbutton2:",{ + user_command::speedcontrolbutton2, + user_command::none } }, + { "speedbutton3:",{ + user_command::speedcontrolbutton3, + user_command::none } }, + { "speedbutton4:",{ + user_command::speedcontrolbutton4, + user_command::none } }, + { "speedbutton5:",{ + user_command::speedcontrolbutton5, + user_command::none } }, + { "speedbutton6:",{ + user_command::speedcontrolbutton6, + user_command::none } }, + { "speedbutton7:",{ + user_command::speedcontrolbutton7, + user_command::none } }, + { "speedbutton8:",{ + user_command::speedcontrolbutton8, + user_command::none } }, + { "speedbutton9:",{ + user_command::speedcontrolbutton9, + user_command::none } } }; }