From e356172a8154cb3448ff7032ee658364c8b8c9c4 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 27 Feb 2019 16:22:46 +0100 Subject: [PATCH] build 190227. joint master controlled cab control, minor bug fixes --- Driver.cpp | 58 ++++++++++++---------- DynObj.cpp | 4 +- Event.cpp | 6 ++- Train.cpp | 105 ++++++++++++++++++++++++++++++++++++---- Train.h | 2 + command.cpp | 1 + command.h | 1 + driverkeyboardinput.cpp | 1 + drivermouseinput.cpp | 48 ++++++++++++++++-- drivermouseinput.h | 1 + driveruipanels.cpp | 4 +- scenenode.cpp | 6 ++- scenenode.h | 4 +- translation.cpp | 3 ++ translation.h | 1 + version.h | 2 +- 16 files changed, 200 insertions(+), 47 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index edcf3fe0..bf336f98 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -372,14 +372,13 @@ bool TSpeedPos::Set(basic_event *event, double dist, double length, TOrders orde iFlags = spEvent; evEvent = event; vPos = event->input_location(); // współrzędne eventu albo komórki pamięci (zrzutować na tor?) - if( dist + length >= 0 ) { - iFlags |= spEnabled; - CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości - } - else { - // located behind the tracking consist, don't bother with it + // ignore events located behind the consist, but with exception of stop points which may be needed to update freshly received timetable + if( ( dist + length < 0 ) + && ( event->input_command() != TCommandType::cm_PassengerStopPoint ) ) { return false; } + iFlags |= spEnabled; + CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości // zależnie od trybu sprawdzenie czy jest tutaj gdzieś semafor lub tarcza manewrowa // jeśli wskazuje stop wtedy wystawiamy true jako koniec sprawdzania // WriteLog("EventSet: Vel=" + AnsiString(fVelNext) + " iFlags=" + AnsiString(iFlags) + " order="+AnsiString(order)); @@ -486,6 +485,20 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) if (iTableDirection != iDirection ) { // jeśli zmiana kierunku, zaczynamy od toru ze wskazanym pojazdem + TableClear(); +/* + // aktualna prędkość // changed to -1 to recognize speed limit, if any + fLastVel = -1.0; + sSpeedTable.clear(); + iLast = -1; + tLast = nullptr; //żaden nie sprawdzony + SemNextIndex = -1; + SemNextStopIndex = -1; +*/ + if( VelSignalLast == 0.0 ) { + // don't allow potential red light overrun keep us from reversing + VelSignalLast = -1.0; + } iTableDirection = iDirection; // ustalenie w jakim kierunku jest wypełniana tabelka względem pojazdu pTrack = pVehicle->RaTrackGet(); // odcinek, na którym stoi fTrackLength = pVehicle->RaTranslationGet(); // pozycja na tym torze (odległość od Point1) @@ -503,17 +516,6 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) .Length(); // aktualna odległość ma być ujemna gdyż jesteśmy na końcu składu fCurrentDistance = -fLength - fTrackLength; - // aktualna prędkość // changed to -1 to recognize speed limit, if any - fLastVel = -1.0; - sSpeedTable.clear(); - iLast = -1; - tLast = nullptr; //żaden nie sprawdzony - SemNextIndex = -1; - SemNextStopIndex = -1; - if( VelSignalLast == 0.0 ) { - // don't allow potential red light overrun keep us from reversing - VelSignalLast = -1.0; - } fTrackLength = pTrack->Length(); //skasowanie zmian w zmiennej żeby poprawnie liczyło w dalszych krokach MoveDistanceReset(); // AI startuje 1s po zaczęciu jazdy i mógł już coś przejechać } @@ -759,7 +761,7 @@ void TController::TableCheck(double fDistance) { // przeliczenie odległości w tabelce, ewentualnie doskanowanie (bez analizy prędkości itp.) if( iTableDirection != iDirection ) { // jak zmiana kierunku, to skanujemy od końca składu - TableTraceRoute( fDistance, pVehicles[ 1 ] ); + TableTraceRoute( fDistance, pVehicles[ end::rear ] ); TableSort(); } else if (iTableDirection) @@ -786,7 +788,7 @@ void TController::TableCheck(double fDistance) --iLast; } tLast = sSpeedTable[ i ].trTrack; - TableTraceRoute( fDistance, pVehicles[ 1 ] ); + TableTraceRoute( fDistance, pVehicles[ end::rear ] ); TableSort(); // nie kontynuujemy pętli, trzeba doskanować ciąg dalszy break; @@ -824,7 +826,7 @@ void TController::TableCheck(double fDistance) sSpeedTable[iLast].Update(); // aktualizacja ostatniego // WriteLog("TableCheck: Upate last track. Dist=" + AnsiString(sSpeedTable[iLast].fDist)); if( sSpeedTable[ iLast ].fDist < fDistance ) { - TableTraceRoute( fDistance, pVehicles[ 1 ] ); // doskanowanie dalszego odcinka + TableTraceRoute( fDistance, pVehicles[ end::rear ] ); // doskanowanie dalszego odcinka TableSort(); } // garbage collection @@ -2353,7 +2355,6 @@ bool TController::PrepareEngine() voltrear = false; LastReactionTime = 0.0; ReactionTime = PrepareTime; - iDrivigFlags |= moveActive; // może skanować sygnały i reagować na komendy if ( mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) { voltfront = true; @@ -2484,6 +2485,8 @@ bool TController::PrepareEngine() } eAction = TAction::actUnknown; iEngineActive = 1; + iDrivigFlags |= moveActive; // może skanować sygnały i reagować na komendy + return true; } else { @@ -3266,10 +3269,10 @@ void TController::Doors( bool const Open, int const Side ) { && ( ( fActionTime > -0.5 ) || ( 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.open_control == control_t::conductor ) + if( ( pVehicle->MoverParameters->Doors.close_control == control_t::conductor ) || ( ( true == AIControllFlag ) - && ( ( pVehicle->MoverParameters->Doors.open_control == control_t::driver ) - || ( pVehicle->MoverParameters->Doors.open_control == control_t::mixed ) ) ) ) { + && ( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver ) + || ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) ) ) { // 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 ); @@ -3306,6 +3309,10 @@ void TController::Doors( bool const Open, int const Side ) { bool TController::doors_open() const { + return ( + IsAnyDoorOpen[ side::right ] + || IsAnyDoorOpen[ side::left ] ); +/* auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu while( vehicle != nullptr ) { if( ( false == vehicle->MoverParameters->Doors.instances[side::right].is_closed ) @@ -3317,6 +3324,7 @@ TController::doors_open() const { } // if we're still here there's nothing open return false; +*/ } void TController::RecognizeCommand() @@ -4215,7 +4223,7 @@ TController::UpdateSituation(double dt) { Obstacle.vehicle_end = std::get( lookup ); Obstacle.distance = std::get( lookup ); - if( Obstacle.distance < ( mvOccupied->CategoryFlag == 2 ? 25 : 75 ) ) { + if( Obstacle.distance < ( mvOccupied->CategoryFlag == 2 ? 25 : 100 ) ) { // at short distances (re)calculate range between couplers directly Obstacle.distance = TMoverParameters::CouplerDist( frontvehicle->MoverParameters, Obstacle.vehicle->MoverParameters ); } diff --git a/DynObj.cpp b/DynObj.cpp index d79f24f5..3be66387 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -3439,13 +3439,13 @@ bool TDynamicObject::Update(double dt, double dt1) else { // unfold mirror on the side with open doors, if not moving too fast if( ( dMirrorMoveL < 1.0 ) - && ( true == MoverParameters->Doors.instances[side::left].is_open ) ) { + && ( true == MoverParameters->Doors.instances[side::left].open_permit ) ) { dMirrorMoveL = std::min( 1.0, dMirrorMoveL + 1.0 * dt1 ); } if( ( dMirrorMoveR < 1.0 ) - && ( true == MoverParameters->Doors.instances[side::right].is_open ) ) { + && ( true == MoverParameters->Doors.instances[side::right].open_permit ) ) { dMirrorMoveR = std::min( 1.0, dMirrorMoveR + 1.0 * dt1 ); diff --git a/Event.cpp b/Event.cpp index 12593cdf..ac58a10e 100644 --- a/Event.cpp +++ b/Event.cpp @@ -960,7 +960,11 @@ whois_event::run_() { 1 : 0, // 1, gdy ma tu zatrzymanie m_input.flags ); - WriteLog( "Train detected: " + m_activator->Mechanik->TrainName() ); + WriteLog( + "Type: WhoIs (" + to_string( m_input.flags ) + ") - " + + "[train: " + m_activator->Mechanik->TrainName() + "], " + + "[stations left: " + to_string( m_activator->Mechanik->StationCount() - m_activator->Mechanik->StationIndex() ) + "], " + + "[stop at next: " + ( m_activator->Mechanik->IsStop() ? "yes" : "no") + "]" ); } } } diff --git a/Train.cpp b/Train.cpp index 30f82b53..75a1942d 100644 --- a/Train.cpp +++ b/Train.cpp @@ -158,6 +158,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::aidriverenable, &TTrain::OnCommand_aidriverenable }, { user_command::aidriverdisable, &TTrain::OnCommand_aidriverdisable }, + { user_command::jointcontrollerset, &TTrain::OnCommand_jointcontrollerset }, { user_command::mastercontrollerincrease, &TTrain::OnCommand_mastercontrollerincrease }, { user_command::mastercontrollerincreasefast, &TTrain::OnCommand_mastercontrollerincreasefast }, { user_command::mastercontrollerdecrease, &TTrain::OnCommand_mastercontrollerdecrease }, @@ -757,12 +758,49 @@ void TTrain::OnCommand_aidriverdisable( TTrain *Train, command_data const &Comma auto const EU07_CONTROLLER_BASERETURNDELAY { 0.5f }; auto const EU07_CONTROLLER_KEYBOARDETURNDELAY { 1.5f }; +void TTrain::OnCommand_jointcontrollerset( TTrain *Train, command_data const &Command ) { + + if( Command.action != GLFW_RELEASE ) { + // on press or hold + // value controls brake in range 0-0.5, master controller in range 0.5-1.0 + if( Command.param1 >= 0.5 ) { + Train->set_master_controller( + ( Command.param1 * 2 - 1 ) + * ( Train->mvControlled->CoupledCtrl ? + Train->mvControlled->MainCtrlPosNo + Train->mvControlled->ScndCtrlPosNo : + Train->mvControlled->MainCtrlPosNo ) ); + Train->m_mastercontrollerinuse = true; + Train->mvOccupied->LocalBrakePosA = 0; + } + else { + Train->mvOccupied->LocalBrakePosA = ( + clamp( + 1.0 - ( Command.param1 * 2 ), + 0.0, 1.0 ) ); + if( Train->mvControlled->MainCtrlPos > 0 ) { + Train->set_master_controller( 0 ); + } + } + } + else { + // release + Train->m_mastercontrollerinuse = false; + Train->m_mastercontrollerreturndelay = EU07_CONTROLLER_BASERETURNDELAY; // NOTE: keyboard return delay is omitted for other input sources + } +} + void TTrain::OnCommand_mastercontrollerincrease( TTrain *Train, command_data const &Command ) { if( Command.action != GLFW_RELEASE ) { // on press or hold - Train->mvControlled->IncMainCtrl( 1 ); - Train->m_mastercontrollerinuse = true; + if( ( Train->ggJointCtrl.SubModel != nullptr ) + && ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { + OnCommand_independentbrakedecrease( Train, Command ); + } + else { + Train->mvControlled->IncMainCtrl( 1 ); + Train->m_mastercontrollerinuse = true; + } } else { // release @@ -775,7 +813,19 @@ void TTrain::OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { // on press or hold - Train->mvControlled->IncMainCtrl( 2 ); + if( ( Train->ggJointCtrl.SubModel != nullptr ) + && ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) { + OnCommand_independentbrakedecreasefast( Train, Command ); + } + else { + Train->mvControlled->IncMainCtrl( 2 ); + Train->m_mastercontrollerinuse = true; + } + } + else { + // release + Train->m_mastercontrollerinuse = false; + Train->m_mastercontrollerreturndelay = EU07_CONTROLLER_KEYBOARDETURNDELAY + EU07_CONTROLLER_BASERETURNDELAY; } } @@ -783,8 +833,14 @@ void TTrain::OnCommand_mastercontrollerdecrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { // on press or hold - Train->mvControlled->DecMainCtrl( 1 ); - Train->m_mastercontrollerinuse = true; + if( ( Train->ggJointCtrl.SubModel != nullptr ) + && ( Train->mvControlled->MainCtrlPos == 0 ) ) { + OnCommand_independentbrakeincrease( Train, Command ); + } + else { + Train->mvControlled->DecMainCtrl( 1 ); + Train->m_mastercontrollerinuse = true; + } } else { // release @@ -797,7 +853,19 @@ void TTrain::OnCommand_mastercontrollerdecreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { // on press or hold - Train->mvControlled->DecMainCtrl( 2 ); + if( ( Train->ggJointCtrl.SubModel != nullptr ) + && ( Train->mvControlled->MainCtrlPos == 0 ) ) { + OnCommand_independentbrakeincreasefast( Train, Command ); + } + else { + Train->mvControlled->DecMainCtrl( 2 ); + Train->m_mastercontrollerinuse = true; + } + } + else { + // release + Train->m_mastercontrollerinuse = false; + Train->m_mastercontrollerreturndelay = EU07_CONTROLLER_KEYBOARDETURNDELAY + EU07_CONTROLLER_BASERETURNDELAY; } } @@ -981,7 +1049,7 @@ void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &C if( Command.action != GLFW_RELEASE ) { - Train->mvControlled->LocalBrakePosA = ( + Train->mvOccupied->LocalBrakePosA = ( clamp( Command.param1, 0.0, 1.0 ) ); @@ -5735,7 +5803,21 @@ bool TTrain::Update( double const Deltatime ) } } // McZapkie-080602: obroty (albo translacje) regulatorow - if (ggMainCtrl.SubModel) { + if( ggJointCtrl.SubModel != nullptr ) { + // joint master controller moves forward to adjust power and backward to adjust brakes + auto const brakerangemultiplier { + ( mvControlled->CoupledCtrl ? + mvControlled->MainCtrlPosNo + mvControlled->ScndCtrlPosNo : + mvControlled->MainCtrlPosNo ) + / static_cast(LocalBrakePosNo) }; + ggJointCtrl.UpdateValue( + ( mvOccupied->LocalBrakePosA > 0.0 ? mvOccupied->LocalBrakePosA * LocalBrakePosNo * -1 * brakerangemultiplier : + mvControlled->CoupledCtrl ? double( mvControlled->MainCtrlPos + mvControlled->ScndCtrlPos ) : + double( mvControlled->MainCtrlPos ) ), + dsbNastawnikJazdy ); + ggJointCtrl.Update(); + } + if ( ggMainCtrl.SubModel != nullptr ) { #ifdef _WIN32 if( ( DynamicObject->Mechanik != nullptr ) @@ -5822,7 +5904,7 @@ bool TTrain::Update( double const Deltatime ) ggBrakeCtrl.Update(); } - if( ggLocalBrake.SubModel ) { + if( ggLocalBrake.SubModel != nullptr ) { #ifdef _WIN32 if( ( DynamicObject->Mechanik != nullptr ) && ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI @@ -6853,6 +6935,9 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) if( dsbReverserKey.offset() == nullvector ) { dsbReverserKey.offset( ggDirKey.model_offset() ); } + if( dsbNastawnikJazdy.offset() == nullvector ) { + dsbNastawnikJazdy.offset( ggJointCtrl.model_offset() ); + } if( dsbNastawnikJazdy.offset() == nullvector ) { dsbNastawnikJazdy.offset( ggMainCtrl.model_offset() ); } @@ -7094,6 +7179,7 @@ void TTrain::clear_cab_controls() // other cab controls // TODO: arrange in more readable manner, and eventually refactor + ggJointCtrl.Clear(); ggMainCtrl.Clear(); ggMainCtrlAct.Clear(); ggScndCtrl.Clear(); @@ -7729,6 +7815,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int const Cabindex) { std::unordered_map const gauges = { + { "jointctrl:", ggJointCtrl }, { "mainctrl:", ggMainCtrl }, { "scndctrl:", ggScndCtrl }, { "dirkey:" , ggDirKey }, diff --git a/Train.h b/Train.h index 35701da2..9cb8eb90 100644 --- a/Train.h +++ b/Train.h @@ -155,6 +155,7 @@ class TTrain // TBD, TODO: consider this approach if we ever want to have customized consist behaviour to received commands, based on the consist/vehicle type or whatever static void OnCommand_aidriverenable( TTrain *Train, command_data const &Command ); static void OnCommand_aidriverdisable( TTrain *Train, command_data const &Command ); + static void OnCommand_jointcontrollerset( TTrain *Train, command_data const &Command ); static void OnCommand_mastercontrollerincrease( TTrain *Train, command_data const &Command ); static void OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data const &Command ); static void OnCommand_mastercontrollerdecrease( TTrain *Train, command_data const &Command ); @@ -372,6 +373,7 @@ public: // reszta może by?publiczna TGauge ggWater1TempB; // McZapkie: definicje regulatorow + TGauge ggJointCtrl; TGauge ggMainCtrl; TGauge ggMainCtrlAct; TGauge ggScndCtrl; diff --git a/command.cpp b/command.cpp index b4036625..6b49e343 100644 --- a/command.cpp +++ b/command.cpp @@ -22,6 +22,7 @@ commanddescription_sequence Commands_descriptions = { { "aidriverenable", command_target::vehicle }, { "aidriverdisable", command_target::vehicle }, + { "jointcontrollerset", command_target::vehicle }, { "mastercontrollerincrease", command_target::vehicle }, { "mastercontrollerincreasefast", command_target::vehicle }, { "mastercontrollerdecrease", command_target::vehicle }, diff --git a/command.h b/command.h index c873cdee..3cdd6bd0 100644 --- a/command.h +++ b/command.h @@ -16,6 +16,7 @@ enum class user_command { aidriverenable, aidriverdisable, + jointcontrollerset, mastercontrollerincrease, mastercontrollerincreasefast, mastercontrollerdecrease, diff --git a/driverkeyboardinput.cpp b/driverkeyboardinput.cpp index 80225887..0ece6a48 100644 --- a/driverkeyboardinput.cpp +++ b/driverkeyboardinput.cpp @@ -27,6 +27,7 @@ driverkeyboard_input::default_bindings() { m_bindingsetups = { { user_command::aidriverenable, GLFW_KEY_Q | keymodifier::shift }, { user_command::aidriverdisable, GLFW_KEY_Q }, + // jointcontrollerset, { user_command::mastercontrollerincrease, GLFW_KEY_KP_ADD }, { user_command::mastercontrollerincreasefast, GLFW_KEY_KP_ADD | keymodifier::shift }, { user_command::mastercontrollerdecrease, GLFW_KEY_KP_SUBTRACT }, diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index 6237935c..a8e04c07 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -21,6 +21,8 @@ http://mozilla.org/MPL/2.0/. #include "uilayer.h" #include "Logs.h" +auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.65 }; + void mouse_slider::bind( user_command const &Command ) { @@ -29,6 +31,7 @@ mouse_slider::bind( user_command const &Command ) { auto const *train { simulation::Train }; TMoverParameters const *vehicle { nullptr }; switch( m_command ) { + case user_command::jointcontrollerset: case user_command::mastercontrollerset: case user_command::secondcontrollerset: { vehicle = ( train ? train->Controlled() : nullptr ); @@ -47,6 +50,29 @@ mouse_slider::bind( user_command const &Command ) { // calculate initial value and accepted range switch( m_command ) { + case user_command::jointcontrollerset: { + // NOTE: special case, merges two separate controls + auto const *occupied { train ? train->Occupied() : nullptr }; + if( occupied == nullptr ) { return; } + + auto const powerrange { static_cast( + vehicle->CoupledCtrl ? + vehicle->MainCtrlPosNo + vehicle->ScndCtrlPosNo : + vehicle->MainCtrlPosNo ) }; + // for simplicity upper half of the range controls power, lower controls brakes + auto const brakerangemultiplier { powerrange / LocalBrakePosNo }; + + m_valuerange = 1.0; + m_value = + 0.5 + + 0.5 * ( vehicle->CoupledCtrl ? + vehicle->MainCtrlPos + vehicle->ScndCtrlPos : + vehicle->MainCtrlPos ) / powerrange + - 0.5 * occupied->LocalBrakePosA; + m_analogue = true; + m_invertrange = false; + break; + } case user_command::mastercontrollerset: { m_valuerange = ( vehicle->CoupledCtrl ? @@ -57,24 +83,28 @@ mouse_slider::bind( user_command const &Command ) { vehicle->MainCtrlPos + vehicle->ScndCtrlPos : vehicle->MainCtrlPos ); m_analogue = false; + m_invertrange = false; break; } case user_command::secondcontrollerset: { m_valuerange = vehicle->ScndCtrlPosNo; m_value = vehicle->ScndCtrlPos; m_analogue = false; + m_invertrange = true; break; } case user_command::trainbrakeset: { m_valuerange = 1.0; m_value = ( vehicle->fBrakeCtrlPos - vehicle->Handle->GetPos( bh_MIN ) ) / ( vehicle->Handle->GetPos( bh_MAX ) - vehicle->Handle->GetPos( bh_MIN ) ); m_analogue = true; + m_invertrange = true; break; } case user_command::independentbrakeset: { m_valuerange = 1.0; m_value = vehicle->LocalBrakePosA; m_analogue = true; + m_invertrange = true; break; } default: { @@ -86,14 +116,18 @@ mouse_slider::bind( user_command const &Command ) { Application.get_cursor_pos( m_cursorposition.x, m_cursorposition.y ); Application.set_cursor( GLFW_CURSOR_DISABLED ); - auto const controlsize { Global.iWindowHeight * 0.75 }; + auto const controlsize { Global.iWindowHeight * EU07_CONTROLLER_MOUSESLIDERSIZE }; auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 }; auto const stepsize { controlsize / m_valuerange }; + if( m_invertrange ) { + m_value = ( m_analogue ? 1.0 : m_valuerange ) - m_value; + } + Application.set_cursor_pos( Global.iWindowWidth * 0.5, ( m_analogue ? - controledge - ( 1.0 - m_value ) * controlsize : + controledge - m_value * controlsize : controledge - m_value * stepsize - 0.5 * stepsize ) ); } @@ -108,15 +142,17 @@ mouse_slider::release() { void mouse_slider::on_move( double const Mousex, double const Mousey ) { - auto const controlsize { Global.iWindowHeight * 0.75 }; + auto const controlsize { Global.iWindowHeight * EU07_CONTROLLER_MOUSESLIDERSIZE }; auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 }; auto const stepsize { controlsize / m_valuerange }; auto mousey = clamp( Mousey, controledge - controlsize, controledge ); m_value = ( m_analogue ? - 1.0 - ( ( controledge - mousey ) / controlsize ) : + ( controledge - mousey ) / controlsize : std::floor( ( controledge - mousey ) / stepsize ) ); + if( m_invertrange ) { + m_value = ( m_analogue ? 1.0 : m_valuerange ) - m_value; } } @@ -370,6 +406,7 @@ drivermouse_input::button( int const Button, int const Action ) { m_varyingpollrate = true; break; } + case user_command::jointcontrollerset: case user_command::mastercontrollerset: case user_command::secondcontrollerset: case user_command::trainbrakeset: @@ -445,6 +482,9 @@ void drivermouse_input::default_bindings() { m_buttonbindings = { + { "jointctrl:", { + user_command::jointcontrollerset, + user_command::none } }, { "mainctrl:", { user_command::mastercontrollerset, user_command::none } }, diff --git a/drivermouseinput.h b/drivermouseinput.h index b8b40a4e..2932a722 100644 --- a/drivermouseinput.h +++ b/drivermouseinput.h @@ -39,6 +39,7 @@ private: double m_value { 0.0 }; double m_valuerange { 0.0 }; bool m_analogue { false }; + bool m_invertrange { false }; glm::dvec2 m_cursorposition { 0.0 }; }; diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 5957935d..0098a6fa 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -696,7 +696,9 @@ debug_panel::update_section_ai( std::vector &Output ) { + ", braking: " + to_string( mechanik.fBrakeDist, 0 ); if( mechanik.Obstacle.distance < 5000 ) { - textline += "\n obstacle: " + to_string( mechanik.Obstacle.distance, 0 ); + textline += + "\n obstacle: " + to_string( mechanik.Obstacle.distance, 0 ) + + " (" + mechanik.Obstacle.vehicle->asName + ")"; } Output.emplace_back( textline, Global.UITextColor ); diff --git a/scenenode.cpp b/scenenode.cpp index eeb2ae98..df5c432d 100644 --- a/scenenode.cpp +++ b/scenenode.cpp @@ -49,10 +49,12 @@ bounding_area::serialize( std::ostream &Output ) const { // restores content of the struct from provided input stream void -bounding_area::deserialize( std::istream &Input ) { +bounding_area::deserialize( std::istream &Input, bool const Preserveradius ) { center = sn_utils::d_dvec3( Input ); - radius = sn_utils::ld_float32( Input ); + radius = ( Preserveradius ? + std::max( radius, sn_utils::ld_float32( Input ) ) : + sn_utils::ld_float32( Input ) ); } diff --git a/scenenode.h b/scenenode.h index 05431fec..06b59356 100644 --- a/scenenode.h +++ b/scenenode.h @@ -59,9 +59,9 @@ struct bounding_area { // stores content of the struct in provided output stream void serialize( std::ostream &Output ) const; - // restores content of the struct from provided input stream + // restores content of the struct from provided input stream. void - deserialize( std::istream &Input ); + deserialize( std::istream &Input, bool const Preserveradius = true ); }; //using group_handle = std::size_t; diff --git a/translation.cpp b/translation.cpp index 854cbfdf..a774082c 100644 --- a/translation.cpp +++ b/translation.cpp @@ -62,6 +62,7 @@ init() { " pantograph: %.2f%cMT", "Forces:\n tractive: %.1f, brake: %.1f, friction: %.2f%s\nAcceleration:\n tangential: %.2f, normal: %.2f (path radius: %s)\nVelocity: %.2f, distance traveled: %.2f\nPosition: [%.2f, %.2f, %.2f]", + "master controller", "master controller", "second controller", "shunt mode power", @@ -206,6 +207,7 @@ init() { " pantograf: %.2f%cZG", "Sily:\n napedna: %.1f, hamowania: %.1f, tarcie: %.2f%s\nPrzyspieszenia:\n styczne: %.2f, normalne: %.2f (promien: %s)\nPredkosc: %.2f, pokonana odleglosc: %.2f\nPozycja: [%.2f, %.2f, %.2f]", + "nastawnik jazdy", "nastawnik jazdy", "nastawnik dodatkowy", "sterowanie analogowe", @@ -322,6 +324,7 @@ init() { { std::vector cabcontrols = { "mainctrl:", + "jointctrl:", "scndctrl:", "shuntmodepower:", "dirkey:", diff --git a/translation.h b/translation.h index d991a771..8a7a056d 100644 --- a/translation.h +++ b/translation.h @@ -52,6 +52,7 @@ enum string { debug_vehicle_forcesaccelerationvelocityposition, cab_mainctrl, + cab_jointctrl, cab_scndctrl, cab_shuntmodepower, cab_dirkey, diff --git a/version.h b/version.h index e1d32d9f..a9aa97a6 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 223 +#define VERSION_MINOR 227 #define VERSION_REVISION 0