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

Merge branch 'tmj-dev' into milek-dev

This commit is contained in:
milek7
2019-04-05 19:26:42 +02:00
21 changed files with 576 additions and 198 deletions

View File

@@ -40,6 +40,7 @@ class powergridsource_table;
class instance_table; class instance_table;
class vehicle_table; class vehicle_table;
struct light_array; struct light_array;
struct dictionary_source;
namespace scene { namespace scene {
struct node_data; struct node_data;

View File

@@ -1373,7 +1373,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if( ( mvOccupied->Vel < v ) if( ( mvOccupied->Vel < v )
|| ( v == 0.0 ) ) { || ( v == 0.0 ) ) {
// if we're going slower than the target velocity and there's enough room for safe stop, speed up // if we're going slower than the target velocity and there's enough room for safe stop, speed up
auto const brakingdistance = fBrakeDist * braking_distance_multiplier( v ); auto const brakingdistance { 1.2 * fBrakeDist * braking_distance_multiplier( v ) };
if( brakingdistance > 0.0 ) { if( brakingdistance > 0.0 ) {
// maintain desired acc while we have enough room to brake safely, when close enough start paying attention // maintain desired acc while we have enough room to brake safely, when close enough start paying attention
// try to make a smooth transition instead of sharp change // try to make a smooth transition instead of sharp change
@@ -1822,8 +1822,7 @@ void TController::Activation()
} }
} }
// Ra: to przełączanie poniżej jest tu bez sensu // Ra: to przełączanie poniżej jest tu bez sensu
mvOccupied->ActiveCab = mvOccupied->ActiveCab = iDirection; // aktywacja kabiny w prowadzonym pojeżdzie (silnikowy może być odwrotnie?)
iDirection; // aktywacja kabiny w prowadzonym pojeżdzie (silnikowy może być odwrotnie?)
// mvOccupied->CabNo=iDirection; // mvOccupied->CabNo=iDirection;
// mvOccupied->ActiveDir=0; //żeby sam ustawił kierunek // mvOccupied->ActiveDir=0; //żeby sam ustawił kierunek
mvOccupied->CabActivisation(); // uruchomienie kabin w członach mvOccupied->CabActivisation(); // uruchomienie kabin w członach
@@ -1963,6 +1962,7 @@ void TController::AutoRewident()
&& ( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) ) { && ( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) ) {
fAccThreshold += 0.10; fAccThreshold += 0.10;
} }
fNominalAccThreshold = fAccThreshold;
} }
if( OrderCurrentGet() & ( Obey_train | Bank ) ) { if( OrderCurrentGet() & ( Obey_train | Bank ) ) {
@@ -2125,6 +2125,11 @@ bool TController::CheckVehicles(TOrders user)
&& ( ( 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
if( p->MoverParameters->HeatingPower > 0 ) {
p->MoverParameters->HeatingAllow = true;
p->MoverParameters->ConverterSwitch( true, range_t::local );
}
} }
if (p->asDestination == "none") if (p->asDestination == "none")
@@ -2354,8 +2359,11 @@ void TController::SetVelocity(double NewVel, double NewVelNext, TStopReason r)
double TController::BrakeAccFactor() const double TController::BrakeAccFactor() const
{ {
double Factor = 1.0; double Factor = 1.0;
if( ( ActualProximityDist > fMinProximityDist )
|| ( mvOccupied->Vel > VelDesired + fVelPlus ) ) { if( ( fAccThreshold != 0.0 )
&& ( AccDesired < 0.0 )
&& ( ( ActualProximityDist > fMinProximityDist )
|| ( mvOccupied->Vel > VelDesired + fVelPlus ) ) ) {
Factor += ( fBrakeReaction * ( /*mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.5 ? 1.5 : 1 ) ) * mvOccupied->Vel / ( std::max( 0.0, ActualProximityDist ) + 1 ) * ( ( AccDesired - AbsAccS_pub ) / fAccThreshold ); Factor += ( fBrakeReaction * ( /*mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.5 ? 1.5 : 1 ) ) * mvOccupied->Vel / ( std::max( 0.0, ActualProximityDist ) + 1 ) * ( ( AccDesired - AbsAccS_pub ) / fAccThreshold );
} }
return Factor; return Factor;
@@ -2520,7 +2528,15 @@ bool TController::PrepareEngine()
// enable train brake if it's off // enable train brake if it's off
if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) { if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) {
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) );
BrakeLevelSet(gbh_RP); // GBH }
// sync virtual brake state with the 'real' one
std::unordered_map<int, int> const brakepositions {
{ static_cast<int>( mvOccupied->Handle->GetPos( bh_RP ) ), gbh_RP },
{ static_cast<int>( mvOccupied->Handle->GetPos( bh_NP ) ), gbh_NP },
{ static_cast<int>( mvOccupied->Handle->GetPos( bh_FS ) ), gbh_FS } };
auto const lookup { brakepositions.find( static_cast<int>( mvOccupied->fBrakeCtrlPos ) ) };
if( lookup != brakepositions.end() ) {
BrakeLevelSet( lookup->second ); // GBH
} }
} }
} }
@@ -2859,7 +2875,7 @@ bool TController::DecBrake()
// mvOccupied->BrakeLevelAdd(-1.0); // mvOccupied->BrakeLevelAdd(-1.0);
/* if (mvOccupied->BrakeCtrlPosR < 0.74) GBH */ /* if (mvOccupied->BrakeCtrlPosR < 0.74) GBH */
if (BrakeCtrlPosition < 0.74) if (BrakeCtrlPosition < 0.74)
/*mvOccupied->*/BrakeLevelSet(0.0); /*mvOccupied->*/BrakeLevelSet(gbh_RP);
} }
} }
if( !OK ) { if( !OK ) {
@@ -3065,7 +3081,7 @@ bool TController::IncSpeed()
if (!mvControlling->FuseFlag) if (!mvControlling->FuseFlag)
if (Ready || (iDrivigFlags & movePress) || (mvOccupied->ShuntMode)) //{(BrakePress<=0.01*MaxBrakePress)} if (Ready || (iDrivigFlags & movePress) || (mvOccupied->ShuntMode)) //{(BrakePress<=0.01*MaxBrakePress)}
{ {
OK = mvControlling->IncMainCtrl(std::max(1,mvOccupied->MainCtrlPosNo/10)); OK = IncSpeedEIM();
// cruise control // cruise control
auto const SpeedCntrlVel { ( auto const SpeedCntrlVel { (
( ActualProximityDist > std::max( 50.0, fMaxProximityDist ) ) ? ( ActualProximityDist > std::max( 50.0, fMaxProximityDist ) ) ?
@@ -3167,6 +3183,34 @@ bool TController::DecSpeed(bool force)
return OK; return OK;
}; };
bool TController::IncSpeedEIM() {
bool OK = false; // domyślnie false, aby wyszło z pętli while
switch( mvControlling->EIMCtrlType ) {
case 0:
OK = mvControlling->IncMainCtrl( std::max( 1, mvOccupied->MainCtrlPosNo / 10 ) );
break;
case 1:
OK = mvControlling->MainCtrlPos < 6;
if( OK )
mvControlling->MainCtrlPos = 6;
/*
// TBD, TODO: set position based on desired acceleration?
OK = mvControlling->MainCtrlPos < mvControlling->MainCtrlPosNo;
if( OK ) {
mvControlling->MainCtrlPos = clamp( mvControlling->MainCtrlPos + 1, 6, mvControlling->MainCtrlPosNo );
}
*/
break;
case 2:
OK = mvControlling->MainCtrlPos < 4;
if( OK )
mvControlling->MainCtrlPos = 4;
break;
}
return OK;
}
bool TController::DecSpeedEIM() bool TController::DecSpeedEIM()
{ // zmniejszenie prędkości (ale nie hamowanie) { // zmniejszenie prędkości (ale nie hamowanie)
bool OK = false; // domyślnie false, aby wyszło z pętli while bool OK = false; // domyślnie false, aby wyszło z pętli while
@@ -3214,59 +3258,59 @@ void TController::SpeedSet()
if (mvControlling->MainCtrlPosNo > 0) if (mvControlling->MainCtrlPosNo > 0)
{ // jeśli ma czym kręcić { // jeśli ma czym kręcić
// TODO: sprawdzanie innego czlonu //if (!FuseFlagCheck()) // TODO: sprawdzanie innego czlonu //if (!FuseFlagCheck())
if ((AccDesired < fAccGravity - 0.05) || if( ( iDrivigFlags & moveIncSpeed ) == 0 ) {
(mvOccupied->Vel > VelDesired)) // jeśli nie ma przyspieszać // przetok rozłączać od razu (no dependency on fActionTime)
mvControlling->DecMainCtrl(2); // na zero while( ( mvControlling->MainCtrlPos )
else if (fActionTime >= 0.0) && ( mvControlling->DecMainCtrl( 1 ) ) ) {
{ // jak już można coś poruszać, przetok rozłączać od razu ; // na zero
if (iDrivigFlags & moveIncSpeed)
{ // jak ma jechać
if (fReady < 0.4) // 0.05*Controlling->MaxBrakePress)
{ // jak jest odhamowany
if (mvOccupied->ActiveDir > 0)
mvOccupied->DirectionForward(); //żeby EN57 jechały na drugiej nastawie
{
if (mvControlling->MainCtrlPos &&
!mvControlling->StLinFlag) // jak niby jedzie, ale ma rozłączone liniowe
mvControlling->DecMainCtrl(2); // to na zero i czekać na przewalenie kułakowego
else
switch (mvControlling->MainCtrlPos)
{ // ruch nastawnika uzależniony jest od aktualnie ustawionej
// pozycji
case 0:
if (mvControlling->MainCtrlActualPos) // jeśli kułakowy nie jest
// wyzerowany
break; // to czekać na wyzerowanie
mvControlling->IncMainCtrl(1); // przetok; bez "break", bo nie
// ma czekania na 1. pozycji
case 1:
if (VelDesired >= 20)
mvControlling->IncMainCtrl(1); // szeregowa
case 2:
if (VelDesired >= 50)
mvControlling->IncMainCtrl(1); // równoległa
case 3:
if (VelDesired >= 80)
mvControlling->IncMainCtrl(1); // bocznik 1
case 4:
if (VelDesired >= 90)
mvControlling->IncMainCtrl(1); // bocznik 2
case 5:
if (VelDesired >= 100)
mvControlling->IncMainCtrl(1); // bocznik 3
} }
if (mvControlling->MainCtrlPos) // jak załączył pozycję if( fActionTime >= 0.0 ) {
{
fActionTime = -5.0; // niech trochę potrzyma fActionTime = -5.0; // niech trochę potrzyma
}
mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania
} }
else {
// jak ma jechać
if( fActionTime < 0.0 ) { break; }
if( fReady > 0.4 ) { break; }
if( mvOccupied->ActiveDir > 0 ) {
mvOccupied->DirectionForward(); //żeby EN57 jechały na drugiej nastawie
}
if( ( mvControlling->MainCtrlPos > 0 )
&& ( false == mvControlling->StLinFlag ) ) {
// jak niby jedzie, ale ma rozłączone liniowe to na zero i czekać na przewalenie kułakowego
mvControlling->DecMainCtrl( 2 );
}
else {
// ruch nastawnika uzależniony jest od aktualnie ustawionej pozycji
switch( mvControlling->MainCtrlPos ) {
case 0:
if( mvControlling->MainCtrlActualPos ) {
// jeśli kułakowy nie jest wyzerowany to czekać na wyzerowanie
break;
}
mvControlling->IncMainCtrl( 1 ); // przetok; bez "break", bo nie ma czekania na 1. pozycji
case 1:
if( VelDesired >= 20 )
mvControlling->IncMainCtrl( 1 ); // szeregowa
case 2:
if( VelDesired >= 50 )
mvControlling->IncMainCtrl( 1 ); // równoległa
case 3:
if( VelDesired >= 80 )
mvControlling->IncMainCtrl( 1 ); // bocznik 1
case 4:
if( VelDesired >= 90 )
mvControlling->IncMainCtrl( 1 ); // bocznik 2
case 5:
if( VelDesired >= 100 )
mvControlling->IncMainCtrl( 1 ); // bocznik 3
} }
} }
} if( mvControlling->MainCtrlPos ) // jak załączył pozycję
else
{ {
while (mvControlling->MainCtrlPos)
mvControlling->DecMainCtrl(1); // na zero
fActionTime = -5.0; // niech trochę potrzyma fActionTime = -5.0; // niech trochę potrzyma
mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania
} }
@@ -3370,7 +3414,7 @@ void TController::SpeedCntrl(double DesiredSpeed)
mvControlling->IncScndCtrl(1); mvControlling->IncScndCtrl(1);
mvControlling->RunCommand("SpeedCntrl", DesiredSpeed, mvControlling->CabNo); mvControlling->RunCommand("SpeedCntrl", DesiredSpeed, mvControlling->CabNo);
} }
else if (mvControlling->ScndCtrlPosNo > 1) else if ((mvControlling->ScndCtrlPosNo > 1) && (!mvOccupied->SpeedCtrlTypeTime))
{ {
int DesiredPos = 1 + mvControlling->ScndCtrlPosNo * ((DesiredSpeed - 1.0) / mvControlling->Vmax); int DesiredPos = 1 + mvControlling->ScndCtrlPosNo * ((DesiredSpeed - 1.0) / mvControlling->Vmax);
while( ( mvControlling->ScndCtrlPos > DesiredPos ) && ( true == mvControlling->DecScndCtrl( 1 ) ) ) { ; } // all work is done in the condition loop while( ( mvControlling->ScndCtrlPos > DesiredPos ) && ( true == mvControlling->DecScndCtrl( 1 ) ) ) { ; } // all work is done in the condition loop
@@ -3412,6 +3456,22 @@ void TController::SetTimeControllers()
if (mvOccupied->LocalBrakePosA > 0.95) mvOccupied->MainCtrlPos = 1; if (mvOccupied->LocalBrakePosA > 0.95) mvOccupied->MainCtrlPos = 1;
} }
} }
//4. Check Speed Control System
if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor && mvOccupied->ScndCtrlPosNo > 1 && mvOccupied->SpeedCtrlTypeTime)
{
double SpeedCntrlVel =
(ActualProximityDist > std::max(50.0, fMaxProximityDist)) ?
VelDesired :
min_speed(VelDesired, VelNext);
SpeedCntrlVel = 10 * std::floor(SpeedCntrlVel*0.1);
if (mvOccupied->ScndCtrlPosNo == 4)
{
if (mvOccupied->NewSpeed + 0.1 < SpeedCntrlVel)
mvOccupied->ScndCtrlPos = 3;
if (mvOccupied->NewSpeed - 0.1 > SpeedCntrlVel)
mvOccupied->ScndCtrlPos = 1;
}
}
}; };
void TController::CheckTimeControllers() void TController::CheckTimeControllers()
@@ -3444,6 +3504,14 @@ void TController::CheckTimeControllers()
if (mvOccupied->eimic < 0) mvOccupied->MainCtrlPos = 2; if (mvOccupied->eimic < 0) mvOccupied->MainCtrlPos = 2;
} }
} }
//4. Check Speed Control System
if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor && mvOccupied->ScndCtrlPosNo>1 && mvOccupied->SpeedCtrlTypeTime)
{
if (mvOccupied->ScndCtrlPosNo == 4)
{
mvOccupied->ScndCtrlPos = 2;
}
}
}; };
// otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT // otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT
@@ -3487,7 +3555,7 @@ void TController::Doors( bool const Open, int const Side ) {
} }
if( AIControllFlag ) { if( AIControllFlag ) {
if( ( true == mvOccupied->Doors.has_autowarning ) if( ( true == mvOccupied->Doors.has_warning )
&& ( false == mvOccupied->DepartureSignal ) && ( false == mvOccupied->DepartureSignal )
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) { && ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
mvOccupied->signal_departure( true ); // załącenie bzyczka mvOccupied->signal_departure( true ); // załącenie bzyczka
@@ -3846,15 +3914,14 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
if( ( NewCommand == "Shunt" ) || ( NewCommand == "Loose_shunt" ) ) if( ( NewCommand == "Shunt" ) || ( NewCommand == "Loose_shunt" ) )
{ // NewValue1 - ilość wagonów (-1=wszystkie); NewValue2: 0=odczep, 1..63=dołącz, -1=bez zmian { // NewValue1 - ilość wagonów (-1=wszystkie); NewValue2: 0=odczep, 1..63=dołącz, -1=bez zmian
//-3,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać w //-3,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać w trybie pociągowym
// trybie pociągowym
//-2,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać //-2,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać
//-2, y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i czekać //-2, y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i czekać
//-1,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i jechać w powrotną stronę //-1,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i jechać w powrotną stronę
//-1, y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i jechać dalej //-1, y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i jechać dalej
//-1, 0 - tryb manewrowy bez zmian (odczepianie z pozostawieniem wagonów nie ma sensu) //-1, 0 - tryb manewrowy bez zmian (odczepianie z pozostawieniem wagonów nie ma sensu)
// 0, 0 - odczepienie lokomotywy // 0, 0 - odczepienie lokomotywy
// 1,-y - podłączyć się do składu (sprzęgiem y>=1), a następnie odczepić i zabrać (x) wagonów // x,-y - podłączyć się do składu (sprzęgiem y>=1), a następnie odczepić i zabrać (x) wagonów
// 1, 0 - odczepienie lokomotywy z jednym wagonem // 1, 0 - odczepienie lokomotywy z jednym wagonem
iDrivigFlags &= ~moveStopHere; // podjeżanie do semaforów zezwolone iDrivigFlags &= ~moveStopHere; // podjeżanie do semaforów zezwolone
if (!iEngineActive) if (!iEngineActive)
@@ -4141,7 +4208,7 @@ TController::UpdateSituation(double dt) {
Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego
} }
// check door state // check door state
auto const switchsides { p->DirectionGet() <= 0 }; auto const switchsides { p->DirectionGet() != iDirection };
IsAnyDoorOpen[ side::right ] = IsAnyDoorOpen[ side::right ] =
IsAnyDoorOpen[ side::right ] IsAnyDoorOpen[ side::right ]
|| ( false == vehicle->Doors.instances[ ( switchsides ? side::left : side::right ) ].is_closed ); || ( false == vehicle->Doors.instances[ ( switchsides ? side::left : side::right ) ].is_closed );
@@ -4563,6 +4630,7 @@ TController::UpdateSituation(double dt) {
auto *vehicleparameters { vehicle->MoverParameters }; auto *vehicleparameters { vehicle->MoverParameters };
int const end { ( vehicle->DirectionGet() > 0 ? end::front : end::rear ) }; int const end { ( vehicle->DirectionGet() > 0 ? end::front : end::rear ) };
auto const &neighbour { vehicleparameters->Neighbours[ end ] }; auto const &neighbour { vehicleparameters->Neighbours[ end ] };
if( neighbour.vehicle != nullptr ) {
// próba podczepienia // próba podczepienia
vehicleparameters->Attach( vehicleparameters->Attach(
end, neighbour.vehicle_end, end, neighbour.vehicle_end,
@@ -4572,11 +4640,11 @@ TController::UpdateSituation(double dt) {
// jeżeli został podłączony // jeżeli został podłączony
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
CheckVehicles(); // sprawdzić światła nowego składu CheckVehicles(); // sprawdzić światła nowego składu
JumpToNextOrder(); // wykonanie następnej komendy JumpToNextOrder(); // wykonanie następnej komendy
} }
}
} // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna } // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna
} }
else { else {
@@ -4606,11 +4674,11 @@ TController::UpdateSituation(double dt) {
// TODO: test if we can use the distances calculation from obey_train // TODO: test if we can use the distances calculation from obey_train
fMinProximityDist = std::min( 5 + iVehicles, 25 ); fMinProximityDist = std::min( 5 + iVehicles, 25 );
fMaxProximityDist = std::min( 10 + iVehicles, 50 ); fMaxProximityDist = std::min( 10 + iVehicles, 50 );
/* // HACK: modern vehicles might brake slower at low speeds, increase safety margin as crude counter
if( IsHeavyCargoTrain ) { if( mvControlling->EIMCtrlType > 0 ) {
fMaxProximityDist *= 1.5; fMinProximityDist += 5.0;
fMaxProximityDist += 5.0;
} }
*/
fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
// margines prędkości powodujący załączenie napędu // margines prędkości powodujący załączenie napędu
// były problemy z jazdą np. 3km/h podczas ładowania wagonów // były problemy z jazdą np. 3km/h podczas ładowania wagonów
@@ -5090,7 +5158,11 @@ TController::UpdateSituation(double dt) {
20.0 ) ); // others 20.0 ) ); // others
if( vel > VelDesired + fVelPlus ) { if( vel > VelDesired + fVelPlus ) {
// if going too fast force some prompt braking // if going too fast force some prompt braking
AccPreferred = std::min( -0.65, AccPreferred ); AccPreferred = std::min(
( ( mvOccupied->CategoryFlag & 2 ) ?
-0.65 : // cars
-0.30 ), // others
AccPreferred );
} }
} }
@@ -5602,11 +5674,11 @@ TController::UpdateSituation(double dt) {
|| ( VelNext > vel - 40.0 ) ) ? || ( VelNext > vel - 40.0 ) ) ?
fBrake_a0[ 0 ] * 0.8 : fBrake_a0[ 0 ] * 0.8 :
-fAccThreshold ) -fAccThreshold )
/ braking_distance_multiplier( VelNext ) ) { / ( 1.2 * braking_distance_multiplier( VelNext ) ) ) {
AccDesired = std::max( -0.06, AccDesired ); AccDesired = std::max( -0.06, AccDesired );
} }
} }
else { if( AccDesired < -0.1 ) {
// i orientuj się szybciej, jeśli hamujesz // i orientuj się szybciej, jeśli hamujesz
ReactionTime = 0.25; ReactionTime = 0.25;
} }
@@ -5705,11 +5777,11 @@ TController::UpdateSituation(double dt) {
} }
} }
} }
// yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej // yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej zwiekszanie predkosci
// zwiekszanie predkosci
// Ra 2F1H: jest konflikt histerezy pomiędzy nastawioną pozycją a uzyskiwanym // Ra 2F1H: jest konflikt histerezy pomiędzy nastawioną pozycją a uzyskiwanym
// przyspieszeniem - utrzymanie pozycji powoduje przekroczenie przyspieszenia // przyspieszeniem - utrzymanie pozycji powoduje przekroczenie przyspieszenia
if( ( AccDesired - AbsAccS > 0.01 ) ) { if( ( AccDesired > -0.06 ) // don't add power if not asked for actual speed-up
&& ( AccDesired - AbsAccS > 0.05 ) ) {
// jeśli przyspieszenie pojazdu jest mniejsze niż żądane oraz... // jeśli przyspieszenie pojazdu jest mniejsze niż żądane oraz...
if( vel < ( if( vel < (
VelDesired == 1.0 ? // work around for trains getting stuck on tracks with speed limit = 1 VelDesired == 1.0 ? // work around for trains getting stuck on tracks with speed limit = 1
@@ -5762,6 +5834,7 @@ TController::UpdateSituation(double dt) {
// przy odłączaniu nie zwalniamy tu hamulca // przy odłączaniu nie zwalniamy tu hamulca
if( AbsAccS < AccDesired - 0.05 ) { if( AbsAccS < AccDesired - 0.05 ) {
// jeśli opóźnienie większe od wymaganego (z histerezą) luzowanie, gdy za dużo // jeśli opóźnienie większe od wymaganego (z histerezą) luzowanie, gdy za dużo
// TBD: check if the condition isn't redundant with the DecBrake() code
if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition >= 0 ) { if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition >= 0 ) {
DecBrake(); // tutaj zmniejszało o 1 przy odczepianiu DecBrake(); // tutaj zmniejszało o 1 przy odczepianiu
} }
@@ -5800,7 +5873,8 @@ TController::UpdateSituation(double dt) {
} }
} }
} }
if ((AccDesired < fAccGravity - 0.05) && (AbsAccS < AccDesired - fBrake_a1[0]*0.51)) { if ( ( AccDesired < fAccGravity - 0.05 )
&& ( ( AccDesired - fBrake_a1[0]*0.51 ) ) - AbsAccS > 0.05 ) {
// jak hamuje, to nie tykaj kranu za często // jak hamuje, to nie tykaj kranu za często
// yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2 // yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2
if( OrderCurrentGet() != Disconnect ) { if( OrderCurrentGet() != Disconnect ) {
@@ -6526,6 +6600,9 @@ void TController::TakeControl(bool yes)
void TController::DirectionForward(bool forward) void TController::DirectionForward(bool forward)
{ // ustawienie jazdy do przodu dla true i do tyłu dla false (zależy od kabiny) { // ustawienie jazdy do przodu dla true i do tyłu dla false (zależy od kabiny)
ZeroSpeed( true ); // TODO: check if force switch is needed anymore here ZeroSpeed( true ); // TODO: check if force switch is needed anymore here
// HACK: make sure the master controller isn't set in position which prevents direction change
mvControlling->MainCtrlPos = std::min( mvControlling->MainCtrlPos, mvControlling->MaxMainCtrlPosNoDirChange );
if( forward ) { if( forward ) {
// do przodu w obecnej kabinie // do przodu w obecnej kabinie
while( ( mvOccupied->ActiveDir <= 0 ) while( ( mvOccupied->ActiveDir <= 0 )

View File

@@ -407,9 +407,9 @@ private:
// methods // methods
public: public:
std::string TrainName() const; std::string TrainName() const;
Mtable::TTrainParameters const * TrainTimetable() const;
private: private:
std::string Relation() const; std::string Relation() const;
Mtable::TTrainParameters const * TrainTimetable() const;
int StationIndex() const; int StationIndex() const;
int StationCount() const; int StationCount() const;
bool IsStop() const; bool IsStop() const;

View File

@@ -162,6 +162,39 @@ void TAnim::Parovoz(){
// animowanie tłoka i rozrządu parowozu // animowanie tłoka i rozrządu parowozu
}; };
*/ */
void TDynamicObject::destination_data::deserialize( cParser &Input ) {
while( true == deserialize_mapping( Input ) ) {
; // all work done by while()
}
}
bool TDynamicObject::destination_data::deserialize_mapping( cParser &Input ) {
// token can be a key or block end
auto const key { Input.getToken<std::string>( true, "\n\r\t ,;[]" ) };
if( ( true == key.empty() ) || ( key == "}" ) ) { return false; }
if( key == "{" ) {
script = Input.getToken<std::string>();
}
else if( key == "update:" ) {
auto const value { Input.getToken<std::string>() };
// TODO: implement
}
else if( key == "instance:" ) {
instancing = Input.getToken<std::string>();
}
else if( key == "parameters:" ) {
parameters = Input.getToken<std::string>();
}
return true;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
TDynamicObject * TDynamicObject::FirstFind(int &coupler_nr, int cf) TDynamicObject * TDynamicObject::FirstFind(int &coupler_nr, int cf)
{ // szukanie skrajnego połączonego pojazdu w pociagu { // szukanie skrajnego połączonego pojazdu w pociagu
@@ -921,6 +954,8 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
btEndSignalsTab2.Turn( true ); btEndSignalsTab2.Turn( true );
btnOn = true; btnOn = true;
} }
// destination signs
update_destinations();
// else btEndSignalsTab2.TurnOff(); // else btEndSignalsTab2.TurnOff();
// McZapkie-181002: krecenie wahaczem (korzysta z kata obrotu silnika) // McZapkie-181002: krecenie wahaczem (korzysta z kata obrotu silnika)
if (iAnimType[ANIM_LEVERS]) if (iAnimType[ANIM_LEVERS])
@@ -1947,6 +1982,10 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
init_sections( mdLowPolyInt, nameprefix ); init_sections( mdLowPolyInt, nameprefix );
} }
} }
// destination sign
if( mdModel ) {
init_destination( mdModel );
}
// 'external_load' is an optional special section in the main model, pointing to submodel of external load // 'external_load' is an optional special section in the main model, pointing to submodel of external load
if( mdModel ) { if( mdModel ) {
init_sections( mdModel, "external_load" ); init_sections( mdModel, "external_load" );
@@ -2070,6 +2109,16 @@ TDynamicObject::init_sections( TModel3d const *Model, std::string const &Namepre
return sectioncount; return sectioncount;
} }
bool
TDynamicObject::init_destination( TModel3d *Model ) {
if( Model->GetSMRoot() == nullptr ) { return false; }
std::tie( DestinationSign.sign, DestinationSign.has_light ) = Model->GetSMRoot()->find_replacable4();
return DestinationSign.sign != nullptr;
}
void void
TDynamicObject::create_controller( std::string const Type, bool const Trainset ) { TDynamicObject::create_controller( std::string const Type, bool const Trainset ) {
@@ -2554,6 +2603,27 @@ na sprzęgach, opóźnienie działania hamulca itp. Oczywiście musi mieć to pe
histerezę czasową, aby te tryby pracy nie przełączały się zbyt szybko. histerezę czasową, aby te tryby pracy nie przełączały się zbyt szybko.
*/ */
void TDynamicObject::update_destinations() {
if( DestinationSign.sign == nullptr ) { return; }
DestinationSign.sign->fLight = (
( ( DestinationSign.has_light ) && ( MoverParameters->Battery ) ) ?
2.0 :
-1.0 );
// jak są 4 tekstury wymienne, to nie zmieniać rozkładem
if( std::abs( m_materialdata.multi_textures ) >= 4 ) { return; }
// TODO: dedicated setting to discern electronic signs, instead of fallback on light presence
m_materialdata.replacable_skins[ 4 ] = (
( ( DestinationSign.destination != null_handle )
&& ( ( false == DestinationSign.has_light ) // physical destination signs remain up until manually changed
|| ( ( true == MoverParameters->Battery ) // lcd signs are off without power
&& ( ctOwner != nullptr ) ) ) ) ? // lcd signs are off for carriages without engine, potentially left on a siding
DestinationSign.destination :
DestinationSign.destination_off );
}
bool TDynamicObject::Update(double dt, double dt1) bool TDynamicObject::Update(double dt, double dt1)
{ {
if (dt1 == 0) if (dt1 == 0)
@@ -2714,6 +2784,7 @@ bool TDynamicObject::Update(double dt, double dt1)
MoverParameters->eimic_real = eimic; MoverParameters->eimic_real = eimic;
MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo); MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo);
auto LBR = Max0R(-eimic, 0); auto LBR = Max0R(-eimic, 0);
auto eim_lb = (Mechanik->AIControllFlag || !MoverParameters->LocHandleTimeTraxx ? 0 : MoverParameters->eim_localbrake);
// 1. ustal wymagana sile hamowania calego pociagu // 1. ustal wymagana sile hamowania calego pociagu
// - opoznienie moze byc ustalane na podstawie charakterystyki // - opoznienie moze byc ustalane na podstawie charakterystyki
@@ -2944,6 +3015,11 @@ bool TDynamicObject::Update(double dt, double dt1)
p->MoverParameters->LocalBrakePosAEIM = p->MoverParameters->LocalBrakePosAEIM; p->MoverParameters->LocalBrakePosAEIM = p->MoverParameters->LocalBrakePosAEIM;
else else
p->MoverParameters->LocalBrakePosAEIM = 0; p->MoverParameters->LocalBrakePosAEIM = 0;
if (p->MoverParameters->LocHandleTimeTraxx)
{
p->MoverParameters->eim_localbrake = eim_lb;
p->MoverParameters->LocalBrakePosAEIM = std::max(p->MoverParameters->LocalBrakePosAEIM, eim_lb);
}
++i; ++i;
} }
@@ -4012,6 +4088,10 @@ void TDynamicObject::RenderSounds() {
} }
if( volume > 0.05 ) { if( volume > 0.05 ) {
rscurve rscurve
.pitch(
true == rscurve.is_combined() ?
MoverParameters->Vel * 0.01f :
rscurve.m_frequencyoffset + rscurve.m_frequencyfactor * 1.f )
.gain( 2.5 * volume ) .gain( 2.5 * volume )
.play( sound_flags::exclusive | sound_flags::looping ); .play( sound_flags::exclusive | sound_flags::looping );
} }
@@ -4237,7 +4317,8 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
} }
// potentially set blank destination texture // potentially set blank destination texture
DestinationSet( {}, {} ); DestinationSign.destination_off = DestinationFind( "nowhere" );
// DestinationSet( {}, {} );
if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) { if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) {
// tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych // tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
@@ -5534,6 +5615,15 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
parser >> JointCabs; parser >> JointCabs;
} }
else if( token == "pydestinationsign:" ) {
DestinationSign.deserialize( parser );
// supply vehicle folder as script path if none is provided
if( ( false == DestinationSign.script.empty() )
&& ( substr_path( DestinationSign.script ).empty() ) ) {
DestinationSign.script = asBaseDir + DestinationSign.script;
}
}
} while( token != "" ); } while( token != "" );
} // internaldata: } // internaldata:
@@ -6091,45 +6181,92 @@ int TDynamicObject::RouteWish(TTrack *tr)
return Mechanik ? Mechanik->CrossRoute(tr) : 0; // wg AI albo prosto return Mechanik ? Mechanik->CrossRoute(tr) : 0; // wg AI albo prosto
}; };
void TDynamicObject::DestinationSet(std::string to, std::string numer) void TDynamicObject::DestinationSet(std::string to, std::string numer) {
{ // ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik // ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik
// w zasadzie, to każdy wagon mógłby mieć inną stację docelową // w zasadzie, to każdy wagon mógłby mieć inną stację docelową
// zwłaszcza w towarowych, pod kątem zautomatyzowania maewrów albo pracy górki // zwłaszcza w towarowych, pod kątem zautomatyzowania maewrów albo pracy górki
// ale to jeszcze potrwa, zanim będzie możliwe, na razie można wpisać stację z // ale to jeszcze potrwa, zanim będzie możliwe, na razie można wpisać stację z
// rozkładu // rozkładu
if( std::abs( m_materialdata.multi_textures ) >= 4 ) {
// jak są 4 tekstury wymienne, to nie zmieniać rozkładem asDestination = to;
if( std::abs( m_materialdata.multi_textures ) >= 4 ) { return; } // jak są 4 tekstury wymienne, to nie zmieniać rozkładem
if( DestinationSign.sign == nullptr ) { return; } // no sign submodel, no problem
// now see if we can find any version of the destination texture
std::vector<std::string> const destinations = {
numer, // try dedicated timetable sign first...
to }; // ...then generic destination sign
for( auto const &destination : destinations ) {
DestinationSign.destination = DestinationFind( destination );
if( DestinationSign.destination != null_handle ) {
// got what we wanted, we're done here
return; return;
} }
numer = Bezogonkow(numer);
asDestination = to;
to = Bezogonkow(to); // do szukania pliku obcinamy ogonki
if( true == to.empty() ) {
to = "nowhere";
} }
// if we didn't get static texture we might be able to make one
if( DestinationSign.script.empty() ) { return; } // no script so no way to make the texture
if( numer == "none" ) { return; } // blank or incomplete/malformed timetable, don't bother
std::string signrequest {
"make:"
+ DestinationSign.script + "?"
// timetable include
+ "$timetable=" + (
ctOwner == nullptr ?
MoverParameters->Name : // leading vehicle, can point to it directly
ctOwner->Vehicle()->MoverParameters->Name ) + "&" // owned vehicle, safer to point to owner as carriages can have identical names
// basic instancing string
// NOTE: underscore doesn't have any magic meaning for the time being, it's just less likely to conflict with regular dictionary keys
+ "_id1=" + (
ctOwner != nullptr ? ctOwner->TrainName() :
Mechanik != nullptr ? Mechanik->TrainName() :
"none" ) }; // shouldn't get here but, eh
// TBD, TODO: replace instancing with support for variables in extra parameters string?
if( false == DestinationSign.instancing.empty() ) {
signrequest +=
"&_id2=" + (
DestinationSign.instancing == "name" ? MoverParameters->Name :
DestinationSign.instancing == "type" ? MoverParameters->TypeName :
"none" );
}
// optionl extra parameters
if( false == DestinationSign.parameters.empty() ) {
signrequest += "&" + DestinationSign.parameters;
}
DestinationSign.destination = GfxRenderer.Fetch_Material( signrequest );
}
material_handle TDynamicObject::DestinationFind( std::string Destination ) {
if( Destination.empty() ) { return null_handle; }
Destination = Bezogonkow( Destination ); // do szukania pliku obcinamy ogonki
// destination textures are kept in the vehicle's directory so we point the current texture path there // destination textures are kept in the vehicle's directory so we point the current texture path there
auto const currenttexturepath { Global.asCurrentTexturePath }; auto const currenttexturepath { Global.asCurrentTexturePath };
Global.asCurrentTexturePath = asBaseDir; Global.asCurrentTexturePath = asBaseDir;
// now see if we can find any version of the texture // now see if we can find any version of the texture
std::vector<std::string> destinations = { std::vector<std::string> const destinations {
numer + '@' + MoverParameters->TypeName, Destination + '@' + MoverParameters->TypeName,
numer, Destination };
to + '@' + MoverParameters->TypeName,
to, auto destinationhandle { null_handle };
"nowhere" + '@' + MoverParameters->TypeName,
"nowhere" };
for( auto const &destination : destinations ) { for( auto const &destination : destinations ) {
auto material = TextureTest( ToLower( destination ) ); auto material = TextureTest( ToLower( destination ) );
if( false == material.empty() ) { if( false == material.empty() ) {
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Material( material ); destinationhandle = GfxRenderer.Fetch_Material( material );
break; break;
} }
} }
// whether we got anything, restore previous texture path // whether we got anything, restore previous texture path
Global.asCurrentTexturePath = currenttexturepath; Global.asCurrentTexturePath = currenttexturepath;
};
return destinationhandle;
}
void TDynamicObject::OverheadTrack(float o) void TDynamicObject::OverheadTrack(float o)
{ // ewentualne wymuszanie jazdy { // ewentualne wymuszanie jazdy
@@ -6814,6 +6951,9 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) {
if( pantograph->hvPowerWire != nullptr ) { if( pantograph->hvPowerWire != nullptr ) {
// jeżeli znamy drut z poprzedniego przebiegu // jeżeli znamy drut z poprzedniego przebiegu
for( int attempts = 0; attempts < 30; ++attempts ) { for( int attempts = 0; attempts < 30; ++attempts ) {
// sanity check. shouldn't happen in theory, but did happen in practice
if( pantograph->hvPowerWire == nullptr ) { break; }
// powtarzane aż do znalezienia odpowiedniego odcinka na liście dwukierunkowej // powtarzane aż do znalezienia odpowiedniego odcinka na liście dwukierunkowej
if( pantograph->hvPowerWire->iLast & 0x3 ) { if( pantograph->hvPowerWire->iLast & 0x3 ) {
// dla ostatniego i przedostatniego przęsła wymuszamy szukanie innego // dla ostatniego i przedostatniego przęsła wymuszamy szukanie innego
@@ -6829,6 +6969,7 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) {
} }
// obliczamy wyraz wolny równania płaszczyzny (to miejsce nie jest odpowienie) // obliczamy wyraz wolny równania płaszczyzny (to miejsce nie jest odpowienie)
// podstawiamy równanie parametryczne drutu do równania płaszczyzny pantografu // podstawiamy równanie parametryczne drutu do równania płaszczyzny pantografu
// TODO: investigate this routine with reardriver/negative speed, does it picks the right wire?
auto const fRaParam = auto const fRaParam =
-( glm::dot( pantograph->hvPowerWire->pPoint1, vFront ) - glm::dot( pant0, vFront ) ) -( glm::dot( pantograph->hvPowerWire->pPoint1, vFront ) - glm::dot( pant0, vFront ) )
/ glm::dot( pantograph->hvPowerWire->vParametric, vFront ); / glm::dot( pantograph->hvPowerWire->vParametric, vFront );

View File

@@ -201,6 +201,20 @@ public:
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
std::array<TSubModel *, 3> LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs std::array<TSubModel *, 3> LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs
bool JointCabs{ false }; // flag for vehicles with multiple virtual 'cabs' sharing location and 3d model(s) bool JointCabs{ false }; // flag for vehicles with multiple virtual 'cabs' sharing location and 3d model(s)
struct destination_data {
TSubModel *sign { nullptr }; // submodel mapped with replacable texture -4
bool has_light { false }; // the submodel was originally configured with self-illumination attribute
material_handle destination { null_handle }; // most recently assigned non-blank destination texture
material_handle destination_off { null_handle }; // blank destination sign
std::string script; // potential python script used to generate texture data
int update_rate { 0 }; // -1: per stop, 0: none, >0: fps // TBD, TODO: implement?
std::string instancing; // potential method to generate more than one texture per timetable
std::string parameters; // potential extra parameters supplied by mmd file
// methods
void deserialize( cParser &Input );
private:
bool deserialize_mapping( cParser &Input );
} DestinationSign;
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?) float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
float LoadOffset { 0.f }; float LoadOffset { 0.f };
std::unordered_map<std::string, std::string> LoadModelOverrides; // potential overrides of default load visualization models std::unordered_map<std::string, std::string> LoadModelOverrides; // potential overrides of default load visualization models
@@ -518,6 +532,7 @@ private:
TTrack *Track, double fDist, std::string DriverType, double fVel, std::string TrainName, TTrack *Track, double fDist, std::string DriverType, double fVel, std::string TrainName,
float Load, std::string LoadType, bool Reversed, std::string); float Load, std::string LoadType, bool Reversed, std::string);
int init_sections( TModel3d const *Model, std::string const &Nameprefix ); int init_sections( TModel3d const *Model, std::string const &Nameprefix );
bool init_destination( TModel3d *Model );
void create_controller( std::string const Type, bool const Trainset ); void create_controller( std::string const Type, bool const Trainset );
void AttachPrev(TDynamicObject *Object, int iType = 1); void AttachPrev(TDynamicObject *Object, int iType = 1);
bool UpdateForce(double dt); bool UpdateForce(double dt);
@@ -532,6 +547,7 @@ private:
void update_load_visibility(); void update_load_visibility();
void update_load_offset(); void update_load_offset();
void shuffle_load_sections(); void shuffle_load_sections();
void update_destinations();
bool Update(double dt, double dt1); bool Update(double dt, double dt1);
bool FastUpdate(double dt); bool FastUpdate(double dt);
void Move(double fDistance); void Move(double fDistance);
@@ -634,6 +650,7 @@ private:
// zapytanie do AI, po którym segmencie skrzyżowania jechać // zapytanie do AI, po którym segmencie skrzyżowania jechać
int RouteWish(TTrack *tr); int RouteWish(TTrack *tr);
void DestinationSet(std::string to, std::string numer); void DestinationSet(std::string to, std::string numer);
material_handle DestinationFind( std::string Destination );
void OverheadTrack(float o); void OverheadTrack(float o);
double MED[9][8]; // lista zmiennych do debugowania hamulca ED double MED[9][8]; // lista zmiennych do debugowania hamulca ED

View File

@@ -892,6 +892,7 @@ public:
TBrakeValve BrakeValve = TBrakeValve::NoValve; TBrakeValve BrakeValve = TBrakeValve::NoValve;
TBrakeHandle BrakeHandle = TBrakeHandle::NoHandle; TBrakeHandle BrakeHandle = TBrakeHandle::NoHandle;
TBrakeHandle BrakeLocHandle = TBrakeHandle::NoHandle; TBrakeHandle BrakeLocHandle = TBrakeHandle::NoHandle;
bool LocHandleTimeTraxx = false; /*hamulec dodatkowy typu traxx*/
double MBPM = 1.0; /*masa najwiekszego cisnienia*/ double MBPM = 1.0; /*masa najwiekszego cisnienia*/
std::shared_ptr<TBrake> Hamulec; std::shared_ptr<TBrake> Hamulec;
@@ -1131,6 +1132,7 @@ public:
double AccN = 0.0; // przyspieszenie normalne w [m/s^2] double AccN = 0.0; // przyspieszenie normalne w [m/s^2]
double AccVert = 0.0; // vertical acceleration double AccVert = 0.0; // vertical acceleration
double nrot = 0.0; double nrot = 0.0;
double nrot_eps = 0.0; //przyspieszenie kątowe kół (bez kierunku)
double WheelFlat = 0.0; double WheelFlat = 0.0;
bool TruckHunting { true }; // enable/disable truck hunting calculation bool TruckHunting { true }; // enable/disable truck hunting calculation
/*! rotacja kol [obr/s]*/ /*! rotacja kol [obr/s]*/
@@ -1306,6 +1308,7 @@ public:
/*- zmienne dla lokomotyw z silnikami indukcyjnymi -*/ /*- zmienne dla lokomotyw z silnikami indukcyjnymi -*/
double eimic = 0; /*aktualna pozycja zintegrowanego sterowania jazda i hamowaniem*/ double eimic = 0; /*aktualna pozycja zintegrowanego sterowania jazda i hamowaniem*/
double eimic_real = 0; /*faktycznie uzywana pozycja zintegrowanego sterowania jazda i hamowaniem*/ double eimic_real = 0; /*faktycznie uzywana pozycja zintegrowanego sterowania jazda i hamowaniem*/
double eim_localbrake = 0; /*nastawa hamowania dodatkowego pneumatycznego lokomotywy*/
int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/ int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/
bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/ bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/
double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/ double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/
@@ -1352,6 +1355,7 @@ public:
std::string StLinSwitchType; std::string StLinSwitchType;
bool Heating = false; //ogrzewanie 'Winger 020304 bool Heating = false; //ogrzewanie 'Winger 020304
bool HeatingAllow { false }; // heating switch // TODO: wrap heating in a basic device
int DoubleTr = 1; //trakcja ukrotniona - przedni pojazd 'Winger 160304 int DoubleTr = 1; //trakcja ukrotniona - przedni pojazd 'Winger 160304
bool PhysicActivation = true; bool PhysicActivation = true;
@@ -1498,6 +1502,7 @@ public:
/*-funkcje typowe dla lokomotywy elektrycznej*/ /*-funkcje typowe dla lokomotywy elektrycznej*/
void ConverterCheck( double const Timestep ); // przetwornica void ConverterCheck( double const Timestep ); // przetwornica
void HeatingCheck( double const Timestep );
void WaterPumpCheck( double const Timestep ); void WaterPumpCheck( double const Timestep );
void WaterHeaterCheck( double const Timestep ); void WaterHeaterCheck( double const Timestep );
void FuelPumpCheck( double const Timestep ); void FuelPumpCheck( double const Timestep );

View File

@@ -502,7 +502,7 @@ bool TMoverParameters::Dettach(int ConnectNo)
bool TMoverParameters::DirectionForward() bool TMoverParameters::DirectionForward()
{ {
if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (MainCtrlPos <= MaxMainCtrlPosNoDirChange) && (EIMDirectionChangeAllow())) if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (EIMDirectionChangeAllow()))
{ {
++ActiveDir; ++ActiveDir;
DirAbsolute = ActiveDir * CabNo; DirAbsolute = ActiveDir * CabNo;
@@ -1075,11 +1075,13 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
for( int side = 0; side < 2; ++side ) { for( int side = 0; side < 2; ++side ) {
// przekazywanie napiec // przekazywanie napiec
auto const oppositeside = ( side == end::front ? end::rear : end::front ); auto const oppositeside { ( side == end::front ? end::rear : end::front ) };
auto const liveconnection{
( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
&& ( Couplers[ side ].Connected->Heating ) ) };
if( ( Couplers[ side ].CouplingFlag & ctrain_power ) if( liveconnection ) {
|| ( ( Heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ]; auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ];
Couplers[ oppositeside ].power_high.voltage = Couplers[ oppositeside ].power_high.voltage =
std::max( std::max(
@@ -1103,8 +1105,8 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
Couplers[ side ].power_high.local = false; // power, if any, will be from external source Couplers[ side ].power_high.local = false; // power, if any, will be from external source
if( ( Couplers[ side ].CouplingFlag & ctrain_power ) if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Heating ) || ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { && ( Couplers[ side ].Connected->Heating ) ) ) {
auto const &connectedcoupler = auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[ Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == end::front ? ( Couplers[ side ].ConnectedNr == end::front ?
@@ -1127,8 +1129,8 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
Couplers[ side ].power_high.local = true; // power is coming from local pantographs Couplers[ side ].power_high.local = true; // power is coming from local pantographs
if( ( Couplers[ side ].CouplingFlag & ctrain_power ) if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Heating ) || ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { && ( Couplers[ side ].Connected->Heating ) ) ) {
auto const &connectedcoupler = auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[ Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == end::front ? ( Couplers[ side ].ConnectedNr == end::front ?
@@ -1409,6 +1411,8 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
// w rozrządczym nie (jest błąd w FIZ!) - Ra 2014-07: teraz we wszystkich // w rozrządczym nie (jest błąd w FIZ!) - Ra 2014-07: teraz we wszystkich
UpdatePantVolume( Deltatime ); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów UpdatePantVolume( Deltatime ); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów
} }
// heating
HeatingCheck( Deltatime );
UpdateBrakePressure(Deltatime); UpdateBrakePressure(Deltatime);
UpdatePipePressure(Deltatime); UpdatePipePressure(Deltatime);
@@ -1462,7 +1466,8 @@ void TMoverParameters::ConverterCheck( double const Timestep ) {
if( ( ConverterAllow ) if( ( ConverterAllow )
&& ( ConverterAllowLocal ) && ( ConverterAllowLocal )
&& ( false == PantPressLockActive ) && ( false == PantPressLockActive )
&& ( Mains ) ) { && ( ( Mains )
|| ( GetTrainsetVoltage() > 0 ) ) ) {
// delay timer can be optionally configured, and is set anew whenever converter goes off // delay timer can be optionally configured, and is set anew whenever converter goes off
if( ConverterStartDelayTimer <= 0.0 ) { if( ConverterStartDelayTimer <= 0.0 ) {
ConverterFlag = true; ConverterFlag = true;
@@ -1477,6 +1482,17 @@ void TMoverParameters::ConverterCheck( double const Timestep ) {
} }
}; };
// heating system status check
void TMoverParameters::HeatingCheck( double const Timestep ) {
Heating = (
( true == HeatingAllow )
// powered vehicles are generally required to activate their power source to provide heating
// passive vehicles get a pass in this regard
&& ( ( Power < 0.1 )
|| ( true == Mains ) ) );
}
// water pump status check // water pump status check
void TMoverParameters::WaterPumpCheck( double const Timestep ) { void TMoverParameters::WaterPumpCheck( double const Timestep ) {
// NOTE: breaker override with start type is sm42 specific hack, replace with ability to define the presence of the breaker // NOTE: breaker override with start type is sm42 specific hack, replace with ability to define the presence of the breaker
@@ -2355,7 +2371,7 @@ bool TMoverParameters::DirectionBackward(void)
DB = true; // DB = true; //
return DB; // exit; TODO: czy dobrze przetlumaczone? return DB; // exit; TODO: czy dobrze przetlumaczone?
} }
if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (MainCtrlPos <= MaxMainCtrlPosNoDirChange) && (EIMDirectionChangeAllow())) if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (EIMDirectionChangeAllow()))
{ {
if (EngineType == TEngineType::WheelsDriven) if (EngineType == TEngineType::WheelsDriven)
CabNo--; CabNo--;
@@ -2376,7 +2392,11 @@ bool TMoverParameters::DirectionBackward(void)
bool TMoverParameters::EIMDirectionChangeAllow(void) bool TMoverParameters::EIMDirectionChangeAllow(void)
{ {
bool OK = false; bool OK = false;
/*
// NOTE: disabled while eimic variables aren't immediately synced with master controller changes inside ai module
OK = (EngineType != TEngineType::ElectricInductionMotor || ((eimic <= 0) && (eimic_real <= 0) && (Vel < 0.1))); OK = (EngineType != TEngineType::ElectricInductionMotor || ((eimic <= 0) && (eimic_real <= 0) && (Vel < 0.1)));
*/
OK = ( MainCtrlPos <= MaxMainCtrlPosNoDirChange );
return OK; return OK;
} }
@@ -3714,7 +3734,7 @@ void TMoverParameters::UpdatePipePressure(double dt)
Pipe->Flow( temp * Hamulec->GetPF( temp * PipePress, dt, Vel ) + GetDVc( dt ) ); Pipe->Flow( temp * Hamulec->GetPF( temp * PipePress, dt, Vel ) + GetDVc( dt ) );
if (ASBType == 128) if (ASBType == 128)
Hamulec->ASB(int(SlippingWheels)); Hamulec->ASB(int(SlippingWheels && (Vel>1))*(1+2*int(nrot_eps<-0.01)));
dpPipe = 0; dpPipe = 0;
@@ -3962,6 +3982,7 @@ void TMoverParameters::ComputeTotalForce(double dt) {
// juz zoptymalizowane: // juz zoptymalizowane:
FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // siła oporów ruchu FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // siła oporów ruchu
double old_nrot = abs(nrot);
nrot = v2n(); // przeliczenie prędkości liniowej na obrotową nrot = v2n(); // przeliczenie prędkości liniowej na obrotową
if( ( true == TestFlag( BrakeMethod, bp_MHS ) ) if( ( true == TestFlag( BrakeMethod, bp_MHS ) )
@@ -4034,8 +4055,9 @@ void TMoverParameters::ComputeTotalForce(double dt) {
} }
else else
{ {
Fb = -Fwheels*Sign(V); double factor = (FTrain - Fb * Sign(V) != 0 ? Fwheels/(FTrain - Fb * Sign(V)) : 1.0);
FTrain = 0; Fb *= factor;
FTrain *= factor;
} }
if (nrot < 0.1) if (nrot < 0.1)
{ {
@@ -4044,6 +4066,7 @@ void TMoverParameters::ComputeTotalForce(double dt) {
nrot = temp_nrot; nrot = temp_nrot;
} }
nrot_eps = (abs(nrot) - (old_nrot))/dt;
// doliczenie sił z innych pojazdów // doliczenie sił z innych pojazdów
for( int end = end::front; end <= end::rear; ++end ) { for( int end = end::front; end <= end::rear; ++end ) {
if( Neighbours[ end ].vehicle != nullptr ) { if( Neighbours[ end ].vehicle != nullptr ) {
@@ -4336,6 +4359,7 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
// zderzenie // zderzenie
coupler.CheckCollision = true; coupler.CheckCollision = true;
if( ( coupler.CouplerType == TCouplerType::Automatic ) if( ( coupler.CouplerType == TCouplerType::Automatic )
&& ( coupler.CouplerType == othercoupler.CouplerType )
&& ( coupler.CouplingFlag == coupling::faux ) ) { && ( coupler.CouplingFlag == coupling::faux ) ) {
// sprzeganie wagonow z samoczynnymi sprzegami // sprzeganie wagonow z samoczynnymi sprzegami
// EN57 // EN57
@@ -6018,6 +6042,26 @@ void TMoverParameters::CheckEIMIC(double dt)
} }
if (MainCtrlPos >= 3 && eimic < 0) eimic = 0; if (MainCtrlPos >= 3 && eimic < 0) eimic = 0;
if (MainCtrlPos <= 3 && eimic > 0) eimic = 0; if (MainCtrlPos <= 3 && eimic > 0) eimic = 0;
if (LocHandleTimeTraxx)
{
if (LocalBrakeRatio() < 0.05) //pozycja 0
{
eim_localbrake -= dt*0.17; //zmniejszanie
}
if (LocalBrakeRatio() > 0.15) //pozycja 2
{
eim_localbrake += dt*0.17; //wzrastanie
eim_localbrake = std::max(eim_localbrake, BrakePress / MaxBrakePress[0]);
}
else
{
if (eim_localbrake < Hamulec->GetEDBCP() / MaxBrakePress[0])
eim_localbrake = 0;
}
eim_localbrake = clamp(eim_localbrake, 0.0, 1.0);
if (eim_localbrake > 0.04 && eimic > 0) eimic = 0;
}
break; break;
case 2: case 2:
switch (MainCtrlPos) switch (MainCtrlPos)
@@ -7261,14 +7305,14 @@ double TMoverParameters::GetTrainsetVoltage(void)
return std::max( return std::max(
( ( ( Couplers[end::front].Connected ) ( ( ( Couplers[end::front].Connected )
&& ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) && ( ( Couplers[ end::front ].CouplingFlag & ctrain_power )
|| ( ( Heating ) || ( ( Couplers[ end::front ].CouplingFlag & ctrain_heating )
&& ( Couplers[ end::front ].CouplingFlag & ctrain_heating ) ) ) ) ? && ( Couplers[ end::front ].Connected->Heating ) ) ) ) ?
Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage : Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage :
0.0 ), 0.0 ),
( ( ( Couplers[end::rear].Connected ) ( ( ( Couplers[end::rear].Connected )
&& ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) && ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power )
|| ( ( Heating ) || ( ( Couplers[ end::rear ].CouplingFlag & ctrain_heating )
&& ( Couplers[ end::rear ].CouplingFlag & ctrain_heating ) ) ) ) ? && ( Couplers[ end::rear ].Connected->Heating ) ) ) ) ?
Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage : Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage :
0.0 ) ); 0.0 ) );
} }
@@ -8638,6 +8682,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
extract_value( CoupledCtrl, "CoupledCtrl", line, "" ); extract_value( CoupledCtrl, "CoupledCtrl", line, "" );
extract_value( EIMCtrlType, "EIMCtrlType", line, "" ); extract_value( EIMCtrlType, "EIMCtrlType", line, "" );
clamp( EIMCtrlType, 0, 3 ); clamp( EIMCtrlType, 0, 3 );
LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes");
extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR

View File

@@ -391,7 +391,8 @@ void TBrake::SetEPS( double const nEPS )
void TBrake::ASB( int const state ) void TBrake::ASB( int const state )
{ // 255-b_asb(32) { // 255-b_asb(32)
BrakeStatus = (BrakeStatus & ~b_asb) | ( state * b_asb ); BrakeStatus = (BrakeStatus & ~b_asb) | ( (state / 2) * b_asb );
BrakeStatus = (BrakeStatus & ~b_asb_unbrake) | ( (state % 2) * b_asb_unbrake);
} }
int TBrake::GetStatus() int TBrake::GetStatus()
@@ -1551,7 +1552,7 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel )
// powtarzacz — podwojny zawor zwrotny // powtarzacz — podwojny zawor zwrotny
temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP); temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP);
double speed = 1; double speed = 1;
if ((ASBP < 0.1) && ((BrakeStatus & b_asb) == b_asb)) if ((ASBP < 0.1) && ((BrakeStatus & b_asb_unbrake) == b_asb_unbrake))
{ {
temp = 0; temp = 0;
speed = 3; speed = 3;
@@ -1559,7 +1560,7 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel )
if ((BrakeCyl->P() > temp)) if ((BrakeCyl->P() > temp))
dv = -PFVd(BrakeCyl->P(), 0, 0.02 * SizeBC * speed, temp) * dt; dv = -PFVd(BrakeCyl->P(), 0, 0.02 * SizeBC * speed, temp) * dt;
else if ((BrakeCyl->P() < temp)) else if ((BrakeCyl->P() < temp) && ((BrakeStatus & b_asb) == 0))
dv = PFVa(BVP, BrakeCyl->P(), 0.02 * SizeBC, temp) * dt; dv = PFVa(BVP, BrakeCyl->P(), 0.02 * SizeBC, temp) * dt;
else else
dv = 0; dv = 0;

View File

@@ -53,7 +53,8 @@ static int const b_on = 2; //napelnianie
static int const b_rfl = 4; //uzupelnianie static int const b_rfl = 4; //uzupelnianie
static int const b_rls = 8; //odluzniacz static int const b_rls = 8; //odluzniacz
static int const b_ep = 16; //elektropneumatyczny static int const b_ep = 16; //elektropneumatyczny
static int const b_asb = 32; //elektropneumatyczny static int const b_asb = 32; //przeciwposlizg-wstrzymanie
static int const b_asb_unbrake = 64; //przeciwposlizg-luzowanie
static int const b_dmg = 128; //wylaczony z dzialania static int const b_dmg = 128; //wylaczony z dzialania
/*uszkodzenia hamulca*/ /*uszkodzenia hamulca*/

View File

@@ -791,6 +791,27 @@ int TSubModel::count_children() {
1 + Child->count_siblings() ); 1 + Child->count_siblings() );
} }
// locates submodel mapped with replacable -4
std::tuple<TSubModel *, bool>
TSubModel::find_replacable4() {
if( m_material == -4 ) {
return std::make_tuple( this, ( fLight != -1.0 ) );
}
if( Next != nullptr ) {
auto lookup { Next->find_replacable4() };
if( std::get<TSubModel *>( lookup ) != nullptr ) { return lookup; }
}
if( Child != nullptr ) {
auto lookup { Child->find_replacable4() };
if( std::get<TSubModel *>( lookup ) != nullptr ) { return lookup; }
}
return std::make_tuple( nullptr, false );
}
uint32_t TSubModel::FlagsCheck() uint32_t TSubModel::FlagsCheck()
{ // analiza koniecznych zmian pomiędzy submodelami { // analiza koniecznych zmian pomiędzy submodelami
// samo pomijanie glBindTexture() nie poprawi wydajności // samo pomijanie glBindTexture() nie poprawi wydajności

View File

@@ -169,6 +169,8 @@ public:
TSubModel * ChildGet() { return Child; }; TSubModel * ChildGet() { return Child; };
int count_siblings(); int count_siblings();
int count_children(); int count_children();
// locates submodel mapped with replacable -4
std::tuple<TSubModel *, bool> find_replacable4();
int TriangleAdd(TModel3d *m, material_handle tex, int tri); int TriangleAdd(TModel3d *m, material_handle tex, int tri);
void SetRotate(float3 vNewRotateAxis, float fNewAngle); void SetRotate(float3 vNewRotateAxis, float fNewAngle);
void SetRotateXYZ( Math3D::vector3 vNewAngles); void SetRotateXYZ( Math3D::vector3 vNewAngles);

View File

@@ -10,9 +10,8 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h" #include "stdafx.h"
#include "PyInt.h" #include "PyInt.h"
#include "Globals.h" #include "dictionary.h"
#include "application.h" #include "application.h"
#include "renderer.h"
#include "Logs.h" #include "Logs.h"
#ifdef __GNUC__ #ifdef __GNUC__

18
PyInt.h
View File

@@ -33,24 +33,6 @@ http://mozilla.org/MPL/2.0/.
#define PyGetBool(param) param ? Py_True : Py_False #define PyGetBool(param) param ? Py_True : Py_False
#define PyGetString(param) PyString_FromString(param) #define PyGetString(param) PyString_FromString(param)
// collection of keyword-value pairs
// NOTE: since our python dictionary operates on a few types, most of the class was hardcoded for simplicity
struct dictionary_source {
// types
template <typename Type_>
using keyvaluepair_sequence = std::vector<std::pair<std::string, Type_>>;
// members
keyvaluepair_sequence<double> floats;
keyvaluepair_sequence<int> integers;
keyvaluepair_sequence<bool> bools;
keyvaluepair_sequence<std::string> strings;
// methods
inline void insert( std::string const &Key, double const Value ) { floats.emplace_back( Key, Value ); }
inline void insert( std::string const &Key, int const Value ) { integers.emplace_back( Key, Value ); }
inline void insert( std::string const &Key, bool const Value ) { bools.emplace_back( Key, Value ); }
inline void insert( std::string const &Key, std::string const Value ) { strings.emplace_back( Key, Value ); }
};
// TODO: extract common base and inherit specialization from it // TODO: extract common base and inherit specialization from it
class render_task { class render_task {

View File

@@ -19,14 +19,16 @@ http://mozilla.org/MPL/2.0/.
#include "GL/glew.h" #include "GL/glew.h"
#include "application.h" #include "application.h"
#include "utilities.h" #include "dictionary.h"
#include "Globals.h" #include "Globals.h"
#include "Logs.h" #include "Logs.h"
#include "utilities.h"
#include "sn_utils.h" #include "sn_utils.h"
#include "utilities.h" #include "utilities.h"
#include "flip-s3tc.h" #include "flip-s3tc.h"
#include <png.h> #include <png.h>
#define EU07_DEFERRED_TEXTURE_UPLOAD #define EU07_DEFERRED_TEXTURE_UPLOAD
texture_manager::texture_manager() { texture_manager::texture_manager() {
@@ -146,17 +148,9 @@ void
opengl_texture::make_request() { opengl_texture::make_request() {
auto const components { Split( name, '?' ) }; auto const components { Split( name, '?' ) };
auto const query { Split( components.back(), '&' ) };
auto *dictionary { new dictionary_source }; auto *dictionary { new dictionary_source( components.back() ) };
if( dictionary != nullptr ) { if( dictionary == nullptr ) { return; }
for( auto const &querypair : query ) {
auto const valuepos { querypair.find( '=' ) };
dictionary->insert(
ToLower( querypair.substr( 0, valuepos ) ),
querypair.substr( valuepos + 1 ) );
}
}
Application.request( { ToLower( components.front() ), dictionary, id } ); Application.request( { ToLower( components.front() ), dictionary, id } );
} }

View File

@@ -30,6 +30,7 @@ http://mozilla.org/MPL/2.0/.
#include "Console.h" #include "Console.h"
#include "application.h" #include "application.h"
#include "renderer.h" #include "renderer.h"
#include "dictionary.h"
/* /*
namespace input { namespace input {
@@ -547,31 +548,8 @@ dictionary_source *TTrain::GetTrainState() {
dict->insert( "velnext", driver->VelNext ); dict->insert( "velnext", driver->VelNext );
dict->insert( "actualproximitydist", driver->ActualProximityDist ); dict->insert( "actualproximitydist", driver->ActualProximityDist );
// train data // train data
auto const *timetable{ driver->TrainTimetable() }; driver->TrainTimetable()->serialize( dict );
dict->insert( "train_stationstart", driver->iStationStart );
dict->insert( "trainnumber", driver->TrainName() );
dict->insert( "train_brakingmassratio", timetable->BrakeRatio );
dict->insert( "train_enginetype", timetable->LocSeries );
dict->insert( "train_engineload", timetable->LocLoad );
dict->insert( "train_stationindex", driver->iStationStart );
auto const stationcount { driver->StationCount() };
dict->insert( "train_stationcount", stationcount );
if( stationcount > 0 ) {
// timetable stations data, if there's any
for( auto stationidx = 1; stationidx <= stationcount; ++stationidx ) {
auto const stationlabel { "train_station" + std::to_string( stationidx ) + "_" };
auto const &timetableline { timetable->TimeTable[ stationidx ] };
dict->insert( ( stationlabel + "name" ), Bezogonkow( timetableline.StationName ) );
dict->insert( ( stationlabel + "fclt" ), Bezogonkow( timetableline.StationWare ) );
dict->insert( ( stationlabel + "lctn" ), timetableline.km );
dict->insert( ( stationlabel + "vmax" ), timetableline.vmax );
dict->insert( ( stationlabel + "ah" ), timetableline.Ah );
dict->insert( ( stationlabel + "am" ), timetableline.Am );
dict->insert( ( stationlabel + "dh" ), timetableline.Dh );
dict->insert( ( stationlabel + "dm" ), timetableline.Dm );
}
}
dict->insert( "train_atpassengerstop", driver->IsAtPassengerStop ); dict->insert( "train_atpassengerstop", driver->IsAtPassengerStop );
// world state data // world state data
dict->insert( "scenario", Global.SceneryFile ); dict->insert( "scenario", Global.SceneryFile );
@@ -4152,7 +4130,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 // only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->Heating ) { if( false == Train->mvControlled->HeatingAllow ) {
// turn on // turn on
OnCommand_heatingenable( Train, Command ); OnCommand_heatingenable( Train, Command );
} }
@@ -4166,24 +4144,20 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
Train->mvControlled->HeatingAllow = true;
// visual feedback // visual feedback
Train->ggTrainHeatingButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggTrainHeatingButton.UpdateValue( 1.0, Train->dsbSwitch );
if( true == Train->mvControlled->Heating ) { return; } // already enabled
Train->mvControlled->Heating = true;
} }
} }
void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
Train->mvControlled->HeatingAllow = false;
// visual feedback // visual feedback
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
if( false == Train->mvControlled->Heating ) { return; } // already disabled
Train->mvControlled->Heating = false;
} }
} }
@@ -5711,6 +5685,7 @@ bool TTrain::Update( double const Deltatime )
btLampkaMalfunction.Turn( mvControlled->dizel_heat.PA ); btLampkaMalfunction.Turn( mvControlled->dizel_heat.PA );
btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ end::front ].is_active ) && ( mvControlled->MotorBlowers[ end::rear ].is_active ) ); btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ end::front ].is_active ) && ( mvControlled->MotorBlowers[ end::rear ].is_active ) );
btLampkaCoolingFans.Turn( mvControlled->RventRot > 1.0 ); btLampkaCoolingFans.Turn( mvControlled->RventRot > 1.0 );
btLampkaTempomat.Turn( mvControlled->ScndCtrlPos > 0 );
// universal devices state indicators // universal devices state indicators
for( auto idx = 0; idx < btUniversals.size(); ++idx ) { for( auto idx = 0; idx < btUniversals.size(); ++idx ) {
btUniversals[ idx ].Turn( ggUniversals[ idx ].GetValue() > 0.5 ); btUniversals[ idx ].Turn( ggUniversals[ idx ].GetValue() > 0.5 );
@@ -5772,6 +5747,7 @@ bool TTrain::Update( double const Deltatime )
btLampkaMalfunction.Turn( false ); btLampkaMalfunction.Turn( false );
btLampkaMotorBlowers.Turn( false ); btLampkaMotorBlowers.Turn( false );
btLampkaCoolingFans.Turn( false ); btLampkaCoolingFans.Turn( false );
btLampkaTempomat.Turn( false );
// universal devices state indicators // universal devices state indicators
for( auto &universal : btUniversals ) { for( auto &universal : btUniversals ) {
universal.Turn( false ); universal.Turn( false );
@@ -6011,7 +5987,6 @@ bool TTrain::Update( double const Deltatime )
//--------- //---------
// hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy // hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy
if( ( mvControlled->Heating == true ) if( ( mvControlled->Heating == true )
&& ( mvControlled->Mains == true )
&& ( mvControlled->ConvOvldFlag == false ) ) && ( mvControlled->ConvOvldFlag == false ) )
btLampkaOgrzewanieSkladu.Turn( true ); btLampkaOgrzewanieSkladu.Turn( true );
else else
@@ -7417,6 +7392,7 @@ void TTrain::clear_cab_controls()
btLampkaMalfunctionB.Clear(); btLampkaMalfunctionB.Clear();
btLampkaMotorBlowers.Clear(); btLampkaMotorBlowers.Clear();
btLampkaCoolingFans.Clear(); btLampkaCoolingFans.Clear();
btLampkaTempomat.Clear();
ggLeftLightButton.Clear(); ggLeftLightButton.Clear();
ggRightLightButton.Clear(); ggRightLightButton.Clear();
@@ -7762,6 +7738,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-vent_trim:", btLampkaWentZaluzje }, { "i-vent_trim:", btLampkaWentZaluzje },
{ "i-motorblowers:", btLampkaMotorBlowers }, { "i-motorblowers:", btLampkaMotorBlowers },
{ "i-coolingfans:", btLampkaCoolingFans }, { "i-coolingfans:", btLampkaCoolingFans },
{ "i-tempomat:", btLampkaTempomat },
{ "i-trainheating:", btLampkaOgrzewanieSkladu }, { "i-trainheating:", btLampkaOgrzewanieSkladu },
{ "i-security_aware:", btLampkaCzuwaka }, { "i-security_aware:", btLampkaCzuwaka },
{ "i-security_cabsignal:", btLampkaSHP }, { "i-security_cabsignal:", btLampkaSHP },

View File

@@ -584,6 +584,7 @@ public: // reszta może by?publiczna
TButton btLampkaMalfunctionB; TButton btLampkaMalfunctionB;
TButton btLampkaMotorBlowers; TButton btLampkaMotorBlowers;
TButton btLampkaCoolingFans; TButton btLampkaCoolingFans;
TButton btLampkaTempomat;
TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine
// Ra 2013-12: wirtualne "lampki" do odbijania na haslerze w PoKeys // Ra 2013-12: wirtualne "lampki" do odbijania na haslerze w PoKeys

55
dictionary.cpp Normal file
View File

@@ -0,0 +1,55 @@
/*
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
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "dictionary.h"
#include "simulation.h"
#include "utilities.h"
#include "DynObj.h"
#include "Driver.h"
#include "mtable.h"
dictionary_source::dictionary_source( std::string const &Input ) {
auto const keyvaluepairs { Split( Input, '&' ) };
for( auto const &keyvaluepair : keyvaluepairs ) {
auto const valuepos { keyvaluepair.find( '=' ) };
if( keyvaluepair[ 0 ] != '$' ) {
// regular key, value pairs
insert(
ToLower( keyvaluepair.substr( 0, valuepos ) ),
keyvaluepair.substr( valuepos + 1 ) );
}
else {
// special case, $key indicates request to include certain dataset clarified by value
auto const key { ToLower( keyvaluepair.substr( 0, valuepos ) ) };
auto const value { keyvaluepair.substr( valuepos + 1 ) };
if( key == "$timetable" ) {
// timetable pulled from (preferably) the owner/direct controller of specified vehicle
auto const *vehicle { simulation::Vehicles.find( value ) };
auto const *controller { (
vehicle == nullptr ? nullptr :
vehicle->ctOwner == nullptr ? vehicle->Mechanik :
vehicle->ctOwner ) };
auto const *timetable { (
controller != nullptr ?
controller->TrainTimetable() :
nullptr ) };
if( timetable != nullptr ) {
timetable->serialize( this );
}
}
}
}
}

31
dictionary.h Normal file
View File

@@ -0,0 +1,31 @@
/*
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
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
// collection of keyword-value pairs
// NOTE: since our python dictionary operates on a few types, most of the class was hardcoded for simplicity
struct dictionary_source {
// types
template <typename Type_>
using keyvaluepair_sequence = std::vector<std::pair<std::string, Type_>>;
// members
keyvaluepair_sequence<double> floats;
keyvaluepair_sequence<int> integers;
keyvaluepair_sequence<bool> bools;
keyvaluepair_sequence<std::string> strings;
// constructors
dictionary_source() = default;
dictionary_source( std::string const &Input );
// methods
inline void insert( std::string const &Key, double const Value ) { floats.emplace_back( Key, Value ); }
inline void insert( std::string const &Key, int const Value ) { integers.emplace_back( Key, Value ); }
inline void insert( std::string const &Key, bool const Value ) { bools.emplace_back( Key, Value ); }
inline void insert( std::string const &Key, std::string const Value ) { strings.emplace_back( Key, Value ); }
};

View File

@@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/.
#include "mtable.h" #include "mtable.h"
#include "Globals.h" #include "Globals.h"
#include "simulationtime.h" #include "simulationtime.h"
#include "dictionary.h"
#include "utilities.h" #include "utilities.h"
double TTrainParameters::CheckTrainLatency() double TTrainParameters::CheckTrainLatency()
@@ -523,3 +524,29 @@ bool TTrainParameters::DirectionChange()
return true; return true;
return false; return false;
} }
void TTrainParameters::serialize( dictionary_source *Output ) const {
Output->insert( "trainnumber", TrainName );
Output->insert( "train_brakingmassratio", BrakeRatio );
Output->insert( "train_enginetype", LocSeries );
Output->insert( "train_engineload", LocLoad );
Output->insert( "train_stationindex", StationIndex );
Output->insert( "train_stationcount", StationCount );
if( StationCount > 0 ) {
// timetable stations data, if there's any
for( auto stationidx = 1; stationidx <= StationCount; ++stationidx ) {
auto const stationlabel { "train_station" + std::to_string( stationidx ) + "_" };
auto const &timetableline { TimeTable[ stationidx ] };
Output->insert( ( stationlabel + "name" ), Bezogonkow( timetableline.StationName ) );
Output->insert( ( stationlabel + "fclt" ), Bezogonkow( timetableline.StationWare ) );
Output->insert( ( stationlabel + "lctn" ), timetableline.km );
Output->insert( ( stationlabel + "vmax" ), timetableline.vmax );
Output->insert( ( stationlabel + "ah" ), timetableline.Ah );
Output->insert( ( stationlabel + "am" ), timetableline.Am );
Output->insert( ( stationlabel + "dh" ), timetableline.Dh );
Output->insert( ( stationlabel + "dm" ), timetableline.Dm );
}
}
}

View File

@@ -83,6 +83,7 @@ class TTrainParameters
bool LoadTTfile(std::string scnpath, int iPlus, double vmax); bool LoadTTfile(std::string scnpath, int iPlus, double vmax);
bool DirectionChange(); bool DirectionChange();
void StationIndexInc(); void StationIndexInc();
void serialize( dictionary_source *Output ) const;
}; };
class TMTableTime class TMTableTime

View File

@@ -1 +1 @@
#define VERSION_INFO "M7 23.03.2018, based on tmj-ae5daac9" #define VERSION_INFO "M7 5.04.2019, based on tmj-a081077c"