diff --git a/ui-overrides.cc b/ui-overrides.cc index 2f587af..24fc29b 100644 --- a/ui-overrides.cc +++ b/ui-overrides.cc @@ -35,11 +35,15 @@ M_DECL_SOVUI( Float ) using namespace ImGui; auto& ov{ dynamic_cast< T_Float& >( ovp ) }; char const* const label( BuildLabel_( counter , sb ) ); + float v{ data[ 0 ] }; const bool changed( ov.slider( ) - ? SliderFloat( label , &data[ 0 ] , ov.min( ) , ov.max( ) , + ? SliderFloat( label , &v , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) - : DragFloat( label , &data[ 0 ] , ov.step( ) , ov.min( ) , + : DragFloat( label , &v , ov.step( ) , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) ); + if ( changed ) { + data.set( 0 , v ); + } return changed; } @@ -60,7 +64,7 @@ M_DECL_SOVUI( Float2 ) ov.max( ) , ov.decimals( ) , ov.power( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 2 ; i ++ ) { - data[ i ] = v[ i ]; + data.set( i , v[ i ] ); } } return changed; @@ -83,7 +87,7 @@ M_DECL_SOVUI( Float3 ) ov.max( ) , ov.decimals( ) , ov.power( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 3 ; i ++ ) { - data[ i ] = v[ i ]; + data.set( i ,v[ i ]); } } return changed; @@ -106,7 +110,7 @@ M_DECL_SOVUI( Float4 ) ov.max( ) , ov.decimals( ) , ov.power( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 4 ; i ++ ) { - data[ i ] = v[ i ]; + data.set( i ,v[ i ]); } } return changed; @@ -126,7 +130,7 @@ M_DECL_SOVUI( Integer ) ? SliderInt( label , &v , ov.min( ) , ov.max( ) ) : DragInt( label , &v , ov.step( ) , ov.min( ) , ov.max( ) ) ); if ( changed ) { - data[ 0 ] = v; + data.set( 0 ,v); } return changed; } @@ -146,7 +150,7 @@ M_DECL_SOVUI( Integer2 ) : DragInt2( label , v , ov.step( ) , ov.min( ) , ov.max( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 2 ; i ++ ) { - data[ i ] = v[ i ]; + data.set( i ,v[ i ]); } } return changed; @@ -167,7 +171,7 @@ M_DECL_SOVUI( Integer3 ) : DragInt3( label , v , ov.step( ) , ov.min( ) , ov.max( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 3 ; i ++ ) { - data[ i ] = v[ i ]; + data.set( i ,v[ i ]); } } return changed; @@ -188,7 +192,7 @@ M_DECL_SOVUI( Integer4 ) : DragInt4( label , v , ov.step( ) , ov.min( ) , ov.max( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 4 ; i ++ ) { - data[ i ] = v[ i ]; + data.set( i ,v[ i ]); } } return changed; @@ -214,7 +218,7 @@ M_DECL_SOVUI( ColorGrading ) if ( changed ) { for ( auto i = 0 ; i < 3 ; i ++ ) { - data[ i ] = v[ i ]; + data.set( i ,v[ i ]); } } return changed; @@ -237,9 +241,9 @@ void InputsFromVector_( A_SyncData& data , glm::vec3 const& v ) noexcept { - data[ vc.x ] = v.x; - data[ vc.y ] = v.y; - data[ vc.z ] = v.z; + data.set( vc.x ,v.x); + data.set( vc.y ,v.y); + data.set( vc.z ,v.z); } /*------------------------------------------------------------------------------*/ @@ -285,7 +289,7 @@ void T_MouseCam_::handleDragAndDrop( InputsFromVector_( ov.target( ) , *data , cam.lookAt( ) ); if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { InputsFromVector_( ov.angles( ) , *data , cam.angles( ) ); - (*data)[ ov.distance( ) ] = cam.distance( ); + data->set( ov.distance( ) ,cam.distance( )); } else { InputsFromVector_( ov.position( ) , *data , cam.position( ) ); InputsFromVector_( ov.up( ) , *data , cam.upVector( ) ); @@ -308,15 +312,15 @@ void T_MouseCam_::handleWheel( if ( modifiers & E_KbdMod::SHIFT ) { auto const& fc( ov.fovConfig( ) ); if ( fc.mode == T_CamOverride::FM_FOV ) { - (*data)[ fc.inputIndex ] = cam.fieldOfView( ); + data->set( fc.inputIndex ,cam.fieldOfView( )); } else { - (*data)[ fc.inputIndex ] = cam.nearPlane( ); + data->set( fc.inputIndex ,cam.nearPlane( )); } } else { InputsFromVector_( ov.target( ) , *data , cam.lookAt( ) ); if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { InputsFromVector_( ov.angles( ) , *data , cam.angles( ) ); - (*data)[ ov.distance( ) ] = cam.distance( ); + data->set( ov.distance( ) ,cam.distance( )); } else { InputsFromVector_( ov.position( ) , *data , cam.position( ) ); InputsFromVector_( ov.up( ) , *data , cam.upVector( ) ); @@ -383,16 +387,16 @@ M_DECL_SOVUI( Camera ) // Update values if ( changes & E_CameraChange::FOV ) { if ( fc.mode == T_CamOverride::FM_FOV ) { - data[ fc.inputIndex ] = camera.fieldOfView( ); + data.set( fc.inputIndex ,camera.fieldOfView( )); } else { - data[ fc.inputIndex ] = camera.nearPlane( ); + data.set( fc.inputIndex ,camera.nearPlane( )); } } if ( changes & E_CameraChange::MATRIX ) { InputsFromVector_( ov.target( ) , data , camera.lookAt( ) ); if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { InputsFromVector_( ov.angles( ) , data , camera.angles( ) ); - data[ ov.distance( ) ] = camera.distance( ); + data.set( ov.distance( ) ,camera.distance( )); } else { InputsFromVector_( ov.position( ) , data , camera.position( ) ); InputsFromVector_( ov.up( ) , data , camera.upVector( ) ); diff --git a/ui-overrides.hh b/ui-overrides.hh index 1d0edbc..68b9fc0 100644 --- a/ui-overrides.hh +++ b/ui-overrides.hh @@ -15,7 +15,8 @@ namespace sov { virtual ~A_SyncData( ) = 0; virtual float operator[]( uint32_t index ) const noexcept = 0; - virtual float& operator[]( uint32_t index ) noexcept = 0; + virtual bool set( uint32_t index , + float value ) noexcept = 0; virtual T_OwnPtr< A_SyncData > clone( ) const noexcept = 0; }; diff --git a/ui-sequencer.cc b/ui-sequencer.cc index 8c7c1e6..6ce193c 100644 --- a/ui-sequencer.cc +++ b/ui-sequencer.cc @@ -6,7 +6,9 @@ #include "ui.hh" #include "ui-app.hh" +#include "ui-overrides.hh" #include "ui-sequencer.hh" +#include "ui-sync.hh" #include "ui-utilities.hh" #include "ui-imgui-sdl.hh" @@ -145,6 +147,114 @@ bool T_ChangeDurationDialog_::onButton( } +/*= T_PointData_ =============================================================*/ + +using T_TempCurveStorage_ = T_AutoArray< T_SyncCurve , 16 >; + +class T_PointData_ : public sov::A_SyncData +{ + private: + T_Optional< T_SyncTrackId > const& selId_; + T_Optional< uint32_t > const& selSegment_; + T_Optional< uint32_t > const& selPoint_; + T_TempCurveStorage_& cOriginals_; + T_TempCurveStorage_& cCopies_; + + T_String useId_; + uint32_t useSegment_; + uint32_t usePoint_; + + A_SyncOverride* ovr_; + + public: + T_PointData_( T_Optional< T_SyncTrackId > const& selId , + T_Optional< uint32_t > const& selSegment , + T_Optional< uint32_t > const& selPoint , + T_TempCurveStorage_& cOriginals , + T_TempCurveStorage_& cCopies ) noexcept + : selId_( selId ) , selSegment_( selSegment ) , + selPoint_( selPoint ) , cOriginals_( cOriginals ) , + cCopies_( cCopies ) + { } + + void use( ) noexcept; + + float operator[]( uint32_t index ) const noexcept override; + bool set( uint32_t index , float value ) noexcept override; + + T_OwnPtr< sov::A_SyncData > clone( ) const noexcept override; +}; + +/*----------------------------------------------------------------------------*/ + +void T_PointData_::use( ) noexcept +{ + assert( selId_ && selSegment_ && selPoint_ ); + assert( selId_->isOverride ); + + useId_ = selId_->id; + useSegment_ = *selSegment_; + usePoint_ = *selPoint_; + ovr_ = Common::Sync( ).getOverride( useId_ ); +} + +float T_PointData_::operator[]( + const uint32_t index ) const noexcept +{ + if ( !( selId_ && selSegment_ && selPoint_ && selId_->isOverride ) + || useId_ != selId_->id || useSegment_ != *selSegment_ + || usePoint_ != *selPoint_ ) { + return 0.f; + } + + auto const& iNames{ ovr_->inputNames( ) }; + if ( cCopies_.size( ) != iNames.size( ) + || cCopies_[ 0 ].name != iNames[ 0 ] ) { + auto const& curve{ *Common::Sync( ).getCurve( iNames[ index ] ) }; + return curve.segments[ useSegment_ ].values[ usePoint_ ]; + } + return cCopies_[ index ].segments[ useSegment_ ].values[ usePoint_ ]; +} + +bool T_PointData_::set( + const uint32_t index , + const float value ) noexcept +{ + if ( !( selId_ && selSegment_ && selPoint_ && selId_->isOverride ) + || useId_ != selId_->id || useSegment_ != *selSegment_ + || usePoint_ != *selPoint_ ) { + return false; + } + + auto const& iNames{ ovr_->inputNames( ) }; + const auto nn{ iNames.size( ) }; + auto& sync{ Common::Sync( ) }; + if ( cCopies_.size( ) != nn || cCopies_[ 0 ].name != iNames[ 0 ] ) { + cOriginals_.clear( ); + cCopies_.clear( ); + for ( auto i = 0u ; i < nn ; i ++ ) { + auto const* const c{ sync.getCurve( iNames[ i ] ) }; + cOriginals_.add( *c ); + cCopies_.add( *c ); + } + } + + cCopies_[ index ].segments[ useSegment_ ].values[ usePoint_ ] = value; + sync.setCurve( cCopies_[ index ] ); + return true; +} + +T_OwnPtr< sov::A_SyncData > T_PointData_::clone( ) const noexcept +{ + auto ptr{ NewOwned< T_PointData_ >( selId_ , selSegment_ , + selPoint_ , cOriginals_ , cCopies_ ) }; + ptr->useId_ = useId_; + ptr->useSegment_ = useSegment_; + ptr->usePoint_ = usePoint_; + return ptr; +} + + /*= T_SyncViewImpl_ ==========================================================*/ struct T_SyncViewImpl_ @@ -322,8 +432,12 @@ struct T_SyncViewImpl_ // Original and copy of curve being modified E_ChangeType selUpdate{ E_ChangeType::NONE }; - T_AutoArray< T_SyncCurve , 16 > selUpdatingOriginals; - T_AutoArray< T_SyncCurve , 16 > selUpdatingCopies; + T_TempCurveStorage_ selUpdatingOriginals; + T_TempCurveStorage_ selUpdatingCopies; + + // Override edition + T_PointData_ selEditor{ selId , selSegment , selPoint , + selUpdatingOriginals , selUpdatingCopies }; // Sub-windows E_SubWindow sub{ SW_NONE }; @@ -1867,7 +1981,7 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept const uint32_t sid{ *selSegment }; const uint32_t pid{ *selPoint }; auto& sync{ Common::Sync( ) }; - auto const* const ovr{ selId->isOverride + auto* const ovr{ selId->isOverride ? sync.getOverride( selId->id ) : nullptr }; auto const* const curve{ selUpdatingCopies.size( ) @@ -1927,26 +2041,33 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept Separator( ); + // This is here because the curve pointer might get fucked over by + // the override control + const auto canInsertBefore{ pid != 0 + && segment.durations[ pid - 1 ] > 1 }; + const auto canInsertAfter{ pid != segment.durations.size( ) + && segment.durations[ pid ] > 1 }; + const auto canDelete{ pid != 0 && pid != segment.durations.size( ) }; + bool changed; - float value{ segment.values[ pid ] }; + float value{ 0 }; if ( ovr ) { - // XXX override control - changed = false; + selEditor.use( ); + uint32_t i{ 0 }; + changed = (UI::Sync( ).uiFor( *ovr ))( + *ovr , selEditor , i , stringBuffer ); } else { Text( "Value:" ); SameLine( 110 ); PushItemWidth( -1 ); + value = segment.values[ pid ]; DragFloat( "##value" , &value , .01f , 0 , 0 , "%.6f" ); changed = IsItemActive( ); PopItemWidth( ); } const bool canUseButtons{ !changed && selUpdate == E_ChangeType::NONE }; - const auto canInsertBefore{ pid != 0 - && segment.durations[ pid - 1 ] > 1 }; - const auto canInsertAfter{ pid != segment.durations.size( ) - && segment.durations[ pid ] > 1 }; - if ( pid != 0 && pid != segment.durations.size( ) ) { + if ( canDelete ) { Separator( ); Text( " " ); SameLine( 110 ); @@ -1976,8 +2097,17 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept } } - if ( changed ) { + if ( ovr && changed ) { if ( selUpdate == E_ChangeType::NONE ) { + selUpdate = E_ChangeType::POINT_VALUE; + } else { + assert( selUpdate == E_ChangeType::POINT_VALUE ); + } + + } else if ( changed ) { + if ( selUpdate == E_ChangeType::NONE ) { + assert( selUpdatingOriginals.empty( ) ); + assert( selUpdatingCopies.empty( ) ); selUpdatingOriginals.add( *curve ); selUpdatingCopies.add( *curve ); selUpdate = E_ChangeType::POINT_VALUE; @@ -1986,10 +2116,15 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept } selUpdatingCopies[ 0 ].segments[ sid ].values[ pid ] = value; sync.setCurve( selUpdatingCopies[ 0 ] ); + } else if ( selUpdate == E_ChangeType::POINT_VALUE ) { selUpdate = E_ChangeType::NONE; - sync.setCurve( selUpdatingOriginals[ 0 ] ); - SyncEditor::ReplaceCurve( std::move( selUpdatingCopies[ 0 ] ) ); + auto& undo{ dynamic_cast< T_UndoSyncChanges& >( + Common::Undo( ).add< T_UndoSyncChanges >( ) ) }; + for ( auto i = 0u ; i < selUpdatingCopies.size( ) ; i ++ ) { + undo.curveReplacement( std::move( selUpdatingOriginals[ i ] ) , + std::move( selUpdatingCopies[ i ] ) ); + } selUpdatingCopies.clear( ); selUpdatingOriginals.clear( ); } diff --git a/ui-sync.cc b/ui-sync.cc index 113035a..a58547a 100644 --- a/ui-sync.cc +++ b/ui-sync.cc @@ -20,7 +20,7 @@ class T_SyncInputData_ : public sov::A_SyncData void setFromOverride( A_SyncOverride const& sov ) noexcept; float operator[]( uint32_t index ) const noexcept override; - float& operator[]( uint32_t index ) noexcept override; + bool set( uint32_t index , float value ) noexcept override; T_OwnPtr< sov::A_SyncData > clone( ) const noexcept override; }; @@ -46,10 +46,12 @@ float T_SyncInputData_::operator[]( return *ptr_[ index ]; } -float& T_SyncInputData_::operator[]( - const uint32_t index ) noexcept +bool T_SyncInputData_::set( + const uint32_t index , + const float value ) noexcept { - return *ptr_[ index ]; + *ptr_[ index ] = value; + return true; } T_OwnPtr< sov::A_SyncData > T_SyncInputData_::clone( ) const noexcept @@ -182,6 +184,7 @@ T_UISync::F_Override T_UISync::uiFor( return rv ? *rv : []( A_SyncOverride& , sov::A_SyncData& , uint32_t& , T_StringBuilder& ) { ImGui::Text( "(missing UI)" ); + return false; }; } diff --git a/ui-sync.hh b/ui-sync.hh index da1dff2..19c6dcb 100644 --- a/ui-sync.hh +++ b/ui-sync.hh @@ -18,7 +18,7 @@ class T_UISync : public A_MouseCtrl void makeOverridesWindow( ); using F_Override = std::function< - void( A_SyncOverride& , sov::A_SyncData& , uint32_t& , + bool( A_SyncOverride& , sov::A_SyncData& , uint32_t& , T_StringBuilder& ) >; F_Override uiFor( A_SyncOverride& target ) const noexcept;