diff --git a/Camera.cpp b/Camera.cpp index cceed381..75297e4f 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -15,23 +15,19 @@ http://mozilla.org/MPL/2.0/. #include "Console.h" #include "Timer.h" #include "mover.h" + //--------------------------------------------------------------------------- // TViewPyramid TCamera::OrgViewPyramid; //={vector3(-1,1,1),vector3(1,1,1),vector3(-1,-1,1),vector3(1,-1,1),vector3(0,0,0)}; -const vector3 OrgCrossPos = vector3(0, -10, 0); - void TCamera::Init(vector3 NPos, vector3 NAngle) { - pOffset = vector3(-0.0, 0, 0); vUp = vector3(0, 1, 0); // pOffset= vector3(-0.8,0,0); - CrossPos = OrgCrossPos; CrossDist = 10; Velocity = vector3(0, 0, 0); - OldVelocity = vector3(0, 0, 0); Pitch = NAngle.x; Yaw = NAngle.y; Roll = NAngle.z; @@ -54,52 +50,445 @@ void TCamera::OnCursorMove(double x, double y) if (Type == tp_Follow) // jeżeli jazda z pojazdem { clamp(Pitch, -M_PI_4, M_PI_4); // ograniczenie kąta spoglądania w dół i w górę - // Fix(Yaw,-M_PI,M_PI); + } +} + +void +TCamera::OnCommand( command_data const &Command ) { + + double const walkspeed = 1.0; + double const runspeed = ( DebugModeFlag ? 50.0 : 7.5 ); + double const speedmultiplier = ( DebugModeFlag ? 7.5 : 1.0 ); + + switch( Command.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 ); + break; + } + + case user_command::movevector: { + + auto const movespeed = + ( Type == tp_Free ? + runspeed * speedmultiplier : + walkspeed ); + + // left-right + double const movex = reinterpret_cast( Command.param1 ); + if( movex > 0.0 ) { + m_keys.right = true; + m_keys.left = false; + } + else if( movex < 0.0 ) { + m_keys.right = false; + m_keys.left = true; + } + else { + m_keys.right = false; + m_keys.left = false; + } + // 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed + m_moverate.x = + walkspeed + + ( std::max( 0.0, std::abs( movex ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ); + + // forward-back + double const movez = reinterpret_cast( Command.param2 ); + if( movez > 0.0 ) { + m_keys.forward = true; + m_keys.back = false; + } + else if( movez < 0.0 ) { + m_keys.forward = false; + m_keys.back = true; + } + else { + m_keys.forward = false; + m_keys.back = false; + } + m_moverate.z = + walkspeed + + ( std::max( 0.0, std::abs( movez ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ); + break; + } + + case user_command::moveforward: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.forward = true; + m_moverate.z = + ( Type == tp_Free ? + walkspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.forward = false; + } + break; + } + + case user_command::moveback: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.back = true; + m_moverate.z = + ( Type == tp_Free ? + walkspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.back = false; + } + break; + } + + case user_command::moveleft: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.left = true; + m_moverate.x = + ( Type == tp_Free ? + walkspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.left = false; + } + break; + } + + case user_command::moveright: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.right = true; + m_moverate.x = + ( Type == tp_Free ? + walkspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.right = false; + } + break; + } + + case user_command::moveup: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.up = true; + m_moverate.y = + ( Type == tp_Free ? + walkspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.up = false; + } + break; + } + + case user_command::movedown: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.down = true; + m_moverate.y = + ( Type == tp_Free ? + walkspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.down = false; + } + break; + } + + case user_command::moveforwardfast: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.forward = true; + m_moverate.z = + ( Type == tp_Free ? + runspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.forward = false; + } + break; + } + + case user_command::movebackfast: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.back = true; + m_moverate.z = + ( Type == tp_Free ? + runspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.back = false; + } + break; + } + + case user_command::moveleftfast: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.left = true; + m_moverate.x = + ( Type == tp_Free ? + runspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.left = false; + } + break; + } + + case user_command::moverightfast: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.right = true; + m_moverate.x = + ( Type == tp_Free ? + runspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.right = false; + } + break; + } + + case user_command::moveupfast: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.up = true; + m_moverate.y = + ( Type == tp_Free ? + runspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.up = false; + } + break; + } + + case user_command::movedownfast: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.down = true; + m_moverate.y = + ( Type == tp_Free ? + runspeed * speedmultiplier : + walkspeed ); + } + else { + m_keys.down = false; + } + break; + } +/* + case user_command::moveforwardfastest: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.forward = true; + m_moverate.z = + ( Type == tp_Free ? + 8.0 : + 0.8 ); + } + else { + m_keys.forward = false; + } + break; + } + + case user_command::movebackfastest: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.back = true; + m_moverate.z = + ( Type == tp_Free ? + 8.0 : + 0.8 ); + } + else { + m_keys.back = false; + } + break; + } + + case user_command::moveleftfastest: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.left = true; + m_moverate.x = + ( Type == tp_Free ? + 8.0 : + 0.8 ); + } + else { + m_keys.left = false; + } + break; + } + + case user_command::moverightfastest: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.right = true; + m_moverate.x = + ( Type == tp_Free ? + 8.0 : + 0.8 ); + } + else { + m_keys.right = false; + } + break; + } + + case user_command::moveupfastest: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.up = true; + m_moverate.y = + ( Type == tp_Free ? + 8.0 : + 0.8 ); + } + else { + m_keys.up = false; + } + break; + } + + case user_command::movedownfastest: { + + if( Command.action != GLFW_RELEASE ) { + m_keys.down = true; + m_moverate.y = + ( Type == tp_Free ? + 8.0 : + 0.8 ); + } + else { + m_keys.down = false; + } + break; + } +*/ } } void TCamera::Update() { - // ABu: zmiana i uniezaleznienie predkosci od FPS - double a = ( Global::shiftState ? 5.00 : 1.00); - if (Global::ctrlState) - a = a * 100; - // OldVelocity=Velocity; - if (FreeFlyModeFlag == true) - Type = tp_Free; - else - Type = tp_Follow; - if (Type == tp_Free) - { - if (Console::Pressed(Global::Keys[k_MechUp])) - Velocity.y += a; - if (Console::Pressed(Global::Keys[k_MechDown])) - Velocity.y -= a; + if( FreeFlyModeFlag == true ) { Type = tp_Free; } + else { Type = 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 + // ultimately we'll need to track position of camera/driver for all human entities present in the scenario + command_data command; + // NOTE: currently we're only storing commands for local entity and there's no id system in place, + // so we're supplying 'default' entity id of 0 + while( simulation::Commands.pop( command, static_cast( command_target::entity ) | 0 ) ) { + + OnCommand( command ); + } + + auto const deltatime = Timer::GetDeltaRenderTime(); // czas bez pauzy + +#ifdef EU07_USE_OLD_COMMAND_SYSTEM + double a = 0.8; // default (walk) movement speed + if( Type == tp_Free ) { + // when not in the cab the speed modifiers are active + if( Global::shiftState ) { a = 2.5; } + if( Global::ctrlState ) { a *= 10.0; } + } + + if( ( Type == tp_Free ) + || ( false == Global::ctrlState ) ) { + // ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed + if( Console::Pressed( Global::Keys[ k_MechUp ] ) ) + Velocity.y = clamp( Velocity.y + a * 10.0 * deltatime, -a, a ); + if( Console::Pressed( Global::Keys[ k_MechDown ] ) ) + Velocity.y = clamp( Velocity.y - a * 10.0 * deltatime, -a, a ); // McZapkie-170402: poruszanie i rozgladanie we free takie samo jak w follow - if (Console::Pressed(Global::Keys[k_MechRight])) - Velocity.x += a; - if (Console::Pressed(Global::Keys[k_MechLeft])) - Velocity.x -= a; - if (Console::Pressed(Global::Keys[k_MechForward])) - Velocity.z -= a; - if (Console::Pressed(Global::Keys[k_MechBackward])) - Velocity.z += a; - // gora-dol - // if (Console::Pressed(GLFW_KEY_KP_9)) Pos.y+=0.1; - // if (Console::Pressed(GLFW_KEY_KP_3)) Pos.y-=0.1; - - // McZapkie: zeby nie hustalo przy malym FPS: - // Velocity= (Velocity+OldVelocity)/2; - // matrix4x4 mat; - vector3 Vec = Velocity; - Vec.RotateY(Yaw); - Pos = Pos + Vec * Timer::GetDeltaRenderTime(); // czas bez pauzy - Velocity = Velocity / 2; // płynne hamowanie ruchu - // double tmp= 10*DeltaTime; - // Velocity+= -Velocity*10 * Timer::GetDeltaTime();//( tmp<1 ? tmp : 1 ); - // Type= tp_Free; + if( Console::Pressed( Global::Keys[ k_MechRight ] ) ) + Velocity.x = clamp( Velocity.x + a * 10.0 * deltatime, -a, a ); + if( Console::Pressed( Global::Keys[ k_MechLeft ] ) ) + Velocity.x = clamp( Velocity.x - a * 10.0 * deltatime, -a, a ); + if( Console::Pressed( Global::Keys[ k_MechForward ] ) ) + Velocity.z = clamp( Velocity.z - a * 10.0 * deltatime, -a, a ); + if( Console::Pressed( Global::Keys[ k_MechBackward ] ) ) + Velocity.z = clamp( Velocity.z + a * 10.0 * deltatime, -a, a ); } +#else +/* + m_moverate = 0.8; // default (walk) movement speed + if( Type == tp_Free ) { + // when not in the cab the speed modifiers are active + if( Global::shiftState ) { m_moverate = 2.5; } + if( Global::ctrlState ) { m_moverate *= 10.0; } + } +*/ + if( ( Type == tp_Free ) + || ( false == Global::ctrlState ) ) { + // ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed + if( m_keys.up ) + Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -m_moverate.y, m_moverate.y ); + if( m_keys.down ) + Velocity.y = clamp( Velocity.y - m_moverate.y * 10.0 * deltatime, -m_moverate.y, m_moverate.y ); + + // McZapkie-170402: poruszanie i rozgladanie we free takie samo jak w follow + if( m_keys.right ) + Velocity.x = clamp( Velocity.x + m_moverate.x * 10.0 * deltatime, -m_moverate.x, m_moverate.x ); + if( m_keys.left ) + Velocity.x = clamp( Velocity.x - m_moverate.x * 10.0 * deltatime, -m_moverate.x, m_moverate.x ); + if( m_keys.forward ) + Velocity.z = clamp( Velocity.z - m_moverate.z * 10.0 * deltatime, -m_moverate.z, m_moverate.z ); + if( m_keys.back ) + Velocity.z = clamp( Velocity.z + m_moverate.z * 10.0 * deltatime, -m_moverate.z, m_moverate.z ); + } +#endif + + if( Type == tp_Free ) { + vector3 Vec = Velocity; + Vec.RotateY( Yaw ); + Pos += Vec * 5.0 * deltatime; + } + else { + + } +/* + if( deltatime < 1.0 / 20.0 ) { + // płynne hamowanie ruchu + Velocity -= Velocity * 20.0 * deltatime; + } + else { + // instant stop + Velocity.Zero(); + } + if( std::abs( Velocity.x ) < 0.01 ) { Velocity.x = 0.0; } + if( std::abs( Velocity.y ) < 0.01 ) { Velocity.y = 0.0; } + if( std::abs( Velocity.z ) < 0.01 ) { Velocity.z = 0.0; } +*/ +/* + Velocity *= 0.5; + if( std::abs( Velocity.x ) < 0.01 ) { Velocity.x = 0.0; } + if( std::abs( Velocity.y ) < 0.01 ) { Velocity.y = 0.0; } + if( std::abs( Velocity.z ) < 0.01 ) { Velocity.z = 0.0; } +*/ } vector3 TCamera::GetDirection() diff --git a/Camera.h b/Camera.h index ebc98a7a..c9ab5e05 100644 --- a/Camera.h +++ b/Camera.h @@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/. #include "dumb3d.h" #include "dynobj.h" +#include "command.h" using namespace Math3D; @@ -25,7 +26,16 @@ enum TCameraType class TCamera { private: - vector3 pOffset; // nie używane (zerowe) + struct keys { + bool forward{ false }; + bool back{ false }; + bool left{ false }; + bool right{ false }; + bool up{ false }; + bool down{ false }; + bool run{ false }; + } m_keys; + glm::dvec3 m_moverate; public: // McZapkie: potrzebuje do kiwania na boki double Pitch; @@ -36,7 +46,6 @@ class TCamera vector3 LookAt; // współrzędne punktu, na który ma patrzeć vector3 vUp; vector3 Velocity; - vector3 OldVelocity; // lepiej usredniac zeby nie bylo rozbiezne przy malym FPS vector3 CrossPos; double CrossDist; void Init(vector3 NPos, vector3 NAngle); @@ -44,10 +53,10 @@ class TCamera { Pitch = Yaw = Roll = 0; }; - void OnCursorMove(double x, double y); + void OnCursorMove(double const x, double const y); + void OnCommand( command_data const &Command ); void Update(); vector3 GetDirection(); - // vector3 inline GetCrossPos() { return Pos+GetDirection()*CrossDist+CrossPos; }; bool SetMatrix(); bool SetMatrix(glm::mat4 &Matrix); void SetCabMatrix( vector3 &p ); diff --git a/Driver.cpp b/Driver.cpp index e2dbc091..5b88f354 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -828,12 +828,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN #if LOGSTOPS WriteLog( pVehicle->asName + " as " + TrainParams->TrainName - + ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute) + + ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute) + " skipped " + asNextStop); // informacja #endif // przy jakim dystansie (stanie licznika) ma przesunąć na następny postój fLastStopExpDist = mvOccupied->DistCounter + 0.250 + 0.001 * fLength; - TrainParams->UpdateMTable( Simulation::Time, asNextStop ); + TrainParams->UpdateMTable( simulation::Time, asNextStop ); TrainParams->StationIndexInc(); // przejście do następnej asNextStop = TrainParams->NextStop(); // pobranie kolejnego miejsca zatrzymania // TableClear(); //aby od nowa sprawdziło W4 z inną nazwą już - to nie @@ -930,7 +930,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN // niezależne od sposobu obsługi drzwi, bo // opóźnia również kierownika } - if (TrainParams->UpdateMTable( Simulation::Time, asNextStop) ) + if (TrainParams->UpdateMTable( simulation::Time, asNextStop) ) { // to się wykona tylko raz po zatrzymaniu na W4 if (TrainParams->CheckTrainLatency() < 0.0) iDrivigFlags |= moveLate; // odnotowano spóźnienie @@ -976,7 +976,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN if (TrainParams->StationIndex < TrainParams->StationCount) { // jeśli są dalsze stacje, czekamy do godziny odjazdu - if (TrainParams->IsTimeToGo(Simulation::Time.data().wHour, Simulation::Time.data().wMinute)) + if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute)) { // z dalszą akcją czekamy do godziny odjazdu /* potencjalny problem z ruszaniem z w4 if (TrainParams->CheckTrainLatency() < 0) @@ -995,7 +995,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN #if LOGSTOPS WriteLog( pVehicle->asName + " as " + TrainParams->TrainName - + ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute) + + ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute) + " next " + asNextStop); // informacja #endif if (int(floor(sSpeedTable[i].evEvent->ValueGet(1))) & 1) @@ -1022,7 +1022,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN #if LOGSTOPS WriteLog( pVehicle->asName + " as " + TrainParams->TrainName - + ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute) + + ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute) + " end of route."); // informacja #endif asNextStop = TrainParams->NextStop(); // informacja o końcu trasy @@ -2865,7 +2865,7 @@ bool TController::PutCommand(std::string NewCommand, double NewValue1, double Ne } else { // inicjacja pierwszego przystanku i pobranie jego nazwy - TrainParams->UpdateMTable( Simulation::Time, TrainParams->NextStationName ); + TrainParams->UpdateMTable( simulation::Time, TrainParams->NextStationName ); TrainParams->StationIndexInc(); // przejście do następnej iStationStart = TrainParams->StationIndex; asNextStop = TrainParams->NextStop(); diff --git a/EU07.cpp b/EU07.cpp index 09dacf5b..b69a5398 100644 --- a/EU07.cpp +++ b/EU07.cpp @@ -23,6 +23,8 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others #include "Globals.h" #include "Logs.h" +#include "keyboardinput.h" +#include "gamepadinput.h" #include "Console.h" #include "PyInt.h" #include "World.h" @@ -60,6 +62,13 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others TWorld World; +namespace input { + +keyboard_input Keyboard; +gamepad_input Gamepad; + +} + #ifdef CAN_I_HAS_LIBPNG void screenshot_save_thread( char *img ) { @@ -113,12 +122,17 @@ void window_resize_callback(GLFWwindow *window, int w, int h) void cursor_pos_callback(GLFWwindow *window, double x, double y) { + input::Keyboard.mouse( x, y ); +#ifdef EU07_USE_OLD_COMMAND_SYSTEM World.OnMouseMove(x * 0.005, y * 0.01); +#endif glfwSetCursorPos(window, 0.0, 0.0); } void key_callback( GLFWwindow *window, int key, int scancode, int action, int mods ) { + input::Keyboard.key( key, action ); + Global::shiftState = ( mods & GLFW_MOD_SHIFT ) ? true : false; Global::ctrlState = ( mods & GLFW_MOD_CONTROL ) ? true : false; @@ -144,6 +158,7 @@ void key_callback( GLFWwindow *window, int key, int scancode, int action, int mo break; } #endif + default: { break; } } } else if( action == GLFW_RELEASE ) @@ -326,6 +341,7 @@ int main(int argc, char *argv[]) return -1; } + input::Gamepad.init(); Global::pWorld = &World; // Ra: wskaźnik potrzebny do usuwania pojazdów if (!World.Init(window)) @@ -335,9 +351,10 @@ int main(int argc, char *argv[]) } Console *pConsole = new Console(); // Ra: nie wiem, czy ma to sens, ale jakoś zainicjowac trzeba - +/* if( !joyGetNumDevs() ) WriteLog( "No joystick" ); +*/ if( Global::iModifyTGA < 0 ) { // tylko modyfikacja TGA, bez uruchamiania symulacji Global::iMaxTextureSize = 64; //żeby nie zamulać pamięci World.ModifyTGA(); // rekurencyjne przeglądanie katalogów @@ -354,7 +371,8 @@ int main(int argc, char *argv[]) && World.Update() && GfxRenderer.Render()) { - glfwPollEvents(); + glfwPollEvents(); + input::Gamepad.poll(); } Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej) } @@ -364,5 +382,6 @@ int main(int argc, char *argv[]) glfwDestroyWindow(window); glfwTerminate(); + return 0; } diff --git a/EvLaunch.cpp b/EvLaunch.cpp index 28789d14..4fda3368 100644 --- a/EvLaunch.cpp +++ b/EvLaunch.cpp @@ -177,9 +177,9 @@ bool TEventLauncher::Render() } else { // jeśli nie cykliczny, to sprawdzić czas - if (Simulation::Time.data().wHour == iHour) + if (simulation::Time.data().wHour == iHour) { - if (Simulation::Time.data().wMinute == iMinute) + if (simulation::Time.data().wMinute == iMinute) { // zgodność czasu uruchomienia if (UpdatedTime < 10) { diff --git a/Ground.cpp b/Ground.cpp index a282326c..393f2dbc 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -2826,7 +2826,7 @@ bool TGround::Init(std::string File) cParser timeparser( token ); timeparser.getTokens( 2, false, ":" ); - auto &time = Simulation::Time.data(); + auto &time = simulation::Time.data(); timeparser >> time.wHour >> time.wMinute; diff --git a/Model3d.cpp b/Model3d.cpp index 64df1b84..d77e1204 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -956,22 +956,22 @@ void TSubModel::RaAnimation(TAnimType a) glRotatef(v_Angles.z, 0.0f, 0.0f, 1.0f); break; case at_SecondsJump: // sekundy z przeskokiem - glRotatef(Simulation::Time.data().wSecond * 6.0, 0.0, 1.0, 0.0); + glRotatef(simulation::Time.data().wSecond * 6.0, 0.0, 1.0, 0.0); break; case at_MinutesJump: // minuty z przeskokiem - glRotatef(Simulation::Time.data().wMinute * 6.0, 0.0, 1.0, 0.0); + glRotatef(simulation::Time.data().wMinute * 6.0, 0.0, 1.0, 0.0); break; case at_HoursJump: // godziny skokowo 12h/360° - glRotatef(Simulation::Time.data().wHour * 30.0 * 0.5, 0.0, 1.0, 0.0); + glRotatef(simulation::Time.data().wHour * 30.0 * 0.5, 0.0, 1.0, 0.0); break; case at_Hours24Jump: // godziny skokowo 24h/360° - glRotatef(Simulation::Time.data().wHour * 15.0 * 0.25, 0.0, 1.0, 0.0); + glRotatef(simulation::Time.data().wHour * 15.0 * 0.25, 0.0, 1.0, 0.0); break; case at_Seconds: // sekundy płynnie - glRotatef(Simulation::Time.second() * 6.0, 0.0, 1.0, 0.0); + glRotatef(simulation::Time.second() * 6.0, 0.0, 1.0, 0.0); break; case at_Minutes: // minuty płynnie - glRotatef(Simulation::Time.data().wMinute * 6.0 + Simulation::Time.second() * 0.1, 0.0, 1.0, 0.0); + glRotatef(simulation::Time.data().wMinute * 6.0 + simulation::Time.second() * 0.1, 0.0, 1.0, 0.0); break; case at_Hours: // godziny płynnie 12h/360° glRotatef(2.0 * Global::fTimeAngleDeg, 0.0, 1.0, 0.0); @@ -996,7 +996,7 @@ void TSubModel::RaAnimation(TAnimType a) } break; case at_Wind: // ruch pod wpływem wiatru (wiatr będziemy liczyć potem...) - glRotated(1.5 * std::sin(M_PI * Simulation::Time.second() / 6.0), 0.0, 1.0, 0.0); + glRotated(1.5 * std::sin(M_PI * simulation::Time.second() / 6.0), 0.0, 1.0, 0.0); break; case at_Sky: // animacja nieba glRotated(Global::fLatitudeDeg, 1.0, 0.0, 0.0); // ustawienie osi OY na północ diff --git a/Train.cpp b/Train.cpp index ac3e74f8..43ad864a 100644 --- a/Train.cpp +++ b/Train.cpp @@ -13,7 +13,6 @@ http://mozilla.org/MPL/2.0/. */ #include "stdafx.h" - #include "Train.h" #include "Globals.h" @@ -22,12 +21,6 @@ http://mozilla.org/MPL/2.0/. #include "Timer.h" #include "Driver.h" #include "Console.h" -#include "McZapkie\hamulce.h" -#include "McZapkie\MOVER.h" -#include "Camera.h" -//--------------------------------------------------------------------------- - -using namespace Timer; TCab::TCab() { @@ -391,13 +384,390 @@ PyObject *TTrain::GetTrainState() { PyDict_SetItemString( dict, "actualproximitydist", PyGetFloat( driver->ActualProximityDist ) ); PyDict_SetItemString( dict, "trainnumber", PyGetString( driver->TrainName().c_str() ) ); // world state data - PyDict_SetItemString( dict, "hours", PyGetInt( Simulation::Time.data().wHour ) ); - PyDict_SetItemString( dict, "minutes", PyGetInt( Simulation::Time.data().wMinute ) ); - PyDict_SetItemString( dict, "seconds", PyGetInt( Simulation::Time.second() ) ); + PyDict_SetItemString( dict, "hours", PyGetInt( simulation::Time.data().wHour ) ); + PyDict_SetItemString( dict, "minutes", PyGetInt( simulation::Time.data().wMinute ) ); + PyDict_SetItemString( dict, "seconds", PyGetInt( simulation::Time.second() ) ); return dict; } +void +TTrain::OnCommand( command_data const &Command ) { + + bool const isEztOer = + ( ( mvControlled->TrainType == dt_EZT ) + && ( mvOccupied->BrakeSubsystem == ss_ESt ) + && ( mvControlled->Battery == true ) + && ( mvControlled->EpFuse == true ) + && ( mvControlled->ActiveDir != 0 ) ); // od yB + + switch( Command.command ) { + + case user_command::mastercontrollerincrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvControlled->IncMainCtrl( 1 ) ) { + // sound feedback + play_sound( dsbNastawnikJazdy ); + } + } + break; + } + + case user_command::mastercontrollerincreasefast: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvControlled->IncMainCtrl( 2 ) ) { + // sound feedback + play_sound( dsbNastawnikJazdy ); + } + } + break; + } + + case user_command::mastercontrollerdecrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvControlled->DecMainCtrl( 1 ) ) { + // sound feedback + play_sound( dsbNastawnikJazdy ); + } + } + break; + } + + case user_command::mastercontrollerdecreasefast: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvControlled->DecMainCtrl( 2 ) ) { + // sound feedback + play_sound( dsbNastawnikJazdy ); + } + } + break; + } + + case user_command::secondcontrollerincrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvControlled->ShuntMode ) { + mvControlled->AnPos += ( Command.time_delta * 0.75f ); + if( mvControlled->AnPos > 1 ) + mvControlled->AnPos = 1; + } + else if( mvControlled->IncScndCtrl( 1 ) ) { + // sound feedback + play_sound( dsbNastawnikBocz, dsbNastawnikJazdy ); + } + } + break; + } + + case user_command::secondcontrollerincreasefast: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvControlled->IncScndCtrl( 2 ) ) { + // sound feedback + play_sound( dsbNastawnikBocz, dsbNastawnikJazdy ); + } + } + break; + } + + case user_command::secondcontrollerdecrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvControlled->ShuntMode ) { + mvControlled->AnPos -= ( Command.time_delta * 0.75f ); + if( mvControlled->AnPos > 1 ) + mvControlled->AnPos = 1; + } + else if( mvControlled->DecScndCtrl( 1 ) ) { + // sound feedback + play_sound( dsbNastawnikBocz, dsbNastawnikJazdy ); + } + } + break; + } + + case user_command::secondcontrollerdecreasefast: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvControlled->DecScndCtrl( 2 ) ) { + // sound feedback + play_sound( dsbNastawnikBocz, dsbNastawnikJazdy ); + } + } + break; + } + + case user_command::independentbrakeincrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvOccupied->LocalBrake != ManualBrake ) { + mvOccupied->IncLocalBrakeLevel( 1 ); + } + } + break; + } + + case user_command::independentbrakeincreasefast: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvOccupied->LocalBrake != ManualBrake ) { + mvOccupied->IncLocalBrakeLevel( 2 ); + } + } + break; + } + + case user_command::independentbrakedecrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( ( mvOccupied->LocalBrake != 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 + || ( mvOccupied->LocalBrakePos != 0 ) ) { + mvOccupied->DecLocalBrakeLevel( 1 ); + } + } + break; + } + + case user_command::independentbrakedecreasefast: { + + if( Command.action != GLFW_RELEASE ) { + + if( ( mvOccupied->LocalBrake != 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 + || ( mvOccupied->LocalBrakePos != 0 ) ) { + mvOccupied->DecLocalBrakeLevel( 2 ); + } + } + break; + } + + case user_command::independentbrakebailoff: { + // 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( ( mvControlled->TrainType != dt_EZT ) + && ( ( mvControlled->EngineType == ElectricSeriesMotor ) + || ( mvControlled->EngineType == DieselElectric ) + || ( mvControlled->EngineType == ElectricInductionMotor ) ) + && ( mvOccupied->BrakeCtrlPosNo > 0 ) ) { + + if( Command.action != GLFW_RELEASE ) { + // press or hold + ggReleaserButton.UpdateValue( 1 ); + mvOccupied->BrakeReleaser( 1 ); + } + else { + // release + ggReleaserButton.UpdateValue( 0 ); + mvOccupied->BrakeReleaser( 0 ); + } + } + break; + } + + case user_command::trainbrakeincrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvOccupied->BrakeHandle == FV4a ) { + mvOccupied->BrakeLevelAdd( 0.1 /*15.0 * Command.time_delta*/ ); + } + else { + if( mvOccupied->BrakeLevelAdd( Global::fBrakeStep ) ) { + // nieodpowiedni warunek; true, jeśli można dalej kręcić + keybrakecount = 0; + if( ( isEztOer ) && ( mvOccupied->BrakeCtrlPos < 3 ) ) { + // Ra: uzależnić dźwięk od zmiany stanu EP, nie od klawisza + play_sound( dsbPneumaticSwitch ); + } + } + } + } + break; + } + + case user_command::trainbrakedecrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvOccupied->BrakeHandle == FV4a ) { + mvOccupied->BrakeLevelAdd( -0.1 /*-15.0 * Command.time_delta*/ ); + } + else { + // nową wersję dostarczył ZiomalCl ("fixed looped sound in ezt when using NUM_9 key") + if( ( mvOccupied->BrakeCtrlPos > -1 ) + || ( keybrakecount > 1 ) ) { + + if( ( isEztOer ) + && ( mvControlled->Mains ) + && ( mvOccupied->BrakeCtrlPos != -1 ) ) { + // Ra: uzależnić dźwięk od zmiany stanu EP, nie od klawisza + play_sound( dsbPneumaticSwitch ); + } + mvOccupied->BrakeLevelAdd( -Global::fBrakeStep ); + } + else + keybrakecount += 1; + // koniec wersji dostarczonej przez ZiomalCl + } + } + break; + } + + case user_command::trainbrakecharging: { + + if( Command.action != GLFW_RELEASE ) { + + // sound feedback + if( ( isEztOer ) + && ( mvControlled->Mains ) + && ( mvOccupied->BrakeCtrlPos != -1 ) ) { + dsbPneumaticSwitch->Play( 0, 0, 0 ); + } + mvOccupied->BrakeLevelSet( -1 ); + } + break; + } + + case user_command::trainbrakerelease: { + + if( Command.action != GLFW_RELEASE ) { + + // sound feedback + if( ( isEztOer ) + && ( ( mvOccupied->BrakeCtrlPos == 1 ) + || ( mvOccupied->BrakeCtrlPos == -1 ) ) ) { + dsbPneumaticSwitch->Play( 0, 0, 0 ); + } + mvOccupied->BrakeLevelSet( 0 ); + } + break; + } + + case user_command::trainbrakefirstservice: { + + if( Command.action != GLFW_RELEASE ) { + + // sound feedback + if( ( isEztOer ) + && ( mvControlled->Mains ) + && ( mvOccupied->BrakeCtrlPos != 1 ) ) { + dsbPneumaticSwitch->Play( 0, 0, 0 ); + } + mvOccupied->BrakeLevelSet( 1 ); + } + break; + } + + case user_command::trainbrakeservice: { + + if( Command.action != GLFW_RELEASE ) { + + // sound feedback + if( ( isEztOer ) + && ( mvControlled->Mains ) + && ( ( mvOccupied->BrakeCtrlPos == 1 ) + || ( mvOccupied->BrakeCtrlPos == -1 ) ) ) { + dsbPneumaticSwitch->Play( 0, 0, 0 ); + } + mvOccupied->BrakeLevelSet( + mvOccupied->BrakeCtrlPosNo / 2 + + ( mvOccupied->BrakeHandle == FV4a ? + 1 : + 0 ) ); + } + break; + } + + case user_command::trainbrakefullservice: { + + if( Command.action != GLFW_RELEASE ) { + + // sound feedback + if( ( isEztOer ) + && ( mvControlled->Mains ) + && ( ( mvOccupied->BrakeCtrlPos == 1 ) + || ( mvOccupied->BrakeCtrlPos == -1 ) ) ) { + dsbPneumaticSwitch->Play( 0, 0, 0 ); + } + mvOccupied->BrakeLevelSet( mvOccupied->BrakeCtrlPosNo - 1 ); + } + break; + } + + case user_command::trainbrakeemergency: { + + if( Command.action != GLFW_RELEASE ) { + + mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_EB ) ); + if( mvOccupied->BrakeCtrlPosNo <= 0.1 ) { + // hamulec bezpieczeństwa dla wagonów + mvOccupied->EmergencyBrakeFlag = true; + } + } + break; + } + + case user_command::reverserincrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvOccupied->DirectionForward() ) { + // sound feedback + play_sound( dsbReverserKey, dsbSwitch ); + // aktualizacja skrajnych pojazdów w składzie + if( ( mvOccupied->ActiveDir ) + && ( DynamicObject->Mechanik ) ) { + + DynamicObject->Mechanik->CheckVehicles( Change_direction ); + } + } + } + break; + } + + case user_command::reverserdecrease: { + + if( Command.action != GLFW_RELEASE ) { + + if( mvOccupied->DirectionBackward() ) { + // sound feedback + play_sound( dsbReverserKey, dsbSwitch ); + // aktualizacja skrajnych pojazdów w składzie + if( ( mvOccupied->ActiveDir ) + && ( DynamicObject->Mechanik ) ) { + + DynamicObject->Mechanik->CheckVehicles( Change_direction ); + } + } + } + break; + } + + default: { + + break; + } + } +} + void TTrain::OnKeyDown(int cKey) { // naciśnięcie klawisza bool isEztOer; @@ -409,6 +779,7 @@ void TTrain::OnKeyDown(int cKey) if (Global::shiftState) { // wciśnięty [Shift] +#ifdef EU07_USE_OLD_COMMAND_SYSTEM if (cKey == Global::Keys[k_IncMainCtrlFAST]) // McZapkie-200702: szybkie // przelaczanie na poz. // bezoporowa @@ -419,7 +790,8 @@ void TTrain::OnKeyDown(int cKey) dsbNastawnikJazdy->Play(0, 0, 0); } } - else if (cKey == Global::Keys[k_DirectionBackward]) +#endif + if (cKey == Global::Keys[k_DirectionBackward]) { if (mvOccupied->Radio == false) if (Global::ctrlState) @@ -429,6 +801,7 @@ void TTrain::OnKeyDown(int cKey) mvOccupied->Radio = true; } } +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else if (cKey == Global::Keys[k_DecMainCtrlFAST]) if (mvControlled->DecMainCtrl(2)) { @@ -469,7 +842,7 @@ void TTrain::OnKeyDown(int cKey) } else ; - else if (cKey == Global::Keys[k_IncLocalBrakeLevelFAST]) + else if( cKey == Global::Keys[ k_IncLocalBrakeLevelFAST ] ) if (mvOccupied->IncLocalBrakeLevel(2)) ; else @@ -479,6 +852,7 @@ void TTrain::OnKeyDown(int cKey) ; else ; +#endif // McZapkie-240302 - wlaczanie glownego obwodu klawiszem M+shift //----------- // hunter-141211: wyl. szybki zalaczony przeniesiony do TTrain::Update() @@ -1177,7 +1551,8 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || } else // McZapkie-240302 - klawisze bez shifta { - if (cKey == Global::Keys[k_IncMainCtrl]) +#ifdef EU07_USE_OLD_COMMAND_SYSTEM + if( cKey == Global::Keys[ k_IncMainCtrl ] ) { if (mvControlled->IncMainCtrl(1)) { @@ -1193,13 +1568,13 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || } else ; - else if (cKey == Global::Keys[k_IncScndCtrl]) + if (cKey == Global::Keys[k_IncScndCtrl]) // if (MoverParameters->ScndCtrlPosScndCtrlPosNo) // if // (mvControlled->EnginePowerSource.SourceType==CurrentCollector) if (mvControlled->ShuntMode) { - mvControlled->AnPos += (GetDeltaTime() / 0.85f); + mvControlled->AnPos += (Timer::GetDeltaTime() / 0.85f); if (mvControlled->AnPos > 1) mvControlled->AnPos = 1; } @@ -1218,11 +1593,11 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || } else ; - else if (cKey == Global::Keys[k_DecScndCtrl]) + else if( cKey == Global::Keys[ k_DecScndCtrl ] ) // if (mvControlled->EnginePowerSource.SourceType==CurrentCollector) if (mvControlled->ShuntMode) { - mvControlled->AnPos -= (GetDeltaTime() / 0.55f); + mvControlled->AnPos -= (Timer::GetDeltaTime() / 0.55f); if (mvControlled->AnPos < 0) mvControlled->AnPos = 0; } @@ -1244,7 +1619,8 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || } else ; - else if (cKey == Global::Keys[k_IncLocalBrakeLevel]) +#endif + if( cKey == Global::Keys[ k_IncLocalBrakeLevel ] ) { // Ra 2014-09: w // trybie latania // obsługa jest w @@ -1258,8 +1634,10 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || } else ; +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else if (mvOccupied->LocalBrake != ManualBrake) mvOccupied->IncLocalBrakeLevel(1); +#endif } } else if (cKey == Global::Keys[k_DecLocalBrakeLevel]) @@ -1274,12 +1652,15 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || mvOccupied->DecManualBrakeLevel(1); else ; +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else // Ra 1014-06: AI potrafi zahamować pomocniczym mimo jego braku - // odhamować jakoś trzeba if ((mvOccupied->LocalBrake != ManualBrake) || mvOccupied->LocalBrakePos) mvOccupied->DecLocalBrakeLevel(1); +#endif } } +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else if ((cKey == Global::Keys[k_IncBrakeLevel]) && (mvOccupied->BrakeHandle != FV4a)) // if (mvOccupied->IncBrakeLevel()) if (mvOccupied->BrakeLevelAdd(Global::fBrakeStep)) // nieodpowiedni @@ -1330,14 +1711,16 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || else keybrakecount+=1; */ } - else if (cKey == Global::Keys[k_EmergencyBrake]) +#endif +#ifdef EU07_USE_OLD_COMMAND_SYSTEM + else if( cKey == Global::Keys[ k_EmergencyBrake ] ) { // while (mvOccupied->IncBrakeLevel()); mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_EB)); if (mvOccupied->BrakeCtrlPosNo <= 0.1) // hamulec bezpieczeństwa dla wagonów mvOccupied->EmergencyBrakeFlag = true; } - else if (cKey == Global::Keys[k_Brake3]) + else if( cKey == Global::Keys[ k_Brake3 ] ) { if ((isEztOer) && ((mvOccupied->BrakeCtrlPos == 1) || (mvOccupied->BrakeCtrlPos == -1))) { @@ -1350,9 +1733,11 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || // mvOccupied->IncBrakeLevel()); mvOccupied->BrakeLevelSet(mvOccupied->BrakeCtrlPosNo - 1); } +#endif else if (cKey == Global::Keys[k_Brake2]) { - if ((isEztOer) && ((mvOccupied->BrakeCtrlPos == 1) || (mvOccupied->BrakeCtrlPos == -1))) +#ifdef EU07_USE_OLD_COMMAND_SYSTEM + if( ( isEztOer ) && ( ( mvOccupied->BrakeCtrlPos == 1 ) || ( mvOccupied->BrakeCtrlPos == -1 ) ) ) { dsbPneumaticSwitch->SetVolume(-10); dsbPneumaticSwitch->Play(0, 0, 0); @@ -1363,13 +1748,15 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || // mvOccupied->IncBrakeLevel()); mvOccupied->BrakeLevelSet(mvOccupied->BrakeCtrlPosNo / 2 + (mvOccupied->BrakeHandle == FV4a ? 1 : 0)); +#endif if (Global::ctrlState) mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos(bh_NP)); // yB: czy ten stos funkcji nie // powinien być jako oddzielna // funkcja movera? } - else if (cKey == Global::Keys[k_Brake1]) +#ifdef EU07_USE_OLD_COMMAND_SYSTEM + else if( cKey == Global::Keys[ k_Brake1 ] ) { if ((isEztOer) && (mvOccupied->BrakeCtrlPos != 1)) { @@ -1380,12 +1767,14 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || // while (mvOccupied->BrakeCtrlPos<1 && mvOccupied->IncBrakeLevel()); mvOccupied->BrakeLevelSet(1); } +#endif else if (cKey == Global::Keys[k_Brake0]) { if (Global::ctrlState) { mvOccupied->BrakeCtrlPos2 = 0; // wyrownaj kapturek } +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else { if ((isEztOer) && @@ -1398,7 +1787,9 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || // while (mvOccupied->BrakeCtrlPos<0 && mvOccupied->IncBrakeLevel()); mvOccupied->BrakeLevelSet(0); } +#endif } +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else if (cKey == Global::Keys[k_WaveBrake]) //[Num.] { if ((isEztOer) && (mvControlled->Mains) && (mvOccupied->BrakeCtrlPos != -1)) @@ -1410,6 +1801,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || // while (mvOccupied->BrakeCtrlPos<-1 && mvOccupied->IncBrakeLevel()); mvOccupied->BrakeLevelSet(-1); } +#endif else if (cKey == Global::Keys[k_Czuwak]) //--------------- // hunter-131211: zbicie czuwaka przeniesione do TTrain::Update() @@ -1457,6 +1849,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || mvControlled->FuseOn(); } } +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else if (cKey == Global::Keys[k_DirectionForward]) // McZapkie-240302 - zmiana kierunku: 'd' do przodu, 'r' do tylu { @@ -1483,6 +1876,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || Change_direction); // aktualizacja skrajnych pojazdów w składzie } } +#endif else if (cKey == Global::Keys[k_DirectionBackward]) // r { if (Global::ctrlState) @@ -1494,6 +1888,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || mvOccupied->Radio = false; } } +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else if (mvOccupied->DirectionBackward()) { //------------ @@ -1516,6 +1911,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || DynamicObject->Mechanik->CheckVehicles( Change_direction); // aktualizacja skrajnych pojazdów w składzie } +#endif } else if (cKey == Global::Keys[k_Main]) // McZapkie-240302 - wylaczanie glownego obwodu @@ -1634,7 +2030,8 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || } } //----------- - else if (cKey == Global::Keys[k_Releaser]) // odluzniacz +#ifdef EU07_USE_OLD_COMMAND_SYSTEM + else if( cKey == Global::Keys[ k_Releaser ] ) // odluzniacz { if (!FreeFlyModeFlag) { @@ -1654,6 +2051,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) || } } } +#endif else if (cKey == Global::Keys[k_SmallCompressor]) // Winger 160404: mala // sprezarka wl { // Ra: bez [Shift] też dać dźwięk @@ -2374,7 +2772,7 @@ if else { // McZapkie: poruszanie sie po kabinie, w updatemechpos zawarte sa wiezy - +/* auto step = 1.0f; auto const camerayaw = Global::pCamera->Yaw; Math3D::vector3 direction( 0.0f, 0.0f, step ); @@ -2428,6 +2826,7 @@ if else if (cKey == Global::Keys[k_MechDown]) pMechOffset.y -= 0.25; // McZapkie-120302 - siadanie } +*/ } // else @@ -2573,14 +2972,14 @@ void TTrain::UpdateMechPosition(double dt) vMechVelocity.y = -vMechVelocity.y; // ABu011104: 5*pMechShake.y, zeby ladnie pudlem rzucalo :) pMechPosition = pMechOffset + vector3( 1.5 * pMechShake.x, 2.0 * pMechShake.y, 1.5 * pMechShake.z ); - vMechMovement = 0.5 * vMechMovement; +// vMechMovement = 0.5 * vMechMovement; } else { // hamowanie rzucania przy spadku FPS pMechShake -= pMechShake * std::min( dt, 1.0 ); // po tym chyba potrafią zostać jakieś ułamki, które powodują zjazd pMechOffset += vMechMovement * dt; vMechVelocity.y = 0.5 * vMechVelocity.y; pMechPosition = pMechOffset + vector3( pMechShake.x, 5 * pMechShake.y, pMechShake.z ); - vMechMovement = 0.5 * vMechMovement; +// vMechMovement = 0.5 * vMechMovement; } // numer kabiny (-1: kabina B) if( DynamicObject->Mechanik ) // może nie być? @@ -2636,6 +3035,30 @@ TTrain::GetWorldMechPosition() { bool TTrain::Update( double const Deltatime ) { + // check for sent user commands + // NOTE: this is a temporary arrangement, for the transition period from old command setup to the new one + // eventually commands are going to be retrieved directly by the vehicle, filtered through active control stand + // and ultimately executed, provided the stand allows it. + command_data command; + // NOTE: currently we're only storing commands for local vehicle and there's no id system in place, + // so we're supplying 'default' vehicle id of 0 + while( simulation::Commands.pop( command, static_cast( command_target::vehicle ) | 0 ) ) { + + OnCommand( command ); + } + + // update driver's position + { + vector3 Vec = Global::pCamera->Velocity * -2.0;// -7.5 * Timer::GetDeltaRenderTime(); + Vec.y = -Vec.y; + if( mvOccupied->ActiveCab < 0 ) { + Vec *= -1.0f; + Vec.y = -Vec.y; + } + Vec.RotateY( Global::pCamera->Yaw ); + vMechMovement = Vec; + } + DWORD stat; double dt = Deltatime; // Timer::GetDeltaTime(); if (DynamicObject->mdKabina) @@ -2648,7 +3071,7 @@ bool TTrain::Update( double const Deltatime ) fTachoVelocity = Min0R(fabs(11.31 * mvControlled->WheelDiameter * mvControlled->nrot), mvControlled->Vmax * 1.05); { // skacze osobna zmienna - float ff = Simulation::Time.data().wSecond; // skacze co sekunde - pol sekundy + float ff = simulation::Time.data().wSecond; // skacze co sekunde - pol sekundy // pomiar, pol sekundy ustawienie if (ff != fTachoTimer) // jesli w tej sekundzie nie zmienial { @@ -3326,11 +3749,11 @@ bool TTrain::Update( double const Deltatime ) // McZapkie-300302: zegarek if (ggClockMInd.SubModel) { - ggClockSInd.UpdateValue(Simulation::Time.data().wSecond); + ggClockSInd.UpdateValue(simulation::Time.data().wSecond); ggClockSInd.Update(); - ggClockMInd.UpdateValue(Simulation::Time.data().wMinute); + ggClockMInd.UpdateValue(simulation::Time.data().wMinute); ggClockMInd.Update(); - ggClockHInd.UpdateValue(Simulation::Time.data().wHour + Simulation::Time.data().wMinute / 60.0); + ggClockHInd.UpdateValue(simulation::Time.data().wHour + simulation::Time.data().wMinute / 60.0); ggClockHInd.Update(); } @@ -4462,7 +4885,7 @@ bool TTrain::Update( double const Deltatime ) else */ //----------------- - +#ifdef EU07_USE_OLD_COMMAND_SYSTEM if ((!FreeFlyModeFlag) && (!(DynamicObject->Mechanik ? DynamicObject->Mechanik->AIControllFlag : false))) { @@ -4486,6 +4909,7 @@ bool TTrain::Update( double const Deltatime ) else mvOccupied->BrakeReleaser(0); } // FFMF +#endif if (Console::Pressed(Global::Keys[k_Univ1])) { @@ -4742,6 +5166,7 @@ bool TTrain::Update( double const Deltatime ) if (mvOccupied->BrakeCtrlPos2 < -1.5) mvOccupied->BrakeCtrlPos2 = -1.5; } +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else { // mvOccupied->BrakeCtrlPosR+=(mvOccupied->BrakeCtrlPosR>mvOccupied->BrakeCtrlPosNo?0:dt*2); @@ -4749,6 +5174,7 @@ bool TTrain::Update( double const Deltatime ) // mvOccupied->BrakeCtrlPos= // floor(mvOccupied->BrakeCtrlPosR+0.499); } +#endif } if ((mvOccupied->BrakeHandle == FV4a) && (Console::Pressed(Global::Keys[k_DecBrakeLevel]))) @@ -4759,6 +5185,7 @@ bool TTrain::Update( double const Deltatime ) if (mvOccupied->BrakeCtrlPos2 < -3) mvOccupied->BrakeCtrlPos2 = -3; } +#ifdef EU07_USE_OLD_COMMAND_SYSTEM else { // mvOccupied->BrakeCtrlPosR-=(mvOccupied->BrakeCtrlPosR<-1?0:dt*2); @@ -4766,6 +5193,7 @@ bool TTrain::Update( double const Deltatime ) // floor(mvOccupied->BrakeCtrlPosR+0.499); mvOccupied->BrakeLevelAdd(-dt * 2); } +#endif } // bool kEP; @@ -5003,7 +5431,9 @@ bool TTrain::Update( double const Deltatime ) ggMainOffButton.UpdateValue(0); ggMainOnButton.UpdateValue(0); ggSecurityResetButton.UpdateValue(0); +/* ggReleaserButton.UpdateValue(0); +*/ ggSandButton.UpdateValue(0); ggAntiSlipButton.UpdateValue(0); ggDepartureSignalButton.UpdateValue(0); @@ -6609,3 +7039,23 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con return true; } + +void +TTrain::play_sound( PSound Sound, PSound Fallbacksound ) { + + if( Sound ) { + + Sound->SetCurrentPosition( 0 ); + Sound->SetVolume( DSBVOLUME_MAX ); + Sound->Play( 0, 0, 0 ); + return; + } + if( Fallbacksound ) { + + Fallbacksound->SetCurrentPosition( 0 ); + Fallbacksound->SetVolume( DSBVOLUME_MAX ); + Fallbacksound->Play( 0, 0, 0 ); + return; + } +} + diff --git a/Train.h b/Train.h index 173d1489..d34ff700 100644 --- a/Train.h +++ b/Train.h @@ -7,24 +7,17 @@ obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef TrainH -#define TrainH +#pragma once -//#include "Track.h" -//#include "TrkFoll.h" -#include "Button.h" +#include #include "DynObj.h" +#include "Button.h" #include "Gauge.h" -#include "Model3d.h" #include "Spring.h" -#include "mtable.h" - #include "AdvSound.h" #include "FadeSound.h" #include "PyInt.h" -#include "RealSound.h" -#include "Sound.h" -#include +#include "command.h" // typedef enum {st_Off, st_Starting, st_On, st_ShuttingDown} T4State; @@ -82,6 +75,7 @@ class TTrain bool Init(TDynamicObject *NewDynamicObject, bool e3d = false); void OnKeyDown(int cKey); void OnKeyUp(int cKey); + void OnCommand( command_data const &Command ); // bool SHP() { fShpTimer= 0; }; @@ -113,6 +107,9 @@ class TTrain // initializes a button matching provided label. returns: true if the label was found, false // otherwise bool initialize_button(cParser &Parser, std::string const &Label, int const Cabindex); + // plays specified sound, or fallback sound if the primary sound isn't presend + // NOTE: temporary routine until sound system is sorted out and paired with switches + void play_sound( PSound Sound, PSound Fallbacksound = nullptr ); private: //żeby go nic z zewnątrz nie przestawiało TDynamicObject *DynamicObject; // przestawia zmiana pojazdu [F5] @@ -438,4 +435,3 @@ class TTrain void Silence(); }; //--------------------------------------------------------------------------- -#endif diff --git a/World.cpp b/World.cpp index 7feafa8c..d42f7cfd 100644 --- a/World.cpp +++ b/World.cpp @@ -39,7 +39,7 @@ std::shared_ptr UIHeader = std::make_shared( 20, 20 ); // he std::shared_ptr UITable = std::make_shared( 20, 100 ); // schedule or scan table std::shared_ptr UITranscripts = std::make_shared( 85, 600 ); // voice transcripts -namespace Simulation { +namespace simulation { simulation_time Time; @@ -82,14 +82,13 @@ simulation_time::init() { void simulation_time::update( double const Deltatime ) { - // use large enough buffer to hold long time skips - auto milliseconds = m_time.wMilliseconds + static_cast(std::floor( 1000.0 * Deltatime )); - while( milliseconds >= 1000.0 ) { + m_milliseconds += ( 1000.0 * Deltatime ); + while( m_milliseconds >= 1000.0 ) { ++m_time.wSecond; - milliseconds -= 1000; + m_milliseconds -= 1000.0; } - m_time.wMilliseconds = milliseconds; + m_time.wMilliseconds = std::floor( m_milliseconds ); while( m_time.wSecond >= 60 ) { ++m_time.wMinute; @@ -310,7 +309,7 @@ bool TWorld::Init( GLFWwindow *Window ) { glfwSetWindowTitle( window, ( Global::AppName + " (" + Global::SceneryFile + ")" ).c_str() ); // nazwa scenerii - Simulation::Time.init(); + simulation::Time.init(); Environment.init(); Camera.Init(Global::FreeCameraInit[0], Global::FreeCameraInitAngle[0]); @@ -502,11 +501,11 @@ void TWorld::OnKeyDown(int cKey) // additional time speedup keys in debug mode if( Global::ctrlState ) { // ctrl-f3 - Simulation::Time.update( 20.0 * 60.0 ); + simulation::Time.update( 20.0 * 60.0 ); } else if( Global::shiftState ) { // shift-f3 - Simulation::Time.update( 5.0 * 60.0 ); + simulation::Time.update( 5.0 * 60.0 ); } } if( ( false == Global::ctrlState ) @@ -972,13 +971,15 @@ bool TWorld::Update() WriteLog("Scenery moved"); }; #endif + Timer::UpdateTimers(Global::iPause != 0); + if( (Global::iPause == false) - || (m_init == false) ) - { // jak pauza, to nie ma po co tego przeliczać + || (m_init == false) ) { + // jak pauza, to nie ma po co tego przeliczać + simulation::Time.update( Timer::GetDeltaTime() ); // Ra 2014-07: przeliczenie kąta czasu (do animacji zależnych od czasu) - Simulation::Time.update( Timer::GetDeltaTime() ); - auto const &time = Simulation::Time.data(); + auto const &time = simulation::Time.data(); Global::fTimeAngleDeg = time.wHour * 15.0 + time.wMinute * 0.25 + ( ( time.wSecond + 0.001 * time.wMilliseconds ) / 240.0 ); Global::fClockAngleDeg[ 0 ] = 36.0 * ( time.wSecond % 10 ); // jednostki sekund Global::fClockAngleDeg[ 1 ] = 36.0 * ( time.wSecond / 10 ); // dziesiątki sekund @@ -1107,6 +1108,13 @@ bool TWorld::Update() fTime50Hz += dt; // w pauzie też trzeba zliczać czas, bo przy dużym FPS będzie problem z odczytem ramek while( fTime50Hz >= 1.0 / 50.0 ) { Console::Update(); // to i tak trzeba wywoływać + Update_UI(); + + Camera.Velocity *= 0.65; + if( std::abs( Camera.Velocity.x ) < 0.01 ) { Camera.Velocity.x = 0.0; } + if( std::abs( Camera.Velocity.y ) < 0.01 ) { Camera.Velocity.y = 0.0; } + if( std::abs( Camera.Velocity.z ) < 0.01 ) { Camera.Velocity.z = 0.0; } + fTime50Hz -= 1.0 / 50.0; } @@ -1114,8 +1122,6 @@ bool TWorld::Update() Update_Camera( dt ); - Update_UI(); // TBD, TODO: move the ui updates to secondary fixed step routines, to reduce workload? - GfxRenderer.Update( dt ); ResourceSweep(); @@ -1644,7 +1650,7 @@ TWorld::Update_UI() { case( GLFW_KEY_F1 ) : { // f1, default mode: current time and timetable excerpt - auto const &time = Simulation::Time.data(); + auto const &time = simulation::Time.data(); uitextline1 = "Time: " + to_string( time.wHour ) + ":" @@ -1695,7 +1701,7 @@ TWorld::Update_UI() { auto const table = tmp->Mechanik->Timetable(); if( table == nullptr ) { break; } - auto const &time = Simulation::Time.data(); + auto const &time = simulation::Time.data(); uitextline1 = "Time: " + to_string( time.wHour ) + ":" @@ -2023,8 +2029,8 @@ TWorld::Update_UI() { to_string( tmp->MoverParameters->RunningShape.R, 1 ) ) + " An=" + to_string( tmp->MoverParameters->AccN, 2 ); // przyspieszenie poprzeczne - if( tprev != Simulation::Time.data().wSecond ) { - tprev = Simulation::Time.data().wSecond; + if( tprev != simulation::Time.data().wSecond ) { + tprev = simulation::Time.data().wSecond; Acc = ( tmp->MoverParameters->Vel - VelPrev ) / 3.6; VelPrev = tmp->MoverParameters->Vel; } @@ -2184,8 +2190,7 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz) if (e) if ((e->Type == tp_Multiple) || (e->Type == tp_Lights) || (e->evJoined != 0)) // tylko jawne albo niejawne Multiple - Ground.AddToQuery(e, NULL); // drugi parametr to dynamic wywołujący - tu - // brak + Ground.AddToQuery(e, NULL); // drugi parametr to dynamic wywołujący - tu brak } break; case 3: // rozkaz dla AI @@ -2229,12 +2234,12 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz) if (*pRozkaz->iPar & 1) // ustawienie czasu { double t = pRozkaz->fPar[1]; - Simulation::Time.data().wDay = std::floor(t); // niby nie powinno być dnia, ale... + simulation::Time.data().wDay = std::floor(t); // niby nie powinno być dnia, ale... if (Global::fMoveLight >= 0) Global::fMoveLight = t; // trzeba by deklinację Słońca przeliczyć - Simulation::Time.data().wHour = std::floor(24 * t) - 24.0 * Simulation::Time.data().wDay; - Simulation::Time.data().wMinute = std::floor(60 * 24 * t) - 60.0 * (24.0 * Simulation::Time.data().wDay + Simulation::Time.data().wHour); - Simulation::Time.data().wSecond = std::floor( 60 * 60 * 24 * t ) - 60.0 * ( 60.0 * ( 24.0 * Simulation::Time.data().wDay + Simulation::Time.data().wHour ) + Simulation::Time.data().wMinute ); + simulation::Time.data().wHour = std::floor(24 * t) - 24.0 * simulation::Time.data().wDay; + simulation::Time.data().wMinute = std::floor(60 * 24 * t) - 60.0 * (24.0 * simulation::Time.data().wDay + simulation::Time.data().wHour); + simulation::Time.data().wSecond = std::floor( 60 * 60 * 24 * t ) - 60.0 * ( 60.0 * ( 24.0 * simulation::Time.data().wDay + simulation::Time.data().wHour ) + simulation::Time.data().wMinute ); } if (*pRozkaz->iPar & 2) { // ustawienie flag zapauzowania diff --git a/World.h b/World.h index dd15dbc3..312bd3cf 100644 --- a/World.h +++ b/World.h @@ -49,11 +49,12 @@ private: 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 ]; }; -namespace Simulation { +namespace simulation { extern simulation_time Time; diff --git a/command.cpp b/command.cpp new file mode 100644 index 00000000..b1bde4f4 --- /dev/null +++ b/command.cpp @@ -0,0 +1,300 @@ +/* +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 "command.h" + +#include "globals.h" +#include "logs.h" +#include "timer.h" + +namespace simulation { + +command_queue Commands; + +} + +// posts specified command for specified recipient +void +command_queue::push( command_data const &Command, std::size_t const Recipient ) { + + auto lookup = m_commands.emplace( Recipient, commanddata_sequence() ); + // recipient stack was either located or created, so we can add to it quite safely + lookup.first->second.emplace( Command ); +} + +// retrieves oldest posted command for specified recipient, if any. returns: true on retrieval, false if there's nothing to retrieve +bool +command_queue::pop( command_data &Command, std::size_t const Recipient ) { + + auto lookup = m_commands.find( Recipient ); + if( lookup == m_commands.end() ) { + // no command stack for this recipient, so no commands + return false; + } + auto &commands = lookup->second; + if( true == commands.empty() ) { + + return false; + } + // we have command stack with command(s) on it, retrieve and pop the first one + Command = commands.front(); + commands.pop(); + + return true; +} + +command_relay::command_relay() { + + m_targets = commandtarget_map{ + + { user_command::mastercontrollerincrease, command_target::vehicle }, + { user_command::mastercontrollerincreasefast, command_target::vehicle }, + { user_command::mastercontrollerdecrease, command_target::vehicle }, + { user_command::mastercontrollerdecreasefast, command_target::vehicle }, + { user_command::secondcontrollerincrease, command_target::vehicle }, + { user_command::secondcontrollerincreasefast, command_target::vehicle }, + { user_command::secondcontrollerdecrease, command_target::vehicle }, + { user_command::secondcontrollerdecreasefast, command_target::vehicle }, + { user_command::independentbrakeincrease, command_target::vehicle }, + { user_command::independentbrakeincreasefast, command_target::vehicle }, + { user_command::independentbrakedecrease, command_target::vehicle }, + { user_command::independentbrakedecreasefast, command_target::vehicle }, + { user_command::independentbrakebailoff, command_target::vehicle }, + { user_command::trainbrakeincrease, command_target::vehicle }, + { user_command::trainbrakedecrease, command_target::vehicle }, + { user_command::trainbrakecharging, command_target::vehicle }, + { user_command::trainbrakerelease, command_target::vehicle }, + { user_command::trainbrakefirstservice, command_target::vehicle }, + { user_command::trainbrakeservice, command_target::vehicle }, + { user_command::trainbrakefullservice, command_target::vehicle }, + { user_command::trainbrakeemergency, command_target::vehicle }, +/* +const int k_AntiSlipping = 21; +const int k_Sand = 22; +const int k_Main = 23; +*/ + { user_command::reverserincrease, command_target::vehicle }, + { user_command::reverserdecrease, command_target::vehicle }, +/* +const int k_Fuse = 26; +const int k_Compressor = 27; +const int k_Converter = 28; +const int k_MaxCurrent = 29; +const int k_CurrentAutoRelay = 30; +const int k_BrakeProfile = 31; +const int k_Czuwak = 32; +const int k_Horn = 33; +const int k_Horn2 = 34; +const int k_FailedEngineCutOff = 35; +*/ + { user_command::viewturn, command_target::entity }, + { user_command::movevector, command_target::entity }, + { user_command::moveleft, command_target::entity }, + { user_command::moveright, command_target::entity }, + { user_command::moveforward, command_target::entity }, + { user_command::moveback, command_target::entity }, + { user_command::moveup, command_target::entity }, + { user_command::movedown, command_target::entity }, + { user_command::moveleftfast, command_target::entity }, + { user_command::moverightfast, command_target::entity }, + { user_command::moveforwardfast, command_target::entity }, + { user_command::movebackfast, command_target::entity }, + { user_command::moveupfast, command_target::entity }, + { user_command::movedownfast, command_target::entity } +/* + { user_command::moveleftfastest, command_target::entity }, + { user_command::moverightfastest, command_target::entity }, + { user_command::moveforwardfastest, command_target::entity }, + { user_command::movebackfastest, command_target::entity }, + { user_command::moveupfastest, command_target::entity }, + { user_command::movedownfastest, command_target::entity } +*/ +/* +const int k_CabForward = 42; +const int k_CabBackward = 43; +const int k_Couple = 44; +const int k_DeCouple = 45; +const int k_ProgramQuit = 46; +// const int k_ProgramPause= 47; +const int k_ProgramHelp = 48; +const int k_OpenLeft = 49; +const int k_OpenRight = 50; +const int k_CloseLeft = 51; +const int k_CloseRight = 52; +const int k_DepartureSignal = 53; +const int k_PantFrontUp = 54; +const int k_PantRearUp = 55; +const int k_PantFrontDown = 56; +const int k_PantRearDown = 57; +const int k_Heating = 58; +// const int k_FreeFlyMode= 59; +const int k_LeftSign = 60; +const int k_UpperSign = 61; +const int k_RightSign = 62; +const int k_SmallCompressor = 63; +const int k_StLinOff = 64; +const int k_CurrentNext = 65; +const int k_Univ1 = 66; +const int k_Univ2 = 67; +const int k_Univ3 = 68; +const int k_Univ4 = 69; +const int k_EndSign = 70; +const int k_Active = 71; +const int k_Battery = 72; +const int k_WalkMode = 73; +int const k_DimHeadlights = 74; +*/ + }; + +#ifdef _DEBUG + m_commandnames = { + + "mastercontrollerincrease", + "mastercontrollerincreasefast", + "mastercontrollerdecrease", + "mastercontrollerdecreasefast", + "secondcontrollerincrease", + "secondcontrollerincreasefast", + "secondcontrollerdecrease", + "secondcontrollerdecreasefast", + "independentbrakeincrease", + "independentbrakeincreasefast", + "independentbrakedecrease", + "independentbrakedecreasefast", + "independentbrakebailoff", + "trainbrakeincrease", + "trainbrakedecrease", + "trainbrakecharging", + "trainbrakerelease", + "trainbrakefirstservice", + "trainbrakeservice", + "trainbrakefullservice", + "trainbrakeemergency", +/* +const int k_AntiSlipping = 21; +const int k_Sand = 22; +const int k_Main = 23; +*/ + "reverserincrease", + "reverserdecrease", +/* +const int k_Fuse = 26; +const int k_Compressor = 27; +const int k_Converter = 28; +const int k_MaxCurrent = 29; +const int k_CurrentAutoRelay = 30; +const int k_BrakeProfile = 31; +const int k_Czuwak = 32; +const int k_Horn = 33; +const int k_Horn2 = 34; +const int k_FailedEngineCutOff = 35; +*/ + "", //"viewturn", + "", //"movevector", + "", //"moveleft", + "", //"moveright", + "", //"moveforward", + "", //"moveback", + "", //"moveup", + "", //"movedown", + "", //"moveleftfast", + "", //"moverightfast", + "", //"moveforwardfast", + "", //"movebackfast", + "", //"moveupfast", + "" //"movedownfast" +/* + "moveleftfastest", + "moverightfastest", + "moveforwardfastest", + "movebackfastest", + "moveupfastest", + "movedownfastest" +*/ +/* +const int k_CabForward = 42; +const int k_CabBackward = 43; +const int k_Couple = 44; +const int k_DeCouple = 45; +const int k_ProgramQuit = 46; +// const int k_ProgramPause= 47; +const int k_ProgramHelp = 48; +const int k_OpenLeft = 49; +const int k_OpenRight = 50; +const int k_CloseLeft = 51; +const int k_CloseRight = 52; +const int k_DepartureSignal = 53; +const int k_PantFrontUp = 54; +const int k_PantRearUp = 55; +const int k_PantFrontDown = 56; +const int k_PantRearDown = 57; +const int k_Heating = 58; +// const int k_FreeFlyMode= 59; +const int k_LeftSign = 60; +const int k_UpperSign = 61; +const int k_RightSign = 62; +const int k_SmallCompressor = 63; +const int k_StLinOff = 64; +const int k_CurrentNext = 65; +const int k_Univ1 = 66; +const int k_Univ2 = 67; +const int k_Univ3 = 68; +const int k_Univ4 = 69; +const int k_EndSign = 70; +const int k_Active = 71; +const int k_Battery = 72; +const int k_WalkMode = 73; +int const k_DimHeadlights = 74; +*/ + }; +#endif +} + +void +command_relay::post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, int const Action, std::uint16_t const Recipient ) const { + + auto const &lookup = m_targets.find( Command ); + if( lookup == m_targets.end() ) { + // shouldn't be really needed but, eh + return; + } + if( ( lookup->second == command_target::vehicle ) + && ( true == FreeFlyModeFlag ) ) { + // don't pass vehicle commands if the user isn't in one + return; + } + + simulation::Commands.push( + command_data{ + Command, + Action, + Param1, + Param2, + Timer::GetDeltaTime() }, + static_cast( lookup->second ) | Recipient ); + +#ifdef _DEBUG + if( Action != GLFW_RELEASE ) { + // key was pressed or is still held + auto const &commandname = m_commandnames.at( static_cast( Command ) ); + if( false == commandname.empty() ) { + WriteLog( "Command issued: " + commandname ); + } + } +/* + else { + // key was released (but we don't log this) + WriteLog( "Key released: " + m_commandnames.at( static_cast( Command ) ) ); + } +*/ +#endif +} + +//--------------------------------------------------------------------------- diff --git a/command.h b/command.h new file mode 100644 index 00000000..ad02d2f7 --- /dev/null +++ b/command.h @@ -0,0 +1,196 @@ +/* +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 +#include + +enum class user_command { + + mastercontrollerincrease, + mastercontrollerincreasefast, + mastercontrollerdecrease, + mastercontrollerdecreasefast, + secondcontrollerincrease, + secondcontrollerincreasefast, + secondcontrollerdecrease, + secondcontrollerdecreasefast, + independentbrakeincrease, + independentbrakeincreasefast, + independentbrakedecrease, + independentbrakedecreasefast, + independentbrakebailoff, + trainbrakeincrease, + trainbrakedecrease, + trainbrakecharging, + trainbrakerelease, + trainbrakefirstservice, + trainbrakeservice, + trainbrakefullservice, + trainbrakeemergency, +/* +const int k_AntiSlipping = 21; +const int k_Sand = 22; +const int k_Main = 23; +*/ + reverserincrease, + reverserdecrease, +/* +const int k_Fuse = 26; +const int k_Compressor = 27; +const int k_Converter = 28; +const int k_MaxCurrent = 29; +const int k_CurrentAutoRelay = 30; +const int k_BrakeProfile = 31; +const int k_Czuwak = 32; +const int k_Horn = 33; +const int k_Horn2 = 34; +const int k_FailedEngineCutOff = 35; +*/ + viewturn, + movevector, + moveleft, + moveright, + moveforward, + moveback, + moveup, + movedown, + moveleftfast, + moverightfast, + moveforwardfast, + movebackfast, + moveupfast, + movedownfast +/* + moveleftfastest, + moverightfastest, + moveforwardfastest, + movebackfastest, + moveupfastest, + movedownfastest +*/ +/* +const int k_CabForward = 42; +const int k_CabBackward = 43; +const int k_Couple = 44; +const int k_DeCouple = 45; +const int k_ProgramQuit = 46; +// const int k_ProgramPause= 47; +const int k_ProgramHelp = 48; +const int k_OpenLeft = 49; +const int k_OpenRight = 50; +const int k_CloseLeft = 51; +const int k_CloseRight = 52; +const int k_DepartureSignal = 53; +const int k_PantFrontUp = 54; +const int k_PantRearUp = 55; +const int k_PantFrontDown = 56; +const int k_PantRearDown = 57; +const int k_Heating = 58; +// const int k_FreeFlyMode= 59; +const int k_LeftSign = 60; +const int k_UpperSign = 61; +const int k_RightSign = 62; +const int k_SmallCompressor = 63; +const int k_StLinOff = 64; +const int k_CurrentNext = 65; +const int k_Univ1 = 66; +const int k_Univ2 = 67; +const int k_Univ3 = 68; +const int k_Univ4 = 69; +const int k_EndSign = 70; +const int k_Active = 71; +const int k_Battery = 72; +const int k_WalkMode = 73; +int const k_DimHeadlights = 74; +*/ + +}; + +enum class command_target { + + userinterface, + simulation, +/* + // NOTE: there's no need for consist- and unit-specific commands at this point, but it's a possibility. + // since command targets are mutually exclusive these don't reduce ranges for individual vehicles etc + consist = 0x4000, + unit = 0x8000, +*/ + // values are combined with object id. 0xffff objects of each type should be quite enough ("for everyone") + vehicle = 0x10000, + signal = 0x20000, + entity = 0x40000 +}; + +struct command_data { + + user_command command; + int action; // press, repeat or release + std::uint64_t param1; + std::uint64_t param2; + double time_delta; +}; + +// command_queues: collects and holds commands from input sources, for processing by their intended recipients +// NOTE: this won't scale well. +// TODO: turn it into a dispatcher and build individual command sequences into the items, where they can be examined without lookups + +class command_queue { + +public: +// methods + // posts specified command for specified recipient + void + push( command_data const &Command, std::size_t const Recipient ); + // retrieves oldest posted command for specified recipient, if any. returns: true on retrieval, false if there's nothing to retrieve + bool + pop( command_data &Command, std::size_t const Recipient ); + +private: +// types + typedef std::queue commanddata_sequence; + typedef std::unordered_map commanddatasequence_map; +// members + commanddatasequence_map m_commands; + +}; + +// NOTE: simulation should be a (light) wrapper rather than namespace so we could potentially instance it, +// but realistically it's not like we're going to run more than one simulation at a time +namespace simulation { + +extern command_queue Commands; + +} + +// command_relay: composite class component, passes specified command to appropriate command stack + +class command_relay { + +public: +// constructors + command_relay(); +// methods + // 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, int const Action, std::uint16_t const Recipient ) const; +private: +// types + typedef std::unordered_map commandtarget_map; +// members + commandtarget_map m_targets; +#ifdef _DEBUG + std::vector m_commandnames; +#endif +}; + +//--------------------------------------------------------------------------- diff --git a/gamepadinput.cpp b/gamepadinput.cpp new file mode 100644 index 00000000..2c1dfa1a --- /dev/null +++ b/gamepadinput.cpp @@ -0,0 +1,352 @@ +/* +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 "gamepadinput.h" +#include "logs.h" +#include "timer.h" +#include "usefull.h" + +glm::vec2 circle_to_square( glm::vec2 const &Point, int const Roundness = 0 ) { + + // Determine the theta angle + auto angle = std::atan2( Point.x, Point.y ) + M_PI; + + glm::vec2 squared; + // Scale according to which wall we're clamping to + // X+ wall + if( angle <= M_PI_4 || angle > 7 * M_PI_4 ) + squared = Point * (float)( 1.0 / std::cos( angle ) ); + // Y+ wall + else if( angle > M_PI_4 && angle <= 3 * M_PI_4 ) + squared = Point * (float)( 1.0 / std::sin( angle ) ); + // X- wall + else if( angle > 3 * M_PI_4 && angle <= 5 * M_PI_4 ) + squared = Point * (float)( -1.0 / std::cos( angle ) ); + // Y- wall + else if( angle > 5 * M_PI_4 && angle <= 7 * M_PI_4 ) + squared = Point * (float)( -1.0 / std::sin( angle ) ); + + // Early-out for a perfect square output + if( Roundness == 0 ) + return squared; + + // Find the inner-roundness scaling factor and LERP + auto const length = glm::length( Point ); + auto const factor = std::pow( length, Roundness ); + return interpolate( Point, squared, factor ); +} + +gamepad_input::gamepad_input() { + + m_modecommands = { + + { user_command::mastercontrollerincrease, user_command::mastercontrollerdecrease }, + { user_command::trainbrakedecrease, user_command::trainbrakeincrease }, + { user_command::secondcontrollerincrease, user_command::secondcontrollerdecrease }, + { user_command::independentbrakedecrease, user_command::independentbrakeincrease } + }; +} + +bool +gamepad_input::init() { + + // NOTE: we're only checking for joystick_1 and rely for it to stay connected throughout. + // not exactly flexible, but for quick hack it'll do + auto const name = glfwGetJoystickName( GLFW_JOYSTICK_1 ); + if( name != nullptr ) { + WriteLog( "Connected gamepad: " + std::string( name ) ); + m_deviceid = GLFW_JOYSTICK_1; + } + else { + // no joystick, + WriteLog( "No gamepad detected" ); + m_axes.clear(); + m_buttons.clear(); + return false; + } + + int count; + + glfwGetJoystickAxes( m_deviceid, &count ); + m_axes.resize( count ); + + glfwGetJoystickButtons( m_deviceid, &count ); + m_buttons.resize( count ); + + return true; +} + +// checks state of the controls and sends issued commands +void +gamepad_input::poll() { + + int count; std::size_t idx = 0; + // poll button state + auto const buttons = glfwGetJoystickButtons( m_deviceid, &count ); + if( count ) { // safety check in case joystick gets pulled out + for( auto &button : m_buttons ) { + + if( button != buttons[ idx ] ) { + // button pressed or released, both are important + on_button( + static_cast( idx ), + ( buttons[ idx ] == 1 ? + GLFW_PRESS : + GLFW_RELEASE ) ); + } + else { + // otherwise we only pass info about button being held down + if( button == 1 ) { + + on_button( + static_cast( idx ), + GLFW_REPEAT ); + } + } + button = buttons[ idx ]; + ++idx; + } + } + + if( m_deviceid == -1 ) { + // if there's no gamepad we can skip the rest + return; + } + // poll axes state + idx = 0; + glm::vec2 leftstick, rightstick, triggers; + auto const axes = glfwGetJoystickAxes( m_deviceid, &count ); + if( count ) { + // safety check in case joystick gets pulled out + if( count >= 2 ) { + leftstick = glm::vec2( + ( std::abs( axes[ gamepad_axes::leftstick_x ] ) > m_deadzone ? + axes[ gamepad_axes::leftstick_x ] : + 0.0f ), + ( std::abs( axes[ gamepad_axes::leftstick_y ] ) > m_deadzone ? + axes[ gamepad_axes::leftstick_y ] : + 0.0f ) ); + } + if( count >= 4 ) { + rightstick = glm::vec2( + ( std::abs( axes[ gamepad_axes::rightstick_x ] ) > m_deadzone ? + axes[ gamepad_axes::rightstick_x ] : + 0.0f ), + ( std::abs( axes[ gamepad_axes::rightstick_y ] ) > m_deadzone ? + axes[ gamepad_axes::rightstick_y ] : + 0.0f ) ); + } + if( count >= 6 ) { + triggers = glm::vec2( + ( axes[ gamepad_axes::lefttrigger ] > m_deadzone ? + axes[ gamepad_axes::lefttrigger ] : + 0.0f ), + ( axes[ gamepad_axes::righttrigger ] > m_deadzone ? + axes[ gamepad_axes::righttrigger ] : + 0.0f ) ); + } + } + process_axes( leftstick, rightstick, triggers ); +} + +void +gamepad_input::on_button( gamepad_button const Button, int const Action ) { + + switch( Button ) { + // NOTE: this is rigid coupling, down the road we should support more flexible binding of functions with buttons + case gamepad_button::a: + case gamepad_button::b: + case gamepad_button::x: + case gamepad_button::y: { + + if( Action == GLFW_RELEASE ) { + // if the button was released the stick controls movement + m_mode = control_mode::entity; + // zero the stick and the accumulator so the input won't bleed between modes + m_leftstick = glm::vec2(); + m_modeaccumulator = 0.0f; + } + else { + // otherwise set control mode to match pressed button + m_mode = static_cast( Button ); + } + break; + } + default: { + break; + } + } +} + +void +gamepad_input::process_axes( glm::vec2 Leftstick, glm::vec2 const &Rightstick, glm::vec2 const &Triggers ) { + + // left stick, look around + if( ( Rightstick.x != 0.0f ) || ( Rightstick.y != 0.0f ) ) { + // TODO: make toggles for the axis flip + auto const deltatime = Timer::GetDeltaRenderTime() * 60.0; + double const turnx = Rightstick.x * 10.0 * deltatime; + double const turny = -Rightstick.y * 10.0 * deltatime; + m_relay.post( + user_command::viewturn, + reinterpret_cast( turnx ), + reinterpret_cast( 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 + 0 ); + } + + // right stick, either movement or controls, depending on currently active mode + if( m_mode == control_mode::entity ) { + + 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::movevector, + reinterpret_cast( movex ), + reinterpret_cast( movez ), + GLFW_PRESS, + 0 ); + } +/* + Leftstick = circle_to_square( Leftstick ); + if( Leftstick.y >= 0.0f ) { + // forward + process_axis( + Leftstick.y, m_leftstick.y, + 1.0, + user_command::moveforward, + user_command::moveforwardfast, + 0 ); + } + if( Leftstick.y <= 0.0f ) { + // back + process_axis( + Leftstick.y, m_leftstick.y, + -1.0, + user_command::moveback, + user_command::movebackfast, + 0 ); + } + if( Leftstick.x >= 0.0f ) { + // right + process_axis( + Leftstick.x, m_leftstick.x, + 1.0, + user_command::moveright, + user_command::moverightfast, + 0 ); + } + if( Leftstick.x <= 0.0f ) { + // left + process_axis( + Leftstick.x, m_leftstick.x, + -1.0, + user_command::moveleft, + user_command::moveleftfast, + 0 ); + } +*/ + } + else { + // vehicle control modes + process_mode( Leftstick.y, 0 ); + } + + m_rightstick = Rightstick; + m_leftstick = Leftstick; + m_triggers = Triggers; +} + +void +gamepad_input::process_axis( float const Value, float const Previousvalue, float const Multiplier, user_command Command, std::uint16_t const Recipient ) { + + process_axis( Value, Previousvalue, Multiplier, Command, Command, Recipient ); +} + +void +gamepad_input::process_axis( float const Value, float const Previousvalue, float const Multiplier, user_command Command1, user_command Command2, std::uint16_t const Recipient ) { + + user_command command{ Command1 }; + if( Value * Multiplier > 0.9 ) { + command = Command2; + } + + if( Value * Multiplier > 0.0f ) { + + m_relay.post( + command, + 0, 0, + GLFW_PRESS, + Recipient + ); + } + else { + // if we had movement before but not now, report this as 'button' release + if( Previousvalue != 0.0f ) { + m_relay.post( + command, // doesn't matter which movement 'mode' we report + 0, 0, + GLFW_RELEASE, + 0 + ); + } + } +} + +void +gamepad_input::process_mode( float const Value, std::uint16_t const Recipient ) { + + // TODO: separate multiplier for each mode, to allow different, customizable sensitivity for each control + auto const deltatime = Timer::GetDeltaTime() * 15.0; + auto const &lookup = m_modecommands.at( static_cast( m_mode ) ); + + if( Value >= 0.0f ) { + if( m_modeaccumulator < 0.0f ) { + // reset accumulator if we're going in the other direction i.e. issuing opposite control + m_modeaccumulator = 0.0f; + } + if( Value > m_deadzone ) { + m_modeaccumulator += Value * deltatime; + while( m_modeaccumulator >= 1.0f ) { + // send commands if the accumulator(s) was filled + m_relay.post( + lookup.first, + 0, 0, + GLFW_PRESS, + Recipient ); + m_modeaccumulator -= 1.0f; + } + } + } + else { + if( m_modeaccumulator > 0.0f ) { + // reset accumulator if we're going in the other direction i.e. issuing opposite control + m_modeaccumulator = 0.0f; + } + if( Value < m_deadzone ) { + m_modeaccumulator += Value * deltatime; + while( m_modeaccumulator <= -1.0f ) { + // send commands if the accumulator(s) was filled + m_relay.post( + lookup.second, + 0, 0, + GLFW_PRESS, + Recipient ); + m_modeaccumulator += 1.0f; + } + } + } +} + +//--------------------------------------------------------------------------- diff --git a/gamepadinput.h b/gamepadinput.h new file mode 100644 index 00000000..21b33cb7 --- /dev/null +++ b/gamepadinput.h @@ -0,0 +1,86 @@ +/* +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 +#include "command.h" + +class gamepad_input { + +public: +// constructors + gamepad_input(); + +// methods + // checks state of the controls and sends issued commands + bool + init(); + void + poll(); + +private: +// types + enum gamepad_button { + a, + b, + x, + y, + left_shoulder, + right_shoulder, + back, + start, + left_sticker, + right_sticker, + dpad_up, + dpad_right, + dpad_down, + dpad_left + }; + enum gamepad_axes { + leftstick_x, + leftstick_y, + rightstick_x, + rightstick_y, + lefttrigger, + righttrigger + }; + enum class control_mode { + entity = -1, + vehicle_mastercontroller, + vehicle_trainbrake, + vehicle_secondarycontroller, + vehicle_independentbrake + }; + typedef std::vector float_sequence; + typedef std::vector char_sequence; + typedef std::vector< std::pair< user_command, user_command > > commandpair_sequence; + +// methods + void on_button( gamepad_button const Button, int const Action ); + void process_axes( glm::vec2 Leftstick, glm::vec2 const &Rightstick, glm::vec2 const &Triggers ); + void process_axis( float const Value, float const Previousvalue, float const Multiplier, user_command Command, std::uint16_t const Recipient ); + void process_axis( float const Value, float const Previousvalue, float const Multiplier, user_command Command1, user_command Command2, /*user_command Command3,*/ std::uint16_t const Recipient ); + void process_mode( float const Value, std::uint16_t const Recipient ); + +// members + command_relay m_relay; + float_sequence m_axes; + char_sequence m_buttons; + int m_deviceid{ -1 }; + control_mode m_mode{ control_mode::entity }; + commandpair_sequence m_modecommands; // sets of commands issued depending on the active control mode + float m_deadzone{ 0.15f }; // TODO: allow to configure this + glm::vec2 m_leftstick; + glm::vec2 m_rightstick; + glm::vec2 m_triggers; + double m_modeaccumulator; // used to throttle command input rate for vehicle controls +}; + +//--------------------------------------------------------------------------- diff --git a/keyboardinput.cpp b/keyboardinput.cpp new file mode 100644 index 00000000..eacbee31 --- /dev/null +++ b/keyboardinput.cpp @@ -0,0 +1,204 @@ +/* +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 "keyboardinput.h" +#include "logs.h" + +void +keyboard_input::recall_bindings() { + + // TODO: implement + + bind(); +} + +bool +keyboard_input::key( int const Key, int const Action ) { + + bool modifier( false ); + + if( ( Key == GLFW_KEY_LEFT_SHIFT ) || ( Key == GLFW_KEY_RIGHT_SHIFT ) ) { + // update internal state, but don't bother passing these + m_shift = + ( Action == GLFW_RELEASE ? + false : + true ); + modifier = true; + } + if( ( Key == GLFW_KEY_LEFT_CONTROL ) || ( Key == GLFW_KEY_RIGHT_CONTROL ) ) { + // update internal state, but don't bother passing these + m_ctrl = + ( Action == GLFW_RELEASE ? + false : + true ); + modifier = true; + } + if( ( Key == GLFW_KEY_LEFT_ALT ) || ( Key == GLFW_KEY_RIGHT_ALT ) ) { + // currently we have no interest in these whatsoever + return false; + } + + // include active modifiers for currently pressed key, except if the key is a modifier itself + auto const key = + Key + | ( modifier ? 0 : ( m_shift ? keymodifier::shift : 0 ) ) + | ( modifier ? 0 : ( m_ctrl ? keymodifier::control : 0 ) ); + + auto const lookup = m_bindings.find( key ); + if( lookup == m_bindings.end() ) { + // no binding for this key + return false; + } + // 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( lookup->second, 0, 0, Action, 0 ); + + return true; +} + +void +keyboard_input::mouse( double Mousex, double Mousey ) { + + m_relay.post( + user_command::viewturn, + reinterpret_cast( Mousex ), + reinterpret_cast( 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 + 0 ); +} + +void +keyboard_input::default_bindings() { + + m_commands = { + + { "mastercontrollerincrease", command_target::vehicle, GLFW_KEY_KP_ADD }, + { "mastercontrollerincreasefast", command_target::vehicle, GLFW_KEY_KP_ADD | keymodifier::shift }, + { "mastercontrollerdecrease", command_target::vehicle, GLFW_KEY_KP_SUBTRACT }, + { "mastercontrollerdecreasefast", command_target::vehicle, GLFW_KEY_KP_SUBTRACT | keymodifier::shift }, + { "secondcontrollerincrease", command_target::vehicle, GLFW_KEY_KP_DIVIDE }, + { "secondcontrollerincreasefast", command_target::vehicle, GLFW_KEY_KP_DIVIDE | keymodifier::shift }, + { "secondcontrollerdecrease", command_target::vehicle, GLFW_KEY_KP_MULTIPLY }, + { "secondcontrollerdecreasefast", command_target::vehicle, GLFW_KEY_KP_MULTIPLY | keymodifier::shift }, + { "independentbrakeincrease", command_target::vehicle, GLFW_KEY_KP_1 }, + { "independentbrakeincreasefast", command_target::vehicle, GLFW_KEY_KP_1 | keymodifier::shift }, + { "independentbrakedecrease", command_target::vehicle, GLFW_KEY_KP_7 }, + { "independentbrakedecreasefast", command_target::vehicle, GLFW_KEY_KP_7 | keymodifier::shift }, + { "independentbrakebailoff", command_target::vehicle, GLFW_KEY_KP_4 }, + { "trainbrakeincrease", command_target::vehicle, GLFW_KEY_KP_3 }, + { "trainbrakedecrease", command_target::vehicle, GLFW_KEY_KP_9 }, + { "trainbrakecharging", command_target::vehicle, GLFW_KEY_KP_DECIMAL }, + { "trainbrakerelease", command_target::vehicle, GLFW_KEY_KP_6 }, + { "trainbrakefirstservice", command_target::vehicle, GLFW_KEY_KP_8 }, + { "trainbrakeservice", command_target::vehicle, GLFW_KEY_KP_5 }, + { "trainbrakefullservice", command_target::vehicle, GLFW_KEY_KP_2 }, + { "trainbrakeemergency", command_target::vehicle, GLFW_KEY_KP_0 }, +/* +const int k_AntiSlipping = 21; +const int k_Sand = 22; +const int k_Main = 23; +*/ + { "reverserincrease", command_target::vehicle, GLFW_KEY_D }, + { "reverserdecrease", command_target::vehicle, GLFW_KEY_R }, +/* +const int k_Fuse = 26; +const int k_Compressor = 27; +const int k_Converter = 28; +const int k_MaxCurrent = 29; +const int k_CurrentAutoRelay = 30; +const int k_BrakeProfile = 31; +const int k_Czuwak = 32; +const int k_Horn = 33; +const int k_Horn2 = 34; +const int k_FailedEngineCutOff = 35; +*/ + { "viewturn", command_target::entity, -1 }, + { "movevector", command_target::entity, -1 }, + { "moveleft", command_target::entity, GLFW_KEY_LEFT }, + { "moveright", command_target::entity, GLFW_KEY_RIGHT }, + { "moveforward", command_target::entity, GLFW_KEY_UP }, + { "moveback", command_target::entity, GLFW_KEY_DOWN }, + { "moveup", command_target::entity, GLFW_KEY_PAGE_UP }, + { "movedown", command_target::entity, GLFW_KEY_PAGE_DOWN }, + { "moveleftfast", command_target::entity, GLFW_KEY_LEFT | keymodifier::shift }, + { "moverightfast", command_target::entity, GLFW_KEY_RIGHT | keymodifier::shift }, + { "moveforwardfast", command_target::entity, GLFW_KEY_UP | keymodifier::shift }, + { "movebackfast", command_target::entity, GLFW_KEY_DOWN | keymodifier::shift }, + { "moveupfast", command_target::entity, GLFW_KEY_PAGE_UP | keymodifier::shift }, + { "movedownfast", command_target::entity, GLFW_KEY_PAGE_DOWN | keymodifier::shift } +/* + { "moveleftfastest", command_target::entity, GLFW_KEY_LEFT | keymodifier::control }, + { "moverightfastest", command_target::entity, GLFW_KEY_RIGHT | keymodifier::control }, + { "moveforwardfastest", command_target::entity, GLFW_KEY_UP | keymodifier::control }, + { "movebackfastest", command_target::entity, GLFW_KEY_DOWN | keymodifier::control }, + { "moveupfastest", command_target::entity, GLFW_KEY_PAGE_UP | keymodifier::control }, + { "movedownfastest", command_target::entity, GLFW_KEY_PAGE_DOWN | keymodifier::control } +*/ +/* +const int k_CabForward = 42; +const int k_CabBackward = 43; +const int k_Couple = 44; +const int k_DeCouple = 45; +const int k_ProgramQuit = 46; +// const int k_ProgramPause= 47; +const int k_ProgramHelp = 48; +const int k_OpenLeft = 49; +const int k_OpenRight = 50; +const int k_CloseLeft = 51; +const int k_CloseRight = 52; +const int k_DepartureSignal = 53; +const int k_PantFrontUp = 54; +const int k_PantRearUp = 55; +const int k_PantFrontDown = 56; +const int k_PantRearDown = 57; +const int k_Heating = 58; +// const int k_FreeFlyMode= 59; +const int k_LeftSign = 60; +const int k_UpperSign = 61; +const int k_RightSign = 62; +const int k_SmallCompressor = 63; +const int k_StLinOff = 64; +const int k_CurrentNext = 65; +const int k_Univ1 = 66; +const int k_Univ2 = 67; +const int k_Univ3 = 68; +const int k_Univ4 = 69; +const int k_EndSign = 70; +const int k_Active = 71; +const int k_Battery = 72; +const int k_WalkMode = 73; +int const k_DimHeadlights = 74; +*/ + }; + + bind(); +} + +void +keyboard_input::bind() { + + m_bindings.clear(); + + int commandcode{ 0 }; + for( auto const &command : m_commands ) { + + if( command.binding != -1 ) { + m_bindings.emplace( + command.binding, + static_cast( commandcode ) ); + } + ++commandcode; + } +} + +//--------------------------------------------------------------------------- diff --git a/keyboardinput.h b/keyboardinput.h new file mode 100644 index 00000000..c8e2fb43 --- /dev/null +++ b/keyboardinput.h @@ -0,0 +1,61 @@ +/* +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 +#include "command.h" + +class keyboard_input { + +public: +// constructors + keyboard_input() { default_bindings(); } + +// methods + void + recall_bindings(); + bool + key( int const Key, int const Action ); + void + mouse( double const Mousex, double const Mousey ); + +private: +// types + enum keymodifier : int { + + shift = 0x10000, + control = 0x20000 + }; + + struct command_setup { + + std::string name; + command_target target; + int binding; + }; + + typedef std::vector commandsetup_sequence; + typedef std::unordered_map usercommand_map; + +// methods + void + default_bindings(); + void + bind(); + +// members + commandsetup_sequence m_commands; + usercommand_map m_bindings; + command_relay m_relay; + bool m_shift{ false }; + bool m_ctrl{ false }; +}; + +//--------------------------------------------------------------------------- diff --git a/maszyna.vcxproj.filters b/maszyna.vcxproj.filters index 9ccc0f0b..56dc3ce8 100644 --- a/maszyna.vcxproj.filters +++ b/maszyna.vcxproj.filters @@ -16,15 +16,15 @@ {fafd38ab-4c2a-48c8-8e66-ad0d928573b3} - - {2d73d7b2-5252-499c-963a-88fa3cb1af53} - {36684428-8a48-435f-bca4-a24d9bfe2587} - + {cdf75bec-91f7-413c-8b57-9e32cba49148} + + {2d73d7b2-5252-499c-963a-88fa3cb1af53} + @@ -157,7 +157,7 @@ Source Files\mczapkie - Source Files\console + Source Files\input Source Files\mczapkie @@ -169,13 +169,13 @@ Source Files\mczapkie - Source Files\console + Source Files\input Source Files - Source Files\console + Source Files\input Source Files @@ -213,6 +213,15 @@ Source Files + + Source Files + + + Source Files\input + + + Source Files + @@ -291,10 +300,10 @@ Header Files\mczapkie - Header Files\console + Header Files\input - Header Files\console + Header Files\input Header Files @@ -375,7 +384,7 @@ Header Files - Header Files\console + Header Files\input Header Files @@ -413,6 +422,15 @@ Header Files + + Header Files + + + Header Files\input + + + Header Files + diff --git a/moon.cpp b/moon.cpp index f3892960..a7db52e5 100644 --- a/moon.cpp +++ b/moon.cpp @@ -116,7 +116,7 @@ void cMoon::move() { static double radtodeg = 57.295779513; // converts from radians to degrees static double degtorad = 0.0174532925; // converts from degrees to radians - SYSTEMTIME localtime = Simulation::Time.data(); // time for the calculation + SYSTEMTIME localtime = simulation::Time.data(); // time for the calculation if( m_observer.hour >= 0 ) { localtime.wHour = m_observer.hour; } if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; } @@ -284,7 +284,7 @@ void cMoon::irradiance() { static double radtodeg = 57.295779513; // converts from radians to degrees static double degtorad = 0.0174532925; // converts from degrees to radians - m_body.dayang = ( Simulation::Time.year_day() - 1 ) * 360.0 / 365.0; + m_body.dayang = ( simulation::Time.year_day() - 1 ) * 360.0 / 365.0; double sd = sin( degtorad * m_body.dayang ); // sine of the day angle double cd = cos( degtorad * m_body.dayang ); // cosine of the day angle or delination m_body.erv = 1.000110 + 0.034221*cd + 0.001280*sd; @@ -310,7 +310,7 @@ void cMoon::phase() { // calculate moon's age in days from new moon - float ip = normalize( ( Simulation::Time.julian_day() - 2451550.1f ) / 29.530588853f ); + float ip = normalize( ( simulation::Time.julian_day() - 2451550.1f ) / 29.530588853f ); m_phase = ip * 29.53f; } diff --git a/sun.cpp b/sun.cpp index 258c4b9c..879709cb 100644 --- a/sun.cpp +++ b/sun.cpp @@ -115,7 +115,7 @@ void cSun::move() { static double radtodeg = 57.295779513; // converts from radians to degrees static double degtorad = 0.0174532925; // converts from degrees to radians - SYSTEMTIME localtime = Simulation::Time.data(); // time for the calculation + SYSTEMTIME localtime = simulation::Time.data(); // time for the calculation if( m_observer.hour >= 0 ) { localtime.wHour = m_observer.hour; } if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; } @@ -258,9 +258,9 @@ void cSun::irradiance() { static double degrad = 57.295779513; // converts from radians to degrees static double raddeg = 0.0174532925; // converts from degrees to radians - auto const &localtime = Simulation::Time.data(); // time for the calculation + auto const &localtime = simulation::Time.data(); // time for the calculation - m_body.dayang = ( Simulation::Time.year_day() - 1 ) * 360.0 / 365.0; + m_body.dayang = ( simulation::Time.year_day() - 1 ) * 360.0 / 365.0; double sd = sin( raddeg * m_body.dayang ); // sine of the day angle double cd = cos( raddeg * m_body.dayang ); // cosine of the day angle or delination m_body.erv = 1.000110 + 0.034221*cd + 0.001280*sd;