16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 11:39:19 +02:00

virtual slider mouse input mode, minor refactoring, minor bug fixes

This commit is contained in:
tmj-fstate
2018-07-11 17:45:50 +02:00
parent 1056f9bb14
commit 12d70fe320
20 changed files with 330 additions and 269 deletions

View File

@@ -67,8 +67,8 @@ TCamera::OnCommand( command_data const &Command ) {
case user_command::viewturn: { case user_command::viewturn: {
OnCursorMove( OnCursorMove(
reinterpret_cast<double const &>( Command.param1 ) * 0.005 * Global.fMouseXScale / Global.ZoomFactor, Command.param1 * 0.005 * Global.fMouseXScale / Global.ZoomFactor,
reinterpret_cast<double const &>( Command.param2 ) * 0.01 * Global.fMouseYScale / Global.ZoomFactor ); Command.param2 * 0.01 * Global.fMouseYScale / Global.ZoomFactor );
break; break;
} }
@@ -86,7 +86,7 @@ TCamera::OnCommand( command_data const &Command ) {
1.0 ); 1.0 );
// left-right // left-right
auto const movexparam { reinterpret_cast<double const &>( Command.param1 ) }; auto const movexparam { Command.param1 };
// 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed // 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed
auto const movex { walkspeed + ( std::max( 0.0, std::abs( movexparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) }; auto const movex { walkspeed + ( std::max( 0.0, std::abs( movexparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) };
@@ -96,7 +96,7 @@ TCamera::OnCommand( command_data const &Command ) {
0.0 ); 0.0 );
// forward-back // forward-back
double const movezparam { reinterpret_cast<double const &>( Command.param2 ) }; double const movezparam { Command.param2 };
auto const movez { walkspeed + ( std::max( 0.0, std::abs( movezparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) }; auto const movez { walkspeed + ( std::max( 0.0, std::abs( movezparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) };
// NOTE: z-axis is flipped given world coordinate system // NOTE: z-axis is flipped given world coordinate system
m_moverate.z = ( m_moverate.z = (
@@ -121,7 +121,7 @@ TCamera::OnCommand( command_data const &Command ) {
1.0 ); 1.0 );
// up-down // up-down
auto const moveyparam { reinterpret_cast<double const &>( Command.param1 ) }; auto const moveyparam { Command.param1 };
// 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed // 2/3rd of the stick range enables walk speed, past that we lerp between walk and run speed
auto const movey { walkspeed + ( std::max( 0.0, std::abs( moveyparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) }; auto const movey { walkspeed + ( std::max( 0.0, std::abs( moveyparam ) - 0.65 ) / 0.35 ) * ( movespeed - walkspeed ) };

View File

@@ -72,6 +72,7 @@ mouse_input Mouse;
gamepad_input Gamepad; gamepad_input Gamepad;
glm::dvec2 mouse_pickmodepos; // stores last mouse position in control picking mode glm::dvec2 mouse_pickmodepos; // stores last mouse position in control picking mode
std::unique_ptr<uart_input> uart; std::unique_ptr<uart_input> uart;
user_command command; // currently issued control command, if any
} }
@@ -170,13 +171,13 @@ void key_callback( GLFWwindow *window, int key, int scancode, int action, int mo
if( Global.ControlPicking ) { if( Global.ControlPicking ) {
// switch off // switch off
glfwGetCursorPos( window, &input::mouse_pickmodepos.x, &input::mouse_pickmodepos.y ); glfwGetCursorPos( window, &input::mouse_pickmodepos.x, &input::mouse_pickmodepos.y );
glfwSetInputMode( window, GLFW_CURSOR, GLFW_CURSOR_DISABLED ); UILayer.set_cursor( GLFW_CURSOR_DISABLED );
glfwSetCursorPos( window, 0, 0 ); glfwSetCursorPos( window, 0, 0 );
} }
else { else {
// enter picking mode // enter picking mode
glfwSetInputMode( window, GLFW_CURSOR, GLFW_CURSOR_NORMAL );
glfwSetCursorPos( window, input::mouse_pickmodepos.x, input::mouse_pickmodepos.y ); glfwSetCursorPos( window, input::mouse_pickmodepos.x, input::mouse_pickmodepos.y );
UILayer.set_cursor( GLFW_CURSOR_NORMAL );
} }
// actually toggle the mode // actually toggle the mode
Global.ControlPicking = !Global.ControlPicking; Global.ControlPicking = !Global.ControlPicking;
@@ -461,6 +462,11 @@ int main(int argc, char *argv[])
if( true == Global.InputMouse ) { input::Mouse.poll(); } if( true == Global.InputMouse ) { input::Mouse.poll(); }
if( true == Global.InputGamepad ) { input::Gamepad.poll(); } if( true == Global.InputGamepad ) { input::Gamepad.poll(); }
if( input::uart != nullptr ) { input::uart->poll(); } if( input::uart != nullptr ) { input::uart->poll(); }
// TODO: wrap current command in object, include other input sources
input::command = (
input::Mouse.command() != user_command::none ?
input::Mouse.command() :
input::Keyboard.command() );
} }
} }
catch( std::bad_alloc const &Error ) { catch( std::bad_alloc const &Error ) {

View File

@@ -179,7 +179,7 @@ TTrack * TTrack::Create400m(int what, double dx)
trk->Segment->Init( Math3D::vector3( -dx, 0, 0 ), Math3D::vector3( -dx, 0, 400 ), 10.0, 0, 0 ); // prosty trk->Segment->Init( Math3D::vector3( -dx, 0, 0 ), Math3D::vector3( -dx, 0, 400 ), 10.0, 0, 0 ); // prosty
trk->location( glm::dvec3{ -dx, 0, 200 } ); //środek, aby się mogło wyświetlić trk->location( glm::dvec3{ -dx, 0, 200 } ); //środek, aby się mogło wyświetlić
simulation::Paths.insert( trk ); simulation::Paths.insert( trk );
simulation::Region->insert_path( trk, scene::scratch_data() ); simulation::Region->insert( trk );
return trk; return trk;
}; };
@@ -273,11 +273,11 @@ TTrack * TTrack::NullCreate(int dir)
// trzeba jeszcze dodać do odpowiedniego segmentu, aby się renderowały z niego pojazdy // trzeba jeszcze dodać do odpowiedniego segmentu, aby się renderowały z niego pojazdy
trk->location( glm::dvec3{ 0.5 * ( p1 + p2 ) } ); //środek, aby się mogło wyświetlić trk->location( glm::dvec3{ 0.5 * ( p1 + p2 ) } ); //środek, aby się mogło wyświetlić
simulation::Paths.insert( trk ); simulation::Paths.insert( trk );
simulation::Region->insert_path( trk, scene::scratch_data() ); simulation::Region->insert( trk );
if( trk2 ) { if( trk2 ) {
trk2->location( trk->location() ); // ten sam środek jest trk2->location( trk->location() ); // ten sam środek jest
simulation::Paths.insert( trk2 ); simulation::Paths.insert( trk2 );
simulation::Region->insert_path( trk2, scene::scratch_data() ); simulation::Region->insert( trk2 );
} }
return trk; return trk;
}; };

View File

@@ -26,6 +26,12 @@ http://mozilla.org/MPL/2.0/.
#include "mtable.h" #include "mtable.h"
#include "Console.h" #include "Console.h"
namespace input {
extern user_command command;
}
void void
control_mapper::insert( TGauge const &Gauge, std::string const &Label ) { control_mapper::insert( TGauge const &Gauge, std::string const &Label ) {
@@ -922,7 +928,7 @@ void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &C
Train->mvControlled->LocalBrakePosA = ( Train->mvControlled->LocalBrakePosA = (
clamp( clamp(
reinterpret_cast<double const &>( Command.param1 ), Command.param1,
0.0, 1.0 ) ); 0.0, 1.0 ) );
/* /*
Train->mvControlled->LocalBrakePos = ( Train->mvControlled->LocalBrakePos = (
@@ -931,7 +937,7 @@ void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &C
0.0, 0.0,
LocalBrakePosNo, LocalBrakePosNo,
clamp( clamp(
reinterpret_cast<double const &>( Command.param1 ), Command.param1,
0.0, 1.0 ) ) ) ); 0.0, 1.0 ) ) ) );
*/ */
} }
@@ -1003,26 +1009,16 @@ void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Co
Train->set_train_brake( Train->mvOccupied->BrakeCtrlPos - Global.fBrakeStep ); Train->set_train_brake( Train->mvOccupied->BrakeCtrlPos - Global.fBrakeStep );
} }
} }
else {
// release
if( ( Train->mvOccupied->BrakeCtrlPos == -1 )
&& ( Train->mvOccupied->BrakeHandle == FVel6 )
&& ( Train->DynamicObject->Controller != AIdriver )
&& ( Global.iFeedbackMode < 3 ) ) {
// Odskakiwanie hamulce EP
Train->set_train_brake( 0 );
}
}
} }
void TTrain::OnCommand_trainbrakeset( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_trainbrakeset( TTrain *Train, command_data const &Command ) {
Train->mvControlled->BrakeLevelSet( Train->mvOccupied->BrakeLevelSet(
interpolate( interpolate(
Train->mvControlled->Handle->GetPos( bh_MIN ), Train->mvOccupied->Handle->GetPos( bh_MIN ),
Train->mvControlled->Handle->GetPos( bh_MAX ), Train->mvOccupied->Handle->GetPos( bh_MAX ),
clamp( clamp(
reinterpret_cast<double const &>( Command.param1 ), Command.param1,
0.0, 1.0 ) ) ); 0.0, 1.0 ) ) );
} }
@@ -4334,18 +4330,35 @@ bool TTrain::Update( double const Deltatime )
{ // Ra: TODO: odczyty klawiatury/pulpitu nie powinny być uzależnione od istnienia modelu kabiny { // Ra: TODO: odczyty klawiatury/pulpitu nie powinny być uzależnione od istnienia modelu kabiny
if( ( DynamicObject->Mechanik != nullptr ) if( ( DynamicObject->Mechanik != nullptr )
&& ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI && ( false == DynamicObject->Mechanik->AIControllFlag ) ) {
&& ( ( mvOccupied->TrainType == dt_ET40 ) // nie blokujemy AI
|| ( mvOccupied->TrainType == dt_EP05 ) ) ) { if( ( mvOccupied->TrainType == dt_ET40 )
// dla ET40 i EU05 automatyczne cofanie nastawnika - i tak nie będzie to działać dobrze... || ( mvOccupied->TrainType == dt_EP05 ) ) {
// TODO: remove direct keyboard check, use deltatime to stabilize speed // dla ET40 i EU05 automatyczne cofanie nastawnika - i tak nie będzie to działać dobrze...
if( ( glfwGetKey( Global.window, GLFW_KEY_KP_ADD ) != GLFW_TRUE ) // TODO: use deltatime to stabilize speed
&& ( mvOccupied->MainCtrlPos > mvOccupied->MainCtrlActualPos ) ) { if( false == (
mvOccupied->DecMainCtrl( 1 ); ( input::command == user_command::mastercontrollerset )
|| ( input::command == user_command::mastercontrollerincrease )
|| ( input::command == user_command::mastercontrollerdecrease ) ) ) {
if( mvOccupied->MainCtrlPos > mvOccupied->MainCtrlActualPos ) {
mvOccupied->DecMainCtrl( 1 );
}
else if( mvOccupied->MainCtrlPos < mvOccupied->MainCtrlActualPos ) {
// Ra 15-01: a to nie miało być tylko cofanie?
mvOccupied->IncMainCtrl( 1 );
}
}
} }
if( ( glfwGetKey( Global.window, GLFW_KEY_KP_SUBTRACT ) != GLFW_TRUE )
&& ( mvOccupied->MainCtrlPos < mvOccupied->MainCtrlActualPos ) ) { if( ( mvOccupied->BrakeHandle == FVel6 )
mvOccupied->IncMainCtrl( 1 ); // Ra 15-01: a to nie miało być tylko cofanie? && ( mvOccupied->fBrakeCtrlPos < 0.0 )
&& ( Global.iFeedbackMode < 3 ) ) {
// Odskakiwanie hamulce EP
if( false == (
( input::command == user_command::trainbrakeset )
|| ( input::command == user_command::trainbrakedecrease ) ) ) {
set_train_brake( 0 );
}
} }
} }

View File

@@ -648,6 +648,8 @@ private:
inline TDynamicObject const *Dynamic() const { return DynamicObject; }; inline TDynamicObject const *Dynamic() const { return DynamicObject; };
inline TMoverParameters *Controlled() { return mvControlled; }; inline TMoverParameters *Controlled() { return mvControlled; };
inline TMoverParameters const *Controlled() const { return mvControlled; }; inline TMoverParameters const *Controlled() const { return mvControlled; };
inline TMoverParameters *Occupied() { return mvOccupied; };
inline TMoverParameters const *Occupied() const { return mvOccupied; };
void DynamicSet(TDynamicObject *d); void DynamicSet(TDynamicObject *d);
}; };

