imgui user interface implementation

This commit is contained in:
tmj-fstate
2018-08-30 20:41:14 +02:00
parent 8b285834b0
commit 0c062e9041
25 changed files with 1563 additions and 1118 deletions

View File

@@ -125,7 +125,7 @@ class TAnimAdvanced
class TAnimModel : public scene::basic_node {
friend opengl_renderer;
friend editor_ui;
friend itemproperties_panel;
public:
// constructors

View File

@@ -33,6 +33,7 @@ class scenario_time;
class TMoverParameters;
class ui_layer;
class editor_ui;
class itemproperties_panel;
class event_manager;
class memory_table;
class powergridsource_table;
@@ -42,6 +43,7 @@ struct light_array;
namespace scene {
struct node_data;
class basic_node;
}
namespace Mtable

View File

@@ -321,7 +321,7 @@ bool TSpeedPos::Update()
return false;
};
std::string TSpeedPos::GetName()
std::string TSpeedPos::GetName() const
{
if (iFlags & spTrack) // jeśli tor
return trTrack->name();
@@ -331,7 +331,7 @@ std::string TSpeedPos::GetName()
return "";
}
std::string TSpeedPos::TableText()
std::string TSpeedPos::TableText() const
{ // pozycja tabelki pr?dko?ci
if (iFlags & spEnabled)
{ // o ile pozycja istotna
@@ -1639,7 +1639,7 @@ TController::~TController()
CloseLog();
};
std::string TController::Order2Str(TOrders Order)
std::string TController::Order2Str(TOrders Order) const
{ // zamiana kodu rozkazu na opis
if (Order & Change_direction)
return "Change_direction"; // może być nałożona na inną i wtedy ma priorytet
@@ -1674,9 +1674,9 @@ std::string TController::Order2Str(TOrders Order)
return "Undefined!";
}
std::string TController::OrderCurrent()
std::string TController::OrderCurrent() const
{ // pobranie aktualnego rozkazu celem wyświetlenia
return std::to_string(OrderPos) + ". " + Order2Str(OrderList[OrderPos]);
return "[" + std::to_string(OrderPos) + "] " + Order2Str(OrderList[OrderPos]);
};
void TController::OrdersClear()
@@ -2244,7 +2244,7 @@ void TController::SetVelocity(double NewVel, double NewVelNext, TStopReason r)
VelNext = NewVelNext; // prędkość przy następnym obiekcie
}
double TController::BrakeAccFactor()
double TController::BrakeAccFactor() const
{
double Factor = 1.0;
if( ( ActualProximityDist > fMinProximityDist )
@@ -4916,7 +4916,7 @@ TController::UpdateSituation(double dt) {
&& ( pVehicles[0]->fTrackBlock < 50.0 ) ) {
// crude detection of edge case, if approaching another vehicle coast slowly until min distance
// this should allow to bunch up trainsets more on sidings
VelDesired = min_speed( VelDesired, 5.0 );
VelDesired = min_speed( 5.0, VelDesired );
}
else {
// hamowanie tak, aby stanąć
@@ -4934,7 +4934,7 @@ TController::UpdateSituation(double dt) {
else {
// outside of max safe range
AccDesired = AccPreferred;
if( vel > min_speed( 10.0, VelDesired ) ) {
if( vel > min_speed( (ActualProximityDist > 10.0 ? 10.0 : 5.0 ), VelDesired ) ) {
// allow to coast at reasonably low speed
auto const brakingdistance { fBrakeDist * braking_distance_multiplier( VelNext ) };
auto const slowdowndistance { (
@@ -6026,7 +6026,7 @@ TCommandType TController::BackwardScan()
return TCommandType::cm_Unknown; // nic
};
std::string TController::NextStop()
std::string TController::NextStop() const
{ // informacja o następnym zatrzymaniu, wyświetlane pod [F1]
if (asNextStop == "[End of route]")
return ""; // nie zawiera nazwy stacji, gdy dojechał do końca
@@ -6130,7 +6130,7 @@ TController::TrainTimetable() const {
return TrainParams;
}
std::string TController::Relation()
std::string TController::Relation() const
{ // zwraca relację pociągu
return TrainParams->ShowRelation();
};
@@ -6150,7 +6150,7 @@ int TController::StationIndex() const
return TrainParams->StationIndex;
};
bool TController::IsStop()
bool TController::IsStop() const
{ // informuje, czy jest zatrzymanie na najbliższej stacji
return TrainParams->IsStop();
};
@@ -6181,7 +6181,7 @@ void TController::ControllingSet()
mvControlling = pVehicle->ControlledFind()->MoverParameters; // poszukiwanie członu sterowanego
};
std::string TController::TableText( std::size_t const Index )
std::string TController::TableText( std::size_t const Index ) const
{ // pozycja tabelki prędkości
if( Index < sSpeedTable.size() ) {
return sSpeedTable[ Index ].TableText();

View File

@@ -154,8 +154,8 @@ class TSpeedPos
fDist -= dist; }
bool Set(TEvent *e, double d, TOrders order = Wait_for_orders);
void Set(TTrack *t, double d, int f);
std::string TableText();
std::string GetName();
std::string TableText() const;
std::string GetName() const;
bool IsProperSemaphor(TOrders order = Wait_for_orders);
};
@@ -205,7 +205,7 @@ public:
double fVelMax = -1.0; // maksymalna prędkość składu (sprawdzany każdy pojazd)
public:
double fBrakeDist = 0.0; // przybliżona droga hamowania
double BrakeAccFactor();
double BrakeAccFactor() const;
double fBrakeReaction = 1.0; //opóźnienie zadziałania hamulca - czas w s / (km/h)
double fAccThreshold = 0.0; // próg opóźnienia dla zadziałania hamulca
double AbsAccS_pub = 0.0; // próg opóźnienia dla zadziałania hamulca
@@ -349,11 +349,11 @@ private:
void OrdersClear();
void OrdersDump();
TController( bool AI, TDynamicObject *NewControll, bool InitPsyche, bool primary = true );
std::string OrderCurrent();
std::string OrderCurrent() const;
void WaitingSet(double Seconds);
private:
std::string Order2Str(TOrders Order);
std::string Order2Str(TOrders Order) const;
void DirectionForward(bool forward);
int OrderDirectionChange(int newdir, TMoverParameters *Vehicle);
void Lights(int head, int rear);
@@ -395,11 +395,11 @@ private:
void TakeControl(bool yes);
Mtable::TTrainParameters const * TrainTimetable() const;
std::string TrainName() const;
std::string Relation();
std::string Relation() const;
int StationCount() const;
int StationIndex() const;
bool IsStop();
std::string NextStop();
bool IsStop() const;
std::string NextStop() const;
inline
bool Primary() const {
return ( ( iDrivigFlags & movePrimary ) != 0 ); };
@@ -411,7 +411,7 @@ private:
TrackBlock() const;
void MoveTo(TDynamicObject *to);
void DirectionInitial();
std::string TableText(std::size_t const Index);
std::string TableText(std::size_t const Index) const;
int CrossRoute(TTrack *tr);
/*
void RouteSwitch(int d);

View File

@@ -128,7 +128,7 @@ class TTrack : public scene::basic_node {
friend opengl_renderer;
// NOTE: temporary arrangement
friend editor_ui;
friend itemproperties_panel;
private:
TIsolated * pIsolated = nullptr; // obwód izolowany obsługujący zajęcia/zwolnienia grupy torów

View File

@@ -153,6 +153,8 @@ eu07_application::exit() {
SafeDelete( simulation::Train );
SafeDelete( simulation::Region );
ui_layer::shutdown();
glfwDestroyWindow( m_window );
glfwTerminate();

View File

@@ -327,24 +327,12 @@ driver_mode::on_key( int const Key, int const Scancode, int const Action, int co
|| ( Key == GLFW_KEY_RIGHT_ALT ) ) ) {
// if the alt key was pressed toggle control picking mode and set matching cursor behaviour
if( Action == GLFW_PRESS ) {
if( Global.ControlPicking ) {
// switch off
Application.get_cursor_pos( m_input.mouse_pickmodepos.x, m_input.mouse_pickmodepos.y );
Application.set_cursor( GLFW_CURSOR_DISABLED );
Application.set_cursor_pos( 0, 0 );
}
else {
// enter picking mode
Application.set_cursor_pos( m_input.mouse_pickmodepos.x, m_input.mouse_pickmodepos.y );
Application.set_cursor( GLFW_CURSOR_NORMAL );
}
// actually toggle the mode
Global.ControlPicking = !Global.ControlPicking;
// toggle picking mode
set_picking( !Global.ControlPicking );
}
}
if( Action != GLFW_RELEASE ) {
if( Action == GLFW_PRESS ) {
OnKeyDown( Key );
@@ -737,7 +725,7 @@ driver_mode::OnKeyDown(int cKey) {
// if (cKey!=VK_F4)
return; // nie są przekazywane do pojazdu wcale
}
/*
if ((Global.iTextMode == GLFW_KEY_F12) ? (cKey >= '0') && (cKey <= '9') : false)
{ // tryb konfiguracji debugmode (przestawianie kamery już wyłączone
if (!Global.shiftState) // bez [Shift]
@@ -757,14 +745,21 @@ driver_mode::OnKeyDown(int cKey) {
// else if (cKey=='3') Global.iWriteLogEnabled^=4; //wypisywanie nazw torów
}
}
else if( cKey == GLFW_KEY_ESCAPE ) {
else */
if( cKey == GLFW_KEY_ESCAPE ) {
// toggle pause
if( Global.iPause & 1 ) // jeśli pauza startowa
Global.iPause &= ~1; // odpauzowanie, gdy po wczytaniu miało nie startować
else if( !( Global.iMultiplayer & 2 ) ) // w multiplayerze pauza nie ma sensu
if( Global.iPause & 1 ) {
// jeśli pauza startowa
// odpauzowanie, gdy po wczytaniu miało nie startować
Global.iPause &= ~1;
}
else if( ( Global.iMultiplayer & 2 ) == 0 ) {
// w multiplayerze pauza nie ma sensu
Global.iPause ^= 2; // zmiana stanu zapauzowania
if( Global.iPause ) {// jak pauza
Global.iTextMode = GLFW_KEY_F1; // to wyświetlić zegar i informację
if( ( Global.iPause & 2 )
&& ( false == Global.ControlPicking ) ) {
set_picking( true );
}
}
}
else {
@@ -992,3 +987,21 @@ driver_mode::InOutKey( bool const Near )
// update window title to reflect the situation
Application.set_title( Global.AppName + " (" + ( train != nullptr ? train->Occupied()->Name : "" ) + " @ " + Global.SceneryFile + ")" );
}
void
driver_mode::set_picking( bool const Picking ) {
if( Picking ) {
// enter picking mode
Application.set_cursor_pos( m_input.mouse_pickmodepos.x, m_input.mouse_pickmodepos.y );
Application.set_cursor( GLFW_CURSOR_NORMAL );
}
else {
// switch off
Application.get_cursor_pos( m_input.mouse_pickmodepos.x, m_input.mouse_pickmodepos.y );
Application.set_cursor( GLFW_CURSOR_DISABLED );
Application.set_cursor_pos( 0, 0 );
}
// actually toggle the mode
Global.ControlPicking = Picking;
}

View File

@@ -73,6 +73,7 @@ private:
void InOutKey( bool const Near = true );
void FollowView( bool wycisz = true );
void DistantView( bool const Near = false );
void set_picking( bool const Picking );
// members
drivermode_input m_input;

View File

@@ -28,21 +28,18 @@ http://mozilla.org/MPL/2.0/.
driver_ui::driver_ui() {
clear_texts();
/*
UIHeader = std::make_shared<ui_panel>( 20, 20 ); // header ui panel
UITable = std::make_shared<ui_panel>( 20, 100 ); // schedule or scan table
UITranscripts = std::make_shared<ui_panel>( 85, 600 ); // voice transcripts
*/
// make 4 empty lines for the ui header, to cut down on work down the road
UIHeader.text_lines.emplace_back( "", Global.UITextColor );
UIHeader.text_lines.emplace_back( "", Global.UITextColor );
UIHeader.text_lines.emplace_back( "", Global.UITextColor );
UIHeader.text_lines.emplace_back( "", Global.UITextColor );
clear_panels();
// bind the panels with ui object. maybe not the best place for this but, eh
push_back( &UIHeader );
push_back( &UITable );
push_back( &UITranscripts );
push_back( &m_aidpanel );
push_back( &m_timetablepanel );
push_back( &m_debugpanel );
push_back( &m_transcriptspanel );
m_timetablepanel.size_min = { 435, 110 };
m_timetablepanel.size_max = { 435, Global.iWindowHeight * 0.95 };
m_transcriptspanel.size_min = { 435, 85 };
m_transcriptspanel.size_max = { Global.iWindowWidth * 0.95, Global.iWindowHeight * 0.95 };
}
// potentially processes provided input key. returns: true if key was processed, false otherwise
@@ -55,9 +52,6 @@ driver_ui::on_key( int const Key, int const Action ) {
case GLFW_KEY_F1:
case GLFW_KEY_F2:
case GLFW_KEY_F3:
case GLFW_KEY_F8:
case GLFW_KEY_F9:
case GLFW_KEY_F10:
case GLFW_KEY_F12: { // ui mode selectors
@@ -67,15 +61,7 @@ driver_ui::on_key( int const Key, int const Action ) {
return false;
}
if( Action == GLFW_RELEASE ) { return true; } // recognized, but ignored
/*
EditorModeFlag = ( Key == GLFW_KEY_F11 );
if( ( true == EditorModeFlag )
&& ( false == Global.ControlPicking ) ) {
set_cursor( GLFW_CURSOR_NORMAL );
Global.ControlPicking = true;
}
*/
if( Action != GLFW_PRESS ) { return true; } // recognized, but ignored
}
default: { // everything else
@@ -87,91 +73,35 @@ driver_ui::on_key( int const Key, int const Action ) {
case GLFW_KEY_F1: {
// basic consist info
if( Global.iTextMode == Key ) { ++Global.iScreenMode[ Key - GLFW_KEY_F1 ]; }
if( Global.iScreenMode[ Key - GLFW_KEY_F1 ] > 1 ) {
// wyłączenie napisów
Global.iTextMode = 0;
Global.iScreenMode[ Key - GLFW_KEY_F1 ] = 0;
}
else {
Global.iTextMode = Key;
}
auto state = (
( m_aidpanel.is_open == false ) ? 0 :
( m_aidpanel.is_expanded == false ) ? 1 :
2 );
state = clamp_circular( ++state, 3 );
m_aidpanel.is_open = ( state > 0 );
m_aidpanel.is_expanded = ( state > 1 );
return true;
}
case GLFW_KEY_F2: {
// parametry pojazdu
if( Global.iTextMode == Key ) { ++Global.iScreenMode[ Key - GLFW_KEY_F1 ]; }
if( Global.iScreenMode[ Key - GLFW_KEY_F1 ] > 1 ) {
// wyłączenie napisów
Global.iTextMode = 0;
Global.iScreenMode[ Key - GLFW_KEY_F1 ] = 0;
}
else {
Global.iTextMode = Key;
}
return true;
}
case GLFW_KEY_F3: {
// timetable
if( Global.iTextMode == Key ) { ++Global.iScreenMode[ Key - GLFW_KEY_F1 ]; }
if( Global.iScreenMode[ Key - GLFW_KEY_F1 ] > 1 ) {
// wyłączenie napisów
Global.iTextMode = 0;
Global.iScreenMode[ Key - GLFW_KEY_F1 ] = 0;
}
else {
Global.iTextMode = Key;
}
auto state = (
( m_timetablepanel.is_open == false ) ? 0 :
( m_timetablepanel.is_expanded == false ) ? 1 :
2 );
state = clamp_circular( ++state, 3 );
m_timetablepanel.is_open = ( state > 0 );
m_timetablepanel.is_expanded = ( state > 1 );
return true;
}
case GLFW_KEY_F8: {
// renderer debug data
Global.iTextMode = Key;
return true;
}
case GLFW_KEY_F9: {
// wersja
Global.iTextMode = Key;
return true;
}
case GLFW_KEY_F10: {
// quit
if( Global.iTextMode == Key ) {
Global.iTextMode =
( Global.iPause && ( Key != GLFW_KEY_F1 ) ?
GLFW_KEY_F1 :
0 ); // wyłączenie napisów, chyba że pauza
}
else {
Global.iTextMode = Key;
}
return true;
}
/*
case GLFW_KEY_F11: {
// scenario inspector
Global.iTextMode = Key;
return true;
}
*/
case GLFW_KEY_F12: {
// coś tam jeszcze
Global.iTextMode = Key;
return true;
}
case GLFW_KEY_Y: {
// potentially quit
if( Global.iTextMode != GLFW_KEY_F10 ) { return false; } // not in quit mode
if( Action == GLFW_RELEASE ) { return true; } // recognized, but ignored
glfwSetWindowShouldClose( m_window, 1 );
// debug panel
m_debugpanel.is_open = !m_debugpanel.is_open;
return true;
}
@@ -187,13 +117,9 @@ driver_ui::on_key( int const Key, int const Action ) {
void
driver_ui::update() {
UITable.text_lines.clear();
std::string uitextline1, uitextline2, uitextline3, uitextline4;
set_tooltip( "" );
auto const *train { simulation::Train };
auto const *controlled { ( train ? train->Dynamic() : nullptr ) };
auto const &camera { Global.pCamera };
if( ( train != nullptr ) && ( false == FreeFlyModeFlag ) ) {
if( false == DebugModeFlag ) {
@@ -214,691 +140,28 @@ driver_ui::update() {
"" ) );
}
switch( Global.iTextMode ) {
case( GLFW_KEY_F1 ) : {
// f1, default mode: current time and timetable excerpt
auto const &time = simulation::Time.data();
uitextline1 =
"Time: "
+ to_string( time.wHour ) + ":"
+ ( time.wMinute < 10 ? "0" : "" ) + to_string( time.wMinute ) + ":"
+ ( time.wSecond < 10 ? "0" : "" ) + to_string( time.wSecond );
if( Global.iPause ) {
uitextline1 += " (paused)";
}
if( ( controlled != nullptr )
&& ( controlled->Mechanik != nullptr ) ) {
auto const *mover = controlled->MoverParameters;
auto const *driver = controlled->Mechanik;
uitextline2 = "Throttle: " + to_string( driver->Controlling()->MainCtrlPos, 0, 2 ) + "+" + std::to_string( driver->Controlling()->ScndCtrlPos );
if( mover->ActiveDir > 0 ) { uitextline2 += " D"; }
else if( mover->ActiveDir < 0 ) { uitextline2 += " R"; }
else { uitextline2 += " N"; }
uitextline3 = "Brakes:" + to_string( mover->fBrakeCtrlPos, 1, 5 ) + "+" + to_string( mover->LocalBrakePosA * LocalBrakePosNo, 0 ) + ( mover->SlippingWheels ? " !" : " " );
uitextline4 = (
true == TestFlag( mover->SecuritySystem.Status, s_aware ) ?
"!ALERTER! " :
" " );
uitextline4 += (
true == TestFlag( mover->SecuritySystem.Status, s_active ) ?
"!SHP! " :
" " );
if( Global.iScreenMode[ Global.iTextMode - GLFW_KEY_F1 ] == 1 ) {
// detail mode on second key press
auto const speedlimit { static_cast<int>( std::floor( driver->VelDesired ) ) };
uitextline2 +=
" Speed: " + std::to_string( static_cast<int>( std::floor( mover->Vel ) ) ) + " km/h"
+ " (limit: " + std::to_string( speedlimit ) + " km/h";
auto const nextspeedlimit { static_cast<int>( std::floor( driver->VelNext ) ) };
if( nextspeedlimit != speedlimit ) {
uitextline2 +=
", new limit: " + std::to_string( nextspeedlimit ) + " km/h"
+ " in " + to_string( driver->ActualProximityDist * 0.001, 1 ) + " km";
}
uitextline2 += ")";
auto const reverser { ( mover->ActiveDir > 0 ? 1 : -1 ) };
auto const grade { controlled->VectorFront().y * 100 * ( controlled->DirectionGet() == reverser ? 1 : -1 ) * reverser };
if( std::abs( grade ) >= 0.25 ) {
uitextline2 += " Grade: " + to_string( grade, 1 ) + "%";
}
uitextline3 +=
" Pressure: " + to_string( mover->BrakePress * 100.0, 2 ) + " kPa"
+ " (train pipe: " + to_string( mover->PipePress * 100.0, 2 ) + " kPa)";
auto const stoptime { static_cast<int>( -1.0 * controlled->Mechanik->fStopTime ) };
if( stoptime > 0 ) {
uitextline4 += " Loading/unloading in progress (" + to_string( stoptime ) + ( stoptime > 1 ? " seconds" : " second" ) + " left)";
}
else {
auto const trackblockdistance{ std::abs( controlled->Mechanik->TrackBlock() ) };
if( trackblockdistance <= 75.0 ) {
uitextline4 += " Another vehicle ahead (distance: " + to_string( trackblockdistance, 1 ) + " m)";
}
}
}
}
break;
}
case( GLFW_KEY_F2 ) : {
// timetable
auto *vehicle {
( FreeFlyModeFlag ?
std::get<TDynamicObject *>( simulation::Region->find_vehicle( camera.Pos, 20, false, false ) ) :
controlled ) }; // w trybie latania lokalizujemy wg mapy
if( vehicle == nullptr ) { break; }
// if the nearest located vehicle doesn't have a direct driver, try to query its owner
auto const owner = (
( ( vehicle->Mechanik != nullptr ) && ( vehicle->Mechanik->Primary() ) ) ?
vehicle->Mechanik :
vehicle->ctOwner );
if( owner == nullptr ){ break; }
auto const *table = owner->TrainTimetable();
if( table == nullptr ) { break; }
auto const &time = simulation::Time.data();
uitextline1 =
"Time: "
+ to_string( time.wHour ) + ":"
+ ( time.wMinute < 10 ? "0" : "" ) + to_string( time.wMinute ) + ":"
+ ( time.wSecond < 10 ? "0" : "" ) + to_string( time.wSecond );
if( Global.iPause ) {
uitextline1 += " (paused)";
}
uitextline2 = Bezogonkow( owner->Relation(), true ) + " (" + Bezogonkow( owner->TrainName(), true ) + ")";
auto const nextstation = Bezogonkow( owner->NextStop(), true );
if( !nextstation.empty() ) {
// jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania
uitextline3 = " -> " + nextstation;
}
if( Global.iScreenMode[ Global.iTextMode - GLFW_KEY_F1 ] == 1 ) {
if( 0 == table->StationCount ) {
// only bother if there's stations to list
UITable.text_lines.emplace_back( "(no timetable)", Global.UITextColor );
}
else {
// header
UITable.text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
TMTableLine const *tableline;
for( int i = owner->iStationStart; i <= std::min( owner->iStationStart + 10, table->StationCount ); ++i ) {
// wyświetlenie pozycji z rozkładu
tableline = table->TimeTable + i; // linijka rozkładu
std::string vmax =
" "
+ to_string( tableline->vmax, 0 );
vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej
std::string const station = (
Bezogonkow( tableline->StationName, true )
+ " " )
.substr( 0, 34 );
std::string const location = (
( tableline->km > 0.0 ?
to_string( tableline->km, 2 ) :
"" )
+ " " )
.substr( 0, 34 - tableline->StationWare.size() );
std::string const arrival = (
tableline->Ah >= 0 ?
to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Am ) ).substr( 1, 2 ) :
" | " );
std::string const departure = (
tableline->Dh >= 0 ?
to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Dm ) ).substr( 1, 2 ) :
" | " );
auto const candeparture = (
( owner->iStationStart < table->StationIndex )
&& ( i < table->StationIndex )
&& ( ( time.wHour * 60 + time.wMinute ) >= ( tableline->Dh * 60 + tableline->Dm ) ) );
auto traveltime =
" "
+ ( i < 2 ? "" :
tableline->Ah >= 0 ? to_string( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), 0 ) :
to_string( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), 0 ) );
traveltime = traveltime.substr( traveltime.size() - 3, 3 ); // z wyrównaniem do prawej
UITable.text_lines.emplace_back(
( "| " + vmax + " | " + station + " | " + arrival + " | " + traveltime + " |" ),
( candeparture ?
glm::vec4( 0.0f, 1.0f, 0.0f, 1.0f ) :// czas minął i odjazd był, to nazwa stacji będzie na zielono
Global.UITextColor ) );
UITable.text_lines.emplace_back(
( "| | " + location + tableline->StationWare + " | " + departure + " | |" ),
( candeparture ?
glm::vec4( 0.0f, 1.0f, 0.0f, 1.0f ) :// czas minął i odjazd był, to nazwa stacji będzie na zielono
Global.UITextColor ) );
// divider/footer
UITable.text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
}
if( owner->iStationStart + 10 < table->StationCount ) {
// if we can't display entire timetable, add a scrolling indicator at the bottom
UITable.text_lines.emplace_back( " ... ", Global.UITextColor );
}
}
}
break;
}
case( GLFW_KEY_F3 ) : {
auto const *vehicle {
( FreeFlyModeFlag ?
std::get<TDynamicObject *>( simulation::Region->find_vehicle( camera.Pos, 20, false, false ) ) :
controlled ) }; // w trybie latania lokalizujemy wg mapy
if( vehicle != nullptr ) {
// jeśli domyślny ekran po pierwszym naciśnięciu
auto const *mover { vehicle->MoverParameters };
uitextline1 = "Vehicle name: " + mover->Name;
if( ( vehicle->Mechanik == nullptr ) && ( vehicle->ctOwner ) ) {
// for cars other than leading unit indicate the leader
uitextline1 += ", owned by " + vehicle->ctOwner->OwnerName();
}
uitextline1 += "; Status: " + mover->EngineDescription( 0 );
// informacja o sprzęgach
uitextline1 +=
"; C0:" +
( vehicle->PrevConnected ?
vehicle->PrevConnected->name() + ":" + to_string( mover->Couplers[ 0 ].CouplingFlag ) + (
mover->Couplers[ 0 ].CouplingFlag == 0 ?
" (" + to_string( mover->Couplers[ 0 ].CoupleDist, 1 ) + " m)" :
"" ) :
"none" );
uitextline1 +=
" C1:" +
( vehicle->NextConnected ?
vehicle->NextConnected->name() + ":" + to_string( mover->Couplers[ 1 ].CouplingFlag ) + (
mover->Couplers[ 1 ].CouplingFlag == 0 ?
" (" + to_string( mover->Couplers[ 1 ].CoupleDist, 1 ) + " m)" :
"" ) :
"none" );
// equipment flags
uitextline2 = ( mover->Battery ? "B" : "." );
uitextline2 += ( mover->Mains ? "M" : "." );
uitextline2 += ( mover->PantRearUp ? ( mover->PantRearVolt > 0.0 ? "O" : "o" ) : "." );
uitextline2 += ( mover->PantFrontUp ? ( mover->PantFrontVolt > 0.0 ? "P" : "p" ) : "." );
uitextline2 += ( mover->PantPressLockActive ? "!" : ( mover->PantPressSwitchActive ? "*" : "." ) );
uitextline2 += ( mover->WaterPump.is_active ? "W" : ( false == mover->WaterPump.breaker ? "-" : ( mover->WaterPump.is_enabled ? "w" : "." ) ) );
uitextline2 += ( true == mover->WaterHeater.is_damaged ? "!" : ( mover->WaterHeater.is_active ? "H" : ( false == mover->WaterHeater.breaker ? "-" : ( mover->WaterHeater.is_enabled ? "h" : "." ) ) ) );
uitextline2 += ( mover->FuelPump.is_active ? "F" : ( mover->FuelPump.is_enabled ? "f" : "." ) );
uitextline2 += ( mover->OilPump.is_active ? "O" : ( mover->OilPump.is_enabled ? "o" : "." ) );
uitextline2 += ( false == mover->ConverterAllowLocal ? "-" : ( mover->ConverterAllow ? ( mover->ConverterFlag ? "X" : "x" ) : "." ) );
uitextline2 += ( mover->ConvOvldFlag ? "!" : "." );
uitextline2 += ( mover->CompressorFlag ? "C" : ( false == mover->CompressorAllowLocal ? "-" : ( ( mover->CompressorAllow || mover->CompressorStart == start_t::automatic ) ? "c" : "." ) ) );
uitextline2 += ( mover->CompressorGovernorLock ? "!" : "." );
auto const *train { simulation::Train };
if( ( train != nullptr ) && ( train->Dynamic() == vehicle ) ) {
uitextline2 += ( mover->Radio ? " R: " : " r: " ) + std::to_string( train->RadioChannel() );
}
uitextline2 += " Bdelay: ";
if( ( mover->BrakeDelayFlag & bdelay_G ) == bdelay_G )
uitextline2 += "G";
if( ( mover->BrakeDelayFlag & bdelay_P ) == bdelay_P )
uitextline2 += "P";
if( ( mover->BrakeDelayFlag & bdelay_R ) == bdelay_R )
uitextline2 += "R";
if( ( mover->BrakeDelayFlag & bdelay_M ) == bdelay_M )
uitextline2 += "+Mg";
uitextline2 += ", Load: " + to_string( mover->Load, 0 ) + " (" + to_string( mover->LoadFlag, 0 ) + ")";
uitextline2 +=
"; Pant: "
+ to_string( mover->PantPress, 2 )
+ ( mover->bPantKurek3 ? "-ZG" : "|ZG" );
uitextline2 +=
"; Ft: " + to_string(
mover->Ft * 0.001f * (
mover->ActiveCab ? mover->ActiveCab :
vehicle->ctOwner ? vehicle->ctOwner->Controlling()->ActiveCab :
1 ), 1 )
+ ", Fb: " + to_string( mover->Fb * 0.001f, 1 )
+ ", Fr: " + to_string( mover->Adhesive( mover->RunningTrack.friction ), 2 )
+ ( mover->SlippingWheels ? " (!)" : "" );
if( vehicle->Mechanik ) {
uitextline2 += "; Ag: " + to_string( vehicle->Mechanik->fAccGravity, 2 ) + " (" + ( vehicle->Mechanik->fAccGravity > 0.01 ? "\\" : ( vehicle->Mechanik->fAccGravity < -0.01 ? "/" : "-" ) ) + ")";
}
uitextline2 +=
"; TC:"
+ to_string( mover->TotalCurrent, 0 );
auto const frontcouplerhighvoltage =
to_string( mover->Couplers[ side::front ].power_high.voltage, 0 )
+ "@"
+ to_string( mover->Couplers[ side::front ].power_high.current, 0 );
auto const rearcouplerhighvoltage =
to_string( mover->Couplers[ side::rear ].power_high.voltage, 0 )
+ "@"
+ to_string( mover->Couplers[ side::rear ].power_high.current, 0 );
uitextline2 += ", HV: ";
if( mover->Couplers[ side::front ].power_high.local == false ) {
uitextline2 +=
"(" + frontcouplerhighvoltage + ")-"
+ ":F" + ( vehicle->DirectionGet() ? "<<" : ">>" ) + "R:"
+ "-(" + rearcouplerhighvoltage + ")";
}
else {
uitextline2 +=
frontcouplerhighvoltage
+ ":F" + ( vehicle->DirectionGet() ? "<<" : ">>" ) + "R:"
+ rearcouplerhighvoltage;
}
uitextline3 +=
"TrB: " + to_string( mover->BrakePress, 2 )
+ ", " + to_hex_str( mover->Hamulec->GetBrakeStatus(), 2 );
uitextline3 +=
"; LcB: " + to_string( mover->LocBrakePress, 2 )
+ "; hat: " + to_string( mover->BrakeCtrlPos2, 2 )
+ "; pipes: " + to_string( mover->PipePress, 2 )
+ "/" + to_string( mover->ScndPipePress, 2 )
+ "/" + to_string( mover->EqvtPipePress, 2 )
+ ", MT: " + to_string( mover->CompressedVolume, 3 )
+ ", BT: " + to_string( mover->Volume, 3 )
+ ", CtlP: " + to_string( mover->CntrlPipePress, 3 )
+ ", CtlT: " + to_string( mover->Hamulec->GetCRP(), 3 );
if( mover->ManualBrakePos > 0 ) {
uitextline3 += "; manual brake on";
}
if( vehicle->Mechanik ) {
// o ile jest ktoś w środku
std::string flags = "cpapcplhhndoiefgvdpseil "; // flagi AI (definicja w Driver.h)
for( int i = 0, j = 1; i < 23; ++i, j <<= 1 )
if( false == ( vehicle->Mechanik->DrivigFlags() & j ) ) // jak bit ustawiony
flags[ i ] = '.';// std::toupper( flags[ i ] ); // ^= 0x20; // to zmiana na wielką literę
uitextline4 = flags;
uitextline4 +=
"Driver: Vd=" + to_string( vehicle->Mechanik->VelDesired, 0 )
+ " Ad=" + to_string( vehicle->Mechanik->AccDesired, 2 )
+ " Ah=" + to_string( vehicle->Mechanik->fAccThreshold, 2 )
+ "@" + to_string( vehicle->Mechanik->fBrake_a0[ 0 ], 2 )
+ "+" + to_string( vehicle->Mechanik->fBrake_a1[ 0 ], 2 )
+ " Bd=" + to_string( vehicle->Mechanik->fBrakeDist, 0 )
+ " Pd=" + to_string( vehicle->Mechanik->ActualProximityDist, 0 )
+ " Vn=" + to_string( vehicle->Mechanik->VelNext, 0 )
+ " VSl=" + to_string( vehicle->Mechanik->VelSignalLast, 0 )
+ " VLl=" + to_string( vehicle->Mechanik->VelLimitLast, 0 )
+ " VRd=" + to_string( vehicle->Mechanik->VelRoad, 0 )
+ " VRst=" + to_string( vehicle->Mechanik->VelRestricted, 0 );
if( ( vehicle->Mechanik->VelNext == 0.0 )
&& ( vehicle->Mechanik->eSignNext ) ) {
// jeśli ma zapamiętany event semafora, nazwa eventu semafora
uitextline4 += " (" + Bezogonkow( vehicle->Mechanik->eSignNext->asName ) + ")";
}
// biezaca komenda dla AI
uitextline4 += ", command: " + vehicle->Mechanik->OrderCurrent();
}
if( Global.iScreenMode[ Global.iTextMode - GLFW_KEY_F1 ] == 1 ) {
// f2 screen, track scan mode
if( vehicle->Mechanik == nullptr ) {
//żeby była tabelka, musi być AI
break;
}
std::size_t i = 0; std::size_t const speedtablesize = clamp( static_cast<int>( vehicle->Mechanik->TableSize() ) - 1, 0, 30 );
do {
std::string scanline = vehicle->Mechanik->TableText( i );
if( scanline.empty() ) { break; }
UITable.text_lines.emplace_back( Bezogonkow( scanline ), Global.UITextColor );
++i;
} while( i < speedtablesize ); // TController:iSpeedTableSize TODO: change when the table gets recoded
}
}
else {
// wyświetlenie współrzędnych w scenerii oraz kąta kamery, gdy nie mamy wskaźnika
uitextline1 =
"Camera position: "
+ to_string( camera.Pos.x, 2 ) + " "
+ to_string( camera.Pos.y, 2 ) + " "
+ to_string( camera.Pos.z, 2 )
+ ", azimuth: "
+ to_string( 180.0 - glm::degrees( camera.Yaw ), 0 ) // ma być azymut, czyli 0 na północy i rośnie na wschód
+ " "
+ std::string( "S SEE NEN NWW SW" )
.substr( 0 + 2 * floor( fmod( 8 + ( camera.Yaw + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 );
// current luminance level
uitextline2 = "Light level: " + to_string( Global.fLuminance, 3 );
if( Global.FakeLight ) { uitextline2 += "(*)"; }
}
break;
}
case( GLFW_KEY_F8 ) : {
// gfx renderer data
uitextline1 =
"FoV: " + to_string( Global.FieldOfView / Global.ZoomFactor, 1 )
+ ", Draw range x " + to_string( Global.fDistanceFactor, 1 )
// + "; sectors: " + std::to_string( GfxRenderer.m_drawcount )
// + ", FPS: " + to_string( Timer::GetFPS(), 2 );
+ ", FPS: " + std::to_string( static_cast<int>(std::round(GfxRenderer.Framerate())) );
if( Global.iSlowMotion ) {
uitextline1 += " (slowmotion " + to_string( Global.iSlowMotion ) + ")";
}
uitextline2 =
std::string( "Rendering mode: " )
+ ( Global.bUseVBO ?
"VBO" :
"Display Lists" )
+ " ";
if( false == Global.LastGLError.empty() ) {
uitextline2 +=
"Last openGL error: "
+ Global.LastGLError;
}
// renderer stats
uitextline3 = GfxRenderer.info_times();
uitextline4 = GfxRenderer.info_stats();
break;
}
case( GLFW_KEY_F9 ) : {
// informacja o wersji
uitextline1 = "MaSzyna " + Global.asVersion; // informacja o wersji
if( Global.iMultiplayer ) {
uitextline1 += " (multiplayer mode is active)";
}
uitextline3 =
"vehicles: " + to_string( Timer::subsystem.sim_dynamics.average(), 2 ) + " msec"
+ " update total: " + to_string( Timer::subsystem.sim_total.average(), 2 ) + " msec";
// current event queue
auto const time { Timer::GetTime() };
auto const *event { simulation::Events.begin() };
auto eventtableindex{ 0 };
while( ( event != nullptr )
&& ( eventtableindex < 30 ) ) {
if( ( false == event->m_ignored )
&& ( true == event->bEnabled ) ) {
auto const delay { " " + to_string( std::max( 0.0, event->fStartTime - time ), 1 ) };
auto const eventline =
"Delay: " + delay.substr( delay.length() - 6 )
+ ", Event: " + event->asName
+ ( event->Activator ? " (by: " + event->Activator->asName + ")" : "" )
+ ( event->evJoined ? " (joint event)" : "" );
UITable.text_lines.emplace_back( eventline, Global.UITextColor );
++eventtableindex;
}
event = event->evNext;
}
break;
}
case( GLFW_KEY_F10 ) : {
uitextline1 = "Press [Y] key to quit / Aby zakonczyc program, przycisnij klawisz [Y].";
break;
}
case( GLFW_KEY_F12 ) : {
// opcje włączenia i wyłączenia logowania
uitextline1 = "[0] Debugmode " + std::string( DebugModeFlag ? "(on)" : "(off)" );
uitextline2 = "[1] log.txt " + std::string( ( Global.iWriteLogEnabled & 1 ) ? "(on)" : "(off)" );
uitextline3 = "[2] Console " + std::string( ( Global.iWriteLogEnabled & 2 ) ? "(on)" : "(off)" );
break;
}
default: {
// uncovered cases, nothing to do here...
// ... unless we're in debug mode
if( DebugModeFlag ) {
auto const *vehicle {
( FreeFlyModeFlag ?
std::get<TDynamicObject *>( simulation::Region->find_vehicle( camera.Pos, 20, false, false ) ) :
controlled ) }; // w trybie latania lokalizujemy wg mapy
if( vehicle == nullptr ) {
break;
}
auto const *mover { vehicle->MoverParameters };
uitextline1 =
"vel: " + to_string( vehicle->GetVelocity(), 2 ) + "/" + to_string( mover->nrot* M_PI * mover->WheelDiameter * 3.6, 2 )
+ " km/h;" + ( mover->SlippingWheels ? " (!)" : " " )
+ " dist: " + to_string( mover->DistCounter, 2 ) + " km"
+ "; pos: [" + to_string( vehicle->GetPosition().x, 2 ) + ", " + to_string( vehicle->GetPosition().y, 2 ) + ", " + to_string( vehicle->GetPosition().z, 2 ) + "]"
+ ", PM=" + to_string( mover->WheelFlat, 1 )
+ " mm; enpwr=" + to_string( mover->EnginePower, 1 )
+ "; enrot=" + to_string( mover->enrot * 60, 0 )
+ " tmrot=" + to_string( std::abs( mover->nrot ) * mover->Transmision.Ratio * 60, 0 )
+ "; ventrot=" + to_string( mover->RventRot * 60, 1 )
+ "; fanrot=" + to_string( mover->dizel_heat.rpmw, 1 ) + ", " + to_string( mover->dizel_heat.rpmw2, 1 );
uitextline2 =
"HamZ=" + to_string( mover->fBrakeCtrlPos, 2 )
+ "; HamP=" + to_string( mover->LocalBrakePosA, 2 )
+ "; NasJ=" + std::to_string( mover->MainCtrlPos ) + "(" + std::to_string( mover->MainCtrlActualPos ) + ")"
+ ( ( mover->ShuntMode && mover->EngineType == TEngineType::DieselElectric ) ?
"; NasB=" + to_string( mover->AnPos, 2 ) :
"; NasB=" + std::to_string( mover->ScndCtrlPos ) + "(" + std::to_string( mover->ScndCtrlActualPos ) + ")" )
+ "; I=" +
( mover->TrainType == dt_EZT ?
std::to_string( int( mover->ShowCurrent( 0 ) ) ) :
std::to_string( int( mover->Im ) ) )
+ "; U=" + to_string( int( mover->RunningTraction.TractionVoltage + 0.5 ) )
+ "; R=" +
( std::abs( mover->RunningShape.R ) > 10000.0 ?
"~0.0" :
to_string( mover->RunningShape.R, 1 ) )
+ " An=" + to_string( mover->AccN, 2 ); // przyspieszenie poprzeczne
if( tprev != simulation::Time.data().wSecond ) {
tprev = simulation::Time.data().wSecond;
Acc = ( mover->Vel - VelPrev ) / 3.6;
VelPrev = mover->Vel;
}
uitextline2 += "; As=" + to_string( Acc, 2 ); // przyspieszenie wzdłużne
// uitextline2 += " eAngle=" + to_string( std::cos( mover->eAngle ), 2 );
uitextline2 += "; oilP=" + to_string( mover->OilPump.pressure_present, 3 );
uitextline2 += " oilT=" + to_string( mover->dizel_heat.To, 2 );
uitextline2 += "; waterT=" + to_string( mover->dizel_heat.temperatura1, 2 );
uitextline2 += ( mover->WaterCircuitsLink ? "-" : "|" );
uitextline2 += to_string( mover->dizel_heat.temperatura2, 2 );
uitextline2 += "; engineT=" + to_string( mover->dizel_heat.Ts, 2 );
uitextline3 =
"cyl.ham. " + to_string( mover->BrakePress, 2 )
+ "; prz.gl. " + to_string( mover->PipePress, 2 )
+ "; zb.gl. " + to_string( mover->CompressedVolume, 2 )
// youBy - drugi wezyk
+ "; p.zas. " + to_string( mover->ScndPipePress, 2 );
// McZapkie: warto wiedziec w jakim stanie sa przelaczniki
if( mover->ConvOvldFlag )
uitextline3 += " C! ";
else if( mover->FuseFlag )
uitextline3 += " F! ";
else if( !mover->Mains )
uitextline3 += " () ";
else {
switch(
mover->ActiveDir *
( mover->Imin == mover->IminLo ?
1 :
2 ) ) {
case 2: { uitextline3 += " >> "; break; }
case 1: { uitextline3 += " -> "; break; }
case 0: { uitextline3 += " -- "; break; }
case -1: { uitextline3 += " <- "; break; }
case -2: { uitextline3 += " << "; break; }
}
}
// McZapkie: predkosc szlakowa
if( mover->RunningTrack.Velmax == -1 ) {
uitextline3 += " Vtrack=Vmax";
}
else {
uitextline3 += " Vtrack " + to_string( mover->RunningTrack.Velmax, 2 );
}
if( ( mover->EnginePowerSource.SourceType == TPowerSource::CurrentCollector )
|| ( mover->TrainType == dt_EZT ) ) {
uitextline3 +=
"; pant. " + to_string( mover->PantPress, 2 )
+ ( mover->bPantKurek3 ? "=" : "^" ) + "ZG";
}
// McZapkie: komenda i jej parametry
if( mover->CommandIn.Command != ( "" ) ) {
uitextline4 =
"C:" + mover->CommandIn.Command
+ " V1=" + to_string( mover->CommandIn.Value1, 0 )
+ " V2=" + to_string( mover->CommandIn.Value2, 0 );
}
if( ( vehicle->Mechanik )
&& ( vehicle->Mechanik->AIControllFlag == AIdriver ) ) {
uitextline4 +=
"AI: Vd=" + to_string( vehicle->Mechanik->VelDesired, 0 )
+ " ad=" + to_string(vehicle->Mechanik->AccDesired, 2)
+ "/" + to_string(vehicle->Mechanik->AccDesired*vehicle->Mechanik->BrakeAccFactor(), 2)
+ " atrain=" + to_string(vehicle->Mechanik->fBrake_a0[0], 2)
+ "+" + to_string(vehicle->Mechanik->fBrake_a1[0], 2)
+ " aS=" + to_string(vehicle->Mechanik->AbsAccS_pub, 2)
+ " Pd=" + to_string( vehicle->Mechanik->ActualProximityDist, 0 )
+ " Vn=" + to_string( vehicle->Mechanik->VelNext, 0 );
}
// induction motor data
if( mover->EngineType == TEngineType::ElectricInductionMotor ) {
UITable.text_lines.emplace_back( " eimc: eimv: press:", Global.UITextColor );
for( int i = 0; i <= 20; ++i ) {
std::string parameters =
mover->eimc_labels[ i ] + to_string( mover->eimc[ i ], 2, 9 )
+ " | "
+ mover->eimv_labels[ i ] + to_string( mover->eimv[ i ], 2, 9 );
if( i < 10 ) {
parameters += " | " + train->fPress_labels[i] + to_string( train->fPress[ i ][ 0 ], 2, 9 );
}
else if( i == 12 ) {
parameters += " med:";
}
else if( i >= 13 ) {
parameters += " | " + vehicle->MED_labels[ i - 13 ] + to_string( vehicle->MED[ 0 ][ i - 13 ], 2, 9 );
}
UITable.text_lines.emplace_back( parameters, Global.UITextColor );
}
}
if (mover->EngineType == TEngineType::DieselEngine) {
std::string parameters = "param value";
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "efill: " + to_string(mover->dizel_fill, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "etorq: " + to_string(mover->dizel_Torque, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "creal: " + to_string(mover->dizel_engage, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "cdesi: " + to_string(mover->dizel_engagestate, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "cdelt: " + to_string(mover->dizel_engagedeltaomega, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "gears: " + to_string(mover->dizel_automaticgearstatus, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "hydro value";
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "hTCnI: " + to_string(mover->hydro_TC_nIn, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "hTCnO: " + to_string(mover->hydro_TC_nOut, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "hTCTM: " + to_string(mover->hydro_TC_TMRatio, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "hTCTI: " + to_string(mover->hydro_TC_TorqueIn, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "hTCTO: " + to_string(mover->hydro_TC_TorqueOut, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "hTCfl: " + to_string(mover->hydro_TC_Fill, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
parameters = "hTCLR: " + to_string(mover->hydro_TC_LockupRate, 2, 9);
UITable.text_lines.emplace_back(parameters, Global.UITextColor);
//parameters = "hTCXX: " + to_string(mover->hydro_TC_nIn, 2, 9);
//UITable.text_lines.emplace_back(parameters, Global.UITextColor);
}
} // if( DebugModeFlag && Controlled )
break;
}
}
#ifdef EU07_USE_OLD_UI_CODE
if( Controlled && DebugModeFlag && !Global.iTextMode ) {
uitextline1 +=
( "; d_omega " ) + to_string( Controlled->MoverParameters->dizel_engagedeltaomega, 3 );
if( Controlled->MoverParameters->EngineType == ElectricInductionMotor ) {
for( int i = 0; i <= 8; i++ ) {
for( int j = 0; j <= 9; j++ ) {
glRasterPos2f( 0.05f + 0.03f * i, 0.16f - 0.01f * j );
uitextline4 = to_string( Train->fEIMParams[ i ][ j ], 2 );
}
}
}
}
#endif
// update the ui header texts
auto &headerdata = UIHeader.text_lines;
headerdata[ 0 ].data = uitextline1;
headerdata[ 1 ].data = uitextline2;
headerdata[ 2 ].data = uitextline3;
headerdata[ 3 ].data = uitextline4;
// stenogramy dźwięków (ukryć, gdy tabelka skanowania lub rozkład?)
auto &transcripts = UITranscripts.text_lines;
transcripts.clear();
for( auto const &transcript : ui::Transcripts.aLines ) {
if( Global.fTimeAngleDeg >= transcript.fShow ) {
cParser parser( transcript.asText );
while( true == parser.getTokens( 1, false, "|" ) ) {
std::string transcriptline; parser >> transcriptline;
transcripts.emplace_back( transcriptline, glm::vec4( 1.0f, 1.0f, 0.0f, 1.0f ) );
}
}
}
ui_layer::update();
}
// render() subclass details
void
driver_ui::render_() {
auto const pausemask { 1 | 2 };
if( ( Global.iPause & pausemask ) != 0 ) {
// pause/quit modal
auto const popupheader{ "Simulation Paused" };
ImGui::OpenPopup( popupheader );
if( ImGui::BeginPopupModal( popupheader, nullptr, ImGuiWindowFlags_AlwaysAutoResize ) ) {
if( ImGui::Button( "Resume", ImVec2( 120, 0 ) ) ) {
ImGui::CloseCurrentPopup();
Global.iPause &= ~pausemask;
}
if( ImGui::Button( "Quit", ImVec2( 120, 0 ) ) ) {
ImGui::CloseCurrentPopup();
glfwSetWindowShouldClose( m_window, 1 );
}
ImGui::EndPopup();
}
}
}

View File

@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
#pragma once
#include "uilayer.h"
#include "driveruipanels.h"
class driver_ui : public ui_layer {
@@ -25,12 +26,14 @@ public:
update() override;
private:
// methods
// render() subclass details
void
render_() override;
// members
ui_panel UIHeader { 20, 20 }; // header ui panel
ui_panel UITable { 20, 100 };// schedule or scan table
ui_panel UITranscripts { 85, 600 }; // voice transcripts
int tprev { 0 }; // poprzedni czas
double VelPrev { 0.0 }; // poprzednia prędkość
double Acc { 0.0 }; // przyspieszenie styczne
drivingaid_panel m_aidpanel { "Driving Aid", true };
timetable_panel m_timetablepanel { "Timetable", false };
debug_panel m_debugpanel { "Debug Data", false };
transcripts_panel m_transcriptspanel { "Transcripts", true }; // voice transcripts
};

896
driveruipanels.cpp Normal file
View File

@@ -0,0 +1,896 @@
/*
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 "driveruipanels.h"
#include "globals.h"
#include "translation.h"
#include "simulation.h"
#include "simulationtime.h"
#include "event.h"
#include "camera.h"
#include "mtable.h"
#include "train.h"
#include "driver.h"
#include "animmodel.h"
#include "dynobj.h"
#include "model3d.h"
#include "renderer.h"
#include "utilities.h"
#include "logs.h"
void
drivingaid_panel::update() {
if( false == is_open ) { return; }
text_lines.clear();
auto const *train { simulation::Train };
auto const *controlled { ( train ? train->Dynamic() : nullptr ) };
if( ( controlled == nullptr )
|| ( controlled->Mechanik == nullptr ) ) { return; }
auto const *mover = controlled->MoverParameters;
auto const *driver = controlled->Mechanik;
{ // throttle, velocity, speed limits and grade
auto textline =
"Throttle: " + to_string( driver->Controlling()->MainCtrlPos, 0, 2 )
+ "+" + std::to_string( driver->Controlling()->ScndCtrlPos )
+ " "
+ ( mover->ActiveDir > 0 ? 'D' :
mover->ActiveDir < 0 ? 'R' :
'N' );
if( is_expanded ) {
auto const speedlimit { static_cast<int>( std::floor( driver->VelDesired ) ) };
textline +=
" Speed: " + std::to_string( static_cast<int>( std::floor( mover->Vel ) ) ) + " km/h"
+ " (limit: " + std::to_string( speedlimit ) + " km/h";
auto const nextspeedlimit { static_cast<int>( std::floor( driver->VelNext ) ) };
if( nextspeedlimit != speedlimit ) {
textline +=
", new limit: " + std::to_string( nextspeedlimit ) + " km/h"
+ " in " + to_string( driver->ActualProximityDist * 0.001, 1 ) + " km";
}
textline += ")";
auto const reverser { ( mover->ActiveDir > 0 ? 1 : -1 ) };
auto const grade { controlled->VectorFront().y * 100 * ( controlled->DirectionGet() == reverser ? 1 : -1 ) * reverser };
if( std::abs( grade ) >= 0.25 ) {
textline += " Grade: " + to_string( grade, 1 ) + "%%";
}
}
text_lines.emplace_back( textline, Global.UITextColor );
}
{ // brakes, air pressure
auto textline =
"Brakes:" + to_string( mover->fBrakeCtrlPos, 1, 5 )
+ "+" + to_string( mover->LocalBrakePosA * LocalBrakePosNo, 0 )
+ ( mover->SlippingWheels ? " !" : " " );
if( textline.size() > 16 ) {
textline.erase( 16 );
}
if( is_expanded ) {
textline +=
" Pressure: " + to_string( mover->BrakePress * 100.0, 2 ) + " kPa"
+ " (train pipe: " + to_string( mover->PipePress * 100.0, 2 ) + " kPa)";
}
text_lines.emplace_back( textline, Global.UITextColor );
}
{ // alerter, hints
std::string textline =
( true == TestFlag( mover->SecuritySystem.Status, s_aware ) ?
"!ALERTER! " :
" " );
textline +=
( true == TestFlag( mover->SecuritySystem.Status, s_active ) ?
"!SHP! " :
" " );
if( is_expanded ) {
auto const stoptime { static_cast<int>( -1.0 * controlled->Mechanik->fStopTime ) };
if( stoptime > 0 ) {
textline += " Loading/unloading in progress (" + to_string( stoptime ) + ( stoptime > 1 ? " seconds" : " second" ) + " left)";
}
else {
auto const trackblockdistance { std::abs( controlled->Mechanik->TrackBlock() ) };
if( trackblockdistance <= 75.0 ) {
textline += " Another vehicle ahead (distance: " + to_string( trackblockdistance, 1 ) + " m)";
}
}
}
text_lines.emplace_back( textline, Global.UITextColor );
}
auto const sizex = ( is_expanded ? 660 : 130 );
size = { sizex, 85 };
}
void
timetable_panel::update() {
if( false == is_open ) { return; }
text_lines.clear();
auto const *train { simulation::Train };
auto const *controlled { ( train ? train->Dynamic() : nullptr ) };
auto const &camera { Global.pCamera };
auto const &time { simulation::Time.data() };
{ // current time
auto textline =
"Time: "
+ to_string( time.wHour ) + ":"
+ ( time.wMinute < 10 ? "0" : "" ) + to_string( time.wMinute ) + ":"
+ ( time.wSecond < 10 ? "0" : "" ) + to_string( time.wSecond );
text_lines.emplace_back( textline, Global.UITextColor );
}
auto *vehicle {
( FreeFlyModeFlag ?
std::get<TDynamicObject *>( simulation::Region->find_vehicle( camera.Pos, 20, false, false ) ) :
controlled ) }; // w trybie latania lokalizujemy wg mapy
if( vehicle == nullptr ) { return; }
// if the nearest located vehicle doesn't have a direct driver, try to query its owner
auto const *owner = (
( ( vehicle->Mechanik != nullptr ) && ( vehicle->Mechanik->Primary() ) ) ?
vehicle->Mechanik :
vehicle->ctOwner );
if( owner == nullptr ) { return; }
auto const *table = owner->TrainTimetable();
if( table == nullptr ) { return; }
{ // destination
auto textline = Bezogonkow( owner->Relation(), true );
if( false == textline.empty() ) {
textline += " (" + Bezogonkow( owner->TrainName(), true ) + ")";
}
text_lines.emplace_back( textline, Global.UITextColor );
}
{ // next station
auto const nextstation = Bezogonkow( owner->NextStop(), true );
if( false == nextstation.empty() ) {
// jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania
auto textline = " -> " + nextstation;
text_lines.emplace_back( textline, Global.UITextColor );
}
}
if( is_expanded ) {
text_lines.emplace_back( "", Global.UITextColor );
if( 0 == table->StationCount ) {
// only bother if there's stations to list
text_lines.emplace_back( "(no timetable)", Global.UITextColor );
}
else {
auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) };
// header
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
TMTableLine const *tableline;
for( int i = owner->iStationStart; i <= table->StationCount; ++i ) {
// wyświetlenie pozycji z rozkładu
tableline = table->TimeTable + i; // linijka rozkładu
std::string vmax =
" "
+ to_string( tableline->vmax, 0 );
vmax = vmax.substr( vmax.size() - 3, 3 ); // z wyrównaniem do prawej
std::string const station = (
Bezogonkow( tableline->StationName, true )
+ " " )
.substr( 0, 34 );
std::string const location = (
( tableline->km > 0.0 ?
to_string( tableline->km, 2 ) :
"" )
+ " " )
.substr( 0, 34 - tableline->StationWare.size() );
std::string const arrival = (
tableline->Ah >= 0 ?
to_string( int( 100 + tableline->Ah ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Am ) ).substr( 1, 2 ) :
" | " );
std::string const departure = (
tableline->Dh >= 0 ?
to_string( int( 100 + tableline->Dh ) ).substr( 1, 2 ) + ":" + to_string( int( 100 + tableline->Dm ) ).substr( 1, 2 ) :
" | " );
auto const candeparture = (
( owner->iStationStart < table->StationIndex )
&& ( i < table->StationIndex )
&& ( ( time.wHour * 60 + time.wMinute ) >= ( tableline->Dh * 60 + tableline->Dm ) ) );
auto traveltime =
" "
+ ( i < 2 ? "" :
tableline->Ah >= 0 ? to_string( CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Ah, tableline->Am ), 0 ) :
to_string( std::max( 0.0, CompareTime( table->TimeTable[ i - 1 ].Dh, table->TimeTable[ i - 1 ].Dm, tableline->Dh, tableline->Dm ) - 0.5 ), 0 ) );
traveltime = traveltime.substr( traveltime.size() - 3, 3 ); // z wyrównaniem do prawej
text_lines.emplace_back(
( "| " + vmax + " | " + station + " | " + arrival + " | " + traveltime + " |" ),
( candeparture ?
readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono
Global.UITextColor ) );
text_lines.emplace_back(
( "| | " + location + tableline->StationWare + " | " + departure + " | |" ),
( candeparture ?
readycolor :// czas minął i odjazd był, to nazwa stacji będzie na zielono
Global.UITextColor ) );
// divider/footer
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
}
}
} // is_expanded
}
void
debug_panel::update() {
if( false == is_open ) { return; }
// input item bindings
m_input.train = simulation::Train;
m_input.controlled = ( m_input.train ? m_input.train->Dynamic() : nullptr );
m_input.camera = &( Global.pCamera );
m_input.vehicle =
( FreeFlyModeFlag ?
std::get<TDynamicObject *>( simulation::Region->find_vehicle( m_input.camera->Pos, 20, false, false ) ) :
m_input.controlled ); // w trybie latania lokalizujemy wg mapy
m_input.mover =
( m_input.vehicle != nullptr ?
m_input.vehicle->MoverParameters :
nullptr );
m_input.mechanik = (
m_input.vehicle != nullptr ?
m_input.vehicle->Mechanik :
nullptr );
// header section
text_lines.clear();
auto textline = "Version " + Global.asVersion;
text_lines.emplace_back( textline, Global.UITextColor );
// sub-sections
m_vehiclelines.clear();
m_enginelines.clear();
m_ailines.clear();
m_scantablelines.clear();
m_scenariolines.clear();
m_eventqueuelines.clear();
m_cameralines.clear();
m_rendererlines.clear();
update_section_vehicle( m_vehiclelines );
update_section_engine( m_enginelines );
update_section_ai( m_ailines );
update_section_scantable( m_scantablelines );
update_section_scenario( m_scenariolines );
update_section_eventqueue( m_eventqueuelines );
update_section_camera( m_cameralines );
update_section_renderer( m_rendererlines );
}
void
debug_panel::render() {
if( false == is_open ) { return; }
auto flags =
ImGuiWindowFlags_NoFocusOnAppearing
| ImGuiWindowFlags_NoCollapse
| ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 );
if( size.x > 0 ) {
ImGui::SetNextWindowSize( ImVec2( size.x, size.y ) );
}
if( size_min.x > 0 ) {
ImGui::SetNextWindowSizeConstraints( ImVec2( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) );
}
if( true == ImGui::Begin( name.c_str(), &is_open, flags ) ) {
// header section
for( auto const &line : text_lines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
// sections
ImGui::Separator();
render_section( "Vehicle", m_vehiclelines );
render_section( "Vehicle Engine", m_enginelines );
render_section( "Vehicle AI", m_ailines );
render_section( "Vehicle Scan Table", m_scantablelines );
render_section( "Scenario", m_scenariolines );
render_section( "Scenario Event Queue", m_eventqueuelines );
render_section( "Camera", m_cameralines );
render_section( "Gfx Renderer", m_rendererlines );
// toggles
ImGui::Separator();
ImGui::Checkbox( "Debug Mode", &DebugModeFlag );
}
ImGui::End();
}
void
debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
if( m_input.vehicle == nullptr ) { return; }
if( m_input.mover == nullptr ) { return; }
auto const &vehicle { *m_input.vehicle };
auto const &mover { *m_input.mover };
// f3 data
auto textline = "Vehicle name: " + mover.Name;
if( ( vehicle.Mechanik == nullptr ) && ( vehicle.ctOwner ) ) {
// for cars other than leading unit indicate the leader
textline += ", owned by " + vehicle.ctOwner->OwnerName();
}
textline += "\nStatus: " + mover.EngineDescription( 0 );
if( mover.WheelFlat > 0.01 ) {
textline += " Flat: " + to_string( mover.WheelFlat, 1 ) + " mm";
}
// informacja o sprzęgach
textline +=
"\nC0:" +
( vehicle.PrevConnected ?
vehicle.PrevConnected->name() + ":" + to_string( mover.Couplers[ 0 ].CouplingFlag ) + (
mover.Couplers[ 0 ].CouplingFlag == 0 ?
" (" + to_string( mover.Couplers[ 0 ].CoupleDist, 1 ) + " m)" :
"" ) :
"none" );
textline +=
" C1:" +
( vehicle.NextConnected ?
vehicle.NextConnected->name() + ":" + to_string( mover.Couplers[ 1 ].CouplingFlag ) + (
mover.Couplers[ 1 ].CouplingFlag == 0 ?
" (" + to_string( mover.Couplers[ 1 ].CoupleDist, 1 ) + " m)" :
"" ) :
"none" );
Output.emplace_back( textline, Global.UITextColor );
// equipment flags
textline = ( mover.Battery ? "B" : "." );
textline += ( mover.Mains ? "M" : "." );
textline += ( mover.PantRearUp ? ( mover.PantRearVolt > 0.0 ? "O" : "o" ) : "." );
textline += ( mover.PantFrontUp ? ( mover.PantFrontVolt > 0.0 ? "P" : "p" ) : "." );
textline += ( mover.PantPressLockActive ? "!" : ( mover.PantPressSwitchActive ? "*" : "." ) );
textline += ( mover.WaterPump.is_active ? "W" : ( false == mover.WaterPump.breaker ? "-" : ( mover.WaterPump.is_enabled ? "w" : "." ) ) );
textline += ( true == mover.WaterHeater.is_damaged ? "!" : ( mover.WaterHeater.is_active ? "H" : ( false == mover.WaterHeater.breaker ? "-" : ( mover.WaterHeater.is_enabled ? "h" : "." ) ) ) );
textline += ( mover.FuelPump.is_active ? "F" : ( mover.FuelPump.is_enabled ? "f" : "." ) );
textline += ( mover.OilPump.is_active ? "O" : ( mover.OilPump.is_enabled ? "o" : "." ) );
textline += ( false == mover.ConverterAllowLocal ? "-" : ( mover.ConverterAllow ? ( mover.ConverterFlag ? "X" : "x" ) : "." ) );
textline += ( mover.ConvOvldFlag ? "!" : "." );
textline += ( mover.CompressorFlag ? "C" : ( false == mover.CompressorAllowLocal ? "-" : ( ( mover.CompressorAllow || mover.CompressorStart == start_t::automatic ) ? "c" : "." ) ) );
textline += ( mover.CompressorGovernorLock ? "!" : "." );
if( ( m_input.train != nullptr ) && ( m_input.train->Dynamic() == m_input.vehicle ) ) {
textline += ( mover.Radio ? " R: " : " r: " ) + std::to_string( m_input.train->RadioChannel() );
}
textline += " Bdelay: ";
if( ( mover.BrakeDelayFlag & bdelay_G ) == bdelay_G )
textline += "G";
if( ( mover.BrakeDelayFlag & bdelay_P ) == bdelay_P )
textline += "P";
if( ( mover.BrakeDelayFlag & bdelay_R ) == bdelay_R )
textline += "R";
if( ( mover.BrakeDelayFlag & bdelay_M ) == bdelay_M )
textline += "+Mg";
textline += ", Load: " + to_string( mover.Load, 0 ) + " (" + to_string( mover.LoadFlag, 0 ) + ")";
textline +=
"\nFt: " + to_string(
mover.Ft * 0.001f * (
mover.ActiveCab ? mover.ActiveCab :
vehicle.ctOwner ? vehicle.ctOwner->Controlling()->ActiveCab :
1 ), 1 )
+ ", Fb: " + to_string( mover.Fb * 0.001f, 1 )
+ ", Fr: " + to_string( mover.Adhesive( mover.RunningTrack.friction ), 2 )
+ ( mover.SlippingWheels ? " (!)" : "" );
textline +=
"\nPant: "
+ to_string( mover.PantPress, 2 )
+ ( mover.bPantKurek3 ? "-ZG" : "|ZG" );
textline +=
" TC:"
+ to_string( mover.TotalCurrent, 0 );
auto const frontcouplerhighvoltage =
to_string( mover.Couplers[ side::front ].power_high.voltage, 0 )
+ "@"
+ to_string( mover.Couplers[ side::front ].power_high.current, 0 );
auto const rearcouplerhighvoltage =
to_string( mover.Couplers[ side::rear ].power_high.voltage, 0 )
+ "@"
+ to_string( mover.Couplers[ side::rear ].power_high.current, 0 );
textline += ", HV: ";
if( mover.Couplers[ side::front ].power_high.local == false ) {
textline +=
"(" + frontcouplerhighvoltage + ")-"
+ ":F" + ( vehicle.DirectionGet() ? "<<" : ">>" ) + "R:"
+ "-(" + rearcouplerhighvoltage + ")";
}
else {
textline +=
frontcouplerhighvoltage
+ ":F" + ( vehicle.DirectionGet() ? "<<" : ">>" ) + "R:"
+ rearcouplerhighvoltage;
}
Output.emplace_back( textline, Global.UITextColor );
textline =
"TrB: " + to_string( mover.BrakePress, 2 )
+ ", " + to_hex_str( mover.Hamulec->GetBrakeStatus(), 2 );
textline +=
"; LcB: " + to_string( mover.LocBrakePress, 2 )
+ "; hat: " + to_string( mover.BrakeCtrlPos2, 2 )
+ "\npipes: " + to_string( mover.PipePress, 2 )
+ "/" + to_string( mover.ScndPipePress, 2 )
+ "/" + to_string( mover.EqvtPipePress, 2 )
+ "\nMT: " + to_string( mover.CompressedVolume, 3 )
+ ", BT: " + to_string( mover.Volume, 3 )
+ ", CtlP: " + to_string( mover.CntrlPipePress, 3 )
+ ", CtlT: " + to_string( mover.Hamulec->GetCRP(), 3 );
if( mover.ManualBrakePos > 0 ) {
textline += "; manual brake on";
}
Output.emplace_back( textline, Global.UITextColor );
// debug mode f1 data
textline =
"vel: " + to_string( vehicle.GetVelocity(), 2 ) + "/" + to_string( mover.nrot* M_PI * mover.WheelDiameter * 3.6, 2 )
+ " km/h;"
+ " dist: " + to_string( mover.DistCounter, 2 ) + " km"
+ "\npos: [" + to_string( vehicle.GetPosition().x, 2 ) + ", " + to_string( vehicle.GetPosition().y, 2 ) + ", " + to_string( vehicle.GetPosition().z, 2 ) + "]"
+ "\nenpwr=" + to_string( mover.EnginePower, 1 )
+ "; enrot=" + to_string( mover.enrot * 60, 0 )
+ " tmrot=" + to_string( std::abs( mover.nrot ) * mover.Transmision.Ratio * 60, 0 )
+ "; ventrot=" + to_string( mover.RventRot * 60, 1 )
+ "; fanrot=" + to_string( mover.dizel_heat.rpmw, 1 ) + ", " + to_string( mover.dizel_heat.rpmw2, 1 );
Output.emplace_back( textline, Global.UITextColor );
textline =
"HamZ=" + to_string( mover.fBrakeCtrlPos, 2 )
+ "; HamP=" + to_string( mover.LocalBrakePosA, 2 )
+ "; NasJ=" + std::to_string( mover.MainCtrlPos ) + "(" + std::to_string( mover.MainCtrlActualPos ) + ")"
+ ( ( mover.ShuntMode && mover.EngineType == TEngineType::DieselElectric ) ?
"; NasB=" + to_string( mover.AnPos, 2 ) :
"; NasB=" + std::to_string( mover.ScndCtrlPos ) + "(" + std::to_string( mover.ScndCtrlActualPos ) + ")" )
+ "\nI=" +
( mover.TrainType == dt_EZT ?
std::to_string( int( mover.ShowCurrent( 0 ) ) ) :
std::to_string( int( mover.Im ) ) )
+ "; U=" + to_string( int( mover.RunningTraction.TractionVoltage + 0.5 ) )
+ "; R=" +
( std::abs( mover.RunningShape.R ) > 10000.0 ?
"~0.0" :
to_string( mover.RunningShape.R, 1 ) )
+ " An=" + to_string( mover.AccN, 2 ); // przyspieszenie poprzeczne
if( tprev != simulation::Time.data().wSecond ) {
tprev = simulation::Time.data().wSecond;
Acc = ( mover.Vel - VelPrev ) / 3.6;
VelPrev = mover.Vel;
}
textline += "; As=" + to_string( Acc, 2 ); // przyspieszenie wzdłużne
// uitextline2 += " eAngle=" + to_string( std::cos( mover.eAngle ), 2 );
textline += "\noilP=" + to_string( mover.OilPump.pressure_present, 3 );
textline += " oilT=" + to_string( mover.dizel_heat.To, 2 );
textline += "; waterT=" + to_string( mover.dizel_heat.temperatura1, 2 );
textline += ( mover.WaterCircuitsLink ? "-" : "|" );
textline += to_string( mover.dizel_heat.temperatura2, 2 );
textline += "; engineT=" + to_string( mover.dizel_heat.Ts, 2 );
Output.emplace_back( textline, Global.UITextColor );
textline =
"cyl.ham. " + to_string( mover.BrakePress, 2 )
+ "; prz.gl. " + to_string( mover.PipePress, 2 )
+ "; zb.gl. " + to_string( mover.CompressedVolume, 2 )
// youBy - drugi wezyk
+ "; p.zas. " + to_string( mover.ScndPipePress, 2 );
// McZapkie: warto wiedziec w jakim stanie sa przelaczniki
if( mover.ConvOvldFlag )
textline += " C! ";
else if( mover.FuseFlag )
textline += " F! ";
else if( !mover.Mains )
textline += " () ";
else {
switch(
mover.ActiveDir *
( mover.Imin == mover.IminLo ?
1 :
2 ) ) {
case 2: { textline += " >> "; break; }
case 1: { textline += " -> "; break; }
case 0: { textline += " -- "; break; }
case -1: { textline += " <- "; break; }
case -2: { textline += " << "; break; }
}
}
Output.emplace_back( textline, Global.UITextColor );
// McZapkie: komenda i jej parametry
if( mover.CommandIn.Command != ( "" ) ) {
textline =
"C:" + mover.CommandIn.Command
+ " V1=" + to_string( mover.CommandIn.Value1, 0 )
+ " V2=" + to_string( mover.CommandIn.Value2, 0 );
Output.emplace_back( textline, Global.UITextColor );
}
}
void
debug_panel::update_section_engine( std::vector<text_line> &Output ) {
if( m_input.train == nullptr ) { return; }
if( m_input.vehicle == nullptr ) { return; }
if( m_input.mover == nullptr ) { return; }
auto const &train { *m_input.train };
auto const &vehicle{ *m_input.vehicle };
auto const &mover{ *m_input.mover };
// engine data
// induction motor data
if( mover.EngineType == TEngineType::ElectricInductionMotor ) {
Output.emplace_back( " eimc: eimv: press:", Global.UITextColor );
for( int i = 0; i <= 20; ++i ) {
std::string parameters =
mover.eimc_labels[ i ] + to_string( mover.eimc[ i ], 2, 9 )
+ " | "
+ mover.eimv_labels[ i ] + to_string( mover.eimv[ i ], 2, 9 );
if( i < 10 ) {
parameters += " | " + train.fPress_labels[i] + to_string( train.fPress[ i ][ 0 ], 2, 9 );
}
else if( i == 12 ) {
parameters += " med:";
}
else if( i >= 13 ) {
parameters += " | " + vehicle.MED_labels[ i - 13 ] + to_string( vehicle.MED[ 0 ][ i - 13 ], 2, 9 );
}
Output.emplace_back( parameters, Global.UITextColor );
}
}
if ( mover.EngineType == TEngineType::DieselEngine) {
std::string parameters = "param value";
Output.emplace_back(parameters, Global.UITextColor);
parameters = "efill: " + to_string( mover.dizel_fill, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "etorq: " + to_string( mover.dizel_Torque, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "creal: " + to_string( mover.dizel_engage, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "cdesi: " + to_string( mover.dizel_engagestate, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "cdelt: " + to_string( mover.dizel_engagedeltaomega, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "gears: " + to_string( mover.dizel_automaticgearstatus, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "hydro value";
Output.emplace_back(parameters, Global.UITextColor);
parameters = "hTCnI: " + to_string( mover.hydro_TC_nIn, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "hTCnO: " + to_string( mover.hydro_TC_nOut, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "hTCTM: " + to_string( mover.hydro_TC_TMRatio, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "hTCTI: " + to_string( mover.hydro_TC_TorqueIn, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "hTCTO: " + to_string( mover.hydro_TC_TorqueOut, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "hTCfl: " + to_string( mover.hydro_TC_Fill, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
parameters = "hTCLR: " + to_string( mover.hydro_TC_LockupRate, 2, 9);
Output.emplace_back(parameters, Global.UITextColor);
//parameters = "hTCXX: " + to_string(mover->hydro_TC_nIn, 2, 9);
//engine_lines.emplace_back(parameters, Global.UITextColor);
}
}
void
debug_panel::update_section_ai( std::vector<text_line> &Output ) {
if( m_input.mover == nullptr ) { return; }
if( m_input.mechanik == nullptr ) { return; }
auto const &mover{ *m_input.mover };
auto const &mechanik{ *m_input.mechanik };
// biezaca komenda dla AI
auto textline = "Current order: " + mechanik.OrderCurrent();
Output.emplace_back( textline, Global.UITextColor );
if( ( mechanik.VelNext == 0.0 )
&& ( mechanik.eSignNext ) ) {
// jeśli ma zapamiętany event semafora, nazwa eventu semafora
Output.emplace_back( "Current signal: " + Bezogonkow( mechanik.eSignNext->asName ), Global.UITextColor );
}
// distances
textline =
"Distances:\n proximity: " + to_string( mechanik.ActualProximityDist, 0 )
+ ", braking: " + to_string( mechanik.fBrakeDist, 0 );
Output.emplace_back( textline, Global.UITextColor );
// velocity factors
textline =
"Velocity:\n desired: " + to_string( mechanik.VelDesired, 0 )
+ ", next: " + to_string( mechanik.VelNext, 0 );
std::vector< std::pair< double, std::string > > const restrictions{
{ mechanik.VelSignalLast, "signal" },
{ mechanik.VelLimitLast, "limit" },
{ mechanik.VelRoad, "road" },
{ mechanik.VelRestricted, "restricted" },
{ mover.RunningTrack.Velmax, "track" } };
std::string restrictionstext;
for( auto const &restriction : restrictions ) {
if( restriction.first < 0.0 ) { continue; }
if( false == restrictionstext.empty() ) {
restrictionstext += ", ";
}
restrictionstext +=
to_string( restriction.first, 0 )
+ " (" + restriction.second + ")";
}
if( false == restrictionstext.empty() ) {
textline += "\n restrictions: " + restrictionstext;
}
Output.emplace_back( textline, Global.UITextColor );
// acceleration
textline =
"Acceleration:\n desired: " + to_string( mechanik.AccDesired, 2 )
+ ", corrected: " + to_string( mechanik.AccDesired * mechanik.BrakeAccFactor(), 2 )
+ "\n current: " + to_string( mechanik.AbsAccS_pub, 2 )
+ ", slope: " + to_string( mechanik.fAccGravity, 2 ) + " (" + ( mechanik.fAccGravity > 0.01 ? "\\" : ( mechanik.fAccGravity < -0.01 ? "/" : "-" ) ) + ")"
+ "\n brake threshold: " + to_string( mechanik.fAccThreshold, 2 )
+ ", delays: " + to_string( mechanik.fBrake_a0[ 0 ], 2 )
+ "+" + to_string( mechanik.fBrake_a1[ 0 ], 2 );
Output.emplace_back( textline, Global.UITextColor );
// ai driving flags
std::vector<std::string> const drivingflagnames {
"StopCloser", "StopPoint", "Active", "Press", "Connect", "Primary", "Late", "StopHere",
"StartHorn", "StartHornNow", "StartHornDone", "Oerlikons", "IncSpeed", "TrackEnd", "SwitchFound", "GuardSignal",
"Visibility", "DoorOpened", "PushPull", "SemaphorFound", "SemaphorWasElapsed", "TrainInsideStation", "SpeedLimitFound" };
textline = "Driving flags:";
for( int idx = 0, flagbit = 1; idx < drivingflagnames.size(); ++idx, flagbit <<= 1 ) {
if( mechanik.DrivigFlags() & flagbit ) {
textline += "\n " + drivingflagnames[ idx ];
}
}
Output.emplace_back( textline, Global.UITextColor );
}
void
debug_panel::update_section_scantable( std::vector<text_line> &Output ) {
if( m_input.mechanik == nullptr ) { return; }
auto const &mechanik{ *m_input.mechanik };
std::size_t i = 0; std::size_t const speedtablesize = clamp( static_cast<int>( mechanik.TableSize() ) - 1, 0, 30 );
do {
auto const scanline = mechanik.TableText( i );
if( scanline.empty() ) { break; }
Output.emplace_back( Bezogonkow( scanline ), Global.UITextColor );
++i;
} while( i < speedtablesize );
if( Output.empty() ) {
Output.emplace_back( "(no points of interest)", Global.UITextColor );
}
}
void
debug_panel::update_section_scenario( std::vector<text_line> &Output ) {
auto textline =
"vehicles: " + to_string( Timer::subsystem.sim_dynamics.average(), 2 ) + " msec"
+ " update total: " + to_string( Timer::subsystem.sim_total.average(), 2 ) + " msec";
Output.emplace_back( textline, Global.UITextColor );
// current luminance level
textline = "Light level: " + to_string( Global.fLuminance, 3 );
if( Global.FakeLight ) { textline += "(*)"; }
Output.emplace_back( textline, Global.UITextColor );
}
void
debug_panel::update_section_eventqueue( std::vector<text_line> &Output ) {
std::string textline;
// current event queue
auto const time { Timer::GetTime() };
auto const *event { simulation::Events.begin() };
auto eventtableindex{ 0 };
while( ( event != nullptr )
&& ( eventtableindex < 30 ) ) {
if( ( false == event->m_ignored )
&& ( true == event->bEnabled ) ) {
auto const delay { " " + to_string( std::max( 0.0, event->fStartTime - time ), 1 ) };
textline =
"Delay: " + delay.substr( delay.length() - 6 )
+ ", Event: " + event->asName
+ ( event->Activator ? " (by: " + event->Activator->asName + ")" : "" )
+ ( event->evJoined ? " (joint event)" : "" );
Output.emplace_back( textline, Global.UITextColor );
++eventtableindex;
}
event = event->evNext;
}
if( Output.empty() ) {
textline = "(no queued events)";
Output.emplace_back( textline, Global.UITextColor );
}
}
void
debug_panel::update_section_camera( std::vector<text_line> &Output ) {
if( m_input.camera == nullptr ) { return; }
auto const &camera{ *m_input.camera };
// camera data
auto textline =
"Position: ["
+ to_string( camera.Pos.x, 2 ) + ", "
+ to_string( camera.Pos.y, 2 ) + ", "
+ to_string( camera.Pos.z, 2 ) + "]";
Output.emplace_back( textline, Global.UITextColor );
textline =
"Azimuth: "
+ to_string( 180.0 - glm::degrees( camera.Yaw ), 0 ) // ma być azymut, czyli 0 na północy i rośnie na wschód
+ " "
+ std::string( "S SEE NEN NWW SW" )
.substr( 0 + 2 * floor( fmod( 8 + ( camera.Yaw + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 );
Output.emplace_back( textline, Global.UITextColor );
}
void
debug_panel::update_section_renderer( std::vector<text_line> &Output ) {
// gfx renderer data
auto textline =
"FoV: " + to_string( Global.FieldOfView / Global.ZoomFactor, 1 )
+ ", Draw range x " + to_string( Global.fDistanceFactor, 1 )
// + "; sectors: " + std::to_string( GfxRenderer.m_drawcount )
// + ", FPS: " + to_string( Timer::GetFPS(), 2 );
+ ", FPS: " + std::to_string( static_cast<int>(std::round(GfxRenderer.Framerate())) );
if( Global.iSlowMotion ) {
textline += " (slowmotion " + to_string( Global.iSlowMotion ) + ")";
}
Output.emplace_back( textline, Global.UITextColor );
textline =
std::string( "Rendering mode: " )
+ ( Global.bUseVBO ?
"VBO" :
"Display Lists" )
+ " ";
if( false == Global.LastGLError.empty() ) {
textline +=
"Last openGL error: "
+ Global.LastGLError;
}
Output.emplace_back( textline, Global.UITextColor );
// renderer stats
Output.emplace_back( GfxRenderer.info_times(), Global.UITextColor );
Output.emplace_back( GfxRenderer.info_stats(), Global.UITextColor );
}
void
debug_panel::render_section( std::string const &Header, std::vector<text_line> const &Lines ) {
if( Lines.empty() ) { return; }
if( false == ImGui::CollapsingHeader( Header.c_str() ) ) { return; }
for( auto const &line : Lines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
}
void
transcripts_panel::update() {
if( false == is_open ) { return; }
text_lines.clear();
for( auto const &transcript : ui::Transcripts.aLines ) {
if( Global.fTimeAngleDeg >= transcript.fShow ) {
// NOTE: legacy transcript lines use | as new line mark
text_lines.emplace_back( ExchangeCharInString( transcript.asText, '|', ' ' ), colors::white );
}
}
}
void
transcripts_panel::render() {
if( false == is_open ) { return; }
if( true == text_lines.empty() ) { return; }
auto flags =
ImGuiWindowFlags_NoFocusOnAppearing
| ImGuiWindowFlags_NoCollapse
| ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 );
if( size.x > 0 ) {
ImGui::SetNextWindowSize( ImVec2( size.x, size.y ) );
}
if( size_min.x > 0 ) {
ImGui::SetNextWindowSizeConstraints( ImVec2( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) );
}
if( true == ImGui::Begin( name.c_str(), &is_open, flags ) ) {
// header section
for( auto const &line : text_lines ) {
ImGui::TextWrapped( line.data.c_str() );
}
}
ImGui::End();
}

93
driveruipanels.h Normal file
View File

@@ -0,0 +1,93 @@
/*
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 "uilayer.h"
#include "classes.h"
class drivingaid_panel : public ui_panel {
public:
drivingaid_panel( std::string const Name, bool const Isopen )
: ui_panel( Name, Isopen )
{}
void update() override;
bool is_expanded { false };
};
class timetable_panel : public ui_panel {
public:
timetable_panel( std::string const Name, bool const Isopen )
: ui_panel( Name, Isopen ) {}
void update() override;
bool is_expanded{ false };
};
class debug_panel : public ui_panel {
public:
debug_panel( std::string const Name, bool const Isopen )
: ui_panel( Name, Isopen ) {}
void update() override;
void render() override;
private:
// types
struct input_data {
TTrain const *train;
TDynamicObject const *controlled;
TCamera const *camera;
TDynamicObject const *vehicle;
TMoverParameters const *mover;
TController const *mechanik;
};
// methods
// generate and send section data to provided output
void update_section_vehicle( std::vector<text_line> &Output );
void update_section_engine( std::vector<text_line> &Output );
void update_section_ai( std::vector<text_line> &Output );
void update_section_scantable( std::vector<text_line> &Output );
void update_section_scenario( std::vector<text_line> &Output );
void update_section_eventqueue( std::vector<text_line> &Output );
void update_section_camera( std::vector<text_line> &Output );
void update_section_renderer( std::vector<text_line> &Output );
// renders provided lines, under specified collapsing header
void render_section( std::string const &Header, std::vector<text_line> const &Lines );
// members
input_data m_input;
std::vector<text_line>
m_vehiclelines,
m_enginelines,
m_ailines,
m_scantablelines,
m_cameralines,
m_scenariolines,
m_eventqueuelines,
m_rendererlines;
int tprev { 0 }; // poprzedni czas
double VelPrev { 0.0 }; // poprzednia prędkość
double Acc { 0.0 }; // przyspieszenie styczne
};
class transcripts_panel : public ui_panel {
public:
transcripts_panel( std::string const Name, bool const Isopen )
: ui_panel( Name, Isopen ) {}
void update() override;
void render() override;
};

View File

@@ -45,9 +45,6 @@ editor_mode::init() {
Camera.Init( { 0, 15, 0 }, { glm::radians( -30.0 ), glm::radians( 180.0 ), 0 }, TCameraType::tp_Free );
m_userinterface->set_progress( "Scenario editor is active. Press F11 to return to driver mode" );
m_userinterface->set_progress( 0, 100 );
return m_input.init();
}

View File

@@ -11,27 +11,13 @@ http://mozilla.org/MPL/2.0/.
#include "editoruilayer.h"
#include "globals.h"
#include "camera.h"
#include "animmodel.h"
#include "track.h"
#include "event.h"
#include "renderer.h"
#include "utilities.h"
#include "logs.h"
editor_ui::editor_ui() {
clear_texts();
/*
UIHeader = std::make_shared<ui_panel>( 20, 20 ); // header ui panel
*/
// make 4 empty lines for the ui header, to cut down on work down the road
UIHeader.text_lines.emplace_back( "", Global.UITextColor );
UIHeader.text_lines.emplace_back( "", Global.UITextColor );
UIHeader.text_lines.emplace_back( "", Global.UITextColor );
UIHeader.text_lines.emplace_back( "", Global.UITextColor );
clear_panels();
// bind the panels with ui object. maybe not the best place for this but, eh
push_back( &UIHeader );
push_back( &m_itempropertiespanel );
}
// potentially processes provided input key. returns: true if key was processed, false otherwise
@@ -45,11 +31,8 @@ editor_ui::on_key( int const Key, int const Action ) {
void
editor_ui::update() {
std::string uitextline1, uitextline2, uitextline3, uitextline4;
set_tooltip( "" );
auto const &camera { Global.pCamera };
if( ( true == Global.ControlPicking )
&& ( true == DebugModeFlag ) ) {
@@ -60,141 +43,8 @@ editor_ui::update() {
"" ) );
}
// scenario inspector
auto const *node { m_node };
if( node == nullptr ) {
auto const mouseposition { camera.Pos + GfxRenderer.Mouse_Position() };
uitextline1 = "mouse location: [" + to_string( mouseposition.x, 2 ) + ", " + to_string( mouseposition.y, 2 ) + ", " + to_string( mouseposition.z, 2 ) + "]";
goto update;
}
uitextline1 =
"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{ camera.Pos.x, 0.0, camera.Pos.z } ), 1 ) + " m)";
// subclass-specific data
// TBD, TODO: specialized data dump method in each node subclass, or data imports in the panel for provided subclass pointer?
if( typeid( *node ) == typeid( TAnimModel ) ) {
auto const *subnode = static_cast<TAnimModel const *>( node );
uitextline2 = "angle: " + to_string( clamp_circular( subnode->vAngle.y, 360.f ), 2 ) + " deg";
uitextline2 += "; lights: ";
if( subnode->iNumLights > 0 ) {
uitextline2 += '[';
for( int lightidx = 0; lightidx < subnode->iNumLights; ++lightidx ) {
uitextline2 += to_string( subnode->lsLights[ lightidx ] );
if( lightidx < subnode->iNumLights - 1 ) {
uitextline2 += ", ";
}
}
uitextline2 += ']';
}
else {
uitextline2 += "none";
}
// 3d shape
auto modelfile { (
( subnode->pModel != nullptr ) ?
subnode->pModel->NameGet() :
"none" ) };
if( modelfile.find( szModelPath ) == 0 ) {
// don't include 'models/' in the path
modelfile.erase( 0, std::string{ szModelPath }.size() );
}
// texture
auto texturefile { (
( subnode->Material()->replacable_skins[ 1 ] != null_handle ) ?
GfxRenderer.Material( subnode->Material()->replacable_skins[ 1 ] ).name :
"none" ) };
if( texturefile.find( szTexturePath ) == 0 ) {
// don't include 'textures/' in the path
texturefile.erase( 0, std::string{ szTexturePath }.size() );
}
uitextline3 = "mesh: " + modelfile;
uitextline4 = "skin: " + texturefile;
}
else if( typeid( *node ) == typeid( TTrack ) ) {
auto const *subnode = static_cast<TTrack const *>( node );
// basic attributes
uitextline2 =
"isolated: " + ( ( subnode->pIsolated != nullptr ) ? subnode->pIsolated->asName : "none" )
+ "; velocity: " + to_string( subnode->SwitchExtension ? subnode->SwitchExtension->fVelocity : subnode->fVelocity )
+ "; width: " + to_string( subnode->fTrackWidth ) + " m"
+ "; friction: " + to_string( subnode->fFriction, 2 )
+ "; quality: " + to_string( subnode->iQualityFlag );
// textures
auto texturefile { (
( subnode->m_material1 != null_handle ) ?
GfxRenderer.Material( subnode->m_material1 ).name :
"none" ) };
if( texturefile.find( szTexturePath ) == 0 ) {
texturefile.erase( 0, std::string{ szTexturePath }.size() );
}
auto texturefile2{ (
( subnode->m_material2 != null_handle ) ?
GfxRenderer.Material( subnode->m_material2 ).name :
"none" ) };
if( texturefile2.find( szTexturePath ) == 0 ) {
texturefile2.erase( 0, std::string{ szTexturePath }.size() );
}
uitextline2 += "; skins: [" + texturefile + ", " + texturefile2 + "]";
// paths
uitextline3 = "paths: ";
for( auto const &path : subnode->m_paths ) {
uitextline3 +=
"["
+ to_string( path.points[ segment_data::point::start ].x, 3 ) + ", "
+ to_string( path.points[ segment_data::point::start ].y, 3 ) + ", "
+ to_string( path.points[ segment_data::point::start ].z, 3 ) + "]->"
+ "["
+ to_string( path.points[ segment_data::point::end ].x, 3 ) + ", "
+ to_string( path.points[ segment_data::point::end ].y, 3 ) + ", "
+ to_string( path.points[ segment_data::point::end ].z, 3 ) + "] ";
}
// events
std::vector< std::pair< std::string, TTrack::event_sequence const * > > const eventsequences {
{ "ev0", &subnode->m_events0 }, { "ev0all", &subnode->m_events0all },
{ "ev1", &subnode->m_events1 }, { "ev1all", &subnode->m_events1all },
{ "ev2", &subnode->m_events2 }, { "ev2all", &subnode->m_events2all } };
for( auto const &eventsequence : eventsequences ) {
if( eventsequence.second->empty() ) { continue; }
uitextline4 += eventsequence.first + ": [";
for( auto const &event : *( eventsequence.second ) ) {
if( uitextline4.back() != '[' ) {
uitextline4 += ", ";
}
if( event.second ) {
uitextline4 += event.second->asName;
}
}
uitextline4 += "] ";
}
}
else if( typeid( *node ) == typeid( TMemCell ) ) {
auto const *subnode = static_cast<TMemCell const *>( node );
uitextline2 =
"data: [" + subnode->Text() + "]"
+ " [" + to_string( subnode->Value1(), 2 ) + "]"
+ " [" + to_string( subnode->Value2(), 2 ) + "]";
uitextline3 = "track: " + ( subnode->asTrackName.empty() ? "none" : subnode->asTrackName );
}
update:
// update the ui header texts
auto &headerdata = UIHeader.text_lines;
headerdata[ 0 ].data = uitextline1;
headerdata[ 1 ].data = uitextline2;
headerdata[ 2 ].data = uitextline3;
headerdata[ 3 ].data = uitextline4;
ui_layer::update();
m_itempropertiespanel.update( m_node );
}
void

View File

@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
#pragma once
#include "uilayer.h"
#include "editoruipanels.h"
namespace scene {
@@ -34,6 +35,6 @@ public:
private:
// members
ui_panel UIHeader { 20, 20 }; // header ui panel
itemproperties_panel m_itempropertiespanel { "Node Properties", true };
scene::basic_node * m_node { nullptr }; // currently bound scene node, if any
};

196
editoruipanels.cpp Normal file
View File

@@ -0,0 +1,196 @@
/*
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 "editoruipanels.h"
#include "globals.h"
#include "camera.h"
#include "animmodel.h"
#include "track.h"
#include "event.h"
#include "renderer.h"
#include "utilities.h"
void
itemproperties_panel::update( scene::basic_node const *Node ) {
if( false == is_open ) { return; }
text_lines.clear();
std::string textline;
// scenario inspector
auto const *node { Node };
auto const &camera { Global.pCamera };
if( node == nullptr ) {
auto const mouseposition { camera.Pos + GfxRenderer.Mouse_Position() };
textline = "mouse location: [" + to_string( mouseposition.x, 2 ) + ", " + to_string( mouseposition.y, 2 ) + ", " + to_string( mouseposition.z, 2 ) + "]";
text_lines.emplace_back( textline, Global.UITextColor );
return;
}
textline =
"node name: " + node->name()
+ "\nlocation: [" + 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{ camera.Pos.x, 0.0, camera.Pos.z } ), 1 ) + " m)";
text_lines.emplace_back( textline, Global.UITextColor );
// subclass-specific data
// TBD, TODO: specialized data dump method in each node subclass, or data imports in the panel for provided subclass pointer?
if( typeid( *node ) == typeid( TAnimModel ) ) {
auto const *subnode = static_cast<TAnimModel const *>( node );
textline = "angle: " + to_string( clamp_circular( subnode->vAngle.y, 360.f ), 2 ) + " deg";
textline += "; lights: ";
if( subnode->iNumLights > 0 ) {
textline += '[';
for( int lightidx = 0; lightidx < subnode->iNumLights; ++lightidx ) {
textline += to_string( subnode->lsLights[ lightidx ] );
if( lightidx < subnode->iNumLights - 1 ) {
textline += ", ";
}
}
textline += ']';
}
else {
textline += "none";
}
text_lines.emplace_back( textline, Global.UITextColor );
// 3d shape
auto modelfile { (
( subnode->pModel != nullptr ) ?
subnode->pModel->NameGet() :
"none" ) };
if( modelfile.find( szModelPath ) == 0 ) {
// don't include 'models/' in the path
modelfile.erase( 0, std::string{ szModelPath }.size() );
}
// texture
auto texturefile { (
( subnode->Material()->replacable_skins[ 1 ] != null_handle ) ?
GfxRenderer.Material( subnode->Material()->replacable_skins[ 1 ] ).name :
"none" ) };
if( texturefile.find( szTexturePath ) == 0 ) {
// don't include 'textures/' in the path
texturefile.erase( 0, std::string{ szTexturePath }.size() );
}
text_lines.emplace_back( "mesh: " + modelfile, Global.UITextColor );
text_lines.emplace_back( "skin: " + texturefile, Global.UITextColor );
}
else if( typeid( *node ) == typeid( TTrack ) ) {
auto const *subnode = static_cast<TTrack const *>( node );
// basic attributes
textline =
"isolated: " + ( ( subnode->pIsolated != nullptr ) ? subnode->pIsolated->asName : "none" )
+ "\nvelocity: " + to_string( subnode->SwitchExtension ? subnode->SwitchExtension->fVelocity : subnode->fVelocity )
+ "\nwidth: " + to_string( subnode->fTrackWidth ) + " m"
+ "\nfriction: " + to_string( subnode->fFriction, 2 )
+ "\nquality: " + to_string( subnode->iQualityFlag );
text_lines.emplace_back( textline, Global.UITextColor );
// textures
auto texturefile { (
( subnode->m_material1 != null_handle ) ?
GfxRenderer.Material( subnode->m_material1 ).name :
"none" ) };
if( texturefile.find( szTexturePath ) == 0 ) {
texturefile.erase( 0, std::string{ szTexturePath }.size() );
}
auto texturefile2{ (
( subnode->m_material2 != null_handle ) ?
GfxRenderer.Material( subnode->m_material2 ).name :
"none" ) };
if( texturefile2.find( szTexturePath ) == 0 ) {
texturefile2.erase( 0, std::string{ szTexturePath }.size() );
}
textline = "skins:\n " + texturefile + "\n " + texturefile2;
text_lines.emplace_back( textline, Global.UITextColor );
// paths
textline = "paths: ";
for( auto const &path : subnode->m_paths ) {
textline +=
"\n ["
+ to_string( path.points[ segment_data::point::start ].x, 3 ) + ", "
+ to_string( path.points[ segment_data::point::start ].y, 3 ) + ", "
+ to_string( path.points[ segment_data::point::start ].z, 3 ) + "]->"
+ "["
+ to_string( path.points[ segment_data::point::end ].x, 3 ) + ", "
+ to_string( path.points[ segment_data::point::end ].y, 3 ) + ", "
+ to_string( path.points[ segment_data::point::end ].z, 3 ) + "] ";
}
text_lines.emplace_back( textline, Global.UITextColor );
// events
textline.clear();
std::vector< std::pair< std::string, TTrack::event_sequence const * > > const eventsequences {
{ "ev0", &subnode->m_events0 }, { "ev0all", &subnode->m_events0all },
{ "ev1", &subnode->m_events1 }, { "ev1all", &subnode->m_events1all },
{ "ev2", &subnode->m_events2 }, { "ev2all", &subnode->m_events2all } };
for( auto const &eventsequence : eventsequences ) {
if( eventsequence.second->empty() ) { continue; }
textline += ( textline.empty() ? "" : "\n" ) + eventsequence.first + ": [";
for( auto const &event : *( eventsequence.second ) ) {
if( textline.back() != '[' ) {
textline += ", ";
}
textline += (
event.second ?
event.second->asName :
event.first + " (missing)" );
}
textline += "] ";
}
text_lines.emplace_back( textline, Global.UITextColor );
}
else if( typeid( *node ) == typeid( TMemCell ) ) {
auto const *subnode = static_cast<TMemCell const *>( node );
textline =
"data: [" + subnode->Text() + "]"
+ " [" + to_string( subnode->Value1(), 2 ) + "]"
+ " [" + to_string( subnode->Value2(), 2 ) + "]";
text_lines.emplace_back( textline, Global.UITextColor );
textline = "track: " + ( subnode->asTrackName.empty() ? "none" : subnode->asTrackName );
text_lines.emplace_back( textline, Global.UITextColor );
}
}
void
itemproperties_panel::render() {
if( false == is_open ) { return; }
if( true == text_lines.empty() ) { return; }
auto flags =
ImGuiWindowFlags_NoFocusOnAppearing
| ImGuiWindowFlags_NoCollapse
| ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 );
if( size.x > 0 ) {
ImGui::SetNextWindowSize( ImVec2( size.x, size.y ) );
}
if( size_min.x > 0 ) {
ImGui::SetNextWindowSizeConstraints( ImVec2( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) );
}
if( true == ImGui::Begin( name.c_str(), nullptr, flags ) ) {
// header section
for( auto const &line : text_lines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
}
ImGui::End();
}

24
editoruipanels.h Normal file
View File

@@ -0,0 +1,24 @@
/*
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 "uilayer.h"
#include "classes.h"
class itemproperties_panel : public ui_panel {
public:
itemproperties_panel( std::string const Name, bool const Isopen )
: ui_panel( Name, Isopen )
{}
void update( scene::basic_node const *Node );
void render() override;
};

View File

@@ -49,6 +49,9 @@
<Filter Include="Source Files\application\input">
<UniqueIdentifier>{0630616b-1afe-4fb6-96d1-3755834ba8aa}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\imgui">
<UniqueIdentifier>{33f7f4ae-692b-4989-a71a-004e0d48ed4f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AirCoupler.cpp">
@@ -306,6 +309,24 @@
<ClCompile Include="scenenodegroups.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ref\imgui\imgui.cpp">
<Filter>Source Files\imgui</Filter>
</ClCompile>
<ClCompile Include="ref\imgui\imgui_draw.cpp">
<Filter>Source Files\imgui</Filter>
</ClCompile>
<ClCompile Include="ref\imgui\examples\imgui_impl_opengl2.cpp">
<Filter>Source Files\imgui</Filter>
</ClCompile>
<ClCompile Include="ref\imgui\examples\imgui_impl_glfw.cpp">
<Filter>Source Files\imgui</Filter>
</ClCompile>
<ClCompile Include="driveruipanels.cpp">
<Filter>Source Files\application\mode_driver</Filter>
</ClCompile>
<ClCompile Include="editoruipanels.cpp">
<Filter>Source Files\application\mode_editor</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Globals.h">
@@ -578,6 +599,12 @@
<ClInclude Include="scenenodegroups.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="driveruipanels.h">
<Filter>Header Files\application\mode_driver</Filter>
</ClInclude>
<ClInclude Include="editoruipanels.h">
<Filter>Header Files\application\mode_editor</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="maszyna.rc">

View File

@@ -33,7 +33,7 @@ double TTrainParameters::WatchMTable(double DistCounter)
return dist;
}
std::string TTrainParameters::NextStop()
std::string TTrainParameters::NextStop() const
{ // pobranie nazwy następnego miejsca zatrzymania
if (StationIndex <= StationCount)
return NextStationName; // nazwa następnego przystanku;
@@ -41,7 +41,7 @@ std::string TTrainParameters::NextStop()
return "[End of route]"; //że niby koniec
}
bool TTrainParameters::IsStop()
bool TTrainParameters::IsStop() const
{ // zapytanie, czy zatrzymywać na następnym punkcie rozkładu
if ((StationIndex < StationCount))
return TimeTable[StationIndex].Ah >= 0; //-1 to brak postoju
@@ -129,7 +129,7 @@ bool TTrainParameters::IsTimeToGo(double hh, double mm)
return false; // dalej nie jechać
}
std::string TTrainParameters::ShowRelation()
std::string TTrainParameters::ShowRelation() const
/*zwraca informację o relacji*/
{
// if (Relation1=TimeTable[1].StationName) and (Relation2=TimeTable[StationCount].StationName)

View File

@@ -69,10 +69,10 @@ class TTrainParameters
int Direction; /*kierunek jazdy w/g kilometrazu*/
double CheckTrainLatency();
/*todo: str hh:mm to int i z powrotem*/
std::string ShowRelation();
std::string ShowRelation() const;
double WatchMTable(double DistCounter);
std::string NextStop();
bool IsStop();
std::string NextStop() const;
bool IsStop() const;
bool IsTimeToGo(double hh, double mm);
bool UpdateMTable(double hh, double mm, std::string const &NewName);
bool UpdateMTable( scenario_time const &Time, std::string const &NewName );

View File

@@ -409,6 +409,9 @@ opengl_renderer::Render() {
m_debugstats = debug_stats();
Render_pass( rendermode::color );
Timer::subsystem.gfx_color.stop();
// add user interface
setup_units( true, false, false );
Application.render_ui();
Timer::subsystem.gfx_swap.start();
glfwSwapBuffers( m_window );
@@ -416,15 +419,19 @@ opengl_renderer::Render() {
m_drawcount = m_cellqueue.size();
m_debugtimestext
+= "frame: " + to_string( Timer::subsystem.gfx_color.average(), 2 ) + " msec (" + std::to_string( m_cellqueue.size() ) + " sectors) "
+= "gpu side: " + to_string( Timer::subsystem.gfx_swap.average(), 2 ) + " msec "
+= "(" + to_string( Timer::subsystem.gfx_color.average() + Timer::subsystem.gfx_swap.average(), 2 ) + " msec total)";
+= "color: " + to_string( Timer::subsystem.gfx_color.average(), 2 ) + " msec (" + std::to_string( m_cellqueue.size() ) + " sectors)\n"
+= "gpu side: " + to_string( Timer::subsystem.gfx_swap.average(), 2 ) + " msec\n"
+= "frame total: " + to_string( Timer::subsystem.gfx_color.average() + Timer::subsystem.gfx_swap.average(), 2 ) + " msec";
m_debugstatstext =
"drawcalls: " + to_string( m_debugstats.drawcalls )
+ "; dyn: " + to_string( m_debugstats.dynamics ) + " mod: " + to_string( m_debugstats.models ) + " sub: " + to_string( m_debugstats.submodels )
+ "; trk: " + to_string( m_debugstats.paths ) + " shp: " + to_string( m_debugstats.shapes )
+ " trc: " + to_string( m_debugstats.traction ) + " lin: " + to_string( m_debugstats.lines );
"drawcalls: " + to_string( m_debugstats.drawcalls ) + "\n"
+ " vehicles: " + to_string( m_debugstats.dynamics ) + "\n"
+ " models: " + to_string( m_debugstats.models ) + "\n"
+ " submodels: " + to_string( m_debugstats.submodels ) + "\n"
+ " paths: " + to_string( m_debugstats.paths ) + "\n"
+ " shapes: " + to_string( m_debugstats.shapes ) + "\n"
+ " traction: " + to_string( m_debugstats.traction ) + "\n"
+ " lines: " + to_string( m_debugstats.lines );
++m_framestamp;
@@ -463,7 +470,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
Render_pass( rendermode::cabshadows );
}
Timer::subsystem.gfx_shadows.stop();
m_debugtimestext += "shadows: " + to_string( Timer::subsystem.gfx_shadows.average(), 2 ) + " msec (" + std::to_string( m_cellqueue.size() ) + " sectors) ";
m_debugtimestext += "shadows: " + to_string( Timer::subsystem.gfx_shadows.average(), 2 ) + " msec (" + std::to_string( m_cellqueue.size() ) + " sectors)\n";
#ifdef EU07_USE_DEBUG_SHADOWMAP
UILayer.set_texture( m_shadowdebugtexture );
#endif
@@ -584,7 +591,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
::glMatrixMode( GL_MODELVIEW );
}
}
Application.render_ui();
break;
}
@@ -1413,10 +1419,6 @@ opengl_renderer::Render( world_environment *Environment ) {
// skydome
Environment->m_skydome.Render();
if( true == Global.bUseVBO ) {
// skydome uses a custom vbo which could potentially confuse the main geometry system. hardly elegant but, eh
gfx::opengl_vbogeometrybank::reset();
}
// stars
if( Environment->m_stars.m_stars != nullptr ) {
// setup

View File

@@ -118,6 +118,9 @@ void CSkyDome::Update( glm::vec3 const &Sun ) {
// render skydome to screen
void CSkyDome::Render() {
// cache entry state
::glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
if( m_vertexbuffer == -1 ) {
// build the buffers
::glGenBuffers( 1, &m_vertexbuffer );
@@ -146,8 +149,7 @@ void CSkyDome::Render() {
::glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer );
::glDrawElements( GL_TRIANGLES, static_cast<GLsizei>( m_indices.size() ), GL_UNSIGNED_SHORT, reinterpret_cast<void const*>( 0 ) );
// cleanup
::glDisableClientState( GL_COLOR_ARRAY );
::glDisableClientState( GL_VERTEX_ARRAY );
::glPopClientAttrib();
}
bool CSkyDome::SetSunPosition( glm::vec3 const &Direction ) {

View File

@@ -77,13 +77,20 @@
#define GLFW_DLL
#endif // _windows
#endif // build_static
#ifndef __ANDROID__
#include "GL/glew.h"
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#ifdef _WIN32
#include "GL/wglew.h"
#endif
#define GLFW_INCLUDE_GLU
//m7todo: jest tu bo nie chcia³o mi siê wpychaæ do wszystkich plików
#ifndef __ANDROID__
#include <GLFW/glfw3.h>
#endif
#define GLM_ENABLE_EXPERIMENTAL
#define GLM_FORCE_CTOR_INIT
@@ -96,3 +103,16 @@
#include <glm/gtx/norm.hpp>
#include "openglmatrixstack.h"
// imgui.h comes with its own operator new which gets wrecked by dbg_new, so we temporarily disable the latter
#ifdef _MSC_VER
#ifdef _DEBUG
#undef new
#endif // _DEBUG
#endif
#include "imgui.h"
#ifdef _MSC_VER
#ifdef _DEBUG
#define new DBG_NEW
#endif // _DEBUG
#endif

View File

@@ -27,61 +27,107 @@ http://mozilla.org/MPL/2.0/.
#include "utilities.h"
#include "logs.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl2.h"
extern "C"
{
GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); //m7todo: potrzebne do directsound
}
GLFWwindow * ui_layer::m_window { nullptr };
ImGuiIO *ui_layer::m_imguiio { nullptr };
GLint ui_layer::m_textureunit { GL_TEXTURE0 };
GLuint ui_layer::m_fontbase { (GLuint)-1 }; // numer DL dla znaków w napisach
bool ui_layer::m_cursorvisible { true };
ui_layer::~ui_layer() {
/*
// this should be invoked manually, or we risk trying to delete the lists after the context is gone
if( m_fontbase != -1 )
::glDeleteLists( m_fontbase, 96 );
*/
ui_panel::ui_panel( std::string const Name, bool const Isopen )
: name( Name ), is_open( Isopen )
{}
void
ui_panel::render() {
if( false == is_open ) { return; }
if( true == text_lines.empty() ) { return; }
auto flags =
ImGuiWindowFlags_NoFocusOnAppearing
| ImGuiWindowFlags_NoCollapse
| ( size.x > 0 ? ImGuiWindowFlags_NoResize : 0 );
if( size.x > 0 ) {
ImGui::SetNextWindowSize( ImVec2( size.x, size.y ) );
}
if( size_min.x > 0 ) {
ImGui::SetNextWindowSizeConstraints( ImVec2( size_min.x, size_min.y ), ImVec2( size_max.x, size_max.y ) );
}
if( true == ImGui::Begin( name.c_str(), &is_open, flags ) ) {
for( auto const &line : text_lines ) {
ImGui::TextColored( ImVec4( line.color.r, line.color.g, line.color.b, line.color.a ), line.data.c_str() );
}
}
ImGui::End();
}
ui_layer::~ui_layer() {}
bool
ui_layer::init( GLFWwindow *Window ) {
m_window = Window;
HFONT font; // Windows Font ID
m_fontbase = ::glGenLists(96); // storage for 96 characters
HDC hDC = ::GetDC( glfwGetWin32Window( m_window ) );
font = ::CreateFont( -MulDiv( 10, ::GetDeviceCaps( hDC, LOGPIXELSY ), 72 ), // height of font
0, // width of font
0, // angle of escapement
0, // orientation angle
(Global.bGlutFont ? FW_MEDIUM : FW_HEAVY), // font weight
FALSE, // italic
FALSE, // underline
FALSE, // strikeout
DEFAULT_CHARSET, // character set identifier
OUT_DEFAULT_PRECIS, // output precision
CLIP_DEFAULT_PRECIS, // clipping precision
(Global.bGlutFont ? CLEARTYPE_QUALITY : PROOF_QUALITY), // output quality
DEFAULT_PITCH | FF_DONTCARE, // family and pitch
"Lucida Console"); // font name
::SelectObject(hDC, font); // selects the font we want
if( TRUE == ::wglUseFontBitmaps( hDC, 32, 96, m_fontbase ) ) {
// builds 96 characters starting at character 32
WriteLog( "Display Lists font used" ); //+AnsiString(glGetError())
WriteLog( "Font init OK" ); //+AnsiString(glGetError())
Global.DLFont = true;
return true;
}
else {
ErrorLog( "Font init failed" );
// return false;
// NOTE: we report success anyway, given some cards can't produce fonts in this manner
Global.DLFont = false;
return true;
}
IMGUI_CHECKVERSION();
ImGui::CreateContext();
m_imguiio = &ImGui::GetIO();
// m_imguiio->Fonts->AddFontFromFileTTF( "c:/windows/fonts/lucon.ttf", 13.0f );
ImGui_ImplGlfw_InitForOpenGL( m_window, false );
ImGui_ImplOpenGL2_Init();
init_colors();
return true;
}
void
ui_layer::init_colors() {
// configure ui colours
auto *style = &ImGui::GetStyle();
auto *colors = style->Colors;
auto const background { ImVec4( 38.0f / 255.0f, 38.0f / 255.0f, 38.0f / 255.0f, 0.65f ) };
auto const accent { ImVec4( 44.0f / 255.0f, 88.0f / 255.0f, 72.0f / 255.0f, 0.75f ) };
auto const itembase { ImVec4( accent.x, accent.y, accent.z, 0.35f ) };
auto const itemhover { ImVec4( accent.x, accent.y, accent.z, 0.65f ) };
auto const itemactive { ImVec4( accent.x, accent.y, accent.z, 0.95f ) };
colors[ ImGuiCol_WindowBg ] = background;
colors[ ImGuiCol_PopupBg ] = background;
colors[ ImGuiCol_FrameBg ] = itembase;
colors[ ImGuiCol_FrameBgHovered ] = itemhover;
colors[ ImGuiCol_FrameBgActive ] = itemactive;
colors[ ImGuiCol_TitleBg ] = background;
colors[ ImGuiCol_TitleBgActive ] = background;
colors[ ImGuiCol_TitleBgCollapsed ] = background;
colors[ ImGuiCol_CheckMark ] = colors[ ImGuiCol_Text ];
colors[ ImGuiCol_Button ] = itembase;
colors[ ImGuiCol_ButtonHovered ] = itemhover;
colors[ ImGuiCol_ButtonActive ] = itemactive;
colors[ ImGuiCol_Header ] = itembase;
colors[ ImGuiCol_HeaderHovered ] = itemhover;
colors[ ImGuiCol_HeaderActive ] = itemactive;
colors[ ImGuiCol_ResizeGrip ] = itembase;
colors[ ImGuiCol_ResizeGripHovered ] = itemhover;
colors[ ImGuiCol_ResizeGripActive ] = itemactive;
}
void
ui_layer::shutdown() {
ImGui_ImplOpenGL2_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
bool
@@ -90,9 +136,18 @@ ui_layer::on_key( int const Key, int const Action ) {
return false;
}
void
ui_layer::update() {
for( auto *panel : m_panels ) {
panel->update();
}
}
void
ui_layer::render() {
// legacy ui code
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, std::max( 1, Global.iWindowWidth ), std::max( 1, Global.iWindowHeight ), 0, -1, 1 );
@@ -120,10 +175,27 @@ ui_layer::render() {
glDisable( GL_BLEND );
glPopAttrib();
// imgui ui code
::glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
::glClientActiveTexture( m_textureunit );
::glBindBuffer( GL_ARRAY_BUFFER, 0 );
ImGui_ImplOpenGL2_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
render_panels();
render_tooltip();
// template method implementation
render_();
glPopAttrib();
ImGui::Render();
ImGui_ImplOpenGL2_RenderDrawData( ImGui::GetDrawData() );
::glPopClientAttrib();
}
void
@@ -207,30 +279,14 @@ ui_layer::render_progress() {
::glRasterPos2f(
( 0.5f * ( Global.iWindowWidth - width ) + origin.x * heightratio ) + ( ( size.x * heightratio - textwidth ) * 0.5f * heightratio ),
( 0.5f * ( Global.iWindowHeight - height ) + origin.y * heightratio ) + ( charsize ) + ( ( size.y * heightratio - textheight ) * 0.5f * heightratio ) );
print( m_progresstext );
}
}
void
ui_layer::render_panels() {
if( m_panels.empty() ) { return; }
float const width = std::min( 4.f / 3.f, static_cast<float>(Global.iWindowWidth) / std::max( 1, Global.iWindowHeight ) ) * Global.iWindowHeight;
float const height = Global.iWindowHeight / 768.f;
for( auto const &panel : m_panels ) {
int lineidx = 0;
for( auto const &line : panel->text_lines ) {
::glColor4fv( glm::value_ptr( line.color ) );
::glRasterPos2f(
0.5f * ( Global.iWindowWidth - width ) + panel->origin_x * height,
panel->origin_y * height + 20.f * lineidx );
print( line.data );
++lineidx;
}
for( auto *panel : m_panels ) {
panel->render();
}
}
@@ -240,12 +296,7 @@ ui_layer::render_tooltip() {
if( m_tooltip.empty() ) { return; }
if( false == m_cursorvisible ) { return; }
glm::dvec2 mousepos;
glfwGetCursorPos( m_window, &mousepos.x, &mousepos.y );
::glColor4fv( glm::value_ptr( colors::white ) );
::glRasterPos2f( mousepos.x + 20.0f, mousepos.y + 25.0f );
print( m_tooltip );
ImGui::SetTooltip( m_tooltip.c_str() );
}
void
@@ -295,21 +346,6 @@ ui_layer::render_texture() {
}
}
void
ui_layer::print( std::string const &Text )
{
if( (false == Global.DLFont)
|| (true == Text.empty()) )
return;
::glPushAttrib( GL_LIST_BIT );
::glListBase( m_fontbase - 32 );
::glCallLists( Text.size(), GL_UNSIGNED_BYTE, Text.c_str() );
::glPopAttrib();
}
void
ui_layer::quad( glm::vec4 const &Coordinates, glm::vec4 const &Color ) {

View File

@@ -14,25 +14,35 @@ http://mozilla.org/MPL/2.0/.
// GuiLayer -- basic user interface class. draws requested information on top of openGL screen
struct ui_panel {
class ui_panel {
public:
// constructor
ui_panel( std::string const Name, bool const Isopen );
// methods
virtual void update() {};
virtual void render();
// temporary access
// types
struct text_line {
std::string data;
glm::vec4 color;
text_line( std::string const &Data, glm::vec4 const &Color):
data(Data), color(Color)
text_line( std::string const &Data, glm::vec4 const &Color)
: data(Data), color(Color)
{}
};
ui_panel( const int X, const int Y):
origin_x(X), origin_y(Y)
{}
// members
bool is_open;
glm::ivec2 size { -1, -1 };
glm::ivec2 size_min { -1, -1 };
glm::ivec2 size_max { -1, -1 };
std::vector<text_line> text_lines;
int origin_x;
int origin_y;
protected:
// members
std::string name;
};
class ui_layer {
@@ -51,6 +61,9 @@ public:
static
void
set_unit( GLint const Textureunit ) { m_textureunit = Textureunit; }
static
void
shutdown();
// potentially processes provided input key. returns: true if the input was processed, false otherwise
virtual
bool
@@ -58,7 +71,7 @@ public:
// updates state of UI elements
virtual
void
update() {}
update();
// draws requested UI elements
void
render();
@@ -79,17 +92,25 @@ public:
void
set_tooltip( std::string const &Tooltip ) { m_tooltip = Tooltip; }
void
clear_texts() { m_panels.clear(); }
clear_panels() { m_panels.clear(); }
void
push_back( ui_panel *Panel ) { m_panels.emplace_back( Panel ); }
protected:
// members
static GLFWwindow *m_window;
static ImGuiIO *m_imguiio;
static bool m_cursorvisible;
private:
// methods
static
void
init_colors();
// render() subclass details
virtual
void
render_() {};
// draws background quad with specified earlier texture
void
render_background();
@@ -102,15 +123,11 @@ private:
render_panels();
void
render_tooltip();
// prints specified text, using display lists font
void
print( std::string const &Text );
// draws a quad between coordinates x,y and z,w with uv-coordinates spanning 0-1
void
quad( glm::vec4 const &Coordinates, glm::vec4 const &Color );
// members
static GLint m_textureunit;
static GLuint m_fontbase; // numer DL dla znaków w napisach
// progress bar config. TODO: put these together into an object
float m_progress { 0.0f }; // percentage of filled progres bar, to indicate lengthy operations.