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

Merge pull request #83 from Unofficial-MaSzyna-Developement/new-features-feb-25

New features done in february 2025
This commit is contained in:
Ryba04
2025-03-16 17:49:08 +01:00
committed by GitHub
27 changed files with 837 additions and 132 deletions

4
.gitmodules vendored
View File

@@ -1,3 +1,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

@@ -429,6 +429,12 @@ target_link_libraries(${PROJECT_NAME} Threads::Threads)
find_package(GLM REQUIRED)
include_directories(${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

@@ -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;
@@ -576,20 +692,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
@@ -5041,7 +5157,8 @@ 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;
@@ -5142,8 +5259,8 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
if (iAnimType[ANIM_PANTS]) // o ile jakieś pantografy są (a domyślnie są)
pants = &pAnimations[k]; // zapamiętanie na potrzeby wyszukania submodeli
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
@@ -7740,9 +7857,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 ) };

View File

@@ -103,7 +103,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 +125,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 +219,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
@@ -573,6 +587,9 @@ 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

View File

@@ -213,6 +213,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 };
@@ -118,7 +126,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 );

View File

@@ -469,6 +469,13 @@ struct TBoilerType {
//}
};
/*rodzaj odbieraka pradu*/
enum TPantType
{
AKP_4E,
DSAx,
EC160_200,
WBL85
};
struct TCurrentCollector {
long CollectorsNo; //musi być tu, bo inaczej się kopie
double MinH; double MaxH; //zakres ruchu pantografu, nigdzie nie używany
@@ -480,6 +487,7 @@ struct TCurrentCollector {
double MaxPress; //maksymalne ciśnienie za reduktorem
bool FakePower;
int PhysicalLayout;
TPantType PantographType;
//inline TCurrentCollector() {
// CollectorsNo = 0;
// MinH, MaxH, CSW, MinV, MaxV = 0.0;
@@ -1069,6 +1077,8 @@ class TMoverParameters
};
public:
std::string chkPath;
bool reload_FIZ();
double dMoveLen = 0.0;
/*---opis lokomotywy, wagonu itp*/
/*--opis serii--*/
@@ -1138,6 +1148,9 @@ class TMoverParameters
int UniversalBrakeButtonFlag[3] = {0, 0, 0}; /* mozliwe działania przycisków hamulcowych */
int UniversalResetButtonFlag[3] = {0, 0, 0}; // customizable reset buttons assignments
int TurboTest = 0;
bool isBatteryButtonImpulse = false; // czy przelacznik baterii traktowac jako pojedynczy przycisk
bool shouldHoldBatteryButton = false; // czy nalezy przytrzymac przycisk baterii aby wlaczyc/wylaczyc baterie
float BatteryButtonHoldTime = 1.f; // minimalny czas przytrzymania przycisku baterii
double MaxBrakeForce = 0.0; /*maksymalna sila nacisku hamulca*/
double MaxBrakePress[5]; // pomocniczy, proz, sred, lad, pp
double P2FTrans = 0.0;
@@ -1213,6 +1226,8 @@ class TMoverParameters
double SpringBrakeDriveEmergencyVel{-1};
bool HideDirStatusWhenMoving{false}; // Czy gasic lampki kierunku powyzej predkosci zdefiniowanej przez HideDirStatusSpeed
int HideDirStatusSpeed{1}; // Predkosc od ktorej lampki kierunku sa wylaczane
bool isDoubleClickForMeasureNeeded = {false}; // czy rozpoczecie pomiaru odleglosci odbywa sie po podwojnym wcisnienciu przycisku?
float DistanceCounterDoublePressPeriod = {1.f}; // czas w jakim nalezy podwojnie wcisnac przycisk, aby rozpoczac pomiar odleglosci
TSecuritySystem SecuritySystem;
int EmergencyBrakeWarningSignal{0}; // combined with basic WarningSignal when manual emergency brake is active
TUniversalCtrlTable UniCtrlList; /*lista pozycji uniwersalnego nastawnika*/

View File

@@ -9444,6 +9444,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;
@@ -10625,6 +10626,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 },
@@ -11331,6 +11338,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, "" );
@@ -12467,6 +12485,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

@@ -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
}

278
Train.cpp
View File

@@ -1317,7 +1317,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
@@ -2388,7 +2398,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
@@ -2402,44 +2413,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) {
@@ -2848,23 +2975,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 ) {
@@ -2872,12 +3019,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 );
}
}
@@ -6926,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 = (
@@ -7435,6 +7603,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);
@@ -7448,6 +7622,7 @@ bool TTrain::Update( double const Deltatime )
else
btAKLVents.Turn(false);
if( true == lowvoltagepower ) {
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if( mvOccupied->SecuritySystem.is_vigilance_blinking() ) {
@@ -8079,6 +8254,9 @@ bool TTrain::Update( double const Deltatime )
ggPantCompressorButton.Update();
ggPantCompressorValve.Update();
ggPantValvesOff.Update();
ggPantValvesUpdate.Update();
ggLightsButton.Update();
ggUpperLightButton.Update();
ggLeftLightButton.Update();
@@ -9572,6 +9750,10 @@ void TTrain::clear_cab_controls()
ggPantValvesButton.Clear();
ggPantCompressorButton.Clear();
ggPantCompressorValve.Clear();
ggPantValvesOff.Clear();
ggPantValvesUpdate.Clear();
ggI1B.Clear();
ggI2B.Clear();
ggI3B.Clear();
@@ -9723,6 +9905,16 @@ void TTrain::set_cab_controls( int const Cab ) {
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 ?
@@ -9781,6 +9973,7 @@ void TTrain::set_cab_controls( int const Cab ) {
0.f ) );
}
ggPantValvesButton.PutValue( 0.5f );
// auxiliary compressor
ggPantCompressorValve.PutValue(
mvControlled->bPantKurek3 ?
@@ -10164,7 +10357,8 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-universal9:", btUniversals[ 9 ] },
{ "i-cabactived:", btCabActived },
{"i-aklvents:", btAKLVents},
{"i-compressorany:", btCompressors }
{"i-compressorany:", btCompressors },
{"i-edenabled", btEDenabled },
};
{
auto lookup = lights.find( Label );
@@ -10396,6 +10590,8 @@ 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}
};
{
auto const lookup { gauges.find( Label ) };

View File

@@ -663,6 +663,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;
@@ -777,6 +779,7 @@ public: // reszta może by?publiczna
TButton btCabActived;
TButton btAKLVents;
TButton btCompressors; // lampka pracy jakiejkolwiek sprezarki
TButton btEDenabled; // czy wlaczony jest hamulec ED (czy dostepny)
// other
TButton btLampkaMalfunction;
TButton btLampkaMalfunctionB;
@@ -840,6 +843,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
@@ -882,6 +887,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

View File

@@ -854,6 +854,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 } },

View File

@@ -620,8 +620,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();
@@ -1469,6 +1470,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
@@ -1492,6 +1501,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;
};

1
ref/discord-rpc Submodule

Submodule ref/discord-rpc added at 963aa9f3e5

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

@@ -283,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") },