16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-23 16:49:18 +02:00

Merge branch 'gfx-work' into sim

This commit is contained in:
milek7
2019-05-23 23:16:22 +02:00
26 changed files with 723 additions and 354 deletions

View File

@@ -454,7 +454,7 @@ bool TController::TableAddNew()
return true; // false gdy się nałoży return true; // false gdy się nałoży
}; };
bool TController::TableNotFound(basic_event const *Event) const bool TController::TableNotFound(basic_event const *Event, double const Distance ) const
{ // sprawdzenie, czy nie został już dodany do tabelki (np. podwójne W4 robi problemy) { // sprawdzenie, czy nie został już dodany do tabelki (np. podwójne W4 robi problemy)
auto lookup = auto lookup =
std::find_if( std::find_if(
@@ -469,7 +469,11 @@ bool TController::TableNotFound(basic_event const *Event) const
WriteLog( "Speed table for " + OwnerName() + " already contains event " + lookup->evEvent->m_name ); WriteLog( "Speed table for " + OwnerName() + " already contains event " + lookup->evEvent->m_name );
} }
return lookup == sSpeedTable.end(); // ignore duplicates which seem to be reasonably apart from each other, on account of looping tracks
// NOTE: since supplied distance is only rough approximation of distance to the event, we're using large safety margin
return (
( lookup == sSpeedTable.end() )
|| ( Distance - lookup->fDist > 100.0 ) );
}; };
void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
@@ -573,7 +577,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
for( auto *pEvent : events ) { for( auto *pEvent : events ) {
if( pEvent != nullptr ) // jeśli jest semafor na tym torze if( pEvent != nullptr ) // jeśli jest semafor na tym torze
{ // trzeba sprawdzić tabelkę, bo dodawanie drugi raz tego samego przystanku nie jest korzystne { // trzeba sprawdzić tabelkę, bo dodawanie drugi raz tego samego przystanku nie jest korzystne
if (TableNotFound(pEvent)) // jeśli nie ma if (TableNotFound(pEvent, fCurrentDistance)) // jeśli nie ma
{ {
TableAddNew(); // zawsze jest true TableAddNew(); // zawsze jest true
@@ -1018,7 +1022,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if (TrainParams->StationIndex < TrainParams->StationCount) { if (TrainParams->StationIndex < TrainParams->StationCount) {
// jeśli są dalsze stacje, czekamy do godziny odjazdu // jeśli są dalsze stacje, czekamy do godziny odjazdu
if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute)) { if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute + simulation::Time.data().wSecond*0.0167 )) {
// z dalszą akcją czekamy do godziny odjazdu // z dalszą akcją czekamy do godziny odjazdu
IsAtPassengerStop = false; IsAtPassengerStop = false;
// przy jakim dystansie (stanie licznika) ma przesunąć na następny postój // przy jakim dystansie (stanie licznika) ma przesunąć na następny postój
@@ -1470,7 +1474,8 @@ TController::braking_distance_multiplier( float const Targetvelocity ) const {
if( ( mvOccupied->TrainType == dt_DMU ) if( ( mvOccupied->TrainType == dt_DMU )
&& ( mvOccupied->Vel < 40.0 ) && ( mvOccupied->Vel < 40.0 )
&& ( Targetvelocity == 0.f ) ) { && ( Targetvelocity == 0.f ) ) {
return interpolate( 2.f, 1.f, static_cast<float>( mvOccupied->Vel / 40.0 ) ); auto const multiplier { clamp( 1.f + iVehicles * 0.5f, 2.f, 4.f ) };
return interpolate( multiplier, 1.f, static_cast<float>( mvOccupied->Vel / 40.0 ) );
} }
// HACK: cargo trains or trains going downhill with high braking threshold need more distance to come to a full stop // HACK: cargo trains or trains going downhill with high braking threshold need more distance to come to a full stop
if( ( fBrake_a0[ 1 ] > 0.2 ) if( ( fBrake_a0[ 1 ] > 0.2 )
@@ -2008,7 +2013,7 @@ void TController::AutoRewident()
fBrakeReaction = 0.25; fBrakeReaction = 0.25;
} }
else if( mvOccupied->TrainType == dt_DMU ) { else if( mvOccupied->TrainType == dt_DMU ) {
fNominalAccThreshold = std::max( -0.45, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] ); fNominalAccThreshold = std::max( -0.75, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
fBrakeReaction = 0.25; fBrakeReaction = 0.25;
} }
else if (ustaw > 16) { else if (ustaw > 16) {
@@ -2120,11 +2125,12 @@ bool TController::CheckVehicles(TOrders user)
while (p) while (p)
{ {
// HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi... // HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi...
if( ( p != pVehicle ) if( p != pVehicle ) {
&& ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 ) if( ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 )
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) { && ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) {
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly // NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
p->MoverParameters->BatterySwitch( true ); p->MoverParameters->BatterySwitch( true );
}
// enable heating and converter in carriages with can be heated // enable heating and converter in carriages with can be heated
if( p->MoverParameters->HeatingPower > 0 ) { if( p->MoverParameters->HeatingPower > 0 ) {
p->MoverParameters->HeatingAllow = true; p->MoverParameters->HeatingAllow = true;
@@ -2366,6 +2372,10 @@ double TController::BrakeAccFactor() const
|| ( mvOccupied->Vel > VelDesired + fVelPlus ) ) ) { || ( mvOccupied->Vel > VelDesired + fVelPlus ) ) ) {
Factor += ( fBrakeReaction * ( /*mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.5 ? 1.5 : 1 ) ) * mvOccupied->Vel / ( std::max( 0.0, ActualProximityDist ) + 1 ) * ( ( AccDesired - AbsAccS_pub ) / fAccThreshold ); Factor += ( fBrakeReaction * ( /*mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.5 ? 1.5 : 1 ) ) * mvOccupied->Vel / ( std::max( 0.0, ActualProximityDist ) + 1 ) * ( ( AccDesired - AbsAccS_pub ) / fAccThreshold );
} }
/*
if (mvOccupied->TrainType == dt_DMU && mvOccupied->Vel > 40 && VelNext<40)
Factor *= 1 + 0.25 * ( (1600 - VelNext * VelNext) / (mvOccupied->Vel * mvOccupied->Vel) );
*/
return Factor; return Factor;
} }
@@ -2719,8 +2729,12 @@ bool TController::IncBrake()
// NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself // NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself
// TODO: add easier ways to access front/rear coupler taking into account vehicle's direction // TODO: add easier ways to access front/rear coupler taking into account vehicle's direction
standalone = standalone =
( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) ) ( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr )
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) ) ); || ( ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control )
&& ( vehicle->MoverParameters->Couplers[ end::front ].Connected->Power > 1 ) ) )
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr )
|| ( ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control )
&& ( vehicle->MoverParameters->Couplers[ end::rear ].Connected->Power > 1 ) ) ) );
vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła) vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
} }
} }
@@ -2770,17 +2784,15 @@ bool TController::IncBrake()
{ {
if( /*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.1 ) { if( /*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.1 ) {
OK = /*mvOccupied->*/BrakeLevelAdd( BrakingInitialLevel ); //GBH OK = /*mvOccupied->*/BrakeLevelAdd( BrakingInitialLevel ); //GBH
/*
// HACK: stronger braking to overcome SA134 engine behaviour // HACK: stronger braking to overcome SA134 engine behaviour
if( ( mvOccupied->TrainType == dt_DMU ) if( ( mvOccupied->TrainType == dt_DMU )
&& ( VelNext == 0.0 ) && ( VelNext == 0.0 )
&& ( fBrakeDist < 200.0 ) ) { && ( fBrakeDist < 200.0 ) ) {
mvOccupied->BrakeLevelAdd( BrakeLevelAdd(
fBrakeDist / ActualProximityDist < 0.8 ? fBrakeDist / ActualProximityDist < 0.8 ?
1.0 : 0.5 :
3.0 ); 1.0 );
} }
*/
} }
else else
{ {
@@ -2801,8 +2813,10 @@ bool TController::IncBrake()
} }
} }
if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition > 0 ) { if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition > 0 ) {
if( mvOccupied->Hamulec->Releaser() ) {
mvOccupied->BrakeReleaser( 0 ); mvOccupied->BrakeReleaser( 0 );
} }
}
break; break;
} }
case TBrakeSystem::ElectroPneumatic: { case TBrakeSystem::ElectroPneumatic: {
@@ -2833,20 +2847,20 @@ bool TController::IncBrake()
bool TController::IncBrakeEIM() bool TController::IncBrakeEIM()
{ // zwiększenie hamowania { // zwiększenie hamowania
bool OK = false; bool OK = false;
switch (mvControlling->EIMCtrlType) switch (mvOccupied->EIMCtrlType)
{ {
case 0: case 0:
OK = mvControlling->IncLocalBrakeLevel(1); OK = mvOccupied->IncLocalBrakeLevel(1);
break; break;
case 1: case 1:
OK = mvControlling->MainCtrlPos > 0; OK = mvOccupied->MainCtrlPos > 0;
if (OK) if (OK)
mvControlling->MainCtrlPos = 0; mvOccupied->MainCtrlPos = 0;
break; break;
case 2: case 2:
OK = mvControlling->MainCtrlPos > 1; OK = mvOccupied->MainCtrlPos > 1;
if (OK) if (OK)
mvControlling->MainCtrlPos = 1; mvOccupied->MainCtrlPos = 1;
break; break;
} }
return OK; return OK;
@@ -2855,7 +2869,8 @@ bool TController::IncBrakeEIM()
bool TController::DecBrake() bool TController::DecBrake()
{ // zmniejszenie siły hamowania { // zmniejszenie siły hamowania
bool OK = false; bool OK = false;
double deltaAcc = 0; double deltaAcc = -1.0;
double pos_diff = 1.0;
switch (mvOccupied->BrakeSystem) switch (mvOccupied->BrakeSystem)
{ {
case TBrakeSystem::Individual: case TBrakeSystem::Individual:
@@ -2865,7 +2880,12 @@ bool TController::DecBrake()
OK = mvOccupied->DecLocalBrakeLevel(1 + floor(0.5 + fabs(AccDesired))); OK = mvOccupied->DecLocalBrakeLevel(1 + floor(0.5 + fabs(AccDesired)));
break; break;
case TBrakeSystem::Pneumatic: case TBrakeSystem::Pneumatic:
deltaAcc = -AccDesired*BrakeAccFactor() - (fBrake_a0[0] + 4 * (/*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition -1.0)*fBrake_a1[0]); if( ( fBrake_a0[ 0 ] != 0.0 )
|| ( fBrake_a1[ 0 ] != 0.0 ) ) {
if( mvOccupied->TrainType == dt_DMU )
pos_diff = 0.25;
deltaAcc = -AccDesired*BrakeAccFactor() - (fBrake_a0[0] + 4 * (/*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition - pos_diff)*fBrake_a1[0]);
}
if (deltaAcc < 0) if (deltaAcc < 0)
{ {
if (/*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition > 0) if (/*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition > 0)
@@ -2884,8 +2904,11 @@ bool TController::DecBrake()
if (!OK) { if (!OK) {
OK = DecBrakeEIM(); OK = DecBrakeEIM();
} }
/*
// NOTE: disabled, duplicate of AI's behaviour in UpdateSituation()
if (mvOccupied->PipePress < 3.0) if (mvOccupied->PipePress < 3.0)
Need_BrakeRelease = true; Need_BrakeRelease = true;
*/
break; break;
case TBrakeSystem::ElectroPneumatic: case TBrakeSystem::ElectroPneumatic:
if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor) { if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor) {
@@ -2916,20 +2939,20 @@ bool TController::DecBrake()
bool TController::DecBrakeEIM() bool TController::DecBrakeEIM()
{ // zmniejszenie siły hamowania { // zmniejszenie siły hamowania
bool OK = false; bool OK = false;
switch (mvControlling->EIMCtrlType) switch (mvOccupied->EIMCtrlType)
{ {
case 0: case 0:
OK = mvControlling->DecLocalBrakeLevel(1); OK = mvOccupied->DecLocalBrakeLevel(1);
break; break;
case 1: case 1:
OK = mvControlling->MainCtrlPos < 2; OK = mvOccupied->MainCtrlPos < 2;
if (OK) if (OK)
mvControlling->MainCtrlPos = 2; mvOccupied->MainCtrlPos = 2;
break; break;
case 2: case 2:
OK = mvControlling->MainCtrlPos < 3; OK = mvOccupied->MainCtrlPos < 3;
if (OK) if (OK)
mvControlling->MainCtrlPos = 3; mvOccupied->MainCtrlPos = 3;
break; break;
} }
return OK; return OK;
@@ -2978,6 +3001,7 @@ bool TController::IncSpeed()
// if it generates enough traction force // if it generates enough traction force
// to build up speed to 30/40 km/h for passenger/cargo train (10 km/h less if going uphill) // to build up speed to 30/40 km/h for passenger/cargo train (10 km/h less if going uphill)
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 }; auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 };
auto const sufficientacceleration { AbsAccS_pub >= ( IsHeavyCargoTrain ? 0.02 : 0.04 ) };
auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) }; auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) };
auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) }; auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) };
auto const useseriesmodevoltage { auto const useseriesmodevoltage {
@@ -2989,6 +3013,7 @@ bool TController::IncSpeed()
( mvControlling->Imax > mvControlling->ImaxLo ) ( mvControlling->Imax > mvControlling->ImaxLo )
|| ( fVoltage < useseriesmodevoltage ) || ( fVoltage < useseriesmodevoltage )
|| ( ( true == sufficienttractionforce ) || ( ( true == sufficienttractionforce )
&& ( true == sufficientacceleration )
&& ( mvOccupied->Vel <= ( IsCargoTrain ? 35 : 25 ) + ( seriesmodefieldshunting ? 5 : 0 ) - ( ( fAccGravity < -0.025 ) ? 10 : 0 ) ) ) ); && ( mvOccupied->Vel <= ( IsCargoTrain ? 35 : 25 ) + ( seriesmodefieldshunting ? 5 : 0 ) - ( ( fAccGravity < -0.025 ) ? 10 : 0 ) ) ) );
// when not in series mode use the first available parallel mode configuration until 50/60 km/h for passenger/cargo train // when not in series mode use the first available parallel mode configuration until 50/60 km/h for passenger/cargo train
// (if there's only one parallel mode configuration it'll be used regardless of current speed) // (if there's only one parallel mode configuration it'll be used regardless of current speed)
@@ -2998,6 +3023,7 @@ bool TController::IncSpeed()
&& ( useseriesmode ? && ( useseriesmode ?
mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 : mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 :
( ( true == sufficienttractionforce ) ( ( true == sufficienttractionforce )
&& ( true == sufficientacceleration )
&& ( mvOccupied->Vel <= ( IsCargoTrain ? 55 : 45 ) + ( parallelmodefieldshunting ? 5 : 0 ) ) ? && ( mvOccupied->Vel <= ( IsCargoTrain ? 55 : 45 ) + ( parallelmodefieldshunting ? 5 : 0 ) ) ?
mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 : mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 :
mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo ) ) ); mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo ) ) );
@@ -3437,6 +3463,21 @@ void TController::SetTimeControllers()
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_NP)); mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_NP));
} }
if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a) mvOccupied->BrakeLevelSet(BrakeCtrlPosition); if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a) mvOccupied->BrakeLevelSet(BrakeCtrlPosition);
if (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P)
{
if (BrakeCtrlPosition == 0)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_RP));
else if (BrakeCtrlPosition == -1)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_FS));
else if (BrakeCtrlPosition == -2)
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_NP));
else if (BrakeCtrlPosition > 4.5)
mvOccupied->BrakeLevelSet(10);
else if (BrakeCtrlPosition > 3.70)
mvOccupied->BrakeLevelSet(9);
else
mvOccupied->BrakeLevelSet(round((BrakeCtrlPosition * 0.4 - 0.1) / 0.15));
}
} }
//2. Check the type of Secondary Brake Handle //2. Check the type of Secondary Brake Handle
@@ -3468,6 +3509,26 @@ void TController::SetTimeControllers()
mvOccupied->ScndCtrlPos = 1; mvOccupied->ScndCtrlPos = 1;
} }
} }
//5. Check Main Controller in Dizels
if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->Vmax>30))
{
int MaxPos = mvControlling->MainCtrlPosNo;
int MinPos = MaxPos;
for (int i = MaxPos; (i > 1) && (mvControlling->RList[i].Mn > 0); i--) MinPos = i;
if ((MaxPos > MinPos)&&(mvControlling->MainCtrlPos>0)&&(AccDesired>0))
{
double Factor = 5 * (mvControlling->Vmax) / (mvControlling->Vmax + mvControlling->Vel);
int DesiredPos = MinPos + (MaxPos - MinPos)*(VelDesired > mvControlling->Vel ? (VelDesired - mvControlling->Vel) / Factor : 0);
if (DesiredPos > MaxPos) DesiredPos = MaxPos;
if (DesiredPos < MinPos) DesiredPos = MinPos;
if (!mvControlling->SlippingWheels)
{
while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1);
if (mvControlling->Vel>mvControlling->dizel_minVelfullengage)
while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1);
}
}
}
}; };
void TController::CheckTimeControllers() void TController::CheckTimeControllers()
@@ -3564,13 +3625,14 @@ void TController::Doors( bool const Open, int const Side ) {
|| ( false == AIControllFlag ) ) ) { || ( false == AIControllFlag ) ) ) {
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things // ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
if( ( pVehicle->MoverParameters->Doors.close_control == control_t::conductor ) if( ( pVehicle->MoverParameters->Doors.close_control == control_t::conductor )
|| ( ( true == AIControllFlag ) || ( ( true == AIControllFlag ) ) ) {
&& ( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) ) ) {
// if the door are controlled by the driver, we let the user operate them unless this user is an ai // if the door are controlled by the driver, we let the user operate them unless this user is an ai
// the train conductor, if present, handles door operation also for human-driven trains // the train conductor, if present, handles door operation also for human-driven trains
if( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) {
pVehicle->MoverParameters->OperateDoors( side::right, false ); pVehicle->MoverParameters->OperateDoors( side::right, false );
pVehicle->MoverParameters->OperateDoors( side::left, false ); pVehicle->MoverParameters->OperateDoors( side::left, false );
}
if( pVehicle->MoverParameters->Doors.permit_needed ) { if( pVehicle->MoverParameters->Doors.permit_needed ) {
pVehicle->MoverParameters->PermitDoors( side::right, false ); pVehicle->MoverParameters->PermitDoors( side::right, false );
pVehicle->MoverParameters->PermitDoors( side::left, false ); pVehicle->MoverParameters->PermitDoors( side::left, false );
@@ -4147,6 +4209,7 @@ TController::UpdateSituation(double dt) {
// HACK: activate route scanning if an idling vehicle is activated by a human user // HACK: activate route scanning if an idling vehicle is activated by a human user
if( ( OrderCurrentGet() == Wait_for_orders ) if( ( OrderCurrentGet() == Wait_for_orders )
&& ( false == AIControllFlag ) && ( false == AIControllFlag )
&& ( false == iEngineActive )
&& ( true == mvControlling->Battery ) ) { && ( true == mvControlling->Battery ) ) {
OrderNext( Prepare_engine ); OrderNext( Prepare_engine );
} }
@@ -5011,9 +5074,14 @@ TController::UpdateSituation(double dt) {
// jeśli dociskanie w celu odczepienia // jeśli dociskanie w celu odczepienia
// 3. faza odczepiania. // 3. faza odczepiania.
SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2 SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2
if( ( mvControlling->MainCtrlPowerPos() > 0 ) if( iVehicleCount >= 0 ) {
|| ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) { // zmieni się po odczepieniu
// jeśli jazda WriteLog( mvOccupied->Name + " dociskanie..." );
while( mvOccupied->DecLocalBrakeLevel( 1 ) ) { // dociśnij sklad
;
}
IncSpeed();
}
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute));
TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
@@ -5051,15 +5119,6 @@ TController::UpdateSituation(double dt) {
iVehicleCount = -2; iVehicleCount = -2;
} // a jak nie, to dociskać dalej } // a jak nie, to dociskać dalej
} }
if (iVehicleCount >= 0) // zmieni się po odczepieniu
if (!mvOccupied->DecLocalBrakeLevel(1))
{ // dociśnij sklad
WriteLog( mvOccupied->Name + " dociskanie..." );
// mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę
// Ready=true; //zamiast sprawdzenia odhamowania całego składu
IncSpeed(); // dla (Ready)==false nie ruszy
}
}
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress)) if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
{ // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij { // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach // za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach
@@ -5729,26 +5788,44 @@ TController::UpdateSituation(double dt) {
ReactionTime = 0.25; ReactionTime = 0.25;
} }
} }
if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic) // napełnianie uderzeniowe if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic) {
if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a || mvOccupied->BrakeHandle == TBrakeHandle::MHZ_6P // napełnianie uderzeniowe
|| mvOccupied->BrakeHandle == TBrakeHandle::M394) if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a )
{ || ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_6P )
|| ( mvOccupied->BrakeHandle == TBrakeHandle::M394 ) ) {
if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == -2 ) { if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == -2 ) {
/*mvOccupied->*/BrakeLevelSet( gbh_RP ); /*mvOccupied->*/BrakeLevelSet( gbh_RP );
} }
if( ( mvOccupied->PipePress < 3.0 )
&& ( AccDesired > -0.03 ) ) { // TODO: combine all releaser handling in single decision tree instead of having bits all over the place
if( ( AccDesired > -0.03 )
&& ( false == mvOccupied->Hamulec->Releaser() ) ) {
if( mvOccupied->PipePress < 3.0 ) {
mvOccupied->BrakeReleaser( 1 ); mvOccupied->BrakeReleaser( 1 );
} }
if( ( mvOccupied->BrakePress > 0.4 )
&& ( mvOccupied->Hamulec->GetCRP() > 4.9 ) ) {
// wyluzuj lokomotywę, to szybciej ruszymy
mvOccupied->BrakeReleaser( 1 );
}
}
if( ( mvOccupied->PipePress > 3.0 )
&& ( mvOccupied->Hamulec->Releaser() ) ) {
// don't overcharge train brake pipe
mvOccupied->BrakeReleaser( 0 );
}
if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == 0 ) if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == 0 )
&& ( AbsAccS < 0.03 ) && ( AbsAccS < 0.03 )
&& ( AccDesired > -0.03 ) && ( AccDesired > -0.03 )
&& ( VelDesired - mvOccupied->Vel > 2.0 ) ) { && ( VelDesired - mvOccupied->Vel > 2.0 ) ) {
if( ( mvOccupied->EqvtPipePress < 4.95 ) if( ( mvOccupied->EqvtPipePress < 4.5 )
&& ( fReady > 0.35 ) && ( fReady > 0.35 )
&& ( BrakeChargingCooldown >= 0.0 ) ) { && ( BrakeChargingCooldown >= 0.0 )
&& ( ( ActualProximityDist > 100.0 ) // don't charge if we're about to be braking soon
|| ( min_speed( mvOccupied->Vel, VelNext ) == mvOccupied->Vel ) ) ) {
if( ( iDrivigFlags & moveOerlikons ) if( ( iDrivigFlags & moveOerlikons )
|| ( true == IsCargoTrain ) ) { || ( true == IsCargoTrain ) ) {
@@ -5759,10 +5836,13 @@ TController::UpdateSituation(double dt) {
BrakeChargingCooldown = -120.0; BrakeChargingCooldown = -120.0;
} }
} }
/*
// NOTE: disabled, duplicate of release activation in #5732
else if( Need_BrakeRelease ) { else if( Need_BrakeRelease ) {
Need_BrakeRelease = false; Need_BrakeRelease = false;
mvOccupied->BrakeReleaser( 1 ); mvOccupied->BrakeReleaser( 1 );
} }
*/
} }
if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition < 0 ) if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition < 0 )
@@ -5771,6 +5851,7 @@ TController::UpdateSituation(double dt) {
BrakeLevelSet( gbh_RP ); BrakeLevelSet( gbh_RP );
} }
} }
}
#if LOGVELOCITY #if LOGVELOCITY
WriteLog("Dist=" + FloatToStrF(ActualProximityDist, ffFixed, 7, 1) + WriteLog("Dist=" + FloatToStrF(ActualProximityDist, ffFixed, 7, 1) +
", VelDesired=" + FloatToStrF(VelDesired, ffFixed, 7, 1) + ", VelDesired=" + FloatToStrF(VelDesired, ffFixed, 7, 1) +
@@ -5809,17 +5890,6 @@ TController::UpdateSituation(double dt) {
AccDesired > 0.0 ) ) { AccDesired > 0.0 ) ) {
// on slopes disengage the brakes only if you actually intend to accelerate // on slopes disengage the brakes only if you actually intend to accelerate
while( true == DecBrake() ) { ; } // jeśli przyspieszamy, to nie hamujemy while( true == DecBrake() ) { ; } // jeśli przyspieszamy, to nie hamujemy
if( ( mvOccupied->BrakePress > 0.4 )
&& ( mvOccupied->Hamulec->GetCRP() > 4.9 ) ) {
// wyluzuj lokomotywę, to szybciej ruszymy
mvOccupied->BrakeReleaser( 1 );
}
else {
if( mvOccupied->PipePress >= 3.0 ) {
// TODO: combine all releaser handling in single decision tree instead of having bits all over the place
mvOccupied->BrakeReleaser( 0 );
}
}
} }
} }
} }
@@ -6574,17 +6644,18 @@ std::string TController::NextStop() const
// dodać godzinę odjazdu // dodać godzinę odjazdu
if (!TrainParams) if (!TrainParams)
return ""; // tu nie powinno nigdy wejść return ""; // tu nie powinno nigdy wejść
std::string nextstop = asNextStop; std::string nextstop = Bezogonkow( asNextStop, true );
TMTableLine *t = TrainParams->TimeTable + TrainParams->StationIndex; TMTableLine *t = TrainParams->TimeTable + TrainParams->StationIndex;
if( t->Ah >= 0 ) { if( t->Ah >= 0 ) {
// przyjazd // przyjazd
nextstop += " przyj." + std::to_string( t->Ah ) + ":" nextstop += " przyj." + std::to_string( t->Ah ) + ":"
+ ( t->Am < 10 ? "0" : "" ) + std::to_string( t->Am ); + to_minutes_str( t->Am, true, 3 );
} }
if( t->Dh >= 0 ) { if( t->Dh >= 0 ) {
// jeśli jest godzina odjazdu // jeśli jest godzina odjazdu
nextstop += " odj." + std::to_string( t->Dh ) + ":" nextstop += " odj." + std::to_string( t->Dh ) + ":"
+ ( t->Dm < 10 ? "0" : "" ) + std::to_string( t->Dm ); + to_minutes_str( t->Dm, true, 3 );
} }
return nextstop; return nextstop;
}; };
@@ -6653,14 +6724,16 @@ void TController::DirectionForward(bool forward)
// do przodu w obecnej kabinie // do przodu w obecnej kabinie
while( ( mvOccupied->ActiveDir <= 0 ) while( ( mvOccupied->ActiveDir <= 0 )
&& ( mvOccupied->DirectionForward() ) ) { && ( mvOccupied->DirectionForward() ) ) {
; // all work is done in the header // force scan table update
iTableDirection = 0;
} }
} }
else { else {
// do tyłu w obecnej kabinie // do tyłu w obecnej kabinie
while( ( mvOccupied->ActiveDir >= 0 ) while( ( mvOccupied->ActiveDir >= 0 )
&& ( mvOccupied->DirectionBackward() ) ) { && ( mvOccupied->DirectionBackward() ) ) {
; // all work is done in the header // force scan table update
iTableDirection = 0;
} }
} }
if( mvOccupied->TrainType == dt_SN61 ) { if( mvOccupied->TrainType == dt_SN61 ) {

View File

@@ -210,6 +210,10 @@ public:
inline inline
TMoverParameters const *Controlling() const { TMoverParameters const *Controlling() const {
return mvControlling; } return mvControlling; }
inline
TMoverParameters const *Occupied() const {
return mvOccupied;
}
void DirectionInitial(); void DirectionInitial();
void DirectionChange(); void DirectionChange();
inline inline
@@ -260,6 +264,7 @@ public:
bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista
int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami
int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami
double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller
private: private:
bool Psyche = false; bool Psyche = false;
int HelperState = 0; //stan pomocnika maszynisty int HelperState = 0; //stan pomocnika maszynisty
@@ -289,7 +294,7 @@ private:
int iCoupler = 0; // maska sprzęgu, jaką należy użyć przy łączeniu (po osiągnięciu trybu Connect), 0 gdy jazda bez łączenia int iCoupler = 0; // maska sprzęgu, jaką należy użyć przy łączeniu (po osiągnięciu trybu Connect), 0 gdy jazda bez łączenia
int iDriverFailCount = 0; // licznik błędów AI int iDriverFailCount = 0; // licznik błędów AI
bool Need_TryAgain = false; // true, jeśli druga pozycja w elektryku nie załapała bool Need_TryAgain = false; // true, jeśli druga pozycja w elektryku nie załapała
bool Need_BrakeRelease = true; // bool Need_BrakeRelease = true;
bool IsAtPassengerStop{ false }; // true if the consist is within acceptable range of w4 post bool IsAtPassengerStop{ false }; // true if the consist is within acceptable range of w4 post
double fMinProximityDist = 30.0; // stawanie między 30 a 60 m przed przeszkodą // minimalna oległość do przeszkody, jaką należy zachować double fMinProximityDist = 30.0; // stawanie między 30 a 60 m przed przeszkodą // minimalna oległość do przeszkody, jaką należy zachować
double fOverhead1 = 3000.0; // informacja o napięciu w sieci trakcyjnej (0=brak drutu, zatrzymaj!) double fOverhead1 = 3000.0; // informacja o napięciu w sieci trakcyjnej (0=brak drutu, zatrzymaj!)
@@ -327,7 +332,6 @@ private:
double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI
double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca
double BrakeChargingCooldown {}; // prevents the ai from trying to charge the train brake too frequently double BrakeChargingCooldown {}; // prevents the ai from trying to charge the train brake too frequently
double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller
double LastReactionTime = 0.0; double LastReactionTime = 0.0;
double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi
double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations
@@ -372,7 +376,7 @@ private:
// Ra: metody obsługujące skanowanie toru // Ra: metody obsługujące skanowanie toru
std::vector<basic_event *> CheckTrackEvent( TTrack *Track, double const fDirection ) const; std::vector<basic_event *> CheckTrackEvent( TTrack *Track, double const fDirection ) const;
bool TableAddNew(); bool TableAddNew();
bool TableNotFound( basic_event const *Event ) const; bool TableNotFound( basic_event const *Event, double const Distance ) const;
void TableTraceRoute( double fDistance, TDynamicObject *pVehicle ); void TableTraceRoute( double fDistance, TDynamicObject *pVehicle );
void TableCheck( double fDistance ); void TableCheck( double fDistance );
TCommandType TableUpdate( double &fVelDes, double &fDist, double &fNext, double &fAcc ); TCommandType TableUpdate( double &fVelDes, double &fDist, double &fNext, double &fAcc );

View File

@@ -2337,7 +2337,9 @@ void TDynamicObject::AttachPrev(TDynamicObject *Object, int iType)
{ // Ra: doczepia Object na końcu składu (nazwa funkcji może być myląca) { // Ra: doczepia Object na końcu składu (nazwa funkcji może być myląca)
// Ra: używane tylko przy wczytywaniu scenerii // Ra: używane tylko przy wczytywaniu scenerii
MoverParameters->Attach( iDirection, Object->iDirection ^ 1, Object->MoverParameters, iType, true, false ); MoverParameters->Attach( iDirection, Object->iDirection ^ 1, Object->MoverParameters, iType, true, false );
// update neighbour data for both affected vehicles
update_neighbours(); update_neighbours();
Object->update_neighbours();
} }
bool TDynamicObject::UpdateForce(double dt) bool TDynamicObject::UpdateForce(double dt)
@@ -2799,6 +2801,8 @@ bool TDynamicObject::Update(double dt, double dt1)
auto eimic = Min0R(MoverParameters->eimic, MoverParameters->eimicSpeedCtrl); auto eimic = Min0R(MoverParameters->eimic, MoverParameters->eimicSpeedCtrl);
MoverParameters->eimic_real = eimic; MoverParameters->eimic_real = eimic;
if (MoverParameters->EIMCtrlType == 2 && MoverParameters->MainCtrlPos == 0)
eimic = -1.0;
MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo); MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo);
auto LBR = Max0R(-eimic, 0); auto LBR = Max0R(-eimic, 0);
auto eim_lb = (Mechanik->AIControllFlag || !MoverParameters->LocHandleTimeTraxx ? 0 : MoverParameters->eim_localbrake); auto eim_lb = (Mechanik->AIControllFlag || !MoverParameters->LocHandleTimeTraxx ? 0 : MoverParameters->eim_localbrake);
@@ -2907,6 +2911,10 @@ bool TDynamicObject::Update(double dt, double dt1)
|| ( ( MoverParameters->BrakeHandle == TBrakeHandle::MHZ_EN57 ) || ( ( MoverParameters->BrakeHandle == TBrakeHandle::MHZ_EN57 )
&& ( MoverParameters->BrakeOpModeFlag & bom_MED ) ) ) { && ( MoverParameters->BrakeOpModeFlag & bom_MED ) ) ) {
FzadED = std::min( Fzad, FmaxED ); FzadED = std::min( Fzad, FmaxED );
}
if (MoverParameters->EIMCtrlType == 2 && MoverParameters->MainCtrlPos < 2 && MoverParameters->eimic > -0.999)
{
FzadED = std::min(FzadED, MED_oldFED);
} }
if ((MoverParameters->BrakeCtrlPos == MoverParameters->Handle->GetPos(bh_EB)) if ((MoverParameters->BrakeCtrlPos == MoverParameters->Handle->GetPos(bh_EB))
&& (MoverParameters->eimc[eimc_p_abed] < 0.001)) && (MoverParameters->eimc[eimc_p_abed] < 0.001))
@@ -3085,6 +3093,8 @@ bool TDynamicObject::Update(double dt, double dt1)
delete[] FzED; delete[] FzED;
delete[] FzEP; delete[] FzEP;
delete[] FmaxEP; delete[] FmaxEP;
MED_oldFED = FzadED;
} }
Mechanik->UpdateSituation(dt1); // przebłyski świadomości AI Mechanik->UpdateSituation(dt1); // przebłyski świadomości AI
@@ -4398,10 +4408,6 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
m_materialdata.textures_alpha |= 0x08080008; m_materialdata.textures_alpha |= 0x08080008;
} }
} }
if( false == MoverParameters->LoadAttributes.empty() ) {
// Ra: tu wczytywanie modelu ładunku jest w porządku
mdLoad = LoadMMediaFile_mdload( MoverParameters->LoadType.name );
}
Global.asCurrentTexturePath = szTexturePath; // z powrotem defaultowa sciezka do tekstur Global.asCurrentTexturePath = szTexturePath; // z powrotem defaultowa sciezka do tekstur
do { do {
token = ""; token = "";
@@ -4983,6 +4989,18 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
} while( ( token != "" ) } while( ( token != "" )
&& ( token != "endmodels" ) ); && ( token != "endmodels" ) );
if( false == MoverParameters->LoadAttributes.empty() ) {
// Ra: tu wczytywanie modelu ładunku jest w porządku
// bieżąca ścieżka do tekstur to dynamic/...
Global.asCurrentTexturePath = asBaseDir;
mdLoad = LoadMMediaFile_mdload( MoverParameters->LoadType.name );
// z powrotem defaultowa sciezka do tekstur
Global.asCurrentTexturePath = std::string( szTexturePath );
}
} // models } // models
else if( token == "sounds:" ) { else if( token == "sounds:" ) {
@@ -6152,30 +6170,32 @@ TDynamicObject * TDynamicObject::ControlledFind()
// problematyczna może być kwestia wybranej kabiny (w silnikowym...) // problematyczna może być kwestia wybranej kabiny (w silnikowym...)
// jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno jeździć dobrze // jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno jeździć dobrze
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym... // również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
TDynamicObject *d = this; // zaczynamy od aktualnego if( MoverParameters->Power > 1.0 ) { return this; }
if( ( d->MoverParameters->TrainType == dt_EZT )
|| ( d->MoverParameters->TrainType == dt_DMU ) ) { auto const couplingtype { (
// na razie dotyczy to EZT ( MoverParameters->TrainType == dt_EZT )
if( ( d->NextConnected() != nullptr ) || ( MoverParameters->TrainType == dt_DMU ) ) ?
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) { coupling::permanent :
// gdy jest człon od sprzęgu 1, a sprzęg łączony warsztatowo (powiedzmy) coupling::control
if( ( d->MoverParameters->Power < 1.0 ) };
&& ( d->NextConnected()->MoverParameters->Power > 1.0 ) ) { // try first to look towards the rear
// my nie mamy mocy, ale ten drugi ma auto *d = this; // zaczynamy od aktualnego
d = d->NextConnected(); // będziemy sterować tym z mocą
} while( ( d = d->Next( couplingtype ) ) != nullptr ) {
} if( d->MoverParameters->Power > 1.0 ) {
else if( ( d->PrevConnected() != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) {
// gdy jest człon od sprzęgu 0, a sprzęg łączony warsztatowo (powiedzmy)
if( ( d->MoverParameters->Power < 1.0 )
&& ( d->PrevConnected()->MoverParameters->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
d = d->PrevConnected(); // będziemy sterować tym z mocą
}
}
}
return d; return d;
}
}
// if we didn't yet find a suitable vehicle try in the other direction
d = this; // zaczynamy od aktualnego
while( ( d = d->Prev( couplingtype ) ) != nullptr ) {
if( d->MoverParameters->Power > 1.0 ) {
return d;
}
}
// if we still don't have a match give up
return this;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -6669,7 +6689,8 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
// youBy - przenioslem, bo diesel tez moze miec turbo // youBy - przenioslem, bo diesel tez moze miec turbo
if( Vehicle.TurboTest > 0 ) { if( Vehicle.TurboTest > 0 ) {
// udawanie turbo: // udawanie turbo:
auto const goalpitch { std::max( 0.025, ( engine_volume + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax : 0 };
auto const goalpitch { std::max( 0.025, ( engine_volume * pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) };
auto const goalvolume { ( auto const goalvolume { (
( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ? ( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ?
std::max( 0.0, ( engine_turbo_pitch + engine_turbo.m_amplitudeoffset ) * engine_turbo.m_amplitudefactor ) : std::max( 0.0, ( engine_turbo_pitch + engine_turbo.m_amplitudeoffset ) * engine_turbo.m_amplitudefactor ) :

View File

@@ -664,6 +664,7 @@ private:
double MEDLogTime = 0; double MEDLogTime = 0;
double MEDLogInactiveTime = 0; double MEDLogInactiveTime = 0;
int MEDLogCount = 0; int MEDLogCount = 0;
double MED_oldFED = 0;
// vehicle shaking calculations // vehicle shaking calculations
// TBD, TODO: make an object out of it // TBD, TODO: make an object out of it

View File

@@ -141,7 +141,13 @@ global_settings::ConfigParse(cParser &Parser) {
// selected device for audio renderer // selected device for audio renderer
Parser.getTokens(); Parser.getTokens();
Parser >> AudioVolume; Parser >> AudioVolume;
AudioVolume = clamp( AudioVolume, 0.0f, 2.f ); AudioVolume = clamp( AudioVolume, 0.f, 2.f );
}
else if( token == "sound.volume.radio" ) {
// selected device for audio renderer
Parser.getTokens();
Parser >> RadioVolume;
RadioVolume = clamp( RadioVolume, 0.f, 1.f );
} }
else if (token == "sound.maxsources") { else if (token == "sound.maxsources") {
Parser.getTokens(); Parser.getTokens();

View File

@@ -137,7 +137,8 @@ struct global_settings {
double fFpsMax{ 65.0 }; // górna granica FPS, przy której promień scenerii będzie zwiększany double fFpsMax{ 65.0 }; // górna granica FPS, przy której promień scenerii będzie zwiększany
// audio // audio
bool bSoundEnabled{ true }; bool bSoundEnabled{ true };
float AudioVolume{ 1.25f }; float AudioVolume{ 1.f };
float RadioVolume{ 0.75f };
int audio_max_sources = 30; int audio_max_sources = 30;
std::string AudioRenderer; std::string AudioRenderer;
// input // input

View File

@@ -782,6 +782,7 @@ private:
// ld inputs // ld inputs
bool lock_enabled { true }; bool lock_enabled { true };
bool step_enabled { true }; bool step_enabled { true };
bool remote_only { false }; // door ignores local control signals
// internal data // internal data
int permit_preset { -1 }; // curent position of preset selection switch int permit_preset { -1 }; // curent position of preset selection switch
// vehicle parts // vehicle parts
@@ -1178,6 +1179,7 @@ public:
bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere) bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere)
bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure
start_t CompressorStart{ start_t::manual }; // whether the compressor is started manually, or another way start_t CompressorStart{ start_t::manual }; // whether the compressor is started manually, or another way
start_t PantographCompressorStart{ start_t::manual };
// TODO converter parameters, for when we start cleaning up mover parameters // TODO converter parameters, for when we start cleaning up mover parameters
start_t ConverterStart{ start_t::manual }; // whether converter is started manually, or by other means start_t ConverterStart{ start_t::manual }; // whether converter is started manually, or by other means
float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met
@@ -1326,6 +1328,8 @@ public:
double eim_localbrake = 0; /*nastawa hamowania dodatkowego pneumatycznego lokomotywy*/ double eim_localbrake = 0; /*nastawa hamowania dodatkowego pneumatycznego lokomotywy*/
int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/ int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/
bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/ bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/
int SpeedCtrlAutoTurnOffFlag = 0; /*czy tempomat sam się wyłącza*/
bool EIMCtrlAdditionalZeros = false; /*czy ma dodatkowe zero jazdy i zero hamowania */
double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/ double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/
double eimv[21]; double eimv[21];
static std::vector<std::string> const eimv_labels; static std::vector<std::string> const eimv_labels;
@@ -1360,8 +1364,6 @@ public:
bool PantRearUp = false; bool PantRearUp = false;
bool PantFrontSP = true; //dzwiek patykow 'Winger 010304 bool PantFrontSP = true; //dzwiek patykow 'Winger 010304
bool PantRearSP = true; bool PantRearSP = true;
int PantFrontStart = 0; //stan patykow 'Winger 160204
int PantRearStart = 0;
double PantFrontVolt = 0.0; //pantograf pod napieciem? 'Winger 160404 double PantFrontVolt = 0.0; //pantograf pod napieciem? 'Winger 160404
double PantRearVolt = 0.0; double PantRearVolt = 0.0;
// TODO: move these switch types where they belong, cabin definition // TODO: move these switch types where they belong, cabin definition
@@ -1568,6 +1570,7 @@ public:
bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist ); bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist );
bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist ); bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist );
bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist ); bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist );
bool ChangeDoorControlMode( bool const State, range_t const Notify = range_t::consist );
bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist ); bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist );
bool LockDoors( bool const State, range_t const Notify = range_t::consist ); bool LockDoors( bool const State, range_t const Notify = range_t::consist );
bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning

View File

@@ -761,12 +761,19 @@ void TMoverParameters::UpdatePantVolume(double dt)
{ // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak { // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak
// check the pantograph compressor while at it // check the pantograph compressor while at it
if( PantCompFlag ) { if( ( PantPress < 4.2 )
if( ( false == Battery ) && ( ( PantographCompressorStart == start_t::automatic )
|| ( PantographCompressorStart == start_t::manualwithautofallback ) )
&& ( ( true == PantRearUp )
|| ( true == PantFrontUp ) ) ) {
// automatic start if the pressure is too low
PantCompFlag = true;
}
if( ( true == PantCompFlag )
&& ( false == Battery )
&& ( false == ConverterFlag ) ) { && ( false == ConverterFlag ) ) {
PantCompFlag = false; PantCompFlag = false;
} }
}
if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący
{ {
@@ -1795,6 +1802,8 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed)
else { else {
++MainCtrlPos; ++MainCtrlPos;
OK = true; OK = true;
if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos))
DecScndCtrl(2);
} }
break; break;
} }
@@ -1957,6 +1966,8 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed)
{ {
MainCtrlPos--; MainCtrlPos--;
OK = true; OK = true;
if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos))
DecScndCtrl(2);
} }
else if (CtrlSpeed > 1) else if (CtrlSpeed > 1)
OK = (DecMainCtrl(1) && DecMainCtrl(2)); // CtrlSpeed-1); OK = (DecMainCtrl(1) && DecMainCtrl(2)); // CtrlSpeed-1);
@@ -2098,13 +2109,17 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed)
if (LastRelayTime > CtrlDelay) if (LastRelayTime > CtrlDelay)
LastRelayTime = 0; LastRelayTime = 0;
if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1)) if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1) && (MainCtrlPos>0))
{ {
// NOTE: round() already adds 0.5, are the ones added here as well correct? // NOTE: round() already adds 0.5, are the ones added here as well correct?
if ((Vmax < 250)) if ((Vmax < 250))
ScndCtrlActualPos = Round(Vel); ScndCtrlActualPos = Round(Vel);
else else
ScndCtrlActualPos = Round(Vel * 0.5); ScndCtrlActualPos = Round(Vel * 0.5);
if ((EIMCtrlType == 0)&&(SpeedCtrlAutoTurnOffFlag == 1))
{
MainCtrlActualPos = MainCtrlPos;
}
SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo); SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo);
} }
@@ -3883,7 +3898,18 @@ void TMoverParameters::ComputeConstans(void)
} }
Ff = TotalMassxg * (BearingF + RollF * V * V / 10.0) / 1000.0; Ff = TotalMassxg * (BearingF + RollF * V * V / 10.0) / 1000.0;
// dorobic liczenie temperatury lozyska! // dorobic liczenie temperatury lozyska!
FrictConst1 = ((TotalMassxg * RollF) / 10000.0) + (Cx * Dim.W * Dim.H); FrictConst1 = ( TotalMassxg * RollF ) / 10000.0;
// drag calculation
{
// NOTE: draft effect of previous vehicle is simplified and doesn't have much to do with reality
auto const *previousvehicle { Couplers[ ( V >= 0.0 ? end::front : end::rear ) ].Connected };
auto dragarea { Dim.W * Dim.H };
if( previousvehicle ) {
dragarea = std::max( 0.0, dragarea - ( 0.85 * previousvehicle->Dim.W * previousvehicle->Dim.H ) );
}
FrictConst1 += Cx * dragarea;
}
Curvature = abs(RunningShape.R); // zero oznacza nieskończony promień Curvature = abs(RunningShape.R); // zero oznacza nieskończony promień
if (Curvature > 0.0) if (Curvature > 0.0)
Curvature = 1.0 / Curvature; Curvature = 1.0 / Curvature;
@@ -4398,7 +4424,7 @@ double TMoverParameters::TractionForce( double dt ) {
if( enrot != tmp ) { if( enrot != tmp ) {
enrot = clamp( enrot = clamp(
enrot + ( dt / 1.25 ) * ( // TODO: equivalent of dizel_aim instead of fixed inertia enrot + ( dt / dizel_AIM ) * (
enrot < tmp ? enrot < tmp ?
1.0 : 1.0 :
-2.0 ), // NOTE: revolutions drop faster than they rise, maybe? TBD: maybe not -2.0 ), // NOTE: revolutions drop faster than they rise, maybe? TBD: maybe not
@@ -5897,7 +5923,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify )
if( PantFrontUp != State ) { if( PantFrontUp != State ) {
PantFrontUp = State; PantFrontUp = State;
if( State == true ) { if( State == true ) {
PantFrontStart = 0;
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych? // wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
@@ -5908,7 +5933,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify )
} }
} }
else { else {
PantFrontStart = 1;
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych? // wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
@@ -5950,7 +5974,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify )
if( PantRearUp != State ) { if( PantRearUp != State ) {
PantRearUp = State; PantRearUp = State;
if( State == true ) { if( State == true ) {
PantRearStart = 0;
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych? // wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
@@ -5961,7 +5984,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify )
} }
} }
else { else {
PantRearStart = 1;
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych? // wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
@@ -5996,6 +6018,13 @@ void TMoverParameters::CheckEIMIC(double dt)
{ {
case 0: case 0:
eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : (double)MainCtrlPos / (double)MainCtrlPosNo); eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : (double)MainCtrlPos / (double)MainCtrlPosNo);
if (EIMCtrlAdditionalZeros)
{
if (eimic > 0.001)
eimic = std::max(0.002, eimic * (double)MainCtrlPosNo / ((double)MainCtrlPosNo - 1.0) - 1.0 / ((double)MainCtrlPosNo - 1.0));
if (eimic < -0.001)
eimic = std::min(-0.002, eimic * (double)LocalBrakePosNo / ((double)LocalBrakePosNo - 1.0) + 1.0 / ((double)LocalBrakePosNo - 1.0));
}
break; break;
case 1: case 1:
switch (MainCtrlPos) switch (MainCtrlPos)
@@ -6046,33 +6075,46 @@ void TMoverParameters::CheckEIMIC(double dt)
} }
break; break;
case 2: case 2:
if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay))
{
double delta = (MainCtrlActualPos == MainCtrlPos ? dt*CtrlDelay : 0.01);
switch (MainCtrlPos) switch (MainCtrlPos)
{ {
case 0: case 0:
eimic = -1.0;
break;
case 1: case 1:
eimic -= clamp(1.0 + eimic, 0.0, dt*0.15); //odejmuj do -1 eimic -= clamp(1.0 + eimic, 0.0, delta); //odejmuj do -1
if (eimic > 0) eimic = 0; if (eimic > 0) eimic = 0;
break; break;
case 2: case 2:
eimic -= clamp(0.0 + eimic, 0.0, dt*0.15); //odejmuj do 0 eimic -= clamp(0.0 + eimic, 0.0, delta); //odejmuj do 0
break; break;
case 3: case 3:
eimic += clamp(0.0 - eimic, 0.0, dt*0.15); //dodawaj do 0 eimic += clamp(0.0 - eimic, 0.0, delta); //dodawaj do 0
break; break;
case 4: case 4:
eimic += clamp(1.0 - eimic, 0.0, dt*0.15); //dodawaj do 1 eimic += clamp(1.0 - eimic, 0.0, delta); //dodawaj do 1
if (eimic < 0) eimic = 0; if (eimic < 0) eimic = 0;
break; break;
} }
}
if (MainCtrlActualPos == MainCtrlPos)
LastRelayTime += dt;
else
{
LastRelayTime = 0;
MainCtrlActualPos = MainCtrlPos;
}
break; break;
case 3: case 3:
eimic -= clamp(-UniCtrlList[MainCtrlPos].SetCtrlVal + eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedDown); //odejmuj do X eimic -= clamp(-UniCtrlList[MainCtrlPos].SetCtrlVal + eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedDown); //odejmuj do X
eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedUp); //dodawaj do X eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedUp); //dodawaj do X
eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal); eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal);
} }
eimic = clamp(eimic, -1.0, 1.0); auto const eimicpowerenabled {
( ( true == Mains ) || ( Power == 0.0 ) )
&& ( ( Doors.instances[ side::left ].open_permit == false )
&& ( Doors.instances[ side::right ].open_permit == false ) ) };
eimic = clamp(eimic, -1.0, eimicpowerenabled ? 1.0 : 0.0);
} }
void TMoverParameters::CheckSpeedCtrl() void TMoverParameters::CheckSpeedCtrl()
@@ -6892,12 +6934,7 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c
bool const initialstate { Doors.instances[Door].open_permit }; bool const initialstate { Doors.instances[Door].open_permit };
if( ( false == Doors.permit_presets.empty() ) // HACK: for cases where preset switch is used before battery
|| ( ( true == Battery )
&& ( false == Doors.is_locked ) ) ) {
Doors.instances[ Door ].open_permit = State; Doors.instances[ Door ].open_permit = State;
}
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
@@ -6916,6 +6953,34 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c
return ( Doors.instances[ Door ].open_permit != initialstate ); return ( Doors.instances[ Door ].open_permit != initialstate );
} }
bool TMoverParameters::ChangeDoorControlMode( bool const State, range_t const Notify ) {
auto const initialstate { Doors.remote_only };
Doors.remote_only = State;
if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych?
SendCtrlToNext(
"DoorMode",
( State == true ?
1 :
0 ),
CabNo,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
if( true == State ) {
// when door are put in remote control mode they're automatically open
// TBD, TODO: make it dependant on config switch?
OperateDoors( side::left, true );
OperateDoors( side::right, true );
}
return ( Doors.step_enabled != initialstate );
}
bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) { bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) {
auto &door { Doors.instances[ Door ] }; auto &door { Doors.instances[ Door ] };
@@ -7023,15 +7088,17 @@ TMoverParameters::update_doors( double const Deltatime ) {
// NBMX Obsluga drzwi, MC: zuniwersalnione // NBMX Obsluga drzwi, MC: zuniwersalnione
auto const localopencontrol { auto const localopencontrol {
( Doors.open_control == control_t::passenger ) ( false == Doors.remote_only )
|| ( Doors.open_control == control_t::mixed ) }; && ( ( Doors.open_control == control_t::passenger )
|| ( Doors.open_control == control_t::mixed ) ) };
auto const remoteopencontrol { auto const remoteopencontrol {
( Doors.open_control == control_t::driver ) ( Doors.open_control == control_t::driver )
|| ( Doors.open_control == control_t::conductor ) || ( Doors.open_control == control_t::conductor )
|| ( Doors.open_control == control_t::mixed ) }; || ( Doors.open_control == control_t::mixed ) };
auto const localclosecontrol { auto const localclosecontrol {
( Doors.close_control == control_t::passenger ) ( false == Doors.remote_only )
|| ( Doors.close_control == control_t::mixed ) }; && ( ( Doors.close_control == control_t::passenger )
|| ( Doors.close_control == control_t::mixed ) ) };
auto const remoteclosecontrol { auto const remoteclosecontrol {
( Doors.close_control == control_t::driver ) ( Doors.close_control == control_t::driver )
|| ( Doors.close_control == control_t::conductor ) || ( Doors.close_control == control_t::conductor )
@@ -7059,13 +7126,18 @@ TMoverParameters::update_doors( double const Deltatime ) {
&& ( door.step_position <= 0.f ); && ( door.step_position <= 0.f );
door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
door.remote_open = door.remote_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); door.remote_open = ( door.remote_open || Doors.remote_only ) && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
door.local_close = door.local_close && ( false == door.is_closed ); door.local_close = door.local_close && ( false == door.is_closed );
door.remote_close = door.remote_close && ( false == door.is_closed ); door.remote_close = door.remote_close && ( false == door.is_closed );
auto const autoopenrequest {
( Doors.open_control == control_t::autonomous )
&& ( ( false == Doors.permit_needed ) || door.open_permit )
};
auto const openrequest { auto const openrequest {
( localopencontrol && door.local_open ) ( localopencontrol && door.local_open )
|| ( remoteopencontrol && door.remote_open ) }; || ( remoteopencontrol && door.remote_open )
|| ( autoopenrequest && ( false == door.is_open ) ) };
auto const autocloserequest { auto const autocloserequest {
( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) ) ( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) )
@@ -8357,12 +8429,6 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
lookup != doorcontrols.end() ? lookup != doorcontrols.end() ?
lookup->second : lookup->second :
control_t::passenger; control_t::passenger;
if( Doors.close_control == control_t::autonomous ) {
// convert legacy method
Doors.close_control = control_t::passenger;
Doors.auto_velocity = 10.0;
}
} }
// automatic closing conditions // automatic closing conditions
extract_value( Doors.auto_duration, "DoorStayOpen", line, "" ); extract_value( Doors.auto_duration, "DoorStayOpen", line, "" );
@@ -8665,6 +8731,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
extract_value( EIMCtrlType, "EIMCtrlType", line, "" ); extract_value( EIMCtrlType, "EIMCtrlType", line, "" );
clamp( EIMCtrlType, 0, 3 ); clamp( EIMCtrlType, 0, 3 );
LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes"); LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes");
EIMCtrlAdditionalZeros = (extract_value("EIMCtrlAddZeros", line) == "Yes");
extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR
@@ -8687,6 +8754,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
(extract_value("SpeedCtrlType", line) == "Time") ? (extract_value("SpeedCtrlType", line) == "Time") ?
true : true :
false; false;
extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", line, "");
// converter // converter
{ {
@@ -8717,6 +8785,14 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
lookup->second : lookup->second :
start_t::manual; start_t::manual;
} }
// pantograph compressor
{
auto lookup = starts.find( extract_value( "PantCompressorStart", line ) );
PantographCompressorStart =
lookup != starts.end() ?
lookup->second :
start_t::manual;
}
// fuel pump // fuel pump
{ {
auto lookup = starts.find( extract_value( "FuelStart", line ) ); auto lookup = starts.find( extract_value( "FuelStart", line ) );
@@ -8925,6 +9001,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
ImaxLo = 1; ImaxLo = 1;
} }
extract_value( EngineHeatingRPM, "HeatingRPM", Input, "" ); extract_value( EngineHeatingRPM, "HeatingRPM", Input, "" );
extract_value( dizel_AIM, "AIM", Input, "1.25" );
break; break;
} }
case TEngineType::ElectricInductionMotor: { case TEngineType::ElectricInductionMotor: {
@@ -10009,6 +10086,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
false ); false );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if( Command == "DoorMode" ) {
Doors.remote_only = (
CValue1 == 1 ?
true :
false );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if( Command == "DepartureSignal" ) { else if( Command == "DepartureSignal" ) {
DepartureSignal = ( DepartureSignal = (
CValue1 == 1 ? CValue1 == 1 ?
@@ -10025,12 +10109,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
if ((CValue1 == 1)) if ((CValue1 == 1))
{ {
PantFrontUp = true; PantFrontUp = true;
PantFrontStart = 0;
} }
else if ((CValue1 == 0)) else if ((CValue1 == 0))
{ {
PantFrontUp = false; PantFrontUp = false;
PantFrontStart = 1;
} }
} }
else else
@@ -10040,24 +10122,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {
PantFrontUp = true; PantFrontUp = true;
PantFrontStart = 0;
} }
else else
{ {
PantRearUp = true; PantRearUp = true;
PantRearStart = 0;
} }
else if ((CValue1 == 0)) else if ((CValue1 == 0))
if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) ||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {
PantFrontUp = false; PantFrontUp = false;
PantFrontStart = 1;
} }
else else
{ {
PantRearUp = false; PantRearUp = false;
PantRearStart = 1;
} }
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
@@ -10070,12 +10148,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
if ((CValue1 == 1)) if ((CValue1 == 1))
{ {
PantRearUp = true; PantRearUp = true;
PantRearStart = 0;
} }
else if ((CValue1 == 0)) else if ((CValue1 == 0))
{ {
PantRearUp = false; PantRearUp = false;
PantRearStart = 1;
} }
} }
else else
@@ -10086,24 +10162,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {
PantRearUp = true; PantRearUp = true;
PantRearStart = 0;
} }
else else
{ {
PantFrontUp = true; PantFrontUp = true;
PantFrontStart = 0;
} }
else if ((CValue1 == 0)) else if ((CValue1 == 0))
if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) ||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {
PantRearUp = false; PantRearUp = false;
PantRearStart = 1;
} }
else else
{ {
PantFrontUp = false; PantFrontUp = false;
PantFrontStart = 1;
} }
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );

