1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-15 15:49:36 +02:00

TrackShifters decide what parts move or stay fixed...

... for now redundantly with the older logic.

Also shorten a function name to Init
This commit is contained in:
Paul Licameli 2020-09-11 11:44:55 -04:00
parent c279fb6588
commit eb22892064
5 changed files with 130 additions and 8 deletions

View File

@ -654,7 +654,7 @@ double DoClipMove
track->GetSelected() && !selectedRegion.isPoint();
state.trackExclusions.clear();
TimeShiftHandle::CreateListOfCapturedClips(
TimeShiftHandle::Init(
state, viewInfo, *track, trackList, syncLocked, t0 );
auto desiredT0 = viewInfo.OffsetTimeByPixels( t0, ( right ? 1 : -1 ) );

View File

@ -741,12 +741,19 @@ public:
}
~NoteTrackShifter() override {}
Track &GetTrack() const override { return *mpTrack; }
HitTestResult HitTest( double ) override
{
return HitTestResult::Intervals;
}
void SelectInterval( const TrackInterval &interval ) override
{
CommonSelectInterval( interval );
}
bool SyncLocks() override { return true; }
private:
std::shared_ptr<NoteTrack> mpTrack;
};

View File

@ -1329,6 +1329,21 @@ public:
return HitTestResult::Intervals;
}
void SelectInterval( const TrackInterval &interval ) override
{
UnfixIntervals( [&](auto &myInterval){
// Use a slightly different test from CommonSelectInterval, rounding times
// to exact samples according to the clip's rate
auto data =
static_cast<WaveTrack::IntervalData*>( myInterval.Extra() );
auto clip = data->GetClip().get();
return !(clip->IsClipStartAfterClip(interval.Start()) ||
clip->BeforeClip(interval.End()));
});
}
bool SyncLocks() override { return true; }
private:
std::shared_ptr<WaveTrack> mpTrack;
};

View File

