Sequencer - Progress on track display
This commit is contained in:
parent
2cfc80a6e4
commit
c4d5bd3fd1
1 changed files with 287 additions and 133 deletions
420
ui-sequencer.cc
420
ui-sequencer.cc
|
@ -16,7 +16,7 @@ using namespace ebcl;
|
|||
|
||||
namespace {
|
||||
|
||||
/*= VARIOUS IMGUI HELPERS ====================================================*/
|
||||
/*= VARIOUS HELPERS ==========================================================*/
|
||||
|
||||
bool FakeTab_(
|
||||
char const* const name ,
|
||||
|
@ -34,6 +34,18 @@ bool FakeTab_(
|
|||
return rv;
|
||||
}
|
||||
|
||||
void TimeToString_(
|
||||
char* const buffer ,
|
||||
const size_t bSize ,
|
||||
const float time ) noexcept
|
||||
{
|
||||
const float msf{ fmod( time , 1.f ) };
|
||||
const float sf{ fmod( time - msf , 60.f ) };
|
||||
snprintf( buffer , bSize , "%02d:%02d.%03d" ,
|
||||
uint32_t( ( time - msf - sf ) / 60.f ) ,
|
||||
uint32_t( sf ) , uint32_t( msf * 1000.f ) );
|
||||
}
|
||||
|
||||
|
||||
/*= T_ChangeDurationDialog_ ==================================================*/
|
||||
|
||||
|
@ -139,10 +151,62 @@ struct T_SyncViewImpl_
|
|||
static constexpr float BarWidth = 40.f;
|
||||
static constexpr float TrackHeight = 15.f;
|
||||
static constexpr float TrackPadding = 2.f;
|
||||
static constexpr float PointRadius = ( TrackHeight - 2.f ) * .5f;
|
||||
static constexpr float PointRadiusSqr = PointRadius * PointRadius;
|
||||
|
||||
bool display( ) noexcept;
|
||||
|
||||
private:
|
||||
// Track display data
|
||||
struct T_TrackDisplay
|
||||
{
|
||||
T_String id;
|
||||
bool isOverride;
|
||||
ImRect area;
|
||||
uint32_t dispSegs;
|
||||
uint32_t firstSeg;
|
||||
};
|
||||
struct T_TrackSegDisplay
|
||||
{
|
||||
uint32_t track;
|
||||
uint32_t seg;
|
||||
ImRect area;
|
||||
uint32_t dispPoints;
|
||||
uint32_t firstPoint;
|
||||
};
|
||||
struct T_TrackPointDisplay
|
||||
{
|
||||
uint32_t seg;
|
||||
uint32_t index;
|
||||
ImVec2 center;
|
||||
enum {
|
||||
START ,
|
||||
MIDDLE ,
|
||||
END
|
||||
} mode;
|
||||
};
|
||||
|
||||
// Description for mouse locations in the sequencer window
|
||||
enum class E_MousePosType
|
||||
{
|
||||
NONE ,
|
||||
TRACK ,
|
||||
SEGMENT ,
|
||||
POINT
|
||||
};
|
||||
struct T_MousePos
|
||||
{
|
||||
E_MousePosType type;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
// Type of sub-windows
|
||||
enum E_SubWindow {
|
||||
SW_NONE ,
|
||||
SW_CURVE_SELECTOR ,
|
||||
SW_OVERRIDE_SELECTOR ,
|
||||
};
|
||||
|
||||
// Make sure all displayed curves/inputs/overrides still exist
|
||||
void checkSelectedCurves( ) noexcept;
|
||||
void displayToolbar( ) noexcept;
|
||||
|
@ -150,18 +214,23 @@ struct T_SyncViewImpl_
|
|||
void computeMetrics( float innerWidth ) noexcept;
|
||||
void sequencerWidget( ) noexcept;
|
||||
void sequencerHeader( ImRect const& bb ) noexcept;
|
||||
bool sequencerBody( ImRect const& bb ) noexcept;
|
||||
bool sequencerTracks(
|
||||
void sequencerBody( ImRect const& bb ) noexcept;
|
||||
void sequencerTracks(
|
||||
float& hue ,
|
||||
ImRect& bb ,
|
||||
ImRect const& container ) noexcept;
|
||||
bool sequencerTrack(
|
||||
void sequencerTrack(
|
||||
float& hue ,
|
||||
ImRect const& bb ,
|
||||
ImRect const& container ,
|
||||
T_String const& name ,
|
||||
T_SyncCurve const* curve ) noexcept;
|
||||
|
||||
void displayTooltips(
|
||||
const float time ) noexcept;
|
||||
|
||||
T_MousePos getMousePos( ) const noexcept;
|
||||
|
||||
void displayCurveSelectorWindow( ) noexcept;
|
||||
void displayCurveSelector( ) noexcept;
|
||||
void displayOverrideSelector( ) noexcept;
|
||||
|
@ -191,19 +260,21 @@ struct T_SyncViewImpl_
|
|||
float totalPixels;
|
||||
float startPixel;
|
||||
|
||||
// Track display
|
||||
T_Array< T_TrackDisplay > dspTracks;
|
||||
T_Array< T_TrackSegDisplay > dspSegments;
|
||||
T_Array< T_TrackPointDisplay > dspPoints;
|
||||
|
||||
// Zoom area selection
|
||||
bool zoomInProgress{ false };
|
||||
bool justZoomed{ false };
|
||||
float firstZoomPixel;
|
||||
float curZoomPixel;
|
||||
|
||||
// Curve display / edition
|
||||
enum E_SubWindow {
|
||||
SW_NONE ,
|
||||
SW_CURVE_SELECTOR ,
|
||||
SW_OVERRIDE_SELECTOR ,
|
||||
};
|
||||
// Sub-windows
|
||||
E_SubWindow sub{ SW_NONE };
|
||||
|
||||
// Curve selection
|
||||
T_KeyValueTable< T_String , bool > sCurves;
|
||||
T_Set< T_String > sOverrides;
|
||||
T_String curveFinder;
|
||||
|
@ -387,17 +458,13 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
|
|||
sequencerHeader( bbHeader );
|
||||
PopID( );
|
||||
}
|
||||
bool mouseConsumed{ false };
|
||||
if ( bbDisplay.Min.y < bbDisplay.Max.y && ItemAdd( bbDisplay , dspId ) ) {
|
||||
PushID( dspId );
|
||||
mouseConsumed = sequencerBody( bbDisplay );
|
||||
sequencerBody( bbDisplay );
|
||||
PopID( );
|
||||
}
|
||||
PopID( );
|
||||
if ( mouseConsumed ) {
|
||||
EndGroup( );
|
||||
return;
|
||||
}
|
||||
EndGroup( );
|
||||
|
||||
auto& io( GetIO( ) );
|
||||
if ( hovered && ( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
||||
|
@ -406,46 +473,56 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
|
|||
}
|
||||
|
||||
const bool active( GetCurrentContext( )->ActiveId == seqId );
|
||||
if ( hovered && !active && io.MouseWheel != 0 ) {
|
||||
zoomLevel = ImSaturate( zoomLevel + .025 * io.MouseWheel );
|
||||
} else if ( active ) {
|
||||
if ( io.MouseDown[ 0 ] ) {
|
||||
const float p{ io.MousePos.x - bbAll.Min.x + startPixel };
|
||||
auto& sync( Common::Sync( ) );
|
||||
sync.setTime( p * Common::Sync( ).duration( ) / totalPixels );
|
||||
auto& sync( Common::Sync( ) );
|
||||
const float mPixels{ io.MousePos.x - bbAll.Min.x + startPixel };
|
||||
const float mTime{ mPixels * sync.duration( ) / totalPixels };
|
||||
|
||||
if ( !active ) {
|
||||
if ( !hovered ) {
|
||||
return;
|
||||
}
|
||||
if ( io.MouseDown[ 1 ] ) {
|
||||
const float p{ io.MousePos.x - bbAll.Min.x + startPixel };
|
||||
if ( !zoomInProgress ) {
|
||||
firstZoomPixel = p;
|
||||
zoomInProgress = true;
|
||||
}
|
||||
curZoomPixel = p;
|
||||
} else if ( zoomInProgress ) {
|
||||
zoomInProgress = false;
|
||||
justZoomed = true;
|
||||
const auto zMin{ std::min( firstZoomPixel , curZoomPixel ) } ,
|
||||
zMax{ std::max( firstZoomPixel , curZoomPixel ) } ,
|
||||
diff{ zMax - zMin };
|
||||
if ( diff > 4 ) {
|
||||
auto& sync( Common::Sync( ) );
|
||||
const float u( sync.durationUnits( ) );
|
||||
startPos = zMin * u / totalPixels;
|
||||
if ( ( width - 2.f ) / u >= BarWidth ) {
|
||||
zoomLevel = 0;
|
||||
} else {
|
||||
const auto length{ std::min( u , diff * u / totalPixels ) };
|
||||
const auto ppu{ std::min( ( width - 2 ) / length , BarWidth ) };
|
||||
zoomLevel = ( ppu - BarWidth ) / ( BarWidth - width / u ) + 1;
|
||||
}
|
||||
}
|
||||
if ( io.MouseWheel != 0 ) {
|
||||
zoomLevel = ImSaturate( zoomLevel + .025 * io.MouseWheel );
|
||||
}
|
||||
if ( !( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
||||
ClearActiveID( );
|
||||
if ( bbDisplay.Contains( io.MousePos ) ) {
|
||||
displayTooltips( mTime );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( io.MouseDown[ 0 ] ) {
|
||||
sync.setTime( mTime );
|
||||
}
|
||||
|
||||
if ( io.MouseDown[ 1 ] ) {
|
||||
if ( !zoomInProgress ) {
|
||||
firstZoomPixel = mPixels;
|
||||
zoomInProgress = true;
|
||||
}
|
||||
curZoomPixel = mPixels;
|
||||
|
||||
} else if ( zoomInProgress ) {
|
||||
zoomInProgress = false;
|
||||
justZoomed = true;
|
||||
const auto zMin{ std::min( firstZoomPixel , curZoomPixel ) } ,
|
||||
zMax{ std::max( firstZoomPixel , curZoomPixel ) } ,
|
||||
diff{ zMax - zMin };
|
||||
if ( diff > 4 ) {
|
||||
const float u( sync.durationUnits( ) );
|
||||
startPos = zMin * u / totalPixels;
|
||||
if ( ( width - 2.f ) / u >= BarWidth ) {
|
||||
zoomLevel = 0;
|
||||
} else {
|
||||
const auto length{ std::min( u , diff * u / totalPixels ) };
|
||||
const auto ppu{ std::min( ( width - 2 ) / length , BarWidth ) };
|
||||
zoomLevel = ( ppu - BarWidth ) / ( BarWidth - width / u ) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndGroup( );
|
||||
if ( !( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
||||
ClearActiveID( );
|
||||
}
|
||||
}
|
||||
|
||||
void T_SyncViewImpl_::computeMetrics(
|
||||
|
@ -526,11 +603,7 @@ void T_SyncViewImpl_::sequencerHeader(
|
|||
const ImVec2 taEnd{ taStart + ImVec2{ barWidth , inner.Max.y - inner.Min.y } };
|
||||
|
||||
const float time{ bar * timePerBar };
|
||||
const float msf{ fmod( time , 1.f ) };
|
||||
const float sf{ fmod( time - msf , 60.f ) };
|
||||
snprintf( buffer , sizeof( buffer ) , "%02d:%02d.%03d" ,
|
||||
uint32_t( ( time - msf - sf ) / 60.f ) ,
|
||||
uint32_t( sf ) , uint32_t( msf * 1000.f ) );
|
||||
TimeToString_( buffer , sizeof( buffer ) , time );
|
||||
RenderTextClipped( taStart , taEnd , buffer , nullptr , nullptr ,
|
||||
ImVec2{ .5f , .05f + ( ( bar % 2 ) ? .9f : 0.f ) } , &inner );
|
||||
pos += barWidth;
|
||||
|
@ -540,7 +613,7 @@ void T_SyncViewImpl_::sequencerHeader(
|
|||
PopFont( );
|
||||
}
|
||||
|
||||
bool T_SyncViewImpl_::sequencerBody(
|
||||
void T_SyncViewImpl_::sequencerBody(
|
||||
ImRect const& bb ) noexcept
|
||||
{
|
||||
using namespace ImGui;
|
||||
|
@ -574,7 +647,6 @@ bool T_SyncViewImpl_::sequencerBody(
|
|||
}
|
||||
|
||||
// Display the curve / override controls
|
||||
bool mouseConsumed{ false };
|
||||
if ( sCurves.size( ) != 0 ) {
|
||||
|
||||
ImRect subBb{ inner };
|
||||
|
@ -585,7 +657,7 @@ bool T_SyncViewImpl_::sequencerBody(
|
|||
float hue{ 0.12f };
|
||||
|
||||
// TODO: display overrides
|
||||
mouseConsumed = sequencerTracks( hue , subBb , inner ) || mouseConsumed;
|
||||
sequencerTracks( hue , subBb , inner );
|
||||
}
|
||||
|
||||
if ( cursorPos >= 0 && cursorPos <= inner.GetWidth( ) ) {
|
||||
|
@ -594,18 +666,14 @@ bool T_SyncViewImpl_::sequencerBody(
|
|||
ImVec2{ inner.Min.x + cursorPos , inner.Max.y - 1 } ,
|
||||
0xffffffff );
|
||||
}
|
||||
|
||||
return mouseConsumed;
|
||||
}
|
||||
|
||||
bool T_SyncViewImpl_::sequencerTracks(
|
||||
void T_SyncViewImpl_::sequencerTracks(
|
||||
float& hue ,
|
||||
ImRect& subBb ,
|
||||
ImRect const& container ) noexcept
|
||||
{
|
||||
auto& sync{ Common::Sync( ) };
|
||||
const auto nc{ sCurves.size( ) };
|
||||
bool mouseConsumed{ false };
|
||||
for ( auto i = 0u ; i < nc ; i ++ ) {
|
||||
if ( sCurves.values( )[ i ] ) {
|
||||
continue;
|
||||
|
@ -613,31 +681,38 @@ bool T_SyncViewImpl_::sequencerTracks(
|
|||
|
||||
auto const& name{ sCurves.keys( )[ i ] };
|
||||
auto* const curve{ sync.getCurve( name ) };
|
||||
mouseConsumed = sequencerTrack( hue , subBb , container , name , curve )
|
||||
|| mouseConsumed;
|
||||
sequencerTrack( hue , subBb , container , name , curve );
|
||||
subBb.Min.y += TrackHeight + 2 * TrackPadding;
|
||||
subBb.Max.y += TrackHeight + 2 * TrackPadding;
|
||||
hue = fmodf( hue + .17f , 1.f );
|
||||
}
|
||||
return mouseConsumed;
|
||||
}
|
||||
|
||||
bool T_SyncViewImpl_::sequencerTrack(
|
||||
void T_SyncViewImpl_::sequencerTrack(
|
||||
float& hue ,
|
||||
ImRect const& bb ,
|
||||
ImRect const& container ,
|
||||
T_String const& name ,
|
||||
T_String const& id ,
|
||||
T_SyncCurve const* curve ) noexcept
|
||||
{
|
||||
using namespace ImGui;
|
||||
// Don't display if the track is fully hidden
|
||||
if ( !container.Overlaps( bb ) ) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
auto* const dl{ GetWindowDrawList( ) };
|
||||
|
||||
// Add track display record
|
||||
const auto dTrackIdx{ dspTracks.size( ) };
|
||||
auto& dTrack{ dspTracks.addNew( ) };
|
||||
dTrack.id = id;
|
||||
dTrack.isOverride = false;
|
||||
dTrack.dispSegs = 0;
|
||||
dTrack.firstSeg = dspSegments.size( );
|
||||
dTrack.area = bb;
|
||||
|
||||
// Compute colors
|
||||
using namespace ImGui;
|
||||
const auto bgColor{ ColorHSVAToU32( hue , .25f , 1.f , .25f ) } ,
|
||||
borderColor{ ColorHSVAToU32( hue , .12f , 1.f , 1.f ) };
|
||||
borderColor{ ColorHSVAToU32( hue , .88f , 1.f , 1.f ) };
|
||||
const uint32_t segColors[ 2 ] = {
|
||||
ColorHSVAToU32( hue - .03f , .4f , 1.f , 1.f ) ,
|
||||
ColorHSVAToU32( hue + .03f , .4f , 1.f , 1.f ) ,
|
||||
|
@ -650,6 +725,7 @@ bool T_SyncViewImpl_::sequencerTrack(
|
|||
ImVec2{ ImFloor( bb.Max.x ) - 1 ,
|
||||
ImFloor( ImMin( container.Max.y , bb.Max.y ) ) }
|
||||
};
|
||||
auto* const dl{ GetWindowDrawList( ) };
|
||||
dl->AddRectFilled( bar.Min , bar.Max , bgColor );
|
||||
if ( container.Contains( bb.GetTL( ) ) ) {
|
||||
dl->AddLine( bar.GetTL( ) , bar.GetTR( ) , borderColor );
|
||||
|
@ -667,13 +743,6 @@ bool T_SyncViewImpl_::sequencerTrack(
|
|||
}
|
||||
dl->PushClipRect( bar.Min , bar.Max );
|
||||
|
||||
#if 0
|
||||
// We'll need to display the right pop-up
|
||||
auto& io( GetIO( ) );
|
||||
const auto mPos{ io.MousePos };
|
||||
bool mousePosUsed{ false } , mouseConsumed{ false };
|
||||
#endif
|
||||
|
||||
// If there's a curve, go through all segments
|
||||
const auto units{ Common::Sync( ).durationUnits( ) };
|
||||
const auto nSeg{ curve ? curve->segments.size( ) : 0u };
|
||||
|
@ -699,6 +768,17 @@ bool T_SyncViewImpl_::sequencerTrack(
|
|||
continue;
|
||||
}
|
||||
|
||||
// Add segment to displayed list
|
||||
auto dSegIdx{ dspSegments.size( ) };
|
||||
auto& dSeg{ dspSegments.addNew( ) };
|
||||
dSeg.area = segFull;
|
||||
dSeg.track = dTrackIdx;
|
||||
dSeg.seg = i;
|
||||
dSeg.dispPoints = 0;
|
||||
dSeg.firstPoint = dspPoints.size( );
|
||||
dTrack.dispSegs ++;
|
||||
|
||||
// Draw segment
|
||||
const ImRect segBar{
|
||||
ImVec2{ ImMax( bar.Min.x , segFull.Min.x ) , segFull.Min.y } ,
|
||||
ImVec2{ ImMin( bar.Max.x , segFull.Max.x ) , segFull.Max.y }
|
||||
|
@ -706,73 +786,147 @@ bool T_SyncViewImpl_::sequencerTrack(
|
|||
dl->AddRectFilled( segBar.Min , segBar.Max , color );
|
||||
dl->PushClipRect( segBar.Min , segBar.Max );
|
||||
|
||||
// Handle points
|
||||
const auto nd{ seg.durations.size( ) };
|
||||
const auto radius{ ( TrackHeight - 2.f ) * .5f };
|
||||
const auto ym{ bb.Min.y + radius + 1 };
|
||||
const auto ym{ bb.Min.y + PointRadius + 1 };
|
||||
auto cDur{ 0 };
|
||||
for ( auto j = 0u ; j < nd + 1 ; j ++ ) {
|
||||
const ImVec2 ctr{
|
||||
std::roundf( xStart + cDur * totalPixels / units ) ,
|
||||
ym
|
||||
};
|
||||
dl->AddCircleFilled( ctr , radius , 0x7f000000 ); // XXX color
|
||||
#if 0
|
||||
if ( ImLengthSqr( mPos - ctr ) <= radius * radius ) {
|
||||
if ( ! mousePosUsed ) {
|
||||
BeginTooltip( );
|
||||
stringBuffer.clear( ) << name << " (input)\nIn "
|
||||
<< seg.type << " segment\nAt " << segDur
|
||||
<< " units\nValue: " << seg.values[ j ];
|
||||
Text( "%s" , stringBuffer.data( ) );
|
||||
EndTooltip( );
|
||||
mousePosUsed = true;
|
||||
}
|
||||
if ( !mouseConsumed && io.MouseDown[ 0 ] ) {
|
||||
printf( "fuck yeah!\n" );
|
||||
mouseConsumed = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
dl->AddCircleFilled( ctr , PointRadius , 0x7f000000 ); // XXX color
|
||||
cDur += j < nd ? seg.durations[ j ] : 0;
|
||||
|
||||
// Add point record
|
||||
auto& dPoint{ dspPoints.addNew( ) };
|
||||
dPoint.center = ctr;
|
||||
dPoint.index = j;
|
||||
dPoint.mode =
|
||||
j == 0 ? T_TrackPointDisplay::START : (
|
||||
j == nd ? T_TrackPointDisplay::END :
|
||||
T_TrackPointDisplay::MIDDLE );
|
||||
dPoint.seg = dSegIdx;
|
||||
dSeg.dispPoints ++;
|
||||
}
|
||||
dl->PopClipRect( );
|
||||
|
||||
#if 0
|
||||
if ( segBar.Contains( mPos ) && !mousePosUsed ) {
|
||||
BeginTooltip( );
|
||||
stringBuffer.clear( ) << name << " (input)\nIn "
|
||||
<< seg.type << " segment\nDuration: "
|
||||
<< segDur << " units (from " << ( segStart - segDur )
|
||||
<< " to " << ( segStart - 1 )
|
||||
<< ")\n";
|
||||
Text( "%s" , stringBuffer.data( ) );
|
||||
EndTooltip( );
|
||||
mousePosUsed = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( bar.Contains( mPos ) && !mousePosUsed ) {
|
||||
const float time{ ( io.MousePos.x - container.Min.x + startPixel )
|
||||
* units / totalPixels };
|
||||
const float msf{ fmod( time , 1.f ) };
|
||||
const float sf{ fmod( time - msf , 60.f ) };
|
||||
char buffer[ 12 ];
|
||||
snprintf( buffer , sizeof( buffer ) , "%02d:%02d.%03d" ,
|
||||
uint32_t( ( time - msf - sf ) / 60.f ) ,
|
||||
uint32_t( sf ) , uint32_t( msf * 1000.f ) );
|
||||
BeginTooltip( );
|
||||
stringBuffer.clear( ) << name << " (input)\nNot defined at "
|
||||
<< buffer << '\0';
|
||||
Text( "%s" , stringBuffer.data( ) );
|
||||
EndTooltip( );
|
||||
mousePosUsed = true;
|
||||
}
|
||||
#endif
|
||||
dl->PopClipRect( );
|
||||
}
|
||||
|
||||
return false;
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
void T_SyncViewImpl_::displayTooltips(
|
||||
const float time ) noexcept
|
||||
{
|
||||
auto mp{ getMousePos( ) };
|
||||
if ( mp.type == E_MousePosType::NONE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Track / segment / point from mouse info
|
||||
auto const& track( [&](){
|
||||
if ( mp.type == E_MousePosType::POINT ) {
|
||||
return dspTracks[ dspSegments[
|
||||
dspPoints[ mp.index ].seg ].track ];
|
||||
}
|
||||
if ( mp.type == E_MousePosType::SEGMENT ) {
|
||||
return dspTracks[ dspSegments[ mp.index ].track ];
|
||||
}
|
||||
return dspTracks[ mp.index ];
|
||||
}() );
|
||||
auto const* const seg( [&]() -> T_TrackSegDisplay const* {
|
||||
if ( mp.type == E_MousePosType::TRACK ) {
|
||||
return nullptr;
|
||||
}
|
||||
if ( mp.type == E_MousePosType::SEGMENT ) {
|
||||
return &dspSegments[ mp.index ];
|
||||
}
|
||||
return &dspSegments[ dspPoints[ mp.index ].seg ];
|
||||
}() );
|
||||
auto const* const point( [&]() -> T_TrackPointDisplay const* {
|
||||
if ( mp.type != E_MousePosType::POINT ) {
|
||||
return nullptr;
|
||||
}
|
||||
return &dspPoints[ mp.index ];
|
||||
}() );
|
||||
|
||||
// Curve from track
|
||||
T_SyncCurve const* const curve{ Common::Sync( ).getCurve( track.id ) };
|
||||
assert( mp.type == E_MousePosType::TRACK || curve != nullptr );
|
||||
|
||||
// Time offset
|
||||
const float dTime( [&](){
|
||||
if ( point ) {
|
||||
auto tDur{ .0f };
|
||||
printf( "segseg %d\n" , seg->seg );
|
||||
for ( auto i = 0u ; i <= seg->seg ; i ++ ) {
|
||||
auto const& s{ curve->segments[ i ] };
|
||||
auto const nd{ i == seg->seg
|
||||
? point->index
|
||||
: s.durations.size( ) };
|
||||
printf( "s %d -> nd %d\n" , i , nd );
|
||||
for ( auto j = 0u ; j < nd ; j ++ ) {
|
||||
tDur += s.durations[ j ];
|
||||
}
|
||||
}
|
||||
return tDur * Common::Sync( ).durationUnitSize( );
|
||||
}
|
||||
return time;
|
||||
}() );
|
||||
char buffer[ 12 ];
|
||||
TimeToString_( buffer , sizeof( buffer ) , dTime );
|
||||
|
||||
const float value{ point ? curve->segments[ seg->seg ].values[ point->index ] : -.666f }; // FIXME
|
||||
|
||||
stringBuffer.clear( ) << track.id << " (input)\n";
|
||||
if ( mp.type == E_MousePosType::TRACK ) {
|
||||
stringBuffer << "No segment";
|
||||
} else {
|
||||
auto const& s{ curve->segments[ seg->seg ] };
|
||||
if ( mp.type == E_MousePosType::SEGMENT ) {
|
||||
stringBuffer << "Segment type: " << s.type;
|
||||
} else {
|
||||
stringBuffer << "On " << s.type << " segment, index " << point->index;
|
||||
}
|
||||
}
|
||||
stringBuffer << "\nTime: " << buffer << "\nValue: " << value;
|
||||
|
||||
using namespace ImGui;
|
||||
stringBuffer << '\0';
|
||||
BeginTooltip( );
|
||||
Text( "%s" , stringBuffer.data( ) );
|
||||
EndTooltip( );
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
T_SyncViewImpl_::T_MousePos T_SyncViewImpl_::getMousePos( ) const noexcept
|
||||
{
|
||||
auto const& mp{ ImGui::GetIO( ).MousePos };
|
||||
for ( auto i = 0u ; i < dspTracks.size( ) ; i ++ ) {
|
||||
auto const& track{ dspTracks[ i ] };
|
||||
if ( !track.area.Contains( mp ) ) {
|
||||
continue;
|
||||
}
|
||||
for ( auto j = 0u ; j < track.dispSegs ; j ++ ) {
|
||||
auto const& seg{ dspSegments[ track.firstSeg + j ] };
|
||||
if ( !seg.area.Contains( mp ) ) {
|
||||
continue;
|
||||
}
|
||||
for ( auto k = 0u ; k < seg.dispPoints ; k ++ ) {
|
||||
auto const& p{ dspPoints[ seg.firstPoint + k ] };
|
||||
if ( ImLengthSqr( mp - p.center ) <= PointRadiusSqr ) {
|
||||
return T_MousePos{ E_MousePosType::POINT ,
|
||||
seg.firstPoint + k };
|
||||
}
|
||||
}
|
||||
return T_MousePos{ E_MousePosType::SEGMENT , i };
|
||||
}
|
||||
return T_MousePos{ E_MousePosType::TRACK , i };
|
||||
}
|
||||
return T_MousePos{ E_MousePosType::NONE , 0 };
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in a new issue