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

basic isolated track section hierarchy, track vertical radius property, ai passenger stop logic tweaks, ai signal speed limit tracking logic tweaks

This commit is contained in:
tmj-fstate
2018-09-11 23:17:59 +02:00
parent 251a31a705
commit d05e404d75
10 changed files with 140 additions and 91 deletions

View File

@@ -812,6 +812,8 @@ void TController::TableCheck(double fDistance)
} }
}; };
auto const passengerstopmaxdistance { 400.0 }; // maximum allowed distance between passenger stop point and consist head
TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fNext, double &fAcc) TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fNext, double &fAcc)
{ // ustalenie parametrów, zwraca typ komendy, jeśli sygnał podaje prędkość do jazdy { // ustalenie parametrów, zwraca typ komendy, jeśli sygnał podaje prędkość do jazdy
// fVelDes - prędkość zadana // fVelDes - prędkość zadana
@@ -826,14 +828,17 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
TCommandType go = TCommandType::cm_Unknown; TCommandType go = TCommandType::cm_Unknown;
eSignNext = NULL; eSignNext = NULL;
// te flagi są ustawiane tutaj, w razie potrzeby // te flagi są ustawiane tutaj, w razie potrzeby
iDrivigFlags &= ~(moveTrackEnd | moveSwitchFound | moveSemaphorFound | moveSpeedLimitFound); iDrivigFlags &= ~(moveTrackEnd | moveSwitchFound | moveSemaphorFound | /*moveSpeedLimitFound*/ moveStopPointFound );
for( std::size_t i = 0; i < sSpeedTable.size(); ++i ) for( std::size_t i = 0; i < sSpeedTable.size(); ++i )
{ // sprawdzenie rekordów od (iFirst) do (iLast), o ile są istotne { // sprawdzenie rekordów od (iFirst) do (iLast), o ile są istotne
if (sSpeedTable[i].iFlags & spEnabled) // badanie istotności if (sSpeedTable[i].iFlags & spEnabled) // badanie istotności
{ // o ile dana pozycja tabelki jest istotna { // o ile dana pozycja tabelki jest istotna
if (sSpeedTable[i].iFlags & spPassengerStopPoint) if (sSpeedTable[i].iFlags & spPassengerStopPoint) {
{ // jeśli przystanek, trzeba obsłużyć wg rozkładu // jeśli przystanek, trzeba obsłużyć wg rozkładu
iDrivigFlags |= moveStopPointFound;
// stop points are irrelevant when not in one of the basic modes
if( ( OrderCurrentGet() & ( Obey_train | Shunt ) ) == 0 ) { continue; }
// first 19 chars of the command is expected to be "PassengerStopPoint:" so we skip them // first 19 chars of the command is expected to be "PassengerStopPoint:" so we skip them
if ( ToLower(sSpeedTable[i].evEvent->CommandGet()).compare( 19, sizeof(asNextStop), ToLower(asNextStop)) != 0 ) if ( ToLower(sSpeedTable[i].evEvent->CommandGet()).compare( 19, sizeof(asNextStop), ToLower(asNextStop)) != 0 )
{ // jeśli nazwa nie jest zgodna { // jeśli nazwa nie jest zgodna
@@ -858,7 +863,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
{ // jeśli nie ma tu postoju { // jeśli nie ma tu postoju
sSpeedTable[i].fVelNext = -1; // maksymalna prędkość w tym miejscu sSpeedTable[i].fVelNext = -1; // maksymalna prędkość w tym miejscu
// przy 160km/h jedzie 44m/s, to da dokładność rzędu 5 sekund // przy 160km/h jedzie 44m/s, to da dokładność rzędu 5 sekund
if (sSpeedTable[i].fDist < 200.0) { if (sSpeedTable[i].fDist < passengerstopmaxdistance * 0.5 ) {
// zaliczamy posterunek w pewnej odległości przed (choć W4 nie zasłania już semafora) // zaliczamy posterunek w pewnej odległości przed (choć W4 nie zasłania już semafora)
#if LOGSTOPS #if LOGSTOPS
WriteLog( WriteLog(
@@ -880,8 +885,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
} // koniec obsługi przelotu na W4 } // koniec obsługi przelotu na W4
else { else {
// zatrzymanie na W4 // zatrzymanie na W4
if ( ( false == sSpeedTable[i].bMoved ) if ( false == sSpeedTable[i].bMoved ) {
&& ( ( OrderCurrentGet() & ( Obey_train | Shunt ) ) != 0 ) ) {
// potentially shift the stop point in accordance with its defined parameters // potentially shift the stop point in accordance with its defined parameters
/* /*
// https://rainsted.com/pl/Wersja/18.2.133#Okr.C4.99gi_dla_W4_i_W32 // https://rainsted.com/pl/Wersja/18.2.133#Okr.C4.99gi_dla_W4_i_W32
@@ -910,16 +914,17 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
} }
} }
isatpassengerstop = ( isatpassengerstop = (
( sSpeedTable[ i ].fDist <= passengerstopmaxdistance )
// Ra 2F1I: odległość plus długość pociągu musi być mniejsza od długości // Ra 2F1I: odległość plus długość pociągu musi być mniejsza od długości
// peronu, chyba że pociąg jest dłuższy, to wtedy minimalna. // peronu, chyba że pociąg jest dłuższy, to wtedy minimalna.
// jeśli długość peronu ((sSpeedTable[i].evEvent->ValueGet(2)) nie podana, // jeśli długość peronu ((sSpeedTable[i].evEvent->ValueGet(2)) nie podana,
// przyjąć odległość fMinProximityDist // przyjąć odległość fMinProximityDist
( iDrivigFlags & moveStopCloser ) ? && ( ( iDrivigFlags & moveStopCloser ) != 0 ?
( sSpeedTable[ i ].fDist + fLength ) <= sSpeedTable[ i ].fDist + fLength <=
std::max( std::max(
std::abs( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ), std::abs( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ),
2.0 * fMaxProximityDist + fLength ) : // fmaxproximitydist typically equals ~50 m 2.0 * fMaxProximityDist + fLength ) : // fmaxproximitydist typically equals ~50 m
sSpeedTable[ i ].fDist < d_to_next_sem ); sSpeedTable[ i ].fDist < d_to_next_sem ) );
if( !eSignNext ) { if( !eSignNext ) {
//jeśli nie widzi następnego sygnału ustawia dotychczasową //jeśli nie widzi następnego sygnału ustawia dotychczasową
@@ -928,8 +933,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if( mvOccupied->Vel > 0.3 ) { if( mvOccupied->Vel > 0.3 ) {
// jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie // jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie
sSpeedTable[ i ].fVelNext = 0; sSpeedTable[ i ].fVelNext = 0;
} } else if( true == isatpassengerstop ) {
else if( true == isatpassengerstop ) {
// jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4 // jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
if( !AIControllFlag ) { if( !AIControllFlag ) {
// w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko // w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko
@@ -1069,7 +1073,11 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
iDrivigFlags |= moveStopHere | moveStartHorn; iDrivigFlags |= moveStopHere | moveStartHorn;
continue; // nie analizować prędkości continue; // nie analizować prędkości
} // koniec obsługi ostatniej stacji } // koniec obsługi ostatniej stacji
} // if (MoverParameters->Vel==0.0) } // vel 0, at passenger stop
else {
// HACK: momentarily deactivate W4 to trick the controller into moving closer
sSpeedTable[ i ].fVelNext = -1;
} // vel 0, outside of passenger stop
} // koniec obsługi zatrzymania na W4 } // koniec obsługi zatrzymania na W4
} // koniec warunku pomijania W4 podczas zmiany czoła } // koniec warunku pomijania W4 podczas zmiany czoła
else else
@@ -1121,15 +1129,11 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if (sSpeedTable[i].iFlags & spOutsideStation) if (sSpeedTable[i].iFlags & spOutsideStation)
{ // jeśli W5, to reakcja zależna od trybu jazdy { // jeśli W5, to reakcja zależna od trybu jazdy
if (OrderCurrentGet() & Obey_train) if (OrderCurrentGet() & Obey_train)
{ // w trybie pociągowym: można przyspieszyć do wskazanej prędkości (po { // w trybie pociągowym: można przyspieszyć do wskazanej prędkości (po zjechaniu z rozjazdów)
// zjechaniu z rozjazdów)
v = -1.0; // ignorować? v = -1.0; // ignorować?
//TODO trzeba zmienić przypisywanie VelSignal na VelSignalLast
if (sSpeedTable[i].fDist < 0.0) // jeśli wskaźnik został minięty if (sSpeedTable[i].fDist < 0.0) // jeśli wskaźnik został minięty
{ {
VelSignalLast = v; //ustawienie prędkości na -1 VelSignalLast = v; //ustawienie prędkości na -1
// iStationStart=TrainParams->StationIndex; //zaktualizować
// wyświetlanie rozkładu
} }
else if (!(iDrivigFlags & moveSwitchFound)) // jeśli rozjazdy już minięte else if (!(iDrivigFlags & moveSwitchFound)) // jeśli rozjazdy już minięte
VelSignalLast = v; //!!! to też koniec ograniczenia VelSignalLast = v; //!!! to też koniec ograniczenia
@@ -1174,7 +1178,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
else else
{ {
iDrivigFlags |= moveSemaphorFound; //jeśli z przodu to dajemy falgę, że jest iDrivigFlags |= moveSemaphorFound; //jeśli z przodu to dajemy falgę, że jest
d_to_next_sem = Min0R(sSpeedTable[i].fDist, d_to_next_sem); d_to_next_sem = std::min(sSpeedTable[i].fDist, d_to_next_sem);
} }
if( sSpeedTable[ i ].fDist <= d_to_next_sem ) if( sSpeedTable[ i ].fDist <= d_to_next_sem )
{ {
@@ -1338,7 +1342,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
&& ( true == TestFlag( sSpeedTable[ i ].iFlags, ( spEnabled | spEvent | spPassengerStopPoint ) ) ) && ( true == TestFlag( sSpeedTable[ i ].iFlags, ( spEnabled | spEvent | spPassengerStopPoint ) ) )
&& ( false == isatpassengerstop ) ) { && ( false == isatpassengerstop ) ) {
// ma podjechać bliżej - czy na pewno w tym miejscu taki warunek? // ma podjechać bliżej - czy na pewno w tym miejscu taki warunek?
a = ( ( ( iDrivigFlags & moveStopCloser ) != 0 ) ? a = ( ( d > passengerstopmaxdistance ) || ( ( iDrivigFlags & moveStopCloser ) != 0 ) ?
fAcc : fAcc :
0.0 ); 0.0 );
} }
@@ -1409,9 +1413,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
} // if (sSpeedTable[i].iFlags&1) } // if (sSpeedTable[i].iFlags&1)
} // for } // for
if (VelSignalLast >= 0.0 && !(iDrivigFlags & (moveSemaphorFound | moveSwitchFound)) && // jeśli mieliśmy ograniczenie z semafora i nie ma przed nami
(OrderCurrentGet() & Obey_train)) if( ( VelSignalLast >= 0.0 )
VelSignalLast = -1.0; // jeśli mieliśmy ograniczenie z semafora i nie ma przed nami && ( ( iDrivigFlags & ( moveSemaphorFound | moveSwitchFound | moveStopPointFound ) ) == 0 )
&& ( true == TestFlag( OrderCurrentGet(), Obey_train ) ) ) {
VelSignalLast = -1.0;
}
//analiza spisanych z tabelki ograniczeń i nadpisanie aktualnego //analiza spisanych z tabelki ograniczeń i nadpisanie aktualnego
if( ( true == isatpassengerstop ) && ( mvOccupied->Vel < 0.01 ) ) { if( ( true == isatpassengerstop ) && ( mvOccupied->Vel < 0.01 ) ) {
@@ -2562,8 +2569,9 @@ bool TController::ReleaseEngine() {
eAction = TAction::actSleep; //śpi (wygaszony) eAction = TAction::actSleep; //śpi (wygaszony)
OrderNext(Wait_for_orders); //żeby nie próbował coś robić dalej OrderNext(Wait_for_orders); //żeby nie próbował coś robić dalej
TableClear(); // zapominamy ograniczenia
iDrivigFlags &= ~moveActive; // ma nie skanować sygnałów i nie reagować na komendy iDrivigFlags &= ~moveActive; // ma nie skanować sygnałów i nie reagować na komendy
TableClear(); // zapominamy ograniczenia
VelSignalLast = -1.0;
} }
return OK; return OK;
} }
@@ -3332,10 +3340,10 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
iStationStart = TrainParams->StationIndex; iStationStart = TrainParams->StationIndex;
asNextStop = TrainParams->NextStop(); asNextStop = TrainParams->NextStop();
iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym
NewCommand = Global.asCurrentSceneryPath + NewCommand; // NewCommand = Global.asCurrentSceneryPath + NewCommand;
auto lookup = auto lookup =
FileExists( FileExists(
{ NewCommand }, { Global.asCurrentSceneryPath + NewCommand, szSoundPath + NewCommand },
{ ".ogg", ".flac", ".wav" } ); { ".ogg", ".flac", ".wav" } );
if( false == lookup.first.empty() ) { if( false == lookup.first.empty() ) {
// wczytanie dźwięku odjazdu podawanego bezpośrenido // wczytanie dźwięku odjazdu podawanego bezpośrenido
@@ -3343,9 +3351,10 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
iGuardRadio = 0; // nie przez radio iGuardRadio = 0; // nie przez radio
} }
else { else {
NewCommand += "radio";
auto lookup = auto lookup =
FileExists( FileExists(
{ NewCommand + "radio" }, { Global.asCurrentSceneryPath + NewCommand, szSoundPath + NewCommand },
{ ".ogg", ".flac", ".wav" } ); { ".ogg", ".flac", ".wav" } );
if( false == lookup.first.empty() ) { if( false == lookup.first.empty() ) {
// wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie) // wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie)
@@ -4051,10 +4060,12 @@ TController::UpdateSituation(double dt) {
} }
*/ */
// route scan // route scan
double routescanrange = ( auto const routescanrange {
std::max(
750.0,
mvOccupied->Vel > 5.0 ? mvOccupied->Vel > 5.0 ?
400 + fBrakeDist : 400 + fBrakeDist :
30.0 * fDriverDist ); // 1500m dla stojących pociągów; 30.0 * fDriverDist ) }; // 1500m dla stojących pociągów;
// Ra 2015-01: przy dłuższej drodze skanowania AI jeździ spokojniej // Ra 2015-01: przy dłuższej drodze skanowania AI jeździ spokojniej
// 2. Sprawdzić, czy tabelka pokrywa założony odcinek (nie musi, jeśli jest STOP). // 2. Sprawdzić, czy tabelka pokrywa założony odcinek (nie musi, jeśli jest STOP).
// 3. Sprawdzić, czy trajektoria ruchu przechodzi przez zwrotnice - jeśli tak, to sprawdzić, // 3. Sprawdzić, czy trajektoria ruchu przechodzi przez zwrotnice - jeśli tak, to sprawdzić,

View File

@@ -52,9 +52,12 @@ enum TMovementStatus
moveDoorOpened = 0x20000, // drzwi zostały otwarte - doliczyć czas na zamknięcie moveDoorOpened = 0x20000, // drzwi zostały otwarte - doliczyć czas na zamknięcie
movePushPull = 0x40000, // zmiana czoła przez zmianę kabiny - nie odczepiać przy zmianie kierunku movePushPull = 0x40000, // zmiana czoła przez zmianę kabiny - nie odczepiać przy zmianie kierunku
moveSemaphorFound = 0x80000, // na drodze skanowania został znaleziony semafor moveSemaphorFound = 0x80000, // na drodze skanowania został znaleziony semafor
moveStopPointFound = 0x100000 // stop point detected ahead
/*
moveSemaphorWasElapsed = 0x100000, // minięty został semafor moveSemaphorWasElapsed = 0x100000, // minięty został semafor
moveTrainInsideStation = 0x200000, // pociąg między semaforem a rozjazdami lub następnym semaforem moveTrainInsideStation = 0x200000, // pociąg między semaforem a rozjazdami lub następnym semaforem
moveSpeedLimitFound = 0x400000 // pociąg w ograniczeniu z podaną jego długością moveSpeedLimitFound = 0x400000 // pociąg w ograniczeniu z podaną jego długością
*/
}; };
enum TStopReason enum TStopReason

View File

@@ -68,12 +68,12 @@ TSwitchExtension::TSwitchExtension(TTrack *owner, int const what)
TSwitchExtension::~TSwitchExtension() TSwitchExtension::~TSwitchExtension()
{ // nie ma nic do usuwania { // nie ma nic do usuwania
} }
/*
TIsolated::TIsolated() TIsolated::TIsolated()
{ // utworznie pustego { // utworznie pustego
TIsolated("none", NULL); TIsolated("none", NULL);
}; };
*/
TIsolated::TIsolated(std::string const &n, TIsolated *i) : TIsolated::TIsolated(std::string const &n, TIsolated *i) :
asName( n ), pNext( i ) asName( n ), pNext( i )
{ {
@@ -102,6 +102,15 @@ TIsolated * TIsolated::Find(std::string const &n)
return pRoot; return pRoot;
}; };
bool
TIsolated::AssignEvents() {
evBusy = simulation::Events.FindEvent( asName + ":busy" );
evFree = simulation::Events.FindEvent( asName + ":free" );
return ( evBusy != nullptr ) && ( evFree != nullptr );
}
void TIsolated::Modify(int i, TDynamicObject *o) void TIsolated::Modify(int i, TDynamicObject *o)
{ // dodanie lub odjęcie osi { // dodanie lub odjęcie osi
if (iAxles) if (iAxles)
@@ -131,6 +140,10 @@ void TIsolated::Modify(int i, TDynamicObject *o)
pMemCell->UpdateValues( "", 0, int( pMemCell->Value2() ) | 1, update_memval2 ); // zmieniamy ostatnią wartość na nieparzystą pMemCell->UpdateValues( "", 0, int( pMemCell->Value2() ) | 1, update_memval2 ); // zmieniamy ostatnią wartość na nieparzystą
} }
} }
// pass the event to the parent
if( pParent != nullptr ) {
pParent->Modify( i, o );
}
}; };
// tworzenie nowego odcinka ruchu // tworzenie nowego odcinka ruchu
@@ -851,6 +864,12 @@ void TTrack::Load(cParser *parser, glm::dvec3 const &pOrigin)
iAction |= 0x40; // flaga opuszczenia pantografu (tor uwzględniany w skanowaniu jako iAction |= 0x40; // flaga opuszczenia pantografu (tor uwzględniany w skanowaniu jako
// ograniczenie dla pantografujących) // ograniczenie dla pantografujących)
} }
else if( str == "vradius" ) {
// y-axis track radius
// NOTE: not used/implemented
parser->getTokens();
*parser >> fVerticalRadius;
}
else else
ErrorLog("Unknown property: \"" + str + "\" in track \"" + m_name + "\""); ErrorLog("Unknown property: \"" + str + "\" in track \"" + m_name + "\"");
parser->getTokens(); parser->getTokens();
@@ -954,19 +973,6 @@ std::string TTrack::IsolatedName()
return ""; return "";
}; };
bool TTrack::IsolatedEventsAssign(TEvent *busy, TEvent *free)
{ // ustawia zdarzenia dla odcinka izolowanego
if (pIsolated)
{
if (busy)
pIsolated->evBusy = busy;
if (free)
pIsolated->evFree = free;
return true;
}
return false;
};
// ABu: przeniesione z Path.h i poprawione!!! // ABu: przeniesione z Path.h i poprawione!!!
bool TTrack::AddDynamicObject(TDynamicObject *Dynamic) bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
{ // dodanie pojazdu do trajektorii { // dodanie pojazdu do trajektorii
@@ -2828,11 +2834,14 @@ TTrack::export_as_text_( std::ostream &Output ) const {
for( auto &eventsequence : eventsequences ) { for( auto &eventsequence : eventsequences ) {
for( auto &event : *( eventsequence.second ) ) { for( auto &event : *( eventsequence.second ) ) {
if( false == event.first.empty() ) { // NOTE: actual event name can be potentially different from its cached name, if it was renamed in the editor
// therefore on export we pull the name from the event itself, if the binding isn't broken
Output Output
<< eventsequence.first << ' ' << eventsequence.first << ' '
<< event.first << ' '; << ( event.second != nullptr ?
} event.second->asName :
event.first )
<< ' ';
} }
} }
if( ( SwitchExtension ) if( ( SwitchExtension )
@@ -2850,6 +2859,9 @@ TTrack::export_as_text_( std::ostream &Output ) const {
if( fOverhead != -1.0 ) { if( fOverhead != -1.0 ) {
Output << "overhead " << fOverhead << ' '; Output << "overhead " << fOverhead << ' ';
} }
if( fVerticalRadius != 0.f ) {
Output << "vradius " << fVerticalRadius << ' ';
}
// footer // footer
Output Output
<< "endtrack" << "endtrack"
@@ -3091,15 +3103,6 @@ path_table::InitTracks() {
} }
} // switch } // switch
// pobranie nazwy odcinka izolowanego
auto const isolatedname { track->IsolatedName() };
if( false == isolatedname.empty() ) {
// jeśli została zwrócona nazwa
track->IsolatedEventsAssign(
simulation::Events.FindEvent( isolatedname + ":busy" ),
simulation::Events.FindEvent( isolatedname + ":free" ) );
}
if( ( trackname[ 0 ] == '*' ) if( ( trackname[ 0 ] == '*' )
&& ( !track->CurrentPrev() && track->CurrentNext() ) ) { && ( !track->CurrentPrev() && track->CurrentNext() ) ) {
// możliwy portal, jeśli nie podłączony od strony 1 // możliwy portal, jeśli nie podłączony od strony 1
@@ -3108,25 +3111,25 @@ path_table::InitTracks() {
} }
} }
TIsolated *isolated = TIsolated::Root(); auto *isolated = TIsolated::Root();
while( isolated ) { while( isolated ) {
// jeśli się znajdzie, to podać wskaźnik
isolated->AssignEvents();
auto *memorycell = simulation::Memory.find( isolated->asName ); // czy jest komóka o odpowiedniej nazwie auto *memorycell = simulation::Memory.find( isolated->asName ); // czy jest komóka o odpowiedniej nazwie
if( memorycell != nullptr ) { if( memorycell == nullptr ) {
// przypisanie powiązanej komórki
isolated->pMemCell = memorycell;
}
else {
// utworzenie automatycznej komórki // utworzenie automatycznej komórki
// TODO: determine suitable location for this one, create and add world reference node // TODO: determine suitable location for this one, create and add world reference node
scene::node_data nodedata; scene::node_data nodedata;
nodedata.name = isolated->asName; nodedata.name = isolated->asName;
auto *memorycell = new TMemCell( nodedata ); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy memorycell = new TMemCell( nodedata ); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy
// NOTE: autogenerated cells aren't exported; they'll be autogenerated anew when exported file is loaded // NOTE: autogenerated cells aren't exported; they'll be autogenerated anew when exported file is loaded
memorycell->is_exportable = false; memorycell->is_exportable = false;
simulation::Memory.insert( memorycell ); simulation::Memory.insert( memorycell );
isolated->pMemCell = memorycell; // wskaźnik komóki przekazany do odcinka izolowanego
} }
// przypisanie powiązanej komórki
isolated->pMemCell = memorycell;
isolated = isolated->Next(); isolated = isolated->Next();
} }
} }

25
Track.h
View File

@@ -99,18 +99,32 @@ class TIsolated
{ // obiekt zbierający zajętości z kilku odcinków { // obiekt zbierający zajętości z kilku odcinków
public: public:
// constructors // constructors
TIsolated();
TIsolated(const std::string &n, TIsolated *i); TIsolated(const std::string &n, TIsolated *i);
// methods // methods
static void DeleteAll(); static void DeleteAll();
static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego
bool AssignEvents();
void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi
bool Busy() { inline
bool
Busy() {
return (iAxles > 0); }; return (iAxles > 0); };
static TIsolated * Root() { inline
static TIsolated *
Root() {
return (pRoot); }; return (pRoot); };
TIsolated * Next() { inline
TIsolated *
Next() {
return (pNext); }; return (pNext); };
inline
void
parent( TIsolated *Parent ) {
pParent = Parent; }
inline
TIsolated *
parent() const {
return pParent; }
// members // members
std::string asName; // nazwa obiektu, baza do nazw eventów std::string asName; // nazwa obiektu, baza do nazw eventów
TEvent *evBusy { nullptr }; // zdarzenie wyzwalane po zajęciu grupy TEvent *evBusy { nullptr }; // zdarzenie wyzwalane po zajęciu grupy
@@ -120,6 +134,7 @@ private:
// members // members
int iAxles { 0 }; // ilość osi na odcinkach obsługiwanych przez obiekt int iAxles { 0 }; // ilość osi na odcinkach obsługiwanych przez obiekt
TIsolated *pNext { nullptr }; // odcinki izolowane są trzymane w postaci listy jednikierunkowej TIsolated *pNext { nullptr }; // odcinki izolowane są trzymane w postaci listy jednikierunkowej
TIsolated *pParent { nullptr }; // optional parent piece, collecting data from its children
static TIsolated *pRoot; // początek listy static TIsolated *pRoot; // początek listy
}; };
@@ -140,6 +155,7 @@ private:
// McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur // McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur
int iTrapezoid = 0; // 0-standard, 1-przechyłka, 2-trapez, 3-oba int iTrapezoid = 0; // 0-standard, 1-przechyłka, 2-trapez, 3-oba
double fRadiusTable[ 2 ] = { 0.0, 0.0 }; // dwa promienie, drugi dla zwrotnicy double fRadiusTable[ 2 ] = { 0.0, 0.0 }; // dwa promienie, drugi dla zwrotnicy
float fVerticalRadius { 0.f }; // y-axis track radius (currently not supported)
float fTexLength = 4.0f; // długość powtarzania tekstury w metrach float fTexLength = 4.0f; // długość powtarzania tekstury w metrach
float fTexRatio1 = 1.0f; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...) float fTexRatio1 = 1.0f; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...)
float fTexRatio2 = 1.0f; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...) float fTexRatio2 = 1.0f; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...)
@@ -265,7 +281,6 @@ public:
if (pIsolated) if (pIsolated)
pIsolated->Modify(i, o); }; // dodanie lub odjęcie osi pIsolated->Modify(i, o); }; // dodanie lub odjęcie osi
std::string IsolatedName(); std::string IsolatedName();
bool IsolatedEventsAssign(TEvent *busy, TEvent *free);
double WidthTotal(); double WidthTotal();
bool IsGroupable(); bool IsGroupable();
int TestPoint( Math3D::vector3 *Point); int TestPoint( Math3D::vector3 *Point);

