build 180708. model instance position and rotation adjustment in scenery editor, support for event launcher activation with mouse click, minor refactoring

This commit is contained in:
tmj-fstate
2018-07-08 23:18:27 +02:00
parent 293787c1b4
commit ff1a85fe5d
29 changed files with 602 additions and 239 deletions

View File

@@ -419,7 +419,7 @@ TAnimModel::TAnimModel( scene::node_data const &Nodedata ) : basic_node( Nodedat
TAnimModel::~TAnimModel()
{
delete pAdvanced; // nie ma zaawansowanej animacji
SafeDelete(pAdvanced); // nie ma zaawansowanej animacji
SafeDelete(pRoot);
}
@@ -630,10 +630,6 @@ int TAnimModel::Flags()
//---------------------------------------------------------------------------
bool TAnimModel::TerrainLoaded()
{ // zliczanie kwadratów kilometrowych (główna linia po Next) do tworznia tablicy
return (this ? pModel != NULL : false);
};
int TAnimModel::TerrainCount()
{ // zliczanie kwadratów kilometrowych (główna linia po Next) do tworznia tablicy
return pModel ? pModel->TerrainCount() : 0;

View File

@@ -138,11 +138,8 @@ public:
bool Load(cParser *parser, bool ter = false);
TAnimContainer * AddContainer(std::string const &Name);
TAnimContainer * GetContainer(std::string const &Name = "");
void RaAnglesSet( glm::vec3 Angles ) {
vAngle = { Angles }; };
void LightSet( int const n, float const v );
void AnimationVND( void *pData, double a, double b, double c, double d );
bool TerrainLoaded();
int TerrainCount();
TSubModel * TerrainSquare(int n);
int Flags();
@@ -154,6 +151,14 @@ public:
TModel3d *
Model() const {
return pModel; }
inline
void
Angles( glm::vec3 const &Angles ) {
vAngle = Angles; }
inline
glm::vec3
Angles() const {
return vAngle; }
// members
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
@@ -178,7 +183,7 @@ private:
int iNumLights { 0 };
TSubModel *LightsOn[ iMaxNumLights ]; // Ra: te wskaźniki powinny być w ramach TModel3d
TSubModel *LightsOff[ iMaxNumLights ];
Math3D::vector3 vAngle; // bazowe obroty egzemplarza względem osi
glm::vec3 vAngle; // bazowe obroty egzemplarza względem osi
material_data m_materialdata;
std::string asText; // tekst dla wyświetlacza znakowego

View File

@@ -237,9 +237,3 @@ void TCamera::RaLook()
m_rotationoffsets.x = 0.0;
}
};
void TCamera::Stop()
{ // wyłącznie bezwładnego ruchu po powrocie do kabiny
Type = tp_Follow;
Velocity = Math3D::vector3(0, 0, 0);
};

View File

