16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 18:39:18 +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/popup.cpp"
"widgets/time.cpp"
"widgets/vehicleparams.cpp"
"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.Value1 << " "
<< mvOccupied->CommandIn.Value2 << " "
<< int(mvControlling->SecuritySystem.Status) << " "
<< int(mvControlling->SecuritySystem.is_blinking()) << " "
<< int(mvControlling->SlippingWheels) << " "
<< mvControlling->dizel_heat.Ts << " "
<< mvControlling->dizel_heat.To << " "
@@ -4231,17 +4231,9 @@ TController::UpdateSituation(double dt) {
// rozpoznaj komende bo lokomotywa jej nie rozpoznaje
RecognizeCommand(); // samo czyta komendę wstawioną do pojazdu?
}
if( mvOccupied->SecuritySystem.Status > 1 ) {
if( mvOccupied->SecuritySystem.is_blinking() ) {
// jak zadziałało CA/SHP
if( !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 );
}
}
mvOccupied->SecuritySystemReset(); // to skasuj
}
// basic emergency stop handling, while at it
if( ( true == mvOccupied->RadioStopFlag ) // radio-stop

View File

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

View File

@@ -78,6 +78,7 @@ zwiekszenie nacisku przy duzych predkosciach w hamulcach Oerlikona
*/
#include "dumb3d.h"
#include "utilities.h"
extern int ConversionError;
@@ -201,17 +202,6 @@ static int const dbrake_switch = 2;
static int const dbrake_reversal = 4;
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*/
enum sound {
none,
@@ -572,23 +562,43 @@ struct TMotorParameters
}
};
struct TSecuritySystem
class TSecuritySystem
{
int SystemType { 0 }; /*0: brak, 1: czuwak aktywny, 2: SHP/sygnalizacja kabinowa*/
double AwareDelay { -1.0 }; // czas powtarzania czuwaka
double AwareMinSpeed; // minimalna prędkość załączenia czuwaka, normalnie 10% Vmax
double SoundSignalDelay { -1.0 };
double EmergencyBrakeDelay { -1.0 };
int Status { 0 }; /*0: wylaczony, 1: wlaczony, 2: czuwak, 4: shp, 8: alarm, 16: hamowanie awaryjne*/
double SystemTimer { 0.0 };
double SystemSoundCATimer { 0.0 };
double SystemSoundSHPTimer { 0.0 };
double SystemBrakeCATimer { 0.0 };
double SystemBrakeSHPTimer { 0.0 };
double SystemBrakeCATestTimer { 0.0 }; // hunter-091012
int VelocityAllowed;
int NextVelocityAllowed; /*predkosc pokazywana przez sygnalizacje kabinowa*/
bool RadioStop; // czy jest RadioStop
bool vigilance_enabled = false;
bool cabsignal_enabled = false;
bool radiostop_enabled = false;
bool cabsignal_active = false;
bool pressed = false;
bool enabled = false;
bool is_sifa = false; // Sifa-like pedal device, with inverted input for convenient keyboard usage
double vigilance_timer = 0.0;
double alert_timer = 0.0;
double press_timer = 0.0;
double velocity = 0.0;
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
@@ -1372,8 +1382,7 @@ public:
bool Sandbox( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/
/*! zbijanie czuwaka/SHP*/
void SSReset(void);
bool SecuritySystemReset(void);
void SecuritySystemReset(void);
void SecuritySystemCheck(double dt);
bool BatterySwitch(bool State);
@@ -1516,7 +1525,6 @@ private:
void LoadFIZ_Cntrl( std::string const &line );
void LoadFIZ_Blending(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_Power( std::string const &Line );
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
// Obliczanie natężenie prądu w silnikach
@@ -362,20 +469,6 @@ ActiveCab( Cab )
RunningTraction.TractionFreq = 0.0;
RunningTraction.TractionMaxCurrent = 0.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,
@@ -2083,7 +2176,7 @@ bool TMoverParameters::CabActivisation(void)
{
CabNo = ActiveCab; // sterowanie jest z kabiny z obsadą
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);
}
return OK;
@@ -2103,7 +2196,7 @@ bool TMoverParameters::CabDeactivisation(void)
CabNo = 0;
DirAbsolute = ActiveDir * CabNo;
DepartureSignal = false; // nie buczeć z nieaktywnej kabiny
SecuritySystem.Status = 0; // deactivate alerter TODO: make it part of control based cab selection
SecuritySystem.set_enabled(false);
SendCtrlToNext("CabActivisation", 0, ActiveCab); // CabNo==0!
}
@@ -2181,58 +2274,18 @@ bool TMoverParameters::Sandbox( bool const State, range_t const Notify )
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
// zbicie czuwaka / SHP
// *****************************************************************************
// hunter-091012: rozbicie alarmow, dodanie testu czuwaka
bool TMoverParameters::SecuritySystemReset(void) // zbijanie czuwaka/SHP
void TMoverParameters::SecuritySystemReset(void) // zbijanie czuwaka/SHP
{
// zbijanie czuwaka/SHP
bool SSR = false;
// with SecuritySystem do
if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0))
{
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;
if (TrainType != dt_EZT && ActiveDir == 0)
return; // Ra 2014-03: w EZT nie trzeba ustawiać kierunku
SecuritySystem.acknowledge_press();
SecuritySystem.acknowledge_release();
}
// *************************************************************************************************
@@ -2241,83 +2294,12 @@ bool TMoverParameters::SecuritySystemReset(void) // zbijanie czuwaka/SHP
// *************************************************************************************************
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
// obsady
// 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
if (Battery) {
SecuritySystem.update(dt, Vel);
}
else if (!Battery)
else
{ // wyłączenie baterii deaktywuje sprzęt
RadiostopSwitch(false);
// SecuritySystem.Status = 0; //deaktywacja czuwaka
}
}
@@ -2339,10 +2321,7 @@ bool TMoverParameters::BatterySwitch(bool State)
SendCtrlToNext("BatterySwitch", 0, CabNo);
BS = true;
if ((Battery) && (ActiveCab != 0)) /*|| (TrainType==dt_EZT)*/
SecuritySystem.Status = (SecuritySystem.Status | s_waiting); // aktywacja czuwaka
else
SecuritySystem.Status = 0; // wyłączenie czuwaka
SecuritySystem.set_enabled((Battery) && (ActiveCab != 0));
return BS;
}
@@ -3569,19 +3548,12 @@ void TMoverParameters::UpdatePipePressure(double dt)
Pipe2->Flow(dpMainValve);
}
// ulepszony hamulec bezp.
if( ( true == RadioStopFlag )
|| ( true == AlarmChainFlag )
|| ( true == TestFlag( SecuritySystem.Status, s_SHPebrake ) )
|| ( 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 ) ) {
|| SecuritySystem.is_braking() ) {
dpMainValve = dpMainValve + PF( 0, PipePress, 0.15 ) * dt;
}
// 0.2*Spg
Pipe->Flow(-dpMainValve);
Pipe->Flow(-(PipePress)*0.001 * dt);
@@ -5047,7 +5019,7 @@ double TMoverParameters::TractionForce( double dt ) {
case TEngineType::ElectricInductionMotor:
{
if( true == Mains ) {
if( true == Mains && !SecuritySystem.is_engine_blocked() ) {
//tempomat
if (ScndCtrlPosNo > 1)
{
@@ -7747,7 +7719,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
{
startBPT = false;
fizlines.emplace( "Security", inputline );
LoadFIZ_Security( inputline );
SecuritySystem.load(inputline, Vmax);
continue;
}
@@ -8568,24 +8540,6 @@ void TMoverParameters::LoadFIZ_Light( std::string const &line ) {
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 ) {
HeatingPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "Heating", line ) );
@@ -9677,10 +9631,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
Battery = true;
else if ((CValue1 == 0))
Battery = false;
if ((Battery) && (ActiveCab != 0) /*or (TrainType=dt_EZT)*/)
SecuritySystem.Status = SecuritySystem.Status || s_waiting; // aktywacja czuwaka
else
SecuritySystem.Status = 0; // wyłączenie czuwaka
SecuritySystem.set_enabled(((Battery) && (ActiveCab != 0)));
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
// 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*/
{ // Ra: to powinno działać tylko w członie obsadzonym
if (/*(TrainType=dt_EZT)or*/ (ActiveCab != 0) && (Battery) &&
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);
}
SecuritySystem.set_cabsignal();
// else OK:=false;
OK = true; // true, gdy można usunąć komendę
}

109
Train.cpp
View File

@@ -486,8 +486,8 @@ dictionary_source *TTrain::GetTrainState() {
dict->insert( "brake_delay_flag", mvOccupied->BrakeDelayFlag );
dict->insert( "brake_op_mode_flag", mvOccupied->BrakeOpModeFlag );
// other controls
dict->insert( "ca", TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) );
dict->insert( "shp", TestFlag( mvOccupied->SecuritySystem.Status, s_active ) );
dict->insert( "ca", mvOccupied->SecuritySystem.is_vigilance_blinking() );
dict->insert( "shp", mvOccupied->SecuritySystem.is_cabsignal_blinking() );
dict->insert( "pantpress", std::abs( mvControlled->PantPress ) );
dict->insert( "universal3", InstrumentLightActive );
dict->insert( "radio_channel", iRadioChannel );
@@ -612,7 +612,7 @@ TTrain::get_state() const {
btLampkaOgrzewanieSkladu.GetValue(),
btHaslerBrakes.GetValue(),
btHaslerCurrent.GetValue(),
( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ),
mvOccupied->SecuritySystem.is_blinking(),
btLampkaHVoltageB.GetValue(),
fTachoVelocity,
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 ) {
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 ) {
// visual feedback
Train->ggSecurityResetButton.UpdateValue( 1.0, Train->dsbSwitch );
if( Train->CAflag == false ) {
Train->CAflag = true;
Train->mvOccupied->SecuritySystemReset();
}
Train->mvOccupied->SecuritySystem.acknowledge_press();
}
else if( Command.action == GLFW_RELEASE ) {
// visual feedback
Train->ggSecurityResetButton.UpdateValue( 0.0 );
Train->fCzuwakTestTimer = 0.0f;
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;
Train->mvOccupied->SecuritySystem.acknowledge_release();
}
}
@@ -1666,11 +1660,7 @@ void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command
if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->SetLights();
}
if( TestFlag( Train->mvOccupied->SecuritySystem.SystemType, 2 ) ) {
// Ra: znowu w kabinie jest coś, co być nie powinno!
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_active );
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_SHPalarm );
}
Train->mvOccupied->SecuritySystem.set_enabled(true); // Ra: znowu w kabinie jest coś, co być nie powinno!
}
}
}
@@ -5449,36 +5439,23 @@ bool TTrain::Update( double const Deltatime )
}
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
if( mvOccupied->SecuritySystem.Status > 0 ) {
if( mvOccupied->SecuritySystem.is_vigilance_blinking() ) {
if( fBlinkTimer > fCzuwakBlink )
fBlinkTimer = -fCzuwakBlink;
else
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
else {
btLampkaCzuwaka.Turn( false );
}
btLampkaSHP.Turn( TestFlag( mvOccupied->SecuritySystem.Status, s_active ) );
}
else // wylaczone
{
btLampkaCzuwaka.Turn( false );
if (mvOccupied->SecuritySystem.is_cabsignal_blinking())
btLampkaSHP.Turn( true );
else
btLampkaSHP.Turn( false );
}
btLampkaWylSzybki.Turn(
( ( (m_linebreakerstate == 2)
@@ -6098,13 +6075,9 @@ bool TTrain::Update( double const Deltatime )
*/
// screens
fScreenTimer += Deltatime;
if( ( fScreenTimer > Global.PythonScreenUpdateRate * 0.001f )
&& !FreeFlyModeFlag && simulation::Train == this ) { // don't bother if we're outside
fScreenTimer = 0.f;
for( auto const &screen : m_screens ) {
Application.request( { std::get<0>(screen), GetTrainState(), std::get<1>(screen) } );
}
}
if (!FreeFlyModeFlag && simulation::Train == this) // don't bother if we're outside
update_screens();
// sounds
update_sounds( Deltatime );
@@ -6299,10 +6272,8 @@ TTrain::update_sounds( double const Deltatime ) {
}
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if (mvOccupied->SecuritySystem.Status > 0) {
if (mvOccupied->SecuritySystem.is_beeping()) {
// hunter-091012: rozdzielenie alarmow
if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm )
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
if( false == dsbBuzzer.is_playing() ) {
dsbBuzzer
@@ -6319,16 +6290,6 @@ TTrain::update_sounds( double const Deltatime ) {
dsbBuzzer.stop();
#ifdef _WIN32
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
#endif
}
}
}
else {
// wylaczone
if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop();
#ifdef _WIN32
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
#endif
}
}
@@ -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)
{ // McZapkie-090902: zmiana kabiny 1->0->2 i z powrotem
if( ( DynamicObject->Mechanik == nullptr )
@@ -6893,16 +6862,16 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
tex->create();
// record renderer and material binding for future update requests
m_screens.emplace_back(
( substr_path(renderername).empty() ? // supply vehicle folder as path if none is provided
const std::string rendererpath {
substr_path(renderername).empty() ? // supply vehicle folder as path if none is provided
DynamicObject->asBaseDir + renderername :
renderername ),
tex->id,
nullptr);
renderername };
// record renderer and material binding for future update requests
m_screens.emplace_back(rendererpath, tex->id, nullptr);
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);
} 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 ) };
}
const TTrain::screen_map& TTrain::get_screens() {
update_screens();
return m_screens;
}
void
TTrain::radio_message( sound_source *Message, int const Channel ) {
@@ -8295,8 +8269,7 @@ std::array<float, 3> TTrain::get_current()
bool TTrain::get_alarm()
{
return (TestFlag(mvOccupied->SecuritySystem.Status, s_CAalarm) ||
TestFlag(mvOccupied->SecuritySystem.Status, s_SHPalarm));
return mvOccupied->SecuritySystem.is_beeping();
}
void TTrain::set_mainctrl(int pos)

View File

@@ -98,6 +98,8 @@ class TTrain
float hv_voltage;
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
bool CabChange(int iDirection);
@@ -151,6 +153,7 @@ class TTrain
void update_sounds( double const Deltatime );
void update_sounds_runningnoise( sound_source &Sound );
void update_sounds_radio();
void update_screens();
// 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
@@ -632,11 +635,8 @@ private:
float fHaslerTimer;
float fConverterTimer; // hunter-261211: dla przekaznika
float fMainRelayTimer; // hunter-141211: zalaczanie WSa z opoznieniem
float fCzuwakTestTimer; // hunter-091012: do testu czuwaka
float fScreenTimer { 0.f };
bool CAflag { false }; // hunter-131211: dla osobnego zbijania CA i SHP
// McZapkie-240302 - przyda sie do tachometru
float fTachoVelocity{ 0.0f };
float fTachoVelocityJump{ 0.0f }; // ze skakaniem
@@ -665,7 +665,7 @@ private:
bool m_mastercontrollerinuse { false };
float m_mastercontrollerreturndelay { 0.f };
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 };
public:
@@ -686,6 +686,7 @@ private:
// checks whether specified point is within boundaries of the active cab
bool point_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_tank_pressure();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -63,7 +63,8 @@ float ui::map_panel::get_vehicle_rotation()
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;
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)
{
const gfx::geometrybank_handle handle = section->get_map_geometry();
if (handle != null_handle) {
if (handle != null_handle)
{
m_section_handles.push_back(handle);
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)
{
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)
continue;
@@ -147,14 +150,13 @@ void ui::map_panel::render_labels(glm::mat4 transform, ImVec2 origin, glm::vec2
TDynamicObject *veh = vehicle;
ImVec2 textsize = ImGui::CalcTextSize(label.c_str());
ImGui::SetCursorPos(ImVec2(origin.x + gui_pos.x - textsize.x / 2.0f,
origin.y + gui_pos.y - textsize.y / 2.0f));
ImGui::SetCursorPos(ImVec2(origin.x + gui_pos.x - textsize.x / 2.0f, origin.y + gui_pos.y - textsize.y / 2.0f));
ImGui::TextUnformatted(label.c_str());
}
ImGui::PopStyleColor();
if (zoom > 0.005f) {
if (zoom > 0.005f)
{
}
}
@@ -179,14 +181,12 @@ void ui::map_panel::render_contents()
glm::mat4 transform;
transform[0][0] = -1.0f;
static enum {
MODE_MANUAL = 0,
MODE_CAMERA,
MODE_VEHICLE
} mode = MODE_MANUAL;
static enum { MODE_MANUAL = 0, MODE_CAMERA, MODE_VEHICLE } mode = MODE_MANUAL;
ImGui::RadioButton("manual", (int*)&mode, 0); ImGui::SameLine();
ImGui::RadioButton("cam", (int*)&mode, 1); ImGui::SameLine();
ImGui::RadioButton("manual", (int *)&mode, 0);
ImGui::SameLine();
ImGui::RadioButton("cam", (int *)&mode, 1);
ImGui::SameLine();
ImGui::RadioButton("vehicle", (int *)&mode, 2);
ImVec2 surface_size_im = ImGui::GetContentRegionAvail();
@@ -235,7 +235,8 @@ void ui::map_panel::render_contents()
if (ImGui::IsItemHovered())
{
if (mode == 0 && ImGui::IsMouseDragging(0)) {
if (mode == 0 && ImGui::IsMouseDragging(0))
{
ImVec2 delta_im = ImGui::GetMouseDragDelta();
ImGui::ResetMouseDragDelta();
@@ -245,27 +246,30 @@ void ui::map_panel::render_contents()
translate -= delta * 2.0f;
}
else {
else
{
ImVec2 screen_pos = ImGui::GetMousePos();
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::vec3 world_pos = glm::inverse(transform) * glm::vec4(ndc_pos.x, 0.0f, -ndc_pos.y, 1.0f);
map::sorted_object_list objects =
map::Objects.find_in_range(glm::vec3(world_pos.x, NAN, world_pos.z), 0.03f / zoom);
map::sorted_object_list objects = 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)
register_popup(std::make_unique<ui::disambiguation_popup>(*this, std::move(objects)));
else if (objects.size() == 1)
handle_map_object_click(*this, objects.begin()->second);
else {
else
{
glm::vec3 nearest = simulation::Region->find_nearest_track_point(world_pos);
if (!glm::isnan(nearest.x) && glm::distance(world_pos, nearest) < (0.03f / zoom))
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);
}
}
@@ -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)
{
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)));
}
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)));
}
}
@@ -288,12 +294,15 @@ void ui::handle_map_object_hover(std::shared_ptr<map::map_object> &obj)
{
ImGui::BeginTooltip();
if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj)) {
for (auto &model : sem->models) {
if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj))
{
for (auto &model : sem->models)
{
ImGui::PushID(model);
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
auto state = model->LightGet(i);
if (!state)
@@ -314,20 +323,22 @@ void ui::handle_map_object_hover(std::shared_ptr<map::map_object> &obj)
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::EndTooltip();
}
ui::disambiguation_popup::disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list)
: popup(panel), m_list(list) { }
ui::disambiguation_popup::disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list) : popup(panel), m_list(list) {}
void ui::disambiguation_popup::render_content()
{
for (auto &item : m_list) {
if (ImGui::Button(item.second->name.c_str())) {
for (auto &item : m_list)
{
if (ImGui::Button(item.second->name.c_str()))
{
ImGui::CloseCurrentPopup();
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)
: popup(panel), m_sem(sem) { }
ui::semaphore_window::semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem) : popup(panel), m_sem(sem) {}
void ui::semaphore_window::render_content()
{
for (auto &model : m_sem->models) {
for (auto &model : m_sem->models)
{
ImGui::PushID(model);
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
auto state = model->LightGet(i);
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));
std::string res = " ##" + std::to_string(i);
if (ImGui::Button(res.c_str())) {
if (ImGui::Button(res.c_str()))
{
level += 1.0f;
if (level >= 3.0f)
level = 0.0f;
@@ -378,7 +391,8 @@ void ui::semaphore_window::render_content()
ImGui::Separator();
for (auto &item : m_sem->events) {
for (auto &item : m_sem->events)
{
std::string displayname = item->name().substr(m_sem->name.size());
if (displayname.size() < 2)
@@ -386,38 +400,40 @@ void ui::semaphore_window::render_content()
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);
}
}
}
ui::switch_window::switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw)
: popup(panel), m_switch(sw) { }
ui::switch_window::switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw) : popup(panel), m_switch(sw) {}
void ui::switch_window::render_content()
{
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);
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);
ImGui::CloseCurrentPopup();
}
}
ui::obstacle_window::obstacle_window(ui_panel &panel, glm::dvec3 const &pos)
: popup(panel), m_position(pos)
ui::obstacle_window::obstacle_window(ui_panel &panel, glm::dvec3 const &pos) : popup(panel), m_position(pos)
{
std::ifstream file;
file.open("obstaclebank.txt", std::ios_base::in | std::ios_base::binary);
std::string line;
while (std::getline(file, line)) {
while (std::getline(file, line))
{
std::istringstream entry(line);
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()
{
ImGui::TextUnformatted(LOC_STR(map_obstacle_insert));
for (auto const &entry : m_obstacles) {
if (ImGui::Button(entry.first.c_str())) {
for (auto const &entry : m_obstacles)
{
if (ImGui::Button(entry.first.c_str()))
{
std::string name("obstacle_" + std::to_string(LocalRandom(0.0, 100000.0)));
TAnimModel *cloned = simulation::State.create_model(entry.second, name, m_position);
ImGui::CloseCurrentPopup();

View File

@@ -7,9 +7,11 @@
#include "widgets/map_objects.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;
public:
@@ -18,7 +20,8 @@ public:
virtual void render_content() override;
};
class semaphore_window : public popup {
class semaphore_window : public popup
{
std::shared_ptr<map::semaphore> m_sem;
command_relay m_relay;
@@ -28,7 +31,8 @@ public:
virtual void render_content() override;
};
class switch_window : public popup {
class switch_window : public popup
{
std::shared_ptr<map::track_switch> m_switch;
command_relay m_relay;
@@ -38,7 +42,8 @@ public:
virtual void render_content() override;
};
class obstacle_window : public popup {
class obstacle_window : public popup
{
glm::dvec3 m_position;
std::vector<std::pair<std::string, std::string>> m_obstacles;
@@ -48,7 +53,8 @@ public:
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::framebuffer> m_msaa_fb;
std::unique_ptr<gl::renderbuffer> m_msaa_rb;
@@ -81,4 +87,4 @@ public:
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);
}
} // 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;
for (auto const entry : entries) {
for (auto const entry : entries)
{
glm::vec3 entry_location = entry->location;
glm::vec3 search_point = from;
if (glm::isnan(from.y)) {
if (glm::isnan(from.y))
{
entry_location.y = 0.0f;
search_point.y = 0.0f;
}
float dist = glm::distance2(entry_location, search_point);
if (dist < max_distance2) {
if (dist < max_distance2)
{
items.emplace(dist, std::move(entry));
}
}

View File

@@ -4,9 +4,11 @@
#include "Event.h"
#include "scene.h"
namespace map {
namespace map
{
struct map_object {
struct map_object
{
std::string name;
glm::vec3 location;
@@ -17,19 +19,22 @@ namespace map {
using sorted_object_list = std::map<float, std::shared_ptr<map::map_object>>;
// semaphore description (only for minimap purposes)
struct semaphore : public map_object {
struct semaphore : public map_object
{
std::vector<TAnimModel *> models;
std::vector<basic_event *> events;
};
// 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;
};
struct objects {
struct objects
{
std::vector<std::shared_ptr<map_object>> entries;
// returns objects in range from vec3, NaN in Y ignores it
@@ -37,4 +42,4 @@ namespace map {
};
extern objects Objects;
}
} // namespace map

View File

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

View File

@@ -2,9 +2,11 @@
class ui_panel;
namespace ui {
namespace ui
{
class popup {
class popup
{
std::string m_id;
static int id;
@@ -19,4 +21,4 @@ protected:
virtual void render_content() = 0;
};
}
} // namespace ui

View File

@@ -3,8 +3,7 @@
#include "simulationtime.h"
#include "Globals.h"
ui::time_panel::time_panel()
: ui_panel(LOC_STR(time_window), false)
ui::time_panel::time_panel() : ui_panel(LOC_STR(time_window), false)
{
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_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::setweather, fog, overcast, 1, 0);
m_relay.post(user_command::settemperature, temperature, 0.0, 1, 0);

View File

@@ -2,8 +2,10 @@
#include "translation.h"
#include "command.h"
namespace ui {
class time_panel : public ui_panel {
namespace ui
{
class time_panel : public ui_panel
{
command_relay m_relay;
float time;
@@ -18,4 +20,4 @@ namespace ui {
void render_contents() override;
void open();
};
}
} // namespace ui

View File

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

View File

@@ -1,10 +1,12 @@
#include "uilayer.h"
namespace ui {
class vehiclelist_panel : public ui_panel {
namespace ui
{
class vehiclelist_panel : public ui_panel
{
public:
vehiclelist_panel() : ui_panel("Vehicle list", true) {}
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