demotool/c-syncedit.cc

367 lines
9.5 KiB
C++

#include "externals.hh"
#include "common.hh"
#include "c-syncedit.hh"
/*= T_UndoSyncChanges ========================================================*/
void T_UndoSyncChanges::undo( ) const noexcept
{
auto& sync{ Common::Sync( ) };
const auto n{ changes_.size( ) };
for ( auto i = 0u ; i < n ; i ++ ) {
auto const& c( changes_[ i ] );
if ( c.before ) {
sync.setCurve( *c.before );
} else {
sync.removeCurve( c.inputId );
}
}
}
void T_UndoSyncChanges::redo( ) const noexcept
{
auto& sync{ Common::Sync( ) };
const auto n{ changes_.size( ) };
for ( auto i = 0u ; i < n ; i ++ ) {
auto const& c( changes_[ i ] );
if ( c.after ) {
sync.setCurve( *c.after );
} else {
sync.removeCurve( c.inputId );
}
}
}
/*----------------------------------------------------------------------------*/
T_UndoSyncChanges& T_UndoSyncChanges::curveCreation(
T_SyncCurve curve ) noexcept
{
#ifndef NDEBUG
{
const auto n{ changes_.size( ) };
for ( auto i = 0u ; i < n ; i ++ ) {
assert( changes_[ i ].inputId != curve.name );
}
}
#endif
changes_.addNew( true , std::move( curve ) );
return *this;
}
T_UndoSyncChanges& T_UndoSyncChanges::curveDeletion(
T_SyncCurve curve ) noexcept
{
#ifndef NDEBUG
{
const auto n{ changes_.size( ) };
for ( auto i = 0u ; i < n ; i ++ ) {
assert( changes_[ i ].inputId != curve.name );
}
}
#endif
changes_.addNew( std::move( curve ) );
return *this;
}
T_UndoSyncChanges& T_UndoSyncChanges::curveReplacement(
T_SyncCurve before ,
T_SyncCurve after ) noexcept
{
assert( before.name == after.name );
#ifndef NDEBUG
{
const auto n{ changes_.size( ) };
for ( auto i = 0u ; i < n ; i ++ ) {
assert( changes_[ i ].inputId != before.name );
}
}
#endif
changes_.addNew( std::move( before ) , std::move( after ) );
return *this;
}
/*= T_UndoDurationChanges ====================================================*/
T_UndoDurationChanges::T_UndoDurationChanges(
const uint32_t units ,
const uint32_t oldUnits ,
const float unitSize ,
const float oldUnitSize ) noexcept
: T_UndoSyncChanges( ) ,
unitsBefore_{ oldUnits } ,
unitsAfter_{ units } ,
uSizeBefore_{ oldUnitSize } ,
uSizeAfter_{ unitSize }
{ }
void T_UndoDurationChanges::undo( ) const noexcept
{
Common::Sync( ).setDuration( uSizeBefore_ , unitsBefore_ );
T_UndoSyncChanges::undo( );
}
void T_UndoDurationChanges::redo( ) const noexcept
{
Common::Sync( ).setDuration( uSizeAfter_ , unitsAfter_ );
T_UndoSyncChanges::redo( );
}
/*= SyncEditor ===============================================================*/
namespace {
T_SyncCurve SESDScaleCurve_(
const float uSizeBefore ,
const float uSizeAfter ,
T_SyncCurve const& curve ) noexcept
{
T_SyncCurve nCurve;
nCurve.name = curve.name;
for ( auto const& segment : curve.segments ) {
const auto nsid{ nCurve.segments.add( segment ) };
T_SyncSegment& nSeg{ nCurve.segments[ nsid ] };
const auto nd{ nSeg.durations.size( ) };
for ( auto i = 0u ; i < nd ; i ++ ) {
const float duration{ nSeg.durations[ i ] * uSizeBefore };
nSeg.durations[ i ] = std::max( 1u , uint32_t( std::roundf(
duration / uSizeAfter ) ) );
#if 0
printf( "initial duration %f (%d units) ; new duration %f (%d units)\n" ,
duration , segment.durations[ i ] ,
uSizeAfter * nSeg.durations[ i ] ,
nSeg.durations[ i ] );
#endif
}
}
return nCurve;
}
} // namespace <anon>
void SyncEditor::SetDuration(
const uint32_t units ,
const float uSize ,
const bool scaleCurves ) noexcept
{
auto& sync{ Common::Sync( ) };
const float oldUnitSize{ sync.durationUnitSize( ) };
const uint32_t oldUnits{ sync.durationUnits( ) };
if ( oldUnits == units && oldUnitSize == uSize ) {
return;
}
auto& undo{ dynamic_cast< T_UndoDurationChanges& >(
Common::Undo( ).add< T_UndoDurationChanges >(
units , oldUnits ,
uSize , oldUnitSize ) ) };
sync.setDuration( uSize , units );
if ( !scaleCurves || uSize == oldUnitSize ) {
return;
}
auto const& curves( sync.curves( ) );
for ( auto const& curve : curves ) {
auto nc{ SESDScaleCurve_( oldUnitSize , uSize , curve ) };
undo.curveReplacement( curve , nc );
sync.setCurve( std::move( nc ) );
}
}
/*----------------------------------------------------------------------------*/
void SyncEditor::ReplaceCurve(
T_SyncCurve replacement ) noexcept
{
auto* const curve{ Common::Sync( ).getCurve( replacement.name ) };
if ( !curve ) {
return;
}
// Create undo entry
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
undo.curveReplacement( *curve , replacement );
Common::Sync( ).setCurve( std::move( replacement ) );
}
/*----------------------------------------------------------------------------*/
void SyncEditor::DeleteCurve(
T_String const& id ) noexcept
{
auto const* const curve{ Common::Sync( ).getCurve( id ) };
if ( !curve ) {
return;
}
// Create undo entry
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
undo.curveDeletion( *curve );
// Delete curve
Common::Sync( ).removeCurve( id );
}
/*----------------------------------------------------------------------------*/
void SyncEditor::AppendSegment(
T_String const& id ,
uint32_t nsDuration ) noexcept
{
assert( nsDuration > 0 );
auto& sync{ Common::Sync( ) };
auto const* const curve{ sync.getCurve( id ) };
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
if ( curve && !curve->segments.empty( ) ) {
const float lastValue{ [&](){
auto const& lSeg{ curve->segments.last( ) };
return lSeg.values.last( );
}( ) };
auto nCurve{ *curve };
auto& nSeg{ nCurve.segments.addNew( ) };
nSeg.type = T_SyncSegment::LINEAR;
nSeg.values.add( lastValue );
nSeg.values.add( lastValue );
nSeg.durations.add( nsDuration );
undo.curveReplacement( *curve , nCurve );
sync.setCurve( std::move( nCurve ) );
} else {
T_SyncCurve nCurve;
nCurve.name = id;
const auto value{ sync.inputs( )[ sync.inputPos( id ) ] };
auto& nSeg{ nCurve.segments.addNew( ) };
nSeg.type = T_SyncSegment::LINEAR;
nSeg.values.add( value );
nSeg.values.add( value );
nSeg.durations.add( nsDuration );
undo.curveCreation( nCurve );
sync.setCurve( std::move( nCurve ) );
}
}
/*----------------------------------------------------------------------------*/
void SyncEditor::DeleteSegment(
T_String const& id ,
const uint32_t segmentIndex ) noexcept
{
auto& sync{ Common::Sync( ) };
auto const* const curve{ sync.getCurve( id ) };
if ( !curve || segmentIndex >= curve->segments.size( ) ) {
return;
}
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
if ( curve->segments.size( ) == 1 ) {
undo.curveDeletion( *curve );
sync.removeCurve( id );
} else {
auto nCurve{ *curve };
nCurve.segments.remove( segmentIndex );
undo.curveReplacement( *curve , nCurve );
sync.setCurve( std::move( nCurve ) );
}
}
/*----------------------------------------------------------------------------*/
void SyncEditor::SetSegmentType(
T_SyncCurve const& initial ,
const uint32_t segmentIndex ,
const T_SyncSegment::E_SegmentType newType ) noexcept
{
assert( segmentIndex < initial.segments.size( ) );
T_SyncSegment const& iSegment{ initial.segments[ segmentIndex ] };
if ( iSegment.type == newType ) {
return;
}
// Create new curve
T_SyncCurve copy{ initial };
copy.segments[ segmentIndex ].type = newType;
// Create undo entry
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
undo.curveReplacement( initial , copy );
// Replace curve
Common::Sync( ).setCurve( std::move( copy ) );
}
/*----------------------------------------------------------------------------*/
void SyncEditor::InsertPoint(
T_String const& id ,
const uint32_t segmentIndex ,
const uint32_t pointIndex ) noexcept
{
auto& sync{ Common::Sync( ) };
auto const* const curve{ sync.getCurve( id ) };
if ( !curve || segmentIndex >= curve->segments.size( ) ) {
return;
}
auto const& segment{ curve->segments[ segmentIndex ] };
if ( pointIndex == 0 || pointIndex > segment.values.size( )
|| segment.durations[ pointIndex - 1 ] == 1 ) {
return;
}
auto c{ *curve };
auto& ns{ c.segments[ segmentIndex ] };
const auto hd{ ns.durations[ pointIndex - 1 ] / 2 };
const float hv{ ns.computeValue( ns.findTimeOfPoint( pointIndex - 1 ) + hd ) };
ns.durations[ pointIndex - 1 ] -= hd;
ns.durations.insert( pointIndex - 1 , hd );
ns.values.insert( pointIndex , hv );
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
undo.curveReplacement( *curve , c );
sync.setCurve( std::move( c ) );
}
/*----------------------------------------------------------------------------*/
void SyncEditor::DeletePoint(
T_String const& id ,
const uint32_t segmentIndex ,
const uint32_t pointIndex ) noexcept
{
auto& sync{ Common::Sync( ) };
auto const* const curve{ sync.getCurve( id ) };
if ( !curve || segmentIndex >= curve->segments.size( ) ) {
return;
}
auto const& segment{ curve->segments[ segmentIndex ] };
if ( pointIndex == 0 || pointIndex >= segment.values.size( ) ) {
return;
}
auto c{ *curve };
auto& ns{ c.segments[ segmentIndex ] };
ns.durations[ pointIndex ] += ns.durations[ pointIndex - 1 ];
ns.durations.remove( pointIndex - 1 );
ns.values.remove( pointIndex );
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
undo.curveReplacement( *curve , c );
sync.setCurve( std::move( c ) );
}