track rendering optimization, application messaging routines moved to separate namespace

This commit is contained in:
tmj-fstate
2017-10-15 01:06:40 +02:00
parent 09dbb3c639
commit 630b9ecf1b
15 changed files with 860 additions and 673 deletions

View File

@@ -17,6 +17,7 @@ http://mozilla.org/MPL/2.0/.
#include "Ground.h"
#include "Globals.h"
#include "messaging.h"
#include "Logs.h"
#include "usefull.h"
#include "Timer.h"
@@ -610,10 +611,10 @@ TGround::DynamicList(bool all)
// powtarzać!)
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
if (all || Current->DynamicObject->Mechanik)
WyslijString(Current->asName, 6); // same nazwy pojazdów
WyslijString("none", 6); // informacja o końcu listy
multiplayer::WyslijString(Current->asName, 6); // same nazwy pojazdów
multiplayer::WyslijString("none", 6); // informacja o końcu listy
};
#ifdef EU07_USE_OLD_GROUNDCODE
// wyszukiwanie obiektu o podanej nazwie i konkretnym typie
TGroundNode *
TGround::FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType) {
@@ -632,7 +633,7 @@ TGround::FindGroundNode(std::string const &asNameToFind, TGroundNodeType const i
}
return nullptr;
}
#endif
TGroundRect *
TGround::GetRect( double x, double z ) {
@@ -3154,7 +3155,7 @@ bool TGround::CheckQuery()
// loc.Z= tmpEvent->Params[8].nGroundNode->pCenter.y;
if (Global::iMultiplayer) // potwierdzenie wykonania dla serwera (odczyt
// semafora już tak nie działa)
WyslijEvent(tmpEvent->asName, tmpEvent->Activator->name());
multiplayer::WyslijEvent(tmpEvent->asName, tmpEvent->Activator->name());
// tmpEvent->Params[9].asMemCell->PutCommand(tmpEvent->Activator->Mechanik,loc);
tmpEvent->Params[9].asMemCell->PutCommand(
tmpEvent->Activator->Mechanik, &tmpEvent->Params[8].nGroundNode->pCenter);
@@ -3244,7 +3245,7 @@ bool TGround::CheckQuery()
tmpEvent->Params[1].asdouble,
tmpEvent->Params[2].asdouble);
if (Global::iMultiplayer) // dajemy znać do serwera o przełożeniu
WyslijEvent(tmpEvent->asName, ""); // wysłanie nazwy eventu przełączajacego
multiplayer::WyslijEvent(tmpEvent->asName, ""); // wysłanie nazwy eventu przełączajacego
// Ra: bardziej by się przydała nazwa toru, ale nie ma do niej stąd dostępu
break;
case tp_TrackVel:
@@ -3287,9 +3288,9 @@ bool TGround::CheckQuery()
0) // jednoznaczne tylko, gdy nie było else
{
if (tmpEvent->Activator)
WyslijEvent(tmpEvent->asName, tmpEvent->Activator->name());
multiplayer::WyslijEvent(tmpEvent->asName, tmpEvent->Activator->name());
else
WyslijEvent(tmpEvent->asName, "");
multiplayer::WyslijEvent(tmpEvent->asName, "");
}
}
}
@@ -3755,214 +3756,6 @@ bool TGround::GetTraction(TDynamicObject *model)
return true;
};
#endif
#ifdef _WINDOWS
//---------------------------------------------------------------------------
void TGround::Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam)
{ // wysłanie komunikatu do sterującego
HWND h = FindWindow(ClassName.c_str(), 0); // można by to zapamiętać
if (h == 0)
h = FindWindow(0, ClassName.c_str()); // można by to zapamiętać
SendMessage(h, Msg, wParam, lParam);
};
//--------------------------------
void TGround::WyslijEvent(const std::string &e, const std::string &d)
{ // Ra: jeszcze do wyczyszczenia
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 2; // 2 - event
size_t i = e.length(), j = d.length();
r.cString[0] = char(i);
strcpy(r.cString + 1, e.c_str()); // zakończony zerem
r.cString[i + 2] = char(j); // licznik po zerze kończącym
strcpy(r.cString + 3 + i, d.c_str()); // zakończony zerem
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(12 + i + j); // 8+dwa liczniki i dwa zera kończące
cData.lpData = &r;
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
CommLog( Now() + " " + std::to_string(r.iComm) + " " + e + " sent" );
};
//---------------------------------------------------------------------------
void TGround::WyslijUszkodzenia(const std::string &t, char fl)
{ // wysłanie informacji w postaci pojedynczego tekstu
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 13; // numer komunikatu
size_t i = t.length();
r.cString[0] = char(fl);
r.cString[1] = char(i);
strcpy(r.cString + 2, t.c_str()); // z zerem kończącym
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(11 + i); // 8+licznik i zero kończące
cData.lpData = &r;
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
};
//---------------------------------------------------------------------------
void TGround::WyslijString(const std::string &t, int n)
{ // wysłanie informacji w postaci pojedynczego tekstu
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = n; // numer komunikatu
size_t i = t.length();
r.cString[0] = char(i);
strcpy(r.cString + 1, t.c_str()); // z zerem kończącym
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(10 + i); // 8+licznik i zero kończące
cData.lpData = &r;
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
};
//---------------------------------------------------------------------------
void TGround::WyslijWolny(const std::string &t)
{ // Ra: jeszcze do wyczyszczenia
WyslijString(t, 4); // tor wolny
};
//--------------------------------
void TGround::WyslijNamiary(TGroundNode *t)
{ // wysłanie informacji o pojeździe - (float), długość ramki będzie zwiększana w miarę potrzeby
// WriteLog("Wysylam pojazd");
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 7; // 7 - dane pojazdu
int i = 32;
size_t j = t->asName.length();
r.iPar[0] = i; // ilość danych liczbowych
r.fPar[1] = Global::fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
r.fPar[2] = t->DynamicObject->MoverParameters->Loc.X; // pozycja X
r.fPar[3] = t->DynamicObject->MoverParameters->Loc.Y; // pozycja Y
r.fPar[4] = t->DynamicObject->MoverParameters->Loc.Z; // pozycja Z
r.fPar[5] = t->DynamicObject->MoverParameters->V; // prędkość ruchu X
r.fPar[6] = t->DynamicObject->MoverParameters->nrot * M_PI *
t->DynamicObject->MoverParameters->WheelDiameter; // prędkość obrotowa kóŁ
r.fPar[7] = 0; // prędkość ruchu Z
r.fPar[8] = t->DynamicObject->MoverParameters->AccS; // przyspieszenie X
r.fPar[9] = t->DynamicObject->MoverParameters->AccN; // przyspieszenie Y //na razie nie
r.fPar[10] = t->DynamicObject->MoverParameters->AccV; // przyspieszenie Z
r.fPar[11] = t->DynamicObject->MoverParameters->DistCounter; // przejechana odległość w km
r.fPar[12] = t->DynamicObject->MoverParameters->PipePress; // ciśnienie w PG
r.fPar[13] = t->DynamicObject->MoverParameters->ScndPipePress; // ciśnienie w PZ
r.fPar[14] = t->DynamicObject->MoverParameters->BrakePress; // ciśnienie w CH
r.fPar[15] = t->DynamicObject->MoverParameters->Compressor; // ciśnienie w ZG
r.fPar[16] = t->DynamicObject->MoverParameters->Itot; // Prąd całkowity
r.iPar[17] = t->DynamicObject->MoverParameters->MainCtrlPos; // Pozycja NJ
r.iPar[18] = t->DynamicObject->MoverParameters->ScndCtrlPos; // Pozycja NB
r.iPar[19] = t->DynamicObject->MoverParameters->MainCtrlActualPos; // Pozycja jezdna
r.iPar[20] = t->DynamicObject->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[21] = t->DynamicObject->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[22] = t->DynamicObject->MoverParameters->ResistorsFlag * 1 +
t->DynamicObject->MoverParameters->ConverterFlag * 2 +
+t->DynamicObject->MoverParameters->CompressorFlag * 4 +
t->DynamicObject->MoverParameters->Mains * 8 +
+t->DynamicObject->MoverParameters->DoorLeftOpened * 16 +
t->DynamicObject->MoverParameters->DoorRightOpened * 32 +
+t->DynamicObject->MoverParameters->FuseFlag * 64 +
t->DynamicObject->MoverParameters->DepartureSignal * 128;
// WriteLog("Zapisalem stare");
// WriteLog("Mam patykow "+IntToStr(t->DynamicObject->iAnimType[ANIM_PANTS]));
for (int p = 0; p < 4; p++)
{
// WriteLog("Probuje pant "+IntToStr(p));
if (p < t->DynamicObject->iAnimType[ANIM_PANTS])
{
r.fPar[23 + p] = t->DynamicObject->pants[p].fParamPants->PantWys; // stan pantografów 4
// WriteLog("Zapisalem pant "+IntToStr(p));
}
else
{
r.fPar[23 + p] = -2;
// WriteLog("Nie mam pant "+IntToStr(p));
}
}
// WriteLog("Zapisalem pantografy");
for (int p = 0; p < 3; p++)
r.fPar[27 + p] =
t->DynamicObject->MoverParameters->ShowCurrent(p + 1); // amperomierze kolejnych grup
// WriteLog("zapisalem prady");
r.iPar[30] = t->DynamicObject->MoverParameters->WarningSignal; // trabienie
r.fPar[31] = t->DynamicObject->MoverParameters->RunningTraction.TractionVoltage; // napiecie WN
// WriteLog("Parametry gotowe");
i <<= 2; // ilość bajtów
r.cString[i] = char(j); // na końcu nazwa, żeby jakoś zidentyfikować
strcpy(r.cString + i + 1, t->asName.c_str()); // zakończony zerem
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(10 + i + j); // 8+licznik i zero kończące
cData.lpData = &r;
// WriteLog("Ramka gotowa");
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
// WriteLog("Ramka poszla!");
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t->asName + " sent");
};
//
void TGround::WyslijObsadzone()
{ // wysłanie informacji o pojeździe
DaneRozkaz2 r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 12; // kod 12
for (int i=0; i<1984; ++i) r.cString[i] = 0;
int i = 0;
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
if (Current->DynamicObject->Mechanik)
{
strcpy(r.cString + 64 * i, Current->DynamicObject->asName.c_str());
r.fPar[16 * i + 4] = Current->DynamicObject->GetPosition().x;
r.fPar[16 * i + 5] = Current->DynamicObject->GetPosition().y;
r.fPar[16 * i + 6] = Current->DynamicObject->GetPosition().z;
r.iPar[16 * i + 7] = Current->DynamicObject->Mechanik->GetAction();
strcpy(r.cString + 64 * i + 32, Current->DynamicObject->GetTrack()->IsolatedName().c_str());
strcpy(r.cString + 64 * i + 48, Current->DynamicObject->Mechanik->Timetable()->TrainName.c_str());
i++;
if (i>30) break;
}
while (i <= 30)
{
strcpy(r.cString + 64 * i, "none");
r.fPar[16 * i + 4] = 1;
r.fPar[16 * i + 5] = 2;
r.fPar[16 * i + 6] = 3;
r.iPar[16 * i + 7] = 0;
strcpy(r.cString + 64 * i + 32, "none");
strcpy(r.cString + 64 * i + 48, "none");
i++;
}
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = 8 + 1984; // 8+licznik i zero kończące
cData.lpData = &r;
// WriteLog("Ramka gotowa");
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
CommLog( Now() + " " + std::to_string(r.iComm) + " obsadzone" + " sent");
}
//--------------------------------
void TGround::WyslijParam(int nr, int fl)
{ // wysłanie parametrów symulacji w ramce (nr) z flagami (fl)
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = nr; // zwykle 5
r.iPar[0] = fl; // flagi istotności kolejnych parametrów
int i = 0; // domyślnie brak danych
switch (nr)
{ // można tym przesyłać różne zestawy parametrów
case 5: // czas i pauza
r.fPar[1] = Global::fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
r.iPar[2] = Global::iPause; // stan zapauzowania
i = 8; // dwa parametry po 4 bajty każdy
break;
}
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = 12 + i; // 12+rozmiar danych
cData.lpData = &r;
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
};
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
@@ -4165,7 +3958,7 @@ void TGround::TrackBusyList()
for (Current = nRootOfType[TP_TRACK]; Current; Current = Current->nNext)
if (!Current->asName.empty()) // musi być nazwa
if( false == Current->pTrack->Dynamics.empty() )
WyslijString(Current->asName, 8); // zajęty
multiplayer::WyslijString(Current->asName, 8); // zajęty
};
//---------------------------------------------------------------------------
@@ -4174,10 +3967,10 @@ void TGround::IsolatedBusyList()
TIsolated *Current;
for (Current = TIsolated::Root(); Current; Current = Current->Next())
if (Current->Busy()) // sprawdź zajętość
WyslijString(Current->asName, 11); // zajęty
multiplayer::WyslijString(Current->asName, 11); // zajęty
else
WyslijString(Current->asName, 10); // wolny
WyslijString("none", 10); // informacja o końcu listy
multiplayer::WyslijString(Current->asName, 10); // wolny
multiplayer::WyslijString("none", 10); // informacja o końcu listy
};
//---------------------------------------------------------------------------
@@ -4189,10 +3982,10 @@ void TGround::IsolatedBusy(const std::string t)
if (Current->asName == t) // wyszukiwanie odcinka o nazwie (t)
if (Current->Busy()) // sprawdź zajetość
{
WyslijString(Current->asName, 11); // zajęty
multiplayer::WyslijString(Current->asName, 11); // zajęty
return; // nie sprawdzaj dalszych
}
WyslijString(t, 10); // wolny
multiplayer::WyslijString(t, 10); // wolny
};
//---------------------------------------------------------------------------

