16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-23 00:29:19 +02:00

combined rain sound support, soundproofing customization support, event diagnostics enhancement, power grid diagnostics enhancement, windowed full screen mode, ai coupling logic tweaks, minor bug fixes

This commit is contained in:
tmj-fstate
2020-10-01 03:01:17 +02:00
parent 4da87e98d9
commit 730ba72516
20 changed files with 234 additions and 186 deletions

View File

@@ -2021,9 +2021,7 @@ void TController::Activation()
if (initiallocalbrakelevel > 0.0) // hamowanie tylko jeśli był wcześniej zahamowany (bo możliwe, że jedzie!)
mvOccupied->LocalBrakePosA = initiallocalbrakelevel; // zahamuj jak wcześniej
*/
if( initialspringbrakestate ) {
mvOccupied->SpringBrakeActivate( initialspringbrakestate );
}
mvOccupied->SpringBrakeActivate( initialspringbrakestate );
CheckVehicles(); // sprawdzenie składu, AI zapali światła
TableClear(); // resetowanie tabelki skanowania torów
}
@@ -2292,11 +2290,15 @@ bool TController::CheckVehicles(TOrders user)
if (p->Mechanik != this) // ale chodzi o inny pojazd, niż aktualnie sprawdzający
if( p->Mechanik->iDrivigFlags & movePrimary ) {
// a tamten ma priorytet
// TODO: take into account drivers' operating modes, one or more of them might be on banking duty
if( ( iDrivigFlags & movePrimary )
&& ( mvOccupied->DirAbsolute )
&& ( mvOccupied->BrakeCtrlPos >= -1 ) ) {
// jeśli rządzi i ma kierunek
p->Mechanik->primary( false ); // dezaktywuje tamtego
p->Mechanik->ZeroLocalBrake();
p->MoverParameters->BrakeLevelSet( p->MoverParameters->Handle->GetPos( bh_NP ) ); // odcięcie na zaworze maszynisty
p->Mechanik->BrakeLevelSet( p->MoverParameters->BrakeCtrlPos ); //ustawienie zmiennej GBH
}
else {
main = false; // nici z rządzenia
@@ -2445,6 +2447,14 @@ bool TController::CheckVehicles(TOrders user)
|| ( mvControlling->EngineType == TEngineType::DieselEngine ) ) ? ( Global.AirTemperature < 10 ) :
true );
}
if( ( true == TestFlag( iDrivigFlags, moveConnect ) )
&& ( true == TestFlag( OrderCurrentGet(), Connect ) ) ) {
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
JumpToNextOrder(); // wykonanie następnej komendy
}
}
else { // gdy człowiek i gdy nastąpiło połącznie albo rozłączenie
// Ra 2014-02: lepiej tu niż w pętli obsługującej komendy, bo tam się zmieni informacja o składzie
@@ -2808,6 +2818,9 @@ bool TController::PrepareEngine()
if( lookup != brakepositions.end() ) {
BrakeLevelSet( lookup->second ); // GBH
}
// sync spring brake state across consist
mvOccupied->SpringBrakeActivate( mvOccupied->SpringBrake.Activate );
OK = ( false == IsAnyConverterOverloadRelayOpen )
&& ( VelforDriver == -1 );
}
@@ -3479,17 +3492,28 @@ bool TController::IncSpeed()
}
break;
case TEngineType::ElectricInductionMotor:
if (!IsAnyMotorOverloadRelayOpen)
if (Ready || (iDrivigFlags & movePress) || (mvOccupied->ShuntMode)) //{(BrakePress<=0.01*MaxBrakePress)}
if( !IsAnyMotorOverloadRelayOpen ) {
if( Ready || ( iDrivigFlags & movePress ) || ( mvOccupied->ShuntMode ) ) //{(BrakePress<=0.01*MaxBrakePress)}
{
OK = IncSpeedEIM();
// cruise control
auto const SpeedCntrlVel { (
( ActualProximityDist > std::max( 50.0, fMaxProximityDist ) ) ?
VelDesired :
min_speed( VelDesired, VelNext ) ) };
SpeedCntrl(SpeedCntrlVel);
if( ( mvControlling->SpeedCtrl ) && ( mvControlling->Mains ) ) {
// cruise control
auto const couplinginprogress{ ( true == TestFlag( iDrivigFlags, moveConnect ) ) && ( true == TestFlag( OrderCurrentGet(), Connect ) ) };
auto const SpeedCntrlVel{ (
( ActualProximityDist > std::max( 50.0, fMaxProximityDist ) ) || ( couplinginprogress ) ?
VelDesired :
min_speed( VelDesired, VelNext ) ) };
if( ( SpeedCntrlVel >= mvControlling->SpeedCtrlUnit.MinVelocity )
&& ( SpeedCntrlVel - mvControlling->SpeedCtrlUnit.MinVelocity == quantize( SpeedCntrlVel - mvControlling->SpeedCtrlUnit.MinVelocity, mvControlling->SpeedCtrlUnit.VelocityStep ) ) ) {
SpeedCntrl( SpeedCntrlVel );
}
else if( SpeedCntrlVel > 0.1 ) {
SpeedCntrl( 0.0 );
mvControlling->DecScndCtrl( 2 );
}
}
}
}
break;
case TEngineType::WheelsDriven:
if (!mvControlling->CabActive)
@@ -3505,16 +3529,19 @@ bool TController::IncSpeed()
// mvControlling->ShuntMode=(OrderList[OrderPos]&Shunt)||(fMass>224000.0);
}
if ((mvControlling->SpeedCtrl)&&(mvControlling->Mains)) {// cruise control
auto const SpeedCntrlVel{ (
(ActualProximityDist > std::max(50.0, fMaxProximityDist)) ?
VelDesired :
min_speed(VelDesired, VelNext)) };
if (SpeedCntrlVel >= mvControlling->SpeedCtrlUnit.MinVelocity) {
SpeedCntrl(SpeedCntrlVel);
}
else if (SpeedCntrlVel > 0.1) {
SpeedCntrl(0.0);
}
auto const couplinginprogress { ( true == TestFlag( iDrivigFlags, moveConnect ) ) && ( true == TestFlag( OrderCurrentGet(), Connect ) ) };
auto const SpeedCntrlVel { (
( ActualProximityDist > std::max( 50.0, fMaxProximityDist ) ) || ( couplinginprogress ) ?
VelDesired :
min_speed( VelDesired, VelNext ) ) };
if( ( SpeedCntrlVel >= mvControlling->SpeedCtrlUnit.MinVelocity )
&& ( SpeedCntrlVel - mvControlling->SpeedCtrlUnit.MinVelocity == quantize( SpeedCntrlVel - mvControlling->SpeedCtrlUnit.MinVelocity, mvControlling->SpeedCtrlUnit.VelocityStep ) ) ) {
SpeedCntrl(SpeedCntrlVel);
}
else if (SpeedCntrlVel > 0.1) {
SpeedCntrl(0.0);
mvControlling->DecScndCtrl( 2 );
}
}
if (mvControlling->EIMCtrlType > 0) {
if (true == Ready)
@@ -3538,6 +3565,7 @@ bool TController::IncSpeed()
}
if( false == mvControlling->Mains ) {
SpeedCntrl(0.0);
mvControlling->DecScndCtrl( 2 );
mvOccupied->MainSwitch( true );
mvOccupied->ConverterSwitch( true );
mvOccupied->CompressorSwitch( true );
@@ -5428,11 +5456,7 @@ TController::UpdateSituation(double dt) {
iCoupler );
if( vehicleparameters->Couplers[ end ].CouplingFlag == iCoupler ) {
// jeżeli został podłączony
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
CheckVehicles( Connect ); // sprawdzić światła nowego składu
JumpToNextOrder(); // wykonanie następnej komendy
}
}
}

