mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
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:
@@ -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;
|
||||
|
||||
13
AnimModel.h
13
AnimModel.h
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
1
Camera.h
1
Camera.h
@@ -31,7 +31,6 @@ class TCamera {
|
||||
Math3D::vector3 GetDirection();
|
||||
bool SetMatrix(glm::dmat4 &Matrix);
|
||||
void RaLook();
|
||||
void Stop();
|
||||
|
||||
TCameraType Type;
|
||||
double Pitch;
|
||||
|
||||
21
EU07.cpp
21
EU07.cpp
@@ -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 ) {
|
||||
|
||||
53
EvLaunch.cpp
53
EvLaunch.cpp
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
17
Segment.cpp
17
Segment.cpp
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
17
Track.h
@@ -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 );
|
||||
|
||||
11
Traction.cpp
11
Traction.cpp
@@ -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
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// button press
|
||||
// freefly mode
|
||||
// left mouse button launches on_click event associated with to the node
|
||||
if( Button == GLFW_MOUSE_BUTTON_LEFT ) {
|
||||
// the left button selects scene node
|
||||
// further behaviour can vary depending on whether we're in editor mode
|
||||
if( Action == GLFW_PRESS ) {
|
||||
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;
|
||||
if( ( node == nullptr )
|
||||
|| ( typeid( *node ) != typeid( TAnimModel ) ) ) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// launch on_click event associated with to the node
|
||||
// TODO: implement
|
||||
simulation::Region->on_click( static_cast<TAnimModel const *>( node ) );
|
||||
}
|
||||
}
|
||||
// right button controls panning
|
||||
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
|
||||
// the right button activates mouse panning mode
|
||||
m_pickmodepanning = true;
|
||||
}
|
||||
m_pickmodepanning = ( Action == GLFW_PRESS );
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -130,16 +119,15 @@ 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() ) );
|
||||
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 ) {
|
||||
if( mousecommand == user_command::none ) { return; }
|
||||
// check manually for commands which have 'fast' variants launched with shift modifier
|
||||
if( Global.shiftState ) {
|
||||
switch( mousecommand ) {
|
||||
@@ -153,7 +141,7 @@ mouse_input::button( int const Button, int const Action ) {
|
||||
}
|
||||
}
|
||||
// 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
|
||||
// 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
|
||||
@@ -169,7 +157,7 @@ mouse_input::button( int const Button, int const Action ) {
|
||||
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_varyingpollrateorigin = m_cursorposition;
|
||||
m_varyingpollrate = true;
|
||||
break;
|
||||
}
|
||||
@@ -178,7 +166,6 @@ mouse_input::button( int const Button, int const Action ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ) {
|
||||
@@ -187,7 +174,6 @@ mouse_input::button( int const Button, int const Action ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -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 ) {
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
60
renderer.cpp
60
renderer.cpp
@@ -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 ) {
|
||||
|
||||
|
||||
24
renderer.h
24
renderer.h
@@ -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
106
scene.cpp
@@ -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
28
scene.h
@@ -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
165
sceneeditor.cpp
Normal 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
73
sceneeditor.h
Normal 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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -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(
|
||||
glm::dvec3 { 0.0 } :
|
||||
glm::dvec3 {
|
||||
Scratchpad.location.offset.top().x,
|
||||
Scratchpad.location.offset.top().y,
|
||||
Scratchpad.location.offset.top().z ) );
|
||||
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 ) );
|
||||
|
||||
17
uilayer.cpp
17
uilayer.cpp
@@ -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 += '[';
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -300,4 +300,8 @@ nearest_segment_point( VecType_ const &Segmentstart, VecType_ const &Segmentend,
|
||||
return c1 / c2;
|
||||
}
|
||||
|
||||
class cParser;
|
||||
|
||||
glm::dvec3 LoadPoint( cParser &Input );
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user