View File

@@ -42,30 +42,6 @@ const int TP_ISOLATED=22; //Ra
const int TP_SUBMODEL = 22; // Ra: submodele terenu
const int TP_LAST = 25; // rozmiar tablicy
struct DaneRozkaz
{ // struktura komunikacji z EU07.EXE
int iSygn; // sygnatura 'EU07'
int iComm; // rozkaz/status (kod ramki)
union
{
float fPar[62];
int iPar[62];
char cString[248]; // upakowane stringi
};
};
struct DaneRozkaz2
{ // struktura komunikacji z EU07.EXE
int iSygn; // sygnatura 'EU07'
int iComm; // rozkaz/status (kod ramki)
union
{
float fPar[496];
int iPar[496];
char cString[1984]; // upakowane stringi
};
};
struct TGroundVertex
{
glm::dvec3 position;
@@ -259,9 +235,8 @@ class TGround
*tmpEvent = nullptr;
typedef std::unordered_map<std::string, TEvent *> event_map;
event_map m_eventmap;
#endif
TNames<TGroundNode *> m_nodemap;
#endif
vector3 pOrigin;
vector3 aRotate;
bool bInitDone = false;
@@ -300,7 +275,9 @@ class TGround
TGroundNode * DynamicFind(std::string const &Name);
#endif
void DynamicList(bool all = false);
#ifdef EU07_USE_OLD_GROUNDCODE
TGroundNode * FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType);
#endif
TGroundRect * GetRect( double x, double z );
TSubRect * GetSubRect( int iCol, int iRow );
inline
@@ -321,32 +298,25 @@ class TGround
#endif
void TrackJoin(TGroundNode *Current);
private:
private:
// convert tp_terrain model to a series of triangle nodes
void convert_terrain( TGroundNode const *Terrain );
void convert_terrain( TSubModel const *Submodel );
#ifdef EU07_USE_OLD_GROUNDCODE
void RaTriangleDivider(TGroundNode *node);
#endif
void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam);
#endif
public:
void TrackBusyList();
void IsolatedBusyList();
void IsolatedBusy( const std::string t );
public:
void WyslijEvent(const std::string &e, const std::string &d);
void WyslijString(const std::string &t, int n);
void WyslijWolny(const std::string &t);
void WyslijNamiary(TGroundNode *t);
void WyslijParam(int nr, int fl);
void WyslijUszkodzenia(const std::string &t, char fl);
void WyslijObsadzone(); // -> skladanie wielu pojazdow
void RadioStop(vector3 pPosition);
TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0, bool mech = false);
TDynamicObject * CouplerNearest(vector3 pPosition, double distance = 20.0, bool mech = false);
void DynamicRemove(TDynamicObject *dyn);
void TerrainRead(std::string const &f);
void TerrainWrite();
void TrackBusyList();
void IsolatedBusyList();
void IsolatedBusy(const std::string t);
void Silence(vector3 gdzie);
};

