From 1ced1239e0f3fc4748c93a7272d7189f75227fb3 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sun, 31 Mar 2019 21:47:40 +0200 Subject: [PATCH 01/12] vehicle heating system tweaks, vehicle destination sign system enhancements --- Driver.cpp | 8 +++- DynObj.cpp | 95 ++++++++++++++++++++++++++++++++++++---------- DynObj.h | 9 +++++ McZapkie/MOVER.h | 2 + McZapkie/Mover.cpp | 42 +++++++++++++------- Model3d.cpp | 21 ++++++++++ Model3d.h | 2 + Train.cpp | 15 +++----- 8 files changed, 149 insertions(+), 45 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 865089a5..7ce285c2 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2127,6 +2127,11 @@ bool TController::CheckVehicles(TOrders user) && ( ( 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; + p->MoverParameters->ConverterSwitch( true, range_t::local ); + } } if (p->asDestination == "none") @@ -2358,6 +2363,7 @@ double TController::BrakeAccFactor() const double Factor = 1.0; if( ( fAccThreshold != 0.0 ) + && ( AccDesired < 0.0 ) && ( ( ActualProximityDist > fMinProximityDist ) || ( 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 ); @@ -3551,7 +3557,7 @@ void TController::Doors( bool const Open, int const Side ) { } if( AIControllFlag ) { - if( ( true == mvOccupied->Doors.has_autowarning ) + if( ( true == mvOccupied->Doors.has_warning ) && ( false == mvOccupied->DepartureSignal ) && ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) { mvOccupied->signal_departure( true ); // załącenie bzyczka diff --git a/DynObj.cpp b/DynObj.cpp index 172c20bf..4cca3979 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -919,6 +919,8 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) btEndSignalsTab2.Turn( true ); btnOn = true; } + // destination signs + update_destinations(); // else btEndSignalsTab2.TurnOff(); // McZapkie-181002: krecenie wahaczem (korzysta z kata obrotu silnika) if (iAnimType[ANIM_LEVERS]) @@ -1946,6 +1948,10 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424" init_sections( mdLowPolyInt, nameprefix ); } } + // destination sign + if( mdModel ) { + init_destination( mdModel ); + } // 'external_load' is an optional special section in the main model, pointing to submodel of external load if( mdModel ) { init_sections( mdModel, "external_load" ); @@ -2069,6 +2075,16 @@ TDynamicObject::init_sections( TModel3d const *Model, std::string const &Namepre return sectioncount; } +bool +TDynamicObject::init_destination( TModel3d *Model ) { + + if( Model->GetSMRoot() == nullptr ) { return false; } + + std::tie( DestinationSign.sign, DestinationSign.has_light ) = Model->GetSMRoot()->find_replacable4(); + + return DestinationSign.sign != nullptr; +} + void TDynamicObject::create_controller( std::string const Type, bool const Trainset ) { @@ -2553,6 +2569,27 @@ na sprzęgach, opóźnienie działania hamulca itp. Oczywiście musi mieć to pe histerezę czasową, aby te tryby pracy nie przełączały się zbyt szybko. */ +void TDynamicObject::update_destinations() { + + if( DestinationSign.sign == nullptr ) { return; } + + DestinationSign.sign->fLight = ( + ( ( DestinationSign.has_light ) && ( MoverParameters->Battery ) ) ? + 2.0 : + -1.0 ); + + // jak są 4 tekstury wymienne, to nie zmieniać rozkładem + if( std::abs( m_materialdata.multi_textures ) >= 4 ) { return; } + // TODO: dedicated setting to discern electronic signs, instead of fallback on light presence + m_materialdata.replacable_skins[ 4 ] = ( + ( ( DestinationSign.destination != null_handle ) + && ( ( false == DestinationSign.has_light ) // physical destination signs remain up until manually changed + || ( ( true == MoverParameters->Battery ) // lcd signs are off without power + && ( ctOwner != nullptr ) ) ) ) ? // lcd signs are off for carriages without engine, potentially left on a siding + DestinationSign.destination : + DestinationSign.destination_off ); +} + bool TDynamicObject::Update(double dt, double dt1) { if (dt1 == 0) @@ -4235,7 +4272,8 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co } // potentially set blank destination texture - DestinationSet( {}, {} ); + DestinationSign.destination_off = DestinationFind( "nowhere" ); +// DestinationSet( {}, {} ); if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) { // tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych @@ -6087,45 +6125,60 @@ int TDynamicObject::RouteWish(TTrack *tr) return Mechanik ? Mechanik->CrossRoute(tr) : 0; // wg AI albo prosto }; -void TDynamicObject::DestinationSet(std::string to, std::string numer) -{ // ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik +void TDynamicObject::DestinationSet(std::string to, std::string numer) { + // ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik // w zasadzie, to każdy wagon mógłby mieć inną stację docelową // zwłaszcza w towarowych, pod kątem zautomatyzowania maewrów albo pracy górki // ale to jeszcze potrwa, zanim będzie możliwe, na razie można wpisać stację z // rozkładu - if( std::abs( m_materialdata.multi_textures ) >= 4 ) { - // jak są 4 tekstury wymienne, to nie zmieniać rozkładem - return; - } - numer = Bezogonkow(numer); + asDestination = to; - to = Bezogonkow(to); // do szukania pliku obcinamy ogonki - if( true == to.empty() ) { - to = "nowhere"; + + if( std::abs( m_materialdata.multi_textures ) >= 4 ) { return; } // jak są 4 tekstury wymienne, to nie zmieniać rozkładem + if( DestinationSign.sign == nullptr ) { return; } // no sign submodel, no problem + + // now see if we can find any version of the destination texture + std::vector const destinations = { + numer, // try dedicated timetable sign first... + to }; // ...then generic destination sign + + for( auto const &destination : destinations ) { + + DestinationSign.destination = DestinationFind( destination ); + if( DestinationSign.destination != null_handle ) { + // got what we wanted, we're done here + break; + } } +} + +material_handle TDynamicObject::DestinationFind( std::string Destination ) { + + if( Destination.empty() ) { return null_handle; } + + Destination = Bezogonkow( Destination ); // do szukania pliku obcinamy ogonki // destination textures are kept in the vehicle's directory so we point the current texture path there auto const currenttexturepath { Global.asCurrentTexturePath }; Global.asCurrentTexturePath = asBaseDir; // now see if we can find any version of the texture - std::vector destinations = { - numer + '@' + MoverParameters->TypeName, - numer, - to + '@' + MoverParameters->TypeName, - to, - "nowhere" + '@' + MoverParameters->TypeName, - "nowhere" }; + std::vector const destinations { + Destination + '@' + MoverParameters->TypeName, + Destination }; + + auto destinationhandle { null_handle }; for( auto const &destination : destinations ) { - auto material = TextureTest( ToLower( destination ) ); if( false == material.empty() ) { - m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Material( material ); + destinationhandle = GfxRenderer.Fetch_Material( material ); break; } } // whether we got anything, restore previous texture path Global.asCurrentTexturePath = currenttexturepath; -}; + + return destinationhandle; +} void TDynamicObject::OverheadTrack(float o) { // ewentualne wymuszanie jazdy diff --git a/DynObj.h b/DynObj.h index f683cce9..ba9c4a78 100644 --- a/DynObj.h +++ b/DynObj.h @@ -200,6 +200,12 @@ public: TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly std::array LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs bool JointCabs{ false }; // flag for vehicles with multiple virtual 'cabs' sharing location and 3d model(s) + struct destination_data { + TSubModel *sign { nullptr }; // submodel mapped with replacable texture -4 + bool has_light { false }; // the submodel was originally configured with self-illumination attribute + material_handle destination { null_handle }; // most recently assigned non-blank destination texture + material_handle destination_off { null_handle }; // blank destination sign + } DestinationSign; float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?) float LoadOffset { 0.f }; std::unordered_map LoadModelOverrides; // potential overrides of default load visualization models @@ -517,6 +523,7 @@ private: TTrack *Track, double fDist, std::string DriverType, double fVel, std::string TrainName, float Load, std::string LoadType, bool Reversed, std::string); int init_sections( TModel3d const *Model, std::string const &Nameprefix ); + bool init_destination( TModel3d *Model ); void create_controller( std::string const Type, bool const Trainset ); void AttachPrev(TDynamicObject *Object, int iType = 1); bool UpdateForce(double dt); @@ -531,6 +538,7 @@ private: void update_load_visibility(); void update_load_offset(); void shuffle_load_sections(); + void update_destinations(); bool Update(double dt, double dt1); bool FastUpdate(double dt); void Move(double fDistance); @@ -633,6 +641,7 @@ private: // zapytanie do AI, po którym segmencie skrzyżowania jechać int RouteWish(TTrack *tr); void DestinationSet(std::string to, std::string numer); + material_handle DestinationFind( std::string Destination ); void OverheadTrack(float o); double MED[9][8]; // lista zmiennych do debugowania hamulca ED diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index f02bd64d..815012dd 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -1351,6 +1351,7 @@ public: std::string StLinSwitchType; bool Heating = false; //ogrzewanie 'Winger 020304 + bool HeatingAllow { false }; // heating switch // TODO: wrap heating in a basic device int DoubleTr = 1; //trakcja ukrotniona - przedni pojazd 'Winger 160304 bool PhysicActivation = true; @@ -1497,6 +1498,7 @@ public: /*-funkcje typowe dla lokomotywy elektrycznej*/ void ConverterCheck( double const Timestep ); // przetwornica + void HeatingCheck( double const Timestep ); void WaterPumpCheck( double const Timestep ); void WaterHeaterCheck( double const Timestep ); void FuelPumpCheck( double const Timestep ); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index dd61392d..f42d92b8 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1075,11 +1075,13 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap for( int side = 0; side < 2; ++side ) { // przekazywanie napiec - auto const oppositeside = ( side == end::front ? end::rear : end::front ); + auto const oppositeside { ( side == end::front ? end::rear : end::front ) }; + auto const liveconnection{ + ( Couplers[ side ].CouplingFlag & ctrain_power ) + || ( ( Couplers[ side ].CouplingFlag & ctrain_heating ) + && ( Couplers[ side ].Connected->Heating ) ) }; - if( ( Couplers[ side ].CouplingFlag & ctrain_power ) - || ( ( Heating ) - && ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { + if( liveconnection ) { auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ]; Couplers[ oppositeside ].power_high.voltage = std::max( @@ -1103,8 +1105,8 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap Couplers[ side ].power_high.local = false; // power, if any, will be from external source if( ( Couplers[ side ].CouplingFlag & ctrain_power ) - || ( ( Heating ) - && ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { + || ( ( Couplers[ side ].CouplingFlag & ctrain_heating ) + && ( Couplers[ side ].Connected->Heating ) ) ) { auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ ( Couplers[ side ].ConnectedNr == end::front ? @@ -1127,8 +1129,8 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap Couplers[ side ].power_high.local = true; // power is coming from local pantographs if( ( Couplers[ side ].CouplingFlag & ctrain_power ) - || ( ( Heating ) - && ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { + || ( ( Couplers[ side ].CouplingFlag & ctrain_heating ) + && ( Couplers[ side ].Connected->Heating ) ) ) { auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ ( Couplers[ side ].ConnectedNr == end::front ? @@ -1409,6 +1411,8 @@ void TMoverParameters::compute_movement_( double const Deltatime ) { // w rozrządczym nie (jest błąd w FIZ!) - Ra 2014-07: teraz we wszystkich UpdatePantVolume( Deltatime ); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów } + // heating + HeatingCheck( Deltatime ); UpdateBrakePressure(Deltatime); UpdatePipePressure(Deltatime); @@ -1462,7 +1466,8 @@ void TMoverParameters::ConverterCheck( double const Timestep ) { if( ( ConverterAllow ) && ( ConverterAllowLocal ) && ( false == PantPressLockActive ) - && ( Mains ) ) { + && ( ( Mains ) + || ( GetTrainsetVoltage() > 0 ) ) ) { // delay timer can be optionally configured, and is set anew whenever converter goes off if( ConverterStartDelayTimer <= 0.0 ) { ConverterFlag = true; @@ -1477,6 +1482,17 @@ void TMoverParameters::ConverterCheck( double const Timestep ) { } }; +// heating system status check +void TMoverParameters::HeatingCheck( double const Timestep ) { + + Heating = ( + ( true == HeatingAllow ) + // powered vehicles are generally required to activate their power source to provide heating + // passive vehicles get a pass in this regard + && ( ( Power < 0.1 ) + || ( true == Mains ) ) ); +} + // water pump status check void TMoverParameters::WaterPumpCheck( double const Timestep ) { // NOTE: breaker override with start type is sm42 specific hack, replace with ability to define the presence of the breaker @@ -7256,14 +7272,14 @@ double TMoverParameters::GetTrainsetVoltage(void) return std::max( ( ( ( Couplers[end::front].Connected ) && ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) - || ( ( Heating ) - && ( Couplers[ end::front ].CouplingFlag & ctrain_heating ) ) ) ) ? + || ( ( Couplers[ end::front ].CouplingFlag & ctrain_heating ) + && ( Couplers[ end::front ].Connected->Heating ) ) ) ) ? Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage : 0.0 ), ( ( ( Couplers[end::rear].Connected ) && ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) - || ( ( Heating ) - && ( Couplers[ end::rear ].CouplingFlag & ctrain_heating ) ) ) ) ? + || ( ( Couplers[ end::rear ].CouplingFlag & ctrain_heating ) + && ( Couplers[ end::rear ].Connected->Heating ) ) ) ) ? Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage : 0.0 ) ); } diff --git a/Model3d.cpp b/Model3d.cpp index 2de55e17..52a24399 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -789,6 +789,27 @@ int TSubModel::count_children() { 1 + Child->count_siblings() ); } +// locates submodel mapped with replacable -4 +std::tuple +TSubModel::find_replacable4() { + + if( m_material == -4 ) { + return std::make_tuple( this, ( fLight != -1.0 ) ); + } + + if( Next != nullptr ) { + auto lookup { Next->find_replacable4() }; + if( std::get( lookup ) != nullptr ) { return lookup; } + } + + if( Child != nullptr ) { + auto lookup { Child->find_replacable4() }; + if( std::get( lookup ) != nullptr ) { return lookup; } + } + + return std::make_tuple( nullptr, false ); +} + int TSubModel::FlagsCheck() { // analiza koniecznych zmian pomiędzy submodelami // samo pomijanie glBindTexture() nie poprawi wydajności diff --git a/Model3d.h b/Model3d.h index 6a1536c3..412c1f2b 100644 --- a/Model3d.h +++ b/Model3d.h @@ -166,6 +166,8 @@ public: TSubModel * ChildGet() { return Child; }; int count_siblings(); int count_children(); + // locates submodel mapped with replacable -4 + std::tuple find_replacable4(); int TriangleAdd(TModel3d *m, material_handle tex, int tri); void SetRotate(float3 vNewRotateAxis, float fNewAngle); void SetRotateXYZ( Math3D::vector3 vNewAngles); diff --git a/Train.cpp b/Train.cpp index 2a437c25..92f42f95 100644 --- a/Train.cpp +++ b/Train.cpp @@ -4153,7 +4153,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 - if( false == Train->mvControlled->Heating ) { + if( false == Train->mvControlled->HeatingAllow ) { // turn on OnCommand_heatingenable( Train, Command ); } @@ -4167,24 +4167,20 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_PRESS ) { + + Train->mvControlled->HeatingAllow = true; // visual feedback Train->ggTrainHeatingButton.UpdateValue( 1.0, Train->dsbSwitch ); - - if( true == Train->mvControlled->Heating ) { return; } // already enabled - - Train->mvControlled->Heating = true; } } void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_PRESS ) { + + Train->mvControlled->HeatingAllow = false; // visual feedback Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch ); - - if( false == Train->mvControlled->Heating ) { return; } // already disabled - - Train->mvControlled->Heating = false; } } @@ -6027,7 +6023,6 @@ bool TTrain::Update( double const Deltatime ) //--------- // hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy if( ( mvControlled->Heating == true ) - && ( mvControlled->Mains == true ) && ( mvControlled->ConvOvldFlag == false ) ) btLampkaOgrzewanieSkladu.Turn( true ); else From 8600550dcde1f55ee78eb5388eb6333219c4f28e Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 2 Apr 2019 18:51:17 +0200 Subject: [PATCH 02/12] build 190402. basic implementation for script generated vehicle destination sign textures --- Classes.h | 1 + Driver.h | 2 +- DynObj.cpp | 76 ++++++++++++++++++++++++++++++++++++++++- DynObj.h | 8 +++++ PyInt.cpp | 3 +- PyInt.h | 18 ---------- Texture.cpp | 16 +++------ Train.cpp | 28 ++------------- dictionary.cpp | 55 +++++++++++++++++++++++++++++ dictionary.h | 31 +++++++++++++++++ maszyna.vcxproj.filters | 6 ++++ mtable.cpp | 27 +++++++++++++++ mtable.h | 1 + version.h | 2 +- 14 files changed, 215 insertions(+), 59 deletions(-) create mode 100644 dictionary.cpp create mode 100644 dictionary.h diff --git a/Classes.h b/Classes.h index ecbfd1b4..8c4209cc 100644 --- a/Classes.h +++ b/Classes.h @@ -40,6 +40,7 @@ class powergridsource_table; class instance_table; class vehicle_table; struct light_array; +struct dictionary_source; namespace scene { struct node_data; diff --git a/Driver.h b/Driver.h index 1c4034d1..d75de7d1 100644 --- a/Driver.h +++ b/Driver.h @@ -407,9 +407,9 @@ private: // methods public: std::string TrainName() const; + Mtable::TTrainParameters const * TrainTimetable() const; private: std::string Relation() const; - Mtable::TTrainParameters const * TrainTimetable() const; int StationIndex() const; int StationCount() const; bool IsStop() const; diff --git a/DynObj.cpp b/DynObj.cpp index 4cca3979..f6fa4469 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -160,6 +160,39 @@ void TAnim::Parovoz(){ // animowanie tłoka i rozrządu parowozu }; */ + + +void TDynamicObject::destination_data::deserialize( cParser &Input ) { + + while( true == deserialize_mapping( Input ) ) { + ; // all work done by while() + } +} + +bool TDynamicObject::destination_data::deserialize_mapping( cParser &Input ) { + // token can be a key or block end + auto const key { Input.getToken( true, "\n\r\t ,;[]" ) }; + + if( ( true == key.empty() ) || ( key == "}" ) ) { return false; } + + if( key == "{" ) { + script = Input.getToken(); + } + else if( key == "update:" ) { + auto const value { Input.getToken() }; + // TODO: implement + } + else if( key == "instance:" ) { + instancing = Input.getToken(); + } + else if( key == "parameters:" ) { + parameters = Input.getToken(); + } + + return true; +} + + //--------------------------------------------------------------------------- TDynamicObject * TDynamicObject::FirstFind(int &coupler_nr, int cf) { // szukanie skrajnego połączonego pojazdu w pociagu @@ -5569,6 +5602,15 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co parser >> JointCabs; } + else if( token == "pydestinationsign:" ) { + DestinationSign.deserialize( parser ); + // supply vehicle folder as script path if none is provided + if( ( false == DestinationSign.script.empty() ) + && ( substr_path( DestinationSign.script ).empty() ) ) { + DestinationSign.script = asBaseDir + DestinationSign.script; + } + } + } while( token != "" ); } // internaldata: @@ -6147,9 +6189,41 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer) { DestinationSign.destination = DestinationFind( destination ); if( DestinationSign.destination != null_handle ) { // got what we wanted, we're done here - break; + return; } } + // if we didn't get static texture we might be able to make one + if( DestinationSign.script.empty() ) { return; } // no script so no way to make the texture + if( numer == "none" ) { return; } // blank or incomplete/malformed timetable, don't bother + + std::string signrequest { + "make:" + + DestinationSign.script + "?" + // timetable include + + "$timetable=" + ( + ctOwner == nullptr ? + MoverParameters->Name : // leading vehicle, can point to it directly + ctOwner->Vehicle()->MoverParameters->Name ) + "&" // owned vehicle, safer to point to owner as carriages can have identical names + // basic instancing string + // NOTE: underscore doesn't have any magic meaning for the time being, it's just less likely to conflict with regular dictionary keys + + "_id1=" + ( + ctOwner != nullptr ? ctOwner->TrainName() : + Mechanik != nullptr ? Mechanik->TrainName() : + "none" ) }; // shouldn't get here but, eh + // TBD, TODO: replace instancing with support for variables in extra parameters string? + if( false == DestinationSign.instancing.empty() ) { + signrequest += + "&_id2=" + ( + DestinationSign.instancing == "name" ? MoverParameters->Name : + DestinationSign.instancing == "type" ? MoverParameters->TypeName : + "none" ); + } + // optionl extra parameters + if( false == DestinationSign.parameters.empty() ) { + signrequest += "&" + DestinationSign.parameters; + } + + DestinationSign.destination = GfxRenderer.Fetch_Material( signrequest ); } material_handle TDynamicObject::DestinationFind( std::string Destination ) { diff --git a/DynObj.h b/DynObj.h index ba9c4a78..1bbe000a 100644 --- a/DynObj.h +++ b/DynObj.h @@ -205,6 +205,14 @@ public: bool has_light { false }; // the submodel was originally configured with self-illumination attribute material_handle destination { null_handle }; // most recently assigned non-blank destination texture material_handle destination_off { null_handle }; // blank destination sign + std::string script; // potential python script used to generate texture data + int update_rate { 0 }; // -1: per stop, 0: none, >0: fps // TBD, TODO: implement? + std::string instancing; // potential method to generate more than one texture per timetable + std::string parameters; // potential extra parameters supplied by mmd file + // methods + void deserialize( cParser &Input ); + private: + bool deserialize_mapping( cParser &Input ); } DestinationSign; float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?) float LoadOffset { 0.f }; diff --git a/PyInt.cpp b/PyInt.cpp index 6ee0891f..e36fd903 100644 --- a/PyInt.cpp +++ b/PyInt.cpp @@ -10,9 +10,8 @@ http://mozilla.org/MPL/2.0/. #include "stdafx.h" #include "PyInt.h" -#include "Globals.h" +#include "dictionary.h" #include "application.h" -#include "renderer.h" #include "Logs.h" void render_task::run() { diff --git a/PyInt.h b/PyInt.h index db097d9b..36880d42 100644 --- a/PyInt.h +++ b/PyInt.h @@ -23,24 +23,6 @@ http://mozilla.org/MPL/2.0/. #define PyGetBool(param) param ? Py_True : Py_False #define PyGetString(param) PyString_FromString(param) -// collection of keyword-value pairs -// NOTE: since our python dictionary operates on a few types, most of the class was hardcoded for simplicity -struct dictionary_source { -// types - template - using keyvaluepair_sequence = std::vector>; -// members - keyvaluepair_sequence floats; - keyvaluepair_sequence integers; - keyvaluepair_sequence bools; - keyvaluepair_sequence strings; -// methods - inline void insert( std::string const &Key, double const Value ) { floats.emplace_back( Key, Value ); } - inline void insert( std::string const &Key, int const Value ) { integers.emplace_back( Key, Value ); } - inline void insert( std::string const &Key, bool const Value ) { bools.emplace_back( Key, Value ); } - inline void insert( std::string const &Key, std::string const Value ) { strings.emplace_back( Key, Value ); } -}; - // TODO: extract common base and inherit specialization from it class render_task { diff --git a/Texture.cpp b/Texture.cpp index e21893bc..11872d34 100644 --- a/Texture.cpp +++ b/Texture.cpp @@ -20,11 +20,13 @@ http://mozilla.org/MPL/2.0/. #include "GL/glew.h" #include "application.h" -#include "utilities.h" +#include "dictionary.h" #include "Globals.h" #include "Logs.h" +#include "utilities.h" #include "sn_utils.h" + #define EU07_DEFERRED_TEXTURE_UPLOAD texture_manager::texture_manager() { @@ -96,17 +98,9 @@ void opengl_texture::make_request() { auto const components { Split( name, '?' ) }; - auto const query { Split( components.back(), '&' ) }; - auto *dictionary { new dictionary_source }; - if( dictionary != nullptr ) { - for( auto const &querypair : query ) { - auto const valuepos { querypair.find( '=' ) }; - dictionary->insert( - ToLower( querypair.substr( 0, valuepos ) ), - querypair.substr( valuepos + 1 ) ); - } - } + auto *dictionary { new dictionary_source( components.back() ) }; + if( dictionary == nullptr ) { return; } Application.request( { ToLower( components.front() ), dictionary, id } ); } diff --git a/Train.cpp b/Train.cpp index 92f42f95..82214068 100644 --- a/Train.cpp +++ b/Train.cpp @@ -30,6 +30,7 @@ http://mozilla.org/MPL/2.0/. #include "Console.h" #include "application.h" #include "renderer.h" +#include "dictionary.h" /* namespace input { @@ -543,31 +544,8 @@ dictionary_source *TTrain::GetTrainState() { dict->insert( "velnext", driver->VelNext ); dict->insert( "actualproximitydist", driver->ActualProximityDist ); // train data - auto const *timetable{ driver->TrainTimetable() }; - - dict->insert( "trainnumber", driver->TrainName() ); - dict->insert( "train_brakingmassratio", timetable->BrakeRatio ); - dict->insert( "train_enginetype", timetable->LocSeries ); - dict->insert( "train_engineload", timetable->LocLoad ); - - dict->insert( "train_stationindex", driver->iStationStart ); - auto const stationcount { driver->StationCount() }; - dict->insert( "train_stationcount", stationcount ); - if( stationcount > 0 ) { - // timetable stations data, if there's any - for( auto stationidx = 1; stationidx <= stationcount; ++stationidx ) { - auto const stationlabel { "train_station" + std::to_string( stationidx ) + "_" }; - auto const &timetableline { timetable->TimeTable[ stationidx ] }; - dict->insert( ( stationlabel + "name" ), Bezogonkow( timetableline.StationName ) ); - dict->insert( ( stationlabel + "fclt" ), Bezogonkow( timetableline.StationWare ) ); - dict->insert( ( stationlabel + "lctn" ), timetableline.km ); - dict->insert( ( stationlabel + "vmax" ), timetableline.vmax ); - dict->insert( ( stationlabel + "ah" ), timetableline.Ah ); - dict->insert( ( stationlabel + "am" ), timetableline.Am ); - dict->insert( ( stationlabel + "dh" ), timetableline.Dh ); - dict->insert( ( stationlabel + "dm" ), timetableline.Dm ); - } - } + driver->TrainTimetable()->serialize( dict ); + dict->insert( "train_stationstart", driver->iStationStart ); dict->insert( "train_atpassengerstop", driver->IsAtPassengerStop ); // world state data dict->insert( "scenario", Global.SceneryFile ); diff --git a/dictionary.cpp b/dictionary.cpp new file mode 100644 index 00000000..f4e987ec --- /dev/null +++ b/dictionary.cpp @@ -0,0 +1,55 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#include "stdafx.h" +#include "dictionary.h" + +#include "simulation.h" +#include "utilities.h" +#include "DynObj.h" +#include "Driver.h" +#include "mtable.h" + +dictionary_source::dictionary_source( std::string const &Input ) { + + auto const keyvaluepairs { Split( Input, '&' ) }; + + for( auto const &keyvaluepair : keyvaluepairs ) { + + auto const valuepos { keyvaluepair.find( '=' ) }; + if( keyvaluepair[ 0 ] != '$' ) { + // regular key, value pairs + insert( + ToLower( keyvaluepair.substr( 0, valuepos ) ), + keyvaluepair.substr( valuepos + 1 ) ); + } + else { + // special case, $key indicates request to include certain dataset clarified by value + auto const key { ToLower( keyvaluepair.substr( 0, valuepos ) ) }; + auto const value { keyvaluepair.substr( valuepos + 1 ) }; + + if( key == "$timetable" ) { + // timetable pulled from (preferably) the owner/direct controller of specified vehicle + auto const *vehicle { simulation::Vehicles.find( value ) }; + auto const *controller { ( + vehicle == nullptr ? nullptr : + vehicle->ctOwner == nullptr ? vehicle->Mechanik : + vehicle->ctOwner ) }; + auto const *timetable { ( + controller != nullptr ? + controller->TrainTimetable() : + nullptr ) }; + + if( timetable != nullptr ) { + timetable->serialize( this ); + } + } + } + } +} diff --git a/dictionary.h b/dictionary.h new file mode 100644 index 00000000..98828856 --- /dev/null +++ b/dictionary.h @@ -0,0 +1,31 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +// collection of keyword-value pairs +// NOTE: since our python dictionary operates on a few types, most of the class was hardcoded for simplicity +struct dictionary_source { +// types + template + using keyvaluepair_sequence = std::vector>; +// members + keyvaluepair_sequence floats; + keyvaluepair_sequence integers; + keyvaluepair_sequence bools; + keyvaluepair_sequence strings; +// constructors + dictionary_source() = default; + dictionary_source( std::string const &Input ); +// methods + inline void insert( std::string const &Key, double const Value ) { floats.emplace_back( Key, Value ); } + inline void insert( std::string const &Key, int const Value ) { integers.emplace_back( Key, Value ); } + inline void insert( std::string const &Key, bool const Value ) { bools.emplace_back( Key, Value ); } + inline void insert( std::string const &Key, std::string const Value ) { strings.emplace_back( Key, Value ); } +}; diff --git a/maszyna.vcxproj.filters b/maszyna.vcxproj.filters index d93a3b07..26cef8b1 100644 --- a/maszyna.vcxproj.filters +++ b/maszyna.vcxproj.filters @@ -339,6 +339,9 @@ Source Files + + Source Files + @@ -623,6 +626,9 @@ Header Files + + Header Files + diff --git a/mtable.cpp b/mtable.cpp index bf910011..01b01259 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/. #include "Globals.h" #include "simulationtime.h" +#include "dictionary.h" #include "utilities.h" double TTrainParameters::CheckTrainLatency() @@ -523,3 +524,29 @@ bool TTrainParameters::DirectionChange() return true; return false; } + +void TTrainParameters::serialize( dictionary_source *Output ) const { + + Output->insert( "trainnumber", TrainName ); + Output->insert( "train_brakingmassratio", BrakeRatio ); + Output->insert( "train_enginetype", LocSeries ); + Output->insert( "train_engineload", LocLoad ); + + Output->insert( "train_stationindex", StationIndex ); + Output->insert( "train_stationcount", StationCount ); + if( StationCount > 0 ) { + // timetable stations data, if there's any + for( auto stationidx = 1; stationidx <= StationCount; ++stationidx ) { + auto const stationlabel { "train_station" + std::to_string( stationidx ) + "_" }; + auto const &timetableline { TimeTable[ stationidx ] }; + Output->insert( ( stationlabel + "name" ), Bezogonkow( timetableline.StationName ) ); + Output->insert( ( stationlabel + "fclt" ), Bezogonkow( timetableline.StationWare ) ); + Output->insert( ( stationlabel + "lctn" ), timetableline.km ); + Output->insert( ( stationlabel + "vmax" ), timetableline.vmax ); + Output->insert( ( stationlabel + "ah" ), timetableline.Ah ); + Output->insert( ( stationlabel + "am" ), timetableline.Am ); + Output->insert( ( stationlabel + "dh" ), timetableline.Dh ); + Output->insert( ( stationlabel + "dm" ), timetableline.Dm ); + } + } +} diff --git a/mtable.h b/mtable.h index ea905e4c..78816aaa 100644 --- a/mtable.h +++ b/mtable.h @@ -83,6 +83,7 @@ class TTrainParameters bool LoadTTfile(std::string scnpath, int iPlus, double vmax); bool DirectionChange(); void StationIndexInc(); + void serialize( dictionary_source *Output ) const; }; class TMTableTime diff --git a/version.h b/version.h index 7ca02639..6c26d2b6 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 327 +#define VERSION_MINOR 402 #define VERSION_REVISION 0 From 7627d18ad351b6dbedfdaa5cf7ad4abd2be1d038 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 3 Apr 2019 16:21:34 +0200 Subject: [PATCH 03/12] ai braking logic tweaks --- Driver.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 7ce285c2..ff2cb70d 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1375,7 +1375,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN if( ( mvOccupied->Vel < v ) || ( v == 0.0 ) ) { // if we're going slower than the target velocity and there's enough room for safe stop, speed up - auto const brakingdistance = fBrakeDist * braking_distance_multiplier( v ); + auto const brakingdistance { 1.2 * fBrakeDist * braking_distance_multiplier( v ) }; if( brakingdistance > 0.0 ) { // maintain desired acc while we have enough room to brake safely, when close enough start paying attention // try to make a smooth transition instead of sharp change @@ -5672,11 +5672,11 @@ TController::UpdateSituation(double dt) { || ( VelNext > vel - 40.0 ) ) ? fBrake_a0[ 0 ] * 0.8 : -fAccThreshold ) - / braking_distance_multiplier( VelNext ) ) { - AccDesired = std::max( -0.06, AccDesired ); + / ( 1.2 * braking_distance_multiplier( VelNext ) ) ) { + AccDesired = std::max( -0.1, AccDesired ); } } - else { + if( AccDesired < -0.1 ) { // i orientuj się szybciej, jeśli hamujesz ReactionTime = 0.25; } @@ -5775,11 +5775,11 @@ TController::UpdateSituation(double dt) { } } } - // yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej - // zwiekszanie predkosci + // yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej zwiekszanie predkosci // Ra 2F1H: jest konflikt histerezy pomiędzy nastawioną pozycją a uzyskiwanym // przyspieszeniem - utrzymanie pozycji powoduje przekroczenie przyspieszenia - if( ( AccDesired - AbsAccS > 0.01 ) ) { + if( ( AccDesired > -0.1 ) // don't add power if not asked for actual speed-up + && ( AccDesired - AbsAccS > 0.025 ) ) { // jeśli przyspieszenie pojazdu jest mniejsze niż żądane oraz... if( vel < ( VelDesired == 1.0 ? // work around for trains getting stuck on tracks with speed limit = 1 From 6769c45103f4b9fd3a8e20fadecaeddf4a7030e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 2 Apr 2019 21:12:46 +0200 Subject: [PATCH 04/12] Better antislipping system in EStED --- McZapkie/MOVER.h | 1 + McZapkie/Mover.cpp | 9 ++++++--- McZapkie/hamulce.cpp | 7 ++++--- McZapkie/hamulce.h | 3 ++- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 815012dd..7352c41c 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -1130,6 +1130,7 @@ public: double AccN = 0.0; // przyspieszenie normalne w [m/s^2] double AccVert = 0.0; // vertical acceleration double nrot = 0.0; + double nrot_eps = 0.0; //przyspieszenie kątowe kół (bez kierunku) double WheelFlat = 0.0; bool TruckHunting { true }; // enable/disable truck hunting calculation /*! rotacja kol [obr/s]*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index f42d92b8..0696c047 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -3724,7 +3724,7 @@ void TMoverParameters::UpdatePipePressure(double dt) Pipe->Flow( temp * Hamulec->GetPF( temp * PipePress, dt, Vel ) + GetDVc( dt ) ); if (ASBType == 128) - Hamulec->ASB(int(SlippingWheels)); + Hamulec->ASB(int(SlippingWheels && (Vel>1))*(1+2*int(nrot_eps<-0.01))); dpPipe = 0; @@ -3972,6 +3972,7 @@ void TMoverParameters::ComputeTotalForce(double dt) { // juz zoptymalizowane: FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // siła oporów ruchu + double old_nrot = abs(nrot); nrot = v2n(); // przeliczenie prędkości liniowej na obrotową if( ( true == TestFlag( BrakeMethod, bp_MHS ) ) @@ -4044,8 +4045,9 @@ void TMoverParameters::ComputeTotalForce(double dt) { } else { - Fb = -Fwheels*Sign(V); - FTrain = 0; + double factor = (FTrain - Fb * Sign(V) != 0 ? Fwheels/(FTrain - Fb * Sign(V)) : 1.0); + Fb *= factor; + FTrain *= factor; } if (nrot < 0.1) { @@ -4054,6 +4056,7 @@ void TMoverParameters::ComputeTotalForce(double dt) { nrot = temp_nrot; } + nrot_eps = (abs(nrot) - (old_nrot))/dt; // doliczenie sił z innych pojazdów for( int end = end::front; end <= end::rear; ++end ) { if( Neighbours[ end ].vehicle != nullptr ) { diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index 6d258f8e..5cc3dd02 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -391,7 +391,8 @@ void TBrake::SetEPS( double const nEPS ) void TBrake::ASB( int const state ) { // 255-b_asb(32) - BrakeStatus = (BrakeStatus & ~b_asb) | ( state * b_asb ); + BrakeStatus = (BrakeStatus & ~b_asb) | ( (state / 2) * b_asb ); + BrakeStatus = (BrakeStatus & ~b_asb_unbrake) | ( (state % 2) * b_asb_unbrake); } int TBrake::GetStatus() @@ -1551,7 +1552,7 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel ) // powtarzacz — podwojny zawor zwrotny temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP); double speed = 1; - if ((ASBP < 0.1) && ((BrakeStatus & b_asb) == b_asb)) + if ((ASBP < 0.1) && ((BrakeStatus & b_asb_unbrake) == b_asb_unbrake)) { temp = 0; speed = 3; @@ -1559,7 +1560,7 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel ) if ((BrakeCyl->P() > temp)) dv = -PFVd(BrakeCyl->P(), 0, 0.02 * SizeBC * speed, temp) * dt; - else if ((BrakeCyl->P() < temp)) + else if ((BrakeCyl->P() < temp) && ((BrakeStatus & b_asb) == 0)) dv = PFVa(BVP, BrakeCyl->P(), 0.02 * SizeBC, temp) * dt; else dv = 0; diff --git a/McZapkie/hamulce.h b/McZapkie/hamulce.h index d09427c5..6ae70eca 100644 --- a/McZapkie/hamulce.h +++ b/McZapkie/hamulce.h @@ -53,7 +53,8 @@ static int const b_on = 2; //napelnianie static int const b_rfl = 4; //uzupelnianie static int const b_rls = 8; //odluzniacz static int const b_ep = 16; //elektropneumatyczny -static int const b_asb = 32; //elektropneumatyczny +static int const b_asb = 32; //przeciwposlizg-wstrzymanie +static int const b_asb_unbrake = 64; //przeciwposlizg-luzowanie static int const b_dmg = 128; //wylaczony z dzialania /*uszkodzenia hamulca*/ From 449cd9f637a5d32acaa2effa2184e7ce98be97e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Tue, 2 Apr 2019 22:54:56 +0200 Subject: [PATCH 05/12] Added new LocalBrake algorithm for TRAXX - test of mechanism --- DynObj.cpp | 6 ++++++ McZapkie/MOVER.h | 2 ++ McZapkie/Mover.cpp | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/DynObj.cpp b/DynObj.cpp index f6fa4469..1ef1538e 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2783,6 +2783,7 @@ bool TDynamicObject::Update(double dt, double dt1) MoverParameters->eimic_real = eimic; MoverParameters->SendCtrlToNext("EIMIC", Max0R(0, eimic), MoverParameters->CabNo); auto LBR = Max0R(-eimic, 0); + auto eim_lb = (Mechanik->AIControllFlag || !MoverParameters->LocHandleTimeTraxx ? 0 : MoverParameters->eim_localbrake); // 1. ustal wymagana sile hamowania calego pociagu // - opoznienie moze byc ustalane na podstawie charakterystyki @@ -3013,6 +3014,11 @@ bool TDynamicObject::Update(double dt, double dt1) p->MoverParameters->LocalBrakePosAEIM = p->MoverParameters->LocalBrakePosAEIM; else p->MoverParameters->LocalBrakePosAEIM = 0; + if (p->MoverParameters->LocHandleTimeTraxx) + { + p->MoverParameters->eim_localbrake = eim_lb; + p->MoverParameters->LocalBrakePosAEIM = std::max(p->MoverParameters->LocalBrakePosAEIM, eim_lb); + } ++i; } diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 7352c41c..6902be65 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -891,6 +891,7 @@ public: TBrakeValve BrakeValve = TBrakeValve::NoValve; TBrakeHandle BrakeHandle = TBrakeHandle::NoHandle; TBrakeHandle BrakeLocHandle = TBrakeHandle::NoHandle; + bool LocHandleTimeTraxx = false; /*hamulec dodatkowy typu traxx*/ double MBPM = 1.0; /*masa najwiekszego cisnienia*/ std::shared_ptr Hamulec; @@ -1306,6 +1307,7 @@ public: /*- zmienne dla lokomotyw z silnikami indukcyjnymi -*/ double eimic = 0; /*aktualna pozycja zintegrowanego sterowania jazda i hamowaniem*/ double eimic_real = 0; /*faktycznie uzywana pozycja zintegrowanego sterowania jazda i hamowaniem*/ + double eim_localbrake = 0; /*nastawa hamowania dodatkowego pneumatycznego lokomotywy*/ int EIMCtrlType = 0; /*rodzaj wariantu zadajnika jazdy*/ bool SpeedCtrlTypeTime = false; /*czy tempomat sterowany czasowo*/ double eimv_pr = 0; /*realizowany procent dostepnej sily rozruchu/hamowania*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 0696c047..82d0e472 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -6032,6 +6032,26 @@ void TMoverParameters::CheckEIMIC(double dt) } if (MainCtrlPos >= 3 && eimic < 0) eimic = 0; if (MainCtrlPos <= 3 && eimic > 0) eimic = 0; + if (LocHandleTimeTraxx) + { + if (LocalBrakeRatio() < 0.05) //pozycja 0 + { + eim_localbrake -= dt*0.17; //zmniejszanie + } + + if (LocalBrakeRatio() > 0.15) //pozycja 2 + { + eim_localbrake += dt*0.17; //wzrastanie + eim_localbrake = std::max(eim_localbrake, BrakePress / MaxBrakePress[0]); + } + else + { + if (eim_localbrake < Hamulec->GetEDBCP() / MaxBrakePress[0]) + eim_localbrake = 0; + } + eim_localbrake = clamp(eim_localbrake, 0.0, 1.0); + if (eim_localbrake > 0.04 && eimic > 0) eimic = 0; + } break; case 2: switch (MainCtrlPos) @@ -8647,6 +8667,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { extract_value( CoupledCtrl, "CoupledCtrl", line, "" ); extract_value( EIMCtrlType, "EIMCtrlType", line, "" ); clamp( EIMCtrlType, 0, 3 ); + LocHandleTimeTraxx = (extract_value("LocalBrakeTraxx", line) == "Yes"); extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR From a081077c2f94de523ec20e3f40cfc1b5faffd14b Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Thu, 4 Apr 2019 01:16:00 +0200 Subject: [PATCH 06/12] build 190403. support for combined rail squeal sound, ai braking logic tweaks --- Driver.cpp | 29 +++++++++++++++++------------ DynObj.cpp | 4 ++++ version.h | 2 +- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index ff2cb70d..09996138 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2533,9 +2533,9 @@ bool TController::PrepareEngine() } // sync virtual brake state with the 'real' one std::unordered_map const brakepositions { - { mvOccupied->Handle->GetPos( bh_RP ), gbh_RP }, - { mvOccupied->Handle->GetPos( bh_NP ), gbh_NP }, - { mvOccupied->Handle->GetPos( bh_FS ), gbh_FS } }; + { static_cast( mvOccupied->Handle->GetPos( bh_RP ) ), gbh_RP }, + { static_cast( mvOccupied->Handle->GetPos( bh_NP ) ), gbh_NP }, + { static_cast( mvOccupied->Handle->GetPos( bh_FS ) ), gbh_FS } }; auto const lookup { brakepositions.find( static_cast( mvOccupied->fBrakeCtrlPos ) ) }; if( lookup != brakepositions.end() ) { BrakeLevelSet( lookup->second ); // GBH @@ -4676,11 +4676,11 @@ TController::UpdateSituation(double dt) { // TODO: test if we can use the distances calculation from obey_train fMinProximityDist = std::min( 5 + iVehicles, 25 ); fMaxProximityDist = std::min( 10 + iVehicles, 50 ); -/* - if( IsHeavyCargoTrain ) { - fMaxProximityDist *= 1.5; + // HACK: modern vehicles might brake slower at low speeds, increase safety margin as crude counter + if( mvControlling->EIMCtrlType > 0 ) { + fMinProximityDist += 5.0; + fMaxProximityDist += 5.0; } -*/ fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania // margines prędkości powodujący załączenie napędu // były problemy z jazdą np. 3km/h podczas ładowania wagonów @@ -5160,7 +5160,11 @@ TController::UpdateSituation(double dt) { 20.0 ) ); // others if( vel > VelDesired + fVelPlus ) { // if going too fast force some prompt braking - AccPreferred = std::min( -0.65, AccPreferred ); + AccPreferred = std::min( + ( ( mvOccupied->CategoryFlag & 2 ) ? + -0.65 : // cars + -0.30 ), // others + AccPreferred ); } } @@ -5673,7 +5677,7 @@ TController::UpdateSituation(double dt) { fBrake_a0[ 0 ] * 0.8 : -fAccThreshold ) / ( 1.2 * braking_distance_multiplier( VelNext ) ) ) { - AccDesired = std::max( -0.1, AccDesired ); + AccDesired = std::max( -0.06, AccDesired ); } } if( AccDesired < -0.1 ) { @@ -5778,8 +5782,8 @@ TController::UpdateSituation(double dt) { // yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej zwiekszanie predkosci // Ra 2F1H: jest konflikt histerezy pomiędzy nastawioną pozycją a uzyskiwanym // przyspieszeniem - utrzymanie pozycji powoduje przekroczenie przyspieszenia - if( ( AccDesired > -0.1 ) // don't add power if not asked for actual speed-up - && ( AccDesired - AbsAccS > 0.025 ) ) { + if( ( AccDesired > -0.06 ) // don't add power if not asked for actual speed-up + && ( AccDesired - AbsAccS > 0.05 ) ) { // jeśli przyspieszenie pojazdu jest mniejsze niż żądane oraz... if( vel < ( VelDesired == 1.0 ? // work around for trains getting stuck on tracks with speed limit = 1 @@ -5871,7 +5875,8 @@ TController::UpdateSituation(double dt) { } } } - if ((AccDesired < fAccGravity - 0.05) && (AbsAccS < AccDesired - fBrake_a1[0]*0.51)) { + if ( ( AccDesired < fAccGravity - 0.05 ) + && ( ( AccDesired - fBrake_a1[0]*0.51 ) ) - AbsAccS > 0.05 ) { // jak hamuje, to nie tykaj kranu za często // yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2 if( OrderCurrentGet() != Disconnect ) { diff --git a/DynObj.cpp b/DynObj.cpp index 1ef1538e..6c93fbb6 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -4087,6 +4087,10 @@ void TDynamicObject::RenderSounds() { } if( volume > 0.05 ) { rscurve + .pitch( + true == rscurve.is_combined() ? + MoverParameters->Vel * 0.01f : + rscurve.m_frequencyoffset + rscurve.m_frequencyfactor * 1.f ) .gain( 2.5 * volume ) .play( sound_flags::exclusive | sound_flags::looping ); } diff --git a/version.h b/version.h index 6c26d2b6..92c0d111 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 19 -#define VERSION_MINOR 402 +#define VERSION_MINOR 403 #define VERSION_REVISION 0 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 07/12] 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 08/12] 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 09/12] 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 10/12] 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 11/12] 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 12/12] 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()