16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-24 06:29:18 +02:00

Merge branch 'manul-staging' of https://github.com/wls50/maszyna-internal into manul-staging

This commit is contained in:
WLs50
2025-03-16 22:14:42 +01:00
38 changed files with 3184 additions and 1397 deletions

4
.gitmodules vendored
View File

@@ -19,3 +19,7 @@
[submodule "ref/asio"] [submodule "ref/asio"]
path = ref/asio path = ref/asio
url = https://github.com/chriskohlhoff/asio.git url = https://github.com/chriskohlhoff/asio.git
[submodule "ref/discord-rpc"]
path = ref/discord-rpc
url = https://github.com/discord/discord-rpc.git
branch = v3.4.0

View File

@@ -318,6 +318,10 @@ bool TAnimModel::Load(cParser *parser, bool ter)
LightsOff[5] = pModel->GetFromName("Light_Off05"); LightsOff[5] = pModel->GetFromName("Light_Off05");
LightsOff[6] = pModel->GetFromName("Light_Off06"); LightsOff[6] = pModel->GetFromName("Light_Off06");
LightsOff[7] = pModel->GetFromName("Light_Off07"); LightsOff[7] = pModel->GetFromName("Light_Off07");
sm_winter_variant = pModel->GetFromName("winter_variant");
sm_spring_variant = pModel->GetFromName("spring_variant");
sm_summer_variant = pModel->GetFromName("summer_variant");
sm_autumn_variant = pModel->GetFromName("autumn_variant");
} }
for (int i = 0; i < iMaxNumLights; ++i) for (int i = 0; i < iMaxNumLights; ++i)
if (LightsOn[i] || LightsOff[i]) // Ra: zlikwidowałem wymóg istnienia obu if (LightsOn[i] || LightsOff[i]) // Ra: zlikwidowałem wymóg istnienia obu
@@ -494,9 +498,59 @@ void TAnimModel::RaAnimate( unsigned int const Framestamp ) {
m_framestamp = Framestamp; m_framestamp = Framestamp;
} }
// aktualizujemy submodele w zaleznosci od aktualnej porty roku
void TAnimModel::on_season_update() {
if (Global.Season == "winter:") // pokazujemy wariant zimowy
{
if (this->sm_winter_variant != nullptr)
this->sm_winter_variant->SetVisibilityLevel(1.f, true, false);
if (this->sm_spring_variant != nullptr)
this->sm_spring_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_summer_variant != nullptr)
this->sm_summer_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_autumn_variant != nullptr)
this->sm_autumn_variant->SetVisibilityLevel(0.f, true, false);
}
else if (Global.Season == "spring:") // pokazujemy wariant wiosenny
{
if (this->sm_winter_variant != nullptr)
this->sm_winter_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_spring_variant != nullptr)
this->sm_spring_variant->SetVisibilityLevel(1.f, true, false);
if (this->sm_summer_variant != nullptr)
this->sm_summer_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_autumn_variant != nullptr)
this->sm_autumn_variant->SetVisibilityLevel(0.f, true, false);
}
else if (Global.Season == "summer:") // pokazujemy wariant letni
{
if (this->sm_winter_variant != nullptr)
this->sm_winter_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_spring_variant != nullptr)
this->sm_spring_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_summer_variant != nullptr)
this->sm_summer_variant->SetVisibilityLevel(1.f, true, false);
if (this->sm_autumn_variant != nullptr)
this->sm_autumn_variant->SetVisibilityLevel(0.f, true, false);
}
else if (Global.Season == "autumn:") // pokazujemy wariant jesienny
{
if (this->sm_winter_variant != nullptr)
this->sm_winter_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_spring_variant != nullptr)
this->sm_spring_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_summer_variant != nullptr)
this->sm_summer_variant->SetVisibilityLevel(0.f, true, false);
if (this->sm_autumn_variant != nullptr)
this->sm_autumn_variant->SetVisibilityLevel(1.f, true, false);
}
}
void TAnimModel::RaPrepare() void TAnimModel::RaPrepare()
{ // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza { // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
bool state; // stan światła bool state; // stan światła
if (Global.UpdateMaterials)
on_season_update();
for (int i = 0; i < iNumLights; ++i) for (int i = 0; i < iNumLights; ++i)
{ {
auto const lightmode { static_cast<int>( std::abs( lsLights[ i ] ) ) }; auto const lightmode { static_cast<int>( std::abs( lsLights[ i ] ) ) };
@@ -656,9 +710,9 @@ TAnimModel::export_as_text_( std::ostream &Output ) const {
// header // header
Output << "model "; Output << "model ";
// location and rotation // location and rotation
Output Output << std::fixed << std::setprecision(3) // ustawienie dokładnie 3 cyfr po przecinku
<< location().x << ' ' << location().x << ' '
<< location().y << ' ' << location().y << ' '
<< location().z << ' '; << location().z << ' ';
Output Output
<< "0 " ; << "0 " ;

View File

@@ -25,12 +25,14 @@ const int iMaxNumLights = 8;
float const DefaultDarkThresholdLevel { 0.325f }; float const DefaultDarkThresholdLevel { 0.325f };
// typy stanu świateł // typy stanu świateł
enum TLightState { enum TLightState
ls_Off = 0, // zgaszone {
ls_On = 1, // zapalone ls_Off = 0, // zgaszone
ls_Blink = 2, // migające ls_On = 1, // zapalone
ls_Dark = 3, // Ra: zapalajce się automatycznie, gdy zrobi się ciemno ls_Blink = 2, // migające
ls_Home = 4 // like ls_dark but off late at night ls_Dark = 3, // Ra: zapalajce się automatycznie, gdy zrobi się ciemno
ls_Home = 4, // like ls_dark but off late at night
ls_winter = 5 // turned on when its winter
}; };
class TAnimVocaloidFrame class TAnimVocaloidFrame
@@ -125,6 +127,7 @@ public:
int TerrainCount(); int TerrainCount();
TSubModel * TerrainSquare(int n); TSubModel * TerrainSquare(int n);
int Flags(); int Flags();
void on_season_update();
inline inline
material_data const * material_data const *
Material() const { Material() const {
@@ -174,6 +177,10 @@ public:
int iNumLights { 0 }; int iNumLights { 0 };
std::array<TSubModel *, iMaxNumLights> LightsOn {}; // Ra: te wskaźniki powinny być w ramach TModel3d std::array<TSubModel *, iMaxNumLights> LightsOn {}; // Ra: te wskaźniki powinny być w ramach TModel3d
std::array<TSubModel *, iMaxNumLights> LightsOff {}; std::array<TSubModel *, iMaxNumLights> LightsOff {};
TSubModel *sm_winter_variant {}; // submodel zimowego wariantu
TSubModel *sm_spring_variant {}; // submodel wiosennego wariantu
TSubModel *sm_summer_variant {}; // submodel letniego wariantu
TSubModel *sm_autumn_variant {}; // submodel jesiennego wariantu
std::array<float, iMaxNumLights> lsLights {}; // ls_Off std::array<float, iMaxNumLights> lsLights {}; // ls_Off
std::array<glm::vec3, iMaxNumLights> m_lightcolors; // -1 in constructor std::array<glm::vec3, iMaxNumLights> m_lightcolors; // -1 in constructor
std::array<float, iMaxNumLights> m_lighttimers {}; std::array<float, iMaxNumLights> m_lighttimers {};

View File

@@ -444,6 +444,12 @@ target_link_libraries(${PROJECT_NAME} Threads::Threads)
find_package(GLM REQUIRED) find_package(GLM REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE ${GLM_INCLUDE_DIR}) target_include_directories(${PROJECT_NAME} PRIVATE ${GLM_INCLUDE_DIR})
# add ref/discord-rpc to the project in the same way other dependencies are added
add_subdirectory(ref/discord-rpc)
target_link_libraries(${PROJECT_NAME} discord-rpc)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
if (TARGET OpenAL::OpenAL) if (TARGET OpenAL::OpenAL)
target_link_libraries(${PROJECT_NAME} OpenAL::OpenAL) target_link_libraries(${PROJECT_NAME} OpenAL::OpenAL)

View File

@@ -5704,6 +5704,7 @@ void TController::TakeControl( bool const Aidriver, bool const Forcevehiclecheck
{ // teraz AI prowadzi { // teraz AI prowadzi
AIControllFlag = AIdriver; AIControllFlag = AIdriver;
pVehicle->Controller = AIdriver; pVehicle->Controller = AIdriver;
control_lights(); // reinicjalizacja swiatel
mvOccupied->CabActivisation(true); mvOccupied->CabActivisation(true);
iDirection = 0; // kierunek jazdy trzeba dopiero zgadnąć iDirection = 0; // kierunek jazdy trzeba dopiero zgadnąć
TableClear(); // ponowne utworzenie tabelki, bo człowiek mógł pojechać niezgodnie z sygnałami TableClear(); // ponowne utworzenie tabelki, bo człowiek mógł pojechać niezgodnie z sygnałami
@@ -5740,6 +5741,8 @@ void TController::TakeControl( bool const Aidriver, bool const Forcevehiclecheck
} }
else else
{ // a teraz użytkownik { // a teraz użytkownik
if (!is_train() || !is_car()) // gasimy swiatla jesli przejmujemy odstawione
pVehicle->RaLightsSet(0, 0);
AIControllFlag = Humandriver; AIControllFlag = Humandriver;
pVehicle->Controller = Humandriver; pVehicle->Controller = Humandriver;
if( eAction == TAction::actSleep ) { if( eAction == TAction::actSleep ) {

View File

@@ -97,8 +97,110 @@ void TAnimPant::AKP_4E()
fHeightExtra[3] = -0.07f; //+0.3048 fHeightExtra[3] = -0.07f; //+0.3048
fHeightExtra[4] = -0.15f; //+0.3810 fHeightExtra[4] = -0.15f; //+0.3810
}; };
void TAnimPant::WBL85()
{ // ustawienie wymiarów dla pantografu WBL88
vPos = Math3D::vector3(0, 0, 0); // przypisanie domyśnych współczynników do pantografów
// mnozniki animacji ramion dla pantografu WBL88
rd1rf = 1.f;
rd2rf = 1.2;
rg1rf = 0.875;
rg2rf = 1.0;
slizgrf = 1.f;
fLenL1 = 1.98374;
fLenU1 = 2.14199;
fHoriz = 0.142; // 0.54555075 przesunięcie ślizgu w długości pojazdu względem
// osi obrotu dolnego ramienia
fHeight = 0.09353; // wysokość ślizgu ponad oś obrotu
fWidth = 0.4969; // połowa szerokości ślizgu
fAngleL0 = DegToRad(2.8547285515689267247882521833308);
fAngleL = fAngleL0; // początkowy kąt dolnego ramienia
// fAngleU0=acos((1.22*cos(fAngleL)+0.535)/1.755); //górne ramię
fAngleU0 = acos((fLenL1 * cos(fAngleL) + fHoriz) / fLenU1); // górne ramię
fAngleU = fAngleU0; // początkowy kąt
// PantWys=1.22*sin(fAngleL)+1.755*sin(fAngleU); //wysokość początkowa
PantWys = fLenL1 * sin(fAngleL) + fLenU1 * sin(fAngleU) + fHeight; // wysokość początkowa
PantTraction = PantWys;
hvPowerWire = NULL;
fWidthExtra = 0.381f; //(2.032m-1.027)/2
// poza obszarem roboczym jest aproksymacja łamaną o 5 odcinkach
fHeightExtra[0] = 0.0f; //+0.0762
fHeightExtra[1] = -0.01f; //+0.1524
fHeightExtra[2] = -0.03f; //+0.2286
fHeightExtra[3] = -0.07f; //+0.3048
fHeightExtra[4] = -0.15f; //+0.3810
};
void TAnimPant::EC160_200()
{ // ustawienie wymiarów dla pantografow EC160 lub EC200
vPos = Math3D::vector3(0, 0, 0); // przypisanie domyśnych współczynników do pantografów
// mnozniki animacji ramion dla pantografow EC160 lub EC200
rd1rf = 1.f;
rd2rf = 0.85;
rg1rf = 1.f;
rg2rf = 1.f; // 0.833
slizgrf = 1.f;
fLenL1 = 1.98374;
fLenU1 = 2.14199;
fHoriz = 0.142; // 0.54555075 przesunięcie ślizgu w długości pojazdu względem
// osi obrotu dolnego ramienia
fHeight = 0.09353; // wysokość ślizgu ponad oś obrotu
fWidth = 0.4969; // połowa szerokości ślizgu
fAngleL0 = DegToRad(2.8547285515689267247882521833308);
fAngleL = fAngleL0; // początkowy kąt dolnego ramienia
// fAngleU0=acos((1.22*cos(fAngleL)+0.535)/1.755); //górne ramię
fAngleU0 = acos((fLenL1 * cos(fAngleL) + fHoriz) / fLenU1); // górne ramię
fAngleU = fAngleU0; // początkowy kąt
// PantWys=1.22*sin(fAngleL)+1.755*sin(fAngleU); //wysokość początkowa
PantWys = fLenL1 * sin(fAngleL) + fLenU1 * sin(fAngleU) + fHeight; // wysokość początkowa
PantTraction = PantWys;
hvPowerWire = NULL;
fWidthExtra = 0.381f; //(2.032m-1.027)/2
// poza obszarem roboczym jest aproksymacja łamaną o 5 odcinkach
fHeightExtra[0] = 0.0f; //+0.0762
fHeightExtra[1] = -0.01f; //+0.1524
fHeightExtra[2] = -0.03f; //+0.2286
fHeightExtra[3] = -0.07f; //+0.3048
fHeightExtra[4] = -0.15f; //+0.3810
};
void TAnimPant::DSAx()
{ // ustawienie wymiarów dla pantografow z rodziny DSA
vPos = Math3D::vector3(0, 0, 0); // przypisanie domyśnych współczynników do pantografów
// mnozniki animacji ramion dla pantografow z rodziny DSA
rd1rf = 1.f;
rd2rf = 1.025;
rg1rf = 0.875;
rg2rf = 1.f;
slizgrf = 1.f;
fLenL1 = 1.98374;
fLenU1 = 2.14199;
fHoriz = 0.142; // 0.54555075 przesunięcie ślizgu w długości pojazdu względem
// osi obrotu dolnego ramienia
fHeight = 0.09353; // wysokość ślizgu ponad oś obrotu
fWidth = 0.4969; // połowa szerokości ślizgu
fAngleL0 = DegToRad(2.8547285515689267247882521833308);
fAngleL = fAngleL0; // początkowy kąt dolnego ramienia
// fAngleU0=acos((1.22*cos(fAngleL)+0.535)/1.755); //górne ramię
fAngleU0 = acos((fLenL1 * cos(fAngleL) + fHoriz) / fLenU1); // górne ramię
fAngleU = fAngleU0; // początkowy kąt
// PantWys=1.22*sin(fAngleL)+1.755*sin(fAngleU); //wysokość początkowa
PantWys = fLenL1 * sin(fAngleL) + fLenU1 * sin(fAngleU) + fHeight; // wysokość początkowa
PantTraction = PantWys;
hvPowerWire = NULL;
fWidthExtra = 0.381f; //(2.032m-1.027)/2
// poza obszarem roboczym jest aproksymacja łamaną o 5 odcinkach
fHeightExtra[0] = 0.0f; //+0.0762
fHeightExtra[1] = -0.01f; //+0.1524
fHeightExtra[2] = -0.03f; //+0.2286
fHeightExtra[3] = -0.07f; //+0.3048
fHeightExtra[4] = -0.15f; //+0.3810
};
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int TAnim::TypeSet(int i, int fl) int TAnim::TypeSet(int i, TMoverParameters currentMover, int fl)
{ // ustawienie typu animacji i zależnej od niego ilości animowanych submodeli { // ustawienie typu animacji i zależnej od niego ilości animowanych submodeli
fMaxDist = -1.0; // normalnie nie pokazywać fMaxDist = -1.0; // normalnie nie pokazywać
switch (i) switch (i)
@@ -127,7 +229,21 @@ int TAnim::TypeSet(int i, int fl)
case 5: // 5-pantograf - 5 submodeli case 5: // 5-pantograf - 5 submodeli
iFlags = 0x055; iFlags = 0x055;
fParamPants = new TAnimPant(); fParamPants = new TAnimPant();
fParamPants->AKP_4E(); switch (currentMover.EnginePowerSource.CollectorParameters.PantographType) {
case (TPantType::AKP_4E):
fParamPants->AKP_4E();
break;
case(TPantType::DSAx):
fParamPants->DSAx();
break;
case(TPantType::EC160_200):
fParamPants->EC160_200();
break;
case(TPantType::WBL85):
fParamPants->WBL85();
break;
}
break; break;
case 6: case 6:
iFlags = 0x068; iFlags = 0x068;
@@ -138,6 +254,9 @@ int TAnim::TypeSet(int i, int fl)
case 8: case 8:
iFlags = 0x080; iFlags = 0x080;
break; // mirror break; // mirror
case 9:
iFlags = 0x023; // 2: Rotating/Motion-based, 8: Uses 3 submodels
break;
default: default:
iFlags = 0; iFlags = 0;
} }
@@ -576,20 +695,20 @@ void TDynamicObject::UpdateDoorPlug(TAnim *pAnim) {
void TDynamicObject::UpdatePant(TAnim *pAnim) void TDynamicObject::UpdatePant(TAnim *pAnim)
{ // animacja pantografu - 4 obracane ramiona, ślizg piąty { // animacja pantografu - 4 obracane ramiona, ślizg piąty
float a, b, c; float a, b, c;
a = RadToDeg(pAnim->fParamPants->fAngleL - pAnim->fParamPants->fAngleL0); a = RadToDeg(pAnim->fParamPants->fAngleL - pAnim->fParamPants->fAngleL0);
b = RadToDeg(pAnim->fParamPants->fAngleU - pAnim->fParamPants->fAngleU0); b = RadToDeg(pAnim->fParamPants->fAngleU - pAnim->fParamPants->fAngleU0);
c = a + b; c = a + b;
if (pAnim->smElement[0]) if (pAnim->smElement[0])
pAnim->smElement[0]->SetRotate(float3(-1, 0, 0), a); // dolne ramię pAnim->smElement[0]->SetRotate(float3(-1, 0, 0), a); // dolne ramie 1
if (pAnim->smElement[1]) if (pAnim->smElement[1])
pAnim->smElement[1]->SetRotate(float3(1, 0, 0), a); pAnim->smElement[1]->SetRotate(float3(1, 0, 0), a * pAnim->fParamPants->rd2rf); // dolne ramie 2
if (pAnim->smElement[2]) if (pAnim->smElement[2])
pAnim->smElement[2]->SetRotate(float3(1, 0, 0), c); // górne ramię pAnim->smElement[2]->SetRotate(float3(1, 0, 0), c); // górne ramie 1
if (pAnim->smElement[3]) if (pAnim->smElement[3])
pAnim->smElement[3]->SetRotate(float3(-1, 0, 0), c); pAnim->smElement[3]->SetRotate(float3(-1, 0, 0), c * pAnim->fParamPants->rg2rf); // gorne ramie 2
if (pAnim->smElement[4]) if (pAnim->smElement[4])
pAnim->smElement[4]->SetRotate(float3(-1, 0, 0), b); //ślizg pAnim->smElement[4]->SetRotate(float3(-1, 0, 0), b * pAnim->fParamPants->slizgrf); // ślizg
} }
// doorstep animation, shift // doorstep animation, shift
@@ -645,6 +764,24 @@ void TDynamicObject::UpdateMirror( TAnim *pAnim ) {
interpolate( 0.0, MoverParameters->MirrorMaxShift, dMirrorMoveL * isactive ) ); interpolate( 0.0, MoverParameters->MirrorMaxShift, dMirrorMoveL * isactive ) );
} }
// wipers
void TDynamicObject::UpdateWiper(TAnim* pAnim)
{
if (!pAnim || !pAnim->smElement)
return;
int i = pAnim->iNumber;
// odwaramy animacje dla parzystych indexow
const double rotateAngle = (i + 1) % 2 == 0 ? -MoverParameters->WiperAngle : MoverParameters->WiperAngle;
if (pAnim->smElement[0]) // ramie 1
pAnim->smElement[0]->SetRotate(float3(0, 1, 0), smoothInterpolate(0.0, rotateAngle, dWiperPos[i]));
if (pAnim->smElement[1]) // ramie 2
pAnim->smElement[1]->SetRotate(float3(0, 1, 0), smoothInterpolate(0.0, rotateAngle, dWiperPos[i]));
if (pAnim->smElement[2]) // pioro
pAnim->smElement[2]->SetRotate(float3(0, 1, 0), smoothInterpolate(0.0, -rotateAngle, dWiperPos[i]));
}
/* /*
void TDynamicObject::UpdateLeverDouble(TAnim *pAnim) void TDynamicObject::UpdateLeverDouble(TAnim *pAnim)
{ // animacja gałki zależna od double { // animacja gałki zależna od double
@@ -1048,12 +1185,15 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
btnOn = true; btnOn = true;
} }
// only external models ( external_only_on / external_only_off )
btExteriorOnly.Turn(!bDisplayCab); // display only when cab is not rendered
if( ( false == bDisplayCab ) // edge case, lowpoly may act as a stand-in for the hi-fi cab, so make sure not to show the driver when inside if( ( false == bDisplayCab ) // edge case, lowpoly may act as a stand-in for the hi-fi cab, so make sure not to show the driver when inside
&& ( Mechanik != nullptr ) && ( Mechanik != nullptr )
&& ( ( Mechanik->action() != TAction::actSleep ) && ( ( Mechanik->action() != TAction::actSleep )
/* || ( MoverParameters->Battery ) */ ) ) { /* || ( MoverParameters->Battery ) */ ) ) {
// rysowanie figurki mechanika // rysowanie figurki mechanika
btMechanik1.Turn( MoverParameters->CabOccupied > 0 ); btMechanik1.Turn(MoverParameters->CabOccupied > 0);
btMechanik2.Turn( MoverParameters->CabOccupied < 0 ); btMechanik2.Turn( MoverParameters->CabOccupied < 0 );
if( MoverParameters->CabOccupied != 0 ) { if( MoverParameters->CabOccupied != 0 ) {
btnOn = true; btnOn = true;
@@ -1168,6 +1308,28 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
} }
btnOn = true; btnOn = true;
} }
// logika dlugich
if (TestFlag(MoverParameters->iLights[end::front], light::highbeamlight_left))
m_highbeam13.TurnxOnWithOnAsFallback();
else
m_highbeam13.TurnOff();
if (TestFlag(MoverParameters->iLights[end::front], light::highbeamlight_right))
m_highbeam12.TurnxOnWithOnAsFallback();
else
m_highbeam12.TurnOff();
// i to samo od dupy strony
if (TestFlag(MoverParameters->iLights[end::rear], light::highbeamlight_left))
m_highbeam23.TurnxOnWithOnAsFallback();
else
m_highbeam23.TurnOff();
if (TestFlag(MoverParameters->iLights[end::rear], light::highbeamlight_right))
m_highbeam22.TurnxOnWithOnAsFallback();
else
m_highbeam22.TurnOff();
} }
// interior light levels // interior light levels
auto sectionlightcolor { glm::vec4( 1.f ) }; auto sectionlightcolor { glm::vec4( 1.f ) };
@@ -2197,9 +2359,13 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
m_headlamp11.Init( "headlamp11", mdModel ); // górne m_headlamp11.Init( "headlamp11", mdModel ); // górne
m_headlamp12.Init( "headlamp12", mdModel ); // prawe m_headlamp12.Init( "headlamp12", mdModel ); // prawe
m_headlamp13.Init( "headlamp13", mdModel ); // lewe m_headlamp13.Init( "headlamp13", mdModel ); // lewe
m_highbeam12.Init("highbeam12", mdModel); // prawe dlugie
m_highbeam13.Init("highbeam13", mdModel); // lewe dlugie
m_headlamp21.Init( "headlamp21", mdModel ); m_headlamp21.Init( "headlamp21", mdModel );
m_headlamp22.Init( "headlamp22", mdModel ); m_headlamp22.Init( "headlamp22", mdModel );
m_headlamp23.Init( "headlamp23", mdModel ); m_headlamp23.Init( "headlamp23", mdModel );
m_highbeam22.Init("highbeam22", mdModel);
m_highbeam23.Init("highbeam23", mdModel);
m_headsignal12.Init( "headsignal12", mdModel ); m_headsignal12.Init( "headsignal12", mdModel );
m_headsignal13.Init( "headsignal13", mdModel ); m_headsignal13.Init( "headsignal13", mdModel );
m_headsignal22.Init( "headsignal22", mdModel ); m_headsignal22.Init( "headsignal22", mdModel );
@@ -2216,6 +2382,10 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
iInventory[ end::front ] |= m_headlamp11.Active() ? light::headlight_upper : 0; iInventory[ end::front ] |= m_headlamp11.Active() ? light::headlight_upper : 0;
iInventory[ end::front ] |= m_headlamp12.Active() ? light::headlight_right : 0; iInventory[ end::front ] |= m_headlamp12.Active() ? light::headlight_right : 0;
iInventory[ end::front ] |= m_headlamp13.Active() ? light::headlight_left : 0; iInventory[ end::front ] |= m_headlamp13.Active() ? light::headlight_left : 0;
iInventory[end::front] |= m_highbeam12.Active() ? light::highbeamlight_right : 0;
iInventory[end::front] |= m_highbeam13.Active() ? light::highbeamlight_left : 0;
iInventory[ end::rear ] |= m_headlamp21.Active() ? light::headlight_upper : 0; iInventory[ end::rear ] |= m_headlamp21.Active() ? light::headlight_upper : 0;
iInventory[ end::rear ] |= m_headlamp22.Active() ? light::headlight_right : 0; iInventory[ end::rear ] |= m_headlamp22.Active() ? light::headlight_right : 0;
iInventory[ end::rear ] |= m_headlamp23.Active() ? light::headlight_left : 0; iInventory[ end::rear ] |= m_headlamp23.Active() ? light::headlight_left : 0;
@@ -2223,8 +2393,15 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
iInventory[ end::front ] |= m_headsignal13.Active() ? light::auxiliary_left : 0; iInventory[ end::front ] |= m_headsignal13.Active() ? light::auxiliary_left : 0;
iInventory[ end::rear ] |= m_headsignal22.Active() ? light::auxiliary_right : 0; iInventory[ end::rear ] |= m_headsignal22.Active() ? light::auxiliary_right : 0;
iInventory[ end::rear ] |= m_headsignal23.Active() ? light::auxiliary_left : 0; iInventory[ end::rear ] |= m_headsignal23.Active() ? light::auxiliary_left : 0;
iInventory[end::rear] |= m_highbeam22.Active() ? light::highbeamlight_right : 0;
iInventory[end::rear] |= m_highbeam23.Active() ? light::highbeamlight_left : 0;
btExteriorOnly.Init("external_only", mdModel, false);
btMechanik1.Init( "mechanik1", mdLowPolyInt, false); btMechanik1.Init( "mechanik1", mdLowPolyInt, false);
btMechanik2.Init( "mechanik2", mdLowPolyInt, false); btMechanik2.Init( "mechanik2", mdLowPolyInt, false);
if( MoverParameters->dizel_heat.water.config.shutters ) { if( MoverParameters->dizel_heat.water.config.shutters ) {
btShutters1.Init( "shutters1", mdModel, false ); btShutters1.Init( "shutters1", mdModel, false );
} }
@@ -3949,6 +4126,70 @@ bool TDynamicObject::Update(double dt, double dt1)
MoverParameters->PantFrontVolt = 0.95 * MoverParameters->EnginePowerSource.MaxVoltage; MoverParameters->PantFrontVolt = 0.95 * MoverParameters->EnginePowerSource.MaxVoltage;
} }
// wipers
if (dWiperPos.size() > 0) // tylko dla wozow ze zdefiniowanymi wycierakami
{
for (int i = 0; i < dWiperPos.size(); i++) // iteracja po kazdej wycieraczce
{
bool wipersActive;
auto const bytesum = MoverParameters->WiperList[MoverParameters->wiperSwitchPos].byteSum;
// rozroznienie kabinowe
if (MoverParameters->CabActive == 1)
{
wipersActive = ((bytesum & (1 << i)) != 0) && MoverParameters->Battery;
}
else if (MoverParameters->CabActive == -1)
{
// odwroconie indexow wycieraczek
wipersActive = ((bytesum & (1 << dWiperPos.size() - 1 - i)) != 0) && MoverParameters->Battery;
}
else {
wipersActive = false;
}
auto const currentWiperParams = MoverParameters->WiperList[workingSwitchPos[i]];
wiperOutTimer[i] += dt1; // aktualizujemy zegarek
wiperParkTimer[i] += dt1; // aktualizujemy zegarek
if (wipersActive || dWiperPos[i] > 0.0) // zeby wrocily do trybu park
{
if (dWiperPos[i] > 0.0 && !wipersActive) // bezwzgledny powrot do zera
{
dWiperPos[i] = std::max(0.0, dWiperPos[i] - (1.f / currentWiperParams.WiperSpeed) * dt1);
}
else {
if (dWiperPos[i] < 1.0 && !wiperDirection[i] && wiperParkTimer[i] > currentWiperParams.interval)
// go out
{
dWiperPos[i] = std::min(1.0, dWiperPos[i] + (1.f / currentWiperParams.WiperSpeed) * dt1);
}
if (dWiperPos[i] > 0.0 && wiperDirection[i] && wiperOutTimer[i] > currentWiperParams.outBackDelay)
// return back
{
dWiperPos[i] = std::max(0.0, dWiperPos[i] - (1.f / currentWiperParams.WiperSpeed) * dt1);
}
if (dWiperPos[i] == 1.0) // we reached end
{
wiperParkTimer[i] = 0.0;
wiperDirection[i] = true; // switch direction
}
if (dWiperPos[i] == 0.0)
{
// when in park position
wiperOutTimer[i] = 0.0;
wiperDirection[i] = false;
workingSwitchPos[i] = MoverParameters->wiperSwitchPos; // update configuration
}
}
}
}
}
// mirrors // mirrors
if( (MoverParameters->Vel > MoverParameters->MirrorVelClose) if( (MoverParameters->Vel > MoverParameters->MirrorVelClose)
|| (MoverParameters->CabActive == 0) && (activation::mirrors) || (MoverParameters->CabActive == 0) && (activation::mirrors)
@@ -4162,6 +4403,10 @@ void TDynamicObject::TurnOff()
m_headlamp21.TurnOff(); m_headlamp21.TurnOff();
m_headlamp22.TurnOff(); m_headlamp22.TurnOff();
m_headlamp23.TurnOff(); m_headlamp23.TurnOff();
m_highbeam12.TurnOff();
m_highbeam13.TurnOff();
m_highbeam22.TurnOff();
m_highbeam23.TurnOff();
m_headsignal12.TurnOff(); m_headsignal12.TurnOff();
m_headsignal13.TurnOff(); m_headsignal13.TurnOff();
m_headsignal22.TurnOff(); m_headsignal22.TurnOff();
@@ -5002,12 +5247,14 @@ TDynamicObject::radius() const {
// McZapkie-250202 // McZapkie-250202
// wczytywanie pliku z danymi multimedialnymi (dzwieki) // wczytywanie pliku z danymi multimedialnymi (dzwieki)
void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string const &ReplacableSkin ) { void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string const &ReplacableSkin ) {
rTypeName = TypeName;
rReplacableSkin = ReplacableSkin;
Global.asCurrentDynamicPath = asBaseDir; Global.asCurrentDynamicPath = asBaseDir;
std::string asFileName = asBaseDir + TypeName + ".mmd"; std::string asFileName = asBaseDir + TypeName + ".mmd";
std::string asAnimName; std::string asAnimName;
bool Stop_InternalData = false; bool Stop_InternalData = false;
pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów
wipers = NULL; // wskaznik pierwszego obiektu animujacego dla wycieraczek
{ {
// preliminary check whether the file exists // preliminary check whether the file exists
cParser parser( TypeName + ".mmd", cParser::buffer_FILE, asBaseDir ); cParser parser( TypeName + ".mmd", cParser::buffer_FILE, asBaseDir );
@@ -5094,16 +5341,20 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
pAnimations.resize( iAnimations ); pAnimations.resize( iAnimations );
int i, j, k = 0, sm = 0; int i, j, k = 0, sm = 0;
for (j = 0; j < ANIM_TYPES; ++j) for (j = 0; j < ANIM_TYPES; ++j) // petla po wszystkich wpisach w animations
for (i = 0; i < iAnimType[j]; ++i) for (i = 0; i < iAnimType[j]; ++i) // petla iteruje sie tyle razy ile mamy wpisane w animations
{ {
if (j == ANIM_PANTS) // zliczamy poprzednie animacje if (j == ANIM_PANTS) // zliczamy poprzednie animacje
if (!pants) if (!pants)
if (iAnimType[ANIM_PANTS]) // o ile jakieś pantografy są (a domyślnie są) if (iAnimType[ANIM_PANTS]) // o ile jakieś pantografy są (a domyślnie są)
pants = &pAnimations[k]; // zapamiętanie na potrzeby wyszukania submodeli pants = &pAnimations[k]; // zapamiętanie na potrzeby wyszukania submodeli
if (j == ANIM_WIPERS)
if (!wipers)
if (iAnimType[ANIM_WIPERS])
wipers = &pAnimations[k];
pAnimations[k].iShift = sm; // przesunięcie do przydzielenia wskaźnika pAnimations[k].iShift = sm; // przesunięcie do przydzielenia wskaźnika
sm += pAnimations[k++].TypeSet(j); // ustawienie typu animacji i zliczanie tablicowanych submodeli sm += pAnimations[k++].TypeSet(j, *MoverParameters); // ustawienie typu animacji i zliczanie tablicowanych submodeli
} }
if (sm) // o ile są bardziej złożone animacje if (sm) // o ile są bardziej złożone animacje
{ {
pAnimated = new TSubModel *[sm]; // tabela na animowane submodele pAnimated = new TSubModel *[sm]; // tabela na animowane submodele
@@ -5673,6 +5924,52 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
} }
} }
else if (token == "animwiperprefix:")
{
parser.getTokens(1, false);
parser >> token;
TSubModel *sm;
if (wipers)
{
for (int i = 0; i < iAnimType[ANIM_WIPERS]; i++) // zebranie wszystkich submodeli wycieraczek
{
dWiperPos.emplace_back(0.0); // dodajemy na koniec zeby sie miejsce tam zrobilo i nie bylo invalid addressow potem
asAnimName = token + std::to_string(i + 1);
// element wycieraczki nr 1
sm = GetSubmodelFromName(mdModel, asAnimName + "_p1");
wipers[i].smElement[0] = sm;
if (sm)
{
wipers[i].smElement[0]->WillBeAnimated();
// auto const offset{wipers[i].smElement[0]->offset()};
}
// element wycieraczki nr 2
sm = GetSubmodelFromName(mdModel, asAnimName + "_p2");
wipers[i].smElement[1] = sm;
if (sm)
{
wipers[i].smElement[1]->WillBeAnimated();
// auto const offset{wipers[i].smElement[0]->offset()};
}
// element wycieraczki nr 3
sm = GetSubmodelFromName(mdModel, asAnimName + "_p3");
wipers[i].smElement[2] = sm;
if (sm)
{
wipers[i].smElement[2]->WillBeAnimated();
// auto const offset{wipers[i].smElement[0]->offset()};
}
wipers[i].yUpdate = std::bind(&TDynamicObject::UpdateWiper, this, std::placeholders::_1);
wipers[i].fMaxDist = 150 * 150;
wipers[i].iNumber = i;
}
}
}
} while( ( token != "" ) } while( ( token != "" )
&& ( token != "endmodels" ) ); && ( token != "endmodels" ) );
@@ -6424,6 +6721,19 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
m_powertrainsounds.rsEngageSlippery.m_frequencyfactor /= ( 1 + MoverParameters->nmax ); m_powertrainsounds.rsEngageSlippery.m_frequencyfactor /= ( 1 + MoverParameters->nmax );
} }
// dzwieki wycieraczkuf
else if (token == "wiperFromPark:")
{
sWiperFromPark.deserialize(parser, sound_type::single);
sWiperFromPark.owner(this);
}
else if (token == "wiperToPark:")
{
sWiperToPark.deserialize(parser, sound_type::single);
sWiperToPark.owner(this);
}
else if (token == "retarder:") { else if (token == "retarder:") {
m_powertrainsounds.retarder.deserialize(parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency); m_powertrainsounds.retarder.deserialize(parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency);
m_powertrainsounds.retarder.owner(this); m_powertrainsounds.retarder.owner(this);
@@ -7000,7 +7310,6 @@ void TDynamicObject::Damage(char flag)
}; };
void TDynamicObject::SetLights() { void TDynamicObject::SetLights() {
auto const isfrontcaboccupied { MoverParameters->CabOccupied * DirectionGet() >= 0 }; auto const isfrontcaboccupied { MoverParameters->CabOccupied * DirectionGet() >= 0 };
int const automaticmarkers { MoverParameters->CabActive == 0 && ( MoverParameters->InactiveCabFlag & activation::redmarkers ) int const automaticmarkers { MoverParameters->CabActive == 0 && ( MoverParameters->InactiveCabFlag & activation::redmarkers )
? light::redmarker_left + light::redmarker_right : 0 }; ? light::redmarker_left + light::redmarker_right : 0 };
@@ -7054,6 +7363,47 @@ void TDynamicObject::RaLightsSet(int head, int rear)
if( head >= 0 ) { if( head >= 0 ) {
auto const vehicleend { iDirection > 0 ? end::front : end::rear }; auto const vehicleend { iDirection > 0 ? end::front : end::rear };
MoverParameters->iLights[ vehicleend ] = ( head & iInventory[ vehicleend ] ); MoverParameters->iLights[ vehicleend ] = ( head & iInventory[ vehicleend ] );
bool tLeft = MoverParameters->iLights[vehicleend] & (light::auxiliary_left | light::headlight_left); // roboczo czy jakiekolwiek swiatlo z lewej jest zapalone
bool tRight = MoverParameters->iLights[vehicleend] & (light::auxiliary_right | light::headlight_right); // a tu z prawej
if (Controller == Humandriver) {
switch (MoverParameters->modernDimmerState)
{
case 0:
// wylaczone
MoverParameters->iLights[vehicleend] &= 0 | light::rearendsignals; // zostawiamy tylko tabliczki jesli sa
HighBeamLights = false;
DimHeadlights = false;
break;
case 1:
// przyciemnione normalne
DimHeadlights = true; // odpalamy przyciemnienie normalnych reflektorow
HighBeamLights = false;
break;
case 3:
// dlugie przyciemnione
DimHeadlights = true;
HighBeamLights = true;
MoverParameters->iLights[vehicleend] &=
light::headlight_upper | light::rearendsignals | light::redmarker_left | light::redmarker_right | light::rearendsignals; // nie ruszamy gornych i koncowek
MoverParameters->iLights[vehicleend] |= tLeft ? light::highbeamlight_left : 0; // jesli swiatlo z lewej zapalone to odpal dlugie
MoverParameters->iLights[vehicleend] |= tRight ? light::highbeamlight_right : 0; // a tu z prawej
break;
case 4:
// zwykle dlugie
DimHeadlights = false;
HighBeamLights = true;
MoverParameters->iLights[vehicleend] &=
light::headlight_upper | light::rearendsignals | light::redmarker_left | light::redmarker_right | light::rearendsignals; // nie ruszamy gornych i koncowek
MoverParameters->iLights[vehicleend] |= tLeft ? light::highbeamlight_left : 0; // jesli swiatlo z lewej zapalone to odpal dlugie
MoverParameters->iLights[vehicleend] |= tRight ? light::highbeamlight_right : 0; // a tu z prawej
break;
default: // to case 2 - zwykle
DimHeadlights = false;
HighBeamLights = false;
break;
}
}
} }
if( rear >= 0 ) { if( rear >= 0 ) {
auto const vehicleend{ iDirection > 0 ? end::rear : end::front }; auto const vehicleend{ iDirection > 0 ? end::rear : end::front };
@@ -7660,9 +8010,9 @@ TDynamicObject::update_shake( double const Timedelta ) {
if( iVel > 0.5 ) { if( iVel > 0.5 ) {
// acceleration-driven base shake // acceleration-driven base shake
shakevector += Math3D::vector3( shakevector += Math3D::vector3(
-MoverParameters->AccN * Timedelta * 5.0, // highlight side sway -MoverParameters->AccN * Timedelta * 5.0 * Global.ShakingMultiplierRL, // highlight side sway
-MoverParameters->AccVert * Timedelta, -MoverParameters->AccVert * Timedelta * Global.ShakingMultiplierUD,
-MoverParameters->AccSVBased * Timedelta * 1.5); // accent acceleration/deceleration -MoverParameters->AccSVBased * Timedelta * 1.5 * Global.ShakingMultiplierBF); // accent acceleration/deceleration
} }
auto shake { 1.25 * ShakeSpring.ComputateForces( shakevector, ShakeState.offset ) }; auto shake { 1.25 * ShakeSpring.ComputateForces( shakevector, ShakeState.offset ) };
@@ -7923,7 +8273,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
// youBy - przenioslem, bo diesel tez moze miec turbo // youBy - przenioslem, bo diesel tez moze miec turbo
if( Vehicle.TurboTest > 0 ) { if( Vehicle.TurboTest > 0 ) {
// udawanie turbo: // udawanie turbo:
auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax * Vehicle.dizel_fill : 1 }; auto const pitch_diesel{(Vehicle.EngineType == TEngineType::DieselEngine || Vehicle.EngineType == TEngineType::DieselElectric) ? Vehicle.enrot / Vehicle.dizel_nmax * Vehicle.dizel_fill : 1};
auto const goalpitch { std::max( 0.025, ( /*engine_volume **/ pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; auto const goalpitch { std::max( 0.025, ( /*engine_volume **/ pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) };
auto const goalvolume { ( auto const goalvolume { (
( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ? ( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ?

View File

@@ -22,6 +22,8 @@ http://mozilla.org/MPL/2.0/.
#include "sound.h" #include "sound.h"
#include "Spring.h" #include "Spring.h"
#include <vector>
#define EU07_SOUND_BOGIESOUNDS #define EU07_SOUND_BOGIESOUNDS
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -36,7 +38,8 @@ int const ANIM_PANTS = 5; // pantografy
int const ANIM_STEAMS = 6; // napęd parowozu int const ANIM_STEAMS = 6; // napęd parowozu
int const ANIM_DOORSTEPS = 7; int const ANIM_DOORSTEPS = 7;
int const ANIM_MIRRORS = 8; int const ANIM_MIRRORS = 8;
int const ANIM_TYPES = 9; // Ra: ilość typów animacji int const ANIM_WIPERS = 9;
int const ANIM_TYPES = 10; // Ra: ilość typów animacji
class TAnim; class TAnim;
//typedef void(__closure *TUpdate)(TAnim *pAnim); // typ funkcji aktualizującej położenie submodeli //typedef void(__closure *TUpdate)(TAnim *pAnim); // typ funkcji aktualizującej położenie submodeli
@@ -103,7 +106,17 @@ class TAnimPant
float fWidthExtra; // dodatkowy rozmiar poziomy poza część roboczą (fWidth) float fWidthExtra; // dodatkowy rozmiar poziomy poza część roboczą (fWidth)
float fHeightExtra[5]; //łamana symulująca kształt nabieżnika float fHeightExtra[5]; //łamana symulująca kształt nabieżnika
// double fHorizontal; //Ra 2015-01: położenie drutu względem osi pantografu // double fHorizontal; //Ra 2015-01: położenie drutu względem osi pantografu
// factory ktore mozna nadpisac z fiza
float rd1rf{1.f}; // mnoznik obrotu ramienia dolnego 1
float rd2rf{1.f}; // mnoznik obrotu ramienia dolnego 2
float rg1rf{1.f}; // mnoznik obrotu ramienia gornego 1
float rg2rf{1.f}; // mnoznik obrotu ramienia gornego 2
float slizgrf{1.f}; // mnoznik obrotu slizgacza
void AKP_4E(); void AKP_4E();
void WBL85();
void DSAx();
void EC160_200();
}; };
class TAnim class TAnim
@@ -115,8 +128,8 @@ public:
// destructor // destructor
~TAnim(); ~TAnim();
// methods // methods
int TypeSet( int i, int fl = 0 ); // ustawienie typu int TypeSet(int i, TMoverParameters currentMover, int fl = 0); // ustawienie typu
// members // members
union union
{ {
TSubModel *smAnimated; // animowany submodel (jeśli tylko jeden, np. oś) TSubModel *smAnimated; // animowany submodel (jeśli tylko jeden, np. oś)
@@ -209,7 +222,11 @@ public:
inline TDynamicObject *PrevConnected() const { return MoverParameters->Neighbours[ end::front ].vehicle; }; // pojazd podłączony od strony sprzęgu 0 (kabina 1) inline TDynamicObject *PrevConnected() const { return MoverParameters->Neighbours[ end::front ].vehicle; }; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
inline int NextConnectedNo() const { return MoverParameters->Neighbours[ end::rear ].vehicle_end; } inline int NextConnectedNo() const { return MoverParameters->Neighbours[ end::rear ].vehicle_end; }
inline int PrevConnectedNo() const { return MoverParameters->Neighbours[ end::front ].vehicle_end; } inline int PrevConnectedNo() const { return MoverParameters->Neighbours[ end::front ].vehicle_end; }
// double fTrackBlock; // odległość do przeszkody do dalszego ruchu (wykrywanie kolizji z innym pojazdem)
// Dev tools
void Reload();
// double fTrackBlock; // odległość do przeszkody do dalszego ruchu (wykrywanie kolizji z innym pojazdem)
// modele składowe pojazdu // modele składowe pojazdu
TModel3d *mdModel; // model pudła TModel3d *mdModel; // model pudła
@@ -277,7 +294,8 @@ private:
void UpdatePlatformTranslate(TAnim *pAnim); // doorstep animation, shift void UpdatePlatformTranslate(TAnim *pAnim); // doorstep animation, shift
void UpdatePlatformRotate(TAnim *pAnim); // doorstep animation, rotate void UpdatePlatformRotate(TAnim *pAnim); // doorstep animation, rotate
void UpdateMirror(TAnim *pAnim); // mirror animation void UpdateMirror(TAnim *pAnim); // mirror animation
/* void UpdateWiper(TAnim *pAnim); // wiper animation
/*
void UpdateLeverDouble(TAnim *pAnim); // animacja gałki zależna od double void UpdateLeverDouble(TAnim *pAnim); // animacja gałki zależna od double
void UpdateLeverFloat(TAnim *pAnim); // animacja gałki zależna od float void UpdateLeverFloat(TAnim *pAnim); // animacja gałki zależna od float
void UpdateLeverInt(TAnim *pAnim); // animacja gałki zależna od int (wartość) void UpdateLeverInt(TAnim *pAnim); // animacja gałki zależna od int (wartość)
@@ -301,6 +319,14 @@ private:
Math3D::vector3 vFloor; // podłoga dla ładunku Math3D::vector3 vFloor; // podłoga dla ładunku
public: public:
TAnim *pants; // indeks obiektu animującego dla pantografu 0 TAnim *pants; // indeks obiektu animującego dla pantografu 0
TAnim *wipers; // wycieraczki
std::vector<double> wiperOutTimer = std::vector<double>(8, 0.0);
std::vector<double> wiperParkTimer = std::vector<double>(8, 0.0);
std::vector<int> workingSwitchPos = std::vector<int>(8, 0); // working switch position (to not break wipers when switching modes)
std::vector<double> dWiperPos; // timing na osi czasu animacji wycieraczki
std::vector<bool> wiperDirection = std::vector<bool>(8, false); // false - return direction; true - out direction
std::vector<bool> wiper_playSoundFromStart = std::vector<bool>(8, false);
std::vector<bool> wiper_playSoundToStart = std::vector<bool>(8, false);
double NoVoltTime; // czas od utraty zasilania double NoVoltTime; // czas od utraty zasilania
double dMirrorMoveL{ 0.0 }; double dMirrorMoveL{ 0.0 };
double dMirrorMoveR{ 0.0 }; double dMirrorMoveR{ 0.0 };
@@ -469,13 +495,18 @@ private:
AirCoupler m_headlamp11; // oswietlenie czolowe - przod AirCoupler m_headlamp11; // oswietlenie czolowe - przod
AirCoupler m_headlamp12; AirCoupler m_headlamp12;
AirCoupler m_headlamp13; AirCoupler m_headlamp13;
AirCoupler m_highbeam12; // dlugie
AirCoupler m_highbeam13;
AirCoupler m_headlamp21; // oswietlenie czolowe - tyl AirCoupler m_headlamp21; // oswietlenie czolowe - tyl
AirCoupler m_headlamp22; AirCoupler m_headlamp22;
AirCoupler m_headlamp23; AirCoupler m_headlamp23;
AirCoupler m_highbeam22;
AirCoupler m_highbeam23;
AirCoupler m_headsignal12; AirCoupler m_headsignal12;
AirCoupler m_headsignal13; AirCoupler m_headsignal13;
AirCoupler m_headsignal22; AirCoupler m_headsignal22;
AirCoupler m_headsignal23; AirCoupler m_headsignal23;
TButton btExteriorOnly;
TButton btMechanik1; TButton btMechanik1;
TButton btMechanik2; TButton btMechanik2;
TButton btShutters1; // cooling shutters for primary water circuit TButton btShutters1; // cooling shutters for primary water circuit
@@ -515,6 +546,8 @@ private:
springbrake_sounds m_springbrakesounds; springbrake_sounds m_springbrakesounds;
sound_source rsSlippery { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab sound_source rsSlippery { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab
sound_source sSand { sound_placement::external }; sound_source sSand { sound_placement::external };
sound_source sWiperToPark { sound_placement::internal };
sound_source sWiperFromPark { sound_placement::internal };
// moving part and other external sounds // moving part and other external sounds
sound_source m_startjolt { sound_placement::general }; // movement start jolt, played once on initial acceleration at slow enough speed sound_source m_startjolt { sound_placement::general }; // movement start jolt, played once on initial acceleration at slow enough speed
bool m_startjoltplayed { false }; bool m_startjoltplayed { false };
@@ -569,8 +602,12 @@ private:
TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler ) const; TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler ) const;
void ABuCheckMyTrack(); void ABuCheckMyTrack();
std::string rTypeName; // nazwa typu pojazdu
std::string rReplacableSkin; // nazwa tekstury pojazdu
public: public:
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
bool HighBeamLights { false }; // status of the highbeam toggle
// checks whether there's unbroken connection of specified type to specified vehicle // checks whether there's unbroken connection of specified type to specified vehicle
bool is_connected( TDynamicObject const *Vehicle, coupling const Coupling = coupling::coupler ) const; bool is_connected( TDynamicObject const *Vehicle, coupling const Coupling = coupling::coupler ) const;
TDynamicObject * PrevAny() const; TDynamicObject * PrevAny() const;

View File

@@ -211,6 +211,15 @@ global_settings::ConfigParse(cParser &Parser) {
{ {
Parser.getTokens(); Parser.getTokens();
Parser >> MultipleLogs; Parser >> MultipleLogs;
}
else if (token == "shakefactor")
{
Parser.getTokens();
Parser >> ShakingMultiplierBF;
Parser.getTokens();
Parser >> ShakingMultiplierRL;
Parser.getTokens();
Parser >> ShakingMultiplierUD;
} }
else if (token == "logs.filter") else if (token == "logs.filter")
{ {

View File

@@ -16,6 +16,9 @@ http://mozilla.org/MPL/2.0/.
#include "light.h" #include "light.h"
#include "utilities.h" #include "utilities.h"
#include "motiontelemetry.h" #include "motiontelemetry.h"
#include "ref/discord-rpc/include/discord_rpc.h"
#include <map>
#ifdef WITH_UART #ifdef WITH_UART
#include "uart.h" #include "uart.h"
#endif #endif
@@ -27,6 +30,11 @@ struct global_settings {
// members // members
// data items // data items
// TODO: take these out of the settings // TODO: take these out of the settings
/// <summary>
/// Mapa z watkami w formacie <std::string nazwa, std::thread watek>
/// </summary>
std::map<std::string, std::thread> threads = {};
bool shiftState{ false }; //m7todo: brzydko bool shiftState{ false }; //m7todo: brzydko
bool ctrlState{ false }; bool ctrlState{ false };
bool altState{ false }; bool altState{ false };
@@ -117,7 +125,9 @@ struct global_settings {
glm::ivec2 window_size; // main window size in platform-specific virtual pixels glm::ivec2 window_size; // main window size in platform-specific virtual pixels
glm::ivec2 cursor_pos; // cursor position in platform-specific virtual pixels glm::ivec2 cursor_pos; // cursor position in platform-specific virtual pixels
glm::ivec2 fb_size; // main window framebuffer size glm::ivec2 fb_size; // main window framebuffer size
float ShakingMultiplierBF {1.f}; // mnożnik bujania kamera przod/tyl
float ShakingMultiplierRL {1.f}; // mnożnik bujania kamera lewo/prawo
float ShakingMultiplierUD {1.f}; // mnożnik bujania kamera gora/dol
float fDistanceFactor{ 1.f }; // baza do przeliczania odległości dla LoD float fDistanceFactor{ 1.f }; // baza do przeliczania odległości dla LoD
float targetfps{ 0.0f }; float targetfps{ 0.0f };
bool bFullScreen{ false }; bool bFullScreen{ false };

118
Logs.cpp
View File

@@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/.
#include "winheaders.h" #include "winheaders.h"
#include "utilities.h" #include "utilities.h"
#include "uilayer.h" #include "uilayer.h"
#include <deque>
std::ofstream output; // standardowy "log.txt", można go wyłączyć std::ofstream output; // standardowy "log.txt", można go wyłączyć
std::ofstream errors; // lista błędów "errors.txt", zawsze działa std::ofstream errors; // lista błędów "errors.txt", zawsze działa
@@ -68,61 +69,88 @@ std::string filename_scenery() {
} }
} }
// log service stacks
std::deque<char *> InfoStack;
std::deque<char *> ErrorStack;
void LogService()
{
while (true)
{
// loop for logging
// write logs and log.txt
while (!InfoStack.empty())
{
char *msg = InfoStack.front(); // get first element of stack
InfoStack.pop_front();
if (Global.iWriteLogEnabled & 1)
{
if (!output.is_open())
{
std::string const filename = (Global.MultipleLogs ? "logs/log (" + filename_scenery() + ") " + filename_date() + ".txt" : "log.txt");
output.open(filename, std::ios::trunc);
}
output << msg << "\n";
output.flush();
}
log_scrollback.emplace_back(std::string(msg));
if (log_scrollback.size() > 200)
log_scrollback.pop_front();
if (Global.iWriteLogEnabled & 2)
{
#ifdef _WIN32
// hunter-271211: pisanie do konsoli tylko, gdy nie jest ukrywana
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
DWORD wr = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), msg, (DWORD)strlen(msg), &wr, NULL);
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), endstring, (DWORD)strlen(endstring), &wr, NULL);
#else
printf("%s\n", msg);
#endif
}
}
// write to errors.txt
while (!ErrorStack.empty())
{
char *msg = ErrorStack.front();
ErrorStack.pop_front();
if (!(Global.iWriteLogEnabled & 1))
return;
if (!errors.is_open())
{
std::string const filename = (Global.MultipleLogs ? "logs/errors (" + filename_scenery() + ") " + filename_date() + ".txt" : "errors.txt");
errors.open(filename, std::ios::trunc);
errors << "EU07.EXE " + Global.asVersion << "\n";
}
errors << msg << "\n";
errors.flush();
}
std::this_thread::sleep_for(std::chrono::milliseconds(5)); // dont burn cpu so much
}
}
void WriteLog( const char *str, logtype const Type ) { void WriteLog( const char *str, logtype const Type ) {
if( str == nullptr ) { return; } if( str == nullptr ) { return; }
if( true == TestFlag( Global.DisabledLogTypes, static_cast<unsigned int>( Type ) ) ) { return; } if( true == TestFlag( Global.DisabledLogTypes, static_cast<unsigned int>( Type ) ) ) { return; }
InfoStack.emplace_back(strdup(str));
if (Global.iWriteLogEnabled & 1) {
if( !output.is_open() ) {
std::string const filename =
( Global.MultipleLogs ?
"logs/log (" + filename_scenery() + ") " + filename_date() + ".txt" :
"log.txt" );
output.open( filename, std::ios::trunc );
}
output << str << "\n";
output.flush();
}
log_scrollback.emplace_back(std::string(str));
if (log_scrollback.size() > 200)
log_scrollback.pop_front();
if( Global.iWriteLogEnabled & 2 ) {
#ifdef _WIN32
// hunter-271211: pisanie do konsoli tylko, gdy nie jest ukrywana
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), FOREGROUND_GREEN | FOREGROUND_INTENSITY );
DWORD wr = 0;
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), str, (DWORD)strlen( str ), &wr, NULL );
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), endstring, (DWORD)strlen( endstring ), &wr, NULL );
#else
printf("%s\n", str);
#endif
}
} }
void ErrorLog( const char *str, logtype const Type ) { void ErrorLog( const char *str, logtype const Type ) {
if( str == nullptr ) { return; } if( str == nullptr ) { return; }
if( true == TestFlag( Global.DisabledLogTypes, static_cast<unsigned int>( Type ) ) ) { return; } if( true == TestFlag( Global.DisabledLogTypes, static_cast<unsigned int>( Type ) ) ) { return; }
ErrorStack.emplace_back(strdup(str));
if (!(Global.iWriteLogEnabled & 1))
return;
if (!errors.is_open()) {
std::string const filename =
( Global.MultipleLogs ?
"logs/errors (" + filename_scenery() + ") " + filename_date() + ".txt" :
"errors.txt" );
errors.open( filename, std::ios::trunc );
errors << "EU07.EXE " + Global.asVersion << "\n";
}
errors << str << "\n";
errors.flush();
}; };
void Error(const std::string &asMessage, bool box) void Error(const std::string &asMessage, bool box)

2
Logs.h
View File

@@ -23,7 +23,7 @@ enum class logtype : unsigned int {
traction = ( 1 << 9 ), traction = ( 1 << 9 ),
powergrid = ( 1 << 10 ), powergrid = ( 1 << 10 ),
}; };
void LogService();
void WriteLog( const char *str, logtype const Type = logtype::generic ); void WriteLog( const char *str, logtype const Type = logtype::generic );
void Error( const std::string &asMessage, bool box = false ); void Error( const std::string &asMessage, bool box = false );
void Error( const char* &asMessage, bool box = false ); void Error( const char* &asMessage, bool box = false );

File diff suppressed because it is too large Load Diff

View File

@@ -8927,7 +8927,7 @@ bool startBPT;
bool startMPT, startMPT0; bool startMPT, startMPT0;
bool startRLIST, startUCLIST; bool startRLIST, startUCLIST;
bool startDIZELMOMENTUMLIST, startDIZELV2NMAXLIST, startHYDROTCLIST, startPMAXLIST; bool startDIZELMOMENTUMLIST, startDIZELV2NMAXLIST, startHYDROTCLIST, startPMAXLIST;
bool startDLIST, startFFLIST, startWWLIST; bool startDLIST, startFFLIST, startWWLIST, startWiperList;
bool startLIGHTSLIST; bool startLIGHTSLIST;
bool startCOMPRESSORLIST; bool startCOMPRESSORLIST;
int LISTLINE; int LISTLINE;
@@ -9279,6 +9279,25 @@ bool TMoverParameters::readFFList( std::string const &line ) {
return true; return true;
} }
// parsowanie wiperList
bool TMoverParameters::readWiperList(std::string const& line)
{
cParser parser(line);
if (false == parser.getTokens(4, false))
{
WriteLog("Read WiperList: arguments missing in line " + std::to_string(LISTLINE + 1));
return false;
}
int idx = LISTLINE++;
if (idx >= sizeof(WiperList) / sizeof(TWiperScheme))
{
WriteLog("Read WiperList: number of entries exceeded capacity of the data table");
return false;
}
parser >> WiperList[idx].byteSum >> WiperList[idx].WiperSpeed >> WiperList[idx].interval >> WiperList[idx].outBackDelay;
return true;
}
// parsowanie WWList // parsowanie WWList
bool TMoverParameters::readWWList( std::string const &line ) { bool TMoverParameters::readWWList( std::string const &line ) {
@@ -9308,7 +9327,6 @@ bool TMoverParameters::readWWList( std::string const &line ) {
SST[ idx ].Pmin = std::sqrt( std::pow( SST[ idx ].Umin, 2 ) / 47.6 ); SST[ idx ].Pmin = std::sqrt( std::pow( SST[ idx ].Umin, 2 ) / 47.6 );
SST[ idx ].Pmax = std::min( SST[ idx ].Pmax, std::pow( SST[ idx ].Umax, 2 ) / 47.6 ); SST[ idx ].Pmax = std::min( SST[ idx ].Pmax, std::pow( SST[ idx ].Umax, 2 ) / 47.6 );
} }
return true; return true;
} }
@@ -9444,6 +9462,7 @@ void TMoverParameters::BrakeSubsystemDecode()
// ************************************************************************************************* // *************************************************************************************************
bool TMoverParameters::LoadFIZ(std::string chkpath) bool TMoverParameters::LoadFIZ(std::string chkpath)
{ {
chkPath = chkpath; // assign class path for reloading
const int param_ok = 1; const int param_ok = 1;
const int wheels_ok = 2; const int wheels_ok = 2;
const int dimensions_ok = 4; const int dimensions_ok = 4;
@@ -9462,6 +9481,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
startPMAXLIST = false; startPMAXLIST = false;
startFFLIST = false; startFFLIST = false;
startWWLIST = false; startWWLIST = false;
startWiperList = false;
startLIGHTSLIST = false; startLIGHTSLIST = false;
startCOMPRESSORLIST = false; startCOMPRESSORLIST = false;
std::string file = TypeName + ".fiz"; std::string file = TypeName + ".fiz";
@@ -9562,6 +9582,13 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
startFFLIST = false; startFFLIST = false;
continue; continue;
} }
if (issection("endwl", inputline))
{
// skonczylismy czytac liste konfiguracji wycieraczek
startBPT = false;
startWiperList = false;
continue;
}
if( issection( "END-WWL", inputline ) ) { if( issection( "END-WWL", inputline ) ) {
startBPT = false; startBPT = false;
startWWLIST = false; startWWLIST = false;
@@ -9666,6 +9693,14 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
continue; continue;
} }
if (issection("Headlights:", inputline))
{
startBPT = false;
fizlines.emplace("Headlights", inputline);
LoadFIZ_Headlights(inputline);
continue;
}
if (issection("Blending:", inputline)) { if (issection("Blending:", inputline)) {
startBPT = false; LISTLINE = 0; startBPT = false; LISTLINE = 0;
@@ -9845,9 +9880,22 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
{ {
startBPT = false; startBPT = false;
startWWLIST = true; LISTLINE = 0; startWWLIST = true; LISTLINE = 0;
continue; continue;
} }
if (issection("WiperList:", inputline))
{
startBPT = false;
fizlines.emplace("WiperList", inputline);
startWiperList = true;
LISTLINE = 0;
LoadFIZ_WiperList(inputline);
continue;
}
if( issection( "LightsList:", inputline ) ) { if( issection( "LightsList:", inputline ) ) {
startBPT = false; startBPT = false;
fizlines.emplace( "LightsList", inputline ); fizlines.emplace( "LightsList", inputline );
@@ -9914,6 +9962,11 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
readWWList( inputline ); readWWList( inputline );
continue; continue;
} }
if (true == startWiperList)
{
readWiperList(inputline);
continue;
}
if( true == startLIGHTSLIST ) { if( true == startLIGHTSLIST ) {
readLightsList( inputline ); readLightsList( inputline );
continue; continue;
@@ -9935,6 +9988,13 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
else else
result = false; result = false;
if (!modernContainOffPos)
modernDimmerState = 2; // jak nie ma opcji wylaczonej to niech sie odpali normalnie
if (!enableModernDimmer)
{
modernDimmerState = 2;
}
WriteLog("CERROR: " + to_string(ConversionError) + ", SUCCES: " + to_string(result)); WriteLog("CERROR: " + to_string(ConversionError) + ", SUCCES: " + to_string(result));
return result; return result;
} }
@@ -10026,6 +10086,18 @@ void TMoverParameters::LoadFIZ_Load( std::string const &line ) {
extract_value( UnLoadSpeed, "UnLoadSpeed", line, "" ); extract_value( UnLoadSpeed, "UnLoadSpeed", line, "" );
} }
void TMoverParameters::LoadFIZ_Headlights(std::string const &line)
{
extract_value(refR, "LampRed", line, "");
extract_value(refG, "LampGreen", line, "");
extract_value(refB, "LampBlue", line, "");
extract_value(dimMultiplier, "DimmedMultiplier", line, "");
extract_value(normMultiplier, "NormalMultiplier", line, "");
extract_value(highDimMultiplier, "HighbeamDimmedMultiplier", line, "");
extract_value(highMultiplier, "HighBeamMultiplier", line, "");
}
void TMoverParameters::LoadFIZ_Dimensions( std::string const &line ) { void TMoverParameters::LoadFIZ_Dimensions( std::string const &line ) {
extract_value( Dim.L, "L", line, "" ); extract_value( Dim.L, "L", line, "" );
@@ -10602,6 +10674,12 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
extract_value(HideDirStatusWhenMoving, "HideDirStatusWhenMoving", line, ""); extract_value(HideDirStatusWhenMoving, "HideDirStatusWhenMoving", line, "");
extract_value(HideDirStatusSpeed, "HideDirStatusSpeed", line, ""); extract_value(HideDirStatusSpeed, "HideDirStatusSpeed", line, "");
extract_value(isDoubleClickForMeasureNeeded, "DCMB", line, "");
extract_value(DistanceCounterDoublePressPeriod, "DCDPP", line, "");
extract_value(isBatteryButtonImpulse, "IBTB", line, "");
extract_value(shouldHoldBatteryButton, "SBBBH", line, "");
extract_value(BatteryButtonHoldTime, "BBHT", line, "");
std::map<std::string, start_t> starts { std::map<std::string, start_t> starts {
{ "Disabled", start_t::disabled }, { "Disabled", start_t::disabled },
@@ -11120,6 +11198,8 @@ void TMoverParameters::LoadFIZ_Switches( std::string const &Input ) {
extract_value( UniversalResetButtonFlag[ 0 ], "RelayResetButton1", Input, "" ); extract_value( UniversalResetButtonFlag[ 0 ], "RelayResetButton1", Input, "" );
extract_value( UniversalResetButtonFlag[ 1 ], "RelayResetButton2", Input, "" ); extract_value( UniversalResetButtonFlag[ 1 ], "RelayResetButton2", Input, "" );
extract_value( UniversalResetButtonFlag[ 2 ], "RelayResetButton3", Input, "" ); extract_value( UniversalResetButtonFlag[ 2 ], "RelayResetButton3", Input, "" );
extract_value(enableModernDimmer, "ModernDimmer", Input, "");
extract_value(modernContainOffPos, "ModernDimmerOffPosition", Input, "");
// pantograph presets // pantograph presets
{ {
auto &presets { PantsPreset.first }; auto &presets { PantsPreset.first };
@@ -11242,6 +11322,13 @@ void TMoverParameters::LoadFIZ_FFList( std::string const &Input ) {
extract_value( RlistSize, "Size", Input, "" ); extract_value( RlistSize, "Size", Input, "" );
} }
void TMoverParameters::LoadFIZ_WiperList(std::string const &Input)
{
extract_value(WiperListSize, "Size", Input, "");
extract_value(WiperAngle, "Angle", Input, "");
}
void TMoverParameters::LoadFIZ_LightsList( std::string const &Input ) { void TMoverParameters::LoadFIZ_LightsList( std::string const &Input ) {
extract_value( LightsPosNo, "Size", Input, "" ); extract_value( LightsPosNo, "Size", Input, "" );
@@ -11306,6 +11393,17 @@ void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparamet
auto &collectorparameters = Powerparameters.CollectorParameters; auto &collectorparameters = Powerparameters.CollectorParameters;
collectorparameters = TCurrentCollector { 0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, 0 }; collectorparameters = TCurrentCollector { 0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, 0 };
std::string PantType = "";
extract_value(PantType, "PantType", Line, "");
if (PantType == "AKP_4E")
collectorparameters.PantographType = TPantType::AKP_4E;
if (PantType._Starts_with("DSA")) // zakladam ze wszystkie pantografy DSA sa takie same
collectorparameters.PantographType = TPantType::DSAx;
if (PantType == "EC160" || PantType == "EC200")
collectorparameters.PantographType = TPantType::EC160_200;
if (PantType == "WBL85")
collectorparameters.PantographType = TPantType::WBL85;
extract_value( collectorparameters.CollectorsNo, "CollectorsNo", Line, "" ); extract_value( collectorparameters.CollectorsNo, "CollectorsNo", Line, "" );
extract_value( collectorparameters.MinH, "MinH", Line, "" ); extract_value( collectorparameters.MinH, "MinH", Line, "" );
@@ -12442,6 +12540,24 @@ double TMoverParameters::ShowCurrentP(int AmpN) const
} }
} }
bool TMoverParameters::reload_FIZ() {
WriteLog("[DEV] Reloading FIZ for " + Name);
// pause simulation
Global.iPause |= 0b1000;
bool result = LoadFIZ(chkPath);
if (result == true)
{
// jesli sie udalo przeladowac FIZ
Global.iPause &= 0b0111;
WriteLog("[DEV] FIZ reloaded for " + Name);
}
else {
// failed to reload - exit simulator
ErrorLog("[DEV] Failed to reload fiz for vehicle " + Name);
}
return true;
}
namespace simulation { namespace simulation {
weights_table Weights; weights_table Weights;

View File

@@ -105,6 +105,38 @@ void render_task::run() {
if( outputwidth != nullptr ) { Py_DECREF( outputwidth ); } if( outputwidth != nullptr ) { Py_DECREF( outputwidth ); }
Py_DECREF( output ); Py_DECREF( output );
} }
// get commands from renderer
auto *commandsPO = PyObject_CallMethod(m_renderer, "getCommands", nullptr);
if (commandsPO != nullptr)
{
std::vector<std::string> commands = python_external_utils::PyObjectToStringArray(commandsPO);
Py_DECREF(commandsPO);
// we perform any actions ONLY when there are any commands in buffer
if (!commands.empty())
{
for (const auto &command : commands)
{
auto it = simulation::commandMap.find(command);
if (it != simulation::commandMap.end())
{
// command found
command_data cd;
cd.command = it->second;
cd.action = GLFW_PRESS;
simulation::Commands.push(cd, static_cast<std::size_t>(command_target::vehicle) | 1); // player train is always 1
}
else
ErrorLog("Python: Command [" + command + "] not found!");
}
}
}
} }
void render_task::upload() void render_task::upload()
@@ -470,6 +502,43 @@ python_taskqueue::error() {
} }
} }
std::vector<std::string> python_external_utils::PyObjectToStringArray(PyObject *pyList)
{
std::vector<std::string> result;
std::vector<std::string> emptyIfError = {};
if (!PySequence_Check(pyList))
{
ErrorLog("Python: Failed to convert PyObject -> vector<string>");
return emptyIfError;
}
Py_ssize_t size = PySequence_Size(pyList);
for (Py_ssize_t i = 0; i < size; ++i)
{
PyObject *item = PySequence_GetItem(pyList, i); // Increments reference count
if (item == nullptr)
{
ErrorLog("Python: Failed to get item from sequence.");
return emptyIfError;
}
const char *str = PyString_AsString(item);
if (str == nullptr)
{
Py_DECREF(item);
ErrorLog("Python: Failed to convert item to string.");
return emptyIfError;
}
result.push_back(std::string(str));
Py_DECREF(item); // Decrease reference count for the item
}
return result;
}
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif

10
PyInt.h
View File

@@ -130,7 +130,8 @@ private:
auto fetch_renderer( std::string const Renderer ) -> PyObject *; auto fetch_renderer( std::string const Renderer ) -> PyObject *;
void run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit ); void run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit );
void error(); void error();
// members
// members
PyObject *m_main { nullptr }; PyObject *m_main { nullptr };
PyObject *m_stderr { nullptr }; PyObject *m_stderr { nullptr };
PyThreadState *m_mainthread{ nullptr }; PyThreadState *m_mainthread{ nullptr };
@@ -143,4 +144,11 @@ private:
bool m_initialized { false }; bool m_initialized { false };
}; };
class python_external_utils
{
public:
static std::vector<std::string> PyObjectToStringArray(PyObject *pyList);
};
#endif #endif

View File

@@ -50,7 +50,7 @@ MaSzyna should work and compile natively under **Linux** and **Windows**. Other
Commands will be written in [`Bash`](https://www.gnu.org/software/bash/). No-Linux users must do in corresponding technology. Commands will be written in [`Bash`](https://www.gnu.org/software/bash/). No-Linux users must do in corresponding technology.
0. Clone source code. 0. Clone source code.
You may download source code [as ZIP archive](https://github.com/eu07/maszyna/archive/master.zip), or clone it by [`Git`](https://git-scm.com/). We won't provide tutorial to second one, the only note worth mention is that, repository doesn't contain submodules, so `--recursive` is not needed. From now, it is assumed that your working directory is inside directory with unpacked source code. You may download source code [as ZIP archive](https://github.com/eu07/maszyna/archive/master.zip), or clone it by [`Git`](https://git-scm.com/). We won't provide tutorial to second one, the only note worth mention is that, repository contain submodules, so `--recursive` is needed. From now, it is assumed that your working directory is inside directory with unpacked source code.
1. Make directory, where build files will be stored, then enter inside it. 1. Make directory, where build files will be stored, then enter inside it.
$ mkdir build $ mkdir build

View File

@@ -40,7 +40,7 @@ Math3D::vector3 TSpring::ComputateForces( Math3D::vector3 const &pPosition1, Mat
// ScaleVector(&deltaP,1.0f / dist, &springForce); // Normalize Distance Vector // ScaleVector(&deltaP,1.0f / dist, &springForce); // Normalize Distance Vector
// ScaleVector(&springForce,-(Hterm + Dterm),&springForce); // Calc Force // ScaleVector(&springForce,-(Hterm + Dterm),&springForce); // Calc Force
springForce = deltaP / dist * ( -( Hterm + Dterm ) ); springForce = deltaP / dist * ( -( Hterm + Dterm ));
// VectorSum(&p1->f,&springForce,&p1->f); // Apply to Particle 1 // VectorSum(&p1->f,&springForce,&p1->f); // Apply to Particle 1
// VectorDifference(&p2->f,&springForce,&p2->f); // - Force on Particle 2 // VectorDifference(&p2->f,&springForce,&p2->f); // - Force on Particle 2
} }

424
Train.cpp
View File

@@ -288,6 +288,10 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::pantographraiserear, &TTrain::OnCommand_pantographraiserear }, { user_command::pantographraiserear, &TTrain::OnCommand_pantographraiserear },
{ user_command::pantographlowerfront, &TTrain::OnCommand_pantographlowerfront }, { user_command::pantographlowerfront, &TTrain::OnCommand_pantographlowerfront },
{ user_command::pantographlowerrear, &TTrain::OnCommand_pantographlowerrear }, { user_command::pantographlowerrear, &TTrain::OnCommand_pantographlowerrear },
{user_command::wiperswitchincrease, &TTrain::OnCommand_wiperswitchincrease},
{user_command::wiperswitchdecrease, &TTrain::OnCommand_wiperswitchdecrease},
{ user_command::pantographlowerall, &TTrain::OnCommand_pantographlowerall }, { user_command::pantographlowerall, &TTrain::OnCommand_pantographlowerall },
{ user_command::pantographselectnext, &TTrain::OnCommand_pantographselectnext }, { user_command::pantographselectnext, &TTrain::OnCommand_pantographselectnext },
{ user_command::pantographselectprevious, &TTrain::OnCommand_pantographselectprevious }, { user_command::pantographselectprevious, &TTrain::OnCommand_pantographselectprevious },
@@ -375,6 +379,8 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::headlighttogglerearupper, &TTrain::OnCommand_headlighttogglerearupper }, { user_command::headlighttogglerearupper, &TTrain::OnCommand_headlighttogglerearupper },
{ user_command::headlightenablerearupper, &TTrain::OnCommand_headlightenablerearupper }, { user_command::headlightenablerearupper, &TTrain::OnCommand_headlightenablerearupper },
{ user_command::headlightdisablerearupper, &TTrain::OnCommand_headlightdisablerearupper }, { user_command::headlightdisablerearupper, &TTrain::OnCommand_headlightdisablerearupper },
{user_command::modernlightdimmerdecrease, &TTrain::OnCommand_modernlightdimmerdecrease},
{user_command::modernlightdimmerincrease, &TTrain::OnCommand_modernlightdimmerincrease},
{ user_command::redmarkertogglerearleft, &TTrain::OnCommand_redmarkertogglerearleft }, { user_command::redmarkertogglerearleft, &TTrain::OnCommand_redmarkertogglerearleft },
{ user_command::redmarkerenablerearleft, &TTrain::OnCommand_redmarkerenablerearleft }, { user_command::redmarkerenablerearleft, &TTrain::OnCommand_redmarkerenablerearleft },
{ user_command::redmarkerdisablerearleft, &TTrain::OnCommand_redmarkerdisablerearleft }, { user_command::redmarkerdisablerearleft, &TTrain::OnCommand_redmarkerdisablerearleft },
@@ -1313,7 +1319,17 @@ void TTrain::OnCommand_distancecounteractivate( TTrain *Train, command_data cons
// visual feedback // visual feedback
Train->ggDistanceCounterButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggDistanceCounterButton.UpdateValue( 1.0, Train->dsbSwitch );
// activate or start anew // activate or start anew
Train->m_distancecounter = 0.f; if (Train->mvOccupied->isDoubleClickForMeasureNeeded) {
// handler tempomatu dla podwojnego kliku
if (Train->trainLenghtMeasureTimer >= 0.f) // jesli zdazylismy w czasie sekundy
Train->m_distancecounter = 0.f; // rozpoczynamy pomiar
else
Train->trainLenghtMeasureTimer = Train->mvOccupied->DistanceCounterDoublePressPeriod; // odpalamy zegarek od nowa
}
else {
// dla pojedynczego kliku
Train->m_distancecounter = 0.f;
}
} }
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
// visual feedback // visual feedback
@@ -2171,6 +2187,31 @@ void TTrain::OnCommand_mubrakingindicatortoggle( TTrain *Train, command_data con
} }
} }
void TTrain::OnCommand_wiperswitchincrease(TTrain *Train, command_data const &Command)
{
if (Command.action == GLFW_PRESS)
{
Train->mvOccupied->wiperSwitchPos++;
if (Train->mvOccupied->wiperSwitchPos > Train->mvOccupied->WiperListSize - 1)
Train->mvOccupied->wiperSwitchPos = Train->mvOccupied->WiperListSize - 1;
// Visual feedback
Train->ggWiperSw.UpdateValue(Train->mvOccupied->wiperSwitchPos, Train->dsbSwitch);
}
}
void TTrain::OnCommand_wiperswitchdecrease(TTrain *Train, command_data const &Command)
{
if (Command.action == GLFW_PRESS)
{
Train->mvOccupied->wiperSwitchPos--;
if (Train->mvOccupied->wiperSwitchPos < 0)
Train->mvOccupied->wiperSwitchPos = 0;
// visual feedback
Train->ggWiperSw.UpdateValue(Train->mvOccupied->wiperSwitchPos, Train->dsbSwitch);
}
}
void TTrain::OnCommand_reverserincrease( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_reverserincrease( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
@@ -2356,7 +2397,8 @@ void TTrain::OnCommand_cabsignalacknowledge( TTrain *Train, command_data const &
void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command )
{ {
if( Command.action != GLFW_REPEAT ) { if (Train->allowBatteryToggle || Command.action != GLFW_REPEAT)
{
// keep the switch from flipping back and forth if key is held down // keep the switch from flipping back and forth if key is held down
if( false == Train->mvOccupied->Power24vIsAvailable ) { if( false == Train->mvOccupied->Power24vIsAvailable ) {
// turn on // turn on
@@ -2370,44 +2412,160 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command
} }
void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) {
if (!Train->mvOccupied->isBatteryButtonImpulse)
{ // regular button behavior
if (Command.action == GLFW_PRESS)
{
// visual feedback
Train->ggBatteryButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->ggBatteryOnButton.UpdateValue(1.0f, Train->dsbSwitch);
if( Command.action == GLFW_PRESS ) { Train->mvOccupied->BatterySwitch(true);
// visual feedback Train->allowBatteryToggle = false;
Train->ggBatteryButton.UpdateValue( 1.0f, Train->dsbSwitch ); // side-effects
Train->ggBatteryOnButton.UpdateValue( 1.0f, Train->dsbSwitch ); if (Train->mvOccupied->LightsPosNo > 0)
{
Train->mvOccupied->BatterySwitch( true ); Train->Dynamic()->SetLights();
}
// side-effects }
if( Train->mvOccupied->LightsPosNo > 0 ) { else if (Command.action == GLFW_RELEASE)
Train->Dynamic()->SetLights(); {
} if (Train->ggBatteryButton.type() == TGaugeType::push)
{
// return the switch to neutral position
Train->ggBatteryButton.UpdateValue(0.5f);
}
Train->ggBatteryOnButton.UpdateValue(0.0f, Train->dsbSwitch);
Train->allowBatteryToggle = true;
}
} }
else if( Command.action == GLFW_RELEASE ) { else // impulse button behavior
if( Train->ggBatteryButton.type() == TGaugeType::push ) { {
// return the switch to neutral position if (Command.action == GLFW_PRESS)
Train->ggBatteryButton.UpdateValue( 0.5f ); {
if (Train->mvOccupied->shouldHoldBatteryButton)
{
// jesli przycisk trzeba przytrzymac
Train->ggBatteryButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->ggBatteryOnButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->fBatteryTimer = Train->mvOccupied->BatteryButtonHoldTime; // start timer
}
else
{
// jesli przycisk dziala od razu
Train->mvOccupied->BatterySwitch(true);
Train->allowBatteryToggle = false;
// side-effects
if (Train->mvOccupied->LightsPosNo > 0)
{
Train->Dynamic()->SetLights();
}
// visual feedback
Train->ggBatteryButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->ggBatteryOnButton.UpdateValue(1.0f, Train->dsbSwitch);
}
} }
Train->ggBatteryOnButton.UpdateValue( 0.0f, Train->dsbSwitch ); else if (Command.action == GLFW_RELEASE)
{
// visual feedback
Train->ggBatteryButton.UpdateValue(0.0f, Train->dsbSwitch);
Train->ggBatteryOnButton.UpdateValue(0.0f, Train->dsbSwitch);
Train->fBatteryTimer = -1.f; //
Train->allowBatteryToggle = true;
}
else if (Command.action == GLFW_REPEAT && Train->mvOccupied->shouldHoldBatteryButton)
{
// trzymamy przycisk
if (Train->fBatteryTimer <= 0.0 && Train->mvOccupied->Battery == false) {
Train->mvOccupied->BatterySwitch(true);
// side-effects
if (Train->mvOccupied->LightsPosNo > 0)
{
Train->Dynamic()->SetLights();
}
Train->allowBatteryToggle = false;
}
}
} }
} }
void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) {
// TBD, TODO: ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora if (!Train->mvOccupied->isBatteryButtonImpulse)
if( Command.action == GLFW_PRESS ) { { // regular button behavior
// visual feedback if (Command.action == GLFW_PRESS)
Train->ggBatteryButton.UpdateValue( 0.0f, Train->dsbSwitch ); {
Train->ggBatteryOffButton.UpdateValue( 1.0f, Train->dsbSwitch ); // visual feedback
Train->ggBatteryButton.UpdateValue(0.0f, Train->dsbSwitch);
Train->ggBatteryOffButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->mvOccupied->BatterySwitch( false ); Train->mvOccupied->BatterySwitch(false);
}
else if( Command.action == GLFW_RELEASE ) { // side-effects
if( Train->ggBatteryButton.type() == TGaugeType::push ) { if (Train->mvOccupied->LightsPosNo > 0)
// return the switch to neutral position {
Train->ggBatteryButton.UpdateValue( 0.5f ); Train->Dynamic()->SetLights();
} }
Train->ggBatteryOffButton.UpdateValue( 0.0f, Train->dsbSwitch ); }
} else if (Command.action == GLFW_RELEASE)
{
if (Train->ggBatteryButton.type() == TGaugeType::push)
{
// return the switch to neutral position
Train->ggBatteryButton.UpdateValue(0.5f);
}
Train->ggBatteryOffButton.UpdateValue(0.0f, Train->dsbSwitch);
}
}
else // impulse button behavior
{
if (Command.action == GLFW_PRESS)
{
if (Train->mvOccupied->shouldHoldBatteryButton)
{
// jesli przycisk trzeba przytrzymac
Train->ggBatteryButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->ggBatteryOffButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->fBatteryTimer = Train->mvOccupied->BatteryButtonHoldTime; // start timer
}
else
{
// jesli przycisk dziala od razu
Train->mvOccupied->BatterySwitch(false);
Train->allowBatteryToggle = false;
// side-effects
if (Train->mvOccupied->LightsPosNo > 0)
{
Train->Dynamic()->SetLights();
}
// visual feedback
Train->ggBatteryButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->ggBatteryOffButton.UpdateValue(1.0f, Train->dsbSwitch);
}
}
else if (Command.action == GLFW_RELEASE)
{
// visual feedback
Train->ggBatteryButton.UpdateValue(0.0f, Train->dsbSwitch);
Train->ggBatteryOffButton.UpdateValue(0.0f, Train->dsbSwitch);
Train->allowBatteryToggle = true;
}
else if (Command.action == GLFW_REPEAT && Train->mvOccupied->shouldHoldBatteryButton)
{
// trzymamy przycisk
if (Train->fBatteryTimer <= 0.0 && Train->mvOccupied->Battery == true) {
Train->mvOccupied->BatterySwitch(false);
Train->allowBatteryToggle = false;
// side-effects
if (Train->mvOccupied->LightsPosNo > 0)
{
Train->Dynamic()->SetLights();
}
}
}
}
} }
void TTrain::OnCommand_cabactivationtoggle(TTrain *Train, command_data const &Command) { void TTrain::OnCommand_cabactivationtoggle(TTrain *Train, command_data const &Command) {
@@ -2816,23 +2974,43 @@ void TTrain::change_pantograph_selection( int const Change ) {
void TTrain::OnCommand_pantographvalvesupdate( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_pantographvalvesupdate( TTrain *Train, command_data const &Command ) {
bool hasSeparateSwitches = Train->m_controlmapper.contains("pantvalvesupdate_bt:") &&
Train->m_controlmapper.contains("pantvalvesoff_bt:");
if( Command.action == GLFW_REPEAT ) { return; } if( Command.action == GLFW_REPEAT ) { return; }
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// implement action if (hasSeparateSwitches)
Train->update_pantograph_valves(); {
// visual feedback // implement action
Train->ggPantValvesButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->update_pantograph_valves();
// visual feedback
Train->ggPantValvesUpdate.UpdateValue(1.0, Train->dsbSwitch);
}
// Old logic to maintain compatibility
else
{
Train->update_pantograph_valves();
Train->ggPantValvesButton.UpdateValue(1.0, Train->dsbSwitch);
}
} }
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
// visual feedback // visual feedback
// NOTE: pantvalves_sw: is a specialized button, with no toggle behavior support // NOTE: pantvalves_sw: is a specialized button, with no toggle behavior support
Train->ggPantValvesButton.UpdateValue( 0.5, Train->dsbSwitch ); if (hasSeparateSwitches)
Train->ggPantValvesUpdate.UpdateValue(0.5, Train->dsbSwitch);
// Old logic to maintain compatibility
else
Train->ggPantValvesButton.UpdateValue(0.5, Train->dsbSwitch);
} }
} }
void TTrain::OnCommand_pantographvalvesoff( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_pantographvalvesoff( TTrain *Train, command_data const &Command ) {
bool hasSeparateSwitches = Train->m_controlmapper.contains("pantvalvesupdate_bt:") && Train->m_controlmapper.contains("pantvalvesoff_bt:");
if( Command.action == GLFW_REPEAT ) { return; } if( Command.action == GLFW_REPEAT ) { return; }
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
@@ -2840,12 +3018,18 @@ void TTrain::OnCommand_pantographvalvesoff( TTrain *Train, command_data const &C
Train->mvOccupied->OperatePantographValve( end::front, operation_t::disable ); Train->mvOccupied->OperatePantographValve( end::front, operation_t::disable );
Train->mvOccupied->OperatePantographValve( end::rear, operation_t::disable ); Train->mvOccupied->OperatePantographValve( end::rear, operation_t::disable );
// visual feedback // visual feedback
Train->ggPantValvesButton.UpdateValue( 0.0, Train->dsbSwitch ); if (hasSeparateSwitches)
Train->ggPantValvesOff.UpdateValue(1.0, Train->dsbSwitch);
else
Train->ggPantValvesButton.UpdateValue( 0.0, Train->dsbSwitch );
} }
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
// visual feedback // visual feedback
// NOTE: pantvalves_sw: is a specialized button, with no toggle behavior support // NOTE: pantvalves_sw: is a speciali zed button, with no toggle behavior support
Train->ggPantValvesButton.UpdateValue( 0.5, Train->dsbSwitch ); if (hasSeparateSwitches)
Train->ggPantValvesOff.UpdateValue(0.f, Train->dsbSwitch);
else
Train->ggPantValvesButton.UpdateValue( 0.5, Train->dsbSwitch );
} }
} }
@@ -4669,6 +4853,44 @@ void TTrain::OnCommand_headlightdisablerearupper( TTrain *Train, command_data co
} }
} }
void TTrain::OnCommand_modernlightdimmerincrease(TTrain* Train, command_data const& Command)
{
if (!Train->mvOccupied->enableModernDimmer)
return; // if modern dimmer is disabled, skip entire command
if (Command.action == GLFW_PRESS)
{
// update modern dimmer state
if (Train->mvOccupied->modernDimmerState < 4)
Train->mvOccupied->modernDimmerState++;
Train->Dynamic()->SetLights();
// visual feedback
if (Train->ggModernLightDimSw.SubModel != nullptr)
if (Train->mvOccupied->modernContainOffPos)
Train->ggModernLightDimSw.UpdateValue(Train->mvOccupied->modernDimmerState, Train->dsbSwitch);
else
Train->ggModernLightDimSw.UpdateValue(Train->mvOccupied->modernDimmerState - 1, Train->dsbSwitch);
}
}
void TTrain::OnCommand_modernlightdimmerdecrease(TTrain *Train, command_data const &Command)
{
if (!Train->mvOccupied->enableModernDimmer)
return; // if modern dimmer is disabled, skip entire command
if (Command.action == GLFW_PRESS)
{
byte minPos = (Train->mvOccupied->modernContainOffPos) ? 0 : 1; // prevent switching to 0 if its not enabled
// update modern dimmer state
if (Train->mvOccupied->modernDimmerState > minPos)
Train->mvOccupied->modernDimmerState--;
Train->Dynamic()->SetLights();
// visual feedback
if (Train->ggModernLightDimSw.SubModel != nullptr)
if (Train->mvOccupied->modernContainOffPos)
Train->ggModernLightDimSw.UpdateValue(Train->mvOccupied->modernDimmerState, Train->dsbSwitch);
else
Train->ggModernLightDimSw.UpdateValue(Train->mvOccupied->modernDimmerState - 1, Train->dsbSwitch);
}
}
void TTrain::OnCommand_redmarkertogglerearleft( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_redmarkertogglerearleft( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
// NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc // NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc
@@ -4848,10 +5070,12 @@ void TTrain::OnCommand_endsignalstoggle( TTrain *Train, command_data const &Comm
} }
void TTrain::OnCommand_headlightsdimtoggle( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_headlightsdimtoggle( TTrain *Train, command_data const &Command ) {
if (Train->DynamicObject->MoverParameters->enableModernDimmer)
return;
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( false == Train->DynamicObject->DimHeadlights ) { if (Train->DynamicObject->MoverParameters->modernDimmerState == 2)
{
// turn on // turn on
OnCommand_headlightsdimenable( Train, Command ); OnCommand_headlightsdimenable( Train, Command );
} }
@@ -4864,37 +5088,57 @@ void TTrain::OnCommand_headlightsdimtoggle( TTrain *Train, command_data const &C
void TTrain::OnCommand_headlightsdimenable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_headlightsdimenable( TTrain *Train, command_data const &Command ) {
if (Train->DynamicObject->MoverParameters->enableModernDimmer)
return;
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->ggDimHeadlightsButton.SubModel == nullptr ) { if( Train->ggDimHeadlightsButton.SubModel != nullptr ) {
// TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels // TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels
WriteLog( "Dim Headlights switch is missing, or wasn't defined" ); // visual feedback
return; Train->ggDimHeadlightsButton.UpdateValue(1.0, Train->dsbSwitch);
} }
// visual feedback
Train->ggDimHeadlightsButton.UpdateValue( 1.0, Train->dsbSwitch );
if( true == Train->DynamicObject->DimHeadlights ) { return; } // already enabled /* // to jest stara logika
if (true == Train->DynamicObject->DimHeadlights)
{
return;
} // already enabled
Train->DynamicObject->DimHeadlights = true; Train->DynamicObject->DimHeadlights = true;
*/
WriteLog("Switch do 1");
Train->DynamicObject->MoverParameters->modernDimmerState = 1; // ustawiamy modern dimmer na flage przyciemnienia
Train->DynamicObject->RaLightsSet(Train->DynamicObject->MoverParameters->iLights[0],
Train->DynamicObject->MoverParameters->iLights[1]
); // aktualizacja swiatelek
} }
} }
void TTrain::OnCommand_headlightsdimdisable( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_headlightsdimdisable( TTrain *Train, command_data const &Command ) {
if (Train->DynamicObject->MoverParameters->enableModernDimmer) // nie wiem dlaczego to tak dziala ze jest odwrocona logika
return;
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->ggDimHeadlightsButton.SubModel == nullptr ) { if( Train->ggDimHeadlightsButton.SubModel != nullptr ) {
// TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels // TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels
WriteLog( "Dim Headlights switch is missing, or wasn't defined" ); // visual feedback
return; Train->ggDimHeadlightsButton.UpdateValue(0.0, Train->dsbSwitch);
} }
// visual feedback
Train->ggDimHeadlightsButton.UpdateValue( 0.0, Train->dsbSwitch );
/* // stara logika przyciemniania
if( false == Train->DynamicObject->DimHeadlights ) { return; } // already enabled if( false == Train->DynamicObject->DimHeadlights ) { return; } // already enabled
Train->DynamicObject->DimHeadlights = false; Train->DynamicObject->DimHeadlights = false;
*/
WriteLog("Switch do 2");
Train->DynamicObject->MoverParameters->modernDimmerState = 2; // ustawiamy modern dimmer na flage rozjasnienia
Train->DynamicObject->RaLightsSet(
Train->DynamicObject->MoverParameters->iLights[0],
Train->DynamicObject->MoverParameters->iLights[1]
); // aktualizacja swiatelek
} }
} }
@@ -6748,6 +6992,7 @@ void TTrain::OnCommand_vehicleboost(TTrain *Train, const command_data &Command)
} }
} }
// cab movement update, fixed step part // cab movement update, fixed step part
void TTrain::UpdateCab() { void TTrain::UpdateCab() {
@@ -6834,6 +7079,21 @@ bool TTrain::Update( double const Deltatime )
mvOccupied->OperateDoors( static_cast<side>( idx ), true ); mvOccupied->OperateDoors( static_cast<side>( idx ), true );
} }
} }
// train measurement timer
if (trainLenghtMeasureTimer >= 0.f) {
trainLenghtMeasureTimer -= Deltatime;
if (trainLenghtMeasureTimer < 0.f)
trainLenghtMeasureTimer = -1.f;
}
// battery timer
if (fBatteryTimer >= 0.f) {
fBatteryTimer -= Deltatime;
if (fBatteryTimer < 0.f)
fBatteryTimer = -1.f;
}
// helper variables // helper variables
if( DynamicObject->Mechanik != nullptr ) { if( DynamicObject->Mechanik != nullptr ) {
m_doors = ( m_doors = (
@@ -7350,6 +7610,12 @@ bool TTrain::Update( double const Deltatime )
else else
btCompressors.Turn(false); btCompressors.Turn(false);
// Lampka zezwolenia na hamowanie ED
if (mvControlled->EpFuse)
btEDenabled.Turn(true);
else
btEDenabled.Turn(false);
// Lampka aktywowanej kabiny // Lampka aktywowanej kabiny
if (mvControlled->CabActive != 0) { if (mvControlled->CabActive != 0) {
btCabActived.Turn(true); btCabActived.Turn(true);
@@ -7358,6 +7624,11 @@ bool TTrain::Update( double const Deltatime )
btCabActived.Turn(false); btCabActived.Turn(false);
} }
if (mvControlled->Battery && mvControlled->CabActive != 0)
btAKLVents.Turn(true);
else
btAKLVents.Turn(false);
if( true == lowvoltagepower ) { if( true == lowvoltagepower ) {
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if( mvOccupied->SecuritySystem.is_vigilance_blinking() ) { if( mvOccupied->SecuritySystem.is_vigilance_blinking() ) {
@@ -7893,6 +8164,7 @@ bool TTrain::Update( double const Deltatime )
ggBrakeProfileG.Update(); ggBrakeProfileG.Update();
ggBrakeProfileR.Update(); ggBrakeProfileR.Update();
ggBrakeOperationModeCtrl.Update(); ggBrakeOperationModeCtrl.Update();
ggWiperSw.Update();
ggMaxCurrentCtrl.UpdateValue( ggMaxCurrentCtrl.UpdateValue(
( true == mvControlled->ShuntModeAllow ? ( true == mvControlled->ShuntModeAllow ?
( true == mvControlled->ShuntMode ? ( true == mvControlled->ShuntMode ?
@@ -7989,12 +8261,16 @@ bool TTrain::Update( double const Deltatime )
ggPantCompressorButton.Update(); ggPantCompressorButton.Update();
ggPantCompressorValve.Update(); ggPantCompressorValve.Update();
ggPantValvesOff.Update();
ggPantValvesUpdate.Update();
ggLightsButton.Update(); ggLightsButton.Update();
ggUpperLightButton.Update(); ggUpperLightButton.Update();
ggLeftLightButton.Update(); ggLeftLightButton.Update();
ggRightLightButton.Update(); ggRightLightButton.Update();
ggLeftEndLightButton.Update(); ggLeftEndLightButton.Update();
ggRightEndLightButton.Update(); ggRightEndLightButton.Update();
ggModernLightDimSw.Update();
// hunter-230112 // hunter-230112
ggRearUpperLightButton.Update(); ggRearUpperLightButton.Update();
ggRearLeftLightButton.Update(); ggRearLeftLightButton.Update();
@@ -8002,6 +8278,7 @@ bool TTrain::Update( double const Deltatime )
ggRearLeftEndLightButton.Update(); ggRearLeftEndLightButton.Update();
ggRearRightEndLightButton.Update(); ggRearRightEndLightButton.Update();
ggDimHeadlightsButton.Update(); ggDimHeadlightsButton.Update();
ggDimHeadlightsButton.Update();
//------------ //------------
ggConverterButton.Update(); ggConverterButton.Update();
ggConverterLocalButton.Update(); ggConverterLocalButton.Update();
@@ -9367,6 +9644,7 @@ void TTrain::clear_cab_controls()
ggBrakeProfileG.Clear(); ggBrakeProfileG.Clear();
ggBrakeProfileR.Clear(); ggBrakeProfileR.Clear();
ggBrakeOperationModeCtrl.Clear(); ggBrakeOperationModeCtrl.Clear();
ggWiperSw.Clear();
ggMaxCurrentCtrl.Clear(); ggMaxCurrentCtrl.Clear();
ggMainOffButton.Clear(); ggMainOffButton.Clear();
ggMainOnButton.Clear(); ggMainOnButton.Clear();
@@ -9469,6 +9747,10 @@ void TTrain::clear_cab_controls()
ggPantValvesButton.Clear(); ggPantValvesButton.Clear();
ggPantCompressorButton.Clear(); ggPantCompressorButton.Clear();
ggPantCompressorValve.Clear(); ggPantCompressorValve.Clear();
ggPantValvesOff.Clear();
ggPantValvesUpdate.Clear();
ggI1B.Clear(); ggI1B.Clear();
ggI2B.Clear(); ggI2B.Clear();
ggI3B.Clear(); ggI3B.Clear();
@@ -9580,6 +9862,7 @@ void TTrain::clear_cab_controls()
ggRightLightButton.Clear(); ggRightLightButton.Clear();
ggUpperLightButton.Clear(); ggUpperLightButton.Clear();
ggDimHeadlightsButton.Clear(); ggDimHeadlightsButton.Clear();
ggModernLightDimSw.Clear();
ggLeftEndLightButton.Clear(); ggLeftEndLightButton.Clear();
ggRightEndLightButton.Clear(); ggRightEndLightButton.Clear();
ggLightsButton.Clear(); ggLightsButton.Clear();
@@ -9611,6 +9894,24 @@ void TTrain::set_cab_controls( int const Cab ) {
m_linebreakerstate > 0 ? 1.f : m_linebreakerstate > 0 ? 1.f :
0.f ) ); 0.f ) );
} }
if (ggModernLightDimSw.SubModel != nullptr) {
if (mvOccupied->modernContainOffPos)
ggModernLightDimSw.PutValue(mvOccupied->modernDimmerState);
else
ggModernLightDimSw.PutValue(mvOccupied->modernDimmerState - 1);
}
// Init separate buttons
if (ggPantValvesUpdate.SubModel != nullptr)
{
ggPantValvesUpdate.PutValue(0.f);
}
if (ggPantValvesOff.SubModel != nullptr)
{
ggPantValvesOff.PutValue(0.f);
}
// motor connectors // motor connectors
ggStLinOffButton.PutValue( ggStLinOffButton.PutValue(
( mvControlled->StLinSwitchOff ? ( mvControlled->StLinSwitchOff ?
@@ -9669,6 +9970,7 @@ void TTrain::set_cab_controls( int const Cab ) {
0.f ) ); 0.f ) );
} }
ggPantValvesButton.PutValue( 0.5f ); ggPantValvesButton.PutValue( 0.5f );
// auxiliary compressor // auxiliary compressor
ggPantCompressorValve.PutValue( ggPantCompressorValve.PutValue(
mvControlled->bPantKurek3 ? mvControlled->bPantKurek3 ?
@@ -9738,7 +10040,7 @@ void TTrain::set_cab_controls( int const Cab ) {
ggRightLightButton.PutValue( -1.f ); ggRightLightButton.PutValue( -1.f );
} }
} }
if( true == DynamicObject->DimHeadlights ) { if( 1 == DynamicObject->MoverParameters->modernDimmerState ) {
ggDimHeadlightsButton.PutValue( 1.f ); ggDimHeadlightsButton.PutValue( 1.f );
} }
// cab lights // cab lights
@@ -9812,6 +10114,12 @@ void TTrain::set_cab_controls( int const Cab ) {
1.f : 1.f :
0.f ); 0.f );
} }
if (ggWiperSw.SubModel != nullptr)
{
ggWiperSw.PutValue(mvOccupied->wiperSwitchPos);
}
if (ggBrakeOperationModeCtrl.SubModel != nullptr) { if (ggBrakeOperationModeCtrl.SubModel != nullptr) {
ggBrakeOperationModeCtrl.PutValue( ggBrakeOperationModeCtrl.PutValue(
(mvOccupied->BrakeOpModeFlag > 0 ? (mvOccupied->BrakeOpModeFlag > 0 ?
@@ -10051,7 +10359,9 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-universal8:", btUniversals[ 8 ] }, { "i-universal8:", btUniversals[ 8 ] },
{ "i-universal9:", btUniversals[ 9 ] }, { "i-universal9:", btUniversals[ 9 ] },
{ "i-cabactived:", btCabActived }, { "i-cabactived:", btCabActived },
{"i-compressorany:", btCompressors } {"i-aklvents:", btAKLVents},
{"i-compressorany:", btCompressors },
{"i-edenabled", btEDenabled },
}; };
{ {
auto lookup = lights.find( Label ); auto lookup = lights.find( Label );
@@ -10172,6 +10482,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "leftend_sw:", ggLeftEndLightButton }, { "leftend_sw:", ggLeftEndLightButton },
{ "rightend_sw:", ggRightEndLightButton }, { "rightend_sw:", ggRightEndLightButton },
{ "lights_sw:", ggLightsButton }, { "lights_sw:", ggLightsButton },
{ "moderndimmer_sw:", ggModernLightDimSw },
{ "rearupperlight_sw:", ggRearUpperLightButton }, { "rearupperlight_sw:", ggRearUpperLightButton },
{ "rearleftlight_sw:", ggRearLeftLightButton }, { "rearleftlight_sw:", ggRearLeftLightButton },
{ "rearrightlight_sw:", ggRearRightLightButton }, { "rearrightlight_sw:", ggRearRightLightButton },
@@ -10282,6 +10593,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "invertertoggle10_bt:", ggInverterToggleButtons[9] }, { "invertertoggle10_bt:", ggInverterToggleButtons[9] },
{ "invertertoggle11_bt:", ggInverterToggleButtons[10] }, { "invertertoggle11_bt:", ggInverterToggleButtons[10] },
{ "invertertoggle12_bt:", ggInverterToggleButtons[11] }, { "invertertoggle12_bt:", ggInverterToggleButtons[11] },
{"pantvalvesupdate_bt:", ggPantValvesUpdate},
{"pantvalvesoff_bt:", ggPantValvesOff},
{"wipers_sw:", ggWiperSw}
}; };
{ {
auto const lookup { gauges.find( Label ) }; auto const lookup { gauges.find( Label ) };

18
Train.h
View File

@@ -226,6 +226,8 @@ class TTrain {
// command handlers // command handlers
// NOTE: we're currently using universal handlers and static handler map but it may be beneficial to have these implemented on individual class instance basis // NOTE: we're currently using universal handlers and static handler map but it may be beneficial to have these implemented on individual class instance basis
// TBD, TODO: consider this approach if we ever want to have customized consist behaviour to received commands, based on the consist/vehicle type or whatever // TBD, TODO: consider this approach if we ever want to have customized consist behaviour to received commands, based on the consist/vehicle type or whatever
static void OnCommand_wiperswitchincrease(TTrain *Train, command_data const &Command);
static void OnCommand_wiperswitchdecrease(TTrain *Train, command_data const &Command);
static void OnCommand_aidriverenable( TTrain *Train, command_data const &Command ); static void OnCommand_aidriverenable( TTrain *Train, command_data const &Command );
static void OnCommand_aidriverdisable( TTrain *Train, command_data const &Command ); static void OnCommand_aidriverdisable( TTrain *Train, command_data const &Command );
static void OnCommand_jointcontrollerset( TTrain *Train, command_data const &Command ); static void OnCommand_jointcontrollerset( TTrain *Train, command_data const &Command );
@@ -399,6 +401,8 @@ class TTrain {
static void OnCommand_headlighttogglerearupper( TTrain *Train, command_data const &Command ); static void OnCommand_headlighttogglerearupper( TTrain *Train, command_data const &Command );
static void OnCommand_headlightenablerearupper( TTrain *Train, command_data const &Command ); static void OnCommand_headlightenablerearupper( TTrain *Train, command_data const &Command );
static void OnCommand_headlightdisablerearupper( TTrain *Train, command_data const &Command ); static void OnCommand_headlightdisablerearupper( TTrain *Train, command_data const &Command );
static void OnCommand_modernlightdimmerincrease(TTrain *Train, command_data const &Command);
static void OnCommand_modernlightdimmerdecrease(TTrain *Train, command_data const &Command);
static void OnCommand_redmarkertogglerearleft( TTrain *Train, command_data const &Command ); static void OnCommand_redmarkertogglerearleft( TTrain *Train, command_data const &Command );
static void OnCommand_redmarkerenablerearleft( TTrain *Train, command_data const &Command ); static void OnCommand_redmarkerenablerearleft( TTrain *Train, command_data const &Command );
static void OnCommand_redmarkerdisablerearleft( TTrain *Train, command_data const &Command ); static void OnCommand_redmarkerdisablerearleft( TTrain *Train, command_data const &Command );
@@ -542,6 +546,8 @@ public: // reszta może by?publiczna
TGauge ggBrakeProfileR; // nastawiacz PR - hamowanie dwustopniowe TGauge ggBrakeProfileR; // nastawiacz PR - hamowanie dwustopniowe
TGauge ggBrakeOperationModeCtrl; //przełącznik trybu pracy PS/PN/EP/MED TGauge ggBrakeOperationModeCtrl; //przełącznik trybu pracy PS/PN/EP/MED
TGauge ggWiperSw; // przelacznik wycieraczek
TGauge ggMaxCurrentCtrl; TGauge ggMaxCurrentCtrl;
TGauge ggMainOffButton; TGauge ggMainOffButton;
@@ -578,6 +584,7 @@ public: // reszta może by?publiczna
TGauge ggRightEndLightButton; TGauge ggRightEndLightButton;
TGauge ggLightsButton; // przelacznik reflektorow (wszystkich) TGauge ggLightsButton; // przelacznik reflektorow (wszystkich)
TGauge ggDimHeadlightsButton; // headlights dimming switch TGauge ggDimHeadlightsButton; // headlights dimming switch
TGauge ggModernLightDimSw; // modern lights dimmer
// hunter-230112: przelacznik swiatel tylnich // hunter-230112: przelacznik swiatel tylnich
TGauge ggRearUpperLightButton; TGauge ggRearUpperLightButton;
@@ -658,6 +665,8 @@ public: // reszta może by?publiczna
TGauge ggPantValvesButton; TGauge ggPantValvesButton;
TGauge ggPantCompressorButton; TGauge ggPantCompressorButton;
TGauge ggPantCompressorValve; TGauge ggPantCompressorValve;
TGauge ggPantValvesUpdate;
TGauge ggPantValvesOff;
// Winger 020304 - wlacznik ogrzewania // Winger 020304 - wlacznik ogrzewania
TGauge ggTrainHeatingButton; TGauge ggTrainHeatingButton;
TGauge ggSignallingButton; TGauge ggSignallingButton;
@@ -769,8 +778,10 @@ public: // reszta może by?publiczna
TButton btLampkaRearRightLight; TButton btLampkaRearRightLight;
TButton btLampkaRearLeftEndLight; TButton btLampkaRearLeftEndLight;
TButton btLampkaRearRightEndLight; TButton btLampkaRearRightEndLight;
TButton btCabActived; TButton btCabActived;
TButton btCompressors; // lampka pracy jakiejkolwiek sprezarki TButton btAKLVents;
TButton btCompressors; // lampka pracy jakiejkolwiek sprezarki
TButton btEDenabled; // czy wlaczony jest hamulec ED (czy dostepny)
// other // other
TButton btLampkaMalfunction; TButton btLampkaMalfunction;
TButton btLampkaMalfunctionB; TButton btLampkaMalfunctionB;
@@ -833,6 +844,8 @@ private:
float fHaslerTimer; float fHaslerTimer;
float fConverterTimer; // hunter-261211: dla przekaznika float fConverterTimer; // hunter-261211: dla przekaznika
float fMainRelayTimer; // hunter-141211: zalaczanie WSa z opoznieniem float fMainRelayTimer; // hunter-141211: zalaczanie WSa z opoznieniem
float fBatteryTimer = {-1.f}; // Hirek: zalaczanie baterii z opoznieniem (tylko gdy zdefiniowano takie zachowanie w fiz)
bool allowBatteryToggle = true; // Hirek: zabezpieczenie przed przelaczaniem bateri on/off
int ScreenUpdateRate { 0 }; // vehicle specific python screen update rate override int ScreenUpdateRate { 0 }; // vehicle specific python screen update rate override
// McZapkie-240302 - przyda sie do tachometru // McZapkie-240302 - przyda sie do tachometru
@@ -875,6 +888,7 @@ private:
bool m_dirbackward{ false }; // helper, true if direction set to backward bool m_dirbackward{ false }; // helper, true if direction set to backward
bool m_doorpermits{ false }; // helper, true if any door permit is active bool m_doorpermits{ false }; // helper, true if any door permit is active
float m_doorpermittimers[2] = { -1.f, -1.f }; float m_doorpermittimers[2] = { -1.f, -1.f };
float trainLenghtMeasureTimer = { -1.f };
// ld substitute // ld substitute
bool m_couplingdisconnect { false }; bool m_couplingdisconnect { false };
bool m_couplingdisconnectback { false }; bool m_couplingdisconnectback { false };

View File

@@ -29,6 +29,9 @@ http://mozilla.org/MPL/2.0/.
#include "Timer.h" #include "Timer.h"
#include "dictionary.h" #include "dictionary.h"
#include "version_info.h" #include "version_info.h"
#include "ref/discord-rpc/include/discord_rpc.h"
#include <chrono>
#include "translation.h"
#ifdef _WIN32 #ifdef _WIN32
#pragma comment (lib, "dsound.lib") #pragma comment (lib, "dsound.lib")
@@ -174,6 +177,83 @@ int eu07_application::run_crashgui()
} }
return -1; return -1;
} }
void eu07_application::DiscordRPCService()
{
// initialize discord-rpc
WriteLog("Initializing Discord Rich Presence...");
static const char *discord_app_id = "1343662664504840222";
DiscordEventHandlers handlers;
memset(&handlers, 0, sizeof(handlers));
Discord_Initialize(discord_app_id, &handlers, 1, nullptr);
std::string rpcScnName = Global.SceneryFile;
if (rpcScnName[0] == '$')
rpcScnName.erase(0, 1);
rpcScnName.erase(rpcScnName.size() - 4, 4);
if (rpcScnName.find('_') != std::string::npos)
{
std::replace(rpcScnName.begin(), rpcScnName.end(), '_', ' ');
}
// calculate startup timestamp
auto now = std::chrono::system_clock::now();
auto now_c = std::chrono::system_clock::to_time_t(now);
// Init RPC object
static DiscordRichPresence discord_rpc;
memset(&discord_rpc, 0, sizeof(discord_rpc));
// realworld timestamp from datetime
discord_rpc.startTimestamp = static_cast<int64_t>(now_c);
static std::string state = Translations.lookup_s("Scenery: ") + rpcScnName;
discord_rpc.state = state.c_str();
discord_rpc.details = Translations.lookup_c("Loading scenery...");
discord_rpc.largeImageKey = "logo";
discord_rpc.largeImageText = "MaSzyna";
// First RPC upload
Discord_UpdatePresence(&discord_rpc);
// run loop
while (!glfwWindowShouldClose(m_windows.front()) && !m_modestack.empty())
{
// Discord RPC updater
if (simulation::is_ready)
{
std::string PlayerVehicle;
if (simulation::Train != nullptr)
{
PlayerVehicle = simulation::Train->name();
// make to upper
for (auto &c : PlayerVehicle)
c = toupper(c);
PlayerVehicle = Translations.lookup_s("Driving: ") + PlayerVehicle;
discord_rpc.details = PlayerVehicle.c_str();
uint16_t playerTrainVelocity = simulation::Train->Dynamic()->GetVelocity();
if (playerTrainVelocity > 1)
{
// ikonka ze jedziemy i nie spimy
discord_rpc.smallImageKey = "driving";
std::string smallText = Translations.lookup_s("Speed: ") + std::to_string(playerTrainVelocity) + " km/h";
discord_rpc.smallImageText = smallText.c_str();
}
else
{
// krecimy postoj
discord_rpc.smallImageKey = "halt";
discord_rpc.smallImageText = Translations.lookup_c("Stopped");
}
}
Discord_UpdatePresence(&discord_rpc);
}
std::this_thread::sleep_for(std::chrono::milliseconds(5000)); // update RPC every 5 secs
}
}
int int
eu07_application::init( int Argc, char *Argv[] ) { eu07_application::init( int Argc, char *Argv[] ) {
@@ -186,6 +266,10 @@ eu07_application::init( int Argc, char *Argv[] ) {
return result; return result;
} }
// start logging service
std::thread sLoggingService(LogService);
Global.threads.emplace("LogService", std::move(sLoggingService));
WriteLog( "Starting MaSzyna rail vehicle simulator (release: " + Global.asVersion + ")" ); WriteLog( "Starting MaSzyna rail vehicle simulator (release: " + Global.asVersion + ")" );
WriteLog( "For online documentation and additional files refer to: http://eu07.pl" ); WriteLog( "For online documentation and additional files refer to: http://eu07.pl" );
WriteLog( "Authors: Marcin_EU, McZapkie, ABu, Winger, Tolaris, nbmx, OLO_EU, Bart, Quark-t, " WriteLog( "Authors: Marcin_EU, McZapkie, ABu, Winger, Tolaris, nbmx, OLO_EU, Bart, Quark-t, "
@@ -239,9 +323,15 @@ eu07_application::init( int Argc, char *Argv[] ) {
if (!init_network()) if (!init_network())
return -1; return -1;
// Run DiscordRPC service
std::thread sDiscordRPC(&eu07_application::DiscordRPCService, this);
Global.threads.emplace("DiscordRPC", std::move(sDiscordRPC));
return result; return result;
} }
double eu07_application::generate_sync() { double eu07_application::generate_sync() {
if (Timer::GetDeltaTime() == 0.0) if (Timer::GetDeltaTime() == 0.0)
return 0.0; return 0.0;
@@ -433,7 +523,8 @@ eu07_application::run() {
std::this_thread::sleep_for( Global.minframetime - frametime ); std::this_thread::sleep_for( Global.minframetime - frametime );
} }
} }
Global.threads["LogService"].~thread(); // kill log service
Global.threads["DiscordRPC"].~thread(); // kill DiscordRPC service
return 0; return 0;
} }

View File

@@ -37,6 +37,8 @@ public:
int int
run(); run();
// issues request for a worker thread to perform specified task. returns: true if task was scheduled // issues request for a worker thread to perform specified task. returns: true if task was scheduled
void eu07_application::DiscordRPCService(); // discord rich presence service function (runs as separate thread)
bool bool
request( python_taskqueue::task_request const &Task ); request( python_taskqueue::task_request const &Task );
// ensures the main thread holds the python gil and can safely execute python calls // ensures the main thread holds the python gil and can safely execute python calls

View File

@@ -3,10 +3,10 @@ image: Visual Studio 2017
clone_depth: 1 clone_depth: 1
build_script: build_script:
- ps: >- - ps: >-
git submodule update --init --recursive
cd ref cd ref
git clone "https://github.com/chriskohlhoff/asio" --depth 1 --branch asio-1-16-1 -q
curl -o crashpad86.zip "http://get.backtrace.io/crashpad/builds/release/x86/crashpad-2020-07-01-release-x86-558c9614e3819179f30b92541450f5ac643afce5.zip" curl -o crashpad86.zip "http://get.backtrace.io/crashpad/builds/release/x86/crashpad-2020-07-01-release-x86-558c9614e3819179f30b92541450f5ac643afce5.zip"
7z x crashpad86.zip 7z x crashpad86.zip

File diff suppressed because it is too large Load Diff

551
command.h
View File

@@ -13,273 +13,279 @@ http://mozilla.org/MPL/2.0/.
#include <queue> #include <queue>
#include <unordered_set> #include <unordered_set>
enum class user_command { enum class user_command
{
aidriverenable = 0, aidriverenable = 0,
aidriverdisable, aidriverdisable,
jointcontrollerset, jointcontrollerset,
mastercontrollerincrease, mastercontrollerincrease,
mastercontrollerincreasefast, mastercontrollerincreasefast,
mastercontrollerdecrease, mastercontrollerdecrease,
mastercontrollerdecreasefast, mastercontrollerdecreasefast,
mastercontrollerset, mastercontrollerset,
secondcontrollerincrease, secondcontrollerincrease,
secondcontrollerincreasefast, secondcontrollerincreasefast,
secondcontrollerdecrease, secondcontrollerdecrease,
secondcontrollerdecreasefast, secondcontrollerdecreasefast,
secondcontrollerset, secondcontrollerset,
mucurrentindicatorothersourceactivate, mucurrentindicatorothersourceactivate,
independentbrakeincrease, independentbrakeincrease,
independentbrakeincreasefast, independentbrakeincreasefast,
independentbrakedecrease, independentbrakedecrease,
independentbrakedecreasefast, independentbrakedecreasefast,
independentbrakeset, independentbrakeset,
independentbrakebailoff, independentbrakebailoff,
universalbrakebutton1, universalbrakebutton1,
universalbrakebutton2, universalbrakebutton2,
universalbrakebutton3, universalbrakebutton3,
trainbrakeincrease, trainbrakeincrease,
trainbrakedecrease, trainbrakedecrease,
trainbrakeset, trainbrakeset,
trainbrakecharging, trainbrakecharging,
trainbrakerelease, trainbrakerelease,
trainbrakefirstservice, trainbrakefirstservice,
trainbrakeservice, trainbrakeservice,
trainbrakefullservice, trainbrakefullservice,
trainbrakehandleoff, trainbrakehandleoff,
trainbrakeemergency, trainbrakeemergency,
trainbrakebasepressureincrease, trainbrakebasepressureincrease,
trainbrakebasepressuredecrease, trainbrakebasepressuredecrease,
trainbrakebasepressurereset, trainbrakebasepressurereset,
trainbrakeoperationtoggle, trainbrakeoperationtoggle,
manualbrakeincrease, manualbrakeincrease,
manualbrakedecrease, manualbrakedecrease,
alarmchaintoggle, alarmchaintoggle,
alarmchainenable, alarmchainenable,
alarmchaindisable, alarmchaindisable,
wheelspinbrakeactivate, wheelspinbrakeactivate,
sandboxactivate, sandboxactivate,
autosandboxtoggle, autosandboxtoggle,
autosandboxactivate, autosandboxactivate,
autosandboxdeactivate, autosandboxdeactivate,
reverserincrease, reverserincrease,
reverserdecrease, reverserdecrease,
reverserforwardhigh, reverserforwardhigh,
reverserforward, reverserforward,
reverserneutral, reverserneutral,
reverserbackward, reverserbackward,
waterpumpbreakertoggle, waterpumpbreakertoggle,
waterpumpbreakerclose, waterpumpbreakerclose,
waterpumpbreakeropen, waterpumpbreakeropen,
waterpumptoggle, waterpumptoggle,
waterpumpenable, waterpumpenable,
waterpumpdisable, waterpumpdisable,
waterheaterbreakertoggle, waterheaterbreakertoggle,
waterheaterbreakerclose, waterheaterbreakerclose,
waterheaterbreakeropen, waterheaterbreakeropen,
waterheatertoggle, waterheatertoggle,
waterheaterenable, waterheaterenable,
waterheaterdisable, waterheaterdisable,
watercircuitslinktoggle, watercircuitslinktoggle,
watercircuitslinkenable, watercircuitslinkenable,
watercircuitslinkdisable, watercircuitslinkdisable,
fuelpumptoggle, fuelpumptoggle,
fuelpumpenable, fuelpumpenable,
fuelpumpdisable, fuelpumpdisable,
oilpumptoggle, oilpumptoggle,
oilpumpenable, oilpumpenable,
oilpumpdisable, oilpumpdisable,
linebreakertoggle, linebreakertoggle,
linebreakeropen, linebreakeropen,
linebreakerclose, linebreakerclose,
convertertoggle, convertertoggle,
converterenable, converterenable,
converterdisable, converterdisable,
convertertogglelocal, convertertogglelocal,
converteroverloadrelayreset, converteroverloadrelayreset,
compressortoggle, compressortoggle,
compressorenable, compressorenable,
compressordisable, compressordisable,
compressortogglelocal, compressortogglelocal,
compressorpresetactivatenext, compressorpresetactivatenext,
compressorpresetactivateprevious, compressorpresetactivateprevious,
compressorpresetactivatedefault, compressorpresetactivatedefault,
motoroverloadrelaythresholdtoggle, motoroverloadrelaythresholdtoggle,
motoroverloadrelaythresholdsetlow, motoroverloadrelaythresholdsetlow,
motoroverloadrelaythresholdsethigh, motoroverloadrelaythresholdsethigh,
motoroverloadrelayreset, motoroverloadrelayreset,
universalrelayreset1, universalrelayreset1,
universalrelayreset2, universalrelayreset2,
universalrelayreset3, universalrelayreset3,
notchingrelaytoggle, notchingrelaytoggle,
epbrakecontroltoggle, epbrakecontroltoggle,
epbrakecontrolenable,
epbrakecontroldisable,
trainbrakeoperationmodeincrease, trainbrakeoperationmodeincrease,
trainbrakeoperationmodedecrease, trainbrakeoperationmodedecrease,
brakeactingspeedincrease, brakeactingspeedincrease,
brakeactingspeeddecrease, brakeactingspeeddecrease,
brakeactingspeedsetcargo, brakeactingspeedsetcargo,
brakeactingspeedsetpassenger, brakeactingspeedsetpassenger,
brakeactingspeedsetrapid, brakeactingspeedsetrapid,
brakeloadcompensationincrease, brakeloadcompensationincrease,
brakeloadcompensationdecrease, brakeloadcompensationdecrease,
mubrakingindicatortoggle, mubrakingindicatortoggle,
alerteracknowledge, alerteracknowledge,
cabsignalacknowledge, cabsignalacknowledge,
hornlowactivate, hornlowactivate,
hornhighactivate, hornhighactivate,
whistleactivate, whistleactivate,
radiotoggle, radiotoggle,
radioenable, radioenable,
radiodisable, radiodisable,
radiochannelincrease, radiochannelincrease,
radiochanneldecrease, radiochanneldecrease,
radiochannelset, radiochannelset,
radiostopsend, radiostopsend,
radiostopenable, radiostopenable,
radiostopdisable, radiostopdisable,
radiostoptest, radiostoptest,
radiocall3send, radiocall3send,
radiovolumeincrease, radiovolumeincrease,
radiovolumedecrease, radiovolumedecrease,
radiovolumeset, radiovolumeset,
cabchangeforward, cabchangeforward,
cabchangebackward, cabchangebackward,
viewturn, modernlightdimmerdecrease,
movehorizontal, modernlightdimmerincrease,
movehorizontalfast,
movevertical,
moveverticalfast,
moveleft,
moveright,
moveforward,
moveback,
moveup,
movedown,
nearestcarcouplingincrease, viewturn,
nearestcarcouplingdisconnect, movehorizontal,
nearestcarcoupleradapterattach, movehorizontalfast,
nearestcarcoupleradapterremove, movevertical,
occupiedcarcouplingdisconnect, moveverticalfast,
moveleft,
moveright,
moveforward,
moveback,
moveup,
movedown,
nearestcarcouplingincrease,
nearestcarcouplingdisconnect,
nearestcarcoupleradapterattach,
nearestcarcoupleradapterremove,
occupiedcarcouplingdisconnect,
occupiedcarcouplingdisconnectback, occupiedcarcouplingdisconnectback,
doortoggleleft, doortoggleleft,
doortoggleright, doortoggleright,
doorpermitleft, doorpermitleft,
doorpermitright, doorpermitright,
doorpermitpresetactivatenext, doorpermitpresetactivatenext,
doorpermitpresetactivateprevious, doorpermitpresetactivateprevious,
dooropenleft, dooropenleft,
dooropenright, dooropenright,
dooropenall, dooropenall,
doorcloseleft, doorcloseleft,
doorcloseright, doorcloseright,
doorcloseall, doorcloseall,
doorsteptoggle, doorsteptoggle,
doormodetoggle, doormodetoggle,
mirrorstoggle, mirrorstoggle,
departureannounce, departureannounce,
doorlocktoggle, doorlocktoggle,
pantographcompressorvalvetoggle, pantographcompressorvalvetoggle,
pantographcompressorvalveenable, pantographcompressorvalveenable,
pantographcompressorvalvedisable, pantographcompressorvalvedisable,
pantographcompressoractivate, pantographcompressoractivate,
pantographtogglefront, pantographtogglefront,
pantographtogglerear, pantographtogglerear,
pantographraisefront, pantographraisefront,
pantographraiserear, pantographraiserear,
pantographlowerfront, pantographlowerfront,
pantographlowerrear, pantographlowerrear,
pantographlowerall, pantographlowerall,
pantographselectnext, pantographselectnext,
pantographselectprevious, pantographselectprevious,
pantographtoggleselected, pantographtoggleselected,
pantographraiseselected, pantographraiseselected,
pantographlowerselected, pantographlowerselected,
pantographvalvesupdate, pantographvalvesupdate,
pantographvalvesoff, pantographvalvesoff,
heatingtoggle, heatingtoggle,
heatingenable, heatingenable,
heatingdisable, heatingdisable,
lightspresetactivatenext, lightspresetactivatenext,
lightspresetactivateprevious, lightspresetactivateprevious,
headlighttoggleleft, headlighttoggleleft,
headlightenableleft, headlightenableleft,
headlightdisableleft, headlightdisableleft,
headlighttoggleright, headlighttoggleright,
headlightenableright, headlightenableright,
headlightdisableright, headlightdisableright,
headlighttoggleupper, headlighttoggleupper,
headlightenableupper, headlightenableupper,
headlightdisableupper, headlightdisableupper,
redmarkertoggleleft, redmarkertoggleleft,
redmarkerenableleft, redmarkerenableleft,
redmarkerdisableleft, redmarkerdisableleft,
redmarkertoggleright, redmarkertoggleright,
redmarkerenableright, redmarkerenableright,
redmarkerdisableright, redmarkerdisableright,
headlighttogglerearleft, headlighttogglerearleft,
headlightenablerearleft, headlightenablerearleft,
headlightdisablerearleft, headlightdisablerearleft,
headlighttogglerearright, headlighttogglerearright,
headlightenablerearright, headlightenablerearright,
headlightdisablerearright, headlightdisablerearright,
headlighttogglerearupper, headlighttogglerearupper,
headlightenablerearupper, headlightenablerearupper,
headlightdisablerearupper, headlightdisablerearupper,
redmarkertogglerearleft, redmarkertogglerearleft,
redmarkerenablerearleft, redmarkerenablerearleft,
redmarkerdisablerearleft, redmarkerdisablerearleft,
redmarkertogglerearright, redmarkertogglerearright,
redmarkerenablerearright, redmarkerenablerearright,
redmarkerdisablerearright, redmarkerdisablerearright,
redmarkerstoggle, redmarkerstoggle,
endsignalstoggle, endsignalstoggle,
headlightsdimtoggle, headlightsdimtoggle,
headlightsdimenable, headlightsdimenable,
headlightsdimdisable, headlightsdimdisable,
motorconnectorsopen, motorconnectorsopen,
motorconnectorsclose, motorconnectorsclose,
motordisconnect, motordisconnect,
interiorlighttoggle, interiorlighttoggle,
interiorlightenable, interiorlightenable,
interiorlightdisable, interiorlightdisable,
interiorlightdimtoggle, interiorlightdimtoggle,
interiorlightdimenable, interiorlightdimenable,
interiorlightdimdisable, interiorlightdimdisable,
compartmentlightstoggle, compartmentlightstoggle,
compartmentlightsenable, compartmentlightsenable,
compartmentlightsdisable, compartmentlightsdisable,
instrumentlighttoggle, instrumentlighttoggle,
instrumentlightenable, instrumentlightenable,
instrumentlightdisable, instrumentlightdisable,
dashboardlighttoggle, dashboardlighttoggle,
dashboardlightenable, dashboardlightenable,
dashboardlightdisable, dashboardlightdisable,
timetablelighttoggle, timetablelighttoggle,
timetablelightenable, timetablelightenable,
timetablelightdisable, timetablelightdisable,
generictoggle0, generictoggle0,
generictoggle1, generictoggle1,
generictoggle2, generictoggle2,
generictoggle3, generictoggle3,
generictoggle4, generictoggle4,
generictoggle5, generictoggle5,
generictoggle6, generictoggle6,
generictoggle7, generictoggle7,
generictoggle8, generictoggle8,
generictoggle9, generictoggle9,
batterytoggle, batterytoggle,
batteryenable, batteryenable,
batterydisable, batterydisable,
cabactivationtoggle, cabactivationtoggle,
cabactivationenable, cabactivationenable,
cabactivationdisable, cabactivationdisable,
motorblowerstogglefront, motorblowerstogglefront,
motorblowerstogglerear, motorblowerstogglerear,
motorblowersdisableall, motorblowersdisableall,
coolingfanstoggle, coolingfanstoggle,
tempomattoggle, tempomattoggle,
springbraketoggle, springbraketoggle,
springbrakeenable, springbrakeenable,
springbrakedisable, springbrakedisable,
@@ -287,7 +293,7 @@ enum class user_command {
springbrakeshutoffenable, springbrakeshutoffenable,
springbrakeshutoffdisable, springbrakeshutoffdisable,
springbrakerelease, springbrakerelease,
distancecounteractivate, distancecounteractivate,
speedcontrolincrease, speedcontrolincrease,
speedcontroldecrease, speedcontroldecrease,
speedcontrolpowerincrease, speedcontrolpowerincrease,
@@ -338,36 +344,38 @@ enum class user_command {
invertertoggle10, invertertoggle10,
invertertoggle11, invertertoggle11,
invertertoggle12, invertertoggle12,
globalradiostop, globalradiostop,
timejump, timejump,
timejumplarge, timejumplarge,
timejumpsmall, timejumpsmall,
setdatetime, setdatetime,
setweather, setweather,
settemperature, settemperature,
vehiclemoveforwards, vehiclemoveforwards,
vehiclemovebackwards, vehiclemovebackwards,
vehicleboost, vehicleboost,
debugtoggle, debugtoggle,
focuspauseset, focuspauseset,
pausetoggle, pausetoggle,
entervehicle, entervehicle,
resetconsist, resetconsist,
fillcompressor, fillcompressor,
consistreleaser, consistreleaser,
queueevent, queueevent,
setlight, setlight,
insertmodel, insertmodel,
deletemodel, deletemodel,
dynamicmove, dynamicmove,
consistteleport, consistteleport,
pullalarmchain, pullalarmchain,
sendaicommand, sendaicommand,
spawntrainset, spawntrainset,
destroytrainset, destroytrainset,
quitsimulation, quitsimulation,
wiperswitchincrease,
wiperswitchdecrease,
none = -1 none = -1
}; };
enum class command_target { enum class command_target {
@@ -481,6 +489,7 @@ extern command_queue Commands;
// TODO: add name to command map, and wrap these two into helper object // TODO: add name to command map, and wrap these two into helper object
extern commanddescription_sequence Commands_descriptions; extern commanddescription_sequence Commands_descriptions;
extern std::unordered_map<std::string, user_command> commandMap;
} }
// command_relay: composite class component, passes specified command to appropriate command stack // command_relay: composite class component, passes specified command to appropriate command stack

View File

@@ -506,7 +506,7 @@ drivermouse_input::bindings( std::string const &Control ) const {
void void
drivermouse_input::default_bindings() { drivermouse_input::default_bindings() {
// pierwsza komenda jest od zwiekszania a druga od zmniejszania - ewentualnie kolejno lewy i prawy przycisk
m_buttonbindings = { m_buttonbindings = {
{ "jointctrl:", { { "jointctrl:", {
user_command::jointcontrollerset, user_command::jointcontrollerset,
@@ -731,6 +731,9 @@ drivermouse_input::default_bindings() {
{ "dimheadlights_sw:", { { "dimheadlights_sw:", {
user_command::headlightsdimtoggle, user_command::headlightsdimtoggle,
user_command::none } }, user_command::none } },
{"moderndimmer_sw:", {
user_command::modernlightdimmerincrease,
user_command::modernlightdimmerdecrease } },
{ "leftend_sw:", { { "leftend_sw:", {
user_command::redmarkertoggleleft, user_command::redmarkertoggleleft,
user_command::none } }, user_command::none } },
@@ -845,6 +848,12 @@ drivermouse_input::default_bindings() {
{ "pantvalves_sw:", { { "pantvalves_sw:", {
user_command::pantographvalvesupdate, user_command::pantographvalvesupdate,
user_command::pantographvalvesoff } }, user_command::pantographvalvesoff } },
{ "pantvalvesupdate_bt:", {
user_command::pantographvalvesupdate,
user_command::none}},
{ "pantvalvesoff_bt:", {
user_command::pantographvalvesoff,
user_command::none}},
{ "pantcompressor_sw:", { { "pantcompressor_sw:", {
user_command::pantographcompressoractivate, user_command::pantographcompressoractivate,
user_command::none } }, user_command::none } },
@@ -1100,6 +1109,10 @@ drivermouse_input::default_bindings() {
{ "invertertoggle12_bt:",{ { "invertertoggle12_bt:",{
user_command::invertertoggle12, user_command::invertertoggle12,
user_command::none } }, user_command::none } },
{ "wipers_sw:",{
user_command::wiperswitchincrease,
user_command::wiperswitchdecrease
} },
}; };
} }

View File

@@ -617,8 +617,9 @@ debug_panel::render() {
ImGui::Checkbox( "Debug Traction", &DebugTractionFlag ); ImGui::Checkbox( "Debug Traction", &DebugTractionFlag );
} }
render_section( "Camera", m_cameralines ); render_section( "Camera", m_cameralines );
render_section( "Gfx Renderer", m_rendererlines ); render_section( "Gfx Renderer / Statistics", m_rendererlines );
render_section_settings(); render_section_settings();
render_section_developer(); // Developer tools
#ifdef WITH_UART #ifdef WITH_UART
if(true == render_section( "UART", m_uartlines)) { if(true == render_section( "UART", m_uartlines)) {
int ports_num = UartStatus.available_ports.size(); int ports_num = UartStatus.available_ports.size();
@@ -1452,6 +1453,14 @@ debug_panel::update_section_renderer( std::vector<text_line> &Output ) {
// renderer stats // renderer stats
Output.emplace_back( GfxRenderer->info_times(), Global.UITextColor ); Output.emplace_back( GfxRenderer->info_times(), Global.UITextColor );
Output.emplace_back( GfxRenderer->info_stats(), Global.UITextColor ); Output.emplace_back( GfxRenderer->info_stats(), Global.UITextColor );
// CPU related
Output.emplace_back("CPU:", Global.UITextColor);
// thread counter
textline = "Running threads: " + std::to_string(Global.threads.size() + 1);
Output.emplace_back(textline, Global.UITextColor);
} }
bool bool
@@ -1475,6 +1484,19 @@ debug_panel::render_section( std::vector<text_line> const &Lines ) {
return true; return true;
} }
bool debug_panel::render_section_developer()
{
if (false == ImGui::CollapsingHeader("Developer tools"))
return false;
ImGui::PushStyleColor(ImGuiCol_Text, {Global.UITextColor.r, Global.UITextColor.g, Global.UITextColor.b, Global.UITextColor.a});
ImGui::TextUnformatted("Warning! These tools are only for developers.\nDo not use them if you are NOT sure what they do!");
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "These settings may crash your simulator!");
if (ImGui::Button("Reload current vehicle .fiz") == true)
{
m_input.vehicle->MoverParameters->reload_FIZ(); // reload fiz
}
}
bool bool
debug_panel::render_section_settings() { debug_panel::render_section_settings() {

View File

@@ -104,7 +104,8 @@ private:
bool render_section_uart(); bool render_section_uart();
#endif #endif
bool render_section_settings(); bool render_section_settings();
// members bool render_section_developer();
// members
std::array<char, 1024> m_buffer; std::array<char, 1024> m_buffer;
std::array<char, 128> m_eventsearch; std::array<char, 128> m_eventsearch;
input_data m_input; input_data m_input;

View File

@@ -206,7 +206,7 @@ editor_mode::on_key( int const Key, int const Scancode, int const Action, int co
m_node = nullptr; m_node = nullptr;
m_dragging = false; m_dragging = false;
Application.set_cursor( GLFW_CURSOR_NORMAL ); //Application.set_cursor( GLFW_CURSOR_NORMAL );
static_cast<editor_ui*>( m_userinterface.get() )->set_node(nullptr); static_cast<editor_ui*>( m_userinterface.get() )->set_node(nullptr);
simulation::State.delete_model(model); simulation::State.delete_model(model);
@@ -318,10 +318,14 @@ editor_mode::on_mouse_button( int const Button, int const Action, int const Mods
if( Action == GLFW_PRESS ) { if( Action == GLFW_PRESS ) {
// left button press // left button press
auto const mode = static_cast<editor_ui*>( m_userinterface.get() )->mode(); auto const mode = static_cast<editor_ui*>( m_userinterface.get() )->mode();
auto const rotation_mode = static_cast<editor_ui*>( m_userinterface.get() )->rot_mode();
auto const fixed_rotation_value =
static_cast<editor_ui *>(m_userinterface.get())->rot_val();
m_node = nullptr; m_node = nullptr;
GfxRenderer->Pick_Node_Callback([this, mode,Action,Button](scene::basic_node *node) { GfxRenderer->Pick_Node_Callback([this, mode, rotation_mode, fixed_rotation_value,
Action, Button](scene::basic_node *node) {
editor_ui *ui = static_cast<editor_ui *>(m_userinterface.get()); editor_ui *ui = static_cast<editor_ui *>(m_userinterface.get());
if (mode == nodebank_panel::MODIFY) { if (mode == nodebank_panel::MODIFY) {
@@ -329,10 +333,10 @@ editor_mode::on_mouse_button( int const Button, int const Action, int const Mods
return; return;
m_node = node; m_node = node;
if( m_node ) //if( m_node )
Application.set_cursor( GLFW_CURSOR_DISABLED ); //Application.set_cursor( GLFW_CURSOR_DISABLED );
else //else
m_dragging = false; //m_dragging = false;
ui->set_node(m_node); ui->set_node(m_node);
} }
else if (mode == nodebank_panel::COPY) { else if (mode == nodebank_panel::COPY) {
@@ -360,8 +364,24 @@ editor_mode::on_mouse_button( int const Button, int const Action, int const Mods
if (!m_dragging) if (!m_dragging)
return; return;
m_node = cloned;
Application.set_cursor( GLFW_CURSOR_DISABLED ); m_node = cloned;
if (rotation_mode == functions_panel::RANDOM)
{
auto const rotation{glm::vec3{0, LocalRandom(0.0, 360.0), 0}};
m_editor.rotate(m_node, rotation, 1);
}
else if (rotation_mode == functions_panel::FIXED)
{
auto const rotation{glm::vec3{0, fixed_rotation_value, 0}};
m_editor.rotate(m_node, rotation, 0);
}
//Application.set_cursor( GLFW_CURSOR_DISABLED );
ui->set_node( m_node ); ui->set_node( m_node );
} }
}); });
@@ -370,8 +390,8 @@ editor_mode::on_mouse_button( int const Button, int const Action, int const Mods
} }
else { else {
// left button release // left button release
if( m_node ) //if( m_node )
Application.set_cursor( GLFW_CURSOR_NORMAL ); //Application.set_cursor( GLFW_CURSOR_NORMAL );
m_dragging = false; m_dragging = false;
// prime history stack for another snapshot // prime history stack for another snapshot
m_takesnapshot = true; m_takesnapshot = true;

View File

@@ -21,6 +21,7 @@ editor_ui::editor_ui() {
add_external_panel( &m_itempropertiespanel ); add_external_panel( &m_itempropertiespanel );
add_external_panel( &m_nodebankpanel ); add_external_panel( &m_nodebankpanel );
add_external_panel( &m_functionspanel );
} }
// updates state of UI elements // updates state of UI elements
@@ -41,6 +42,7 @@ editor_ui::update() {
ui_layer::update(); ui_layer::update();
m_itempropertiespanel.update( m_node ); m_itempropertiespanel.update( m_node );
m_functionspanel.update( m_node );
} }
void void
@@ -63,3 +65,17 @@ nodebank_panel::edit_mode
editor_ui::mode() { editor_ui::mode() {
return m_nodebankpanel.mode; return m_nodebankpanel.mode;
} }
functions_panel::rotation_mode
editor_ui::rot_mode() {
return m_functionspanel.rot_mode;
}
float
editor_ui::rot_val() {
return m_functionspanel.rot_value;
}
bool
editor_ui::rot_from_last()
{
return m_functionspanel.rot_from_last;
}

View File

@@ -31,6 +31,12 @@ public:
set_node( scene::basic_node * Node ); set_node( scene::basic_node * Node );
void void
add_node_template(const std::string &desc); add_node_template(const std::string &desc);
float
rot_val();
bool
rot_from_last();
functions_panel::rotation_mode
rot_mode();
const std::string * const std::string *
get_active_node_template(); get_active_node_template();
nodebank_panel::edit_mode nodebank_panel::edit_mode
@@ -39,6 +45,7 @@ public:
private: private:
// members // members
itemproperties_panel m_itempropertiespanel { "Node Properties", true }; itemproperties_panel m_itempropertiespanel { "Node Properties", true };
functions_panel m_functionspanel { "Functions", true };
nodebank_panel m_nodebankpanel{ "Node Bank", true }; nodebank_panel m_nodebankpanel{ "Node Bank", true };
scene::basic_node * m_node { nullptr }; // currently bound scene node, if any scene::basic_node * m_node { nullptr }; // currently bound scene node, if any
}; };

View File

@@ -420,8 +420,6 @@ nodebank_panel::render() {
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("Insert from bank", (int*)&mode, ADD); ImGui::RadioButton("Insert from bank", (int*)&mode, ADD);
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("Brush", (int*)&mode, BRUSH);
ImGui::SameLine();
ImGui::RadioButton( "Copy to bank", (int*)&mode, COPY ); ImGui::RadioButton( "Copy to bank", (int*)&mode, COPY );
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Reload Nodebank")) if (ImGui::Button("Reload Nodebank"))
@@ -493,3 +491,64 @@ nodebank_panel::generate_node_label( std::string Input ) const {
model : model :
model + " (" + texture + ")" ); model + " (" + texture + ")" );
} }
void functions_panel::update(scene::basic_node const *Node)
{
m_node = Node;
if (false == is_open)
{
return;
}
text_lines.clear();
m_grouplines.clear();
std::string textline;
// scenario inspector
auto const *node{Node};
auto const &camera{Global.pCamera};
}
void
functions_panel::render() {
if( false == is_open ) { return; }
auto flags =
ImGuiWindowFlags_NoFocusOnAppearing
| ImGuiWindowFlags_NoCollapse
| ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 );
if( size.x > 0 ) {
ImGui::SetNextWindowSize( ImVec2S( size.x, size.y ) );
}
if( size_min.x > 0 ) {
ImGui::SetNextWindowSizeConstraints( ImVec2S( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) );
}
auto const panelname { (
title.empty() ?
m_name :
title )
+ "###" + m_name };
if( true == ImGui::Begin( panelname.c_str(), nullptr, flags ) ) {
// header section
ImGui::RadioButton("Random rotation", (int *)&rot_mode, RANDOM);
ImGui::RadioButton("Fixed rotation", (int *)&rot_mode, FIXED);
if(rot_mode == FIXED){
//ImGui::Checkbox("Get rotation from last object", &rot_from_last);
ImGui::SliderFloat("Rotation Value", &rot_value, 0.0f, 360.0f, "%.1f");
};
ImGui::RadioButton("Default rotation", (int *)&rot_mode, DEFAULT);
for( auto const &line : text_lines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
}
ImGui::End();
}

View File

@@ -73,3 +73,35 @@ private:
char m_nodesearch[ 128 ]; char m_nodesearch[ 128 ];
std::shared_ptr<std::string> m_selectedtemplate; std::shared_ptr<std::string> m_selectedtemplate;
}; };
class functions_panel : public ui_panel
{
public:
enum rotation_mode
{
RANDOM,
FIXED,
DEFAULT
};
rotation_mode rot_mode = DEFAULT;
float rot_value = 0.0f;
bool rot_from_last = false;
functions_panel(std::string const &Name, bool const Isopen) : ui_panel(Name, Isopen) {}
void update(scene::basic_node const *Node);
void render() override;
private:
// methods
// members
scene::basic_node const *m_node{nullptr}; // scene node bound to the panel
scene::group_handle m_grouphandle{null_handle}; // scene group bound to the panel
std::string m_groupprefix;
std::vector<text_line> m_grouplines;
};

View File

@@ -65,17 +65,42 @@ light_array::update() {
light.count = 0 light.count = 0
+ ( ( lights & light::headlight_left ) ? 1 : 0 ) + ( ( lights & light::headlight_left ) ? 1 : 0 )
+ ( ( lights & light::headlight_right ) ? 1 : 0 ) + ( ( lights & light::headlight_right ) ? 1 : 0 )
+ ( ( lights & light::headlight_upper ) ? 1 : 0 ); + ( ( lights & light::headlight_upper ) ? 1 : 0 )
+ ( ( lights & light::highbeamlight_left ) ? 1: 0)
+ ( ( lights & light::highbeamlight_right ) ? 1 : 0);
if( light.count > 0 ) { if( light.count > 0 ) {
light.intensity = std::max( 0.0f, std::log( (float)light.count + 1.0f ) ); light.intensity = std::max(0.0f, std::log((float)light.count + 1.0f));
light.intensity *= ( light.owner->DimHeadlights ? 0.6f : 1.0f ); if (light.owner->DimHeadlights && !light.owner->HighBeamLights) // tylko przyciemnione
light.intensity *= light.owner->MoverParameters->dimMultiplier;
else if (!light.owner->DimHeadlights && !light.owner->HighBeamLights) // normalne
light.intensity *= light.owner->MoverParameters->normMultiplier;
else if (light.owner->DimHeadlights && light.owner->HighBeamLights) // przyciemnione dlugie
light.intensity *= light.owner->MoverParameters->highDimMultiplier;
else if (!light.owner->DimHeadlights && light.owner->HighBeamLights) // dlugie zwykle
light.intensity *= light.owner->MoverParameters->highMultiplier;
// TBD, TODO: intensity can be affected further by other factors // TBD, TODO: intensity can be affected further by other factors
light.state = { light.state = {
( ( lights & light::headlight_left ) ? 1.f : 0.f ), ( ( lights & light::headlight_left | light::highbeamlight_left ) ? 1.f : 0.f ),
( ( lights & light::headlight_upper ) ? 1.f : 0.f ), ( ( lights & light::headlight_upper ) ? 1.f : 0.f ),
( ( lights & light::headlight_right ) ? 1.f : 0.f ) }; ( ( lights & light::headlight_right | light::highbeamlight_right) ? 1.f : 0.f ) };
light.state *= ( light.owner->DimHeadlights ? 0.6f : 1.0f );
light.color = {
static_cast<float>(light.owner->MoverParameters->refR) / 255.0f,
static_cast<float>(light.owner->MoverParameters->refG) / 255.0f,
static_cast<float>(light.owner->MoverParameters->refB) / 255.0f
};
if (light.owner->DimHeadlights && !light.owner->HighBeamLights) // tylko przyciemnione
light.state *= light.owner->MoverParameters->dimMultiplier;
else if (!light.owner->DimHeadlights && !light.owner->HighBeamLights)
light.state *= light.owner->MoverParameters->normMultiplier;
else if (light.owner->DimHeadlights && light.owner->HighBeamLights) // przyciemnione dlugie
light.state *= light.owner->MoverParameters->highDimMultiplier;
else if (!light.owner->DimHeadlights && light.owner->HighBeamLights) // dlugie zwykle
light.state *= light.owner->MoverParameters->highMultiplier;
} }
else { else {
light.intensity = 0.0f; light.intensity = 0.0f;

1
ref/discord-rpc Submodule

Submodule ref/discord-rpc added at 963aa9f3e5

View File

@@ -47,8 +47,7 @@ operator!=( lighting_data const &Left, lighting_data const &Right ) {
namespace scene { namespace scene {
struct bounding_area { struct bounding_area {
glm::highp_dvec3 center; // mid point of the rectangle
glm::dvec3 center; // mid point of the rectangle
float radius { -1.0f }; // radius of the bounding sphere float radius { -1.0f }; // radius of the bounding sphere
bounding_area() = default; bounding_area() = default;
@@ -94,7 +93,7 @@ public:
material_handle material { null_handle }; material_handle material { null_handle };
lighting_data lighting; lighting_data lighting;
// geometry data // geometry data
glm::dvec3 origin; // world position of the relative coordinate system origin glm::highp_dvec3 origin; // world position of the relative coordinate system origin
gfx::geometry_handle geometry { 0, 0 }; // relative origin-centered chunk of geometry held by gfx renderer gfx::geometry_handle geometry { 0, 0 }; // relative origin-centered chunk of geometry held by gfx renderer
std::vector<world_vertex> vertices; // world space source data of the geometry std::vector<world_vertex> vertices; // world space source data of the geometry
// methods: // methods:

2
thread_list.txt Normal file
View File

@@ -0,0 +1,2 @@
- DiscordRPC - Thread for refreshing discord rich presence
- LogService - Service that logs data to files and console

View File

@@ -249,6 +249,7 @@ std::string locale::label_cab_control(std::string const &Label)
{ "leftlight_sw:", STRN("left headlight") }, { "leftlight_sw:", STRN("left headlight") },
{ "rightlight_sw:", STRN("right headlight") }, { "rightlight_sw:", STRN("right headlight") },
{ "dimheadlights_sw:", STRN("headlights dimmer") }, { "dimheadlights_sw:", STRN("headlights dimmer") },
{ "moderndimmer_sw:", STRN("headlights dimmer") },
{ "leftend_sw:", STRN("left marker light") }, { "leftend_sw:", STRN("left marker light") },
{ "rightend_sw:", STRN("right marker light") }, { "rightend_sw:", STRN("right marker light") },
{ "lights_sw:", STRN("light pattern") }, { "lights_sw:", STRN("light pattern") },
@@ -282,6 +283,8 @@ std::string locale::label_cab_control(std::string const &Label)
{ "pantselectedoff_sw:", STRN("selected pantograph") }, { "pantselectedoff_sw:", STRN("selected pantograph") },
{ "pantselect_sw:", STRN("selected pantograph") }, { "pantselect_sw:", STRN("selected pantograph") },
{ "pantvalves_sw:", STRN("selected pantograph") }, { "pantvalves_sw:", STRN("selected pantograph") },
{ "pantvalvesoff_bt:", STRN("all pantographs down") },
{ "pantvalvesupdate_bt:", STRN("selected pantographs up") },
{ "pantcompressor_sw:", STRN("pantograph compressor") }, { "pantcompressor_sw:", STRN("pantograph compressor") },
{ "pantcompressorvalve_sw:", STRN("pantograph 3 way valve") }, { "pantcompressorvalve_sw:", STRN("pantograph 3 way valve") },
{ "trainheating_sw:", STRN("heating") }, { "trainheating_sw:", STRN("heating") },
@@ -319,7 +322,8 @@ std::string locale::label_cab_control(std::string const &Label)
{ "universal6:", STRN("interactive part") }, { "universal6:", STRN("interactive part") },
{ "universal7:", STRN("interactive part") }, { "universal7:", STRN("interactive part") },
{ "universal8:", STRN("interactive part") }, { "universal8:", STRN("interactive part") },
{ "universal9:", STRN("interactive part") } { "universal9:", STRN("interactive part") },
{ "wipers_sw:", STRN("wipers mode selector") },
}; };
auto const it = cabcontrols_labels.find( Label ); auto const it = cabcontrols_labels.find( Label );

View File

@@ -335,6 +335,14 @@ interpolate( Type_ const &First, Type_ const &Second, double const Factor ) {
return static_cast<Type_>( ( First * ( 1.0 - Factor ) ) + ( Second * Factor ) ); return static_cast<Type_>( ( First * ( 1.0 - Factor ) ) + ( Second * Factor ) );
} }
template <typename Type_> Type_ smoothInterpolate(Type_ const &First, Type_ const &Second, double Factor)
{
// Apply smoothing (ease-in-out quadratic)
Factor = Factor * Factor * (3 - 2 * Factor);
return static_cast<Type_>((First * (1.0 - Factor)) + (Second * Factor));
}
// tests whether provided points form a degenerate triangle // tests whether provided points form a degenerate triangle
template <typename VecType_> template <typename VecType_>
bool bool