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

Merge with TMJ

This commit is contained in:
Królik Uszasty
2019-05-22 21:31:56 +02:00
22 changed files with 370 additions and 214 deletions

View File

@@ -2127,11 +2127,12 @@ bool TController::CheckVehicles(TOrders user)
while (p) while (p)
{ {
// HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi... // HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi...
if( ( p != pVehicle ) if( p != pVehicle ) {
&& ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 ) if( ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 )
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) { && ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) {
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly // NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
p->MoverParameters->BatterySwitch( true ); p->MoverParameters->BatterySwitch( true );
}
// enable heating and converter in carriages with can be heated // enable heating and converter in carriages with can be heated
if( p->MoverParameters->HeatingPower > 0 ) { if( p->MoverParameters->HeatingPower > 0 ) {
p->MoverParameters->HeatingAllow = true; p->MoverParameters->HeatingAllow = true;
@@ -2730,8 +2731,12 @@ bool TController::IncBrake()
// NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself // NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself
// TODO: add easier ways to access front/rear coupler taking into account vehicle's direction // TODO: add easier ways to access front/rear coupler taking into account vehicle's direction
standalone = standalone =
( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) ) ( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr )
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) ) ); || ( ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control )
&& ( vehicle->MoverParameters->Couplers[ end::front ].Connected->Power > 1 ) ) )
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr )
|| ( ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control )
&& ( vehicle->MoverParameters->Couplers[ end::rear ].Connected->Power > 1 ) ) ) );
vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła) vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
} }
} }
@@ -4196,6 +4201,7 @@ TController::UpdateSituation(double dt) {
// HACK: activate route scanning if an idling vehicle is activated by a human user // HACK: activate route scanning if an idling vehicle is activated by a human user
if( ( OrderCurrentGet() == Wait_for_orders ) if( ( OrderCurrentGet() == Wait_for_orders )
&& ( false == AIControllFlag ) && ( false == AIControllFlag )
&& ( false == iEngineActive )
&& ( true == mvControlling->Battery ) ) { && ( true == mvControlling->Battery ) ) {
OrderNext( Prepare_engine ); OrderNext( Prepare_engine );
} }
@@ -5024,54 +5030,50 @@ TController::UpdateSituation(double dt) {
// jeśli dociskanie w celu odczepienia // jeśli dociskanie w celu odczepienia
// 3. faza odczepiania. // 3. faza odczepiania.
SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2 SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2
if( ( mvControlling->MainCtrlPowerPos() > 0 ) if( iVehicleCount >= 0 ) {
|| ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) { // zmieni się po odczepieniu
// jeśli jazda WriteLog( mvOccupied->Name + " dociskanie..." );
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); while( mvOccupied->DecLocalBrakeLevel( 1 ) ) { // dociśnij sklad
TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI ;
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
int n = iVehicleCount; // ile wagonów ma zostać
do
{ // szukanie pojazdu do odczepienia
d = p->DirectionGet() > 0 ?
end::front :
end::rear; // numer sprzęgu od strony czoła składu
// if (p->MoverParameters->Couplers[d].CouplerType==Articulated)
// //jeśli sprzęg typu wózek (za mało)
if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany
// if (p->GetTrack()->) //a nie stoi na torze warsztatowym
// (ustalić po czym poznać taki tor)
++n; // to liczymy człony jako jeden
p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać
// GBH p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował
BrakeLevelSet(gbh_RP);
if (n)
{ // jeśli jeszcze nie koniec
p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy
if (!p)
iVehicleCount = -2,
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
}
} while (n--);
if( ( p == nullptr )
|| ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) {
// no target, or already just virtual coupling
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
iVehicleCount = -2; // odczepiono, co było do odczepienia
} else if ( p->Dettach(d) == coupling::faux ) {
// tylko jeśli odepnie
WriteLog( mvOccupied->Name + " odczepiony." );
iVehicleCount = -2;
} // a jak nie, to dociskać dalej
}
if (iVehicleCount >= 0) // zmieni się po odczepieniu
if (!mvOccupied->DecLocalBrakeLevel(1))
{ // dociśnij sklad
WriteLog( mvOccupied->Name + " dociskanie..." );
// mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę
// Ready=true; //zamiast sprawdzenia odhamowania całego składu
IncSpeed(); // dla (Ready)==false nie ruszy
} }
IncSpeed();
}
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute));
TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
int n = iVehicleCount; // ile wagonów ma zostać
do
{ // szukanie pojazdu do odczepienia
d = p->DirectionGet() > 0 ?
end::front :
end::rear; // numer sprzęgu od strony czoła składu
// if (p->MoverParameters->Couplers[d].CouplerType==Articulated)
// //jeśli sprzęg typu wózek (za mało)
if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany
// if (p->GetTrack()->) //a nie stoi na torze warsztatowym
// (ustalić po czym poznać taki tor)
++n; // to liczymy człony jako jeden
p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać
// GBH p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował
BrakeLevelSet(gbh_RP);
if (n)
{ // jeśli jeszcze nie koniec
p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy
if (!p)
iVehicleCount = -2,
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
}
} while (n--);
if( ( p == nullptr )
|| ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) {
// no target, or already just virtual coupling
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
iVehicleCount = -2; // odczepiono, co było do odczepienia
} else if ( p->Dettach(d) == coupling::faux ) {
// tylko jeśli odepnie
WriteLog( mvOccupied->Name + " odczepiony." );
iVehicleCount = -2;
} // a jak nie, to dociskać dalej
} }
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress)) if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
{ // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij { // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij
@@ -6598,17 +6600,18 @@ std::string TController::NextStop() const
// dodać godzinę odjazdu // dodać godzinę odjazdu
if (!TrainParams) if (!TrainParams)
return ""; // tu nie powinno nigdy wejść return ""; // tu nie powinno nigdy wejść
std::string nextstop = asNextStop; std::string nextstop = Bezogonkow( asNextStop, true );
TMTableLine *t = TrainParams->TimeTable + TrainParams->StationIndex; TMTableLine *t = TrainParams->TimeTable + TrainParams->StationIndex;
if( t->Ah >= 0 ) { if( t->Ah >= 0 ) {
// przyjazd // przyjazd
nextstop += " przyj." + std::to_string( t->Ah ) + ":" nextstop += " przyj." + std::to_string( t->Ah ) + ":"
+ ( t->Am < 10 ? "0" : "" ) + std::to_string( int(t->Am) ) + "." + std::to_string(int(t->Am * 10) % 10); + to_minutes_str( t->Am, true, 3 );
} }
if( t->Dh >= 0 ) { if( t->Dh >= 0 ) {
// jeśli jest godzina odjazdu // jeśli jest godzina odjazdu
nextstop += " odj." + std::to_string( t->Dh ) + ":" nextstop += " odj." + std::to_string( t->Dh ) + ":"
+ ( t->Dm < 10 ? "0" : "" ) + std::to_string( int( t->Dm )) + "." + std::to_string(int(t->Dm * 10) % 10); + to_minutes_str( t->Dm, true, 3 );
} }
return nextstop; return nextstop;
}; };

