mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-24 08:39:18 +02:00
Merge remote-tracking branch 'refs/remotes/TMJ/master'
This commit is contained in:
@@ -40,6 +40,7 @@ class powergridsource_table;
|
|||||||
class instance_table;
|
class instance_table;
|
||||||
class vehicle_table;
|
class vehicle_table;
|
||||||
struct light_array;
|
struct light_array;
|
||||||
|
struct dictionary_source;
|
||||||
|
|
||||||
namespace scene {
|
namespace scene {
|
||||||
struct node_data;
|
struct node_data;
|
||||||
|
|||||||
54
Driver.cpp
54
Driver.cpp
@@ -1375,7 +1375,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
if( ( mvOccupied->Vel < v )
|
if( ( mvOccupied->Vel < v )
|
||||||
|| ( v == 0.0 ) ) {
|
|| ( v == 0.0 ) ) {
|
||||||
// if we're going slower than the target velocity and there's enough room for safe stop, speed up
|
// 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 ) {
|
if( brakingdistance > 0.0 ) {
|
||||||
// maintain desired acc while we have enough room to brake safely, when close enough start paying attention
|
// 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
|
// try to make a smooth transition instead of sharp change
|
||||||
@@ -2127,6 +2127,11 @@ bool TController::CheckVehicles(TOrders user)
|
|||||||
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) {
|
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) {
|
||||||
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
|
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
|
||||||
p->MoverParameters->BatterySwitch( true );
|
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")
|
if (p->asDestination == "none")
|
||||||
@@ -2358,6 +2363,7 @@ double TController::BrakeAccFactor() const
|
|||||||
double Factor = 1.0;
|
double Factor = 1.0;
|
||||||
|
|
||||||
if( ( fAccThreshold != 0.0 )
|
if( ( fAccThreshold != 0.0 )
|
||||||
|
&& ( AccDesired < 0.0 )
|
||||||
&& ( ( ActualProximityDist > fMinProximityDist )
|
&& ( ( ActualProximityDist > fMinProximityDist )
|
||||||
|| ( mvOccupied->Vel > VelDesired + fVelPlus ) ) ) {
|
|| ( 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 );
|
Factor += ( fBrakeReaction * ( /*mvOccupied->BrakeCtrlPosR*/BrakeCtrlPosition < 0.5 ? 1.5 : 1 ) ) * mvOccupied->Vel / ( std::max( 0.0, ActualProximityDist ) + 1 ) * ( ( AccDesired - AbsAccS_pub ) / fAccThreshold );
|
||||||
@@ -2529,9 +2535,9 @@ bool TController::PrepareEngine()
|
|||||||
}
|
}
|
||||||
// sync virtual brake state with the 'real' one
|
// sync virtual brake state with the 'real' one
|
||||||
std::unordered_map<int, int> const brakepositions {
|
std::unordered_map<int, int> const brakepositions {
|
||||||
{ mvOccupied->Handle->GetPos( bh_RP ), gbh_RP },
|
{ static_cast<int>( mvOccupied->Handle->GetPos( bh_RP ) ), gbh_RP },
|
||||||
{ mvOccupied->Handle->GetPos( bh_NP ), gbh_NP },
|
{ static_cast<int>( mvOccupied->Handle->GetPos( bh_NP ) ), gbh_NP },
|
||||||
{ mvOccupied->Handle->GetPos( bh_FS ), gbh_FS } };
|
{ static_cast<int>( mvOccupied->Handle->GetPos( bh_FS ) ), gbh_FS } };
|
||||||
auto const lookup { brakepositions.find( static_cast<int>( mvOccupied->fBrakeCtrlPos ) ) };
|
auto const lookup { brakepositions.find( static_cast<int>( mvOccupied->fBrakeCtrlPos ) ) };
|
||||||
if( lookup != brakepositions.end() ) {
|
if( lookup != brakepositions.end() ) {
|
||||||
BrakeLevelSet( lookup->second ); // GBH
|
BrakeLevelSet( lookup->second ); // GBH
|
||||||
@@ -3568,7 +3574,7 @@ void TController::Doors( bool const Open, int const Side ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( AIControllFlag ) {
|
if( AIControllFlag ) {
|
||||||
if( ( true == mvOccupied->Doors.has_autowarning )
|
if( ( true == mvOccupied->Doors.has_warning )
|
||||||
&& ( false == mvOccupied->DepartureSignal )
|
&& ( false == mvOccupied->DepartureSignal )
|
||||||
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
||||||
mvOccupied->signal_departure( true ); // załącenie bzyczka
|
mvOccupied->signal_departure( true ); // załącenie bzyczka
|
||||||
@@ -3581,13 +3587,14 @@ void TController::Doors( bool const Open, int const Side ) {
|
|||||||
|| ( false == AIControllFlag ) ) ) {
|
|| ( false == AIControllFlag ) ) ) {
|
||||||
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
|
// 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 )
|
if( ( pVehicle->MoverParameters->Doors.close_control == control_t::conductor )
|
||||||
|| ( ( true == AIControllFlag )
|
|| ( ( true == AIControllFlag ) ) ) {
|
||||||
&& ( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|
|
||||||
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) ) ) {
|
|
||||||
// if the door are controlled by the driver, we let the user operate them unless this user is an ai
|
// 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
|
// the train conductor, if present, handles door operation also for human-driven trains
|
||||||
pVehicle->MoverParameters->OperateDoors( side::right, false );
|
if( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|
||||||
pVehicle->MoverParameters->OperateDoors( side::left, false );
|
|| ( 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 ) {
|
if( pVehicle->MoverParameters->Doors.permit_needed ) {
|
||||||
pVehicle->MoverParameters->PermitDoors( side::right, false );
|
pVehicle->MoverParameters->PermitDoors( side::right, false );
|
||||||
pVehicle->MoverParameters->PermitDoors( side::left, false );
|
pVehicle->MoverParameters->PermitDoors( side::left, false );
|
||||||
@@ -4687,11 +4694,11 @@ TController::UpdateSituation(double dt) {
|
|||||||
// TODO: test if we can use the distances calculation from obey_train
|
// TODO: test if we can use the distances calculation from obey_train
|
||||||
fMinProximityDist = std::min( 5 + iVehicles, 25 );
|
fMinProximityDist = std::min( 5 + iVehicles, 25 );
|
||||||
fMaxProximityDist = std::min( 10 + iVehicles, 50 );
|
fMaxProximityDist = std::min( 10 + iVehicles, 50 );
|
||||||
/*
|
// HACK: modern vehicles might brake slower at low speeds, increase safety margin as crude counter
|
||||||
if( IsHeavyCargoTrain ) {
|
if( mvControlling->EIMCtrlType > 0 ) {
|
||||||
fMaxProximityDist *= 1.5;
|
fMinProximityDist += 5.0;
|
||||||
|
fMaxProximityDist += 5.0;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
|
fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
|
||||||
// margines prędkości powodujący załączenie napędu
|
// margines prędkości powodujący załączenie napędu
|
||||||
// były problemy z jazdą np. 3km/h podczas ładowania wagonów
|
// były problemy z jazdą np. 3km/h podczas ładowania wagonów
|
||||||
@@ -5171,7 +5178,11 @@ TController::UpdateSituation(double dt) {
|
|||||||
20.0 ) ); // others
|
20.0 ) ); // others
|
||||||
if( vel > VelDesired + fVelPlus ) {
|
if( vel > VelDesired + fVelPlus ) {
|
||||||
// if going too fast force some prompt braking
|
// 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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5683,11 +5694,11 @@ TController::UpdateSituation(double dt) {
|
|||||||
|| ( VelNext > vel - 40.0 ) ) ?
|
|| ( VelNext > vel - 40.0 ) ) ?
|
||||||
fBrake_a0[ 0 ] * 0.8 :
|
fBrake_a0[ 0 ] * 0.8 :
|
||||||
-fAccThreshold )
|
-fAccThreshold )
|
||||||
/ braking_distance_multiplier( VelNext ) ) {
|
/ ( 1.2 * braking_distance_multiplier( VelNext ) ) ) {
|
||||||
AccDesired = std::max( -0.06, AccDesired );
|
AccDesired = std::max( -0.06, AccDesired );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
if( AccDesired < -0.1 ) {
|
||||||
// i orientuj się szybciej, jeśli hamujesz
|
// i orientuj się szybciej, jeśli hamujesz
|
||||||
ReactionTime = 0.25;
|
ReactionTime = 0.25;
|
||||||
}
|
}
|
||||||
@@ -5786,11 +5797,11 @@ TController::UpdateSituation(double dt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej
|
// yB: usunięte różne dziwne warunki, oddzielamy część zadającą od wykonawczej zwiekszanie predkosci
|
||||||
// zwiekszanie predkosci
|
|
||||||
// Ra 2F1H: jest konflikt histerezy pomiędzy nastawioną pozycją a uzyskiwanym
|
// Ra 2F1H: jest konflikt histerezy pomiędzy nastawioną pozycją a uzyskiwanym
|
||||||
// przyspieszeniem - utrzymanie pozycji powoduje przekroczenie przyspieszenia
|
// przyspieszeniem - utrzymanie pozycji powoduje przekroczenie przyspieszenia
|
||||||
if( ( AccDesired - AbsAccS > 0.01 ) ) {
|
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...
|
// jeśli przyspieszenie pojazdu jest mniejsze niż żądane oraz...
|
||||||
if( vel < (
|
if( vel < (
|
||||||
VelDesired == 1.0 ? // work around for trains getting stuck on tracks with speed limit = 1
|
VelDesired == 1.0 ? // work around for trains getting stuck on tracks with speed limit = 1
|
||||||
@@ -5882,7 +5893,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
|
// jak hamuje, to nie tykaj kranu za często
|
||||||
// yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2
|
// yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2
|
||||||
if( OrderCurrentGet() != Disconnect ) {
|
if( OrderCurrentGet() != Disconnect ) {
|
||||||
|
|||||||
2
Driver.h
2
Driver.h
@@ -407,9 +407,9 @@ private:
|
|||||||
// methods
|
// methods
|
||||||
public:
|
public:
|
||||||
std::string TrainName() const;
|
std::string TrainName() const;
|
||||||
|
Mtable::TTrainParameters const * TrainTimetable() const;
|
||||||
private:
|
private:
|
||||||
std::string Relation() const;
|
std::string Relation() const;
|
||||||
Mtable::TTrainParameters const * TrainTimetable() const;
|
|
||||||
int StationIndex() const;
|
int StationIndex() const;
|
||||||
int StationCount() const;
|
int StationCount() const;
|
||||||
bool IsStop() const;
|
bool IsStop() const;
|
||||||
|
|||||||
173
DynObj.cpp
173
DynObj.cpp
@@ -160,6 +160,39 @@ void TAnim::Parovoz(){
|
|||||||
// animowanie tłoka i rozrządu parowozu
|
// 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)
|
TDynamicObject * TDynamicObject::FirstFind(int &coupler_nr, int cf)
|
||||||
{ // szukanie skrajnego połączonego pojazdu w pociagu
|
{ // szukanie skrajnego połączonego pojazdu w pociagu
|
||||||
@@ -919,6 +952,8 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
|
|||||||
btEndSignalsTab2.Turn( true );
|
btEndSignalsTab2.Turn( true );
|
||||||
btnOn = true;
|
btnOn = true;
|
||||||
}
|
}
|
||||||
|
// destination signs
|
||||||
|
update_destinations();
|
||||||
// else btEndSignalsTab2.TurnOff();
|
// else btEndSignalsTab2.TurnOff();
|
||||||
// McZapkie-181002: krecenie wahaczem (korzysta z kata obrotu silnika)
|
// McZapkie-181002: krecenie wahaczem (korzysta z kata obrotu silnika)
|
||||||
if (iAnimType[ANIM_LEVERS])
|
if (iAnimType[ANIM_LEVERS])
|
||||||
@@ -1946,6 +1981,10 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
init_sections( mdLowPolyInt, nameprefix );
|
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
|
// 'external_load' is an optional special section in the main model, pointing to submodel of external load
|
||||||
if( mdModel ) {
|
if( mdModel ) {
|
||||||
init_sections( mdModel, "external_load" );
|
init_sections( mdModel, "external_load" );
|
||||||
@@ -2069,6 +2108,16 @@ TDynamicObject::init_sections( TModel3d const *Model, std::string const &Namepre
|
|||||||
return sectioncount;
|
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
|
void
|
||||||
TDynamicObject::create_controller( std::string const Type, bool const Trainset ) {
|
TDynamicObject::create_controller( std::string const Type, bool const Trainset ) {
|
||||||
|
|
||||||
@@ -2553,6 +2602,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.
|
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)
|
bool TDynamicObject::Update(double dt, double dt1)
|
||||||
{
|
{
|
||||||
if (dt1 == 0)
|
if (dt1 == 0)
|
||||||
@@ -4017,6 +4087,10 @@ void TDynamicObject::RenderSounds() {
|
|||||||
}
|
}
|
||||||
if( volume > 0.05 ) {
|
if( volume > 0.05 ) {
|
||||||
rscurve
|
rscurve
|
||||||
|
.pitch(
|
||||||
|
true == rscurve.is_combined() ?
|
||||||
|
MoverParameters->Vel * 0.01f :
|
||||||
|
rscurve.m_frequencyoffset + rscurve.m_frequencyfactor * 1.f )
|
||||||
.gain( 2.5 * volume )
|
.gain( 2.5 * volume )
|
||||||
.play( sound_flags::exclusive | sound_flags::looping );
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
}
|
}
|
||||||
@@ -4241,7 +4315,8 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// potentially set blank destination texture
|
// potentially set blank destination texture
|
||||||
DestinationSet( {}, {} );
|
DestinationSign.destination_off = DestinationFind( "nowhere" );
|
||||||
|
// DestinationSet( {}, {} );
|
||||||
|
|
||||||
if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) {
|
if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) {
|
||||||
// tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
|
// tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
|
||||||
@@ -5537,6 +5612,15 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
parser >> JointCabs;
|
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 != "" );
|
} while( token != "" );
|
||||||
|
|
||||||
} // internaldata:
|
} // internaldata:
|
||||||
@@ -6093,45 +6177,92 @@ int TDynamicObject::RouteWish(TTrack *tr)
|
|||||||
return Mechanik ? Mechanik->CrossRoute(tr) : 0; // wg AI albo prosto
|
return Mechanik ? Mechanik->CrossRoute(tr) : 0; // wg AI albo prosto
|
||||||
};
|
};
|
||||||
|
|
||||||
void TDynamicObject::DestinationSet(std::string to, std::string numer)
|
void TDynamicObject::DestinationSet(std::string to, std::string numer) {
|
||||||
{ // ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik
|
// ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik
|
||||||
// w zasadzie, to każdy wagon mógłby mieć inną stację docelową
|
// 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
|
// 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
|
// ale to jeszcze potrwa, zanim będzie możliwe, na razie można wpisać stację z
|
||||||
// rozkładu
|
// 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;
|
asDestination = to;
|
||||||
to = Bezogonkow(to); // do szukania pliku obcinamy ogonki
|
|
||||||
if( true == to.empty() ) {
|
if( std::abs( m_materialdata.multi_textures ) >= 4 ) { return; } // jak są 4 tekstury wymienne, to nie zmieniać rozkładem
|
||||||
to = "nowhere";
|
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
|
// destination textures are kept in the vehicle's directory so we point the current texture path there
|
||||||
auto const currenttexturepath { Global.asCurrentTexturePath };
|
auto const currenttexturepath { Global.asCurrentTexturePath };
|
||||||
Global.asCurrentTexturePath = asBaseDir;
|
Global.asCurrentTexturePath = asBaseDir;
|
||||||
// now see if we can find any version of the texture
|
// now see if we can find any version of the texture
|
||||||
std::vector<std::string> destinations = {
|
std::vector<std::string> const destinations {
|
||||||
numer + '@' + MoverParameters->TypeName,
|
Destination + '@' + MoverParameters->TypeName,
|
||||||
numer,
|
Destination };
|
||||||
to + '@' + MoverParameters->TypeName,
|
|
||||||
to,
|
auto destinationhandle { null_handle };
|
||||||
"nowhere" + '@' + MoverParameters->TypeName,
|
|
||||||
"nowhere" };
|
|
||||||
|
|
||||||
for( auto const &destination : destinations ) {
|
for( auto const &destination : destinations ) {
|
||||||
|
|
||||||
auto material = TextureTest( ToLower( destination ) );
|
auto material = TextureTest( ToLower( destination ) );
|
||||||
if( false == material.empty() ) {
|
if( false == material.empty() ) {
|
||||||
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Material( material );
|
destinationhandle = GfxRenderer.Fetch_Material( material );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// whether we got anything, restore previous texture path
|
// whether we got anything, restore previous texture path
|
||||||
Global.asCurrentTexturePath = currenttexturepath;
|
Global.asCurrentTexturePath = currenttexturepath;
|
||||||
};
|
|
||||||
|
return destinationhandle;
|
||||||
|
}
|
||||||
|
|
||||||
void TDynamicObject::OverheadTrack(float o)
|
void TDynamicObject::OverheadTrack(float o)
|
||||||
{ // ewentualne wymuszanie jazdy
|
{ // ewentualne wymuszanie jazdy
|
||||||
|
|||||||
17
DynObj.h
17
DynObj.h
@@ -200,6 +200,20 @@ public:
|
|||||||
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
|
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
|
||||||
std::array<TSubModel *, 3> LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs
|
std::array<TSubModel *, 3> 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)
|
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
|
||||||
|
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 fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
|
||||||
float LoadOffset { 0.f };
|
float LoadOffset { 0.f };
|
||||||
std::unordered_map<std::string, std::string> LoadModelOverrides; // potential overrides of default load visualization models
|
std::unordered_map<std::string, std::string> LoadModelOverrides; // potential overrides of default load visualization models
|
||||||
@@ -517,6 +531,7 @@ private:
|
|||||||
TTrack *Track, double fDist, std::string DriverType, double fVel, std::string TrainName,
|
TTrack *Track, double fDist, std::string DriverType, double fVel, std::string TrainName,
|
||||||
float Load, std::string LoadType, bool Reversed, std::string);
|
float Load, std::string LoadType, bool Reversed, std::string);
|
||||||
int init_sections( TModel3d const *Model, std::string const &Nameprefix );
|
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 create_controller( std::string const Type, bool const Trainset );
|
||||||
void AttachPrev(TDynamicObject *Object, int iType = 1);
|
void AttachPrev(TDynamicObject *Object, int iType = 1);
|
||||||
bool UpdateForce(double dt);
|
bool UpdateForce(double dt);
|
||||||
@@ -531,6 +546,7 @@ private:
|
|||||||
void update_load_visibility();
|
void update_load_visibility();
|
||||||
void update_load_offset();
|
void update_load_offset();
|
||||||
void shuffle_load_sections();
|
void shuffle_load_sections();
|
||||||
|
void update_destinations();
|
||||||
bool Update(double dt, double dt1);
|
bool Update(double dt, double dt1);
|
||||||
bool FastUpdate(double dt);
|
bool FastUpdate(double dt);
|
||||||
void Move(double fDistance);
|
void Move(double fDistance);
|
||||||
@@ -633,6 +649,7 @@ private:
|
|||||||
// zapytanie do AI, po którym segmencie skrzyżowania jechać
|
// zapytanie do AI, po którym segmencie skrzyżowania jechać
|
||||||
int RouteWish(TTrack *tr);
|
int RouteWish(TTrack *tr);
|
||||||
void DestinationSet(std::string to, std::string numer);
|
void DestinationSet(std::string to, std::string numer);
|
||||||
|
material_handle DestinationFind( std::string Destination );
|
||||||
void OverheadTrack(float o);
|
void OverheadTrack(float o);
|
||||||
|
|
||||||
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
|
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ struct global_settings {
|
|||||||
bool bLiveTraction{ true };
|
bool bLiveTraction{ true };
|
||||||
float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
|
float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
|
||||||
glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f };
|
glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f };
|
||||||
double fFogStart{ 1700 };
|
|
||||||
double fFogEnd{ 2000 };
|
double fFogEnd{ 2000 };
|
||||||
std::string Season{}; // season of the year, based on simulation date
|
std::string Season{}; // season of the year, based on simulation date
|
||||||
std::string Weather{ "cloudy:" }; // current weather
|
std::string Weather{ "cloudy:" }; // current weather
|
||||||
|
|||||||
@@ -1354,6 +1354,7 @@ public:
|
|||||||
std::string StLinSwitchType;
|
std::string StLinSwitchType;
|
||||||
|
|
||||||
bool Heating = false; //ogrzewanie 'Winger 020304
|
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
|
int DoubleTr = 1; //trakcja ukrotniona - przedni pojazd 'Winger 160304
|
||||||
|
|
||||||
bool PhysicActivation = true;
|
bool PhysicActivation = true;
|
||||||
@@ -1500,6 +1501,7 @@ public:
|
|||||||
|
|
||||||
/*-funkcje typowe dla lokomotywy elektrycznej*/
|
/*-funkcje typowe dla lokomotywy elektrycznej*/
|
||||||
void ConverterCheck( double const Timestep ); // przetwornica
|
void ConverterCheck( double const Timestep ); // przetwornica
|
||||||
|
void HeatingCheck( double const Timestep );
|
||||||
void WaterPumpCheck( double const Timestep );
|
void WaterPumpCheck( double const Timestep );
|
||||||
void WaterHeaterCheck( double const Timestep );
|
void WaterHeaterCheck( double const Timestep );
|
||||||
void FuelPumpCheck( double const Timestep );
|
void FuelPumpCheck( double const Timestep );
|
||||||
|
|||||||
@@ -1075,11 +1075,13 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
|
|||||||
|
|
||||||
for( int side = 0; side < 2; ++side ) {
|
for( int side = 0; side < 2; ++side ) {
|
||||||
// przekazywanie napiec
|
// 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 )
|
if( liveconnection ) {
|
||||||
|| ( ( Heating )
|
|
||||||
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
|
|
||||||
auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ];
|
auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ];
|
||||||
Couplers[ oppositeside ].power_high.voltage =
|
Couplers[ oppositeside ].power_high.voltage =
|
||||||
std::max(
|
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
|
Couplers[ side ].power_high.local = false; // power, if any, will be from external source
|
||||||
|
|
||||||
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|
||||||
|| ( ( Heating )
|
|| ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
|
||||||
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
|
&& ( Couplers[ side ].Connected->Heating ) ) ) {
|
||||||
auto const &connectedcoupler =
|
auto const &connectedcoupler =
|
||||||
Couplers[ side ].Connected->Couplers[
|
Couplers[ side ].Connected->Couplers[
|
||||||
( Couplers[ side ].ConnectedNr == end::front ?
|
( 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
|
Couplers[ side ].power_high.local = true; // power is coming from local pantographs
|
||||||
|
|
||||||
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|
||||||
|| ( ( Heating )
|
|| ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
|
||||||
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
|
&& ( Couplers[ side ].Connected->Heating ) ) ) {
|
||||||
auto const &connectedcoupler =
|
auto const &connectedcoupler =
|
||||||
Couplers[ side ].Connected->Couplers[
|
Couplers[ side ].Connected->Couplers[
|
||||||
( Couplers[ side ].ConnectedNr == end::front ?
|
( 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
|
// 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
|
UpdatePantVolume( Deltatime ); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów
|
||||||
}
|
}
|
||||||
|
// heating
|
||||||
|
HeatingCheck( Deltatime );
|
||||||
|
|
||||||
UpdateBrakePressure(Deltatime);
|
UpdateBrakePressure(Deltatime);
|
||||||
UpdatePipePressure(Deltatime);
|
UpdatePipePressure(Deltatime);
|
||||||
@@ -1462,7 +1466,8 @@ void TMoverParameters::ConverterCheck( double const Timestep ) {
|
|||||||
if( ( ConverterAllow )
|
if( ( ConverterAllow )
|
||||||
&& ( ConverterAllowLocal )
|
&& ( ConverterAllowLocal )
|
||||||
&& ( false == PantPressLockActive )
|
&& ( false == PantPressLockActive )
|
||||||
&& ( Mains ) ) {
|
&& ( ( Mains )
|
||||||
|
|| ( GetTrainsetVoltage() > 0 ) ) ) {
|
||||||
// delay timer can be optionally configured, and is set anew whenever converter goes off
|
// delay timer can be optionally configured, and is set anew whenever converter goes off
|
||||||
if( ConverterStartDelayTimer <= 0.0 ) {
|
if( ConverterStartDelayTimer <= 0.0 ) {
|
||||||
ConverterFlag = true;
|
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
|
// water pump status check
|
||||||
void TMoverParameters::WaterPumpCheck( double const Timestep ) {
|
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
|
// NOTE: breaker override with start type is sm42 specific hack, replace with ability to define the presence of the breaker
|
||||||
@@ -7055,9 +7071,14 @@ TMoverParameters::update_doors( double const Deltatime ) {
|
|||||||
door.local_close = door.local_close && ( false == door.is_closed );
|
door.local_close = door.local_close && ( false == door.is_closed );
|
||||||
door.remote_close = door.remote_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 {
|
auto const openrequest {
|
||||||
( localopencontrol && door.local_open )
|
( localopencontrol && door.local_open )
|
||||||
|| ( remoteopencontrol && door.remote_open ) };
|
|| ( remoteopencontrol && door.remote_open )
|
||||||
|
|| ( autoopenrequest && ( false == door.is_open ) ) };
|
||||||
|
|
||||||
auto const autocloserequest {
|
auto const autocloserequest {
|
||||||
( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) )
|
( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) )
|
||||||
@@ -7279,14 +7300,14 @@ double TMoverParameters::GetTrainsetVoltage(void)
|
|||||||
return std::max(
|
return std::max(
|
||||||
( ( ( Couplers[end::front].Connected )
|
( ( ( Couplers[end::front].Connected )
|
||||||
&& ( ( Couplers[ end::front ].CouplingFlag & ctrain_power )
|
&& ( ( 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 :
|
Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage :
|
||||||
0.0 ),
|
0.0 ),
|
||||||
( ( ( Couplers[end::rear].Connected )
|
( ( ( Couplers[end::rear].Connected )
|
||||||
&& ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power )
|
&& ( ( 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 :
|
Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage :
|
||||||
0.0 ) );
|
0.0 ) );
|
||||||
}
|
}
|
||||||
@@ -8344,12 +8365,6 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
|
|||||||
lookup != doorcontrols.end() ?
|
lookup != doorcontrols.end() ?
|
||||||
lookup->second :
|
lookup->second :
|
||||||
control_t::passenger;
|
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
|
// automatic closing conditions
|
||||||
extract_value( Doors.auto_duration, "DoorStayOpen", line, "" );
|
extract_value( Doors.auto_duration, "DoorStayOpen", line, "" );
|
||||||
|
|||||||
21
Model3d.cpp
21
Model3d.cpp
@@ -789,6 +789,27 @@ int TSubModel::count_children() {
|
|||||||
1 + Child->count_siblings() );
|
1 + Child->count_siblings() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// locates submodel mapped with replacable -4
|
||||||
|
std::tuple<TSubModel *, bool>
|
||||||
|
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<TSubModel *>( lookup ) != nullptr ) { return lookup; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Child != nullptr ) {
|
||||||
|
auto lookup { Child->find_replacable4() };
|
||||||
|
if( std::get<TSubModel *>( lookup ) != nullptr ) { return lookup; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_tuple( nullptr, false );
|
||||||
|
}
|
||||||
|
|
||||||
int TSubModel::FlagsCheck()
|
int TSubModel::FlagsCheck()
|
||||||
{ // analiza koniecznych zmian pomiędzy submodelami
|
{ // analiza koniecznych zmian pomiędzy submodelami
|
||||||
// samo pomijanie glBindTexture() nie poprawi wydajności
|
// samo pomijanie glBindTexture() nie poprawi wydajności
|
||||||
|
|||||||
@@ -166,6 +166,8 @@ public:
|
|||||||
TSubModel * ChildGet() { return Child; };
|
TSubModel * ChildGet() { return Child; };
|
||||||
int count_siblings();
|
int count_siblings();
|
||||||
int count_children();
|
int count_children();
|
||||||
|
// locates submodel mapped with replacable -4
|
||||||
|
std::tuple<TSubModel *, bool> find_replacable4();
|
||||||
int TriangleAdd(TModel3d *m, material_handle tex, int tri);
|
int TriangleAdd(TModel3d *m, material_handle tex, int tri);
|
||||||
void SetRotate(float3 vNewRotateAxis, float fNewAngle);
|
void SetRotate(float3 vNewRotateAxis, float fNewAngle);
|
||||||
void SetRotateXYZ( Math3D::vector3 vNewAngles);
|
void SetRotateXYZ( Math3D::vector3 vNewAngles);
|
||||||
|
|||||||
@@ -10,9 +10,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "PyInt.h"
|
#include "PyInt.h"
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "dictionary.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "renderer.h"
|
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
|
|
||||||
void render_task::run() {
|
void render_task::run() {
|
||||||
|
|||||||
18
PyInt.h
18
PyInt.h
@@ -23,24 +23,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#define PyGetBool(param) param ? Py_True : Py_False
|
#define PyGetBool(param) param ? Py_True : Py_False
|
||||||
#define PyGetString(param) PyString_FromString(param)
|
#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 <typename Type_>
|
|
||||||
using keyvaluepair_sequence = std::vector<std::pair<std::string, Type_>>;
|
|
||||||
// members
|
|
||||||
keyvaluepair_sequence<double> floats;
|
|
||||||
keyvaluepair_sequence<int> integers;
|
|
||||||
keyvaluepair_sequence<bool> bools;
|
|
||||||
keyvaluepair_sequence<std::string> 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
|
// TODO: extract common base and inherit specialization from it
|
||||||
class render_task {
|
class render_task {
|
||||||
|
|
||||||
|
|||||||
16
Texture.cpp
16
Texture.cpp
@@ -20,11 +20,13 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "GL/glew.h"
|
#include "GL/glew.h"
|
||||||
|
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "utilities.h"
|
#include "dictionary.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
|
#include "utilities.h"
|
||||||
#include "sn_utils.h"
|
#include "sn_utils.h"
|
||||||
|
|
||||||
|
|
||||||
#define EU07_DEFERRED_TEXTURE_UPLOAD
|
#define EU07_DEFERRED_TEXTURE_UPLOAD
|
||||||
|
|
||||||
texture_manager::texture_manager() {
|
texture_manager::texture_manager() {
|
||||||
@@ -96,17 +98,9 @@ void
|
|||||||
opengl_texture::make_request() {
|
opengl_texture::make_request() {
|
||||||
|
|
||||||
auto const components { Split( name, '?' ) };
|
auto const components { Split( name, '?' ) };
|
||||||
auto const query { Split( components.back(), '&' ) };
|
|
||||||
|
|
||||||
auto *dictionary { new dictionary_source };
|
auto *dictionary { new dictionary_source( components.back() ) };
|
||||||
if( dictionary != nullptr ) {
|
if( dictionary == nullptr ) { return; }
|
||||||
for( auto const &querypair : query ) {
|
|
||||||
auto const valuepos { querypair.find( '=' ) };
|
|
||||||
dictionary->insert(
|
|
||||||
ToLower( querypair.substr( 0, valuepos ) ),
|
|
||||||
querypair.substr( valuepos + 1 ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Application.request( { ToLower( components.front() ), dictionary, id } );
|
Application.request( { ToLower( components.front() ), dictionary, id } );
|
||||||
}
|
}
|
||||||
|
|||||||
118
Train.cpp
118
Train.cpp
@@ -30,6 +30,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
#include "dictionary.h"
|
||||||
/*
|
/*
|
||||||
namespace input {
|
namespace input {
|
||||||
|
|
||||||
@@ -543,31 +544,8 @@ dictionary_source *TTrain::GetTrainState() {
|
|||||||
dict->insert( "velnext", driver->VelNext );
|
dict->insert( "velnext", driver->VelNext );
|
||||||
dict->insert( "actualproximitydist", driver->ActualProximityDist );
|
dict->insert( "actualproximitydist", driver->ActualProximityDist );
|
||||||
// train data
|
// train data
|
||||||
auto const *timetable{ driver->TrainTimetable() };
|
driver->TrainTimetable()->serialize( dict );
|
||||||
|
dict->insert( "train_stationstart", driver->iStationStart );
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dict->insert( "train_atpassengerstop", driver->IsAtPassengerStop );
|
dict->insert( "train_atpassengerstop", driver->IsAtPassengerStop );
|
||||||
// world state data
|
// world state data
|
||||||
dict->insert( "scenario", Global.SceneryFile );
|
dict->insert( "scenario", Global.SceneryFile );
|
||||||
@@ -4153,7 +4131,7 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
|
|||||||
|
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
// 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
|
// turn on
|
||||||
OnCommand_heatingenable( Train, Command );
|
OnCommand_heatingenable( Train, Command );
|
||||||
}
|
}
|
||||||
@@ -4167,24 +4145,20 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
|
|||||||
void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) {
|
void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command ) {
|
||||||
|
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
|
|
||||||
|
Train->mvControlled->HeatingAllow = true;
|
||||||
// visual feedback
|
// visual feedback
|
||||||
Train->ggTrainHeatingButton.UpdateValue( 1.0, Train->dsbSwitch );
|
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 ) {
|
void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Command ) {
|
||||||
|
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
|
|
||||||
|
Train->mvControlled->HeatingAllow = false;
|
||||||
// visual feedback
|
// visual feedback
|
||||||
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
|
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||||
|
|
||||||
if( false == Train->mvControlled->Heating ) { return; } // already disabled
|
|
||||||
|
|
||||||
Train->mvControlled->Heating = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4315,37 +4289,73 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman
|
|||||||
|
|
||||||
void TTrain::OnCommand_doorpermitleft( TTrain *Train, command_data const &Command ) {
|
void TTrain::OnCommand_doorpermitleft( TTrain *Train, command_data const &Command ) {
|
||||||
|
|
||||||
|
if( Command.action == GLFW_REPEAT ) { return; }
|
||||||
|
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
|
|
||||||
Train->mvOccupied->PermitDoors(
|
auto const side { (
|
||||||
( Train->mvOccupied->ActiveCab == 1 ?
|
Train->mvOccupied->ActiveCab == 1 ?
|
||||||
side::left :
|
side::left :
|
||||||
side::right ) );
|
side::right ) };
|
||||||
|
|
||||||
// visual feedback
|
if( Train->ggDoorLeftPermitButton.type() == TGaugeType::push ) {
|
||||||
Train->ggDoorLeftPermitButton.UpdateValue( 1.0, Train->dsbSwitch );
|
// 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 ) {
|
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 ) {
|
void TTrain::OnCommand_doorpermitright( TTrain *Train, command_data const &Command ) {
|
||||||
|
|
||||||
|
if( Command.action == GLFW_REPEAT ) { return; }
|
||||||
|
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
|
|
||||||
Train->mvOccupied->PermitDoors(
|
auto const side { (
|
||||||
( Train->mvOccupied->ActiveCab == 1 ?
|
Train->mvOccupied->ActiveCab == 1 ?
|
||||||
side::right :
|
side::right :
|
||||||
side::left ) );
|
side::left ) };
|
||||||
|
|
||||||
// visual feedback
|
if( Train->ggDoorRightPermitButton.type() == TGaugeType::push ) {
|
||||||
Train->ggDoorRightPermitButton.UpdateValue( 1.0, Train->dsbSwitch );
|
// 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 ) {
|
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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6027,7 +6037,6 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
//---------
|
//---------
|
||||||
// hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy
|
// hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy
|
||||||
if( ( mvControlled->Heating == true )
|
if( ( mvControlled->Heating == true )
|
||||||
&& ( mvControlled->Mains == true )
|
|
||||||
&& ( mvControlled->ConvOvldFlag == false ) )
|
&& ( mvControlled->ConvOvldFlag == false ) )
|
||||||
btLampkaOgrzewanieSkladu.Turn( true );
|
btLampkaOgrzewanieSkladu.Turn( true );
|
||||||
else
|
else
|
||||||
@@ -7612,7 +7621,12 @@ void TTrain::set_cab_controls( int const Cab ) {
|
|||||||
1.f :
|
1.f :
|
||||||
0.f ) );
|
0.f ) );
|
||||||
// doors
|
// 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 );
|
ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset );
|
||||||
ggDoorLeftButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].is_closed ? 0.f : 1.f );
|
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 );
|
ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].is_closed ? 0.f : 1.f );
|
||||||
@@ -7841,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
|
// TODO: move viable dedicated lights to the automatic light array
|
||||||
std::unordered_map<std::string, bool *> const autolights = {
|
std::unordered_map<std::string, bool *> const autolights = {
|
||||||
{ "i-doorpermit_left:", &mvOccupied->Doors.instances[side::left].open_permit },
|
{ "i-doorpermit_left:", &mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit },
|
||||||
{ "i-doorpermit_right:", &mvOccupied->Doors.instances[ 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 }
|
{ "i-doorstep:", &mvOccupied->Doors.step_enabled }
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
|
|||||||
12
audio.cpp
12
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
|
// TBD, TODO: customized vorbis_decode to avoid unnecessary shuffling around of the decoded data
|
||||||
int channels, samplerate;
|
int channels, samplerate;
|
||||||
std::int16_t *filedata { nullptr };
|
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 ) {
|
if( samplecount > 0 ) {
|
||||||
rate = samplerate;
|
rate = samplerate;
|
||||||
data.resize( samplecount );
|
data.resize( samplecount * channels );
|
||||||
std::copy( filedata, filedata + samplecount, std::begin( data ) );
|
std::copy( filedata, filedata + data.size(), std::begin( data ) );
|
||||||
free( filedata );
|
free( filedata );
|
||||||
if( channels > 1 ) {
|
if( channels > 1 ) {
|
||||||
narrow_to_mono( channels );
|
narrow_to_mono( channels );
|
||||||
data.resize( samplecount / channels );
|
data.resize( samplecount );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -109,7 +109,7 @@ void
|
|||||||
openal_buffer::narrow_to_mono( std::uint16_t const Channelcount ) {
|
openal_buffer::narrow_to_mono( std::uint16_t const Channelcount ) {
|
||||||
|
|
||||||
std::size_t monodataindex { 0 };
|
std::size_t monodataindex { 0 };
|
||||||
std::int32_t accumulator { 0 };
|
std::int64_t accumulator { 0 };
|
||||||
auto channelcount { Channelcount };
|
auto channelcount { Channelcount };
|
||||||
|
|
||||||
for( auto const channeldata : data ) {
|
for( auto const channeldata : data ) {
|
||||||
@@ -117,7 +117,7 @@ openal_buffer::narrow_to_mono( std::uint16_t const Channelcount ) {
|
|||||||
accumulator += channeldata;
|
accumulator += channeldata;
|
||||||
if( --channelcount == 0 ) {
|
if( --channelcount == 0 ) {
|
||||||
|
|
||||||
data[ monodataindex++ ] = accumulator / Channelcount;
|
data[ monodataindex++ ] = static_cast<std::int16_t>( accumulator / Channelcount );
|
||||||
accumulator = 0;
|
accumulator = 0;
|
||||||
channelcount = Channelcount;
|
channelcount = Channelcount;
|
||||||
}
|
}
|
||||||
|
|||||||
55
dictionary.cpp
Normal file
55
dictionary.cpp
Normal file
@@ -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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
dictionary.h
Normal file
31
dictionary.h
Normal file
@@ -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 <typename Type_>
|
||||||
|
using keyvaluepair_sequence = std::vector<std::pair<std::string, Type_>>;
|
||||||
|
// members
|
||||||
|
keyvaluepair_sequence<double> floats;
|
||||||
|
keyvaluepair_sequence<int> integers;
|
||||||
|
keyvaluepair_sequence<bool> bools;
|
||||||
|
keyvaluepair_sequence<std::string> 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 ); }
|
||||||
|
};
|
||||||
@@ -21,7 +21,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "uilayer.h"
|
#include "uilayer.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
|
|
||||||
auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.65 };
|
auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.6 };
|
||||||
|
|
||||||
void
|
void
|
||||||
mouse_slider::bind( user_command const &Command ) {
|
mouse_slider::bind( user_command const &Command ) {
|
||||||
|
|||||||
@@ -339,6 +339,9 @@
|
|||||||
<ClCompile Include="ref\stb\stb_vorbis.c">
|
<ClCompile Include="ref\stb\stb_vorbis.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="dictionary.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Globals.h">
|
<ClInclude Include="Globals.h">
|
||||||
@@ -623,6 +626,9 @@
|
|||||||
<ClInclude Include="openglcolor.h">
|
<ClInclude Include="openglcolor.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="dictionary.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="maszyna.rc">
|
<ResourceCompile Include="maszyna.rc">
|
||||||
|
|||||||
29
mtable.cpp
29
mtable.cpp
@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "simulationtime.h"
|
#include "simulationtime.h"
|
||||||
|
#include "dictionary.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
double TTrainParameters::CheckTrainLatency()
|
double TTrainParameters::CheckTrainLatency()
|
||||||
@@ -523,3 +524,31 @@ bool TTrainParameters::DirectionChange()
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
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_stationfrom", Relation1 );
|
||||||
|
Output->insert( "train_stationto", Relation2 );
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
1
mtable.h
1
mtable.h
@@ -83,6 +83,7 @@ class TTrainParameters
|
|||||||
bool LoadTTfile(std::string scnpath, int iPlus, double vmax);
|
bool LoadTTfile(std::string scnpath, int iPlus, double vmax);
|
||||||
bool DirectionChange();
|
bool DirectionChange();
|
||||||
void StationIndexInc();
|
void StationIndexInc();
|
||||||
|
void serialize( dictionary_source *Output ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TMTableTime
|
class TMTableTime
|
||||||
|
|||||||
@@ -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/
|
// http://nothings.org/stb_vorbis/
|
||||||
//
|
//
|
||||||
// Original version written by Sean Barrett in 2007.
|
// Original version written by Sean Barrett in 2007.
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
// Timur Gagiev
|
// Timur Gagiev
|
||||||
//
|
//
|
||||||
// Partial history:
|
// 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.14 - 2018-02-11 - delete bogus dealloca usage
|
||||||
// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
|
// 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
|
// 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
|
// 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.
|
// 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
|
// 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
|
// 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
|
// owns the _entire_ rest of the file after the start point. Use the next
|
||||||
// function, stb_vorbis_open_file_section(), to limit it.
|
// function, stb_vorbis_open_file_section(), to limit it.
|
||||||
@@ -374,7 +376,8 @@ enum STBVorbisError
|
|||||||
VORBIS_invalid_first_page,
|
VORBIS_invalid_first_page,
|
||||||
VORBIS_bad_packet_type,
|
VORBIS_bad_packet_type,
|
||||||
VORBIS_cant_find_last_page,
|
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);
|
assert(z >= 0 && z < 32);
|
||||||
available[z] = 0;
|
available[z] = 0;
|
||||||
add_entry(c, bit_reverse(res), i, m++, len[i], values);
|
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]) {
|
if (z != len[i]) {
|
||||||
assert(len[i] >= 0 && len[i] < 32);
|
assert(len[i] >= 0 && len[i] < 32);
|
||||||
for (y=len[i]; y > z; --y) {
|
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.
|
// once I combined the passes.
|
||||||
|
|
||||||
// so there's a missing 'times 2' here (for adding X to itself).
|
// 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.
|
// 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);
|
if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page);
|
||||||
// check for expected packet length
|
// check for expected packet length
|
||||||
if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page);
|
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
|
// read packet
|
||||||
// check packet header
|
// check packet header
|
||||||
if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page);
|
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;
|
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
|
// start of a packet
|
||||||
static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset)
|
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)
|
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)
|
if (f)
|
||||||
return stb_vorbis_open_file(f, TRUE, error, alloc);
|
return stb_vorbis_open_file(f, TRUE, error, alloc);
|
||||||
if (error) *error = VORBIS_file_open_failure;
|
if (error) *error = VORBIS_file_open_failure;
|
||||||
|
|||||||
59
renderer.cpp
59
renderer.cpp
@@ -32,17 +32,18 @@ int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental
|
|||||||
void
|
void
|
||||||
opengl_light::apply_intensity( float const Factor ) {
|
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_AMBIENT, glm::value_ptr( ambient ) );
|
||||||
::glLightfv( id, GL_DIFFUSE, glm::value_ptr( diffuse ) );
|
::glLightfv( id, GL_DIFFUSE, glm::value_ptr( diffuse ) );
|
||||||
::glLightfv( id, GL_SPECULAR, glm::value_ptr( specular ) );
|
::glLightfv( id, GL_SPECULAR, glm::value_ptr( specular ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
auto const factor{ clamp( Factor, 0.05f, 1.f ) };
|
||||||
// temporary light scaling mechanics (ultimately this work will be left to the shaders
|
// 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 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 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 scaledspecular( specular.r * factor, specular.g * factor, specular.b * factor, specular.a );
|
||||||
glLightfv( id, GL_AMBIENT, glm::value_ptr( scaledambient ) );
|
glLightfv( id, GL_AMBIENT, glm::value_ptr( scaledambient ) );
|
||||||
glLightfv( id, GL_DIFFUSE, glm::value_ptr( scaleddiffuse ) );
|
glLightfv( id, GL_DIFFUSE, glm::value_ptr( scaleddiffuse ) );
|
||||||
glLightfv( id, GL_SPECULAR, glm::value_ptr( scaledspecular ) );
|
glLightfv( id, GL_SPECULAR, glm::value_ptr( scaledspecular ) );
|
||||||
@@ -2170,34 +2171,36 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
|||||||
m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being
|
m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being
|
||||||
// render
|
// render
|
||||||
if( Dynamic->mdLowPolyInt ) {
|
if( Dynamic->mdLowPolyInt ) {
|
||||||
// low poly interior
|
// HACK: reduce light level for vehicle interior if there's strong global lighting source
|
||||||
/*
|
auto const luminance { static_cast<float>( 0.5 * ( std::max( 0.3, Global.fLuminance - Global.Overcast ) ) ) };
|
||||||
if( ( true == FreeFlyModeFlag )
|
m_sunlight.apply_intensity(
|
||||||
|| ( ( Dynamic->mdKabina == nullptr ) || ( false == Dynamic->bDisplayCab ) ) ) {
|
clamp( (
|
||||||
*/
|
Dynamic->fShade > 0.f ?
|
||||||
/*
|
Dynamic->fShade :
|
||||||
// enable cab light if needed
|
1.f )
|
||||||
if( Dynamic->InteriorLightLevel > 0.0f ) {
|
- luminance,
|
||||||
|
0.f, 1.f ) );
|
||||||
|
|
||||||
// crude way to light the cabin, until we have something more complete in place
|
// low poly interior
|
||||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) );
|
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 ) {
|
||||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
// renderowanie nieprzezroczystego ładunku
|
||||||
/*
|
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||||
if( Dynamic->InteriorLightLevel > 0.0f ) {
|
|
||||||
// reset the overall ambient
|
|
||||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( m_baseambient ) );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
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 );
|
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
|
// post-render cleanup
|
||||||
m_renderspecular = false;
|
m_renderspecular = false;
|
||||||
if( Dynamic->fShade > 0.0f ) {
|
if( Dynamic->fShade > 0.0f ) {
|
||||||
|
|||||||
@@ -164,14 +164,22 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch
|
|||||||
// atmosphere color; legacy parameter, no longer used
|
// atmosphere color; legacy parameter, no longer used
|
||||||
Input.getTokens( 3 );
|
Input.getTokens( 3 );
|
||||||
// fog range
|
// fog range
|
||||||
Input.getTokens( 2 );
|
{
|
||||||
Input
|
double fograngestart, fograngeend;
|
||||||
>> Global.fFogStart
|
Input.getTokens( 2 );
|
||||||
>> Global.fFogEnd;
|
Input
|
||||||
|
>> fograngestart
|
||||||
|
>> fograngeend;
|
||||||
|
|
||||||
if( Global.fFogEnd > 0.0 ) {
|
if( Global.fFogEnd != 0.0 ) {
|
||||||
// fog colour; optional legacy parameter, no longer used
|
// fog colour; optional legacy parameter, no longer used
|
||||||
Input.getTokens( 3 );
|
Input.getTokens( 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Global.fFogEnd =
|
||||||
|
clamp(
|
||||||
|
Random( fograngestart, fograngeend ),
|
||||||
|
100.0, 2000.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string token { Input.getToken<std::string>() };
|
std::string token { Input.getToken<std::string>() };
|
||||||
|
|||||||
Reference in New Issue
Block a user