diff --git a/sync.cc b/sync.cc index 119061a..e0c23a2 100644 --- a/sync.cc +++ b/sync.cc @@ -381,13 +381,19 @@ void A_SyncOverride::setup( ) noexcept assert( ni != 0 ); assert( inputPos_.size( ) == 0 ); + T_StringBuilder sb; inputPos_.ensureCapacity( ni ); for ( auto i = 0u ; i < ni ; i ++ ) { // FIXME: insufficient; the manager should be made aware of // the presence of an override for that value (and it should // fail for missing values). inputPos_.add( Globals::Sync( ).inputPos( inputs_[ i ] ) ); + if ( sb.size( ) ) { + sb << ';'; + } + sb << inputs_[ i ]; } + id_ = std::move( sb ); } char const* A_SyncOverride::buildLabel( @@ -676,6 +682,7 @@ void T_SyncManager::clearOverrides( ) noexcept mouseDelegate_ = nullptr; soRoot_.subsections.clear( ); soRoot_.overrides.clear( ); + soTable_.clear( ); } void T_SyncManager::mergeOverrides( @@ -684,14 +691,14 @@ void T_SyncManager::mergeOverrides( assert( overrides.overrides.empty( ) ); soRoot_.merge( overrides ); - T_SyncOverrideVisitor v; - v.visitor.visit( &soRoot_ , - []( T_SyncOverrideVisitor::T_Element node , bool exit ) -> bool { + soVisitor_.visitor.visit( &soRoot_ , + [this]( T_SyncOverrideVisitor::T_Element node , bool exit ) -> bool { if ( exit || node.hasType< T_SyncOverrideSection* >( ) ) { return true; } auto& ovr( *node.value< A_SyncOverride* >( ) ); ovr.setup( ); + soTable_.add( ovr.id( ) , &ovr ); return false; } ); @@ -717,6 +724,12 @@ void T_SyncManager::setOverridesActive( } } +void T_SyncManager::visitOverrides( + T_SyncOverrideVisitor::F_NodeAction visitor ) +{ + soVisitor_.visitor.visit( &soRoot_ , visitor ); +} + /*------------------------------------------------------------------------------*/ void T_SyncManager::makeOverridesWindow( ) diff --git a/sync.hh b/sync.hh index 12e80b0..0bf4b0e 100644 --- a/sync.hh +++ b/sync.hh @@ -173,6 +173,7 @@ class A_SyncOverride const T_String type_; bool enabled_{ false }; ebcl::T_SRDLocation location_; + T_String id_; protected: ebcl::T_Buffer< char > title_; @@ -208,6 +209,11 @@ class A_SyncOverride bool enabled( ) const noexcept { return enabled_; } + T_String const& id( ) const noexcept + { return id_; } + char const* title( ) const noexcept + { return &title_[ 0 ]; } + ebcl::T_SRDLocation& location( ) noexcept { return location_; } ebcl::T_SRDLocation const& location( ) const noexcept @@ -265,10 +271,12 @@ struct T_SyncOverrideVisitor T_SyncOverrideSection* , A_SyncOverride* >; using T_OpElement = T_Optional< T_Element >; + using T_Visitor = ebcl::T_Visitor< T_Element , T_Element >; + using F_NodeAction = T_Visitor::F_NodeAction; static T_OpElement nodeBrowser( T_Element element , uint32_t child ); - ebcl::T_Visitor< T_Element , T_Element > visitor{ nodeBrowser }; + T_Visitor visitor{ nodeBrowser }; }; /*============================================================================*/ @@ -352,6 +360,9 @@ struct T_SyncManager : public virtual A_MouseCtrl uint32_t n , uint32_t const* pos ); + // Visit the overrides tree + void visitOverrides( T_SyncOverrideVisitor::F_NodeAction visitor ); + // --------------------------------------------------------------------- // Update @@ -389,14 +400,21 @@ struct T_SyncManager : public virtual A_MouseCtrl 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 T_Array< P_SyncCurveCache > curveCaches_; // Cache for curve segments + bool ovWindow_{ false }; // Overrides window T_SyncOverrideSection soRoot_; // Root for overrides + T_SyncOverrideVisitor soVisitor_; + T_KeyValueTable< T_String , A_SyncOverride* > soTable_; + // Table of sync overrides, by ID + A_MouseCtrl* mouseDelegate_{ nullptr }; // Delegate for mouse actions }; diff --git a/syncview.cc b/syncview.cc index c6c5d9f..9aae7dc 100644 --- a/syncview.cc +++ b/syncview.cc @@ -60,6 +60,7 @@ struct T_SyncViewImpl_ void displayCurveSelectorWindow( ) noexcept; void displayCurveSelector( ) noexcept; + void displayOverrideSelector( ) noexcept; // Misc stuff T_StringBuilder stringBuffer; // XXX damn this shit to fucking hell @@ -86,7 +87,8 @@ struct T_SyncViewImpl_ SW_OVERRIDE_SELECTOR , }; E_SubWindow sub{ SW_NONE }; - T_KeyValueTable< T_String , bool > curves; + T_KeyValueTable< T_String , bool > sCurves; + T_Set< T_String > sOverrides; T_String curveFinder; }; @@ -463,6 +465,7 @@ void T_SyncViewImpl_::displayCurveSelectorWindow( ) noexcept displayCurveSelector( ); break; case SW_OVERRIDE_SELECTOR: + displayOverrideSelector( ); break; default: fprintf( stderr , "unexpected bullshit in sync view\n" ); @@ -505,8 +508,8 @@ void T_SyncViewImpl_::displayCurveSelector( ) noexcept // The list ImGui::BeginChild( "content" ); for ( auto const& n : names ) { - const bool present{ curves.contains( n ) }; - const bool overriden{ present && *curves.get( n ) }; + const bool present{ sCurves.contains( n ) }; + const bool overriden{ present && *sCurves.get( n ) }; if ( overriden ) { PushItemFlag( ImGuiItemFlags_Disabled , true ); @@ -518,9 +521,9 @@ void T_SyncViewImpl_::displayCurveSelector( ) noexcept stringBuffer.clear( ) << n << '\0'; if ( Checkbox( stringBuffer.data( ) , &select ) ) { if ( select ) { - curves.add( n , false ); + sCurves.add( n , false ); } else { - curves.remove( n ); + sCurves.remove( n ); } } @@ -529,7 +532,69 @@ void T_SyncViewImpl_::displayCurveSelector( ) noexcept PopStyleVar( ); } } - ImGui::EndChild( ); + EndChild( ); +} + +void T_SyncViewImpl_::displayOverrideSelector( ) noexcept +{ + using namespace ImGui; + + BeginChild( "content" ); + Globals::Sync( ).visitOverrides( [&]( T_SyncOverrideVisitor::T_Element element , const bool exit ) { + if ( element.hasType< T_SyncOverrideSection* >( ) ) { + auto const& sos{ *element.value< T_SyncOverrideSection* >( ) }; + if ( sos.title == "*root*" ) { + return true; + } + if ( exit ) { + TreePop( ); + } else { + return TreeNodeEx( &sos.cTitle[ 0 ] , + ImGuiTreeNodeFlags_DefaultOpen ); + } + } else if ( exit ) { + auto const& ov{ *element.value< A_SyncOverride* >( ) }; + auto const& id{ ov.id( ) }; + auto const& in{ ov.inputNames( ) }; + const bool present{ sOverrides.contains( id ) }; + const bool hasCurves{ !present && [&](){ + for ( auto i = 0u ; i < in.size( ) ; i ++ ) { + if ( sCurves.contains( in[ i ] ) ) { + return true; + } + } + return false; + }() }; + + if ( hasCurves ) { + PushItemFlag( ImGuiItemFlags_Disabled , true ); + PushStyleVar( ImGuiStyleVar_Alpha , + GetStyle( ).Alpha * .5f ); + } + + bool select{ present }; + if ( Checkbox( ov.title( ) , &select ) ) { + if ( select ) { + sOverrides.add( id ); + for ( auto i = 0u ; i < in.size( ) ; i ++ ) { + sCurves.add( in[ i ] , true ); + } + } else { + sOverrides.remove( id ); + for ( auto i = 0u ; i < in.size( ) ; i ++ ) { + sCurves.remove( in[ i ] ); + } + } + } + + if ( hasCurves ) { + PopItemFlag( ); + PopStyleVar( ); + } + } + return true; + } ); + EndChild( ); }