diff --git a/Driver.cpp b/Driver.cpp index 72b76b03..20de084e 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2110,12 +2110,18 @@ bool TController::CheckVehicles(TOrders user) { // sprawdzanie, czy jest głównym sterującym, żeby nie było konfliktu if (p->Mechanik) // jeśli ma obsadę if (p->Mechanik != this) // ale chodzi o inny pojazd, niż aktualnie sprawdzający - if (p->Mechanik->iDrivigFlags & movePrimary) // a tamten ma priorytet - if ((iDrivigFlags & movePrimary) && (mvOccupied->DirAbsolute) && - (mvOccupied->BrakeCtrlPos >= -1)) // jeśli rządzi i ma kierunek - p->Mechanik->iDrivigFlags &= ~movePrimary; // dezaktywuje tamtego - else + if( p->Mechanik->iDrivigFlags & movePrimary ) { + // a tamten ma priorytet + if( ( iDrivigFlags & movePrimary ) + && ( mvOccupied->DirAbsolute ) + && ( mvOccupied->BrakeCtrlPos >= -1 ) ) { + // jeśli rządzi i ma kierunek + p->Mechanik->primary( false ); // dezaktywuje tamtego + } + else { main = false; // nici z rządzenia + } + } ++iVehicles; // jest jeden pojazd więcej pVehicles[1] = p; // zapamiętanie ostatniego fLength += p->MoverParameters->Dim.L; // dodanie długości pojazdu @@ -4763,7 +4769,7 @@ TController::UpdateSituation(double dt) { // rozpoznaj komende bo lokomotywa jej nie rozpoznaje RecognizeCommand(); // samo czyta komendę wstawioną do pojazdu? } - if( mvOccupied->SecuritySystem.Status > 1 ) { + if( mvOccupied->SecuritySystem.Status != s_off ) { // jak zadziałało CA/SHP if( !mvOccupied->SecuritySystemReset() ) { // to skasuj if( ( /*mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == 0 ) @@ -6759,43 +6765,56 @@ void TController::UpdateDelayFlag() { //-----------koniec skanowania semaforow -void TController::TakeControl(bool yes) +void TController::TakeControl( bool const Aidriver, bool const Forcevehiclecheck ) { // przejęcie kontroli przez AI albo oddanie - if (AIControllFlag == yes) + if (AIControllFlag == Aidriver) return; // już jest jak ma być - if (yes) //żeby nie wykonywać dwa razy + if (Aidriver) //żeby nie wykonywać dwa razy { // teraz AI prowadzi AIControllFlag = AIdriver; pVehicle->Controller = AIdriver; iDirection = 0; // kierunek jazdy trzeba dopiero zgadnąć - // gdy zgaszone światła, flaga podjeżdżania pod semafory pozostaje bez zmiany - // conditional below disabled to get around the situation where the AI train does nothing ever - // because it is waiting for orders which don't come until the engine is engaged, i.e. effectively never - if (OrderCurrentGet()) // jeśli coś robi - PrepareEngine(); // niech sprawdzi stan silnika - else // jeśli nic nie robi - if (pVehicle->iLights[ ( mvOccupied->CabNo < 0 ? - end::rear : - end::front ) ] - & (light::headlight_left | light::headlight_right | light::headlight_upper)) // któreś ze świateł zapalone? - { // od wersji 357 oczekujemy podania komend dla AI przez scenerię - OrderNext(Prepare_engine); - if (pVehicle->iLights[mvOccupied->CabNo < 0 ? end::rear : end::front] & light::headlight_upper) // górne światło zapalone - OrderNext(Obey_train); // jazda pociągowa - else - OrderNext(Shunt); // jazda manewrowa - if (mvOccupied->Vel >= 1.0) // jeśli jedzie (dla 0.1 ma stać) - iDrivigFlags &= ~moveStopHere; // to ma nie czekać na sygnał, tylko jechać - else - iDrivigFlags |= moveStopHere; // a jak stoi, to niech czeka - } - CheckVehicles(); // ustawienie świateł TableClear(); // ponowne utworzenie tabelki, bo człowiek mógł pojechać niezgodnie z sygnałami + if( action() != TAction::actSleep ) { + // gdy zgaszone światła, flaga podjeżdżania pod semafory pozostaje bez zmiany + // conditional below disabled to get around the situation where the AI train does nothing ever + // because it is waiting for orders which don't come until the engine is engaged, i.e. effectively never + if( OrderCurrentGet() ) { + // jeśli coś robi + PrepareEngine(); // niech sprawdzi stan silnika + } + else { + // jeśli nic nie robi + if( pVehicle->iLights[ ( mvOccupied->CabNo < 0 ? + end::rear : + end::front ) ] + & ( light::headlight_left | light::headlight_right | light::headlight_upper ) ) // któreś ze świateł zapalone? + { // od wersji 357 oczekujemy podania komend dla AI przez scenerię + OrderNext( Prepare_engine ); + if( pVehicle->iLights[ mvOccupied->CabNo < 0 ? end::rear : end::front ] & light::headlight_upper ) // górne światło zapalone + OrderNext( Obey_train ); // jazda pociągowa + else + OrderNext( Shunt ); // jazda manewrowa + if( mvOccupied->Vel >= 1.0 ) // jeśli jedzie (dla 0.1 ma stać) + iDrivigFlags &= ~moveStopHere; // to ma nie czekać na sygnał, tylko jechać + else + iDrivigFlags |= moveStopHere; // a jak stoi, to niech czeka + } + } + CheckVehicles(); // ustawienie świateł + } } else { // a teraz użytkownik AIControllFlag = Humandriver; pVehicle->Controller = Humandriver; + if( eAction == TAction::actSleep ) { + eAction = TAction::actUnknown; + } + if( Forcevehiclecheck ) { + // update consist ownership and other consist data + CheckVehicles(); + } } }; diff --git a/Driver.h b/Driver.h index 85177dbe..062691af 100644 --- a/Driver.h +++ b/Driver.h @@ -194,9 +194,13 @@ public: public: void UpdateSituation(double dt); // uruchamiac przynajmniej raz na sekundę void MoveTo(TDynamicObject *to); - void TakeControl(bool yes); + void TakeControl(bool const Aidriver, bool const Forcevehiclecheck = false); inline - bool Primary() const { + bool primary( bool const Primary ) { + SetFlag( iDrivigFlags, ( Primary ? movePrimary : -movePrimary ) ); + return primary(); } + inline + bool primary() const { return ( ( iDrivigFlags & movePrimary ) != 0 ); }; inline TMoverParameters const *Controlling() const { @@ -210,8 +214,11 @@ public: inline int Direction() const { return iDirection; } + inline + TAction & action() { + return eAction; } inline - TAction GetAction() { + TAction const & action() const { return eAction; } private: void Activation(); // umieszczenie obsady w odpowiednim członie diff --git a/DynObj.cpp b/DynObj.cpp index ba0f1b44..a0568347 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -980,8 +980,8 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) if( ( false == bDisplayCab ) // edge case, lowpoly may act as a stand-in for the hi-fi cab, so make sure not to show the driver when inside && ( Mechanik != nullptr ) - && ( ( Mechanik->GetAction() != TAction::actSleep ) - || ( MoverParameters->Battery ) ) ) { + && ( ( Mechanik->action() != TAction::actSleep ) + /* || ( MoverParameters->Battery ) */ ) ) { // rysowanie figurki mechanika btMechanik1.Turn( MoverParameters->ActiveCab > 0 ); btMechanik2.Turn( MoverParameters->ActiveCab < 0 ); @@ -2762,14 +2762,14 @@ bool TDynamicObject::Update(double dt, double dt1) if (Mechanik) { // Ra 2F3F: do Driver.cpp to przenieść? MoverParameters->EqvtPipePress = GetEPP(); // srednie cisnienie w PG - if ((Mechanik->Primary()) + if ((Mechanik->primary()) && (MoverParameters->EngineType == TEngineType::DieselEngine) && (MoverParameters->EIMCtrlType > 0)) { MoverParameters->CheckEIMIC(dt1); MoverParameters->eimic_real = MoverParameters->eimic; MoverParameters->SendCtrlToNext("EIMIC", MoverParameters->eimic, MoverParameters->CabNo); } - if( ( Mechanik->Primary() ) + if( ( Mechanik->primary() ) && ( MoverParameters->EngineType == TEngineType::ElectricInductionMotor ) ) { // jesli glowny i z asynchronami, to niech steruje hamulcem i napedem lacznie dla calego pociagu/ezt auto const kier = (DirectionGet() * MoverParameters->ActiveCab > 0); diff --git a/Event.cpp b/Event.cpp index 2e7ff1ca..fdcf7e93 100644 --- a/Event.cpp +++ b/Event.cpp @@ -897,7 +897,7 @@ whois_event::run_() { // jeśli typ pojazdu // TODO: define and recognize individual request types auto const owner { ( - ( ( m_activator->Mechanik != nullptr ) && ( m_activator->Mechanik->Primary() ) ) ? + ( ( m_activator->Mechanik != nullptr ) && ( m_activator->Mechanik->primary() ) ) ? m_activator->Mechanik : m_activator->ctOwner ) }; auto const consistbrakelevel { ( @@ -952,7 +952,7 @@ whois_event::run_() { } // +0 else if( m_activator->Mechanik ) { - if( m_activator->Mechanik->Primary() ) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera! + if( m_activator->Mechanik->primary() ) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera! targetcell->UpdateValues( m_activator->Mechanik->TrainName(), m_activator->Mechanik->StationCount() - m_activator->Mechanik->StationIndex(), // ile przystanków do końca diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 3c4bc493..65df7e6f 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -204,6 +204,7 @@ static int const dbrake_automatic = 8; /*status czuwaka/SHP*/ //hunter-091012: rozdzielenie alarmow, dodanie testu czuwaka +static int const s_off = 0; //disabled static int const s_waiting = 1; //działa static int const s_aware = 2; //czuwak miga static int const s_active = 4; //SHP świeci diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index e25494cd..db55491f 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1051,7 +1051,10 @@ void TMoverParameters::CollisionDetect(int const End, double const dt) if( velocitydifference > safevelocitylimit ) { // HACK: crude estimation for potential derail, will take place with velocity difference > 15 km/h adjusted for vehicle mass ratio - WriteLog( "Bad driving: " + Name + " and " + othervehicle->Name + " collided with velocity " + to_string( velocitydifference, 0 ) + " km/h" ); + if( ( false == TestFlag( DamageFlag, dtrain_out ) ) + || ( false == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) ) { + WriteLog( "Bad driving: " + Name + " and " + othervehicle->Name + " collided with velocity " + to_string( velocitydifference, 0 ) + " km/h" ); + } if( velocitydifference > safevelocitylimit * ( TotalMass / othervehicle->TotalMass ) ) { derail( 5 ); @@ -1084,12 +1087,14 @@ void TMoverParameters::CollisionDetect(int const End, double const dt) void TMoverParameters::damage_coupler( int const End ) { + auto &coupler{ Couplers[ End ] }; + + if( coupler.CouplerType == TCouplerType::Articulated ) { return; } // HACK: don't break articulated couplings no matter what + if( SetFlag( DamageFlag, dtrain_coupling ) ) EventFlag = true; - auto &coupler { Couplers[ End ] }; - - if( ( coupler.CouplingFlag & ctrain_pneumatic ) == ctrain_pneumatic ) { + if( ( coupler.CouplingFlag & coupling::brakehose ) == coupling::brakehose ) { // hamowanie nagle - zerwanie przewodow hamulcowych AlarmChainFlag = true; } @@ -1100,11 +1105,11 @@ TMoverParameters::damage_coupler( int const End ) { switch( End ) { // break connection with other vehicle, if there's any case 0: { - coupler.Connected->Couplers[ end::rear ].CouplingFlag = 0; + coupler.Connected->Couplers[ end::rear ].CouplingFlag = coupling::faux; break; } case 1: { - coupler.Connected->Couplers[ end::front ].CouplingFlag = 0; + coupler.Connected->Couplers[ end::front ].CouplingFlag = coupling::faux; break; } default: { @@ -2301,7 +2306,7 @@ bool TMoverParameters::CabDeactivisation(void) CabNo = 0; DirAbsolute = ActiveDir * CabNo; DepartureSignal = false; // nie buczeć z nieaktywnej kabiny - SecuritySystem.Status = 0; // deactivate alerter TODO: make it part of control based cab selection + SecuritySystem.Status = s_off; // deactivate alerter TODO: make it part of control based cab selection SendCtrlToNext("CabActivisation", 0, ActiveCab); // CabNo==0! } @@ -2446,7 +2451,7 @@ void TMoverParameters::SecuritySystemCheck(double dt) RadiostopSwitch(false); if ((SecuritySystem.SystemType > 0) - && (SecuritySystem.Status > 0) + && (SecuritySystem.Status != s_off) && (Battery)) // Ra: EZT ma teraz czuwak w rozrządczym { // CA @@ -2537,8 +2542,8 @@ bool TMoverParameters::BatterySwitch(bool State) SendCtrlToNext("BatterySwitch", 0, CabNo); BS = true; - if ((Battery) && (ActiveCab != 0)) /*|| (TrainType==dt_EZT)*/ - SecuritySystem.Status = (SecuritySystem.Status | s_waiting); // aktywacja czuwaka + if ((Battery) && (ActiveCab != 0)) + SecuritySystem.Status |= s_waiting; // aktywacja czuwaka else SecuritySystem.Status = 0; // wyłączenie czuwaka @@ -10397,10 +10402,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C Battery = true; else if ((CValue1 == 0)) Battery = false; - if ((Battery) && (ActiveCab != 0) /*or (TrainType=dt_EZT)*/) + /* + // TBD: makes no sense to activate alerters in entire consist + if ((Battery) && (ActiveCab != 0) ) SecuritySystem.Status = SecuritySystem.Status | s_waiting; // aktywacja czuwaka else SecuritySystem.Status = 0; // wyłączenie czuwaka + */ OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } // else if command='EpFuseSwitch' then {NBMX} diff --git a/Train.cpp b/Train.cpp index 73095609..f670d74e 100644 --- a/Train.cpp +++ b/Train.cpp @@ -5667,7 +5667,7 @@ bool TTrain::Update( double const Deltatime ) } } // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa - if( mvOccupied->SecuritySystem.Status > 0 ) { + if( mvOccupied->SecuritySystem.Status != s_off ) { if( fBlinkTimer > fCzuwakBlink ) fBlinkTimer = -fCzuwakBlink; else @@ -5695,7 +5695,7 @@ bool TTrain::Update( double const Deltatime ) false ) ); btLampkaWylSzybkiOff.Turn( ( ( ( mvControlled->MainsInitTimeCountdown > 0.0 ) - || ( fHVoltage == 0.0 ) +// || ( fHVoltage == 0.0 ) || ( m_linebreakerstate == 2 ) || ( true == mvControlled->Mains ) ) ? false : @@ -5928,7 +5928,10 @@ bool TTrain::Update( double const Deltatime ) auto const *mover { tmp->MoverParameters }; btLampkaWylSzybkiB.Turn( mover->Mains ); - btLampkaWylSzybkiBOff.Turn( ( false == mover->Mains ) && ( mover->MainsInitTimeCountdown <= 0.0 ) && ( fHVoltage != 0.0 ) ); + btLampkaWylSzybkiBOff.Turn( + ( false == mover->Mains ) + && ( mover->MainsInitTimeCountdown <= 0.0 ) + /*&& ( fHVoltage != 0.0 )*/ ); btLampkaOporyB.Turn(mover->ResistorsFlagCheck()); btLampkaBezoporowaB.Turn( @@ -6528,7 +6531,7 @@ TTrain::update_sounds( double const Deltatime ) { } // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa - if (mvOccupied->SecuritySystem.Status > 0) { + if (mvOccupied->SecuritySystem.Status != s_off ) { // hunter-091012: rozdzielenie alarmow if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) { diff --git a/TrkFoll.cpp b/TrkFoll.cpp index dc462a78..d7f2aebe 100644 --- a/TrkFoll.cpp +++ b/TrkFoll.cpp @@ -116,7 +116,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if( false == ismoving ) { //McZapkie-140602: wyzwalanie zdarzenia gdy pojazd stoi if( ( Owner->Mechanik != nullptr ) - && ( Owner->Mechanik->Primary() ) ) { + && ( Owner->Mechanik->primary() ) ) { // tylko dla jednego członu pCurrentTrack->QueueEvents( pCurrentTrack->m_events0, Owner ); } @@ -127,7 +127,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if( SetFlag( iEventFlag, -1 ) ) { // zawsze zeruje flagę sprawdzenia, jak mechanik dosiądzie, to się nie wykona if( ( Owner->Mechanik != nullptr ) - && ( Owner->Mechanik->Primary() ) ) { + && ( Owner->Mechanik->primary() ) ) { // tylko dla jednego członu // McZapkie-280503: wyzwalanie event tylko dla pojazdow z obsada pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner ); @@ -143,7 +143,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if( SetFlag( iEventFlag, -2 ) ) { // zawsze ustawia flagę sprawdzenia, jak mechanik dosiądzie, to się nie wykona if( ( Owner->Mechanik != nullptr ) - && ( Owner->Mechanik->Primary() ) ) { + && ( Owner->Mechanik->primary() ) ) { // tylko dla jednego członu pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner ); } diff --git a/application.cpp b/application.cpp index 791ccbcd..c825d12b 100644 --- a/application.cpp +++ b/application.cpp @@ -43,6 +43,9 @@ http://mozilla.org/MPL/2.0/. #pragma comment (lib, "dbghelp.lib") #pragma comment (lib, "version.lib") +extern "C" { _declspec( dllexport ) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; } +extern "C" { _declspec( dllexport ) DWORD NvOptimusEnablement = 0x00000001; } + eu07_application Application; ui_layer uilayerstaticinitializer; diff --git a/drivermode.cpp b/drivermode.cpp index 0f152e61..17273b94 100644 --- a/drivermode.cpp +++ b/drivermode.cpp @@ -723,20 +723,36 @@ driver_mode::OnKeyDown(int cKey) { if( tmp != nullptr ) { - if( simulation::Train ) {// jeśli mielismy pojazd - if( simulation::Train->Dynamic()->Mechanik ) { // na skutek jakiegoś błędu może czasem zniknąć - simulation::Train->Dynamic()->Mechanik->TakeControl( true ); // oddajemy dotychczasowy AI - } - } - if( ( true == DebugModeFlag ) || ( tmp->MoverParameters->Vel <= 5.0 ) ) { // works always in debug mode, or for stopped/slow moving vehicles otherwise + if( simulation::Train ) { // jeśli mielismy pojazd + if( simulation::Train->Dynamic()->Mechanik ) { // na skutek jakiegoś błędu może czasem zniknąć + if( ( tmp->ctOwner == simulation::Train->Dynamic()->Mechanik ) + && ( true == Global.ctrlState ) ) { + // if the vehicle we left to the ai controlled the vehicle we're about to take over + // put the ai we left in charge of our old vehicle to sleep + // TODO: remove ctrl key mode once manual cab (de)activation is in place + simulation::Train->Dynamic()->Mechanik->primary( false ); + simulation::Train->Dynamic()->Mechanik->action() = TAction::actSleep; + simulation::Train->Dynamic()->MoverParameters->CabDeactivisation(); + } + simulation::Train->Dynamic()->Mechanik->TakeControl( true ); // oddajemy dotychczasowy AI + } + } + if( simulation::Train == nullptr ) { simulation::Train = new TTrain(); // jeśli niczym jeszcze nie jeździlismy } - if( simulation::Train->Init( tmp ) ) { // przejmujemy sterowanie - simulation::Train->Dynamic()->Mechanik->TakeControl( false ); + if( simulation::Train->Init( tmp ) ) { + // przejmujemy sterowanie + if( true == Global.ctrlState ) { + // make sure we can take over the consist + // TODO: remove ctrl key mode once manual cab (de)activation is in place + simulation::Train->Dynamic()->Mechanik->primary( true ); + simulation::Train->Dynamic()->MoverParameters->CabActivisation(); + } + simulation::Train->Dynamic()->Mechanik->TakeControl( false, true ); } else { SafeDelete( simulation::Train ); // i nie ma czym sterować diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 96ef1b98..34267430 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -170,7 +170,7 @@ scenario_panel::update() { std::get( simulation::Region->find_vehicle( camera.Pos, 20, false, false ) ) ); // w trybie latania lokalizujemy wg mapy if( m_nearest == nullptr ) { return; } auto const *owner { ( - ( ( m_nearest->Mechanik != nullptr ) && ( m_nearest->Mechanik->Primary() ) ) ? + ( ( m_nearest->Mechanik != nullptr ) && ( m_nearest->Mechanik->primary() ) ) ? m_nearest->Mechanik : m_nearest->ctOwner ) }; if( owner == nullptr ) { return; } @@ -208,7 +208,7 @@ scenario_panel::render() { if( true == ImGui::Begin( panelname.c_str(), &is_open, flags ) ) { // potential assignment section auto const *owner { ( - ( ( m_nearest->Mechanik != nullptr ) && ( m_nearest->Mechanik->Primary() ) ) ? + ( ( m_nearest->Mechanik != nullptr ) && ( m_nearest->Mechanik->primary() ) ) ? m_nearest->Mechanik : m_nearest->ctOwner ) }; if( owner != nullptr ) { @@ -261,7 +261,7 @@ timetable_panel::update() { if( vehicle == nullptr ) { return; } // if the nearest located vehicle doesn't have a direct driver, try to query its owner auto const *owner = ( - ( ( vehicle->Mechanik != nullptr ) && ( vehicle->Mechanik->Primary() ) ) ? + ( ( vehicle->Mechanik != nullptr ) && ( vehicle->Mechanik->primary() ) ) ? vehicle->Mechanik : vehicle->ctOwner ); if( owner == nullptr ) { return; } @@ -553,7 +553,7 @@ debug_panel::update_section_vehicle( std::vector &Output ) { auto const &vehicle { *m_input.vehicle }; auto const &mover { *m_input.mover }; - auto const isowned { ( vehicle.Mechanik == nullptr ) && ( vehicle.ctOwner != nullptr ) }; + auto const isowned { /* ( vehicle.Mechanik == nullptr ) && */ ( vehicle.ctOwner != nullptr ) && ( vehicle.ctOwner->Vehicle() != m_input.vehicle ) }; auto const isplayervehicle { ( m_input.train != nullptr ) && ( m_input.train->Dynamic() == m_input.vehicle ) }; auto const isdieselenginepowered { ( mover.EngineType == TEngineType::DieselElectric ) || ( mover.EngineType == TEngineType::DieselEngine ) }; auto const isdieselinshuntmode { mover.ShuntMode && mover.EngineType == TEngineType::DieselElectric }; diff --git a/messaging.cpp b/messaging.cpp index cae047ff..95712c0c 100644 --- a/messaging.cpp +++ b/messaging.cpp @@ -370,7 +370,7 @@ WyslijObsadzone() r.fPar[ 16 * i + 4 ] = vehicle->GetPosition().x; r.fPar[ 16 * i + 5 ] = vehicle->GetPosition().y; r.fPar[ 16 * i + 6 ] = vehicle->GetPosition().z; - r.iPar[ 16 * i + 7 ] = static_cast( vehicle->Mechanik->GetAction() ); + r.iPar[ 16 * i + 7 ] = static_cast( vehicle->Mechanik->action() ); strcpy( r.cString + 64 * i + 32, vehicle->GetTrack()->IsolatedName().c_str() ); strcpy( r.cString + 64 * i + 48, vehicle->Mechanik->TrainName().c_str() ); i++; diff --git a/renderer.cpp b/renderer.cpp index 58de9245..e1c23d04 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -179,16 +179,17 @@ opengl_particles::update( opengl_camera const &Camera ) { if( m_buffercapacity < m_particlevertices.size() ) { // allocate gpu side buffer big enough to hold the data m_buffercapacity = 0; - if( m_buffer != -1 ) { + if( m_buffer != (GLuint)-1 ) { // get rid of the old buffer ::glDeleteBuffers( 1, &m_buffer ); + m_buffer = (GLuint)-1; } ::glGenBuffers( 1, &m_buffer ); - ::glBindBuffer( GL_ARRAY_BUFFER, m_buffer ); - if( m_buffer > 0 ) { + if( ( m_buffer > 0 ) && ( m_buffer != (GLuint)-1 ) ) { // if we didn't get a buffer we'll try again during the next draw call // NOTE: we match capacity instead of current size to reduce number of re-allocations auto const particlecount { m_particlevertices.capacity() }; + ::glBindBuffer( GL_ARRAY_BUFFER, m_buffer ); ::glBufferData( GL_ARRAY_BUFFER, particlecount * sizeof( particle_vertex ), @@ -198,7 +199,7 @@ opengl_particles::update( opengl_camera const &Camera ) { // TBD: throw a bad_alloc? ErrorLog( "openGL error: out of memory; failed to create a geometry buffer" ); ::glDeleteBuffers( 1, &m_buffer ); - m_buffer = -1; + m_buffer = (GLuint)-1; } else { m_buffercapacity = particlecount; @@ -206,7 +207,7 @@ opengl_particles::update( opengl_camera const &Camera ) { } } // ...send the data... - if( m_buffer > 0 ) { + if( ( m_buffer > 0 ) && ( m_buffer != (GLuint)-1 ) ) { // if the buffer exists at this point it's guaranteed to be big enough to hold our data ::glBindBuffer( GL_ARRAY_BUFFER, m_buffer ); ::glBufferSubData( @@ -225,6 +226,7 @@ opengl_particles::render( int const Textureunit ) { if( false == Global.Smoke ) { return; } if( m_buffercapacity == 0 ) { return; } if( m_particlevertices.empty() ) { return; } + if( ( m_buffer == 0 ) || ( m_buffer == (GLuint)-1 ) ) { return; } // setup... ::glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT ); @@ -239,6 +241,10 @@ opengl_particles::render( int const Textureunit ) { // ...draw... ::glDrawArrays( GL_QUADS, 0, m_particlevertices.size() ); // ...and cleanup + ::glBindBuffer( GL_ARRAY_BUFFER, 0 ); + if( Global.bUseVBO ) { + gfx::opengl_vbogeometrybank::reset(); + } ::glPopClientAttrib(); } @@ -3163,10 +3169,6 @@ opengl_renderer::Render_particles() { Bind_Texture( m_smoketexture ); m_particlerenderer.render( m_diffusetextureunit ); - if( Global.bUseVBO ) { - // shouldn't be strictly necessary but, eh - gfx::opengl_vbogeometrybank::reset(); - } ::glDepthMask( GL_TRUE ); ::glEnable( GL_LIGHTING ); diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index a58e16d1..5d686521 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -672,7 +672,7 @@ state_serializer::deserialize_endtrainset( cParser &Input, scene::scratch_data & for( auto *vehicle : Scratchpad.trainset.vehicles ) { // go through list of vehicles in the trainset, coupling them together and checking for potential driver if( ( vehicle->Mechanik != nullptr ) - && ( vehicle->Mechanik->Primary() ) ) { + && ( vehicle->Mechanik->primary() ) ) { // primary driver will receive the timetable for this trainset Scratchpad.trainset.driver = vehicle; // they'll also receive assignment data if there's any diff --git a/version.h b/version.h index f159e50b..e4cf28bb 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 902 +#define VERSION_MINOR 906 #define VERSION_REVISION 0