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

vehicle params window, aware system rewrite, sifa

This commit is contained in:
milek7
2019-03-16 01:21:59 +01:00
parent f1c8c8f1cd
commit 3556a2d0e6
24 changed files with 622 additions and 451 deletions

View File

@@ -128,6 +128,7 @@ set(SOURCES
"widgets/map_objects.cpp" "widgets/map_objects.cpp"
"widgets/popup.cpp" "widgets/popup.cpp"
"widgets/time.cpp" "widgets/time.cpp"
"widgets/vehicleparams.cpp"
"ref/glad/src/glad.c" "ref/glad/src/glad.c"

View File

@@ -3759,7 +3759,7 @@ void TController::PhysicsLog()
<< ( mvOccupied->CommandIn.Command.empty() ? "none" : mvOccupied->CommandIn.Command.c_str() ) << " " << ( mvOccupied->CommandIn.Command.empty() ? "none" : mvOccupied->CommandIn.Command.c_str() ) << " "
<< mvOccupied->CommandIn.Value1 << " " << mvOccupied->CommandIn.Value1 << " "
<< mvOccupied->CommandIn.Value2 << " " << mvOccupied->CommandIn.Value2 << " "
<< int(mvControlling->SecuritySystem.Status) << " " << int(mvControlling->SecuritySystem.is_blinking()) << " "
<< int(mvControlling->SlippingWheels) << " " << int(mvControlling->SlippingWheels) << " "
<< mvControlling->dizel_heat.Ts << " " << mvControlling->dizel_heat.Ts << " "
<< mvControlling->dizel_heat.To << " " << mvControlling->dizel_heat.To << " "
@@ -4231,17 +4231,9 @@ TController::UpdateSituation(double dt) {
// rozpoznaj komende bo lokomotywa jej nie rozpoznaje // rozpoznaj komende bo lokomotywa jej nie rozpoznaje
RecognizeCommand(); // samo czyta komendę wstawioną do pojazdu? RecognizeCommand(); // samo czyta komendę wstawioną do pojazdu?
} }
if( mvOccupied->SecuritySystem.Status > 1 ) { if( mvOccupied->SecuritySystem.is_blinking() ) {
// jak zadziałało CA/SHP // jak zadziałało CA/SHP
if( !mvOccupied->SecuritySystemReset() ) { // to skasuj mvOccupied->SecuritySystemReset(); // to skasuj
if( ( mvOccupied->BrakeCtrlPos == 0 )
&& ( AccDesired > 0.0 )
&& ( ( TestFlag( mvOccupied->SecuritySystem.Status, s_SHPebrake ) )
|| ( TestFlag( mvOccupied->SecuritySystem.Status, s_CAebrake ) ) ) ) {
//!!! hm, może po prostu normalnie sterować hamulcem?
mvOccupied->BrakeLevelSet( 0 );
}
}
} }
// basic emergency stop handling, while at it // basic emergency stop handling, while at it
if( ( true == mvOccupied->RadioStopFlag ) // radio-stop if( ( true == mvOccupied->RadioStopFlag ) // radio-stop

View File

@@ -5957,7 +5957,7 @@ void TDynamicObject::RadioStop()
{ // zatrzymanie pojazdu { // zatrzymanie pojazdu
if( Mechanik ) { if( Mechanik ) {
// o ile ktoś go prowadzi // o ile ktoś go prowadzi
if( ( MoverParameters->SecuritySystem.RadioStop ) if( ( MoverParameters->SecuritySystem.radiostop_available() )
&& ( MoverParameters->Radio ) ) { && ( MoverParameters->Radio ) ) {
// jeśli pojazd ma RadioStop i jest on aktywny // jeśli pojazd ma RadioStop i jest on aktywny
// HACK cast until math types unification // HACK cast until math types unification

View File

@@ -78,6 +78,7 @@ zwiekszenie nacisku przy duzych predkosciach w hamulcach Oerlikona
*/ */
#include "dumb3d.h" #include "dumb3d.h"
#include "utilities.h"
extern int ConversionError; extern int ConversionError;
@@ -201,17 +202,6 @@ static int const dbrake_switch = 2;
static int const dbrake_reversal = 4; static int const dbrake_reversal = 4;
static int const dbrake_automatic = 8; static int const dbrake_automatic = 8;
/*status czuwaka/SHP*/
//hunter-091012: rozdzielenie alarmow, dodanie testu czuwaka
static int const s_waiting = 1; //działa
static int const s_aware = 2; //czuwak miga
static int const s_active = 4; //SHP świeci
static int const s_CAalarm = 8; //buczy
static int const s_SHPalarm = 16; //buczy
static int const s_CAebrake = 32; //hamuje
static int const s_SHPebrake = 64; //hamuje
static int const s_CAtest = 128;
/*dzwieki*/ /*dzwieki*/
enum sound { enum sound {
none, none,
@@ -572,23 +562,43 @@ struct TMotorParameters
} }
}; };
struct TSecuritySystem class TSecuritySystem
{ {
int SystemType { 0 }; /*0: brak, 1: czuwak aktywny, 2: SHP/sygnalizacja kabinowa*/ bool vigilance_enabled = false;
double AwareDelay { -1.0 }; // czas powtarzania czuwaka bool cabsignal_enabled = false;
double AwareMinSpeed; // minimalna prędkość załączenia czuwaka, normalnie 10% Vmax bool radiostop_enabled = false;
double SoundSignalDelay { -1.0 };
double EmergencyBrakeDelay { -1.0 }; bool cabsignal_active = false;
int Status { 0 }; /*0: wylaczony, 1: wlaczony, 2: czuwak, 4: shp, 8: alarm, 16: hamowanie awaryjne*/ bool pressed = false;
double SystemTimer { 0.0 }; bool enabled = false;
double SystemSoundCATimer { 0.0 }; bool is_sifa = false; // Sifa-like pedal device, with inverted input for convenient keyboard usage
double SystemSoundSHPTimer { 0.0 };
double SystemBrakeCATimer { 0.0 }; double vigilance_timer = 0.0;
double SystemBrakeSHPTimer { 0.0 }; double alert_timer = 0.0;
double SystemBrakeCATestTimer { 0.0 }; // hunter-091012 double press_timer = 0.0;
int VelocityAllowed;
int NextVelocityAllowed; /*predkosc pokazywana przez sygnalizacje kabinowa*/ double velocity = 0.0;
bool RadioStop; // czy jest RadioStop
double AwareDelay = 30.0;
double AwareMinSpeed = 0.0;
double SoundSignalDelay = 5.0;
double EmergencyBrakeDelay = 5.0;
double MaxHoldTime = 5.0;
public:
void set_enabled(bool e);
void acknowledge_press();
void acknowledge_release();
void update(double dt, double Vel);
void set_cabsignal();
bool is_blinking() const;
bool is_vigilance_blinking() const;
bool is_cabsignal_blinking() const;
bool is_beeping() const;
bool is_braking() const;
bool is_engine_blocked() const;
bool radiostop_available() const;
void load(std::string const &line, double Vmax);
}; };
struct TTransmision struct TTransmision
@@ -1372,8 +1382,7 @@ public:
bool Sandbox( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ bool Sandbox( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/
/*! zbijanie czuwaka/SHP*/ /*! zbijanie czuwaka/SHP*/
void SSReset(void); void SecuritySystemReset(void);
bool SecuritySystemReset(void);
void SecuritySystemCheck(double dt); void SecuritySystemCheck(double dt);
bool BatterySwitch(bool State); bool BatterySwitch(bool State);
@@ -1516,7 +1525,6 @@ private:
void LoadFIZ_Cntrl( std::string const &line ); void LoadFIZ_Cntrl( std::string const &line );
void LoadFIZ_Blending(std::string const &line); void LoadFIZ_Blending(std::string const &line);
void LoadFIZ_Light( std::string const &line ); void LoadFIZ_Light( std::string const &line );
void LoadFIZ_Security( std::string const &line );
void LoadFIZ_Clima( std::string const &line ); void LoadFIZ_Clima( std::string const &line );
void LoadFIZ_Power( std::string const &Line ); void LoadFIZ_Power( std::string const &Line );
void LoadFIZ_Engine( std::string const &Input ); void LoadFIZ_Engine( std::string const &Input );

View File

@@ -78,6 +78,113 @@ int DirF(int CouplerN)
} }
} }
void TSecuritySystem::set_enabled(bool e) {
if (vigilance_enabled || cabsignal_enabled)
enabled = e;
if (enabled && cabsignal_enabled && !is_sifa) {
cabsignal_active = true;
alert_timer = SoundSignalDelay;
}
}
void TSecuritySystem::acknowledge_press() {
pressed = true;
if (cabsignal_active) {
cabsignal_active = false;
alert_timer = 0.0;
return;
}
vigilance_timer = 0.0;
alert_timer = 0.0;
}
void TSecuritySystem::acknowledge_release() {
pressed = false;
press_timer = 0.0;
alert_timer = 0.0;
}
void TSecuritySystem::update(double dt, double vel) {
if (!enabled) {
cabsignal_active = false;
vigilance_timer = 0.0;
alert_timer = 0.0;
press_timer = 0.0;
return;
}
velocity = vel;
if (vigilance_enabled && velocity > AwareMinSpeed)
vigilance_timer += dt;
if (pressed && (!is_sifa || velocity > AwareMinSpeed))
press_timer += dt;
if (vigilance_timer > AwareDelay
|| press_timer > MaxHoldTime
|| cabsignal_active)
alert_timer += dt;
}
void TSecuritySystem::set_cabsignal() {
if (cabsignal_enabled)
cabsignal_active = true;
}
bool TSecuritySystem::is_blinking() const {
return alert_timer > 0.0;
}
bool TSecuritySystem::is_vigilance_blinking() const {
return press_timer > MaxHoldTime || vigilance_timer > AwareDelay;
}
bool TSecuritySystem::is_cabsignal_blinking() const {
return cabsignal_active;
}
bool TSecuritySystem::is_beeping() const {
return alert_timer > SoundSignalDelay;
}
bool TSecuritySystem::is_braking() const {
return alert_timer > SoundSignalDelay + EmergencyBrakeDelay
&& velocity > AwareMinSpeed;
}
bool TSecuritySystem::radiostop_available() const {
return radiostop_enabled;
}
bool TSecuritySystem::is_engine_blocked() const {
if (!is_sifa)
return false;
return velocity < AwareMinSpeed && pressed;
}
void TSecuritySystem::load(std::string const &line, double Vmax) {
std::string awaresystem = extract_value( "AwareSystem", line );
if( awaresystem.find( "Active" ) != std::string::npos )
vigilance_enabled = true;
if( awaresystem.find( "CabSignal" ) != std::string::npos )
cabsignal_enabled = true;
if( awaresystem.find( "Sifa" ) != std::string::npos )
is_sifa = true;
extract_value( AwareDelay, "AwareDelay", line, "" );
AwareMinSpeed = 0.1 * Vmax; //domyślnie 10% Vmax
extract_value( AwareMinSpeed, "AwareMinSpeed", line, "" );
extract_value( SoundSignalDelay, "SoundSignalDelay", line, "" );
extract_value( EmergencyBrakeDelay, "EmergencyBrakeDelay", line, "" );
extract_value( MaxHoldTime, "MaxHoldTime", line, "" );
extract_value( radiostop_enabled, "RadioStop", line, "" );
}
// ************************************************************************************************* // *************************************************************************************************
// Q: 20160716 // Q: 20160716
// Obliczanie natężenie prądu w silnikach // Obliczanie natężenie prądu w silnikach
@@ -362,20 +469,6 @@ ActiveCab( Cab )
RunningTraction.TractionFreq = 0.0; RunningTraction.TractionFreq = 0.0;
RunningTraction.TractionMaxCurrent = 0.0; RunningTraction.TractionMaxCurrent = 0.0;
RunningTraction.TractionResistivity = 1.0; RunningTraction.TractionResistivity = 1.0;
SecuritySystem.SystemType = 0;
SecuritySystem.AwareDelay = -1.0;
SecuritySystem.SoundSignalDelay = -1.0;
SecuritySystem.EmergencyBrakeDelay = -1.0;
SecuritySystem.Status = 0;
SecuritySystem.SystemTimer = 0.0;
SecuritySystem.SystemBrakeCATimer = 0.0;
SecuritySystem.SystemBrakeSHPTimer = 0.0; // hunter-091012
SecuritySystem.VelocityAllowed = -1;
SecuritySystem.NextVelocityAllowed = -1;
SecuritySystem.RadioStop = false; // domyślnie nie ma
SecuritySystem.AwareMinSpeed = 0.1 * Vmax;
s_CAtestebrake = false;
}; };
double TMoverParameters::Distance(const TLocation &Loc1, const TLocation &Loc2, double TMoverParameters::Distance(const TLocation &Loc1, const TLocation &Loc2,
@@ -2083,7 +2176,7 @@ bool TMoverParameters::CabActivisation(void)
{ {
CabNo = ActiveCab; // sterowanie jest z kabiny z obsadą CabNo = ActiveCab; // sterowanie jest z kabiny z obsadą
DirAbsolute = ActiveDir * CabNo; DirAbsolute = ActiveDir * CabNo;
SecuritySystem.Status |= s_waiting; // activate the alerter TODO: make it part of control based cab selection SecuritySystem.set_enabled(true);
SendCtrlToNext("CabActivisation", 1, CabNo); SendCtrlToNext("CabActivisation", 1, CabNo);
} }
return OK; return OK;
@@ -2103,7 +2196,7 @@ bool TMoverParameters::CabDeactivisation(void)
CabNo = 0; CabNo = 0;
DirAbsolute = ActiveDir * CabNo; DirAbsolute = ActiveDir * CabNo;
DepartureSignal = false; // nie buczeć z nieaktywnej kabiny DepartureSignal = false; // nie buczeć z nieaktywnej kabiny
SecuritySystem.Status = 0; // deactivate alerter TODO: make it part of control based cab selection SecuritySystem.set_enabled(false);
SendCtrlToNext("CabActivisation", 0, ActiveCab); // CabNo==0! SendCtrlToNext("CabActivisation", 0, ActiveCab); // CabNo==0!
} }
@@ -2181,58 +2274,18 @@ bool TMoverParameters::Sandbox( bool const State, range_t const Notify )
return result; return result;
} }
void TMoverParameters::SSReset(void)
{ // funkcja pomocnicza dla SecuritySystemReset - w Delphi Reset()
SecuritySystem.SystemTimer = 0;
if (TestFlag(SecuritySystem.Status, s_aware))
{
SecuritySystem.SystemBrakeCATimer = 0;
SecuritySystem.SystemSoundCATimer = 0;
SetFlag(SecuritySystem.Status, -s_aware);
SetFlag(SecuritySystem.Status, -s_CAalarm);
SetFlag(SecuritySystem.Status, -s_CAebrake);
// EmergencyBrakeFlag = false; //YB-HN
SecuritySystem.VelocityAllowed = -1;
}
else if (TestFlag(SecuritySystem.Status, s_active))
{
SecuritySystem.SystemBrakeSHPTimer = 0;
SecuritySystem.SystemSoundSHPTimer = 0;
SetFlag(SecuritySystem.Status, -s_active);
SetFlag(SecuritySystem.Status, -s_SHPalarm);
SetFlag(SecuritySystem.Status, -s_SHPebrake);
// EmergencyBrakeFlag = false; //YB-HN
SecuritySystem.VelocityAllowed = -1;
}
}
// ***************************************************************************** // *****************************************************************************
// Q: 20160710 // Q: 20160710
// zbicie czuwaka / SHP // zbicie czuwaka / SHP
// ***************************************************************************** // *****************************************************************************
// hunter-091012: rozbicie alarmow, dodanie testu czuwaka // hunter-091012: rozbicie alarmow, dodanie testu czuwaka
bool TMoverParameters::SecuritySystemReset(void) // zbijanie czuwaka/SHP void TMoverParameters::SecuritySystemReset(void) // zbijanie czuwaka/SHP
{ {
// zbijanie czuwaka/SHP if (TrainType != dt_EZT && ActiveDir == 0)
bool SSR = false; return; // Ra 2014-03: w EZT nie trzeba ustawiać kierunku
// with SecuritySystem do
if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0)) SecuritySystem.acknowledge_press();
{ SecuritySystem.acknowledge_release();
SSR = true;
if ((TrainType == dt_EZT) ||
(ActiveDir != 0)) // Ra 2014-03: w EZT nie trzeba ustawiać kierunku
if (!TestFlag(SecuritySystem.Status, s_CAebrake) ||
!TestFlag(SecuritySystem.Status, s_SHPebrake))
SSReset();
// else
// if EmergencyBrakeSwitch(false) then
// Reset;
}
else
SSR = false;
// SendCtrlToNext('SecurityReset',0,CabNo);
return SSR;
} }
// ************************************************************************************************* // *************************************************************************************************
@@ -2241,83 +2294,12 @@ bool TMoverParameters::SecuritySystemReset(void) // zbijanie czuwaka/SHP
// ************************************************************************************************* // *************************************************************************************************
void TMoverParameters::SecuritySystemCheck(double dt) void TMoverParameters::SecuritySystemCheck(double dt)
{ {
// Ra: z CA/SHP w EZT jest ten problem, że w rozrządczym nie ma kierunku, a w silnikowym nie ma if (Battery) {
// obsady SecuritySystem.update(dt, Vel);
// poza tym jest zdefiniowany we wszystkich 3 członach EN57
if ((!Radio))
RadiostopSwitch(false);
if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0) &&
(Battery)) // Ra: EZT ma teraz czuwak w rozrządczym
{
// CA
if( ( SecuritySystem.AwareMinSpeed > 0.0 ?
( Vel >= SecuritySystem.AwareMinSpeed ) :
( ActiveDir != 0 ) ) ) {
// domyślnie predkość większa od 10% Vmax, albo podanej jawnie w FIZ
// with defined minspeed of 0 the alerter will activate with reverser out of neutral position
// this emulates behaviour of engines like SM42
SecuritySystem.SystemTimer += dt;
if (TestFlag(SecuritySystem.SystemType, 1) &&
TestFlag(SecuritySystem.Status, s_aware)) // jeśli świeci albo miga
SecuritySystem.SystemSoundCATimer += dt;
if (TestFlag(SecuritySystem.SystemType, 1) &&
TestFlag(SecuritySystem.Status, s_CAalarm)) // jeśli buczy
SecuritySystem.SystemBrakeCATimer += dt;
if (TestFlag(SecuritySystem.SystemType, 1))
if ((SecuritySystem.SystemTimer > SecuritySystem.AwareDelay) &&
(SecuritySystem.AwareDelay >= 0)) //-1 blokuje
if (!SetFlag(SecuritySystem.Status, s_aware)) // juz wlaczony sygnal swietlny
if ((SecuritySystem.SystemSoundCATimer > SecuritySystem.SoundSignalDelay) &&
(SecuritySystem.SoundSignalDelay >= 0))
if (!SetFlag(SecuritySystem.Status,
s_CAalarm)) // juz wlaczony sygnal dzwiekowy
if ((SecuritySystem.SystemBrakeCATimer >
SecuritySystem.EmergencyBrakeDelay) &&
(SecuritySystem.EmergencyBrakeDelay >= 0))
SetFlag(SecuritySystem.Status, s_CAebrake);
// SHP
if (TestFlag(SecuritySystem.SystemType, 2) &&
TestFlag(SecuritySystem.Status, s_active)) // jeśli świeci albo miga
SecuritySystem.SystemSoundSHPTimer += dt;
if (TestFlag(SecuritySystem.SystemType, 2) &&
TestFlag(SecuritySystem.Status, s_SHPalarm)) // jeśli buczy
SecuritySystem.SystemBrakeSHPTimer += dt;
if (TestFlag(SecuritySystem.SystemType, 2) && TestFlag(SecuritySystem.Status, s_active))
if ((Vel > SecuritySystem.VelocityAllowed) && (SecuritySystem.VelocityAllowed >= 0))
SetFlag(SecuritySystem.Status, s_SHPebrake);
else if (((SecuritySystem.SystemSoundSHPTimer > SecuritySystem.SoundSignalDelay) &&
(SecuritySystem.SoundSignalDelay >= 0)) ||
((Vel > SecuritySystem.NextVelocityAllowed) &&
(SecuritySystem.NextVelocityAllowed >= 0)))
if (!SetFlag(SecuritySystem.Status,
s_SHPalarm)) // juz wlaczony sygnal dzwiekowy}
if ((SecuritySystem.SystemBrakeSHPTimer >
SecuritySystem.EmergencyBrakeDelay) &&
(SecuritySystem.EmergencyBrakeDelay >= 0))
SetFlag(SecuritySystem.Status, s_SHPebrake);
} // else SystemTimer:=0;
// TEST CA
if (TestFlag(SecuritySystem.Status, s_CAtest)) // jeśli świeci albo miga
SecuritySystem.SystemBrakeCATestTimer += dt;
if (TestFlag(SecuritySystem.SystemType, 1))
if (TestFlag(SecuritySystem.Status, s_CAtest)) // juz wlaczony sygnal swietlny
if ((SecuritySystem.SystemBrakeCATestTimer > SecuritySystem.EmergencyBrakeDelay) &&
(SecuritySystem.EmergencyBrakeDelay >= 0))
s_CAtestebrake = true;
// wdrazanie hamowania naglego
// if TestFlag(Status,s_SHPebrake) or TestFlag(Status,s_CAebrake) or
// (s_CAtestebrake=true) then
// EmergencyBrakeFlag:=true; //YB-HN
} }
else if (!Battery) else
{ // wyłączenie baterii deaktywuje sprzęt { // wyłączenie baterii deaktywuje sprzęt
RadiostopSwitch(false); RadiostopSwitch(false);
// SecuritySystem.Status = 0; //deaktywacja czuwaka
} }
} }
@@ -2339,10 +2321,7 @@ bool TMoverParameters::BatterySwitch(bool State)
SendCtrlToNext("BatterySwitch", 0, CabNo); SendCtrlToNext("BatterySwitch", 0, CabNo);
BS = true; BS = true;
if ((Battery) && (ActiveCab != 0)) /*|| (TrainType==dt_EZT)*/ SecuritySystem.set_enabled((Battery) && (ActiveCab != 0));
SecuritySystem.Status = (SecuritySystem.Status | s_waiting); // aktywacja czuwaka
else
SecuritySystem.Status = 0; // wyłączenie czuwaka
return BS; return BS;
} }
@@ -3569,19 +3548,12 @@ void TMoverParameters::UpdatePipePressure(double dt)
Pipe2->Flow(dpMainValve); Pipe2->Flow(dpMainValve);
} }
// ulepszony hamulec bezp. if( ( true == RadioStopFlag )
if( ( true == RadioStopFlag ) || ( true == AlarmChainFlag )
|| ( true == AlarmChainFlag ) || SecuritySystem.is_braking() ) {
|| ( true == TestFlag( SecuritySystem.Status, s_SHPebrake ) ) dpMainValve = dpMainValve + PF( 0, PipePress, 0.15 ) * dt;
|| ( true == TestFlag( SecuritySystem.Status, s_CAebrake ) ) }
/*
// NOTE: disabled because 32 is 'load destroyed' flag, what does this have to do with emergency brake?
// (if it's supposed to be broken coupler, such event sets alarmchainflag instead when appropriate)
|| ( true == TestFlag( EngDmgFlag, 32 ) )
*/
|| ( true == s_CAtestebrake ) ) {
dpMainValve = dpMainValve + PF( 0, PipePress, 0.15 ) * dt;
}
// 0.2*Spg // 0.2*Spg
Pipe->Flow(-dpMainValve); Pipe->Flow(-dpMainValve);
Pipe->Flow(-(PipePress)*0.001 * dt); Pipe->Flow(-(PipePress)*0.001 * dt);
@@ -5047,7 +5019,7 @@ double TMoverParameters::TractionForce( double dt ) {
case TEngineType::ElectricInductionMotor: case TEngineType::ElectricInductionMotor:
{ {
if( true == Mains ) { if( true == Mains && !SecuritySystem.is_engine_blocked() ) {
//tempomat //tempomat
if (ScndCtrlPosNo > 1) if (ScndCtrlPosNo > 1)
{ {
@@ -7747,7 +7719,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
{ {
startBPT = false; startBPT = false;
fizlines.emplace( "Security", inputline ); fizlines.emplace( "Security", inputline );
LoadFIZ_Security( inputline ); SecuritySystem.load(inputline, Vmax);
continue; continue;
} }
@@ -8568,24 +8540,6 @@ void TMoverParameters::LoadFIZ_Light( std::string const &line ) {
NominalBatteryVoltage = BatteryVoltage; NominalBatteryVoltage = BatteryVoltage;
} }
void TMoverParameters::LoadFIZ_Security( std::string const &line ) {
std::string awaresystem = extract_value( "AwareSystem", line );
if( awaresystem.find( "Active" ) != std::string::npos ) {
SetFlag( SecuritySystem.SystemType, 1 );
}
if( awaresystem.find( "CabSignal" ) != std::string::npos ) {
SetFlag( SecuritySystem.SystemType, 2 );
}
extract_value( SecuritySystem.AwareDelay, "AwareDelay", line, "" );
SecuritySystem.AwareMinSpeed = 0.1 * Vmax; //domyślnie 10% Vmax
extract_value( SecuritySystem.AwareMinSpeed, "AwareMinSpeed", line, "" );
extract_value( SecuritySystem.SoundSignalDelay, "SoundSignalDelay", line, "" );
extract_value( SecuritySystem.EmergencyBrakeDelay, "EmergencyBrakeDelay", line, "" );
extract_value( SecuritySystem.RadioStop, "RadioStop", line, "" );
}
void TMoverParameters::LoadFIZ_Clima( std::string const &line ) { void TMoverParameters::LoadFIZ_Clima( std::string const &line ) {
HeatingPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "Heating", line ) ); HeatingPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "Heating", line ) );
@@ -9677,10 +9631,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
Battery = true; Battery = true;
else if ((CValue1 == 0)) else if ((CValue1 == 0))
Battery = false; Battery = false;
if ((Battery) && (ActiveCab != 0) /*or (TrainType=dt_EZT)*/) SecuritySystem.set_enabled(((Battery) && (ActiveCab != 0)));
SecuritySystem.Status = SecuritySystem.Status || s_waiting; // aktywacja czuwaka
else
SecuritySystem.Status = 0; // wyłączenie czuwaka
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
// else if command='EpFuseSwitch' then {NBMX} // else if command='EpFuseSwitch' then {NBMX}
@@ -9903,16 +9854,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
} }
else if (Command == "CabSignal") /*SHP,Indusi*/ else if (Command == "CabSignal") /*SHP,Indusi*/
{ // Ra: to powinno działać tylko w członie obsadzonym { // Ra: to powinno działać tylko w członie obsadzonym
if (/*(TrainType=dt_EZT)or*/ (ActiveCab != 0) && (Battery) && SecuritySystem.set_cabsignal();
TestFlag(SecuritySystem.SystemType,
2)) // jeśli kabina jest obsadzona (silnikowy w EZT?)
/*?*/ /* WITH SecuritySystem */
{
SecuritySystem.VelocityAllowed = static_cast<int>(floor(CValue1));
SecuritySystem.NextVelocityAllowed = static_cast<int>(floor(CValue2));
SecuritySystem.SystemSoundSHPTimer = 0; // hunter-091012
SetFlag(SecuritySystem.Status, s_active);
}
// else OK:=false; // else OK:=false;
OK = true; // true, gdy można usunąć komendę OK = true; // true, gdy można usunąć komendę
} }

113
Train.cpp
View File

@@ -486,8 +486,8 @@ dictionary_source *TTrain::GetTrainState() {
dict->insert( "brake_delay_flag", mvOccupied->BrakeDelayFlag ); dict->insert( "brake_delay_flag", mvOccupied->BrakeDelayFlag );
dict->insert( "brake_op_mode_flag", mvOccupied->BrakeOpModeFlag ); dict->insert( "brake_op_mode_flag", mvOccupied->BrakeOpModeFlag );
// other controls // other controls
dict->insert( "ca", TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) ); dict->insert( "ca", mvOccupied->SecuritySystem.is_vigilance_blinking() );
dict->insert( "shp", TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ); dict->insert( "shp", mvOccupied->SecuritySystem.is_cabsignal_blinking() );
dict->insert( "pantpress", std::abs( mvControlled->PantPress ) ); dict->insert( "pantpress", std::abs( mvControlled->PantPress ) );
dict->insert( "universal3", InstrumentLightActive ); dict->insert( "universal3", InstrumentLightActive );
dict->insert( "radio_channel", iRadioChannel ); dict->insert( "radio_channel", iRadioChannel );
@@ -612,7 +612,7 @@ TTrain::get_state() const {
btLampkaOgrzewanieSkladu.GetValue(), btLampkaOgrzewanieSkladu.GetValue(),
btHaslerBrakes.GetValue(), btHaslerBrakes.GetValue(),
btHaslerCurrent.GetValue(), btHaslerCurrent.GetValue(),
( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ), mvOccupied->SecuritySystem.is_blinking(),
btLampkaHVoltageB.GetValue(), btLampkaHVoltageB.GetValue(),
fTachoVelocity, fTachoVelocity,
static_cast<float>( mvOccupied->Compressor ), static_cast<float>( mvOccupied->Compressor ),
@@ -1612,26 +1612,20 @@ void TTrain::OnCommand_reverserbackward( TTrain *Train, command_data const &Comm
} }
void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Command ) {
if (Train->mvOccupied->TrainType != dt_EZT && Train->mvOccupied->ActiveDir == 0)
return; // Ra 2014-03: w EZT nie trzeba ustawiać kierunku
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// visual feedback // visual feedback
Train->ggSecurityResetButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggSecurityResetButton.UpdateValue( 1.0, Train->dsbSwitch );
if( Train->CAflag == false ) {
Train->CAflag = true; Train->mvOccupied->SecuritySystem.acknowledge_press();
Train->mvOccupied->SecuritySystemReset();
}
} }
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
// visual feedback // visual feedback
Train->ggSecurityResetButton.UpdateValue( 0.0 ); Train->ggSecurityResetButton.UpdateValue( 0.0 );
Train->fCzuwakTestTimer = 0.0f; Train->mvOccupied->SecuritySystem.acknowledge_release();
if( TestFlag( Train->mvOccupied->SecuritySystem.Status, s_CAtest ) ) {
SetFlag( Train->mvOccupied->SecuritySystem.Status, -s_CAtest );
Train->mvOccupied->s_CAtestebrake = false;
Train->mvOccupied->SecuritySystem.SystemBrakeCATestTimer = 0.0;
}
Train->CAflag = false;
} }
} }
@@ -1666,11 +1660,7 @@ void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command
if( Train->mvOccupied->LightsPosNo > 0 ) { if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->SetLights(); Train->SetLights();
} }
if( TestFlag( Train->mvOccupied->SecuritySystem.SystemType, 2 ) ) { Train->mvOccupied->SecuritySystem.set_enabled(true); // Ra: znowu w kabinie jest coś, co być nie powinno!
// Ra: znowu w kabinie jest coś, co być nie powinno!
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_active );
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_SHPalarm );
}
} }
} }
} }
@@ -5449,37 +5439,24 @@ bool TTrain::Update( double const Deltatime )
} }
if (mvControlled->Battery || mvControlled->ConverterFlag) { if (mvControlled->Battery || mvControlled->ConverterFlag) {
// alerter test
if( true == CAflag ) {
if( ggSecurityResetButton.GetDesiredValue() > 0.95 ) {
fCzuwakTestTimer += Deltatime;
}
if( fCzuwakTestTimer > 1.0 ) {
SetFlag( mvOccupied->SecuritySystem.Status, s_CAtest );
}
}
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if( mvOccupied->SecuritySystem.Status > 0 ) { if( mvOccupied->SecuritySystem.is_vigilance_blinking() ) {
if( fBlinkTimer > fCzuwakBlink ) if( fBlinkTimer > fCzuwakBlink )
fBlinkTimer = -fCzuwakBlink; fBlinkTimer = -fCzuwakBlink;
else else
fBlinkTimer += Deltatime; fBlinkTimer += Deltatime;
// hunter-091012: dodanie testu czuwaka
if( ( TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) )
|| ( TestFlag( mvOccupied->SecuritySystem.Status, s_CAtest ) ) ) {
btLampkaCzuwaka.Turn( fBlinkTimer > 0 );
}
else
btLampkaCzuwaka.Turn( false );
btLampkaSHP.Turn( TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ); btLampkaCzuwaka.Turn( fBlinkTimer > 0 );
} }
else // wylaczone else {
{
btLampkaCzuwaka.Turn( false ); btLampkaCzuwaka.Turn( false );
btLampkaSHP.Turn( false );
} }
if (mvOccupied->SecuritySystem.is_cabsignal_blinking())
btLampkaSHP.Turn( true );
else
btLampkaSHP.Turn( false );
btLampkaWylSzybki.Turn( btLampkaWylSzybki.Turn(
( ( (m_linebreakerstate == 2) ( ( (m_linebreakerstate == 2)
|| (true == mvControlled->Mains) ) ? || (true == mvControlled->Mains) ) ?
@@ -6098,13 +6075,9 @@ bool TTrain::Update( double const Deltatime )
*/ */
// screens // screens
fScreenTimer += Deltatime; fScreenTimer += Deltatime;
if( ( fScreenTimer > Global.PythonScreenUpdateRate * 0.001f ) if (!FreeFlyModeFlag && simulation::Train == this) // don't bother if we're outside
&& !FreeFlyModeFlag && simulation::Train == this ) { // don't bother if we're outside update_screens();
fScreenTimer = 0.f;
for( auto const &screen : m_screens ) {
Application.request( { std::get<0>(screen), GetTrainState(), std::get<1>(screen) } );
}
}
// sounds // sounds
update_sounds( Deltatime ); update_sounds( Deltatime );
@@ -6299,10 +6272,8 @@ TTrain::update_sounds( double const Deltatime ) {
} }
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if (mvOccupied->SecuritySystem.Status > 0) { if (mvOccupied->SecuritySystem.is_beeping()) {
// hunter-091012: rozdzielenie alarmow // hunter-091012: rozdzielenie alarmow
if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm )
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
if( false == dsbBuzzer.is_playing() ) { if( false == dsbBuzzer.is_playing() ) {
dsbBuzzer dsbBuzzer
@@ -6313,7 +6284,7 @@ TTrain::update_sounds( double const Deltatime ) {
Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys
#endif #endif
} }
} }
else { else {
if( true == dsbBuzzer.is_playing() ) { if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop(); dsbBuzzer.stop();
@@ -6322,16 +6293,6 @@ TTrain::update_sounds( double const Deltatime ) {
#endif #endif
} }
} }
}
else {
// wylaczone
if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop();
#ifdef _WIN32
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
#endif
}
}
update_sounds_radio(); update_sounds_radio();
@@ -6435,6 +6396,14 @@ void TTrain::update_sounds_radio() {
} }
} }
void TTrain::update_screens() {
if (fScreenTimer > Global.PythonScreenUpdateRate * 0.001f) {
fScreenTimer = 0.f;
for (auto const &screen : m_screens)
Application.request( { std::get<0>(screen), GetTrainState(), std::get<1>(screen) } );
}
}
bool TTrain::CabChange(int iDirection) bool TTrain::CabChange(int iDirection)
{ // McZapkie-090902: zmiana kabiny 1->0->2 i z powrotem { // McZapkie-090902: zmiana kabiny 1->0->2 i z powrotem
if( ( DynamicObject->Mechanik == nullptr ) if( ( DynamicObject->Mechanik == nullptr )
@@ -6893,16 +6862,16 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
tex->create(); tex->create();
const std::string rendererpath {
substr_path(renderername).empty() ? // supply vehicle folder as path if none is provided
DynamicObject->asBaseDir + renderername :
renderername };
// record renderer and material binding for future update requests // record renderer and material binding for future update requests
m_screens.emplace_back( m_screens.emplace_back(rendererpath, tex->id, nullptr);
( substr_path(renderername).empty() ? // supply vehicle folder as path if none is provided
DynamicObject->asBaseDir + renderername :
renderername ),
tex->id,
nullptr);
if (Global.python_displaywindows) if (Global.python_displaywindows)
std::get<2>(m_screens.back()) = std::make_unique<python_screen_viewer>(tex->id, submodelname); std::get<2>(m_screens.back()) = std::make_unique<python_screen_viewer>(tex->id, rendererpath);
} }
// btLampkaUnknown.Init("unknown",mdKabina,false); // btLampkaUnknown.Init("unknown",mdKabina,false);
} while (token != ""); } while (token != "");
@@ -7170,6 +7139,11 @@ TTrain::clamp_inside( Math3D::vector3 const &Point ) const {
clamp( Point.z, Cabine[ iCabn ].CabPos1.z, Cabine[ iCabn ].CabPos2.z ) }; clamp( Point.z, Cabine[ iCabn ].CabPos1.z, Cabine[ iCabn ].CabPos2.z ) };
} }
const TTrain::screen_map& TTrain::get_screens() {
update_screens();
return m_screens;
}
void void
TTrain::radio_message( sound_source *Message, int const Channel ) { TTrain::radio_message( sound_source *Message, int const Channel ) {
@@ -8295,8 +8269,7 @@ std::array<float, 3> TTrain::get_current()
bool TTrain::get_alarm() bool TTrain::get_alarm()
{ {
return (TestFlag(mvOccupied->SecuritySystem.Status, s_CAalarm) || return mvOccupied->SecuritySystem.is_beeping();
TestFlag(mvOccupied->SecuritySystem.Status, s_SHPalarm));
} }
void TTrain::set_mainctrl(int pos) void TTrain::set_mainctrl(int pos)

View File

@@ -98,6 +98,8 @@ class TTrain
float hv_voltage; float hv_voltage;
std::array<float, 3> hv_current; std::array<float, 3> hv_current;
}; };
typedef std::tuple<std::string, GLuint, std::unique_ptr<python_screen_viewer>> screen_entry;
typedef std::vector<screen_entry> screen_map;
// methods // methods
bool CabChange(int iDirection); bool CabChange(int iDirection);
@@ -151,6 +153,7 @@ class TTrain
void update_sounds( double const Deltatime ); void update_sounds( double const Deltatime );
void update_sounds_runningnoise( sound_source &Sound ); void update_sounds_runningnoise( sound_source &Sound );
void update_sounds_radio(); void update_sounds_radio();
void update_screens();
// command handlers // command handlers
// NOTE: we're currently using universal handlers and static handler map but it may be beneficial to have these implemented on individual class instance basis // NOTE: we're currently using universal handlers and static handler map but it may be beneficial to have these implemented on individual class instance basis
@@ -632,11 +635,8 @@ private:
float fHaslerTimer; float fHaslerTimer;
float fConverterTimer; // hunter-261211: dla przekaznika float fConverterTimer; // hunter-261211: dla przekaznika
float fMainRelayTimer; // hunter-141211: zalaczanie WSa z opoznieniem float fMainRelayTimer; // hunter-141211: zalaczanie WSa z opoznieniem
float fCzuwakTestTimer; // hunter-091012: do testu czuwaka
float fScreenTimer { 0.f }; float fScreenTimer { 0.f };
bool CAflag { false }; // hunter-131211: dla osobnego zbijania CA i SHP
// McZapkie-240302 - przyda sie do tachometru // McZapkie-240302 - przyda sie do tachometru
float fTachoVelocity{ 0.0f }; float fTachoVelocity{ 0.0f };
float fTachoVelocityJump{ 0.0f }; // ze skakaniem float fTachoVelocityJump{ 0.0f }; // ze skakaniem
@@ -665,7 +665,7 @@ private:
bool m_mastercontrollerinuse { false }; bool m_mastercontrollerinuse { false };
float m_mastercontrollerreturndelay { 0.f }; float m_mastercontrollerreturndelay { 0.f };
int iRadioChannel { 1 }; // numer aktualnego kana?u radiowego int iRadioChannel { 1 }; // numer aktualnego kana?u radiowego
std::vector<std::tuple<std::string, GLuint, std::unique_ptr<python_screen_viewer>>> m_screens; screen_map m_screens;
uint16_t vid { 0 }; uint16_t vid { 0 };
public: public:
@@ -686,6 +686,7 @@ private:
// checks whether specified point is within boundaries of the active cab // checks whether specified point is within boundaries of the active cab
bool point_inside( Math3D::vector3 const Point ) const; bool point_inside( Math3D::vector3 const Point ) const;
Math3D::vector3 clamp_inside( Math3D::vector3 const &Point ) const; Math3D::vector3 clamp_inside( Math3D::vector3 const &Point ) const;
const screen_map & get_screens();
float get_tacho(); float get_tacho();
float get_tank_pressure(); float get_tank_pressure();

