Sequencer - Very primitive track display
There are pieces of disabled mouse handling code in the display code.
This commit is contained in:
parent
aa84f95727
commit
2cfc80a6e4
3 changed files with 220 additions and 20 deletions
218
ui-sequencer.cc
218
ui-sequencer.cc
|
@ -135,8 +135,10 @@ bool T_ChangeDurationDialog_::onButton(
|
||||||
|
|
||||||
struct T_SyncViewImpl_
|
struct T_SyncViewImpl_
|
||||||
{
|
{
|
||||||
static constexpr float SeqHeaderHeight = 24;
|
static constexpr float SeqHeaderHeight = 24.f;
|
||||||
static constexpr float BarWidth = 40;
|
static constexpr float BarWidth = 40.f;
|
||||||
|
static constexpr float TrackHeight = 15.f;
|
||||||
|
static constexpr float TrackPadding = 2.f;
|
||||||
|
|
||||||
bool display( ) noexcept;
|
bool display( ) noexcept;
|
||||||
|
|
||||||
|
@ -148,9 +150,17 @@ struct T_SyncViewImpl_
|
||||||
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;
|
||||||
void sequencerBody( ImRect const& bb ) noexcept;
|
bool sequencerBody( ImRect const& bb ) noexcept;
|
||||||
void sequencerCurves( ) noexcept;
|
bool sequencerTracks(
|
||||||
void sequencerCurve( T_SyncCurve const& curve ) noexcept;
|
float& hue ,
|
||||||
|
ImRect& bb ,
|
||||||
|
ImRect const& container ) noexcept;
|
||||||
|
bool sequencerTrack(
|
||||||
|
float& hue ,
|
||||||
|
ImRect const& bb ,
|
||||||
|
ImRect const& container ,
|
||||||
|
T_String const& name ,
|
||||||
|
T_SyncCurve const* curve ) noexcept;
|
||||||
|
|
||||||
void displayCurveSelectorWindow( ) noexcept;
|
void displayCurveSelectorWindow( ) noexcept;
|
||||||
void displayCurveSelector( ) noexcept;
|
void displayCurveSelector( ) noexcept;
|
||||||
|
@ -225,12 +235,9 @@ bool T_SyncViewImpl_::display( ) noexcept
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Sequencer widget & subwindows
|
// Sequencer widget & subwindows
|
||||||
|
|
||||||
BeginChild( "##sequencer" , ImVec2{ 0 , 0 } , false ,
|
|
||||||
ImGuiWindowFlags_NoScrollWithMouse );
|
|
||||||
PushItemWidth( -1 );
|
PushItemWidth( -1 );
|
||||||
sequencerWidget( );
|
sequencerWidget( );
|
||||||
PopItemWidth( );
|
PopItemWidth( );
|
||||||
EndChild( );
|
|
||||||
End( );
|
End( );
|
||||||
|
|
||||||
switch ( sub ) {
|
switch ( sub ) {
|
||||||
|
@ -380,12 +387,17 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
|
||||||
sequencerHeader( bbHeader );
|
sequencerHeader( bbHeader );
|
||||||
PopID( );
|
PopID( );
|
||||||
}
|
}
|
||||||
|
bool mouseConsumed{ false };
|
||||||
if ( bbDisplay.Min.y < bbDisplay.Max.y && ItemAdd( bbDisplay , dspId ) ) {
|
if ( bbDisplay.Min.y < bbDisplay.Max.y && ItemAdd( bbDisplay , dspId ) ) {
|
||||||
PushID( dspId );
|
PushID( dspId );
|
||||||
sequencerBody( bbDisplay );
|
mouseConsumed = sequencerBody( bbDisplay );
|
||||||
PopID( );
|
PopID( );
|
||||||
}
|
}
|
||||||
PopID( );
|
PopID( );
|
||||||
|
if ( mouseConsumed ) {
|
||||||
|
EndGroup( );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& io( GetIO( ) );
|
auto& io( GetIO( ) );
|
||||||
if ( hovered && ( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
if ( hovered && ( io.MouseDown[ 0 ] || io.MouseDown[ 1 ] ) ) {
|
||||||
|
@ -528,7 +540,7 @@ void T_SyncViewImpl_::sequencerHeader(
|
||||||
PopFont( );
|
PopFont( );
|
||||||
}
|
}
|
||||||
|
|
||||||
void T_SyncViewImpl_::sequencerBody(
|
bool T_SyncViewImpl_::sequencerBody(
|
||||||
ImRect const& bb ) noexcept
|
ImRect const& bb ) noexcept
|
||||||
{
|
{
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
|
@ -562,11 +574,18 @@ void T_SyncViewImpl_::sequencerBody(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the curve / override controls
|
// Display the curve / override controls
|
||||||
|
bool mouseConsumed{ false };
|
||||||
if ( sCurves.size( ) != 0 ) {
|
if ( sCurves.size( ) != 0 ) {
|
||||||
BeginGroup( );
|
|
||||||
|
ImRect subBb{ inner };
|
||||||
|
// FIXME scroll
|
||||||
|
subBb.Min.y += TrackPadding;
|
||||||
|
subBb.Max.y = subBb.Min.y + TrackHeight;
|
||||||
|
|
||||||
|
float hue{ 0.12f };
|
||||||
|
|
||||||
// TODO: display overrides
|
// TODO: display overrides
|
||||||
sequencerCurves( );
|
mouseConsumed = sequencerTracks( hue , subBb , inner ) || mouseConsumed;
|
||||||
EndGroup( );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cursorPos >= 0 && cursorPos <= inner.GetWidth( ) ) {
|
if ( cursorPos >= 0 && cursorPos <= inner.GetWidth( ) ) {
|
||||||
|
@ -575,26 +594,185 @@ void T_SyncViewImpl_::sequencerBody(
|
||||||
ImVec2{ inner.Min.x + cursorPos , inner.Max.y - 1 } ,
|
ImVec2{ inner.Min.x + cursorPos , inner.Max.y - 1 } ,
|
||||||
0xffffffff );
|
0xffffffff );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mouseConsumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void T_SyncViewImpl_::sequencerCurves( ) noexcept
|
bool T_SyncViewImpl_::sequencerTracks(
|
||||||
|
float& hue ,
|
||||||
|
ImRect& subBb ,
|
||||||
|
ImRect const& container ) noexcept
|
||||||
{
|
{
|
||||||
auto& sync{ Common::Sync( ) };
|
auto& sync{ Common::Sync( ) };
|
||||||
const auto nc{ sCurves.size( ) };
|
const auto nc{ sCurves.size( ) };
|
||||||
|
bool mouseConsumed{ false };
|
||||||
for ( auto i = 0u ; i < nc ; i ++ ) {
|
for ( auto i = 0u ; i < nc ; i ++ ) {
|
||||||
if ( sCurves.values( )[ i ] ) {
|
if ( sCurves.values( )[ i ] ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto* const curve{ sync.getCurve( sCurves.keys( )[ i ] ) };
|
|
||||||
assert( curve );
|
auto const& name{ sCurves.keys( )[ i ] };
|
||||||
sequencerCurve( *curve );
|
auto* const curve{ sync.getCurve( name ) };
|
||||||
|
mouseConsumed = sequencerTrack( hue , subBb , container , name , curve )
|
||||||
|
|| mouseConsumed;
|
||||||
|
subBb.Min.y += TrackHeight + 2 * TrackPadding;
|
||||||
|
subBb.Max.y += TrackHeight + 2 * TrackPadding;
|
||||||
|
hue = fmodf( hue + .17f , 1.f );
|
||||||
}
|
}
|
||||||
|
return mouseConsumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void T_SyncViewImpl_::sequencerCurve(
|
bool T_SyncViewImpl_::sequencerTrack(
|
||||||
T_SyncCurve const& curve ) noexcept
|
float& hue ,
|
||||||
|
ImRect const& bb ,
|
||||||
|
ImRect const& container ,
|
||||||
|
T_String const& name ,
|
||||||
|
T_SyncCurve const* curve ) noexcept
|
||||||
{
|
{
|
||||||
#warning implement the fuck
|
using namespace ImGui;
|
||||||
|
if ( !container.Overlaps( bb ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto* const dl{ GetWindowDrawList( ) };
|
||||||
|
|
||||||
|
// Compute colors
|
||||||
|
const auto bgColor{ ColorHSVAToU32( hue , .25f , 1.f , .25f ) } ,
|
||||||
|
borderColor{ ColorHSVAToU32( hue , .12f , 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 ) ,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw the bar itself
|
||||||
|
const ImRect bar{
|
||||||
|
ImVec2{ ImFloor( bb.Min.x ) ,
|
||||||
|
ImFloor( ImMax( container.Min.y , bb.Min.y ) ) } ,
|
||||||
|
ImVec2{ ImFloor( bb.Max.x ) - 1 ,
|
||||||
|
ImFloor( ImMin( container.Max.y , bb.Max.y ) ) }
|
||||||
|
};
|
||||||
|
dl->AddRectFilled( bar.Min , bar.Max , bgColor );
|
||||||
|
if ( container.Contains( bb.GetTL( ) ) ) {
|
||||||
|
dl->AddLine( bar.GetTL( ) , bar.GetTR( ) , borderColor );
|
||||||
|
}
|
||||||
|
if ( container.Contains( bb.GetBL( ) ) ) {
|
||||||
|
dl->AddLine( bar.GetBL( ) , bar.GetBR( ) , borderColor );
|
||||||
|
}
|
||||||
|
// Left only has a border if this is the start
|
||||||
|
if ( startPos == 0.f ) {
|
||||||
|
dl->AddLine( bar.GetTL( ) , bar.GetBL( ) , borderColor );
|
||||||
|
}
|
||||||
|
// Right has a border if the end is being displayed.
|
||||||
|
if ( startPixel + container.GetWidth( ) >= totalPixels ) {
|
||||||
|
dl->AddLine( bar.GetTR( ) , bar.GetBR( ) , borderColor );
|
||||||
|
}
|
||||||
|
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 };
|
||||||
|
uint32_t segStart{ 0 };
|
||||||
|
for ( auto i = 0u ; i < nSeg ; i ++ ) {
|
||||||
|
const auto color{ segColors[ i % 2 ] };
|
||||||
|
auto const& seg{ curve->segments[ i ] };
|
||||||
|
const auto segDur{ [&](){
|
||||||
|
auto t{ 0u };
|
||||||
|
for ( auto d : seg.durations ) {
|
||||||
|
t += d;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}() };
|
||||||
|
const float xStart{ ImFloor( container.Min.x + ( segStart - startPos ) * totalPixels / units ) };
|
||||||
|
const float xEnd{ xStart + ImFloor( segDur * totalPixels / units ) };
|
||||||
|
const ImRect segFull{
|
||||||
|
ImVec2{ xStart , bar.Min.y + 1 } ,
|
||||||
|
ImVec2{ xEnd , bar.Max.y }
|
||||||
|
};
|
||||||
|
segStart += segDur;
|
||||||
|
if ( !segFull.Overlaps( bar ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 }
|
||||||
|
};
|
||||||
|
dl->AddRectFilled( segBar.Min , segBar.Max , color );
|
||||||
|
dl->PushClipRect( segBar.Min , segBar.Max );
|
||||||
|
|
||||||
|
const auto nd{ seg.durations.size( ) };
|
||||||
|
const auto radius{ ( TrackHeight - 2.f ) * .5f };
|
||||||
|
const auto ym{ bb.Min.y + radius + 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
|
||||||
|
cDur += j < nd ? seg.durations[ j ] : 0;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -60,6 +60,20 @@ void ImGui::ToolbarSeparator( ) noexcept
|
||||||
SameLine( );
|
SameLine( );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
uint32_t ImGui::ColorHSVAToU32(
|
||||||
|
float hue ,
|
||||||
|
float saturation ,
|
||||||
|
float value ,
|
||||||
|
float alpha ) noexcept
|
||||||
|
{
|
||||||
|
ImVec4 out{ 0, 0, 0, alpha };
|
||||||
|
ColorConvertHSVtoRGB( hue , saturation , value ,
|
||||||
|
out.x , out.y , out.z );
|
||||||
|
return GetColorU32( out );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*= T_CameraMouseControl =======================================================*/
|
/*= T_CameraMouseControl =======================================================*/
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,14 @@ namespace ImGui {
|
||||||
char const* const tooltip = nullptr ,
|
char const* const tooltip = nullptr ,
|
||||||
bool enabled = true ) noexcept;
|
bool enabled = true ) noexcept;
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
uint32_t ColorHSVAToU32(
|
||||||
|
float hue ,
|
||||||
|
float saturation ,
|
||||||
|
float value ,
|
||||||
|
float alpha ) noexcept;
|
||||||
|
|
||||||
} // namespace ImGui
|
} // namespace ImGui
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
Loading…
Reference in a new issue