Sequencer - Edit demo duration
This commit is contained in:
parent
5445021664
commit
bd8eb2ff02
6 changed files with 275 additions and 32 deletions
1
TODO
1
TODO
|
@ -37,7 +37,6 @@ Sync / inputs:
|
|||
* Value changes
|
||||
* Duration changes
|
||||
* Point insertion
|
||||
* Total duration / duration unit changes
|
||||
* Compaction
|
||||
* Local changes vs file update
|
||||
* Editing single values
|
||||
|
|
11
main.cc
11
main.cc
|
@ -10,8 +10,7 @@
|
|||
#include "rendertarget.hh"
|
||||
#include "sync.hh"
|
||||
#include "syncview.hh"
|
||||
|
||||
using ebcl::T_Optional;
|
||||
#include "undo.hh"
|
||||
|
||||
|
||||
/*= T_Main ===================================================================*/
|
||||
|
@ -205,9 +204,17 @@ void T_Main::handleCapture( )
|
|||
void T_Main::makeUI( )
|
||||
{
|
||||
using namespace ImGui;
|
||||
auto& undo( Globals::Undo( ) );
|
||||
bool eSequencer{ sequencer };
|
||||
if ( BeginMainMenuBar( ) ) {
|
||||
if ( BeginMenu( "File" ) ) {
|
||||
if ( MenuItem( "Undo" , "C-z" , false , undo.canUndo( ) ) ) {
|
||||
undo.undo( );
|
||||
}
|
||||
if ( MenuItem( "Redo" , "C-Z" , false , undo.canRedo( ) ) ) {
|
||||
undo.redo( );
|
||||
}
|
||||
Separator( );
|
||||
if ( MenuItem( "Quit" ) ) {
|
||||
done = true;
|
||||
}
|
||||
|
|
3
sync.hh
3
sync.hh
|
@ -348,6 +348,9 @@ struct T_SyncManager : public virtual A_MouseCtrl
|
|||
void setCurve( T_SyncCurve curve );
|
||||
void removeCurve( T_String const& curve ) noexcept;
|
||||
|
||||
T_Array< T_SyncCurve > const& curves( ) const noexcept
|
||||
{ return curves_.curves.values( ); }
|
||||
|
||||
private:
|
||||
void curvesChanged_( );
|
||||
bool loadCurves_( bool& missing );
|
||||
|
|
92
syncedit.cc
92
syncedit.cc
|
@ -3,7 +3,7 @@
|
|||
#include "globals.hh"
|
||||
|
||||
|
||||
/*= T_UndoSyncChanges ==========================================================*/
|
||||
/*= T_UndoSyncChanges ========================================================*/
|
||||
|
||||
void T_UndoSyncChanges::undo( ) const noexcept
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ void T_UndoSyncChanges::redo( ) const noexcept
|
|||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
T_UndoSyncChanges& T_UndoSyncChanges::curveCreation(
|
||||
T_SyncCurve curve ) noexcept
|
||||
|
@ -81,3 +81,91 @@ T_UndoSyncChanges& T_UndoSyncChanges::curveReplacement(
|
|||
changes_.addNew( std::move( before ) , std::move( after ) );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*= T_UndoDurationChanges ====================================================*/
|
||||
|
||||
T_UndoDurationChanges::T_UndoDurationChanges(
|
||||
const uint32_t units ,
|
||||
const uint32_t oldUnits ,
|
||||
const float unitSize ,
|
||||
const float oldUnitSize ) noexcept
|
||||
: T_UndoSyncChanges( ) ,
|
||||
unitsBefore_{ oldUnits } ,
|
||||
unitsAfter_{ units } ,
|
||||
uSizeBefore_{ oldUnitSize } ,
|
||||
uSizeAfter_{ unitSize }
|
||||
{ }
|
||||
|
||||
void T_UndoDurationChanges::undo( ) const noexcept
|
||||
{
|
||||
Globals::Sync( ).setDuration( uSizeBefore_ , unitsBefore_ );
|
||||
T_UndoSyncChanges::undo( );
|
||||
}
|
||||
|
||||
void T_UndoDurationChanges::redo( ) const noexcept
|
||||
{
|
||||
Globals::Sync( ).setDuration( uSizeAfter_ , unitsAfter_ );
|
||||
T_UndoSyncChanges::redo( );
|
||||
}
|
||||
|
||||
|
||||
/*= SyncEditor ===============================================================*/
|
||||
|
||||
namespace {
|
||||
|
||||
T_SyncCurve SESDScaleCurve_(
|
||||
const float uSizeBefore ,
|
||||
const float uSizeAfter ,
|
||||
T_SyncCurve const& curve ) noexcept
|
||||
{
|
||||
T_SyncCurve nCurve;
|
||||
nCurve.name = curve.name;
|
||||
for ( auto const& segment : curve.segments ) {
|
||||
const auto nsid{ nCurve.segments.add( segment ) };
|
||||
T_SyncSegment& nSeg{ nCurve.segments[ nsid ] };
|
||||
const auto nd{ nSeg.durations.size( ) };
|
||||
for ( auto i = 0u ; i < nd ; i ++ ) {
|
||||
const float duration{ nSeg.durations[ i ] * uSizeBefore };
|
||||
nSeg.durations[ i ] = std::max( 1u , uint32_t( std::roundf(
|
||||
duration / uSizeAfter ) ) );
|
||||
printf( "initial duration %f (%d units) ; new duration %f (%d units)\n" ,
|
||||
duration , segment.durations[ i ] ,
|
||||
uSizeAfter * nSeg.durations[ i ] ,
|
||||
nSeg.durations[ i ] );
|
||||
}
|
||||
}
|
||||
return nCurve;
|
||||
}
|
||||
|
||||
} // namespace <anon>
|
||||
|
||||
void SyncEditor::SetDuration(
|
||||
const uint32_t units ,
|
||||
const float uSize ,
|
||||
const bool scaleCurves ) noexcept
|
||||
{
|
||||
auto& sync{ Globals::Sync( ) };
|
||||
const float oldUnitSize{ sync.durationUnitSize( ) };
|
||||
const uint32_t oldUnits{ sync.durationUnits( ) };
|
||||
if ( oldUnits == units && oldUnitSize == uSize ) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& undo{ dynamic_cast< T_UndoDurationChanges& >(
|
||||
Globals::Undo( ).add< T_UndoDurationChanges >(
|
||||
units , oldUnits ,
|
||||
uSize , oldUnitSize ) ) };
|
||||
sync.setDuration( uSize , units );
|
||||
if ( !scaleCurves || uSize == oldUnitSize ) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto const& curves( sync.curves( ) );
|
||||
for ( auto const& curve : curves ) {
|
||||
auto nc{ SESDScaleCurve_( oldUnitSize , uSize , curve ) };
|
||||
undo.curveReplacement( curve , nc );
|
||||
sync.setCurve( std::move( nc ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
41
syncedit.hh
41
syncedit.hh
|
@ -3,7 +3,7 @@
|
|||
#include "undo.hh"
|
||||
|
||||
|
||||
/*= GENERAL STRUCTURE FOR SYNC EDITOR UNDOS ====================================*/
|
||||
/*= GENERAL STRUCTURE FOR SYNC EDITOR UNDOS ==================================*/
|
||||
|
||||
class T_UndoSyncChanges : public A_UndoAction
|
||||
{
|
||||
|
@ -51,3 +51,42 @@ class T_UndoSyncChanges : public A_UndoAction
|
|||
T_SyncCurve before ,
|
||||
T_SyncCurve after ) noexcept;
|
||||
};
|
||||
|
||||
|
||||
/*= DURATION CHANGES =========================================================*/
|
||||
|
||||
class T_UndoDurationChanges final : public T_UndoSyncChanges
|
||||
{
|
||||
private:
|
||||
uint32_t unitsBefore_ , unitsAfter_;
|
||||
float uSizeBefore_ , uSizeAfter_;
|
||||
|
||||
public:
|
||||
T_UndoDurationChanges(
|
||||
uint32_t units ,
|
||||
uint32_t oldUnits ,
|
||||
float unitSize ,
|
||||
float oldUnitSize ) noexcept;
|
||||
|
||||
T_UndoDurationChanges( ) noexcept = delete;
|
||||
DEF_MOVE( T_UndoDurationChanges );
|
||||
NO_COPY( T_UndoDurationChanges );
|
||||
|
||||
void undo( ) const noexcept override;
|
||||
void redo( ) const noexcept override;
|
||||
};
|
||||
|
||||
|
||||
/*= EDITION FUNCTIONS ========================================================*/
|
||||
|
||||
struct SyncEditor final
|
||||
{
|
||||
// Change the duration of the demo using the specified unit count and
|
||||
// size. If scaleCurves is true and the unit size has changed, the
|
||||
// curves' durations will be scaled so that the timings match as
|
||||
// closely as possible.
|
||||
static void SetDuration(
|
||||
uint32_t units ,
|
||||
float uSize ,
|
||||
bool scaleCurves ) noexcept;
|
||||
};
|
||||
|
|
159
syncview.cc
159
syncview.cc
|
@ -2,38 +2,130 @@
|
|||
#include "syncview.hh"
|
||||
#include "globals.hh"
|
||||
#include "window.hh"
|
||||
#include "syncedit.hh"
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <imgui_internal.h>
|
||||
|
||||
using namespace ebcl;
|
||||
|
||||
/*= FAKE TABS HELPER ===========================================================*/
|
||||
|
||||
namespace {
|
||||
bool FakeTab_(
|
||||
char const* const name ,
|
||||
const bool disabled ,
|
||||
const float width = 0.f )
|
||||
{
|
||||
using namespace ImGui;
|
||||
if ( disabled ) {
|
||||
PushItemFlag( ImGuiItemFlags_Disabled , true );
|
||||
PushStyleVar( ImGuiStyleVar_Alpha ,
|
||||
GetStyle( ).Alpha * .5f );
|
||||
}
|
||||
const bool rv( Button( name , ImVec2{ width , 0.f } ) );
|
||||
if ( disabled ) {
|
||||
PopItemFlag( );
|
||||
PopStyleVar( );
|
||||
}
|
||||
return rv;
|
||||
|
||||
/*= FAKE TABS HELPER =========================================================*/
|
||||
|
||||
bool FakeTab_(
|
||||
char const* const name ,
|
||||
const bool disabled ,
|
||||
const float width = 0.f )
|
||||
{
|
||||
using namespace ImGui;
|
||||
if ( disabled ) {
|
||||
PushItemFlag( ImGuiItemFlags_Disabled , true );
|
||||
PushStyleVar( ImGuiStyleVar_Alpha ,
|
||||
GetStyle( ).Alpha * .5f );
|
||||
}
|
||||
} // namespace <anon>
|
||||
const bool rv( Button( name , ImVec2{ width , 0.f } ) );
|
||||
if ( disabled ) {
|
||||
PopItemFlag( );
|
||||
PopStyleVar( );
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*= T_SyncViewImpl_ ============================================================*/
|
||||
namespace {
|
||||
/*= T_ChangeDurationDialog_ ==================================================*/
|
||||
|
||||
class T_ChangeDurationDialog_ : public A_ModalDialog
|
||||
{
|
||||
private:
|
||||
const uint32_t units0_;
|
||||
const float uSize0_;
|
||||
const uint32_t uPerMinute0_;
|
||||
uint32_t units_;
|
||||
float uSize_;
|
||||
uint32_t uPerMinute_;
|
||||
bool scale_{ true };
|
||||
|
||||
protected:
|
||||
bool drawDialog( ) noexcept override;
|
||||
void onOK( ) noexcept override;
|
||||
|
||||
public:
|
||||
T_ChangeDurationDialog_(
|
||||
uint32_t units ,
|
||||
float uSize ) noexcept;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
T_ChangeDurationDialog_::T_ChangeDurationDialog_(
|
||||
const uint32_t units ,
|
||||
const float uSize ) noexcept
|
||||
: A_ModalDialog{ "Set demo duration...##duration-dialog" } ,
|
||||
units0_{ units } , uSize0_{ std::max( 1.f / 60.f , uSize ) } ,
|
||||
uPerMinute0_{ uint32_t( ImClamp( roundf( 60.f / uSize0_ ) , 1.f , 3600.f ) ) } ,
|
||||
units_{ units0_ } , uSize_{ uSize0_ } , uPerMinute_{ uPerMinute0_ }
|
||||
{
|
||||
setInitialSize( 300.f , 180.f );
|
||||
}
|
||||
|
||||
bool T_ChangeDurationDialog_::drawDialog( ) noexcept
|
||||
{
|
||||
using namespace ImGui;
|
||||
|
||||
int tUnits( units_ );
|
||||
if ( DragInt( "Duration##units" , &tUnits , .1f , 1 , INT32_MAX , "%.0f unit(s)" ) ) {
|
||||
units_ = uint32_t( std::min( INT32_MAX , std::max( 1 , tUnits ) ) );
|
||||
}
|
||||
|
||||
float tDuration( units_ * uSize_ );
|
||||
if ( DragFloat( "##seconds" , &tDuration , 1.f , .001f , FLT_MAX , "%.3f second(s)" ) ) {
|
||||
units_ = std::min( uint32_t( INT32_MAX ) , std::max( 1u ,
|
||||
uint32_t( roundf( tDuration / uSize_ ) ) ) );
|
||||
}
|
||||
|
||||
Separator( );
|
||||
|
||||
int tUsize( floorf( uSize_ * 1000.f ) );
|
||||
if ( SliderInt( "Units" , &tUsize , 16 , 2000 , "%.0f ms" ) ) {
|
||||
const float pDur{ uSize_ * units_ };
|
||||
uSize_ = std::min( 2.f , std::max( 1.f / 60.f ,
|
||||
.001f * tUsize ) );
|
||||
uPerMinute_ = roundf( 60.f / uSize_ );
|
||||
units_ = uint32_t( roundf( pDur / uSize_ ) );
|
||||
}
|
||||
|
||||
int tPerMin( uPerMinute_ );
|
||||
if ( SliderInt( "Units/minute" , &tPerMin , 30 , 3600 ) ) {
|
||||
const float pDur{ uSize_ * units_ };
|
||||
uPerMinute_ = std::max( 30u , std::min( 3600u , uint32_t( tPerMin ) ) );
|
||||
uSize_ = 60.f / uPerMinute_;
|
||||
units_ = uint32_t( roundf( pDur / uSize_ ) );
|
||||
}
|
||||
|
||||
if ( uPerMinute0_ == uPerMinute_ ) {
|
||||
PushItemFlag( ImGuiItemFlags_Disabled , true );
|
||||
PushStyleVar( ImGuiStyleVar_Alpha ,
|
||||
GetStyle( ).Alpha * .5f );
|
||||
}
|
||||
Checkbox( "Scale curves" , &scale_ );
|
||||
if ( uPerMinute0_ == uPerMinute_ ) {
|
||||
PopItemFlag( );
|
||||
PopStyleVar( );
|
||||
}
|
||||
|
||||
return units_ != units0_ || uPerMinute_ != uPerMinute0_;
|
||||
}
|
||||
|
||||
void T_ChangeDurationDialog_::onOK( ) noexcept
|
||||
{
|
||||
SyncEditor::SetDuration( units_ ,
|
||||
uPerMinute_ != uPerMinute0_ ? uSize_ : uSize0_ ,
|
||||
scale_ );
|
||||
}
|
||||
|
||||
|
||||
/*= T_SyncViewImpl_ ==========================================================*/
|
||||
|
||||
struct T_SyncViewImpl_
|
||||
{
|
||||
|
@ -94,7 +186,7 @@ struct T_SyncViewImpl_
|
|||
|
||||
constexpr float T_SyncViewImpl_::BarWidth;
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
bool T_SyncViewImpl_::display( ) noexcept
|
||||
{
|
||||
|
@ -168,6 +260,20 @@ bool T_SyncViewImpl_::display( ) noexcept
|
|||
VerticalSeparator( );
|
||||
SameLine( );
|
||||
|
||||
if ( Button( ICON_FA_CLOCK_O , BtSize ) ) {
|
||||
Globals::Window( ).pushDialog( NewOwned< T_ChangeDurationDialog_ >(
|
||||
sync.durationUnits( ) , sync.durationUnitSize( ) ) );
|
||||
}
|
||||
if ( IsItemHovered( ) ) {
|
||||
BeginTooltip( );
|
||||
Text( "Change duration and time units." );
|
||||
EndTooltip( );
|
||||
}
|
||||
|
||||
SameLine( );
|
||||
VerticalSeparator( );
|
||||
SameLine( );
|
||||
|
||||
if ( Button( ICON_FA_LINE_CHART ) ) {
|
||||
const bool displaySelector{ sub == SW_CURVE_SELECTOR
|
||||
|| sub == SW_OVERRIDE_SELECTOR };
|
||||
|
@ -425,7 +531,7 @@ void T_SyncViewImpl_::sequencerBody(
|
|||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
void T_SyncViewImpl_::displayCurveSelectorWindow( ) noexcept
|
||||
{
|
||||
|
@ -597,9 +703,10 @@ void T_SyncViewImpl_::displayOverrideSelector( ) noexcept
|
|||
EndChild( );
|
||||
}
|
||||
|
||||
} // namespace <anon>
|
||||
|
||||
} // namespace
|
||||
/*= T_SyncView =================================================================*/
|
||||
|
||||
/*= T_SyncView ===============================================================*/
|
||||
|
||||
T_SyncView::T_SyncView( ) noexcept
|
||||
: A_PrivateImplementation( new T_SyncViewImpl_( ) )
|
||||
|
|
Loading…
Reference in a new issue