mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 18:39:18 +02:00
Merge branch 'tmj-dev' into milek-dev
This commit is contained in:
102
AnimModel.cpp
102
AnimModel.cpp
@@ -446,7 +446,8 @@ bool TAnimModel::Init(std::string const &asName, std::string const &asReplacable
|
||||
m_materialdata.textures_alpha = 0x30300030;
|
||||
}
|
||||
|
||||
fBlinkTimer = double( Random( 1000 * fOffTime ) ) / ( 1000 * fOffTime );
|
||||
// TODO: redo the random timer initialization
|
||||
// fBlinkTimer = Random() * ( fOnTime + fOffTime );
|
||||
|
||||
pModel = TModelsManager::GetModel( asName );
|
||||
return ( pModel != nullptr );
|
||||
@@ -548,9 +549,73 @@ void TAnimModel::RaAnimate( unsigned int const Framestamp ) {
|
||||
|
||||
if( Framestamp == m_framestamp ) { return; }
|
||||
|
||||
fBlinkTimer -= Timer::GetDeltaTime();
|
||||
if( fBlinkTimer <= 0 )
|
||||
fBlinkTimer += fOffTime;
|
||||
auto const timedelta { Timer::GetDeltaTime() };
|
||||
|
||||
// interpretacja ułamka zależnie od typu
|
||||
// case ls_Off: ustalenie czasu migotania, t<1s (f>1Hz), np. 0.1 => t=0.1 (f=10Hz)
|
||||
// case ls_On: ustalenie wypełnienia ułamkiem, np. 1.25 => zapalony przez 1/4 okresu
|
||||
// case ls_Blink: ustalenie częstotliwości migotania, f<1Hz (t>1s), np. 2.2 => f=0.2Hz (t=5s)
|
||||
float modeintegral, modefractional;
|
||||
for( int idx = 0; idx < iNumLights; ++idx ) {
|
||||
|
||||
modefractional = std::modf( std::abs( lsLights[ idx ] ), &modeintegral );
|
||||
|
||||
if( modeintegral >= ls_Dark ) {
|
||||
// light threshold modes don't use timers
|
||||
continue;
|
||||
}
|
||||
auto const mode { static_cast<int>( modeintegral ) };
|
||||
|
||||
auto &opacity { m_lightopacities[ idx ] };
|
||||
auto &timer { m_lighttimers[ idx ] };
|
||||
if( ( modeintegral < ls_Blink ) && ( modefractional < 0.01f ) ) {
|
||||
// simple flip modes
|
||||
switch( mode ) {
|
||||
case ls_Off: {
|
||||
// reduce to zero
|
||||
timer = std::max<float>( 0.f, timer - timedelta );
|
||||
break;
|
||||
}
|
||||
case ls_On: {
|
||||
// increase to max value
|
||||
timer = std::min<float>( fTransitionTime, timer + timedelta );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
opacity = timer / fTransitionTime;
|
||||
}
|
||||
else {
|
||||
// blink modes
|
||||
auto const ontime { (
|
||||
( mode == ls_Blink ) ? ( ( modefractional < 0.01f ) ? fOnTime : ( 1.f / modefractional ) * 0.5f ) :
|
||||
( mode == ls_Off ) ? modefractional * 0.5f :
|
||||
( mode == ls_On ) ? modefractional * ( fOnTime + fOffTime ) :
|
||||
fOnTime ) }; // fallback
|
||||
auto const offtime { (
|
||||
( mode == ls_Blink ) ? ( ( modefractional < 0.01f ) ? fOffTime : ontime ) :
|
||||
( mode == ls_Off ) ? ontime :
|
||||
( mode == ls_On ) ? ( fOnTime + fOffTime ) - ontime :
|
||||
fOffTime ) }; // fallback
|
||||
auto const transitiontime {
|
||||
std::min(
|
||||
1.f,
|
||||
std::min( ontime, offtime ) * 0.9f ) };
|
||||
|
||||
timer = clamp_circular<float>( timer + timedelta * ( lsLights[ idx ] > 0.f ? 1.f : -1.f ), ontime + offtime );
|
||||
// set opacity depending on blink stage
|
||||
if( timer < ontime ) {
|
||||
// blink on
|
||||
opacity = clamp( timer / transitiontime, 0.f, 1.f );
|
||||
}
|
||||
else {
|
||||
// blink off
|
||||
opacity = 1.f - clamp( ( timer - ontime ) / transitiontime, 0.f, 1.f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ra 2F1I: to by można pomijać dla modeli bez animacji, których jest większość
|
||||
TAnimContainer *pCurrent;
|
||||
@@ -569,17 +634,19 @@ void TAnimModel::RaPrepare()
|
||||
bool state; // stan światła
|
||||
for (int i = 0; i < iNumLights; ++i)
|
||||
{
|
||||
auto const lightmode { static_cast<int>( lsLights[ i ] ) };
|
||||
auto const lightmode { static_cast<int>( std::abs( lsLights[ i ] ) ) };
|
||||
switch( lightmode ) {
|
||||
case ls_On:
|
||||
case ls_Off: {
|
||||
// zapalony albo zgaszony
|
||||
state = ( lightmode == ls_On );
|
||||
break;
|
||||
}
|
||||
case ls_Off:
|
||||
case ls_Blink: {
|
||||
// migotanie
|
||||
state = ( fBlinkTimer < fOnTime );
|
||||
if (LightsOn[i]) {
|
||||
LightsOn[i]->iVisible = ( m_lightopacities[i] > 0.f );
|
||||
LightsOn[i]->SetVisibilityLevel( m_lightopacities[i], true, false );
|
||||
}
|
||||
if (LightsOff[i]) {
|
||||
LightsOff[i]->iVisible = ( m_lightopacities[i] < 1.f );
|
||||
LightsOff[i]->SetVisibilityLevel( 1.f, true, false );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ls_Dark: {
|
||||
@@ -607,11 +674,17 @@ void TAnimModel::RaPrepare()
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (LightsOn[i])
|
||||
if( lightmode >= ls_Dark ) {
|
||||
// crude as hell but for test will do :x
|
||||
if (LightsOn[i]) {
|
||||
LightsOn[i]->iVisible = state;
|
||||
// TODO: set visibility for the entire submodel's children as well
|
||||
LightsOn[i]->fVisible = m_lightopacities[i];
|
||||
}
|
||||
if (LightsOff[i])
|
||||
LightsOff[i]->iVisible = !state;
|
||||
}
|
||||
}
|
||||
TSubModel::iInstance = reinterpret_cast<std::uintptr_t>( this ); //żeby nie robić cudzych animacji
|
||||
TSubModel::pasText = &asText; // przekazanie tekstu do wyświetlacza (!!!! do przemyślenia)
|
||||
if (pAdvanced) // jeśli jest zaawansowana animacja
|
||||
@@ -775,8 +848,9 @@ void TAnimModel::AnimationVND(void *pData, double a, double b, double c, double
|
||||
//---------------------------------------------------------------------------
|
||||
void TAnimModel::LightSet(int const n, float const v)
|
||||
{ // ustawienie światła (n) na wartość (v)
|
||||
if (n >= iMaxNumLights)
|
||||
if( n >= iMaxNumLights ) {
|
||||
return; // przekroczony zakres
|
||||
}
|
||||
lsLights[ n ] = v;
|
||||
};
|
||||
|
||||
|
||||
11
AnimModel.h
11
AnimModel.h
@@ -179,7 +179,7 @@ private:
|
||||
// members
|
||||
TAnimContainer *pRoot { nullptr }; // pojemniki sterujące, tylko dla aniomowanych submodeli
|
||||
TModel3d *pModel { nullptr };
|
||||
double fBlinkTimer { 0.0 };
|
||||
// double fBlinkTimer { 0.0 };
|
||||
int iNumLights { 0 };
|
||||
TSubModel *LightsOn[ iMaxNumLights ]; // Ra: te wskaźniki powinny być w ramach TModel3d
|
||||
TSubModel *LightsOff[ iMaxNumLights ];
|
||||
@@ -188,10 +188,13 @@ private:
|
||||
|
||||
std::string asText; // tekst dla wyświetlacza znakowego
|
||||
TAnimAdvanced *pAdvanced { nullptr };
|
||||
// TODO: wrap into a light state struct
|
||||
float lsLights[ iMaxNumLights ];
|
||||
// float fDark { DefaultDarkThresholdLevel }; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?)
|
||||
float fOnTime { 0.66f };
|
||||
float fOffTime { 0.66f + 0.66f }; // były stałymi, teraz mogą być zmienne dla każdego egzemplarza
|
||||
std::array<float, iMaxNumLights> m_lighttimers { 0.f };
|
||||
std::array<float, iMaxNumLights> m_lightopacities { 1.f };
|
||||
float fOnTime { 1.f / 2 };// { 60.f / 45.f / 2 };
|
||||
float fOffTime { 1.f / 2 };// { 60.f / 45.f / 2 }; // były stałymi, teraz mogą być zmienne dla każdego egzemplarza
|
||||
float fTransitionTime { fOnTime * 0.9f }; // time
|
||||
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
|
||||
};
|
||||
|
||||
|
||||
@@ -105,9 +105,17 @@ set(SOURCES
|
||||
"imgui/imgui_demo.cpp"
|
||||
"imgui/imgui_draw.cpp"
|
||||
"imgui/imgui_impl_glfw.cpp"
|
||||
"imgui/imgui_impl_opengl3.cpp"
|
||||
)
|
||||
|
||||
option(USE_IMGUI_GL3 "Use OpenGL3+ imgui implementation" OFF)
|
||||
|
||||
if (USE_IMGUI_GL3)
|
||||
set(SOURCES ${SOURCES} "imgui/imgui_impl_opengl3.cpp")
|
||||
else()
|
||||
add_definitions(-DEU07_USEIMGUIIMPLOPENGL2)
|
||||
set(SOURCES ${SOURCES} "imgui/imgui_impl_opengl2.cpp")
|
||||
endif()
|
||||
|
||||
set (PREFIX "")
|
||||
|
||||
if (WIN32)
|
||||
|
||||
260
Driver.cpp
260
Driver.cpp
@@ -339,8 +339,8 @@ std::string TSpeedPos::TableText() const
|
||||
{ // pozycja tabelki pr?dko?ci
|
||||
if (iFlags & spEnabled)
|
||||
{ // o ile pozycja istotna
|
||||
return "Flags:" + to_hex_str(iFlags, 8) + ", Dist:" + to_string(fDist, 1, 6) +
|
||||
", Vel:" + (fVelNext == -1.0 ? " - " : to_string(static_cast<int>(fVelNext), 0, 3)) + ", Name:" + GetName();
|
||||
return to_hex_str(iFlags, 8) + " " + to_string(fDist, 1, 6) +
|
||||
" " + (fVelNext == -1.0 ? " -" : to_string(static_cast<int>(fVelNext), 0, 3)) + " " + GetName();
|
||||
}
|
||||
return "Empty";
|
||||
}
|
||||
@@ -2437,6 +2437,11 @@ bool TController::PrepareEngine()
|
||||
mvOccupied->ConverterSwitch( true );
|
||||
// w EN57 sprężarka w ra jest zasilana z silnikowego
|
||||
mvOccupied->CompressorSwitch( true );
|
||||
// enable motor blowers
|
||||
mvOccupied->MotorBlowersSwitchOff( false, side::front );
|
||||
mvOccupied->MotorBlowersSwitch( true, side::front );
|
||||
mvOccupied->MotorBlowersSwitchOff( false, side::rear );
|
||||
mvOccupied->MotorBlowersSwitch( true, side::rear );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -4254,123 +4259,6 @@ TController::UpdateSituation(double dt) {
|
||||
fMaxProximityDist = 10.0; //[m]
|
||||
fVelPlus = 1.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
|
||||
fVelMinus = 0.5; // margines prędkości powodujący załączenie napędu
|
||||
if (AIControllFlag) {
|
||||
if (iVehicleCount >= 0) {
|
||||
// jeśli była podana ilość wagonów
|
||||
if (iDrivigFlags & movePress) {
|
||||
// jeśli dociskanie w celu odczepienia
|
||||
// 3. faza odczepiania.
|
||||
SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2
|
||||
if ((mvControlling->MainCtrlPos > 0) ||
|
||||
(mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic)) // jeśli jazda
|
||||
{
|
||||
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute));
|
||||
TDynamicObject *p =
|
||||
pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI
|
||||
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
|
||||
int n = iVehicleCount; // ile wagonów ma zostać
|
||||
do
|
||||
{ // szukanie pojazdu do odczepienia
|
||||
d = p->DirectionGet() > 0 ?
|
||||
0 :
|
||||
1; // numer sprzęgu od strony czoła składu
|
||||
// if (p->MoverParameters->Couplers[d].CouplerType==Articulated)
|
||||
// //jeśli sprzęg typu wózek (za mało)
|
||||
if (p->MoverParameters->Couplers[d].CouplingFlag &
|
||||
ctrain_depot) // jeżeli sprzęg zablokowany
|
||||
// if (p->GetTrack()->) //a nie stoi na torze warsztatowym
|
||||
// (ustalić po czym poznać taki tor)
|
||||
++n; // to liczymy człony jako jeden
|
||||
p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać
|
||||
p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował
|
||||
if (n)
|
||||
{ // jeśli jeszcze nie koniec
|
||||
p = p->Prev(); // kolejny w stronę czoła składu (licząc od
|
||||
// tyłu), bo dociskamy
|
||||
if (!p)
|
||||
iVehicleCount = -2,
|
||||
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
|
||||
}
|
||||
} while (n--);
|
||||
if( p ? p->MoverParameters->Couplers[ d ].CouplingFlag == coupling::faux : true ) {
|
||||
// no target, or already just virtual coupling
|
||||
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
|
||||
iVehicleCount = -2; // odczepiono, co było do odczepienia
|
||||
} else if ( p->Dettach(d) == coupling::faux ) {
|
||||
// tylko jeśli odepnie
|
||||
WriteLog( mvOccupied->Name + " odczepiony." );
|
||||
iVehicleCount = -2;
|
||||
} // a jak nie, to dociskać dalej
|
||||
}
|
||||
if (iVehicleCount >= 0) // zmieni się po odczepieniu
|
||||
if (!mvOccupied->DecLocalBrakeLevel(1))
|
||||
{ // dociśnij sklad
|
||||
WriteLog( mvOccupied->Name + " dociskanie..." );
|
||||
// mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę
|
||||
// Ready=true; //zamiast sprawdzenia odhamowania całego składu
|
||||
IncSpeed(); // dla (Ready)==false nie ruszy
|
||||
}
|
||||
}
|
||||
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
|
||||
{ // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij
|
||||
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach
|
||||
// powino zostać wyłączone)
|
||||
// WriteLog("Zahamowanie składu");
|
||||
mvOccupied->BrakeLevelSet(
|
||||
mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
|
||||
1 :
|
||||
3 );
|
||||
double p = mvOccupied->BrakePressureActual.PipePressureVal;
|
||||
if( p < 3.9 ) {
|
||||
// tu może być 0 albo -1 nawet
|
||||
// TODO: zabezpieczenie przed dziwnymi CHK do czasu wyjaśnienia sensu 0 oraz -1 w tym miejscu
|
||||
p = 3.9;
|
||||
}
|
||||
if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
|
||||
mvOccupied->BrakePress > 2 :
|
||||
mvOccupied->PipePress < p + 0.1)
|
||||
{ // jeśli w miarę został zahamowany (ciśnienie mniejsze niż podane na
|
||||
// pozycji 3, zwyle 0.37)
|
||||
if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic)
|
||||
mvOccupied->BrakeLevelSet(0); // wyłączenie EP, gdy wystarczy (może
|
||||
// nie być potrzebne, bo na początku
|
||||
// jest)
|
||||
WriteLog("Luzowanie lokomotywy i zmiana kierunku");
|
||||
mvOccupied->BrakeReleaser(1); // wyluzuj lokomotywę; a ST45?
|
||||
mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca
|
||||
iDrivigFlags |= movePress; // następnie będzie dociskanie
|
||||
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie)
|
||||
CheckVehicles(); // od razu zmienić światła (zgasić) - bez tego się nie odczepi
|
||||
/*
|
||||
// NOTE: disabled to prevent closing the door before passengers can disembark
|
||||
fStopTime = 0.0; // nie ma na co czekać z odczepianiem
|
||||
*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( mvOccupied->Vel > 0.01 ) {
|
||||
// 1st phase(?)
|
||||
// bring it to stop if it's not already stopped
|
||||
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
|
||||
}
|
||||
}
|
||||
} // odczepiania
|
||||
else // to poniżej jeśli ilość wagonów ujemna
|
||||
if (iDrivigFlags & movePress)
|
||||
{ // 4. faza odczepiania: zwolnij i zmień kierunek
|
||||
SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie
|
||||
if (!DecSpeed()) // jeśli już bardziej wyłączyć się nie da
|
||||
{ // ponowna zmiana kierunku
|
||||
WriteLog( mvOccupied->Name + " ponowna zmiana kierunku" );
|
||||
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na właściwy
|
||||
iDrivigFlags &= ~movePress; // koniec dociskania
|
||||
JumpToNextOrder(); // zmieni światła
|
||||
TableClear(); // skanowanie od nowa
|
||||
iDrivigFlags &= ~moveStartHorn; // bez trąbienia przed ruszeniem
|
||||
SetVelocity(fShuntVelocity, fShuntVelocity); // ustawienie prędkości jazdy
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Shunt: {
|
||||
@@ -4585,10 +4473,13 @@ TController::UpdateSituation(double dt) {
|
||||
}
|
||||
|
||||
// ustalanie zadanej predkosci
|
||||
if (iDrivigFlags & moveActive) // jeśli może skanować sygnały i reagować na komendy
|
||||
{ // jeśli jest wybrany kierunek jazdy, można ustalić prędkość jazdy
|
||||
// Ra: tu by jeszcze trzeba było wstawić uzależnienie (VelDesired) od odległości od
|
||||
// przeszkody
|
||||
if (iDrivigFlags & moveActive) {
|
||||
|
||||
SetDriverPsyche(); // ustawia AccPreferred (potrzebne tu?)
|
||||
|
||||
// jeśli może skanować sygnały i reagować na komendy
|
||||
// jeśli jest wybrany kierunek jazdy, można ustalić prędkość jazdy
|
||||
// Ra: tu by jeszcze trzeba było wstawić uzależnienie (VelDesired) od odległości od przeszkody
|
||||
// no chyba żeby to uwzgldnić już w (ActualProximityDist)
|
||||
VelDesired = fVelMax; // wstępnie prędkość maksymalna dla pojazdu(-ów), będzie
|
||||
// następnie ograniczana
|
||||
@@ -4597,9 +4488,6 @@ TController::UpdateSituation(double dt) {
|
||||
// jeśli ma rozkład i ograniczenie w rozkładzie to nie przekraczać rozkladowej
|
||||
VelDesired = min_speed( VelDesired, TrainParams->TTVmax );
|
||||
}
|
||||
|
||||
SetDriverPsyche(); // ustawia AccPreferred (potrzebne tu?)
|
||||
|
||||
// szukanie optymalnych wartości
|
||||
AccDesired = AccPreferred; // AccPreferred wynika z osobowości mechanika
|
||||
VelNext = VelDesired; // maksymalna prędkość wynikająca z innych czynników niż trajektoria ruchu
|
||||
@@ -4647,6 +4535,126 @@ TController::UpdateSituation(double dt) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// disconnect mode potentially overrides scan results
|
||||
// TBD: when in this mode skip scanning altogether?
|
||||
if( ( OrderCurrentGet() & Disconnect ) != 0 ) {
|
||||
|
||||
if (AIControllFlag) {
|
||||
if (iVehicleCount >= 0) {
|
||||
// jeśli była podana ilość wagonów
|
||||
if (iDrivigFlags & movePress) {
|
||||
// jeśli dociskanie w celu odczepienia
|
||||
// 3. faza odczepiania.
|
||||
SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2
|
||||
if ((mvControlling->MainCtrlPos > 0) ||
|
||||
(mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic)) // jeśli jazda
|
||||
{
|
||||
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute));
|
||||
TDynamicObject *p =
|
||||
pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI
|
||||
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
|
||||
int n = iVehicleCount; // ile wagonów ma zostać
|
||||
do
|
||||
{ // szukanie pojazdu do odczepienia
|
||||
d = p->DirectionGet() > 0 ?
|
||||
0 :
|
||||
1; // numer sprzęgu od strony czoła składu
|
||||
// if (p->MoverParameters->Couplers[d].CouplerType==Articulated)
|
||||
// //jeśli sprzęg typu wózek (za mało)
|
||||
if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany
|
||||
// if (p->GetTrack()->) //a nie stoi na torze warsztatowym
|
||||
// (ustalić po czym poznać taki tor)
|
||||
++n; // to liczymy człony jako jeden
|
||||
p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać
|
||||
p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował
|
||||
if (n)
|
||||
{ // jeśli jeszcze nie koniec
|
||||
p = p->Prev(); // kolejny w stronę czoła składu (licząc od
|
||||
// tyłu), bo dociskamy
|
||||
if (!p)
|
||||
iVehicleCount = -2,
|
||||
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
|
||||
}
|
||||
} while (n--);
|
||||
if( p ? p->MoverParameters->Couplers[ d ].CouplingFlag == coupling::faux : true ) {
|
||||
// no target, or already just virtual coupling
|
||||
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
|
||||
iVehicleCount = -2; // odczepiono, co było do odczepienia
|
||||
} else if ( p->Dettach(d) == coupling::faux ) {
|
||||
// tylko jeśli odepnie
|
||||
WriteLog( mvOccupied->Name + " odczepiony." );
|
||||
iVehicleCount = -2;
|
||||
} // a jak nie, to dociskać dalej
|
||||
}
|
||||
if (iVehicleCount >= 0) // zmieni się po odczepieniu
|
||||
if (!mvOccupied->DecLocalBrakeLevel(1))
|
||||
{ // dociśnij sklad
|
||||
WriteLog( mvOccupied->Name + " dociskanie..." );
|
||||
// mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę
|
||||
// Ready=true; //zamiast sprawdzenia odhamowania całego składu
|
||||
IncSpeed(); // dla (Ready)==false nie ruszy
|
||||
}
|
||||
}
|
||||
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
|
||||
{ // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij
|
||||
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach
|
||||
// powino zostać wyłączone)
|
||||
// WriteLog("Zahamowanie składu");
|
||||
mvOccupied->BrakeLevelSet(
|
||||
mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
|
||||
1 :
|
||||
3 );
|
||||
double p = mvOccupied->BrakePressureActual.PipePressureVal;
|
||||
if( p < 3.9 ) {
|
||||
// tu może być 0 albo -1 nawet
|
||||
// TODO: zabezpieczenie przed dziwnymi CHK do czasu wyjaśnienia sensu 0 oraz -1 w tym miejscu
|
||||
p = 3.9;
|
||||
}
|
||||
if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
|
||||
mvOccupied->BrakePress > 2 :
|
||||
mvOccupied->PipePress < p + 0.1)
|
||||
{ // jeśli w miarę został zahamowany (ciśnienie mniejsze niż podane na
|
||||
// pozycji 3, zwyle 0.37)
|
||||
if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic)
|
||||
mvOccupied->BrakeLevelSet(0); // wyłączenie EP, gdy wystarczy (może
|
||||
// nie być potrzebne, bo na początku jest)
|
||||
WriteLog("Luzowanie lokomotywy i zmiana kierunku");
|
||||
mvOccupied->BrakeReleaser(1); // wyluzuj lokomotywę; a ST45?
|
||||
mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca
|
||||
iDrivigFlags |= movePress; // następnie będzie dociskanie
|
||||
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie)
|
||||
CheckVehicles(); // od razu zmienić światła (zgasić) - bez tego się nie odczepi
|
||||
/*
|
||||
// NOTE: disabled to prevent closing the door before passengers can disembark
|
||||
fStopTime = 0.0; // nie ma na co czekać z odczepianiem
|
||||
*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( mvOccupied->Vel > 0.01 ) {
|
||||
// 1st phase(?)
|
||||
// bring it to stop if it's not already stopped
|
||||
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
|
||||
}
|
||||
}
|
||||
} // odczepiania
|
||||
else // to poniżej jeśli ilość wagonów ujemna
|
||||
if (iDrivigFlags & movePress)
|
||||
{ // 4. faza odczepiania: zwolnij i zmień kierunek
|
||||
SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie
|
||||
if (!DecSpeed()) // jeśli już bardziej wyłączyć się nie da
|
||||
{ // ponowna zmiana kierunku
|
||||
WriteLog( mvOccupied->Name + " ponowna zmiana kierunku" );
|
||||
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na właściwy
|
||||
iDrivigFlags &= ~movePress; // koniec dociskania
|
||||
JumpToNextOrder(); // zmieni światła
|
||||
TableClear(); // skanowanie od nowa
|
||||
iDrivigFlags &= ~moveStartHorn; // bez trąbienia przed ruszeniem
|
||||
SetVelocity(fShuntVelocity, fShuntVelocity); // ustawienie prędkości jazdy
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( true == TestFlag( OrderList[ OrderPos ], Change_direction ) ) {
|
||||
// if ordered to change direction, try to stop
|
||||
|
||||
2
Driver.h
2
Driver.h
@@ -167,7 +167,7 @@ static const bool Aggressive = true;
|
||||
static const bool Easyman = false;
|
||||
static const bool AIdriver = true;
|
||||
static const bool Humandriver = false;
|
||||
static const int maxorders = 32; // ilość rozkazów w tabelce
|
||||
static const int maxorders = 64; // ilość rozkazów w tabelce
|
||||
static const int maxdriverfails = 4; // ile błędów może zrobić AI zanim zmieni nastawienie
|
||||
extern bool WriteLogFlag; // logowanie parametrów fizycznych
|
||||
static const int BrakeAccTableSize = 20;
|
||||
|
||||
57
DynObj.cpp
57
DynObj.cpp
@@ -2690,7 +2690,7 @@ void TDynamicObject::LoadUpdate() {
|
||||
}
|
||||
else if( MoverParameters->LoadAmount == 0 ) {
|
||||
// nie ma ładunku
|
||||
MoverParameters->AssignLoad( "" );
|
||||
// MoverParameters->AssignLoad( "" );
|
||||
mdLoad = nullptr;
|
||||
// erase bindings between lowpoly sections and potential load chunks placed inside them
|
||||
update_load_sections();
|
||||
@@ -5260,6 +5260,35 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
}
|
||||
}
|
||||
|
||||
else if( token == "motorblower:" ) {
|
||||
|
||||
sound_source blowertemplate { sound_placement::engine };
|
||||
blowertemplate.deserialize( parser, sound_type::single, sound_parameters::range | sound_parameters::amplitude | sound_parameters::frequency );
|
||||
blowertemplate.owner( this );
|
||||
|
||||
auto const amplitudedivisor = static_cast<float>(
|
||||
MoverParameters->MotorBlowers[ side::front ].speed > 0.f ?
|
||||
MoverParameters->MotorBlowers[ side::front ].speed * MoverParameters->nmax * 60 + MoverParameters->Power * 3 :
|
||||
MoverParameters->MotorBlowers[ side::front ].speed * -1 );
|
||||
blowertemplate.m_amplitudefactor /= amplitudedivisor;
|
||||
blowertemplate.m_frequencyfactor /= amplitudedivisor;
|
||||
|
||||
if( true == m_powertrainsounds.motors.empty() ) {
|
||||
// fallback for cases without specified motor locations, convert sound template to a single sound source
|
||||
m_powertrainsounds.motorblowers.emplace_back( blowertemplate );
|
||||
}
|
||||
else {
|
||||
// apply configuration to all defined motor blowers
|
||||
for( auto &blower : m_powertrainsounds.motorblowers ) {
|
||||
// combine potential x- and y-axis offsets of the sound template with z-axis offsets of individual blowers
|
||||
auto bloweroffset { blowertemplate.offset() };
|
||||
bloweroffset.z = blower.offset().z;
|
||||
blower = blowertemplate;
|
||||
blower.offset( bloweroffset );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if( token == "inverter:" ) {
|
||||
// plik z dzwiekiem wentylatora, mnozniki i ofsety amp. i czest.
|
||||
m_powertrainsounds.inverter.deserialize( parser, sound_type::single, sound_parameters::range | sound_parameters::amplitude | sound_parameters::frequency );
|
||||
@@ -5607,10 +5636,13 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
auto const offset { std::atof( token.c_str() ) * -1.f };
|
||||
// NOTE: we skip setting owner of the sounds, it'll be done during individual sound deserialization
|
||||
sound_source motor { sound_placement::external }; // generally traction motor
|
||||
sound_source motorblower { sound_placement::engine }; // associated motor blowers
|
||||
// add entry to the list
|
||||
auto const location { glm::vec3 { 0.f, 0.f, offset } };
|
||||
motor.offset( location );
|
||||
m_powertrainsounds.motors.emplace_back( motor );
|
||||
motorblower.offset( location );
|
||||
m_powertrainsounds.motorblowers.emplace_back( motorblower );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6714,6 +6746,27 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
|
||||
motor.stop();
|
||||
}
|
||||
}
|
||||
// motor blowers
|
||||
if( false == motorblowers.empty() ) {
|
||||
for( auto &blowersound : motorblowers ) {
|
||||
// match the motor blower and the sound source based on whether they're located in the front or the back of the vehicle
|
||||
auto const &blower { Vehicle.MotorBlowers[ ( blowersound.offset().z > 0 ? side::front : side::rear ) ] };
|
||||
if( blower.revolutions > 1 ) {
|
||||
|
||||
blowersound
|
||||
.pitch(
|
||||
true == blowersound.is_combined() ?
|
||||
blower.revolutions * 0.01f :
|
||||
blowersound.m_frequencyoffset + blowersound.m_frequencyfactor * blower.revolutions )
|
||||
.gain( blowersound.m_amplitudeoffset + blowersound.m_amplitudefactor * blower.revolutions )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
blowersound.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// inverter sounds
|
||||
if( Vehicle.EngineType == TEngineType::ElectricInductionMotor ) {
|
||||
if( Vehicle.InverterFrequency > 0.1 ) {
|
||||
@@ -7020,7 +7073,7 @@ vehicle_table::erase_disabled() {
|
||||
if( ( simulation::Train != nullptr )
|
||||
&& ( simulation::Train->Dynamic() == vehicle ) ) {
|
||||
// clear potential train binding
|
||||
// TBD, TODO: manually eject the driver first ?
|
||||
// TBD, TODO: kill vehicle sounds
|
||||
SafeDelete( simulation::Train );
|
||||
}
|
||||
// remove potential entries in the light array
|
||||
|
||||
1
DynObj.h
1
DynObj.h
@@ -328,6 +328,7 @@ private:
|
||||
|
||||
struct powertrain_sounds {
|
||||
sound_source inverter { sound_placement::engine };
|
||||
std::vector<sound_source> motorblowers;
|
||||
std::vector<sound_source> motors; // generally traction motor(s)
|
||||
double motor_volume { 0.0 }; // MC: pomocnicze zeby gladziej silnik buczal
|
||||
float motor_momentum { 0.f }; // recent change in motor revolutions
|
||||
|
||||
@@ -367,6 +367,11 @@ global_settings::ConfigParse(cParser &Parser) {
|
||||
Parser >> splinefidelity;
|
||||
SplineFidelity = clamp( splinefidelity, 1.f, 4.f );
|
||||
}
|
||||
else if( token == "createswitchtrackbeds" ) {
|
||||
// podwójna jasność ambient
|
||||
Parser.getTokens();
|
||||
Parser >> CreateSwitchTrackbeds;
|
||||
}
|
||||
else if( token == "gfx.resource.sweep" ) {
|
||||
|
||||
Parser.getTokens();
|
||||
|
||||
@@ -53,6 +53,7 @@ struct global_settings {
|
||||
// settings
|
||||
// filesystem
|
||||
bool bLoadTraction{ true };
|
||||
bool CreateSwitchTrackbeds { true };
|
||||
std::string szTexturesTGA{ ".tga" }; // lista tekstur od TGA
|
||||
std::string szTexturesDDS{ ".dds" }; // lista tekstur od DDS
|
||||
std::string szDefaultExt{ szTexturesDDS };
|
||||
|
||||
@@ -166,6 +166,7 @@ enum class start_t {
|
||||
manual,
|
||||
automatic,
|
||||
manualwithautofallback,
|
||||
converter,
|
||||
battery
|
||||
};
|
||||
// recognized vehicle light locations and types; can be combined
|
||||
@@ -619,57 +620,74 @@ struct TCoupling {
|
||||
int sounds { 0 }; // sounds emitted by the coupling devices
|
||||
};
|
||||
|
||||
// basic approximation of a fuel pump
|
||||
// TODO: fuel consumption, optional automatic engine start after activation
|
||||
struct fuel_pump {
|
||||
class TMoverParameters
|
||||
{ // Ra: wrapper na kod pascalowy, przejmujący jego funkcje Q: 20160824 - juz nie wrapper a klasa bazowa :)
|
||||
private:
|
||||
// types
|
||||
|
||||
// basic approximation of a generic device
|
||||
// TBD: inheritance or composition?
|
||||
struct basic_device {
|
||||
// config
|
||||
start_t start_type { start_t::manual };
|
||||
// ld inputs
|
||||
bool is_enabled { false }; // device is allowed/requested to operate
|
||||
bool is_disabled { false }; // device is requested to stop
|
||||
// TODO: add remaining inputs; start conditions and potential breakers
|
||||
// ld outputs
|
||||
bool is_active { false }; // device is working
|
||||
start_t start_type { start_t::manual };
|
||||
};
|
||||
};
|
||||
|
||||
// basic approximation of a fuel pump
|
||||
// TODO: fuel consumption, optional automatic engine start after activation
|
||||
struct oil_pump {
|
||||
struct cooling_fan : public basic_device {
|
||||
// config
|
||||
float speed { 0.f }; // cooling fan rpm; either fraction of parent rpm, or absolute value if negative
|
||||
// ld outputs
|
||||
float revolutions { 0.f }; // current fan rpm
|
||||
};
|
||||
|
||||
bool is_enabled { false }; // device is allowed/requested to operate
|
||||
bool is_disabled { false }; // device is requested to stop
|
||||
bool is_active { false }; // device is working
|
||||
start_t start_type { start_t::manual };
|
||||
float resource_amount { 1.f };
|
||||
// basic approximation of a fuel pump
|
||||
struct fuel_pump : public basic_device {
|
||||
// TODO: fuel consumption, optional automatic engine start after activation
|
||||
};
|
||||
|
||||
// basic approximation of an oil pump
|
||||
struct oil_pump : public basic_device {
|
||||
// config
|
||||
float pressure_minimum { 0.f }; // lowest acceptable working pressure
|
||||
float pressure_maximum { 0.65f }; // oil pressure at maximum engine revolutions
|
||||
// ld inputs
|
||||
float resource_amount { 1.f }; // amount of affected resource, compared to nominal value
|
||||
// internal data
|
||||
float pressure_target { 0.f };
|
||||
float pressure_present { 0.f };
|
||||
};
|
||||
|
||||
struct water_pump {
|
||||
// ld outputs
|
||||
float pressure { 0.f }; // current pressure
|
||||
};
|
||||
|
||||
// basic approximation of a water pump
|
||||
struct water_pump : public basic_device {
|
||||
// ld inputs
|
||||
// TODO: move to breaker list in the basic device once implemented
|
||||
bool breaker { true }; // device is allowed to operate
|
||||
bool is_enabled { false }; // device is requested to operate
|
||||
bool is_disabled { false }; // device is requested to stop
|
||||
bool is_active { false }; // device is working
|
||||
start_t start_type { start_t::manual };
|
||||
};
|
||||
|
||||
struct water_heater {
|
||||
|
||||
bool breaker { true }; // device is allowed to operate
|
||||
bool is_enabled { false }; // device is requested to operate
|
||||
bool is_active { false }; // device is working
|
||||
bool is_damaged { false }; // device is damaged
|
||||
};
|
||||
|
||||
struct water_heater {
|
||||
// config
|
||||
struct heater_config_t {
|
||||
float temp_min { -1 }; // lowest accepted temperature
|
||||
float temp_max { -1 }; // highest accepted temperature
|
||||
} config;
|
||||
};
|
||||
// ld inputs
|
||||
bool breaker { true }; // device is allowed to operate
|
||||
bool is_enabled { false }; // device is requested to operate
|
||||
// ld outputs
|
||||
bool is_active { false }; // device is working
|
||||
bool is_damaged { false }; // device is damaged
|
||||
};
|
||||
|
||||
struct heat_data {
|
||||
struct heat_data {
|
||||
// input, state of relevant devices
|
||||
bool cooling { false }; // TODO: user controlled device, implement
|
||||
// bool okienko { true }; // window in the engine compartment
|
||||
// bool okienko { true }; // window in the engine compartment
|
||||
// system configuration
|
||||
bool auxiliary_water_circuit { false }; // cooling system has an extra water circuit
|
||||
double fan_speed { 0.075 }; // cooling fan rpm; either fraction of engine rpm, or absolute value if negative
|
||||
@@ -716,10 +734,8 @@ struct heat_data {
|
||||
float Twy2 { 40.0 }; // secondary circuit water temperature
|
||||
float temperatura1 { 50.0 };
|
||||
float temperatura2 { 40.0 };
|
||||
};
|
||||
};
|
||||
|
||||
class TMoverParameters
|
||||
{ // Ra: wrapper na kod pascalowy, przejmujący jego funkcje Q: 20160824 - juz nie wrapper a klasa bazowa :)
|
||||
public:
|
||||
|
||||
double dMoveLen = 0.0;
|
||||
@@ -1040,6 +1056,7 @@ public:
|
||||
water_heater WaterHeater;
|
||||
bool WaterCircuitsLink { false }; // optional connection between water circuits
|
||||
heat_data dizel_heat;
|
||||
std::array<cooling_fan, 2> MotorBlowers;
|
||||
|
||||
int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/
|
||||
double BrakeCtrlPosR = 0.0; /*nastawa hamulca zespolonego - plynna dla FV4a*/
|
||||
@@ -1343,6 +1360,8 @@ public:
|
||||
bool FuelPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // fuel pump state toggle
|
||||
bool OilPumpSwitch( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle
|
||||
bool OilPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle
|
||||
bool MotorBlowersSwitch( bool State, side const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle
|
||||
bool MotorBlowersSwitchOff( bool State, side const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle
|
||||
bool MainSwitch( bool const State, range_t const Notify = range_t::consist );/*! wylacznik glowny*/
|
||||
bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/
|
||||
bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/
|
||||
@@ -1353,6 +1372,7 @@ public:
|
||||
void WaterHeaterCheck( double const Timestep );
|
||||
void FuelPumpCheck( double const Timestep );
|
||||
void OilPumpCheck( double const Timestep );
|
||||
void MotorBlowersCheck( double const Timestep );
|
||||
bool FuseOn(void); //bezpiecznik nadamiary
|
||||
bool FuseFlagCheck(void) const; // sprawdzanie flagi nadmiarowego
|
||||
void FuseOff(void); // wylaczenie nadmiarowego
|
||||
|
||||
@@ -1436,6 +1436,8 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
|
||||
SetFlag( SoundFlag, sound::relay );
|
||||
}
|
||||
}
|
||||
// traction motors
|
||||
MotorBlowersCheck( Deltatime );
|
||||
// uklady hamulcowe:
|
||||
ConverterCheck( Deltatime );
|
||||
if (VeselVolume > 0)
|
||||
@@ -1532,6 +1534,11 @@ void TMoverParameters::WaterPumpCheck( double const Timestep ) {
|
||||
// water heater status check
|
||||
void TMoverParameters::WaterHeaterCheck( double const Timestep ) {
|
||||
|
||||
WaterHeater.is_damaged = (
|
||||
( true == WaterHeater.is_damaged )
|
||||
|| ( ( true == WaterHeater.is_active )
|
||||
&& ( false == WaterPump.is_active ) ) );
|
||||
|
||||
WaterHeater.is_active = (
|
||||
( false == WaterHeater.is_damaged )
|
||||
&& ( true == Battery )
|
||||
@@ -1543,11 +1550,6 @@ void TMoverParameters::WaterHeaterCheck( double const Timestep ) {
|
||||
&& ( dizel_heat.temperatura1 > WaterHeater.config.temp_max ) ) {
|
||||
WaterHeater.is_active = false;
|
||||
}
|
||||
|
||||
WaterHeater.is_damaged = (
|
||||
( true == WaterHeater.is_damaged )
|
||||
|| ( ( true == WaterHeater.is_active )
|
||||
&& ( false == WaterPump.is_active ) ) );
|
||||
}
|
||||
|
||||
// fuel pump status update
|
||||
@@ -1590,20 +1592,57 @@ void TMoverParameters::OilPumpCheck( double const Timestep ) {
|
||||
true == OilPump.is_active ? std::min( minpressure + 0.1f, OilPump.pressure_maximum ) : // slight pressure margin to give time to switch off the pump and start the engine
|
||||
0.f );
|
||||
|
||||
if( OilPump.pressure_present < OilPump.pressure_target ) {
|
||||
if( OilPump.pressure < OilPump.pressure_target ) {
|
||||
// TODO: scale change rate from 0.01-0.05 with oil/engine temperature/idle time
|
||||
OilPump.pressure_present =
|
||||
OilPump.pressure =
|
||||
std::min<float>(
|
||||
OilPump.pressure_target,
|
||||
OilPump.pressure_present + ( enrot > 5.0 ? 0.05 : 0.035 ) * Timestep );
|
||||
OilPump.pressure + ( enrot > 5.0 ? 0.05 : 0.035 ) * Timestep );
|
||||
}
|
||||
if( OilPump.pressure_present > OilPump.pressure_target ) {
|
||||
OilPump.pressure_present =
|
||||
if( OilPump.pressure > OilPump.pressure_target ) {
|
||||
OilPump.pressure =
|
||||
std::max<float>(
|
||||
OilPump.pressure_target,
|
||||
OilPump.pressure_present - 0.01 * Timestep );
|
||||
OilPump.pressure - 0.01 * Timestep );
|
||||
}
|
||||
OilPump.pressure = clamp( OilPump.pressure, 0.f, 1.5f );
|
||||
}
|
||||
|
||||
void TMoverParameters::MotorBlowersCheck( double const Timestep ) {
|
||||
// activation check
|
||||
for( auto &blower : MotorBlowers ) {
|
||||
|
||||
blower.is_active = (
|
||||
// TODO: bind properly power source when ld is in place
|
||||
( blower.start_type == start_t::battery ? Battery :
|
||||
blower.start_type == start_t::converter ? ConverterFlag :
|
||||
Mains ) // power source
|
||||
// breaker condition disabled until it's implemented in the class data
|
||||
// && ( true == blower.breaker )
|
||||
&& ( false == blower.is_disabled )
|
||||
&& ( ( true == blower.is_active )
|
||||
|| ( blower.start_type == start_t::manual ? blower.is_enabled : true ) ) );
|
||||
}
|
||||
// update
|
||||
for( auto &fan : MotorBlowers ) {
|
||||
|
||||
auto const revolutionstarget { (
|
||||
fan.is_active ?
|
||||
( fan.speed > 0.f ? fan.speed * static_cast<float>( enrot ) * 60 : fan.speed * -1 ) :
|
||||
0.f ) };
|
||||
|
||||
if( std::abs( fan.revolutions - revolutionstarget ) < 0.01f ) {
|
||||
fan.revolutions = revolutionstarget;
|
||||
continue;
|
||||
}
|
||||
if( revolutionstarget > 0.f ) {
|
||||
auto const speedincreasecap { std::max( 50.f, fan.speed * 0.05f * -1 ) }; // 5% of fixed revolution speed, or 50
|
||||
fan.revolutions += clamp( revolutionstarget - fan.revolutions, speedincreasecap * -2, speedincreasecap ) * Timestep;
|
||||
}
|
||||
else {
|
||||
fan.revolutions *= std::max( 0.0, 1.0 - Timestep );
|
||||
}
|
||||
}
|
||||
OilPump.pressure_present = clamp( OilPump.pressure_present, 0.f, 1.5f );
|
||||
}
|
||||
|
||||
|
||||
@@ -2606,6 +2645,60 @@ bool TMoverParameters::OilPumpSwitchOff( bool State, range_t const Notify ) {
|
||||
return ( OilPump.is_disabled != initialstate );
|
||||
}
|
||||
|
||||
bool TMoverParameters::MotorBlowersSwitch( bool State, side const Side, range_t const Notify ) {
|
||||
|
||||
auto &fan { MotorBlowers[ Side ] };
|
||||
|
||||
if( ( fan.start_type != start_t::manual )
|
||||
&& ( fan.start_type != start_t::manualwithautofallback ) ) {
|
||||
// automatic device ignores 'manual' state commands
|
||||
return false;
|
||||
}
|
||||
|
||||
bool const initialstate { fan.is_enabled };
|
||||
|
||||
fan.is_enabled = State;
|
||||
|
||||
if( Notify != range_t::local ) {
|
||||
SendCtrlToNext(
|
||||
( Side == side::front ? "MotorBlowersFrontSwitch" : "MotorBlowersRearSwitch" ),
|
||||
( fan.is_enabled ? 1 : 0 ),
|
||||
CabNo,
|
||||
( Notify == range_t::unit ?
|
||||
coupling::control | coupling::permanent :
|
||||
coupling::control ) );
|
||||
}
|
||||
|
||||
return ( fan.is_enabled != initialstate );
|
||||
}
|
||||
|
||||
bool TMoverParameters::MotorBlowersSwitchOff( bool State, side const Side, range_t const Notify ) {
|
||||
|
||||
auto &fan { MotorBlowers[ Side ] };
|
||||
|
||||
if( ( fan.start_type != start_t::manual )
|
||||
&& ( fan.start_type != start_t::manualwithautofallback ) ) {
|
||||
// automatic device ignores 'manual' state commands
|
||||
return false;
|
||||
}
|
||||
|
||||
bool const initialstate { fan.is_disabled };
|
||||
|
||||
fan.is_disabled = State;
|
||||
|
||||
if( Notify != range_t::local ) {
|
||||
SendCtrlToNext(
|
||||
( Side == side::front ? "MotorBlowersFrontSwitchOff" : "MotorBlowersRearSwitchOff" ),
|
||||
( fan.is_disabled ? 1 : 0 ),
|
||||
CabNo,
|
||||
( Notify == range_t::unit ?
|
||||
coupling::control | coupling::permanent :
|
||||
coupling::control ) );
|
||||
}
|
||||
|
||||
return ( fan.is_disabled != initialstate );
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Q: 20160713
|
||||
// włączenie / wyłączenie obwodu głownego
|
||||
@@ -6020,7 +6113,7 @@ bool TMoverParameters::dizel_StartupCheck() {
|
||||
}
|
||||
// test the oil pump
|
||||
if( ( false == OilPump.is_active )
|
||||
|| ( OilPump.pressure_present < OilPump.pressure_minimum ) ) {
|
||||
|| ( OilPump.pressure < OilPump.pressure_minimum ) ) {
|
||||
engineisready = false;
|
||||
if( OilPump.start_type == start_t::manual ) {
|
||||
// with manual pump control startup procedure is done only once per starter switch press
|
||||
@@ -6545,15 +6638,14 @@ TMoverParameters::AssignLoad( std::string const &Name, float const Amount ) {
|
||||
}
|
||||
}
|
||||
|
||||
// can't mix load types, at least for the time being
|
||||
if( ( LoadAmount > 0 ) && ( LoadType.name != Name ) ) { return false; }
|
||||
|
||||
if( Name.empty() ) {
|
||||
// empty the vehicle
|
||||
// empty the vehicle if requested
|
||||
LoadType = load_attributes();
|
||||
LoadAmount = 0.f;
|
||||
return true;
|
||||
}
|
||||
// can't mix load types, at least for the time being
|
||||
if( ( LoadAmount > 0 ) && ( LoadType.name != Name ) ) { return false; }
|
||||
|
||||
for( auto const &loadattributes : LoadAttributes ) {
|
||||
if( Name == loadattributes.name ) {
|
||||
@@ -8206,59 +8298,54 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
|
||||
}
|
||||
extract_value( ConverterStartDelay, "ConverterStartDelay", line, "" );
|
||||
|
||||
// compressor
|
||||
{
|
||||
// devices
|
||||
std::map<std::string, start_t> starts {
|
||||
{ "Manual", start_t::manual },
|
||||
{ "Automatic", start_t::automatic }
|
||||
};
|
||||
{ "Automatic", start_t::automatic },
|
||||
{ "Mixed", start_t::manualwithautofallback },
|
||||
{ "Battery", start_t::battery },
|
||||
{ "Converter", start_t::converter } };
|
||||
// compressor
|
||||
{
|
||||
auto lookup = starts.find( extract_value( "CompressorStart", line ) );
|
||||
CompressorStart =
|
||||
lookup != starts.end() ?
|
||||
lookup->second :
|
||||
start_t::manual;
|
||||
}
|
||||
|
||||
// fuel pump
|
||||
{
|
||||
std::map<std::string, start_t> starts {
|
||||
{ "Manual", start_t::manual },
|
||||
{ "Automatic", start_t::automatic },
|
||||
{ "Mixed", start_t::manualwithautofallback }
|
||||
};
|
||||
auto lookup = starts.find( extract_value( "FuelStart", line ) );
|
||||
FuelPump.start_type =
|
||||
lookup != starts.end() ?
|
||||
lookup->second :
|
||||
start_t::manual;
|
||||
}
|
||||
|
||||
// oil pump
|
||||
{
|
||||
std::map<std::string, start_t> starts {
|
||||
{ "Manual", start_t::manual },
|
||||
{ "Automatic", start_t::automatic },
|
||||
{ "Mixed", start_t::manualwithautofallback }
|
||||
};
|
||||
auto lookup = starts.find( extract_value( "OilStart", line ) );
|
||||
OilPump.start_type =
|
||||
lookup != starts.end() ?
|
||||
lookup->second :
|
||||
start_t::manual;
|
||||
}
|
||||
|
||||
// water pump
|
||||
{
|
||||
std::map<std::string, start_t> starts {
|
||||
{ "Manual", start_t::manual },
|
||||
{ "Battery", start_t::battery }
|
||||
};
|
||||
auto lookup = starts.find( extract_value( "WaterStart", line ) );
|
||||
WaterPump.start_type =
|
||||
lookup != starts.end() ?
|
||||
lookup->second :
|
||||
start_t::manual;
|
||||
}
|
||||
// traction motor fans
|
||||
{
|
||||
auto lookup = starts.find( extract_value( "MotorBlowersStart", line ) );
|
||||
MotorBlowers[side::front].start_type =
|
||||
MotorBlowers[side::rear].start_type =
|
||||
lookup != starts.end() ?
|
||||
lookup->second :
|
||||
start_t::manual;
|
||||
}
|
||||
}
|
||||
|
||||
void TMoverParameters::LoadFIZ_Blending(std::string const &line) {
|
||||
@@ -8511,6 +8598,10 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
|
||||
extract_value( WaterHeater.config.temp_min, "HeaterMinTemperature", Input, "" );
|
||||
extract_value( WaterHeater.config.temp_max, "HeaterMaxTemperature", Input, "" );
|
||||
}
|
||||
|
||||
// traction motors
|
||||
extract_value( MotorBlowers[ side::front ].speed, "MotorBlowersSpeed", Input, "" );
|
||||
MotorBlowers[ side::rear ] = MotorBlowers[ side::front ];
|
||||
}
|
||||
|
||||
void TMoverParameters::LoadFIZ_Switches( std::string const &Input ) {
|
||||
@@ -9287,6 +9378,38 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if( Command == "MotorBlowersFrontSwitch" ) {
|
||||
if( ( MotorBlowers[ side::front ].start_type != start_t::manual )
|
||||
&& ( MotorBlowers[ side::front ].start_type != start_t::manualwithautofallback ) ) {
|
||||
// automatic device ignores 'manual' state commands
|
||||
MotorBlowers[side::front].is_enabled = ( CValue1 == 1 );
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if( Command == "MotorBlowersFrontSwitchOff" ) {
|
||||
if( ( MotorBlowers[ side::front ].start_type != start_t::manual )
|
||||
&& ( MotorBlowers[ side::front ].start_type != start_t::manualwithautofallback ) ) {
|
||||
// automatic device ignores 'manual' state commands
|
||||
MotorBlowers[side::front].is_disabled = ( CValue1 == 1 );
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if( Command == "MotorBlowersRearSwitch" ) {
|
||||
if( ( MotorBlowers[ side::rear ].start_type != start_t::manual )
|
||||
&& ( MotorBlowers[ side::rear ].start_type != start_t::manualwithautofallback ) ) {
|
||||
// automatic device ignores 'manual' state commands
|
||||
MotorBlowers[side::rear].is_enabled = ( CValue1 == 1 );
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if( Command == "MotorBlowersRearSwitchOff" ) {
|
||||
if( ( MotorBlowers[ side::rear ].start_type != start_t::manual )
|
||||
&& ( MotorBlowers[ side::rear ].start_type != start_t::manualwithautofallback ) ) {
|
||||
// automatic device ignores 'manual' state commands
|
||||
MotorBlowers[side::rear].is_disabled = ( CValue1 == 1 );
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if (Command == "MainSwitch")
|
||||
{
|
||||
if (CValue1 == 1) {
|
||||
|
||||
23
Model3d.cpp
23
Model3d.cpp
@@ -72,6 +72,23 @@ void TSubModel::Name(std::string const &Name)
|
||||
pName = Name;
|
||||
};
|
||||
|
||||
// sets visibility level (alpha component) to specified value
|
||||
void
|
||||
TSubModel::SetVisibilityLevel( float const Level, bool const Includechildren, bool const Includesiblings ) {
|
||||
|
||||
fVisible = Level;
|
||||
if( true == Includesiblings ) {
|
||||
auto sibling { this };
|
||||
while( ( sibling = sibling->Next ) != nullptr ) {
|
||||
sibling->SetVisibilityLevel( Level, Includechildren, false ); // no need for all siblings to duplicate the work
|
||||
}
|
||||
}
|
||||
if( ( true == Includechildren )
|
||||
&& ( Child != nullptr ) ) {
|
||||
Child->SetVisibilityLevel( Level, Includechildren, true ); // node's children include child's siblings and children
|
||||
}
|
||||
}
|
||||
|
||||
// sets light level (alpha component of illumination color) to specified value
|
||||
void
|
||||
TSubModel::SetLightLevel( float const Level, bool const Includechildren, bool const Includesiblings ) {
|
||||
@@ -1321,7 +1338,8 @@ void TSubModel::serialize(std::ostream &s,
|
||||
else
|
||||
sn_utils::ls_int32(s, (int32_t)get_container_pos(textures, m_materialname));
|
||||
|
||||
sn_utils::ls_float32(s, fVisible);
|
||||
// sn_utils::ls_float32(s, fVisible);
|
||||
sn_utils::ls_float32(s, 1.f);
|
||||
sn_utils::ls_float32(s, fLight);
|
||||
|
||||
sn_utils::s_vec4(s, f4Ambient);
|
||||
@@ -1441,7 +1459,8 @@ void TSubModel::deserialize(std::istream &s)
|
||||
tVboPtr = sn_utils::ld_int32(s);
|
||||
iTexture = sn_utils::ld_int32(s);
|
||||
|
||||
fVisible = sn_utils::ld_float32(s);
|
||||
// fVisible = sn_utils::ld_float32(s);
|
||||
auto discard = sn_utils::ld_float32(s);
|
||||
fLight = sn_utils::ld_float32(s);
|
||||
|
||||
f4Ambient = sn_utils::d_vec4(s);
|
||||
|
||||
@@ -100,7 +100,6 @@ private:
|
||||
int iNumVerts { -1 }; // ilość wierzchołków (1 dla FreeSpotLight)
|
||||
int tVboPtr; // początek na liście wierzchołków albo indeksów
|
||||
int iTexture { 0 }; // numer nazwy tekstury, -1 wymienna, 0 brak
|
||||
float fVisible { 0.0f }; // próg jasności światła do załączenia submodelu
|
||||
float fLight { -1.0f }; // próg jasności światła do zadziałania selfillum
|
||||
glm::vec4
|
||||
f4Ambient { 1.0f,1.0f,1.0f,1.0f },
|
||||
@@ -142,7 +141,8 @@ public: // chwilowo
|
||||
float4x4 *mAnimMatrix{ nullptr }; // macierz do animacji kwaternionowych (należy do AnimContainer)
|
||||
TSubModel **smLetter{ nullptr }; // wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D)
|
||||
TSubModel *Parent{ nullptr }; // nadrzędny, np. do wymnażania macierzy
|
||||
int iVisible{ 1 }; // roboczy stan widoczności
|
||||
int iVisible { 1 }; // roboczy stan widoczności
|
||||
float fVisible { 1.f }; // visibility level
|
||||
std::string m_materialname; // robocza nazwa tekstury do zapisania w pliku binarnym
|
||||
std::string pName; // robocza nazwa
|
||||
private:
|
||||
@@ -195,6 +195,8 @@ public:
|
||||
uint32_t Flags() const { return iFlags; };
|
||||
void UnFlagNext() { iFlags &= 0x00FFFFFF; };
|
||||
void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
|
||||
// sets visibility level (alpha component) to specified value
|
||||
void SetVisibilityLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false );
|
||||
// sets light level (alpha component of illumination color) to specified value
|
||||
void SetLightLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false );
|
||||
inline float3 Translation1Get() {
|
||||
|
||||
18
Segment.cpp
18
Segment.cpp
@@ -112,9 +112,6 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
||||
|
||||
ErrorLog( "Bad track: zero length spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
||||
fLength = 0.01; // crude workaround TODO: fix this properly
|
||||
/*
|
||||
return false; // zerowe nie mogą być
|
||||
*/
|
||||
}
|
||||
|
||||
fStoop = std::atan2((Point2.y - Point1.y), fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
|
||||
@@ -126,13 +123,12 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
||||
// NOTE: a workaround for too short switches (less than 3 segments) messing up animation/generation of blades
|
||||
fStep = fLength / ( 3.0 * Global.SplineFidelity );
|
||||
}
|
||||
iSegCount = static_cast<int>( std::ceil( fLength / fStep ) ); // potrzebne do VBO
|
||||
/*
|
||||
// iSegCount = static_cast<int>( std::ceil( fLength / fStep ) ); // potrzebne do VBO
|
||||
iSegCount = (
|
||||
pOwner->eType == tt_Switch ?
|
||||
6 * Global.SplineFidelity :
|
||||
static_cast<int>( std::ceil( fLength / fStep ) ) ); // potrzebne do VBO
|
||||
*/
|
||||
|
||||
fStep = fLength / iSegCount; // update step to equalize size of individual pieces
|
||||
|
||||
fTsBuffer.resize( iSegCount + 1 );
|
||||
@@ -376,7 +372,7 @@ Math3D::vector3 TSegment::FastGetPoint(double const t) const
|
||||
interpolate( Point1, Point2, t ) );
|
||||
}
|
||||
|
||||
bool TSegment::RenderLoft( gfx::vertex_array &Output, Math3D::vector3 const &Origin, const gfx::basic_vertex *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, float fOffsetX, glm::vec3 **p, bool bRender)
|
||||
bool TSegment::RenderLoft( gfx::vertex_array &Output, Math3D::vector3 const &Origin, const gfx::vertex_array &ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, float fOffsetX, glm::vec3 **p, bool bRender)
|
||||
{ // generowanie trójkątów dla odcinka trajektorii ruchu
|
||||
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
|
||||
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
|
||||
@@ -457,7 +453,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, Math3D::vector3 const &Ori
|
||||
Output.emplace_back(
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ( jmm1 * ShapePoints[ j ].texture.x + m1 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv1 } );
|
||||
glm::vec2 { 1.f - ( jmm1 * ShapePoints[ j ].texture.x + m1 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv1 } );
|
||||
}
|
||||
if( p ) // jeśli jest wskaźnik do tablicy
|
||||
if( *p )
|
||||
@@ -477,7 +473,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, Math3D::vector3 const &Ori
|
||||
Output.emplace_back(
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ( jmm2 * ShapePoints[ j ].texture.x + m2 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv2 } );
|
||||
glm::vec2 { 1.f - ( jmm2 * ShapePoints[ j ].texture.x + m2 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv2 } );
|
||||
}
|
||||
if( p ) // jeśli jest wskaźnik do tablicy
|
||||
if( *p )
|
||||
@@ -501,7 +497,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, Math3D::vector3 const &Ori
|
||||
Output.emplace_back(
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ShapePoints[ j ].texture.x / texturescale, tv1 } );
|
||||
glm::vec2 { 1.f - ShapePoints[ j ].texture.x / texturescale, tv1 } );
|
||||
|
||||
pt = parallel2 * ShapePoints[ j ].position.x + pos2;
|
||||
pt.y += ShapePoints[ j ].position.y;
|
||||
@@ -512,7 +508,7 @@ bool TSegment::RenderLoft( gfx::vertex_array &Output, Math3D::vector3 const &Ori
|
||||
Output.emplace_back(
|
||||
pt,
|
||||
glm::normalize( norm ),
|
||||
glm::vec2 { ShapePoints[ j ].texture.x / texturescale, tv2 } );
|
||||
glm::vec2 { 1.f - ShapePoints[ j ].texture.x / texturescale, tv2 } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
r2 = fRoll2; }
|
||||
|
||||
bool
|
||||
RenderLoft( gfx::vertex_array &Output, Math3D::vector3 const &Origin, gfx::basic_vertex const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, float fOffsetX = 0.f, glm::vec3 **p = nullptr, bool bRender = true);
|
||||
RenderLoft( gfx::vertex_array &Output, Math3D::vector3 const &Origin, gfx::vertex_array const &ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, float fOffsetX = 0.f, glm::vec3 **p = nullptr, bool bRender = true);
|
||||
/*
|
||||
void
|
||||
Render();
|
||||
|
||||
13
Track.h
13
Track.h
@@ -93,6 +93,8 @@ class TSwitchExtension
|
||||
*evMinus = nullptr; // zdarzenia sygnalizacji rozprucia
|
||||
float fVelocity = -1.0; // maksymalne ograniczenie prędkości (ustawianej eventem)
|
||||
Math3D::vector3 vTrans; // docelowa translacja przesuwnicy
|
||||
material_handle m_material3 = 0; // texture of auto generated switch trackbed
|
||||
gfx::geometry_handle Geometry3; // geometry of auto generated switch trackbed
|
||||
};
|
||||
|
||||
class TIsolated
|
||||
@@ -134,7 +136,7 @@ private:
|
||||
// members
|
||||
int iAxles { 0 }; // ilość osi na odcinkach obsługiwanych przez obiekt
|
||||
TIsolated *pNext { nullptr }; // odcinki izolowane są trzymane w postaci listy jednikierunkowej
|
||||
TIsolated *pParent { nullptr }; // optional parent piece, collecting data from its children
|
||||
TIsolated *pParent { nullptr }; // optional parent piece, receiving data from its children
|
||||
static TIsolated *pRoot; // początek listy
|
||||
};
|
||||
|
||||
@@ -222,6 +224,7 @@ public:
|
||||
void ConnectPrevNext(TTrack *pNewPrev, int typ);
|
||||
void ConnectNextPrev(TTrack *pNewNext, int typ);
|
||||
void ConnectNextNext(TTrack *pNewNext, int typ);
|
||||
material_handle copy_adjacent_trackbed_material( TTrack const *Exclude = nullptr );
|
||||
inline double Length() const {
|
||||
return Segment->GetLength(); };
|
||||
inline std::shared_ptr<TSegment> CurrentSegment() const {
|
||||
@@ -288,6 +291,7 @@ public:
|
||||
void VelocitySet(float v);
|
||||
double VelocityGet();
|
||||
void ConnectionsLog();
|
||||
bool DoubleSlip() const;
|
||||
|
||||
private:
|
||||
// radius() subclass details, calculates node's bounding radius
|
||||
@@ -300,6 +304,13 @@ private:
|
||||
void export_as_text_( std::ostream &Output ) const;
|
||||
// returns texture length for specified material
|
||||
float texture_length( material_handle const Material );
|
||||
// creates profile for a part of current path
|
||||
void create_switch_trackbed( gfx::vertex_array &Output );
|
||||
void create_track_rail_profile( gfx::vertex_array &Right, gfx::vertex_array &Left );
|
||||
void create_track_blade_profile( gfx::vertex_array &Right, gfx::vertex_array &Left );
|
||||
void create_track_bed_profile( gfx::vertex_array &Output, TTrack const *Previous, TTrack const *Next );
|
||||
void create_road_profile( gfx::vertex_array &Output, bool const Forcetransition = false );
|
||||
void create_road_side_profile( gfx::vertex_array &Right, gfx::vertex_array &Left, gfx::vertex_array const &Road, bool const Forcetransition = false );
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -567,7 +567,7 @@ TTraction::wire_color() const {
|
||||
color.r *= Global.DayLight.ambient[ 0 ];
|
||||
color.g *= Global.DayLight.ambient[ 1 ];
|
||||
color.b *= Global.DayLight.ambient[ 2 ];
|
||||
color *= 0.5f;
|
||||
color *= 0.35f;
|
||||
}
|
||||
else {
|
||||
// tymczasowo pokazanie zasilanych odcinków
|
||||
|
||||
229
Train.cpp
229
Train.cpp
@@ -266,6 +266,9 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
|
||||
{ user_command::compressorenable, &TTrain::OnCommand_compressorenable },
|
||||
{ user_command::compressordisable, &TTrain::OnCommand_compressordisable },
|
||||
{ user_command::compressortogglelocal, &TTrain::OnCommand_compressortogglelocal },
|
||||
{ user_command::motorblowerstogglefront, &TTrain::OnCommand_motorblowerstogglefront },
|
||||
{ user_command::motorblowerstogglerear, &TTrain::OnCommand_motorblowerstogglerear },
|
||||
{ user_command::motorblowersdisableall, &TTrain::OnCommand_motorblowersdisableall },
|
||||
{ user_command::motorconnectorsopen, &TTrain::OnCommand_motorconnectorsopen },
|
||||
{ user_command::motorconnectorsclose, &TTrain::OnCommand_motorconnectorsclose },
|
||||
{ user_command::motordisconnect, &TTrain::OnCommand_motordisconnect },
|
||||
@@ -448,7 +451,9 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
||||
PyObject *TTrain::GetTrainState() {
|
||||
|
||||
auto const *mover = DynamicObject->MoverParameters;
|
||||
PyEval_AcquireLock();
|
||||
auto *dict = PyDict_New();
|
||||
PyEval_ReleaseLock();
|
||||
if( ( dict == nullptr )
|
||||
|| ( mover == nullptr ) ) {
|
||||
return nullptr;
|
||||
@@ -2776,8 +2781,193 @@ void TTrain::OnCommand_compressortogglelocal( TTrain *Train, command_data const
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &cmd ) {
|
||||
command_data Command = cmd;
|
||||
void TTrain::OnCommand_motorblowerstogglefront( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Train->ggMotorBlowersFrontButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
// currently there's no off button so we always try to turn it on
|
||||
OnCommand_motorblowersenablefront( Train, Command );
|
||||
}
|
||||
else {
|
||||
// two-state switch
|
||||
if( Command.action == GLFW_RELEASE ) { return; }
|
||||
|
||||
if( false == Train->mvControlled->MotorBlowers[side::front].is_enabled ) {
|
||||
// turn on
|
||||
OnCommand_motorblowersenablefront( Train, Command );
|
||||
}
|
||||
else {
|
||||
//turn off
|
||||
OnCommand_motorblowersdisablefront( Train, Command );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_motorblowersenablefront( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Train->ggMotorBlowersFrontButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersFrontButton.UpdateValue( 1.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitch( true, side::front );
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersFrontButton.UpdateValue( 0.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitch( false, side::front );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// two-state switch, only cares about press events
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersFrontButton.UpdateValue( 1.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitch( true, side::front );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( false, side::front );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_motorblowersdisablefront( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Train->ggMotorBlowersFrontButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
// currently there's no disable return type switch
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// two-state switch, only cares about press events
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersFrontButton.UpdateValue( 0.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitch( false, side::front );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( true, side::front );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_motorblowerstogglerear( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Train->ggMotorBlowersRearButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
// currently there's no off button so we always try to turn it on
|
||||
OnCommand_motorblowersenablerear( Train, Command );
|
||||
}
|
||||
else {
|
||||
// two-state switch
|
||||
if( Command.action == GLFW_RELEASE ) { return; }
|
||||
|
||||
if( false == Train->mvControlled->MotorBlowers[ side::rear ].is_enabled ) {
|
||||
// turn on
|
||||
OnCommand_motorblowersenablerear( Train, Command );
|
||||
}
|
||||
else {
|
||||
//turn off
|
||||
OnCommand_motorblowersdisablerear( Train, Command );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_motorblowersenablerear( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Train->ggMotorBlowersRearButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersRearButton.UpdateValue( 1.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitch( true, side::rear );
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersRearButton.UpdateValue( 0.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitch( false, side::rear );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// two-state switch, only cares about press events
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersRearButton.UpdateValue( 1.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitch( true, side::rear );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( false, side::rear );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_motorblowersdisablerear( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Train->ggMotorBlowersRearButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
// currently there's no disable return type switch
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// two-state switch, only cares about press events
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersRearButton.UpdateValue( 0.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitch( false, side::rear );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( true, side::rear );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_motorblowersdisableall( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Command.action == GLFW_REPEAT ) { return; }
|
||||
|
||||
if( Train->ggMotorBlowersAllOffButton.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersAllOffButton.UpdateValue( 1.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( true, side::front );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( true, side::rear );
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersAllOffButton.UpdateValue( 0.f, Train->dsbSwitch );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( false, side::front );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( false, side::rear );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// two-state switch, only cares about press events
|
||||
// NOTE: generally this switch doesn't come in two-state form
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
if( Train->ggMotorBlowersAllOffButton.GetDesiredValue() < 0.5f ) {
|
||||
// switch is off, activate
|
||||
Train->mvControlled->MotorBlowersSwitchOff( true, side::front );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( true, side::rear );
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersRearButton.UpdateValue( 1.f, Train->dsbSwitch );
|
||||
}
|
||||
else {
|
||||
// deactivate
|
||||
Train->mvControlled->MotorBlowersSwitchOff( false, side::front );
|
||||
Train->mvControlled->MotorBlowersSwitchOff( false, side::rear );
|
||||
// visual feedback
|
||||
Train->ggMotorBlowersRearButton.UpdateValue( 0.f, Train->dsbSwitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
// TODO: don't rely on presense of 3d model to determine presence of the switch
|
||||
if( Train->ggStLinOffButton.SubModel == nullptr ) {
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
@@ -5055,7 +5245,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
ggWater1TempB.Update();
|
||||
}
|
||||
if( ggOilPressB.SubModel ) {
|
||||
ggOilPressB.UpdateValue( tmp->MoverParameters->OilPump.pressure_present );
|
||||
ggOilPressB.UpdateValue( tmp->MoverParameters->OilPump.pressure );
|
||||
ggOilPressB.Update();
|
||||
}
|
||||
}
|
||||
@@ -5356,7 +5546,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
btLampkaRearRightEndLight.Turn( ( mvOccupied->iLights[ side::rear ] & light::redmarker_right ) != 0 );
|
||||
// others
|
||||
btLampkaMalfunction.Turn( mvControlled->dizel_heat.PA );
|
||||
btLampkaMotorBlowers.Turn( mvControlled->RventRot > 0.1 );
|
||||
btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ side::front ].is_active ) && ( mvControlled->MotorBlowers[ side::rear ].is_active ) );
|
||||
}
|
||||
else {
|
||||
// wylaczone
|
||||
@@ -5715,6 +5905,9 @@ bool TTrain::Update( double const Deltatime )
|
||||
ggWaterCircuitsLinkButton.Update();
|
||||
ggFuelPumpButton.Update();
|
||||
ggOilPumpButton.Update();
|
||||
ggMotorBlowersFrontButton.Update();
|
||||
ggMotorBlowersRearButton.Update();
|
||||
ggMotorBlowersAllOffButton.Update();
|
||||
//------
|
||||
}
|
||||
// wyprowadzenie sygnałów dla haslera na PoKeys (zaznaczanie na taśmie)
|
||||
@@ -6945,6 +7138,9 @@ void TTrain::clear_cab_controls()
|
||||
ggWaterCircuitsLinkButton.Clear();
|
||||
ggFuelPumpButton.Clear();
|
||||
ggOilPumpButton.Clear();
|
||||
ggMotorBlowersFrontButton.Clear();
|
||||
ggMotorBlowersRearButton.Clear();
|
||||
ggMotorBlowersAllOffButton.Clear();
|
||||
|
||||
btLampkaPrzetw.Clear();
|
||||
btLampkaPrzetwB.Clear();
|
||||
@@ -7289,6 +7485,26 @@ void TTrain::set_cab_controls() {
|
||||
1.0 :
|
||||
0.0 );
|
||||
}
|
||||
// traction motor fans
|
||||
if( ggMotorBlowersFrontButton.type() != TGaugeType::push ) {
|
||||
ggMotorBlowersFrontButton.PutValue(
|
||||
mvControlled->MotorBlowers[side::front].is_enabled ?
|
||||
1.0 :
|
||||
0.0 );
|
||||
}
|
||||
if( ggMotorBlowersRearButton.type() != TGaugeType::push ) {
|
||||
ggMotorBlowersRearButton.PutValue(
|
||||
mvControlled->MotorBlowers[side::rear].is_enabled ?
|
||||
1.0 :
|
||||
0.0 );
|
||||
}
|
||||
if( ggMotorBlowersAllOffButton.type() != TGaugeType::push ) {
|
||||
ggMotorBlowersAllOffButton.PutValue(
|
||||
( mvControlled->MotorBlowers[side::front].is_disabled
|
||||
|| mvControlled->MotorBlowers[ side::front ].is_disabled ) ?
|
||||
1.0 :
|
||||
0.0 );
|
||||
}
|
||||
|
||||
// we reset all indicators, as they're set during the update pass
|
||||
// TODO: when cleaning up break setting indicator state into a separate function, so we can reuse it
|
||||
@@ -7483,6 +7699,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
||||
{ "fuelpump_sw:", ggFuelPumpButton },
|
||||
{ "oilpump_sw:", ggOilPumpButton },
|
||||
{ "oilpressb:", ggOilPressB },
|
||||
{ "motorblowersfront_sw:", ggMotorBlowersFrontButton },
|
||||
{ "motorblowersrear_sw:", ggMotorBlowersRearButton },
|
||||
{ "motorblowersalloff_sw:", ggMotorBlowersAllOffButton },
|
||||
{ "radio_sw:", ggRadioButton },
|
||||
{ "radiochannel_sw:", ggRadioChannelSelector },
|
||||
{ "radiochannelprev_sw:", ggRadioChannelPrevious },
|
||||
@@ -7648,7 +7867,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
||||
// oil pressure
|
||||
auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna gałka
|
||||
gauge.Load( Parser, DynamicObject, DynamicObject->mdKabina, nullptr );
|
||||
gauge.AssignFloat( &mvControlled->OilPump.pressure_present );
|
||||
gauge.AssignFloat( &mvControlled->OilPump.pressure );
|
||||
}
|
||||
else if( Label == "oiltemp:" ) {
|
||||
// oil temperature
|
||||
|
||||
13
Train.h
13
Train.h
@@ -252,6 +252,13 @@ class TTrain
|
||||
static void OnCommand_compressorenable( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_compressordisable( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_compressortogglelocal( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorblowerstogglefront( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorblowersenablefront( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorblowersdisablefront( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorblowerstogglerear( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorblowersenablerear( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorblowersdisablerear( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorblowersdisableall( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorconnectorsopen( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motorconnectorsclose( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_motordisconnect( TTrain *Train, command_data const &Command );
|
||||
@@ -323,6 +330,7 @@ class TTrain
|
||||
static void OnCommand_cabchangebackward( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_generictoggle( TTrain *Train, command_data const &Command );
|
||||
|
||||
|
||||
// members
|
||||
TDynamicObject *DynamicObject { nullptr }; // przestawia zmiana pojazdu [F5]
|
||||
TMoverParameters *mvControlled { nullptr }; // człon, w którym sterujemy silnikiem
|
||||
@@ -351,7 +359,7 @@ public: // reszta może by?publiczna
|
||||
TGauge ggI3B;
|
||||
TGauge ggItotalB;
|
||||
|
||||
TGauge ggOilPressB;
|
||||
TGauge ggOilPressB; // other unit oil pressure indicator
|
||||
TGauge ggWater1TempB;
|
||||
|
||||
// McZapkie: definicje regulatorow
|
||||
@@ -459,6 +467,9 @@ public: // reszta może by?publiczna
|
||||
TGauge ggWaterCircuitsLinkButton;
|
||||
TGauge ggFuelPumpButton; // fuel pump switch
|
||||
TGauge ggOilPumpButton; // fuel pump switch
|
||||
TGauge ggMotorBlowersFrontButton; // front traction motor fan switch
|
||||
TGauge ggMotorBlowersRearButton; // rear traction motor fan switch
|
||||
TGauge ggMotorBlowersAllOffButton; // motor fans shutdown switch
|
||||
|
||||
TButton btLampkaPoslizg;
|
||||
TButton btLampkaStyczn;
|
||||
|
||||
@@ -214,10 +214,13 @@ commanddescription_sequence Commands_descriptions = {
|
||||
{ "generictoggle9", command_target::vehicle, command_mode::oneoff },
|
||||
{ "batterytoggle", command_target::vehicle, command_mode::oneoff },
|
||||
{ "batteryenable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "batterydisable", command_target::vehicle, command_mode::oneoff }
|
||||
{ "batterydisable", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motorblowerstogglefront", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motorblowerstogglerear", command_target::vehicle, command_mode::oneoff },
|
||||
{ "motorblowersdisableall", command_target::vehicle, command_mode::oneoff }
|
||||
};
|
||||
|
||||
}
|
||||
} // simulation
|
||||
|
||||
void command_queue::update()
|
||||
{
|
||||
|
||||
@@ -209,6 +209,9 @@ enum class user_command {
|
||||
batterytoggle,
|
||||
batteryenable,
|
||||
batterydisable,
|
||||
motorblowerstogglefront,
|
||||
motorblowerstogglerear,
|
||||
motorblowersdisableall,
|
||||
|
||||
none = -1
|
||||
};
|
||||
|
||||
@@ -217,6 +217,10 @@ driverkeyboard_input::default_bindings() {
|
||||
{ user_command::batterytoggle, GLFW_KEY_J },
|
||||
// batteryenable,
|
||||
// batterydisable,
|
||||
{ user_command::motorblowerstogglefront, GLFW_KEY_N | keymodifier::shift },
|
||||
{ user_command::motorblowerstogglerear, GLFW_KEY_M | keymodifier::shift },
|
||||
{ user_command::motorblowersdisableall, GLFW_KEY_M | keymodifier::control }
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -182,6 +182,11 @@ driver_mode::update() {
|
||||
|
||||
// variable step simulation time routines
|
||||
|
||||
if( ( simulation::Train == nullptr ) && ( false == FreeFlyModeFlag ) ) {
|
||||
// intercept cases when the driven train got removed after entering portal
|
||||
InOutKey();
|
||||
}
|
||||
|
||||
if( Global.changeDynObj ) {
|
||||
// ABu zmiana pojazdu - przejście do innego
|
||||
ChangeDynamic();
|
||||
|
||||
@@ -499,6 +499,15 @@ drivermouse_input::default_bindings() {
|
||||
{ "oilpump_sw:", {
|
||||
user_command::oilpumptoggle,
|
||||
user_command::none } },
|
||||
{ "motorblowersfront_sw:", {
|
||||
user_command::motorblowerstogglefront,
|
||||
user_command::none } },
|
||||
{ "motorblowersrear_sw:", {
|
||||
user_command::motorblowerstogglerear,
|
||||
user_command::none } },
|
||||
{ "motorblowersalloff_sw:", {
|
||||
user_command::motorblowersdisableall,
|
||||
user_command::none } },
|
||||
{ "main_off_bt:", {
|
||||
user_command::linebreakeropen,
|
||||
user_command::none } },
|
||||
|
||||
@@ -356,7 +356,10 @@ debug_panel::render() {
|
||||
render_section( "Vehicle AI", m_ailines );
|
||||
render_section( "Vehicle Scan Table", m_scantablelines );
|
||||
render_section( "Scenario", m_scenariolines );
|
||||
render_section( "Scenario Event Queue", m_eventqueuelines );
|
||||
if( true == render_section( "Scenario Event Queue", m_eventqueuelines ) ) {
|
||||
// event queue filter
|
||||
ImGui::Checkbox( "By This Vehicle Only", &m_eventqueueactivevehicleonly );
|
||||
}
|
||||
render_section( "Camera", m_cameralines );
|
||||
render_section( "Gfx Renderer", m_rendererlines );
|
||||
// toggles
|
||||
@@ -414,7 +417,7 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
|
||||
( mover.CompressorFlag ? 'C' : ( false == mover.CompressorAllowLocal ? '-' : ( ( mover.CompressorAllow || mover.CompressorStart == start_t::automatic ) ? 'c' : '.' ) ) ),
|
||||
( mover.CompressorGovernorLock ? '!' : '.' ),
|
||||
std::string( isplayervehicle ? locale::strings[ locale::string::debug_vehicle_radio ] + ( mover.Radio ? std::to_string( m_input.train->RadioChannel() ) : "-" ) : "" ).c_str(),
|
||||
std::string( isdieselenginepowered ? locale::strings[ locale::string::debug_vehicle_oilpressure ] + to_string( mover.OilPump.pressure_present, 2 ) : "" ).c_str(),
|
||||
std::string( isdieselenginepowered ? locale::strings[ locale::string::debug_vehicle_oilpressure ] + to_string( mover.OilPump.pressure, 2 ) : "" ).c_str(),
|
||||
// power transfers
|
||||
mover.Couplers[ side::front ].power_high.voltage,
|
||||
mover.Couplers[ side::front ].power_high.current,
|
||||
@@ -440,6 +443,8 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
|
||||
std::abs( mover.enrot ) * 60,
|
||||
std::abs( mover.nrot ) * mover.Transmision.Ratio * 60,
|
||||
mover.RventRot * 60,
|
||||
mover.MotorBlowers[side::front].revolutions,
|
||||
mover.MotorBlowers[side::rear].revolutions,
|
||||
mover.dizel_heat.rpmw,
|
||||
mover.dizel_heat.rpmw2 );
|
||||
|
||||
@@ -762,6 +767,8 @@ debug_panel::update_section_scantable( std::vector<text_line> &Output ) {
|
||||
|
||||
if( m_input.mechanik == nullptr ) { return; }
|
||||
|
||||
Output.emplace_back( "Flags: Dist: Vel: Name:", Global.UITextColor );
|
||||
|
||||
auto const &mechanik{ *m_input.mechanik };
|
||||
|
||||
std::size_t i = 0; std::size_t const speedtablesize = clamp( static_cast<int>( mechanik.TableSize() ) - 1, 0, 30 );
|
||||
@@ -771,8 +778,8 @@ debug_panel::update_section_scantable( std::vector<text_line> &Output ) {
|
||||
Output.emplace_back( Bezogonkow( scanline ), Global.UITextColor );
|
||||
++i;
|
||||
} while( i < speedtablesize );
|
||||
if( Output.empty() ) {
|
||||
Output.emplace_back( "(no points of interest)", Global.UITextColor );
|
||||
if( Output.size() == 1 ) {
|
||||
Output.front().data = "(no points of interest)";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,7 +792,8 @@ debug_panel::update_section_scenario( std::vector<text_line> &Output ) {
|
||||
|
||||
Output.emplace_back( textline, Global.UITextColor );
|
||||
// current luminance level
|
||||
textline = "Light level: " + to_string( Global.fLuminance, 3 );
|
||||
textline = "Cloud cover: " + to_string( Global.Overcast, 3 );
|
||||
textline += "\nLight level: " + to_string( Global.fLuminance, 3 );
|
||||
if( Global.FakeLight ) { textline += "(*)"; }
|
||||
textline += "\nAir temperature: " + to_string( Global.AirTemperature, 1 ) + " deg C";
|
||||
|
||||
@@ -800,28 +808,29 @@ debug_panel::update_section_eventqueue( std::vector<text_line> &Output ) {
|
||||
// current event queue
|
||||
auto const time { Timer::GetTime() };
|
||||
auto const *event { simulation::Events.begin() };
|
||||
auto eventtableindex{ 0 };
|
||||
|
||||
Output.emplace_back( "Delay: Event:", Global.UITextColor );
|
||||
|
||||
while( ( event != nullptr )
|
||||
&& ( eventtableindex < 30 ) ) {
|
||||
&& ( Output.size() < 30 ) ) {
|
||||
|
||||
if( ( false == event->m_ignored )
|
||||
&& ( false == event->m_passive ) ) {
|
||||
&& ( false == event->m_passive )
|
||||
&& ( ( false == m_eventqueueactivevehicleonly )
|
||||
|| ( event->m_activator == m_input.vehicle ) ) ) {
|
||||
|
||||
auto const delay { " " + to_string( std::max( 0.0, event->m_launchtime - time ), 1 ) };
|
||||
textline =
|
||||
"Delay: " + delay.substr( delay.length() - 6 )
|
||||
+ ", Event: " + event->m_name
|
||||
textline = delay.substr( delay.length() - 6 )
|
||||
+ " " + event->m_name
|
||||
+ ( event->m_activator ? " (by: " + event->m_activator->asName + ")" : "" )
|
||||
+ ( event->m_sibling ? " (joint event)" : "" );
|
||||
|
||||
Output.emplace_back( textline, Global.UITextColor );
|
||||
++eventtableindex;
|
||||
}
|
||||
event = event->m_next;
|
||||
}
|
||||
if( Output.empty() ) {
|
||||
textline = "(no queued events)";
|
||||
Output.emplace_back( textline, Global.UITextColor );
|
||||
if( Output.size() == 1 ) {
|
||||
Output.front().data = "(no queued events)";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -883,15 +892,16 @@ debug_panel::update_section_renderer( std::vector<text_line> &Output ) {
|
||||
Output.emplace_back( GfxRenderer.info_stats(), Global.UITextColor );
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
debug_panel::render_section( std::string const &Header, std::vector<text_line> const &Lines ) {
|
||||
|
||||
if( Lines.empty() ) { return; }
|
||||
if( false == ImGui::CollapsingHeader( Header.c_str() ) ) { return; }
|
||||
if( true == Lines.empty() ) { return false; }
|
||||
if( false == ImGui::CollapsingHeader( Header.c_str() ) ) { return false; }
|
||||
|
||||
for( auto const &line : Lines ) {
|
||||
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
std::string update_vehicle_coupler( int const Side );
|
||||
std::string update_vehicle_brake() const;
|
||||
// renders provided lines, under specified collapsing header
|
||||
void render_section( std::string const &Header, std::vector<text_line> const &Lines );
|
||||
bool render_section( std::string const &Header, std::vector<text_line> const &Lines );
|
||||
// members
|
||||
std::array<char, 1024> m_buffer;
|
||||
input_data m_input;
|
||||
@@ -92,6 +92,7 @@ private:
|
||||
int tprev { 0 }; // poprzedni czas
|
||||
double VelPrev { 0.0 }; // poprzednia prędkość
|
||||
double Acc { 0.0 }; // przyspieszenie styczne
|
||||
bool m_eventqueueactivevehicleonly { false };
|
||||
};
|
||||
|
||||
class transcripts_panel : public ui_panel {
|
||||
|
||||
201
imgui/imgui_impl_opengl2.cpp
Normal file
201
imgui/imgui_impl_opengl2.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
// dear imgui: Renderer for OpenGL2 (legacy OpenGL, fixed pipeline)
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||
// **Prefer using the code in imgui_impl_opengl3.cpp**
|
||||
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
||||
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
||||
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
||||
// confuse your GPU driver.
|
||||
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications.
|
||||
// 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
|
||||
// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself.
|
||||
// 2017-09-01: OpenGL: Save and restore current polygon mode.
|
||||
// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
|
||||
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_opengl2.h"
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
|
||||
#include <stddef.h> // intptr_t
|
||||
#else
|
||||
#include <stdint.h> // intptr_t
|
||||
#endif
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
// OpenGL Data
|
||||
static GLuint g_FontTexture = 0;
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOpenGL2_Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_Shutdown()
|
||||
{
|
||||
ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_NewFrame()
|
||||
{
|
||||
if (!g_FontTexture)
|
||||
ImGui_ImplOpenGL2_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
// OpenGL2 Render function.
|
||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
||||
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
|
||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
// Render command lists
|
||||
ImVec2 pos = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
|
||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos)));
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback (registered via ImDrawList::AddCallback)
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
|
||||
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
|
||||
{
|
||||
// Apply scissor/clipping rectangle
|
||||
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
|
||||
|
||||
// Bind texture, Draw
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
||||
}
|
||||
}
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore modified state
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
|
||||
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL2_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGenTextures(1, &g_FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
|
||||
|
||||
// Restore state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_DestroyFontsTexture()
|
||||
{
|
||||
if (g_FontTexture)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
glDeleteTextures(1, &g_FontTexture);
|
||||
io.Fonts->TexID = 0;
|
||||
g_FontTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL2_CreateDeviceObjects()
|
||||
{
|
||||
return ImGui_ImplOpenGL2_CreateFontsTexture();
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL2_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplOpenGL2_DestroyFontsTexture();
|
||||
}
|
||||
28
imgui/imgui_impl_opengl2.h
Normal file
28
imgui/imgui_impl_opengl2.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// dear imgui: Renderer for OpenGL2 (legacy OpenGL, fixed pipeline)
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||
// **Prefer using the code in imgui_impl_opengl3.cpp**
|
||||
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
||||
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
||||
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
||||
// confuse your GPU driver.
|
||||
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateFontsTexture();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyFontsTexture();
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
|
||||
161
renderer.cpp
161
renderer.cpp
@@ -1083,9 +1083,9 @@ opengl_renderer::setup_drawing( bool const Alpha ) {
|
||||
// setup fog
|
||||
if( Global.fFogEnd > 0 ) {
|
||||
// fog setup
|
||||
auto const adjustedfogrange { Global.fFogEnd / std::max( 1.f, Global.Overcast * 2.f ) };
|
||||
m_fogrange = Global.fFogEnd / std::max( 1.f, Global.Overcast * 2.f );
|
||||
::glFogfv( GL_FOG_COLOR, glm::value_ptr( Global.FogColor ) );
|
||||
::glFogf( GL_FOG_DENSITY, static_cast<GLfloat>( 1.0 / adjustedfogrange ) );
|
||||
::glFogf( GL_FOG_DENSITY, static_cast<GLfloat>( 1.0 / m_fogrange ) );
|
||||
::glEnable( GL_FOG );
|
||||
}
|
||||
else { ::glDisable( GL_FOG ); }
|
||||
@@ -2434,7 +2434,20 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
Bind_Material( Submodel->m_material );
|
||||
}
|
||||
// ...colors...
|
||||
if( Submodel->fVisible < 1.f ) {
|
||||
// setup
|
||||
::glAlphaFunc( GL_GREATER, 0.f );
|
||||
::glEnable( GL_BLEND );
|
||||
::glColor4f(
|
||||
Submodel->f4Diffuse.r,
|
||||
Submodel->f4Diffuse.g,
|
||||
Submodel->f4Diffuse.b,
|
||||
Submodel->fVisible );
|
||||
}
|
||||
else {
|
||||
::glColor3fv( glm::value_ptr( Submodel->f4Diffuse ) ); // McZapkie-240702: zamiast ub
|
||||
}
|
||||
// ...specular...
|
||||
if( ( true == m_renderspecular ) && ( m_sunlight.specular.a > 0.01f ) ) {
|
||||
// specular strength in legacy models is set uniformly to 150, 150, 150 so we scale it down for opaque elements
|
||||
::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( Submodel->f4Specular * m_sunlight.specular.a * m_specularopaquescalefactor ) );
|
||||
@@ -2466,6 +2479,10 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
}
|
||||
*/
|
||||
// post-draw reset
|
||||
if( Submodel->fVisible < 1.f ) {
|
||||
::glAlphaFunc( GL_GREATER, 0.5f );
|
||||
::glDisable( GL_BLEND );
|
||||
}
|
||||
if( ( true == m_renderspecular ) && ( m_sunlight.specular.a > 0.01f ) ) {
|
||||
::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( colors::none ) );
|
||||
}
|
||||
@@ -2557,42 +2574,65 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
float const anglefactor = clamp(
|
||||
( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( Submodel->fCosHotspotAngle - Submodel->fCosFalloffAngle ),
|
||||
0.f, 1.f );
|
||||
lightlevel *= anglefactor;
|
||||
float const precipitationfactor { interpolate( 1.f, 0.25f, clamp( Global.Overcast * 0.75f - 0.5f, 0.f, 1.f ) ) };
|
||||
lightlevel *= precipitationfactor;
|
||||
|
||||
if( lightlevel > 0.f ) {
|
||||
// distance attenuation. NOTE: since it's fixed pipeline with built-in gamma correction we're using linear attenuation
|
||||
// we're capping how much effect the distance attenuation can have, otherwise the lights get too tiny at regular distances
|
||||
float const distancefactor { std::max( 0.5f, ( Submodel->fSquareMaxDist - TSubModel::fSquareDist ) / Submodel->fSquareMaxDist ) };
|
||||
float const precipitationfactor { std::max( 1.f, Global.Overcast - 1.f ) };
|
||||
auto const pointsize { std::max( 3.f, 5.f * distancefactor * anglefactor ) };
|
||||
|
||||
if( lightlevel > 0.f ) {
|
||||
// material configuration:
|
||||
::glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_POINT_BIT );
|
||||
|
||||
Bind_Material( null_handle );
|
||||
::glPointSize( std::max( 3.f, 5.f * distancefactor * anglefactor ) );
|
||||
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], std::min( 1.f, lightlevel * anglefactor * precipitationfactor ) );
|
||||
// limit impact of dense fog on the lights
|
||||
::glFogf( GL_FOG_DENSITY, static_cast<GLfloat>( 1.0 / std::min<float>( Global.fFogEnd, m_fogrange * 2 ) ) );
|
||||
|
||||
::glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_POINT_BIT );
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glEnable( GL_BLEND );
|
||||
::glAlphaFunc( GL_GREATER, 0.f );
|
||||
|
||||
::glPushMatrix();
|
||||
::glLoadIdentity();
|
||||
::glTranslatef( lightcenter.x, lightcenter.y, lightcenter.z ); // początek układu zostaje bez zmian
|
||||
/*
|
||||
setup_shadow_color( colors::white );
|
||||
*/
|
||||
|
||||
auto const unitstate = m_unitstate;
|
||||
switch_units( m_unitstate.diffuse, false, false );
|
||||
|
||||
// main draw call
|
||||
if( Global.Overcast > 1.f ) {
|
||||
// fake fog halo
|
||||
float const fogfactor {
|
||||
interpolate(
|
||||
2.f, 1.f,
|
||||
clamp<float>( Global.fFogEnd / 2000, 0.f, 1.f ) )
|
||||
* std::max( 1.f, Global.Overcast ) };
|
||||
::glPointSize( pointsize * fogfactor );
|
||||
::glColor4f(
|
||||
Submodel->f4Diffuse[ 0 ],
|
||||
Submodel->f4Diffuse[ 1 ],
|
||||
Submodel->f4Diffuse[ 2 ],
|
||||
Submodel->fVisible * std::min( 1.f, lightlevel ) * 0.5f );
|
||||
::glDepthMask( GL_FALSE );
|
||||
m_geometry.draw( Submodel->m_geometry );
|
||||
::glDepthMask( GL_TRUE );
|
||||
}
|
||||
::glPointSize( pointsize );
|
||||
::glColor4f(
|
||||
Submodel->f4Diffuse[ 0 ],
|
||||
Submodel->f4Diffuse[ 1 ],
|
||||
Submodel->f4Diffuse[ 2 ],
|
||||
Submodel->fVisible * std::min( 1.f, lightlevel ) );
|
||||
m_geometry.draw( Submodel->m_geometry );
|
||||
|
||||
// post-draw reset
|
||||
// re-enable shadows
|
||||
/*
|
||||
setup_shadow_color( m_shadowcolor );
|
||||
*/
|
||||
switch_units( unitstate.diffuse, unitstate.shadows, unitstate.reflections );
|
||||
|
||||
::glPopMatrix();
|
||||
::glPopAttrib();
|
||||
::glFogf( GL_FOG_DENSITY, static_cast<GLfloat>( 1.0 / m_fogrange ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2649,7 +2689,9 @@ void
|
||||
opengl_renderer::Render( TTrack *Track ) {
|
||||
|
||||
if( ( Track->m_material1 == 0 )
|
||||
&& ( Track->m_material2 == 0 ) ) {
|
||||
&& ( Track->m_material2 == 0 )
|
||||
&& ( ( Track->eType != tt_Switch )
|
||||
|| ( Track->SwitchExtension->m_material3 == 0 ) ) ) {
|
||||
return;
|
||||
}
|
||||
if( false == Track->m_visible ) {
|
||||
@@ -2671,6 +2713,11 @@ opengl_renderer::Render( TTrack *Track ) {
|
||||
Bind_Material( Track->m_material2 );
|
||||
m_geometry.draw( std::begin( Track->Geometry2 ), std::end( Track->Geometry2 ) );
|
||||
}
|
||||
if( ( Track->eType == tt_Switch )
|
||||
&& ( Track->SwitchExtension->m_material3 != 0 ) ) {
|
||||
Bind_Material( Track->SwitchExtension->m_material3 );
|
||||
m_geometry.draw( Track->SwitchExtension->Geometry3 );
|
||||
}
|
||||
setup_environment_light();
|
||||
break;
|
||||
}
|
||||
@@ -2691,6 +2738,11 @@ opengl_renderer::Render( TTrack *Track ) {
|
||||
Bind_Material( Track->m_material2 );
|
||||
m_geometry.draw( std::begin( Track->Geometry2 ), std::end( Track->Geometry2 ) );
|
||||
}
|
||||
if( ( Track->eType == tt_Switch )
|
||||
&& ( Track->SwitchExtension->m_material3 != 0 ) ) {
|
||||
Bind_Material( Track->SwitchExtension->m_material3 );
|
||||
m_geometry.draw( Track->SwitchExtension->Geometry3 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rendermode::pickcontrols:
|
||||
@@ -2717,6 +2769,7 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: render auto generated trackbeds together with regular trackbeds in pass 1, and all rails in pass 2
|
||||
// first pass, material 1
|
||||
for( auto first { First }; first != Last; ++first ) {
|
||||
|
||||
@@ -2807,6 +2860,53 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
|
||||
}
|
||||
}
|
||||
}
|
||||
// third pass, material 3
|
||||
for( auto first { First }; first != Last; ++first ) {
|
||||
|
||||
auto const track { *first };
|
||||
|
||||
if( track->eType != tt_Switch ) {
|
||||
continue;
|
||||
}
|
||||
if( track->SwitchExtension->m_material3 == 0 ) {
|
||||
continue;
|
||||
}
|
||||
if( false == track->m_visible ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::color:
|
||||
case rendermode::reflections: {
|
||||
if( track->eEnvironment != e_flat ) {
|
||||
setup_environment_light( track->eEnvironment );
|
||||
}
|
||||
Bind_Material( track->SwitchExtension->m_material3 );
|
||||
m_geometry.draw( track->SwitchExtension->Geometry3 );
|
||||
if( track->eEnvironment != e_flat ) {
|
||||
// restore default lighting
|
||||
setup_environment_light();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rendermode::shadows: {
|
||||
if( ( std::abs( track->fTexHeight1 ) < 0.35f )
|
||||
|| ( ( track->iCategoryFlag == 1 )
|
||||
&& ( track->eType != tt_Normal ) ) ) {
|
||||
// shadows are only calculated for high enough trackbeds
|
||||
continue;
|
||||
}
|
||||
Bind_Material( track->SwitchExtension->m_material3 );
|
||||
m_geometry.draw( track->SwitchExtension->Geometry3 );
|
||||
break;
|
||||
}
|
||||
case rendermode::pickscenery: // pick scenery mode uses piece-by-piece approach
|
||||
case rendermode::pickcontrols:
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// post-render reset
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::shadows: {
|
||||
@@ -3083,7 +3183,7 @@ opengl_renderer::Render_Alpha( TTraction *Traction ) {
|
||||
::glLineWidth(
|
||||
clamp(
|
||||
0.5f * linealpha + Traction->WireThickness * Traction->radius() / 1000.f,
|
||||
1.f, 1.5f ) );
|
||||
1.f, 1.75f ) );
|
||||
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
|
||||
::glColor4fv(
|
||||
glm::value_ptr(
|
||||
@@ -3401,24 +3501,28 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
static_cast<float>( TSubModel::fSquareDist / Submodel->fSquareMaxDist ) ); // pozycja punktu świecącego względem kamery
|
||||
Submodel->fCosViewAngle = glm::dot( glm::normalize( modelview * glm::vec4( 0.f, 0.f, -1.f, 1.f ) - lightcenter ), glm::normalize( -lightcenter ) );
|
||||
|
||||
float glarelevel = 0.6f; // luminosity at night is at level of ~0.1, so the overall resulting transparency in clear conditions is ~0.5 at full 'brightness'
|
||||
if( Submodel->fCosViewAngle > Submodel->fCosFalloffAngle ) {
|
||||
// only bother if the viewer is inside the visibility cone
|
||||
auto glarelevel { clamp<float>(
|
||||
0.6f
|
||||
- Global.fLuminance // reduce the glare in bright daylight
|
||||
+ std::max( 0.f, Global.Overcast - 1.f ), // increase the glare in rainy/foggy conditions
|
||||
// luminosity at night is at level of ~0.1, so the overall resulting transparency in clear conditions is ~0.5 at full 'brightness'
|
||||
auto glarelevel { clamp(
|
||||
std::max<float>(
|
||||
0.6f - Global.fLuminance, // reduce the glare in bright daylight
|
||||
Global.Overcast - 1.f ), // ensure some glare in rainy/foggy conditions
|
||||
0.f, 1.f ) };
|
||||
// scale it down based on view angle
|
||||
glarelevel *= ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0f - Submodel->fCosFalloffAngle );
|
||||
// view angle attenuation
|
||||
float const anglefactor { clamp(
|
||||
( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( Submodel->fCosHotspotAngle - Submodel->fCosFalloffAngle ),
|
||||
0.f, 1.f ) };
|
||||
glarelevel *= anglefactor;
|
||||
|
||||
if( glarelevel > 0.0f ) {
|
||||
// setup
|
||||
::glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT );
|
||||
|
||||
Bind_Texture( m_glaretexture );
|
||||
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], glarelevel );
|
||||
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], Submodel->fVisible * glarelevel );
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glDisable( GL_FOG );
|
||||
::glDepthMask( GL_FALSE );
|
||||
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
|
||||
@@ -3823,8 +3927,13 @@ opengl_renderer::Init_caps() {
|
||||
+ " Vendor: " + std::string( (char *)glGetString( GL_VENDOR ) )
|
||||
+ " OpenGL Version: " + oglversion );
|
||||
|
||||
#ifdef EU07_USEIMGUIIMPLOPENGL2
|
||||
if( !GLEW_VERSION_1_5 ) {
|
||||
ErrorLog( "Requires openGL >= 1.5" );
|
||||
#else
|
||||
if( !GLEW_VERSION_3_0 ) {
|
||||
ErrorLog( "Requires openGL >= 3.0" ); // technically 1.5 for now, but imgui wants more
|
||||
ErrorLog( "Requires openGL >= 3.0" );
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -385,6 +385,7 @@ private:
|
||||
|
||||
glm::vec4 m_baseambient { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
glm::vec4 m_shadowcolor { colors::shadow };
|
||||
float m_fogrange { 2000.f };
|
||||
// TEnvironmentType m_environment { e_flat };
|
||||
float m_specularopaquescalefactor { 1.f };
|
||||
float m_speculartranslucentscalefactor { 1.f };
|
||||
|
||||
22
scene.cpp
22
scene.cpp
@@ -1156,9 +1156,31 @@ basic_region::RadioStop( glm::dvec3 const &Location ) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> switchtrackbedtextures {
|
||||
"rozkrz8r150-1pods-new",
|
||||
"rozkrz8r150-2pods-new",
|
||||
"rozkrz34r150-tpbps-new2",
|
||||
"rozkrz34r150-tpd1",
|
||||
"rkpd34r190-tpd1",
|
||||
"rkpd34r190-tpd2",
|
||||
"rkpd34r190-tpd-oil2",
|
||||
"zwr41r500",
|
||||
"zwrot-tpd-oil1",
|
||||
"zwrot34r300pods-new" };
|
||||
|
||||
void
|
||||
basic_region::insert( shape_node Shape, scratch_data &Scratchpad, bool const Transform ) {
|
||||
|
||||
if( Global.CreateSwitchTrackbeds ) {
|
||||
|
||||
auto const materialname{ GfxRenderer.Material( Shape.data().material ).name };
|
||||
for( auto const &switchtrackbedtexture : switchtrackbedtextures ) {
|
||||
if( materialname.find( switchtrackbedtexture ) != std::string::npos ) {
|
||||
// geometry with blacklisted texture, part of old switch trackbed; ignore it
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// shape might need to be split into smaller pieces, so we create list of nodes instead of just single one
|
||||
// using deque so we can do single pass iterating and addding generated pieces without invalidating anything
|
||||
std::deque<shape_node> shapes { Shape };
|
||||
|
||||
@@ -161,7 +161,15 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch
|
||||
std::string token { Input.getToken<std::string>() };
|
||||
if( token != "endatmo" ) {
|
||||
// optional overcast parameter
|
||||
Global.Overcast = clamp( std::stof( token ), 0.f, 2.f );
|
||||
Global.Overcast = std::stof( token );
|
||||
if( Global.Overcast < 0.f ) {
|
||||
// negative overcast means random value in range 0-abs(specified range)
|
||||
Global.Overcast =
|
||||
Random(
|
||||
clamp(
|
||||
std::abs( Global.Overcast ),
|
||||
0.f, 2.f ) );
|
||||
}
|
||||
// overcast drives weather so do a calculation here
|
||||
// NOTE: ugly, clean it up when we're done with world refactoring
|
||||
simulation::Environment.compute_weather();
|
||||
@@ -432,7 +440,16 @@ state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratch
|
||||
|| ( nodedata.type == "triangle_strip" )
|
||||
|| ( nodedata.type == "triangle_fan" ) ) {
|
||||
|
||||
if( false == Scratchpad.binary.terrain ) {
|
||||
auto const skip {
|
||||
// all shapes will be loaded from the binary version of the file
|
||||
( true == Scratchpad.binary.terrain )
|
||||
// crude way to detect fixed switch trackbed geometry
|
||||
|| ( ( true == Global.CreateSwitchTrackbeds )
|
||||
&& ( Input.Name().size() >= 15 )
|
||||
&& ( Input.Name().substr( 0, 11 ) == "scenery/zwr" )
|
||||
&& ( Input.Name().substr( Input.Name().size() - 4 ) == ".inc" ) ) };
|
||||
|
||||
if( false == skip ) {
|
||||
|
||||
simulation::Region->insert(
|
||||
scene::shape_node().import(
|
||||
@@ -441,7 +458,6 @@ state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratch
|
||||
true );
|
||||
}
|
||||
else {
|
||||
// all shapes were already loaded from the binary version of the file
|
||||
skip_until( Input, "endtri" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ init() {
|
||||
"Devices: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nPower transfers: %.0f@%.0f%s%s%s%.0f@%.0f",
|
||||
" radio: ",
|
||||
" oil pressure: ",
|
||||
"Controllers:\n master: %d(%d), secondary: %s\nEngine output: %.1f, current: %.0f\nRevolutions:\n engine: %.0f, motors: %.0f, ventilators: %.0f, fans: %.0f+%.0f",
|
||||
"Controllers:\n master: %d(%d), secondary: %s\nEngine output: %.1f, current: %.0f\nRevolutions:\n engine: %.0f, motors: %.0f\n engine fans: %.0f, motor fans: %.0f+%.0f, cooling fans: %.0f+%.0f",
|
||||
" (shunt mode)",
|
||||
"\nTemperatures:\n engine: %.2f, oil: %.2f, water: %.2f%c%.2f",
|
||||
"Brakes:\n train: %.2f, independent: %.2f, delay: %s, load flag: %d\nBrake cylinder pressures:\n train: %.2f, independent: %.2f, status: 0x%.2x\nPipe pressures:\n brake: %.2f (hat: %.2f), main: %.2f, control: %.2f\nTank pressures:\n auxiliary: %.2f, main: %.2f, control: %.2f",
|
||||
@@ -80,6 +80,9 @@ init() {
|
||||
"water circuits link",
|
||||
"fuel pump",
|
||||
"oil pump",
|
||||
"motor blowers A",
|
||||
"motor blowers B",
|
||||
"all motor blowers",
|
||||
"line breaker",
|
||||
"line breaker",
|
||||
"alerter",
|
||||
@@ -188,7 +191,7 @@ init() {
|
||||
"Urzadzenia: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nTransfer pradow: %.0f@%.0f%s%s%s%.0f@%.0f",
|
||||
" radio: ",
|
||||
" cisn.oleju: ",
|
||||
"Nastawniki:\n glowny: %d(%d), dodatkowy: %s\nMoc silnika: %.1f, prad silnika: %.0f\nObroty:\n silnik: %.0f, motory: %.0f, went.silnika: %.0f, went.chlodnicy: %.0f+%.0f",
|
||||
"Nastawniki:\n glowny: %d(%d), dodatkowy: %s\nMoc silnika: %.1f, prad silnika: %.0f\nObroty:\n silnik: %.0f, motory: %.0f\n went.silnika: %.0f, went.motorow: %.0f+%.0f, went.chlodnicy: %.0f+%.0f",
|
||||
" (tryb manewrowy)",
|
||||
"\nTemperatury:\n silnik: %.2f, olej: %.2f, woda: %.2f%c%.2f",
|
||||
"Hamulce:\n zespolony: %.2f, pomocniczy: %.2f, nastawa: %s, ladunek: %d\nCisnienie w cylindrach:\n zespolony: %.2f, pomocniczy: %.2f, status: 0x%.2x\nCisnienia w przewodach:\n glowny: %.2f (kapturek: %.2f), zasilajacy: %.2f, kontrolny: %.2f\nCisnienia w zbiornikach:\n pomocniczy: %.2f, glowny: %.2f, sterujacy: %.2f",
|
||||
@@ -214,6 +217,9 @@ init() {
|
||||
"zawor polaczenia obiegow wody",
|
||||
"pompa paliwa",
|
||||
"pompa oleju",
|
||||
"wentylatory silnikow trakcyjnych A",
|
||||
"wentylatory silnikow trakcyjnych B",
|
||||
"wszystkie wentylatory silnikow trakcyjnych",
|
||||
"wylacznik szybki",
|
||||
"wylacznik szybki",
|
||||
"czuwak",
|
||||
@@ -320,6 +326,9 @@ init() {
|
||||
"watercircuitslink_sw:",
|
||||
"fuelpump_sw:",
|
||||
"oilpump_sw:",
|
||||
"motorblowersfront_sw:",
|
||||
"motorblowersrear_sw:",
|
||||
"motorblowersalloff_sw:",
|
||||
"main_off_bt:",
|
||||
"main_on_bt:",
|
||||
"security_reset_bt:",
|
||||
|
||||
@@ -69,6 +69,9 @@ enum string {
|
||||
cab_watercircuitslink_sw,
|
||||
cab_fuelpump_sw,
|
||||
cab_oilpump_sw,
|
||||
cab_motorblowersfront_sw,
|
||||
cab_motorblowersrear_sw,
|
||||
cab_motorblowersalloff_sw,
|
||||
cab_main_off_bt,
|
||||
cab_main_on_bt,
|
||||
cab_security_reset_bt,
|
||||
|
||||
26
uilayer.cpp
26
uilayer.cpp
@@ -15,7 +15,11 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Logs.h"
|
||||
|
||||
#include "imgui/imgui_impl_glfw.h"
|
||||
#ifdef EU07_USEIMGUIIMPLOPENGL2
|
||||
#include "imgui/imgui_impl_opengl2.h"
|
||||
#else
|
||||
#include "imgui/imgui_impl_opengl3.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C"
|
||||
@@ -100,11 +104,16 @@ ui_layer::init( GLFWwindow *Window ) {
|
||||
m_imguiio = &ImGui::GetIO();
|
||||
m_imguiio->Fonts->AddFontFromFileTTF("DejaVuSansMono.ttf", 13.0f);
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(m_window);
|
||||
ImGui_ImplOpenGL3_Init("#version 130");
|
||||
ImGui::StyleColorsClassic();
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(m_window);
|
||||
#ifdef EU07_USEIMGUIIMPLOPENGL2
|
||||
ImGui_ImplOpenGL2_Init();
|
||||
ImGui_ImplOpenGL2_NewFrame();
|
||||
#else
|
||||
ImGui_ImplOpenGL3_Init("#version 130");
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
#endif
|
||||
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
@@ -115,7 +124,11 @@ void
|
||||
ui_layer::shutdown() {
|
||||
ImGui::EndFrame();
|
||||
|
||||
#ifdef EU07_USEIMGUIIMPLOPENGL2
|
||||
ImGui_ImplOpenGL2_Shutdown();
|
||||
#else
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
#endif
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
@@ -183,9 +196,14 @@ ui_layer::render() {
|
||||
render_();
|
||||
|
||||
ImGui::Render();
|
||||
#ifdef EU07_USEIMGUIIMPLOPENGL2
|
||||
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
|
||||
ImGui_ImplOpenGL2_NewFrame();
|
||||
#else
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
#endif
|
||||
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user