From 2c97f3a52e3333e27d7b188fcf341132fcdb597c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sun, 19 Nov 2017 10:21:08 +0100 Subject: [PATCH] UI overhaul * Use menus instead of a silly window with checkboxes * Windows can be closed, cannot be collapsed * Left side windows have more vertical space * Specific window for the sequencer --- demo.cc | 10 +--- demo.hh | 5 -- demo.srd | 2 + main.cc | 51 ++++++++---------- odbg.cc | 22 ++++---- profiling.cc | 6 +-- shaders.cc | 49 +++++++++-------- sync.cc | 148 +++++++++++++++++++++------------------------------ sync.hh | 20 ++++++- utilities.cc | 13 +++++ utilities.hh | 10 ++++ 11 files changed, 167 insertions(+), 169 deletions(-) diff --git a/demo.cc b/demo.cc index c872920..4b0c0dd 100644 --- a/demo.cc +++ b/demo.cc @@ -28,15 +28,7 @@ void T_Demo::render( ) } auto& sync( Globals::Sync( ) ); - if ( playing ) { - const float time = SDL_GetTicks( ) * 1e-3; - if ( playingPrevious ) { - sync.timeDelta( time - lastFrame ); - playing = !sync.finished( ); - } - lastFrame = time; - } - playingPrevious = playing; + sync.updateTime( ); if ( context && !context->aborted ) { try { diff --git a/demo.hh b/demo.hh index f7292b7..c9c8bd2 100644 --- a/demo.hh +++ b/demo.hh @@ -32,8 +32,6 @@ struct T_Demo // --------------------------------------------------------------------- - bool playing = false; - private: uint32_t width; uint32_t height; @@ -41,8 +39,5 @@ struct T_Demo T_OwnPtr< ops::T_OpProgram > program; T_OwnPtr< ops::T_OpContext > context; - bool playingPrevious = false; - float lastFrame; - bool runInit( ops::T_OpProgram& program ); }; diff --git a/demo.srd b/demo.srd index cbca145..875bd30 100644 --- a/demo.srd +++ b/demo.srd @@ -444,6 +444,8 @@ ) ) ) + # FIXME: overrides for vignette + # FIXME: overrides for color grading ) ) diff --git a/main.cc b/main.cc index df33fb5..b30a724 100644 --- a/main.cc +++ b/main.cc @@ -178,42 +178,35 @@ void T_Main::handleCapture( ) void T_Main::makeUI( ) { - ImGui::SetNextWindowSize( ImVec2( 300 , 150 ) , - ImGuiSetCond_Once ); - ImGui::SetNextWindowPos( ImVec2( ) , ImGuiSetCond_Once ); - ImGui::Begin( "Tools" ); - - ImGui::Checkbox( "Output debugger" , &Globals::ODbg( ).uiEnabled( ) ); - ImGui::Checkbox( "Profiler" , &Globals::Profiler( ).uiEnabled( ) ); - ImGui::Checkbox( "Shaders" , &Globals::Shaders( ).uiEnabled( ) ); - -#warning big fucking FIXME - static bool lol{ false }; - ImGui::Checkbox( "Input overrides" , &lol ); - - 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( ); + using namespace ImGui; + if ( BeginMainMenuBar( ) ) { + if ( BeginMenu( "File" ) ) { + if ( MenuItem( "Quit" ) ) { + done = true; + } + EndMenu( ); } - ImGui::SameLine( ); - if ( ImGui::Button( demo->playing ? "Stop" : "Play" ) ) { - demo->playing = !demo->playing; + 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( ); } - ImGui::End( ); - Globals::Profiler( ).makeUI( ); Globals::ODbg( ).makeUI( ); Globals::Shaders( ).makeUI( ); - if ( lol ) { - Globals::Sync( ).makeOverridesWindow( ); - } + Globals::Sync( ).makeOverridesWindow( ); + Globals::Sync( ).makeSequencerWindow( ); } void T_Main::render( ) diff --git a/odbg.cc b/odbg.cc index 99e16b0..abd4586 100644 --- a/odbg.cc +++ b/odbg.cc @@ -41,12 +41,12 @@ void T_OutputDebugger::makeUI( ) if ( !enabled_ ) { return; } - auto const& dspSize( ImGui::GetIO( ).DisplaySize ); - ImGui::SetNextWindowSize( ImVec2( 300 , dspSize.y - 300 ) , - ImGuiSetCond_Once ); - ImGui::SetNextWindowPos( ImVec2( 0 , 150 ) , - ImGuiSetCond_Once ); - ImGui::Begin( "Output debugger" ); + + using namespace ImGui; + auto const& dspSize( GetIO( ).DisplaySize ); + SetNextWindowSize( ImVec2( 300 , dspSize.y - 170 ) , ImGuiSetCond_Appearing ); + SetNextWindowPos( ImVec2( 0 , 20 ) , ImGuiSetCond_Appearing ); + Begin( "Output debugger" , &enabled_ , ImGuiWindowFlags_NoCollapse ); // Main selector if ( selectorItems_ == nullptr ) { @@ -60,11 +60,11 @@ void T_OutputDebugger::makeUI( ) } } assert( csi != -1 ); - if ( ImGui::Combo( "Output" , &csi , selectorItems_ ) ) { + if ( Combo( "Output" , &csi , selectorItems_ ) ) { selected_ = selectorMapping_[ csi ]; } if ( selected_ == -1 ) { - ImGui::End( ); + End( ); return; } @@ -77,13 +77,13 @@ void T_OutputDebugger::makeUI( ) ptr += 1 + snprintf( ptr , sizeof( lodCombo ) - ( ptr - lodCombo ) , "%d" , i ); } *ptr = 0; - ImGui::Combo( "Level" , &t.lod , lodCombo ); + Combo( "Level" , &t.lod , lodCombo ); } // Submode selector - ImGui::Combo( "Display" , &t.submode , smCombo_[ int( t.mode ) ] ); + Combo( "Display" , &t.submode , smCombo_[ int( t.mode ) ] ); - ImGui::End( ); + End( ); } void T_OutputDebugger::registerTexture( diff --git a/profiling.cc b/profiling.cc index d59add4..8d51f2f 100644 --- a/profiling.cc +++ b/profiling.cc @@ -119,10 +119,10 @@ void T_Profiler::makeUI( ) auto const& dspSize( ImGui::GetIO( ).DisplaySize ); ImGui::SetNextWindowSize( ImVec2( dspSize.x , 150 ) , - ImGuiSetCond_Once ); + ImGuiSetCond_Appearing ); ImGui::SetNextWindowPos( ImVec2( 0 , dspSize.y - 150 ) , - ImGuiSetCond_Once ); - ImGui::Begin( "Profiler" ); + ImGuiSetCond_Appearing ); + ImGui::Begin( "Profiler" , &uiEnabled_ , ImGuiWindowFlags_NoCollapse ); ImGui::BeginChild( "left" , ImVec2( 180 , 0 ) , true ); float angle( 0 ); diff --git a/shaders.cc b/shaders.cc index dc34aa7..8df3529 100644 --- a/shaders.cc +++ b/shaders.cc @@ -1111,12 +1111,11 @@ void T_ShaderManager::makeUI( ) return; } - auto const& dspSize( ImGui::GetIO( ).DisplaySize ); - ImGui::SetNextWindowSize( ImVec2( dspSize.x , 150 ) , - ImGuiSetCond_Once ); - ImGui::SetNextWindowPos( ImVec2( 0 , dspSize.y - 150 ) , - ImGuiSetCond_Once ); - ImGui::Begin( "Shaders" ); + using namespace ImGui; + auto const& dspSize( GetIO( ).DisplaySize ); + SetNextWindowSize( ImVec2( dspSize.x , 150 ) , ImGuiSetCond_Appearing ); + SetNextWindowPos( ImVec2( 0 , dspSize.y - 150 ) , ImGuiSetCond_Appearing ); + Begin( "Shaders" , &uiEnabled_ , ImGuiWindowFlags_NoCollapse ); const auto n( std::count_if( programs_.begin( ) , programs_.end( ) , []( auto const& p ) { @@ -1149,40 +1148,40 @@ void T_ShaderManager::makeUI( ) const auto nErrors( program.code.errors.size( ) ); const bool open( nErrors - ? ImGui::TreeNodeEx( &program , ImGuiTreeNodeFlags_OpenOnArrow + ? TreeNodeEx( &program , ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick , "%s" , program.name.toOSString( ).data( ) ) : false ); if ( !nErrors ) { - ImGui::Text( "%s" , program.name.toOSString( ).data( ) ); + Text( "%s" , program.name.toOSString( ).data( ) ); } - ImGui::SameLine( 400 ); - ImGui::Text( "Usage: %u" , program.plReferences.size( ) + program.saReferences ); - ImGui::SameLine( 550 ); + SameLine( 400 ); + Text( "Usage: %u" , program.plReferences.size( ) + program.saReferences ); + SameLine( 550 ); if ( program.code.errors.empty( ) ) { - ImGui::PushStyleColor( ImGuiCol_Text , ImVec4( .6 , 1 , .6 , 1 ) ); - ImGui::Text( "No errors" ); + PushStyleColor( ImGuiCol_Text , ImVec4( .6 , 1 , .6 , 1 ) ); + Text( "No errors" ); } else { - ImGui::PushStyleColor( ImGuiCol_Text , ImVec4( 1 , .6 , .6 , 1 ) ); - ImGui::Text( "%u error%s" , nErrors , nErrors > 1 ? "s" : "" ); + PushStyleColor( ImGuiCol_Text , ImVec4( 1 , .6 , .6 , 1 ) ); + Text( "%u error%s" , nErrors , nErrors > 1 ? "s" : "" ); } - ImGui::PopStyleColor( ); + PopStyleColor( ); if ( open ) { for ( auto const& err : program.code.errors ) { - ImGui::NewLine( ); - ImGui::SameLine( 50 ); - ImGui::Text( "%s" , err.source.toOSString( ).data( ) ); - ImGui::SameLine( 250 ); - ImGui::Text( "line %d" , err.line ); - ImGui::SameLine( 370 ); - ImGui::Text( "%s" , err.error.toOSString( ).data( ) ); + NewLine( ); + SameLine( 50 ); + Text( "%s" , err.source.toOSString( ).data( ) ); + SameLine( 250 ); + Text( "line %d" , err.line ); + SameLine( 370 ); + Text( "%s" , err.error.toOSString( ).data( ) ); } - ImGui::TreePop( ); + TreePop( ); } } - ImGui::End( ); + End( ); } diff --git a/sync.cc b/sync.cc index 2f7d2f1..85abb2f 100644 --- a/sync.cc +++ b/sync.cc @@ -540,6 +540,19 @@ void T_SyncManager::setTime( updateValues( ); } +void T_SyncManager::updateTime( ) noexcept +{ + if ( playing_ ) { + const float time( SDL_GetTicks( ) * 1e-3 ); + if ( playingPrevious_ ) { + timeDelta( time - lastFrame_ ); + playing_ = !finished( ); + } + lastFrame_ = time; + } + playingPrevious_ = playing_; +} + /*----------------------------------------------------------------------------*/ void T_SyncManager::checkCurveFile( ) @@ -674,28 +687,6 @@ void T_SyncManager::mergeOverrides( ); } -void T_SyncManager::makeOverridesWindow( ) -{ - auto const& dspSize( ImGui::GetIO( ).DisplaySize ); - ImGui::SetNextWindowSize( ImVec2( 300 , dspSize.y - 300 ) , - ImGuiSetCond_Once ); - ImGui::SetNextWindowPos( ImVec2( 0 , 150 ) , - ImGuiSetCond_Once ); - ImGui::Begin( "Input overrides" ); - - if ( soRoot_.subsections.empty( ) ) { - ImGui::Text( "No overrides have been defined." ); - } else { - T_StringBuilder temp; - uint32_t counter{ 0 }; - for ( auto& section : soRoot_.subsections ) { - section->makeUI( counter , temp , true ); - } - } - - ImGui::End( ); -} - void T_SyncManager::setOverridesActive( const bool active , const uint32_t n , @@ -716,76 +707,61 @@ void T_SyncManager::setOverridesActive( } } -#if 0 -void T_SyncManager::makeUI( ) -{ - auto const& dspSize( ImGui::GetIO( ).DisplaySize ); +/*------------------------------------------------------------------------------*/ - if ( wOverrides ) { - ImGui::SetNextWindowSize( ImVec2( 300 , dspSize.y - 300 ) , - ImGuiSetCond_Once ); - ImGui::SetNextWindowPos( ImVec2( 0 , 150 ) , - ImGuiSetCond_Once ); - ImGui::Begin( "Input overrides" ); - displayOvSections( uiRoot , true ); - ImGui::End( ); +void T_SyncManager::makeSequencerWindow( ) +{ + if ( !tmWindow_ ) { + return; } - if ( wCurves ) { - ImGui::SetNextWindowSize( ImVec2( dspSize.x , 150 ) , - ImGuiSetCond_Once ); - ImGui::SetNextWindowPos( ImVec2( 0 , dspSize.y - 150 ) , - ImGuiSetCond_Once ); - ImGui::Begin( "Curve editor" ); - // XXX contents - ImGui::End( ); + + using namespace ImGui; + auto const& dspSize( GetIO( ).DisplaySize ); + SetNextWindowSize( ImVec2( dspSize.x , 150 ) , ImGuiSetCond_Appearing ); + SetNextWindowPos( ImVec2( 0 , dspSize.y - 150 ) , ImGuiSetCond_Appearing ); + Begin( "Sequencer" , &tmWindow_ , ImGuiWindowFlags_NoCollapse ); + + PushID( "playing" ); + if ( Button( playing_ ? "Stop" : "Play" ) ) { + playing_ = !playing_; } + PopID( ); + + const float d( duration( ) ); + float tm( time( ) ); + SameLine( ); + PushID( "sequencer" ); + PushItemWidth( -1 ); + if ( SliderFloat( "" , &tm , 0 , d , "%.1fs" ) ) { + setTime( tm ); + playing_ = playing_ && !finished( ); + } + PopItemWidth( ); + PopID( ); + End( ); } -void T_SyncManager::displayOvSections( - T_SyncUISections& sections , - const bool topLevel ) +void T_SyncManager::makeOverridesWindow( ) { - for ( auto& s : sections ) { - const bool display( topLevel - ? ImGui::CollapsingHeader( s->title.c_str( ) ) - : ImGui::TreeNode( s->title.c_str( ) ) ); - if ( !display ) { - continue; - } - displayOvSections( s->subsections ); - if ( s->subsections.size( ) && s->overrides.size( ) ) { - ImGui::Separator( ); - } - displayOvControls( s->overrides ); - if ( !topLevel ) { - ImGui::TreePop( ); + if ( !ovWindow_ ) { + return; + } + + using namespace ImGui; + auto const& dspSize( GetIO( ).DisplaySize ); + SetNextWindowSize( ImVec2( 300 , dspSize.y - 170 ) , ImGuiSetCond_Appearing ); + SetNextWindowPos( ImVec2( 0 , 20 ) , ImGuiSetCond_Appearing ); + Begin( "Input overrides" , &ovWindow_ , + ImGuiWindowFlags_NoCollapse ); + + if ( soRoot_.subsections.empty( ) ) { + Text( "No overrides have been defined." ); + } else { + T_StringBuilder temp; + uint32_t counter{ 0 }; + for ( auto& section : soRoot_.subsections ) { + section->makeUI( counter , temp , true ); } } + End( ); } - -void T_SyncManager::displayOvControls( - T_SyncUIOverrides& overrides ) -{ - for ( auto& o : overrides ) { - // XXX enable override checkbox should be selected and disabled - // if there is no curve - const bool changed( ImGui::Checkbox( "" , &o->enabled ) ); - if ( changed ) { - // XXX mark the inputs as coming from the UI / the curves - } - ImGui::SameLine( ); - - switch ( o->type ) { - case T_SyncUIOverride::FLOAT: - case T_SyncUIOverride::VEC2: - case T_SyncUIOverride::VEC3: - case T_SyncUIOverride::VEC4: - case T_SyncUIOverride::INT: - case T_SyncUIOverride::COLOR: - case T_SyncUIOverride::COLOR_GRADING: - case T_SyncUIOverride::CAMERA: - break; - } - } -} -#endif diff --git a/sync.hh b/sync.hh index a3216ce..b509fbf 100644 --- a/sync.hh +++ b/sync.hh @@ -291,8 +291,11 @@ struct T_SyncManager float time( ) const noexcept { return time_.time; } + bool playing( ) const noexcept + { return playing_; } bool finished( ) const noexcept { return time_.time >= time_.duration( ); } + void updateTime( ) noexcept; // --------------------------------------------------------------------- // Value access @@ -327,7 +330,6 @@ struct T_SyncManager public: void clearOverrides( ) noexcept; void mergeOverrides( T_SyncOverrideSection& overrides ); - void makeOverridesWindow( ); // Mark a bunch of inputs as overridden / not overridden void setOverridesActive( bool active , @@ -340,12 +342,28 @@ struct T_SyncManager void updateCurveCaches( ); void updateValues( ); + // --------------------------------------------------------------------- + // User interface + + bool& sequencerWindowEnabled( ) noexcept + { return tmWindow_; } + void makeSequencerWindow( ); + + bool& overridesWindowEnabled( ) noexcept + { return ovWindow_; } + void makeOverridesWindow( ); + private: ebcl::T_SRDParserConfig pConfig_; // Parser config for curves P_WatchedFiles watcher_; // Curves file watcher T_SyncTime time_; // Duration/time information + bool playing_{ false }; // Is it playing? + bool playingPrevious_{ false }; // Was it playing before? + float lastFrame_{ 0 }; // Time of last frame T_SyncValues values_; // Value storage T_SyncCurves curves_; // Curves storage + bool tmWindow_{ false }; // Sequencer window T_Array< P_SyncCurveCache > curveCaches_; // Cache for curve segments + bool ovWindow_{ false }; // Overrides window T_SyncOverrideSection soRoot_; // Root for overrides }; diff --git a/utilities.cc b/utilities.cc index 0461844..b6ec7e4 100644 --- a/utilities.cc +++ b/utilities.cc @@ -69,3 +69,16 @@ T_String GetParentPath( free( rp ); return rv; } + +/*------------------------------------------------------------------------------*/ + +bool ImGui::MenuItemCheckbox( + char const* name , + bool* checked ) +{ + bool rv{ MenuItem( name , "" , *checked , true ) }; + if ( rv ) { + *checked = !*checked; + } + return rv; +} diff --git a/utilities.hh b/utilities.hh index 20cabfe..b5539cf 100644 --- a/utilities.hh +++ b/utilities.hh @@ -76,3 +76,13 @@ std::string GetAbsolutePath( // Get the absolute parent path for a (possibly relative) path std::string GetParentPath( std::string const& path ); + +/*----------------------------------------------------------------------------*/ + +namespace ImGui { + + bool MenuItemCheckbox( + char const* name , + bool* checked ); + +} // namespace ImGui