mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
build 210324. event queue text filter enhancement, contextual uncoupling sounds, parameter support for python screens, radio and odometer state exposed to python scripts, configurable audio volume when paused, skydome color calculation tweak, fog color calculation tweak, doorstep cab control enhancement, tempomat cab control enhancement, pantograph selector preset list support, minor bug fixes
This commit is contained in:
102
Driver.cpp
102
Driver.cpp
@@ -964,7 +964,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
VelLimitLastDist.second = d + point.trTrack->Length() + fLength;
|
||||
}
|
||||
else if( VelLimitLastDist.second > 0 ) { // the speed limit can potentially start afterwards, so don't mark it as broken too soon
|
||||
speedlimitiscontinuous = false;
|
||||
if( ( point.iFlags & ( spSwitch | spPassengerStopPoint ) ) == 0 ) {
|
||||
speedlimitiscontinuous = false;
|
||||
}
|
||||
}
|
||||
if( false == railwaytrackend ) {
|
||||
continue; // i tyle wystarczy
|
||||
@@ -1213,7 +1215,7 @@ TController::TableUpdateStopPoint( TCommandType &Command, TSpeedPos &Point, doub
|
||||
//jeśli nie widzi następnego sygnału ustawia dotychczasową
|
||||
eSignNext = Point.evEvent;
|
||||
}
|
||||
if( mvOccupied->Vel > 0.3 ) {
|
||||
if( mvOccupied->Vel > EU07_AI_MOVEMENT ) {
|
||||
// jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie
|
||||
Point.fVelNext = 0;
|
||||
// potentially announce pending stop
|
||||
@@ -1540,7 +1542,7 @@ TController::TableUpdateEvent( double &Velocity, TCommandType &Command, TSpeedPo
|
||||
Velocity = 0.0;
|
||||
}
|
||||
else {
|
||||
VelSignalNext - Point.fVelNext;
|
||||
VelSignalNext = Point.fVelNext;
|
||||
if( Velocity < 0 ) {
|
||||
Velocity = fVelMax;
|
||||
VelSignal = fVelMax;
|
||||
@@ -2510,10 +2512,8 @@ bool TController::CheckVehicles(TOrders user)
|
||||
*/
|
||||
}
|
||||
|
||||
// Ra 2014-09: tymczasowo prymitywne ustawienie warunku pod kątem SN61
|
||||
if( ( is_emu() )
|
||||
|| ( is_dmu() )
|
||||
|| ( iVehicles == 1 ) ) {
|
||||
// detect push-pull train configurations and mark them accordingly
|
||||
if( pVehicles[ end::front ]->is_connected( pVehicles[ end::rear ], coupling::control ) ) {
|
||||
// zmiana czoła przez zmianę kabiny
|
||||
iDrivigFlags |= movePushPull;
|
||||
}
|
||||
@@ -2540,7 +2540,7 @@ void TController::Lights(int head, int rear)
|
||||
void TController::DirectionInitial()
|
||||
{ // ustawienie kierunku po wczytaniu trainset (może jechać na wstecznym
|
||||
mvOccupied->CabActivisation(); // załączenie rozrządu (wirtualne kabiny)
|
||||
if (mvOccupied->Vel > 0.0)
|
||||
if (mvOccupied->Vel > EU07_AI_NOMOVEMENT)
|
||||
{ // jeśli na starcie jedzie
|
||||
iDirection = iDirectionOrder =
|
||||
(mvOccupied->V > 0 ? 1 : -1); // początkowa prędkość wymusza kierunek jazdy
|
||||
@@ -2825,7 +2825,7 @@ bool TController::ReleaseEngine() {
|
||||
}
|
||||
*/
|
||||
// don't bother with the rest until we're standing still
|
||||
if( mvOccupied->Vel > 0.01 ) { return false; }
|
||||
if( mvOccupied->Vel > EU07_AI_NOMOVEMENT ) { return false; }
|
||||
|
||||
LastReactionTime = 0.0;
|
||||
ReactionTime = PrepareTime;
|
||||
@@ -3248,7 +3248,7 @@ bool TController::DecBrakeEIM()
|
||||
{
|
||||
case 0: {
|
||||
if( mvOccupied->MED_amax != 9.81 ) {
|
||||
auto const desiredacceleration { ( mvOccupied->Vel > 0.01 ? AccDesired : std::max( 0.0, AccDesired ) ) };
|
||||
auto const desiredacceleration { ( mvOccupied->Vel > EU07_AI_NOMOVEMENT ? AccDesired : std::max( 0.0, AccDesired ) ) };
|
||||
auto const brakeposition { clamp( -1.0 * mvOccupied->AIHintLocalBrakeAccFactor * desiredacceleration / mvOccupied->MED_amax, 0.0, 1.0 ) };
|
||||
OK = ( brakeposition != mvOccupied->LocalBrakePosA );
|
||||
mvOccupied->LocalBrakePosA = brakeposition;
|
||||
@@ -3684,7 +3684,7 @@ void TController::SpeedSet() {
|
||||
else {
|
||||
// jak ma jechać
|
||||
if( fActionTime < 0.0 ) { break; }
|
||||
if( fReady > ( mvOccupied->Vel > 5.0 ? 0.5 : 0.4 ) ) { break; }
|
||||
if( false == Ready ) { break; }
|
||||
|
||||
if( mvOccupied->DirActive > 0 ) {
|
||||
mvOccupied->DirectionForward(); //żeby EN57 jechały na drugiej nastawie
|
||||
@@ -4210,7 +4210,7 @@ void TController::Doors( bool const Open, int const Side ) {
|
||||
|
||||
if( ( true == ismanualdoor )
|
||||
&& ( ( vehicle->LoadExchangeTime() == 0.f )
|
||||
|| ( vehicle->MoverParameters->Vel > 0.1 ) ) ) {
|
||||
|| ( vehicle->MoverParameters->Vel > EU07_AI_MOVEMENT ) ) ) {
|
||||
vehicle->MoverParameters->OperateDoors( side::right, false, range_t::local );
|
||||
vehicle->MoverParameters->OperateDoors( side::left, false, range_t::local );
|
||||
}
|
||||
@@ -4535,7 +4535,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
||||
OrderNext(o); // to samo robić po zmianie
|
||||
else if (!o) // jeśli wcześniej było czekanie
|
||||
OrderNext(Shunt); // to dalej jazda manewrowa
|
||||
if (mvOccupied->Vel >= 1.0) // jeśli jedzie
|
||||
if (mvOccupied->Vel >= EU07_AI_MOVEMENT) // jeśli jedzie
|
||||
iDrivigFlags &= ~moveStartHorn; // to bez trąbienia po ruszeniu z zatrzymania
|
||||
// Change_direction wykona się samo i następnie przejdzie do kolejnej komendy
|
||||
return true;
|
||||
@@ -4795,7 +4795,7 @@ TController::Update( double const Timedelta ) {
|
||||
auto const awarenessrange {
|
||||
std::max(
|
||||
750.0,
|
||||
mvOccupied->Vel > 5.0 ?
|
||||
mvOccupied->Vel > EU07_AI_MOVEMENT ?
|
||||
400 + fBrakeDist :
|
||||
30.0 * fDriverDist ) }; // 1500m dla stojących pociągów;
|
||||
if( is_active() ) {
|
||||
@@ -4893,8 +4893,9 @@ TController::PrepareDirection() {
|
||||
|
||||
if( iDirection == 0 ) {
|
||||
// jeśli nie ma ustalonego kierunku
|
||||
if( mvOccupied->Vel < 0.01 ) { // ustalenie kierunku, gdy stoi
|
||||
if( mvOccupied->Vel < EU07_AI_NOMOVEMENT ) { // ustalenie kierunku, gdy stoi
|
||||
iDirection = mvOccupied->CabActive; // wg wybranej kabiny
|
||||
/*
|
||||
if( iDirection == 0 ) {
|
||||
// jeśli nie ma ustalonego kierunku
|
||||
if( mvOccupied->Couplers[ end::rear ].Connected == nullptr ) {
|
||||
@@ -4906,6 +4907,7 @@ TController::PrepareDirection() {
|
||||
iDirection = 1; // jazda w kierunku sprzęgu 0
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
else {
|
||||
// ustalenie kierunku, gdy jedzie
|
||||
@@ -5354,7 +5356,7 @@ TCommandType TController::BackwardScan( double const Range )
|
||||
}
|
||||
else {
|
||||
if( ( scandist > fMinProximityDist )
|
||||
&& ( ( mvOccupied->Vel > 0.0 )
|
||||
&& ( ( mvOccupied->Vel > EU07_AI_NOMOVEMENT )
|
||||
&& ( ( OrderCurrentGet() & ( Shunt | Loose_shunt ) ) == 0 ) ) ) {
|
||||
// jeśli semafor jest daleko, a pojazd jedzie, to informujemy o zmianie prędkości
|
||||
// jeśli jedzie manewrowo, musi dostać SetVelocity, żeby sie na pociągowy przełączył
|
||||
@@ -5393,12 +5395,12 @@ TCommandType TController::BackwardScan( double const Range )
|
||||
if (move ? true : e->input_command() == TCommandType::cm_ShuntVelocity)
|
||||
{ // jeśli powyżej było SetVelocity 0 0, to dociągamy pod S1
|
||||
if ((scandist > fMinProximityDist) &&
|
||||
(mvOccupied->Vel > 0.0) || (vmechmax == 0.0) )
|
||||
(mvOccupied->Vel > EU07_AI_NOMOVEMENT) || (vmechmax == 0.0) )
|
||||
{ // jeśli tarcza jest daleko, to:
|
||||
//- jesli pojazd jedzie, to informujemy o zmianie prędkości
|
||||
//- jeśli stoi, to z własnej inicjatywy może podjechać pod zamkniętą
|
||||
// tarczę
|
||||
if (mvOccupied->Vel > 0.0) // tylko jeśli jedzie
|
||||
if (mvOccupied->Vel > EU07_AI_NOMOVEMENT) // tylko jeśli jedzie
|
||||
{ // Mechanik->PutCommand("SetProximityVelocity",scandist,vmechmax,sl);
|
||||
#if LOGBACKSCAN
|
||||
// WriteLog(edir+"SetProximityVelocity "+AnsiString(scandist)+"
|
||||
@@ -5907,7 +5909,7 @@ TController::determine_consist_state() {
|
||||
fAccGravity /= fMass;
|
||||
{
|
||||
auto absaccs { fAccGravity }; // Ra 2014-03: jesli skład stoi, to działa na niego składowa styczna grawitacji
|
||||
if( mvOccupied->Vel > 0.01 ) {
|
||||
if( mvOccupied->Vel > EU07_AI_NOMOVEMENT ) {
|
||||
absaccs = 0;
|
||||
auto *d = pVehicles[ end::front ]; // pojazd na czele składu
|
||||
while( d ) {
|
||||
@@ -5939,7 +5941,7 @@ TController::determine_consist_state() {
|
||||
if( has_diesel_engine() ) {
|
||||
|
||||
Ready = (
|
||||
( vehicle->Vel > 0.5 ) // already moving
|
||||
( vehicle->Vel > EU07_AI_MOVEMENT ) // already moving
|
||||
|| ( false == vehicle->Mains ) // deadweight vehicle
|
||||
|| ( vehicle->enrot > 0.8 * (
|
||||
vehicle->EngineType == TEngineType::DieselEngine ?
|
||||
@@ -6001,7 +6003,7 @@ TController::control_pantographs() {
|
||||
|| ( is_emu() ) // special case
|
||||
|| ( mvControlling->TrainType == dt_ET41 ) }; // special case
|
||||
|
||||
if( mvOccupied->Vel > 0.05 ) {
|
||||
if( mvOccupied->Vel > EU07_AI_NOMOVEMENT ) {
|
||||
|
||||
if( ( fOverhead2 >= 0.0 ) || iOverheadZero ) {
|
||||
// jeśli jazda bezprądowa albo z opuszczonym pantografem
|
||||
@@ -6116,7 +6118,7 @@ TController::control_horns( double const Timedelta ) {
|
||||
cue_action( locale::string::driver_hint_hornoff ); // a tu się kończy
|
||||
}
|
||||
}
|
||||
if( mvOccupied->Vel >= 5.0 ) {
|
||||
if( mvOccupied->Vel > EU07_AI_MOVEMENT ) {
|
||||
// jesli jedzie, można odblokować trąbienie, bo się wtedy nie włączy
|
||||
iDrivigFlags &= ~moveStartHornDone; // zatrąbi dopiero jak następnym razem stanie
|
||||
iDrivigFlags |= moveStartHorn; // i trąbić przed następnym ruszeniem
|
||||
@@ -6292,7 +6294,7 @@ TController::control_doors() {
|
||||
if( false == doors_open() ) { return; }
|
||||
// jeżeli jedzie
|
||||
// nie zamykać drzwi przy drganiach, bo zatrzymanie na W4 akceptuje niewielkie prędkości
|
||||
if( mvOccupied->Vel > 1.0 ) {
|
||||
if( mvOccupied->Vel > EU07_AI_MOVEMENT ) {
|
||||
Doors( false );
|
||||
return;
|
||||
}
|
||||
@@ -6600,25 +6602,30 @@ TController::check_departure() {
|
||||
void
|
||||
TController::UpdateChangeDirection() {
|
||||
// TODO: rework into driver mode independent routine
|
||||
if( ( true == AIControllFlag)
|
||||
&& ( true == TestFlag( OrderCurrentGet(), Change_direction ) ) ) {
|
||||
if( false == TestFlag( OrderCurrentGet(), Change_direction ) ) { return; }
|
||||
|
||||
if( true == AIControllFlag ) {
|
||||
// sprobuj zmienic kierunek (może być zmieszane z jeszcze jakąś komendą)
|
||||
if( mvOccupied->Vel < 0.1 ) {
|
||||
if( mvOccupied->Vel < EU07_AI_NOMOVEMENT ) {
|
||||
// jeśli się zatrzymał, to zmieniamy kierunek jazdy, a nawet kabinę/człon
|
||||
Activation(); // ustawienie zadanego wcześniej kierunku i ewentualne przemieszczenie AI
|
||||
PrepareEngine();
|
||||
JumpToNextOrder(); // następnie robimy, co jest do zrobienia (Shunt albo Obey_train)
|
||||
if( OrderCurrentGet() & ( Shunt | Loose_shunt | Connect ) ) {
|
||||
// jeśli dalej mamy manewry
|
||||
if( false == TestFlag( iDrivigFlags, moveStopHere ) ) {
|
||||
// o ile nie ma stać w miejscu,
|
||||
// jechać od razu w przeciwną stronę i nie trąbić z tego tytułu:
|
||||
iDrivigFlags &= ~moveStartHorn;
|
||||
SetVelocity( fShuntVelocity, fShuntVelocity );
|
||||
}
|
||||
} // Change_direction (tylko dla AI)
|
||||
}
|
||||
// shared part of the routine, implement if direction matches what was requested
|
||||
if( ( mvOccupied->Vel < EU07_AI_NOMOVEMENT )
|
||||
&& ( iDirection == iDirectionOrder ) ) {
|
||||
PrepareEngine();
|
||||
JumpToNextOrder(); // następnie robimy, co jest do zrobienia (Shunt albo Obey_train)
|
||||
if( OrderCurrentGet() & ( Shunt | Loose_shunt | Connect ) ) {
|
||||
// jeśli dalej mamy manewry
|
||||
if( false == TestFlag( iDrivigFlags, moveStopHere ) ) {
|
||||
// o ile nie ma stać w miejscu,
|
||||
// jechać od razu w przeciwną stronę i nie trąbić z tego tytułu:
|
||||
iDrivigFlags &= ~moveStartHorn;
|
||||
SetVelocity( fShuntVelocity, fShuntVelocity );
|
||||
}
|
||||
}
|
||||
} // Change_direction (tylko dla AI)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -7116,7 +7123,7 @@ TController::adjust_desired_speed_for_obstacles() {
|
||||
}
|
||||
}
|
||||
ReactionTime = (
|
||||
mvOccupied->Vel > 0.01 ?
|
||||
mvOccupied->Vel > EU07_AI_NOMOVEMENT ?
|
||||
0.1 : // orientuj się, bo jest goraco
|
||||
2.0 ); // we're already standing still, so take it easy
|
||||
}
|
||||
@@ -7225,7 +7232,7 @@ TController::adjust_desired_speed_for_target_speed( double const Range ) {
|
||||
&& ( ActualProximityDist <= Range )
|
||||
&& ( vel >= VelNext ) ) {
|
||||
// gdy zbliża się i jest za szybki do nowej prędkości, albo stoi na zatrzymaniu
|
||||
if (vel > 0.0) {
|
||||
if (vel > EU07_AI_NOMOVEMENT) {
|
||||
// jeśli jedzie
|
||||
if( ( vel < VelNext )
|
||||
&& ( ActualProximityDist > fMaxProximityDist * ( 1.0 + 0.1 * vel ) ) ) {
|
||||
@@ -7402,7 +7409,7 @@ TController::adjust_desired_speed_for_current_speed() {
|
||||
clamp( VelDesired - speedestimate, 0.0, fVelMinus ) / fVelMinus ) );
|
||||
}
|
||||
// final tweaks
|
||||
if( vel > 0.1 ) {
|
||||
if( vel > EU07_AI_NOMOVEMENT ) {
|
||||
// going downhill also take into account impact of gravity
|
||||
AccDesired -= fAccGravity;
|
||||
// HACK: if the max allowed speed was exceeded something went wrong; brake harder
|
||||
@@ -7450,7 +7457,7 @@ TController::adjust_desired_speed_for_current_speed() {
|
||||
if( vel < VelDesired ) {
|
||||
// don't adjust acceleration when going above current target speed
|
||||
if( -AccDesired * BrakeAccFactor() < (
|
||||
( ( fReady > ( IsHeavyCargoTrain ? 0.4 : ( mvOccupied->Vel > 5.0 ) ? 0.45 : 0.4 ) )
|
||||
( ( false == Ready )
|
||||
|| ( VelNext > vel - 40.0 ) ) ?
|
||||
fBrake_a0[ 0 ] * 0.8 :
|
||||
-fAccThreshold )
|
||||
@@ -7483,7 +7490,7 @@ TController::control_tractive_and_braking_force() {
|
||||
|
||||
// if the radio-stop was issued don't waste effort trying to fight it
|
||||
if( ( true == mvOccupied->RadioStopFlag ) // radio-stop
|
||||
&& ( mvOccupied->Vel > 0.0 ) ) { // and still moving
|
||||
&& ( mvOccupied->Vel > EU07_AI_NOMOVEMENT ) ) { // and still moving
|
||||
cue_action( locale::string::driver_hint_mastercontrollersetzerospeed ); // just throttle down...
|
||||
return; // ...and don't touch any other controls
|
||||
}
|
||||
@@ -7702,15 +7709,18 @@ void TController::control_braking_force() {
|
||||
}
|
||||
|
||||
// odhamowywanie składu po zatrzymaniu i zabezpieczanie lokomotywy
|
||||
if( ( mvOccupied->Vel < 0.01 )
|
||||
if( ( mvOccupied->Vel < EU07_AI_NOMOVEMENT )
|
||||
&& ( ( VelDesired == 0.0 )
|
||||
|| ( AccDesired <= EU07_AI_NOACCELERATION ) ) ) {
|
||||
|
||||
if( ( ( OrderCurrentGet() & ( Disconnect | Connect ) ) == 0 ) // przy (p)odłączaniu nie zwalniamy tu hamulca
|
||||
if( ( ( OrderCurrentGet() & ( Disconnect | Connect | Change_direction ) ) == 0 ) // przy (p)odłączaniu nie zwalniamy tu hamulca
|
||||
&& ( std::abs( fAccGravity ) < 0.01 ) ) { // only do this on flats, on slopes keep applied the train brake
|
||||
// do it only if the vehicle actually has the independent brake
|
||||
apply_independent_brake_only();
|
||||
}
|
||||
// if told to change direction don't confuse human driver with request to leave applied brake in the cab they're about to leave
|
||||
if( ( OrderCurrentGet() & ( Change_direction ) ) != 0 ) {
|
||||
cue_action( locale::string::driver_hint_independentbrakerelease );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7924,7 +7934,7 @@ TController::check_route_behind( double const Range ) {
|
||||
void
|
||||
TController::UpdateBrakingHelper() {
|
||||
|
||||
if (( HelperState > 0 ) && (-AccDesired < fBrake_a0[0] + 2 * fBrake_a1[0]) && (mvOccupied->Vel > 1)) {
|
||||
if (( HelperState > 0 ) && (-AccDesired < fBrake_a0[0] + 2 * fBrake_a1[0]) && (mvOccupied->Vel > EU07_AI_NOMOVEMENT)) {
|
||||
HelperState = 0;
|
||||
}
|
||||
|
||||
|
||||
2
Driver.h
2
Driver.h
@@ -18,6 +18,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "translation.h"
|
||||
|
||||
auto const EU07_AI_NOACCELERATION = -0.05;
|
||||
auto const EU07_AI_NOMOVEMENT = 0.05; // standstill velocity threshold
|
||||
auto const EU07_AI_MOVEMENT = 1.0; // deliberate movement velocity threshold
|
||||
auto const EU07_AI_SPEEDLIMITEXTENDSBEYONDSCANRANGE = 10000.0;
|
||||
|
||||
enum TOrders
|
||||
|
||||
73
DynObj.cpp
73
DynObj.cpp
@@ -249,6 +249,9 @@ bool TDynamicObject::destination_data::deserialize_mapping( cParser &Input ) {
|
||||
else if( key == "parameters:" ) {
|
||||
parameters = Input.getToken<std::string>();
|
||||
}
|
||||
else if( key == "background:" ) {
|
||||
background = Input.getToken<std::string>();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -4648,31 +4651,47 @@ void TDynamicObject::RenderSounds() {
|
||||
}
|
||||
}
|
||||
// attach/detach sounds
|
||||
if( ( coupler.sounds & sound::attachcoupler ) != 0 ) {
|
||||
couplersounds.attach_coupler.play();
|
||||
if( ( coupler.sounds & sound::detach ) == 0 ) {
|
||||
// potentially added some couplings
|
||||
if( ( coupler.sounds & sound::attachcoupler ) != 0 ) {
|
||||
couplersounds.attach_coupler.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachbrakehose ) != 0 ) {
|
||||
couplersounds.attach_brakehose.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachmainhose ) != 0 ) {
|
||||
couplersounds.attach_mainhose.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachcontrol ) != 0 ) {
|
||||
couplersounds.attach_control.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachgangway ) != 0 ) {
|
||||
couplersounds.attach_gangway.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachheating ) != 0 ) {
|
||||
couplersounds.attach_heating.play();
|
||||
}
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachbrakehose ) != 0 ) {
|
||||
couplersounds.attach_brakehose.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachmainhose ) != 0 ) {
|
||||
couplersounds.attach_mainhose.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachcontrol ) != 0 ) {
|
||||
couplersounds.attach_control.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachgangway ) != 0 ) {
|
||||
couplersounds.attach_gangway.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachheating ) != 0 ) {
|
||||
couplersounds.attach_heating.play();
|
||||
}
|
||||
if( true == TestFlag( coupler.sounds, sound::detachall ) ) {
|
||||
couplersounds.detach_coupler.play();
|
||||
couplersounds.detach_brakehose.play();
|
||||
couplersounds.detach_mainhose.play();
|
||||
couplersounds.detach_control.play();
|
||||
couplersounds.detach_gangway.play();
|
||||
couplersounds.detach_heating.play();
|
||||
else {
|
||||
// potentially removed some couplings
|
||||
if( ( coupler.sounds & sound::attachcoupler ) != 0 ) {
|
||||
couplersounds.detach_coupler.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachbrakehose ) != 0 ) {
|
||||
couplersounds.detach_brakehose.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachmainhose ) != 0 ) {
|
||||
couplersounds.detach_mainhose.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachcontrol ) != 0 ) {
|
||||
couplersounds.detach_control.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachgangway ) != 0 ) {
|
||||
couplersounds.detach_gangway.play();
|
||||
}
|
||||
if( ( coupler.sounds & sound::attachheating ) != 0 ) {
|
||||
couplersounds.detach_heating.play();
|
||||
}
|
||||
}
|
||||
if( true == TestFlag( coupler.sounds, sound::attachadapter ) ) {
|
||||
couplersounds.dsbAdapterAttach.play();
|
||||
@@ -5992,12 +6011,15 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
// vehicle faces +Z in 'its' space, for motor locations negative value means ahead of centre
|
||||
auto const offset { std::atof( token.c_str() ) * -1.f };
|
||||
// NOTE: we skip setting owner of the sounds, it'll be done during individual sound deserialization
|
||||
sound_source motor { sound_placement::external }; // generally traction motor
|
||||
sound_source motor { sound_placement::external }; // generic traction motor sounds
|
||||
sound_source acmotor { sound_placement::external }; // inverter-specific traction motor sounds
|
||||
sound_source motorblower { sound_placement::engine }; // associated motor blowers
|
||||
// add entry to the list
|
||||
auto const location { glm::vec3 { 0.f, 0.f, offset } };
|
||||
motor.offset( location );
|
||||
m_powertrainsounds.motors.emplace_back( motor );
|
||||
acmotor.offset( location );
|
||||
m_powertrainsounds.acmotors.emplace_back( acmotor );
|
||||
motorblower.offset( location );
|
||||
m_powertrainsounds.motorblowers.emplace_back( motorblower );
|
||||
}
|
||||
@@ -6344,6 +6366,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
DestinationSign.script = asBaseDir + DestinationSign.script;
|
||||
}
|
||||
}
|
||||
// NOTE: legacy key, now expected as optional "background:" parameter in pydestinationsign: { parameter block }
|
||||
else if( token == "destinationsignbackground:" ) {
|
||||
parser.getTokens();
|
||||
parser >> DestinationSign.background;
|
||||
|
||||
8
Gauge.h
8
Gauge.h
@@ -58,6 +58,14 @@ public:
|
||||
// returns offset of submodel associated with the button from the model centre
|
||||
glm::vec3 model_offset() const;
|
||||
TGaugeType type() const;
|
||||
inline
|
||||
bool is_push() const {
|
||||
return ( static_cast<int>( type() ) & static_cast<int>( TGaugeType::push ) ) != 0; }
|
||||
inline
|
||||
bool is_toggle() const {
|
||||
return ( static_cast<int>( type() ) & static_cast<int>( TGaugeType::toggle ) ) != 0; }
|
||||
bool is_delayed() const {
|
||||
return ( static_cast<int>( type() ) & static_cast<int>( TGaugeType::delayed ) ) != 0; }
|
||||
// members
|
||||
TSubModel *SubModel { nullptr }, // McZapkie-310302: zeby mozna bylo sprawdzac czy zainicjowany poprawnie
|
||||
*SubModelOn { nullptr }; // optional submodel visible when the state input is set
|
||||
|
||||
@@ -174,6 +174,12 @@ global_settings::ConfigParse(cParser &Parser) {
|
||||
Parser >> EnvironmentAmbientVolume;
|
||||
EnvironmentAmbientVolume = clamp(EnvironmentAmbientVolume, 0.f, 1.f);
|
||||
}
|
||||
else if( token == "sound.volume.paused" ) {
|
||||
// selected device for audio renderer
|
||||
Parser.getTokens();
|
||||
Parser >> PausedVolume;
|
||||
EnvironmentAmbientVolume = clamp( EnvironmentAmbientVolume, 0.f, 1.f );
|
||||
}
|
||||
// else if (str==AnsiString("renderalpha")) //McZapkie-1312302 - dwuprzebiegowe renderowanie
|
||||
// bRenderAlpha=(GetNextSymbol().LowerCase()==AnsiString("yes"));
|
||||
else if (token == "physicslog")
|
||||
@@ -1035,6 +1041,7 @@ global_settings::export_as_text( std::ostream &Output ) const {
|
||||
export_as_text( Output, "sound.volume.vehicle", VehicleVolume );
|
||||
export_as_text( Output, "sound.volume.positional", EnvironmentPositionalVolume );
|
||||
export_as_text( Output, "sound.volume.ambient", EnvironmentAmbientVolume );
|
||||
export_as_text( Output, "sound.volume.paused", PausedVolume );
|
||||
export_as_text( Output, "physicslog", WriteLogFlag );
|
||||
export_as_text( Output, "fullphysics", FullPhysics );
|
||||
export_as_text( Output, "debuglog", iWriteLogEnabled );
|
||||
|
||||
@@ -159,6 +159,7 @@ struct global_settings {
|
||||
float VehicleVolume{ 1.0f };
|
||||
float EnvironmentPositionalVolume{ 1.0f };
|
||||
float EnvironmentAmbientVolume{ 1.0f };
|
||||
float PausedVolume { 0.15f };
|
||||
std::string AudioRenderer;
|
||||
// input
|
||||
float fMouseXScale{ 1.5f };
|
||||
|
||||
@@ -243,7 +243,7 @@ enum sound {
|
||||
parallel = 1 << 4,
|
||||
shuntfield = 1 << 5,
|
||||
pneumatic = 1 << 6,
|
||||
detachall = 1 << 7,
|
||||
detach = 1 << 7,
|
||||
attachcoupler = 1 << 8,
|
||||
attachbrakehose = 1 << 9,
|
||||
attachmainhose = 1 << 10,
|
||||
@@ -1168,6 +1168,7 @@ public:
|
||||
bool UniCtrlIntegratedBrakeCtrl = false; /*zintegrowany nastawnik JH obsluguje hamowanie*/
|
||||
bool UniCtrlIntegratedLocalBrakeCtrl = false; /*zintegrowany nastawnik JH obsluguje hamowanie hamulcem pomocniczym*/
|
||||
int UniCtrlNoPowerPos{ 0 }; // cached highesr position not generating traction force
|
||||
std::pair<std::string, std::array<int, 2>> PantsPreset { "", { 0, 0 } }; // pantograph preset switches; .first holds possible setups as chars, .second holds currently selected preset in each cab
|
||||
|
||||
/*-sekcja parametrow dla lokomotywy elektrycznej*/
|
||||
TSchemeTable RList; /*lista rezystorow rozruchowych i polaczen silnikow, dla dizla: napelnienia*/
|
||||
|
||||
@@ -511,23 +511,39 @@ bool TMoverParameters::Dettach(int ConnectNo)
|
||||
|
||||
if( othervehicle == nullptr ) { return true; } // nie ma nic, to odczepiono
|
||||
|
||||
auto const i = DettachStatus(ConnectNo); // stan sprzęgu
|
||||
if (i < 0) {
|
||||
auto couplingchange { coupler.CouplingFlag }; // presume we'll uncouple all active flags
|
||||
auto const couplingstate { DettachStatus( ConnectNo ) }; // stan sprzęgu
|
||||
if (couplingstate < 0) {
|
||||
// gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony)
|
||||
std::tie( coupler.Connected, coupler.ConnectedNr, coupler.CouplingFlag )
|
||||
= std::tie( othercoupler.Connected, othercoupler.ConnectedNr, othercoupler.CouplingFlag )
|
||||
= std::make_tuple( nullptr, -1, coupling::faux );
|
||||
// set sound event flag
|
||||
SetFlag( coupler.sounds, sound::detachall );
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (i > 0)
|
||||
else if (couplingstate > 0)
|
||||
{ // odłączamy węże i resztę, pozostaje sprzęg fizyczny, który wymaga dociśnięcia (z wirtualnym nic)
|
||||
coupler.CouplingFlag &= coupling::coupler;
|
||||
othercoupler.CouplingFlag &= coupling::coupler;
|
||||
}
|
||||
return false; // jeszcze nie rozłączony
|
||||
// set sound event flag
|
||||
couplingchange ^= coupler.CouplingFlag; // remaining bits were removed from coupling
|
||||
if( couplingchange != 0 ) {
|
||||
int soundflag { sound::detach }; // HACK: use detach flag to indicate removal of listed coupling
|
||||
std::vector<std::pair<coupling, sound>> const soundmappings = {
|
||||
{ coupling::coupler, sound::attachcoupler },
|
||||
{ coupling::brakehose, sound::attachbrakehose },
|
||||
{ coupling::mainhose, sound::attachmainhose },
|
||||
{ coupling::control, sound::attachcontrol},
|
||||
{ coupling::gangway, sound::attachgangway},
|
||||
{ coupling::heating, sound::attachheating} };
|
||||
for( auto const &soundmapping : soundmappings ) {
|
||||
if( ( couplingchange & soundmapping.first ) != 0 ) {
|
||||
soundflag |= soundmapping.second;
|
||||
}
|
||||
}
|
||||
SetFlag( coupler.sounds, soundflag );
|
||||
}
|
||||
|
||||
return ( couplingstate < 0 );
|
||||
};
|
||||
|
||||
bool TMoverParameters::DirectionForward()
|
||||
@@ -10800,6 +10816,14 @@ void TMoverParameters::LoadFIZ_Switches( std::string const &Input ) {
|
||||
extract_value( UniversalResetButtonFlag[ 0 ], "RelayResetButton1", Input, "" );
|
||||
extract_value( UniversalResetButtonFlag[ 1 ], "RelayResetButton2", Input, "" );
|
||||
extract_value( UniversalResetButtonFlag[ 2 ], "RelayResetButton3", Input, "" );
|
||||
// pantograph presets
|
||||
{
|
||||
auto &presets { PantsPreset.first };
|
||||
extract_value( presets, "PantographPresets", Input, "0|1|3|2" );
|
||||
presets.erase(
|
||||
std::remove( std::begin( presets ), std::end( presets ), '|' ),
|
||||
std::end( presets ) );
|
||||
}
|
||||
}
|
||||
|
||||
void TMoverParameters::LoadFIZ_MotorParamTable( std::string const &Input ) {
|
||||
|
||||
287
Train.cpp
287
Train.cpp
@@ -31,7 +31,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Console.h"
|
||||
#include "application.h"
|
||||
#include "renderer.h"
|
||||
#include "dictionary.h"
|
||||
/*
|
||||
namespace input {
|
||||
|
||||
@@ -72,6 +71,38 @@ control_mapper::contains( std::string const Control ) const {
|
||||
return ( m_names.find( Control ) != m_names.end() );
|
||||
}
|
||||
|
||||
void TTrain::screen_entry::deserialize( cParser &Input ) {
|
||||
|
||||
while( true == deserialize_mapping( Input ) ) {
|
||||
; // all work done by while()
|
||||
}
|
||||
}
|
||||
|
||||
bool TTrain::screen_entry::deserialize_mapping( cParser &Input ) {
|
||||
// token can be a key or block end
|
||||
auto const key { Input.getToken<std::string>( true, "\n\r\t ,;[]" ) };
|
||||
|
||||
if( ( true == key.empty() ) || ( key == "}" ) ) { return false; }
|
||||
|
||||
if( key == "{" ) {
|
||||
script = Input.getToken<std::string>();
|
||||
}
|
||||
else if( key == "target:" ) {
|
||||
target = Input.getToken<std::string>();
|
||||
}
|
||||
else if( key == "parameters:" ) {
|
||||
parameters = dictionary_source( Input.getToken<std::string>() );
|
||||
}
|
||||
else {
|
||||
// HACK: we expect this to be true only if the screen entry doesn't start with a { which means legacy configuration format
|
||||
target = key;
|
||||
script = Input.getToken<std::string>();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TCab::Load(cParser &Parser)
|
||||
{
|
||||
// NOTE: clearing control tables here is bit of a crutch, imposed by current scheme of loading compartments anew on each cab change
|
||||
@@ -537,12 +568,12 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
||||
return true;
|
||||
}
|
||||
|
||||
dictionary_source *TTrain::GetTrainState() {
|
||||
dictionary_source *TTrain::GetTrainState( dictionary_source const &Extraparameters ) {
|
||||
|
||||
if( ( mvOccupied == nullptr )
|
||||
|| ( mvControlled == nullptr ) ) { return nullptr; }
|
||||
|
||||
auto *dict { new dictionary_source };
|
||||
auto *dict { new dictionary_source( Extraparameters ) };
|
||||
if( dict == nullptr ) { return nullptr; }
|
||||
|
||||
dict->insert( "name", DynamicObject->asName );
|
||||
@@ -612,6 +643,7 @@ dictionary_source *TTrain::GetTrainState() {
|
||||
dict->insert( "distance_counter", m_distancecounter );
|
||||
dict->insert( "pantpress", std::abs( mvPantographUnit->PantPress ) );
|
||||
dict->insert( "universal3", InstrumentLightActive );
|
||||
dict->insert( "radio", mvOccupied->Radio );
|
||||
dict->insert( "radio_channel", RadioChannel() );
|
||||
dict->insert( "radio_volume", Global.RadioVolume );
|
||||
dict->insert( "door_lock", mvOccupied->Doors.lock_enabled );
|
||||
@@ -621,6 +653,7 @@ dictionary_source *TTrain::GetTrainState() {
|
||||
dict->insert( "tractionforce", std::abs( mvOccupied->Ft ) );
|
||||
dict->insert( "slipping_wheels", mvOccupied->SlippingWheels );
|
||||
dict->insert( "sanding", mvOccupied->SandDose );
|
||||
dict->insert( "odometer", mvOccupied->DistCounter );
|
||||
// electric current data
|
||||
dict->insert( "traction_voltage", std::abs( mvPantographUnit->PantographVoltage ) );
|
||||
dict->insert( "voltage", std::abs( mvControlled->EngineVoltage ) );
|
||||
@@ -1122,18 +1155,30 @@ void TTrain::OnCommand_tempomattoggle( TTrain *Train, command_data const &Comman
|
||||
if( Train->ggScndCtrlButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
if( Command.action == GLFW_RELEASE ) {
|
||||
// just move the button back to default position
|
||||
// just move the button(s) back to default position
|
||||
// visual feedback
|
||||
Train->ggScndCtrlButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
Train->ggScndCtrlOffButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
return;
|
||||
}
|
||||
// glfw_press
|
||||
if( Train->mvControlled->ScndCtrlPos == 0 ) {
|
||||
// turn on if needed
|
||||
// turn on if it's not active
|
||||
Train->mvControlled->IncScndCtrl( 1 );
|
||||
// visual feedback
|
||||
Train->ggScndCtrlButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
else {
|
||||
// otherwise turn off
|
||||
Train->mvControlled->DecScndCtrl( 2 );
|
||||
// visual feedback
|
||||
if( Train->m_controlmapper.contains( "tempomatoff_sw:" ) ) {
|
||||
Train->ggScndCtrlOffButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
else {
|
||||
Train->ggScndCtrlButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
}
|
||||
// visual feedback
|
||||
Train->ggScndCtrlButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
else {
|
||||
// two-state switch
|
||||
@@ -2194,7 +2239,7 @@ void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Comman
|
||||
void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
// HACK: presence of pantograph selector prevents manual operation of the individual valves
|
||||
if( Train->ggPantSelectButton.SubModel ) { return; }
|
||||
if( Train->m_controlmapper.contains( "pantselect_sw:" ) ) { return; }
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
||||
@@ -2226,7 +2271,7 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
|
||||
void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
// HACK: presence of pantograph selector prevents manual operation of the individual valves
|
||||
if( Train->ggPantSelectButton.SubModel ) { return; }
|
||||
if( Train->m_controlmapper.contains( "pantselect_sw:" ) ) { return; }
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
||||
@@ -2258,7 +2303,7 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
|
||||
void TTrain::OnCommand_pantographraisefront( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
// HACK: presence of pantograph selector prevents manual operation of the individual valves
|
||||
if( Train->ggPantSelectButton.SubModel ) { return; }
|
||||
if( Train->m_controlmapper.contains( "pantselect_sw:" ) ) { return; }
|
||||
// prevent operation without submodel outside of engine compartment
|
||||
if( ( Train->iCabn != 0 )
|
||||
&& ( false == Train->m_controlmapper.contains( "pantfront_sw:" ) ) ) { return; }
|
||||
@@ -2285,7 +2330,7 @@ void TTrain::OnCommand_pantographraisefront( TTrain *Train, command_data const &
|
||||
void TTrain::OnCommand_pantographraiserear( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
// HACK: presence of pantograph selector prevents manual operation of the individual valves
|
||||
if( Train->ggPantSelectButton.SubModel ) { return; }
|
||||
if( Train->m_controlmapper.contains( "pantselect_sw:" ) ) { return; }
|
||||
// prevent operation without submodel outside of engine compartment
|
||||
if( ( Train->iCabn != 0 )
|
||||
&& ( false == Train->m_controlmapper.contains( "pantrear_sw:" ) ) ) { return; }
|
||||
@@ -2312,7 +2357,7 @@ void TTrain::OnCommand_pantographraiserear( TTrain *Train, command_data const &C
|
||||
void TTrain::OnCommand_pantographlowerfront( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
// HACK: presence of pantograph selector prevents manual operation of the individual valves
|
||||
if( Train->ggPantSelectButton.SubModel ) { return; }
|
||||
if( Train->m_controlmapper.contains( "pantselect_sw:" ) ) { return; }
|
||||
// prevent operation without submodel outside of engine compartment
|
||||
if( ( Train->iCabn != 0 )
|
||||
&& ( false == Train->m_controlmapper.contains(
|
||||
@@ -2344,7 +2389,8 @@ void TTrain::OnCommand_pantographlowerfront( TTrain *Train, command_data const &
|
||||
void TTrain::OnCommand_pantographlowerrear( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
// HACK: presence of pantograph selector prevents manual operation of the individual valves
|
||||
if( Train->ggPantSelectButton.SubModel ) { return; }
|
||||
if( Train->m_controlmapper.contains( "pantselect_sw:" ) ) { return; }
|
||||
|
||||
if( ( Train->iCabn != 0 )
|
||||
&& ( false == Train->m_controlmapper.contains(
|
||||
Train->mvOccupied->PantSwitchType == "impulse" ?
|
||||
@@ -2404,7 +2450,7 @@ void TTrain::OnCommand_pantographselectnext( TTrain *Train, command_data const &
|
||||
|
||||
if( Command.action != GLFW_PRESS ) { return; }
|
||||
|
||||
if( Train->ggPantSelectButton.SubModel == nullptr ) { return; }
|
||||
if( false == Train->m_controlmapper.contains( "pantselect_sw:" ) ) { return; }
|
||||
|
||||
Train->change_pantograph_selection( 1 );
|
||||
}
|
||||
@@ -2413,7 +2459,7 @@ void TTrain::OnCommand_pantographselectprevious( TTrain *Train, command_data con
|
||||
|
||||
if( Command.action != GLFW_PRESS ) { return; }
|
||||
|
||||
if( Train->ggPantSelectButton.SubModel == nullptr ) { return; }
|
||||
if( false == Train->m_controlmapper.contains( "pantselect_sw:" ) ) { return; }
|
||||
|
||||
Train->change_pantograph_selection( -1 );
|
||||
}
|
||||
@@ -2508,19 +2554,19 @@ void TTrain::OnCommand_pantographlowerselected( TTrain *Train, command_data cons
|
||||
|
||||
void TTrain::change_pantograph_selection( int const Change ) {
|
||||
|
||||
auto const initialstate { m_pantselection };
|
||||
auto const &presets { mvOccupied->PantsPreset.first };
|
||||
auto &selection { mvOccupied->PantsPreset.second[ cab_to_end() ] };
|
||||
auto const initialstate { selection };
|
||||
selection = clamp<int>( selection + Change, 0, std::max<int>( presets.size() - 1, 0 ) );
|
||||
|
||||
m_pantselection = clamp( m_pantselection + Change, 0, 3 );
|
||||
// visual feedback
|
||||
ggPantSelectButton.UpdateValue( m_pantselection );
|
||||
|
||||
if( m_pantselection == initialstate ) { return; } // no change, nothing to do
|
||||
if( selection == initialstate ) { return; } // no change, nothing to do
|
||||
|
||||
// configure pantograph valves matching the new state
|
||||
auto const preset { presets[ selection ] - '0' };
|
||||
auto const swapends { cab_to_end() != end::front };
|
||||
// check desired states for both pantographs; value: whether the pantograph should be raised
|
||||
auto const frontstate{ ( m_pantselection == 2 ) || ( m_pantselection == ( swapends ? 1 : 3 ) ) };
|
||||
auto const rearstate{ ( m_pantselection == 2 ) || ( m_pantselection == ( swapends ? 3 : 1 ) ) };
|
||||
auto const frontstate { preset & ( swapends ? 1 : 2 ) };
|
||||
auto const rearstate { preset & ( swapends ? 2 : 1 ) };
|
||||
// potentially adjust pantograph valves
|
||||
mvOccupied->OperatePantographValve( end::front, ( frontstate ? operation_t::enable : operation_t::disable ) );
|
||||
mvOccupied->OperatePantographValve( end::rear, ( rearstate ? operation_t::enable : operation_t::disable ) );
|
||||
@@ -5503,9 +5549,27 @@ void TTrain::OnCommand_doorcloseall( TTrain *Train, command_data const &Command
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
// TODO: move logic/visualization code to the gauge, on_command() should return hint whether it should invoke a reaction
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
Train->mvOccupied->PermitDoorStep( false == Train->mvOccupied->Doors.step_enabled );
|
||||
// effect
|
||||
if( false == Train->ggDoorStepButton.is_delayed() ) {
|
||||
Train->mvOccupied->PermitDoorStep( false == Train->mvOccupied->Doors.step_enabled );
|
||||
}
|
||||
// visual feedback
|
||||
auto const isactive { (
|
||||
Train->ggDoorStepButton.is_push() // always press push button
|
||||
|| Train->mvOccupied->Doors.step_enabled ) }; // for toggle buttons indicate item state
|
||||
Train->ggDoorStepButton.UpdateValue( isactive ? 1 : 0 );
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
// effect
|
||||
if( Train->ggDoorStepButton.is_delayed() ) {
|
||||
Train->mvOccupied->PermitDoorStep( false == Train->mvOccupied->Doors.step_enabled );
|
||||
}
|
||||
// visual feedback
|
||||
if( Train->ggDoorStepButton.is_push() ) {
|
||||
Train->ggDoorStepButton.UpdateValue( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6964,6 +7028,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
ggScndCtrl.Update();
|
||||
}
|
||||
ggScndCtrlButton.Update( lowvoltagepower );
|
||||
ggScndCtrlOffButton.Update( lowvoltagepower );
|
||||
ggDistanceCounterButton.Update();
|
||||
if (ggDirKey.SubModel) {
|
||||
if (mvControlled->TrainType != dt_EZT)
|
||||
@@ -7047,16 +7112,17 @@ bool TTrain::Update( double const Deltatime )
|
||||
// NBMX wrzesien 2003 - drzwi
|
||||
ggDoorLeftPermitButton.Update( lowvoltagepower );
|
||||
ggDoorRightPermitButton.Update( lowvoltagepower );
|
||||
ggDoorPermitPresetButton.Update();
|
||||
ggDoorLeftButton.Update();
|
||||
ggDoorRightButton.Update();
|
||||
ggDoorLeftOnButton.Update();
|
||||
ggDoorRightOnButton.Update();
|
||||
ggDoorLeftOffButton.Update();
|
||||
ggDoorRightOffButton.Update();
|
||||
ggDoorAllOnButton.Update();
|
||||
ggDoorPermitPresetButton.Update( lowvoltagepower );
|
||||
ggDoorLeftButton.Update( lowvoltagepower );
|
||||
ggDoorRightButton.Update( lowvoltagepower );
|
||||
ggDoorLeftOnButton.Update( lowvoltagepower );
|
||||
ggDoorRightOnButton.Update( lowvoltagepower );
|
||||
ggDoorLeftOffButton.Update( lowvoltagepower );
|
||||
ggDoorRightOffButton.Update( lowvoltagepower );
|
||||
ggDoorAllOnButton.Update( lowvoltagepower );
|
||||
ggDoorAllOffButton.Update( lowvoltagepower );
|
||||
ggDoorSignallingButton.Update();
|
||||
ggDoorSignallingButton.Update( lowvoltagepower );
|
||||
ggDoorStepButton.Update( lowvoltagepower );
|
||||
// NBMX dzwignia sprezarki
|
||||
ggCompressorButton.Update();
|
||||
ggCompressorLocalButton.Update();
|
||||
@@ -7125,7 +7191,6 @@ bool TTrain::Update( double const Deltatime )
|
||||
ggPantAllDownButton.Update();
|
||||
ggPantSelectedDownButton.Update();
|
||||
ggPantSelectedButton.Update();
|
||||
ggPantSelectButton.Update();
|
||||
ggPantCompressorButton.Update();
|
||||
ggPantCompressorValve.Update();
|
||||
|
||||
@@ -7237,13 +7302,13 @@ bool TTrain::Update( double const Deltatime )
|
||||
&& ( fScreenTimer > std::max( fScreenUpdateRate, Global.PythonScreenUpdateRate ) * 0.001f )
|
||||
&& ( false == FreeFlyModeFlag ) ) { // don't bother if we're outside
|
||||
fScreenTimer = 0.f;
|
||||
for( auto const &screen : m_screens ) {
|
||||
auto state_dict = GetTrainState();
|
||||
for( auto &screen : m_screens ) {
|
||||
auto *state_dict = GetTrainState( screen.parameters );
|
||||
/*
|
||||
state_dict->insert("touches", *screen.touch_list);
|
||||
screen.touch_list->clear();
|
||||
*/
|
||||
Application.request({ screen.rendererpath, state_dict, screen.rt } );
|
||||
Application.request( { screen.script, state_dict, screen.rt } );
|
||||
}
|
||||
}
|
||||
// sounds
|
||||
@@ -8038,60 +8103,62 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
||||
// TODO: add "pydestination:"
|
||||
else if (token == "pyscreen:")
|
||||
{
|
||||
std::string submodelname, renderername;
|
||||
parser.getTokens( 2 );
|
||||
parser
|
||||
>> submodelname
|
||||
>> renderername;
|
||||
screen_entry screen;
|
||||
screen.deserialize(parser);
|
||||
if ((false == screen.script.empty()) && (substr_path(screen.script).empty()))
|
||||
{
|
||||
screen.script = DynamicObject->asBaseDir + screen.script;
|
||||
}
|
||||
|
||||
const std::string rendererpath {
|
||||
substr_path(renderername).empty() ? // supply vehicle folder as path if none is provided
|
||||
DynamicObject->asBaseDir + renderername :
|
||||
renderername };
|
||||
|
||||
opengl_texture *tex = nullptr;
|
||||
opengl_texture *tex = nullptr;
|
||||
TSubModel *submodel = nullptr;
|
||||
if (submodelname != "none") {
|
||||
submodel = (
|
||||
DynamicObject->mdKabina ? DynamicObject->mdKabina->GetFromName( submodelname ) :
|
||||
DynamicObject->mdLowPolyInt ? DynamicObject->mdLowPolyInt->GetFromName( submodelname ) :
|
||||
nullptr );
|
||||
if( submodel == nullptr ) {
|
||||
WriteLog( "Python Screen: submodel " + submodelname + " not found - Ignoring screen" );
|
||||
continue;
|
||||
}
|
||||
auto const material { submodel->GetMaterial() };
|
||||
if( material <= 0 ) {
|
||||
// sub model nie posiada tekstury lub tekstura wymienna - nie obslugiwana
|
||||
WriteLog( "Python Screen: invalid texture id " + std::to_string( material ) + " - Ignoring screen" );
|
||||
continue;
|
||||
}
|
||||
if (screen.target != "none")
|
||||
{
|
||||
submodel = (DynamicObject->mdKabina ?
|
||||
DynamicObject->mdKabina->GetFromName(screen.target) :
|
||||
DynamicObject->mdLowPolyInt ?
|
||||
DynamicObject->mdLowPolyInt->GetFromName(screen.target) :
|
||||
nullptr);
|
||||
if (submodel == nullptr)
|
||||
{
|
||||
WriteLog("Python Screen: submodel " + screen.target +
|
||||
" not found - Ignoring screen");
|
||||
continue;
|
||||
}
|
||||
auto const material{submodel->GetMaterial()};
|
||||
if (material <= 0)
|
||||
{
|
||||
// sub model nie posiada tekstury lub tekstura wymienna - nie obslugiwana
|
||||
WriteLog("Python Screen: invalid texture id " + std::to_string(material) +
|
||||
" - Ignoring screen");
|
||||
continue;
|
||||
}
|
||||
|
||||
tex = &GfxRenderer->Texture(GfxRenderer->Material(material).textures[0]);
|
||||
}
|
||||
else {
|
||||
// TODO: fix leak
|
||||
tex = new opengl_texture();
|
||||
tex->make_stub();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: fix leak
|
||||
tex = new opengl_texture();
|
||||
tex->make_stub();
|
||||
}
|
||||
|
||||
tex->create( true ); // make the surface static so it doesn't get destroyed by garbage collector if the user spends long time outside cab
|
||||
// TBD, TODO: keep texture handles around, so we can undo the static switch when the user changes cabs?
|
||||
tex->create(true); // make the surface static so it doesn't get destroyed by garbage
|
||||
// collector if the user spends long time outside cab
|
||||
// TBD, TODO: keep texture handles around, so we can undo the static switch when the
|
||||
// user changes cabs?
|
||||
auto rt = std::make_shared<python_rt>();
|
||||
rt->shared_tex = tex->id;
|
||||
|
||||
auto touch_list = std::make_shared<std::vector<glm::vec2>>();
|
||||
auto rt = std::make_shared<python_rt>();
|
||||
rt->shared_tex = tex->id;
|
||||
/*
|
||||
if (submodel)
|
||||
submodel->screen_touch_list = touch_list;
|
||||
*/
|
||||
// record renderer and material binding for future update requests
|
||||
m_screens.emplace_back();
|
||||
m_screens.back().rendererpath = rendererpath;
|
||||
m_screens.emplace_back(screen);
|
||||
m_screens.back().rt = rt;
|
||||
/*
|
||||
m_screens.back().touch_list = touch_list;
|
||||
|
||||
m_screens.back().touch_list = std::make_shared<std::vector<glm::vec2>>();
|
||||
if (submodel) // guaranteed at this point
|
||||
submodel->screen_touch_list = m_screens.back().touch_list;
|
||||
*/
|
||||
/*
|
||||
if (Global.python_displaywindows)
|
||||
m_screens.back().viewer = std::make_unique<python_screen_viewer>(rt, touch_list, rendererpath);
|
||||
*/
|
||||
@@ -8280,8 +8347,14 @@ TTrain::MoveToVehicle(TDynamicObject *target) {
|
||||
target_train->Occupied()->LimPipePress = target_train->Occupied()->PipePress;
|
||||
target_train->Occupied()->CabActivisation( true ); // załączenie rozrządu (wirtualne kabiny)
|
||||
target_train->Dynamic()->MechInside = true;
|
||||
target_train->Dynamic()->Controller = ( target_train->Dynamic()->Mechanik ? !target_train->Dynamic()->Mechanik->AIControllFlag : Humandriver );
|
||||
} else {
|
||||
if( target_train->Dynamic()->Mechanik ) {
|
||||
target_train->Dynamic()->Controller = target_train->Dynamic()->Mechanik->AIControllFlag;
|
||||
target_train->Dynamic()->Mechanik->DirectionChange();
|
||||
}
|
||||
else {
|
||||
target_train->Dynamic()->Controller = Humandriver;
|
||||
}
|
||||
} else {
|
||||
target_train->Dynamic()->bDisplayCab = false;
|
||||
target_train->Dynamic()->ABuSetModelShake( {} );
|
||||
}
|
||||
@@ -8327,7 +8400,13 @@ TTrain::MoveToVehicle(TDynamicObject *target) {
|
||||
Occupied()->LimPipePress = Occupied()->PipePress;
|
||||
Occupied()->CabActivisation( true ); // załączenie rozrządu (wirtualne kabiny)
|
||||
Dynamic()->MechInside = true;
|
||||
Dynamic()->Controller = ( Dynamic()->Mechanik ? Dynamic()->Mechanik->AIControllFlag : Humandriver );
|
||||
if( Dynamic()->Mechanik ) {
|
||||
Dynamic()->Controller = Dynamic()->Mechanik->AIControllFlag;
|
||||
Dynamic()->Mechanik->DirectionChange();
|
||||
}
|
||||
else {
|
||||
Dynamic()->Controller = Humandriver;
|
||||
}
|
||||
} else {
|
||||
Dynamic()->bDisplayCab = false;
|
||||
Dynamic()->ABuSetModelShake( {} );
|
||||
@@ -8429,6 +8508,7 @@ void TTrain::clear_cab_controls()
|
||||
ggMainCtrlAct.Clear();
|
||||
ggScndCtrl.Clear();
|
||||
ggScndCtrlButton.Clear();
|
||||
ggScndCtrlOffButton.Clear();
|
||||
ggDistanceCounterButton.Clear();
|
||||
ggDirKey.Clear();
|
||||
ggDirForwardButton.Clear();
|
||||
@@ -8512,6 +8592,7 @@ void TTrain::clear_cab_controls()
|
||||
ggTrainHeatingButton.Clear();
|
||||
ggSignallingButton.Clear();
|
||||
ggDoorSignallingButton.Clear();
|
||||
ggDoorStepButton.Clear();
|
||||
ggDepartureSignalButton.Clear();
|
||||
ggCompressorButton.Clear();
|
||||
ggCompressorLocalButton.Clear();
|
||||
@@ -8528,7 +8609,6 @@ void TTrain::clear_cab_controls()
|
||||
ggPantAllDownButton.Clear();
|
||||
ggPantSelectedButton.Clear();
|
||||
ggPantSelectedDownButton.Clear();
|
||||
ggPantSelectButton.Clear();
|
||||
ggPantCompressorButton.Clear();
|
||||
ggPantCompressorValve.Clear();
|
||||
ggI1B.Clear();
|
||||
@@ -8705,13 +8785,6 @@ void TTrain::set_cab_controls( int const Cab ) {
|
||||
}
|
||||
*/
|
||||
// front/end pantograph selection is relative to occupied cab
|
||||
m_pantselection = (
|
||||
m_pantselection == 1 ? ( cab_to_end( Cab ) == cab_to_end() ? 1 : 3 ) :
|
||||
m_pantselection == 3 ? ( cab_to_end( Cab ) == cab_to_end() ? 3 : 1 ) :
|
||||
m_pantselection ); // other settings affect both pantographs
|
||||
if( ggPantSelectButton.SubModel ) {
|
||||
ggPantSelectButton.PutValue( m_pantselection );
|
||||
}
|
||||
if( ggPantSelectedButton.type() == TGaugeType::toggle ) {
|
||||
ggPantSelectedButton.PutValue(
|
||||
( mvPantographUnit->PantsValve.is_enabled ?
|
||||
@@ -8825,10 +8898,10 @@ void TTrain::set_cab_controls( int const Cab ) {
|
||||
1.f :
|
||||
0.f ) );
|
||||
// doors permits
|
||||
if( ggDoorLeftPermitButton.type() != TGaugeType::push ) {
|
||||
if( false == ggDoorLeftPermitButton.is_push() ) {
|
||||
ggDoorLeftPermitButton.PutValue( mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::left : side::right ) ].open_permit ? 1.f : 0.f );
|
||||
}
|
||||
if( ggDoorRightPermitButton.type() != TGaugeType::push ) {
|
||||
if( false == ggDoorRightPermitButton.is_push() ) {
|
||||
ggDoorRightPermitButton.PutValue( mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::right : side::left ) ].open_permit ? 1.f : 0.f );
|
||||
}
|
||||
ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset );
|
||||
@@ -8840,8 +8913,15 @@ void TTrain::set_cab_controls( int const Cab ) {
|
||||
mvOccupied->Doors.lock_enabled ?
|
||||
1.f :
|
||||
0.f );
|
||||
// door step
|
||||
if( false == ggDoorStepButton.is_push() ) {
|
||||
ggDoorStepButton.PutValue(
|
||||
mvOccupied->Doors.step_enabled ?
|
||||
1.f :
|
||||
0.f );
|
||||
}
|
||||
// heating
|
||||
if( ggTrainHeatingButton.type() != TGaugeType::push ) {
|
||||
if( false == ggTrainHeatingButton.is_push() ) {
|
||||
ggTrainHeatingButton.PutValue(
|
||||
mvControlled->Heating ?
|
||||
1.f :
|
||||
@@ -8946,7 +9026,7 @@ void TTrain::set_cab_controls( int const Cab ) {
|
||||
0.f );
|
||||
}
|
||||
// tempomat
|
||||
if( ggScndCtrlButton.type() != TGaugeType::push ) {
|
||||
if( false == ggScndCtrlButton.is_push() ) {
|
||||
ggScndCtrlButton.PutValue(
|
||||
( mvControlled->ScndCtrlPos > 0 ) ?
|
||||
1.f :
|
||||
@@ -9225,7 +9305,6 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
||||
{ "pantalloff_sw:", ggPantAllDownButton },
|
||||
{ "pantselected_sw:", ggPantSelectedButton },
|
||||
{ "pantselectedoff_sw:", ggPantSelectedDownButton },
|
||||
{ "pantselect_sw:", ggPantSelectButton },
|
||||
{ "pantcompressor_sw:", ggPantCompressorButton },
|
||||
{ "pantcompressorvalve_sw:", ggPantCompressorValve },
|
||||
{ "trainheating_sw:", ggTrainHeatingButton },
|
||||
@@ -9265,9 +9344,12 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// TODO: move viable gauges to the state driven array
|
||||
// dedicated gauges with state-driven optional submodel
|
||||
// TODO: move viable gauges here
|
||||
// TODO: convert dedicated gauges to auto-allocated ones, replace dedicated references in command handlers to mapper lookups
|
||||
std::unordered_map<std::string, std::tuple<TGauge &, bool const *> > const stategauges = {
|
||||
{ "tempomat_sw:", { ggScndCtrlButton, &mvOccupied->SpeedCtrlUnit.IsActive } },
|
||||
{ "tempomatoff_sw:", { ggScndCtrlOffButton, &mvOccupied->SpeedCtrlUnit.IsActive } },
|
||||
{ "speedinc_bt:", { ggSpeedControlIncreaseButton, &mvOccupied->SpeedCtrlUnit.IsActive } },
|
||||
{ "speeddec_bt:", { ggSpeedControlDecreaseButton, &mvOccupied->SpeedCtrlUnit.IsActive } },
|
||||
{ "speedctrlpowerinc_bt:", { ggSpeedControlPowerIncreaseButton, &mvOccupied->SpeedCtrlUnit.IsActive } },
|
||||
@@ -9285,7 +9367,8 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
||||
{ "doorleftpermit_sw:", { ggDoorLeftPermitButton, &mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::left : side::right ) ].open_permit } },
|
||||
{ "doorrightpermit_sw:", { ggDoorRightPermitButton, &mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::right : side::left ) ].open_permit } },
|
||||
{ "dooralloff_sw:", { ggDoorAllOffButton, &m_doors } },
|
||||
{ "dirforward_bt:", { ggDirForwardButton, &m_dirforward } },
|
||||
{ "doorstep_sw:", { ggDoorStepButton, &mvOccupied->Doors.step_enabled } },
|
||||
{ "dirforward_bt:", { ggDirForwardButton, &m_dirforward } },
|
||||
{ "dirneutral_bt:", { ggDirNeutralButton, &m_dirneutral } },
|
||||
{ "dirbackward_bt:", { ggDirBackwardButton, &m_dirbackward } },
|
||||
};
|
||||
@@ -9302,7 +9385,6 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
||||
// TODO: move viable dedicated gauges to the automatic array
|
||||
std::unordered_map<std::string, bool *> const autoboolgauges = {
|
||||
{ "doormode_sw:", &mvOccupied->Doors.remote_only },
|
||||
{ "doorstep_sw:", &mvOccupied->Doors.step_enabled },
|
||||
{ "coolingfans_sw:", &mvControlled->RVentForceOn },
|
||||
{ "pantfront_sw:", &mvPantographUnit->Pantographs[end::front].valve.is_enabled },
|
||||
{ "pantrear_sw:", &mvPantographUnit->Pantographs[end::rear].valve.is_enabled },
|
||||
@@ -9326,6 +9408,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
||||
// TODO: move viable dedicated gauges to the automatic array
|
||||
std::unordered_map<std::string, int *> const autointgauges = {
|
||||
{ "manualbrake:", &mvOccupied->ManualBrakePos },
|
||||
{ "pantselect_sw:", &mvOccupied->PantsPreset.second[cab_to_end()] },
|
||||
};
|
||||
{
|
||||
auto lookup = autointgauges.find( Label );
|
||||
|
||||
32
Train.h
32
Train.h
@@ -17,6 +17,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "sound.h"
|
||||
#include "PyInt.h"
|
||||
#include "command.h"
|
||||
#include "dictionary.h"
|
||||
|
||||
#undef snprintf // pyint.h->python
|
||||
|
||||
@@ -113,15 +114,21 @@ class TTrain {
|
||||
};
|
||||
|
||||
struct screen_entry {
|
||||
std::string rendererpath;
|
||||
|
||||
std::string script;
|
||||
std::string target;
|
||||
std::shared_ptr<python_rt> rt;
|
||||
/*
|
||||
std::unique_ptr<python_screen_viewer> viewer;
|
||||
std::shared_ptr<std::vector<glm::vec2>> touch_list;
|
||||
*/
|
||||
dictionary_source parameters; // cached pre-processed optional per-screen parameters
|
||||
|
||||
void deserialize( cParser &Input );
|
||||
bool deserialize_mapping( cParser &Input );
|
||||
};
|
||||
|
||||
typedef std::vector<screen_entry> screen_map;
|
||||
typedef std::vector<screen_entry> screenentry_sequence;
|
||||
|
||||
// constructors
|
||||
TTrain();
|
||||
@@ -132,16 +139,23 @@ class TTrain {
|
||||
// McZapkie-010302
|
||||
bool Init(TDynamicObject *NewDynamicObject, bool e3d = false);
|
||||
|
||||
inline Math3D::vector3 GetDirection() { return DynamicObject->VectorFront(); };
|
||||
inline Math3D::vector3 GetUp() { return DynamicObject->VectorUp(); };
|
||||
inline std::string GetLabel( TSubModel const *Control ) const { return m_controlmapper.find( Control ); }
|
||||
inline
|
||||
Math3D::vector3 GetDirection() const {
|
||||
return DynamicObject->VectorFront(); };
|
||||
inline
|
||||
Math3D::vector3 GetUp() const {
|
||||
return DynamicObject->VectorUp(); };
|
||||
inline
|
||||
std::string GetLabel( TSubModel const *Control ) const {
|
||||
return m_controlmapper.find( Control ); }
|
||||
void UpdateCab();
|
||||
bool Update( double const Deltatime );
|
||||
void add_distance( double const Distance );
|
||||
// McZapkie-310302: ladowanie parametrow z pliku
|
||||
bool LoadMMediaFile(std::string const &asFileName);
|
||||
dictionary_source *GetTrainState();
|
||||
dictionary_source *GetTrainState( dictionary_source const &Extraparameters );
|
||||
state_t get_state() const;
|
||||
// basic_table interface
|
||||
inline
|
||||
std::string name() const {
|
||||
return Dynamic()->name(); }
|
||||
@@ -464,6 +478,7 @@ public: // reszta może by?publiczna
|
||||
TGauge ggMainCtrlAct;
|
||||
TGauge ggScndCtrl;
|
||||
TGauge ggScndCtrlButton;
|
||||
TGauge ggScndCtrlOffButton;
|
||||
TGauge ggDirKey;
|
||||
TGauge ggDirForwardButton;
|
||||
TGauge ggDirNeutralButton;
|
||||
@@ -572,6 +587,7 @@ public: // reszta może by?publiczna
|
||||
TGauge ggDoorAllOnButton;
|
||||
TGauge ggDoorAllOffButton;
|
||||
TGauge ggDepartureSignalButton;
|
||||
TGauge ggDoorStepButton;
|
||||
|
||||
// Winger 160204 - obsluga pantografow - ZROBIC
|
||||
/*
|
||||
@@ -583,7 +599,6 @@ public: // reszta może by?publiczna
|
||||
TGauge ggPantAllDownButton;
|
||||
TGauge ggPantSelectedButton;
|
||||
TGauge ggPantSelectedDownButton;
|
||||
TGauge ggPantSelectButton;
|
||||
TGauge ggPantCompressorButton;
|
||||
TGauge ggPantCompressorValve;
|
||||
// Winger 020304 - wlacznik ogrzewania
|
||||
@@ -790,11 +805,10 @@ private:
|
||||
float fPPress, fNPress;
|
||||
bool m_mastercontrollerinuse { false };
|
||||
float m_mastercontrollerreturndelay { 0.f };
|
||||
screen_map m_screens;
|
||||
screenentry_sequence m_screens;
|
||||
uint16_t vid { 0 }; // train network recipient id
|
||||
float m_distancecounter { -1.f }; // distance traveled since meter was activated or -1 if inactive
|
||||
double m_brakehandlecp{ 0.0 };
|
||||
int m_pantselection{ 0 };
|
||||
bool m_doors{ false }; // helper, true if any door is open
|
||||
bool m_dirforward{ false }; // helper, true if direction set to forward
|
||||
bool m_dirneutral{ false }; // helper, true if direction set to neutral
|
||||
|
||||
@@ -335,7 +335,7 @@ void
|
||||
openal_renderer::update( double const Deltatime ) {
|
||||
// update listener
|
||||
// gain
|
||||
::alListenerf( AL_GAIN, clamp( Global.AudioVolume, 0.f, 2.f ) * ( Global.iPause == 0 ? 1.f : 0.15f ) );
|
||||
::alListenerf( AL_GAIN, clamp( Global.AudioVolume, 0.f, 2.f ) * ( Global.iPause == 0 ? 1.f : Global.PausedVolume ) );
|
||||
// orientation
|
||||
glm::dmat4 cameramatrix;
|
||||
Global.pCamera.SetMatrix( cameramatrix );
|
||||
|
||||
@@ -279,7 +279,7 @@ scenario_panel::render() {
|
||||
// hints
|
||||
if( owner != nullptr ) {
|
||||
auto const hintheader{ locale::strings[ locale::string::driver_hint_header ] };
|
||||
if( true == ImGui::CollapsingHeader( hintheader.c_str() ) ) {
|
||||
if( true == ImGui::CollapsingHeader( hintheader.c_str(), ImGuiTreeNodeFlags_DefaultOpen ) ) {
|
||||
for( auto const &hint : owner->m_hints ) {
|
||||
auto const isdone { std::get<TController::hintpredicate>( hint )( std::get<float>( hint ) ) };
|
||||
auto const hintcolor{ (
|
||||
@@ -1254,14 +1254,15 @@ debug_panel::update_section_eventqueue( std::vector<text_line> &Output ) {
|
||||
&& ( ( false == m_eventqueueactivevehicleonly )
|
||||
|| ( event->m_activator == m_input.vehicle ) ) ) {
|
||||
|
||||
auto const label { event->m_name + ( event->m_activator ? " (by: " + event->m_activator->asName + ")" : "" ) };
|
||||
|
||||
if( ( false == searchfilter.empty() )
|
||||
&& ( event->m_name.find( searchfilter ) == std::string::npos ) ) {
|
||||
&& ( label.find( searchfilter ) == std::string::npos ) ) {
|
||||
event = event->m_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const delay { " " + to_string( std::max( 0.0, event->m_launchtime - time ), 1 ) };
|
||||
auto const label { event->m_name + ( event->m_activator ? " (by: " + event->m_activator->asName + ")" : "" ) };
|
||||
textline =
|
||||
delay.substr( delay.length() - 6 )
|
||||
+ " "
|
||||
|
||||
@@ -64,7 +64,8 @@ class debug_panel : public ui_panel {
|
||||
|
||||
public:
|
||||
debug_panel( std::string const &Name, bool const Isopen )
|
||||
: ui_panel( Name, Isopen ) {}
|
||||
: ui_panel( Name, Isopen ) {
|
||||
m_eventsearch.fill( 0 ); }
|
||||
|
||||
void update() override;
|
||||
void render() override;
|
||||
|
||||
@@ -112,7 +112,7 @@ world_environment::update() {
|
||||
// twilight factor can be reset later down, so we do it here while it's still reflecting state of the sun
|
||||
// turbidity varies from 2-3 during the day based on overcast, 3-4 after sunset to deal with sunlight bleeding too much into the sky from below horizon
|
||||
m_skydome.SetTurbidity(
|
||||
2.f
|
||||
2.25f
|
||||
+ clamp( Global.Overcast, 0.f, 1.f )
|
||||
+ interpolate( 0.f, 1.f, clamp( twilightfactor * 1.5f, 0.f, 1.f ) ) );
|
||||
m_skydome.SetOvercastFactor( Global.Overcast );
|
||||
@@ -173,8 +173,9 @@ world_environment::update() {
|
||||
|
||||
// update the fog. setting it to match the average colour of the sky dome is cheap
|
||||
// but quite effective way to make the distant items blend with background better
|
||||
// NOTE: base brightness calculation provides scaled up value, so we bring it back to 'real' one here
|
||||
Global.FogColor = m_skydome.GetAverageHorizonColor();
|
||||
Global.FogColor =
|
||||
interpolate( m_skydome.GetAverageColor(), m_skydome.GetAverageHorizonColor(), 0.33f )
|
||||
* clamp<float>( Global.fLuminance, 0.25f, 1.f );
|
||||
|
||||
// weather-related simulation factors
|
||||
Global.FrictionWeatherFactor = (
|
||||
|
||||
@@ -264,6 +264,10 @@ void CSkyDome::RebuildColors() {
|
||||
colorconverter.z = 1.0f - std::exp( -m_expfactor * colorconverter.z );
|
||||
}
|
||||
|
||||
if( colorconverter.z > 0.85f ) {
|
||||
colorconverter.z = 0.85f + ( colorconverter.z - 0.85f ) * 0.35f;
|
||||
}
|
||||
|
||||
colorconverter.y = clamp( colorconverter.y * 1.15f, 0.0f, 1.0f );
|
||||
// desaturate sky colour, based on overcast level
|
||||
if( colorconverter.y > 0.0f ) {
|
||||
@@ -310,14 +314,14 @@ void CSkyDome::RebuildColors() {
|
||||
// save
|
||||
m_colours[ i ] = color;
|
||||
averagecolor += color;
|
||||
if( ( m_vertices.size() - i ) <= ( m_tesselation * 2 ) ) {
|
||||
if( ( m_vertices.size() - i ) <= ( m_tesselation * 3 + 3 ) ) {
|
||||
// calculate horizon colour from the bottom band of tris
|
||||
averagehorizoncolor += color;
|
||||
}
|
||||
}
|
||||
|
||||
m_averagecolour = glm::max( glm::vec3(), averagecolor / static_cast<float>( m_vertices.size() ) );
|
||||
m_averagehorizoncolour = glm::max( glm::vec3(), averagehorizoncolor / static_cast<float>( m_tesselation * 2 ) );
|
||||
m_averagehorizoncolour = glm::max( glm::vec3(), averagehorizoncolor / static_cast<float>( m_tesselation * 3 + 3 ) );
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ ui_layer::init( GLFWwindow *Window ) {
|
||||
|
||||
static ImWchar const glyphranges[] = {
|
||||
0x0020, 0x00FF, // ascii + extension
|
||||
0x0100, 0x017F, // latin extended-a
|
||||
0x2070, 0x2079, // superscript
|
||||
0x2500, 0x256C, // box drawings
|
||||
0,
|
||||
|
||||
Reference in New Issue
Block a user