#include "externals.hh" #define IMGUI_DEFINE_MATH_OPERATORS #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" using ebcl::T_Optional; /*= 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; 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( ); } Globals::Watcher( ).check( ); Globals::Shaders( ).update( ); Globals::Sync( ).checkCurveFile( ); 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( ) { 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 ); } } bool CGCModeButton_( char const* const name , const bool disabled ) { using namespace ImGui; if ( disabled ) { PushItemFlag( ImGuiItemFlags_Disabled , true ); PushStyleVar( ImGuiStyleVar_Alpha , GetStyle( ).Alpha * 0.5f ); } const bool rv( Button( name ) ); if ( disabled ) { PopItemFlag( ); PopStyleVar( ); } return rv; } bool CGCComponentBar_( float* const value , const float base , const float unit , const ImVec4 color , char const* const label ) noexcept { using namespace ImGui; const float BarWidth = 24.f; const float BarHeight = 180.f; const float fullWidth = CalcItemWidth( ); const ImVec2 labelSize = CalcTextSize( label ); const ImVec2 maxValueSize = CalcTextSize( "-9.99" ); // Compute bounding boxes auto* const win( GetCurrentWindow( ) ); const ImVec2 cPos( win->DC.CursorPos ); const ImRect bbBar( cPos + ImVec2( ( fullWidth - BarWidth ) * .5f , 0 ) , cPos + ImVec2( ( fullWidth + BarWidth ) * .5f , BarHeight ) ); const ImRect bbLabel( cPos + ImVec2( 0 , BarHeight + 2 ) , cPos + ImVec2( fullWidth , BarHeight + labelSize.y + 2 ) ); const ImRect bbValue( ImVec2( cPos.x , bbLabel.Max.y + 2 ) , bbLabel.Max + ImVec2( 0 , maxValueSize.y + 2 ) ); const ImRect bbAll( cPos , bbValue.Max ); auto& style( GetStyle( ) ); auto id( win->GetID( label ) ); ItemSize( bbAll , style.FramePadding.y ); if ( !ItemAdd( bbAll , id ) ) { return false; } const bool tabFocus{ FocusableItemRegister( win , id ) }; const bool hovered{ ItemHoverable( bbBar , id ) }; auto* const ctx( GetCurrentContext( ) ); if ( tabFocus || ( hovered && ctx->IO.MouseClicked[ 0 ] ) ) { SetActiveID( id , win ); FocusWindow( win ); } float nValue{ *value }; const bool active{ ctx->ActiveId == id }; if ( active ) { if ( ctx->IO.MouseDown[ 0 ] ) { const float mPos{ ctx->IO.MousePos.y }; const float clickPos{ 1.0f - ImClamp( ( mPos - bbBar.Min.y - 1 ) / ( BarHeight - 2 ) , 0.0f , 1.0f ) }; nValue = base + unit * 2.f * clickPos; } else { ClearActiveID( ); } } else if ( hovered && ctx->IO.KeyCtrl && ctx->IO.MouseWheel != 0.f ) { nValue += unit * .01f * ctx->IO.MouseWheel; ctx->IO.MouseWheel = 0.f; } //- DRAW --------------------------------------------------------------- auto* const dl( GetWindowDrawList( ) ); const auto dispColor{ GetColorU32( ImVec4( color.x * ( ( hovered || active ) ? 1.f : .5f ) , color.y * ( ( hovered || active ) ? 1.f : .5f ) , color.z * ( ( hovered || active ) ? 1.f : .5f ) , 1 ) ) }; // Draw bar body const ImU32 bgCol{ GetColorU32( ( ctx->ActiveId == id || hovered ) ? ImVec4( .25f , .25f , .25f , 1.f ) : ImVec4( .1f , .1f , .1f , 1.f ) ) }; const ImU32 fCol{ GetColorU32( ( ctx->ActiveId == id || hovered ) ? ImVec4( 1.f , 1.f , 1.f , 1.f ) : ImVec4( 0.f , 0.f , 0.f , 1.f ) ) }; dl->AddRectFilled( bbBar.Min , bbBar.Max , bgCol ); dl->AddRect( bbBar.Min , bbBar.Max , fCol ); // Draw colored area on bar const float val( std::max( base , std::min( unit * 2 , nValue ) ) ); const float vy2( ( BarHeight - 2 ) * ( 1 - val / ( unit * 2 ) ) ); dl->AddRectFilled( bbBar.Min + ImVec2( 1 , BarHeight * .5 ) , bbBar.Min + ImVec2( BarWidth - 1 , 1 + vy2 ) , dispColor ); dl->AddLine( bbBar.Min + ImVec2( 1 , BarHeight * .5 ) , bbBar.Min + ImVec2( BarWidth - 1 , BarHeight * .5 ) , dispColor ); // Draw label & value const char* tStart = &ctx->TempBuffer[ 0 ]; const char* tEnd = tStart + ImFormatString( ctx->TempBuffer, IM_ARRAYSIZE( ctx->TempBuffer ), "%.2f" , *value ); PushStyleColor( ImGuiCol_Text , dispColor ); RenderTextClipped( bbLabel.Min , bbLabel.Max , label , nullptr , nullptr , ImVec2( .5f , .5f ) ); RenderTextClipped( bbValue.Min , bbValue.Max , tStart , tEnd , nullptr , ImVec2( .5f , .5f ) ); PopStyleColor( ); if ( nValue != *value ) { *value = val; return true; } return false; } bool ColorGradingControls( char const* const name , float* const red , float* const green , float* const blue , const float base = 0.f , const float unit = 1.f ) noexcept { using namespace ImGui; assert( red && green && blue ); assert( unit > 0.f && "invalid unit" ); PushID( name ); BeginGroup( ); ImGuiWindow* const window{ GetCurrentWindow() }; ImGuiStorage* const storage{ window->DC.StateStorage }; const bool wheelMode{ storage->GetBool( window->GetID( name ) ) }; // Mode selection bool modeChanged{ false }; modeChanged = CGCModeButton_( "Components" , !wheelMode ); SameLine( ); modeChanged = CGCModeButton_( "Color wheel" , wheelMode ) || modeChanged; if ( modeChanged ) { storage->SetBool( window->GetID( name ) , !wheelMode ); } bool changed; if ( wheelMode ^ modeChanged ) { changed = false; #warning implement the fuck } else { PushItemWidth( -1 ); PushMultiItemsWidths( 3 ); changed = CGCComponentBar_( red , base , unit , ImVec4( 1 , 0 , 0 , 0 ) , "R" ); PopItemWidth( ); SameLine( 0 , GetStyle( ).ItemInnerSpacing.x ); changed = CGCComponentBar_( green , base , unit , ImVec4( 0 , 1 , 0 , 0 ) , "G" ) || changed; PopItemWidth( ); SameLine( 0 , GetStyle( ).ItemInnerSpacing.x ); changed = CGCComponentBar_( blue , base , unit , ImVec4( .3 , .3 , 1 , 0 ) , "B" ) || changed; PopItemWidth( ); PopItemWidth( ); } EndGroup( ); PopID( ); return changed; } void T_Main::makeUI( ) { using namespace ImGui; if ( BeginMainMenuBar( ) ) { if ( BeginMenu( "File" ) ) { if ( MenuItem( "Quit" ) ) { done = true; } EndMenu( ); } if ( BeginMenu( "Views" ) ) { MenuItemCheckbox( "Input overrides" , &Globals::Sync( ).overridesWindowEnabled( ) ); MenuItemCheckbox( "Output debugger" , &Globals::ODbg( ).uiEnabled( ) ); MenuItemCheckbox( "Profiler" , &Globals::Profiler( ).uiEnabled( ) ); MenuItemCheckbox( "Sequencer" , &Globals::Sync( ).sequencerWindowEnabled( ) ); MenuItemCheckbox( "Shaders" , &Globals::Shaders( ).uiEnabled( ) ); EndMenu( ); } EndMainMenuBar( ); } Globals::Profiler( ).makeUI( ); Globals::ODbg( ).makeUI( ); Globals::Shaders( ).makeUI( ); Globals::Sync( ).makeOverridesWindow( ); Globals::Sync( ).makeSequencerWindow( ); #warning color grading widget test static float cgRed = 1 , cgGreen = 1 , cgBlue = 1; static float wtf[ 3 ] = { 0 , 0 , 0 }; auto const& dspSize( GetIO( ).DisplaySize ); SetNextWindowSize( ImVec2( 300 , 300 ) , ImGuiSetCond_Appearing ); SetNextWindowPos( ImVec2( ( dspSize.x - 300 ) / 2 , (dspSize.y - 300)/2 ) , ImGuiSetCond_Appearing ); Begin( "Test!" , nullptr , ImGuiWindowFlags_NoCollapse ); ColorEdit3( "yo" , wtf ); ColorGradingControls( "lolwut" , &cgRed , &cgGreen , &cgBlue ); End( ); } 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 ); } 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; }