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

control messaging system, keyboard and gamepad inputs

This commit is contained in:
tmj-fstate
2017-04-07 00:36:07 +02:00
parent 886f0dad0f
commit e6f488ed6f
20 changed files with 2237 additions and 151 deletions

View File

@@ -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<double const &>( Command.param1 ) * 0.005 * Global::fMouseXScale / Global::ZoomFactor,
reinterpret_cast<double const &>( 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<double const &>( 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<double const &>( 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( 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<std::size_t>( 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 += a;
Velocity.y = clamp( Velocity.y + a * 10.0 * deltatime, -a, a );
if( Console::Pressed( Global::Keys[ k_MechDown ] ) )
Velocity.y -= a;
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;
Velocity.x = clamp( Velocity.x + a * 10.0 * deltatime, -a, a );
if( Console::Pressed( Global::Keys[ k_MechLeft ] ) )
Velocity.x -= a;
Velocity.x = clamp( Velocity.x - a * 10.0 * deltatime, -a, a );
if( Console::Pressed( Global::Keys[ k_MechForward ] ) )
Velocity.z -= a;
Velocity.z = clamp( Velocity.z - a * 10.0 * deltatime, -a, 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;
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: zeby nie hustalo przy malym FPS:
// Velocity= (Velocity+OldVelocity)/2;
// matrix4x4 mat;
// 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 = 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;
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()

View File

@@ -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 );

View File

@@ -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();

View File

@@ -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
@@ -355,6 +372,7 @@ int main(int argc, char *argv[])
&& GfxRenderer.Render())
{
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;
}

View File

@@ -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)
{

View File

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

View File

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

496
Train.cpp
View File

@@ -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))
{
@@ -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,6 +1551,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) ||
}
else // McZapkie-240302 - klawisze bez shifta
{
#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->ScndCtrlPos<MoverParameters->ScndCtrlPosNo)
// 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;
}
@@ -1222,7 +1597,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) ||
// 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,6 +1711,8 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) ||
else keybrakecount+=1;
*/
}
#endif
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
else if( cKey == Global::Keys[ k_EmergencyBrake ] )
{
// while (mvOccupied->IncBrakeLevel());
@@ -1350,8 +1733,10 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) ||
// mvOccupied->IncBrakeLevel());
mvOccupied->BrakeLevelSet(mvOccupied->BrakeCtrlPosNo - 1);
}
#endif
else if (cKey == Global::Keys[k_Brake2])
{
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
if( ( isEztOer ) && ( ( mvOccupied->BrakeCtrlPos == 1 ) || ( mvOccupied->BrakeCtrlPos == -1 ) ) )
{
dsbPneumaticSwitch->SetVolume(-10);
@@ -1363,12 +1748,14 @@ 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?
}
#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,6 +2030,7 @@ if ((mvControlled->PantFrontVolt) || (mvControlled->PantRearVolt) ||
}
}
//-----------
#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<std::size_t>( 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;
}
}

20
Train.h
View File

@@ -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 <string>
#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 <string>
#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

View File

@@ -39,7 +39,7 @@ std::shared_ptr<ui_panel> UIHeader = std::make_shared<ui_panel>( 20, 20 ); // he
std::shared_ptr<ui_panel> UITable = std::make_shared<ui_panel>( 20, 100 ); // schedule or scan table
std::shared_ptr<ui_panel> UITranscripts = std::make_shared<ui_panel>( 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<size_t>(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

View File

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

300
command.cpp Normal file
View File

@@ -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<std::size_t>( lookup->second ) | Recipient );
#ifdef _DEBUG
if( Action != GLFW_RELEASE ) {
// key was pressed or is still held
auto const &commandname = m_commandnames.at( static_cast<std::size_t>( 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<std::size_t>( Command ) ) );
}
*/
#endif
}
//---------------------------------------------------------------------------

196
command.h Normal file
View File

@@ -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 <unordered_map>
#include <queue>
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<command_data> commanddata_sequence;
typedef std::unordered_map<std::size_t, commanddata_sequence> 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<user_command, command_target> commandtarget_map;
// members
commandtarget_map m_targets;
#ifdef _DEBUG
std::vector<std::string> m_commandnames;
#endif
};
//---------------------------------------------------------------------------