View File

@@ -201,6 +201,10 @@ public:
inline inline
TMoverParameters const *Controlling() const { TMoverParameters const *Controlling() const {
return mvControlling; } return mvControlling; }
inline
TMoverParameters const *Occupied() const {
return mvOccupied;
}
void DirectionInitial(); void DirectionInitial();
void DirectionChange(); void DirectionChange();
inline inline
@@ -251,6 +255,7 @@ public:
bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista
int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami
int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami
double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller
private: private:
bool Psyche = false; bool Psyche = false;
int HelperState = 0; //stan pomocnika maszynisty int HelperState = 0; //stan pomocnika maszynisty
@@ -318,7 +323,6 @@ private:
double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI
double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca
double BrakeChargingCooldown {}; // prevents the ai from trying to charge the train brake too frequently double BrakeChargingCooldown {}; // prevents the ai from trying to charge the train brake too frequently
double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller
double LastReactionTime = 0.0; double LastReactionTime = 0.0;
double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi
double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations

View File

@@ -6120,30 +6120,32 @@ TDynamicObject * TDynamicObject::ControlledFind()
// problematyczna może być kwestia wybranej kabiny (w silnikowym...) // problematyczna może być kwestia wybranej kabiny (w silnikowym...)
// jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno jeździć dobrze // jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno jeździć dobrze
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym... // również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
TDynamicObject *d = this; // zaczynamy od aktualnego if( MoverParameters->Power > 1.0 ) { return this; }
if( ( d->MoverParameters->TrainType == dt_EZT )
|| ( d->MoverParameters->TrainType == dt_DMU ) ) { auto const couplingtype { (
// na razie dotyczy to EZT ( MoverParameters->TrainType == dt_EZT )
if( ( d->NextConnected() != nullptr ) || ( MoverParameters->TrainType == dt_DMU ) ) ?
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) { coupling::permanent :
// gdy jest człon od sprzęgu 1, a sprzęg łączony warsztatowo (powiedzmy) coupling::control
if( ( d->MoverParameters->Power < 1.0 ) };
&& ( d->NextConnected()->MoverParameters->Power > 1.0 ) ) { // try first to look towards the rear
// my nie mamy mocy, ale ten drugi ma auto *d = this; // zaczynamy od aktualnego
d = d->NextConnected(); // będziemy sterować tym z mocą
} while( ( d = d->NextC( couplingtype ) ) != nullptr ) {
} if( d->MoverParameters->Power > 1.0 ) {
else if( ( d->PrevConnected() != nullptr ) return d;
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) {
// gdy jest człon od sprzęgu 0, a sprzęg łączony warsztatowo (powiedzmy)
if( ( d->MoverParameters->Power < 1.0 )
&& ( d->PrevConnected()->MoverParameters->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
d = d->PrevConnected(); // będziemy sterować tym z mocą
}
} }
} }
return d; // if we didn't yet find a suitable vehicle try in the other direction
d = this; // zaczynamy od aktualnego
while( ( d = d->PrevC( couplingtype ) ) != nullptr ) {
if( d->MoverParameters->Power > 1.0 ) {
return d;
}
}
// if we still don't have a match give up
return this;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -766,6 +766,7 @@ private:
// ld inputs // ld inputs
bool lock_enabled { true }; bool lock_enabled { true };
bool step_enabled { true }; bool step_enabled { true };
bool remote_only { false }; // door ignores local control signals
// internal data // internal data
int permit_preset { -1 }; // curent position of preset selection switch int permit_preset { -1 }; // curent position of preset selection switch
// vehicle parts // vehicle parts
@@ -1162,6 +1163,7 @@ public:
bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere) bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere)
bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure
start_t CompressorStart{ start_t::manual }; // whether the compressor is started manually, or another way start_t CompressorStart{ start_t::manual }; // whether the compressor is started manually, or another way
start_t PantographCompressorStart{ start_t::manual };
// TODO converter parameters, for when we start cleaning up mover parameters // TODO converter parameters, for when we start cleaning up mover parameters
start_t ConverterStart{ start_t::manual }; // whether converter is started manually, or by other means start_t ConverterStart{ start_t::manual }; // whether converter is started manually, or by other means
float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met
@@ -1346,8 +1348,6 @@ public:
bool PantRearUp = false; bool PantRearUp = false;
bool PantFrontSP = true; //dzwiek patykow 'Winger 010304 bool PantFrontSP = true; //dzwiek patykow 'Winger 010304
bool PantRearSP = true; bool PantRearSP = true;
int PantFrontStart = 0; //stan patykow 'Winger 160204
int PantRearStart = 0;
double PantFrontVolt = 0.0; //pantograf pod napieciem? 'Winger 160404 double PantFrontVolt = 0.0; //pantograf pod napieciem? 'Winger 160404
double PantRearVolt = 0.0; double PantRearVolt = 0.0;
// TODO: move these switch types where they belong, cabin definition // TODO: move these switch types where they belong, cabin definition
@@ -1555,6 +1555,7 @@ public:
bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist ); bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist );
bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist ); bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist );
bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist ); bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist );
bool ChangeDoorControlMode( bool const State, range_t const Notify = range_t::consist );
bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist ); bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist );
bool LockDoors( bool const State, range_t const Notify = range_t::consist ); bool LockDoors( bool const State, range_t const Notify = range_t::consist );
bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning

