diff --git a/Button.cpp b/Button.cpp index 3d8d5511..219c1f64 100644 --- a/Button.cpp +++ b/Button.cpp @@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/. #include "Button.h" #include "parser.h" #include "Model3d.h" +#include "DynObj.h" #include "Console.h" #include "Logs.h" #include "renderer.h" @@ -25,17 +26,19 @@ void TButton::Clear(int i) Update(); // kasowanie bitu Feedback, o ile jakiś ustawiony }; -void TButton::Init( std::string const &asName, TModel3d *pModel, bool bNewOn ) { +bool TButton::Init( std::string const &asName, TModel3d const *pModel, bool bNewOn ) { - if( pModel == nullptr ) { return; } + if( pModel == nullptr ) { return false; } pModelOn = pModel->GetFromName( asName + "_on" ); pModelOff = pModel->GetFromName( asName + "_off" ); m_state = bNewOn; Update(); + + return( ( pModelOn != nullptr ) || ( pModelOff != nullptr ) ); }; -void TButton::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *pModel1, TModel3d *pModel2 ) { +void TButton::Load( cParser &Parser, TDynamicObject const *Owner ) { std::string submodelname; @@ -57,21 +60,17 @@ void TButton::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *pMod m_soundfxincrease.owner( Owner ); m_soundfxdecrease.owner( Owner ); - if( pModel1 ) { - // poszukiwanie submodeli w modelu - Init( submodelname, pModel1, false ); + std::array sources { Owner->mdKabina, Owner->mdLowPolyInt, Owner->mdModel }; + for( auto const *source : sources ) { + if( true == Init( submodelname, source, false ) ) { + // got what we wanted, bail out + break; + } } - if( ( pModelOn == nullptr ) - && ( pModelOff == nullptr ) - && ( pModel2 != nullptr ) ) { - // poszukiwanie submodeli w modelu - Init( submodelname, pModel2, false ); - } - if( ( pModelOn == nullptr ) && ( pModelOff == nullptr ) ) { // if we failed to locate even one state submodel, cry - ErrorLog( "Bad model: failed to locate sub-model \"" + submodelname + "\" in 3d model \"" + ( pModel1 != nullptr ? pModel1->NameGet() : pModel2 != nullptr ? pModel2->NameGet() : "NULL" ) + "\"", logtype::model ); + ErrorLog( "Bad model: failed to locate sub-model \"" + submodelname + "\" in 3d model(s) of \"" + Owner->name() + "\"", logtype::model ); } // pass submodel location to defined sounds diff --git a/Button.h b/Button.h index bfb993ac..67bd312d 100644 --- a/Button.h +++ b/Button.h @@ -31,8 +31,8 @@ public: return ( ( pModelOn != nullptr ) || ( pModelOff != nullptr ) ); } void Update(); - void Init( std::string const &asName, TModel3d *pModel, bool bNewOn = false ); - void Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *pModel1, TModel3d *pModel2 = nullptr ); + bool Init( std::string const &asName, TModel3d const *pModel, bool bNewOn = false ); + void Load( cParser &Parser, TDynamicObject const *Owner ); void AssignBool(bool const *bValue); // returns offset of submodel associated with the button from the model centre glm::vec3 model_offset() const; diff --git a/DynObj.cpp b/DynObj.cpp index dc067d34..058e66a0 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -648,16 +648,14 @@ TDynamicObject::toggle_lights() { } void -TDynamicObject::set_cab_lights( float const Level ) { - - if( Level == InteriorLightLevel ) { return; } - - InteriorLightLevel = Level; +TDynamicObject::set_cab_lights( int const Cab, float const Level ) { for( auto §ion : Sections ) { // cab compartments are placed at the beginning of the list, so we can bail out as soon as we find different compartment type auto const sectionname { section.compartment->pName }; + if( sectionname.size() < 4 ) { return; } if( sectionname.find( "cab" ) != 0 ) { return; } + if( sectionname[ 3 ] != Cab + '0' ) { continue; } // match the cab with correct index section.light_level = Level; } @@ -985,7 +983,8 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) btnOn = true; } - if( ( Mechanik != nullptr ) + 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 ) ) ) { // rysowanie figurki mechanika @@ -1040,10 +1039,19 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) // else btHeadSignals23.TurnOff(); } // interior light levels + auto sectionlightcolor { glm::vec4( 1.f ) }; for( auto const §ion : Sections ) { - section.compartment->SetLightLevel( section.light_level, true ); + /* + sectionlightcolor = glm::vec4( InteriorLight, section.light_level ); + */ + sectionlightcolor = glm::vec4( + ( ( ( section.light_level == 0.f ) || ( Global.fLuminance > section.compartment->fLight ) ) ? + glm::vec3( 240.f / 255.f ) : // TBD: save and restore initial submodel diffuse instead of enforcing one? + InteriorLight ), // TODO: per-compartment (type) light color + section.light_level ); + section.compartment->SetLightLevel( sectionlightcolor, true ); if( section.load != nullptr ) { - section.load->SetLightLevel( section.light_level, true ); + section.load->SetLightLevel( sectionlightcolor, true ); } } // load chunks visibility @@ -1062,7 +1070,17 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) sectionchunk = sectionchunk->NextGet(); } } - + // driver cabs visibility + for( int cabidx = 0; cabidx < LowPolyIntCabs.size(); ++cabidx ) { + if( LowPolyIntCabs[ cabidx ] == nullptr ) { continue; } + LowPolyIntCabs[ cabidx ]->iVisible = ( + mdKabina == nullptr ? true : // there's no hi-fi cab + bDisplayCab == false ? true : // we're in external view + simulation::Train == nullptr ? true : // not a player-driven vehicle, implies external view + simulation::Train->Dynamic() != this ? true : // not a player-driven vehicle, implies external view + JointCabs ? false : // internal view, all cabs share the model so hide them 'all' + ( simulation::Train->iCabn != cabidx ) ); // internal view, hide occupied cab and show others + } } // ABu 29.01.05 koniec przeklejenia ************************************* @@ -2185,9 +2203,18 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424" // check the low poly interior for potential compartments of interest, ie ones which can be individually lit // TODO: definition of relevant compartments in the .mmd file TSubModel *submodel { nullptr }; - if( ( submodel = mdLowPolyInt->GetFromName( "cab1" ) ) != nullptr ) { Sections.push_back( { submodel, nullptr, 0.0f } ); } - if( ( submodel = mdLowPolyInt->GetFromName( "cab2" ) ) != nullptr ) { Sections.push_back( { submodel, nullptr, 0.0f } ); } - if( ( submodel = mdLowPolyInt->GetFromName( "cab0" ) ) != nullptr ) { Sections.push_back( { submodel, nullptr, 0.0f } ); } + if( ( submodel = mdLowPolyInt->GetFromName( "cab0" ) ) != nullptr ) { + Sections.push_back( { submodel, nullptr, 0.0f } ); + LowPolyIntCabs[ 0 ] = submodel; + } + if( ( submodel = mdLowPolyInt->GetFromName( "cab1" ) ) != nullptr ) { + Sections.push_back( { submodel, nullptr, 0.0f } ); + LowPolyIntCabs[ 1 ] = submodel; + } + if( ( submodel = mdLowPolyInt->GetFromName( "cab2" ) ) != nullptr ) { + Sections.push_back( { submodel, nullptr, 0.0f } ); + LowPolyIntCabs[ 2 ] = submodel; + } // passenger car compartments std::vector nameprefixes = { "corridor", "korytarz", "compartment", "przedzial" }; for( auto const &nameprefix : nameprefixes ) { @@ -5899,6 +5926,10 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co >> HuntingShake.fadein_end; } + else if( token == "jointcabs:" ) { + parser.getTokens(); + parser >> JointCabs; + } } while( token != "" ); diff --git a/DynObj.h b/DynObj.h index f6308ab7..7725f03b 100644 --- a/DynObj.h +++ b/DynObj.h @@ -197,6 +197,8 @@ public: TModel3d *mdLoad; // model zmiennego ładunku TModel3d *mdKabina; // model kabiny dla użytkownika; McZapkie-030303: to z train.h TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly + std::array LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs + bool JointCabs{ false }; // flag for vehicles with multiple virtual 'cabs' sharing location and 3d model(s) float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?) float LoadOffset { 0.f }; glm::vec3 InteriorLight { 0.9f * 255.f / 255.f, 0.9f * 216.f / 255.f, 0.9f * 176.f / 255.f }; // tungsten light. TODO: allow definition of light type? @@ -616,7 +618,7 @@ private: void Damage(char flag); void RaLightsSet(int head, int rear); int LightList( side const Side ) const { return iInventory[ Side ]; } - void set_cab_lights( float const Level ); + void set_cab_lights( int const Cab, float const Level ); TDynamicObject * FirstFind(int &coupler_nr, int cf = 1); float GetEPP(); // wyliczanie sredniego cisnienia w PG int DirectionSet(int d); // ustawienie kierunku w składzie diff --git a/Gauge.cpp b/Gauge.cpp index c9c09490..79218ce8 100644 --- a/Gauge.cpp +++ b/Gauge.cpp @@ -17,6 +17,7 @@ http://mozilla.org/MPL/2.0/. #include "Gauge.h" #include "parser.h" #include "Model3d.h" +#include "DynObj.h" #include "Timer.h" #include "Logs.h" #include "renderer.h" @@ -76,7 +77,7 @@ void TGauge::Init(TSubModel *Submodel, TGaugeAnimation Type, float Scale, float } }; -bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, TModel3d *md2, double mul ) { +void TGauge::Load( cParser &Parser, TDynamicObject const *Owner, double const mul ) { std::string submodelname, gaugetypename; float scale, endscale, endvalue, offset, friction; @@ -138,13 +139,17 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, if( interpolatescale ) { endscale *= mul; } - TSubModel *submodel = md1->GetFromName( submodelname ); - if (submodel) // jeśli nie znaleziony - md2 = nullptr; // informacja, że znaleziony - else if (md2) // a jest podany drugi model (np. zewnętrzny) - submodel = md2->GetFromName(submodelname); // to może tam będzie, co za różnica gdzie + TSubModel *submodel { nullptr }; + std::array sources { Owner->mdKabina, Owner->mdLowPolyInt }; + for( auto const *source : sources ) { + if( ( source != nullptr ) + && ( submodel = source->GetFromName( submodelname ) ) != nullptr ) { + // got what we wanted, bail out + break; + } + } if( submodel == nullptr ) { - ErrorLog( "Bad model: failed to locate sub-model \"" + submodelname + "\" in 3d model \"" + md1->NameGet() + "\"", logtype::model ); + ErrorLog( "Bad model: failed to locate sub-model \"" + submodelname + "\" in 3d model(s) of \"" + Owner->name() + "\"", logtype::model ); } std::map gaugetypes { @@ -163,7 +168,7 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, Init( submodel, type, scale, offset, friction, 0, endvalue, endscale, interpolatescale ); - return md2 != nullptr; // true, gdy podany model zewnętrzny, a w kabinie nie było +// return md2 != nullptr; // true, gdy podany model zewnętrzny, a w kabinie nie było }; bool diff --git a/Gauge.h b/Gauge.h index 82de24af..e812831b 100644 --- a/Gauge.h +++ b/Gauge.h @@ -38,7 +38,7 @@ public: void Clear() { *this = TGauge(); } void Init(TSubModel *Submodel, TGaugeAnimation Type, float Scale = 1, float Offset = 0, float Friction = 0, float Value = 0, float const Endvalue = -1.0, float const Endscale = -1.0, bool const Interpolate = false ); - bool Load(cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, TModel3d *md2 = nullptr, double mul = 1.0); + void Load(cParser &Parser, TDynamicObject const *Owner, double const mul = 1.0); void UpdateValue( float fNewDesired ); void UpdateValue( float fNewDesired, sound_source &Fallbacksound ); void PutValue(float fNewDesired); diff --git a/Model3d.cpp b/Model3d.cpp index 92a40e31..2977fa30 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -109,9 +109,12 @@ TSubModel::SetVisibilityLevel( float const Level, bool const Includechildren, bo // sets light level (alpha component of illumination color) to specified value void -TSubModel::SetLightLevel( float const Level, bool const Includechildren, bool const Includesiblings ) { - - f4Emision.a = Level; +TSubModel::SetLightLevel( glm::vec4 const &Level, bool const Includechildren, bool const Includesiblings ) { + /* + f4Emision = Level; + */ + f4Diffuse = { Level.r, Level.g, Level.b, f4Diffuse.a }; + f4Emision.a = Level.a; if( true == Includesiblings ) { auto sibling { this }; while( ( sibling = sibling->Next ) != nullptr ) { diff --git a/Model3d.h b/Model3d.h index af52323b..884dca3f 100644 --- a/Model3d.h +++ b/Model3d.h @@ -198,7 +198,7 @@ public: // sets visibility level (alpha component) to specified value void SetVisibilityLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false ); // sets light level (alpha component of illumination color) to specified value - void SetLightLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false ); + void SetLightLevel( glm::vec4 const &Level, bool const Includechildren = false, bool const Includesiblings = false ); inline float3 Translation1Get() { return fMatrix ? *(fMatrix->TranslationGet()) + v_TransVector : v_TransVector; } inline float3 Translation2Get() { diff --git a/Train.cpp b/Train.cpp index 02959338..38f1294e 100644 --- a/Train.cpp +++ b/Train.cpp @@ -30,13 +30,13 @@ http://mozilla.org/MPL/2.0/. #include "Console.h" #include "application.h" #include "renderer.h" - +/* namespace input { extern user_command command; } - +*/ void control_mapper::insert( TGauge const &Gauge, std::string const &Label ) { @@ -67,9 +67,10 @@ void TCab::Load(cParser &Parser) std::string token; Parser.getTokens(); Parser >> token; - if (token == "cablight") + if (token == "cablight:") { Parser.getTokens( 9, false ); +/* Parser >> dimm.r >> dimm.g @@ -80,6 +81,7 @@ void TCab::Load(cParser &Parser) >> intlitlow.r >> intlitlow.g >> intlitlow.b; +*/ Parser.getTokens(); Parser >> token; } CabPos1.x = std::stod( token ); @@ -369,10 +371,6 @@ TTrain::TTrain() { fBlinkTimer = 0; fHaslerTimer = 0; DynamicSet(NULL); // ustawia wszystkie mv* - iCabLightFlag = 0; - // hunter-091012 - bCabLight = false; - bCabLightDim = false; //----- pMechSittingPosition = Math3D::vector3(0, 0, 0); // ABu: 180404 fTachoTimer = 0.0; // włączenie skoków wskazań prędkościomierza @@ -765,6 +763,11 @@ void TTrain::OnCommand_mastercontrollerdecrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { // on press or hold Train->mvControlled->DecMainCtrl( 1 ); + Train->m_mastercontrollerinuse = true; + } + else { + // release + Train->m_mastercontrollerinuse = false; } } @@ -781,6 +784,11 @@ void TTrain::OnCommand_mastercontrollerset( TTrain *Train, command_data const &C if( Command.action != GLFW_RELEASE ) { // on press or hold Train->set_master_controller( Command.param1 ); + Train->m_mastercontrollerinuse = true; + } + else { + // release + Train->m_mastercontrollerinuse = false; } } @@ -797,6 +805,11 @@ void TTrain::OnCommand_secondcontrollerincrease( TTrain *Train, command_data con else { Train->mvControlled->IncScndCtrl( 1 ); } + Train->m_mastercontrollerinuse = true; + } + else { + // release + Train->m_mastercontrollerinuse = false; } } @@ -1028,17 +1041,39 @@ void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Co Train->set_train_brake( Train->mvOccupied->BrakeCtrlPos - Global.fBrakeStep ); } } + else { + // release + if( ( Train->mvOccupied->BrakeCtrlPos == -1 ) + && ( Train->mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) + && ( Train->DynamicObject->Controller != AIdriver ) + && ( Global.iFeedbackMode < 3 ) ) { + // Odskakiwanie hamulce EP + Train->set_train_brake( 0 ); + } + } } void TTrain::OnCommand_trainbrakeset( TTrain *Train, command_data const &Command ) { - Train->mvOccupied->BrakeLevelSet( - interpolate( - Train->mvOccupied->Handle->GetPos( bh_MIN ), - Train->mvOccupied->Handle->GetPos( bh_MAX ), - clamp( - Command.param1, - 0.0, 1.0 ) ) ); + if( Command.action != GLFW_RELEASE ) { + // press or hold + Train->mvOccupied->BrakeLevelSet( + interpolate( + Train->mvOccupied->Handle->GetPos( bh_MIN ), + Train->mvOccupied->Handle->GetPos( bh_MAX ), + clamp( + Command.param1, + 0.0, 1.0 ) ) ); + } else { + // release + if( ( Train->mvOccupied->BrakeCtrlPos == -1 ) + && ( Train->mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) + && ( Train->DynamicObject->Controller != AIdriver ) + && ( Global.iFeedbackMode < 3 ) ) { + // Odskakiwanie hamulce EP + Train->set_train_brake( 0 ); + } + } } void TTrain::OnCommand_trainbrakecharging( TTrain *Train, command_data const &Command ) { @@ -3758,7 +3793,7 @@ void TTrain::OnCommand_interiorlighttoggle( TTrain *Train, command_data const &C if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( false == Train->bCabLight ) { + if( false == Train->Cabine[Train->iCabn].bLight ) { // turn on OnCommand_interiorlightenable( Train, Command ); } @@ -3780,11 +3815,18 @@ void TTrain::OnCommand_interiorlightenable( TTrain *Train, command_data const &C } // visual feedback Train->ggCabLightButton.UpdateValue( 1.0, Train->dsbSwitch ); - - if( true == Train->bCabLight ) { return; } // already enabled - - Train->bCabLight = true; Train->btCabLight.Turn( true ); + // store lighting switch states + if( false == Train->DynamicObject->JointCabs ) { + // vehicles with separate cabs get separate lighting switch states + Train->Cabine[ Train->iCabn ].bLight = true; + } + else { + // joint virtual cabs share lighting switch states + for( auto &cab : Train->Cabine ) { + cab.bLight = true; + } + } } } @@ -3799,11 +3841,18 @@ void TTrain::OnCommand_interiorlightdisable( TTrain *Train, command_data const & } // visual feedback Train->ggCabLightButton.UpdateValue( 0.0, Train->dsbSwitch ); - - if( false == Train->bCabLight ) { return; } // already disabled - - Train->bCabLight = false; Train->btCabLight.Turn( false ); + // store lighting switch states + if( false == Train->DynamicObject->JointCabs ) { + // vehicles with separate cabs get separate lighting switch states + Train->Cabine[ Train->iCabn ].bLight = false; + } + else { + // joint virtual cabs share lighting switch states + for( auto &cab : Train->Cabine ) { + cab.bLight = false; + } + } } } @@ -3811,7 +3860,7 @@ void TTrain::OnCommand_interiorlightdimtoggle( TTrain *Train, command_data const if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( false == Train->bCabLightDim ) { + if( false == Train->Cabine[ Train->iCabn ].bLightDim ) { // turn on OnCommand_interiorlightdimenable( Train, Command ); } @@ -3833,10 +3882,17 @@ void TTrain::OnCommand_interiorlightdimenable( TTrain *Train, command_data const } // visual feedback Train->ggCabLightDimButton.UpdateValue( 1.0, Train->dsbSwitch ); - - if( true == Train->bCabLightDim ) { return; } // already enabled - - Train->bCabLightDim = true; + // store lighting switch states + if( false == Train->DynamicObject->JointCabs ) { + // vehicles with separate cabs get separate lighting switch states + Train->Cabine[ Train->iCabn ].bLightDim = true; + } + else { + // joint virtual cabs share lighting switch states + for( auto &cab : Train->Cabine ) { + cab.bLightDim = true; + } + } } } @@ -3851,10 +3907,17 @@ void TTrain::OnCommand_interiorlightdimdisable( TTrain *Train, command_data cons } // visual feedback Train->ggCabLightDimButton.UpdateValue( 0.0, Train->dsbSwitch ); - - if( false == Train->bCabLightDim ) { return; } // already disabled - - Train->bCabLightDim = false; + // store lighting switch states + if( false == Train->DynamicObject->JointCabs ) { + // vehicles with separate cabs get separate lighting switch states + Train->Cabine[ Train->iCabn ].bLightDim = false; + } + else { + // joint virtual cabs share lighting switch states + for( auto &cab : Train->Cabine ) { + cab.bLightDim = false; + } + } } } @@ -4808,10 +4871,13 @@ bool TTrain::Update( double const Deltatime ) || ( mvOccupied->TrainType == dt_EP05 ) ) { // dla ET40 i EU05 automatyczne cofanie nastawnika - i tak nie będzie to działać dobrze... // TODO: use deltatime to stabilize speed +/* if( false == ( ( input::command == user_command::mastercontrollerset ) || ( input::command == user_command::mastercontrollerincrease ) || ( input::command == user_command::mastercontrollerdecrease ) ) ) { +*/ + if( false == m_mastercontrollerinuse ) { if( mvOccupied->MainCtrlPos > mvOccupied->MainCtrlActualPos ) { mvOccupied->DecMainCtrl( 1 ); } @@ -4821,7 +4887,7 @@ bool TTrain::Update( double const Deltatime ) } } } - +/* if( ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) && ( mvOccupied->fBrakeCtrlPos < 0.0 ) && ( Global.iFeedbackMode < 3 ) ) { @@ -4833,6 +4899,7 @@ bool TTrain::Update( double const Deltatime ) set_train_brake( 0 ); } } +*/ } // McZapkie: predkosc wyswietlana na tachometrze brana jest z obrotow kol @@ -5021,17 +5088,6 @@ bool TTrain::Update( double const Deltatime ) Console::ValueSet(6, fTachoVelocity); } #endif - // hunter-091012: swiatlo - if (bCabLight == true) - { - if (bCabLightDim == true) - iCabLightFlag = 1; - else - iCabLightFlag = 2; - } - else - iCabLightFlag = 0; - //------------------ // hunter-261211: nadmiarowy przetwornicy i ogrzewania // Ra 15-01: to musi stąd wylecieć - zależności nie mogą być w kabinie @@ -5770,43 +5826,34 @@ bool TTrain::Update( double const Deltatime ) btHaslerCurrent.Turn(DynamicObject->MoverParameters->Im != 0.0); // prąd na silnikach // calculate current level of interior illumination - // TODO: organize it along with rest of train update in a more sensible arrangement - auto interiorlightlevel { 0.f }; - switch( iCabLightFlag ) // Ra: uzeleżnic od napięcia w obwodzie sterowania - { // hunter-091012: uzaleznienie jasnosci od przetwornicy - case 0: { - //światło wewnętrzne zgaszone - interiorlightlevel = 0.0f; - break; - } - case 1: { - //światło wewnętrzne przygaszone (255 216 176) - auto const converteractive { ( - ( mvOccupied->ConverterFlag ) - || ( ( ( mvOccupied->Couplers[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::front ].Connected->ConverterFlag ) - || ( ( ( mvOccupied->Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::rear ].Connected->ConverterFlag ) ) }; + { + // TODO: organize it along with rest of train update in a more sensible arrangement + auto const converteractive{ ( + ( mvOccupied->ConverterFlag ) + || ( ( ( mvOccupied->Couplers[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::front ].Connected->ConverterFlag ) + || ( ( ( mvOccupied->Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::rear ].Connected->ConverterFlag ) ) }; + // Ra: uzeleżnic od napięcia w obwodzie sterowania + // hunter-091012: uzaleznienie jasnosci od przetwornicy + int cabidx { 0 }; + for( auto &cab : Cabine ) { - interiorlightlevel = ( - converteractive ? - 0.4f : - 0.2f ); - break; - } - case 2: { - //światło wewnętrzne zapalone (255 216 176) - auto const converteractive { ( - ( mvOccupied->ConverterFlag ) - || ( ( ( mvOccupied->Couplers[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::front ].Connected->ConverterFlag ) - || ( ( ( mvOccupied->Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::rear ].Connected->ConverterFlag ) ) }; + auto const cablightlevel = + ( ( cab.bLight == false ) ? 0.f : + ( cab.bLightDim == true ) ? 0.4f : + 1.f ) + * ( converteractive ? 1.f : 0.5f ); - interiorlightlevel = ( - converteractive ? - 1.0f : - 0.5f ); - break; + if( cab.LightLevel != cablightlevel ) { + cab.LightLevel = cablightlevel; + DynamicObject->set_cab_lights( cabidx, cab.LightLevel ); + } + if( cabidx == iCabn ) { + DynamicObject->InteriorLightLevel = cablightlevel; + } + + ++cabidx; } } - DynamicObject->set_cab_lights( interiorlightlevel ); // anti slip system activation, maintained while the control button is down if( mvOccupied->BrakeSystem != TBrakeSystem::ElectroPneumatic ) { @@ -6192,15 +6239,16 @@ bool TTrain::CabChange(int iDirection) else { // jeśli pojazd prowadzony ręcznie albo wcale (wagon) DynamicObject->MoverParameters->CabDeactivisation(); - if (DynamicObject->MoverParameters->ChangeCab(iDirection)) - if (InitializeCab(DynamicObject->MoverParameters->ActiveCab, - DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + - ".mmd")) - { // zmiana kabiny w ramach tego samego pojazdu + if( DynamicObject->MoverParameters->ChangeCab( iDirection ) ) { + if( InitializeCab( + DynamicObject->MoverParameters->ActiveCab, + DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" ) ) { + // zmiana kabiny w ramach tego samego pojazdu DynamicObject->MoverParameters->CabActivisation(); // załączenie rozrządu (wirtualne kabiny) DynamicObject->Mechanik->CheckVehicles( Change_direction ); return true; // udało się zmienić kabinę } + } // aktywizacja poprzedniej, bo jeszcze nie wiadomo, czy jakiś pojazd jest DynamicObject->MoverParameters->CabActivisation(); } @@ -6496,10 +6544,10 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) >> viewangle.y // yaw first, then pitch >> viewangle.x; pMechViewAngle = glm::radians( viewangle ); -/* - Global.pCamera.Pitch = pMechViewAngle.x; - Global.pCamera.Yaw = pMechViewAngle.y; -*/ + + Global.pCamera.Angle.x = pMechViewAngle.x; + Global.pCamera.Angle.y = pMechViewAngle.y; + parser.getTokens(); parser >> token; } @@ -6579,11 +6627,13 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) } clear_cab_controls(); } +/* if (nullptr == DynamicObject->mdKabina) { // don't bother with other parts until the cab is initialised continue; } +*/ else if (true == initialize_gauge(parser, token, cabindex)) { // matched the token, grab the next one @@ -6603,7 +6653,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) >> submodelname >> renderername; - auto const *submodel { DynamicObject->mdKabina->GetFromName( submodelname ) }; + auto const *submodel { ( DynamicObject->mdKabina ? DynamicObject->mdKabina->GetFromName( submodelname ) : nullptr ) }; if( submodel == nullptr ) { WriteLog( "Python Screen: submodel " + submodelname + " not found - Ignoring screen" ); continue; @@ -6628,8 +6678,10 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) { return false; } +/* if (DynamicObject->mdKabina) { +*/ // configure placement of sound emitters which aren't bound with any device model, and weren't placed manually // try first to bind sounds to location of possible devices if( dsbReverserKey.offset() == nullvector ) { @@ -6681,28 +6733,37 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) } } - DynamicObject->mdKabina->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie binarnego - set_cab_controls(); + if( DynamicObject->mdKabina ) + DynamicObject->mdKabina->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie binarnego + set_cab_controls( NewCabNo < 0 ? 2 : NewCabNo ); +/* return true; } return (token == "none"); +*/ + return true; } Math3D::vector3 TTrain::MirrorPosition(bool lewe) { // zwraca współrzędne widoku kamery z lusterka switch (iCabn) { - case 1: // przednia (1) - return DynamicObject->mMatrix * - Math3D::vector3(lewe ? Cabine[iCabn].CabPos2.x : Cabine[iCabn].CabPos1.x, - 1.5 + Cabine[iCabn].CabPos1.y, Cabine[iCabn].CabPos2.z); case 2: // tylna (-1) return DynamicObject->mMatrix * - Math3D::vector3(lewe ? Cabine[iCabn].CabPos1.x : Cabine[iCabn].CabPos2.x, - 1.5 + Cabine[iCabn].CabPos1.y, Cabine[iCabn].CabPos1.z); + Math3D::vector3( + mvOccupied->Dim.W * ( lewe ? -0.5 : 0.5 ) + 0.2 * ( lewe ? -1 : 1 ), + 1.5 + Cabine[iCabn].CabPos1.y, + Cabine[iCabn].CabPos1.z); + case 1: // przednia (1) + default: + return DynamicObject->mMatrix * + Math3D::vector3( + mvOccupied->Dim.W * ( lewe ? 0.5 : -0.5 ) + 0.2 * ( lewe ? 1 : -1 ), + 1.5 + Cabine[iCabn].CabPos1.y, + Cabine[iCabn].CabPos2.z); } - return DynamicObject->GetPosition(); // współrzędne środka pojazdu +// return DynamicObject->GetPosition(); // współrzędne środka pojazdu }; void TTrain::DynamicSet(TDynamicObject *d) @@ -7052,20 +7113,20 @@ void TTrain::clear_cab_controls() } // NOTE: we can get rid of this function once we have per-cab persistent state -void TTrain::set_cab_controls() { +void TTrain::set_cab_controls( int const Cab ) { // switches // battery if( true == mvOccupied->Battery ) { - ggBatteryButton.PutValue( 1.0 ); + ggBatteryButton.PutValue( 1.f ); } // motor connectors ggStLinOffButton.PutValue( ( mvControlled->StLinSwitchOff ? - 1.0 : - 0.0 ) ); + 1.f : + 0.f ) ); // radio if( true == mvOccupied->Radio ) { - ggRadioButton.PutValue( 1.0 ); + ggRadioButton.PutValue( 1.f ); } ggRadioChannelSelector.PutValue( iRadioChannel - 1 ); // pantographs @@ -7073,96 +7134,96 @@ void TTrain::set_cab_controls() { if( ggPantFrontButton.SubModel ) { ggPantFrontButton.PutValue( ( mvControlled->PantFrontUp ? - 1.0 : - 0.0 ) ); + 1.f : + 0.f ) ); } if( ggPantFrontButtonOff.SubModel ) { ggPantFrontButtonOff.PutValue( ( mvControlled->PantFrontUp ? - 0.0 : - 1.0 ) ); + 0.f : + 1.f ) ); } // NOTE: currently we animate the selectable pantograph control for both pantographs // TODO: implement actual selection control, and refactor handling this control setup in a separate method if( ggPantSelectedButton.SubModel ) { ggPantSelectedButton.PutValue( ( mvControlled->PantFrontUp ? - 1.0 : - 0.0 ) ); + 1.f : + 0.f ) ); } if( ggPantSelectedDownButton.SubModel ) { ggPantSelectedDownButton.PutValue( ( mvControlled->PantFrontUp ? - 0.0 : - 1.0 ) ); + 0.f : + 1.f ) ); } } if( mvOccupied->PantSwitchType != "impulse" ) { if( ggPantRearButton.SubModel ) { ggPantRearButton.PutValue( ( mvControlled->PantRearUp ? - 1.0 : - 0.0 ) ); + 1.f : + 0.f ) ); } if( ggPantRearButtonOff.SubModel ) { ggPantRearButtonOff.PutValue( ( mvControlled->PantRearUp ? - 0.0 : - 1.0 ) ); + 0.f : + 1.f ) ); } // NOTE: currently we animate the selectable pantograph control for both pantographs // TODO: implement actual selection control, and refactor handling this control setup in a separate method if( ggPantSelectedButton.SubModel ) { ggPantSelectedButton.PutValue( ( mvControlled->PantRearUp ? - 1.0 : - 0.0 ) ); + 1.f : + 0.f ) ); } if( ggPantSelectedDownButton.SubModel ) { ggPantSelectedDownButton.PutValue( ( mvControlled->PantRearUp ? - 0.0 : - 1.0 ) ); + 0.f : + 1.f ) ); } } // auxiliary compressor ggPantCompressorValve.PutValue( mvControlled->bPantKurek3 ? - 0.0 : // default setting is pantographs connected with primary tank - 1.0 ); + 0.f : // default setting is pantographs connected with primary tank + 1.f ); ggPantCompressorButton.PutValue( mvControlled->PantCompFlag ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); // converter if( mvOccupied->ConvSwitchType != "impulse" ) { ggConverterButton.PutValue( mvControlled->ConverterAllow ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } ggConverterLocalButton.PutValue( mvControlled->ConverterAllowLocal ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); // compressor ggCompressorButton.PutValue( mvControlled->CompressorAllow ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); ggCompressorLocalButton.PutValue( mvControlled->CompressorAllowLocal ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); // motor overload relay threshold / shunt mode ggMaxCurrentCtrl.PutValue( ( true == mvControlled->ShuntModeAllow ? ( true == mvControlled->ShuntMode ? - 1.0 : - 0.0 ) : + 1.f : + 0.f ) : ( mvControlled->Imax == mvControlled->ImaxHi ? - 1.0 : - 0.0 ) ) ); + 1.f : + 0.f ) ) ); // lights ggLightsButton.PutValue( mvOccupied->LightsPos - 1 ); @@ -7172,84 +7233,84 @@ void TTrain::set_cab_controls() { side::rear ); if( ( DynamicObject->iLights[ vehicleside ] & light::headlight_left ) != 0 ) { - ggLeftLightButton.PutValue( 1.0 ); + ggLeftLightButton.PutValue( 1.f ); } if( ( DynamicObject->iLights[ vehicleside ] & light::headlight_right ) != 0 ) { - ggRightLightButton.PutValue( 1.0 ); + ggRightLightButton.PutValue( 1.f ); } if( ( DynamicObject->iLights[ vehicleside ] & light::headlight_upper ) != 0 ) { - ggUpperLightButton.PutValue( 1.0 ); + ggUpperLightButton.PutValue( 1.f ); } if( ( DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) != 0 ) { if( ggLeftEndLightButton.SubModel != nullptr ) { - ggLeftEndLightButton.PutValue( 1.0 ); + ggLeftEndLightButton.PutValue( 1.f ); } else { - ggLeftLightButton.PutValue( -1.0 ); + ggLeftLightButton.PutValue( -1.f ); } } if( ( DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) != 0 ) { if( ggRightEndLightButton.SubModel != nullptr ) { - ggRightEndLightButton.PutValue( 1.0 ); + ggRightEndLightButton.PutValue( 1.f ); } else { - ggRightLightButton.PutValue( -1.0 ); + ggRightLightButton.PutValue( -1.f ); } } if( true == DynamicObject->DimHeadlights ) { - ggDimHeadlightsButton.PutValue( 1.0 ); + ggDimHeadlightsButton.PutValue( 1.f ); } // cab lights - if( true == bCabLight ) { - ggCabLightButton.PutValue( 1.0 ); + if( true == Cabine[Cab].bLight ) { + ggCabLightButton.PutValue( 1.f ); } - if( true == bCabLightDim ) { - ggCabLightDimButton.PutValue( 1.0 ); + if( true == Cabine[Cab].bLightDim ) { + ggCabLightDimButton.PutValue( 1.f ); } ggInstrumentLightButton.PutValue( ( InstrumentLightActive ? - 1.0 : - 0.0 ) ); + 1.f : + 0.f ) ); ggDashboardLightButton.PutValue( ( DashboardLightActive ? - 1.0 : - 0.0 ) ); + 1.f : + 0.f ) ); ggTimetableLightButton.PutValue( ( TimetableLightActive ? - 1.0 : - 0.0 ) ); + 1.f : + 0.f ) ); // doors // NOTE: we're relying on the cab models to have switches reversed for the rear cab(?) - ggDoorLeftButton.PutValue( mvOccupied->DoorLeftOpened ? 1.0 : 0.0 ); - ggDoorRightButton.PutValue( mvOccupied->DoorRightOpened ? 1.0 : 0.0 ); + ggDoorLeftButton.PutValue( mvOccupied->DoorLeftOpened ? 1.f : 0.f ); + ggDoorRightButton.PutValue( mvOccupied->DoorRightOpened ? 1.f : 0.f ); // door lock ggDoorSignallingButton.PutValue( mvOccupied->DoorLockEnabled ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); // heating if( true == mvControlled->Heating ) { - ggTrainHeatingButton.PutValue( 1.0 ); + ggTrainHeatingButton.PutValue( 1.f ); } // brake acting time if( ggBrakeProfileCtrl.SubModel != nullptr ) { ggBrakeProfileCtrl.PutValue( ( ( mvOccupied->BrakeDelayFlag & bdelay_R ) != 0 ? - 2.0 : + 2.f : mvOccupied->BrakeDelayFlag - 1 ) ); } if( ggBrakeProfileG.SubModel != nullptr ) { ggBrakeProfileG.PutValue( mvOccupied->BrakeDelayFlag == bdelay_G ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } if( ggBrakeProfileR.SubModel != nullptr ) { ggBrakeProfileR.PutValue( ( mvOccupied->BrakeDelayFlag & bdelay_R ) != 0 ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } if (ggBrakeOperationModeCtrl.SubModel != nullptr) { ggBrakeOperationModeCtrl.PutValue( @@ -7260,75 +7321,75 @@ void TTrain::set_cab_controls() { // alarm chain ggAlarmChain.PutValue( mvControlled->AlarmChainFlag ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); // brake signalling ggSignallingButton.PutValue( mvControlled->Signalling ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); // multiple-unit current indicator source ggNextCurrentButton.PutValue( ShowNextCurrent ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); // water pump ggWaterPumpBreakerButton.PutValue( mvControlled->WaterPump.breaker ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); if( ggWaterPumpButton.type() != TGaugeType::push ) { ggWaterPumpButton.PutValue( mvControlled->WaterPump.is_enabled ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } // water heater ggWaterHeaterBreakerButton.PutValue( mvControlled->WaterHeater.breaker ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); ggWaterHeaterButton.PutValue( mvControlled->WaterHeater.is_enabled ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); ggWaterCircuitsLinkButton.PutValue( mvControlled->WaterCircuitsLink ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); // fuel pump if( ggFuelPumpButton.type() != TGaugeType::push ) { ggFuelPumpButton.PutValue( mvControlled->FuelPump.is_enabled ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } // oil pump if( ggOilPumpButton.type() != TGaugeType::push ) { ggOilPumpButton.PutValue( mvControlled->OilPump.is_enabled ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } // traction motor fans if( ggMotorBlowersFrontButton.type() != TGaugeType::push ) { ggMotorBlowersFrontButton.PutValue( mvControlled->MotorBlowers[side::front].is_enabled ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } if( ggMotorBlowersRearButton.type() != TGaugeType::push ) { ggMotorBlowersRearButton.PutValue( mvControlled->MotorBlowers[side::rear].is_enabled ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } if( ggMotorBlowersAllOffButton.type() != TGaugeType::push ) { ggMotorBlowersAllOffButton.PutValue( ( mvControlled->MotorBlowers[side::front].is_disabled || mvControlled->MotorBlowers[ side::front ].is_disabled ) ? - 1.0 : - 0.0 ); + 1.f : + 0.f ); } // we reset all indicators, as they're set during the update pass @@ -7421,33 +7482,33 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co }; auto lookup = lights.find( Label ); if( lookup != lights.end() ) { - lookup->second.Load( Parser, DynamicObject, DynamicObject->mdKabina ); + lookup->second.Load( Parser, DynamicObject ); } else if( Label == "i-instrumentlight:" ) { - btInstrumentLight.Load( Parser, DynamicObject, DynamicObject->mdKabina, DynamicObject->mdModel ); + btInstrumentLight.Load( Parser, DynamicObject ); InstrumentLightType = 0; } else if( Label == "i-instrumentlight_M:" ) { - btInstrumentLight.Load( Parser, DynamicObject, DynamicObject->mdKabina, DynamicObject->mdModel ); + btInstrumentLight.Load( Parser, DynamicObject ); InstrumentLightType = 1; } else if( Label == "i-instrumentlight_C:" ) { - btInstrumentLight.Load( Parser, DynamicObject, DynamicObject->mdKabina, DynamicObject->mdModel ); + btInstrumentLight.Load( Parser, DynamicObject ); InstrumentLightType = 2; } else if (Label == "i-doors:") { int i = Parser.getToken() - 1; auto &button = Cabine[Cabindex].Button(-1); // pierwsza wolna lampka - button.Load(Parser, DynamicObject, DynamicObject->mdKabina); + button.Load(Parser, DynamicObject); button.AssignBool(bDoors[0] + 3 * i); } /* else if( Label == "i-malfunction:" ) { // generic malfunction indicator auto &button = Cabine[ Cabindex ].Button( -1 ); // pierwsza wolna gałka - button.Load( Parser, DynamicObject, DynamicObject->mdKabina ); + button.Load( Parser, DynamicObject ); button.AssignBool( &mvOccupied->dizel_heat.PA ); } */ @@ -7567,19 +7628,19 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con }; auto lookup = gauges.find( Label ); if( lookup != gauges.end() ) { - lookup->second.Load( Parser, DynamicObject, DynamicObject->mdKabina ); + lookup->second.Load( Parser, DynamicObject); m_controlmapper.insert( lookup->second, lookup->first ); } // ABu 090305: uniwersalne przyciski lub inne rzeczy else if( Label == "mainctrlact:" ) { - ggMainCtrlAct.Load( Parser, DynamicObject, DynamicObject->mdKabina, DynamicObject->mdModel ); + ggMainCtrlAct.Load( Parser, DynamicObject); } // SEKCJA WSKAZNIKOW else if ((Label == "tachometer:") || (Label == "tachometerb:")) { // predkosciomierz wskaźnikowy z szarpaniem auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(&fTachoVelocityJump); // bind tachometer sound location to the meter if( dsbHasler.offset() == glm::vec3() ) { @@ -7590,7 +7651,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { // predkosciomierz wskaźnikowy bez szarpania auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(&fTachoVelocity); // bind tachometer sound location to the meter if( dsbHasler.offset() == glm::vec3() ) { @@ -7601,7 +7662,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { // predkosciomierz cyfrowy auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(&fTachoVelocity); // bind tachometer sound location to the meter if( dsbHasler.offset() == glm::vec3() ) { @@ -7612,28 +7673,28 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { // 1szy amperomierz auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(fHCurrent + 1); } else if ((Label == "hvcurrent2:") || (Label == "hvcurrent2b:")) { // 2gi amperomierz auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(fHCurrent + 2); } else if ((Label == "hvcurrent3:") || (Label == "hvcurrent3b:")) { // 3ci amperomierz auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałska - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(fHCurrent + 3); } else if ((Label == "hvcurrent:") || (Label == "hvcurrentb:")) { // amperomierz calkowitego pradu auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(fHCurrent); } else if (Label == "eimscreen:") @@ -7643,7 +7704,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con Parser.getTokens(2, false); Parser >> i >> j; auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(&fEIMParams[i][j]); } else if (Label == "brakes:") @@ -7653,7 +7714,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con Parser.getTokens(2, false); Parser >> i >> j; auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(&fPress[i - 1][j]); } else if ((Label == "brakepress:") || (Label == "brakepressb:")) @@ -7661,79 +7722,79 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con // manometr cylindrow hamulcowych // Ra 2014-08: przeniesione do TCab auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina, nullptr, 0.1); + gauge.Load(Parser, DynamicObject, 0.1); gauge.AssignDouble(&mvOccupied->BrakePress); } else if ((Label == "pipepress:") || (Label == "pipepressb:")) { // manometr przewodu hamulcowego auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina, nullptr, 0.1); + gauge.Load(Parser, DynamicObject, 0.1); gauge.AssignDouble(&mvOccupied->PipePress); } else if (Label == "limpipepress:") { // manometr zbiornika sterujacego zaworu maszynisty - ggZbS.Load(Parser, DynamicObject, DynamicObject->mdKabina, nullptr, 0.1); + ggZbS.Load(Parser, DynamicObject, 0.1); } else if (Label == "cntrlpress:") { // manometr zbiornika kontrolnego/rorzďż˝du auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina, nullptr, 0.1); + gauge.Load(Parser, DynamicObject, 0.1); gauge.AssignDouble(&mvControlled->PantPress); } else if ((Label == "compressor:") || (Label == "compressorb:")) { // manometr sprezarki/zbiornika glownego auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina, nullptr, 0.1); + gauge.Load(Parser, DynamicObject, 0.1); gauge.AssignDouble(&mvOccupied->Compressor); } else if( Label == "oilpress:" ) { // oil pressure auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna gałka - gauge.Load( Parser, DynamicObject, DynamicObject->mdKabina, nullptr ); + gauge.Load( Parser, DynamicObject ); gauge.AssignFloat( &mvControlled->OilPump.pressure ); } else if( Label == "oiltemp:" ) { // oil temperature auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna gałka - gauge.Load( Parser, DynamicObject, DynamicObject->mdKabina, nullptr ); + gauge.Load( Parser, DynamicObject ); gauge.AssignFloat( &mvControlled->dizel_heat.To ); } else if( Label == "water1temp:" ) { // main circuit water temperature auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna gałka - gauge.Load( Parser, DynamicObject, DynamicObject->mdKabina, nullptr ); + gauge.Load( Parser, DynamicObject ); gauge.AssignFloat( &mvControlled->dizel_heat.temperatura1 ); } else if( Label == "water2temp:" ) { // auxiliary circuit water temperature auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna gałka - gauge.Load( Parser, DynamicObject, DynamicObject->mdKabina, nullptr ); + gauge.Load( Parser, DynamicObject ); gauge.AssignFloat( &mvControlled->dizel_heat.temperatura2 ); } // yB - dla drugiej sekcji else if (Label == "hvbcurrent1:") { // 1szy amperomierz - ggI1B.Load(Parser, DynamicObject, DynamicObject->mdKabina); + ggI1B.Load(Parser, DynamicObject); } else if (Label == "hvbcurrent2:") { // 2gi amperomierz - ggI2B.Load(Parser, DynamicObject, DynamicObject->mdKabina); + ggI2B.Load(Parser, DynamicObject); } else if (Label == "hvbcurrent3:") { // 3ci amperomierz - ggI3B.Load(Parser, DynamicObject, DynamicObject->mdKabina); + ggI3B.Load(Parser, DynamicObject); } else if (Label == "hvbcurrent:") { // amperomierz calkowitego pradu - ggItotalB.Load(Parser, DynamicObject, DynamicObject->mdKabina); + ggItotalB.Load(Parser, DynamicObject); } //************************************************************* else if (Label == "clock:") @@ -7741,76 +7802,78 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con // zegar analogowy if (Parser.getToken() == "analog") { - // McZapkie-300302: zegarek - ggClockSInd.Init(DynamicObject->mdKabina->GetFromName("ClockShand"), TGaugeAnimation::gt_Rotate, 1.0/60.0); - ggClockMInd.Init(DynamicObject->mdKabina->GetFromName("ClockMhand"), TGaugeAnimation::gt_Rotate, 1.0/60.0); - ggClockHInd.Init(DynamicObject->mdKabina->GetFromName("ClockHhand"), TGaugeAnimation::gt_Rotate, 1.0/12.0); + if( DynamicObject->mdKabina ) { + // McZapkie-300302: zegarek + ggClockSInd.Init( DynamicObject->mdKabina->GetFromName( "ClockShand" ), TGaugeAnimation::gt_Rotate, 1.0 / 60.0 ); + ggClockMInd.Init( DynamicObject->mdKabina->GetFromName( "ClockMhand" ), TGaugeAnimation::gt_Rotate, 1.0 / 60.0 ); + ggClockHInd.Init( DynamicObject->mdKabina->GetFromName( "ClockHhand" ), TGaugeAnimation::gt_Rotate, 1.0 / 12.0 ); + } } } else if (Label == "evoltage:") { // woltomierz napiecia silnikow - ggEngineVoltage.Load(Parser, DynamicObject, DynamicObject->mdKabina); + ggEngineVoltage.Load(Parser, DynamicObject); } else if (Label == "hvoltage:") { // woltomierz wysokiego napiecia auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(&fHVoltage); } else if (Label == "lvoltage:") { // woltomierz niskiego napiecia - ggLVoltage.Load(Parser, DynamicObject, DynamicObject->mdKabina); + ggLVoltage.Load(Parser, DynamicObject); } else if (Label == "enrot1m:") { // obrotomierz auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(fEngine + 1); } // ggEnrot1m.Load(Parser,DynamicObject->mdKabina); else if (Label == "enrot2m:") { // obrotomierz auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(fEngine + 2); } // ggEnrot2m.Load(Parser,DynamicObject->mdKabina); else if (Label == "enrot3m:") { // obrotomierz auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignFloat(fEngine + 3); } // ggEnrot3m.Load(Parser,DynamicObject->mdKabina); else if (Label == "engageratio:") { // np. ciśnienie sterownika sprzęgła auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignDouble(&mvControlled->dizel_engage); } // ggEngageRatio.Load(Parser,DynamicObject->mdKabina); else if (Label == "maingearstatus:") { // np. ciśnienie sterownika skrzyni biegów - ggMainGearStatus.Load(Parser, DynamicObject, DynamicObject->mdKabina); + ggMainGearStatus.Load(Parser, DynamicObject); } else if (Label == "ignitionkey:") { - ggIgnitionKey.Load(Parser, DynamicObject, DynamicObject->mdKabina); + ggIgnitionKey.Load(Parser, DynamicObject); } else if (Label == "distcounter:") { // Ra 2014-07: licznik kilometrów auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignDouble(&mvControlled->DistCounter); } else if( Label == "shuntmodepower:" ) { // shunt mode power slider auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka - gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina); + gauge.Load(Parser, DynamicObject); gauge.AssignDouble(&mvControlled->AnPos); m_controlmapper.insert( gauge, "shuntmodepower:" ); } diff --git a/Train.h b/Train.h index 144f05ae..78e3c3ff 100644 --- a/Train.h +++ b/Train.h @@ -33,16 +33,21 @@ public: // methods void Load(cParser &Parser); void Update(); + TGauge &Gauge( int n = -1 ); // pobranie adresu obiektu + TButton &Button( int n = -1 ); // pobranie adresu obiektu // members Math3D::vector3 CabPos1 { 0, 1, 1 }; Math3D::vector3 CabPos2 { 0, 1, -1 }; bool bEnabled { false }; bool bOccupied { true }; +/* glm::vec3 dimm; // McZapkie-120503: tlumienie swiatla glm::vec3 intlit; // McZapkie-120503: oswietlenie kabiny glm::vec3 intlitlow; // McZapkie-120503: przyciemnione oswietlenie kabiny - TGauge &Gauge( int n = -1 ); // pobranie adresu obiektu - TButton &Button( int n = -1 ); // pobranie adresu obiektu +*/ + bool bLight { false }; // hunter-091012: czy swiatlo jest zapalone? + bool bLightDim { false }; // hunter-091012: czy przyciemnienie kabiny jest zapalone? + float LightLevel{ 0.f }; // last calculated interior light level private: // members @@ -121,7 +126,7 @@ class TTrain void clear_cab_controls(); // sets cabin controls based on current state of the vehicle // NOTE: we can get rid of this function once we have per-cab persistent state - void set_cab_controls(); + void set_cab_controls( int const Cab ); // initializes a gauge matching provided label. returns: true if the label was found, false otherwise bool initialize_gauge(cParser &Parser, std::string const &Label, int const Cabindex); // initializes a button matching provided label. returns: true if the label was found, false otherwise @@ -589,14 +594,14 @@ public: // reszta może by?publiczna sound_source m_radiosound { sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // cached template for radio messages std::vector>> m_radiomessages; // list of currently played radio messages sound_source m_radiostop { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; - +/* int iCabLightFlag; // McZapkie:120503: oswietlenie kabiny (0: wyl, 1: przyciemnione, 2: pelne) bool bCabLight; // hunter-091012: czy swiatlo jest zapalone? bool bCabLightDim; // hunter-091012: czy przyciemnienie kabiny jest zapalone? - +*/ // McZapkie: opis kabiny - obszar poruszania sie mechanika oraz zajetosc - TCab Cabine[ maxcab + 1 ]; // przedzial maszynowy, kabina 1 (A), kabina 2 (B) - int iCabn; + std::array Cabine; // przedzial maszynowy, kabina 1 (A), kabina 2 (B) + int iCabn { 0 }; // McZapkie: do poruszania sie po kabinie Math3D::vector3 pMechSittingPosition; // ABu 180404 Math3D::vector3 MirrorPosition( bool lewe ); @@ -638,6 +643,7 @@ private: bool bHeat[8]; // grzanie // McZapkie: do syczenia float fPPress, fNPress; + bool m_mastercontrollerinuse { false }; int iRadioChannel { 1 }; // numer aktualnego kana?u radiowego std::vector> m_screens; diff --git a/drivermode.cpp b/drivermode.cpp index d8996095..6bcc62ad 100644 --- a/drivermode.cpp +++ b/drivermode.cpp @@ -27,13 +27,13 @@ http://mozilla.org/MPL/2.0/. #include "renderer.h" #include "utilities.h" #include "Logs.h" - +/* namespace input { user_command command; // currently issued control command, if any } - +*/ void driver_mode::drivermode_input::poll() { @@ -47,11 +47,13 @@ driver_mode::drivermode_input::poll() { if( uart != nullptr ) { uart->poll(); } +/* // TBD, TODO: wrap current command in object, include other input sources? input::command = ( mouse.command() != user_command::none ? mouse.command() : keyboard.command() ); +*/ } bool @@ -468,6 +470,15 @@ driver_mode::update_camera( double const Deltatime ) { simulation::Train->pMechViewAngle = { Camera.Angle.x, Camera.Angle.y }; simulation::Train->pMechOffset = Camera.m_owneroffset; } + + if( ( true == FreeFlyModeFlag ) + && ( Camera.m_owner != nullptr ) ) { + // cache external view config + auto &externalviewconfig { m_externalviewconfigs[ m_externalviewmode ] }; + externalviewconfig.owner = Camera.m_owner; + externalviewconfig.offset = Camera.m_owneroffset; + externalviewconfig.angle = Camera.Angle; + } } else { // debug camera @@ -567,13 +578,13 @@ driver_mode::update_camera( double const Deltatime ) { // gdy w korytarzu Camera.LookAt = Camera.m_owner->GetWorldPosition( Camera.m_owneroffset ) - + simulation::Train->GetDirection() * 5.0; + + Camera.m_owner->VectorFront() * 5.0; } else { // patrzenie w kierunku osi pojazdu, z uwzględnieniem kabiny Camera.LookAt = Camera.m_owner->GetWorldPosition( Camera.m_owneroffset ) - + simulation::Train->GetDirection() * 5.0 + + Camera.m_owner->VectorFront() * 5.0 * simulation::Train->Occupied()->ActiveCab; //-1 albo 1 } Camera.vUp = simulation::Train->GetUp(); @@ -914,18 +925,26 @@ driver_mode::ExternalView() { Camera.m_owner = owner; - auto const offsetflip { - ( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab ) - * ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir ) }; + auto const &viewconfig { m_externalviewconfigs[ m_externalviewmode ] }; + if( owner == viewconfig.owner ) { + // restore view config for previous owner + Camera.m_owneroffset = viewconfig.offset; + Camera.Angle = viewconfig.angle; + } + else { + // default view setup + auto const offsetflip{ + ( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab ) + * ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir ) }; - Camera.m_owneroffset = { - 1.5 * owner->MoverParameters->Dim.W * offsetflip, - std::max( 5.0, 1.25 * owner->MoverParameters->Dim.H ), - - 0.4 * owner->MoverParameters->Dim.L * offsetflip }; + Camera.m_owneroffset = { + 1.5 * owner->MoverParameters->Dim.W * offsetflip, + std::max( 5.0, 1.25 * owner->MoverParameters->Dim.H ), + -0.4 * owner->MoverParameters->Dim.L * offsetflip }; - Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 180.0 : 0.0 ) ); - - auto const shakeangles { owner->shake_angles() }; + Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 180.0 : 0.0 ) ); + } + auto const shakeangles{ owner->shake_angles() }; Camera.Angle.x -= 0.5 * shakeangles.second; // hustanie kamery przod tyl Camera.Angle.z = shakeangles.first; // hustanie kamery na boki @@ -937,18 +956,26 @@ driver_mode::ExternalView() { Camera.m_owner = owner; - auto const offsetflip { - ( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab ) - * ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir ) - * -1 }; + auto const &viewconfig{ m_externalviewconfigs[ m_externalviewmode ] }; + if( owner == viewconfig.owner ) { + // restore view config for previous owner + Camera.m_owneroffset = viewconfig.offset; + Camera.Angle = viewconfig.angle; + } + else { + // default view setup + auto const offsetflip{ + ( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab ) + * ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir ) + * -1 }; - Camera.m_owneroffset = { - 1.5 * owner->MoverParameters->Dim.W * offsetflip, - std::max( 5.0, 1.25 * owner->MoverParameters->Dim.H ), - 0.2 * owner->MoverParameters->Dim.L * offsetflip }; - - Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 0.0 : 180.0 ) ); + Camera.m_owneroffset = { + 1.5 * owner->MoverParameters->Dim.W * offsetflip, + std::max( 5.0, 1.25 * owner->MoverParameters->Dim.H ), + 0.2 * owner->MoverParameters->Dim.L * offsetflip }; + Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 0.0 : 180.0 ) ); + } auto const shakeangles { owner->shake_angles() }; Camera.Angle.x -= 0.5 * shakeangles.second; // hustanie kamery przod tyl Camera.Angle.z = shakeangles.first; // hustanie kamery na boki @@ -959,17 +986,25 @@ driver_mode::ExternalView() { Camera.m_owner = owner; - auto const offsetflip { - ( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab ) - * ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir ) }; + auto const &viewconfig{ m_externalviewconfigs[ m_externalviewmode ] }; + if( owner == viewconfig.owner ) { + // restore view config for previous owner + Camera.m_owneroffset = viewconfig.offset; + Camera.Angle = viewconfig.angle; + } + else { + // default view setup + auto const offsetflip{ + ( vehicle->MoverParameters->ActiveCab == 0 ? 1 : vehicle->MoverParameters->ActiveCab ) + * ( vehicle->MoverParameters->ActiveDir == 0 ? 1 : vehicle->MoverParameters->ActiveDir ) }; - Camera.m_owneroffset = { - - 0.65 * owner->MoverParameters->Dim.W * offsetflip, - 0.90, - 0.15 * owner->MoverParameters->Dim.L * offsetflip }; - - Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 180.0 : 0.0 ) ); + Camera.m_owneroffset = { + -0.65 * owner->MoverParameters->Dim.W * offsetflip, + 0.90, + 0.15 * owner->MoverParameters->Dim.L * offsetflip }; + Camera.Angle.y = glm::radians( ( vehicle->MoverParameters->ActiveDir < 0 ? 180.0 : 0.0 ) ); + } auto const shakeangles { owner->shake_angles() }; Camera.Angle.x -= 0.5 * shakeangles.second; // hustanie kamery przod tyl Camera.Angle.z = shakeangles.first; // hustanie kamery na boki diff --git a/drivermode.h b/drivermode.h index 19ec4493..0f4f1a81 100644 --- a/drivermode.h +++ b/drivermode.h @@ -60,6 +60,12 @@ private: count_ }; + struct view_config { + TDynamicObject const *owner { nullptr }; + Math3D::vector3 offset {}; + Math3D::vector3 angle {}; + }; + struct drivermode_input { gamepad_input gamepad; @@ -91,6 +97,7 @@ private: TCamera DebugCamera; int m_externalviewmode { view::consistfront }; // selected external view mode bool m_externalview { false }; + std::array m_externalviewconfigs; TDynamicObject *pDynamicNearest { nullptr }; // vehicle nearest to the active camera. TODO: move to camera double fTime50Hz { 0.0 }; // bufor czasu dla komunikacji z PoKeys double const m_primaryupdaterate { 1.0 / 100.0 }; diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index a725481d..5c4c6503 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -319,6 +319,7 @@ drivermouse_input::button( int const Button, int const Action ) { else { if( Button == GLFW_MOUSE_BUTTON_LEFT ) { if( m_slider.command() != user_command::none ) { + m_relay.post( m_slider.command(), 0, 0, Action, 0 ); m_slider.release(); } } diff --git a/renderer.cpp b/renderer.cpp index 769c651a..229c0647 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -562,7 +562,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) { if( vehicle->InteriorLightLevel > 0.f ) { setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); } - Render_cab( vehicle, false ); + Render_cab( vehicle, vehicle->InteriorLightLevel, false ); if( vehicle->InteriorLightLevel > 0.f ) { setup_shadow_color( shadowcolor ); } @@ -581,17 +581,17 @@ opengl_renderer::Render_pass( rendermode const Mode ) { setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix ); // cache shadow colour in case we need to account for cab light auto const shadowcolor{ m_shadowcolor }; - auto const *vehicle{ simulation::Train->Dynamic() }; + auto const *vehicle { simulation::Train->Dynamic() }; if( vehicle->InteriorLightLevel > 0.f ) { setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); } if( Global.Overcast > 1.f ) { // with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab setup_drawing( false ); - Render_cab( vehicle, false ); + Render_cab( vehicle, vehicle->InteriorLightLevel, false ); setup_drawing( true ); } - Render_cab( vehicle, true ); + Render_cab( vehicle, vehicle->InteriorLightLevel, true ); if( vehicle->InteriorLightLevel > 0.f ) { setup_shadow_color( shadowcolor ); } @@ -681,8 +681,8 @@ opengl_renderer::Render_pass( rendermode const Mode ) { #else setup_units( false, false, false ); #endif - Render_cab( simulation::Train->Dynamic(), false ); - Render_cab( simulation::Train->Dynamic(), true ); + Render_cab( simulation::Train->Dynamic(), 0.f, false ); + Render_cab( simulation::Train->Dynamic(), 0.f, true ); m_cabshadowpass = m_renderpass; // post-render restore @@ -745,7 +745,10 @@ opengl_renderer::Render_pass( rendermode const Mode ) { setup_drawing( false ); setup_units( false, false, false ); // cab render skips translucent parts, so we can do it here - if( simulation::Train != nullptr ) { Render_cab( simulation::Train->Dynamic() ); } + if( simulation::Train != nullptr ) { + Render_cab( simulation::Train->Dynamic(), 0.f ); + Render( simulation::Train->Dynamic() ); + } // post-render cleanup } break; @@ -816,7 +819,7 @@ opengl_renderer::setup_pass( renderpass_config &Config, rendermode const Mode, f switch( Mode ) { case rendermode::color: { Config.draw_range = Global.BaseDrawRange; break; } case rendermode::shadows: { Config.draw_range = Global.BaseDrawRange * 0.5f; break; } - case rendermode::cabshadows: { Config.draw_range = ( simulation::Train->Occupied()->ActiveCab != 0 ? 10.f : 20.f ); break; } + case rendermode::cabshadows: { Config.draw_range = simulation::Train->Occupied()->Dim.L; break; } case rendermode::reflections: { Config.draw_range = Global.BaseDrawRange; break; } case rendermode::pickcontrols: { Config.draw_range = 50.f; break; } case rendermode::pickscenery: { Config.draw_range = Global.BaseDrawRange * 0.5f; break; } @@ -2158,7 +2161,10 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { // render if( Dynamic->mdLowPolyInt ) { // low poly interior - if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) { + /* + if( ( true == FreeFlyModeFlag ) + || ( ( Dynamic->mdKabina == nullptr ) || ( false == Dynamic->bDisplayCab ) ) ) { + */ /* // enable cab light if needed if( Dynamic->InteriorLightLevel > 0.0f ) { @@ -2174,7 +2180,9 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( m_baseambient ) ); } */ + /* } + */ } if( Dynamic->mdModel ) Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); @@ -2191,9 +2199,9 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { case rendermode::shadows: { if( Dynamic->mdLowPolyInt ) { // low poly interior - if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) { +// if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) { Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance ); - } +// } } if( Dynamic->mdModel ) Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); @@ -2202,7 +2210,13 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { // post-render cleanup break; } - case rendermode::pickcontrols: + case rendermode::pickcontrols: { + if( Dynamic->mdLowPolyInt ) { + // low poly interior + Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance ); + } + break; + } case rendermode::pickscenery: default: { break; @@ -2220,7 +2234,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { // rendering kabiny gdy jest oddzielnym modelem i ma byc wyswietlana bool -opengl_renderer::Render_cab( TDynamicObject const *Dynamic, bool const Alpha ) { +opengl_renderer::Render_cab( TDynamicObject const *Dynamic, float const Lightlevel, bool const Alpha ) { if( Dynamic == nullptr ) { @@ -2252,9 +2266,9 @@ opengl_renderer::Render_cab( TDynamicObject const *Dynamic, bool const Alpha ) { // change light level based on light level of the occupied track m_sunlight.apply_intensity( Dynamic->fShade ); } - if( Dynamic->InteriorLightLevel > 0.f ) { + if( Lightlevel > 0.f ) { // crude way to light the cabin, until we have something more complete in place - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Lightlevel ) ); } // render if( true == Alpha ) { @@ -2270,7 +2284,7 @@ opengl_renderer::Render_cab( TDynamicObject const *Dynamic, bool const Alpha ) { // change light level based on light level of the occupied track m_sunlight.apply_intensity(); } - if( Dynamic->InteriorLightLevel > 0.0f ) { + if( Lightlevel > 0.f ) { // reset the overall ambient ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr(m_baseambient) ); } @@ -2435,9 +2449,10 @@ opengl_renderer::Render( TSubModel *Submodel ) { } // ...luminance auto const unitstate = m_unitstate; - if( Global.fLuminance < Submodel->fLight ) { + auto const isemissive { ( Submodel->f4Emision.a > 0.f ) && ( Global.fLuminance < Submodel->fLight ) }; + if( isemissive ) { // zeby swiecilo na kolorowo - ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( Submodel->f4Diffuse * Submodel->f4Emision.a ) ); + ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( /* Submodel->f4Emision */ Submodel->f4Diffuse * Submodel->f4Emision.a ) ); // disable shadows so they don't obstruct self-lit items /* setup_shadow_color( colors::white ); @@ -2466,7 +2481,7 @@ opengl_renderer::Render( TSubModel *Submodel ) { if( ( true == m_renderspecular ) && ( m_sunlight.specular.a > 0.01f ) ) { ::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( colors::none ) ); } - if( Global.fLuminance < Submodel->fLight ) { + if( isemissive ) { // restore default (lack of) brightness ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( colors::none ) ); /* @@ -3245,7 +3260,7 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { // render if( Dynamic->mdLowPolyInt ) { // low poly interior - if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) { +// if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) { /* // enable cab light if needed if( Dynamic->InteriorLightLevel > 0.0f ) { @@ -3261,7 +3276,7 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( m_baseambient ) ); } */ - } +// } } if( Dynamic->mdModel ) @@ -3403,9 +3418,10 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { } // ...luminance auto const unitstate = m_unitstate; - if( Global.fLuminance < Submodel->fLight ) { + auto const isemissive { ( Submodel->f4Emision.a > 0.f ) && ( Global.fLuminance < Submodel->fLight ) }; + if( isemissive ) { // zeby swiecilo na kolorowo - ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( Submodel->f4Diffuse * Submodel->f4Emision.a ) ); + ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( /* Submodel->f4Emision */ Submodel->f4Diffuse * Submodel->f4Emision.a ) ); // disable shadows so they don't obstruct self-lit items /* setup_shadow_color( colors::white ); @@ -3420,7 +3436,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { if( ( true == m_renderspecular ) && ( m_sunlight.specular.a > 0.01f ) ) { ::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( colors::none ) ); } - if( Global.fLuminance < Submodel->fLight ) { + if( isemissive ) { // restore default (lack of) brightness ::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( colors::none ) ); /* diff --git a/renderer.h b/renderer.h index 64ed1625..6bdc8777 100644 --- a/renderer.h +++ b/renderer.h @@ -292,7 +292,7 @@ private: void Render( scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last ); bool - Render_cab( TDynamicObject const *Dynamic, bool const Alpha = false ); + Render_cab( TDynamicObject const *Dynamic, float const Lightlevel, bool const Alpha = false ); void Render( TMemCell *Memcell ); void