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

Merge branch 'tmj-dev' into milek-dev

This commit is contained in:
milek7
2019-05-23 22:26:31 +02:00
28 changed files with 775 additions and 392 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,7 +2813,9 @@ bool TController::IncBrake()
} }
} }
if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition > 0 ) { if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition > 0 ) {
mvOccupied->BrakeReleaser( 0 ); if( mvOccupied->Hamulec->Releaser() ) {
mvOccupied->BrakeReleaser( 0 );
}
} }
break; break;
} }
@@ -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;
@@ -2982,6 +3005,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 {
@@ -2993,6 +3017,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)
@@ -3002,6 +3027,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 ) ) );
@@ -3441,6 +3467,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
@@ -3472,6 +3513,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()
@@ -3568,13 +3629,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
pVehicle->MoverParameters->OperateDoors( side::right, false ); if( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
pVehicle->MoverParameters->OperateDoors( side::left, false ); || ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) {
pVehicle->MoverParameters->OperateDoors( side::right, 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 );
@@ -4137,6 +4199,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 );
} }
@@ -4965,54 +5028,50 @@ 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..." );
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); while( mvOccupied->DecLocalBrakeLevel( 1 ) ) { // dociśnij sklad
TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI ;
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
int n = iVehicleCount; // ile wagonów ma zostać
do
{ // szukanie pojazdu do odczepienia
d = p->DirectionGet() > 0 ?
end::front :
end::rear; // numer sprzęgu od strony czoła składu
// if (p->MoverParameters->Couplers[d].CouplerType==Articulated)
// //jeśli sprzęg typu wózek (za mało)
if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany
// if (p->GetTrack()->) //a nie stoi na torze warsztatowym
// (ustalić po czym poznać taki tor)
++n; // to liczymy człony jako jeden
p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać
// GBH p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował
BrakeLevelSet(gbh_RP);
if (n)
{ // jeśli jeszcze nie koniec
p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy
if (!p)
iVehicleCount = -2,
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
}
} while (n--);
if( ( p == nullptr )
|| ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) {
// no target, or already just virtual coupling
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
iVehicleCount = -2; // odczepiono, co było do odczepienia
} else if ( p->Dettach(d) == coupling::faux ) {
// tylko jeśli odepnie
WriteLog( mvOccupied->Name + " odczepiony." );
iVehicleCount = -2;
} // a jak nie, to dociskać dalej
}
if (iVehicleCount >= 0) // zmieni się po odczepieniu
if (!mvOccupied->DecLocalBrakeLevel(1))
{ // dociśnij sklad
WriteLog( mvOccupied->Name + " dociskanie..." );
// mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę
// Ready=true; //zamiast sprawdzenia odhamowania całego składu
IncSpeed(); // dla (Ready)==false nie ruszy
} }
IncSpeed();
}
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute));
TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
int n = iVehicleCount; // ile wagonów ma zostać
do
{ // szukanie pojazdu do odczepienia
d = p->DirectionGet() > 0 ?
end::front :
end::rear; // numer sprzęgu od strony czoła składu
// if (p->MoverParameters->Couplers[d].CouplerType==Articulated)
// //jeśli sprzęg typu wózek (za mało)
if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany
// if (p->GetTrack()->) //a nie stoi na torze warsztatowym
// (ustalić po czym poznać taki tor)
++n; // to liczymy człony jako jeden
p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać
// GBH p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował
BrakeLevelSet(gbh_RP);
if (n)
{ // jeśli jeszcze nie koniec
p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy
if (!p)
iVehicleCount = -2,
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
}
} while (n--);
if( ( p == nullptr )
|| ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) {
// no target, or already just virtual coupling
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
iVehicleCount = -2; // odczepiono, co było do odczepienia
} else if ( p->Dettach(d) == coupling::faux ) {
// tylko jeśli odepnie
WriteLog( mvOccupied->Name + " odczepiony." );
iVehicleCount = -2;
} // a jak nie, to dociskać dalej
} }
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress)) 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
@@ -5683,16 +5742,32 @@ 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
mvOccupied->BrakeReleaser( 1 ); if( ( AccDesired > -0.03 )
&& ( false == mvOccupied->Hamulec->Releaser() ) ) {
if( mvOccupied->PipePress < 3.0 ) {
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 )
@@ -5700,31 +5775,37 @@ TController::UpdateSituation(double dt) {
&& ( 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 ) ) {
// napełnianie w Oerlikonie // napełnianie w Oerlikonie
/* mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_FS ) ); GBH */ /* mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_FS ) ); GBH */
BrakeLevelSet(gbh_FS); BrakeLevelSet( gbh_FS );
// don't charge the brakes too often, or we risk overcharging // don't charge the brakes too often, or we risk overcharging
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 )
&& ( mvOccupied->EqvtPipePress > ( fReady < 0.25 ? 5.1 : 5.2 ) ) ) { && ( mvOccupied->EqvtPipePress > ( fReady < 0.25 ? 5.1 : 5.2 ) ) ) {
/* GBH mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); */ /* GBH mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); */
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) +
@@ -5763,17 +5844,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 );
}
}
} }
} }
} }
@@ -6528,17 +6598,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;
}; };
@@ -6607,14 +6678,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