View File

@@ -6284,6 +6284,17 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
>> HuntingShake.fadein_end;
}
else if( token == "soundproofing:" ) {
for( auto &soundproofingtable : m_soundproofing ) {
for( auto &soundproofingelement : soundproofingtable ) {
auto const value { parser.getToken<float>( false ) };
if( value != -1.f ) {
soundproofingelement = std::sqrtf( clamp( value, 0.f, 1.f ) );
}
}
}
}
else if( token == "jointcabs:" ) {
parser.getTokens();
parser >> JointCabs;
@@ -6786,7 +6797,8 @@ TDynamicObject::update_neighbours() {
neighbour.vehicle_end = std::get<int>( lookup );
neighbour.distance = std::get<double>( lookup );
if( neighbour.distance < ( neighbour.vehicle->MoverParameters->CategoryFlag == 2 ? 50 : 100 ) ) {
if( ( neighbour.vehicle )
&& ( neighbour.distance < ( neighbour.vehicle->MoverParameters->CategoryFlag == 2 ? 50 : 100 ) ) ) {
// at short distances (re)calculate range between couplers directly
neighbour.distance = TMoverParameters::CouplerDist( MoverParameters, neighbour.vehicle->MoverParameters );
// take into account potential adapters attached to the couplers
@@ -6835,7 +6847,9 @@ TDynamicObject::find_vehicle( int const Direction, double const Distance ) const
// jeśli następny tor jest podpięty od Point2
direction = -direction; // to zmieniamy kierunek szukania na tym torze
}
track = track->CurrentNext(); // potem dopiero zmieniamy wskaźnik
if( track ) {
track = track->CurrentNext(); // potem dopiero zmieniamy wskaźnik
}
}
else {
// w kierunku Point1
@@ -6845,7 +6859,9 @@ TDynamicObject::find_vehicle( int const Direction, double const Distance ) const
// jeśli poprzedni tor nie jest podpięty od Point2
direction = -direction; // to zmieniamy kierunek szukania na tym torze
}
track = track->CurrentPrev(); // potem dopiero zmieniamy wskaźnik
if( track ) {
track = track->CurrentPrev(); // potem dopiero zmieniamy wskaźnik
}
}
if (track) {
// jesli jest kolejny odcinek toru

View File

@@ -516,6 +516,16 @@ private:
std::vector<doorspeaker_sounds> m_doorspeakers;
pasystem_sounds m_pasystem;
std::array<
std::array<float, 6> // listener: rear cab, engine, front cab, window, attached camera, free camera
, 5> m_soundproofing = {{
{{ EU07_SOUNDPROOFING_NONE, EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_NONE, EU07_SOUNDPROOFING_SOME, EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_STRONG }}, // internal sounds
{{ EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_NONE, EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_SOME, EU07_SOUNDPROOFING_SOME, EU07_SOUNDPROOFING_SOME }}, // engine sounds
{{ EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_SOME, EU07_SOUNDPROOFING_SOME, EU07_SOUNDPROOFING_NONE }}, // external sound
{{ EU07_SOUNDPROOFING_VERYSTRONG, EU07_SOUNDPROOFING_VERYSTRONG, EU07_SOUNDPROOFING_VERYSTRONG, EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_STRONG, EU07_SOUNDPROOFING_NONE }}, // external ambient sound
{{ EU07_SOUNDPROOFING_NONE, EU07_SOUNDPROOFING_NONE, EU07_SOUNDPROOFING_NONE, EU07_SOUNDPROOFING_NONE, EU07_SOUNDPROOFING_NONE, EU07_SOUNDPROOFING_NONE }}, // custom sounds
}};
coupleradapter_data m_coupleradapter;
bool renderme; // yB - czy renderowac
@@ -729,6 +739,9 @@ private:
void move_set(double distance);
// playes specified announcement, potentially preceding it with a chime
void announce( announcement_t const Announcement, bool const Chime = true );
// returns soundproofing for specified sound type and listener location
float soundproofing( int const Placement, int const Listener ) const {
return m_soundproofing[ Placement - 1 ][ Listener + 1 ]; }
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
static std::string const MED_labels[ 8 ];

View File

@@ -523,7 +523,6 @@ updatevalues_event::run_() {
+ ( ( m_input.flags & flags::text ) ? m_input.data_text : "X" ) + "] ["
+ ( ( m_input.flags & flags::value1 ) ? to_string( m_input.data_value_1, 2 ) : "X" ) + "] ["
+ ( ( m_input.flags & flags::value2 ) ? to_string( m_input.data_value_2, 2 ) : "X" ) + "]" );
// TODO: dump status of target cells after the operation
for( auto &target : m_targets ) {
auto *targetcell { static_cast<TMemCell *>( std::get<scene::basic_node *>( target ) ) };
if( targetcell == nullptr ) { continue; }
@@ -532,13 +531,18 @@ updatevalues_event::run_() {
m_input.data_value_1,
m_input.data_value_2,
m_input.flags );
WriteLog( " Memcell: " + targetcell->name() + " - " + targetcell->Values() );
// targetcell->LogValues();
if( targetcell->Track == nullptr ) { continue; }
// McZapkie-100302 - updatevalues oprocz zmiany wartosci robi putcommand dla wszystkich 'dynamic' na danym torze
auto const location { targetcell->location() };
for( auto dynamic : targetcell->Track->Dynamics ) {
targetcell->PutCommand(
dynamic->Mechanik,
&location );
for( auto vehicle : targetcell->Track->Dynamics ) {
if( vehicle->Mechanik ) {
targetcell->PutCommand(
vehicle->Mechanik,
&location );
WriteLog( " Vehicle: [" + vehicle->name() + "]" );
}
}
}
}
@@ -771,8 +775,10 @@ putvalues_event::run_() {
m_input.location.z,
m_input.location.y };
std::string vehiclename;
if( m_activator->Mechanik ) {
// przekazanie rozkazu do AI
vehiclename = m_activator->Mechanik->Vehicle()->name();
m_activator->Mechanik->PutCommand(
m_input.data_text,
m_input.data_value_1,
@@ -784,6 +790,7 @@ putvalues_event::run_() {
// send the command to consist owner,
// we're acting on presumption there's hardly ever need to issue command to unmanned vehicle
// and the intended recipient moved between vehicles after the event was queued
vehiclename = m_activator->ctOwner->Vehicle()->name();
m_activator->ctOwner->PutCommand(
m_input.data_text,
m_input.data_value_1,
@@ -792,12 +799,15 @@ putvalues_event::run_() {
}
else {
// przekazanie do pojazdu
vehiclename = m_activator->name();
m_activator->MoverParameters->PutCommand(
m_input.data_text,
m_input.data_value_1,
m_input.data_value_2,
loc );
}
WriteLog( " Vehicle: [" + vehiclename + "]" );
}
// export_as_text() subclass details
@@ -927,13 +937,18 @@ copyvalues_event::run_() {
m_input.data_value_1,
m_input.data_value_2,
m_input.flags );
WriteLog( " Memcell: " + targetcell->name() + " - " + targetcell->Values() );
// targetcell->LogValues();
if( targetcell->Track == nullptr ) { continue; }
// McZapkie-100302 - updatevalues oprocz zmiany wartosci robi putcommand dla wszystkich 'dynamic' na danym torze
auto const location { targetcell->location() };
for( auto dynamic : targetcell->Track->Dynamics ) {
targetcell->PutCommand(
dynamic->Mechanik,
&location );
for( auto vehicle : targetcell->Track->Dynamics ) {
if( vehicle->Mechanik ) {
targetcell->PutCommand(
vehicle->Mechanik,
&location );
WriteLog( " Vehicle: [" + vehicle->name() + "]" );
}
}
}
}
@@ -1142,11 +1157,7 @@ logvalues_event::run_() {
for( auto &target : m_targets ) {
auto *targetcell { static_cast<TMemCell *>( std::get<scene::basic_node *>( target ) ) };
if( targetcell == nullptr ) { continue; }
WriteLog(
"Memcell \"" + targetcell->name() + "\": ["
+ targetcell->Text() + "] ["
+ to_string( targetcell->Value1(), 2 ) + "] ["
+ to_string( targetcell->Value2(), 2 ) + "]" );
targetcell->LogValues();
}
}
}

View File

@@ -100,6 +100,10 @@ global_settings::ConfigParse(cParser &Parser) {
Parser.getTokens(1, false);
Parser >> fullscreen_monitor;
}
else if( token == "fullscreenwindowed" ) {
Parser.getTokens();
Parser >> fullscreen_windowed;
}
else if( token == "vsync" ) {
Parser.getTokens();
@@ -987,6 +991,7 @@ global_settings::export_as_text( std::ostream &Output ) const {
export_as_text( Output, "basedrawrange", BaseDrawRange );
export_as_text( Output, "fullscreen", bFullScreen );
export_as_text( Output, "fullscreenmonitor", fullscreen_monitor );
export_as_text( Output, "fullscreenwindowed", fullscreen_windowed );
export_as_text( Output, "vsync", VSync );
// NOTE: values are changed dynamically during simulation. cache initial settings and export instead
if( FreeFlyModeFlag ) {

View File

@@ -203,6 +203,7 @@ struct global_settings {
std::chrono::duration<float> minframetime{ 0.0f };
std::string fullscreen_monitor;
bool fullscreen_windowed{ false };
bool python_enabled = true;
bool python_mipmaps = true;

View File

@@ -1717,13 +1717,17 @@ void TMoverParameters::PowerCouplersCheck( double const Deltatime, coupling cons
for( auto side = 0; side < 2; ++side ) {
auto &coupler { Couplers[ side ] };
auto const &connectedothercoupler { coupler.Connected->Couplers[ ( coupler.ConnectedNr == end::front ? end::rear : end::front ) ] };
auto *coupling = (
Coupling == coupling::highvoltage ? &coupler.power_high :
Coupling == coupling::power110v ? &coupler.power_110v :
Coupling == coupling::power24v ? &coupler.power_24v :
nullptr );
coupling->current = 0.0;
if( coupler.Connected == nullptr ) { continue; }
auto const &connectedothercoupler { coupler.Connected->Couplers[ ( coupler.ConnectedNr == end::front ? end::rear : end::front ) ] };
auto const *connectedothercoupling = (
Coupling == coupling::highvoltage ? &connectedothercoupler.power_high :
Coupling == coupling::power110v ? &connectedothercoupler.power_110v :
@@ -1733,7 +1737,6 @@ void TMoverParameters::PowerCouplersCheck( double const Deltatime, coupling cons
Coupling == coupling::highvoltage ? std::abs( Itot ) * IsVehicleEIMBrakingFactor() :
0.0 );
coupling->current = 0.0;
if( false == localpowersource ) {
// bez napiecia...
if( couplervoltage != 0.0 ) {
@@ -3493,7 +3496,7 @@ bool TMoverParameters::MainSwitchCheck() const {
}
case TEngineType::ElectricSeriesMotor:
case TEngineType::ElectricInductionMotor: {
powerisavailable == ( std::max( GetTrainsetHighVoltage(), PantographVoltage ) > 0.5 * EnginePowerSource.MaxVoltage );
powerisavailable = ( std::max( GetTrainsetHighVoltage(), PantographVoltage ) > 0.5 * EnginePowerSource.MaxVoltage );
break;
}
default: {

View File

@@ -205,6 +205,16 @@ void TMemCell::AssignEvents(basic_event *e)
OnSent = e;
};
std::string TMemCell::Values() const {
return { "[" + Text() + "] [" + to_string( Value1(), 2 ) + "] [" + to_string( Value2(), 2 ) + "]" };
}
void TMemCell::LogValues() const {
WriteLog( "Memcell " + name() + ": " + Values() );
}
// serialize() subclass details, sends content of the subclass to provided stream
void
TMemCell::serialize_( std::ostream &Output ) const {
@@ -264,10 +274,6 @@ void
memory_table::log_all() {
for( auto *cell : m_items ) {
WriteLog( "Memcell \"" + cell->name() + "\": ["
+ cell->Text() + "] ["
+ to_string( cell->Value1(), 2 ) + "] ["
+ to_string( cell->Value2(), 2 ) + "]" );
cell->LogValues();
}
}

View File

@@ -51,6 +51,8 @@ public:
TCommandType CommandCheck();
bool IsVelocity() const;
void AssignEvents(basic_event *e);
std::string Values() const;
void LogValues() const;
// members
std::string asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
TTrack *Track { nullptr }; // resolved binding with the specified track

View File

@@ -372,6 +372,8 @@ TTraction::Connect(int my, TTraction *with, int to) {
iLast = 0;
}
if( with == nullptr ) { return; }
with->hvNext[ to ] = this;
with->iNext[ to ] = my;

View File

@@ -74,7 +74,7 @@ bool TTractionPowerSource::Load(cParser *parser) {
bool TTractionPowerSource::Update(double dt)
{ // powinno być wykonane raz na krok fizyki
// iloczyn napięcia i admitancji daje prąd
if (NominalVoltage * TotalPreviousAdmitance > MaxOutputCurrent) {
if (TotalCurrent > MaxOutputCurrent) {
FastFuse = true;
FuseCounter += 1;

View File

@@ -5573,10 +5573,10 @@ void TTrain::OnCommand_occupiedcarcouplingdisconnect( TTrain *Train, command_dat
if( Train->DynamicObject ) {
Train->DynamicObject->uncouple( Train->cab_to_end() );
}
if( Train->DynamicObject->Mechanik ) {
// aktualizacja flag kierunku w składzie
Train->DynamicObject->Mechanik->CheckVehicles( Disconnect );
if( Train->DynamicObject->Mechanik ) {
// aktualizacja flag kierunku w składzie
Train->DynamicObject->Mechanik->CheckVehicles( Disconnect );
}
}
}
else if( Command.action == GLFW_RELEASE ) {
@@ -5937,15 +5937,17 @@ void TTrain::OnCommand_vehicleboost(TTrain *Train, const command_data &Command)
double boost = Command.param1 != 0.0 ? Command.param1 : 2.78;
TDynamicObject *d = Train->DynamicObject;
while( d ) {
d->MoverParameters->V += d->DirectionGet() * boost;
d = d->Next(); // pozostałe też
if( Train->DynamicObject == nullptr ) { return; }
auto *vehicle { Train->DynamicObject };
while( vehicle ) {
vehicle->MoverParameters->V += vehicle->DirectionGet() * boost;
vehicle = vehicle->Next(); // pozostałe też
}
d = Train->DynamicObject->Prev();
while( d ) {
d->MoverParameters->V += d->DirectionGet() * boost;
d = d->Prev(); // w drugą stronę też
vehicle = Train->DynamicObject->Prev();
while( vehicle ) {
vehicle->MoverParameters->V += vehicle->DirectionGet() * boost;
vehicle = vehicle->Prev(); // w drugą stronę też
}
}
@@ -6491,15 +6493,6 @@ bool TTrain::Update( double const Deltatime )
btLampkaPoslizg.Turn( false );
}
if ((mvControlled->Mains) || (mvControlled->TrainType == dt_EZT))
{
btLampkaNadmSil.Turn(mvControlled->FuseFlagCheck());
}
else
{
btLampkaNadmSil.Turn( false );
}
if( true == lowvoltagepower ) {
// alerter test
if( true == CAflag ) {
@@ -6578,6 +6571,11 @@ bool TTrain::Update( double const Deltatime )
false :
( mvControlled->BrakePress < 1.0 ) ); // relay is off and needs a reset
btLampkaNadmSil.Turn(
( ( false == mvControlled->FuseFlagCheck() ) || ( mvControlled->ControlPressureSwitch ) ) ?
false :
( mvControlled->BrakePress < 1.0 ) ); // relay is off and needs a reset
if( ( ( mvControlled->CabOccupied == 1 ) && ( TestFlag( mvControlled->Couplers[ end::rear ].CouplingFlag, coupling::control ) ) )
|| ( ( mvControlled->CabOccupied == -1 ) && ( TestFlag( mvControlled->Couplers[ end::front ].CouplingFlag, coupling::control ) ) ) ) {
btLampkaUkrotnienie.Turn( true );
@@ -7398,10 +7396,15 @@ TTrain::update_sounds( double const Deltatime ) {
if( ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen )
&& ( Global.Weather == "rain:" ) ) {
m_precipitationsound.play( sound_flags::exclusive | sound_flags::looping );
if( m_rainsound.is_combined() ) {
m_rainsound.pitch( Global.Overcast - 1.0 );
}
m_rainsound
.gain( m_rainsound.m_amplitudeoffset + m_rainsound.m_amplitudefactor * 1.f )
.play( sound_flags::exclusive | sound_flags::looping );
}
else {
m_precipitationsound.stop();
m_rainsound.stop();
}
if( fTachoCount >= 3.f ) {
@@ -7743,8 +7746,8 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName)
}
else if( token == "rainsound:" ) {
// precipitation sound:
m_precipitationsound.deserialize( parser, sound_type::single );
m_precipitationsound.owner( DynamicObject );
m_rainsound.deserialize( parser, sound_type::single );
m_rainsound.owner( DynamicObject );
}
} while (token != "");
@@ -8055,9 +8058,9 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
{
*/
// assign default samples to sound emitters which weren't included in the config file
if( m_precipitationsound.empty() ) {
m_precipitationsound.deserialize( "rainsound_default", sound_type::single );
m_precipitationsound.owner( DynamicObject );
if( m_rainsound.empty() ) {
m_rainsound.deserialize( "rainsound_default", sound_type::single );
m_rainsound.owner( DynamicObject );
}
// configure placement of sound emitters which aren't bound with any device model, and weren't placed manually
// try first to bind sounds to location of possible devices

View File

@@ -726,7 +726,7 @@ public: // reszta może by?publiczna
sound_source rsFadeSound { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source rsRunningNoise{ sound_placement::internal, EU07_SOUND_GLOBALRANGE };
sound_source rsHuntingNoise{ sound_placement::internal, EU07_SOUND_GLOBALRANGE };
sound_source m_precipitationsound { sound_placement::internal, -1 };
sound_source m_rainsound { sound_placement::internal, -1 };
sound_source dsbHasler { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source dsbBuzzer { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };

View File

@@ -763,8 +763,16 @@ eu07_application::init_glfw() {
}
}
if( Global.fullscreen_windowed ) {
// overwrite resolution settings to match default monitor
auto const mode = glfwGetVideoMode( monitor );
Global.iWindowWidth = mode->width;
Global.iWindowHeight = mode->height;
glfwWindowHint( GLFW_DECORATED, GLFW_FALSE );
monitor = nullptr;
}
auto *mainwindow = window(
-1, true, Global.iWindowWidth, Global.iWindowHeight, Global.bFullScreen ? monitor : nullptr, true, false );
-1, true, Global.iWindowWidth, Global.iWindowHeight, ( Global.bFullScreen ? monitor : nullptr ), true, false );
if( mainwindow == nullptr ) {
ErrorLog( "Bad init: failed to create glfw window" );

View File

@@ -573,7 +573,8 @@ driver_mode::update_camera( double const Deltatime ) {
// uwzględnienie ruchu wywołanego klawiszami
if( false == DebugCameraFlag ) {
// regular camera
if( ( false == FreeFlyModeFlag )
if( ( simulation::Train != nullptr )
&& ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen ) ) {
// if in cab potentially alter camera placement based on changes in train object
Camera.m_owneroffset = simulation::Train->pMechOffset;
@@ -583,12 +584,14 @@ driver_mode::update_camera( double const Deltatime ) {
Camera.Update();
if( false == FreeFlyModeFlag ) {
if( ( simulation::Train != nullptr )
&& ( false == FreeFlyModeFlag ) ) {
// keep the camera within cab boundaries
Camera.m_owneroffset = simulation::Train->clamp_inside( Camera.m_owneroffset );
}
if( ( false == FreeFlyModeFlag )
if( ( simulation::Train != nullptr )
&& ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen ) ) {
// cache cab camera in case of view type switch
simulation::Train->pMechViewAngle = { Camera.Angle.x, Camera.Angle.y };

View File

@@ -1149,7 +1149,7 @@ debug_panel::update_section_powergrid( std::vector<text_line> &Output ) {
auto const lowpowercolor { glm::vec4( 164.0f / 255.0f, 132.0f / 255.0f, 84.0f / 255.0f, 1.f ) };
auto const nopowercolor { glm::vec4( 164.0f / 255.0f, 84.0f / 255.0f, 84.0f / 255.0f, 1.f ) };
Output.emplace_back( "Name: Output: Timeout:", Global.UITextColor );
Output.emplace_back( "Name: Output: Current: Timeout:", Global.UITextColor );
std::string textline;
@@ -1166,7 +1166,8 @@ debug_panel::update_section_powergrid( std::vector<text_line> &Output ) {
textline =
name.substr( 0, 20 )
+ " " + to_string( powerstation->OutputVoltage, 0, 5 )
+ " " + to_string( powerstation->FuseTimer, 1, 12 )
+ " " + to_string( powerstation->TotalCurrent, 1, 8 )
+ " " + to_string( powerstation->FuseTimer, 1, 8 )
+ ( powerstation->FuseCounter == 0 ?
"" :
" (x" + to_string( powerstation->FuseCounter ) + ")" );
@@ -1218,7 +1219,8 @@ debug_panel::update_section_renderer( std::vector<text_line> &Output ) {
+ ", Draw range: " + to_string( Global.BaseDrawRange * Global.fDistanceFactor, 0 ) + "m"
// + "; sectors: " + std::to_string( GfxRenderer->m_drawcount )
// + ", FPS: " + to_string( Timer::GetFPS(), 2 );
+ ", FPS: " + std::to_string( static_cast<int>(std::round(GfxRenderer->Framerate())) );
+ ", FPS: " + std::to_string( static_cast<int>(std::round(GfxRenderer->Framerate())) )
+ ( Global.VSync ? " (vsync on)" : "" );
if( Global.iSlowMotion ) {
textline += " (slowmotion " + to_string( Global.iSlowMotion ) + ")";
}

View File

@@ -192,7 +192,9 @@ world_environment::update() {
if( m_rainsound.is_combined() ) {
m_rainsound.pitch( Global.Overcast - 1.0 );
}
m_rainsound.play( sound_flags::exclusive | sound_flags::looping );
m_rainsound
.gain( m_rainsound.m_amplitudeoffset + m_rainsound.m_amplitudefactor * 1.f )
.play( sound_flags::exclusive | sound_flags::looping );
}
else {
m_rainsound.stop();

131
sound.cpp
View File

@@ -229,6 +229,7 @@ sound_source::deserialize_mapping( cParser &Input ) {
{ "internal", sound_placement::internal },
{ "engine", sound_placement::engine },
{ "external", sound_placement::external },
{ "custom", sound_placement::custom },
{ "general", sound_placement::general } };
auto lookup{ placements.find( value ) };
if( lookup != placements.end() ) {
@@ -933,115 +934,53 @@ sound_source::update_location() {
m_properties.location = location();
}
float const EU07_SOUNDPROOFING_GLOBAL_VERYSTRONG { 0.01f };
float const EU07_SOUNDPROOFING_GLOBAL_STRONG { std::sqrtf( 0.025 ) };
float const EU07_SOUNDPROOFING_GLOBAL_SOME { std::sqrtf( 0.15 ) };
float const EU07_SOUNDPROOFING_GLOBAL_NONE { std::sqrtf( 0.40 ) };
float const EU07_SOUNDPROOFING_STRONG { std::sqrtf( 0.20 ) };
float const EU07_SOUNDPROOFING_SOME { std::sqrtf( 0.65 ) };
float const EU07_SOUNDPROOFING_NONE { 1.f };
bool
sound_source::update_soundproofing() {
// NOTE, HACK: current cab id can vary from -1 to +1, and we use higher priority values for open cab window and external views
// we use this as modifier to force re-calculations when moving between compartments or changing window state
int const occupiedcab = (
Global.CabWindowOpen ? 2 :
auto const *listenervehicle { Global.pCamera.m_owner }; // nullptr in free roam mode
auto const occupiedcab { (
Global.CabWindowOpen ? 2 : // window view
FreeFlyModeFlag ? (
Global.pCamera.m_owner ?
3 :
0 ) :
( simulation::Train ?
simulation::Train->Occupied()->CabOccupied :
0 ) );
listenervehicle ?
3 : // external view
4 ) : // free roam view
listenervehicle->MoverParameters->CabOccupied ) }; // some internal view so we can be sure listener isn't a nullptr
// location-based gain factor:
std::uintptr_t soundproofingstamp = reinterpret_cast<std::uintptr_t>( (
FreeFlyModeFlag ?
Global.pCamera.m_owner :
( simulation::Train ?
simulation::Train->Dynamic() :
nullptr ) ) )
+ occupiedcab;
std::uintptr_t soundproofingstamp =
reinterpret_cast<std::uintptr_t>( listenervehicle )
+ ( listenervehicle ?
occupiedcab :
0 );
if( soundproofingstamp == m_properties.soundproofing_stamp ) { return false; }
// listener location has changed, calculate new location-based gain factor
auto const externalcamera { ( Global.CabWindowOpen ) || ( Global.pCamera.m_owner && FreeFlyModeFlag ) };
switch( m_placement ) {
case sound_placement::general: {
m_properties.soundproofing = (
m_range >= -1 ?
EU07_SOUNDPROOFING_NONE :
EU07_SOUNDPROOFING_GLOBAL_NONE );
break;
// TBD, TODO: clean up parameters for soundproofing() call -- make ambient separate, explicit placement
m_properties.soundproofing = EU07_SOUNDPROOFING_NONE; // default proofing for environment sounds and free listener
if( m_placement != sound_placement::general ) {
auto const isambient { ( ( m_placement == sound_placement::external ) && ( m_owner == nullptr ) && ( m_range < -1 ) ? 1 : 0 ) };
auto const placement { ( isambient ? sound_placement::external_ambient : m_placement ) };
if( m_owner != nullptr ) {
m_properties.soundproofing =
m_owner->soundproofing(
static_cast<int>( placement ),
( m_owner != listenervehicle ?
4 : // part of two-stage calculation owner->outside->listener, or single stage owner->outside one
occupiedcab ) );
}
case sound_placement::external: {
if( m_range >= -1 ) { // limited range sound...
m_properties.soundproofing = (
soundproofingstamp == 0 ? EU07_SOUNDPROOFING_NONE : // ...with listener outside
externalcamera ? EU07_SOUNDPROOFING_SOME : // ...with listener inside and window open
EU07_SOUNDPROOFING_STRONG ); // ...with listener inside and window closed
}
else { // global sound...
m_properties.soundproofing = (
soundproofingstamp == 0 ? EU07_SOUNDPROOFING_GLOBAL_NONE : // ...with listener outside
externalcamera ? EU07_SOUNDPROOFING_GLOBAL_STRONG : // ...with listener inside and window open
EU07_SOUNDPROOFING_GLOBAL_VERYSTRONG ); // ...with listener inside and window closed
}
break;
}
case sound_placement::internal: {
if( m_range >= -1 ) { // limited range sound
m_properties.soundproofing = (
( FreeFlyModeFlag || externalcamera ) ?
EU07_SOUNDPROOFING_STRONG : // listener outside HACK: won't be true if active vehicle has open window
( simulation::Train->Dynamic() != m_owner ?
EU07_SOUNDPROOFING_STRONG : // in another vehicle
( occupiedcab == 0 ?
EU07_SOUNDPROOFING_STRONG : // listener in the engine compartment
EU07_SOUNDPROOFING_NONE ) ) ); // listener in the cab of the same vehicle
}
else { // global sound
m_properties.soundproofing = (
( FreeFlyModeFlag || externalcamera ) ?
EU07_SOUNDPROOFING_GLOBAL_STRONG : // listener outside HACK: won't be true if active vehicle has open window
( simulation::Train->Dynamic() != m_owner ?
EU07_SOUNDPROOFING_GLOBAL_VERYSTRONG : // in another vehicle
( occupiedcab == 0 ?
EU07_SOUNDPROOFING_GLOBAL_NONE : // listener in the engine compartment
EU07_SOUNDPROOFING_GLOBAL_STRONG ) ) ); // listener in the cab of the same vehicle
}
break;
}
case sound_placement::engine: {
if( m_range >= -1 ) { // limited range sound
m_properties.soundproofing = (
( FreeFlyModeFlag || externalcamera ) ?
EU07_SOUNDPROOFING_SOME : // listener outside or has a window open
( simulation::Train->Dynamic() != m_owner ?
EU07_SOUNDPROOFING_STRONG : // in another vehicle
( occupiedcab == 0 ?
EU07_SOUNDPROOFING_NONE : // listener in the engine compartment
EU07_SOUNDPROOFING_STRONG ) ) ); // listener in another compartment of the same vehicle
}
else { // global sound
m_properties.soundproofing = (
( FreeFlyModeFlag || externalcamera ) ?
EU07_SOUNDPROOFING_GLOBAL_STRONG : // listener outside or has a window open
( simulation::Train->Dynamic() != m_owner ?
EU07_SOUNDPROOFING_GLOBAL_VERYSTRONG : // in another vehicle
( occupiedcab == 0 ?
EU07_SOUNDPROOFING_NONE : // listener in the engine compartment
EU07_SOUNDPROOFING_GLOBAL_STRONG ) ) ); // listener in another compartment of the same vehicle
}
break;
}
default: {
// shouldn't ever land here, but, eh
m_properties.soundproofing = EU07_SOUNDPROOFING_NONE;
break;
if( ( listenervehicle ) && ( listenervehicle != m_owner ) ) {
// if the listener is located in another vehicle, calculate additional proofing of the sound coming from outside
m_properties.soundproofing *=
listenervehicle->soundproofing(
static_cast<int>( sound_placement::external ) + isambient,
occupiedcab );
}
}
// for ambient sounds reduce their volume to account for their placement right on top of the listener
if( m_range < -1 ) {
m_properties.soundproofing *= 0.4f;
}
m_properties.soundproofing_stamp = soundproofingstamp;
return true;

View File

@@ -41,9 +41,16 @@ enum class sound_placement {
general, // source is equally audible in potential carrier and outside of it
internal, // source is located inside of the carrier, and less audible when the listener is outside
engine, // source is located in the engine compartment, less audible when the listener is outside and even less in the cabs
external // source is located on the outside of the carrier, and less audible when the listener is inside
external, // source is located on the outside of the carrier, and less audible when the listener is inside
external_ambient, // source is located on the outside of the carrier, with fixed volume
custom, // source doesn't fit in any standard location or requires custom soundproofing
};
auto const EU07_SOUNDPROOFING_NONE{ 1.f };
auto const EU07_SOUNDPROOFING_SOME{ std::sqrtf( 0.65f ) };
auto const EU07_SOUNDPROOFING_STRONG{ std::sqrtf( 0.20f ) };
auto const EU07_SOUNDPROOFING_VERYSTRONG{ std::sqrtf( 0.01f ) };
// mini controller and audio dispatcher; issues play commands for the audio renderer,
// updates parameters of created audio emitters for the playback duration
// TODO: move to simulation namespace after clean up of owner classes

View File

@@ -416,6 +416,7 @@ void uart_input::poll()
if (conf.debug)
{
char buf[buffer.size() * 3 + 1];
buf[ buffer.size() * 3 ] = NULL;
size_t pos = 0;
for (uint8_t b : buffer)
pos += sprintf(&buf[pos], "%02X ", b);