View File

@@ -28,6 +28,7 @@ driver_ui::driver_ui() {
push_back( &m_transcriptspanel ); push_back( &m_transcriptspanel );
//push_back( &m_vehiclelist ); //push_back( &m_vehiclelist );
push_back( &m_vehicleparams );
push_back( &m_timepanel ); push_back( &m_timepanel );
push_back( &m_mappanel ); push_back( &m_mappanel );
push_back( &m_logpanel ); push_back( &m_logpanel );
@@ -57,6 +58,8 @@ void driver_ui::render_menu_contents() {
if (ImGui::MenuItem(m_timepanel.get_name().c_str())) if (ImGui::MenuItem(m_timepanel.get_name().c_str()))
m_timepanel.open(); m_timepanel.open();
ImGui::MenuItem(m_vehicleparams.get_name().c_str(), nullptr, &m_vehicleparams.is_open);
ImGui::EndMenu(); ImGui::EndMenu();
} }
} }

View File

@@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/.
#include "command.h" #include "command.h"
#include "widgets/vehiclelist.h" #include "widgets/vehiclelist.h"
#include "widgets/vehicleparams.h"
#include "widgets/map.h" #include "widgets/map.h"
#include "widgets/time.h" #include "widgets/time.h"
@@ -58,6 +59,7 @@ private:
command_relay m_relay; command_relay m_relay;
ui::vehiclelist_panel m_vehiclelist; ui::vehiclelist_panel m_vehiclelist;
ui::vehicleparams_panel m_vehicleparams;
ui::map_panel m_mappanel; ui::map_panel m_mappanel;
ui::time_panel m_timepanel; ui::time_panel m_timepanel;
}; };

