Merge branch 'milek-dev' into gfx-work

This commit is contained in:
milek7
2019-04-05 19:36:50 +02:00
26 changed files with 612 additions and 203 deletions

View File

@@ -162,6 +162,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<std::string>( true, "\n\r\t ,;[]" ) };
if( ( true == key.empty() ) || ( key == "}" ) ) { return false; }
if( key == "{" ) {
script = Input.getToken<std::string>();
}
else if( key == "update:" ) {
auto const value { Input.getToken<std::string>() };
// TODO: implement
}
else if( key == "instance:" ) {
instancing = Input.getToken<std::string>();
}
else if( key == "parameters:" ) {
parameters = Input.getToken<std::string>();
}
return true;
}
//---------------------------------------------------------------------------
TDynamicObject * TDynamicObject::FirstFind(int &coupler_nr, int cf)
{ // szukanie skrajnego połączonego pojazdu w pociagu
@@ -918,6 +951,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])
@@ -1944,6 +1979,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" );
@@ -2067,6 +2106,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 ) {
@@ -2540,6 +2589,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.0)
@@ -2700,6 +2770,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
@@ -2930,6 +3001,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;
}
@@ -4014,6 +4090,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 );
}
@@ -4239,7 +4319,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 ] ).get_or_guess_opacity() == 0.0f ) {
// tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
@@ -5536,6 +5617,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:
@@ -6083,45 +6173,92 @@ 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<std::string> 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
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 ) {
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<std::string> destinations = {
numer + '@' + MoverParameters->TypeName,
numer,
to + '@' + MoverParameters->TypeName,
to,
"nowhere" + '@' + MoverParameters->TypeName,
"nowhere" };
std::vector<std::string> 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
@@ -6806,6 +6943,9 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) {
if( pantograph->hvPowerWire != nullptr ) {
// jeżeli znamy drut z poprzedniego przebiegu
for( int attempts = 0; attempts < 30; ++attempts ) {
// sanity check. shouldn't happen in theory, but did happen in practice
if( pantograph->hvPowerWire == nullptr ) { break; }
// powtarzane aż do znalezienia odpowiedniego odcinka na liście dwukierunkowej
if( pantograph->hvPowerWire->iLast & 0x3 ) {
// dla ostatniego i przedostatniego przęsła wymuszamy szukanie innego
@@ -6821,6 +6961,7 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) {
}
// obliczamy wyraz wolny równania płaszczyzny (to miejsce nie jest odpowienie)
// podstawiamy równanie parametryczne drutu do równania płaszczyzny pantografu
// TODO: investigate this routine with reardriver/negative speed, does it picks the right wire?
auto const fRaParam =
-( glm::dot( pantograph->hvPowerWire->pPoint1, vFront ) - glm::dot( pant0, vFront ) )
/ glm::dot( pantograph->hvPowerWire->vParametric, vFront );