View File

@@ -385,6 +385,11 @@ void TBrake::Releaser( int const state )
BrakeStatus = (BrakeStatus & ~b_rls) | ( state * b_rls ); BrakeStatus = (BrakeStatus & ~b_rls) | ( state * b_rls );
} }
bool TBrake::Releaser() const {
return ( ( BrakeStatus & b_rls ) == b_rls );
}
void TBrake::SetEPS( double const nEPS ) void TBrake::SetEPS( double const nEPS )
{ {
} }
@@ -1370,7 +1375,7 @@ double TLSt::GetPF( double const PP, double const dt, double const Vel )
temp = 10000; temp = 10000;
// powtarzacz — podwojny zawor zwrotny // powtarzacz — podwojny zawor zwrotny
temp = Max0R(((CVP - BCP) * BVM + ASBP * int((BrakeStatus & b_asb) == b_asb)) / temp, LBP); temp = Max0R(((CVP - BCP) * BVM + ASBP * int((BrakeStatus & b_asb_unbrake) == b_asb_unbrake)) / temp, LBP);
// luzowanie CH // luzowanie CH
if ((BrakeCyl->P() > temp + 0.005) || (temp < 0.28)) if ((BrakeCyl->P() > temp + 0.005) || (temp < 0.28))
// dV:=PF(0,BrakeCyl->P(),0.0015*3*sizeBC)*dt // dV:=PF(0,BrakeCyl->P(),0.0015*3*sizeBC)*dt
@@ -2773,6 +2778,8 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
void TMHZ_K5P::Init(double Press) void TMHZ_K5P::Init(double Press)
{ {
CP = Press; CP = Press;
Time = true;
TimeEP = true;
} }
void TMHZ_K5P::SetReductor(double nAdj) void TMHZ_K5P::SetReductor(double nAdj)

