build 180909. scenario time override, support for random texture sets in .mat files, minor bug fixes

This commit is contained in:
tmj-fstate
2018-09-09 21:25:09 +02:00
parent 397628242c
commit 251a31a705
14 changed files with 107 additions and 93 deletions

View File

@@ -2817,9 +2817,9 @@ bool TController::IncSpeed()
// if it generates enough traction force
// to build up speed to 30/40 km/h for passenger/cargo train (10 km/h less if going uphill)
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 };
auto const useseriesmodevoltage { 0.80 * mvControlling->EnginePowerSource.CollectorParameters.MaxV };
auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) };
auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) };
auto const useseriesmodevoltage { 0.80 * mvControlling->EnginePowerSource.CollectorParameters.MaxV };
auto const useseriesmode = (
( mvControlling->Imax > mvControlling->ImaxLo )
|| ( fVoltage < useseriesmodevoltage )

View File

@@ -307,6 +307,12 @@ global_settings::ConfigParse(cParser &Parser) {
// max 8 lights per opengl specs, minus one used for sun. at least one light for controlled vehicle
DynamicLightCount = clamp( DynamicLightCount, 1, 7 );
}
else if( token == "scenario.time.override" ) {
// shift (in hours) applied to train timetables
Parser.getTokens( 1, false );
Parser >> ScenarioTimeOverride;
ScenarioTimeOverride = clamp( ScenarioTimeOverride, 0.f, 24 * 1439 / 1440.f );
}
else if( token == "scenario.time.offset" ) {
// shift (in hours) applied to train timetables
Parser.getTokens( 1, false );

View File

@@ -78,6 +78,7 @@ struct global_settings {
bool FakeLight{ false }; // toggle between fixed and dynamic daylight
double fTimeSpeed{ 1.0 }; // przyspieszenie czasu, zmienna do testów
double fLatitudeDeg{ 52.0 }; // szerokość geograficzna
float ScenarioTimeOverride { std::numeric_limits<float>::quiet_NaN() }; // requested scenario start time
float ScenarioTimeOffset { 0.f }; // time shift (in hours) applied to train timetables
bool ScenarioTimeCurrent { false }; // automatic time shift to match scenario time with local clock
bool bInactivePause{ true }; // automatyczna pauza, gdy okno nieaktywne

View File

@@ -1127,7 +1127,8 @@ public:
double dizel_engage = 0.0; /*sprzeglo skrzyni biegow: aktualny docisk*/
double dizel_automaticgearstatus = 0.0; /*0 - bez zmiany, -1 zmiana na nizszy +1 zmiana na wyzszy*/
bool dizel_startup { false }; // engine startup procedure request indicator
bool dizel_ignition = false; // engine ignition request indicator
bool dizel_ignition { false }; // engine ignition request indicator
bool dizel_spinup { false }; // engine spin up to idle speed flag
double dizel_engagedeltaomega = 0.0; /*roznica predkosci katowych tarcz sprzegla*/
double dizel_n_old = 0.0; /*poredkosc na potrzeby obliczen sprzegiel*/
double dizel_Torque = 0.0; /*poredkosc na potrzeby obliczen sprzegiel*/

View File

@@ -5974,8 +5974,9 @@ bool TMoverParameters::dizel_Update(double dt) {
dizel_startup = false;
dizel_ignition = false;
// TODO: split engine and main circuit state indicator in two separate flags
Mains = true;
LastSwitchingTime = 0;
Mains = true;
dizel_spinup = true;
enrot = std::max(
enrot,
0.35 * ( // TODO: dac zaleznie od temperatury i baterii
@@ -5985,6 +5986,14 @@ bool TMoverParameters::dizel_Update(double dt) {
}
dizel_spinup = (
dizel_spinup
&& Mains
&& ( enrot < 0.95 * (
EngineType == TEngineType::DieselEngine ?
dizel_nmin :
DElist[ 0 ].RPM / 60.0 ) ) );
if( ( true == Mains )
&& ( false == FuelPump.is_active ) ) {
// knock out the engine if the fuel pump isn't feeding it
@@ -6105,7 +6114,7 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt)
// wstrzymywanie przy malych obrotach
Moment -= dizel_Mstand;
}
if (true == dizel_ignition)
if (true == dizel_spinup)
Moment += dizel_Mstand / (0.3 + std::max(0.0, enrot/dizel_nmin)); //rozrusznik
dizel_Torque = Moment;
@@ -6216,11 +6225,10 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt)
}
if ((enrot <= 0) && (!dizel_ignition))
{
Mains = false;
enrot = 0;
}
if( ( enrot <= 0 ) && ( false == dizel_spinup ) ) {
MainSwitch( false );
enrot = 0;
}
dizel_n_old = n; //obecna predkosc katowa na potrzeby kolejnej klatki

View File

@@ -5094,16 +5094,16 @@ bool TTrain::Update( double const Deltatime )
( true == mvControlled->ResistorsFlagCheck() )
|| ( mvControlled->MainCtrlActualPos == 0 ) ); // do EU04
if( ( mvControlled->Im != 0 )
|| ( mvOccupied->BrakePress > 2 )
if( ( mvControlled->StLinFlag )
|| ( mvOccupied->BrakePress > 2.0 )
|| ( mvOccupied->PipePress < 3.6 ) ) {
// Ra: czy to jest udawanie działania styczników liniowych?
btLampkaStyczn.Turn( false );
}
else if( mvOccupied->BrakePress < 1 )
else if( mvOccupied->BrakePress < 1.0 )
btLampkaStyczn.Turn( true ); // mozna prowadzic rozruch
if( ( ( TestFlag( mvControlled->Couplers[ 1 ].CouplingFlag, ctrain_controll ) ) && ( mvControlled->CabNo == 1 ) ) ||
( ( TestFlag( mvControlled->Couplers[ 0 ].CouplingFlag, ctrain_controll ) ) && ( mvControlled->CabNo == -1 ) ) )
if( ( ( TestFlag( mvControlled->Couplers[ side::rear ].CouplingFlag, coupling::control ) ) && ( mvControlled->CabNo == 1 ) )
|| ( ( TestFlag( mvControlled->Couplers[ side::front ].CouplingFlag, coupling::control ) ) && ( mvControlled->CabNo == -1 ) ) )
btLampkaUkrotnienie.Turn( true );
else
btLampkaUkrotnienie.Turn( false );
@@ -5155,10 +5155,10 @@ bool TTrain::Update( double const Deltatime )
}
if( mvControlled->Signalling == true ) {
if( mvOccupied->BrakePress >= 0.145f ) {
if( mvOccupied->BrakePress >= 1.45f ) {
btLampkaHamowanie1zes.Turn( true );
}
if( mvControlled->BrakePress < 0.075f ) {
if( mvControlled->BrakePress < 0.75f ) {
btLampkaHamowanie1zes.Turn( false );
}
}
@@ -5298,12 +5298,12 @@ bool TTrain::Update( double const Deltatime )
( true == tmp->MoverParameters->ResistorsFlagCheck() )
|| ( tmp->MoverParameters->MainCtrlActualPos == 0 ) ); // do EU04
if( ( tmp->MoverParameters->Itot != 0 )
|| ( tmp->MoverParameters->BrakePress > 0.2 )
if( ( tmp->MoverParameters->StLinFlag )
|| ( tmp->MoverParameters->BrakePress > 2.0 )
|| ( tmp->MoverParameters->PipePress < 0.36 ) ) {
btLampkaStycznB.Turn( false );
}
else if( tmp->MoverParameters->BrakePress < 0.1 ) {
else if( tmp->MoverParameters->BrakePress < 1.0 ) {
btLampkaStycznB.Turn( true ); // mozna prowadzic rozruch
}
// hunter-271211: sygnalizacja poslizgu w pierwszym pojezdzie, gdy wystapi w drugim
@@ -5311,12 +5311,15 @@ bool TTrain::Update( double const Deltatime )
btLampkaSprezarkaB.Turn( tmp->MoverParameters->CompressorFlag ); // mutopsitka dziala
btLampkaSprezarkaBOff.Turn( false == tmp->MoverParameters->CompressorFlag );
if ((tmp->MoverParameters->BrakePress >= 0.145f) && (mvControlled->Signalling == true))
{
btLampkaHamowanie2zes.Turn( true );
if( mvControlled->Signalling == true ) {
if( tmp->MoverParameters->BrakePress >= 1.45f ) {
btLampkaHamowanie2zes.Turn( true );
}
if( tmp->MoverParameters->BrakePress < 0.75f ) {
btLampkaHamowanie2zes.Turn( false );
}
}
if ((tmp->MoverParameters->BrakePress < 0.075f) || (mvControlled->Signalling == false))
{
else {
btLampkaHamowanie2zes.Turn( false );
}
btLampkaNadmPrzetwB.Turn( tmp->MoverParameters->ConvOvldFlag ); // nadmiarowy przetwornicy?

View File

@@ -33,13 +33,10 @@ opengl_material::deserialize( cParser &Input, bool const Loadnow ) {
// imports member data pair from the config file
bool
opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool const Loadnow ) {
// token can be a key or block end
std::string const key { Input.getToken<std::string>( true, "\n\r\t ;[]" ) };
if( ( true == key.empty() ) || ( key == "}" ) ) { return false; }
// NOTE: comma can be part of legacy file names, so we don't treat it as a separator here
auto const value { Input.getToken<std::string>( true, "\n\r\t ;" ) };
std::string const key { Input.getToken<std::string>( true, "\n\r\t ;[]" ) };
// key can be an actual key or block end
if( ( true == key.empty() ) || ( key == "}" ) ) { return false; }
if( Priority != -1 ) {
// regular attribute processing mode
@@ -60,7 +57,7 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c
|| ( key == "texture_diffuse:" ) ) {
if( ( texture1 == null_handle )
|| ( Priority > priority1 ) ) {
texture1 = GfxRenderer.Fetch_Texture( value, Loadnow );
texture1 = GfxRenderer.Fetch_Texture( deserialize_random_set( Input ), Loadnow );
priority1 = Priority;
}
}
@@ -68,20 +65,24 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c
|| ( key == "texture_normalmap:" ) ) {
if( ( texture2 == null_handle )
|| ( Priority > priority2 ) ) {
texture2 = GfxRenderer.Fetch_Texture( value, Loadnow );
texture2 = GfxRenderer.Fetch_Texture( deserialize_random_set( Input ), Loadnow );
priority2 = Priority;
}
}
else if( value == "{" ) {
// unrecognized or ignored token, but comes with attribute block and potential further nesting
// go through it and discard the content
while( true == deserialize_mapping( Input, -1, Loadnow ) ) {
; // all work is done in the header
else {
auto const value { Input.getToken<std::string>( true, "\n\r\t ;" ) };
if( value == "{" ) {
// unrecognized or ignored token, but comes with attribute block and potential further nesting
// go through it and discard the content
while( true == deserialize_mapping( Input, -1, Loadnow ) ) {
; // all work is done in the header
}
}
}
}
else {
// discard mode; ignores all retrieved tokens
auto const value { Input.getToken<std::string>( true, "\n\r\t ;" ) };
if( value == "{" ) {
// ignored tokens can come with their own blocks, ignore these recursively
// go through it and discard the content

View File

@@ -37,6 +37,9 @@ private:
// imports member data pair from the config file, overriding existing parameter values of lower priority
bool
deserialize_mapping( cParser &Input, int const Priority, bool const Loadnow );
// extracts name of the sound file from provided data stream
std::string
deserialize_filename( cParser &Input );
// members
int priority1 { -1 }; // priority of last loaded primary texture

View File

@@ -541,6 +541,10 @@ state_serializer::deserialize_time( cParser &Input, scene::scratch_data &Scratch
auto const *localtime = std::localtime( &timenow );
Global.ScenarioTimeOffset = ( ( localtime->tm_hour * 60 + localtime->tm_min ) - ( time.wHour * 60 + time.wMinute ) ) / 60.f;
}
else if( false == std::isnan( Global.ScenarioTimeOverride ) ) {
// scenario time override takes precedence over scenario time offset
Global.ScenarioTimeOffset = ( ( Global.ScenarioTimeOverride * 60 ) - ( time.wHour * 60 + time.wMinute ) ) / 60.f;
}
// remaining sunrise and sunset parameters are no longer used, as they're now calculated dynamically
// anything else left in the section has no defined meaning

View File

@@ -101,13 +101,13 @@ sound_source::deserialize( cParser &Input, sound_type const Legacytype, int cons
switch( Legacytype ) {
case sound_type::single: {
// single sample only
m_sounds[ main ].buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
m_sounds[ main ].buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
break;
}
case sound_type::multipart: {
// three samples: start, middle, stop
for( auto &sound : m_sounds ) {
sound.buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
sound.buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
}
break;
}
@@ -147,32 +147,6 @@ sound_source::deserialize( cParser &Input, sound_type const Legacytype, int cons
return *this;
}
// extracts name of the sound file from provided data stream
std::string
sound_source::deserialize_filename( cParser &Input ) {
auto token { Input.getToken<std::string>( true, "\n\r\t ,;" ) };
if( token != "[" ) {
// simple case, single file
return token;
}
// if instead of filename we've encountered '[' this marks a beginning of random sounds
// we retrieve all entries, then return a random one
std::vector<std::string> filenames;
while( ( ( token = Input.getToken<std::string>( true, "\n\r\t ,;" ) ) != "" )
&& ( token != "]" ) ) {
filenames.emplace_back( token );
}
if( false == filenames.empty() ) {
std::shuffle( std::begin( filenames ), std::end( filenames ), Global.random_engine );
return filenames.front();
}
else {
// shouldn't ever get here but, eh
return "";
}
}
// imports member data pair from the config file
bool
sound_source::deserialize_mapping( cParser &Input ) {
@@ -183,16 +157,16 @@ sound_source::deserialize_mapping( cParser &Input ) {
// if not block end then the key is followed by assigned value or sub-block
if( key == "soundmain:" ) {
sound( sound_id::main ).buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
sound( sound_id::main ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
}
else if( key == "soundset:" ) {
deserialize_soundset( Input );
}
else if( key == "soundbegin:" ) {
sound( sound_id::begin ).buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
sound( sound_id::begin ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
}
else if( key == "soundend:" ) {
sound( sound_id::end ).buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
sound( sound_id::end ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
}
else if( key.compare( 0, std::min<std::size_t>( key.size(), 5 ), "sound" ) == 0 ) {
// sound chunks, defined with key soundX where X = activation threshold
@@ -203,7 +177,7 @@ sound_source::deserialize_mapping( cParser &Input ) {
m_soundchunks.emplace_back(
soundchunk_pair {
// sound data
{ audio::renderer.fetch_buffer( deserialize_filename( Input ) ), 0 },
{ audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) ), 0 },
// chunk data
{ std::stoi( key.substr( indexstart, indexend - indexstart ) ), 0, 0, 1.f } } );
}
@@ -272,26 +246,12 @@ sound_source::deserialize_mapping( cParser &Input ) {
void
sound_source::deserialize_soundset( cParser &Input ) {
auto token { Input.getToken<std::string>( true, "\n\r\t ,;|" ) };
if( token != "[" ) {
// simple case, basic set of three filenames separated with |
// three samples: start, middle, stop
sound( sound_id::begin ).buffer = audio::renderer.fetch_buffer( token );
sound( sound_id::main ).buffer = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;|" ) );
sound( sound_id::end ).buffer = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;|" ) );
return;
}
// if instead of filename we've encountered '[' this marks a beginning of random sets
// we retrieve all entries, then process a random one
std::vector<std::string> soundsets;
while( ( ( token = Input.getToken<std::string>( true, "\n\r\t ,;" ) ) != "" )
&& ( token != "]" ) ) {
soundsets.emplace_back( token );
}
if( false == soundsets.empty() ) {
std::shuffle( std::begin( soundsets ), std::end( soundsets ), Global.random_engine );
return deserialize_soundset( cParser( soundsets.front() ) );
}
auto const soundset { deserialize_random_set( Input, "\n\r\t ,;" ) };
// split retrieved set
cParser setparser( soundset );
sound( sound_id::begin ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
sound( sound_id::main ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
sound( sound_id::end ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
}
// sends content of the class in legacy (text) format to provided stream

View File

@@ -150,9 +150,6 @@ private:
};
// methods
// extracts name of the sound file from provided data stream
std::string
deserialize_filename( cParser &Input );
// imports member data pair from the provided data stream
bool
deserialize_mapping( cParser &Input );

View File

@@ -416,3 +416,29 @@ glm::dvec3 LoadPoint( cParser &Input ) {
return point;
}
// extracts a group of tokens from provided data stream, returns one of them picked randomly
std::string
deserialize_random_set( cParser &Input, char const *Break ) {
auto token { Input.getToken<std::string>( true, Break ) };
if( token != "[" ) {
// simple case, single token
return token;
}
// if instead of a single token we've encountered '[' this marks a beginning of a random set
// we retrieve all entries, then return a random one
std::vector<std::string> tokens;
while( ( ( token = deserialize_random_set( Input, Break ) ) != "" )
&& ( token != "]" ) ) {
tokens.emplace_back( token );
}
if( false == tokens.empty() ) {
std::shuffle( std::begin( tokens ), std::end( tokens ), Global.random_engine );
return tokens.front();
}
else {
// shouldn't ever get here but, eh
return "";
}
}

View File

@@ -309,4 +309,8 @@ nearest_segment_point( VecType_ const &Segmentstart, VecType_ const &Segmentend,
glm::dvec3 LoadPoint( class cParser &Input );
// extracts a group of tokens from provided data stream
std::string
deserialize_random_set( cParser &Input, char const *Break = "\n\r\t ;" );
//---------------------------------------------------------------------------

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 18
#define VERSION_MINOR 904
#define VERSION_MINOR 909
#define VERSION_REVISION 0