View File

@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
#include <unordered_map>
#include <string>
#ifdef EU07_USE_OLD_GROUNDCODE
template <typename Type_>
class TNames {
@@ -65,6 +66,7 @@ private:
// members:
typemap_map m_maps; // list of object maps of types specified so far
};
#endif
template <typename Type_>
class basic_table {

View File

@@ -118,7 +118,7 @@ void TIsolated::Modify(int i, TDynamicObject *o)
if (evFree)
Global::AddToQuery(evFree, o); // dodanie zwolnienia do kolejki
if (Global::iMultiplayer) // jeśli multiplayer
Global::pGround->WyslijString(asName, 10); // wysłanie pakietu o zwolnieniu
multiplayer::WyslijString(asName, 10); // wysłanie pakietu o zwolnieniu
if (pMemCell) // w powiązanej komórce
pMemCell->UpdateValues( "", 0, int( pMemCell->Value2() ) & ~0xFF,
update_memval2 ); //"zerujemy" ostatnią wartość
@@ -132,7 +132,7 @@ void TIsolated::Modify(int i, TDynamicObject *o)
if (evBusy)
Global::AddToQuery(evBusy, o); // dodanie zajętości do kolejki
if (Global::iMultiplayer) // jeśli multiplayer
Global::pGround->WyslijString(asName, 11); // wysłanie pakietu o zajęciu
multiplayer::WyslijString(asName, 11); // wysłanie pakietu o zajęciu
if (pMemCell) // w powiązanej komórce
pMemCell->UpdateValues( "", 0, int( pMemCell->Value2() ) | 1, update_memval2 ); // zmieniamy ostatnią wartość na nieparzystą
}
@@ -178,6 +178,13 @@ void TTrack::Init()
}
}
bool
TTrack::sort_by_material( TTrack const *Left, TTrack const *Right ) {
return ( ( Left->m_material1 < Right->m_material1 )
&& ( Left->m_material2 < Right->m_material2 ) );
}
TTrack * TTrack::Create400m(int what, double dx)
{ // tworzenie toru do wstawiania taboru podczas konwersji na E3D
TGroundNode *tmp = new TGroundNode(TP_TRACK); // node
@@ -932,7 +939,7 @@ bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
// pierwszy zajmujący
if( m_name != "none" ) {
// przekazanie informacji o zajętości toru
Global::pGround->WyslijString( m_name, 8 );
multiplayer::WyslijString( m_name, 8 );
}
}
}
@@ -1024,7 +1031,7 @@ bool TTrack::RemoveDynamicObject(TDynamicObject *Dynamic)
// jeśli już nie ma żadnego
if( m_name != "none" ) {
// przekazanie informacji o zwolnieniu toru
Global::pGround->WyslijString( m_name, 9 );
multiplayer::WyslijString( m_name, 9 );
}
}
}
@@ -2158,7 +2165,6 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
void TTrack::EnvironmentSet()
{ // ustawienie zmienionego światła
glColor3f(1.0f, 1.0f, 1.0f); // Ra: potrzebne to?
switch( eEnvironment ) {
case e_canyon: {
Global::DayLight.apply_intensity( 0.4f );

View File

@@ -186,6 +186,7 @@ public:
virtual ~TTrack();
void Init();
static bool sort_by_material( TTrack const *Left, TTrack const *Right );
static TTrack * Create400m(int what, double dx);
TTrack * NullCreate(int dir);
inline bool IsEmpty() {

View File

@@ -23,7 +23,6 @@ http://mozilla.org/MPL/2.0/.
#include "Timer.h"
#include "mtable.h"
#include "Sound.h"
#include "Camera.h"
#include "ResourceManager.h"
#include "Event.h"
#include "Train.h"
@@ -1079,7 +1078,7 @@ bool TWorld::Update() {
// awaria PoKeys mogła włączyć pauzę - przekazać informację
if( Global::iMultiplayer ) // dajemy znać do serwera o wykonaniu
if( iPause != Global::iPause ) { // przesłanie informacji o pauzie do programu nadzorującego
Ground.WyslijParam( 5, 3 ); // ramka 5 z czasem i stanem zapauzowania
multiplayer::WyslijParam( 5, 3 ); // ramka 5 z czasem i stanem zapauzowania
iPause = Global::iPause;
}
@@ -1890,25 +1889,24 @@ TWorld::Update_UI() {
}
//---------------------------------------------------------------------------
void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
{ // odebranie komunikatu z serwera
if (pRozkaz->iSygn == MAKE_ID4('E','U','0','7') )
switch (pRozkaz->iComm)
{
case 0: // odesłanie identyfikatora wersji
CommLog( Now() + " " + std::to_string(pRozkaz->iComm) + " version" + " rcvd");
Ground.WyslijString(Global::asVersion, 0); // przedsatwienie się
multiplayer::WyslijString(Global::asVersion, 0); // przedsatwienie się
break;
case 1: // odesłanie identyfikatora wersji
CommLog( Now() + " " + std::to_string(pRozkaz->iComm) + " scenery" + " rcvd");
Ground.WyslijString(Global::SceneryFile, 1); // nazwa scenerii
multiplayer::WyslijString(Global::SceneryFile, 1); // nazwa scenerii
break;
case 2: {
// event
CommLog( Now() + " " + std::to_string( pRozkaz->iComm ) + " " +
std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) + " rcvd" );
/*
// TODO: re-enable when messaging module is in place
#ifdef EU07_USE_OLD_GROUNDCODE
if( Global::iMultiplayer ) {
// WriteLog("Komunikat: "+AnsiString(pRozkaz->Name1));
TEvent *e = Ground.FindEvent(
@@ -1918,7 +1916,20 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
( e->evJoined != 0 ) ) // tylko jawne albo niejawne Multiple
Ground.AddToQuery( e, NULL ); // drugi parametr to dynamic wywołujący - tu brak
}
*/
#else
if( Global::iMultiplayer ) {
// WriteLog("Komunikat: "+AnsiString(pRozkaz->Name1));
auto *event = simulation::Events.FindEvent( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
if( event != nullptr ) {
if( ( event->Type == tp_Multiple )
|| ( event->Type == tp_Lights )
|| ( event->evJoined != 0 ) ) {
// tylko jawne albo niejawne Multiple
simulation::Events.AddToQuery( event, nullptr ); // drugi parametr to dynamic wywołujący - tu brak
}
}
}
#endif
break;
}
case 3: // rozkaz dla AI
@@ -1961,17 +1972,23 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
{
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) + " rcvd");
TGroundNode *t = Ground.FindGroundNode(
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])), TP_TRACK);
#ifdef EU07_USE_OLD_GROUNDCODE
TGroundNode *t = Ground.FindGroundNode( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ), TP_TRACK );
if (t)
if (t->pTrack->IsEmpty())
Ground.WyslijWolny(t->asName);
multiplayer::WyslijWolny(t->asName);
#else
auto *track = simulation::Paths.find( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
if( ( track != nullptr )
&& ( track->IsEmpty() ) ) {
multiplayer::WyslijWolny( track->name() );
}
#endif
}
break;
case 5: // ustawienie parametrów
{
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " params " +
to_string(*pRozkaz->iPar) + " rcvd");
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " params " + to_string(*pRozkaz->iPar) + " rcvd");
if (*pRozkaz->iPar == 0) // sprawdzenie czasu
if (*pRozkaz->iPar & 1) // ustawienie czasu
{
@@ -1990,13 +2007,15 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
}
break;
case 6: // pobranie parametrów ruchu pojazdu
if (Global::iMultiplayer)
{ // Ra 2014-12: to ma działać również dla pojazdów bez obsady
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) +
" rcvd");
if (pRozkaz->cString[0]) // jeśli długość nazwy jest niezerowa
{ // szukamy pierwszego pojazdu o takiej nazwie i odsyłamy parametry ramką #7
if (Global::iMultiplayer) {
// Ra 2014-12: to ma działać również dla pojazdów bez obsady
CommLog(
Now() + " "
+ to_string( pRozkaz->iComm ) + " "
+ std::string{ pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) }
+ " rcvd" );
if (pRozkaz->cString[0]) {
// jeśli długość nazwy jest niezerowa szukamy pierwszego pojazdu o takiej nazwie i odsyłamy parametry ramką #7
#ifdef EU07_USE_OLD_GROUNDCODE
TGroundNode *t;
if (pRozkaz->cString[1] == '*')
@@ -2006,14 +2025,22 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
t = Ground.DynamicFindAny(std::string(
pRozkaz->cString + 1, (unsigned)pRozkaz->cString[0])); // nazwa pojazdu
if (t)
Ground.WyslijNamiary(t); // wysłanie informacji o pojeździe
multiplayer::WyslijNamiary(t); // wysłanie informacji o pojeździe
#else
// TODO: implement
/*
// TODO: re-enable when messaging component is in place
auto *vehicle = (
pRozkaz->cString[ 1 ] == '*' ?
simulation::Vehicles.find( Global::asHumanCtrlVehicle ) :
simulation::Vehicles.find( std::string{ pRozkaz->cString + 1, (unsigned)pRozkaz->cString[ 0 ] } ) );
if( vehicle != nullptr ) {
multiplayer::WyslijNamiary( vehicle ); // wysłanie informacji o pojeździe
}
*/
#endif
}
else
{ // dla pustego wysyłamy ramki 6 z nazwami pojazdów AI (jeśli potrzebne wszystkie,
// to rozpoznać np. "*")
else {
// dla pustego wysyłamy ramki 6 z nazwami pojazdów AI (jeśli potrzebne wszystkie, to rozpoznać np. "*")
Ground.DynamicList();
}
}
@@ -2036,12 +2063,10 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
break;
case 12: // skrocona ramka parametrow pojazdow AI (wszystkich!!)
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " obsadzone" + " rcvd");
Ground.WyslijObsadzone();
multiplayer::WyslijObsadzone();
// Ground.IsolatedBusy(AnsiString(pRozkaz->cString+1,(unsigned)(pRozkaz->cString[0])));
break;
case 13: // ramka uszkodzenia i innych stanow pojazdu, np. wylaczenie CA, wlaczenie recznego itd.
// WriteLog("Przyszlo 13!");
// WriteLog(pRozkaz->cString);
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) +
" rcvd");
@@ -2067,7 +2092,7 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
d->Damage( pRozkaz->cString[ 0 ] );
d = d->Prev(); // w drugą stronę też
}
Ground.WyslijUszkodzenia( t->asName, t->DynamicObject->MoverParameters->EngDmgFlag ); // zwrot informacji o pojeździe
multiplayer::WyslijUszkodzenia( t->asName, t->DynamicObject->MoverParameters->EngDmgFlag ); // zwrot informacji o pojeździe
}
}
#else