@ -265,6 +265,19 @@ void TrackShifter::UnfixAll()
mFixed = Intervals{};
}
void TrackShifter::SelectInterval( const TrackInterval & )
{
UnfixAll();
}
void TrackShifter::CommonSelectInterval(const TrackInterval &interval)
{
UnfixIntervals( [&](auto &myInterval){
return !(interval.End() < myInterval.Start() ||
myInterval.End() < interval.Start());
});
}
void TrackShifter::InitIntervals()
{
mMoving.clear();
@ -284,15 +297,21 @@ auto CoarseTrackShifter::HitTest( double ) -> HitTestResult
return HitTestResult::Track;
}
bool CoarseTrackShifter::SyncLocks()
{
return false;
}
template<> auto MakeTrackShifter::Implementation() -> Function {
return [](Track &track) {
return std::make_unique<CoarseTrackShifter>(track);
};
}
void TimeShiftHandle::CreateListOfCapturedClips
void TimeShiftHandle::Init
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
TrackList &trackList, bool syncLocked, double clickTime )
TrackList &trackList, bool syncLocked, double clickTime,
bool capturedAClip )
{
// The captured clip is the focus, but we need to create a list
// of all clips that have to move, also...
@ -302,9 +321,11 @@ void TimeShiftHandle::CreateListOfCapturedClips
// First, if click was in selection, capture selected clips; otherwise
// just the clicked-on clip
if ( state.capturedClipIsSelection )
// All selected tracks may move some intervals
for (auto t : trackList.Selected())
AddClipsToCaptured( state, viewInfo, t );
else {
// Move intervals only of the chosen channel group
state.capturedClipArray.push_back
(TrackClip( &capturedTrack, state.capturedClip ));
@ -320,6 +341,7 @@ void TimeShiftHandle::CreateListOfCapturedClips
// Now, if sync-lock is enabled, capture any clip that's linked to a
// captured clip.
if ( syncLocked ) {
// Sync lock propagation of unfixing of intervals
// AWD: capturedClipArray expands as the loop runs, so newly-added
// clips are considered (the effect is like recursion and terminates
// because AddClipsToCaptured doesn't add duplicate clips); to remove
@ -351,6 +373,70 @@ void TimeShiftHandle::CreateListOfCapturedClips
#endif
}
}
// Analogy of the steps above, but with TrackShifters, follows below
if ( state.capturedClipIsSelection ) {
// All selected tracks may move some intervals
const TrackInterval interval{
viewInfo.selectedRegion.t0(),
viewInfo.selectedRegion.t1()
};
for ( const auto &pair : state.shifters ) {
auto &shifter = *pair.second;
auto &track = shifter.GetTrack();
if ( track.IsSelected() )
shifter.SelectInterval( interval );
}
}
else {
// Move intervals only of the chosen channel group
for ( auto channel : TrackList::Channels( &capturedTrack ) ) {
auto &shifter = *state.shifters[channel];
if ( capturedAClip ) {
if ( channel != &capturedTrack )
shifter.SelectInterval(TrackInterval{clickTime, clickTime});
}
else
shifter.UnfixAll();
}
}
// Sync lock propagation of unfixing of intervals
if ( syncLocked ) {
bool change = true;
while( change ) {
change = false;
// Iterate over all unfixed intervals in all shifters
// that do propagation...
for ( auto &pair : state.shifters ) {
auto &shifter = *pair.second.get();
if (!shifter.SyncLocks())
continue;
auto &track = shifter.GetTrack();
auto &intervals = shifter.MovingIntervals();
for (auto &interval : intervals) {
// ...and tell all other tracks to select that interval...
for ( auto &pair2 : state.shifters ) {
auto &shifter2 = *pair2.second.get();
if (&shifter2.GetTrack() == &track)
continue;
auto size = shifter2.MovingIntervals().size();
shifter2.SelectInterval( interval );
change = change ||
(shifter2.SyncLocks() &&
size != shifter2.MovingIntervals().size());
}
}
}
// ... and repeat if any other interval became unfixed in a
// shifter that propagates
}
}
}
void TimeShiftHandle::DoSlideHorizontal
@ -542,9 +628,9 @@ UIHandle::Result TimeShiftHandle::Click
pShifter = MakeTrackShifter::Call( *track );
}
CreateListOfCapturedClips(
Init(
mClipMoveState, viewInfo, *pTrack, trackList,
ProjectSettings::Get( *pProject ).IsSyncLocked(), clickTime );
ProjectSettings::Get( *pProject ).IsSyncLocked(), clickTime, capturedAClip );
}
mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive;

View File

@ -58,7 +58,17 @@ public:
//! Change all intervals from fixed to moving
void UnfixAll();
//! Notifies the shifter that a region is selected, so it may update its fixed and moving intervals
/*! Default behavior: if any part of the track is selected, unfix all parts of it. */
virtual void SelectInterval( const TrackInterval &interval );
//! Whether unfixing of an interval should propagate to all overlapping intervals in the sync lock group
virtual bool SyncLocks() = 0;
protected:
/*! Unfix any of the intervals that intersect the given one; may be useful to override `SelectInterval()` */
void CommonSelectInterval( const TrackInterval &interval );
//! Derived class constructor can initialize all intervals reported by the track as fixed, none moving
/*! This can't be called by the base class constructor, when GetTrack() isn't yet callable */
void InitIntervals();
@ -76,6 +86,9 @@ public:
HitTestResult HitTest( double ) override;
//! Returns false
bool SyncLocks() override;
private:
std::shared_ptr<Track> mpTrack;
};
@ -150,9 +163,10 @@ public:
std::shared_ptr<Track> GetTrack() const { return mCapturedTrack; }
// A utility function also used by menu commands
static void CreateListOfCapturedClips
static void Init
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
TrackList &trackList, bool syncLocked, double clickTime );
TrackList &trackList, bool syncLocked, double clickTime,
bool capturedAClip = true );
// A utility function also used by menu commands
static void DoSlideHorizontal