using QuikDawEditor.EditingClasses; using QuikDawEditor.Undo; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.Windows.Shapes; using static QuikDawEditor.EDITING.MiscMethods; using static QuikDawEditor.EDITING.StaticProperties; namespace QuikDawEditor.EDITING.PianoRollModel; public partial class PianoRollModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public void RelRes() { ReleaseResources(); } public delegate void VerticalScrollChangeEventHandler(double setVertical); public event VerticalScrollChangeEventHandler VerticalScrollChange; public delegate void ScrollToNoteChangeEventHandler(double scrollToNote); public event ScrollToNoteChangeEventHandler ScrollToNoteChange; public double PianoRollHeight { get { return 1160; } } public double ScaleCanvasHeight { get { return 20; } } public Visibility PianoRollVisibility { get { return IsVisible ? Visibility.Visible : Visibility.Hidden; } } private bool _IsVisible = false; public bool IsVisible { get { return _IsVisible; } set { _IsVisible = value; NotifyPropertyChanged(nameof(PianoRollVisibility)); } } public ObservableCollection GridMeasureNos { get; set; } = new ObservableCollection(); public ObservableCollection NoteNames { get; set; } = new ObservableCollection(); public ObservableCollection GridMeasureScaleLines { get; set; } = new ObservableCollection(); public ObservableCollection GridMeasureContentLines { get; set; } = new ObservableCollection(); public ObservableCollection TripletLines { get; set; } = new ObservableCollection(); public List PianoKeys { get; set; } = new List(); private string _CurrentValDisplayString = ""; public string CurrentValDisplayString { get { return _CurrentValDisplayString; } set { _CurrentValDisplayString = value; NotifyPropertyChanged(nameof(CurrentValDisplayString)); NotifyPropertyChanged(nameof(CurrentValDisplayStringVisibility)); } } public Visibility CurrentValDisplayStringVisibility { get { return _CurrentValDisplayString == "" ? Visibility.Hidden : Visibility.Visible; } } private Thickness _CurrentValDisplayStringMargin; public Thickness CurrentValDisplayStringMargin { get { return _CurrentValDisplayStringMargin; } set { _CurrentValDisplayStringMargin = value; NotifyPropertyChanged(nameof(CurrentValDisplayStringMargin)); } } public PianoRollModel() { DrawHorizontalLines(); GetPianoKeys(); } public double NotesGridWidth { get { return myClip == null ? 800 : MsecToPixelsGrid(myClip.ClipSourceLenMilliseconds); } } public double UnusedSourceWidthHead { get { return myClip == null ? 0 : MsecToPixelsGrid(myClip.ClipRelativeLoopStartMs); } } public double UnusedSourceWidthTail { get { return myClip == null ? 0 : MsecToPixelsGrid(myClip.ClipSourceLenMilliseconds - myClip.ClipRelativeLoopEndMs); } } private double _CurrentMidiPlayingPosMS = 0; public double CurrentMidiPlayingPosMS { get { return _CurrentMidiPlayingPosMS; } set { _CurrentMidiPlayingPosMS = value - myClip.ClipLeftMs + myClip.ClipRelativeLoopStartMs; NotifyPropertyChanged(nameof(CurrentMidiPlayingPosPix)); } } public double CurrentMidiPlayingPosPix { get { return MsecToPixelsGrid(CurrentMidiPlayingPosMS); } } double measurePixels { get { return MsecToPixelsGrid(MillisecondsPerBeat * editingProject.BeatsPerMeasure); } } double _VerticalScrollValue = 0; internal double VerticalScrollValue { get { return _VerticalScrollValue; } set { _VerticalScrollValue = value; if (VerticalScrollChange != null)VerticalScrollChange(value); } } internal List MidiEvents { get { return _myClip == null ? null : _myClip.ClipMidiEvents; } } public ObservableCollection MidiNotes { get { return _myClip == null ? null : _myClip.ClipMidiNotes; } } internal List SelectedMidiNotes { get { return _myClip == null ? null : MidiNotes.Where(mn => mn.Selected).ToList(); } } internal void UpdateMidiNotesDisplay() { NotifyPropertyChanged(nameof(MidiNotes)); NotifyPropertyChanged(nameof(SelectedMidiNotes)); NotifyPropertyChanged(nameof(MidiEvents)); } public double keepPlayPos = 0; private Clip _myClip = null; public Clip myClip { get { return _myClip; } set { if (!IsUndoing) if (_myClip == null || value == null || _myClip.UndoClipID != value.UndoClipID) undoActions.Add(new MidiEditingSourceClipSelectUndo(this, _myClip == null ? "" : _myClip.UndoClipID, VerticalScrollValue)); _myClip = value; if (_myClip == null) IsVisible = false; else { CurrentMidiPlayingPosMS = _myClip.ClipLeftMs; NotifyPropertyChanged(nameof(NotesGridWidth)); NotifyPropertyChanged(nameof(UnusedSourceWidthHead)); NotifyPropertyChanged(nameof(UnusedSourceWidthTail)); NotifyPropertyChanged(nameof(MidiNotes)); foreach (QDMidiEvent qdme in _myClip.ClipMidiEvents) qdme.UpdateEventReverseZoom(WorkingGridXZoomFacReverse); } } } private void MyClip_clipSourceSizeChanged() { DrawMeasureLines(); } private void MyClip_clipSizeChanged() { UpdateUnusedSourceWidth(); } internal void UpdatePianoRollDisplayAll() { DrawMeasureLines(); DrawTripletLines(); NotifyPropertyChanged(nameof(NotesGridWidth)); UpdateUnusedSourceWidth(); } internal void UpdateUnusedSourceWidth() { NotifyPropertyChanged(nameof(UnusedSourceWidthHead)); NotifyPropertyChanged(nameof(UnusedSourceWidthTail)); } internal void SetClip(Clip settingClip) { if (myClip != null) { myClip.clipSizeChanged -= MyClip_clipSizeChanged; myClip.clipSourceSizeChanged -= MyClip_clipSourceSizeChanged; } myClip = settingClip; IsVisible = true; SelectedMidiEventIndex = -1; SelectedMidiEventIndex = 0; if (myClip != null) { myClip.clipSizeChanged += MyClip_clipSizeChanged; myClip.clipSourceSizeChanged += MyClip_clipSourceSizeChanged; } if (MidiNotes == null) return; double avNote = MidiNotes.Count == 0 ? 67 : MidiNotes.Take(new Range(0, Math.Min(MidiNotes.Count, 5))).ToList().Average(mn => mn.Note); ScrollToNoteChange(avNote); } internal int PreviousMidiEventIndex = 0; private int _selectedMidiEventIndex = 0; public int SelectedMidiEventIndex { get { return _selectedMidiEventIndex; } set { _selectedMidiEventIndex = value; NotifyPropertyChanged(nameof(SelectedMidiEventIndex)); } } private bool _clipPlaying = false; public bool clipPlaying { get { return _clipPlaying; } set { _clipPlaying = value; NotifyPropertyChanged(nameof(MidiPlayButImageSource)); } } public string MidiPlayButImageSource { get { return clipPlaying ? "/EDITING/images/StopButImg.png" : "/EDITING/images/PlayButImgAlt.png"; } } private bool _TripletOn = false; public bool TripletOn { get { return _TripletOn; } set { _TripletOn = value; NotifyPropertyChanged(nameof(TripletButImageSource)); NotifyPropertyChanged(nameof(TripletOn)); NotifyPropertyChanged(nameof(GridLinesCanvasOpacity)); } } public string TripletButImageSource { get { return TripletOn ? "/EDITING/images/TripletButOn.png" : "/EDITING/images/TripletButOff.png"; } } public double GridLinesCanvasOpacity { get { return TripletOn ? 0.35 : 1; } } public Track myTrack; public bool keepProjectPlaying = false; public void StopPlay() { if (myTrack != null) myTrack.TrackOutputVolume = 0; projPlayer.CurrentPlayingPosMS = keepPlayPos; foreach (Track t in editingProject.GetAllTracksInProject) t.IsPianoRollMuted = false; } private double _WorkingGridXZoomFac = 1; public double WorkingGridXZoomFac { get { return _WorkingGridXZoomFac; } set { _WorkingGridXZoomFac = value; NotifyPropertyChanged(nameof(WorkingGridXZoomFac)); NotifyPropertyChanged(nameof(WorkingGridXZoomFacReverse)); NotifyPropertyChanged(nameof(NoteSelectBorderThickness)); foreach (QDMidiEvent mevent in MidiEvents) mevent.UpdateEventReverseZoom(WorkingGridXZoomFacReverse); } } public Thickness NoteSelectBorderThickness { get { return new Thickness(WorkingGridXZoomFacReverse, 1, WorkingGridXZoomFacReverse, 1); } } public double WorkingGridXZoomFacReverse { get { return 1 / _WorkingGridXZoomFac; } } private bool _SelVisible = false; public bool SelVisible { get { return _SelVisible; } set { _SelVisible = value; NotifyPropertyChanged(nameof(SelVisible)); } } private double _SelWidthMs = 100; public double SelWidthMs { get { return _SelWidthMs; } set { _SelWidthMs = value; NotifyPropertyChanged(nameof(SelWidthPix)); } } public double SelWidthPix { get { return MsecToPixelsGrid(_SelWidthMs); } } private double _SelHeightPix = 60; public double SelHeightPix { get { return _SelHeightPix; } set { _SelHeightPix = value; NotifyPropertyChanged(nameof(SelHeightPix)); } } public double SelLeftMs { get { return PixelsToMsecGrid(SelLeftPix); } } private double _SelTopPix = 0; public double SelTopPix { get { return _SelTopPix; } set { _SelTopPix = value; NotifyPropertyChanged(nameof(SelMargin)); } } private double _SelLeftPix = 0; public double SelLeftPix { get { return _SelLeftPix; } set { _SelLeftPix = value; NotifyPropertyChanged(nameof(SelMargin)); } } public Thickness SelMargin { get { return new Thickness(SelLeftPix, SelTopPix, 0, 0); } } private bool _EventSelVisible = false; public bool EventSelVisible { get { return _EventSelVisible; } set { _EventSelVisible = value; NotifyPropertyChanged(nameof(EventSelVisible)); } } private double _EventSelTopPix = 0; public double EventSelTopPix { get { return _EventSelTopPix; } set { _EventSelTopPix = value; NotifyPropertyChanged(nameof(EventSelMargin)); } } private double _EventSelLeftPix = 0; public double EventSelLeftPix { get { return _EventSelLeftPix; } set { _EventSelLeftPix = value; NotifyPropertyChanged(nameof(EventSelMargin)); } } public Thickness EventSelMargin { get { return new Thickness(EventSelLeftPix, EventSelTopPix, 0, 0); } } private double _EventSelWidthPix = 10; public double EventSelWidthPix { get { return _EventSelWidthPix; } set { _EventSelWidthPix = value; NotifyPropertyChanged(nameof(EventSelWidthPix)); } }//{ get { return MsecToPixelsGrid(_EventSelWidthMs); } } private double _EventSelHeightPix = 60; public double EventSelHeightPix { get { return _EventSelHeightPix; } set { _EventSelHeightPix = value; NotifyPropertyChanged(nameof(EventSelHeightPix)); } } public double EventSelLeftMs { get { return PixelsToMsecGrid(EventSelLeftPix / WorkingGridXZoomFac); } } public double EventSelWidthMs { get { return PixelsToMsecGrid(_EventSelWidthPix) / WorkingGridXZoomFac; } } public double NoteYPix(int noteno) { int GridHeight = (int)(PianoRollNoteHeight * NumMidiNotesVertical); return GridHeight - PianoRollNoteHeight - noteno * PianoRollNoteHeight; } public double PianokeyYPix(int noteno) { int GridHeight = (int)(PianoRollNoteHeight * NumMidiNotesVertical); return GridHeight - PianoRollNoteHeight - noteno * PianoRollNoteHeight; } internal bool ContainsNote(QDMidiNote mn) { double xMs = mn.ClipRelNoteOnTimeMs; double wMs = mn.ClipRelNoteOnTimeMs + mn.NoteLengthMs; double yPix = NoteYPix(mn.Note); return xMs > SelLeftMs && wMs < SelLeftMs + SelWidthMs && yPix > SelTopPix - PianoRollNoteHeight && yPix < SelTopPix + SelHeightPix - PianoRollNoteHeight * 1.2; } internal bool ContainsEvent(QDMidiEvent qme, double canvasHeight) { double xMs = qme.ClipRelTimeMs; double yPixTop = Math.Max(0, 10D - qme.DisplayLineHeightPerc.Value * 0.95) / 10D * canvasHeight + 4; return xMs > EventSelLeftMs && xMs < EventSelLeftMs + EventSelWidthMs && yPixTop > EventSelTopPix && yPixTop < EventSelTopPix + EventSelHeightPix; } private void GetPianoKeys() { for (int noteno = 0; noteno < NumMidiNotesVertical; noteno += 1) { PianoKeys.Add(new PianoKey(noteno, PianoRollNoteHeight)); } } }