View File

@@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/.
#include <GLFW/glfw3.h>
#include <string>
#include "Camera.h"
#include "Ground.h"
#include "scene.h"
@@ -20,6 +21,7 @@ http://mozilla.org/MPL/2.0/.
#include "stars.h"
#include "skydome.h"
#include "mczapkie/mover.h"
#include "messaging.h"
// wrapper for simulation time
class simulation_time {
@@ -104,7 +106,7 @@ TWorld();
void OnKeyDown(int cKey);
// void UpdateWindow();
void OnMouseMove(double x, double y);
void OnCommandGet(DaneRozkaz *pRozkaz);
void OnCommandGet(multiplayer::DaneRozkaz *pRozkaz);
bool Update();
void TrainDelete(TDynamicObject *d = NULL);
TTrain const *

View File

@@ -240,6 +240,9 @@
<ClCompile Include="vertex.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="messaging.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Globals.h">
@@ -470,6 +473,9 @@
<ClInclude Include="simulation.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="messaging.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="maszyna.rc">

245
messaging.cpp Normal file
View File

@@ -0,0 +1,245 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "messaging.h"
#include "globals.h"
#include "simulation.h"
#include "ground.h"
#include "mtable.h"
#include "logs.h"
extern "C"
{
GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); //m7todo: potrzebne do directsound
}
namespace multiplayer {
#ifdef _WINDOWS
void
Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam) {
// wysłanie komunikatu do sterującego
HWND h = FindWindow(ClassName.c_str(), 0); // można by to zapamiętać
if (h == 0)
h = FindWindow(0, ClassName.c_str()); // można by to zapamiętać
SendMessage(h, Msg, wParam, lParam);
}
void
WyslijEvent(const std::string &e, const std::string &d)
{ // Ra: jeszcze do wyczyszczenia
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 2; // 2 - event
size_t i = e.length(), j = d.length();
r.cString[0] = char(i);
strcpy(r.cString + 1, e.c_str()); // zakończony zerem
r.cString[i + 2] = char(j); // licznik po zerze kończącym
strcpy(r.cString + 3 + i, d.c_str()); // zakończony zerem
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(12 + i + j); // 8+dwa liczniki i dwa zera kończące
cData.lpData = &r;
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
CommLog( Now() + " " + std::to_string(r.iComm) + " " + e + " sent" );
}
void
WyslijUszkodzenia(const std::string &t, char fl)
{ // wysłanie informacji w postaci pojedynczego tekstu
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 13; // numer komunikatu
size_t i = t.length();
r.cString[0] = char(fl);
r.cString[1] = char(i);
strcpy(r.cString + 2, t.c_str()); // z zerem kończącym
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(11 + i); // 8+licznik i zero kończące
cData.lpData = &r;
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
}
void
WyslijString(const std::string &t, int n)
{ // wysłanie informacji w postaci pojedynczego tekstu
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = n; // numer komunikatu
size_t i = t.length();
r.cString[0] = char(i);
strcpy(r.cString + 1, t.c_str()); // z zerem kończącym
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(10 + i); // 8+licznik i zero kończące
cData.lpData = &r;
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
}
void
WyslijWolny(const std::string &t)
{ // Ra: jeszcze do wyczyszczenia
WyslijString(t, 4); // tor wolny
}
void
WyslijNamiary(TGroundNode *t)
{ // wysłanie informacji o pojeździe - (float), długość ramki będzie zwiększana w miarę potrzeby
// WriteLog("Wysylam pojazd");
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 7; // 7 - dane pojazdu
int i = 32;
size_t j = t->asName.length();
r.iPar[0] = i; // ilość danych liczbowych
r.fPar[1] = Global::fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
r.fPar[2] = t->DynamicObject->MoverParameters->Loc.X; // pozycja X
r.fPar[3] = t->DynamicObject->MoverParameters->Loc.Y; // pozycja Y
r.fPar[4] = t->DynamicObject->MoverParameters->Loc.Z; // pozycja Z
r.fPar[5] = t->DynamicObject->MoverParameters->V; // prędkość ruchu X
r.fPar[6] = t->DynamicObject->MoverParameters->nrot * M_PI *
t->DynamicObject->MoverParameters->WheelDiameter; // prędkość obrotowa kóŁ
r.fPar[7] = 0; // prędkość ruchu Z
r.fPar[8] = t->DynamicObject->MoverParameters->AccS; // przyspieszenie X
r.fPar[9] = t->DynamicObject->MoverParameters->AccN; // przyspieszenie Y //na razie nie
r.fPar[10] = t->DynamicObject->MoverParameters->AccV; // przyspieszenie Z
r.fPar[11] = t->DynamicObject->MoverParameters->DistCounter; // przejechana odległość w km
r.fPar[12] = t->DynamicObject->MoverParameters->PipePress; // ciśnienie w PG
r.fPar[13] = t->DynamicObject->MoverParameters->ScndPipePress; // ciśnienie w PZ
r.fPar[14] = t->DynamicObject->MoverParameters->BrakePress; // ciśnienie w CH
r.fPar[15] = t->DynamicObject->MoverParameters->Compressor; // ciśnienie w ZG
r.fPar[16] = t->DynamicObject->MoverParameters->Itot; // Prąd całkowity
r.iPar[17] = t->DynamicObject->MoverParameters->MainCtrlPos; // Pozycja NJ
r.iPar[18] = t->DynamicObject->MoverParameters->ScndCtrlPos; // Pozycja NB
r.iPar[19] = t->DynamicObject->MoverParameters->MainCtrlActualPos; // Pozycja jezdna
r.iPar[20] = t->DynamicObject->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[21] = t->DynamicObject->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[22] = t->DynamicObject->MoverParameters->ResistorsFlag * 1 +
t->DynamicObject->MoverParameters->ConverterFlag * 2 +
+t->DynamicObject->MoverParameters->CompressorFlag * 4 +
t->DynamicObject->MoverParameters->Mains * 8 +
+t->DynamicObject->MoverParameters->DoorLeftOpened * 16 +
t->DynamicObject->MoverParameters->DoorRightOpened * 32 +
+t->DynamicObject->MoverParameters->FuseFlag * 64 +
t->DynamicObject->MoverParameters->DepartureSignal * 128;
// WriteLog("Zapisalem stare");
// WriteLog("Mam patykow "+IntToStr(t->DynamicObject->iAnimType[ANIM_PANTS]));
for (int p = 0; p < 4; p++)
{
// WriteLog("Probuje pant "+IntToStr(p));
if (p < t->DynamicObject->iAnimType[ANIM_PANTS])
{
r.fPar[23 + p] = t->DynamicObject->pants[p].fParamPants->PantWys; // stan pantografów 4
// WriteLog("Zapisalem pant "+IntToStr(p));
}
else
{
r.fPar[23 + p] = -2;
// WriteLog("Nie mam pant "+IntToStr(p));
}
}
// WriteLog("Zapisalem pantografy");
for (int p = 0; p < 3; p++)
r.fPar[27 + p] =
t->DynamicObject->MoverParameters->ShowCurrent(p + 1); // amperomierze kolejnych grup
// WriteLog("zapisalem prady");
r.iPar[30] = t->DynamicObject->MoverParameters->WarningSignal; // trabienie
r.fPar[31] = t->DynamicObject->MoverParameters->RunningTraction.TractionVoltage; // napiecie WN
// WriteLog("Parametry gotowe");
i <<= 2; // ilość bajtów
r.cString[i] = char(j); // na końcu nazwa, żeby jakoś zidentyfikować
strcpy(r.cString + i + 1, t->asName.c_str()); // zakończony zerem
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(10 + i + j); // 8+licznik i zero kończące
cData.lpData = &r;
// WriteLog("Ramka gotowa");
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
// WriteLog("Ramka poszla!");
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t->asName + " sent");
}
void
WyslijObsadzone()
{ // wysłanie informacji o pojeździe
DaneRozkaz2 r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 12; // kod 12
for (int i=0; i<1984; ++i) r.cString[i] = 0;
// TODO: clean this up, we shouldn't be relying on direct list access
auto &vehiclelist = simulation::Vehicles.sequence();
int i = 0;
for( auto *vehicle : vehiclelist ) {
if( vehicle->Mechanik ) {
strcpy( r.cString + 64 * i, vehicle->asName.c_str() );
r.fPar[ 16 * i + 4 ] = vehicle->GetPosition().x;
r.fPar[ 16 * i + 5 ] = vehicle->GetPosition().y;
r.fPar[ 16 * i + 6 ] = vehicle->GetPosition().z;
r.iPar[ 16 * i + 7 ] = vehicle->Mechanik->GetAction();
strcpy( r.cString + 64 * i + 32, vehicle->GetTrack()->IsolatedName().c_str() );
strcpy( r.cString + 64 * i + 48, vehicle->Mechanik->Timetable()->TrainName.c_str() );
i++;
if( i > 30 ) break;
}
}
while (i <= 30)
{
strcpy(r.cString + 64 * i, "none");
r.fPar[16 * i + 4] = 1;
r.fPar[16 * i + 5] = 2;
r.fPar[16 * i + 6] = 3;
r.iPar[16 * i + 7] = 0;
strcpy(r.cString + 64 * i + 32, "none");
strcpy(r.cString + 64 * i + 48, "none");
i++;
}
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = 8 + 1984; // 8+licznik i zero kończące
cData.lpData = &r;
// WriteLog("Ramka gotowa");
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
CommLog( Now() + " " + std::to_string(r.iComm) + " obsadzone" + " sent");
}
void
WyslijParam(int nr, int fl)
{ // wysłanie parametrów symulacji w ramce (nr) z flagami (fl)
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = nr; // zwykle 5
r.iPar[0] = fl; // flagi istotności kolejnych parametrów
int i = 0; // domyślnie brak danych
switch (nr)
{ // można tym przesyłać różne zestawy parametrów
case 5: // czas i pauza
r.fPar[1] = Global::fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
r.iPar[2] = Global::iPause; // stan zapauzowania
i = 8; // dwa parametry po 4 bajty każdy
break;
}
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = 12 + i; // 12+rozmiar danych
cData.lpData = &r;
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
}
#endif
} // multiplayer
//---------------------------------------------------------------------------