View File

@@ -137,11 +137,11 @@ drivingaid_panel::update() {
} }
} }
std::string textline = std::string textline =
( true == TestFlag( mover->SecuritySystem.Status, s_aware ) ? ( mover->SecuritySystem.is_vigilance_blinking() ?
locale::strings[ locale::string::driver_aid_alerter ] : locale::strings[ locale::string::driver_aid_alerter ] :
" " ); " " );
textline += textline +=
( true == TestFlag( mover->SecuritySystem.Status, s_active ) ? ( mover->SecuritySystem.is_cabsignal_blinking() ?
locale::strings[ locale::string::driver_aid_shp ] : locale::strings[ locale::string::driver_aid_shp ] :
" " ); " " );

View File

@@ -91,6 +91,8 @@ init() {
"Divert /", "Divert /",
"Insert obstacle:", "Insert obstacle:",
"Vehicle parameters",
"master controller", "master controller",
"second controller", "second controller",
"shunt mode power", "shunt mode power",
@@ -263,6 +265,8 @@ init() {
u8"W bok /", u8"W bok /",
u8"Wstaw przeszkodę:", u8"Wstaw przeszkodę:",
u8"Parametry pojazdu",
u8"nastawnik jazdy", u8"nastawnik jazdy",
u8"nastawnik dodatkowy", u8"nastawnik dodatkowy",
u8"sterowanie analogowe", u8"sterowanie analogowe",

View File

@@ -80,6 +80,8 @@ enum string {
map_divert, map_divert,
map_obstacle_insert, map_obstacle_insert,
vehicleparams_window,
cab_mainctrl, cab_mainctrl,
cab_scndctrl, cab_scndctrl,
cab_shuntmodepower, cab_shuntmodepower,

View File

@@ -10,8 +10,8 @@
ui::map_panel::map_panel() : ui_panel(LOC_STR(ui_map), false) ui::map_panel::map_panel() : ui_panel(LOC_STR(ui_map), false)
{ {
size_min = { 200, 200 }; size_min = {200, 200};
size_max = { fb_size, fb_size }; size_max = {fb_size, fb_size};
window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
gl::shader vert("map.vert"); gl::shader vert("map.vert");
@@ -57,13 +57,14 @@ ui::map_panel::map_panel() : ui_panel(LOC_STR(ui_map), false)
float ui::map_panel::get_vehicle_rotation() float ui::map_panel::get_vehicle_rotation()
{ {
const TDynamicObject *vehicle = simulation::Train->Dynamic(); const TDynamicObject *vehicle = simulation::Train->Dynamic();
glm::vec3 front = glm::dvec3(vehicle->VectorFront()) * (vehicle->DirectionGet() > 0 ? 1.0 : -1.0); glm::vec3 front = glm::dvec3(vehicle->VectorFront()) * (vehicle->DirectionGet() > 0 ? 1.0 : -1.0);
glm::vec2 north_ptr(0.0f, 1.0f); glm::vec2 north_ptr(0.0f, 1.0f);
return glm::atan(front.z, front.x) - glm::atan(north_ptr.y, north_ptr.x); return glm::atan(front.z, front.x) - glm::atan(north_ptr.y, north_ptr.x);
} }
void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_size) { void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_size)
{
cFrustum frustum; cFrustum frustum;
frustum.calculate(transform, glm::mat4()); frustum.calculate(transform, glm::mat4());
@@ -78,7 +79,8 @@ void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_si
if (section && frustum.sphere_inside(section->area().center, section->area().radius) > 0.f) if (section && frustum.sphere_inside(section->area().center, section->area().radius) > 0.f)
{ {
const gfx::geometrybank_handle handle = section->get_map_geometry(); const gfx::geometrybank_handle handle = section->get_map_geometry();
if (handle != null_handle) { if (handle != null_handle)
{
m_section_handles.push_back(handle); m_section_handles.push_back(handle);
section->get_map_active_switches(m_switch_handles); section->get_map_active_switches(m_switch_handles);
} }
@@ -130,7 +132,8 @@ void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_si
void ui::map_panel::render_labels(glm::mat4 transform, ImVec2 origin, glm::vec2 surface_size) void ui::map_panel::render_labels(glm::mat4 transform, ImVec2 origin, glm::vec2 surface_size)
{ {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.7f, 1.0f, 0.7f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.7f, 1.0f, 0.7f, 1.0f));
for (TDynamicObject *vehicle : simulation::Vehicles.sequence()) { for (TDynamicObject *vehicle : simulation::Vehicles.sequence())
{
if (vehicle->Prev() || !vehicle->Mechanik) if (vehicle->Prev() || !vehicle->Mechanik)
continue; continue;
@@ -147,14 +150,13 @@ void ui::map_panel::render_labels(glm::mat4 transform, ImVec2 origin, glm::vec2
TDynamicObject *veh = vehicle; TDynamicObject *veh = vehicle;
ImVec2 textsize = ImGui::CalcTextSize(label.c_str()); ImVec2 textsize = ImGui::CalcTextSize(label.c_str());
ImGui::SetCursorPos(ImVec2(origin.x + gui_pos.x - textsize.x / 2.0f, ImGui::SetCursorPos(ImVec2(origin.x + gui_pos.x - textsize.x / 2.0f, origin.y + gui_pos.y - textsize.y / 2.0f));
origin.y + gui_pos.y - textsize.y / 2.0f));
ImGui::TextUnformatted(label.c_str()); ImGui::TextUnformatted(label.c_str());
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
if (zoom > 0.005f) { if (zoom > 0.005f)
{
} }
} }
@@ -179,15 +181,13 @@ void ui::map_panel::render_contents()
glm::mat4 transform; glm::mat4 transform;
transform[0][0] = -1.0f; transform[0][0] = -1.0f;
static enum { static enum { MODE_MANUAL = 0, MODE_CAMERA, MODE_VEHICLE } mode = MODE_MANUAL;
MODE_MANUAL = 0,
MODE_CAMERA,
MODE_VEHICLE
} mode = MODE_MANUAL;
ImGui::RadioButton("manual", (int*)&mode, 0); ImGui::SameLine(); ImGui::RadioButton("manual", (int *)&mode, 0);
ImGui::RadioButton("cam", (int*)&mode, 1); ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("vehicle", (int*)&mode, 2); ImGui::RadioButton("cam", (int *)&mode, 1);
ImGui::SameLine();
ImGui::RadioButton("vehicle", (int *)&mode, 2);
ImVec2 surface_size_im = ImGui::GetContentRegionAvail(); ImVec2 surface_size_im = ImGui::GetContentRegionAvail();
glm::vec2 surface_size(surface_size_im.x, surface_size_im.y); glm::vec2 surface_size(surface_size_im.x, surface_size_im.y);
@@ -231,11 +231,12 @@ void ui::map_panel::render_contents()
ImVec2 window_origin = ImGui::GetCursorPos(); ImVec2 window_origin = ImGui::GetCursorPos();
ImVec2 screen_origin = ImGui::GetCursorScreenPos(); ImVec2 screen_origin = ImGui::GetCursorScreenPos();
ImGui::ImageButton(reinterpret_cast<void*>(m_tex->id), surface_size_im, ImVec2(0, surface_size.y / fb_size), ImVec2(surface_size.x / fb_size, 0), 0); ImGui::ImageButton(reinterpret_cast<void *>(m_tex->id), surface_size_im, ImVec2(0, surface_size.y / fb_size), ImVec2(surface_size.x / fb_size, 0), 0);
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
{ {
if (mode == 0 && ImGui::IsMouseDragging(0)) { if (mode == 0 && ImGui::IsMouseDragging(0))
{
ImVec2 delta_im = ImGui::GetMouseDragDelta(); ImVec2 delta_im = ImGui::GetMouseDragDelta();
ImGui::ResetMouseDragDelta(); ImGui::ResetMouseDragDelta();
@@ -245,27 +246,30 @@ void ui::map_panel::render_contents()
translate -= delta * 2.0f; translate -= delta * 2.0f;
} }
else { else
{
ImVec2 screen_pos = ImGui::GetMousePos(); ImVec2 screen_pos = ImGui::GetMousePos();
glm::vec2 surface_pos(screen_pos.x - screen_origin.x, screen_pos.y - screen_origin.y); glm::vec2 surface_pos(screen_pos.x - screen_origin.x, screen_pos.y - screen_origin.y);
glm::vec2 ndc_pos = surface_pos / surface_size * 2.0f - 1.0f; glm::vec2 ndc_pos = surface_pos / surface_size * 2.0f - 1.0f;
glm::vec3 world_pos = glm::inverse(transform) * glm::vec4(ndc_pos.x, 0.0f, -ndc_pos.y, 1.0f); glm::vec3 world_pos = glm::inverse(transform) * glm::vec4(ndc_pos.x, 0.0f, -ndc_pos.y, 1.0f);
map::sorted_object_list objects = map::sorted_object_list objects = map::Objects.find_in_range(glm::vec3(world_pos.x, NAN, world_pos.z), 0.03f / zoom);
map::Objects.find_in_range(glm::vec3(world_pos.x, NAN, world_pos.z), 0.03f / zoom);
if (ImGui::IsMouseClicked(1)) { if (ImGui::IsMouseClicked(1))
{
if (objects.size() > 1) if (objects.size() > 1)
register_popup(std::make_unique<ui::disambiguation_popup>(*this, std::move(objects))); register_popup(std::make_unique<ui::disambiguation_popup>(*this, std::move(objects)));
else if (objects.size() == 1) else if (objects.size() == 1)
handle_map_object_click(*this, objects.begin()->second); handle_map_object_click(*this, objects.begin()->second);
else { else
{
glm::vec3 nearest = simulation::Region->find_nearest_track_point(world_pos); glm::vec3 nearest = simulation::Region->find_nearest_track_point(world_pos);
if (!glm::isnan(nearest.x) && glm::distance(world_pos, nearest) < (0.03f / zoom)) if (!glm::isnan(nearest.x) && glm::distance(world_pos, nearest) < (0.03f / zoom))
register_popup(std::make_unique<obstacle_window>(*this, std::move(nearest))); register_popup(std::make_unique<obstacle_window>(*this, std::move(nearest)));
} }
} }
else if (!objects.empty()) { else if (!objects.empty())
{
handle_map_object_hover(objects.begin()->second); handle_map_object_hover(objects.begin()->second);
} }
} }
@@ -276,10 +280,12 @@ void ui::map_panel::render_contents()
void ui::handle_map_object_click(ui_panel &parent, std::shared_ptr<map::map_object> &obj) void ui::handle_map_object_click(ui_panel &parent, std::shared_ptr<map::map_object> &obj)
{ {
if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj)) { if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj))
{
parent.register_popup(std::make_unique<semaphore_window>(parent, std::move(sem))); parent.register_popup(std::make_unique<semaphore_window>(parent, std::move(sem)));
} }
else if (auto track = std::dynamic_pointer_cast<map::track_switch>(obj)) { else if (auto track = std::dynamic_pointer_cast<map::track_switch>(obj))
{
parent.register_popup(std::make_unique<switch_window>(parent, std::move(track))); parent.register_popup(std::make_unique<switch_window>(parent, std::move(track)));
} }
} }
@@ -288,12 +294,15 @@ void ui::handle_map_object_hover(std::shared_ptr<map::map_object> &obj)
{ {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj)) { if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj))
for (auto &model : sem->models) { {
for (auto &model : sem->models)
{
ImGui::PushID(model); ImGui::PushID(model);
ImGui::TextUnformatted(model->name().c_str()); ImGui::TextUnformatted(model->name().c_str());
for (int i = 0; i < iMaxNumLights; i++) { for (int i = 0; i < iMaxNumLights; i++)
{
GfxRenderer.Update_AnimModel(model); // update lamp opacities GfxRenderer.Update_AnimModel(model); // update lamp opacities
auto state = model->LightGet(i); auto state = model->LightGet(i);
if (!state) if (!state)
@@ -314,20 +323,22 @@ void ui::handle_map_object_hover(std::shared_ptr<map::map_object> &obj)
ImGui::PopID(); ImGui::PopID();
} }
} }
else if (auto sw = std::dynamic_pointer_cast<map::track_switch>(obj)) { else if (auto sw = std::dynamic_pointer_cast<map::track_switch>(obj))
{
ImGui::TextUnformatted(sw->name.c_str()); ImGui::TextUnformatted(sw->name.c_str());
} }
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
ui::disambiguation_popup::disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list) ui::disambiguation_popup::disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list) : popup(panel), m_list(list) {}
: popup(panel), m_list(list) { }
void ui::disambiguation_popup::render_content() void ui::disambiguation_popup::render_content()
{ {
for (auto &item : m_list) { for (auto &item : m_list)
if (ImGui::Button(item.second->name.c_str())) { {
if (ImGui::Button(item.second->name.c_str()))
{
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
handle_map_object_click(m_parent, item.second); handle_map_object_click(m_parent, item.second);
@@ -335,16 +346,17 @@ void ui::disambiguation_popup::render_content()
} }
} }
ui::semaphore_window::semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem) ui::semaphore_window::semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem) : popup(panel), m_sem(sem) {}
: popup(panel), m_sem(sem) { }
void ui::semaphore_window::render_content() void ui::semaphore_window::render_content()
{ {
for (auto &model : m_sem->models) { for (auto &model : m_sem->models)
{
ImGui::PushID(model); ImGui::PushID(model);
ImGui::TextUnformatted(model->name().c_str()); ImGui::TextUnformatted(model->name().c_str());
for (int i = 0; i < iMaxNumLights; i++) { for (int i = 0; i < iMaxNumLights; i++)
{
GfxRenderer.Update_AnimModel(model); // update lamp opacities GfxRenderer.Update_AnimModel(model); // update lamp opacities
auto state = model->LightGet(i); auto state = model->LightGet(i);
if (!state) if (!state)
@@ -361,7 +373,8 @@ void ui::semaphore_window::render_content()
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(current_color.x, current_color.y, current_color.z, 1.0f)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(current_color.x, current_color.y, current_color.z, 1.0f));
std::string res = " ##" + std::to_string(i); std::string res = " ##" + std::to_string(i);
if (ImGui::Button(res.c_str())) { if (ImGui::Button(res.c_str()))
{
level += 1.0f; level += 1.0f;
if (level >= 3.0f) if (level >= 3.0f)
level = 0.0f; level = 0.0f;
@@ -378,7 +391,8 @@ void ui::semaphore_window::render_content()
ImGui::Separator(); ImGui::Separator();
for (auto &item : m_sem->events) { for (auto &item : m_sem->events)
{
std::string displayname = item->name().substr(m_sem->name.size()); std::string displayname = item->name().substr(m_sem->name.size());
if (displayname.size() < 2) if (displayname.size() < 2)
@@ -386,38 +400,40 @@ void ui::semaphore_window::render_content()
displayname[1] = std::toupper(displayname[1]); displayname[1] = std::toupper(displayname[1]);
if (ImGui::Button(displayname.c_str())) { if (ImGui::Button(displayname.c_str()))
{
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(item), 0.0, GLFW_PRESS, 0); m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(item), 0.0, GLFW_PRESS, 0);
} }
} }
} }
ui::switch_window::switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw) ui::switch_window::switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw) : popup(panel), m_switch(sw) {}
: popup(panel), m_switch(sw) { }
void ui::switch_window::render_content() void ui::switch_window::render_content()
{ {
ImGui::TextUnformatted(m_switch->name.c_str()); ImGui::TextUnformatted(m_switch->name.c_str());
if (ImGui::Button(LOC_STR(map_straight))) { if (ImGui::Button(LOC_STR(map_straight)))
{
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(m_switch->straight_event), 0.0, GLFW_PRESS, 0); m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(m_switch->straight_event), 0.0, GLFW_PRESS, 0);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
if (ImGui::Button(LOC_STR(map_divert))) { if (ImGui::Button(LOC_STR(map_divert)))
{
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(m_switch->divert_event), 0.0, GLFW_PRESS, 0); m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(m_switch->divert_event), 0.0, GLFW_PRESS, 0);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
} }
ui::obstacle_window::obstacle_window(ui_panel &panel, glm::dvec3 const &pos) ui::obstacle_window::obstacle_window(ui_panel &panel, glm::dvec3 const &pos) : popup(panel), m_position(pos)
: popup(panel), m_position(pos)
{ {
std::ifstream file; std::ifstream file;
file.open("obstaclebank.txt", std::ios_base::in | std::ios_base::binary); file.open("obstaclebank.txt", std::ios_base::in | std::ios_base::binary);
std::string line; std::string line;
while (std::getline(file, line)) { while (std::getline(file, line))
{
std::istringstream entry(line); std::istringstream entry(line);
std::string name; std::string name;
@@ -432,8 +448,10 @@ ui::obstacle_window::obstacle_window(ui_panel &panel, glm::dvec3 const &pos)
void ui::obstacle_window::render_content() void ui::obstacle_window::render_content()
{ {
ImGui::TextUnformatted(LOC_STR(map_obstacle_insert)); ImGui::TextUnformatted(LOC_STR(map_obstacle_insert));
for (auto const &entry : m_obstacles) { for (auto const &entry : m_obstacles)
if (ImGui::Button(entry.first.c_str())) { {
if (ImGui::Button(entry.first.c_str()))
{
std::string name("obstacle_" + std::to_string(LocalRandom(0.0, 100000.0))); std::string name("obstacle_" + std::to_string(LocalRandom(0.0, 100000.0)));
TAnimModel *cloned = simulation::State.create_model(entry.second, name, m_position); TAnimModel *cloned = simulation::State.create_model(entry.second, name, m_position);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();

View File

@@ -7,66 +7,72 @@
#include "widgets/map_objects.h" #include "widgets/map_objects.h"
#include "widgets/popup.h" #include "widgets/popup.h"
namespace ui { namespace ui
{
class disambiguation_popup : public popup { class disambiguation_popup : public popup
{
map::sorted_object_list m_list; map::sorted_object_list m_list;
public: public:
disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list); disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list);
virtual void render_content() override; virtual void render_content() override;
}; };
class semaphore_window : public popup { class semaphore_window : public popup
{
std::shared_ptr<map::semaphore> m_sem; std::shared_ptr<map::semaphore> m_sem;
command_relay m_relay; command_relay m_relay;
public: public:
semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem); semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem);
virtual void render_content() override; virtual void render_content() override;
}; };
class switch_window : public popup { class switch_window : public popup
{
std::shared_ptr<map::track_switch> m_switch; std::shared_ptr<map::track_switch> m_switch;
command_relay m_relay; command_relay m_relay;
public: public:
switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw); switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw);
virtual void render_content() override; virtual void render_content() override;
}; };
class obstacle_window : public popup { class obstacle_window : public popup
{
glm::dvec3 m_position; glm::dvec3 m_position;
std::vector<std::pair<std::string, std::string>> m_obstacles; std::vector<std::pair<std::string, std::string>> m_obstacles;
public: public:
obstacle_window(ui_panel &panel, glm::dvec3 const &pos); obstacle_window(ui_panel &panel, glm::dvec3 const &pos);
virtual void render_content() override; virtual void render_content() override;
}; };
class map_panel : public ui_panel { class map_panel : public ui_panel
{
std::unique_ptr<gl::program> m_shader; std::unique_ptr<gl::program> m_shader;
std::unique_ptr<gl::framebuffer> m_msaa_fb; std::unique_ptr<gl::framebuffer> m_msaa_fb;
std::unique_ptr<gl::renderbuffer> m_msaa_rb; std::unique_ptr<gl::renderbuffer> m_msaa_rb;
std::unique_ptr<gl::framebuffer> m_fb; std::unique_ptr<gl::framebuffer> m_fb;
std::unique_ptr<opengl_texture> m_tex; std::unique_ptr<opengl_texture> m_tex;
std::unique_ptr<gl::ubo> scene_ubo; std::unique_ptr<gl::ubo> scene_ubo;
gl::scene_ubs scene_ubs; gl::scene_ubs scene_ubs;
std::vector<gfx::geometrybank_handle> m_section_handles; std::vector<gfx::geometrybank_handle> m_section_handles;
std::vector<gfx::geometrybank_handle> m_switch_handles; std::vector<gfx::geometrybank_handle> m_switch_handles;
const int fb_size = 1024; const int fb_size = 1024;
glm::vec2 translate; glm::vec2 translate;
float zoom = 1.0f / 1000.0f; float zoom = 1.0f / 1000.0f;
float get_vehicle_rotation(); float get_vehicle_rotation();
void render_map_texture(glm::mat4 transform, glm::vec2 surface_size); void render_map_texture(glm::mat4 transform, glm::vec2 surface_size);
void render_labels(glm::mat4 transform, ImVec2 origin, glm::vec2 surface_size); void render_labels(glm::mat4 transform, ImVec2 origin, glm::vec2 surface_size);
@@ -74,11 +80,11 @@ class map_panel : public ui_panel {
std::optional<map::semaphore> active; std::optional<map::semaphore> active;
public: public:
map_panel(); map_panel();
void render_contents() override; void render_contents() override;
}; };
void handle_map_object_click(ui_panel &parent, std::shared_ptr<map::map_object> &obj); void handle_map_object_click(ui_panel &parent, std::shared_ptr<map::map_object> &obj);
void handle_map_object_hover(std::shared_ptr<map::map_object> &obj); void handle_map_object_hover(std::shared_ptr<map::map_object> &obj);
} } // namespace ui

View File

@@ -8,17 +8,20 @@ map::sorted_object_list map::objects::find_in_range(glm::vec3 from, float distan
float max_distance2 = distance * distance; float max_distance2 = distance * distance;
for (auto const entry : entries) { for (auto const entry : entries)
{
glm::vec3 entry_location = entry->location; glm::vec3 entry_location = entry->location;
glm::vec3 search_point = from; glm::vec3 search_point = from;
if (glm::isnan(from.y)) { if (glm::isnan(from.y))
{
entry_location.y = 0.0f; entry_location.y = 0.0f;
search_point.y = 0.0f; search_point.y = 0.0f;
} }
float dist = glm::distance2(entry_location, search_point); float dist = glm::distance2(entry_location, search_point);
if (dist < max_distance2) { if (dist < max_distance2)
{
items.emplace(dist, std::move(entry)); items.emplace(dist, std::move(entry));
} }
} }

View File

@@ -4,37 +4,42 @@
#include "Event.h" #include "Event.h"
#include "scene.h" #include "scene.h"
namespace map { namespace map
{
struct map_object { struct map_object
std::string name; {
glm::vec3 location; std::string name;
glm::vec3 location;
virtual ~map_object() = default; virtual ~map_object() = default;
}; };
using object_list = std::vector<std::shared_ptr<map::map_object>>; using object_list = std::vector<std::shared_ptr<map::map_object>>;
using sorted_object_list = std::map<float, std::shared_ptr<map::map_object>>; using sorted_object_list = std::map<float, std::shared_ptr<map::map_object>>;
// semaphore description (only for minimap purposes) // semaphore description (only for minimap purposes)
struct semaphore : public map_object { struct semaphore : public map_object
std::vector<TAnimModel *> models; {
std::vector<TAnimModel *> models;
std::vector<basic_event *> events; std::vector<basic_event *> events;
}; };
// switch description (only for minimap purposes) // switch description (only for minimap purposes)
struct track_switch : public map_object { struct track_switch : public map_object
basic_event *straight_event = nullptr; {
basic_event *divert_event = nullptr; basic_event *straight_event = nullptr;
}; basic_event *divert_event = nullptr;
};
struct objects { struct objects
std::vector<std::shared_ptr<map_object>> entries; {
std::vector<std::shared_ptr<map_object>> entries;
// returns objects in range from vec3, NaN in Y ignores it // returns objects in range from vec3, NaN in Y ignores it
sorted_object_list find_in_range(glm::vec3 from, float distance); sorted_object_list find_in_range(glm::vec3 from, float distance);
}; };
extern objects Objects; extern objects Objects;
} } // namespace map

View File

@@ -1,17 +1,13 @@
#include "widgets/popup.h" #include "widgets/popup.h"
ui::popup::popup(ui_panel &panel) ui::popup::popup(ui_panel &panel) : m_parent(panel) {}
: m_parent(panel)
{
}
ui::popup::~popup() ui::popup::~popup() {}
{
}
bool ui::popup::render() bool ui::popup::render()
{ {
if (!m_id.size()) { if (!m_id.size())
{
m_id = "popup:" + std::to_string(id++); m_id = "popup:" + std::to_string(id++);
ImGui::OpenPopup(m_id.c_str()); ImGui::OpenPopup(m_id.c_str());
} }

View File

@@ -2,21 +2,23 @@
class ui_panel; class ui_panel;
namespace ui { namespace ui
{
class popup { class popup
{
std::string m_id; std::string m_id;
static int id; static int id;
public: public:
popup(ui_panel &panel); popup(ui_panel &panel);
~popup(); ~popup();
bool render(); bool render();
protected: protected:
ui_panel &m_parent; ui_panel &m_parent;
virtual void render_content() = 0; virtual void render_content() = 0;
}; };
} } // namespace ui

View File

@@ -3,8 +3,7 @@
#include "simulationtime.h" #include "simulationtime.h"
#include "Globals.h" #include "Globals.h"
ui::time_panel::time_panel() ui::time_panel::time_panel() : ui_panel(LOC_STR(time_window), false)
: ui_panel(LOC_STR(time_window), false)
{ {
size.x = 450; size.x = 450;
} }
@@ -17,7 +16,8 @@ void ui::time_panel::render_contents()
ImGui::SliderFloat(LOC_STR(time_weather), &overcast, 0.0f, 2.0f, "%.1f"); ImGui::SliderFloat(LOC_STR(time_weather), &overcast, 0.0f, 2.0f, "%.1f");
ImGui::SliderFloat(LOC_STR(time_temperature), &temperature, -20.0f, 40.0f, "%.0f"); ImGui::SliderFloat(LOC_STR(time_temperature), &temperature, -20.0f, 40.0f, "%.0f");
if (ImGui::Button(LOC_STR(time_apply))) { if (ImGui::Button(LOC_STR(time_apply)))
{
m_relay.post(user_command::setdatetime, (double)yearday, time, 1, 0); m_relay.post(user_command::setdatetime, (double)yearday, time, 1, 0);
m_relay.post(user_command::setweather, fog, overcast, 1, 0); m_relay.post(user_command::setweather, fog, overcast, 1, 0);
m_relay.post(user_command::settemperature, temperature, 0.0, 1, 0); m_relay.post(user_command::settemperature, temperature, 0.0, 1, 0);

View File

@@ -2,20 +2,22 @@
#include "translation.h" #include "translation.h"
#include "command.h" #include "command.h"
namespace ui { namespace ui
class time_panel : public ui_panel { {
command_relay m_relay; class time_panel : public ui_panel
{
command_relay m_relay;
float time; float time;
int yearday; int yearday;
float fog; float fog;
float overcast; float overcast;
float temperature; float temperature;
public: public:
time_panel(); time_panel();
void render_contents() override; void render_contents() override;
void open(); void open();
}; };
} } // namespace ui

View File

@@ -3,8 +3,10 @@
#include "simulation.h" #include "simulation.h"
#include "Driver.h" #include "Driver.h"
void ui::vehiclelist_panel::render_contents() { void ui::vehiclelist_panel::render_contents()
for (TDynamicObject* vehicle : simulation::Vehicles.sequence()) { {
for (TDynamicObject *vehicle : simulation::Vehicles.sequence())
{
if (vehicle->Prev()) if (vehicle->Prev())
continue; continue;
@@ -17,9 +19,11 @@ void ui::vehiclelist_panel::render_contents() {
std::string label = std::string(name + ", " + timetable + std::to_string(speed) + " km/h"); std::string label = std::string(name + ", " + timetable + std::to_string(speed) + " km/h");
if (!vehicle->Next()) if (!vehicle->Next())
ImGui::TextUnformatted(label.c_str()); ImGui::TextUnformatted(label.c_str());
else if (ImGui::TreeNode(vehicle, label.c_str())) { else if (ImGui::TreeNode(vehicle, label.c_str()))
{
vehicle = vehicle->Next(); vehicle = vehicle->Next();
while (vehicle) { while (vehicle)
{
ImGui::TextUnformatted(vehicle->name().c_str()); ImGui::TextUnformatted(vehicle->name().c_str());
vehicle = vehicle->Next(); vehicle = vehicle->Next();
} }
@@ -27,5 +31,5 @@ void ui::vehiclelist_panel::render_contents() {
} }
} }
//ImGui::ShowDemoWindow(); // ImGui::ShowDemoWindow();
} }

View File

@@ -1,10 +1,12 @@
#include "uilayer.h" #include "uilayer.h"
namespace ui { namespace ui
class vehiclelist_panel : public ui_panel { {
public: class vehiclelist_panel : public ui_panel
vehiclelist_panel() : ui_panel("Vehicle list", true) {} {
public:
vehiclelist_panel() : ui_panel("Vehicle list", true) {}
void render_contents() override; void render_contents() override;
}; };
} } // namespace ui

189
widgets/vehicleparams.cpp Normal file
View File

@@ -0,0 +1,189 @@
#include "stdafx.h"
#include "widgets/vehicleparams.h"
#include "simulation.h"
#include "driveruipanels.h"
#include "Driver.h"
#include "Train.h"
ui::vehicleparams_panel::vehicleparams_panel()
: ui_panel(LOC_STR(vehicleparams_window), false)
{
}
void ui::vehicleparams_panel::render_contents()
{
if (m_vehicle_name.empty())
m_vehicle_name = simulation::Vehicles.sequence()[0]->name();
TDynamicObject *vehicle_ptr = simulation::Vehicles.find(m_vehicle_name);
if (!vehicle_ptr) {
is_open = false;
return;
}
TTrain *train_ptr = simulation::Trains.find(m_vehicle_name);
if (train_ptr) {
const TTrain::screen_map &screens = train_ptr->get_screens();
for (const auto &viewport : Global.python_viewports) {
for (auto const &entry : screens) {
if (std::get<std::string>(entry) != viewport.surface)
continue;
float aspect = (float)viewport.size.y / viewport.size.x;
glm::mat3 proj = glm::translate(glm::scale(glm::mat3(), 1.0f / viewport.scale), viewport.offset);
glm::vec2 uv0 = glm::vec2(proj * glm::vec3(0.0f, 1.0f, 1.0f));
glm::vec2 uv1 = glm::vec2(proj * glm::vec3(1.0f, 0.0f, 1.0f));
ImGui::Image(reinterpret_cast<void*>(std::get<GLuint>(entry)), ImVec2(500, 500 * aspect), ImVec2(uv0.x, uv0.y), ImVec2(uv1.x, uv1.y));
}
}
}
TDynamicObject &vehicle = *vehicle_ptr;
TMoverParameters &mover = *vehicle.MoverParameters;
std::vector<text_line> lines;
std::array<char, 1024> buffer;
auto const isdieselenginepowered { ( mover.EngineType == TEngineType::DieselElectric ) || ( mover.EngineType == TEngineType::DieselEngine ) };
auto const isdieselinshuntmode { mover.ShuntMode && mover.EngineType == TEngineType::DieselElectric };
std::snprintf(
buffer.data(), buffer.size(),
locale::strings[ locale::string::debug_vehicle_devicespower ].c_str(),
// devices
( mover.Battery ? 'B' : '.' ),
( mover.Mains ? 'M' : '.' ),
( mover.FuseFlag ? '!' : '.' ),
( mover.PantRearUp ? ( mover.PantRearVolt > 0.0 ? 'O' : 'o' ) : '.' ),
( mover.PantFrontUp ? ( mover.PantFrontVolt > 0.0 ? 'P' : 'p' ) : '.' ),
( mover.PantPressLockActive ? '!' : ( mover.PantPressSwitchActive ? '*' : '.' ) ),
( mover.WaterPump.is_active ? 'W' : ( false == mover.WaterPump.breaker ? '-' : ( mover.WaterPump.is_enabled ? 'w' : '.' ) ) ),
( true == mover.WaterHeater.is_damaged ? '!' : ( mover.WaterHeater.is_active ? 'H' : ( false == mover.WaterHeater.breaker ? '-' : ( mover.WaterHeater.is_enabled ? 'h' : '.' ) ) ) ),
( mover.FuelPump.is_active ? 'F' : ( mover.FuelPump.is_enabled ? 'f' : '.' ) ),
( mover.OilPump.is_active ? 'O' : ( mover.OilPump.is_enabled ? 'o' : '.' ) ),
( false == mover.ConverterAllowLocal ? '-' : ( mover.ConverterAllow ? ( mover.ConverterFlag ? 'X' : 'x' ) : '.' ) ),
( mover.ConvOvldFlag ? '!' : '.' ),
( mover.CompressorFlag ? 'C' : ( false == mover.CompressorAllowLocal ? '-' : ( ( mover.CompressorAllow || mover.CompressorStart == start_t::automatic ) ? 'c' : '.' ) ) ),
( mover.CompressorGovernorLock ? '!' : '.' ),
"",
std::string( isdieselenginepowered ? locale::strings[ locale::string::debug_vehicle_oilpressure ] + to_string( mover.OilPump.pressure, 2 ) : "" ).c_str(),
// power transfers
mover.Couplers[ end::front ].power_high.voltage,
mover.Couplers[ end::front ].power_high.current,
std::string( mover.Couplers[ end::front ].power_high.local ? "" : "-" ).c_str(),
std::string( vehicle.DirectionGet() ? ":<<:" : ":>>:" ).c_str(),
std::string( mover.Couplers[ end::rear ].power_high.local ? "" : "-" ).c_str(),
mover.Couplers[ end::rear ].power_high.voltage,
mover.Couplers[ end::rear ].power_high.current );
ImGui::TextUnformatted(buffer.data());
std::snprintf(
buffer.data(), buffer.size(),
locale::strings[ locale::string::debug_vehicle_controllersenginerevolutions ].c_str(),
// controllers
mover.MainCtrlPos,
mover.MainCtrlActualPos,
std::string( isdieselinshuntmode ? to_string( mover.AnPos, 2 ) + locale::strings[ locale::string::debug_vehicle_shuntmode ] : std::to_string( mover.ScndCtrlPos ) + "(" + std::to_string( mover.ScndCtrlActualPos ) + ")" ).c_str(),
// engine
mover.EnginePower,
std::abs( mover.TrainType == dt_EZT ? mover.ShowCurrent( 0 ) : mover.Im ),
// revolutions
std::abs( mover.enrot ) * 60,
std::abs( mover.nrot ) * mover.Transmision.Ratio * 60,
mover.RventRot * 60,
std::abs( mover.MotorBlowers[end::front].revolutions ),
std::abs( mover.MotorBlowers[end::rear].revolutions ),
mover.dizel_heat.rpmw,
mover.dizel_heat.rpmw2 );
ImGui::TextUnformatted(buffer.data());
if( isdieselenginepowered ) {
std::snprintf(
buffer.data(), buffer.size(),
locale::strings[ locale::string::debug_vehicle_temperatures ].c_str(),
mover.dizel_heat.Ts,
mover.dizel_heat.To,
mover.dizel_heat.temperatura1,
( mover.WaterCircuitsLink ? '-' : '|' ),
mover.dizel_heat.temperatura2 );
ImGui::TextUnformatted(buffer.data());
}
std::string brakedelay;
{
std::vector<std::pair<int, std::string>> delays {
{ bdelay_G, "G" },
{ bdelay_P, "P" },
{ bdelay_R, "R" },
{ bdelay_M, "+Mg" } };
for( auto const &delay : delays ) {
if( ( mover.BrakeDelayFlag & delay.first ) == delay.first ) {
brakedelay += delay.second;
}
}
}
std::snprintf(
buffer.data(), buffer.size(),
locale::strings[ locale::string::debug_vehicle_brakespressures ].c_str(),
// brakes
mover.fBrakeCtrlPos,
mover.LocalBrakePosA,
mover.BrakeOpModeFlag,
brakedelay.c_str(),
mover.LoadFlag,
// cylinders
mover.BrakePress,
mover.LocBrakePress,
mover.Hamulec->GetBrakeStatus(),
// pipes
mover.PipePress,
mover.BrakeCtrlPos2,
mover.ScndPipePress,
mover.CntrlPipePress,
// tanks
mover.Hamulec->GetBRP(),
mover.Compressor,
mover.Hamulec->GetCRP() );
ImGui::TextUnformatted(buffer.data());
if( mover.EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) {
std::snprintf(
buffer.data(), buffer.size(),
locale::strings[ locale::string::debug_vehicle_pantograph ].c_str(),
mover.PantPress,
( mover.bPantKurek3 ? '-' : '|' ) );
ImGui::TextUnformatted(buffer.data());
}
std::snprintf(
buffer.data(), buffer.size(),
locale::strings[ locale::string::debug_vehicle_forcesaccelerationvelocityposition ].c_str(),
// forces
mover.Ft * 0.001f * ( mover.ActiveCab ? mover.ActiveCab : vehicle.ctOwner ? vehicle.ctOwner->Controlling()->ActiveCab : 1 ) + 0.001f,
mover.Fb * 0.001f,
mover.Adhesive( mover.RunningTrack.friction ),
( mover.SlippingWheels ? " (!)" : "" ),
// acceleration
mover.AccSVBased,
mover.AccN + 0.001f,
std::string( std::abs( mover.RunningShape.R ) > 10000.0 ? "~0" : to_string( mover.RunningShape.R, 0 ) ).c_str(),
// velocity
vehicle.GetVelocity(),
mover.DistCounter,
// position
vehicle.GetPosition().x,
vehicle.GetPosition().y,
vehicle.GetPosition().z );
ImGui::TextUnformatted(buffer.data());
}

16
widgets/vehicleparams.h Normal file
View File

@@ -0,0 +1,16 @@
#include "uilayer.h"
#include "translation.h"
#include "command.h"
namespace ui
{
class vehicleparams_panel : public ui_panel
{
std::string m_vehicle_name;
public:
vehicleparams_panel();
void render_contents() override;
};
} // namespace ui