mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 06:59:18 +02:00
varying scale cab control animation types, basic shunt mode power slider cab control, minor ai logic tweaks, minor bug fixes
This commit is contained in:
22
Driver.cpp
22
Driver.cpp
@@ -2223,13 +2223,15 @@ bool TController::PrepareEngine()
|
|||||||
voltfront = true;
|
voltfront = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto workingtemperature { true };
|
||||||
if (AIControllFlag) {
|
if (AIControllFlag) {
|
||||||
// część wykonawcza dla sterowania przez komputer
|
// część wykonawcza dla sterowania przez komputer
|
||||||
mvOccupied->BatterySwitch( true );
|
mvOccupied->BatterySwitch( true );
|
||||||
if( ( mvControlling->EngineType == DieselElectric )
|
if( ( mvControlling->EngineType == DieselElectric )
|
||||||
|| ( mvControlling->EngineType == DieselEngine ) ) {
|
|| ( mvControlling->EngineType == DieselEngine ) ) {
|
||||||
mvControlling->OilPumpSwitch( true );
|
mvControlling->OilPumpSwitch( true );
|
||||||
if( true == UpdateHeating() ) {
|
workingtemperature = UpdateHeating();
|
||||||
|
if( true == workingtemperature ) {
|
||||||
mvControlling->FuelPumpSwitch( true );
|
mvControlling->FuelPumpSwitch( true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2339,7 +2341,7 @@ bool TController::PrepareEngine()
|
|||||||
else
|
else
|
||||||
OK = false;
|
OK = false;
|
||||||
|
|
||||||
OK = OK && (mvOccupied->ActiveDir != 0) && (mvControlling->CompressorAllow);
|
OK = OK && (mvOccupied->ActiveDir != 0) && (mvControlling->CompressorAllow) && (workingtemperature);
|
||||||
if (OK)
|
if (OK)
|
||||||
{
|
{
|
||||||
if (eStopReason == stopSleep) // jeśli dotychczas spał
|
if (eStopReason == stopSleep) // jeśli dotychczas spał
|
||||||
@@ -2378,6 +2380,7 @@ bool TController::ReleaseEngine()
|
|||||||
mvControlling->PantFront(false);
|
mvControlling->PantFront(false);
|
||||||
mvControlling->PantRear(false);
|
mvControlling->PantRear(false);
|
||||||
}
|
}
|
||||||
|
// line breaker
|
||||||
OK = mvControlling->MainSwitch(false);
|
OK = mvControlling->MainSwitch(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2410,7 +2413,20 @@ bool TController::ReleaseEngine()
|
|||||||
eAction = actSleep; //śpi (wygaszony)
|
eAction = actSleep; //śpi (wygaszony)
|
||||||
if (AIControllFlag)
|
if (AIControllFlag)
|
||||||
{
|
{
|
||||||
Lights(0, 0); // gasimy światła
|
if( ( mvControlling->EngineType == DieselElectric )
|
||||||
|
|| ( mvControlling->EngineType == DieselEngine ) ) {
|
||||||
|
// heating/cooling subsystem
|
||||||
|
mvControlling->WaterHeaterSwitch( false );
|
||||||
|
// optionally turn off the water pump as well
|
||||||
|
if( mvControlling->WaterPump.start_type != start::battery ) {
|
||||||
|
mvControlling->WaterPumpSwitch( false );
|
||||||
|
}
|
||||||
|
// fuel and oil subsystems
|
||||||
|
mvControlling->FuelPumpSwitch( false );
|
||||||
|
mvControlling->OilPumpSwitch( false );
|
||||||
|
}
|
||||||
|
// gasimy światła
|
||||||
|
Lights(0, 0);
|
||||||
mvOccupied->BatterySwitch(false);
|
mvOccupied->BatterySwitch(false);
|
||||||
}
|
}
|
||||||
OrderNext(Wait_for_orders); //żeby nie próbował coś robić dalej
|
OrderNext(Wait_for_orders); //żeby nie próbował coś robić dalej
|
||||||
|
|||||||
4
EU07.cpp
4
EU07.cpp
@@ -412,7 +412,9 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::renderer.init();
|
if( Global.bSoundEnabled ) {
|
||||||
|
Global.bSoundEnabled &= audio::renderer.init();
|
||||||
|
}
|
||||||
|
|
||||||
input::Keyboard.init();
|
input::Keyboard.init();
|
||||||
input::Mouse.init();
|
input::Mouse.init();
|
||||||
|
|||||||
275
Gauge.cpp
275
Gauge.cpp
@@ -21,46 +21,54 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
|
||||||
void TGauge::Init(TSubModel *NewSubModel, TGaugeType eNewType, double fNewScale, double fNewOffset, double fNewFriction, double fNewValue)
|
void TGauge::Init(TSubModel *Submodel, TGaugeType Type, float Scale, float Offset, float Friction, float Value, float const Endvalue, float const Endscale, bool const Interpolatescale )
|
||||||
{ // ustawienie parametrów animacji submodelu
|
{ // ustawienie parametrów animacji submodelu
|
||||||
if (NewSubModel) {
|
SubModel = Submodel;
|
||||||
// warunek na wszelki wypadek, gdyby się submodel nie podłączył
|
m_value = Value;
|
||||||
fFriction = fNewFriction;
|
m_type = Type;
|
||||||
fValue = fNewValue;
|
m_scale = Scale;
|
||||||
fOffset = fNewOffset;
|
m_offset = Offset;
|
||||||
fScale = fNewScale;
|
m_friction = Friction;
|
||||||
SubModel = NewSubModel;
|
m_interpolatescale = Interpolatescale;
|
||||||
eType = eNewType;
|
m_endvalue = Endvalue;
|
||||||
if (eType == gt_Digital) {
|
m_endscale = Endscale;
|
||||||
|
|
||||||
TSubModel *sm = SubModel->ChildGet();
|
if( Submodel == nullptr ) {
|
||||||
do {
|
// warunek na wszelki wypadek, gdyby się submodel nie podłączył
|
||||||
// pętla po submodelach potomnych i obracanie ich o kąt zależy od cyfry w (fValue)
|
return;
|
||||||
if (sm->pName.size())
|
}
|
||||||
{ // musi mieć niepustą nazwę
|
|
||||||
if (sm->pName[0] >= '0')
|
if( m_type == gt_Digital ) {
|
||||||
if (sm->pName[0] <= '9')
|
|
||||||
sm->WillBeAnimated(); // wyłączenie optymalizacji
|
TSubModel *sm = SubModel->ChildGet();
|
||||||
}
|
do {
|
||||||
sm = sm->NextGet();
|
// pętla po submodelach potomnych i obracanie ich o kąt zależy od cyfry w (fValue)
|
||||||
} while (sm);
|
if( sm->pName.size() ) { // musi mieć niepustą nazwę
|
||||||
}
|
if( sm->pName[ 0 ] >= '0' )
|
||||||
else // a banan może być z optymalizacją?
|
if( sm->pName[ 0 ] <= '9' )
|
||||||
NewSubModel->WillBeAnimated(); // wyłączenie ignowania jedynkowego transformu
|
sm->WillBeAnimated(); // wyłączenie optymalizacji
|
||||||
// pass submodel location to defined sounds
|
}
|
||||||
auto const offset { model_offset() };
|
sm = sm->NextGet();
|
||||||
m_soundfxincrease.offset( offset );
|
} while( sm );
|
||||||
m_soundfxdecrease.offset( offset );
|
}
|
||||||
for( auto &soundfxrecord : m_soundfxvalues ) {
|
else // a banan może być z optymalizacją?
|
||||||
soundfxrecord.second.offset( offset );
|
Submodel->WillBeAnimated(); // wyłączenie ignowania jedynkowego transformu
|
||||||
}
|
// pass submodel location to defined sounds
|
||||||
|
auto const offset{ model_offset() };
|
||||||
|
m_soundfxincrease.offset( offset );
|
||||||
|
m_soundfxdecrease.offset( offset );
|
||||||
|
for( auto &soundfxrecord : m_soundfxvalues ) {
|
||||||
|
soundfxrecord.second.offset( offset );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, TModel3d *md2, double mul ) {
|
bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, TModel3d *md2, double mul ) {
|
||||||
|
|
||||||
std::string submodelname, gaugetypename;
|
std::string submodelname, gaugetypename;
|
||||||
double scale, offset, friction;
|
float scale, endscale, endvalue, offset, friction;
|
||||||
|
endscale = -1;
|
||||||
|
endvalue = -1;
|
||||||
|
bool interpolatescale { false };
|
||||||
|
|
||||||
Parser.getTokens();
|
Parser.getTokens();
|
||||||
if( Parser.peek() != "{" ) {
|
if( Parser.peek() != "{" ) {
|
||||||
@@ -72,6 +80,14 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1,
|
|||||||
>> scale
|
>> scale
|
||||||
>> offset
|
>> offset
|
||||||
>> friction;
|
>> friction;
|
||||||
|
if( ( gaugetypename == "rotvar" )
|
||||||
|
|| ( gaugetypename == "movvar" ) ) {
|
||||||
|
interpolatescale = true;
|
||||||
|
Parser.getTokens( 2, false );
|
||||||
|
Parser
|
||||||
|
>> endvalue
|
||||||
|
>> endscale;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// new, block type config
|
// new, block type config
|
||||||
@@ -83,6 +99,14 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1,
|
|||||||
>> scale
|
>> scale
|
||||||
>> offset
|
>> offset
|
||||||
>> friction;
|
>> friction;
|
||||||
|
if( ( gaugetypename == "rotvar" )
|
||||||
|
|| ( gaugetypename == "movvar" ) ) {
|
||||||
|
interpolatescale = true;
|
||||||
|
Parser.getTokens( 2, false );
|
||||||
|
Parser
|
||||||
|
>> endvalue
|
||||||
|
>> endscale;
|
||||||
|
}
|
||||||
// new, variable length section
|
// new, variable length section
|
||||||
while( true == Load_mapping( Parser ) ) {
|
while( true == Load_mapping( Parser ) ) {
|
||||||
; // all work done by while()
|
; // all work done by while()
|
||||||
@@ -97,11 +121,10 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
scale *= mul;
|
scale *= mul;
|
||||||
TSubModel *submodel = md1->GetFromName( submodelname );
|
if( interpolatescale ) {
|
||||||
if( scale == 0.0 ) {
|
endscale *= mul;
|
||||||
ErrorLog( "Bad model: scale of 0.0 defined for sub-model \"" + submodelname + "\" in 3d model \"" + md1->NameGet() + "\". Forcing scale of 1.0 to prevent division by 0", logtype::model );
|
|
||||||
scale = 1.0;
|
|
||||||
}
|
}
|
||||||
|
TSubModel *submodel = md1->GetFromName( submodelname );
|
||||||
if (submodel) // jeśli nie znaleziony
|
if (submodel) // jeśli nie znaleziony
|
||||||
md2 = nullptr; // informacja, że znaleziony
|
md2 = nullptr; // informacja, że znaleziony
|
||||||
else if (md2) // a jest podany drugi model (np. zewnętrzny)
|
else if (md2) // a jest podany drugi model (np. zewnętrzny)
|
||||||
@@ -111,7 +134,10 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, TGaugeType> gaugetypes {
|
std::map<std::string, TGaugeType> gaugetypes {
|
||||||
|
{ "rot", gt_Rotate },
|
||||||
|
{ "rotvar", gt_Rotate },
|
||||||
{ "mov", gt_Move },
|
{ "mov", gt_Move },
|
||||||
|
{ "movvar", gt_Move },
|
||||||
{ "wip", gt_Wiper },
|
{ "wip", gt_Wiper },
|
||||||
{ "dgt", gt_Digital }
|
{ "dgt", gt_Digital }
|
||||||
};
|
};
|
||||||
@@ -119,8 +145,9 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1,
|
|||||||
auto const type = (
|
auto const type = (
|
||||||
lookup != gaugetypes.end() ?
|
lookup != gaugetypes.end() ?
|
||||||
lookup->second :
|
lookup->second :
|
||||||
gt_Rotate );
|
gt_Unknown );
|
||||||
Init(submodel, type, scale, offset, friction);
|
|
||||||
|
Init( submodel, type, scale, offset, friction, 0, endvalue, endscale, interpolatescale );
|
||||||
|
|
||||||
return md2 != nullptr; // true, gdy podany model zewnętrzny, a w kabinie nie było
|
return md2 != nullptr; // true, gdy podany model zewnętrzny, a w kabinie nie było
|
||||||
};
|
};
|
||||||
@@ -151,51 +178,27 @@ TGauge::Load_mapping( cParser &Input ) {
|
|||||||
return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized
|
return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized
|
||||||
}
|
}
|
||||||
|
|
||||||
void TGauge::PermIncValue(double fNewDesired)
|
|
||||||
{
|
|
||||||
fDesiredValue = fDesiredValue + fNewDesired * fScale + fOffset;
|
|
||||||
if (fDesiredValue - fOffset > 360 / fScale)
|
|
||||||
{
|
|
||||||
fDesiredValue = fDesiredValue - (360 / fScale);
|
|
||||||
fValue = fValue - (360 / fScale);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void TGauge::IncValue(double fNewDesired)
|
|
||||||
{ // używane tylko dla uniwersali
|
|
||||||
fDesiredValue = fDesiredValue + fNewDesired * fScale + fOffset;
|
|
||||||
if (fDesiredValue > fScale + fOffset)
|
|
||||||
fDesiredValue = fScale + fOffset;
|
|
||||||
};
|
|
||||||
|
|
||||||
void TGauge::DecValue(double fNewDesired)
|
|
||||||
{ // używane tylko dla uniwersali
|
|
||||||
fDesiredValue = fDesiredValue - fNewDesired * fScale + fOffset;
|
|
||||||
if (fDesiredValue < 0)
|
|
||||||
fDesiredValue = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TGauge::UpdateValue( double fNewDesired ) {
|
TGauge::UpdateValue( float fNewDesired ) {
|
||||||
|
|
||||||
return UpdateValue( fNewDesired, nullptr );
|
return UpdateValue( fNewDesired, nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TGauge::UpdateValue( double fNewDesired, sound_source &Fallbacksound ) {
|
TGauge::UpdateValue( float fNewDesired, sound_source &Fallbacksound ) {
|
||||||
|
|
||||||
return UpdateValue( fNewDesired, &Fallbacksound );
|
return UpdateValue( fNewDesired, &Fallbacksound );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ustawienie wartości docelowej. plays provided fallback sound, if no sound was defined in the control itself
|
// ustawienie wartości docelowej. plays provided fallback sound, if no sound was defined in the control itself
|
||||||
void
|
void
|
||||||
TGauge::UpdateValue( double fNewDesired, sound_source *Fallbacksound ) {
|
TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) {
|
||||||
|
|
||||||
auto const desiredtimes100 = static_cast<int>( std::round( 100.0 * fNewDesired ) );
|
auto const desiredtimes100 = static_cast<int>( std::round( 100.0 * fNewDesired ) );
|
||||||
if( static_cast<int>( std::round( 100.0 * ( fDesiredValue - fOffset ) / fScale ) ) == desiredtimes100 ) {
|
if( desiredtimes100 == static_cast<int>( 100.0 * m_targetvalue ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fDesiredValue = fNewDesired * fScale + fOffset;
|
m_targetvalue = fNewDesired;
|
||||||
// if there's any sound associated with new requested value, play it
|
// if there's any sound associated with new requested value, play it
|
||||||
// check value-specific table first...
|
// check value-specific table first...
|
||||||
if( desiredtimes100 % 100 == 0 ) {
|
if( desiredtimes100 % 100 == 0 ) {
|
||||||
@@ -224,115 +227,137 @@ TGauge::UpdateValue( double fNewDesired, sound_source *Fallbacksound ) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void TGauge::PutValue(double fNewDesired)
|
void TGauge::PutValue(float fNewDesired)
|
||||||
{ // McZapkie-281102: natychmiastowe wpisanie wartosci
|
{ // McZapkie-281102: natychmiastowe wpisanie wartosci
|
||||||
fDesiredValue = fNewDesired * fScale + fOffset;
|
m_targetvalue = fNewDesired;
|
||||||
fValue = fDesiredValue;
|
m_value = m_targetvalue;
|
||||||
};
|
};
|
||||||
|
|
||||||
double TGauge::GetValue() const {
|
float TGauge::GetValue() const {
|
||||||
// we feed value in range 0-1 so we should be getting it reported in the same range
|
// we feed value in range 0-1 so we should be getting it reported in the same range
|
||||||
return ( fValue - fOffset ) / fScale;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
double TGauge::GetDesiredValue() const {
|
float TGauge::GetDesiredValue() const {
|
||||||
// we feed value in range 0-1 so we should be getting it reported in the same range
|
// we feed value in range 0-1 so we should be getting it reported in the same range
|
||||||
return ( fDesiredValue - fOffset ) / fScale;
|
return m_targetvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TGauge::Update() {
|
void TGauge::Update() {
|
||||||
|
|
||||||
if( fValue != fDesiredValue ) {
|
if( m_value != m_targetvalue ) {
|
||||||
float dt = Timer::GetDeltaTime();
|
float dt = Timer::GetDeltaTime();
|
||||||
if( ( fFriction > 0 ) && ( dt < 0.5 * fFriction ) ) {
|
if( ( m_friction > 0 ) && ( dt < 0.5 * m_friction ) ) {
|
||||||
// McZapkie-281102: zabezpieczenie przed oscylacjami dla dlugich czasow
|
// McZapkie-281102: zabezpieczenie przed oscylacjami dla dlugich czasow
|
||||||
fValue += dt * ( fDesiredValue - fValue ) / fFriction;
|
m_value += dt * ( m_targetvalue - m_value ) / m_friction;
|
||||||
if( std::abs( fDesiredValue - fValue ) <= 0.0001 ) {
|
if( std::abs( m_targetvalue - m_value ) <= 0.0001 ) {
|
||||||
// close enough, we can stop updating the model
|
// close enough, we can stop updating the model
|
||||||
fValue = fDesiredValue; // set it exactly as requested just in case it matters
|
m_value = m_targetvalue; // set it exactly as requested just in case it matters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fValue = fDesiredValue;
|
m_value = m_targetvalue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( SubModel )
|
if( SubModel )
|
||||||
{ // warunek na wszelki wypadek, gdyby się submodel nie podłączył
|
{ // warunek na wszelki wypadek, gdyby się submodel nie podłączył
|
||||||
TSubModel *sm;
|
switch (m_type) {
|
||||||
switch (eType)
|
case gt_Rotate: {
|
||||||
{
|
SubModel->SetRotate( float3( 0, 1, 0 ), GetScaledValue() * 360.0 );
|
||||||
case gt_Rotate:
|
break;
|
||||||
SubModel->SetRotate(float3(0, 1, 0), fValue * 360.0);
|
|
||||||
break;
|
|
||||||
case gt_Move:
|
|
||||||
SubModel->SetTranslate(float3(0, 0, fValue));
|
|
||||||
break;
|
|
||||||
case gt_Wiper:
|
|
||||||
SubModel->SetRotate(float3(0, 1, 0), fValue * 360.0);
|
|
||||||
sm = SubModel->ChildGet();
|
|
||||||
if (sm)
|
|
||||||
{
|
|
||||||
sm->SetRotate(float3(0, 1, 0), fValue * 360.0);
|
|
||||||
sm = sm->ChildGet();
|
|
||||||
if (sm)
|
|
||||||
sm->SetRotate(float3(0, 1, 0), fValue * 360.0);
|
|
||||||
}
|
}
|
||||||
break;
|
case gt_Move: {
|
||||||
case gt_Digital: // Ra 2014-07: licznik cyfrowy
|
SubModel->SetTranslate( float3( 0, 0, GetScaledValue() ) );
|
||||||
sm = SubModel->ChildGet();
|
break;
|
||||||
/* std::string n = FormatFloat( "0000000000", floor( fValue ) ); // na razie tak trochę bez sensu
|
}
|
||||||
*/ std::string n( "000000000" + std::to_string( static_cast<int>( std::floor( fValue ) ) ) );
|
case gt_Wiper: {
|
||||||
if( n.length() > 10 ) { n.erase( 0, n.length() - 10 ); } // also dumb but should work for now
|
auto const scaledvalue { GetScaledValue() };
|
||||||
do
|
SubModel->SetRotate( float3( 0, 1, 0 ), scaledvalue * 360.0 );
|
||||||
{ // pętla po submodelach potomnych i obracanie ich o kąt zależy od cyfry w (fValue)
|
auto *sm = SubModel->ChildGet();
|
||||||
if( sm->pName.size() ) {
|
if( sm ) {
|
||||||
// musi mieć niepustą nazwę
|
sm->SetRotate( float3( 0, 1, 0 ), scaledvalue * 360.0 );
|
||||||
if( ( sm->pName[ 0 ] >= '0' )
|
sm = sm->ChildGet();
|
||||||
&& ( sm->pName[ 0 ] <= '9' ) ) {
|
if( sm )
|
||||||
|
sm->SetRotate( float3( 0, 1, 0 ), scaledvalue * 360.0 );
|
||||||
sm->SetRotate(
|
|
||||||
float3( 0, 1, 0 ),
|
|
||||||
-36.0 * ( n[ '0' + 9 - sm->pName[ 0 ] ] - '0' ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sm = sm->NextGet();
|
break;
|
||||||
} while (sm);
|
}
|
||||||
break;
|
case gt_Digital: {
|
||||||
|
// Ra 2014-07: licznik cyfrowy
|
||||||
|
auto *sm = SubModel->ChildGet();
|
||||||
|
/* std::string n = FormatFloat( "0000000000", floor( fValue ) ); // na razie tak trochę bez sensu
|
||||||
|
*/ std::string n( "000000000" + std::to_string( static_cast<int>( std::floor( GetScaledValue() ) ) ) );
|
||||||
|
if( n.length() > 10 ) { n.erase( 0, n.length() - 10 ); } // also dumb but should work for now
|
||||||
|
do { // pętla po submodelach potomnych i obracanie ich o kąt zależy od cyfry w (fValue)
|
||||||
|
if( sm->pName.size() ) {
|
||||||
|
// musi mieć niepustą nazwę
|
||||||
|
if( ( sm->pName[ 0 ] >= '0' )
|
||||||
|
&& ( sm->pName[ 0 ] <= '9' ) ) {
|
||||||
|
|
||||||
|
sm->SetRotate(
|
||||||
|
float3( 0, 1, 0 ),
|
||||||
|
-36.0 * ( n[ '0' + 9 - sm->pName[ 0 ] ] - '0' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sm = sm->NextGet();
|
||||||
|
} while( sm );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void TGauge::AssignFloat(float *fValue)
|
void TGauge::AssignFloat(float *fValue)
|
||||||
{
|
{
|
||||||
cDataType = 'f';
|
m_datatype = 'f';
|
||||||
fData = fValue;
|
fData = fValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TGauge::AssignDouble(double *dValue)
|
void TGauge::AssignDouble(double *dValue)
|
||||||
{
|
{
|
||||||
cDataType = 'd';
|
m_datatype = 'd';
|
||||||
dData = dValue;
|
dData = dValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TGauge::AssignInt(int *iValue)
|
void TGauge::AssignInt(int *iValue)
|
||||||
{
|
{
|
||||||
cDataType = 'i';
|
m_datatype = 'i';
|
||||||
iData = iValue;
|
iData = iValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TGauge::UpdateValue()
|
void TGauge::UpdateValue()
|
||||||
{ // ustawienie wartości docelowej z parametru
|
{ // ustawienie wartości docelowej z parametru
|
||||||
switch (cDataType)
|
switch (m_datatype)
|
||||||
{ // to nie jest zbyt optymalne, można by zrobić osobne funkcje
|
{ // to nie jest zbyt optymalne, można by zrobić osobne funkcje
|
||||||
case 'f':
|
case 'f':
|
||||||
fDesiredValue = (*fData) * fScale + fOffset;
|
m_targetvalue = (*fData);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
fDesiredValue = (*dData) * fScale + fOffset;
|
m_targetvalue = (*dData);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
fDesiredValue = (*iData) * fScale + fOffset;
|
m_targetvalue = (*iData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float TGauge::GetScaledValue() const {
|
||||||
|
|
||||||
|
return (
|
||||||
|
( false == m_interpolatescale ) ?
|
||||||
|
m_value * m_scale + m_offset :
|
||||||
|
m_value
|
||||||
|
* interpolate(
|
||||||
|
m_scale, m_endscale,
|
||||||
|
clamp(
|
||||||
|
m_value / m_endvalue,
|
||||||
|
0.f, 1.f ) )
|
||||||
|
+ m_offset );
|
||||||
|
}
|
||||||
|
|
||||||
// returns offset of submodel associated with the button from the model centre
|
// returns offset of submodel associated with the button from the model centre
|
||||||
glm::vec3
|
glm::vec3
|
||||||
TGauge::model_offset() const {
|
TGauge::model_offset() const {
|
||||||
|
|||||||
38
Gauge.h
38
Gauge.h
@@ -29,16 +29,13 @@ public:
|
|||||||
TGauge() = default;
|
TGauge() = default;
|
||||||
inline
|
inline
|
||||||
void Clear() { *this = TGauge(); }
|
void Clear() { *this = TGauge(); }
|
||||||
void Init(TSubModel *NewSubModel, TGaugeType eNewTyp, double fNewScale = 1, double fNewOffset = 0, double fNewFriction = 0, double fNewValue = 0);
|
void Init(TSubModel *Submodel, TGaugeType Type, float Scale = 1, float Offset = 0, float Friction = 0, float Value = 0, float const Endvalue = -1.0, float const Endscale = -1.0, bool const Interpolate = false );
|
||||||
bool Load(cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, TModel3d *md2 = nullptr, double mul = 1.0);
|
bool Load(cParser &Parser, TDynamicObject const *Owner, TModel3d *md1, TModel3d *md2 = nullptr, double mul = 1.0);
|
||||||
void PermIncValue(double fNewDesired);
|
void UpdateValue( float fNewDesired );
|
||||||
void IncValue(double fNewDesired);
|
void UpdateValue( float fNewDesired, sound_source &Fallbacksound );
|
||||||
void DecValue(double fNewDesired);
|
void PutValue(float fNewDesired);
|
||||||
void UpdateValue( double fNewDesired );
|
float GetValue() const;
|
||||||
void UpdateValue( double fNewDesired, sound_source &Fallbacksound );
|
float GetDesiredValue() const;
|
||||||
void PutValue(double fNewDesired);
|
|
||||||
double GetValue() const;
|
|
||||||
double GetDesiredValue() const;
|
|
||||||
void Update();
|
void Update();
|
||||||
void AssignFloat(float *fValue);
|
void AssignFloat(float *fValue);
|
||||||
void AssignDouble(double *dValue);
|
void AssignDouble(double *dValue);
|
||||||
@@ -54,15 +51,22 @@ private:
|
|||||||
// imports member data pair from the config file
|
// imports member data pair from the config file
|
||||||
bool
|
bool
|
||||||
Load_mapping( cParser &Input );
|
Load_mapping( cParser &Input );
|
||||||
void UpdateValue( double fNewDesired, sound_source *Fallbacksound );
|
void
|
||||||
|
UpdateValue( float fNewDesired, sound_source *Fallbacksound );
|
||||||
|
float
|
||||||
|
GetScaledValue() const;
|
||||||
|
|
||||||
// members
|
// members
|
||||||
TGaugeType eType { gt_Unknown }; // typ ruchu
|
TGaugeType m_type { gt_Unknown }; // typ ruchu
|
||||||
double fFriction { 0.0 }; // hamowanie przy zliżaniu się do zadanej wartości
|
float m_friction { 0.f }; // hamowanie przy zliżaniu się do zadanej wartości
|
||||||
double fDesiredValue { 0.0 }; // wartość docelowa
|
float m_targetvalue { 0.f }; // wartość docelowa
|
||||||
double fValue { 0.0 }; // wartość obecna
|
float m_value { 0.f }; // wartość obecna
|
||||||
double fOffset { 0.0 }; // wartość początkowa ("0")
|
float m_offset { 0.f }; // wartość początkowa ("0")
|
||||||
double fScale { 1.0 }; // wartość końcowa ("1")
|
float m_scale { 1.f }; // scale applied to the value at the start of accepted value range
|
||||||
char cDataType; // typ zmiennej parametru: f-float, d-double, i-int
|
float m_endscale { -1.f }; // scale applied to the value at the end of accepted value range
|
||||||
|
float m_endvalue { -1.f }; // end value of accepted value range
|
||||||
|
bool m_interpolatescale { false };
|
||||||
|
char m_datatype; // typ zmiennej parametru: f-float, d-double, i-int
|
||||||
union {
|
union {
|
||||||
// wskaźnik na parametr pokazywany przez animację
|
// wskaźnik na parametr pokazywany przez animację
|
||||||
float *fData;
|
float *fData;
|
||||||
|
|||||||
@@ -1572,7 +1572,7 @@ void TMoverParameters::WaterHeaterCheck( double const Timestep ) {
|
|||||||
&& ( true == Battery )
|
&& ( true == Battery )
|
||||||
&& ( true == WaterHeater.is_enabled )
|
&& ( true == WaterHeater.is_enabled )
|
||||||
&& ( true == WaterHeater.breaker )
|
&& ( true == WaterHeater.breaker )
|
||||||
&& ( ( WaterHeater.config.temp_min < 0 ) || ( dizel_heat.temperatura1 < WaterHeater.config.temp_min ) ) );
|
&& ( ( WaterHeater.is_active ) || ( WaterHeater.config.temp_min < 0 ) || ( dizel_heat.temperatura1 < WaterHeater.config.temp_min ) ) );
|
||||||
|
|
||||||
if( ( WaterHeater.config.temp_max > 0 )
|
if( ( WaterHeater.config.temp_max > 0 )
|
||||||
&& ( dizel_heat.temperatura1 > WaterHeater.config.temp_max ) ) {
|
&& ( dizel_heat.temperatura1 > WaterHeater.config.temp_max ) ) {
|
||||||
@@ -4555,7 +4555,7 @@ double TMoverParameters::TractionForce(double dt)
|
|||||||
// TBD, TODO: currently ignores RVentType, fix this?
|
// TBD, TODO: currently ignores RVentType, fix this?
|
||||||
RventRot += clamp( enrot - RventRot, -100.0, 50.0 ) * dt;
|
RventRot += clamp( enrot - RventRot, -100.0, 50.0 ) * dt;
|
||||||
dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt;
|
dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt;
|
||||||
dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt;
|
dizel_heat.rpmw2 += clamp( dizel_heat.rpmwz2 - dizel_heat.rpmw2, -100.f, 50.f ) * dt;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt );
|
RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt );
|
||||||
@@ -4569,7 +4569,7 @@ double TMoverParameters::TractionForce(double dt)
|
|||||||
// NOTE: we update only radiator fans, as vehicles with diesel engine don't have other ventilators
|
// NOTE: we update only radiator fans, as vehicles with diesel engine don't have other ventilators
|
||||||
if( true == Mains ) {
|
if( true == Mains ) {
|
||||||
dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt;
|
dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt;
|
||||||
dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt;
|
dizel_heat.rpmw2 += clamp( dizel_heat.rpmwz2 - dizel_heat.rpmw2, -100.f, 50.f ) * dt;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dizel_heat.rpmw *= std::max( 0.0, 1.0 - dizel_heat.rpmw * dt );
|
dizel_heat.rpmw *= std::max( 0.0, 1.0 - dizel_heat.rpmw * dt );
|
||||||
@@ -4703,11 +4703,18 @@ double TMoverParameters::TractionForce(double dt)
|
|||||||
// tmpV:=V*CabNo*ActiveDir;
|
// tmpV:=V*CabNo*ActiveDir;
|
||||||
auto const tmpV { nrot * Pirazy2 * 0.5 * WheelDiameter * DirAbsolute }; //*CabNo*ActiveDir;
|
auto const tmpV { nrot * Pirazy2 * 0.5 * WheelDiameter * DirAbsolute }; //*CabNo*ActiveDir;
|
||||||
// jazda manewrowa
|
// jazda manewrowa
|
||||||
if (ShuntMode)
|
if( true == ShuntMode ) {
|
||||||
{
|
if( ( true == Mains ) && ( MainCtrlPos > 0 ) ) {
|
||||||
Voltage = (SST[MainCtrlPos].Umax * AnPos) + (SST[MainCtrlPos].Umin * (1.0 - AnPos));
|
Voltage = ( SST[ MainCtrlPos ].Umax * AnPos ) + ( SST[ MainCtrlPos ].Umin * ( 1.0 - AnPos ) );
|
||||||
tmp = (SST[MainCtrlPos].Pmax * AnPos) + (SST[MainCtrlPos].Pmin * (1.0 - AnPos));
|
// NOTE: very crude way to approximate power generated at current rpm instead of instant top output
|
||||||
Ft = tmp * 1000.0 / (abs(tmpV) + 1.6);
|
auto const rpmratio { 60.0 * enrot / DElist[ MainCtrlPos ].RPM };
|
||||||
|
tmp = rpmratio * ( SST[ MainCtrlPos ].Pmax * AnPos ) + ( SST[ MainCtrlPos ].Pmin * ( 1.0 - AnPos ) );
|
||||||
|
Ft = tmp * 1000.0 / ( abs( tmpV ) + 1.6 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Voltage = 0;
|
||||||
|
Ft = 0;
|
||||||
|
}
|
||||||
PosRatio = 1;
|
PosRatio = 1;
|
||||||
}
|
}
|
||||||
else // jazda ciapongowa
|
else // jazda ciapongowa
|
||||||
|
|||||||
20
Train.cpp
20
Train.cpp
@@ -757,7 +757,7 @@ void TTrain::OnCommand_secondcontrollerincrease( TTrain *Train, command_data con
|
|||||||
// on press or hold
|
// on press or hold
|
||||||
if( Train->mvControlled->ShuntMode ) {
|
if( Train->mvControlled->ShuntMode ) {
|
||||||
Train->mvControlled->AnPos = clamp(
|
Train->mvControlled->AnPos = clamp(
|
||||||
Train->mvControlled->AnPos + ( Command.time_delta * 1.0f ),
|
Train->mvControlled->AnPos + ( Command.time_delta * 2.0 ),
|
||||||
0.0, 1.0 );
|
0.0, 1.0 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -818,7 +818,7 @@ void TTrain::OnCommand_secondcontrollerdecrease( TTrain *Train, command_data con
|
|||||||
// on press or hold
|
// on press or hold
|
||||||
if( Train->mvControlled->ShuntMode ) {
|
if( Train->mvControlled->ShuntMode ) {
|
||||||
Train->mvControlled->AnPos = clamp(
|
Train->mvControlled->AnPos = clamp(
|
||||||
Train->mvControlled->AnPos - ( Command.time_delta * 1.0f ),
|
Train->mvControlled->AnPos - ( Command.time_delta * 2.0 ),
|
||||||
0.0, 1.0 );
|
0.0, 1.0 );
|
||||||
}
|
}
|
||||||
Train->mvControlled->DecScndCtrl( 1 );
|
Train->mvControlled->DecScndCtrl( 1 );
|
||||||
@@ -4867,6 +4867,7 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
btLampkaNadmPrzetwB.Turn( tmp->MoverParameters->ConvOvldFlag ); // nadmiarowy przetwornicy?
|
btLampkaNadmPrzetwB.Turn( tmp->MoverParameters->ConvOvldFlag ); // nadmiarowy przetwornicy?
|
||||||
btLampkaPrzetwB.Turn( tmp->MoverParameters->ConverterFlag ); // zalaczenie przetwornicy
|
btLampkaPrzetwB.Turn( tmp->MoverParameters->ConverterFlag ); // zalaczenie przetwornicy
|
||||||
btLampkaPrzetwBOff.Turn( false == tmp->MoverParameters->ConverterFlag );
|
btLampkaPrzetwBOff.Turn( false == tmp->MoverParameters->ConverterFlag );
|
||||||
|
btLampkaMalfunctionB.Turn( tmp->MoverParameters->dizel_heat.PA );
|
||||||
}
|
}
|
||||||
else // wylaczone
|
else // wylaczone
|
||||||
{
|
{
|
||||||
@@ -4881,6 +4882,7 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
btLampkaNadmPrzetwB.Turn( false );
|
btLampkaNadmPrzetwB.Turn( false );
|
||||||
btLampkaPrzetwB.Turn( false );
|
btLampkaPrzetwB.Turn( false );
|
||||||
btLampkaPrzetwBOff.Turn( false );
|
btLampkaPrzetwBOff.Turn( false );
|
||||||
|
btLampkaMalfunctionB.Turn( false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6306,6 +6308,7 @@ void TTrain::clear_cab_controls()
|
|||||||
btCabLight.Clear(); // hunter-171012
|
btCabLight.Clear(); // hunter-171012
|
||||||
// others
|
// others
|
||||||
btLampkaMalfunction.Clear();
|
btLampkaMalfunction.Clear();
|
||||||
|
btLampkaMalfunctionB.Clear();
|
||||||
btLampkaMotorBlowers.Clear();
|
btLampkaMotorBlowers.Clear();
|
||||||
|
|
||||||
ggLeftLightButton.Clear();
|
ggLeftLightButton.Clear();
|
||||||
@@ -6615,6 +6618,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
|
|||||||
{ "i-contactorsb:", btLampkaStycznB },
|
{ "i-contactorsb:", btLampkaStycznB },
|
||||||
{ "i-conv_ovldb:", btLampkaNadmPrzetwB },
|
{ "i-conv_ovldb:", btLampkaNadmPrzetwB },
|
||||||
{ "i-malfunction:", btLampkaMalfunction },
|
{ "i-malfunction:", btLampkaMalfunction },
|
||||||
|
{ "i-malfunctionb:", btLampkaMalfunctionB },
|
||||||
{ "i-forward:", btLampkaForward },
|
{ "i-forward:", btLampkaForward },
|
||||||
{ "i-backward:", btLampkaBackward },
|
{ "i-backward:", btLampkaBackward },
|
||||||
{ "i-upperlight:", btLampkaUpperLight },
|
{ "i-upperlight:", btLampkaUpperLight },
|
||||||
@@ -6937,9 +6941,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
|||||||
if (Parser.getToken<std::string>() == "analog")
|
if (Parser.getToken<std::string>() == "analog")
|
||||||
{
|
{
|
||||||
// McZapkie-300302: zegarek
|
// McZapkie-300302: zegarek
|
||||||
ggClockSInd.Init(DynamicObject->mdKabina->GetFromName("ClockShand"), gt_Rotate, 1.0/60.0, 0, 0);
|
ggClockSInd.Init(DynamicObject->mdKabina->GetFromName("ClockShand"), gt_Rotate, 1.0/60.0);
|
||||||
ggClockMInd.Init(DynamicObject->mdKabina->GetFromName("ClockMhand"), gt_Rotate, 1.0/60.0, 0, 0);
|
ggClockMInd.Init(DynamicObject->mdKabina->GetFromName("ClockMhand"), gt_Rotate, 1.0/60.0);
|
||||||
ggClockHInd.Init(DynamicObject->mdKabina->GetFromName("ClockHhand"), gt_Rotate, 1.0/12.0, 0, 0);
|
ggClockHInd.Init(DynamicObject->mdKabina->GetFromName("ClockHhand"), gt_Rotate, 1.0/12.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Label == "evoltage:")
|
else if (Label == "evoltage:")
|
||||||
@@ -7002,6 +7006,12 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
|||||||
gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina);
|
gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina);
|
||||||
gauge.AssignDouble(&mvControlled->DistCounter);
|
gauge.AssignDouble(&mvControlled->DistCounter);
|
||||||
}
|
}
|
||||||
|
else if( Label == "shuntmodepower:" ) {
|
||||||
|
// shunt mode power slider
|
||||||
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
||||||
|
gauge.Load(Parser, DynamicObject, DynamicObject->mdKabina);
|
||||||
|
gauge.AssignDouble(&mvControlled->AnPos);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// failed to match the label
|
// failed to match the label
|
||||||
|
|||||||
1
Train.h
1
Train.h
@@ -512,6 +512,7 @@ public: // reszta może by?publiczna
|
|||||||
TButton btLampkaRearRightEndLight;
|
TButton btLampkaRearRightEndLight;
|
||||||
// other
|
// other
|
||||||
TButton btLampkaMalfunction;
|
TButton btLampkaMalfunction;
|
||||||
|
TButton btLampkaMalfunctionB;
|
||||||
TButton btLampkaMotorBlowers;
|
TButton btLampkaMotorBlowers;
|
||||||
|
|
||||||
TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine
|
TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine
|
||||||
|
|||||||
Reference in New Issue
Block a user