Sequencer - Identify overrides where inputs would cause trouble

This commit is contained in:
Emmanuel BENOîT 2017-11-28 10:42:04 +01:00
parent ec34bcc9bb
commit 5080866cbe
3 changed files with 153 additions and 34 deletions

View file

@ -254,6 +254,40 @@ float T_SyncCurve::computeValue(
return it->computeValue( timeUnits - prevSegStart ); 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 =============================================================*/ /*= T_SyncCurves =============================================================*/

View file

@ -51,6 +51,34 @@ struct T_SyncSegment
}; };
M_LSHIFT_OP( T_StringBuilder , T_SyncSegment::E_SegmentType ); 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 // An input curve
struct T_SyncCurve struct T_SyncCurve
{ {
@ -69,8 +97,14 @@ struct T_SyncCurve
// Compute the value at the specified time. // Compute the value at the specified time.
float computeValue( float timeUnits ) const noexcept; 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 // 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. // 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 // because some include was commented out), in which case we don't want to

View file

@ -259,6 +259,7 @@ struct T_SyncViewImpl_
void displayInputSelector( ) noexcept; void displayInputSelector( ) noexcept;
void displayOverrideSelector( ) noexcept; void displayOverrideSelector( ) noexcept;
// Selection display/edition windows
void displayTrackWindow( ) noexcept; void displayTrackWindow( ) noexcept;
void displaySegmentWindow( ) noexcept; void displaySegmentWindow( ) noexcept;
void displayPointWindow( ) noexcept; void displayPointWindow( ) noexcept;
@ -1321,6 +1322,24 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
{ {
using namespace ImGui; 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" ); BeginChild( "content" );
Common::Sync( ).visitOverrides( [&]( T_SyncOverrideVisitor::T_Element element , const bool exit ) { Common::Sync( ).visitOverrides( [&]( T_SyncOverrideVisitor::T_Element element , const bool exit ) {
if ( element.hasType< T_SyncOverrideSection* >( ) ) { if ( element.hasType< T_SyncOverrideSection* >( ) ) {
@ -1330,11 +1349,15 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
} }
if ( exit ) { if ( exit ) {
TreePop( ); TreePop( );
} else { return true;
}
return TreeNodeEx( &sos.cTitle[ 0 ] , return TreeNodeEx( &sos.cTitle[ 0 ] ,
ImGuiTreeNodeFlags_DefaultOpen ); ImGuiTreeNodeFlags_DefaultOpen );
} }
} else if ( exit ) { if ( ! exit ) {
return false;
}
auto const& ov{ *element.value< A_SyncOverride* >( ) }; auto const& ov{ *element.value< A_SyncOverride* >( ) };
auto const& id{ ov.id( ) }; auto const& id{ ov.id( ) };
auto const& in{ ov.inputNames( ) }; auto const& in{ ov.inputNames( ) };
@ -1348,9 +1371,34 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
return false; return false;
}() }; }() };
// 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 ) { if ( hasCurves ) {
PushDisabled( ); PushDisabled( );
} }
if ( bad ) {
PushStyleColor( ImGuiCol_Text , 0xff0000ff );
}
bool select{ present }; bool select{ present };
if ( Checkbox( ov.title( ) , &select ) ) { if ( Checkbox( ov.title( ) , &select ) ) {
@ -1367,10 +1415,13 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
} }
} }
if ( bad ) {
PopStyleColor( );
}
if ( hasCurves ) { if ( hasCurves ) {
PopDisabled( ); PopDisabled( );
} }
}
return true; return true;
} ); } );
EndChild( ); EndChild( );