16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-23 10:59: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"]
path = ref/asio
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[6] = pModel->GetFromName("Light_Off06");
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)
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;
}
// 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()
{ // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
bool state; // stan światła
if (Global.UpdateMaterials)
on_season_update();
for (int i = 0; i < iNumLights; ++i)
{
auto const lightmode { static_cast<int>( std::abs( lsLights[ i ] ) ) };
@@ -656,9 +710,9 @@ TAnimModel::export_as_text_( std::ostream &Output ) const {
// header
Output << "model ";
// location and rotation
Output
<< location().x << ' '
<< location().y << ' '
Output << std::fixed << std::setprecision(3) // ustawienie dokładnie 3 cyfr po przecinku
<< location().x << ' '
<< location().y << ' '
<< location().z << ' ';
Output
<< "0 " ;

View File

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

View File

@@ -444,6 +444,12 @@ target_link_libraries(${PROJECT_NAME} Threads::Threads)
find_package(GLM REQUIRED)
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)
if (TARGET 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
AIControllFlag = AIdriver;
pVehicle->Controller = AIdriver;
control_lights(); // reinicjalizacja swiatel
mvOccupied->CabActivisation(true);
iDirection = 0; // kierunek jazdy trzeba dopiero zgadnąć
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
{ // a teraz użytkownik
if (!is_train() || !is_car()) // gasimy swiatla jesli przejmujemy odstawione
pVehicle->RaLightsSet(0, 0);
AIControllFlag = Humandriver;
pVehicle->Controller = Humandriver;
if( eAction == TAction::actSleep ) {

View File

@@ -97,8 +97,110 @@ void TAnimPant::AKP_4E()
fHeightExtra[3] = -0.07f; //+0.3048
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
fMaxDist = -1.0; // normalnie nie pokazywać
switch (i)
@@ -127,7 +229,21 @@ int TAnim::TypeSet(int i, int fl)
case 5: // 5-pantograf - 5 submodeli
iFlags = 0x055;
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;
case 6:
iFlags = 0x068;
@@ -138,6 +254,9 @@ int TAnim::TypeSet(int i, int fl)
case 8:
iFlags = 0x080;
break; // mirror
case 9:
iFlags = 0x023; // 2: Rotating/Motion-based, 8: Uses 3 submodels
break;
default:
iFlags = 0;
}
@@ -576,20 +695,20 @@ void TDynamicObject::UpdateDoorPlug(TAnim *pAnim) {
void TDynamicObject::UpdatePant(TAnim *pAnim)
{ // animacja pantografu - 4 obracane ramiona, ślizg piąty
float a, b, c;
a = RadToDeg(pAnim->fParamPants->fAngleL - pAnim->fParamPants->fAngleL0);
b = RadToDeg(pAnim->fParamPants->fAngleU - pAnim->fParamPants->fAngleU0);
c = a + b;
if (pAnim->smElement[0])
pAnim->smElement[0]->SetRotate(float3(-1, 0, 0), a); // dolne ramię
if (pAnim->smElement[1])
pAnim->smElement[1]->SetRotate(float3(1, 0, 0), a);
if (pAnim->smElement[2])
pAnim->smElement[2]->SetRotate(float3(1, 0, 0), c); // górne ramię
if (pAnim->smElement[3])
pAnim->smElement[3]->SetRotate(float3(-1, 0, 0), c);
if (pAnim->smElement[4])
pAnim->smElement[4]->SetRotate(float3(-1, 0, 0), b); //ślizg
float a, b, c;
a = RadToDeg(pAnim->fParamPants->fAngleL - pAnim->fParamPants->fAngleL0);
b = RadToDeg(pAnim->fParamPants->fAngleU - pAnim->fParamPants->fAngleU0);
c = a + b;
if (pAnim->smElement[0])
pAnim->smElement[0]->SetRotate(float3(-1, 0, 0), a); // dolne ramie 1
if (pAnim->smElement[1])
pAnim->smElement[1]->SetRotate(float3(1, 0, 0), a * pAnim->fParamPants->rd2rf); // dolne ramie 2
if (pAnim->smElement[2])
pAnim->smElement[2]->SetRotate(float3(1, 0, 0), c); // górne ramie 1
if (pAnim->smElement[3])
pAnim->smElement[3]->SetRotate(float3(-1, 0, 0), c * pAnim->fParamPants->rg2rf); // gorne ramie 2
if (pAnim->smElement[4])
pAnim->smElement[4]->SetRotate(float3(-1, 0, 0), b * pAnim->fParamPants->slizgrf); // ślizg
}
// doorstep animation, shift
@@ -645,6 +764,24 @@ void TDynamicObject::UpdateMirror( TAnim *pAnim ) {
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)
{ // animacja gałki zależna od double
@@ -1048,12 +1185,15 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
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
&& ( Mechanik != nullptr )
&& ( ( Mechanik->action() != TAction::actSleep )
/* || ( MoverParameters->Battery ) */ ) ) {
// rysowanie figurki mechanika
btMechanik1.Turn( MoverParameters->CabOccupied > 0 );
btMechanik1.Turn(MoverParameters->CabOccupied > 0);
btMechanik2.Turn( MoverParameters->CabOccupied < 0 );
if( MoverParameters->CabOccupied != 0 ) {
btnOn = true;
@@ -1168,6 +1308,28 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
}
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
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_headlamp12.Init( "headlamp12", mdModel ); // prawe
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_headlamp22.Init( "headlamp22", mdModel );
m_headlamp23.Init( "headlamp23", mdModel );
m_highbeam22.Init("highbeam22", mdModel);
m_highbeam23.Init("highbeam23", mdModel);
m_headsignal12.Init( "headsignal12", mdModel );
m_headsignal13.Init( "headsignal13", 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_headlamp12.Active() ? light::headlight_right : 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_headlamp22.Active() ? light::headlight_right : 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::rear ] |= m_headsignal22.Active() ? light::auxiliary_right : 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);
btMechanik2.Init( "mechanik2", mdLowPolyInt, false);
if( MoverParameters->dizel_heat.water.config.shutters ) {
btShutters1.Init( "shutters1", mdModel, false );
}
@@ -3949,6 +4126,70 @@ bool TDynamicObject::Update(double dt, double dt1)
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
if( (MoverParameters->Vel > MoverParameters->MirrorVelClose)
|| (MoverParameters->CabActive == 0) && (activation::mirrors)
@@ -4162,6 +4403,10 @@ void TDynamicObject::TurnOff()
m_headlamp21.TurnOff();
m_headlamp22.TurnOff();
m_headlamp23.TurnOff();
m_highbeam12.TurnOff();
m_highbeam13.TurnOff();
m_highbeam22.TurnOff();
m_highbeam23.TurnOff();
m_headsignal12.TurnOff();
m_headsignal13.TurnOff();
m_headsignal22.TurnOff();
@@ -5002,12 +5247,14 @@ TDynamicObject::radius() const {
// McZapkie-250202
// wczytywanie pliku z danymi multimedialnymi (dzwieki)
void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string const &ReplacableSkin ) {
rTypeName = TypeName;
rReplacableSkin = ReplacableSkin;
Global.asCurrentDynamicPath = asBaseDir;
std::string asFileName = asBaseDir + TypeName + ".mmd";
std::string asAnimName;
bool Stop_InternalData = false;
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
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 );
int i, j, k = 0, sm = 0;
for (j = 0; j < ANIM_TYPES; ++j)
for (i = 0; i < iAnimType[j]; ++i)
for (j = 0; j < ANIM_TYPES; ++j) // petla po wszystkich wpisach w animations
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 (!pants)
if (iAnimType[ANIM_PANTS]) // o ile jakieś pantografy są (a domyślnie są)
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
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
{
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 != "" )
&& ( token != "endmodels" ) );
@@ -6424,6 +6721,19 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
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:") {
m_powertrainsounds.retarder.deserialize(parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency);
m_powertrainsounds.retarder.owner(this);
@@ -7000,7 +7310,6 @@ void TDynamicObject::Damage(char flag)
};
void TDynamicObject::SetLights() {
auto const isfrontcaboccupied { MoverParameters->CabOccupied * DirectionGet() >= 0 };
int const automaticmarkers { MoverParameters->CabActive == 0 && ( MoverParameters->InactiveCabFlag & activation::redmarkers )
? light::redmarker_left + light::redmarker_right : 0 };
@@ -7054,6 +7363,47 @@ void TDynamicObject::RaLightsSet(int head, int rear)
if( head >= 0 ) {
auto const vehicleend { iDirection > 0 ? end::front : end::rear };
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 ) {
auto const vehicleend{ iDirection > 0 ? end::rear : end::front };
@@ -7660,9 +8010,9 @@ TDynamicObject::update_shake( double const Timedelta ) {
if( iVel > 0.5 ) {
// acceleration-driven base shake
shakevector += Math3D::vector3(
-MoverParameters->AccN * Timedelta * 5.0, // highlight side sway
-MoverParameters->AccVert * Timedelta,
-MoverParameters->AccSVBased * Timedelta * 1.5); // accent acceleration/deceleration
-MoverParameters->AccN * Timedelta * 5.0 * Global.ShakingMultiplierRL, // highlight side sway
-MoverParameters->AccVert * Timedelta * Global.ShakingMultiplierUD,
-MoverParameters->AccSVBased * Timedelta * 1.5 * Global.ShakingMultiplierBF); // accent acceleration/deceleration
}
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
if( Vehicle.TurboTest > 0 ) {
// 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 goalvolume { (
( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ?

View File

@@ -22,6 +22,8 @@ http://mozilla.org/MPL/2.0/.
#include "sound.h"
#include "Spring.h"
#include <vector>
#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_DOORSTEPS = 7;
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;
//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 fHeightExtra[5]; //łamana symulująca kształt nabieżnika
// 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 WBL85();
void DSAx();
void EC160_200();
};
class TAnim
@@ -115,8 +128,8 @@ public:
// destructor
~TAnim();
// methods
int TypeSet( int i, int fl = 0 ); // ustawienie typu
// members
int TypeSet(int i, TMoverParameters currentMover, int fl = 0); // ustawienie typu
// members
union
{
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 int NextConnectedNo() const { return MoverParameters->Neighbours[ end::rear ].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
TModel3d *mdModel; // model pudła
@@ -277,7 +294,8 @@ private:
void UpdatePlatformTranslate(TAnim *pAnim); // doorstep animation, shift
void UpdatePlatformRotate(TAnim *pAnim); // doorstep animation, rotate
void UpdateMirror(TAnim *pAnim); // mirror animation
/*
void UpdateWiper(TAnim *pAnim); // wiper animation
/*
void UpdateLeverDouble(TAnim *pAnim); // animacja gałki zależna od double
void UpdateLeverFloat(TAnim *pAnim); // animacja gałki zależna od float
void UpdateLeverInt(TAnim *pAnim); // animacja gałki zależna od int (wartość)
@@ -301,6 +319,14 @@ private:
Math3D::vector3 vFloor; // podłoga dla ładunku
public:
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 dMirrorMoveL{ 0.0 };
double dMirrorMoveR{ 0.0 };
@@ -469,13 +495,18 @@ private:
AirCoupler m_headlamp11; // oswietlenie czolowe - przod
AirCoupler m_headlamp12;
AirCoupler m_headlamp13;
AirCoupler m_highbeam12; // dlugie
AirCoupler m_highbeam13;
AirCoupler m_headlamp21; // oswietlenie czolowe - tyl
AirCoupler m_headlamp22;
AirCoupler m_headlamp23;
AirCoupler m_highbeam22;
AirCoupler m_highbeam23;
AirCoupler m_headsignal12;
AirCoupler m_headsignal13;
AirCoupler m_headsignal22;
AirCoupler m_headsignal23;
TButton btExteriorOnly;
TButton btMechanik1;
TButton btMechanik2;
TButton btShutters1; // cooling shutters for primary water circuit
@@ -515,6 +546,8 @@ private:
springbrake_sounds m_springbrakesounds;
sound_source rsSlippery { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab
sound_source sSand { sound_placement::external };
sound_source sWiperToPark { sound_placement::internal };
sound_source sWiperFromPark { sound_placement::internal };
// 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
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;
void ABuCheckMyTrack();
std::string rTypeName; // nazwa typu pojazdu
std::string rReplacableSkin; // nazwa tekstury pojazdu
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 HighBeamLights { false }; // status of the highbeam toggle
// checks whether there's unbroken connection of specified type to specified vehicle
bool is_connected( TDynamicObject const *Vehicle, coupling const Coupling = coupling::coupler ) const;
TDynamicObject * PrevAny() const;

View File

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

View File

@@ -16,6 +16,9 @@ http://mozilla.org/MPL/2.0/.
#include "light.h"
#include "utilities.h"
#include "motiontelemetry.h"
#include "ref/discord-rpc/include/discord_rpc.h"
#include <map>
#ifdef WITH_UART
#include "uart.h"
#endif
@@ -27,6 +30,11 @@ struct global_settings {
// members
// data items
// 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 ctrlState{ 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 cursor_pos; // cursor position in platform-specific virtual pixels
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 targetfps{ 0.0f };
bool bFullScreen{ false };

118
Logs.cpp
View File

@@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/.
#include "winheaders.h"
#include "utilities.h"
#include "uilayer.h"
#include <deque>
std::ofstream output; // standardowy "log.txt", można go wyłączyć
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 ) {
if( str == nullptr ) { return; }
if( true == TestFlag( Global.DisabledLogTypes, static_cast<unsigned int>( Type ) ) ) { return; }
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
}
InfoStack.emplace_back(strdup(str));
}
void ErrorLog( const char *str, logtype const Type ) {
if( str == nullptr ) { return; }
if( true == TestFlag( Global.DisabledLogTypes, static_cast<unsigned int>( Type ) ) ) { return; }
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();
ErrorStack.emplace_back(strdup(str));
};
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 ),
powergrid = ( 1 << 10 ),
};
void LogService();
void WriteLog( const char *str, logtype const Type = logtype::generic );
void Error( const std::string &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 startRLIST, startUCLIST;
bool startDIZELMOMENTUMLIST, startDIZELV2NMAXLIST, startHYDROTCLIST, startPMAXLIST;
bool startDLIST, startFFLIST, startWWLIST;
bool startDLIST, startFFLIST, startWWLIST, startWiperList;
bool startLIGHTSLIST;
bool startCOMPRESSORLIST;
int LISTLINE;
@@ -9279,6 +9279,25 @@ bool TMoverParameters::readFFList( std::string const &line ) {
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
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 ].Pmax = std::min( SST[ idx ].Pmax, std::pow( SST[ idx ].Umax, 2 ) / 47.6 );
}
return true;
}
@@ -9444,6 +9462,7 @@ void TMoverParameters::BrakeSubsystemDecode()
// *************************************************************************************************
bool TMoverParameters::LoadFIZ(std::string chkpath)
{
chkPath = chkpath; // assign class path for reloading
const int param_ok = 1;
const int wheels_ok = 2;
const int dimensions_ok = 4;
@@ -9462,6 +9481,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
startPMAXLIST = false;
startFFLIST = false;
startWWLIST = false;
startWiperList = false;
startLIGHTSLIST = false;
startCOMPRESSORLIST = false;
std::string file = TypeName + ".fiz";
@@ -9562,6 +9582,13 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
startFFLIST = false;
continue;
}
if (issection("endwl", inputline))
{
// skonczylismy czytac liste konfiguracji wycieraczek
startBPT = false;
startWiperList = false;
continue;
}
if( issection( "END-WWL", inputline ) ) {
startBPT = false;
startWWLIST = false;
@@ -9666,6 +9693,14 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
continue;
}
if (issection("Headlights:", inputline))
{
startBPT = false;
fizlines.emplace("Headlights", inputline);
LoadFIZ_Headlights(inputline);
continue;
}
if (issection("Blending:", inputline)) {
startBPT = false; LISTLINE = 0;
@@ -9845,9 +9880,22 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
{
startBPT = false;
startWWLIST = true; LISTLINE = 0;
continue;
}
if (issection("WiperList:", inputline))
{
startBPT = false;
fizlines.emplace("WiperList", inputline);
startWiperList = true;
LISTLINE = 0;
LoadFIZ_WiperList(inputline);
continue;
}
if( issection( "LightsList:", inputline ) ) {
startBPT = false;
fizlines.emplace( "LightsList", inputline );
@@ -9914,6 +9962,11 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
readWWList( inputline );
continue;
}
if (true == startWiperList)
{
readWiperList(inputline);
continue;
}
if( true == startLIGHTSLIST ) {
readLightsList( inputline );
continue;
@@ -9935,6 +9988,13 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
else
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));
return result;
}
@@ -10026,6 +10086,18 @@ void TMoverParameters::LoadFIZ_Load( std::string const &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 ) {
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(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 {
{ "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[ 1 ], "RelayResetButton2", Input, "" );
extract_value( UniversalResetButtonFlag[ 2 ], "RelayResetButton3", Input, "" );
extract_value(enableModernDimmer, "ModernDimmer", Input, "");
extract_value(modernContainOffPos, "ModernDimmerOffPosition", Input, "");
// pantograph presets
{
auto &presets { PantsPreset.first };
@@ -11242,6 +11322,13 @@ void TMoverParameters::LoadFIZ_FFList( std::string const &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 ) {
extract_value( LightsPosNo, "Size", Input, "" );
@@ -11306,6 +11393,17 @@ void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparamet
auto &collectorparameters = Powerparameters.CollectorParameters;
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.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 {
weights_table Weights;

View File

@@ -105,6 +105,38 @@ void render_task::run() {
if( outputwidth != nullptr ) { Py_DECREF( outputwidth ); }
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()
@@ -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__
#pragma GCC diagnostic pop
#endif

10
PyInt.h
View File

@@ -130,7 +130,8 @@ private:
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 error();
// members
// members
PyObject *m_main { nullptr };
PyObject *m_stderr { nullptr };
PyThreadState *m_mainthread{ nullptr };
@@ -143,4 +144,11 @@ private:
bool m_initialized { false };
};
class python_external_utils
{
public:
static std::vector<std::string> PyObjectToStringArray(PyObject *pyList);
};
#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.
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.
$ 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(&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
// 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::pantographlowerfront, &TTrain::OnCommand_pantographlowerfront },
{ 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::pantographselectnext, &TTrain::OnCommand_pantographselectnext },
{ 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::headlightenablerearupper, &TTrain::OnCommand_headlightenablerearupper },
{ 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::redmarkerenablerearleft, &TTrain::OnCommand_redmarkerenablerearleft },
{ user_command::redmarkerdisablerearleft, &TTrain::OnCommand_redmarkerdisablerearleft },
@@ -1313,7 +1319,17 @@ void TTrain::OnCommand_distancecounteractivate( TTrain *Train, command_data cons
// visual feedback
Train->ggDistanceCounterButton.UpdateValue( 1.0, Train->dsbSwitch );
// 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 ) {
// 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 ) {
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 )
{
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
if( false == Train->mvOccupied->Power24vIsAvailable ) {
// 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 ) {
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 ) {
// visual feedback
Train->ggBatteryButton.UpdateValue( 1.0f, Train->dsbSwitch );
Train->ggBatteryOnButton.UpdateValue( 1.0f, Train->dsbSwitch );
Train->mvOccupied->BatterySwitch( true );
// side-effects
if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->Dynamic()->SetLights();
}
Train->mvOccupied->BatterySwitch(true);
Train->allowBatteryToggle = false;
// side-effects
if (Train->mvOccupied->LightsPosNo > 0)
{
Train->Dynamic()->SetLights();
}
}
else if (Command.action == GLFW_RELEASE)
{
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 ) {
if( Train->ggBatteryButton.type() == TGaugeType::push ) {
// return the switch to neutral position
Train->ggBatteryButton.UpdateValue( 0.5f );
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->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 ) {
// TBD, TODO: ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
if( Command.action == GLFW_PRESS ) {
// visual feedback
Train->ggBatteryButton.UpdateValue( 0.0f, Train->dsbSwitch );
Train->ggBatteryOffButton.UpdateValue( 1.0f, Train->dsbSwitch );
if (!Train->mvOccupied->isBatteryButtonImpulse)
{ // regular button behavior
if (Command.action == GLFW_PRESS)
{
// visual feedback
Train->ggBatteryButton.UpdateValue(0.0f, Train->dsbSwitch);
Train->ggBatteryOffButton.UpdateValue(1.0f, Train->dsbSwitch);
Train->mvOccupied->BatterySwitch( false );
}
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 );
}
Train->mvOccupied->BatterySwitch(false);
// side-effects
if (Train->mvOccupied->LightsPosNo > 0)
{
Train->Dynamic()->SetLights();
}
}
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) {
@@ -2816,23 +2974,43 @@ void TTrain::change_pantograph_selection( int const Change ) {
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_PRESS ) {
// implement action
Train->update_pantograph_valves();
// visual feedback
Train->ggPantValvesButton.UpdateValue( 1.0, Train->dsbSwitch );
if (hasSeparateSwitches)
{
// implement action
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 ) {
// visual feedback
// 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 ) {
bool hasSeparateSwitches = Train->m_controlmapper.contains("pantvalvesupdate_bt:") && Train->m_controlmapper.contains("pantvalvesoff_bt:");
if( Command.action == GLFW_REPEAT ) { return; }
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::rear, operation_t::disable );
// 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 ) {
// visual feedback
// NOTE: pantvalves_sw: is a specialized button, with no toggle behavior support
Train->ggPantValvesButton.UpdateValue( 0.5, Train->dsbSwitch );
// NOTE: pantvalves_sw: is a speciali zed button, with no toggle behavior support
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 ) {
if( Command.action == GLFW_PRESS ) {
// 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 ) {
if (Train->DynamicObject->MoverParameters->enableModernDimmer)
return;
if( Command.action == GLFW_PRESS ) {
// 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
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 ) {
if (Train->DynamicObject->MoverParameters->enableModernDimmer)
return;
if( Command.action == GLFW_PRESS ) {
// 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
WriteLog( "Dim Headlights switch is missing, or wasn't defined" );
return;
// visual feedback
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;
*/
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 ) {
if (Train->DynamicObject->MoverParameters->enableModernDimmer) // nie wiem dlaczego to tak dziala ze jest odwrocona logika
return;
if( Command.action == GLFW_PRESS ) {
// 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
WriteLog( "Dim Headlights switch is missing, or wasn't defined" );
return;
// visual feedback
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
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
void TTrain::UpdateCab() {
@@ -6834,6 +7079,21 @@ bool TTrain::Update( double const Deltatime )
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
if( DynamicObject->Mechanik != nullptr ) {
m_doors = (
@@ -7350,6 +7610,12 @@ bool TTrain::Update( double const Deltatime )
else
btCompressors.Turn(false);
// Lampka zezwolenia na hamowanie ED
if (mvControlled->EpFuse)
btEDenabled.Turn(true);
else
btEDenabled.Turn(false);
// Lampka aktywowanej kabiny
if (mvControlled->CabActive != 0) {
btCabActived.Turn(true);
@@ -7358,6 +7624,11 @@ bool TTrain::Update( double const Deltatime )
btCabActived.Turn(false);
}
if (mvControlled->Battery && mvControlled->CabActive != 0)
btAKLVents.Turn(true);
else
btAKLVents.Turn(false);
if( true == lowvoltagepower ) {
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if( mvOccupied->SecuritySystem.is_vigilance_blinking() ) {
@@ -7893,6 +8164,7 @@ bool TTrain::Update( double const Deltatime )
ggBrakeProfileG.Update();
ggBrakeProfileR.Update();
ggBrakeOperationModeCtrl.Update();
ggWiperSw.Update();
ggMaxCurrentCtrl.UpdateValue(
( true == mvControlled->ShuntModeAllow ?
( true == mvControlled->ShuntMode ?
@@ -7989,12 +8261,16 @@ bool TTrain::Update( double const Deltatime )
ggPantCompressorButton.Update();
ggPantCompressorValve.Update();
ggPantValvesOff.Update();
ggPantValvesUpdate.Update();
ggLightsButton.Update();
ggUpperLightButton.Update();
ggLeftLightButton.Update();
ggRightLightButton.Update();
ggLeftEndLightButton.Update();
ggRightEndLightButton.Update();
ggModernLightDimSw.Update();
// hunter-230112
ggRearUpperLightButton.Update();
ggRearLeftLightButton.Update();
@@ -8002,6 +8278,7 @@ bool TTrain::Update( double const Deltatime )
ggRearLeftEndLightButton.Update();
ggRearRightEndLightButton.Update();
ggDimHeadlightsButton.Update();
ggDimHeadlightsButton.Update();
//------------
ggConverterButton.Update();
ggConverterLocalButton.Update();
@@ -9367,6 +9644,7 @@ void TTrain::clear_cab_controls()
ggBrakeProfileG.Clear();
ggBrakeProfileR.Clear();
ggBrakeOperationModeCtrl.Clear();
ggWiperSw.Clear();
ggMaxCurrentCtrl.Clear();
ggMainOffButton.Clear();
ggMainOnButton.Clear();
@@ -9469,6 +9747,10 @@ void TTrain::clear_cab_controls()
ggPantValvesButton.Clear();
ggPantCompressorButton.Clear();
ggPantCompressorValve.Clear();
ggPantValvesOff.Clear();
ggPantValvesUpdate.Clear();
ggI1B.Clear();
ggI2B.Clear();
ggI3B.Clear();
@@ -9580,6 +9862,7 @@ void TTrain::clear_cab_controls()
ggRightLightButton.Clear();
ggUpperLightButton.Clear();
ggDimHeadlightsButton.Clear();
ggModernLightDimSw.Clear();
ggLeftEndLightButton.Clear();
ggRightEndLightButton.Clear();
ggLightsButton.Clear();
@@ -9611,6 +9894,24 @@ void TTrain::set_cab_controls( int const Cab ) {
m_linebreakerstate > 0 ? 1.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
ggStLinOffButton.PutValue(
( mvControlled->StLinSwitchOff ?
@@ -9669,6 +9970,7 @@ void TTrain::set_cab_controls( int const Cab ) {
0.f ) );
}
ggPantValvesButton.PutValue( 0.5f );
// auxiliary compressor
ggPantCompressorValve.PutValue(
mvControlled->bPantKurek3 ?
@@ -9738,7 +10040,7 @@ void TTrain::set_cab_controls( int const Cab ) {
ggRightLightButton.PutValue( -1.f );
}
}
if( true == DynamicObject->DimHeadlights ) {
if( 1 == DynamicObject->MoverParameters->modernDimmerState ) {
ggDimHeadlightsButton.PutValue( 1.f );
}
// cab lights
@@ -9812,6 +10114,12 @@ void TTrain::set_cab_controls( int const Cab ) {
1.f :
0.f );
}
if (ggWiperSw.SubModel != nullptr)
{
ggWiperSw.PutValue(mvOccupied->wiperSwitchPos);
}
if (ggBrakeOperationModeCtrl.SubModel != nullptr) {
ggBrakeOperationModeCtrl.PutValue(
(mvOccupied->BrakeOpModeFlag > 0 ?
@@ -10051,7 +10359,9 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-universal8:", btUniversals[ 8 ] },
{ "i-universal9:", btUniversals[ 9 ] },
{ "i-cabactived:", btCabActived },
{"i-compressorany:", btCompressors }
{"i-aklvents:", btAKLVents},
{"i-compressorany:", btCompressors },
{"i-edenabled", btEDenabled },
};
{
auto lookup = lights.find( Label );
@@ -10172,6 +10482,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "leftend_sw:", ggLeftEndLightButton },
{ "rightend_sw:", ggRightEndLightButton },
{ "lights_sw:", ggLightsButton },
{ "moderndimmer_sw:", ggModernLightDimSw },
{ "rearupperlight_sw:", ggRearUpperLightButton },
{ "rearleftlight_sw:", ggRearLeftLightButton },
{ "rearrightlight_sw:", ggRearRightLightButton },
@@ -10282,6 +10593,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "invertertoggle10_bt:", ggInverterToggleButtons[9] },
{ "invertertoggle11_bt:", ggInverterToggleButtons[10] },
{ "invertertoggle12_bt:", ggInverterToggleButtons[11] },
{"pantvalvesupdate_bt:", ggPantValvesUpdate},
{"pantvalvesoff_bt:", ggPantValvesOff},
{"wipers_sw:", ggWiperSw}
};
{
auto const lookup { gauges.find( Label ) };

18
Train.h
View File

@@ -226,6 +226,8 @@ class TTrain {
// 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
// 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_aidriverdisable( 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_headlightenablerearupper( 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_redmarkerenablerearleft( 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 ggBrakeOperationModeCtrl; //przełącznik trybu pracy PS/PN/EP/MED
TGauge ggWiperSw; // przelacznik wycieraczek
TGauge ggMaxCurrentCtrl;
TGauge ggMainOffButton;
@@ -578,6 +584,7 @@ public: // reszta może by?publiczna
TGauge ggRightEndLightButton;
TGauge ggLightsButton; // przelacznik reflektorow (wszystkich)
TGauge ggDimHeadlightsButton; // headlights dimming switch
TGauge ggModernLightDimSw; // modern lights dimmer
// hunter-230112: przelacznik swiatel tylnich
TGauge ggRearUpperLightButton;
@@ -658,6 +665,8 @@ public: // reszta może by?publiczna
TGauge ggPantValvesButton;
TGauge ggPantCompressorButton;
TGauge ggPantCompressorValve;
TGauge ggPantValvesUpdate;
TGauge ggPantValvesOff;
// Winger 020304 - wlacznik ogrzewania
TGauge ggTrainHeatingButton;
TGauge ggSignallingButton;
@@ -769,8 +778,10 @@ public: // reszta może by?publiczna
TButton btLampkaRearRightLight;
TButton btLampkaRearLeftEndLight;
TButton btLampkaRearRightEndLight;
TButton btCabActived;
TButton btCompressors; // lampka pracy jakiejkolwiek sprezarki
TButton btCabActived;
TButton btAKLVents;
TButton btCompressors; // lampka pracy jakiejkolwiek sprezarki
TButton btEDenabled; // czy wlaczony jest hamulec ED (czy dostepny)
// other
TButton btLampkaMalfunction;
TButton btLampkaMalfunctionB;
@@ -833,6 +844,8 @@ private:
float fHaslerTimer;
float fConverterTimer; // hunter-261211: dla przekaznika
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
// McZapkie-240302 - przyda sie do tachometru
@@ -875,6 +888,7 @@ private:
bool m_dirbackward{ false }; // helper, true if direction set to backward
bool m_doorpermits{ false }; // helper, true if any door permit is active
float m_doorpermittimers[2] = { -1.f, -1.f };
float trainLenghtMeasureTimer = { -1.f };
// ld substitute
bool m_couplingdisconnect { false };
bool m_couplingdisconnectback { false };

View File

@@ -29,6 +29,9 @@ http://mozilla.org/MPL/2.0/.
#include "Timer.h"
#include "dictionary.h"
#include "version_info.h"
#include "ref/discord-rpc/include/discord_rpc.h"
#include <chrono>
#include "translation.h"
#ifdef _WIN32
#pragma comment (lib, "dsound.lib")
@@ -174,6 +177,83 @@ int eu07_application::run_crashgui()
}
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
eu07_application::init( int Argc, char *Argv[] ) {
@@ -186,6 +266,10 @@ eu07_application::init( int Argc, char *Argv[] ) {
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( "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, "
@@ -239,9 +323,15 @@ eu07_application::init( int Argc, char *Argv[] ) {
if (!init_network())
return -1;
// Run DiscordRPC service
std::thread sDiscordRPC(&eu07_application::DiscordRPCService, this);
Global.threads.emplace("DiscordRPC", std::move(sDiscordRPC));
return result;
}
double eu07_application::generate_sync() {
if (Timer::GetDeltaTime() == 0.0)
return 0.0;
@@ -433,7 +523,8 @@ eu07_application::run() {
std::this_thread::sleep_for( Global.minframetime - frametime );
}
}
Global.threads["LogService"].~thread(); // kill log service
Global.threads["DiscordRPC"].~thread(); // kill DiscordRPC service
return 0;
}

View File

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

View File

@@ -506,7 +506,7 @@ drivermouse_input::bindings( std::string const &Control ) const {
void
drivermouse_input::default_bindings() {
// pierwsza komenda jest od zwiekszania a druga od zmniejszania - ewentualnie kolejno lewy i prawy przycisk
m_buttonbindings = {
{ "jointctrl:", {
user_command::jointcontrollerset,
@@ -731,6 +731,9 @@ drivermouse_input::default_bindings() {
{ "dimheadlights_sw:", {
user_command::headlightsdimtoggle,
user_command::none } },
{"moderndimmer_sw:", {
user_command::modernlightdimmerincrease,
user_command::modernlightdimmerdecrease } },
{ "leftend_sw:", {
user_command::redmarkertoggleleft,
user_command::none } },
@@ -845,6 +848,12 @@ drivermouse_input::default_bindings() {
{ "pantvalves_sw:", {
user_command::pantographvalvesupdate,
user_command::pantographvalvesoff } },
{ "pantvalvesupdate_bt:", {
user_command::pantographvalvesupdate,
user_command::none}},
{ "pantvalvesoff_bt:", {
user_command::pantographvalvesoff,
user_command::none}},
{ "pantcompressor_sw:", {
user_command::pantographcompressoractivate,
user_command::none } },
@@ -1100,6 +1109,10 @@ drivermouse_input::default_bindings() {
{ "invertertoggle12_bt:",{
user_command::invertertoggle12,
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 );
}
render_section( "Camera", m_cameralines );
render_section( "Gfx Renderer", m_rendererlines );
render_section( "Gfx Renderer / Statistics", m_rendererlines );
render_section_settings();
render_section_developer(); // Developer tools
#ifdef WITH_UART
if(true == render_section( "UART", m_uartlines)) {
int ports_num = UartStatus.available_ports.size();
@@ -1452,6 +1453,14 @@ debug_panel::update_section_renderer( std::vector<text_line> &Output ) {
// renderer stats
Output.emplace_back( GfxRenderer->info_times(), 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
@@ -1475,6 +1484,19 @@ debug_panel::render_section( std::vector<text_line> const &Lines ) {
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
debug_panel::render_section_settings() {

View File

@@ -104,7 +104,8 @@ private:
bool render_section_uart();
#endif
bool render_section_settings();
// members
bool render_section_developer();
// members
std::array<char, 1024> m_buffer;
std::array<char, 128> m_eventsearch;
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_dragging = false;
Application.set_cursor( GLFW_CURSOR_NORMAL );
//Application.set_cursor( GLFW_CURSOR_NORMAL );
static_cast<editor_ui*>( m_userinterface.get() )->set_node(nullptr);
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 ) {
// left button press
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;
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());
if (mode == nodebank_panel::MODIFY) {
@@ -329,10 +333,10 @@ editor_mode::on_mouse_button( int const Button, int const Action, int const Mods
return;
m_node = node;
if( m_node )
Application.set_cursor( GLFW_CURSOR_DISABLED );
else
m_dragging = false;
//if( m_node )
//Application.set_cursor( GLFW_CURSOR_DISABLED );
//else
//m_dragging = false;
ui->set_node(m_node);
}
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)
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 );
}
});
@@ -370,8 +390,8 @@ editor_mode::on_mouse_button( int const Button, int const Action, int const Mods
}
else {
// left button release
if( m_node )
Application.set_cursor( GLFW_CURSOR_NORMAL );
//if( m_node )
//Application.set_cursor( GLFW_CURSOR_NORMAL );
m_dragging = false;
// prime history stack for another snapshot
m_takesnapshot = true;

View File

@@ -21,6 +21,7 @@ editor_ui::editor_ui() {
add_external_panel( &m_itempropertiespanel );
add_external_panel( &m_nodebankpanel );
add_external_panel( &m_functionspanel );
}
// updates state of UI elements
@@ -41,6 +42,7 @@ editor_ui::update() {
ui_layer::update();
m_itempropertiespanel.update( m_node );
m_functionspanel.update( m_node );
}
void
@@ -63,3 +65,17 @@ nodebank_panel::edit_mode
editor_ui::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 );
void
add_node_template(const std::string &desc);
float
rot_val();
bool
rot_from_last();
functions_panel::rotation_mode
rot_mode();
const std::string *
get_active_node_template();
nodebank_panel::edit_mode
@@ -39,6 +45,7 @@ public:
private:
// members
itemproperties_panel m_itempropertiespanel { "Node Properties", true };
functions_panel m_functionspanel { "Functions", true };
nodebank_panel m_nodebankpanel{ "Node Bank", true };
scene::basic_node * m_node { nullptr }; // currently bound scene node, if any
};

View File

@@ -420,8 +420,6 @@ nodebank_panel::render() {
ImGui::SameLine();
ImGui::RadioButton("Insert from bank", (int*)&mode, ADD);
ImGui::SameLine();
ImGui::RadioButton("Brush", (int*)&mode, BRUSH);
ImGui::SameLine();
ImGui::RadioButton( "Copy to bank", (int*)&mode, COPY );
ImGui::SameLine();
if (ImGui::Button("Reload Nodebank"))
@@ -493,3 +491,64 @@ nodebank_panel::generate_node_label( std::string Input ) const {
model :
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 ];
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
+ ( ( lights & light::headlight_left ) ? 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 ) {
light.intensity = std::max( 0.0f, std::log( (float)light.count + 1.0f ) );
light.intensity *= ( light.owner->DimHeadlights ? 0.6f : 1.0f );
light.intensity = std::max(0.0f, std::log((float)light.count + 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
light.state = {
( ( lights & light::headlight_left ) ? 1.f : 0.f ),
( ( lights & light::headlight_upper ) ? 1.f : 0.f ),
( ( lights & light::headlight_right ) ? 1.f : 0.f ) };
light.state *= ( light.owner->DimHeadlights ? 0.6f : 1.0f );
( ( lights & light::headlight_left | light::highbeamlight_left ) ? 1.f : 0.f ),
( ( lights & light::headlight_upper ) ? 1.f : 0.f ),
( ( lights & light::headlight_right | light::highbeamlight_right) ? 1.f : 0.f ) };
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 {
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 {
struct bounding_area {
glm::dvec3 center; // mid point of the rectangle
glm::highp_dvec3 center; // mid point of the rectangle
float radius { -1.0f }; // radius of the bounding sphere
bounding_area() = default;
@@ -94,7 +93,7 @@ public:
material_handle material { null_handle };
lighting_data lighting;
// 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
std::vector<world_vertex> vertices; // world space source data of the geometry
// 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") },
{ "rightlight_sw:", STRN("right headlight") },
{ "dimheadlights_sw:", STRN("headlights dimmer") },
{ "moderndimmer_sw:", STRN("headlights dimmer") },
{ "leftend_sw:", STRN("left marker light") },
{ "rightend_sw:", STRN("right marker light") },
{ "lights_sw:", STRN("light pattern") },
@@ -282,6 +283,8 @@ std::string locale::label_cab_control(std::string const &Label)
{ "pantselectedoff_sw:", STRN("selected pantograph") },
{ "pantselect_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") },
{ "pantcompressorvalve_sw:", STRN("pantograph 3 way valve") },
{ "trainheating_sw:", STRN("heating") },
@@ -319,7 +322,8 @@ std::string locale::label_cab_control(std::string const &Label)
{ "universal6:", STRN("interactive part") },
{ "universal7:", 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 );

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 ) );
}
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
template <typename VecType_>
bool