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
This commit is contained in:
Emmanuel BENOîT 2017-11-19 10:21:08 +01:00
parent f16ff2ec2e
commit 2c97f3a52e
11 changed files with 167 additions and 169 deletions

10
demo.cc
View file

@ -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 {

View file

@ -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 );
};

View file

@ -444,6 +444,8 @@
)
)
)
# FIXME: overrides for vignette
# FIXME: overrides for color grading
)
)

49
main.cc
View file

@ -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;
}
ImGui::SameLine( );
if ( ImGui::Button( demo->playing ? "Stop" : "Play" ) ) {
demo->playing = !demo->playing;
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( );
}
ImGui::End( );
Globals::Profiler( ).makeUI( );
Globals::ODbg( ).makeUI( );
Globals::Shaders( ).makeUI( );
if ( lol ) {
Globals::Sync( ).makeOverridesWindow( );
}
Globals::Sync( ).makeSequencerWindow( );
}
void T_Main::render( )

22
odbg.cc
View file

@ -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(

View file

@ -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 );

View file

@ -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( );
}

142
sync.cc
View file

@ -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;
if ( !ovWindow_ ) {
return;
}
displayOvSections( s->subsections );
if ( s->subsections.size( ) && s->overrides.size( ) ) {
ImGui::Separator( );
}
displayOvControls( s->overrides );
if ( !topLevel ) {
ImGui::TreePop( );
}
}
}
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( );
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 );
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;
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( );
}
#endif

20
sync.hh
View file

@ -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
};

View file

@ -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;
}

View file

@ -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