From e99dc9a02ca4d74c395443b0774144c23066e3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Thu, 4 Apr 2019 22:10:56 +0200 Subject: [PATCH 01/24] AI is able to use MHZ_K8P now --- Driver.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Driver.cpp b/Driver.cpp index 09996138..f9b7df0b 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3443,6 +3443,21 @@ void TController::SetTimeControllers() mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_NP)); } if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a) mvOccupied->BrakeLevelSet(BrakeCtrlPosition); + if (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P) + { + if (BrakeCtrlPosition == 0) + mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_RP)); + else if (BrakeCtrlPosition == -1) + mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_FS)); + else if (BrakeCtrlPosition == -2) + mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_NP)); + else if (BrakeCtrlPosition > 4.5) + mvOccupied->BrakeLevelSet(10); + else if (BrakeCtrlPosition > 3.70) + mvOccupied->BrakeLevelSet(9); + else + mvOccupied->BrakeLevelSet(round((BrakeCtrlPosition * 0.4 - 0.1) / 0.15)); + } } //2. Check the type of Secondary Brake Handle From b9807284fc8d7179e18bd4e798e45ab82539f060 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sat, 6 Apr 2019 22:25:12 +0200 Subject: [PATCH 02/24] build 190405. autonomous vehicle door mode, door permit cab control type support, random fog range, global light level driven vehicle interior lighting, ogg vorbis multichannel file decoding fix --- Driver.cpp | 11 ++--- Globals.h | 1 - McZapkie/Mover.cpp | 13 +++--- Train.cpp | 75 +++++++++++++++++++++++++++-------- audio.cpp | 12 +++--- drivermouseinput.cpp | 2 +- renderer.cpp | 50 ++++++++++++----------- simulationstateserializer.cpp | 22 ++++++---- version.h | 2 +- 9 files changed, 119 insertions(+), 69 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index f9b7df0b..a082ac18 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3585,13 +3585,14 @@ void TController::Doors( bool const Open, int const Side ) { || ( false == AIControllFlag ) ) ) { // ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things if( ( pVehicle->MoverParameters->Doors.close_control == control_t::conductor ) - || ( ( true == AIControllFlag ) - && ( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver ) - || ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) ) ) { + || ( ( true == AIControllFlag ) ) ) { // if the door are controlled by the driver, we let the user operate them unless this user is an ai // the train conductor, if present, handles door operation also for human-driven trains - pVehicle->MoverParameters->OperateDoors( side::right, false ); - pVehicle->MoverParameters->OperateDoors( side::left, false ); + if( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver ) + || ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) { + pVehicle->MoverParameters->OperateDoors( side::right, false ); + pVehicle->MoverParameters->OperateDoors( side::left, false ); + } if( pVehicle->MoverParameters->Doors.permit_needed ) { pVehicle->MoverParameters->PermitDoors( side::right, false ); pVehicle->MoverParameters->PermitDoors( side::left, false ); diff --git a/Globals.h b/Globals.h index bfe3a2a6..2b1f9dd8 100644 --- a/Globals.h +++ b/Globals.h @@ -70,7 +70,6 @@ struct global_settings { bool bLiveTraction{ true }; float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f }; - double fFogStart{ 1700 }; double fFogEnd{ 2000 }; std::string Season{}; // season of the year, based on simulation date std::string Weather{ "cloudy:" }; // current weather diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 82d0e472..4375a90c 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -7071,9 +7071,14 @@ TMoverParameters::update_doors( double const Deltatime ) { door.local_close = door.local_close && ( false == door.is_closed ); door.remote_close = door.remote_close && ( false == door.is_closed ); + auto const autoopenrequest { + ( Doors.open_control == control_t::autonomous ) + && ( ( false == Doors.permit_needed ) || door.open_permit ) + }; auto const openrequest { ( localopencontrol && door.local_open ) - || ( remoteopencontrol && door.remote_open ) }; + || ( remoteopencontrol && door.remote_open ) + || ( autoopenrequest && ( false == door.is_open ) ) }; auto const autocloserequest { ( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) ) @@ -8360,12 +8365,6 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) { lookup != doorcontrols.end() ? lookup->second : control_t::passenger; - - if( Doors.close_control == control_t::autonomous ) { - // convert legacy method - Doors.close_control = control_t::passenger; - Doors.auto_velocity = 10.0; - } } // automatic closing conditions extract_value( Doors.auto_duration, "DoorStayOpen", line, "" ); diff --git a/Train.cpp b/Train.cpp index 82214068..a38c799c 100644 --- a/Train.cpp +++ b/Train.cpp @@ -4289,37 +4289,73 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman void TTrain::OnCommand_doorpermitleft( TTrain *Train, command_data const &Command ) { + if( Command.action == GLFW_REPEAT ) { return; } + if( Command.action == GLFW_PRESS ) { - Train->mvOccupied->PermitDoors( - ( Train->mvOccupied->ActiveCab == 1 ? + auto const side { ( + Train->mvOccupied->ActiveCab == 1 ? side::left : - side::right ) ); + side::right ) }; - // visual feedback - Train->ggDoorLeftPermitButton.UpdateValue( 1.0, Train->dsbSwitch ); + if( Train->ggDoorLeftPermitButton.type() == TGaugeType::push ) { + // impulse switch + Train->mvOccupied->PermitDoors( side ); + // visual feedback + Train->ggDoorLeftPermitButton.UpdateValue( 1.0, Train->dsbSwitch ); + } + else { + // two-state switch + auto const newstate { !( Train->mvOccupied->Doors.instances[ side ].open_permit ) }; + + Train->mvOccupied->PermitDoors( side, newstate ); + // visual feedback + Train->ggDoorLeftPermitButton.UpdateValue( ( newstate ? 1.0 : 0.0 ), Train->dsbSwitch ); + } } else if( Command.action == GLFW_RELEASE ) { - // visual feedback - Train->ggDoorLeftPermitButton.UpdateValue( 0.0, Train->dsbSwitch ); + + if( Train->ggDoorLeftPermitButton.type() == TGaugeType::push ) { + // impulse switch + // visual feedback + Train->ggDoorLeftPermitButton.UpdateValue( 0.0, Train->dsbSwitch ); + } } } void TTrain::OnCommand_doorpermitright( TTrain *Train, command_data const &Command ) { + if( Command.action == GLFW_REPEAT ) { return; } + if( Command.action == GLFW_PRESS ) { - Train->mvOccupied->PermitDoors( - ( Train->mvOccupied->ActiveCab == 1 ? + auto const side { ( + Train->mvOccupied->ActiveCab == 1 ? side::right : - side::left ) ); + side::left ) }; - // visual feedback - Train->ggDoorRightPermitButton.UpdateValue( 1.0, Train->dsbSwitch ); + if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) { + // impulse switch + Train->mvOccupied->PermitDoors( side ); + // visual feedback + Train->ggDoorRightPermitButton.UpdateValue( 1.0, Train->dsbSwitch ); + } + else { + // two-state switch + auto const newstate { !( Train->mvOccupied->Doors.instances[ side ].open_permit ) }; + + Train->mvOccupied->PermitDoors( side, newstate ); + // visual feedback + Train->ggDoorRightPermitButton.UpdateValue( ( newstate ? 1.0 : 0.0 ), Train->dsbSwitch ); + } } else if( Command.action == GLFW_RELEASE ) { - // visual feedback - Train->ggDoorRightPermitButton.UpdateValue( 0.0, Train->dsbSwitch ); + + if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) { + // impulse switch + // visual feedback + Train->ggDoorRightPermitButton.UpdateValue( 0.0, Train->dsbSwitch ); + } } } @@ -7585,7 +7621,12 @@ void TTrain::set_cab_controls( int const Cab ) { 1.f : 0.f ) ); // doors - // NOTE: for the time being permit switches are presumed to be impulse switches + if( ggDoorLeftPermitButton.type() != TGaugeType::push ) { + ggDoorLeftPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit ? 1.f : 0.f ); + } + if( ggDoorRightPermitButton.type() != TGaugeType::push ) { + ggDoorRightPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit ? 1.f : 0.f ); + } ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset ); ggDoorLeftButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].is_closed ? 0.f : 1.f ); ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].is_closed ? 0.f : 1.f ); @@ -7814,8 +7855,8 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co } // TODO: move viable dedicated lights to the automatic light array std::unordered_map const autolights = { - { "i-doorpermit_left:", &mvOccupied->Doors.instances[side::left].open_permit }, - { "i-doorpermit_right:", &mvOccupied->Doors.instances[ side::right ].open_permit }, + { "i-doorpermit_left:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit }, + { "i-doorpermit_right:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit }, { "i-doorstep:", &mvOccupied->Doors.step_enabled } }; { diff --git a/audio.cpp b/audio.cpp index 22a66729..558f325e 100644 --- a/audio.cpp +++ b/audio.cpp @@ -78,15 +78,15 @@ openal_buffer::openal_buffer( std::string const &Filename ) : // TBD, TODO: customized vorbis_decode to avoid unnecessary shuffling around of the decoded data int channels, samplerate; std::int16_t *filedata { nullptr }; - auto const samplecount{ stb_vorbis_decode_filename( Filename.c_str(), &channels, &samplerate, &filedata ) }; + auto const samplecount { stb_vorbis_decode_filename( Filename.c_str(), &channels, &samplerate, &filedata ) }; if( samplecount > 0 ) { rate = samplerate; - data.resize( samplecount ); - std::copy( filedata, filedata + samplecount, std::begin( data ) ); + data.resize( samplecount * channels ); + std::copy( filedata, filedata + data.size(), std::begin( data ) ); free( filedata ); if( channels > 1 ) { narrow_to_mono( channels ); - data.resize( samplecount / channels ); + data.resize( samplecount ); } } else { @@ -109,7 +109,7 @@ void openal_buffer::narrow_to_mono( std::uint16_t const Channelcount ) { std::size_t monodataindex { 0 }; - std::int32_t accumulator { 0 }; + std::int64_t accumulator { 0 }; auto channelcount { Channelcount }; for( auto const channeldata : data ) { @@ -117,7 +117,7 @@ openal_buffer::narrow_to_mono( std::uint16_t const Channelcount ) { accumulator += channeldata; if( --channelcount == 0 ) { - data[ monodataindex++ ] = accumulator / Channelcount; + data[ monodataindex++ ] = static_cast( accumulator / Channelcount ); accumulator = 0; channelcount = Channelcount; } diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index 5792999b..e74cc17c 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -21,7 +21,7 @@ http://mozilla.org/MPL/2.0/. #include "uilayer.h" #include "Logs.h" -auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.65 }; +auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.6 }; void mouse_slider::bind( user_command const &Command ) { diff --git a/renderer.cpp b/renderer.cpp index e9e16df2..ce8da5f6 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -2170,34 +2170,36 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being // render if( Dynamic->mdLowPolyInt ) { - // low poly interior - /* - if( ( true == FreeFlyModeFlag ) - || ( ( Dynamic->mdKabina == nullptr ) || ( false == Dynamic->bDisplayCab ) ) ) { - */ -/* - // enable cab light if needed - if( Dynamic->InteriorLightLevel > 0.0f ) { + // HACK: reduce light level for vehicle interior if there's strong global lighting source + auto const luminance { static_cast( 0.5 * ( std::max( 0.3, Global.fLuminance - Global.Overcast ) ) ) }; + m_sunlight.apply_intensity( + clamp( ( + Dynamic->fShade > 0.f ? + Dynamic->fShade : + 1.f ) + - luminance, + 0.f, 1.f ) ); - // crude way to light the cabin, until we have something more complete in place - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) ); - } -*/ - Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance ); -/* - if( Dynamic->InteriorLightLevel > 0.0f ) { - // reset the overall ambient - ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( m_baseambient ) ); - } -*/ - /* + // low poly interior + Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance ); + // HACK: if the model has low poly interior, we presume the load is placed inside and also affected by reduced light level + if( Dynamic->mdLoad ) { + // renderowanie nieprzezroczystego ładunku + Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} ); } - */ + + m_sunlight.apply_intensity( Dynamic->fShade > 0.f ? Dynamic->fShade : 1.f ); } - if( Dynamic->mdModel ) + else { + // HACK: if the model lacks low poly interior, we presume the load is placed outside + if( Dynamic->mdLoad ) { + // renderowanie nieprzezroczystego ładunku + Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} ); + } + } + if( Dynamic->mdModel ) { Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); - if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku - Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} ); + } // post-render cleanup m_renderspecular = false; if( Dynamic->fShade > 0.0f ) { diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index 2cbfdbcc..dbf53ff1 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -164,14 +164,22 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch // atmosphere color; legacy parameter, no longer used Input.getTokens( 3 ); // fog range - Input.getTokens( 2 ); - Input - >> Global.fFogStart - >> Global.fFogEnd; + { + double fograngestart, fograngeend; + Input.getTokens( 2 ); + Input + >> fograngestart + >> fograngeend; - if( Global.fFogEnd > 0.0 ) { - // fog colour; optional legacy parameter, no longer used - Input.getTokens( 3 ); + if( Global.fFogEnd != 0.0 ) { + // fog colour; optional legacy parameter, no longer used + Input.getTokens( 3 ); + } + + Global.fFogEnd = + clamp( + Random( fograngestart, fograngeend ), + 100.0, 2000.0 ); } std::string token { Input.getToken() }; diff --git a/version.h b/version.h index 92c0d111..0f25130e 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 403 +#define VERSION_MINOR 406 #define VERSION_REVISION 0 From b5da5ade72ffd7662dec70c14c8a82ed51f64a0c Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 9 Apr 2019 00:34:28 +0200 Subject: [PATCH 03/24] additional timetable data for python scripts, light level application fix --- mtable.cpp | 2 ++ renderer.cpp | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mtable.cpp b/mtable.cpp index 01b01259..6aed55d0 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -532,6 +532,8 @@ void TTrainParameters::serialize( dictionary_source *Output ) const { Output->insert( "train_enginetype", LocSeries ); Output->insert( "train_engineload", LocLoad ); + Output->insert( "train_stationfrom", Relation1 ); + Output->insert( "train_stationto", Relation2 ); Output->insert( "train_stationindex", StationIndex ); Output->insert( "train_stationcount", StationCount ); if( StationCount > 0 ) { diff --git a/renderer.cpp b/renderer.cpp index ce8da5f6..1840192d 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -32,17 +32,18 @@ int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental void opengl_light::apply_intensity( float const Factor ) { - if( Factor == 1.0 ) { + if( Factor == 1.f ) { ::glLightfv( id, GL_AMBIENT, glm::value_ptr( ambient ) ); ::glLightfv( id, GL_DIFFUSE, glm::value_ptr( diffuse ) ); ::glLightfv( id, GL_SPECULAR, glm::value_ptr( specular ) ); } else { + auto const factor{ clamp( Factor, 0.05f, 1.f ) }; // temporary light scaling mechanics (ultimately this work will be left to the shaders - glm::vec4 scaledambient( ambient.r * Factor, ambient.g * Factor, ambient.b * Factor, ambient.a ); - glm::vec4 scaleddiffuse( diffuse.r * Factor, diffuse.g * Factor, diffuse.b * Factor, diffuse.a ); - glm::vec4 scaledspecular( specular.r * Factor, specular.g * Factor, specular.b * Factor, specular.a ); + glm::vec4 scaledambient( ambient.r * factor, ambient.g * factor, ambient.b * factor, ambient.a ); + glm::vec4 scaleddiffuse( diffuse.r * factor, diffuse.g * factor, diffuse.b * factor, diffuse.a ); + glm::vec4 scaledspecular( specular.r * factor, specular.g * factor, specular.b * factor, specular.a ); glLightfv( id, GL_AMBIENT, glm::value_ptr( scaledambient ) ); glLightfv( id, GL_DIFFUSE, glm::value_ptr( scaleddiffuse ) ); glLightfv( id, GL_SPECULAR, glm::value_ptr( scaledspecular ) ); From 2002587d012ae0ef81dbf08e1809d0d2409b560c Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 9 Apr 2019 00:54:05 +0200 Subject: [PATCH 04/24] mantenance: stb_vorbis update to v1.16 --- ref/stb/stb_vorbis.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/ref/stb/stb_vorbis.c b/ref/stb/stb_vorbis.c index 69a23bca..ff117abe 100644 --- a/ref/stb/stb_vorbis.c +++ b/ref/stb/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.14 - public domain +// Ogg Vorbis audio decoder - v1.16 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -33,6 +33,8 @@ // Timur Gagiev // // Partial history: +// 1.16 - 2019-03-04 - fix warnings +// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found // 1.14 - 2018-02-11 - delete bogus dealloca usage // 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) // 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files @@ -253,7 +255,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, // create an ogg vorbis decoder from an open FILE *, looking for a stream at // the _current_ seek point (ftell). on failure, returns NULL and sets *error. // note that stb_vorbis must "own" this stream; if you seek it in between -// calls to stb_vorbis, it will become confused. Morever, if you attempt to +// calls to stb_vorbis, it will become confused. Moreover, if you attempt to // perform stb_vorbis_seek_*() operations on this file, it will assume it // owns the _entire_ rest of the file after the start point. Use the next // function, stb_vorbis_open_file_section(), to limit it. @@ -374,7 +376,8 @@ enum STBVorbisError VORBIS_invalid_first_page, VORBIS_bad_packet_type, VORBIS_cant_find_last_page, - VORBIS_seek_failed + VORBIS_seek_failed, + VORBIS_ogg_skeleton_not_supported }; @@ -1073,7 +1076,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) assert(z >= 0 && z < 32); available[z] = 0; add_entry(c, bit_reverse(res), i, m++, len[i], values); - // propogate availability up the tree + // propagate availability up the tree if (z != len[i]) { assert(len[i] >= 0 && len[i] < 32); for (y=len[i]; y > z; --y) { @@ -2637,7 +2640,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) // once I combined the passes. // so there's a missing 'times 2' here (for adding X to itself). - // this propogates through linearly to the end, where the numbers + // this propagates through linearly to the end, where the numbers // are 1/2 too small, and need to be compensated for. { @@ -3578,7 +3581,22 @@ static int start_decoder(vorb *f) if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); // check for expected packet length if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); - if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page); + if (f->segments[0] != 30) { + // check for the Ogg skeleton fishead identifying header to refine our error + if (f->segments[0] == 64 && + getn(f, header, 6) && + header[0] == 'f' && + header[1] == 'i' && + header[2] == 's' && + header[3] == 'h' && + header[4] == 'e' && + header[5] == 'a' && + get8(f) == 'd' && + get8(f) == '\0') return error(f, VORBIS_ogg_skeleton_not_supported); + else + return error(f, VORBIS_invalid_first_page); + } + // read packet // check packet header if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); @@ -4566,7 +4584,7 @@ static int get_seek_page_info(stb_vorbis *f, ProbedPage *z) return 1; } -// rarely used function to seek back to the preceeding page while finding the +// rarely used function to seek back to the preceding page while finding the // start of a packet static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset) { @@ -4973,7 +4991,13 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, con stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) { - FILE *f = fopen(filename, "rb"); + FILE *f; +#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) + if (0 != fopen_s(&f, filename, "rb")) + f = NULL; +#else + f = fopen(filename, "rb"); +#endif if (f) return stb_vorbis_open_file(f, TRUE, error, alloc); if (error) *error = VORBIS_file_open_failure; @@ -5459,4 +5483,4 @@ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ -*/ \ No newline at end of file +*/ From 2f3ef8c5292c2e33e57f50b37c59b0e7eed76281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 7 Apr 2019 19:14:14 +0200 Subject: [PATCH 05/24] Fixed manual AntiSlippingBraking for LSt valve --- McZapkie/hamulce.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index 5cc3dd02..7efb0994 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -1370,7 +1370,7 @@ double TLSt::GetPF( double const PP, double const dt, double const Vel ) temp = 10000; // powtarzacz — podwojny zawor zwrotny - temp = Max0R(((CVP - BCP) * BVM + ASBP * int((BrakeStatus & b_asb) == b_asb)) / temp, LBP); + temp = Max0R(((CVP - BCP) * BVM + ASBP * int((BrakeStatus & b_asb_unbrake) == b_asb_unbrake)) / temp, LBP); // luzowanie CH if ((BrakeCyl->P() > temp + 0.005) || (temp < 0.28)) // dV:=PF(0,BrakeCyl->P(),0.0015*3*sizeBC)*dt From 934163a6239294e6f5a0a8469dfbfff3eec6ddb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Mon, 8 Apr 2019 21:46:29 +0200 Subject: [PATCH 06/24] No positive eimic values when main switch is off --- McZapkie/Mover.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 4375a90c..25875f18 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -6080,7 +6080,7 @@ void TMoverParameters::CheckEIMIC(double dt) eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedUp); //dodawaj do X eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal); } - eimic = clamp(eimic, -1.0, 1.0); + eimic = clamp(eimic, -1.0, Mains ? 1.0 : 0.0); } void TMoverParameters::CheckSpeedCtrl() From 4794ec07ecfa17388a347f343172a3b193794e70 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sun, 14 Apr 2019 16:33:48 +0200 Subject: [PATCH 07/24] build 190411. configurable diesel-electric engine momentum, minor bug fixes --- Driver.cpp | 6 ++++-- DynObj.cpp | 11 +++++++---- McZapkie/Mover.cpp | 5 +++-- Train.cpp | 2 +- simulationstateserializer.cpp | 2 +- version.h | 2 +- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index a082ac18..e3201111 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -6625,14 +6625,16 @@ void TController::DirectionForward(bool forward) // do przodu w obecnej kabinie while( ( mvOccupied->ActiveDir <= 0 ) && ( mvOccupied->DirectionForward() ) ) { - ; // all work is done in the header + // force scan table update + iTableDirection = 0; } } else { // do tyłu w obecnej kabinie while( ( mvOccupied->ActiveDir >= 0 ) && ( mvOccupied->DirectionBackward() ) ) { - ; // all work is done in the header + // force scan table update + iTableDirection = 0; } } if( mvOccupied->TrainType == dt_SN61 ) { diff --git a/DynObj.cpp b/DynObj.cpp index 6c93fbb6..a759d3ef 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2319,7 +2319,9 @@ void TDynamicObject::AttachPrev(TDynamicObject *Object, int iType) { // Ra: doczepia Object na końcu składu (nazwa funkcji może być myląca) // Ra: używane tylko przy wczytywaniu scenerii MoverParameters->Attach( iDirection, Object->iDirection ^ 1, Object->MoverParameters, iType, true, false ); + // update neighbour data for both affected vehicles update_neighbours(); + Object->update_neighbours(); } bool TDynamicObject::UpdateForce(double dt) @@ -4343,10 +4345,6 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co m_materialdata.textures_alpha |= 0x08080008; } } - if( false == MoverParameters->LoadAttributes.empty() ) { - // Ra: tu wczytywanie modelu ładunku jest w porządku - mdLoad = LoadMMediaFile_mdload( MoverParameters->LoadType.name ); - } Global.asCurrentTexturePath = szTexturePath; // z powrotem defaultowa sciezka do tekstur do { token = ""; @@ -4927,6 +4925,11 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co } while( ( token != "" ) && ( token != "endmodels" ) ); + if( false == MoverParameters->LoadAttributes.empty() ) { + // Ra: tu wczytywanie modelu ładunku jest w porządku + mdLoad = LoadMMediaFile_mdload( MoverParameters->LoadType.name ); + } + } // models else if( token == "sounds:" ) { diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 25875f18..8d81b9c3 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -4406,7 +4406,7 @@ double TMoverParameters::TractionForce( double dt ) { if( enrot != tmp ) { enrot = clamp( - enrot + ( dt / 1.25 ) * ( // TODO: equivalent of dizel_aim instead of fixed inertia + enrot + ( dt / dizel_AIM ) * ( enrot < tmp ? 1.0 : -2.0 ), // NOTE: revolutions drop faster than they rise, maybe? TBD: maybe not @@ -6080,7 +6080,7 @@ void TMoverParameters::CheckEIMIC(double dt) eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedUp); //dodawaj do X eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal); } - eimic = clamp(eimic, -1.0, Mains ? 1.0 : 0.0); + eimic = clamp(eimic, -1.0, ( ( true == Mains ) || ( Power == 0.0 ) ) ? 1.0 : 0.0); } void TMoverParameters::CheckSpeedCtrl() @@ -8945,6 +8945,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { ImaxLo = 1; } extract_value( EngineHeatingRPM, "HeatingRPM", Input, "" ); + extract_value( dizel_AIM, "AIM", Input, "1.25" ); break; } case TEngineType::ElectricInductionMotor: { diff --git a/Train.cpp b/Train.cpp index a38c799c..eb0c4d74 100644 --- a/Train.cpp +++ b/Train.cpp @@ -5221,7 +5221,7 @@ bool TTrain::Update( double const Deltatime ) } bool kier = (DynamicObject->DirectionGet() * mvOccupied->ActiveCab > 0); - TDynamicObject *p = DynamicObject->GetFirstDynamic(mvOccupied->ActiveCab < 0 ? 1 : 0, 4); + TDynamicObject *p = DynamicObject->GetFirstDynamic(mvOccupied->ActiveCab < 0 ? end::rear : end::front, 4); int in = 0; fEIMParams[0][6] = 0; iCarNo = 0; diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index dbf53ff1..e28992a0 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -178,7 +178,7 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch Global.fFogEnd = clamp( - Random( fograngestart, fograngeend ), + Random( std::min( fograngestart, fograngeend ), std::max( fograngestart, fograngeend ) ), 100.0, 2000.0 ); } diff --git a/version.h b/version.h index 0f25130e..8f8c33cb 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 406 +#define VERSION_MINOR 411 #define VERSION_REVISION 0 From f0e0cbf6f71b67c1bea203ea38aad7ef0a3f5926 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Thu, 18 Apr 2019 15:54:35 +0200 Subject: [PATCH 08/24] eimic value calculation fix --- McZapkie/Mover.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 8d81b9c3..3aaa4d88 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -6080,7 +6080,11 @@ void TMoverParameters::CheckEIMIC(double dt) eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedUp); //dodawaj do X eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal); } - eimic = clamp(eimic, -1.0, ( ( true == Mains ) || ( Power == 0.0 ) ) ? 1.0 : 0.0); + auto const eimicpowerenabled { + ( ( true == Mains ) || ( Power == 0.0 ) ) + && ( ( Doors.instances[ side::left ].open_permit == false ) + && ( Doors.instances[ side::right ].open_permit == false ) ) }; + eimic = clamp(eimic, -1.0, eimicpowerenabled ? 1.0 : 0.0); } void TMoverParameters::CheckSpeedCtrl() From 111026f700873e714ddfc5d04db8877111bd7afb Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Fri, 19 Apr 2019 20:29:00 +0200 Subject: [PATCH 09/24] build 190419. radio message volume, drag calculation enhancement, ai acceleration logic tweak, event duplicate scanning fix --- Driver.cpp | 17 ++++++++++++++--- Driver.h | 2 +- Globals.cpp | 8 +++++++- Globals.h | 3 ++- McZapkie/Mover.cpp | 13 ++++++++++++- McZapkie/hamulce.cpp | 2 ++ Train.cpp | 2 +- version.h | 2 +- 8 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index e3201111..2f81de54 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -456,7 +456,7 @@ bool TController::TableAddNew() return true; // false gdy się nałoży }; -bool TController::TableNotFound(basic_event const *Event) const +bool TController::TableNotFound(basic_event const *Event, double const Distance ) const { // sprawdzenie, czy nie został już dodany do tabelki (np. podwójne W4 robi problemy) auto lookup = std::find_if( @@ -471,7 +471,11 @@ bool TController::TableNotFound(basic_event const *Event) const WriteLog( "Speed table for " + OwnerName() + " already contains event " + lookup->evEvent->m_name ); } - return lookup == sSpeedTable.end(); + // ignore duplicates which seem to be reasonably apart from each other, on account of looping tracks + // NOTE: since supplied distance is only rough approximation of distance to the event, we're using large safety margin + return ( + ( lookup == sSpeedTable.end() ) + || ( Distance - lookup->fDist > 100.0 ) ); }; void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) @@ -575,7 +579,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) for( auto *pEvent : events ) { if( pEvent != nullptr ) // jeśli jest semafor na tym torze { // trzeba sprawdzić tabelkę, bo dodawanie drugi raz tego samego przystanku nie jest korzystne - if (TableNotFound(pEvent)) // jeśli nie ma + if (TableNotFound(pEvent, fCurrentDistance)) // jeśli nie ma { TableAddNew(); // zawsze jest true @@ -2368,6 +2372,10 @@ double TController::BrakeAccFactor() const || ( mvOccupied->Vel > VelDesired + fVelPlus ) ) ) { Factor += ( fBrakeReaction * ( /*mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.5 ? 1.5 : 1 ) ) * mvOccupied->Vel / ( std::max( 0.0, ActualProximityDist ) + 1 ) * ( ( AccDesired - AbsAccS_pub ) / fAccThreshold ); } +/* + if (mvOccupied->TrainType == dt_DMU && mvOccupied->Vel > 40 && VelNext<40) + Factor *= 1 + ( (1600 - VelNext * VelNext) / (mvOccupied->Vel * mvOccupied->Vel) ); +*/ return Factor; } @@ -2984,6 +2992,7 @@ bool TController::IncSpeed() // if it generates enough traction force // to build up speed to 30/40 km/h for passenger/cargo train (10 km/h less if going uphill) auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 }; + auto const sufficientacceleration { AbsAccS_pub >= ( IsHeavyCargoTrain ? 0.02 : 0.04 ) }; auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) }; auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) }; auto const useseriesmodevoltage { @@ -2995,6 +3004,7 @@ bool TController::IncSpeed() ( mvControlling->Imax > mvControlling->ImaxLo ) || ( fVoltage < useseriesmodevoltage ) || ( ( true == sufficienttractionforce ) + && ( true == sufficientacceleration ) && ( mvOccupied->Vel <= ( IsCargoTrain ? 35 : 25 ) + ( seriesmodefieldshunting ? 5 : 0 ) - ( ( fAccGravity < -0.025 ) ? 10 : 0 ) ) ) ); // when not in series mode use the first available parallel mode configuration until 50/60 km/h for passenger/cargo train // (if there's only one parallel mode configuration it'll be used regardless of current speed) @@ -3004,6 +3014,7 @@ bool TController::IncSpeed() && ( useseriesmode ? mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 : ( ( true == sufficienttractionforce ) + && ( true == sufficientacceleration ) && ( mvOccupied->Vel <= ( IsCargoTrain ? 55 : 45 ) + ( parallelmodefieldshunting ? 5 : 0 ) ) ? mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 : mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo ) ) ); diff --git a/Driver.h b/Driver.h index d75de7d1..4abade2c 100644 --- a/Driver.h +++ b/Driver.h @@ -363,7 +363,7 @@ private: // Ra: metody obsługujące skanowanie toru std::vector CheckTrackEvent( TTrack *Track, double const fDirection ) const; bool TableAddNew(); - bool TableNotFound( basic_event const *Event ) const; + bool TableNotFound( basic_event const *Event, double const Distance ) const; void TableTraceRoute( double fDistance, TDynamicObject *pVehicle ); void TableCheck( double fDistance ); TCommandType TableUpdate( double &fVelDes, double &fDist, double &fNext, double &fAcc ); diff --git a/Globals.cpp b/Globals.cpp index 41ebbc35..562b6b2c 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -127,7 +127,13 @@ global_settings::ConfigParse(cParser &Parser) { // selected device for audio renderer Parser.getTokens(); Parser >> AudioVolume; - AudioVolume = clamp( AudioVolume, 0.0f, 2.f ); + AudioVolume = clamp( AudioVolume, 0.f, 2.f ); + } + else if( token == "sound.volume.radio" ) { + // selected device for audio renderer + Parser.getTokens(); + Parser >> RadioVolume; + RadioVolume = clamp( RadioVolume, 0.f, 1.f ); } // else if (str==AnsiString("renderalpha")) //McZapkie-1312302 - dwuprzebiegowe renderowanie // bRenderAlpha=(GetNextSymbol().LowerCase()==AnsiString("yes")); diff --git a/Globals.h b/Globals.h index 2b1f9dd8..9348b9d1 100644 --- a/Globals.h +++ b/Globals.h @@ -133,7 +133,8 @@ struct global_settings { double fFpsMax{ 65.0 }; // górna granica FPS, przy której promień scenerii będzie zwiększany // audio bool bSoundEnabled{ true }; - float AudioVolume{ 1.25f }; + float AudioVolume{ 1.f }; + float RadioVolume{ 0.75f }; std::string AudioRenderer; // input float fMouseXScale{ 1.5f }; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 3aaa4d88..15f84897 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -3891,7 +3891,18 @@ void TMoverParameters::ComputeConstans(void) } Ff = TotalMassxg * (BearingF + RollF * V * V / 10.0) / 1000.0; // dorobic liczenie temperatury lozyska! - FrictConst1 = ((TotalMassxg * RollF) / 10000.0) + (Cx * Dim.W * Dim.H); + FrictConst1 = ( TotalMassxg * RollF ) / 10000.0; + // drag calculation + { + // NOTE: draft effect of previous vehicle is simplified and doesn't have much to do with reality + auto const *previousvehicle { Couplers[ ( V >= 0.0 ? end::front : end::rear ) ].Connected }; + auto dragarea { Dim.W * Dim.H }; + if( previousvehicle ) { + dragarea = std::max( 0.0, dragarea - ( 0.85 * previousvehicle->Dim.W * previousvehicle->Dim.H ) ); + } + FrictConst1 += Cx * dragarea; + } + Curvature = abs(RunningShape.R); // zero oznacza nieskończony promień if (Curvature > 0.0) Curvature = 1.0 / Curvature; diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index 7efb0994..c6c33e34 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -2773,6 +2773,8 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) void TMHZ_K5P::Init(double Press) { CP = Press; + Time = true; + TimeEP = true; } void TMHZ_K5P::SetReductor(double nAdj) diff --git a/Train.cpp b/Train.cpp index eb0c4d74..0555adac 100644 --- a/Train.cpp +++ b/Train.cpp @@ -6537,7 +6537,7 @@ void TTrain::update_sounds_radio() { auto const volume { ( true == radioenabled ) && ( message.first == iRadioChannel ) ? - 1.0 : + Global.RadioVolume : 0.0 }; message.second->gain( volume ); } diff --git a/version.h b/version.h index 8f8c33cb..62cba964 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 411 +#define VERSION_MINOR 419 #define VERSION_REVISION 0 From 819c183f9120be165d7a7c4335c3157ca6b38c1b Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Mon, 29 Apr 2019 17:24:57 +0200 Subject: [PATCH 10/24] vehicle load visualization model texture source fix, python script data source fix --- DynObj.cpp | 7 +++++++ Train.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index a759d3ef..9c0bd8e1 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -4927,7 +4927,14 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co if( false == MoverParameters->LoadAttributes.empty() ) { // Ra: tu wczytywanie modelu ładunku jest w porządku + + // bieżąca ścieżka do tekstur to dynamic/... + Global.asCurrentTexturePath = asBaseDir; + mdLoad = LoadMMediaFile_mdload( MoverParameters->LoadType.name ); + + // z powrotem defaultowa sciezka do tekstur + Global.asCurrentTexturePath = std::string( szTexturePath ); } } // models diff --git a/Train.cpp b/Train.cpp index 0555adac..53aef0c1 100644 --- a/Train.cpp +++ b/Train.cpp @@ -450,10 +450,10 @@ dictionary_source *TTrain::GetTrainState() { // reverser dict->insert( "direction", mover->ActiveDir ); // throttle - 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 ); + dict->insert( "mainctrl_pos", mvControlled->MainCtrlPos ); + dict->insert( "main_ctrl_actual_pos", mvControlled->MainCtrlActualPos ); + dict->insert( "scndctrl_pos", mvControlled->ScndCtrlPos ); + dict->insert( "scnd_ctrl_actual_pos", mvControlled->ScndCtrlActualPos ); dict->insert( "new_speed", mover->NewSpeed); // brakes dict->insert( "manual_brake", ( mvOccupied->ManualBrakePos > 0 ) ); From fbe570950d9439c5ca2fc3eedbddf96f0379c14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 28 Apr 2019 10:49:49 +0200 Subject: [PATCH 11/24] Delayed ED braking for ELF --- DynObj.cpp | 8 ++++++++ DynObj.h | 1 + McZapkie/Mover.cpp | 2 -- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index 9c0bd8e1..4f39db3a 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2783,6 +2783,8 @@ bool TDynamicObject::Update(double dt, double dt1) auto eimic = Min0R(MoverParameters->eimic, MoverParameters->eimicSpeedCtrl); MoverParameters->eimic_real = eimic; + if (MoverParameters->EIMCtrlType == 2 && MoverParameters->MainCtrlPos == 0) + eimic = -1.0; MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo); auto LBR = Max0R(-eimic, 0); auto eim_lb = (Mechanik->AIControllFlag || !MoverParameters->LocHandleTimeTraxx ? 0 : MoverParameters->eim_localbrake); @@ -2892,6 +2894,10 @@ bool TDynamicObject::Update(double dt, double dt1) && ( MoverParameters->BrakeOpModeFlag & bom_MED ) ) ) { FzadED = std::min( Fzad, FmaxED ); } + if (MoverParameters->EIMCtrlType == 2 && MoverParameters->MainCtrlPos < 2 && MoverParameters->eimic > -0.999) + { + FzadED = std::min(FzadED, MED_oldFED); + } if ((MoverParameters->BrakeCtrlPos == MoverParameters->Handle->GetPos(bh_EB)) && (MoverParameters->eimc[eimc_p_abed] < 0.001)) FzadED = 0; //pętla bezpieczeństwa - bez ED @@ -3069,6 +3075,8 @@ bool TDynamicObject::Update(double dt, double dt1) delete[] FzED; delete[] FzEP; delete[] FmaxEP; + + MED_oldFED = FzadED; } Mechanik->UpdateSituation(dt1); // przebłyski świadomości AI diff --git a/DynObj.h b/DynObj.h index 1bbe000a..4b89c201 100644 --- a/DynObj.h +++ b/DynObj.h @@ -658,6 +658,7 @@ private: double MEDLogTime = 0; double MEDLogInactiveTime = 0; int MEDLogCount = 0; + double MED_oldFED = 0; // vehicle shaking calculations // TBD, TODO: make an object out of it diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 15f84897..74783d83 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -6068,8 +6068,6 @@ void TMoverParameters::CheckEIMIC(double dt) switch (MainCtrlPos) { case 0: - eimic = -1.0; - break; case 1: eimic -= clamp(1.0 + eimic, 0.0, dt*0.15); //odejmuj do -1 if (eimic > 0) eimic = 0; From 57f7ac27da4cb9c80c3d6dda00f4b487d9b0ad4b Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 1 May 2019 03:44:53 +0200 Subject: [PATCH 12/24] build 190430. ai braking logic tweaks --- Driver.cpp | 87 +++++++++++++++++++++++++++----------------- Driver.h | 2 +- McZapkie/hamulce.cpp | 5 +++ McZapkie/hamulce.h | 1 + version.h | 2 +- 5 files changed, 62 insertions(+), 35 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 2f81de54..04198d18 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1476,7 +1476,8 @@ TController::braking_distance_multiplier( float const Targetvelocity ) const { if( ( mvOccupied->TrainType == dt_DMU ) && ( mvOccupied->Vel < 40.0 ) && ( Targetvelocity == 0.f ) ) { - return interpolate( 2.f, 1.f, static_cast( mvOccupied->Vel / 40.0 ) ); + auto const multiplier { clamp( 1.f + iVehicles * 0.5f, 2.f, 4.f ) }; + return interpolate( multiplier, 1.f, static_cast( mvOccupied->Vel / 40.0 ) ); } // HACK: cargo trains or trains going downhill with high braking threshold need more distance to come to a full stop if( ( fBrake_a0[ 1 ] > 0.2 ) @@ -2014,7 +2015,7 @@ void TController::AutoRewident() fBrakeReaction = 0.25; } else if( mvOccupied->TrainType == dt_DMU ) { - fNominalAccThreshold = std::max( -0.45, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] ); + fNominalAccThreshold = std::max( -0.75, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] ); fBrakeReaction = 0.25; } else if (ustaw > 16) { @@ -2374,7 +2375,7 @@ double TController::BrakeAccFactor() const } /* if (mvOccupied->TrainType == dt_DMU && mvOccupied->Vel > 40 && VelNext<40) - Factor *= 1 + ( (1600 - VelNext * VelNext) / (mvOccupied->Vel * mvOccupied->Vel) ); + Factor *= 1 + 0.25 * ( (1600 - VelNext * VelNext) / (mvOccupied->Vel * mvOccupied->Vel) ); */ return Factor; } @@ -2780,17 +2781,15 @@ bool TController::IncBrake() { if( /*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.1 ) { OK = /*mvOccupied->*/BrakeLevelAdd( BrakingInitialLevel ); //GBH -/* // HACK: stronger braking to overcome SA134 engine behaviour if( ( mvOccupied->TrainType == dt_DMU ) && ( VelNext == 0.0 ) && ( fBrakeDist < 200.0 ) ) { - mvOccupied->BrakeLevelAdd( + BrakeLevelAdd( fBrakeDist / ActualProximityDist < 0.8 ? - 1.0 : - 3.0 ); + 0.5 : + 1.0 ); } -*/ } else { @@ -2811,7 +2810,9 @@ bool TController::IncBrake() } } if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition > 0 ) { - mvOccupied->BrakeReleaser( 0 ); + if( mvOccupied->Hamulec->Releaser() ) { + mvOccupied->BrakeReleaser( 0 ); + } } break; } @@ -2865,7 +2866,8 @@ bool TController::IncBrakeEIM() bool TController::DecBrake() { // zmniejszenie siły hamowania bool OK = false; - double deltaAcc = 0; + double deltaAcc = -1.0; + double pos_diff = 1.0; switch (mvOccupied->BrakeSystem) { case TBrakeSystem::Individual: @@ -2875,7 +2877,12 @@ bool TController::DecBrake() OK = mvOccupied->DecLocalBrakeLevel(1 + floor(0.5 + fabs(AccDesired))); break; case TBrakeSystem::Pneumatic: - deltaAcc = -AccDesired*BrakeAccFactor() - (fBrake_a0[0] + 4 * (/*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition -1.0)*fBrake_a1[0]); + if( ( fBrake_a0[ 0 ] != 0.0 ) + || ( fBrake_a1[ 0 ] != 0.0 ) ) { + if( mvOccupied->TrainType == dt_DMU ) + pos_diff = 0.25; + deltaAcc = -AccDesired*BrakeAccFactor() - (fBrake_a0[0] + 4 * (/*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition - pos_diff)*fBrake_a1[0]); + } if (deltaAcc < 0) { if (/*GBH mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition > 0) @@ -2894,8 +2901,11 @@ bool TController::DecBrake() if (!OK) { OK = DecBrakeEIM(); } +/* +// NOTE: disabled, duplicate of AI's behaviour in UpdateSituation() if (mvOccupied->PipePress < 3.0) Need_BrakeRelease = true; +*/ break; case TBrakeSystem::ElectroPneumatic: if (mvOccupied->EngineType == TEngineType::ElectricInductionMotor) { @@ -5712,16 +5722,32 @@ TController::UpdateSituation(double dt) { ReactionTime = 0.25; } } - if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic) // napełnianie uderzeniowe - if (mvOccupied->BrakeHandle == TBrakeHandle::FV4a || mvOccupied->BrakeHandle == TBrakeHandle::MHZ_6P - || mvOccupied->BrakeHandle == TBrakeHandle::M394) - { + if (mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic) { + // napełnianie uderzeniowe + if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) + || ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_6P ) + || ( mvOccupied->BrakeHandle == TBrakeHandle::M394 ) ) { + if( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == -2 ) { /*mvOccupied->*/BrakeLevelSet( gbh_RP ); } - if( ( mvOccupied->PipePress < 3.0 ) - && ( AccDesired > -0.03 ) ) { - mvOccupied->BrakeReleaser( 1 ); + + // TODO: combine all releaser handling in single decision tree instead of having bits all over the place + if( ( AccDesired > -0.03 ) + && ( false == mvOccupied->Hamulec->Releaser() ) ) { + if( mvOccupied->PipePress < 3.0 ) { + mvOccupied->BrakeReleaser( 1 ); + } + if( ( mvOccupied->BrakePress > 0.4 ) + && ( mvOccupied->Hamulec->GetCRP() > 4.9 ) ) { + // wyluzuj lokomotywę, to szybciej ruszymy + mvOccupied->BrakeReleaser( 1 ); + } + } + if( ( mvOccupied->PipePress > 3.0 ) + && ( mvOccupied->Hamulec->Releaser() ) ) { + // don't overcharge train brake pipe + mvOccupied->BrakeReleaser( 0 ); } if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition == 0 ) @@ -5729,31 +5755,37 @@ TController::UpdateSituation(double dt) { && ( AccDesired > -0.03 ) && ( VelDesired - mvOccupied->Vel > 2.0 ) ) { - if( ( mvOccupied->EqvtPipePress < 4.95 ) + if( ( mvOccupied->EqvtPipePress < 4.5 ) && ( fReady > 0.35 ) - && ( BrakeChargingCooldown >= 0.0 ) ) { + && ( BrakeChargingCooldown >= 0.0 ) + && ( ( ActualProximityDist > 100.0 ) // don't charge if we're about to be braking soon + || ( min_speed( mvOccupied->Vel, VelNext ) == mvOccupied->Vel ) ) ) { if( ( iDrivigFlags & moveOerlikons ) || ( true == IsCargoTrain ) ) { // napełnianie w Oerlikonie /* mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_FS ) ); GBH */ - BrakeLevelSet(gbh_FS); + BrakeLevelSet( gbh_FS ); // don't charge the brakes too often, or we risk overcharging BrakeChargingCooldown = -120.0; } } +/* +// NOTE: disabled, duplicate of release activation in #5732 else if( Need_BrakeRelease ) { Need_BrakeRelease = false; mvOccupied->BrakeReleaser( 1 ); } +*/ } if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition < 0 ) && ( mvOccupied->EqvtPipePress > ( fReady < 0.25 ? 5.1 : 5.2 ) ) ) { /* GBH mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); */ - BrakeLevelSet(gbh_RP); + BrakeLevelSet( gbh_RP ); } } + } #if LOGVELOCITY WriteLog("Dist=" + FloatToStrF(ActualProximityDist, ffFixed, 7, 1) + ", VelDesired=" + FloatToStrF(VelDesired, ffFixed, 7, 1) + @@ -5792,17 +5824,6 @@ TController::UpdateSituation(double dt) { AccDesired > 0.0 ) ) { // on slopes disengage the brakes only if you actually intend to accelerate while( true == DecBrake() ) { ; } // jeśli przyspieszamy, to nie hamujemy - if( ( mvOccupied->BrakePress > 0.4 ) - && ( mvOccupied->Hamulec->GetCRP() > 4.9 ) ) { - // wyluzuj lokomotywę, to szybciej ruszymy - mvOccupied->BrakeReleaser( 1 ); - } - else { - if( mvOccupied->PipePress >= 3.0 ) { - // TODO: combine all releaser handling in single decision tree instead of having bits all over the place - mvOccupied->BrakeReleaser( 0 ); - } - } } } } diff --git a/Driver.h b/Driver.h index 4abade2c..2b0a8053 100644 --- a/Driver.h +++ b/Driver.h @@ -280,7 +280,7 @@ private: int iCoupler = 0; // maska sprzęgu, jaką należy użyć przy łączeniu (po osiągnięciu trybu Connect), 0 gdy jazda bez łączenia int iDriverFailCount = 0; // licznik błędów AI bool Need_TryAgain = false; // true, jeśli druga pozycja w elektryku nie załapała - bool Need_BrakeRelease = true; +// bool Need_BrakeRelease = true; bool IsAtPassengerStop{ false }; // true if the consist is within acceptable range of w4 post double fMinProximityDist = 30.0; // stawanie między 30 a 60 m przed przeszkodą // minimalna oległość do przeszkody, jaką należy zachować double fOverhead1 = 3000.0; // informacja o napięciu w sieci trakcyjnej (0=brak drutu, zatrzymaj!) diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index c6c33e34..59ffb5bb 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -385,6 +385,11 @@ void TBrake::Releaser( int const state ) BrakeStatus = (BrakeStatus & ~b_rls) | ( state * b_rls ); } +bool TBrake::Releaser() const { + + return ( ( BrakeStatus & b_rls ) == b_rls ); +} + void TBrake::SetEPS( double const nEPS ) { } diff --git a/McZapkie/hamulce.h b/McZapkie/hamulce.h index 6ae70eca..814718da 100644 --- a/McZapkie/hamulce.h +++ b/McZapkie/hamulce.h @@ -203,6 +203,7 @@ class TBrake { virtual double GetCRP(); //cisnienie zbiornika sterujacego bool SetBDF( int const nBDF ); //nastawiacz GPRM void Releaser( int const state ); //odluzniacz + bool Releaser() const; virtual void SetEPS( double const nEPS ); //hamulec EP virtual void SetRM( double const RMR ) {}; //ustalenie przelozenia rapida virtual void SetRV( double const RVR) {}; //ustalenie przelozenia rapida diff --git a/version.h b/version.h index 62cba964..7bcb12d5 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 419 +#define VERSION_MINOR 430 #define VERSION_REVISION 0 From e6bbce64b73e6abf7dafb4308f8a6ae8e5e42a88 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 8 May 2019 19:35:18 +0200 Subject: [PATCH 13/24] build 190504. pantograph compressor start method, door control mode support, impulse type battery switch support, disconnect ai logic tweak --- Driver.cpp | 91 +++++++++++++++++++-------------------- McZapkie/MOVER.h | 5 ++- McZapkie/Mover.cpp | 95 +++++++++++++++++++++++++++-------------- Train.cpp | 64 +++++++++++++++++---------- Train.h | 1 + command.cpp | 1 + command.h | 1 + driverkeyboardinput.cpp | 1 + drivermouseinput.cpp | 3 ++ translation.cpp | 3 ++ translation.h | 1 + version.h | 2 +- 12 files changed, 163 insertions(+), 105 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 04198d18..15275845 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -4176,6 +4176,7 @@ TController::UpdateSituation(double dt) { // HACK: activate route scanning if an idling vehicle is activated by a human user if( ( OrderCurrentGet() == Wait_for_orders ) && ( false == AIControllFlag ) + && ( false == iEngineActive ) && ( true == mvControlling->Battery ) ) { OrderNext( Prepare_engine ); } @@ -5004,54 +5005,50 @@ TController::UpdateSituation(double dt) { // jeśli dociskanie w celu odczepienia // 3. faza odczepiania. SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2 - if( ( mvControlling->MainCtrlPowerPos() > 0 ) - || ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) { - // jeśli jazda - WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); - TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI - int d; // numer sprzęgu, który sprawdzamy albo odczepiamy - int n = iVehicleCount; // ile wagonów ma zostać - do - { // szukanie pojazdu do odczepienia - d = p->DirectionGet() > 0 ? - end::front : - end::rear; // numer sprzęgu od strony czoła składu - // if (p->MoverParameters->Couplers[d].CouplerType==Articulated) - // //jeśli sprzęg typu wózek (za mało) - if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany - // if (p->GetTrack()->) //a nie stoi na torze warsztatowym - // (ustalić po czym poznać taki tor) - ++n; // to liczymy człony jako jeden - p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać - // GBH p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował - BrakeLevelSet(gbh_RP); - if (n) - { // jeśli jeszcze nie koniec - p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy - if (!p) - iVehicleCount = -2, - n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone - } - } while (n--); - if( ( p == nullptr ) - || ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) { - // no target, or already just virtual coupling - WriteLog( mvOccupied->Name + " didn't find anything to disconnect." ); - iVehicleCount = -2; // odczepiono, co było do odczepienia - } else if ( p->Dettach(d) == coupling::faux ) { - // tylko jeśli odepnie - WriteLog( mvOccupied->Name + " odczepiony." ); - iVehicleCount = -2; - } // a jak nie, to dociskać dalej - } - if (iVehicleCount >= 0) // zmieni się po odczepieniu - if (!mvOccupied->DecLocalBrakeLevel(1)) - { // dociśnij sklad - WriteLog( mvOccupied->Name + " dociskanie..." ); - // mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę - // Ready=true; //zamiast sprawdzenia odhamowania całego składu - IncSpeed(); // dla (Ready)==false nie ruszy + if( iVehicleCount >= 0 ) { + // zmieni się po odczepieniu + WriteLog( mvOccupied->Name + " dociskanie..." ); + while( mvOccupied->DecLocalBrakeLevel( 1 ) ) { // dociśnij sklad + ; } + IncSpeed(); + } + WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); + TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI + int d; // numer sprzęgu, który sprawdzamy albo odczepiamy + int n = iVehicleCount; // ile wagonów ma zostać + do + { // szukanie pojazdu do odczepienia + d = p->DirectionGet() > 0 ? + end::front : + end::rear; // numer sprzęgu od strony czoła składu + // if (p->MoverParameters->Couplers[d].CouplerType==Articulated) + // //jeśli sprzęg typu wózek (za mało) + if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany + // if (p->GetTrack()->) //a nie stoi na torze warsztatowym + // (ustalić po czym poznać taki tor) + ++n; // to liczymy człony jako jeden + p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać + // GBH p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował + BrakeLevelSet(gbh_RP); + if (n) + { // jeśli jeszcze nie koniec + p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy + if (!p) + iVehicleCount = -2, + n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone + } + } while (n--); + if( ( p == nullptr ) + || ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) { + // no target, or already just virtual coupling + WriteLog( mvOccupied->Name + " didn't find anything to disconnect." ); + iVehicleCount = -2; // odczepiono, co było do odczepienia + } else if ( p->Dettach(d) == coupling::faux ) { + // tylko jeśli odepnie + WriteLog( mvOccupied->Name + " odczepiony." ); + iVehicleCount = -2; + } // a jak nie, to dociskać dalej } if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress)) { // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 6902be65..9092074c 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -766,6 +766,7 @@ private: // ld inputs bool lock_enabled { true }; bool step_enabled { true }; + bool remote_only { false }; // door ignores local control signals // internal data int permit_preset { -1 }; // curent position of preset selection switch // vehicle parts @@ -1162,6 +1163,7 @@ public: bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere) bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure start_t CompressorStart{ start_t::manual }; // whether the compressor is started manually, or another way + start_t PantographCompressorStart{ start_t::manual }; // TODO converter parameters, for when we start cleaning up mover parameters start_t ConverterStart{ start_t::manual }; // whether converter is started manually, or by other means float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met @@ -1344,8 +1346,6 @@ public: bool PantRearUp = false; bool PantFrontSP = true; //dzwiek patykow 'Winger 010304 bool PantRearSP = true; - int PantFrontStart = 0; //stan patykow 'Winger 160204 - int PantRearStart = 0; double PantFrontVolt = 0.0; //pantograf pod napieciem? 'Winger 160404 double PantRearVolt = 0.0; // TODO: move these switch types where they belong, cabin definition @@ -1553,6 +1553,7 @@ public: bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist ); bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist ); bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist ); + bool ChangeDoorControlMode( bool const State, range_t const Notify = range_t::consist ); bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist ); bool LockDoors( bool const State, range_t const Notify = range_t::consist ); bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 74783d83..67c43ee4 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -653,11 +653,18 @@ void TMoverParameters::UpdatePantVolume(double dt) { // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak // check the pantograph compressor while at it - if( PantCompFlag ) { - if( ( false == Battery ) - && ( false == ConverterFlag ) ) { - PantCompFlag = false; - } + if( ( PantPress < 4.2 ) + && ( ( PantographCompressorStart == start_t::automatic ) + || ( PantographCompressorStart == start_t::manualwithautofallback ) ) + && ( ( true == PantRearUp ) + || ( true == PantFrontUp ) ) ) { + // automatic start if the pressure is too low + PantCompFlag = true; + } + if( ( true == PantCompFlag ) + && ( false == Battery ) + && ( false == ConverterFlag ) ) { + PantCompFlag = false; } if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący @@ -5916,7 +5923,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify ) if( PantFrontUp != State ) { PantFrontUp = State; if( State == true ) { - PantFrontStart = 0; if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( @@ -5927,7 +5933,6 @@ bool TMoverParameters::PantFront( bool const State, range_t const Notify ) } } else { - PantFrontStart = 1; if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( @@ -5969,7 +5974,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify ) if( PantRearUp != State ) { PantRearUp = State; if( State == true ) { - PantRearStart = 0; if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( @@ -5980,7 +5984,6 @@ bool TMoverParameters::PantRear( bool const State, range_t const Notify ) } } else { - PantRearStart = 1; if( Notify != range_t::local ) { // wysłanie wyłączenia do pozostałych? SendCtrlToNext( @@ -6913,12 +6916,7 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c bool const initialstate { Doors.instances[Door].open_permit }; - if( ( false == Doors.permit_presets.empty() ) // HACK: for cases where preset switch is used before battery - || ( ( true == Battery ) - && ( false == Doors.is_locked ) ) ) { - - Doors.instances[ Door ].open_permit = State; - } + Doors.instances[ Door ].open_permit = State; if( Notify != range_t::local ) { @@ -6937,6 +6935,34 @@ bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t c return ( Doors.instances[ Door ].open_permit != initialstate ); } +bool TMoverParameters::ChangeDoorControlMode( bool const State, range_t const Notify ) { + + auto const initialstate { Doors.remote_only }; + + Doors.remote_only = State; + if( Notify != range_t::local ) { + // wysłanie wyłączenia do pozostałych? + SendCtrlToNext( + "DoorMode", + ( State == true ? + 1 : + 0 ), + CabNo, + ( Notify == range_t::unit ? + coupling::control | coupling::permanent : + coupling::control ) ); + } + + if( true == State ) { + // when door are put in remote control mode they're automatically open + // TBD, TODO: make it dependant on config switch? + OperateDoors( side::left, true ); + OperateDoors( side::right, true ); + } + + return ( Doors.step_enabled != initialstate ); +} + bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) { auto &door { Doors.instances[ Door ] }; @@ -7044,15 +7070,17 @@ TMoverParameters::update_doors( double const Deltatime ) { // NBMX Obsluga drzwi, MC: zuniwersalnione auto const localopencontrol { - ( Doors.open_control == control_t::passenger ) - || ( Doors.open_control == control_t::mixed ) }; + ( false == Doors.remote_only ) + && ( ( Doors.open_control == control_t::passenger ) + || ( Doors.open_control == control_t::mixed ) ) }; auto const remoteopencontrol { ( Doors.open_control == control_t::driver ) || ( Doors.open_control == control_t::conductor ) || ( Doors.open_control == control_t::mixed ) }; auto const localclosecontrol { - ( Doors.close_control == control_t::passenger ) - || ( Doors.close_control == control_t::mixed ) }; + ( false == Doors.remote_only ) + && ( ( Doors.close_control == control_t::passenger ) + || ( Doors.close_control == control_t::mixed ) ) }; auto const remoteclosecontrol { ( Doors.close_control == control_t::driver ) || ( Doors.close_control == control_t::conductor ) @@ -7080,7 +7108,7 @@ TMoverParameters::update_doors( double const Deltatime ) { && ( door.step_position <= 0.f ); door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); - door.remote_open = door.remote_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); + door.remote_open = ( door.remote_open || Doors.remote_only ) && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); door.local_close = door.local_close && ( false == door.is_closed ); door.remote_close = door.remote_close && ( false == door.is_closed ); @@ -8732,6 +8760,14 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { lookup->second : start_t::manual; } + // pantograph compressor + { + auto lookup = starts.find( extract_value( "PantCompressorStart", line ) ); + PantographCompressorStart = + lookup != starts.end() ? + lookup->second : + start_t::manual; + } // fuel pump { auto lookup = starts.find( extract_value( "FuelStart", line ) ); @@ -10046,6 +10082,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C false ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } + else if( Command == "DoorMode" ) { + Doors.remote_only = ( + CValue1 == 1 ? + true : + false ); + OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + } else if( Command == "DepartureSignal" ) { DepartureSignal = ( CValue1 == 1 ? @@ -10062,12 +10105,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C if ((CValue1 == 1)) { PantFrontUp = true; - PantFrontStart = 0; } else if ((CValue1 == 0)) { PantFrontUp = false; - PantFrontStart = 1; } } else @@ -10077,24 +10118,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) { PantFrontUp = true; - PantFrontStart = 0; } else { PantRearUp = true; - PantRearStart = 0; } else if ((CValue1 == 0)) if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) { PantFrontUp = false; - PantFrontStart = 1; } else { PantRearUp = false; - PantRearStart = 1; } } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); @@ -10107,12 +10144,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C if ((CValue1 == 1)) { PantRearUp = true; - PantRearStart = 0; } else if ((CValue1 == 0)) { PantRearUp = false; - PantRearStart = 1; } } else @@ -10123,24 +10158,20 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) { PantRearUp = true; - PantRearStart = 0; } else { PantFrontUp = true; - PantFrontStart = 0; } else if ((CValue1 == 0)) if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) { PantRearUp = false; - PantRearStart = 1; } else { PantFrontUp = false; - PantFrontStart = 1; } } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); diff --git a/Train.cpp b/Train.cpp index 53aef0c1..a52d36b9 100644 --- a/Train.cpp +++ b/Train.cpp @@ -327,6 +327,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::dooropenall, &TTrain::OnCommand_dooropenall }, { user_command::doorcloseall, &TTrain::OnCommand_doorcloseall }, { user_command::doorsteptoggle, &TTrain::OnCommand_doorsteptoggle }, + { user_command::doormodetoggle, &TTrain::OnCommand_doormodetoggle }, { user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease }, { user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect }, { user_command::departureannounce, &TTrain::OnCommand_departureannounce }, @@ -778,7 +779,7 @@ void TTrain::OnCommand_mastercontrollerincrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { // on press or hold if( ( Train->ggJointCtrl.SubModel != nullptr ) - && ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { + && ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) { OnCommand_independentbrakedecrease( Train, Command ); } else { @@ -798,7 +799,7 @@ void TTrain::OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { // on press or hold if( ( Train->ggJointCtrl.SubModel != nullptr ) - && ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { + && ( Train->mvOccupied->LocalBrakePosA > 0.0 ) ) { OnCommand_independentbrakedecreasefast( Train, Command ); } else { @@ -1722,10 +1723,11 @@ void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Co } } +// TODO: replace battery with a two-state device, update switch code accordingly void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) { - if( Command.action == GLFW_PRESS ) { - // only reacting to press, so the switch doesn't flip back and forth if key is held down + if( Command.action != GLFW_REPEAT ) { + // keep the switch from flipping back and forth if key is held down if( false == Train->mvOccupied->Battery ) { // turn on OnCommand_batteryenable( Train, Command ); @@ -1739,16 +1741,13 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command ) { - if( true == Train->mvOccupied->Battery ) { return; } // already on - if( Command.action == GLFW_PRESS ) { - // ignore repeats - // wyłącznik jest też w SN61, ewentualnie załączać prąd na stałe z poziomu FIZ + // visual feedback + Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch ); + + if( true == Train->mvOccupied->Battery ) { return; } // already on + if( Train->mvOccupied->BatterySwitch( true ) ) { - // bateria potrzebna np. do zapalenia świateł - if( Train->ggBatteryButton.SubModel ) { - Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch ); - } // side-effects if( Train->mvOccupied->LightsPosNo > 0 ) { Train->SetLights(); @@ -1760,19 +1759,23 @@ void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command } } } + else if( Command.action == GLFW_RELEASE ) { + if( Train->ggBatteryButton.type() == TGaugeType::push ) { + // return the switch to neutral position + Train->ggBatteryButton.UpdateValue( 0.5f ); + } + } } void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Command ) { - - if( false == Train->mvOccupied->Battery ) { return; } // already off - + // TBD, TODO: ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora if( Command.action == GLFW_PRESS ) { - // ignore repeats + // visual feedback + Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch ); + + if( false == Train->mvOccupied->Battery ) { return; } // already off + if( Train->mvOccupied->BatterySwitch( false ) ) { - // ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora - if( Train->ggBatteryButton.SubModel ) { - Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch ); - } // side-effects if( false == Train->mvControlled->ConverterFlag ) { // if there's no (low voltage) power source left, drop pantographs @@ -1781,6 +1784,12 @@ void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Comman } } } + else if( Command.action == GLFW_RELEASE ) { + if( Train->ggBatteryButton.type() == TGaugeType::push ) { + // return the switch to neutral position + Train->ggBatteryButton.UpdateValue( 0.5f ); + } + } } void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &Command ) { @@ -4725,6 +4734,13 @@ void TTrain::OnCommand_doorsteptoggle( TTrain *Train, command_data const &Comman } } +void TTrain::OnCommand_doormodetoggle( TTrain *Train, command_data const &Command ) { + + if( Command.action == GLFW_PRESS ) { + Train->mvOccupied->ChangeDoorControlMode( false == Train->mvOccupied->Doors.remote_only ); + } +} + void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) { if( ( true == FreeFlyModeFlag ) @@ -7456,9 +7472,10 @@ void TTrain::clear_cab_controls() void TTrain::set_cab_controls( int const Cab ) { // switches // battery - if( true == mvOccupied->Battery ) { - ggBatteryButton.PutValue( 1.f ); - } + ggBatteryButton.PutValue( + ( ggBatteryButton.type() == TGaugeType::push ? 0.5f : + mvOccupied->Battery ? 1.f : + 0.f ) ); // motor connectors ggStLinOffButton.PutValue( ( mvControlled->StLinSwitchOff ? @@ -8026,6 +8043,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con } // TODO: move viable dedicated gauges to the automatic array std::unordered_map const autoboolgauges = { + { "doormode_sw:", &mvOccupied->Doors.remote_only }, { "doorstep_sw:", &mvOccupied->Doors.step_enabled }, { "coolingfans_sw:", &mvControlled->RVentForceOn } }; diff --git a/Train.h b/Train.h index 208cea21..11f9098a 100644 --- a/Train.h +++ b/Train.h @@ -329,6 +329,7 @@ class TTrain static void OnCommand_dooropenall( TTrain *Train, command_data const &Command ); static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command ); static void OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command ); + static void OnCommand_doormodetoggle( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command ); static void OnCommand_departureannounce( TTrain *Train, command_data const &Command ); diff --git a/command.cpp b/command.cpp index 25eeac6c..ea77daed 100644 --- a/command.cpp +++ b/command.cpp @@ -154,6 +154,7 @@ commanddescription_sequence Commands_descriptions = { { "doorcloseright", command_target::vehicle }, { "doorcloseall", command_target::vehicle }, { "doorsteptoggle", command_target::vehicle }, + { "doormodetoggle", command_target::vehicle }, { "departureannounce", command_target::vehicle }, { "doorlocktoggle", command_target::vehicle }, { "pantographcompressorvalvetoggle", command_target::vehicle }, diff --git a/command.h b/command.h index 9e321ffe..76f87aea 100644 --- a/command.h +++ b/command.h @@ -147,6 +147,7 @@ enum class user_command { doorcloseright, doorcloseall, doorsteptoggle, + doormodetoggle, departureannounce, doorlocktoggle, pantographcompressorvalvetoggle, diff --git a/driverkeyboardinput.cpp b/driverkeyboardinput.cpp index 1b530384..3d8d3a08 100644 --- a/driverkeyboardinput.cpp +++ b/driverkeyboardinput.cpp @@ -156,6 +156,7 @@ driverkeyboard_input::default_bindings() { // doorcloseright, { user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control }, // doorsteptoggle, + { user_command::doormodetoggle, GLFW_KEY_SLASH | keymodifier::shift | keymodifier::control }, { user_command::departureannounce, GLFW_KEY_SLASH }, { user_command::doorlocktoggle, GLFW_KEY_S | keymodifier::control }, { user_command::pantographcompressorvalvetoggle, GLFW_KEY_V | keymodifier::control }, diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index e74cc17c..4d5b3130 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -633,6 +633,9 @@ drivermouse_input::default_bindings() { { "doorstep_sw:", { user_command::doorsteptoggle, user_command::none } }, + { "doormode_sw:", { + user_command::doormodetoggle, + user_command::none } }, { "departure_signal_bt:", { user_command::departureannounce, user_command::none } }, diff --git a/translation.cpp b/translation.cpp index cd7d56bc..fe0df205 100644 --- a/translation.cpp +++ b/translation.cpp @@ -131,6 +131,7 @@ init() { "all doors (open)", "all doors (close)", "doorstep", + "door control mode", "departure signal", "upper headlight", "left headlight", @@ -296,6 +297,7 @@ init() { "drzwi (otworz)", "drzwi (zamknij)", "stopien drzwi", + "tryb sterowania drzwiami", "sygnal odjazdu", "reflektor gorny", "reflektor lewy", @@ -414,6 +416,7 @@ init() { "doorallon_sw:", "dooralloff_sw:", "doorstep_sw:", + "doormode_sw:", "departure_signal_bt:", "upperlight_sw:", "leftlight_sw:", diff --git a/translation.h b/translation.h index 18edda94..71bec11c 100644 --- a/translation.h +++ b/translation.h @@ -120,6 +120,7 @@ enum string { cab_doorallon_sw, cab_dooralloff_sw, cab_doorstep_sw, + cab_doormode_sw, cab_departure_signal_bt, cab_upperlight_sw, cab_leftlight_sw, diff --git a/version.h b/version.h index 7bcb12d5..5ee96a7f 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 430 +#define VERSION_MINOR 504 #define VERSION_REVISION 0 From 9185030b4be2243d38971c535a7e810b04d214f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 7 May 2019 22:33:15 +0200 Subject: [PATCH 14/24] Autoreturn for MHZ_K8P --- Train.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Train.cpp b/Train.cpp index a52d36b9..e78c333d 100644 --- a/Train.cpp +++ b/Train.cpp @@ -646,7 +646,8 @@ void TTrain::zero_charging_train_brake() { && ( DynamicObject->Controller != AIdriver ) && ( Global.iFeedbackMode < 3 ) && ( ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) - || ( mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57 ) ) ) { + || (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_EN57) + || (mvOccupied->BrakeHandle == TBrakeHandle::MHZ_K8P)) ) { // Odskakiwanie hamulce EP set_train_brake( 0 ); } From 2db964ea402b806f5d84916ca3b1a2f26a56b425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Wed, 8 May 2019 21:44:19 +0200 Subject: [PATCH 15/24] Additionl 0 position for EIM EMUs, configurable Elf controller, first try of speedcontrol for EN57A --- Driver.cpp | 24 ++++++++--------- McZapkie/MOVER.h | 2 ++ McZapkie/Mover.cpp | 65 ++++++++++++++++++++++++++++++++++------------ 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 15275845..f4561e68 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2844,20 +2844,20 @@ bool TController::IncBrake() bool TController::IncBrakeEIM() { // zwiększenie hamowania bool OK = false; - switch (mvControlling->EIMCtrlType) + switch (mvOccupied->EIMCtrlType) { case 0: - OK = mvControlling->IncLocalBrakeLevel(1); + OK = mvOccupied->IncLocalBrakeLevel(1); break; case 1: - OK = mvControlling->MainCtrlPos > 0; + OK = mvOccupied->MainCtrlPos > 0; if (OK) - mvControlling->MainCtrlPos = 0; + mvOccupied->MainCtrlPos = 0; break; case 2: - OK = mvControlling->MainCtrlPos > 1; + OK = mvOccupied->MainCtrlPos > 1; if (OK) - mvControlling->MainCtrlPos = 1; + mvOccupied->MainCtrlPos = 1; break; } return OK; @@ -2936,20 +2936,20 @@ bool TController::DecBrake() bool TController::DecBrakeEIM() { // zmniejszenie siły hamowania bool OK = false; - switch (mvControlling->EIMCtrlType) + switch (mvOccupied->EIMCtrlType) { case 0: - OK = mvControlling->DecLocalBrakeLevel(1); + OK = mvOccupied->DecLocalBrakeLevel(1); break; case 1: - OK = mvControlling->MainCtrlPos < 2; + OK = mvOccupied->MainCtrlPos < 2; if (OK) - mvControlling->MainCtrlPos = 2; + mvOccupied->MainCtrlPos = 2; break; case 2: - OK = mvControlling->MainCtrlPos < 3; + OK = mvOccupied->MainCtrlPos < 3; if (OK) - mvControlling->MainCtrlPos = 3; + mvOccupied->MainCtrlPos = 3; break; } return OK; diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 9092074c..a286f238 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -1312,6 +1312,8 @@ public: double eim_localbrake = 0; /*nastawa hamowania dodatkowego pneumatycznego lokomotywy*/ int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/ bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/ + int SpeedCtrlAutoTurnOffFlag = 0; /*czy tempomat sam się wyłącza*/ + bool EIMCtrlAdditionalZeros = false; /*czy ma dodatkowe zero jazdy i zero hamowania */ double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/ double eimv[21]; static std::vector const eimv_labels; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 67c43ee4..93f048f6 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2001,6 +2001,10 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) ScndCtrlActualPos = Round(Vel); else ScndCtrlActualPos = Round(Vel * 0.5); + if ((EIMCtrlType == 0)&&(SpeedCtrlAutoTurnOffFlag == 1)) + { + MainCtrlActualPos = MainCtrlPos; + } SendCtrlToNext("SpeedCntrl", ScndCtrlActualPos, CabNo); } @@ -6018,6 +6022,13 @@ void TMoverParameters::CheckEIMIC(double dt) { case 0: eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : (double)MainCtrlPos / (double)MainCtrlPosNo); + if (EIMCtrlAdditionalZeros) + { + if (eimic > 0.001) + eimic = std::max(0.002, eimic * (double)MainCtrlPosNo / ((double)MainCtrlPosNo - 1.0) - 1.0 / ((double)MainCtrlPosNo - 1.0)); + if (eimic < -0.001) + eimic = std::min(-0.002, eimic * (double)LocalBrakePosNo / ((double)LocalBrakePosNo - 1.0) + 1.0 / ((double)LocalBrakePosNo - 1.0)); + } break; case 1: switch (MainCtrlPos) @@ -6068,23 +6079,34 @@ void TMoverParameters::CheckEIMIC(double dt) } break; case 2: - switch (MainCtrlPos) + if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay)) { - case 0: - case 1: - eimic -= clamp(1.0 + eimic, 0.0, dt*0.15); //odejmuj do -1 - if (eimic > 0) eimic = 0; - break; - case 2: - eimic -= clamp(0.0 + eimic, 0.0, dt*0.15); //odejmuj do 0 - break; - case 3: - eimic += clamp(0.0 - eimic, 0.0, dt*0.15); //dodawaj do 0 - break; - case 4: - eimic += clamp(1.0 - eimic, 0.0, dt*0.15); //dodawaj do 1 - if (eimic < 0) eimic = 0; - break; + double delta = (MainCtrlActualPos == MainCtrlPos ? dt*CtrlDelay : 0.01); + switch (MainCtrlPos) + { + case 0: + case 1: + eimic -= clamp(1.0 + eimic, 0.0, delta); //odejmuj do -1 + if (eimic > 0) eimic = 0; + break; + case 2: + eimic -= clamp(0.0 + eimic, 0.0, delta); //odejmuj do 0 + break; + case 3: + eimic += clamp(0.0 - eimic, 0.0, delta); //dodawaj do 0 + break; + case 4: + eimic += clamp(1.0 - eimic, 0.0, delta); //dodawaj do 1 + if (eimic < 0) eimic = 0; + break; + } + } + if (MainCtrlActualPos == MainCtrlPos) + LastRelayTime += dt; + else + { + LastRelayTime = 0; + MainCtrlActualPos = MainCtrlPos; } break; case 3: @@ -6108,6 +6130,15 @@ void TMoverParameters::CheckSpeedCtrl() eimicSpeedCtrl = clamp(0.5 * (ScndCtrlActualPos * 2 - Vel), -1.0, 1.0); else eimicSpeedCtrl = 1; + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) + { + DecScndCtrl(1); + if (CabNo == 0) + { + SendCtrlToNext("ScndCtrl", ScndCtrlPos, 1); + SendCtrlToNext("ScndCtrl", ScndCtrlPos, -1); + } + } } // ************************************************************************************************* @@ -8708,6 +8739,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { extract_value( EIMCtrlType, "EIMCtrlType", line, "" ); clamp( EIMCtrlType, 0, 3 ); LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes"); + EIMCtrlAdditionalZeros = (extract_value("EIMCtrlAddZeros", line) == "Yes"); extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR @@ -8730,6 +8762,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { (extract_value("SpeedCtrlType", line) == "Time") ? true : false; + extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", line, ""); // converter { From bbdc67c9b298a62413d9178cb64d2f38fd3a1908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Thu, 9 May 2019 19:39:23 +0200 Subject: [PATCH 16/24] Fixed speedcontrol for EN57A --- McZapkie/Mover.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 93f048f6..fb83ef35 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1691,7 +1691,9 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) else { ++MainCtrlPos; OK = true; - } + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) + DecScndCtrl(2); + } break; } @@ -1853,6 +1855,8 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) { MainCtrlPos--; OK = true; + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) + DecScndCtrl(2); } else if (CtrlSpeed > 1) OK = (DecMainCtrl(1) && DecMainCtrl(2)); // CtrlSpeed-1); @@ -1994,7 +1998,7 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) if (LastRelayTime > CtrlDelay) LastRelayTime = 0; - if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1)) + if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1) && (MainCtrlPos>0)) { // NOTE: round() already adds 0.5, are the ones added here as well correct? if ((Vmax < 250)) @@ -6130,15 +6134,6 @@ void TMoverParameters::CheckSpeedCtrl() eimicSpeedCtrl = clamp(0.5 * (ScndCtrlActualPos * 2 - Vel), -1.0, 1.0); else eimicSpeedCtrl = 1; - if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag == 1) && (MainCtrlActualPos != MainCtrlPos)) - { - DecScndCtrl(1); - if (CabNo == 0) - { - SendCtrlToNext("ScndCtrl", ScndCtrlPos, 1); - SendCtrlToNext("ScndCtrl", ScndCtrlPos, -1); - } - } } // ************************************************************************************************* From bddb0575bf5376e64cc9fab9140210c31c5fc400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sat, 11 May 2019 13:46:07 +0200 Subject: [PATCH 17/24] Changed turbo modulation, AI can drive DMUs with constant speed --- Driver.cpp | 16 ++++++++++++++++ DynObj.cpp | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Driver.cpp b/Driver.cpp index f4561e68..fdc7b3c2 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3510,6 +3510,22 @@ void TController::SetTimeControllers() mvOccupied->ScndCtrlPos = 1; } } + //5. Check Main Controller in Dizels + if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->hydro_TC)) + { + int MaxPos = mvControlling->MainCtrlPosNo; + int MinPos = MaxPos; + for (int i = MaxPos; (i > 1) && (mvControlling->RList[i].Mn > 0); i--) MinPos = i; + if ((MaxPos > MinPos)&&(mvControlling->MainCtrlPos>0)&&(AccDesired>0)) + { + double Factor = 5 * (mvControlling->Vmax) / (mvControlling->Vmax + mvControlling->Vel); + int DesiredPos = MinPos + (MaxPos - MinPos)*(VelDesired > mvControlling->Vel ? (VelDesired - mvControlling->Vel) / Factor : 0); + if (DesiredPos > MaxPos) DesiredPos = MaxPos; + if (DesiredPos < MinPos) DesiredPos = MinPos; + while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1); + while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1); + } + } }; void TController::CheckTimeControllers() diff --git a/DynObj.cpp b/DynObj.cpp index 4f39db3a..6008549d 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -6624,7 +6624,8 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub // youBy - przenioslem, bo diesel tez moze miec turbo if( Vehicle.TurboTest > 0 ) { // udawanie turbo: - auto const goalpitch { std::max( 0.025, ( engine_volume + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; + auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax : 0 }; + auto const goalpitch { std::max( 0.025, ( engine_volume + pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; auto const goalvolume { ( ( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ? std::max( 0.0, ( engine_turbo_pitch + engine_turbo.m_amplitudeoffset ) * engine_turbo.m_amplitudefactor ) : From 0b79e7d1b9f7b0bd8b56451e63a85af18742cc48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 12 May 2019 13:35:20 +0200 Subject: [PATCH 18/24] Small fix for AI driving DieselEngine - better cruising in SN61 too --- Driver.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index fdc7b3c2..82af9898 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3511,7 +3511,7 @@ void TController::SetTimeControllers() } } //5. Check Main Controller in Dizels - if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->hydro_TC)) + if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->Vmax>30)) { int MaxPos = mvControlling->MainCtrlPosNo; int MinPos = MaxPos; @@ -3522,8 +3522,12 @@ void TController::SetTimeControllers() int DesiredPos = MinPos + (MaxPos - MinPos)*(VelDesired > mvControlling->Vel ? (VelDesired - mvControlling->Vel) / Factor : 0); if (DesiredPos > MaxPos) DesiredPos = MaxPos; if (DesiredPos < MinPos) DesiredPos = MinPos; - while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1); - while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1); + if (!mvControlling->SlippingWheels) + { + while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1); + if (mvControlling->Vel>mvControlling->dizel_minVelfullengage) + while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1); + } } } }; From 448472c84ac12d5cfcf98f2e695bc529de1929dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 12 May 2019 19:04:30 +0200 Subject: [PATCH 19/24] Another change in turbocharger sound, added rpm in engine ui panel. --- DynObj.cpp | 2 +- driveruipanels.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index 6008549d..e8ad81bd 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -6625,7 +6625,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub if( Vehicle.TurboTest > 0 ) { // udawanie turbo: auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax : 0 }; - auto const goalpitch { std::max( 0.025, ( engine_volume + pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; + auto const goalpitch { std::max( 0.025, ( engine_volume * pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; auto const goalvolume { ( ( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ? std::max( 0.0, ( engine_turbo_pitch + engine_turbo.m_amplitudeoffset ) * engine_turbo.m_amplitudefactor ) : diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 8efa947d..b278f53f 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -717,7 +717,8 @@ debug_panel::update_section_engine( std::vector &Output ) { std::string parameterstext = "param value"; std::vector< std::pair > const paramvalues { - { "efill: ", mover.dizel_fill }, + { " rpm: ", mover.enrot * 60.0 }, + { "efill: ", mover.dizel_fill }, { "etorq: ", mover.dizel_Torque }, { "creal: ", mover.dizel_engage }, { "cdesi: ", mover.dizel_engagestate }, From 1626224dc804f576d1300f15ef30211983653f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Sun, 12 May 2019 23:38:40 +0200 Subject: [PATCH 20/24] departure/arrival time in timetable can be a fraction of minute --- Driver.cpp | 2 +- driveruipanels.cpp | 2 +- mtable.cpp | 24 ++++++++++++------------ mtable.h | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 82af9898..52a62e7b 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1024,7 +1024,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN if (TrainParams->StationIndex < TrainParams->StationCount) { // jeśli są dalsze stacje, czekamy do godziny odjazdu - if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute)) { + if (TrainParams->IsTimeToGo(simulation::Time.data().wHour, simulation::Time.data().wMinute + simulation::Time.data().wSecond*0.0167 )) { // z dalszą akcją czekamy do godziny odjazdu IsAtPassengerStop = false; // przy jakim dystansie (stanie licznika) ma przesunąć na następny postój diff --git a/driveruipanels.cpp b/driveruipanels.cpp index b278f53f..03d44f38 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -353,7 +353,7 @@ timetable_panel::update() { ( owner->iStationStart < table->StationIndex ) && ( i < table->StationIndex ) && ( ( tableline->Ah < 0 ) // pass-through, always valid - || ( time.wHour * 60 + time.wMinute >= tableline->Dh * 60 + tableline->Dm ) ) ); + || ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ); auto traveltime = " " + ( i < 2 ? "" : diff --git a/mtable.cpp b/mtable.cpp index 6aed55d0..3d207cdb 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -52,7 +52,7 @@ bool TTrainParameters::IsStop() const bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) { - return UpdateMTable( Time.data().wHour, Time.data().wMinute, NewName ); + return UpdateMTable( Time.data().wHour, Time.data().wMinute + Time.data().wSecond * 0.0167, NewName ); } bool TTrainParameters::UpdateMTable(double hh, double mm, std::string const &NewName) @@ -358,12 +358,12 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) if (s.find(hrsd) != std::string::npos) { record->Ah = atoi( s.substr(0, s.find(hrsd)).c_str()); // godzina przyjazdu - record->Am = atoi(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta przyjazdu + record->Am = atof(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta przyjazdu } else { record->Ah = TimeTable[StationCount - 1].Ah; // godzina z poprzedniej pozycji - record->Am = atoi(s.c_str()); // bo tylko minuty podane + record->Am = atof(s.c_str()); // bo tylko minuty podane } } do @@ -408,12 +408,12 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) if (s.find(hrsd) != std::string::npos) { record->Dh = atoi(s.substr(0, s.find(hrsd)).c_str()); // godzina odjazdu - record->Dm = atoi(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta odjazdu + record->Dm = atof(s.substr(s.find(hrsd) + 1, s.length()).c_str()); // minuta odjazdu } else { record->Dh = TimeTable[StationCount - 1].Dh; // godzina z poprzedniej pozycji - record->Dm = atoi(s.c_str()); // bo tylko minuty podane + record->Dm = atof(s.c_str()); // bo tylko minuty podane } } else @@ -475,20 +475,20 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) if( timeoffset != 0 ) // jeżeli jest przesunięcie rozkładu { long i_end = StationCount + 1; - int adjustedtime; // do zwiększania czasu + float adjustedtime; // do zwiększania czasu for (auto i = 1; i < i_end; ++i) // bez with, bo ciężko się przenosi na C++ { if ((TimeTable[i].Ah >= 0)) { - adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty - TimeTable[i].Am = adjustedtime % 60; - TimeTable[i].Ah = (adjustedtime / 60) % 24; + adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24.0 * 60.0 ); // nowe minuty + TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.0; + TimeTable[i].Ah = int((adjustedtime) / 60) % 24; } if ((TimeTable[i].Dh >= 0)) { - adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty - TimeTable[i].Dm = adjustedtime % 60; - TimeTable[i].Dh = (adjustedtime / 60) % 24; + adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24.0 * 60.0 ); // nowe minuty + TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.0; + TimeTable[i].Dh = int((adjustedtime) / 60) % 24; } } } diff --git a/mtable.h b/mtable.h index 78816aaa..17191ff1 100644 --- a/mtable.h +++ b/mtable.h @@ -32,9 +32,9 @@ struct TMTableLine std::string StationWare; // typ i wyposazenie stacji, oddz. przecinkami} int TrackNo; // ilosc torow szlakowych int Ah; - int Am; // godz. i min. przyjazdu, -1 gdy bez postoju + double Am; // godz. i min. przyjazdu, -1 gdy bez postoju int Dh; - int Dm; // godz. i min. odjazdu + double Dm; // godz. i min. odjazdu double tm; // czas jazdy do tej stacji w min. (z kolumny) TMTableLine() { From 9cdce2d346e13f218b8badbdb7abdd3ece47e1df Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 14 May 2019 20:15:01 +0200 Subject: [PATCH 21/24] build 190514. partial usage of utf8 in the ui, timetable panel appeaance improvements --- Driver.cpp | 9 ++- driveruipanels.cpp | 134 ++++++++++++++++++++++++---------- driveruipanels.h | 4 +- mtable.cpp | 8 +- mtable.h | 10 +-- simulationstateserializer.cpp | 2 +- uilayer.cpp | 9 ++- utilities.cpp | 20 ++++- utilities.h | 1 + version.h | 2 +- 10 files changed, 144 insertions(+), 55 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 52a62e7b..5fc4ee24 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -6595,17 +6595,18 @@ std::string TController::NextStop() const // dodać godzinę odjazdu if (!TrainParams) return ""; // tu nie powinno nigdy wejść - std::string nextstop = asNextStop; + std::string nextstop = Bezogonkow( asNextStop, true ); TMTableLine *t = TrainParams->TimeTable + TrainParams->StationIndex; if( t->Ah >= 0 ) { // przyjazd - nextstop += " przyj." + std::to_string( t->Ah ) + ":" - + ( t->Am < 10 ? "0" : "" ) + std::to_string( t->Am ); + nextstop += " przyj." + std::to_string( t->Ah ) + ":" + + to_minutes_str( t->Am, true, 3 ); + } if( t->Dh >= 0 ) { // jeśli jest godzina odjazdu nextstop += " odj." + std::to_string( t->Dh ) + ":" - + ( t->Dm < 10 ? "0" : "" ) + std::to_string( t->Dm ); + + to_minutes_str( t->Dm, true, 3 ); } return nextstop; }; diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 03d44f38..6a482e81 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -229,6 +229,7 @@ timetable_panel::update() { if( false == is_open ) { return; } text_lines.clear(); + m_tablelines.clear(); auto const *train { simulation::Train }; auto const *controlled { ( train ? train->Dynamic() : nullptr ) }; @@ -239,7 +240,7 @@ timetable_panel::update() { std::snprintf( m_buffer.data(), m_buffer.size(), locale::strings[ locale::string::driver_timetable_header ].c_str(), - 40, 40, + 37, 37, locale::strings[ locale::string::driver_timetable_name ].c_str(), time.wHour, time.wMinute, @@ -274,7 +275,7 @@ timetable_panel::update() { } { // next station - auto const nextstation = Bezogonkow( owner->NextStop(), true ); + auto const nextstation = owner->NextStop(); if( false == nextstation.empty() ) { // jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania auto textline = " -> " + nextstation; @@ -317,67 +318,126 @@ timetable_panel::update() { } else { + auto const loadingcolor { glm::vec4( 164.0f / 255.0f, 84.0f / 255.0f, 84.0f / 255.0f, 1.f ) }; + auto const waitcolor { glm::vec4( 164.0f / 255.0f, 132.0f / 255.0f, 84.0f / 255.0f, 1.f ) }; auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) }; // header - text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor ); + m_tablelines.emplace_back( u8"┌─────┬────────────────────────────────────┬─────────┬─────┐", Global.UITextColor ); TMTableLine const *tableline; for( int i = owner->iStationStart; i <= table->StationCount; ++i ) { // wyświetlenie pozycji z rozkładu tableline = table->TimeTable + i; // linijka rozkładu - std::string vmax = - " " - + to_string( tableline->vmax, 0 ); - vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej - std::string const station = ( + bool vmaxchange { true }; + if( i > owner->iStationStart ) { + auto const *previoustableline { tableline - 1 }; + if( tableline->vmax == previoustableline->vmax ) { + vmaxchange = false; + } + } + std::string vmax { " " }; + if( true == vmaxchange ) { + vmax += to_string( tableline->vmax, 0 ); + vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej + } + auto const station { ( Bezogonkow( tableline->StationName, true ) + " " ) - .substr( 0, 34 ); - std::string const location = ( + .substr( 0, 34 ) }; + auto const location { ( ( tableline->km > 0.0 ? to_string( tableline->km, 2 ) : "" ) + " " ) - .substr( 0, 34 - tableline->StationWare.size() ); - std::string const arrival = ( + .substr( 0, 34 - tableline->StationWare.size() ) }; + auto const arrival { ( tableline->Ah >= 0 ? - to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Am ) ).substr( 1, 2 ) : - " | " ); - std::string const departure = ( + to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Am, true, 3 ) : + u8" │ " ) }; + auto const departure { ( tableline->Dh >= 0 ? - to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Dm ) ).substr( 1, 2 ) : - " | " ); - auto const candeparture = ( + to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_minutes_str( tableline->Dm, true, 3 ) : + u8" │ " ) }; + auto const candeparture { ( ( owner->iStationStart < table->StationIndex ) && ( i < table->StationIndex ) && ( ( tableline->Ah < 0 ) // pass-through, always valid - || ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ); - auto traveltime = - " " - + ( i < 2 ? "" : - tableline->Ah >= 0 ? to_string( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), 0 ) : - to_string( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), 0 ) ); - traveltime = traveltime.substr( traveltime.size() - 3, 3 ); // z wyrównaniem do prawej - - text_lines.emplace_back( - ( "| " + vmax + " | " + station + " | " + arrival + " | " + traveltime + " |" ), - ( candeparture ? - readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono - Global.UITextColor ) ); - text_lines.emplace_back( - ( "| | " + location + tableline->StationWare + " | " + departure + " | |" ), - ( candeparture ? - readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono - Global.UITextColor ) ); + || ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ) }; + auto const loadchangeinprogress { ( ( static_cast( std::ceil( -1.0 * owner->fStopTime ) ) ) > 0 ) }; + auto const isatpassengerstop { ( true == owner->IsAtPassengerStop ) && ( vehicle->MoverParameters->Vel < 1.0 ) }; + auto const traveltime { ( + i < 2 ? " " : + tableline->Ah >= 0 ? to_minutes_str( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), false, 3 ) : + to_minutes_str( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), false, 3 ) ) }; + auto const linecolor { ( + ( i != owner->iStationStart ) ? Global.UITextColor : + loadchangeinprogress ? loadingcolor : + candeparture ? readycolor : // czas minął i odjazd był, to nazwa stacji będzie na zielono + isatpassengerstop ? waitcolor : + Global.UITextColor ) }; + m_tablelines.emplace_back( + ( u8"│ " + vmax + u8" │ " + station + u8" │ " + arrival + u8" │ " + traveltime + u8" │" ), + linecolor ); + m_tablelines.emplace_back( + ( u8"│ │ " + location + tableline->StationWare + u8" │ " + departure + u8" │ │" ), + linecolor ); // divider/footer - text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor ); + if( i < table->StationCount ) { + auto const *nexttableline { tableline + 1 }; + if( tableline->vmax == nexttableline->vmax ) { + m_tablelines.emplace_back( u8"│ ├────────────────────────────────────┼─────────┼─────┤", Global.UITextColor ); + } + else { + m_tablelines.emplace_back( u8"├─────┼────────────────────────────────────┼─────────┼─────┤", Global.UITextColor ); + } + } + else { + m_tablelines.emplace_back( u8"└─────┴────────────────────────────────────┴─────────┴─────┘", Global.UITextColor ); + } } } } // is_expanded } +void +timetable_panel::render() { + + if( false == is_open ) { return; } + if( true == text_lines.empty() ) { return; } + + auto flags = + ImGuiWindowFlags_NoFocusOnAppearing + | ImGuiWindowFlags_NoCollapse + | ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 ); + + if( size.x > 0 ) { + ImGui::SetNextWindowSize( ImVec2( size.x, size.y ) ); + } + if( size_min.x > 0 ) { + ImGui::SetNextWindowSizeConstraints( ImVec2( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) ); + } + auto const panelname { ( + title.empty() ? + name : + title ) + + "###" + name }; + if( true == ImGui::Begin( panelname.c_str(), &is_open, flags ) ) { + for( auto const &line : text_lines ) { + ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() ); + } + if( is_expanded ) { + ImGui::PushStyleVar( ImGuiStyleVar_ItemSpacing, ImVec2( 1, 0 ) ); + for( auto const &line : m_tablelines ) { + ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() ); + } + ImGui::PopStyleVar(); + } + } + ImGui::End(); +} + void debug_panel::update() { diff --git a/driveruipanels.h b/driveruipanels.h index 28363796..7c075562 100644 --- a/driveruipanels.h +++ b/driveruipanels.h @@ -50,12 +50,14 @@ public: : ui_panel( Name, Isopen ) {} void update() override; + void render() override; bool is_expanded{ false }; private: - // members +// members std::array m_buffer; + std::vector m_tablelines; }; class debug_panel : public ui_panel { diff --git a/mtable.cpp b/mtable.cpp index 3d207cdb..957a4f8d 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -480,14 +480,14 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) { if ((TimeTable[i].Ah >= 0)) { - adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24.0 * 60.0 ); // nowe minuty - TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.0; + adjustedtime = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 24 * 60 ); // nowe minuty + TimeTable[i].Am = (int(60 * adjustedtime) % 3600) / 60.f; TimeTable[i].Ah = int((adjustedtime) / 60) % 24; } if ((TimeTable[i].Dh >= 0)) { - adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24.0 * 60.0 ); // nowe minuty - TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.0; + adjustedtime = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 24 * 60 ); // nowe minuty + TimeTable[i].Dm = (int(60 * adjustedtime) % 3600) / 60.f; TimeTable[i].Dh = int((adjustedtime) / 60) % 24; } } diff --git a/mtable.h b/mtable.h index 17191ff1..b0bea8bd 100644 --- a/mtable.h +++ b/mtable.h @@ -24,18 +24,18 @@ static char const *hrsd = "."; struct TMTableLine { - double km; // kilometraz linii - double vmax; // predkosc rozkladowa przed przystankiem + float km; // kilometraz linii + float vmax; // predkosc rozkladowa przed przystankiem // StationName:string[32]; //nazwa stacji ('_' zamiast spacji) // StationWare:string[32]; //typ i wyposazenie stacji, oddz. przecinkami} std::string StationName; // nazwa stacji ('_' zamiast spacji) std::string StationWare; // typ i wyposazenie stacji, oddz. przecinkami} int TrackNo; // ilosc torow szlakowych int Ah; - double Am; // godz. i min. przyjazdu, -1 gdy bez postoju + float Am; // godz. i min. przyjazdu, -1 gdy bez postoju int Dh; - double Dm; // godz. i min. odjazdu - double tm; // czas jazdy do tej stacji w min. (z kolumny) + float Dm; // godz. i min. odjazdu + float tm; // czas jazdy do tej stacji w min. (z kolumny) TMTableLine() { km = 0; diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index e28992a0..10f20e2e 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -179,7 +179,7 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch Global.fFogEnd = clamp( Random( std::min( fograngestart, fograngeend ), std::max( fograngestart, fograngeend ) ), - 100.0, 2000.0 ); + 10.0, 2000.0 ); } std::string token { Input.getToken() }; diff --git a/uilayer.cpp b/uilayer.cpp index 6ad6929f..c5aea330 100644 --- a/uilayer.cpp +++ b/uilayer.cpp @@ -74,8 +74,15 @@ ui_layer::init( GLFWwindow *Window ) { IMGUI_CHECKVERSION(); ImGui::CreateContext(); + + static ImWchar const glyphranges[] = { + 0x0020, 0x00FF, // ascii + extension + 0x2070, 0x2079, // superscript + 0x2500, 0x256C, // box drawings + 0, + }; m_imguiio = &ImGui::GetIO(); -// m_imguiio->Fonts->AddFontFromFileTTF( "c:/windows/fonts/lucon.ttf", 13.0f ); + m_imguiio->Fonts->AddFontFromFileTTF( "fonts/dejavusansmono.ttf", 13.0f, nullptr, &glyphranges[ 0 ] ); ImGui_ImplGlfw_InitForOpenGL( m_window, false ); #ifdef EU07_USEIMGUIIMPLOPENGL2 diff --git a/utilities.cpp b/utilities.cpp index 971b034d..4c9953b1 100644 --- a/utilities.cpp +++ b/utilities.cpp @@ -1,4 +1,4 @@ -/* +/* 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 @@ -246,6 +246,24 @@ std::string to_hex_str( int const Value, int const Width ) return converter.str(); }; +char * const fractionlabels[] = { " ", u8"¹", u8"²", u8"³", u8"⁴", u8"⁵", u8"⁶", u8"⁷", u8"⁸", u8"⁹" }; + +std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width ) { + + float minutesintegral; + auto const minutesfractional { std::modf( Minutes, &minutesintegral ) }; + auto const width { Width - 1 }; + auto minutes = ( + std::string( width - 1, ' ' ) + + ( Leadingzero ? + to_string( 100 + minutesintegral ).substr( 1, 2 ) : + to_string( minutesintegral, 0 ) ) ); + return ( + minutes.substr( minutes.size() - width, width ) + + fractionlabels[ static_cast( std::floor( minutesfractional * 10 + 0.1 ) ) ] ); +} + + int stol_def(const std::string &str, const int &DefaultValue) { int result { DefaultValue }; diff --git a/utilities.h b/utilities.h index 400f12df..1c930f7a 100644 --- a/utilities.h +++ b/utilities.h @@ -107,6 +107,7 @@ std::string to_string(double Value); std::string to_string(double Value, int precision); std::string to_string(double Value, int precision, int width); std::string to_hex_str( int const Value, int const width = 4 ); +std::string to_minutes_str( float const Minutes, bool const Leadingzero, int const Width ); inline std::string to_string(bool Value) { diff --git a/version.h b/version.h index 5ee96a7f..f3ad8c74 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 504 +#define VERSION_MINOR 514 #define VERSION_REVISION 0 From a7393bac953899bb0f1f69426c507fca40a52bde Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 22 May 2019 16:29:00 +0200 Subject: [PATCH 22/24] controlled vehicle lookup enhancement --- DynObj.cpp | 46 ++++++++++++++++++++++++---------------------- Train.cpp | 25 ++++--------------------- 2 files changed, 28 insertions(+), 43 deletions(-) diff --git a/DynObj.cpp b/DynObj.cpp index e8ad81bd..6f2f3eaf 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -6120,30 +6120,32 @@ TDynamicObject * TDynamicObject::ControlledFind() // problematyczna może być kwestia wybranej kabiny (w silnikowym...) // jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno jeździć dobrze // również hamowanie wykonuje się zaworem w członie, a nie w silnikowym... - TDynamicObject *d = this; // zaczynamy od aktualnego - if( ( d->MoverParameters->TrainType == dt_EZT ) - || ( d->MoverParameters->TrainType == dt_DMU ) ) { - // na razie dotyczy to EZT - if( ( d->NextConnected() != nullptr ) - && ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) { - // gdy jest człon od sprzęgu 1, a sprzęg łączony warsztatowo (powiedzmy) - if( ( d->MoverParameters->Power < 1.0 ) - && ( d->NextConnected()->MoverParameters->Power > 1.0 ) ) { - // my nie mamy mocy, ale ten drugi ma - d = d->NextConnected(); // będziemy sterować tym z mocą - } - } - else if( ( d->PrevConnected() != nullptr ) - && ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) { - // gdy jest człon od sprzęgu 0, a sprzęg łączony warsztatowo (powiedzmy) - if( ( d->MoverParameters->Power < 1.0 ) - && ( d->PrevConnected()->MoverParameters->Power > 1.0 ) ) { - // my nie mamy mocy, ale ten drugi ma - d = d->PrevConnected(); // będziemy sterować tym z mocą - } + if( MoverParameters->Power > 1.0 ) { return this; } + + auto const couplingtype { ( + ( MoverParameters->TrainType == dt_EZT ) + || ( MoverParameters->TrainType == dt_DMU ) ) ? + coupling::permanent : + coupling::control + }; + // try first to look towards the rear + auto *d = this; // zaczynamy od aktualnego + + while( ( d = d->NextC( couplingtype ) ) != nullptr ) { + if( d->MoverParameters->Power > 1.0 ) { + return d; } } - return d; + // if we didn't yet find a suitable vehicle try in the other direction + d = this; // zaczynamy od aktualnego + + while( ( d = d->PrevC( couplingtype ) ) != nullptr ) { + if( d->MoverParameters->Power > 1.0 ) { + return d; + } + } + // if we still don't have a match give up + return this; }; //--------------------------------------------------------------------------- diff --git a/Train.cpp b/Train.cpp index e78c333d..fa4135a5 100644 --- a/Train.cpp +++ b/Train.cpp @@ -7128,28 +7128,11 @@ void TTrain::DynamicSet(TDynamicObject *d) // jeździć dobrze // również hamowanie wykonuje się zaworem w członie, a nie w silnikowym... DynamicObject = d; // jedyne miejsce zmiany - mvOccupied = mvControlled = d ? DynamicObject->MoverParameters : NULL; // albo silnikowy w EZT - if (!DynamicObject) - return; - // TODO: leverage code already present in TDynamicObject::ControlledFind() - if( ( d->MoverParameters->TrainType == dt_EZT ) - || ( d->MoverParameters->TrainType == dt_DMU ) ) { + mvOccupied = mvControlled = ( d ? DynamicObject->MoverParameters : nullptr ); // albo silnikowy w EZT - if( ( d->NextConnected() != nullptr ) - && ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) { - if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 1 ].Connected->Power > 1.0 ) ) { - // my nie mamy mocy, ale ten drugi ma - mvControlled = DynamicObject->NextConnected()->MoverParameters; // będziemy sterować tym z mocą - } - } - else if( ( d->PrevConnected() != nullptr ) - && ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) { - if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 0 ].Connected->Power > 1.0 ) ) { - // my nie mamy mocy, ale ten drugi ma - mvControlled = DynamicObject->PrevConnected()->MoverParameters; // będziemy sterować tym z mocą - } - } - } + if( DynamicObject == nullptr ) { return; } + + mvControlled = DynamicObject->ControlledFind()->MoverParameters; mvSecond = NULL; // gdyby się nic nie znalazło if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo if (mvOccupied->Couplers[1].Connected ? From 06f099dca18ff80542ad9de4e36d854a03510940 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 22 May 2019 20:51:11 +0200 Subject: [PATCH 23/24] build 190522. minor ai logic tweaks, impulse type heating switch support --- Driver.cpp | 19 ++++++++++++------- Driver.h | 6 +++++- Train.cpp | 23 +++++++++++++++++++---- version.h | 2 +- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 5fc4ee24..46369124 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2127,11 +2127,12 @@ bool TController::CheckVehicles(TOrders user) while (p) { // HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi... - if( ( p != pVehicle ) - && ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 ) - && ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) { - // NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly - p->MoverParameters->BatterySwitch( true ); + if( p != pVehicle ) { + if( ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 ) + && ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) { + // NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly + p->MoverParameters->BatterySwitch( true ); + } // enable heating and converter in carriages with can be heated if( p->MoverParameters->HeatingPower > 0 ) { p->MoverParameters->HeatingAllow = true; @@ -2730,8 +2731,12 @@ bool TController::IncBrake() // NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself // TODO: add easier ways to access front/rear coupler taking into account vehicle's direction standalone = - ( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) ) - && ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) ) ); + ( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) + || ( ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) + && ( vehicle->MoverParameters->Couplers[ end::front ].Connected->Power > 1 ) ) ) + && ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) + || ( ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) + && ( vehicle->MoverParameters->Couplers[ end::rear ].Connected->Power > 1 ) ) ) ); vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła) } } diff --git a/Driver.h b/Driver.h index 2b0a8053..96067b79 100644 --- a/Driver.h +++ b/Driver.h @@ -201,6 +201,10 @@ public: inline TMoverParameters const *Controlling() const { return mvControlling; } + inline + TMoverParameters const *Occupied() const { + return mvOccupied; + } void DirectionInitial(); void DirectionChange(); inline @@ -251,6 +255,7 @@ public: bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami + double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller private: bool Psyche = false; int HelperState = 0; //stan pomocnika maszynisty @@ -318,7 +323,6 @@ private: double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca double BrakeChargingCooldown {}; // prevents the ai from trying to charge the train brake too frequently - double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller double LastReactionTime = 0.0; double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations diff --git a/Train.cpp b/Train.cpp index fa4135a5..6166f457 100644 --- a/Train.cpp +++ b/Train.cpp @@ -4140,7 +4140,7 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command } if( Command.action == GLFW_PRESS ) { - // only reacting to press, so the switch doesn't flip back and forth if key is held down + // ignore repeats so the switch doesn't flip back and forth if key is held down if( false == Train->mvControlled->HeatingAllow ) { // turn on OnCommand_heatingenable( Train, Command ); @@ -4150,6 +4150,14 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command OnCommand_heatingdisable( Train, Command ); } } + else if( Command.action == GLFW_RELEASE ) { + + if( Train->ggTrainHeatingButton.type() == TGaugeType::push ) { + // impulse switch + // visual feedback + Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch ); + } + } } void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) { @@ -4168,7 +4176,11 @@ void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Comman Train->mvControlled->HeatingAllow = false; // visual feedback - Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch ); + Train->ggTrainHeatingButton.UpdateValue( + ( Train->ggTrainHeatingButton.type() == TGaugeType::push ? + 1.0 : + 0.0 ), + Train->dsbSwitch ); } } @@ -7637,8 +7649,11 @@ void TTrain::set_cab_controls( int const Cab ) { 1.f : 0.f ); // heating - if( true == mvControlled->Heating ) { - ggTrainHeatingButton.PutValue( 1.f ); + if( ggTrainHeatingButton.type() != TGaugeType::push ) { + ggTrainHeatingButton.PutValue( + mvControlled->Heating ? + 1.f : + 0.f ); } // brake acting time if( ggBrakeProfileCtrl.SubModel != nullptr ) { diff --git a/version.h b/version.h index f3ad8c74..5424911c 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 514 +#define VERSION_MINOR 522 #define VERSION_REVISION 0 From 39596c76ba260a25f6f06e8aa8f5fb67401a8da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Wed, 22 May 2019 19:42:52 +0200 Subject: [PATCH 24/24] Parameters of DieselEngine for Python dictionary --- Train.cpp | 47 +++++++++++++++++++++++++++++++++++------------ Train.h | 1 + 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Train.cpp b/Train.cpp index 6166f457..1870279e 100644 --- a/Train.cpp +++ b/Train.cpp @@ -389,8 +389,11 @@ TTrain::TTrain() { bHeat[ i ] = false; } for( int i = 0; i < 9; ++i ) - for( int j = 0; j < 10; ++j ) - fEIMParams[ i ][ j ] = 0.0; + for (int j = 0; j < 10; ++j) + { + fEIMParams[i][j] = 0.0; + fDieselParams[i][j] = 0.0; + } for( int i = 0; i < 20; ++i ) for( int j = 0; j < 3; ++j ) @@ -493,6 +496,7 @@ dictionary_source *TTrain::GetTrainState() { // 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 *TXTD[ 10 ] = { "enrot", "nrot", "fill_des", "fill_real", "clutch_des", "clutch_real", "water_temp", "oil_press", "res1", "res2" }; char const *TXTP[ 3 ] = { "bc", "bp", "sp" }; for( int j = 0; j < 10; ++j ) dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] ); @@ -500,6 +504,9 @@ dictionary_source *TTrain::GetTrainState() { for( int j = 0; j < 10; ++j ) dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] ); + for (int j = 0; j < 10; ++j) + dict->insert(("diesel_param_" + std::to_string(i + 1) + "_" + std::string(TXTD[j])), fDieselParams[i + 1][j]); + 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 ] ); @@ -5319,6 +5326,27 @@ bool TTrain::Update( double const Deltatime ) in++; iPowerNo = in; } + if ((in < 8) && (p->MoverParameters->EngineType==TEngineType::DieselEngine)) + { + fDieselParams[1 + in][0] = p->MoverParameters->enrot*60; + fDieselParams[1 + in][1] = p->MoverParameters->nrot; + fDieselParams[1 + in][2] = p->MoverParameters->RList[p->MoverParameters->MainCtrlPos].R; + fDieselParams[1 + in][3] = p->MoverParameters->dizel_fill; + fDieselParams[1 + in][4] = p->MoverParameters->RList[p->MoverParameters->MainCtrlPos].Mn; + fDieselParams[1 + in][5] = p->MoverParameters->dizel_engage; + fDieselParams[1 + in][6] = p->MoverParameters->dizel_heat.Twy; + fDieselParams[1 + in][7] = p->MoverParameters->OilPump.pressure; + //fDieselParams[1 + in][8] = p->MoverParameters-> + //fDieselParams[1 + in][9] = p->MoverParameters-> + bMains[in] = p->MoverParameters->Mains; + fCntVol[in] = p->MoverParameters->BatteryVoltage; + bFuse[in] = p->MoverParameters->FuseFlag; + bBatt[in] = p->MoverParameters->Battery; + bConv[in] = p->MoverParameters->ConverterFlag; + bHeat[in] = p->MoverParameters->Heating; + in++; + iPowerNo = in; + } // p = p->NextC(4); //prev if ((kier ? p->NextC(128) : p->PrevC(128)) != (kier ? p->NextC(4) : p->PrevC(4))) iUnitNo++; @@ -5361,16 +5389,11 @@ bool TTrain::Update( double const Deltatime ) for (int i = in; i < 8; i++) { - fEIMParams[1 + i][0] = 0; - fEIMParams[1 + i][1] = 0; - fEIMParams[1 + i][2] = 0; - fEIMParams[1 + i][3] = 0; - fEIMParams[1 + i][4] = 0; - fEIMParams[1 + i][5] = 0; - fEIMParams[1 + i][6] = 0; - fEIMParams[1 + i][7] = 0; - fEIMParams[1 + i][8] = 0; - fEIMParams[1 + i][9] = 0; + for (int j = 0; j <= 9; j++) + { + fEIMParams[1 + i][j] = 0; + fDieselParams[1 + i][j] = 0; + } } #ifdef _WIN32 if (Global.iFeedbackMode == 4) { diff --git a/Train.h b/Train.h index 11f9098a..27a8c43e 100644 --- a/Train.h +++ b/Train.h @@ -675,6 +675,7 @@ private: float fPress[20][3]; // cisnienia dla wszystkich czlonow static std::vector const fPress_labels; float fEIMParams[9][10]; // parametry dla silnikow asynchronicznych + float fDieselParams[9][10]; // parametry dla silnikow asynchronicznych int RadioChannel() const { return iRadioChannel; }; // plays provided sound from position of the radio void radio_message( sound_source *Message, int const Channel );