void Envelope::MoveDraggedPoint( wxMouseEvent & event, wxRect & r, double WXUNUSED(h), double pps, bool dB, float zoomMin, float zoomMax) { int clip_y = event.m_y - r.y; if(clip_y < 0) clip_y = 0; if(clip_y > r.height) clip_y = r.height; double newVal = ValueOfPixel(clip_y, r.height, mUpper, dB, zoomMin, zoomMax); wxASSERT( pps > 0 ); // We no longer tolerate multiple envelope points at the same t. // epsilon is less than the time offset of a single sample // 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 = mInitialWhen + (event.m_x - mInitialX) / pps; // 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.Count() - 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); }
bool Envelope::HandleDragging( wxMouseEvent & event, wxRect & r, double h, double pps, bool dB, float zoomMin, float zoomMax ) { int clip_y = event.m_y - r.y; if(clip_y < 0) clip_y = 0; if(clip_y > r.height) clip_y = r.height; mDirty = true; wxRect larger = r; larger.Inflate(10, 10); if (!mIsDeleting && !larger.Inside(event.m_x, event.m_y)){ if( mEnv.Count()> 1) { if(mDragPoint > 0){ mEnv[mDragPoint]->t = mEnv[mDragPoint - 1]->t; mEnv[mDragPoint]->val = mEnv[mDragPoint - 1]->val; } else{ mEnv[mDragPoint]->t = mEnv[mDragPoint + 1]->t; mEnv[mDragPoint]->val = mEnv[mDragPoint + 1]->val; } } else { // temporary state when dragging only! mEnv[mDragPoint]->t = -1000000.0; mEnv[mDragPoint]->val = mDefaultValue; } mIsDeleting = true; return true; } if (larger.Inside(event.m_x, event.m_y)) mIsDeleting = false; if (mIsDeleting) return false; double newVal = ValueOfPixel(clip_y, r.height, mUpper, dB, zoomMin, zoomMax); //float MaxAmplify = ( mContourOffset ) ? 1.4 : 1.0; float MaxAmplify = 2.0; if (newVal > MaxAmplify) newVal = MaxAmplify; // We no longer tolerate multiple envelope points at the same t. // epsilon is less than the time offset of a single sample double newWhen = mInitialWhen + (event.m_x - mInitialX) / pps; if (mDragPoint > 0 && newWhen - mTrackEpsilon < mEnv[mDragPoint - 1]->t) newWhen = mEnv[mDragPoint - 1]->t + mTrackEpsilon; if (mDragPoint < (int)mEnv.Count() - 1 && newWhen + mTrackEpsilon > (double)mEnv[mDragPoint + 1]->t) newWhen = mEnv[mDragPoint + 1]->t - mTrackEpsilon; if(newWhen < 0.0) newWhen = 0.0; if(newWhen > mTrackLen) newWhen = mTrackLen; mEnv[mDragPoint]->t = newWhen; mEnv[mDragPoint]->val = newVal; return true; }
bool Envelope::HandleMouseButtonDown(wxMouseEvent & event, wxRect & r, double h, double pps, bool dB, float zoomMin, float zoomMax) { bool upper; int ctr = (int)(r.height * zoomMax / (zoomMax - zoomMin)); upper = (event.m_y - r.y < ctr); int clip_y = event.m_y - r.y; if(clip_y < 0) clip_y = 0; if(clip_y > r.height) clip_y = r.height; mIsDeleting = false; double tleft = h - mOffset; double tright = tleft + (r.width / pps); int bestNum = -1; int bestDist = 10; // Must be within 10 pixel radius. double dBr = gPrefs->Read("/GUI/EnvdBRange", ENV_DB_RANGE); mContourOffset = false; // wxLogDebug("Y:%i Height:%i Offset:%i", y, height, mContourOffset ); int len = mEnv.Count(); for (int i = 0; i < len; i++) { if (mEnv[i]->t >= tleft && mEnv[i]->t <= tright) { int x = int ((mEnv[i]->t + mOffset - h) * pps) + r.x; int y[4]; int numControlPoints; // Outer control points y[0] = GetWaveYPosNew( mEnv[i]->val, zoomMin, zoomMax, r.height, dB, true, dBr, false); y[1] = GetWaveYPosNew( -mEnv[i]->val, zoomMin, zoomMax, r.height, dB, true, dBr, false); // Inner control points(contour) y[2] = GetWaveYPosNew( mEnv[i]->val, zoomMin, zoomMax, r.height, dB, false, dBr, false); y[3] = GetWaveYPosNew( -mEnv[i]->val-.00000001, zoomMin, zoomMax, r.height, dB, false, dBr, false); numControlPoints = 4; if (y[2] > y[3]) numControlPoints = 2; if (!mMirror) numControlPoints = 1; for(int j=0; j<numControlPoints; j++){ int d = (int)(sqrt((double)(SQR(x-event.m_x) + SQR(y[j]-(event.m_y-r.y)))) + 0.5); if (d < bestDist) { bestNum = i; bestDist = d; mContourOffset = (bool)(j > 1); } } } } if (bestNum >= 0) { mDragPoint = bestNum; } else { // Create new point double when = h + (event.m_x - r.x) / pps - mOffset; // if (when <= 0 || when >= mTrackLen) // return false; double v = GetValueAtX( event.m_x, r, h, pps ); int ct = GetWaveYPosNew( v, zoomMin, zoomMax, r.height, dB, false, dBr, false) ; int cb = GetWaveYPosNew( -v-.000000001, zoomMin, zoomMax, r.height, dB, false, dBr, false) ; if( ct <= cb || !mMirror ){ int t = GetWaveYPosNew( v, zoomMin, zoomMax, r.height, dB, true, dBr, false) ; int b = GetWaveYPosNew( -v, zoomMin, zoomMax, r.height, dB, true, dBr, false) ; ct = (t + ct) / 2; cb = (b + cb) / 2; if(mMirror && (event.m_y - r.y) > ct && ((event.m_y - r.y) < cb)) mContourOffset = true; else mContourOffset = false; } double newVal = ValueOfPixel(clip_y, r.height, upper, dB, zoomMin, zoomMax); //float MaxAmplify = ( mContourOffset ) ? 1.4 : 1.0; float MaxAmplify = 2.0; if (newVal > MaxAmplify) newVal = MaxAmplify; mDragPoint = Insert(when, newVal); mDirty = true; } mUpper = upper; mInitialWhen = mEnv[mDragPoint]->t; mInitialVal = mEnv[mDragPoint]->val; mInitialX = event.m_x; mInitialY = event.m_y+mContourOffset; return true; }
/// HandleMouseButtonDown either finds an existing control point or adds a new one /// which is then recorded as the point to drag. /// This is slightly complicated by there possibly being four control points for /// 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(wxMouseEvent & event, wxRect & r, double h, double pps, bool dB, float zoomMin, float zoomMax) { int ctr = (int)(r.height * zoomMax / (zoomMax - zoomMin)); bool upper = !mMirror || (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 if(clip_y > r.GetBottom()) clip_y = r.GetBottom(); double tleft = h - mOffset; double tright = tleft + (r.width / pps); int bestNum = -1; int bestDist = 10; // Must be within 10 pixel radius. // TODO: Cache the gPrefs value. Reading it every time is inefficient. double dBr = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); // 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.Count(); // 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 if (mEnv[i]->GetT() >= tleft && mEnv[i]->GetT() <= tright) { int x = int ((mEnv[i]->GetT() + mOffset - h) * pps) + r.x; int y[4]; int numControlPoints; // Outer control points y[0] = GetWaveYPos( mEnv[i]->GetVal(), zoomMin, zoomMax, r.height, dB, true, dBr, false); y[1] = GetWaveYPos( -mEnv[i]->GetVal(), zoomMin, zoomMax, r.height, dB, true, dBr, false); // Inner control points(contour) y[2] = GetWaveYPos( mEnv[i]->GetVal(), zoomMin, zoomMax, r.height, dB, false, dBr, false); y[3] = GetWaveYPos( -mEnv[i]->GetVal()-.00000001, zoomMin, zoomMax, r.height, dB, false, dBr, false); numControlPoints = 4; if (y[2] > y[3]) numControlPoints = 2; if (!mMirror) numControlPoints = 1; for(int j=0; j<numControlPoints; j++){ int d = (int)(sqrt((double)(SQR(x-event.m_x) + SQR(y[j]-(event.m_y-r.y)))) + 0.5); if (d < bestDist) { bestNum = i; bestDist = d; mContourOffset = (bool)(j > 1); } } } } if (bestNum >= 0) { mDragPoint = bestNum; } else { // TODO: Extract this into a function CreateNewPoint double when = h + (event.m_x - r.x) / pps - mOffset; // if (when <= 0 || when >= mTrackLen) // return false; double v = GetValueAtX( event.m_x, r, h, pps ); int ct = GetWaveYPos( v, zoomMin, zoomMax, r.height, dB, false, dBr, false) ; int cb = GetWaveYPos( -v-.000000001, zoomMin, zoomMax, r.height, dB, false, dBr, false) ; if( ct <= cb || !mMirror ){ int t = GetWaveYPos( v, zoomMin, zoomMax, r.height, dB, true, dBr, false) ; int b = GetWaveYPos( -v, zoomMin, zoomMax, r.height, dB, true, dBr, false) ; ct = (t + ct) / 2; cb = (b + cb) / 2; if(mMirror && (event.m_y - r.y) > ct && ((event.m_y - r.y) < cb)) mContourOffset = true; else mContourOffset = false; } double newVal = ValueOfPixel(clip_y, r.height, upper, dB, zoomMin, zoomMax); mDragPoint = Insert(when, newVal); mDirty = true; } mUpper = upper; mInitialWhen = mEnv[mDragPoint]->GetT(); mInitialVal = mEnv[mDragPoint]->GetVal(); mInitialX = event.m_x; mInitialY = event.m_y+mContourOffset; return true; }