16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 18:39:18 +02:00
This commit is contained in:
milek7
2018-10-24 12:59:34 +02:00
parent 472255931d
commit 8abe898735
8 changed files with 150 additions and 120 deletions

View File

@@ -147,6 +147,9 @@ eu07_application::run() {
// main application loop // main application loop
while (!glfwWindowShouldClose( m_windows.front() ) && !m_modestack.empty()) while (!glfwWindowShouldClose( m_windows.front() ) && !m_modestack.empty())
{ {
Timer::subsystem.mainloop_total.start();
glfwPollEvents();
if (!m_modes[ m_modestack.top() ]->update()) if (!m_modes[ m_modestack.top() ]->update())
break; break;
if (!GfxRenderer.Render()) if (!GfxRenderer.Render())
@@ -154,9 +157,6 @@ eu07_application::run() {
GfxRenderer.SwapBuffers(); GfxRenderer.SwapBuffers();
Timer::subsystem.mainloop_total.start();
glfwPollEvents();
if (m_modestack.empty()) if (m_modestack.empty())
return 0; return 0;

View File

@@ -288,12 +288,13 @@ drivermouse_input::button( int const Button, int const Action ) {
// left mouse button launches on_click event associated with to the node // left mouse button launches on_click event associated with to the node
if( Button == GLFW_MOUSE_BUTTON_LEFT ) { if( Button == GLFW_MOUSE_BUTTON_LEFT ) {
if( Action == GLFW_PRESS ) { if( Action == GLFW_PRESS ) {
auto const *node { GfxRenderer.Update_Pick_Node() }; GfxRenderer.pick_node([this](scene::basic_node *node)
if( ( node == nullptr ) {
|| ( typeid( *node ) != typeid( TAnimModel ) ) ) { if( ( node == nullptr )
return; || ( typeid( *node ) != typeid( TAnimModel ) ) )
} return;
simulation::Region->on_click( static_cast<TAnimModel const *>( node ) ); simulation::Region->on_click( static_cast<TAnimModel const *>( node ) );
});
} }
} }
// right button controls panning // right button controls panning
@@ -333,67 +334,71 @@ drivermouse_input::button( int const Button, int const Action ) {
} }
else { else {
// if not release then it's press // if not release then it's press
auto const lookup = m_buttonbindings.find( simulation::Train->GetLabel( GfxRenderer.Update_Pick_Control() ) );
if( lookup != m_buttonbindings.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; }
}
}
switch( mousecommand ) { GfxRenderer.pick_control([this, Button, Action, &mousecommand](TSubModel const *control)
case user_command::mastercontrollerincrease: {
case user_command::mastercontrollerdecrease: auto const lookup = m_buttonbindings.find( simulation::Train->GetLabel( control ) );
case user_command::secondcontrollerincrease: if( lookup != m_buttonbindings.end() ) {
case user_command::secondcontrollerdecrease: // if the recognized element under the cursor has a command associated with the pressed button, notify the recipient
case user_command::trainbrakeincrease: mousecommand = (
case user_command::trainbrakedecrease: Button == GLFW_MOUSE_BUTTON_LEFT ?
case user_command::independentbrakeincrease: lookup->second.left :
case user_command::independentbrakedecrease: { lookup->second.right
// 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 if( mousecommand == user_command::none ) { return; }
m_varyingpollrateorigin = m_cursorposition; // check manually for commands which have 'fast' variants launched with shift modifier
m_varyingpollrate = true; if( Global.shiftState ) {
break; 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; }
}
} }
case user_command::mastercontrollerset:
case user_command::secondcontrollerset: switch( mousecommand ) {
case user_command::trainbrakeset: case user_command::mastercontrollerincrease:
case user_command::independentbrakeset: { case user_command::mastercontrollerdecrease:
m_slider.bind( mousecommand ); case user_command::secondcontrollerincrease:
mousecommand = user_command::none; case user_command::secondcontrollerdecrease:
return; 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;
}
case user_command::mastercontrollerset:
case user_command::secondcontrollerset:
case user_command::trainbrakeset:
case user_command::independentbrakeset: {
m_slider.bind( mousecommand );
mousecommand = user_command::none;
return;
}
default: {
break;
}
} }
default: { // NOTE: basic keyboard controls don't have any parameters
break; // 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
}
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
}
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;
}
}
} }
} }
} }

View File