View File

@@ -653,11 +653,18 @@ void TMoverParameters::UpdatePantVolume(double dt)
{ // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak { // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak
// check the pantograph compressor while at it // check the pantograph compressor while at it
if( PantCompFlag ) { if( ( PantPress < 4.2 )
if( ( false == Battery ) && ( ( PantographCompressorStart == start_t::automatic )
&& ( false == ConverterFlag ) ) { || ( PantographCompressorStart == start_t::manualwithautofallback ) )
PantCompFlag = false; && ( ( true == PantRearUp )
} || ( true == PantFrontUp ) ) ) {
// automatic start if the pressure is too low
PantCompFlag = true;
}
if( ( true == PantCompFlag )
&& ( false == Battery )
&& ( false == ConverterFlag ) ) {
PantCompFlag = false;
} }
if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący
@@ -5924,7 +5931,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify )
if( PantFrontUp != State ) { if( PantFrontUp != State ) {
PantFrontUp = State; PantFrontUp = State;
if( State == true ) { if( State == true ) {
PantFrontStart = 0;
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych? // wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
@@ -5935,7 +5941,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify )
} }
} }
else { else {
PantFrontStart = 1;
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych? // wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
@@ -5977,7 +5982,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify )
if( PantRearUp != State ) { if( PantRearUp != State ) {
PantRearUp = State; PantRearUp = State;
if( State == true ) { if( State == true ) {
PantRearStart = 0;
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych? // wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
@@ -5988,7 +5992,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify )
} }
} }
else { else {
PantRearStart = 1;
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych? // wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
@@ -6939,12 +6942,7 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c
bool const initialstate { Doors.instances[Door].open_permit }; bool const initialstate { Doors.instances[Door].open_permit };
if( ( false == Doors.permit_presets.empty() ) // HACK: for cases where preset switch is used before battery Doors.instances[ Door ].open_permit = State;
|| ( ( true == Battery )
&& ( false == Doors.is_locked ) ) ) {
Doors.instances[ Door ].open_permit = State;
}
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
@@ -6963,6 +6961,34 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c
return ( Doors.instances[ Door ].open_permit != initialstate ); return ( Doors.instances[ Door ].open_permit != initialstate );
} }
bool TMoverParameters::ChangeDoorControlMode( bool const State, range_t const Notify ) {
auto const initialstate { Doors.remote_only };
Doors.remote_only = State;
if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych?
SendCtrlToNext(
"DoorMode",
( State == true ?
1 :
0 ),
CabNo,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
if( true == State ) {
// when door are put in remote control mode they're automatically open
// TBD, TODO: make it dependant on config switch?
OperateDoors( side::left, true );
OperateDoors( side::right, true );
}
return ( Doors.step_enabled != initialstate );
}
bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) { bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) {
auto &door { Doors.instances[ Door ] }; auto &door { Doors.instances[ Door ] };
@@ -7070,15 +7096,17 @@ TMoverParameters::update_doors( double const Deltatime ) {
// NBMX Obsluga drzwi, MC: zuniwersalnione // NBMX Obsluga drzwi, MC: zuniwersalnione
auto const localopencontrol { auto const localopencontrol {
( Doors.open_control == control_t::passenger ) ( false == Doors.remote_only )
|| ( Doors.open_control == control_t::mixed ) }; && ( ( Doors.open_control == control_t::passenger )
|| ( Doors.open_control == control_t::mixed ) ) };
auto const remoteopencontrol { auto const remoteopencontrol {
( Doors.open_control == control_t::driver ) ( Doors.open_control == control_t::driver )
|| ( Doors.open_control == control_t::conductor ) || ( Doors.open_control == control_t::conductor )
|| ( Doors.open_control == control_t::mixed ) }; || ( Doors.open_control == control_t::mixed ) };
auto const localclosecontrol { auto const localclosecontrol {
( Doors.close_control == control_t::passenger ) ( false == Doors.remote_only )
|| ( Doors.close_control == control_t::mixed ) }; && ( ( Doors.close_control == control_t::passenger )
|| ( Doors.close_control == control_t::mixed ) ) };
auto const remoteclosecontrol { auto const remoteclosecontrol {
( Doors.close_control == control_t::driver ) ( Doors.close_control == control_t::driver )
|| ( Doors.close_control == control_t::conductor ) || ( Doors.close_control == control_t::conductor )
@@ -7106,7 +7134,7 @@ TMoverParameters::update_doors( double const Deltatime ) {
&& ( door.step_position <= 0.f ); && ( door.step_position <= 0.f );
door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
door.remote_open = door.remote_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); door.remote_open = ( door.remote_open || Doors.remote_only ) && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit );
door.local_close = door.local_close && ( false == door.is_closed ); door.local_close = door.local_close && ( false == door.is_closed );
door.remote_close = door.remote_close && ( false == door.is_closed ); door.remote_close = door.remote_close && ( false == door.is_closed );
@@ -8760,6 +8788,14 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
lookup->second : lookup->second :
start_t::manual; start_t::manual;
} }
// pantograph compressor
{
auto lookup = starts.find( extract_value( "PantCompressorStart", line ) );
PantographCompressorStart =
lookup != starts.end() ?
lookup->second :
start_t::manual;
}
// fuel pump // fuel pump
{ {
auto lookup = starts.find( extract_value( "FuelStart", line ) ); auto lookup = starts.find( extract_value( "FuelStart", line ) );
@@ -10074,6 +10110,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
false ); false );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if( Command == "DoorMode" ) {
Doors.remote_only = (
CValue1 == 1 ?
true :
false );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if( Command == "DepartureSignal" ) { else if( Command == "DepartureSignal" ) {
DepartureSignal = ( DepartureSignal = (
CValue1 == 1 ? CValue1 == 1 ?
@@ -10090,12 +10133,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
if ((CValue1 == 1)) if ((CValue1 == 1))
{ {
PantFrontUp = true; PantFrontUp = true;
PantFrontStart = 0;
} }
else if ((CValue1 == 0)) else if ((CValue1 == 0))
{ {
PantFrontUp = false; PantFrontUp = false;
PantFrontStart = 1;
} }
} }
else else
@@ -10105,24 +10146,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {
PantFrontUp = true; PantFrontUp = true;
PantFrontStart = 0;
} }
else else
{ {
PantRearUp = true; PantRearUp = true;
PantRearStart = 0;
} }
else if ((CValue1 == 0)) else if ((CValue1 == 0))
if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) ||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {
PantFrontUp = false; PantFrontUp = false;
PantFrontStart = 1;
} }
else else
{ {
PantRearUp = false; PantRearUp = false;
PantRearStart = 1;
} }
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
@@ -10135,12 +10172,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
if ((CValue1 == 1)) if ((CValue1 == 1))
{ {
PantRearUp = true; PantRearUp = true;
PantRearStart = 0;
} }
else if ((CValue1 == 0)) else if ((CValue1 == 0))
{ {
PantRearUp = false; PantRearUp = false;
PantRearStart = 1;
} }
} }
else else
@@ -10151,24 +10186,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {
PantRearUp = true; PantRearUp = true;
PantRearStart = 0;
} }
else else
{ {
PantFrontUp = true; PantFrontUp = true;
PantFrontStart = 0;
} }
else if ((CValue1 == 0)) else if ((CValue1 == 0))
if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) ||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {
PantRearUp = false; PantRearUp = false;
PantRearStart = 1;
} }
else else
{ {
PantFrontUp = false; PantFrontUp = false;
PantFrontStart = 1;
} }
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );

