mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 17:29:18 +02:00
Merge branch 'tmj-dev' into milek-dev
This commit is contained in:
209
Driver.cpp
209
Driver.cpp
@@ -454,7 +454,7 @@ bool TController::TableAddNew()
|
||||
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)
|
||||
auto lookup =
|
||||
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 );
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -573,7 +577,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
||||
for( auto *pEvent : events ) {
|
||||
if( pEvent != nullptr ) // jeśli jest semafor na tym torze
|
||||
{ // 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
|
||||
|
||||
@@ -1018,7 +1022,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
|
||||
if (TrainParams->StationIndex < TrainParams->StationCount) {
|
||||
// jeśli są dalsze stacje, czekamy do godziny odjazdu
|
||||
if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute)) {
|
||||
if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute + simulation::Time.data().wSecond*0.0167 )) {
|
||||
// z dalszą akcją czekamy do godziny odjazdu
|
||||
IsAtPassengerStop = false;
|
||||
// przy jakim dystansie (stanie licznika) ma przesunąć na następny postój
|
||||
@@ -1470,7 +1474,8 @@ TController::braking_distance_multiplier( float const Targetvelocity ) const {
|
||||
if( ( mvOccupied->TrainType == dt_DMU )
|
||||
&& ( mvOccupied->Vel < 40.0 )
|
||||
&& ( 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
|
||||
if( ( fBrake_a0[ 1 ] > 0.2 )
|
||||
@@ -2008,7 +2013,7 @@ void TController::AutoRewident()
|
||||
fBrakeReaction = 0.25;
|
||||
}
|
||||
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;
|
||||
}
|
||||
else if (ustaw > 16) {
|
||||
@@ -2120,11 +2125,12 @@ bool TController::CheckVehicles(TOrders user)
|
||||
while (p)
|
||||
{
|
||||
// HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi...
|
||||
if( ( p != pVehicle )
|
||||
&& ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 )
|
||||
if( p != pVehicle ) {
|
||||
if( ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 )
|
||||
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) {
|
||||
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
|
||||
p->MoverParameters->BatterySwitch( true );
|
||||
}
|
||||
// enable heating and converter in carriages with can be heated
|
||||
if( p->MoverParameters->HeatingPower > 0 ) {
|
||||
p->MoverParameters->HeatingAllow = true;
|
||||
@@ -2366,6 +2372,10 @@ double TController::BrakeAccFactor() const
|
||||
|| ( 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 );
|
||||
}
|
||||
/*
|
||||
if (mvOccupied->TrainType == dt_DMU && mvOccupied->Vel > 40 && VelNext<40)
|
||||
Factor *= 1 + 0.25 * ( (1600 - VelNext * VelNext) / (mvOccupied->Vel * mvOccupied->Vel) );
|
||||
*/
|
||||
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
|
||||
// TODO: add easier ways to access front/rear coupler taking into account vehicle's direction
|
||||
standalone =
|
||||
( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) )
|
||||
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) ) );
|
||||
( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr )
|
||||
|| ( ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control )
|
||||
&& ( vehicle->MoverParameters->Couplers[ end::front ].Connected->Power > 1 ) ) )
|
||||
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr )
|
||||
|| ( ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control )
|
||||
&& ( vehicle->MoverParameters->Couplers[ end::rear ].Connected->Power > 1 ) ) ) );
|
||||
vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
|
||||
}
|
||||
}
|
||||
@@ -2770,17 +2784,15 @@ bool TController::IncBrake()
|
||||
{
|
||||
if( /*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.1 ) {
|
||||
OK = /*mvOccupied->*/BrakeLevelAdd( BrakingInitialLevel ); //GBH
|
||||
/*
|
||||
// HACK: stronger braking to overcome SA134 engine behaviour
|
||||
if( ( mvOccupied->TrainType == dt_DMU )
|
||||
&& ( VelNext == 0.0 )
|
||||
&& ( fBrakeDist < 200.0 ) ) {
|
||||
mvOccupied->BrakeLevelAdd(
|
||||
BrakeLevelAdd(
|
||||
fBrakeDist / ActualProximityDist < 0.8 ?
|
||||
1.0 :
|
||||
3.0 );
|
||||
0.5 :
|
||||
1.0 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2801,8 +2813,10 @@ bool TController::IncBrake()
|
||||
}
|
||||
}
|
||||
if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition > 0 ) {
|
||||
if( mvOccupied->Hamulec->Releaser() ) {
|
||||
mvOccupied->BrakeReleaser( 0 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TBrakeSystem::ElectroPneumatic: {
|
||||
@@ -2833,20 +2847,20 @@ bool TController::IncBrake()
|
||||
bool TController::IncBrakeEIM()
|
||||
{ // zwiększenie hamowania
|
||||
bool OK = false;
|
||||
switch (mvControlling->EIMCtrlType)
|
||||
switch (mvOccupied->EIMCtrlType)
|
||||
{
|
||||
case 0:
|
||||
OK = mvControlling->IncLocalBrakeLevel(1);
|
||||
OK = mvOccupied->IncLocalBrakeLevel(1);
|
||||
break;
|
||||
case 1:
|
||||
OK = mvControlling->MainCtrlPos > 0;
|
||||
OK = mvOccupied->MainCtrlPos > 0;
|
||||
if (OK)
|
||||
mvControlling->MainCtrlPos = 0;
|
||||
mvOccupied->MainCtrlPos = 0;
|
||||
break;
|
||||
case 2:
|
||||
OK = mvControlling->MainCtrlPos > 1;
|
||||
OK = mvOccupied->MainCtrlPos > 1;
|
||||
if (OK)
|
||||
mvControlling->MainCtrlPos = 1;
|
||||
mvOccupied->MainCtrlPos = 1;
|
||||
break;
|
||||
}
|
||||
return OK;
|
||||
@@ -2855,7 +2869,8 @@ bool TController::IncBrakeEIM()
|
||||
bool TController::DecBrake()
|
||||
{ // zmniejszenie siły hamowania
|
||||
bool OK = false;
|
||||
double deltaAcc = 0;
|
||||
double deltaAcc = -1.0;
|
||||
double pos_diff = 1.0;
|
||||
switch (mvOccupied->BrakeSystem)
|
||||
{
|
||||
case TBrakeSystem::Individual:
|
||||
@@ -2865,7 +2880,12 @@ bool TController::DecBrake()
|
||||
OK = mvOccupied->DecLocalBrakeLevel(1 + floor(0.5 + fabs(AccDesired)));
|
||||
break;
|
||||
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 (/*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition > 0)
|
||||
@@ -2884,8 +2904,11 @@ bool TController::DecBrake()
|
||||
if (!OK) {
|
||||
OK = DecBrakeEIM();
|
||||
}
|
||||
/*
|
||||
// NOTE: disabled, duplicate of AI's behaviour in UpdateSituation()
|
||||
if (mvOccupied->PipePress < 3.0)
|
||||
Need_BrakeRelease = true;
|
||||
*/
|
||||
break;
|
||||
case TBrakeSystem::ElectroPneumatic:
|
||||
if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor) {
|
||||
@@ -2916,20 +2939,20 @@ bool TController::DecBrake()
|
||||
bool TController::DecBrakeEIM()
|
||||
{ // zmniejszenie siły hamowania
|
||||
bool OK = false;
|
||||
switch (mvControlling->EIMCtrlType)
|
||||
switch (mvOccupied->EIMCtrlType)
|
||||
{
|
||||
case 0:
|
||||
OK = mvControlling->DecLocalBrakeLevel(1);
|
||||
OK = mvOccupied->DecLocalBrakeLevel(1);
|
||||
break;
|
||||
case 1:
|
||||
OK = mvControlling->MainCtrlPos < 2;
|
||||
OK = mvOccupied->MainCtrlPos < 2;
|
||||
if (OK)
|
||||
mvControlling->MainCtrlPos = 2;
|
||||
mvOccupied->MainCtrlPos = 2;
|
||||
break;
|
||||
case 2:
|
||||
OK = mvControlling->MainCtrlPos < 3;
|
||||
OK = mvOccupied->MainCtrlPos < 3;
|
||||
if (OK)
|
||||
mvControlling->MainCtrlPos = 3;
|
||||
mvOccupied->MainCtrlPos = 3;
|
||||
break;
|
||||
}
|
||||
return OK;
|
||||
@@ -2982,6 +3005,7 @@ bool TController::IncSpeed()
|
||||
// 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)
|
||||
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 parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) };
|
||||
auto const useseriesmodevoltage {
|
||||
@@ -2993,6 +3017,7 @@ bool TController::IncSpeed()
|
||||
( mvControlling->Imax > mvControlling->ImaxLo )
|
||||
|| ( fVoltage < useseriesmodevoltage )
|
||||
|| ( ( true == sufficienttractionforce )
|
||||
&& ( true == sufficientacceleration )
|
||||
&& ( 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
|
||||
// (if there's only one parallel mode configuration it'll be used regardless of current speed)
|
||||
@@ -3002,6 +3027,7 @@ bool TController::IncSpeed()
|
||||
&& ( useseriesmode ?
|
||||
mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 :
|
||||
( ( true == sufficienttractionforce )
|
||||
&& ( true == sufficientacceleration )
|
||||
&& ( mvOccupied->Vel <= ( IsCargoTrain ? 55 : 45 ) + ( parallelmodefieldshunting ? 5 : 0 ) ) ?
|
||||
mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 :
|
||||
mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo ) ) );
|
||||
@@ -3441,6 +3467,21 @@ void TController::SetTimeControllers()
|
||||
mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_NP));
|
||||
}
|
||||
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
|
||||
|
||||
@@ -3472,6 +3513,26 @@ void TController::SetTimeControllers()
|
||||
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()
|
||||
@@ -3568,13 +3629,14 @@ void TController::Doors( bool const Open, int const Side ) {
|
||||
|| ( false == AIControllFlag ) ) ) {
|
||||
// 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 )
|
||||
|| ( ( true == AIControllFlag )
|
||||
&& ( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|
||||
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) ) ) {
|
||||
|| ( ( true == AIControllFlag ) ) ) {
|
||||
// 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
|
||||
if( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|
||||
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) {
|
||||
pVehicle->MoverParameters->OperateDoors( side::right, false );
|
||||
pVehicle->MoverParameters->OperateDoors( side::left, false );
|
||||
}
|
||||
if( pVehicle->MoverParameters->Doors.permit_needed ) {
|
||||
pVehicle->MoverParameters->PermitDoors( side::right, 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
|
||||
if( ( OrderCurrentGet() == Wait_for_orders )
|
||||
&& ( false == AIControllFlag )
|
||||
&& ( false == iEngineActive )
|
||||
&& ( true == mvControlling->Battery ) ) {
|
||||
OrderNext( Prepare_engine );
|
||||
}
|
||||
@@ -4965,9 +5028,14 @@ TController::UpdateSituation(double dt) {
|
||||
// jeśli dociskanie w celu odczepienia
|
||||
// 3. faza odczepiania.
|
||||
SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2
|
||||
if( ( mvControlling->MainCtrlPowerPos() > 0 )
|
||||
|| ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) {
|
||||
// jeśli jazda
|
||||
if( iVehicleCount >= 0 ) {
|
||||
// zmieni się po odczepieniu
|
||||
WriteLog( mvOccupied->Name + " dociskanie..." );
|
||||
while( mvOccupied->DecLocalBrakeLevel( 1 ) ) { // dociśnij sklad
|
||||
;
|
||||
}
|
||||
IncSpeed();
|
||||
}
|
||||
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute));
|
||||
TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI
|
||||
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
|
||||
@@ -5005,15 +5073,6 @@ TController::UpdateSituation(double dt) {
|
||||
iVehicleCount = -2;
|
||||
} // a jak nie, to dociskać dalej
|
||||
}
|
||||
if (iVehicleCount >= 0) // zmieni się po odczepieniu
|
||||
if (!mvOccupied->DecLocalBrakeLevel(1))
|
||||
{ // dociśnij sklad
|
||||
WriteLog( mvOccupied->Name + " dociskanie..." );
|
||||
// mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę
|
||||
// Ready=true; //zamiast sprawdzenia odhamowania całego składu
|
||||
IncSpeed(); // dla (Ready)==false nie ruszy
|
||||
}
|
||||
}
|
||||
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
|
||||
{ // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij
|
||||
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach
|
||||
@@ -5683,26 +5742,44 @@ TController::UpdateSituation(double dt) {
|
||||
ReactionTime = 0.25;
|
||||
}
|
||||
}
|
||||
if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic) // napełnianie uderzeniowe
|
||||
if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a || mvOccupied->BrakeHandle == TBrakeHandle::MHZ_6P
|
||||
|| mvOccupied->BrakeHandle == TBrakeHandle::M394)
|
||||
{
|
||||
if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic) {
|
||||
// napełnianie uderzeniowe
|
||||
if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a )
|
||||
|| ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_6P )
|
||||
|| ( mvOccupied->BrakeHandle == TBrakeHandle::M394 ) ) {
|
||||
|
||||
if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == -2 ) {
|
||||
/*mvOccupied->*/BrakeLevelSet( gbh_RP );
|
||||
}
|
||||
if( ( mvOccupied->PipePress < 3.0 )
|
||||
&& ( AccDesired > -0.03 ) ) {
|
||||
|
||||
// TODO: combine all releaser handling in single decision tree instead of having bits all over the place
|
||||
if( ( AccDesired > -0.03 )
|
||||
&& ( false == mvOccupied->Hamulec->Releaser() ) ) {
|
||||
if( mvOccupied->PipePress < 3.0 ) {
|
||||
mvOccupied->BrakeReleaser( 1 );
|
||||
}
|
||||
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 )
|
||||
&& ( AbsAccS < 0.03 )
|
||||
&& ( AccDesired > -0.03 )
|
||||
&& ( VelDesired - mvOccupied->Vel > 2.0 ) ) {
|
||||
|
||||
if( ( mvOccupied->EqvtPipePress < 4.95 )
|
||||
if( ( mvOccupied->EqvtPipePress < 4.5 )
|
||||
&& ( 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 )
|
||||
|| ( true == IsCargoTrain ) ) {
|
||||
@@ -5713,10 +5790,13 @@ TController::UpdateSituation(double dt) {
|
||||
BrakeChargingCooldown = -120.0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
// NOTE: disabled, duplicate of release activation in #5732
|
||||
else if( Need_BrakeRelease ) {
|
||||
Need_BrakeRelease = false;
|
||||
mvOccupied->BrakeReleaser( 1 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition < 0 )
|
||||
@@ -5725,6 +5805,7 @@ TController::UpdateSituation(double dt) {
|
||||
BrakeLevelSet( gbh_RP );
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LOGVELOCITY
|
||||
WriteLog("Dist=" + FloatToStrF(ActualProximityDist, ffFixed, 7, 1) +
|
||||
", VelDesired=" + FloatToStrF(VelDesired, ffFixed, 7, 1) +
|
||||
@@ -5763,17 +5844,6 @@ TController::UpdateSituation(double dt) {
|
||||
AccDesired > 0.0 ) ) {
|
||||
// on slopes disengage the brakes only if you actually intend to accelerate
|
||||
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
|
||||
if (!TrainParams)
|
||||
return ""; // tu nie powinno nigdy wejść
|
||||
std::string nextstop = asNextStop;
|
||||
std::string nextstop = Bezogonkow( asNextStop, true );
|
||||
TMTableLine *t = TrainParams->TimeTable + TrainParams->StationIndex;
|
||||
if( t->Ah >= 0 ) {
|
||||
// przyjazd
|
||||
nextstop += " przyj." + std::to_string( t->Ah ) + ":"
|
||||
+ ( t->Am < 10 ? "0" : "" ) + std::to_string( t->Am );
|
||||
+ to_minutes_str( t->Am, true, 3 );
|
||||
|
||||
}
|
||||
if( t->Dh >= 0 ) {
|
||||
// jeśli jest godzina odjazdu
|
||||
nextstop += " odj." + std::to_string( t->Dh ) + ":"
|
||||
+ ( t->Dm < 10 ? "0" : "" ) + std::to_string( t->Dm );
|
||||
+ to_minutes_str( t->Dm, true, 3 );
|
||||
}
|
||||
return nextstop;
|
||||
};
|
||||
@@ -6607,14 +6678,16 @@ void TController::DirectionForward(bool forward)
|
||||
// do przodu w obecnej kabinie
|
||||
while( ( mvOccupied->ActiveDir <= 0 )
|
||||
&& ( mvOccupied->DirectionForward() ) ) {
|
||||
; // all work is done in the header
|
||||
// force scan table update
|
||||
iTableDirection = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// do tyłu w obecnej kabinie
|
||||
while( ( mvOccupied->ActiveDir >= 0 )
|
||||
&& ( mvOccupied->DirectionBackward() ) ) {
|
||||
; // all work is done in the header
|
||||
// force scan table update
|
||||
iTableDirection = 0;
|
||||
}
|
||||
}
|
||||
if( mvOccupied->TrainType == dt_SN61 ) {
|
||||
|
||||
10
Driver.h
10
Driver.h
@@ -201,6 +201,10 @@ public:
|
||||
inline
|
||||
TMoverParameters const *Controlling() const {
|
||||
return mvControlling; }
|
||||
inline
|
||||
TMoverParameters const *Occupied() const {
|
||||
return mvOccupied;
|
||||
}
|
||||
void DirectionInitial();
|
||||
void DirectionChange();
|
||||
inline
|
||||
@@ -251,6 +255,7 @@ public:
|
||||
bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista
|
||||
int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami
|
||||
int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami
|
||||
double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller
|
||||
private:
|
||||
bool Psyche = false;
|
||||
int HelperState = 0; //stan pomocnika maszynisty
|
||||
@@ -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 iDriverFailCount = 0; // licznik błędów AI
|
||||
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
|
||||
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!)
|
||||
@@ -318,7 +323,6 @@ private:
|
||||
double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI
|
||||
double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca
|
||||
double BrakeChargingCooldown {}; // prevents the ai from trying to charge the train brake too frequently
|
||||
double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller
|
||||
double LastReactionTime = 0.0;
|
||||
double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi
|
||||
double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations
|
||||
@@ -363,7 +367,7 @@ private:
|
||||
// Ra: metody obsługujące skanowanie toru
|
||||
std::vector<basic_event *> CheckTrackEvent( TTrack *Track, double const fDirection ) const;
|
||||
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 TableCheck( double fDistance );
|
||||
TCommandType TableUpdate( double &fVelDes, double &fDist, double &fNext, double &fAcc );
|
||||
|
||||
77
DynObj.cpp
77
DynObj.cpp
@@ -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: używane tylko przy wczytywaniu scenerii
|
||||
MoverParameters->Attach( iDirection, Object->iDirection ^ 1, Object->MoverParameters, iType, true, false );
|
||||
// update neighbour data for both affected vehicles
|
||||
update_neighbours();
|
||||
Object->update_neighbours();
|
||||
}
|
||||
|
||||
bool TDynamicObject::UpdateForce(double dt)
|
||||
@@ -2782,6 +2784,8 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
|
||||
auto eimic = Min0R(MoverParameters->eimic, MoverParameters->eimicSpeedCtrl);
|
||||
MoverParameters->eimic_real = eimic;
|
||||
if (MoverParameters->EIMCtrlType == 2 && MoverParameters->MainCtrlPos == 0)
|
||||
eimic = -1.0;
|
||||
MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo);
|
||||
auto LBR = Max0R(-eimic, 0);
|
||||
auto eim_lb = (Mechanik->AIControllFlag || !MoverParameters->LocHandleTimeTraxx ? 0 : MoverParameters->eim_localbrake);
|
||||
@@ -2890,6 +2894,10 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
|| ( ( MoverParameters->BrakeHandle == TBrakeHandle::MHZ_EN57 )
|
||||
&& ( MoverParameters->BrakeOpModeFlag & bom_MED ) ) ) {
|
||||
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))
|
||||
&& (MoverParameters->eimc[eimc_p_abed] < 0.001))
|
||||
@@ -3068,6 +3076,8 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
delete[] FzED;
|
||||
delete[] FzEP;
|
||||
delete[] FmaxEP;
|
||||
|
||||
MED_oldFED = FzadED;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
do {
|
||||
token = "";
|
||||
@@ -4930,6 +4936,18 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
} while( ( token != "" )
|
||||
&& ( 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
|
||||
|
||||
else if( token == "sounds:" ) {
|
||||
@@ -6106,30 +6124,32 @@ TDynamicObject * TDynamicObject::ControlledFind()
|
||||
// problematyczna może być kwestia wybranej kabiny (w silnikowym...)
|
||||
// jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno jeździć dobrze
|
||||
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
|
||||
TDynamicObject *d = this; // zaczynamy od aktualnego
|
||||
if( ( d->MoverParameters->TrainType == dt_EZT )
|
||||
|| ( d->MoverParameters->TrainType == dt_DMU ) ) {
|
||||
// na razie dotyczy to EZT
|
||||
if( ( d->NextConnected() != nullptr )
|
||||
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) {
|
||||
// gdy jest człon od sprzęgu 1, a sprzęg łączony warsztatowo (powiedzmy)
|
||||
if( ( d->MoverParameters->Power < 1.0 )
|
||||
&& ( d->NextConnected()->MoverParameters->Power > 1.0 ) ) {
|
||||
// my nie mamy mocy, ale ten drugi ma
|
||||
d = d->NextConnected(); // będziemy sterować tym z mocą
|
||||
}
|
||||
}
|
||||
else if( ( d->PrevConnected() != nullptr )
|
||||
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) {
|
||||
// gdy jest człon od sprzęgu 0, a sprzęg łączony warsztatowo (powiedzmy)
|
||||
if( ( d->MoverParameters->Power < 1.0 )
|
||||
&& ( d->PrevConnected()->MoverParameters->Power > 1.0 ) ) {
|
||||
// my nie mamy mocy, ale ten drugi ma
|
||||
d = d->PrevConnected(); // będziemy sterować tym z mocą
|
||||
}
|
||||
}
|
||||
}
|
||||
if( MoverParameters->Power > 1.0 ) { return this; }
|
||||
|
||||
auto const couplingtype { (
|
||||
( MoverParameters->TrainType == dt_EZT )
|
||||
|| ( MoverParameters->TrainType == dt_DMU ) ) ?
|
||||
coupling::permanent :
|
||||
coupling::control
|
||||
};
|
||||
// try first to look towards the rear
|
||||
auto *d = this; // zaczynamy od aktualnego
|
||||
|
||||
while( ( d = d->NextC( couplingtype ) ) != nullptr ) {
|
||||
if( d->MoverParameters->Power > 1.0 ) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
// 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
|
||||
if( Vehicle.TurboTest > 0 ) {
|
||||
// udawanie turbo:
|
||||
auto const goalpitch { std::max( 0.025, ( engine_volume + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) };
|
||||
auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax : 0 };
|
||||
auto const goalpitch { std::max( 0.025, ( engine_volume * pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) };
|
||||
auto const goalvolume { (
|
||||
( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ?
|
||||
std::max( 0.0, ( engine_turbo_pitch + engine_turbo.m_amplitudeoffset ) * engine_turbo.m_amplitudefactor ) :
|
||||
|
||||
1
DynObj.h
1
DynObj.h
@@ -659,6 +659,7 @@ private:
|
||||
double MEDLogTime = 0;
|
||||
double MEDLogInactiveTime = 0;
|
||||
int MEDLogCount = 0;
|
||||
double MED_oldFED = 0;
|
||||
|
||||
// vehicle shaking calculations
|
||||
// TBD, TODO: make an object out of it
|
||||
|
||||
@@ -127,7 +127,13 @@ global_settings::ConfigParse(cParser &Parser) {
|
||||
// selected device for audio renderer
|
||||
Parser.getTokens();
|
||||
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") {
|
||||
Parser.getTokens();
|
||||
|
||||
@@ -74,7 +74,6 @@ struct global_settings {
|
||||
bool bLiveTraction{ true };
|
||||
float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
|
||||
glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f };
|
||||
double fFogStart{ 1700 };
|
||||
double fFogEnd{ 2000 };
|
||||
std::string Season{}; // season of the year, based on simulation date
|
||||
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
|
||||
// audio
|
||||
bool bSoundEnabled{ true };
|
||||
float AudioVolume{ 1.25f };
|
||||
float AudioVolume{ 1.f };
|
||||
float RadioVolume{ 0.75f };
|
||||
int audio_max_sources = 30;
|
||||
std::string AudioRenderer;
|
||||
// input
|
||||
|
||||
@@ -767,6 +767,7 @@ private:
|
||||
// ld inputs
|
||||
bool lock_enabled { true };
|
||||
bool step_enabled { true };
|
||||
bool remote_only { false }; // door ignores local control signals
|
||||
// internal data
|
||||
int permit_preset { -1 }; // curent position of preset selection switch
|
||||
// vehicle parts
|
||||
@@ -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 CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure
|
||||
start_t CompressorStart{ start_t::manual }; // whether the compressor is started manually, or another way
|
||||
start_t PantographCompressorStart{ start_t::manual };
|
||||
// TODO converter parameters, for when we start cleaning up mover parameters
|
||||
start_t ConverterStart{ start_t::manual }; // whether converter is started manually, or by other means
|
||||
float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met
|
||||
@@ -1311,6 +1313,8 @@ public:
|
||||
double eim_localbrake = 0; /*nastawa hamowania dodatkowego pneumatycznego lokomotywy*/
|
||||
int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/
|
||||
bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/
|
||||
int SpeedCtrlAutoTurnOffFlag = 0; /*czy tempomat sam się wyłącza*/
|
||||
bool EIMCtrlAdditionalZeros = false; /*czy ma dodatkowe zero jazdy i zero hamowania */
|
||||
double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/
|
||||
double eimv[21];
|
||||
static std::vector<std::string> const eimv_labels;
|
||||
@@ -1345,8 +1349,6 @@ public:
|
||||
bool PantRearUp = false;
|
||||
bool PantFrontSP = true; //dzwiek patykow 'Winger 010304
|
||||
bool PantRearSP = true;
|
||||
int PantFrontStart = 0; //stan patykow 'Winger 160204
|
||||
int PantRearStart = 0;
|
||||
double PantFrontVolt = 0.0; //pantograf pod napieciem? 'Winger 160404
|
||||
double PantRearVolt = 0.0;
|
||||
// TODO: move these switch types where they belong, cabin definition
|
||||
@@ -1554,6 +1556,7 @@ public:
|
||||
bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist );
|
||||
bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist );
|
||||
bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist );
|
||||
bool ChangeDoorControlMode( bool const State, range_t const Notify = range_t::consist );
|
||||
bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist );
|
||||
bool LockDoors( bool const State, range_t const Notify = range_t::consist );
|
||||
bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning
|
||||
|
||||
@@ -653,12 +653,19 @@ void TMoverParameters::UpdatePantVolume(double dt)
|
||||
{ // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak
|
||||
|
||||
// check the pantograph compressor while at it
|
||||
if( PantCompFlag ) {
|
||||
if( ( false == Battery )
|
||||
if( ( PantPress < 4.2 )
|
||||
&& ( ( PantographCompressorStart == start_t::automatic )
|
||||
|| ( PantographCompressorStart == start_t::manualwithautofallback ) )
|
||||
&& ( ( true == PantRearUp )
|
||||
|| ( true == PantFrontUp ) ) ) {
|
||||
// automatic start if the pressure is too low
|
||||
PantCompFlag = true;
|
||||
}
|
||||
if( ( true == PantCompFlag )
|
||||
&& ( false == Battery )
|
||||
&& ( false == ConverterFlag ) ) {
|
||||
PantCompFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący
|
||||
{
|
||||
@@ -1684,6 +1691,8 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed)
|
||||
else {
|
||||
++MainCtrlPos;
|
||||
OK = true;
|
||||
if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos))
|
||||
DecScndCtrl(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1846,6 +1855,8 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed)
|
||||
{
|
||||
MainCtrlPos--;
|
||||
OK = true;
|
||||
if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos))
|
||||
DecScndCtrl(2);
|
||||
}
|
||||
else if (CtrlSpeed > 1)
|
||||
OK = (DecMainCtrl(1) && DecMainCtrl(2)); // CtrlSpeed-1);
|
||||
@@ -1987,13 +1998,17 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed)
|
||||
if (LastRelayTime > CtrlDelay)
|
||||
LastRelayTime = 0;
|
||||
|
||||
if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1))
|
||||
if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1) && (MainCtrlPos>0))
|
||||
{
|
||||
// NOTE: round() already adds 0.5, are the ones added here as well correct?
|
||||
if ((Vmax < 250))
|
||||
ScndCtrlActualPos = Round(Vel);
|
||||
else
|
||||
ScndCtrlActualPos = Round(Vel * 0.5);
|
||||
if ((EIMCtrlType == 0)&&(SpeedCtrlAutoTurnOffFlag == 1))
|
||||
{
|
||||
MainCtrlActualPos = MainCtrlPos;
|
||||
}
|
||||
SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo);
|
||||
}
|
||||
|
||||
@@ -3901,7 +3916,18 @@ void TMoverParameters::ComputeConstans(void)
|
||||
}
|
||||
Ff = TotalMassxg * (BearingF + RollF * V * V / 10.0) / 1000.0;
|
||||
// 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ń
|
||||
if (Curvature > 0.0)
|
||||
Curvature = 1.0 / Curvature;
|
||||
@@ -4416,7 +4442,7 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
|
||||
if( enrot != tmp ) {
|
||||
enrot = clamp(
|
||||
enrot + ( dt / 1.25 ) * ( // TODO: equivalent of dizel_aim instead of fixed inertia
|
||||
enrot + ( dt / dizel_AIM ) * (
|
||||
enrot < tmp ?
|
||||
1.0 :
|
||||
-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 ) {
|
||||
PantFrontUp = State;
|
||||
if( State == true ) {
|
||||
PantFrontStart = 0;
|
||||
if( Notify != range_t::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
@@ -5926,7 +5951,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify )
|
||||
}
|
||||
}
|
||||
else {
|
||||
PantFrontStart = 1;
|
||||
if( Notify != range_t::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
@@ -5968,7 +5992,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify )
|
||||
if( PantRearUp != State ) {
|
||||
PantRearUp = State;
|
||||
if( State == true ) {
|
||||
PantRearStart = 0;
|
||||
if( Notify != range_t::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
@@ -5979,7 +6002,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify )
|
||||
}
|
||||
}
|
||||
else {
|
||||
PantRearStart = 1;
|
||||
if( Notify != range_t::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
@@ -6014,6 +6036,13 @@ void TMoverParameters::CheckEIMIC(double dt)
|
||||
{
|
||||
case 0:
|
||||
eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : (double)MainCtrlPos / (double)MainCtrlPosNo);
|
||||
if (EIMCtrlAdditionalZeros)
|
||||
{
|
||||
if (eimic > 0.001)
|
||||
eimic = std::max(0.002, eimic * (double)MainCtrlPosNo / ((double)MainCtrlPosNo - 1.0) - 1.0 / ((double)MainCtrlPosNo - 1.0));
|
||||
if (eimic < -0.001)
|
||||
eimic = std::min(-0.002, eimic * (double)LocalBrakePosNo / ((double)LocalBrakePosNo - 1.0) + 1.0 / ((double)LocalBrakePosNo - 1.0));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
switch (MainCtrlPos)
|
||||
@@ -6064,33 +6093,46 @@ void TMoverParameters::CheckEIMIC(double dt)
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay))
|
||||
{
|
||||
double delta = (MainCtrlActualPos == MainCtrlPos ? dt*CtrlDelay : 0.01);
|
||||
switch (MainCtrlPos)
|
||||
{
|
||||
case 0:
|
||||
eimic = -1.0;
|
||||
break;
|
||||
case 1:
|
||||
eimic -= clamp(1.0 + eimic, 0.0, dt*0.15); //odejmuj do -1
|
||||
eimic -= clamp(1.0 + eimic, 0.0, delta); //odejmuj do -1
|
||||
if (eimic > 0) eimic = 0;
|
||||
break;
|
||||
case 2:
|
||||
eimic -= clamp(0.0 + eimic, 0.0, dt*0.15); //odejmuj do 0
|
||||
eimic -= clamp(0.0 + eimic, 0.0, delta); //odejmuj do 0
|
||||
break;
|
||||
case 3:
|
||||
eimic += clamp(0.0 - eimic, 0.0, dt*0.15); //dodawaj do 0
|
||||
eimic += clamp(0.0 - eimic, 0.0, delta); //dodawaj do 0
|
||||
break;
|
||||
case 4:
|
||||
eimic += clamp(1.0 - eimic, 0.0, dt*0.15); //dodawaj do 1
|
||||
eimic += clamp(1.0 - eimic, 0.0, delta); //dodawaj do 1
|
||||
if (eimic < 0) eimic = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (MainCtrlActualPos == MainCtrlPos)
|
||||
LastRelayTime += dt;
|
||||
else
|
||||
{
|
||||
LastRelayTime = 0;
|
||||
MainCtrlActualPos = MainCtrlPos;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
eimic -= clamp(-UniCtrlList[MainCtrlPos].SetCtrlVal + eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedDown); //odejmuj do X
|
||||
eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedUp); //dodawaj do X
|
||||
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()
|
||||
@@ -6910,12 +6952,7 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c
|
||||
|
||||
bool const initialstate { Doors.instances[Door].open_permit };
|
||||
|
||||
if( ( false == Doors.permit_presets.empty() ) // HACK: for cases where preset switch is used before battery
|
||||
|| ( ( true == Battery )
|
||||
&& ( false == Doors.is_locked ) ) ) {
|
||||
|
||||
Doors.instances[ Door ].open_permit = State;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
bool TMoverParameters::ChangeDoorControlMode( bool const State, range_t const Notify ) {
|
||||
|
||||
auto const initialstate { Doors.remote_only };
|
||||
|
||||
Doors.remote_only = State;
|
||||
if( Notify != range_t::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
"DoorMode",
|
||||
( State == true ?
|
||||
1 :
|
||||
0 ),
|
||||
CabNo,
|
||||
( Notify == range_t::unit ?
|
||||
coupling::control | coupling::permanent :
|
||||
coupling::control ) );
|
||||
}
|
||||
|
||||
if( true == State ) {
|
||||
// when door are put in remote control mode they're automatically open
|
||||
// TBD, TODO: make it dependant on config switch?
|
||||
OperateDoors( side::left, true );
|
||||
OperateDoors( side::right, true );
|
||||
}
|
||||
|
||||
return ( Doors.step_enabled != initialstate );
|
||||
}
|
||||
|
||||
bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) {
|
||||
|
||||
auto &door { Doors.instances[ Door ] };
|
||||
@@ -7041,15 +7106,17 @@ TMoverParameters::update_doors( double const Deltatime ) {
|
||||
|
||||
// NBMX Obsluga drzwi, MC: zuniwersalnione
|
||||
auto const localopencontrol {
|
||||
( Doors.open_control == control_t::passenger )
|
||||
|| ( Doors.open_control == control_t::mixed ) };
|
||||
( false == Doors.remote_only )
|
||||
&& ( ( Doors.open_control == control_t::passenger )
|
||||
|| ( Doors.open_control == control_t::mixed ) ) };
|
||||
auto const remoteopencontrol {
|
||||
( Doors.open_control == control_t::driver )
|
||||
|| ( Doors.open_control == control_t::conductor )
|
||||
|| ( Doors.open_control == control_t::mixed ) };
|
||||
auto const localclosecontrol {
|
||||
( Doors.close_control == control_t::passenger )
|
||||
|| ( Doors.close_control == control_t::mixed ) };
|
||||
( false == Doors.remote_only )
|
||||
&& ( ( Doors.close_control == control_t::passenger )
|
||||
|| ( Doors.close_control == control_t::mixed ) ) };
|
||||
auto const remoteclosecontrol {
|
||||
( Doors.close_control == control_t::driver )
|
||||
|| ( Doors.close_control == control_t::conductor )
|
||||
@@ -7077,13 +7144,18 @@ TMoverParameters::update_doors( double const Deltatime ) {
|
||||
&& ( door.step_position <= 0.f );
|
||||
|
||||
door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
|
||||
door.remote_open = door.remote_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
|
||||
door.remote_open = ( door.remote_open || Doors.remote_only ) && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
|
||||
door.local_close = door.local_close && ( false == door.is_closed );
|
||||
door.remote_close = door.remote_close && ( false == door.is_closed );
|
||||
|
||||
auto const autoopenrequest {
|
||||
( Doors.open_control == control_t::autonomous )
|
||||
&& ( ( false == Doors.permit_needed ) || door.open_permit )
|
||||
};
|
||||
auto const openrequest {
|
||||
( localopencontrol && door.local_open )
|
||||
|| ( remoteopencontrol && door.remote_open ) };
|
||||
|| ( remoteopencontrol && door.remote_open )
|
||||
|| ( autoopenrequest && ( false == door.is_open ) ) };
|
||||
|
||||
auto const autocloserequest {
|
||||
( ( 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->second :
|
||||
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
|
||||
extract_value( Doors.auto_duration, "DoorStayOpen", line, "" );
|
||||
@@ -8683,6 +8749,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
|
||||
extract_value( EIMCtrlType, "EIMCtrlType", line, "" );
|
||||
clamp( EIMCtrlType, 0, 3 );
|
||||
LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes");
|
||||
EIMCtrlAdditionalZeros = (extract_value("EIMCtrlAddZeros", line) == "Yes");
|
||||
|
||||
extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR
|
||||
|
||||
@@ -8705,6 +8772,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
|
||||
(extract_value("SpeedCtrlType", line) == "Time") ?
|
||||
true :
|
||||
false;
|
||||
extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", line, "");
|
||||
|
||||
// converter
|
||||
{
|
||||
@@ -8735,6 +8803,14 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
|
||||
lookup->second :
|
||||
start_t::manual;
|
||||
}
|
||||
// pantograph compressor
|
||||
{
|
||||
auto lookup = starts.find( extract_value( "PantCompressorStart", line ) );
|
||||
PantographCompressorStart =
|
||||
lookup != starts.end() ?
|
||||
lookup->second :
|
||||
start_t::manual;
|
||||
}
|
||||
// fuel pump
|
||||
{
|
||||
auto lookup = starts.find( extract_value( "FuelStart", line ) );
|
||||
@@ -8961,6 +9037,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
|
||||
ImaxLo = 1;
|
||||
}
|
||||
extract_value( EngineHeatingRPM, "HeatingRPM", Input, "" );
|
||||
extract_value( dizel_AIM, "AIM", Input, "1.25" );
|
||||
break;
|
||||
}
|
||||
case TEngineType::ElectricInductionMotor: {
|
||||
@@ -10048,6 +10125,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
false );
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if( Command == "DoorMode" ) {
|
||||
Doors.remote_only = (
|
||||
CValue1 == 1 ?
|
||||
true :
|
||||
false );
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if( Command == "DepartureSignal" ) {
|
||||
DepartureSignal = (
|
||||
CValue1 == 1 ?
|
||||
@@ -10064,12 +10148,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
if ((CValue1 == 1))
|
||||
{
|
||||
PantFrontUp = true;
|
||||
PantFrontStart = 0;
|
||||
}
|
||||
else if ((CValue1 == 0))
|
||||
{
|
||||
PantFrontUp = false;
|
||||
PantFrontStart = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -10079,24 +10161,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
|
||||
{
|
||||
PantFrontUp = true;
|
||||
PantFrontStart = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PantRearUp = true;
|
||||
PantRearStart = 0;
|
||||
}
|
||||
else if ((CValue1 == 0))
|
||||
if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) ||
|
||||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
|
||||
{
|
||||
PantFrontUp = false;
|
||||
PantFrontStart = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PantRearUp = false;
|
||||
PantRearStart = 1;
|
||||
}
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
@@ -10109,12 +10187,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
if ((CValue1 == 1))
|
||||
{
|
||||
PantRearUp = true;
|
||||
PantRearStart = 0;
|
||||
}
|
||||
else if ((CValue1 == 0))
|
||||
{
|
||||
PantRearUp = false;
|
||||
PantRearStart = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -10125,24 +10201,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
|
||||
{
|
||||
PantRearUp = true;
|
||||
PantRearStart = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PantFrontUp = true;
|
||||
PantFrontStart = 0;
|
||||
}
|
||||
else if ((CValue1 == 0))
|
||||
if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) ||
|
||||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
|
||||
{
|
||||
PantRearUp = false;
|
||||
PantRearStart = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PantFrontUp = false;
|
||||
PantFrontStart = 1;
|
||||
}
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
|
||||
@@ -385,6 +385,11 @@ void TBrake::Releaser( int const state )
|
||||
BrakeStatus = (BrakeStatus & ~b_rls) | ( state * b_rls );
|
||||
}
|
||||
|
||||
bool TBrake::Releaser() const {
|
||||
|
||||
return ( ( BrakeStatus & b_rls ) == b_rls );
|
||||
}
|
||||
|
||||
void TBrake::SetEPS( double const nEPS )
|
||||
{
|
||||
}
|
||||
@@ -1370,7 +1375,7 @@ double TLSt::GetPF( double const PP, double const dt, double const Vel )
|
||||
temp = 10000;
|
||||
|
||||
// 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
|
||||
if ((BrakeCyl->P() > temp + 0.005) || (temp < 0.28))
|
||||
// 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)
|
||||
{
|
||||
CP = Press;
|
||||
Time = true;
|
||||
TimeEP = true;
|
||||
}
|
||||
|
||||
void TMHZ_K5P::SetReductor(double nAdj)
|
||||
|
||||
@@ -203,6 +203,7 @@ class TBrake {
|
||||
virtual double GetCRP(); //cisnienie zbiornika sterujacego
|
||||
bool SetBDF( int const nBDF ); //nastawiacz GPRM
|
||||
void Releaser( int const state ); //odluzniacz
|
||||
bool Releaser() const;
|
||||
virtual void SetEPS( double const nEPS ); //hamulec EP
|
||||
virtual void SetRM( double const RMR ) {}; //ustalenie przelozenia rapida
|
||||
virtual void SetRV( double const RVR) {}; //ustalenie przelozenia rapida
|
||||
|
||||
227
Train.cpp
227
Train.cpp
@@ -327,6 +327,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
|
||||
{ user_command::dooropenall, &TTrain::OnCommand_dooropenall },
|
||||
{ user_command::doorcloseall, &TTrain::OnCommand_doorcloseall },
|
||||
{ user_command::doorsteptoggle, &TTrain::OnCommand_doorsteptoggle },
|
||||
{ user_command::doormodetoggle, &TTrain::OnCommand_doormodetoggle },
|
||||
{ user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease },
|
||||
{ user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect },
|
||||
{ user_command::departureannounce, &TTrain::OnCommand_departureannounce },
|
||||
@@ -389,7 +390,10 @@ TTrain::TTrain() {
|
||||
}
|
||||
for( int i = 0; i < 9; ++i )
|
||||
for (int j = 0; j < 10; ++j)
|
||||
{
|
||||
fEIMParams[i][j] = 0.0;
|
||||
fDieselParams[i][j] = 0.0;
|
||||
}
|
||||
|
||||
for( int i = 0; i < 20; ++i )
|
||||
for( int j = 0; j < 3; ++j )
|
||||
@@ -454,10 +458,10 @@ dictionary_source *TTrain::GetTrainState() {
|
||||
// reverser
|
||||
dict->insert( "direction", mover->ActiveDir );
|
||||
// throttle
|
||||
dict->insert( "mainctrl_pos", mover->MainCtrlPos );
|
||||
dict->insert( "main_ctrl_actual_pos", mover->MainCtrlActualPos );
|
||||
dict->insert( "scndctrl_pos", mover->ScndCtrlPos );
|
||||
dict->insert( "scnd_ctrl_actual_pos", mover->ScndCtrlActualPos );
|
||||
dict->insert( "mainctrl_pos", mvControlled->MainCtrlPos );
|
||||
dict->insert( "main_ctrl_actual_pos", mvControlled->MainCtrlActualPos );
|
||||
dict->insert( "scndctrl_pos", mvControlled->ScndCtrlPos );
|
||||
dict->insert( "scnd_ctrl_actual_pos", mvControlled->ScndCtrlActualPos );
|
||||
dict->insert( "new_speed", mover->NewSpeed);
|
||||
// brakes
|
||||
dict->insert( "manual_brake", ( mvOccupied->ManualBrakePos > 0 ) );
|
||||
@@ -496,6 +500,7 @@ dictionary_source *TTrain::GetTrainState() {
|
||||
// induction motor state data
|
||||
char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
|
||||
char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
|
||||
char const *TXTD[ 10 ] = { "enrot", "nrot", "fill_des", "fill_real", "clutch_des", "clutch_real", "water_temp", "oil_press", "res1", "res2" };
|
||||
char const *TXTP[ 3 ] = { "bc", "bp", "sp" };
|
||||
for( int j = 0; j < 10; ++j )
|
||||
dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] );
|
||||
@@ -503,6 +508,9 @@ dictionary_source *TTrain::GetTrainState() {
|
||||
for( int j = 0; j < 10; ++j )
|
||||
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] );
|
||||
|
||||
for (int j = 0; j < 10; ++j)
|
||||
dict->insert(("diesel_param_" + std::to_string(i + 1) + "_" + std::string(TXTD[j])), fDieselParams[i + 1][j]);
|
||||
|
||||
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_ms" ), bMains[ i ] );
|
||||
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_cv" ), fCntVol[ i ] );
|
||||
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pf" ), bPants[ i ][ 0 ] );
|
||||
@@ -648,7 +656,8 @@ void TTrain::zero_charging_train_brake() {
|
||||
&& ( DynamicObject->Controller != AIdriver )
|
||||
&& ( Global.iFeedbackMode < 3 )
|
||||
&& ( ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 )
|
||||
|| ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57 ) ) ) {
|
||||
|| (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57)
|
||||
|| (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P)) ) {
|
||||
// Odskakiwanie hamulce EP
|
||||
set_train_brake( 0 );
|
||||
}
|
||||
@@ -781,7 +790,7 @@ void TTrain::OnCommand_mastercontrollerincrease( TTrain *Train, command_data con
|
||||
if( Command.action != GLFW_RELEASE ) {
|
||||
// on press or hold
|
||||
if( ( Train->ggJointCtrl.SubModel != nullptr )
|
||||
&& ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) {
|
||||
&& ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) {
|
||||
OnCommand_independentbrakedecrease( Train, Command );
|
||||
}
|
||||
else {
|
||||
@@ -801,7 +810,7 @@ void TTrain::OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data
|
||||
if( Command.action != GLFW_RELEASE ) {
|
||||
// on press or hold
|
||||
if( ( Train->ggJointCtrl.SubModel != nullptr )
|
||||
&& ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) {
|
||||
&& ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) {
|
||||
OnCommand_independentbrakedecreasefast( Train, Command );
|
||||
}
|
||||
else {
|
||||
@@ -1712,10 +1721,11 @@ void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Co
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// 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_REPEAT ) {
|
||||
// keep the switch from flipping back and forth if key is held down
|
||||
if( false == Train->mvOccupied->Battery ) {
|
||||
// turn on
|
||||
OnCommand_batteryenable( Train, Command );
|
||||
@@ -1729,16 +1739,13 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command
|
||||
|
||||
void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
|
||||
if( true == Train->mvOccupied->Battery ) { return; } // already on
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// ignore repeats
|
||||
// wyłącznik jest też w SN61, ewentualnie załączać prąd na stałe z poziomu FIZ
|
||||
if( Train->mvOccupied->BatterySwitch( true ) ) {
|
||||
// bateria potrzebna np. do zapalenia świateł
|
||||
if( Train->ggBatteryButton.SubModel ) {
|
||||
Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
// side-effects
|
||||
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
||||
Train->SetLights();
|
||||
@@ -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 ) {
|
||||
// TBD, TODO: ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
|
||||
if( false == Train->mvOccupied->Battery ) { return; } // already off
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// ignore repeats
|
||||
if( Train->mvOccupied->BatterySwitch( false ) ) {
|
||||
// ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
|
||||
if( Train->ggBatteryButton.SubModel ) {
|
||||
Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
}
|
||||
// side-effects
|
||||
if( false == Train->mvControlled->ConverterFlag ) {
|
||||
// if there's no (low voltage) power source left, drop pantographs
|
||||
@@ -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 )
|
||||
@@ -4129,7 +4146,7 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
|
||||
}
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
||||
// ignore repeats so the switch doesn't flip back and forth if key is held down
|
||||
if( false == Train->mvControlled->HeatingAllow ) {
|
||||
// turn on
|
||||
OnCommand_heatingenable( Train, Command );
|
||||
@@ -4139,6 +4156,14 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
|
||||
OnCommand_heatingdisable( Train, Command );
|
||||
}
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
|
||||
if( Train->ggTrainHeatingButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
// visual feedback
|
||||
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) {
|
||||
@@ -4157,7 +4182,11 @@ void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Comman
|
||||
|
||||
Train->mvControlled->HeatingAllow = false;
|
||||
// visual feedback
|
||||
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
Train->ggTrainHeatingButton.UpdateValue(
|
||||
( Train->ggTrainHeatingButton.type() == TGaugeType::push ?
|
||||
1.0 :
|
||||
0.0 ),
|
||||
Train->dsbSwitch );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4288,39 +4317,75 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman
|
||||
|
||||
void TTrain::OnCommand_doorpermitleft( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
Train->mvOccupied->PermitDoors(
|
||||
( Train->mvOccupied->ActiveCab == 1 ?
|
||||
auto const side { (
|
||||
Train->mvOccupied->ActiveCab == 1 ?
|
||||
side::left :
|
||||
side::right ) );
|
||||
side::right ) };
|
||||
|
||||
if( Train->ggDoorLeftPermitButton.type() == TGaugeType::push ) {
|
||||
// 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 ) {
|
||||
|
||||
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 ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
Train->mvOccupied->PermitDoors(
|
||||
( Train->mvOccupied->ActiveCab == 1 ?
|
||||
auto const side { (
|
||||
Train->mvOccupied->ActiveCab == 1 ?
|
||||
side::right :
|
||||
side::left ) );
|
||||
side::left ) };
|
||||
|
||||
if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) {
|
||||
// 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 ) {
|
||||
|
||||
if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
// visual feedback
|
||||
Train->ggDoorRightPermitButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_doorpermitpresetactivatenext( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
if( ( true == FreeFlyModeFlag )
|
||||
@@ -5171,7 +5243,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
}
|
||||
|
||||
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;
|
||||
fEIMParams[0][6] = 0;
|
||||
iCarNo = 0;
|
||||
@@ -5240,6 +5312,27 @@ bool TTrain::Update( double const Deltatime )
|
||||
in++;
|
||||
iPowerNo = in;
|
||||
}
|
||||
if ((in < 8) && (p->MoverParameters->EngineType==TEngineType::DieselEngine))
|
||||
{
|
||||
fDieselParams[1 + in][0] = p->MoverParameters->enrot*60;
|
||||
fDieselParams[1 + in][1] = p->MoverParameters->nrot;
|
||||
fDieselParams[1 + in][2] = p->MoverParameters->RList[p->MoverParameters->MainCtrlPos].R;
|
||||
fDieselParams[1 + in][3] = p->MoverParameters->dizel_fill;
|
||||
fDieselParams[1 + in][4] = p->MoverParameters->RList[p->MoverParameters->MainCtrlPos].Mn;
|
||||
fDieselParams[1 + in][5] = p->MoverParameters->dizel_engage;
|
||||
fDieselParams[1 + in][6] = p->MoverParameters->dizel_heat.Twy;
|
||||
fDieselParams[1 + in][7] = p->MoverParameters->OilPump.pressure;
|
||||
//fDieselParams[1 + in][8] = p->MoverParameters->
|
||||
//fDieselParams[1 + in][9] = p->MoverParameters->
|
||||
bMains[in] = p->MoverParameters->Mains;
|
||||
fCntVol[in] = p->MoverParameters->BatteryVoltage;
|
||||
bFuse[in] = p->MoverParameters->FuseFlag;
|
||||
bBatt[in] = p->MoverParameters->Battery;
|
||||
bConv[in] = p->MoverParameters->ConverterFlag;
|
||||
bHeat[in] = p->MoverParameters->Heating;
|
||||
in++;
|
||||
iPowerNo = in;
|
||||
}
|
||||
// p = p->NextC(4); //prev
|
||||
if ((kier ? p->NextC(128) : p->PrevC(128)) != (kier ? p->NextC(4) : p->PrevC(4)))
|
||||
iUnitNo++;
|
||||
@@ -5282,16 +5375,11 @@ bool TTrain::Update( double const Deltatime )
|
||||
|
||||
for (int i = in; i < 8; i++)
|
||||
{
|
||||
fEIMParams[1 + i][0] = 0;
|
||||
fEIMParams[1 + i][1] = 0;
|
||||
fEIMParams[1 + i][2] = 0;
|
||||
fEIMParams[1 + i][3] = 0;
|
||||
fEIMParams[1 + i][4] = 0;
|
||||
fEIMParams[1 + i][5] = 0;
|
||||
fEIMParams[1 + i][6] = 0;
|
||||
fEIMParams[1 + i][7] = 0;
|
||||
fEIMParams[1 + i][8] = 0;
|
||||
fEIMParams[1 + i][9] = 0;
|
||||
for (int j = 0; j <= 9; j++)
|
||||
{
|
||||
fEIMParams[1 + i][j] = 0;
|
||||
fDieselParams[1 + i][j] = 0;
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (Global.iFeedbackMode == 4) {
|
||||
@@ -6493,7 +6581,7 @@ void TTrain::update_sounds_radio() {
|
||||
auto const volume {
|
||||
( true == radioenabled )
|
||||
&& ( message.first == iRadioChannel ) ?
|
||||
1.0 :
|
||||
Global.RadioVolume :
|
||||
0.0 };
|
||||
message.second->gain( volume );
|
||||
}
|
||||
@@ -7068,28 +7156,11 @@ void TTrain::DynamicSet(TDynamicObject *d)
|
||||
// jeździć dobrze
|
||||
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
|
||||
DynamicObject = d; // jedyne miejsce zmiany
|
||||
mvOccupied = mvControlled = d ? DynamicObject->MoverParameters : NULL; // albo silnikowy w EZT
|
||||
if (!DynamicObject)
|
||||
return;
|
||||
// TODO: leverage code already present in TDynamicObject::ControlledFind()
|
||||
if( ( d->MoverParameters->TrainType == dt_EZT )
|
||||
|| ( d->MoverParameters->TrainType == dt_DMU ) ) {
|
||||
mvOccupied = mvControlled = ( d ? DynamicObject->MoverParameters : nullptr ); // albo silnikowy w EZT
|
||||
|
||||
if( ( d->NextConnected() != nullptr )
|
||||
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) {
|
||||
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 1 ].Connected->Power > 1.0 ) ) {
|
||||
// my nie mamy mocy, ale ten drugi ma
|
||||
mvControlled = DynamicObject->NextConnected()->MoverParameters; // będziemy sterować tym z mocą
|
||||
}
|
||||
}
|
||||
else if( ( d->PrevConnected() != nullptr )
|
||||
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) {
|
||||
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 0 ].Connected->Power > 1.0 ) ) {
|
||||
// my nie mamy mocy, ale ten drugi ma
|
||||
mvControlled = DynamicObject->PrevConnected()->MoverParameters; // będziemy sterować tym z mocą
|
||||
}
|
||||
}
|
||||
}
|
||||
if( DynamicObject == nullptr ) { return; }
|
||||
|
||||
mvControlled = DynamicObject->ControlledFind()->MoverParameters;
|
||||
mvSecond = NULL; // gdyby się nic nie znalazło
|
||||
if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo
|
||||
if (mvOccupied->Couplers[1].Connected ?
|
||||
@@ -7413,9 +7484,10 @@ void TTrain::clear_cab_controls()
|
||||
void TTrain::set_cab_controls( int const Cab ) {
|
||||
// switches
|
||||
// battery
|
||||
if( true == mvOccupied->Battery ) {
|
||||
ggBatteryButton.PutValue( 1.f );
|
||||
}
|
||||
ggBatteryButton.PutValue(
|
||||
( ggBatteryButton.type() == TGaugeType::push ? 0.5f :
|
||||
mvOccupied->Battery ? 1.f :
|
||||
0.f ) );
|
||||
// motor connectors
|
||||
ggStLinOffButton.PutValue(
|
||||
( mvControlled->StLinSwitchOff ?
|
||||
@@ -7578,7 +7650,12 @@ void TTrain::set_cab_controls( int const Cab ) {
|
||||
1.f :
|
||||
0.f ) );
|
||||
// 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 );
|
||||
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 );
|
||||
@@ -7588,8 +7665,11 @@ void TTrain::set_cab_controls( int const Cab ) {
|
||||
1.f :
|
||||
0.f );
|
||||
// heating
|
||||
if( true == mvControlled->Heating ) {
|
||||
ggTrainHeatingButton.PutValue( 1.f );
|
||||
if( ggTrainHeatingButton.type() != TGaugeType::push ) {
|
||||
ggTrainHeatingButton.PutValue(
|
||||
mvControlled->Heating ?
|
||||
1.f :
|
||||
0.f );
|
||||
}
|
||||
// brake acting time
|
||||
if( ggBrakeProfileCtrl.SubModel != nullptr ) {
|
||||
@@ -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
|
||||
std::unordered_map<std::string, bool *> const autolights = {
|
||||
{ "i-doorpermit_left:", &mvOccupied->Doors.instances[side::left].open_permit },
|
||||
{ "i-doorpermit_right:", &mvOccupied->Doors.instances[ side::right ].open_permit },
|
||||
{ "i-doorpermit_left:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit },
|
||||
{ "i-doorpermit_right:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit },
|
||||
{ "i-doorstep:", &mvOccupied->Doors.step_enabled }
|
||||
};
|
||||
{
|
||||
@@ -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
|
||||
std::unordered_map<std::string, bool *> const autoboolgauges = {
|
||||
{ "doormode_sw:", &mvOccupied->Doors.remote_only },
|
||||
{ "doorstep_sw:", &mvOccupied->Doors.step_enabled },
|
||||
{ "coolingfans_sw:", &mvControlled->RVentForceOn }
|
||||
};
|
||||
|
||||
2
Train.h
2
Train.h
@@ -330,6 +330,7 @@ class TTrain
|
||||
static void OnCommand_dooropenall( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_doormodetoggle( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_departureannounce( TTrain *Train, command_data const &Command );
|
||||
@@ -675,6 +676,7 @@ private:
|
||||
float fPress[20][3]; // cisnienia dla wszystkich czlonow
|
||||
static std::vector<std::string> const fPress_labels;
|
||||
float fEIMParams[9][10]; // parametry dla silnikow asynchronicznych
|
||||
float fDieselParams[9][10]; // parametry dla silnikow asynchronicznych
|
||||
int RadioChannel() const { return iRadioChannel; };
|
||||
// plays provided sound from position of the radio
|
||||
void radio_message( sound_source *Message, int const Channel );
|
||||
|
||||
@@ -154,6 +154,7 @@ commanddescription_sequence Commands_descriptions = {
|
||||
{ "doorcloseright", command_target::vehicle, command_mode::oneoff },
|
||||
{ "doorcloseall", 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 },
|
||||
{ "doorlocktoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "pantographcompressorvalvetoggle", command_target::vehicle, command_mode::oneoff },
|
||||
|
||||
@@ -148,6 +148,7 @@ enum class user_command {
|
||||
doorcloseright,
|
||||
doorcloseall,
|
||||
doorsteptoggle,
|
||||
doormodetoggle,
|
||||
departureannounce,
|
||||
doorlocktoggle,
|
||||
pantographcompressorvalvetoggle,
|
||||
|
||||
@@ -156,6 +156,7 @@ driverkeyboard_input::default_bindings() {
|
||||
// doorcloseright,
|
||||
{ user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control },
|
||||
// doorsteptoggle,
|
||||
{ user_command::doormodetoggle, GLFW_KEY_SLASH | keymodifier::shift | keymodifier::control },
|
||||
{ user_command::departureannounce, GLFW_KEY_SLASH },
|
||||
{ user_command::doorlocktoggle, GLFW_KEY_S | keymodifier::control },
|
||||
{ user_command::pantographcompressorvalvetoggle, GLFW_KEY_V | keymodifier::control },
|
||||
|
||||
@@ -22,7 +22,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "uilayer.h"
|
||||
#include "Logs.h"
|
||||
|
||||
auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.65 };
|
||||
auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.6 };
|
||||
|
||||
void
|
||||
mouse_slider::bind( user_command const &Command ) {
|
||||
@@ -634,6 +634,9 @@ drivermouse_input::default_bindings() {
|
||||
{ "doorstep_sw:", {
|
||||
user_command::doorsteptoggle,
|
||||
user_command::none } },
|
||||
{ "doormode_sw:", {
|
||||
user_command::doormodetoggle,
|
||||
user_command::none } },
|
||||
{ "departure_signal_bt:", {
|
||||
user_command::departureannounce,
|
||||
user_command::none } },
|
||||
|
||||
@@ -229,6 +229,7 @@ timetable_panel::update() {
|
||||
if( false == is_open ) { return; }
|
||||
|
||||
text_lines.clear();
|
||||
m_tablelines.clear();
|
||||
|
||||
auto const *train { simulation::Train };
|
||||
auto const *controlled { ( train ? train->Dynamic() : nullptr ) };
|
||||
@@ -239,7 +240,7 @@ timetable_panel::update() {
|
||||
std::snprintf(
|
||||
m_buffer.data(), m_buffer.size(),
|
||||
locale::strings[ locale::string::driver_timetable_header ].c_str(),
|
||||
40, 40,
|
||||
37, 37,
|
||||
locale::strings[ locale::string::driver_timetable_name ].c_str(),
|
||||
time.wHour,
|
||||
time.wMinute,
|
||||
@@ -274,7 +275,7 @@ timetable_panel::update() {
|
||||
}
|
||||
|
||||
{ // next station
|
||||
auto const nextstation = Bezogonkow( owner->NextStop(), true );
|
||||
auto const nextstation = owner->NextStop();
|
||||
if( false == nextstation.empty() ) {
|
||||
// jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania
|
||||
auto textline = " -> " + nextstation;
|
||||
@@ -317,67 +318,126 @@ timetable_panel::update() {
|
||||
}
|
||||
else {
|
||||
|
||||
auto const loadingcolor { glm::vec4( 164.0f / 255.0f, 84.0f / 255.0f, 84.0f / 255.0f, 1.f ) };
|
||||
auto const waitcolor { glm::vec4( 164.0f / 255.0f, 132.0f / 255.0f, 84.0f / 255.0f, 1.f ) };
|
||||
auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) };
|
||||
|
||||
// header
|
||||
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
|
||||
m_tablelines.emplace_back( u8"┌─────┬────────────────────────────────────┬─────────┬─────┐", Global.UITextColor );
|
||||
|
||||
TMTableLine const *tableline;
|
||||
for( int i = owner->iStationStart; i <= table->StationCount; ++i ) {
|
||||
// wyświetlenie pozycji z rozkładu
|
||||
tableline = table->TimeTable + i; // linijka rozkładu
|
||||
|
||||
std::string vmax =
|
||||
" "
|
||||
+ to_string( tableline->vmax, 0 );
|
||||
bool vmaxchange { true };
|
||||
if( i > owner->iStationStart ) {
|
||||
auto const *previoustableline { tableline - 1 };
|
||||
if( tableline->vmax == previoustableline->vmax ) {
|
||||
vmaxchange = false;
|
||||
}
|
||||
}
|
||||
std::string vmax { " " };
|
||||
if( true == vmaxchange ) {
|
||||
vmax += to_string( tableline->vmax, 0 );
|
||||
vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej
|
||||
std::string const station = (
|
||||
}
|
||||
auto const station { (
|
||||
Bezogonkow( tableline->StationName, true )
|
||||
+ " " )
|
||||
.substr( 0, 34 );
|
||||
std::string const location = (
|
||||
.substr( 0, 34 ) };
|
||||
auto const location { (
|
||||
( tableline->km > 0.0 ?
|
||||
to_string( tableline->km, 2 ) :
|
||||
"" )
|
||||
+ " " )
|
||||
.substr( 0, 34 - tableline->StationWare.size() );
|
||||
std::string const arrival = (
|
||||
.substr( 0, 34 - tableline->StationWare.size() ) };
|
||||
auto const arrival { (
|
||||
tableline->Ah >= 0 ?
|
||||
to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Am ) ).substr( 1, 2 ) :
|
||||
" | " );
|
||||
std::string const departure = (
|
||||
to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Am, true, 3 ) :
|
||||
u8" │ " ) };
|
||||
auto const departure { (
|
||||
tableline->Dh >= 0 ?
|
||||
to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Dm ) ).substr( 1, 2 ) :
|
||||
" | " );
|
||||
auto const candeparture = (
|
||||
to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Dm, true, 3 ) :
|
||||
u8" │ " ) };
|
||||
auto const candeparture { (
|
||||
( owner->iStationStart < table->StationIndex )
|
||||
&& ( i < table->StationIndex )
|
||||
&& ( ( tableline->Ah < 0 ) // pass-through, always valid
|
||||
|| ( time.wHour * 60 + time.wMinute >= tableline->Dh * 60 + tableline->Dm ) ) );
|
||||
auto traveltime =
|
||||
" "
|
||||
+ ( i < 2 ? "" :
|
||||
tableline->Ah >= 0 ? to_string( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), 0 ) :
|
||||
to_string( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), 0 ) );
|
||||
traveltime = traveltime.substr( traveltime.size() - 3, 3 ); // z wyrównaniem do prawej
|
||||
|
||||
text_lines.emplace_back(
|
||||
( "| " + vmax + " | " + station + " | " + arrival + " | " + traveltime + " |" ),
|
||||
( candeparture ?
|
||||
readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono
|
||||
Global.UITextColor ) );
|
||||
text_lines.emplace_back(
|
||||
( "| | " + location + tableline->StationWare + " | " + departure + " | |" ),
|
||||
( candeparture ?
|
||||
readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono
|
||||
Global.UITextColor ) );
|
||||
|| ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ) };
|
||||
auto const loadchangeinprogress { ( ( static_cast<int>( std::ceil( -1.0 * owner->fStopTime ) ) ) > 0 ) };
|
||||
auto const isatpassengerstop { ( true == owner->IsAtPassengerStop ) && ( vehicle->MoverParameters->Vel < 1.0 ) };
|
||||
auto const traveltime { (
|
||||
i < 2 ? " " :
|
||||
tableline->Ah >= 0 ? to_minutes_str( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), false, 3 ) :
|
||||
to_minutes_str( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), false, 3 ) ) };
|
||||
auto const linecolor { (
|
||||
( i != owner->iStationStart ) ? Global.UITextColor :
|
||||
loadchangeinprogress ? loadingcolor :
|
||||
candeparture ? readycolor : // czas minął i odjazd był, to nazwa stacji będzie na zielono
|
||||
isatpassengerstop ? waitcolor :
|
||||
Global.UITextColor ) };
|
||||
m_tablelines.emplace_back(
|
||||
( u8"│ " + vmax + u8" │ " + station + u8" │ " + arrival + u8" │ " + traveltime + u8" │" ),
|
||||
linecolor );
|
||||
m_tablelines.emplace_back(
|
||||
( u8"│ │ " + location + tableline->StationWare + u8" │ " + departure + u8" │ │" ),
|
||||
linecolor );
|
||||
// divider/footer
|
||||
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
|
||||
if( i < table->StationCount ) {
|
||||
auto const *nexttableline { tableline + 1 };
|
||||
if( tableline->vmax == nexttableline->vmax ) {
|
||||
m_tablelines.emplace_back( u8"│ ├────────────────────────────────────┼─────────┼─────┤", Global.UITextColor );
|
||||
}
|
||||
else {
|
||||
m_tablelines.emplace_back( u8"├─────┼────────────────────────────────────┼─────────┼─────┤", Global.UITextColor );
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_tablelines.emplace_back( u8"└─────┴────────────────────────────────────┴─────────┴─────┘", Global.UITextColor );
|
||||
}
|
||||
}
|
||||
}
|
||||
} // is_expanded
|
||||
}
|
||||
|
||||
void
|
||||
timetable_panel::render() {
|
||||
|
||||
if( false == is_open ) { return; }
|
||||
if( true == text_lines.empty() ) { return; }
|
||||
|
||||
auto flags =
|
||||
ImGuiWindowFlags_NoFocusOnAppearing
|
||||
| ImGuiWindowFlags_NoCollapse
|
||||
| ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 );
|
||||
|
||||
if( size.x > 0 ) {
|
||||
ImGui::SetNextWindowSize( ImVec2( size.x, size.y ) );
|
||||
}
|
||||
if( size_min.x > 0 ) {
|
||||
ImGui::SetNextWindowSizeConstraints( ImVec2( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) );
|
||||
}
|
||||
auto const panelname { (
|
||||
title.empty() ?
|
||||
name :
|
||||
title )
|
||||
+ "###" + name };
|
||||
if( true == ImGui::Begin( panelname.c_str(), &is_open, flags ) ) {
|
||||
for( auto const &line : text_lines ) {
|
||||
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
|
||||
}
|
||||
if( is_expanded ) {
|
||||
ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 1, 0 ) );
|
||||
for( auto const &line : m_tablelines ) {
|
||||
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void
|
||||
debug_panel::update() {
|
||||
|
||||
@@ -725,6 +785,7 @@ debug_panel::update_section_engine( std::vector<text_line> &Output ) {
|
||||
|
||||
std::string parameterstext = "param value";
|
||||
std::vector< std::pair <std::string, double> > const paramvalues {
|
||||
{ " rpm: ", mover.enrot * 60.0 },
|
||||
{ "efill: ", mover.dizel_fill },
|
||||
{ "etorq: ", mover.dizel_Torque },
|
||||
{ "creal: ", mover.dizel_engage },
|
||||
|
||||
@@ -50,12 +50,14 @@ public:
|
||||
: ui_panel( Name, Isopen ) {}
|
||||
|
||||
void update() override;
|
||||
void render() override;
|
||||
|
||||
bool is_expanded{ false };
|
||||
|
||||
private:
|
||||
// members
|
||||
std::array<char, 256> m_buffer;
|
||||
std::vector<text_line> m_tablelines;
|
||||
};
|
||||
|
||||
class debug_panel : public ui_panel {
|
||||
|
||||
26
mtable.cpp
26
mtable.cpp
@@ -51,7 +51,7 @@ bool TTrainParameters::IsStop() const
|
||||
|
||||
bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) {
|
||||
|
||||
return UpdateMTable( Time.data().wHour, Time.data().wMinute, NewName );
|
||||
return UpdateMTable( Time.data().wHour, Time.data().wMinute + Time.data().wSecond * 0.0167, NewName );
|
||||
}
|
||||
|
||||
bool TTrainParameters::UpdateMTable(double hh, double mm, std::string const &NewName)
|
||||
@@ -358,12 +358,12 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
|
||||
if (s.find(hrsd) != std::string::npos)
|
||||
{
|
||||
record->Ah = atoi( s.substr(0, s.find(hrsd)).c_str()); // godzina przyjazdu
|
||||
record->Am = atoi(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta przyjazdu
|
||||
record->Am = atof(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta przyjazdu
|
||||
}
|
||||
else
|
||||
{
|
||||
record->Ah = TimeTable[StationCount - 1].Ah; // godzina z poprzedniej pozycji
|
||||
record->Am = atoi(s.c_str()); // bo tylko minuty podane
|
||||
record->Am = atof(s.c_str()); // bo tylko minuty podane
|
||||
}
|
||||
}
|
||||
do
|
||||
@@ -408,12 +408,12 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
|
||||
if (s.find(hrsd) != std::string::npos)
|
||||
{
|
||||
record->Dh = atoi(s.substr(0, s.find(hrsd)).c_str()); // godzina odjazdu
|
||||
record->Dm = atoi(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta odjazdu
|
||||
record->Dm = atof(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta odjazdu
|
||||
}
|
||||
else
|
||||
{
|
||||
record->Dh = TimeTable[StationCount - 1].Dh; // godzina z poprzedniej pozycji
|
||||
record->Dm = atoi(s.c_str()); // bo tylko minuty podane
|
||||
record->Dm = atof(s.c_str()); // bo tylko minuty podane
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -475,20 +475,20 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
|
||||
if( timeoffset != 0 ) // jeżeli jest przesunięcie rozkładu
|
||||
{
|
||||
long i_end = StationCount + 1;
|
||||
int adjustedtime; // do zwiększania czasu
|
||||
float adjustedtime; // do zwiększania czasu
|
||||
for (auto i = 1; i < i_end; ++i) // bez with, bo ciężko się przenosi na C++
|
||||
{
|
||||
if ((TimeTable[i].Ah >= 0))
|
||||
{
|
||||
adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty
|
||||
TimeTable[i].Am = adjustedtime % 60;
|
||||
TimeTable[i].Ah = (adjustedtime / 60) % 24;
|
||||
adjustedtime = clamp_circular<float>( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty
|
||||
TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.f;
|
||||
TimeTable[i].Ah = int((adjustedtime) / 60) % 24;
|
||||
}
|
||||
if ((TimeTable[i].Dh >= 0))
|
||||
{
|
||||
adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty
|
||||
TimeTable[i].Dm = adjustedtime % 60;
|
||||
TimeTable[i].Dh = (adjustedtime / 60) % 24;
|
||||
adjustedtime = clamp_circular<float>( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty
|
||||
TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.f;
|
||||
TimeTable[i].Dh = int((adjustedtime) / 60) % 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -532,6 +532,8 @@ void TTrainParameters::serialize( dictionary_source *Output ) const {
|
||||
Output->insert( "train_enginetype", LocSeries );
|
||||
Output->insert( "train_engineload", LocLoad );
|
||||
|
||||
Output->insert( "train_stationfrom", Relation1 );
|
||||
Output->insert( "train_stationto", Relation2 );
|
||||
Output->insert( "train_stationindex", StationIndex );
|
||||
Output->insert( "train_stationcount", StationCount );
|
||||
if( StationCount > 0 ) {
|
||||
|
||||
10
mtable.h
10
mtable.h
@@ -24,18 +24,18 @@ static char const *hrsd = ".";
|
||||
|
||||
struct TMTableLine
|
||||
{
|
||||
double km; // kilometraz linii
|
||||
double vmax; // predkosc rozkladowa przed przystankiem
|
||||
float km; // kilometraz linii
|
||||
float vmax; // predkosc rozkladowa przed przystankiem
|
||||
// StationName:string[32]; //nazwa stacji ('_' zamiast spacji)
|
||||
// StationWare:string[32]; //typ i wyposazenie stacji, oddz. przecinkami}
|
||||
std::string StationName; // nazwa stacji ('_' zamiast spacji)
|
||||
std::string StationWare; // typ i wyposazenie stacji, oddz. przecinkami}
|
||||
int TrackNo; // ilosc torow szlakowych
|
||||
int Ah;
|
||||
int Am; // godz. i min. przyjazdu, -1 gdy bez postoju
|
||||
float Am; // godz. i min. przyjazdu, -1 gdy bez postoju
|
||||
int Dh;
|
||||
int Dm; // godz. i min. odjazdu
|
||||
double tm; // czas jazdy do tej stacji w min. (z kolumny)
|
||||
float Dm; // godz. i min. odjazdu
|
||||
float tm; // czas jazdy do tej stacji w min. (z kolumny)
|
||||
TMTableLine()
|
||||
{
|
||||
km = 0;
|
||||
|
||||
61
renderer.cpp
61
renderer.cpp
@@ -32,17 +32,18 @@ int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental
|
||||
void
|
||||
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_DIFFUSE, glm::value_ptr( diffuse ) );
|
||||
::glLightfv( id, GL_SPECULAR, glm::value_ptr( specular ) );
|
||||
}
|
||||
else {
|
||||
auto const factor{ clamp( Factor, 0.05f, 1.f ) };
|
||||
// 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 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 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 scaledspecular( specular.r * factor, specular.g * factor, specular.b * factor, specular.a );
|
||||
glLightfv( id, GL_AMBIENT, glm::value_ptr( scaledambient ) );
|
||||
glLightfv( id, GL_DIFFUSE, glm::value_ptr( scaleddiffuse ) );
|
||||
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
|
||||
// render
|
||||
if( Dynamic->mdLowPolyInt ) {
|
||||
// low poly interior
|
||||
/*
|
||||
if( ( true == FreeFlyModeFlag )
|
||||
|| ( ( Dynamic->mdKabina == nullptr ) || ( false == Dynamic->bDisplayCab ) ) ) {
|
||||
*/
|
||||
/*
|
||||
// enable cab light if needed
|
||||
if( Dynamic->InteriorLightLevel > 0.0f ) {
|
||||
// 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 ) ) ) };
|
||||
m_sunlight.apply_intensity(
|
||||
clamp( (
|
||||
Dynamic->fShade > 0.f ?
|
||||
Dynamic->fShade :
|
||||
1.f )
|
||||
- luminance,
|
||||
0.f, 1.f ) );
|
||||
|
||||
// crude way to light the cabin, until we have something more complete in place
|
||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) );
|
||||
}
|
||||
*/
|
||||
// low poly interior
|
||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||
/*
|
||||
if( Dynamic->InteriorLightLevel > 0.0f ) {
|
||||
// reset the overall ambient
|
||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( m_baseambient ) );
|
||||
}
|
||||
*/
|
||||
/*
|
||||
}
|
||||
*/
|
||||
}
|
||||
if( Dynamic->mdModel )
|
||||
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
|
||||
// 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 ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
}
|
||||
|
||||
m_sunlight.apply_intensity( Dynamic->fShade > 0.f ? Dynamic->fShade : 1.f );
|
||||
}
|
||||
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 );
|
||||
}
|
||||
// post-render cleanup
|
||||
m_renderspecular = false;
|
||||
if( Dynamic->fShade > 0.0f ) {
|
||||
|
||||
@@ -163,16 +163,24 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch
|
||||
// atmosphere color; legacy parameter, no longer used
|
||||
Input.getTokens( 3 );
|
||||
// fog range
|
||||
{
|
||||
double fograngestart, fograngeend;
|
||||
Input.getTokens( 2 );
|
||||
Input
|
||||
>> Global.fFogStart
|
||||
>> Global.fFogEnd;
|
||||
>> fograngestart
|
||||
>> fograngeend;
|
||||
|
||||
if( Global.fFogEnd > 0.0 ) {
|
||||
if( Global.fFogEnd != 0.0 ) {
|
||||
// fog colour; optional legacy parameter, no longer used
|
||||
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>() };
|
||||
if( token != "endatmo" ) {
|
||||
// optional overcast parameter
|
||||
|
||||
@@ -131,6 +131,7 @@ init() {
|
||||
"all doors (open)",
|
||||
"all doors (close)",
|
||||
"doorstep",
|
||||
"door control mode",
|
||||
"departure signal",
|
||||
"upper headlight",
|
||||
"left headlight",
|
||||
@@ -296,6 +297,7 @@ init() {
|
||||
"drzwi (otworz)",
|
||||
"drzwi (zamknij)",
|
||||
"stopien drzwi",
|
||||
"tryb sterowania drzwiami",
|
||||
"sygnal odjazdu",
|
||||
"reflektor gorny",
|
||||
"reflektor lewy",
|
||||
@@ -414,6 +416,7 @@ init() {
|
||||
"doorallon_sw:",
|
||||
"dooralloff_sw:",
|
||||
"doorstep_sw:",
|
||||
"doormode_sw:",
|
||||
"departure_signal_bt:",
|
||||
"upperlight_sw:",
|
||||
"leftlight_sw:",
|
||||
|
||||
@@ -120,6 +120,7 @@ enum string {
|
||||
cab_doorallon_sw,
|
||||
cab_dooralloff_sw,
|
||||
cab_doorstep_sw,
|
||||
cab_doormode_sw,
|
||||
cab_departure_signal_bt,
|
||||
cab_upperlight_sw,
|
||||
cab_leftlight_sw,
|
||||
|
||||
@@ -101,8 +101,15 @@ ui_layer::init( GLFWwindow *Window ) {
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
||||
static ImWchar const glyphranges[] = {
|
||||
0x0020, 0x00FF, // ascii + extension
|
||||
0x2070, 0x2079, // superscript
|
||||
0x2500, 0x256C, // box drawings
|
||||
0,
|
||||
};
|
||||
m_imguiio = &ImGui::GetIO();
|
||||
m_imguiio->Fonts->AddFontFromFileTTF("fonts/dejavusansmono.ttf", 13.0f);
|
||||
m_imguiio->Fonts->AddFontFromFileTTF( "fonts/dejavusansmono.ttf", 13.0f, nullptr, &glyphranges[ 0 ] );
|
||||
|
||||
ImGui::StyleColorsClassic();
|
||||
ImGui_ImplGlfw_InitForOpenGL(m_window);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
@@ -246,6 +246,24 @@ std::string to_hex_str( int const Value, int const Width )
|
||||
return converter.str();
|
||||
};
|
||||
|
||||
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 result { DefaultValue };
|
||||
|
||||
@@ -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, int width);
|
||||
std::string to_hex_str( int const Value, int const width = 4 );
|
||||
std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width );
|
||||
|
||||
inline std::string to_string(bool Value) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user