From 4af6f57cc32a3c57ef739bbb9c85eb95dad1edca Mon Sep 17 00:00:00 2001 From: Kamil Lewan Date: Sun, 14 Oct 2018 00:04:51 +0200 Subject: [PATCH 1/8] Add settings struct to `renderer`. --- renderer.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/renderer.h b/renderer.h index 0f82e3c3..ab2df34b 100644 --- a/renderer.h +++ b/renderer.h @@ -115,6 +115,12 @@ class opengl_renderer { public: // types + /// Renderer runtime settings. + struct Settings + { + /** Force normal render of traction, when user is in debug mode. */ + bool force_normal_traction_render { false }; + } settings; // constructors opengl_renderer() = default; // destructor From b21ebd80b3f4bcddf45106e73ff8019af4b0a740 Mon Sep 17 00:00:00 2001 From: Kamil Lewan Date: Sat, 13 Oct 2018 23:09:23 +0200 Subject: [PATCH 2/8] Traction wire depends on renderer settings. --- Traction.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Traction.cpp b/Traction.cpp index 82153f60..9a652e31 100644 --- a/Traction.cpp +++ b/Traction.cpp @@ -531,7 +531,8 @@ glm::vec3 TTraction::wire_color() const { glm::vec3 color; - if( false == DebugModeFlag ) { + if( !DebugModeFlag || GfxRenderer.settings.force_normal_traction_render ) + { switch( Material ) { // Ra: kolory podzieliłem przez 2, bo po zmianie ambient za jasne były // trzeba uwzględnić kierunek świecenia Słońca - tylko ze Słońcem widać kolor case 1: { From b81e9e30feb54f192b5bdf1bdcf43501c185d46e Mon Sep 17 00:00:00 2001 From: Kamil Lewan Date: Sat, 13 Oct 2018 23:41:45 +0200 Subject: [PATCH 3/8] Add checkbox in debug pannel. - checkbox to force normal render mode of traction. --- driveruipanels.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 0c9b6605..02e32885 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -362,6 +362,14 @@ debug_panel::render() { // toggles ImGui::Separator(); ImGui::Checkbox( "Debug Mode", &DebugModeFlag ); + if( DebugModeFlag ) + { + ImGui::Indent(); + ImGui::Checkbox( + "Draw normal traction", + &GfxRenderer.settings.force_normal_traction_render ); + ImGui::Unindent(); + } } ImGui::End(); } From 753cf7ee5d918320112ca71fe2942e3c68bd5ea4 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 23 Jan 2019 19:38:59 +0100 Subject: [PATCH 4/8] refactoring: python task data creation moved to the task queue worker --- PyInt.cpp | 24 ++++--- PyInt.h | 27 +++++-- Texture.cpp | 22 +++--- Train.cpp | 184 +++++++++++++++++++++++------------------------- Train.h | 2 +- application.cpp | 8 ++- 6 files changed, 144 insertions(+), 123 deletions(-) diff --git a/PyInt.cpp b/PyInt.cpp index 6765d7b4..6ee0891f 100644 --- a/PyInt.cpp +++ b/PyInt.cpp @@ -16,9 +16,18 @@ http://mozilla.org/MPL/2.0/. #include "Logs.h" void render_task::run() { + + // convert provided input to a python dictionary + auto *input = PyDict_New(); + if( input == nullptr ) { goto exit; } + for( auto const &datapair : m_input->floats ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetFloat( datapair.second ) ); } + for( auto const &datapair : m_input->integers ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetInt( datapair.second ) ); } + for( auto const &datapair : m_input->bools ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetBool( datapair.second ) ); } + for( auto const &datapair : m_input->strings ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetString( datapair.second.c_str() ) ); } + // call the renderer - auto *output { PyObject_CallMethod( m_renderer, "render", "O", m_input ) }; - Py_DECREF( m_input ); + auto *output { PyObject_CallMethod( m_renderer, "render", "O", input ) }; + Py_DECREF( input ); if( output != nullptr ) { auto *outputwidth { PyObject_CallMethod( m_renderer, "get_width", nullptr ) }; @@ -48,13 +57,16 @@ void render_task::run() { if( outputwidth != nullptr ) { Py_DECREF( outputwidth ); } Py_DECREF( output ); } + +exit: // clean up after yourself + delete m_input; delete this; } void render_task::cancel() { - Py_DECREF( m_input ); + delete m_input; delete this; } @@ -158,11 +170,7 @@ auto python_taskqueue::insert( task_request const &Task ) -> bool { for( auto &task : m_tasks.data ) { if( task->target() == Task.target ) { // replace pending task in the slot with the more recent one - acquire_lock(); - { - task->cancel(); - } - release_lock(); + task->cancel(); task = newtask; newtaskinserted = true; break; diff --git a/PyInt.h b/PyInt.h index f03f931b..db097d9b 100644 --- a/PyInt.h +++ b/PyInt.h @@ -18,18 +18,35 @@ http://mozilla.org/MPL/2.0/. #endif #include "Classes.h" -#define PyGetFloat(param) PyFloat_FromDouble(param >= 0 ? param : -param) -#define PyGetFloatS(param) PyFloat_FromDouble(param) +#define PyGetFloat(param) PyFloat_FromDouble(param) #define PyGetInt(param) PyInt_FromLong(param) #define PyGetBool(param) param ? Py_True : Py_False #define PyGetString(param) PyString_FromString(param) +// collection of keyword-value pairs +// NOTE: since our python dictionary operates on a few types, most of the class was hardcoded for simplicity +struct dictionary_source { +// types + template + using keyvaluepair_sequence = std::vector>; +// members + keyvaluepair_sequence floats; + keyvaluepair_sequence integers; + keyvaluepair_sequence bools; + keyvaluepair_sequence strings; +// methods + inline void insert( std::string const &Key, double const Value ) { floats.emplace_back( Key, Value ); } + inline void insert( std::string const &Key, int const Value ) { integers.emplace_back( Key, Value ); } + inline void insert( std::string const &Key, bool const Value ) { bools.emplace_back( Key, Value ); } + inline void insert( std::string const &Key, std::string const Value ) { strings.emplace_back( Key, Value ); } +}; + // TODO: extract common base and inherit specialization from it class render_task { public: // constructors - render_task( PyObject *Renderer, PyObject *Input, GLuint Target ) : + render_task( PyObject *Renderer, dictionary_source *Input, GLuint Target ) : m_renderer( Renderer ), m_input( Input ), m_target( Target ) {} // methods @@ -40,7 +57,7 @@ public: private: // members PyObject *m_renderer {nullptr}; - PyObject *m_input { nullptr }; + dictionary_source *m_input { nullptr }; GLuint m_target { 0 }; }; @@ -53,7 +70,7 @@ public: struct task_request { std::string const &renderer; - PyObject *input; + dictionary_source *input; GLuint target; }; // constructors diff --git a/Texture.cpp b/Texture.cpp index 0bd13502..e21893bc 100644 --- a/Texture.cpp +++ b/Texture.cpp @@ -98,23 +98,17 @@ opengl_texture::make_request() { auto const components { Split( name, '?' ) }; auto const query { Split( components.back(), '&' ) }; - PyObject *pythondictionary { nullptr }; - Application.acquire_python_lock(); - { - pythondictionary = PyDict_New(); - if( pythondictionary != nullptr ) { - for( auto const &querypair : query ) { - auto const valuepos { querypair.find( '=' ) }; - PyDict_SetItemString( - pythondictionary, - ToLower( querypair.substr( 0, valuepos ) ).c_str(), - PyGetString( querypair.substr( valuepos + 1 ).c_str() ) ); - } + auto *dictionary { new dictionary_source }; + if( dictionary != nullptr ) { + for( auto const &querypair : query ) { + auto const valuepos { querypair.find( '=' ) }; + dictionary->insert( + ToLower( querypair.substr( 0, valuepos ) ), + querypair.substr( valuepos + 1 ) ); } } - Application.release_python_lock(); - Application.request( { ToLower( components.front() ), pythondictionary, id } ); + Application.request( { ToLower( components.front() ), dictionary, id } ); } void diff --git a/Train.cpp b/Train.cpp index c9479341..35c317c1 100644 --- a/Train.cpp +++ b/Train.cpp @@ -432,36 +432,33 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d) return true; } -PyObject *TTrain::GetTrainState() { +dictionary_source *TTrain::GetTrainState() { auto const *mover = DynamicObject->MoverParameters; - Application.acquire_python_lock(); - auto *dict = PyDict_New(); - if( ( dict == nullptr ) - || ( mover == nullptr ) ) { - Application.release_python_lock(); - return nullptr; - } + if( mover == nullptr ) { return nullptr; } - PyDict_SetItemString( dict, "name", PyGetString( DynamicObject->asName.c_str() ) ); - PyDict_SetItemString( dict, "cab", PyGetInt( mover->ActiveCab ) ); + auto *dict { new dictionary_source }; + if( dict == nullptr ) { return nullptr; } + + dict->insert( "name", DynamicObject->asName ); + dict->insert( "cab", mover->ActiveCab ); // basic systems state data - PyDict_SetItemString( dict, "battery", PyGetBool( mvControlled->Battery ) ); - PyDict_SetItemString( dict, "linebreaker", PyGetBool( mvControlled->Mains ) ); - PyDict_SetItemString( dict, "converter", PyGetBool( mvControlled->ConverterFlag ) ); - PyDict_SetItemString( dict, "converter_overload", PyGetBool( mvControlled->ConvOvldFlag ) ); - PyDict_SetItemString( dict, "compress", PyGetBool( mvControlled->CompressorFlag ) ); + dict->insert( "battery", mvControlled->Battery ); + dict->insert( "linebreaker", mvControlled->Mains ); + dict->insert( "converter", mvControlled->ConverterFlag ); + dict->insert( "converter_overload", mvControlled->ConvOvldFlag ); + dict->insert( "compress", mvControlled->CompressorFlag ); // reverser - PyDict_SetItemString( dict, "direction", PyGetInt( mover->ActiveDir ) ); + dict->insert( "direction", mover->ActiveDir ); // throttle - PyDict_SetItemString( dict, "mainctrl_pos", PyGetInt( mover->MainCtrlPos ) ); - PyDict_SetItemString( dict, "main_ctrl_actual_pos", PyGetInt( mover->MainCtrlActualPos ) ); - PyDict_SetItemString( dict, "scndctrl_pos", PyGetInt( mover->ScndCtrlPos ) ); - PyDict_SetItemString( dict, "scnd_ctrl_actual_pos", PyGetInt( mover->ScndCtrlActualPos ) ); + dict->insert( "mainctrl_pos", mover->MainCtrlPos ); + dict->insert( "main_ctrl_actual_pos", mover->MainCtrlActualPos ); + dict->insert( "scndctrl_pos", mover->ScndCtrlPos ); + dict->insert( "scnd_ctrl_actual_pos", mover->ScndCtrlActualPos ); // brakes - PyDict_SetItemString( dict, "manual_brake", PyGetBool( mvOccupied->ManualBrakePos > 0 ) ); + dict->insert( "manual_brake", ( mvOccupied->ManualBrakePos > 0 ) ); bool const bEP = ( mvControlled->LocHandle->GetCP() > 0.2 ) || ( fEIMParams[ 0 ][ 2 ] > 0.01 ); - PyDict_SetItemString( dict, "dir_brake", PyGetBool( bEP ) ); + dict->insert( "dir_brake", bEP ); bool bPN; if( ( typeid( *mvOccupied->Hamulec ) == typeid( TLSt ) ) || ( typeid( *mvOccupied->Hamulec ) == typeid( TEStED ) ) ) { @@ -471,114 +468,113 @@ PyObject *TTrain::GetTrainState() { } else bPN = false; - PyDict_SetItemString( dict, "indir_brake", PyGetBool( bPN ) ); - PyDict_SetItemString( dict, "brake_delay_flag", PyGetInt( mvOccupied->BrakeDelayFlag )); - PyDict_SetItemString( dict, "brake_op_mode_flag", PyGetInt( mvOccupied->BrakeOpModeFlag )); + dict->insert( "indir_brake", bPN ); + dict->insert( "brake_delay_flag", mvOccupied->BrakeDelayFlag ); + dict->insert( "brake_op_mode_flag", mvOccupied->BrakeOpModeFlag ); // other controls - PyDict_SetItemString( dict, "ca", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) ) ); - PyDict_SetItemString( dict, "shp", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ) ); - PyDict_SetItemString( dict, "pantpress", PyGetFloat( mvControlled->PantPress ) ); - PyDict_SetItemString( dict, "universal3", PyGetBool( InstrumentLightActive ) ); - PyDict_SetItemString( dict, "radio_channel", PyGetInt( iRadioChannel ) ); - PyDict_SetItemString( dict, "door_lock", PyGetInt( mvOccupied->DoorLockEnabled ) ); + dict->insert( "ca", TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) ); + dict->insert( "shp", TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ); + dict->insert( "pantpress", std::abs( mvControlled->PantPress ) ); + dict->insert( "universal3", InstrumentLightActive ); + dict->insert( "radio_channel", iRadioChannel ); + dict->insert( "door_lock", mvOccupied->DoorLockEnabled ); // movement data - PyDict_SetItemString( dict, "velocity", PyGetFloat( mover->Vel ) ); - PyDict_SetItemString( dict, "tractionforce", PyGetFloat( mover->Ft ) ); - PyDict_SetItemString( dict, "slipping_wheels", PyGetBool( mover->SlippingWheels ) ); - PyDict_SetItemString( dict, "sanding", PyGetBool( mover->SandDose ) ); + dict->insert( "velocity", std::abs( mover->Vel ) ); + dict->insert( "tractionforce", std::abs( mover->Ft ) ); + dict->insert( "slipping_wheels", mover->SlippingWheels ); + dict->insert( "sanding", mover->SandDose ); // electric current data - PyDict_SetItemString( dict, "traction_voltage", PyGetFloat( mvControlled->RunningTraction.TractionVoltage ) ); - PyDict_SetItemString( dict, "voltage", PyGetFloat( mvControlled->Voltage ) ); - PyDict_SetItemString( dict, "im", PyGetFloat( mvControlled->Im ) ); - PyDict_SetItemString( dict, "fuse", PyGetBool( mvControlled->FuseFlag ) ); - PyDict_SetItemString( dict, "epfuse", PyGetBool( mvOccupied->EpFuse ) ); + dict->insert( "traction_voltage", std::abs( mvControlled->RunningTraction.TractionVoltage ) ); + dict->insert( "voltage", std::abs( mvControlled->Voltage ) ); + dict->insert( "im", std::abs( mvControlled->Im ) ); + dict->insert( "fuse", mvControlled->FuseFlag ); + dict->insert( "epfuse", mvOccupied->EpFuse ); // induction motor state data char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" }; char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" }; char const *TXTP[ 3 ] = { "bc", "bp", "sp" }; for( int j = 0; j < 10; ++j ) - PyDict_SetItemString( dict, ( std::string( "eimp_t_" ) + std::string( TXTT[ j ] ) ).c_str(), PyGetFloatS( fEIMParams[ 0 ][ j ] ) ); + dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] ); for( int i = 0; i < 8; ++i ) { for( int j = 0; j < 10; ++j ) - PyDict_SetItemString( dict, ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ).c_str(), PyGetFloatS( fEIMParams[ i + 1 ][ j ] ) ); + dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] ); - PyDict_SetItemString( dict, ( "eimp_c" + std::to_string( i + 1 ) + "_ms" ).c_str(), PyGetBool( bMains[ i ] ) ); - PyDict_SetItemString( dict, ( "eimp_c" + std::to_string( i + 1 ) + "_cv" ).c_str(), PyGetFloatS( fCntVol[ i ] ) ); - PyDict_SetItemString( dict, ( "eimp_u" + std::to_string( i + 1 ) + "_pf" ).c_str(), PyGetBool( bPants[ i ][ 0 ] ) ); - PyDict_SetItemString( dict, ( "eimp_u" + std::to_string( i + 1 ) + "_pr" ).c_str(), PyGetBool( bPants[ i ][ 1 ] ) ); - PyDict_SetItemString( dict, ( "eimp_c" + std::to_string( i + 1 ) + "_fuse" ).c_str(), PyGetBool( bFuse[ i ] ) ); - PyDict_SetItemString( dict, ( "eimp_c" + std::to_string( i + 1 ) + "_batt" ).c_str(), PyGetBool( bBatt[ i ] ) ); - PyDict_SetItemString( dict, ( "eimp_c" + std::to_string( i + 1 ) + "_conv" ).c_str(), PyGetBool( bConv[ i ] ) ); - PyDict_SetItemString( dict, ( "eimp_u" + std::to_string( i + 1 ) + "_comp_a" ).c_str(), PyGetBool( bComp[ i ][ 0 ] ) ); - PyDict_SetItemString( dict, ( "eimp_u" + std::to_string( i + 1 ) + "_comp_w" ).c_str(), PyGetBool( bComp[ i ][ 1 ] ) ); - PyDict_SetItemString( dict, ( "eimp_c" + std::to_string( i + 1 ) + "_heat" ).c_str(), PyGetBool( bHeat[ i ] ) ); + dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_ms" ), bMains[ i ] ); + dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_cv" ), fCntVol[ i ] ); + dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pf" ), bPants[ i ][ 0 ] ); + dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pr" ), bPants[ i ][ 1 ] ); + dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_fuse" ), bFuse[ i ] ); + dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_batt" ), bBatt[ i ] ); + dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_conv" ), bConv[ i ] ); + dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_comp_a" ), bComp[ i ][ 0 ] ); + dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_comp_w" ), bComp[ i ][ 1 ] ); + dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_heat" ), bHeat[ i ] ); } for( int i = 0; i < 20; ++i ) { - for( int j = 0; j < 3; ++j ) - PyDict_SetItemString( dict, ( "eimp_pn" + std::to_string( i + 1 ) + "_" + TXTP[ j ] ).c_str(), - PyGetFloatS( fPress[ i ][ j ] ) ); + for( int j = 0; j < 3; ++j ) { + dict->insert( ( "eimp_pn" + std::to_string( i + 1 ) + "_" + TXTP[ j ] ), fPress[ i ][ j ] ); + } } // multi-unit state data - PyDict_SetItemString( dict, "car_no", PyGetInt( iCarNo ) ); - PyDict_SetItemString( dict, "power_no", PyGetInt( iPowerNo ) ); - PyDict_SetItemString( dict, "unit_no", PyGetInt( iUnitNo ) ); + dict->insert( "car_no", iCarNo ); + dict->insert( "power_no", iPowerNo ); + dict->insert( "unit_no", iUnitNo ); for( int i = 0; i < 20; i++ ) { - PyDict_SetItemString( dict, ( "doors_" + std::to_string( i + 1 ) ).c_str(), PyGetBool( bDoors[ i ][ 0 ] ) ); - PyDict_SetItemString( dict, ( "doors_r_" + std::to_string( i + 1 ) ).c_str(), PyGetBool( bDoors[ i ][ 1 ] ) ); - PyDict_SetItemString( dict, ( "doors_l_" + std::to_string( i + 1 ) ).c_str(), PyGetBool( bDoors[ i ][ 2 ] ) ); - PyDict_SetItemString( dict, ( "doors_no_" + std::to_string( i + 1 ) ).c_str(), PyGetInt( iDoorNo[ i ] ) ); - PyDict_SetItemString( dict, ( "code_" + std::to_string( i + 1 ) ).c_str(), PyGetString( ( std::to_string( iUnits[ i ] ) + cCode[ i ] ).c_str() ) ); - PyDict_SetItemString( dict, ( "car_name" + std::to_string( i + 1 ) ).c_str(), PyGetString( asCarName[ i ].c_str() ) ); - PyDict_SetItemString( dict, ( "slip_" + std::to_string( i + 1 ) ).c_str(), PyGetBool( bSlip[ i ] ) ); + dict->insert( ( "doors_" + std::to_string( i + 1 ) ), bDoors[ i ][ 0 ] ); + dict->insert( ( "doors_r_" + std::to_string( i + 1 ) ), bDoors[ i ][ 1 ] ); + dict->insert( ( "doors_l_" + std::to_string( i + 1 ) ), bDoors[ i ][ 2 ] ); + dict->insert( ( "doors_no_" + std::to_string( i + 1 ) ), iDoorNo[ i ] ); + dict->insert( ( "code_" + std::to_string( i + 1 ) ), ( std::to_string( iUnits[ i ] ) + cCode[ i ] ) ); + dict->insert( ( "car_name" + std::to_string( i + 1 ) ), asCarName[ i ] ); + dict->insert( ( "slip_" + std::to_string( i + 1 ) ), bSlip[ i ] ); } // ai state data auto const *driver = DynamicObject->Mechanik; - PyDict_SetItemString( dict, "velocity_desired", PyGetFloat( driver->VelDesired ) ); - PyDict_SetItemString( dict, "velroad", PyGetFloat( driver->VelRoad ) ); - PyDict_SetItemString( dict, "vellimitlast", PyGetFloat( driver->VelLimitLast ) ); - PyDict_SetItemString( dict, "velsignallast", PyGetFloat( driver->VelSignalLast ) ); - PyDict_SetItemString( dict, "velsignalnext", PyGetFloat( driver->VelSignalNext ) ); - PyDict_SetItemString( dict, "velnext", PyGetFloat( driver->VelNext ) ); - PyDict_SetItemString( dict, "actualproximitydist", PyGetFloat( driver->ActualProximityDist ) ); + dict->insert( "velocity_desired", driver->VelDesired ); + dict->insert( "velroad", driver->VelRoad ); + dict->insert( "vellimitlast", driver->VelLimitLast ); + dict->insert( "velsignallast", driver->VelSignalLast ); + dict->insert( "velsignalnext", driver->VelSignalNext ); + dict->insert( "velnext", driver->VelNext ); + dict->insert( "actualproximitydist", driver->ActualProximityDist ); // train data auto const *timetable{ driver->TrainTimetable() }; - PyDict_SetItemString( dict, "trainnumber", PyGetString( driver->TrainName().c_str() ) ); - PyDict_SetItemString( dict, "train_brakingmassratio", PyGetFloat( timetable->BrakeRatio ) ); - PyDict_SetItemString( dict, "train_enginetype", PyGetString( timetable->LocSeries.c_str() ) ); - PyDict_SetItemString( dict, "train_engineload", PyGetFloat( timetable->LocLoad ) ); + dict->insert( "trainnumber", driver->TrainName() ); + dict->insert( "train_brakingmassratio", timetable->BrakeRatio ); + dict->insert( "train_enginetype", timetable->LocSeries ); + dict->insert( "train_engineload", timetable->LocLoad ); - PyDict_SetItemString( dict, "train_stationindex", PyGetInt( driver->iStationStart ) ); + dict->insert( "train_stationindex", driver->iStationStart ); auto const stationcount { driver->StationCount() }; - PyDict_SetItemString( dict, "train_stationcount", PyGetInt( stationcount ) ); + dict->insert( "train_stationcount", stationcount ); if( stationcount > 0 ) { // timetable stations data, if there's any for( auto stationidx = 1; stationidx <= stationcount; ++stationidx ) { auto const stationlabel { "train_station" + std::to_string( stationidx ) + "_" }; auto const &timetableline { timetable->TimeTable[ stationidx ] }; - PyDict_SetItemString( dict, ( stationlabel + "name" ).c_str(), PyGetString( Bezogonkow( timetableline.StationName ).c_str() ) ); - PyDict_SetItemString( dict, ( stationlabel + "fclt" ).c_str(), PyGetString( Bezogonkow( timetableline.StationWare ).c_str() ) ); - PyDict_SetItemString( dict, ( stationlabel + "lctn" ).c_str(), PyGetFloat( timetableline.km ) ); - PyDict_SetItemString( dict, ( stationlabel + "vmax" ).c_str(), PyGetInt( timetableline.vmax ) ); - PyDict_SetItemString( dict, ( stationlabel + "ah" ).c_str(), PyGetInt( timetableline.Ah ) ); - PyDict_SetItemString( dict, ( stationlabel + "am" ).c_str(), PyGetInt( timetableline.Am ) ); - PyDict_SetItemString( dict, ( stationlabel + "dh" ).c_str(), PyGetInt( timetableline.Dh ) ); - PyDict_SetItemString( dict, ( stationlabel + "dm" ).c_str(), PyGetInt( timetableline.Dm ) ); + dict->insert( ( stationlabel + "name" ), Bezogonkow( timetableline.StationName ) ); + dict->insert( ( stationlabel + "fclt" ), Bezogonkow( timetableline.StationWare ) ); + dict->insert( ( stationlabel + "lctn" ), timetableline.km ); + dict->insert( ( stationlabel + "vmax" ), timetableline.vmax ); + dict->insert( ( stationlabel + "ah" ), timetableline.Ah ); + dict->insert( ( stationlabel + "am" ), timetableline.Am ); + dict->insert( ( stationlabel + "dh" ), timetableline.Dh ); + dict->insert( ( stationlabel + "dm" ), timetableline.Dm ); } } - PyDict_SetItemString( dict, "train_atpassengerstop", PyGetBool( driver->IsAtPassengerStop ) ); + dict->insert( "train_atpassengerstop", driver->IsAtPassengerStop ); // world state data - PyDict_SetItemString( dict, "scenario", PyGetString( Global.SceneryFile.c_str() ) ); - PyDict_SetItemString( dict, "hours", PyGetInt( simulation::Time.data().wHour ) ); - PyDict_SetItemString( dict, "minutes", PyGetInt( simulation::Time.data().wMinute ) ); - PyDict_SetItemString( dict, "seconds", PyGetInt( simulation::Time.second() ) ); - PyDict_SetItemString( dict, "air_temperature", PyGetInt( Global.AirTemperature ) ); - PyDict_SetItemString( dict, "light_level", PyGetFloat( Global.fLuminance - std::max( 0.f, Global.Overcast - 1.f ) ) ); + dict->insert( "scenario", Global.SceneryFile ); + dict->insert( "hours", static_cast( simulation::Time.data().wHour ) ); + dict->insert( "minutes", static_cast( simulation::Time.data().wMinute ) ); + dict->insert( "seconds", static_cast( simulation::Time.second() ) ); + dict->insert( "air_temperature", Global.AirTemperature ); + dict->insert( "light_level", Global.fLuminance - std::max( 0.f, Global.Overcast - 1.f ) ); - Application.release_python_lock(); return dict; } diff --git a/Train.h b/Train.h index a398ec20..988982c9 100644 --- a/Train.h +++ b/Train.h @@ -114,7 +114,7 @@ class TTrain void SetLights(); // McZapkie-310302: ladowanie parametrow z pliku bool LoadMMediaFile(std::string const &asFileName); - PyObject *GetTrainState(); + dictionary_source *GetTrainState(); state_t get_state() const; private: diff --git a/application.cpp b/application.cpp index 6fe6552f..4bab5455 100644 --- a/application.cpp +++ b/application.cpp @@ -155,7 +155,13 @@ eu07_application::run() { bool eu07_application::request( python_taskqueue::task_request const &Task ) { - return m_taskqueue.insert( Task ); + auto const result { m_taskqueue.insert( Task ) }; + if( ( false == result ) + && ( Task.input != nullptr ) ) { + // clean up allocated resources since the worker won't + delete Task.input; + } + return result; } // ensures the main thread holds the python gil and can safely execute python calls From 22c32b0119e60b4cb53a1a1e347bc389d00ed793 Mon Sep 17 00:00:00 2001 From: milek7 Date: Sun, 27 Jan 2019 13:00:24 +0100 Subject: [PATCH 5/8] apply lerp also to walk speed --- Camera.cpp | 12 +++++++++--- keyboardinput.cpp | 6 +++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Camera.cpp b/Camera.cpp index 28405e8a..7a09b48a 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -73,10 +73,14 @@ TCamera::OnCommand( command_data const &Command ) { 30.0 : 1.0 ); + // threshold position on stick between walk lerp and walk/run lerp + auto const stickthreshold = 2.0 / 3.0; + // left-right auto const movexparam { Command.param1 }; - // 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed - auto const movex { walkspeed + ( std::max( 0.0, std::abs( movexparam ) - 0.65 ) / 0.35 ) * std::max( 0.0, movespeed - walkspeed ) }; + // 2/3rd of the stick range lerps walk speed, past that we lerp between max walk and run speed + auto const movex { walkspeed * std::min(std::abs(movexparam) * (1.0 / stickthreshold), 1.0) + + ( std::max( 0.0, std::abs( movexparam ) - stickthreshold ) / (1.0 - stickthreshold) ) * std::max( 0.0, movespeed - walkspeed ) }; m_moverate.x = ( movexparam > 0.0 ? movex * speedmultiplier : @@ -85,7 +89,9 @@ TCamera::OnCommand( command_data const &Command ) { // forward-back double const movezparam { Command.param2 }; - auto const movez { walkspeed + ( std::max( 0.0, std::abs( movezparam ) - 0.65 ) / 0.35 ) * std::max( 0.0, movespeed - walkspeed ) }; + auto const movez { walkspeed * std::min(std::abs(movezparam) * (1.0 / stickthreshold), 1.0) + + ( std::max( 0.0, std::abs( movezparam ) - stickthreshold ) / (1.0 - stickthreshold) ) * std::max( 0.0, movespeed - walkspeed ) }; + // NOTE: z-axis is flipped given world coordinate system m_moverate.z = ( movezparam > 0.0 ? -movez * speedmultiplier : diff --git a/keyboardinput.cpp b/keyboardinput.cpp index dcb79db2..d405af34 100644 --- a/keyboardinput.cpp +++ b/keyboardinput.cpp @@ -228,12 +228,12 @@ keyboard_input::poll() { glm::vec2 const movementhorizontal { // x-axis - ( Global.shiftState ? 1.f : 0.5f ) * + ( Global.shiftState ? 1.f : 0.66f ) * ( input::keys[ m_bindingscache.left ] != GLFW_RELEASE ? -1.f : input::keys[ m_bindingscache.right ] != GLFW_RELEASE ? 1.f : 0.f ), // z-axis - ( Global.shiftState ? 1.f : 0.5f ) * + ( Global.shiftState ? 1.f : 0.66f ) * ( input::keys[ m_bindingscache.forward ] != GLFW_RELEASE ? 1.f : input::keys[ m_bindingscache.back ] != GLFW_RELEASE ? -1.f : 0.f ) }; @@ -254,7 +254,7 @@ keyboard_input::poll() { float const movementvertical { // y-axis - ( Global.shiftState ? 1.f : 0.5f ) * + ( Global.shiftState ? 1.f : 0.66f ) * ( input::keys[ m_bindingscache.up ] != GLFW_RELEASE ? 1.f : input::keys[ m_bindingscache.down ] != GLFW_RELEASE ? -1.f : 0.f ) }; From 5f4ec676a6450ed646ace440ef4bee70fce7b8a5 Mon Sep 17 00:00:00 2001 From: milek7 Date: Sun, 27 Jan 2019 13:00:24 +0100 Subject: [PATCH 6/8] apply lerp also to walk speed --- Camera.cpp | 12 +++++++++--- keyboardinput.cpp | 6 +++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Camera.cpp b/Camera.cpp index 28405e8a..7a09b48a 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -73,10 +73,14 @@ TCamera::OnCommand( command_data const &Command ) { 30.0 : 1.0 ); + // threshold position on stick between walk lerp and walk/run lerp + auto const stickthreshold = 2.0 / 3.0; + // left-right auto const movexparam { Command.param1 }; - // 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed - auto const movex { walkspeed + ( std::max( 0.0, std::abs( movexparam ) - 0.65 ) / 0.35 ) * std::max( 0.0, movespeed - walkspeed ) }; + // 2/3rd of the stick range lerps walk speed, past that we lerp between max walk and run speed + auto const movex { walkspeed * std::min(std::abs(movexparam) * (1.0 / stickthreshold), 1.0) + + ( std::max( 0.0, std::abs( movexparam ) - stickthreshold ) / (1.0 - stickthreshold) ) * std::max( 0.0, movespeed - walkspeed ) }; m_moverate.x = ( movexparam > 0.0 ? movex * speedmultiplier : @@ -85,7 +89,9 @@ TCamera::OnCommand( command_data const &Command ) { // forward-back double const movezparam { Command.param2 }; - auto const movez { walkspeed + ( std::max( 0.0, std::abs( movezparam ) - 0.65 ) / 0.35 ) * std::max( 0.0, movespeed - walkspeed ) }; + auto const movez { walkspeed * std::min(std::abs(movezparam) * (1.0 / stickthreshold), 1.0) + + ( std::max( 0.0, std::abs( movezparam ) - stickthreshold ) / (1.0 - stickthreshold) ) * std::max( 0.0, movespeed - walkspeed ) }; + // NOTE: z-axis is flipped given world coordinate system m_moverate.z = ( movezparam > 0.0 ? -movez * speedmultiplier : diff --git a/keyboardinput.cpp b/keyboardinput.cpp index dcb79db2..a095c2fa 100644 --- a/keyboardinput.cpp +++ b/keyboardinput.cpp @@ -228,12 +228,12 @@ keyboard_input::poll() { glm::vec2 const movementhorizontal { // x-axis - ( Global.shiftState ? 1.f : 0.5f ) * + ( Global.shiftState ? 1.f : (2.0f / 3.0f) ) * ( input::keys[ m_bindingscache.left ] != GLFW_RELEASE ? -1.f : input::keys[ m_bindingscache.right ] != GLFW_RELEASE ? 1.f : 0.f ), // z-axis - ( Global.shiftState ? 1.f : 0.5f ) * + ( Global.shiftState ? 1.f : (2.0f / 3.0f) ) * ( input::keys[ m_bindingscache.forward ] != GLFW_RELEASE ? 1.f : input::keys[ m_bindingscache.back ] != GLFW_RELEASE ? -1.f : 0.f ) }; @@ -254,7 +254,7 @@ keyboard_input::poll() { float const movementvertical { // y-axis - ( Global.shiftState ? 1.f : 0.5f ) * + ( Global.shiftState ? 1.f : (2.0f / 3.0f) ) * ( input::keys[ m_bindingscache.up ] != GLFW_RELEASE ? 1.f : input::keys[ m_bindingscache.down ] != GLFW_RELEASE ? -1.f : 0.f ) }; From 0bf7238b0089068dee441e2b03559a6f6636c402 Mon Sep 17 00:00:00 2001 From: milek7 Date: Sun, 27 Jan 2019 21:10:41 +0100 Subject: [PATCH 7/8] walk lerping also for Y --- Camera.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Camera.cpp b/Camera.cpp index 7a09b48a..0d1c5c5b 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -47,6 +47,9 @@ TCamera::OnCommand( command_data const &Command ) { auto const walkspeed { 1.0 }; auto const runspeed { 10.0 }; + // threshold position on stick between walk lerp and walk/run lerp + auto const stickthreshold = 2.0 / 3.0; + bool iscameracommand { true }; switch( Command.command ) { @@ -73,9 +76,6 @@ TCamera::OnCommand( command_data const &Command ) { 30.0 : 1.0 ); - // threshold position on stick between walk lerp and walk/run lerp - auto const stickthreshold = 2.0 / 3.0; - // left-right auto const movexparam { Command.param1 }; // 2/3rd of the stick range lerps walk speed, past that we lerp between max walk and run speed @@ -117,8 +117,9 @@ TCamera::OnCommand( command_data const &Command ) { 1.0 ); // up-down auto const moveyparam { Command.param1 }; - // 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed - auto const movey { walkspeed + ( std::max( 0.0, std::abs( moveyparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) }; + // 2/3rd of the stick range lerps walk speed, past that we lerp between max walk and run speed + auto const movey { walkspeed * std::min(std::abs(moveyparam) * (1.0 / stickthreshold), 1.0) + + ( std::max( 0.0, std::abs( moveyparam ) - stickthreshold ) / (1.0 - stickthreshold) ) * std::max( 0.0, movespeed - walkspeed ) }; m_moverate.y = ( moveyparam > 0.0 ? movey * speedmultiplier : From 4dc7b3d3d0f1e0b2e943c7345bc12170fc8692f2 Mon Sep 17 00:00:00 2001 From: milek7 Date: Sun, 27 Jan 2019 21:53:15 +0100 Subject: [PATCH 8/8] fix: replace backslashes in TAnimModel parsing --- AnimModel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/AnimModel.cpp b/AnimModel.cpp index c01b88b9..46e1b0b7 100644 --- a/AnimModel.cpp +++ b/AnimModel.cpp @@ -447,6 +447,7 @@ bool TAnimModel::Load(cParser *parser, bool ter) std::string name = parser->getToken(); std::string texture = parser->getToken( false ); // tekstura (zmienia na małe) replace_slashes( name ); + replace_slashes( texture ); if (!Init( name, texture )) { if (name != "notload")