View File

@@ -243,7 +243,7 @@ command_queue::pop( command_data &Command, std::size_t const Recipient ) {
} }
void void
command_relay::post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, int const Action, std::uint16_t const Recipient ) const { command_relay::post( user_command const Command, double const Param1, double const Param2, int const Action, std::uint16_t const Recipient ) const {
auto const &command = simulation::Commands_descriptions[ static_cast<std::size_t>( Command ) ]; auto const &command = simulation::Commands_descriptions[ static_cast<std::size_t>( Command ) ];
if( ( command.target == command_target::vehicle ) if( ( command.target == command_target::vehicle )

View File

@@ -231,8 +231,8 @@ struct command_data {
user_command command; user_command command;
int action; // press, repeat or release int action; // press, repeat or release
std::uint64_t param1; double param1;
std::uint64_t param2; double param2;
double time_delta; double time_delta;
}; };
@@ -282,7 +282,7 @@ public:
// posts specified command for the specified recipient // posts specified command for the specified recipient
// TODO: replace uint16_t with recipient handle, based on item id // TODO: replace uint16_t with recipient handle, based on item id
void void
post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, post( user_command const Command, double const Param1, double const Param2,
int const Action, std::uint16_t const Recipient ) const; int const Action, std::uint16_t const Recipient ) const;
private: private:
// types // types

View File

@@ -198,8 +198,8 @@ gamepad_input::process_axes( glm::vec2 Leftstick, glm::vec2 const &Rightstick, g
double const turny = -Rightstick.y * 10.0 * deltatime; double const turny = -Rightstick.y * 10.0 * deltatime;
m_relay.post( m_relay.post(
user_command::viewturn, user_command::viewturn,
reinterpret_cast<std::uint64_t const &>( turnx ), turnx,
reinterpret_cast<std::uint64_t const &>( turny ), turny,
GLFW_PRESS, GLFW_PRESS,
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // 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 // TODO: pass correct entity id once the missing systems are in place
@@ -211,12 +211,10 @@ gamepad_input::process_axes( glm::vec2 Leftstick, glm::vec2 const &Rightstick, g
if( ( Leftstick.x != 0.0 || Leftstick.y != 0.0 ) if( ( Leftstick.x != 0.0 || Leftstick.y != 0.0 )
|| ( m_leftstick.x != 0.0 || m_leftstick.y != 0.0 ) ) { || ( m_leftstick.x != 0.0 || m_leftstick.y != 0.0 ) ) {
double const movex = static_cast<double>( Leftstick.x );
double const movez = static_cast<double>( Leftstick.y );
m_relay.post( m_relay.post(
user_command::movehorizontal, user_command::movehorizontal,
reinterpret_cast<std::uint64_t const &>( movex ), Leftstick.x,
reinterpret_cast<std::uint64_t const &>( movez ), Leftstick.y,
GLFW_PRESS, GLFW_PRESS,
0 ); 0 );
} }

View File

@@ -161,6 +161,10 @@ keyboard_input::key( int const Key, int const Action ) {
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // 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 // TODO: pass correct entity id once the missing systems are in place
m_relay.post( lookup->second, 0, 0, Action, 0 ); m_relay.post( lookup->second, 0, 0, Action, 0 );
m_command = (
Action == GLFW_RELEASE ?
user_command::none :
lookup->second );
return true; return true;
} }
@@ -600,14 +604,12 @@ keyboard_input::poll() {
if( ( movementhorizontal.x != 0.f || movementhorizontal.y != 0.f ) if( ( movementhorizontal.x != 0.f || movementhorizontal.y != 0.f )
|| ( m_movementhorizontal.x != 0.f || m_movementhorizontal.y != 0.f ) ) { || ( m_movementhorizontal.x != 0.f || m_movementhorizontal.y != 0.f ) ) {
double const movexparam = static_cast<double>( movementhorizontal.x );
double const movezparam = static_cast<double>( movementhorizontal.y );
m_relay.post( m_relay.post(
( true == Global.ctrlState ? ( true == Global.ctrlState ?
user_command::movehorizontalfast : user_command::movehorizontalfast :
user_command::movehorizontal ), user_command::movehorizontal ),
reinterpret_cast<std::uint64_t const &>( movexparam ), movementhorizontal.x,
reinterpret_cast<std::uint64_t const &>( movezparam ), movementhorizontal.y,
GLFW_PRESS, GLFW_PRESS,
0 ); 0 );
} }
@@ -623,12 +625,11 @@ keyboard_input::poll() {
if( ( movementvertical != 0.f ) if( ( movementvertical != 0.f )
|| ( m_movementvertical != 0.f ) ) { || ( m_movementvertical != 0.f ) ) {
double const moveyparam = static_cast<double>( movementvertical );
m_relay.post( m_relay.post(
( true == Global.ctrlState ? ( true == Global.ctrlState ?
user_command::moveverticalfast : user_command::moveverticalfast :
user_command::movevertical ), user_command::movevertical ),
reinterpret_cast<std::uint64_t const &>( moveyparam ), movementvertical,
0, 0,
GLFW_PRESS, GLFW_PRESS,
0 ); 0 );

View File

@@ -28,6 +28,10 @@ public:
key( int const Key, int const Action ); key( int const Key, int const Action );
void void
poll(); poll();
inline
user_command const
command() const {
return m_command; }
private: private:
// types // types
@@ -65,6 +69,7 @@ private:
// members // members
commandsetup_sequence m_commands; commandsetup_sequence m_commands;
user_command m_command; // last, if any, issued command
usercommand_map m_bindings; usercommand_map m_bindings;
command_relay m_relay; command_relay m_relay;
bool m_shift{ false }; bool m_shift{ false };

View File

@@ -16,9 +16,111 @@ http://mozilla.org/MPL/2.0/.
#include "world.h" #include "world.h"
#include "train.h" #include "train.h"
#include "renderer.h" #include "renderer.h"
#include "uilayer.h"
extern TWorld World; extern TWorld World;
void
mouse_slider::bind( user_command const &Command ) {
m_command = Command;
auto const *train { World.train() };
TMoverParameters const *vehicle { nullptr };
switch( m_command ) {
case user_command::mastercontrollerset:
case user_command::secondcontrollerset: {
vehicle = ( train ? train->Controlled() : nullptr );
break;
}
case user_command::trainbrakeset:
case user_command::independentbrakeset: {
vehicle = ( train ? train->Occupied() : nullptr );
break;
}
default: {
break;
}
}
if( vehicle == nullptr ) { return; }
// calculate initial value and accepted range
switch( m_command ) {
case user_command::mastercontrollerset: {
m_valuerange = (
vehicle->CoupledCtrl ?
vehicle->MainCtrlPosNo + vehicle->ScndCtrlPosNo :
vehicle->MainCtrlPosNo );
m_value = (
vehicle->CoupledCtrl ?
vehicle->MainCtrlPos + vehicle->ScndCtrlPos :
vehicle->MainCtrlPos );
m_analogue = false;
break;
}
case user_command::secondcontrollerset: {
m_valuerange = vehicle->ScndCtrlPosNo;
m_value = vehicle->ScndCtrlPos;
m_analogue = false;
break;
}
case user_command::trainbrakeset: {
m_valuerange = 1.0;
m_value = ( vehicle->fBrakeCtrlPos - vehicle->Handle->GetPos( bh_MIN ) ) / ( vehicle->Handle->GetPos( bh_MAX ) - vehicle->Handle->GetPos( bh_MIN ) );
m_analogue = true;
break;
}
case user_command::independentbrakeset: {
m_valuerange = 1.0;
m_value = vehicle->LocalBrakePosA;
m_analogue = true;
break;
}
default: {
m_valuerange = 1;
break;
}
}
// hide the cursor and place it in accordance with current slider value
glfwGetCursorPos( Global.window, &m_cursorposition.x, &m_cursorposition.y );
UILayer.set_cursor( GLFW_CURSOR_DISABLED );
auto const controlsize { Global.iWindowHeight * 0.75 };
auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 };
auto const stepsize { controlsize / m_valuerange };
glfwSetCursorPos(
Global.window,
Global.iWindowWidth * 0.5,
( m_analogue ?
controledge - ( 1.0 - m_value ) * controlsize :
controledge - m_value * stepsize - 0.5 * stepsize ) );
}
void
mouse_slider::release() {
m_command = user_command::none;
glfwSetCursorPos( Global.window, m_cursorposition.x, m_cursorposition.y );
UILayer.set_cursor( GLFW_CURSOR_NORMAL );
}
void
mouse_slider::on_move( double const Mousex, double const Mousey ) {
auto const controlsize { Global.iWindowHeight * 0.75 };
auto const controledge { Global.iWindowHeight * 0.5 + controlsize * 0.5 };
auto const stepsize { controlsize / m_valuerange };
auto mousey = clamp( Mousey, controledge - controlsize, controledge );
m_value = (
m_analogue ?
1.0 - ( ( controledge - mousey ) / controlsize ) :
std::floor( ( controledge - mousey ) / stepsize ) );
}
bool bool
mouse_input::init() { mouse_input::init() {
@@ -40,8 +142,8 @@ mouse_input::move( double Mousex, double Mousey ) {
// default control mode // default control mode
m_relay.post( m_relay.post(
user_command::viewturn, user_command::viewturn,
reinterpret_cast<std::uint64_t const &>( Mousex ), Mousex,
reinterpret_cast<std::uint64_t const &>( Mousey ), Mousey,
GLFW_PRESS, GLFW_PRESS,
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // 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 // TODO: pass correct entity id once the missing systems are in place
@@ -49,6 +151,17 @@ mouse_input::move( double Mousex, double Mousey ) {
} }
else { else {
// control picking mode // control picking mode
if( m_slider.command() != user_command::none ) {
m_slider.on_move( Mousex, Mousey );
m_relay.post(
m_slider.command(),
m_slider.value(),
0,
GLFW_PRESS,
// TODO: pass correct entity id once the missing systems are in place
0 );
}
if( false == m_pickmodepanning ) { if( false == m_pickmodepanning ) {
// even if the view panning isn't active we capture the cursor position in case it does get activated // even if the view panning isn't active we capture the cursor position in case it does get activated
m_cursorposition.x = Mousex; m_cursorposition.x = Mousex;
@@ -59,8 +172,8 @@ mouse_input::move( double Mousex, double Mousey ) {
auto const viewoffset = cursorposition - m_cursorposition; auto const viewoffset = cursorposition - m_cursorposition;
m_relay.post( m_relay.post(
user_command::viewturn, user_command::viewturn,
reinterpret_cast<std::uint64_t const &>( viewoffset.x ), viewoffset.x,
reinterpret_cast<std::uint64_t const &>( viewoffset.y ), viewoffset.y,
GLFW_PRESS, GLFW_PRESS,
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 // 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 // TODO: pass correct entity id once the missing systems are in place
@@ -109,6 +222,11 @@ mouse_input::button( int const Button, int const Action ) {
mousecommand = user_command::none; mousecommand = user_command::none;
} }
else { else {
if( Button == GLFW_MOUSE_BUTTON_LEFT ) {
if( m_slider.command() != user_command::none ) {
m_slider.release();
}
}
// if it's the right mouse button that got released and we had no command active, we were potentially in view panning mode; stop it // if it's the right mouse button that got released and we had no command active, we were potentially in view panning mode; stop it
if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { if( Button == GLFW_MOUSE_BUTTON_RIGHT ) {
m_pickmodepanning = false; m_pickmodepanning = false;
@@ -140,11 +258,6 @@ mouse_input::button( int const Button, int const Action ) {
default: { break; } default: { break; }
} }
} }
// 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 ) { switch( mousecommand ) {
case user_command::mastercontrollerincrease: case user_command::mastercontrollerincrease:
@@ -161,10 +274,23 @@ mouse_input::button( int const Button, int const Action ) {
m_varyingpollrate = true; m_varyingpollrate = true;
break; 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: { default: {
break; break;
} }
} }
// 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 { else {
// if we don't have any recognized element under the cursor and the right button was pressed, enter view panning mode // if we don't have any recognized element under the cursor and the right button was pressed, enter view panning mode
@@ -204,16 +330,25 @@ mouse_input::poll() {
} }
} }
user_command
mouse_input::command() const {
return (
m_slider.command() != user_command::none ? m_slider.command() :
m_mousecommandleft != user_command::none ? m_mousecommandleft :
m_mousecommandright );
}
void void
mouse_input::default_bindings() { mouse_input::default_bindings() {
m_mousecommands = { m_mousecommands = {
{ "mainctrl:", { { "mainctrl:", {
user_command::mastercontrollerincrease, user_command::mastercontrollerset,
user_command::mastercontrollerdecrease } }, user_command::none } },
{ "scndctrl:", { { "scndctrl:", {
user_command::secondcontrollerincrease, user_command::secondcontrollerset,
user_command::secondcontrollerdecrease } }, user_command::none } },
{ "shuntmodepower:", { { "shuntmodepower:", {
user_command::secondcontrollerincrease, user_command::secondcontrollerincrease,
user_command::secondcontrollerdecrease } }, user_command::secondcontrollerdecrease } },
@@ -221,11 +356,11 @@ mouse_input::default_bindings() {
user_command::reverserincrease, user_command::reverserincrease,
user_command::reverserdecrease } }, user_command::reverserdecrease } },
{ "brakectrl:", { { "brakectrl:", {
user_command::trainbrakeincrease, user_command::trainbrakeset,
user_command::trainbrakedecrease } }, user_command::none } },
{ "localbrake:", { { "localbrake:", {
user_command::independentbrakeincrease, user_command::independentbrakeset,
user_command::independentbrakedecrease } }, user_command::none } },
{ "manualbrake:", { { "manualbrake:", {
user_command::manualbrakeincrease, user_command::manualbrakeincrease,
user_command::manualbrakedecrease } }, user_command::manualbrakedecrease } },

View File

@@ -12,6 +12,36 @@ http://mozilla.org/MPL/2.0/.
#include <unordered_map> #include <unordered_map>
#include "command.h" #include "command.h"
// virtual slider; value determined by position of the mouse
class mouse_slider {
public:
// constructors
mouse_slider() = default;
// methods
void
bind( user_command const &Command );
void
release();
void
on_move( double const Mousex, double const Mousey );
inline
user_command
command() const {
return m_command; }
double
value() const {
return m_value; }
private:
// members
user_command m_command { user_command::none };
double m_value { 0.0 };
double m_valuerange { 0.0 };
bool m_analogue { false };
glm::dvec2 m_cursorposition { 0.0 };
};
class mouse_input { class mouse_input {
public: public:
@@ -27,6 +57,8 @@ public:
move( double const Mousex, double const Mousey ); move( double const Mousex, double const Mousey );
void void
poll(); poll();
user_command
command() const;
private: private:
// types // types
@@ -44,6 +76,7 @@ private:
// members // members
command_relay m_relay; command_relay m_relay;
mouse_slider m_slider; // virtual control, when active translates intercepted mouse position to a value
controlcommands_map m_mousecommands; controlcommands_map m_mousecommands;
user_command m_mousecommandleft { user_command::none }; // last if any command issued with left mouse button user_command m_mousecommandleft { user_command::none }; // last if any command issued with left mouse button
user_command m_mousecommandright { user_command::none }; // last if any command issued with right mouse button user_command m_mousecommandright { user_command::none }; // last if any command issued with right mouse button

151
scene.cpp
View File

@@ -1118,7 +1118,7 @@ basic_region::RadioStop( glm::dvec3 const &Location ) {
} }
void void
basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad, bool const Transform ) { basic_region::insert( shape_node Shape, scratch_data &Scratchpad, bool const Transform ) {
// shape might need to be split into smaller pieces, so we create list of nodes instead of just single one // shape might need to be split into smaller pieces, so we create list of nodes instead of just single one
// using deque so we can do single pass iterating and addding generated pieces without invalidating anything // using deque so we can do single pass iterating and addding generated pieces without invalidating anything
@@ -1182,7 +1182,7 @@ basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad, bool con
// inserts provided lines in the region // inserts provided lines in the region
void void
basic_region::insert_lines( lines_node Lines, scratch_data &Scratchpad ) { basic_region::insert( lines_node Lines, scratch_data &Scratchpad ) {
if( Lines.m_data.vertices.empty() ) { return; } if( Lines.m_data.vertices.empty() ) { return; }
// transform point coordinates if needed // transform point coordinates if needed
@@ -1224,135 +1224,6 @@ basic_region::insert_lines( lines_node Lines, scratch_data &Scratchpad ) {
} }
} }
// inserts provided track in the region
void
basic_region::insert_path( TTrack *Path, scratch_data &Scratchpad ) {
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
auto location = Path->location();
if( point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
section( location ).insert( Path );
}
else {
// tracks are guaranteed to hava a name so we can skip the check
ErrorLog( "Bad scenario: track node \"" + Path->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
}
// also register path ends in appropriate sections, for path merging lookups
// TODO: clean this up during track refactoring
for( auto &point : Path->endpoints() ) {
register_path( Path, point );
}
}
// inserts provided track in the region
void
basic_region::insert_traction( TTraction *Traction, scratch_data &Scratchpad ) {
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
auto location = Traction->location();
if( point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
section( location ).insert( Traction );
}
else {
// tracks are guaranteed to hava a name so we can skip the check
ErrorLog( "Bad scenario: traction node \"" + Traction->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
}
// also register traction ends in appropriate sections, for path merging lookups
// TODO: clean this up during track refactoring
for( auto &point : Traction->endpoints() ) {
register_traction( Traction, point );
}
}
// inserts provided instance of 3d model in the region
void
basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ) {
auto const location { Instance->location() };
if( point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
section( location ).insert( Instance );
}
else {
// tracks are guaranteed to hava a name so we can skip the check
ErrorLog( "Bad scenario: model node \"" + Instance->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
}
}
// 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 );
}
}
// removes specified memory cell from the region
void
basic_region::erase_memorycell( TMemCell *Memorycell ) {
auto const location { Memorycell->location() };
if( point_inside( location ) ) {
section( location ).erase( Memorycell );
}
}
// inserts provided sound in the region
void
basic_region::insert_sound( sound_source *Sound, scratch_data &Scratchpad ) {
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
auto location = Sound->location();
if( point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
section( location ).insert( Sound );
}
else {
// tracks are guaranteed to hava a name so we can skip the check
ErrorLog( "Bad scenario: sound node \"" + Sound->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
}
}
// inserts provided event launcher in the region
void
basic_region::insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad ) {
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
auto location = Launcher->location();
if( point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
section( location ).insert( Launcher );
}
else {
// tracks are guaranteed to hava a name so we can skip the check
ErrorLog( "Bad scenario: event launcher \"" + Launcher->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
}
}
// inserts provided memory cell in the region
void
basic_region::insert_memorycell( TMemCell *Memorycell, scratch_data &Scratchpad ) {
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
auto location = Memorycell->location();
if( point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
section( location ).insert( Memorycell );
}
else {
// tracks are guaranteed to hava a name so we can skip the check
ErrorLog( "Bad scenario: memory cell \"" + Memorycell->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
}
}
// find a vehicle located neares to specified location, within specified radius, optionally discarding vehicles without drivers // find a vehicle located neares to specified location, within specified radius, optionally discarding vehicles without drivers
std::tuple<TDynamicObject *, float> std::tuple<TDynamicObject *, float>
basic_region::find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) { basic_region::find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) {
@@ -1463,24 +1334,6 @@ basic_region::sections( glm::dvec3 const &Point, float const Radius ) {
return m_scratchpad.sections; return m_scratchpad.sections;
} }
// registers specified path in the lookup directory of a cell enclosing specified point
void
basic_region::register_path( TTrack *Path, glm::dvec3 const &Point ) {
if( point_inside( Point ) ) {
section( Point ).register_node( Path, Point );
}
}
// registers specified end point of the provided traction piece in the lookup directory of the region
void
basic_region::register_traction( TTraction *Traction, glm::dvec3 const &Point ) {
if( point_inside( Point ) ) {
section( Point ).register_node( Traction, Point );
}
}
// checks whether specified point is within boundaries of the region // checks whether specified point is within boundaries of the region
bool bool
basic_region::point_inside( glm::dvec3 const &Location ) { basic_region::point_inside( glm::dvec3 const &Location ) {

53
scene.h
View File

@@ -339,34 +339,35 @@ public:
RadioStop( glm::dvec3 const &Location ); RadioStop( glm::dvec3 const &Location );
// inserts provided shape in the region // inserts provided shape in the region
void void
insert_shape( shape_node Shape, scratch_data &Scratchpad, bool const Transform ); insert( shape_node Shape, scratch_data &Scratchpad, bool const Transform );
// inserts provided lines in the region // inserts provided lines in the region
void void
insert_lines( lines_node Lines, scratch_data &Scratchpad ); insert( lines_node Lines, scratch_data &Scratchpad );
// inserts provided track in the region // inserts provided node in the region
template <class Type_>
void void
insert_path( TTrack *Path, scratch_data &Scratchpad ); insert( Type_ *Node ) {
// inserts provided track in the region auto const location { Node->location() };
if( false == point_inside( location ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
// TBD, TODO: clamp coordinates to region boundaries?
return; }
section( location ).insert( Node ); }
// inserts provided node in the region and registers its ends in lookup directory
template <class Type_>
void void
insert_traction( TTraction *Traction, scratch_data &Scratchpad ); insert_and_register( Type_ *Node ) {
// inserts provided instance of 3d model in the region insert( Node );
for( auto const &point : Node->endpoints() ) {
if( point_inside( point ) ) {
section( point ).register_node( Node, point ); } } }
// removes specified node from the region
template <class Type_>
void void
insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ); erase( Type_ *Node ) {
// inserts provided sound in the region auto const location{ Node->location() };
void if( point_inside( location ) ) {
insert_sound( sound_source *Sound, scratch_data &Scratchpad ); section( location ).erase( Node ); } }
// inserts provided event launcher in the region
void
insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad );
// 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 );
// removes specified memory cell from the region
void
erase_memorycell( TMemCell *Memorycell );
// find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance // find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float> std::tuple<TDynamicObject *, float>
find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ); find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );
@@ -393,12 +394,6 @@ private:
}; };
// methods // methods
// registers specified end point of the provided path in the lookup directory of the region
void
register_path( TTrack *Path, glm::dvec3 const &Point );
// registers specified end point of the provided traction piece in the lookup directory of the region
void
register_traction( TTraction *Traction, glm::dvec3 const &Point );
// checks whether specified point is within boundaries of the region // checks whether specified point is within boundaries of the region
bool bool
point_inside( glm::dvec3 const &Location ); point_inside( glm::dvec3 const &Location );

View File

@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
#include "globals.h" #include "globals.h"
#include "simulation.h" #include "simulation.h"
#include "uilayer.h"
#include "renderer.h" #include "renderer.h"
namespace scene { namespace scene {
@@ -46,7 +47,7 @@ basic_editor::on_mouse_button( int const Button, int const Action ) {
m_node = GfxRenderer.Update_Pick_Node(); m_node = GfxRenderer.Update_Pick_Node();
m_nodesnapshot = { m_node }; m_nodesnapshot = { m_node };
if( m_node ) { if( m_node ) {
glfwSetInputMode( Global.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED ); UILayer.set_cursor( GLFW_CURSOR_DISABLED );
} }
} }
else { else {
@@ -54,7 +55,7 @@ basic_editor::on_mouse_button( int const Button, int const Action ) {
// TODO: record the current undo step on the undo stack // TODO: record the current undo step on the undo stack
m_nodesnapshot = { m_node }; m_nodesnapshot = { m_node };
if( m_node ) { if( m_node ) {
glfwSetInputMode( Global.window, GLFW_CURSOR, GLFW_CURSOR_NORMAL ); UILayer.set_cursor( GLFW_CURSOR_NORMAL );
} }
} }
@@ -136,9 +137,9 @@ basic_editor::translate( float const Offset ) {
void void
basic_editor::translate_instance( TAnimModel *Instance, glm::dvec3 const &Location ) { basic_editor::translate_instance( TAnimModel *Instance, glm::dvec3 const &Location ) {
simulation::Region->erase_instance( Instance ); simulation::Region->erase( Instance );
Instance->location( Location ); Instance->location( Location );
simulation::Region->insert_instance( Instance, scene::scratch_data() ); simulation::Region->insert( Instance );
} }
void void
@@ -152,9 +153,9 @@ basic_editor::translate_instance( TAnimModel *Instance, float const Offset ) {
void void
basic_editor::translate_memorycell( TMemCell *Memorycell, glm::dvec3 const &Location ) { basic_editor::translate_memorycell( TMemCell *Memorycell, glm::dvec3 const &Location ) {
simulation::Region->erase_memorycell( Memorycell ); simulation::Region->erase( Memorycell );
Memorycell->location( Location ); Memorycell->location( Location );
simulation::Region->insert_memorycell( Memorycell, scene::scratch_data() ); simulation::Region->insert( Memorycell );
} }
void void
@@ -182,8 +183,8 @@ basic_editor::rotate_instance( TAnimModel *Instance, glm::vec3 const &Angle ) {
glm::vec3 angle = glm::dvec3 { Instance->Angles() }; glm::vec3 angle = glm::dvec3 { Instance->Angles() };
angle.y = clamp_circular( angle.y + Angle.y, 360.f ); angle.y = clamp_circular( angle.y + Angle.y, 360.f );
if( mode_snap() ) { if( mode_snap() ) {
auto const quantizationstep { 15.f }; // TBD, TODO: adjustable quantization step
angle.y = quantizationstep * std::round( angle.y * ( 1.f / quantizationstep ) ); angle.y = quantize( angle.y, 15.f );
} }
Instance->Angles( angle ); Instance->Angles( angle );
// update scene // update scene

View File

@@ -327,7 +327,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
delete pathnode; delete pathnode;
*/ */
} }
simulation::Region->insert_path( path, Scratchpad ); simulation::Region->insert_and_register( path );
} }
else if( nodedata.type == "traction" ) { else if( nodedata.type == "traction" ) {
@@ -338,7 +338,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
if( false == simulation::Traction.insert( traction ) ) { if( false == simulation::Traction.insert( traction ) ) {
ErrorLog( "Bad scenario: traction piece with duplicate name \"" + traction->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" ); ErrorLog( "Bad scenario: traction piece with duplicate name \"" + traction->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
} }
simulation::Region->insert_traction( traction, Scratchpad ); simulation::Region->insert_and_register( traction );
} }
else if( nodedata.type == "tractionpowersource" ) { else if( nodedata.type == "tractionpowersource" ) {
@@ -367,14 +367,14 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
auto const cellcount = instance->TerrainCount() + 1; // zliczenie submodeli auto const cellcount = instance->TerrainCount() + 1; // zliczenie submodeli
for( auto i = 1; i < cellcount; ++i ) { for( auto i = 1; i < cellcount; ++i ) {
auto *submodel = instance->TerrainSquare( i - 1 ); auto *submodel = instance->TerrainSquare( i - 1 );
simulation::Region->insert_shape( simulation::Region->insert(
scene::shape_node().convert( submodel ), scene::shape_node().convert( submodel ),
Scratchpad, Scratchpad,
false ); false );
// if there's more than one group of triangles in the cell they're held as children of the primary submodel // if there's more than one group of triangles in the cell they're held as children of the primary submodel
submodel = submodel->ChildGet(); submodel = submodel->ChildGet();
while( submodel != nullptr ) { while( submodel != nullptr ) {
simulation::Region->insert_shape( simulation::Region->insert(
scene::shape_node().convert( submodel ), scene::shape_node().convert( submodel ),
Scratchpad, Scratchpad,
false ); false );
@@ -398,7 +398,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
if( false == simulation::Instances.insert( instance ) ) { if( false == simulation::Instances.insert( instance ) ) {
ErrorLog( "Bad scenario: 3d model instance with duplicate name \"" + instance->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" ); ErrorLog( "Bad scenario: 3d model instance with duplicate name \"" + instance->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
} }
simulation::Region->insert_instance( instance, Scratchpad ); simulation::Region->insert( instance );
} }
} }
else if( ( nodedata.type == "triangles" ) else if( ( nodedata.type == "triangles" )
@@ -407,7 +407,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
if( false == Scratchpad.binary.terrain ) { if( false == Scratchpad.binary.terrain ) {
simulation::Region->insert_shape( simulation::Region->insert(
scene::shape_node().import( scene::shape_node().import(
Input, nodedata ), Input, nodedata ),
Scratchpad, Scratchpad,
@@ -424,7 +424,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
if( false == Scratchpad.binary.terrain ) { if( false == Scratchpad.binary.terrain ) {
simulation::Region->insert_lines( simulation::Region->insert(
scene::lines_node().import( scene::lines_node().import(
Input, nodedata ), Input, nodedata ),
Scratchpad ); Scratchpad );
@@ -440,7 +440,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
if( false == simulation::Memory.insert( memorycell ) ) { if( false == simulation::Memory.insert( memorycell ) ) {
ErrorLog( "Bad scenario: memory memorycell with duplicate name \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" ); ErrorLog( "Bad scenario: memory memorycell with duplicate name \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
} }
simulation::Region->insert_memorycell( memorycell, Scratchpad ); simulation::Region->insert( memorycell );
} }
else if( nodedata.type == "eventlauncher" ) { else if( nodedata.type == "eventlauncher" ) {
@@ -454,7 +454,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
simulation::Events.queue( eventlauncher ); simulation::Events.queue( eventlauncher );
} }
else { else {
simulation::Region->insert_launcher( eventlauncher, Scratchpad ); simulation::Region->insert( eventlauncher );
} }
} }
else if( nodedata.type == "sound" ) { else if( nodedata.type == "sound" ) {
@@ -463,7 +463,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
if( false == simulation::Sounds.insert( sound ) ) { if( false == simulation::Sounds.insert( sound ) ) {
ErrorLog( "Bad scenario: sound node with duplicate name \"" + sound->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" ); ErrorLog( "Bad scenario: sound node with duplicate name \"" + sound->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
} }
simulation::Region->insert_sound( sound, Scratchpad ); simulation::Region->insert( sound );
} }
} }

View File

@@ -208,7 +208,7 @@ void uart_input::poll()
double const position { (float)( ( (uint16_t)buffer[ 8 ] | ( (uint16_t)buffer[ 9 ] << 8 ) ) - conf.mainbrakemin ) / ( conf.mainbrakemax - conf.mainbrakemin ) }; double const position { (float)( ( (uint16_t)buffer[ 8 ] | ( (uint16_t)buffer[ 9 ] << 8 ) ) - conf.mainbrakemin ) / ( conf.mainbrakemax - conf.mainbrakemin ) };
relay.post( relay.post(
user_command::trainbrakeset, user_command::trainbrakeset,
reinterpret_cast<std::uint64_t const &>( position ), position,
0, 0,
GLFW_PRESS, GLFW_PRESS,
// TODO: pass correct entity id once the missing systems are in place // TODO: pass correct entity id once the missing systems are in place
@@ -219,7 +219,7 @@ void uart_input::poll()
double const position { (float)( ( (uint16_t)buffer[ 10 ] | ( (uint16_t)buffer[ 11 ] << 8 ) ) - conf.localbrakemin ) / ( conf.localbrakemax - conf.localbrakemin ) }; double const position { (float)( ( (uint16_t)buffer[ 10 ] | ( (uint16_t)buffer[ 11 ] << 8 ) ) - conf.localbrakemin ) / ( conf.localbrakemax - conf.localbrakemin ) };
relay.post( relay.post(
user_command::independentbrakeset, user_command::independentbrakeset,
reinterpret_cast<std::uint64_t const &>( position ), position,
0, 0,
GLFW_PRESS, GLFW_PRESS,
// TODO: pass correct entity id once the missing systems are in place // TODO: pass correct entity id once the missing systems are in place

View File

@@ -109,7 +109,7 @@ ui_layer::on_key( int const Key, int const Action ) {
EditorModeFlag = ( Key == GLFW_KEY_F11 ); EditorModeFlag = ( Key == GLFW_KEY_F11 );
if( ( true == EditorModeFlag ) if( ( true == EditorModeFlag )
&& ( false == Global.ControlPicking ) ) { && ( false == Global.ControlPicking ) ) {
glfwSetInputMode( m_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL ); set_cursor( GLFW_CURSOR_NORMAL );
Global.ControlPicking = true; Global.ControlPicking = true;
} }
} }
@@ -1113,6 +1113,13 @@ ui_layer::render() {
glPopAttrib(); glPopAttrib();
} }
void
ui_layer::set_cursor( int const Mode ) {
glfwSetInputMode( m_window, GLFW_CURSOR, Mode );
m_cursorvisible = ( Mode != GLFW_CURSOR_DISABLED );
}
void void
ui_layer::set_progress( float const Progress, float const Subtaskprogress ) { ui_layer::set_progress( float const Progress, float const Subtaskprogress ) {
@@ -1214,6 +1221,7 @@ void
ui_layer::render_tooltip() { ui_layer::render_tooltip() {
if( m_tooltip.empty() ) { return; } if( m_tooltip.empty() ) { return; }
if( false == m_cursorvisible ) { return; }
glm::dvec2 mousepos; glm::dvec2 mousepos;
glfwGetCursorPos( m_window, &mousepos.x, &mousepos.y ); glfwGetCursorPos( m_window, &mousepos.x, &mousepos.y );

View File

@@ -52,6 +52,9 @@ public:
// draws requested UI elements // draws requested UI elements
void void
render(); render();
//
void
set_cursor( int const Mode );
// stores operation progress // stores operation progress
void void
set_progress( float const Progress = 0.0f, float const Subtaskprogress = 0.0f ); set_progress( float const Progress = 0.0f, float const Subtaskprogress = 0.0f );
@@ -114,6 +117,7 @@ private:
int tprev; // poprzedni czas int tprev; // poprzedni czas
double VelPrev; // poprzednia prędkość double VelPrev; // poprzednia prędkość
double Acc; // przyspieszenie styczne double Acc; // przyspieszenie styczne
bool m_cursorvisible { false };
}; };
extern ui_layer UILayer; extern ui_layer UILayer;

View File

@@ -228,6 +228,13 @@ clamp_circular( Type_ Value, Type_ const Range = static_cast<Type_>(360) ) {
return Value; return Value;
} }
template <typename Type_>
Type_
quantize( Type_ const Value, Type_ const Step ) {
return ( Step * std::round( Value / Step ) );
}
template <typename Type_> template <typename Type_>
Type_ Type_
min_speed( Type_ const Left, Type_ const Right ) { min_speed( Type_ const Left, Type_ const Right ) {