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

build 200608. model texture change event, whois event enhancement, optional track friction modifier, three state headlight visualization, three state coupler visualizaion, vehicle light activation fix

This commit is contained in:
tmj-fstate
2020-06-08 16:13:18 +02:00
parent 03561b11d8
commit 8bb5554b20
14 changed files with 450 additions and 183 deletions

View File

@@ -42,7 +42,34 @@ class TAirCoupler
bxOn = true; bxOn = true;
Update(); Update();
}; };
// inline bool Active() { if ((pModelOn)||(pModelOff)) return true; return false;}; // if the xOn model is missing, activate plain On instead
inline void TurnxOnWithOnAsFallback()
{
if( pModelxOn != nullptr ) {
bOn = false;
bxOn = true;
Update();
}
else {
TurnOn();
}
};
// if the xOn model is missing, activate plain Off instead
inline void TurnxOnWithOffAsFallback()
{
if( pModelxOn != nullptr ) {
bOn = false;
bxOn = true;
Update();
}
else {
TurnOff();
}
};
inline bool Active() const
{
return ( ( pModelOn != nullptr ) || ( pModelxOn != nullptr ) );
};
int GetStatus(); int GetStatus();
void Init(std::string const &asName, TModel3d *pModel); void Init(std::string const &asName, TModel3d *pModel);
void Load(cParser *Parser, TModel3d *pModel); void Load(cParser *Parser, TModel3d *pModel);

View File

