mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01: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:
77
Driver.cpp
77
Driver.cpp
@@ -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)
|
||||
{ // ustalenie parametrów, zwraca typ komendy, jeśli sygnał podaje prędkość do jazdy
|
||||
// fVelDes - prędkość zadana
|
||||
@@ -826,14 +828,17 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
TCommandType go = TCommandType::cm_Unknown;
|
||||
eSignNext = NULL;
|
||||
// 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 )
|
||||
{ // sprawdzenie rekordów od (iFirst) do (iLast), o ile są istotne
|
||||
if (sSpeedTable[i].iFlags & spEnabled) // badanie istotności
|
||||
{ // o ile dana pozycja tabelki jest istotna
|
||||
if (sSpeedTable[i].iFlags & spPassengerStopPoint)
|
||||
{ // jeśli przystanek, trzeba obsłużyć wg rozkładu
|
||||
if (sSpeedTable[i].iFlags & spPassengerStopPoint) {
|
||||
// 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
|
||||
if ( ToLower(sSpeedTable[i].evEvent->CommandGet()).compare( 19, sizeof(asNextStop), ToLower(asNextStop)) != 0 )
|
||||
{ // 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
|
||||
sSpeedTable[i].fVelNext = -1; // maksymalna prędkość w tym miejscu
|
||||
// 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)
|
||||
#if LOGSTOPS
|
||||
WriteLog(
|
||||
@@ -880,8 +885,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
} // koniec obsługi przelotu na W4
|
||||
else {
|
||||
// zatrzymanie na W4
|
||||
if ( ( false == sSpeedTable[i].bMoved )
|
||||
&& ( ( OrderCurrentGet() & ( Obey_train | Shunt ) ) != 0 ) ) {
|
||||
if ( false == sSpeedTable[i].bMoved ) {
|
||||
// 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
|
||||
@@ -910,16 +914,17 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
}
|
||||
}
|
||||
isatpassengerstop = (
|
||||
( sSpeedTable[ i ].fDist <= passengerstopmaxdistance )
|
||||
// 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.
|
||||
// jeśli długość peronu ((sSpeedTable[i].evEvent->ValueGet(2)) nie podana,
|
||||
// przyjąć odległość fMinProximityDist
|
||||
( iDrivigFlags & moveStopCloser ) ?
|
||||
( sSpeedTable[ i ].fDist + fLength ) <=
|
||||
std::max(
|
||||
std::abs( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ),
|
||||
2.0 * fMaxProximityDist + fLength ) : // fmaxproximitydist typically equals ~50 m
|
||||
sSpeedTable[ i ].fDist < d_to_next_sem );
|
||||
&& ( ( iDrivigFlags & moveStopCloser ) != 0 ?
|
||||
sSpeedTable[ i ].fDist + fLength <=
|
||||
std::max(
|
||||
std::abs( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ),
|
||||
2.0 * fMaxProximityDist + fLength ) : // fmaxproximitydist typically equals ~50 m
|
||||
sSpeedTable[ i ].fDist < d_to_next_sem ) );
|
||||
|
||||
if( !eSignNext ) {
|
||||
//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 ) {
|
||||
// jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie
|
||||
sSpeedTable[ i ].fVelNext = 0;
|
||||
}
|
||||
else if( true == isatpassengerstop ) {
|
||||
} else if( true == isatpassengerstop ) {
|
||||
// jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
|
||||
if( !AIControllFlag ) {
|
||||
// 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;
|
||||
continue; // nie analizować prędkości
|
||||
} // 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 warunku pomijania W4 podczas zmiany czoła
|
||||
else
|
||||
@@ -1121,15 +1129,11 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
if (sSpeedTable[i].iFlags & spOutsideStation)
|
||||
{ // jeśli W5, to reakcja zależna od trybu jazdy
|
||||
if (OrderCurrentGet() & Obey_train)
|
||||
{ // w trybie pociągowym: można przyspieszyć do wskazanej prędkości (po
|
||||
// zjechaniu z rozjazdów)
|
||||
{ // w trybie pociągowym: można przyspieszyć do wskazanej prędkości (po zjechaniu z rozjazdów)
|
||||
v = -1.0; // ignorować?
|
||||
//TODO trzeba zmienić przypisywanie VelSignal na VelSignalLast
|
||||
if (sSpeedTable[i].fDist < 0.0) // jeśli wskaźnik został minięty
|
||||
{
|
||||
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
|
||||
VelSignalLast = v; //!!! to też koniec ograniczenia
|
||||
@@ -1174,7 +1178,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
else
|
||||
{
|
||||
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 )
|
||||
{
|
||||
@@ -1338,7 +1342,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
&& ( true == TestFlag( sSpeedTable[ i ].iFlags, ( spEnabled | spEvent | spPassengerStopPoint ) ) )
|
||||
&& ( false == isatpassengerstop ) ) {
|
||||
// ma podjechać bliżej - czy na pewno w tym miejscu taki warunek?
|
||||
a = ( ( ( iDrivigFlags & moveStopCloser ) != 0 ) ?
|
||||
a = ( ( d > passengerstopmaxdistance ) || ( ( iDrivigFlags & moveStopCloser ) != 0 ) ?
|
||||
fAcc :
|
||||
0.0 );
|
||||
}
|
||||
@@ -1409,9 +1413,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
} // if (sSpeedTable[i].iFlags&1)
|
||||
} // for
|
||||
|
||||
if (VelSignalLast >= 0.0 && !(iDrivigFlags & (moveSemaphorFound | moveSwitchFound)) &&
|
||||
(OrderCurrentGet() & Obey_train))
|
||||
VelSignalLast = -1.0; // jeśli mieliśmy ograniczenie z semafora i nie ma przed nami
|
||||
// jeśli mieliśmy ograniczenie z semafora i nie ma przed nami
|
||||
if( ( VelSignalLast >= 0.0 )
|
||||
&& ( ( iDrivigFlags & ( moveSemaphorFound | moveSwitchFound | moveStopPointFound ) ) == 0 )
|
||||
&& ( true == TestFlag( OrderCurrentGet(), Obey_train ) ) ) {
|
||||
VelSignalLast = -1.0;
|
||||
}
|
||||
|
||||
//analiza spisanych z tabelki ograniczeń i nadpisanie aktualnego
|
||||
if( ( true == isatpassengerstop ) && ( mvOccupied->Vel < 0.01 ) ) {
|
||||
@@ -2562,8 +2569,9 @@ bool TController::ReleaseEngine() {
|
||||
eAction = TAction::actSleep; //śpi (wygaszony)
|
||||
|
||||
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
|
||||
TableClear(); // zapominamy ograniczenia
|
||||
VelSignalLast = -1.0;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
@@ -3332,10 +3340,10 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
||||
iStationStart = TrainParams->StationIndex;
|
||||
asNextStop = TrainParams->NextStop();
|
||||
iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym
|
||||
NewCommand = Global.asCurrentSceneryPath + NewCommand;
|
||||
// NewCommand = Global.asCurrentSceneryPath + NewCommand;
|
||||
auto lookup =
|
||||
FileExists(
|
||||
{ NewCommand },
|
||||
{ Global.asCurrentSceneryPath + NewCommand, szSoundPath + NewCommand },
|
||||
{ ".ogg", ".flac", ".wav" } );
|
||||
if( false == lookup.first.empty() ) {
|
||||
// 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
|
||||
}
|
||||
else {
|
||||
NewCommand += "radio";
|
||||
auto lookup =
|
||||
FileExists(
|
||||
{ NewCommand + "radio" },
|
||||
{ Global.asCurrentSceneryPath + NewCommand, szSoundPath + NewCommand },
|
||||
{ ".ogg", ".flac", ".wav" } );
|
||||
if( false == lookup.first.empty() ) {
|
||||
// wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie)
|
||||
@@ -4051,10 +4060,12 @@ TController::UpdateSituation(double dt) {
|
||||
}
|
||||
*/
|
||||
// route scan
|
||||
double routescanrange = (
|
||||
mvOccupied->Vel > 5.0 ?
|
||||
400 + fBrakeDist :
|
||||
30.0 * fDriverDist ); // 1500m dla stojących pociągów;
|
||||
auto const routescanrange {
|
||||
std::max(
|
||||
750.0,
|
||||
mvOccupied->Vel > 5.0 ?
|
||||
400 + fBrakeDist :
|
||||
30.0 * fDriverDist ) }; // 1500m dla stojących pociągów;
|
||||
// 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).
|
||||
// 3. Sprawdzić, czy trajektoria ruchu przechodzi przez zwrotnice - jeśli tak, to sprawdzić,
|
||||
|
||||
3
Driver.h
3
Driver.h
@@ -52,9 +52,12 @@ enum TMovementStatus
|
||||
moveDoorOpened = 0x20000, // drzwi zostały otwarte - doliczyć czas na zamknięcie
|
||||
movePushPull = 0x40000, // zmiana czoła przez zmianę kabiny - nie odczepiać przy zmianie kierunku
|
||||
moveSemaphorFound = 0x80000, // na drodze skanowania został znaleziony semafor
|
||||
moveStopPointFound = 0x100000 // stop point detected ahead
|
||||
/*
|
||||
moveSemaphorWasElapsed = 0x100000, // minięty został semafor
|
||||
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ą
|
||||
*/
|
||||
};
|
||||
|
||||
enum TStopReason
|
||||
|
||||
89
Track.cpp
89
Track.cpp
@@ -68,12 +68,12 @@ TSwitchExtension::TSwitchExtension(TTrack *owner, int const what)
|
||||
TSwitchExtension::~TSwitchExtension()
|
||||
{ // nie ma nic do usuwania
|
||||
}
|
||||
|
||||
/*
|
||||
TIsolated::TIsolated()
|
||||
{ // utworznie pustego
|
||||
TIsolated("none", NULL);
|
||||
};
|
||||
|
||||
*/
|
||||
TIsolated::TIsolated(std::string const &n, TIsolated *i) :
|
||||
asName( n ), pNext( i )
|
||||
{
|
||||
@@ -102,6 +102,15 @@ TIsolated * TIsolated::Find(std::string const &n)
|
||||
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)
|
||||
{ // dodanie lub odjęcie osi
|
||||
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ą
|
||||
}
|
||||
}
|
||||
// pass the event to the parent
|
||||
if( pParent != nullptr ) {
|
||||
pParent->Modify( i, o );
|
||||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
// ograniczenie dla pantografujących)
|
||||
}
|
||||
else if( str == "vradius" ) {
|
||||
// y-axis track radius
|
||||
// NOTE: not used/implemented
|
||||
parser->getTokens();
|
||||
*parser >> fVerticalRadius;
|
||||
}
|
||||
else
|
||||
ErrorLog("Unknown property: \"" + str + "\" in track \"" + m_name + "\"");
|
||||
parser->getTokens();
|
||||
@@ -954,19 +973,6 @@ std::string TTrack::IsolatedName()
|
||||
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!!!
|
||||
bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
|
||||
{ // dodanie pojazdu do trajektorii
|
||||
@@ -2764,7 +2770,7 @@ TTrack::export_as_text_( std::ostream &Output ) const {
|
||||
eEnvironment == e_canyon ? "canyon" :
|
||||
eEnvironment == e_mountains ? "mountains" :
|
||||
"none" )
|
||||
<< ' ';
|
||||
<< ' ';
|
||||
// visibility
|
||||
// NOTE: 'invis' would be less wrong than 'unvis', but potentially incompatible with old 3rd party tools
|
||||
Output << ( m_visible ? "vis" : "unvis" ) << ' ';
|
||||
@@ -2772,8 +2778,8 @@ TTrack::export_as_text_( std::ostream &Output ) const {
|
||||
// texture parameters are supplied only if the path is set as visible
|
||||
auto texturefile { (
|
||||
m_material1 != null_handle ?
|
||||
GfxRenderer.Material( m_material1 ).name :
|
||||
"none" ) };
|
||||
GfxRenderer.Material( m_material1 ).name :
|
||||
"none" ) };
|
||||
if( texturefile.find( szTexturePath ) == 0 ) {
|
||||
// don't include 'textures/' in the path
|
||||
texturefile.erase( 0, std::string{ szTexturePath }.size() );
|
||||
@@ -2784,8 +2790,8 @@ TTrack::export_as_text_( std::ostream &Output ) const {
|
||||
|
||||
texturefile = (
|
||||
m_material2 != null_handle ?
|
||||
GfxRenderer.Material( m_material2 ).name :
|
||||
"none" );
|
||||
GfxRenderer.Material( m_material2 ).name :
|
||||
"none" );
|
||||
if( texturefile.find( szTexturePath ) == 0 ) {
|
||||
// don't include 'textures/' in the path
|
||||
texturefile.erase( 0, std::string{ szTexturePath }.size() );
|
||||
@@ -2828,11 +2834,14 @@ TTrack::export_as_text_( std::ostream &Output ) const {
|
||||
|
||||
for( auto &eventsequence : eventsequences ) {
|
||||
for( auto &event : *( eventsequence.second ) ) {
|
||||
if( false == event.first.empty() ) {
|
||||
Output
|
||||
<< eventsequence.first << ' '
|
||||
<< event.first << ' ';
|
||||
}
|
||||
// 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
|
||||
<< eventsequence.first << ' '
|
||||
<< ( event.second != nullptr ?
|
||||
event.second->asName :
|
||||
event.first )
|
||||
<< ' ';
|
||||
}
|
||||
}
|
||||
if( ( SwitchExtension )
|
||||
@@ -2850,6 +2859,9 @@ TTrack::export_as_text_( std::ostream &Output ) const {
|
||||
if( fOverhead != -1.0 ) {
|
||||
Output << "overhead " << fOverhead << ' ';
|
||||
}
|
||||
if( fVerticalRadius != 0.f ) {
|
||||
Output << "vradius " << fVerticalRadius << ' ';
|
||||
}
|
||||
// footer
|
||||
Output
|
||||
<< "endtrack"
|
||||
@@ -3091,15 +3103,6 @@ path_table::InitTracks() {
|
||||
}
|
||||
} // 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 ] == '*' )
|
||||
&& ( !track->CurrentPrev() && track->CurrentNext() ) ) {
|
||||
// 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 ) {
|
||||
// jeśli się znajdzie, to podać wskaźnik
|
||||
|
||||
isolated->AssignEvents();
|
||||
|
||||
auto *memorycell = simulation::Memory.find( isolated->asName ); // czy jest komóka o odpowiedniej nazwie
|
||||
if( memorycell != nullptr ) {
|
||||
// przypisanie powiązanej komórki
|
||||
isolated->pMemCell = memorycell;
|
||||
}
|
||||
else {
|
||||
if( memorycell == nullptr ) {
|
||||
// utworzenie automatycznej komórki
|
||||
// TODO: determine suitable location for this one, create and add world reference node
|
||||
scene::node_data nodedata;
|
||||
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
|
||||
memorycell->is_exportable = false;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
31
Track.h
31
Track.h
@@ -99,18 +99,32 @@ class TIsolated
|
||||
{ // obiekt zbierający zajętości z kilku odcinków
|
||||
public:
|
||||
// constructors
|
||||
TIsolated();
|
||||
TIsolated(const std::string &n, TIsolated *i);
|
||||
// methods
|
||||
static void DeleteAll();
|
||||
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
|
||||
bool Busy() {
|
||||
return (iAxles > 0); };
|
||||
static TIsolated * Root() {
|
||||
return (pRoot); };
|
||||
TIsolated * Next() {
|
||||
return (pNext); };
|
||||
inline
|
||||
bool
|
||||
Busy() {
|
||||
return (iAxles > 0); };
|
||||
inline
|
||||
static TIsolated *
|
||||
Root() {
|
||||
return (pRoot); };
|
||||
inline
|
||||
TIsolated *
|
||||
Next() {
|
||||
return (pNext); };
|
||||
inline
|
||||
void
|
||||
parent( TIsolated *Parent ) {
|
||||
pParent = Parent; }
|
||||
inline
|
||||
TIsolated *
|
||||
parent() const {
|
||||
return pParent; }
|
||||
// members
|
||||
std::string asName; // nazwa obiektu, baza do nazw eventów
|
||||
TEvent *evBusy { nullptr }; // zdarzenie wyzwalane po zajęciu grupy
|
||||
@@ -120,6 +134,7 @@ private:
|
||||
// members
|
||||
int iAxles { 0 }; // ilość osi na odcinkach obsługiwanych przez obiekt
|
||||
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
|
||||
};
|
||||
|
||||
@@ -140,6 +155,7 @@ private:
|
||||
// McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur
|
||||
int iTrapezoid = 0; // 0-standard, 1-przechyłka, 2-trapez, 3-oba
|
||||
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 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...)
|
||||
@@ -265,7 +281,6 @@ public:
|
||||
if (pIsolated)
|
||||
pIsolated->Modify(i, o); }; // dodanie lub odjęcie osi
|
||||
std::string IsolatedName();
|
||||
bool IsolatedEventsAssign(TEvent *busy, TEvent *free);
|
||||
double WidthTotal();
|
||||
bool IsGroupable();
|
||||
int TestPoint( Math3D::vector3 *Point);
|
||||
|
||||
@@ -251,9 +251,10 @@ timetable_panel::update() {
|
||||
to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Dm ) ).substr( 1, 2 ) :
|
||||
" | " );
|
||||
auto const candeparture = (
|
||||
( owner->iStationStart < table->StationIndex )
|
||||
( owner->iStationStart < 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 =
|
||||
" "
|
||||
+ ( i < 2 ? "" :
|
||||
@@ -726,7 +727,7 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
|
||||
textline =
|
||||
"Acceleration:\n desired: " + to_string( mechanik.AccDesired, 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 ? "/" : "-" ) ) + ")"
|
||||
+ "\n brake threshold: " + to_string( mechanik.fAccThreshold, 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 {
|
||||
"StopCloser", "StopPoint", "Active", "Press", "Connect", "Primary", "Late", "StopHere",
|
||||
"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:";
|
||||
for( int idx = 0, flagbit = 1; idx < drivingflagnames.size(); ++idx, flagbit <<= 1 ) {
|
||||
|
||||
@@ -147,7 +147,7 @@ itemproperties_panel::update( scene::basic_node const *Node ) {
|
||||
textline += ", ";
|
||||
}
|
||||
textline += (
|
||||
event.second ?
|
||||
event.second != nullptr ?
|
||||
event.second->asName :
|
||||
event.first + " (missing)" );
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ std::string cParser::readToken( bool ToLower, const char *Break ) {
|
||||
// update line counter
|
||||
++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() ) {
|
||||
|
||||
@@ -67,6 +67,7 @@ state_serializer::deserialize( cParser &Input, scene::scratch_data &Scratchpad )
|
||||
std::pair<
|
||||
std::string,
|
||||
deserializefunction> > functionlist = {
|
||||
{ "area", &state_serializer::deserialize_area },
|
||||
{ "atmo", &state_serializer::deserialize_atmo },
|
||||
{ "camera", &state_serializer::deserialize_camera },
|
||||
{ "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
|
||||
state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ private:
|
||||
// methods
|
||||
// restores class data from provided stream
|
||||
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_camera( cParser &Input, scene::scratch_data &Scratchpad );
|
||||
void deserialize_config( cParser &Input, scene::scratch_data &Scratchpad );
|
||||
|
||||
Reference in New Issue
Block a user