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

Merge branch 'tmj-dev'

This commit is contained in:
milek7
2018-03-06 19:09:52 +01:00
19 changed files with 571 additions and 356 deletions

View File

@@ -868,53 +868,15 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// jeśli długość peronu ((sSpeedTable[i].evEvent->ValueGet(2)) nie podana,
// przyjąć odległość fMinProximityDist
{ // jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
if (!AIControllFlag) // AI tylko sobie otwiera drzwi
iDrivigFlags &= ~moveStopCloser; // w razie przełączenia na AI ma
// nie podciągać do W4, gdy
// użytkownik zatrzymał za daleko
if ((iDrivigFlags & moveDoorOpened) == 0)
{ // drzwi otwierać jednorazowo
if( !AIControllFlag ) {
// w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko
iDrivigFlags &= ~moveStopCloser;
}
if( ( iDrivigFlags & moveDoorOpened ) == 0 ) {
// drzwi otwierać jednorazowo
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
if (mvOccupied->DoorOpenCtrl == 1) //(mvOccupied->TrainType==dt_EZT)
{ // otwieranie drzwi w EZT
if (AIControllFlag) // tylko AI otwiera drzwi EZT, użytkownik
// musi samodzielnie
if (!mvOccupied->DoorLeftOpened &&
!mvOccupied->DoorRightOpened)
{ // otwieranie drzwi
int p2 =
int(floor(sSpeedTable[i].evEvent->ValueGet(2))) %
10; // p7=platform side (1:left, 2:right, 3:both)
int lewe = (iDirection > 0) ? 1 : 2; // jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
int prawe = (iDirection > 0) ? 2 : 1;
if (p2 & lewe)
mvOccupied->DoorLeft(true);
if (p2 & prawe)
mvOccupied->DoorRight(true);
}
}
else
{ // otwieranie drzwi w składach wagonowych - docelowo wysyłać komendę zezwolenia na otwarcie drzwi
int p7, lewe, prawe; // p7=platform side (1:left, 2:right, 3:both)
// tu będzie jeszcze długość peronu zaokrąglona do 10m
// (20m bezpieczniej, bo nie modyfikuje bitu 1)
p7 = int(std::floor(sSpeedTable[i].evEvent->ValueGet(2))) % 10;
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
while (p)
{ // otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
lewe = (p->DirectionGet() > 0) ? 1 : 2;
prawe = 3 - lewe;
// wagony muszą mieć baterię załączoną do otwarcia drzwi...
p->MoverParameters->BatterySwitch(true);
if (p7 & lewe)
p->MoverParameters->DoorLeft(true);
if (p7 & prawe)
p->MoverParameters->DoorRight(true);
// pojazd podłączony z tyłu (patrząc od czoła)
p = p->Next();
}
}
Doors( true, static_cast<int>( std::floor( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ) ) % 10 );
}
if (TrainParams->UpdateMTable( simulation::Time, asNextStop) ) {
// to się wykona tylko raz po zatrzymaniu na W4
@@ -924,23 +886,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
iDrivigFlags &= ~( moveStartHorn | moveStartHornNow );
}
// perform loading/unloading
auto const exchangetime { simulation::Station.update_load( pVehicles[ 0 ], *TrainParams ) };
// TBD: adjust time to load exchange size
if( fStopTime > -55 ) {
// na końcu rozkładu się ustawia 60s i tu by było skrócenie
// WaitingSet( 15.0 + Random( 15.0 ) ); // 10 sekund (wziąć z rozkładu????) - czekanie
// with door open on both sides calculated loading time is halved
// p7=platform side (1:left, 2:right, 3:both)
auto const platformside = static_cast<int>( std::floor( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ) ) % 10;
WaitingSet(
platformside == 3 ?
exchangetime * 0.5 :
exchangetime );
}
// update brake settings and ai braking tables
// NOTE: this calculation is run after completing loading/unloading
// remember to move it to a more fitting spot, when loading/unloading taks some actual time
AutoRewident(); // nastawianie hamulca do jazdy pociągowej
auto const exchangetime = simulation::Station.update_load( pVehicles[ 0 ], *TrainParams, platformside );
WaitingSet( std::max( -fStopTime, exchangetime ) ); // na końcu rozkładu się ustawia 60s i tu by było skrócenie
if( TrainParams->CheckTrainLatency() < 0.0 ) {
// odnotowano spóźnienie
@@ -1011,6 +959,10 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
+ ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute)
+ " next " + asNextStop); // informacja
#endif
// update brake settings and ai braking tables
// NOTE: this calculation is expected to run after completing loading/unloading
AutoRewident(); // nastawianie hamulca do jazdy pociągowej
if( int( floor( sSpeedTable[ i ].evEvent->ValueGet( 1 ) ) ) & 1 ) {
// nie podjeżdżać do semafora, jeśli droga nie jest wolna
iDrivigFlags |= moveStopHere;
@@ -2400,7 +2352,7 @@ bool TController::ReleaseEngine()
ReactionTime = PrepareTime;
if (AIControllFlag)
{ // jeśli steruje komputer
if (mvOccupied->DoorOpenCtrl == 1)
if (mvOccupied->DoorCloseCtrl == control::driver)
{ // zamykanie drzwi
if (mvOccupied->DoorLeftOpened)
mvOccupied->DoorLeft(false);
@@ -3050,50 +3002,66 @@ void TController::SpeedSet()
}
};
void TController::Doors(bool what)
{ // otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT
if (what)
{ // otwarcie
// otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT
void TController::Doors( bool const Open, int const Side ) {
if( true == Open ) {
// otwieranie drzwi
// otwieranie drzwi w składach wagonowych - docelowo wysyłać komendę zezwolenia na otwarcie drzwi
// tu będzie jeszcze długość peronu zaokrąglona do 10m (20m bezpieczniej, bo nie modyfikuje bitu 1)
// p7=platform side (1:left, 2:right, 3:both)
auto *vehicle = pVehicles[0]; // pojazd na czole składu
while( vehicle != nullptr ) {
// wagony muszą mieć baterię załączoną do otwarcia drzwi...
vehicle->MoverParameters->BatterySwitch( true );
// otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza
if( vehicle->MoverParameters->DoorOpenCtrl != control::passenger ) {
// if the door are controlled by the driver, we let the user operate them...
if( true == AIControllFlag ) {
// ...unless this user is an ai
// p7=platform side (1:left, 2:right, 3:both)
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
auto const lewe = ( vehicle->DirectionGet() > 0 ) ? 1 : 2;
auto const prawe = 3 - lewe;
if( Side & lewe )
vehicle->MoverParameters->DoorLeft( true, range::local );
if( Side & prawe )
vehicle->MoverParameters->DoorRight( true, range::local );
}
else
{ // zamykanie
if (mvOccupied->DoorOpenCtrl == 1)
{ // jeśli drzwi sterowane z kabiny
}
// pojazd podłączony z tyłu (patrząc od czoła)
vehicle = vehicle->Next();
}
}
else {
// zamykanie
if( AIControllFlag ) {
if( mvOccupied->DoorLeftOpened || mvOccupied->DoorRightOpened ) {
// AI zamyka drzwi przed odjazdem
if( ( true == mvOccupied->DoorClosureWarning )
&& ( false == mvOccupied->DepartureSignal )
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
mvOccupied->signal_departure( true ); // załącenie bzyczka
fActionTime = -3.0 - 0.1 * Random( 10 ); // 3-4 second wait
}
if( fActionTime > -0.5 ) {
// Ra: trzeba by ustawić jakiś czas oczekiwania na zamknięcie się drzwi
mvOccupied->DoorLeft( false ); // zamykanie drzwi
mvOccupied->DoorRight( false );
iDrivigFlags &= ~moveDoorOpened;
// 1.5-2.5 sec wait, +potentially 0.5 remaining
fActionTime = -1.5 - 0.1 * Random( 10 );
}
if( ( true == TestFlag( iDrivigFlags, moveDoorOpened ) )
&& ( ( fActionTime > -0.5 )
|| ( false == AIControllFlag ) ) ) {
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
while( vehicle != nullptr ) {
// zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
if( vehicle->MoverParameters->DoorCloseCtrl != control::passenger ) {
vehicle->MoverParameters->DoorLeft( false, range::local ); // w lokomotywie można by nie zamykać...
vehicle->MoverParameters->DoorRight( false, range::local );
}
vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
}
}
else
{ // jeśli nie, to zamykanie w składzie wagonowym
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
while (p)
{ // zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
p->MoverParameters->DoorLeft(false); // w lokomotywie można by nie zamykać...
p->MoverParameters->DoorRight(false);
p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
}
// WaitingSet(5); //10 sekund tu to za długo, opóźnia odjazd o pół minuty
fActionTime = -3.0 - 0.1 * Random(10); // czekanie sekundę, może trochę dłużej
fActionTime = -2.5 - 0.1 * Random( 10 ); // 2.5-3.5 sec wait, +potentially 0.5 remaining
iDrivigFlags &= ~moveDoorOpened; // zostały zamknięte - nie wykonywać drugi raz
}
}
};
}
void TController::RecognizeCommand()
{ // odczytuje i wykonuje komendę przekazaną lokomotywie
@@ -3631,7 +3599,7 @@ TController::UpdateSituation(double dt) {
// for human-controlled vehicles with no door control and dynamic brake auto-activating with door open
if( ( false == AIControllFlag )
&& ( iDrivigFlags & moveDoorOpened )
&& ( mvOccupied->DoorOpenCtrl != 1 )
&& ( mvOccupied->DoorCloseCtrl != control::driver )
&& ( mvControlling->MainCtrlPos > 0 ) ) {
Doors( false );
}
@@ -4097,7 +4065,10 @@ TController::UpdateSituation(double dt) {
iDrivigFlags |= movePress; // następnie będzie dociskanie
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie)
CheckVehicles(); // od razu zmienić światła (zgasić) - bez tego się nie odczepi
/*
// NOTE: disabled to prevent closing the door before passengers can disembark
fStopTime = 0.0; // nie ma na co czekać z odczepianiem
*/
}
}
else {
@@ -4246,8 +4217,8 @@ TController::UpdateSituation(double dt) {
&& ( false == TestFlag( iDrivigFlags, movePress ) )
&& ( iCoupler == 0 )
// && ( mvOccupied->Vel > 0.0 )
&& ( pVehicle->PrevConnected == nullptr )
&& ( pVehicle->NextConnected == nullptr ) ) {
&& ( pVehicle->MoverParameters->Couplers[ side::front ].CouplingFlag == coupling::faux )
&& ( pVehicle->MoverParameters->Couplers[ side::rear ].CouplingFlag == coupling::faux ) ) {
SetVelocity(0, 0, stopJoin); // 1. faza odczepiania: zatrzymanie
// WriteLog("Zatrzymanie w celu odczepienia");
AccPreferred = std::min( 0.0, AccPreferred );
@@ -5039,7 +5010,7 @@ TController::UpdateSituation(double dt) {
fMinProximityDist : // cars are allowed to move within min proximity distance
fMaxProximityDist ) ? // other vehicle types keep wider margin
true :
vel < VelNext ) ) {
( vel + 1.0 ) < VelNext ) ) {
// to można przyspieszyć
IncSpeed();
}

View File

@@ -303,7 +303,7 @@ private:
bool IncSpeed();
bool DecSpeed(bool force = false);
void SpeedSet();
void Doors(bool what);
void Doors(bool const Open, int const Side = 0);
void RecognizeCommand(); // odczytuje komende przekazana lokomotywie
void Activation(); // umieszczenie obsady w odpowiednim członie
void ControllingSet(); // znajduje człon do sterowania

View File

@@ -1926,37 +1926,49 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
}
} // koniec hamulce
else if( ( ActPar.size() >= 3 )
&& ( ActPar.substr( 0, 2 ) == "WF" ) ) {
// wheel flat
// TODO: convert this whole mess to something more elegant one day
ActPar.erase( 0, 2 );
&& ( ActPar[ 0 ] == 'W' ) ) {
// wheel
ActPar.erase( 0, 1 );
auto fixedflatsize { 0 };
{
// fixed size flat
auto const indexend { ActPar.find_first_not_of( "1234567890", 0 ) };
fixedflatsize = std::atoi( ActPar.substr( 0, indexend ).c_str() );
ActPar.erase( 0, indexend );
}
// optional parameters
auto randomflatsize { 0 };
auto randomflatchance { 100 };
auto flatchance { 100 };
while( false == ActPar.empty() ) {
if( ActPar[ 0 ] == 'R' ) {
// TODO: convert this whole copy and paste mess to something more elegant one day
switch( ActPar[ 0 ] ) {
case 'F': {
// fixed flat size
auto const indexstart { 1 };
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
fixedflatsize = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
ActPar.erase( 0, indexend );
break;
}
case 'R': {
// random flat size
auto const indexstart { 1 };
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
randomflatsize = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
ActPar.erase( 0, indexend );
break;
}
else if( ActPar[ 0 ] == 'P' ) {
case 'P': {
// random flat probability
auto const indexstart { 1 };
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
randomflatchance = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
flatchance = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
ActPar.erase( 0, indexend );
break;
}
default: {
// unrecognized key
ActPar.erase( 0, 1 );
break;
}
}
if( Random(0, 100) <= randomflatchance ) {
}
if( Random( 0, 100 ) <= flatchance ) {
MoverParameters->WheelFlat += fixedflatsize + Random( 0, randomflatsize );
}
}
@@ -2478,6 +2490,87 @@ bool TDynamicObject::UpdateForce(double dt, double dt1, bool FullVer)
return true;
}
// initiates load change by specified amounts, with a platform on specified side
void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platform ) {
if( ( MoverParameters->DoorOpenCtrl == control::passenger )
|| ( MoverParameters->DoorOpenCtrl == control::mixed ) ) {
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
auto const lewe = ( DirectionGet() > 0 ) ? 1 : 2;
auto const prawe = 3 - lewe;
if( Platform & lewe ) {
MoverParameters->DoorLeft( true, range::local );
}
if( Platform & prawe ) {
MoverParameters->DoorRight( true, range::local );
}
}
m_exchange.unload_count += Disembark;
m_exchange.load_count += Embark;
m_exchange.speed_factor = (
Platform == 3 ?
2.0 :
1.0 );
m_exchange.time = 0.0;
}
// update state of load exchange operation
void TDynamicObject::update_exchange( double const Deltatime ) {
if( ( m_exchange.unload_count < 0.01 ) && ( m_exchange.load_count < 0.01 ) ) { return; }
if( ( MoverParameters->Vel < 2.0 )
&& ( ( true == MoverParameters->DoorLeftOpened )
|| ( true == MoverParameters->DoorRightOpened ) ) ) {
m_exchange.time += Deltatime;
while( ( m_exchange.unload_count > 0.01 )
&& ( m_exchange.time >= 1.0 ) ) {
m_exchange.time -= 1.0;
auto const exchangesize = std::min( m_exchange.unload_count, MoverParameters->UnLoadSpeed * m_exchange.speed_factor );
m_exchange.unload_count -= exchangesize;
MoverParameters->LoadStatus = 1;
MoverParameters->Load = std::max( 0.f, MoverParameters->Load - exchangesize );
update_load_visibility();
}
if( m_exchange.unload_count < 0.01 ) {
// finish any potential unloading operation before adding new load
// don't load more than can fit
m_exchange.load_count = std::min( m_exchange.load_count, MoverParameters->MaxLoad - MoverParameters->Load );
while( ( m_exchange.load_count > 0.01 )
&& ( m_exchange.time >= 1.0 ) ) {
m_exchange.time -= 1.0;
auto const exchangesize = std::min( m_exchange.load_count, MoverParameters->LoadSpeed * m_exchange.speed_factor );
m_exchange.load_count -= exchangesize;
MoverParameters->LoadStatus = 2;
MoverParameters->Load = std::min( MoverParameters->MaxLoad, MoverParameters->Load + exchangesize ); // std::max not strictly needed but, eh
update_load_visibility();
}
}
}
if( MoverParameters->Vel > 2.0 ) {
// if the vehicle moves too fast cancel the exchange
m_exchange.unload_count = 0;
m_exchange.load_count = 0;
}
if( ( m_exchange.unload_count < 0.01 )
&& ( m_exchange.load_count < 0.01 ) ) {
MoverParameters->LoadStatus = 0;
// if the exchange is completed (or canceled) close the door, if applicable
if( ( MoverParameters->DoorCloseCtrl == control::passenger )
|| ( MoverParameters->DoorCloseCtrl == control::mixed ) ) {
MoverParameters->DoorLeft( false, range::local );
MoverParameters->DoorRight( false, range::local );
}
}
}
void TDynamicObject::LoadUpdate() {
// przeładowanie modelu ładunku
// Ra: nie próbujemy wczytywać modeli miliony razy podczas renderowania!!!
@@ -2496,7 +2589,11 @@ void TDynamicObject::LoadUpdate() {
}
if( mdLoad == nullptr ) {
// if this fails, try generic load model
mdLoad = TModelsManager::GetModel( asBaseDir + MoverParameters->LoadType, true );
auto const genericloadfilename { asBaseDir + MoverParameters->LoadType };
if( ( true == FileExists( genericloadfilename + ".e3d" ) )
|| ( true == FileExists( genericloadfilename + ".t3d" ) ) ) {
mdLoad = TModelsManager::GetModel( genericloadfilename, true );
}
}
if( mdLoad != nullptr ) {
// TODO: discern from vehicle component which merely uses vehicle directory and has no animations, so it can be initialized outright
@@ -2541,11 +2638,11 @@ TDynamicObject::update_load_sections() {
void
TDynamicObject::update_load_visibility() {
/*
if( Random() < 0.25 ) {
shuffle_load_sections();
}
*/
auto loadpercentage { (
MoverParameters->MaxLoad == 0.0 ?
0.0 :
@@ -3523,6 +3620,8 @@ bool TDynamicObject::Update(double dt, double dt1)
}
MoverParameters->DerailReason = 0; //żeby tylko raz
}
update_exchange( dt );
if (MoverParameters->LoadStatus)
LoadUpdate(); // zmiana modelu ładunku
@@ -3563,6 +3662,7 @@ bool TDynamicObject::FastUpdate(double dt)
// ResetdMoveLen();
FastMove(dDOMoveLen);
update_exchange( dt );
if (MoverParameters->LoadStatus)
LoadUpdate(); // zmiana modelu ładunku
return true; // Ra: chyba tak?
@@ -3759,6 +3859,19 @@ void TDynamicObject::RenderSounds() {
}
// other sounds
// load exchange
if( MoverParameters->LoadStatus & 1 ) {
m_exchangesounds.unloading.play( sound_flags::exclusive );
}
else {
m_exchangesounds.unloading.stop();
}
if( MoverParameters->LoadStatus & 2 ) {
m_exchangesounds.loading.play( sound_flags::exclusive );
}
else {
m_exchangesounds.loading.stop();
}
// NBMX sygnal odjazdu
if( MoverParameters->DoorClosureWarning ) {
if( MoverParameters->DepartureSignal ) {
@@ -4880,6 +4993,16 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
}
}
else if( token == "unloading:" ) {
m_exchangesounds.unloading.deserialize( parser, sound_type::single );
m_exchangesounds.unloading.owner( this );
}
else if( token == "loading:" ) {
m_exchangesounds.loading.deserialize( parser, sound_type::single );
m_exchangesounds.loading.owner( this );
}
else if( token == "sand:" ) {
sSand.deserialize( parser, sound_type::multipart, sound_parameters::range );
sSand.owner( this );

View File

@@ -265,6 +265,13 @@ private:
private:
// types
struct exchange_data {
float unload_count { 0.f }; // amount to unload
float load_count { 0.f }; // amount to load
float speed_factor { 1.f }; // operation speed modifier
float time { 0.f }; // time spent on the operation
};
struct coupler_sounds {
sound_source dsbCouplerAttach { sound_placement::external }; // moved from cab
sound_source dsbCouplerDetach { sound_placement::external }; // moved from cab
@@ -283,6 +290,11 @@ private:
sound_source rsDoorClose { sound_placement::general, 25.f };
};
struct exchange_sounds {
sound_source loading { sound_placement::general };
sound_source unloading { sound_placement::general };
};
struct axle_sounds {
double distance; // distance to rail joint
double offset; // axle offset from centre of the vehicle
@@ -319,6 +331,8 @@ private:
void ABuBogies();
void ABuModelRoll();
void TurnOff();
// update state of load exchange operation
void update_exchange( double const Deltatime );
// members
TButton btCoupler1; // sprzegi
@@ -386,6 +400,9 @@ private:
sound_source rscurve { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; // youBy
sound_source rsDerailment { sound_placement::external, 250.f }; // McZapkie-051202
exchange_data m_exchange; // state of active load exchange procedure, if any
exchange_sounds m_exchangesounds; // sounds associated with the load exchange
Math3D::vector3 modelShake;
bool renderme; // yB - czy renderowac
@@ -467,6 +484,8 @@ private:
void create_controller( std::string const Type, bool const Trainset );
void AttachPrev(TDynamicObject *Object, int iType = 1);
bool UpdateForce(double dt, double dt1, bool FullVer);
// initiates load change by specified amounts, with a platform on specified side
void LoadExchange( int const Disembark, int const Embark, int const Platform );
void LoadUpdate();
void update_load_sections();
void update_load_visibility();
@@ -554,6 +573,7 @@ private:
void DestinationSet(std::string to, std::string numer);
std::string TextureTest(std::string const &name);
void OverheadTrack(float o);
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
static std::string const MED_labels[ 8 ];
};

View File

@@ -438,7 +438,6 @@ int main(int argc, char *argv[])
return -1;
}
TPythonInterpreter::killInstance();
#ifdef _WIN32
Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej)
SafeDelete( pConsole );
@@ -448,7 +447,8 @@ int main(int argc, char *argv[])
glfwDestroyWindow(window);
glfwTerminate();
_exit(0); // skip destructors, there are ordering errors which causes segfaults
TPythonInterpreter::killInstance();
_exit(0); // skip destructors, there are ordering errors which causes segfaults
return 0;
}

View File

@@ -118,6 +118,7 @@ struct global_settings {
float SplineFidelity{ 1.f }; // determines segment size during conversion of splines to geometry
bool ResourceSweep{ true }; // gfx resource garbage collection
bool ResourceMove{ false }; // gfx resources are moved between cpu and gpu side instead of sending a copy
bool compress_tex{ true }; // all textures are compressed on gpu side
std::string asSky{ "1" };
bool bGlutFont{ false }; // czy tekst generowany przez GLUT32.DLL
double fFpsAverage{ 20.0 }; // oczekiwana wartosć FPS
@@ -168,7 +169,6 @@ struct global_settings {
std::string screenshot_dir;
bool loading_log = true;
bool dds_upper_origin = false;
bool compress_tex = true;
// methods
void LoadIniFile( std::string asFileName );

View File

@@ -153,7 +153,8 @@ enum coupling {
gangway = 0x10,
mainhose = 0x20,
heating = 0x40,
permanent = 0x80
permanent = 0x80,
uic = 0x100
};
// possible effect ranges for control commands; exclusive
enum range {
@@ -176,6 +177,15 @@ enum light {
redmarker_right = 0x20,
rearendsignals = 0x40
};
// door operation methods; exclusive
enum control {
passenger, // local, opened/closed for duration of loading
driver, // remote, operated by the driver
autonomous, // local, closed when vehicle moves and/or after timeout
conductor, // remote, operated by the conductor
mixed // primary manual but answers also to remote control
};
/*typ hamulca elektrodynamicznego*/
static int const dbrake_none = 0;
static int const dbrake_passive = 1;
@@ -307,7 +317,7 @@ struct TCommand
std::string Command; /*komenda*/
double Value1 = 0.0; /*argumenty komendy*/
double Value2 = 0.0;
int Coupling{ ctrain_controll }; // coupler flag used to determine command propagation
int Coupling { coupling::control }; // coupler flag used to determine command propagation
TLocation Location;
};
@@ -821,10 +831,10 @@ public:
static std::vector<std::string> const eimc_labels;
double InverterFrequency { 0.0 }; // current frequency of power inverters
/*-dla wagonow*/
double MaxLoad = 0.0; /*masa w T lub ilosc w sztukach - ladownosc*/
float MaxLoad = 0.f; /*masa w T lub ilosc w sztukach - ladownosc*/
std::string LoadAccepted; std::string LoadQuantity; /*co moze byc zaladowane, jednostki miary*/
double OverLoadFactor = 0.0; /*ile razy moze byc przekroczona ladownosc*/
double LoadSpeed = 0.0; double UnLoadSpeed = 0.0;/*szybkosc na- i rozladunku jednostki/s*/
float LoadSpeed = 0.f; float UnLoadSpeed = 0.f;/*szybkosc na- i rozladunku jednostki/s*/
int DoorOpenCtrl = 0; int DoorCloseCtrl = 0; /*0: przez pasazera, 1: przez maszyniste, 2: samoczynne (zamykanie)*/
double DoorStayOpen = 0.0; /*jak dlugo otwarte w przypadku DoorCloseCtrl=2*/
bool DoorClosureWarning = false; /*czy jest ostrzeganie przed zamknieciem*/
@@ -887,7 +897,7 @@ public:
bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere)
bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure
// TODO converter parameters, for when we start cleaning up mover parameters
start ConverterStart{ manual }; // whether converter is started manually, or by other means
start ConverterStart{ start::manual }; // whether converter is started manually, or by other means
float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met
double ConverterStartDelayTimer{ 0.0 }; // helper, for tracking whether converter start delay passed
bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/
@@ -1024,7 +1034,7 @@ public:
double eAngle = M_PI * 0.5;
/*-dla wagonow*/
double Load = 0.0; /*masa w T lub ilosc w sztukach - zaladowane*/
float Load = 0.f; /*masa w T lub ilosc w sztukach - zaladowane*/
std::string LoadType; /*co jest zaladowane*/
int LoadStatus = 0; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model
double LastLoadChangeTime = 0.0; //raz (roz)ładowania
@@ -1220,8 +1230,8 @@ public:
/* funckje dla wagonow*/
bool LoadingDone(double LSpeed, std::string LoadInit);
bool DoorLeft(bool State); //obsluga drzwi lewych
bool DoorRight(bool State); //obsluga drzwi prawych
bool DoorLeft(bool State, int const Notify = range::consist ); //obsluga drzwi lewych
bool DoorRight(bool State, int const Notify = range::consist ); //obsluga drzwi prawych
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi
bool signal_departure( bool const State, int const Notify = range::consist ); // toggles departure warning

View File

@@ -6004,65 +6004,80 @@ bool TMoverParameters::DoorBlockedFlag(void)
// Q: 20160713
// Otwiera / zamyka lewe drzwi
// *************************************************************************************************
bool TMoverParameters::DoorLeft(bool State)
{
bool DL = false;
if ((DoorLeftOpened != State) && (DoorBlockedFlag() == false) && (Battery == true))
{
DL = true;
// NOTE: door methods work regardless of vehicle door control type,
// but commands issued through the command system work only for vehicles which accept remote door control
bool TMoverParameters::DoorLeft(bool State, int const Notify ) {
if( DoorLeftOpened == State ) {
// TBD: should the command be passed to other vehicles regardless of whether it affected the primary target?
// (for the time being no, methods are often invoked blindly which would lead to commands spam)
return false;
}
bool result { false };
if( ( Battery == true )
&& ( DoorBlockedFlag() == false ) ) {
DoorLeftOpened = State;
if (State == true)
{
if (CabNo > 0)
SendCtrlToNext("DoorOpen", 1, CabNo); // 1=lewe, 2=prawe
else
SendCtrlToNext("DoorOpen", 2, CabNo); // zamiana
CompressedVolume -= 0.003;
result = true;
}
else
{
if (CabNo > 0)
SendCtrlToNext("DoorClose", 1, CabNo);
else
SendCtrlToNext("DoorClose", 2, CabNo);
if( Notify != range::local ) {
SendCtrlToNext(
( State == true ?
"DoorOpen" :
"DoorClose" ),
( CabNo > 0 ? // 1=lewe, 2=prawe (swap if reversed)
1 :
2 ),
CabNo,
( Notify == range::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
}
else
DL = false;
return DL;
return result;
}
// *************************************************************************************************
// Q: 20160713
// Otwiera / zamyka prawe drzwi
// *************************************************************************************************
bool TMoverParameters::DoorRight(bool State)
{
bool DR = false;
if ((DoorRightOpened != State) && (DoorBlockedFlag() == false) && (Battery == true))
{
DR = true;
DoorRightOpened = State;
if (State == true)
{
if (CabNo > 0)
SendCtrlToNext("DoorOpen", 2, CabNo); // 1=lewe, 2=prawe
else
SendCtrlToNext("DoorOpen", 1, CabNo); // zamiana
CompressedVolume -= 0.003;
}
else
{
if (CabNo > 0)
SendCtrlToNext("DoorClose", 2, CabNo);
else
SendCtrlToNext("DoorClose", 1, CabNo);
}
}
else
DR = false;
// NOTE: door methods work regardless of vehicle door control type,
// but commands issued through the command system work only for vehicles which accept remote door control
bool TMoverParameters::DoorRight(bool State, int const Notify ) {
return DR;
if( DoorRightOpened == State ) {
// TBD: should the command be passed to other vehicles regardless of whether it affected the primary target?
// (for the time being no, methods are often invoked blindly which would lead to commands spam)
return false;
}
bool result { false };
if( ( Battery == true )
&& ( DoorBlockedFlag() == false ) ) {
DoorRightOpened = State;
result = true;
}
if( Notify != range::local ) {
SendCtrlToNext(
( State == true ?
"DoorOpen" :
"DoorClose" ),
( CabNo > 0 ? // 1=lewe, 2=prawe (swap if reversed)
2 :
1 ),
CabNo,
( Notify == range::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
return result;
}
// toggles departure warning
@@ -6084,8 +6099,8 @@ TMoverParameters::signal_departure( bool const State, int const Notify ) {
0 ),
CabNo,
( Notify == range::unit ?
ctrain_controll | ctrain_depot :
ctrain_controll ) );
coupling::control | coupling::permanent :
coupling::control ) );
}
return true;
@@ -7195,16 +7210,31 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) {
void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
DoorOpenCtrl = 0;
std::string openctrl; extract_value( openctrl, "OpenCtrl", line, "" );
if( openctrl == "DriverCtrl" ) { DoorOpenCtrl = 1; }
DoorCloseCtrl = 0;
std::string closectrl; extract_value( closectrl, "CloseCtrl", line, "" );
if( closectrl == "DriverCtrl" ) { DoorCloseCtrl = 1; }
else if( closectrl == "AutomaticCtrl" ) { DoorCloseCtrl = 2; }
if( DoorCloseCtrl == 2 ) { extract_value( DoorStayOpen, "DoorStayOpen", line, "" ); }
std::map<std::string, int> doorcontrols {
{ "Passenger", control::passenger },
{ "AutomaticCtrl", control::autonomous },
{ "DriverCtrl", control::driver },
{ "Conductor", control::conductor },
{ "Mixed", control::mixed }
};
// opening method
{
auto lookup = doorcontrols.find( extract_value( "OpenCtrl", line ) );
DoorOpenCtrl =
lookup != doorcontrols.end() ?
lookup->second :
control::passenger;
}
// closing method
{
auto lookup = doorcontrols.find( extract_value( "CloseCtrl", line ) );
DoorCloseCtrl =
lookup != doorcontrols.end() ?
lookup->second :
control::passenger;
}
// automatic closing timer
if( DoorCloseCtrl == control::autonomous ) { extract_value( DoorStayOpen, "DoorStayOpen", line, "" ); }
extract_value( DoorOpenSpeed, "OpenSpeed", line, "" );
extract_value( DoorCloseSpeed, "CloseSpeed", line, "" );
@@ -8314,6 +8344,7 @@ bool TMoverParameters::SendCtrlToNext( std::string const CtrlCommand, double con
// musi być wybrana niezerowa kabina
if( ( Couplers[ d ].Connected != nullptr )
&& ( TestFlag( Couplers[ d ].CouplingFlag, Couplertype ) ) ) {
if( Couplers[ d ].ConnectedNr != d ) {
// jeśli ten nastpęny jest zgodny z aktualnym
if( Couplers[ d ].Connected->SetInternalCommand( CtrlCommand, ctrlvalue, dir, Couplertype ) )
@@ -8472,38 +8503,48 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
}
else if (Command == "DoorOpen") /*NBMX*/
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
if ((CValue2 > 0))
{ // normalne ustawienie pojazdu
if( ( DoorCloseCtrl == control::conductor )
|| ( DoorCloseCtrl == control::driver )
|| ( DoorCloseCtrl == control::mixed ) ) {
// ignore remote command if the door is only operated locally
if( CValue2 > 0 ) {
// normalne ustawienie pojazdu
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
DoorLeftOpened = true;
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
DoorRightOpened = true;
}
else
{ // odwrotne ustawienie pojazdu
else {
// odwrotne ustawienie pojazdu
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
DoorLeftOpened = true;
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
DoorRightOpened = true;
}
}
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if (Command == "DoorClose") /*NBMX*/
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
if ((CValue2 > 0))
{ // normalne ustawienie pojazdu
if( ( DoorCloseCtrl == control::conductor )
|| ( DoorCloseCtrl == control::driver )
|| ( DoorCloseCtrl == control::mixed ) ) {
// ignore remote command if the door is only operated locally
if( CValue2 > 0 ) {
// normalne ustawienie pojazdu
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
DoorLeftOpened = false;
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
DoorRightOpened = false;
}
else
{ // odwrotne ustawienie pojazdu
else {
// odwrotne ustawienie pojazdu
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
DoorLeftOpened = false;
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
DoorRightOpened = false;
}
}
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if( Command == "DepartureSignal" ) {

View File

@@ -18,6 +18,7 @@ http://mozilla.org/MPL/2.0/.
#include "Model3d.h"
#include "Globals.h"
#include "Logs.h"
#include "utilities.h"
// wczytanie modelu do kontenerka
@@ -78,42 +79,76 @@ TModelsManager::GetModel(std::string const &Name, bool const Dynamic)
// - wczytanie uproszczonego wnętrza, ścieżka dokładna, tekstury z katalogu modelu
// - niebo animowane, ścieżka brana ze wpisu, tekstury nieokreślone
// - wczytanie modelu animowanego - Init() - sprawdzić
std::string buf;
std::string const buftp = Global.asCurrentTexturePath; // zapamiętanie aktualnej ścieżki do tekstur,
if( Name.find('\\') == std::string::npos )
{
buf = "models\\" + Name; // Ra: było by lepiej katalog dodać w parserze
if( Name.find( '/') != std::string::npos)
{
Global.asCurrentTexturePath = Global.asCurrentTexturePath + Name;
Global.asCurrentTexturePath.erase(Global.asCurrentTexturePath.find("/") + 1,
Global.asCurrentTexturePath.length());
std::string const buftp { Global.asCurrentTexturePath }; // zapamiętanie aktualnej ścieżki do tekstur,
std::string filename { Name };
if( Name.find( '/' ) != std::string::npos ) {
// pobieranie tekstur z katalogu, w którym jest model
Global.asCurrentTexturePath += Name;
Global.asCurrentTexturePath.erase( Global.asCurrentTexturePath.rfind( "/" ) + 1 );
}
}
else
{
buf = Name;
if( Dynamic ) {
// na razie tak, bo nie wiadomo, jaki może mieć wpływ na pozostałe modele
if( Name.find( '/' ) != std::string::npos ) { // pobieranie tekstur z katalogu, w którym jest model
Global.asCurrentTexturePath = Global.asCurrentTexturePath + Name;
Global.asCurrentTexturePath.erase(
Global.asCurrentTexturePath.find( "/" ) + 1,
Global.asCurrentTexturePath.length() - 1 );
}
}
}
buf = ToLower( buf );
auto const lookup = m_modelsmap.find( buf );
if( lookup != m_modelsmap.end() ) {
filename = ToLower( filename );
if( ( filename.rfind( '.' ) != std::string::npos )
&& ( filename.rfind( '.' ) != filename.rfind( ".." ) + 1 ) ) {
// trim extension if there's one, but don't mistake folder traverse for extension
filename.erase( filename.rfind( '.' ) );
}
// see if we have it in the databank
auto *model { find_in_databank( filename ) };
if( model != nullptr ) {
Global.asCurrentTexturePath = buftp;
return ( m_models[ lookup->second ].Model.get() );
return model;
}
auto model = LoadModel(buf, Dynamic); // model nie znaleziony, to wczytać
// not yet loaded, check if it's on disk
std::string lookup { find_on_disk( filename ) };
if( false == lookup.empty() ) {
model = LoadModel( lookup, Dynamic ); // model nie znaleziony, to wczytać
}
else {
// there's nothing matching in the databank nor on the disk, report failure
ErrorLog( "Bad file: failed do locate 3d model file \"" + filename + "\"", logtype::file );
}
Global.asCurrentTexturePath = buftp; // odtworzenie ścieżki do tekstur
return model; // NULL jeśli błąd
};
TModel3d *
TModelsManager::find_in_databank( std::string const &Name ) {
std::vector<std::string> filenames {
Name,
szModelPath + Name };
for( auto const &filename : filenames ) {
auto const lookup { m_modelsmap.find( filename ) };
if( lookup != m_modelsmap.end() ) {
return ( m_models[ lookup->second ].Model.get() );
}
}
return nullptr;
}
// checks whether specified file exists. returns name of the located file, or empty string.
std::string
TModelsManager::find_on_disk( std::string const &Name ) {
std::vector<std::string> extensions { { ".e3d" }, { ".t3d" } };
for( auto const &extension : extensions ) {
auto lookup = (
FileExists( Name + extension ) ? Name :
FileExists( szModelPath + Name + extension ) ? szModelPath + Name :
"" );
if( false == lookup.empty() ) {
return lookup;
}
}
return {};
}
//---------------------------------------------------------------------------

View File

@@ -20,6 +20,11 @@ private:
// klasa statyczna, nie ma obiektu
class TModelsManager {
public:
// McZapkie: dodalem sciezke, notabene Path!=Patch :)
static TModel3d *GetModel( std::string const &Name, bool dynamic = false );
private:
// types:
typedef std::deque<TMdlContainer> modelcontainer_sequence;
typedef std::unordered_map<std::string, modelcontainer_sequence::size_type> stringmodelcontainerindex_map;
@@ -28,9 +33,10 @@ class TModelsManager {
static stringmodelcontainerindex_map m_modelsmap;
// methods:
static TModel3d *LoadModel( std::string const &Name, bool const Dynamic );
public:
// McZapkie: dodalem sciezke, notabene Path!=Patch :)
static TModel3d *GetModel( std::string const &Name, bool dynamic = false );
static TModel3d *find_in_databank( std::string const &Name );
// checks whether specified file exists. returns name of the located file, or empty string.
static std::string find_on_disk( std::string const &Name );
};
//---------------------------------------------------------------------------

View File

@@ -647,7 +647,8 @@ opengl_texture::create() {
else {
// uncompressed texture data. have the gfx card do the compression as it sees fit
::glTexImage2D(
GL_TEXTURE_2D, 0, Global.compress_tex ? GL_COMPRESSED_RGBA : GL_RGBA,
GL_TEXTURE_2D, 0,
Global.compress_tex ? GL_COMPRESSED_RGBA : GL_RGBA,
data_width, data_height, 0,
data_format, GL_UNSIGNED_BYTE, (GLubyte *)&data[ 0 ] );
}
@@ -821,7 +822,10 @@ texture_manager::create( std::string Filename, bool const Loadnow ) {
Filename.erase( Filename.rfind( '.' ) );
}
std::replace(Filename.begin(), Filename.end(), '\\', '/'); // fix slashes
// change slashes to cross-platform
std::replace(
std::begin( Filename ), std::end( Filename ),
'\\', '/' );
std::vector<std::string> extensions{ { ".dds" }, { ".tga" }, { ".png" }, { ".bmp" }, { ".ext" } };
@@ -998,17 +1002,19 @@ texture_manager::info() const {
texture_handle
texture_manager::find_in_databank( std::string const &Texturename ) const {
auto lookup = m_texturemappings.find( Texturename );
if( lookup != m_texturemappings.end() ) {
return (int)lookup->second;
}
// jeszcze próba z dodatkową ścieżką
lookup = m_texturemappings.find( global_texture_path + Texturename );
std::vector<std::string> filenames {
Global.asCurrentTexturePath + Texturename,
Texturename,
szTexturePath + Texturename };
return (
lookup != m_texturemappings.end() ?
(int)lookup->second :
npos );
for( auto const &filename : filenames ) {
auto const lookup { m_texturemappings.find( filename ) };
if( lookup != m_texturemappings.end() ) {
return lookup->second;
}
}
return npos;
}
// checks whether specified file exists.
@@ -1016,8 +1022,9 @@ std::string
texture_manager::find_on_disk( std::string const &Texturename ) const {
return(
FileExists( Global.asCurrentTexturePath + Texturename ) ? Global.asCurrentTexturePath + Texturename :
FileExists( Texturename ) ? Texturename :
FileExists( global_texture_path + Texturename ) ? global_texture_path + Texturename :
FileExists( szTexturePath + Texturename ) ? szTexturePath + Texturename :
"" );
}

View File

@@ -380,12 +380,12 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
}
}
*/
MechSpring.Init(250);
MechSpring.Init(125.0);
vMechVelocity = Math3D::vector3(0, 0, 0);
pMechOffset = Math3D::vector3( 0, 0, 0 );
fMechSpringX = 1;
fMechSpringY = 0.5;
fMechSpringZ = 0.5;
fMechSpringX = 0.2;
fMechSpringY = 0.2;
fMechSpringZ = 0.1;
fMechMaxSpring = 0.15;
fMechRoll = 0.05;
fMechPitch = 0.1;
@@ -3296,9 +3296,6 @@ void TTrain::OnCommand_doorlocktoggle( TTrain *Train, command_data const &Comman
void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Command ) {
if( Train->mvOccupied->DoorOpenCtrl != 1 ) {
return;
}
if( Command.action == GLFW_PRESS ) {
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
if( false == (
@@ -3306,42 +3303,40 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman
Train->mvOccupied->DoorLeftOpened :
Train->mvOccupied->DoorRightOpened ) ) {
// open
if( Train->mvOccupied->ActiveCab == 1 ) {
if( Train->mvOccupied->DoorLeft( true ) ) {
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
if( Train->mvOccupied->DoorOpenCtrl != control::driver ) {
return;
}
if( Train->mvOccupied->ActiveCab == 1 ) {
Train->mvOccupied->DoorLeft( true );
}
else {
// in the rear cab sides are reversed...
if( Train->mvOccupied->DoorRight( true ) ) {
// ...but so are the switches
Train->mvOccupied->DoorRight( true );
}
// visual feedback
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
}
}
}
else {
// close
if( Train->mvOccupied->ActiveCab == 1 ) {
if( Train->mvOccupied->DoorLeft( false ) ) {
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
if( Train->mvOccupied->DoorCloseCtrl != control::driver ) {
return;
}
// TODO: move door opening/closing to the update, so the switch animation doesn't hinge on door working
if( Train->mvOccupied->ActiveCab == 1 ) {
Train->mvOccupied->DoorLeft( false );
}
else {
// in the rear cab sides are reversed...
if( Train->mvOccupied->DoorRight( false ) ) {
// ...but so are the switches
Train->mvOccupied->DoorRight( false );
}
// visual feedback
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
}
}
}
}
}
void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Command ) {
if( Train->mvOccupied->DoorOpenCtrl != 1 ) {
return;
}
if( Command.action == GLFW_PRESS ) {
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
if( false == (
@@ -3349,36 +3344,36 @@ void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Comma
Train->mvOccupied->DoorRightOpened :
Train->mvOccupied->DoorLeftOpened ) ) {
// open
if( Train->mvOccupied->ActiveCab == 1 ) {
if( Train->mvOccupied->DoorRight( true ) ) {
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
if( Train->mvOccupied->DoorOpenCtrl != control::driver ) {
return;
}
if( Train->mvOccupied->ActiveCab == 1 ) {
Train->mvOccupied->DoorRight( true );
}
else {
// in the rear cab sides are reversed...
if( Train->mvOccupied->DoorLeft( true ) ) {
// ...but so are the switches
Train->mvOccupied->DoorLeft( true );
}
// visual feedback
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
}
}
}
else {
// close
if( Train->mvOccupied->ActiveCab == 1 ) {
if( Train->mvOccupied->DoorRight( false ) ) {
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
if( Train->mvOccupied->DoorCloseCtrl != control::driver ) {
return;
}
if( Train->mvOccupied->ActiveCab == 1 ) {
Train->mvOccupied->DoorRight( false );
}
else {
// in the rear cab sides are reversed...
if( Train->mvOccupied->DoorLeft( false ) ) {
// ...but so are the switches
Train->mvOccupied->DoorLeft( false );
}
// visual feedback
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
}
}
}
}
}
void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) {

View File

@@ -69,14 +69,14 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c
else if( key == "texture1:" ) {
if( ( texture1 == null_handle )
|| ( Priority > priority1 ) ) {
texture1 = GfxRenderer.Fetch_Texture( path( name ) + value, Loadnow );
texture1 = GfxRenderer.Fetch_Texture( value, Loadnow );
priority1 = Priority;
}
}
else if( key == "texture2:" ) {
if( ( texture2 == null_handle )
|| ( Priority > priority2 ) ) {
texture2 = GfxRenderer.Fetch_Texture( path( name ) + value, Loadnow );
texture2 = GfxRenderer.Fetch_Texture( value, Loadnow );
priority2 = Priority;
}
}
@@ -120,12 +120,10 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
}
filename += ".mat";
std::replace(filename.begin(), filename.end(), '\\', '/'); // fix slashes
if( filename.find( '/' ) == std::string::npos ) {
// jeśli bieżaca ścieżka do tekstur nie została dodana to dodajemy domyślną
filename = global_texture_path + filename;
}
// change slashes to llinux-compatible
std::replace(
std::begin( filename ), std::end( filename ),
'\\', '/' );
// try to locate requested material in the databank
auto const databanklookup = find_in_databank( filename );
@@ -168,7 +166,7 @@ material_manager::find_in_databank( std::string const &Materialname ) const {
return lookup->second;
}
// jeszcze próba z dodatkową ścieżką
lookup = m_materialmappings.find( global_texture_path + Materialname );
lookup = m_materialmappings.find( szTexturePath + Materialname );
return (
lookup != m_materialmappings.end() ?
@@ -183,7 +181,7 @@ material_manager::find_on_disk( std::string const &Materialname ) const {
return(
FileExists( Materialname ) ? Materialname :
FileExists( global_texture_path + Materialname ) ? global_texture_path + Materialname :
FileExists( szTexturePath + Materialname ) ? szTexturePath + Materialname :
"" );
}

View File

@@ -182,11 +182,11 @@ opengl_renderer::Init( GLFWwindow *Window ) {
}
// preload some common textures
WriteLog( "Loading common gfx data..." );
m_glaretexture = Fetch_Texture( "fx\\lightglare" );
m_suntexture = Fetch_Texture( "fx\\sun" );
m_moontexture = Fetch_Texture( "fx\\moon" );
m_glaretexture = Fetch_Texture( "fx/lightglare" );
m_suntexture = Fetch_Texture( "fx/sun" );
m_moontexture = Fetch_Texture( "fx/moon" );
if( m_helpertextureunit >= 0 ) {
m_reflectiontexture = Fetch_Texture( "fx\\reflections" );
m_reflectiontexture = Fetch_Texture( "fx/reflections" );
}
WriteLog( "...gfx data pre-loading done" );

View File

@@ -15,7 +15,7 @@ http://mozilla.org/MPL/2.0/.
// exchanges load with consist attached to specified vehicle, operating on specified schedule
double
basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule ) {
basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule, int const Platform ) {
auto const firststop { Schedule.StationIndex == 1 };
auto const laststop { Schedule.StationIndex == Schedule.StationCount };
@@ -30,7 +30,13 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
auto const stationsizemodifier { ( trainstop ? 1.0 : 2.0 ) };
// go through all vehicles and update their load
// NOTE: for the time being we limit ourselves to passenger-carrying cars only
auto exchangetime { 0.0 };
auto exchangetime { 0.f };
// platform (1:left, 2:right, 3:both)
// with exchange performed on both sides waiting times are halved
auto const exchangetimemodifier { (
Platform == 3 ?
0.5f :
1.0f ) };
auto *vehicle { First };
while( vehicle != nullptr ) {
@@ -47,24 +53,29 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
// NOTE: for the time being we're doing simple, random load change calculation
// TODO: exchange driven by station parameters and time of the day
auto unloadcount = static_cast<int>(
firststop ? 0 :
laststop ? parameters.Load :
std::min(
firststop ? 0 :
std::min<float>(
parameters.Load,
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) ) );
auto loadcount = static_cast<int>(
laststop ?
0 :
Random( parameters.MaxLoad * 0.15 * stationsizemodifier ) );
Random( parameters.MaxLoad * 0.15f * stationsizemodifier ) );
if( true == firststop ) {
// slightly larger group at the initial station
loadcount *= 2;
}
parameters.Load = std::min( parameters.MaxLoad, parameters.Load - unloadcount + loadcount );
if( ( unloadcount > 0 ) || ( loadcount > 0 ) ) {
vehicle->LoadExchange( unloadcount, loadcount, Platform );
/*
vehicle->LoadUpdate();
vehicle->update_load_visibility();
exchangetime = std::max( exchangetime, unloadcount / parameters.UnLoadSpeed + loadcount / parameters.LoadSpeed);
*/
exchangetime = std::max( exchangetime, exchangetimemodifier * ( unloadcount / parameters.UnLoadSpeed + loadcount / parameters.LoadSpeed ) );
}
}
vehicle = vehicle->Next();
}

View File

@@ -18,5 +18,5 @@ public:
// methods
// exchanges load with consist attached to specified vehicle, operating on specified schedule; returns: time needed for exchange, in seconds
double
update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule );
update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule, int const Platform );
};

View File

@@ -25,12 +25,10 @@ http://mozilla.org/MPL/2.0/.
#define DegToRad(a) ((M_PI / 180.0) * (a)) //(a) w nawiasie, bo może być dodawaniem
#define RadToDeg(r) ((180.0 / M_PI) * (r))
#define asModelsPath std::string("models\\")
#define asSceneryPath std::string("scenery\\")
#define szSceneryPath "scenery\\"
#define szTexturePath "textures\\"
#define szSoundPath "sounds\\"
#define global_texture_path "textures/"
#define szSceneryPath "scenery/"
#define szTexturePath "textures/"
#define szModelPath "models/"
#define szSoundPath "sounds/"
#define MAKE_ID4(a,b,c,d) (((std::uint32_t)(d)<<24)|((std::uint32_t)(c)<<16)|((std::uint32_t)(b)<<8)|(std::uint32_t)(a))