@@ -201,6 +201,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
@@ -251,6 +255,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
@@ -280,7 +285,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!)
@@ -318,7 +323,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
@@ -363,7 +367,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

@@ -2320,7 +2320,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)
@@ -2782,6 +2784,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);
@@ -2891,6 +2895,10 @@ bool TDynamicObject::Update(double dt, double dt1)
&& ( 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))
FzadED = 0; //pętla bezpieczeństwa - bez ED FzadED = 0; //pętla bezpieczeństwa - bez ED
@@ -3068,6 +3076,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
@@ -4345,10 +4355,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 = "";
@@ -4930,6 +4936,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:" ) {
@@ -6106,30 +6124,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->NextC( couplingtype ) ) != nullptr ) {
} if( d->MoverParameters->Power > 1.0 ) {
else if( ( d->PrevConnected() != nullptr ) return d;
&& ( 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; // if we didn't yet find a suitable vehicle try in the other direction
d = this; // zaczynamy od aktualnego
while( ( d = d->PrevC( couplingtype ) ) != nullptr ) {
if( d->MoverParameters->Power > 1.0 ) {
return d;
}
}
// if we still don't have a match give up
return this;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -6610,7 +6630,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

@@ -659,6 +659,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

@@ -127,7 +127,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

@@ -74,7 +74,6 @@ struct global_settings {
bool bLiveTraction{ true }; bool bLiveTraction{ true };
float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f }; glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f };
double fFogStart{ 1700 };
double fFogEnd{ 2000 }; double fFogEnd{ 2000 };
std::string Season{}; // season of the year, based on simulation date std::string Season{}; // season of the year, based on simulation date
std::string Weather{ "cloudy:" }; // current weather std::string Weather{ "cloudy:" }; // current weather
@@ -136,7 +135,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

@@ -767,6 +767,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
@@ -1163,6 +1164,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
@@ -1311,6 +1313,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;
@@ -1345,8 +1349,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
@@ -1554,6 +1556,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

@@ -653,11 +653,18 @@ void TMoverParameters::UpdatePantVolume(double dt)
{ // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak { // 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 )
&& ( false == ConverterFlag ) ) { || ( PantographCompressorStart == start_t::manualwithautofallback ) )
PantCompFlag = false; && ( ( true == PantRearUp )
} || ( true == PantFrontUp ) ) ) {
// automatic start if the pressure is too low
PantCompFlag = true;
}
if( ( true == PantCompFlag )
&& ( false == Battery )
&& ( false == ConverterFlag ) ) {
PantCompFlag = false;
} }
if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący
@@ -1684,7 +1691,9 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed)
else { else {
++MainCtrlPos; ++MainCtrlPos;
OK = true; OK = true;
} if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos))
DecScndCtrl(2);
}
break; break;
} }
@@ -1846,6 +1855,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);
@@ -1987,13 +1998,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);
} }
@@ -3901,7 +3916,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;
@@ -4416,7 +4442,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
@@ -5915,7 +5941,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(
@@ -5926,7 +5951,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(
@@ -5968,7 +5992,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(
@@ -5979,7 +6002,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(
@@ -6014,6 +6036,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)
@@ -6064,25 +6093,34 @@ void TMoverParameters::CheckEIMIC(double dt)
} }
break; break;
case 2: case 2:
switch (MainCtrlPos) if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay))
{ {
case 0: double delta = (MainCtrlActualPos == MainCtrlPos ? dt*CtrlDelay : 0.01);
eimic = -1.0; switch (MainCtrlPos)
break; {
case 1: case 0:
eimic -= clamp(1.0 + eimic, 0.0, dt*0.15); //odejmuj do -1 case 1:
if (eimic > 0) eimic = 0; eimic -= clamp(1.0 + eimic, 0.0, delta); //odejmuj do -1
break; if (eimic > 0) eimic = 0;
case 2: break;
eimic -= clamp(0.0 + eimic, 0.0, dt*0.15); //odejmuj do 0 case 2:
break; eimic -= clamp(0.0 + eimic, 0.0, delta); //odejmuj do 0
case 3: break;
eimic += clamp(0.0 - eimic, 0.0, dt*0.15); //dodawaj do 0 case 3:
break; eimic += clamp(0.0 - eimic, 0.0, delta); //dodawaj do 0
case 4: break;
eimic += clamp(1.0 - eimic, 0.0, dt*0.15); //dodawaj do 1 case 4:
if (eimic < 0) eimic = 0; eimic += clamp(1.0 - eimic, 0.0, delta); //dodawaj do 1
break; if (eimic < 0) eimic = 0;
break;
}
}
if (MainCtrlActualPos == MainCtrlPos)
LastRelayTime += dt;
else
{
LastRelayTime = 0;
MainCtrlActualPos = MainCtrlPos;
} }
break; break;
case 3: case 3:
@@ -6090,7 +6128,11 @@ void TMoverParameters::CheckEIMIC(double dt)
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()
@@ -6910,12 +6952,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 Doors.instances[ Door ].open_permit = State;
|| ( ( true == Battery )
&& ( false == Doors.is_locked ) ) ) {
Doors.instances[ Door ].open_permit = State;
}
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
@@ -6934,6 +6971,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 ] };
@@ -7041,15 +7106,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 )
@@ -7077,13 +7144,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 ) )
@@ -8375,12 +8447,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, "" );
@@ -8683,6 +8749,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
@@ -8705,6 +8772,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
{ {
@@ -8735,6 +8803,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 ) );
@@ -8961,6 +9037,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: {
@@ -10048,6 +10125,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 ?
@@ -10064,12 +10148,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
@@ -10079,24 +10161,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 );
@@ -10109,12 +10187,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
@@ -10125,24 +10201,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

