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:
@@ -551,7 +551,7 @@ void TAnimModel::RaAnimate( unsigned int const Framestamp ) {
|
||||
|
||||
// Ra 2F1I: to by można pomijać dla modeli bez animacji, których jest większość
|
||||
TAnimContainer *pCurrent;
|
||||
for (pCurrent = pRoot; pCurrent != NULL; pCurrent = pCurrent->pNext)
|
||||
for (pCurrent = pRoot; pCurrent != nullptr; pCurrent = pCurrent->pNext)
|
||||
if (!pCurrent->evDone) // jeśli jest bez eventu
|
||||
pCurrent->UpdateModel(); // przeliczenie animacji każdego submodelu
|
||||
// if () //tylko dla modeli z IK !!!!
|
||||
|
||||
@@ -125,6 +125,7 @@ class TAnimAdvanced
|
||||
class TAnimModel : public scene::basic_node {
|
||||
|
||||
friend class opengl_renderer;
|
||||
friend class ui_layer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
@@ -151,7 +152,7 @@ public:
|
||||
return &m_materialdata; }
|
||||
inline
|
||||
TModel3d *
|
||||
Model() {
|
||||
Model() const {
|
||||
return pModel; }
|
||||
// members
|
||||
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
|
||||
|
||||
232
Driver.cpp
232
Driver.cpp
@@ -520,7 +520,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
||||
pTrack = lastspeedpoint.trTrack;
|
||||
assert( pTrack != nullptr );
|
||||
// flaga ustawiona, gdy Point2 toru jest blizej
|
||||
fLastDir = lastspeedpoint.iFlags & spReverse ? -1.0 : 1.0;
|
||||
fLastDir = ( ( ( lastspeedpoint.iFlags & spReverse ) != 0 ) ? -1.0 : 1.0 );
|
||||
fCurrentDistance = lastspeedpoint.fDist; // aktualna odleglosc do jego Point1
|
||||
fTrackLength = pTrack->Length();
|
||||
}
|
||||
@@ -858,6 +858,35 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
} // koniec obsługi przelotu na W4
|
||||
else {
|
||||
// zatrzymanie na W4
|
||||
if ( ( false == sSpeedTable[i].bMoved )
|
||||
&& ( ( OrderCurrentGet() & ( Obey_train | Shunt ) ) != 0 ) ) {
|
||||
// potentially shift the stop point in accordance with its defined parameters
|
||||
/*
|
||||
// https://rainsted.com/pl/Wersja/18.2.133#Okr.C4.99gi_dla_W4_i_W32
|
||||
Pierwszy parametr ujemny - preferowane zatrzymanie czoła składu (np. przed przejściem).
|
||||
Pierwszy parametr dodatni - preferowane zatrzymanie środka składu (np. przy wiacie, przejściu podziemnym).
|
||||
Drugi parametr ujemny - wskazanie zatrzymania dla krótszych składów (W32).
|
||||
Drugi paramer dodatni - długość peronu (W4).
|
||||
*/
|
||||
auto L = 0.0;
|
||||
auto Par1 = sSpeedTable[i].evEvent->ValueGet(1);
|
||||
auto Par2 = sSpeedTable[i].evEvent->ValueGet(2);
|
||||
if ((Par2 >= 0) || (fLength < -Par2)) { //użyj tego W4
|
||||
if (Par1 < 0) {
|
||||
L = -Par1;
|
||||
}
|
||||
else {
|
||||
//środek
|
||||
L = Par1 - fMinProximityDist - fLength * 0.5;
|
||||
}
|
||||
L = std::max(0.0, std::min(L, std::abs(Par2) - fMinProximityDist - fLength));
|
||||
sSpeedTable[i].UpdateDistance(L);
|
||||
sSpeedTable[i].bMoved = true;
|
||||
}
|
||||
else {
|
||||
sSpeedTable[i].iFlags = 0;
|
||||
}
|
||||
}
|
||||
isatpassengerstop = (
|
||||
// Ra 2F1I: odległość plus długość pociągu musi być mniejsza od długości
|
||||
// peronu, chyba że pociąg jest dłuższy, to wtedy minimalna.
|
||||
@@ -866,7 +895,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
( iDrivigFlags & moveStopCloser ) ?
|
||||
( sSpeedTable[ i ].fDist + fLength ) <=
|
||||
std::max(
|
||||
sSpeedTable[ i ].evEvent->ValueGet( 2 ),
|
||||
std::abs( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ),
|
||||
2.0 * fMaxProximityDist + fLength ) : // fmaxproximitydist typically equals ~50 m
|
||||
sSpeedTable[ i ].fDist < d_to_next_sem );
|
||||
|
||||
@@ -969,7 +998,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
// NOTE: this calculation is expected to run after completing loading/unloading
|
||||
AutoRewident(); // nastawianie hamulca do jazdy pociągowej
|
||||
|
||||
if( int( floor( sSpeedTable[ i ].evEvent->ValueGet( 1 ) ) ) & 1 ) {
|
||||
if( static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->ValueGet( 1 ) ) ) ) % 2 ) {
|
||||
// nie podjeżdżać do semafora, jeśli droga nie jest wolna
|
||||
iDrivigFlags |= moveStopHere;
|
||||
}
|
||||
@@ -1201,26 +1230,29 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
sSpeedTable[ i ].iFlags = 0;
|
||||
}
|
||||
}
|
||||
else if (go == cm_Unknown) // jeśli jeszcze nie ma komendy
|
||||
if (v != 0.0) // komenda jest tylko gdy ma jechać, bo stoi na podstawie
|
||||
// tabelki
|
||||
{ // jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie
|
||||
// VelSignal
|
||||
else if( go == cm_Unknown ) {
|
||||
// jeśli jeszcze nie ma komendy
|
||||
// komenda jest tylko gdy ma jechać, bo stoi na podstawietabelki
|
||||
if( v != 0.0 ) {
|
||||
// jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie VelSignal
|
||||
go = cm_ShuntVelocity; // w trybie pociągowym tylko jeśli włącza
|
||||
// tryb manewrowy (v!=0.0)
|
||||
// Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo Tm może być
|
||||
// daleko
|
||||
// VelSignal=v; //nie do końca tak, to jest druga prędkość
|
||||
if (VelSignal == 0.0)
|
||||
VelSignal = v; // aby stojący ruszył
|
||||
if (sSpeedTable[i].fDist < 0.0) // jeśli przejechany
|
||||
{
|
||||
VelSignal = v; //!!! ustawienie, gdy przejechany jest lepsze niż
|
||||
// wcale, ale to jeszcze nie to
|
||||
sSpeedTable[i].iFlags =
|
||||
0; // to można usunąć (nie mogą być usuwane w skanowaniu)
|
||||
if( VelSignal == 0.0 ) {
|
||||
// aby stojący ruszył
|
||||
VelSignal = v;
|
||||
}
|
||||
if( sSpeedTable[ i ].fDist < 0.0 ) {
|
||||
// jeśli przejechany
|
||||
//!!! ustawienie, gdy przejechany jest lepsze niż wcale, ale to jeszcze nie to
|
||||
VelSignal = v;
|
||||
// to można usunąć (nie mogą być usuwane w skanowaniu)
|
||||
sSpeedTable[ i ].iFlags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( !( sSpeedTable[ i ].iFlags & spSectionVel ) ) {
|
||||
//jeśli jakiś event pasywny ale nie ograniczenie
|
||||
@@ -1285,7 +1317,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
&& ( true == TestFlag( sSpeedTable[ i ].iFlags, ( spEnabled | spEvent | spPassengerStopPoint ) ) )
|
||||
&& ( false == isatpassengerstop ) ) {
|
||||
// ma podjechać bliżej - czy na pewno w tym miejscu taki warunek?
|
||||
a = ( iDrivigFlags & moveStopCloser ?
|
||||
a = ( ( ( iDrivigFlags & moveStopCloser ) != 0 ) ?
|
||||
fAcc :
|
||||
0.0 );
|
||||
}
|
||||
@@ -2699,65 +2731,69 @@ bool TController::IncSpeed()
|
||||
if (!mvControlling->FuseFlag) //&&mvControlling->StLinFlag) //yBARC
|
||||
if ((mvControlling->MainCtrlPos == 0) ||
|
||||
(mvControlling->StLinFlag)) // youBy polecił dodać 2012-09-08 v367
|
||||
// na pozycji 0 przejdzie, a na pozostałych będzie czekać, aż się załączą liniowe
|
||||
// (zgaśnie DelayCtrlFlag)
|
||||
if (Ready || (iDrivigFlags & movePress))
|
||||
{
|
||||
bool scndctrl = ((mvOccupied->Vel <= 30) ||
|
||||
(mvControlling->Imax > mvControlling->ImaxLo) ||
|
||||
(fVoltage + fVoltage <
|
||||
mvControlling->EnginePowerSource.CollectorParameters.MinV +
|
||||
mvControlling->EnginePowerSource.CollectorParameters.MaxV) ||
|
||||
(mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo));
|
||||
scndctrl = ((scndctrl) && (mvControlling->MainCtrlPos > 1) && (mvControlling->RList[mvControlling->MainCtrlActualPos].R < 0.01)&& (mvControlling->ScndCtrlPos != mvControlling->ScndCtrlPosNo));
|
||||
double Vs = 99999;
|
||||
if((mvControlling->MainCtrlPos != mvControlling->MainCtrlPosNo)||(mvControlling->ScndCtrlPos!=mvControlling->ScndCtrlPosNo))
|
||||
Vs = ESMVelocity(!scndctrl);
|
||||
// na pozycji 0 przejdzie, a na pozostałych będzie czekać, aż się załączą liniowe (zgaśnie DelayCtrlFlag)
|
||||
if (Ready || (iDrivigFlags & movePress)) {
|
||||
// use series mode to build up speed, when high threshold is set for motor overload relay or if the power station is heavily burdened
|
||||
auto const useseriesmodevoltage { 0.85 * mvControlling->EnginePowerSource.CollectorParameters.MaxV };
|
||||
auto const useseriesmode = (
|
||||
( mvOccupied->Vel <= ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ? 35 : 25 ) + ( mvControlling->ScndCtrlPos == 0 ? 0 : 5 ) )
|
||||
|| ( mvControlling->Imax > mvControlling->ImaxLo )
|
||||
|| ( fVoltage < useseriesmodevoltage ) );
|
||||
|
||||
if ((fabs(mvControlling->Im) <
|
||||
(fReady < 0.4 ? mvControlling->Imin : mvControlling->IminLo))||(mvControlling->Vel>Vs))
|
||||
{ // Ra: wywalał nadmiarowy, bo Im może być ujemne; jak nie odhamowany, to nie
|
||||
// przesadzać z prądem
|
||||
if ((mvOccupied->Vel <= 30) ||
|
||||
(mvControlling->Imax > mvControlling->ImaxLo) ||
|
||||
(fVoltage + fVoltage <
|
||||
mvControlling->EnginePowerSource.CollectorParameters.MinV +
|
||||
mvControlling->EnginePowerSource.CollectorParameters.MaxV))
|
||||
{ // bocznik na szeregowej przy ciezkich bruttach albo przy wysokim rozruchu
|
||||
// pod górę albo przy niskim napięciu
|
||||
if (mvControlling->MainCtrlPos ?
|
||||
mvControlling->RList[mvControlling->MainCtrlPos].R > 0.0 :
|
||||
true) // oporowa
|
||||
{
|
||||
OK = (mvControlling->DelayCtrlFlag ?
|
||||
true :
|
||||
mvControlling->IncMainCtrl(1)); // kręcimy nastawnik jazdy
|
||||
if ((OK) &&
|
||||
(mvControlling->MainCtrlPos ==
|
||||
1)) // czekaj na 1 pozycji, zanim się nie włączą liniowe
|
||||
iDrivigFlags |= moveIncSpeed;
|
||||
else
|
||||
iDrivigFlags &= ~moveIncSpeed; // usunięcie flagi czekania
|
||||
}
|
||||
else // jeśli bezoporowa (z wyjątekiem 0)
|
||||
OK = false; // to dać bocznik
|
||||
}
|
||||
else
|
||||
{ // przekroczone 30km/h, można wejść na jazdę równoległą
|
||||
if (mvControlling->ScndCtrlPos) // jeśli ustawiony bocznik
|
||||
if (mvControlling->MainCtrlPos <
|
||||
mvControlling->MainCtrlPosNo - 1) // a nie jest ostatnia pozycja
|
||||
mvControlling->DecScndCtrl(2); // to bocznik na zero po chamsku
|
||||
// (ktoś miał to poprawić...)
|
||||
OK = mvControlling->IncMainCtrl(1);
|
||||
}
|
||||
if ((mvControlling->MainCtrlPos > 2) &&
|
||||
(mvControlling->Im == 0)) // brak prądu na dalszych pozycjach
|
||||
Need_TryAgain = true; // nie załączona lokomotywa albo wywalił
|
||||
// nadmiarowy
|
||||
else if (!OK) // nie da się wrzucić kolejnej pozycji
|
||||
OK = mvControlling->IncScndCtrl(1); // to dać bocznik
|
||||
auto const scndctrl = (
|
||||
( mvControlling->StLinFlag )
|
||||
&& ( mvControlling->RList[ mvControlling->MainCtrlActualPos ].R < 0.01 )
|
||||
&& ( useseriesmode ?
|
||||
mvControlling->RList[ mvControlling->MainCtrlActualPos ].Bn == 1 :
|
||||
mvControlling->RList[ mvControlling->MainCtrlActualPos ].Bn > 1 ) );
|
||||
|
||||
double Vs = 99999;
|
||||
if( scndctrl ?
|
||||
( mvControlling->ScndCtrlPos < mvControlling->ScndCtrlPosNo ) :
|
||||
( mvControlling->MainCtrlPos < mvControlling->MainCtrlPosNo ) ) {
|
||||
Vs = ESMVelocity( !scndctrl );
|
||||
}
|
||||
|
||||
if( ( std::abs( mvControlling->Im ) < ( fReady < 0.4 ? mvControlling->Imin : mvControlling->IminLo ) )
|
||||
|| ( mvControlling->Vel > Vs ) ) {
|
||||
// Ra: wywalał nadmiarowy, bo Im może być ujemne; jak nie odhamowany, to nie przesadzać z prądem
|
||||
if( scndctrl ) {
|
||||
// to dać bocznik
|
||||
// engage the shuntfield only if there's sufficient power margin to draw from
|
||||
OK = (
|
||||
fVoltage > useseriesmodevoltage + 0.0125 * mvControlling->EnginePowerSource.CollectorParameters.MaxV ?
|
||||
mvControlling->IncScndCtrl( 1 ) :
|
||||
false );
|
||||
}
|
||||
else {
|
||||
// jeśli ustawiony bocznik to bocznik na zero po chamsku
|
||||
if( mvControlling->ScndCtrlPos ) {
|
||||
mvControlling->DecScndCtrl( 2 );
|
||||
}
|
||||
// kręcimy nastawnik jazdy
|
||||
OK = (
|
||||
mvControlling->DelayCtrlFlag ?
|
||||
true :
|
||||
mvControlling->IncMainCtrl( 1 ) );
|
||||
// czekaj na 1 pozycji, zanim się nie włączą liniowe
|
||||
if( true == mvControlling->StLinFlag ) {
|
||||
iDrivigFlags |= moveIncSpeed;
|
||||
}
|
||||
else {
|
||||
iDrivigFlags &= ~moveIncSpeed;
|
||||
}
|
||||
|
||||
if( ( mvControlling->Im == 0 )
|
||||
&& ( mvControlling->MainCtrlPos > 2 ) ) {
|
||||
// brak prądu na dalszych pozycjach
|
||||
// nie załączona lokomotywa albo wywalił nadmiarowy
|
||||
Need_TryAgain = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
OK = false;
|
||||
}
|
||||
}
|
||||
mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania
|
||||
break;
|
||||
@@ -2943,11 +2979,8 @@ void TController::SpeedSet()
|
||||
break;
|
||||
case ElectricSeriesMotor:
|
||||
if( ( false == mvControlling->StLinFlag )
|
||||
&& ( false == mvControlling->DelayCtrlFlag )
|
||||
&& ( 0 == ( iDrivigFlags & moveIncSpeed ) ) ) // styczniki liniowe rozłączone yBARC
|
||||
{
|
||||
// if (iDrivigFlags&moveIncSpeed) {} //jeśli czeka na załączenie liniowych
|
||||
// else
|
||||
&& ( false == mvControlling->DelayCtrlFlag ) ) {
|
||||
// styczniki liniowe rozłączone yBARC
|
||||
while( DecSpeed() )
|
||||
; // zerowanie napędu
|
||||
}
|
||||
@@ -3820,6 +3853,28 @@ TController::UpdateSituation(double dt) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if( fVoltage < 0.8 * mvControlling->EnginePowerSource.CollectorParameters.MaxV ) {
|
||||
// if the power station is heavily burdened try to reduce the load
|
||||
switch( mvControlling->EngineType ) {
|
||||
|
||||
case ElectricSeriesMotor: {
|
||||
if( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) {
|
||||
// limit yourself to series mode
|
||||
if( mvControlling->ScndCtrlPos ) {
|
||||
mvControlling->DecScndCtrl( 2 );
|
||||
}
|
||||
while( ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 )
|
||||
&& ( mvControlling->DecMainCtrl( 1 ) ) ) {
|
||||
; // all work is performed in the header
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( ( IdleTime > 45.0 )
|
||||
@@ -4574,14 +4629,14 @@ TController::UpdateSituation(double dt) {
|
||||
else {
|
||||
// jeśli oba jadą, to przyhamuj lekko i ogranicz prędkość
|
||||
if( vehicle->fTrackBlock < (
|
||||
mvOccupied->CategoryFlag & 2 ?
|
||||
( mvOccupied->CategoryFlag & 2 ) ?
|
||||
fMaxProximityDist + 0.5 * vel : // cars
|
||||
2.0 * fMaxProximityDist + 2.0 * vel ) ) { //others
|
||||
// jak tamten jedzie wolniej a jest w drodze hamowania
|
||||
AccPreferred = std::min( -0.9, AccPreferred );
|
||||
VelNext = min_speed( std::round( k ) - 5.0, VelDesired );
|
||||
if( vehicle->fTrackBlock <= (
|
||||
mvOccupied->CategoryFlag & 2 ?
|
||||
( mvOccupied->CategoryFlag & 2 ) ?
|
||||
fMaxProximityDist : // cars
|
||||
2.0 * fMaxProximityDist ) ) { //others
|
||||
// try to force speed change if obstacle is really close
|
||||
@@ -4647,22 +4702,13 @@ TController::UpdateSituation(double dt) {
|
||||
VelDesired,
|
||||
TrainParams->TTVmax );
|
||||
}
|
||||
|
||||
if( ( ( iDrivigFlags & moveStopHere ) != 0 )
|
||||
&& ( vel < 0.01 )
|
||||
&& ( SemNextIndex != -1 )
|
||||
&& ( SemNextIndex < sSpeedTable.size() ) // BUG: index can point at non-existing slot. investigate reason(s)
|
||||
&& ( sSpeedTable[ SemNextIndex ].fVelNext == 0.0 ) ) {
|
||||
// don't depart if told to wait at passenger stop until allowed to by the signal
|
||||
VelDesired = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
if( ( OrderCurrentGet() & ( Shunt | Obey_train ) ) != 0 ) {
|
||||
// w Connect nie, bo moveStopHere odnosi się do stanu po połączeniu
|
||||
if( ( ( iDrivigFlags & moveStopHere ) != 0 )
|
||||
&& ( vel < 0.01 )
|
||||
&& ( VelSignal == 0.0 ) ) {
|
||||
&& ( VelSignalNext == 0.0 ) ) {
|
||||
// jeśli ma czekać na wolną drogę, stoi a wyjazdu nie ma, to ma stać
|
||||
VelDesired = 0.0;
|
||||
}
|
||||
@@ -4825,7 +4871,7 @@ TController::UpdateSituation(double dt) {
|
||||
else {
|
||||
// jeśli daleko jechać nie można
|
||||
if( ActualProximityDist > (
|
||||
mvOccupied->CategoryFlag & 2 ?
|
||||
( mvOccupied->CategoryFlag & 2 ) ?
|
||||
fMinProximityDist : // cars
|
||||
fMaxProximityDist ) ) { // trains and others
|
||||
// ale ma kawałek do sygnalizatora
|
||||
@@ -5133,7 +5179,7 @@ TController::UpdateSituation(double dt) {
|
||||
VelDesired - fVelMinus ) ) {
|
||||
// ...jeśli prędkość w kierunku czoła jest mniejsza od dozwolonej o margines
|
||||
if( ( ActualProximityDist > (
|
||||
mvOccupied->CategoryFlag & 2 ?
|
||||
( mvOccupied->CategoryFlag & 2 ) ?
|
||||
fMinProximityDist : // cars are allowed to move within min proximity distance
|
||||
fMaxProximityDist ) ? // other vehicle types keep wider margin
|
||||
true :
|
||||
|
||||
1
Driver.h
1
Driver.h
@@ -131,6 +131,7 @@ class TSpeedPos
|
||||
// zwrotnicy,32-minięty,64=koniec,128=łuk
|
||||
// 0x100=event,0x200=manewrowa,0x400=przystanek,0x800=SBL,0x1000=wysłana komenda,0x2000=W5
|
||||
// 0x4000=semafor,0x10000=zatkanie
|
||||
bool bMoved{ false }; // czy przesunięty (dotyczy punktu zatrzymania w peronie)
|
||||
Math3D::vector3 vPos; // współrzędne XYZ do liczenia odległości
|
||||
struct
|
||||
{
|
||||
|
||||
166
Event.cpp
166
Event.cpp
@@ -39,7 +39,6 @@ TEvent::~TEvent() {
|
||||
switch (Type)
|
||||
{ // sprzątanie
|
||||
case tp_Multiple:
|
||||
// SafeDeleteArray(Params[9].asText); //nie usuwać - nazwa obiektu powiązanego zamieniana na wskaźnik
|
||||
if (iFlags & conditional_memstring) // o ile jest łańcuch do porównania w memcompare
|
||||
SafeDeleteArray(Params[10].asText);
|
||||
break;
|
||||
@@ -68,12 +67,6 @@ void TEvent::Conditions(cParser *parser, std::string s)
|
||||
if (s == "condition")
|
||||
{ // jesli nie "endevent"
|
||||
std::string token, str;
|
||||
if (!asNodeName.empty())
|
||||
{ // podczepienie łańcucha, jeśli nie jest pusty
|
||||
// BUG: source of a memory leak -- the array never gets deleted. fix the destructor
|
||||
Params[9].asText = new char[asNodeName.size() + 1]; // usuwane i zamieniane na wskaźnik
|
||||
strcpy(Params[9].asText, asNodeName.c_str());
|
||||
}
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
str = token;
|
||||
@@ -986,75 +979,76 @@ event_manager::FindEvent( std::string const &Name ) {
|
||||
|
||||
// legacy method, inserts specified event in the event query
|
||||
bool
|
||||
event_manager::AddToQuery( TEvent *Event, TDynamicObject *Owner, double delay ) {
|
||||
event_manager::AddToQuery( TEvent *Event, TDynamicObject const *Owner, double delay ) {
|
||||
|
||||
if( true == Event->bEnabled ) {
|
||||
// jeśli może być dodany do kolejki (nie używany w skanowaniu)
|
||||
if( !Event->iQueued ) // jeśli nie dodany jeszcze do kolejki
|
||||
{ // kolejka eventów jest posortowana względem (fStartTime)
|
||||
Event->Activator = Owner;
|
||||
if( ( Event->Type == tp_AddValues )
|
||||
&& ( Event->fDelay == 0.0 ) ) {
|
||||
// eventy AddValues trzeba wykonywać natychmiastowo, inaczej kolejka może zgubić jakieś dodawanie
|
||||
// Ra: kopiowanie wykonania tu jest bez sensu, lepiej by było wydzielić funkcję
|
||||
// wykonującą eventy i ją wywołać
|
||||
if( ( false == Event->m_ignored )
|
||||
&& ( true == EventConditon( Event ) ) ) { // teraz mogą być warunki do tych eventów
|
||||
if( false == Event->bEnabled ) { return false; }
|
||||
if( Event->iQueued != 0 ) { return false; }
|
||||
// jeśli może być dodany do kolejki (nie używany w skanowaniu)
|
||||
// jeśli nie dodany jeszcze do kolejki
|
||||
|
||||
// kolejka eventów jest posortowana względem (fStartTime)
|
||||
Event->Activator = Owner;
|
||||
if( ( Event->Type == tp_AddValues )
|
||||
&& ( Event->fDelay == 0.0 ) ) {
|
||||
// eventy AddValues trzeba wykonywać natychmiastowo, inaczej kolejka może zgubić jakieś dodawanie
|
||||
// Ra: kopiowanie wykonania tu jest bez sensu, lepiej by było wydzielić funkcję
|
||||
// wykonującą eventy i ją wywołać
|
||||
if( ( false == Event->m_ignored )
|
||||
&& ( true == EventConditon( Event ) ) ) { // teraz mogą być warunki do tych eventów
|
||||
|
||||
Event->Params[ 5 ].asMemCell->UpdateValues(
|
||||
Event->Params[ 0 ].asText, Event->Params[ 1 ].asdouble,
|
||||
Event->Params[ 2 ].asdouble, Event->iFlags );
|
||||
Event->Params[ 5 ].asMemCell->UpdateValues(
|
||||
Event->Params[ 0 ].asText, Event->Params[ 1 ].asdouble,
|
||||
Event->Params[ 2 ].asdouble, Event->iFlags );
|
||||
|
||||
if( Event->Params[ 6 ].asTrack ) { // McZapkie-100302 - updatevalues oprocz zmiany wartosci robi putcommand dla
|
||||
// wszystkich 'dynamic' na danym torze
|
||||
for( auto dynamic : Event->Params[ 6 ].asTrack->Dynamics ) {
|
||||
Event->Params[ 5 ].asMemCell->PutCommand(
|
||||
dynamic->Mechanik,
|
||||
Event->Params[ 4 ].asLocation );
|
||||
}
|
||||
//if (DebugModeFlag)
|
||||
WriteLog(
|
||||
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues & Track command - ["
|
||||
+ std::string{ Event->Params[ 0 ].asText } + "] ["
|
||||
+ to_string( Event->Params[ 1 ].asdouble, 2 ) + "] ["
|
||||
+ to_string( Event->Params[ 2 ].asdouble, 2 ) + " ]" );
|
||||
}
|
||||
//else if (DebugModeFlag)
|
||||
WriteLog(
|
||||
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues - ["
|
||||
+ std::string( Event->Params[ 0 ].asText ) + "] ["
|
||||
+ to_string( Event->Params[ 1 ].asdouble, 2 ) + "] ["
|
||||
+ to_string( Event->Params[ 2 ].asdouble, 2 ) + "]" );
|
||||
}
|
||||
// jeśli jest kolejny o takiej samej nazwie, to idzie do kolejki (and if there's no joint event it'll be set to null and processing will end here)
|
||||
do {
|
||||
Event = Event->evJoined;
|
||||
// NOTE: we could've received a new event from joint event above, so we need to check conditions just in case and discard the bad events
|
||||
// TODO: refactor this arrangement, it's hardly optimal
|
||||
} while( ( Event != nullptr )
|
||||
&& ( ( false == Event->bEnabled )
|
||||
|| ( Event->iQueued > 0 ) ) );
|
||||
}
|
||||
if( ( Event != nullptr )
|
||||
&& ( false == Event->m_ignored ) ) {
|
||||
// standardowe dodanie do kolejki
|
||||
++Event->iQueued; // zabezpieczenie przed podwójnym dodaniem do kolejki
|
||||
WriteLog( "EVENT ADDED TO QUEUE" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": " + Event->asName );
|
||||
Event->fStartTime = delay + std::abs( Event->fDelay ) + Timer::GetTime(); // czas od uruchomienia scenerii
|
||||
if( Event->fRandomDelay > 0.0 ) {
|
||||
// doliczenie losowego czasu opóźnienia
|
||||
Event->fStartTime += Event->fRandomDelay * Random( 10000 ) * 0.0001;
|
||||
}
|
||||
if( QueryRootEvent != nullptr ) {
|
||||
TEvent::AddToQuery( Event, QueryRootEvent );
|
||||
}
|
||||
else {
|
||||
QueryRootEvent = Event;
|
||||
QueryRootEvent->evNext = nullptr;
|
||||
if( Event->Params[ 6 ].asTrack ) {
|
||||
// McZapkie-100302 - updatevalues oprocz zmiany wartosci robi putcommand dla wszystkich 'dynamic' na danym torze
|
||||
for( auto dynamic : Event->Params[ 6 ].asTrack->Dynamics ) {
|
||||
Event->Params[ 5 ].asMemCell->PutCommand(
|
||||
dynamic->Mechanik,
|
||||
Event->Params[ 4 ].asLocation );
|
||||
}
|
||||
//if (DebugModeFlag)
|
||||
WriteLog(
|
||||
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues & Track command - ["
|
||||
+ std::string{ Event->Params[ 0 ].asText } + "] ["
|
||||
+ to_string( Event->Params[ 1 ].asdouble, 2 ) + "] ["
|
||||
+ to_string( Event->Params[ 2 ].asdouble, 2 ) + " ]" );
|
||||
}
|
||||
//else if (DebugModeFlag)
|
||||
WriteLog(
|
||||
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues - ["
|
||||
+ std::string( Event->Params[ 0 ].asText ) + "] ["
|
||||
+ to_string( Event->Params[ 1 ].asdouble, 2 ) + "] ["
|
||||
+ to_string( Event->Params[ 2 ].asdouble, 2 ) + "]" );
|
||||
}
|
||||
// jeśli jest kolejny o takiej samej nazwie, to idzie do kolejki (and if there's no joint event it'll be set to null and processing will end here)
|
||||
do {
|
||||
Event = Event->evJoined;
|
||||
// NOTE: we could've received a new event from joint event above, so we need to check conditions just in case and discard the bad events
|
||||
// TODO: refactor this arrangement, it's hardly optimal
|
||||
} while( ( Event != nullptr )
|
||||
&& ( ( false == Event->bEnabled )
|
||||
|| ( Event->iQueued > 0 ) ) );
|
||||
}
|
||||
if( ( Event != nullptr )
|
||||
&& ( false == Event->m_ignored ) ) {
|
||||
// standardowe dodanie do kolejki
|
||||
++Event->iQueued; // zabezpieczenie przed podwójnym dodaniem do kolejki
|
||||
WriteLog( "EVENT ADDED TO QUEUE" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": " + Event->asName );
|
||||
Event->fStartTime = delay + std::abs( Event->fDelay ) + Timer::GetTime(); // czas od uruchomienia scenerii
|
||||
if( Event->fRandomDelay > 0.0 ) {
|
||||
// doliczenie losowego czasu opóźnienia
|
||||
Event->fStartTime += Event->fRandomDelay * Random( 10000 ) * 0.0001;
|
||||
}
|
||||
if( QueryRootEvent != nullptr ) {
|
||||
TEvent::AddToQuery( Event, QueryRootEvent );
|
||||
}
|
||||
else {
|
||||
QueryRootEvent = Event;
|
||||
QueryRootEvent->evNext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1666,26 +1660,22 @@ event_manager::InitEvents() {
|
||||
break;
|
||||
}
|
||||
case tp_Multiple: {
|
||||
std::string cellastext;
|
||||
if( event->Params[ 9 ].asText != nullptr ) { // przepisanie nazwy do bufora
|
||||
cellastext = event->Params[ 9 ].asText;
|
||||
SafeDeleteArray( event->Params[ 9 ].asText );
|
||||
event->Params[ 9 ].asPointer = nullptr; // zerowanie wskaźnika, aby wykryć brak obeiktu
|
||||
}
|
||||
if( event->iFlags & ( conditional_trackoccupied | conditional_trackfree ) ) {
|
||||
// jeśli chodzi o zajetosc toru
|
||||
event->Params[ 9 ].asTrack = simulation::Paths.find( cellastext );
|
||||
if( event->Params[ 9 ].asTrack == nullptr ) {
|
||||
ErrorLog( "Bad event: multi-event \"" + event->asName + "\" cannot find track \"" + cellastext + "\"" );
|
||||
event->iFlags &= ~( conditional_trackoccupied | conditional_trackfree ); // zerowanie flag
|
||||
if( false == event->asNodeName.empty() ) {
|
||||
if( event->iFlags & ( conditional_trackoccupied | conditional_trackfree ) ) {
|
||||
// jeśli chodzi o zajetosc toru
|
||||
event->Params[ 9 ].asTrack = simulation::Paths.find( event->asNodeName );
|
||||
if( event->Params[ 9 ].asTrack == nullptr ) {
|
||||
ErrorLog( "Bad event: multi-event \"" + event->asName + "\" cannot find track \"" + event->asNodeName + "\"" );
|
||||
event->iFlags &= ~( conditional_trackoccupied | conditional_trackfree ); // zerowanie flag
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( event->iFlags & ( conditional_memstring | conditional_memval1 | conditional_memval2 ) ) {
|
||||
// jeśli chodzi o komorke pamieciową
|
||||
event->Params[ 9 ].asMemCell = simulation::Memory.find( cellastext );
|
||||
if( event->Params[ 9 ].asMemCell == nullptr ) {
|
||||
ErrorLog( "Bad event: multi-event \"" + event->asName + "\" cannot find memory cell \"" + cellastext + "\"" );
|
||||
event->iFlags &= ~( conditional_memstring | conditional_memval1 | conditional_memval2 );
|
||||
else if( event->iFlags & ( conditional_memstring | conditional_memval1 | conditional_memval2 ) ) {
|
||||
// jeśli chodzi o komorke pamieciową
|
||||
event->Params[ 9 ].asMemCell = simulation::Memory.find( event->asNodeName );
|
||||
if( event->Params[ 9 ].asMemCell == nullptr ) {
|
||||
ErrorLog( "Bad event: multi-event \"" + event->asName + "\" cannot find memory cell \"" + event->asNodeName + "\"" );
|
||||
event->iFlags &= ~( conditional_memstring | conditional_memval1 | conditional_memval2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
for( auto &childevent : event->m_children ) {
|
||||
|
||||
6
Event.h
6
Event.h
@@ -105,7 +105,7 @@ public:
|
||||
TEventType Type = tp_Unknown;
|
||||
double fStartTime = 0.0;
|
||||
double fDelay = 0.0;
|
||||
TDynamicObject *Activator = nullptr;
|
||||
TDynamicObject const *Activator = nullptr;
|
||||
TParam Params[13]; // McZapkie-070502 //Ra: zamienić to na union/struct
|
||||
|
||||
unsigned int iFlags = 0; // zamiast Params[8] z flagami warunku
|
||||
@@ -122,6 +122,8 @@ private:
|
||||
class event_manager {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
event_manager() = default;
|
||||
// destructor
|
||||
~event_manager();
|
||||
// methods
|
||||
@@ -147,7 +149,7 @@ public:
|
||||
FindEvent( std::string const &Name );
|
||||
// legacy method, inserts specified event in the event query
|
||||
bool
|
||||
AddToQuery( TEvent *Event, TDynamicObject *Owner, double delay = 0.0 );
|
||||
AddToQuery( TEvent *Event, TDynamicObject const *Owner, double delay = 0.0 );
|
||||
// legacy method, executes queued events
|
||||
bool
|
||||
CheckQuery();
|
||||
|
||||
@@ -36,16 +36,6 @@ std::vector<std::string> const TMoverParameters::eimv_labels = {
|
||||
"Fful:"
|
||||
};
|
||||
|
||||
inline long Trunc(float f)
|
||||
{
|
||||
return (long)f;
|
||||
}
|
||||
|
||||
inline long ROUND(float f)
|
||||
{
|
||||
return Trunc(f + 0.5f);
|
||||
}
|
||||
|
||||
inline double square(double val) // SQR() zle liczylo w current() ...
|
||||
{
|
||||
return val * val;
|
||||
@@ -293,10 +283,10 @@ TMoverParameters::TMoverParameters(double VelInitial, std::string TypeNameInit,
|
||||
int Cab) ://: T_MoverParameters(VelInitial, TypeNameInit,
|
||||
//NameInit, LoadInitial, LoadTypeInitial, Cab)
|
||||
TypeName( TypeNameInit ),
|
||||
Name( NameInit ),
|
||||
ActiveCab( Cab ),
|
||||
LoadType( LoadTypeInitial ),
|
||||
Load( LoadInitial ),
|
||||
Name( NameInit )
|
||||
LoadType( LoadTypeInitial )
|
||||
{
|
||||
WriteLog(
|
||||
"------------------------------------------------------");
|
||||
@@ -1577,9 +1567,10 @@ void TMoverParameters::WaterHeaterCheck( double const Timestep ) {
|
||||
WaterHeater.is_active = false;
|
||||
}
|
||||
|
||||
WaterHeater.is_damaged |= (
|
||||
( true == WaterHeater.is_active )
|
||||
&& ( false == WaterPump.is_active ) );
|
||||
WaterHeater.is_damaged = (
|
||||
( true == WaterHeater.is_damaged )
|
||||
|| ( ( true == WaterHeater.is_active )
|
||||
&& ( false == WaterPump.is_active ) ) );
|
||||
}
|
||||
|
||||
// fuel pump status update
|
||||
@@ -1711,19 +1702,12 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed)
|
||||
// szybkie przejœcie na bezoporow¹
|
||||
if( TrainType == dt_ET40 ) {
|
||||
break; // this means ET40 won't react at all to fast acceleration command. should it issue just IncMainCtrl(1) instead?
|
||||
}
|
||||
}
|
||||
while( ( RList[ MainCtrlPos ].R > 0.0 )
|
||||
&& IncMainCtrl( 1 ) ) {
|
||||
// all work is done in the loop header
|
||||
;
|
||||
}
|
||||
// OK:=true ; {takie chamskie, potem poprawie} <-Ra: kto mia³ to poprawiæ i po co?
|
||||
if( ActiveDir < 0 ) {
|
||||
while( ( RList[ MainCtrlPos ].Bn > 1 )
|
||||
&& IncMainCtrl( 1 ) ) {
|
||||
--MainCtrlPos;
|
||||
}
|
||||
}
|
||||
OK = false; // shouldn't this be part of the loop above?
|
||||
// if (TrainType=dt_ET40) then
|
||||
// while Abs (Im)>IminHi do
|
||||
@@ -1749,14 +1733,6 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed)
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ActiveDir < 0 ) {
|
||||
if( ( TrainType != dt_PseudoDiesel )
|
||||
&& ( RList[ MainCtrlPos ].Bn > 1 ) ) {
|
||||
// blokada wejścia na równoległą podczas jazdy do tyłu
|
||||
--MainCtrlPos;
|
||||
OK = false;
|
||||
}
|
||||
}
|
||||
//
|
||||
// if (TrainType == "et40")
|
||||
// if (Abs(Im) > IminHi)
|
||||
@@ -1765,15 +1741,14 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed)
|
||||
// OK = false;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
if( ( TrainType == dt_ET42 ) && ( true == DynamicBrakeFlag ) ) {
|
||||
if( MainCtrlPos > 20 ) {
|
||||
MainCtrlPos = 20;
|
||||
if( ( TrainType == dt_ET42 ) && ( true == DynamicBrakeFlag ) ) {
|
||||
if( MainCtrlPos > 20 ) {
|
||||
MainCtrlPos = 20;
|
||||
OK = false;
|
||||
}
|
||||
}
|
||||
// return OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2863,7 +2838,6 @@ bool TMoverParameters::IncLocalBrakeLevel(int CtrlSpeed)
|
||||
while ((LocalBrakePos < LocalBrakePosNo) && (CtrlSpeed > 0))
|
||||
{
|
||||
LocalBrakePos++;
|
||||
// LocalBrakePosA = static_cast<double>(LocalBrakePos) / LocalBrakePosNo; // temporary hack until i figure out how this element is supposed to work
|
||||
CtrlSpeed--;
|
||||
}
|
||||
IBL = true;
|
||||
@@ -2887,7 +2861,6 @@ bool TMoverParameters::DecLocalBrakeLevel(int CtrlSpeed)
|
||||
while ((CtrlSpeed > 0) && (LocalBrakePos > 0))
|
||||
{
|
||||
LocalBrakePos--;
|
||||
// LocalBrakePosA = static_cast<double>( LocalBrakePos ) / LocalBrakePosNo; // temporary hack until i figure out how this element is supposed to work
|
||||
CtrlSpeed--;
|
||||
}
|
||||
DBL = true;
|
||||
@@ -2909,7 +2882,6 @@ bool TMoverParameters::IncLocalBrakeLevelFAST(void)
|
||||
if (LocalBrakePos < LocalBrakePosNo)
|
||||
{
|
||||
LocalBrakePos = LocalBrakePosNo;
|
||||
// LocalBrakePosA = static_cast<double>( LocalBrakePos ) / LocalBrakePosNo; // temporary hack until i figure out how this element is supposed to work
|
||||
ILBLF = true;
|
||||
}
|
||||
else
|
||||
@@ -2928,7 +2900,6 @@ bool TMoverParameters::DecLocalBrakeLevelFAST(void)
|
||||
if (LocalBrakePos > 0)
|
||||
{
|
||||
LocalBrakePos = 0;
|
||||
// LocalBrakePosA = static_cast<double>( LocalBrakePos ) / LocalBrakePosNo; // temporary hack until i figure out how this element is supposed to work
|
||||
DLBLF = true;
|
||||
}
|
||||
else
|
||||
@@ -5091,7 +5062,7 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
Hamulec->SetED(0);
|
||||
// (Hamulec as TLSt).SetLBP(LocBrakePress);
|
||||
if ((PosRatio > dizel_fill))
|
||||
tmp = 1;
|
||||
tmp = 4;
|
||||
else
|
||||
tmp = 4; // szybkie malenie, powolne wzrastanie
|
||||
}
|
||||
@@ -5100,7 +5071,7 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
// TODO: gather these in single place so they can be resolved together
|
||||
if( ( SlippingWheels ) ) {
|
||||
PosRatio = 0;
|
||||
tmp = 9;
|
||||
tmp = 10;
|
||||
Sandbox( true, range::unit );
|
||||
} // przeciwposlizg
|
||||
else {
|
||||
@@ -5108,7 +5079,7 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
Sandbox( false, range::unit );
|
||||
}
|
||||
|
||||
dizel_fill += Max0R(Min0R(PosRatio - dizel_fill, 0.1), -0.1) * 2 *
|
||||
dizel_fill += Max0R(Min0R(PosRatio - dizel_fill, 0.02), -0.02) * 12 *
|
||||
(tmp /*2{+4*byte(PosRatio<dizel_fill)*/) *
|
||||
dt; // wartość zadana/procent czegoś
|
||||
|
||||
@@ -5986,16 +5957,19 @@ bool TMoverParameters::dizel_AutoGearCheck(void)
|
||||
if (MotorParam[ScndCtrlActualPos].AutoSwitch &&
|
||||
(dizel_automaticgearstatus == 0)) // sprawdz czy zmienic biegi
|
||||
{
|
||||
if ((Vel > MotorParam[ScndCtrlActualPos].mfi) &&
|
||||
(ScndCtrlActualPos < ScndCtrlPosNo))
|
||||
{
|
||||
dizel_automaticgearstatus = 1;
|
||||
OK = true;
|
||||
if( Vel > MotorParam[ ScndCtrlActualPos ].mfi ) {
|
||||
// shift up
|
||||
if( ScndCtrlActualPos < ScndCtrlPosNo ) {
|
||||
dizel_automaticgearstatus = 1;
|
||||
OK = true;
|
||||
}
|
||||
}
|
||||
else if ((Vel < MotorParam[ScndCtrlActualPos].fi) && (ScndCtrlActualPos > 0))
|
||||
{
|
||||
dizel_automaticgearstatus = -1;
|
||||
OK = true;
|
||||
else if( Vel < MotorParam[ ScndCtrlActualPos ].fi ) {
|
||||
// shift down
|
||||
if( ScndCtrlActualPos > 0 ) {
|
||||
dizel_automaticgearstatus = -1;
|
||||
OK = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6466,7 +6440,7 @@ void TMoverParameters::dizel_Heat( double const dt ) {
|
||||
auto const zaluzje2 { ( dizel_heat.zaluzje2 ? 1 : 0 ) };
|
||||
// auxiliary water circuit heat transfer values
|
||||
auto const kf2 { kurek07 * ( ( dizel_heat.kw * ( 0.3 + 0.7 * zaluzje2 ) ) * dizel_heat.rpmw2 + ( dizel_heat.kv * ( 0.3 + 0.7 * zaluzje2 ) * Vel / 3.6 ) ) + 2 };
|
||||
auto const dTs2 { ( ( dizel_heat.kfs * ( 0.3 ) * ( dizel_heat.To - dizel_heat.Tsr2 ) ) ) / ( gw2 * Cw ) };
|
||||
auto const dTs2 { ( ( dizel_heat.kfo2 * ( dizel_heat.To - dizel_heat.Tsr2 ) ) ) / ( gw2 * Cw ) };
|
||||
// przy otwartym kurku B ma³y obieg jest dogrzewany przez du¿y - stosujemy przy korzystaniu z podgrzewacza oraz w zimie
|
||||
auto const Qch2 { -kf2 * ( dizel_heat.Tsr2 - dizel_heat.Te ) + ( 80 * ( true == WaterCircuitsLink ? 1 : 0 ) * ( dizel_heat.Twy - dizel_heat.Tsr2 ) ) };
|
||||
auto const dTch2 { Qch2 / ( gw2 * Cw ) };
|
||||
@@ -6923,41 +6897,11 @@ bool startDLIST, startFFLIST, startWWLIST;
|
||||
bool startLIGHTSLIST;
|
||||
int LISTLINE;
|
||||
|
||||
// *************************************************************************************************
|
||||
// Q: 20160717
|
||||
// *************************************************************************************************
|
||||
size_t Pos(std::string str_find, std::string in)
|
||||
{
|
||||
size_t pos = in.find(str_find);
|
||||
return (pos != std::string::npos ? pos+1 : 0);
|
||||
}
|
||||
/*
|
||||
// *************************************************************************************************
|
||||
// Q: 20160717
|
||||
// *************************************************************************************************
|
||||
bool issection(std::string const &name)
|
||||
{
|
||||
sectionname = name;
|
||||
if (xline.compare(0, name.size(), name) == 0)
|
||||
{
|
||||
lastsectionname = name;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
bool issection( std::string const &Name, std::string const &Input ) {
|
||||
|
||||
return ( Input.compare( 0, Name.size(), Name ) == 0 );
|
||||
}
|
||||
|
||||
int MARKERROR(int code, std::string type, std::string msg)
|
||||
{
|
||||
WriteLog(msg);
|
||||
return code;
|
||||
}
|
||||
|
||||
int s2NPW(std::string s)
|
||||
{ // wylicza ilosc osi napednych z opisu ukladu osi
|
||||
const char A = 64;
|
||||
@@ -9175,9 +9119,7 @@ bool TMoverParameters::SendCtrlToNext( std::string const CtrlCommand, double con
|
||||
// jakiejś zmiany (np. IncMainCtrl) lepiej wywołać funkcję, czy od razu wysłać komendę.
|
||||
bool TMoverParameters::RunCommand( std::string Command, double CValue1, double CValue2, int const Couplertype )
|
||||
{
|
||||
bool OK;
|
||||
std::string testload;
|
||||
OK = false;
|
||||
bool OK { false };
|
||||
|
||||
if (Command == "MainCtrl")
|
||||
{
|
||||
@@ -9602,29 +9544,37 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
OK = true; // true, gdy można usunąć komendę
|
||||
}
|
||||
/*naladunek/rozladunek*/
|
||||
else if (Pos("Load=", Command) == 1)
|
||||
else if ( issection( "Load=", Command ) )
|
||||
{
|
||||
OK = false; // będzie powtarzane aż się załaduje
|
||||
if ((Vel == 0) && (MaxLoad > 0) &&
|
||||
(Load < MaxLoad * (1.0 + OverLoadFactor))) // czy można ładowac?
|
||||
if (Distance(Loc, CommandIn.Location, Dim, Dim) < 10) // ten peron/rampa
|
||||
{
|
||||
testload = ToLower(DUE(Command));
|
||||
if (Pos(testload, LoadAccepted) > 0) // nazwa jest obecna w CHK
|
||||
OK = LoadingDone(Min0R(CValue2, LoadSpeed), testload); // zmienia LoadStatus
|
||||
}
|
||||
if( ( Vel < 0.01 )
|
||||
&& ( MaxLoad > 0 )
|
||||
&& ( Load < MaxLoad * ( 1.0 + OverLoadFactor ) ) ) {
|
||||
// czy można ładowac?
|
||||
if( Distance( Loc, CommandIn.Location, Dim, Dim ) < 10 ) {
|
||||
// ten peron/rampa
|
||||
auto const testload { ToLower( extract_value( "Load", Command ) ) };
|
||||
if( LoadAccepted.find( testload ) != std::string::npos ) // nazwa jest obecna w CHK
|
||||
OK = LoadingDone( Min0R( CValue2, LoadSpeed ), testload ); // zmienia LoadStatus
|
||||
}
|
||||
}
|
||||
// if OK then LoadStatus:=0; //nie udalo sie w ogole albo juz skonczone
|
||||
}
|
||||
else if (Pos("UnLoad=", Command) == 1)
|
||||
else if( issection( "UnLoad=", Command ) )
|
||||
{
|
||||
OK = false; // będzie powtarzane aż się rozładuje
|
||||
if ((Vel == 0) && (Load > 0)) // czy jest co rozladowac?
|
||||
if (Distance(Loc, CommandIn.Location, Dim, Dim) < 10) // ten peron
|
||||
{
|
||||
testload = DUE(Command); // zgodność nazwy ładunku z CHK
|
||||
if (LoadType == testload) /*mozna to rozladowac*/
|
||||
OK = LoadingDone(-Min0R(CValue2, LoadSpeed), testload);
|
||||
}
|
||||
if( ( Vel < 0.01 )
|
||||
&& ( Load > 0 ) ) {
|
||||
// czy jest co rozladowac?
|
||||
if( Distance( Loc, CommandIn.Location, Dim, Dim ) < 10 ) {
|
||||
// ten peron
|
||||
auto const testload { ToLower( extract_value( "UnLoad", Command ) ) }; // zgodność nazwy ładunku z CHK
|
||||
if( LoadType == testload ) {
|
||||
/*mozna to rozladowac*/
|
||||
OK = LoadingDone( -Min0R( CValue2, LoadSpeed ), testload );
|
||||
}
|
||||
}
|
||||
}
|
||||
// if OK then LoadStatus:=0;
|
||||
}
|
||||
else if (Command == "SpeedCntrl")
|
||||
|
||||
@@ -155,6 +155,7 @@ public:
|
||||
static float fSquareDist;
|
||||
static TModel3d *pRoot;
|
||||
static std::string *pasText; // tekst dla wyświetlacza (!!!! do przemyślenia)
|
||||
TSubModel() = default;
|
||||
~TSubModel();
|
||||
int Load(cParser &Parser, TModel3d *Model, /*int Pos,*/ bool dynamic);
|
||||
void ChildAdd(TSubModel *SubModel);
|
||||
|
||||
4
Timer.h
4
Timer.h
@@ -29,6 +29,9 @@ void UpdateTimers(bool pause);
|
||||
class stopwatch {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
stopwatch() = default;
|
||||
// methods
|
||||
void
|
||||
start() {
|
||||
m_start = std::chrono::steady_clock::now(); }
|
||||
@@ -40,6 +43,7 @@ public:
|
||||
return m_accumulator / 20.f;}
|
||||
|
||||
private:
|
||||
// members
|
||||
std::chrono::time_point<std::chrono::steady_clock> m_start { std::chrono::steady_clock::now() };
|
||||
float m_accumulator { 1000.f / 30.f * 20.f }; // 20 last samples, initial 'neutral' rate of 30 fps
|
||||
};
|
||||
|
||||
21
Track.cpp
21
Track.cpp
@@ -924,6 +924,25 @@ bool TTrack::AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus)
|
||||
return false;
|
||||
};
|
||||
|
||||
void TTrack::QueueEvents( event_sequence const &Events, TDynamicObject const *Owner ) {
|
||||
|
||||
for( auto const &event : Events ) {
|
||||
if( event.second != nullptr ) {
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrack::QueueEvents( event_sequence const &Events, TDynamicObject const *Owner, double const Delaylimit ) {
|
||||
|
||||
for( auto const &event : Events ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->fDelay <= Delaylimit) ) {
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string TTrack::IsolatedName()
|
||||
{ // podaje nazwę odcinka izolowanego, jesli nie ma on jeszcze przypisanych zdarzeń
|
||||
if (pIsolated)
|
||||
@@ -1191,7 +1210,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
||||
{ szyna[ i ].texture.x,
|
||||
szyna[ i ].texture.y } };
|
||||
|
||||
if( false == iTrapezoid ) { continue; }
|
||||
if( iTrapezoid == 0 ) { continue; }
|
||||
// trapez albo przechyłki, to oddzielne punkty na końcu
|
||||
|
||||
rpts1[ 12 + i ] = {
|
||||
|
||||
4
Track.h
4
Track.h
@@ -127,6 +127,8 @@ private:
|
||||
class TTrack : public scene::basic_node {
|
||||
|
||||
friend class opengl_renderer;
|
||||
// NOTE: temporary arrangement
|
||||
friend class ui_layer;
|
||||
|
||||
private:
|
||||
TIsolated * pIsolated = nullptr; // obwód izolowany obsługujący zajęcia/zwolnienia grupy torów
|
||||
@@ -247,6 +249,8 @@ public:
|
||||
void Load(cParser *parser, Math3D::vector3 pOrigin);
|
||||
bool AssignEvents();
|
||||
bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus);
|
||||
void QueueEvents( event_sequence const &Events, TDynamicObject const *Owner );
|
||||
void QueueEvents( event_sequence const &Events, TDynamicObject const *Owner, double const Delaylimit );
|
||||
bool CheckDynamicObject(TDynamicObject *Dynamic);
|
||||
bool AddDynamicObject(TDynamicObject *Dynamic);
|
||||
bool RemoveDynamicObject(TDynamicObject *Dynamic);
|
||||
|
||||
14
Train.cpp
14
Train.cpp
@@ -924,7 +924,12 @@ void TTrain::OnCommand_independentbrakedecreasefast( TTrain *Train, command_data
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
|
||||
Train->mvControlled->LocalBrakePosA = (
|
||||
clamp(
|
||||
reinterpret_cast<double const &>( Command.param1 ),
|
||||
0.0, 1.0 ) );
|
||||
/*
|
||||
Train->mvControlled->LocalBrakePos = (
|
||||
std::round(
|
||||
interpolate<double>(
|
||||
@@ -933,6 +938,7 @@ void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &C
|
||||
clamp(
|
||||
reinterpret_cast<double const &>( Command.param1 ),
|
||||
0.0, 1.0 ) ) ) );
|
||||
*/
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_independentbrakebailoff( TTrain *Train, command_data const &Command ) {
|
||||
@@ -5174,7 +5180,8 @@ bool TTrain::Update( double const Deltatime )
|
||||
}
|
||||
else
|
||||
#endif
|
||||
ggLocalBrake.UpdateValue(double(mvOccupied->LocalBrakePos));
|
||||
// standardowa prodedura z kranem powiązanym z klawiaturą
|
||||
ggLocalBrake.UpdateValue( std::max<double>( mvOccupied->LocalBrakePos, mvOccupied->LocalBrakePosA * LocalBrakePosNo ) );
|
||||
ggLocalBrake.Update();
|
||||
}
|
||||
if (ggManualBrake.SubModel != nullptr) {
|
||||
@@ -5650,7 +5657,7 @@ TTrain::update_sounds( double const Deltatime ) {
|
||||
m_radiostop.stop();
|
||||
}
|
||||
|
||||
if( fTachoCount > 3.f ) {
|
||||
if( fTachoCount >= 3.f ) {
|
||||
auto const frequency { (
|
||||
true == dsbHasler.is_combined() ?
|
||||
fTachoVelocity * 0.01 :
|
||||
@@ -6355,6 +6362,7 @@ void TTrain::clear_cab_controls()
|
||||
ggRadioTest.Clear();
|
||||
ggDoorLeftButton.Clear();
|
||||
ggDoorRightButton.Clear();
|
||||
ggTrainHeatingButton.Clear();
|
||||
ggDepartureSignalButton.Clear();
|
||||
ggCompressorButton.Clear();
|
||||
ggConverterButton.Clear();
|
||||
|
||||
75
TrkFoll.cpp
75
TrkFoll.cpp
@@ -109,19 +109,9 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
||||
if( ( Owner->Mechanik != nullptr )
|
||||
&& ( Owner->Mechanik->Primary() ) ) {
|
||||
// tylko dla jednego członu
|
||||
for( auto &event : pCurrentTrack->m_events0 ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->iQueued == 0 ) ) {
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
for( auto &event : pCurrentTrack->m_events0all ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->iQueued == 0 ) ) {
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events0, Owner );
|
||||
}
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events0all, Owner );
|
||||
}
|
||||
else if (fDistance < 0) {
|
||||
// event1, eventall1
|
||||
@@ -132,26 +122,14 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
||||
// tylko dla jednego członu
|
||||
// McZapkie-280503: wyzwalanie event tylko dla pojazdow z obsada
|
||||
if( true == bPrimary ) {
|
||||
for( auto &event : pCurrentTrack->m_events1 ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->iQueued == 0 ) ) {
|
||||
// dodanie do kolejki
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( SetFlag( iEventallFlag, -1 ) ) {
|
||||
// McZapkie-280503: wyzwalanie eventall dla wszystkich pojazdow
|
||||
if( true == bPrimary ) {
|
||||
for( auto &event : pCurrentTrack->m_events1all ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->iQueued == 0 ) ) {
|
||||
// dodanie do kolejki
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1all, Owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,26 +141,14 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
||||
&& ( Owner->Mechanik->Primary() ) ) {
|
||||
// tylko dla jednego członu
|
||||
if( true == bPrimary ) {
|
||||
for( auto &event : pCurrentTrack->m_events2 ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->iQueued == 0 ) ) {
|
||||
// dodanie do kolejki
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( SetFlag( iEventallFlag, -2 ) ) {
|
||||
// sprawdza i zeruje na przyszłość, true jeśli zmieni z 2 na 0
|
||||
if( true == bPrimary ) {
|
||||
for( auto &event : pCurrentTrack->m_events2all ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->iQueued == 0 ) ) {
|
||||
// dodanie do kolejki
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2all, Owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,34 +245,13 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
||||
{ // tylko gdy początkowe ustawienie, dodajemy eventy stania do kolejki
|
||||
if (Owner->MoverParameters->ActiveCab != 0) {
|
||||
|
||||
for( auto &event : pCurrentTrack->m_events1 ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->fDelay <= -1.0 ) ) {
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
for( auto &event : pCurrentTrack->m_events2 ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->fDelay <= -1.0 ) ) {
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
for( auto &event : pCurrentTrack->m_events1all ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->fDelay <= -1.0 ) ) {
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
}
|
||||
for( auto &event : pCurrentTrack->m_events2all ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( event.second->fDelay <= -1.0 ) ) {
|
||||
simulation::Events.AddToQuery( event.second, Owner );
|
||||
}
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner, -1.0 );
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner, -1.0 );
|
||||
}
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1all, Owner, -1.0 );
|
||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2all, Owner, -1.0 );
|
||||
}
|
||||
fCurrentDistance = s;
|
||||
// fDistance=0;
|
||||
return ComputatePosition(); // przeliczenie XYZ, true o ile nie wyjechał na NULL
|
||||
}
|
||||
}
|
||||
|
||||
67
TrkFoll.h
67
TrkFoll.h
@@ -13,49 +13,50 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Classes.h"
|
||||
#include "Segment.h"
|
||||
|
||||
class TTrackFollower
|
||||
{ // oś poruszająca się po torze
|
||||
private:
|
||||
TTrack *pCurrentTrack = nullptr; // na którym torze siê znajduje
|
||||
std::shared_ptr<TSegment> pCurrentSegment; // zwrotnice mog¹ mieæ dwa segmenty
|
||||
double fCurrentDistance = 0.0; // przesuniêcie wzglêdem Point1 w stronê Point2
|
||||
double fDirection = 1.0; // ustawienie wzglêdem toru: -1.0 albo 1.0, mno¿one przez dystans // jest przodem do Point2
|
||||
bool ComputatePosition(); // przeliczenie pozycji na torze
|
||||
TDynamicObject *Owner = nullptr; // pojazd posiadający
|
||||
int iEventFlag = 0; // McZapkie-020602: informacja o tym czy wyzwalac zdarzenie: 0,1,2,3
|
||||
int iEventallFlag = 0;
|
||||
int iSegment = 0; // który segment toru jest używany (żeby nie przeskakiwało po przestawieniu
|
||||
// zwrotnicy pod taborem)
|
||||
public:
|
||||
double fOffsetH = 0.0; // Ra: odległość środka osi od osi toru (dla samochodów) - użyć do wężykowania
|
||||
Math3D::vector3 pPosition; // współrzędne XYZ w układzie scenerii
|
||||
Math3D::vector3 vAngles; // x:przechyłka, y:pochylenie, z:kierunek w planie (w radianach)
|
||||
// oś poruszająca się po torze
|
||||
class TTrackFollower {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
TTrackFollower() = default;
|
||||
// destructor
|
||||
~TTrackFollower();
|
||||
// methods
|
||||
TTrack * SetCurrentTrack(TTrack *pTrack, int end);
|
||||
bool Move(double fDistance, bool bPrimary);
|
||||
inline TTrack * GetTrack() const
|
||||
{
|
||||
return pCurrentTrack;
|
||||
};
|
||||
inline double GetRoll()
|
||||
{
|
||||
return vAngles.x;
|
||||
}; // przechyłka policzona przy ustalaniu pozycji
|
||||
inline TTrack * GetTrack() const {
|
||||
return pCurrentTrack; };
|
||||
// przechyłka policzona przy ustalaniu pozycji
|
||||
inline double GetRoll() {
|
||||
return vAngles.x; };
|
||||
//{return pCurrentSegment->GetRoll(fCurrentDistance)*fDirection;}; //zamiast liczyć można pobrać
|
||||
inline double GetDirection() const
|
||||
{
|
||||
return fDirection;
|
||||
}; // zwrot na torze
|
||||
inline double GetTranslation() const
|
||||
{
|
||||
return fCurrentDistance;
|
||||
}; // ABu-030403
|
||||
// zwrot na torze
|
||||
inline double GetDirection() const {
|
||||
return fDirection; };
|
||||
// ABu-030403
|
||||
inline double GetTranslation() const {
|
||||
return fCurrentDistance; };
|
||||
// inline double GetLength(vector3 p1, vector3 cp1, vector3 cp2, vector3 p2)
|
||||
//{ return pCurrentSegment->ComputeLength(p1,cp1,cp2,p2); };
|
||||
// inline double GetRadius(double L, double d); //McZapkie-150503
|
||||
bool Init(TTrack *pTrack, TDynamicObject *NewOwner, double fDir);
|
||||
void Render(float fNr);
|
||||
// members
|
||||
double fOffsetH = 0.0; // Ra: odległość środka osi od osi toru (dla samochodów) - użyć do wężykowania
|
||||
Math3D::vector3 pPosition; // współrzędne XYZ w układzie scenerii
|
||||
Math3D::vector3 vAngles; // x:przechyłka, y:pochylenie, z:kierunek w planie (w radianach)
|
||||
private:
|
||||
// methods
|
||||
bool ComputatePosition(); // przeliczenie pozycji na torze
|
||||
// members
|
||||
TTrack *pCurrentTrack = nullptr; // na którym torze siê znajduje
|
||||
std::shared_ptr<TSegment> pCurrentSegment; // zwrotnice mog¹ mieæ dwa segmenty
|
||||
double fCurrentDistance = 0.0; // przesuniêcie wzglêdem Point1 w stronê Point2
|
||||
double fDirection = 1.0; // ustawienie wzglêdem toru: -1.0 albo 1.0, mno¿one przez dystans // jest przodem do Point2
|
||||
TDynamicObject *Owner = nullptr; // pojazd posiadający
|
||||
int iEventFlag = 0; // McZapkie-020602: informacja o tym czy wyzwalac zdarzenie: 0,1,2,3
|
||||
int iEventallFlag = 0;
|
||||
int iSegment = 0; // który segment toru jest używany (żeby nie przeskakiwało po przestawieniu zwrotnicy pod taborem)
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
43
World.cpp
43
World.cpp
@@ -74,6 +74,12 @@ simulation_time::init() {
|
||||
m_time.wMinute = tms->tm_min;
|
||||
m_time.wSecond = tms->tm_sec;
|
||||
m_time.wMilliseconds = ts.tv_nsec / 1000000;
|
||||
|
||||
/*
|
||||
time_t local = mktime(localtime(&ts.tv_sec));
|
||||
time_t utc = mktime(gmtime(&ts.tv_sec));
|
||||
m_timezonebias = (double)(local - utc) / 3600.0f;
|
||||
*/
|
||||
#elif _WIN32
|
||||
::GetLocalTime( &m_time );
|
||||
#endif
|
||||
@@ -92,6 +98,30 @@ simulation_time::init() {
|
||||
}
|
||||
|
||||
m_yearday = year_day( m_time.wDay, m_time.wMonth, m_time.wYear );
|
||||
|
||||
// calculate time zone bias
|
||||
// retrieve relevant time zone info from system registry (or fall back on supplied default)
|
||||
// TODO: select timezone matching defined geographic location and/or country
|
||||
struct registry_time_zone_info {
|
||||
long Bias;
|
||||
long StandardBias;
|
||||
long DaylightBias;
|
||||
SYSTEMTIME StandardDate;
|
||||
SYSTEMTIME DaylightDate;
|
||||
} timezoneinfo = { -60, 0, -60, { 0, 10, 0, 5, 3, 0, 0, 0 }, { 0, 3, 0, 5, 2, 0, 0, 0 } };
|
||||
|
||||
auto zonebias { timezoneinfo.Bias };
|
||||
if( m_yearday < year_day( timezoneinfo.DaylightDate.wDay, timezoneinfo.DaylightDate.wMonth, m_time.wYear ) ) {
|
||||
zonebias += timezoneinfo.StandardBias;
|
||||
}
|
||||
else if( m_yearday < year_day( timezoneinfo.StandardDate.wDay, timezoneinfo.StandardDate.wMonth, m_time.wYear ) ) {
|
||||
zonebias += timezoneinfo.DaylightBias;
|
||||
}
|
||||
else {
|
||||
zonebias += timezoneinfo.StandardBias;
|
||||
}
|
||||
|
||||
m_timezonebias = ( zonebias / 60.0 );
|
||||
}
|
||||
|
||||
void
|
||||
@@ -216,15 +246,14 @@ void TWorld::TrainDelete(TDynamicObject *d)
|
||||
if (Train)
|
||||
if (Train->Dynamic() != d)
|
||||
return; // nie tego usuwać
|
||||
#ifdef EU07_SCENERY_EDITOR
|
||||
if( ( Train->DynamicObject )
|
||||
&& ( Train->DynamicObject->Mechanik ) ) {
|
||||
/*
|
||||
if( ( Train->Dynamic() )
|
||||
&& ( Train->Dynamic()->Mechanik ) ) {
|
||||
// likwidacja kabiny wymaga przejęcia przez AI
|
||||
Train->DynamicObject->Mechanik->TakeControl( true );
|
||||
Train->Dynamic()->Mechanik->TakeControl( true );
|
||||
}
|
||||
#endif
|
||||
delete Train; // i nie ma czym sterować
|
||||
Train = NULL;
|
||||
*/
|
||||
SafeDelete( Train ); // i nie ma czym sterować
|
||||
Controlled = NULL; // tego też już nie ma
|
||||
mvControlled = NULL;
|
||||
};
|
||||
|
||||
3
World.h
3
World.h
@@ -44,6 +44,8 @@ public:
|
||||
year_day( int Day, int const Month, int const Year ) const;
|
||||
int
|
||||
julian_day() const;
|
||||
double
|
||||
zone_bias() const { return m_timezonebias; }
|
||||
|
||||
private:
|
||||
// calculates day and month from given day of year
|
||||
@@ -54,6 +56,7 @@ private:
|
||||
double m_milliseconds{ 0.0 };
|
||||
int m_yearday;
|
||||
char m_monthdaycounts[ 2 ][ 13 ];
|
||||
double m_timezonebias{ 0.0 };
|
||||
};
|
||||
|
||||
namespace simulation {
|
||||
|
||||
@@ -53,7 +53,8 @@ struct openal_source {
|
||||
bool is_looping { false };
|
||||
sound_properties properties;
|
||||
sync_state sync { sync_state::good };
|
||||
|
||||
// constructors
|
||||
openal_source() = default;
|
||||
// methods
|
||||
template <class Iterator_>
|
||||
openal_source &
|
||||
@@ -102,6 +103,8 @@ class openal_renderer {
|
||||
friend class opengl_renderer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
openal_renderer() = default;
|
||||
// destructor
|
||||
~openal_renderer();
|
||||
// methods
|
||||
|
||||
@@ -24,7 +24,7 @@ class cFrustum {
|
||||
|
||||
public:
|
||||
// constructors:
|
||||
|
||||
cFrustum() = default;
|
||||
// methods:
|
||||
// update the frustum to match current view orientation
|
||||
void
|
||||
|
||||
2
lua.h
2
lua.h
@@ -17,5 +17,5 @@ public:
|
||||
|
||||
void interpret(std::string file);
|
||||
|
||||
typedef void (*eventhandler_t)(TEvent*, TDynamicObject*);
|
||||
typedef void (*eventhandler_t)(TEvent*, const TDynamicObject*);
|
||||
};
|
||||
|
||||
27
moon.cpp
27
moon.cpp
@@ -9,18 +9,6 @@ cMoon::cMoon() {
|
||||
setLocation( 19.00f, 52.00f ); // default location roughly in centre of Poland
|
||||
m_observer.press = 1013.0; // surface pressure, millibars
|
||||
m_observer.temp = 15.0; // ambient dry-bulb temperature, degrees C
|
||||
|
||||
#ifdef _WIN32
|
||||
TIME_ZONE_INFORMATION timezoneinfo; // TODO: timezone dependant on geographic location
|
||||
::GetTimeZoneInformation( &timezoneinfo );
|
||||
m_observer.timezone = -timezoneinfo.Bias / 60.0f;
|
||||
#elif __linux__
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
time_t local = mktime(localtime(&ts.tv_sec));
|
||||
time_t utc = mktime(gmtime(&ts.tv_sec));
|
||||
m_observer.timezone = (local - utc) / 3600.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
cMoon::~cMoon() { gluDeleteQuadric( moonsphere ); }
|
||||
@@ -28,16 +16,20 @@ cMoon::~cMoon() { gluDeleteQuadric( moonsphere ); }
|
||||
void
|
||||
cMoon::init() {
|
||||
|
||||
moonsphere = gluNewQuadric();
|
||||
gluQuadricNormals( moonsphere, GLU_SMOOTH );
|
||||
m_observer.timezone = -1.0 * simulation::Time.zone_bias();
|
||||
// NOTE: we're calculating phase just once, because it's unlikely simulation will last a few days,
|
||||
// plus a sudden texture change would be pretty jarring
|
||||
phase();
|
||||
|
||||
moonsphere = gluNewQuadric();
|
||||
gluQuadricNormals( moonsphere, GLU_SMOOTH );
|
||||
}
|
||||
|
||||
void
|
||||
cMoon::update() {
|
||||
|
||||
m_observer.temp = Global.AirTemperature;
|
||||
|
||||
move();
|
||||
glm::vec3 position( 0.f, 0.f, -1.f );
|
||||
position = glm::rotateX( position, glm::radians( static_cast<float>( m_body.elevref ) ) );
|
||||
@@ -121,7 +113,7 @@ void cMoon::move() {
|
||||
if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; }
|
||||
if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; }
|
||||
|
||||
double ut =
|
||||
double localut =
|
||||
localtime.wHour
|
||||
+ localtime.wMinute / 60.0 // too low resolution, noticeable skips
|
||||
+ localtime.wSecond / 3600.0; // good enough in normal circumstances
|
||||
@@ -134,11 +126,10 @@ void cMoon::move() {
|
||||
+ 275 * localtime.wMonth / 9
|
||||
+ localtime.wDay
|
||||
- 730530
|
||||
+ ( ut / 24.0 );
|
||||
+ ( localut / 24.0 );
|
||||
|
||||
// Universal Coordinated (Greenwich standard) time
|
||||
m_observer.utime = ut * 3600.0;
|
||||
m_observer.utime = m_observer.utime / 3600.0 - m_observer.timezone;
|
||||
m_observer.utime = localut - m_observer.timezone;
|
||||
|
||||
// obliquity of the ecliptic
|
||||
m_body.oblecl = clamp_circular( 23.4393 - 3.563e-7 * daynumber );
|
||||
|
||||
@@ -75,7 +75,7 @@ mouse_input::button( int const Button, int const Action ) {
|
||||
|
||||
if( true == FreeFlyModeFlag ) {
|
||||
// world editor controls
|
||||
// currently we only handle view panning in this mode
|
||||
// TODO: separate behaviour when the scenery editor is active and in 'regular' free fly mode
|
||||
if( Action == GLFW_RELEASE ) {
|
||||
// if it's the right mouse button that got released we were potentially in view panning mode; stop it
|
||||
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
|
||||
@@ -84,6 +84,19 @@ mouse_input::button( int const Button, int const Action ) {
|
||||
}
|
||||
else {
|
||||
// button press
|
||||
if( Button == GLFW_MOUSE_BUTTON_LEFT ) {
|
||||
// the left button selects scene node
|
||||
// further behaviour can vary depending on whether we're in editor mode
|
||||
auto const *node { GfxRenderer.Update_Pick_Node() };
|
||||
if( true == EditorModeFlag ) {
|
||||
// NOTE: until we have proper editor object in place we set the current node manually
|
||||
editor::Node = node;
|
||||
}
|
||||
else {
|
||||
// launch on_click event associated with to the node
|
||||
// TODO: implement
|
||||
}
|
||||
}
|
||||
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
|
||||
// the right button activates mouse panning mode
|
||||
m_pickmodepanning = true;
|
||||
|
||||
@@ -266,6 +266,8 @@ typedef geometry_handle geometrybank_handle;
|
||||
class geometrybank_manager {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
geometrybank_manager() = default;
|
||||
// methods:
|
||||
// performs a resource sweep
|
||||
void update();
|
||||
|
||||
54
renderer.cpp
54
renderer.cpp
@@ -1826,15 +1826,6 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
||||
// tracks
|
||||
// TODO: update after path node refactoring
|
||||
Render( std::begin( cell->m_paths ), std::end( cell->m_paths ) );
|
||||
#ifdef EU07_SCENERY_EDITOR
|
||||
// TODO: re-implement
|
||||
// memcells
|
||||
if( EditorModeFlag ) {
|
||||
for( auto const memcell : Groundsubcell->m_memcells ) {
|
||||
Render( memcell );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef EU07_USE_DEBUG_CULLING
|
||||
// debug
|
||||
::glLineWidth( 2.f );
|
||||
@@ -1904,16 +1895,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
||||
::glColor3fv( glm::value_ptr( pick_color( m_picksceneryitems.size() + 1 ) ) );
|
||||
Render( path );
|
||||
}
|
||||
#ifdef EU07_SCENERY_EDITOR
|
||||
// memcells
|
||||
// TODO: re-implement
|
||||
if( EditorModeFlag ) {
|
||||
for( auto const memcell : Groundsubcell->m_memcells ) {
|
||||
::glColor3fv( glm::value_ptr( pick_color( m_picksceneryitems.size() + 1 ) ) );
|
||||
Render( memcell );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
|
||||
@@ -1944,6 +1926,17 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
||||
Render( dynamic );
|
||||
}
|
||||
}
|
||||
// memcells
|
||||
if( ( EditorModeFlag )
|
||||
&& ( DebugModeFlag ) ) {
|
||||
::glPushAttrib( GL_ENABLE_BIT );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
::glColor3f( 0.36f, 0.75f, 0.35f );
|
||||
for( auto const *memorycell : cell->m_memorycells ) {
|
||||
Render( memorycell );
|
||||
}
|
||||
::glPopAttrib();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rendermode::pickscenery: {
|
||||
@@ -1953,6 +1946,14 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
||||
::glColor3fv( glm::value_ptr( pick_color( m_picksceneryitems.size() + 1 ) ) );
|
||||
Render( instance );
|
||||
}
|
||||
// memcells
|
||||
if( ( EditorModeFlag )
|
||||
&& ( DebugModeFlag ) ) {
|
||||
for( auto const *memorycell : cell->m_memorycells ) {
|
||||
::glColor3fv( glm::value_ptr( pick_color( m_picksceneryitems.size() + 1 ) ) );
|
||||
Render( memorycell );
|
||||
}
|
||||
}
|
||||
// vehicles aren't included in scenery picking for the time being
|
||||
break;
|
||||
}
|
||||
@@ -2774,25 +2775,22 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::Render( TMemCell *Memcell ) {
|
||||
opengl_renderer::Render( TMemCell const *Memcell ) {
|
||||
|
||||
::glPushMatrix();
|
||||
auto const position = Memcell->location() - m_renderpass.camera.position();
|
||||
::glTranslated( position.x, position.y + 0.5, position.z );
|
||||
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::color: {
|
||||
::glPushAttrib( GL_ENABLE_BIT );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
::glColor3f( 0.36f, 0.75f, 0.35f );
|
||||
|
||||
case rendermode::color:
|
||||
case rendermode::shadows: {
|
||||
::gluSphere( m_quadric, 0.35, 4, 2 );
|
||||
|
||||
::glPopAttrib();
|
||||
break;
|
||||
}
|
||||
case rendermode::shadows:
|
||||
case rendermode::pickscenery: {
|
||||
// add the node to the pick list
|
||||
m_picksceneryitems.emplace_back( Memcell );
|
||||
|
||||
::gluSphere( m_quadric, 0.35, 4, 2 );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ struct opengl_technique {
|
||||
class opengl_camera {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
opengl_camera() = default;
|
||||
// methods:
|
||||
inline
|
||||
void
|
||||
@@ -113,10 +115,10 @@ class opengl_renderer {
|
||||
|
||||
public:
|
||||
// types
|
||||
|
||||
// constructors
|
||||
opengl_renderer() = default;
|
||||
// destructor
|
||||
~opengl_renderer() { gluDeleteQuadric( m_quadric ); }
|
||||
|
||||
// methods
|
||||
bool
|
||||
Init( GLFWwindow *Window );
|
||||
@@ -287,7 +289,7 @@ private:
|
||||
bool
|
||||
Render_cab( TDynamicObject const *Dynamic, bool const Alpha = false );
|
||||
void
|
||||
Render( TMemCell *Memcell );
|
||||
Render( TMemCell const *Memcell );
|
||||
void
|
||||
Render_Alpha( scene::basic_region *Region );
|
||||
void
|
||||
|
||||
32
scene.cpp
32
scene.cpp
@@ -124,7 +124,6 @@ basic_cell::update_events() {
|
||||
void
|
||||
basic_cell::update_sounds() {
|
||||
|
||||
auto const deltatime = Timer::GetDeltaRenderTime();
|
||||
for( auto *sound : m_sounds ) {
|
||||
sound->play_event();
|
||||
}
|
||||
@@ -361,6 +360,7 @@ basic_cell::insert( sound_source *Sound ) {
|
||||
m_active = true;
|
||||
|
||||
m_sounds.emplace_back( Sound );
|
||||
// NOTE: sound sources are virtual 'points' hence they don't ever expand cell range
|
||||
}
|
||||
|
||||
// adds provided sound instance to the cell
|
||||
@@ -374,6 +374,16 @@ basic_cell::insert( TEventLauncher *Launcher ) {
|
||||
enclose_area( Launcher );
|
||||
}
|
||||
|
||||
// adds provided memory cell to the cell
|
||||
void
|
||||
basic_cell::insert( TMemCell *Memorycell ) {
|
||||
|
||||
m_active = true;
|
||||
|
||||
m_memorycells.emplace_back( Memorycell );
|
||||
// NOTE: memory cells are virtual 'points' hence they don't ever expand cell range
|
||||
}
|
||||
|
||||
// registers provided path in the lookup directory of the cell
|
||||
void
|
||||
basic_cell::register_end( TTrack *Path ) {
|
||||
@@ -1133,7 +1143,6 @@ basic_region::insert_lines( lines_node Lines, scratch_data &Scratchpad ) {
|
||||
// inserts provided track in the region
|
||||
void
|
||||
basic_region::insert_path( TTrack *Path, const scratch_data &Scratchpad ) {
|
||||
|
||||
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||
auto location = Path->location();
|
||||
|
||||
@@ -1155,7 +1164,6 @@ basic_region::insert_path( TTrack *Path, const scratch_data &Scratchpad ) {
|
||||
// inserts provided track in the region
|
||||
void
|
||||
basic_region::insert_traction( TTraction *Traction, scratch_data &Scratchpad ) {
|
||||
|
||||
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||
auto location = Traction->location();
|
||||
|
||||
@@ -1177,7 +1185,6 @@ basic_region::insert_traction( TTraction *Traction, scratch_data &Scratchpad ) {
|
||||
// inserts provided instance of 3d model in the region
|
||||
void
|
||||
basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ) {
|
||||
|
||||
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||
auto location = Instance->location();
|
||||
|
||||
@@ -1210,7 +1217,6 @@ basic_region::insert_sound( sound_source *Sound, scratch_data &Scratchpad ) {
|
||||
// inserts provided event launcher in the region
|
||||
void
|
||||
basic_region::insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad ) {
|
||||
|
||||
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||
auto location = Launcher->location();
|
||||
|
||||
@@ -1224,6 +1230,22 @@ basic_region::insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpa
|
||||
}
|
||||
}
|
||||
|
||||
// inserts provided memory cell in the region
|
||||
void
|
||||
basic_region::insert_memorycell( TMemCell *Memorycell, scratch_data &Scratchpad ) {
|
||||
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||
auto location = Memorycell->location();
|
||||
|
||||
if( point_inside( location ) ) {
|
||||
// NOTE: nodes placed outside of region boundaries are discarded
|
||||
section( location ).insert( Memorycell );
|
||||
}
|
||||
else {
|
||||
// tracks are guaranteed to hava a name so we can skip the check
|
||||
ErrorLog( "Bad scenario: memory cell \"" + Memorycell->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
|
||||
}
|
||||
}
|
||||
|
||||
// find a vehicle located neares to specified location, within specified radius, optionally discarding vehicles without drivers
|
||||
std::tuple<TDynamicObject *, float>
|
||||
basic_region::find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) {
|
||||
|
||||
12
scene.h
12
scene.h
@@ -64,6 +64,8 @@ class basic_cell {
|
||||
friend class ::opengl_renderer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
basic_cell() = default;
|
||||
// methods
|
||||
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
|
||||
void
|
||||
@@ -113,6 +115,9 @@ public:
|
||||
// adds provided event launcher to the cell
|
||||
void
|
||||
insert( TEventLauncher *Launcher );
|
||||
// adds provided memory cell to the cell
|
||||
void
|
||||
insert( TMemCell *Memorycell );
|
||||
// registers provided path in the lookup directory of the cell
|
||||
void
|
||||
register_end( TTrack *Path );
|
||||
@@ -150,6 +155,7 @@ private:
|
||||
using instance_sequence = std::vector<TAnimModel *>;
|
||||
using sound_sequence = std::vector<sound_source *>;
|
||||
using eventlauncher_sequence = std::vector<TEventLauncher *>;
|
||||
using memorycell_sequence = std::vector<TMemCell *>;
|
||||
// methods
|
||||
void
|
||||
enclose_area( scene::basic_node *Node );
|
||||
@@ -166,6 +172,7 @@ private:
|
||||
traction_sequence m_traction;
|
||||
sound_sequence m_sounds;
|
||||
eventlauncher_sequence m_eventlaunchers;
|
||||
memorycell_sequence m_memorycells;
|
||||
// search helpers
|
||||
struct lookup_data {
|
||||
path_sequence paths;
|
||||
@@ -183,6 +190,8 @@ class basic_section {
|
||||
friend class ::opengl_renderer;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
basic_section() = default;
|
||||
// methods
|
||||
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
|
||||
void
|
||||
@@ -325,6 +334,9 @@ public:
|
||||
// inserts provided event launcher in the region
|
||||
void
|
||||
insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad );
|
||||
// inserts provided memory cell in the region
|
||||
void
|
||||
insert_memorycell( TMemCell *Memorycell, scratch_data &Scratchpad );
|
||||
// find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
|
||||
std::tuple<TDynamicObject *, float>
|
||||
find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );
|
||||
|
||||
@@ -759,4 +759,11 @@ basic_node::radius_() {
|
||||
}
|
||||
|
||||
} // scene
|
||||
|
||||
namespace editor {
|
||||
|
||||
scene::basic_node const *Node { nullptr }; // temporary helper, currently selected scene node
|
||||
|
||||
} // editor
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -381,4 +381,10 @@ basic_node::visible() const {
|
||||
|
||||
} // scene
|
||||
|
||||
namespace editor {
|
||||
|
||||
extern scene::basic_node const *Node; // temporary helper, currently selected scene node
|
||||
|
||||
} // editor
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -450,10 +450,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
if( false == simulation::Memory.insert( memorycell ) ) {
|
||||
ErrorLog( "Bad scenario: memory memorycell with duplicate name \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||
}
|
||||
/*
|
||||
// TODO: implement this
|
||||
simulation::Region.insert_memorycell( memorycell, Scratchpad );
|
||||
*/
|
||||
simulation::Region->insert_memorycell( memorycell, Scratchpad );
|
||||
}
|
||||
else if( nodedata.type == "eventlauncher" ) {
|
||||
|
||||
|
||||
8
sky.h
8
sky.h
@@ -16,11 +16,13 @@ class TSky {
|
||||
|
||||
friend class opengl_renderer;
|
||||
|
||||
public:
|
||||
TSky() = default;
|
||||
|
||||
void Init();
|
||||
|
||||
private:
|
||||
TModel3d *mdCloud { nullptr };
|
||||
|
||||
public:
|
||||
void Init();
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -467,7 +467,7 @@ float
|
||||
sound_source::compute_combined_point() const {
|
||||
|
||||
return (
|
||||
m_properties.pitch < 1.1f ?
|
||||
m_properties.pitch <= 1.f ?
|
||||
// most sounds use 0-1 value range, we clamp these to 0-99 to allow more intuitive sound definition in .mmd files
|
||||
clamp( m_properties.pitch, 0.f, 0.99f ) :
|
||||
std::max( 0.f, m_properties.pitch )
|
||||
|
||||
2
stars.h
2
stars.h
@@ -16,7 +16,7 @@ public:
|
||||
// methods:
|
||||
void init();
|
||||
// constructors:
|
||||
|
||||
cStars() = default;
|
||||
// deconstructor:
|
||||
|
||||
// members:
|
||||
|
||||
23
sun.cpp
23
sun.cpp
@@ -20,25 +20,17 @@ cSun::~cSun() { gluDeleteQuadric( sunsphere ); }
|
||||
void
|
||||
cSun::init() {
|
||||
|
||||
m_observer.timezone = -1.0 * simulation::Time.zone_bias();
|
||||
|
||||
sunsphere = gluNewQuadric();
|
||||
gluQuadricNormals( sunsphere, GLU_SMOOTH );
|
||||
|
||||
#ifdef _WIN32
|
||||
TIME_ZONE_INFORMATION timezoneinfo; // TODO: timezone dependant on geographic location
|
||||
::GetTimeZoneInformation( &timezoneinfo );
|
||||
m_observer.timezone = -timezoneinfo.Bias / 60.0f;
|
||||
#elif __linux__
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
time_t local = mktime(localtime(&ts.tv_sec));
|
||||
time_t utc = mktime(gmtime(&ts.tv_sec));
|
||||
m_observer.timezone = (local - utc) / 3600.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
cSun::update() {
|
||||
|
||||
m_observer.temp = Global.AirTemperature;
|
||||
|
||||
move();
|
||||
glm::vec3 position( 0.f, 0.f, -1.f );
|
||||
position = glm::rotateX( position, glm::radians( static_cast<float>( m_body.elevref ) ) );
|
||||
@@ -131,7 +123,7 @@ void cSun::move() {
|
||||
if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; }
|
||||
if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; }
|
||||
|
||||
double ut =
|
||||
double localut =
|
||||
localtime.wHour
|
||||
+ localtime.wMinute / 60.0 // too low resolution, noticeable skips
|
||||
+ localtime.wSecond / 3600.0; // good enough in normal circumstances
|
||||
@@ -144,11 +136,10 @@ void cSun::move() {
|
||||
+ 275 * localtime.wMonth / 9
|
||||
+ localtime.wDay
|
||||
- 730530
|
||||
+ ( ut / 24.0 );
|
||||
+ ( localut / 24.0 );
|
||||
|
||||
// Universal Coordinated (Greenwich standard) time
|
||||
m_observer.utime = ut * 3600.0;
|
||||
m_observer.utime = m_observer.utime / 3600.0 - m_observer.timezone;
|
||||
m_observer.utime = localut - m_observer.timezone;
|
||||
// perihelion longitude
|
||||
m_body.phlong = 282.9404 + 4.70935e-5 * daynumber; // w
|
||||
// orbit eccentricity
|
||||
|
||||
149
uilayer.cpp
149
uilayer.cpp
@@ -266,6 +266,8 @@ ui_layer::update() {
|
||||
"" ) );
|
||||
}
|
||||
|
||||
EditorModeFlag = ( Global.iTextMode == GLFW_KEY_F11 );
|
||||
|
||||
switch( Global.iTextMode ) {
|
||||
|
||||
case( GLFW_KEY_F1 ) : {
|
||||
@@ -689,19 +691,7 @@ ui_layer::update() {
|
||||
uitextline3 =
|
||||
"vehicles: " + to_string( Timer::subsystem.sim_dynamics.average(), 2 ) + " msec"
|
||||
+ " update total: " + to_string( Timer::subsystem.sim_total.average(), 2 ) + " msec";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F10 ) : {
|
||||
|
||||
uitextline1 = "Press [Y] key to quit / Aby zakonczyc program, przycisnij klawisz [Y].";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F11 ): {
|
||||
// scenario inspector
|
||||
// current event queue
|
||||
auto const time { Timer::GetTime() };
|
||||
auto const *event { simulation::Events.begin() };
|
||||
auto eventtableindex{ 0 };
|
||||
@@ -727,6 +717,139 @@ ui_layer::update() {
|
||||
break;
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F10 ) : {
|
||||
|
||||
uitextline1 = "Press [Y] key to quit / Aby zakonczyc program, przycisnij klawisz [Y].";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F11 ): {
|
||||
// scenario inspector
|
||||
auto const *node { editor::Node };
|
||||
|
||||
if( node == nullptr ) { break; }
|
||||
|
||||
uitextline1 =
|
||||
"Node name: " + node->name()
|
||||
+ "; location: [" + to_string( node->location().x, 2 ) + ", " + to_string( node->location().y, 2 ) + ", " + to_string( node->location().z, 2 ) + "]"
|
||||
+ " (distance: " + to_string( glm::length( glm::dvec3{ node->location().x, 0.0, node->location().z } -glm::dvec3{ Global.pCameraPosition.x, 0.0, Global.pCameraPosition.z } ), 1 ) + " m)";
|
||||
// subclass-specific data
|
||||
// TBD, TODO: specialized data dump method in each node subclass, or data imports in the panel for provided subclass pointer?
|
||||
if( typeid( *node ) == typeid( TAnimModel ) ) {
|
||||
|
||||
auto const *subnode = static_cast<TAnimModel const *>( node );
|
||||
|
||||
uitextline2 = "angle: " + to_string( clamp_circular( subnode->vAngle.y, 360.0 ), 2 ) + " deg";
|
||||
uitextline2 += "; lights: ";
|
||||
if( subnode->iNumLights > 0 ) {
|
||||
uitextline2 += '[';
|
||||
for( int lightidx = 0; lightidx < subnode->iNumLights; ++lightidx ) {
|
||||
uitextline2 += to_string( subnode->lsLights[ lightidx ] );
|
||||
if( lightidx < subnode->iNumLights - 1 ) {
|
||||
uitextline2 += ", ";
|
||||
}
|
||||
}
|
||||
uitextline2 += ']';
|
||||
}
|
||||
else {
|
||||
uitextline2 += "none";
|
||||
}
|
||||
// 3d shape
|
||||
auto modelfile { (
|
||||
subnode->pModel ?
|
||||
subnode->pModel->NameGet() :
|
||||
"none" ) };
|
||||
if( modelfile.find( szModelPath ) == 0 ) {
|
||||
// don't include 'models/' in the path
|
||||
modelfile.erase( 0, std::string{ szModelPath }.size() );
|
||||
}
|
||||
// texture
|
||||
auto texturefile { (
|
||||
subnode->Material()->replacable_skins[ 1 ] != null_handle ?
|
||||
GfxRenderer.Material( subnode->Material()->replacable_skins[ 1 ] ).name :
|
||||
"none" ) };
|
||||
if( texturefile.find( szTexturePath ) == 0 ) {
|
||||
// don't include 'textures/' in the path
|
||||
texturefile.erase( 0, std::string{ szTexturePath }.size() );
|
||||
}
|
||||
uitextline3 = "mesh: " + modelfile;
|
||||
uitextline4 = "skin: " + texturefile;
|
||||
}
|
||||
else if( typeid( *node ) == typeid( TTrack ) ) {
|
||||
|
||||
auto const *subnode = static_cast<TTrack const *>( node );
|
||||
// basic attributes
|
||||
uitextline2 =
|
||||
"isolated: " + ( subnode->pIsolated ? subnode->pIsolated->asName : "none" )
|
||||
+ "; velocity: " + to_string( subnode->SwitchExtension ? subnode->SwitchExtension->fVelocity : subnode->fVelocity )
|
||||
+ "; width: " + to_string( subnode->fTrackWidth ) + " m"
|
||||
+ "; friction: " + to_string( subnode->fFriction, 2 )
|
||||
+ "; quality: " + to_string( subnode->iQualityFlag );
|
||||
// textures
|
||||
auto texturefile { (
|
||||
subnode->m_material1 != null_handle ?
|
||||
GfxRenderer.Material( subnode->m_material1 ).name :
|
||||
"none" ) };
|
||||
if( texturefile.find( szTexturePath ) == 0 ) {
|
||||
texturefile.erase( 0, std::string{ szTexturePath }.size() );
|
||||
}
|
||||
auto texturefile2{ (
|
||||
subnode->m_material2 != null_handle ?
|
||||
GfxRenderer.Material( subnode->m_material2 ).name :
|
||||
"none" ) };
|
||||
if( texturefile2.find( szTexturePath ) == 0 ) {
|
||||
texturefile2.erase( 0, std::string{ szTexturePath }.size() );
|
||||
}
|
||||
uitextline2 += "; skins: [" + texturefile + ", " + texturefile2 + "]";
|
||||
// paths
|
||||
uitextline3 = "paths: ";
|
||||
for( auto const &path : subnode->m_paths ) {
|
||||
uitextline3 +=
|
||||
"["
|
||||
+ to_string( path.points[ segment_data::point::start ].x, 3 ) + ", "
|
||||
+ to_string( path.points[ segment_data::point::start ].y, 3 ) + ", "
|
||||
+ to_string( path.points[ segment_data::point::start ].z, 3 ) + "]->"
|
||||
+ "["
|
||||
+ to_string( path.points[ segment_data::point::end ].x, 3 ) + ", "
|
||||
+ to_string( path.points[ segment_data::point::end ].y, 3 ) + ", "
|
||||
+ to_string( path.points[ segment_data::point::end ].z, 3 ) + "] ";
|
||||
}
|
||||
// events
|
||||
std::vector< std::pair< std::string, TTrack::event_sequence const * > > const eventsequences {
|
||||
{ "ev0", &subnode->m_events0 }, { "ev0all", &subnode->m_events0all },
|
||||
{ "ev1", &subnode->m_events1 }, { "ev1all", &subnode->m_events1all },
|
||||
{ "ev2", &subnode->m_events2 }, { "ev2all", &subnode->m_events2all } };
|
||||
|
||||
for( auto const &eventsequence : eventsequences ) {
|
||||
if( eventsequence.second->empty() ) { continue; }
|
||||
uitextline4 += eventsequence.first + ": [";
|
||||
for( auto const &event : *( eventsequence.second ) ) {
|
||||
if( uitextline4.back() != '[' ) {
|
||||
uitextline4 += ", ";
|
||||
}
|
||||
if( event.second ) {
|
||||
uitextline4 += event.second->asName;
|
||||
}
|
||||
}
|
||||
uitextline4 += "] ";
|
||||
}
|
||||
|
||||
}
|
||||
else if( typeid( *node ) == typeid( TMemCell ) ) {
|
||||
|
||||
auto const *subnode = static_cast<TMemCell const *>( node );
|
||||
|
||||
uitextline2 =
|
||||
"data: [" + subnode->Text() + "]"
|
||||
+ " [" + to_string( subnode->Value1(), 2 ) + "]"
|
||||
+ " [" + to_string( subnode->Value2(), 2 ) + "]";
|
||||
uitextline3 = "track: " + ( subnode->asTrackName.empty() ? "none" : subnode->asTrackName );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F12 ) : {
|
||||
// opcje włączenia i wyłączenia logowania
|
||||
uitextline1 = "[0] Debugmode " + std::string( DebugModeFlag ? "(on)" : "(off)" );
|
||||
|
||||
@@ -9,8 +9,8 @@ struct ui_panel {
|
||||
|
||||
struct text_line {
|
||||
|
||||
glm::vec4 color;
|
||||
std::string data;
|
||||
glm::vec4 color;
|
||||
|
||||
text_line( std::string const &Data, glm::vec4 const &Color):
|
||||
data(Data), color(Color)
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
// parameters:
|
||||
|
||||
// constructors:
|
||||
|
||||
ui_layer() = default;
|
||||
// destructor:
|
||||
~ui_layer();
|
||||
|
||||
|
||||
@@ -19,13 +19,14 @@ struct TTranscript {
|
||||
class TTranscripts {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
TTranscripts() = default;
|
||||
// methods
|
||||
void AddLine( std::string const &txt, float show, float hide, bool it );
|
||||
// dodanie tekstów, długość dźwięku, czy istotne
|
||||
void Add( std::string const &txt, bool background = false );
|
||||
// usuwanie niepotrzebnych (ok. 10 razy na sekundę)
|
||||
void Update();
|
||||
|
||||
// members
|
||||
std::deque<TTranscript> aLines;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user