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

merge with tmj

This commit is contained in:
Królik Uszasty
2019-03-03 21:28:28 +01:00
28 changed files with 1453 additions and 1506 deletions

View File

@@ -123,12 +123,13 @@ TButton::Turn( bool const State ) {
}
}
void TButton::Update() {
void TButton::Update( bool const Power ) {
if( ( bData != nullptr )
&& ( *bData != m_state ) ) {
auto const state { Power && ( bData ? *bData : m_state ) };
m_state = ( *bData );
if( state != m_state ) {
m_state = state;
play();
}

View File

@@ -30,7 +30,7 @@ public:
bool Active() {
return ( ( pModelOn != nullptr )
|| ( pModelOff != nullptr ) ); }
void Update();
void Update( bool const Power = true );
bool Init( std::string const &asName, TModel3d const *pModel, bool bNewOn = false );
void Load( cParser &Parser, TDynamicObject const *Owner );
void AssignBool(bool const *bValue);

View File

@@ -372,14 +372,13 @@ bool TSpeedPos::Set(basic_event *event, double dist, double length, TOrders orde
iFlags = spEvent;
evEvent = event;
vPos = event->input_location(); // współrzędne eventu albo komórki pamięci (zrzutować na tor?)
if( dist + length >= 0 ) {
iFlags |= spEnabled;
CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości
}
else {
// located behind the tracking consist, don't bother with it
// ignore events located behind the consist, but with exception of stop points which may be needed to update freshly received timetable
if( ( dist + length < 0 )
&& ( event->input_command() != TCommandType::cm_PassengerStopPoint ) ) {
return false;
}
iFlags |= spEnabled;
CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości
// zależnie od trybu sprawdzenie czy jest tutaj gdzieś semafor lub tarcza manewrowa
// jeśli wskazuje stop wtedy wystawiamy true jako koniec sprawdzania
// WriteLog("EventSet: Vel=" + AnsiString(fVelNext) + " iFlags=" + AnsiString(iFlags) + " order="+AnsiString(order));
@@ -486,6 +485,20 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
if (iTableDirection != iDirection ) {
// jeśli zmiana kierunku, zaczynamy od toru ze wskazanym pojazdem
TableClear();
/*
// aktualna prędkość // changed to -1 to recognize speed limit, if any
fLastVel = -1.0;
sSpeedTable.clear();
iLast = -1;
tLast = nullptr; //żaden nie sprawdzony
SemNextIndex = -1;
SemNextStopIndex = -1;
*/
if( VelSignalLast == 0.0 ) {
// don't allow potential red light overrun keep us from reversing
VelSignalLast = -1.0;
}
iTableDirection = iDirection; // ustalenie w jakim kierunku jest wypełniana tabelka względem pojazdu
pTrack = pVehicle->RaTrackGet(); // odcinek, na którym stoi
fTrackLength = pVehicle->RaTranslationGet(); // pozycja na tym torze (odległość od Point1)
@@ -503,17 +516,6 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
.Length();
// aktualna odległość ma być ujemna gdyż jesteśmy na końcu składu
fCurrentDistance = -fLength - fTrackLength;
// aktualna prędkość // changed to -1 to recognize speed limit, if any
fLastVel = -1.0;
sSpeedTable.clear();
iLast = -1;
tLast = nullptr; //żaden nie sprawdzony
SemNextIndex = -1;
SemNextStopIndex = -1;
if( VelSignalLast == 0.0 ) {
// don't allow potential red light overrun keep us from reversing
VelSignalLast = -1.0;
}
fTrackLength = pTrack->Length(); //skasowanie zmian w zmiennej żeby poprawnie liczyło w dalszych krokach
MoveDistanceReset(); // AI startuje 1s po zaczęciu jazdy i mógł już coś przejechać
}
@@ -759,7 +761,7 @@ void TController::TableCheck(double fDistance)
{ // przeliczenie odległości w tabelce, ewentualnie doskanowanie (bez analizy prędkości itp.)
if( iTableDirection != iDirection ) {
// jak zmiana kierunku, to skanujemy od końca składu
TableTraceRoute( fDistance, pVehicles[ 1 ] );
TableTraceRoute( fDistance, pVehicles[ end::rear ] );
TableSort();
}
else if (iTableDirection)
@@ -786,7 +788,7 @@ void TController::TableCheck(double fDistance)
--iLast;
}
tLast = sSpeedTable[ i ].trTrack;
TableTraceRoute( fDistance, pVehicles[ 1 ] );
TableTraceRoute( fDistance, pVehicles[ end::rear ] );
TableSort();
// nie kontynuujemy pętli, trzeba doskanować ciąg dalszy
break;
@@ -824,7 +826,7 @@ void TController::TableCheck(double fDistance)
sSpeedTable[iLast].Update(); // aktualizacja ostatniego
// WriteLog("TableCheck: Upate last track. Dist=" + AnsiString(sSpeedTable[iLast].fDist));
if( sSpeedTable[ iLast ].fDist < fDistance ) {
TableTraceRoute( fDistance, pVehicles[ 1 ] ); // doskanowanie dalszego odcinka
TableTraceRoute( fDistance, pVehicles[ end::rear ] ); // doskanowanie dalszego odcinka
TableSort();
}
// garbage collection
@@ -1030,9 +1032,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
+ ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute)
+ " next " + asNextStop); // informacja
#endif
// update brake settings and ai braking tables
// update consist weight, brake settings and ai braking tables
// NOTE: this calculation is expected to run after completing loading/unloading
AutoRewident(); // nastawianie hamulca do jazdy pociągowej
CheckVehicles(); // nastawianie hamulca do jazdy pociągowej
if( static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 1 ) ) ) ) % 2 ) {
// nie podjeżdżać do semafora, jeśli droga nie jest wolna
@@ -1173,7 +1175,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if( mvOccupied->Vel < 2.0 ) {
// stanąć nie musi, ale zwolnić przynajmniej
if( ( sSpeedTable[ i ].fDist < fMaxProximityDist )
&& ( TrackBlock() > 1000.0 ) ) {
&& ( Obstacle.distance > 1000 ) ) {
// jest w maksymalnym zasięgu to można go pominąć (wziąć drugą prędkosć)
// as long as there isn't any obstacle in arbitrary view range
eSignSkip = sSpeedTable[ i ].evEvent;
@@ -1259,7 +1261,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
//sprawdzenie eventów pasywnych przed nami
if( ( mvOccupied->CategoryFlag & 1 )
&& ( sSpeedTable[ i ].fDist > pVehicles[ 0 ]->fTrackBlock - 20.0 ) ) {
&& ( sSpeedTable[ i ].fDist > Obstacle.distance - 20 ) ) {
// jak sygnał jest dalej niż zawalidroga
v = 0.0; // to może być podany dla tamtego: jechać tak, jakby tam stop był
}
@@ -2061,7 +2063,7 @@ bool TController::CheckVehicles(TOrders user)
&& ( p->MoverParameters->BrakeSubsystem != TBrakeSubSystem::ss_LSt ) ) {
iDrivigFlags &= ~( moveOerlikons );
}
p = p->Neightbour(dir); // pojazd podłączony od wskazanej strony
p = p->Neighbour(dir); // pojazd podłączony od wskazanej strony
}
if (main)
iDrivigFlags |= movePrimary; // nie znaleziono innego, można się porządzić
@@ -2353,7 +2355,6 @@ bool TController::PrepareEngine()
voltrear = false;
LastReactionTime = 0.0;
ReactionTime = PrepareTime;
iDrivigFlags |= moveActive; // może skanować sygnały i reagować na komendy
if ( mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) {
voltfront = true;
@@ -2408,11 +2409,11 @@ bool TController::PrepareEngine()
if( !iDirection ) {
// jeśli nie ma ustalonego kierunku
if( ( mvControlling->PantFrontVolt != 0.0 ) || ( mvControlling->PantRearVolt != 0.0 ) || voltfront || voltrear ) {
if( mvOccupied->Couplers[ 1 ].CouplingFlag == coupling::faux ) {
if( mvOccupied->Couplers[ end::rear ].Connected == nullptr ) {
// jeśli z tyłu nie ma nic
iDirection = -1; // jazda w kierunku sprzęgu 1
}
if( mvOccupied->Couplers[ 0 ].CouplingFlag == coupling::faux ) {
if( mvOccupied->Couplers[ end::front ].Connected == nullptr ) {
// jeśli z przodu nie ma nic
iDirection = 1; // jazda w kierunku sprzęgu 0
}
@@ -2484,6 +2485,8 @@ bool TController::PrepareEngine()
}
eAction = TAction::actUnknown;
iEngineActive = 1;
iDrivigFlags |= moveActive; // może skanować sygnały i reagować na komendy
return true;
}
else {
@@ -2618,12 +2621,12 @@ bool TController::IncBrake()
|| ( mvOccupied->TrainType == dt_ET42 ) ) {
// NOTE: we're doing simplified checks full of presuptions here.
// they'll break if someone does strange thing like turning around the second unit
if( ( mvOccupied->Couplers[ 1 ].CouplingFlag & coupling::permanent )
&& ( mvOccupied->Couplers[ 1 ].Connected->Couplers[ 1 ].CouplingFlag > 0 ) ) {
if( ( mvOccupied->Couplers[ end::rear ].CouplingFlag & coupling::permanent )
&& ( mvOccupied->Couplers[ end::rear ].Connected->Couplers[ end::rear ].Connected != nullptr ) ) {
standalone = false;
}
if( ( mvOccupied->Couplers[ 0 ].CouplingFlag & coupling::permanent )
&& ( mvOccupied->Couplers[ 0 ].Connected->Couplers[ 0 ].CouplingFlag > 0 ) ) {
if( ( mvOccupied->Couplers[ end::front ].CouplingFlag & coupling::permanent )
&& ( mvOccupied->Couplers[ end::front ].Connected->Couplers[ end::front ].Connected != nullptr ) ) {
standalone = false;
}
}
@@ -2637,16 +2640,16 @@ bool TController::IncBrake()
( ( mvOccupied->Couplers[ 0 ].CouplingFlag == 0 )
&& ( mvOccupied->Couplers[ 1 ].CouplingFlag == 0 ) );
*/
if( pVehicles[ 0 ] != pVehicles[ 1 ] ) {
if( pVehicles[ end::front ] != pVehicles[ end::rear ] ) {
// more detailed version, will use manual braking also for coupled sets of controlled vehicles
auto *vehicle = pVehicles[ 0 ]; // start from first
auto *vehicle = pVehicles[ end::front ]; // start from first
while( ( true == standalone )
&& ( vehicle != nullptr ) ) {
// NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself
// TODO: add easier ways to access front/rear coupler taking into account vehicle's direction
standalone =
( ( ( vehicle->MoverParameters->Couplers[ 0 ].CouplingFlag == 0 ) || ( vehicle->MoverParameters->Couplers[ 0 ].CouplingFlag & coupling::control ) )
&& ( ( vehicle->MoverParameters->Couplers[ 1 ].CouplingFlag == 0 ) || ( vehicle->MoverParameters->Couplers[ 1 ].CouplingFlag & coupling::control ) ) );
( ( ( vehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::front ].CouplingFlag & coupling::control ) )
&& ( ( vehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) || ( vehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag & coupling::control ) ) );
vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
}
}
@@ -3172,7 +3175,7 @@ void TController::SpeedSet()
// Ra 2014-06: "automatyczna" skrzynia biegów...
if (!mvControlling->MotorParam[mvControlling->ScndCtrlPos].AutoSwitch) // gdy biegi ręczne
if ((mvControlling->ShuntMode ? mvControlling->AnPos : 1.0) * mvControlling->Vel >
0.6 * mvControlling->MotorParam[mvControlling->ScndCtrlPos].mfi)
0.75 * mvControlling->MotorParam[mvControlling->ScndCtrlPos].mfi)
// if (mvControlling->enrot>0.95*mvControlling->dizel_nMmax) //youBy: jeśli obroty >
// 0,95 nmax, wrzuć wyższy bieg - Ra: to nie działa
{ // jak prędkość większa niż 0.6 maksymalnej na danym biegu, wrzucić wyższy
@@ -3223,7 +3226,7 @@ void TController::Doors( bool const Open, int const Side ) {
auto const lewe = ( pVehicle->DirectionGet() > 0 ) ? 1 : 2;
auto const prawe = 3 - lewe;
if( ( pVehicle->MoverParameters->Doors.open_permit == false )
if( ( true == pVehicle->MoverParameters->Doors.permit_needed )
&& ( true == AIControllFlag ) ) {
// grant door control permission if it's not automatic
// TBD: stricter requirements?
@@ -3247,7 +3250,8 @@ void TController::Doors( bool const Open, int const Side ) {
}
else {
// zamykanie
if( ( true == pVehicle->MoverParameters->Doors.open_permit ) && ( false == doors_open() ) ) {
if( ( false == pVehicle->MoverParameters->Doors.permit_needed )
&& ( false == doors_open() ) ) {
// the doors are already closed and we don't have to revoke control permit, we can skip all hard work
iDrivigFlags &= ~moveDoorOpened;
}
@@ -3265,14 +3269,18 @@ void TController::Doors( bool const Open, int const Side ) {
&& ( ( fActionTime > -0.5 )
|| ( false == AIControllFlag ) ) ) {
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
if( ( pVehicle->MoverParameters->Doors.open_control == control_t::conductor )
if( ( pVehicle->MoverParameters->Doors.close_control == control_t::conductor )
|| ( ( true == AIControllFlag )
&& ( ( pVehicle->MoverParameters->Doors.open_control == control_t::driver )
|| ( pVehicle->MoverParameters->Doors.open_control == control_t::mixed ) ) ) ) {
&& ( ( pVehicle->MoverParameters->Doors.close_control == control_t::driver )
|| ( pVehicle->MoverParameters->Doors.close_control == control_t::mixed ) ) ) ) {
// if the door are controlled by the driver, we let the user operate them unless this user is an ai
// the train conductor, if present, handles door operation also for human-driven trains
pVehicle->MoverParameters->OperateDoors( side::right, false );
pVehicle->MoverParameters->OperateDoors( side::left, false );
if( pVehicle->MoverParameters->Doors.permit_needed ) {
pVehicle->MoverParameters->PermitDoors( side::right, false );
pVehicle->MoverParameters->PermitDoors( side::left, false );
}
}
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
@@ -3301,6 +3309,10 @@ void TController::Doors( bool const Open, int const Side ) {
bool
TController::doors_open() const {
return (
IsAnyDoorOpen[ side::right ]
|| IsAnyDoorOpen[ side::left ] );
/*
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
while( vehicle != nullptr ) {
if( ( false == vehicle->MoverParameters->Doors.instances[side::right].is_closed )
@@ -3312,6 +3324,7 @@ TController::doors_open() const {
}
// if we're still here there's nothing open
return false;
*/
}
void TController::RecognizeCommand()
@@ -3624,22 +3637,21 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
}
WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
}
else // if (NewValue2==0.0) //zerowy sprzęg
if (NewValue1 >= 0.0) // jeśli ilość wagonów inna niż wszystkie
{ // będzie odczepianie, ale jeśli wagony są z przodu, to trzeba najpierw zmienić kierunek
if ((mvOccupied->Couplers[mvOccupied->DirAbsolute > 0 ? 1 : 0].CouplingFlag ==
0) ? // z tyłu nic
(mvOccupied->Couplers[mvOccupied->DirAbsolute > 0 ? 0 : 1].CouplingFlag > 0) :
false) // a z przodu skład
{
iDirectionOrder = -iDirection; // zmiana na ciągnięcie
OrderNext(Change_direction); // najpierw zmień kierunek (zastąpi Disconnect)
OrderPush(Disconnect); // a odczep już po zmianie kierunku
else { // if (NewValue2==0.0) //zerowy sprzęg
if( NewValue1 >= 0.0 ) {
// jeśli ilość wagonów inna niż wszystkie będzie odczepianie,
// ale jeśli wagony są z przodu, to trzeba najpierw zmienić kierunek
if( ( mvOccupied->Couplers[ mvOccupied->DirAbsolute > 0 ? end::rear : end::front ].Connected == nullptr ) // z tyłu nic
&& ( mvOccupied->Couplers[ mvOccupied->DirAbsolute > 0 ? end::front : end::rear ].Connected != nullptr ) ) { // a z przodu skład
iDirectionOrder = -iDirection; // zmiana na ciągnięcie
OrderNext( Change_direction ); // najpierw zmień kierunek (zastąpi Disconnect)
OrderPush( Disconnect ); // a odczep już po zmianie kierunku
}
else if( mvOccupied->Couplers[ mvOccupied->DirAbsolute > 0 ? end::rear : end::front ].Connected != nullptr ) { // z tyłu coś
OrderNext( Disconnect ); // jak ciągnie, to tylko odczep (NewValue1) wagonów
}
WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
}
else if (mvOccupied->Couplers[mvOccupied->DirAbsolute > 0 ? 1 : 0].CouplingFlag >
0) // z tyłu coś
OrderNext(Disconnect); // jak ciągnie, to tylko odczep (NewValue1) wagonów
WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
}
if (NewValue1 == -1.0)
{
@@ -4180,55 +4192,46 @@ TController::UpdateSituation(double dt) {
// 8. Ustalić częstotliwość świadomości AI (zatrzymanie precyzyjne - częściej, brak atrakcji
// - rzadziej).
// check for potential colliders
// check for potential collisions
{
auto rearvehicle = (
pVehicles[ 0 ] == pVehicles[ 1 ] ?
pVehicles[ 0 ] :
pVehicles[ 1 ] );
// HACK: vehicle order in the consist is based on intended travel direction
// if our actual travel direction doesn't match that, we should be scanning from the other end of the consist
// we cast to int to avoid getting confused by microstutters
auto *frontvehicle { pVehicles[ ( static_cast<int>( mvOccupied->V ) * iDirection >= 0 ? end::front : end::rear ) ] };
int routescandirection;
// for moving vehicle determine heading from velocity; for standing fall back on the set direction
if( ( std::abs( mvOccupied->V ) < 0.1 ? // ignore potential micro-stutters in oposite direction during "almost stop"
if( ( std::abs( frontvehicle->MoverParameters->V ) > 0.5 ? // ignore potential micro-stutters in oposite direction during "almost stop"
frontvehicle->MoverParameters->V > 0.0 :
( pVehicle->DirectionGet() == frontvehicle->DirectionGet() ?
iDirection > 0 :
mvOccupied->V > 0.0 ) ) {
iDirection < 0 ) ) ) {
// towards coupler 0
if( ( mvOccupied->V * iDirection < 0.0 )
|| ( ( rearvehicle->NextConnected != nullptr )
&& ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 1 : 0 ) ].CouplingFlag == coupling::faux ) ) ) {
// scan behind if we're moving backward, or if we had something connected there and are moving away
rearvehicle->ABuScanObjects( (
pVehicle->DirectionGet() == rearvehicle->DirectionGet() ?
-1 :
1 ),
fMaxProximityDist );
}
pVehicles[ 0 ]->ABuScanObjects( (
pVehicle->DirectionGet() == pVehicles[ 0 ]->DirectionGet() ?
1 :
-1 ),
routescanrange );
routescandirection = end::front;
}
else {
// towards coupler 1
if( ( mvOccupied->V * iDirection < 0.0 )
|| ( ( rearvehicle->PrevConnected != nullptr )
&& ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 0 : 1 ) ].CouplingFlag == coupling::faux ) ) ) {
// scan behind if we're moving backward, or if we had something connected there and are moving away
rearvehicle->ABuScanObjects( (
pVehicle->DirectionGet() == rearvehicle->DirectionGet() ?
1 :
-1 ),
fMaxProximityDist );
routescandirection = end::rear;
}
Obstacle = neighbour_data();
auto const lookup { frontvehicle->find_vehicle( routescandirection, routescanrange ) };
if( std::get<bool>( lookup ) == true ) {
Obstacle.vehicle = std::get<TDynamicObject *>( lookup );
Obstacle.vehicle_end = std::get<int>( lookup );
Obstacle.distance = std::get<double>( lookup );
if( Obstacle.distance < ( mvOccupied->CategoryFlag == 2 ? 25 : 100 ) ) {
// at short distances (re)calculate range between couplers directly
Obstacle.distance = TMoverParameters::CouplerDist( frontvehicle->MoverParameters, Obstacle.vehicle->MoverParameters );
}
pVehicles[ 0 ]->ABuScanObjects( (
pVehicle->DirectionGet() == pVehicles[ 0 ]->DirectionGet() ?
-1 :
1 ),
routescanrange );
}
else {
Obstacle.distance = 10000; // legacy value. TBD, TODO: use standard -1 instead?
}
}
// tu bedzie logika sterowania
if (AIControllFlag) {
@@ -4290,37 +4293,17 @@ TController::UpdateSituation(double dt) {
if (AIControllFlag)
{ // to robi tylko AI, wersję dla człowieka trzeba dopiero zrobić
// sprzęgi sprawdzamy w pierwszej kolejności, bo jak połączony, to koniec
bool ok; // true gdy się podłączy (uzyskany sprzęg będzie zgodny z żądanym)
if (pVehicles[0]->DirectionGet() > 0) // jeśli sprzęg 0
{ // sprzęg 0 - próba podczepienia
if( pVehicles[ 0 ]->MoverParameters->Couplers[ 0 ].Connected ) {
// jeśli jest coś wykryte (a chyba jest, nie?)
if( pVehicles[ 0 ]->MoverParameters->Attach(
0, 2, pVehicles[ 0 ]->MoverParameters->Couplers[ 0 ].Connected,
iCoupler ) ) {
// pVehicles[0]->dsbCouplerAttach->SetVolume(DSBVOLUME_MAX);
// pVehicles[0]->dsbCouplerAttach->Play(0,0,0);
}
}
// udało się? (mogło częściowo)
ok = (pVehicles[0]->MoverParameters->Couplers[0].CouplingFlag == iCoupler);
}
else // if (pVehicles[0]->MoverParameters->DirAbsolute<0) //jeśli sprzęg 1
{ // sprzęg 1 - próba podczepienia
if( pVehicles[ 0 ]->MoverParameters->Couplers[ 1 ].Connected ) {
// jeśli jest coś wykryte (a chyba jest, nie?)
if( pVehicles[ 0 ]->MoverParameters->Attach(
1, 2, pVehicles[ 0 ]->MoverParameters->Couplers[ 1 ].Connected,
iCoupler ) ) {
// pVehicles[0]->dsbCouplerAttach->SetVolume(DSBVOLUME_MAX);
// pVehicles[0]->dsbCouplerAttach->Play(0,0,0);
}
}
// udało się? (mogło częściowo)
ok = (pVehicles[0]->MoverParameters->Couplers[1].CouplingFlag == iCoupler);
}
if (ok)
{ // jeżeli został podłączony
auto *vehicle { pVehicles[ end::front ] };
auto *vehicleparameters { vehicle->MoverParameters };
int const end { ( vehicle->DirectionGet() > 0 ? end::front : end::rear ) };
auto const &neighbour { vehicleparameters->Neighbours[ end ] };
// próba podczepienia
vehicleparameters->Attach(
end, neighbour.vehicle_end,
neighbour.vehicle->MoverParameters,
iCoupler );
if( vehicleparameters->Couplers[ end ].CouplingFlag == iCoupler ) {
// jeżeli został podłączony
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie
@@ -4336,7 +4319,7 @@ TController::UpdateSituation(double dt) {
fMaxProximityDist = 5.0; //[m] w takim przedziale odległości powinien stanąć
fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
fVelMinus = 1.0; // margines prędkości powodujący załączenie napędu
if( pVehicles[ 0 ]->fTrackBlock <= 20.0 ) {
if( Obstacle.distance <= 20.0 ) {
// przy zderzeniu fTrackBlock nie jest miarodajne
// początek podczepiania, z wyłączeniem sprawdzania fTrackBlock
iDrivigFlags |= moveConnect;
@@ -4476,8 +4459,8 @@ TController::UpdateSituation(double dt) {
&& ( false == TestFlag( iDrivigFlags, movePress ) )
&& ( iCoupler == 0 )
// && ( mvOccupied->Vel > 0.0 )
&& ( pVehicle->MoverParameters->Couplers[ end::front ].CouplingFlag == coupling::faux )
&& ( pVehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag == coupling::faux ) ) {
&& ( pVehicle->MoverParameters->Couplers[ end::front ].Connected == nullptr )
&& ( pVehicle->MoverParameters->Couplers[ end::rear ].Connected == nullptr ) ) {
SetVelocity(0, 0, stopJoin); // 1. faza odczepiania: zatrzymanie
// WriteLog("Zatrzymanie w celu odczepienia");
AccPreferred = std::min( 0.0, AccPreferred );
@@ -4515,7 +4498,7 @@ TController::UpdateSituation(double dt) {
else
{ // samochód ma stać, aż dostanie odjazd, chyba że stoi przez kolizję
if (eStopReason == stopBlock)
if (pVehicles[0]->fTrackBlock > fDriverDist)
if (Obstacle.distance > fDriverDist)
if (AIControllFlag)
{
PrepareEngine(); // zmieni ustawiony kierunek
@@ -4667,7 +4650,8 @@ TController::UpdateSituation(double dt) {
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
}
} while (n--);
if( p ? p->MoverParameters->Couplers[ d ].CouplingFlag == coupling::faux : true ) {
if( ( p == nullptr )
|| ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) {
// no target, or already just virtual coupling
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
iVehicleCount = -2; // odczepiono, co było do odczepienia
@@ -4758,9 +4742,9 @@ TController::UpdateSituation(double dt) {
// w trybie Connect skanować do tyłu tylko jeśli przed kolejnym sygnałem nie ma taboru do podłączenia
// Ra 2F1H: z tym (fTrackBlock) to nie jest najlepszy pomysł, bo lepiej by
// było porównać z odległością od sygnalizatora z przodu
if( ( OrderList[ OrderPos ] & Connect ) ?
( pVehicles[ 0 ]->fTrackBlock > 2000 || pVehicles[ 0 ]->fTrackBlock > FirstSemaphorDist ) :
true ) {
if( ( ( OrderList[ OrderPos ] & Connect ) == 0 )
|| ( Obstacle.distance > std::min( 2000.0, FirstSemaphorDist ) ) ) {
if( ( comm = BackwardScan() ) != TCommandType::cm_Unknown ) {
// jeśli w drugą można jechać
// należy sprawdzać odległość od znalezionego sygnalizatora,
@@ -4785,121 +4769,99 @@ TController::UpdateSituation(double dt) {
VelDesired = fVelMax; // bo VelDesired<0 oznacza prędkość maksymalną
// Ra: jazda na widoczność
/*
// condition disabled, it'd prevent setting reduced acceleration in the last connect stage
if ((iDrivigFlags & moveConnect) == 0) // przy końcówce podłączania nie hamować
*/
{ // sprawdzenie jazdy na widoczność
auto const vehicle = pVehicles[ 0 ]; // base calculactions off relevant end of the consist
auto const coupler =
vehicle->MoverParameters->Couplers + (
vehicle->DirectionGet() > 0 ?
0 :
1 ); // sprzęg z przodu składu
if( ( coupler->Connected )
&& ( coupler->CouplingFlag == coupling::faux ) ) {
// mamy coś z przodu podłączone sprzęgiem wirtualnym
// wyliczanie optymalnego przyspieszenia do jazdy na widoczność
/*
ActualProximityDist = std::min(
if( Obstacle.distance < 5000 ) {
// mamy coś z przodu
// prędkość pojazdu z przodu (zakładając, że jedzie w tę samą stronę!!!)
auto const k { Obstacle.vehicle->MoverParameters->Vel };
if( k - vel < 5 ) {
// porównanie modułów prędkości [km/h]
// zatroszczyć się trzeba, jeśli tamten nie jedzie znacząco szybciej
ActualProximityDist = std::min<double>(
ActualProximityDist,
vehicle->fTrackBlock - (
mvOccupied->CategoryFlag & 2 ?
fMinProximityDist : // cars can bunch up tighter
fMaxProximityDist ) ); // other vehicle types less so
*/
// prędkość pojazdu z przodu (zakładając, że jedzie w tę samą stronę!!!)
double k = coupler->Connected->Vel;
if( k - vel < 5 ) {
// porównanie modułów prędkości [km/h]
// zatroszczyć się trzeba, jeśli tamten nie jedzie znacząco szybciej
ActualProximityDist = std::min(
ActualProximityDist,
vehicle->fTrackBlock );
Obstacle.distance );
if( ActualProximityDist <= (
( mvOccupied->CategoryFlag & 2 ) ?
100.0 : // cars
250.0 ) ) { // others
// regardless of driving mode at close distance take precaution measures:
// match the other vehicle's speed or slow down if the other vehicle is stopped
VelDesired =
min_speed(
VelDesired,
std::max(
k,
( mvOccupied->CategoryFlag & 2 ) ?
40.0 : // cars
20.0 ) ); // others
if( vel > VelDesired + fVelPlus ) {
// if going too fast force some prompt braking
AccPreferred = std::min( -0.65, AccPreferred );
}
if( ActualProximityDist <= (
( mvOccupied->CategoryFlag & 2 ) ?
100.0 : // cars
250.0 ) ) { // others
// regardless of driving mode at close distance take precaution measures:
// match the other vehicle's speed or slow down if the other vehicle is stopped
VelDesired =
min_speed(
VelDesired,
std::max(
k,
( mvOccupied->CategoryFlag & 2 ) ?
40.0 : // cars
20.0 ) ); // others
if( vel > VelDesired + fVelPlus ) {
// if going too fast force some prompt braking
AccPreferred = std::min( -0.65, AccPreferred );
}
}
double const distance = vehicle->fTrackBlock - fMaxProximityDist - ( fBrakeDist * 1.15 ); // odległość bezpieczna zależy od prędkości
if( distance < 0.0 ) {
// jeśli odległość jest zbyt mała
if( k < 10.0 ) // k - prędkość tego z przodu
{ // jeśli tamten porusza się z niewielką prędkością albo stoi
if( OrderCurrentGet() & Connect ) {
// jeśli spinanie, to jechać dalej
AccPreferred = std::min( 0.35, AccPreferred ); // nie hamuj
VelDesired =
min_speed(
VelDesired,
( vehicle->fTrackBlock > 150.0 ?
20.0:
4.0 ) );
VelNext = 2.0; // i pakuj się na tamtego
}
else {
// a normalnie to hamować
VelNext = 0.0;
if( vehicle->fTrackBlock <= fMinProximityDist ) {
VelDesired = 0.0;
}
if( ( mvOccupied->CategoryFlag & 1 )
&& ( OrderCurrentGet() & Obey_train ) ) {
// trains which move normally should try to stop at safe margin
ActualProximityDist -= fDriverDist;
}
}
}
else {
// jeśli oba jadą, to przyhamuj lekko i ogranicz prędkość
if( vehicle->fTrackBlock < (
( 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 ) ?
fMaxProximityDist : // cars
2.0 * fMaxProximityDist ) ) { //others
// try to force speed change if obstacle is really close
VelDesired = VelNext;
}
}
}
ReactionTime = (
mvOccupied->Vel > 0.01 ?
0.1 : // orientuj się, bo jest goraco
2.0 ); // we're already standing still, so take it easy
}
else {
double const distance = Obstacle.distance - fMaxProximityDist - ( fBrakeDist * 1.15 ); // odległość bezpieczna zależy od prędkości
if( distance < 0.0 ) {
// jeśli odległość jest zbyt mała
if( k < 10.0 ) // k - prędkość tego z przodu
{ // jeśli tamten porusza się z niewielką prędkością albo stoi
if( OrderCurrentGet() & Connect ) {
// if there's something nearby in the connect mode don't speed up too much
// jeśli spinanie, to jechać dalej
AccPreferred = std::min( 0.35, AccPreferred ); // nie hamuj
VelDesired =
min_speed(
VelDesired,
( vehicle->fTrackBlock > 100.0 ?
20.0 :
( Obstacle.distance > 150 ?
20.0:
4.0 ) );
VelNext = 2.0; // i pakuj się na tamtego
}
else {
// a normalnie to hamować
VelNext = 0.0;
if( Obstacle.distance <= fMinProximityDist ) {
VelDesired = 0.0;
}
if( ( mvOccupied->CategoryFlag & 1 )
&& ( OrderCurrentGet() & Obey_train ) ) {
// trains which move normally should try to stop at safe margin
ActualProximityDist -= fDriverDist;
}
}
}
else {
// jeśli oba jadą, to przyhamuj lekko i ogranicz prędkość
if( Obstacle.distance < (
( 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( Obstacle.distance <= (
( mvOccupied->CategoryFlag & 2 ) ?
fMaxProximityDist : // cars
2.0 * fMaxProximityDist ) ) { //others
// try to force speed change if obstacle is really close
VelDesired = VelNext;
}
}
}
ReactionTime = (
mvOccupied->Vel > 0.01 ?
0.1 : // orientuj się, bo jest goraco
2.0 ); // we're already standing still, so take it easy
}
else {
if( OrderCurrentGet() & Connect ) {
// if there's something nearby in the connect mode don't speed up too much
VelDesired =
min_speed(
VelDesired,
( Obstacle.distance > 100 ?
20.0 :
4.0 ) );
}
}
}
@@ -5059,7 +5021,7 @@ TController::UpdateSituation(double dt) {
if( mvOccupied->CategoryFlag & 1 ) {
// trains
if( ( OrderCurrentGet() & ( Shunt | Connect ) )
&& ( pVehicles[0]->fTrackBlock < 50.0 ) ) {
&& ( Obstacle.distance < 50 ) ) {
// crude detection of edge case, if approaching another vehicle coast slowly until min distance
// this should allow to bunch up trainsets more on sidings
VelDesired = min_speed( 5.0, VelDesired );
@@ -6343,7 +6305,7 @@ bool TController::IsStop() const
double
TController::TrackBlock() const {
return pVehicles[ end::front ]->fTrackBlock;
return Obstacle.distance;
}
void TController::MoveTo(TDynamicObject *to)

View File

@@ -376,6 +376,7 @@ private:
std::size_t SemNextStopIndex{ std::size_t( -1 ) };
double dMoveLen = 0.0; // odległość przejechana od ostatniego sprawdzenia tabelki
basic_event *eSignNext = nullptr; // sygnał zmieniający prędkość, do pokazania na [F2]
neighbour_data Obstacle; // nearest vehicle detected ahead on current route
// timetable
// methods

File diff suppressed because it is too large Load Diff

View File

@@ -183,12 +183,13 @@ public:
std::string asDestination; // dokąd pojazd ma być kierowany "(stacja):(tor)"
Math3D::matrix4x4 mMatrix; // macierz przekształcenia do renderowania modeli
TMoverParameters *MoverParameters; // parametry fizyki ruchu oraz przeliczanie
TDynamicObject *NextConnected; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
TDynamicObject *PrevConnected; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
int NextConnectedNo; // numer sprzęgu podłączonego z tyłu
int PrevConnectedNo; // numer sprzęgu podłączonego z przodu
double fScanDist; // odległość skanowania torów na obecność innych pojazdów
double fTrackBlock; // odległość do przeszkody do dalszego ruchu (wykrywanie kolizji z innym pojazdem)
inline TDynamicObject *NextConnected() { return MoverParameters->Neighbours[ end::rear ].vehicle; }; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
inline TDynamicObject *PrevConnected() { return MoverParameters->Neighbours[ end::front ].vehicle; }; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
inline TDynamicObject *NextConnected() const { return MoverParameters->Neighbours[ end::rear ].vehicle; }; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
inline TDynamicObject *PrevConnected() const { return MoverParameters->Neighbours[ end::front ].vehicle; }; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
inline int NextConnectedNo() const { return MoverParameters->Neighbours[ end::rear ].vehicle_end; }
inline int PrevConnectedNo() const { return MoverParameters->Neighbours[ end::front ].vehicle_end; }
// double fTrackBlock; // odległość do przeszkody do dalszego ruchu (wykrywanie kolizji z innym pojazdem)
TPowerSource ConnectedEnginePowerSource( TDynamicObject const *Caller ) const;
@@ -455,11 +456,8 @@ private:
int iNumAxles; // ilość osi
std::string asModel;
public:
void ABuScanObjects(int ScanDir, double ScanDist);
private:
TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler );
TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler ) const;
void ABuCheckMyTrack();
public:
@@ -470,7 +468,6 @@ private:
TDynamicObject * Next();
TDynamicObject * PrevC(int C);
TDynamicObject * NextC(int C);
double NextDistance(double d = -1.0);
void SetdMoveLen(double dMoveLen) {
MoverParameters->dMoveLen = dMoveLen; }
void ResetdMoveLen() {
@@ -485,6 +482,7 @@ private:
return this ?
asName :
std::string(); };
std::string asBaseDir;
// std::ofstream PneuLogFile; //zapis parametrow pneumatycznych
// youBy - dym
@@ -506,7 +504,6 @@ private:
bool bDisplayCab; // czy wyswietlac kabine w train.cpp
int iCabs; // maski bitowe modeli kabin
TTrack *MyTrack; // McZapkie-030303: tor na ktorym stoi, ABu
std::string asBaseDir;
int iOverheadMask; // maska przydzielana przez AI pojazdom posiadającym pantograf, aby wymuszały jazdę bezprądową
TTractionParam tmpTraction;
double fAdjustment; // korekcja - docelowo przenieść do TrkFoll.cpp wraz z odległością od poprzedniego
@@ -521,7 +518,7 @@ private:
int init_sections( TModel3d const *Model, std::string const &Nameprefix );
void create_controller( std::string const Type, bool const Trainset );
void AttachPrev(TDynamicObject *Object, int iType = 1);
bool UpdateForce(double dt, double dt1, bool FullVer);
bool UpdateForce(double dt);
// initiates load change by specified amounts, with a platform on specified side
void LoadExchange( int const Disembark, int const Embark, int const Platform );
// calculates time needed to complete current load change
@@ -605,14 +602,13 @@ private:
Axle1.GetTranslation() :
Axle0.GetTranslation(); };
// zwraca tor z aktywną osią
inline TTrack * RaTrackGet() {
inline TTrack * RaTrackGet() const {
return iAxleFirst ?
Axle1.GetTrack() :
Axle0.GetTrack(); };
void couple( int const Side );
int uncouple( int const Side );
void CouplersDettach(double MinDist, int MyScanDir);
void RadioStop();
void Damage(char flag);
void RaLightsSet(int head, int rear);
@@ -626,8 +622,11 @@ private:
return iDirection + iDirection - 1; };
int DettachStatus(int dir);
int Dettach(int dir);
TDynamicObject * Neightbour(int &dir);
void CoupleDist();
TDynamicObject * Neighbour(int &dir);
// updates potential collision sources
void update_neighbours();
// locates potential collision source within specified range, scanning its route in specified direction
auto find_vehicle( int const Direction, double const Range ) const -> std::tuple<TDynamicObject *, int, double, bool>;
TDynamicObject * ControlledFind();
void ParamSet(int what, int into);
// zapytanie do AI, po którym segmencie skrzyżowania jechać

View File

@@ -886,9 +886,14 @@ whois_event::run_() {
auto *targetcell { static_cast<TMemCell *>( std::get<scene::basic_node *>( target ) ) };
if( targetcell == nullptr ) { continue; }
// event effect code
// +24: vehicle type, consist brake level, obstacle distance
// +16: load type, load amount, max load amount
// +8: destination, direction, engine power
// +0: train name, station count, stop on next station
if( m_input.flags & flags::load ) {
// +16 or +24
// jeśli pytanie o ładunek
if( m_input.flags & flags::mode_add ) {
if( m_input.flags & flags::mode_alt ) {
// jeśli typ pojazdu
// TODO: define and recognize individual request types
auto const owner { (
@@ -912,7 +917,7 @@ whois_event::run_() {
WriteLog(
"Type: WhoIs (" + to_string( m_input.flags ) + ") - "
+ "[name: " + m_activator->MoverParameters->TypeName + "], "
+ "[type: " + m_activator->MoverParameters->TypeName + "], "
+ "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], "
+ "[obstacle distance: " + to_string( collisiondistance, 2 ) + " m]" );
}
@@ -931,7 +936,8 @@ whois_event::run_() {
+ "[max load: " + to_string( m_activator->MoverParameters->MaxLoad, 2 ) + "]" );
}
}
else if( m_input.flags & flags::mode_add ) { // jeśli miejsce docelowe pojazdu
// +8
else if( m_input.flags & flags::mode_alt ) { // jeśli miejsce docelowe pojazdu
targetcell->UpdateValues(
m_activator->asDestination, // adres docelowy
m_activator->DirectionGet(), // kierunek pojazdu względem czoła składu (1=zgodny,-1=przeciwny)
@@ -944,6 +950,7 @@ whois_event::run_() {
+ "[direction: " + to_string( m_activator->DirectionGet() ) + "], "
+ "[engine power: " + to_string( m_activator->MoverParameters->Power, 2 ) + "]" );
}
// +0
else if( m_activator->Mechanik ) {
if( m_activator->Mechanik->Primary() ) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera!
targetcell->UpdateValues(
@@ -953,7 +960,11 @@ whois_event::run_() {
1 :
0, // 1, gdy ma tu zatrzymanie
m_input.flags );
WriteLog( "Train detected: " + m_activator->Mechanik->TrainName() );
WriteLog(
"Type: WhoIs (" + to_string( m_input.flags ) + ") - "
+ "[train: " + m_activator->Mechanik->TrainName() + "], "
+ "[stations left: " + to_string( m_activator->Mechanik->StationCount() - m_activator->Mechanik->StationIndex() ) + "], "
+ "[stop at next: " + ( m_activator->Mechanik->IsStop() ? "yes" : "no") + "]" );
}
}
}

View File

@@ -25,8 +25,10 @@ public:
value_1 = 1 << 1,
value_2 = 1 << 2,
// update values
load = 1 << 3,
mode_add = 1 << 4,
mode_add = 1 << 3,
// whois
mode_alt = 1 << 3,
load = 1 << 4,
// condition values
track_busy = 1 << 3,
track_free = 1 << 4,

View File

@@ -360,21 +360,35 @@ void TGauge::AssignInt(int *iValue)
iData = iValue;
};
void TGauge::AssignBool(bool *bValue)
{
m_datatype = 'b';
bData = bValue;
};
void TGauge::UpdateValue()
{ // ustawienie wartości docelowej z parametru
switch (m_datatype)
{ // to nie jest zbyt optymalne, można by zrobić osobne funkcje
case 'f':
UpdateValue( *fData );
break;
case 'd':
UpdateValue( *dData );
break;
case 'i':
UpdateValue( *iData );
break;
default:
break;
case 'f': {
UpdateValue( *fData );
break;
}
case 'd': {
UpdateValue( *dData );
break;
}
case 'i': {
UpdateValue( *iData );
break;
}
case 'b': {
UpdateValue( ( *bData ? 1.f : 0.f ) );
break;
}
default: {
break;
}
}
};

View File

@@ -48,6 +48,7 @@ public:
void AssignFloat(float *fValue);
void AssignDouble(double *dValue);
void AssignInt(int *iValue);
void AssignBool(bool *bValue);
void UpdateValue();
// returns offset of submodel associated with the button from the model centre
glm::vec3 model_offset() const;
@@ -82,6 +83,7 @@ private:
float *fData;
double *dData { nullptr };
int *iData;
bool *bData;
};
int m_soundtype { 0 }; // toggle between exclusive and multiple sound generation
sound_source m_soundtemplate { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // shared properties for control's sounds

View File

@@ -140,7 +140,7 @@ static int const ctrain_depot = 128; //nie rozłączalny podczas zwykłyc
// vehicle sides; exclusive
enum end {
front = 0,
rear
rear = 1
};
enum side {
@@ -609,18 +609,16 @@ struct power_coupling {
struct TCoupling {
/*parametry*/
double SpringKB = 1.0; /*stala sprezystosci zderzaka/sprzegu, %tlumiennosci */
double SpringKC = 1.0;
double beta = 0.0;
double DmaxB = 0.1; /*tolerancja scisku/rozciagania, sila rozerwania*/
double FmaxB = 1000.0;
double SpringKC = 1.0;
double DmaxC = 0.1;
double FmaxC = 1000.0;
TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/
/*zmienne*/
double beta = 0.0;
TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/
int AllowedFlag = 3; //Ra: maska dostępnych
/*zmienne*/
int CouplingFlag = 0; /*0 - wirtualnie, 1 - sprzegi, 2 - pneumatycznie, 4 - sterowanie, 8 - kabel mocy*/
int AllowedFlag = 3; //Ra: znaczenie jak wyżej, maska dostępnych
bool Render = false; /*ABu: czy rysowac jak zaczepiony sprzeg*/
double CoupleDist = 0.0; /*ABu: optymalizacja - liczenie odleglosci raz na klatkę, bez iteracji*/
class TMoverParameters *Connected = nullptr; /*co jest podlaczone*/
int ConnectedNr = 0; //Ra: od której strony podłączony do (Connected): 0=przód, 1=tył
double CForce = 0.0; /*sila z jaka dzialal*/
@@ -628,16 +626,39 @@ struct TCoupling {
bool CheckCollision = false; /*czy sprawdzac sile czy pedy*/
power_coupling power_high;
power_coupling power_low; // TODO: implement this
// power_coupling power_low; // TODO: implement this
int sounds { 0 }; // sounds emitted by the coupling devices
bool Render = false; /*ABu: czy rysowac jak zaczepiony sprzeg*/
};
struct neighbour_data {
TDynamicObject *vehicle { nullptr }; // detected obstacle
int vehicle_end { -1 }; // facing end of the obstacle
float distance { -1.f }; // distance to the obstacle
};
class TMoverParameters
{ // Ra: wrapper na kod pascalowy, przejmujący jego funkcje Q: 20160824 - juz nie wrapper a klasa bazowa :)
private:
// types
/* TODO: implement
// communication cable, exchanging control signals with adjacent vehicle
struct jumper_cable {
// types
using flag_pair = std::pair<bool, bool>;
// members
// booleans
// std::array<bool, 1> flags {};
// boolean pairs, exchanged data is swapped when connected to a matching end (front to front or back to back)
// TBD, TODO: convert to regular bool array for efficiency once it's working?
std::array<flag_pair, 1> flag_pairs {};
// integers
// std::array<int, 1> values {};
};
*/
// basic approximation of a generic device
// TBD: inheritance or composition?
struct basic_device {
@@ -702,6 +723,8 @@ private:
bool is_closing { false }; // the door is currently closing
bool is_opening { false }; // the door is currently opening
bool is_open { false }; // the door is fully open
bool step_folding { false }; // the doorstep is currently closing
bool step_unfolding { false }; // the doorstep is currently opening
};
struct door_data {
@@ -722,9 +745,14 @@ private:
bool has_autowarning { false };
float auto_duration { -1.f }; // automatic door closure delay period
float auto_velocity { -1.f }; // automatic door closure velocity threshold
bool auto_include_remote { false }; // automatic door closure applies also to remote control
bool permit_needed { false };
std::vector<int> permit_presets; // permit presets selectable with preset switch
// ld inputs
bool lock_enabled { true };
bool open_permit { true };
bool step_enabled { true };
// internal data
int permit_preset { -1 }; // curent position of preset selection switch
// vehicle parts
std::array<basic_door, 2> instances; // door on the right and left side of the vehicle
// ld outputs
@@ -800,14 +828,12 @@ private:
public:
double dMoveLen = 0.0;
std::string filename;
/*---opis lokomotywy, wagonu itp*/
/*--opis serii--*/
int CategoryFlag = 1; /*1 - pociag, 2 - samochod, 4 - statek, 8 - samolot*/
/*--sekcja stalych typowych parametrow*/
std::string TypeName; /*nazwa serii/typu*/
//TrainType: string; {typ: EZT/elektrowoz - Winger 040304}
int TrainType = 0; /*Ra: powinno być szybciej niż string*/
int TrainType = 0; /*typ: EZT/elektrowoz - Winger 040304 Ra: powinno być szybciej niż string*/
TEngineType EngineType = TEngineType::None; /*typ napedu*/
TPowerParameters EnginePowerSource; /*zrodlo mocy dla silnikow*/
TPowerParameters SystemPowerSource; /*zrodlo mocy dla systemow sterowania/przetwornic/sprezarek*/
@@ -1059,6 +1085,7 @@ public:
TRotation Rot { 0.0, 0.0, 0.0 };
std::string Name; /*nazwa wlasna*/
TCoupling Couplers[2]; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami
std::array<neighbour_data, 2> Neighbours; // potential collision sources
bool EventFlag = false; /*!o true jesli cos nietypowego sie wydarzy*/
int SoundFlag = 0; /*!o patrz stale sound_ */
double DistCounter = 0.0; /*! licznik kilometrow */
@@ -1289,24 +1316,19 @@ public:
double FrictConst2d= 0.0;
double TotalMassxg = 0.0; /*TotalMass*g*/
Math3D::vector3 vCoulpler[2]; // powtórzenie współrzędnych sprzęgów z DynObj :/
double fBrakeCtrlPos = -2.0; // płynna nastawa hamulca zespolonego
bool bPantKurek3 = true; // kurek trójdrogowy (pantografu): true=połączenie z ZG, false=połączenie z małą sprężarką // domyślnie zbiornik pantografu połączony jest ze zbiornikiem głównym
int iProblem = 0; // flagi problemów z taborem, aby AI nie musiało porównywać; 0=może jechać
int iLights[2]; // bity zapalonych świateł tutaj, żeby dało się liczyć pobór prądu
private:
double CouplerDist(int Coupler);
public:
TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int Cab);
// obsługa sprzęgów
double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2);
/* double Distance(const vector3 &Loc1, const vector3 &Loc2, const vector3 &Dim1, const vector3 &Dim2);
*/ //bool AttachA(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced = false);
static double CouplerDist( TMoverParameters const *Left, TMoverParameters const *Right );
static double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2);
bool Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced = false, bool Audible = true);
int DettachStatus(int ConnectNo);
bool Dettach(int ConnectNo);
void SetCoupleDist();
bool DirectionForward();
void BrakeLevelSet(double b);
bool BrakeLevelAdd(double b);
@@ -1322,7 +1344,7 @@ public:
// Q *******************************************************************************************
double GetTrainsetVoltage(void);
bool Physic_ReActivation(void);
bool switch_physics(bool const State);
double LocalBrakeRatio(void);
double ManualBrakeRatio(void);
double PipeRatio(void);/*ile napelniac*/
@@ -1394,17 +1416,17 @@ public:
/*funkcje obliczajace sily*/
void ComputeConstans(void);//ABu: wczesniejsze wyznaczenie stalych dla liczenia sil
double ComputeMass(void);
void ComputeTotalForce(double dt, double dt1, bool FullVer);
void ComputeTotalForce(double dt);
double Adhesive(double staticfriction) const;
double TractionForce(double dt);
double FrictionForce(double R, int TDamage);
double BrakeForceR(double ratio, double velocity);
double BrakeForceP(double press, double velocity);
double BrakeForce(const TTrackParam &Track);
double CouplerForce(int CouplerN, double dt);
double CouplerForce(int const End, double dt);
void CollisionDetect(int CouplerN, double dt);
/*obrot kol uwzgledniajacy poslizg*/
double ComputeRotatingWheel(double WForce, double dt, double n);
double ComputeRotatingWheel(double WForce, double dt, double n) const;
/*--funkcje dla lokomotyw*/
bool DirectionBackward(void);/*! kierunek ruchu*/
@@ -1472,7 +1494,9 @@ public:
/* funckje dla wagonow*/
bool AssignLoad( std::string const &Name, float const Amount = 0.f );
bool LoadingDone(double LSpeed, std::string const &Loadname);
bool PermitDoors( side const Door, range_t const Notify = range_t::consist );
bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist );
bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist );
bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist );
bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist );
bool LockDoors( bool const State, range_t const Notify = range_t::consist );
bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning

File diff suppressed because it is too large Load Diff

278
Train.cpp
View File

@@ -138,28 +138,17 @@ TButton &TCab::Button(int n)
}
};
void TCab::Update()
void TCab::Update( bool const Power )
{ // odczyt parametrów i ustawienie animacji submodelom
/*
int i;
for (i = 0; i < iGauges; ++i)
{ // animacje izometryczne
ggList[i].UpdateValue(); // odczyt parametru i przeliczenie na kąt
ggList[i].Update(); // ustawienie animacji
}
for (i = 0; i < iButtons; ++i)
{ // animacje dwustanowe
btList[i].Update(); // odczyt parametru i wybór submodelu
}
*/
for( auto &gauge : ggList ) {
// animacje izometryczne
gauge.UpdateValue(); // odczyt parametru i przeliczenie na kąt
gauge.Update(); // ustawienie animacji
}
for( auto &button : btList ) {
// animacje dwustanowe
button.Update(); // odczyt parametru i wybór submodelu
button.Update( Power ); // odczyt parametru i wybór submodelu
}
};
@@ -169,6 +158,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::aidriverenable, &TTrain::OnCommand_aidriverenable },
{ user_command::aidriverdisable, &TTrain::OnCommand_aidriverdisable },
{ user_command::jointcontrollerset, &TTrain::OnCommand_jointcontrollerset },
{ user_command::mastercontrollerincrease, &TTrain::OnCommand_mastercontrollerincrease },
{ user_command::mastercontrollerincreasefast, &TTrain::OnCommand_mastercontrollerincreasefast },
{ user_command::mastercontrollerdecrease, &TTrain::OnCommand_mastercontrollerdecrease },
@@ -325,12 +315,15 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::doortoggleright, &TTrain::OnCommand_doortoggleright },
{ user_command::doorpermitleft, &TTrain::OnCommand_doorpermitleft },
{ user_command::doorpermitright, &TTrain::OnCommand_doorpermitright },
{ user_command::doorpermitpresetactivatenext, &TTrain::OnCommand_doorpermitpresetactivatenext },
{ user_command::doorpermitpresetactivateprevious, &TTrain::OnCommand_doorpermitpresetactivateprevious },
{ user_command::dooropenleft, &TTrain::OnCommand_dooropenleft },
{ user_command::dooropenright, &TTrain::OnCommand_dooropenright },
{ user_command::doorcloseleft, &TTrain::OnCommand_doorcloseleft },
{ user_command::doorcloseright, &TTrain::OnCommand_doorcloseright },
{ user_command::dooropenall, &TTrain::OnCommand_dooropenall },
{ user_command::doorcloseall, &TTrain::OnCommand_doorcloseall },
{ user_command::doorsteptoggle, &TTrain::OnCommand_doorsteptoggle },
{ user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease },
{ user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect },
{ user_command::departureannounce, &TTrain::OnCommand_departureannounce },
@@ -765,12 +758,49 @@ void TTrain::OnCommand_aidriverdisable( TTrain *Train, command_data const &Comma
auto const EU07_CONTROLLER_BASERETURNDELAY { 0.5f };
auto const EU07_CONTROLLER_KEYBOARDETURNDELAY { 1.5f };
void TTrain::OnCommand_jointcontrollerset( TTrain *Train, command_data const &Command ) {
if( Command.action != GLFW_RELEASE ) {
// on press or hold
// value controls brake in range 0-0.5, master controller in range 0.5-1.0
if( Command.param1 >= 0.5 ) {
Train->set_master_controller(
( Command.param1 * 2 - 1 )
* ( Train->mvControlled->CoupledCtrl ?
Train->mvControlled->MainCtrlPosNo + Train->mvControlled->ScndCtrlPosNo :
Train->mvControlled->MainCtrlPosNo ) );
Train->m_mastercontrollerinuse = true;
Train->mvOccupied->LocalBrakePosA = 0;
}
else {
Train->mvOccupied->LocalBrakePosA = (
clamp(
1.0 - ( Command.param1 * 2 ),
0.0, 1.0 ) );
if( Train->mvControlled->MainCtrlPos > 0 ) {
Train->set_master_controller( 0 );
}
}
}
else {
// release
Train->m_mastercontrollerinuse = false;
Train->m_mastercontrollerreturndelay = EU07_CONTROLLER_BASERETURNDELAY; // NOTE: keyboard return delay is omitted for other input sources
}
}
void TTrain::OnCommand_mastercontrollerincrease( TTrain *Train, command_data const &Command ) {
if( Command.action != GLFW_RELEASE ) {
// on press or hold
Train->mvControlled->IncMainCtrl( 1 );
Train->m_mastercontrollerinuse = true;
if( ( Train->ggJointCtrl.SubModel != nullptr )
&& ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) {
OnCommand_independentbrakedecrease( Train, Command );
}
else {
Train->mvControlled->IncMainCtrl( 1 );
Train->m_mastercontrollerinuse = true;
}
}
else {
// release
@@ -783,7 +813,19 @@ void TTrain::OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data
if( Command.action != GLFW_RELEASE ) {
// on press or hold
Train->mvControlled->IncMainCtrl( 2 );
if( ( Train->ggJointCtrl.SubModel != nullptr )
&& ( Train->mvControlled->LocalBrakePosA > 0.0 ) ) {
OnCommand_independentbrakedecreasefast( Train, Command );
}
else {
Train->mvControlled->IncMainCtrl( 2 );
Train->m_mastercontrollerinuse = true;
}
}
else {
// release
Train->m_mastercontrollerinuse = false;
Train->m_mastercontrollerreturndelay = EU07_CONTROLLER_KEYBOARDETURNDELAY + EU07_CONTROLLER_BASERETURNDELAY;
}
}
@@ -791,8 +833,14 @@ void TTrain::OnCommand_mastercontrollerdecrease( TTrain *Train, command_data con
if( Command.action != GLFW_RELEASE ) {
// on press or hold
Train->mvControlled->DecMainCtrl( 1 );
Train->m_mastercontrollerinuse = true;
if( ( Train->ggJointCtrl.SubModel != nullptr )
&& ( Train->mvControlled->MainCtrlPos == 0 ) ) {
OnCommand_independentbrakeincrease( Train, Command );
}
else {
Train->mvControlled->DecMainCtrl( 1 );
Train->m_mastercontrollerinuse = true;
}
}
else {
// release
@@ -805,7 +853,19 @@ void TTrain::OnCommand_mastercontrollerdecreasefast( TTrain *Train, command_data
if( Command.action != GLFW_RELEASE ) {
// on press or hold
Train->mvControlled->DecMainCtrl( 2 );
if( ( Train->ggJointCtrl.SubModel != nullptr )
&& ( Train->mvControlled->MainCtrlPos == 0 ) ) {
OnCommand_independentbrakeincreasefast( Train, Command );
}
else {
Train->mvControlled->DecMainCtrl( 2 );
Train->m_mastercontrollerinuse = true;
}
}
else {
// release
Train->m_mastercontrollerinuse = false;
Train->m_mastercontrollerreturndelay = EU07_CONTROLLER_KEYBOARDETURNDELAY + EU07_CONTROLLER_BASERETURNDELAY;
}
}
@@ -989,7 +1049,7 @@ void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &C
if( Command.action != GLFW_RELEASE ) {
Train->mvControlled->LocalBrakePosA = (
Train->mvOccupied->LocalBrakePosA = (
clamp(
Command.param1,
0.0, 1.0 ) );
@@ -4237,6 +4297,27 @@ void TTrain::OnCommand_doorpermitright( TTrain *Train, command_data const &Comma
}
}
void TTrain::OnCommand_doorpermitpresetactivatenext( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
Train->mvOccupied->ChangeDoorPermitPreset( 1 );
// visual feedback
Train->ggDoorPermitPresetButton.UpdateValue( Train->mvOccupied->Doors.permit_preset, Train->dsbSwitch );
}
}
void TTrain::OnCommand_doorpermitpresetactivateprevious( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
Train->mvOccupied->ChangeDoorPermitPreset( -1 );
// visual feedback
Train->ggDoorPermitPresetButton.UpdateValue( Train->mvOccupied->Doors.permit_preset, Train->dsbSwitch );
}
}
void TTrain::OnCommand_dooropenleft( TTrain *Train, command_data const &Command ) {
auto const remoteopencontrol {
@@ -4575,6 +4656,13 @@ void TTrain::OnCommand_doorcloseall( TTrain *Train, command_data const &Command
}
}
void TTrain::OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
Train->mvOccupied->PermitDoorStep( false == Train->mvOccupied->Doors.step_enabled );
}
}
void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) {
if( ( true == FreeFlyModeFlag )
@@ -4844,11 +4932,11 @@ void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Comm
if( false == Train->CabChange( 1 ) ) {
if( TestFlag( Train->DynamicObject->MoverParameters->Couplers[ end::front ].CouplingFlag, coupling::gangway ) ) {
// przejscie do nastepnego pojazdu
Global.changeDynObj = Train->DynamicObject->PrevConnected;
Global.changeDynObj = Train->DynamicObject->PrevConnected();
Global.changeDynObj->MoverParameters->ActiveCab = (
Train->DynamicObject->PrevConnectedNo ?
-1 :
1 );
Train->DynamicObject->MoverParameters->Neighbours[end::front].vehicle_end ?
-1 :
1 );
}
}
}
@@ -4860,11 +4948,11 @@ void TTrain::OnCommand_cabchangebackward( TTrain *Train, command_data const &Com
if( false == Train->CabChange( -1 ) ) {
if( TestFlag( Train->DynamicObject->MoverParameters->Couplers[ end::rear ].CouplingFlag, coupling::gangway ) ) {
// przejscie do nastepnego pojazdu
Global.changeDynObj = Train->DynamicObject->NextConnected;
Global.changeDynObj = Train->DynamicObject->NextConnected();
Global.changeDynObj->MoverParameters->ActiveCab = (
Train->DynamicObject->NextConnectedNo ?
-1 :
1 );
Train->DynamicObject->MoverParameters->Neighbours[end::rear].vehicle_end ?
-1 :
1 );
}
}
}
@@ -5237,14 +5325,14 @@ bool TTrain::Update( double const Deltatime )
{
TDynamicObject *tmp;
tmp = NULL;
if (DynamicObject->NextConnected)
if (DynamicObject->NextConnected())
if ((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) &&
(mvOccupied->ActiveCab == 1))
tmp = DynamicObject->NextConnected;
if (DynamicObject->PrevConnected)
tmp = DynamicObject->NextConnected();
if (DynamicObject->PrevConnected())
if ((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) &&
(mvOccupied->ActiveCab == -1))
tmp = DynamicObject->PrevConnected;
tmp = DynamicObject->PrevConnected();
if( tmp ) {
if( tmp->MoverParameters->Power > 0 ) {
if( ggI1B.SubModel ) {
@@ -5285,7 +5373,7 @@ bool TTrain::Update( double const Deltatime )
ggClockHInd.Update();
}
Cabine[iCabn].Update(); // nowy sposób ustawienia animacji
Cabine[iCabn].Update( mvControlled->Battery || mvControlled->ConverterFlag ); // nowy sposób ustawienia animacji
if (ggZbS.SubModel)
{
ggZbS.UpdateValue(mvOccupied->Handle->GetCP());
@@ -5645,10 +5733,10 @@ bool TTrain::Update( double const Deltatime )
tmp = NULL;
if ((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) &&
(mvOccupied->ActiveCab > 0))
tmp = DynamicObject->NextConnected;
tmp = DynamicObject->NextConnected();
if ((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) &&
(mvOccupied->ActiveCab < 0))
tmp = DynamicObject->PrevConnected;
tmp = DynamicObject->PrevConnected();
if (tmp)
if ( mvControlled->Battery || mvControlled->ConverterFlag ) {
@@ -5715,7 +5803,21 @@ bool TTrain::Update( double const Deltatime )
}
}
// McZapkie-080602: obroty (albo translacje) regulatorow
if (ggMainCtrl.SubModel) {
if( ggJointCtrl.SubModel != nullptr ) {
// joint master controller moves forward to adjust power and backward to adjust brakes
auto const brakerangemultiplier {
( mvControlled->CoupledCtrl ?
mvControlled->MainCtrlPosNo + mvControlled->ScndCtrlPosNo :
mvControlled->MainCtrlPosNo )
/ static_cast<double>(LocalBrakePosNo) };
ggJointCtrl.UpdateValue(
( mvOccupied->LocalBrakePosA > 0.0 ? mvOccupied->LocalBrakePosA * LocalBrakePosNo * -1 * brakerangemultiplier :
mvControlled->CoupledCtrl ? double( mvControlled->MainCtrlPos + mvControlled->ScndCtrlPos ) :
double( mvControlled->MainCtrlPos ) ),
dsbNastawnikJazdy );
ggJointCtrl.Update();
}
if ( ggMainCtrl.SubModel != nullptr ) {
#ifdef _WIN32
if( ( DynamicObject->Mechanik != nullptr )
@@ -5802,7 +5904,7 @@ bool TTrain::Update( double const Deltatime )
ggBrakeCtrl.Update();
}
if( ggLocalBrake.SubModel ) {
if( ggLocalBrake.SubModel != nullptr ) {
#ifdef _WIN32
if( ( DynamicObject->Mechanik != nullptr )
&& ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI
@@ -5839,6 +5941,7 @@ bool TTrain::Update( double const Deltatime )
// NBMX wrzesien 2003 - drzwi
ggDoorLeftPermitButton.Update();
ggDoorRightPermitButton.Update();
ggDoorPermitPresetButton.Update();
ggDoorLeftButton.Update();
ggDoorRightButton.Update();
ggDoorLeftOnButton.Update();
@@ -5869,11 +5972,12 @@ bool TTrain::Update( double const Deltatime )
InstrumentLightType == 1 ? mvControlled->Mains :
InstrumentLightType == 2 ? mvControlled->ConverterFlag :
InstrumentLightType == 3 ? mvControlled->Battery || mvControlled->ConverterFlag :
InstrumentLightType == 4 ? mvControlled->Battery || mvControlled->ConverterFlag :
false ) };
if( InstrumentLightType == 3 ) {
// TODO: link the light state with the state of the master key
InstrumentLightActive = true;
}
InstrumentLightActive = (
InstrumentLightType == 3 ? true : // TODO: link the light state with the state of the master key
InstrumentLightType == 4 ? ( mvOccupied->iLights[end::front] != 0 ) || ( mvOccupied->iLights[end::rear] != 0 ) :
InstrumentLightActive );
btInstrumentLight.Turn( InstrumentLightActive && lightpower );
btDashboardLight.Turn( DashboardLightActive && lightpower );
btTimetableLight.Turn( TimetableLightActive && lightpower );
@@ -6245,7 +6349,10 @@ TTrain::update_sounds( double const Deltatime ) {
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
if( false == dsbBuzzer.is_playing() ) {
dsbBuzzer.play( sound_flags::looping );
dsbBuzzer
.pitch( dsbBuzzer.m_frequencyoffset + dsbBuzzer.m_frequencyfactor )
.gain( dsbBuzzer.m_amplitudeoffset + dsbBuzzer.m_amplitudefactor )
.play( sound_flags::looping );
Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
}
@@ -6270,9 +6377,10 @@ TTrain::update_sounds( double const Deltatime ) {
auto const frequency { (
true == dsbHasler.is_combined() ?
fTachoVelocity * 0.01 :
1.0 ) };
dsbHasler.m_frequencyoffset + dsbHasler.m_frequencyfactor ) };
dsbHasler
.pitch( frequency )
.gain( dsbHasler.m_amplitudeoffset + dsbHasler.m_amplitudefactor )
.play( sound_flags::exclusive | sound_flags::looping );
}
else if( fTachoCount < 1.f ) {
@@ -6827,6 +6935,9 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
if( dsbReverserKey.offset() == nullvector ) {
dsbReverserKey.offset( ggDirKey.model_offset() );
}
if( dsbNastawnikJazdy.offset() == nullvector ) {
dsbNastawnikJazdy.offset( ggJointCtrl.model_offset() );
}
if( dsbNastawnikJazdy.offset() == nullvector ) {
dsbNastawnikJazdy.offset( ggMainCtrl.model_offset() );
}
@@ -6925,26 +7036,25 @@ void TTrain::DynamicSet(TDynamicObject *d)
mvOccupied = mvControlled = d ? DynamicObject->MoverParameters : NULL; // albo silnikowy w EZT
if (!DynamicObject)
return;
if (mvControlled->TrainType & dt_EZT) // na razie dotyczy to EZT
if (DynamicObject->NextConnected ? mvControlled->Couplers[1].AllowedFlag & ctrain_depot :
false)
{ // gdy jest człon od sprzęgu 1, a sprzęg łączony
// warsztatowo (powiedzmy)
if ((mvControlled->Power < 1.0) && (mvControlled->Couplers[1].Connected->Power >
1.0)) // my nie mamy mocy, ale ten drugi ma
mvControlled =
DynamicObject->NextConnected->MoverParameters; // będziemy sterować tym z mocą
// TODO: leverage code already present in TDynamicObject::ControlledFind()
if( ( d->MoverParameters->TrainType == dt_EZT )
|| ( d->MoverParameters->TrainType == dt_DMU ) ) {
if( ( d->NextConnected() != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::rear ].AllowedFlag, coupling::permanent ) ) ) {
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 1 ].Connected->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
mvControlled = DynamicObject->NextConnected()->MoverParameters; // będziemy sterować tym z mocą
}
}
else if (DynamicObject->PrevConnected ?
mvControlled->Couplers[0].AllowedFlag & ctrain_depot :
false)
{ // gdy jest człon od sprzęgu 0, a sprzęg łączony
// warsztatowo (powiedzmy)
if ((mvControlled->Power < 1.0) && (mvControlled->Couplers[0].Connected->Power >
1.0)) // my nie mamy mocy, ale ten drugi ma
mvControlled =
DynamicObject->PrevConnected->MoverParameters; // będziemy sterować tym z mocą
else if( ( d->PrevConnected() != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ end::front ].AllowedFlag, coupling::permanent ) ) ) {
if( ( mvControlled->Power < 1.0 ) && ( mvControlled->Couplers[ 0 ].Connected->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
mvControlled = DynamicObject->PrevConnected()->MoverParameters; // będziemy sterować tym z mocą
}
}
}
mvSecond = NULL; // gdyby się nic nie znalazło
if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo
if (mvOccupied->Couplers[1].Connected ?
@@ -7069,6 +7179,7 @@ void TTrain::clear_cab_controls()
// other cab controls
// TODO: arrange in more readable manner, and eventually refactor
ggJointCtrl.Clear();
ggMainCtrl.Clear();
ggMainCtrlAct.Clear();
ggScndCtrl.Clear();
@@ -7116,6 +7227,7 @@ void TTrain::clear_cab_controls()
ggRadioTest.Clear();
ggDoorLeftPermitButton.Clear();
ggDoorRightPermitButton.Clear();
ggDoorPermitPresetButton.Clear();
ggDoorLeftButton.Clear();
ggDoorRightButton.Clear();
ggDoorLeftOnButton.Clear();
@@ -7429,6 +7541,7 @@ void TTrain::set_cab_controls( int const Cab ) {
0.f ) );
// doors
// NOTE: for the time being permit switches are presumed to be impulse switches
ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset );
ggDoorLeftButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].is_closed ? 0.f : 1.f );
ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].is_closed ? 0.f : 1.f );
// door lock
@@ -7648,7 +7761,8 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
// TODO: move viable dedicated lights to the automatic light array
std::unordered_map<std::string, bool *> const autolights = {
{ "i-doorpermit_left:", &mvOccupied->Doors.instances[side::left].open_permit },
{ "i-doorpermit_right:", &mvOccupied->Doors.instances[ side::right ].open_permit }
{ "i-doorpermit_right:", &mvOccupied->Doors.instances[ side::right ].open_permit },
{ "i-doorstep:", &mvOccupied->Doors.step_enabled }
};
{
auto lookup = autolights.find( Label );
@@ -7676,6 +7790,10 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
btInstrumentLight.Load( Parser, DynamicObject );
InstrumentLightType = 3;
}
else if( Label == "i-instrumentlight_l:" ) {
btInstrumentLight.Load( Parser, DynamicObject );
InstrumentLightType = 4;
}
else if (Label == "i-doors:")
{
int i = Parser.getToken<int>() - 1;
@@ -7697,6 +7815,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int const Cabindex) {
std::unordered_map<std::string, TGauge &> const gauges = {
{ "jointctrl:", ggJointCtrl },
{ "mainctrl:", ggMainCtrl },
{ "scndctrl:", ggScndCtrl },
{ "dirkey:" , ggDirKey },
@@ -7725,6 +7844,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "stlinoff_bt:", ggStLinOffButton },
{ "doorleftpermit_sw:", ggDoorLeftPermitButton },
{ "doorrightpermit_sw:", ggDoorRightPermitButton },
{ "doorpermitpreset_sw:", ggDoorPermitPresetButton },
{ "door_left_sw:", ggDoorLeftButton },
{ "door_right_sw:", ggDoorRightButton },
{ "doorlefton_sw:", ggDoorLeftOnButton },
@@ -7800,14 +7920,31 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "universal8:", ggUniversals[ 8 ] },
{ "universal9:", ggUniversals[ 9 ] }
};
auto lookup = gauges.find( Label );
if( lookup != gauges.end() ) {
lookup->second.Load( Parser, DynamicObject);
m_controlmapper.insert( lookup->second, lookup->first );
return true;
{
auto lookup = gauges.find( Label );
if( lookup != gauges.end() ) {
lookup->second.Load( Parser, DynamicObject );
m_controlmapper.insert( lookup->second, lookup->first );
return true;
}
}
// TODO: move viable dedicated gauges to the automatic array
std::unordered_map<std::string, bool *> const autoboolgauges = {
{ "doorstep_sw:", &mvOccupied->Doors.step_enabled }
};
{
auto lookup = autoboolgauges.find( Label );
if( lookup != autoboolgauges.end() ) {
auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna lampka
gauge.Load( Parser, DynamicObject );
gauge.AssignBool( lookup->second );
m_controlmapper.insert( gauge, lookup->first );
return true;
}
}
// ABu 090305: uniwersalne przyciski lub inne rzeczy
else if( Label == "mainctrlact:" ) {
if( Label == "mainctrlact:" ) {
ggMainCtrlAct.Load( Parser, DynamicObject);
}
// SEKCJA WSKAZNIKOW
@@ -7997,6 +8134,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
}
}
}
else if( Label == "clock_seconds:" ) {
ggClockSInd.Load( Parser, DynamicObject );
}
else if (Label == "evoltage:")
{
// woltomierz napiecia silnikow

12
Train.h
View File

@@ -32,7 +32,7 @@ class TCab {
public:
// methods
void Load(cParser &Parser);
void Update();
void Update( bool const Power );
TGauge &Gauge( int n = -1 ); // pobranie adresu obiektu
TButton &Button( int n = -1 ); // pobranie adresu obiektu
// members
@@ -51,7 +51,7 @@ public:
private:
// members
std::vector<TGauge> ggList;
std::deque<TGauge> ggList; // need a container which doesn't invalidate references
std::vector<TButton> btList;
};
@@ -155,6 +155,7 @@ class TTrain
// TBD, TODO: consider this approach if we ever want to have customized consist behaviour to received commands, based on the consist/vehicle type or whatever
static void OnCommand_aidriverenable( TTrain *Train, command_data const &Command );
static void OnCommand_aidriverdisable( TTrain *Train, command_data const &Command );
static void OnCommand_jointcontrollerset( TTrain *Train, command_data const &Command );
static void OnCommand_mastercontrollerincrease( TTrain *Train, command_data const &Command );
static void OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data const &Command );
static void OnCommand_mastercontrollerdecrease( TTrain *Train, command_data const &Command );
@@ -315,12 +316,15 @@ class TTrain
static void OnCommand_doortoggleright( TTrain *Train, command_data const &Command );
static void OnCommand_doorpermitleft( TTrain *Train, command_data const &Command );
static void OnCommand_doorpermitright( TTrain *Train, command_data const &Command );
static void OnCommand_doorpermitpresetactivatenext( TTrain *Train, command_data const &Command );
static void OnCommand_doorpermitpresetactivateprevious( TTrain *Train, command_data const &Command );
static void OnCommand_dooropenleft( TTrain *Train, command_data const &Command );
static void OnCommand_dooropenright( TTrain *Train, command_data const &Command );
static void OnCommand_doorcloseleft( TTrain *Train, command_data const &Command );
static void OnCommand_doorcloseright( TTrain *Train, command_data const &Command );
static void OnCommand_dooropenall( TTrain *Train, command_data const &Command );
static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command );
static void OnCommand_doorsteptoggle( TTrain *Train, command_data const &Command );
static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command );
static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command );
static void OnCommand_departureannounce( TTrain *Train, command_data const &Command );
@@ -369,6 +373,7 @@ public: // reszta może by?publiczna
TGauge ggWater1TempB;
// McZapkie: definicje regulatorow
TGauge ggJointCtrl;
TGauge ggMainCtrl;
TGauge ggMainCtrlAct;
TGauge ggScndCtrl;
@@ -445,6 +450,7 @@ public: // reszta może by?publiczna
// NBMX wrzesien 2003 - obsluga drzwi
TGauge ggDoorLeftPermitButton;
TGauge ggDoorRightPermitButton;
TGauge ggDoorPermitPresetButton;
TGauge ggDoorLeftButton;
TGauge ggDoorRightButton;
TGauge ggDoorLeftOnButton;
@@ -517,7 +523,7 @@ public: // reszta może by?publiczna
TButton btInstrumentLight;
TButton btDashboardLight;
TButton btTimetableLight;
int InstrumentLightType{ 0 }; // ABu 030405 - swiecenie uzaleznione od: 0-nic, 1-obw.gl, 2-przetw., 3-rozrzad
int InstrumentLightType{ 0 }; // ABu 030405 - swiecenie uzaleznione od: 0-nic, 1-obw.gl, 2-przetw., 3-rozrzad, 4-external lights
bool InstrumentLightActive{ false };
bool DashboardLightActive{ false };
bool TimetableLightActive{ false };

View File

@@ -96,10 +96,6 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
// bPrimary=true - jest pierwszą osią w pojeździe, czyli generuje eventy i przepisuje pojazd
// Ra: zwraca false, jeśli pojazd ma być usunięty
auto const ismoving { ( std::abs( fDistance ) > 0.01 ) && ( Owner->GetVelocity() > 0.01 ) };
int const eventfilter { (
( ( true == ismoving ) && ( Owner->ctOwner != nullptr ) ) ?
Owner->ctOwner->Direction() * ( Owner->ctOwner->Vehicle()->DirectionGet() == Owner->DirectionGet() ? 1 : -1 ) * ( fDirection > 0 ? 1 : -1 ) :
0 ) };
fDistance *= fDirection; // dystans mnożnony przez kierunek
double s; // roboczy dystans
double dir; // zapamiętany kierunek do sprawdzenia, czy się zmienił
@@ -110,6 +106,13 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
// TODO: refactor following block as track method
if( pCurrentTrack->m_events ) { // sumaryczna informacja o eventach
// omijamy cały ten blok, gdy tor nie ma on żadnych eventów (większość nie ma)
int const eventfilter { (
false == ismoving ? 0 : // only moving vehicles activate events type 1/2
false == bPrimary ? 0 : // only primary axle activates events type 1/2
Owner->ctOwner == nullptr ?
( fDistance > 0 ? 1 : -1 ) : // loose vehicle has no means to determine 'intended' direction so the filter does effectively nothing in such case
( fDirection > 0 ? 1 : -1 ) * Owner->ctOwner->Direction() * ( Owner->ctOwner->Vehicle()->DirectionGet() == Owner->DirectionGet() ? 1 : -1 ) ) };
if( false == ismoving ) {
//McZapkie-140602: wyzwalanie zdarzenia gdy pojazd stoi
if( ( Owner->Mechanik != nullptr )
@@ -127,16 +130,12 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
&& ( Owner->Mechanik->Primary() ) ) {
// tylko dla jednego członu
// McZapkie-280503: wyzwalanie event tylko dla pojazdow z obsada
if( true == bPrimary ) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner );
}
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner );
}
}
if( SetFlag( iEventallFlag, -1 ) ) {
// McZapkie-280503: wyzwalanie eventall dla wszystkich pojazdow
if( true == bPrimary ) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1all, Owner );
}
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1all, Owner );
}
}
else if( ( fDistance > 0 ) && ( eventfilter > 0 ) ) {
@@ -146,16 +145,12 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
if( ( Owner->Mechanik != nullptr )
&& ( Owner->Mechanik->Primary() ) ) {
// tylko dla jednego członu
if( true == bPrimary ) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, 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 ) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2all, Owner );
}
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2all, Owner );
}
}
}

View File

@@ -22,6 +22,7 @@ commanddescription_sequence Commands_descriptions = {
{ "aidriverenable", command_target::vehicle },
{ "aidriverdisable", command_target::vehicle },
{ "jointcontrollerset", command_target::vehicle },
{ "mastercontrollerincrease", command_target::vehicle },
{ "mastercontrollerincreasefast", command_target::vehicle },
{ "mastercontrollerdecrease", command_target::vehicle },
@@ -144,12 +145,15 @@ commanddescription_sequence Commands_descriptions = {
{ "doortoggleright", command_target::vehicle },
{ "doorpermitleft", command_target::vehicle },
{ "doorpermitright", command_target::vehicle },
{ "doorpermitpresetactivatenext", command_target::vehicle },
{ "doorpermitpresetactivateprevious", command_target::vehicle },
{ "dooropenleft", command_target::vehicle },
{ "dooropenright", command_target::vehicle },
{ "dooropenall", command_target::vehicle },
{ "doorcloseleft", command_target::vehicle },
{ "doorcloseright", command_target::vehicle },
{ "doorcloseall", command_target::vehicle },
{ "doorsteptoggle", command_target::vehicle },
{ "departureannounce", command_target::vehicle },
{ "doorlocktoggle", command_target::vehicle },
{ "pantographcompressorvalvetoggle", command_target::vehicle },

View File

@@ -16,6 +16,7 @@ enum class user_command {
aidriverenable,
aidriverdisable,
jointcontrollerset,
mastercontrollerincrease,
mastercontrollerincreasefast,
mastercontrollerdecrease,
@@ -137,12 +138,15 @@ enum class user_command {
doortoggleright,
doorpermitleft,
doorpermitright,
doorpermitpresetactivatenext,
doorpermitpresetactivateprevious,
dooropenleft,
dooropenright,
dooropenall,
doorcloseleft,
doorcloseright,
doorcloseall,
doorsteptoggle,
departureannounce,
doorlocktoggle,
pantographcompressorvalvetoggle,

View File

@@ -27,6 +27,7 @@ driverkeyboard_input::default_bindings() {
m_bindingsetups = {
{ user_command::aidriverenable, GLFW_KEY_Q | keymodifier::shift },
{ user_command::aidriverdisable, GLFW_KEY_Q },
// jointcontrollerset,
{ user_command::mastercontrollerincrease, GLFW_KEY_KP_ADD },
{ user_command::mastercontrollerincreasefast, GLFW_KEY_KP_ADD | keymodifier::shift },
{ user_command::mastercontrollerdecrease, GLFW_KEY_KP_SUBTRACT },
@@ -144,11 +145,17 @@ driverkeyboard_input::default_bindings() {
{ user_command::carcouplingdisconnect, GLFW_KEY_DELETE },
{ user_command::doortoggleleft, GLFW_KEY_COMMA },
{ user_command::doortoggleright, GLFW_KEY_PERIOD },
{ user_command::doorpermitleft, GLFW_KEY_COMMA | keymodifier::shift },
{ user_command::doorpermitright, GLFW_KEY_PERIOD | keymodifier::shift },
{ user_command::doorpermitpresetactivatenext, GLFW_KEY_PERIOD | keymodifier::shift | keymodifier::control },
{ user_command::doorpermitpresetactivateprevious, GLFW_KEY_COMMA | keymodifier::shift | keymodifier::control },
// dooropenleft,
// dooropenright,
{ user_command::dooropenall, GLFW_KEY_SLASH | keymodifier::shift },
// doorcloseleft,
// doorcloseright,
{ user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control },
// doorsteptoggle,
{ user_command::departureannounce, GLFW_KEY_SLASH },
{ user_command::doorlocktoggle, GLFW_KEY_S | keymodifier::control },
{ user_command::pantographcompressorvalvetoggle, GLFW_KEY_V | keymodifier::control },
@@ -202,8 +209,8 @@ driverkeyboard_input::default_bindings() {
{ user_command::instrumentlighttoggle, GLFW_KEY_SEMICOLON },
// instrumentlightenable,
// instrumentlightdisable,
// dashboardlighttoggle,
// timetablelighttoggle,
{ user_command::dashboardlighttoggle, GLFW_KEY_SEMICOLON | keymodifier::shift },
{ user_command::timetablelighttoggle, GLFW_KEY_APOSTROPHE | keymodifier::shift },
{ user_command::generictoggle0, GLFW_KEY_0 },
{ user_command::generictoggle1, GLFW_KEY_1 },
{ user_command::generictoggle2, GLFW_KEY_2 },

View File

@@ -21,6 +21,8 @@ http://mozilla.org/MPL/2.0/.
#include "uilayer.h"
#include "Logs.h"
auto const EU07_CONTROLLER_MOUSESLIDERSIZE{ 0.65 };
void
mouse_slider::bind( user_command const &Command ) {
@@ -29,6 +31,7 @@ mouse_slider::bind( user_command const &Command ) {
auto const *train { simulation::Train };
TMoverParameters const *vehicle { nullptr };
switch( m_command ) {
case user_command::jointcontrollerset:
case user_command::mastercontrollerset:
case user_command::secondcontrollerset: {
vehicle = ( train ? train->Controlled() : nullptr );
@@ -47,6 +50,29 @@ mouse_slider::bind( user_command const &Command ) {
// calculate initial value and accepted range
switch( m_command ) {
case user_command::jointcontrollerset: {
// NOTE: special case, merges two separate controls
auto const *occupied { train ? train->Occupied() : nullptr };
if( occupied == nullptr ) { return; }
auto const powerrange { static_cast<double>(
vehicle->CoupledCtrl ?
vehicle->MainCtrlPosNo + vehicle->ScndCtrlPosNo :
vehicle->MainCtrlPosNo ) };
// for simplicity upper half of the range controls power, lower controls brakes
auto const brakerangemultiplier { powerrange / LocalBrakePosNo };
m_valuerange = 1.0;
m_value =
0.5
+ 0.5 * ( vehicle->CoupledCtrl ?
vehicle->MainCtrlPos + vehicle->ScndCtrlPos :
vehicle->MainCtrlPos ) / powerrange
- 0.5 * occupied->LocalBrakePosA;
m_analogue = true;
m_invertrange = false;
break;
}
case user_command::mastercontrollerset: {
m_valuerange = (
vehicle->CoupledCtrl ?
@@ -57,24 +83,28 @@ mouse_slider::bind( user_command const &Command ) {
vehicle->MainCtrlPos + vehicle->ScndCtrlPos :
vehicle->MainCtrlPos );
m_analogue = false;
m_invertrange = false;
break;
}
case user_command::secondcontrollerset: {
m_valuerange = vehicle->ScndCtrlPosNo;
m_value = vehicle->ScndCtrlPos;
m_analogue = false;
m_invertrange = true;
break;
}
case user_command::trainbrakeset: {
m_valuerange = 1.0;
m_value = ( vehicle->fBrakeCtrlPos - vehicle->Handle->GetPos( bh_MIN ) ) / ( vehicle->Handle->GetPos( bh_MAX ) - vehicle->Handle->GetPos( bh_MIN ) );
m_analogue = true;
m_invertrange = true;
break;
}
case user_command::independentbrakeset: {
m_valuerange = 1.0;
m_value = vehicle->LocalBrakePosA;
m_analogue = true;
m_invertrange = true;
break;
}
default: {
@@ -86,14 +116,18 @@ mouse_slider::bind( user_command const &Command ) {
Application.get_cursor_pos( m_cursorposition.x, m_cursorposition.y );
Application.set_cursor( GLFW_CURSOR_DISABLED );
auto const controlsize { Global.iWindowHeight * 0.75 };
auto const controlsize { Global.iWindowHeight * EU07_CONTROLLER_MOUSESLIDERSIZE };
auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 };
auto const stepsize { controlsize / m_valuerange };
if( m_invertrange ) {
m_value = ( m_analogue ? 1.0 : m_valuerange ) - m_value;
}
Application.set_cursor_pos(
Global.iWindowWidth * 0.5,
( m_analogue ?
controledge - ( 1.0 - m_value ) * controlsize :
controledge - m_value * controlsize :
controledge - m_value * stepsize - 0.5 * stepsize ) );
}
@@ -108,15 +142,17 @@ mouse_slider::release() {
void
mouse_slider::on_move( double const Mousex, double const Mousey ) {
auto const controlsize { Global.iWindowHeight * 0.75 };
auto const controlsize { Global.iWindowHeight * EU07_CONTROLLER_MOUSESLIDERSIZE };
auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 };
auto const stepsize { controlsize / m_valuerange };
auto mousey = clamp( Mousey, controledge - controlsize, controledge );
m_value = (
m_analogue ?
1.0 - ( ( controledge - mousey ) / controlsize ) :
( controledge - mousey ) / controlsize :
std::floor( ( controledge - mousey ) / stepsize ) );
if( m_invertrange ) {
m_value = ( m_analogue ? 1.0 : m_valuerange ) - m_value; }
}
@@ -370,6 +406,7 @@ drivermouse_input::button( int const Button, int const Action ) {
m_varyingpollrate = true;
break;
}
case user_command::jointcontrollerset:
case user_command::mastercontrollerset:
case user_command::secondcontrollerset:
case user_command::trainbrakeset:
@@ -445,6 +482,9 @@ void
drivermouse_input::default_bindings() {
m_buttonbindings = {
{ "jointctrl:", {
user_command::jointcontrollerset,
user_command::none } },
{ "mainctrl:", {
user_command::mastercontrollerset,
user_command::none } },
@@ -557,6 +597,9 @@ drivermouse_input::default_bindings() {
{ "doorrightpermit_sw:", {
user_command::doorpermitright,
user_command::none } },
{ "doorpermitpreset_sw:", {
user_command::doorpermitpresetactivatenext,
user_command::doorpermitpresetactivateprevious } },
{ "door_left_sw:", {
user_command::doortoggleleft,
user_command::none } },
@@ -581,6 +624,9 @@ drivermouse_input::default_bindings() {
{ "dooralloff_sw:", {
user_command::doorcloseall,
user_command::none } },
{ "doorstep_sw:", {
user_command::doorsteptoggle,
user_command::none } },
{ "departure_signal_bt:", {
user_command::departureannounce,
user_command::none } },

View File

@@ -39,6 +39,7 @@ private:
double m_value { 0.0 };
double m_valuerange { 0.0 };
bool m_analogue { false };
bool m_invertrange { false };
glm::dvec2 m_cursorposition { 0.0 };
};

View File

@@ -207,29 +207,45 @@ timetable_panel::update() {
auto textline = " -> " + nextstation;
text_lines.emplace_back( textline, Global.UITextColor );
text_lines.emplace_back( "", Global.UITextColor );
}
}
if( is_expanded ) {
text_lines.emplace_back( "", Global.UITextColor );
if( vehicle->MoverParameters->CategoryFlag == 1 ) {
// consist data
auto consistmass { owner->fMass };
auto consistlength { owner->fLength };
if( ( owner->mvControlling->TrainType != dt_DMU )
&& ( owner->mvControlling->TrainType != dt_EZT ) ) {
//odejmij lokomotywy czynne, a przynajmniej aktualną
consistmass -= owner->pVehicle->MoverParameters->TotalMass;
// subtract potential other half of a two-part vehicle
auto const *previous { owner->pVehicle->PrevC( coupling::permanent ) };
if( previous != nullptr ) { consistmass -= previous->MoverParameters->TotalMass; }
auto const *next { owner->pVehicle->NextC( coupling::permanent ) };
if( next != nullptr ) { consistmass -= next->MoverParameters->TotalMass; }
}
std::snprintf(
m_buffer.data(), m_buffer.size(),
locale::strings[ locale::string::driver_timetable_consistdata ].c_str(),
static_cast<int>( table->LocLoad ),
static_cast<int>( consistmass / 1000 ),
static_cast<int>( consistlength ) );
text_lines.emplace_back( m_buffer.data(), Global.UITextColor );
text_lines.emplace_back( "", Global.UITextColor );
}
if( 0 == table->StationCount ) {
// only bother if there's stations to list
text_lines.emplace_back( locale::strings[ locale::string::driver_timetable_notimetable ], Global.UITextColor );
}
else {
auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) };
text_lines.emplace_back("Brutto rozkl. " + to_string(table->LocLoad), Global.UITextColor);
auto fMass = owner->fMass / 1000;
if (owner->mvControlling->TrainType & (dt_DMU + dt_EZT) == 0)
{
//odejmij lokomotywy czynne, a przynajmniej aktualną
}
text_lines.emplace_back("Brutto rzecz. " + to_string(fMass,0), Global.UITextColor);
text_lines.emplace_back("Dl.poc. rzecz. " + to_string(owner->fLength,0), Global.UITextColor);
// header
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
@@ -545,10 +561,7 @@ debug_panel::update_vehicle_coupler( int const Side ) {
// NOTE: mover and vehicle are guaranteed to be valid by the caller
std::string couplerstatus { locale::strings[ locale::string::debug_vehicle_none ] };
auto const *connected { (
Side == end::front ?
m_input.vehicle->PrevConnected :
m_input.vehicle->NextConnected ) };
auto const *connected { m_input.vehicle->MoverParameters->Neighbours[ Side ].vehicle };
if( connected == nullptr ) { return couplerstatus; }
@@ -556,10 +569,10 @@ debug_panel::update_vehicle_coupler( int const Side ) {
std::snprintf(
m_buffer.data(), m_buffer.size(),
"%s [%d]%s",
"%s [%d] (%.1f m)",
connected->name().c_str(),
mover.Couplers[ Side ].CouplingFlag,
std::string( mover.Couplers[ Side ].CouplingFlag == 0 ? " (" + to_string( mover.Couplers[ Side ].CoupleDist, 1 ) + " m)" : "" ).c_str() );
mover.Neighbours[ Side ].distance );
return { m_buffer.data() };
}
@@ -682,6 +695,12 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
"Distances:\n proximity: " + to_string( mechanik.ActualProximityDist, 0 )
+ ", braking: " + to_string( mechanik.fBrakeDist, 0 );
if( mechanik.Obstacle.distance < 5000 ) {
textline +=
"\n obstacle: " + to_string( mechanik.Obstacle.distance, 0 )
+ " (" + mechanik.Obstacle.vehicle->asName + ")";
}
Output.emplace_back( textline, Global.UITextColor );
// velocity factors

View File

@@ -174,6 +174,7 @@ opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream
// try to set up the buffer we need
::glGenBuffers( 1, &m_buffer );
bind_buffer();
if( m_buffer == 0 ) { return; } // if we didn't get a buffer we'll try again during the next draw call
// NOTE: we're using static_draw since it's generally true for all we have implemented at the moment
// TODO: allow to specify usage hint at the object creation, and pass it here
::glBufferData(

View File

@@ -49,10 +49,12 @@ bounding_area::serialize( std::ostream &Output ) const {
// restores content of the struct from provided input stream
void
bounding_area::deserialize( std::istream &Input ) {
bounding_area::deserialize( std::istream &Input, bool const Preserveradius ) {
center = sn_utils::d_dvec3( Input );
radius = sn_utils::ld_float32( Input );
radius = ( Preserveradius ?
std::max( radius, sn_utils::ld_float32( Input ) ) :
sn_utils::ld_float32( Input ) );
}

View File

@@ -59,9 +59,9 @@ struct bounding_area {
// stores content of the struct in provided output stream
void
serialize( std::ostream &Output ) const;
// restores content of the struct from provided input stream
// restores content of the struct from provided input stream.
void
deserialize( std::istream &Input );
deserialize( std::istream &Input, bool const Preserveradius = true );
};
//using group_handle = std::size_t;

View File

@@ -59,7 +59,7 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
firststop ? 0 :
std::min<float>(
parameters.LoadAmount,
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) ) );
Random( parameters.MaxLoad * 0.15f * stationsizemodifier ) ) );
auto loadcount = static_cast<int>(
laststop ?
0 :

View File

@@ -41,6 +41,7 @@ init() {
"Timetable",
"Time: %d:%02d:%02d",
"(no timetable)",
"Consist weight: %d t (specified) %d t (actual)\nConsist length: %d m",
"Transcripts",
@@ -61,6 +62,7 @@ init() {
" pantograph: %.2f%cMT",
"Forces:\n tractive: %.1f, brake: %.1f, friction: %.2f%s\nAcceleration:\n tangential: %.2f, normal: %.2f (path radius: %s)\nVelocity: %.2f, distance traveled: %.2f\nPosition: [%.2f, %.2f, %.2f]",
"master controller",
"master controller",
"second controller",
"shunt mode power",
@@ -97,16 +99,18 @@ init() {
"motor overload relay reset",
"converter overload relay reset",
"motor connectors",
"left door (permit)",
"right door (permit)",
"door (permit)",
"left door",
"right door",
"left door",
"right door",
"left door",
"right door",
"left door",
"right door",
"all doors",
"all doors",
"left door (open)",
"right door (open)",
"left door (close)",
"right door (close)",
"all doors (open)",
"all doors (close)",
"doorstep",
"departure signal",
"upper headlight",
"left headlight",
@@ -182,6 +186,7 @@ init() {
"Rozklad jazdy",
"Godzina: %d:%02d:%02d",
"(brak rozkladu)",
"Brutto: %d t (rozkladowe) %d t (rzeczywiste)\nDlugosc pociagu: %d m",
"Transkrypcje",
@@ -202,6 +207,7 @@ init() {
" pantograf: %.2f%cZG",
"Sily:\n napedna: %.1f, hamowania: %.1f, tarcie: %.2f%s\nPrzyspieszenia:\n styczne: %.2f, normalne: %.2f (promien: %s)\nPredkosc: %.2f, pokonana odleglosc: %.2f\nPozycja: [%.2f, %.2f, %.2f]",
"nastawnik jazdy",
"nastawnik jazdy",
"nastawnik dodatkowy",
"sterowanie analogowe",
@@ -238,16 +244,18 @@ init() {
"przekaznik nadmiarowy silnikow trakcyjnych",
"przekaznik nadmiarowy przetwornicy",
"styczniki liniowe",
"drzwi lewe (zezwol)",
"drzwi prawe (zezwol)",
"drzwi (zezwol)",
"drzwi lewe",
"drzwi prawe",
"drzwi lewe",
"drzwi prawe",
"drzwi lewe",
"drzwi prawe",
"drzwi lewe",
"drzwi prawe",
"drzwi",
"drzwi",
"drzwi lewe (otworz)",
"drzwi prawe (otworz)",
"drzwi lewe (zamknij)",
"drzwi prawe (zamknij)",
"drzwi (otworz)",
"drzwi (zamknij)",
"stopien drzwi",
"sygnal odjazdu",
"reflektor gorny",
"reflektor lewy",
@@ -316,6 +324,7 @@ init() {
{
std::vector<std::string> cabcontrols = {
"mainctrl:",
"jointctrl:",
"scndctrl:",
"shuntmodepower:",
"dirkey:",
@@ -353,6 +362,7 @@ init() {
"stlinoff_bt:",
"doorleftpermit_sw:",
"doorrightpermit_sw:",
"doorpermitpreset_sw:",
"door_left_sw:",
"door_right_sw:",
"doorlefton_sw:",
@@ -361,6 +371,7 @@ init() {
"doorrightoff_sw:",
"doorallon_sw:",
"dooralloff_sw:",
"doorstep_sw:",
"departure_signal_bt:",
"upperlight_sw:",
"leftlight_sw:",

View File

@@ -30,6 +30,7 @@ enum string {
driver_timetable_header,
driver_timetable_time,
driver_timetable_notimetable,
driver_timetable_consistdata,
driver_transcripts_header,
@@ -51,6 +52,7 @@ enum string {
debug_vehicle_forcesaccelerationvelocityposition,
cab_mainctrl,
cab_jointctrl,
cab_scndctrl,
cab_shuntmodepower,
cab_dirkey,
@@ -88,6 +90,7 @@ enum string {
cab_stlinoff_bt,
cab_doorleftpermit_sw,
cab_doorrightpermit_sw,
cab_doorpermitpreset_sw,
cab_door_left_sw,
cab_door_right_sw,
cab_doorlefton_sw,
@@ -96,6 +99,7 @@ enum string {
cab_doorrightoff_sw,
cab_doorallon_sw,
cab_dooralloff_sw,
cab_doorstep_sw,
cab_departure_signal_bt,
cab_upperlight_sw,
cab_leftlight_sw,

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 19
#define VERSION_MINOR 129
#define VERSION_MINOR 227
#define VERSION_REVISION 0