diff --git a/AnimModel.cpp b/AnimModel.cpp index 2cb80ff8..2a26e7d8 100644 --- a/AnimModel.cpp +++ b/AnimModel.cpp @@ -18,6 +18,7 @@ http://mozilla.org/MPL/2.0/. #include "renderer.h" #include "MdlMngr.h" #include "simulation.h" +#include "simulationtime.h" #include "Globals.h" #include "Timer.h" #include "Logs.h" @@ -361,13 +362,14 @@ void TAnimContainer::UpdateModelIK() { // odwrotna kinematyka wyliczana dopiero po ustawieniu macierzy w submodelach if (pSubModel) // pozbyć się tego - sprawdzać wcześniej { - if (pSubModel->b_Anim & at_IK) + if ((pSubModel->b_Anim == TAnimType::at_IK) + ||(pSubModel->b_Anim == TAnimType::at_IK22)) { // odwrotna kinematyka float3 d, k; TSubModel *ch = pSubModel->ChildGet(); switch (pSubModel->b_Anim) { - case at_IK11: // stopa: ustawić w kierunku czubka (pierwszy potomny) + case TAnimType::at_IK11: // stopa: ustawić w kierunku czubka (pierwszy potomny) d = ch->Translation1Get(); // wektor względem aktualnego układu (nie uwzględnia // obrotu) k = float3(RadToDeg(atan2(d.z, hypot(d.x, d.y))), 0.0, @@ -377,7 +379,7 @@ void TAnimContainer::UpdateModelIK() // WriteLog("--> "+AnsiString(k.x)+" "+AnsiString(k.y)+" "+AnsiString(k.z)); // Ra: to już jest dobrze, może być inna ćwiartka i znak break; - case at_IK22: // udo: ustawić w kierunku pierwszej potomnej pierwszej potomnej (kostki) + case TAnimType::at_IK22: // udo: ustawić w kierunku pierwszej potomnej pierwszej potomnej (kostki) // pozycję kostki należy określić względem kości centralnej (+biodro może być // pochylone) // potem wyliczyć ewentualne odchylenie w tej i następnej @@ -420,7 +422,7 @@ TAnimModel::TAnimModel( scene::node_data const &Nodedata ) : basic_node( Nodedat TAnimModel::~TAnimModel() { - delete pAdvanced; // nie ma zaawansowanej animacji + SafeDelete(pAdvanced); // nie ma zaawansowanej animacji SafeDelete(pRoot); } @@ -631,10 +633,6 @@ int TAnimModel::Flags() //--------------------------------------------------------------------------- -bool TAnimModel::TerrainLoaded() -{ // zliczanie kwadratów kilometrowych (główna linia po Next) do tworznia tablicy - return (this ? pModel != NULL : false); -}; int TAnimModel::TerrainCount() { // zliczanie kwadratów kilometrowych (główna linia po Next) do tworznia tablicy return pModel ? pModel->TerrainCount() : 0; diff --git a/AnimModel.h b/AnimModel.h index b2a73536..29402f4a 100644 --- a/AnimModel.h +++ b/AnimModel.h @@ -47,7 +47,7 @@ class TEvent; class TAnimContainer { // opakowanie submodelu, określające animację egzemplarza - obsługiwane jako lista - friend class TAnimModel; + friend TAnimModel; private: Math3D::vector3 vRotateAngles; // dla obrotów Eulera @@ -124,8 +124,8 @@ class TAnimAdvanced // opakowanie modelu, określające stan egzemplarza class TAnimModel : public scene::basic_node { - friend class opengl_renderer; - friend class ui_layer; + friend opengl_renderer; + friend ui_layer; public: // constructors @@ -138,11 +138,8 @@ public: bool Load(cParser *parser, bool ter = false); TAnimContainer * AddContainer(std::string const &Name); TAnimContainer * GetContainer(std::string const &Name = ""); - void RaAnglesSet( glm::vec3 Angles ) { - vAngle = { Angles }; }; void LightSet( int const n, float const v ); void AnimationVND( void *pData, double a, double b, double c, double d ); - bool TerrainLoaded(); int TerrainCount(); TSubModel * TerrainSquare(int n); int Flags(); @@ -154,6 +151,14 @@ public: TModel3d * Model() const { return pModel; } + inline + void + Angles( glm::vec3 const &Angles ) { + vAngle = Angles; } + inline + glm::vec3 + Angles() const { + return vAngle; } // members static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania @@ -178,7 +183,7 @@ private: int iNumLights { 0 }; TSubModel *LightsOn[ iMaxNumLights ]; // Ra: te wskaźniki powinny być w ramach TModel3d TSubModel *LightsOff[ iMaxNumLights ]; - Math3D::vector3 vAngle; // bazowe obroty egzemplarza względem osi + glm::vec3 vAngle; // bazowe obroty egzemplarza względem osi material_data m_materialdata; std::string asText; // tekst dla wyświetlacza znakowego diff --git a/CMakeLists.txt b/CMakeLists.txt index dc42695f..ad2d3a51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,10 @@ set(SOURCES "light.cpp" "uitranscripts.cpp" "station.cpp" +"application.cpp" +"simulationtime.cpp" +"sceneeditor.cpp" +"screenshot.cpp" ) set (PREFIX "") diff --git a/Camera.cpp b/Camera.cpp index b8758101..4e9f97b8 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -27,7 +27,7 @@ void TCamera::Init( Math3D::vector3 NPos, Math3D::vector3 NAngle) { Roll = NAngle.z; Pos = NPos; - Type = (Global.bFreeFly ? tp_Free : tp_Follow); + Type = (Global.bFreeFly ? TCameraType::tp_Free : TCameraType::tp_Follow); }; void TCamera::Reset() { @@ -67,8 +67,8 @@ TCamera::OnCommand( command_data const &Command ) { case user_command::viewturn: { OnCursorMove( - reinterpret_cast( Command.param1 ) * 0.005 * Global.fMouseXScale / Global.ZoomFactor, - reinterpret_cast( Command.param2 ) * 0.01 * Global.fMouseYScale / Global.ZoomFactor ); + Command.param1 * 0.005 * Global.fMouseXScale / Global.ZoomFactor, + Command.param2 * 0.01 * Global.fMouseYScale / Global.ZoomFactor ); break; } @@ -76,17 +76,17 @@ TCamera::OnCommand( command_data const &Command ) { case user_command::movehorizontalfast: { auto const movespeed = ( - Type == tp_Free ? runspeed : - Type == tp_Follow ? walkspeed : + Type == TCameraType::tp_Free ? runspeed : + Type == TCameraType::tp_Follow ? walkspeed : 0.0 ); auto const speedmultiplier = ( - ( ( Type == tp_Free ) && ( Command.command == user_command::movehorizontalfast ) ) ? + ( ( Type == TCameraType::tp_Free ) && ( Command.command == user_command::movehorizontalfast ) ) ? 30.0 : 1.0 ); // left-right - auto const movexparam { reinterpret_cast( Command.param1 ) }; + auto const movexparam { Command.param1 }; // 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed auto const movex { walkspeed + ( std::max( 0.0, std::abs( movexparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) }; @@ -96,7 +96,7 @@ TCamera::OnCommand( command_data const &Command ) { 0.0 ); // forward-back - double const movezparam { reinterpret_cast( Command.param2 ) }; + double const movezparam { Command.param2 }; auto const movez { walkspeed + ( std::max( 0.0, std::abs( movezparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) }; // NOTE: z-axis is flipped given world coordinate system m_moverate.z = ( @@ -111,17 +111,17 @@ TCamera::OnCommand( command_data const &Command ) { case user_command::moveverticalfast: { auto const movespeed = ( - Type == tp_Free ? runspeed * 0.5 : - Type == tp_Follow ? walkspeed : + Type == TCameraType::tp_Free ? runspeed * 0.5 : + Type == TCameraType::tp_Follow ? walkspeed : 0.0 ); auto const speedmultiplier = ( - ( ( Type == tp_Free ) && ( Command.command == user_command::moveverticalfast ) ) ? + ( ( Type == TCameraType::tp_Free ) && ( Command.command == user_command::moveverticalfast ) ) ? 10.0 : 1.0 ); // up-down - auto const moveyparam { reinterpret_cast( Command.param1 ) }; + auto const moveyparam { Command.param1 }; // 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed auto const movey { walkspeed + ( std::max( 0.0, std::abs( moveyparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) }; @@ -145,8 +145,8 @@ TCamera::OnCommand( command_data const &Command ) { void TCamera::Update() { - if( FreeFlyModeFlag == true ) { Type = tp_Free; } - else { Type = tp_Follow; } + if( FreeFlyModeFlag == true ) { Type = TCameraType::tp_Free; } + else { Type = TCameraType::tp_Follow; } // check for sent user commands // NOTE: this is a temporary arrangement, for the transition period from old command setup to the new one @@ -162,7 +162,7 @@ void TCamera::Update() auto const deltatime { Timer::GetDeltaRenderTime() }; // czas bez pauzy // update position - if( ( Type == tp_Free ) + if( ( Type == TCameraType::tp_Free ) || ( false == Global.ctrlState ) || ( true == DebugCameraFlag ) ) { // ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed @@ -172,7 +172,7 @@ void TCamera::Update() Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -std::abs( m_moverate.y ), std::abs( m_moverate.y ) ); } - if( ( Type == tp_Free ) + if( ( Type == TCameraType::tp_Free ) || ( true == DebugCameraFlag ) ) { // free movement position update is handled here, movement while in vehicle is handled by train update Math3D::vector3 Vec = Velocity; @@ -193,7 +193,7 @@ void TCamera::Update() Pitch -= rotationfactor * m_rotationoffsets.x; m_rotationoffsets.x *= ( 1.0 - rotationfactor ); - if( Type == tp_Follow ) { + if( Type == TCameraType::tp_Follow ) { // jeżeli jazda z pojazdem ograniczenie kąta spoglądania w dół i w górę Pitch = clamp( Pitch, -M_PI_4, M_PI_4 ); } @@ -211,7 +211,7 @@ bool TCamera::SetMatrix( glm::dmat4 &Matrix ) { Matrix = glm::rotate( Matrix, -Pitch, glm::dvec3( 1.0, 0.0, 0.0 ) ); Matrix = glm::rotate( Matrix, -Yaw, glm::dvec3( 0.0, 1.0, 0.0 ) ); // w zewnętrznym widoku: kierunek patrzenia - if( ( Type == tp_Follow ) && ( false == DebugCameraFlag ) ) { + if( ( Type == TCameraType::tp_Follow ) && ( false == DebugCameraFlag ) ) { Matrix *= glm::lookAt( glm::dvec3{ Pos }, @@ -238,9 +238,3 @@ void TCamera::RaLook() m_rotationoffsets.x = 0.0; } }; - -void TCamera::Stop() -{ // wyłącznie bezwładnego ruchu po powrocie do kabiny - Type = tp_Follow; - Velocity = Math3D::vector3(0, 0, 0); -}; diff --git a/Camera.h b/Camera.h index 9a70d438..792f488d 100644 --- a/Camera.h +++ b/Camera.h @@ -13,7 +13,7 @@ http://mozilla.org/MPL/2.0/. #include "command.h" //--------------------------------------------------------------------------- -enum TCameraType +enum class TCameraType { // tryby pracy kamery tp_Follow, // jazda z pojazdem tp_Free, // stoi na scenerii @@ -31,7 +31,6 @@ class TCamera { Math3D::vector3 GetDirection(); bool SetMatrix(glm::dmat4 &Matrix); void RaLook(); - void Stop(); TCameraType Type; double Pitch; diff --git a/Classes.h b/Classes.h index d9a3aa6a..e146f462 100644 --- a/Classes.h +++ b/Classes.h @@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/. //--------------------------------------------------------------------------- // Ra: zestaw klas do robienia wskaźników, aby uporządkować nagłówki //--------------------------------------------------------------------------- +class opengl_renderer; class TTrack; // odcinek trajektorii class TEvent; class TTrain; // pojazd sterowany @@ -29,9 +30,9 @@ class TTraction; // drut class TTractionPowerSource; // zasilanie drutów class TWorld; class TCamera; - -class simulation_time; +class scenario_time; class TMoverParameters; +class ui_layer; namespace scene { struct node_data; @@ -45,7 +46,7 @@ class TMtableTime; // czas dla danego posterunku class TController; // obiekt sterujący pociągiem (AI) -enum TCommandType +enum class TCommandType { // binarne odpowiedniki komend w komórce pamięci cm_Unknown, // ciąg nierozpoznany (nie jest komendą) cm_Ready, // W4 zezwala na odjazd, ale semafor może zatrzymać diff --git a/Console.cpp b/Console.cpp index 9150c21d..bbec4fde 100644 --- a/Console.cpp +++ b/Console.cpp @@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/. #include "stdafx.h" #include "Console.h" #include "Globals.h" +#include "application.h" #include "LPT.h" #include "Logs.h" #include "PoKeys55.h" diff --git a/Console.h b/Console.h index 4a231128..ce403487 100644 --- a/Console.h +++ b/Console.h @@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/. #ifndef ConsoleH #define ConsoleH #include "Globals.h" +#include "application.h" //--------------------------------------------------------------------------- class TConsoleDevice; // urządzenie podłączalne za pomocą DLL class TPoKeys55; @@ -51,7 +52,7 @@ class Console inline static bool Pressed(int x) { // na razie tak - czyta się tylko klawiatura - if (glfwGetKey(Global.window, x) == GLFW_TRUE) + if (glfwGetKey(Application.window(), x) == GLFW_TRUE) return true; else return false; diff --git a/Driver.cpp b/Driver.cpp index 63aed652..35672d30 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -25,6 +25,8 @@ http://mozilla.org/MPL/2.0/. #include "utilities.h" #include "McZapkie/MOVER.h" #include "Track.h" +#include "simulationtime.h" +#include "station.h" #define LOGVELOCITY 0 #define LOGORDERS 1 @@ -199,12 +201,12 @@ void TSpeedPos::CommandCheck() double value2 = evEvent->ValueGet(2); switch (command) { - case cm_ShuntVelocity: + case TCommandType::cm_ShuntVelocity: // prędkość manewrową zapisać, najwyżej AI zignoruje przy analizie tabelki fVelNext = value1; // powinno być value2, bo druga określa "za"? iFlags |= spShuntSemaphor; break; - case cm_SetVelocity: + case TCommandType::cm_SetVelocity: // w semaforze typu "m" jest ShuntVelocity dla Ms2 i SetVelocity dla S1 // SetVelocity * 0 -> można jechać, ale stanąć przed // SetVelocity 0 20 -> stanąć przed, potem można jechać 20 (SBL) @@ -220,31 +222,31 @@ void TSpeedPos::CommandCheck() iFlags |= spStopOnSBL; // flaga, że ma zatrzymać; na pewno nie zezwoli na manewry } break; - case cm_SectionVelocity: + case TCommandType::cm_SectionVelocity: // odcinek z ograniczeniem prędkości fVelNext = value1; fSectionVelocityDist = value2; iFlags |= spSectionVel; break; - case cm_RoadVelocity: + case TCommandType::cm_RoadVelocity: // prędkość drogowa (od tej pory będzie jako domyślna najwyższa) fVelNext = value1; iFlags |= spRoadVel; break; - case cm_PassengerStopPoint: + case TCommandType::cm_PassengerStopPoint: // nie ma dostępu do rozkładu // przystanek, najwyżej AI zignoruje przy analizie tabelki // if ((iFlags & spPassengerStopPoint) == 0) fVelNext = 0.0; // TrainParams->IsStop()?0.0:-1.0; //na razie tak iFlags |= spPassengerStopPoint; // niestety nie da się w tym miejscu współpracować z rozkładem break; - case cm_SetProximityVelocity: + case TCommandType::cm_SetProximityVelocity: // musi zostać gdyż inaczej nie działają manewry fVelNext = -1; iFlags |= spProximityVelocity; // fSectionVelocityDist = value2; break; - case cm_OutsideStation: + case TCommandType::cm_OutsideStation: // w trybie manewrowym: skanować od niej wstecz i stanąć po wyjechaniu za sygnalizator i // zmienić kierunek // w trybie pociągowym: można przyspieszyć do wskazanej prędkości (po zjechaniu z rozjazdów) @@ -801,7 +803,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN double d; // droga double d_to_next_sem = 10000.0; //ustaiwamy na pewno dalej niż widzi AI bool isatpassengerstop { false }; // true if the consist is within acceptable range of w4 post - TCommandType go = cm_Unknown; + TCommandType go = TCommandType::cm_Unknown; eSignNext = NULL; // te flagi są ustawiane tutaj, w razie potrzeby iDrivigFlags &= ~(moveTrackEnd | moveSwitchFound | moveSemaphorFound | moveSpeedLimitFound); @@ -1009,8 +1011,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN iDrivigFlags |= moveStopCloser; // do następnego W4 podjechać blisko (z dociąganiem) sSpeedTable[i].iFlags = 0; // nie liczy się już zupełnie (nie wyśle SetVelocity) sSpeedTable[i].fVelNext = -1; // można jechać za W4 - if (go == cm_Unknown) // jeśli nie było komendy wcześniej - go = cm_Ready; // gotów do odjazdu z W4 (semafor może + if (go == TCommandType::cm_Unknown) // jeśli nie było komendy wcześniej + go = TCommandType::cm_Ready; // gotów do odjazdu z W4 (semafor może // zatrzymać) if( false == tsGuardSignal.empty() ) { // jeśli mamy głos kierownika, to odegrać @@ -1230,12 +1232,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN sSpeedTable[ i ].iFlags = 0; } } - else if( go == cm_Unknown ) { + else if( go == TCommandType::cm_Unknown ) { // jeśli jeszcze nie ma komendy // komenda jest tylko gdy ma jechać, bo stoi na podstawietabelki if( v != 0.0 ) { // jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie VelSignal - go = cm_ShuntVelocity; // w trybie pociągowym tylko jeśli włącza + go = TCommandType::cm_ShuntVelocity; // w trybie pociągowym tylko jeśli włącza // tryb manewrowy (v!=0.0) // Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo Tm może być // daleko @@ -1256,12 +1258,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN } else if( !( sSpeedTable[ i ].iFlags & spSectionVel ) ) { //jeśli jakiś event pasywny ale nie ograniczenie - if( go == cm_Unknown ) { + if( go == TCommandType::cm_Unknown ) { // jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie VelSignal if( ( v < 0.0 ) || ( v >= 1.0 ) ) { // bo wartość 0.1 służy do hamowania tylko - go = cm_SetVelocity; // może odjechać + go = TCommandType::cm_SetVelocity; // może odjechać // Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo semafor może być daleko // VelSignal=v; //nie do końca tak, to jest druga prędkość; -1 nie wpisywać... if( VelSignal == 0.0 ) { @@ -1293,12 +1295,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN eSignNext = sSpeedTable[ i ].evEvent; // dla informacji if( true == TestFlag( iDrivigFlags, moveStopHere ) ) { // jeśli ma stać, dostaje komendę od razu - go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu + go = TCommandType::cm_Command; // komenda z komórki, do wykonania po zatrzymaniu } else if( sSpeedTable[ i ].fDist <= fMaxProximityDist ) { // jeśli ma dociągnąć, to niech dociąga // (moveStopCloser dotyczy dociągania do W4, nie semafora) - go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu + go = TCommandType::cm_Command; // komenda z komórki, do wykonania po zatrzymaniu } } } @@ -1669,7 +1671,7 @@ void TController::Activation() TDynamicObject *old = pVehicle, *d = pVehicle; // w tym siedzi AI TController *drugi; // jakby były dwa, to zamienić miejscami, a nie robić wycieku pamięci // poprzez nadpisanie - int brake = mvOccupied->LocalBrakePos; + auto const localbrakelevel { mvOccupied->LocalBrakePosA }; while (mvControlling->MainCtrlPos) // samo zapętlenie DecSpeed() nie wystarcza :/ DecSpeed(true); // wymuszenie zerowania nastawnika jazdy while (mvOccupied->ActiveDir < 0) @@ -1681,7 +1683,7 @@ void TController::Activation() { mvControlling->MainSwitch( false); // dezaktywacja czuwaka, jeśli przejście do innego członu - mvOccupied->DecLocalBrakeLevel(10); // zwolnienie hamulca w opuszczanym pojeździe + mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe // mvOccupied->BrakeLevelSet((mvOccupied->BrakeHandle==FVel6)?4:-2); //odcięcie na // zaworze maszynisty, FVel6 po drugiej stronie nie luzuje mvOccupied->BrakeLevelSet( @@ -1719,7 +1721,7 @@ void TController::Activation() ControllingSet(); // utworzenie połączenia do sterowanego pojazdu (może się zmienić) - // silnikowy dla EZT } - if( mvControlling->EngineType == DieselEngine ) { + if( mvControlling->EngineType == TEngineType::DieselEngine ) { // dla 2Ls150 - przed ustawieniem kierunku - można zmienić tryb pracy if( mvControlling->ShuntModeAllow ) { mvControlling->CurrentSwitch( @@ -1734,8 +1736,8 @@ void TController::Activation() // mvOccupied->ActiveDir=0; //żeby sam ustawił kierunek mvOccupied->CabActivisation(); // uruchomienie kabin w członach DirectionForward(true); // nawrotnik do przodu - if (brake) // hamowanie tylko jeśli był wcześniej zahamowany (bo możliwe, że jedzie!) - mvOccupied->IncLocalBrakeLevel(brake); // zahamuj jak wcześniej + if (localbrakelevel > 0.0) // hamowanie tylko jeśli był wcześniej zahamowany (bo możliwe, że jedzie!) + mvOccupied->LocalBrakePosA = localbrakelevel; // zahamuj jak wcześniej CheckVehicles(); // sprawdzenie składu, AI zapali światła TableClear(); // resetowanie tabelki skanowania torów } @@ -1982,7 +1984,7 @@ bool TController::CheckVehicles(TOrders user) p->DestinationSet(TrainParams->Relation2, TrainParams->TrainName); // relacja docelowa, jeśli nie było if (AIControllFlag) // jeśli prowadzi komputer p->RaLightsSet(0, 0); // gasimy światła - if (p->MoverParameters->EnginePowerSource.SourceType == CurrentCollector) + if (p->MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) { // jeśli pojazd posiada pantograf, to przydzielamy mu maskę, którą będzie informował o // jeździe bezprądowej p->iOverheadMask = pantmask; @@ -2272,7 +2274,7 @@ bool TController::PrepareEngine() ReactionTime = PrepareTime; iDrivigFlags |= moveActive; // może skanować sygnały i reagować na komendy - if ( mvControlling->EnginePowerSource.SourceType == CurrentCollector ) { + if ( mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) { voltfront = true; voltrear = true; } @@ -2286,15 +2288,15 @@ bool TController::PrepareEngine() if (AIControllFlag) { // część wykonawcza dla sterowania przez komputer mvOccupied->BatterySwitch( true ); - if( ( mvControlling->EngineType == DieselElectric ) - || ( mvControlling->EngineType == DieselEngine ) ) { + if( ( mvControlling->EngineType == TEngineType::DieselElectric ) + || ( mvControlling->EngineType == TEngineType::DieselEngine ) ) { mvControlling->OilPumpSwitch( true ); workingtemperature = UpdateHeating(); if( true == workingtemperature ) { mvControlling->FuelPumpSwitch( true ); } } - if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) + if (mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) { // jeśli silnikowy jest pantografującym mvOccupied->PantFront( true ); mvOccupied->PantRear( true ); @@ -2425,7 +2427,7 @@ bool TController::ReleaseEngine() ReactionTime = PrepareTime; if (AIControllFlag) { // jeśli steruje komputer - if (mvOccupied->DoorCloseCtrl == control::driver) + if (mvOccupied->DoorCloseCtrl == control_t::driver) { // zamykanie drzwi if (mvOccupied->DoorLeftOpened) mvOccupied->DoorLeft(false); @@ -2437,7 +2439,7 @@ bool TController::ReleaseEngine() { mvControlling->CompressorSwitch(false); mvControlling->ConverterSwitch(false); - if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) + if (mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) { mvControlling->PantFront(false); mvControlling->PantRear(false); @@ -2472,15 +2474,15 @@ bool TController::ReleaseEngine() { // jeśli się zatrzymał iEngineActive = 0; eStopReason = stopSleep; // stoimy z powodu wyłączenia - eAction = actSleep; //śpi (wygaszony) + eAction = TAction::actSleep; //śpi (wygaszony) if (AIControllFlag) { - if( ( mvControlling->EngineType == DieselElectric ) - || ( mvControlling->EngineType == DieselEngine ) ) { + if( ( mvControlling->EngineType == TEngineType::DieselElectric ) + || ( mvControlling->EngineType == TEngineType::DieselEngine ) ) { // heating/cooling subsystem mvControlling->WaterHeaterSwitch( false ); // optionally turn off the water pump as well - if( mvControlling->WaterPump.start_type != start::battery ) { + if( mvControlling->WaterPump.start_type != start_t::battery ) { mvControlling->WaterPumpSwitch( false ); } // fuel and oil subsystems @@ -2502,8 +2504,8 @@ bool TController::IncBrake() { // zwiększenie hamowania bool OK = false; switch( mvOccupied->BrakeSystem ) { - case Individual: { - if( mvOccupied->LocalBrake == ManualBrake ) { + case TBrakeSystem::Individual: { + if( mvOccupied->LocalBrake == TLocalBrake::ManualBrake ) { OK = mvOccupied->IncManualBrakeLevel( 1 + static_cast( std::floor( 0.5 + std::fabs( AccDesired ) ) ) ); } else { @@ -2511,7 +2513,7 @@ bool TController::IncBrake() } break; } - case Pneumatic: { + case TBrakeSystem::Pneumatic: { // NOTE: can't perform just test whether connected vehicle == nullptr, due to virtual couplers formed with nearby vehicles bool standalone { true }; if( ( mvOccupied->TrainType == dt_ET41 ) @@ -2575,7 +2577,7 @@ bool TController::IncBrake() } pos_corr = pos_corr / fMass * 2.5; - if (mvOccupied->BrakeHandle == FV4a) + if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a) { pos_corr += mvOccupied->Handle->GetCP()*0.2; @@ -2619,9 +2621,9 @@ bool TController::IncBrake() } break; } - case ElectroPneumatic: { - if( mvOccupied->EngineType == ElectricInductionMotor ) { - if (mvOccupied->BrakeHandle == MHZ_EN57) { + case TBrakeSystem::ElectroPneumatic: { + if( mvOccupied->EngineType == TEngineType::ElectricInductionMotor ) { + if (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57) { if (mvOccupied->BrakeCtrlPos < mvOccupied->Handle->GetPos(bh_FB)) OK = mvOccupied->BrakeLevelAdd(1.0); } @@ -2650,13 +2652,13 @@ bool TController::DecBrake() double deltaAcc = 0; switch (mvOccupied->BrakeSystem) { - case Individual: - if (mvOccupied->LocalBrake == ManualBrake) + case TBrakeSystem::Individual: + if (mvOccupied->LocalBrake == TLocalBrake::ManualBrake) OK = mvOccupied->DecManualBrakeLevel(1 + floor(0.5 + fabs(AccDesired))); else OK = mvOccupied->DecLocalBrakeLevel(1 + floor(0.5 + fabs(AccDesired))); break; - case Pneumatic: + case TBrakeSystem::Pneumatic: deltaAcc = -AccDesired*BrakeAccFactor() - (fBrake_a0[0] + 4 * (mvOccupied->BrakeCtrlPosR-1.0)*fBrake_a1[0]); if (deltaAcc < 0) { @@ -2670,13 +2672,13 @@ bool TController::DecBrake() } } if (!OK) - OK = mvOccupied->DecLocalBrakeLevel(2); + OK = mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); if (mvOccupied->PipePress < 3.0) Need_BrakeRelease = true; break; - case ElectroPneumatic: - if (mvOccupied->EngineType == ElectricInductionMotor) { - if (mvOccupied->BrakeHandle == MHZ_EN57) { + case TBrakeSystem::ElectroPneumatic: + if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor) { + if (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57) { if (mvOccupied->BrakeCtrlPos > mvOccupied->Handle->GetPos(bh_RP)) OK = mvOccupied->BrakeLevelAdd(-1.0); } @@ -2694,7 +2696,7 @@ bool TController::DecBrake() else OK = false; if (!OK) - OK = mvOccupied->DecLocalBrakeLevel(2); + OK = mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); break; } return OK; @@ -2724,12 +2726,12 @@ bool TController::IncSpeed() return false; // jak poślizg, to nie przyspieszamy switch (mvOccupied->EngineType) { - case None: // McZapkie-041003: wagon sterowniczy + case TEngineType::None: // McZapkie-041003: wagon sterowniczy if (mvControlling->MainCtrlPosNo > 0) // jeśli ma czym kręcić iDrivigFlags |= moveIncSpeed; // ustawienie flagi jazdy return false; - case ElectricSeriesMotor: - if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) // jeśli pantografujący + case TEngineType::ElectricSeriesMotor: + if (mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // jeśli pantografujący { if (fOverhead2 >= 0.0) // a jazda bezprądowa ustawiana eventami (albo opuszczenie) return false; // to nici z ruszania @@ -2811,8 +2813,8 @@ bool TController::IncSpeed() } mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania break; - case Dumb: - case DieselElectric: + case TEngineType::Dumb: + case TEngineType::DieselElectric: if (!mvControlling->FuseFlag) if (Ready || (iDrivigFlags & movePress)) //{(BrakePress<=0.01*MaxBrakePress)} { @@ -2821,7 +2823,7 @@ bool TController::IncSpeed() OK = mvControlling->IncScndCtrl(1); } break; - case ElectricInductionMotor: + case TEngineType::ElectricInductionMotor: if (!mvControlling->FuseFlag) if (Ready || (iDrivigFlags & movePress) || (mvOccupied->ShuntMode)) //{(BrakePress<=0.01*MaxBrakePress)} { @@ -2837,7 +2839,7 @@ bool TController::IncSpeed() } break; - case WheelsDriven: + case TEngineType::WheelsDriven: if (!mvControlling->CabNo) mvControlling->CabActivisation(); if (sin(mvControlling->eAngle) > 0) @@ -2845,7 +2847,7 @@ bool TController::IncSpeed() else mvControlling->DecMainCtrl(3 + 3 * floor(0.5 + fabs(AccDesired))); break; - case DieselEngine: + case TEngineType::DieselEngine: if (mvControlling->ShuntModeAllow) { // dla 2Ls150 można zmienić tryb pracy, jeśli jest w liniowym i nie daje rady (wymaga zerowania kierunku) // mvControlling->ShuntMode=(OrderList[OrderPos]&Shunt)||(fMass>224000.0); @@ -2874,29 +2876,29 @@ bool TController::DecSpeed(bool force) bool OK = false; // domyślnie false, aby wyszło z pętli while switch (mvOccupied->EngineType) { - case None: // McZapkie-041003: wagon sterowniczy + case TEngineType::None: // McZapkie-041003: wagon sterowniczy iDrivigFlags &= ~moveIncSpeed; // usunięcie flagi jazdy if (force) // przy aktywacji kabiny jest potrzeba natychmiastowego wyzerowania if (mvControlling->MainCtrlPosNo > 0) // McZapkie-041003: wagon sterowniczy, np. EZT mvControlling->DecMainCtrl(1 + (mvControlling->MainCtrlPos > 2 ? 1 : 0)); mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania return false; - case ElectricSeriesMotor: + case TEngineType::ElectricSeriesMotor: OK = mvControlling->DecScndCtrl(2); // najpierw bocznik na zero if (!OK) OK = mvControlling->DecMainCtrl(1 + (mvControlling->MainCtrlPos > 2 ? 1 : 0)); mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania break; - case Dumb: - case DieselElectric: + case TEngineType::Dumb: + case TEngineType::DieselElectric: OK = mvControlling->DecScndCtrl(2); if (!OK) OK = mvControlling->DecMainCtrl(2 + (mvControlling->MainCtrlPos / 2)); break; - case ElectricInductionMotor: + case TEngineType::ElectricInductionMotor: OK = mvControlling->DecMainCtrl(1); break; - case WheelsDriven: + case TEngineType::WheelsDriven: if (!mvControlling->CabNo) mvControlling->CabActivisation(); if (sin(mvControlling->eAngle) < 0) @@ -2904,7 +2906,7 @@ bool TController::DecSpeed(bool force) else mvControlling->DecMainCtrl(3 + 3 * floor(0.5 + fabs(AccDesired))); break; - case DieselEngine: + case TEngineType::DieselEngine: if ((mvControlling->Vel > mvControlling->dizel_minVelfullengage)) { if (mvControlling->RList[mvControlling->MainCtrlPos].Mn > 0) @@ -2926,7 +2928,7 @@ void TController::SpeedSet() // ma dokręcać do bezoporowych i zdejmować pozycje w przypadku przekroczenia prądu switch (mvOccupied->EngineType) { - case None: // McZapkie-041003: wagon sterowniczy + case TEngineType::None: // McZapkie-041003: wagon sterowniczy if (mvControlling->MainCtrlPosNo > 0) { // jeśli ma czym kręcić // TODO: sprawdzanie innego czlonu //if (!FuseFlagCheck()) @@ -2991,7 +2993,7 @@ void TController::SpeedSet() } } break; - case ElectricSeriesMotor: + case TEngineType::ElectricSeriesMotor: if( ( false == mvControlling->StLinFlag ) && ( false == mvControlling->DelayCtrlFlag ) ) { // styczniki liniowe rozłączone yBARC @@ -3061,15 +3063,15 @@ void TController::SpeedSet() // bezoporowej } break; - case Dumb: - case DieselElectric: - case ElectricInductionMotor: + case TEngineType::Dumb: + case TEngineType::DieselElectric: + case TEngineType::ElectricInductionMotor: break; // WheelsDriven : // begin // OK:=False; // end; - case DieselEngine: + case TEngineType::DieselEngine: // Ra 2014-06: "automatyczna" skrzynia biegów... if (!mvControlling->MotorParam[mvControlling->ScndCtrlPos].AutoSwitch) // gdy biegi ręczne if ((mvControlling->ShuntMode ? mvControlling->AnPos : 1.0) * mvControlling->Vel > @@ -3126,7 +3128,7 @@ void TController::Doors( bool const Open, int const Side ) { // wagony muszą mieć baterię załączoną do otwarcia drzwi... vehicle->MoverParameters->BatterySwitch( true ); // otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza - if( vehicle->MoverParameters->DoorOpenCtrl != control::passenger ) { + if( vehicle->MoverParameters->DoorOpenCtrl != control_t::passenger ) { // if the door are controlled by the driver, we let the user operate them... if( true == AIControllFlag ) { // ...unless this user is an ai @@ -3135,9 +3137,9 @@ void TController::Doors( bool const Open, int const Side ) { auto const lewe = ( vehicle->DirectionGet() > 0 ) ? 1 : 2; auto const prawe = 3 - lewe; if( Side & lewe ) - vehicle->MoverParameters->DoorLeft( true, range::local ); + vehicle->MoverParameters->DoorLeft( true, range_t::local ); if( Side & prawe ) - vehicle->MoverParameters->DoorRight( true, range::local ); + vehicle->MoverParameters->DoorRight( true, range_t::local ); } } // pojazd podłączony z tyłu (patrząc od czoła) @@ -3167,9 +3169,9 @@ void TController::Doors( bool const Open, int const Side ) { auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu while( vehicle != nullptr ) { // zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza - if( vehicle->MoverParameters->DoorCloseCtrl != control::autonomous ) { - vehicle->MoverParameters->DoorLeft( false, range::local ); // w lokomotywie można by nie zamykać... - vehicle->MoverParameters->DoorRight( false, range::local ); + if( vehicle->MoverParameters->DoorCloseCtrl != control_t::autonomous ) { + vehicle->MoverParameters->DoorLeft( false, range_t::local ); // w lokomotywie można by nie zamykać... + vehicle->MoverParameters->DoorRight( false, range_t::local ); } vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła) } @@ -3623,8 +3625,8 @@ void TController::PhysicsLog() << mvControlling->Im << " " << int(mvControlling->MainCtrlPos) << " " << int(mvControlling->ScndCtrlPos) << " " - << int(mvOccupied->BrakeCtrlPos) << " " - << int(mvOccupied->LocalBrakePos) << " " + << mvOccupied->fBrakeCtrlPos << " " + << mvOccupied->LocalBrakePosA << " " << int(mvControlling->ActiveDir) << " " << ( mvOccupied->CommandIn.Command.empty() ? "none" : mvOccupied->CommandIn.Command.c_str() ) << " " << mvOccupied->CommandIn.Value1 << " " @@ -3750,14 +3752,14 @@ TController::UpdateSituation(double dt) { auto const *vehicle { p->MoverParameters }; - if( ( vehicle->EngineType == DieselEngine ) - || ( vehicle->EngineType == DieselElectric ) ) { + if( ( vehicle->EngineType == TEngineType::DieselEngine ) + || ( vehicle->EngineType == TEngineType::DieselElectric ) ) { Ready = ( ( vehicle->Vel > 0.5 ) // already moving || ( false == vehicle->Mains ) // deadweight vehicle || ( vehicle->enrot > 0.8 * ( - vehicle->EngineType == DieselEngine ? + vehicle->EngineType == TEngineType::DieselEngine ? vehicle->dizel_nmin : vehicle->DElist[ 0 ].RPM / 60.0 ) ) ); } @@ -3768,7 +3770,7 @@ TController::UpdateSituation(double dt) { // for human-controlled vehicles with no door control and dynamic brake auto-activating with door open if( ( false == AIControllFlag ) && ( iDrivigFlags & moveDoorOpened ) - && ( mvOccupied->DoorCloseCtrl != control::driver ) + && ( mvOccupied->DoorCloseCtrl != control_t::driver ) && ( mvControlling->MainCtrlPos > 0 ) ) { Doors( false ); } @@ -3788,7 +3790,7 @@ TController::UpdateSituation(double dt) { } } - if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) { + if (mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) { if( mvOccupied->ScndPipePress > 4.3 ) { // gdy główna sprężarka bezpiecznie nabije ciśnienie to można przestawić kurek na zasilanie pantografów z głównej pneumatyki @@ -3825,7 +3827,7 @@ TController::UpdateSituation(double dt) { */ } - if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) { + if (mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) { if( mvOccupied->Vel > 0.05 ) { // is moving @@ -3871,7 +3873,7 @@ TController::UpdateSituation(double dt) { // if the power station is heavily burdened try to reduce the load switch( mvControlling->EngineType ) { - case ElectricSeriesMotor: { + case TEngineType::ElectricSeriesMotor: { if( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) { // limit yourself to series mode if( mvControlling->ScndCtrlPos ) { @@ -4166,7 +4168,7 @@ TController::UpdateSituation(double dt) { // 3. faza odczepiania. SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2 if ((mvControlling->MainCtrlPos > 0) || - (mvOccupied->BrakeSystem == ElectroPneumatic)) // jeśli jazda + (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic)) // jeśli jazda { WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); TDynamicObject *p = @@ -4221,7 +4223,7 @@ TController::UpdateSituation(double dt) { // powino zostać wyłączone) // WriteLog("Zahamowanie składu"); mvOccupied->BrakeLevelSet( - mvOccupied->BrakeSystem == ElectroPneumatic ? + mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ? 1 : 3 ); double p = mvOccupied->BrakePressureActual.PipePressureVal; @@ -4230,18 +4232,18 @@ TController::UpdateSituation(double dt) { // TODO: zabezpieczenie przed dziwnymi CHK do czasu wyjaśnienia sensu 0 oraz -1 w tym miejscu p = 3.9; } - if (mvOccupied->BrakeSystem == ElectroPneumatic ? + if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ? mvOccupied->BrakePress > 2 : mvOccupied->PipePress < p + 0.1) { // jeśli w miarę został zahamowany (ciśnienie mniejsze niż podane na // pozycji 3, zwyle 0.37) - if (mvOccupied->BrakeSystem == ElectroPneumatic) + if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic) mvOccupied->BrakeLevelSet(0); // wyłączenie EP, gdy wystarczy (może // nie być potrzebne, bo na początku // jest) WriteLog("Luzowanie lokomotywy i zmiana kierunku"); mvOccupied->BrakeReleaser(1); // wyluzuj lokomotywę; a ST45? - mvOccupied->DecLocalBrakeLevel(10); // zwolnienie hamulca + mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca iDrivigFlags |= movePress; // następnie będzie dociskanie DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie) CheckVehicles(); // od razu zmienić światła (zgasić) - bez tego się nie odczepi @@ -4510,7 +4512,7 @@ TController::UpdateSituation(double dt) { switch (comm) { // ustawienie VelSignal - trochę proteza = do przemyślenia - case cm_Ready: // W4 zezwolił na jazdę + case TCommandType::cm_Ready: // W4 zezwolił na jazdę // ewentualne doskanowanie trasy za W4, który zezwolił na jazdę TableCheck( routescanrange); TableUpdate(VelDesired, ActualProximityDist, VelNext, AccDesired); // aktualizacja po skanowaniu @@ -4518,21 +4520,21 @@ TController::UpdateSituation(double dt) { break; // ale jak coś z przodu zamyka, to ma stać if (iDrivigFlags & moveStopCloser) VelSignal = -1.0; // ma czekać na sygnał z sygnalizatora! - case cm_SetVelocity: // od wersji 357 semafor nie budzi wyłączonej lokomotywy + case TCommandType::cm_SetVelocity: // od wersji 357 semafor nie budzi wyłączonej lokomotywy if (!(OrderList[OrderPos] & ~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders if (fabs(VelSignal) >= 1.0) // 0.1 nie wysyła się do samochodow, bo potem nie ruszą PutCommand("SetVelocity", VelSignal, VelNext, nullptr); // komenda robi dodatkowe operacje break; - case cm_ShuntVelocity: // od wersji 357 Tm nie budzi wyłączonej lokomotywy + case TCommandType::cm_ShuntVelocity: // od wersji 357 Tm nie budzi wyłączonej lokomotywy if (!(OrderList[OrderPos] & ~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders PutCommand("ShuntVelocity", VelSignal, VelNext, nullptr); else if (iCoupler) // jeśli jedzie w celu połączenia SetVelocity(VelSignal, VelNext); break; - case cm_Command: // komenda z komórki + case TCommandType::cm_Command: // komenda z komórki if( !( OrderList[ OrderPos ] & ~( Obey_train | Shunt ) ) ) { // jedzie w dowolnym trybie albo Wait_for_orders if( mvOccupied->Vel < 0.1 ) { @@ -4555,12 +4557,12 @@ TController::UpdateSituation(double dt) { if( ( OrderList[ OrderPos ] & Connect ) ? ( pVehicles[ 0 ]->fTrackBlock > 2000 || pVehicles[ 0 ]->fTrackBlock > FirstSemaphorDist ) : true ) { - if( ( comm = BackwardScan() ) != cm_Unknown ) { + if( ( comm = BackwardScan() ) != TCommandType::cm_Unknown ) { // jeśli w drugą można jechać // należy sprawdzać odległość od znalezionego sygnalizatora, // aby w przypadku prędkości 0.1 wyciągnąć najpierw skład za sygnalizator // i dopiero wtedy zmienić kierunek jazdy, oczekując podania prędkości >0.5 - if( comm == cm_Command ) { + if( comm == TCommandType::cm_Command ) { // jeśli komenda Shunt to ją odbierz bez przemieszczania się (np. odczep wagony po dopchnięciu do końca toru) iDrivigFlags |= moveStopHere; } @@ -5042,9 +5044,9 @@ TController::UpdateSituation(double dt) { PrepareEngine(); // próba ponownego załączenia } // włączanie bezpiecznika - if ((mvControlling->EngineType == ElectricSeriesMotor) || + if ((mvControlling->EngineType == TEngineType::ElectricSeriesMotor) || (mvControlling->TrainType & dt_EZT) || - (mvControlling->EngineType == DieselElectric)) + (mvControlling->EngineType == TEngineType::DieselElectric)) if (mvControlling->FuseFlag || Need_TryAgain) { Need_TryAgain = false; // true, jeśli druga pozycja w elektryku nie załapała @@ -5077,8 +5079,8 @@ TController::UpdateSituation(double dt) { ReactionTime = 0.25; } } - if (mvOccupied->BrakeSystem == Pneumatic) // napełnianie uderzeniowe - if (mvOccupied->BrakeHandle == FV4a) + if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic) // napełnianie uderzeniowe + if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a) { if( mvOccupied->BrakeCtrlPos == -2 ) { mvOccupied->BrakeLevelSet( 0 ); @@ -5280,7 +5282,7 @@ TController::UpdateSituation(double dt) { if( ( VelDesired == 0.0 ) && ( vel > VelDesired ) && ( ActualProximityDist <= fMinProximityDist ) - && ( mvOccupied->LocalBrakePos == 0 ) ) { + && ( mvOccupied->LocalBrakePosA < 0.01 ) ) { IncBrake(); } } @@ -5333,8 +5335,8 @@ TController::UpdateHeating() { switch( mvControlling->EngineType ) { - case DieselElectric: - case DieselEngine: { + case TEngineType::DieselElectric: + case TEngineType::DieselEngine: { auto const &heat { mvControlling->dizel_heat }; @@ -5366,7 +5368,7 @@ TController::UpdateHeating() { mvControlling->WaterHeaterSwitch( false ); mvControlling->WaterHeaterBreakerSwitch( false ); // optionally turn off the water pump as well - if( mvControlling->WaterPump.start_type != start::battery ) { + if( mvControlling->WaterPump.start_type != start_t::battery ) { mvControlling->WaterPumpSwitch( false ); mvControlling->WaterPumpBreakerSwitch( false ); } @@ -5736,13 +5738,13 @@ TCommandType TController::BackwardScan() // zwraca true, jeśli należy odwrócić kierunek jazdy pojazdu if( ( OrderList[ OrderPos ] & ~( Shunt | Connect ) ) ) { // skanowanie sygnałów tylko gdy jedzie w trybie manewrowym albo czeka na rozkazy - return cm_Unknown; + return TCommandType::cm_Unknown; } // kierunek jazdy względem sprzęgów pojazdu na czele int const startdir = -pVehicles[0]->DirectionGet(); if( startdir == 0 ) { // jeśli kabina i kierunek nie jest określony nie robimy nic - return cm_Unknown; + return TCommandType::cm_Unknown; } // szukamy od pierwszej osi w wybranym kierunku double scandir = startdir * pVehicles[0]->RaDirectionGet(); @@ -5757,7 +5759,7 @@ TCommandType TController::BackwardScan() auto const dir = startdir * pVehicles[0]->VectorFront(); // wektor w kierunku jazdy/szukania if( !scantrack ) { // jeśli wstecz wykryto koniec toru to raczej nic się nie da w takiej sytuacji zrobić - return cm_Unknown; + return TCommandType::cm_Unknown; } else { // a jeśli są dalej tory @@ -5787,7 +5789,7 @@ TCommandType TController::BackwardScan() #if LOGBACKSCAN WriteLog(edir + " - ignored as not passed yet"); #endif - return cm_Unknown; // nic + return TCommandType::cm_Unknown; // nic } vmechmax = e->ValueGet(1); // prędkość przy tym semaforze // przeliczamy odległość od semafora - potrzebne by były współrzędne początku składu @@ -5797,7 +5799,7 @@ TCommandType TController::BackwardScan() scandist = 0; } bool move = false; // czy AI w trybie manewerowym ma dociągnąć pod S1 - if( e->Command() == cm_SetVelocity ) { + if( e->Command() == TCommandType::cm_SetVelocity ) { if( ( vmechmax == 0.0 ) ? ( OrderCurrentGet() & ( Shunt | Connect ) ) : ( OrderCurrentGet() & Connect ) ) { // przy podczepianiu ignorować wyjazd? @@ -5816,8 +5818,8 @@ TCommandType TController::BackwardScan() // SetProximityVelocity(scandist,vmechmax,&sl); return ( vmechmax > 0 ? - cm_SetVelocity : - cm_Unknown ); + TCommandType::cm_SetVelocity : + TCommandType::cm_Unknown ); } else { // ustawiamy prędkość tylko wtedy, gdy ma ruszyć, stanąć albo ma stać @@ -5833,15 +5835,15 @@ TCommandType TController::BackwardScan() #endif return ( vmechmax > 0 ? - cm_SetVelocity : - cm_Unknown ); + TCommandType::cm_SetVelocity : + TCommandType::cm_Unknown ); } } } if (OrderCurrentGet() ? OrderCurrentGet() & (Shunt | Connect) : true) // w Wait_for_orders też widzi tarcze { // reakcja AI w trybie manewrowym dodatkowo na sygnały manewrowe - if (move ? true : e->Command() == cm_ShuntVelocity) + if (move ? true : e->Command() == TCommandType::cm_ShuntVelocity) { // jeśli powyżej było SetVelocity 0 0, to dociągamy pod S1 if ((scandist > fMinProximityDist) ? (mvOccupied->Vel > 0.0) || (vmechmax == 0.0) : @@ -5859,8 +5861,8 @@ TCommandType TController::BackwardScan() #endif // SetProximityVelocity(scandist,vmechmax,&sl); return (iDrivigFlags & moveTrackEnd) ? - cm_ChangeDirection : - cm_Unknown; // jeśli jedzie na W5 albo koniec toru, + TCommandType::cm_ChangeDirection : + TCommandType::cm_Unknown; // jeśli jedzie na W5 albo koniec toru, // to można zmienić kierunek } } @@ -5878,8 +5880,8 @@ TCommandType TController::BackwardScan() #endif return ( vmechmax > 0 ? - cm_ShuntVelocity : - cm_Unknown ); + TCommandType::cm_ShuntVelocity : + TCommandType::cm_Unknown ); } } if ((vmechmax != 0.0) && (scandist < 100.0)) { @@ -5890,19 +5892,19 @@ TCommandType TController::BackwardScan() #endif return ( vmechmax > 0 ? - cm_ShuntVelocity : - cm_Unknown ); + TCommandType::cm_ShuntVelocity : + TCommandType::cm_Unknown ); } } // if (move?... } // if (OrderCurrentGet()==Shunt) if (!e->bEnabled) // jeśli skanowany if (e->StopCommand()) // a podłączona komórka ma komendę - return cm_Command; // to też się obrócić + return TCommandType::cm_Command; // to też się obrócić } // if (e->Type==tp_GetValues) } // if (e) } // if (scantrack) } // if (scandir!=0.0) - return cm_Unknown; // nic + return TCommandType::cm_Unknown; // nic }; std::string TController::NextStop() diff --git a/Driver.h b/Driver.h index 865f933c..63d15cf5 100644 --- a/Driver.h +++ b/Driver.h @@ -73,7 +73,7 @@ enum TStopReason stopError // z powodu błędu w obliczeniu drogi hamowania }; -enum TAction +enum class TAction : int { // przechowanie aktualnego stanu AI od poprzedniego przebłysku świadomości actUnknown, // stan nieznany (domyślny na początku) actPantUp, // podnieś pantograf (info dla użytkownika) @@ -223,7 +223,7 @@ private: double LastReactionTime = 0.0; double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations - TAction eAction { actUnknown }; // aktualny stan + TAction eAction { TAction::actUnknown }; // aktualny stan public: inline TAction GetAction() { diff --git a/DynObj.cpp b/DynObj.cpp index 4b15f23b..a6d23b51 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -969,7 +969,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) } if( ( Mechanik != nullptr ) - && ( Mechanik->GetAction() != actSleep ) ) { + && ( Mechanik->GetAction() != TAction::actSleep ) ) { // rysowanie figurki mechanika btMechanik1.Turn( MoverParameters->ActiveCab > 0 ); btMechanik2.Turn( MoverParameters->ActiveCab < 0 ); @@ -1829,7 +1829,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424" return 0.0; // zerowa długość to brak pojazdu } // ustawienie pozycji hamulca - MoverParameters->LocalBrakePos = 0; + MoverParameters->LocalBrakePosA = 0.0; if (driveractive) { if (Cab == 0) @@ -2300,7 +2300,7 @@ TDynamicObject::create_controller( std::string const Type, bool const Trainset ) if( asName == Global.asHumanCtrlVehicle ) { // jeśli pojazd wybrany do prowadzenia - if( MoverParameters->EngineType != Dumb ) { + if( MoverParameters->EngineType != TEngineType::Dumb ) { // wsadzamy tam sterującego Controller = Humandriver; } @@ -2577,16 +2577,16 @@ bool TDynamicObject::UpdateForce(double dt, double dt1, bool FullVer) // initiates load change by specified amounts, with a platform on specified side void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platform ) { - if( ( MoverParameters->DoorOpenCtrl == control::passenger ) - || ( MoverParameters->DoorOpenCtrl == control::mixed ) ) { + if( ( MoverParameters->DoorOpenCtrl == control_t::passenger ) + || ( MoverParameters->DoorOpenCtrl == control_t::mixed ) ) { // jeśli jedzie do tyłu, to drzwi otwiera odwrotnie auto const lewe = ( DirectionGet() > 0 ) ? 1 : 2; auto const prawe = 3 - lewe; if( Platform & lewe ) { - MoverParameters->DoorLeft( true, range::local ); + MoverParameters->DoorLeft( true, range_t::local ); } if( Platform & prawe ) { - MoverParameters->DoorRight( true, range::local ); + MoverParameters->DoorRight( true, range_t::local ); } } m_exchange.unload_count += Disembark; @@ -2646,18 +2646,18 @@ void TDynamicObject::update_exchange( double const Deltatime ) { MoverParameters->LoadStatus = 0; // if the exchange is completed (or canceled) close the door, if applicable - if( ( MoverParameters->DoorCloseCtrl == control::passenger ) - || ( MoverParameters->DoorCloseCtrl == control::mixed ) ) { + if( ( MoverParameters->DoorCloseCtrl == control_t::passenger ) + || ( MoverParameters->DoorCloseCtrl == control_t::mixed ) ) { if( ( MoverParameters->Vel > 2.0 ) || ( Random() < ( // remotely controlled door are more likely to be left open - MoverParameters->DoorCloseCtrl == control::passenger ? + MoverParameters->DoorCloseCtrl == control_t::passenger ? 0.75 : 0.50 ) ) ) { - MoverParameters->DoorLeft( false, range::local ); - MoverParameters->DoorRight( false, range::local ); + MoverParameters->DoorLeft( false, range_t::local ); + MoverParameters->DoorRight( false, range_t::local ); } } } @@ -2795,7 +2795,7 @@ bool TDynamicObject::Update(double dt, double dt1) return false; // a normalnie powinny mieć bEnabled==false // McZapkie-260202 - if ((MoverParameters->EnginePowerSource.SourceType == CurrentCollector) && + if ((MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) && (MoverParameters->Power > 1.0)) // aby rozrządczy nie opuszczał silnikowemu /* if ((MechInside) || (MoverParameters->TrainType == dt_EZT)) @@ -2818,7 +2818,7 @@ bool TDynamicObject::Update(double dt, double dt1) // pressure switch safety measure -- open the line breaker, unless there's alternate source of traction voltage if( MoverParameters->GetTrainsetVoltage() < 0.5 * MoverParameters->EnginePowerSource.MaxVoltage ) { // TODO: check whether line breaker should be open EMU-wide - MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) ); + MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? range_t::unit : range_t::local ) ); } } else { @@ -2826,7 +2826,7 @@ bool TDynamicObject::Update(double dt, double dt1) // and prevents their activation until pressure switch is set again MoverParameters->PantPressLockActive = true; // TODO: separate 'heating allowed' from actual heating flag, so we can disable it here without messing up heating toggle - MoverParameters->ConverterSwitch( false, range::unit ); + MoverParameters->ConverterSwitch( false, range_t::unit ); } // mark the pressure switch as spent MoverParameters->PantPressSwitchActive = false; @@ -2924,7 +2924,7 @@ bool TDynamicObject::Update(double dt, double dt1) // znane napięcia // TTractionParam tmpTraction; // tmpTraction.TractionVoltage=0; - if (MoverParameters->EnginePowerSource.SourceType == CurrentCollector) + if (MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) { // dla EZT tylko silnikowy // if (Global.bLiveTraction) { // Ra 2013-12: to niżej jest chyba trochę bez sensu @@ -2989,7 +2989,7 @@ bool TDynamicObject::Update(double dt, double dt1) { // Ra 2F3F: do Driver.cpp to przenieść? MoverParameters->EqvtPipePress = GetEPP(); // srednie cisnienie w PG if( ( Mechanik->Primary() ) - && ( MoverParameters->EngineType == ElectricInductionMotor ) ) { + && ( MoverParameters->EngineType == TEngineType::ElectricInductionMotor ) ) { // jesli glowny i z asynchronami, to niech steruje hamulcem lacznie dla calego pociagu/ezt auto const kier = (DirectionGet() * MoverParameters->ActiveCab > 0); auto FED { 0.0 }; @@ -3068,6 +3068,9 @@ bool TDynamicObject::Update(double dt, double dt1) (MoverParameters->LocalBrakeRatio() < 0.01); } auto Fzad = amax * MoverParameters->LocalBrakeRatio() * masa; + if ((MoverParameters->BrakeCtrlPos == MoverParameters->Handle->GetPos(bh_EB)) + && (MoverParameters->eimc[eimc_p_abed] < 0.001)) + Fzad = amax * masa; //pętla bezpieczeństwa - pełne służbowe if ((MoverParameters->ScndS) && (MoverParameters->Vel > MoverParameters->eimc[eimc_p_Vh1]) && (FmaxED > 0)) { @@ -3080,9 +3083,10 @@ bool TDynamicObject::Update(double dt, double dt1) } if ((Fzad > 1) && (!MEDLogFile.is_open()) && (MoverParameters->Vel > 1)) { - MEDLogFile.open(std::string("MEDLOGS/" + MoverParameters->Name + "_" + to_string(++MEDLogCount) + ".csv"), - std::ios::in | std::ios::out | std::ios::trunc); - MEDLogFile << std::string("t\tVel\tMasa\tOsie\tFmaxPN\tFmaxED\tFfulED\tFrED\tFzad\tFzadED\tFzadPN").c_str(); + MEDLogFile.open( + "MEDLOGS/" + MoverParameters->Name + "_" + to_string( ++MEDLogCount ) + ".csv", + std::ios::in | std::ios::out | std::ios::trunc ); + MEDLogFile << "t\tVel\tMasa\tOsie\tFmaxPN\tFmaxED\tFfulED\tFrED\tFzad\tFzadED\tFzadPN"; for(int k=1;k<=np;k++) { MEDLogFile << "\tBP" << k; @@ -3093,11 +3097,14 @@ bool TDynamicObject::Update(double dt, double dt1) MEDLogTime = 0; } auto FzadED { 0.0 }; - if( ( MoverParameters->EpFuse && (MoverParameters->BrakeHandle != MHZ_EN57)) - || ( ( MoverParameters->BrakeHandle == MHZ_EN57 ) + if( ( MoverParameters->EpFuse && (MoverParameters->BrakeHandle != TBrakeHandle::MHZ_EN57)) + || ( ( MoverParameters->BrakeHandle == TBrakeHandle::MHZ_EN57 ) && ( MoverParameters->BrakeOpModeFlag & bom_MED ) ) ) { FzadED = std::min( Fzad, FmaxED ); } + if ((MoverParameters->BrakeCtrlPos == MoverParameters->Handle->GetPos(bh_EB)) + && (MoverParameters->eimc[eimc_p_abed] < 0.001)) + FzadED = 0; //pętla bezpieczeństwa - bez ED auto const FzadPN = Fzad - FrED; //np = 0; // BUG: likely memory leak, allocation per inner loop, deleted only once outside @@ -3275,10 +3282,10 @@ bool TDynamicObject::Update(double dt, double dt1) // NOTE: disabled on account of multi-unit setups, where the unmanned unit wouldn't be affected && ( Controller == Humandriver ) */ - && ( MoverParameters->EngineType != DieselEngine ) - && ( MoverParameters->EngineType != WheelsDriven ) ) + && ( MoverParameters->EngineType != TEngineType::DieselEngine ) + && ( MoverParameters->EngineType != TEngineType::WheelsDriven ) ) { // jeśli bateria wyłączona, a nie diesel ani drezyna reczna - if( MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) ) ) { + if( MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? range_t::unit : range_t::local ) ) ) { // wyłączyć zasilanie // NOTE: we turn off entire EMU, but only the affected unit for other multi-unit consists MoverParameters->EventFlag = true; @@ -3620,8 +3627,8 @@ bool TDynamicObject::Update(double dt, double dt1) } */ } - else if (MoverParameters->EnginePowerSource.SourceType == InternalSource) - if (MoverParameters->EnginePowerSource.PowerType == SteamPower) + else if (MoverParameters->EnginePowerSource.SourceType == TPowerSource::InternalSource) + if (MoverParameters->EnginePowerSource.PowerType == TPowerType::SteamPower) // if (smPatykird1[0]) { // Ra: animacja rozrządu parowozu, na razie nieoptymalizowane /* //Ra: tymczasowo wyłączone ze względu na porządkowanie animacji @@ -3981,7 +3988,7 @@ void TDynamicObject::RenderSounds() { // NBMX dzwiek przetwornicy if( MoverParameters->ConverterFlag ) { frequency = ( - MoverParameters->EngineType == ElectricSeriesMotor ? + MoverParameters->EngineType == TEngineType::ElectricSeriesMotor ? ( MoverParameters->RunningTraction.TractionVoltage / MoverParameters->NominalVoltage ) * MoverParameters->RList[ MoverParameters->RlistSize ].Mn : 1.0 ); frequency = sConverter.m_frequencyoffset + sConverter.m_frequencyfactor * frequency; @@ -4613,7 +4620,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, } if( !MoverParameters->LoadAccepted.empty() ) { - if( ( MoverParameters->EnginePowerSource.SourceType == CurrentCollector ) + if( ( MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) && ( asLoadName == "pantstate" ) ) { // wartość niby "pantstate" - nazwa dla formalności, ważna jest ilość if( MoverParameters->Load == 1 ) { @@ -5073,7 +5080,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, (k) */ MoverParameters->EnginePowerSource.PowerType = - SteamPower; // Ra: po chamsku, ale z CHK nie działa + TPowerType::SteamPower; // Ra: po chamsku, ale z CHK nie działa } else if( token == "animreturnprefix:" ) { @@ -5269,8 +5276,8 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, m_powertrainsounds.engine.owner( this ); auto const amplitudedivisor = static_cast( ( - MoverParameters->EngineType == DieselEngine ? 1 : - MoverParameters->EngineType == DieselElectric ? 1 : + MoverParameters->EngineType == TEngineType::DieselEngine ? 1 : + MoverParameters->EngineType == TEngineType::DieselElectric ? 1 : MoverParameters->nmax * 60 + MoverParameters->Power * 3 ) ); m_powertrainsounds.engine.m_amplitudefactor /= amplitudedivisor; } @@ -6439,7 +6446,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub if( ( std::abs( Vehicle.enrot ) > 0.01 ) // McZapkie-280503: zeby dla dumb dzialal silnik na jalowych obrotach - || ( Vehicle.EngineType == Dumb ) ) { + || ( Vehicle.EngineType == TEngineType::Dumb ) ) { // frequency calculation auto const normalizer { ( @@ -6453,14 +6460,14 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub engine.m_frequencyoffset + engine.m_frequencyfactor * std::abs( Vehicle.enrot ) * normalizer; - if( Vehicle.EngineType == Dumb ) { + if( Vehicle.EngineType == TEngineType::Dumb ) { frequency -= 0.2 * Vehicle.EnginePower / ( 1 + Vehicle.Power * 1000 ); } // base volume calculation switch( Vehicle.EngineType ) { // TODO: check calculated values - case DieselElectric: { + case TEngineType::DieselElectric: { volume = engine.m_amplitudeoffset @@ -6469,7 +6476,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub + 0.75 * ( Vehicle.enrot * 60 ) / ( Vehicle.DElist[ Vehicle.MainCtrlPosNo ].RPM ) ); break; } - case DieselEngine: { + case TEngineType::DieselEngine: { if( Vehicle.enrot > 0.0 ) { volume = ( Vehicle.EnginePower > 0 ? @@ -6489,15 +6496,15 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub if( engine_volume >= 0.05 ) { auto enginerevvolume { 0.f }; - if( ( Vehicle.EngineType == DieselElectric ) - || ( Vehicle.EngineType == DieselEngine ) ) { + if( ( Vehicle.EngineType == TEngineType::DieselElectric ) + || ( Vehicle.EngineType == TEngineType::DieselEngine ) ) { // diesel engine revolutions increase; it can potentially decrease volume of base engine sound if( engine_revs_last != -1.f ) { // calculate potential recent increase of engine revolutions auto const revolutionsperminute { Vehicle.enrot * 60 }; auto const revolutionsdifference { revolutionsperminute - engine_revs_last }; auto const idlerevolutionsthreshold { 1.01 * ( - Vehicle.EngineType == DieselElectric ? + Vehicle.EngineType == TEngineType::DieselElectric ? Vehicle.DElist[ 0 ].RPM : Vehicle.dizel_nmin * 60 ) }; @@ -6624,13 +6631,13 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub // base volume calculation switch( Vehicle.EngineType ) { - case ElectricInductionMotor: { + case TEngineType::ElectricInductionMotor: { volume = motor.m_amplitudeoffset + motor.m_amplitudefactor * ( Vehicle.EnginePower + motorrevolutions * 2 ); break; } - case ElectricSeriesMotor: { + case TEngineType::ElectricSeriesMotor: { volume = motor.m_amplitudeoffset + motor.m_amplitudefactor * ( Vehicle.EnginePower / 1000 + motorrevolutions * 60.0 ); @@ -6644,7 +6651,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub } } - if( Vehicle.EngineType == ElectricSeriesMotor ) { + if( Vehicle.EngineType == TEngineType::ElectricSeriesMotor ) { // volume variation if( ( volume < 1.0 ) && ( Vehicle.EnginePower < 100 ) ) { @@ -6695,7 +6702,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub } } // inverter sounds - if( Vehicle.EngineType == ElectricInductionMotor ) { + if( Vehicle.EngineType == TEngineType::ElectricInductionMotor ) { if( Vehicle.InverterFrequency > 0.1 ) { volume = inverter.m_amplitudeoffset + inverter.m_amplitudefactor * std::sqrt( std::abs( Vehicle.dizel_fill ) ); @@ -6722,8 +6729,8 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub rsWentylator.stop(); } // radiator fan sounds - if( ( Vehicle.EngineType == DieselEngine ) - || ( Vehicle.EngineType == DieselElectric ) ) { + if( ( Vehicle.EngineType == TEngineType::DieselEngine ) + || ( Vehicle.EngineType == TEngineType::DieselElectric ) ) { if( Vehicle.dizel_heat.rpmw > 0.1 ) { // NOTE: fan speed tends to max out at ~100 rpm; by default we try to get pitch range of 0.5-1.5 and volume range of 0.5-1.0 @@ -6817,7 +6824,7 @@ vehicle_table::update( double Deltatime, int Iterationcount ) { for( auto *vehicle : m_items ) { if( false == vehicle->bEnabled ) { continue; } // Ra: zmienić warunek na sprawdzanie pantografów w jednej zmiennej: czy pantografy i czy podniesione - if( vehicle->MoverParameters->EnginePowerSource.SourceType == CurrentCollector ) { + if( vehicle->MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) { update_traction( vehicle ); } vehicle->MoverParameters->ComputeConstans(); @@ -6993,16 +7000,22 @@ vehicle_table::erase_disabled() { ++vehicleiter; } else { - if( vehicle->MyTrack != nullptr ) { - vehicle->MyTrack->RemoveDynamicObject( vehicle ); + if( ( vehicle->MyTrack != nullptr ) + && ( true == vehicle->MyTrack->RemoveDynamicObject( vehicle ) ) ) { + vehicle->MyTrack = nullptr; } // clear potential train binding Global.pWorld->TrainDelete( vehicle ); // remove potential entries in the light array simulation::Lights.remove( vehicle ); +/* // finally get rid of the vehicle and its record themselves + // BUG: deleting the vehicle leaves dangling pointers in event->Activator and potentially elsewhere + // TBD, TODO: either mark 'dead' vehicles with additional flag, or delete the references as well SafeDelete( vehicle ); vehicleiter = m_items.erase( vehicleiter ); +*/ + ++vehicleiter; // NOTE: instead of the erase in the disabled section } } // ...and call it a day diff --git a/DynObj.h b/DynObj.h index 30ad38c0..d378884c 100644 --- a/DynObj.h +++ b/DynObj.h @@ -158,7 +158,7 @@ struct material_data { class TDynamicObject { // klasa pojazdu - friend class opengl_renderer; + friend opengl_renderer; public: static bool bDynamicRemove; // moved from ground diff --git a/EU07.cpp b/EU07.cpp index 20a7757d..a5a9f2f3 100644 --- a/EU07.cpp +++ b/EU07.cpp @@ -7,8 +7,8 @@ obtain one at http://mozilla.org/MPL/2.0/. */ /* - MaSzyna EU07 locomotive simulator - Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others +MaSzyna EU07 locomotive simulator +Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others */ /* Authors: @@ -17,448 +17,31 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others */ #include "stdafx.h" -#include -#include -#include "World.h" -#include "simulation.h" -#include "Globals.h" -#include "Timer.h" +#include "application.h" #include "Logs.h" -#include "renderer.h" -#include "uilayer.h" -#include "audiorenderer.h" -#include "keyboardinput.h" -#include "mouseinput.h" -#include "gamepadinput.h" -#include "Console.h" -#include "uart.h" -#include "PyInt.h" -#include "World.h" -#include "MOVER.h" -#include "utilities.h" -#include "Timer.h" -#include "resource.h" -#include "uilayer.h" -#include "uart.h" -#include "motiontelemetry.h" - -#pragma comment (lib, "glu32.lib") -#pragma comment (lib, "dsound.lib") -#pragma comment (lib, "winmm.lib") -#pragma comment (lib, "setupapi.lib") -#pragma comment (lib, "dbghelp.lib") -#pragma comment (lib, "version.lib") +#include #ifdef _MSC_VER #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") #endif -TWorld World; -namespace input { - -keyboard_input Keyboard; -mouse_input Mouse; -gamepad_input Gamepad; -glm::dvec2 mouse_pickmodepos; // stores last mouse position in control picking mode -std::unique_ptr uart; -std::unique_ptr motiontelemetry; -} - -void screenshot_save_thread( char *img ) +int main( int argc, char *argv[] ) { - png_image png; - memset(&png, 0, sizeof(png_image)); - png.version = PNG_IMAGE_VERSION; - png.width = Global.iWindowWidth; - png.height = Global.iWindowHeight; - png.format = PNG_FORMAT_RGB; - - char datetime[64]; - time_t timer; - struct tm* tm_info; - time(&timer); - tm_info = localtime(&timer); - strftime(datetime, 64, "%Y-%m-%d_%H-%M-%S", tm_info); - - uint64_t perf; -#ifdef _WIN32 - QueryPerformanceCounter((LARGE_INTEGER*)&perf); -#elif __linux__ - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - perf = ts.tv_nsec; -#endif - - std::string filename = Global.screenshot_dir + "/" + std::string(datetime) + - "_" + std::to_string(perf) + ".png"; - - if (png_image_write_to_file(&png, filename.c_str(), 0, img, -Global.iWindowWidth * 3, nullptr) == 1) - WriteLog("saved " + filename + "."); - else - WriteLog("failed to save screenshot."); - - delete[] img; -} - -void make_screenshot() -{ - char *img = new char[Global.iWindowWidth * Global.iWindowHeight * 3]; - glReadPixels(0, 0, Global.iWindowWidth, Global.iWindowHeight, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)img); - - std::thread t(screenshot_save_thread, img); - t.detach(); -} - -void window_resize_callback(GLFWwindow *window, int w, int h) -{ - // NOTE: we have two variables which basically do the same thing as we don't have dynamic fullscreen toggle - // TBD, TODO: merge them? - Global.iWindowWidth = w; - Global.iWindowHeight = h; - Global.fDistanceFactor = std::max( 0.5f, h / 768.0f ); // not sure if this is really something we want to use - glViewport(0, 0, w, h); -} - -void cursor_pos_callback(GLFWwindow *window, double x, double y) -{ - if (!window) - return; - - input::Mouse.move( x, y ); - - if( !Global.ControlPicking ) { - glfwSetCursorPos( window, 0, 0 ); - } -} - -void mouse_button_callback( GLFWwindow* window, int button, int action, int mods ) { - - if( ( button == GLFW_MOUSE_BUTTON_LEFT ) - || ( button == GLFW_MOUSE_BUTTON_RIGHT ) ) { - // we don't care about other mouse buttons at the moment - input::Mouse.button( button, action ); - } -} - -void key_callback( GLFWwindow *window, int key, int scancode, int action, int mods ) { - - Global.shiftState = ( mods & GLFW_MOD_SHIFT ) ? true : false; - Global.ctrlState = ( mods & GLFW_MOD_CONTROL ) ? true : false; - - // give the ui first shot at the input processing... - if( true == UILayer.on_key( key, action ) ) { return; } - // ...if the input is left untouched, pass it on - input::Keyboard.key( key, action ); - - if( ( true == Global.InputMouse ) - && ( ( key == GLFW_KEY_LEFT_ALT ) - || ( key == GLFW_KEY_RIGHT_ALT ) ) ) { - // if the alt key was pressed toggle control picking mode and set matching cursor behaviour - if( action == GLFW_RELEASE ) { - - if( Global.ControlPicking ) { - // switch off - glfwGetCursorPos( window, &input::mouse_pickmodepos.x, &input::mouse_pickmodepos.y ); - glfwSetInputMode( window, GLFW_CURSOR, GLFW_CURSOR_DISABLED ); - glfwSetCursorPos( window, 0, 0 ); - } - else { - // enter picking mode - glfwSetInputMode( window, GLFW_CURSOR, GLFW_CURSOR_NORMAL ); - glfwSetCursorPos( window, input::mouse_pickmodepos.x, input::mouse_pickmodepos.y ); - } - // actually toggle the mode - Global.ControlPicking = !Global.ControlPicking; - } - } - - if( ( key == GLFW_KEY_LEFT_SHIFT ) - || ( key == GLFW_KEY_LEFT_CONTROL ) - || ( key == GLFW_KEY_LEFT_ALT ) - || ( key == GLFW_KEY_RIGHT_SHIFT ) - || ( key == GLFW_KEY_RIGHT_CONTROL ) - || ( key == GLFW_KEY_RIGHT_ALT ) ) { - // don't bother passing these - return; - } - - if( action == GLFW_PRESS || action == GLFW_REPEAT ) { - - World.OnKeyDown( key ); - - switch( key ) - { - case GLFW_KEY_PRINT_SCREEN: { - make_screenshot(); - break; - } - default: { break; } - } - } -} - -void focus_callback( GLFWwindow *window, int focus ) -{ - if( Global.bInactivePause ) // jeśli ma być pauzowanie okna w tle - if( focus ) - Global.iPause &= ~4; // odpauzowanie, gdy jest na pierwszym planie - else - Global.iPause |= 4; // włączenie pauzy, gdy nieaktywy -} - -void scroll_callback( GLFWwindow* window, double xoffset, double yoffset ) { - - if( Global.ctrlState ) { - // ctrl + scroll wheel adjusts fov in debug mode - Global.FieldOfView = clamp( static_cast(Global.FieldOfView - yoffset * 20.0 / Global.fFpsAverage), 15.0f, 75.0f ); - } -} - -#ifdef _WIN32 -extern "C" -{ - GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); -} - -LONG CALLBACK unhandled_handler(::EXCEPTION_POINTERS* e); -LRESULT APIENTRY WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -extern HWND Hwnd; -extern WNDPROC BaseWindowProc; -#endif - -int main(int argc, char *argv[]) -{ -#if defined(_MSC_VER) && defined (_DEBUG) - // memory leaks - _CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_LEAK_CHECK_DF ); - // floating point operation errors - auto state = _clearfp(); - state = _control87( 0, 0 ); - // this will turn on FPE for #IND and zerodiv - state = _control87( state & ~( _EM_ZERODIVIDE | _EM_INVALID ), _MCW_EM ); -#endif -#ifdef _WIN32 - ::SetUnhandledExceptionFilter( unhandled_handler ); -#endif - - if (!glfwInit()) - return -1; - -#ifdef _WIN32 - DeleteFile( "log.txt" ); - DeleteFile( "errors.txt" ); - CreateDirectory("logs", NULL); -#endif - Global.LoadIniFile("eu07.ini"); - -#ifdef _WIN32 - // hunter-271211: ukrywanie konsoli - if( Global.iWriteLogEnabled & 2 ) - { - AllocConsole(); - SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), FOREGROUND_GREEN ); - } -#endif - - for (int i = 1; i < argc; ++i) - { - std::string token(argv[i]); - - if (token == "-e3d") { - if (Global.iConvertModels > 0) - Global.iConvertModels = -Global.iConvertModels; - else - Global.iConvertModels = -7; // z optymalizacją, bananami i prawidłowym Opacity - } - else if (i + 1 < argc && token == "-s") - { - Global.SceneryFile = std::string(argv[++i]); - std::replace(Global.SceneryFile.begin(), Global.SceneryFile.end(), '\\', '/'); - } - else if (i + 1 < argc && token == "-v") - { - std::string v(argv[++i]); - std::transform(v.begin(), v.end(), v.begin(), ::tolower); - Global.asHumanCtrlVehicle = v; - } - else - { - std::cout - << "usage: " << std::string(argv[0]) - << " [-s sceneryfilepath]" - << " [-v vehiclename]" - << " [-e3d]" - << std::endl; - return -1; - } - } - - // match requested video mode to current to allow for - // fullwindow creation when resolution is the same - GLFWmonitor *monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode *vmode = glfwGetVideoMode(monitor); - - glfwWindowHint(GLFW_RED_BITS, vmode->redBits); - glfwWindowHint(GLFW_GREEN_BITS, vmode->greenBits); - glfwWindowHint(GLFW_BLUE_BITS, vmode->blueBits); - glfwWindowHint(GLFW_REFRESH_RATE, vmode->refreshRate); - - glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE); - if( Global.iMultisampling > 0 ) { - glfwWindowHint( GLFW_SAMPLES, 1 << Global.iMultisampling ); - } - - if (Global.bFullScreen) - { - // match screen dimensions with selected monitor, for 'borderless window' in fullscreen mode - Global.iWindowWidth = vmode->width; - Global.iWindowHeight = vmode->height; - } - - GLFWwindow *window = - glfwCreateWindow( - Global.iWindowWidth, - Global.iWindowHeight, - Global.AppName.c_str(), - ( Global.bFullScreen ? - monitor : - nullptr), - nullptr ); - - if (!window) - { - std::cout << "failed to create window" << std::endl; - return -1; - } - glfwMakeContextCurrent(window); - glfwSwapInterval(Global.VSync ? 1 : 0); //vsync - glfwSetCursorPos(window, 0.0, 0.0); - glfwSetFramebufferSizeCallback(window, window_resize_callback); - glfwSetCursorPosCallback(window, cursor_pos_callback); - glfwSetMouseButtonCallback( window, mouse_button_callback ); - glfwSetKeyCallback(window, key_callback); - glfwSetScrollCallback( window, scroll_callback ); - glfwSetWindowFocusCallback(window, focus_callback); - { - int width, height; - glfwGetFramebufferSize(window, &width, &height); - window_resize_callback(window, width, height); - } - - if (glewInit() != GLEW_OK) - { - std::cout << "failed to init GLEW" << std::endl; - return -1; - } - -#ifdef _WIN32 - // setup wrapper for base glfw window proc, to handle copydata messages - Hwnd = glfwGetWin32Window( window ); - BaseWindowProc = (WNDPROC)::SetWindowLongPtr( Hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc ); - // switch off the topmost flag - ::SetWindowPos( Hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); -#endif - - try { - Global.ControlPicking = true; - - if ((false == GfxRenderer.Init(window)) - || (false == UILayer.init(window))) - return -1; - - if( Global.bSoundEnabled ) { - Global.bSoundEnabled &= audio::renderer.init(); - } - - audio::renderer.init(); - input::Keyboard.init(); - input::Mouse.init(); - input::Gamepad.init(); - if (Global.uart_conf.enable) - input::uart = std::make_unique(); - if (Global.motiontelemetry_conf.enable) - input::motiontelemetry = std::make_unique(); - - Global.pWorld = &World; - if( false == World.Init( window ) ) { - ErrorLog( "Simulation setup failed" ); - return -1; + try + { + auto result { Application.init( argc, argv ) }; + if( result == 0 ) { + result = Application.run(); } + Application.exit(); + std::_Exit(0); // skip destructors, there are ordering errors which causes segfaults + return result; } catch( std::bad_alloc const &Error ) { ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) ); return -1; } - catch (std::runtime_error e) - { - ErrorLog(e.what()); -#ifdef _WIN32 - MessageBox(NULL, e.what(), "MaSzyna", MB_OK); -#endif - return -1; - } - -#ifdef _WIN32 - Console *pConsole = new Console(); // Ra: nie wiem, czy ma to sens, ale jakoś zainicjowac trzeba -#endif -/* - if( !joyGetNumDevs() ) - WriteLog( "No joystick" ); -*/ - if( Global.iConvertModels < 0 ) { - Global.iConvertModels = -Global.iConvertModels; - World.CreateE3D( szModelPath ); // rekurencyjne przeglądanie katalogów - World.CreateE3D( szDynamicPath, true ); - } // po zrobieniu E3D odpalamy normalnie scenerię, by ją zobaczyć - -#ifdef _WIN32 - Console::On(); // włączenie konsoli -#endif - - Global.ControlPicking = false; - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); //capture cursor - - try { - while( ( false == glfwWindowShouldClose( window ) ) - && ( true == World.Update() ) - && ( true == GfxRenderer.Render() ) ) { - if (input::motiontelemetry) - input::motiontelemetry->update(); - glfwPollEvents(); - input::Keyboard.poll(); - simulation::Commands.update(); - if( true == Global.InputMouse ) { input::Mouse.poll(); } - if( true == Global.InputGamepad ) { input::Gamepad.poll(); } - if( input::uart != nullptr ) { input::uart->poll(); } - } - } - catch (std::runtime_error e) - { - ErrorLog(e.what()); -#ifdef _WIN32 - MessageBox(NULL, e.what(), "MaSzyna", MB_OK); -#endif - return -1; - } - catch( std::bad_alloc const &Error ) { - ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) ); - return -1; - } - -#ifdef _WIN32 - Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej) - SafeDelete( pConsole ); -#endif - SafeDelete( simulation::Region ); - - glfwDestroyWindow(window); - glfwTerminate(); - - TPythonInterpreter::killInstance(); - - _exit(0); // skip destructors, there are ordering errors which causes segfaults - return 0; } diff --git a/EvLaunch.cpp b/EvLaunch.cpp index 64d9e0fd..e881dfaa 100644 --- a/EvLaunch.cpp +++ b/EvLaunch.cpp @@ -24,6 +24,7 @@ http://mozilla.org/MPL/2.0/. #include "parser.h" #include "Console.h" #include "World.h" +#include "simulationtime.h" #include "utilities.h" //--------------------------------------------------------------------------- @@ -137,10 +138,11 @@ bool TEventLauncher::Load(cParser *parser) return true; } -bool TEventLauncher::check_conditions() -{ //"renderowanie" wyzwalacza +bool TEventLauncher::check_activation() { + auto bCond { false }; - if (iKey != 0) { + + if( iKey != 0 ) { if( iKey > 255 ) { // key and modifier auto const modifier = ( iKey & 0xff00 ) >> 8; @@ -153,37 +155,45 @@ bool TEventLauncher::check_conditions() bCond = ( Console::Pressed( iKey & 0xff ) ); // czy klawisz wciśnięty } } - if (DeltaTime > 0) - { - if (UpdatedTime > DeltaTime) - { + if( DeltaTime > 0 ) { + if( UpdatedTime > DeltaTime ) { UpdatedTime = 0; // naliczanie od nowa bCond = true; } - else - UpdatedTime += Timer::GetDeltaTime(); // aktualizacja naliczania czasu + else { + // aktualizacja naliczania czasu + UpdatedTime += Timer::GetDeltaTime(); + } } - else - { // jeśli nie cykliczny, to sprawdzić czas - if (simulation::Time.data().wHour == iHour) - { - if (simulation::Time.data().wMinute == iMinute) - { // zgodność czasu uruchomienia - if (UpdatedTime < 10) - { + else { + // jeśli nie cykliczny, to sprawdzić czas + if( simulation::Time.data().wHour == iHour ) { + if( simulation::Time.data().wMinute == iMinute ) { + // zgodność czasu uruchomienia + if( UpdatedTime < 10 ) { UpdatedTime = 20; // czas do kolejnego wyzwolenia? bCond = true; } } } - else + else { UpdatedTime = 1; + } } - if (bCond) // jeśli spełniony został warunek - { - if ((iCheckMask != 0) && MemCell) // sprawdzanie warunku na komórce pamięci - bCond = MemCell->Compare(szText, fVal1, fVal2, iCheckMask); + + return bCond; +} + +bool TEventLauncher::check_conditions() { + + auto bCond { true }; + + if( ( iCheckMask != 0 ) + && ( MemCell != nullptr ) ) { + // sprawdzanie warunku na komórce pamięci + bCond = MemCell->Compare( szText, fVal1, fVal2, iCheckMask ); } + return bCond; // sprawdzanie dRadius w Ground.cpp } diff --git a/EvLaunch.h b/EvLaunch.h index 83487d50..f545ca57 100644 --- a/EvLaunch.h +++ b/EvLaunch.h @@ -24,6 +24,7 @@ public: // methods bool Load( cParser *parser ); + bool check_activation(); // checks conditions associated with the event. returns: true if the conditions are met bool check_conditions(); bool IsGlobal() const; diff --git a/Event.cpp b/Event.cpp index fefd4859..7b3b2aea 100644 --- a/Event.cpp +++ b/Event.cpp @@ -294,37 +294,37 @@ void TEvent::Load(cParser *parser, Math3D::vector3 const &org) if (token.find('#') != std::string::npos) token.erase(token.find('#')); // obcięcie unikatowości win1250_to_ascii( token ); // get rid of non-ascii chars - Params[6].asCommand = cm_PassengerStopPoint; + Params[6].asCommand = TCommandType::cm_PassengerStopPoint; // nie do kolejki (dla SetVelocity też, ale jak jest do toru dowiązany) bEnabled = false; } else if (token == "SetVelocity") { bEnabled = false; - Params[6].asCommand = cm_SetVelocity; + Params[6].asCommand = TCommandType::cm_SetVelocity; } else if (token == "RoadVelocity") { bEnabled = false; - Params[6].asCommand = cm_RoadVelocity; + Params[6].asCommand = TCommandType::cm_RoadVelocity; } else if (token == "SectionVelocity") { bEnabled = false; - Params[6].asCommand = cm_SectionVelocity; + Params[6].asCommand = TCommandType::cm_SectionVelocity; } else if (token == "ShuntVelocity") { bEnabled = false; - Params[6].asCommand = cm_ShuntVelocity; + Params[6].asCommand = TCommandType::cm_ShuntVelocity; } else if (token == "OutsideStation") { bEnabled = false; // ma być skanowny, aby AI nie przekraczało W5 - Params[6].asCommand = cm_OutsideStation; + Params[6].asCommand = TCommandType::cm_OutsideStation; } else - Params[6].asCommand = cm_Unknown; + Params[6].asCommand = TCommandType::cm_Unknown; Params[0].asText = new char[token.size() + 1]; strcpy(Params[0].asText, token.c_str()); parser->getTokens(); @@ -814,7 +814,7 @@ TCommandType TEvent::Command() case tp_PutValues: return Params[6].asCommand; // komenda zakodowana binarnie } - return cm_Unknown; // inne eventy się nie liczą + return TCommandType::cm_Unknown; // inne eventy się nie liczą }; double TEvent::ValueGet(int n) @@ -891,7 +891,7 @@ event_manager::update() { // test list of global events for possible new additions to the queue for( auto *launcher : m_launcherqueue ) { - if( true == launcher->check_conditions() ) { + if( true == ( launcher->check_activation() && launcher->check_conditions() ) ) { // NOTE: we're presuming global events aren't going to use event2 WriteLog( "Eventlauncher " + launcher->name() ); if( launcher->Event1 ) { diff --git a/Gauge.cpp b/Gauge.cpp index 46b7cb3b..cc74504d 100644 --- a/Gauge.cpp +++ b/Gauge.cpp @@ -45,7 +45,7 @@ void TGauge::Init(TSubModel *Submodel, TGaugeType Type, float Scale, float Offse return; } - if( m_type == gt_Digital ) { + if( m_type == TGaugeType::gt_Digital ) { TSubModel *sm = SubModel->ChildGet(); do { @@ -148,18 +148,18 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, } std::map gaugetypes { - { "rot", gt_Rotate }, - { "rotvar", gt_Rotate }, - { "mov", gt_Move }, - { "movvar", gt_Move }, - { "wip", gt_Wiper }, - { "dgt", gt_Digital } + { "rot", TGaugeType::gt_Rotate }, + { "rotvar", TGaugeType::gt_Rotate }, + { "mov", TGaugeType::gt_Move }, + { "movvar", TGaugeType::gt_Move }, + { "wip", TGaugeType::gt_Wiper }, + { "dgt", TGaugeType::gt_Digital } }; auto lookup = gaugetypes.find( gaugetypename ); auto const type = ( lookup != gaugetypes.end() ? lookup->second : - gt_Unknown ); + TGaugeType::gt_Unknown ); Init( submodel, type, scale, offset, friction, 0, endvalue, endscale, interpolatescale ); @@ -228,16 +228,16 @@ TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) { if( ( currentvalue < fNewDesired ) && ( false == m_soundfxincrease.empty() ) ) { // shift up - m_soundfxincrease.play(); + m_soundfxincrease.play( sound_flags::exclusive ); } else if( ( currentvalue > fNewDesired ) && ( false == m_soundfxdecrease.empty() ) ) { // shift down - m_soundfxdecrease.play(); + m_soundfxdecrease.play( sound_flags::exclusive ); } else if( Fallbacksound != nullptr ) { // ...and if that fails too, try the provided fallback sound from legacy system - Fallbacksound->play(); + Fallbacksound->play( sound_flags::exclusive ); } }; @@ -276,15 +276,15 @@ void TGauge::Update() { if( SubModel ) { // warunek na wszelki wypadek, gdyby się submodel nie podłączył switch (m_type) { - case gt_Rotate: { + case TGaugeType::gt_Rotate: { SubModel->SetRotate( float3( 0, 1, 0 ), GetScaledValue() * 360.0 ); break; } - case gt_Move: { + case TGaugeType::gt_Move: { SubModel->SetTranslate( float3( 0, 0, GetScaledValue() ) ); break; } - case gt_Wiper: { + case TGaugeType::gt_Wiper: { auto const scaledvalue { GetScaledValue() }; SubModel->SetRotate( float3( 0, 1, 0 ), scaledvalue * 360.0 ); auto *sm = SubModel->ChildGet(); @@ -296,7 +296,7 @@ void TGauge::Update() { } break; } - case gt_Digital: { + case TGaugeType::gt_Digital: { // Ra 2014-07: licznik cyfrowy auto *sm = SubModel->ChildGet(); /* std::string n = FormatFloat( "0000000000", floor( fValue ) ); // na razie tak trochę bez sensu diff --git a/Gauge.h b/Gauge.h index 87e78781..9baeca83 100644 --- a/Gauge.h +++ b/Gauge.h @@ -12,7 +12,7 @@ http://mozilla.org/MPL/2.0/. #include "Classes.h" #include "sound.h" -enum TGaugeType { +enum class TGaugeType { // typ ruchu gt_Unknown, // na razie nie znany gt_Rotate, // obrót @@ -60,7 +60,7 @@ private: GetScaledValue() const; // members - TGaugeType m_type { gt_Unknown }; // typ ruchu + TGaugeType m_type { TGaugeType::gt_Unknown }; // typ ruchu float m_friction { 0.f }; // hamowanie przy zliżaniu się do zadanej wartości float m_targetvalue { 0.f }; // wartość docelowa float m_value { 0.f }; // wartość obecna diff --git a/Globals.h b/Globals.h index 4f917656..2731c7b4 100644 --- a/Globals.h +++ b/Globals.h @@ -22,9 +22,9 @@ struct global_settings { // members // data items // TODO: take these out of the settings - GLFWwindow *window{ nullptr }; bool shiftState{ false }; //m7todo: brzydko bool ctrlState{ false }; + bool altState{ false }; std::mt19937 random_engine{ std::mt19937( static_cast( std::time( NULL ) ) ) }; TDynamicObject *changeDynObj{ nullptr };// info o zmianie pojazdu TWorld *pWorld{ nullptr }; // wskaźnik na świat do usuwania pojazdów diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index dec46d5e..426d3f6f 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -156,13 +156,13 @@ enum coupling { uic = 0x100 }; // possible effect ranges for control commands; exclusive -enum range { +enum class range_t { local, unit, consist }; // start method for devices; exclusive -enum start { +enum class start_t { manual, automatic, manualwithautofallback, @@ -180,7 +180,7 @@ enum light { }; // door operation methods; exclusive -enum control { +enum control_t { passenger, // local, opened/closed for duration of loading driver, // remote, operated by the driver autonomous, // local, closed when vehicle moves and/or after timeout @@ -351,13 +351,13 @@ struct TTractionParam /*powyzsze parametry zwiazane sa z torem po ktorym aktualnie pojazd jedzie*/ /*typy hamulcow zespolonych*/ -enum TBrakeSystem { Individual, Pneumatic, ElectroPneumatic }; +enum class TBrakeSystem { Individual, Pneumatic, ElectroPneumatic }; /*podtypy hamulcow zespolonych*/ -enum TBrakeSubSystem { ss_None, ss_W, ss_K, ss_KK, ss_Hik, ss_ESt, ss_KE, ss_LSt, ss_MT, ss_Dako }; -enum TBrakeValve { NoValve, W, W_Lu_VI, W_Lu_L, W_Lu_XR, K, Kg, Kp, Kss, Kkg, Kkp, Kks, Hikg1, Hikss, Hikp1, KE, SW, EStED, NESt3, ESt3, LSt, ESt4, ESt3AL2, EP1, EP2, M483, CV1_L_TR, CV1, CV1_R, Other }; -enum TBrakeHandle { NoHandle, West, FV4a, M394, M254, FVel1, FVel6, D2, Knorr, FD1, BS2, testH, St113, MHZ_P, MHZ_T, MHZ_EN57, MHZ_K5P }; +enum class TBrakeSubSystem { ss_None, ss_W, ss_K, ss_KK, ss_Hik, ss_ESt, ss_KE, ss_LSt, ss_MT, ss_Dako }; +enum class TBrakeValve { NoValve, W, W_Lu_VI, W_Lu_L, W_Lu_XR, K, Kg, Kp, Kss, Kkg, Kkp, Kks, Hikg1, Hikss, Hikp1, KE, SW, EStED, NESt3, ESt3, LSt, ESt4, ESt3AL2, EP1, EP2, M483, CV1_L_TR, CV1, CV1_R, Other }; +enum class TBrakeHandle { NoHandle, West, FV4a, M394, M254, FVel1, FVel6, D2, Knorr, FD1, BS2, testH, St113, MHZ_P, MHZ_T, MHZ_EN57, MHZ_K5P }; /*typy hamulcow indywidualnych*/ -enum TLocalBrake { NoBrake, ManualBrake, PneumaticBrake, HydraulicBrake }; +enum class TLocalBrake { NoBrake, ManualBrake, PneumaticBrake, HydraulicBrake }; /*dla osob/towar: opoznienie hamowania/odhamowania*/ typedef double TBrakeDelayTable[4]; @@ -366,17 +366,17 @@ struct TBrakePressure double PipePressureVal = 0.0; double BrakePressureVal = 0.0; double FlowSpeedVal = 0.0; - TBrakeSystem BrakeType = Pneumatic; + TBrakeSystem BrakeType = TBrakeSystem::Pneumatic; }; typedef std::map TBrakePressureTable; /*typy napedow*/ -enum TEngineTypes { None, Dumb, WheelsDriven, ElectricSeriesMotor, ElectricInductionMotor, DieselEngine, SteamEngine, DieselElectric }; +enum class TEngineType { None, Dumb, WheelsDriven, ElectricSeriesMotor, ElectricInductionMotor, DieselEngine, SteamEngine, DieselElectric }; /*postac dostarczanej energii*/ -enum TPowerType { NoPower, BioPower, MechPower, ElectricPower, SteamPower }; +enum class TPowerType { NoPower, BioPower, MechPower, ElectricPower, SteamPower }; /*rodzaj paliwa*/ -enum TFuelType { Undefined, Coal, Oil }; +enum class TFuelType { Undefined, Coal, Oil }; /*rodzaj rusztu*/ struct TGrateType { TFuelType FuelType; @@ -425,7 +425,7 @@ struct TCurrentCollector { //} }; /*typy źródeł mocy*/ -enum TPowerSource { NotDefined, InternalSource, Transducer, Generator, Accumulator, CurrentCollector, PowerCable, Heater }; +enum class TPowerSource { NotDefined, InternalSource, Transducer, Generator, Accumulator, CurrentCollector, PowerCable, Heater }; struct _mover__1 @@ -481,7 +481,7 @@ struct TPowerParameters }; struct { - TEngineTypes GeneratorEngine; + TEngineType GeneratorEngine; }; struct { @@ -498,9 +498,9 @@ struct TPowerParameters MaxVoltage = 0.0; MaxCurrent = 0.0; IntR = 0.001; - SourceType = NotDefined; - PowerType = NoPower; - RPowerCable.PowerTrans = NoPower; + SourceType = TPowerSource::NotDefined; + PowerType = TPowerType::NoPower; + RPowerCable.PowerTrans = TPowerType::NoPower; } }; @@ -584,7 +584,7 @@ struct TTransmision double Ratio = 1.0; }; -enum TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic }; +enum class TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic }; struct power_coupling { double current{ 0.0 }; @@ -601,7 +601,7 @@ struct TCoupling { double FmaxB = 1000.0; double DmaxC = 0.1; double FmaxC = 1000.0; - TCouplerType CouplerType = NoCoupler; /*typ sprzegu*/ + TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/ /*zmienne*/ int CouplingFlag = 0; /*0 - wirtualnie, 1 - sprzegi, 2 - pneumatycznie, 4 - sterowanie, 8 - kabel mocy*/ int AllowedFlag = 3; //Ra: znaczenie jak wyżej, maska dostępnych @@ -625,7 +625,7 @@ struct fuel_pump { bool is_enabled { false }; // device is allowed/requested to operate bool is_active { false }; // device is working - start start_type { start::manual }; + start_t start_type { start_t::manual }; }; // basic approximation of a fuel pump @@ -634,7 +634,7 @@ struct oil_pump { bool is_enabled { false }; // device is allowed/requested to operate bool is_active { false }; // device is working - start start_type { start::manual }; + start_t start_type { start_t::manual }; float resource_amount { 1.f }; float pressure_minimum { 0.f }; // lowest acceptable working pressure float pressure_maximum { 0.65f }; // oil pressure at maximum engine revolutions @@ -647,7 +647,7 @@ struct water_pump { bool breaker { true }; // device is allowed to operate bool is_enabled { false }; // device is requested to operate bool is_active { false }; // device is working - start start_type { start::manual }; + start_t start_type { start_t::manual }; }; struct water_heater { @@ -728,7 +728,7 @@ public: std::string TypeName; /*nazwa serii/typu*/ //TrainType: string; {typ: EZT/elektrowoz - Winger 040304} int TrainType = 0; /*Ra: powinno być szybciej niż string*/ - TEngineTypes EngineType = None; /*typ napedu*/ + TEngineType EngineType = TEngineType::None; /*typ napedu*/ TPowerParameters EnginePowerSource; /*zrodlo mocy dla silnikow*/ TPowerParameters SystemPowerSource; /*zrodlo mocy dla systemow sterowania/przetwornic/sprezarek*/ TPowerParameters HeatingPowerSource; /*zrodlo mocy dla ogrzewania*/ @@ -766,11 +766,11 @@ public: /*hamulce:*/ int NBpA = 0; /*ilosc el. ciernych na os: 0 1 2 lub 4*/ int SandCapacity = 0; /*zasobnik piasku [kg]*/ - TBrakeSystem BrakeSystem = Individual;/*rodzaj hamulca zespolonego*/ - TBrakeSubSystem BrakeSubsystem = ss_None ; - TBrakeValve BrakeValve = NoValve; - TBrakeHandle BrakeHandle = NoHandle; - TBrakeHandle BrakeLocHandle = NoHandle; + TBrakeSystem BrakeSystem = TBrakeSystem::Individual;/*rodzaj hamulca zespolonego*/ + TBrakeSubSystem BrakeSubsystem = TBrakeSubSystem::ss_None ; + TBrakeValve BrakeValve = TBrakeValve::NoValve; + TBrakeHandle BrakeHandle = TBrakeHandle::NoHandle; + TBrakeHandle BrakeLocHandle = TBrakeHandle::NoHandle; double MBPM = 1.0; /*masa najwiekszego cisnienia*/ std::shared_ptr Hamulec; @@ -779,7 +779,7 @@ public: std::shared_ptr Pipe; std::shared_ptr Pipe2; - TLocalBrake LocalBrake = NoBrake; /*rodzaj hamulca indywidualnego*/ + TLocalBrake LocalBrake = TLocalBrake::NoBrake; /*rodzaj hamulca indywidualnego*/ TBrakePressureTable BrakePressureTable; /*wyszczegolnienie cisnien w rurze*/ TBrakePressure BrakePressureActual; //wartości ważone dla aktualnej pozycji kranu int ASBType = 0; /*0: brak hamulca przeciwposlizgowego, 1: reczny, 2: automat*/ @@ -1006,9 +1006,9 @@ public: bool CompressorAllow = false; /*! zezwolenie na uruchomienie sprezarki NBMX*/ bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere) bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure - start CompressorStart{ start::manual }; // whether the compressor is started manually, or another way + start_t CompressorStart{ start_t::manual }; // whether the compressor is started manually, or another way // TODO converter parameters, for when we start cleaning up mover parameters - start ConverterStart{ start::manual }; // whether converter is started manually, or by other means + start_t ConverterStart{ start_t::manual }; // whether converter is started manually, or by other means float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met double ConverterStartDelayTimer{ 0.0 }; // helper, for tracking whether converter start delay passed bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/ @@ -1024,7 +1024,6 @@ public: int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/ double BrakeCtrlPosR = 0.0; /*nastawa hamulca zespolonego - plynna dla FV4a*/ double BrakeCtrlPos2 = 0.0; /*nastawa hamulca zespolonego - kapturek dla FV4a*/ - int LocalBrakePos = 0; /*nastawa hamulca indywidualnego*/ int ManualBrakePos = 0; /*nastawa hamulca recznego*/ double LocalBrakePosA = 0.0; /* @@ -1250,7 +1249,7 @@ public: bool AddPulseForce(int Multipler);/*dla drezyny*/ - bool Sandbox( bool const State, int const Notify = range::consist );/*wlacza/wylacza sypanie piasku*/ + bool Sandbox( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ /*! zbijanie czuwaka/SHP*/ void SSReset(void); @@ -1263,11 +1262,9 @@ public: /*! stopnie hamowania - hamulec zasadniczy*/ bool IncBrakeLevelOld(void); bool DecBrakeLevelOld(void); - bool IncLocalBrakeLevel(int CtrlSpeed); - bool DecLocalBrakeLevel(int CtrlSpeed); + bool IncLocalBrakeLevel(float const CtrlSpeed); + bool DecLocalBrakeLevel(float const CtrlSpeed); /*! ABu 010205: - skrajne polozenia ham. pomocniczego*/ - bool IncLocalBrakeLevelFAST(void); - bool DecLocalBrakeLevelFAST(void); bool IncManualBrakeLevel(int CtrlSpeed); bool DecManualBrakeLevel(int CtrlSpeed); bool DynamicBrakeSwitch(bool Switch); @@ -1309,16 +1306,16 @@ public: /*--funkcje dla lokomotyw*/ bool DirectionBackward(void);/*! kierunek ruchu*/ - bool WaterPumpBreakerSwitch( bool State, int const Notify = range::consist ); // water pump breaker state toggle - bool WaterPumpSwitch( bool State, int const Notify = range::consist ); // water pump state toggle - bool WaterHeaterBreakerSwitch( bool State, int const Notify = range::consist ); // water heater breaker state toggle - bool WaterHeaterSwitch( bool State, int const Notify = range::consist ); // water heater state toggle - bool WaterCircuitsLinkSwitch( bool State, int const Notify = range::consist ); // water circuits link state toggle - bool FuelPumpSwitch( bool State, int const Notify = range::consist ); // fuel pump state toggle - bool OilPumpSwitch( bool State, int const Notify = range::consist ); // oil pump state toggle - bool MainSwitch( bool const State, int const Notify = range::consist );/*! wylacznik glowny*/ - bool ConverterSwitch( bool State, int const Notify = range::consist );/*! wl/wyl przetwornicy*/ - bool CompressorSwitch( bool State, int const Notify = range::consist );/*! wl/wyl sprezarki*/ + bool WaterPumpBreakerSwitch( bool State, range_t const Notify = range_t::consist ); // water pump breaker state toggle + bool WaterPumpSwitch( bool State, range_t const Notify = range_t::consist ); // water pump state toggle + bool WaterHeaterBreakerSwitch( bool State, range_t const Notify = range_t::consist ); // water heater breaker state toggle + bool WaterHeaterSwitch( bool State, range_t const Notify = range_t::consist ); // water heater state toggle + bool WaterCircuitsLinkSwitch( bool State, range_t const Notify = range_t::consist ); // water circuits link state toggle + bool FuelPumpSwitch( bool State, range_t const Notify = range_t::consist ); // fuel pump state toggle + bool OilPumpSwitch( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle + bool MainSwitch( bool const State, range_t const Notify = range_t::consist );/*! wylacznik glowny*/ + bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/ + bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/ /*-funkcje typowe dla lokomotywy elektrycznej*/ void ConverterCheck( double const Timestep ); // przetwornica @@ -1348,8 +1345,8 @@ public: bool AutoRelayCheck(void);//symulacja automatycznego rozruchu bool ResistorsFlagCheck(void); //sprawdzenie kontrolki oporow rozruchowych NBMX - bool PantFront( bool const State, int const Notify = range::consist ); //obsluga pantografou przedniego - bool PantRear( bool const State, int const Notify = range::consist ); //obsluga pantografu tylnego + bool PantFront( bool const State, range_t const Notify = range_t::consist ); //obsluga pantografou przedniego + bool PantRear( bool const State, range_t const Notify = range_t::consist ); //obsluga pantografu tylnego /*-funkcje typowe dla lokomotywy spalinowej z przekladnia mechaniczna*/ bool dizel_EngageSwitch(double state); @@ -1364,10 +1361,10 @@ public: /* funckje dla wagonow*/ bool LoadingDone(double LSpeed, std::string LoadInit); - bool DoorLeft(bool State, int const Notify = range::consist ); //obsluga drzwi lewych - bool DoorRight(bool State, int const Notify = range::consist ); //obsluga drzwi prawych + bool DoorLeft(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi lewych + bool DoorRight(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi prawych bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi - bool signal_departure( bool const State, int const Notify = range::consist ); // toggles departure warning + bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning void update_autonomous_doors( double const Deltatime ); // automatic door controller update /* funkcje dla samochodow*/ @@ -1403,7 +1400,7 @@ private: void LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparameters, std::string const Prefix, std::string const &Input ); TPowerType LoadFIZ_PowerDecode( std::string const &Power ); TPowerSource LoadFIZ_SourceDecode( std::string const &Source ); - TEngineTypes LoadFIZ_EngineDecode( std::string const &Engine ); + TEngineType LoadFIZ_EngineDecode( std::string const &Engine ); bool readMPT0( std::string const &line ); bool readMPT( std::string const &line ); //Q 20160717 bool readMPTElectricSeries( std::string const &line ); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 6e132be6..c645135b 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -330,7 +330,7 @@ LoadType( LoadTypeInitial ) for (int b = 0; b < 2; ++b) // Ra: kto tu zrobił "for b:=1 to 2 do" ??? { - Couplers[b].CouplerType = NoCoupler; + Couplers[b].CouplerType = TCouplerType::NoCoupler; Couplers[b].SpringKB = 1.0; Couplers[b].SpringKC = 1.0; Couplers[b].DmaxB = 0.1; @@ -465,7 +465,7 @@ bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters * auto &othercoupler = ConnectTo->Couplers[ coupler.ConnectedNr ]; if( ( Forced ) || ( ( coupler.CoupleDist <= dEpsilon ) - && ( coupler.CouplerType != NoCoupler ) + && ( coupler.CouplerType != TCouplerType::NoCoupler ) && ( coupler.CouplerType == othercoupler.CouplerType ) ) ) { // stykaja sie zderzaki i kompatybilne typy sprzegow, chyba że łączenie na starcie if( coupler.CouplingFlag == ctrain_virtual ) { @@ -510,7 +510,7 @@ int TMoverParameters::DettachStatus(int ConnectNo) // if (CouplerType==Articulated) return false; //sprzęg nie do rozpięcia - może być tylko urwany // Couplers[ConnectNo].CoupleDist=Distance(Loc,Couplers[ConnectNo].Connected->Loc,Dim,Couplers[ConnectNo].Connected->Dim); CouplerDist(ConnectNo); - if (Couplers[ConnectNo].CouplerType == Screw ? Couplers[ConnectNo].CoupleDist < 0.0 : true) + if (Couplers[ConnectNo].CouplerType == TCouplerType::Screw ? Couplers[ConnectNo].CoupleDist < 0.0 : true) return -Couplers[ConnectNo].CouplingFlag; // można rozłączać, jeśli dociśnięty return (Couplers[ConnectNo].CoupleDist > 0.2) ? -Couplers[ConnectNo].CouplingFlag : Couplers[ConnectNo].CouplingFlag; @@ -651,7 +651,7 @@ bool TMoverParameters::ChangeCab(int direction) { // if (ActiveCab+direction=0) then LastCab:=ActiveCab; ActiveCab = ActiveCab + direction; - if ((BrakeSystem == Pneumatic) && (BrakeCtrlPosNo > 0)) + if ((BrakeSystem == TBrakeSystem::Pneumatic) && (BrakeCtrlPosNo > 0)) { // if (BrakeHandle==FV4a) //!!!POBIERAĆ WARTOŚĆ Z KLASY ZAWORU!!! // BrakeLevelSet(-2); //BrakeCtrlPos=-2; @@ -697,7 +697,7 @@ TMoverParameters::CurrentSwitch(bool const State) { } // TBD, TODO: split off shunt mode toggle into a separate command? It doesn't make much sense to have these two together like that // dla 2Ls150 - if( ( EngineType == DieselEngine ) + if( ( EngineType == TEngineType::DieselEngine ) && ( true == ShuntModeAllow ) && ( ActiveDir == 0 ) ) { // przed ustawieniem kierunku @@ -705,7 +705,7 @@ TMoverParameters::CurrentSwitch(bool const State) { return true; } // for SM42/SP42 - if( ( EngineType == DieselElectric ) + if( ( EngineType == TEngineType::DieselElectric ) && ( true == ShuntModeAllow ) && ( MainCtrlPos == 0 ) ) { ShuntMode = State; @@ -726,7 +726,7 @@ void TMoverParameters::UpdatePantVolume(double dt) } } - if (EnginePowerSource.SourceType == CurrentCollector) // tylko jeśli pantografujący + if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący { // Ra 2014-07: zasadniczo, to istnieje zbiornik rozrządu i zbiornik pantografów - na razie mamy razem // Ra 2014-07: kurek trójdrogowy łączy spr.pom. z pantografami i wyłącznikiem ciśnieniowym WS @@ -813,8 +813,8 @@ void TMoverParameters::UpdateBatteryVoltage(double dt) sn4 = 0.0, sn5 = 0.0; // Ra: zrobić z tego amperomierz NN if( ( BatteryVoltage > 0 ) - && ( EngineType != DieselEngine ) - && ( EngineType != WheelsDriven ) + && ( EngineType != TEngineType::DieselEngine ) + && ( EngineType != TEngineType::WheelsDriven ) && ( NominalBatteryVoltage > 0 ) ) { if ((NominalBatteryVoltage / BatteryVoltage < 1.22) && Battery) @@ -877,7 +877,7 @@ void TMoverParameters::UpdateBatteryVoltage(double dt) }; BatteryVoltage -= (sn1 + sn2 + sn3 + sn4 + sn5); if (NominalBatteryVoltage / BatteryVoltage > 1.57) - if (MainSwitch(false) && (EngineType != DieselEngine) && (EngineType != WheelsDriven)) + if (MainSwitch(false) && (EngineType != TEngineType::DieselEngine) && (EngineType != TEngineType::WheelsDriven)) EventFlag = true; // wywalanie szybkiego z powodu zbyt niskiego napiecia if (BatteryVoltage > NominalBatteryVoltage) BatteryVoltage = NominalBatteryVoltage; // wstrzymanie ładowania pow. 110V @@ -936,7 +936,7 @@ ZN //masa double TMoverParameters::LocalBrakeRatio(void) { double LBR; - if (BrakeHandle == MHZ_EN57) + if (BrakeHandle == TBrakeHandle::MHZ_EN57) if ((BrakeOpModeFlag >= bom_EP)) LBR = Handle->GetEP(BrakeCtrlPosR); else @@ -944,7 +944,7 @@ double TMoverParameters::LocalBrakeRatio(void) else { if (LocalBrakePosNo > 0) - LBR = (double)LocalBrakePos / LocalBrakePosNo; + LBR = LocalBrakePosA; else LBR = 0; } @@ -1354,7 +1354,7 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap UpdatePantVolume(dt); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów auto const d { ( - EngineType == WheelsDriven ? + EngineType == TEngineType::WheelsDriven ? dL * CabNo : // na chwile dla testu dL ) }; @@ -1434,7 +1434,7 @@ double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape UpdatePantVolume(dt); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów auto const d { ( - EngineType == WheelsDriven ? + EngineType == TEngineType::WheelsDriven ? dL * CabNo : // na chwile dla testu dL ) }; @@ -1457,13 +1457,13 @@ void TMoverParameters::compute_movement_( double const Deltatime ) { RunInternalCommand(); // automatyczny rozruch - if (EngineType == ElectricSeriesMotor) + if (EngineType == TEngineType::ElectricSeriesMotor) if (AutoRelayCheck()) SetFlag(SoundFlag, sound::relay); - if( ( EngineType == DieselEngine ) - || ( EngineType == DieselElectric ) ) { + if( ( EngineType == TEngineType::DieselEngine ) + || ( EngineType == TEngineType::DieselElectric ) ) { if( dizel_Update( Deltatime ) ) { SetFlag( SoundFlag, sound::relay ); } @@ -1523,7 +1523,7 @@ double TMoverParameters::ShowEngineRotation(int VehN) // sprawdzanie przetwornicy void TMoverParameters::ConverterCheck( double const Timestep ) { // TODO: move other converter checks here, to have it all in one place for potential device object - if( ConverterStart == start::automatic ) { + if( ConverterStart == start_t::automatic ) { ConverterAllow = Mains; } @@ -1551,7 +1551,7 @@ void TMoverParameters::WaterPumpCheck( double const Timestep ) { WaterPump.is_active = ( ( true == Battery ) && ( true == WaterPump.breaker ) - && ( ( true == WaterPump.is_enabled ) || ( WaterPump.start_type == start::battery ) ) ); + && ( ( true == WaterPump.is_enabled ) || ( WaterPump.start_type == start_t::battery ) ) ); } // water heater status check @@ -1578,12 +1578,12 @@ void TMoverParameters::WaterHeaterCheck( double const Timestep ) { // fuel pump status update void TMoverParameters::FuelPumpCheck( double const Timestep ) { - if( FuelPump.start_type == start::automatic ) { - FuelPump.is_enabled = ( dizel_startup || Mains ); - } FuelPump.is_active = ( ( true == Battery ) - && ( true == FuelPump.is_enabled ) ); + && ( FuelPump.start_type == start_t::manual ? ( FuelPump.is_enabled ) : + FuelPump.start_type == start_t::automatic ? ( dizel_startup || Mains ) : + FuelPump.start_type == start_t::manualwithautofallback ? ( FuelPump.is_enabled || dizel_startup || Mains ) : + false ) ); // shouldn't ever get this far but, eh } // oil pump status update @@ -1591,13 +1591,13 @@ void TMoverParameters::OilPumpCheck( double const Timestep ) { OilPump.is_active = ( ( true == Battery ) - && ( OilPump.start_type == start::manual ? ( OilPump.is_enabled ) : - OilPump.start_type == start::automatic ? ( dizel_startup || Mains ) : - OilPump.start_type == start::manualwithautofallback ? ( OilPump.is_enabled || dizel_startup || Mains ) : + && ( OilPump.start_type == start_t::manual ? ( OilPump.is_enabled ) : + OilPump.start_type == start_t::automatic ? ( dizel_startup || Mains ) : + OilPump.start_type == start_t::manualwithautofallback ? ( OilPump.is_enabled || dizel_startup || Mains ) : false ) ); // shouldn't ever get this far but, eh auto const maxrevolutions { - EngineType == DieselEngine ? + EngineType == TEngineType::DieselEngine ? dizel_nmax : DElist[ MainCtrlPosNo ].RPM / 60.0 }; auto const minpressure { @@ -1631,7 +1631,7 @@ double TMoverParameters::ShowCurrent(int AmpN) { // Odczyt poboru prądu na podanym amperomierzu switch (EngineType) { - case ElectricInductionMotor: + case TEngineType::ElectricInductionMotor: switch (AmpN) { // do asynchronicznych case 1: @@ -1642,7 +1642,7 @@ double TMoverParameters::ShowCurrent(int AmpN) return ShowCurrentP(AmpN); // T_MoverParameters:: } break; - case DieselElectric: + case TEngineType::DieselElectric: return fabs(Im); break; default: @@ -1680,10 +1680,10 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) if (MainCtrlPos < MainCtrlPosNo) { switch( EngineType ) { - case None: - case Dumb: - case DieselElectric: - case ElectricInductionMotor: + case TEngineType::None: + case TEngineType::Dumb: + case TEngineType::DieselElectric: + case TEngineType::ElectricInductionMotor: { if( CtrlSpeed > 1 ) { OK = ( IncMainCtrl( 1 ) @@ -1696,7 +1696,7 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) break; } - case ElectricSeriesMotor: + case TEngineType::ElectricSeriesMotor: { if( ActiveDir == 0 ) { return false; } @@ -1754,7 +1754,7 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) break; } - case DieselEngine: + case TEngineType::DieselEngine: { if( CtrlSpeed > 1 ) { while( MainCtrlPos < MainCtrlPosNo ) { @@ -1770,7 +1770,7 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) break; } - case WheelsDriven: + case TEngineType::WheelsDriven: { OK = AddPulseForce( CtrlSpeed ); break; @@ -1842,14 +1842,14 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) else switch (EngineType) { - case None: - case Dumb: - case DieselElectric: - case ElectricInductionMotor: + case TEngineType::None: + case TEngineType::Dumb: + case TEngineType::DieselElectric: + case TEngineType::ElectricInductionMotor: { if (((CtrlSpeed == 1) && - /*(ScndCtrlPos==0) and*/ (EngineType != DieselElectric)) || - ((CtrlSpeed == 1) && (EngineType == DieselElectric))) + /*(ScndCtrlPos==0) and*/ (EngineType != TEngineType::DieselElectric)) || + ((CtrlSpeed == 1) && (EngineType == TEngineType::DieselElectric))) { MainCtrlPos--; OK = true; @@ -1859,7 +1859,7 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) break; } - case ElectricSeriesMotor: + case TEngineType::ElectricSeriesMotor: { if (CtrlSpeed == 1) /*and (ScndCtrlPos=0)*/ { @@ -1883,7 +1883,7 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) break; } - case DieselEngine: + case TEngineType::DieselEngine: { if (CtrlSpeed == 1) { @@ -1901,7 +1901,7 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) } // switch EngineType } } - else if (EngineType == WheelsDriven) + else if (EngineType == TEngineType::WheelsDriven) OK = AddPulseForce(-CtrlSpeed); else OK = false; @@ -1947,7 +1947,7 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) // if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (ScndCtrlPos CtrlDelay) LastRelayTime = 0; - if ((OK) && (EngineType == ElectricInductionMotor) && (ScndCtrlPosNo == 1)) + if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1)) { // NOTE: round() already adds 0.5, are the ones added here as well correct? if ((Vmax < 250)) @@ -2006,7 +2006,7 @@ bool TMoverParameters::DecScndCtrl(int CtrlSpeed) else if ((ScndCtrlPosNo > 0) && (CabNo != 0)) { if ((ScndCtrlPos > 0) && (!CoupledCtrl) && - ((EngineType != DieselElectric) || (!AutoRelayFlag))) + ((EngineType != TEngineType::DieselElectric) || (!AutoRelayFlag))) { if (CtrlSpeed == 1) { @@ -2034,7 +2034,7 @@ bool TMoverParameters::DecScndCtrl(int CtrlSpeed) if (LastRelayTime > CtrlDownDelay) LastRelayTime = 0; - if ((OK) && (EngineType == ElectricInductionMotor) && (ScndCtrlPosNo == 1)) + if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1)) { ScndCtrlActualPos = 0; SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo); @@ -2090,8 +2090,8 @@ bool TMoverParameters::CabDeactivisation(void) bool TMoverParameters::AddPulseForce(int Multipler) { bool APF; - if ((EngineType == WheelsDriven) && (EnginePowerSource.SourceType == InternalSource) && - (EnginePowerSource.PowerType == BioPower)) + if ((EngineType == TEngineType::WheelsDriven) && (EnginePowerSource.SourceType == TPowerSource::InternalSource) && + (EnginePowerSource.PowerType == TPowerType::BioPower)) { ActiveDir = CabNo; DirAbsolute = ActiveDir * CabNo; @@ -2115,7 +2115,7 @@ bool TMoverParameters::AddPulseForce(int Multipler) // Q: 20160713 // sypanie piasku // ************************************************************************************************* -bool TMoverParameters::Sandbox( bool const State, int const Notify ) +bool TMoverParameters::Sandbox( bool const State, range_t const Notify ) { bool result{ false }; @@ -2134,10 +2134,10 @@ bool TMoverParameters::Sandbox( bool const State, int const Notify ) } } - if( Notify != range::local ) { + if( Notify != range_t::local ) { // if requested pass the command on auto const couplingtype = - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ); @@ -2352,7 +2352,7 @@ bool TMoverParameters::DirectionBackward(void) } if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (MainCtrlPos == 0)) { - if (EngineType == WheelsDriven) + if (EngineType == TEngineType::WheelsDriven) CabNo--; // else ActiveDir--; @@ -2379,7 +2379,7 @@ bool TMoverParameters::AntiSlippingButton(void) } // water pump breaker state toggle -bool TMoverParameters::WaterPumpBreakerSwitch( bool State, int const Notify ) { +bool TMoverParameters::WaterPumpBreakerSwitch( bool State, range_t const Notify ) { /* if( FuelPump.start_type == start::automatic ) { // automatic fuel pump ignores 'manual' state commands @@ -2390,12 +2390,12 @@ bool TMoverParameters::WaterPumpBreakerSwitch( bool State, int const Notify ) { WaterPump.breaker = State; - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "WaterPumpBreakerSwitch", ( WaterPump.breaker ? 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -2404,9 +2404,9 @@ bool TMoverParameters::WaterPumpBreakerSwitch( bool State, int const Notify ) { } // water pump state toggle -bool TMoverParameters::WaterPumpSwitch( bool State, int const Notify ) { +bool TMoverParameters::WaterPumpSwitch( bool State, range_t const Notify ) { - if( WaterPump.start_type == start::battery ) { + if( WaterPump.start_type == start_t::battery ) { // automatic fuel pump ignores 'manual' state commands return false; } @@ -2415,12 +2415,12 @@ bool TMoverParameters::WaterPumpSwitch( bool State, int const Notify ) { WaterPump.is_enabled = State; - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "WaterPumpSwitch", ( WaterPump.is_enabled ? 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -2429,7 +2429,7 @@ bool TMoverParameters::WaterPumpSwitch( bool State, int const Notify ) { } // water heater breaker state toggle -bool TMoverParameters::WaterHeaterBreakerSwitch( bool State, int const Notify ) { +bool TMoverParameters::WaterHeaterBreakerSwitch( bool State, range_t const Notify ) { /* if( FuelPump.start_type == start::automatic ) { // automatic fuel pump ignores 'manual' state commands @@ -2440,12 +2440,12 @@ bool TMoverParameters::WaterHeaterBreakerSwitch( bool State, int const Notify ) WaterHeater.breaker = State; - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "WaterHeaterBreakerSwitch", ( WaterHeater.breaker ? 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -2454,7 +2454,7 @@ bool TMoverParameters::WaterHeaterBreakerSwitch( bool State, int const Notify ) } // water heater state toggle -bool TMoverParameters::WaterHeaterSwitch( bool State, int const Notify ) { +bool TMoverParameters::WaterHeaterSwitch( bool State, range_t const Notify ) { /* if( FuelPump.start_type == start::automatic ) { // automatic fuel pump ignores 'manual' state commands @@ -2465,12 +2465,12 @@ bool TMoverParameters::WaterHeaterSwitch( bool State, int const Notify ) { WaterHeater.is_enabled = State; - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "WaterHeaterSwitch", ( WaterHeater.is_enabled ? 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -2479,7 +2479,7 @@ bool TMoverParameters::WaterHeaterSwitch( bool State, int const Notify ) { } // water circuits link state toggle -bool TMoverParameters::WaterCircuitsLinkSwitch( bool State, int const Notify ) { +bool TMoverParameters::WaterCircuitsLinkSwitch( bool State, range_t const Notify ) { if( false == dizel_heat.auxiliary_water_circuit ) { // can't link the circuits if the vehicle only has one @@ -2490,12 +2490,12 @@ bool TMoverParameters::WaterCircuitsLinkSwitch( bool State, int const Notify ) { WaterCircuitsLink = State; - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "WaterCircuitsLinkSwitch", ( WaterCircuitsLink ? 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -2504,9 +2504,9 @@ bool TMoverParameters::WaterCircuitsLinkSwitch( bool State, int const Notify ) { } // fuel pump state toggle -bool TMoverParameters::FuelPumpSwitch( bool State, int const Notify ) { +bool TMoverParameters::FuelPumpSwitch( bool State, range_t const Notify ) { - if( FuelPump.start_type == start::automatic ) { + if( FuelPump.start_type == start_t::automatic ) { // automatic fuel pump ignores 'manual' state commands return false; } @@ -2515,12 +2515,12 @@ bool TMoverParameters::FuelPumpSwitch( bool State, int const Notify ) { FuelPump.is_enabled = State; - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "FuelPumpSwitch", ( FuelPump.is_enabled ? 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -2529,9 +2529,9 @@ bool TMoverParameters::FuelPumpSwitch( bool State, int const Notify ) { } // oil pump state toggle -bool TMoverParameters::OilPumpSwitch( bool State, int const Notify ) { +bool TMoverParameters::OilPumpSwitch( bool State, range_t const Notify ) { - if( OilPump.start_type == start::automatic ) { + if( OilPump.start_type == start_t::automatic ) { // automatic pump ignores 'manual' state commands return false; } @@ -2540,12 +2540,12 @@ bool TMoverParameters::OilPumpSwitch( bool State, int const Notify ) { OilPump.is_enabled = State; - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "OilPumpSwitch", ( OilPump.is_enabled ? 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -2557,7 +2557,7 @@ bool TMoverParameters::OilPumpSwitch( bool State, int const Notify ) { // Q: 20160713 // włączenie / wyłączenie obwodu głownego // ************************************************************************************************* -bool TMoverParameters::MainSwitch( bool const State, int const Notify ) +bool TMoverParameters::MainSwitch( bool const State, range_t const Notify ) { bool const initialstate { Mains || dizel_startup }; @@ -2565,7 +2565,7 @@ bool TMoverParameters::MainSwitch( bool const State, int const Notify ) && ( MainCtrlPosNo > 0 ) ) { if( ( false == State ) - || ( ( ( ScndCtrlPos == 0 ) || ( EngineType == ElectricInductionMotor ) ) + || ( ( ( ScndCtrlPos == 0 ) || ( EngineType == TEngineType::ElectricInductionMotor ) ) && ( ( ConvOvldFlag == false ) || ( TrainType == dt_EZT ) ) && ( LastSwitchingTime > CtrlDelay ) && ( false == TestFlag( DamageFlag, dtrain_out ) ) @@ -2573,8 +2573,8 @@ bool TMoverParameters::MainSwitch( bool const State, int const Notify ) if( true == State ) { // switch on - if( ( EngineType == DieselEngine ) - || ( EngineType == DieselElectric ) ) { + if( ( EngineType == TEngineType::DieselEngine ) + || ( EngineType == TEngineType::DieselElectric ) ) { // launch diesel engine startup procedure dizel_startup = true; } @@ -2596,13 +2596,13 @@ bool TMoverParameters::MainSwitch( bool const State, int const Notify ) LastSwitchingTime = 0; } - if( Notify != range::local ) { + if( Notify != range_t::local ) { // pass the command to other vehicles SendCtrlToNext( "MainSwitch", ( State ? 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -2616,7 +2616,7 @@ bool TMoverParameters::MainSwitch( bool const State, int const Notify ) // Q: 20160713 // włączenie / wyłączenie przetwornicy // ************************************************************************************************* -bool TMoverParameters::ConverterSwitch( bool State, int const Notify ) +bool TMoverParameters::ConverterSwitch( bool State, range_t const Notify ) { bool CS = false; // Ra: normalnie chyba false? @@ -2626,19 +2626,19 @@ bool TMoverParameters::ConverterSwitch( bool State, int const Notify ) CS = true; } if( ConverterAllow == true ) { - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "ConverterSwitch", 1, CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ) ); } } else { - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "ConverterSwitch", 0, CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ) ); } @@ -2651,9 +2651,9 @@ bool TMoverParameters::ConverterSwitch( bool State, int const Notify ) // Q: 20160713 // włączenie / wyłączenie sprężarki // ************************************************************************************************* -bool TMoverParameters::CompressorSwitch( bool State, int const Notify ) +bool TMoverParameters::CompressorSwitch( bool State, range_t const Notify ) { - if( CompressorStart != start::manual ) { + if( CompressorStart != start_t::manual ) { // only pay attention if the compressor can be controlled manually return false; } @@ -2665,19 +2665,19 @@ bool TMoverParameters::CompressorSwitch( bool State, int const Notify ) CS = true; } if( CompressorAllow == true ) { - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "CompressorSwitch", 1, CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ) ); } } else { - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( "CompressorSwitch", 0, CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ) ); } @@ -2763,7 +2763,7 @@ bool TMoverParameters::DecBrakeLevelOld(void) if ((BrakeCtrlPosNo > 0) /*&& (LocalBrakePos == 0)*/) { - if (BrakeCtrlPos > -1 - int(BrakeHandle == FV4a)) + if (BrakeCtrlPos > -1 - int(BrakeHandle == TBrakeHandle::FV4a)) { BrakeCtrlPos--; // BrakeCtrlPosR:=BrakeCtrlPos; @@ -2832,16 +2832,12 @@ bool TMoverParameters::DecBrakeLevelOld(void) // Q: 20160711 // zwiększenie nastawy hamulca pomocnicznego // ************************************************************************************************* -bool TMoverParameters::IncLocalBrakeLevel(int CtrlSpeed) +bool TMoverParameters::IncLocalBrakeLevel(float const CtrlSpeed) { bool IBL; - if ((LocalBrakePos < LocalBrakePosNo) /*and (BrakeCtrlPos<1)*/) + if ((LocalBrakePosA < 1.0) /*and (BrakeCtrlPos<1)*/) { - while ((LocalBrakePos < LocalBrakePosNo) && (CtrlSpeed > 0)) - { - LocalBrakePos++; - CtrlSpeed--; - } + LocalBrakePosA = std::min( 1.0, LocalBrakePosA + CtrlSpeed / LocalBrakePosNo ); IBL = true; } else @@ -2855,16 +2851,12 @@ bool TMoverParameters::IncLocalBrakeLevel(int CtrlSpeed) // Q: 20160711 // zmniejszenie nastawy hamulca pomocniczego // ************************************************************************************************* -bool TMoverParameters::DecLocalBrakeLevel(int CtrlSpeed) +bool TMoverParameters::DecLocalBrakeLevel(float const CtrlSpeed) { bool DBL; - if (LocalBrakePos > 0) + if (LocalBrakePosA > 0) { - while ((CtrlSpeed > 0) && (LocalBrakePos > 0)) - { - LocalBrakePos--; - CtrlSpeed--; - } + LocalBrakePosA = std::max( 0.0, LocalBrakePosA - CtrlSpeed / LocalBrakePosNo ); DBL = true; } else @@ -2874,42 +2866,6 @@ bool TMoverParameters::DecLocalBrakeLevel(int CtrlSpeed) return DBL; } -// ************************************************************************************************* -// Q: 20160711 -// ustawienie pozycji kranu pomocniczego na masymalną wartość -// ************************************************************************************************* -bool TMoverParameters::IncLocalBrakeLevelFAST(void) -{ - bool ILBLF; - if (LocalBrakePos < LocalBrakePosNo) - { - LocalBrakePos = LocalBrakePosNo; - ILBLF = true; - } - else - ILBLF = false; - UnBrake = true; - return ILBLF; -} - -// ************************************************************************************************* -// Q: 20160711 -// ustawienie pozycji hamulca pomocniczego na minimalną -// ************************************************************************************************* -bool TMoverParameters::DecLocalBrakeLevelFAST(void) -{ - bool DLBLF; - if (LocalBrakePos > 0) - { - LocalBrakePos = 0; - DLBLF = true; - } - else - DLBLF = false; - UnBrake = true; - return DLBLF; -} - // ************************************************************************************************* // Q: 20160711 // zwiększenie nastawy hamulca ręcznego @@ -2988,7 +2944,7 @@ bool TMoverParameters::DynamicBrakeSwitch(bool Switch) bool TMoverParameters::RadiostopSwitch(bool Switch) { bool EBS; - if( ( BrakeSystem != Individual ) + if( ( BrakeSystem != TBrakeSystem::Individual ) && ( BrakeCtrlPosNo > 0 ) ) { if( ( true == Switch ) @@ -3067,7 +3023,7 @@ bool TMoverParameters::SwitchEPBrake(int state) double temp; OK = false; - if ((BrakeHandle == St113) && (ActiveCab != 0)) + if ((BrakeHandle == TBrakeHandle::St113) && (ActiveCab != 0)) { if (state > 0) temp = Handle->GetCP(); // TODO: przetlumaczyc @@ -3148,7 +3104,7 @@ bool TMoverParameters::BrakeDelaySwitch(int BDS) { bool rBDS; // if (BrakeCtrlPosNo > 0) - if (BrakeHandle == MHZ_EN57) + if (BrakeHandle == TBrakeHandle::MHZ_EN57) { if ((BDS != BrakeOpModeFlag) && ((BDS & BrakeOpModes) > 0)) { @@ -3268,7 +3224,7 @@ void TMoverParameters::CompressorCheck(double dt) && ( true == Mains ) && ( MainCtrlPos > 0 ) ) { if( Compressor < MaxCompressor ) { - if( ( EngineType == DieselElectric ) + if( ( EngineType == TEngineType::DieselElectric ) && ( CompressorPower > 0 ) ) { CompressedVolume += CompressorSpeed @@ -3293,7 +3249,7 @@ void TMoverParameters::CompressorCheck(double dt) else { if( CompressorPower == 3 ) { // experimental: make sure compressor coupled with diesel engine is always ready for work - CompressorStart = start::automatic; + CompressorStart = start_t::automatic; } if (CompressorFlag) // jeśli sprężarka załączona { // sprawdzić możliwe warunki wyłączenia sprężarki @@ -3301,7 +3257,7 @@ void TMoverParameters::CompressorCheck(double dt) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) if( Couplers[ side::rear ].Connected != NULL ) { CompressorFlag = ( - ( ( Couplers[ side::rear ].Connected->CompressorAllow ) || ( CompressorStart == start::automatic ) ) + ( ( Couplers[ side::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) && ( CompressorAllowLocal ) && ( Couplers[ side::rear ].Connected->ConverterFlag ) ); } @@ -3314,7 +3270,7 @@ void TMoverParameters::CompressorCheck(double dt) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) if( Couplers[ side::front ].Connected != NULL ) { CompressorFlag = ( - ( ( Couplers[ side::front ].Connected->CompressorAllow ) || ( CompressorStart == start::automatic ) ) + ( ( Couplers[ side::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) && ( CompressorAllowLocal ) && ( Couplers[ side::front ].Connected->ConverterFlag ) ); } @@ -3324,7 +3280,7 @@ void TMoverParameters::CompressorCheck(double dt) } else CompressorFlag = ( - ( ( CompressorAllow ) || ( CompressorStart == start::automatic ) ) + ( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) && ( CompressorAllowLocal ) && ( Mains ) && ( ( ConverterFlag ) @@ -3377,7 +3333,7 @@ void TMoverParameters::CompressorCheck(double dt) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) if( Couplers[ side::rear ].Connected != NULL ) { CompressorFlag = ( - ( ( Couplers[ side::rear ].Connected->CompressorAllow ) || ( CompressorStart == start::automatic ) ) + ( ( Couplers[ side::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) && ( CompressorAllowLocal ) && ( Couplers[ side::rear ].Connected->ConverterFlag ) ); } @@ -3390,7 +3346,7 @@ void TMoverParameters::CompressorCheck(double dt) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) if( Couplers[ side::front ].Connected != NULL ) { CompressorFlag = ( - ( ( Couplers[ side::front ].Connected->CompressorAllow ) || ( CompressorStart == start::automatic ) ) + ( ( Couplers[ side::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) && ( CompressorAllowLocal ) && ( Couplers[ side::front ].Connected->ConverterFlag ) ); } @@ -3400,7 +3356,7 @@ void TMoverParameters::CompressorCheck(double dt) } else { CompressorFlag = ( - ( ( CompressorAllow ) || ( CompressorStart == start::automatic ) ) + ( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) && ( CompressorAllowLocal ) && ( Mains ) && ( ( ConverterFlag ) @@ -3438,8 +3394,8 @@ void TMoverParameters::CompressorCheck(double dt) // the compressor is coupled with the diesel engine, engine revolutions affect the output if( false == CompressorGovernorLock ) { auto const enginefactor { ( - EngineType == DieselElectric ? ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) : - EngineType == DieselEngine ? ( std::abs( enrot ) / nmax ) : + EngineType == TEngineType::DieselElectric ? ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) : + EngineType == TEngineType::DieselEngine ? ( std::abs( enrot ) / nmax ) : 1.0 ) }; // shouldn't ever get here but, eh CompressedVolume += CompressorSpeed @@ -3504,18 +3460,12 @@ void TMoverParameters::UpdatePipePressure(double dt) if ((BrakeCtrlPosNo > 1) /*&& (ActiveCab != 0)*/) // with BrakePressureTable[BrakeCtrlPos] do { - if ((EngineType != ElectricInductionMotor)) - dpLocalValve = - LocHandle->GetPF(std::max(static_cast(LocalBrakePos) / LocalBrakePosNo, LocalBrakePosA), - Hamulec->GetBCP(), ScndPipePress, dt, 0); - else - dpLocalValve = - LocHandle->GetPF(LocalBrakePosA, Hamulec->GetBCP(), ScndPipePress, dt, 0); + dpLocalValve = LocHandle->GetPF(LocalBrakePosA, Hamulec->GetBCP(), ScndPipePress, dt, 0); - if( ( BrakeHandle == FV4a ) + if( ( BrakeHandle == TBrakeHandle::FV4a ) && ( ( PipePress < 2.75 ) && ( ( Hamulec->GetStatus() & b_rls ) == 0 ) ) - && ( BrakeSubsystem == ss_LSt ) + && ( BrakeSubsystem == TBrakeSubSystem::ss_LSt ) && ( TrainType != dt_EZT ) ) { temp = PipePress + 0.00001; } @@ -3526,7 +3476,7 @@ void TMoverParameters::UpdatePipePressure(double dt) if ((BrakeOpModeFlag != bom_PS)) if ((BrakeOpModeFlag < bom_EP) || ((Handle->GetPos(bh_EB) - 0.5) < BrakeCtrlPosR) || - (BrakeHandle != MHZ_EN57)) + (BrakeHandle != TBrakeHandle::MHZ_EN57)) dpMainValve = Handle->GetPF(BrakeCtrlPosR, PipePress, temp, dt, EqvtPipePress); else dpMainValve = Handle->GetPF(0, PipePress, temp, dt, EqvtPipePress); @@ -3569,10 +3519,10 @@ void TMoverParameters::UpdatePipePressure(double dt) switch (BrakeValve) { - case K: - case W: { + case TBrakeValve::K: + case TBrakeValve::W: { - if( BrakeLocHandle != NoHandle ) { + if( BrakeLocHandle != TBrakeHandle::NoHandle ) { LocBrakePress = LocHandle->GetCP(); //(Hamulec as TWest).SetLBP(LocBrakePress); @@ -3587,8 +3537,8 @@ void TMoverParameters::UpdatePipePressure(double dt) break; } - case LSt: - case EStED: { + case TBrakeValve::LSt: + case TBrakeValve::EStED: { LocBrakePress = LocHandle->GetCP(); for( int b = 0; b < 2; b++ ) @@ -3609,7 +3559,7 @@ void TMoverParameters::UpdatePipePressure(double dt) //(Hamulec as TLSt).SetLBP(LocBrakePress); Hamulec->SetLBP( LocBrakePress ); - if( ( BrakeValve == EStED ) ) + if( ( BrakeValve == TBrakeValve::EStED ) ) if( MBPM < 2 ) Hamulec->PLC( MaxBrakePress[ LoadFlag ] ); else @@ -3617,7 +3567,7 @@ void TMoverParameters::UpdatePipePressure(double dt) break; } - case CV1_L_TR: + case TBrakeValve::CV1_L_TR: { LocBrakePress = LocHandle->GetCP(); //(Hamulec as TCV1L_TR).SetLBP(LocBrakePress); @@ -3625,15 +3575,15 @@ void TMoverParameters::UpdatePipePressure(double dt) break; } - case EP2: + case TBrakeValve::EP2: { Hamulec->PLC( TotalMass ); break; } - case ESt3AL2: - case NESt3: - case ESt4: - case ESt3: + case TBrakeValve::ESt3AL2: + case TBrakeValve::NESt3: + case TBrakeValve::ESt4: + case TBrakeValve::ESt3: { if( MBPM < 2 ) //(Hamulec as TNESt3).PLC(MaxBrakePress[LoadFlag]) @@ -3646,7 +3596,7 @@ void TMoverParameters::UpdatePipePressure(double dt) Hamulec->SetLBP( LocBrakePress ); break; } - case KE: + case TBrakeValve::KE: { LocBrakePress = LocHandle->GetCP(); //(Hamulec as TKE).SetLBP(LocBrakePress); @@ -3668,7 +3618,7 @@ void TMoverParameters::UpdatePipePressure(double dt) } } // switch - if ((BrakeHandle == FVel6) && (ActiveCab != 0)) + if ((BrakeHandle == TBrakeHandle::FVel6) && (ActiveCab != 0)) { if ((Battery) && (ActiveDir != 0) @@ -3934,9 +3884,9 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) // ABu: to dla optymalizacji, bo chyba te rzeczy wystarczy sprawdzac 1 raz na // klatke? LastSwitchingTime += dt1; - if (EngineType == ElectricSeriesMotor) + if (EngineType == TEngineType::ElectricSeriesMotor) LastRelayTime += dt1; - if( Mains && /*(abs(CabNo) < 2) &&*/ ( EngineType == ElectricSeriesMotor ) ) // potem ulepszyc! pantogtrafy! + if( Mains && /*(abs(CabNo) < 2) &&*/ ( EngineType == TEngineType::ElectricSeriesMotor ) ) // potem ulepszyc! pantogtrafy! { // Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być // zdefiniowany nawrotnik if( CabNo == 0 ) @@ -3944,7 +3894,7 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) else Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo; } // bo nie dzialalo - else if( ( EngineType == ElectricInductionMotor ) + else if( ( EngineType == TEngineType::ElectricInductionMotor ) || ( ( ( Couplers[ side::front ].CouplingFlag & ctrain_power ) == ctrain_power ) || ( ( Couplers[ side::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) { // potem ulepszyc! pantogtrafy! @@ -4094,11 +4044,11 @@ double TMoverParameters::BrakeForce( TTrackParam const &Track ) { double K{ 0 }, Fb{ 0 }, sm{ 0 }; switch( LocalBrake ) { - case ManualBrake: { + case TLocalBrake::ManualBrake: { K = MaxBrakeForce * ManualBrakeRatio(); break; } - case HydraulicBrake: { + case TLocalBrake::HydraulicBrake: { K = MaxBrakeForce * LocalBrakeRatio(); break; } @@ -4130,7 +4080,7 @@ double TMoverParameters::BrakeForce( TTrackParam const &Track ) { K += Ntotal; // w kN K *= static_cast(BrakeCylNo) / (NBrakeAxles * static_cast(NBpA)); // w kN na os } - if ((BrakeSystem == Pneumatic) || (BrakeSystem == ElectroPneumatic)) + if ((BrakeSystem == TBrakeSystem::Pneumatic) || (BrakeSystem == TBrakeSystem::ElectroPneumatic)) { u = Hamulec->GetFC(Vel, K); UnitBrakeForce = u * K * 1000.0; // sila na jeden klocek w N @@ -4375,7 +4325,7 @@ double TMoverParameters::CouplerForce(int CouplerN, double dt) //***if -tempdist>(DmaxB+Connected^.Couplers[CNext].DmaxB)/10 then {zderzenie} { Couplers[CouplerN].CheckCollision = true; - if( ( Couplers[ CouplerN ].CouplerType == Automatic ) + if( ( Couplers[ CouplerN ].CouplerType == TCouplerType::Automatic ) && ( Couplers[ CouplerN ].CouplingFlag == coupling::faux ) ) { // sprzeganie wagonow z samoczynnymi sprzegami} // CouplingFlag:=ctrain_coupler+ctrain_pneumatic+ctrain_controll+ctrain_passenger+ctrain_scndpneumatic; @@ -4405,7 +4355,7 @@ double TMoverParameters::TractionForce( double dt ) { dmoment = 0; // youBy switch( EngineType ) { - case DieselElectric: { + case TEngineType::DieselElectric: { if( ( true == Mains ) && ( true == FuelPump.is_active ) ) { @@ -4441,7 +4391,7 @@ double TMoverParameters::TractionForce( double dt ) { } break; } - case DieselEngine: { + case TEngineType::DieselEngine: { if( ShuntMode ) // dodatkowa przekładnia np. dla 2Ls150 dtrans = AnPos * Transmision.Ratio * MotorParam[ ScndCtrlActualPos ].mIsat; else @@ -4469,7 +4419,7 @@ double TMoverParameters::TractionForce( double dt ) { // TBD, TODO: move this to update, it doesn't exactly have much to do with traction switch( EngineType ) { - case ElectricSeriesMotor: { + case TEngineType::ElectricSeriesMotor: { if( true == Mains ) { switch( RVentType ) { @@ -4517,7 +4467,7 @@ double TMoverParameters::TractionForce( double dt ) { break; } - case DieselElectric: { + case TEngineType::DieselElectric: { // NOTE: for this type RventRot is the speed of motor blowers; we also update radiator fans while at it if( true == Mains ) { // TBD, TODO: currently ignores RVentType, fix this? @@ -4533,7 +4483,7 @@ double TMoverParameters::TractionForce( double dt ) { break; } - case DieselEngine: { + case TEngineType::DieselEngine: { // NOTE: we update only radiator fans, as vehicles with diesel engine don't have other ventilators if( true == Mains ) { dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt; @@ -4552,12 +4502,12 @@ double TMoverParameters::TractionForce( double dt ) { } switch( EngineType ) { - case Dumb: { + case TEngineType::Dumb: { PosRatio = ( MainCtrlPos + ScndCtrlPos ) / ( MainCtrlPosNo + ScndCtrlPosNo + 0.01 ); EnginePower = 1000.0 * Power * PosRatio; break; } - case DieselEngine: { + case TEngineType::DieselEngine: { EnginePower = ( 2 * dizel_Mstand + dmoment ) * enrot * ( 2.0 * M_PI / 1000.0 ); if( MainCtrlPos > 1 ) { // dodatkowe opory z powodu sprezarki} @@ -4565,7 +4515,7 @@ double TMoverParameters::TractionForce( double dt ) { } break; } - case DieselElectric: { + case TEngineType::DieselElectric: { EnginePower = 0; // the actual calculation is done in two steps later in the method break; } @@ -4577,7 +4527,7 @@ double TMoverParameters::TractionForce( double dt ) { if (ActiveDir != 0) switch (EngineType) { - case Dumb: + case TEngineType::Dumb: { if (Mains && (CabNo != 0)) { @@ -4594,10 +4544,10 @@ double TMoverParameters::TractionForce( double dt ) { break; } // Dumb - case WheelsDriven: + case TEngineType::WheelsDriven: { - if (EnginePowerSource.SourceType == InternalSource) - if (EnginePowerSource.PowerType == BioPower) + if (EnginePowerSource.SourceType == TPowerSource::InternalSource) + if (EnginePowerSource.PowerType == TPowerType::BioPower) Ft = Sign(sin(eAngle)) * PulseForce * Transmision.Ratio; PulseForceTimer = PulseForceTimer + dt; if (PulseForceTimer > CtrlDelay) @@ -4610,7 +4560,7 @@ double TMoverParameters::TractionForce( double dt ) { break; } // WheelsDriven - case ElectricSeriesMotor: + case TEngineType::ElectricSeriesMotor: { // enrot:=Transmision.Ratio*nrot; // yB: szereg dwoch sekcji w ET42 @@ -4658,7 +4608,7 @@ double TMoverParameters::TractionForce( double dt ) { if ( (std::max(GetTrainsetVoltage(), std::abs(Voltage)) < EnginePowerSource.CollectorParameters.MinV) || (std::max(GetTrainsetVoltage(), std::abs(Voltage)) * EnginePowerSource.CollectorParameters.OVP > EnginePowerSource.CollectorParameters.MaxV)) - if( MainSwitch( false, ( TrainType == dt_EZT ? range::unit : range::local ) ) ) // TODO: check whether we need to send this EMU-wide + if( MainSwitch( false, ( TrainType == dt_EZT ? range_t::unit : range_t::local ) ) ) // TODO: check whether we need to send this EMU-wide EventFlag = true; // wywalanie szybkiego z powodu niewłaściwego napięcia if (((DynamicBrakeType == dbrake_automatic) || (DynamicBrakeType == dbrake_switch)) && (DynamicBrakeFlag)) @@ -4673,7 +4623,7 @@ double TMoverParameters::TractionForce( double dt ) { break; } - case DieselEngine: + case TEngineType::DieselEngine: { Mm = dmoment; //bylo * dizel_engage Mw = Mm * dtrans; // dmoment i dtrans policzone przy okazji enginerotation @@ -4683,7 +4633,7 @@ double TMoverParameters::TractionForce( double dt ) { break; } - case DieselElectric: // youBy + case TEngineType::DieselElectric: // youBy { // tmpV:=V*CabNo*ActiveDir; auto const tmpV { nrot * Pirazy2 * 0.5 * WheelDiameter * DirAbsolute }; //*CabNo*ActiveDir; @@ -4758,16 +4708,15 @@ double TMoverParameters::TractionForce( double dt ) { else Im = NPoweredAxles * sqrt(abs(Mm * MotorParam[ScndCtrlPos].Isat)); - if (ShuntMode) - { + if( ShuntMode ) { EnginePower = Voltage * Im / 1000.0; - if (EnginePower > tmp) - { - EnginePower = tmp * 1000.0; - Voltage = EnginePower / Im; + if( EnginePower > tmp ) { + EnginePower = tmp; + Voltage = EnginePower * 1000.0 / Im; + } + if( EnginePower < tmp ) { + Ft *= EnginePower / tmp; } - if (EnginePower < tmp) - Ft = Ft * EnginePower / tmp; } else { @@ -4981,13 +4930,13 @@ double TMoverParameters::TractionForce( double dt ) { break; } // DieselElectric - case ElectricInductionMotor: + case TEngineType::ElectricInductionMotor: { if( ( Mains ) ) { // nie wchodzić w funkcję bez potrzeby if( ( std::max( std::abs( Voltage ), GetTrainsetVoltage() ) < EnginePowerSource.CollectorParameters.MinV ) || ( std::max( std::abs( Voltage ), GetTrainsetVoltage() ) > EnginePowerSource.CollectorParameters.MaxV + 200 ) ) { - MainSwitch( false, ( TrainType == dt_EZT ? range::unit : range::local ) ); // TODO: check whether we need to send this EMU-wide + MainSwitch( false, ( TrainType == dt_EZT ? range_t::unit : range_t::local ) ); // TODO: check whether we need to send this EMU-wide } } if( true == Mains ) { @@ -5019,7 +4968,7 @@ double TMoverParameters::TractionForce( double dt ) { if (((DoorLeftOpened) || (DoorRightOpened))) DynamicBrakeFlag = true; else if (((dtrans < 0.25) && (LocHandle->GetCP() < 0.25) && (AnPos < 0.01)) || - ((dtrans < 0.25) && (ShuntModeAllow) && (LocalBrakePos == 0))) + ((dtrans < 0.25) && (ShuntModeAllow) && (LocalBrakePosA < 0.01))) DynamicBrakeFlag = false; else if ((((BrakePress > 0.25) && (dtrans > 0.25) || (LocHandle->GetCP() > 0.25))) || (AnPos > 0.02)) @@ -5027,25 +4976,35 @@ double TMoverParameters::TractionForce( double dt ) { dtrans = Hamulec->GetEDBCP() * eimc[eimc_p_abed]; // stala napedu if ((DynamicBrakeFlag)) { + // ustalanie współczynnika blendingu do luzowania hamulca PN if (eimv[eimv_Fmax] * Sign(V) * DirAbsolute < -1) { PosRatio = -Sign(V) * DirAbsolute * eimv[eimv_Fr] / (eimc[eimc_p_Fh] * - Max0R(Max0R(dtrans,0.01) / MaxBrakePress[0], AnPos) /*dizel_fill*/); + Max0R(dtrans,Max0R(0.01,Hamulec->GetEDBCP())) / MaxBrakePress[0]); + PosRatio = clamp(PosRatio, 0.0, 1.0); } - else - PosRatio = 0; - PosRatio = Round(20.0 * PosRatio) / 20.0; + else + { + PosRatio = 0; + } + PosRatio = Round(20.0 * PosRatio) / 20.0; //stopniowanie PN/ED if (PosRatio < 19.5 / 20.0) - PosRatio *= 0.9; - // if PosRatio<0 then - // PosRatio:=2+PosRatio-2; - Hamulec->SetED(Max0R(0.0, std::min(PosRatio, 1.0))); - // (Hamulec as TLSt).SetLBP(LocBrakePress*(1-PosRatio)); - PosRatio = -std::max(std::min(dtrans * 1.0 / MaxBrakePress[0], 1.0), AnPos) * - std::max(0.0, std::min(1.0, (Vel - eimc[eimc_p_Vh0]) / - (eimc[eimc_p_Vh1] - eimc[eimc_p_Vh0]))); - eimv[eimv_Fzad] = -std::max(LocalBrakeRatio(), dtrans / MaxBrakePress[0]); + PosRatio *= 0.9; + Hamulec->SetED(Max0R(0.0, std::min(PosRatio, 1.0))); //ustalenie stopnia zmniejszenia ciśnienia + // ustalanie siły hamowania ED + if ((Hamulec->GetEDBCP() > 0.25) && (eimc[eimc_p_abed] < 0.001)) //jeśli PN wyłącza ED + { + PosRatio = 0; + eimv[eimv_Fzad] = 0; + } + else + { + PosRatio = -std::max(std::min(dtrans * 1.0 / MaxBrakePress[0], 1.0), AnPos) * + std::max(0.0, std::min(1.0, (Vel - eimc[eimc_p_Vh0]) / + (eimc[eimc_p_Vh1] - eimc[eimc_p_Vh0]))); + eimv[eimv_Fzad] = -std::max(LocalBrakeRatio(), dtrans / MaxBrakePress[0]); + } tmp = 5; } else @@ -5074,11 +5033,11 @@ double TMoverParameters::TractionForce( double dt ) { if( ( SlippingWheels ) ) { PosRatio = 0; tmp = 10; - Sandbox( true, range::unit ); + Sandbox( true, range_t::unit ); } // przeciwposlizg else { // switch sandbox off - Sandbox( false, range::unit ); + Sandbox( false, range_t::unit ); } dizel_fill += Max0R(Min0R(PosRatio - dizel_fill, 0.02), -0.02) * 12 * @@ -5229,17 +5188,17 @@ double TMoverParameters::TractionForce( double dt ) { break; } // ElectricInductionMotor - case None: + case TEngineType::None: default: { break; } } // case EngineType switch( EngineType ) { - case DieselElectric: { + case TEngineType::DieselElectric: { // rough approximation of extra effort to overcome friction etc auto const rpmratio{ 60.0 * enrot / DElist[ MainCtrlPosNo ].RPM }; - EnginePower += rpmratio * 0.2 * DElist[ MainCtrlPosNo ].GenPower; + EnginePower += rpmratio * 0.15 * DElist[ MainCtrlPosNo ].GenPower; break; } default: { @@ -5301,7 +5260,7 @@ bool TMoverParameters::FuseOn(void) ((Mains) || (TrainType != dt_EZT)) && (!TestFlag(EngDmgFlag, 1))) { // w ET40 jest blokada nastawnika, ale czy działa dobrze? SendCtrlToNext("FuseSwitch", 1, CabNo); - if (((EngineType == ElectricSeriesMotor) || ((EngineType == DieselElectric))) && FuseFlag) + if (((EngineType == TEngineType::ElectricSeriesMotor) || ((EngineType == TEngineType::DieselElectric))) && FuseFlag) { FuseFlag = false; // wlaczenie ponowne obwodu FO = true; @@ -5393,7 +5352,7 @@ double TMoverParameters::MomentumF(double I, double Iw, int SCP) bool TMoverParameters::CutOffEngine(void) { bool COE = false; // Ra: wartość domyślna, sprawdzić to trzeba - if ((NPoweredAxles > 0) && (CabNo == 0) && (EngineType == ElectricSeriesMotor)) + if ((NPoweredAxles > 0) && (CabNo == 0) && (EngineType == TEngineType::ElectricSeriesMotor)) { if (SetFlag(DamageFlag, -dtrain_engine)) { @@ -5411,7 +5370,7 @@ bool TMoverParameters::CutOffEngine(void) bool TMoverParameters::MaxCurrentSwitch(bool State) { bool MCS = false; - if (EngineType == ElectricSeriesMotor) + if (EngineType == TEngineType::ElectricSeriesMotor) if (ImaxHi > ImaxLo) { if (State && (Imax == ImaxLo) && (RList[MainCtrlPos].Bn < 2) && @@ -5442,7 +5401,7 @@ bool TMoverParameters::MaxCurrentSwitch(bool State) bool TMoverParameters::MinCurrentSwitch(bool State) { bool MCS = false; - if (((EngineType == ElectricSeriesMotor) && (IminHi > IminLo)) || (TrainType == dt_EZT)) + if (((EngineType == TEngineType::ElectricSeriesMotor) && (IminHi > IminLo)) || (TrainType == dt_EZT)) { if (State && (Imin == IminLo)) { @@ -5784,7 +5743,7 @@ bool TMoverParameters::AutoRelayCheck(void) // Q: 20160713 // Podnosi / opuszcza przedni pantograf. Returns: state of the pantograph after the operation // ************************************************************************************************* -bool TMoverParameters::PantFront( bool const State, int const Notify ) +bool TMoverParameters::PantFront( bool const State, range_t const Notify ) { /* if( ( true == Battery ) @@ -5794,22 +5753,22 @@ bool TMoverParameters::PantFront( bool const State, int const Notify ) PantFrontUp = State; if( State == true ) { PantFrontStart = 0; - if( Notify != range::local ) { + if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( "PantFront", 1, CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ) ); } } else { PantFrontStart = 1; - if( Notify != range::local ) { + if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( "PantFront", 0, CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ) ); } @@ -5837,7 +5796,7 @@ bool TMoverParameters::PantFront( bool const State, int const Notify ) // Q: 20160713 // Podnoszenie / opuszczanie pantografu tylnego // ************************************************************************************************* -bool TMoverParameters::PantRear( bool const State, int const Notify ) +bool TMoverParameters::PantRear( bool const State, range_t const Notify ) { /* if( ( true == Battery ) @@ -5847,22 +5806,22 @@ bool TMoverParameters::PantRear( bool const State, int const Notify ) PantRearUp = State; if( State == true ) { PantRearStart = 0; - if( Notify != range::local ) { + if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( "PantRear", 1, CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ) ); } } else { PantRearStart = 1; - if( Notify != range::local ) { + if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( "PantRear", 0, CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? ctrain_controll | ctrain_depot : ctrain_controll ) ); } @@ -5892,7 +5851,7 @@ bool TMoverParameters::PantRear( bool const State, int const Notify ) // ************************************************************************************************* bool TMoverParameters::dizel_EngageSwitch(double state) { - if ((EngineType == DieselEngine) && (state <= 1) && (state >= 0) && + if ((EngineType == TEngineType::DieselEngine) && (state <= 1) && (state >= 0) && (state != dizel_engagestate)) { dizel_engagestate = state; @@ -6010,6 +5969,12 @@ bool TMoverParameters::dizel_AutoGearCheck(void) else dizel_EngageSwitch(0.66); break; + case 5: + if (Vel>dizel_minVelfullengage) + dizel_EngageSwitch(1.0); + else + dizel_EngageSwitch(0.35*(1+RList[MainCtrlPos].R)*RList[MainCtrlPos].R); + break; default: if (hydro_TC && hydro_TC_Fill>0.01) dizel_EngageSwitch(1.0); @@ -6032,9 +5997,10 @@ bool TMoverParameters::dizel_StartupCheck() { auto engineisready { true }; // make inital optimistic presumption, then watch the reality crush it // test the fuel pump + // TODO: add fuel pressure check if( false == FuelPump.is_active ) { engineisready = false; - if( FuelPump.start_type == start::manual ) { + if( FuelPump.start_type == start_t::manual ) { // with manual pump control startup procedure is done only once per starter switch press dizel_startup = false; } @@ -6043,7 +6009,7 @@ bool TMoverParameters::dizel_StartupCheck() { if( ( false == OilPump.is_active ) || ( OilPump.pressure_present < OilPump.pressure_minimum ) ) { engineisready = false; - if( OilPump.start_type == start::manual ) { + if( OilPump.start_type == start_t::manual ) { // with manual pump control startup procedure is done only once per starter switch press dizel_startup = false; } @@ -6084,7 +6050,7 @@ bool TMoverParameters::dizel_Update(double dt) { enrot = std::max( enrot, 0.35 * ( // TODO: dac zaleznie od temperatury i baterii - EngineType == DieselEngine ? + EngineType == TEngineType::DieselEngine ? dizel_nmin : DElist[ 0 ].RPM / 60.0 ) ); @@ -6099,7 +6065,7 @@ bool TMoverParameters::dizel_Update(double dt) { bool DU { false }; - if( EngineType == DieselEngine ) { + if( EngineType == TEngineType::DieselEngine ) { dizel_EngageChange( dt ); DU = dizel_AutoGearCheck(); double const fillspeed { 2 }; @@ -6161,6 +6127,12 @@ double TMoverParameters::dizel_fillcheck(int mcp) else nreg = dizel_nmin * 0.75 + dizel_nmax * 0.25; break; + case 5: + if (Vel > dizel_minVelfullengage) + nreg = dizel_nmax; + else + nreg = dizel_nmin + 0.8 * (dizel_nmax - dizel_nmin) * RList[mcp].R; + break; default: realfill = 0; // sluczaj break; @@ -6361,8 +6333,8 @@ void TMoverParameters::dizel_Heat( double const dt ) { auto const rpm { enrot * 60 }; // TODO: calculate this once and cache for further use, instead of doing it repeatedly all over the place auto const maxrevolutions { ( - EngineType == DieselEngine ? dizel_nmax * 60 : - EngineType == DieselElectric ? DElist[ MainCtrlPosNo ].RPM : + EngineType == TEngineType::DieselEngine ? dizel_nmax * 60 : + EngineType == TEngineType::DieselElectric ? DElist[ MainCtrlPosNo ].RPM : std::numeric_limits::max() ) }; // shouldn't ever get here but, eh auto const revolutionsfactor { clamp( rpm / maxrevolutions, 0.0, 1.0 ) }; auto const waterpump { WaterPump.is_active ? 1 : 0 }; @@ -6601,7 +6573,7 @@ bool TMoverParameters::DoorBlockedFlag(void) // ************************************************************************************************* // NOTE: door methods work regardless of vehicle door control type, // but commands issued through the command system work only for vehicles which accept remote door control -bool TMoverParameters::DoorLeft(bool State, int const Notify ) { +bool TMoverParameters::DoorLeft(bool State, range_t const Notify ) { if( DoorLeftOpened == State ) { // TBD: should the command be passed to other vehicles regardless of whether it affected the primary target? @@ -6618,7 +6590,7 @@ bool TMoverParameters::DoorLeft(bool State, int const Notify ) { DoorLeftOpened = State; result = true; - if( DoorCloseCtrl == control::autonomous ) { + if( DoorCloseCtrl == control_t::autonomous ) { // activate or disable the door timer depending on whether door were open or closed // NOTE: this it a local-only operation but shouldn't be an issue as automatic door are operated locally anyway DoorLeftOpenTimer = ( @@ -6627,7 +6599,7 @@ bool TMoverParameters::DoorLeft(bool State, int const Notify ) { -1.0 ); } } - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( ( State == true ? @@ -6637,7 +6609,7 @@ bool TMoverParameters::DoorLeft(bool State, int const Notify ) { 1 : 2 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -6651,7 +6623,7 @@ bool TMoverParameters::DoorLeft(bool State, int const Notify ) { // ************************************************************************************************* // NOTE: door methods work regardless of vehicle door control type, // but commands issued through the command system work only for vehicles which accept remote door control -bool TMoverParameters::DoorRight(bool State, int const Notify ) { +bool TMoverParameters::DoorRight(bool State, range_t const Notify ) { if( DoorRightOpened == State ) { // TBD: should the command be passed to other vehicles regardless of whether it affected the primary target? @@ -6668,7 +6640,7 @@ bool TMoverParameters::DoorRight(bool State, int const Notify ) { DoorRightOpened = State; result = true; - if( DoorCloseCtrl == control::autonomous ) { + if( DoorCloseCtrl == control_t::autonomous ) { // activate or disable the door timer depending on whether door were open or closed // NOTE: this it a local-only operation but shouldn't be an issue as automatic door are operated locally anyway DoorRightOpenTimer = ( @@ -6677,7 +6649,7 @@ bool TMoverParameters::DoorRight(bool State, int const Notify ) { -1.0 ); } } - if( Notify != range::local ) { + if( Notify != range_t::local ) { SendCtrlToNext( ( State == true ? @@ -6687,7 +6659,7 @@ bool TMoverParameters::DoorRight(bool State, int const Notify ) { 2 : 1 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -6697,7 +6669,7 @@ bool TMoverParameters::DoorRight(bool State, int const Notify ) { // toggles departure warning bool -TMoverParameters::signal_departure( bool const State, int const Notify ) { +TMoverParameters::signal_departure( bool const State, range_t const Notify ) { if( DepartureSignal == State ) { // TBD: should the command be passed to other vehicles regardless of whether it affected the primary target? @@ -6705,7 +6677,7 @@ TMoverParameters::signal_departure( bool const State, int const Notify ) { } DepartureSignal = State; - if( Notify != range::local ) { + if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( "DepartureSignal", @@ -6713,7 +6685,7 @@ TMoverParameters::signal_departure( bool const State, int const Notify ) { 1 : 0 ), CabNo, - ( Notify == range::unit ? + ( Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control ) ); } @@ -6725,7 +6697,7 @@ TMoverParameters::signal_departure( bool const State, int const Notify ) { void TMoverParameters::update_autonomous_doors( double const Deltatime ) { - if( ( DoorCloseCtrl != control::autonomous ) + if( ( DoorCloseCtrl != control_t::autonomous ) || ( ( false == DoorLeftOpened ) && ( false == DoorRightOpened ) ) ) { // nothing to do @@ -6748,14 +6720,14 @@ TMoverParameters::update_autonomous_doors( double const Deltatime ) { if( ( ( DoorStayOpen > 0.0 ) && ( DoorLeftOpenTimer < 0.0 ) ) || ( Vel > 5.0 ) ) { // close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving) - DoorLeft( false, range::local ); + DoorLeft( false, range_t::local ); } } if( true == DoorRightOpened ) { if( ( ( DoorStayOpen > 0.0 ) && ( DoorRightOpenTimer < 0.0 ) ) || ( Vel > 5.0 ) ) { // close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving) - DoorRight( false, range::local ); + DoorRight( false, range_t::local ); } } } @@ -6965,10 +6937,10 @@ bool TMoverParameters::readMPT( std::string const &line ) { switch( EngineType ) { - case ElectricSeriesMotor: { return readMPTElectricSeries( line ); } - case DieselElectric: { return readMPTDieselElectric( line ); } - case DieselEngine: { return readMPTDieselEngine( line ); } - default: { return false; } + case TEngineType::ElectricSeriesMotor: { return readMPTElectricSeries( line ); } + case TEngineType::DieselElectric: { return readMPTDieselElectric( line ); } + case TEngineType::DieselEngine: { return readMPTDieselEngine( line ); } + default: { return false; } } } @@ -7056,9 +7028,9 @@ bool TMoverParameters::readBPT( std::string const &line ) { >> BrakePressureTable[ idx ].BrakePressureVal >> BrakePressureTable[ idx ].FlowSpeedVal >> braketype; - if( braketype == "Pneumatic" ) { BrakePressureTable[ idx ].BrakeType = Pneumatic; } - else if( braketype == "ElectroPneumatic" ) { BrakePressureTable[ idx ].BrakeType = ElectroPneumatic; } - else { BrakePressureTable[ idx ].BrakeType = Individual; } + if( braketype == "Pneumatic" ) { BrakePressureTable[ idx ].BrakeType = TBrakeSystem::Pneumatic; } + else if( braketype == "ElectroPneumatic" ) { BrakePressureTable[ idx ].BrakeType = TBrakeSystem::ElectroPneumatic; } + else { BrakePressureTable[ idx ].BrakeType = TBrakeSystem::Individual; } return true; } @@ -7182,46 +7154,46 @@ bool TMoverParameters::readLightsList( std::string const &Input ) { // ************************************************************************************************* void TMoverParameters::BrakeValveDecode( std::string const &Valve ) { - std::map valvetypes{ - { "W", W }, - { "W_Lu_L", W_Lu_L }, - { "W_Lu_XR", W_Lu_XR }, - { "W_Lu_VI", W_Lu_VI }, - { "K", K }, - { "Kg", Kg }, - { "Kp", Kp }, - { "Kss", Kss }, - { "Kkg", Kkg }, - { "Kkp", Kkp }, - { "Kks", Kks }, - { "Hikp1", Hikp1 }, - { "Hikss", Hikss }, - { "Hikg1", Hikg1 }, - { "KE", KE }, - { "SW", SW }, - { "EStED", EStED }, - { "NESt3", NESt3 }, - { "ESt3", ESt3 }, - { "LSt", LSt }, - { "ESt4", ESt4 }, - { "ESt3AL2", ESt3AL2 }, - { "EP1", EP1 }, - { "EP2", EP2 }, - { "M483", M483 }, - { "CV1_L_TR", CV1_L_TR }, - { "CV1", CV1 }, - { "CV1_R", CV1_R } + std::map valvetypes { + { "W", TBrakeValve::W }, + { "W_Lu_L", TBrakeValve::W_Lu_L }, + { "W_Lu_XR", TBrakeValve::W_Lu_XR }, + { "W_Lu_VI", TBrakeValve::W_Lu_VI }, + { "K", TBrakeValve::K }, + { "Kg", TBrakeValve::Kg }, + { "Kp", TBrakeValve::Kp }, + { "Kss", TBrakeValve::Kss }, + { "Kkg", TBrakeValve::Kkg }, + { "Kkp", TBrakeValve::Kkp }, + { "Kks", TBrakeValve::Kks }, + { "Hikp1", TBrakeValve::Hikp1 }, + { "Hikss", TBrakeValve::Hikss }, + { "Hikg1", TBrakeValve::Hikg1 }, + { "KE", TBrakeValve::KE }, + { "SW", TBrakeValve::SW }, + { "EStED", TBrakeValve::EStED }, + { "NESt3", TBrakeValve::NESt3 }, + { "ESt3", TBrakeValve::ESt3 }, + { "LSt", TBrakeValve::LSt }, + { "ESt4", TBrakeValve::ESt4 }, + { "ESt3AL2", TBrakeValve::ESt3AL2 }, + { "EP1", TBrakeValve::EP1 }, + { "EP2", TBrakeValve::EP2 }, + { "M483", TBrakeValve::M483 }, + { "CV1_L_TR", TBrakeValve::CV1_L_TR }, + { "CV1", TBrakeValve::CV1 }, + { "CV1_R", TBrakeValve::CV1_R } }; auto lookup = valvetypes.find( Valve ); BrakeValve = lookup != valvetypes.end() ? lookup->second : - Other; + TBrakeValve::Other; - if( ( BrakeValve == Other ) + if( ( BrakeValve == TBrakeValve::Other ) && ( Valve.find( "ESt" ) != std::string::npos ) ) { - BrakeValve = ESt3; + BrakeValve = TBrakeValve::ESt3; } } @@ -7230,32 +7202,32 @@ void TMoverParameters::BrakeValveDecode( std::string const &Valve ) { // ************************************************************************************************* void TMoverParameters::BrakeSubsystemDecode() { - BrakeSubsystem = ss_None; + BrakeSubsystem = TBrakeSubSystem::ss_None; switch (BrakeValve) { - case W: - case W_Lu_L: - case W_Lu_VI: - case W_Lu_XR: - BrakeSubsystem = ss_W; + case TBrakeValve::W: + case TBrakeValve::W_Lu_L: + case TBrakeValve::W_Lu_VI: + case TBrakeValve::W_Lu_XR: + BrakeSubsystem = TBrakeSubSystem::ss_W; break; - case ESt3: - case ESt3AL2: - case ESt4: - case EP2: - case EP1: - BrakeSubsystem = ss_ESt; + case TBrakeValve::ESt3: + case TBrakeValve::ESt3AL2: + case TBrakeValve::ESt4: + case TBrakeValve::EP2: + case TBrakeValve::EP1: + BrakeSubsystem = TBrakeSubSystem::ss_ESt; break; - case KE: - BrakeSubsystem = ss_KE; + case TBrakeValve::KE: + BrakeSubsystem = TBrakeSubSystem::ss_KE; break; - case CV1: - case CV1_L_TR: - BrakeSubsystem = ss_Dako; + case TBrakeValve::CV1: + case TBrakeValve::CV1_L_TR: + BrakeSubsystem = TBrakeSubSystem::ss_Dako; break; - case LSt: - case EStED: - BrakeSubsystem = ss_LSt; + case TBrakeValve::LSt: + case TBrakeValve::EStED: + BrakeSubsystem = TBrakeSubSystem::ss_LSt; break; } } @@ -7841,11 +7813,11 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) { void TMoverParameters::LoadFIZ_Doors( std::string const &line ) { std::map doorcontrols { - { "Passenger", control::passenger }, - { "AutomaticCtrl", control::autonomous }, - { "DriverCtrl", control::driver }, - { "Conductor", control::conductor }, - { "Mixed", control::mixed } + { "Passenger", control_t::passenger }, + { "AutomaticCtrl", control_t::autonomous }, + { "DriverCtrl", control_t::driver }, + { "Conductor", control_t::conductor }, + { "Mixed", control_t::mixed } }; // opening method { @@ -7853,7 +7825,7 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) { DoorOpenCtrl = lookup != doorcontrols.end() ? lookup->second : - control::passenger; + control_t::passenger; } // closing method { @@ -7861,10 +7833,10 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) { DoorCloseCtrl = lookup != doorcontrols.end() ? lookup->second : - control::passenger; + control_t::passenger; } // automatic closing timer - if( DoorCloseCtrl == control::autonomous ) { extract_value( DoorStayOpen, "DoorStayOpen", line, "" ); } + if( DoorCloseCtrl == control_t::autonomous ) { extract_value( DoorStayOpen, "DoorStayOpen", line, "" ); } extract_value( DoorOpenSpeed, "OpenSpeed", line, "" ); extract_value( DoorCloseSpeed, "CloseSpeed", line, "" ); @@ -7900,17 +7872,17 @@ void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Ind else { coupler = &Couplers[ 0 ]; } std::map couplertypes { - { "Automatic", Automatic }, - { "Screw", Screw }, - { "Chain", Chain }, - { "Bare", Bare }, - { "Articulated", Articulated }, + { "Automatic", TCouplerType::Automatic }, + { "Screw", TCouplerType::Screw }, + { "Chain", TCouplerType::Chain }, + { "Bare", TCouplerType::Bare }, + { "Articulated", TCouplerType::Articulated }, }; auto lookup = couplertypes.find( extract_value( "CType", line ) ); coupler->CouplerType = ( lookup != couplertypes.end() ? lookup->second : - NoCoupler ); + TCouplerType::NoCoupler ); extract_value( coupler->SpringKC, "kC", line, "" ); extract_value( coupler->DmaxC, "DmaxC", line, "" ); @@ -7926,16 +7898,16 @@ void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Ind coupler->AllowedFlag = ( ( -coupler->AllowedFlag ) | ctrain_depot ); } - if( ( coupler->CouplerType != NoCoupler ) - && ( coupler->CouplerType != Bare ) - && ( coupler->CouplerType != Articulated ) ) { + if( ( coupler->CouplerType != TCouplerType::NoCoupler ) + && ( coupler->CouplerType != TCouplerType::Bare ) + && ( coupler->CouplerType != TCouplerType::Articulated ) ) { coupler->SpringKC *= 1000; coupler->FmaxC *= 1000; coupler->SpringKB *= 1000; coupler->FmaxB *= 1000; } - else if( coupler->CouplerType == Bare ) { + else if( coupler->CouplerType == TCouplerType::Bare ) { coupler->SpringKC = 50.0 * Mass + Ftmax / 0.05; coupler->DmaxC = 0.05; @@ -7945,7 +7917,7 @@ void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Ind coupler->FmaxB = 50.0 * Mass + 2.0 * Ftmax; coupler->beta = 0.3; } - else if( coupler->CouplerType == Articulated ) { + else if( coupler->CouplerType == TCouplerType::Articulated ) { coupler->SpringKC = 60.0 * Mass + 1000; coupler->DmaxC = 0.05; @@ -7971,16 +7943,16 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { { std::map brakesystems{ - { "Pneumatic", Pneumatic }, - { "ElectroPneumatic", ElectroPneumatic } + { "Pneumatic", TBrakeSystem::Pneumatic }, + { "ElectroPneumatic", TBrakeSystem::ElectroPneumatic } }; auto lookup = brakesystems.find( extract_value( "BrakeSystem", line ) ); BrakeSystem = lookup != brakesystems.end() ? lookup->second : - Individual; + TBrakeSystem::Individual; } - if( BrakeSystem != Individual ) { + if( BrakeSystem != TBrakeSystem::Individual ) { extract_value( BrakeCtrlPosNo, "BCPN", line, "" ); for( int idx = 0; idx < 4; ++idx ) { @@ -7989,7 +7961,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { } // brakedelays, brakedelayflag { - std::map brakedelays{ + std::map brakedelays { { "GPR", bdelay_G + bdelay_P + bdelay_R }, { "PR", bdelay_P + bdelay_R }, { "GP", bdelay_G + bdelay_P }, @@ -7999,7 +7971,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { { "GPR+Mg", bdelay_G + bdelay_P + bdelay_R + bdelay_M }, { "PR+Mg", bdelay_P + bdelay_R + bdelay_M } }; - std::map brakedelayflags{ + std::map brakedelayflags { { "R", bdelay_R }, { "P", bdelay_P }, { "G", bdelay_G } @@ -8010,7 +7982,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { BrakeDelays = lookup != brakedelays.end() ? lookup->second : - Individual; + 0; lookup = brakedelayflags.find( brakedelay ); BrakeDelayFlag = lookup != brakedelayflags.end() ? @@ -8032,35 +8004,35 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { // brakehandle { std::map brakehandles{ - { "FV4a", FV4a }, - { "test", testH }, - { "D2", D2 }, - { "MHZ_EN57", MHZ_EN57 }, - { "MHZ_K5P", MHZ_K5P }, - { "M394", M394 }, - { "Knorr", Knorr }, - { "Westinghouse", West }, - { "FVel6", FVel6 }, - { "St113", St113 } + { "FV4a", TBrakeHandle::FV4a }, + { "test", TBrakeHandle::testH }, + { "D2", TBrakeHandle::D2 }, + { "MHZ_EN57", TBrakeHandle::MHZ_EN57 }, + { "MHZ_K5P", TBrakeHandle::MHZ_K5P }, + { "M394", TBrakeHandle::M394 }, + { "Knorr", TBrakeHandle::Knorr }, + { "Westinghouse", TBrakeHandle::West }, + { "FVel6", TBrakeHandle::FVel6 }, + { "St113", TBrakeHandle::St113 } }; auto lookup = brakehandles.find( extract_value( "BrakeHandle", line ) ); BrakeHandle = lookup != brakehandles.end() ? lookup->second : - NoHandle; + TBrakeHandle::NoHandle; } // brakelochandle { std::map locbrakehandles{ - { "FD1", FD1 }, - { "Knorr", Knorr }, - { "Westinghouse", West } + { "FD1", TBrakeHandle::FD1 }, + { "Knorr", TBrakeHandle::Knorr }, + { "Westinghouse", TBrakeHandle::West } }; auto lookup = locbrakehandles.find( extract_value( "LocBrakeHandle", line ) ); BrakeLocHandle = lookup != locbrakehandles.end() ? lookup->second : - NoHandle; + TBrakeHandle::NoHandle; } // mbpm @@ -8087,15 +8059,15 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { // localbrake { std::map localbrakes{ - { "ManualBrake", ManualBrake }, - { "PneumaticBrake", PneumaticBrake }, - { "HydraulicBrake", HydraulicBrake } + { "ManualBrake", TLocalBrake::ManualBrake }, + { "PneumaticBrake", TLocalBrake::PneumaticBrake }, + { "HydraulicBrake", TLocalBrake::HydraulicBrake } }; auto lookup = localbrakes.find( extract_value( "LocalBrake", line ) ); LocalBrake = lookup != localbrakes.end() ? lookup->second : - NoBrake; + TLocalBrake::NoBrake; } // mbrake MBrake = ( extract_value( "ManualBrake", line ) == "Yes" ); @@ -8146,69 +8118,70 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { // converter { - std::map starts { - { "Manual", start::manual }, - { "Automatic", start::automatic } + std::map starts { + { "Manual", start_t::manual }, + { "Automatic", start_t::automatic } }; auto lookup = starts.find( extract_value( "ConverterStart", line ) ); ConverterStart = lookup != starts.end() ? lookup->second : - start::manual; + start_t::manual; } extract_value( ConverterStartDelay, "ConverterStartDelay", line, "" ); // compressor { - std::map starts { - { "Manual", start::manual }, - { "Automatic", start::automatic } + std::map starts { + { "Manual", start_t::manual }, + { "Automatic", start_t::automatic } }; auto lookup = starts.find( extract_value( "CompressorStart", line ) ); CompressorStart = lookup != starts.end() ? lookup->second : - start::manual; + start_t::manual; } // fuel pump { - std::map starts { - { "Manual", start::manual }, - { "Automatic", start::automatic } + std::map starts { + { "Manual", start_t::manual }, + { "Automatic", start_t::automatic }, + { "Mixed", start_t::manualwithautofallback } }; auto lookup = starts.find( extract_value( "FuelStart", line ) ); FuelPump.start_type = lookup != starts.end() ? lookup->second : - start::manual; + start_t::manual; } // oil pump { - std::map starts { - { "Manual", start::manual }, - { "Automatic", start::automatic }, - { "Mixed", start::manualwithautofallback } + std::map starts { + { "Manual", start_t::manual }, + { "Automatic", start_t::automatic }, + { "Mixed", start_t::manualwithautofallback } }; auto lookup = starts.find( extract_value( "OilStart", line ) ); OilPump.start_type = lookup != starts.end() ? lookup->second : - start::manual; + start_t::manual; } // water pump { - std::map starts { - { "Manual", start::manual }, - { "Battery", start::battery } + std::map starts { + { "Manual", start_t::manual }, + { "Battery", start_t::battery } }; auto lookup = starts.find( extract_value( "WaterStart", line ) ); WaterPump.start_type = lookup != starts.end() ? lookup->second : - start::manual; + start_t::manual; } } @@ -8266,14 +8239,14 @@ void TMoverParameters::LoadFIZ_Power( std::string const &Line ) { EnginePowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "EnginePower", Line ) ); LoadFIZ_PowerParamsDecode( EnginePowerSource, "", Line ); - if( ( EnginePowerSource.SourceType == Generator ) - && ( EnginePowerSource.GeneratorEngine == WheelsDriven ) ) { + if( ( EnginePowerSource.SourceType == TPowerSource::Generator ) + && ( EnginePowerSource.GeneratorEngine == TEngineType::WheelsDriven ) ) { // perpetuum mobile? ConversionError = 666; } if( Power == 0.0 ) { //jeśli nie ma mocy, np. rozrządcze EZT - EnginePowerSource.SourceType = NotDefined; + EnginePowerSource.SourceType = TPowerSource::NotDefined; } SystemPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "SystemPower", Line ) ); @@ -8304,7 +8277,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { switch( EngineType ) { - case ElectricSeriesMotor: { + case TEngineType::ElectricSeriesMotor: { extract_value( NominalVoltage, "Volt", Input, "" ); extract_value( WindingRes, "WindingRes", Input, "" ); @@ -8316,13 +8289,13 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { nmax /= 60.0; break; } - case WheelsDriven: - case Dumb: { + case TEngineType::WheelsDriven: + case TEngineType::Dumb: { extract_value( Ftmax, "Ftmax", Input, "" ); break; } - case DieselEngine: { + case TEngineType::DieselEngine: { extract_value( dizel_nmin, "nmin", Input, "" ); dizel_nmin /= 60.0; @@ -8374,7 +8347,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { } break; } - case DieselElectric: { //youBy + case TEngineType::DieselElectric: { //youBy extract_value( Ftmax, "Ftmax", Input, "" ); Flat = ( extract_value( "Flat", Input ) == "1" ); @@ -8395,7 +8368,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { extract_value( EngineHeatingRPM, "HeatingRPM", Input, "" ); break; } - case ElectricInductionMotor: { + case TEngineType::ElectricInductionMotor: { RVentnmax = 1.0; extract_value( NominalVoltage, "Volt", Input, "" ); @@ -8432,8 +8405,8 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { } // engine type // NOTE: elements shared by both diesel engine variants; crude but, eh - if( ( EngineType == DieselEngine ) - || ( EngineType == DieselElectric ) ) { + if( ( EngineType == TEngineType::DieselEngine ) + || ( EngineType == TEngineType::DieselElectric ) ) { // oil pump extract_value( OilPump.pressure_minimum, "OilMinPressure", Input, "" ); extract_value( OilPump.pressure_maximum, "OilMaxPressure", Input, "" ); @@ -8479,7 +8452,7 @@ void TMoverParameters::LoadFIZ_MotorParamTable( std::string const &Input ) { switch( EngineType ) { - case DieselEngine: { + case TEngineType::DieselEngine: { extract_value( dizel_minVelfullengage, "minVelfullengage", Input, "" ); extract_value( dizel_engageDia, "engageDia", Input, "" ); @@ -8562,29 +8535,29 @@ void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparamet switch( Powerparameters.SourceType ) { - case NotDefined: - case InternalSource: { + case TPowerSource::NotDefined: + case TPowerSource::InternalSource: { Powerparameters.PowerType = LoadFIZ_PowerDecode( extract_value( Prefix + "PowerType", Line ) ); break; } - case Transducer: { + case TPowerSource::Transducer: { extract_value( Powerparameters.InputVoltage, Prefix + "TransducerInputV", Line, "" ); break; } - case Generator: { + case TPowerSource::Generator: { Powerparameters.GeneratorEngine = LoadFIZ_EngineDecode( extract_value( Prefix + "GeneratorEngine", Line ) ); break; } - case Accumulator: { + case TPowerSource::Accumulator: { extract_value( Powerparameters.RAccumulator.MaxCapacity, Prefix + "Cap", Line, "" ); Powerparameters.RAccumulator.RechargeSource = LoadFIZ_SourceDecode( extract_value( Prefix + "RS", Line ) ); break; } - case CurrentCollector: { + case TPowerSource::CurrentCollector: { auto &collectorparameters = Powerparameters.CollectorParameters; @@ -8610,16 +8583,16 @@ void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparamet extract_value( collectorparameters.MaxPress, "MaxPress", Line, "" ); break; } - case PowerCable: { + case TPowerSource::PowerCable: { Powerparameters.RPowerCable.PowerTrans = LoadFIZ_PowerDecode( extract_value( Prefix + "PowerTrans", Line ) ); - if( Powerparameters.RPowerCable.PowerTrans == SteamPower ) { + if( Powerparameters.RPowerCable.PowerTrans == TPowerType::SteamPower ) { extract_value( Powerparameters.RPowerCable.SteamPressure, Prefix + "SteamPress", Line, "" ); } break; } - case Heater: { + case TPowerSource::Heater: { //jeszcze nie skonczone! break; } @@ -8627,8 +8600,8 @@ void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparamet ; // nothing here } - if( ( Powerparameters.SourceType != Heater ) - && ( Powerparameters.SourceType != InternalSource ) ) { + if( ( Powerparameters.SourceType != TPowerSource::Heater ) + && ( Powerparameters.SourceType != TPowerSource::InternalSource ) ) { extract_value( Powerparameters.MaxVoltage, Prefix + "MaxVoltage", Line, "" ); @@ -8640,53 +8613,53 @@ void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparamet TPowerType TMoverParameters::LoadFIZ_PowerDecode( std::string const &Power ) { std::map powertypes{ - { "BioPower", BioPower }, - { "MechPower", MechPower }, - { "ElectricPower", ElectricPower }, - { "SteamPower", SteamPower } + { "BioPower", TPowerType::BioPower }, + { "MechPower", TPowerType::MechPower }, + { "ElectricPower", TPowerType::ElectricPower }, + { "SteamPower", TPowerType::SteamPower } }; auto lookup = powertypes.find( Power ); return lookup != powertypes.end() ? lookup->second : - NoPower; + TPowerType::NoPower; } TPowerSource TMoverParameters::LoadFIZ_SourceDecode( std::string const &Source ) { std::map powersources{ - { "Transducer", Transducer }, - { "Generator", Generator }, - { "Accu", Accumulator }, - { "CurrentCollector", CurrentCollector }, - { "PowerCable", PowerCable }, - { "Heater", Heater }, - { "Internal", InternalSource } + { "Transducer", TPowerSource::Transducer }, + { "Generator", TPowerSource::Generator }, + { "Accu", TPowerSource::Accumulator }, + { "CurrentCollector", TPowerSource::CurrentCollector }, + { "PowerCable", TPowerSource::PowerCable }, + { "Heater", TPowerSource::Heater }, + { "Internal", TPowerSource::InternalSource } }; auto lookup = powersources.find( Source ); return lookup != powersources.end() ? lookup->second : - NotDefined; + TPowerSource::NotDefined; } -TEngineTypes TMoverParameters::LoadFIZ_EngineDecode( std::string const &Engine ) { +TEngineType TMoverParameters::LoadFIZ_EngineDecode( std::string const &Engine ) { - std::map enginetypes{ - { "ElectricSeriesMotor", ElectricSeriesMotor }, - { "DieselEngine", DieselEngine }, - { "SteamEngine", SteamEngine }, - { "WheelsDriven", WheelsDriven }, - { "Dumb", Dumb }, - { "DieselElectric", DieselElectric }, - { "DumbDE", DieselElectric }, - { "ElectricInductionMotor", ElectricInductionMotor } + std::map enginetypes { + { "ElectricSeriesMotor", TEngineType::ElectricSeriesMotor }, + { "DieselEngine", TEngineType::DieselEngine }, + { "SteamEngine", TEngineType::SteamEngine }, + { "WheelsDriven", TEngineType::WheelsDriven }, + { "Dumb", TEngineType::Dumb }, + { "DieselElectric", TEngineType::DieselElectric }, + { "DumbDE", TEngineType::DieselElectric }, + { "ElectricInductionMotor", TEngineType::ElectricInductionMotor } }; auto lookup = enginetypes.find( Engine ); return lookup != enginetypes.end() ? lookup->second : - None; + TEngineType::None; } // ************************************************************************************************* @@ -8705,14 +8678,14 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) // NOTE: for diesel-powered vehicles we automatically convert legacy "main" power source to more accurate "engine" if( ( CompressorPower == 0 ) - && ( ( EngineType == DieselEngine ) - || ( EngineType == DieselElectric ) ) ) { + && ( ( EngineType == TEngineType::DieselEngine ) + || ( EngineType == TEngineType::DieselElectric ) ) ) { CompressorPower = 3; } // WriteLog("aa = " + AxleArangement + " " + std::string( Pos("o", AxleArangement)) ); - if( ( AxleArangement.find( "o" ) != std::string::npos ) && ( EngineType == ElectricSeriesMotor ) ) { + if( ( AxleArangement.find( "o" ) != std::string::npos ) && ( EngineType == TEngineType::ElectricSeriesMotor ) ) { // test poprawnosci ilosci osi indywidualnie napedzanych OK = ( ( RList[ 1 ].Bn * RList[ 1 ].Mn ) == NPoweredAxles ); // WriteLogSS("aa ok", BoolToYN(OK)); @@ -8723,11 +8696,11 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) Load = 0.0; } - if (BrakeSystem == Individual) - if (BrakeSubsystem != ss_None) + if (BrakeSystem == TBrakeSystem::Individual) + if (BrakeSubsystem != TBrakeSubSystem::ss_None) OK = false; //! - if( ( BrakeVVolume == 0 ) && ( MaxBrakePress[ 3 ] > 0 ) && ( BrakeSystem != Individual ) ) { + if( ( BrakeVVolume == 0 ) && ( MaxBrakePress[ 3 ] > 0 ) && ( BrakeSystem != TBrakeSystem::Individual ) ) { BrakeVVolume = MaxBrakePress[ 3 ] / ( 5.0 - MaxBrakePress[ 3 ] ) * ( BrakeCylRadius * BrakeCylRadius * BrakeCylDist * BrakeCylNo * M_PI ) * 1000; @@ -8739,8 +8712,8 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) switch( BrakeValve ) { - case W: - case K: + case TBrakeValve::W: + case TBrakeValve::K: { WriteLog( "XBT W, K" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); @@ -8750,7 +8723,7 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); break; } - case KE: + case TBrakeValve::KE: { WriteLog( "XBT WKE" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); @@ -8761,10 +8734,10 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); break; } - case NESt3: - case ESt3: - case ESt3AL2: - case ESt4: + case TBrakeValve::NESt3: + case TBrakeValve::ESt3: + case TBrakeValve::ESt3AL2: + case TBrakeValve::ESt4: { WriteLog( "XBT NESt3, ESt3, ESt3AL2, ESt4" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); @@ -8775,14 +8748,14 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); break; } - case LSt: + case TBrakeValve::LSt: { WriteLog( "XBT LSt" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); Hamulec->SetRM( RapidMult ); break; } - case EStED: + case TBrakeValve::EStED: { WriteLog( "XBT EStED" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); @@ -8797,20 +8770,20 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) } break; } - case EP2: + case TBrakeValve::EP2: { WriteLog( "XBT EP2" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); break; } - case CV1: + case TBrakeValve::CV1: { WriteLog( "XBT CV1" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); break; } - case CV1_L_TR: + case TBrakeValve::CV1_L_TR: { WriteLog( "XBT CV1_L_T" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); @@ -8823,28 +8796,28 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) Hamulec->SetASBP( MaxBrakePress[ 4 ] ); switch( BrakeHandle ) { - case FV4a: + case TBrakeHandle::FV4a: Handle = std::make_shared(); break; - case MHZ_EN57: + case TBrakeHandle::MHZ_EN57: Handle = std::make_shared(); break; - case FVel6: + case TBrakeHandle::FVel6: Handle = std::make_shared(); break; - case testH: + case TBrakeHandle::testH: Handle = std::make_shared(); break; - case M394: + case TBrakeHandle::M394: Handle = std::make_shared(); break; - case Knorr: + case TBrakeHandle::Knorr: Handle = std::make_shared(); break; - case St113: + case TBrakeHandle::St113: Handle = std::make_shared(); break; - case MHZ_K5P: + case TBrakeHandle::MHZ_K5P: Handle = std::make_shared(); break; default: @@ -8852,7 +8825,7 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) } switch( BrakeLocHandle ) { - case FD1: + case TBrakeHandle::FD1: { LocHandle = std::make_shared(); LocHandle->Init( MaxBrakePress[ 0 ] ); @@ -8862,7 +8835,7 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) } break; } - case Knorr: + case TBrakeHandle::Knorr: { LocHandle = std::make_shared(); LocHandle->Init( MaxBrakePress[ 0 ] ); @@ -8901,7 +8874,7 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) 0.0 ); PipePress = CntrlPipePress; BrakePress = 0.0; - LocalBrakePos = 0; + LocalBrakePosA = 0.0; if( CabNo == 0 ) BrakeCtrlPos = static_cast( Handle->GetPos( bh_NP ) ); else @@ -8932,7 +8905,7 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) PipePress = LowPipePress; PipeBrakePress = MaxBrakePress[ 3 ] * 0.5; BrakePress = MaxBrakePress[ 3 ] * 0.5; - LocalBrakePos = 0; + LocalBrakePosA = 0.0; BrakeCtrlPos = static_cast( Handle->GetPos( bh_NP ) ); LimPipePress = LowPipePress; } @@ -8940,8 +8913,8 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) ActFlowSpeed = 0.0; BrakeCtrlPosR = BrakeCtrlPos; - if( BrakeLocHandle == Knorr ) - LocalBrakePos = 5; + if( BrakeLocHandle == TBrakeHandle::Knorr ) + LocalBrakePosA = 0.5; Pipe->CreatePress( PipePress ); Pipe2->CreatePress( ScndPipePress ); @@ -9168,7 +9141,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C } else if( Command == "WaterPumpSwitch" ) { - if( WaterPump.start_type != start::battery ) { + if( WaterPump.start_type != start_t::battery ) { // automatic fuel pump ignores 'manual' state commands WaterPump.is_enabled = ( CValue1 == 1 ); } @@ -9204,14 +9177,14 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } else if (Command == "FuelPumpSwitch") { - if( FuelPump.start_type != start::automatic ) { + if( FuelPump.start_type != start_t::automatic ) { // automatic fuel pump ignores 'manual' state commands FuelPump.is_enabled = ( CValue1 == 1 ); } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } else if (Command == "OilPumpSwitch") { - if( OilPump.start_type != start::automatic ) { + if( OilPump.start_type != start_t::automatic ) { // automatic pump ignores 'manual' state commands OilPump.is_enabled = ( CValue1 == 1 ); } @@ -9221,8 +9194,8 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C { if (CValue1 == 1) { - if( ( EngineType == DieselEngine ) - || ( EngineType == DieselElectric ) ) { + if( ( EngineType == TEngineType::DieselEngine ) + || ( EngineType == TEngineType::DieselElectric ) ) { dizel_startup = true; } else { @@ -9271,7 +9244,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C } else if (Command == "FuseSwitch") { - if (((EngineType == ElectricSeriesMotor) || (EngineType == DieselElectric)) && FuseFlag && + if (((EngineType == TEngineType::ElectricSeriesMotor) || (EngineType == TEngineType::DieselElectric)) && FuseFlag && (CValue1 == 1) && (MainCtrlActualPos == 0) && (ScndCtrlActualPos == 0) && Mains) /* if (EngineType=ElectricSeriesMotor) and (CValue1=1) and (MainCtrlActualPos=0) and (ScndCtrlActualPos=0) and Mains then*/ @@ -9309,16 +9282,16 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C // end else if (Command == "CompressorSwitch") /*NBMX*/ { - if( CompressorStart == start::manual ) { + if( CompressorStart == start_t::manual ) { CompressorAllow = ( CValue1 == 1 ); } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } else if (Command == "DoorOpen") /*NBMX*/ { // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów - if( ( DoorOpenCtrl == control::conductor ) - || ( DoorOpenCtrl == control::driver ) - || ( DoorOpenCtrl == control::mixed ) ) { + if( ( DoorOpenCtrl == control_t::conductor ) + || ( DoorOpenCtrl == control_t::driver ) + || ( DoorOpenCtrl == control_t::mixed ) ) { // ignore remote command if the door is only operated locally if( CValue2 > 0 ) { // normalne ustawienie pojazdu @@ -9355,9 +9328,9 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C } else if (Command == "DoorClose") /*NBMX*/ { // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów - if( ( DoorCloseCtrl == control::conductor ) - || ( DoorCloseCtrl == control::driver ) - || ( DoorCloseCtrl == control::mixed ) ) { + if( ( DoorCloseCtrl == control_t::conductor ) + || ( DoorCloseCtrl == control_t::driver ) + || ( DoorCloseCtrl == control_t::mixed ) ) { // ignore remote command if the door is only operated locally if( CValue2 > 0 ) { // normalne ustawienie pojazdu @@ -9528,7 +9501,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C } else if (Command == "Sandbox") { - OK = Sandbox( CValue1 == 1, range::local ); + OK = Sandbox( CValue1 == 1, range_t::local ); } else if (Command == "CabSignal") /*SHP,Indusi*/ { // Ra: to powinno działać tylko w członie obsadzonym @@ -9581,7 +9554,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C } else if (Command == "SpeedCntrl") { - if ((EngineType == ElectricInductionMotor)) + if ((EngineType == TEngineType::ElectricInductionMotor)) ScndCtrlActualPos = static_cast(round(CValue1)); OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } diff --git a/MemCell.cpp b/MemCell.cpp index d63764b9..3da41fb5 100644 --- a/MemCell.cpp +++ b/MemCell.cpp @@ -49,37 +49,37 @@ TCommandType TMemCell::CommandCheck() { // rozpoznanie komendy if( szText == "SetVelocity" ) // najpopularniejsze { - eCommand = cm_SetVelocity; + eCommand = TCommandType::cm_SetVelocity; bCommand = false; // ta komenda nie jest wysyłana } else if( szText == "ShuntVelocity" ) // w tarczach manewrowych { - eCommand = cm_ShuntVelocity; + eCommand = TCommandType::cm_ShuntVelocity; bCommand = false; // ta komenda nie jest wysyłana } else if( szText == "Change_direction" ) // zdarza się { - eCommand = cm_ChangeDirection; + eCommand = TCommandType::cm_ChangeDirection; bCommand = true; // do wysłania } else if( szText == "OutsideStation" ) // zdarza się { - eCommand = cm_OutsideStation; + eCommand = TCommandType::cm_OutsideStation; bCommand = false; // tego nie powinno być w komórce } else if( szText.compare( 0, 19, "PassengerStopPoint:" ) == 0 ) // porównanie początków { - eCommand = cm_PassengerStopPoint; + eCommand = TCommandType::cm_PassengerStopPoint; bCommand = false; // tego nie powinno być w komórce } else if( szText == "SetProximityVelocity" ) // nie powinno tego być { - eCommand = cm_SetProximityVelocity; + eCommand = TCommandType::cm_SetProximityVelocity; bCommand = false; // ta komenda nie jest wysyłana } else { - eCommand = cm_Unknown; // ciąg nierozpoznany (nie jest komendą) + eCommand = TCommandType::cm_Unknown; // ciąg nierozpoznany (nie jest komendą) bCommand = true; // do wysłania } return eCommand; @@ -139,11 +139,11 @@ bool TMemCell::Compare( std::string const &szTestText, double const fTestValue1, bool TMemCell::IsVelocity() const { // sprawdzenie, czy event odczytu tej komórki ma być do skanowania, czy do kolejkowania - if (eCommand == cm_SetVelocity) + if (eCommand == TCommandType::cm_SetVelocity) return true; - if (eCommand == cm_ShuntVelocity) + if (eCommand == TCommandType::cm_ShuntVelocity) return true; - return (eCommand == cm_SetProximityVelocity); + return (eCommand == TCommandType::cm_SetProximityVelocity); }; void TMemCell::StopCommandSent() diff --git a/MemCell.h b/MemCell.h index bdf5004f..5614cfaa 100644 --- a/MemCell.h +++ b/MemCell.h @@ -64,7 +64,7 @@ private: double fValue1 { 0.0 }; double fValue2 { 0.0 }; // other - TCommandType eCommand { cm_Unknown }; + TCommandType eCommand { TCommandType::cm_Unknown }; bool bCommand { false }; // czy zawiera komendę dla zatrzymanego AI TEvent *OnSent { nullptr }; // event dodawany do kolejki po wysłaniu komendy zatrzymującej skład }; diff --git a/Model3d.cpp b/Model3d.cpp index 70205db2..1d92112b 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -20,6 +20,7 @@ Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others #include "utilities.h" #include "renderer.h" #include "Timer.h" +#include "simulationtime.h" #include "mtable.h" #include "sn_utils.h" #include "World.h" @@ -110,22 +111,6 @@ int TSubModel::SeekFaceNormal(std::vector const &Masks, int const float emm1[] = { 1, 1, 1, 0 }; float emm2[] = { 0, 0, 0, 1 }; -inline double readIntAsDouble(cParser &parser, int base = 255) -{ - int value = parser.getToken(false); - return (static_cast(value) / base); -}; - -template inline void readColor(cParser &parser, ColorT *color) -{ - double discard; - parser.getTokens(4, false); - parser >> discard >> color[0] >> color[1] >> color[2]; - color[ 0 ] /= 255.0; - color[ 1 ] /= 255.0; - color[ 2 ] /= 255.0; -}; - inline void readColor(cParser &parser, glm::vec4 &color) { int discard; @@ -195,41 +180,41 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic { iFlags |= 0x4000; // jak animacja, to trzeba przechowywać macierz zawsze if (type == "seconds_jump") - b_Anim = b_aAnim = at_SecondsJump; // sekundy z przeskokiem + b_Anim = b_aAnim = TAnimType::at_SecondsJump; // sekundy z przeskokiem else if (type == "minutes_jump") - b_Anim = b_aAnim = at_MinutesJump; // minuty z przeskokiem + b_Anim = b_aAnim = TAnimType::at_MinutesJump; // minuty z przeskokiem else if (type == "hours_jump") - b_Anim = b_aAnim = at_HoursJump; // godziny z przeskokiem + b_Anim = b_aAnim = TAnimType::at_HoursJump; // godziny z przeskokiem else if (type == "hours24_jump") - b_Anim = b_aAnim = at_Hours24Jump; // godziny z przeskokiem + b_Anim = b_aAnim = TAnimType::at_Hours24Jump; // godziny z przeskokiem else if (type == "seconds") - b_Anim = b_aAnim = at_Seconds; // minuty płynnie + b_Anim = b_aAnim = TAnimType::at_Seconds; // minuty płynnie else if (type == "minutes") - b_Anim = b_aAnim = at_Minutes; // minuty płynnie + b_Anim = b_aAnim = TAnimType::at_Minutes; // minuty płynnie else if (type == "hours") - b_Anim = b_aAnim = at_Hours; // godziny płynnie + b_Anim = b_aAnim = TAnimType::at_Hours; // godziny płynnie else if (type == "hours24") - b_Anim = b_aAnim = at_Hours24; // godziny płynnie + b_Anim = b_aAnim = TAnimType::at_Hours24; // godziny płynnie else if (type == "billboard") - b_Anim = b_aAnim = at_Billboard; // obrót w pionie do kamery + b_Anim = b_aAnim = TAnimType::at_Billboard; // obrót w pionie do kamery else if (type == "wind") - b_Anim = b_aAnim = at_Wind; // ruch pod wpływem wiatru + b_Anim = b_aAnim = TAnimType::at_Wind; // ruch pod wpływem wiatru else if (type == "sky") - b_Anim = b_aAnim = at_Sky; // aniamacja nieba + b_Anim = b_aAnim = TAnimType::at_Sky; // aniamacja nieba else if (type == "ik") - b_Anim = b_aAnim = at_IK; // IK: zadający + b_Anim = b_aAnim = TAnimType::at_IK; // IK: zadający else if (type == "ik11") - b_Anim = b_aAnim = at_IK11; // IK: kierunkowany + b_Anim = b_aAnim = TAnimType::at_IK11; // IK: kierunkowany else if (type == "ik21") - b_Anim = b_aAnim = at_IK21; // IK: kierunkowany + b_Anim = b_aAnim = TAnimType::at_IK21; // IK: kierunkowany else if (type == "ik22") - b_Anim = b_aAnim = at_IK22; // IK: kierunkowany + b_Anim = b_aAnim = TAnimType::at_IK22; // IK: kierunkowany else if (type == "digital") - b_Anim = b_aAnim = at_Digital; // licznik mechaniczny + b_Anim = b_aAnim = TAnimType::at_Digital; // licznik mechaniczny else if (type == "digiclk") - b_Anim = b_aAnim = at_DigiClk; // zegar cyfrowy + b_Anim = b_aAnim = TAnimType::at_DigiClk; // zegar cyfrowy else - b_Anim = b_aAnim = at_Undefined; // nieznana forma animacji + b_Anim = b_aAnim = TAnimType::at_Undefined; // nieznana forma animacji } } if (eType < TP_ROTATOR) @@ -284,19 +269,16 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic else if (eType < TP_ROTATOR) { std::string discard; - parser.getTokens(5, false); + parser.getTokens(6, false); parser >> discard >> bWire >> discard >> fWireSize - >> discard; + >> discard >> Opacity; // wymagane jest 0 dla szyb, 100 idzie w nieprzezroczyste - Opacity = readIntAsDouble(parser, 100.0f); - if (Opacity > 1.0f) - Opacity *= 0.01f; // w 2013 był błąd i aby go obejść, trzeba było wpisać 10000.0 -/* - if ((Global.iConvertModels & 1) == 0) // dla zgodności wstecz - Opacity = 0.0; // wszystko idzie w przezroczyste albo zależnie od tekstury -*/ + if( Opacity > 1.f ) { + Opacity = std::min( 1.f, Opacity * 0.01f ); + } + if (!parser.expectToken("map:")) Error("Model map parse failure!"); std::string material = parser.getToken(); @@ -797,8 +779,8 @@ void TSubModel::SetRotate(float3 vNewRotateAxis, float fNewAngle) f_Angle = fNewAngle; if (fNewAngle != 0.0) { - b_Anim = at_Rotate; - b_aAnim = at_Rotate; + b_Anim = TAnimType::at_Rotate; + b_aAnim = TAnimType::at_Rotate; } iAnimOwner = iInstance; // zapamiętanie czyja jest animacja } @@ -808,8 +790,8 @@ void TSubModel::SetRotateXYZ(float3 vNewAngles) // podane kąty wokół osi // lokalnego układu v_Angles = vNewAngles; - b_Anim = at_RotateXYZ; - b_aAnim = at_RotateXYZ; + b_Anim = TAnimType::at_RotateXYZ; + b_aAnim = TAnimType::at_RotateXYZ; iAnimOwner = iInstance; // zapamiętanie czyja jest animacja } @@ -820,16 +802,16 @@ void TSubModel::SetRotateXYZ( Math3D::vector3 vNewAngles) v_Angles.x = vNewAngles.x; v_Angles.y = vNewAngles.y; v_Angles.z = vNewAngles.z; - b_Anim = at_RotateXYZ; - b_aAnim = at_RotateXYZ; + b_Anim = TAnimType::at_RotateXYZ; + b_aAnim = TAnimType::at_RotateXYZ; iAnimOwner = iInstance; // zapamiętanie czyja jest animacja } void TSubModel::SetTranslate(float3 vNewTransVector) { // przesunięcie submodelu (np. w kabinie) v_TransVector = vNewTransVector; - b_Anim = at_Translate; - b_aAnim = at_Translate; + b_Anim = TAnimType::at_Translate; + b_aAnim = TAnimType::at_Translate; iAnimOwner = iInstance; // zapamiętanie czyja jest animacja } @@ -838,8 +820,8 @@ void TSubModel::SetTranslate( Math3D::vector3 vNewTransVector) v_TransVector.x = vNewTransVector.x; v_TransVector.y = vNewTransVector.y; v_TransVector.z = vNewTransVector.z; - b_Anim = at_Translate; - b_aAnim = at_Translate; + b_Anim = TAnimType::at_Translate; + b_aAnim = TAnimType::at_Translate; iAnimOwner = iInstance; // zapamiętanie czyja jest animacja } @@ -902,17 +884,17 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a) { // wykonanie animacji niezależnie od renderowania switch (a) { // korekcja położenia, jeśli submodel jest animowany - case at_Translate: // Ra: było "true" + case TAnimType::at_Translate: // Ra: było "true" if (iAnimOwner != iInstance) break; // cudza animacja m = glm::translate(m, glm::vec3(v_TransVector.x, v_TransVector.y, v_TransVector.z)); break; - case at_Rotate: // Ra: było "true" + case TAnimType::at_Rotate: // Ra: było "true" if (iAnimOwner != iInstance) break; // cudza animacja m = glm::rotate(m, glm::radians(f_Angle), glm::vec3(v_RotateAxis.x, v_RotateAxis.y, v_RotateAxis.z)); break; - case at_RotateXYZ: + case TAnimType::at_RotateXYZ: if (iAnimOwner != iInstance) break; // cudza animacja m = glm::translate(m, glm::vec3(v_TransVector.x, v_TransVector.y, v_TransVector.z)); @@ -920,33 +902,33 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a) m = glm::rotate(m, glm::radians(v_Angles.y), glm::vec3(0.0f, 1.0f, 0.0f)); m = glm::rotate(m, glm::radians(v_Angles.z), glm::vec3(0.0f, 0.0f, 1.0f)); break; - case at_SecondsJump: // sekundy z przeskokiem + case TAnimType::at_SecondsJump: // sekundy z przeskokiem m = glm::rotate(m, glm::radians(simulation::Time.data().wSecond * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_MinutesJump: // minuty z przeskokiem + case TAnimType::at_MinutesJump: // minuty z przeskokiem m = glm::rotate(m, glm::radians(simulation::Time.data().wMinute * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_HoursJump: // godziny skokowo 12h/360° + case TAnimType::at_HoursJump: // godziny skokowo 12h/360° m = glm::rotate(m, glm::radians(simulation::Time.data().wHour * 30.0f * 0.5f), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_Hours24Jump: // godziny skokowo 24h/360° + case TAnimType::at_Hours24Jump: // godziny skokowo 24h/360° m = glm::rotate(m, glm::radians(simulation::Time.data().wHour * 15.0f * 0.25f), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_Seconds: // sekundy płynnie + case TAnimType::at_Seconds: // sekundy płynnie m = glm::rotate(m, glm::radians((float)simulation::Time.second() * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_Minutes: // minuty płynnie + case TAnimType::at_Minutes: // minuty płynnie m = glm::rotate(m, glm::radians(simulation::Time.data().wMinute * 6.0f + (float)simulation::Time.second() * 0.1f), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_Hours: // godziny płynnie 12h/360° + case TAnimType::at_Hours: // godziny płynnie 12h/360° // glRotatef(GlobalTime->hh*30.0+GlobalTime->mm*0.5+GlobalTime->mr/120.0,0.0,1.0,0.0); m = glm::rotate(m, glm::radians(2.0f * (float)Global.fTimeAngleDeg), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_Hours24: // godziny płynnie 24h/360° + case TAnimType::at_Hours24: // godziny płynnie 24h/360° // glRotatef(GlobalTime->hh*15.0+GlobalTime->mm*0.25+GlobalTime->mr/240.0,0.0,1.0,0.0); m = glm::rotate(m, glm::radians((float)Global.fTimeAngleDeg), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_Billboard: // obrót w pionie do kamery + case TAnimType::at_Billboard: // obrót w pionie do kamery { Math3D::matrix4x4 mat; mat.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) ); float3 gdzie = float3(mat[3][0], mat[3][1], mat[3][2]); // początek układu współrzędnych submodelu względem kamery @@ -955,18 +937,18 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a) m = glm::rotate(m, (float)atan2(gdzie.x, gdzie.y), glm::vec3(0.0f, 1.0f, 0.0f)); // jedynie obracamy w pionie o kąt } break; - case at_Wind: // ruch pod wpływem wiatru (wiatr będziemy liczyć potem...) + case TAnimType::at_Wind: // ruch pod wpływem wiatru (wiatr będziemy liczyć potem...) m = glm::rotate(m, glm::radians(1.5f * (float)sin(M_PI * simulation::Time.second() / 6.0)), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_Sky: // animacja nieba + case TAnimType::at_Sky: // animacja nieba m = glm::rotate(m, glm::radians((float)Global.fLatitudeDeg), glm::vec3(0.0f, 1.0f, 0.0f)); // ustawienie osi OY na północ m = glm::rotate(m, glm::radians((float)-fmod(Global.fTimeAngleDeg, 360.0)), glm::vec3(0.0f, 1.0f, 0.0f)); break; - case at_IK11: // ostatni element animacji szkieletowej (podudzie, stopa) + case TAnimType::at_IK11: // ostatni element animacji szkieletowej (podudzie, stopa) m = glm::rotate(m, glm::radians(v_Angles.z), glm::vec3(0.0f, 1.0f, 0.0f)); // obrót względem osi pionowej (azymut) m = glm::rotate(m, glm::radians(v_Angles.x), glm::vec3(1.0f, 0.0f, 0.0f)); // obrót względem poziomu (deklinacja) break; - case at_DigiClk: // animacja zegara cyfrowego + case TAnimType::at_DigiClk: // animacja zegara cyfrowego { // ustawienie animacji w submodelach potomnych TSubModel *sm = ChildGet(); do diff --git a/Model3d.h b/Model3d.h index 61b8f08c..9028a160 100644 --- a/Model3d.h +++ b/Model3d.h @@ -21,7 +21,7 @@ const int TP_FREESPOTLIGHT = 257; const int TP_STARS = 258; const int TP_TEXT = 259; -enum TAnimType // rodzaj animacji +enum class TAnimType // rodzaj animacji { at_None, // brak at_Rotate, // obrót względem wektora o kąt @@ -38,13 +38,13 @@ enum TAnimType // rodzaj animacji at_Billboard, // obrót w pionie do kamery at_Wind, // ruch pod wpływem wiatru at_Sky, // animacja nieba - at_IK = 0x100, // odwrotna kinematyka - submodel sterujący (np. staw skokowy) - at_IK11 = 0x101, // odwrotna kinematyka - submodel nadrzędny do sterowango (np. stopa) - at_IK21 = 0x102, // odwrotna kinematyka - submodel nadrzędny do sterowango (np. podudzie) - at_IK22 = 0x103, // odwrotna kinematyka - submodel nadrzędny do nadrzędnego sterowango (np. udo) - at_Digital = 0x200, // dziesięciocyfrowy licznik mechaniczny (z cylindrami) - at_DigiClk = 0x201, // zegar cyfrowy jako licznik na dziesięciościanach - at_Undefined = 0x800000FF // animacja chwilowo nieokreślona + at_IK, // odwrotna kinematyka - submodel sterujący (np. staw skokowy) + at_IK11, // odwrotna kinematyka - submodel nadrzędny do sterowango (np. stopa) + at_IK21, // odwrotna kinematyka - submodel nadrzędny do sterowango (np. podudzie) + at_IK22, // odwrotna kinematyka - submodel nadrzędny do nadrzędnego sterowango (np. udo) + at_Digital, // dziesięciocyfrowy licznik mechaniczny (z cylindrami) + at_DigiClk, // zegar cyfrowy jako licznik na dziesięciościanach + at_Undefined // animacja chwilowo nieokreślona }; namespace scene { @@ -55,10 +55,12 @@ class TModel3d; class TSubModel { // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów - friend class opengl_renderer; - friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy - friend class TDynamicObject; // temporary etc - friend class scene::shape_node; // temporary etc + //m7todo: zrobić normalną serializację + + friend opengl_renderer; + friend TModel3d; // temporary workaround. TODO: clean up class content/hierarchy + friend TDynamicObject; // temporary etc + friend scene::shape_node; // temporary etc public: enum normalization { @@ -73,7 +75,7 @@ private: int eType{ TP_ROTATOR }; // Ra: modele binarne dają więcej możliwości niż mesh złożony z trójkątów int iName{ -1 }; // numer łańcucha z nazwą submodelu, albo -1 gdy anonimowy public: // chwilowo - TAnimType b_Anim{ at_None }; + TAnimType b_Anim{ TAnimType::at_None }; private: uint32_t iFlags{ 0x0200 }; // bit 9=1: submodel został utworzony a nie ustawiony na wczytany plik @@ -136,7 +138,7 @@ public: // chwilowo gfx::vertex_array Vertices; float m_boundingradius { 0 }; size_t iAnimOwner{ 0 }; // roboczy numer egzemplarza, który ustawił animację - TAnimType b_aAnim{ at_None }; // kody animacji oddzielnie, bo zerowane + TAnimType b_aAnim{ TAnimType::at_None }; // kody animacji oddzielnie, bo zerowane float4x4 *mAnimMatrix{ nullptr }; // macierz do animacji kwaternionowych (należy do AnimContainer) TSubModel **smLetter{ nullptr }; // wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D) TSubModel *Parent{ nullptr }; // nadrzędny, np. do wymnażania macierzy @@ -219,7 +221,7 @@ public: class TModel3d { - friend class opengl_renderer; + friend opengl_renderer; private: TSubModel *Root; // drzewo submodeli diff --git a/Segment.cpp b/Segment.cpp index ecc4bf0a..f0a25276 100644 --- a/Segment.cpp +++ b/Segment.cpp @@ -17,7 +17,7 @@ http://mozilla.org/MPL/2.0/. #include "renderer.h" void -segment_data::deserialize( cParser &Input, Math3D::vector3 const &Offset ) { +segment_data::deserialize( cParser &Input, glm::dvec3 const &Offset ) { points[ segment_data::point::start ] = LoadPoint( Input ) + Offset; Input.getTokens(); diff --git a/Segment.h b/Segment.h index 094820c7..7387b507 100644 --- a/Segment.h +++ b/Segment.h @@ -29,7 +29,7 @@ struct segment_data { // constructors segment_data() = default; // methods - void deserialize( cParser &Input, Math3D::vector3 const &Offset ); + void deserialize( cParser &Input, glm::dvec3 const &Offset ); }; class TSegment diff --git a/Track.cpp b/Track.cpp index a517b7d4..74a8d6f8 100644 --- a/Track.cpp +++ b/Track.cpp @@ -181,7 +181,7 @@ TTrack * TTrack::Create400m(int what, double dx) trk->Segment->Init( Math3D::vector3( -dx, 0, 0 ), Math3D::vector3( -dx, 0, 400 ), 10.0, 0, 0 ); // prosty trk->location( glm::dvec3{ -dx, 0, 200 } ); //środek, aby się mogło wyświetlić simulation::Paths.insert( trk ); - simulation::Region->insert_path( trk, scene::scratch_data() ); + simulation::Region->insert( trk ); return trk; }; @@ -275,11 +275,11 @@ TTrack * TTrack::NullCreate(int dir) // trzeba jeszcze dodać do odpowiedniego segmentu, aby się renderowały z niego pojazdy trk->location( glm::dvec3{ 0.5 * ( p1 + p2 ) } ); //środek, aby się mogło wyświetlić simulation::Paths.insert( trk ); - simulation::Region->insert_path( trk, scene::scratch_data() ); + simulation::Region->insert( trk ); if( trk2 ) { trk2->location( trk->location() ); // ten sam środek jest simulation::Paths.insert( trk2 ); - simulation::Region->insert_path( trk2, scene::scratch_data() ); + simulation::Region->insert( trk2 ); } return trk; }; @@ -345,7 +345,7 @@ void TTrack::ConnectNextNext(TTrack *pTrack, int typ) } } -void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin) +void TTrack::Load(cParser *parser, glm::dvec3 const &pOrigin) { // pobranie obiektu trajektorii ruchu Math3D::vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań double a1, a2, r1, r2, r3, r4; @@ -864,11 +864,11 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin) } // calculate path location - m_area.center = ( glm::dvec3{ ( + location( ( CurrentSegment()->FastGetPoint_0() + CurrentSegment()->FastGetPoint( 0.5 ) + CurrentSegment()->FastGetPoint_1() ) - / 3.0 } ); + / 3.0 ); } bool TTrack::AssignEvents() { diff --git a/Track.h b/Track.h index 0627647b..b9b803d6 100644 --- a/Track.h +++ b/Track.h @@ -126,9 +126,9 @@ private: // trajektoria ruchu - opakowanie class TTrack : public scene::basic_node { - friend class opengl_renderer; + friend opengl_renderer; // NOTE: temporary arrangement - friend class ui_layer; + friend ui_layer; private: TIsolated * pIsolated = nullptr; // obwód izolowany obsługujący zajęcia/zwolnienia grupy torów @@ -170,20 +170,7 @@ public: m_events1, m_events2; bool m_events { false }; // Ra: flaga informująca o obecności eventów -/* - TEvent *evEventall0 = nullptr; // McZapkie-140302: wyzwalany gdy pojazd stoi - TEvent *evEventall1 = nullptr; - TEvent *evEventall2 = nullptr; - TEvent *evEvent0 = nullptr; // McZapkie-280503: wyzwalany tylko gdy headdriver - TEvent *evEvent1 = nullptr; - TEvent *evEvent2 = nullptr; - std::string asEventall0Name; // nazwy eventów - std::string asEventall1Name; - std::string asEventall2Name; - std::string asEvent0Name; - std::string asEvent1Name; - std::string asEvent2Name; -*/ + int iNextDirection = 0; // 0:Point1, 1:Point2, 3:do odchylonego na zwrotnicy int iPrevDirection = 0; // domyślnie wirtualne odcinki dołączamy stroną od Point1 TTrackType eType = tt_Normal; // domyślnie zwykły @@ -246,7 +233,7 @@ public: SwitchExtension != nullptr ? SwitchExtension->iRoads - 1 : 1 ); } - void Load(cParser *parser, Math3D::vector3 pOrigin); + void Load(cParser *parser, glm::dvec3 const &pOrigin); bool AssignEvents(); bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus); void QueueEvents( event_sequence const &Events, TDynamicObject const *Owner ); diff --git a/Traction.h b/Traction.h index 0059528e..1b49472a 100644 --- a/Traction.h +++ b/Traction.h @@ -21,7 +21,7 @@ class TTractionPowerSource; class TTraction : public scene::basic_node { - friend class opengl_renderer; + friend opengl_renderer; public: // na razie TTractionPowerSource *psPower[ 2 ] { nullptr, nullptr }; // najbliższe zasilacze z obu kierunków diff --git a/Train.cpp b/Train.cpp index 56e716f1..af228f59 100644 --- a/Train.cpp +++ b/Train.cpp @@ -19,6 +19,7 @@ http://mozilla.org/MPL/2.0/. #include "simulation.h" #include "World.h" #include "Camera.h" +#include "simulationtime.h" #include "Logs.h" #include "MdlMngr.h" #include "Timer.h" @@ -27,6 +28,12 @@ http://mozilla.org/MPL/2.0/. #include "Console.h" #include "sound.h" +namespace input { + +extern user_command command; + +} + void control_mapper::insert( TGauge const &Gauge, std::string const &Label ) { @@ -599,7 +606,7 @@ bool TTrain::is_eztoer() const { return ( ( mvControlled->TrainType == dt_EZT ) - && ( mvOccupied->BrakeSubsystem == ss_ESt ) + && ( mvOccupied->BrakeSubsystem == TBrakeSubSystem::ss_ESt ) && ( mvControlled->Battery == true ) && ( mvControlled->EpFuse == true ) && ( mvControlled->ActiveDir != 0 ) ); // od yB @@ -768,7 +775,7 @@ void TTrain::OnCommand_secondcontrollerincrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { // on press or hold - if( ( Train->mvControlled->EngineType == DieselElectric ) + if( ( Train->mvControlled->EngineType == TEngineType::DieselElectric ) && ( true == Train->mvControlled->ShuntMode ) ) { Train->mvControlled->AnPos = clamp( Train->mvControlled->AnPos + 0.025, @@ -784,7 +791,7 @@ void TTrain::OnCommand_secondcontrollerincreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { // on press or hold - if( ( Train->mvControlled->EngineType == DieselElectric ) + if( ( Train->mvControlled->EngineType == TEngineType::DieselElectric ) && ( true == Train->mvControlled->ShuntMode ) ) { Train->mvControlled->AnPos = 1.0; } @@ -836,7 +843,7 @@ void TTrain::OnCommand_secondcontrollerdecrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { // on press or hold - if( ( Train->mvControlled->EngineType == DieselElectric ) + if( ( Train->mvControlled->EngineType == TEngineType::DieselElectric ) && ( true == Train->mvControlled->ShuntMode ) ) { Train->mvControlled->AnPos = clamp( Train->mvControlled->AnPos - 0.025, @@ -852,7 +859,7 @@ void TTrain::OnCommand_secondcontrollerdecreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { // on press or hold - if( ( Train->mvControlled->EngineType == DieselElectric ) + if( ( Train->mvControlled->EngineType == TEngineType::DieselElectric ) && ( true == Train->mvControlled->ShuntMode ) ) { Train->mvControlled->AnPos = 0.0; } @@ -881,7 +888,7 @@ void TTrain::OnCommand_independentbrakeincrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { - if( Train->mvOccupied->LocalBrake != ManualBrake ) { + if( Train->mvOccupied->LocalBrake != TLocalBrake::ManualBrake ) { Train->mvOccupied->IncLocalBrakeLevel( 1 ); } } @@ -891,8 +898,8 @@ void TTrain::OnCommand_independentbrakeincreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { - if( Train->mvOccupied->LocalBrake != ManualBrake ) { - Train->mvOccupied->IncLocalBrakeLevel( 2 ); + if( Train->mvOccupied->LocalBrake != TLocalBrake::ManualBrake ) { + Train->mvOccupied->IncLocalBrakeLevel( LocalBrakePosNo ); } } } @@ -901,10 +908,10 @@ void TTrain::OnCommand_independentbrakedecrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { - if( ( Train->mvOccupied->LocalBrake != ManualBrake ) + if( ( Train->mvOccupied->LocalBrake != TLocalBrake::ManualBrake ) // Ra 1014-06: AI potrafi zahamować pomocniczym mimo jego braku - odhamować jakoś trzeba // TODO: sort AI out so it doesn't do things it doesn't have equipment for - || ( Train->mvOccupied->LocalBrakePos != 0 ) ) { + || ( Train->mvOccupied->LocalBrakePosA > 0 ) ) { Train->mvOccupied->DecLocalBrakeLevel( 1 ); } } @@ -914,11 +921,11 @@ void TTrain::OnCommand_independentbrakedecreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { - if( ( Train->mvOccupied->LocalBrake != ManualBrake ) + if( ( Train->mvOccupied->LocalBrake != TLocalBrake::ManualBrake ) // Ra 1014-06: AI potrafi zahamować pomocniczym mimo jego braku - odhamować jakoś trzeba // TODO: sort AI out so it doesn't do things it doesn't have equipment for - || ( Train->mvOccupied->LocalBrakePos != 0 ) ) { - Train->mvOccupied->DecLocalBrakeLevel( 2 ); + || ( Train->mvOccupied->LocalBrakePosA > 0 ) ) { + Train->mvOccupied->DecLocalBrakeLevel( LocalBrakePosNo ); } } } @@ -927,7 +934,7 @@ void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &C Train->mvControlled->LocalBrakePosA = ( clamp( - reinterpret_cast( Command.param1 ), + Command.param1, 0.0, 1.0 ) ); /* Train->mvControlled->LocalBrakePos = ( @@ -936,7 +943,7 @@ void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &C 0.0, LocalBrakePosNo, clamp( - reinterpret_cast( Command.param1 ), + Command.param1, 0.0, 1.0 ) ) ) ); */ } @@ -947,9 +954,9 @@ void TTrain::OnCommand_independentbrakebailoff( TTrain *Train, command_data cons // TODO: check if this set of conditions can be simplified. // it'd be more flexible to have an attribute indicating whether bail off position is supported if( ( Train->mvControlled->TrainType != dt_EZT ) - && ( ( Train->mvControlled->EngineType == ElectricSeriesMotor ) - || ( Train->mvControlled->EngineType == DieselElectric ) - || ( Train->mvControlled->EngineType == ElectricInductionMotor ) ) + && ( ( Train->mvControlled->EngineType == TEngineType::ElectricSeriesMotor ) + || ( Train->mvControlled->EngineType == TEngineType::DieselElectric ) + || ( Train->mvControlled->EngineType == TEngineType::ElectricInductionMotor ) ) && ( Train->mvOccupied->BrakeCtrlPosNo > 0 ) ) { if( Command.action == GLFW_PRESS ) { @@ -985,22 +992,22 @@ void TTrain::OnCommand_independentbrakebailoff( TTrain *Train, command_data cons } void TTrain::OnCommand_trainbrakeincrease( TTrain *Train, command_data const &Command ) { - if (Command.action == GLFW_REPEAT && Train->mvOccupied->BrakeHandle == FV4a) + if (Command.action == GLFW_REPEAT && Train->mvOccupied->BrakeHandle == TBrakeHandle::FV4a) Train->mvOccupied->BrakeLevelAdd( Global.brake_speed * Command.time_delta ); - else if (Command.action == GLFW_PRESS && Train->mvOccupied->BrakeHandle != FV4a) + else if (Command.action == GLFW_PRESS && Train->mvOccupied->BrakeHandle != TBrakeHandle::FV4a) Train->set_train_brake( Train->mvOccupied->fBrakeCtrlPos + Global.fBrakeStep ); } void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Command ) { - if (Command.action == GLFW_REPEAT && Train->mvOccupied->BrakeHandle == FV4a) + if (Command.action == GLFW_REPEAT && Train->mvOccupied->BrakeHandle == TBrakeHandle::FV4a) Train->mvOccupied->BrakeLevelAdd( -Global.brake_speed * Command.time_delta ); - else if (Command.action == GLFW_PRESS && Train->mvOccupied->BrakeHandle != FV4a) + else if (Command.action == GLFW_PRESS && Train->mvOccupied->BrakeHandle != TBrakeHandle::FV4a) Train->set_train_brake( Train->mvOccupied->fBrakeCtrlPos - Global.fBrakeStep ); if (Command.action == GLFW_RELEASE) { // release if( ( Train->mvOccupied->BrakeCtrlPos == -1 ) - && ( Train->mvOccupied->BrakeHandle == FVel6 ) + && ( Train->mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) && ( Train->DynamicObject->Controller != AIdriver ) && ( Global.iFeedbackMode < 3 ) ) { // Odskakiwanie hamulce EP @@ -1011,12 +1018,12 @@ void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Co void TTrain::OnCommand_trainbrakeset( TTrain *Train, command_data const &Command ) { - Train->mvControlled->BrakeLevelSet( + Train->mvOccupied->BrakeLevelSet( interpolate( - Train->mvControlled->Handle->GetPos( bh_MIN ), - Train->mvControlled->Handle->GetPos( bh_MAX ), + Train->mvOccupied->Handle->GetPos( bh_MIN ), + Train->mvOccupied->Handle->GetPos( bh_MAX ), clamp( - reinterpret_cast( Command.param1 ), + Command.param1, 0.0, 1.0 ) ) ); } @@ -1029,7 +1036,7 @@ void TTrain::OnCommand_trainbrakecharging( TTrain *Train, command_data const &Co else { // release if( ( Train->mvOccupied->BrakeCtrlPos == -1 ) - && ( Train->mvOccupied->BrakeHandle == FVel6 ) + && ( Train->mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) && ( Train->DynamicObject->Controller != AIdriver ) && ( Global.iFeedbackMode < 3 ) ) { // Odskakiwanie hamulce EP @@ -1060,7 +1067,7 @@ void TTrain::OnCommand_trainbrakeservice( TTrain *Train, command_data const &Com Train->set_train_brake( ( Train->mvOccupied->BrakeCtrlPosNo / 2 - + ( Train->mvOccupied->BrakeHandle == FV4a ? + + ( Train->mvOccupied->BrakeHandle == TBrakeHandle::FV4a ? 1 : 0 ) ) ); } @@ -1101,7 +1108,7 @@ void TTrain::OnCommand_trainbrakebasepressureincrease( TTrain *Train, command_da if( Command.action != GLFW_RELEASE ) { switch( Train->mvOccupied->BrakeHandle ) { - case FV4a: { + case TBrakeHandle::FV4a: { Train->mvOccupied->BrakeCtrlPos2 = clamp( Train->mvOccupied->BrakeCtrlPos2 - 0.01, -1.5, 2.0 ); break; } @@ -1118,7 +1125,7 @@ void TTrain::OnCommand_trainbrakebasepressuredecrease( TTrain *Train, command_da if( Command.action != GLFW_RELEASE ) { switch( Train->mvOccupied->BrakeHandle ) { - case FV4a: { + case TBrakeHandle::FV4a: { Train->mvOccupied->BrakeCtrlPos2 = clamp( Train->mvOccupied->BrakeCtrlPos2 + 0.01, -1.5, 2.0 ); break; } @@ -1156,7 +1163,7 @@ void TTrain::OnCommand_manualbrakeincrease( TTrain *Train, command_data const &C auto *vehicle { Train->find_nearest_consist_vehicle() }; if( vehicle == nullptr ) { return; } - if( ( vehicle->MoverParameters->LocalBrake == ManualBrake ) + if( ( vehicle->MoverParameters->LocalBrake == TLocalBrake::ManualBrake ) || ( vehicle->MoverParameters->MBrake == true ) ) { vehicle->MoverParameters->IncManualBrakeLevel( 1 ); @@ -1171,7 +1178,7 @@ void TTrain::OnCommand_manualbrakedecrease( TTrain *Train, command_data const &C auto *vehicle { Train->find_nearest_consist_vehicle() }; if( vehicle == nullptr ) { return; } - if( ( vehicle->MoverParameters->LocalBrake == ManualBrake ) + if( ( vehicle->MoverParameters->LocalBrake == TLocalBrake::ManualBrake ) || ( vehicle->MoverParameters->MBrake == true ) ) { vehicle->MoverParameters->DecManualBrakeLevel( 1 ); @@ -1208,7 +1215,7 @@ void TTrain::OnCommand_wheelspinbrakeactivate( TTrain *Train, command_data const return; } - if( Train->mvOccupied->BrakeSystem != ElectroPneumatic ) { + if( Train->mvOccupied->BrakeSystem != TBrakeSystem::ElectroPneumatic ) { // standard behaviour if( Command.action == GLFW_PRESS ) { // visual feedback @@ -1227,7 +1234,7 @@ void TTrain::OnCommand_wheelspinbrakeactivate( TTrain *Train, command_data const // visual feedback Train->ggAntiSlipButton.UpdateValue( 1.0, Train->dsbPneumaticSwitch ); - if( ( Train->mvOccupied->BrakeHandle == St113 ) + if( ( Train->mvOccupied->BrakeHandle == TBrakeHandle::St113 ) && ( Train->mvControlled->EpFuse == true ) ) { Train->mvOccupied->SwitchEPBrake( 1 ); } @@ -2075,8 +2082,8 @@ void TTrain::OnCommand_linebreakerclose( TTrain *Train, command_data const &Comm if( Train->m_linebreakerstate == 2 ) { // we don't need to start the diesel twice, but the other types (with impulse switch setup) still need to be launched - if( ( Train->mvControlled->EngineType != DieselEngine ) - && ( Train->mvControlled->EngineType != DieselElectric ) ) { + if( ( Train->mvControlled->EngineType != TEngineType::DieselEngine ) + && ( Train->mvControlled->EngineType != TEngineType::DieselElectric ) ) { // try to finalize state change of the line breaker, set the state based on the outcome Train->m_linebreakerstate = ( Train->mvControlled->MainSwitch( true ) ? @@ -2388,7 +2395,7 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma void TTrain::OnCommand_converterenable( TTrain *Train, command_data const &Command ) { - if( Train->mvControlled->ConverterStart == start::automatic ) { + if( Train->mvControlled->ConverterStart == start_t::automatic ) { // let the automatic thing do its automatic thing... return; } @@ -2422,7 +2429,7 @@ void TTrain::OnCommand_converterenable( TTrain *Train, command_data const &Comma void TTrain::OnCommand_converterdisable( TTrain *Train, command_data const &Command ) { - if( Train->mvControlled->ConverterStart == start::automatic ) { + if( Train->mvControlled->ConverterStart == start_t::automatic ) { // let the automatic thing do its automatic thing... return; } @@ -2462,7 +2469,7 @@ void TTrain::OnCommand_converterdisable( TTrain *Train, command_data const &Comm void TTrain::OnCommand_convertertogglelocal( TTrain *Train, command_data const &Command ) { - if( Train->mvOccupied->ConverterStart == start::automatic ) { + if( Train->mvOccupied->ConverterStart == start_t::automatic ) { // let the automatic thing do its automatic thing... return; } @@ -3721,7 +3728,7 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman Train->mvOccupied->DoorLeftOpened : Train->mvOccupied->DoorRightOpened ) ) { // open - if( Train->mvOccupied->DoorOpenCtrl != control::driver ) { + if( Train->mvOccupied->DoorOpenCtrl != control_t::driver ) { return; } if( Train->mvOccupied->ActiveCab == 1 ) { @@ -3736,7 +3743,7 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman } else { // close - if( Train->mvOccupied->DoorCloseCtrl != control::driver ) { + if( Train->mvOccupied->DoorCloseCtrl != control_t::driver ) { return; } // TODO: move door opening/closing to the update, so the switch animation doesn't hinge on door working @@ -3762,7 +3769,7 @@ void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Comma Train->mvOccupied->DoorRightOpened : Train->mvOccupied->DoorLeftOpened ) ) { // open - if( Train->mvOccupied->DoorOpenCtrl != control::driver ) { + if( Train->mvOccupied->DoorOpenCtrl != control_t::driver ) { return; } if( Train->mvOccupied->ActiveCab == 1 ) { @@ -3777,7 +3784,7 @@ void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Comma } else { // close - if( Train->mvOccupied->DoorCloseCtrl != control::driver ) { + if( Train->mvOccupied->DoorCloseCtrl != control_t::driver ) { return; } if( Train->mvOccupied->ActiveCab == 1 ) { @@ -4114,8 +4121,8 @@ void TTrain::UpdateMechPosition(double dt) && ( pMechOffset.y < 4.0 ) ) // Ra 15-01: przy oglądaniu pantografu bujanie przeszkadza { Math3D::vector3 shakevector; - if( ( mvOccupied->EngineType == DieselElectric ) - || ( mvOccupied->EngineType == DieselEngine ) ) { + if( ( mvOccupied->EngineType == TEngineType::DieselElectric ) + || ( mvOccupied->EngineType == TEngineType::DieselEngine ) ) { if( std::abs( mvOccupied->enrot ) > 0.0 ) { // engine vibration shakevector.x += @@ -4265,8 +4272,8 @@ bool TTrain::Update( double const Deltatime ) || ( ggMainOnButton.GetDesiredValue() > 0.95 ) ) { // keep track of period the line breaker button is held down, to determine when/if circuit closes if( ( fHVoltage > 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) - || ( ( mvControlled->EngineType != ElectricSeriesMotor ) - && ( mvControlled->EngineType != ElectricInductionMotor ) + || ( ( mvControlled->EngineType != TEngineType::ElectricSeriesMotor ) + && ( mvControlled->EngineType != TEngineType::ElectricInductionMotor ) && ( true == mvControlled->Battery ) ) ) { // prevent the switch from working if there's no power // TODO: consider whether it makes sense for diesel engines and such @@ -4291,8 +4298,8 @@ bool TTrain::Update( double const Deltatime ) if( m_linebreakerstate == 2 ) { // for diesels and/or vehicles with toggle switch setup we complete the engine start here if( ( ggMainOnButton.SubModel == nullptr ) - || ( ( mvControlled->EngineType == DieselEngine ) - || ( mvControlled->EngineType == DieselElectric ) ) ) { + || ( ( mvControlled->EngineType == TEngineType::DieselEngine ) + || ( mvControlled->EngineType == TEngineType::DieselElectric ) ) ) { // try to finalize state change of the line breaker, set the state based on the outcome m_linebreakerstate = ( mvControlled->MainSwitch( true ) ? @@ -4337,18 +4344,35 @@ bool TTrain::Update( double const Deltatime ) { // Ra: TODO: odczyty klawiatury/pulpitu nie powinny być uzależnione od istnienia modelu kabiny if( ( DynamicObject->Mechanik != nullptr ) - && ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI - && ( ( mvOccupied->TrainType == dt_ET40 ) - || ( mvOccupied->TrainType == dt_EP05 ) ) ) { - // dla ET40 i EU05 automatyczne cofanie nastawnika - i tak nie będzie to działać dobrze... - // TODO: remove direct keyboard check, use deltatime to stabilize speed - if( ( glfwGetKey( Global.window, GLFW_KEY_KP_ADD ) != GLFW_TRUE ) - && ( mvOccupied->MainCtrlPos > mvOccupied->MainCtrlActualPos ) ) { - mvOccupied->DecMainCtrl( 1 ); + && ( false == DynamicObject->Mechanik->AIControllFlag ) ) { + // nie blokujemy AI + if( ( mvOccupied->TrainType == dt_ET40 ) + || ( mvOccupied->TrainType == dt_EP05 ) ) { + // dla ET40 i EU05 automatyczne cofanie nastawnika - i tak nie będzie to działać dobrze... + // TODO: use deltatime to stabilize speed + if( false == ( + ( input::command == user_command::mastercontrollerset ) + || ( input::command == user_command::mastercontrollerincrease ) + || ( input::command == user_command::mastercontrollerdecrease ) ) ) { + if( mvOccupied->MainCtrlPos > mvOccupied->MainCtrlActualPos ) { + mvOccupied->DecMainCtrl( 1 ); + } + else if( mvOccupied->MainCtrlPos < mvOccupied->MainCtrlActualPos ) { + // Ra 15-01: a to nie miało być tylko cofanie? + mvOccupied->IncMainCtrl( 1 ); + } + } } - if( ( glfwGetKey( Global.window, GLFW_KEY_KP_SUBTRACT ) != GLFW_TRUE ) - && ( mvOccupied->MainCtrlPos < mvOccupied->MainCtrlActualPos ) ) { - mvOccupied->IncMainCtrl( 1 ); // Ra 15-01: a to nie miało być tylko cofanie? + + if( ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) + && ( mvOccupied->fBrakeCtrlPos < 0.0 ) + && ( Global.iFeedbackMode < 3 ) ) { + // Odskakiwanie hamulce EP + if( false == ( + ( input::command == user_command::trainbrakeset ) + || ( input::command == user_command::trainbrakedecrease ) ) ) { + set_train_brake( 0 ); + } } } @@ -4379,8 +4403,8 @@ bool TTrain::Update( double const Deltatime ) } // Ra 2014-09: napięcia i prądy muszą być ustalone najpierw, bo wysyłane są ewentualnie na PoKeys - if ((mvControlled->EngineType != DieselElectric) - && (mvControlled->EngineType != ElectricInductionMotor)) // Ra 2014-09: czy taki rozdzia? ma sens? + if ((mvControlled->EngineType != TEngineType::DieselElectric) + && (mvControlled->EngineType != TEngineType::ElectricInductionMotor)) // Ra 2014-09: czy taki rozdzia? ma sens? fHVoltage = mvControlled->RunningTraction.TractionVoltage; // Winger czy to nie jest zle? // *mvControlled->Mains); else @@ -4443,7 +4467,7 @@ bool TTrain::Update( double const Deltatime ) asCarName[i] = p->name(); bPants[iUnitNo - 1][0] = (bPants[iUnitNo - 1][0] || p->MoverParameters->PantFrontUp); bPants[iUnitNo - 1][1] = (bPants[iUnitNo - 1][1] || p->MoverParameters->PantRearUp); - bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start::automatic)); + bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start_t::automatic)); bSlip[i] = p->MoverParameters->SlippingWheels; if (p->MoverParameters->CompressorSpeed > 0.00001) { @@ -4542,12 +4566,12 @@ bool TTrain::Update( double const Deltatime ) // hunter-080812: wyrzucanie szybkiego na elektrykach gdy nie ma napiecia przy dowolnym ustawieniu kierunkowego // Ra: to już jest w T_MoverParameters::TractionForce(), ale zależy od kierunku if( ( mvControlled->Mains ) - && ( mvControlled->EngineType == ElectricSeriesMotor ) ) { + && ( mvControlled->EngineType == TEngineType::ElectricSeriesMotor ) ) { if( std::max( mvControlled->GetTrainsetVoltage(), std::fabs( mvControlled->RunningTraction.TractionVoltage ) ) < 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) { // TODO: check whether it should affect entire consist for EMU // TODO: check whether it should happen if there's power supplied alternatively through hvcouplers // TODO: potentially move this to the mover module, as there isn't much reason to have this dependent on the operator presence - mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? range::unit : range::local ) ); + mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? range_t::unit : range_t::local ) ); } } @@ -4569,7 +4593,7 @@ bool TTrain::Update( double const Deltatime ) { fConverterTimer += Deltatime; if ((mvControlled->CompressorFlag == true) && (mvControlled->CompressorPower == 1) && - ((mvControlled->EngineType == ElectricSeriesMotor) || + ((mvControlled->EngineType == TEngineType::ElectricSeriesMotor) || (mvControlled->TrainType == dt_EZT)) && (DynamicObject->Controller == Humandriver)) // hunter-110212: poprawka dla EZT { // hunter-091012: poprawka (zmiana warunku z CompressorPower /rozne od @@ -4578,7 +4602,7 @@ bool TTrain::Update( double const Deltatime ) { mvControlled->ConvOvldFlag = true; if (mvControlled->TrainType != dt_EZT) - mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? range::unit : range::local ) ); + mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? range_t::unit : range_t::local ) ); } else if( fConverterTimer >= fConverterPrzekaznik ) { // changed switch from always true to take into account state of the compressor switch @@ -4697,13 +4721,13 @@ bool TTrain::Update( double const Deltatime ) ggLVoltage.Update(); } - if (mvControlled->EngineType == DieselElectric) + if (mvControlled->EngineType == TEngineType::DieselElectric) { // ustawienie zmiennych dla silnika spalinowego fEngine[1] = mvControlled->ShowEngineRotation(1); fEngine[2] = mvControlled->ShowEngineRotation(2); } - else if (mvControlled->EngineType == DieselEngine) + else if (mvControlled->EngineType == TEngineType::DieselEngine) { // albo dla innego spalinowego fEngine[1] = mvControlled->ShowEngineRotation(1); fEngine[2] = mvControlled->ShowEngineRotation(2); @@ -5088,6 +5112,20 @@ bool TTrain::Update( double const Deltatime ) // McZapkie-080602: obroty (albo translacje) regulatorow if (ggMainCtrl.SubModel) { +#ifdef _WIN32 + if ((DynamicObject->Mechanik != nullptr) + && (false == DynamicObject->Mechanik->AIControllFlag) // nie blokujemy AI + && (Global.iFeedbackMode == 4) + && (Global.fCalibrateIn[2][1] != 0.0)) { + auto const b = clamp( + Console::AnalogCalibrateGet(2) * mvOccupied->MainCtrlPosNo, + 0.0, + mvOccupied->MainCtrlPosNo); + while (mvOccupied->MainCtrlPos < b) { mvOccupied->MainCtrlPos = b - 1; mvOccupied->IncMainCtrl(1); } + while (mvOccupied->MainCtrlPos > b) { mvOccupied->MainCtrlPos = b + 1; mvOccupied->DecMainCtrl(1); } + } +#endif + if( mvControlled->CoupledCtrl ) { ggMainCtrl.UpdateValue( double( mvControlled->MainCtrlPos + mvControlled->ScndCtrlPos ), @@ -5137,7 +5175,7 @@ bool TTrain::Update( double const Deltatime ) false) // nie blokujemy AI { // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba // Firleju: dlatego kasujemy i zastepujemy funkcją w Console - if (mvOccupied->BrakeHandle == FV4a) + if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a) { double b = Console::AnalogCalibrateGet(0); b = b * 8.0 - 2.0; @@ -5145,7 +5183,7 @@ bool TTrain::Update( double const Deltatime ) ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia mvOccupied->BrakeLevelSet(b); } - if (mvOccupied->BrakeHandle == FVel6) // może można usunąć ograniczenie do FV4a i FVel6? + if (mvOccupied->BrakeHandle == TBrakeHandle::FVel6) // może można usunąć ograniczenie do FV4a i FVel6? { double b = Console::AnalogCalibrateGet(0); b = b * 7.0 - 1.0; @@ -5166,22 +5204,24 @@ bool TTrain::Update( double const Deltatime ) #ifdef _WIN32 if( ( DynamicObject->Mechanik != nullptr ) && ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI - && ( mvOccupied->BrakeLocHandle == FD1 ) + && ( mvOccupied->BrakeLocHandle == TBrakeHandle::FD1 ) && ( ( Global.iFeedbackMode == 4 ) /*|| ( Global.bMWDmasterEnable && Global.bMWDBreakEnable )*/ ) ) { // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba // Firleju: dlatego kasujemy i zastepujemy funkcją w Console auto const b = clamp( - Console::AnalogCalibrateGet( 1 ) * 10.0, + Console::AnalogCalibrateGet( 1 ), 0.0, - ManualBrakePosNo ); - ggLocalBrake.UpdateValue( b ); // przesów bez zaokrąglenia - mvOccupied->LocalBrakePos = int( 1.09 * b ); // sposób zaokrąglania jest do ustalenia + 1.0 ); + mvOccupied->LocalBrakePosA = b; + ggLocalBrake.UpdateValue( b * LocalBrakePosNo ); } else #endif - // standardowa prodedura z kranem powiązanym z klawiaturą - ggLocalBrake.UpdateValue( std::max( mvOccupied->LocalBrakePos, mvOccupied->LocalBrakePosA * LocalBrakePosNo ) ); + { + // standardowa prodedura z kranem powiązanym z klawiaturą + ggLocalBrake.UpdateValue( mvOccupied->LocalBrakePosA * LocalBrakePosNo ); + } ggLocalBrake.Update(); } if (ggManualBrake.SubModel != nullptr) { @@ -5342,7 +5382,7 @@ bool TTrain::Update( double const Deltatime ) } // anti slip system activation, maintained while the control button is down - if( mvOccupied->BrakeSystem != ElectroPneumatic ) { + if( mvOccupied->BrakeSystem != TBrakeSystem::ElectroPneumatic ) { if( ggAntiSlipButton.GetDesiredValue() > 0.95 ) { mvControlled->AntiSlippingBrake(); } @@ -5448,8 +5488,8 @@ TTrain::update_sounds( double const Deltatime ) { // McZapkie-280302 - syczenie // TODO: softer volume reduction than plain abrupt stop, perhaps as reusable wrapper? - if( ( mvOccupied->BrakeHandle == FV4a ) - || ( mvOccupied->BrakeHandle == FVel6 ) ) { + if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) + || ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) ) { // upuszczanie z PG fPPress = interpolate( fPPress, static_cast( mvOccupied->Handle->GetSound( s_fv4a_b ) ), 0.05f ); volume = ( @@ -7119,9 +7159,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con if (Parser.getToken() == "analog") { // McZapkie-300302: zegarek - ggClockSInd.Init(DynamicObject->mdKabina->GetFromName("ClockShand"), gt_Rotate, 1.0/60.0); - ggClockMInd.Init(DynamicObject->mdKabina->GetFromName("ClockMhand"), gt_Rotate, 1.0/60.0); - ggClockHInd.Init(DynamicObject->mdKabina->GetFromName("ClockHhand"), gt_Rotate, 1.0/12.0); + ggClockSInd.Init(DynamicObject->mdKabina->GetFromName("ClockShand"), TGaugeType::gt_Rotate, 1.0/60.0); + ggClockMInd.Init(DynamicObject->mdKabina->GetFromName("ClockMhand"), TGaugeType::gt_Rotate, 1.0/60.0); + ggClockHInd.Init(DynamicObject->mdKabina->GetFromName("ClockHhand"), TGaugeType::gt_Rotate, 1.0/12.0); } } else if (Label == "evoltage:") @@ -7265,7 +7305,7 @@ void TTrain::set_localbrake(float val) val = std::min(1.0f, std::max(0.0f, val)); float min = 0.0f; float max = (float)LocalBrakePosNo; - mvControlled->LocalBrakePos = std::round(min + val * (max - min)); + mvControlled->LocalBrakePosA = std::round(min + val * (max - min)); } int TTrain::get_drive_direction() diff --git a/Train.h b/Train.h index a3c3b832..b271f962 100644 --- a/Train.h +++ b/Train.h @@ -650,8 +650,8 @@ private: inline TDynamicObject const *Dynamic() const { return DynamicObject; }; inline TMoverParameters *Controlled() { return mvControlled; }; inline TMoverParameters const *Controlled() const { return mvControlled; }; - inline TMoverParameters *Occupied() { return mvOccupied; }; - inline TMoverParameters const *Occupied() const { return mvOccupied; }; + inline TMoverParameters *Occupied() { return mvOccupied; }; + inline TMoverParameters const *Occupied() const { return mvOccupied; }; void DynamicSet(TDynamicObject *d); float get_tacho(); diff --git a/World.cpp b/World.cpp index 2ca5da5f..dab46364 100644 --- a/World.cpp +++ b/World.cpp @@ -16,7 +16,9 @@ http://mozilla.org/MPL/2.0/. #include "World.h" #include "Globals.h" +#include "application.h" #include "simulation.h" +#include "simulationtime.h" #include "Logs.h" #include "MdlMngr.h" #include "renderer.h" @@ -34,12 +36,7 @@ http://mozilla.org/MPL/2.0/. //--------------------------------------------------------------------------- -namespace simulation { - -simulation_time Time; - -basic_station Station; -} +TWorld World; #ifdef _WIN32 extern "C" @@ -48,182 +45,6 @@ extern "C" } #endif -void -simulation_time::init() { - - char monthdaycounts[ 2 ][ 13 ] = { - { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; - ::memcpy( m_monthdaycounts, monthdaycounts, sizeof( monthdaycounts ) ); - - // potentially adjust scenario clock - auto const requestedtime { clamp_circular( m_time.wHour * 60 + m_time.wMinute + Global.ScenarioTimeOffset * 60, 24 * 60 ) }; - auto const requestedhour { ( requestedtime / 60 ) % 24 }; - auto const requestedminute { requestedtime % 60 }; - // cache requested elements, if any - -#ifdef __linux__ - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - tm *tms = localtime(&ts.tv_sec); - m_time.wYear = tms->tm_year; - m_time.wMonth = tms->tm_mon; - m_time.wDayOfWeek = tms->tm_wday; - m_time.wDay = tms->tm_mday; - m_time.wHour = tms->tm_hour; - m_time.wMinute = tms->tm_min; - m_time.wSecond = tms->tm_sec; - m_time.wMilliseconds = ts.tv_nsec / 1000000; - -/* - time_t local = mktime(localtime(&ts.tv_sec)); - time_t utc = mktime(gmtime(&ts.tv_sec)); - m_timezonebias = (double)(local - utc) / 3600.0f; -*/ -#elif _WIN32 - ::GetLocalTime( &m_time ); -#endif - - if( Global.fMoveLight > 0.0 ) { - // day and month of the year can be overriden by scenario setup - daymonth( m_time.wDay, m_time.wMonth, m_time.wYear, static_cast( Global.fMoveLight ) ); - } - - if( requestedhour != -1 ) { m_time.wHour = static_cast( clamp( requestedhour, 0, 23 ) ); } - if( requestedminute != -1 ) { m_time.wMinute = static_cast( clamp( requestedminute, 0, 59 ) ); } - // if the time is taken from the local clock leave the seconds intact, otherwise set them to zero - if( ( requestedhour != -1 ) - || ( requestedminute != 1 ) ) { - m_time.wSecond = 0; - } - - m_yearday = year_day( m_time.wDay, m_time.wMonth, m_time.wYear ); - - // calculate time zone bias - // retrieve relevant time zone info from system registry (or fall back on supplied default) - // TODO: select timezone matching defined geographic location and/or country - struct registry_time_zone_info { - long Bias; - long StandardBias; - long DaylightBias; - SYSTEMTIME StandardDate; - SYSTEMTIME DaylightDate; - } timezoneinfo = { -60, 0, -60, { 0, 10, 0, 5, 3, 0, 0, 0 }, { 0, 3, 0, 5, 2, 0, 0, 0 } }; - - auto zonebias { timezoneinfo.Bias }; - if( m_yearday < year_day( timezoneinfo.DaylightDate.wDay, timezoneinfo.DaylightDate.wMonth, m_time.wYear ) ) { - zonebias += timezoneinfo.StandardBias; - } - else if( m_yearday < year_day( timezoneinfo.StandardDate.wDay, timezoneinfo.StandardDate.wMonth, m_time.wYear ) ) { - zonebias += timezoneinfo.DaylightBias; - } - else { - zonebias += timezoneinfo.StandardBias; - } - - m_timezonebias = ( zonebias / 60.0 ); -} - -void -simulation_time::update( double const Deltatime ) { - - m_milliseconds += ( 1000.0 * Deltatime ); - while( m_milliseconds >= 1000.0 ) { - - ++m_time.wSecond; - m_milliseconds -= 1000.0; - } - m_time.wMilliseconds = std::floor( m_milliseconds ); - while( m_time.wSecond >= 60 ) { - - ++m_time.wMinute; - m_time.wSecond -= 60; - } - while( m_time.wMinute >= 60 ) { - - ++m_time.wHour; - m_time.wMinute -= 60; - } - while( m_time.wHour >= 24 ) { - - ++m_time.wDay; - ++m_time.wDayOfWeek; - if( m_time.wDayOfWeek >= 7 ) { - m_time.wDayOfWeek -= 7; - } - m_time.wHour -= 24; - } - int leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 ); - while( m_time.wDay > m_monthdaycounts[ leap ][ m_time.wMonth ] ) { - - m_time.wDay -= m_monthdaycounts[ leap ][ m_time.wMonth ]; - ++m_time.wMonth; - // unlikely but we might've entered a new year - if( m_time.wMonth > 12 ) { - - ++m_time.wYear; - leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 ); - m_time.wMonth -= 12; - } - } -} - -int -simulation_time::year_day( int Day, const int Month, const int Year ) const { - - char const daytab[ 2 ][ 13 ] = { - { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } - }; - - int leap { ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ) }; - for( int i = 1; i < Month; ++i ) - Day += daytab[ leap ][ i ]; - - return Day; -} - -void -simulation_time::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ) { - - WORD daytab[ 2 ][ 13 ] = { - { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, - { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } - }; - - int leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ); - WORD idx = 1; - while( ( idx < 13 ) && ( Yearday >= daytab[ leap ][ idx ] ) ) { - - ++idx; - } - Month = idx; - Day = Yearday - daytab[ leap ][ idx - 1 ]; -} - -int -simulation_time::julian_day() const { - - int yy = ( m_time.wYear < 0 ? m_time.wYear + 1 : m_time.wYear ) - std::floor( ( 12 - m_time.wMonth ) / 10.f ); - int mm = m_time.wMonth + 9; - if( mm >= 12 ) { mm -= 12; } - - int K1 = std::floor( 365.25 * ( yy + 4712 ) ); - int K2 = std::floor( 30.6 * mm + 0.5 ); - - // for dates in Julian calendar - int JD = K1 + K2 + m_time.wDay + 59; - // for dates in Gregorian calendar; 2299160 is October 15th, 1582 - const int gregorianswitchday = 2299160; - if( JD > gregorianswitchday ) { - - int K3 = std::floor( std::floor( ( yy * 0.01 ) + 49 ) * 0.75 ) - 38; - JD -= K3; - } - - return JD; -} - TWorld::TWorld() { Train = NULL; @@ -263,7 +84,6 @@ bool TWorld::Init( GLFWwindow *Window ) { auto timestart = std::chrono::system_clock::now(); window = Window; - Global.window = Window; // do WM_COPYDATA Global.pCamera = &Camera; // Ra: wskaźnik potrzebny do likwidacji drgań WriteLog( "\nStarting MaSzyna rail vehicle simulator (release: " + Global.asVersion + ")" ); @@ -310,7 +130,7 @@ bool TWorld::Init( GLFWwindow *Window ) { Controlled = NULL; mvControlled = NULL; SafeDelete( Train ); - Camera.Type = tp_Free; + Camera.Type = TCameraType::tp_Free; } } else @@ -323,7 +143,7 @@ bool TWorld::Init( GLFWwindow *Window ) { glfwSwapBuffers( window ); Controlled = NULL; mvControlled = NULL; - Camera.Type = tp_Free; + Camera.Type = TCameraType::tp_Free; DebugCamera = Camera; Global.DebugCameraPosition = DebugCamera.Pos; } @@ -885,7 +705,7 @@ bool TWorld::Update() { // fixed step part of the camera update if( ( Train != nullptr ) - && ( Camera.Type == tp_Follow ) + && ( Camera.Type == TCameraType::tp_Follow ) && ( false == DebugCameraFlag ) ) { // jeśli jazda w kabinie, przeliczyć trzeba parametry kamery Train->UpdateMechPosition( m_secondaryupdaterate ); @@ -949,7 +769,6 @@ bool TWorld::Update() { audio::renderer.update( Global.iPause ? 0.0 : dt ); GfxRenderer.Update( dt ); - ResourceSweep(); m_init = true; @@ -1014,19 +833,19 @@ TWorld::Update_Camera( double const Deltatime ) { Global.CabWindowOpen = false; if( ( Train != nullptr ) - && ( Camera.Type == tp_Follow ) + && ( Camera.Type == TCameraType::tp_Follow ) && ( false == DebugCameraFlag ) ) { // jeśli jazda w kabinie, przeliczyć trzeba parametry kamery auto tempangle = Controlled->VectorFront() * ( Controlled->MoverParameters->ActiveCab == -1 ? -1 : 1 ); // double modelrotate = atan2( -tempangle.x, tempangle.z ); if( ( true == Global.ctrlState ) - && ( ( glfwGetKey( Global.window, GLFW_KEY_LEFT ) == GLFW_TRUE ) - || ( glfwGetKey( Global.window, GLFW_KEY_RIGHT ) == GLFW_TRUE ) ) ) { + && ( ( glfwGetKey( Application.window(), GLFW_KEY_LEFT ) == GLFW_TRUE ) + || ( glfwGetKey( Application.window(), GLFW_KEY_RIGHT ) == GLFW_TRUE ) ) ) { // jeśli lusterko lewe albo prawe (bez rzucania na razie) Global.CabWindowOpen = true; - auto const lr { glfwGetKey( Global.window, GLFW_KEY_LEFT ) == GLFW_TRUE }; + auto const lr { glfwGetKey( Application.window(), GLFW_KEY_LEFT ) == GLFW_TRUE }; // Camera.Yaw powinno być wyzerowane, aby po powrocie patrzeć do przodu Camera.Pos = Controlled->GetPosition() + Train->MirrorPosition( lr ); // pozycja lusterka Camera.Yaw = 0; // odchylenie na bok od Camera.LookAt @@ -1093,13 +912,6 @@ void TWorld::Update_Environment() { Environment.update(); } -void TWorld::ResourceSweep() -{ -/* - ResourceManager::Sweep( Timer::GetSimulationTime() ); -*/ -}; - //--------------------------------------------------------------------------- void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz) { // odebranie komunikatu z serwera @@ -1459,11 +1271,11 @@ TWorld::compute_season( int const Yearday ) const { using dayseasonpair = std::pair; std::vector seasonsequence { - { 65, "winter" }, - { 158, "spring" }, - { 252, "summer" }, - { 341, "autumn" }, - { 366, "winter" } }; + { 65, "winter:" }, + { 158, "spring:" }, + { 252, "summer:" }, + { 341, "autumn:" }, + { 366, "winter:" } }; auto const lookup = std::lower_bound( std::begin( seasonsequence ), std::end( seasonsequence ), @@ -1471,7 +1283,7 @@ TWorld::compute_season( int const Yearday ) const { []( dayseasonpair const &Left, const int Right ) { return Left.first < Right; } ); - Global.Season = lookup->second + ":"; + Global.Season = lookup->second; // season can affect the weather so if it changes, re-calculate weather as well compute_weather(); } diff --git a/World.h b/World.h index 95b277d5..c5cac85b 100644 --- a/World.h +++ b/World.h @@ -20,52 +20,6 @@ http://mozilla.org/MPL/2.0/. #include "stars.h" #include "skydome.h" #include "messaging.h" -#include "station.h" - -// wrapper for simulation time -class simulation_time { - -public: - simulation_time() { m_time.wHour = 10; m_time.wMinute = 30; } - void - init(); - void - update( double const Deltatime ); - SYSTEMTIME & - data() { return m_time; } - SYSTEMTIME const & - data() const { return m_time; } - double - second() const { return ( m_time.wMilliseconds * 0.001 + m_time.wSecond ); } - int - year_day() const { return m_yearday; } - // helper, calculates day of year from given date - int - year_day( int Day, int const Month, int const Year ) const; - int - julian_day() const; - double - zone_bias() const { return m_timezonebias; } - -private: - // calculates day and month from given day of year - void - daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ); - - SYSTEMTIME m_time; - double m_milliseconds{ 0.0 }; - int m_yearday; - char m_monthdaycounts[ 2 ][ 13 ]; - double m_timezonebias{ 0.0 }; -}; - -namespace simulation { - -extern simulation_time Time; - -extern basic_station Station; // temporary object, for station functionality tests - -} class opengl_renderer; @@ -128,7 +82,6 @@ TWorld(); private: void Update_Environment(); void Update_Camera( const double Deltatime ); - void ResourceSweep(); // handles vehicle change flag void ChangeDynamic(); void InOutKey( bool const Near = true ); @@ -156,5 +109,7 @@ private: GLFWwindow *window; }; +extern TWorld World; + //--------------------------------------------------------------------------- diff --git a/application.cpp b/application.cpp new file mode 100644 index 00000000..bdc68b19 --- /dev/null +++ b/application.cpp @@ -0,0 +1,484 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#include "stdafx.h" +#include "application.h" + +#include "Globals.h" +#include "keyboardinput.h" +#include "mouseinput.h" +#include "gamepadinput.h" +#include "Console.h" +#include "simulation.h" +#include "World.h" +#include "PyInt.h" +#include "sceneeditor.h" +#include "renderer.h" +#include "uilayer.h" +#include "Logs.h" +#include "screenshot.h" +#include "motiontelemetry.h" + +#pragma comment (lib, "glu32.lib") +#pragma comment (lib, "dsound.lib") +#pragma comment (lib, "winmm.lib") +#pragma comment (lib, "setupapi.lib") +#pragma comment (lib, "dbghelp.lib") +#pragma comment (lib, "version.lib") + +#ifdef __linux__ +#include +#include +#endif + +eu07_application Application; +screenshot_manager screenshot_man; + +namespace input { + +gamepad_input Gamepad; +mouse_input Mouse; +glm::dvec2 mouse_pickmodepos; // stores last mouse position in control picking mode +keyboard_input Keyboard; +std::unique_ptr uart; +user_command command; // currently issued control command, if any +std::unique_ptr motiontelemetry; +#ifdef _WIN32 +Console console; +#endif +} + +#ifdef _WIN32 +extern "C" +{ + GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); +} + +LONG CALLBACK unhandled_handler( ::EXCEPTION_POINTERS* e ); +LRESULT APIENTRY WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); +extern HWND Hwnd; +extern WNDPROC BaseWindowProc; +#endif + +// user input callbacks + +void window_resize_callback( GLFWwindow *window, int w, int h ) { + // NOTE: we have two variables which basically do the same thing as we don't have dynamic fullscreen toggle + // TBD, TODO: merge them? + Global.iWindowWidth = w; + Global.iWindowHeight = h; + Global.fDistanceFactor = std::max( 0.5f, h / 768.0f ); // not sure if this is really something we want to use + glViewport( 0, 0, w, h ); +} + +void cursor_pos_callback( GLFWwindow *window, double x, double y ) { + if( false == Global.ControlPicking ) { + glfwSetCursorPos( window, 0, 0 ); + } + + // give the potential event recipient a shot at it, in the virtual z order + if( true == scene::Editor.on_mouse_move( x, y ) ) { return; } + input::Mouse.move( x, y ); +} + +void mouse_button_callback( GLFWwindow* window, int button, int action, int mods ) { + + if( ( button != GLFW_MOUSE_BUTTON_LEFT ) + && ( button != GLFW_MOUSE_BUTTON_RIGHT ) ) { + // we don't care about other mouse buttons at the moment + return; + } + // give the potential event recipient a shot at it, in the virtual z order + if( true == scene::Editor.on_mouse_button( button, action ) ) { return; } + input::Mouse.button( button, action ); +} + +void key_callback( GLFWwindow *window, int key, int scancode, int action, int mods ) { + + Global.shiftState = ( mods & GLFW_MOD_SHIFT ) ? true : false; + Global.ctrlState = ( mods & GLFW_MOD_CONTROL ) ? true : false; + Global.altState = ( mods & GLFW_MOD_ALT ) ? true : false; + + // give the ui first shot at the input processing... + if( true == UILayer.on_key( key, action ) ) { return; } + if( true == scene::Editor.on_key( key, action ) ) { return; } + // ...if the input is left untouched, pass it on + input::Keyboard.key( key, action ); + + if( ( true == Global.InputMouse ) + && ( ( key == GLFW_KEY_LEFT_ALT ) + || ( key == GLFW_KEY_RIGHT_ALT ) ) ) { + // if the alt key was pressed toggle control picking mode and set matching cursor behaviour + if( action == GLFW_RELEASE ) { + + if( Global.ControlPicking ) { + // switch off + Application.get_cursor_pos( input::mouse_pickmodepos.x, input::mouse_pickmodepos.y ); + Application.set_cursor( GLFW_CURSOR_DISABLED ); + Application.set_cursor_pos( 0, 0 ); + } + else { + // enter picking mode + Application.set_cursor_pos( input::mouse_pickmodepos.x, input::mouse_pickmodepos.y ); + Application.set_cursor( GLFW_CURSOR_NORMAL ); + } + // actually toggle the mode + Global.ControlPicking = !Global.ControlPicking; + } + } + + if( ( key == GLFW_KEY_LEFT_SHIFT ) + || ( key == GLFW_KEY_LEFT_CONTROL ) + || ( key == GLFW_KEY_LEFT_ALT ) + || ( key == GLFW_KEY_RIGHT_SHIFT ) + || ( key == GLFW_KEY_RIGHT_CONTROL ) + || ( key == GLFW_KEY_RIGHT_ALT ) ) { + // don't bother passing these + return; + } + + if( action == GLFW_PRESS || action == GLFW_REPEAT ) { + + World.OnKeyDown( key ); + + switch( key ) { + case GLFW_KEY_PRINT_SCREEN: { + Application.queue_screenshot(); + break; + } + default: { break; } + } + } +} +void focus_callback( GLFWwindow *window, int focus ) { + if( Global.bInactivePause ) // jeśli ma być pauzowanie okna w tle + if( focus ) + Global.iPause &= ~4; // odpauzowanie, gdy jest na pierwszym planie + else + Global.iPause |= 4; // włączenie pauzy, gdy nieaktywy +} + +void scroll_callback( GLFWwindow* window, double xoffset, double yoffset ) { + + if( Global.ctrlState ) { + // ctrl + scroll wheel adjusts fov in debug mode + Global.FieldOfView = clamp( static_cast( Global.FieldOfView - yoffset * 20.0 / Global.fFpsAverage ), 15.0f, 75.0f ); + } +} + +// public: + +void eu07_application::queue_screenshot() +{ + screenshot_queued = true; +} + +int +eu07_application::init( int Argc, char *Argv[] ) { + + int result { 0 }; + + init_debug(); + init_files(); + if( ( result = init_settings( Argc, Argv ) ) != 0 ) { + return result; + } + if( ( result = init_glfw() ) != 0 ) { + return result; + } + init_callbacks(); + if( ( result = init_gfx() ) != 0 ) { + return result; + } + if( ( result = init_audio() ) != 0 ) { + return result; + } + + return result; +} + +int +eu07_application::run() +{ + // HACK: prevent mouse capture before simulation starts + Global.ControlPicking = true; + // TODO: move input sources and their initializations to the application mode member + input::Keyboard.init(); + input::Mouse.init(); + input::Gamepad.init(); + if( true == Global.uart_conf.enable ) { + input::uart = std::make_unique(); + input::uart->init(); + } + if (Global.motiontelemetry_conf.enable) + input::motiontelemetry = std::make_unique(); +#ifdef _WIN32 + Console::On(); // włączenie konsoli +#endif + + Global.pWorld = &World; // Ra: wskaźnik potrzebny do usuwania pojazdów + + if( false == World.Init( m_window ) ) { + ErrorLog( "Bad init: simulation setup failed" ); + return -1; + } + + if( Global.iConvertModels < 0 ) { + // generate binary files for all 3d models + Global.iConvertModels = -Global.iConvertModels; + World.CreateE3D( szModelPath ); // rekurencyjne przeglądanie katalogów + World.CreateE3D( szDynamicPath, true ); + // auto-close when you're done + WriteLog( "Binary 3d model generation completed" ); + return 0; + } + + set_cursor( GLFW_CURSOR_DISABLED ); + set_cursor_pos( 0, 0 ); + Global.ControlPicking = false; + + // main application loop + // TODO: split into parts and delegate these to application mode member + while( ( false == glfwWindowShouldClose( m_window ) ) + && ( true == World.Update() ) + && ( true == GfxRenderer.Render() ) ) { + glfwPollEvents(); + input::Keyboard.poll(); + if (input::motiontelemetry) + input::motiontelemetry->update(); + if (screenshot_queued) + { + screenshot_queued = false; + screenshot_man.make_screenshot(); + } + if( true == Global.InputMouse ) { input::Mouse.poll(); } + if( true == Global.InputGamepad ) { input::Gamepad.poll(); } + if( input::uart != nullptr ) { input::uart->poll(); } + // TODO: wrap current command in object, include other input sources + input::command = ( + input::Mouse.command() != user_command::none ? + input::Mouse.command() : + input::Keyboard.command() ); + } + + return 0; +} + +void +eu07_application::exit() { + +#ifdef _WIN32 + Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej) +#endif + SafeDelete( simulation::Region ); + + glfwDestroyWindow( m_window ); + glfwTerminate(); + + TPythonInterpreter::killInstance(); +} + +void +eu07_application::set_cursor( int const Mode ) { + + UILayer.set_cursor( Mode ); +} + +void +eu07_application::set_cursor_pos( double const X, double const Y ) { + + if( m_window != nullptr ) { + glfwSetCursorPos( m_window, X, Y ); + } +} + +void +eu07_application::get_cursor_pos( double &X, double &Y ) const { + + if( m_window != nullptr ) { + glfwGetCursorPos( m_window, &X, &Y ); + } +} + +// private: + +void +eu07_application::init_debug() { + +#if defined(_MSC_VER) && defined (_DEBUG) + // memory leaks + _CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_LEAK_CHECK_DF ); + // floating point operation errors + auto state { _clearfp() }; + state = _control87( 0, 0 ); + // this will turn on FPE for #IND and zerodiv + state = _control87( state & ~( _EM_ZERODIVIDE | _EM_INVALID ), _MCW_EM ); +#endif +#ifdef _WIN32 + ::SetUnhandledExceptionFilter( unhandled_handler ); +#endif +} + +void +eu07_application::init_files() { + +#ifdef _WIN32 + DeleteFile( "log.txt" ); + DeleteFile( "errors.txt" ); + CreateDirectory( "logs", NULL ); +#elif __linux__ + unlink("log.txt"); + unlink("errors.txt"); + mkdir("logs", 0664); +#endif +} + +int +eu07_application::init_settings( int Argc, char *Argv[] ) { + + Global.LoadIniFile( "eu07.ini" ); +#ifdef _WIN32 + if( ( Global.iWriteLogEnabled & 2 ) != 0 ) { + // show output console if requested + AllocConsole(); + } +#endif + + Global.asVersion = VERSION_INFO; + + // process command line arguments + for( int i = 1; i < Argc; ++i ) { + + std::string token { Argv[ i ] }; + + if( token == "-e3d" ) { + Global.iConvertModels = ( + Global.iConvertModels > 0 ? + -Global.iConvertModels : + -7 ); // z optymalizacją, bananami i prawidłowym Opacity + } + else if( token == "-s" ) { + if( i + 1 < Argc ) { + Global.SceneryFile = ToLower( Argv[ ++i ] ); + } + } + else if( token == "-v" ) { + if( i + 1 < Argc ) { + Global.asHumanCtrlVehicle = ToLower( Argv[ ++i ] ); + } + } + else { + std::cout + << "usage: " << std::string( Argv[ 0 ] ) + << " [-s sceneryfilepath]" + << " [-v vehiclename]" + << " [-e3d]" + << std::endl; + return -1; + } + } + + return 0; +} + +int +eu07_application::init_glfw() +{ + if( glfwInit() == GLFW_FALSE ) { + ErrorLog( "Bad init: failed to initialize glfw" ); + return -1; + } + + // match requested video mode to current to allow for + // fullwindow creation when resolution is the same + auto *monitor { glfwGetPrimaryMonitor() }; + auto const *vmode { glfwGetVideoMode( monitor ) }; + + glfwWindowHint( GLFW_RED_BITS, vmode->redBits ); + glfwWindowHint( GLFW_GREEN_BITS, vmode->greenBits ); + glfwWindowHint( GLFW_BLUE_BITS, vmode->blueBits ); + glfwWindowHint( GLFW_REFRESH_RATE, vmode->refreshRate ); + + glfwWindowHint( GLFW_AUTO_ICONIFY, GLFW_FALSE ); + if( Global.iMultisampling > 0 ) { + glfwWindowHint( GLFW_SAMPLES, 1 << Global.iMultisampling ); + } + + auto *window { + glfwCreateWindow( + Global.iWindowWidth, + Global.iWindowHeight, + Global.AppName.c_str(), + ( Global.bFullScreen ? + monitor : + nullptr ), + nullptr ) }; + + if( window == nullptr ) { + ErrorLog( "Bad init: failed to create glfw window" ); + return -1; + } + + glfwMakeContextCurrent( window ); + glfwSwapInterval( Global.VSync ? 1 : 0 ); //vsync + +#ifdef _WIN32 +// setup wrapper for base glfw window proc, to handle copydata messages + Hwnd = glfwGetWin32Window( window ); + BaseWindowProc = ( WNDPROC )::SetWindowLongPtr( Hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc ); + // switch off the topmost flag + ::SetWindowPos( Hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); +#endif + // TBD, TODO: move the global pointer to a more appropriate place + m_window = window; + + return 0; +} + +void +eu07_application::init_callbacks() { + + glfwSetFramebufferSizeCallback( m_window, window_resize_callback ); + glfwSetCursorPosCallback( m_window, cursor_pos_callback ); + glfwSetMouseButtonCallback( m_window, mouse_button_callback ); + glfwSetKeyCallback( m_window, key_callback ); + glfwSetScrollCallback( m_window, scroll_callback ); + glfwSetWindowFocusCallback( m_window, focus_callback ); + { + int width, height; + glfwGetFramebufferSize( m_window, &width, &height ); + window_resize_callback( m_window, width, height ); + } +} + +int +eu07_application::init_gfx() { + + if( glewInit() != GLEW_OK ) { + ErrorLog( "Bad init: failed to initialize glew" ); + return -1; + } + + if( ( false == GfxRenderer.Init( m_window ) ) + || ( false == UILayer.init( m_window ) ) ) { + return -1; + } + + return 0; +} + +int +eu07_application::init_audio() { + + if( Global.bSoundEnabled ) { + Global.bSoundEnabled &= audio::renderer.init(); + } + // NOTE: lack of audio isn't deemed a failure serious enough to throw in the towel + return 0; +} diff --git a/application.h b/application.h new file mode 100644 index 00000000..71afd949 --- /dev/null +++ b/application.h @@ -0,0 +1,50 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +class eu07_application { + +public: +// constructors + eu07_application() = default; +// methods + int + init( int Argc, char *Argv[] ); + int + run(); + void + exit(); + void + set_cursor( int const Mode ); + void + set_cursor_pos( double const X, double const Y ); + void + get_cursor_pos( double &X, double &Y ) const; + void queue_screenshot(); + inline + GLFWwindow * + window() { + return m_window; } + +private: +// methods + void init_debug(); + void init_files(); + int init_settings( int Argc, char *Argv[] ); + int init_glfw(); + void init_callbacks(); + int init_gfx(); + int init_audio(); +// members + GLFWwindow * m_window { nullptr }; + bool screenshot_queued = false; +}; + +extern eu07_application Application; diff --git a/audiorenderer.cpp b/audiorenderer.cpp index 4348c929..a7509b1e 100644 --- a/audiorenderer.cpp +++ b/audiorenderer.cpp @@ -21,6 +21,20 @@ namespace audio { openal_renderer renderer; float const EU07_SOUND_CUTOFFRANGE { 3000.f }; // 2750 m = max expected emitter spawn range, plus safety margin +float const EU07_SOUND_VELOCITYLIMIT { 250 / 3.6f }; // 343 m/sec ~= speed of sound; arbitrary limit of 250 km/h + +// potentially clamps length of provided vector to 343 meters +// TBD: make a generic method for utilities out of this +glm::vec3 +limit_velocity( glm::vec3 const &Velocity ) { + + auto const ratio { glm::length( Velocity ) / EU07_SOUND_VELOCITYLIMIT }; + + return ( + ratio > 1.f ? + Velocity / ratio : + Velocity ); +} // starts playback of queued buffers void @@ -93,7 +107,7 @@ openal_source::sync_with( sound_properties const &State ) { && ( sound_range >= 0 ) && ( properties.location != glm::dvec3() ) ) { // after sound position was initialized we can start velocity calculations - sound_velocity = ( State.location - properties.location ) / update_deltatime; + sound_velocity = limit_velocity( ( State.location - properties.location ) / update_deltatime ); } // NOTE: velocity at this point can be either listener velocity for global sounds, actual sound velocity, or 0 if sound position is yet unknown ::alSourcefv( id, AL_VELOCITY, glm::value_ptr( sound_velocity ) ); @@ -337,8 +351,8 @@ openal_renderer::update( double const Deltatime ) { m_listenerposition = listenerposition; m_listenervelocity = ( glm::length( listenermovement ) < 1000.0 ? // large jumps are typically camera changes - listenermovement / Deltatime : - glm::dvec3() ); + limit_velocity( listenermovement / Deltatime ) : + glm::vec3() ); ::alListenerfv( AL_VELOCITY, reinterpret_cast( glm::value_ptr( m_listenervelocity ) ) ); } diff --git a/audiorenderer.h b/audiorenderer.h index bb7c9afe..6084d94e 100644 --- a/audiorenderer.h +++ b/audiorenderer.h @@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/. #include "ResourceManager.h" #include "uitranscripts.h" +class opengl_renderer; class sound_source; using uint32_sequence = std::vector; @@ -100,7 +101,7 @@ private: class openal_renderer { - friend class opengl_renderer; + friend opengl_renderer; public: // constructors diff --git a/command.cpp b/command.cpp index d0da0def..6eef3f36 100644 --- a/command.cpp +++ b/command.cpp @@ -263,7 +263,7 @@ command_queue::pop( command_data &Command, std::size_t const Recipient ) { } void -command_relay::post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, +command_relay::post( user_command const Command, double const Param1, double const Param2, int const Action, std::uint16_t const Recipient) const { auto const &command = simulation::Commands_descriptions[ static_cast( Command ) ]; diff --git a/command.h b/command.h index 7065ea2e..cd7b2c82 100644 --- a/command.h +++ b/command.h @@ -237,8 +237,8 @@ struct command_data { user_command command; int action; // press, repeat or release - std::uint64_t param1; - std::uint64_t param2; + double param1; + double param2; double time_delta; }; @@ -292,7 +292,7 @@ public: // posts specified command for the specified recipient // TODO: replace uint16_t with recipient handle, based on item id void - post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, + post( user_command const Command, double const Param1, double const Param2, int const Action, std::uint16_t const Recipient ) const; private: // types diff --git a/gamepadinput.cpp b/gamepadinput.cpp index c7a23c56..7f1b93ff 100644 --- a/gamepadinput.cpp +++ b/gamepadinput.cpp @@ -198,8 +198,8 @@ gamepad_input::process_axes( glm::vec2 Leftstick, glm::vec2 const &Rightstick, g double const turny = -Rightstick.y * 10.0 * deltatime; m_relay.post( user_command::viewturn, - reinterpret_cast( turnx ), - reinterpret_cast( turny ), + turnx, + turny, GLFW_PRESS, // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // TODO: pass correct entity id once the missing systems are in place @@ -211,12 +211,10 @@ gamepad_input::process_axes( glm::vec2 Leftstick, glm::vec2 const &Rightstick, g if( ( Leftstick.x != 0.0 || Leftstick.y != 0.0 ) || ( m_leftstick.x != 0.0 || m_leftstick.y != 0.0 ) ) { - double const movex = static_cast( Leftstick.x ); - double const movez = static_cast( Leftstick.y ); m_relay.post( user_command::movehorizontal, - reinterpret_cast( movex ), - reinterpret_cast( movez ), + Leftstick.x, + Leftstick.y, GLFW_PRESS, 0 ); } diff --git a/keyboardinput.cpp b/keyboardinput.cpp index 461a98b4..d20cf003 100644 --- a/keyboardinput.cpp +++ b/keyboardinput.cpp @@ -12,9 +12,6 @@ http://mozilla.org/MPL/2.0/. #include "Logs.h" #include "Globals.h" #include "parser.h" -#include "World.h" - -extern TWorld World; bool keyboard_input::recall_bindings() { @@ -161,6 +158,10 @@ keyboard_input::key( int const Key, int const Action ) { // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // TODO: pass correct entity id once the missing systems are in place m_relay.post( lookup->second, 0, 0, Action, 0 ); + m_command = ( + Action == GLFW_RELEASE ? + user_command::none : + lookup->second ); return true; } @@ -600,14 +601,12 @@ keyboard_input::poll() { if( ( movementhorizontal.x != 0.f || movementhorizontal.y != 0.f ) || ( m_movementhorizontal.x != 0.f || m_movementhorizontal.y != 0.f ) ) { - double const movexparam = static_cast( movementhorizontal.x ); - double const movezparam = static_cast( movementhorizontal.y ); m_relay.post( ( true == Global.ctrlState ? user_command::movehorizontalfast : user_command::movehorizontal ), - reinterpret_cast( movexparam ), - reinterpret_cast( movezparam ), + movementhorizontal.x, + movementhorizontal.y, GLFW_PRESS, 0 ); } @@ -623,12 +622,11 @@ keyboard_input::poll() { if( ( movementvertical != 0.f ) || ( m_movementvertical != 0.f ) ) { - double const moveyparam = static_cast( movementvertical ); m_relay.post( ( true == Global.ctrlState ? user_command::moveverticalfast : user_command::movevertical ), - reinterpret_cast( moveyparam ), + movementvertical, 0, GLFW_PRESS, 0 ); diff --git a/keyboardinput.h b/keyboardinput.h index ab5bb0bc..0e59b258 100644 --- a/keyboardinput.h +++ b/keyboardinput.h @@ -28,6 +28,10 @@ public: key( int const Key, int const Action ); void poll(); + inline + user_command const + command() const { + return m_command; } private: // types @@ -65,13 +69,14 @@ private: // members commandsetup_sequence m_commands; + user_command m_command { user_command::none }; // last, if any, issued command usercommand_map m_bindings; command_relay m_relay; - bool m_shift{ false }; - bool m_ctrl{ false }; + bool m_shift { false }; + bool m_ctrl { false }; bindings_cache m_bindingscache; - glm::vec2 m_movementhorizontal; - float m_movementvertical; + glm::vec2 m_movementhorizontal { 0.f }; + float m_movementvertical { 0.f }; std::array m_keys; }; diff --git a/messaging.cpp b/messaging.cpp index 8b30c652..7ada5b92 100644 --- a/messaging.cpp +++ b/messaging.cpp @@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/. #include "messaging.h" #include "Globals.h" +#include "application.h" #include "simulation.h" #include "mtable.h" #include "Logs.h" @@ -51,7 +52,7 @@ WyslijEvent(const std::string &e, const std::string &d) cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura cData.cbData = (DWORD)(12 + i + j); // 8+dwa liczniki i dwa zera kończące cData.lpData = &r; - Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData ); + Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData ); CommLog( Now() + " " + std::to_string(r.iComm) + " " + e + " sent" ); #endif } @@ -71,7 +72,7 @@ WyslijUszkodzenia(const std::string &t, char fl) cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura cData.cbData = (DWORD)(11 + i); // 8+licznik i zero kończące cData.lpData = &r; - Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData ); + Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData ); CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent"); #endif } @@ -90,7 +91,7 @@ WyslijString(const std::string &t, int n) cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura cData.cbData = (DWORD)(10 + i); // 8+licznik i zero kończące cData.lpData = &r; - Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData ); + Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData ); CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent"); #endif } @@ -173,7 +174,7 @@ WyslijNamiary(TDynamicObject const *Vehicle) cData.cbData = (DWORD)(10 + i + j); // 8+licznik i zero kończące cData.lpData = &r; // WriteLog("Ramka gotowa"); - Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData ); + Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData ); // WriteLog("Ramka poszla!"); CommLog( Now() + " " + std::to_string(r.iComm) + " " + Vehicle->asName + " sent"); #endif @@ -198,7 +199,7 @@ WyslijObsadzone() r.fPar[ 16 * i + 4 ] = vehicle->GetPosition().x; r.fPar[ 16 * i + 5 ] = vehicle->GetPosition().y; r.fPar[ 16 * i + 6 ] = vehicle->GetPosition().z; - r.iPar[ 16 * i + 7 ] = vehicle->Mechanik->GetAction(); + r.iPar[ 16 * i + 7 ] = static_cast( vehicle->Mechanik->GetAction() ); strcpy( r.cString + 64 * i + 32, vehicle->GetTrack()->IsolatedName().c_str() ); strcpy( r.cString + 64 * i + 48, vehicle->Mechanik->TrainName().c_str() ); i++; @@ -222,7 +223,7 @@ WyslijObsadzone() cData.cbData = 8 + 1984; // 8+licznik i zero kończące cData.lpData = &r; // WriteLog("Ramka gotowa"); - Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData ); + Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData ); CommLog( Now() + " " + std::to_string(r.iComm) + " obsadzone" + " sent"); #endif } @@ -248,7 +249,7 @@ WyslijParam(int nr, int fl) cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura cData.cbData = 12 + i; // 12+rozmiar danych cData.lpData = &r; - Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData ); + Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData ); #endif } diff --git a/moon.cpp b/moon.cpp index 668bc4bf..a6814ac0 100644 --- a/moon.cpp +++ b/moon.cpp @@ -3,6 +3,11 @@ #include "Globals.h" #include "mtable.h" #include "World.h" +#include "utilities.h" +#include "simulationtime.h" + +////////////////////////////////////////////////////////////////////////////////////////// +// cSun -- class responsible for dynamic calculation of position and intensity of the Sun, cMoon::cMoon() { diff --git a/mouseinput.cpp b/mouseinput.cpp index a63fc02b..12eec82f 100644 --- a/mouseinput.cpp +++ b/mouseinput.cpp @@ -14,9 +14,111 @@ http://mozilla.org/MPL/2.0/. #include "World.h" #include "Train.h" #include "utilities.h" +#include "application.h" +#include "utilities.h" +#include "simulation.h" #include "renderer.h" +#include "uilayer.h" + +void +mouse_slider::bind( user_command const &Command ) { + + m_command = Command; + + auto const *train { World.train() }; + TMoverParameters const *vehicle { nullptr }; + switch( m_command ) { + case user_command::mastercontrollerset: + case user_command::secondcontrollerset: { + vehicle = ( train ? train->Controlled() : nullptr ); + break; + } + case user_command::trainbrakeset: + case user_command::independentbrakeset: { + vehicle = ( train ? train->Occupied() : nullptr ); + break; + } + default: { + break; + } + } + if( vehicle == nullptr ) { return; } + + // calculate initial value and accepted range + switch( m_command ) { + case user_command::mastercontrollerset: { + m_valuerange = ( + vehicle->CoupledCtrl ? + vehicle->MainCtrlPosNo + vehicle->ScndCtrlPosNo : + vehicle->MainCtrlPosNo ); + m_value = ( + vehicle->CoupledCtrl ? + vehicle->MainCtrlPos + vehicle->ScndCtrlPos : + vehicle->MainCtrlPos ); + m_analogue = false; + break; + } + case user_command::secondcontrollerset: { + m_valuerange = vehicle->ScndCtrlPosNo; + m_value = vehicle->ScndCtrlPos; + m_analogue = false; + break; + } + case user_command::trainbrakeset: { + m_valuerange = 1.0; + m_value = ( vehicle->fBrakeCtrlPos - vehicle->Handle->GetPos( bh_MIN ) ) / ( vehicle->Handle->GetPos( bh_MAX ) - vehicle->Handle->GetPos( bh_MIN ) ); + m_analogue = true; + break; + } + case user_command::independentbrakeset: { + m_valuerange = 1.0; + m_value = vehicle->LocalBrakePosA; + m_analogue = true; + break; + } + default: { + m_valuerange = 1; + break; + } + } + // hide the cursor and place it in accordance with current slider value + Application.get_cursor_pos( m_cursorposition.x, m_cursorposition.y ); + Application.set_cursor( GLFW_CURSOR_DISABLED ); + + auto const controlsize { Global.iWindowHeight * 0.75 }; + auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 }; + auto const stepsize { controlsize / m_valuerange }; + + Application.set_cursor_pos( + Global.iWindowWidth * 0.5, + ( m_analogue ? + controledge - ( 1.0 - m_value ) * controlsize : + controledge - m_value * stepsize - 0.5 * stepsize ) ); +} + +void +mouse_slider::release() { + + m_command = user_command::none; + Application.set_cursor_pos( m_cursorposition.x, m_cursorposition.y ); + Application.set_cursor( GLFW_CURSOR_NORMAL ); +} + +void +mouse_slider::on_move( double const Mousex, double const Mousey ) { + + auto const controlsize { Global.iWindowHeight * 0.75 }; + auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 }; + auto const stepsize { controlsize / m_valuerange }; + + auto mousey = clamp( Mousey, controledge - controlsize, controledge ); + m_value = ( + m_analogue ? + 1.0 - ( ( controledge - mousey ) / controlsize ) : + std::floor( ( controledge - mousey ) / stepsize ) ); +} + -extern TWorld World; bool mouse_input::init() { @@ -39,8 +141,8 @@ mouse_input::move( double Mousex, double Mousey ) { // default control mode m_relay.post( user_command::viewturn, - reinterpret_cast( Mousex ), - reinterpret_cast( Mousey ), + Mousex, + Mousey, GLFW_PRESS, // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // TODO: pass correct entity id once the missing systems are in place @@ -48,6 +150,17 @@ mouse_input::move( double Mousex, double Mousey ) { } else { // control picking mode + if( m_slider.command() != user_command::none ) { + m_slider.on_move( Mousex, Mousey ); + m_relay.post( + m_slider.command(), + m_slider.value(), + 0, + GLFW_PRESS, + // TODO: pass correct entity id once the missing systems are in place + 0 ); + } + if( false == m_pickmodepanning ) { // even if the view panning isn't active we capture the cursor position in case it does get activated m_cursorposition.x = Mousex; @@ -58,8 +171,8 @@ mouse_input::move( double Mousex, double Mousey ) { auto const viewoffset = cursorposition - m_cursorposition; m_relay.post( user_command::viewturn, - reinterpret_cast( viewoffset.x ), - reinterpret_cast( viewoffset.y ), + viewoffset.x, + viewoffset.y, GLFW_PRESS, // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // TODO: pass correct entity id once the missing systems are in place @@ -74,33 +187,21 @@ mouse_input::button( int const Button, int const Action ) { if( false == Global.ControlPicking ) { return; } if( true == FreeFlyModeFlag ) { - // world editor controls - // TODO: separate behaviour when the scenery editor is active and in 'regular' free fly mode - if( Action == GLFW_RELEASE ) { - // if it's the right mouse button that got released we were potentially in view panning mode; stop it - if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { - m_pickmodepanning = false; + // freefly mode + // left mouse button launches on_click event associated with to the node + if( Button == GLFW_MOUSE_BUTTON_LEFT ) { + if( Action == GLFW_PRESS ) { + auto const *node { GfxRenderer.Update_Pick_Node() }; + if( ( node == nullptr ) + || ( typeid( *node ) != typeid( TAnimModel ) ) ) { + return; + } + simulation::Region->on_click( static_cast( node ) ); } } - else { - // button press - if( Button == GLFW_MOUSE_BUTTON_LEFT ) { - // the left button selects scene node - // further behaviour can vary depending on whether we're in editor mode - auto const *node { GfxRenderer.Update_Pick_Node() }; - if( true == EditorModeFlag ) { - // NOTE: until we have proper editor object in place we set the current node manually - editor::Node = node; - } - else { - // launch on_click event associated with to the node - // TODO: implement - } - } - if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { - // the right button activates mouse panning mode - m_pickmodepanning = true; - } + // right button controls panning + if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { + m_pickmodepanning = ( Action == GLFW_PRESS ); } } else { @@ -120,6 +221,11 @@ mouse_input::button( int const Button, int const Action ) { mousecommand = user_command::none; } else { + if( Button == GLFW_MOUSE_BUTTON_LEFT ) { + if( m_slider.command() != user_command::none ) { + m_slider.release(); + } + } // if it's the right mouse button that got released and we had no command active, we were potentially in view panning mode; stop it if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { m_pickmodepanning = false; @@ -130,60 +236,65 @@ mouse_input::button( int const Button, int const Action ) { } else { // if not release then it's press - auto train = World.train(); - if( train != nullptr ) { - auto lookup = m_mousecommands.find( train->GetLabel( GfxRenderer.Update_Pick_Control() ) ); - if( lookup != m_mousecommands.end() ) { - mousecommand = ( - Button == GLFW_MOUSE_BUTTON_LEFT ? - lookup->second.left : - lookup->second.right - ); - if( mousecommand != user_command::none ) { - // check manually for commands which have 'fast' variants launched with shift modifier - if( Global.shiftState ) { - switch( mousecommand ) { - case user_command::mastercontrollerincrease: { mousecommand = user_command::mastercontrollerincreasefast; break; } - case user_command::mastercontrollerdecrease: { mousecommand = user_command::mastercontrollerdecreasefast; break; } - case user_command::secondcontrollerincrease: { mousecommand = user_command::secondcontrollerincreasefast; break; } - case user_command::secondcontrollerdecrease: { mousecommand = user_command::secondcontrollerdecreasefast; break; } - case user_command::independentbrakeincrease: { mousecommand = user_command::independentbrakeincreasefast; break; } - case user_command::independentbrakedecrease: { mousecommand = user_command::independentbrakedecreasefast; break; } - default: { break; } - } - } - // NOTE: basic keyboard controls don't have any parameters - // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 - // TODO: pass correct entity id once the missing systems are in place - m_relay.post( mousecommand, 0, 0, Action, 0 ); - m_updateaccumulator = -0.25; // prevent potential command repeat right after issuing one - - switch( mousecommand ) { - case user_command::mastercontrollerincrease: - case user_command::mastercontrollerdecrease: - case user_command::secondcontrollerincrease: - case user_command::secondcontrollerdecrease: - case user_command::trainbrakeincrease: - case user_command::trainbrakedecrease: - case user_command::independentbrakeincrease: - case user_command::independentbrakedecrease: { - // these commands trigger varying repeat rate mode, - // which scales the rate based on the distance of the cursor from its point when the command was first issued - m_commandstartcursor = m_cursorposition; - m_varyingpollrate = true; - break; - } - default: { - break; - } - } + auto const lookup = m_mousecommands.find( World.train()->GetLabel( GfxRenderer.Update_Pick_Control() ) ); + if( lookup != m_mousecommands.end() ) { + // if the recognized element under the cursor has a command associated with the pressed button, notify the recipient + mousecommand = ( + Button == GLFW_MOUSE_BUTTON_LEFT ? + lookup->second.left : + lookup->second.right + ); + if( mousecommand == user_command::none ) { return; } + // check manually for commands which have 'fast' variants launched with shift modifier + if( Global.shiftState ) { + switch( mousecommand ) { + case user_command::mastercontrollerincrease: { mousecommand = user_command::mastercontrollerincreasefast; break; } + case user_command::mastercontrollerdecrease: { mousecommand = user_command::mastercontrollerdecreasefast; break; } + case user_command::secondcontrollerincrease: { mousecommand = user_command::secondcontrollerincreasefast; break; } + case user_command::secondcontrollerdecrease: { mousecommand = user_command::secondcontrollerdecreasefast; break; } + case user_command::independentbrakeincrease: { mousecommand = user_command::independentbrakeincreasefast; break; } + case user_command::independentbrakedecrease: { mousecommand = user_command::independentbrakedecreasefast; break; } + default: { break; } } } - else { - // if we don't have any recognized element under the cursor and the right button was pressed, enter view panning mode - if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { - m_pickmodepanning = true; + + switch( mousecommand ) { + case user_command::mastercontrollerincrease: + case user_command::mastercontrollerdecrease: + case user_command::secondcontrollerincrease: + case user_command::secondcontrollerdecrease: + case user_command::trainbrakeincrease: + case user_command::trainbrakedecrease: + case user_command::independentbrakeincrease: + case user_command::independentbrakedecrease: { + // these commands trigger varying repeat rate mode, + // which scales the rate based on the distance of the cursor from its point when the command was first issued + m_varyingpollrateorigin = m_cursorposition; + m_varyingpollrate = true; + break; } + case user_command::mastercontrollerset: + case user_command::secondcontrollerset: + case user_command::trainbrakeset: + case user_command::independentbrakeset: { + m_slider.bind( mousecommand ); + mousecommand = user_command::none; + return; + } + default: { + break; + } + } + // NOTE: basic keyboard controls don't have any parameters + // NOTE: as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 + // TODO: pass correct entity id once the missing systems are in place + m_relay.post( mousecommand, 0, 0, Action, 0 ); + m_updateaccumulator = -0.25; // prevent potential command repeat right after issuing one + } + else { + // if we don't have any recognized element under the cursor and the right button was pressed, enter view panning mode + if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { + m_pickmodepanning = true; } } } @@ -197,7 +308,7 @@ mouse_input::poll() { auto updaterate { m_updaterate }; if( m_varyingpollrate ) { - updaterate /= std::max( 0.15, 2.0 * glm::length( m_cursorposition - m_commandstartcursor ) / std::max( 1, Global.iWindowHeight ) ); + updaterate /= std::max( 0.15, 2.0 * glm::length( m_cursorposition - m_varyingpollrateorigin ) / std::max( 1, Global.iWindowHeight ) ); } while( m_updateaccumulator > updaterate ) { @@ -218,16 +329,25 @@ mouse_input::poll() { } } +user_command +mouse_input::command() const { + + return ( + m_slider.command() != user_command::none ? m_slider.command() : + m_mousecommandleft != user_command::none ? m_mousecommandleft : + m_mousecommandright ); +} + void mouse_input::default_bindings() { m_mousecommands = { { "mainctrl:", { - user_command::mastercontrollerincrease, - user_command::mastercontrollerdecrease } }, + user_command::mastercontrollerset, + user_command::none } }, { "scndctrl:", { - user_command::secondcontrollerincrease, - user_command::secondcontrollerdecrease } }, + user_command::secondcontrollerset, + user_command::none } }, { "shuntmodepower:", { user_command::secondcontrollerincrease, user_command::secondcontrollerdecrease } }, @@ -235,11 +355,11 @@ mouse_input::default_bindings() { user_command::reverserincrease, user_command::reverserdecrease } }, { "brakectrl:", { - user_command::trainbrakeincrease, - user_command::trainbrakedecrease } }, + user_command::trainbrakeset, + user_command::none } }, { "localbrake:", { - user_command::independentbrakeincrease, - user_command::independentbrakedecrease } }, + user_command::independentbrakeset, + user_command::none } }, { "manualbrake:", { user_command::manualbrakeincrease, user_command::manualbrakedecrease } }, @@ -404,10 +524,10 @@ mouse_input::default_bindings() { user_command::pantographtogglerear, user_command::none } }, { "pantfrontoff_sw:", { - user_command::pantographtogglefront, + user_command::pantographlowerfront, user_command::none } }, // TODO: dedicated lower pantograph commands { "pantrearoff_sw:", { - user_command::pantographtogglerear, + user_command::pantographlowerrear, user_command::none } }, // TODO: dedicated lower pantograph commands { "pantalloff_sw:", { user_command::pantographlowerall, diff --git a/mouseinput.h b/mouseinput.h index ff9c77eb..c0fa2cb2 100644 --- a/mouseinput.h +++ b/mouseinput.h @@ -12,6 +12,36 @@ http://mozilla.org/MPL/2.0/. #include #include "command.h" +// virtual slider; value determined by position of the mouse +class mouse_slider { + +public: +// constructors + mouse_slider() = default; +// methods + void + bind( user_command const &Command ); + void + release(); + void + on_move( double const Mousex, double const Mousey ); + inline + user_command + command() const { + return m_command; } + double + value() const { + return m_value; } + +private: +// members + user_command m_command { user_command::none }; + double m_value { 0.0 }; + double m_valuerange { 0.0 }; + bool m_analogue { false }; + glm::dvec2 m_cursorposition { 0.0 }; +}; + class mouse_input { public: @@ -21,12 +51,14 @@ public: // methods bool init(); - void - move( double const Mousex, double const Mousey ); void button( int const Button, int const Action ); + void + move( double const Mousex, double const Mousey ); void poll(); + user_command + command() const; private: // types @@ -44,6 +76,7 @@ private: // members command_relay m_relay; + mouse_slider m_slider; // virtual control, when active translates intercepted mouse position to a value controlcommands_map m_mousecommands; user_command m_mousecommandleft { user_command::none }; // last if any command issued with left mouse button user_command m_mousecommandright { user_command::none }; // last if any command issued with right mouse button @@ -52,8 +85,8 @@ private: double m_updateaccumulator { 0.0 }; bool m_pickmodepanning { false }; // indicates mouse is in view panning mode glm::dvec2 m_cursorposition; // stored last cursor position, used for panning - glm::dvec2 m_commandstartcursor; // helper, cursor position when the command was initiated bool m_varyingpollrate { false }; // indicates rate of command repeats is affected by the cursor position + glm::dvec2 m_varyingpollrateorigin; // helper, cursor position when the command was initiated }; //--------------------------------------------------------------------------- diff --git a/mtable.cpp b/mtable.cpp index 543082a4..f7c64eb1 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/. #include "mtable.h" #include "World.h" #include "Globals.h" +#include "simulationtime.h" #include "utilities.h" double TTrainParameters::CheckTrainLatency() @@ -48,7 +49,7 @@ bool TTrainParameters::IsStop() return true; // na ostatnim się zatrzymać zawsze } -bool TTrainParameters::UpdateMTable( simulation_time const &Time, std::string const &NewName ) { +bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) { return UpdateMTable( Time.data().wHour, Time.data().wMinute, NewName ); } diff --git a/mtable.h b/mtable.h index a02af9a6..c28dec87 100644 --- a/mtable.h +++ b/mtable.h @@ -74,7 +74,7 @@ class TTrainParameters bool IsStop(); bool IsTimeToGo(double hh, double mm); bool UpdateMTable(double hh, double mm, std::string const &NewName); - bool UpdateMTable( simulation_time const &Time, std::string const &NewName ); + bool UpdateMTable( scenario_time const &Time, std::string const &NewName ); bool RewindTimeTable( std::string actualStationName ); TTrainParameters( std::string const &NewTrainName ); void NewName(std::string const &NewTrainName); diff --git a/openglgeometrybank.h b/openglgeometrybank.h index b6045eec..ec3c5cb8 100644 --- a/openglgeometrybank.h +++ b/openglgeometrybank.h @@ -51,7 +51,7 @@ struct stream_units { std::vector texture { GL_TEXTURE0 }; // unit associated with main texture data stream. TODO: allow multiple units per stream }; -typedef std::vector vertex_array; +using vertex_array = std::vector; // generic geometry bank class, allows storage, update and drawing of geometry chunks @@ -129,7 +129,7 @@ protected: } }; - typedef std::vector geometrychunk_sequence; + using geometrychunk_sequence = std::vector; // methods inline @@ -181,21 +181,21 @@ private: bool is_good{ false }; // true if local content of the chunk matches the data on the opengl end }; - typedef std::vector chunkrecord_sequence; + using chunkrecord_sequence = std::vector; // methods: // create() subclass details void - create_( gfx::geometry_handle const &Geometry ); + create_( gfx::geometry_handle const &Geometry ) override; // replace() subclass details void - replace_( gfx::geometry_handle const &Geometry ); + replace_( gfx::geometry_handle const &Geometry ) override; // draw() subclass details void - draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ); + draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) override; // release() subclass details void - release_(); + release_() override; void bind_buffer(); void @@ -236,21 +236,21 @@ private: unsigned int streams { 0 }; // stream combination used to generate the display list }; - typedef std::vector chunkrecord_sequence; + using chunkrecord_sequence = std::vector; // methods: // create() subclass details void - create_( gfx::geometry_handle const &Geometry ); + create_( gfx::geometry_handle const &Geometry ) override; // replace() subclass details void - replace_( gfx::geometry_handle const &Geometry ); + replace_( gfx::geometry_handle const &Geometry ) override; // draw() subclass details void - draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ); + draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) override; // release () subclass details void - release_(); + release_() override; void delete_list( gfx::geometry_handle const &Geometry ); @@ -261,7 +261,7 @@ private: // geometry bank manager, holds collection of geometry banks -typedef geometry_handle geometrybank_handle; +using geometrybank_handle = geometry_handle; class geometrybank_manager { @@ -301,11 +301,8 @@ public: private: // types: - typedef std::pair< - std::shared_ptr, - resource_timestamp > geometrybanktimepoint_pair; - - typedef std::deque< geometrybanktimepoint_pair > geometrybanktimepointpair_sequence; + using geometrybanktimepoint_pair = std::pair< std::shared_ptr, resource_timestamp >; + using geometrybanktimepointpair_sequence = std::deque< geometrybanktimepoint_pair >; // members: geometrybanktimepointpair_sequence m_geometrybanks; diff --git a/renderer.cpp b/renderer.cpp index 0bcdf099..5ad9d6ed 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -15,12 +15,16 @@ http://mozilla.org/MPL/2.0/. #include "Timer.h" #include "Train.h" #include "simulation.h" +#include "simulationtime.h" +#include "World.h" +#include "DynObj.h" +#include "AnimModel.h" +#include "Traction.h" #include "uilayer.h" #include "Logs.h" #include "utilities.h" opengl_renderer GfxRenderer; -extern TWorld World; int const EU07_PICKBUFFERSIZE { 1024 }; // size of (square) textures bound with the pick framebuffer int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental cube map texture @@ -471,6 +475,8 @@ opengl_renderer::Render_pass( rendermode const Mode ) { case rendermode::color: { + m_colorpass = m_renderpass; + if( ( true == Global.RenderShadows ) && ( false == Global.bWireFrame ) && ( true == World.InitPerformed() ) @@ -1688,6 +1694,11 @@ opengl_renderer::Render( scene::basic_region *Region ) { Update_Lights( simulation::Lights ); Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) ); + if( EditorModeFlag && FreeFlyModeFlag ) { + // when editor mode is active calculate world position of the cursor + // at this stage the z-buffer is filled with only ground geometry + Update_Mouse_Position(); + } // draw queue is filled while rendering sections Render( std::begin( m_cellqueue ), std::end( m_cellqueue ) ); break; @@ -1932,7 +1943,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator ::glPushAttrib( GL_ENABLE_BIT ); ::glDisable( GL_TEXTURE_2D ); ::glColor3f( 0.36f, 0.75f, 0.35f ); - for( auto const *memorycell : cell->m_memorycells ) { + for( auto *memorycell : cell->m_memorycells ) { Render( memorycell ); } ::glPopAttrib(); @@ -1949,7 +1960,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator // memcells if( ( EditorModeFlag ) && ( DebugModeFlag ) ) { - for( auto const *memorycell : cell->m_memorycells ) { + for( auto *memorycell : cell->m_memorycells ) { ::glColor3fv( glm::value_ptr( pick_color( m_picksceneryitems.size() + 1 ) ) ); Render( memorycell ); } @@ -2330,16 +2341,16 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, float c } bool -opengl_renderer::Render( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ) { +opengl_renderer::Render( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, glm::vec3 const &Angle ) { ::glPushMatrix(); ::glTranslated( Position.x, Position.y, Position.z ); if( Angle.y != 0.0 ) - ::glRotated( Angle.y, 0.0, 1.0, 0.0 ); + ::glRotatef( Angle.y, 0.f, 1.f, 0.f ); if( Angle.x != 0.0 ) - ::glRotated( Angle.x, 1.0, 0.0, 0.0 ); + ::glRotatef( Angle.x, 1.f, 0.f, 0.f ); if( Angle.z != 0.0 ) - ::glRotated( Angle.z, 0.0, 0.0, 1.0 ); + ::glRotatef( Angle.z, 0.f, 0.f, 1.f ); auto const result = Render( Model, Material, Squaredistance ); @@ -2363,7 +2374,7 @@ opengl_renderer::Render( TSubModel *Submodel ) { ::glPushMatrix(); if( Submodel->fMatrix ) ::glMultMatrixf( Submodel->fMatrix->readArray() ); - if( Submodel->b_Anim ) + if( Submodel->b_Anim != TAnimType::at_None ) Submodel->RaAnimation( Submodel->b_Anim ); } @@ -2775,7 +2786,7 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First, } void -opengl_renderer::Render( TMemCell const *Memcell ) { +opengl_renderer::Render( TMemCell *Memcell ) { ::glPushMatrix(); auto const position = Memcell->location() - m_renderpass.camera.position(); @@ -3149,16 +3160,16 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, f } bool -opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ) { +opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, glm::vec3 const &Angle ) { ::glPushMatrix(); ::glTranslated( Position.x, Position.y, Position.z ); if( Angle.y != 0.0 ) - ::glRotated( Angle.y, 0.0, 1.0, 0.0 ); + ::glRotatef( Angle.y, 0.f, 1.f, 0.f ); if( Angle.x != 0.0 ) - ::glRotated( Angle.x, 1.0, 0.0, 0.0 ); + ::glRotatef( Angle.x, 1.f, 0.f, 0.f ); if( Angle.z != 0.0 ) - ::glRotated( Angle.z, 0.0, 0.0, 1.0 ); + ::glRotatef( Angle.z, 0.f, 0.f, 1.f ); auto const result = Render_Alpha( Model, Material, Squaredistance ); // position is effectively camera offset @@ -3182,7 +3193,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { ::glPushMatrix(); if( Submodel->fMatrix ) ::glMultMatrixf( Submodel->fMatrix->readArray() ); - if( Submodel->b_aAnim ) + if( Submodel->b_aAnim != TAnimType::at_None ) Submodel->RaAnimation( Submodel->b_aAnim ); } @@ -3399,7 +3410,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { // utility methods -TSubModel const * +TSubModel * opengl_renderer::Update_Pick_Control() { #ifdef EU07_USE_PICKING_FRAMEBUFFER @@ -3432,7 +3443,7 @@ opengl_renderer::Update_Pick_Control() { unsigned char pickreadout[4]; ::glReadPixels( pickbufferpos.x, pickbufferpos.y, 1, 1, GL_BGRA, GL_UNSIGNED_BYTE, pickreadout ); auto const controlindex = pick_index( glm::ivec3{ pickreadout[ 2 ], pickreadout[ 1 ], pickreadout[ 0 ] } ); - TSubModel const *control { nullptr }; + TSubModel *control { nullptr }; if( ( controlindex > 0 ) && ( controlindex <= m_pickcontrolsitems.size() ) ) { control = m_pickcontrolsitems[ controlindex - 1 ]; @@ -3446,7 +3457,7 @@ opengl_renderer::Update_Pick_Control() { return control; } -scene::basic_node const * +scene::basic_node * opengl_renderer::Update_Pick_Node() { #ifdef EU07_USE_PICKING_FRAMEBUFFER @@ -3481,7 +3492,7 @@ opengl_renderer::Update_Pick_Node() { unsigned char pickreadout[4]; ::glReadPixels( pickbufferpos.x, pickbufferpos.y, 1, 1, GL_BGRA, GL_UNSIGNED_BYTE, pickreadout ); auto const nodeindex = pick_index( glm::ivec3{ pickreadout[ 2 ], pickreadout[ 1 ], pickreadout[ 0 ] } ); - scene::basic_node const *node { nullptr }; + scene::basic_node *node { nullptr }; if( ( nodeindex > 0 ) && ( nodeindex <= m_picksceneryitems.size() ) ) { node = m_picksceneryitems[ nodeindex - 1 ]; @@ -3495,6 +3506,29 @@ opengl_renderer::Update_Pick_Node() { return node; } +// converts provided screen coordinates to world coordinates of most recent color pass +glm::dvec3 +opengl_renderer::Update_Mouse_Position() { + + glm::dvec2 mousepos; + glfwGetCursorPos( m_window, &mousepos.x, &mousepos.y ); + mousepos.x = clamp( mousepos.x, 0, Global.iWindowWidth - 1 ); + mousepos.y = clamp( Global.iWindowHeight - clamp( mousepos.y, 0, Global.iWindowHeight ), 0, Global.iWindowHeight - 1 ) ; + GLfloat pointdepth; + ::glReadPixels( mousepos.x, mousepos.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pointdepth ); + + if( pointdepth < 1.0 ) { + m_worldmousecoordinates = + glm::unProject( + glm::vec3{ mousepos, pointdepth }, + glm::mat4{ glm::mat3{ m_colorpass.camera.modelview() } }, + m_colorpass.camera.projection(), + glm::vec4{ 0, 0, Global.iWindowWidth, Global.iWindowHeight } ); + } + + return m_colorpass.camera.position() + glm::dvec3{ m_worldmousecoordinates }; +} + void opengl_renderer::Update( double const Deltatime ) { diff --git a/renderer.h b/renderer.h index 4c40eb37..a39f4ddf 100644 --- a/renderer.h +++ b/renderer.h @@ -167,13 +167,17 @@ public: Pick_Control() const { return m_pickcontrolitem; } scene::basic_node const * Pick_Node() const { return m_picksceneryitem; } + glm::dvec3 + Mouse_Position() const { return m_worldmousecoordinates; } // maintenance methods void Update( double const Deltatime ); - TSubModel const * + TSubModel * Update_Pick_Control(); - scene::basic_node const * + scene::basic_node * Update_Pick_Node(); + glm::dvec3 + Update_Mouse_Position(); // debug methods std::string const & info_times() const; @@ -277,7 +281,7 @@ private: bool Render( TDynamicObject *Dynamic ); bool - Render( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ); + Render( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, glm::vec3 const &Angle ); bool Render( TModel3d *Model, material_data const *Material, float const Squaredistance ); void @@ -289,7 +293,7 @@ private: bool Render_cab( TDynamicObject const *Dynamic, bool const Alpha = false ); void - Render( TMemCell const *Memcell ); + Render( TMemCell *Memcell ); void Render_Alpha( scene::basic_region *Region ); void @@ -303,7 +307,7 @@ private: bool Render_Alpha( TDynamicObject *Dynamic ); bool - Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ); + Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, glm::vec3 const &Angle ); bool Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance ); void @@ -386,12 +390,14 @@ private: renderpass_config m_renderpass; // parameters for current render pass section_sequence m_sectionqueue; // list of sections in current render pass cell_sequence m_cellqueue; + renderpass_config m_colorpass; // parametrs of most recent color pass renderpass_config m_shadowpass; // parametrs of most recent shadowmap pass renderpass_config m_cabshadowpass; // parameters of most recent cab shadowmap pass - std::vector m_pickcontrolsitems; - TSubModel const *m_pickcontrolitem { nullptr }; - std::vector m_picksceneryitems; - scene::basic_node const *m_picksceneryitem { nullptr }; + std::vector m_pickcontrolsitems; + TSubModel *m_pickcontrolitem { nullptr }; + std::vector m_picksceneryitems; + scene::basic_node *m_picksceneryitem { nullptr }; + glm::vec3 m_worldmousecoordinates { 0.f }; #ifdef EU07_USE_DEBUG_CAMERA renderpass_config m_worldcamera; // debug item #endif diff --git a/scene.cpp b/scene.cpp index 6c9910f3..736866d3 100644 --- a/scene.cpp +++ b/scene.cpp @@ -22,6 +22,19 @@ namespace scene { std::string const EU07_FILEEXTENSION_REGION { ".sbt" }; std::uint32_t const EU07_FILEVERSION_REGION { MAKE_ID4( 'S', 'B', 'T', 1 ) }; +// potentially activates event handler with the same name as provided node, and within handler activation range +void +basic_cell::on_click( TAnimModel const *Instance ) { + + for( auto *launcher : m_eventlaunchers ) { + if( ( launcher->name() == Instance->name() ) + && ( glm::length2( launcher->location() - Instance->location() ) < launcher->dRadius ) + && ( true == launcher->check_conditions() ) ) { + launch_event( launcher ); + } + } +} + // legacy method, finds and assigns traction piece to specified pantograph of provided vehicle void basic_cell::update_traction( TDynamicObject *Vehicle, int const Pantographindex ) { @@ -105,17 +118,10 @@ basic_cell::update_events() { // event launchers for( auto *launcher : m_eventlaunchers ) { - if( ( true == launcher->check_conditions() ) + if( ( true == ( launcher->check_activation() && launcher->check_conditions() ) ) && ( SquareMagnitude( launcher->location() - Global.pCameraPosition ) < launcher->dRadius ) ) { - WriteLog( "Eventlauncher " + launcher->name() ); - if( ( true == Global.shiftState ) - && ( launcher->Event2 != nullptr ) ) { - simulation::Events.AddToQuery( launcher->Event2, nullptr ); - } - else if( launcher->Event1 ) { - simulation::Events.AddToQuery( launcher->Event1, nullptr ); - } + launch_event( launcher ); } } } @@ -384,6 +390,50 @@ basic_cell::insert( TMemCell *Memorycell ) { // NOTE: memory cells are virtual 'points' hence they don't ever expand cell range } +// removes provided model instance from the cell +void +basic_cell::erase( TAnimModel *Instance ) { + + auto const flags = Instance->Flags(); + auto alpha = + ( Instance->Material() != nullptr ? + Instance->Material()->textures_alpha : + 0x30300030 ); + + if( alpha & flags & 0x2F2F002F ) { + // instance has translucent pieces + m_instancetranslucent.erase( + std::remove_if( + std::begin( m_instancetranslucent ), std::end( m_instancetranslucent ), + [=]( TAnimModel *instance ) { + return instance == Instance; } ), + std::end( m_instancetranslucent ) ); + } + alpha ^= 0x0F0F000F; // odwrócenie flag tekstur, aby wyłapać nieprzezroczyste + if( alpha & flags & 0x1F1F001F ) { + // instance has opaque pieces + m_instancesopaque.erase( + std::remove_if( + std::begin( m_instancesopaque ), std::end( m_instancesopaque ), + [=]( TAnimModel *instance ) { + return instance == Instance; } ), + std::end( m_instancesopaque ) ); + } + // TODO: update cell bounding area +} + +// removes provided memory cell from the cell +void +basic_cell::erase( TMemCell *Memorycell ) { + + m_memorycells.erase( + std::remove_if( + std::begin( m_memorycells ), std::end( m_memorycells ), + [=]( TMemCell *memorycell ) { + return memorycell == Memorycell; } ), + std::end( m_memorycells ) ); +} + // registers provided path in the lookup directory of the cell void basic_cell::register_end( TTrack *Path ) { @@ -549,6 +599,20 @@ basic_cell::create_geometry( gfx::geometrybank_handle const &Bank ) { m_geometrycreated = true; // helper for legacy animation code, get rid of it after refactoring } +// executes event assigned to specified launcher +void +basic_cell::launch_event( TEventLauncher *Launcher ) { + + WriteLog( "Eventlauncher " + Launcher->name() ); + if( ( true == Global.shiftState ) + && ( Launcher->Event2 != nullptr ) ) { + simulation::Events.AddToQuery( Launcher->Event2, nullptr ); + } + else if( Launcher->Event1 ) { + simulation::Events.AddToQuery( Launcher->Event1, nullptr ); + } +} + // adjusts cell bounding area to enclose specified node void basic_cell::enclose_area( scene::basic_node *Node ) { @@ -560,6 +624,13 @@ basic_cell::enclose_area( scene::basic_node *Node ) { +// potentially activates event handler with the same name as provided node, and within handler activation range +void +basic_section::on_click( TAnimModel const *Instance ) { + + cell( Instance->location() ).on_click( Instance ); +} + // legacy method, finds and assigns traction piece(s) to pantographs of provided vehicle void basic_section::update_traction( TDynamicObject *Vehicle, int const Pantographindex ) { @@ -856,6 +927,19 @@ basic_region::~basic_region() { for( auto *section : m_sections ) { if( section != nullptr ) { delete section; } } } +// potentially activates event handler with the same name as provided node, and within handler activation range +void +basic_region::on_click( TAnimModel const *Instance ) { + + if( Instance->name().empty() || ( Instance->name() == "none" ) ) { return; } + + auto const location { Instance->location() }; + + if( point_inside( location ) ) { + section( location ).on_click( Instance ); + } +} + // legacy method, polls event launchers around camera void basic_region::update_events() { @@ -1034,7 +1118,7 @@ basic_region::RadioStop( glm::dvec3 const &Location ) { } void -basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad, bool const Transform ) { +basic_region::insert( shape_node Shape, scratch_data &Scratchpad, bool const Transform ) { // shape might need to be split into smaller pieces, so we create list of nodes instead of just single one // using deque so we can do single pass iterating and addding generated pieces without invalidating anything @@ -1098,7 +1182,7 @@ basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad, bool con // inserts provided lines in the region void -basic_region::insert_lines( lines_node Lines, scratch_data &Scratchpad ) { +basic_region::insert( lines_node Lines, scratch_data &Scratchpad ) { if( Lines.m_data.vertices.empty() ) { return; } // transform point coordinates if needed @@ -1140,112 +1224,6 @@ basic_region::insert_lines( lines_node Lines, scratch_data &Scratchpad ) { } } -// inserts provided track in the region -void -basic_region::insert_path( TTrack *Path, const scratch_data &Scratchpad ) { - // NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done - auto location = Path->location(); - - if( point_inside( location ) ) { - // NOTE: nodes placed outside of region boundaries are discarded - section( location ).insert( Path ); - } - else { - // tracks are guaranteed to hava a name so we can skip the check - ErrorLog( "Bad scenario: track node \"" + Path->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" ); - } - // also register path ends in appropriate sections, for path merging lookups - // TODO: clean this up during track refactoring - for( auto &point : Path->endpoints() ) { - register_path( Path, point ); - } -} - -// inserts provided track in the region -void -basic_region::insert_traction( TTraction *Traction, scratch_data &Scratchpad ) { - // NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done - auto location = Traction->location(); - - if( point_inside( location ) ) { - // NOTE: nodes placed outside of region boundaries are discarded - section( location ).insert( Traction ); - } - else { - // tracks are guaranteed to hava a name so we can skip the check - ErrorLog( "Bad scenario: traction node \"" + Traction->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" ); - } - // also register traction ends in appropriate sections, for path merging lookups - // TODO: clean this up during track refactoring - for( auto &point : Traction->endpoints() ) { - register_traction( Traction, point ); - } -} - -// inserts provided instance of 3d model in the region -void -basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ) { - // NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done - auto location = Instance->location(); - - if( point_inside( location ) ) { - // NOTE: nodes placed outside of region boundaries are discarded - section( location ).insert( Instance ); - } - else { - // tracks are guaranteed to hava a name so we can skip the check - ErrorLog( "Bad scenario: model node \"" + Instance->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" ); - } -} - -// inserts provided sound in the region -void -basic_region::insert_sound( sound_source *Sound, scratch_data &Scratchpad ) { - // NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done - auto location = Sound->location(); - - if( point_inside( location ) ) { - // NOTE: nodes placed outside of region boundaries are discarded - section( location ).insert( Sound ); - } - else { - // tracks are guaranteed to hava a name so we can skip the check - ErrorLog( "Bad scenario: sound node \"" + Sound->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" ); - } -} - -// inserts provided event launcher in the region -void -basic_region::insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad ) { - // NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done - auto location = Launcher->location(); - - if( point_inside( location ) ) { - // NOTE: nodes placed outside of region boundaries are discarded - section( location ).insert( Launcher ); - } - else { - // tracks are guaranteed to hava a name so we can skip the check - ErrorLog( "Bad scenario: event launcher \"" + Launcher->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" ); - } -} - -// inserts provided memory cell in the region -void -basic_region::insert_memorycell( TMemCell *Memorycell, scratch_data &Scratchpad ) { - // NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done - auto location = Memorycell->location(); - - if( point_inside( location ) ) { - // NOTE: nodes placed outside of region boundaries are discarded - section( location ).insert( Memorycell ); - } - else { - // tracks are guaranteed to hava a name so we can skip the check - ErrorLog( "Bad scenario: memory cell \"" + Memorycell->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" ); - } -} - // find a vehicle located neares to specified location, within specified radius, optionally discarding vehicles without drivers std::tuple basic_region::find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) { @@ -1356,24 +1334,6 @@ basic_region::sections( glm::dvec3 const &Point, float const Radius ) { return m_scratchpad.sections; } -// registers specified path in the lookup directory of a cell enclosing specified point -void -basic_region::register_path( TTrack *Path, glm::dvec3 const &Point ) { - - if( point_inside( Point ) ) { - section( Point ).register_node( Path, Point ); - } -} - -// registers specified end point of the provided traction piece in the lookup directory of the region -void -basic_region::register_traction( TTraction *Traction, glm::dvec3 const &Point ) { - - if( point_inside( Point ) ) { - section( Point ).register_node( Traction, Point ); - } -} - // checks whether specified point is within boundaries of the region bool basic_region::point_inside( glm::dvec3 const &Location ) { diff --git a/scene.h b/scene.h index ed997aa9..e784caba 100644 --- a/scene.h +++ b/scene.h @@ -61,12 +61,15 @@ struct scratch_data { // TBD, TODO: replace with quadtree scheme? class basic_cell { - friend class ::opengl_renderer; + friend opengl_renderer; public: // constructors basic_cell() = default; // methods + // potentially activates event handler with the same name as provided node, and within handler activation range + void + on_click( TAnimModel const *Instance ); // legacy method, finds and assigns traction piece to specified pantograph of provided vehicle void update_traction( TDynamicObject *Vehicle, int const Pantographindex ); @@ -124,6 +127,12 @@ public: // registers provided traction piece in the lookup directory of the cell void register_end( TTraction *Traction ); + // removes provided model instance from the cell + void + erase( TAnimModel *Instance ); + // removes provided memory cell from the cell + void + erase( TMemCell *Memorycell ); // find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance std::tuple find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) const; @@ -157,6 +166,8 @@ private: using eventlauncher_sequence = std::vector; using memorycell_sequence = std::vector; // methods + void + launch_event( TEventLauncher *Launcher ); void enclose_area( scene::basic_node *Node ); // members @@ -187,13 +198,16 @@ private: // basic scene partitioning structure, holds terrain geometry and collection of cells class basic_section { - friend class ::opengl_renderer; + friend opengl_renderer; public: // constructors basic_section() = default; // methods -// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle + // potentially activates event handler with the same name as provided node, and within handler activation range + void + on_click( TAnimModel const *Instance ); + // legacy method, finds and assigns traction piece to specified pantograph of provided vehicle void update_traction( TDynamicObject *Vehicle, int const Pantographindex ); // legacy method, updates sounds and polls event launchers within radius around specified point @@ -230,6 +244,13 @@ public: m_area.radius = std::max( m_area.radius, static_cast( glm::length( m_area.center - targetcell.area().center ) + targetcell.area().radius ) ); } + // erases provided node from the section + template + void + erase( Type_ *Node ) { + auto &targetcell { cell( Node->location() ) }; + // TODO: re-calculate bounding area after removal + targetcell.erase( Node ); } // registers provided node in the lookup directory of the section enclosing specified point template void @@ -281,7 +302,7 @@ private: // top-level of scene spatial structure, holds collection of sections class basic_region { - friend class ::opengl_renderer; + friend opengl_renderer; public: // constructors @@ -289,7 +310,10 @@ public: // destructor ~basic_region(); // methods -// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle + // potentially activates event handler with the same name as provided node, and within handler activation range + void + on_click( TAnimModel const *Instance ); + // legacy method, finds and assigns traction piece to specified pantograph of provided vehicle void update_traction( TDynamicObject *Vehicle, int const Pantographindex ); // legacy method, polls event launchers around camera @@ -315,28 +339,35 @@ public: RadioStop( glm::dvec3 const &Location ); // inserts provided shape in the region void - insert_shape( shape_node Shape, scratch_data &Scratchpad, bool const Transform ); + insert( shape_node Shape, scratch_data &Scratchpad, bool const Transform ); // inserts provided lines in the region void - insert_lines( lines_node Lines, scratch_data &Scratchpad ); - // inserts provided track in the region + insert( lines_node Lines, scratch_data &Scratchpad ); + // inserts provided node in the region + template void - insert_path( TTrack *Path, const scratch_data &Scratchpad ); - // inserts provided track in the region + insert( Type_ *Node ) { + auto const location { Node->location() }; + if( false == point_inside( location ) ) { + // NOTE: nodes placed outside of region boundaries are discarded + // TBD, TODO: clamp coordinates to region boundaries? + return; } + section( location ).insert( Node ); } + // inserts provided node in the region and registers its ends in lookup directory + template void - insert_traction( TTraction *Traction, scratch_data &Scratchpad ); - // inserts provided instance of 3d model in the region + insert_and_register( Type_ *Node ) { + insert( Node ); + for( auto const &point : Node->endpoints() ) { + if( point_inside( point ) ) { + section( point ).register_node( Node, point ); } } } + // removes specified node from the region + template void - insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ); - // inserts provided sound in the region - void - insert_sound( sound_source *Sound, scratch_data &Scratchpad ); - // inserts provided event launcher in the region - void - insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad ); - // inserts provided memory cell in the region - void - insert_memorycell( TMemCell *Memorycell, scratch_data &Scratchpad ); + erase( Type_ *Node ) { + auto const location{ Node->location() }; + if( point_inside( location ) ) { + section( location ).erase( Node ); } } // find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance std::tuple find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ); @@ -363,12 +394,6 @@ private: }; // methods - // registers specified end point of the provided path in the lookup directory of the region - void - register_path( TTrack *Path, glm::dvec3 const &Point ); - // registers specified end point of the provided traction piece in the lookup directory of the region - void - register_traction( TTraction *Traction, glm::dvec3 const &Point ); // checks whether specified point is within boundaries of the region bool point_inside( glm::dvec3 const &Location ); diff --git a/sceneeditor.cpp b/sceneeditor.cpp new file mode 100644 index 00000000..a96ef502 --- /dev/null +++ b/sceneeditor.cpp @@ -0,0 +1,213 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#include "stdafx.h" +#include "sceneeditor.h" + +#include "Globals.h" +#include "application.h" +#include "simulation.h" +#include "renderer.h" + +namespace scene { + +basic_editor Editor; + +bool +basic_editor::on_key( int const Key, int const Action ) { + + if( false == EditorModeFlag ) { return false; } + + if( ( Key == GLFW_KEY_LEFT_ALT ) + || ( Key == GLFW_KEY_RIGHT_ALT ) ) { + // intercept these while in editor mode + return true; + } + + return false; +} + +bool +basic_editor::on_mouse_button( int const Button, int const Action ) { + + if( false == EditorModeFlag ) { return false; } + // TBD: automatically activate and enforce freefly mode when editor is active? + if( false == FreeFlyModeFlag ) { return false; } + + if( Button == GLFW_MOUSE_BUTTON_LEFT ) { + + if( Action == GLFW_PRESS ) { + + m_node = GfxRenderer.Update_Pick_Node(); + m_nodesnapshot = { m_node }; + if( m_node ) { + Application.set_cursor( GLFW_CURSOR_DISABLED ); + } + } + else { + // left button release + // TODO: record the current undo step on the undo stack + m_nodesnapshot = { m_node }; + if( m_node ) { + Application.set_cursor( GLFW_CURSOR_NORMAL ); + } + } + + m_mouseleftbuttondown = ( Action == GLFW_PRESS ); + + return ( m_node != nullptr ); + } + + return false; +} + +bool +basic_editor::on_mouse_move( double const Mousex, double const Mousey ) { + + auto const mousemove { glm::dvec2{ Mousex, Mousey } - m_mouseposition }; + m_mouseposition = { Mousex, Mousey }; + + if( false == EditorModeFlag ) { return false; } + if( false == m_mouseleftbuttondown ) { return false; } + if( m_node == nullptr ) { return false; } + + if( mode_translation() ) { + // move selected node + if( mode_translation_vertical() ) { + auto const translation { mousemove.y * -0.01f }; + translate( translation ); + } + else { + auto const mouseworldposition{ Global.pCamera->Pos + GfxRenderer.Mouse_Position() }; + translate( mouseworldposition ); + } + } + else { + // rotate selected node + auto const rotation { glm::vec3 { mousemove.y, mousemove.x, 0 } * 0.25f }; + rotate( rotation ); + } + + return true; +} + +void +basic_editor::translate( glm::dvec3 const &Location ) { + + auto *node { m_node }; // placeholder for operations on multiple nodes + + auto location { Location }; + if( false == mode_snap() ) { + location.y = node->location().y; + } + + if( typeid( *node ) == typeid( TAnimModel ) ) { + translate_instance( static_cast( node ), location ); + } + else if( typeid( *node ) == typeid( TMemCell ) ) { + translate_memorycell( static_cast( node ), location ); + } + +} + +void +basic_editor::translate( float const Offset ) { + + // NOTE: offset scaling is calculated early so the same multiplier can be applied to potential whole group + auto location { m_node->location() }; + auto const distance { glm::length( location - glm::dvec3{ Global.pCamera->Pos } ) }; + auto const offset { Offset * std::max( 1.0, distance * 0.01 ) }; + + auto *node { m_node }; // placeholder for operations on multiple nodes + + if( typeid( *node ) == typeid( TAnimModel ) ) { + translate_instance( static_cast( node ), offset ); + } + else if( typeid( *node ) == typeid( TMemCell ) ) { + translate_memorycell( static_cast( node ), offset ); + } +} + +void +basic_editor::translate_instance( TAnimModel *Instance, glm::dvec3 const &Location ) { + + simulation::Region->erase( Instance ); + Instance->location( Location ); + simulation::Region->insert( Instance ); +} + +void +basic_editor::translate_instance( TAnimModel *Instance, float const Offset ) { + + auto location { Instance->location() }; + location.y += Offset; + Instance->location( location ); +} + +void +basic_editor::translate_memorycell( TMemCell *Memorycell, glm::dvec3 const &Location ) { + + simulation::Region->erase( Memorycell ); + Memorycell->location( Location ); + simulation::Region->insert( Memorycell ); +} + +void +basic_editor::translate_memorycell( TMemCell *Memorycell, float const Offset ) { + + auto location { Memorycell->location() }; + location.y += Offset; + Memorycell->location( location ); +} + +void +basic_editor::rotate( glm::vec3 const &Angle ) { + + auto *node { m_node }; // placeholder for operations on multiple nodes + + if( typeid( *node ) == typeid( TAnimModel ) ) { + rotate_instance( static_cast( node ), Angle ); + } +} + +void +basic_editor::rotate_instance( TAnimModel *Instance, glm::vec3 const &Angle ) { + + // adjust node data + glm::vec3 angle = glm::dvec3 { Instance->Angles() }; + angle.y = clamp_circular( angle.y + Angle.y, 360.f ); + if( mode_snap() ) { + // TBD, TODO: adjustable quantization step + angle.y = quantize( angle.y, 15.f ); + } + Instance->Angles( angle ); + // update scene +} + +bool +basic_editor::mode_translation() const { + + return ( false == Global.altState ); +} + +bool +basic_editor::mode_translation_vertical() const { + + return ( true == Global.shiftState ); +} + +bool +basic_editor::mode_snap() const { + + return ( true == Global.ctrlState ); +} + +} // scene + +//--------------------------------------------------------------------------- diff --git a/sceneeditor.h b/sceneeditor.h new file mode 100644 index 00000000..b69874b8 --- /dev/null +++ b/sceneeditor.h @@ -0,0 +1,81 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include "scenenode.h" + +namespace scene { + +class basic_editor { + +public: +// methods + bool + on_key( int const Key, int const Action ); + bool + on_mouse_button( int const Button, int const Action ); + bool + on_mouse_move( double const Mousex, double const Mousey ); + scene::basic_node const * + node() const { + return m_node; } +private: +// types + struct node_snapshot { + + scene::basic_node *node; + std::string data; + + node_snapshot( scene::basic_node *Node ) : + node( Node ) { + if( Node != nullptr ) { + Node->export_as_text( data ); } }; + }; + friend bool operator==( basic_editor::node_snapshot const &Left, basic_editor::node_snapshot const &Right ); + friend bool operator!=( basic_editor::node_snapshot const &Left, basic_editor::node_snapshot const &Right ); +// methods + bool + mode_translation() const; + bool + mode_translation_vertical() const; + bool + mode_snap() const; + void + translate( glm::dvec3 const &Location ); + void + translate( float const Offset ); + void + translate_instance( TAnimModel *Instance, glm::dvec3 const &Location ); + void + translate_instance( TAnimModel *Instance, float const Offset ); + void + translate_memorycell( TMemCell *Memorycell, glm::dvec3 const &Location ); + void + translate_memorycell( TMemCell *Memorycell, float const Offset ); + void + rotate( glm::vec3 const &Angle ); + void + rotate_instance( TAnimModel *Instance, glm::vec3 const &Angle ); +// members + scene::basic_node *m_node; // temporary helper, currently selected scene node + node_snapshot m_nodesnapshot { nullptr }; // currently selected scene node in its pre-modified state + glm::dvec2 m_mouseposition { 0.0 }; + bool m_mouseleftbuttondown { false }; + +}; + +inline bool operator==( basic_editor::node_snapshot const &Left, basic_editor::node_snapshot const &Right ) { return ( ( Left.node == Right.node ) && ( Left.data == Right.data ) ); } +inline bool operator!=( basic_editor::node_snapshot const &Left, basic_editor::node_snapshot const &Right ) { return ( !( Left == Right ) ); } + +extern basic_editor Editor; + +} // scene + +//--------------------------------------------------------------------------- diff --git a/scenenode.cpp b/scenenode.cpp index f81a002b..21a0c2ce 100644 --- a/scenenode.cpp +++ b/scenenode.cpp @@ -740,6 +740,14 @@ basic_node::export_as_text( std::ostream &Output ) const { export_as_text_( Output ); } +void +basic_node::export_as_text( std::string &Output ) const { + + std::stringstream converter; + export_as_text( converter ); + Output += converter.str(); +} + float const & basic_node::radius() { @@ -760,10 +768,4 @@ basic_node::radius_() { } // scene -namespace editor { - -scene::basic_node const *Node { nullptr }; // temporary helper, currently selected scene node - -} // editor - //--------------------------------------------------------------------------- diff --git a/scenenode.h b/scenenode.h index 0e61b8b6..6d45b29d 100644 --- a/scenenode.h +++ b/scenenode.h @@ -316,6 +316,8 @@ public: // sends basic content of the class in legacy (text) format to provided stream void export_as_text( std::ostream &Output ) const; + void + export_as_text( std::string &Output ) const; std::string const & name() const; void @@ -381,10 +383,4 @@ basic_node::visible() const { } // scene -namespace editor { - -extern scene::basic_node const *Node; // temporary helper, currently selected scene node - -} // editor - //--------------------------------------------------------------------------- diff --git a/screenshot.cpp b/screenshot.cpp new file mode 100644 index 00000000..9751a08e --- /dev/null +++ b/screenshot.cpp @@ -0,0 +1,52 @@ +#include "stdafx.h" +#include "screenshot.h" +#include "Globals.h" +#include "Logs.h" +#include + +void screenshot_manager::screenshot_save_thread( char *img ) +{ + png_image png; + memset(&png, 0, sizeof(png_image)); + png.version = PNG_IMAGE_VERSION; + png.width = Global.iWindowWidth; + png.height = Global.iWindowHeight; + png.format = PNG_FORMAT_RGB; + + char datetime[64]; + time_t timer; + struct tm* tm_info; + time(&timer); + tm_info = localtime(&timer); + strftime(datetime, 64, "%Y-%m-%d_%H-%M-%S", tm_info); + + uint64_t perf; +#ifdef _WIN32 + QueryPerformanceCounter((LARGE_INTEGER*)&perf); +#elif __linux__ + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + perf = ts.tv_nsec; +#endif + + std::string filename = Global.screenshot_dir + "/" + std::string(datetime) + + "_" + std::to_string(perf) + ".png"; + + if (png_image_write_to_file(&png, filename.c_str(), 0, img, -Global.iWindowWidth * 3, nullptr) == 1) + WriteLog("saved " + filename); + else + WriteLog("failed to save " + filename); + + delete[] img; +} + +void screenshot_manager::make_screenshot() +{ + char *img = new char[Global.iWindowWidth * Global.iWindowHeight * 3]; + glReadPixels(0, 0, Global.iWindowWidth, Global.iWindowHeight, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)img); + //m7t: use pbo + + std::thread t(screenshot_save_thread, img); + t.detach(); +} + diff --git a/screenshot.h b/screenshot.h new file mode 100644 index 00000000..9f0e732b --- /dev/null +++ b/screenshot.h @@ -0,0 +1,7 @@ +class screenshot_manager +{ + static void screenshot_save_thread( char *img ); + +public: + static void make_screenshot(); +}; diff --git a/simulation.cpp b/simulation.cpp index 614a3070..1c0c6dae 100644 --- a/simulation.cpp +++ b/simulation.cpp @@ -15,7 +15,8 @@ http://mozilla.org/MPL/2.0/. #include "uilayer.h" #include "renderer.h" #include "World.h" - +#include "simulationtime.h" +#include "Logs.h" namespace simulation { @@ -33,9 +34,42 @@ lua Lua; scene::basic_region *Region { nullptr }; + + bool state_manager::deserialize( std::string const &Scenariofile ) { + return m_serializer.deserialize( Scenariofile ); +} + +// stores class data in specified file, in legacy (text) format +void +state_manager::export_as_text( std::string const &Scenariofile ) const { + + return m_serializer.export_as_text( Scenariofile ); +} + +// legacy method, calculates changes in simulation state over specified time +void +state_manager::update( double const Deltatime, int Iterationcount ) { + // aktualizacja animacji krokiem FPS: dt=krok czasu [s], dt*iter=czas od ostatnich przeliczeń + if (Deltatime == 0.0) { + return; + } + + auto const totaltime { Deltatime * Iterationcount }; + // NOTE: we perform animations first, as they can determine factors like contact with powergrid + TAnimModel::AnimUpdate( totaltime ); // wykonanie zakolejkowanych animacji + + simulation::Powergrid.update( totaltime ); + simulation::Vehicles.update( Deltatime, Iterationcount ); +} + + + +bool +state_serializer::deserialize( std::string const &Scenariofile ) { + // TODO: move initialization to separate routine so we can reuse it SafeDelete( Region ); Region = new scene::basic_region(); @@ -62,51 +96,34 @@ state_manager::deserialize( std::string const &Scenariofile ) { return true; } -// legacy method, calculates changes in simulation state over specified time -void -state_manager::update( double const Deltatime, int Iterationcount ) { - // aktualizacja animacji krokiem FPS: dt=krok czasu [s], dt*iter=czas od ostatnich przeliczeń - if (Deltatime == 0.0) { - // jeśli załączona jest pauza, to tylko obsłużyć ruch w kabinie trzeba - return; - } - - auto const totaltime { Deltatime * Iterationcount }; - // NOTE: we perform animations first, as they can determine factors like contact with powergrid - TAnimModel::AnimUpdate( totaltime ); // wykonanie zakolejkowanych animacji - - simulation::Powergrid.update( totaltime ); - simulation::Vehicles.update( Deltatime, Iterationcount ); -} - // restores class data from provided stream void -state_manager::deserialize( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize( cParser &Input, scene::scratch_data &Scratchpad ) { // prepare deserialization function table // since all methods use the same objects, we can have simple, hard-coded binds or lambdas for the task - using deserializefunction = void(state_manager::*)(cParser &, scene::scratch_data &); + using deserializefunction = void( state_serializer::*)(cParser &, scene::scratch_data &); std::vector< std::pair< std::string, deserializefunction> > functionlist = { - { "atmo", &state_manager::deserialize_atmo }, - { "camera", &state_manager::deserialize_camera }, - { "config", &state_manager::deserialize_config }, - { "description", &state_manager::deserialize_description }, - { "event", &state_manager::deserialize_event }, - { "lua", &state_manager::deserialize_lua }, - { "firstinit", &state_manager::deserialize_firstinit }, - { "light", &state_manager::deserialize_light }, - { "node", &state_manager::deserialize_node }, - { "origin", &state_manager::deserialize_origin }, - { "endorigin", &state_manager::deserialize_endorigin }, - { "rotate", &state_manager::deserialize_rotate }, - { "sky", &state_manager::deserialize_sky }, - { "test", &state_manager::deserialize_test }, - { "time", &state_manager::deserialize_time }, - { "trainset", &state_manager::deserialize_trainset }, - { "endtrainset", &state_manager::deserialize_endtrainset } }; + { "atmo", &state_serializer::deserialize_atmo }, + { "camera", &state_serializer::deserialize_camera }, + { "config", &state_serializer::deserialize_config }, + { "description", &state_serializer::deserialize_description }, + { "event", &state_serializer::deserialize_event }, + { "lua", &state_serializer::deserialize_lua }, + { "firstinit", &state_serializer::deserialize_firstinit }, + { "light", &state_serializer::deserialize_light }, + { "node", &state_serializer::deserialize_node }, + { "origin", &state_serializer::deserialize_origin }, + { "endorigin", &state_serializer::deserialize_endorigin }, + { "rotate", &state_serializer::deserialize_rotate }, + { "sky", &state_serializer::deserialize_sky }, + { "test", &state_serializer::deserialize_test }, + { "time", &state_serializer::deserialize_time }, + { "trainset", &state_serializer::deserialize_trainset }, + { "endtrainset", &state_serializer::deserialize_endtrainset } }; using deserializefunctionbind = std::function; std::unordered_map< std::string, @@ -148,7 +165,7 @@ state_manager::deserialize( cParser &Input, scene::scratch_data &Scratchpad ) { } void -state_manager::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ) { // NOTE: parameter system needs some decent replacement, but not worth the effort if we're moving to built-in editor // atmosphere color; legacy parameter, no longer used @@ -180,7 +197,7 @@ state_manager::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad } void -state_manager::deserialize_camera( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_camera( cParser &Input, scene::scratch_data &Scratchpad ) { glm::dvec3 xyz, abc; int i = -1, into = -1; // do której definicji kamery wstawić @@ -234,21 +251,21 @@ state_manager::deserialize_camera( cParser &Input, scene::scratch_data &Scratchp } void -state_manager::deserialize_config( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_config( cParser &Input, scene::scratch_data &Scratchpad ) { // config parameters (re)definition Global.ConfigParse( Input ); } void -state_manager::deserialize_description( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_description( cParser &Input, scene::scratch_data &Scratchpad ) { // legacy section, never really used; skip_until( Input, "enddescription" ); } void -state_manager::deserialize_event( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_event( cParser &Input, scene::scratch_data &Scratchpad ) { // TODO: refactor event class and its de/serialization. do offset and rotation after deserialization is done auto *event = new TEvent(); @@ -266,7 +283,7 @@ state_manager::deserialize_event( cParser &Input, scene::scratch_data &Scratchpa } } -void state_manager::deserialize_lua( cParser &Input, scene::scratch_data &Scratchpad ) +void state_serializer::deserialize_lua( cParser &Input, scene::scratch_data &Scratchpad ) { Input.getTokens(1, false); std::string file; @@ -275,7 +292,7 @@ void state_manager::deserialize_lua( cParser &Input, scene::scratch_data &Scratc } void -state_manager::deserialize_firstinit( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_firstinit( cParser &Input, scene::scratch_data &Scratchpad ) { if( true == Scratchpad.initialized ) { return; } @@ -289,14 +306,14 @@ state_manager::deserialize_firstinit( cParser &Input, scene::scratch_data &Scrat } void -state_manager::deserialize_light( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_light( cParser &Input, scene::scratch_data &Scratchpad ) { // legacy section, no longer used nor supported; skip_until( Input, "endlight" ); } void -state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad ) { auto const inputline = Input.Line(); // cache in case we need to report error @@ -337,7 +354,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad delete pathnode; */ } - simulation::Region->insert_path( path, Scratchpad ); + simulation::Region->insert_and_register( path ); } else if( nodedata.type == "traction" ) { @@ -348,7 +365,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad if( false == simulation::Traction.insert( traction ) ) { ErrorLog( "Bad scenario: traction piece with duplicate name \"" + traction->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" ); } - simulation::Region->insert_traction( traction, Scratchpad ); + simulation::Region->insert_and_register( traction ); } else if( nodedata.type == "tractionpowersource" ) { @@ -377,14 +394,14 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad auto const cellcount = instance->TerrainCount() + 1; // zliczenie submodeli for( auto i = 1; i < cellcount; ++i ) { auto *submodel = instance->TerrainSquare( i - 1 ); - simulation::Region->insert_shape( + simulation::Region->insert( scene::shape_node().convert( submodel ), Scratchpad, false ); // if there's more than one group of triangles in the cell they're held as children of the primary submodel submodel = submodel->ChildGet(); while( submodel != nullptr ) { - simulation::Region->insert_shape( + simulation::Region->insert( scene::shape_node().convert( submodel ), Scratchpad, false ); @@ -408,7 +425,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad if( false == simulation::Instances.insert( instance ) ) { ErrorLog( "Bad scenario: 3d model instance with duplicate name \"" + instance->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" ); } - simulation::Region->insert_instance( instance, Scratchpad ); + simulation::Region->insert( instance ); } } else if( ( nodedata.type == "triangles" ) @@ -417,7 +434,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad if( false == Scratchpad.binary.terrain ) { - simulation::Region->insert_shape( + simulation::Region->insert( scene::shape_node().import( Input, nodedata ), Scratchpad, @@ -434,7 +451,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad if( false == Scratchpad.binary.terrain ) { - simulation::Region->insert_lines( + simulation::Region->insert( scene::lines_node().import( Input, nodedata ), Scratchpad ); @@ -450,7 +467,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad if( false == simulation::Memory.insert( memorycell ) ) { ErrorLog( "Bad scenario: memory memorycell with duplicate name \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" ); } - simulation::Region->insert_memorycell( memorycell, Scratchpad ); + simulation::Region->insert( memorycell ); } else if( nodedata.type == "eventlauncher" ) { @@ -464,7 +481,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad simulation::Events.queue( eventlauncher ); } else { - simulation::Region->insert_launcher( eventlauncher, Scratchpad ); + simulation::Region->insert( eventlauncher ); } } else if( nodedata.type == "sound" ) @@ -473,13 +490,13 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad if( false == simulation::Sounds.insert( sound ) ) { ErrorLog( "Bad scenario: sound node with duplicate name \"" + sound->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" ); } - simulation::Region->insert_sound( sound, Scratchpad ); + simulation::Region->insert( sound ); } } void -state_manager::deserialize_origin( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_origin( cParser &Input, scene::scratch_data &Scratchpad ) { glm::dvec3 offset; Input.getTokens( 3 ); @@ -496,7 +513,7 @@ state_manager::deserialize_origin( cParser &Input, scene::scratch_data &Scratchp } void -state_manager::deserialize_endorigin( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_endorigin( cParser &Input, scene::scratch_data &Scratchpad ) { if( false == Scratchpad.location.offset.empty() ) { Scratchpad.location.offset.pop(); @@ -507,7 +524,7 @@ state_manager::deserialize_endorigin( cParser &Input, scene::scratch_data &Scrat } void -state_manager::deserialize_rotate( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_rotate( cParser &Input, scene::scratch_data &Scratchpad ) { Input.getTokens( 3 ); Input @@ -517,7 +534,7 @@ state_manager::deserialize_rotate( cParser &Input, scene::scratch_data &Scratchp } void -state_manager::deserialize_sky( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_sky( cParser &Input, scene::scratch_data &Scratchpad ) { // sky model Input.getTokens( 1 ); @@ -528,14 +545,14 @@ state_manager::deserialize_sky( cParser &Input, scene::scratch_data &Scratchpad } void -state_manager::deserialize_test( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_test( cParser &Input, scene::scratch_data &Scratchpad ) { // legacy section, no longer supported; skip_until( Input, "endtest" ); } void -state_manager::deserialize_time( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_time( cParser &Input, scene::scratch_data &Scratchpad ) { // current scenario time cParser timeparser( Input.getToken() ); @@ -558,7 +575,7 @@ state_manager::deserialize_time( cParser &Input, scene::scratch_data &Scratchpad } void -state_manager::deserialize_trainset( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_trainset( cParser &Input, scene::scratch_data &Scratchpad ) { if( true == Scratchpad.trainset.is_open ) { // shouldn't happen but if it does wrap up currently open trainset and report an error @@ -578,7 +595,7 @@ state_manager::deserialize_trainset( cParser &Input, scene::scratch_data &Scratc } void -state_manager::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scratchpad ) { +state_serializer::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scratchpad ) { if( ( false == Scratchpad.trainset.is_open ) || ( true == Scratchpad.trainset.vehicles.empty() ) ) { @@ -626,24 +643,24 @@ state_manager::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scr // creates path and its wrapper, restoring class data from provided stream TTrack * -state_manager::deserialize_path( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { +state_serializer::deserialize_path( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { // TODO: refactor track and wrapper classes and their de/serialization. do offset and rotation after deserialization is done auto *track = new TTrack( Nodedata ); - Math3D::vector3 offset = ( + auto const offset { ( Scratchpad.location.offset.empty() ? - Math3D::vector3() : - Math3D::vector3( - Scratchpad.location.offset.top().x, - Scratchpad.location.offset.top().y, - Scratchpad.location.offset.top().z ) ); + glm::dvec3 { 0.0 } : + glm::dvec3 { + Scratchpad.location.offset.top().x, + Scratchpad.location.offset.top().y, + Scratchpad.location.offset.top().z } ) }; track->Load( &Input, offset ); return track; } TTraction * -state_manager::deserialize_traction( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { +state_serializer::deserialize_traction( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { if( false == Global.bLoadTraction ) { skip_until( Input, "endtraction" ); @@ -661,7 +678,7 @@ state_manager::deserialize_traction( cParser &Input, scene::scratch_data &Scratc } TTractionPowerSource * -state_manager::deserialize_tractionpowersource( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { +state_serializer::deserialize_tractionpowersource( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { if( false == Global.bLoadTraction ) { skip_until( Input, "end" ); @@ -677,7 +694,7 @@ state_manager::deserialize_tractionpowersource( cParser &Input, scene::scratch_d } TMemCell * -state_manager::deserialize_memorycell( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { +state_serializer::deserialize_memorycell( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { auto *memorycell = new TMemCell( Nodedata ); memorycell->Load( &Input ); @@ -688,7 +705,7 @@ state_manager::deserialize_memorycell( cParser &Input, scene::scratch_data &Scra } TEventLauncher * -state_manager::deserialize_eventlauncher( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { +state_serializer::deserialize_eventlauncher( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { glm::dvec3 location; Input.getTokens( 3 ); @@ -705,7 +722,7 @@ state_manager::deserialize_eventlauncher( cParser &Input, scene::scratch_data &S } TAnimModel * -state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { +state_serializer::deserialize_model( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { glm::dvec3 location; glm::vec3 rotation; @@ -717,7 +734,7 @@ state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpa >> rotation.y; auto *instance = new TAnimModel( Nodedata ); - instance->RaAnglesSet( Scratchpad.location.rotation + rotation ); // dostosowanie do pochylania linii + instance->Angles( Scratchpad.location.rotation + rotation ); // dostosowanie do pochylania linii if( instance->Load( &Input, false ) ) { instance->location( transform( location, Scratchpad ) ); @@ -731,7 +748,7 @@ state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpa } TDynamicObject * -state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { +state_serializer::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { if( false == Scratchpad.trainset.is_open ) { // part of trainset data is used when loading standalone vehicles, so clear it just in case @@ -861,7 +878,7 @@ state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratch } sound_source * -state_manager::deserialize_sound( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { +state_serializer::deserialize_sound( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) { glm::dvec3 location; Input.getTokens( 3 ); @@ -884,7 +901,7 @@ state_manager::deserialize_sound( cParser &Input, scene::scratch_data &Scratchpa // skips content of stream until specified token void -state_manager::skip_until( cParser &Input, std::string const &Token ) { +state_serializer::skip_until( cParser &Input, std::string const &Token ) { std::string token { Input.getToken() }; while( ( false == token.empty() ) @@ -896,7 +913,7 @@ state_manager::skip_until( cParser &Input, std::string const &Token ) { // transforms provided location by specifed rotation and offset glm::dvec3 -state_manager::transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad ) { +state_serializer::transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad ) { if( Scratchpad.location.rotation != glm::vec3( 0, 0, 0 ) ) { auto const rotation = glm::radians( Scratchpad.location.rotation ); @@ -911,7 +928,7 @@ state_manager::transform( glm::dvec3 Location, scene::scratch_data const &Scratc // stores class data in specified file, in legacy (text) format void -state_manager::export_as_text( std::string const &Scenariofile ) const { +state_serializer::export_as_text( std::string const &Scenariofile ) const { if( Scenariofile == "$.scn" ) { ErrorLog( "Bad file: scenery export not supported for file \"$.scn\"" ); diff --git a/simulation.h b/simulation.h index ae56926a..1ae27cbc 100644 --- a/simulation.h +++ b/simulation.h @@ -26,15 +26,11 @@ http://mozilla.org/MPL/2.0/. namespace simulation { -class state_manager { +class state_serializer { public: -// types - // methods - // legacy method, calculates changes in simulation state over specified time - void - update( double Deltatime, int Iterationcount ); + // restores simulation data from specified file. returns: true on success, false otherwise bool deserialize( std::string const &Scenariofile ); // stores class data in specified file, in legacy (text) format @@ -74,7 +70,25 @@ private: void skip_until( cParser &Input, std::string const &Token ); // transforms provided location by specifed rotation and offset glm::dvec3 transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad ); +}; +class state_manager { + +public: +// methods + // legacy method, calculates changes in simulation state over specified time + void + update( double Deltatime, int Iterationcount ); + // restores simulation data from specified file. returns: true on success, false otherwise + bool + deserialize( std::string const &Scenariofile ); + // stores class data in specified file, in legacy (text) format + void + export_as_text( std::string const &Scenariofile ) const; + +private: +// members + state_serializer m_serializer; }; extern state_manager State; diff --git a/simulationtime.cpp b/simulationtime.cpp new file mode 100644 index 00000000..69ec910e --- /dev/null +++ b/simulationtime.cpp @@ -0,0 +1,197 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#include "stdafx.h" +#include "simulationtime.h" + +#include "Globals.h" +#include "utilities.h" + +namespace simulation { + +scenario_time Time; + +} // simulation + +void +scenario_time::init() { + char monthdaycounts[ 2 ][ 13 ] = { + { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; + ::memcpy( m_monthdaycounts, monthdaycounts, sizeof( monthdaycounts ) ); + + // potentially adjust scenario clock + auto const requestedtime { clamp_circular( m_time.wHour * 60 + m_time.wMinute + Global.ScenarioTimeOffset * 60, 24 * 60 ) }; + auto const requestedhour { ( requestedtime / 60 ) % 24 }; + auto const requestedminute { requestedtime % 60 }; + // cache requested elements, if any + +#ifdef __linux__ + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + tm *tms = localtime(&ts.tv_sec); + m_time.wYear = tms->tm_year; + m_time.wMonth = tms->tm_mon; + m_time.wDayOfWeek = tms->tm_wday; + m_time.wDay = tms->tm_mday; + m_time.wHour = tms->tm_hour; + m_time.wMinute = tms->tm_min; + m_time.wSecond = tms->tm_sec; + m_time.wMilliseconds = ts.tv_nsec / 1000000; + +/* + time_t local = mktime(localtime(&ts.tv_sec)); + time_t utc = mktime(gmtime(&ts.tv_sec)); + m_timezonebias = (double)(local - utc) / 3600.0f; +*/ +#elif _WIN32 + ::GetLocalTime( &m_time ); +#endif + + if( Global.fMoveLight > 0.0 ) { + // day and month of the year can be overriden by scenario setup + daymonth( m_time.wDay, m_time.wMonth, m_time.wYear, static_cast( Global.fMoveLight ) ); + } + + if( requestedhour != -1 ) { m_time.wHour = static_cast( clamp( requestedhour, 0, 23 ) ); } + if( requestedminute != -1 ) { m_time.wMinute = static_cast( clamp( requestedminute, 0, 59 ) ); } + // if the time is taken from the local clock leave the seconds intact, otherwise set them to zero + if( ( requestedhour != -1 ) + || ( requestedminute != 1 ) ) { + m_time.wSecond = 0; + } + + m_yearday = year_day( m_time.wDay, m_time.wMonth, m_time.wYear ); + + // calculate time zone bias + // retrieve relevant time zone info from system registry (or fall back on supplied default) + // TODO: select timezone matching defined geographic location and/or country + struct registry_time_zone_info { + long Bias; + long StandardBias; + long DaylightBias; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; + } timezoneinfo = { -60, 0, -60, { 0, 10, 0, 5, 3, 0, 0, 0 }, { 0, 3, 0, 5, 2, 0, 0, 0 } }; + + auto zonebias { timezoneinfo.Bias }; + if( m_yearday < year_day( timezoneinfo.DaylightDate.wDay, timezoneinfo.DaylightDate.wMonth, m_time.wYear ) ) { + zonebias += timezoneinfo.StandardBias; + } + else if( m_yearday < year_day( timezoneinfo.StandardDate.wDay, timezoneinfo.StandardDate.wMonth, m_time.wYear ) ) { + zonebias += timezoneinfo.DaylightBias; + } + else { + zonebias += timezoneinfo.StandardBias; + } + + m_timezonebias = ( zonebias / 60.0 ); +} + +void +scenario_time::update( double const Deltatime ) { + + m_milliseconds += ( 1000.0 * Deltatime ); + while( m_milliseconds >= 1000.0 ) { + + ++m_time.wSecond; + m_milliseconds -= 1000.0; + } + m_time.wMilliseconds = std::floor( m_milliseconds ); + while( m_time.wSecond >= 60 ) { + + ++m_time.wMinute; + m_time.wSecond -= 60; + } + while( m_time.wMinute >= 60 ) { + + ++m_time.wHour; + m_time.wMinute -= 60; + } + while( m_time.wHour >= 24 ) { + + ++m_time.wDay; + ++m_time.wDayOfWeek; + if( m_time.wDayOfWeek >= 7 ) { + m_time.wDayOfWeek -= 7; + } + m_time.wHour -= 24; + } + int leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 ); + while( m_time.wDay > m_monthdaycounts[ leap ][ m_time.wMonth ] ) { + + m_time.wDay -= m_monthdaycounts[ leap ][ m_time.wMonth ]; + ++m_time.wMonth; + // unlikely but we might've entered a new year + if( m_time.wMonth > 12 ) { + + ++m_time.wYear; + leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 ); + m_time.wMonth -= 12; + } + } +} + +int +scenario_time::year_day( int Day, const int Month, const int Year ) const { + + char const daytab[ 2 ][ 13 ] = { + { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } + }; + + int leap { ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ) }; + for( int i = 1; i < Month; ++i ) + Day += daytab[ leap ][ i ]; + + return Day; +} + +void +scenario_time::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ) { + + WORD daytab[ 2 ][ 13 ] = { + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } + }; + + int leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ); + WORD idx = 1; + while( ( idx < 13 ) && ( Yearday >= daytab[ leap ][ idx ] ) ) { + + ++idx; + } + Month = idx; + Day = Yearday - daytab[ leap ][ idx - 1 ]; +} + +int +scenario_time::julian_day() const { + + int yy = ( m_time.wYear < 0 ? m_time.wYear + 1 : m_time.wYear ) - std::floor( ( 12 - m_time.wMonth ) / 10.f ); + int mm = m_time.wMonth + 9; + if( mm >= 12 ) { mm -= 12; } + + int K1 = std::floor( 365.25 * ( yy + 4712 ) ); + int K2 = std::floor( 30.6 * mm + 0.5 ); + + // for dates in Julian calendar + int JD = K1 + K2 + m_time.wDay + 59; + // for dates in Gregorian calendar; 2299160 is October 15th, 1582 + const int gregorianswitchday = 2299160; + if( JD > gregorianswitchday ) { + + int K3 = std::floor( std::floor( ( yy * 0.01 ) + 49 ) * 0.75 ) - 38; + JD -= K3; + } + + return JD; +} + +//--------------------------------------------------------------------------- diff --git a/simulationtime.h b/simulationtime.h new file mode 100644 index 00000000..695a24cc --- /dev/null +++ b/simulationtime.h @@ -0,0 +1,68 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include "winheaders.h" + +// wrapper for scenario time +class scenario_time { + +public: + scenario_time() { + m_time.wHour = 10; m_time.wMinute = 30; } + void + init(); + void + update( double const Deltatime ); + inline + SYSTEMTIME & + data() { + return m_time; } + inline + SYSTEMTIME const & + data() const { + return m_time; } + inline + double + second() const { + return ( m_time.wMilliseconds * 0.001 + m_time.wSecond ); } + inline + int + year_day() const { + return m_yearday; } + // helper, calculates day of year from given date + int + year_day( int Day, int const Month, int const Year ) const; + int + julian_day() const; + inline + double + zone_bias() const { + return m_timezonebias; } + +private: + // calculates day and month from given day of year + void + daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ); + + SYSTEMTIME m_time; + double m_milliseconds{ 0.0 }; + int m_yearday; + char m_monthdaycounts[ 2 ][ 13 ]; + double m_timezonebias{ 0.0 }; +}; + +namespace simulation { + +extern scenario_time Time; + +} // simulation + +//--------------------------------------------------------------------------- diff --git a/sky.h b/sky.h index 3fd5f642..9397422a 100644 --- a/sky.h +++ b/sky.h @@ -14,7 +14,7 @@ http://mozilla.org/MPL/2.0/. class TSky { - friend class opengl_renderer; + friend opengl_renderer; public: TSky() = default; diff --git a/stars.h b/stars.h index 6a8ef87d..9ca380ed 100644 --- a/stars.h +++ b/stars.h @@ -8,7 +8,7 @@ class cStars { - friend class opengl_renderer; + friend opengl_renderer; public: // types: diff --git a/station.cpp b/station.cpp index b9b4b441..a9fb9cbc 100644 --- a/station.cpp +++ b/station.cpp @@ -13,6 +13,12 @@ http://mozilla.org/MPL/2.0/. #include "DynObj.h" #include "mtable.h" +namespace simulation { + +basic_station Station; + +} + // exchanges load with consist attached to specified vehicle, operating on specified schedule double basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule, int const Platform ) { diff --git a/station.h b/station.h index 1b6ef061..7d6e184d 100644 --- a/station.h +++ b/station.h @@ -20,3 +20,10 @@ public: double update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule, int const Platform ); }; + +namespace simulation { + +extern basic_station Station; // temporary object, for station functionality tests + +} // simulation + diff --git a/sun.cpp b/sun.cpp index 73b2490c..16895b05 100644 --- a/sun.cpp +++ b/sun.cpp @@ -4,6 +4,7 @@ #include "mtable.h" #include "World.h" #include "utilities.h" +#include "simulationtime.h" ////////////////////////////////////////////////////////////////////////////////////////// // cSun -- class responsible for dynamic calculation of position and intensity of the Sun, diff --git a/uart.cpp b/uart.cpp index 6365df8b..bc84da90 100644 --- a/uart.cpp +++ b/uart.cpp @@ -95,7 +95,7 @@ uart_input::recall_bindings() { auto const bindingtype { typelookup->second }; std::array bindingcommands { user_command::none, user_command::none }; - auto const commandcount { ( bindingtype == toggle ? 2 : 1 ) }; + auto const commandcount { ( bindingtype == input_type_t::toggle ? 2 : 1 ) }; for( int commandidx = 0; commandidx < commandcount; ++commandidx ) { // grab command(s) associated with the input pin auto const bindingcommandname { entryparser.getToken() }; @@ -166,14 +166,14 @@ void uart_input::poll() auto const type { std::get( entry ) }; auto const action { ( - type != impulse ? + type != input_type_t::impulse ? GLFW_PRESS : ( state ? GLFW_PRESS : GLFW_RELEASE ) ) }; auto const command { ( - type != toggle ? + type != input_type_t::toggle ? std::get<2>( entry ) : ( state ? std::get<2>( entry ) : @@ -208,7 +208,7 @@ void uart_input::poll() double const position { (float)( ( (uint16_t)buffer[ 8 ] | ( (uint16_t)buffer[ 9 ] << 8 ) ) - conf.mainbrakemin ) / ( conf.mainbrakemax - conf.mainbrakemin ) }; relay.post( user_command::trainbrakeset, - reinterpret_cast( position ), + position, 0, GLFW_PRESS, // TODO: pass correct entity id once the missing systems are in place @@ -219,7 +219,7 @@ void uart_input::poll() double const position { (float)( ( (uint16_t)buffer[ 10 ] | ( (uint16_t)buffer[ 11 ] << 8 ) ) - conf.localbrakemin ) / ( conf.localbrakemax - conf.localbrakemin ) }; relay.post( user_command::independentbrakeset, - reinterpret_cast( position ), + position, 0, GLFW_PRESS, // TODO: pass correct entity id once the missing systems are in place diff --git a/uart.h b/uart.h index f4544110..b6e1dd6b 100644 --- a/uart.h +++ b/uart.h @@ -48,7 +48,7 @@ public: private: // types - enum input_type_t + enum class input_type_t { toggle, // two commands, each mapped to one state; press event on state change impulse, // one command; press event when set, release when cleared diff --git a/uilayer.cpp b/uilayer.cpp index 7abf008b..ee34cb1b 100644 --- a/uilayer.cpp +++ b/uilayer.cpp @@ -1,16 +1,18 @@ #include "stdafx.h" #include "uilayer.h" -#include "uitranscripts.h" #include "Globals.h" #include "translation.h" #include "simulation.h" +#include "simulationtime.h" #include "mtable.h" #include "Train.h" #include "DynObj.h" #include "Model3d.h" #include "renderer.h" #include "Timer.h" +#include "sceneeditor.h" +#include "renderer.h" #include "utilities.h" #include "Logs.h" #include @@ -126,6 +128,13 @@ ui_layer::on_key( int const Key, int const Action ) { } if( Action == GLFW_RELEASE ) { return true; } // recognized, but ignored + + EditorModeFlag = ( Key == GLFW_KEY_F11 ); + if( ( true == EditorModeFlag ) + && ( false == Global.ControlPicking ) ) { + set_cursor( GLFW_CURSOR_NORMAL ); + Global.ControlPicking = true; + } } default: { // everything else @@ -266,8 +275,6 @@ ui_layer::update() { "" ) ); } - EditorModeFlag = ( Global.iTextMode == GLFW_KEY_F11 ); - switch( Global.iTextMode ) { case( GLFW_KEY_F1 ) : { @@ -293,7 +300,7 @@ ui_layer::update() { else if( mover->ActiveDir < 0 ) { uitextline2 += " R"; } else { uitextline2 += " N"; } - uitextline3 = "Brakes:" + to_string( mover->fBrakeCtrlPos, 1, 5 ) + "+" + std::to_string( mover->LocalBrakePos ) + ( mover->SlippingWheels ? " !" : " " ); + uitextline3 = "Brakes:" + to_string( mover->fBrakeCtrlPos, 1, 5 ) + "+" + to_string( mover->LocalBrakePosA * LocalBrakePosNo, 0 ) + ( mover->SlippingWheels ? " !" : " " ); uitextline4 = ( true == TestFlag( mover->SecuritySystem.Status, s_aware ) ? @@ -489,7 +496,7 @@ ui_layer::update() { uitextline2 += ( vehicle->MoverParameters->OilPump.is_active ? "O" : ( vehicle->MoverParameters->OilPump.is_enabled ? "o" : "." ) ); uitextline2 += ( false == vehicle->MoverParameters->ConverterAllowLocal ? "-" : ( vehicle->MoverParameters->ConverterAllow ? ( vehicle->MoverParameters->ConverterFlag ? "X" : "x" ) : "." ) ); uitextline2 += ( vehicle->MoverParameters->ConvOvldFlag ? "!" : "." ); - uitextline2 += ( vehicle->MoverParameters->CompressorFlag ? "C" : ( false == vehicle->MoverParameters->CompressorAllowLocal ? "-" : ( ( vehicle->MoverParameters->CompressorAllow || vehicle->MoverParameters->CompressorStart == start::automatic ) ? "c" : "." ) ) ); + uitextline2 += ( vehicle->MoverParameters->CompressorFlag ? "C" : ( false == vehicle->MoverParameters->CompressorAllowLocal ? "-" : ( ( vehicle->MoverParameters->CompressorAllow || vehicle->MoverParameters->CompressorStart == start_t::automatic ) ? "c" : "." ) ) ); uitextline2 += ( vehicle->MoverParameters->CompressorGovernorLock ? "!" : "." ); auto const train { Global.pWorld->train() }; @@ -726,12 +733,16 @@ ui_layer::update() { case( GLFW_KEY_F11 ): { // scenario inspector - auto const *node { editor::Node }; + auto const *node { scene::Editor.node() }; - if( node == nullptr ) { break; } + if( node == nullptr ) { + auto const mouseposition { Global.pCamera->Pos + GfxRenderer.Mouse_Position() }; + uitextline1 = "mouse location: [" + to_string( mouseposition.x, 2 ) + ", " + to_string( mouseposition.y, 2 ) + ", " + to_string( mouseposition.z, 2 ) + "]"; + break; + } uitextline1 = - "Node name: " + node->name() + "node name: " + node->name() + "; location: [" + to_string( node->location().x, 2 ) + ", " + to_string( node->location().y, 2 ) + ", " + to_string( node->location().z, 2 ) + "]" + " (distance: " + to_string( glm::length( glm::dvec3{ node->location().x, 0.0, node->location().z } -glm::dvec3{ Global.pCameraPosition.x, 0.0, Global.pCameraPosition.z } ), 1 ) + " m)"; // subclass-specific data @@ -740,7 +751,7 @@ ui_layer::update() { auto const *subnode = static_cast( node ); - uitextline2 = "angle: " + to_string( clamp_circular( subnode->vAngle.y, 360.0 ), 2 ) + " deg"; + uitextline2 = "angle: " + to_string( clamp_circular( subnode->vAngle.y, 360.f ), 2 ) + " deg"; uitextline2 += "; lights: "; if( subnode->iNumLights > 0 ) { uitextline2 += '['; @@ -885,9 +896,9 @@ ui_layer::update() { uitextline2 = "HamZ=" + to_string( vehicle->MoverParameters->fBrakeCtrlPos, 2 ) - + "; HamP=" + std::to_string( vehicle->MoverParameters->LocalBrakePos ) + "/" + to_string( vehicle->MoverParameters->LocalBrakePosA, 2 ) + + "; HamP=" + to_string( vehicle->MoverParameters->LocalBrakePosA, 2 ) + "; NasJ=" + std::to_string( vehicle->MoverParameters->MainCtrlPos ) + "(" + std::to_string( vehicle->MoverParameters->MainCtrlActualPos ) + ")" - + ( ( vehicle->MoverParameters->ShuntMode && vehicle->MoverParameters->EngineType == DieselElectric ) ? + + ( ( vehicle->MoverParameters->ShuntMode && vehicle->MoverParameters->EngineType == TEngineType::DieselElectric ) ? "; NasB=" + to_string( vehicle->MoverParameters->AnPos, 2 ) : "; NasB=" + std::to_string( vehicle->MoverParameters->ScndCtrlPos ) + "(" + std::to_string( vehicle->MoverParameters->ScndCtrlActualPos ) + ")" ) + "; I=" + @@ -952,7 +963,7 @@ ui_layer::update() { uitextline3 += " Vtrack " + to_string( vehicle->MoverParameters->RunningTrack.Velmax, 2 ); } - if( ( vehicle->MoverParameters->EnginePowerSource.SourceType == CurrentCollector ) + if( ( vehicle->MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) || ( vehicle->MoverParameters->TrainType == dt_EZT ) ) { uitextline3 += "; pant. " + to_string( vehicle->MoverParameters->PantPress, 2 ) @@ -980,7 +991,7 @@ ui_layer::update() { } // induction motor data - if( vehicle->MoverParameters->EngineType == ElectricInductionMotor ) { + if( vehicle->MoverParameters->EngineType == TEngineType::ElectricInductionMotor ) { UITable->text_lines.emplace_back( " eimc: eimv: press:", Global.UITextColor ); for( int i = 0; i <= 20; ++i ) { @@ -1003,7 +1014,7 @@ ui_layer::update() { UITable->text_lines.emplace_back( parameters, Global.UITextColor ); } } - if (vehicle->MoverParameters->EngineType == DieselEngine) { + if (vehicle->MoverParameters->EngineType == TEngineType::DieselEngine) { std::string parameters = "param value"; UITable->text_lines.emplace_back(parameters, Global.UITextColor); parameters = "efill: " + to_string(vehicle->MoverParameters->dizel_fill, 2, 9); @@ -1122,6 +1133,13 @@ ui_layer::render() { glPopAttrib(); } +void +ui_layer::set_cursor( int const Mode ) { + + glfwSetInputMode( m_window, GLFW_CURSOR, Mode ); + m_cursorvisible = ( Mode != GLFW_CURSOR_DISABLED ); +} + void ui_layer::set_progress( float const Progress, float const Subtaskprogress ) { @@ -1227,6 +1245,7 @@ void ui_layer::render_tooltip() { if( m_tooltip.empty() ) { return; } + if( false == m_cursorvisible ) { return; } glm::dvec2 mousepos; glfwGetCursorPos( m_window, &mousepos.x, &mousepos.y ); diff --git a/uilayer.h b/uilayer.h index 1963427d..6f2e79d8 100644 --- a/uilayer.h +++ b/uilayer.h @@ -52,6 +52,9 @@ public: // draws requested UI elements void render(); + // + void + set_cursor( int const Mode ); // stores operation progress void set_progress( float const Progress = 0.0f, float const Subtaskprogress = 0.0f ); @@ -114,6 +117,7 @@ private: int tprev; // poprzedni czas double VelPrev; // poprzednia prędkość double Acc; // przyspieszenie styczne + bool m_cursorvisible { false }; }; extern ui_layer UILayer; diff --git a/utilities.cpp b/utilities.cpp index 1eb02df0..47f9d1c3 100644 --- a/utilities.cpp +++ b/utilities.cpp @@ -29,7 +29,7 @@ Copyright (C) 2007-2014 Maciej Cierniak bool DebugModeFlag = false; bool FreeFlyModeFlag = false; -bool EditorModeFlag = true; +bool EditorModeFlag = false; bool DebugCameraFlag = false; double Max0R(double x1, double x2) @@ -257,18 +257,24 @@ int stol_def(const std::string &str, const int &DefaultValue) { return result; } -std::string ToLower(std::string const &text) -{ - std::string lowercase( text ); - std::transform(text.begin(), text.end(), lowercase.begin(), ::tolower); +std::string ToLower(std::string const &text) { + + auto lowercase { text }; + std::transform( + std::begin( text ), std::end( text ), + std::begin( lowercase ), + []( unsigned char c ) { return std::tolower( c ); } ); return lowercase; } -std::string ToUpper(std::string const &text) -{ - std::string uppercase( text ); - std::transform(text.begin(), text.end(), uppercase.begin(), ::toupper); - return uppercase; +std::string ToUpper(std::string const &text) { + + auto uppercase { text }; + std::transform( + std::begin( text ), std::end( text ), + std::begin( uppercase ), + []( unsigned char c ) { return std::toupper( c ); } ); + return uppercase; } // replaces polish letters with basic ascii diff --git a/utilities.h b/utilities.h index e811c9c0..22b9b9b3 100644 --- a/utilities.h +++ b/utilities.h @@ -229,6 +229,13 @@ clamp_circular( Type_ Value, Type_ const Range = static_cast(360) ) { return Value; } +template +Type_ +quantize( Type_ const Value, Type_ const Step ) { + + return ( Step * std::round( Value / Step ) ); +} + template Type_ min_speed( Type_ const Left, Type_ const Right ) { diff --git a/version.h b/version.h index 89a1940a..5ec2a9c8 100644 --- a/version.h +++ b/version.h @@ -1 +1 @@ -#define VERSION_INFO "M7 30.06.2018/2, based on tmj 293787c" +#define VERSION_INFO "M7 17.07.2018/2, based on tmj 3751c8a" diff --git a/windows.cpp b/windows.cpp index df9bca7c..ba96868b 100644 --- a/windows.cpp +++ b/windows.cpp @@ -50,7 +50,6 @@ LONG CALLBACK unhandled_handler(::EXCEPTION_POINTERS* e) HWND Hwnd; WNDPROC BaseWindowProc; PCOPYDATASTRUCT pDane; -extern TWorld World; LRESULT APIENTRY WndProc( HWND hWnd, // handle for this window UINT uMsg, // message for this window