#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" #include "ops.hh" #include "rendertarget.hh" #include "sync.hh" #include "syncview.hh" #include "undo.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; T_Optional< T_Demo > demo; T_Optional< T_SyncView > sequencer; void initDemo( ); void startIteration( ); void handleCapture( ); void makeUI( ); void render( ); }; /*----------------------------------------------------------------------------*/ T_Main::T_Main( ) { Globals::Init( ); prevSize = ImVec2( -1 , -1 ); } void T_Main::mainLoop( ) { auto& p( Globals::Profiler( ) ); while ( !done ) { 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; } } bool needInit( !demo ); if ( stopResize > 0 ) { stopResize --; if ( stopResize == 0 ) { needInit = true; } } if ( needInit ) { initDemo( ); } #warning FIXME remove this if ( !sequencer ) { sequencer.setNew( ); } 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.clear( ); Globals::Shutdown( ); } /*----------------------------------------------------------------------------*/ 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 ) ) { Globals::Profiler( ).clear( ); } } 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( ) { using namespace ImGui; auto const& io( GetIO( ) ); const T_MouseButtons mb( ([]() {; T_MouseButtons mb; if ( IsMouseDown( 0 ) ) { mb |= E_MouseButton::LEFT; } if ( IsMouseDown( 1 ) ) { mb |= E_MouseButton::RIGHT; } if ( IsMouseDown( 2 ) ) { mb |= E_MouseButton::MIDDLE; } return mb; })() ); const T_KeyboardModifiers kb( ([&io]() { T_KeyboardModifiers kb; if ( io.KeyCtrl ) { kb |= E_KeyboardModifier::CTRL; } if ( io.KeyShift ) { kb |= E_KeyboardModifier::SHIFT; } if ( io.KeyAlt ) { kb |= E_KeyboardModifier::ALT; } return kb; })() ); const bool appCanGrab( !( ImGui::IsMouseHoveringAnyWindow( ) || io.WantCaptureMouse || io.WantCaptureKeyboard ) ); if ( capture && !mb ) { capture = false; CaptureMouseFromApp( false ); SDL_SetRelativeMouseMode( SDL_FALSE ); Globals::Window( ).warpMouse( mouseInitial ); SetMouseCursor( ImGuiMouseCursor_Arrow ); } else if ( capture ) { SetMouseCursor( ImGuiMouseCursor_Move ); Globals::Sync( ).handleDragAndDrop( mouseMove , kb , mb ); } else if ( appCanGrab && mb ) { capture = true; mouseInitial = GetMousePos( ); CaptureMouseFromApp( true ); SDL_SetRelativeMouseMode( SDL_TRUE ); SetMouseCursor( ImGuiMouseCursor_Move ); } if ( ( appCanGrab || capture ) && io.MouseWheel ) { Globals::Sync( ).handleWheel( io.MouseWheel , kb , mb ); } } void T_Main::makeUI( ) { using namespace ImGui; auto& undo( Globals::Undo( ) ); auto& sync( Globals::Sync( ) ); bool eSequencer{ sequencer }; if ( BeginMainMenuBar( ) ) { if ( BeginMenu( "File" ) ) { if ( MenuItem( "Save curves" , "C-s" , false , sync.curvesModified( ) ) ) { if ( sync.curvesFileChanged( ) ) { Globals::Window( ).msgbox( "Curves file changed" , "The file containing the curves has been modified " "on the disk. These changes will be overwritten. " "Do you want to continue?" , []( auto b ) { if ( b == T_MessageBox::BT_YES ) { Globals::Sync( ).saveCurves( ); } } , { T_MessageBox::BT_YES , T_MessageBox::BT_NO } ); } else { sync.saveCurves( ); } } if ( MenuItem( "Reload curves" , "C-R" , false , sync.curvesModified( ) ) ) { Globals::Window( ).msgbox( "Reload curves?" , "Changes you made to the curves will be lost. Do you " "want to continue?" , []( auto b ) { if ( b == T_MessageBox::BT_YES ) { Globals::Sync( ).loadCurves( ); } } , { T_MessageBox::BT_YES , T_MessageBox::BT_NO } ); } Separator( ); if ( MenuItem( "Undo" , "C-z" , false , undo.canUndo( ) ) ) { undo.undo( ); } if ( MenuItem( "Redo" , "C-Z" , false , undo.canRedo( ) ) ) { undo.redo( ); } Separator( ); if ( MenuItem( "Quit" ) ) { done = true; } EndMenu( ); } if ( BeginMenu( "Views" ) ) { MenuItemCheckbox( "Input overrides" , &sync.overridesWindowEnabled( ) ); MenuItemCheckbox( "Output debugger" , &Globals::ODbg( ).uiEnabled( ) ); MenuItemCheckbox( "Profiler" , &Globals::Profiler( ).uiEnabled( ) ); MenuItemCheckbox( "Sequencer" , &eSequencer ); MenuItemCheckbox( "Shaders" , &Globals::Shaders( ).uiEnabled( ) ); EndMenu( ); } EndMainMenuBar( ); } if ( eSequencer && !sequencer ) { sequencer.setNew( ); } else if ( !eSequencer && sequencer ) { sequencer.clear( ); } Globals::Profiler( ).makeUI( ); Globals::ODbg( ).makeUI( ); Globals::Shaders( ).makeUI( ); Globals::Sync( ).makeOverridesWindow( ); if ( sequencer && !sequencer->display( ) ) { sequencer.clear( ); } } void T_Main::render( ) { if ( demo ) { demo->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 ); } Globals::Window( ).handleDialogs( ); 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; }