From 9d008d2a3e0089fc92993f2fdb17fb14619f6d08 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 24 Jan 2018 22:27:58 +0100 Subject: [PATCH] additional motor ventilator parameters exposed in .fiz file, motor ventilator spin rate tweaks, mouse support for radiostop commands, restricted speed mode for driver ai, passed signals scanning fix, mouse and keyboard command input rate unification, basic material textures priority system --- Driver.cpp | 143 +++++++++++++++++++++++++-------------------- Driver.h | 5 +- DynObj.cpp | 79 ++++++++++++------------- Globals.cpp | 1 + Globals.h | 1 + McZapkie/MOVER.h | 7 ++- McZapkie/Mover.cpp | 25 +++++++- Segment.h | 6 +- Track.cpp | 43 +++++++++----- Track.h | 2 +- Train.cpp | 54 ++++++++++++++++- Train.h | 5 ++ World.cpp | 14 ++--- command.cpp | 1 + command.h | 1 + keyboardinput.cpp | 4 +- material.cpp | 12 +++- material.h | 9 ++- mouseinput.cpp | 42 +++++++------ mouseinput.h | 1 + renderer.cpp | 3 +- translation.h | 2 + version.h | 2 +- 23 files changed, 299 insertions(+), 163 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 9135c524..1dcb3123 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -253,18 +253,21 @@ void TSpeedPos::CommandCheck() break; default: // inna komenda w evencie skanowanym powoduje zatrzymanie i wysłanie tej komendy - iFlags &= ~(spShuntSemaphor | spPassengerStopPoint | - spStopOnSBL); // nie manewrowa, nie przystanek, nie zatrzymać na SBL - fVelNext = 0.0; // jak nieznana komenda w komórce sygnałowej, to zatrzymujemy + // nie manewrowa, nie przystanek, nie zatrzymać na SBL + iFlags &= ~(spShuntSemaphor | spPassengerStopPoint | spStopOnSBL); + // jak nieznana komenda w komórce sygnałowej, to zatrzymujemy + fVelNext = 0.0; } }; bool TSpeedPos::Update() { - if( fDist < 0.0 ) - iFlags |= spElapsed; // trzeba zazanaczyć, że minięty - if (iFlags & spTrack) // road/track - { + if( fDist < 0.0 ) { + // trzeba zazanaczyć, że minięty + iFlags |= spElapsed; + } + if (iFlags & spTrack) { + // road/track if (trTrack) { // może być NULL, jeśli koniec toru (???) fVelNext = trTrack->VelocityGet(); // aktualizacja prędkości (może być zmieniana eventem) @@ -301,10 +304,15 @@ bool TSpeedPos::Update() } } } - else if (iFlags & spEvent) // jeśli event - { // odczyt komórki pamięci najlepiej by było zrobić jako notyfikację, czyli zmiana komórki - // wywoła jakąś podaną funkcję - CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości + else if (iFlags & spEvent) { + // jeśli event + if( ( ( iFlags & spElapsed ) == 0 ) + || ( fVelNext == 0.0 ) ) { + // ignore already passed signals, but keep an eye on overrun stops + // odczyt komórki pamięci najlepiej by było zrobić jako notyfikację, + // czyli zmiana komórki wywoła jakąś podaną funkcję + CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości + } } return false; }; @@ -1107,23 +1115,28 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN // koniec toru) } } - else if (sSpeedTable[i].iFlags & spStopOnSBL) - { // jeśli S1 na SBL - if (mvOccupied->Vel < 2.0) // stanąć nie musi, ale zwolnić przynajmniej - if (sSpeedTable[i].fDist < fMaxProximityDist) // jest w maksymalnym zasięgu - { - eSignSkip = sSpeedTable[i] - .evEvent; // to można go pominąć (wziąć drugą prędkosć) - iDrivigFlags |= moveVisibility; // jazda na widoczność - skanować - // możliwość kolizji i nie podjeżdżać - // zbyt blisko + else if (sSpeedTable[i].iFlags & spStopOnSBL) { + // jeśli S1 na SBL + if( mvOccupied->Vel < 2.0 ) { + // stanąć nie musi, ale zwolnić przynajmniej + if( ( sSpeedTable[ i ].fDist < fMaxProximityDist ) + && ( TrackBlock() > 1000.0 ) ) { + // jest w maksymalnym zasięgu to można go pominąć (wziąć drugą prędkosć) + // as long as there isn't any obstacle in arbitrary view range + eSignSkip = sSpeedTable[ i ].evEvent; + // jazda na widoczność - skanować możliwość kolizji i nie podjeżdżać zbyt blisko // usunąć flagę po podjechaniu blisko semafora zezwalającego na jazdę - // ostrożnie interpretować sygnały - semafor może zezwalać na jazdę - // pociągu z przodu! + // ostrożnie interpretować sygnały - semafor może zezwalać na jazdę pociągu z przodu! + iDrivigFlags |= moveVisibility; + // store the ordered restricted speed and don't exceed it until the flag is cleared + VelRestricted = sSpeedTable[ i ].evEvent->ValueGet( 2 ); } - if (eSignSkip != sSpeedTable[i].evEvent) // jeśli ten SBL nie jest do pominięcia - // TODO sprawdzić do której zmiennej jest przypisywane v i zmienić to tutaj - v = sSpeedTable[i].evEvent->ValueGet(1); // to ma 0 odczytywać + } + if( eSignSkip != sSpeedTable[ i ].evEvent ) { + // jeśli ten SBL nie jest do pominięcia to ma 0 odczytywać + v = sSpeedTable[ i ].evEvent->ValueGet( 1 ); + // TODO sprawdzić do której zmiennej jest przypisywane v i zmienić to tutaj + } } else if (sSpeedTable[i].IsProperSemaphor(OrderCurrentGet())) { // to semaphor @@ -1230,41 +1243,42 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN } } } - else if (!(sSpeedTable[i].iFlags & spSectionVel)) //jeśli jakiś event pasywny ale nie ograniczenie - if (go == cm_Unknown) // jeśli nie było komendy wcześniej - pierwsza się liczy - // - ustawianie VelSignal - if (v < 0.0 ? true : v >= 1.0) // bo wartość 0.1 służy do hamowania tylko - { - go = cm_SetVelocity; // może odjechać - // Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo semafor może - // być daleko - // VelSignal=v; //nie do końca tak, to jest druga prędkość; -1 nie - // wpisywać... - if (VelSignal == 0.0) - VelSignal = -1.0; // aby stojący ruszył - if (sSpeedTable[i].fDist < 0.0) // jeśli przejechany - { - VelSignal = (v != 0 ? -1.0 : 0.0); - // ustawienie, gdy przejechany jest lepsze niż - // wcale, ale to jeszcze nie to - if (sSpeedTable[i].iFlags & spEvent) // jeśli event - if ((sSpeedTable[i].evEvent != eSignSkip) ? - true : - (sSpeedTable[i].fVelNext != 0.0)) // ale inny niż ten, - // na którym minięto - // S1, chyba że się - // już zmieniło - iDrivigFlags &= ~moveVisibility; // sygnał zezwalający na - // jazdę wyłącza jazdę na - // widoczność (S1 na SBL) - - // usunąć jeśli nie jest ograniczeniem prędkości - sSpeedTable[i].iFlags = - 0; // to można usunąć (nie mogą być usuwane w skanowaniu) + else if( !( sSpeedTable[ i ].iFlags & spSectionVel ) ) { + //jeśli jakiś event pasywny ale nie ograniczenie + if( go == cm_Unknown ) { + // jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie VelSignal + if( ( v < 0.0 ) + || ( v >= 1.0 ) ) { + // bo wartość 0.1 służy do hamowania tylko + go = cm_SetVelocity; // może odjechać + // Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo semafor może być daleko + // VelSignal=v; //nie do końca tak, to jest druga prędkość; -1 nie wpisywać... + if( VelSignal == 0.0 ) { + // aby stojący ruszył + VelSignal = -1.0; + } + if( sSpeedTable[ i ].fDist < 0.0 ) { + // jeśli przejechany + VelSignal = ( v == 0.0 ? 0.0 : -1.0 ); + // ustawienie, gdy przejechany jest lepsze niż wcale, ale to jeszcze nie to + if( sSpeedTable[ i ].iFlags & spEvent ) { + // jeśli event + if( ( sSpeedTable[ i ].evEvent != eSignSkip ) + || ( sSpeedTable[ i ].fVelNext != VelRestricted ) ) { + // ale inny niż ten, na którym minięto S1, chyba że się już zmieniło + // sygnał zezwalający na jazdę wyłącza jazdę na widoczność (po S1 na SBL) + iDrivigFlags &= ~moveVisibility; + // remove restricted speed + VelRestricted = -1.0; + } + } + // jeśli nie jest ograniczeniem prędkości to można usunąć + // (nie mogą być usuwane w skanowaniu) + sSpeedTable[ i ].iFlags = 0; } } - else if (sSpeedTable[i].evEvent->StopCommand()) - { // jeśli prędkość jest zerowa, a komórka zawiera komendę + else if( sSpeedTable[ i ].evEvent->StopCommand() ) { + // jeśli prędkość jest zerowa, a komórka zawiera komendę eSignNext = sSpeedTable[ i ].evEvent; // dla informacji if( true == TestFlag( iDrivigFlags, moveStopHere ) ) { // jeśli ma stać, dostaje komendę od razu @@ -1276,6 +1290,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu } } + } + } } // jeśli nie ma zawalidrogi } // jeśli event if (v >= 0.0) @@ -1366,7 +1382,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN fVelDes = Min0R(fVelDes, VelLimitLast); if (VelRoad >= 0.0) fVelDes = Min0R(fVelDes, VelRoad); - // nastepnego semafora albo zwrotnicy to uznajemy, że mijamy W5 + if( VelRestricted >= 0.0 ) + fVelDes = Min0R( fVelDes, VelRestricted ); + // nastepnego semafora albo zwrotnicy to uznajemy, że mijamy W5 FirstSemaphorDist = d_to_next_sem; // przepisanie znalezionej wartosci do zmiennej return go; }; @@ -3740,7 +3758,6 @@ TController::UpdateSituation(double dt) { // check for potential colliders { - auto const collisionscanrange = 300.0 + fBrakeDist; auto rearvehicle = ( pVehicles[ 0 ] == pVehicles[ 1 ] ? pVehicles[ 0 ] : @@ -3764,7 +3781,7 @@ TController::UpdateSituation(double dt) { pVehicle->DirectionGet() == pVehicles[ 0 ]->DirectionGet() ? 1 : -1 ), - collisionscanrange ); + routescanrange ); } else { // towards coupler 1 @@ -3782,7 +3799,7 @@ TController::UpdateSituation(double dt) { pVehicle->DirectionGet() == pVehicles[ 0 ]->DirectionGet() ? -1 : 1 ), - collisionscanrange ); + routescanrange ); } } diff --git a/Driver.h b/Driver.h index 628f69dd..966c0887 100644 --- a/Driver.h +++ b/Driver.h @@ -152,7 +152,7 @@ class TSpeedPos inline void UpdateDistance( double dist ) { - fDist -= dist; } + fDist -= dist; } bool Set(TEvent *e, double d, TOrders order = Wait_for_orders); void Set(TTrack *t, double d, int f); std::string TableText(); @@ -224,7 +224,7 @@ private: double LastReactionTime = 0.0; double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations - TAction eAction = actSleep; // aktualny stan + TAction eAction { actUnknown }; // aktualny stan public: inline TAction GetAction() { @@ -258,6 +258,7 @@ private: double VelLimitLast = -1.0; // prędkość zadana przez ograniczenie // ostatnie ograniczenie bez ograniczenia double VelRoad = -1.0; // aktualna prędkość drogowa (ze znaku W27) (PutValues albo komendą) // prędkość drogowa bez ograniczenia double VelNext = 120.0; // prędkość, jaka ma być po przejechaniu długości ProximityDist + double VelRestricted = -1.0; // speed of travel after passing a permissive signal at stop private: double fProximityDist = 0.0; // odleglosc podawana w SetProximityVelocity(); >0:przeliczać do punktu, <0:podana wartość double FirstSemaphorDist = 10000.0; // odległość do pierwszego znalezionego semafora diff --git a/DynObj.cpp b/DynObj.cpp index de857e76..21f91194 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -915,14 +915,12 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) smWahacze[i]->SetRotate(float3(1, 0, 0), fWahaczeAmp * cos(MoverParameters->eAngle)); - if (Mechanik) { + if( ( Mechanik != nullptr ) + && ( Mechanik->GetAction() != actSleep ) ) { // rysowanie figurki mechanika - if( MoverParameters->ActiveCab > 0 ) { - btMechanik1.Turn( true ); - btnOn = true; - } - if( MoverParameters->ActiveCab < 0 ) { - btMechanik2.Turn( true ); + btMechanik1.Turn( MoverParameters->ActiveCab > 0 ); + btMechanik2.Turn( MoverParameters->ActiveCab < 0 ); + if( MoverParameters->ActiveCab != 0 ) { btnOn = true; } } @@ -2309,7 +2307,7 @@ void TDynamicObject::Move(double fDistance) { // liczymy proporcję double d = Axle0.GetTranslation(); // aktualne położenie na torze if (Axle0.GetDirection() < 0) - d = t0->fTrackLength - d; // od drugiej strony liczona długość + d = t0->Length() - d; // od drugiej strony liczona długość d /= fAxleDist; // rozsataw osi procentowe znajdowanie się na torze float shadefrom = 1.0f, shadeto = 1.0f; @@ -3483,9 +3481,9 @@ void TDynamicObject::RenderSounds() { if( Global::iPause != 0 ) { return; } - double const dt { Timer::GetDeltaRenderTime() }; - double volume { 0.0 }; - double frequency { 1.0 }; + double const dt{ Timer::GetDeltaRenderTime() }; + double volume{ 0.0 }; + double frequency{ 1.0 }; m_powertrainsounds.render( *MoverParameters, dt ); @@ -3493,8 +3491,8 @@ void TDynamicObject::RenderSounds() { if( MoverParameters->ConverterFlag ) { frequency = ( MoverParameters->EngineType == ElectricSeriesMotor ? - ( MoverParameters->RunningTraction.TractionVoltage / MoverParameters->NominalVoltage ) * MoverParameters->RList[ MoverParameters->RlistSize ].Mn : - 1.0 ); + ( MoverParameters->RunningTraction.TractionVoltage / MoverParameters->NominalVoltage ) * MoverParameters->RList[ MoverParameters->RlistSize ].Mn : + 1.0 ); frequency = sConverter.m_frequencyoffset + sConverter.m_frequencyfactor * frequency; sConverter .pitch( clamp( frequency, 0.5, 1.25 ) ) // arbitrary limits ) @@ -3526,7 +3524,7 @@ void TDynamicObject::RenderSounds() { // brake system and braking sounds: if( m_lastbrakepressure != -1.f ) { // calculate rate of pressure drop in brake cylinder, once it's been initialized - auto const brakepressuredifference { m_lastbrakepressure - MoverParameters->BrakePress }; + auto const brakepressuredifference{ m_lastbrakepressure - MoverParameters->BrakePress }; m_brakepressurechange = interpolate( m_brakepressurechange, brakepressuredifference / dt, 0.005f ); } m_lastbrakepressure = MoverParameters->BrakePress; @@ -3562,9 +3560,9 @@ void TDynamicObject::RenderSounds() { if( MoverParameters->SlippingWheels ) { if( ( MoverParameters->UnitBrakeForce > 100.0 ) - && ( GetVelocity() > 1.0 ) ) { + && ( GetVelocity() > 1.0 ) ) { - auto const velocitydifference { GetVelocity() / MoverParameters->Vmax }; + auto const velocitydifference{ GetVelocity() / MoverParameters->Vmax }; rsSlippery .gain( rsSlippery.m_amplitudeoffset + rsSlippery.m_amplitudefactor * velocitydifference ) .play( sound_flags::exclusive | sound_flags::looping ); @@ -3582,10 +3580,10 @@ void TDynamicObject::RenderSounds() { sSand.stop(); } - auto brakeforceratio { 0.0 }; + auto brakeforceratio{ 0.0 }; if( //( false == mvOccupied->SlippingWheels ) && ( MoverParameters->UnitBrakeForce > 10.0 ) - && ( MoverParameters->Vel > 0.05 ) ) { + && ( MoverParameters->Vel > 0.05 ) ) { brakeforceratio = clamp( @@ -3639,7 +3637,7 @@ void TDynamicObject::RenderSounds() { } // NBMX Obsluga drzwi, MC: zuniwersalnione if( ( true == MoverParameters->DoorLeftOpened ) - && ( dDoorMoveL < MoverParameters->DoorMaxShiftL ) ) { + && ( dDoorMoveL < MoverParameters->DoorMaxShiftL ) ) { for( auto &door : m_doorsounds ) { if( door.rsDoorClose.offset().x > 0.f ) { @@ -3650,7 +3648,7 @@ void TDynamicObject::RenderSounds() { } } if( ( false == MoverParameters->DoorLeftOpened ) - && ( dDoorMoveL > 0.01 ) ) { + && ( dDoorMoveL > 0.01 ) ) { for( auto &door : m_doorsounds ) { if( door.rsDoorClose.offset().x > 0.f ) { @@ -3661,7 +3659,7 @@ void TDynamicObject::RenderSounds() { } } if( ( true == MoverParameters->DoorRightOpened ) - && ( dDoorMoveR < MoverParameters->DoorMaxShiftR ) ) { + && ( dDoorMoveR < MoverParameters->DoorMaxShiftR ) ) { for( auto &door : m_doorsounds ) { if( door.rsDoorClose.offset().x < 0.f ) { @@ -3672,7 +3670,7 @@ void TDynamicObject::RenderSounds() { } } if( ( false == MoverParameters->DoorRightOpened ) - && ( dDoorMoveR > 0.01 ) ) { + && ( dDoorMoveR > 0.01 ) ) { for( auto &door : m_doorsounds ) { if( door.rsDoorClose.offset().x < 0.f ) { @@ -3699,15 +3697,15 @@ void TDynamicObject::RenderSounds() { if( ( GetVelocity() > 0.5 ) && ( false == rsOuterNoise.empty() ) && ( // compound test whether the vehicle belongs to user-driven consist (as these don't emit outer noise in cab view) - FreeFlyModeFlag ? true : // in external view all vehicles emit outer noise - // Global::pWorld->train() == nullptr ? true : // (can skip this check, with no player train the external view is a given) - ctOwner == nullptr ? true : // standalone vehicle, can't be part of user-driven train - ctOwner != Global::pWorld->train()->Dynamic()->ctOwner ? true : // confirmed isn't a part of the user-driven train - Global::CabWindowOpen ? true : // sticking head out we get to hear outer noise - false ) ) { + FreeFlyModeFlag ? true : // in external view all vehicles emit outer noise + // Global::pWorld->train() == nullptr ? true : // (can skip this check, with no player train the external view is a given) + ctOwner == nullptr ? true : // standalone vehicle, can't be part of user-driven train + ctOwner != Global::pWorld->train()->Dynamic()->ctOwner ? true : // confirmed isn't a part of the user-driven train + Global::CabWindowOpen ? true : // sticking head out we get to hear outer noise + false ) ) { - // frequency calculation - auto const normalizer { ( + // frequency calculation + auto const normalizer{ ( true == rsOuterNoise.is_combined() ? MoverParameters->Vmax * 0.01f : 1.f ) }; @@ -3749,15 +3747,18 @@ void TDynamicObject::RenderSounds() { rsOuterNoise.stop( false == FreeFlyModeFlag ); } // flat spot sound - if( ( GetVelocity() > 1.0 ) - && ( MoverParameters->WheelFlat > 5.0 ) ) { - m_wheelflat - .pitch( m_wheelflat.m_frequencyoffset + std::abs( MoverParameters->nrot ) * m_wheelflat.m_frequencyfactor ) - .gain( m_wheelflat.m_amplitudeoffset + m_wheelflat.m_amplitudefactor * ( ( 1.0 + ( MoverParameters->Vel / MoverParameters->Vmax ) + clamp( MoverParameters->WheelFlat / 60.0, 0.0, 1.0 ) ) / 3.0 ) ) - .play( sound_flags::exclusive | sound_flags::looping ); - } - else { - m_wheelflat.stop(); + if( MoverParameters->CategoryFlag == 1 ) { + // trains only + if( ( GetVelocity() > 1.0 ) + && ( MoverParameters->WheelFlat > 5.0 ) ) { + m_wheelflat + .pitch( m_wheelflat.m_frequencyoffset + std::abs( MoverParameters->nrot ) * m_wheelflat.m_frequencyfactor ) + .gain( m_wheelflat.m_amplitudeoffset + m_wheelflat.m_amplitudefactor * ( ( 1.0 + ( MoverParameters->Vel / MoverParameters->Vmax ) + clamp( MoverParameters->WheelFlat / 60.0, 0.0, 1.0 ) ) / 3.0 ) ) + .play( sound_flags::exclusive | sound_flags::looping ); + } + else { + m_wheelflat.stop(); + } } // youBy: dzwiek ostrych lukow i ciasnych zwrotek diff --git a/Globals.cpp b/Globals.cpp index 4dd3d0ff..080bc445 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -68,6 +68,7 @@ double Global::fFogStart = 1700; double Global::fFogEnd = 2000; float Global::Overcast { 0.1f }; // NOTE: all this weather stuff should be moved elsewhere std::string Global::Season; // season of the year, based on simulation date +std::string Global::Weather { "clear" }; // current weather float Global::BaseDrawRange { 2500.f }; opengl_light Global::DayLight; diff --git a/Globals.h b/Globals.h index 8213e37a..806e2585 100644 --- a/Globals.h +++ b/Globals.h @@ -189,6 +189,7 @@ public: static double fFogStart; static double fFogEnd; static std::string Season; // season of the year, based on simulation date + static std::string Weather; // current weather // TODO: put these things in the renderer static float BaseDrawRange; diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 1f4c934f..24094d74 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -84,8 +84,6 @@ extern int ConversionError; const double Steel2Steel_friction = 0.15; //tarcie statyczne const double g = 9.81; //przyspieszenie ziemskie const double SandSpeed = 0.1; //ile kg/s} -const double RVentSpeed = 3.5; //rozpedzanie sie wentylatora obr/s^2} -const double RVentMinI = 50.0; //przy jakim pradzie sie wylaczaja} const double Pirazy2 = 6.2831853071794f; #define PI 3.1415926535897f @@ -739,7 +737,8 @@ public: double u = 0.0; //wspolczynnik tarcia yB wywalic!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! double CircuitRes = 0.0; /*rezystancje silnika i obwodu*/ int IminLo = 0; int IminHi = 0; /*prady przelacznika automatycznego rozruchu, uzywane tez przez ai_driver*/ - int ImaxLo = 0; int ImaxHi = 0; /*maksymalny prad niskiego i wysokiego rozruchu*/ + int ImaxLo = 0; // maksymalny prad niskiego rozruchu + int ImaxHi = 0; // maksymalny prad wysokiego rozruchu double nmax = 0.0; /*maksymalna dop. ilosc obrotow /s*/ double InitialCtrlDelay = 0.0; double CtrlDelay = 0.0; /* -//- -//- miedzy kolejnymi poz.*/ double CtrlDownDelay = 0.0; /* -//- -//- przy schodzeniu z poz.*/ /*hunter-101012*/ @@ -752,6 +751,8 @@ public: int RVentType = 0; /*0 - brak, 1 - jest, 2 - automatycznie wlaczany*/ double RVentnmax = 1.0; /*maks. obroty wentylatorow oporow rozruchowych*/ double RVentCutOff = 0.0; /*rezystancja wylaczania wentylatorow dla RVentType=2*/ + double RVentSpeed { 0.5 }; //rozpedzanie sie wentylatora obr/s^2} + double RVentMinI { 50.0 }; //przy jakim pradzie sie wylaczaja} int CompressorPower = 1; /*0: bezp. z obwodow silnika, 1: z przetwornicy, reczne, 2: w przetwornicy, stale, 5: z silnikowego*/ int SmallCompressorPower = 0; /*Winger ZROBIC*/ bool Trafo = false; /*pojazd wyposażony w transformator*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 54f5cfff..1f865215 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -4252,7 +4252,7 @@ double TMoverParameters::TractionForce(double dt) RventRot += ( RVentnmax - RventRot ) * RVentSpeed * dt; } else { - RventRot = std::max( 0.0, RventRot - RVentSpeed * dt ); + RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt ); } break; } @@ -4260,14 +4260,30 @@ double TMoverParameters::TractionForce(double dt) case 2: { // automatic if( ( std::abs( Itot ) > RVentMinI ) && ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) { +/* RventRot += ( RVentnmax * abs( Itot ) / ( ImaxLo * RList[ MainCtrlActualPos ].Bn ) - RventRot ) * RVentSpeed * dt; +*/ + RventRot = std::min( + RVentnmax, + RventRot + + ( RVentnmax + * std::abs( Itot ) + * std::min( 1.25, ( ( std::abs( Itot ) / NPoweredAxles ) / RVentMinI ) ) + / ImaxLo + - RventRot ) + * RVentSpeed * dt ); +/* +RventRot = std::min( +RVentnmax, +RventRot + ( ( std::abs( Itot ) / ( RList[ MainCtrlActualPos ].Bn * RList[ MainCtrlActualPos ].Mn ) ) / RVentMinI ) * RVentSpeed * dt ); +*/ } else if( ( DynamicBrakeType == dbrake_automatic ) && ( true == DynamicBrakeFlag ) ) { RventRot += ( RVentnmax * Im / ImaxLo - RventRot ) * RVentSpeed * dt; } else { - RventRot = std::max( 0.0, RventRot - RVentSpeed * dt ); + RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt ); } break; } @@ -4278,8 +4294,9 @@ double TMoverParameters::TractionForce(double dt) } // rventtype } // mains else { - RventRot = std::max( 0.0, RventRot - RVentSpeed * dt ); + RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt ); } + break; } case DieselElectric: { @@ -7739,6 +7756,8 @@ void TMoverParameters::LoadFIZ_RList( std::string const &Input ) { RVentnmax /= 60.0; extract_value( RVentCutOff, "RVentCutOff", Input, "" ); } + extract_value( RVentMinI, "RVentMinI", Input, "" ); + extract_value( RVentSpeed, "RVentSpeed", Input, "" ); } void TMoverParameters::LoadFIZ_DList( std::string const &Input ) { diff --git a/Segment.h b/Segment.h index 319186c9..0cc000a8 100644 --- a/Segment.h +++ b/Segment.h @@ -19,9 +19,9 @@ class TSegment private: Math3D::vector3 Point1, CPointOut, CPointIn, Point2; float - fRoll1{ 0.f }, - fRoll2{ 0.f }; // przechyłka na końcach - double fLength = 0.0; // długość policzona + fRoll1 { 0.f }, + fRoll2 { 0.f }; // przechyłka na końcach + double fLength { -1.0 }; // długość policzona double *fTsBuffer = nullptr; // wartości parametru krzywej dla równych odcinków double fStep = 0.0; int iSegCount = 0; // ilość odcinków do rysowania krzywej diff --git a/Track.cpp b/Track.cpp index db3e1ebd..c40349f0 100644 --- a/Track.cpp +++ b/Track.cpp @@ -406,7 +406,12 @@ void TTrack::Load(cParser *parser, vector3 pOrigin) if (Global::iWriteLogEnabled & 4) WriteLog(str); parser->getTokens(4); - *parser >> fTrackLength >> fTrackWidth >> fFriction >> fSoundDistance; + float discard {}; + *parser + >> discard + >> fTrackWidth + >> fFriction + >> fSoundDistance; fTrackWidth2 = fTrackWidth; // rozstaw/szerokość w punkcie 2, na razie taka sama parser->getTokens(2); *parser >> iQualityFlag >> iDamageFlag; @@ -485,30 +490,40 @@ void TTrack::Load(cParser *parser, vector3 pOrigin) p2.y += 0.18; // na przechyłce doliczyć jeszcze pół przechyłki } - if( fRadius != 0 ) // gdy podany promień - segsize = clamp( std::fabs( fRadius ) * ( 0.02 / Global::SplineFidelity ), 2.0 / Global::SplineFidelity, 10.0 ); + + if( ( ( ( p1 + p1 + p2 ) / 3.0 - p1 - cp1 ).Length() < 0.02 ) + || ( ( ( p1 + p2 + p2 ) / 3.0 - p2 + cp1 ).Length() < 0.02 ) ) { + // "prostowanie" prostych z kontrolnymi, dokładność 2cm + cp1 = cp2 = Math3D::vector3( 0, 0, 0 ); + } + + if( fRadius != 0 ) { + // gdy podany promień + segsize = clamp( std::abs( fRadius ) * ( 0.02 / Global::SplineFidelity ), 2.0 / Global::SplineFidelity, 10.0 ); + } else { // HACK: crude check whether claimed straight is an actual straight piece - // NOTE: won't detect cases where control points are placed on the straight line formed by the ends, but, eh if( ( cp1 == Math3D::vector3() ) - && ( cp1 == Math3D::vector3() ) ) { + && ( cp2 == Math3D::vector3() ) ) { segsize = 10.0; // for straights, 10m per segment works good enough } else { // HACK: divide roughly in 10 segments. - segsize = clamp( fTrackLength * ( 0.1 / Global::SplineFidelity ), 2.0 / Global::SplineFidelity, 10.0 ); + segsize = clamp( ( p1 - p2 ).Length() * ( 0.1 / Global::SplineFidelity ), 2.0 / Global::SplineFidelity, 10.0 ); } } - if ((((p1 + p1 + p2) / 3.0 - p1 - cp1).Length() < 0.02) || - (((p1 + p2 + p2) / 3.0 - p2 + cp1).Length() < 0.02)) - cp1 = cp2 = vector3(0, 0, 0); //"prostowanie" prostych z kontrolnymi, dokładność 2cm + if( ( cp1 == vector3( 0, 0, 0 ) ) + && ( cp2 == vector3( 0, 0, 0 ) ) ) { + // Ra: hm, czasem dla prostego są podane... + // gdy prosty, kontrolne wyliczane przy zmiennej przechyłce + Segment->Init( p1, p2, segsize, r1, r2 ); + } + else { + // gdy łuk (ustawia bCurve=true) + Segment->Init( p1, cp1 + p1, cp2 + p2, p2, segsize, r1, r2 ); + } - if ((cp1 == vector3(0, 0, 0)) && - (cp2 == vector3(0, 0, 0))) // Ra: hm, czasem dla prostego są podane... - Segment->Init(p1, p2, segsize, r1, r2); // gdy prosty, kontrolne wyliczane przy zmiennej przechyłce - else - Segment->Init(p1, cp1 + p1, cp2 + p2, p2, segsize, r1, r2); // gdy łuk (ustawia bCurve=true) if ((r1 != 0) || (r2 != 0)) iTrapezoid = 1; // są przechyłki do uwzględniania w rysowaniu if (eType == tt_Table) // obrotnica ma doklejkę diff --git a/Track.h b/Track.h index 3af0fbcd..ee569462 100644 --- a/Track.h +++ b/Track.h @@ -184,7 +184,7 @@ private: double fVelocity = -1.0; // ograniczenie prędkości // prędkość dla AI (powyżej rośnie prawdopowobieństwo wykolejenia) public: // McZapkie-100502: - double fTrackLength = 100.0; // długość z wpisu, nigdzie nie używana +// double fTrackLength = 100.0; // długość z wpisu, nigdzie nie używana double fRadius = 0.0; // promień, dla zwrotnicy kopiowany z tabeli bool ScannedFlag = false; // McZapkie: do zaznaczania kolorem torów skanowanych przez AI TGroundNode *nFouling[ 2 ] = { nullptr, nullptr }; // współrzędne ukresu albo oporu kozła diff --git a/Train.cpp b/Train.cpp index 529d8ba1..0b81c1ea 100644 --- a/Train.cpp +++ b/Train.cpp @@ -285,6 +285,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::radiotoggle, &TTrain::OnCommand_radiotoggle }, { user_command::radiochannelincrease, &TTrain::OnCommand_radiochannelincrease }, { user_command::radiochanneldecrease, &TTrain::OnCommand_radiochanneldecrease }, + { user_command::radiostopsend, &TTrain::OnCommand_radiostopsend }, { user_command::radiostoptest, &TTrain::OnCommand_radiostoptest }, { user_command::cabchangeforward, &TTrain::OnCommand_cabchangeforward }, { user_command::cabchangebackward, &TTrain::OnCommand_cabchangebackward }, @@ -3104,11 +3105,33 @@ void TTrain::OnCommand_radiochanneldecrease( TTrain *Train, command_data const & } } +void TTrain::OnCommand_radiostopsend( TTrain *Train, command_data const &Command ) { + + if( Command.action == GLFW_PRESS ) { + if( true == Train->mvOccupied->Radio ) { + simulation::Region->RadioStop( Train->Dynamic()->GetPosition() ); + } + // visual feedback + Train->ggRadioStop.UpdateValue( 1.0 ); + } + else if( Command.action == GLFW_RELEASE ) { + // visual feedback + Train->ggRadioStop.UpdateValue( 0.0 ); + } +} void TTrain::OnCommand_radiostoptest( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_PRESS ) { - Train->Dynamic()->RadioStop(); + if( Train->RadioChannel() == 10 ) { + Train->Dynamic()->RadioStop(); + } + // visual feedback + Train->ggRadioTest.UpdateValue( 1.0 ); + } + else if( Command.action == GLFW_RELEASE ) { + // visual feedback + Train->ggRadioTest.UpdateValue( 0.0 ); } } @@ -3939,6 +3962,7 @@ bool TTrain::Update( double const Deltatime ) btLampkaMaxSila.Turn(abs(mvControlled->Im) >= 350); btLampkaPrzekrMaxSila.Turn(abs(mvControlled->Im) >= 450); btLampkaRadio.Turn(mvOccupied->Radio); + btLampkaRadioStop.Turn( mvOccupied->Radio && mvOccupied->RadioStopFlag ); btLampkaHamulecReczny.Turn(mvOccupied->ManualBrakePos > 0); // NBMX wrzesien 2003 - drzwi oraz sygnał odjazdu btLampkaDoorLeft.Turn(mvOccupied->DoorLeftOpened); @@ -3974,6 +3998,7 @@ bool TTrain::Update( double const Deltatime ) btLampkaMaxSila.Turn( false ); btLampkaPrzekrMaxSila.Turn( false ); btLampkaRadio.Turn( false ); + btLampkaRadioStop.Turn( false ); btLampkaHamulecReczny.Turn( false ); btLampkaDoorLeft.Turn( false ); btLampkaDoorRight.Turn( false ); @@ -4187,6 +4212,8 @@ bool TTrain::Update( double const Deltatime ) ggRadioChannelSelector.Update(); ggRadioChannelPrevious.Update(); ggRadioChannelNext.Update(); + ggRadioStop.Update(); + ggRadioTest.Update(); ggDepartureSignalButton.Update(); ggPantFrontButton.Update(); @@ -4563,6 +4590,15 @@ TTrain::update_sounds( double const Deltatime ) { } } + // radiostop + if( ( true == mvOccupied->Radio ) + && ( true == mvOccupied->RadioStopFlag ) ) { + m_radiostop.play( sound_flags::exclusive | sound_flags::looping ); + } + else { + m_radiostop.stop(); + } + if( fTachoCount > 3.f ) { dsbHasler.play( sound_flags::exclusive | sound_flags::looping ); } @@ -4648,6 +4684,11 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName) dsbBuzzer.deserialize( parser, sound_type::single ); dsbBuzzer.owner( DynamicObject ); } + else if( token == "radiostop:" ) { + // radiostop + m_radiostop.deserialize( parser, sound_type::single ); + m_radiostop.owner( DynamicObject ); + } else if (token == "slipalarm:") { // Bombardier 011010: alarm przy poslizgu: @@ -4787,7 +4828,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) &dsbSwitch, &dsbPneumaticSwitch, &rsHiss, &rsHissU, &rsHissE, &rsHissX, &rsHissT, &rsSBHiss, &rsSBHissU, &rsFadeSound, &rsRunningNoise, - &dsbHasler, &dsbBuzzer, &dsbSlipAlarm, &m_radiosound + &dsbHasler, &dsbBuzzer, &dsbSlipAlarm, &m_radiosound, &m_radiostop }; for( auto sound : sounds ) { sound->offset( nullvector ); @@ -4967,6 +5008,9 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) if( m_radiosound.offset() == nullvector ) { m_radiosound.offset( btLampkaRadio.model_offset() ); } + if( m_radiostop.offset() == nullvector ) { + m_radiostop.offset( m_radiosound.offset() ); + } auto const localbrakeoffset { ggLocalBrake.model_offset() }; std::vector localbrakesounds = { &rsSBHiss, &rsSBHissU @@ -5183,6 +5227,8 @@ void TTrain::clear_cab_controls() ggRadioChannelSelector.Clear(); ggRadioChannelPrevious.Clear(); ggRadioChannelNext.Clear(); + ggRadioStop.Clear(); + ggRadioTest.Clear(); ggDoorLeftButton.Clear(); ggDoorRightButton.Clear(); ggDepartureSignalButton.Clear(); @@ -5242,6 +5288,7 @@ void TTrain::clear_cab_controls() btLampkaMaxSila.Clear(); btLampkaPrzekrMaxSila.Clear(); btLampkaRadio.Clear(); + btLampkaRadioStop.Clear(); btLampkaHamulecReczny.Clear(); btLampkaBlokadaDrzwi.Clear(); btInstrumentLight.Clear(); @@ -5502,6 +5549,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co { "i-maxft:", btLampkaMaxSila }, { "i-maxftt:", btLampkaPrzekrMaxSila }, { "i-radio:", btLampkaRadio }, + { "i-radiostop:", btLampkaRadioStop }, { "i-manual_brake:", btLampkaHamulecReczny }, { "i-door_blocked:", btLampkaBlokadaDrzwi }, { "i-slippery:", btLampkaPoslizg }, @@ -5655,6 +5703,8 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "radiochannel_sw:", ggRadioChannelSelector }, { "radiochannelprev_sw:", ggRadioChannelPrevious }, { "radiochannelnext_sw:", ggRadioChannelNext }, + { "radiostop_sw:", ggRadioStop }, + { "radiotest_sw:", ggRadioTest }, { "pantfront_sw:", ggPantFrontButton }, { "pantrear_sw:", ggPantRearButton }, { "pantfrontoff_sw:", ggPantFrontButtonOff }, diff --git a/Train.h b/Train.h index 48892cbe..99d4bbe7 100644 --- a/Train.h +++ b/Train.h @@ -211,6 +211,7 @@ class TTrain static void OnCommand_radiotoggle( TTrain *Train, command_data const &Command ); static void OnCommand_radiochannelincrease( TTrain *Train, command_data const &Command ); static void OnCommand_radiochanneldecrease( TTrain *Train, command_data const &Command ); + static void OnCommand_radiostopsend( TTrain *Train, command_data const &Command ); static void OnCommand_radiostoptest( TTrain *Train, command_data const &Command ); static void OnCommand_cabchangeforward( TTrain *Train, command_data const &Command ); static void OnCommand_cabchangebackward( TTrain *Train, command_data const &Command ); @@ -274,6 +275,8 @@ public: // reszta może by?publiczna TGauge ggRadioChannelSelector; TGauge ggRadioChannelPrevious; TGauge ggRadioChannelNext; + TGauge ggRadioTest; + TGauge ggRadioStop; TGauge ggUpperLightButton; TGauge ggLeftLightButton; TGauge ggRightLightButton; @@ -357,6 +360,7 @@ public: // reszta może by?publiczna TButton btLampkaUkrotnienie; TButton btLampkaHamPosp; TButton btLampkaRadio; + TButton btLampkaRadioStop; TButton btLampkaHamowanie1zes; TButton btLampkaHamowanie2zes; TButton btLampkaOpory; @@ -458,6 +462,7 @@ public: // reszta może by?publiczna sound_source dsbSlipAlarm { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // Bombardier 011010: alarm przy poslizgu dla 181/182 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? diff --git a/World.cpp b/World.cpp index 4e580d6d..77404f11 100644 --- a/World.cpp +++ b/World.cpp @@ -629,11 +629,6 @@ void TWorld::OnKeyDown(int cKey) { Global::iTextMode = GLFW_KEY_F1; // to wyświetlić zegar i informację } } - else if( ( cKey == GLFW_KEY_PAUSE ) && ( Global::ctrlState ) && ( Global::shiftState ) ) { - //[Ctrl]+[Break] hamowanie wszystkich pojazdów w okolicy // added shift to prevent odd issue with glfw producing pause presses on its own - if( Controlled->MoverParameters->Radio ) - simulation::Region->RadioStop( Camera.Pos ); - } else { if( ( true == DebugModeFlag ) @@ -1424,15 +1419,16 @@ TWorld::Update_UI() { uitextline4 += "Driver: Vd=" + to_string( vehicle->Mechanik->VelDesired, 0 ) + " Ad=" + to_string( vehicle->Mechanik->AccDesired, 2 ) - + " Ah=" + to_string( vehicle->Mechanik->fAccThreshold, 2 ) - + "@" + to_string( vehicle->Mechanik->fBrake_a0[0], 2 ) - + "+" + to_string( vehicle->Mechanik->fBrake_a1[0], 2 ) + + " Ah=" + to_string( vehicle->Mechanik->fAccThreshold, 2 ) + + "@" + to_string( vehicle->Mechanik->fBrake_a0[ 0 ], 2 ) + + "+" + to_string( vehicle->Mechanik->fBrake_a1[ 0 ], 2 ) + " Bd=" + to_string( vehicle->Mechanik->fBrakeDist, 0 ) + " Pd=" + to_string( vehicle->Mechanik->ActualProximityDist, 0 ) + " Vn=" + to_string( vehicle->Mechanik->VelNext, 0 ) + " VSl=" + to_string( vehicle->Mechanik->VelSignalLast, 0 ) + " VLl=" + to_string( vehicle->Mechanik->VelLimitLast, 0 ) - + " VRd=" + to_string( vehicle->Mechanik->VelRoad, 0 ); + + " VRd=" + to_string( vehicle->Mechanik->VelRoad, 0 ) + + " VRst=" + to_string( vehicle->Mechanik->VelRestricted, 0 ); if( ( vehicle->Mechanik->VelNext == 0.0 ) && ( vehicle->Mechanik->eSignNext ) ) { diff --git a/command.cpp b/command.cpp index e9d31988..6a2f72ff 100644 --- a/command.cpp +++ b/command.cpp @@ -76,6 +76,7 @@ commanddescription_sequence Commands_descriptions = { { "radiotoggle", command_target::vehicle }, { "radiochannelincrease", command_target::vehicle }, { "radiochanneldecrease", command_target::vehicle }, + { "radiostopsend", command_target::vehicle }, { "radiostoptest", command_target::vehicle }, // TBD, TODO: make cab change controls entity-centric { "cabchangeforward", command_target::vehicle }, diff --git a/command.h b/command.h index be604dd1..98a69caa 100644 --- a/command.h +++ b/command.h @@ -71,6 +71,7 @@ enum class user_command { radiotoggle, radiochannelincrease, radiochanneldecrease, + radiostopsend, radiostoptest, cabchangeforward, cabchangebackward, diff --git a/keyboardinput.cpp b/keyboardinput.cpp index 8071e9f3..2fde9b6d 100644 --- a/keyboardinput.cpp +++ b/keyboardinput.cpp @@ -42,7 +42,7 @@ keyboard_input::recall_bindings() { { ";", GLFW_KEY_SEMICOLON }, { "'", GLFW_KEY_APOSTROPHE }, { "enter", GLFW_KEY_ENTER }, { ",", GLFW_KEY_COMMA }, { ".", GLFW_KEY_PERIOD }, { "/", GLFW_KEY_SLASH }, { "space", GLFW_KEY_SPACE }, - { "insert", GLFW_KEY_INSERT },{ "delete", GLFW_KEY_DELETE }, { "home", GLFW_KEY_HOME }, { "end", GLFW_KEY_END }, + { "pause", GLFW_KEY_PAUSE }, { "insert", GLFW_KEY_INSERT }, { "delete", GLFW_KEY_DELETE }, { "home", GLFW_KEY_HOME }, { "end", GLFW_KEY_END }, // numpad block { "num_/", GLFW_KEY_KP_DIVIDE }, { "num_*", GLFW_KEY_KP_MULTIPLY }, { "num_-", GLFW_KEY_KP_SUBTRACT }, { "num_7", GLFW_KEY_KP_7 }, { "num_8", GLFW_KEY_KP_8 }, { "num_9", GLFW_KEY_KP_9 }, { "num_+", GLFW_KEY_KP_ADD }, @@ -281,6 +281,8 @@ keyboard_input::default_bindings() { { GLFW_KEY_R | keymodifier::shift }, // radiochanneldecrease { GLFW_KEY_R }, + // radiostopsend + { GLFW_KEY_PAUSE | keymodifier::shift | keymodifier::control }, // radiostoptest { GLFW_KEY_R | keymodifier::shift | keymodifier::control }, // cabchangeforward diff --git a/material.cpp b/material.cpp index ed224744..7e49e030 100644 --- a/material.cpp +++ b/material.cpp @@ -57,19 +57,27 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c ; // all work is done in the header } } + else if( key == Global::Weather ) { + // weather textures override generic and seasonal textures + while( true == deserialize_mapping( blockparser, 2, Loadnow ) ) { + ; // all work is done in the header + } + } } else if( key == "texture1:" ) { // TODO: full-fledged priority system if( ( texture1 == null_handle ) - || ( Priority > 0 ) ) { + || ( Priority > priority1 ) ) { texture1 = GfxRenderer.Fetch_Texture( path + value, Loadnow ); + priority1 = Priority; } } else if( key == "texture2:" ) { // TODO: full-fledged priority system if( ( texture2 == null_handle ) - || ( Priority > 0 ) ) { + || ( Priority > priority2 ) ) { texture2 = GfxRenderer.Fetch_Texture( path + value, Loadnow ); + priority2 = Priority; } } diff --git a/material.h b/material.h index 72093fc3..881c14b9 100644 --- a/material.h +++ b/material.h @@ -24,13 +24,20 @@ struct opengl_material { bool has_alpha { false }; // alpha state, calculated from presence of alpha in texture1 std::string name; -// methods: + +// methods bool deserialize( cParser &Input, bool const Loadnow ); + private: +// methods // imports member data pair from the config file, overriding existing parameter values of lower priority bool deserialize_mapping( cParser &Input, int const Priority, bool const Loadnow ); + +// members + int priority1 { -1 }; // priority of last loaded primary texture + int priority2 { -1 }; // priority of last loaded secondary texture }; class material_manager { diff --git a/mouseinput.cpp b/mouseinput.cpp index 370d6b85..f885e090 100644 --- a/mouseinput.cpp +++ b/mouseinput.cpp @@ -25,6 +25,10 @@ mouse_input::init() { DWORD systemkeyboardspeed; ::SystemParametersInfo( SPI_GETKEYBOARDSPEED, 0, &systemkeyboardspeed, 0 ); m_updaterate = interpolate( 0.5, 0.04, systemkeyboardspeed / 31.0 ); + DWORD systemkeyboarddelay; + ::SystemParametersInfo( SPI_GETKEYBOARDDELAY, 0, &systemkeyboarddelay, 0 ); + m_updatedelay = interpolate( 0.25, 1.0, systemkeyboarddelay / 3.0 ); + #endif return true; } @@ -139,7 +143,7 @@ mouse_input::button( int const Button, int const Action ) { // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // TODO: pass correct entity id once the missing systems are in place m_relay.post( mousecommand, 0, 0, Action, 0 ); - m_updateaccumulator = 0.0; // prevent potential command repeat right after issuing one + m_updateaccumulator = -0.25; // prevent potential command repeat right after issuing one switch( mousecommand ) { case user_command::mastercontrollerincrease: @@ -183,23 +187,21 @@ mouse_input::poll() { updaterate /= std::max( 0.15, 2.0 * glm::length( m_cursorposition - m_commandstartcursor ) / std::max( 1, Global::iWindowHeight ) ); } - if( m_updateaccumulator < updaterate ) { - // too early for any work - return; - } - m_updateaccumulator -= updaterate; + while( m_updateaccumulator > updaterate ) { - if( m_mousecommandleft != user_command::none ) { - // NOTE: basic keyboard controls don't have any parameters - // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 - // TODO: pass correct entity id once the missing systems are in place - m_relay.post( m_mousecommandleft, 0, 0, GLFW_REPEAT, 0 ); - } - if( m_mousecommandright != user_command::none ) { - // NOTE: basic keyboard controls don't have any parameters - // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 - // TODO: pass correct entity id once the missing systems are in place - m_relay.post( m_mousecommandright, 0, 0, GLFW_REPEAT, 0 ); + if( m_mousecommandleft != user_command::none ) { + // NOTE: basic keyboard controls don't have any parameters + // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 + // TODO: pass correct entity id once the missing systems are in place + m_relay.post( m_mousecommandleft, 0, 0, GLFW_REPEAT, 0 ); + } + if( m_mousecommandright != user_command::none ) { + // NOTE: basic keyboard controls don't have any parameters + // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 + // TODO: pass correct entity id once the missing systems are in place + m_relay.post( m_mousecommandright, 0, 0, GLFW_REPEAT, 0 ); + } + m_updateaccumulator -= updaterate; } } @@ -351,6 +353,12 @@ mouse_input::default_bindings() { { "radiochannelnext_sw:", { user_command::radiochannelincrease, user_command::none } }, + { "radiostop_sw:", { + user_command::radiostopsend, + user_command::none } }, + { "radiotest_sw:", { + user_command::radiostoptest, + user_command::none } }, { "pantfront_sw:", { user_command::pantographtogglefront, user_command::none } }, diff --git a/mouseinput.h b/mouseinput.h index 9c7a853e..ff9c77eb 100644 --- a/mouseinput.h +++ b/mouseinput.h @@ -48,6 +48,7 @@ private: user_command m_mousecommandleft { user_command::none }; // last if any command issued with left mouse button user_command m_mousecommandright { user_command::none }; // last if any command issued with right mouse button double m_updaterate { 0.075 }; + double m_updatedelay { 0.25 }; double m_updateaccumulator { 0.0 }; bool m_pickmodepanning { false }; // indicates mouse is in view panning mode glm::dvec2 m_cursorposition; // stored last cursor position, used for panning diff --git a/renderer.cpp b/renderer.cpp index 9eb9f84d..2177046d 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -1460,8 +1460,7 @@ opengl_renderer::Render( world_environment *Environment ) { Render( Environment->m_clouds.mdCloud, nullptr, 100.0 ); Render_Alpha( Environment->m_clouds.mdCloud, nullptr, 100.0 ); // post-render cleanup - GLfloat noambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, noambient ); + ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( colors::none ) ); ::glEnable( GL_LIGHT0 ); // other lights will be enabled during lights update ::glDisable( GL_LIGHTING ); } diff --git a/translation.h b/translation.h index 3abc7bb5..6233b87f 100644 --- a/translation.h +++ b/translation.h @@ -66,6 +66,8 @@ static std::unordered_map m_cabcontrols = { { "radiochannel_sw:", "radio channel" }, { "radiochannelprev_sw:", "radio channel" }, { "radiochannelnext_sw:", "radio channel" }, + { "radiotest_sw:", "radiostop test" }, + { "radiostop_sw:", "radiostop" }, { "pantfront_sw:", "pantograph A" }, { "pantrear_sw:", "pantograph B" }, { "pantfrontoff_sw:", "pantograph A" }, diff --git a/version.h b/version.h index 7ed4a66e..8560b6c9 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 18 -#define VERSION_MINOR 122 +#define VERSION_MINOR 124 #define VERSION_REVISION 0