112
Train.cpp
View File

@@ -327,6 +327,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::dooropenall, &TTrain::OnCommand_dooropenall }, { user_command::dooropenall, &TTrain::OnCommand_dooropenall },
{ user_command::doorcloseall, &TTrain::OnCommand_doorcloseall }, { user_command::doorcloseall, &TTrain::OnCommand_doorcloseall },
{ user_command::doorsteptoggle, &TTrain::OnCommand_doorsteptoggle }, { user_command::doorsteptoggle, &TTrain::OnCommand_doorsteptoggle },
{ user_command::doormodetoggle, &TTrain::OnCommand_doormodetoggle },
{ user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease }, { user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease },
{ user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect }, { user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect },
{ user_command::departureannounce, &TTrain::OnCommand_departureannounce }, { user_command::departureannounce, &TTrain::OnCommand_departureannounce },
@@ -786,7 +787,7 @@ void TTrain::OnCommand_mastercontrollerincrease( TTrain *Train, command_data con
if( Command.action != GLFW_RELEASE ) { if( Command.action != GLFW_RELEASE ) {
// on press or hold // on press or hold
if( ( Train->ggJointCtrl.SubModel != nullptr ) if( ( Train->ggJointCtrl.SubModel != nullptr )
&& ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { && ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) {
OnCommand_independentbrakedecrease( Train, Command ); OnCommand_independentbrakedecrease( Train, Command );
} }
else { else {
@@ -806,7 +807,7 @@ void TTrain::OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data
if( Command.action != GLFW_RELEASE ) { if( Command.action != GLFW_RELEASE ) {
// on press or hold // on press or hold
if( ( Train->ggJointCtrl.SubModel != nullptr ) if( ( Train->ggJointCtrl.SubModel != nullptr )
&& ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { && ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) {
OnCommand_independentbrakedecreasefast( Train, Command ); OnCommand_independentbrakedecreasefast( Train, Command );
} }
else { else {
@@ -1730,10 +1731,11 @@ void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Co
} }
} }
// TODO: replace battery with a two-state device, update switch code accordingly
void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) { if( Command.action != GLFW_REPEAT ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down // keep the switch from flipping back and forth if key is held down
if( false == Train->mvOccupied->Battery ) { if( false == Train->mvOccupied->Battery ) {
// turn on // turn on
OnCommand_batteryenable( Train, Command ); OnCommand_batteryenable( Train, Command );
@@ -1747,16 +1749,13 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command
void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) {
if( true == Train->mvOccupied->Battery ) { return; } // already on
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// ignore repeats // visual feedback
// wyłącznik jest też w SN61, ewentualnie załączać prąd na stałe z poziomu FIZ Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch );
if( true == Train->mvOccupied->Battery ) { return; } // already on
if( Train->mvOccupied->BatterySwitch( true ) ) { if( Train->mvOccupied->BatterySwitch( true ) ) {
// bateria potrzebna np. do zapalenia świateł
if( Train->ggBatteryButton.SubModel ) {
Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch );
}
// side-effects // side-effects
if( Train->mvOccupied->LightsPosNo > 0 ) { if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->SetLights(); Train->SetLights();
@@ -1768,19 +1767,23 @@ void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command
} }
} }
} }
else if( Command.action == GLFW_RELEASE ) {
if( Train->ggBatteryButton.type() == TGaugeType::push ) {
// return the switch to neutral position
Train->ggBatteryButton.UpdateValue( 0.5f );
}
}
} }
void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) {
// TBD, TODO: ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
if( false == Train->mvOccupied->Battery ) { return; } // already off
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// ignore repeats // visual feedback
Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch );
if( false == Train->mvOccupied->Battery ) { return; } // already off
if( Train->mvOccupied->BatterySwitch( false ) ) { if( Train->mvOccupied->BatterySwitch( false ) ) {
// ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
if( Train->ggBatteryButton.SubModel ) {
Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch );
}
// side-effects // side-effects
if( false == Train->mvControlled->ConverterFlag ) { if( false == Train->mvControlled->ConverterFlag ) {
// if there's no (low voltage) power source left, drop pantographs // if there's no (low voltage) power source left, drop pantographs
@@ -1789,6 +1792,12 @@ void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Comman
} }
} }
} }
else if( Command.action == GLFW_RELEASE ) {
if( Train->ggBatteryButton.type() == TGaugeType::push ) {
// return the switch to neutral position
Train->ggBatteryButton.UpdateValue( 0.5f );
}
}
} }
void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &Command ) {
@@ -4138,7 +4147,7 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
} }
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down // ignore repeats so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->HeatingAllow ) { if( false == Train->mvControlled->HeatingAllow ) {
// turn on // turn on
OnCommand_heatingenable( Train, Command ); OnCommand_heatingenable( Train, Command );
@@ -4148,6 +4157,14 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
OnCommand_heatingdisable( Train, Command ); OnCommand_heatingdisable( Train, Command );
} }
} }
else if( Command.action == GLFW_RELEASE ) {
if( Train->ggTrainHeatingButton.type() == TGaugeType::push ) {
// impulse switch
// visual feedback
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
}
}
} }
void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) {
@@ -4166,7 +4183,11 @@ void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Comman
Train->mvControlled->HeatingAllow = false; Train->mvControlled->HeatingAllow = false;
// visual feedback // visual feedback
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggTrainHeatingButton.UpdateValue(
( Train->ggTrainHeatingButton.type() == TGaugeType::push ?
1.0 :
0.0 ),
Train->dsbSwitch );
} }
} }
@@ -4733,6 +4754,13 @@ void TTrain::OnCommand_doorsteptoggle( TTrain *Train, command_data const &Comman
} }
} }
void TTrain::OnCommand_doormodetoggle( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
Train->mvOccupied->ChangeDoorControlMode( false == Train->mvOccupied->Doors.remote_only );
}
}
void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) {
if( ( true == FreeFlyModeFlag ) if( ( true == FreeFlyModeFlag )
@@ -7135,28 +7163,11 @@ void TTrain::DynamicSet(TDynamicObject *d)
// jeździć dobrze // jeździć dobrze
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym... // również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
DynamicObject = d; // jedyne miejsce zmiany DynamicObject = d; // jedyne miejsce zmiany
mvOccupied = mvControlled = d ? DynamicObject->MoverParameters : NULL; // albo silnikowy w EZT mvOccupied = mvControlled = ( d ? DynamicObject->MoverParameters : nullptr ); // albo silnikowy w EZT
if (!DynamicObject)
return;
// TODO: leverage code already present in TDynamicObject::ControlledFind()
if( ( d->MoverParameters->TrainType == dt_EZT )
|| ( d->MoverParameters->TrainType == dt_DMU ) ) {
if( ( d->NextConnected() != nullptr ) if( DynamicObject == nullptr ) { return; }
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) {
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 1 ].Connected->Power > 1.0 ) ) { mvControlled = DynamicObject->ControlledFind()->MoverParameters;
// my nie mamy mocy, ale ten drugi ma
mvControlled = DynamicObject->NextConnected()->MoverParameters; // będziemy sterować tym z mocą
}
}
else if( ( d->PrevConnected() != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) {
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 0 ].Connected->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
mvControlled = DynamicObject->PrevConnected()->MoverParameters; // będziemy sterować tym z mocą
}
}
}
mvSecond = NULL; // gdyby się nic nie znalazło mvSecond = NULL; // gdyby się nic nie znalazło
if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo
if (mvOccupied->Couplers[1].Connected ? if (mvOccupied->Couplers[1].Connected ?
@@ -7480,9 +7491,10 @@ void TTrain::clear_cab_controls()
void TTrain::set_cab_controls( int const Cab ) { void TTrain::set_cab_controls( int const Cab ) {
// switches // switches
// battery // battery
if( true == mvOccupied->Battery ) { ggBatteryButton.PutValue(
ggBatteryButton.PutValue( 1.f ); ( ggBatteryButton.type() == TGaugeType::push ? 0.5f :
} mvOccupied->Battery ? 1.f :
0.f ) );
// motor connectors // motor connectors
ggStLinOffButton.PutValue( ggStLinOffButton.PutValue(
( mvControlled->StLinSwitchOff ? ( mvControlled->StLinSwitchOff ?
@@ -7660,8 +7672,11 @@ void TTrain::set_cab_controls( int const Cab ) {
1.f : 1.f :
0.f ); 0.f );
// heating // heating
if( true == mvControlled->Heating ) { if( ggTrainHeatingButton.type() != TGaugeType::push ) {
ggTrainHeatingButton.PutValue( 1.f ); ggTrainHeatingButton.PutValue(
mvControlled->Heating ?
1.f :
0.f );
} }
// brake acting time // brake acting time
if( ggBrakeProfileCtrl.SubModel != nullptr ) { if( ggBrakeProfileCtrl.SubModel != nullptr ) {
@@ -8050,6 +8065,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
} }
// TODO: move viable dedicated gauges to the automatic array // TODO: move viable dedicated gauges to the automatic array
std::unordered_map<std::string, bool *> const autoboolgauges = { std::unordered_map<std::string, bool *> const autoboolgauges = {
{ "doormode_sw:", &mvOccupied->Doors.remote_only },
{ "doorstep_sw:", &mvOccupied->Doors.step_enabled }, { "doorstep_sw:", &mvOccupied->Doors.step_enabled },
{ "coolingfans_sw:", &mvControlled->RVentForceOn } { "coolingfans_sw:", &mvControlled->RVentForceOn }
}; };

View File

@@ -329,6 +329,7 @@ class TTrain
static void OnCommand_dooropenall( TTrain *Train, command_data const &Command ); static void OnCommand_dooropenall( TTrain *Train, command_data const &Command );
static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command ); static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command );
static void OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command ); static void OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command );
static void OnCommand_doormodetoggle( TTrain *Train, command_data const &Command );
static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command );
static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command );
static void OnCommand_departureannounce( TTrain *Train, command_data const &Command ); static void OnCommand_departureannounce( TTrain *Train, command_data const &Command );

View File

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

View File

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

View File

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

View File

@@ -633,6 +633,9 @@ drivermouse_input::default_bindings() {
{ "doorstep_sw:", { { "doorstep_sw:", {
user_command::doorsteptoggle, user_command::doorsteptoggle,
user_command::none } }, user_command::none } },
{ "doormode_sw:", {
user_command::doormodetoggle,
user_command::none } },
{ "departure_signal_bt:", { { "departure_signal_bt:", {
user_command::departureannounce, user_command::departureannounce,
user_command::none } }, user_command::none } },

View File

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

View File

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

View File

@@ -480,14 +480,14 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
{ {
if ((TimeTable[i].Ah >= 0)) if ((TimeTable[i].Ah >= 0))
{ {
adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24.0 * 60.0 ); // nowe minuty adjustedtime = clamp_circular<float>( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty
TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.0; TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.f;
TimeTable[i].Ah = int((adjustedtime) / 60) % 24; TimeTable[i].Ah = int((adjustedtime) / 60) % 24;
} }
if ((TimeTable[i].Dh >= 0)) if ((TimeTable[i].Dh >= 0))
{ {
adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24.0 * 60.0 ); // nowe minuty adjustedtime = clamp_circular<float>( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty
TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.0; TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.f;
TimeTable[i].Dh = int((adjustedtime) / 60) % 24; TimeTable[i].Dh = int((adjustedtime) / 60) % 24;
} }
} }

