Sequencer - Segment window + type selection
This commit is contained in:
parent
c4d5bd3fd1
commit
42e8437692
1 changed files with 187 additions and 28 deletions
215
ui-sequencer.cc
215
ui-sequencer.cc
|
@ -203,14 +203,18 @@ struct T_SyncViewImpl_
|
||||||
// Type of sub-windows
|
// Type of sub-windows
|
||||||
enum E_SubWindow {
|
enum E_SubWindow {
|
||||||
SW_NONE ,
|
SW_NONE ,
|
||||||
SW_CURVE_SELECTOR ,
|
SW_INPUT_SELECTOR ,
|
||||||
SW_OVERRIDE_SELECTOR ,
|
SW_OVERRIDE_SELECTOR ,
|
||||||
|
SW_SEGMENT ,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make sure all displayed curves/inputs/overrides still exist
|
// Make sure all displayed curves/inputs/overrides still exist
|
||||||
void checkSelectedCurves( ) noexcept;
|
void checkSelectedCurves( ) noexcept;
|
||||||
void displayToolbar( ) noexcept;
|
void displayToolbar( ) noexcept;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Sequencer widget methods
|
||||||
|
|
||||||
void computeMetrics( float innerWidth ) noexcept;
|
void computeMetrics( float innerWidth ) noexcept;
|
||||||
void sequencerWidget( ) noexcept;
|
void sequencerWidget( ) noexcept;
|
||||||
void sequencerHeader( ImRect const& bb ) noexcept;
|
void sequencerHeader( ImRect const& bb ) noexcept;
|
||||||
|
@ -231,10 +235,17 @@ struct T_SyncViewImpl_
|
||||||
|
|
||||||
T_MousePos getMousePos( ) const noexcept;
|
T_MousePos getMousePos( ) const noexcept;
|
||||||
|
|
||||||
void displayCurveSelectorWindow( ) noexcept;
|
//----------------------------------------------------------------------
|
||||||
void displayCurveSelector( ) noexcept;
|
|
||||||
|
// Track selector
|
||||||
|
void displayTrackSelectorWindow( ) noexcept;
|
||||||
|
void displayInputSelector( ) noexcept;
|
||||||
void displayOverrideSelector( ) noexcept;
|
void displayOverrideSelector( ) noexcept;
|
||||||
|
|
||||||
|
void displaySegmentWindow( ) noexcept;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
// Colors, sizes, etc.
|
// Colors, sizes, etc.
|
||||||
const uint32_t ColFrame{ ImGui::GetColorU32( ImVec4{ 0 , 0 , 0 , .8 } ) };
|
const uint32_t ColFrame{ ImGui::GetColorU32( ImVec4{ 0 , 0 , 0 , .8 } ) };
|
||||||
const uint32_t ColHeader{ ImGui::GetColorU32( ImVec4{ .5 , .5 , .5 , .8 } ) };
|
const uint32_t ColHeader{ ImGui::GetColorU32( ImVec4{ .5 , .5 , .5 , .8 } ) };
|
||||||
|
@ -271,6 +282,12 @@ struct T_SyncViewImpl_
|
||||||
float firstZoomPixel;
|
float firstZoomPixel;
|
||||||
float curZoomPixel;
|
float curZoomPixel;
|
||||||
|
|
||||||
|
// Selected item
|
||||||
|
T_String selId{ };
|
||||||
|
bool selIsOverride;
|
||||||
|
uint32_t selSegment;
|
||||||
|
T_Optional< uint32_t > selPoint;
|
||||||
|
|
||||||
// Sub-windows
|
// Sub-windows
|
||||||
E_SubWindow sub{ SW_NONE };
|
E_SubWindow sub{ SW_NONE };
|
||||||
|
|
||||||
|
@ -315,9 +332,13 @@ bool T_SyncViewImpl_::display( ) noexcept
|
||||||
case SW_NONE:
|
case SW_NONE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SW_CURVE_SELECTOR:
|
case SW_INPUT_SELECTOR:
|
||||||
case SW_OVERRIDE_SELECTOR:
|
case SW_OVERRIDE_SELECTOR:
|
||||||
displayCurveSelectorWindow( );
|
displayTrackSelectorWindow( );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SW_SEGMENT:
|
||||||
|
displaySegmentWindow( );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,9 +437,9 @@ void T_SyncViewImpl_::displayToolbar( ) noexcept
|
||||||
|
|
||||||
if ( ToolbarButton( ICON_FA_LINE_CHART , BtSize ,
|
if ( ToolbarButton( ICON_FA_LINE_CHART , BtSize ,
|
||||||
"Select curves or sets thereof to display & edit." ) ) {
|
"Select curves or sets thereof to display & edit." ) ) {
|
||||||
const bool displaySelector{ sub == SW_CURVE_SELECTOR
|
const bool displaySelector{ sub == SW_INPUT_SELECTOR
|
||||||
|| sub == SW_OVERRIDE_SELECTOR };
|
|| sub == SW_OVERRIDE_SELECTOR };
|
||||||
sub = displaySelector ? SW_NONE : SW_CURVE_SELECTOR;
|
sub = displaySelector ? SW_NONE : SW_INPUT_SELECTOR;
|
||||||
curveFinder = T_String{};
|
curveFinder = T_String{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,18 +511,7 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( io.MouseDown[ 0 ] ) {
|
if ( zoomInProgress && !io.MouseDown[ 1 ] ) {
|
||||||
sync.setTime( mTime );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( io.MouseDown[ 1 ] ) {
|
|
||||||
if ( !zoomInProgress ) {
|
|
||||||
firstZoomPixel = mPixels;
|
|
||||||
zoomInProgress = true;
|
|
||||||
}
|
|
||||||
curZoomPixel = mPixels;
|
|
||||||
|
|
||||||
} else if ( zoomInProgress ) {
|
|
||||||
zoomInProgress = false;
|
zoomInProgress = false;
|
||||||
justZoomed = true;
|
justZoomed = true;
|
||||||
const auto zMin{ std::min( firstZoomPixel , curZoomPixel ) } ,
|
const auto zMin{ std::min( firstZoomPixel , curZoomPixel ) } ,
|
||||||
|
@ -522,6 +532,32 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
|
||||||
|
|
||||||
if ( !( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
if ( !( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
||||||
ClearActiveID( );
|
ClearActiveID( );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto mp{ getMousePos( ) };
|
||||||
|
if ( mp.type == E_MousePosType::NONE ) {
|
||||||
|
if ( io.MouseDown[ 0 ] ) {
|
||||||
|
sync.setTime( mTime );
|
||||||
|
}
|
||||||
|
if ( io.MouseDown[ 1 ] ) {
|
||||||
|
if ( !zoomInProgress ) {
|
||||||
|
firstZoomPixel = mPixels;
|
||||||
|
zoomInProgress = true;
|
||||||
|
}
|
||||||
|
curZoomPixel = mPixels;
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if ( mp.type == E_MousePosType::SEGMENT ) {
|
||||||
|
auto const& dSeg{ dspSegments[ mp.index ] };
|
||||||
|
auto const& dTrack{ dspTracks[ dSeg.track ] };
|
||||||
|
if ( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) {
|
||||||
|
selId = dTrack.id;
|
||||||
|
selIsOverride = dTrack.isOverride;
|
||||||
|
selSegment = dSeg.seg;
|
||||||
|
selPoint = {};
|
||||||
|
sub = E_SubWindow::SW_SEGMENT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,6 +683,9 @@ void T_SyncViewImpl_::sequencerBody(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the curve / override controls
|
// Display the curve / override controls
|
||||||
|
dspTracks.clear( );
|
||||||
|
dspSegments.clear( );
|
||||||
|
dspPoints.clear( );
|
||||||
if ( sCurves.size( ) != 0 ) {
|
if ( sCurves.size( ) != 0 ) {
|
||||||
|
|
||||||
ImRect subBb{ inner };
|
ImRect subBb{ inner };
|
||||||
|
@ -860,13 +899,11 @@ void T_SyncViewImpl_::displayTooltips(
|
||||||
const float dTime( [&](){
|
const float dTime( [&](){
|
||||||
if ( point ) {
|
if ( point ) {
|
||||||
auto tDur{ .0f };
|
auto tDur{ .0f };
|
||||||
printf( "segseg %d\n" , seg->seg );
|
|
||||||
for ( auto i = 0u ; i <= seg->seg ; i ++ ) {
|
for ( auto i = 0u ; i <= seg->seg ; i ++ ) {
|
||||||
auto const& s{ curve->segments[ i ] };
|
auto const& s{ curve->segments[ i ] };
|
||||||
auto const nd{ i == seg->seg
|
auto const nd{ i == seg->seg
|
||||||
? point->index
|
? point->index
|
||||||
: s.durations.size( ) };
|
: s.durations.size( ) };
|
||||||
printf( "s %d -> nd %d\n" , i , nd );
|
|
||||||
for ( auto j = 0u ; j < nd ; j ++ ) {
|
for ( auto j = 0u ; j < nd ; j ++ ) {
|
||||||
tDur += s.durations[ j ];
|
tDur += s.durations[ j ];
|
||||||
}
|
}
|
||||||
|
@ -922,7 +959,8 @@ T_SyncViewImpl_::T_MousePos T_SyncViewImpl_::getMousePos( ) const noexcept
|
||||||
seg.firstPoint + k };
|
seg.firstPoint + k };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return T_MousePos{ E_MousePosType::SEGMENT , i };
|
return T_MousePos{ E_MousePosType::SEGMENT ,
|
||||||
|
track.firstSeg + j };
|
||||||
}
|
}
|
||||||
return T_MousePos{ E_MousePosType::TRACK , i };
|
return T_MousePos{ E_MousePosType::TRACK , i };
|
||||||
}
|
}
|
||||||
|
@ -931,7 +969,7 @@ T_SyncViewImpl_::T_MousePos T_SyncViewImpl_::getMousePos( ) const noexcept
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void T_SyncViewImpl_::displayCurveSelectorWindow( ) noexcept
|
void T_SyncViewImpl_::displayTrackSelectorWindow( ) noexcept
|
||||||
{
|
{
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
auto const& dspSize( GetIO( ).DisplaySize );
|
auto const& dspSize( GetIO( ).DisplaySize );
|
||||||
|
@ -955,8 +993,8 @@ void T_SyncViewImpl_::displayCurveSelectorWindow( ) noexcept
|
||||||
const float buttonWidth{ std::max( 50.f ,
|
const float buttonWidth{ std::max( 50.f ,
|
||||||
( innerWidth - nButtons * style.FramePadding.x ) / nButtons ) };
|
( innerWidth - nButtons * style.FramePadding.x ) / nButtons ) };
|
||||||
|
|
||||||
if ( FakeTab_( "Individual inputs" , sub == SW_CURVE_SELECTOR , buttonWidth ) ) {
|
if ( FakeTab_( "Individual inputs" , sub == SW_INPUT_SELECTOR , buttonWidth ) ) {
|
||||||
sub = SW_CURVE_SELECTOR;
|
sub = SW_INPUT_SELECTOR;
|
||||||
}
|
}
|
||||||
SameLine( 0 );
|
SameLine( 0 );
|
||||||
if ( FakeTab_( "Overrides" , sub == SW_OVERRIDE_SELECTOR , buttonWidth ) ) {
|
if ( FakeTab_( "Overrides" , sub == SW_OVERRIDE_SELECTOR , buttonWidth ) ) {
|
||||||
|
@ -965,8 +1003,8 @@ void T_SyncViewImpl_::displayCurveSelectorWindow( ) noexcept
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
switch ( sub ) {
|
switch ( sub ) {
|
||||||
case SW_CURVE_SELECTOR:
|
case SW_INPUT_SELECTOR:
|
||||||
displayCurveSelector( );
|
displayInputSelector( );
|
||||||
break;
|
break;
|
||||||
case SW_OVERRIDE_SELECTOR:
|
case SW_OVERRIDE_SELECTOR:
|
||||||
displayOverrideSelector( );
|
displayOverrideSelector( );
|
||||||
|
@ -978,7 +1016,7 @@ void T_SyncViewImpl_::displayCurveSelectorWindow( ) noexcept
|
||||||
End( );
|
End( );
|
||||||
}
|
}
|
||||||
|
|
||||||
void T_SyncViewImpl_::displayCurveSelector( ) noexcept
|
void T_SyncViewImpl_::displayInputSelector( ) noexcept
|
||||||
{
|
{
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
T_Array< T_String > names{ Common::Sync( ).inputNames( ) };
|
T_Array< T_String > names{ Common::Sync( ).inputNames( ) };
|
||||||
|
@ -1095,6 +1133,127 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
|
||||||
EndChild( );
|
EndChild( );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void T_SyncViewImpl_::displaySegmentWindow( ) noexcept
|
||||||
|
{
|
||||||
|
using namespace ImGui;
|
||||||
|
auto const& dspSize( GetIO( ).DisplaySize );
|
||||||
|
|
||||||
|
// Window set-up
|
||||||
|
SetNextWindowSize( ImVec2( dspSize.x * .25f , dspSize.y * .66f - 20 ) , ImGuiSetCond_Appearing );
|
||||||
|
SetNextWindowPos( ImVec2( dspSize.x * .75f , 20 ) , ImGuiSetCond_Appearing );
|
||||||
|
bool displayed{ true };
|
||||||
|
Begin( "Selected segment" , &displayed , ImGuiWindowFlags_NoCollapse );
|
||||||
|
if ( !displayed ) {
|
||||||
|
End( );
|
||||||
|
sub = SW_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text( "Curve:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%s" , selId.toOSString( ).data( ) );
|
||||||
|
|
||||||
|
Text( "Index:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%d" , selSegment );
|
||||||
|
|
||||||
|
Separator( );
|
||||||
|
|
||||||
|
auto& sync{ Common::Sync( ) };
|
||||||
|
auto* const curve{ sync.getCurve( selId ) };
|
||||||
|
auto& segment{ curve->segments[ selSegment ] };
|
||||||
|
|
||||||
|
// Find start and duration
|
||||||
|
uint32_t start{ 0 } , duration{ 0 };
|
||||||
|
for ( auto i = 0u ; i <= selSegment ; i ++ ) {
|
||||||
|
auto const& s{ curve->segments[ i ] };
|
||||||
|
auto& tgt{ i == selSegment ? duration : start };
|
||||||
|
for ( auto d : s.durations ) {
|
||||||
|
tgt += d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const float tStart{ sync.durationUnitSize( ) * start } ,
|
||||||
|
tDuration{ sync.durationUnitSize( ) * duration };
|
||||||
|
|
||||||
|
Text( "Start:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%d units" , start );
|
||||||
|
|
||||||
|
Text( " " );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%.3f seconds" , tStart );
|
||||||
|
|
||||||
|
Text( "End:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%d units" , start + duration );
|
||||||
|
|
||||||
|
Text( " " );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%.3f seconds" , tStart + tDuration );
|
||||||
|
|
||||||
|
Text( "Duration:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%d units" , duration );
|
||||||
|
|
||||||
|
Text( " " );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%.3f seconds" , tDuration );
|
||||||
|
|
||||||
|
Separator( );
|
||||||
|
|
||||||
|
// Generate the combo box's data
|
||||||
|
static constexpr T_SyncSegment::E_SegmentType types[] = {
|
||||||
|
T_SyncSegment::LINEAR , T_SyncSegment::RAMP , T_SyncSegment::SMOOTH
|
||||||
|
};
|
||||||
|
stringBuffer.clear( );
|
||||||
|
for ( auto t : types ) {
|
||||||
|
stringBuffer << t << '\0';
|
||||||
|
}
|
||||||
|
stringBuffer << '\0';
|
||||||
|
Text( "Type:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
PushItemWidth( -1 );
|
||||||
|
int t{ int( segment.type ) };
|
||||||
|
const bool change{ Combo( "##type" , &t , stringBuffer.data( ) ) };
|
||||||
|
PopItemWidth( );
|
||||||
|
|
||||||
|
Separator( );
|
||||||
|
|
||||||
|
Text( "Points:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%d" , segment.values.size( ) );
|
||||||
|
|
||||||
|
// Find min/max
|
||||||
|
float sMin{ FLT_MAX } , sMax{ -FLT_MAX };
|
||||||
|
for ( auto v : segment.values ) {
|
||||||
|
sMin = ImMin( sMin , v );
|
||||||
|
sMax = ImMax( sMax , v );
|
||||||
|
}
|
||||||
|
|
||||||
|
Text( "Min. value:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%f" , sMin );
|
||||||
|
|
||||||
|
Text( "Max. value:" );
|
||||||
|
SameLine( 110 );
|
||||||
|
Text( "%f" , sMax );
|
||||||
|
|
||||||
|
if ( change ) {
|
||||||
|
#warning fixme move to syncedit
|
||||||
|
T_SyncCurve copy{ *curve };
|
||||||
|
copy.segments[ selSegment ].type = T_SyncSegment::E_SegmentType( t );
|
||||||
|
|
||||||
|
auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
|
||||||
|
Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
|
||||||
|
undo.curveReplacement( *curve , copy );
|
||||||
|
sync.setCurve( std::move( copy ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
End( );
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace <anon>
|
} // namespace <anon>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue