mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
refactoring: application mode code split
This commit is contained in:
303
application.cpp
303
application.cpp
@@ -9,14 +9,13 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "application.h"
|
||||
#include "scenarioloadermode.h"
|
||||
#include "drivermode.h"
|
||||
#include "editormode.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "keyboardinput.h"
|
||||
#include "mouseinput.h"
|
||||
#include "gamepadinput.h"
|
||||
#include "console.h"
|
||||
#include "simulation.h"
|
||||
#include "world.h"
|
||||
#include "train.h"
|
||||
#include "pyint.h"
|
||||
#include "sceneeditor.h"
|
||||
#include "renderer.h"
|
||||
@@ -45,17 +44,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
ui_layer uilayerstaticinitializer;
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C"
|
||||
@@ -71,6 +60,14 @@ extern WNDPROC BaseWindowProc;
|
||||
|
||||
// user input callbacks
|
||||
|
||||
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 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?
|
||||
@@ -81,101 +78,23 @@ void window_resize_callback( GLFWwindow *window, int w, int 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 );
|
||||
Application.on_cursor_pos( 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
|
||||
Application.on_mouse_button( button, action, mods );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
Application.on_scroll( xoffset, yoffset );
|
||||
}
|
||||
|
||||
void key_callback( GLFWwindow *window, int key, int scancode, int action, int mods ) {
|
||||
|
||||
Application.on_key( key, scancode, action, mods );
|
||||
}
|
||||
|
||||
// public:
|
||||
@@ -190,6 +109,12 @@ eu07_application::init( int Argc, char *Argv[] ) {
|
||||
if( ( result = init_settings( Argc, Argv ) ) != 0 ) {
|
||||
return result;
|
||||
}
|
||||
|
||||
WriteLog( "Starting MaSzyna rail vehicle simulator (release: " + Global.asVersion + ")" );
|
||||
WriteLog( "For online documentation and additional files refer to: http://eu07.pl" );
|
||||
WriteLog( "Authors: Marcin_EU, McZapkie, ABu, Winger, Tolaris, nbmx, OLO_EU, Bart, Quark-t, "
|
||||
"ShaXbee, Oli_EU, youBy, KURS90, Ra, hunter, szociu, Stele, Q, firleju and others\n" );
|
||||
|
||||
if( ( result = init_glfw() ) != 0 ) {
|
||||
return result;
|
||||
}
|
||||
@@ -200,6 +125,9 @@ eu07_application::init( int Argc, char *Argv[] ) {
|
||||
if( ( result = init_audio() ) != 0 ) {
|
||||
return result;
|
||||
}
|
||||
if( ( result = init_modes() ) != 0 ) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -207,56 +135,12 @@ eu07_application::init( int Argc, char *Argv[] ) {
|
||||
int
|
||||
eu07_application::run() {
|
||||
|
||||
// HACK: prevent mouse capture before simulation starts
|
||||
Global.ControlPicking = true;
|
||||
// TODO: move input sources and their initializations to the application mode member
|
||||
input::Keyboard.init();
|
||||
input::Mouse.init();
|
||||
input::Gamepad.init();
|
||||
if( true == Global.uart_conf.enable ) {
|
||||
input::uart = std::make_unique<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 );
|
||||
Global.ControlPicking = false;
|
||||
|
||||
// main application loop
|
||||
// TODO: split into parts and delegate these to application mode member
|
||||
while( ( false == glfwWindowShouldClose( m_window ) )
|
||||
&& ( true == World.Update() )
|
||||
&& ( false == m_modestack.empty() )
|
||||
&& ( true == m_modes[ m_modestack.top() ]->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;
|
||||
@@ -265,9 +149,7 @@ eu07_application::run() {
|
||||
void
|
||||
eu07_application::exit() {
|
||||
|
||||
#ifdef _WIN32
|
||||
Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej)
|
||||
#endif
|
||||
SafeDelete( simulation::Train );
|
||||
SafeDelete( simulation::Region );
|
||||
|
||||
glfwDestroyWindow( m_window );
|
||||
@@ -276,28 +158,103 @@ eu07_application::exit() {
|
||||
TPythonInterpreter::killInstance();
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::render_ui() {
|
||||
|
||||
if( m_modestack.empty() ) { return; }
|
||||
|
||||
m_modes[ m_modestack.top() ]->render_ui();
|
||||
}
|
||||
|
||||
bool
|
||||
eu07_application::pop_mode() {
|
||||
|
||||
if( m_modestack.empty() ) { return false; }
|
||||
|
||||
m_modes[ m_modestack.top() ]->exit();
|
||||
m_modestack.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
eu07_application::push_mode( eu07_application::mode const Mode ) {
|
||||
|
||||
if( Mode >= mode::count_ ) { return false; }
|
||||
|
||||
m_modes[ Mode ]->enter();
|
||||
m_modestack.push( Mode );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::set_title( std::string const &Title ) {
|
||||
|
||||
glfwSetWindowTitle( m_window, Title.c_str() );
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::set_progress( float const Progress, float const Subtaskprogress ) {
|
||||
|
||||
if( m_modestack.empty() ) { return; }
|
||||
|
||||
m_modes[ m_modestack.top() ]->set_progress( Progress, Subtaskprogress );
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::set_cursor( int const Mode ) {
|
||||
|
||||
UILayer.set_cursor( Mode );
|
||||
ui_layer::set_cursor( Mode );
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::set_cursor_pos( double const X, double const Y ) {
|
||||
eu07_application::set_cursor_pos( double const Horizontal, double const Vertical ) {
|
||||
|
||||
if( m_window != nullptr ) {
|
||||
glfwSetCursorPos( m_window, X, Y );
|
||||
glfwSetCursorPos( m_window, Horizontal, Vertical );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::get_cursor_pos( double &X, double &Y ) const {
|
||||
eu07_application::get_cursor_pos( double &Horizontal, double &Vertical ) const {
|
||||
|
||||
if( m_window != nullptr ) {
|
||||
glfwGetCursorPos( m_window, &X, &Y );
|
||||
glfwGetCursorPos( m_window, &Horizontal, &Vertical );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::on_key( int const Key, int const Scancode, int const Action, int const Mods ) {
|
||||
|
||||
if( m_modestack.empty() ) { return; }
|
||||
|
||||
m_modes[ m_modestack.top() ]->on_key( Key, Scancode, Action, Mods );
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::on_cursor_pos( double const Horizontal, double const Vertical ) {
|
||||
|
||||
if( m_modestack.empty() ) { return; }
|
||||
|
||||
m_modes[ m_modestack.top() ]->on_cursor_pos( Horizontal, Vertical );
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::on_mouse_button( int const Button, int const Action, int const Mods ) {
|
||||
|
||||
if( m_modestack.empty() ) { return; }
|
||||
|
||||
m_modes[ m_modestack.top() ]->on_mouse_button( Button, Action, Mods );
|
||||
}
|
||||
|
||||
void
|
||||
eu07_application::on_scroll( double const Xoffset, double const Yoffset ) {
|
||||
|
||||
if( m_modestack.empty() ) { return; }
|
||||
|
||||
m_modes[ m_modestack.top() ]->on_scroll( Xoffset, Yoffset );
|
||||
}
|
||||
|
||||
// private:
|
||||
|
||||
void
|
||||
@@ -385,13 +342,7 @@ eu07_application::init_settings( int Argc, char *Argv[] ) {
|
||||
|
||||
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( token == "-s" ) {
|
||||
if( i + 1 < Argc ) {
|
||||
Global.SceneryFile = ToLower( Argv[ ++i ] );
|
||||
}
|
||||
@@ -406,7 +357,6 @@ eu07_application::init_settings( int Argc, char *Argv[] ) {
|
||||
<< "usage: " << std::string( Argv[ 0 ] )
|
||||
<< " [-s sceneryfilepath]"
|
||||
<< " [-v vehiclename]"
|
||||
<< " [-e3d]"
|
||||
<< std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -468,7 +418,6 @@ eu07_application::init_glfw() {
|
||||
// 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;
|
||||
@@ -499,7 +448,7 @@ eu07_application::init_gfx() {
|
||||
}
|
||||
|
||||
if( ( false == GfxRenderer.Init( m_window ) )
|
||||
|| ( false == UILayer.init( m_window ) ) ) {
|
||||
|| ( false == ui_layer::init( m_window ) ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -515,3 +464,25 @@ eu07_application::init_audio() {
|
||||
// NOTE: lack of audio isn't deemed a failure serious enough to throw in the towel
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eu07_application::init_modes() {
|
||||
|
||||
// NOTE: we could delay creation/initialization until transition to specific mode is requested,
|
||||
// but doing it in one go at the start saves us some error checking headache down the road
|
||||
|
||||
// create all application behaviour modes
|
||||
m_modes[ mode::scenarioloader ] = std::make_shared<scenarioloader_mode>();
|
||||
m_modes[ mode::driver ] = std::make_shared<driver_mode>();
|
||||
m_modes[ mode::editor ] = std::make_shared<editor_mode>();
|
||||
// initialize the mode objects
|
||||
for( auto &mode : m_modes ) {
|
||||
if( false == mode->init() ) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// activate the default mode
|
||||
push_mode( mode::scenarioloader );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user