View File

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

View File

@@ -179,7 +179,7 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch
Global.fFogEnd = Global.fFogEnd =
clamp( clamp(
Random( std::min( fograngestart, fograngeend ), std::max( fograngestart, fograngeend ) ), Random( std::min( fograngestart, fograngeend ), std::max( fograngestart, fograngeend ) ),
100.0, 2000.0 ); 10.0, 2000.0 );
} }
std::string token { Input.getToken<std::string>() }; std::string token { Input.getToken<std::string>() };

View File

@@ -131,6 +131,7 @@ init() {
"all doors (open)", "all doors (open)",
"all doors (close)", "all doors (close)",
"doorstep", "doorstep",
"door control mode",
"departure signal", "departure signal",
"upper headlight", "upper headlight",
"left headlight", "left headlight",
@@ -296,6 +297,7 @@ init() {
"drzwi (otworz)", "drzwi (otworz)",
"drzwi (zamknij)", "drzwi (zamknij)",
"stopien drzwi", "stopien drzwi",
"tryb sterowania drzwiami",
"sygnal odjazdu", "sygnal odjazdu",
"reflektor gorny", "reflektor gorny",
"reflektor lewy", "reflektor lewy",
@@ -414,6 +416,7 @@ init() {
"doorallon_sw:", "doorallon_sw:",
"dooralloff_sw:", "dooralloff_sw:",
"doorstep_sw:", "doorstep_sw:",
"doormode_sw:",
"departure_signal_bt:", "departure_signal_bt:",
"upperlight_sw:", "upperlight_sw:",
"leftlight_sw:", "leftlight_sw:",

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
/* /*
This Source Code Form is subject to the This Source Code Form is subject to the
terms of the Mozilla Public License, v. terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not 2.0. If a copy of the MPL was not
@@ -246,6 +246,24 @@ std::string to_hex_str( int const Value, int const Width )
return converter.str(); return converter.str();
}; };
char * const fractionlabels[] = { " ", u8"¹", u8"²", u8"³", u8"", u8"", u8"", u8"", u8"", u8"" };
std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width ) {
float minutesintegral;
auto const minutesfractional { std::modf( Minutes, &minutesintegral ) };
auto const width { Width - 1 };
auto minutes = (
std::string( width - 1, ' ' )
+ ( Leadingzero ?
to_string( 100 + minutesintegral ).substr( 1, 2 ) :
to_string( minutesintegral, 0 ) ) );
return (
minutes.substr( minutes.size() - width, width )
+ fractionlabels[ static_cast<int>( std::floor( minutesfractional * 10 + 0.1 ) ) ] );
}
int stol_def(const std::string &str, const int &DefaultValue) { int stol_def(const std::string &str, const int &DefaultValue) {
int result { DefaultValue }; int result { DefaultValue };

View File

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

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 19 #define VERSION_MAJOR 19
#define VERSION_MINOR 430 #define VERSION_MINOR 522
#define VERSION_REVISION 0 #define VERSION_REVISION 0