View File

@@ -203,6 +203,7 @@ class TBrake {
virtual double GetCRP(); //cisnienie zbiornika sterujacego virtual double GetCRP(); //cisnienie zbiornika sterujacego
bool SetBDF( int const nBDF ); //nastawiacz GPRM bool SetBDF( int const nBDF ); //nastawiacz GPRM
void Releaser( int const state ); //odluzniacz void Releaser( int const state ); //odluzniacz
bool Releaser() const;
virtual void SetEPS( double const nEPS ); //hamulec EP virtual void SetEPS( double const nEPS ); //hamulec EP
virtual void SetRM( double const RMR ) {}; //ustalenie przelozenia rapida virtual void SetRM( double const RMR ) {}; //ustalenie przelozenia rapida
virtual void SetRV( double const RVR) {}; //ustalenie przelozenia rapida virtual void SetRV( double const RVR) {}; //ustalenie przelozenia rapida

222
Train.cpp
View File

@@ -328,6 +328,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::dooropenall, &TTrain::OnCommand_dooropenall }, { user_command::dooropenall, &TTrain::OnCommand_dooropenall },
{ user_command::doorcloseall, &TTrain::OnCommand_doorcloseall }, { user_command::doorcloseall, &TTrain::OnCommand_doorcloseall },
{ user_command::doorsteptoggle, &TTrain::OnCommand_doorsteptoggle }, { user_command::doorsteptoggle, &TTrain::OnCommand_doorsteptoggle },
{ user_command::doormodetoggle, &TTrain::OnCommand_doormodetoggle },
{ user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease }, { user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease },
{ user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect }, { user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect },
{ user_command::departureannounce, &TTrain::OnCommand_departureannounce }, { user_command::departureannounce, &TTrain::OnCommand_departureannounce },
@@ -394,7 +395,10 @@ TTrain::TTrain() {
} }
for( int i = 0; i < 9; ++i ) for( int i = 0; i < 9; ++i )
for (int j = 0; j < 10; ++j) for (int j = 0; j < 10; ++j)
{
fEIMParams[i][j] = 0.0; fEIMParams[i][j] = 0.0;
fDieselParams[i][j] = 0.0;
}
for( int i = 0; i < 20; ++i ) for( int i = 0; i < 20; ++i )
for( int j = 0; j < 3; ++j ) for( int j = 0; j < 3; ++j )
@@ -459,10 +463,10 @@ dictionary_source *TTrain::GetTrainState() {
// reverser // reverser
dict->insert( "direction", mover->ActiveDir ); dict->insert( "direction", mover->ActiveDir );
// throttle // throttle
dict->insert( "mainctrl_pos", mover->MainCtrlPos ); dict->insert( "mainctrl_pos", mvControlled->MainCtrlPos );
dict->insert( "main_ctrl_actual_pos", mover->MainCtrlActualPos ); dict->insert( "main_ctrl_actual_pos", mvControlled->MainCtrlActualPos );
dict->insert( "scndctrl_pos", mover->ScndCtrlPos ); dict->insert( "scndctrl_pos", mvControlled->ScndCtrlPos );
dict->insert( "scnd_ctrl_actual_pos", mover->ScndCtrlActualPos ); dict->insert( "scnd_ctrl_actual_pos", mvControlled->ScndCtrlActualPos );
dict->insert( "new_speed", mover->NewSpeed); dict->insert( "new_speed", mover->NewSpeed);
// brakes // brakes
dict->insert( "manual_brake", ( mvOccupied->ManualBrakePos > 0 ) ); dict->insert( "manual_brake", ( mvOccupied->ManualBrakePos > 0 ) );
@@ -501,6 +505,7 @@ dictionary_source *TTrain::GetTrainState() {
// induction motor state data // induction motor state data
char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" }; 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 *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
char const *TXTD[ 10 ] = { "enrot", "nrot", "fill_des", "fill_real", "clutch_des", "clutch_real", "water_temp", "oil_press", "res1", "res2" };
char const *TXTP[ 3 ] = { "bc", "bp", "sp" }; char const *TXTP[ 3 ] = { "bc", "bp", "sp" };
for( int j = 0; j < 10; ++j ) for( int j = 0; j < 10; ++j )
dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] ); dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] );
@@ -508,6 +513,9 @@ dictionary_source *TTrain::GetTrainState() {
for( int j = 0; j < 10; ++j ) for( int j = 0; j < 10; ++j )
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] ); dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] );
for (int j = 0; j < 10; ++j)
dict->insert(("diesel_param_" + std::to_string(i + 1) + "_" + std::string(TXTD[j])), fDieselParams[i + 1][j]);
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_ms" ), bMains[ i ] ); dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_ms" ), bMains[ i ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_cv" ), fCntVol[ i ] ); dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_cv" ), fCntVol[ i ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pf" ), bPants[ i ][ 0 ] ); dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pf" ), bPants[ i ][ 0 ] );
@@ -653,7 +661,8 @@ void TTrain::zero_charging_train_brake() {
&& ( DynamicObject->Controller != AIdriver ) && ( DynamicObject->Controller != AIdriver )
&& ( Global.iFeedbackMode < 3 ) && ( Global.iFeedbackMode < 3 )
&& ( ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) && ( ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 )
|| ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57 ) ) ) { || (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57)
|| (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P)) ) {
// Odskakiwanie hamulce EP // Odskakiwanie hamulce EP
set_train_brake( 0 ); set_train_brake( 0 );
} }
@@ -785,7 +794,7 @@ void TTrain::OnCommand_mastercontrollerincrease( TTrain *Train, command_data con
if( Command.action != GLFW_RELEASE ) { if( Command.action != GLFW_RELEASE ) {
// on press or hold // on press or hold
if( ( Train->ggJointCtrl.SubModel != nullptr ) if( ( Train->ggJointCtrl.SubModel != nullptr )
&& ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { && ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) {
OnCommand_independentbrakedecrease( Train, Command ); OnCommand_independentbrakedecrease( Train, Command );
} }
else { else {
@@ -805,7 +814,7 @@ void TTrain::OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data
if( Command.action != GLFW_RELEASE ) { if( Command.action != GLFW_RELEASE ) {
// on press or hold // on press or hold
if( ( Train->ggJointCtrl.SubModel != nullptr ) if( ( Train->ggJointCtrl.SubModel != nullptr )
&& ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { && ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) {
OnCommand_independentbrakedecreasefast( Train, Command ); OnCommand_independentbrakedecreasefast( Train, Command );
} }
else { else {
@@ -1718,8 +1727,8 @@ void TTrain::OnCommand_cabsignalacknowledge( TTrain *Train, command_data const &
void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command )
{ {
if( Command.action == GLFW_PRESS ) { if( Command.action != GLFW_REPEAT ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down // keep the switch from flipping back and forth if key is held down
if( false == Train->mvOccupied->Battery ) { if( false == Train->mvOccupied->Battery ) {
// turn on // turn on
OnCommand_batteryenable( Train, Command ); OnCommand_batteryenable( Train, Command );
@@ -1733,35 +1742,36 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command
void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
// visual feedback
Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch );
if( true == Train->mvOccupied->Battery ) { return; } // already on if( true == Train->mvOccupied->Battery ) { return; } // already on
if( Command.action == GLFW_PRESS ) {
// ignore repeats
// wyłącznik jest też w SN61, ewentualnie załączać prąd na stałe z poziomu FIZ
if( Train->mvOccupied->BatterySwitch( true ) ) { if( Train->mvOccupied->BatterySwitch( true ) ) {
// bateria potrzebna np. do zapalenia świateł
if( Train->ggBatteryButton.SubModel ) {
Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch );
}
// side-effects // side-effects
if( Train->mvOccupied->LightsPosNo > 0 ) { if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->SetLights(); Train->SetLights();
} }
} }
} }
else if( Command.action == GLFW_RELEASE ) {
if( Train->ggBatteryButton.type() == TGaugeType::push ) {
// return the switch to neutral position
Train->ggBatteryButton.UpdateValue( 0.5f );
}
}
} }
void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) {
// TBD, TODO: ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
if( Command.action == GLFW_PRESS ) {
// visual feedback
Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch );
if( false == Train->mvOccupied->Battery ) { return; } // already off if( false == Train->mvOccupied->Battery ) { return; } // already off
if( Command.action == GLFW_PRESS ) {
// ignore repeats
if( Train->mvOccupied->BatterySwitch( false ) ) { if( Train->mvOccupied->BatterySwitch( false ) ) {
// ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
if( Train->ggBatteryButton.SubModel ) {
Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch );
}
// side-effects // side-effects
if( false == Train->mvControlled->ConverterFlag ) { if( false == Train->mvControlled->ConverterFlag ) {
// if there's no (low voltage) power source left, drop pantographs // if there's no (low voltage) power source left, drop pantographs
@@ -1770,6 +1780,12 @@ void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Comman
} }
} }
} }
else if( Command.action == GLFW_RELEASE ) {
if( Train->ggBatteryButton.type() == TGaugeType::push ) {
// return the switch to neutral position
Train->ggBatteryButton.UpdateValue( 0.5f );
}
}
} }
void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &cmd ) void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &cmd )
@@ -4125,7 +4141,7 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
} }
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down // ignore repeats so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->HeatingAllow ) { if( false == Train->mvControlled->HeatingAllow ) {
// turn on // turn on
OnCommand_heatingenable( Train, Command ); OnCommand_heatingenable( Train, Command );
@@ -4135,6 +4151,14 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
OnCommand_heatingdisable( Train, Command ); OnCommand_heatingdisable( Train, Command );
} }
} }
else if( Command.action == GLFW_RELEASE ) {
if( Train->ggTrainHeatingButton.type() == TGaugeType::push ) {
// impulse switch
// visual feedback
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
}
}
} }
void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) {
@@ -4153,7 +4177,11 @@ void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Comman
Train->mvControlled->HeatingAllow = false; Train->mvControlled->HeatingAllow = false;
// visual feedback // visual feedback
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggTrainHeatingButton.UpdateValue(
( Train->ggTrainHeatingButton.type() == TGaugeType::push ?
1.0 :
0.0 ),
Train->dsbSwitch );
} }
} }
@@ -4284,39 +4312,75 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman
void TTrain::OnCommand_doorpermitleft( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_doorpermitleft( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_REPEAT ) { return; }
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
Train->mvOccupied->PermitDoors( auto const side { (
( Train->mvOccupied->ActiveCab == 1 ? Train->mvOccupied->ActiveCab == 1 ?
side::left : side::left :
side::right ) ); side::right ) };
if( Train->ggDoorLeftPermitButton.type() == TGaugeType::push ) {
// impulse switch
Train->mvOccupied->PermitDoors( side );
// visual feedback // visual feedback
Train->ggDoorLeftPermitButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggDoorLeftPermitButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
else {
// two-state switch
auto const newstate { !( Train->mvOccupied->Doors.instances[ side ].open_permit ) };
Train->mvOccupied->PermitDoors( side, newstate );
// visual feedback
Train->ggDoorLeftPermitButton.UpdateValue( ( newstate ? 1.0 : 0.0 ), Train->dsbSwitch );
}
}
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
if( Train->ggDoorLeftPermitButton.type() == TGaugeType::push ) {
// impulse switch
// visual feedback // visual feedback
Train->ggDoorLeftPermitButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggDoorLeftPermitButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
} }
}
void TTrain::OnCommand_doorpermitright( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_doorpermitright( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_REPEAT ) { return; }
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
Train->mvOccupied->PermitDoors( auto const side { (
( Train->mvOccupied->ActiveCab == 1 ? Train->mvOccupied->ActiveCab == 1 ?
side::right : side::right :
side::left ) ); side::left ) };
if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) {
// impulse switch
Train->mvOccupied->PermitDoors( side );
// visual feedback // visual feedback
Train->ggDoorRightPermitButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggDoorRightPermitButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
else {
// two-state switch
auto const newstate { !( Train->mvOccupied->Doors.instances[ side ].open_permit ) };
Train->mvOccupied->PermitDoors( side, newstate );
// visual feedback
Train->ggDoorRightPermitButton.UpdateValue( ( newstate ? 1.0 : 0.0 ), Train->dsbSwitch );
}
}
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) {
// impulse switch
// visual feedback // visual feedback
Train->ggDoorRightPermitButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggDoorRightPermitButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
} }
}
void TTrain::OnCommand_doorpermitpresetactivatenext( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_doorpermitpresetactivatenext( TTrain *Train, command_data const &Command ) {
@@ -4684,6 +4748,13 @@ void TTrain::OnCommand_doorsteptoggle( TTrain *Train, command_data const &Comman
} }
} }
void TTrain::OnCommand_doormodetoggle( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
Train->mvOccupied->ChangeDoorControlMode( false == Train->mvOccupied->Doors.remote_only );
}
}
void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) {
if( ( true == Command.freefly ) if( ( true == Command.freefly )
@@ -5199,7 +5270,7 @@ bool TTrain::Update( double const Deltatime )
} }
bool kier = (DynamicObject->DirectionGet() * mvOccupied->ActiveCab > 0); bool kier = (DynamicObject->DirectionGet() * mvOccupied->ActiveCab > 0);
TDynamicObject *p = DynamicObject->GetFirstDynamic(mvOccupied->ActiveCab < 0 ? 1 : 0, 4); TDynamicObject *p = DynamicObject->GetFirstDynamic(mvOccupied->ActiveCab < 0 ? end::rear : end::front, 4);
int in = 0; int in = 0;
fEIMParams[0][6] = 0; fEIMParams[0][6] = 0;
iCarNo = 0; iCarNo = 0;
@@ -5268,6 +5339,27 @@ bool TTrain::Update( double const Deltatime )
in++; in++;
iPowerNo = in; iPowerNo = in;
} }
if ((in < 8) && (p->MoverParameters->EngineType==TEngineType::DieselEngine))
{
fDieselParams[1 + in][0] = p->MoverParameters->enrot*60;
fDieselParams[1 + in][1] = p->MoverParameters->nrot;
fDieselParams[1 + in][2] = p->MoverParameters->RList[p->MoverParameters->MainCtrlPos].R;
fDieselParams[1 + in][3] = p->MoverParameters->dizel_fill;
fDieselParams[1 + in][4] = p->MoverParameters->RList[p->MoverParameters->MainCtrlPos].Mn;
fDieselParams[1 + in][5] = p->MoverParameters->dizel_engage;
fDieselParams[1 + in][6] = p->MoverParameters->dizel_heat.Twy;
fDieselParams[1 + in][7] = p->MoverParameters->OilPump.pressure;
//fDieselParams[1 + in][8] = p->MoverParameters->
//fDieselParams[1 + in][9] = p->MoverParameters->
bMains[in] = p->MoverParameters->Mains;
fCntVol[in] = p->MoverParameters->BatteryVoltage;
bFuse[in] = p->MoverParameters->FuseFlag;
bBatt[in] = p->MoverParameters->Battery;
bConv[in] = p->MoverParameters->ConverterFlag;
bHeat[in] = p->MoverParameters->Heating;
in++;
iPowerNo = in;
}
// p = p->NextC(4); //prev // p = p->NextC(4); //prev
if ((kier ? p->Next(128) : p->Prev(128)) != (kier ? p->Next(4) : p->Prev(4))) if ((kier ? p->Next(128) : p->Prev(128)) != (kier ? p->Next(4) : p->Prev(4)))
iUnitNo++; iUnitNo++;
@@ -5310,16 +5402,11 @@ bool TTrain::Update( double const Deltatime )
for (int i = in; i < 8; i++) for (int i = in; i < 8; i++)
{ {
fEIMParams[1 + i][0] = 0; for (int j = 0; j <= 9; j++)
fEIMParams[1 + i][1] = 0; {
fEIMParams[1 + i][2] = 0; fEIMParams[1 + i][j] = 0;
fEIMParams[1 + i][3] = 0; fDieselParams[1 + i][j] = 0;
fEIMParams[1 + i][4] = 0; }
fEIMParams[1 + i][5] = 0;
fEIMParams[1 + i][6] = 0;
fEIMParams[1 + i][7] = 0;
fEIMParams[1 + i][8] = 0;
fEIMParams[1 + i][9] = 0;
} }
#ifdef _WIN32 #ifdef _WIN32
if (Global.iFeedbackMode == 4) { if (Global.iFeedbackMode == 4) {
@@ -6504,7 +6591,7 @@ void TTrain::update_sounds_radio() {
auto const volume { auto const volume {
( true == radioenabled ) ( true == radioenabled )
&& ( message.first == iRadioChannel ) ? && ( message.first == iRadioChannel ) ?
1.0 : Global.RadioVolume :
0.0 }; 0.0 };
message.second->gain( volume ); message.second->gain( volume );
} }
@@ -7121,28 +7208,11 @@ void TTrain::DynamicSet(TDynamicObject *d)
// jeździć dobrze // jeździć dobrze
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym... // również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
DynamicObject = d; // jedyne miejsce zmiany DynamicObject = d; // jedyne miejsce zmiany
mvOccupied = mvControlled = d ? DynamicObject->MoverParameters : NULL; // albo silnikowy w EZT mvOccupied = mvControlled = ( d ? DynamicObject->MoverParameters : nullptr ); // albo silnikowy w EZT
if (!DynamicObject)
return;
// TODO: leverage code already present in TDynamicObject::ControlledFind()
if( ( d->MoverParameters->TrainType == dt_EZT )
|| ( d->MoverParameters->TrainType == dt_DMU ) ) {
if( ( d->NextConnected() != nullptr ) if( DynamicObject == nullptr ) { return; }
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) {
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 1 ].Connected->Power > 1.0 ) ) { mvControlled = DynamicObject->ControlledFind()->MoverParameters;
// my nie mamy mocy, ale ten drugi ma
mvControlled = DynamicObject->NextConnected()->MoverParameters; // będziemy sterować tym z mocą
}
}
else if( ( d->PrevConnected() != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) {
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 0 ].Connected->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
mvControlled = DynamicObject->PrevConnected()->MoverParameters; // będziemy sterować tym z mocą
}
}
}
mvSecond = NULL; // gdyby się nic nie znalazło mvSecond = NULL; // gdyby się nic nie znalazło
if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo
if (mvOccupied->Couplers[1].Connected ? if (mvOccupied->Couplers[1].Connected ?
@@ -7561,9 +7631,10 @@ void TTrain::clear_cab_controls()
void TTrain::set_cab_controls( int const Cab ) { void TTrain::set_cab_controls( int const Cab ) {
// switches // switches
// battery // battery
if( true == mvOccupied->Battery ) { ggBatteryButton.PutValue(
ggBatteryButton.PutValue( 1.f ); ( ggBatteryButton.type() == TGaugeType::push ? 0.5f :
} mvOccupied->Battery ? 1.f :
0.f ) );
// motor connectors // motor connectors
ggStLinOffButton.PutValue( ggStLinOffButton.PutValue(
( mvControlled->StLinSwitchOff ? ( mvControlled->StLinSwitchOff ?
@@ -7726,7 +7797,12 @@ void TTrain::set_cab_controls( int const Cab ) {
1.f : 1.f :
0.f ) ); 0.f ) );
// doors // doors
// NOTE: for the time being permit switches are presumed to be impulse switches if( ggDoorLeftPermitButton.type() != TGaugeType::push ) {
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[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit ? 1.f : 0.f );
}
ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset ); ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset );
ggDoorLeftButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].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 ); ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].is_closed ? 0.f : 1.f );
@@ -7736,8 +7812,11 @@ void TTrain::set_cab_controls( int const Cab ) {
1.f : 1.f :
0.f ); 0.f );
// heating // heating
if( true == mvControlled->Heating ) { if( ggTrainHeatingButton.type() != TGaugeType::push ) {
ggTrainHeatingButton.PutValue( 1.f ); ggTrainHeatingButton.PutValue(
mvControlled->Heating ?
1.f :
0.f );
} }
// brake acting time // brake acting time
if( ggBrakeProfileCtrl.SubModel != nullptr ) { if( ggBrakeProfileCtrl.SubModel != nullptr ) {
@@ -7955,8 +8034,8 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
} }
// TODO: move viable dedicated lights to the automatic light array // TODO: move viable dedicated lights to the automatic light array
std::unordered_map<std::string, bool *> const autolights = { std::unordered_map<std::string, bool *> const autolights = {
{ "i-doorpermit_left:", &mvOccupied->Doors.instances[side::left].open_permit }, { "i-doorpermit_left:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit },
{ "i-doorpermit_right:", &mvOccupied->Doors.instances[ 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 } { "i-doorstep:", &mvOccupied->Doors.step_enabled }
}; };
{ {
@@ -8126,6 +8205,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
} }
// TODO: move viable dedicated gauges to the automatic array // TODO: move viable dedicated gauges to the automatic array
std::unordered_map<std::string, bool *> const autoboolgauges = { std::unordered_map<std::string, bool *> const autoboolgauges = {
{ "doormode_sw:", &mvOccupied->Doors.remote_only },
{ "doorstep_sw:", &mvOccupied->Doors.step_enabled }, { "doorstep_sw:", &mvOccupied->Doors.step_enabled },
{ "coolingfans_sw:", &mvControlled->RVentForceOn } { "coolingfans_sw:", &mvControlled->RVentForceOn }
}; };

View File

@@ -335,6 +335,7 @@ class TTrain
static void OnCommand_dooropenall( TTrain *Train, command_data const &Command ); static void OnCommand_dooropenall( TTrain *Train, command_data const &Command );
static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command ); static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command );
static void OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command ); static void OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command );
static void OnCommand_doormodetoggle( TTrain *Train, command_data const &Command );
static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command );
static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command );
static void OnCommand_departureannounce( TTrain *Train, command_data const &Command ); static void OnCommand_departureannounce( TTrain *Train, command_data const &Command );
@@ -681,6 +682,7 @@ private:
float fPress[20][3]; // cisnienia dla wszystkich czlonow float fPress[20][3]; // cisnienia dla wszystkich czlonow
static std::vector<std::string> const fPress_labels; static std::vector<std::string> const fPress_labels;
float fEIMParams[9][10]; // parametry dla silnikow asynchronicznych float fEIMParams[9][10]; // parametry dla silnikow asynchronicznych
float fDieselParams[9][10]; // parametry dla silnikow asynchronicznych
int RadioChannel() const { return iRadioChannel; }; int RadioChannel() const { return iRadioChannel; };
// plays provided sound from position of the radio // plays provided sound from position of the radio
void radio_message( sound_source *Message, int const Channel ); void radio_message( sound_source *Message, int const Channel );