50
messaging.h Normal file
View File

@@ -0,0 +1,50 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <string>
class TGroundNode;
namespace multiplayer {
struct DaneRozkaz { // struktura komunikacji z EU07.EXE
int iSygn; // sygnatura 'EU07'
int iComm; // rozkaz/status (kod ramki)
union {
float fPar[ 62 ];
int iPar[ 62 ];
char cString[ 248 ]; // upakowane stringi
};
};
struct DaneRozkaz2 { // struktura komunikacji z EU07.EXE
int iSygn; // sygnatura 'EU07'
int iComm; // rozkaz/status (kod ramki)
union {
float fPar[ 496 ];
int iPar[ 496 ];
char cString[ 1984 ]; // upakowane stringi
};
};
void Navigate( std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam );
void WyslijEvent( const std::string &e, const std::string &d );
void WyslijString( const std::string &t, int n );
void WyslijWolny( const std::string &t );
void WyslijNamiary( TGroundNode *t );
void WyslijParam( int nr, int fl );
void WyslijUszkodzenia( const std::string &t, char fl );
void WyslijObsadzone(); // -> skladanie wielu pojazdow
} // multiplayer
//---------------------------------------------------------------------------

View File

@@ -1598,6 +1598,212 @@ opengl_renderer::Render( TSubRect *Groundsubcell ) {
return true;
}
bool
opengl_renderer::Render( TGroundNode *Node ) {
double distancesquared;
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
default: {
distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
}
if( ( distancesquared < Node->fSquareMinRadius )
|| ( distancesquared >= Node->fSquareRadius ) ) {
return false;
}
switch (Node->iType) {
case TP_TRACK: {
// setup
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
return false;
}
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
Render( Node->pTrack );
// debug
++m_debugstats.paths;
++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
return true;
}
case TP_MODEL: {
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
Node->Model->RaAnimate( m_framestamp ); // jednorazowe przeliczenie animacji
Node->Model->RaPrepare();
if( Node->Model->pModel ) {
// renderowanie rekurencyjne submodeli
Render(
Node->Model->pModel,
Node->Model->Material(),
distancesquared,
Node->pCenter - m_renderpass.camera.position(),
Node->Model->vAngle );
}
return true;
}
case GL_LINES: {
if( ( Node->Piece->geometry == null_handle )
|| ( Node->fLineThickness > 0.0 ) ) {
return false;
}
// setup
auto const distance = std::sqrt( distancesquared );
auto const linealpha =
10.0 * Node->fLineThickness
/ std::max(
0.5 * Node->m_radius + 1.0,
distance - ( 0.5 * Node->m_radius ) );
switch( m_renderpass.draw_mode ) {
// wire colouring is disabled for modes other than colour
case rendermode::color: {
::glColor4fv(
glm::value_ptr(
glm::vec4(
Node->Diffuse * glm::vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
1.0 ) ) ); // if the thickness is defined negative, lines are always drawn opaque
break;
}
case rendermode::shadows:
case rendermode::pickcontrols:
case rendermode::pickscenery:
default: {
break;
}
}
auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 8.0 );
if( linewidth > 1.0 ) {
::glLineWidth( static_cast<float>( linewidth ) );
}
GfxRenderer.Bind_Material( null_handle );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
// render
m_geometry.draw( Node->Piece->geometry );
// debug
// ++m_debugstats.lines;
// ++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
if( linewidth > 1.0 ) { ::glLineWidth( 1.0f ); }
return true;
}
case GL_TRIANGLES: {
if( ( Node->Piece->geometry == null_handle )
|| ( ( Node->iFlags & 0x10 ) == 0 ) ) {
return false;
}
// setup
Bind_Material( Node->m_material );
switch( m_renderpass.draw_mode ) {
case rendermode::color: {
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
break;
}
// pick modes get custom colours, and shadow pass doesn't use any
case rendermode::shadows:
case rendermode::pickcontrols:
case rendermode::pickscenery:
default: {
break;
}
}
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
// render
m_geometry.draw( Node->Piece->geometry );
// debug
++m_debugstats.shapes;
++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
return true;
}
case TP_MEMCELL: {
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
Render( Node->MemCell );
return true;
}
default: { break; }
}
// in theory we shouldn't ever get here but, eh
return false;
}
#else
void
opengl_renderer::Render( scene::basic_region *Region ) {
@@ -1848,7 +2054,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
for( auto const &shape : cell->m_shapesopaque ) { Render( shape, false ); }
// tracks
// TODO: update after path node refactoring
for( auto *path : cell->m_paths ) { Render( path ); }
Render( std::begin( cell->m_paths ), std::end( cell->m_paths ) );
// TODO: add other content types
// post-render cleanup
@@ -1880,10 +2086,14 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
// opaque non-instanced shapes
::glColor3fv( glm::value_ptr( colors::none ) );
for( auto const &shape : cell->m_shapesopaque ) { Render( shape, false ); }
// tracks
// TODO: add path to the node picking list
for( auto *path : cell->m_paths ) { Render( path ); }
for( auto *path : cell->m_paths ) {
::glColor3fv( glm::value_ptr( pick_color( m_picksceneryitems.size() + 1 ) ) );
Render( path );
}
// TODO: add other content types
// post-render cleanup
::glPopMatrix();
@@ -2053,212 +2263,6 @@ opengl_renderer::Render( TAnimModel *Instance ) {
}
#endif
bool
opengl_renderer::Render( TGroundNode *Node ) {
double distancesquared;
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
default: {
distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
}
if( ( distancesquared < Node->fSquareMinRadius )
|| ( distancesquared >= Node->fSquareRadius ) ) {
return false;
}
switch (Node->iType) {
case TP_TRACK: {
// setup
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
return false;
}
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
Render( Node->pTrack );
// debug
++m_debugstats.paths;
++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
return true;
}
case TP_MODEL: {
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
Node->Model->RaAnimate( m_framestamp ); // jednorazowe przeliczenie animacji
Node->Model->RaPrepare();
if( Node->Model->pModel ) {
// renderowanie rekurencyjne submodeli
Render(
Node->Model->pModel,
Node->Model->Material(),
distancesquared,
Node->pCenter - m_renderpass.camera.position(),
Node->Model->vAngle );
}
return true;
}
case GL_LINES: {
if( ( Node->Piece->geometry == null_handle )
|| ( Node->fLineThickness > 0.0 ) ) {
return false;
}
// setup
auto const distance = std::sqrt( distancesquared );
auto const linealpha =
10.0 * Node->fLineThickness
/ std::max(
0.5 * Node->m_radius + 1.0,
distance - ( 0.5 * Node->m_radius ) );
switch( m_renderpass.draw_mode ) {
// wire colouring is disabled for modes other than colour
case rendermode::color: {
::glColor4fv(
glm::value_ptr(
glm::vec4(
Node->Diffuse * glm::vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
1.0 ) ) ); // if the thickness is defined negative, lines are always drawn opaque
break;
}
case rendermode::shadows:
case rendermode::pickcontrols:
case rendermode::pickscenery:
default: {
break;
}
}
auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 8.0 );
if( linewidth > 1.0 ) {
::glLineWidth( static_cast<float>( linewidth ) );
}
GfxRenderer.Bind_Material( null_handle );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
// render
m_geometry.draw( Node->Piece->geometry );
// debug
// ++m_debugstats.lines;
// ++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
if( linewidth > 1.0 ) { ::glLineWidth( 1.0f ); }
return true;
}
case GL_TRIANGLES: {
if( ( Node->Piece->geometry == null_handle )
|| ( ( Node->iFlags & 0x10 ) == 0 ) ) {
return false;
}
// setup
Bind_Material( Node->m_material );
switch( m_renderpass.draw_mode ) {
case rendermode::color: {
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
break;
}
// pick modes get custom colours, and shadow pass doesn't use any
case rendermode::shadows:
case rendermode::pickcontrols:
case rendermode::pickscenery:
default: {
break;
}
}
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
// render
m_geometry.draw( Node->Piece->geometry );
// debug
++m_debugstats.shapes;
++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
return true;
}
case TP_MEMCELL: {
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// add the node to the pick list
m_picksceneryitems.emplace_back( Node );
break;
}
default: {
break;
}
}
Render( Node->MemCell );
return true;
}
default: { break; }
}
// in theory we shouldn't ever get here but, eh
return false;
}
bool
opengl_renderer::Render( TDynamicObject *Dynamic ) {
@@ -2794,6 +2798,83 @@ opengl_renderer::Render( TTrack *Track ) {
}
}
// experimental, does track rendering in two passes, to take advantage of reduced texture switching
void
opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last ) {
::glColor3fv( glm::value_ptr( colors::white ) );
// first pass, material 1
for( auto first { First }; first != Last; ++first ) {
auto const track { *first };
if( track->m_material1 == 0 ) {
continue;
}
if( false == track->m_visible ) {
continue;
}
++m_debugstats.paths;
++m_debugstats.drawcalls;
switch( m_renderpass.draw_mode ) {
case rendermode::color:
case rendermode::reflections: {
track->EnvironmentSet();
Bind_Material( track->m_material1 );
m_geometry.draw( std::begin( track->Geometry1 ), std::end( track->Geometry1 ) );
track->EnvironmentReset();
break;
}
case rendermode::shadows: {
Bind_Material( track->m_material1 );
m_geometry.draw( std::begin( track->Geometry1 ), std::end( track->Geometry1 ) );
break;
}
case rendermode::pickscenery: // pick scenery should use track-by-track approach
case rendermode::pickcontrols:
default: {
break;
}
}
}
// second pass, material 2
for( auto first { First }; first != Last; ++first ) {
auto const track { *first };
if( track->m_material2 == 0 ) {
continue;
}
if( false == track->m_visible ) {
continue;
}
switch( m_renderpass.draw_mode ) {
case rendermode::color:
case rendermode::reflections: {
track->EnvironmentSet();
Bind_Material( track->m_material2 );
m_geometry.draw( std::begin( track->Geometry2 ), std::end( track->Geometry2 ) );
track->EnvironmentReset();
break;
}
case rendermode::shadows: {
Bind_Material( track->m_material2 );
m_geometry.draw( std::begin( track->Geometry2 ), std::end( track->Geometry2 ) );
break;
}
case rendermode::pickscenery: // pick scenery should use track-by-track approach
case rendermode::pickcontrols:
default: {
break;
}
}
}
}
void
opengl_renderer::Render( TMemCell *Memcell ) {
@@ -2879,6 +2960,162 @@ opengl_renderer::Render_Alpha( TSubRect *Groundsubcell ) {
return true;
}
bool
opengl_renderer::Render_Alpha( TGroundNode *Node ) {
double distancesquared;
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
default: {
distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
}
if( ( distancesquared < Node->fSquareMinRadius )
|| ( distancesquared >= Node->fSquareRadius ) ) {
return false;
}
switch (Node->iType)
{
case TP_TRACTION: {
if( Node->bVisible ) {
// rysuj jesli sa druty i nie zerwana
if( ( Node->hvTraction->Wires == 0 )
|| ( true == TestFlag( Node->hvTraction->DamageFlag, 128 ) ) ) {
return false;
}
// setup
if( !Global::bSmoothTraction ) {
// na liniach kiepsko wygląda - robi gradient
::glDisable( GL_LINE_SMOOTH );
}
float const linealpha = static_cast<float>(
std::min(
1.25,
5000 * Node->hvTraction->WireThickness / ( distancesquared + 1.0 ) ) ); // zbyt grube nie są dobre
::glLineWidth( linealpha );
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
auto const color { Node->hvTraction->wire_color() };
::glColor4f( color.r, color.g, color.b, linealpha );
Bind_Material( null_handle );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
m_geometry.draw( Node->hvTraction->m_geometry );
// debug data
++m_debugstats.traction;
++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
::glLineWidth( 1.0 );
if( !Global::bSmoothTraction ) {
::glEnable( GL_LINE_SMOOTH );
}
return true;
}
else {
return false;
}
}
case TP_MODEL: {
Node->Model->RaPrepare();
if( Node->Model->pModel ) {
// renderowanie rekurencyjne submodeli
Render_Alpha(
Node->Model->pModel,
Node->Model->Material(),
distancesquared,
Node->pCenter - m_renderpass.camera.position(),
Node->Model->vAngle );
}
return true;
}
case GL_LINES: {
if( ( Node->Piece->geometry == null_handle )
|| ( Node->fLineThickness < 0.0 ) ) {
return false;
}
// setup
auto const distance = std::sqrt( distancesquared );
auto const linealpha =
10.0 * Node->fLineThickness
/ std::max(
0.5 * Node->m_radius + 1.0,
distance - ( 0.5 * Node->m_radius ) );
::glColor4fv(
glm::value_ptr(
glm::vec4(
Node->Diffuse * glm::vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
std::min( 1.0, linealpha ) ) ) );
auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 8.0 );
if( linewidth > 1.0 ) {
::glLineWidth( static_cast<float>(linewidth) );
}
GfxRenderer.Bind_Material( null_handle );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
m_geometry.draw( Node->Piece->geometry );
// ++m_debugstats.lines;
// ++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
if( linewidth > 1.0 ) { ::glLineWidth( 1.0f ); }
return true;
}
case GL_TRIANGLES: {
if( ( Node->Piece->geometry == null_handle )
|| ( ( Node->iFlags & 0x20 ) == 0 ) ) {
return false;
}
// setup
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
Bind_Material( Node->m_material );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
m_geometry.draw( Node->Piece->geometry );
// debug data
++m_debugstats.shapes;
++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
return true;
}
default: { break; }
}
// in theory we shouldn't ever get here but, eh
return false;
}
#else
void
opengl_renderer::Render_Alpha( scene::basic_region *Region ) {
@@ -3051,162 +3288,6 @@ opengl_renderer::Render_Alpha( TTraction *Traction ) {
++m_debugstats.drawcalls;
}
#endif
bool
opengl_renderer::Render_Alpha( TGroundNode *Node ) {
double distancesquared;
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
default: {
distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
}
if( ( distancesquared < Node->fSquareMinRadius )
|| ( distancesquared >= Node->fSquareRadius ) ) {
return false;
}
switch (Node->iType)
{
case TP_TRACTION: {
if( Node->bVisible ) {
// rysuj jesli sa druty i nie zerwana
if( ( Node->hvTraction->Wires == 0 )
|| ( true == TestFlag( Node->hvTraction->DamageFlag, 128 ) ) ) {
return false;
}
// setup
if( !Global::bSmoothTraction ) {
// na liniach kiepsko wygląda - robi gradient
::glDisable( GL_LINE_SMOOTH );
}
float const linealpha = static_cast<float>(
std::min(
1.25,
5000 * Node->hvTraction->WireThickness / ( distancesquared + 1.0 ) ) ); // zbyt grube nie są dobre
::glLineWidth( linealpha );
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
auto const color { Node->hvTraction->wire_color() };
::glColor4f( color.r, color.g, color.b, linealpha );
Bind_Material( null_handle );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
m_geometry.draw( Node->hvTraction->m_geometry );
// debug data
++m_debugstats.traction;
++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
::glLineWidth( 1.0 );
if( !Global::bSmoothTraction ) {
::glEnable( GL_LINE_SMOOTH );
}
return true;
}
else {
return false;
}
}
case TP_MODEL: {
Node->Model->RaPrepare();
if( Node->Model->pModel ) {
// renderowanie rekurencyjne submodeli
Render_Alpha(
Node->Model->pModel,
Node->Model->Material(),
distancesquared,
Node->pCenter - m_renderpass.camera.position(),
Node->Model->vAngle );
}
return true;
}
case GL_LINES: {
if( ( Node->Piece->geometry == null_handle )
|| ( Node->fLineThickness < 0.0 ) ) {
return false;
}
// setup
auto const distance = std::sqrt( distancesquared );
auto const linealpha =
10.0 * Node->fLineThickness
/ std::max(
0.5 * Node->m_radius + 1.0,
distance - ( 0.5 * Node->m_radius ) );
::glColor4fv(
glm::value_ptr(
glm::vec4(
Node->Diffuse * glm::vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
std::min( 1.0, linealpha ) ) ) );
auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 8.0 );
if( linewidth > 1.0 ) {
::glLineWidth( static_cast<float>(linewidth) );
}
GfxRenderer.Bind_Material( null_handle );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
m_geometry.draw( Node->Piece->geometry );
// ++m_debugstats.lines;
// ++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
if( linewidth > 1.0 ) { ::glLineWidth( 1.0f ); }
return true;
}
case GL_TRIANGLES: {
if( ( Node->Piece->geometry == null_handle )
|| ( ( Node->iFlags & 0x20 ) == 0 ) ) {
return false;
}
// setup
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
Bind_Material( Node->m_material );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
m_geometry.draw( Node->Piece->geometry );
// debug data
++m_debugstats.shapes;
++m_debugstats.drawcalls;
// post-render cleanup
::glPopMatrix();
return true;
}
default: { break; }
}
// in theory we shouldn't ever get here but, eh
return false;
}
bool
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {

View File

@@ -294,6 +294,8 @@ private:
Render( TGroundRect *Groundcell );
bool
Render( TSubRect *Groundsubcell );
bool
Render( TGroundNode *Node );
#else
void
Render( scene::basic_region *Region );
@@ -306,8 +308,6 @@ private:
void
Render( TAnimModel *Instance );
#endif
bool
Render( TGroundNode *Node );
bool
Render( TDynamicObject *Dynamic );
bool
@@ -318,6 +318,8 @@ private:
Render( TSubModel *Submodel );
void
Render( TTrack *Track );
void
Render( scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last );
bool
Render_cab( TDynamicObject *Dynamic, bool const Alpha = false );
void
@@ -327,6 +329,8 @@ private:
Render_Alpha( TGround *Ground );
bool
Render_Alpha( TSubRect *Groundsubcell );
bool
Render_Alpha( TGroundNode *Node );
#else
void
Render_Alpha( scene::basic_region *Region );
@@ -337,8 +341,6 @@ private:
void
Render_Alpha( TTraction *Traction );
#endif
bool
Render_Alpha( TGroundNode *Node );
bool
Render_Alpha( TDynamicObject *Dynamic );
bool

View File

@@ -372,6 +372,10 @@ basic_cell::create_geometry( geometrybank_handle const &Bank ) {
for( auto *path : m_paths ) { path->create_geometry( Bank ); }
for( auto *traction : m_traction ) { traction->create_geometry( Bank ); }
#endif
// arrange content by assigned materials to minimize state switching
std::sort(
std::begin( m_paths ), std::end( m_paths ),
TTrack::sort_by_material );
}

View File

@@ -685,7 +685,7 @@ state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratch
Input.getToken<std::string>() );
auto const offset { Input.getToken<double>( false ) };
auto const drivertype { Input.getToken<std::string>() };
auto const couplingparams = (
auto const couplingdata = (
Scratchpad.trainset.is_open ?
Input.getToken<std::string>() :
"3" );
@@ -694,11 +694,11 @@ state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratch
Scratchpad.trainset.velocity :
Input.getToken<float>( false ) );
// extract coupling type and optional parameters
auto const couplingparamsplit = couplingparams.find( '.' );
auto const couplingdatawithparams = couplingdata.find( '.' );
auto coupling = (
couplingparamsplit != std::string::npos ?
std::atoi( couplingparams.substr( 0, couplingparamsplit ).c_str() ) :
std::atoi( couplingparams.c_str() ) );
couplingdatawithparams != std::string::npos ?
std::atoi( couplingdata.substr( 0, couplingdatawithparams ).c_str() ) :
std::atoi( couplingdata.c_str() ) );
if( coupling < 0 ) {
// sprzęg zablokowany (pojazdy nierozłączalne przy manewrach)
coupling = ( -coupling ) | coupling::permanent;
@@ -706,11 +706,11 @@ state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratch
if( ( offset != -1.0 )
&& ( std::abs( offset ) > 0.5 ) ) { // maksymalna odległość między sprzęgami - do przemyślenia
// likwidacja sprzęgu, jeśli odległość zbyt duża - to powinno być uwzględniane w fizyce sprzęgów...
coupling = 0;
coupling = coupling::faux;
}
auto const params = (
couplingparamsplit != std::string::npos ?
couplingparams.substr( couplingparamsplit + 1 ) :
couplingdatawithparams != std::string::npos ?
couplingdata.substr( couplingdatawithparams + 1 ) :
"" );
// load amount and type
auto loadcount { Input.getToken<int>( false ) };

View File

@@ -63,7 +63,7 @@ LRESULT APIENTRY WndProc( HWND hWnd, // handle for this window
// obsługa danych przesłanych przez program sterujący
pDane = (PCOPYDATASTRUCT)lParam;
if( pDane->dwData == MAKE_ID4('E', 'U', '0', '7')) // sygnatura danych
World.OnCommandGet( (DaneRozkaz *)( pDane->lpData ) );
World.OnCommandGet( ( multiplayer::DaneRozkaz *)( pDane->lpData ) );
break;
}
}