diff --git a/src/Envelope.cpp b/src/Envelope.cpp index 7ae799fed..a78d4df0b 100644 --- a/src/Envelope.cpp +++ b/src/Envelope.cpp @@ -57,27 +57,19 @@ Envelope::Envelope() mDB = true; mDefaultValue = 1.0; mDragPoint = -1; - mDirty = false; - mIsDeleting = false; - mMirror = true; mMinValue = 1.0e-7; mMaxValue = 2.0; - mButton = wxMOUSE_BTN_NONE; - mSearchGuess = -1; + + mDragPointValid = false; } Envelope::~Envelope() { } -void Envelope::Mirror(bool mirror) -{ - mMirror = mirror; -} - /// Rescale function for time tracks (could also be used for other tracks though). /// This is used to load old time track project files where the envelope used a 0 to 1 /// range instead of storing the actual time track values. This function will change the range of the envelope @@ -112,6 +104,84 @@ void Envelope::Flatten(double value) mDefaultValue = ClampValue(value); } +void Envelope::SetDragPoint(int dragPoint) +{ + mDragPoint = std::max(-1, std::min(int(mEnv.size() - 1), dragPoint)); + mDragPointValid = (mDragPoint >= 0); +} + +void Envelope::SetDragPointValid(bool valid) +{ + mDragPointValid = (valid && mDragPoint >= 0); + if (mDragPoint >= 0 && !valid) { + // We're going to be deleting the point; On + // screen we show this by having the envelope move to + // the position it will have after deletion of the point. + // Without deleting the point we move it left or right + // to the same position as the previous or next point. + + static const double big = std::numeric_limits::max(); + auto size = mEnv.size(); + + if( size <= 1) { + // There is only one point - just move it + // off screen and at default height. + // temporary state when dragging only! + mEnv[mDragPoint].SetT(big); + mEnv[mDragPoint].SetVal(mDefaultValue); + return; + } + else if ( mDragPoint + 1 == size ) { + // Put the point at the height of the last point, but also off screen. + mEnv[mDragPoint].SetT(big); + mEnv[mDragPoint].SetVal(mEnv[ size - 1 ].GetVal()); + } + else { + // Place it exactly on its right neighbour. + // That way the drawing code will overpaint the dark dot with + // a light dot, as if it were deleted. + const auto &neighbor = mEnv[mDragPoint + 1]; + mEnv[mDragPoint].SetT(neighbor.GetT()); + mEnv[mDragPoint].SetVal(neighbor.GetVal()); + } + } +} + +void Envelope::MoveDragPoint(double newWhen, double value) +{ + SetDragPointValid(true); + if (!mDragPointValid) + return; + + // We'll limit the drag point time to be between those of the preceding + // and next envelope point. + double limitLo = 0.0; + double limitHi = mTrackLen; + + if (mDragPoint > 0) + limitLo = std::max(limitLo, mEnv[mDragPoint - 1].GetT()); + if (mDragPoint + 1 < mEnv.size()) + limitHi = std::min(limitHi, mEnv[mDragPoint + 1].GetT()); + + EnvPoint &dragPoint = mEnv[mDragPoint]; + const double tt = + std::max(limitLo, std::min(limitHi, newWhen)); + + // This might temporary violate the constraint that at most two + // points share a time value. + dragPoint.SetT(tt); + dragPoint.SetVal(value); +} + +void Envelope::ClearDragPoint() +{ + if (!mDragPointValid && mDragPoint >= 0) + Delete(mDragPoint); + + mDragPoint = -1; + mDragPointValid = false; +} + void Envelope::SetRange(double minValue, double maxValue) { mMinValue = minValue; mMaxValue = maxValue; @@ -186,7 +256,7 @@ static void DrawPoint(wxDC & dc, const wxRect & r, int x, int y, bool top) /// TODO: This should probably move to track artist. void Envelope::DrawPoints(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo, bool dB, double dBRange, - float zoomMin, float zoomMax) const + float zoomMin, float zoomMax, bool mirrored) const { dc.SetPen(AColor::envelopePen); dc.SetBrush(*wxWHITE_BRUSH); @@ -207,7 +277,7 @@ void Envelope::DrawPoints(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo, y = GetWaveYPos(v, zoomMin, zoomMax, r.height, dB, true, dBRange, false); - if (!mMirror) { + if (!mirrored) { DrawPoint(dc, r, x, y, true); } else { @@ -311,7 +381,7 @@ inline int SQR(int x) { return x * x; } /// @dB - display mode either linear or log. /// @zoomMin - vertical scale, typically -1.0 /// @zoomMax - vertical scale, typically +1.0 -float Envelope::ValueOfPixel( int y, int height, bool upper, +float EnvelopeEditor::ValueOfPixel( int y, int height, bool upper, bool dB, double dBRange, float zoomMin, float zoomMax) { @@ -320,9 +390,9 @@ float Envelope::ValueOfPixel( int y, int height, bool upper, // MB: this is mostly equivalent to what the old code did, I'm not sure // if anything special is needed for asymmetric ranges if(upper) - return ClampValue(v); + return mEnvelope.ClampValue(v); else - return ClampValue(-v); + return mEnvelope.ClampValue(-v); } /// HandleMouseButtonDown either finds an existing control point or adds a NEW one @@ -331,13 +401,13 @@ float Envelope::ValueOfPixel( int y, int height, bool upper, /// a given time value: /// We have an upper and lower envelope line. /// Also we may be showing an inner envelope (at 0.5 the range). -bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, +bool EnvelopeEditor::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, const ZoomInfo &zoomInfo, bool dB, double dBRange, float zoomMin, float zoomMax) { int ctr = (int)(r.height * zoomMax / (zoomMax - zoomMin)); - bool upper = !mMirror || (zoomMin >= 0.0) || (event.m_y - r.y < ctr); + bool upper = !mMirrored || (zoomMin >= 0.0) || (event.m_y - r.y < ctr); int clip_y = event.m_y - r.y; if(clip_y < 0) clip_y = 0; //keeps point in rect r, even if mouse isn't @@ -348,16 +418,15 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, // Member variables hold state that will be needed in dragging. mButton = event.GetButton(); - mIsDeleting = false; mContourOffset = false; // wxLogDebug(wxT("Y:%i Height:%i Offset:%i"), y, height, mContourOffset ); - int len = mEnv.size(); + int len = mEnvelope.GetNumberOfPoints(); // TODO: extract this into a function FindNearestControlPoint() // TODO: also fix it so that we can drag the last point on an envelope. for (int i = 0; i < len; i++) { //search for control point nearest click - const double time = mEnv[i].GetT() + mOffset; + const double time = mEnvelope[i].GetT() + mEnvelope.GetOffset(); const wxInt64 position = zoomInfo.TimeToPosition(time); if (position >= 0 && position < r.width) { @@ -366,7 +435,7 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, int numControlPoints; // Outer control points - double value = mEnv[i].GetVal(); + double value = mEnvelope[i].GetVal(); y[0] = GetWaveYPos(value, zoomMin, zoomMax, r.height, dB, true, dBRange, false); y[1] = GetWaveYPos(-value, zoomMin, zoomMax, r.height, @@ -383,7 +452,7 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, if (y[2] > y[3]) numControlPoints = 2; - if (!mMirror) + if (!mMirrored) numControlPoints = 1; const int deltaXSquared = SQR(x - (event.m_x - r.x)); @@ -400,7 +469,7 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, } if (bestNum >= 0) { - mDragPoint = bestNum; + mEnvelope.SetDragPoint(bestNum); } else { // TODO: Extract this into a function CreateNewPoint @@ -409,13 +478,13 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, // if (when <= 0 || when >= mTrackLen) // return false; - const double v = GetValue( when ); + const double v = mEnvelope.GetValue( when ); int ct = GetWaveYPos( v, zoomMin, zoomMax, r.height, dB, false, dBRange, false) ; int cb = GetWaveYPos( -v-.000000001, zoomMin, zoomMax, r.height, dB, false, dBRange, false) ; - if( ct <= cb || !mMirror ){ + if (ct <= cb || !mMirrored) { int t = GetWaveYPos( v, zoomMin, zoomMax, r.height, dB, true, dBRange, false) ; int b = GetWaveYPos( -v, zoomMin, zoomMax, r.height, dB, @@ -424,7 +493,7 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, ct = (t + ct) / 2; cb = (b + cb) / 2; - if(mMirror && + if (mMirrored && (event.m_y - r.y) > ct && ((event.m_y - r.y) < cb)) mContourOffset = true; @@ -435,50 +504,22 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, double newVal = ValueOfPixel(clip_y, r.height, upper, dB, dBRange, zoomMin, zoomMax); - mDragPoint = Insert(when - mOffset, newVal); + mEnvelope.SetDragPoint(mEnvelope.Insert(when - mEnvelope.GetOffset(), newVal)); mDirty = true; } mUpper = upper; - mInitialVal = mEnv[mDragPoint].GetVal(); - - mInitialY = event.m_y+mContourOffset; + // const int dragPoint = mEnvelope.GetDragPoint(); + // mInitialVal = mEnvelope[dragPoint].GetVal(); + // mInitialY = event.m_y+mContourOffset; return true; } -/// Mark dragged point for deletion. -/// It will be deleted on mouse button up. -void Envelope::MarkDragPointForDeletion() -{ - mIsDeleting = true; - - // We're going to be deleting the point; On - // screen we show this by having the envelope move to - // the position it will have after deletion of the point. - // Without delting the point we move it left or right - // to the same position as the previous or next point. - - if( mEnv.size() <= 1) - { - // There is only one point - just move it - // off screen and at default height. - // temporary state when dragging only! - mEnv[mDragPoint].SetT(-1000000.0); - mEnv[mDragPoint].SetVal(mDefaultValue); - return; - } - - // Place it exactly on one of its neighbours. - int iNeighbourPoint = mDragPoint + ((mDragPoint > 0) ? -1:+1); - mEnv[mDragPoint].SetT(mEnv[iNeighbourPoint].GetT()); - mEnv[mDragPoint].SetVal(mEnv[iNeighbourPoint].GetVal()); -} - -void Envelope::MoveDraggedPoint( const wxMouseEvent & event, wxRect & r, - const ZoomInfo &zoomInfo, bool dB, double dBRange, - float zoomMin, float zoomMax) +void EnvelopeEditor::MoveDragPoint(const wxMouseEvent & event, wxRect & r, + const ZoomInfo &zoomInfo, bool dB, double dBRange, + float zoomMin, float zoomMax) { int clip_y = event.m_y - r.y; if(clip_y < 0) clip_y = 0; @@ -491,29 +532,14 @@ void Envelope::MoveDraggedPoint( const wxMouseEvent & event, wxRect & r, // TODO: However because mTrackEpsilon assumes 200KHz this use // of epsilon is a tad bogus. What we need to do instead is DELETE // a duplicated point on a mouse up. - double newWhen = zoomInfo.PositionToTime(event.m_x, r.x) - mOffset; - - // We'll limit the drag point time to be between those of the preceding - // and next envelope point. - double limitLo = 0.0; - double limitHi = mTrackLen; - - if (mDragPoint > 0) - limitLo = mEnv[mDragPoint - 1].GetT() + mTrackEpsilon; - if (mDragPoint < (int)mEnv.size() - 1 ) - limitHi = mEnv[mDragPoint + 1].GetT() - mTrackEpsilon; - - newWhen = Limit( limitLo, newWhen, limitHi ); - newWhen = Limit( mTrackEpsilon, newWhen, mTrackLen - mTrackEpsilon); - - mEnv[mDragPoint].SetT(newWhen); - mEnv[mDragPoint].SetVal(newVal); - + double newWhen = zoomInfo.PositionToTime(event.m_x, r.x) - mEnvelope.GetOffset(); + mEnvelope.MoveDragPoint(newWhen, newVal); } -bool Envelope::HandleDragging( const wxMouseEvent & event, wxRect & r, +bool EnvelopeEditor::HandleDragging(const wxMouseEvent & event, wxRect & r, const ZoomInfo &zoomInfo, bool dB, double dBRange, - float zoomMin, float zoomMax) + float zoomMin, float zoomMax, + float WXUNUSED(eMin), float WXUNUSED(eMax)) { mDirty = true; @@ -523,27 +549,24 @@ bool Envelope::HandleDragging( const wxMouseEvent & event, wxRect & r, if (larger.Contains(event.m_x, event.m_y)) { // IF we're in the rect THEN we're not deleting this point (anymore). - mIsDeleting = false; // ...we're dragging it. - MoveDraggedPoint( event, r, zoomInfo, dB, dBRange, zoomMin, zoomMax); + MoveDragPoint( event, r, zoomInfo, dB, dBRange, zoomMin, zoomMax); return true; } - if(mIsDeleting ) + if(!mEnvelope.GetDragPointValid()) // IF we already know we're deleting THEN no envelope point to update. return false; - MarkDragPointForDeletion(); + // Invalidate the point + mEnvelope.SetDragPointValid(false); return true; } -// Exit dragging mode and deletes dragged point if neccessary. -bool Envelope::HandleMouseButtonUp() +// Exit dragging mode and delete dragged point if neccessary. +bool EnvelopeEditor::HandleMouseButtonUp() { - if (mIsDeleting) { - Delete(mDragPoint); - } - mDragPoint = -1; + mEnvelope.ClearDragPoint(); mButton = wxMOUSE_BTN_NONE; return true; } @@ -559,14 +582,14 @@ void Envelope::Insert(int point, const EnvPoint &p) } // Returns true if parent needs to be redrawn -bool Envelope::MouseEvent(const wxMouseEvent & event, wxRect & r, +bool EnvelopeEditor::MouseEvent(const wxMouseEvent & event, wxRect & r, const ZoomInfo &zoomInfo, bool dB, double dBRange, float zoomMin, float zoomMax) { if (event.ButtonDown() && mButton == wxMOUSE_BTN_NONE) return HandleMouseButtonDown( event, r, zoomInfo, dB, dBRange, zoomMin, zoomMax); - if (event.Dragging() && mDragPoint >= 0) + if (event.Dragging() && mEnvelope.GetDragPoint() >= 0) return HandleDragging( event, r, zoomInfo, dB, dBRange, zoomMin, zoomMax); if (event.ButtonUp() && event.GetButton() == mButton) @@ -1523,7 +1546,6 @@ void Envelope::testMe() double t0=0, t1=0; SetInterpolateDB(false); - Mirror(false); Flatten(0.5); checkResult( 1, Integral(0.0,100.0), 50); @@ -1575,3 +1597,18 @@ void Envelope::testMe() checkResult( 19, NextPointAfter( 5 ), 10 ); } +EnvelopeEditor::EnvelopeEditor(Envelope &envelope, bool mirrored) + : mEnvelope(envelope) + , mMirrored(mirrored) + , mContourOffset(-1) + // , mInitialVal(-1.0) + // , mInitialY(-1) + , mUpper(false) + , mButton(wxMOUSE_BTN_NONE) + , mDirty(false) +{ +} + +EnvelopeEditor::~EnvelopeEditor() +{ +} diff --git a/src/Envelope.h b/src/Envelope.h index 2da8ad7cb..a95222066 100644 --- a/src/Envelope.h +++ b/src/Envelope.h @@ -81,13 +81,14 @@ class Envelope final : public XMLTagHandler { virtual ~ Envelope(); + double GetOffset() const { return mOffset; } + double GetTrackLen() const { return mTrackLen; } + bool GetInterpolateDB() { return mDB; } void SetInterpolateDB(bool db) { mDB = db; } - void Mirror(bool mirror); void Rescale(double minValue, double maxValue); void Flatten(double value); - int GetDragPoint(void) {return mDragPoint;} double GetMinValue() const { return mMinValue; } double GetMaxValue() const { return mMaxValue; } @@ -107,21 +108,8 @@ class Envelope final : public XMLTagHandler { void WriteXML(XMLWriter &xmlFile) const /* not override */; void DrawPoints(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo, - bool dB, double dBRange, - float zoomMin, float zoomMax) const; - - // Event Handlers - // Each ofthese returns true if parents needs to be redrawn - bool MouseEvent(const wxMouseEvent & event, wxRect & r, - const ZoomInfo &zoomInfo, bool dB, double dBRange, - float zoomMin, float zoomMax); - bool HandleMouseButtonDown( const wxMouseEvent & event, wxRect & r, - const ZoomInfo &zoomInfo, bool dB, double dBRange, - float zoomMin, float zoomMax); - bool HandleDragging( const wxMouseEvent & event, wxRect & r, - const ZoomInfo &zoomInfo, bool dB, double dBRange, - float zoomMin, float zoomMax); - bool HandleMouseButtonUp(); + bool dB, double dBRange, + float zoomMin, float zoomMax, bool mirrored) const; // Handling Cut/Copy/Paste events void CollapseRegion(double t0, double t1); @@ -181,28 +169,38 @@ class Envelope final : public XMLTagHandler { /** \brief Return number of points */ size_t GetNumberOfPoints() const; +private: + friend class EnvelopeEditor; /** \brief Accessor for points */ - const EnvPoint &operator[] (int index) const + EnvPoint &operator[] (int index) { return mEnv[index]; } +public: /** \brief Returns the sets of when and value pairs */ void GetPoints(double *bufferWhen, - double *bufferValue, - int bufferLen) const; + double *bufferValue, + int bufferLen) const; + + // UI-related + // The drag point needs to display differently. + int GetDragPoint() const { return mDragPoint; } + // Choose the drag point. + void SetDragPoint(int dragPoint); + // Mark or unmark the drag point for deletion. + void SetDragPointValid(bool valid); + bool GetDragPointValid() const { return mDragPointValid; } + // Modify the dragged point and change its value. + // But consistency constraints may move it less then you ask for. + void MoveDragPoint(double newWhen, double value); + // May delete the drag point. Restores envelope consistency. + void ClearDragPoint(); private: EnvPoint * AddPointAtEnd( double t, double val ); - void MarkDragPointForDeletion(); - float ValueOfPixel( int y, int height, bool upper, - bool dB, double dBRange, - float zoomMin, float zoomMax); void BinarySearchForTime( int &Lo, int &Hi, double t ) const; double GetInterpolationStartValueAtPoint( int iPoint ) const; - void MoveDraggedPoint( const wxMouseEvent & event, wxRect & r, - const ZoomInfo &zoomInfo, bool dB, double dBRange, - float zoomMin, float zoomMax); // Possibly inline functions: // This function resets them integral memoizers (call whenever the Envelope changes) @@ -210,7 +208,6 @@ private: // The list of envelope control points. EnvArray mEnv; - bool mMirror; /** \brief The time at which the envelope starts, i.e. the start offset */ double mOffset; @@ -224,21 +221,7 @@ private: * before being considered the same point */ double mTrackEpsilon; double mDefaultValue; - - /** \brief Number of pixels contour is from the true envelope. */ - int mContourOffset; - - double mInitialVal; - - // These are used in dragging. - int mDragPoint; - int mInitialY; - bool mUpper; - bool mIsDeleting; - int mButton; bool mDB; - bool mDirty; - double mMinValue, mMaxValue; // These are memoizing variables for Integral() @@ -246,8 +229,11 @@ private: double lastIntegral_t1; double lastIntegral_result; - mutable int mSearchGuess; + // UI stuff + bool mDragPointValid; + int mDragPoint; + mutable int mSearchGuess; }; inline EnvPoint::EnvPoint(Envelope *envelope, double t, double val) @@ -262,5 +248,49 @@ inline void EnvPoint::SetVal(double val) mVal = mEnvelope->ClampValue(val); } -#endif +// A class that holds state for the duration of dragging +// of an envelope point. +class EnvelopeEditor +{ +public: + EnvelopeEditor(Envelope &envelope, bool mirrored); + ~EnvelopeEditor(); + // Event Handlers + // Each of these returns true if the envelope needs to be redrawn + bool MouseEvent(const wxMouseEvent & event, wxRect & r, + const ZoomInfo &zoomInfo, bool dB, double dBRange, + float zoomMin = -1.0, float zoomMax = 1.0); + +private: + bool HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r, + const ZoomInfo &zoomInfo, bool dB, double dBRange, + float zoomMin = -1.0, float zoomMax = 1.0); + bool HandleDragging(const wxMouseEvent & event, wxRect & r, + const ZoomInfo &zoomInfo, bool dB, double dBRange, + float zoomMin = -1.0, float zoomMax = 1.0, float eMin = 0., float eMax = 2.); + bool HandleMouseButtonUp(); + +private: + float ValueOfPixel(int y, int height, bool upper, + bool dB, double dBRange, + float zoomMin, float zoomMax); + void MoveDragPoint(const wxMouseEvent & event, wxRect & r, + const ZoomInfo &zoomInfo, bool dB, double dBRange, + float zoomMin, float zoomMax); + + Envelope &mEnvelope; + const bool mMirrored; + + /** \brief Number of pixels contour is from the true envelope. */ + int mContourOffset; + + // double mInitialVal; + + // int mInitialY; + bool mUpper; + int mButton; + bool mDirty; +}; + +#endif diff --git a/src/TimeTrack.cpp b/src/TimeTrack.cpp index 4be32cfd5..bdfa67d8f 100644 --- a/src/TimeTrack.cpp +++ b/src/TimeTrack.cpp @@ -48,7 +48,6 @@ TimeTrack::TimeTrack(const std::shared_ptr &projDirManager, const Zo mEnvelope->SetTrackLen(DBL_MAX); mEnvelope->SetInterpolateDB(true); mEnvelope->Flatten(1.0); - mEnvelope->Mirror(false); mEnvelope->SetOffset(0); mEnvelope->SetRange(TIMETRACK_MIN, TIMETRACK_MAX); @@ -75,7 +74,6 @@ TimeTrack::TimeTrack(const TimeTrack &orig): mEnvelope->SetTrackLen(DBL_MAX); SetInterpolateLog(orig.GetInterpolateLog()); // this calls Envelope::SetInterpolateDB mEnvelope->Flatten(1.0); - mEnvelope->Mirror(false); mEnvelope->SetOffset(0); mEnvelope->SetRange(orig.mEnvelope->GetMinValue(), orig.mEnvelope->GetMaxValue()); mEnvelope->Paste(0.0, orig.mEnvelope.get()); diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp index 2c3ee0f68..6838ae735 100644 --- a/src/TrackArtist.cpp +++ b/src/TrackArtist.cpp @@ -1926,7 +1926,7 @@ void TrackArtist::DrawClipWaveform(const WaveTrack *track, if (drawEnvelope) { DrawEnvelope(dc, mid, env, zoomMin, zoomMax, dB, dBRange); - clip->GetEnvelope()->DrawPoints(dc, rect, zoomInfo, dB, dBRange, zoomMin, zoomMax); + clip->GetEnvelope()->DrawPoints(dc, rect, zoomInfo, dB, dBRange, zoomMin, zoomMax, true); } // Draw arrows on the left side if the track extends to the left of the @@ -3209,7 +3209,7 @@ void TrackArtist::DrawTimeTrack(const TimeTrack *track, upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / mdBrange + 1.0; } track->GetEnvelope()->DrawPoints(dc, envRect, zoomInfo, - track->GetDisplayLog(), mdBrange, lower, upper); + track->GetDisplayLog(), mdBrange, lower, upper, false); } void TrackArtist::UpdatePrefs() diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 1b8fd67df..66bace059 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -3213,8 +3213,13 @@ void TrackPanel::ForwardEventToTimeTrackEnvelope(wxMouseEvent & event) lower = LINEAR_TO_DB(std::max(1.0e-7, lower)) / dBRange + 1.0; upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / dBRange + 1.0; } + if (event.ButtonDown()) { + mEnvelopeEditor = std::make_unique(*pspeedenvelope, false); + mEnvelopeEditorRight.reset(); + } bool needUpdate = - pspeedenvelope->MouseEvent( + mEnvelopeEditor && + mEnvelopeEditor->MouseEvent( event, envRect, *mViewInfo, ptimetrack->GetDisplayLog(), dBRange, lower, upper); @@ -3250,7 +3255,13 @@ void TrackPanel::ForwardEventToWaveTrackEnvelope(wxMouseEvent & event) wxRect envRect = mCapturedRect; float zoomMin, zoomMax; pwavetrack->GetDisplayBounds(&zoomMin, &zoomMax); - needUpdate = penvelope->MouseEvent( + if (event.ButtonDown()) { + mEnvelopeEditor = std::make_unique(*penvelope, true); + mEnvelopeEditorRight.reset(); + } + needUpdate = + mEnvelopeEditor && + mEnvelopeEditor->MouseEvent( event, envRect, *mViewInfo, dB, dBRange, zoomMin, zoomMax); @@ -3260,30 +3271,23 @@ void TrackPanel::ForwardEventToWaveTrackEnvelope(wxMouseEvent & event) // Assume linked track is wave or null const auto link = static_cast(mCapturedTrack->GetLink()); if (link) { - Envelope *e2 = link->GetEnvelopeAtX(event.GetX()); - // There isn't necessarily an envelope there; no guarantee a - // linked track has the same WaveClip structure... - bool updateNeeded = false; - if (e2) { + if (event.ButtonDown()) { + Envelope *e2 = link->GetEnvelopeAtX(event.GetX()); + if (e2) + mEnvelopeEditorRight = std::make_unique(*e2, true); + else { + // There isn't necessarily an envelope there; no guarantee a + // linked track has the same WaveClip structure... + } + } + if (mEnvelopeEditorRight) { wxRect envRect = mCapturedRect; float zoomMin, zoomMax; pwavetrack->GetDisplayBounds(&zoomMin, &zoomMax); - updateNeeded = e2->MouseEvent(event, envRect, - *mViewInfo, dB, dBRange, - zoomMin, zoomMax); - needUpdate |= updateNeeded; - } - if(!e2 || !updateNeeded) // no envelope found at this x point, or found but not updated - { - if( (e2 = link->GetActiveEnvelope()) != 0 ) // search for any active DragPoint - { - wxRect envRect = mCapturedRect; - float zoomMin, zoomMax; - pwavetrack->GetDisplayBounds(&zoomMin, &zoomMax); - needUpdate |= e2->MouseEvent(event, envRect, - *mViewInfo, dB, dBRange, - zoomMin, zoomMax); - } + needUpdate|= mEnvelopeEditorRight->MouseEvent(event, envRect, + *mViewInfo, + dB, dBRange, + zoomMin, zoomMax); } } diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 6adc12be8..76af1ecc1 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -30,6 +30,7 @@ class wxMenu; class wxRect; +class EnvelopeEditor; class LabelTrack; class SpectrumAnalyst; class TrackPanel; @@ -809,6 +810,9 @@ protected: // Keeps track of extra fractional vertical scroll steps double mVertScrollRemainder; + std::unique_ptr mEnvelopeEditor; + std::unique_ptr mEnvelopeEditorRight; + protected: // The screenshot class needs to access internals diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 174d612ce..87018fee4 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -2228,18 +2228,6 @@ Envelope* WaveTrack::GetEnvelopeAtX(int xcoord) return NULL; } -// Search for any active DragPoint on the current track -Envelope* WaveTrack::GetActiveEnvelope(void) -{ - for (const auto &clip : mClips) - { - Envelope* env = clip->GetEnvelope() ; - if (env->GetDragPoint() >= 0) - return env; - } - return NULL; -} - Sequence* WaveTrack::GetSequenceAtX(int xcoord) { WaveClip* clip = GetClipAtX(xcoord); diff --git a/src/WaveTrack.h b/src/WaveTrack.h index 4d729da84..372169b6a 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -264,7 +264,6 @@ class AUDACITY_DLL_API WaveTrack final : public Track { WaveClip* GetClipAtX(int xcoord); Sequence* GetSequenceAtX(int xcoord); Envelope* GetEnvelopeAtX(int xcoord); - Envelope* GetActiveEnvelope(void); WaveClip* GetClipAtSample(sampleCount sample); diff --git a/src/effects/Equalization.cpp b/src/effects/Equalization.cpp index 0138d36ba..9cd91036c 100644 --- a/src/effects/Equalization.cpp +++ b/src/effects/Equalization.cpp @@ -241,12 +241,10 @@ EffectEqualization::EffectEqualization() mLogEnvelope = std::make_unique(); mLogEnvelope->SetInterpolateDB(false); - mLogEnvelope->Mirror(false); mLogEnvelope->SetRange(MIN_dBMin, MAX_dBMax); // MB: this is the highest possible range mLinEnvelope = std::make_unique(); mLinEnvelope->SetInterpolateDB(false); - mLinEnvelope->Mirror(false); mLinEnvelope->SetRange(MIN_dBMin, MAX_dBMax); // MB: this is the highest possible range mEnvelope = (mLin ? mLinEnvelope : mLogEnvelope).get(); @@ -2365,7 +2363,6 @@ void EffectEqualization::ErrMin(void) int j=0; Envelope testEnvelope; testEnvelope.SetInterpolateDB(false); - testEnvelope.Mirror(false); testEnvelope.SetRange(-120.0, 60.0); testEnvelope.Flatten(0.); testEnvelope.SetTrackLen(1.0); @@ -2893,8 +2890,8 @@ EqualizationPanel::EqualizationPanel(EffectEqualization *effect, wxWindow *paren mWidth = 0; mHeight = 0; + mEditor = std::make_unique(*mEffect->mEnvelope, false); mEffect->mEnvelope->Flatten(0.); - mEffect->mEnvelope->Mirror(false); mEffect->mEnvelope->SetTrackLen(1.0); ForceRecalc(); @@ -3103,7 +3100,7 @@ void EqualizationPanel::OnPaint(wxPaintEvent & WXUNUSED(event)) if( mEffect->mDraw->GetValue() ) { mEffect->mEnvelope->DrawPoints(memDC, mEnvRect, ZoomInfo(0.0, mEnvRect.width-1), false, 0.0, - mEffect->mdBMin, mEffect->mdBMax); + mEffect->mdBMin, mEffect->mdBMax, false); } dc.Blit(0, 0, mWidth, mHeight, &memDC, 0, 0, wxCOPY, FALSE); @@ -3121,7 +3118,7 @@ void EqualizationPanel::OnMouseEvent(wxMouseEvent & event) CaptureMouse(); } - if (mEffect->mEnvelope->MouseEvent(event, mEnvRect, ZoomInfo(0.0, mEnvRect.width), + if (mEditor->MouseEvent(event, mEnvRect, ZoomInfo(0.0, mEnvRect.width), false, 0.0, mEffect->mdBMin, mEffect->mdBMax)) { diff --git a/src/effects/Equalization.h b/src/effects/Equalization.h index 8923ad9b1..9be3d2da4 100644 --- a/src/effects/Equalization.h +++ b/src/effects/Equalization.h @@ -46,6 +46,7 @@ class Envelope; +class EnvelopeEditor; class EqualizationPanel; // @@ -308,6 +309,7 @@ public: private: wxWindow *mParent; EffectEqualization *mEffect; + std::unique_ptr mEditor; bool mRecalcRequired; diff --git a/src/effects/NoiseRemoval.cpp b/src/effects/NoiseRemoval.cpp index 99f1bd88b..effefc33c 100644 --- a/src/effects/NoiseRemoval.cpp +++ b/src/effects/NoiseRemoval.cpp @@ -45,7 +45,6 @@ #include "NoiseRemoval.h" -#include "../Envelope.h" #include "../WaveTrack.h" #include "../Prefs.h" #include "../Project.h" @@ -883,4 +882,4 @@ void NoiseRemovalDialog::OnTimeSlider(wxCommandEvent & WXUNUSED(event)) mTimeT->SetValue(wxString::Format(wxT("%.2f"), mTime)); } -#endif \ No newline at end of file +#endif