#include "externals.hh" #include "ui-imgui-sdl.hh" #include "demo.hh" #include "globals.hh" #include "profiling.hh" #include "window.hh" #include "shaders.hh" #include "odbg.hh" #include "opemu.hh" #include "rendertarget.hh" #include "sync.hh" #include "ui.hh" #include "ui-sequencer.hh" #include "ui-sync.hh" #include "ui-utilities.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( ); UI::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( ); UI::Shaders( ).update( ); glFinish( ); p.startFrame( ); p.start( "Full frame" ); startIteration( ); if ( !done ) { handleCapture( ); makeUI( ); render( ); p.end( "Full frame" ); UI::Window( ).swap( ); p.endFrame( ); } } } T_Main::~T_Main( ) { demo.clear( ); UI::Shutdown( ); 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; } } UI::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 ); UI::Window( ).warpMouse( mouseInitial ); SetMouseCursor( ImGuiMouseCursor_Arrow ); } else if ( capture ) { SetMouseCursor( ImGuiMouseCursor_Move ); UI::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 ) { UI::Sync( ).handleWheel( io.MouseWheel , kb , mb ); } } void T_Main::makeUI( ) { using namespace ImGui; auto& undo( Globals::Undo( ) ); bool eSequencer{ sequencer }; if ( BeginMainMenuBar( ) ) { if ( BeginMenu( "File" ) ) { UI::Window( ).actionMenu( "Save curves" ); UI::Window( ).actionMenu( "Reload curves" ); 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" , &UI::Sync( ).overridesWindowEnabled( ) ); MenuItemCheckbox( "Output debugger" , &UI::ODbg( ).uiEnabled( ) ); MenuItemCheckbox( "Profiler" , &Globals::Profiler( ).uiEnabled( ) ); MenuItemCheckbox( "Sequencer" , &eSequencer ); MenuItemCheckbox( "Shaders" , &UI::Shaders( ).uiEnabled( ) ); EndMenu( ); } EndMainMenuBar( ); } if ( eSequencer && !sequencer ) { sequencer.setNew( ); } else if ( !eSequencer && sequencer ) { sequencer.clear( ); } Globals::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( ); Globals::Profiler( ).start( "Debug" ); T_Rendertarget::MainOutput( ); if ( UI::ODbg( ).isActive( ) ) { UI::ODbg( ).debugOutput( ); } glFinish( ); Globals::Profiler( ).end( "Debug" ); } else { T_Rendertarget::MainOutput( ); glClearColor( 0 , 0 , 0 , 1 ); glClear( GL_COLOR_BUFFER_BIT ); } UI::Window( ).handleDialogs( ); glUseProgram( 0 ); glBindProgramPipeline( 0 ); UI::Textures( ).reset( ); glClearColor( 0 , 0 , 0 , 1 ); ImGui::Render( ); } /*============================================================================*/ int main( int , char** ) { T_Main m; m.mainLoop( ); return 0; }