@@ -861,6 +861,11 @@ void TAnimModel::LightSet(int const n, float const v)
lsLights[ n ] = v; lsLights[ n ] = v;
}; };
void TAnimModel::SkinSet( int const Index, material_handle const Material ) {
m_materialdata.replacable_skins[ clamp( Index, 1, 4 ) ] = Material;
}
void TAnimModel::AnimUpdate(double dt) void TAnimModel::AnimUpdate(double dt)
{ // wykonanie zakolejkowanych animacji, nawet gdy modele nie są aktualnie wyświetlane { // wykonanie zakolejkowanych animacji, nawet gdy modele nie są aktualnie wyświetlane
TAnimContainer *p = TAnimModel::acAnimList; TAnimContainer *p = TAnimModel::acAnimList;

View File

@@ -140,6 +140,7 @@ public:
TAnimContainer * AddContainer(std::string const &Name); TAnimContainer * AddContainer(std::string const &Name);
TAnimContainer * GetContainer(std::string const &Name = ""); TAnimContainer * GetContainer(std::string const &Name = "");
void LightSet( int const n, float const v ); void LightSet( int const n, float const v );
void SkinSet( int const Index, material_handle const Material );
void AnimationVND( void *pData, double a, double b, double c, double d ); void AnimationVND( void *pData, double a, double b, double c, double d );
int TerrainCount(); int TerrainCount();
TSubModel * TerrainSquare(int n); TSubModel * TerrainSquare(int n);

View File

@@ -7307,13 +7307,13 @@ void TController::TakeControl( bool const Aidriver, bool const Forcevehiclecheck
} }
else { else {
// jeśli nic nie robi // jeśli nic nie robi
if( pVehicle->iLights[ ( mvOccupied->CabActive < 0 ? if( pVehicle->MoverParameters->iLights[ ( mvOccupied->CabActive < 0 ?
end::rear : end::rear :
end::front ) ] end::front ) ]
& ( light::headlight_left | light::headlight_right | light::headlight_upper ) ) // któreś ze świateł zapalone? & ( light::headlight_left | light::headlight_right | light::headlight_upper ) ) // któreś ze świateł zapalone?
{ // od wersji 357 oczekujemy podania komend dla AI przez scenerię { // od wersji 357 oczekujemy podania komend dla AI przez scenerię
OrderNext( Prepare_engine ); OrderNext( Prepare_engine );
if( pVehicle->iLights[ mvOccupied->CabActive < 0 ? end::rear : end::front ] & light::headlight_upper ) // górne światło zapalone if( pVehicle->MoverParameters->iLights[ mvOccupied->CabActive < 0 ? end::rear : end::front ] & light::headlight_upper ) // górne światło zapalone
OrderNext( Obey_train ); // jazda pociągowa OrderNext( Obey_train ); // jazda pociągowa
else else
OrderNext( Shunt ); // jazda manewrowa OrderNext( Shunt ); // jazda manewrowa

View File

@@ -748,25 +748,41 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
// ABu011104: liczenie obrotow wozkow // ABu011104: liczenie obrotow wozkow
ABuBogies(); ABuBogies();
// Mczapkie-100402: rysowanie lub nie - sprzegow // Mczapkie-100402: rysowanie lub nie - sprzegow
// ABu-240105: Dodatkowy warunek: if (...).Render, zeby rysowal tylko // ABu-240105: Dodatkowy warunek: if (...).Render, zeby rysowal tylko jeden z polaczonych sprzegow
// jeden // display _on if connected with another vehicle and the coupling owner (render flag)
// z polaczonych sprzegow // display _xon if connected with another vehicle and not the coupling owner
if ((false == MoverParameters->Couplers[ end::front ].has_adapter()) && // display _xon if not connected, but equipped with coupling adapter
(TestFlag(MoverParameters->Couplers[end::front].CouplingFlag, ctrain_coupler)) && // display _off if not connected, not equipped with coupling adapter or if _xon model is missing
(MoverParameters->Couplers[end::front].Render)) if( TestFlag( MoverParameters->Couplers[ end::front ].CouplingFlag, coupling::coupler ) ) {
{ if( MoverParameters->Couplers[ end::front ].Render ) {
btCoupler1.Turn( true ); btCoupler1.TurnOn();
}
else {
btCoupler1.TurnxOnWithOffAsFallback();
}
btnOn = true; btnOn = true;
} }
// else btCoupler1.TurnOff(); else {
if ((false == MoverParameters->Couplers[ end::rear ].has_adapter()) && if( true == MoverParameters->Couplers[ end::front ].has_adapter() ) {
(TestFlag(MoverParameters->Couplers[end::rear].CouplingFlag, ctrain_coupler)) && btCoupler1.TurnxOnWithOffAsFallback();
(MoverParameters->Couplers[end::rear].Render)) btnOn = true;
{ }
btCoupler2.Turn( true ); }
if( TestFlag( MoverParameters->Couplers[ end::rear ].CouplingFlag, coupling::coupler ) ) {
if( MoverParameters->Couplers[ end::rear ].Render ) {
btCoupler2.TurnOn();
}
else {
btCoupler2.TurnxOnWithOffAsFallback();
}
btnOn = true; btnOn = true;
} }
// else btCoupler2.TurnOff(); else {
if( true == MoverParameters->Couplers[ end::rear ].has_adapter() ) {
btCoupler2.TurnxOnWithOffAsFallback();
btnOn = true;
}
}
//******************************************************************************** //********************************************************************************
// przewody powietrzne j.w., ABu: decyzja czy rysowac tylko na podstawie // przewody powietrzne j.w., ABu: decyzja czy rysowac tylko na podstawie
// 'render' - juz // 'render' - juz
@@ -960,7 +976,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
{ // sygnaly konca pociagu { // sygnaly konca pociagu
if (btEndSignals1.Active()) if (btEndSignals1.Active())
{ {
if (TestFlag(iLights[0], 2) || TestFlag(iLights[0], 32)) if (TestFlag(MoverParameters->iLights[0], 2) || TestFlag(MoverParameters->iLights[0], 32))
{ {
btEndSignals1.Turn( true ); btEndSignals1.Turn( true );
btnOn = true; btnOn = true;
@@ -969,13 +985,13 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
} }
else else
{ {
if (TestFlag(iLights[0], 2)) if (TestFlag(MoverParameters->iLights[0], 2))
{ {
btEndSignals11.Turn( true ); btEndSignals11.Turn( true );
btnOn = true; btnOn = true;
} }
// else btEndSignals11.TurnOff(); // else btEndSignals11.TurnOff();
if (TestFlag(iLights[0], 32)) if (TestFlag(MoverParameters->iLights[0], 32))
{ {
btEndSignals13.Turn( true ); btEndSignals13.Turn( true );
btnOn = true; btnOn = true;
@@ -984,7 +1000,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
} }
if (btEndSignals2.Active()) if (btEndSignals2.Active())
{ {
if (TestFlag(iLights[1], 2) || TestFlag(iLights[1], 32)) if (TestFlag(MoverParameters->iLights[1], 2) || TestFlag(MoverParameters->iLights[1], 32))
{ {
btEndSignals2.Turn( true ); btEndSignals2.Turn( true );
btnOn = true; btnOn = true;
@@ -993,13 +1009,13 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
} }
else else
{ {
if (TestFlag(iLights[1], 2)) if (TestFlag(MoverParameters->iLights[1], 2))
{ {
btEndSignals21.Turn( true ); btEndSignals21.Turn( true );
btnOn = true; btnOn = true;
} }
// else btEndSignals21.TurnOff(); // else btEndSignals21.TurnOff();
if (TestFlag(iLights[1], 32)) if (TestFlag(MoverParameters->iLights[1], 32))
{ {
btEndSignals23.Turn( true ); btEndSignals23.Turn( true );
btnOn = true; btnOn = true;
@@ -1008,13 +1024,13 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
} }
} }
// tablice blaszane: // tablice blaszane:
if (TestFlag(iLights[end::front], light::rearendsignals)) if (TestFlag(MoverParameters->iLights[end::front], light::rearendsignals))
{ {
btEndSignalsTab1.Turn( true ); btEndSignalsTab1.Turn( true );
btnOn = true; btnOn = true;
} }
// else btEndSignalsTab1.TurnOff(); // else btEndSignalsTab1.TurnOff();
if (TestFlag(iLights[end::rear], light::rearendsignals)) if (TestFlag(MoverParameters->iLights[end::rear], light::rearendsignals))
{ {
btEndSignalsTab2.Turn( true ); btEndSignalsTab2.Turn( true );
btnOn = true; btnOn = true;
@@ -1060,42 +1076,67 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
{ // sygnały czoła pociagu //Ra: wyświetlamy bez { // sygnały czoła pociagu //Ra: wyświetlamy bez
// ograniczeń odległości, by były widoczne z // ograniczeń odległości, by były widoczne z
// daleka // daleka
if (TestFlag(iLights[0], 1)) if (TestFlag(MoverParameters->iLights[end::front], light::headlight_left))
{ {
btHeadSignals11.Turn( true ); if( DimHeadlights ) {
btHeadSignals11.TurnxOnWithOnAsFallback();
}
else {
btHeadSignals11.TurnOn();
}
btnOn = true; btnOn = true;
} }
// else btHeadSignals11.TurnOff(); if (TestFlag(MoverParameters->iLights[end::front], light::headlight_upper))
if (TestFlag(iLights[0], 4))
{ {
btHeadSignals12.Turn( true ); if( DimHeadlights ) {
btHeadSignals12.TurnxOnWithOnAsFallback();
}
else {
btHeadSignals12.TurnOn();
}
btnOn = true; btnOn = true;
} }
// else btHeadSignals12.TurnOff(); if (TestFlag(MoverParameters->iLights[end::front], light::headlight_right))
if (TestFlag(iLights[0], 16))
{ {
btHeadSignals13.Turn( true ); if( DimHeadlights ) {
btHeadSignals13.TurnxOnWithOnAsFallback();
}
else {
btHeadSignals13.TurnOn();
}
btnOn = true; btnOn = true;
} }
// else btHeadSignals13.TurnOff(); // else btHeadSignals13.TurnOff();
if (TestFlag(iLights[1], 1)) if (TestFlag(MoverParameters->iLights[end::rear], light::headlight_left))
{ {
btHeadSignals21.Turn( true ); if( DimHeadlights ) {
btHeadSignals21.TurnxOnWithOnAsFallback();
}
else {
btHeadSignals21.TurnOn();
}
btnOn = true; btnOn = true;
} }
// else btHeadSignals21.TurnOff(); if (TestFlag(MoverParameters->iLights[end::rear], light::headlight_upper))
if (TestFlag(iLights[1], 4))
{ {
btHeadSignals22.Turn( true ); if( DimHeadlights ) {
btHeadSignals22.TurnxOnWithOnAsFallback();
}
else {
btHeadSignals22.TurnOn();
}
btnOn = true; btnOn = true;
} }
// else btHeadSignals22.TurnOff(); if (TestFlag(MoverParameters->iLights[end::rear], light::headlight_right))
if (TestFlag(iLights[1], 16))
{ {
btHeadSignals23.Turn( true ); if( DimHeadlights ) {
btHeadSignals23.TurnxOnWithOnAsFallback();
}
else {
btHeadSignals23.TurnOn();
}
btnOn = true; btnOn = true;
} }
// else btHeadSignals23.TurnOff();
} }
// interior light levels // interior light levels
auto sectionlightcolor { glm::vec4( 1.f ) }; auto sectionlightcolor { glm::vec4( 1.f ) };
@@ -1764,7 +1805,6 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
*/ */
// utworzenie parametrów fizyki // utworzenie parametrów fizyki
MoverParameters = new TMoverParameters(iDirection ? fVel : -fVel, Type_Name, asName, Cab); MoverParameters = new TMoverParameters(iDirection ? fVel : -fVel, Type_Name, asName, Cab);
iLights = MoverParameters->iLights; // wskaźnik na stan własnych świateł
// McZapkie: TypeName musi byc nazwą CHK/MMD pojazdu // McZapkie: TypeName musi byc nazwą CHK/MMD pojazdu
if (!MoverParameters->LoadFIZ(asBaseDir)) if (!MoverParameters->LoadFIZ(asBaseDir))
{ // jak wczytanie CHK się nie uda, to błąd { // jak wczytanie CHK się nie uda, to błąd
@@ -2072,8 +2112,8 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
erase_extension( asReplacableSkin ); erase_extension( asReplacableSkin );
LoadMMediaFile(Type_Name, asReplacableSkin); LoadMMediaFile(Type_Name, asReplacableSkin);
// McZapkie-100402: wyszukiwanie submodeli sprzegów // McZapkie-100402: wyszukiwanie submodeli sprzegów
btCoupler1.Init( "coupler1", mdModel, false ); // false - ma być wyłączony btCoupler1.Init( "coupler1", mdModel ); // false - ma być wyłączony
btCoupler2.Init( "coupler2", mdModel, false); btCoupler2.Init( "coupler2", mdModel );
// brake hoses // brake hoses
btCPneumatic1.Init("cpneumatic1", mdModel); btCPneumatic1.Init("cpneumatic1", mdModel);
btCPneumatic2.Init("cpneumatic2", mdModel); btCPneumatic2.Init("cpneumatic2", mdModel);
@@ -2110,12 +2150,12 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
iInventory[ end::rear ] |= btEndSignals2.Active() ? ( light::redmarker_left | light::redmarker_right ) : 0; iInventory[ end::rear ] |= btEndSignals2.Active() ? ( light::redmarker_left | light::redmarker_right ) : 0;
iInventory[ end::rear ] |= btEndSignalsTab2.Active() ? light::rearendsignals : 0; iInventory[ end::rear ] |= btEndSignalsTab2.Active() ? light::rearendsignals : 0;
// ABu Uwaga! tu zmienic w modelu! // ABu Uwaga! tu zmienic w modelu!
btHeadSignals11.Init( "headlamp13", mdModel, false); // lewe btHeadSignals11.Init( "headlamp13", mdModel); // lewe
btHeadSignals12.Init( "headlamp11", mdModel, false); // górne btHeadSignals12.Init( "headlamp11", mdModel); // górne
btHeadSignals13.Init( "headlamp12", mdModel, false); // prawe btHeadSignals13.Init( "headlamp12", mdModel); // prawe
btHeadSignals21.Init( "headlamp23", mdModel, false); btHeadSignals21.Init( "headlamp23", mdModel);
btHeadSignals22.Init( "headlamp21", mdModel, false); btHeadSignals22.Init( "headlamp21", mdModel);
btHeadSignals23.Init( "headlamp22", mdModel, false); btHeadSignals23.Init( "headlamp22", mdModel);
iInventory[ end::front ] |= btHeadSignals11.Active() ? light::headlight_left : 0; iInventory[ end::front ] |= btHeadSignals11.Active() ? light::headlight_left : 0;
iInventory[ end::front ] |= btHeadSignals12.Active() ? light::headlight_upper : 0; iInventory[ end::front ] |= btHeadSignals12.Active() ? light::headlight_upper : 0;
iInventory[ end::front ] |= btHeadSignals13.Active() ? light::headlight_right : 0; iInventory[ end::front ] |= btHeadSignals13.Active() ? light::headlight_right : 0;
@@ -2877,7 +2917,7 @@ bool TDynamicObject::Update(double dt, double dt1)
// TTrackParam tp; // TTrackParam tp;
tp.Width = MyTrack->fTrackWidth; tp.Width = MyTrack->fTrackWidth;
// McZapkie-250202 // McZapkie-250202
tp.friction = MyTrack->fFriction * Global.fFriction * Global.FrictionWeatherFactor; tp.friction = MyTrack->Friction() * Global.fFriction * Global.FrictionWeatherFactor;
tp.CategoryFlag = MyTrack->iCategoryFlag & 15; tp.CategoryFlag = MyTrack->iCategoryFlag & 15;
tp.DamageFlag = MyTrack->iDamageFlag; tp.DamageFlag = MyTrack->iDamageFlag;
tp.QualityFlag = MyTrack->iQualityFlag; tp.QualityFlag = MyTrack->iQualityFlag;
@@ -3928,8 +3968,8 @@ void TDynamicObject::TurnOff()
{ // wyłączenie rysowania submodeli zmiennych dla { // wyłączenie rysowania submodeli zmiennych dla
// egemplarza pojazdu // egemplarza pojazdu
btnOn = false; btnOn = false;
btCoupler1.Turn( false ); btCoupler1.TurnOff();
btCoupler2.Turn( false ); btCoupler2.TurnOff();
btCPneumatic1.TurnOff(); btCPneumatic1.TurnOff();
btCPneumatic1r.TurnOff(); btCPneumatic1r.TurnOff();
btCPneumatic2.TurnOff(); btCPneumatic2.TurnOff();
@@ -3950,12 +3990,12 @@ void TDynamicObject::TurnOff()
btEndSignals2.Turn( false ); btEndSignals2.Turn( false );
btEndSignalsTab1.Turn( false ); btEndSignalsTab1.Turn( false );
btEndSignalsTab2.Turn( false ); btEndSignalsTab2.Turn( false );
btHeadSignals11.Turn( false ); btHeadSignals11.TurnOff();
btHeadSignals12.Turn( false ); btHeadSignals12.TurnOff();
btHeadSignals13.Turn( false ); btHeadSignals13.TurnOff();
btHeadSignals21.Turn( false ); btHeadSignals21.TurnOff();
btHeadSignals22.Turn( false ); btHeadSignals22.TurnOff();
btHeadSignals23.Turn( false ); btHeadSignals23.TurnOff();
btMechanik1.Turn( false ); btMechanik1.Turn( false );
btMechanik2.Turn( false ); btMechanik2.Turn( false );
btShutters1.Turn( false ); btShutters1.Turn( false );
@@ -6308,32 +6348,21 @@ void TDynamicObject::Damage(char flag)
void TDynamicObject::SetLights() { void TDynamicObject::SetLights() {
TDynamicObject *p = GetFirstDynamic(MoverParameters->CabOccupied < 0 ? 1 : 0, 4); auto const isfrontcaboccupied { MoverParameters->CabOccupied * DirectionGet() >= 0 };
bool kier = (DirectionGet() * MoverParameters->CabOccupied > 0); int const front { ( isfrontcaboccupied ? end::front : end::rear ) };
int xs = (kier ? 0 : 1); int const rear { 1 - front };
if (kier ? p->NextC(1) : p->PrevC(1)) // jesli jest nastepny, to tylko przod auto const lightpos { MoverParameters->LightsPos - 1 };
{ auto const frontlights { MoverParameters->Lights[ front ][ lightpos ] };
p->RaLightsSet(MoverParameters->Lights[xs][MoverParameters->LightsPos - 1] * (1 - xs), auto const rearlights { MoverParameters->Lights[ rear ][ lightpos ] };
MoverParameters->Lights[1 - xs][MoverParameters->LightsPos - 1] * xs); auto *vehicle { GetFirstDynamic( MoverParameters->CabOccupied >= 0 ? end::front : end::rear, coupling::control ) };
p = (kier ? p->NextC(4) : p->PrevC(4)); while( vehicle != nullptr ) {
while (p) // set lights on given side if there's no coupling with another vehicle, turn them off otherwise
{ auto const *frontvehicle { ( isfrontcaboccupied ? vehicle->PrevC( coupling::coupler ) : vehicle->NextC( coupling::coupler ) ) };
if (kier ? p->NextC(1) : p->PrevC(1)) auto const *rearvehicle { ( isfrontcaboccupied ? vehicle->NextC( coupling::coupler ) : vehicle->PrevC( coupling::coupler ) ) };
{ vehicle->RaLightsSet(
p->RaLightsSet(0, 0); ( frontvehicle == nullptr ? frontlights : 0 ),
} ( rearvehicle == nullptr ? rearlights : 0 ) );
else vehicle = ( isfrontcaboccupied ? vehicle->NextC( coupling::control ) : vehicle->PrevC( coupling::control ) );
{
p->RaLightsSet(MoverParameters->Lights[xs][MoverParameters->LightsPos - 1] * xs,
MoverParameters->Lights[1 - xs][MoverParameters->LightsPos - 1] * (1 - xs));
}
p = (kier ? p->NextC(4) : p->PrevC(4));
}
}
else // calosc
{
p->RaLightsSet(MoverParameters->Lights[xs][MoverParameters->LightsPos - 1],
MoverParameters->Lights[1 - xs][MoverParameters->LightsPos - 1]);
} }
}; };
@@ -6370,16 +6399,16 @@ void TDynamicObject::RaLightsSet(int head, int rear)
if (iDirection) // w zależności od kierunku pojazdu w składzie if (iDirection) // w zależności od kierunku pojazdu w składzie
{ // jesli pojazd stoi sprzęgiem 0 w stronę czoła { // jesli pojazd stoi sprzęgiem 0 w stronę czoła
if (head >= 0) if (head >= 0)
iLights[0] = head; MoverParameters->iLights[0] = head;
if (rear >= 0) if (rear >= 0)
iLights[1] = rear; MoverParameters->iLights[1] = rear;
} }
else else
{ // jak jest odwrócony w składzie (-1), to zapalamy odwrotnie { // jak jest odwrócony w składzie (-1), to zapalamy odwrotnie
if (head >= 0) if (head >= 0)
iLights[1] = head; MoverParameters->iLights[1] = head;
if (rear >= 0) if (rear >= 0)
iLights[0] = rear; MoverParameters->iLights[0] = rear;
} }
}; };

View File

@@ -394,8 +394,8 @@ private:
void update_exchange( double const Deltatime ); void update_exchange( double const Deltatime );
// members // members
TButton btCoupler1; // sprzegi TAirCoupler btCoupler1; // sprzegi
TButton btCoupler2; TAirCoupler btCoupler2;
std::array<TModel3d *, 2> m_coupleradapters = { nullptr, nullptr }; std::array<TModel3d *, 2> m_coupleradapters = { nullptr, nullptr };
TAirCoupler btCPneumatic1; // sprzegi powietrzne //yB - zmienione z Button na AirCoupler - krzyzyki TAirCoupler btCPneumatic1; // sprzegi powietrzne //yB - zmienione z Button na AirCoupler - krzyzyki
TAirCoupler btCPneumatic2; TAirCoupler btCPneumatic2;
@@ -420,12 +420,12 @@ private:
TButton btEndSignals2; TButton btEndSignals2;
TButton btEndSignalsTab1; // sygnaly konca pociagu (blachy) TButton btEndSignalsTab1; // sygnaly konca pociagu (blachy)
TButton btEndSignalsTab2; TButton btEndSignalsTab2;
TButton btHeadSignals11; // oswietlenie czolowe - przod TAirCoupler btHeadSignals11; // oswietlenie czolowe - przod
TButton btHeadSignals12; TAirCoupler btHeadSignals12;
TButton btHeadSignals13; TAirCoupler btHeadSignals13;
TButton btHeadSignals21; // oswietlenie czolowe - tyl TAirCoupler btHeadSignals21; // oswietlenie czolowe - tyl
TButton btHeadSignals22; TAirCoupler btHeadSignals22;
TButton btHeadSignals23; TAirCoupler btHeadSignals23;
TButton btMechanik1; TButton btMechanik1;
TButton btMechanik2; TButton btMechanik2;
TButton btShutters1; // cooling shutters for primary water circuit TButton btShutters1; // cooling shutters for primary water circuit
@@ -498,7 +498,6 @@ private:
void ABuCheckMyTrack(); void ABuCheckMyTrack();
public: public:
int *iLights; // wskaźnik na bity zapalonych świateł (własne albo innego członu)
bool DimHeadlights{ false }; // status of the headlight dimming toggle. NOTE: single toggle for all lights is a simplification. TODO: separate per-light switches bool DimHeadlights{ false }; // status of the headlight dimming toggle. NOTE: single toggle for all lights is a simplification. TODO: separate per-light switches
TDynamicObject * PrevAny() const; TDynamicObject * PrevAny() const;
TDynamicObject * Prev() const; TDynamicObject * Prev() const;
@@ -665,7 +664,7 @@ private:
TDynamicObject * FirstFind(int &coupler_nr, int cf = 1); TDynamicObject * FirstFind(int &coupler_nr, int cf = 1);
float GetEPP(); // wyliczanie sredniego cisnienia w PG float GetEPP(); // wyliczanie sredniego cisnienia w PG
int DirectionSet(int d); // ustawienie kierunku w składzie int DirectionSet(int d); // ustawienie kierunku w składzie
// odczyt kierunku w składzie // odczyt kierunku w składzie; returns 1 if true, -1 otherwise
int DirectionGet() const { int DirectionGet() const {
return iDirection + iDirection - 1; }; return iDirection + iDirection - 1; };
int DettachStatus(int dir); int DettachStatus(int dir);

129
Event.cpp
View File

@@ -27,6 +27,7 @@ http://mozilla.org/MPL/2.0/.
#include "AnimModel.h" #include "AnimModel.h"
#include "DynObj.h" #include "DynObj.h"
#include "Driver.h" #include "Driver.h"
#include "renderer.h"
#include "Timer.h" #include "Timer.h"
#include "Logs.h" #include "Logs.h"
@@ -234,11 +235,12 @@ basic_event::event_conditions::export_as_text( std::ostream &Output ) const {
<< probability << ' '; << probability << ' ';
} }
if( ( flags & ( flags::text | flags::value1 | flags::value2 ) ) != 0 ) { if( ( flags & ( flags::text | flags::value1 | flags::value2 ) ) != 0 ) {
// NOTE: export doesn't preserve original memcompare condition, these are all upgraded to memcompareex format for simplicity
Output Output
<< "memcompare " << "memcompareex "
<< ( ( flags & flags::text ) == 0 ? "*" : memcompare_text ) << ' ' << ( ( flags & flags::text ) == 0 ? "*" : memcompare_text + ' ' + to_string( memcompare_text_operator ) ) << ' '
<< ( ( flags & flags::value1 ) == 0 ? "*" : to_string( memcompare_value1 ) ) << ' ' << ( ( flags & flags::value1 ) == 0 ? "*" : to_string( memcompare_value1 ) + ' ' + to_string( memcompare_value1_operator ) ) << ' '
<< ( ( flags & flags::value2 ) == 0 ? "*" : to_string( memcompare_value2 ) ) << ' '; << ( ( flags & flags::value2 ) == 0 ? "*" : to_string( memcompare_value2 ) + ' ' + to_string( memcompare_value2_operator ) ) << ' ';
} }
} }
} }
@@ -937,11 +939,26 @@ whois_event::run_() {
auto *targetcell { static_cast<TMemCell *>( std::get<scene::basic_node *>( target ) ) }; auto *targetcell { static_cast<TMemCell *>( std::get<scene::basic_node *>( target ) ) };
if( targetcell == nullptr ) { continue; } if( targetcell == nullptr ) { continue; }
// event effect code // event effect code
// +32: vehicle name
// +24: vehicle type, consist brake level, obstacle distance // +24: vehicle type, consist brake level, obstacle distance
// +16: load type, load amount, max load amount // +16: load type, load amount, max load amount
// +8: destination, direction, engine power // +8: destination, direction, engine power
// +0: train name, station count, stop on next station // +0: train name, station count, stop on next station
if( m_input.flags & flags::load ) { if( m_input.flags & flags::whois_name ) {
// +32 or +40
targetcell->UpdateValues(
m_activator->asName, // vehicle name
0, // unused
0, // unused
m_input.flags & ( flags::text | flags::value1 | flags::value2 ) );
WriteLog(
"Type: WhoIs (" + to_string( m_input.flags ) + ") - "
+ "[name: " + m_activator->asName + "], "
+ "[X], "
+ "[X]" );
}
else if( m_input.flags & flags::whois_load ) {
// +16 or +24 // +16 or +24
// jeśli pytanie o ładunek // jeśli pytanie o ładunek
if( m_input.flags & flags::mode_alt ) { if( m_input.flags & flags::mode_alt ) {
@@ -1321,6 +1338,105 @@ sound_event::deserialize_targets( std::string const &Input ) {
TMemCell const *
texture_event::input_data::data_cell() const {
return static_cast<TMemCell const *>( std::get<scene::basic_node *>( data_source ) );
}
TMemCell *
texture_event::input_data::data_cell() {
return static_cast<TMemCell *>( std::get<scene::basic_node *>( data_source ) );
}
// prepares event for use
void
texture_event::init() {
// target models
init_targets( simulation::Instances, "model instance" );
// optional input data memory cell
TMemCell *inputcell { nullptr };
auto const inputcellname { std::get<std::string>( m_input.data_source ) };
if( inputcellname != "none" ) {
inputcell = simulation::Memory.find( inputcellname );
if( inputcell == nullptr ) {
ErrorLog( "Bad event: \"" + m_name + "\" (type: " + type() + ") can't find memory cell \"" + inputcellname + "\"" );
}
}
std::get<scene::basic_node *>( m_input.data_source ) = inputcell;
}
// event type string
std::string
texture_event::type() const {
return "texture";
}
// deserialize() subclass details
void
texture_event::deserialize_( cParser &Input, scene::scratch_data &Scratchpad ) {
Input.getTokens( 3 );
Input
>> m_skinindex
>> m_skin
>> std::get<std::string>( m_input.data_source );
// validate input
if( m_skinindex < 0 ) {
// intercept potential error, index specified using .t3d format convention
m_skinindex *= -1;
}
m_skinindex = clamp( m_skinindex, 1, 4 ); // TODO: define-based upper bound in case of future extension
Input.getTokens(); // preload next token
}
// run() subclass details
void
texture_event::run_() {
material_handle material { null_handle };
if( m_input.data_cell() == nullptr ) {
// straightforward variant without parameters, we can pass expression directly
material = GfxRenderer->Fetch_Material( m_skin );
}
else {
// variant with memory cell: pass the cell content as parameters and generate filename
cParser expression(
m_skin, cParser::buffer_TEXT,
"", true,
{ m_input.data_cell()->Text(),
to_string( m_input.data_cell()->Value1(), 0 ), // memory cell values are passed as ints
to_string( m_input.data_cell()->Value2(), 0 ) } );
material = GfxRenderer->Fetch_Material( expression.getToken<std::string>( false, "\n\r" ) );
}
// assign received material to target models
for( auto &target : m_targets ) {
auto *targetmodel = static_cast<TAnimModel *>( std::get<scene::basic_node *>( target ) );
if( targetmodel == nullptr ) { continue; }
// event effect code
targetmodel->SkinSet( m_skinindex, material );
}
}
// export_as_text() subclass details
void
texture_event::export_as_text_( std::ostream &Output ) const {
// playback mode
Output
<< m_skinindex << ' '
<< m_skin << ' '
<< std::get<std::string>( m_input.data_source ) << ' ';
}
// destructor // destructor
animation_event::~animation_event() { animation_event::~animation_event() {
@@ -1947,6 +2063,7 @@ make_event( cParser &Input, scene::scratch_data &Scratchpad ) {
else if( type == "switch" ) { event = new switch_event(); } else if( type == "switch" ) { event = new switch_event(); }
else if( type == "trackvel" ) { event = new track_event(); } else if( type == "trackvel" ) { event = new track_event(); }
else if( type == "sound" ) { event = new sound_event(); } else if( type == "sound" ) { event = new sound_event(); }
else if( type == "texture" ) { event = new texture_event(); }
else if( type == "animation" ) { event = new animation_event(); } else if( type == "animation" ) { event = new animation_event(); }
else if( type == "lights" ) { event = new lights_event(); } else if( type == "lights" ) { event = new lights_event(); }
else if( type == "voltage" ) { event = new voltage_event(); } else if( type == "voltage" ) { event = new voltage_event(); }
@@ -1955,7 +2072,7 @@ make_event( cParser &Input, scene::scratch_data &Scratchpad ) {
else if( type == "message" ) { event = new message_event(); } else if( type == "message" ) { event = new message_event(); }
if( event == nullptr ) { if( event == nullptr ) {
WriteLog( "Bad event: unrecognized type \"" + type + "\" specified for event \"" + name + "\"." ); ErrorLog( "Bad event: unrecognized type \"" + type + "\" specified for event \"" + name + "\"." );
return event; return event;
} }

55
Event.h
View File

@@ -29,7 +29,8 @@ public:
mode_add = 1 << 3, mode_add = 1 << 3,
// whois // whois
mode_alt = 1 << 3, mode_alt = 1 << 3,
load = 1 << 4, whois_load = 1 << 4,
whois_name = 1 << 5,
// condition values // condition values
track_busy = 1 << 3, track_busy = 1 << 3,
track_free = 1 << 4, track_free = 1 << 4,
@@ -341,6 +342,8 @@ private:
event_conditions m_conditions; event_conditions m_conditions;
}; };
class sound_event : public basic_event { class sound_event : public basic_event {
public: public:
@@ -369,6 +372,42 @@ private:
int m_soundradiochannel{ 0 }; int m_soundradiochannel{ 0 };
}; };
// assigns a texture as specified replacable skin to a list of specified scene model nodes
// skin filename is built dynamically using specified expression and list of parameters from optional specified memory cell
class texture_event : public basic_event {
public:
// methods
// prepares event for use
void init() override;
private:
// types
struct input_data {
basic_node data_source { "", nullptr };
TMemCell const * data_cell() const;
TMemCell * data_cell();
};
// methods
// event type string
std::string type() const override;
// deserialize() subclass details
void deserialize_( cParser &Input, scene::scratch_data &Scratchpad ) override;
// run() subclass details
void run_() override;
// export_as_text() subclass details
void export_as_text_( std::ostream &Output ) const override;
// members
int m_skinindex { 0 }; // index of target replacable skin
std::string m_skin; // expression defining skin filename
input_data m_input; // optional source of expression parameters
};
class animation_event : public basic_event { class animation_event : public basic_event {
public: public:
@@ -398,6 +437,8 @@ private:
char *m_animationfiledata{ nullptr }; char *m_animationfiledata{ nullptr };
}; };
class lights_event : public basic_event { class lights_event : public basic_event {
public: public:
@@ -419,6 +460,8 @@ private:
std::vector<float> m_lights; std::vector<float> m_lights;
}; };
class switch_event : public basic_event { class switch_event : public basic_event {
public: public:
@@ -442,6 +485,8 @@ private:
float m_switchmovedelay{ -1.f }; float m_switchmovedelay{ -1.f };
}; };
class track_event : public basic_event { class track_event : public basic_event {
public: public:
@@ -463,6 +508,8 @@ private:
float m_velocity{ 0.f }; float m_velocity{ 0.f };
}; };
class voltage_event : public basic_event { class voltage_event : public basic_event {
public: public:
@@ -484,6 +531,8 @@ private:
float m_voltage{ -1.f }; float m_voltage{ -1.f };
}; };
class visible_event : public basic_event { class visible_event : public basic_event {
public: public:
@@ -505,6 +554,8 @@ private:
bool m_visible{ true }; bool m_visible{ true };
}; };
class friction_event : public basic_event { class friction_event : public basic_event {
public: public:
@@ -526,6 +577,8 @@ private:
float m_friction{ -1.f }; float m_friction{ -1.f };
}; };
class message_event : public basic_event { class message_event : public basic_event {
public: public:

View File

@@ -891,6 +891,10 @@ void TTrack::Load(cParser *parser, glm::dvec3 const &pOrigin)
m_profile1 = fetch_track_rail_profile( railprofile ); m_profile1 = fetch_track_rail_profile( railprofile );
} }
} }
else if( str == "friction" ) {
// memory cell holding friction value modifiers
m_friction.first = parser->getToken<std::string>();
}
else else
ErrorLog("Bad track: unknown property: \"" + str + "\" defined for track \"" + m_name + "\""); ErrorLog("Bad track: unknown property: \"" + str + "\" defined for track \"" + m_name + "\"");
parser->getTokens(); parser->getTokens();
@@ -2162,6 +2166,9 @@ TTrack::export_as_text_( std::ostream &Output ) const {
} }
Output << "trackbed " << texturefile << ' '; Output << "trackbed " << texturefile << ' ';
} }
if( false == m_friction.first.empty() ) {
Output << "friction " << m_friction.first << ' ';
}
// footer // footer
Output Output
<< "endtrack" << "endtrack"
@@ -2313,6 +2320,16 @@ double TTrack::VelocityGet()
return ((iDamageFlag & 128) ? 0.0 : fVelocity); // tor uszkodzony = prędkość zerowa return ((iDamageFlag & 128) ? 0.0 : fVelocity); // tor uszkodzony = prędkość zerowa
}; };
float TTrack::Friction() const {
if( m_friction.second == nullptr ) {
return fFriction;
}
else {
return clamp( fFriction * m_friction.second->Value1() + m_friction.second->Value2(), 0.0, 1.0 );
}
}
void TTrack::ConnectionsLog() void TTrack::ConnectionsLog()
{ // wypisanie informacji o połączeniach { // wypisanie informacji o połączeniach
int i; int i;
@@ -3298,6 +3315,17 @@ path_table::InitTracks() {
// ustawienie flagi portalu // ustawienie flagi portalu
track->iCategoryFlag |= 0x100; track->iCategoryFlag |= 0x100;
} }
{
auto const inputcellname { track->m_friction.first };
if( false == inputcellname.empty() ) {
track->m_friction.second = simulation::Memory.find( inputcellname );
if( track->m_friction.second == nullptr ) {
ErrorLog( "Bad track: " + ( trackname.empty() ? "unnamed track" : "\"" + trackname + "\"" ) + " can't find assigned memory cell \"" + inputcellname + "\"" );
}
}
}
} }
if( Global.CreateSwitchTrackbeds ) { if( Global.CreateSwitchTrackbeds ) {

View File

@@ -191,6 +191,7 @@ public:
m_events1, m_events1,
m_events2; m_events2;
bool m_events { false }; // Ra: flaga informująca o obecności eventów bool m_events { false }; // Ra: flaga informująca o obecności eventów
std::pair<std::string, TMemCell *> m_friction { "", nullptr };
int iNextDirection = 0; // 0:Point1, 1:Point2, 3:do odchylonego na zwrotnicy int iNextDirection = 0; // 0:Point1, 1:Point2, 3:do odchylonego na zwrotnicy
int iPrevDirection = 0; // domyślnie wirtualne odcinki dołączamy stroną od Point1 int iPrevDirection = 0; // domyślnie wirtualne odcinki dołączamy stroną od Point1
@@ -293,6 +294,7 @@ public:
void MovedUp1(float const dh); void MovedUp1(float const dh);
void VelocitySet(float v); void VelocitySet(float v);
double VelocityGet(); double VelocityGet();
float Friction() const;
void ConnectionsLog(); void ConnectionsLog();
bool DoubleSlip() const; bool DoubleSlip() const;
static void fetch_default_profiles(); static void fetch_default_profiles();

150
Train.cpp
View File

@@ -3740,7 +3740,7 @@ void TTrain::OnCommand_headlighttoggleleft( TTrain *Train, command_data const &C
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_left ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_left ) == 0 ) {
// turn on // turn on
OnCommand_headlightenableleft( Train, Command ); OnCommand_headlightenableleft( Train, Command );
} }
@@ -3764,12 +3764,12 @@ void TTrain::OnCommand_headlightenableleft( TTrain *Train, command_data const &C
// implementation // implementation
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_left ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_left ) == 0 ) {
Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_left; Train->mvOccupied->iLights[ vehicleend ] ^= light::headlight_left;
} }
// if the light is controlled by 3-way switch, disable marker light // if the light is controlled by 3-way switch, disable marker light
if( Train->ggLeftEndLightButton.SubModel == nullptr ) { if( Train->ggLeftEndLightButton.SubModel == nullptr ) {
Train->DynamicObject->iLights[ vehicleend ] &= ~light::redmarker_left; Train->mvOccupied->iLights[ vehicleend ] &= ~light::redmarker_left;
} }
} }
} }
@@ -3785,9 +3785,9 @@ void TTrain::OnCommand_headlightdisableleft( TTrain *Train, command_data const &
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
int const vehicleend { Train->cab_to_end() }; int const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_left ) == 0 ) { return; } // already disabled if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_left ) == 0 ) { return; } // already disabled
Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_left; Train->mvOccupied->iLights[ vehicleend ] ^= light::headlight_left;
// visual feedback // visual feedback
Train->ggLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
@@ -3799,7 +3799,7 @@ void TTrain::OnCommand_headlighttoggleright( TTrain *Train, command_data const &
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_right ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_right ) == 0 ) {
// turn on // turn on
OnCommand_headlightenableright( Train, Command ); OnCommand_headlightenableright( Train, Command );
} }
@@ -3823,12 +3823,12 @@ void TTrain::OnCommand_headlightenableright( TTrain *Train, command_data const &
// implementation // implementation
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_right ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_right ) == 0 ) {
Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_right; Train->mvOccupied->iLights[ vehicleend ] ^= light::headlight_right;
} }
// if the light is controlled by 3-way switch, disable marker light // if the light is controlled by 3-way switch, disable marker light
if( Train->ggRightEndLightButton.SubModel == nullptr ) { if( Train->ggRightEndLightButton.SubModel == nullptr ) {
Train->DynamicObject->iLights[ vehicleend ] &= ~light::redmarker_right; Train->mvOccupied->iLights[ vehicleend ] &= ~light::redmarker_right;
} }
} }
} }
@@ -3844,9 +3844,9 @@ void TTrain::OnCommand_headlightdisableright( TTrain *Train, command_data const
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_right ) == 0 ) { return; } // already disabled if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_right ) == 0 ) { return; } // already disabled
Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_right; Train->mvOccupied->iLights[ vehicleend ] ^= light::headlight_right;
// visual feedback // visual feedback
Train->ggRightLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggRightLightButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
@@ -3858,7 +3858,7 @@ void TTrain::OnCommand_headlighttoggleupper( TTrain *Train, command_data const &
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_upper ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_upper ) == 0 ) {
// turn on // turn on
OnCommand_headlightenableupper( Train, Command ); OnCommand_headlightenableupper( Train, Command );
} }
@@ -3880,9 +3880,9 @@ void TTrain::OnCommand_headlightenableupper( TTrain *Train, command_data const &
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_upper ) != 0 ) { return; } // already enabled if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_upper ) != 0 ) { return; } // already enabled
Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_upper; Train->mvOccupied->iLights[ vehicleend ] ^= light::headlight_upper;
// visual feedback // visual feedback
Train->ggUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
@@ -3899,9 +3899,9 @@ void TTrain::OnCommand_headlightdisableupper( TTrain *Train, command_data const
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::headlight_upper ) == 0 ) { return; } // already disabled if( ( Train->mvOccupied->iLights[ vehicleend ] & light::headlight_upper ) == 0 ) { return; } // already disabled
Train->DynamicObject->iLights[ vehicleend ] ^= light::headlight_upper; Train->mvOccupied->iLights[ vehicleend ] ^= light::headlight_upper;
// visual feedback // visual feedback
Train->ggUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
@@ -3913,7 +3913,7 @@ void TTrain::OnCommand_redmarkertoggleleft( TTrain *Train, command_data const &C
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_left ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleend ] & light::redmarker_left ) == 0 ) {
// turn on // turn on
OnCommand_redmarkerenableleft( Train, Command ); OnCommand_redmarkerenableleft( Train, Command );
} }
@@ -3935,9 +3935,9 @@ void TTrain::OnCommand_redmarkerenableleft( TTrain *Train, command_data const &C
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_left ) != 0 ) { return; } // already enabled if( ( Train->mvOccupied->iLights[ vehicleend ] & light::redmarker_left ) != 0 ) { return; } // already enabled
Train->DynamicObject->iLights[ vehicleend ] ^= light::redmarker_left; Train->mvOccupied->iLights[ vehicleend ] ^= light::redmarker_left;
// visual feedback // visual feedback
if( Train->ggLeftEndLightButton.SubModel != nullptr ) { if( Train->ggLeftEndLightButton.SubModel != nullptr ) {
Train->ggLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch );
@@ -3947,7 +3947,7 @@ void TTrain::OnCommand_redmarkerenableleft( TTrain *Train, command_data const &C
// this is crude, but for now will do // this is crude, but for now will do
Train->ggLeftLightButton.UpdateValue( -1.0, Train->dsbSwitch ); Train->ggLeftLightButton.UpdateValue( -1.0, Train->dsbSwitch );
// if the light is controlled by 3-way switch, disable the headlight // if the light is controlled by 3-way switch, disable the headlight
Train->DynamicObject->iLights[ vehicleend ] &= ~light::headlight_left; Train->mvOccupied->iLights[ vehicleend ] &= ~light::headlight_left;
} }
} }
} }
@@ -3963,9 +3963,9 @@ void TTrain::OnCommand_redmarkerdisableleft( TTrain *Train, command_data const &
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_left ) == 0 ) { return; } // already disabled if( ( Train->mvOccupied->iLights[ vehicleend ] & light::redmarker_left ) == 0 ) { return; } // already disabled
Train->DynamicObject->iLights[ vehicleend ] ^= light::redmarker_left; Train->mvOccupied->iLights[ vehicleend ] ^= light::redmarker_left;
// visual feedback // visual feedback
if( Train->ggLeftEndLightButton.SubModel != nullptr ) { if( Train->ggLeftEndLightButton.SubModel != nullptr ) {
Train->ggLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -3984,7 +3984,7 @@ void TTrain::OnCommand_redmarkertoggleright( TTrain *Train, command_data const &
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_right ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleend ] & light::redmarker_right ) == 0 ) {
// turn on // turn on
OnCommand_redmarkerenableright( Train, Command ); OnCommand_redmarkerenableright( Train, Command );
} }
@@ -4006,9 +4006,9 @@ void TTrain::OnCommand_redmarkerenableright( TTrain *Train, command_data const &
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_right ) != 0 ) { return; } // already enabled if( ( Train->mvOccupied->iLights[ vehicleend ] & light::redmarker_right ) != 0 ) { return; } // already enabled
Train->DynamicObject->iLights[ vehicleend ] ^= light::redmarker_right; Train->mvOccupied->iLights[ vehicleend ] ^= light::redmarker_right;
// visual feedback // visual feedback
if( Train->ggRightEndLightButton.SubModel != nullptr ) { if( Train->ggRightEndLightButton.SubModel != nullptr ) {
Train->ggRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch );
@@ -4018,7 +4018,7 @@ void TTrain::OnCommand_redmarkerenableright( TTrain *Train, command_data const &
// this is crude, but for now will do // this is crude, but for now will do
Train->ggRightLightButton.UpdateValue( -1.0, Train->dsbSwitch ); Train->ggRightLightButton.UpdateValue( -1.0, Train->dsbSwitch );
// if the light is controlled by 3-way switch, disable the headlight // if the light is controlled by 3-way switch, disable the headlight
Train->DynamicObject->iLights[ vehicleend ] &= ~light::headlight_right; Train->mvOccupied->iLights[ vehicleend ] &= ~light::headlight_right;
} }
} }
} }
@@ -4034,9 +4034,9 @@ void TTrain::OnCommand_redmarkerdisableright( TTrain *Train, command_data const
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const vehicleend { Train->cab_to_end() }; auto const vehicleend { Train->cab_to_end() };
if( ( Train->DynamicObject->iLights[ vehicleend ] & light::redmarker_right ) == 0 ) { return; } // already disabled if( ( Train->mvOccupied->iLights[ vehicleend ] & light::redmarker_right ) == 0 ) { return; } // already disabled
Train->DynamicObject->iLights[ vehicleend ] ^= light::redmarker_right; Train->mvOccupied->iLights[ vehicleend ] ^= light::redmarker_right;
// visual feedback // visual feedback
if( Train->ggRightEndLightButton.SubModel != nullptr ) { if( Train->ggRightEndLightButton.SubModel != nullptr ) {
Train->ggRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -4063,15 +4063,15 @@ void TTrain::OnCommand_headlighttogglerearleft( TTrain *Train, command_data cons
end::rear : end::rear :
end::front ) }; end::front ) };
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::headlight_right ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleotherend ] & light::headlight_right ) == 0 ) {
// turn on // turn on
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_right; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::headlight_right;
// visual feedback // visual feedback
Train->ggRearLeftLightButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggRearLeftLightButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
else { else {
//turn off //turn off
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_right; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::headlight_right;
// visual feedback // visual feedback
Train->ggRearLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggRearLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
@@ -4092,15 +4092,15 @@ void TTrain::OnCommand_headlighttogglerearright( TTrain *Train, command_data con
end::rear : end::rear :
end::front ) }; end::front ) };
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::headlight_left ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleotherend ] & light::headlight_left ) == 0 ) {
// turn on // turn on
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_left; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::headlight_left;
// visual feedback // visual feedback
Train->ggRearRightLightButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggRearRightLightButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
else { else {
//turn off //turn off
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_left; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::headlight_left;
// visual feedback // visual feedback
Train->ggRearRightLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggRearRightLightButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
@@ -4120,15 +4120,15 @@ void TTrain::OnCommand_headlighttogglerearupper( TTrain *Train, command_data con
Train->cab_to_end() == end::front ? Train->cab_to_end() == end::front ?
end::rear : end::rear :
end::front ) }; end::front ) };
if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::headlight_upper ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleotherend ] & light::headlight_upper ) == 0 ) {
// turn on // turn on
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_upper; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::headlight_upper;
// visual feedback // visual feedback
Train->ggRearUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggRearUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
else { else {
//turn off //turn off
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::headlight_upper; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::headlight_upper;
// visual feedback // visual feedback
Train->ggRearUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggRearUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
@@ -4149,15 +4149,15 @@ void TTrain::OnCommand_redmarkertogglerearleft( TTrain *Train, command_data cons
end::rear : end::rear :
end::front ) }; end::front ) };
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::redmarker_right ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleotherend ] & light::redmarker_right ) == 0 ) {
// turn on // turn on
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::redmarker_right; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::redmarker_right;
// visual feedback // visual feedback
Train->ggRearLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggRearLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
else { else {
//turn off //turn off
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::redmarker_right; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::redmarker_right;
// visual feedback // visual feedback
Train->ggRearLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggRearLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
@@ -4178,15 +4178,15 @@ void TTrain::OnCommand_redmarkertogglerearright( TTrain *Train, command_data con
end::rear : end::rear :
end::front ) }; end::front ) };
// only reacting to press, so the switch doesn't flip back and forth if key is held down // only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleotherend ] & light::redmarker_left ) == 0 ) { if( ( Train->mvOccupied->iLights[ vehicleotherend ] & light::redmarker_left ) == 0 ) {
// turn on // turn on
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::redmarker_left; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::redmarker_left;
// visual feedback // visual feedback
Train->ggRearRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggRearRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
else { else {
//turn off //turn off
Train->DynamicObject->iLights[ vehicleotherend ] ^= light::redmarker_left; Train->mvOccupied->iLights[ vehicleotherend ] ^= light::redmarker_left;
// visual feedback // visual feedback
Train->ggRearRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggRearRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
@@ -4212,10 +4212,10 @@ void TTrain::OnCommand_redmarkerstoggle( TTrain *Train, command_data const &Comm
auto const lightset { light::redmarker_left | light::redmarker_right }; auto const lightset { light::redmarker_left | light::redmarker_right };
vehicle->iLights[ CouplNr ] = ( vehicle->MoverParameters->iLights[ CouplNr ] = (
false == TestFlag( vehicle->iLights[ CouplNr ], lightset ) ? false == TestFlag( vehicle->MoverParameters->iLights[ CouplNr ], lightset ) ?
vehicle->iLights[ CouplNr ] |= lightset : // turn signals on vehicle->MoverParameters->iLights[ CouplNr ] |= lightset : // turn signals on
vehicle->iLights[ CouplNr ] ^= lightset ); // turn signals off vehicle->MoverParameters->iLights[ CouplNr ] ^= lightset ); // turn signals off
} }
} }
@@ -4238,10 +4238,10 @@ void TTrain::OnCommand_endsignalstoggle( TTrain *Train, command_data const &Comm
auto const lightset { light::rearendsignals }; auto const lightset { light::rearendsignals };
vehicle->iLights[ CouplNr ] = ( vehicle->MoverParameters->iLights[ CouplNr ] = (
false == TestFlag( vehicle->iLights[ CouplNr ], lightset ) ? false == TestFlag( vehicle->MoverParameters->iLights[ CouplNr ], lightset ) ?
vehicle->iLights[ CouplNr ] |= lightset : // turn signals on vehicle->MoverParameters->iLights[ CouplNr ] |= lightset : // turn signals on
vehicle->iLights[ CouplNr ] ^= lightset ); // turn signals off vehicle->MoverParameters->iLights[ CouplNr ] ^= lightset ); // turn signals off
} }
} }
@@ -5787,6 +5787,10 @@ void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Comm
if( Train->ggDoorPermitPresetButton.SubModel != nullptr ) { if( Train->ggDoorPermitPresetButton.SubModel != nullptr ) {
Train->mvOccupied->ChangeDoorPermitPreset( 0 ); Train->mvOccupied->ChangeDoorPermitPreset( 0 );
} }
// HACK: update lights state
if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->DynamicObject->SetLights();
}
} }
} }
@@ -5821,6 +5825,10 @@ void TTrain::OnCommand_cabchangebackward( TTrain *Train, command_data const &Com
if( Train->ggDoorPermitPresetButton.SubModel != nullptr ) { if( Train->ggDoorPermitPresetButton.SubModel != nullptr ) {
Train->mvOccupied->ChangeDoorPermitPreset( 0 ); Train->mvOccupied->ChangeDoorPermitPreset( 0 );
} }
// HACK: update lights state
if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->DynamicObject->SetLights();
}
} }
} }
@@ -7303,24 +7311,22 @@ TTrain::update_sounds( double const Deltatime ) {
// power-reliant sounds // power-reliant sounds
if( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable ) { if( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable ) {
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if( mvOccupied->SecuritySystem.Status != s_off ) {
// hunter-091012: rozdzielenie alarmow // hunter-091012: rozdzielenie alarmow
if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm )
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) { || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
if( false == dsbBuzzer.is_playing() ) { if( false == dsbBuzzer.is_playing() ) {
dsbBuzzer dsbBuzzer
.pitch( dsbBuzzer.m_frequencyoffset + dsbBuzzer.m_frequencyfactor ) .pitch( dsbBuzzer.m_frequencyoffset + dsbBuzzer.m_frequencyfactor )
.gain( dsbBuzzer.m_amplitudeoffset + dsbBuzzer.m_amplitudefactor ) .gain( dsbBuzzer.m_amplitudeoffset + dsbBuzzer.m_amplitudefactor )
.play( sound_flags::looping ); .play( sound_flags::looping );
Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
} }
else { }
if( true == dsbBuzzer.is_playing() ) { else {
dsbBuzzer.stop(); if( true == dsbBuzzer.is_playing() ) {
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys dsbBuzzer.stop();
} Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
} }
} }
// distance meter alert // distance meter alert
@@ -8591,16 +8597,16 @@ void TTrain::set_cab_controls( int const Cab ) {
auto const vehicleend { cab_to_end( Cab ) }; auto const vehicleend { cab_to_end( Cab ) };
if( ( DynamicObject->iLights[ vehicleend ] & light::headlight_left ) != 0 ) { if( ( mvOccupied->iLights[ vehicleend ] & light::headlight_left ) != 0 ) {
ggLeftLightButton.PutValue( 1.f ); ggLeftLightButton.PutValue( 1.f );
} }
if( ( DynamicObject->iLights[ vehicleend ] & light::headlight_right ) != 0 ) { if( ( mvOccupied->iLights[ vehicleend ] & light::headlight_right ) != 0 ) {
ggRightLightButton.PutValue( 1.f ); ggRightLightButton.PutValue( 1.f );
} }
if( ( DynamicObject->iLights[ vehicleend ] & light::headlight_upper ) != 0 ) { if( ( mvOccupied->iLights[ vehicleend ] & light::headlight_upper ) != 0 ) {
ggUpperLightButton.PutValue( 1.f ); ggUpperLightButton.PutValue( 1.f );
} }
if( ( DynamicObject->iLights[ vehicleend ] & light::redmarker_left ) != 0 ) { if( ( mvOccupied->iLights[ vehicleend ] & light::redmarker_left ) != 0 ) {
if( ggLeftEndLightButton.SubModel != nullptr ) { if( ggLeftEndLightButton.SubModel != nullptr ) {
ggLeftEndLightButton.PutValue( 1.f ); ggLeftEndLightButton.PutValue( 1.f );
} }
@@ -8608,7 +8614,7 @@ void TTrain::set_cab_controls( int const Cab ) {
ggLeftLightButton.PutValue( -1.f ); ggLeftLightButton.PutValue( -1.f );
} }
} }
if( ( DynamicObject->iLights[ vehicleend ] & light::redmarker_right ) != 0 ) { if( ( mvOccupied->iLights[ vehicleend ] & light::redmarker_right ) != 0 ) {
if( ggRightEndLightButton.SubModel != nullptr ) { if( ggRightEndLightButton.SubModel != nullptr ) {
ggRightEndLightButton.PutValue( 1.f ); ggRightEndLightButton.PutValue( 1.f );
} }

View File

@@ -61,7 +61,7 @@ light_array::update() {
|| ( true == light.owner->MoverParameters->Power110vIsAvailable ) ) { || ( true == light.owner->MoverParameters->Power110vIsAvailable ) ) {
// with power on, the intensity depends on the state of activated switches // with power on, the intensity depends on the state of activated switches
// first we cross-check the list of enabled lights with the lights installed in the vehicle... // first we cross-check the list of enabled lights with the lights installed in the vehicle...
auto const lights { light.owner->iLights[ light.index ] & light.owner->LightList( static_cast<end>( light.index ) ) }; auto const lights { light.owner->MoverParameters->iLights[ light.index ] & light.owner->LightList( static_cast<end>( light.index ) ) };
// ...then check their individual state // ...then check their individual state
light.count = 0 light.count = 0
+ ( ( lights & light::headlight_left ) ? 1 : 0 ) + ( ( lights & light::headlight_left ) ? 1 : 0 )

View File

@@ -12,7 +12,7 @@ http://mozilla.org/MPL/2.0/.
#include "geometrybank.h" #include "geometrybank.h"
#include "material.h" #include "material.h"
class lighting_data; struct lighting_data;
class gfx_renderer { class gfx_renderer {

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 20 #define VERSION_MAJOR 20
#define VERSION_MINOR 604 #define VERSION_MINOR 608
#define VERSION_REVISION 0 #define VERSION_REVISION 0