mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
refactoring: basic application code wrapper
This commit is contained in:
@@ -18,6 +18,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "renderer.h"
|
||||
#include "MdlMngr.h"
|
||||
#include "simulation.h"
|
||||
#include "simulationtime.h"
|
||||
#include "Globals.h"
|
||||
#include "Timer.h"
|
||||
#include "Logs.h"
|
||||
|
||||
@@ -47,7 +47,7 @@ class TEvent;
|
||||
|
||||
class TAnimContainer
|
||||
{ // opakowanie submodelu, określające animację egzemplarza - obsługiwane jako lista
|
||||
friend class TAnimModel;
|
||||
friend TAnimModel;
|
||||
|
||||
private:
|
||||
Math3D::vector3 vRotateAngles; // dla obrotów Eulera
|
||||
@@ -124,8 +124,8 @@ class TAnimAdvanced
|
||||
// opakowanie modelu, określające stan egzemplarza
|
||||
class TAnimModel : public scene::basic_node {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend class ui_layer;
|
||||
friend opengl_renderer;
|
||||
friend ui_layer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
|
||||
@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
//---------------------------------------------------------------------------
|
||||
// Ra: zestaw klas do robienia wskaźników, aby uporządkować nagłówki
|
||||
//---------------------------------------------------------------------------
|
||||
class opengl_renderer;
|
||||
class TTrack; // odcinek trajektorii
|
||||
class TEvent;
|
||||
class TTrain; // pojazd sterowany
|
||||
@@ -29,8 +30,9 @@ class TTraction; // drut
|
||||
class TTractionPowerSource; // zasilanie drutów
|
||||
class TWorld;
|
||||
class TCamera;
|
||||
class simulation_time;
|
||||
class scenario_time;
|
||||
class TMoverParameters;
|
||||
class ui_layer;
|
||||
|
||||
namespace scene {
|
||||
struct node_data;
|
||||
|
||||
@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "stdafx.h"
|
||||
#include "Console.h"
|
||||
#include "Globals.h"
|
||||
#include "application.h"
|
||||
#include "LPT.h"
|
||||
#include "Logs.h"
|
||||
#include "PoKeys55.h"
|
||||
@@ -247,7 +248,7 @@ void Console::BitsUpdate(int mask)
|
||||
|
||||
bool Console::Pressed(int x)
|
||||
{ // na razie tak - czyta się tylko klawiatura
|
||||
if (glfwGetKey(Global.window, x) == GLFW_TRUE)
|
||||
if (glfwGetKey(Application.window(), x) == GLFW_TRUE)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
@@ -22,10 +22,11 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "DynObj.h"
|
||||
#include "Event.h"
|
||||
#include "MemCell.h"
|
||||
#include "World.h"
|
||||
#include "utilities.h"
|
||||
#include "McZapkie/MOVER.h"
|
||||
#include "world.h"
|
||||
#include "simulationtime.h"
|
||||
#include "track.h"
|
||||
#include "station.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#define LOGVELOCITY 0
|
||||
#define LOGORDERS 1
|
||||
|
||||
2
DynObj.h
2
DynObj.h
@@ -157,7 +157,7 @@ struct material_data {
|
||||
|
||||
class TDynamicObject { // klasa pojazdu
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
static bool bDynamicRemove; // moved from ground
|
||||
|
||||
468
EU07.cpp
468
EU07.cpp
@@ -7,8 +7,8 @@ obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
/*
|
||||
MaSzyna EU07 locomotive simulator
|
||||
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
|
||||
MaSzyna EU07 locomotive simulator
|
||||
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
|
||||
*/
|
||||
/*
|
||||
Authors:
|
||||
@@ -16,475 +16,27 @@ MarcinW, McZapkie, Shaxbee, ABu, nbmx, youBy, Ra, winger, mamut, Q424,
|
||||
Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#ifdef CAN_I_HAS_LIBPNG
|
||||
#include <png.h>
|
||||
#endif
|
||||
|
||||
#include "World.h"
|
||||
#include "simulation.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "Globals.h"
|
||||
#include "timer.h"
|
||||
#include "Logs.h"
|
||||
#include "renderer.h"
|
||||
#include "uilayer.h"
|
||||
#include "audiorenderer.h"
|
||||
#include "keyboardinput.h"
|
||||
#include "mouseinput.h"
|
||||
#include "gamepadinput.h"
|
||||
#include "Console.h"
|
||||
#include "uart.h"
|
||||
#include "PyInt.h"
|
||||
|
||||
#ifdef EU07_BUILD_STATIC
|
||||
#pragma comment( lib, "glfw3.lib" )
|
||||
#pragma comment( lib, "glew32s.lib" )
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#pragma comment( lib, "glfw3dll.lib" )
|
||||
#else
|
||||
#pragma comment( lib, "glfw3.lib" )
|
||||
#endif
|
||||
#pragma comment( lib, "glew32.lib" )
|
||||
#endif // build_static
|
||||
#pragma comment( lib, "opengl32.lib" )
|
||||
#pragma comment( lib, "glu32.lib" )
|
||||
#pragma comment( lib, "openal32.lib")
|
||||
#pragma comment( lib, "setupapi.lib" )
|
||||
#pragma comment( lib, "python27.lib" )
|
||||
#pragma comment( lib, "libserialport-0.lib" )
|
||||
#pragma comment (lib, "dbghelp.lib")
|
||||
#pragma comment (lib, "version.lib")
|
||||
#ifdef CAN_I_HAS_LIBPNG
|
||||
#pragma comment (lib, "libpng16.lib")
|
||||
#endif
|
||||
#include "application.h"
|
||||
#include "logs.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
|
||||
#endif
|
||||
|
||||
TWorld World;
|
||||
int main( int argc, char *argv[] ) {
|
||||
|
||||
namespace input {
|
||||
|
||||
keyboard_input Keyboard;
|
||||
mouse_input Mouse;
|
||||
gamepad_input Gamepad;
|
||||
glm::dvec2 mouse_pickmodepos; // stores last mouse position in control picking mode
|
||||
std::unique_ptr<uart_input> uart;
|
||||
user_command command; // currently issued control command, if any
|
||||
|
||||
}
|
||||
|
||||
#ifdef CAN_I_HAS_LIBPNG
|
||||
void screenshot_save_thread( char *img )
|
||||
{
|
||||
png_image png;
|
||||
memset(&png, 0, sizeof(png_image));
|
||||
png.version = PNG_IMAGE_VERSION;
|
||||
png.width = Global.iWindowWidth;
|
||||
png.height = Global.iWindowHeight;
|
||||
png.format = PNG_FORMAT_RGB;
|
||||
|
||||
char datetime[64];
|
||||
time_t timer;
|
||||
struct tm* tm_info;
|
||||
time(&timer);
|
||||
tm_info = localtime(&timer);
|
||||
strftime(datetime, 64, "%Y-%m-%d_%H-%M-%S", tm_info);
|
||||
|
||||
uint64_t perf;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&perf);
|
||||
|
||||
std::string filename = "screenshots/" + std::string(datetime) +
|
||||
"_" + std::to_string(perf) + ".png";
|
||||
|
||||
if (png_image_write_to_file(&png, filename.c_str(), 0, img, -Global.iWindowWidth * 3, nullptr) == 1)
|
||||
WriteLog("saved " + filename + ".");
|
||||
else
|
||||
WriteLog("failed to save screenshot.");
|
||||
|
||||
delete[] img;
|
||||
}
|
||||
|
||||
void make_screenshot()
|
||||
{
|
||||
char *img = new char[Global.iWindowWidth * Global.iWindowHeight * 3];
|
||||
glReadPixels(0, 0, Global.iWindowWidth, Global.iWindowHeight, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)img);
|
||||
|
||||
std::thread t(screenshot_save_thread, img);
|
||||
t.detach();
|
||||
}
|
||||
#endif
|
||||
|
||||
void window_resize_callback(GLFWwindow *window, int w, int h)
|
||||
{
|
||||
// NOTE: we have two variables which basically do the same thing as we don't have dynamic fullscreen toggle
|
||||
// TBD, TODO: merge them?
|
||||
Global.iWindowWidth = w;
|
||||
Global.iWindowHeight = h;
|
||||
Global.fDistanceFactor = std::max( 0.5f, h / 768.0f ); // not sure if this is really something we want to use
|
||||
glViewport(0, 0, w, h);
|
||||
}
|
||||
|
||||
void cursor_pos_callback(GLFWwindow *window, double x, double y)
|
||||
{
|
||||
if( false == Global.ControlPicking ) {
|
||||
glfwSetCursorPos( window, 0, 0 );
|
||||
}
|
||||
|
||||
// give the potential event recipient a shot at it, in the virtual z order
|
||||
if( true == scene::Editor.on_mouse_move( x, y ) ) { return; }
|
||||
input::Mouse.move( x, y );
|
||||
}
|
||||
|
||||
void mouse_button_callback( GLFWwindow* window, int button, int action, int mods ) {
|
||||
|
||||
if( ( button != GLFW_MOUSE_BUTTON_LEFT )
|
||||
&& ( button != GLFW_MOUSE_BUTTON_RIGHT ) ) {
|
||||
// we don't care about other mouse buttons at the moment
|
||||
return;
|
||||
}
|
||||
// give the potential event recipient a shot at it, in the virtual z order
|
||||
if( true == scene::Editor.on_mouse_button( button, action ) ) { return; }
|
||||
input::Mouse.button( button, action );
|
||||
}
|
||||
|
||||
void key_callback( GLFWwindow *window, int key, int scancode, int action, int mods ) {
|
||||
|
||||
Global.shiftState = ( mods & GLFW_MOD_SHIFT ) ? true : false;
|
||||
Global.ctrlState = ( mods & GLFW_MOD_CONTROL ) ? true : false;
|
||||
Global.altState = ( mods & GLFW_MOD_ALT ) ? true : false;
|
||||
|
||||
// give the ui first shot at the input processing...
|
||||
if( true == UILayer.on_key( key, action ) ) { return; }
|
||||
if( true == scene::Editor.on_key( key, action ) ) { return; }
|
||||
// ...if the input is left untouched, pass it on
|
||||
input::Keyboard.key( key, action );
|
||||
|
||||
if( ( true == Global.InputMouse )
|
||||
&& ( ( key == GLFW_KEY_LEFT_ALT )
|
||||
|| ( key == GLFW_KEY_RIGHT_ALT ) ) ) {
|
||||
// if the alt key was pressed toggle control picking mode and set matching cursor behaviour
|
||||
if( action == GLFW_RELEASE ) {
|
||||
|
||||
if( Global.ControlPicking ) {
|
||||
// switch off
|
||||
glfwGetCursorPos( window, &input::mouse_pickmodepos.x, &input::mouse_pickmodepos.y );
|
||||
UILayer.set_cursor( GLFW_CURSOR_DISABLED );
|
||||
glfwSetCursorPos( window, 0, 0 );
|
||||
}
|
||||
else {
|
||||
// enter picking mode
|
||||
glfwSetCursorPos( window, input::mouse_pickmodepos.x, input::mouse_pickmodepos.y );
|
||||
UILayer.set_cursor( GLFW_CURSOR_NORMAL );
|
||||
}
|
||||
// actually toggle the mode
|
||||
Global.ControlPicking = !Global.ControlPicking;
|
||||
}
|
||||
}
|
||||
|
||||
if( ( key == GLFW_KEY_LEFT_SHIFT )
|
||||
|| ( key == GLFW_KEY_LEFT_CONTROL )
|
||||
|| ( key == GLFW_KEY_LEFT_ALT )
|
||||
|| ( key == GLFW_KEY_RIGHT_SHIFT )
|
||||
|| ( key == GLFW_KEY_RIGHT_CONTROL )
|
||||
|| ( key == GLFW_KEY_RIGHT_ALT ) ) {
|
||||
// don't bother passing these
|
||||
return;
|
||||
}
|
||||
|
||||
if( action == GLFW_PRESS || action == GLFW_REPEAT ) {
|
||||
|
||||
World.OnKeyDown( key );
|
||||
|
||||
#ifdef CAN_I_HAS_LIBPNG
|
||||
switch( key )
|
||||
{
|
||||
case GLFW_KEY_PRINT_SCREEN: {
|
||||
make_screenshot();
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void focus_callback( GLFWwindow *window, int focus )
|
||||
{
|
||||
if( Global.bInactivePause ) // jeśli ma być pauzowanie okna w tle
|
||||
if( focus )
|
||||
Global.iPause &= ~4; // odpauzowanie, gdy jest na pierwszym planie
|
||||
else
|
||||
Global.iPause |= 4; // włączenie pauzy, gdy nieaktywy
|
||||
}
|
||||
|
||||
void scroll_callback( GLFWwindow* window, double xoffset, double yoffset ) {
|
||||
|
||||
if( Global.ctrlState ) {
|
||||
// ctrl + scroll wheel adjusts fov in debug mode
|
||||
Global.FieldOfView = clamp( static_cast<float>(Global.FieldOfView - yoffset * 20.0 / Global.fFpsAverage), 15.0f, 75.0f );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C"
|
||||
{
|
||||
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
|
||||
}
|
||||
|
||||
LONG CALLBACK unhandled_handler(::EXCEPTION_POINTERS* e);
|
||||
LRESULT APIENTRY WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
extern HWND Hwnd;
|
||||
extern WNDPROC BaseWindowProc;
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#if defined(_MSC_VER) && defined (_DEBUG)
|
||||
// memory leaks
|
||||
_CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_LEAK_CHECK_DF );
|
||||
// floating point operation errors
|
||||
auto state = _clearfp();
|
||||
state = _control87( 0, 0 );
|
||||
// this will turn on FPE for #IND and zerodiv
|
||||
state = _control87( state & ~( _EM_ZERODIVIDE | _EM_INVALID ), _MCW_EM );
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
::SetUnhandledExceptionFilter( unhandled_handler );
|
||||
#endif
|
||||
|
||||
if (!glfwInit())
|
||||
return -1;
|
||||
|
||||
#ifdef _WIN32
|
||||
DeleteFile( "log.txt" );
|
||||
DeleteFile( "errors.txt" );
|
||||
_mkdir("logs");
|
||||
#endif
|
||||
Global.LoadIniFile("eu07.ini");
|
||||
|
||||
// hunter-271211: ukrywanie konsoli
|
||||
if( Global.iWriteLogEnabled & 2 )
|
||||
{
|
||||
AllocConsole();
|
||||
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), FOREGROUND_GREEN );
|
||||
}
|
||||
/*
|
||||
std::string executable( argv[ 0 ] ); auto const pathend = executable.rfind( '\\' );
|
||||
Global.ExecutableName =
|
||||
( pathend != std::string::npos ?
|
||||
executable.substr( executable.rfind( '\\' ) + 1 ) :
|
||||
executable );
|
||||
*/
|
||||
// retrieve product version from the file's version data table
|
||||
{
|
||||
auto const fileversionsize = ::GetFileVersionInfoSize( argv[ 0 ], NULL );
|
||||
std::vector<BYTE>fileversiondata; fileversiondata.resize( fileversionsize );
|
||||
if( ::GetFileVersionInfo( argv[ 0 ], 0, fileversionsize, fileversiondata.data() ) ) {
|
||||
|
||||
struct lang_codepage {
|
||||
WORD language;
|
||||
WORD codepage;
|
||||
} *langcodepage;
|
||||
UINT datasize;
|
||||
|
||||
::VerQueryValue(
|
||||
fileversiondata.data(),
|
||||
TEXT( "\\VarFileInfo\\Translation" ),
|
||||
(LPVOID*)&langcodepage,
|
||||
&datasize );
|
||||
|
||||
std::string subblock; subblock.resize( 50 );
|
||||
::StringCchPrintf(
|
||||
&subblock[0], subblock.size(),
|
||||
TEXT( "\\StringFileInfo\\%04x%04x\\ProductVersion" ),
|
||||
langcodepage->language,
|
||||
langcodepage->codepage );
|
||||
|
||||
VOID *stringdata;
|
||||
if( ::VerQueryValue(
|
||||
fileversiondata.data(),
|
||||
subblock.data(),
|
||||
&stringdata,
|
||||
&datasize ) ) {
|
||||
|
||||
Global.asVersion = std::string( reinterpret_cast<char*>(stringdata) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string token(argv[i]);
|
||||
|
||||
if (token == "-e3d") {
|
||||
if (Global.iConvertModels > 0)
|
||||
Global.iConvertModels = -Global.iConvertModels;
|
||||
else
|
||||
Global.iConvertModels = -7; // z optymalizacją, bananami i prawidłowym Opacity
|
||||
}
|
||||
else if (i + 1 < argc && token == "-s")
|
||||
Global.SceneryFile = std::string(argv[++i]);
|
||||
else if (i + 1 < argc && token == "-v")
|
||||
{
|
||||
std::string v(argv[++i]);
|
||||
std::transform(v.begin(), v.end(), v.begin(), ::tolower);
|
||||
Global.asHumanCtrlVehicle = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout
|
||||
<< "usage: " << std::string(argv[0])
|
||||
<< " [-s sceneryfilepath]"
|
||||
<< " [-v vehiclename]"
|
||||
<< " [-e3d]"
|
||||
<< std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// match requested video mode to current to allow for
|
||||
// fullwindow creation when resolution is the same
|
||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||
const GLFWvidmode *vmode = glfwGetVideoMode(monitor);
|
||||
|
||||
glfwWindowHint(GLFW_RED_BITS, vmode->redBits);
|
||||
glfwWindowHint(GLFW_GREEN_BITS, vmode->greenBits);
|
||||
glfwWindowHint(GLFW_BLUE_BITS, vmode->blueBits);
|
||||
glfwWindowHint(GLFW_REFRESH_RATE, vmode->refreshRate);
|
||||
|
||||
glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
|
||||
if( Global.iMultisampling > 0 ) {
|
||||
glfwWindowHint( GLFW_SAMPLES, 1 << Global.iMultisampling );
|
||||
}
|
||||
|
||||
if (Global.bFullScreen)
|
||||
{
|
||||
// match screen dimensions with selected monitor, for 'borderless window' in fullscreen mode
|
||||
Global.iWindowWidth = vmode->width;
|
||||
Global.iWindowHeight = vmode->height;
|
||||
}
|
||||
|
||||
GLFWwindow *window =
|
||||
glfwCreateWindow(
|
||||
Global.iWindowWidth,
|
||||
Global.iWindowHeight,
|
||||
Global.AppName.c_str(),
|
||||
( Global.bFullScreen ?
|
||||
monitor :
|
||||
nullptr),
|
||||
nullptr );
|
||||
|
||||
if (!window)
|
||||
{
|
||||
std::cout << "failed to create window" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(Global.VSync ? 1 : 0); //vsync
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); //capture cursor
|
||||
glfwSetCursorPos(window, 0.0, 0.0);
|
||||
glfwSetFramebufferSizeCallback(window, window_resize_callback);
|
||||
glfwSetCursorPosCallback(window, cursor_pos_callback);
|
||||
glfwSetMouseButtonCallback( window, mouse_button_callback );
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetScrollCallback( window, scroll_callback );
|
||||
glfwSetWindowFocusCallback(window, focus_callback);
|
||||
{
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
window_resize_callback(window, width, height);
|
||||
}
|
||||
|
||||
if (glewInit() != GLEW_OK)
|
||||
{
|
||||
std::cout << "failed to init GLEW" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// setup wrapper for base glfw window proc, to handle copydata messages
|
||||
Hwnd = glfwGetWin32Window( window );
|
||||
BaseWindowProc = (WNDPROC)::SetWindowLongPtr( Hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc );
|
||||
// switch off the topmost flag
|
||||
::SetWindowPos( Hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
||||
#endif
|
||||
|
||||
if( ( false == GfxRenderer.Init( window ) )
|
||||
|| ( false == UILayer.init( window ) ) ) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( Global.bSoundEnabled ) {
|
||||
Global.bSoundEnabled &= audio::renderer.init();
|
||||
}
|
||||
|
||||
input::Keyboard.init();
|
||||
input::Mouse.init();
|
||||
input::Gamepad.init();
|
||||
if( true == Global.uart_conf.enable ) {
|
||||
input::uart = std::make_unique<uart_input>();
|
||||
input::uart->init();
|
||||
}
|
||||
|
||||
Global.pWorld = &World; // Ra: wskaźnik potrzebny do usuwania pojazdów
|
||||
try {
|
||||
if( false == World.Init( window ) ) {
|
||||
ErrorLog( "Simulation setup failed" );
|
||||
return -1;
|
||||
auto result { Application.init( argc, argv ) };
|
||||
if( result == 0 ) {
|
||||
result = Application.run();
|
||||
}
|
||||
Application.exit();
|
||||
return result;
|
||||
}
|
||||
catch( std::bad_alloc const &Error ) {
|
||||
|
||||
ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) );
|
||||
return -1;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
Console *pConsole = new Console(); // Ra: nie wiem, czy ma to sens, ale jakoś zainicjowac trzeba
|
||||
#endif
|
||||
if( Global.iConvertModels < 0 ) {
|
||||
Global.iConvertModels = -Global.iConvertModels;
|
||||
World.CreateE3D( szModelPath ); // rekurencyjne przeglądanie katalogów
|
||||
World.CreateE3D( szDynamicPath, true );
|
||||
} // po zrobieniu E3D odpalamy normalnie scenerię, by ją zobaczyć
|
||||
#ifdef _WIN32
|
||||
Console::On(); // włączenie konsoli
|
||||
#endif
|
||||
try {
|
||||
while( ( false == glfwWindowShouldClose( window ) )
|
||||
&& ( true == World.Update() )
|
||||
&& ( true == GfxRenderer.Render() ) ) {
|
||||
glfwPollEvents();
|
||||
input::Keyboard.poll();
|
||||
if( true == Global.InputMouse ) { input::Mouse.poll(); }
|
||||
if( true == Global.InputGamepad ) { input::Gamepad.poll(); }
|
||||
if( input::uart != nullptr ) { input::uart->poll(); }
|
||||
// TODO: wrap current command in object, include other input sources
|
||||
input::command = (
|
||||
input::Mouse.command() != user_command::none ?
|
||||
input::Mouse.command() :
|
||||
input::Keyboard.command() );
|
||||
}
|
||||
}
|
||||
catch( std::bad_alloc const &Error ) {
|
||||
|
||||
ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej)
|
||||
SafeDelete( pConsole );
|
||||
#endif
|
||||
SafeDelete( simulation::Region );
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
|
||||
TPythonInterpreter::killInstance();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Timer.h"
|
||||
#include "parser.h"
|
||||
#include "Console.h"
|
||||
#include "world.h"
|
||||
#include "simulationtime.h"
|
||||
#include "utilities.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -20,7 +20,6 @@ struct global_settings {
|
||||
// members
|
||||
// data items
|
||||
// TODO: take these out of the settings
|
||||
GLFWwindow *window{ nullptr };
|
||||
bool shiftState{ false }; //m7todo: brzydko
|
||||
bool ctrlState{ false };
|
||||
bool altState{ false };
|
||||
|
||||
@@ -20,6 +20,7 @@ Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
|
||||
#include "utilities.h"
|
||||
#include "renderer.h"
|
||||
#include "Timer.h"
|
||||
#include "simulationtime.h"
|
||||
#include "mtable.h"
|
||||
#include "sn_utils.h"
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
10
Model3d.h
10
Model3d.h
@@ -55,10 +55,10 @@ class TSubModel
|
||||
{ // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
|
||||
//m7todo: zrobić normalną serializację
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
|
||||
friend class TDynamicObject; // temporary etc
|
||||
friend class scene::shape_node; // temporary etc
|
||||
friend opengl_renderer;
|
||||
friend TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
|
||||
friend TDynamicObject; // temporary etc
|
||||
friend scene::shape_node; // temporary etc
|
||||
|
||||
public:
|
||||
enum normalization {
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
|
||||
class TModel3d
|
||||
{
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
private:
|
||||
TSubModel *Root; // drzewo submodeli
|
||||
|
||||
4
Track.h
4
Track.h
@@ -126,9 +126,9 @@ private:
|
||||
// trajektoria ruchu - opakowanie
|
||||
class TTrack : public scene::basic_node {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
// NOTE: temporary arrangement
|
||||
friend class ui_layer;
|
||||
friend ui_layer;
|
||||
|
||||
private:
|
||||
TIsolated * pIsolated = nullptr; // obwód izolowany obsługujący zajęcia/zwolnienia grupy torów
|
||||
|
||||
@@ -20,7 +20,7 @@ class TTractionPowerSource;
|
||||
|
||||
class TTraction : public scene::basic_node {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
public: // na razie
|
||||
TTractionPowerSource *psPower[ 2 ] { nullptr, nullptr }; // najbliższe zasilacze z obu kierunków
|
||||
|
||||
@@ -17,7 +17,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "Globals.h"
|
||||
#include "simulation.h"
|
||||
#include "world.h"
|
||||
#include "simulationtime.h"
|
||||
#include "camera.h"
|
||||
#include "Logs.h"
|
||||
#include "MdlMngr.h"
|
||||
|
||||
206
World.cpp
206
World.cpp
@@ -16,7 +16,9 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "World.h"
|
||||
|
||||
#include "Globals.h"
|
||||
#include "application.h"
|
||||
#include "simulation.h"
|
||||
#include "simulationtime.h"
|
||||
#include "Logs.h"
|
||||
#include "MdlMngr.h"
|
||||
#include "renderer.h"
|
||||
@@ -33,188 +35,13 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
namespace simulation {
|
||||
|
||||
simulation_time Time;
|
||||
|
||||
basic_station Station;
|
||||
}
|
||||
TWorld World;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); //m7todo: potrzebne do directsound
|
||||
}
|
||||
|
||||
void
|
||||
simulation_time::init() {
|
||||
|
||||
char monthdaycounts[ 2 ][ 13 ] = {
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
|
||||
::memcpy( m_monthdaycounts, monthdaycounts, sizeof( monthdaycounts ) );
|
||||
|
||||
// potentially adjust scenario clock
|
||||
auto const requestedtime { clamp_circular<int>( m_time.wHour * 60 + m_time.wMinute + Global.ScenarioTimeOffset * 60, 24 * 60 ) };
|
||||
auto const requestedhour { ( requestedtime / 60 ) % 24 };
|
||||
auto const requestedminute { requestedtime % 60 };
|
||||
// cache requested elements, if any
|
||||
::GetLocalTime( &m_time );
|
||||
|
||||
if( Global.fMoveLight > 0.0 ) {
|
||||
// day and month of the year can be overriden by scenario setup
|
||||
daymonth( m_time.wDay, m_time.wMonth, m_time.wYear, static_cast<WORD>( Global.fMoveLight ) );
|
||||
}
|
||||
|
||||
if( requestedhour != -1 ) { m_time.wHour = static_cast<WORD>( clamp( requestedhour, 0, 23 ) ); }
|
||||
if( requestedminute != -1 ) { m_time.wMinute = static_cast<WORD>( clamp( requestedminute, 0, 59 ) ); }
|
||||
// if the time is taken from the local clock leave the seconds intact, otherwise set them to zero
|
||||
if( ( requestedhour != -1 )
|
||||
|| ( requestedminute != 1 ) ) {
|
||||
m_time.wSecond = 0;
|
||||
}
|
||||
|
||||
m_yearday = year_day( m_time.wDay, m_time.wMonth, m_time.wYear );
|
||||
|
||||
// calculate time zone bias
|
||||
// retrieve relevant time zone info from system registry (or fall back on supplied default)
|
||||
// TODO: select timezone matching defined geographic location and/or country
|
||||
struct registry_time_zone_info {
|
||||
long Bias;
|
||||
long StandardBias;
|
||||
long DaylightBias;
|
||||
SYSTEMTIME StandardDate;
|
||||
SYSTEMTIME DaylightDate;
|
||||
} registrytimezoneinfo = { -60, 0, -60, { 0, 10, 0, 5, 3, 0, 0, 0 }, { 0, 3, 0, 5, 2, 0, 0, 0 } };
|
||||
|
||||
#ifdef _WIN32
|
||||
TCHAR timezonekeyname[] { TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\Central European Standard Time" ) };
|
||||
HKEY timezonekey { NULL };
|
||||
DWORD size { sizeof( registrytimezoneinfo ) };
|
||||
if( ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, timezonekeyname, 0, KEY_QUERY_VALUE, &timezonekey ) == ERROR_SUCCESS ) {
|
||||
::RegQueryValueEx( timezonekey, "TZI", NULL, NULL, (BYTE *)®istrytimezoneinfo, &size );
|
||||
}
|
||||
#endif
|
||||
TIME_ZONE_INFORMATION timezoneinfo { 0 };
|
||||
timezoneinfo.Bias = registrytimezoneinfo.Bias;
|
||||
timezoneinfo.DaylightBias = registrytimezoneinfo.DaylightBias;
|
||||
timezoneinfo.DaylightDate = registrytimezoneinfo.DaylightDate;
|
||||
timezoneinfo.StandardBias = registrytimezoneinfo.StandardBias;
|
||||
timezoneinfo.StandardDate = registrytimezoneinfo.StandardDate;
|
||||
|
||||
auto zonebias { timezoneinfo.Bias };
|
||||
if( m_yearday < year_day( timezoneinfo.DaylightDate.wDay, timezoneinfo.DaylightDate.wMonth, m_time.wYear ) ) {
|
||||
zonebias += timezoneinfo.StandardBias;
|
||||
}
|
||||
else if( m_yearday < year_day( timezoneinfo.StandardDate.wDay, timezoneinfo.StandardDate.wMonth, m_time.wYear ) ) {
|
||||
zonebias += timezoneinfo.DaylightBias;
|
||||
}
|
||||
else {
|
||||
zonebias += timezoneinfo.StandardBias;
|
||||
}
|
||||
|
||||
m_timezonebias = ( zonebias / 60.0 );
|
||||
}
|
||||
|
||||
void
|
||||
simulation_time::update( double const Deltatime ) {
|
||||
|
||||
m_milliseconds += ( 1000.0 * Deltatime );
|
||||
while( m_milliseconds >= 1000.0 ) {
|
||||
|
||||
++m_time.wSecond;
|
||||
m_milliseconds -= 1000.0;
|
||||
}
|
||||
m_time.wMilliseconds = std::floor( m_milliseconds );
|
||||
while( m_time.wSecond >= 60 ) {
|
||||
|
||||
++m_time.wMinute;
|
||||
m_time.wSecond -= 60;
|
||||
}
|
||||
while( m_time.wMinute >= 60 ) {
|
||||
|
||||
++m_time.wHour;
|
||||
m_time.wMinute -= 60;
|
||||
}
|
||||
while( m_time.wHour >= 24 ) {
|
||||
|
||||
++m_time.wDay;
|
||||
++m_time.wDayOfWeek;
|
||||
if( m_time.wDayOfWeek >= 7 ) {
|
||||
m_time.wDayOfWeek -= 7;
|
||||
}
|
||||
m_time.wHour -= 24;
|
||||
}
|
||||
int leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 );
|
||||
while( m_time.wDay > m_monthdaycounts[ leap ][ m_time.wMonth ] ) {
|
||||
|
||||
m_time.wDay -= m_monthdaycounts[ leap ][ m_time.wMonth ];
|
||||
++m_time.wMonth;
|
||||
// unlikely but we might've entered a new year
|
||||
if( m_time.wMonth > 12 ) {
|
||||
|
||||
++m_time.wYear;
|
||||
leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 );
|
||||
m_time.wMonth -= 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
simulation_time::year_day( int Day, const int Month, const int Year ) const {
|
||||
|
||||
char const daytab[ 2 ][ 13 ] = {
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
int leap { ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ) };
|
||||
for( int i = 1; i < Month; ++i )
|
||||
Day += daytab[ leap ][ i ];
|
||||
|
||||
return Day;
|
||||
}
|
||||
|
||||
void
|
||||
simulation_time::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ) {
|
||||
|
||||
WORD daytab[ 2 ][ 13 ] = {
|
||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
|
||||
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
|
||||
};
|
||||
|
||||
int leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 );
|
||||
WORD idx = 1;
|
||||
while( ( idx < 13 ) && ( Yearday >= daytab[ leap ][ idx ] ) ) {
|
||||
|
||||
++idx;
|
||||
}
|
||||
Month = idx;
|
||||
Day = Yearday - daytab[ leap ][ idx - 1 ];
|
||||
}
|
||||
|
||||
int
|
||||
simulation_time::julian_day() const {
|
||||
|
||||
int yy = ( m_time.wYear < 0 ? m_time.wYear + 1 : m_time.wYear ) - std::floor( ( 12 - m_time.wMonth ) / 10.f );
|
||||
int mm = m_time.wMonth + 9;
|
||||
if( mm >= 12 ) { mm -= 12; }
|
||||
|
||||
int K1 = std::floor( 365.25 * ( yy + 4712 ) );
|
||||
int K2 = std::floor( 30.6 * mm + 0.5 );
|
||||
|
||||
// for dates in Julian calendar
|
||||
int JD = K1 + K2 + m_time.wDay + 59;
|
||||
// for dates in Gregorian calendar; 2299160 is October 15th, 1582
|
||||
const int gregorianswitchday = 2299160;
|
||||
if( JD > gregorianswitchday ) {
|
||||
|
||||
int K3 = std::floor( std::floor( ( yy * 0.01 ) + 49 ) * 0.75 ) - 38;
|
||||
JD -= K3;
|
||||
}
|
||||
|
||||
return JD;
|
||||
}
|
||||
|
||||
TWorld::TWorld()
|
||||
{
|
||||
Train = NULL;
|
||||
@@ -254,7 +81,6 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
||||
auto timestart = std::chrono::system_clock::now();
|
||||
|
||||
window = Window;
|
||||
Global.window = Window; // do WM_COPYDATA
|
||||
Global.pCamera = &Camera; // Ra: wskaźnik potrzebny do likwidacji drgań
|
||||
|
||||
WriteLog( "\nStarting MaSzyna rail vehicle simulator (release: " + Global.asVersion + ")" );
|
||||
@@ -935,7 +761,6 @@ bool TWorld::Update() {
|
||||
audio::renderer.update( dt );
|
||||
|
||||
GfxRenderer.Update( dt );
|
||||
ResourceSweep();
|
||||
|
||||
m_init = true;
|
||||
|
||||
@@ -1007,12 +832,12 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
// double modelrotate = atan2( -tempangle.x, tempangle.z );
|
||||
|
||||
if( ( true == Global.ctrlState )
|
||||
&& ( ( glfwGetKey( Global.window, GLFW_KEY_LEFT ) == GLFW_TRUE )
|
||||
|| ( glfwGetKey( Global.window, GLFW_KEY_RIGHT ) == GLFW_TRUE ) ) ) {
|
||||
&& ( ( glfwGetKey( Application.window(), GLFW_KEY_LEFT ) == GLFW_TRUE )
|
||||
|| ( glfwGetKey( Application.window(), GLFW_KEY_RIGHT ) == GLFW_TRUE ) ) ) {
|
||||
// jeśli lusterko lewe albo prawe (bez rzucania na razie)
|
||||
Global.CabWindowOpen = true;
|
||||
|
||||
auto const lr { glfwGetKey( Global.window, GLFW_KEY_LEFT ) == GLFW_TRUE };
|
||||
auto const lr { glfwGetKey( Application.window(), GLFW_KEY_LEFT ) == GLFW_TRUE };
|
||||
// Camera.Yaw powinno być wyzerowane, aby po powrocie patrzeć do przodu
|
||||
Camera.Pos = Controlled->GetPosition() + Train->MirrorPosition( lr ); // pozycja lusterka
|
||||
Camera.Yaw = 0; // odchylenie na bok od Camera.LookAt
|
||||
@@ -1079,13 +904,6 @@ void TWorld::Update_Environment() {
|
||||
Environment.update();
|
||||
}
|
||||
|
||||
void TWorld::ResourceSweep()
|
||||
{
|
||||
/*
|
||||
ResourceManager::Sweep( Timer::GetSimulationTime() );
|
||||
*/
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
|
||||
{ // odebranie komunikatu z serwera
|
||||
@@ -1445,11 +1263,11 @@ TWorld::compute_season( int const Yearday ) const {
|
||||
using dayseasonpair = std::pair<int, std::string>;
|
||||
|
||||
std::vector<dayseasonpair> seasonsequence {
|
||||
{ 65, "winter" },
|
||||
{ 158, "spring" },
|
||||
{ 252, "summer" },
|
||||
{ 341, "autumn" },
|
||||
{ 366, "winter" } };
|
||||
{ 65, "winter:" },
|
||||
{ 158, "spring:" },
|
||||
{ 252, "summer:" },
|
||||
{ 341, "autumn:" },
|
||||
{ 366, "winter:" } };
|
||||
auto const lookup =
|
||||
std::lower_bound(
|
||||
std::begin( seasonsequence ), std::end( seasonsequence ),
|
||||
@@ -1457,7 +1275,7 @@ TWorld::compute_season( int const Yearday ) const {
|
||||
[]( dayseasonpair const &Left, const int Right ) {
|
||||
return Left.first < Right; } );
|
||||
|
||||
Global.Season = lookup->second + ":";
|
||||
Global.Season = lookup->second;
|
||||
// season can affect the weather so if it changes, re-calculate weather as well
|
||||
compute_weather();
|
||||
}
|
||||
|
||||
49
World.h
49
World.h
@@ -20,52 +20,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "stars.h"
|
||||
#include "skydome.h"
|
||||
#include "messaging.h"
|
||||
#include "station.h"
|
||||
|
||||
// wrapper for simulation time
|
||||
class simulation_time {
|
||||
|
||||
public:
|
||||
simulation_time() { m_time.wHour = 10; m_time.wMinute = 30; }
|
||||
void
|
||||
init();
|
||||
void
|
||||
update( double const Deltatime );
|
||||
SYSTEMTIME &
|
||||
data() { return m_time; }
|
||||
SYSTEMTIME const &
|
||||
data() const { return m_time; }
|
||||
double
|
||||
second() const { return ( m_time.wMilliseconds * 0.001 + m_time.wSecond ); }
|
||||
int
|
||||
year_day() const { return m_yearday; }
|
||||
// helper, calculates day of year from given date
|
||||
int
|
||||
year_day( int Day, int const Month, int const Year ) const;
|
||||
int
|
||||
julian_day() const;
|
||||
double
|
||||
zone_bias() const { return m_timezonebias; }
|
||||
|
||||
private:
|
||||
// calculates day and month from given day of year
|
||||
void
|
||||
daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday );
|
||||
|
||||
SYSTEMTIME m_time;
|
||||
double m_milliseconds{ 0.0 };
|
||||
int m_yearday;
|
||||
char m_monthdaycounts[ 2 ][ 13 ];
|
||||
double m_timezonebias{ 0.0 };
|
||||
};
|
||||
|
||||
namespace simulation {
|
||||
|
||||
extern simulation_time Time;
|
||||
|
||||
extern basic_station Station; // temporary object, for station functionality tests
|
||||
|
||||
}
|
||||
|
||||
// wrapper for environment elements -- sky, sun, stars, clouds etc
|
||||
class world_environment {
|
||||
@@ -126,7 +80,6 @@ TWorld();
|
||||
private:
|
||||
void Update_Environment();
|
||||
void Update_Camera( const double Deltatime );
|
||||
void ResourceSweep();
|
||||
// handles vehicle change flag
|
||||
void ChangeDynamic();
|
||||
void InOutKey( bool const Near = true );
|
||||
@@ -154,5 +107,7 @@ private:
|
||||
GLFWwindow *window;
|
||||
};
|
||||
|
||||
extern TWorld World;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
514
application.cpp
Normal file
514
application.cpp
Normal file
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "application.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "keyboardinput.h"
|
||||
#include "mouseinput.h"
|
||||
#include "gamepadinput.h"
|
||||
#include "console.h"
|
||||
#include "simulation.h"
|
||||
#include "world.h"
|
||||
#include "pyint.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "renderer.h"
|
||||
#include "uilayer.h"
|
||||
#include "logs.h"
|
||||
|
||||
#ifdef EU07_BUILD_STATIC
|
||||
#pragma comment( lib, "glfw3.lib" )
|
||||
#pragma comment( lib, "glew32s.lib" )
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#pragma comment( lib, "glfw3dll.lib" )
|
||||
#else
|
||||
#pragma comment( lib, "glfw3.lib" )
|
||||
#endif
|
||||
#pragma comment( lib, "glew32.lib" )
|
||||
#endif // build_static
|
||||
#pragma comment( lib, "opengl32.lib" )
|
||||
#pragma comment( lib, "glu32.lib" )
|
||||
#pragma comment( lib, "openal32.lib")
|
||||
#pragma comment( lib, "setupapi.lib" )
|
||||
#pragma comment( lib, "python27.lib" )
|
||||
#pragma comment( lib, "libserialport-0.lib" )
|
||||
#pragma comment (lib, "dbghelp.lib")
|
||||
#pragma comment (lib, "version.lib")
|
||||
|
||||
eu07_application Application;
|
||||
|
||||
namespace input {
|
||||
|
||||
gamepad_input Gamepad;
|
||||
mouse_input Mouse;
|
||||
glm::dvec2 mouse_pickmodepos; // stores last mouse position in control picking mode
|
||||
keyboard_input Keyboard;
|
||||
Console console;
|
||||
std::unique_ptr<uart_input> uart;
|
||||
user_command command; // currently issued control command, if any
|
||||
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C"
|
||||
{
|
||||
GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window );
|
||||
}
|
||||
|
||||
LONG CALLBACK unhandled_handler( ::EXCEPTION_POINTERS* e );
|
||||
LRESULT APIENTRY WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
extern HWND Hwnd;
|
||||
extern WNDPROC BaseWindowProc;
|
||||
#endif
|
||||
|
||||
// user input callbacks
|
||||
|
||||
void window_resize_callback( GLFWwindow *window, int w, int h ) {
|
||||
// NOTE: we have two variables which basically do the same thing as we don't have dynamic fullscreen toggle
|
||||
// TBD, TODO: merge them?
|
||||
Global.iWindowWidth = w;
|
||||
Global.iWindowHeight = h;
|
||||
Global.fDistanceFactor = std::max( 0.5f, h / 768.0f ); // not sure if this is really something we want to use
|
||||
glViewport( 0, 0, w, h );
|
||||
}
|
||||
|
||||
void cursor_pos_callback( GLFWwindow *window, double x, double y ) {
|
||||
if( false == Global.ControlPicking ) {
|
||||
glfwSetCursorPos( window, 0, 0 );
|
||||
}
|
||||
|
||||
// give the potential event recipient a shot at it, in the virtual z order
|
||||
if( true == scene::Editor.on_mouse_move( x, y ) ) { return; }
|
||||
input::Mouse.move( x, y );
|
||||
}
|
||||
|
||||
void mouse_button_callback( GLFWwindow* window, int button, int action, int mods ) {
|
||||
|
||||
if( ( button != GLFW_MOUSE_BUTTON_LEFT )
|
||||
&& ( button != GLFW_MOUSE_BUTTON_RIGHT ) ) {
|
||||
// we don't care about other mouse buttons at the moment
|
||||
return;
|
||||
}
|
||||
// give the potential event recipient a shot at it, in the virtual z order
|
||||
if( true == scene::Editor.on_mouse_button( button, action ) ) { return; }
|
||||
input::Mouse.button( button, action );
|
||||
}
|
||||
|
||||
void key_callback( GLFWwindow *window, int key, int scancode, int action, int mods ) {
|
||||
|
||||
Global.shiftState = ( mods & GLFW_MOD_SHIFT ) ? true : false;
|
||||
Global.ctrlState = ( mods & GLFW_MOD_CONTROL ) ? true : false;
|
||||
Global.altState = ( mods & GLFW_MOD_ALT ) ? true : false;
|
||||
|
||||
// give the ui first shot at the input processing...
|
||||
if( true == UILayer.on_key( key, action ) ) { return; }
|
||||
if( true == scene::Editor.on_key( key, action ) ) { return; }
|
||||
// ...if the input is left untouched, pass it on
|
||||
input::Keyboard.key( key, action );
|
||||
|
||||
if( ( true == Global.InputMouse )
|
||||
&& ( ( key == GLFW_KEY_LEFT_ALT )
|
||||
|| ( key == GLFW_KEY_RIGHT_ALT ) ) ) {
|
||||
// if the alt key was pressed toggle control picking mode and set matching cursor behaviour
|
||||
if( action == GLFW_RELEASE ) {
|
||||
|
||||
if( Global.ControlPicking ) {
|
||||
// switch off
|
||||
Application.get_cursor_pos( input::mouse_pickmodepos.x, input::mouse_pickmodepos.y );
|
||||
Application.set_cursor( GLFW_CURSOR_DISABLED );
|
||||
Application.set_cursor_pos( 0, 0 );
|
||||
}
|
||||
else {
|
||||
// enter picking mode
|
||||
Application.set_cursor_pos( input::mouse_pickmodepos.x, input::mouse_pickmodepos.y );
|
||||
Application.set_cursor( GLFW_CURSOR_NORMAL );
|
||||
}
|
||||
// actually toggle the mode
|
||||
Global.ControlPicking = !Global.ControlPicking;
|
||||
}
|
||||
}
|
||||
|
||||
if( ( key == GLFW_KEY_LEFT_SHIFT )
|
||||
|| ( key == GLFW_KEY_LEFT_CONTROL )
|
||||
|| ( key == GLFW_KEY_LEFT_ALT )
|
||||
|| ( key == GLFW_KEY_RIGHT_SHIFT )
|
||||
|| ( key == GLFW_KEY_RIGHT_CONTROL )
|
||||
|| ( key == GLFW_KEY_RIGHT_ALT ) ) {
|
||||
// don't bother passing these
|
||||
return;
|
||||
}
|
||||
|
||||
if( action == GLFW_PRESS || action == GLFW_REPEAT ) {
|
||||
|
||||
World.OnKeyDown( key );
|
||||
|
||||
#ifdef CAN_I_HAS_LIBPNG
|
||||
switch( key ) {
|
||||
case GLFW_KEY_PRINT_SCREEN: {
|
||||
make_screenshot();
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void focus_callback( GLFWwindow *window, int focus ) {
|
||||
if( Global.bInactivePause ) // jeśli ma być pauzowanie okna w tle
|
||||
if( focus )
|
||||
Global.iPause &= ~4; // odpauzowanie, gdy jest na pierwszym planie
|
||||
else
|
||||
Global.iPause |= 4; // włączenie pauzy, gdy nieaktywy
|
||||
}
|
||||
|
||||
void scroll_callback( GLFWwindow* window, double xoffset, double yoffset ) {
|
||||
|
||||
if( Global.ctrlState ) {
|
||||
// ctrl + scroll wheel adjusts fov in debug mode
|
||||
Global.FieldOfView = clamp( static_cast<float>( Global.FieldOfView - yoffset * 20.0 / Global.fFpsAverage ), 15.0f, 75.0f );
|
||||
}
|
||||
}
|
||||
|
||||
// public:
|
||||
|
||||
int
|
||||
eu07_application::init( int Argc, char *Argv[] ) {
|
||||
|
||||
int result { 0 };
|
||||
|
||||
init_debug();
|
||||
init_files();
|
||||
if( ( result = init_settings( Argc, Argv ) ) != 0 ) {
|
||||
return result;
|
||||
}
|
||||
if( ( result = init_glfw() ) != 0 ) {
|
||||
return result;
|
||||
}
|
||||
init_callbacks();
|
||||
if( ( result = init_gfx() ) != 0 ) {
|
||||
return result;
|
||||
}
|
||||
if( ( result = init_audio() ) != 0 ) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
eu07_application::run() {
|
||||
|
||||
// TODO: move input sources and their initializations to the application mode member
|
||||
input::Keyboard.init();
|
||||
input::Mouse.init();
|
||||
input::Gamepad.init();
|
||||
if( true == Global.uart_conf.enable ) {
|
||||
input::uart = std::make_unique<uart_input>();
|
||||
input::uart->init();
|
||||
}
|
||||
#ifdef _WIN32
|
||||
Console::On(); // włączenie konsoli
|
||||
#endif
|
||||
|
||||
Global.pWorld = &World; // Ra: wskaźnik potrzebny do usuwania pojazdów
|
||||
|
||||
if( false == World.Init( m_window ) ) {
|
||||
ErrorLog( "Bad init: simulation setup failed" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( Global.iConvertModels < 0 ) {
|
||||
// generate binary files for all 3d models
|
||||
Global.iConvertModels = -Global.iConvertModels;
|
||||
World.CreateE3D( szModelPath ); // rekurencyjne przeglądanie katalogów
|
||||
World.CreateE3D( szDynamicPath, true );
|
||||
// auto-close when you're done
|
||||
WriteLog( "Binary 3d model generation completed" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_cursor( GLFW_CURSOR_DISABLED );
|
||||
set_cursor_pos( 0, 0 );
|
||||
|
||||
// main application loop
|
||||
// TODO: split into parts and delegate these to application mode member
|
||||
while( ( false == glfwWindowShouldClose( m_window ) )
|
||||
&& ( true == World.Update() )
|
||||
&& ( true == GfxRenderer.Render() ) ) {
|
||||
glfwPollEvents();
|
||||
input::Keyboard.poll();
|
||||
if( true == Global.InputMouse ) { input::Mouse.poll(); }
|
||||
if( true == Global.InputGamepad ) { input::Gamepad.poll(); }
|
||||
if( input::uart != nullptr ) { input::uart->poll(); }
|
||||
// TODO: wrap current command in object, include other input sources
|
||||
input::command = (
|
||||
input::Mouse.command() != user_command::none ?
|
||||
input::Mouse.command() :
|
||||
input::Keyboard.command() );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::exit() {
|
||||
|
||||
#ifdef _WIN32
|
||||
Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej)
|
||||
#endif
|
||||
SafeDelete( simulation::Region );
|
||||
|
||||
glfwDestroyWindow( m_window );
|
||||
glfwTerminate();
|
||||
|
||||
TPythonInterpreter::killInstance();
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::set_cursor( int const Mode ) {
|
||||
|
||||
UILayer.set_cursor( Mode );
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::set_cursor_pos( double const X, double const Y ) {
|
||||
|
||||
if( m_window != nullptr ) {
|
||||
glfwSetCursorPos( m_window, X, Y );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::get_cursor_pos( double &X, double &Y ) const {
|
||||
|
||||
if( m_window != nullptr ) {
|
||||
glfwGetCursorPos( m_window, &X, &Y );
|
||||
}
|
||||
}
|
||||
|
||||
// private:
|
||||
|
||||
void
|
||||
eu07_application::init_debug() {
|
||||
|
||||
#if defined(_MSC_VER) && defined (_DEBUG)
|
||||
// memory leaks
|
||||
_CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_LEAK_CHECK_DF );
|
||||
// floating point operation errors
|
||||
auto state { _clearfp() };
|
||||
state = _control87( 0, 0 );
|
||||
// this will turn on FPE for #IND and zerodiv
|
||||
state = _control87( state & ~( _EM_ZERODIVIDE | _EM_INVALID ), _MCW_EM );
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
::SetUnhandledExceptionFilter( unhandled_handler );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::init_files() {
|
||||
|
||||
#ifdef _WIN32
|
||||
DeleteFile( "log.txt" );
|
||||
DeleteFile( "errors.txt" );
|
||||
_mkdir( "logs" );
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
eu07_application::init_settings( int Argc, char *Argv[] ) {
|
||||
|
||||
Global.LoadIniFile( "eu07.ini" );
|
||||
if( ( Global.iWriteLogEnabled & 2 ) != 0 ) {
|
||||
// show output console if requested
|
||||
AllocConsole();
|
||||
}
|
||||
/*
|
||||
std::string executable( argv[ 0 ] ); auto const pathend = executable.rfind( '\\' );
|
||||
Global.ExecutableName =
|
||||
( pathend != std::string::npos ?
|
||||
executable.substr( executable.rfind( '\\' ) + 1 ) :
|
||||
executable );
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
// retrieve product version from the file's version data table
|
||||
{
|
||||
auto const fileversionsize { ::GetFileVersionInfoSize( Argv[ 0 ], NULL ) };
|
||||
std::vector<BYTE>fileversiondata; fileversiondata.resize( fileversionsize );
|
||||
if( ::GetFileVersionInfo( Argv[ 0 ], 0, fileversionsize, fileversiondata.data() ) ) {
|
||||
|
||||
struct lang_codepage {
|
||||
WORD language;
|
||||
WORD codepage;
|
||||
} *langcodepage;
|
||||
UINT datasize;
|
||||
|
||||
::VerQueryValue(
|
||||
fileversiondata.data(),
|
||||
TEXT( "\\VarFileInfo\\Translation" ),
|
||||
(LPVOID*)&langcodepage,
|
||||
&datasize );
|
||||
|
||||
std::string subblock; subblock.resize( 50 );
|
||||
::StringCchPrintf(
|
||||
&subblock[0], subblock.size(),
|
||||
TEXT( "\\StringFileInfo\\%04x%04x\\ProductVersion" ),
|
||||
langcodepage->language,
|
||||
langcodepage->codepage );
|
||||
|
||||
VOID *stringdata;
|
||||
if( ::VerQueryValue(
|
||||
fileversiondata.data(),
|
||||
subblock.data(),
|
||||
&stringdata,
|
||||
&datasize ) ) {
|
||||
|
||||
Global.asVersion = std::string( reinterpret_cast<char*>(stringdata) );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// process command line arguments
|
||||
for( int i = 1; i < Argc; ++i ) {
|
||||
|
||||
std::string token { Argv[ i ] };
|
||||
|
||||
if( token == "-e3d" ) {
|
||||
Global.iConvertModels = (
|
||||
Global.iConvertModels > 0 ?
|
||||
-Global.iConvertModels :
|
||||
-7 ); // z optymalizacją, bananami i prawidłowym Opacity
|
||||
}
|
||||
else if( token == "-s" ) {
|
||||
if( i + 1 < Argc ) {
|
||||
Global.SceneryFile = Argv[ ++i ];
|
||||
}
|
||||
}
|
||||
else if( token == "-v" ) {
|
||||
if( i + 1 < Argc ) {
|
||||
Global.asHumanCtrlVehicle = Argv[ ++i ];
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cout
|
||||
<< "usage: " << std::string( Argv[ 0 ] )
|
||||
<< " [-s sceneryfilepath]"
|
||||
<< " [-v vehiclename]"
|
||||
<< " [-e3d]"
|
||||
<< std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eu07_application::init_glfw() {
|
||||
|
||||
if( glfwInit() == GLFW_FALSE ) {
|
||||
ErrorLog( "Bad init: failed to initialize glfw" );
|
||||
return -1;
|
||||
}
|
||||
// match requested video mode to current to allow for
|
||||
// fullwindow creation when resolution is the same
|
||||
auto *monitor { glfwGetPrimaryMonitor() };
|
||||
auto const *vmode { glfwGetVideoMode( monitor ) };
|
||||
|
||||
glfwWindowHint( GLFW_RED_BITS, vmode->redBits );
|
||||
glfwWindowHint( GLFW_GREEN_BITS, vmode->greenBits );
|
||||
glfwWindowHint( GLFW_BLUE_BITS, vmode->blueBits );
|
||||
glfwWindowHint( GLFW_REFRESH_RATE, vmode->refreshRate );
|
||||
|
||||
glfwWindowHint( GLFW_AUTO_ICONIFY, GLFW_FALSE );
|
||||
if( Global.iMultisampling > 0 ) {
|
||||
glfwWindowHint( GLFW_SAMPLES, 1 << Global.iMultisampling );
|
||||
}
|
||||
|
||||
if( Global.bFullScreen ) {
|
||||
// match screen dimensions with selected monitor, for 'borderless window' in fullscreen mode
|
||||
Global.iWindowWidth = vmode->width;
|
||||
Global.iWindowHeight = vmode->height;
|
||||
}
|
||||
|
||||
auto *window {
|
||||
glfwCreateWindow(
|
||||
Global.iWindowWidth,
|
||||
Global.iWindowHeight,
|
||||
Global.AppName.c_str(),
|
||||
( Global.bFullScreen ?
|
||||
monitor :
|
||||
nullptr ),
|
||||
nullptr ) };
|
||||
|
||||
if( window == nullptr ) {
|
||||
ErrorLog( "Bad init: failed to create glfw window" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent( window );
|
||||
glfwSwapInterval( Global.VSync ? 1 : 0 ); //vsync
|
||||
|
||||
#ifdef _WIN32
|
||||
// setup wrapper for base glfw window proc, to handle copydata messages
|
||||
Hwnd = glfwGetWin32Window( window );
|
||||
BaseWindowProc = ( WNDPROC )::SetWindowLongPtr( Hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc );
|
||||
// switch off the topmost flag
|
||||
::SetWindowPos( Hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
||||
#endif
|
||||
// TBD, TODO: move the global pointer to a more appropriate place
|
||||
m_window = window;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::init_callbacks() {
|
||||
|
||||
glfwSetFramebufferSizeCallback( m_window, window_resize_callback );
|
||||
glfwSetCursorPosCallback( m_window, cursor_pos_callback );
|
||||
glfwSetMouseButtonCallback( m_window, mouse_button_callback );
|
||||
glfwSetKeyCallback( m_window, key_callback );
|
||||
glfwSetScrollCallback( m_window, scroll_callback );
|
||||
glfwSetWindowFocusCallback( m_window, focus_callback );
|
||||
{
|
||||
int width, height;
|
||||
glfwGetFramebufferSize( m_window, &width, &height );
|
||||
window_resize_callback( m_window, width, height );
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
eu07_application::init_gfx() {
|
||||
|
||||
if( glewInit() != GLEW_OK ) {
|
||||
ErrorLog( "Bad init: failed to initialize glew" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( ( false == GfxRenderer.Init( m_window ) )
|
||||
|| ( false == UILayer.init( m_window ) ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eu07_application::init_audio() {
|
||||
|
||||
if( Global.bSoundEnabled ) {
|
||||
Global.bSoundEnabled &= audio::renderer.init();
|
||||
}
|
||||
// NOTE: lack of audio isn't deemed a failure serious enough to throw in the towel
|
||||
return 0;
|
||||
}
|
||||
46
application.h
Normal file
46
application.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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/.
|
||||
*/
|
||||
|
||||
class eu07_application {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
eu07_application() = default;
|
||||
// methods
|
||||
int
|
||||
init( int Argc, char *Argv[] );
|
||||
int
|
||||
run();
|
||||
void
|
||||
exit();
|
||||
void
|
||||
set_cursor( int const Mode );
|
||||
void
|
||||
set_cursor_pos( double const X, double const Y );
|
||||
void
|
||||
get_cursor_pos( double &X, double &Y ) const;
|
||||
inline
|
||||
GLFWwindow *
|
||||
window() {
|
||||
return m_window; }
|
||||
|
||||
private:
|
||||
// methods
|
||||
void init_debug();
|
||||
void init_files();
|
||||
int init_settings( int Argc, char *Argv[] );
|
||||
int init_glfw();
|
||||
void init_callbacks();
|
||||
int init_gfx();
|
||||
int init_audio();
|
||||
// members
|
||||
GLFWwindow * m_window { nullptr };
|
||||
};
|
||||
|
||||
extern eu07_application Application;
|
||||
@@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "resourcemanager.h"
|
||||
#include "uitranscripts.h"
|
||||
|
||||
class opengl_renderer;
|
||||
class sound_source;
|
||||
|
||||
using uint32_sequence = std::vector<std::uint32_t>;
|
||||
@@ -100,7 +101,7 @@ private:
|
||||
|
||||
class openal_renderer {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
|
||||
@@ -12,9 +12,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "globals.h"
|
||||
#include "logs.h"
|
||||
#include "parser.h"
|
||||
#include "world.h"
|
||||
|
||||
extern TWorld World;
|
||||
|
||||
bool
|
||||
keyboard_input::recall_bindings() {
|
||||
|
||||
@@ -51,9 +51,6 @@
|
||||
<ClCompile Include="DynObj.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EU07.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Event.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -246,6 +243,15 @@
|
||||
<ClCompile Include="sceneeditor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="simulationtime.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="application.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="eu07.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Globals.h">
|
||||
@@ -476,6 +482,12 @@
|
||||
<ClInclude Include="sceneeditor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="simulationtime.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="application.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="maszyna.rc">
|
||||
|
||||
@@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "messaging.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "application.h"
|
||||
#include "simulation.h"
|
||||
#include "mtable.h"
|
||||
#include "logs.h"
|
||||
@@ -51,7 +52,7 @@ WyslijEvent(const std::string &e, const std::string &d)
|
||||
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||
cData.cbData = (DWORD)(12 + i + j); // 8+dwa liczniki i dwa zera kończące
|
||||
cData.lpData = &r;
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData );
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " " + e + " sent" );
|
||||
#endif
|
||||
}
|
||||
@@ -71,7 +72,7 @@ WyslijUszkodzenia(const std::string &t, char fl)
|
||||
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||
cData.cbData = (DWORD)(11 + i); // 8+licznik i zero kończące
|
||||
cData.lpData = &r;
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData );
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
|
||||
#endif
|
||||
}
|
||||
@@ -90,7 +91,7 @@ WyslijString(const std::string &t, int n)
|
||||
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||
cData.cbData = (DWORD)(10 + i); // 8+licznik i zero kończące
|
||||
cData.lpData = &r;
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData );
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
|
||||
#endif
|
||||
}
|
||||
@@ -174,7 +175,7 @@ WyslijNamiary(TDynamicObject const *Vehicle)
|
||||
cData.cbData = (DWORD)(10 + i + j); // 8+licznik i zero kończące
|
||||
cData.lpData = &r;
|
||||
// WriteLog("Ramka gotowa");
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData );
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
// WriteLog("Ramka poszla!");
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " " + Vehicle->asName + " sent");
|
||||
#endif
|
||||
@@ -223,7 +224,7 @@ WyslijObsadzone()
|
||||
cData.cbData = 8 + 1984; // 8+licznik i zero kończące
|
||||
cData.lpData = &r;
|
||||
// WriteLog("Ramka gotowa");
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData );
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
CommLog( Now() + " " + std::to_string(r.iComm) + " obsadzone" + " sent");
|
||||
#endif
|
||||
}
|
||||
@@ -249,7 +250,7 @@ WyslijParam(int nr, int fl)
|
||||
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||
cData.cbData = 12 + i; // 12+rozmiar danych
|
||||
cData.lpData = &r;
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global.window ), (LPARAM)&cData );
|
||||
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Application.window() ), (LPARAM)&cData );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
2
moon.cpp
2
moon.cpp
@@ -4,7 +4,7 @@
|
||||
#include "globals.h"
|
||||
#include "mtable.h"
|
||||
#include "utilities.h"
|
||||
#include "world.h"
|
||||
#include "simulationtime.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSun -- class responsible for dynamic calculation of position and intensity of the Sun,
|
||||
|
||||
@@ -9,6 +9,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "mouseinput.h"
|
||||
|
||||
#include "application.h"
|
||||
#include "utilities.h"
|
||||
#include "globals.h"
|
||||
#include "timer.h"
|
||||
@@ -18,8 +20,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "renderer.h"
|
||||
#include "uilayer.h"
|
||||
|
||||
extern TWorld World;
|
||||
|
||||
void
|
||||
mouse_slider::bind( user_command const &Command ) {
|
||||
|
||||
@@ -82,15 +82,14 @@ mouse_slider::bind( user_command const &Command ) {
|
||||
}
|
||||
}
|
||||
// hide the cursor and place it in accordance with current slider value
|
||||
glfwGetCursorPos( Global.window, &m_cursorposition.x, &m_cursorposition.y );
|
||||
UILayer.set_cursor( GLFW_CURSOR_DISABLED );
|
||||
Application.get_cursor_pos( m_cursorposition.x, m_cursorposition.y );
|
||||
Application.set_cursor( GLFW_CURSOR_DISABLED );
|
||||
|
||||
auto const controlsize { Global.iWindowHeight * 0.75 };
|
||||
auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 };
|
||||
auto const stepsize { controlsize / m_valuerange };
|
||||
|
||||
glfwSetCursorPos(
|
||||
Global.window,
|
||||
Application.set_cursor_pos(
|
||||
Global.iWindowWidth * 0.5,
|
||||
( m_analogue ?
|
||||
controledge - ( 1.0 - m_value ) * controlsize :
|
||||
@@ -101,8 +100,8 @@ void
|
||||
mouse_slider::release() {
|
||||
|
||||
m_command = user_command::none;
|
||||
glfwSetCursorPos( Global.window, m_cursorposition.x, m_cursorposition.y );
|
||||
UILayer.set_cursor( GLFW_CURSOR_NORMAL );
|
||||
Application.set_cursor_pos( m_cursorposition.x, m_cursorposition.y );
|
||||
Application.set_cursor( GLFW_CURSOR_NORMAL );
|
||||
}
|
||||
|
||||
void
|
||||
@@ -525,10 +524,10 @@ mouse_input::default_bindings() {
|
||||
user_command::pantographtogglerear,
|
||||
user_command::none } },
|
||||
{ "pantfrontoff_sw:", {
|
||||
user_command::pantographtogglefront,
|
||||
user_command::pantographlowerfront,
|
||||
user_command::none } }, // TODO: dedicated lower pantograph commands
|
||||
{ "pantrearoff_sw:", {
|
||||
user_command::pantographtogglerear,
|
||||
user_command::pantographlowerrear,
|
||||
user_command::none } }, // TODO: dedicated lower pantograph commands
|
||||
{ "pantalloff_sw:", {
|
||||
user_command::pantographlowerall,
|
||||
|
||||
@@ -11,7 +11,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "mtable.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "world.h"
|
||||
#include "simulationtime.h"
|
||||
#include "utilities.h"
|
||||
|
||||
double TTrainParameters::CheckTrainLatency()
|
||||
@@ -49,7 +49,7 @@ bool TTrainParameters::IsStop()
|
||||
return true; // na ostatnim się zatrzymać zawsze
|
||||
}
|
||||
|
||||
bool TTrainParameters::UpdateMTable( simulation_time const &Time, std::string const &NewName ) {
|
||||
bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) {
|
||||
|
||||
return UpdateMTable( Time.data().wHour, Time.data().wMinute, NewName );
|
||||
}
|
||||
|
||||
2
mtable.h
2
mtable.h
@@ -75,7 +75,7 @@ class TTrainParameters
|
||||
bool IsStop();
|
||||
bool IsTimeToGo(double hh, double mm);
|
||||
bool UpdateMTable(double hh, double mm, std::string const &NewName);
|
||||
bool UpdateMTable( simulation_time const &Time, std::string const &NewName );
|
||||
bool UpdateMTable( scenario_time const &Time, std::string const &NewName );
|
||||
bool RewindTimeTable( std::string actualStationName );
|
||||
TTrainParameters( std::string const &NewTrainName );
|
||||
void NewName(std::string const &NewTrainName);
|
||||
|
||||
@@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "globals.h"
|
||||
#include "timer.h"
|
||||
#include "simulation.h"
|
||||
#include "simulationtime.h"
|
||||
#include "world.h"
|
||||
#include "train.h"
|
||||
#include "dynobj.h"
|
||||
@@ -24,7 +25,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "utilities.h"
|
||||
|
||||
opengl_renderer GfxRenderer;
|
||||
extern TWorld World;
|
||||
|
||||
int const EU07_PICKBUFFERSIZE { 1024 }; // size of (square) textures bound with the pick framebuffer
|
||||
int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental cube map texture
|
||||
|
||||
6
scene.h
6
scene.h
@@ -60,7 +60,7 @@ struct scratch_data {
|
||||
// TBD, TODO: replace with quadtree scheme?
|
||||
class basic_cell {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
@@ -198,7 +198,7 @@ private:
|
||||
// basic scene partitioning structure, holds terrain geometry and collection of cells
|
||||
class basic_section {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
@@ -302,7 +302,7 @@ private:
|
||||
// top-level of scene spatial structure, holds collection of sections
|
||||
class basic_region {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
|
||||
@@ -11,8 +11,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "sceneeditor.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "application.h"
|
||||
#include "simulation.h"
|
||||
#include "uilayer.h"
|
||||
#include "renderer.h"
|
||||
|
||||
namespace scene {
|
||||
@@ -47,7 +47,7 @@ basic_editor::on_mouse_button( int const Button, int const Action ) {
|
||||
m_node = GfxRenderer.Update_Pick_Node();
|
||||
m_nodesnapshot = { m_node };
|
||||
if( m_node ) {
|
||||
UILayer.set_cursor( GLFW_CURSOR_DISABLED );
|
||||
Application.set_cursor( GLFW_CURSOR_DISABLED );
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -55,7 +55,7 @@ basic_editor::on_mouse_button( int const Button, int const Action ) {
|
||||
// TODO: record the current undo step on the undo stack
|
||||
m_nodesnapshot = { m_node };
|
||||
if( m_node ) {
|
||||
UILayer.set_cursor( GLFW_CURSOR_NORMAL );
|
||||
Application.set_cursor( GLFW_CURSOR_NORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
144
simulation.cpp
144
simulation.cpp
@@ -10,11 +10,11 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "stdafx.h"
|
||||
#include "simulation.h"
|
||||
|
||||
#include "world.h"
|
||||
#include "globals.h"
|
||||
#include "logs.h"
|
||||
#include "simulationtime.h"
|
||||
#include "uilayer.h"
|
||||
#include "renderer.h"
|
||||
#include "logs.h"
|
||||
|
||||
|
||||
namespace simulation {
|
||||
@@ -32,9 +32,42 @@ light_array Lights;
|
||||
|
||||
scene::basic_region *Region { nullptr };
|
||||
|
||||
|
||||
|
||||
bool
|
||||
state_manager::deserialize( std::string const &Scenariofile ) {
|
||||
|
||||
return m_serializer.deserialize( Scenariofile );
|
||||
}
|
||||
|
||||
// stores class data in specified file, in legacy (text) format
|
||||
void
|
||||
state_manager::export_as_text( std::string const &Scenariofile ) const {
|
||||
|
||||
return m_serializer.export_as_text( Scenariofile );
|
||||
}
|
||||
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
state_manager::update( double const Deltatime, int Iterationcount ) {
|
||||
// aktualizacja animacji krokiem FPS: dt=krok czasu [s], dt*iter=czas od ostatnich przeliczeń
|
||||
if (Deltatime == 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto const totaltime { Deltatime * Iterationcount };
|
||||
// NOTE: we perform animations first, as they can determine factors like contact with powergrid
|
||||
TAnimModel::AnimUpdate( totaltime ); // wykonanie zakolejkowanych animacji
|
||||
|
||||
simulation::Powergrid.update( totaltime );
|
||||
simulation::Vehicles.update( Deltatime, Iterationcount );
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
state_serializer::deserialize( std::string const &Scenariofile ) {
|
||||
|
||||
// TODO: move initialization to separate routine so we can reuse it
|
||||
SafeDelete( Region );
|
||||
Region = new scene::basic_region();
|
||||
@@ -61,50 +94,33 @@ state_manager::deserialize( std::string const &Scenariofile ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
state_manager::update( double const Deltatime, int Iterationcount ) {
|
||||
// aktualizacja animacji krokiem FPS: dt=krok czasu [s], dt*iter=czas od ostatnich przeliczeń
|
||||
if (Deltatime == 0.0) {
|
||||
// jeśli załączona jest pauza, to tylko obsłużyć ruch w kabinie trzeba
|
||||
return;
|
||||
}
|
||||
|
||||
auto const totaltime { Deltatime * Iterationcount };
|
||||
// NOTE: we perform animations first, as they can determine factors like contact with powergrid
|
||||
TAnimModel::AnimUpdate( totaltime ); // wykonanie zakolejkowanych animacji
|
||||
|
||||
simulation::Powergrid.update( totaltime );
|
||||
simulation::Vehicles.update( Deltatime, Iterationcount );
|
||||
}
|
||||
|
||||
// restores class data from provided stream
|
||||
void
|
||||
state_manager::deserialize( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// prepare deserialization function table
|
||||
// since all methods use the same objects, we can have simple, hard-coded binds or lambdas for the task
|
||||
using deserializefunction = void(state_manager::*)(cParser &, scene::scratch_data &);
|
||||
using deserializefunction = void( state_serializer::*)(cParser &, scene::scratch_data &);
|
||||
std::vector<
|
||||
std::pair<
|
||||
std::string,
|
||||
deserializefunction> > functionlist = {
|
||||
{ "atmo", &state_manager::deserialize_atmo },
|
||||
{ "camera", &state_manager::deserialize_camera },
|
||||
{ "config", &state_manager::deserialize_config },
|
||||
{ "description", &state_manager::deserialize_description },
|
||||
{ "event", &state_manager::deserialize_event },
|
||||
{ "firstinit", &state_manager::deserialize_firstinit },
|
||||
{ "light", &state_manager::deserialize_light },
|
||||
{ "node", &state_manager::deserialize_node },
|
||||
{ "origin", &state_manager::deserialize_origin },
|
||||
{ "endorigin", &state_manager::deserialize_endorigin },
|
||||
{ "rotate", &state_manager::deserialize_rotate },
|
||||
{ "sky", &state_manager::deserialize_sky },
|
||||
{ "test", &state_manager::deserialize_test },
|
||||
{ "time", &state_manager::deserialize_time },
|
||||
{ "trainset", &state_manager::deserialize_trainset },
|
||||
{ "endtrainset", &state_manager::deserialize_endtrainset } };
|
||||
{ "atmo", &state_serializer::deserialize_atmo },
|
||||
{ "camera", &state_serializer::deserialize_camera },
|
||||
{ "config", &state_serializer::deserialize_config },
|
||||
{ "description", &state_serializer::deserialize_description },
|
||||
{ "event", &state_serializer::deserialize_event },
|
||||
{ "firstinit", &state_serializer::deserialize_firstinit },
|
||||
{ "light", &state_serializer::deserialize_light },
|
||||
{ "node", &state_serializer::deserialize_node },
|
||||
{ "origin", &state_serializer::deserialize_origin },
|
||||
{ "endorigin", &state_serializer::deserialize_endorigin },
|
||||
{ "rotate", &state_serializer::deserialize_rotate },
|
||||
{ "sky", &state_serializer::deserialize_sky },
|
||||
{ "test", &state_serializer::deserialize_test },
|
||||
{ "time", &state_serializer::deserialize_time },
|
||||
{ "trainset", &state_serializer::deserialize_trainset },
|
||||
{ "endtrainset", &state_serializer::deserialize_endtrainset } };
|
||||
using deserializefunctionbind = std::function<void()>;
|
||||
std::unordered_map<
|
||||
std::string,
|
||||
@@ -146,7 +162,7 @@ state_manager::deserialize( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// NOTE: parameter system needs some decent replacement, but not worth the effort if we're moving to built-in editor
|
||||
// atmosphere color; legacy parameter, no longer used
|
||||
@@ -178,7 +194,7 @@ state_manager::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_camera( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_camera( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
glm::dvec3 xyz, abc;
|
||||
int i = -1, into = -1; // do której definicji kamery wstawić
|
||||
@@ -232,21 +248,21 @@ state_manager::deserialize_camera( cParser &Input, scene::scratch_data &Scratchp
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_config( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_config( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// config parameters (re)definition
|
||||
Global.ConfigParse( Input );
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_description( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_description( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// legacy section, never really used;
|
||||
skip_until( Input, "enddescription" );
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_event( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_event( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// TODO: refactor event class and its de/serialization. do offset and rotation after deserialization is done
|
||||
auto *event = new TEvent();
|
||||
@@ -265,7 +281,7 @@ state_manager::deserialize_event( cParser &Input, scene::scratch_data &Scratchpa
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_firstinit( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_firstinit( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
if( true == Scratchpad.initialized ) { return; }
|
||||
|
||||
@@ -279,14 +295,14 @@ state_manager::deserialize_firstinit( cParser &Input, scene::scratch_data &Scrat
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_light( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_light( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// legacy section, no longer used nor supported;
|
||||
skip_until( Input, "endlight" );
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||
|
||||
@@ -469,7 +485,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_origin( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_origin( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
glm::dvec3 offset;
|
||||
Input.getTokens( 3 );
|
||||
@@ -486,7 +502,7 @@ state_manager::deserialize_origin( cParser &Input, scene::scratch_data &Scratchp
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_endorigin( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_endorigin( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
if( false == Scratchpad.location.offset.empty() ) {
|
||||
Scratchpad.location.offset.pop();
|
||||
@@ -497,7 +513,7 @@ state_manager::deserialize_endorigin( cParser &Input, scene::scratch_data &Scrat
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_rotate( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_rotate( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
Input.getTokens( 3 );
|
||||
Input
|
||||
@@ -507,7 +523,7 @@ state_manager::deserialize_rotate( cParser &Input, scene::scratch_data &Scratchp
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_sky( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_sky( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// sky model
|
||||
Input.getTokens( 1 );
|
||||
@@ -518,14 +534,14 @@ state_manager::deserialize_sky( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_test( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_test( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// legacy section, no longer supported;
|
||||
skip_until( Input, "endtest" );
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_time( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_time( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// current scenario time
|
||||
cParser timeparser( Input.getToken<std::string>() );
|
||||
@@ -548,7 +564,7 @@ state_manager::deserialize_time( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_trainset( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_trainset( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
if( true == Scratchpad.trainset.is_open ) {
|
||||
// shouldn't happen but if it does wrap up currently open trainset and report an error
|
||||
@@ -568,7 +584,7 @@ state_manager::deserialize_trainset( cParser &Input, scene::scratch_data &Scratc
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
state_serializer::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
if( ( false == Scratchpad.trainset.is_open )
|
||||
|| ( true == Scratchpad.trainset.vehicles.empty() ) ) {
|
||||
@@ -616,7 +632,7 @@ state_manager::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scr
|
||||
|
||||
// creates path and its wrapper, restoring class data from provided stream
|
||||
TTrack *
|
||||
state_manager::deserialize_path( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
state_serializer::deserialize_path( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
// TODO: refactor track and wrapper classes and their de/serialization. do offset and rotation after deserialization is done
|
||||
auto *track = new TTrack( Nodedata );
|
||||
@@ -633,7 +649,7 @@ state_manager::deserialize_path( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
|
||||
TTraction *
|
||||
state_manager::deserialize_traction( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
state_serializer::deserialize_traction( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
if( false == Global.bLoadTraction ) {
|
||||
skip_until( Input, "endtraction" );
|
||||
@@ -651,7 +667,7 @@ state_manager::deserialize_traction( cParser &Input, scene::scratch_data &Scratc
|
||||
}
|
||||
|
||||
TTractionPowerSource *
|
||||
state_manager::deserialize_tractionpowersource( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
state_serializer::deserialize_tractionpowersource( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
if( false == Global.bLoadTraction ) {
|
||||
skip_until( Input, "end" );
|
||||
@@ -667,7 +683,7 @@ state_manager::deserialize_tractionpowersource( cParser &Input, scene::scratch_d
|
||||
}
|
||||
|
||||
TMemCell *
|
||||
state_manager::deserialize_memorycell( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
state_serializer::deserialize_memorycell( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
auto *memorycell = new TMemCell( Nodedata );
|
||||
memorycell->Load( &Input );
|
||||
@@ -678,7 +694,7 @@ state_manager::deserialize_memorycell( cParser &Input, scene::scratch_data &Scra
|
||||
}
|
||||
|
||||
TEventLauncher *
|
||||
state_manager::deserialize_eventlauncher( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
state_serializer::deserialize_eventlauncher( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
glm::dvec3 location;
|
||||
Input.getTokens( 3 );
|
||||
@@ -695,7 +711,7 @@ state_manager::deserialize_eventlauncher( cParser &Input, scene::scratch_data &S
|
||||
}
|
||||
|
||||
TAnimModel *
|
||||
state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
state_serializer::deserialize_model( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
glm::dvec3 location;
|
||||
glm::vec3 rotation;
|
||||
@@ -721,7 +737,7 @@ state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpa
|
||||
}
|
||||
|
||||
TDynamicObject *
|
||||
state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
state_serializer::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
if( false == Scratchpad.trainset.is_open ) {
|
||||
// part of trainset data is used when loading standalone vehicles, so clear it just in case
|
||||
@@ -846,7 +862,7 @@ state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratch
|
||||
}
|
||||
|
||||
sound_source *
|
||||
state_manager::deserialize_sound( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
state_serializer::deserialize_sound( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
glm::dvec3 location;
|
||||
Input.getTokens( 3 );
|
||||
@@ -869,7 +885,7 @@ state_manager::deserialize_sound( cParser &Input, scene::scratch_data &Scratchpa
|
||||
|
||||
// skips content of stream until specified token
|
||||
void
|
||||
state_manager::skip_until( cParser &Input, std::string const &Token ) {
|
||||
state_serializer::skip_until( cParser &Input, std::string const &Token ) {
|
||||
|
||||
std::string token { Input.getToken<std::string>() };
|
||||
while( ( false == token.empty() )
|
||||
@@ -881,7 +897,7 @@ state_manager::skip_until( cParser &Input, std::string const &Token ) {
|
||||
|
||||
// transforms provided location by specifed rotation and offset
|
||||
glm::dvec3
|
||||
state_manager::transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad ) {
|
||||
state_serializer::transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad ) {
|
||||
|
||||
if( Scratchpad.location.rotation != glm::vec3( 0, 0, 0 ) ) {
|
||||
auto const rotation = glm::radians( Scratchpad.location.rotation );
|
||||
@@ -896,7 +912,7 @@ state_manager::transform( glm::dvec3 Location, scene::scratch_data const &Scratc
|
||||
|
||||
// stores class data in specified file, in legacy (text) format
|
||||
void
|
||||
state_manager::export_as_text( std::string const &Scenariofile ) const {
|
||||
state_serializer::export_as_text( std::string const &Scenariofile ) const {
|
||||
|
||||
if( Scenariofile == "$.scn" ) {
|
||||
ErrorLog( "Bad file: scenery export not supported for file \"$.scn\"" );
|
||||
|
||||
26
simulation.h
26
simulation.h
@@ -25,15 +25,11 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
namespace simulation {
|
||||
|
||||
class state_manager {
|
||||
class state_serializer {
|
||||
|
||||
public:
|
||||
// types
|
||||
|
||||
// methods
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
update( double Deltatime, int Iterationcount );
|
||||
// restores simulation data from specified file. returns: true on success, false otherwise
|
||||
bool
|
||||
deserialize( std::string const &Scenariofile );
|
||||
// stores class data in specified file, in legacy (text) format
|
||||
@@ -72,7 +68,25 @@ private:
|
||||
void skip_until( cParser &Input, std::string const &Token );
|
||||
// transforms provided location by specifed rotation and offset
|
||||
glm::dvec3 transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad );
|
||||
};
|
||||
|
||||
class state_manager {
|
||||
|
||||
public:
|
||||
// methods
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
update( double Deltatime, int Iterationcount );
|
||||
// restores simulation data from specified file. returns: true on success, false otherwise
|
||||
bool
|
||||
deserialize( std::string const &Scenariofile );
|
||||
// stores class data in specified file, in legacy (text) format
|
||||
void
|
||||
export_as_text( std::string const &Scenariofile ) const;
|
||||
|
||||
private:
|
||||
// members
|
||||
state_serializer m_serializer;
|
||||
};
|
||||
|
||||
extern state_manager State;
|
||||
|
||||
192
simulationtime.cpp
Normal file
192
simulationtime.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "simulationtime.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace simulation {
|
||||
|
||||
scenario_time Time;
|
||||
|
||||
} // simulation
|
||||
|
||||
void
|
||||
scenario_time::init() {
|
||||
|
||||
char monthdaycounts[ 2 ][ 13 ] = {
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
|
||||
::memcpy( m_monthdaycounts, monthdaycounts, sizeof( monthdaycounts ) );
|
||||
|
||||
// potentially adjust scenario clock
|
||||
auto const requestedtime { clamp_circular<int>( m_time.wHour * 60 + m_time.wMinute + Global.ScenarioTimeOffset * 60, 24 * 60 ) };
|
||||
auto const requestedhour { ( requestedtime / 60 ) % 24 };
|
||||
auto const requestedminute { requestedtime % 60 };
|
||||
// cache requested elements, if any
|
||||
::GetLocalTime( &m_time );
|
||||
|
||||
if( Global.fMoveLight > 0.0 ) {
|
||||
// day and month of the year can be overriden by scenario setup
|
||||
daymonth( m_time.wDay, m_time.wMonth, m_time.wYear, static_cast<WORD>( Global.fMoveLight ) );
|
||||
}
|
||||
|
||||
if( requestedhour != -1 ) { m_time.wHour = static_cast<WORD>( clamp( requestedhour, 0, 23 ) ); }
|
||||
if( requestedminute != -1 ) { m_time.wMinute = static_cast<WORD>( clamp( requestedminute, 0, 59 ) ); }
|
||||
// if the time is taken from the local clock leave the seconds intact, otherwise set them to zero
|
||||
if( ( requestedhour != -1 )
|
||||
|| ( requestedminute != 1 ) ) {
|
||||
m_time.wSecond = 0;
|
||||
}
|
||||
|
||||
m_yearday = year_day( m_time.wDay, m_time.wMonth, m_time.wYear );
|
||||
|
||||
// calculate time zone bias
|
||||
// retrieve relevant time zone info from system registry (or fall back on supplied default)
|
||||
// TODO: select timezone matching defined geographic location and/or country
|
||||
struct registry_time_zone_info {
|
||||
long Bias;
|
||||
long StandardBias;
|
||||
long DaylightBias;
|
||||
SYSTEMTIME StandardDate;
|
||||
SYSTEMTIME DaylightDate;
|
||||
} registrytimezoneinfo = { -60, 0, -60, { 0, 10, 0, 5, 3, 0, 0, 0 }, { 0, 3, 0, 5, 2, 0, 0, 0 } };
|
||||
|
||||
#ifdef _WIN32
|
||||
TCHAR timezonekeyname[] { TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\Central European Standard Time" ) };
|
||||
HKEY timezonekey { NULL };
|
||||
DWORD size { sizeof( registrytimezoneinfo ) };
|
||||
if( ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, timezonekeyname, 0, KEY_QUERY_VALUE, &timezonekey ) == ERROR_SUCCESS ) {
|
||||
::RegQueryValueEx( timezonekey, "TZI", NULL, NULL, (BYTE *)®istrytimezoneinfo, &size );
|
||||
}
|
||||
#endif
|
||||
TIME_ZONE_INFORMATION timezoneinfo { 0 };
|
||||
timezoneinfo.Bias = registrytimezoneinfo.Bias;
|
||||
timezoneinfo.DaylightBias = registrytimezoneinfo.DaylightBias;
|
||||
timezoneinfo.DaylightDate = registrytimezoneinfo.DaylightDate;
|
||||
timezoneinfo.StandardBias = registrytimezoneinfo.StandardBias;
|
||||
timezoneinfo.StandardDate = registrytimezoneinfo.StandardDate;
|
||||
|
||||
auto zonebias { timezoneinfo.Bias };
|
||||
if( m_yearday < year_day( timezoneinfo.DaylightDate.wDay, timezoneinfo.DaylightDate.wMonth, m_time.wYear ) ) {
|
||||
zonebias += timezoneinfo.StandardBias;
|
||||
}
|
||||
else if( m_yearday < year_day( timezoneinfo.StandardDate.wDay, timezoneinfo.StandardDate.wMonth, m_time.wYear ) ) {
|
||||
zonebias += timezoneinfo.DaylightBias;
|
||||
}
|
||||
else {
|
||||
zonebias += timezoneinfo.StandardBias;
|
||||
}
|
||||
|
||||
m_timezonebias = ( zonebias / 60.0 );
|
||||
}
|
||||
|
||||
void
|
||||
scenario_time::update( double const Deltatime ) {
|
||||
|
||||
m_milliseconds += ( 1000.0 * Deltatime );
|
||||
while( m_milliseconds >= 1000.0 ) {
|
||||
|
||||
++m_time.wSecond;
|
||||
m_milliseconds -= 1000.0;
|
||||
}
|
||||
m_time.wMilliseconds = std::floor( m_milliseconds );
|
||||
while( m_time.wSecond >= 60 ) {
|
||||
|
||||
++m_time.wMinute;
|
||||
m_time.wSecond -= 60;
|
||||
}
|
||||
while( m_time.wMinute >= 60 ) {
|
||||
|
||||
++m_time.wHour;
|
||||
m_time.wMinute -= 60;
|
||||
}
|
||||
while( m_time.wHour >= 24 ) {
|
||||
|
||||
++m_time.wDay;
|
||||
++m_time.wDayOfWeek;
|
||||
if( m_time.wDayOfWeek >= 7 ) {
|
||||
m_time.wDayOfWeek -= 7;
|
||||
}
|
||||
m_time.wHour -= 24;
|
||||
}
|
||||
int leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 );
|
||||
while( m_time.wDay > m_monthdaycounts[ leap ][ m_time.wMonth ] ) {
|
||||
|
||||
m_time.wDay -= m_monthdaycounts[ leap ][ m_time.wMonth ];
|
||||
++m_time.wMonth;
|
||||
// unlikely but we might've entered a new year
|
||||
if( m_time.wMonth > 12 ) {
|
||||
|
||||
++m_time.wYear;
|
||||
leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 );
|
||||
m_time.wMonth -= 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
scenario_time::year_day( int Day, const int Month, const int Year ) const {
|
||||
|
||||
char const daytab[ 2 ][ 13 ] = {
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
int leap { ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ) };
|
||||
for( int i = 1; i < Month; ++i )
|
||||
Day += daytab[ leap ][ i ];
|
||||
|
||||
return Day;
|
||||
}
|
||||
|
||||
void
|
||||
scenario_time::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ) {
|
||||
|
||||
WORD daytab[ 2 ][ 13 ] = {
|
||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
|
||||
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
|
||||
};
|
||||
|
||||
int leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 );
|
||||
WORD idx = 1;
|
||||
while( ( idx < 13 ) && ( Yearday >= daytab[ leap ][ idx ] ) ) {
|
||||
|
||||
++idx;
|
||||
}
|
||||
Month = idx;
|
||||
Day = Yearday - daytab[ leap ][ idx - 1 ];
|
||||
}
|
||||
|
||||
int
|
||||
scenario_time::julian_day() const {
|
||||
|
||||
int yy = ( m_time.wYear < 0 ? m_time.wYear + 1 : m_time.wYear ) - std::floor( ( 12 - m_time.wMonth ) / 10.f );
|
||||
int mm = m_time.wMonth + 9;
|
||||
if( mm >= 12 ) { mm -= 12; }
|
||||
|
||||
int K1 = std::floor( 365.25 * ( yy + 4712 ) );
|
||||
int K2 = std::floor( 30.6 * mm + 0.5 );
|
||||
|
||||
// for dates in Julian calendar
|
||||
int JD = K1 + K2 + m_time.wDay + 59;
|
||||
// for dates in Gregorian calendar; 2299160 is October 15th, 1582
|
||||
const int gregorianswitchday = 2299160;
|
||||
if( JD > gregorianswitchday ) {
|
||||
|
||||
int K3 = std::floor( std::floor( ( yy * 0.01 ) + 49 ) * 0.75 ) - 38;
|
||||
JD -= K3;
|
||||
}
|
||||
|
||||
return JD;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
66
simulationtime.h
Normal file
66
simulationtime.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
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
|
||||
|
||||
// wrapper for scenario time
|
||||
class scenario_time {
|
||||
|
||||
public:
|
||||
scenario_time() {
|
||||
m_time.wHour = 10; m_time.wMinute = 30; }
|
||||
void
|
||||
init();
|
||||
void
|
||||
update( double const Deltatime );
|
||||
inline
|
||||
SYSTEMTIME &
|
||||
data() {
|
||||
return m_time; }
|
||||
inline
|
||||
SYSTEMTIME const &
|
||||
data() const {
|
||||
return m_time; }
|
||||
inline
|
||||
double
|
||||
second() const {
|
||||
return ( m_time.wMilliseconds * 0.001 + m_time.wSecond ); }
|
||||
inline
|
||||
int
|
||||
year_day() const {
|
||||
return m_yearday; }
|
||||
// helper, calculates day of year from given date
|
||||
int
|
||||
year_day( int Day, int const Month, int const Year ) const;
|
||||
int
|
||||
julian_day() const;
|
||||
inline
|
||||
double
|
||||
zone_bias() const {
|
||||
return m_timezonebias; }
|
||||
|
||||
private:
|
||||
// calculates day and month from given day of year
|
||||
void
|
||||
daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday );
|
||||
|
||||
SYSTEMTIME m_time;
|
||||
double m_milliseconds{ 0.0 };
|
||||
int m_yearday;
|
||||
char m_monthdaycounts[ 2 ][ 13 ];
|
||||
double m_timezonebias{ 0.0 };
|
||||
};
|
||||
|
||||
namespace simulation {
|
||||
|
||||
extern scenario_time Time;
|
||||
|
||||
} // simulation
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
2
sky.h
2
sky.h
@@ -14,7 +14,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
class TSky {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
TSky() = default;
|
||||
|
||||
2
stars.h
2
stars.h
@@ -8,7 +8,7 @@
|
||||
|
||||
class cStars {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
// types:
|
||||
|
||||
@@ -13,6 +13,12 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "dynobj.h"
|
||||
#include "mtable.h"
|
||||
|
||||
namespace simulation {
|
||||
|
||||
basic_station Station;
|
||||
|
||||
}
|
||||
|
||||
// exchanges load with consist attached to specified vehicle, operating on specified schedule
|
||||
double
|
||||
basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule, int const Platform ) {
|
||||
|
||||
@@ -19,4 +19,10 @@ public:
|
||||
// exchanges load with consist attached to specified vehicle, operating on specified schedule; returns: time needed for exchange, in seconds
|
||||
double
|
||||
update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule, int const Platform );
|
||||
};
|
||||
};
|
||||
|
||||
namespace simulation {
|
||||
|
||||
extern basic_station Station; // temporary object, for station functionality tests
|
||||
|
||||
} // simulation
|
||||
|
||||
2
sun.cpp
2
sun.cpp
@@ -4,7 +4,7 @@
|
||||
#include "globals.h"
|
||||
#include "mtable.h"
|
||||
#include "utilities.h"
|
||||
#include "world.h"
|
||||
#include "simulationtime.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSun -- class responsible for dynamic calculation of position and intensity of the Sun,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "globals.h"
|
||||
#include "translation.h"
|
||||
#include "simulation.h"
|
||||
#include "simulationtime.h"
|
||||
#include "mtable.h"
|
||||
#include "train.h"
|
||||
#include "sceneeditor.h"
|
||||
|
||||
@@ -257,18 +257,24 @@ int stol_def(const std::string &str, const int &DefaultValue) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ToLower(std::string const &text)
|
||||
{
|
||||
std::string lowercase( text );
|
||||
std::transform(text.begin(), text.end(), lowercase.begin(), ::tolower);
|
||||
std::string ToLower(std::string const &text) {
|
||||
|
||||
auto lowercase { text };
|
||||
std::transform(
|
||||
std::begin( text ), std::end( text ),
|
||||
std::begin( lowercase ),
|
||||
[]( unsigned char c ) { return std::tolower( c ); } );
|
||||
return lowercase;
|
||||
}
|
||||
|
||||
std::string ToUpper(std::string const &text)
|
||||
{
|
||||
std::string uppercase( text );
|
||||
std::transform(text.begin(), text.end(), uppercase.begin(), ::toupper);
|
||||
return uppercase;
|
||||
std::string ToUpper(std::string const &text) {
|
||||
|
||||
auto uppercase { text };
|
||||
std::transform(
|
||||
std::begin( text ), std::end( text ),
|
||||
std::begin( uppercase ),
|
||||
[]( unsigned char c ) { return std::toupper( c ); } );
|
||||
return uppercase;
|
||||
}
|
||||
|
||||
// replaces polish letters with basic ascii
|
||||
|
||||
@@ -50,7 +50,6 @@ LONG CALLBACK unhandled_handler(::EXCEPTION_POINTERS* e)
|
||||
HWND Hwnd;
|
||||
WNDPROC BaseWindowProc;
|
||||
PCOPYDATASTRUCT pDane;
|
||||
extern TWorld World;
|
||||
|
||||
LRESULT APIENTRY WndProc( HWND hWnd, // handle for this window
|
||||
UINT uMsg, // message for this window
|
||||
|
||||
Reference in New Issue
Block a user