352
gamepadinput.cpp Normal file
View File

@@ -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<gamepad_button>( 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<gamepad_button>( 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<control_mode>( 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<std::uint64_t const &>( turnx ),
reinterpret_cast<std::uint64_t const &>( 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<double>( Leftstick.x );
double const movez = static_cast<double>( Leftstick.y );
m_relay.post(
user_command::movevector,
reinterpret_cast<std::uint64_t const &>( movex ),
reinterpret_cast<std::uint64_t const &>( 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<size_t>( 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;
}
}
}
}
//---------------------------------------------------------------------------

86
gamepadinput.h Normal file
View File

@@ -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 <vector>
#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> float_sequence;
typedef std::vector<char> 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
};
//---------------------------------------------------------------------------

204
keyboardinput.cpp Normal file
View File

@@ -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<std::uint64_t const &>( Mousex ),
reinterpret_cast<std::uint64_t const &>( 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<user_command>( commandcode ) );
}
++commandcode;
}
}
//---------------------------------------------------------------------------

61
keyboardinput.h Normal file
View File

@@ -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 <unordered_map>
#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<command_setup> commandsetup_sequence;
typedef std::unordered_map<int, user_command> 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 };
};
//---------------------------------------------------------------------------

View File

@@ -16,15 +16,15 @@
<Filter Include="Source Files\mczapkie">
<UniqueIdentifier>{fafd38ab-4c2a-48c8-8e66-ad0d928573b3}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\console">
<UniqueIdentifier>{2d73d7b2-5252-499c-963a-88fa3cb1af53}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\mczapkie">
<UniqueIdentifier>{36684428-8a48-435f-bca4-a24d9bfe2587}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\console">
<Filter Include="Header Files\input">
<UniqueIdentifier>{cdf75bec-91f7-413c-8b57-9e32cba49148}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\input">
<UniqueIdentifier>{2d73d7b2-5252-499c-963a-88fa3cb1af53}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AdvSound.cpp">
@@ -157,7 +157,7 @@
<Filter>Source Files\mczapkie</Filter>
</ClCompile>
<ClCompile Include="console\LPT.cpp">
<Filter>Source Files\console</Filter>
<Filter>Source Files\input</Filter>
</ClCompile>
<ClCompile Include="mczapkie\mctools.cpp">
<Filter>Source Files\mczapkie</Filter>
@@ -169,13 +169,13 @@
<Filter>Source Files\mczapkie</Filter>
</ClCompile>
<ClCompile Include="console\PoKeys55.cpp">
<Filter>Source Files\console</Filter>
<Filter>Source Files\input</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Console\MWD.cpp">
<Filter>Source Files\console</Filter>
<Filter>Source Files\input</Filter>
</ClCompile>
<ClCompile Include="Names.cpp">
<Filter>Source Files</Filter>
@@ -213,6 +213,15 @@
<ClCompile Include="moon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="command.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="keyboardinput.cpp">
<Filter>Source Files\input</Filter>
</ClCompile>
<ClCompile Include="gamepadinput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Globals.h">
@@ -291,10 +300,10 @@
<Filter>Header Files\mczapkie</Filter>
</ClInclude>
<ClInclude Include="Console\PoKeys55.h">
<Filter>Header Files\console</Filter>
<Filter>Header Files\input</Filter>
</ClInclude>
<ClInclude Include="Console\LPT.h">
<Filter>Header Files\console</Filter>
<Filter>Header Files\input</Filter>
</ClInclude>
<ClInclude Include="RealSound.h">
<Filter>Header Files</Filter>
@@ -375,7 +384,7 @@
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Console\MWD.h">
<Filter>Header Files\console</Filter>
<Filter>Header Files\input</Filter>
</ClInclude>
<ClInclude Include="sun.h">
<Filter>Header Files</Filter>
@@ -413,6 +422,15 @@
<ClInclude Include="moon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="command.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="keyboardinput.h">
<Filter>Header Files\input</Filter>
</ClInclude>
<ClInclude Include="gamepadinput.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="maszyna.rc">

View File

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

View File

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