253
Train.cpp
View File

@@ -327,6 +327,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 },
@@ -388,8 +389,11 @@ TTrain::TTrain() {
bHeat[ i ] = false; bHeat[ i ] = false;
} }
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 )
@@ -454,10 +458,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 ) );
@@ -496,6 +500,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 ] );
@@ -503,6 +508,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 ] );
@@ -648,7 +656,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 );
} }
@@ -781,7 +790,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 {
@@ -801,7 +810,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 {
@@ -1712,10 +1721,11 @@ void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Co
} }
} }
void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) // TODO: replace battery with a two-state device, update switch code accordingly
{ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down if( Command.action != GLFW_REPEAT ) {
// keep the switch from flipping back and forth if key is held down
if( false == Train->mvOccupied->Battery ) { if( false == Train->mvOccupied->Battery ) {
// turn on // turn on
OnCommand_batteryenable( Train, Command ); OnCommand_batteryenable( Train, Command );
@@ -1729,16 +1739,13 @@ 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( true == Train->mvOccupied->Battery ) { return; } // already on
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// ignore repeats // visual feedback
// wyłącznik jest też w SN61, ewentualnie załączać prąd na stałe z poziomu FIZ Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch );
if( true == Train->mvOccupied->Battery ) { return; } // already on
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();
@@ -1750,19 +1757,23 @@ void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command
} }
} }
} }
else if( Command.action == GLFW_RELEASE ) {
if( Train->ggBatteryButton.type() == TGaugeType::push ) {
// return the switch to neutral position
Train->ggBatteryButton.UpdateValue( 0.5f );
}
}
} }
void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) { 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( false == Train->mvOccupied->Battery ) { return; } // already off
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// ignore repeats // visual feedback
Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch );
if( false == Train->mvOccupied->Battery ) { return; } // already off
if( Train->mvOccupied->BatterySwitch( false ) ) { 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
@@ -1771,6 +1782,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 )
@@ -4129,7 +4146,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 );
@@ -4139,6 +4156,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 ) {
@@ -4157,7 +4182,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 );
} }
} }
@@ -4288,37 +4317,73 @@ 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 ) };
// visual feedback if( Train->ggDoorLeftPermitButton.type() == TGaugeType::push ) {
Train->ggDoorLeftPermitButton.UpdateValue( 1.0, Train->dsbSwitch ); // impulse switch
Train->mvOccupied->PermitDoors( side );
// visual feedback
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 ) {
// visual feedback
Train->ggDoorLeftPermitButton.UpdateValue( 0.0, Train->dsbSwitch ); if( Train->ggDoorLeftPermitButton.type() == TGaugeType::push ) {
// impulse switch
// visual feedback
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 ) };
// visual feedback if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) {
Train->ggDoorRightPermitButton.UpdateValue( 1.0, Train->dsbSwitch ); // impulse switch
Train->mvOccupied->PermitDoors( side );
// visual feedback
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 ) {
// visual feedback
Train->ggDoorRightPermitButton.UpdateValue( 0.0, Train->dsbSwitch ); if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) {
// impulse switch
// visual feedback
Train->ggDoorRightPermitButton.UpdateValue( 0.0, Train->dsbSwitch );
}
} }
} }
@@ -4688,6 +4753,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 == FreeFlyModeFlag ) if( ( true == FreeFlyModeFlag )
@@ -5171,7 +5243,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;
@@ -5240,6 +5312,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->NextC(128) : p->PrevC(128)) != (kier ? p->NextC(4) : p->PrevC(4))) if ((kier ? p->NextC(128) : p->PrevC(128)) != (kier ? p->NextC(4) : p->PrevC(4)))
iUnitNo++; iUnitNo++;
@@ -5282,16 +5375,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) {
@@ -6493,7 +6581,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 );
} }
@@ -7068,28 +7156,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 ?
@@ -7413,9 +7484,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 ?
@@ -7578,7 +7650,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 );
@@ -7588,8 +7665,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 ) {
@@ -7807,8 +7887,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 }
}; };
{ {
@@ -7978,6 +8058,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

@@ -330,6 +330,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 );
@@ -675,6 +676,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

@@ -154,6 +154,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

@@ -148,6 +148,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 ) {
@@ -634,6 +634,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

@@ -229,6 +229,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 ) };
@@ -239,7 +240,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,
@@ -274,7 +275,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;
@@ -317,67 +318,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 };
vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej if( tableline->vmax == previoustableline->vmax ) {
std::string const station = ( vmaxchange = false;
}
}
std::string vmax { " " };
if( true == vmaxchange ) {
vmax += to_string( tableline->vmax, 0 );
vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej
}
auto const station { (
Bezogonkow( tableline->StationName, true ) 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() ?
name :
title )
+ "###" + name };
if( true == ImGui::Begin( panelname.c_str(), &is_open, flags ) ) {
for( auto const &line : text_lines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
if( is_expanded ) {
ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 1, 0 ) );
for( auto const &line : m_tablelines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
ImGui::PopStyleVar();
}
}
ImGui::End();
}
void void
debug_panel::update() { debug_panel::update() {
@@ -725,7 +785,8 @@ 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 {
{ "efill: ", mover.dizel_fill }, { " rpm: ", mover.enrot * 60.0 },
{ "efill: ", mover.dizel_fill },
{ "etorq: ", mover.dizel_Torque }, { "etorq: ", mover.dizel_Torque },
{ "creal: ", mover.dizel_engage }, { "creal: ", mover.dizel_engage },
{ "cdesi: ", mover.dizel_engagestate }, { "cdesi: ", mover.dizel_engagestate },

View File

@@ -50,12 +50,14 @@ public:
: ui_panel( Name, Isopen ) {} : ui_panel( Name, Isopen ) {}
void update() override; void update() override;
void render() override;
bool is_expanded{ false }; bool is_expanded{ false };
private: private:
// members // members
std::array<char, 256> m_buffer; std::array<char, 256> m_buffer;
std::vector<text_line> m_tablelines;
}; };
class debug_panel : public ui_panel { class debug_panel : public ui_panel {

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)
@@ -358,12 +358,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
@@ -408,12 +408,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
@@ -475,20 +475,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;
} }
} }
} }
@@ -532,6 +532,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

