Sequencer - Identify overrides where inputs would cause trouble
This commit is contained in:
parent
ec34bcc9bb
commit
5080866cbe
3 changed files with 153 additions and 34 deletions
34
c-sync.cc
34
c-sync.cc
|
@ -254,6 +254,40 @@ float T_SyncCurve::computeValue(
|
|||
return it->computeValue( timeUnits - prevSegStart );
|
||||
}
|
||||
|
||||
E_SyncCurveMatch T_SyncCurve::matches(
|
||||
T_SyncCurve const& other ) const noexcept
|
||||
{
|
||||
const auto tSegs{ this->segments.size( ) };
|
||||
const auto oSegs{ other.segments.size( ) };
|
||||
const auto nSegs{ std::min( tSegs , oSegs ) };
|
||||
for ( auto i = 0u ; i < nSegs ; i ++ ) {
|
||||
auto const& tDur{ this->segments[ i ].durations };
|
||||
auto const& oDur{ other.segments[ i ].durations };
|
||||
const bool lastSeg{ i == nSegs - 1 };
|
||||
if ( !lastSeg && tDur.size( ) != oDur.size( ) ) {
|
||||
return E_SyncCurveMatch::MISMATCH;
|
||||
}
|
||||
|
||||
const auto nd{ std::min( tDur.size( ) , oDur.size( ) ) };
|
||||
for ( auto j = 0u ; j < nd ; j ++ ) {
|
||||
if ( tDur[ j ] != oDur[ j ] ) {
|
||||
return E_SyncCurveMatch::MISMATCH;
|
||||
}
|
||||
}
|
||||
if ( tDur.size( ) != oDur.size( ) ) {
|
||||
return tDur.size( ) < oDur.size( )
|
||||
? E_SyncCurveMatch::LASTSEG_SHORT
|
||||
: E_SyncCurveMatch::LASTSEG_LONG;
|
||||
}
|
||||
}
|
||||
if ( tSegs == oSegs ) {
|
||||
return E_SyncCurveMatch::IDENTICAL;
|
||||
}
|
||||
return tSegs < oSegs
|
||||
? E_SyncCurveMatch::MATCHING_SHORT
|
||||
: E_SyncCurveMatch::MATCHING_LONG;
|
||||
}
|
||||
|
||||
|
||||
/*= T_SyncCurves =============================================================*/
|
||||
|
||||
|
|
34
c-sync.hh
34
c-sync.hh
|
@ -51,6 +51,34 @@ struct T_SyncSegment
|
|||
};
|
||||
M_LSHIFT_OP( T_StringBuilder , T_SyncSegment::E_SegmentType );
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
// Possible results when trying to check whether two curves have a similar
|
||||
// structure.
|
||||
enum class E_SyncCurveMatch
|
||||
{
|
||||
// Both curves have the same structure.
|
||||
IDENTICAL ,
|
||||
|
||||
// One of the curves has less information than the other, but the
|
||||
// information in the shortest curve matches the corresponding
|
||||
// information in the longest curve (i.e. it is only missing
|
||||
// segments). _SHORT/_LONG indicate that the curve for which the
|
||||
// comparison method was called is the shortest/longest (resp.)
|
||||
MATCHING_SHORT ,
|
||||
MATCHING_LONG ,
|
||||
|
||||
// One of the curves has less information than the other, and its
|
||||
// last segment is shorter than the corresponding segment in the
|
||||
// longest record (but its end matches a point in the longest curve's
|
||||
// segment).
|
||||
LASTSEG_SHORT ,
|
||||
LASTSEG_LONG ,
|
||||
|
||||
// The curves do not match.
|
||||
MISMATCH
|
||||
};
|
||||
|
||||
// An input curve
|
||||
struct T_SyncCurve
|
||||
{
|
||||
|
@ -69,8 +97,14 @@ struct T_SyncCurve
|
|||
|
||||
// Compute the value at the specified time.
|
||||
float computeValue( float timeUnits ) const noexcept;
|
||||
|
||||
// Compare this curve to another.
|
||||
E_SyncCurveMatch matches(
|
||||
T_SyncCurve const& other ) const noexcept;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
// All configured curves. Some may not actually correspond to an input and may
|
||||
// have been defined for inputs that have been removed temporarily (e.g.
|
||||
// because some include was commented out), in which case we don't want to
|
||||
|
|
119
ui-sequencer.cc
119
ui-sequencer.cc
|
@ -259,6 +259,7 @@ struct T_SyncViewImpl_
|
|||
void displayInputSelector( ) noexcept;
|
||||
void displayOverrideSelector( ) noexcept;
|
||||
|
||||
// Selection display/edition windows
|
||||
void displayTrackWindow( ) noexcept;
|
||||
void displaySegmentWindow( ) noexcept;
|
||||
void displayPointWindow( ) noexcept;
|
||||
|
@ -1321,6 +1322,24 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
|
|||
{
|
||||
using namespace ImGui;
|
||||
|
||||
/*
|
||||
* An override can be selected directly if the inputs that are part of
|
||||
* it are consistent.
|
||||
*
|
||||
* A pair of inputs are consistent if
|
||||
* - one or both inputs do not have curve information attached;
|
||||
* - the durations and segment boundaries of the shortest curve
|
||||
* attached to the inputs match the boundaries and durations from the
|
||||
* other input's curve OR the last segment is shorter but its end
|
||||
* matches the location of one of the points in the corresponding
|
||||
* segment of the other curve.
|
||||
*
|
||||
* If the inputs are not consistent, it will be necessary to reset
|
||||
* some of their curves; best option would be to try and be clever, but
|
||||
* a temporary measure (resetting all curves to match the structure of
|
||||
* the first longest curve) would work.
|
||||
*/
|
||||
|
||||
BeginChild( "content" );
|
||||
Common::Sync( ).visitOverrides( [&]( T_SyncOverrideVisitor::T_Element element , const bool exit ) {
|
||||
if ( element.hasType< T_SyncOverrideSection* >( ) ) {
|
||||
|
@ -1330,47 +1349,79 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
|
|||
}
|
||||
if ( exit ) {
|
||||
TreePop( );
|
||||
} else {
|
||||
return TreeNodeEx( &sos.cTitle[ 0 ] ,
|
||||
ImGuiTreeNodeFlags_DefaultOpen );
|
||||
return true;
|
||||
}
|
||||
} 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;
|
||||
}() };
|
||||
return TreeNodeEx( &sos.cTitle[ 0 ] ,
|
||||
ImGuiTreeNodeFlags_DefaultOpen );
|
||||
}
|
||||
if ( ! exit ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( hasCurves ) {
|
||||
PushDisabled( );
|
||||
}
|
||||
|
||||
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 ] );
|
||||
}
|
||||
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 ) {
|
||||
PopDisabled( );
|
||||
// FIXME MOVE THIS \/ //
|
||||
bool bad{ false };
|
||||
for ( auto i = 0u ; i < in.size( ) - 1 && !bad ; i ++ ) {
|
||||
T_SyncCurve const* const c0{
|
||||
Common::Sync( ).getCurve( in[ i ] )
|
||||
};
|
||||
if ( !c0 ) {
|
||||
continue;
|
||||
}
|
||||
for ( auto j = i + 1 ; j < in.size( ) && !bad ; j ++ ) {
|
||||
T_SyncCurve const* const c1{
|
||||
Common::Sync( ).getCurve( in[ j ] )
|
||||
};
|
||||
if ( !c1 ) {
|
||||
continue;
|
||||
}
|
||||
const auto res{ c0->matches( *c1 ) };
|
||||
bad = ( res == E_SyncCurveMatch::MISMATCH );
|
||||
}
|
||||
}
|
||||
// FIXME MOVE THIS /\ //
|
||||
|
||||
if ( hasCurves ) {
|
||||
PushDisabled( );
|
||||
}
|
||||
if ( bad ) {
|
||||
PushStyleColor( ImGuiCol_Text , 0xff0000ff );
|
||||
}
|
||||
|
||||
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 ( bad ) {
|
||||
PopStyleColor( );
|
||||
}
|
||||
if ( hasCurves ) {
|
||||
PopDisabled( );
|
||||
}
|
||||
|
||||
return true;
|
||||
} );
|
||||
EndChild( );
|
||||
|
|
Loading…
Reference in a new issue