View File

@@ -156,6 +156,7 @@ commanddescription_sequence Commands_descriptions = {
{ "doorcloseright", command_target::vehicle, command_mode::oneoff }, { "doorcloseright", command_target::vehicle, command_mode::oneoff },
{ "doorcloseall", command_target::vehicle, command_mode::oneoff }, { "doorcloseall", command_target::vehicle, command_mode::oneoff },
{ "doorsteptoggle", command_target::vehicle, command_mode::oneoff }, { "doorsteptoggle", command_target::vehicle, command_mode::oneoff },
{ "doormodetoggle", command_target::vehicle, command_mode::oneoff },
{ "departureannounce", command_target::vehicle, command_mode::oneoff }, { "departureannounce", command_target::vehicle, command_mode::oneoff },
{ "doorlocktoggle", command_target::vehicle, command_mode::oneoff }, { "doorlocktoggle", command_target::vehicle, command_mode::oneoff },
{ "pantographcompressorvalvetoggle", command_target::vehicle, command_mode::oneoff }, { "pantographcompressorvalvetoggle", command_target::vehicle, command_mode::oneoff },

View File

@@ -149,6 +149,7 @@ enum class user_command {
doorcloseright, doorcloseright,
doorcloseall, doorcloseall,
doorsteptoggle, doorsteptoggle,
doormodetoggle,
departureannounce, departureannounce,
doorlocktoggle, doorlocktoggle,
pantographcompressorvalvetoggle, pantographcompressorvalvetoggle,

View File

@@ -156,6 +156,7 @@ driverkeyboard_input::default_bindings() {
// doorcloseright, // doorcloseright,
{ user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control }, { user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control },
// doorsteptoggle, // doorsteptoggle,
{ user_command::doormodetoggle, GLFW_KEY_SLASH | keymodifier::shift | keymodifier::control },
{ user_command::departureannounce, GLFW_KEY_SLASH }, { user_command::departureannounce, GLFW_KEY_SLASH },
{ user_command::doorlocktoggle, GLFW_KEY_S | keymodifier::control }, { user_command::doorlocktoggle, GLFW_KEY_S | keymodifier::control },
{ user_command::pantographcompressorvalvetoggle, GLFW_KEY_V | keymodifier::control }, { user_command::pantographcompressorvalvetoggle, GLFW_KEY_V | keymodifier::control },

View File

@@ -22,7 +22,7 @@ http://mozilla.org/MPL/2.0/.
#include "uilayer.h" #include "uilayer.h"
#include "Logs.h" #include "Logs.h"
auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.65 }; auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.6 };
void void
mouse_slider::bind( user_command const &Command ) { mouse_slider::bind( user_command const &Command ) {
@@ -641,6 +641,9 @@ drivermouse_input::default_bindings() {
{ "doorstep_sw:", { { "doorstep_sw:", {
user_command::doorsteptoggle, user_command::doorsteptoggle,
user_command::none } }, user_command::none } },
{ "doormode_sw:", {
user_command::doormodetoggle,
user_command::none } },
{ "departure_signal_bt:", { { "departure_signal_bt:", {
user_command::departureannounce, user_command::departureannounce,
user_command::none } }, user_command::none } },

View File

@@ -226,6 +226,7 @@ timetable_panel::update() {
if( false == is_open ) { return; } if( false == is_open ) { return; }
text_lines.clear(); text_lines.clear();
m_tablelines.clear();
auto const *train { simulation::Train }; auto const *train { simulation::Train };
auto const *controlled { ( train ? train->Dynamic() : nullptr ) }; auto const *controlled { ( train ? train->Dynamic() : nullptr ) };
@@ -236,7 +237,7 @@ timetable_panel::update() {
std::snprintf( std::snprintf(
m_buffer.data(), m_buffer.size(), m_buffer.data(), m_buffer.size(),
locale::strings[ locale::string::driver_timetable_header ].c_str(), locale::strings[ locale::string::driver_timetable_header ].c_str(),
40, 40, 37, 37,
locale::strings[ locale::string::driver_timetable_name ].c_str(), locale::strings[ locale::string::driver_timetable_name ].c_str(),
time.wHour, time.wHour,
time.wMinute, time.wMinute,
@@ -271,7 +272,7 @@ timetable_panel::update() {
} }
{ // next station { // next station
auto const nextstation = Bezogonkow( owner->NextStop(), true ); auto const nextstation = owner->NextStop();
if( false == nextstation.empty() ) { if( false == nextstation.empty() ) {
// jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania // jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania
auto textline = " -> " + nextstation; auto textline = " -> " + nextstation;
@@ -314,67 +315,126 @@ timetable_panel::update() {
} }
else { else {
auto const loadingcolor { glm::vec4( 164.0f / 255.0f, 84.0f / 255.0f, 84.0f / 255.0f, 1.f ) };
auto const waitcolor { glm::vec4( 164.0f / 255.0f, 132.0f / 255.0f, 84.0f / 255.0f, 1.f ) };
auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) }; auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) };
// header // header
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor ); m_tablelines.emplace_back( u8"┌─────┬────────────────────────────────────┬─────────┬─────┐", Global.UITextColor );
TMTableLine const *tableline; TMTableLine const *tableline;
for( int i = owner->iStationStart; i <= table->StationCount; ++i ) { for( int i = owner->iStationStart; i <= table->StationCount; ++i ) {
// wyświetlenie pozycji z rozkładu // wyświetlenie pozycji z rozkładu
tableline = table->TimeTable + i; // linijka rozkładu tableline = table->TimeTable + i; // linijka rozkładu
std::string vmax = bool vmaxchange { true };
" " if( i > owner->iStationStart ) {
+ to_string( tableline->vmax, 0 ); auto const *previoustableline { tableline - 1 };
if( tableline->vmax == previoustableline->vmax ) {
vmaxchange = false;
}
}
std::string vmax { " " };
if( true == vmaxchange ) {
vmax += to_string( tableline->vmax, 0 );
vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej
std::string const station = ( }
auto const station { (
Bezogonkow( tableline->StationName, true ) Bezogonkow( tableline->StationName, true )
+ " " ) + " " )
.substr( 0, 34 ); .substr( 0, 34 ) };
std::string const location = ( auto const location { (
( tableline->km > 0.0 ? ( tableline->km > 0.0 ?
to_string( tableline->km, 2 ) : to_string( tableline->km, 2 ) :
"" ) "" )
+ " " ) + " " )
.substr( 0, 34 - tableline->StationWare.size() ); .substr( 0, 34 - tableline->StationWare.size() ) };
std::string const arrival = ( auto const arrival { (
tableline->Ah >= 0 ? tableline->Ah >= 0 ?
to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Am ) ).substr( 1, 2 ) : to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Am, true, 3 ) :
" | " ); u8" " ) };
std::string const departure = ( auto const departure { (
tableline->Dh >= 0 ? tableline->Dh >= 0 ?
to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Dm ) ).substr( 1, 2 ) : to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Dm, true, 3 ) :
" | " ); u8" " ) };
auto const candeparture = ( auto const candeparture { (
( owner->iStationStart < table->StationIndex ) ( owner->iStationStart < table->StationIndex )
&& ( i < table->StationIndex ) && ( i < table->StationIndex )
&& ( ( tableline->Ah < 0 ) // pass-through, always valid && ( ( tableline->Ah < 0 ) // pass-through, always valid
|| ( time.wHour * 60 + time.wMinute >= tableline->Dh * 60 + tableline->Dm ) ) ); || ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ) };
auto traveltime = auto const loadchangeinprogress { ( ( static_cast<int>( std::ceil( -1.0 * owner->fStopTime ) ) ) > 0 ) };
" " auto const isatpassengerstop { ( true == owner->IsAtPassengerStop ) && ( vehicle->MoverParameters->Vel < 1.0 ) };
+ ( i < 2 ? "" : auto const traveltime { (
tableline->Ah >= 0 ? to_string( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), 0 ) : i < 2 ? " " :
to_string( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), 0 ) ); tableline->Ah >= 0 ? to_minutes_str( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), false, 3 ) :
traveltime = traveltime.substr( traveltime.size() - 3, 3 ); // z wyrównaniem do prawej to_minutes_str( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), false, 3 ) ) };
auto const linecolor { (
text_lines.emplace_back( ( i != owner->iStationStart ) ? Global.UITextColor :
( "| " + vmax + " | " + station + " | " + arrival + " | " + traveltime + " |" ), loadchangeinprogress ? loadingcolor :
( candeparture ? candeparture ? readycolor : // czas minął i odjazd był, to nazwa stacji będzie na zielono
readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono isatpassengerstop ? waitcolor :
Global.UITextColor ) ); Global.UITextColor ) };
text_lines.emplace_back( m_tablelines.emplace_back(
( "| | " + location + tableline->StationWare + " | " + departure + " | |" ), ( u8"" + vmax + u8" " + station + u8"" + arrival + u8" " + traveltime + u8" " ),
( candeparture ? linecolor );
readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono m_tablelines.emplace_back(
Global.UITextColor ) ); ( u8"│ │ " + location + tableline->StationWare + u8"" + departure + u8" │ │" ),
linecolor );
// divider/footer // divider/footer
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor ); if( i < table->StationCount ) {
auto const *nexttableline { tableline + 1 };
if( tableline->vmax == nexttableline->vmax ) {
m_tablelines.emplace_back( u8"│ ├────────────────────────────────────┼─────────┼─────┤", Global.UITextColor );
}
else {
m_tablelines.emplace_back( u8"├─────┼────────────────────────────────────┼─────────┼─────┤", Global.UITextColor );
}
}
else {
m_tablelines.emplace_back( u8"└─────┴────────────────────────────────────┴─────────┴─────┘", Global.UITextColor );
}
} }
} }
} // is_expanded } // is_expanded
} }
void
timetable_panel::render() {
if( false == is_open ) { return; }
if( true == text_lines.empty() ) { return; }
auto flags =
ImGuiWindowFlags_NoFocusOnAppearing
| ImGuiWindowFlags_NoCollapse
| ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 );
if( size.x > 0 ) {
ImGui::SetNextWindowSize( ImVec2( size.x, size.y ) );
}
if( size_min.x > 0 ) {
ImGui::SetNextWindowSizeConstraints( ImVec2( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) );
}
auto const panelname { (
title.empty() ?
m_name :
title )
+ "###" + m_name };
if( true == ImGui::Begin( panelname.c_str(), &is_open, flags ) ) {
for( auto const &line : text_lines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
if( is_expanded ) {
ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 1, 0 ) );
for( auto const &line : m_tablelines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
ImGui::PopStyleVar();
}
}
ImGui::End();
}
void void
debug_panel::update() { debug_panel::update() {
@@ -722,6 +782,7 @@ debug_panel::update_section_engine( std::vector<text_line> &Output ) {
std::string parameterstext = "param value"; std::string parameterstext = "param value";
std::vector< std::pair <std::string, double> > const paramvalues { std::vector< std::pair <std::string, double> > const paramvalues {
{ " rpm: ", mover.enrot * 60.0 },
{ "efill: ", mover.dizel_fill }, { "efill: ", mover.dizel_fill },
{ "etorq: ", mover.dizel_Torque }, { "etorq: ", mover.dizel_Torque },
{ "creal: ", mover.dizel_engage }, { "creal: ", mover.dizel_engage },

View File

@@ -33,10 +33,12 @@ public:
: ui_expandable_panel( Name, Isopen ) {} : ui_expandable_panel( Name, Isopen ) {}
void update() override; void update() override;
void render() override;
private: private:
// members // members
std::array<char, 256> m_buffer; std::array<char, 256> m_buffer;
std::vector<text_line> m_tablelines;
}; };
class scenario_panel : public ui_panel { class scenario_panel : public ui_panel {
@@ -48,9 +50,11 @@ public:
void update() override; void update() override;
void render() override; void render() override;
bool is_expanded{ false };
private: private:
// members // members
// std::array<char, 256> m_buffer; std::array<char, 256> m_buffer;
TDynamicObject const *m_nearest { nullptr }; TDynamicObject const *m_nearest { nullptr };
}; };

View File

@@ -51,7 +51,7 @@ bool TTrainParameters::IsStop() const
bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) { bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) {
return UpdateMTable( Time.data().wHour, Time.data().wMinute, NewName ); return UpdateMTable( Time.data().wHour, Time.data().wMinute + Time.data().wSecond * 0.0167, NewName );
} }
bool TTrainParameters::UpdateMTable(double hh, double mm, std::string const &NewName) bool TTrainParameters::UpdateMTable(double hh, double mm, std::string const &NewName)
@@ -359,12 +359,12 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
if (s.find(hrsd) != std::string::npos) if (s.find(hrsd) != std::string::npos)
{ {
record->Ah = atoi( s.substr(0, s.find(hrsd)).c_str()); // godzina przyjazdu record->Ah = atoi( s.substr(0, s.find(hrsd)).c_str()); // godzina przyjazdu
record->Am = atoi(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta przyjazdu record->Am = atof(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta przyjazdu
} }
else else
{ {
record->Ah = TimeTable[StationCount - 1].Ah; // godzina z poprzedniej pozycji record->Ah = TimeTable[StationCount - 1].Ah; // godzina z poprzedniej pozycji
record->Am = atoi(s.c_str()); // bo tylko minuty podane record->Am = atof(s.c_str()); // bo tylko minuty podane
} }
} }
do do
@@ -409,12 +409,12 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
if (s.find(hrsd) != std::string::npos) if (s.find(hrsd) != std::string::npos)
{ {
record->Dh = atoi(s.substr(0, s.find(hrsd)).c_str()); // godzina odjazdu record->Dh = atoi(s.substr(0, s.find(hrsd)).c_str()); // godzina odjazdu
record->Dm = atoi(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta odjazdu record->Dm = atof(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta odjazdu
} }
else else
{ {
record->Dh = TimeTable[StationCount - 1].Dh; // godzina z poprzedniej pozycji record->Dh = TimeTable[StationCount - 1].Dh; // godzina z poprzedniej pozycji
record->Dm = atoi(s.c_str()); // bo tylko minuty podane record->Dm = atof(s.c_str()); // bo tylko minuty podane
} }
} }
else else
@@ -476,20 +476,20 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
if( timeoffset != 0 ) // jeżeli jest przesunięcie rozkładu if( timeoffset != 0 ) // jeżeli jest przesunięcie rozkładu
{ {
long i_end = StationCount + 1; long i_end = StationCount + 1;
int adjustedtime; // do zwiększania czasu float adjustedtime; // do zwiększania czasu
for (auto i = 1; i < i_end; ++i) // bez with, bo ciężko się przenosi na C++ for (auto i = 1; i < i_end; ++i) // bez with, bo ciężko się przenosi na C++
{ {
if ((TimeTable[i].Ah >= 0)) if ((TimeTable[i].Ah >= 0))
{ {
adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty adjustedtime = clamp_circular<float>( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty
TimeTable[i].Am = adjustedtime % 60; TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.f;
TimeTable[i].Ah = (adjustedtime / 60) % 24; TimeTable[i].Ah = int((adjustedtime) / 60) % 24;
} }
if ((TimeTable[i].Dh >= 0)) if ((TimeTable[i].Dh >= 0))
{ {
adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty adjustedtime = clamp_circular<float>( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty
TimeTable[i].Dm = adjustedtime % 60; TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.f;
TimeTable[i].Dh = (adjustedtime / 60) % 24; TimeTable[i].Dh = int((adjustedtime) / 60) % 24;
} }
} }
} }
@@ -533,6 +533,8 @@ void TTrainParameters::serialize( dictionary_source *Output ) const {
Output->insert( "train_enginetype", LocSeries ); Output->insert( "train_enginetype", LocSeries );
Output->insert( "train_engineload", LocLoad ); Output->insert( "train_engineload", LocLoad );
Output->insert( "train_stationfrom", Relation1 );
Output->insert( "train_stationto", Relation2 );
Output->insert( "train_stationindex", StationIndex ); Output->insert( "train_stationindex", StationIndex );
Output->insert( "train_stationcount", StationCount ); Output->insert( "train_stationcount", StationCount );
if( StationCount > 0 ) { if( StationCount > 0 ) {

View File

@@ -24,18 +24,18 @@ static char const *hrsd = ".";
struct TMTableLine struct TMTableLine
{ {
double km; // kilometraz linii float km; // kilometraz linii
double vmax; // predkosc rozkladowa przed przystankiem float vmax; // predkosc rozkladowa przed przystankiem
// StationName:string[32]; //nazwa stacji ('_' zamiast spacji) // StationName:string[32]; //nazwa stacji ('_' zamiast spacji)
// StationWare:string[32]; //typ i wyposazenie stacji, oddz. przecinkami} // StationWare:string[32]; //typ i wyposazenie stacji, oddz. przecinkami}
std::string StationName; // nazwa stacji ('_' zamiast spacji) std::string StationName; // nazwa stacji ('_' zamiast spacji)
std::string StationWare; // typ i wyposazenie stacji, oddz. przecinkami} std::string StationWare; // typ i wyposazenie stacji, oddz. przecinkami}
int TrackNo; // ilosc torow szlakowych int TrackNo; // ilosc torow szlakowych
int Ah; int Ah;
int Am; // godz. i min. przyjazdu, -1 gdy bez postoju float Am; // godz. i min. przyjazdu, -1 gdy bez postoju
int Dh; int Dh;
int Dm; // godz. i min. odjazdu float Dm; // godz. i min. odjazdu
double tm; // czas jazdy do tej stacji w min. (z kolumny) float tm; // czas jazdy do tej stacji w min. (z kolumny)
TMTableLine() TMTableLine()
{ {
km = 0; km = 0;

View File

@@ -176,6 +176,7 @@ init() {
"all doors (open)", "all doors (open)",
"all doors (close)", "all doors (close)",
"doorstep", "doorstep",
"door control mode",
"departure signal", "departure signal",
"upper headlight", "upper headlight",
"left headlight", "left headlight",
@@ -386,6 +387,7 @@ init() {
u8"drzwi (otwórz)", u8"drzwi (otwórz)",
u8"drzwi (zamknij)", u8"drzwi (zamknij)",
u8"stopień drzwi", u8"stopień drzwi",
u8"tryb sterowania drzwiami",
u8"sygnal odjazdu", u8"sygnal odjazdu",
u8"reflektor gorny", u8"reflektor gorny",
u8"reflektor lewy", u8"reflektor lewy",
@@ -504,6 +506,7 @@ init() {
"doorallon_sw:", "doorallon_sw:",
"dooralloff_sw:", "dooralloff_sw:",
"doorstep_sw:", "doorstep_sw:",
"doormode_sw",
"departure_signal_bt:", "departure_signal_bt:",
"upperlight_sw:", "upperlight_sw:",
"leftlight_sw:", "leftlight_sw:",

View File

@@ -165,6 +165,7 @@ enum string {
cab_doorallon_sw, cab_doorallon_sw,
cab_dooralloff_sw, cab_dooralloff_sw,
cab_doorstep_sw, cab_doorstep_sw,
cab_doormode_sw,
cab_departure_signal_bt, cab_departure_signal_bt,
cab_upperlight_sw, cab_upperlight_sw,
cab_leftlight_sw, cab_leftlight_sw,

View File

@@ -137,6 +137,8 @@ bool ui_layer::init(GLFWwindow *Window)
{ {
0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x0020, 0x00FF, // Basic Latin + Latin Supplement
0x0100, 0x017F, // Latin Extended-A 0x0100, 0x017F, // Latin Extended-A
0x2070, 0x2079, // superscript
0x2500, 0x256C, // box drawings
0, 0,
}; };

View File

@@ -268,6 +268,24 @@ bool string_starts_with(const std::string &string, const std::string &begin)
return string.compare(0, begin.length(), begin) == 0; return string.compare(0, begin.length(), begin) == 0;
} }
std::string const fractionlabels[] = { " ", u8"¹", u8"²", u8"³", u8"", u8"", u8"", u8"", u8"", u8"" };
std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width ) {
float minutesintegral;
auto const minutesfractional { std::modf( Minutes, &minutesintegral ) };
auto const width { Width - 1 };
auto minutes = (
std::string( width - 1, ' ' )
+ ( Leadingzero ?
to_string( 100 + minutesintegral ).substr( 1, 2 ) :
to_string( minutesintegral, 0 ) ) );
return (
minutes.substr( minutes.size() - width, width )
+ fractionlabels[ static_cast<int>( std::floor( minutesfractional * 10 + 0.1 ) ) ] );
}
int stol_def(const std::string &str, const int &DefaultValue) { int stol_def(const std::string &str, const int &DefaultValue) {
int result { DefaultValue }; int result { DefaultValue };

View File

@@ -119,6 +119,7 @@ std::string to_string(double Value);
std::string to_string(double Value, int precision); std::string to_string(double Value, int precision);
std::string to_string(double Value, int precision, int width); std::string to_string(double Value, int precision, int width);
std::string to_hex_str( int const Value, int const width = 4 ); std::string to_hex_str( int const Value, int const width = 4 );
std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width );
inline std::string to_string(bool Value) { inline std::string to_string(bool Value) {

View File

@@ -1 +1 @@
#define VERSION_INFO "M7 (GL3 NET) 15.04.2019" #define VERSION_INFO "M7 (sim) 23.05.2019"