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:
parent
c279fb6588
commit
eb22892064
@ -654,7 +654,7 @@ double DoClipMove
|
|||||||
track->GetSelected() && !selectedRegion.isPoint();
|
track->GetSelected() && !selectedRegion.isPoint();
|
||||||
state.trackExclusions.clear();
|
state.trackExclusions.clear();
|
||||||
|
|
||||||
TimeShiftHandle::CreateListOfCapturedClips(
|
TimeShiftHandle::Init(
|
||||||
state, viewInfo, *track, trackList, syncLocked, t0 );
|
state, viewInfo, *track, trackList, syncLocked, t0 );
|
||||||
|
|
||||||
auto desiredT0 = viewInfo.OffsetTimeByPixels( t0, ( right ? 1 : -1 ) );
|
auto desiredT0 = viewInfo.OffsetTimeByPixels( t0, ( right ? 1 : -1 ) );
|
||||||
|
@ -741,12 +741,19 @@ public:
|
|||||||
}
|
}
|
||||||
~NoteTrackShifter() override {}
|
~NoteTrackShifter() override {}
|
||||||
Track &GetTrack() const override { return *mpTrack; }
|
Track &GetTrack() const override { return *mpTrack; }
|
||||||
|
|
||||||
HitTestResult HitTest( double ) override
|
HitTestResult HitTest( double ) override
|
||||||
{
|
{
|
||||||
return HitTestResult::Intervals;
|
return HitTestResult::Intervals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SelectInterval( const TrackInterval &interval ) override
|
||||||
|
{
|
||||||
|
CommonSelectInterval( interval );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SyncLocks() override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<NoteTrack> mpTrack;
|
std::shared_ptr<NoteTrack> mpTrack;
|
||||||
};
|
};
|
||||||
|
@ -1329,6 +1329,21 @@ public:
|
|||||||
return HitTestResult::Intervals;
|
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:
|
private:
|
||||||
std::shared_ptr<WaveTrack> mpTrack;
|
std::shared_ptr<WaveTrack> mpTrack;
|
||||||
};
|
};
|
||||||
|
@ -265,6 +265,19 @@ void TrackShifter::UnfixAll()
|
|||||||
mFixed = Intervals{};
|
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()
|
void TrackShifter::InitIntervals()
|
||||||
{
|
{
|
||||||
mMoving.clear();
|
mMoving.clear();
|
||||||
@ -284,15 +297,21 @@ auto CoarseTrackShifter::HitTest( double ) -> HitTestResult
|
|||||||
return HitTestResult::Track;
|
return HitTestResult::Track;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CoarseTrackShifter::SyncLocks()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
template<> auto MakeTrackShifter::Implementation() -> Function {
|
template<> auto MakeTrackShifter::Implementation() -> Function {
|
||||||
return [](Track &track) {
|
return [](Track &track) {
|
||||||
return std::make_unique<CoarseTrackShifter>(track);
|
return std::make_unique<CoarseTrackShifter>(track);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeShiftHandle::CreateListOfCapturedClips
|
void TimeShiftHandle::Init
|
||||||
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
|
( 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
|
// The captured clip is the focus, but we need to create a list
|
||||||
// of all clips that have to move, also...
|
// 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
|
// First, if click was in selection, capture selected clips; otherwise
|
||||||
// just the clicked-on clip
|
// just the clicked-on clip
|
||||||
if ( state.capturedClipIsSelection )
|
if ( state.capturedClipIsSelection )
|
||||||
|
// All selected tracks may move some intervals
|
||||||
for (auto t : trackList.Selected())
|
for (auto t : trackList.Selected())
|
||||||
AddClipsToCaptured( state, viewInfo, t );
|
AddClipsToCaptured( state, viewInfo, t );
|
||||||
else {
|
else {
|
||||||
|
// Move intervals only of the chosen channel group
|
||||||
state.capturedClipArray.push_back
|
state.capturedClipArray.push_back
|
||||||
(TrackClip( &capturedTrack, state.capturedClip ));
|
(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
|
// Now, if sync-lock is enabled, capture any clip that's linked to a
|
||||||
// captured clip.
|
// captured clip.
|
||||||
if ( syncLocked ) {
|
if ( syncLocked ) {
|
||||||
|
// Sync lock propagation of unfixing of intervals
|
||||||
// AWD: capturedClipArray expands as the loop runs, so newly-added
|
// AWD: capturedClipArray expands as the loop runs, so newly-added
|
||||||
// clips are considered (the effect is like recursion and terminates
|
// clips are considered (the effect is like recursion and terminates
|
||||||
// because AddClipsToCaptured doesn't add duplicate clips); to remove
|
// because AddClipsToCaptured doesn't add duplicate clips); to remove
|
||||||
@ -351,6 +373,70 @@ void TimeShiftHandle::CreateListOfCapturedClips
|
|||||||
#endif
|
#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
|
void TimeShiftHandle::DoSlideHorizontal
|
||||||
@ -542,9 +628,9 @@ UIHandle::Result TimeShiftHandle::Click
|
|||||||
pShifter = MakeTrackShifter::Call( *track );
|
pShifter = MakeTrackShifter::Call( *track );
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateListOfCapturedClips(
|
Init(
|
||||||
mClipMoveState, viewInfo, *pTrack, trackList,
|
mClipMoveState, viewInfo, *pTrack, trackList,
|
||||||
ProjectSettings::Get( *pProject ).IsSyncLocked(), clickTime );
|
ProjectSettings::Get( *pProject ).IsSyncLocked(), clickTime, capturedAClip );
|
||||||
}
|
}
|
||||||
|
|
||||||
mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive;
|
mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive;
|
||||||
|
@ -58,7 +58,17 @@ public:
|
|||||||
//! Change all intervals from fixed to moving
|
//! Change all intervals from fixed to moving
|
||||||
void UnfixAll();
|
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:
|
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
|
//! 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 */
|
/*! This can't be called by the base class constructor, when GetTrack() isn't yet callable */
|
||||||
void InitIntervals();
|
void InitIntervals();
|
||||||
@ -76,6 +86,9 @@ public:
|
|||||||
|
|
||||||
HitTestResult HitTest( double ) override;
|
HitTestResult HitTest( double ) override;
|
||||||
|
|
||||||
|
//! Returns false
|
||||||
|
bool SyncLocks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Track> mpTrack;
|
std::shared_ptr<Track> mpTrack;
|
||||||
};
|
};
|
||||||
@ -150,9 +163,10 @@ public:
|
|||||||
std::shared_ptr<Track> GetTrack() const { return mCapturedTrack; }
|
std::shared_ptr<Track> GetTrack() const { return mCapturedTrack; }
|
||||||
|
|
||||||
// A utility function also used by menu commands
|
// A utility function also used by menu commands
|
||||||
static void CreateListOfCapturedClips
|
static void Init
|
||||||
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
|
( 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
|
// A utility function also used by menu commands
|
||||||
static void DoSlideHorizontal
|
static void DoSlideHorizontal
|
||||||
|
Loading…
x
Reference in New Issue
Block a user