View File

@@ -253,7 +253,8 @@ timetable_panel::update() {
auto const candeparture = ( auto const candeparture = (
( owner->iStationStart < table->StationIndex ) ( owner->iStationStart < table->StationIndex )
&& ( i < table->StationIndex ) && ( i < table->StationIndex )
&& ( ( time.wHour * 60 + time.wMinute ) >= ( tableline->Dh * 60 + tableline->Dm ) ) ); && ( ( tableline->Ah < 0 ) // pass-through, always valid
|| ( time.wHour * 60 + time.wMinute >= tableline->Dh * 60 + tableline->Dm ) ) );
auto traveltime = auto traveltime =
" " " "
+ ( i < 2 ? "" : + ( i < 2 ? "" :
@@ -726,7 +727,7 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
textline = textline =
"Acceleration:\n desired: " + to_string( mechanik.AccDesired, 2 ) "Acceleration:\n desired: " + to_string( mechanik.AccDesired, 2 )
+ ", corrected: " + to_string( mechanik.AccDesired * mechanik.BrakeAccFactor(), 2 ) + ", corrected: " + to_string( mechanik.AccDesired * mechanik.BrakeAccFactor(), 2 )
+ "\n current: " + to_string( mechanik.AbsAccS_pub, 2 ) + "\n current: " + to_string( mechanik.AbsAccS_pub + 0.001f, 2 )
+ ", slope: " + to_string( mechanik.fAccGravity + 0.001f, 2 ) + " (" + ( mechanik.fAccGravity > 0.01 ? "\\" : ( mechanik.fAccGravity < -0.01 ? "/" : "-" ) ) + ")" + ", slope: " + to_string( mechanik.fAccGravity + 0.001f, 2 ) + " (" + ( mechanik.fAccGravity > 0.01 ? "\\" : ( mechanik.fAccGravity < -0.01 ? "/" : "-" ) ) + ")"
+ "\n brake threshold: " + to_string( mechanik.fAccThreshold, 2 ) + "\n brake threshold: " + to_string( mechanik.fAccThreshold, 2 )
+ ", delays: " + to_string( mechanik.fBrake_a0[ 0 ], 2 ) + ", delays: " + to_string( mechanik.fBrake_a0[ 0 ], 2 )
@@ -744,7 +745,7 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
std::vector<std::string> const drivingflagnames { std::vector<std::string> const drivingflagnames {
"StopCloser", "StopPoint", "Active", "Press", "Connect", "Primary", "Late", "StopHere", "StopCloser", "StopPoint", "Active", "Press", "Connect", "Primary", "Late", "StopHere",
"StartHorn", "StartHornNow", "StartHornDone", "Oerlikons", "IncSpeed", "TrackEnd", "SwitchFound", "GuardSignal", "StartHorn", "StartHornNow", "StartHornDone", "Oerlikons", "IncSpeed", "TrackEnd", "SwitchFound", "GuardSignal",
"Visibility", "DoorOpened", "PushPull", "SemaphorFound", "SemaphorWasElapsed", "TrainInsideStation", "SpeedLimitFound" }; "Visibility", "DoorOpened", "PushPull", "SemaphorFound", "StopPointFound" /*"SemaphorWasElapsed", "TrainInsideStation", "SpeedLimitFound"*/ };
textline = "Driving flags:"; textline = "Driving flags:";
for( int idx = 0, flagbit = 1; idx < drivingflagnames.size(); ++idx, flagbit <<= 1 ) { for( int idx = 0, flagbit = 1; idx < drivingflagnames.size(); ++idx, flagbit <<= 1 ) {

View File

@@ -147,7 +147,7 @@ itemproperties_panel::update( scene::basic_node const *Node ) {
textline += ", "; textline += ", ";
} }
textline += ( textline += (
event.second ? event.second != nullptr ?
event.second->asName : event.second->asName :
event.first + " (missing)" ); event.first + " (missing)" );
} }

View File

@@ -196,7 +196,7 @@ std::string cParser::readToken( bool ToLower, const char *Break ) {
// update line counter // update line counter
++mLine; ++mLine;
} }
} while( token == "" && mStream->peek() != EOF ); // double check to deal with trailing spaces } while( token == "" && mStream->peek() != EOF ); // double check in case of consecutive separators
} }
if( false == parameters.empty() ) { if( false == parameters.empty() ) {

View File

@@ -67,6 +67,7 @@ state_serializer::deserialize( cParser &Input, scene::scratch_data &Scratchpad )
std::pair< std::pair<
std::string, std::string,
deserializefunction> > functionlist = { deserializefunction> > functionlist = {
{ "area", &state_serializer::deserialize_area },
{ "atmo", &state_serializer::deserialize_atmo }, { "atmo", &state_serializer::deserialize_atmo },
{ "camera", &state_serializer::deserialize_camera }, { "camera", &state_serializer::deserialize_camera },
{ "config", &state_serializer::deserialize_config }, { "config", &state_serializer::deserialize_config },
@@ -125,6 +126,20 @@ state_serializer::deserialize( cParser &Input, scene::scratch_data &Scratchpad )
} }
} }
void
state_serializer::deserialize_area( cParser &Input, scene::scratch_data &Scratchpad ) {
// first parameter specifies name of parent piece...
auto token { Input.getToken<std::string>() };
auto *groupowner { TIsolated::Find( token ) };
// ...followed by list of its children
while( ( false == ( token = Input.getToken<std::string>() ).empty() )
&& ( token != "endarea" ) ) {
// bind the children with their parent
auto *isolated { TIsolated::Find( token ) };
isolated->parent( groupowner );
}
}
void void
state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ) { state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ) {

View File

@@ -29,6 +29,7 @@ private:
// methods // methods
// restores class data from provided stream // restores class data from provided stream
void deserialize( cParser &Input, scene::scratch_data &Scratchpad ); void deserialize( cParser &Input, scene::scratch_data &Scratchpad );
void deserialize_area( cParser &Input, scene::scratch_data &Scratchpad );
void deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ); void deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad );
void deserialize_camera( cParser &Input, scene::scratch_data &Scratchpad ); void deserialize_camera( cParser &Input, scene::scratch_data &Scratchpad );
void deserialize_config( cParser &Input, scene::scratch_data &Scratchpad ); void deserialize_config( cParser &Input, scene::scratch_data &Scratchpad );

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 18 #define VERSION_MAJOR 18
#define VERSION_MINOR 909 #define VERSION_MINOR 911
#define VERSION_REVISION 0 #define VERSION_REVISION 0