using QuikDawEditor.Undo; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using static QuikDawEditor.EDITING.StaticProperties; using QuikDawEditor.EditingClasses; namespace QuikDawEditor { public partial class PianoRoll { bool MouseInMidiEventRect = false; bool MouseDownInMidiEventRect = false; double MouseDownInMidiEventY = 0; double MouseDownInMidiEventX = 0; double MouseDownEventMainValue = 0; private void MidiEventRect_MouseEnter(object sender, MouseEventArgs e) { MouseInMidiEventRect = true; DockPanel thisDP = (DockPanel)sender; QDMidiEvent thisQME = (QDMidiEvent)thisDP.DataContext; if (e.GetPosition(thisDP).Y < thisDP.ActualHeight / 2) Cursor = Cursors.ScrollNS; else { if (thisQME is not QDMidiNote) Cursor = Cursors.ScrollWE; } Grid thisGrid = (Grid)thisDP.Parent; thisPianoRoll.CurrentValDisplayStringMargin = new Thickness((thisGrid.Margin.Left + 10D / thisPianoRoll.WorkingGridXZoomFac) * thisPianoRoll.WorkingGridXZoomFac, 2, 0, 0); if (Cursor == Cursors.ScrollNS) thisPianoRoll.CurrentValDisplayString = thisQME.DisplayString; else thisPianoRoll.CurrentValDisplayString = Math.Round(thisQME.ClipRelTimeMs).ToString() + " ms"; thisQME.IsHovering = true; } private void MidiEventRect_MouseLeave(object sender, MouseEventArgs e) { if (MouseDownInMidiEventRect) return; MouseInMidiEventRect = false; Cursor = Cursors.Arrow; thisPianoRoll.CurrentValDisplayString = ""; object dcontext = ((DockPanel)sender).DataContext; if (dcontext.GetType() == typeof(QDMidiEvent)) { QDMidiEvent thisQME = (QDMidiEvent)dcontext; thisQME.IsHovering = false; } else { foreach (QDMidiEvent qme in thisPianoRoll.myClip.ClipMidiEvents) qme.IsHovering = false; } } private void MidiEventRect_PreviewMouseMove(object sender, MouseEventArgs e) { e.Handled = true; DockPanel thisRect = (DockPanel)sender; if (MouseDownInMidiEventRect) { if (Cursor == Cursors.ScrollNS) { //change value of midi event double diffY = e.GetPosition(MidiEventsSV).Y - MouseDownInMidiEventY; double percDiff = diffY / MidiEventsSV.ActualHeight; if (MidiEventsIC.ItemsSource == thisPianoRoll.MidiNotes) { QDMidiNote thisQDMnote = (QDMidiNote)thisRect.DataContext; double currVal = thisQDMnote.MainValue; double newVal = MouseDownEventMainValue - (thisQDMnote.MaxEventValue * percDiff); double ValChange = newVal - currVal; if (thisPianoRoll.SelectedMidiNotes.Contains(thisQDMnote)) //Do for all selected notes foreach (QDMidiNote mnote in thisPianoRoll.SelectedMidiNotes) mnote.MainValue = Math.Max(0, Math.Min(mnote.MaxEventValue, mnote.MainValue + ValChange)); else // just the one thisQDMnote.MainValue = Math.Max(0, Math.Min(thisQDMnote.MaxEventValue, thisQDMnote.MainValue + ValChange)); thisPianoRoll.CurrentValDisplayString = thisQDMnote.DisplayString; } if (MidiEventsIC.ItemsSource == myClip.ClipPitchChangeEvents) { QDPitchChange pitchChangeEvent = (QDPitchChange)thisRect.DataContext; double currVal = pitchChangeEvent.MainValue; double newVal = MouseDownEventMainValue - (pitchChangeEvent.MaxEventValue * percDiff); double ValChange = newVal - currVal; if (myClip.ClipPitchChangeEvents.Where(cpce => cpce.Selected).Contains(pitchChangeEvent)) //Do for all selected sustains foreach (QDPitchChange pchange in myClip.ClipPitchChangeEvents.Where(cpce => cpce.Selected)) pchange.MainValue = Math.Max(0, Math.Min(pchange.MaxEventValue, pchange.MainValue + ValChange)); else // just the one pitchChangeEvent.MainValue = Math.Max(0, Math.Min(pitchChangeEvent.MaxEventValue, pitchChangeEvent.MainValue + ValChange)); thisPianoRoll.CurrentValDisplayString = pitchChangeEvent.DisplayString; } if (MidiEventsIC.ItemsSource == myClip.ClipModulationEvents) { QDModulation modEvent = (QDModulation)thisRect.DataContext; double currVal = modEvent.MainValue; double newVal = MouseDownEventMainValue - (modEvent.MaxEventValue * percDiff); double ValChange = newVal - currVal; if (myClip.ClipModulationEvents.Where(cme => cme.Selected).Contains(modEvent)) //Do for all selected sustains foreach (QDModulation modchange in myClip.ClipModulationEvents.Where(cme => cme.Selected)) modchange.MainValue = Math.Max(0, Math.Min(modchange.MaxEventValue, modchange.MainValue + ValChange)); else // just the one modEvent.MainValue = Math.Max(0, Math.Min(modEvent.MaxEventValue, modEvent.MainValue + ValChange)); thisPianoRoll.CurrentValDisplayString = modEvent.DisplayString; } thisPianoRoll.CurrentValDisplayStringMargin = new Thickness(thisPianoRoll.CurrentValDisplayStringMargin.Left, 2, 0, 0); lastValY = e.GetPosition(MidiEventsIC).Y; } else {// horizontal shifting of midi event MouseDownMs = PixelsToMsecGrid(e.GetPosition(MidiEventsCanvas).X) / thisPianoRoll.WorkingGridXZoomFac; double diffMs = Math.Max(-mindiffMs, Math.Min(MouseDownMs - startMouseDownMs, maxdiffMs)); switch (MidiEventsIC.ItemsSource) { case var isource when isource == thisPianoRoll.myClip.ClipPitchChangeEvents: QDPitchChange pitchChangeEvent = (QDPitchChange)thisRect.DataContext; foreach (QDPitchChange qpb in originalPitchbends) { qpb.ClipRelTimeMs = qpb.OriginalMs + diffMs; qpb.UpdateMargin(); } pitchChangeEvent.UpdateMargin(); break; case var isource when isource == thisPianoRoll.myClip.ClipModulationEvents: QDModulation modulationEvent = (QDModulation)thisRect.DataContext; foreach (QDModulation qmod in originalModulations) { qmod.ClipRelTimeMs = qmod.OriginalMs + diffMs; qmod.UpdateMargin(); } break; } } } } double mindiffMs, maxdiffMs; double lastValY = 0; double startMouseDownMs; List previousNoteVelocities; List previousPitches; List previousModulations; private void MidiEventRect_PreviewMouseUp(object sender, MouseButtonEventArgs e) { e.Handled = true; MouseDownInMidiEventRect = false; DockPanel thisRect = (DockPanel)sender; thisPianoRoll.CurrentValDisplayString = ""; if (Cursor == Cursors.ScrollNS) { //change value of midi event switch (MidiEventsIC.ItemsSource) { case var isource when isource == thisPianoRoll.MidiNotes: QDMidiNote thisQDMnote = (QDMidiNote)thisRect.DataContext; undoActions.Add(new MidiNoteVelocitiesChangeUndo(myClip.UndoClipID, originalNotes.ConvertAll(mn => myClip.ClipMidiNotes.IndexOf(mn)), new List(previousNoteVelocities))); break; case var isource3 when isource3 == thisPianoRoll.myClip.ClipPitchChangeEvents: QDPitchChange thisPitchChange = (QDPitchChange)thisRect.DataContext; undoActions.Add(new MidiPitchValuesChangeUndo(myClip.UndoClipID, originalPitchbends.ConvertAll(pch => myClip.ClipPitchChangeEvents.IndexOf(pch)), new List(previousPitches))); break; case var isource when isource == thisPianoRoll.myClip.ClipModulationEvents: QDModulation thisModulation = (QDModulation)thisRect.DataContext; undoActions.Add(new MidiModulationValuesChangeUndo(myClip.UndoClipID, originalModulations.ConvertAll(mod => myClip.ClipModulationEvents.IndexOf(mod)), new List(previousModulations))); break; } } else { switch (MidiEventsIC.ItemsSource) { case var isource when isource == thisPianoRoll.myClip.ClipPitchChangeEvents: myClip.SortMidiEventSubGroup(typeof(QDPitchChange)); List pcbIndexes = originalPitchbends.ConvertAll(pcb => myClip.ClipPitchChangeEvents.IndexOf(pcb)); undoActions.Add(new MidiPitchbendMoveUndo(myClip.UndoClipID, pcbIndexes, originalPitchbends.ConvertAll(pcb => pcb.OriginalMs))); break; case var isource when isource == thisPianoRoll.myClip.ClipModulationEvents: myClip.SortMidiEventSubGroup(typeof(QDModulation)); List modIndexes = originalModulations.ConvertAll(mod => myClip.ClipModulationEvents.IndexOf(mod)); undoActions.Add(new MidiModulationMoveUndo(myClip.UndoClipID, modIndexes, originalModulations.ConvertAll(mod => mod.OriginalMs))); break; } } thisRect.ReleaseMouseCapture(); Keyboard.Focus(this); } private void MidiEventRect_PreviewMouseDown(object sender, MouseButtonEventArgs e) { e.Handled = true; DockPanel thisRect = (DockPanel)sender; thisRect.CaptureMouse(); QDMidiEvent thisQME = (QDMidiEvent)thisRect.DataContext; MouseDownInMidiEventRect = MouseInMidiEventRect; Grid thisGrid = (Grid)thisRect.Parent; thisPianoRoll.CurrentValDisplayStringMargin = new Thickness((thisGrid.Margin.Left + 10D / thisPianoRoll.WorkingGridXZoomFac) * thisPianoRoll.WorkingGridXZoomFac, 2, 0, 0); if (Cursor == Cursors.ScrollNS) { MouseDownEventMainValue = thisQME.MainValue; MouseDownInMidiEventY = e.GetPosition(MidiEventsSV).Y; lastValY = e.GetPosition(MidiEventsSV).Y; thisPianoRoll.CurrentValDisplayString = thisQME.DisplayString; switch (MidiEventsIC.ItemsSource) { case var isource when isource == thisPianoRoll.MidiNotes: QDMidiNote thisQDMnote = (QDMidiNote)thisRect.DataContext; if (thisPianoRoll.SelectedMidiNotes.Contains(thisQDMnote)) originalNotes = thisPianoRoll.SelectedMidiNotes; else originalNotes = new List() { thisQDMnote }; previousNoteVelocities = originalNotes.ConvertAll(smn => smn.Velocity); break; case var isource when isource == myClip.ClipPitchChangeEvents: QDPitchChange thisPitchChange = (QDPitchChange)thisRect.DataContext; List selectedPitchChanges = myClip.ClipPitchChangeEvents.Where(pch => pch.Selected).ToList(); if (selectedPitchChanges.Contains(thisPitchChange)) originalPitchbends = selectedPitchChanges; else originalPitchbends = new List() { thisPitchChange }; previousPitches = originalPitchbends.ConvertAll(pch => pch.PitchValue); break; case var isource when isource == myClip.ClipModulationEvents: QDModulation thisModulation = (QDModulation)thisRect.DataContext; List selectedModulations = myClip.ClipModulationEvents.Where(mod => mod.Selected).ToList(); if (selectedModulations.Contains(thisModulation)) originalModulations = selectedModulations; else originalModulations = new List() { thisModulation }; previousModulations = originalModulations.ConvertAll(mod=>mod.ModValue); break; } } else { if (Cursor == Cursors.ScrollWE) { MouseDownInMidiEventX = e.GetPosition(MidiEventsCanvas).X; thisPianoRoll.CurrentValDisplayString = Math.Round(thisQME.ClipRelTimeMs).ToString() + " ms"; QDMidiEvent minSelectedEvent = null; QDMidiEvent maxSelectedEvent = null; switch (MidiEventsIC.ItemsSource) { case var isource when isource == myClip.ClipPitchChangeEvents: QDPitchChange thisPitchbend = (QDPitchChange)thisRect.DataContext; startMouseDownMs = thisPitchbend.ClipRelTimeMs; originalPitchbends = myClip.ClipPitchChangeEvents.Where(pch => pch.Selected).ToList(); if (!originalPitchbends.Contains(thisPitchbend)) originalPitchbends = new List() { thisPitchbend }; foreach (QDPitchChange qpcb in originalPitchbends) { qpcb.OriginalMs = qpcb.ClipRelTimeMs; } //foreach (QDPitchChange qpcb in originalPitchbends) { qpcb.OriginalMs = qpcb.ClipRelTimeMs; qpcb.OriginalIndex = myClip.ClipPitchChangeEvents.IndexOf(qpcb); } minSelectedEvent = originalPitchbends.FirstOrDefault(pcb => pcb.ClipRelTimeMs == originalPitchbends.Min(spcb => spcb.ClipRelTimeMs)); maxSelectedEvent = originalPitchbends.LastOrDefault(pcb => pcb.ClipRelTimeMs == originalPitchbends.Max(spcb => spcb.ClipRelTimeMs)); break; case var isource when isource == myClip.ClipModulationEvents: QDModulation thisModulation = (QDModulation)thisRect.DataContext; startMouseDownMs = thisModulation.ClipRelTimeMs; originalModulations = myClip.ClipModulationEvents.Where(mod => mod.Selected).ToList(); if (!originalModulations.Contains(thisModulation)) originalModulations = new List() { thisModulation }; //foreach (QDModulation qmod in originalModulations) {qmod.OriginalMs = qmod.ClipRelTimeMs; qmod.OriginalIndex = myClip.ClipModulationEvents.IndexOf(qmod); } foreach (QDModulation qmod in originalModulations) { qmod.OriginalMs = qmod.ClipRelTimeMs; } minSelectedEvent = originalModulations.FirstOrDefault(mod => mod.ClipRelTimeMs == originalModulations.Min(smod => smod.ClipRelTimeMs)); maxSelectedEvent = originalModulations.LastOrDefault(mod => mod.ClipRelTimeMs == originalModulations.Max(smod => smod.ClipRelTimeMs)); break; } mindiffMs = minSelectedEvent.ClipRelTimeMs; maxdiffMs = thisPianoRoll.myClip.ClipWidthMs - maxSelectedEvent.ClipRelTimeMs - 50; } } } bool MouseDownOnEventsCanvas = false; bool EventDrawAddMode = false; bool EventDrawChangeMode = false; List originalPitchbends = new List(); List erasedPitchbends = new List(); List originalModulations = new List(); List erasedModulations = new List(); List overlappedPitchbends = new List(); List overlappedModulations = new List(); List overlappedVelocities = new List(); List originalNotes = new List(); List originalPitchVals = new List(); List originalModVals = new List(); List originalVelocityVals = new List(); int addedEventCount; int insertIndex; private void MidiEventsCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e) { MidiEventsCanvas.Focus(); if (MouseInMidiEventRect) return; MidiEventsCanvas.CaptureMouse(); thisPianoRoll.EventSelLeftPix = e.GetPosition(MidiEventsCanvas).X; thisPianoRoll.EventSelTopPix = e.GetPosition(MidiEventsCanvas).Y; MouseDownMs = PixelsToMsecGrid(thisPianoRoll.EventSelLeftPix) / thisPianoRoll.WorkingGridXZoomFac; lastMouseX = e.GetPosition(MidiEventsCanvas).X; if (Keyboard.IsKeyDown(Key.LeftCtrl)) { //Draw new events and erase any in path EventDrawAddMode = true; addedEventCount = 0; Cursor = Cursors.Pen; switch (MidiEventsIC.ItemsSource) { case var isource when isource == myClip.ClipPitchChangeEvents: QDPitchChange qdpch = myClip.ClipPitchChangeEvents.LastOrDefault(pc => pc.ClipRelTimeMs < MouseDownMs); insertIndex = (qdpch == null) ? 0 : myClip.ClipPitchChangeEvents.IndexOf(qdpch) + 1; originalPitchbends = new List(thisPianoRoll.myClip.ClipPitchChangeEvents); break; case var isource when isource == myClip.ClipModulationEvents: QDModulation qdmod = myClip.ClipModulationEvents.LastOrDefault(pc => pc.ClipRelTimeMs < MouseDownMs); insertIndex = (qdmod == null) ? 0 : myClip.ClipModulationEvents.IndexOf(qdmod) + 1; originalModulations = new List(thisPianoRoll.myClip.ClipModulationEvents); break; } return; } if (Keyboard.IsKeyDown(Key.LeftShift)) { //Draw existing events to new values EventDrawChangeMode = true; Cursor = Cursors.Cross; switch (MidiEventsIC.ItemsSource) { case var isource when isource == myClip.ClipPitchChangeEvents: originalPitchVals.Clear(); QDPitchChange qdpch = myClip.ClipPitchChangeEvents.LastOrDefault(pc => pc.ClipRelTimeMs < MouseDownMs); insertIndex = (qdpch == null) ? 0 : myClip.ClipPitchChangeEvents.IndexOf(qdpch) + 1; break; case var isource when isource == myClip.ClipModulationEvents: originalModVals.Clear(); QDModulation qdmod = myClip.ClipModulationEvents.LastOrDefault(pc => pc.ClipRelTimeMs < MouseDownMs); insertIndex = (qdmod == null) ? 0 : myClip.ClipModulationEvents.IndexOf(qdmod) + 1; break; case var isource when isource == myClip.ClipMidiNotes: originalVelocityVals.Clear(); QDMidiNote qmn = myClip.ClipMidiNotes.LastOrDefault(pc => pc.ClipRelTimeMs < MouseDownMs); insertIndex = (qmn == null) ? 0 : myClip.ClipMidiNotes.IndexOf(qmn) + 1; break; } return; } MouseDownOnEventsCanvas = true; } private void MidiEventsCanvas_PreviewMouseUp(object sender, MouseButtonEventArgs e) { if (MouseDownInMidiEventRect) return; MouseDownOnEventsCanvas = false; MidiEventsCanvas.ReleaseMouseCapture(); Cursor = Cursors.Arrow; if (EventDrawAddMode) { switch (MidiEventsIC.ItemsSource) { case var isource when isource == myClip.ClipPitchChangeEvents: undoActions.Add(new MidiPitchDrawAddUndo(myClip.UndoClipID, addedEventCount, insertIndex, new List(erasedPitchbends))); originalPitchbends.Clear(); erasedPitchbends.Clear(); myClip.SortMidiEventSubGroup(typeof(QDPitchChange)); break; case var isource when isource == myClip.ClipModulationEvents: undoActions.Add(new MidiModulationDrawAddUndo(myClip.UndoClipID, addedEventCount, insertIndex, new List(erasedModulations))); originalModulations.Clear(); erasedModulations.Clear(); myClip.SortMidiEventSubGroup(typeof(QDModulation)); break; } EventDrawAddMode = false; return; } if (EventDrawChangeMode) { switch (MidiEventsIC.ItemsSource) { case var isource when isource == myClip.ClipPitchChangeEvents: undoActions.Add(new MidiPitchDrawChangeUndo(myClip.UndoClipID, insertIndex, new List(originalPitchVals))); break; case var isource when isource == myClip.ClipModulationEvents: undoActions.Add(new MidiModulationDrawChangeUndo(myClip.UndoClipID, insertIndex, new List(originalModVals))); break; case var isource when isource == myClip.ClipMidiNotes: undoActions.Add(new MidiVelocityDrawChangeUndo(myClip.UndoClipID, insertIndex, new List(originalVelocityVals))); break; } EventDrawChangeMode = false; return; } if (!thisPianoRoll.EventSelVisible && !MouseInMidiEventRect) { //Add midi event if applicable double newClipRelTimeMs = PixelsToMsecGrid(e.GetPosition(MidiEventsCanvas).X) / thisPianoRoll.WorkingGridXZoomFac; double percMouseY = 1D - e.GetPosition(MidiEventsCanvas).Y / MidiEventsCanvas.ActualHeight; if (MidiEventsIC.ItemsSource == myClip.ClipSustainEvents) { QDSustain susevent = new QDSustain(); susevent.MainValue = Math.Max(0, Math.Min(susevent.MaxEventValue, Math.Truncate(percMouseY * susevent.MaxEventValue))); susevent.ClipRelTimeMs = newClipRelTimeMs; susevent.UpdateEventReverseZoom(thisPianoRoll.WorkingGridXZoomFacReverse); myClip.ClipSustainEvents.Add(susevent); myClip.SortMidiEventSubGroup(typeof(QDSustain)); undoActions.Add(new MidiSustainAddUndo(myClip.UndoClipID, myClip.ClipSustainEvents.IndexOf(susevent))); } if (MidiEventsIC.ItemsSource == myClip.ClipPitchChangeEvents) { QDPitchChange pchevent = new QDPitchChange(); pchevent.MainValue = Math.Max(0, Math.Min(pchevent.MaxEventValue, Math.Truncate(percMouseY * pchevent.MaxEventValue))); pchevent.ClipRelTimeMs = newClipRelTimeMs; pchevent.UpdateEventReverseZoom(thisPianoRoll.WorkingGridXZoomFacReverse); myClip.ClipPitchChangeEvents.Add(pchevent); myClip.SortMidiEventSubGroup(typeof(QDPitchChange)); undoActions.Add(new MidiPitchChangeAddUndo(myClip.UndoClipID, myClip.ClipPitchChangeEvents.IndexOf(pchevent))); } if (MidiEventsIC.ItemsSource == myClip.ClipModulationEvents) { QDModulation modevent = new QDModulation(); modevent.MainValue = Math.Max(0, Math.Min(modevent.MaxEventValue, Math.Truncate(percMouseY * modevent.MaxEventValue))); modevent.ClipRelTimeMs = newClipRelTimeMs; modevent.UpdateEventReverseZoom(thisPianoRoll.WorkingGridXZoomFacReverse); myClip.ClipModulationEvents.Add(modevent); myClip.SortMidiEventSubGroup(typeof(QDModulation)); undoActions.Add(new MidiModulationAddUndo(myClip.UndoClipID, myClip.ClipModulationEvents.IndexOf(modevent))); } } thisPianoRoll.EventSelVisible = false; } double lastMouseX = 0; double MouseDownMs; private void MidiEventsCanvas_PreviewMouseMove(object sender, MouseEventArgs e) { if (EventDrawAddMode) { double currPosX = e.GetPosition(MidiEventsCanvas).X; double newClipRelTimeMs = Math.Round(PixelsToMsecGrid(currPosX) / thisPianoRoll.WorkingGridXZoomFac); if (currPosX - lastMouseX > 0) { switch (MidiEventsIC.ItemsSource) { case var isource when isource == myClip.ClipPitchChangeEvents: overlappedPitchbends = originalPitchbends.Where(pche => (pche.ClipRelTimeMs >= MouseDownMs && pche.ClipRelTimeMs <= newClipRelTimeMs)).ToList(); foreach (QDPitchChange qpch in overlappedPitchbends) { erasedPitchbends.Add(qpch); originalPitchbends.Remove(qpch); thisPianoRoll.myClip.ClipPitchChangeEvents.Remove(qpch); } QDPitchChange pchevent = new QDPitchChange() { revZoomX = 1 / thisPianoRoll.WorkingGridXZoomFac }; pchevent.MainValue = Math.Max(0, Math.Min(pchevent.MaxEventValue, Math.Truncate((1D - e.GetPosition(MidiEventsCanvas).Y / MidiEventsCanvas.ActualHeight) * pchevent.MaxEventValue))); pchevent.ClipRelTimeMs = newClipRelTimeMs; myClip.ClipPitchChangeEvents.Insert(insertIndex + addedEventCount, pchevent); addedEventCount += 1; break; case var isource when isource == myClip.ClipModulationEvents: overlappedModulations = originalModulations.Where(pche => (pche.ClipRelTimeMs >= MouseDownMs && pche.ClipRelTimeMs <= newClipRelTimeMs)).ToList(); foreach (QDModulation qmod in overlappedModulations) { erasedModulations.Add(qmod); originalModulations.Remove(qmod); thisPianoRoll.myClip.ClipModulationEvents.Remove(qmod); } QDModulation pchmod = new QDModulation() { revZoomX = 1 / thisPianoRoll.WorkingGridXZoomFac }; pchmod.MainValue = Math.Max(0, Math.Min(pchmod.MaxEventValue, Math.Truncate((1D - e.GetPosition(MidiEventsCanvas).Y / MidiEventsCanvas.ActualHeight) * pchmod.MaxEventValue))); pchmod.ClipRelTimeMs = newClipRelTimeMs; myClip.ClipModulationEvents.Insert(insertIndex + addedEventCount, pchmod); addedEventCount += 1; break; } lastMouseX = currPosX; } return; } if (EventDrawChangeMode) { double currPosX = e.GetPosition(MidiEventsCanvas).X; double newClipRelTimeMs = Math.Round(PixelsToMsecGrid(currPosX) / thisPianoRoll.WorkingGridXZoomFac); double oldClipRelTimeMs = Math.Round(PixelsToMsecGrid(lastMouseX) / thisPianoRoll.WorkingGridXZoomFac); if (currPosX - lastMouseX > 0) { switch (MidiEventsIC.ItemsSource) { case var isource when isource == myClip.ClipPitchChangeEvents: overlappedPitchbends = myClip.ClipPitchChangeEvents.Where(pche => (pche.ClipRelTimeMs > oldClipRelTimeMs && pche.ClipRelTimeMs <= newClipRelTimeMs) && !overlappedPitchbends.Contains(pche)).ToList(); originalPitchVals.AddRange(new List(overlappedPitchbends.ConvertAll(pb => pb.PitchValue))); double percMouseYP = 1D - e.GetPosition(MidiEventsCanvas).Y / MidiEventsCanvas.ActualHeight - 0.085; foreach (QDPitchChange pch in overlappedPitchbends) pch.PitchValue = (int)Math.Max(0, Math.Min(pch.MaxEventValue, Math.Truncate(percMouseYP * pch.MaxEventValue))); break; case var isource when isource == myClip.ClipModulationEvents: overlappedModulations = myClip.ClipModulationEvents.Where(mod => (mod.ClipRelTimeMs > oldClipRelTimeMs && mod.ClipRelTimeMs <= newClipRelTimeMs) && !overlappedModulations.Contains(mod)).ToList(); originalModVals.AddRange(new List(overlappedModulations.ConvertAll(mod => mod.ModValue))); double percMouseYM = 1D - e.GetPosition(MidiEventsCanvas).Y / MidiEventsCanvas.ActualHeight - 0.085; foreach (QDModulation mod in overlappedModulations) mod.ModValue = (int)Math.Max(0, Math.Min(mod.MaxEventValue, Math.Truncate(percMouseYM * mod.MaxEventValue))); break; case var isource when isource == myClip.ClipMidiNotes: overlappedVelocities = myClip.ClipMidiNotes.Where(qmn => (qmn.ClipRelTimeMs > oldClipRelTimeMs && qmn.ClipRelTimeMs <= newClipRelTimeMs) && !overlappedVelocities.Contains(qmn)).ToList(); originalVelocityVals.AddRange(new List(overlappedVelocities.ConvertAll(qmn => qmn.Velocity))); double percMouseYV = 1D - e.GetPosition(MidiEventsCanvas).Y / MidiEventsCanvas.ActualHeight - 0.085; foreach (QDMidiNote qmn in overlappedVelocities) qmn.Velocity = (int)Math.Max(0, Math.Min(qmn.MaxEventValue, Math.Truncate(percMouseYV * qmn.MaxEventValue))); break; } addedEventCount += 1; lastMouseX = currPosX; } return; } if (MouseDownOnEventsCanvas) { double selwidth = e.GetPosition(MidiEventsCanvas).X - thisPianoRoll.EventSelLeftPix; double selheight = e.GetPosition(MidiEventsCanvas).Y - thisPianoRoll.EventSelTopPix; if (selwidth > 5 || selheight > 5) { thisPianoRoll.EventSelVisible = true; thisPianoRoll.EventSelHeightPix = Math.Max(5, selheight); thisPianoRoll.EventSelWidthPix = Math.Max(5, selwidth); IEnumerable shownEvents = (IEnumerable)MidiEventsIC.ItemsSource; foreach (QDMidiEvent selmevent in shownEvents.Where(sme => sme.Selected)) selmevent.Selected = false; foreach (QDMidiEvent mevent in shownEvents.Where(mev => thisPianoRoll.ContainsEvent(mev, MidiEventsCanvas.ActualHeight))) mevent.Selected = true; } } } } }