@@ -173,16 +173,16 @@ driver_ui::update() {
if( ( train != nullptr ) && ( false == FreeFlyModeFlag ) ) { if( ( train != nullptr ) && ( false == FreeFlyModeFlag ) ) {
if( false == DebugModeFlag ) { if( false == DebugModeFlag ) {
// in regular mode show control functions, for defined controls // in regular mode show control functions, for defined controls
set_tooltip( locale::label_cab_control( train->GetLabel( GfxRenderer.Pick_Control() ) ) ); set_tooltip( locale::label_cab_control( train->GetLabel( GfxRenderer.get_picked_control() ) ) );
} }
else { else {
// in debug mode show names of submodels, to help with cab setup and/or debugging // in debug mode show names of submodels, to help with cab setup and/or debugging
auto const cabcontrol = GfxRenderer.Pick_Control(); auto const cabcontrol = GfxRenderer.get_picked_control();
set_tooltip( ( cabcontrol ? cabcontrol->pName : "" ) ); set_tooltip( ( cabcontrol ? cabcontrol->pName : "" ) );
} }
} }
if( ( true == Global.ControlPicking ) && ( true == FreeFlyModeFlag ) && ( true == DebugModeFlag ) ) { if( ( true == Global.ControlPicking ) && ( true == FreeFlyModeFlag ) && ( true == DebugModeFlag ) ) {
auto const scenerynode = GfxRenderer.Pick_Node(); auto const scenerynode = GfxRenderer.get_picked_node();
set_tooltip( set_tooltip(
( scenerynode ? ( scenerynode ?
scenerynode->name() : scenerynode->name() :

View File

@@ -230,17 +230,24 @@ editor_mode::on_mouse_button( int const Button, int const Action, int const Mods
if( Action == GLFW_PRESS ) { if( Action == GLFW_PRESS ) {
// left button press // left button press
m_node = GfxRenderer.Update_Pick_Node(); GfxRenderer.pick_node([this](scene::basic_node *node)
if( m_node ) { {
Application.set_cursor( GLFW_CURSOR_DISABLED ); if (!m_dragging)
} return;
dynamic_cast<editor_ui*>( m_userinterface.get() )->set_node( m_node ); m_node = node;
if( m_node )
Application.set_cursor( GLFW_CURSOR_DISABLED );
else
m_dragging = false;
dynamic_cast<editor_ui*>( m_userinterface.get() )->set_node( m_node );
});
m_dragging = true;
} }
else { else {
// left button release // left button release
if( m_node ) { if( m_node )
Application.set_cursor( GLFW_CURSOR_NORMAL ); Application.set_cursor( GLFW_CURSOR_NORMAL );
} m_dragging = false;
// prime history stack for another snapshot // prime history stack for another snapshot
m_takesnapshot = true; m_takesnapshot = true;
} }

View File

@@ -82,5 +82,5 @@ private:
scene::basic_node *m_node; // currently selected scene node scene::basic_node *m_node; // currently selected scene node
bool m_takesnapshot { true }; // helper, hints whether snapshot of selected node(s) should be taken before modification bool m_takesnapshot { true }; // helper, hints whether snapshot of selected node(s) should be taken before modification
state_backup m_statebackup; // helper, cached variables to be restored on mode exit state_backup m_statebackup; // helper, cached variables to be restored on mode exit
bool m_dragging = false;
}; };

View File

@@ -38,7 +38,7 @@ editor_ui::update() {
if( ( true == Global.ControlPicking ) if( ( true == Global.ControlPicking )
&& ( true == DebugModeFlag ) ) { && ( true == DebugModeFlag ) ) {
auto const scenerynode = GfxRenderer.Pick_Node(); auto const scenerynode = GfxRenderer.get_picked_node();
set_tooltip( set_tooltip(
( scenerynode ? ( scenerynode ?
scenerynode->name() : scenerynode->name() :

View File

@@ -3351,7 +3351,7 @@ void opengl_renderer::Render_Alpha(TSubModel *Submodel)
}; };
// utility methods // utility methods
TSubModel const *opengl_renderer::Update_Pick_Control() void opengl_renderer::Update_Pick_Control()
{ {
if (!m_picking_pbo->is_busy()) if (!m_picking_pbo->is_busy())
{ {
@@ -3366,26 +3366,31 @@ TSubModel const *opengl_renderer::Update_Pick_Control()
} }
m_pickcontrolitem = control; m_pickcontrolitem = control;
for (auto f : m_control_pick_requests)
f(m_pickcontrolitem);
m_control_pick_requests.clear();
} }
// determine point to examine if (!m_control_pick_requests.empty())
glm::dvec2 mousepos = Application.get_cursor_pos(); {
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl // determine point to examine
glm::dvec2 mousepos = Application.get_cursor_pos();
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl
glm::ivec2 pickbufferpos; glm::ivec2 pickbufferpos;
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)}; pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1)); pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1));
Render_pass(rendermode::pickcontrols); Render_pass(rendermode::pickcontrols);
m_pick_fb->bind(); m_pick_fb->bind();
m_picking_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1); m_picking_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1);
m_pick_fb->unbind(); m_pick_fb->unbind();
}
} }
return m_pickcontrolitem;
} }
scene::basic_node *opengl_renderer::Update_Pick_Node() void opengl_renderer::Update_Pick_Node()
{ {
if (!m_picking_node_pbo->is_busy()) if (!m_picking_node_pbo->is_busy())
{ {
@@ -3400,23 +3405,38 @@ scene::basic_node *opengl_renderer::Update_Pick_Node()
} }
m_picksceneryitem = node; m_picksceneryitem = node;
for (auto f : m_node_pick_requests)
f(m_picksceneryitem);
m_node_pick_requests.clear();
} }
// determine point to examine if (!m_picking_node_pbo->is_busy())
glm::dvec2 mousepos = Application.get_cursor_pos(); {
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl // determine point to examine
glm::dvec2 mousepos = Application.get_cursor_pos();
mousepos.y = Global.iWindowHeight - mousepos.y; // cursor coordinates are flipped compared to opengl
glm::ivec2 pickbufferpos; glm::ivec2 pickbufferpos;
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)}; pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1)); pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1));
Render_pass(rendermode::pickscenery); Render_pass(rendermode::pickscenery);
m_pick_fb->bind(); m_pick_fb->bind();
m_picking_node_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1); m_picking_node_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1);
m_pick_fb->unbind(); m_pick_fb->unbind();
}
} }
}
return m_picksceneryitem; void opengl_renderer::pick_control(std::function<void(TSubModel const *)> callback)
{
m_control_pick_requests.push_back(callback);
}
void opengl_renderer::pick_node(std::function<void(scene::basic_node *)> callback)
{
m_node_pick_requests.push_back(callback);
} }
glm::dvec3 opengl_renderer::Update_Mouse_Position() glm::dvec3 opengl_renderer::Update_Mouse_Position()
@@ -3446,6 +3466,9 @@ glm::dvec3 opengl_renderer::Update_Mouse_Position()
void opengl_renderer::Update(double const Deltatime) void opengl_renderer::Update(double const Deltatime)
{ {
Update_Pick_Control();
Update_Pick_Node();
m_updateaccumulator += Deltatime; m_updateaccumulator += Deltatime;
if (m_updateaccumulator < 1.0) if (m_updateaccumulator < 1.0)
@@ -3497,22 +3520,11 @@ void opengl_renderer::Update(double const Deltatime)
} }
if ((true == Global.ControlPicking) && (false == FreeFlyModeFlag)) if ((true == Global.ControlPicking) && (false == FreeFlyModeFlag))
{ pick_control([](const TSubModel*) {});
Update_Pick_Control();
}
else
{
m_pickcontrolitem = nullptr;
}
// temporary conditions for testing. eventually will be coupled with editor mode // temporary conditions for testing. eventually will be coupled with editor mode
if ((true == Global.ControlPicking) && (true == DebugModeFlag) && (true == FreeFlyModeFlag)) if ((true == Global.ControlPicking) && (true == DebugModeFlag) && (true == FreeFlyModeFlag))
{ pick_node([](scene::basic_node*) {});
Update_Pick_Node();
}
else
{
m_picksceneryitem = nullptr;
}
// dump last opengl error, if any // dump last opengl error, if any
auto const glerror = ::glGetError(); auto const glerror = ::glGetError();
if (glerror != GL_NO_ERROR) if (glerror != GL_NO_ERROR)

