#include "externals.hh" #include "common.hh" #include "c-filewatcher.hh" #include "ui.hh" #include "ui-app.hh" #include "ui-demo.hh" #include "ui-odbg.hh" #include "ui-opemu.hh" #include "ui-profiling.hh" #include "ui-rendertarget.hh" #include "ui-sequencer.hh" #include "ui-shaders.hh" #include "ui-sync.hh" #include "ui-utilities.hh" /*= T_Main ===================================================================*/ struct T_Main { static constexpr uint32_t ResizeDelay = 50; explicit T_Main( T_FSPath const& path ); ~T_Main( ); void mainLoop( ); private: bool done = false; uint32_t stopResize = 0; ImVec2 prevSize; UI ui; T_Optional< T_Demo > demo; T_Optional< T_SyncView > sequencer; void initDemo( ); void startIteration( ); void makeUI( ); void render( ); }; /*----------------------------------------------------------------------------*/ T_Main::T_Main( T_FSPath const& path ) : ui{ path } { prevSize = ImVec2( -1 , -1 ); } void T_Main::mainLoop( ) { auto& m( UI::Main( ) ); auto& p( UI::Profiler( ) ); while ( !m.exiting( ) ) { // Check whether there's a resize in progress auto const& dspSize( ImGui::GetIO( ).DisplaySize ); if ( prevSize.x != dspSize.x || prevSize.y != dspSize.y ) { const auto doit( prevSize.x > 0 ); prevSize = dspSize; if ( doit ) { stopResize = ResizeDelay; } } // If there was a resize and some time has passed, // re-initialise the demo. bool needInit( !demo ); if ( stopResize > 0 ) { stopResize --; if ( stopResize == 0 ) { needInit = true; } } if ( needInit ) { initDemo( ); } // Update file watcher and shaders Common::Watcher( ).check( ); UI::Shaders( ).update( ); // Display p.startFrame( ); p.start( "Full frame" ); m.handleEvents( ); if ( !m.exiting( ) ) { makeUI( ); render( ); m.render( ); } p.end( "Full frame" ); m.swap( ); p.endFrame( ); } } T_Main::~T_Main( ) { demo.clear( ); } /*----------------------------------------------------------------------------*/ void T_Main::initDemo( ) { auto const& dspSize( ImGui::GetIO( ).DisplaySize ); if ( dspSize.x < 0 || dspSize.y < 0 ) { return; } if ( !demo ) { demo.setNew( ); } printf( "init w/ dspsize %dx%d\n" , int( dspSize.x ) , int( dspSize.y ) ); if ( demo->initialise( (uint32_t) dspSize.x , (uint32_t) dspSize.y ) ) { UI::Profiler( ).clear( ); } } void T_Main::makeUI( ) { using namespace ImGui; auto& main{ UI::Main( ) }; bool eSequencer{ sequencer }; if ( BeginMainMenuBar( ) ) { if ( BeginMenu( "File" ) ) { main.actionMenu( "Save curves" ); main.actionMenu( "Reload curves" ); Separator( ); main.actionMenu( "Undo" ); main.actionMenu( "Redo" ); Separator( ); main.actionMenu( "Quit" ); EndMenu( ); } if ( BeginMenu( "Views" ) ) { MenuItemCheckbox( "Input overrides" , &UI::Sync( ).overridesWindowEnabled( ) ); MenuItemCheckbox( "Output debugger" , &UI::ODbg( ).uiEnabled( ) ); MenuItemCheckbox( "Profiler" , &UI::Profiler( ).uiEnabled( ) ); MenuItemCheckbox( "Sequencer" , &eSequencer ); MenuItemCheckbox( "Shaders" , &UI::Shaders( ).uiEnabled( ) ); EndMenu( ); } EndMainMenuBar( ); } if ( eSequencer && !sequencer ) { sequencer.setNew( ); } else if ( !eSequencer && sequencer ) { sequencer.clear( ); } UI::Profiler( ).makeUI( ); UI::ODbg( ).makeUI( ); UI::Shaders( ).makeUI( ); UI::Sync( ).makeOverridesWindow( ); if ( sequencer && !sequencer->display( ) ) { sequencer.clear( ); } } void T_Main::render( ) { if ( demo ) { demo->render( ); UI::Profiler( ).start( "Debug" ); T_Rendertarget::MainOutput( ); if ( UI::ODbg( ).isActive( ) ) { UI::ODbg( ).debugOutput( ); } UI::Profiler( ).end( "Debug" ); } else { T_Rendertarget::MainOutput( ); glClearColor( 0 , 0 , 0 , 1 ); glClear( GL_COLOR_BUFFER_BIT ); } } /*============================================================================*/ int main( int argc , char** argv ) { const T_FSPath cwd{ Filesystem::Cwd( ) }; T_FSPath pp; if ( argc >= 2 ) { pp = T_String{ argv[ 1 ] }; if ( !pp.isValid( ) ) { fprintf( stderr , "Invalid path '%s'\n" , argv[ 1 ] ); return 1; } } else { pp = T_String{ "." }; } const T_FSPath rpp{ ( pp.isRelative( ) ? ( cwd + pp ) : pp ).canonical( ) }; T_Main m{ rpp }; m.mainLoop( ); return 0; }