@@ -32,17 +32,18 @@ int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental
void void
opengl_light::apply_intensity( float const Factor ) { opengl_light::apply_intensity( float const Factor ) {
if( Factor == 1.0 ) { if( Factor == 1.f ) {
::glLightfv( id, GL_AMBIENT, glm::value_ptr( ambient ) ); ::glLightfv( id, GL_AMBIENT, glm::value_ptr( ambient ) );
::glLightfv( id, GL_DIFFUSE, glm::value_ptr( diffuse ) ); ::glLightfv( id, GL_DIFFUSE, glm::value_ptr( diffuse ) );
::glLightfv( id, GL_SPECULAR, glm::value_ptr( specular ) ); ::glLightfv( id, GL_SPECULAR, glm::value_ptr( specular ) );
} }
else { else {
auto const factor{ clamp( Factor, 0.05f, 1.f ) };
// temporary light scaling mechanics (ultimately this work will be left to the shaders // temporary light scaling mechanics (ultimately this work will be left to the shaders
glm::vec4 scaledambient( ambient.r * Factor, ambient.g * Factor, ambient.b * Factor, ambient.a ); glm::vec4 scaledambient( ambient.r * factor, ambient.g * factor, ambient.b * factor, ambient.a );
glm::vec4 scaleddiffuse( diffuse.r * Factor, diffuse.g * Factor, diffuse.b * Factor, diffuse.a ); glm::vec4 scaleddiffuse( diffuse.r * factor, diffuse.g * factor, diffuse.b * factor, diffuse.a );
glm::vec4 scaledspecular( specular.r * Factor, specular.g * Factor, specular.b * Factor, specular.a ); glm::vec4 scaledspecular( specular.r * factor, specular.g * factor, specular.b * factor, specular.a );
glLightfv( id, GL_AMBIENT, glm::value_ptr( scaledambient ) ); glLightfv( id, GL_AMBIENT, glm::value_ptr( scaledambient ) );
glLightfv( id, GL_DIFFUSE, glm::value_ptr( scaleddiffuse ) ); glLightfv( id, GL_DIFFUSE, glm::value_ptr( scaleddiffuse ) );
glLightfv( id, GL_SPECULAR, glm::value_ptr( scaledspecular ) ); glLightfv( id, GL_SPECULAR, glm::value_ptr( scaledspecular ) );
@@ -2194,34 +2195,36 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being
// render // render
if( Dynamic->mdLowPolyInt ) { if( Dynamic->mdLowPolyInt ) {
// low poly interior // HACK: reduce light level for vehicle interior if there's strong global lighting source
/* auto const luminance { static_cast<float>( 0.5 * ( std::max( 0.3, Global.fLuminance - Global.Overcast ) ) ) };
if( ( true == FreeFlyModeFlag ) m_sunlight.apply_intensity(
|| ( ( Dynamic->mdKabina == nullptr ) || ( false == Dynamic->bDisplayCab ) ) ) { clamp( (
*/ Dynamic->fShade > 0.f ?
/* Dynamic->fShade :
// enable cab light if needed 1.f )
if( Dynamic->InteriorLightLevel > 0.0f ) { - luminance,
0.f, 1.f ) );
// crude way to light the cabin, until we have something more complete in place // low poly interior
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) ); Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
} // HACK: if the model has low poly interior, we presume the load is placed inside and also affected by reduced light level
*/ if( Dynamic->mdLoad ) {
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance ); // renderowanie nieprzezroczystego ładunku
/* Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
if( Dynamic->InteriorLightLevel > 0.0f ) {
// reset the overall ambient
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( m_baseambient ) );
}
*/
/*
} }
*/
m_sunlight.apply_intensity( Dynamic->fShade > 0.f ? Dynamic->fShade : 1.f );
} }
if( Dynamic->mdModel ) else {
// HACK: if the model lacks low poly interior, we presume the load is placed outside
if( Dynamic->mdLoad ) {
// renderowanie nieprzezroczystego ładunku
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
}
}
if( Dynamic->mdModel ) {
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku }
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
// post-render cleanup // post-render cleanup
m_renderspecular = false; m_renderspecular = false;
if( Dynamic->fShade > 0.0f ) { if( Dynamic->fShade > 0.0f ) {

View File

@@ -163,14 +163,22 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch
// atmosphere color; legacy parameter, no longer used // atmosphere color; legacy parameter, no longer used
Input.getTokens( 3 ); Input.getTokens( 3 );
// fog range // fog range
Input.getTokens( 2 ); {
Input double fograngestart, fograngeend;
>> Global.fFogStart Input.getTokens( 2 );
>> Global.fFogEnd; Input
>> fograngestart
>> fograngeend;
if( Global.fFogEnd > 0.0 ) { if( Global.fFogEnd != 0.0 ) {
// fog colour; optional legacy parameter, no longer used // fog colour; optional legacy parameter, no longer used
Input.getTokens( 3 ); Input.getTokens( 3 );
}
Global.fFogEnd =
clamp(
Random( std::min( fograngestart, fograngeend ), std::max( fograngestart, fograngeend ) ),
10.0, 2000.0 );
} }
std::string token { Input.getToken<std::string>() }; std::string token { Input.getToken<std::string>() };

View File

@@ -131,6 +131,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",
@@ -296,6 +297,7 @@ init() {
"drzwi (otworz)", "drzwi (otworz)",
"drzwi (zamknij)", "drzwi (zamknij)",
"stopien drzwi", "stopien drzwi",
"tryb sterowania drzwiami",
"sygnal odjazdu", "sygnal odjazdu",
"reflektor gorny", "reflektor gorny",
"reflektor lewy", "reflektor lewy",
@@ -414,6 +416,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

@@ -120,6 +120,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

@@ -101,8 +101,15 @@ ui_layer::init( GLFWwindow *Window ) {
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
static ImWchar const glyphranges[] = {
0x0020, 0x00FF, // ascii + extension
0x2070, 0x2079, // superscript
0x2500, 0x256C, // box drawings
0,
};
m_imguiio = &ImGui::GetIO(); m_imguiio = &ImGui::GetIO();
m_imguiio->Fonts->AddFontFromFileTTF("fonts/dejavusansmono.ttf", 13.0f); m_imguiio->Fonts->AddFontFromFileTTF( "fonts/dejavusansmono.ttf", 13.0f, nullptr, &glyphranges[ 0 ] );
ImGui::StyleColorsClassic(); ImGui::StyleColorsClassic();
ImGui_ImplGlfw_InitForOpenGL(m_window); ImGui_ImplGlfw_InitForOpenGL(m_window);

View File

@@ -1,4 +1,4 @@
/* /*
This Source Code Form is subject to the This Source Code Form is subject to the
terms of the Mozilla Public License, v. terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not 2.0. If a copy of the MPL was not
@@ -246,6 +246,24 @@ std::string to_hex_str( int const Value, int const Width )
return converter.str(); return converter.str();
}; };
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

@@ -108,6 +108,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 5.04.2019, based on tmj-a081077c" #define VERSION_INFO "M7 23.05.2019"