View File

@@ -166,11 +166,11 @@ class opengl_renderer
void Bind_Texture(size_t Unit, texture_handle const Texture); void Bind_Texture(size_t Unit, texture_handle const Texture);
opengl_texture &Texture(texture_handle const Texture) const; opengl_texture &Texture(texture_handle const Texture) const;
// utility methods // utility methods
TSubModel const *Pick_Control() const TSubModel const *get_picked_control() const
{ {
return m_pickcontrolitem; return m_pickcontrolitem;
} }
scene::basic_node const *Pick_Node() const scene::basic_node const *get_picked_node() const
{ {
return m_picksceneryitem; return m_picksceneryitem;
} }
@@ -180,13 +180,16 @@ class opengl_renderer
} }
// maintenance methods // maintenance methods
void Update(double const Deltatime); void Update(double const Deltatime);
TSubModel const *Update_Pick_Control(); void Update_Pick_Control();
scene::basic_node *Update_Pick_Node(); void Update_Pick_Node();
glm::dvec3 Update_Mouse_Position(); glm::dvec3 Update_Mouse_Position();
// debug methods // debug methods
std::string const &info_times() const; std::string const &info_times() const;
std::string const &info_stats() const; std::string const &info_stats() const;
void pick_control(std::function<void(TSubModel const *)> callback);
void pick_node(std::function<void(scene::basic_node *)> callback);
// members // members
GLenum static const sunlight{0}; GLenum static const sunlight{0};
std::size_t m_drawcount{0}; std::size_t m_drawcount{0};
@@ -338,6 +341,9 @@ class opengl_renderer
glm::mat4 ortho_projection(float left, float right, float bottom, float top, float z_near, float z_far); glm::mat4 ortho_projection(float left, float right, float bottom, float top, float z_near, float z_far);
glm::mat4 ortho_frustumtest_projection(float left, float right, float bottom, float top, float z_near, float z_far); glm::mat4 ortho_frustumtest_projection(float left, float right, float bottom, float top, float z_near, float z_far);
std::vector<std::function<void(TSubModel const *)>> m_control_pick_requests;
std::vector<std::function<void(scene::basic_node *)>> m_node_pick_requests;
std::unique_ptr<gl::shader> m_vertex_shader; std::unique_ptr<gl::shader> m_vertex_shader;
std::unique_ptr<gl::ubo> scene_ubo; std::unique_ptr<gl::ubo> scene_ubo;