#include "externals.hh" #include "imgui_impl_sdl.h" #include "demo.hh" #include "globals.hh" #include "profiling.hh" #include "window.hh" #include "shaders.hh" #include "odbg.hh" /*= T_Main ===================================================================*/ struct T_Main { static constexpr uint32_t ResizeDelay = 50; T_Main( ); ~T_Main( ); void mainLoop( ); private: bool done = false; bool capture = false; ImVec2 mouseInitial; ImVec2 mouseMove; uint32_t stopResize = 0; ImVec2 prevSize; bool demoCtrl_ = false; std::unique_ptr< T_Demo > demo; void initDemo( ); void startIteration( ); void handleCapture( ); void makeUI( ); void render( ); }; /*----------------------------------------------------------------------------*/ T_Main::T_Main( ) { Globals::Init( ); prevSize = ImVec2( 1280 , 720 ); } void T_Main::mainLoop( ) { auto& p( Globals::Profiler( ) ); while ( !done ) { if ( demo ) { auto const& dspSize( ImGui::GetIO( ).DisplaySize ); if ( prevSize.x != dspSize.x || prevSize.y != dspSize.y ) { stopResize = ResizeDelay; prevSize = dspSize; } } if ( stopResize > 0 ) { stopResize --; if ( stopResize == 0 ) { demo.reset( ); } } if ( !demo ) { initDemo( ); } Globals::Watcher( ).check( ); Globals::Shaders( ).update( ); glFinish( ); p.startFrame( ); p.start( "Full frame" ); startIteration( ); if ( !done ) { handleCapture( ); makeUI( ); render( ); p.end( "Full frame" ); Globals::Window( ).swap( ); p.endFrame( ); } } } T_Main::~T_Main( ) { demo.reset( ); Globals::Shutdown( ); } /*----------------------------------------------------------------------------*/ void T_Main::initDemo( ) { assert( !demo ); auto const& dspSize( ImGui::GetIO( ).DisplaySize ); if ( dspSize.x < 0 || dspSize.y < 0 ) { return; } printf( "init w/ dspsize %dx%d\n" , int( dspSize.x ) , int( dspSize.y ) ); demo = std::make_unique< T_Demo >( dspSize.x , dspSize.y ); if ( demo->initialise( ) ) { Globals::Profiler( ).clear( ); } else { demo.reset( ); } } void T_Main::startIteration( ) { SDL_Event event; mouseMove = ImVec2( ); while ( SDL_PollEvent( &event ) ) { ImGui_ImplSdl_ProcessEvent( &event ); if ( event.type == SDL_QUIT ) { done = true; return; } if ( capture && event.type == SDL_MOUSEMOTION ) { mouseMove.x += event.motion.xrel; mouseMove.y += event.motion.yrel; } } Globals::Window( ).startFrame( capture , mouseInitial ); ImGui::GetIO( ).MouseDrawCursor = true; } void T_Main::handleCapture( ) { auto const& io( ImGui::GetIO( ) ); const bool lmb( ImGui::IsMouseDown( 0 ) ); const bool mb( lmb || ImGui::IsMouseDown( 1 ) ); const bool appCanGrab( !( ImGui::IsMouseHoveringAnyWindow( ) || io.WantCaptureMouse || io.WantCaptureKeyboard ) ); const bool shift( io.KeyShift ); const bool ctrl( io.KeyCtrl ); if ( capture && !mb ) { capture = false; ImGui::CaptureMouseFromApp( false ); SDL_SetRelativeMouseMode( SDL_FALSE ); Globals::Window( ).warpMouse( mouseInitial ); ImGui::SetMouseCursor( ImGuiMouseCursor_Arrow ); } else if ( capture ) { ImGui::SetMouseCursor( ImGuiMouseCursor_Move ); if ( demo ) { demo->handleDND( mouseMove , ctrl , shift , lmb ); } } else if ( appCanGrab && mb ) { capture = true; mouseInitial = ImGui::GetMousePos( ); ImGui::CaptureMouseFromApp( true ); SDL_SetRelativeMouseMode( SDL_TRUE ); ImGui::SetMouseCursor( ImGuiMouseCursor_Move ); } if ( ( appCanGrab || capture ) && io.MouseWheel && demo ) { demo->handleWheel( io.MouseWheel , ctrl , shift ); } } void T_Main::makeUI( ) { ImGui::SetNextWindowSize( ImVec2( 300 , 150 ) , ImGuiSetCond_Once ); ImGui::SetNextWindowPos( ImVec2( ) , ImGuiSetCond_Once ); ImGui::Begin( "Tools" ); ImGui::Checkbox( "Demo controls" , &demoCtrl_ ); ImGui::Checkbox( "Output debugger" , &Globals::ODbg( ).uiEnabled( ) ); ImGui::Checkbox( "Profiler" , &Globals::Profiler( ).uiEnabled( ) ); ImGui::Checkbox( "Shaders" , &Globals::Shaders( ).uiEnabled( ) ); if ( demo ) { ImGui::Separator( ); auto& sync( Globals::Sync( ) ); const float duration( sync.duration( ) ); float time( sync.time( ) ); if ( ImGui::SliderFloat( "" , &time , 0 , duration , "%.1fs" ) ) { sync.setTime( time ); demo->playing = demo->playing && ! sync.finished( ); } ImGui::SameLine( ); if ( ImGui::Button( demo->playing ? "Stop" : "Play" ) ) { demo->playing = !demo->playing; } } ImGui::End( ); if ( demo && demoCtrl_ ) { demo->makeUI( ); } Globals::Profiler( ).makeUI( ); Globals::ODbg( ).makeUI( ); Globals::Shaders( ).makeUI( ); } void T_Main::render( ) { if ( demo ) { Globals::Profiler( ).start( "Render" ); demo->render( ); glFinish( ); Globals::Profiler( ).end( "Render" ); Globals::Profiler( ).start( "Debug" ); T_Rendertarget::MainOutput( ); if ( Globals::ODbg( ).isActive( ) ) { Globals::ODbg( ).debugOutput( ); } glFinish( ); Globals::Profiler( ).end( "Debug" ); } else { T_Rendertarget::MainOutput( ); glClearColor( 0 , 0 , 0 , 1 ); glClear( GL_COLOR_BUFFER_BIT ); } glUseProgram( 0 ); glBindProgramPipeline( 0 ); Globals::Textures( ).reset( ); glClearColor( 0 , 0 , 0 , 1 ); ImGui::Render( ); } /*============================================================================*/ int main( int , char** ) { T_Main m; m.mainLoop( ); return 0; }