@@ -31,7 +31,6 @@ class TCamera {
Math3D::vector3 GetDirection();
bool SetMatrix(glm::dmat4 &Matrix);
void RaLook();
void Stop();
TCameraType Type;
double Pitch;

View File

@@ -22,6 +22,7 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others
#include "World.h"
#include "simulation.h"
#include "sceneeditor.h"
#include "Globals.h"
#include "timer.h"
#include "Logs.h"
@@ -127,23 +128,25 @@ void window_resize_callback(GLFWwindow *window, int w, int h)
void cursor_pos_callback(GLFWwindow *window, double x, double y)
{
input::Mouse.move( x, y );
if( true == Global.ControlPicking ) {
glfwSetCursorPos( window, x, y );
}
else {
if( false == Global.ControlPicking ) {
glfwSetCursorPos( window, 0, 0 );
}
// give the potential event recipient a shot at it, in the virtual z order
if( true == scene::Editor.on_mouse_move( x, y ) ) { return; }
input::Mouse.move( x, y );
}
void mouse_button_callback( GLFWwindow* window, int button, int action, int mods ) {
if( ( button == GLFW_MOUSE_BUTTON_LEFT )
|| ( button == GLFW_MOUSE_BUTTON_RIGHT ) ) {
if( ( button != GLFW_MOUSE_BUTTON_LEFT )
&& ( button != GLFW_MOUSE_BUTTON_RIGHT ) ) {
// we don't care about other mouse buttons at the moment
input::Mouse.button( button, action );
return;
}
// give the potential event recipient a shot at it, in the virtual z order
if( true == scene::Editor.on_mouse_button( button, action ) ) { return; }
input::Mouse.button( button, action );
}
void key_callback( GLFWwindow *window, int key, int scancode, int action, int mods ) {

View File

@@ -135,10 +135,11 @@ bool TEventLauncher::Load(cParser *parser)
return true;
}
bool TEventLauncher::check_conditions()
{ //"renderowanie" wyzwalacza
bool TEventLauncher::check_activation() {
auto bCond { false };
if (iKey != 0) {
if( iKey != 0 ) {
if( iKey > 255 ) {
// key and modifier
auto const modifier = ( iKey & 0xff00 ) >> 8;
@@ -151,37 +152,45 @@ bool TEventLauncher::check_conditions()
bCond = ( Console::Pressed( iKey & 0xff ) ); // czy klawisz wciśnięty
}
}
if (DeltaTime > 0)
{
if (UpdatedTime > DeltaTime)
{
if( DeltaTime > 0 ) {
if( UpdatedTime > DeltaTime ) {
UpdatedTime = 0; // naliczanie od nowa
bCond = true;
}
else
UpdatedTime += Timer::GetDeltaTime(); // aktualizacja naliczania czasu
else {
// aktualizacja naliczania czasu
UpdatedTime += Timer::GetDeltaTime();
}
}
else
{ // jeśli nie cykliczny, to sprawdzić czas
if (simulation::Time.data().wHour == iHour)
{
if (simulation::Time.data().wMinute == iMinute)
{ // zgodność czasu uruchomienia
if (UpdatedTime < 10)
{
else {
// jeśli nie cykliczny, to sprawdzić czas
if( simulation::Time.data().wHour == iHour ) {
if( simulation::Time.data().wMinute == iMinute ) {
// zgodność czasu uruchomienia
if( UpdatedTime < 10 ) {
UpdatedTime = 20; // czas do kolejnego wyzwolenia?
bCond = true;
}
}
}
else
else {
UpdatedTime = 1;
}
}
if (bCond) // jeśli spełniony został warunek
{
if ((iCheckMask != 0) && MemCell) // sprawdzanie warunku na komórce pamięci
bCond = MemCell->Compare(szText, fVal1, fVal2, iCheckMask);
return bCond;
}
bool TEventLauncher::check_conditions() {
auto bCond { true };
if( ( iCheckMask != 0 )
&& ( MemCell != nullptr ) ) {
// sprawdzanie warunku na komórce pamięci
bCond = MemCell->Compare( szText, fVal1, fVal2, iCheckMask );
}
return bCond; // sprawdzanie dRadius w Ground.cpp
}

View File

@@ -24,6 +24,7 @@ public:
// methods
bool Load( cParser *parser );
bool check_activation();
// checks conditions associated with the event. returns: true if the conditions are met
bool check_conditions();
bool IsGlobal() const;

View File

@@ -894,7 +894,7 @@ event_manager::update() {
// test list of global events for possible new additions to the queue
for( auto *launcher : m_launcherqueue ) {
if( true == launcher->check_conditions() ) {
if( true == ( launcher->check_activation() && launcher->check_conditions() ) ) {
// NOTE: we're presuming global events aren't going to use event2
WriteLog( "Eventlauncher " + launcher->name() );
if( launcher->Event1 ) {

View File

@@ -18,23 +18,8 @@ http://mozilla.org/MPL/2.0/.
//---------------------------------------------------------------------------
// helper, restores content of a 3d vector from provided input stream
// 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 ) {
segment_data::deserialize( cParser &Input, glm::dvec3 const &Offset ) {
points[ segment_data::point::start ] = LoadPoint( Input ) + Offset;
Input.getTokens();

View File

@@ -29,7 +29,7 @@ struct segment_data {
// constructors
segment_data() = default;
// methods
void deserialize( cParser &Input, Math3D::vector3 const &Offset );
void deserialize( cParser &Input, glm::dvec3 const &Offset );
};
class TSegment

View File

@@ -343,7 +343,7 @@ void TTrack::ConnectNextNext(TTrack *pTrack, int typ)
}
}
void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
void TTrack::Load(cParser *parser, glm::dvec3 const &pOrigin)
{ // pobranie obiektu trajektorii ruchu
Math3D::vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań
double a1, a2, r1, r2, r3, r4;
@@ -862,7 +862,7 @@ void TTrack::Load(cParser *parser, Math3D::vector3 pOrigin)
}
// calculate path location
m_area.center = ( glm::dvec3{ (
location( { (
CurrentSegment()->FastGetPoint_0()
+ CurrentSegment()->FastGetPoint( 0.5 )
+ CurrentSegment()->FastGetPoint_1() )

17
Track.h
View File

@@ -170,20 +170,7 @@ public:
m_events1,
m_events2;
bool m_events { false }; // Ra: flaga informująca o obecności eventów
/*
TEvent *evEventall0 = nullptr; // McZapkie-140302: wyzwalany gdy pojazd stoi
TEvent *evEventall1 = nullptr;
TEvent *evEventall2 = nullptr;
TEvent *evEvent0 = nullptr; // McZapkie-280503: wyzwalany tylko gdy headdriver
TEvent *evEvent1 = nullptr;
TEvent *evEvent2 = nullptr;
std::string asEventall0Name; // nazwy eventów
std::string asEventall1Name;
std::string asEventall2Name;
std::string asEvent0Name;
std::string asEvent1Name;
std::string asEvent2Name;
*/
int iNextDirection = 0; // 0:Point1, 1:Point2, 3:do odchylonego na zwrotnicy
int iPrevDirection = 0; // domyślnie wirtualne odcinki dołączamy stroną od Point1
TTrackType eType = tt_Normal; // domyślnie zwykły
@@ -246,7 +233,7 @@ public:
SwitchExtension != nullptr ?
SwitchExtension->iRoads - 1 :
1 ); }
void Load(cParser *parser, Math3D::vector3 pOrigin);
void Load(cParser *parser, glm::dvec3 const &pOrigin);
bool AssignEvents();
bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus);
void QueueEvents( event_sequence const &Events, TDynamicObject const *Owner );

View File

@@ -91,17 +91,6 @@ jawnie nazwę sekcji, ewentualnie nazwę zasilacza (zostanie zastąpiona wskazan
sekcji z sąsiedniego przęsła).
*/
glm::dvec3 LoadPoint( cParser &Input ) {
// pobranie współrzędnych punktu
glm::dvec3 point;
Input.getTokens( 3 );
Input
>> point.x
>> point.y
>> point.z;
return point;
}
TTraction::TTraction( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
void

View File

@@ -240,6 +240,12 @@
<ClCompile Include="station.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stb_vorbis.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sceneeditor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Globals.h">
@@ -467,6 +473,9 @@
<ClInclude Include="station.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="sceneeditor.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="maszyna.rc">

View File

@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
#include "utilities.h"
#include "globals.h"
#include "timer.h"
#include "simulation.h"
#include "world.h"
#include "train.h"
#include "renderer.h"
@@ -74,33 +75,21 @@ mouse_input::button( int const Button, int const Action ) {
if( false == Global.ControlPicking ) { return; }
if( true == FreeFlyModeFlag ) {
// world editor controls
// TODO: separate behaviour when the scenery editor is active and in 'regular' free fly mode
if( Action == GLFW_RELEASE ) {
// if it's the right mouse button that got released we were potentially in view panning mode; stop it
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
m_pickmodepanning = false;
// freefly mode
// left mouse button launches on_click event associated with to the node
if( Button == GLFW_MOUSE_BUTTON_LEFT ) {
if( Action == GLFW_PRESS ) {
auto const *node { GfxRenderer.Update_Pick_Node() };
if( ( node == nullptr )
|| ( typeid( *node ) != typeid( TAnimModel ) ) ) {
return;
}
simulation::Region->on_click( static_cast<TAnimModel const *>( node ) );
}
}
else {
// button press
if( Button == GLFW_MOUSE_BUTTON_LEFT ) {
// the left button selects scene node
// further behaviour can vary depending on whether we're in editor mode
auto const *node { GfxRenderer.Update_Pick_Node() };
if( true == EditorModeFlag ) {
// NOTE: until we have proper editor object in place we set the current node manually
editor::Node = node;
}
else {
// launch on_click event associated with to the node
// TODO: implement
}
}
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
// the right button activates mouse panning mode
m_pickmodepanning = true;
}
// right button controls panning
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
m_pickmodepanning = ( Action == GLFW_PRESS );
}
}
else {
@@ -130,60 +119,57 @@ mouse_input::button( int const Button, int const Action ) {
}
else {
// if not release then it's press
auto train = World.train();
if( train != nullptr ) {
auto lookup = m_mousecommands.find( train->GetLabel( GfxRenderer.Update_Pick_Control() ) );
if( lookup != m_mousecommands.end() ) {
mousecommand = (
Button == GLFW_MOUSE_BUTTON_LEFT ?
lookup->second.left :
lookup->second.right
);
if( mousecommand != user_command::none ) {
// check manually for commands which have 'fast' variants launched with shift modifier
if( Global.shiftState ) {
switch( mousecommand ) {
case user_command::mastercontrollerincrease: { mousecommand = user_command::mastercontrollerincreasefast; break; }
case user_command::mastercontrollerdecrease: { mousecommand = user_command::mastercontrollerdecreasefast; break; }
case user_command::secondcontrollerincrease: { mousecommand = user_command::secondcontrollerincreasefast; break; }
case user_command::secondcontrollerdecrease: { mousecommand = user_command::secondcontrollerdecreasefast; break; }
case user_command::independentbrakeincrease: { mousecommand = user_command::independentbrakeincreasefast; break; }
case user_command::independentbrakedecrease: { mousecommand = user_command::independentbrakedecreasefast; break; }
default: { break; }
}
}
// NOTE: basic keyboard controls don't have any parameters
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
m_relay.post( mousecommand, 0, 0, Action, 0 );
m_updateaccumulator = -0.25; // prevent potential command repeat right after issuing one
switch( mousecommand ) {
case user_command::mastercontrollerincrease:
case user_command::mastercontrollerdecrease:
case user_command::secondcontrollerincrease:
case user_command::secondcontrollerdecrease:
case user_command::trainbrakeincrease:
case user_command::trainbrakedecrease:
case user_command::independentbrakeincrease:
case user_command::independentbrakedecrease: {
// these commands trigger varying repeat rate mode,
// which scales the rate based on the distance of the cursor from its point when the command was first issued
m_commandstartcursor = m_cursorposition;
m_varyingpollrate = true;
break;
}
default: {
break;
}
}
auto const lookup = m_mousecommands.find( World.train()->GetLabel( GfxRenderer.Update_Pick_Control() ) );
if( lookup != m_mousecommands.end() ) {
// if the recognized element under the cursor has a command associated with the pressed button, notify the recipient
mousecommand = (
Button == GLFW_MOUSE_BUTTON_LEFT ?
lookup->second.left :
lookup->second.right
);
if( mousecommand == user_command::none ) { return; }
// check manually for commands which have 'fast' variants launched with shift modifier
if( Global.shiftState ) {
switch( mousecommand ) {
case user_command::mastercontrollerincrease: { mousecommand = user_command::mastercontrollerincreasefast; break; }
case user_command::mastercontrollerdecrease: { mousecommand = user_command::mastercontrollerdecreasefast; break; }
case user_command::secondcontrollerincrease: { mousecommand = user_command::secondcontrollerincreasefast; break; }
case user_command::secondcontrollerdecrease: { mousecommand = user_command::secondcontrollerdecreasefast; break; }
case user_command::independentbrakeincrease: { mousecommand = user_command::independentbrakeincreasefast; break; }
case user_command::independentbrakedecrease: { mousecommand = user_command::independentbrakedecreasefast; break; }
default: { break; }
}
}
else {
// if we don't have any recognized element under the cursor and the right button was pressed, enter view panning mode
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
m_pickmodepanning = true;
// NOTE: basic keyboard controls don't have any parameters
// NOTE: as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
m_relay.post( mousecommand, 0, 0, Action, 0 );
m_updateaccumulator = -0.25; // prevent potential command repeat right after issuing one
switch( mousecommand ) {
case user_command::mastercontrollerincrease:
case user_command::mastercontrollerdecrease:
case user_command::secondcontrollerincrease:
case user_command::secondcontrollerdecrease:
case user_command::trainbrakeincrease:
case user_command::trainbrakedecrease:
case user_command::independentbrakeincrease:
case user_command::independentbrakedecrease: {
// these commands trigger varying repeat rate mode,
// which scales the rate based on the distance of the cursor from its point when the command was first issued
m_varyingpollrateorigin = m_cursorposition;
m_varyingpollrate = true;
break;
}
default: {
break;
}
}
}
else {
// if we don't have any recognized element under the cursor and the right button was pressed, enter view panning mode
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
m_pickmodepanning = true;
}
}
}
@@ -197,7 +183,7 @@ mouse_input::poll() {
auto updaterate { m_updaterate };
if( m_varyingpollrate ) {
updaterate /= std::max( 0.15, 2.0 * glm::length( m_cursorposition - m_commandstartcursor ) / std::max( 1, Global.iWindowHeight ) );
updaterate /= std::max( 0.15, 2.0 * glm::length( m_cursorposition - m_varyingpollrateorigin ) / std::max( 1, Global.iWindowHeight ) );
}
while( m_updateaccumulator > updaterate ) {

View File

@@ -21,10 +21,10 @@ public:
// methods
bool
init();
void
move( double const Mousex, double const Mousey );
void
button( int const Button, int const Action );
void
move( double const Mousex, double const Mousey );
void
poll();
@@ -52,8 +52,8 @@ private:
double m_updateaccumulator { 0.0 };
bool m_pickmodepanning { false }; // indicates mouse is in view panning mode
glm::dvec2 m_cursorposition; // stored last cursor position, used for panning
glm::dvec2 m_commandstartcursor; // helper, cursor position when the command was initiated
bool m_varyingpollrate { false }; // indicates rate of command repeats is affected by the cursor position
glm::dvec2 m_varyingpollrateorigin; // helper, cursor position when the command was initiated
};
//---------------------------------------------------------------------------

View File

@@ -449,6 +449,8 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
case rendermode::color: {
m_colorpass = m_renderpass;
if( ( true == Global.RenderShadows )
&& ( false == Global.bWireFrame )
&& ( true == World.InitPerformed() )
@@ -1668,6 +1670,11 @@ opengl_renderer::Render( scene::basic_region *Region ) {
Update_Lights( simulation::Lights );
Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) );
if( EditorModeFlag && FreeFlyModeFlag && Global.ControlPicking ) {
// when editor mode is active calculate world position of the cursor
// at this stage the z-buffer is filled with only ground geometry
Update_Mouse_Position();
}
// draw queue is filled while rendering sections
Render( std::begin( m_cellqueue ), std::end( m_cellqueue ) );
break;
@@ -1912,7 +1919,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
::glPushAttrib( GL_ENABLE_BIT );
::glDisable( GL_TEXTURE_2D );
::glColor3f( 0.36f, 0.75f, 0.35f );
for( auto const *memorycell : cell->m_memorycells ) {
for( auto *memorycell : cell->m_memorycells ) {
Render( memorycell );
}
::glPopAttrib();
@@ -1929,7 +1936,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
// memcells
if( ( EditorModeFlag )
&& ( DebugModeFlag ) ) {
for( auto const *memorycell : cell->m_memorycells ) {
for( auto *memorycell : cell->m_memorycells ) {
::glColor3fv( glm::value_ptr( pick_color( m_picksceneryitems.size() + 1 ) ) );
Render( memorycell );
}
@@ -2310,16 +2317,16 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, float c
}
bool
opengl_renderer::Render( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ) {
opengl_renderer::Render( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, glm::vec3 const &Angle ) {
::glPushMatrix();
::glTranslated( Position.x, Position.y, Position.z );
if( Angle.y != 0.0 )
::glRotated( Angle.y, 0.0, 1.0, 0.0 );
::glRotatef( Angle.y, 0.f, 1.f, 0.f );
if( Angle.x != 0.0 )
::glRotated( Angle.x, 1.0, 0.0, 0.0 );
::glRotatef( Angle.x, 1.f, 0.f, 0.f );
if( Angle.z != 0.0 )
::glRotated( Angle.z, 0.0, 0.0, 1.0 );
::glRotatef( Angle.z, 0.f, 0.f, 1.f );
auto const result = Render( Model, Material, Squaredistance );
@@ -2755,7 +2762,7 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
}
void
opengl_renderer::Render( TMemCell const *Memcell ) {
opengl_renderer::Render( TMemCell *Memcell ) {
::glPushMatrix();
auto const position = Memcell->location() - m_renderpass.camera.position();
@@ -3129,16 +3136,16 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, f
}
bool
opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ) {
opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, glm::vec3 const &Angle ) {
::glPushMatrix();
::glTranslated( Position.x, Position.y, Position.z );
if( Angle.y != 0.0 )
::glRotated( Angle.y, 0.0, 1.0, 0.0 );
::glRotatef( Angle.y, 0.f, 1.f, 0.f );
if( Angle.x != 0.0 )
::glRotated( Angle.x, 1.0, 0.0, 0.0 );
::glRotatef( Angle.x, 1.f, 0.f, 0.f );
if( Angle.z != 0.0 )
::glRotated( Angle.z, 0.0, 0.0, 1.0 );
::glRotatef( Angle.z, 0.f, 0.f, 1.f );
auto const result = Render_Alpha( Model, Material, Squaredistance ); // position is effectively camera offset
@@ -3379,7 +3386,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
// utility methods
TSubModel const *
TSubModel *
opengl_renderer::Update_Pick_Control() {
#ifdef EU07_USE_PICKING_FRAMEBUFFER
@@ -3412,7 +3419,7 @@ opengl_renderer::Update_Pick_Control() {
unsigned char pickreadout[4];
::glReadPixels( pickbufferpos.x, pickbufferpos.y, 1, 1, GL_BGRA, GL_UNSIGNED_BYTE, pickreadout );
auto const controlindex = pick_index( glm::ivec3{ pickreadout[ 2 ], pickreadout[ 1 ], pickreadout[ 0 ] } );
TSubModel const *control { nullptr };
TSubModel *control { nullptr };
if( ( controlindex > 0 )
&& ( controlindex <= m_pickcontrolsitems.size() ) ) {
control = m_pickcontrolsitems[ controlindex - 1 ];
@@ -3426,7 +3433,7 @@ opengl_renderer::Update_Pick_Control() {
return control;
}
scene::basic_node const *
scene::basic_node *
opengl_renderer::Update_Pick_Node() {
#ifdef EU07_USE_PICKING_FRAMEBUFFER
@@ -3461,7 +3468,7 @@ opengl_renderer::Update_Pick_Node() {
unsigned char pickreadout[4];
::glReadPixels( pickbufferpos.x, pickbufferpos.y, 1, 1, GL_BGRA, GL_UNSIGNED_BYTE, pickreadout );
auto const nodeindex = pick_index( glm::ivec3{ pickreadout[ 2 ], pickreadout[ 1 ], pickreadout[ 0 ] } );
scene::basic_node const *node { nullptr };
scene::basic_node *node { nullptr };
if( ( nodeindex > 0 )
&& ( nodeindex <= m_picksceneryitems.size() ) ) {
node = m_picksceneryitems[ nodeindex - 1 ];
@@ -3475,6 +3482,29 @@ opengl_renderer::Update_Pick_Node() {
return node;
}
// converts provided screen coordinates to world coordinates of most recent color pass
glm::dvec3
opengl_renderer::Update_Mouse_Position() {
glm::dvec2 mousepos;
glfwGetCursorPos( m_window, &mousepos.x, &mousepos.y );
mousepos.x = clamp<int>( mousepos.x, 0, Global.iWindowWidth - 1 );
mousepos.y = clamp<int>( Global.iWindowHeight - clamp<int>( mousepos.y, 0, Global.iWindowHeight ), 0, Global.iWindowHeight - 1 ) ;
GLfloat pointdepth;
::glReadPixels( mousepos.x, mousepos.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pointdepth );
if( pointdepth < 1.0 ) {
m_worldmousecoordinates =
glm::unProject(
glm::vec3{ mousepos, pointdepth },
glm::mat4{ glm::mat3{ m_colorpass.camera.modelview() } },
m_colorpass.camera.projection(),
glm::vec4{ 0, 0, Global.iWindowWidth, Global.iWindowHeight } );
}
return m_colorpass.camera.position() + glm::dvec3{ m_worldmousecoordinates };
}
void
opengl_renderer::Update( double const Deltatime ) {

View File

@@ -167,13 +167,17 @@ public:
Pick_Control() const { return m_pickcontrolitem; }
scene::basic_node const *
Pick_Node() const { return m_picksceneryitem; }
glm::dvec3
Mouse_Position() const { return m_worldmousecoordinates; }
// maintenance methods
void
Update( double const Deltatime );
TSubModel const *
TSubModel *
Update_Pick_Control();
scene::basic_node const *
scene::basic_node *
Update_Pick_Node();
glm::dvec3
Update_Mouse_Position();
// debug methods
std::string const &
info_times() const;
@@ -277,7 +281,7 @@ private:
bool
Render( TDynamicObject *Dynamic );
bool
Render( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
Render( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, glm::vec3 const &Angle );
bool
Render( TModel3d *Model, material_data const *Material, float const Squaredistance );
void
@@ -289,7 +293,7 @@ private:
bool
Render_cab( TDynamicObject const *Dynamic, bool const Alpha = false );
void
Render( TMemCell const *Memcell );
Render( TMemCell *Memcell );
void
Render_Alpha( scene::basic_region *Region );
void
@@ -303,7 +307,7 @@ private:
bool
Render_Alpha( TDynamicObject *Dynamic );
bool
Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance, Math3D::vector3 const &Position, glm::vec3 const &Angle );
bool
Render_Alpha( TModel3d *Model, material_data const *Material, float const Squaredistance );
void
@@ -386,12 +390,14 @@ private:
renderpass_config m_renderpass; // parameters for current render pass
section_sequence m_sectionqueue; // list of sections in current render pass
cell_sequence m_cellqueue;
renderpass_config m_colorpass; // parametrs of most recent color pass
renderpass_config m_shadowpass; // parametrs of most recent shadowmap pass
renderpass_config m_cabshadowpass; // parameters of most recent cab shadowmap pass
std::vector<TSubModel const *> m_pickcontrolsitems;
TSubModel const *m_pickcontrolitem { nullptr };
std::vector<scene::basic_node const *> m_picksceneryitems;
scene::basic_node const *m_picksceneryitem { nullptr };
std::vector<TSubModel *> m_pickcontrolsitems;
TSubModel *m_pickcontrolitem { nullptr };
std::vector<scene::basic_node *> m_picksceneryitems;
scene::basic_node *m_picksceneryitem { nullptr };
glm::vec3 m_worldmousecoordinates { 0.f };
#ifdef EU07_USE_DEBUG_CAMERA
renderpass_config m_worldcamera; // debug item
#endif

106
scene.cpp
View File

@@ -22,6 +22,19 @@ namespace scene {
std::string const EU07_FILEEXTENSION_REGION { ".sbt" };
std::uint32_t const EU07_FILEVERSION_REGION { MAKE_ID4( 'S', 'B', 'T', 1 ) };
// potentially activates event handler with the same name as provided node, and within handler activation range
void
basic_cell::on_click( TAnimModel const *Instance ) {
for( auto *launcher : m_eventlaunchers ) {
if( ( launcher->name() == Instance->name() )
&& ( glm::length2( launcher->location() - Instance->location() ) < launcher->dRadius )
&& ( true == launcher->check_conditions() ) ) {
launch_event( launcher );
}
}
}
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
void
basic_cell::update_traction( TDynamicObject *Vehicle, int const Pantographindex ) {
@@ -105,17 +118,10 @@ basic_cell::update_events() {
// event launchers
for( auto *launcher : m_eventlaunchers ) {
if( ( true == launcher->check_conditions() )
if( ( true == ( launcher->check_activation() && launcher->check_conditions() ) )
&& ( SquareMagnitude( launcher->location() - Global.pCameraPosition ) < launcher->dRadius ) ) {
WriteLog( "Eventlauncher " + launcher->name() );
if( ( true == Global.shiftState )
&& ( launcher->Event2 != nullptr ) ) {
simulation::Events.AddToQuery( launcher->Event2, nullptr );
}
else if( launcher->Event1 ) {
simulation::Events.AddToQuery( launcher->Event1, nullptr );
}
launch_event( launcher );
}
}
}
@@ -384,6 +390,38 @@ basic_cell::insert( TMemCell *Memorycell ) {
// NOTE: memory cells are virtual 'points' hence they don't ever expand cell range
}
// removes provided model instance from the cell
void
basic_cell::erase( TAnimModel *Instance ) {
auto const flags = Instance->Flags();
auto alpha =
( Instance->Material() != nullptr ?
Instance->Material()->textures_alpha :
0x30300030 );
if( alpha & flags & 0x2F2F002F ) {
// instance has translucent pieces
m_instancetranslucent.erase(
std::remove_if(
std::begin( m_instancetranslucent ), std::end( m_instancetranslucent ),
[=]( TAnimModel *instance ) {
return instance == Instance; } ),
std::end( m_instancetranslucent ) );
}
alpha ^= 0x0F0F000F; // odwrócenie flag tekstur, aby wyłapać nieprzezroczyste
if( alpha & flags & 0x1F1F001F ) {
// instance has opaque pieces
m_instancesopaque.erase(
std::remove_if(
std::begin( m_instancesopaque ), std::end( m_instancesopaque ),
[=]( TAnimModel *instance ) {
return instance == Instance; } ),
std::end( m_instancesopaque ) );
}
// TODO: update cell bounding area
}
// registers provided path in the lookup directory of the cell
void
basic_cell::register_end( TTrack *Path ) {
@@ -549,6 +587,20 @@ basic_cell::create_geometry( gfx::geometrybank_handle const &Bank ) {
m_geometrycreated = true; // helper for legacy animation code, get rid of it after refactoring
}
// executes event assigned to specified launcher
void
basic_cell::launch_event( TEventLauncher *Launcher ) {
WriteLog( "Eventlauncher " + Launcher->name() );
if( ( true == Global.shiftState )
&& ( Launcher->Event2 != nullptr ) ) {
simulation::Events.AddToQuery( Launcher->Event2, nullptr );
}
else if( Launcher->Event1 ) {
simulation::Events.AddToQuery( Launcher->Event1, nullptr );
}
}
// adjusts cell bounding area to enclose specified node
void
basic_cell::enclose_area( scene::basic_node *Node ) {
@@ -560,6 +612,13 @@ basic_cell::enclose_area( scene::basic_node *Node ) {
// potentially activates event handler with the same name as provided node, and within handler activation range
void
basic_section::on_click( TAnimModel const *Instance ) {
cell( Instance->location() ).on_click( Instance );
}
// legacy method, finds and assigns traction piece(s) to pantographs of provided vehicle
void
basic_section::update_traction( TDynamicObject *Vehicle, int const Pantographindex ) {
@@ -856,6 +915,19 @@ basic_region::~basic_region() {
for( auto *section : m_sections ) { if( section != nullptr ) { delete section; } }
}
// potentially activates event handler with the same name as provided node, and within handler activation range
void
basic_region::on_click( TAnimModel const *Instance ) {
if( Instance->name().empty() || ( Instance->name() == "none" ) ) { return; }
auto const location { Instance->location() };
if( point_inside( location ) ) {
section( location ).on_click( Instance );
}
}
// legacy method, polls event launchers around camera
void
basic_region::update_events() {
@@ -1185,8 +1257,8 @@ basic_region::insert_traction( TTraction *Traction, scratch_data &Scratchpad ) {
// inserts provided instance of 3d model in the region
void
basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ) {
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
auto location = Instance->location();
auto const location { Instance->location() };
if( point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
@@ -1198,6 +1270,18 @@ basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad )
}
}
// removes specified instance of 3d model from the region
void
basic_region::erase_instance( TAnimModel *Instance ) {
auto const location { Instance->location() };
if( point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
section( location ).erase( Instance );
}
}
// inserts provided sound in the region
void
basic_region::insert_sound( sound_source *Sound, scratch_data &Scratchpad ) {

28
scene.h
View File

@@ -66,6 +66,9 @@ public:
// constructors
basic_cell() = default;
// methods
// potentially activates event handler with the same name as provided node, and within handler activation range
void
on_click( TAnimModel const *Instance );
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
void
update_traction( TDynamicObject *Vehicle, int const Pantographindex );
@@ -123,6 +126,9 @@ public:
// registers provided traction piece in the lookup directory of the cell
void
register_end( TTraction *Traction );
// removes provided model instance from the cell
void
erase( TAnimModel *Instance );
// find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float>
find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) const;
@@ -157,6 +163,8 @@ private:
using eventlauncher_sequence = std::vector<TEventLauncher *>;
using memorycell_sequence = std::vector<TMemCell *>;
// methods
void
launch_event( TEventLauncher *Launcher );
void
enclose_area( scene::basic_node *Node );
// members
@@ -193,7 +201,10 @@ public:
// constructors
basic_section() = default;
// methods
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
// potentially activates event handler with the same name as provided node, and within handler activation range
void
on_click( TAnimModel const *Instance );
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
void
update_traction( TDynamicObject *Vehicle, int const Pantographindex );
// legacy method, updates sounds and polls event launchers within radius around specified point
@@ -230,6 +241,13 @@ public:
m_area.radius = std::max(
m_area.radius,
static_cast<float>( glm::length( m_area.center - targetcell.area().center ) + targetcell.area().radius ) ); }
// erases provided node from the section
template <class Type_>
void
erase( Type_ *Node ) {
auto &targetcell { cell( Node->location() ) };
// TODO: re-calculate bounding area after removal
targetcell.erase( Node ); }
// registers provided node in the lookup directory of the section enclosing specified point
template <class Type_>
void
@@ -289,7 +307,10 @@ public:
// destructor
~basic_region();
// methods
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
// potentially activates event handler with the same name as provided node, and within handler activation range
void
on_click( TAnimModel const *Instance );
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
void
update_traction( TDynamicObject *Vehicle, int const Pantographindex );
// legacy method, polls event launchers around camera
@@ -337,6 +358,9 @@ public:
// inserts provided memory cell in the region
void
insert_memorycell( TMemCell *Memorycell, scratch_data &Scratchpad );
// removes specified instance of 3d model from the region
void
erase_instance( TAnimModel *Instance );
// find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float>
find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );

165
sceneeditor.cpp Normal file
View File

@@ -0,0 +1,165 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "sceneeditor.h"
#include "globals.h"
#include "simulation.h"
#include "renderer.h"
namespace scene {
basic_editor Editor;
bool
basic_editor::on_mouse_button( int const Button, int const Action ) {
if( false == EditorModeFlag ) { return false; }
// TBD: automatically activate and enforce picking mode and/or freefly mode when editor is active?
if( false == FreeFlyModeFlag ) { return false; }
if( false == Global.ControlPicking ) { return false; }
if( Button == GLFW_MOUSE_BUTTON_LEFT ) {
if( Action == GLFW_PRESS ) {
m_node = GfxRenderer.Update_Pick_Node();
m_nodesnapshot = { m_node };
if( m_node ) {
glfwSetInputMode( Global.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED );
}
}
else {
// left button release
// TODO: record the current undo step on the undo stack
m_nodesnapshot = { m_node };
if( m_node ) {
glfwSetInputMode( Global.window, GLFW_CURSOR, GLFW_CURSOR_NORMAL );
}
}
m_mouseleftbuttondown = ( Action == GLFW_PRESS );
return ( m_node != nullptr );
}
return false;
}
bool
basic_editor::on_mouse_move( double const Mousex, double const Mousey ) {
auto const mousemove { glm::dvec2{ Mousex, Mousey } - m_mouseposition };
m_mouseposition = { Mousex, Mousey };
if( false == EditorModeFlag ) { return false; }
if( false == m_mouseleftbuttondown ) { return false; }
if( m_node == nullptr ) { return false; }
if( mode_translation() ) {
// move selected node
if( mode_translation_vertical() ) {
auto const translation { mousemove.y * -0.01f };
translate( translation );
}
else {
auto const mouseworldposition{ Global.pCamera->Pos + GfxRenderer.Mouse_Position() };
translate( mouseworldposition );
}
}
else {
// rotate selected node
auto const rotation { glm::vec3 { mousemove.y, mousemove.x, 0 } * 0.25f };
rotate( rotation );
}
return true;
}
void
basic_editor::translate( glm::dvec3 const &Location ) {
auto *node { m_node }; // placeholder for operations on multiple nodes
auto location { Location };
if( typeid( *node ) == typeid( TAnimModel ) ) {
// TBD, TODO: don't modify y coordinate if snap-to-ground mode is active?
// location.y = node->location().y;
translate_instance( static_cast<TAnimModel *>( node ), location );
}
}
void
basic_editor::translate( float const Offset ) {
// NOTE: offset scaling is calculated early so the same multiplier can be applied to potential whole group
auto location { m_node->location() };
auto const distance { glm::length( location - glm::dvec3{ Global.pCamera->Pos } ) };
auto const offset { Offset * std::max( 1.0, distance * 0.01 ) };
auto *node { m_node }; // placeholder for operations on multiple nodes
if( typeid( *node ) == typeid( TAnimModel ) ) {
translate_instance( static_cast<TAnimModel *>( node ), offset );
}
}
void
basic_editor::translate_instance( TAnimModel *Instance, glm::dvec3 const &Location ) {
simulation::Region->erase_instance( Instance );
Instance->location( Location );
simulation::Region->insert_instance( Instance, scene::scratch_data() );
}
void
basic_editor::translate_instance( TAnimModel *Instance, float const Offset ) {
auto location { Instance->location() };
location.y += Offset;
Instance->location( location );
}
void
basic_editor::rotate( glm::vec3 const &Angle ) {
auto *node { m_node }; // placeholder for operations on multiple nodes
if( typeid( *node ) == typeid( TAnimModel ) ) {
rotate_instance( static_cast<TAnimModel *>( node ), Angle );
}
}
void
basic_editor::rotate_instance( TAnimModel *Instance, glm::vec3 const &Angle ) {
// adjust node data
glm::vec3 angle = glm::dvec3 { Instance->Angles() };
angle.y = clamp_circular( angle.y + Angle.y, 360.f );
Instance->Angles( angle );
// update scene
}
bool
basic_editor::mode_translation() const {
return ( false == Global.ctrlState );
}
bool
basic_editor::mode_translation_vertical() const {
return ( true == Global.shiftState );
}
} // scene
//---------------------------------------------------------------------------

73
sceneeditor.h Normal file
View File

@@ -0,0 +1,73 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "scenenode.h"
namespace scene {
class basic_editor {
public:
// methods
bool
on_mouse_button( int const Button, int const Action );
bool
on_mouse_move( double const Mousex, double const Mousey );
scene::basic_node const *
node() const {
return m_node; }
private:
// types
struct node_snapshot {
scene::basic_node *node;
std::string data;
node_snapshot( scene::basic_node *Node ) :
node( Node ) {
if( Node != nullptr ) {
Node->export_as_text( data ); } };
};
friend bool operator==( basic_editor::node_snapshot const &Left, basic_editor::node_snapshot const &Right );
friend bool operator!=( basic_editor::node_snapshot const &Left, basic_editor::node_snapshot const &Right );
// methods
bool
mode_translation() const;
bool
mode_translation_vertical() const;
void
translate( glm::dvec3 const &Location );
void
translate( float const Offset );
void
translate_instance( TAnimModel *Instance, glm::dvec3 const &Location );
void
translate_instance( TAnimModel *Instance, float const Offset );
void
rotate( glm::vec3 const &Angle );
void
rotate_instance( TAnimModel *Instance, glm::vec3 const &Angle );
// members
scene::basic_node *m_node; // temporary helper, currently selected scene node
node_snapshot m_nodesnapshot { nullptr }; // currently selected scene node in its pre-modified state
glm::dvec2 m_mouseposition { 0.0 };
bool m_mouseleftbuttondown { false };
};
inline bool operator==( basic_editor::node_snapshot const &Left, basic_editor::node_snapshot const &Right ) { return ( ( Left.node == Right.node ) && ( Left.data == Right.data ) ); }
inline bool operator!=( basic_editor::node_snapshot const &Left, basic_editor::node_snapshot const &Right ) { return ( !( Left == Right ) ); }
extern basic_editor Editor;
} // scene
//---------------------------------------------------------------------------

View File

@@ -743,6 +743,14 @@ basic_node::export_as_text( std::ostream &Output ) const {
export_as_text_( Output );
}
void
basic_node::export_as_text( std::string &Output ) const {
std::stringstream converter;
export_as_text( converter );
Output += converter.str();
}
float const &
basic_node::radius() {
@@ -763,10 +771,4 @@ basic_node::radius_() {
} // scene
namespace editor {
scene::basic_node const *Node { nullptr }; // temporary helper, currently selected scene node
} // editor
//---------------------------------------------------------------------------

View File

@@ -316,6 +316,8 @@ public:
// sends basic content of the class in legacy (text) format to provided stream
void
export_as_text( std::ostream &Output ) const;
void
export_as_text( std::string &Output ) const;
std::string const &
name() const;
void
@@ -381,10 +383,4 @@ basic_node::visible() const {
} // scene
namespace editor {
extern scene::basic_node const *Node; // temporary helper, currently selected scene node
} // editor
//---------------------------------------------------------------------------

View File

@@ -620,13 +620,13 @@ state_manager::deserialize_path( cParser &Input, scene::scratch_data &Scratchpad
// TODO: refactor track and wrapper classes and their de/serialization. do offset and rotation after deserialization is done
auto *track = new TTrack( Nodedata );
Math3D::vector3 offset = (
auto const offset { (
Scratchpad.location.offset.empty() ?
Math3D::vector3() :
Math3D::vector3(
Scratchpad.location.offset.top().x,
Scratchpad.location.offset.top().y,
Scratchpad.location.offset.top().z ) );
glm::dvec3 { 0.0 } :
glm::dvec3 {
Scratchpad.location.offset.top().x,
Scratchpad.location.offset.top().y,
Scratchpad.location.offset.top().z } ) };
track->Load( &Input, offset );
return track;
@@ -707,7 +707,7 @@ state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpa
>> rotation.y;
auto *instance = new TAnimModel( Nodedata );
instance->RaAnglesSet( Scratchpad.location.rotation + rotation ); // dostosowanie do pochylania linii
instance->Angles( Scratchpad.location.rotation + rotation ); // dostosowanie do pochylania linii
if( instance->Load( &Input, false ) ) {
instance->location( transform( location, Scratchpad ) );

View File

@@ -2,17 +2,14 @@
#include "stdafx.h"
#include "uilayer.h"
#include "uitranscripts.h"
#include "globals.h"
#include "translation.h"
#include "simulation.h"
#include "mtable.h"
#include "train.h"
#include "dynobj.h"
#include "model3d.h"
#include "sceneeditor.h"
#include "renderer.h"
#include "timer.h"
#include "utilities.h"
#include "logs.h"
@@ -710,12 +707,16 @@ ui_layer::update() {
case( GLFW_KEY_F11 ): {
// scenario inspector
auto const *node { editor::Node };
auto const *node { scene::Editor.node() };
if( node == nullptr ) { break; }
if( node == nullptr ) {
auto const mouseposition { Global.pCamera->Pos + GfxRenderer.Mouse_Position() };
uitextline1 = "mouse location: [" + to_string( mouseposition.x, 2 ) + ", " + to_string( mouseposition.y, 2 ) + ", " + to_string( mouseposition.z, 2 ) + "]";
break;
}
uitextline1 =
"Node name: " + node->name()
"node name: " + node->name()
+ "; location: [" + to_string( node->location().x, 2 ) + ", " + to_string( node->location().y, 2 ) + ", " + to_string( node->location().z, 2 ) + "]"
+ " (distance: " + to_string( glm::length( glm::dvec3{ node->location().x, 0.0, node->location().z } -glm::dvec3{ Global.pCameraPosition.x, 0.0, Global.pCameraPosition.z } ), 1 ) + " m)";
// subclass-specific data
@@ -724,7 +725,7 @@ ui_layer::update() {
auto const *subnode = static_cast<TAnimModel const *>( node );
uitextline2 = "angle: " + to_string( clamp_circular( subnode->vAngle.y, 360.0 ), 2 ) + " deg";
uitextline2 = "angle: " + to_string( clamp_circular( subnode->vAngle.y, 360.f ), 2 ) + " deg";
uitextline2 += "; lights: ";
if( subnode->iNumLights > 0 ) {
uitextline2 += '[';

View File

@@ -25,10 +25,11 @@ Copyright (C) 2007-2014 Maciej Cierniak
#include "utilities.h"
#include "globals.h"
#include "parser.h"
bool DebugModeFlag = false;
bool FreeFlyModeFlag = false;
bool EditorModeFlag = true;
bool EditorModeFlag = false;
bool DebugCameraFlag = false;
double Max0R(double x1, double x2)
@@ -387,3 +388,17 @@ substr_path( std::string const &Filename ) {
Filename.substr( 0, Filename.rfind( '/' ) + 1 ) :
"" );
}
// helper, restores content of a 3d vector from provided input stream
// TODO: review and clean up the helper routines, there's likely some redundant ones
glm::dvec3 LoadPoint( cParser &Input ) {
// pobranie współrzędnych punktu
Input.getTokens( 3 );
glm::dvec3 point;
Input
>> point.x
>> point.y
>> point.z;
return point;
}

View File

@@ -300,4 +300,8 @@ nearest_segment_point( VecType_ const &Segmentstart, VecType_ const &Segmentend,
return c1 / c2;
}
class cParser;
glm::dvec3 LoadPoint( cParser &Input );
//---------------------------------------------------------------------------

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 18
#define VERSION_MINOR 629
#define VERSION_MINOR 708
#define VERSION_REVISION 0