16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 16: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 vehicle_table;
struct light_array;
struct dictionary_source;
namespace scene {
struct node_data;

View File

@@ -1373,7 +1373,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if( ( mvOccupied->Vel < v )
|| ( v == 0.0 ) ) {
// 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 ) {
// 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
@@ -1822,8 +1822,7 @@ void TController::Activation()
}
}
// Ra: to przełączanie poniżej jest tu bez sensu
mvOccupied->ActiveCab =
iDirection; // aktywacja kabiny w prowadzonym pojeżdzie (silnikowy może być odwrotnie?)
mvOccupied->ActiveCab = iDirection; // aktywacja kabiny w prowadzonym pojeżdzie (silnikowy może być odwrotnie?)
// mvOccupied->CabNo=iDirection;
// mvOccupied->ActiveDir=0; //żeby sam ustawił kierunek
mvOccupied->CabActivisation(); // uruchomienie kabin w członach
@@ -1963,6 +1962,7 @@ void TController::AutoRewident()
&& ( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) ) {
fAccThreshold += 0.10;
}
fNominalAccThreshold = fAccThreshold;
}
if( OrderCurrentGet() & ( Obey_train | Bank ) ) {
@@ -2125,6 +2125,11 @@ bool TController::CheckVehicles(TOrders user)
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) {
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
p->MoverParameters->BatterySwitch( true );
// enable heating and converter in carriages with can be heated
if( p->MoverParameters->HeatingPower > 0 ) {
p->MoverParameters->HeatingAllow = true;
p->MoverParameters->ConverterSwitch( true, range_t::local );
}
}
if (p->asDestination == "none")
@@ -2354,8 +2359,11 @@ void TController::SetVelocity(double NewVel, double NewVelNext, TStopReason r)
double TController::BrakeAccFactor() const
{
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 );
}
return Factor;
@@ -2520,7 +2528,15 @@ bool TController::PrepareEngine()
// enable train brake if it's off
if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) {
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);
/* if (mvOccupied->BrakeCtrlPosR < 0.74) GBH */
if (BrakeCtrlPosition < 0.74)
/*mvOccupied->*/BrakeLevelSet(0.0);
/*mvOccupied->*/BrakeLevelSet(gbh_RP);
}
}
if( !OK ) {
@@ -3065,7 +3081,7 @@ bool TController::IncSpeed()
if (!mvControlling->FuseFlag)
if (Ready || (iDrivigFlags & movePress) || (mvOccupied->ShuntMode)) //{(BrakePress<=0.01*MaxBrakePress)}
{
OK = mvControlling->IncMainCtrl(std::max(1,mvOccupied->MainCtrlPosNo/10));
OK = IncSpeedEIM();
// cruise control
auto const SpeedCntrlVel { (
( ActualProximityDist > std::max( 50.0, fMaxProximityDist ) ) ?
@@ -3167,6 +3183,34 @@ bool TController::DecSpeed(bool force)
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()
{ // zmniejszenie prędkości (ale nie hamowanie)
bool OK = false; // domyślnie false, aby wyszło z pętli while
@@ -3214,31 +3258,40 @@ void TController::SpeedSet()
if (mvControlling->MainCtrlPosNo > 0)
{ // jeśli ma czym kręcić
// TODO: sprawdzanie innego czlonu //if (!FuseFlagCheck())
if ((AccDesired < fAccGravity - 0.05) ||
(mvOccupied->Vel > VelDesired)) // jeśli nie ma przyspieszać
mvControlling->DecMainCtrl(2); // na zero
else if (fActionTime >= 0.0)
{ // jak już można coś poruszać, przetok rozłączać od razu
if (iDrivigFlags & moveIncSpeed)
{ // jak ma jechać
if (fReady < 0.4) // 0.05*Controlling->MaxBrakePress)
{ // jak jest odhamowany
if (mvOccupied->ActiveDir > 0)
if( ( iDrivigFlags & moveIncSpeed ) == 0 ) {
// przetok rozłączać od razu (no dependency on fActionTime)
while( ( mvControlling->MainCtrlPos )
&& ( mvControlling->DecMainCtrl( 1 ) ) ) {
; // na zero
}
if( fActionTime >= 0.0 ) {
fActionTime = -5.0; // niech trochę potrzyma
}
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 &&
!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
}
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
break; // to czekać na wyzerowanie
mvControlling->IncMainCtrl(1); // przetok; bez "break", bo nie
// ma czekania na 1. pozycji
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
@@ -3255,6 +3308,7 @@ void TController::SpeedSet()
if( VelDesired >= 100 )
mvControlling->IncMainCtrl( 1 ); // bocznik 3
}
}
if( mvControlling->MainCtrlPos ) // jak załączył pozycję
{
fActionTime = -5.0; // niech trochę potrzyma
@@ -3262,16 +3316,6 @@ void TController::SpeedSet()
}
}
}
}
else
{
while (mvControlling->MainCtrlPos)
mvControlling->DecMainCtrl(1); // na zero
fActionTime = -5.0; // niech trochę potrzyma
mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania
}
}
}
break;
case TEngineType::ElectricSeriesMotor:
if( ( false == mvControlling->StLinFlag )
@@ -3370,7 +3414,7 @@ void TController::SpeedCntrl(double DesiredSpeed)
mvControlling->IncScndCtrl(1);
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);
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;
}
}
//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()
@@ -3444,6 +3504,14 @@ void TController::CheckTimeControllers()
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
@@ -3487,7 +3555,7 @@ void TController::Doors( bool const Open, int const Side ) {
}
if( AIControllFlag ) {
if( ( true == mvOccupied->Doors.has_autowarning )
if( ( true == mvOccupied->Doors.has_warning )
&& ( false == mvOccupied->DepartureSignal )
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
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" ) )
{ // 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
// trybie pociągowym
//-3,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać w 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) 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ć dalej
//-1, 0 - tryb manewrowy bez zmian (odczepianie z pozostawieniem wagonów nie ma sensu)
// 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
iDrivigFlags &= ~moveStopHere; // podjeżanie do semaforów zezwolone
if (!iEngineActive)
@@ -4141,7 +4208,7 @@ TController::UpdateSituation(double dt) {
Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego
}
// check door state
auto const switchsides { p->DirectionGet() <= 0 };
auto const switchsides { p->DirectionGet() != iDirection };
IsAnyDoorOpen[ side::right ] =
IsAnyDoorOpen[ side::right ]
|| ( false == vehicle->Doors.instances[ ( switchsides ? side::left : side::right ) ].is_closed );
@@ -4563,6 +4630,7 @@ TController::UpdateSituation(double dt) {
auto *vehicleparameters { vehicle->MoverParameters };
int const end { ( vehicle->DirectionGet() > 0 ? end::front : end::rear ) };
auto const &neighbour { vehicleparameters->Neighbours[ end ] };
if( neighbour.vehicle != nullptr ) {
// próba podczepienia
vehicleparameters->Attach(
end, neighbour.vehicle_end,
@@ -4576,7 +4644,7 @@ TController::UpdateSituation(double dt) {
CheckVehicles(); // sprawdzić światła nowego składu
JumpToNextOrder(); // wykonanie następnej komendy
}
}
} // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna
}
else {
@@ -4606,11 +4674,11 @@ TController::UpdateSituation(double dt) {
// TODO: test if we can use the distances calculation from obey_train
fMinProximityDist = std::min( 5 + iVehicles, 25 );
fMaxProximityDist = std::min( 10 + iVehicles, 50 );
/*
if( IsHeavyCargoTrain ) {
fMaxProximityDist *= 1.5;
// HACK: modern vehicles might brake slower at low speeds, increase safety margin as crude counter
if( mvControlling->EIMCtrlType > 0 ) {
fMinProximityDist += 5.0;
fMaxProximityDist += 5.0;
}
*/
fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
// margines prędkości powodujący załączenie napędu
// były problemy z jazdą np. 3km/h podczas ładowania wagonów
@@ -5090,7 +5158,11 @@ TController::UpdateSituation(double dt) {
20.0 ) ); // others
if( vel > VelDesired + fVelPlus ) {
// 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 ) ) ?
fBrake_a0[ 0 ] * 0.8 :
-fAccThreshold )
/ braking_distance_multiplier( VelNext ) ) {
/ ( 1.2 * braking_distance_multiplier( VelNext ) ) ) {
AccDesired = std::max( -0.06, AccDesired );
}
}
else {
if( AccDesired < -0.1 ) {
// i orientuj się szybciej, jeśli hamujesz
ReactionTime = 0.25;
}
@@ -5705,11 +5777,11 @@ TController::UpdateSituation(double dt) {
}
}
}
// yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej
// zwiekszanie predkosci
// yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej zwiekszanie predkosci
// Ra 2F1H: jest konflikt histerezy pomiędzy nastawioną pozycją a uzyskiwanym
// 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...
if( vel < (
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
if( AbsAccS < AccDesired - 0.05 ) {
// 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 ) {
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
// yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2
if( OrderCurrentGet() != Disconnect ) {
@@ -6526,6 +6600,9 @@ void TController::TakeControl(bool yes)
void TController::DirectionForward(bool forward)
{ // 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
// 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 ) {
// do przodu w obecnej kabinie
while( ( mvOccupied->ActiveDir <= 0 )

View File

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

View File

@@ -162,6 +162,39 @@ void TAnim::Parovoz(){
// 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)
{ // szukanie skrajnego połączonego pojazdu w pociagu
@@ -921,6 +954,8 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
btEndSignalsTab2.Turn( true );
btnOn = true;
}
// destination signs
update_destinations();
// else btEndSignalsTab2.TurnOff();
// McZapkie-181002: krecenie wahaczem (korzysta z kata obrotu silnika)
if (iAnimType[ANIM_LEVERS])
@@ -1947,6 +1982,10 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
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
if( mdModel ) {
init_sections( mdModel, "external_load" );
@@ -2070,6 +2109,16 @@ TDynamicObject::init_sections( TModel3d const *Model, std::string const &Namepre
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
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.
*/
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)
{
if (dt1 == 0)
@@ -2714,6 +2784,7 @@ bool TDynamicObject::Update(double dt, double dt1)
MoverParameters->eimic_real = eimic;
MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo);
auto LBR = Max0R(-eimic, 0);
auto eim_lb = (Mechanik->AIControllFlag || !MoverParameters->LocHandleTimeTraxx ? 0 : MoverParameters->eim_localbrake);
// 1. ustal wymagana sile hamowania calego pociagu
// - opoznienie moze byc ustalane na podstawie charakterystyki
@@ -2944,6 +3015,11 @@ bool TDynamicObject::Update(double dt, double dt1)
p->MoverParameters->LocalBrakePosAEIM = p->MoverParameters->LocalBrakePosAEIM;
else
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;
}
@@ -4012,6 +4088,10 @@ void TDynamicObject::RenderSounds() {
}
if( volume > 0.05 ) {
rscurve
.pitch(
true == rscurve.is_combined() ?
MoverParameters->Vel * 0.01f :
rscurve.m_frequencyoffset + rscurve.m_frequencyfactor * 1.f )
.gain( 2.5 * volume )
.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
DestinationSet( {}, {} );
DestinationSign.destination_off = DestinationFind( "nowhere" );
// DestinationSet( {}, {} );
if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) {
// 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;
}
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 != "" );
} // internaldata:
@@ -6091,45 +6181,92 @@ int TDynamicObject::RouteWish(TTrack *tr)
return Mechanik ? Mechanik->CrossRoute(tr) : 0; // wg AI albo prosto
};
void TDynamicObject::DestinationSet(std::string to, std::string numer)
{ // ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik
void TDynamicObject::DestinationSet(std::string to, std::string numer) {
// ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik
// 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
// ale to jeszcze potrwa, zanim będzie możliwe, na razie można wpisać stację z
// 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;
}
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
auto const currenttexturepath { Global.asCurrentTexturePath };
Global.asCurrentTexturePath = asBaseDir;
// now see if we can find any version of the texture
std::vector<std::string> destinations = {
numer + '@' + MoverParameters->TypeName,
numer,
to + '@' + MoverParameters->TypeName,
to,
"nowhere" + '@' + MoverParameters->TypeName,
"nowhere" };
std::vector<std::string> const destinations {
Destination + '@' + MoverParameters->TypeName,
Destination };
auto destinationhandle { null_handle };
for( auto const &destination : destinations ) {
auto material = TextureTest( ToLower( destination ) );
if( false == material.empty() ) {
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Material( material );
destinationhandle = GfxRenderer.Fetch_Material( material );
break;
}
}
// whether we got anything, restore previous texture path
Global.asCurrentTexturePath = currenttexturepath;
};
return destinationhandle;
}
void TDynamicObject::OverheadTrack(float o)
{ // ewentualne wymuszanie jazdy
@@ -6814,6 +6951,9 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) {
if( pantograph->hvPowerWire != nullptr ) {
// jeżeli znamy drut z poprzedniego przebiegu
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
if( pantograph->hvPowerWire->iLast & 0x3 ) {
// 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)
// 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 =
-( glm::dot( pantograph->hvPowerWire->pPoint1, vFront ) - glm::dot( pant0, vFront ) )
/ glm::dot( pantograph->hvPowerWire->vParametric, vFront );

View File

@@ -201,6 +201,20 @@ public:
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
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)
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 LoadOffset { 0.f };
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,
float Load, std::string LoadType, bool Reversed, std::string);
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 AttachPrev(TDynamicObject *Object, int iType = 1);
bool UpdateForce(double dt);
@@ -532,6 +547,7 @@ private:
void update_load_visibility();
void update_load_offset();
void shuffle_load_sections();
void update_destinations();
bool Update(double dt, double dt1);
bool FastUpdate(double dt);
void Move(double fDistance);
@@ -634,6 +650,7 @@ private:
// zapytanie do AI, po którym segmencie skrzyżowania jechać
int RouteWish(TTrack *tr);
void DestinationSet(std::string to, std::string numer);
material_handle DestinationFind( std::string Destination );
void OverheadTrack(float o);
double MED[9][8]; // lista zmiennych do debugowania hamulca ED

View File

@@ -892,6 +892,7 @@ public:
TBrakeValve BrakeValve = TBrakeValve::NoValve;
TBrakeHandle BrakeHandle = TBrakeHandle::NoHandle;
TBrakeHandle BrakeLocHandle = TBrakeHandle::NoHandle;
bool LocHandleTimeTraxx = false; /*hamulec dodatkowy typu traxx*/
double MBPM = 1.0; /*masa najwiekszego cisnienia*/
std::shared_ptr<TBrake> Hamulec;
@@ -1131,6 +1132,7 @@ public:
double AccN = 0.0; // przyspieszenie normalne w [m/s^2]
double AccVert = 0.0; // vertical acceleration
double nrot = 0.0;
double nrot_eps = 0.0; //przyspieszenie kątowe kół (bez kierunku)
double WheelFlat = 0.0;
bool TruckHunting { true }; // enable/disable truck hunting calculation
/*! rotacja kol [obr/s]*/
@@ -1306,6 +1308,7 @@ public:
/*- zmienne dla lokomotyw z silnikami indukcyjnymi -*/
double eimic = 0; /*aktualna 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*/
bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/
double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/
@@ -1352,6 +1355,7 @@ public:
std::string StLinSwitchType;
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
bool PhysicActivation = true;
@@ -1498,6 +1502,7 @@ public:
/*-funkcje typowe dla lokomotywy elektrycznej*/
void ConverterCheck( double const Timestep ); // przetwornica
void HeatingCheck( double const Timestep );
void WaterPumpCheck( double const Timestep );
void WaterHeaterCheck( double const Timestep );
void FuelPumpCheck( double const Timestep );

View File

@@ -502,7 +502,7 @@ bool TMoverParameters::Dettach(int ConnectNo)
bool TMoverParameters::DirectionForward()
{
if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (MainCtrlPos <= MaxMainCtrlPosNoDirChange) && (EIMDirectionChangeAllow()))
if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (EIMDirectionChangeAllow()))
{
++ActiveDir;
DirAbsolute = ActiveDir * CabNo;
@@ -1075,11 +1075,13 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
for( int side = 0; side < 2; ++side ) {
// 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 )
|| ( ( Heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
if( liveconnection ) {
auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ];
Couplers[ oppositeside ].power_high.voltage =
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
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
|| ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
&& ( Couplers[ side ].Connected->Heating ) ) ) {
auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[
( 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
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
|| ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
&& ( Couplers[ side ].Connected->Heating ) ) ) {
auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[
( 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
UpdatePantVolume( Deltatime ); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów
}
// heating
HeatingCheck( Deltatime );
UpdateBrakePressure(Deltatime);
UpdatePipePressure(Deltatime);
@@ -1462,7 +1466,8 @@ void TMoverParameters::ConverterCheck( double const Timestep ) {
if( ( ConverterAllow )
&& ( ConverterAllowLocal )
&& ( false == PantPressLockActive )
&& ( Mains ) ) {
&& ( ( Mains )
|| ( GetTrainsetVoltage() > 0 ) ) ) {
// delay timer can be optionally configured, and is set anew whenever converter goes off
if( ConverterStartDelayTimer <= 0.0 ) {
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
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
@@ -2355,7 +2371,7 @@ bool TMoverParameters::DirectionBackward(void)
DB = true; //
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)
CabNo--;
@@ -2376,7 +2392,11 @@ bool TMoverParameters::DirectionBackward(void)
bool TMoverParameters::EIMDirectionChangeAllow(void)
{
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 = ( MainCtrlPos <= MaxMainCtrlPosNoDirChange );
return OK;
}
@@ -3714,7 +3734,7 @@ void TMoverParameters::UpdatePipePressure(double dt)
Pipe->Flow( temp * Hamulec->GetPF( temp * PipePress, dt, Vel ) + GetDVc( dt ) );
if (ASBType == 128)
Hamulec->ASB(int(SlippingWheels));
Hamulec->ASB(int(SlippingWheels && (Vel>1))*(1+2*int(nrot_eps<-0.01)));
dpPipe = 0;
@@ -3962,6 +3982,7 @@ void TMoverParameters::ComputeTotalForce(double dt) {
// juz zoptymalizowane:
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ą
if( ( true == TestFlag( BrakeMethod, bp_MHS ) )
@@ -4034,8 +4055,9 @@ void TMoverParameters::ComputeTotalForce(double dt) {
}
else
{
Fb = -Fwheels*Sign(V);
FTrain = 0;
double factor = (FTrain - Fb * Sign(V) != 0 ? Fwheels/(FTrain - Fb * Sign(V)) : 1.0);
Fb *= factor;
FTrain *= factor;
}
if (nrot < 0.1)
{
@@ -4044,6 +4066,7 @@ void TMoverParameters::ComputeTotalForce(double dt) {
nrot = temp_nrot;
}
nrot_eps = (abs(nrot) - (old_nrot))/dt;
// doliczenie sił z innych pojazdów
for( int end = end::front; end <= end::rear; ++end ) {
if( Neighbours[ end ].vehicle != nullptr ) {
@@ -4336,6 +4359,7 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
// zderzenie
coupler.CheckCollision = true;
if( ( coupler.CouplerType == TCouplerType::Automatic )
&& ( coupler.CouplerType == othercoupler.CouplerType )
&& ( coupler.CouplingFlag == coupling::faux ) ) {
// sprzeganie wagonow z samoczynnymi sprzegami
// 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 (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;
case 2:
switch (MainCtrlPos)
@@ -7261,14 +7305,14 @@ double TMoverParameters::GetTrainsetVoltage(void)
return std::max(
( ( ( Couplers[end::front].Connected )
&& ( ( 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 :
0.0 ),
( ( ( Couplers[end::rear].Connected )
&& ( ( 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 :
0.0 ) );
}
@@ -8638,6 +8682,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
extract_value( CoupledCtrl, "CoupledCtrl", line, "" );
extract_value( EIMCtrlType, "EIMCtrlType", line, "" );
clamp( EIMCtrlType, 0, 3 );
LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes");
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 )
{ // 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()
@@ -1551,7 +1552,7 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel )
// powtarzacz — podwojny zawor zwrotny
temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP);
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;
speed = 3;
@@ -1559,7 +1560,7 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel )
if ((BrakeCyl->P() > temp))
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;
else
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_rls = 8; //odluzniacz
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
/*uszkodzenia hamulca*/

View File

@@ -791,6 +791,27 @@ int TSubModel::count_children() {
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()
{ // analiza koniecznych zmian pomiędzy submodelami
// samo pomijanie glBindTexture() nie poprawi wydajności

View File

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

View File

@@ -10,9 +10,8 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h"
#include "PyInt.h"
#include "Globals.h"
#include "dictionary.h"
#include "application.h"
#include "renderer.h"
#include "Logs.h"
#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 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
class render_task {

View File

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

View File

@@ -30,6 +30,7 @@ http://mozilla.org/MPL/2.0/.
#include "Console.h"
#include "application.h"
#include "renderer.h"
#include "dictionary.h"
/*
namespace input {
@@ -547,31 +548,8 @@ dictionary_source *TTrain::GetTrainState() {
dict->insert( "velnext", driver->VelNext );
dict->insert( "actualproximitydist", driver->ActualProximityDist );
// train data
auto const *timetable{ driver->TrainTimetable() };
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 );
}
}
driver->TrainTimetable()->serialize( dict );
dict->insert( "train_stationstart", driver->iStationStart );
dict->insert( "train_atpassengerstop", driver->IsAtPassengerStop );
// world state data
dict->insert( "scenario", Global.SceneryFile );
@@ -4152,7 +4130,7 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->Heating ) {
if( false == Train->mvControlled->HeatingAllow ) {
// turn on
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 ) {
if( Command.action == GLFW_PRESS ) {
Train->mvControlled->HeatingAllow = true;
// visual feedback
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 ) {
if( Command.action == GLFW_PRESS ) {
Train->mvControlled->HeatingAllow = false;
// visual feedback
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 );
btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ end::front ].is_active ) && ( mvControlled->MotorBlowers[ end::rear ].is_active ) );
btLampkaCoolingFans.Turn( mvControlled->RventRot > 1.0 );
btLampkaTempomat.Turn( mvControlled->ScndCtrlPos > 0 );
// universal devices state indicators
for( auto idx = 0; idx < btUniversals.size(); ++idx ) {
btUniversals[ idx ].Turn( ggUniversals[ idx ].GetValue() > 0.5 );
@@ -5772,6 +5747,7 @@ bool TTrain::Update( double const Deltatime )
btLampkaMalfunction.Turn( false );
btLampkaMotorBlowers.Turn( false );
btLampkaCoolingFans.Turn( false );
btLampkaTempomat.Turn( false );
// universal devices state indicators
for( auto &universal : btUniversals ) {
universal.Turn( false );
@@ -6011,7 +5987,6 @@ bool TTrain::Update( double const Deltatime )
//---------
// hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy
if( ( mvControlled->Heating == true )
&& ( mvControlled->Mains == true )
&& ( mvControlled->ConvOvldFlag == false ) )
btLampkaOgrzewanieSkladu.Turn( true );
else
@@ -7417,6 +7392,7 @@ void TTrain::clear_cab_controls()
btLampkaMalfunctionB.Clear();
btLampkaMotorBlowers.Clear();
btLampkaCoolingFans.Clear();
btLampkaTempomat.Clear();
ggLeftLightButton.Clear();
ggRightLightButton.Clear();
@@ -7762,6 +7738,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-vent_trim:", btLampkaWentZaluzje },
{ "i-motorblowers:", btLampkaMotorBlowers },
{ "i-coolingfans:", btLampkaCoolingFans },
{ "i-tempomat:", btLampkaTempomat },
{ "i-trainheating:", btLampkaOgrzewanieSkladu },
{ "i-security_aware:", btLampkaCzuwaka },
{ "i-security_cabsignal:", btLampkaSHP },

View File

@@ -584,6 +584,7 @@ public: // reszta może by?publiczna
TButton btLampkaMalfunctionB;
TButton btLampkaMotorBlowers;
TButton btLampkaCoolingFans;
TButton btLampkaTempomat;
TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine
// 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 "Globals.h"
#include "simulationtime.h"
#include "dictionary.h"
#include "utilities.h"
double TTrainParameters::CheckTrainLatency()
@@ -523,3 +524,29 @@ bool TTrainParameters::DirectionChange()
return true;
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 DirectionChange();
void StationIndexInc();
void serialize( dictionary_source *Output ) const;
};
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"