mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 18:39:18 +02:00
basic scenery data export in legacy text format
This commit is contained in:
112
AnimModel.cpp
112
AnimModel.cpp
@@ -423,13 +423,6 @@ TAnimModel::~TAnimModel()
|
|||||||
SafeDelete(pRoot);
|
SafeDelete(pRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TAnimModel::Init(TModel3d *pNewModel)
|
|
||||||
{
|
|
||||||
fBlinkTimer = double(Random(1000 * fOffTime)) / (1000 * fOffTime);
|
|
||||||
pModel = pNewModel;
|
|
||||||
return (pModel != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TAnimModel::Init(std::string const &asName, std::string const &asReplacableTexture)
|
bool TAnimModel::Init(std::string const &asName, std::string const &asReplacableTexture)
|
||||||
{
|
{
|
||||||
if( asReplacableTexture.substr( 0, 1 ) == "*" ) {
|
if( asReplacableTexture.substr( 0, 1 ) == "*" ) {
|
||||||
@@ -445,17 +438,21 @@ bool TAnimModel::Init(std::string const &asName, std::string const &asReplacable
|
|||||||
m_materialdata.textures_alpha = 0x31310031;
|
m_materialdata.textures_alpha = 0x31310031;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// tekstura nieprzezroczysta - nie renderować w cyklu
|
// tekstura nieprzezroczysta - nie renderować w cyklu przezroczystych
|
||||||
m_materialdata.textures_alpha = 0x30300030;
|
m_materialdata.textures_alpha = 0x30300030;
|
||||||
}
|
}
|
||||||
// przezroczystych
|
|
||||||
return (Init(TModelsManager::GetModel(asName)));
|
fBlinkTimer = double( Random( 1000 * fOffTime ) ) / ( 1000 * fOffTime );
|
||||||
|
|
||||||
|
pModel = TModelsManager::GetModel( asName );
|
||||||
|
return ( pModel != nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TAnimModel::Load(cParser *parser, bool ter)
|
bool TAnimModel::Load(cParser *parser, bool ter)
|
||||||
{ // rozpoznanie wpisu modelu i ustawienie świateł
|
{ // rozpoznanie wpisu modelu i ustawienie świateł
|
||||||
std::string name = parser->getToken<std::string>();
|
std::string name = parser->getToken<std::string>();
|
||||||
std::string texture = parser->getToken<std::string>(false); // tekstura (zmienia na małe)
|
std::string texture = parser->getToken<std::string>(); // tekstura (zmienia na małe)
|
||||||
|
replace_slashes( name );
|
||||||
if (!Init( name, texture ))
|
if (!Init( name, texture ))
|
||||||
{
|
{
|
||||||
if (name != "notload")
|
if (name != "notload")
|
||||||
@@ -504,7 +501,7 @@ bool TAnimModel::Load(cParser *parser, bool ter)
|
|||||||
while( ( token != "" )
|
while( ( token != "" )
|
||||||
&& ( token != "endmodel" ) ) {
|
&& ( token != "endmodel" ) ) {
|
||||||
|
|
||||||
LightSet( i, std::stod( token ) ); // stan światła jest liczbą z ułamkiem
|
LightSet( i, std::stof( token ) ); // stan światła jest liczbą z ułamkiem
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
token = "";
|
token = "";
|
||||||
@@ -563,15 +560,6 @@ void TAnimModel::RaAnimate( unsigned int const Framestamp ) {
|
|||||||
m_framestamp = Framestamp;
|
m_framestamp = Framestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
// calculates piece's bounding radius
|
|
||||||
void
|
|
||||||
TAnimModel::radius_() {
|
|
||||||
|
|
||||||
if( pModel != nullptr ) {
|
|
||||||
m_area.radius = pModel->bounding_radius();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TAnimModel::RaPrepare()
|
void TAnimModel::RaPrepare()
|
||||||
{ // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
|
{ // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
|
||||||
bool state; // stan światła
|
bool state; // stan światła
|
||||||
@@ -584,7 +572,11 @@ void TAnimModel::RaPrepare()
|
|||||||
state = ( fBlinkTimer < fOnTime );
|
state = ( fBlinkTimer < fOnTime );
|
||||||
break;
|
break;
|
||||||
case ls_Dark: // zapalone, gdy ciemno
|
case ls_Dark: // zapalone, gdy ciemno
|
||||||
state = ( Global.fLuminance <= ( lsLights[i] - 3.0 ) );
|
state = (
|
||||||
|
Global.fLuminance <= (
|
||||||
|
lsLights[i] == 3.f ?
|
||||||
|
DefaultDarkThresholdLevel :
|
||||||
|
( lsLights[i] - 3.f ) ) );
|
||||||
break;
|
break;
|
||||||
default: // zapalony albo zgaszony
|
default: // zapalony albo zgaszony
|
||||||
state = (lightmode == ls_On);
|
state = (lightmode == ls_On);
|
||||||
@@ -780,15 +772,17 @@ void TAnimModel::LightSet(int const n, float const v)
|
|||||||
}
|
}
|
||||||
case ls_Dark: {
|
case ls_Dark: {
|
||||||
// zapalenie świateł zależne od oświetlenia scenerii
|
// zapalenie świateł zależne od oświetlenia scenerii
|
||||||
if( v == 3.0 ) {
|
/*
|
||||||
|
if( v == 3.f ) {
|
||||||
// standardowy próg zaplania
|
// standardowy próg zaplania
|
||||||
lsLights[ n ] = 3.0 + DefaultDarkThresholdLevel;
|
lsLights[ n ] = 3.f + DefaultDarkThresholdLevel;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void TAnimModel::AnimUpdate(double dt)
|
void TAnimModel::AnimUpdate(double dt)
|
||||||
{ // wykonanie zakolejkowanych animacji, nawet gdy modele nie są aktualnie wyświetlane
|
{ // wykonanie zakolejkowanych animacji, nawet gdy modele nie są aktualnie wyświetlane
|
||||||
TAnimContainer *p = TAnimModel::acAnimList;
|
TAnimContainer *p = TAnimModel::acAnimList;
|
||||||
@@ -798,4 +792,72 @@ void TAnimModel::AnimUpdate(double dt)
|
|||||||
p = p->acAnimNext; // na razie bez usuwania z listy, bo głównie obrotnica na nią wchodzi
|
p = p->acAnimNext; // na razie bez usuwania z listy, bo głównie obrotnica na nią wchodzi
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// radius() subclass details, calculates node's bounding radius
|
||||||
|
float
|
||||||
|
TAnimModel::radius_() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
pModel ?
|
||||||
|
pModel->bounding_radius() :
|
||||||
|
0.f );
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void
|
||||||
|
TAnimModel::serialize_( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void
|
||||||
|
TAnimModel::deserialize_( std::istream &Input ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
TAnimModel::export_as_text_( std::ostream &Output ) const {
|
||||||
|
// header
|
||||||
|
Output << "model ";
|
||||||
|
// location and rotation
|
||||||
|
Output
|
||||||
|
<< location().x << ' '
|
||||||
|
<< location().y << ' '
|
||||||
|
<< location().z << ' '
|
||||||
|
<< vAngle.y << ' ';
|
||||||
|
// 3d shape
|
||||||
|
auto modelfile { (
|
||||||
|
pModel ?
|
||||||
|
pModel->NameGet() + ".t3d" : // rainsted requires model file names to include an extension
|
||||||
|
"none" ) };
|
||||||
|
if( modelfile.find( szModelPath ) == 0 ) {
|
||||||
|
// don't include 'models/' in the path
|
||||||
|
modelfile.erase( 0, std::string{ szModelPath }.size() );
|
||||||
|
}
|
||||||
|
Output << modelfile << ' ';
|
||||||
|
// texture
|
||||||
|
auto texturefile { (
|
||||||
|
m_materialdata.replacable_skins[ 1 ] != null_handle ?
|
||||||
|
GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).name :
|
||||||
|
"none" ) };
|
||||||
|
if( texturefile.find( szTexturePath ) == 0 ) {
|
||||||
|
// don't include 'textures/' in the path
|
||||||
|
texturefile.erase( 0, std::string{ szTexturePath }.size() );
|
||||||
|
}
|
||||||
|
Output << texturefile << ' ';
|
||||||
|
// light submodels activation configuration
|
||||||
|
if( iNumLights > 0 ) {
|
||||||
|
Output << "lights ";
|
||||||
|
for( int lightidx = 0; lightidx < iNumLights; ++lightidx ) {
|
||||||
|
Output << lsLights[ lightidx ] << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// footer
|
||||||
|
Output
|
||||||
|
<< "endmodel"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
21
AnimModel.h
21
AnimModel.h
@@ -122,7 +122,7 @@ class TAnimAdvanced
|
|||||||
};
|
};
|
||||||
|
|
||||||
// opakowanie modelu, określające stan egzemplarza
|
// opakowanie modelu, określające stan egzemplarza
|
||||||
class TAnimModel : public editor::basic_node {
|
class TAnimModel : public scene::basic_node {
|
||||||
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
|
|
||||||
@@ -133,15 +133,12 @@ public:
|
|||||||
~TAnimModel();
|
~TAnimModel();
|
||||||
// methods
|
// methods
|
||||||
static void AnimUpdate( double dt );
|
static void AnimUpdate( double dt );
|
||||||
bool Init(TModel3d *pNewModel);
|
|
||||||
bool Init(std::string const &asName, std::string const &asReplacableTexture);
|
bool Init(std::string const &asName, std::string const &asReplacableTexture);
|
||||||
bool Load(cParser *parser, bool ter = false);
|
bool Load(cParser *parser, bool ter = false);
|
||||||
TAnimContainer * AddContainer(std::string const &Name);
|
TAnimContainer * AddContainer(std::string const &Name);
|
||||||
TAnimContainer * GetContainer(std::string const &Name = "");
|
TAnimContainer * GetContainer(std::string const &Name = "");
|
||||||
void RaAnglesSet( glm::vec3 Angles ) {
|
void RaAnglesSet( glm::vec3 Angles ) {
|
||||||
vAngle.x = Angles.x;
|
vAngle = { Angles }; };
|
||||||
vAngle.y = Angles.y;
|
|
||||||
vAngle.z = Angles.z; };
|
|
||||||
void LightSet( int const n, float const v );
|
void LightSet( int const n, float const v );
|
||||||
void AnimationVND( void *pData, double a, double b, double c, double d );
|
void AnimationVND( void *pData, double a, double b, double c, double d );
|
||||||
bool TerrainLoaded();
|
bool TerrainLoaded();
|
||||||
@@ -159,16 +156,20 @@ public:
|
|||||||
// members
|
// members
|
||||||
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
|
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
|
||||||
|
|
||||||
protected:
|
|
||||||
// calculates piece's bounding radius
|
|
||||||
void
|
|
||||||
radius_();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// methods
|
// methods
|
||||||
void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu
|
void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu
|
||||||
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji egzemplarza
|
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji egzemplarza
|
||||||
void Advanced();
|
void Advanced();
|
||||||
|
// radius() subclass details, calculates node's bounding radius
|
||||||
|
float radius_();
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void serialize_( std::ostream &Output ) const;
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void deserialize_( std::istream &Input );
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void export_as_text_( std::ostream &Output ) const;
|
||||||
|
|
||||||
// members
|
// members
|
||||||
TAnimContainer *pRoot { nullptr }; // pojemniki sterujące, tylko dla aniomowanych submodeli
|
TAnimContainer *pRoot { nullptr }; // pojemniki sterujące, tylko dla aniomowanych submodeli
|
||||||
TModel3d *pModel { nullptr };
|
TModel3d *pModel { nullptr };
|
||||||
|
|||||||
85
EvLaunch.cpp
85
EvLaunch.cpp
@@ -194,11 +194,90 @@ bool TEventLauncher::IsGlobal() const {
|
|||||||
&& ( dRadius < 0.0 ) ); // bez ograniczenia zasięgu
|
&& ( dRadius < 0.0 ) ); // bez ograniczenia zasięgu
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculates node's bounding radius
|
// radius() subclass details, calculates node's bounding radius
|
||||||
void
|
float
|
||||||
TEventLauncher::radius_() {
|
TEventLauncher::radius_() {
|
||||||
|
|
||||||
m_area.radius = std::sqrt( dRadius );
|
return std::sqrt( dRadius );
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void
|
||||||
|
TEventLauncher::serialize_( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void
|
||||||
|
TEventLauncher::deserialize_( std::istream &Input ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
TEventLauncher::export_as_text_( std::ostream &Output ) const {
|
||||||
|
// header
|
||||||
|
Output << "eventlauncher ";
|
||||||
|
// location
|
||||||
|
Output
|
||||||
|
<< location().x << ' '
|
||||||
|
<< location().y << ' '
|
||||||
|
<< location().z << ' ';
|
||||||
|
// activation radius
|
||||||
|
Output
|
||||||
|
<< ( dRadius > 0 ? std::sqrt( dRadius ) : dRadius ) << ' ';
|
||||||
|
// activation key
|
||||||
|
if( iKey != 0 ) {
|
||||||
|
auto const key { iKey & 0xff };
|
||||||
|
auto const modifier { ( iKey & 0xff00 ) >> 8 };
|
||||||
|
if( ( key >= GLFW_KEY_A ) && ( key <= GLFW_KEY_Z ) ) {
|
||||||
|
Output << static_cast<char>(( 'A' + key - GLFW_KEY_A + ( ( modifier & 1 ) == 0 ? 32 : 0 ) )) << ' ';
|
||||||
|
}
|
||||||
|
else if( ( key >= GLFW_KEY_0 ) && ( key <= GLFW_KEY_9 ) ) {
|
||||||
|
Output << static_cast<char>(( '0' + key - GLFW_KEY_0 )) << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Output << "none ";
|
||||||
|
}
|
||||||
|
// activation interval or hour
|
||||||
|
if( DeltaTime != 0 ) {
|
||||||
|
// cyclical launcher
|
||||||
|
Output << -DeltaTime << ' ';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// single activation at specified time
|
||||||
|
if( ( iHour < 0 )
|
||||||
|
&& ( iMinute < 0 ) ) {
|
||||||
|
Output << DeltaTime << ' ';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// NOTE: activation hour might be affected by user-requested time offset
|
||||||
|
auto const timeoffset{ static_cast<int>( Global.ScenarioTimeOffset * 60 ) };
|
||||||
|
auto const adjustedtime{ clamp_circular( iHour * 60 + iMinute - timeoffset, 24 * 60 ) };
|
||||||
|
Output
|
||||||
|
<< ( adjustedtime / 60 ) % 24
|
||||||
|
<< ( adjustedtime % 60 )
|
||||||
|
<< ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// associated event(s)
|
||||||
|
Output << ( asEvent1Name.empty() ? "none" : asEvent1Name ) << ' ';
|
||||||
|
Output << ( asEvent2Name.empty() ? "none" : asEvent2Name ) << ' ';
|
||||||
|
if( false == asMemCellName.empty() ) {
|
||||||
|
// conditional event
|
||||||
|
Output
|
||||||
|
<< "condition "
|
||||||
|
<< asMemCellName << ' '
|
||||||
|
<< szText << ' '
|
||||||
|
<< ( ( iCheckMask & conditional_memval1 ) != 0 ? to_string( fVal1 ) : "*" ) << ' '
|
||||||
|
<< ( ( iCheckMask & conditional_memval2 ) != 0 ? to_string( fVal2 ) : "*" ) << ' ';
|
||||||
|
}
|
||||||
|
// footer
|
||||||
|
Output
|
||||||
|
<< "end"
|
||||||
|
<< "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
17
EvLaunch.h
17
EvLaunch.h
@@ -14,7 +14,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Classes.h"
|
#include "Classes.h"
|
||||||
#include "scenenode.h"
|
#include "scenenode.h"
|
||||||
|
|
||||||
class TEventLauncher : public editor::basic_node {
|
class TEventLauncher : public scene::basic_node {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
@@ -37,12 +37,17 @@ public:
|
|||||||
int iCheckMask { 0 };
|
int iCheckMask { 0 };
|
||||||
double dRadius { 0.0 };
|
double dRadius { 0.0 };
|
||||||
|
|
||||||
protected:
|
|
||||||
// calculates node's bounding radius
|
|
||||||
void
|
|
||||||
radius_();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// methods
|
||||||
|
// radius() subclass details, calculates node's bounding radius
|
||||||
|
float radius_();
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void serialize_( std::ostream &Output ) const;
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void deserialize_( std::istream &Input );
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void export_as_text_( std::ostream &Output ) const;
|
||||||
|
|
||||||
// members
|
// members
|
||||||
int iKey { 0 };
|
int iKey { 0 };
|
||||||
double DeltaTime { -1.0 };
|
double DeltaTime { -1.0 };
|
||||||
|
|||||||
244
Event.cpp
244
Event.cpp
@@ -304,9 +304,9 @@ void TEvent::Load(cParser *parser, Math3D::vector3 const &org)
|
|||||||
if (token.find('#') != std::string::npos)
|
if (token.find('#') != std::string::npos)
|
||||||
token.erase(token.find('#')); // obcięcie unikatowości
|
token.erase(token.find('#')); // obcięcie unikatowości
|
||||||
win1250_to_ascii( token ); // get rid of non-ascii chars
|
win1250_to_ascii( token ); // get rid of non-ascii chars
|
||||||
bEnabled = false; // nie do kolejki (dla SetVelocity też, ale jak jest do toru
|
|
||||||
// dowiązany)
|
|
||||||
Params[6].asCommand = cm_PassengerStopPoint;
|
Params[6].asCommand = cm_PassengerStopPoint;
|
||||||
|
// nie do kolejki (dla SetVelocity też, ale jak jest do toru dowiązany)
|
||||||
|
bEnabled = false;
|
||||||
}
|
}
|
||||||
else if (token == "SetVelocity")
|
else if (token == "SetVelocity")
|
||||||
{
|
{
|
||||||
@@ -328,11 +328,6 @@ void TEvent::Load(cParser *parser, Math3D::vector3 const &org)
|
|||||||
bEnabled = false;
|
bEnabled = false;
|
||||||
Params[6].asCommand = cm_ShuntVelocity;
|
Params[6].asCommand = cm_ShuntVelocity;
|
||||||
}
|
}
|
||||||
//else if (str == "SetProximityVelocity")
|
|
||||||
//{
|
|
||||||
// bEnabled = false;
|
|
||||||
// Params[6].asCommand = cm_SetProximityVelocity;
|
|
||||||
//}
|
|
||||||
else if (token == "OutsideStation")
|
else if (token == "OutsideStation")
|
||||||
{
|
{
|
||||||
bEnabled = false; // ma być skanowny, aby AI nie przekraczało W5
|
bEnabled = false; // ma być skanowny, aby AI nie przekraczało W5
|
||||||
@@ -391,6 +386,11 @@ void TEvent::Load(cParser *parser, Math3D::vector3 const &org)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while( token.compare( "endevent" ) != 0 );
|
} while( token.compare( "endevent" ) != 0 );
|
||||||
|
while( paramidx < 8 ) {
|
||||||
|
// HACK: mark unspecified lights with magic value
|
||||||
|
Params[ paramidx ].asdouble = -2.0;
|
||||||
|
++paramidx;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Visible: // zmiana wyświetlania obiektu
|
case tp_Visible: // zmiana wyświetlania obiektu
|
||||||
@@ -403,7 +403,7 @@ void TEvent::Load(cParser *parser, Math3D::vector3 const &org)
|
|||||||
case tp_Velocity:
|
case tp_Velocity:
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
Params[0].asdouble = atof(token.c_str()) * 0.28;
|
Params[0].asdouble = atof(token.c_str()) * ( 1000.0 / 3600.0 );
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
break;
|
break;
|
||||||
@@ -420,7 +420,6 @@ void TEvent::Load(cParser *parser, Math3D::vector3 const &org)
|
|||||||
*parser >> token;
|
*parser >> token;
|
||||||
break;
|
break;
|
||||||
case tp_Exit:
|
case tp_Exit:
|
||||||
asNodeName = ExchangeCharInString( asNodeName, '_', ' ' );
|
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
break;
|
break;
|
||||||
@@ -605,6 +604,191 @@ void TEvent::Load(cParser *parser, Math3D::vector3 const &org)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
TEvent::export_as_text( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
if( Type == tp_Unknown ) { return; }
|
||||||
|
|
||||||
|
// header
|
||||||
|
Output << "event ";
|
||||||
|
// name
|
||||||
|
Output << asName << ' ';
|
||||||
|
// type
|
||||||
|
std::vector<std::string> const types {
|
||||||
|
"unknown", "sound", "exit", "disable", "velocity", "animation", "lights",
|
||||||
|
"updatevalues", "getvalues", "putvalues", "switch", "dynvel", "trackvel",
|
||||||
|
"multiple", "addvalues", "copyvalues", "whois", "logvalues", "visible",
|
||||||
|
"voltage", "message", "friction" };
|
||||||
|
Output << types[ Type ] << ' ';
|
||||||
|
// delay
|
||||||
|
Output << fDelay << ' ';
|
||||||
|
// associated node
|
||||||
|
Output << ( asNodeName.empty() ? "none" : asNodeName ) << ' ';
|
||||||
|
// type-specific attributes
|
||||||
|
switch( Type ) {
|
||||||
|
case tp_AddValues:
|
||||||
|
case tp_UpdateValues: {
|
||||||
|
Output
|
||||||
|
<< ( ( iFlags & update_memstring ) == 0 ? "*" : Params[ 0 ].asText ) << ' '
|
||||||
|
<< ( ( iFlags & update_memval1 ) == 0 ? "*" : to_string( Params[ 1 ].asdouble ) ) << ' '
|
||||||
|
<< ( ( iFlags & update_memval2 ) == 0 ? "*" : to_string( Params[ 2 ].asdouble ) ) << ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_CopyValues: {
|
||||||
|
// NOTE: there's no way to get the original parameter value if it doesn't point to existing memcell
|
||||||
|
Output
|
||||||
|
<< ( Params[ 9 ].asMemCell == nullptr ? "none" : Params[ 9 ].asMemCell->name() ) << ' '
|
||||||
|
<< ( iFlags & ( update_memstring | update_memval1 | update_memval2 ) ) << ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_PutValues: {
|
||||||
|
Output
|
||||||
|
// location
|
||||||
|
<< Params[ 3 ].asdouble << ' '
|
||||||
|
<< Params[ 4 ].asdouble << ' '
|
||||||
|
<< Params[ 5 ].asdouble << ' '
|
||||||
|
// command
|
||||||
|
<< Params[ 0 ].asText << ' '
|
||||||
|
<< Params[ 1 ].asdouble << ' '
|
||||||
|
<< Params[ 2 ].asdouble << ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Multiple: {
|
||||||
|
// NOTE: conditional_anyelse won't work when event cap is removed
|
||||||
|
bool hasconditionalelse { false };
|
||||||
|
for( auto eventidx = 0; eventidx < 8; ++eventidx ) {
|
||||||
|
if( Params[ eventidx ].asEvent == nullptr ) { continue; }
|
||||||
|
if( ( iFlags & ( conditional_else << eventidx ) ) == 0 ) {
|
||||||
|
Output << Params[ eventidx ].asEvent->asName << ' ';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// this event is executed as part of the 'else' block
|
||||||
|
hasconditionalelse = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// optional 'else' block
|
||||||
|
if( true == hasconditionalelse ) {
|
||||||
|
Output << "else ";
|
||||||
|
for( auto eventidx = 0; eventidx < 8; ++eventidx ) {
|
||||||
|
if( Params[ eventidx ].asEvent == nullptr ) { continue; }
|
||||||
|
if( ( iFlags & ( conditional_else << eventidx ) ) != 0 ) {
|
||||||
|
Output << Params[ eventidx ].asEvent->asName << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Visible: {
|
||||||
|
Output << Params[ 0 ].asInt << ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Switch: {
|
||||||
|
Output << Params[ 0 ].asInt << ' ';
|
||||||
|
if( ( Params[ 1 ].asdouble != -1.0 )
|
||||||
|
|| ( Params[ 2 ].asdouble != -1.0 ) ) {
|
||||||
|
Output << Params[ 1 ].asdouble << ' ';
|
||||||
|
}
|
||||||
|
if( Params[ 2 ].asdouble != -1.0 ) {
|
||||||
|
Output << Params[ 2 ].asdouble << ' ';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Lights: {
|
||||||
|
auto lightidx { 0 };
|
||||||
|
while( ( lightidx < iMaxNumLights )
|
||||||
|
&& ( Params[ lightidx ].asdouble > -2.0 ) ) {
|
||||||
|
Output << Params[ lightidx ].asdouble << ' ';
|
||||||
|
++lightidx;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Animation: {
|
||||||
|
// animation type
|
||||||
|
Output << (
|
||||||
|
Params[ 0 ].asInt == 1 ? "rotate" :
|
||||||
|
Params[ 0 ].asInt == 2 ? "translate" :
|
||||||
|
// NOTE: .vmd animation doesn't preserve file name, can't be exported. TODO: fix this
|
||||||
|
Params[ 0 ].asInt == 8 ? "digital" :
|
||||||
|
"none" )
|
||||||
|
<< ' ';
|
||||||
|
// submodel
|
||||||
|
Output << (
|
||||||
|
Params[ 9 ].asAnimContainer != nullptr ?
|
||||||
|
Params[ 9 ].asAnimContainer->NameGet() :
|
||||||
|
"none" ) << ' ';
|
||||||
|
// animation parameters
|
||||||
|
Output
|
||||||
|
<< Params[ 1 ].asdouble << ' '
|
||||||
|
<< Params[ 2 ].asdouble << ' '
|
||||||
|
<< Params[ 3 ].asdouble << ' '
|
||||||
|
<< Params[ 4 ].asdouble << ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Sound: {
|
||||||
|
// playback mode
|
||||||
|
Output << Params[ 0 ].asInt << ' ';
|
||||||
|
// optional radio channel
|
||||||
|
if( Params[ 1 ].asdouble > 0.0 ) {
|
||||||
|
Output << Params[ 1 ].asdouble << ' ';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_DynVel:
|
||||||
|
case tp_TrackVel:
|
||||||
|
case tp_Voltage:
|
||||||
|
case tp_Friction: {
|
||||||
|
Output << Params[ 0 ].asdouble << ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Velocity: {
|
||||||
|
Output << Params[ 0 ].asdouble * ( 3600.0 / 1000.0 ) << ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_WhoIs: {
|
||||||
|
Output
|
||||||
|
<< ( iFlags & ( update_memstring | update_memval1 | update_memval2 ) ) << ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// optional conditions
|
||||||
|
// NOTE: for flexibility condition check and export is performed for all event types rather than only for these which support it currently
|
||||||
|
auto const isconditional { ( conditional_trackoccupied | conditional_trackfree | conditional_propability | conditional_memcompare ) };
|
||||||
|
if( ( ( iFlags & isconditional ) != 0 ) ) {
|
||||||
|
Output << "condition ";
|
||||||
|
if( ( iFlags & conditional_trackoccupied ) != 0 ) {
|
||||||
|
Output << "trackoccupied ";
|
||||||
|
}
|
||||||
|
else if( ( iFlags & conditional_trackfree ) != 0 ) {
|
||||||
|
Output << "trackfree ";
|
||||||
|
}
|
||||||
|
else if( ( iFlags & conditional_propability ) != 0 ) {
|
||||||
|
Output
|
||||||
|
<< "propability "
|
||||||
|
<< Params[ 10 ].asdouble << ' ';
|
||||||
|
}
|
||||||
|
else if( ( iFlags & conditional_memcompare ) != 0 ) {
|
||||||
|
Output
|
||||||
|
<< "memcompare "
|
||||||
|
<< ( ( iFlags & conditional_memstring ) == 0 ? "*" : Params[ 10 ].asText ) << ' '
|
||||||
|
<< ( ( iFlags & conditional_memval1 ) == 0 ? "*" : to_string( Params[ 11 ].asdouble ) ) << ' '
|
||||||
|
<< ( ( iFlags & conditional_memval2 ) == 0 ? "*" : to_string( Params[ 12 ].asdouble ) ) << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( fRandomDelay != 0.0 ) {
|
||||||
|
Output
|
||||||
|
<< "randomdelay "
|
||||||
|
<< fRandomDelay << ' ';
|
||||||
|
}
|
||||||
|
// footer
|
||||||
|
Output
|
||||||
|
<< "endevent"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
void TEvent::AddToQuery( TEvent *Event, TEvent *&Start ) {
|
void TEvent::AddToQuery( TEvent *Event, TEvent *&Start ) {
|
||||||
|
|
||||||
TEvent *target( Start );
|
TEvent *target( Start );
|
||||||
@@ -1002,6 +1186,10 @@ event_manager::CheckQuery() {
|
|||||||
case tp_Lights: {
|
case tp_Lights: {
|
||||||
if( m_workevent->Params[ 9 ].asModel ) {
|
if( m_workevent->Params[ 9 ].asModel ) {
|
||||||
for( i = 0; i < iMaxNumLights; ++i ) {
|
for( i = 0; i < iMaxNumLights; ++i ) {
|
||||||
|
if( m_workevent->Params[ i ].asdouble == -2.0 ) {
|
||||||
|
// processed all supplied values, bail out
|
||||||
|
break;
|
||||||
|
}
|
||||||
if( m_workevent->Params[ i ].asdouble >= 0 ) {
|
if( m_workevent->Params[ i ].asdouble >= 0 ) {
|
||||||
// -1 zostawia bez zmiany
|
// -1 zostawia bez zmiany
|
||||||
m_workevent->Params[ 9 ].asModel->LightSet(
|
m_workevent->Params[ 9 ].asModel->LightSet(
|
||||||
@@ -1013,8 +1201,8 @@ event_manager::CheckQuery() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Visible: {
|
case tp_Visible: {
|
||||||
if( m_workevent->Params[ 9 ].asEditorNode )
|
if( m_workevent->Params[ 9 ].asSceneNode )
|
||||||
m_workevent->Params[ 9 ].asEditorNode->visible( m_workevent->Params[ 0 ].asInt > 0 );
|
m_workevent->Params[ 9 ].asSceneNode->visible( m_workevent->Params[ 0 ].asInt > 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Velocity: {
|
case tp_Velocity: {
|
||||||
@@ -1022,8 +1210,12 @@ event_manager::CheckQuery() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Exit: {
|
case tp_Exit: {
|
||||||
MessageBox( 0, m_workevent->asNodeName.c_str(), " THE END ", MB_OK );
|
// wyłączenie takie samo jak sekwencja F10 -> Y
|
||||||
Global.iTextMode = -1; // wyłączenie takie samo jak sekwencja F10 -> Y
|
MessageBox(
|
||||||
|
0,
|
||||||
|
ExchangeCharInString( m_workevent->asNodeName, '_', ' ' ).c_str(),
|
||||||
|
" THE END ",
|
||||||
|
MB_OK );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case tp_Sound: {
|
case tp_Sound: {
|
||||||
@@ -1404,7 +1596,6 @@ event_manager::InitEvents() {
|
|||||||
else {
|
else {
|
||||||
ErrorLog( "Bad event: animation event \"" + event->asName + "\" cannot find model instance \"" + event->asNodeName + "\"" );
|
ErrorLog( "Bad event: animation event \"" + event->asName + "\" cannot find model instance \"" + event->asNodeName + "\"" );
|
||||||
}
|
}
|
||||||
event->asNodeName = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Lights: {
|
case tp_Lights: {
|
||||||
@@ -1414,12 +1605,11 @@ event_manager::InitEvents() {
|
|||||||
event->Params[ 9 ].asModel = instance;
|
event->Params[ 9 ].asModel = instance;
|
||||||
else
|
else
|
||||||
ErrorLog( "Bad event: lights event \"" + event->asName + "\" cannot find model instance \"" + event->asNodeName + "\"" );
|
ErrorLog( "Bad event: lights event \"" + event->asName + "\" cannot find model instance \"" + event->asNodeName + "\"" );
|
||||||
event->asNodeName = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Visible: {
|
case tp_Visible: {
|
||||||
// ukrycie albo przywrócenie obiektu
|
// ukrycie albo przywrócenie obiektu
|
||||||
editor::basic_node *node = simulation::Instances.find( event->asNodeName ); // najpierw model
|
scene::basic_node *node = simulation::Instances.find( event->asNodeName ); // najpierw model
|
||||||
if( node == nullptr ) {
|
if( node == nullptr ) {
|
||||||
// albo tory?
|
// albo tory?
|
||||||
node = simulation::Paths.find( event->asNodeName );
|
node = simulation::Paths.find( event->asNodeName );
|
||||||
@@ -1429,12 +1619,11 @@ event_manager::InitEvents() {
|
|||||||
node = simulation::Traction.find( event->asNodeName );
|
node = simulation::Traction.find( event->asNodeName );
|
||||||
}
|
}
|
||||||
if( node != nullptr )
|
if( node != nullptr )
|
||||||
event->Params[ 9 ].asEditorNode = node;
|
event->Params[ 9 ].asSceneNode = node;
|
||||||
else {
|
else {
|
||||||
event->m_ignored = true;
|
event->m_ignored = true;
|
||||||
ErrorLog( "Bad event: visibility event \"" + event->asName + "\" cannot find item \"" + event->asNodeName + "\"" );
|
ErrorLog( "Bad event: visibility event \"" + event->asName + "\" cannot find item \"" + event->asNodeName + "\"" );
|
||||||
}
|
}
|
||||||
event->asNodeName = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Switch: {
|
case tp_Switch: {
|
||||||
@@ -1460,7 +1649,6 @@ event_manager::InitEvents() {
|
|||||||
else {
|
else {
|
||||||
ErrorLog( "Bad event: switch event \"" + event->asName + "\" cannot find track \"" + event->asNodeName + "\"" );
|
ErrorLog( "Bad event: switch event \"" + event->asName + "\" cannot find track \"" + event->asNodeName + "\"" );
|
||||||
}
|
}
|
||||||
event->asNodeName = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Sound: {
|
case tp_Sound: {
|
||||||
@@ -1470,7 +1658,6 @@ event_manager::InitEvents() {
|
|||||||
event->Params[ 9 ].tsTextSound = sound;
|
event->Params[ 9 ].tsTextSound = sound;
|
||||||
else
|
else
|
||||||
ErrorLog( "Bad event: sound event \"" + event->asName + "\" cannot find static sound \"" + event->asNodeName + "\"" );
|
ErrorLog( "Bad event: sound event \"" + event->asName + "\" cannot find static sound \"" + event->asNodeName + "\"" );
|
||||||
event->asNodeName = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_TrackVel: {
|
case tp_TrackVel: {
|
||||||
@@ -1486,7 +1673,6 @@ event_manager::InitEvents() {
|
|||||||
ErrorLog( "Bad event: track velocity event \"" + event->asName + "\" cannot find track \"" + event->asNodeName + "\"" );
|
ErrorLog( "Bad event: track velocity event \"" + event->asName + "\" cannot find track \"" + event->asNodeName + "\"" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event->asNodeName = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_DynVel: {
|
case tp_DynVel: {
|
||||||
@@ -1500,7 +1686,6 @@ event_manager::InitEvents() {
|
|||||||
else
|
else
|
||||||
ErrorLog( "Bad event: vehicle velocity event \"" + event->asName + "\" cannot find vehicle \"" + event->asNodeName + "\"" );
|
ErrorLog( "Bad event: vehicle velocity event \"" + event->asName + "\" cannot find vehicle \"" + event->asNodeName + "\"" );
|
||||||
}
|
}
|
||||||
event->asNodeName = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Multiple: {
|
case tp_Multiple: {
|
||||||
@@ -1548,7 +1733,6 @@ event_manager::InitEvents() {
|
|||||||
else
|
else
|
||||||
ErrorLog( "Bad event: voltage event \"" + event->asName + "\" cannot find power source \"" + event->asNodeName + "\"" );
|
ErrorLog( "Bad event: voltage event \"" + event->asName + "\" cannot find power source \"" + event->asNodeName + "\"" );
|
||||||
}
|
}
|
||||||
event->asNodeName = "";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tp_Message: {
|
case tp_Message: {
|
||||||
@@ -1597,6 +1781,20 @@ event_manager::InitLaunchers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
event_manager::export_as_text( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
Output << "// events\n";
|
||||||
|
for( auto const *event : m_events ) {
|
||||||
|
event->export_as_text( Output );
|
||||||
|
}
|
||||||
|
Output << "// event launchers\n";
|
||||||
|
for( auto const *launcher : m_launchers.sequence() ) {
|
||||||
|
launcher->export_as_text( Output );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// legacy method, verifies condition for specified event
|
// legacy method, verifies condition for specified event
|
||||||
bool
|
bool
|
||||||
event_manager::EventConditon( TEvent *Event ) {
|
event_manager::EventConditon( TEvent *Event ) {
|
||||||
|
|||||||
10
Event.h
10
Event.h
@@ -17,7 +17,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
enum TEventType {
|
enum TEventType {
|
||||||
tp_Unknown,
|
tp_Unknown,
|
||||||
tp_Sound,
|
tp_Sound,
|
||||||
tp_SoundPos,
|
|
||||||
tp_Exit,
|
tp_Exit,
|
||||||
tp_Disable,
|
tp_Disable,
|
||||||
tp_Velocity,
|
tp_Velocity,
|
||||||
@@ -31,7 +30,6 @@ enum TEventType {
|
|||||||
tp_TrackVel,
|
tp_TrackVel,
|
||||||
tp_Multiple,
|
tp_Multiple,
|
||||||
tp_AddValues,
|
tp_AddValues,
|
||||||
// tp_Ignored, // NOTE: refactored to separate flag
|
|
||||||
tp_CopyValues,
|
tp_CopyValues,
|
||||||
tp_WhoIs,
|
tp_WhoIs,
|
||||||
tp_LogValues,
|
tp_LogValues,
|
||||||
@@ -61,7 +59,7 @@ union TParam
|
|||||||
{
|
{
|
||||||
void *asPointer;
|
void *asPointer;
|
||||||
TMemCell *asMemCell;
|
TMemCell *asMemCell;
|
||||||
editor::basic_node *asEditorNode;
|
scene::basic_node *asSceneNode;
|
||||||
glm::dvec3 const *asLocation;
|
glm::dvec3 const *asLocation;
|
||||||
TTrack *asTrack;
|
TTrack *asTrack;
|
||||||
TAnimModel *asModel;
|
TAnimModel *asModel;
|
||||||
@@ -103,6 +101,9 @@ public:
|
|||||||
TEvent(std::string const &m = "");
|
TEvent(std::string const &m = "");
|
||||||
~TEvent();
|
~TEvent();
|
||||||
void Load(cParser *parser, Math3D::vector3 const &org);
|
void Load(cParser *parser, Math3D::vector3 const &org);
|
||||||
|
// sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
export_as_text( std::ostream &Output ) const;
|
||||||
static void AddToQuery( TEvent *Event, TEvent *&Start );
|
static void AddToQuery( TEvent *Event, TEvent *&Start );
|
||||||
std::string CommandGet();
|
std::string CommandGet();
|
||||||
TCommandType Command();
|
TCommandType Command();
|
||||||
@@ -151,6 +152,9 @@ public:
|
|||||||
// legacy method, initializes event launchers after deserialization from scenario file
|
// legacy method, initializes event launchers after deserialization from scenario file
|
||||||
void
|
void
|
||||||
InitLaunchers();
|
InitLaunchers();
|
||||||
|
// sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
export_as_text( std::ostream &Output ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
|
|||||||
35
MemCell.cpp
35
MemCell.cpp
@@ -164,6 +164,41 @@ void TMemCell::AssignEvents(TEvent *e)
|
|||||||
OnSent = e;
|
OnSent = e;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void
|
||||||
|
TMemCell::serialize_( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void
|
||||||
|
TMemCell::deserialize_( std::istream &Input ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
TMemCell::export_as_text_( std::ostream &Output ) const {
|
||||||
|
// header
|
||||||
|
Output << "memcell ";
|
||||||
|
// location
|
||||||
|
Output
|
||||||
|
<< location().x << ' '
|
||||||
|
<< location().y << ' '
|
||||||
|
<< location().z << ' '
|
||||||
|
// cell data
|
||||||
|
<< szText << ' '
|
||||||
|
<< fValue1 << ' '
|
||||||
|
<< fValue2 << ' '
|
||||||
|
// associated track
|
||||||
|
<< ( asTrackName.empty() ? "none" : asTrackName ) << ' '
|
||||||
|
// footer
|
||||||
|
<< "endmemcell"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// legacy method, initializes traction after deserialization from scenario file
|
// legacy method, initializes traction after deserialization from scenario file
|
||||||
|
|||||||
12
MemCell.h
12
MemCell.h
@@ -13,10 +13,11 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "scenenode.h"
|
#include "scenenode.h"
|
||||||
#include "names.h"
|
#include "names.h"
|
||||||
|
|
||||||
class TMemCell : public editor::basic_node {
|
class TMemCell : public scene::basic_node {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
|
std::string asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
|
||||||
|
bool is_exportable { true }; // export helper; autogenerated cells don't need to be exported
|
||||||
|
|
||||||
explicit TMemCell( scene::node_data const &Nodedata );
|
explicit TMemCell( scene::node_data const &Nodedata );
|
||||||
|
|
||||||
@@ -49,6 +50,15 @@ public:
|
|||||||
void AssignEvents(TEvent *e);
|
void AssignEvents(TEvent *e);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// methods
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void serialize_( std::ostream &Output ) const;
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void deserialize_( std::istream &Input );
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void export_as_text_( std::ostream &Output ) const;
|
||||||
|
|
||||||
|
// members
|
||||||
// content
|
// content
|
||||||
std::string szText;
|
std::string szText;
|
||||||
double fValue1 { 0.0 };
|
double fValue1 { 0.0 };
|
||||||
|
|||||||
3
Names.h
3
Names.h
@@ -60,5 +60,8 @@ public:
|
|||||||
type_sequence &
|
type_sequence &
|
||||||
sequence() {
|
sequence() {
|
||||||
return m_items; }
|
return m_items; }
|
||||||
|
type_sequence const &
|
||||||
|
sequence() const {
|
||||||
|
return m_items; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
62
Segment.cpp
62
Segment.cpp
@@ -18,8 +18,36 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// 101206 Ra: trapezoidalne drogi
|
// helper, restores content of a 3d vector from provided input stream
|
||||||
// 110806 Ra: odwrócone mapowanie wzdłuż - Point1 == 1.0
|
// TODO: review and clean up the helper routines, there's likely some redundant ones
|
||||||
|
Math3D::vector3 LoadPoint( cParser &Input ) {
|
||||||
|
// pobranie współrzędnych punktu
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Math3D::vector3 point;
|
||||||
|
Input
|
||||||
|
>> point.x
|
||||||
|
>> point.y
|
||||||
|
>> point.z;
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
segment_data::deserialize( cParser &Input, Math3D::vector3 const &Offset ) {
|
||||||
|
|
||||||
|
points[ segment_data::point::start ] = LoadPoint( Input ) + Offset;
|
||||||
|
Input.getTokens();
|
||||||
|
Input >> rolls[ 0 ];
|
||||||
|
points[ segment_data::point::control1 ] = LoadPoint( Input );
|
||||||
|
points[ segment_data::point::control2 ] = LoadPoint( Input );
|
||||||
|
points[ segment_data::point::end ] = LoadPoint( Input ) + Offset;
|
||||||
|
Input.getTokens( 2 );
|
||||||
|
Input
|
||||||
|
>> rolls[ 1 ]
|
||||||
|
>> radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TSegment::TSegment(TTrack *owner) :
|
TSegment::TSegment(TTrack *owner) :
|
||||||
pOwner( owner )
|
pOwner( owner )
|
||||||
@@ -62,6 +90,7 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
|||||||
// poprawienie przechyłki
|
// poprawienie przechyłki
|
||||||
fRoll1 = glm::radians(fNewRoll1); // Ra: przeliczone jest bardziej przydatne do obliczeń
|
fRoll1 = glm::radians(fNewRoll1); // Ra: przeliczone jest bardziej przydatne do obliczeń
|
||||||
fRoll2 = glm::radians(fNewRoll2);
|
fRoll2 = glm::radians(fNewRoll2);
|
||||||
|
bCurve = bIsCurve;
|
||||||
if (Global.bRollFix)
|
if (Global.bRollFix)
|
||||||
{ // Ra: poprawianie przechyłki
|
{ // Ra: poprawianie przechyłki
|
||||||
// Przechyłka powinna być na środku wewnętrznej szyny, a standardowo jest w osi
|
// Przechyłka powinna być na środku wewnętrznej szyny, a standardowo jest w osi
|
||||||
@@ -91,7 +120,6 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
|||||||
// kąt w planie, żeby nie liczyć wielokrotnie
|
// kąt w planie, żeby nie liczyć wielokrotnie
|
||||||
// Ra: ten kąt jeszcze do przemyślenia jest
|
// Ra: ten kąt jeszcze do przemyślenia jest
|
||||||
fDirection = -std::atan2(Point2.x - Point1.x, Point2.z - Point1.z);
|
fDirection = -std::atan2(Point2.x - Point1.x, Point2.z - Point1.z);
|
||||||
bCurve = bIsCurve;
|
|
||||||
if (bCurve)
|
if (bCurve)
|
||||||
{ // przeliczenie współczynników wielomianu, będzie mniej mnożeń i można policzyć pochodne
|
{ // przeliczenie współczynników wielomianu, będzie mniej mnożeń i można policzyć pochodne
|
||||||
vC = 3.0 * (CPointOut - Point1); // t^1
|
vC = 3.0 * (CPointOut - Point1); // t^1
|
||||||
@@ -99,9 +127,9 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
|||||||
vA = Point2 - Point1 - vC - vB; // t^3
|
vA = Point2 - Point1 - vC - vB; // t^3
|
||||||
fLength = ComputeLength();
|
fLength = ComputeLength();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
fLength = (Point1 - Point2).Length();
|
fLength = ( Point1 - Point2 ).Length();
|
||||||
fStep = fNewStep;
|
}
|
||||||
if (fLength <= 0) {
|
if (fLength <= 0) {
|
||||||
|
|
||||||
ErrorLog( "Bad track: zero length spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
ErrorLog( "Bad track: zero length spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
||||||
@@ -111,17 +139,25 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( pOwner->eType == tt_Switch )
|
|
||||||
&& ( fStep * 3.0 > fLength ) ) {
|
|
||||||
// NOTE: a workaround for too short switches (less than 3 segments) messing up animation/generation of blades
|
|
||||||
fStep = fLength / 3.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fStoop = std::atan2((Point2.y - Point1.y), fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
|
fStoop = std::atan2((Point2.y - Point1.y), fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
|
||||||
SafeDeleteArray(fTsBuffer);
|
|
||||||
|
|
||||||
|
fStep = fNewStep;
|
||||||
|
// NOTE: optionally replace this part with the commented version, after solving geometry issues with double switches
|
||||||
|
if( ( pOwner->eType == tt_Switch )
|
||||||
|
&& ( fStep * ( 3.0 * Global.SplineFidelity ) > fLength ) ) {
|
||||||
|
// NOTE: a workaround for too short switches (less than 3 segments) messing up animation/generation of blades
|
||||||
|
fStep = fLength / ( 3.0 * Global.SplineFidelity );
|
||||||
|
}
|
||||||
iSegCount = static_cast<int>( std::ceil( fLength / fStep ) ); // potrzebne do VBO
|
iSegCount = static_cast<int>( std::ceil( fLength / fStep ) ); // potrzebne do VBO
|
||||||
|
/*
|
||||||
|
iSegCount = (
|
||||||
|
pOwner->eType == tt_Switch ?
|
||||||
|
6 * Global.SplineFidelity :
|
||||||
|
static_cast<int>( std::ceil( fLength / fStep ) ) ); // potrzebne do VBO
|
||||||
|
*/
|
||||||
fStep = fLength / iSegCount; // update step to equalize size of individual pieces
|
fStep = fLength / iSegCount; // update step to equalize size of individual pieces
|
||||||
|
|
||||||
|
SafeDeleteArray( fTsBuffer );
|
||||||
fTsBuffer = new double[ iSegCount + 1 ];
|
fTsBuffer = new double[ iSegCount + 1 ];
|
||||||
fTsBuffer[ 0 ] = 0.0;
|
fTsBuffer[ 0 ] = 0.0;
|
||||||
for( int i = 1; i < iSegCount; ++i ) {
|
for( int i = 1; i < iSegCount; ++i ) {
|
||||||
|
|||||||
18
Segment.h
18
Segment.h
@@ -14,6 +14,24 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "openglgeometrybank.h"
|
#include "openglgeometrybank.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
|
struct segment_data {
|
||||||
|
// types
|
||||||
|
enum point {
|
||||||
|
start = 0,
|
||||||
|
control1,
|
||||||
|
control2,
|
||||||
|
end
|
||||||
|
};
|
||||||
|
// members
|
||||||
|
std::array<glm::dvec3, 4> points {};
|
||||||
|
std::array<float, 2> rolls {};
|
||||||
|
float radius {};
|
||||||
|
// constructors
|
||||||
|
segment_data() = default;
|
||||||
|
// methods
|
||||||
|
void deserialize( cParser &Input, Math3D::vector3 const &Offset );
|
||||||
|
};
|
||||||
|
|
||||||
class TSegment
|
class TSegment
|
||||||
{ // aproksymacja toru (zwrotnica ma dwa takie, jeden z nich jest aktywny)
|
{ // aproksymacja toru (zwrotnica ma dwa takie, jeden z nich jest aktywny)
|
||||||
private:
|
private:
|
||||||
|
|||||||
523
Track.cpp
523
Track.cpp
@@ -343,14 +343,6 @@ void TTrack::ConnectNextNext(TTrack *pTrack, int typ)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Math3D::vector3 LoadPoint(cParser *parser)
|
|
||||||
{ // pobranie współrzędnych punktu
|
|
||||||
Math3D::vector3 p;
|
|
||||||
parser->getTokens(3);
|
|
||||||
*parser >> p.x >> p.y >> p.z;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
||||||
{ // pobranie obiektu trajektorii ruchu
|
{ // pobranie obiektu trajektorii ruchu
|
||||||
Math3D::vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań
|
Math3D::vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań
|
||||||
@@ -473,20 +465,44 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
WriteLog("unvis");
|
WriteLog("unvis");
|
||||||
Init(); // ustawia SwitchExtension
|
Init(); // ustawia SwitchExtension
|
||||||
double segsize = 5.0; // długość odcinka segmentowania
|
double segsize = 5.0; // długość odcinka segmentowania
|
||||||
switch (eType)
|
|
||||||
{ // Ra: łuki segmentowane co 5m albo 314-kątem foremnym
|
// path data
|
||||||
case tt_Table: // obrotnica jest prawie jak zwykły tor
|
// all subtypes contain at least one path
|
||||||
|
m_paths.emplace_back();
|
||||||
|
m_paths.back().deserialize( *parser, pOrigin );
|
||||||
|
switch( eType ) {
|
||||||
|
case tt_Switch:
|
||||||
|
case tt_Cross:
|
||||||
|
case tt_Tributary: {
|
||||||
|
// these subtypes contain additional path
|
||||||
|
m_paths.emplace_back();
|
||||||
|
m_paths.back().deserialize( *parser, pOrigin );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (eType) {
|
||||||
|
// Ra: łuki segmentowane co 5m albo 314-kątem foremnym
|
||||||
|
case tt_Table: {
|
||||||
|
// obrotnica jest prawie jak zwykły tor
|
||||||
iAction |= 2; // flaga zmiany położenia typu obrotnica
|
iAction |= 2; // flaga zmiany położenia typu obrotnica
|
||||||
case tt_Normal:
|
}
|
||||||
p1 = LoadPoint(parser) + pOrigin; // pobranie współrzędnych P1
|
case tt_Normal: {
|
||||||
parser->getTokens();
|
// pobranie współrzędnych P1
|
||||||
*parser >> r1; // pobranie przechyłki w P1
|
auto const &path { m_paths[ 0 ] };
|
||||||
cp1 = LoadPoint(parser); // pobranie współrzędnych punktów kontrolnych
|
p1 = path.points[ segment_data::point::start ];
|
||||||
cp2 = LoadPoint(parser);
|
// pobranie współrzędnych punktów kontrolnych
|
||||||
p2 = LoadPoint(parser) + pOrigin; // pobranie współrzędnych P2
|
cp1 = path.points[ segment_data::point::control1 ];
|
||||||
parser->getTokens(2);
|
cp2 = path.points[ segment_data::point::control2 ];
|
||||||
*parser >> r2 >> fRadius; // pobranie przechyłki w P1 i promienia
|
// pobranie współrzędnych P2
|
||||||
fRadius = fabs(fRadius); // we wpisie może być ujemny
|
p2 = path.points[ segment_data::point::end ];
|
||||||
|
r1 = path.rolls[ 0 ];
|
||||||
|
r2 = path.rolls[ 1 ];
|
||||||
|
fRadius = std::abs( path.radius ); // we wpisie może być ujemny
|
||||||
|
|
||||||
if (iCategoryFlag & 1)
|
if (iCategoryFlag & 1)
|
||||||
{ // zero na główce szyny
|
{ // zero na główce szyny
|
||||||
p1.y += 0.18;
|
p1.y += 0.18;
|
||||||
@@ -502,7 +518,11 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
|
|
||||||
if( fRadius != 0 ) {
|
if( fRadius != 0 ) {
|
||||||
// gdy podany promień
|
// gdy podany promień
|
||||||
segsize = clamp( std::abs( fRadius ) * ( 0.02 / Global.SplineFidelity ), 2.0 / Global.SplineFidelity, 10.0 );
|
segsize =
|
||||||
|
clamp(
|
||||||
|
std::abs( fRadius ) * ( 0.02 / Global.SplineFidelity ),
|
||||||
|
2.0 / Global.SplineFidelity,
|
||||||
|
10.0 / Global.SplineFidelity );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// HACK: crude check whether claimed straight is an actual straight piece
|
// HACK: crude check whether claimed straight is an actual straight piece
|
||||||
@@ -512,7 +532,11 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// HACK: divide roughly in 10 segments.
|
// HACK: divide roughly in 10 segments.
|
||||||
segsize = clamp( ( p1 - p2 ).Length() * ( 0.1 / Global.SplineFidelity ), 2.0 / Global.SplineFidelity, 10.0 );
|
segsize =
|
||||||
|
clamp(
|
||||||
|
( p1 - p2 ).Length() * 0.1,
|
||||||
|
2.0 / Global.SplineFidelity,
|
||||||
|
10.0 / Global.SplineFidelity );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,6 +553,7 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
|
|
||||||
if ((r1 != 0) || (r2 != 0))
|
if ((r1 != 0) || (r2 != 0))
|
||||||
iTrapezoid = 1; // są przechyłki do uwzględniania w rysowaniu
|
iTrapezoid = 1; // są przechyłki do uwzględniania w rysowaniu
|
||||||
|
|
||||||
if (eType == tt_Table) // obrotnica ma doklejkę
|
if (eType == tt_Table) // obrotnica ma doklejkę
|
||||||
{ // SwitchExtension=new TSwitchExtension(this,1); //dodatkowe zmienne dla obrotnicy
|
{ // SwitchExtension=new TSwitchExtension(this,1); //dodatkowe zmienne dla obrotnicy
|
||||||
SwitchExtension->Segments[0]->Init(p1, p2, segsize); // kopia oryginalnego toru
|
SwitchExtension->Segments[0]->Init(p1, p2, segsize); // kopia oryginalnego toru
|
||||||
@@ -549,56 +574,92 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
fTexRatio2 = w / h; // proporcja boków
|
fTexRatio2 = w / h; // proporcja boków
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case tt_Cross: // skrzyżowanie dróg - 4 punkty z wektorami kontrolnymi
|
case tt_Cross: {
|
||||||
segsize = 1.0; // specjalne segmentowanie ze względu na małe promienie
|
// skrzyżowanie dróg - 4 punkty z wektorami kontrolnymi
|
||||||
|
// segsize = 1.0; // specjalne segmentowanie ze względu na małe promienie
|
||||||
|
}
|
||||||
case tt_Tributary: // dopływ
|
case tt_Tributary: // dopływ
|
||||||
case tt_Switch: // zwrotnica
|
case tt_Switch: { // zwrotnica
|
||||||
iAction |= 1; // flaga zmiany położenia typu zwrotnica lub skrzyżowanie dróg
|
iAction |= 1; // flaga zmiany położenia typu zwrotnica lub skrzyżowanie dróg
|
||||||
// problemy z animacją iglic powstaje, gdzy odcinek prosty ma zmienną przechyłkę
|
// problemy z animacją iglic powstaje, gdzy odcinek prosty ma zmienną przechyłkę
|
||||||
// wtedy dzieli się na dodatkowe odcinki (po 0.2m, bo R=0) i animację diabli biorą
|
// wtedy dzieli się na dodatkowe odcinki (po 0.2m, bo R=0) i animację diabli biorą
|
||||||
// Ra: na razie nie podejmuję się przerabiania iglic
|
// Ra: na razie nie podejmuję się przerabiania iglic
|
||||||
|
|
||||||
// SwitchExtension=new TSwitchExtension(this,eType==tt_Cross?6:2); //zwrotnica ma doklejkę
|
// SwitchExtension=new TSwitchExtension(this,eType==tt_Cross?6:2); //zwrotnica ma doklejkę
|
||||||
|
auto const &path { m_paths[ 0 ] };
|
||||||
|
p1 = path.points[ segment_data::point::start ];
|
||||||
|
// pobranie współrzędnych punktów kontrolnych
|
||||||
|
cp1 = path.points[ segment_data::point::control1 ];
|
||||||
|
cp2 = path.points[ segment_data::point::control2 ];
|
||||||
|
// pobranie współrzędnych P2
|
||||||
|
p2 = path.points[ segment_data::point::end ];
|
||||||
|
r1 = path.rolls[ 0 ];
|
||||||
|
r2 = path.rolls[ 1 ];
|
||||||
|
fRadiusTable[0] = std::abs( path.radius ); // we wpisie może być ujemny
|
||||||
|
|
||||||
p1 = LoadPoint(parser) + pOrigin; // pobranie współrzędnych P1
|
|
||||||
parser->getTokens();
|
|
||||||
*parser >> r1;
|
|
||||||
cp1 = LoadPoint(parser);
|
|
||||||
cp2 = LoadPoint(parser);
|
|
||||||
p2 = LoadPoint(parser) + pOrigin; // pobranie współrzędnych P2
|
|
||||||
parser->getTokens(2);
|
|
||||||
*parser >> r2 >> fRadiusTable[0];
|
|
||||||
fRadiusTable[0] = fabs(fRadiusTable[0]); // we wpisie może być ujemny
|
|
||||||
if (iCategoryFlag & 1)
|
if (iCategoryFlag & 1)
|
||||||
{ // zero na główce szyny
|
{ // zero na główce szyny
|
||||||
p1.y += 0.18;
|
p1.y += 0.18;
|
||||||
p2.y += 0.18;
|
p2.y += 0.18;
|
||||||
// na przechyłce doliczyć jeszcze pół przechyłki?
|
// na przechyłce doliczyć jeszcze pół przechyłki?
|
||||||
}
|
}
|
||||||
if (fRadiusTable[0] > 0)
|
|
||||||
segsize = clamp( 0.2 + fRadiusTable[0] * 0.02, 2.0, 5.0 );
|
|
||||||
else if (eType != tt_Cross) // dla skrzyżowań muszą być podane kontrolne
|
|
||||||
{ // jak promień zerowy, to przeliczamy punkty kontrolne
|
|
||||||
cp1 = (p1 + p1 + p2) / 3.0 - p1; // jak jest prosty, to się zoptymalizuje
|
|
||||||
cp2 = (p1 + p2 + p2) / 3.0 - p2;
|
|
||||||
segsize = 5.0;
|
|
||||||
} // ułomny prosty
|
|
||||||
|
|
||||||
if (!(cp1 == Math3D::vector3(0, 0, 0)) && !(cp2 == Math3D::vector3(0, 0, 0)))
|
if( eType != tt_Cross ) {
|
||||||
SwitchExtension->Segments[0]->Init(p1, p1 + cp1, p2 + cp2, p2, segsize, r1, r2);
|
// dla skrzyżowań muszą być podane kontrolne
|
||||||
else
|
if( ( ( ( p1 + p1 + p2 ) / 3.0 - p1 - cp1 ).Length() < 0.02 )
|
||||||
SwitchExtension->Segments[0]->Init(p1, p2, segsize, r1, r2);
|
|| ( ( ( p1 + p2 + p2 ) / 3.0 - p2 + cp1 ).Length() < 0.02 ) ) {
|
||||||
|
// "prostowanie" prostych z kontrolnymi, dokładność 2cm
|
||||||
|
cp1 = cp2 = Math3D::vector3( 0, 0, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fRadiusTable[ 0 ] != 0 ) {
|
||||||
|
// gdy podany promień
|
||||||
|
segsize =
|
||||||
|
clamp(
|
||||||
|
std::abs( fRadiusTable[ 0 ] ) * ( 0.02 / Global.SplineFidelity ),
|
||||||
|
2.0 / Global.SplineFidelity,
|
||||||
|
10.0 / Global.SplineFidelity );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// HACK: crude check whether claimed straight is an actual straight piece
|
||||||
|
if( ( cp1 == Math3D::vector3() )
|
||||||
|
&& ( cp2 == Math3D::vector3() ) ) {
|
||||||
|
segsize = 10.0; // for straights, 10m per segment works good enough
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// HACK: divide roughly in 10 segments.
|
||||||
|
segsize =
|
||||||
|
clamp(
|
||||||
|
( p1 - p2 ).Length() * 0.1,
|
||||||
|
2.0 / Global.SplineFidelity,
|
||||||
|
10.0 / Global.SplineFidelity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( cp1 == Math3D::vector3( 0, 0, 0 ) )
|
||||||
|
&& ( cp2 == Math3D::vector3( 0, 0, 0 ) ) ) {
|
||||||
|
// Ra: hm, czasem dla prostego są podane...
|
||||||
|
// gdy prosty, kontrolne wyliczane przy zmiennej przechyłce
|
||||||
|
SwitchExtension->Segments[ 0 ]->Init( p1, p2, segsize, r1, r2 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// gdy łuk (ustawia bCurve=true)
|
||||||
|
SwitchExtension->Segments[ 0 ]->Init( p1, cp1 + p1, cp2 + p2, p2, segsize, r1, r2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const &path2 { m_paths[ 1 ] };
|
||||||
|
p3 = path2.points[ segment_data::point::start ];
|
||||||
|
// pobranie współrzędnych punktów kontrolnych
|
||||||
|
cp3 = path2.points[ segment_data::point::control1 ];
|
||||||
|
cp4 = path2.points[ segment_data::point::control2 ];
|
||||||
|
// pobranie współrzędnych P2
|
||||||
|
p4 = path2.points[ segment_data::point::end ];
|
||||||
|
r3 = path2.rolls[ 0 ];
|
||||||
|
r4 = path2.rolls[ 1 ];
|
||||||
|
fRadiusTable[1] = std::abs( path2.radius ); // we wpisie może być ujemny
|
||||||
|
|
||||||
p3 = LoadPoint(parser) + pOrigin; // pobranie współrzędnych P3
|
|
||||||
parser->getTokens();
|
|
||||||
*parser >> r3;
|
|
||||||
cp3 = LoadPoint(parser);
|
|
||||||
cp4 = LoadPoint(parser);
|
|
||||||
p4 = LoadPoint(parser) + pOrigin; // pobranie współrzędnych P4
|
|
||||||
parser->getTokens(2);
|
|
||||||
*parser >> r4 >> fRadiusTable[1];
|
|
||||||
fRadiusTable[1] = fabs(fRadiusTable[1]); // we wpisie może być ujemny
|
|
||||||
if (iCategoryFlag & 1)
|
if (iCategoryFlag & 1)
|
||||||
{ // zero na główce szyny
|
{ // zero na główce szyny
|
||||||
p3.y += 0.18;
|
p3.y += 0.18;
|
||||||
@@ -606,25 +667,54 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
// na przechyłce doliczyć jeszcze pół przechyłki?
|
// na przechyłce doliczyć jeszcze pół przechyłki?
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fRadiusTable[1] > 0)
|
if( eType != tt_Cross ) {
|
||||||
segsize = clamp( 0.2 + fRadiusTable[ 1 ] * 0.02, 2.0, 5.0 );
|
// dla skrzyżowań muszą być podane kontrolne
|
||||||
|
if( ( ( ( p3 + p3 + p4 ) / 3.0 - p3 - cp3 ).Length() < 0.02 )
|
||||||
else if (eType != tt_Cross) // dla skrzyżowań muszą być podane kontrolne
|
|| ( ( ( p3 + p4 + p4 ) / 3.0 - p4 + cp3 ).Length() < 0.02 ) ) {
|
||||||
{ // jak promień zerowy, to przeliczamy punkty kontrolne
|
// "prostowanie" prostych z kontrolnymi, dokładność 2cm
|
||||||
cp3 = (p3 + p3 + p4) / 3.0 - p3; // jak jest prosty, to się zoptymalizuje
|
cp3 = cp4 = Math3D::vector3( 0, 0, 0 );
|
||||||
cp4 = (p3 + p4 + p4) / 3.0 - p4;
|
}
|
||||||
segsize = 5.0;
|
}
|
||||||
} // ułomny prosty
|
|
||||||
|
if( fRadiusTable[ 1 ] != 0 ) {
|
||||||
if (!(cp3 == Math3D::vector3(0, 0, 0)) && !(cp4 == Math3D::vector3(0, 0, 0)))
|
// gdy podany promień
|
||||||
{ // dla skrzyżowania dróg dać odwrotnie końce, żeby brzegi generować lewym
|
segsize =
|
||||||
if (eType != tt_Cross)
|
clamp(
|
||||||
SwitchExtension->Segments[1]->Init(p3, p3 + cp3, p4 + cp4, p4, segsize, r3, r4);
|
std::abs( fRadiusTable[ 1 ] ) * ( 0.02 / Global.SplineFidelity ),
|
||||||
else
|
2.0 / Global.SplineFidelity,
|
||||||
SwitchExtension->Segments[1]->Init(p4, p4 + cp4, p3 + cp3, p3, segsize, r4, r3); // odwrócony
|
10.0 / Global.SplineFidelity );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// HACK: crude check whether claimed straight is an actual straight piece
|
||||||
|
if( ( cp3 == Math3D::vector3() )
|
||||||
|
&& ( cp4 == Math3D::vector3() ) ) {
|
||||||
|
segsize = 10.0; // for straights, 10m per segment works good enough
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// HACK: divide roughly in 10 segments.
|
||||||
|
segsize =
|
||||||
|
clamp(
|
||||||
|
( p3 - p4 ).Length() * 0.1,
|
||||||
|
2.0 / Global.SplineFidelity,
|
||||||
|
10.0 / Global.SplineFidelity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( cp3 == Math3D::vector3( 0, 0, 0 ) )
|
||||||
|
&& ( cp4 == Math3D::vector3( 0, 0, 0 ) ) ) {
|
||||||
|
// Ra: hm, czasem dla prostego są podane...
|
||||||
|
// gdy prosty, kontrolne wyliczane przy zmiennej przechyłce
|
||||||
|
SwitchExtension->Segments[ 1 ]->Init( p3, p4, segsize, r3, r4 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( eType != tt_Cross ) {
|
||||||
|
SwitchExtension->Segments[ 1 ]->Init( p3, p3 + cp3, p4 + cp4, p4, segsize, r3, r4 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// dla skrzyżowania dróg dać odwrotnie końce, żeby brzegi generować lewym
|
||||||
|
SwitchExtension->Segments[ 1 ]->Init( p4, p4 + cp4, p3 + cp3, p3, segsize, r4, r3 ); // odwrócony
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
SwitchExtension->Segments[1]->Init(p3, p4, segsize, r3, r4);
|
|
||||||
|
|
||||||
if (eType == tt_Cross)
|
if (eType == tt_Cross)
|
||||||
{ // Ra 2014-07: dla skrzyżowań będą dodatkowe segmenty
|
{ // Ra 2014-07: dla skrzyżowań będą dodatkowe segmenty
|
||||||
@@ -646,10 +736,10 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
{
|
{
|
||||||
Math3D::vector3 v1, v2;
|
Math3D::vector3 v1, v2;
|
||||||
double a1, a2;
|
double a1, a2;
|
||||||
v1 = SwitchExtension->Segments[0]->FastGetPoint_1() -
|
v1 = SwitchExtension->Segments[0]->FastGetPoint_1()
|
||||||
SwitchExtension->Segments[0]->FastGetPoint_0();
|
- SwitchExtension->Segments[0]->FastGetPoint_0();
|
||||||
v2 = SwitchExtension->Segments[1]->FastGetPoint_1() -
|
v2 = SwitchExtension->Segments[1]->FastGetPoint_1()
|
||||||
SwitchExtension->Segments[1]->FastGetPoint_0();
|
- SwitchExtension->Segments[1]->FastGetPoint_0();
|
||||||
a1 = atan2(v1.x, v1.z);
|
a1 = atan2(v1.x, v1.z);
|
||||||
a2 = atan2(v2.x, v2.z);
|
a2 = atan2(v2.x, v2.z);
|
||||||
a2 = a2 - a1;
|
a2 = a2 - a1;
|
||||||
@@ -660,7 +750,10 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
SwitchExtension->RightSwitch = a2 < 0; // lustrzany układ OXY...
|
SwitchExtension->RightSwitch = a2 < 0; // lustrzany układ OXY...
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// optional attributes
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
str = token;
|
str = token;
|
||||||
@@ -707,9 +800,9 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> fVelocity; //*0.28; McZapkie-010602
|
*parser >> fVelocity; //*0.28; McZapkie-010602
|
||||||
if (SwitchExtension) // jeśli tor ruchomy
|
if (SwitchExtension) // jeśli tor ruchomy
|
||||||
if (std::fabs(fVelocity) >= 1.0) //żeby zero nie ograniczało dożywotnio
|
if (std::abs(fVelocity) >= 1.0) //żeby zero nie ograniczało dożywotnio
|
||||||
SwitchExtension->fVelocity = static_cast<float>(fVelocity); // zapamiętanie głównego ograniczenia; a
|
// zapamiętanie głównego ograniczenia; a np. -40 ogranicza tylko na bok
|
||||||
// np. -40 ogranicza tylko na bok
|
SwitchExtension->fVelocity = static_cast<float>(fVelocity);
|
||||||
}
|
}
|
||||||
else if (str == "isolated")
|
else if (str == "isolated")
|
||||||
{ // obwód izolowany, do którego tor należy
|
{ // obwód izolowany, do którego tor należy
|
||||||
@@ -777,20 +870,25 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: refactor this mess
|
// TODO: refactor this mess
|
||||||
bool TTrack::AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2)
|
bool TTrack::AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2, bool const Explicit )
|
||||||
{
|
{
|
||||||
bool bError = false;
|
bool bError = false;
|
||||||
|
|
||||||
if( NewEvent0 == nullptr ) {
|
if( NewEvent0 == nullptr ) {
|
||||||
if( false == asEvent0Name.empty() ) {
|
if( false == asEvent0Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEvent0Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
|
||||||
bError = true;
|
bError = true;
|
||||||
|
if( true == Explicit ) {
|
||||||
|
ErrorLog( "Bad event: event \"" + asEvent0Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( evEvent0 == nullptr ) {
|
if( evEvent0 == nullptr ) {
|
||||||
evEvent0 = NewEvent0;
|
evEvent0 = NewEvent0;
|
||||||
|
/*
|
||||||
|
// preserve event names, we'll need them if we want the scenario export to be unaffected by missing events and such
|
||||||
asEvent0Name = "";
|
asEvent0Name = "";
|
||||||
|
*/
|
||||||
iEvents |= 1; // sumaryczna informacja o eventach
|
iEvents |= 1; // sumaryczna informacja o eventach
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -801,14 +899,18 @@ bool TTrack::AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent
|
|||||||
|
|
||||||
if( NewEvent1 == nullptr ) {
|
if( NewEvent1 == nullptr ) {
|
||||||
if( false == asEvent1Name.empty() ) {
|
if( false == asEvent1Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEvent1Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
|
||||||
bError = true;
|
bError = true;
|
||||||
|
if( true == Explicit ) {
|
||||||
|
ErrorLog( "Bad event: event \"" + asEvent1Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( evEvent1 == nullptr ) {
|
if( evEvent1 == nullptr ) {
|
||||||
evEvent1 = NewEvent1;
|
evEvent1 = NewEvent1;
|
||||||
|
/*
|
||||||
asEvent1Name = "";
|
asEvent1Name = "";
|
||||||
|
*/
|
||||||
iEvents |= 2; // sumaryczna informacja o eventach
|
iEvents |= 2; // sumaryczna informacja o eventach
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -819,14 +921,18 @@ bool TTrack::AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent
|
|||||||
|
|
||||||
if( NewEvent2 == nullptr ) {
|
if( NewEvent2 == nullptr ) {
|
||||||
if( false == asEvent2Name.empty() ) {
|
if( false == asEvent2Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEvent2Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
|
||||||
bError = true;
|
bError = true;
|
||||||
|
if( true == Explicit ) {
|
||||||
|
ErrorLog( "Bad event: event \"" + asEvent2Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( evEvent2 == nullptr ) {
|
if( evEvent2 == nullptr ) {
|
||||||
evEvent2 = NewEvent2;
|
evEvent2 = NewEvent2;
|
||||||
|
/*
|
||||||
asEvent2Name = "";
|
asEvent2Name = "";
|
||||||
|
*/
|
||||||
iEvents |= 4; // sumaryczna informacja o eventach
|
iEvents |= 4; // sumaryczna informacja o eventach
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -838,20 +944,25 @@ bool TTrack::AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent
|
|||||||
return ( bError == false );
|
return ( bError == false );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2)
|
bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2, bool const Explicit)
|
||||||
{
|
{
|
||||||
bool bError = false;
|
bool bError = false;
|
||||||
|
|
||||||
if( NewEvent0 == nullptr ) {
|
if( NewEvent0 == nullptr ) {
|
||||||
if( false == asEventall0Name.empty() ) {
|
if( false == asEventall0Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEventall0Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
|
||||||
bError = true;
|
bError = true;
|
||||||
|
if( true == Explicit ) {
|
||||||
|
ErrorLog( "Bad event: event \"" + asEventall0Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( evEventall0 == nullptr ) {
|
if( evEventall0 == nullptr ) {
|
||||||
evEventall0 = NewEvent0;
|
evEventall0 = NewEvent0;
|
||||||
|
/*
|
||||||
|
// preserve event names, we'll need them if we want the scenario export to be unaffected by missing events and such
|
||||||
asEventall0Name = "";
|
asEventall0Name = "";
|
||||||
|
*/
|
||||||
iEvents |= 8; // sumaryczna informacja o eventach
|
iEvents |= 8; // sumaryczna informacja o eventach
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -862,14 +973,18 @@ bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEv
|
|||||||
|
|
||||||
if( NewEvent1 == nullptr ) {
|
if( NewEvent1 == nullptr ) {
|
||||||
if( false == asEventall1Name.empty() ) {
|
if( false == asEventall1Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEventall1Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
|
||||||
bError = true;
|
bError = true;
|
||||||
|
if( true == Explicit ) {
|
||||||
|
ErrorLog( "Bad event: event \"" + asEventall1Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( evEventall1 == nullptr ) {
|
if( evEventall1 == nullptr ) {
|
||||||
evEventall1 = NewEvent1;
|
evEventall1 = NewEvent1;
|
||||||
|
/*
|
||||||
asEventall1Name = "";
|
asEventall1Name = "";
|
||||||
|
*/
|
||||||
iEvents |= 16; // sumaryczna informacja o eventach
|
iEvents |= 16; // sumaryczna informacja o eventach
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -880,14 +995,18 @@ bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEv
|
|||||||
|
|
||||||
if( NewEvent2 == nullptr ) {
|
if( NewEvent2 == nullptr ) {
|
||||||
if( false == asEventall2Name.empty() ) {
|
if( false == asEventall2Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEventall2Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
|
||||||
bError = true;
|
bError = true;
|
||||||
|
if( true == Explicit ) {
|
||||||
|
ErrorLog( "Bad event: event \"" + asEventall2Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( evEventall2 == nullptr ) {
|
if( evEventall2 == nullptr ) {
|
||||||
evEventall2 = NewEvent2;
|
evEventall2 = NewEvent2;
|
||||||
|
/*
|
||||||
asEventall2Name = "";
|
asEventall2Name = "";
|
||||||
|
*/
|
||||||
iEvents |= 32; // sumaryczna informacja o eventach
|
iEvents |= 32; // sumaryczna informacja o eventach
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1404,6 +1523,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
|||||||
{szyna[ i ].texture.x, 0.f} };
|
{szyna[ i ].texture.x, 0.f} };
|
||||||
}
|
}
|
||||||
// TODO, TBD: change all track geometry to triangles, to allow packing data in less, larger buffers
|
// TODO, TBD: change all track geometry to triangles, to allow packing data in less, larger buffers
|
||||||
|
auto const bladelength { 2 * Global.SplineFidelity };
|
||||||
if (SwitchExtension->RightSwitch)
|
if (SwitchExtension->RightSwitch)
|
||||||
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
||||||
gfx::vertex_array vertices;
|
gfx::vertex_array vertices;
|
||||||
@@ -1412,11 +1532,11 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
|||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength, 1.0, 2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength, 1.0, bladelength );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, bladelength, SwitchExtension->fOffset2 );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -1425,11 +1545,11 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
|||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength, 1.0, 2 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength, 1.0, bladelength );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, bladelength, -fMaxOffset + SwitchExtension->fOffset1 );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -1442,11 +1562,11 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
|||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength, 1.0, bladelength ); // prawa szyna za iglicą
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, bladelength, -SwitchExtension->fOffset2 );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -1455,11 +1575,11 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
|||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength, 1.0, bladelength ); // lewa szyna za iglicą
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, bladelength, fMaxOffset - SwitchExtension->fOffset1 );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -2220,9 +2340,13 @@ bool TTrack::Switch(int i, float const t, float const d)
|
|||||||
iNextDirection = SwitchExtension->iNextDirection[i];
|
iNextDirection = SwitchExtension->iNextDirection[i];
|
||||||
iPrevDirection = SwitchExtension->iPrevDirection[i];
|
iPrevDirection = SwitchExtension->iPrevDirection[i];
|
||||||
fRadius = fRadiusTable[i]; // McZapkie: wybor promienia toru
|
fRadius = fRadiusTable[i]; // McZapkie: wybor promienia toru
|
||||||
if (SwitchExtension->fVelocity <=
|
if( SwitchExtension->fVelocity <= -2 ) {
|
||||||
-2) //-1 oznacza maksymalną prędkość, a dalsze ujemne to ograniczenie na bok
|
//-1 oznacza maksymalną prędkość, a dalsze ujemne to ograniczenie na bok
|
||||||
fVelocity = i ? -SwitchExtension->fVelocity : -1;
|
fVelocity = i ? -SwitchExtension->fVelocity : -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fVelocity = SwitchExtension->fVelocity;
|
||||||
|
}
|
||||||
if (SwitchExtension->pOwner ? SwitchExtension->pOwner->RaTrackAnimAdd(this) :
|
if (SwitchExtension->pOwner ? SwitchExtension->pOwner->RaTrackAnimAdd(this) :
|
||||||
true) // jeśli nie dodane do animacji
|
true) // jeśli nie dodane do animacji
|
||||||
{ // nie ma się co bawić
|
{ // nie ma się co bawić
|
||||||
@@ -2455,17 +2579,18 @@ TTrack * TTrack::RaAnimate()
|
|||||||
|
|
||||||
gfx::vertex_array vertices;
|
gfx::vertex_array vertices;
|
||||||
|
|
||||||
|
auto const bladelength { 2 * Global.SplineFidelity };
|
||||||
if (SwitchExtension->RightSwitch)
|
if (SwitchExtension->RightSwitch)
|
||||||
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
||||||
if( m_material1 ) {
|
if( m_material1 ) {
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, bladelength, SwitchExtension->fOffset2 );
|
||||||
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
if( m_material2 ) {
|
if( m_material2 ) {
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, bladelength, -fMaxOffset + SwitchExtension->fOffset1 );
|
||||||
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -2473,13 +2598,13 @@ TTrack * TTrack::RaAnimate()
|
|||||||
else { // lewa działa lepiej niż prawa
|
else { // lewa działa lepiej niż prawa
|
||||||
if( m_material1 ) {
|
if( m_material1 ) {
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, bladelength, -SwitchExtension->fOffset2 );
|
||||||
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
if( m_material2 ) {
|
if( m_material2 ) {
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, bladelength, fMaxOffset - SwitchExtension->fOffset1 );
|
||||||
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -2659,32 +2784,188 @@ TTrack::endpoints() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculates path's bounding radius
|
// radius() subclass details, calculates node's bounding radius
|
||||||
void
|
float
|
||||||
TTrack::radius_() {
|
TTrack::radius_() {
|
||||||
|
|
||||||
auto const points = endpoints();
|
auto const points { endpoints() };
|
||||||
|
auto radius { 0.f };
|
||||||
for( auto &point : points ) {
|
for( auto &point : points ) {
|
||||||
m_area.radius = std::max(
|
radius = std::max(
|
||||||
m_area.radius,
|
radius,
|
||||||
static_cast<float>( glm::length( m_area.center - point ) ) ); // extra margin to prevent driven vehicle from flicking
|
static_cast<float>( glm::length( m_area.center - point ) ) ); // extra margin to prevent driven vehicle from flicking
|
||||||
}
|
}
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void
|
||||||
|
TTrack::serialize_( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void
|
||||||
|
TTrack::deserialize_( std::istream &Input ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
TTrack::export_as_text_( std::ostream &Output ) const {
|
||||||
|
// header
|
||||||
|
Output << "track ";
|
||||||
|
// type
|
||||||
|
Output << (
|
||||||
|
eType == tt_Normal ? (
|
||||||
|
iCategoryFlag == 1 ? "normal" :
|
||||||
|
iCategoryFlag == 2 ? "road" :
|
||||||
|
iCategoryFlag == 4 ? "river" :
|
||||||
|
"none" ) :
|
||||||
|
eType == tt_Switch ? "switch" :
|
||||||
|
eType == tt_Cross ? "cross" :
|
||||||
|
eType == tt_Table ? "turn" :
|
||||||
|
eType == tt_Tributary ? "tributary" :
|
||||||
|
"none" )
|
||||||
|
<< ' ';
|
||||||
|
// basic attributes
|
||||||
|
Output
|
||||||
|
<< Length() << ' '
|
||||||
|
<< fTrackWidth << ' '
|
||||||
|
<< fFriction << ' '
|
||||||
|
<< fSoundDistance << ' '
|
||||||
|
<< iQualityFlag << ' '
|
||||||
|
<< iDamageFlag << ' ';
|
||||||
|
// environment
|
||||||
|
Output << (
|
||||||
|
eEnvironment == e_flat ? "flat" :
|
||||||
|
eEnvironment == e_bridge ? "bridge" :
|
||||||
|
eEnvironment == e_tunnel ? "tunnel" :
|
||||||
|
eEnvironment == e_bank ? "bank" :
|
||||||
|
eEnvironment == e_canyon ? "canyon" :
|
||||||
|
eEnvironment == e_mountains ? "mountains" :
|
||||||
|
"none" )
|
||||||
|
<< ' ';
|
||||||
|
// visibility
|
||||||
|
// NOTE: 'invis' would be less wrong than 'unvis', but potentially incompatible with old 3rd party tools
|
||||||
|
Output << ( m_visible ? "vis" : "unvis" ) << ' ';
|
||||||
|
if( m_visible ) {
|
||||||
|
// texture parameters are supplied only if the path is set as visible
|
||||||
|
auto texturefile { (
|
||||||
|
m_material1 != null_handle ?
|
||||||
|
GfxRenderer.Material( m_material1 ).name :
|
||||||
|
"none" ) };
|
||||||
|
if( texturefile.find( szTexturePath ) == 0 ) {
|
||||||
|
// don't include 'textures/' in the path
|
||||||
|
texturefile.erase( 0, std::string{ szTexturePath }.size() );
|
||||||
|
}
|
||||||
|
Output
|
||||||
|
<< texturefile << ' '
|
||||||
|
<< fTexLength << ' ';
|
||||||
|
|
||||||
|
texturefile = (
|
||||||
|
m_material2 != null_handle ?
|
||||||
|
GfxRenderer.Material( m_material2 ).name :
|
||||||
|
"none" );
|
||||||
|
if( texturefile.find( szTexturePath ) == 0 ) {
|
||||||
|
// don't include 'textures/' in the path
|
||||||
|
texturefile.erase( 0, std::string{ szTexturePath }.size() );
|
||||||
|
}
|
||||||
|
Output << texturefile << ' ';
|
||||||
|
|
||||||
|
Output
|
||||||
|
<< (fTexHeight1 - fTexHeightOffset ) * ( ( iCategoryFlag & 4 ) ? -1 : 1 ) << ' '
|
||||||
|
<< fTexWidth << ' '
|
||||||
|
<< fTexSlope << ' ';
|
||||||
|
}
|
||||||
|
// path data
|
||||||
|
for( auto const &path : m_paths ) {
|
||||||
|
Output
|
||||||
|
<< path.points[ segment_data::point::start ].x << ' '
|
||||||
|
<< path.points[ segment_data::point::start ].y << ' '
|
||||||
|
<< path.points[ segment_data::point::start ].z << ' '
|
||||||
|
<< path.rolls[ 0 ] << ' '
|
||||||
|
|
||||||
|
<< path.points[ segment_data::point::control1 ].x << ' '
|
||||||
|
<< path.points[ segment_data::point::control1 ].y << ' '
|
||||||
|
<< path.points[ segment_data::point::control1 ].z << ' '
|
||||||
|
|
||||||
|
<< path.points[ segment_data::point::control2 ].x << ' '
|
||||||
|
<< path.points[ segment_data::point::control2 ].y << ' '
|
||||||
|
<< path.points[ segment_data::point::control2 ].z << ' '
|
||||||
|
|
||||||
|
<< path.points[ segment_data::point::end ].x << ' '
|
||||||
|
<< path.points[ segment_data::point::end ].y << ' '
|
||||||
|
<< path.points[ segment_data::point::end ].z << ' '
|
||||||
|
<< path.rolls[ 1 ] << ' '
|
||||||
|
|
||||||
|
<< path.radius << ' ';
|
||||||
|
}
|
||||||
|
// optional attributes
|
||||||
|
if( false == asEvent0Name.empty() ) {
|
||||||
|
Output << "event0 " << asEvent0Name << ' ';
|
||||||
|
}
|
||||||
|
if( false == asEvent1Name.empty() ) {
|
||||||
|
Output << "event1 " << asEvent1Name << ' ';
|
||||||
|
}
|
||||||
|
if( false == asEvent2Name.empty() ) {
|
||||||
|
Output << "event2 " << asEvent2Name << ' ';
|
||||||
|
}
|
||||||
|
if( false == asEventall0Name.empty() ) {
|
||||||
|
Output << "eventall0 " << asEventall0Name << ' ';
|
||||||
|
}
|
||||||
|
if( false == asEventall1Name.empty() ) {
|
||||||
|
Output << "eventall1 " << asEventall1Name << ' ';
|
||||||
|
}
|
||||||
|
if( false == asEventall2Name.empty() ) {
|
||||||
|
Output << "eventall2 " << asEventall2Name << ' ';
|
||||||
|
}
|
||||||
|
if( ( SwitchExtension )
|
||||||
|
&& ( SwitchExtension->fVelocity != -1.0 ) ) {
|
||||||
|
Output << "velocity " << SwitchExtension->fVelocity << ' ';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( fVelocity != -1.0 ) {
|
||||||
|
Output << "velocity " << fVelocity << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( pIsolated ) {
|
||||||
|
Output << "isolated " << pIsolated->asName << ' ';
|
||||||
|
}
|
||||||
|
if( fOverhead != -1.0 ) {
|
||||||
|
Output << "overhead " << fOverhead << ' ';
|
||||||
|
}
|
||||||
|
// footer
|
||||||
|
Output
|
||||||
|
<< "endtrack"
|
||||||
|
<< "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTrack::MovedUp1(float const dh)
|
void TTrack::MovedUp1(float const dh)
|
||||||
{ // poprawienie przechyłki wymaga wydłużenia podsypki
|
{ // poprawienie przechyłki wymaga wydłużenia podsypki
|
||||||
fTexHeight1 += dh;
|
fTexHeight1 += dh;
|
||||||
|
fTexHeightOffset += dh;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TTrack::VelocitySet(float v)
|
// ustawienie prędkości z ograniczeniem do pierwotnej wartości (zapisanej w scenerii)
|
||||||
{ // ustawienie prędkości z ograniczeniem do pierwotnej wartości (zapisanej w scenerii)
|
void TTrack::VelocitySet(float v) {
|
||||||
if (SwitchExtension ? SwitchExtension->fVelocity >= 0.0 : false)
|
// TBD, TODO: add a variable to preserve potential speed limit set by the track configuration on basic track pieces
|
||||||
{ // zwrotnica może mieć odgórne ograniczenie, nieprzeskakiwalne eventem
|
if( ( SwitchExtension )
|
||||||
if (v > SwitchExtension->fVelocity ? true : v < 0.0)
|
&& ( SwitchExtension->fVelocity != -1 ) ) {
|
||||||
return void(fVelocity =
|
// zwrotnica może mieć odgórne ograniczenie, nieprzeskakiwalne eventem
|
||||||
SwitchExtension->fVelocity); // maksymalnie tyle, ile było we wpisie
|
fVelocity =
|
||||||
|
min_speed<float>(
|
||||||
|
v,
|
||||||
|
( SwitchExtension->fVelocity > 0 ?
|
||||||
|
SwitchExtension->fVelocity : // positive limit applies to both switch tracks
|
||||||
|
( SwitchExtension->CurrentIndex == 0 ?
|
||||||
|
-1 : // negative limit applies only to the diverging track
|
||||||
|
-SwitchExtension->fVelocity ) ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fVelocity = v; // nie ma ograniczenia
|
||||||
}
|
}
|
||||||
fVelocity = v; // nie ma ograniczenia
|
|
||||||
};
|
};
|
||||||
|
|
||||||
double TTrack::VelocityGet()
|
double TTrack::VelocityGet()
|
||||||
@@ -2800,11 +3081,13 @@ path_table::InitTracks() {
|
|||||||
track->AssignEvents(
|
track->AssignEvents(
|
||||||
simulation::Events.FindEvent( trackname + ":event0" ),
|
simulation::Events.FindEvent( trackname + ":event0" ),
|
||||||
simulation::Events.FindEvent( trackname + ":event1" ),
|
simulation::Events.FindEvent( trackname + ":event1" ),
|
||||||
simulation::Events.FindEvent( trackname + ":event2" ) );
|
simulation::Events.FindEvent( trackname + ":event2" ),
|
||||||
|
false );
|
||||||
track->AssignallEvents(
|
track->AssignallEvents(
|
||||||
simulation::Events.FindEvent( trackname + ":eventall0" ),
|
simulation::Events.FindEvent( trackname + ":eventall0" ),
|
||||||
simulation::Events.FindEvent( trackname + ":eventall1" ),
|
simulation::Events.FindEvent( trackname + ":eventall1" ),
|
||||||
simulation::Events.FindEvent( trackname + ":eventall2" ) );
|
simulation::Events.FindEvent( trackname + ":eventall2" ),
|
||||||
|
false );
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (track->eType) {
|
switch (track->eType) {
|
||||||
@@ -2948,6 +3231,8 @@ path_table::InitTracks() {
|
|||||||
scene::node_data nodedata;
|
scene::node_data nodedata;
|
||||||
nodedata.name = isolated->asName;
|
nodedata.name = isolated->asName;
|
||||||
auto *memorycell = new TMemCell( nodedata ); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy
|
auto *memorycell = new TMemCell( nodedata ); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy
|
||||||
|
// NOTE: autogenerated cells aren't exported; they'll be autogenerated anew when exported file is loaded
|
||||||
|
memorycell->is_exportable = false;
|
||||||
simulation::Memory.insert( memorycell );
|
simulation::Memory.insert( memorycell );
|
||||||
isolated->pMemCell = memorycell; // wskaźnik komóki przekazany do odcinka izolowanego
|
isolated->pMemCell = memorycell; // wskaźnik komóki przekazany do odcinka izolowanego
|
||||||
}
|
}
|
||||||
|
|||||||
23
Track.h
23
Track.h
@@ -124,7 +124,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// trajektoria ruchu - opakowanie
|
// trajektoria ruchu - opakowanie
|
||||||
class TTrack : public editor::basic_node {
|
class TTrack : public scene::basic_node {
|
||||||
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
|
|
||||||
@@ -142,6 +142,7 @@ private:
|
|||||||
float fTexRatio1 = 1.0f; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...)
|
float fTexRatio1 = 1.0f; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...)
|
||||||
float fTexRatio2 = 1.0f; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...)
|
float fTexRatio2 = 1.0f; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...)
|
||||||
float fTexHeight1 = 0.6f; // wysokość brzegu względem trajektorii
|
float fTexHeight1 = 0.6f; // wysokość brzegu względem trajektorii
|
||||||
|
float fTexHeightOffset = 0.f; // potential adjustment to account for the path roll
|
||||||
float fTexWidth = 0.9f; // szerokość boku
|
float fTexWidth = 0.9f; // szerokość boku
|
||||||
float fTexSlope = 0.9f;
|
float fTexSlope = 0.9f;
|
||||||
|
|
||||||
@@ -152,6 +153,8 @@ private:
|
|||||||
geometryhandle_sequence Geometry1; // geometry chunks textured with texture 1
|
geometryhandle_sequence Geometry1; // geometry chunks textured with texture 1
|
||||||
geometryhandle_sequence Geometry2; // geometry chunks textured with texture 2
|
geometryhandle_sequence Geometry2; // geometry chunks textured with texture 2
|
||||||
|
|
||||||
|
std::vector<segment_data> m_paths; // source data for owned paths
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::deque<TDynamicObject *> dynamics_sequence;
|
typedef std::deque<TDynamicObject *> dynamics_sequence;
|
||||||
dynamics_sequence Dynamics;
|
dynamics_sequence Dynamics;
|
||||||
@@ -231,8 +234,8 @@ public:
|
|||||||
SwitchExtension->iRoads - 1 :
|
SwitchExtension->iRoads - 1 :
|
||||||
1 ); }
|
1 ); }
|
||||||
void Load(cParser *parser, Math3D::vector3 pOrigin);
|
void Load(cParser *parser, Math3D::vector3 pOrigin);
|
||||||
bool AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
|
bool AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2, bool const Explicit = true );
|
||||||
bool AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
|
bool AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2, bool const Explicit = true );
|
||||||
bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus);
|
bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus);
|
||||||
bool CheckDynamicObject(TDynamicObject *Dynamic);
|
bool CheckDynamicObject(TDynamicObject *Dynamic);
|
||||||
bool AddDynamicObject(TDynamicObject *Dynamic);
|
bool AddDynamicObject(TDynamicObject *Dynamic);
|
||||||
@@ -270,10 +273,16 @@ public:
|
|||||||
double VelocityGet();
|
double VelocityGet();
|
||||||
void ConnectionsLog();
|
void ConnectionsLog();
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
// calculates path's bounding radius
|
// radius() subclass details, calculates node's bounding radius
|
||||||
void
|
float radius_();
|
||||||
radius_();
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void serialize_( std::ostream &Output ) const;
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void deserialize_( std::istream &Input );
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void export_as_text_( std::ostream &Output ) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
84
Traction.cpp
84
Traction.cpp
@@ -529,18 +529,6 @@ double TTraction::VoltageGet(double u, double i)
|
|||||||
return 0.0; // gdy nie podłączony wcale?
|
return 0.0; // gdy nie podłączony wcale?
|
||||||
};
|
};
|
||||||
|
|
||||||
// calculates path's bounding radius
|
|
||||||
void
|
|
||||||
TTraction::radius_() {
|
|
||||||
|
|
||||||
auto const points = endpoints();
|
|
||||||
for( auto &point : points ) {
|
|
||||||
m_area.radius = std::max(
|
|
||||||
m_area.radius,
|
|
||||||
static_cast<float>( glm::length( m_area.center - point ) ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3
|
glm::vec3
|
||||||
TTraction::wire_color() const {
|
TTraction::wire_color() const {
|
||||||
|
|
||||||
@@ -580,6 +568,7 @@ TTraction::wire_color() const {
|
|||||||
color.r *= Global.DayLight.ambient[ 0 ];
|
color.r *= Global.DayLight.ambient[ 0 ];
|
||||||
color.g *= Global.DayLight.ambient[ 1 ];
|
color.g *= Global.DayLight.ambient[ 1 ];
|
||||||
color.b *= Global.DayLight.ambient[ 2 ];
|
color.b *= Global.DayLight.ambient[ 2 ];
|
||||||
|
color *= 0.5f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// tymczasowo pokazanie zasilanych odcinków
|
// tymczasowo pokazanie zasilanych odcinków
|
||||||
@@ -675,6 +664,77 @@ TTraction::wire_color() const {
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// radius() subclass details, calculates node's bounding radius
|
||||||
|
float
|
||||||
|
TTraction::radius_() {
|
||||||
|
|
||||||
|
auto const points { endpoints() };
|
||||||
|
auto radius { 0.f };
|
||||||
|
for( auto &point : points ) {
|
||||||
|
radius = std::max(
|
||||||
|
radius,
|
||||||
|
static_cast<float>( glm::length( m_area.center - point ) ) );
|
||||||
|
}
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void
|
||||||
|
TTraction::serialize_( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void
|
||||||
|
TTraction::deserialize_( std::istream &Input ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
TTraction::export_as_text_( std::ostream &Output ) const {
|
||||||
|
// header
|
||||||
|
Output << "traction ";
|
||||||
|
// basic attributes
|
||||||
|
Output
|
||||||
|
<< asPowerSupplyName << ' '
|
||||||
|
<< NominalVoltage << ' '
|
||||||
|
<< MaxCurrent << ' '
|
||||||
|
<< ( fResistivity * 1000 ) << ' '
|
||||||
|
<< (
|
||||||
|
Material == 2 ? "al" :
|
||||||
|
Material == 0 ? "none" :
|
||||||
|
"cu" ) << ' '
|
||||||
|
<< WireThickness << ' '
|
||||||
|
<< DamageFlag << ' ';
|
||||||
|
// path data
|
||||||
|
Output
|
||||||
|
<< pPoint1.x << ' ' << pPoint1.y << ' ' << pPoint1.z << ' '
|
||||||
|
<< pPoint2.x << ' ' << pPoint2.y << ' ' << pPoint2.z << ' '
|
||||||
|
<< pPoint3.x << ' ' << pPoint3.y << ' ' << pPoint3.z << ' '
|
||||||
|
<< pPoint4.x << ' ' << pPoint4.y << ' ' << pPoint4.z << ' ';
|
||||||
|
// minimum height
|
||||||
|
Output << ( ( pPoint3.y - pPoint1.y + pPoint4.y - pPoint2.y ) * 0.5 - fHeightDifference ) << ' ';
|
||||||
|
// segment length
|
||||||
|
Output << static_cast<int>( iNumSections ? glm::length( pPoint1 - pPoint2 ) / iNumSections : 0.0 ) << ' ';
|
||||||
|
// wire data
|
||||||
|
Output
|
||||||
|
<< Wires << ' '
|
||||||
|
<< WireOffset << ' ';
|
||||||
|
// visibility
|
||||||
|
// NOTE: 'invis' would be less wrong than 'unvis', but potentially incompatible with old 3rd party tools
|
||||||
|
Output << ( m_visible ? "vis" : "unvis" ) << ' ';
|
||||||
|
// optional attributes
|
||||||
|
if( false == asParallel.empty() ) {
|
||||||
|
Output << "parallel " << asParallel << ' ';
|
||||||
|
}
|
||||||
|
// footer
|
||||||
|
Output
|
||||||
|
<< "endtraction"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// legacy method, initializes traction after deserialization from scenario file
|
// legacy method, initializes traction after deserialization from scenario file
|
||||||
|
|||||||
17
Traction.h
17
Traction.h
@@ -18,7 +18,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
class TTractionPowerSource;
|
class TTractionPowerSource;
|
||||||
|
|
||||||
class TTraction : public editor::basic_node {
|
class TTraction : public scene::basic_node {
|
||||||
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
|
|
||||||
@@ -73,13 +73,18 @@ class TTraction : public editor::basic_node {
|
|||||||
void PowerSet(TTractionPowerSource *ps);
|
void PowerSet(TTractionPowerSource *ps);
|
||||||
double VoltageGet(double u, double i);
|
double VoltageGet(double u, double i);
|
||||||
|
|
||||||
protected:
|
|
||||||
// calculates piece's bounding radius
|
|
||||||
void
|
|
||||||
radius_();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// methods
|
||||||
glm::vec3 wire_color() const;
|
glm::vec3 wire_color() const;
|
||||||
|
// radius() subclass details, calculates node's bounding radius
|
||||||
|
float radius_();
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void serialize_( std::ostream &Output ) const;
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void deserialize_( std::istream &Input );
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void export_as_text_( std::ostream &Output ) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,52 @@ void TTractionPowerSource::PowerSet(TTractionPowerSource *ps)
|
|||||||
// else ErrorLog("nie może być więcej punktów zasilania niż dwa");
|
// else ErrorLog("nie może być więcej punktów zasilania niż dwa");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void
|
||||||
|
TTractionPowerSource::serialize_( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void
|
||||||
|
TTractionPowerSource::deserialize_( std::istream &Input ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
TTractionPowerSource::export_as_text_( std::ostream &Output ) const {
|
||||||
|
// header
|
||||||
|
Output << "tractionpowersource ";
|
||||||
|
// placement
|
||||||
|
Output
|
||||||
|
<< location().x << ' '
|
||||||
|
<< location().y << ' '
|
||||||
|
<< location().z << ' ';
|
||||||
|
// basic attributes
|
||||||
|
Output
|
||||||
|
<< NominalVoltage << ' '
|
||||||
|
<< VoltageFrequency << ' '
|
||||||
|
<< InternalRes << ' '
|
||||||
|
<< MaxOutputCurrent << ' '
|
||||||
|
<< FastFuseTimeOut << ' '
|
||||||
|
<< FastFuseRepetition << ' '
|
||||||
|
<< SlowFuseTimeOut << ' ';
|
||||||
|
// optional attributes
|
||||||
|
if( true == Recuperation ) {
|
||||||
|
Output << "recuperation ";
|
||||||
|
}
|
||||||
|
if( true == bSection ) {
|
||||||
|
Output << "section ";
|
||||||
|
}
|
||||||
|
// footer
|
||||||
|
Output
|
||||||
|
<< "end"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// legacy method, calculates changes in simulation state over specified time
|
// legacy method, calculates changes in simulation state over specified time
|
||||||
|
|||||||
@@ -13,9 +13,33 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "scenenode.h"
|
#include "scenenode.h"
|
||||||
#include "names.h"
|
#include "names.h"
|
||||||
|
|
||||||
class TTractionPowerSource : public editor::basic_node {
|
class TTractionPowerSource : public scene::basic_node {
|
||||||
|
|
||||||
private:
|
public:
|
||||||
|
// constructor
|
||||||
|
TTractionPowerSource( scene::node_data const &Nodedata );
|
||||||
|
// methods
|
||||||
|
void Init(double const u, double const i);
|
||||||
|
bool Load(cParser *parser);
|
||||||
|
bool Update(double dt);
|
||||||
|
double CurrentGet(double res);
|
||||||
|
void VoltageSet(double const v) {
|
||||||
|
NominalVoltage = v; };
|
||||||
|
void PowerSet(TTractionPowerSource *ps);
|
||||||
|
// members
|
||||||
|
TTractionPowerSource *psNode[ 2 ] = { nullptr, nullptr }; // zasilanie na końcach dla sekcji
|
||||||
|
bool bSection = false; // czy jest sekcją
|
||||||
|
|
||||||
|
private:
|
||||||
|
// methods
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
void serialize_( std::ostream &Output ) const;
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
void deserialize_( std::istream &Input );
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void export_as_text_( std::ostream &Output ) const;
|
||||||
|
|
||||||
|
// members
|
||||||
double NominalVoltage = 0.0;
|
double NominalVoltage = 0.0;
|
||||||
double VoltageFrequency = 0.0;
|
double VoltageFrequency = 0.0;
|
||||||
double InternalRes = 0.2;
|
double InternalRes = 0.2;
|
||||||
@@ -34,20 +58,6 @@ class TTractionPowerSource : public editor::basic_node {
|
|||||||
double FuseTimer = 0.0;
|
double FuseTimer = 0.0;
|
||||||
int FuseCounter = 0;
|
int FuseCounter = 0;
|
||||||
|
|
||||||
public:
|
|
||||||
// zmienne publiczne
|
|
||||||
TTractionPowerSource *psNode[ 2 ] = { nullptr, nullptr }; // zasilanie na końcach dla sekcji
|
|
||||||
bool bSection = false; // czy jest sekcją
|
|
||||||
|
|
||||||
TTractionPowerSource( scene::node_data const &Nodedata );
|
|
||||||
|
|
||||||
void Init(double const u, double const i);
|
|
||||||
bool Load(cParser *parser);
|
|
||||||
bool Update(double dt);
|
|
||||||
double CurrentGet(double res);
|
|
||||||
void VoltageSet(double const v) {
|
|
||||||
NominalVoltage = v; };
|
|
||||||
void PowerSet(TTractionPowerSource *ps);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
84
World.cpp
84
World.cpp
@@ -311,49 +311,47 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
|||||||
|
|
||||||
void TWorld::OnKeyDown(int cKey) {
|
void TWorld::OnKeyDown(int cKey) {
|
||||||
// dump keypress info in the log
|
// dump keypress info in the log
|
||||||
if( !Global.iPause ) {
|
// podczas pauzy klawisze nie działają
|
||||||
// podczas pauzy klawisze nie działają
|
std::string keyinfo;
|
||||||
std::string keyinfo;
|
auto keyname = glfwGetKeyName( cKey, 0 );
|
||||||
auto keyname = glfwGetKeyName( cKey, 0 );
|
if( keyname != nullptr ) {
|
||||||
if( keyname != nullptr ) {
|
keyinfo += std::string( keyname );
|
||||||
keyinfo += std::string( keyname );
|
}
|
||||||
}
|
else {
|
||||||
else {
|
switch( cKey ) {
|
||||||
switch( cKey ) {
|
|
||||||
|
|
||||||
case GLFW_KEY_SPACE: { keyinfo += "Space"; break; }
|
case GLFW_KEY_SPACE: { keyinfo += "Space"; break; }
|
||||||
case GLFW_KEY_ENTER: { keyinfo += "Enter"; break; }
|
case GLFW_KEY_ENTER: { keyinfo += "Enter"; break; }
|
||||||
case GLFW_KEY_ESCAPE: { keyinfo += "Esc"; break; }
|
case GLFW_KEY_ESCAPE: { keyinfo += "Esc"; break; }
|
||||||
case GLFW_KEY_TAB: { keyinfo += "Tab"; break; }
|
case GLFW_KEY_TAB: { keyinfo += "Tab"; break; }
|
||||||
case GLFW_KEY_INSERT: { keyinfo += "Insert"; break; }
|
case GLFW_KEY_INSERT: { keyinfo += "Insert"; break; }
|
||||||
case GLFW_KEY_DELETE: { keyinfo += "Delete"; break; }
|
case GLFW_KEY_DELETE: { keyinfo += "Delete"; break; }
|
||||||
case GLFW_KEY_HOME: { keyinfo += "Home"; break; }
|
case GLFW_KEY_HOME: { keyinfo += "Home"; break; }
|
||||||
case GLFW_KEY_END: { keyinfo += "End"; break; }
|
case GLFW_KEY_END: { keyinfo += "End"; break; }
|
||||||
case GLFW_KEY_F1: { keyinfo += "F1"; break; }
|
case GLFW_KEY_F1: { keyinfo += "F1"; break; }
|
||||||
case GLFW_KEY_F2: { keyinfo += "F2"; break; }
|
case GLFW_KEY_F2: { keyinfo += "F2"; break; }
|
||||||
case GLFW_KEY_F3: { keyinfo += "F3"; break; }
|
case GLFW_KEY_F3: { keyinfo += "F3"; break; }
|
||||||
case GLFW_KEY_F4: { keyinfo += "F4"; break; }
|
case GLFW_KEY_F4: { keyinfo += "F4"; break; }
|
||||||
case GLFW_KEY_F5: { keyinfo += "F5"; break; }
|
case GLFW_KEY_F5: { keyinfo += "F5"; break; }
|
||||||
case GLFW_KEY_F6: { keyinfo += "F6"; break; }
|
case GLFW_KEY_F6: { keyinfo += "F6"; break; }
|
||||||
case GLFW_KEY_F7: { keyinfo += "F7"; break; }
|
case GLFW_KEY_F7: { keyinfo += "F7"; break; }
|
||||||
case GLFW_KEY_F8: { keyinfo += "F8"; break; }
|
case GLFW_KEY_F8: { keyinfo += "F8"; break; }
|
||||||
case GLFW_KEY_F9: { keyinfo += "F9"; break; }
|
case GLFW_KEY_F9: { keyinfo += "F9"; break; }
|
||||||
case GLFW_KEY_F10: { keyinfo += "F10"; break; }
|
case GLFW_KEY_F10: { keyinfo += "F10"; break; }
|
||||||
case GLFW_KEY_F11: { keyinfo += "F11"; break; }
|
case GLFW_KEY_F11: { keyinfo += "F11"; break; }
|
||||||
case GLFW_KEY_F12: { keyinfo += "F12"; break; }
|
case GLFW_KEY_F12: { keyinfo += "F12"; break; }
|
||||||
case GLFW_KEY_PAUSE: { keyinfo += "Pause"; break; }
|
case GLFW_KEY_PAUSE: { keyinfo += "Pause"; break; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if( keyinfo.empty() == false ) {
|
}
|
||||||
|
if( keyinfo.empty() == false ) {
|
||||||
|
|
||||||
std::string keymodifiers;
|
std::string keymodifiers;
|
||||||
if( Global.shiftState )
|
if( Global.shiftState )
|
||||||
keymodifiers += "[Shift]+";
|
keymodifiers += "[Shift]+";
|
||||||
if( Global.ctrlState )
|
if( Global.ctrlState )
|
||||||
keymodifiers += "[Ctrl]+";
|
keymodifiers += "[Ctrl]+";
|
||||||
|
|
||||||
WriteLog( "Key pressed: " + keymodifiers + "[" + keyinfo + "]" );
|
WriteLog( "Key pressed: " + keymodifiers + "[" + keyinfo + "]" );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// actual key processing
|
// actual key processing
|
||||||
@@ -504,6 +502,14 @@ void TWorld::OnKeyDown(int cKey) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GLFW_KEY_F11: {
|
||||||
|
// scenery export
|
||||||
|
if( Global.ctrlState
|
||||||
|
&& Global.shiftState ) {
|
||||||
|
simulation::State.export_as_text( Global.SceneryFile );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GLFW_KEY_F12: {
|
case GLFW_KEY_F12: {
|
||||||
// quick debug mode toggle
|
// quick debug mode toggle
|
||||||
if( Global.ctrlState
|
if( Global.ctrlState
|
||||||
|
|||||||
35
scene.cpp
35
scene.cpp
@@ -228,6 +228,17 @@ basic_cell::deserialize( std::istream &Input ) {
|
|||||||
|| ( false == m_lines.empty() ) );
|
|| ( false == m_lines.empty() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sends content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
basic_cell::export_as_text( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
// text format export dumps only relevant basic objects
|
||||||
|
// sounds
|
||||||
|
for( auto const *sound : m_sounds ) {
|
||||||
|
sound->export_as_text( Output );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// adds provided shape to the cell
|
// adds provided shape to the cell
|
||||||
void
|
void
|
||||||
basic_cell::insert( shape_node Shape ) {
|
basic_cell::insert( shape_node Shape ) {
|
||||||
@@ -530,7 +541,7 @@ basic_cell::create_geometry( gfx::geometrybank_handle const &Bank ) {
|
|||||||
|
|
||||||
// adjusts cell bounding area to enclose specified node
|
// adjusts cell bounding area to enclose specified node
|
||||||
void
|
void
|
||||||
basic_cell::enclose_area( editor::basic_node *Node ) {
|
basic_cell::enclose_area( scene::basic_node *Node ) {
|
||||||
|
|
||||||
m_area.radius = std::max(
|
m_area.radius = std::max(
|
||||||
m_area.radius,
|
m_area.radius,
|
||||||
@@ -645,6 +656,16 @@ basic_section::deserialize( std::istream &Input ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sends content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
basic_section::export_as_text( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
// text format export dumps only relevant basic objects from non-empty cells
|
||||||
|
for( auto const &cell : m_cells ) {
|
||||||
|
cell.export_as_text( Output );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// adds provided shape to the section
|
// adds provided shape to the section
|
||||||
void
|
void
|
||||||
basic_section::insert( shape_node Shape ) {
|
basic_section::insert( shape_node Shape ) {
|
||||||
@@ -949,6 +970,18 @@ basic_region::deserialize( std::string const &Scenariofile ) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sends content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
basic_region::export_as_text( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
for( auto *section : m_sections ) {
|
||||||
|
// text format export dumps only relevant basic objects from non-empty sections
|
||||||
|
if( section != nullptr ) {
|
||||||
|
section->export_as_text( Output );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// legacy method, links specified path piece with potential neighbours
|
// legacy method, links specified path piece with potential neighbours
|
||||||
void
|
void
|
||||||
basic_region::TrackJoin( TTrack *Track ) {
|
basic_region::TrackJoin( TTrack *Track ) {
|
||||||
|
|||||||
11
scene.h
11
scene.h
@@ -88,6 +88,9 @@ public:
|
|||||||
// restores content of the class from provided stream
|
// restores content of the class from provided stream
|
||||||
void
|
void
|
||||||
deserialize( std::istream &Input );
|
deserialize( std::istream &Input );
|
||||||
|
// sends content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
export_as_text( std::ostream &Output ) const;
|
||||||
// adds provided shape to the cell
|
// adds provided shape to the cell
|
||||||
void
|
void
|
||||||
insert( shape_node Shape );
|
insert( shape_node Shape );
|
||||||
@@ -149,7 +152,7 @@ private:
|
|||||||
using eventlauncher_sequence = std::vector<TEventLauncher *>;
|
using eventlauncher_sequence = std::vector<TEventLauncher *>;
|
||||||
// methods
|
// methods
|
||||||
void
|
void
|
||||||
enclose_area( editor::basic_node *Node );
|
enclose_area( scene::basic_node *Node );
|
||||||
// members
|
// members
|
||||||
scene::bounding_area m_area { glm::dvec3(), static_cast<float>( 0.5 * M_SQRT2 * EU07_CELLSIZE ) };
|
scene::bounding_area m_area { glm::dvec3(), static_cast<float>( 0.5 * M_SQRT2 * EU07_CELLSIZE ) };
|
||||||
bool m_active { false }; // whether the cell holds any actual data
|
bool m_active { false }; // whether the cell holds any actual data
|
||||||
@@ -199,6 +202,9 @@ public:
|
|||||||
// restores content of the class from provided stream
|
// restores content of the class from provided stream
|
||||||
void
|
void
|
||||||
deserialize( std::istream &Input );
|
deserialize( std::istream &Input );
|
||||||
|
// sends content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
export_as_text( std::ostream &Output ) const;
|
||||||
// adds provided shape to the section
|
// adds provided shape to the section
|
||||||
void
|
void
|
||||||
insert( shape_node Shape );
|
insert( shape_node Shape );
|
||||||
@@ -289,6 +295,9 @@ public:
|
|||||||
// restores content of the class from file with specified name. returns: true on success, false otherwise
|
// restores content of the class from file with specified name. returns: true on success, false otherwise
|
||||||
bool
|
bool
|
||||||
deserialize( std::string const &Scenariofile );
|
deserialize( std::string const &Scenariofile );
|
||||||
|
// sends content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
export_as_text( std::ostream &Output ) const;
|
||||||
// legacy method, links specified path piece with potential neighbours
|
// legacy method, links specified path piece with potential neighbours
|
||||||
void
|
void
|
||||||
TrackJoin( TTrack *Track );
|
TrackJoin( TTrack *Track );
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ shape_node::deserialize( std::istream &Input ) {
|
|||||||
|
|
||||||
// restores content of the node from provided input stream
|
// restores content of the node from provided input stream
|
||||||
shape_node &
|
shape_node &
|
||||||
shape_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
|
shape_node::import( cParser &Input, scene::node_data const &Nodedata ) {
|
||||||
|
|
||||||
// import common data
|
// import common data
|
||||||
m_name = Nodedata.name;
|
m_name = Nodedata.name;
|
||||||
@@ -523,7 +523,7 @@ lines_node::deserialize( std::istream &Input ) {
|
|||||||
|
|
||||||
// restores content of the node from provded input stream
|
// restores content of the node from provded input stream
|
||||||
lines_node &
|
lines_node &
|
||||||
lines_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
|
lines_node::import( cParser &Input, scene::node_data const &Nodedata ) {
|
||||||
|
|
||||||
// import common data
|
// import common data
|
||||||
m_name = Nodedata.name;
|
m_name = Nodedata.name;
|
||||||
@@ -684,12 +684,9 @@ memory_node::deserialize( cParser &Input, node_data const &Nodedata ) {
|
|||||||
memorycell.Load( &Input );
|
memorycell.Load( &Input );
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
} // scene
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace editor {
|
|
||||||
|
|
||||||
basic_node::basic_node( scene::node_data const &Nodedata ) :
|
basic_node::basic_node( scene::node_data const &Nodedata ) :
|
||||||
m_name( Nodedata.name )
|
m_name( Nodedata.name )
|
||||||
{
|
{
|
||||||
@@ -700,23 +697,69 @@ basic_node::basic_node( scene::node_data const &Nodedata ) :
|
|||||||
std::numeric_limits<double>::max() );
|
std::numeric_limits<double>::max() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sends content of the class to provided stream
|
||||||
|
void
|
||||||
|
basic_node::serialize( std::ostream &Output ) const {
|
||||||
|
// bounding area
|
||||||
|
m_area.serialize( Output );
|
||||||
|
// visibility
|
||||||
|
sn_utils::ls_float64( Output, m_rangesquaredmin );
|
||||||
|
sn_utils::ls_float64( Output, m_rangesquaredmax );
|
||||||
|
sn_utils::s_bool( Output, m_visible );
|
||||||
|
// name
|
||||||
|
sn_utils::s_str( Output, m_name );
|
||||||
|
// template method implementation
|
||||||
|
serialize_( Output );
|
||||||
|
}
|
||||||
|
|
||||||
|
// restores content of the class from provided stream
|
||||||
|
void
|
||||||
|
basic_node::deserialize( std::istream &Input ) {
|
||||||
|
// bounding area
|
||||||
|
m_area.deserialize( Input );
|
||||||
|
// visibility
|
||||||
|
m_rangesquaredmin = sn_utils::ld_float64( Input );
|
||||||
|
m_rangesquaredmax = sn_utils::ld_float64( Input );
|
||||||
|
m_visible = sn_utils::d_bool( Input );
|
||||||
|
// name
|
||||||
|
m_name = sn_utils::d_str( Input );
|
||||||
|
// template method implementation
|
||||||
|
deserialize_( Input );
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
basic_node::export_as_text( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
Output
|
||||||
|
// header
|
||||||
|
<< "node"
|
||||||
|
// visibility
|
||||||
|
<< ' ' << ( m_rangesquaredmax < std::numeric_limits<double>::max() ? std::sqrt( m_rangesquaredmax ) : -1 )
|
||||||
|
<< ' ' << std::sqrt( m_rangesquaredmin )
|
||||||
|
// name
|
||||||
|
<< ' ' << m_name << ' ';
|
||||||
|
// template method implementation
|
||||||
|
export_as_text_( Output );
|
||||||
|
}
|
||||||
|
|
||||||
float const &
|
float const &
|
||||||
basic_node::radius() {
|
basic_node::radius() {
|
||||||
|
|
||||||
if( m_area.radius == -1.0 ) {
|
if( m_area.radius == -1.0 ) {
|
||||||
// calculate if needed
|
// calculate if needed
|
||||||
radius_();
|
m_area.radius = radius_();
|
||||||
}
|
}
|
||||||
return m_area.radius;
|
return m_area.radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
// radius() subclass details, calculates node's bounding radius
|
// radius() subclass details, calculates node's bounding radius
|
||||||
// by default nodes are 'virtual don't extend from their center point
|
// by default nodes are 'virtual don't extend from their center point
|
||||||
void
|
float
|
||||||
basic_node::radius_() {
|
basic_node::radius_() {
|
||||||
|
|
||||||
m_area.radius = 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // editor
|
} // scene
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
34
scenenode.h
34
scenenode.h
@@ -112,7 +112,7 @@ public:
|
|||||||
deserialize( std::istream &Input );
|
deserialize( std::istream &Input );
|
||||||
// restores content of the node from provided input stream
|
// restores content of the node from provided input stream
|
||||||
shape_node &
|
shape_node &
|
||||||
deserialize( cParser &Input, scene::node_data const &Nodedata );
|
import( cParser &Input, scene::node_data const &Nodedata );
|
||||||
// imports data from provided submodel
|
// imports data from provided submodel
|
||||||
shape_node &
|
shape_node &
|
||||||
convert( TSubModel const *Submodel );
|
convert( TSubModel const *Submodel );
|
||||||
@@ -201,7 +201,7 @@ public:
|
|||||||
deserialize( std::istream &Input );
|
deserialize( std::istream &Input );
|
||||||
// restores content of the node from provided input stream
|
// restores content of the node from provided input stream
|
||||||
lines_node &
|
lines_node &
|
||||||
deserialize( cParser &Input, scene::node_data const &Nodedata );
|
import( cParser &Input, scene::node_data const &Nodedata );
|
||||||
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
||||||
bool
|
bool
|
||||||
merge( lines_node &Lines );
|
merge( lines_node &Lines );
|
||||||
@@ -295,12 +295,9 @@ private:
|
|||||||
TTrack * m_path;
|
TTrack * m_path;
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
} // scene
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace editor {
|
|
||||||
|
|
||||||
// base interface for nodes which can be actvated in scenario editor
|
// base interface for nodes which can be actvated in scenario editor
|
||||||
struct basic_node {
|
struct basic_node {
|
||||||
|
|
||||||
@@ -310,6 +307,15 @@ public:
|
|||||||
// destructor
|
// destructor
|
||||||
virtual ~basic_node() = default;
|
virtual ~basic_node() = default;
|
||||||
// methods
|
// methods
|
||||||
|
// sends content of the class to provided stream
|
||||||
|
void
|
||||||
|
serialize( std::ostream &Output ) const;
|
||||||
|
// restores content of the class from provided stream
|
||||||
|
void
|
||||||
|
deserialize( std::istream &Input );
|
||||||
|
// sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
export_as_text( std::ostream &Output ) const;
|
||||||
std::string const &
|
std::string const &
|
||||||
name() const;
|
name() const;
|
||||||
void
|
void
|
||||||
@@ -324,15 +330,23 @@ public:
|
|||||||
visible() const;
|
visible() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// methods
|
|
||||||
// radius() subclass details, calculates node's bounding radius
|
|
||||||
virtual void radius_();
|
|
||||||
// members
|
// members
|
||||||
scene::bounding_area m_area;
|
scene::bounding_area m_area;
|
||||||
bool m_visible { true };
|
|
||||||
double m_rangesquaredmin { 0.0 }; // visibility range, min
|
double m_rangesquaredmin { 0.0 }; // visibility range, min
|
||||||
double m_rangesquaredmax { 0.0 }; // visibility range, max
|
double m_rangesquaredmax { 0.0 }; // visibility range, max
|
||||||
|
bool m_visible { true }; // visibility flag
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// methods
|
||||||
|
// radius() subclass details, calculates node's bounding radius
|
||||||
|
virtual float radius_();
|
||||||
|
// serialize() subclass details, sends content of the subclass to provided stream
|
||||||
|
virtual void serialize_( std::ostream &Output ) const = 0;
|
||||||
|
// deserialize() subclass details, restores content of the subclass from provided stream
|
||||||
|
virtual void deserialize_( std::istream &Input ) = 0;
|
||||||
|
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
|
||||||
|
virtual void export_as_text_( std::ostream &Output ) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
@@ -365,6 +379,6 @@ basic_node::visible() const {
|
|||||||
return m_visible;
|
return m_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // editor
|
} // scene
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "uilayer.h"
|
#include "uilayer.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
|
||||||
|
|
||||||
namespace simulation {
|
namespace simulation {
|
||||||
|
|
||||||
state_manager State;
|
state_manager State;
|
||||||
@@ -57,8 +58,6 @@ state_manager::deserialize( std::string const &Scenariofile ) {
|
|||||||
// as long as the scenario file wasn't rainsted-created base file override
|
// as long as the scenario file wasn't rainsted-created base file override
|
||||||
Region->serialize( Scenariofile );
|
Region->serialize( Scenariofile );
|
||||||
}
|
}
|
||||||
|
|
||||||
Global.iPause &= ~0x10; // koniec pauzy wczytywania
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +408,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
|||||||
if( false == Scratchpad.binary.terrain ) {
|
if( false == Scratchpad.binary.terrain ) {
|
||||||
|
|
||||||
simulation::Region->insert_shape(
|
simulation::Region->insert_shape(
|
||||||
scene::shape_node().deserialize(
|
scene::shape_node().import(
|
||||||
Input, nodedata ),
|
Input, nodedata ),
|
||||||
Scratchpad,
|
Scratchpad,
|
||||||
true );
|
true );
|
||||||
@@ -426,7 +425,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
|||||||
if( false == Scratchpad.binary.terrain ) {
|
if( false == Scratchpad.binary.terrain ) {
|
||||||
|
|
||||||
simulation::Region->insert_lines(
|
simulation::Region->insert_lines(
|
||||||
scene::lines_node().deserialize(
|
scene::lines_node().import(
|
||||||
Input, nodedata ),
|
Input, nodedata ),
|
||||||
Scratchpad );
|
Scratchpad );
|
||||||
}
|
}
|
||||||
@@ -439,7 +438,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
|||||||
|
|
||||||
auto *memorycell { deserialize_memorycell( Input, Scratchpad, nodedata ) };
|
auto *memorycell { deserialize_memorycell( Input, Scratchpad, nodedata ) };
|
||||||
if( false == simulation::Memory.insert( memorycell ) ) {
|
if( false == simulation::Memory.insert( memorycell ) ) {
|
||||||
ErrorLog( "Bad scenario: memory cell with duplicate name \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
ErrorLog( "Bad scenario: memory memorycell with duplicate name \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
// TODO: implement this
|
// TODO: implement this
|
||||||
@@ -897,6 +896,65 @@ state_manager::transform( glm::dvec3 Location, scene::scratch_data const &Scratc
|
|||||||
return Location;
|
return Location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// stores class data in specified file, in legacy (text) format
|
||||||
|
void
|
||||||
|
state_manager::export_as_text( std::string const &Scenariofile ) const {
|
||||||
|
|
||||||
|
if( Scenariofile == "$.scn" ) {
|
||||||
|
ErrorLog( "Bad file: scenery export not supported for file \"$.scn\"" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WriteLog( "Scenery data export in progress..." );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto filename { Scenariofile };
|
||||||
|
while( filename[ 0 ] == '$' ) {
|
||||||
|
// trim leading $ char rainsted utility may add to the base name for modified .scn files
|
||||||
|
filename.erase( 0, 1 );
|
||||||
|
}
|
||||||
|
erase_extension( filename );
|
||||||
|
filename = Global.asCurrentSceneryPath + filename + "_export";
|
||||||
|
|
||||||
|
std::ofstream scmfile { filename + ".scm" };
|
||||||
|
// tracks
|
||||||
|
scmfile << "// paths\n";
|
||||||
|
for( auto const *path : Paths.sequence() ) {
|
||||||
|
path->export_as_text( scmfile );
|
||||||
|
}
|
||||||
|
// traction
|
||||||
|
scmfile << "// traction\n";
|
||||||
|
for( auto const *traction : Traction.sequence() ) {
|
||||||
|
traction->export_as_text( scmfile );
|
||||||
|
}
|
||||||
|
// power grid
|
||||||
|
scmfile << "// traction power sources\n";
|
||||||
|
for( auto const *powersource : Powergrid.sequence() ) {
|
||||||
|
powersource->export_as_text( scmfile );
|
||||||
|
}
|
||||||
|
// models
|
||||||
|
scmfile << "// instanced models\n";
|
||||||
|
for( auto const *instance : Instances.sequence() ) {
|
||||||
|
instance->export_as_text( scmfile );
|
||||||
|
}
|
||||||
|
// sounds
|
||||||
|
scmfile << "// sounds\n";
|
||||||
|
Region->export_as_text( scmfile );
|
||||||
|
|
||||||
|
std::ofstream ctrfile { filename + ".ctr" };
|
||||||
|
// mem cells
|
||||||
|
ctrfile << "// memory cells\n";
|
||||||
|
for( auto const *memorycell : Memory.sequence() ) {
|
||||||
|
if( true == memorycell->is_exportable ) {
|
||||||
|
memorycell->export_as_text( ctrfile );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// events
|
||||||
|
Events.export_as_text( ctrfile );
|
||||||
|
|
||||||
|
WriteLog( "Scenery data export done." );
|
||||||
|
}
|
||||||
|
|
||||||
} // simulation
|
} // simulation
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ public:
|
|||||||
update( double Deltatime, int Iterationcount );
|
update( double Deltatime, int Iterationcount );
|
||||||
bool
|
bool
|
||||||
deserialize( std::string const &Scenariofile );
|
deserialize( std::string const &Scenariofile );
|
||||||
|
// stores class data in specified file, in legacy (text) format
|
||||||
|
void
|
||||||
|
export_as_text( std::string const &Scenariofile ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// methods
|
// methods
|
||||||
@@ -69,6 +72,7 @@ private:
|
|||||||
void skip_until( cParser &Input, std::string const &Token );
|
void skip_until( cParser &Input, std::string const &Token );
|
||||||
// transforms provided location by specifed rotation and offset
|
// transforms provided location by specifed rotation and offset
|
||||||
glm::dvec3 transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad );
|
glm::dvec3 transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern state_manager State;
|
extern state_manager State;
|
||||||
|
|||||||
37
sound.cpp
37
sound.cpp
@@ -293,6 +293,43 @@ sound_source::deserialize_soundset( cParser &Input ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sends content of the class in legacy (text) format to provided stream
|
||||||
|
// NOTE: currently exports only the main sound
|
||||||
|
void
|
||||||
|
sound_source::export_as_text( std::ostream &Output ) const {
|
||||||
|
|
||||||
|
if( sound( sound_id::main ).buffer == null_handle ) { return; }
|
||||||
|
|
||||||
|
// generic node header
|
||||||
|
Output
|
||||||
|
<< "node "
|
||||||
|
// visibility
|
||||||
|
<< m_range << ' '
|
||||||
|
<< 0 << ' '
|
||||||
|
// name
|
||||||
|
<< m_name << ' ';
|
||||||
|
// sound node header
|
||||||
|
Output
|
||||||
|
<< "sound ";
|
||||||
|
// location
|
||||||
|
Output
|
||||||
|
<< m_offset.x << ' '
|
||||||
|
<< m_offset.y << ' '
|
||||||
|
<< m_offset.z << ' ';
|
||||||
|
// sound data
|
||||||
|
auto soundfile { audio::renderer.buffer( sound( sound_id::main ).buffer ).name };
|
||||||
|
if( soundfile.find( szSoundPath ) == 0 ) {
|
||||||
|
// don't include 'sounds/' in the path
|
||||||
|
soundfile.erase( 0, std::string{ szSoundPath }.size() );
|
||||||
|
}
|
||||||
|
Output
|
||||||
|
<< soundfile << ' ';
|
||||||
|
// footer
|
||||||
|
Output
|
||||||
|
<< "endsound"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
// copies list of sounds from provided source
|
// copies list of sounds from provided source
|
||||||
sound_source &
|
sound_source &
|
||||||
sound_source::copy_sounds( sound_source const &Source ) {
|
sound_source::copy_sounds( sound_source const &Source ) {
|
||||||
|
|||||||
3
sound.h
3
sound.h
@@ -60,6 +60,9 @@ public:
|
|||||||
deserialize( cParser &Input, sound_type const Legacytype, int const Legacyparameters = 0, int const Chunkrange = 100 );
|
deserialize( cParser &Input, sound_type const Legacytype, int const Legacyparameters = 0, int const Chunkrange = 100 );
|
||||||
sound_source &
|
sound_source &
|
||||||
deserialize( std::string const &Input, sound_type const Legacytype, int const Legacyparameters = 0 );
|
deserialize( std::string const &Input, sound_type const Legacytype, int const Legacyparameters = 0 );
|
||||||
|
// sends content of the class in legacy (text) format to provided stream
|
||||||
|
void
|
||||||
|
export_as_text( std::ostream &Output ) const;
|
||||||
// copies list of sounds from provided source
|
// copies list of sounds from provided source
|
||||||
sound_source &
|
sound_source &
|
||||||
copy_sounds( sound_source const &Source );
|
copy_sounds( sound_source const &Source );
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ ui_layer::on_key( int const Key, int const Action ) {
|
|||||||
case GLFW_KEY_F8:
|
case GLFW_KEY_F8:
|
||||||
case GLFW_KEY_F9:
|
case GLFW_KEY_F9:
|
||||||
case GLFW_KEY_F10:
|
case GLFW_KEY_F10:
|
||||||
|
case GLFW_KEY_F11:
|
||||||
case GLFW_KEY_F12: { // ui mode selectors
|
case GLFW_KEY_F12: { // ui mode selectors
|
||||||
|
|
||||||
if( ( true == Global.ctrlState )
|
if( ( true == Global.ctrlState )
|
||||||
|
|||||||
Reference in New Issue
Block a user