diff --git a/DereTore.Applications.ScoreViewer/Controls/RenderHelper.cs b/DereTore.Applications.ScoreViewer/Controls/RenderHelper.cs index 24570b4..42e3e80 100644 --- a/DereTore.Applications.ScoreViewer/Controls/RenderHelper.cs +++ b/DereTore.Applications.ScoreViewer/Controls/RenderHelper.cs @@ -97,7 +97,11 @@ public static void DrawNotes(RenderParams renderParams, IList notes, int s switch (note.Type) { case NoteType.TapOrFlick: if (note.FlickType == NoteStatus.Tap) { - DrawTapNote(renderParams, note); + if (note.IsHoldRelease) { + DrawHoldNote(renderParams, note); + } else { + DrawTapNote(renderParams, note); + } } else { DrawFlickNote(renderParams, note); } diff --git a/DereTore.Applications.ScoreViewer/Model/Note.cs b/DereTore.Applications.ScoreViewer/Model/Note.cs index 201cfeb..31f1c91 100644 --- a/DereTore.Applications.ScoreViewer/Model/Note.cs +++ b/DereTore.Applications.ScoreViewer/Model/Note.cs @@ -69,7 +69,7 @@ public sealed class Note : ICloneable { [Browsable(false)] public bool IsHoldPress => Type == NoteType.Hold && HasNextHold; [Browsable(false)] - public bool IsHoldRelease => Type == NoteType.Hold && HasPrevHold; + public bool IsHoldRelease => (Type == NoteType.TapOrFlick || Type == NoteType.Slide) && HasPrevHold; [Browsable(false)] public bool IsSlide => Type == NoteType.Slide; [Browsable(false)] diff --git a/DereTore.Applications.ScoreViewer/Properties/AssemblyInfo.cs b/DereTore.Applications.ScoreViewer/Properties/AssemblyInfo.cs index 774202a..5414048 100644 --- a/DereTore.Applications.ScoreViewer/Properties/AssemblyInfo.cs +++ b/DereTore.Applications.ScoreViewer/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.7.0.0")] +[assembly: AssemblyFileVersion("0.7.1.0")] diff --git a/StarlightDirector.Entities/Note.cs b/StarlightDirector.Entities/Note.cs index 5903a5a..7e61526 100644 --- a/StarlightDirector.Entities/Note.cs +++ b/StarlightDirector.Entities/Note.cs @@ -173,7 +173,7 @@ public bool IsSlide { public bool IsSlideStart => Type == NoteType.Slide && !HasPrevFlickOrSlide && HasNextFlickOrSlide; - public bool IsSlideContinuation => Type == NoteType.Slide && HasPrevFlickOrSlide && HasNextFlickOrSlide; + public bool IsSlideContinuation => Type == NoteType.Slide && HasPrevFlickOrSlide && HasNextFlickOrSlide && PrevFlickOrSlideNote.IsSlide && NextFlickOrSlideNote.IsSlide; public bool IsSlideEnd => Type == NoteType.Slide && !HasNextFlickOrSlide && HasPrevFlickOrSlide; @@ -429,6 +429,7 @@ private static void OnTypeChanged(DependencyObject obj, DependencyPropertyChange note.IsTap = note.IsTapInternal(); note.IsSlide = note.IsSlideInternal(); note.UpdateFlickTypeStep2(); + note.DecideRenderingAsFlickOrSlide(); } private static void OnFlickTypeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { @@ -436,6 +437,7 @@ private static void OnFlickTypeChanged(DependencyObject obj, DependencyPropertyC note.IsFlick = note.IsFlickInternal(); note.IsTap = note.IsTapInternal(); note.IsSlide = note.IsSlideInternal(); + note.DecideRenderingAsFlickOrSlide(); } private static void OnExtraParamsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { @@ -487,10 +489,12 @@ private void UpdateFlickTypeStep2() { } } } + } + private void DecideRenderingAsFlickOrSlide() { if (IsFlick || IsSlide) { if (IsSlide) { - ShouldBeRenderedAsSlide = HasNextFlickOrSlide && !NextFlickOrSlideNote.IsFlick; + ShouldBeRenderedAsSlide = !HasNextFlickOrSlide || !NextFlickOrSlideNote.IsFlick; } else { ShouldBeRenderedAsSlide = false; } diff --git a/StarlightDirector/Properties/AssemblyInfo.cs b/StarlightDirector/Properties/AssemblyInfo.cs index 8dc96da..6daf701 100644 --- a/StarlightDirector/Properties/AssemblyInfo.cs +++ b/StarlightDirector/Properties/AssemblyInfo.cs @@ -50,6 +50,6 @@ // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.4.0.0")] -[assembly: AssemblyFileVersion("0.7.0.0")] +[assembly: AssemblyFileVersion("0.7.1.0")] [assembly: Guid("de69897a-be1b-410a-a159-814b5f4033b4")] diff --git a/StarlightDirector/UI/Controls/ScoreEditor.DependencyProperties.cs b/StarlightDirector/UI/Controls/ScoreEditor.DependencyProperties.cs index 107d866..4275585 100644 --- a/StarlightDirector/UI/Controls/ScoreEditor.DependencyProperties.cs +++ b/StarlightDirector/UI/Controls/ScoreEditor.DependencyProperties.cs @@ -1,4 +1,5 @@ using System.Windows; +using System.Windows.Controls; using System.Windows.Input; using StarlightDirector.Entities; @@ -15,12 +16,20 @@ public Project Project { set { SetValue(ProjectProperty, value); } } + public TextBlock NoteInfoBlock { + get { return (TextBlock)GetValue(NoteInfoBlockProperty); } + set { SetValue(NoteInfoBlockProperty, value); } + } + public static readonly DependencyProperty EditModeProperty = DependencyProperty.Register(nameof(EditMode), typeof(EditMode), typeof(ScoreEditor), new PropertyMetadata(EditMode.Select)); public static readonly DependencyProperty ProjectProperty = DependencyProperty.Register(nameof(Project), typeof(Project), typeof(ScoreEditor), new PropertyMetadata(null, OnProjectChanged)); + public static readonly DependencyProperty NoteInfoBlockProperty = DependencyProperty.Register(nameof(NoteInfoBlock), typeof(TextBlock), typeof(ScoreEditor), + new PropertyMetadata(null)); + private static void OnProjectChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { var editor = (ScoreEditor)obj; var oldproject = (Project)e.OldValue; diff --git a/StarlightDirector/UI/Controls/ScoreEditor.Editing.cs b/StarlightDirector/UI/Controls/ScoreEditor.Editing.cs index 3c59c0b..151e460 100644 --- a/StarlightDirector/UI/Controls/ScoreEditor.Editing.cs +++ b/StarlightDirector/UI/Controls/ScoreEditor.Editing.cs @@ -114,6 +114,8 @@ private ScoreNote AddScoreNote(ScoreBar scoreBar, int row, int column, Note data scoreNote.MouseDown += ScoreNote_MouseDown; scoreNote.MouseUp += ScoreNote_MouseUp; scoreNote.MouseDoubleClick += ScoreNote_MouseDoubleClick; + scoreNote.MouseEnter += ScoreNote_MouseEnter; + scoreNote.MouseLeave += ScoreNote_MouseLeave; if (dataTemplate == null) { Project.IsChanged = true; } @@ -142,6 +144,8 @@ private void RemoveScoreNote(ScoreNote scoreNote, bool modifiesModel, bool repos scoreNote.MouseDown -= ScoreNote_MouseDown; scoreNote.MouseUp -= ScoreNote_MouseUp; scoreNote.MouseDoubleClick -= ScoreNote_MouseDoubleClick; + scoreNote.MouseEnter -= ScoreNote_MouseEnter; + scoreNote.MouseLeave -= ScoreNote_MouseLeave; scoreNote.ContextMenu = null; EditableScoreNotes.Remove(scoreNote); LineLayer.NoteRelations.RemoveAll(scoreNote); diff --git a/StarlightDirector/UI/Controls/ScoreEditor.EventHandlers.cs b/StarlightDirector/UI/Controls/ScoreEditor.EventHandlers.cs index 23063f6..e7810c5 100644 --- a/StarlightDirector/UI/Controls/ScoreEditor.EventHandlers.cs +++ b/StarlightDirector/UI/Controls/ScoreEditor.EventHandlers.cs @@ -1,7 +1,9 @@ using System; using System.Diagnostics; +using System.Linq; using System.Windows; using System.Windows.Controls; +using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using StarlightDirector.Entities; @@ -137,14 +139,14 @@ private void ScoreNote_MouseUp(object sender, MouseButtonEventArgs e) { throw new ArgumentOutOfRangeException(nameof(mode)); } var first = ns < ne ? ns : ne; + var second = first.Equals(ns) ? ne : ns; if (ns.Bar == ne.Bar && ns.IndexInGrid == ne.IndexInGrid && !ns.IsSync && !ne.IsSync) { // sync Note.ConnectSync(ns, ne); LineLayer.NoteRelations.Add(start, end, NoteRelation.Sync); LineLayer.InvalidateVisual(); - } else if (ns.FinishPosition != ne.FinishPosition && (ns.Bar != ne.Bar || ns.IndexInGrid != ne.IndexInGrid) && (!ns.IsHoldStart && !ne.IsHoldStart)) { + } else if (ns.FinishPosition != ne.FinishPosition && (ns.Bar != ne.Bar || ns.IndexInGrid != ne.IndexInGrid) && (!ns.IsHoldStart && !ne.IsHoldStart) && !second.IsFlick) { // flick - var second = first.Equals(ns) ? ne : ns; if (first.HasNextFlickOrSlide || second.HasPrevFlickOrSlide) { MessageBox.Show(Application.Current.FindResource(App.ResourceKeys.FlickRelationIsFullPrompt), App.Title, MessageBoxButton.OK, MessageBoxImage.Exclamation); return; @@ -152,7 +154,7 @@ private void ScoreNote_MouseUp(object sender, MouseButtonEventArgs e) { Note.ConnectFlick(first, second); LineLayer.NoteRelations.Add(start, end, NoteRelation.FlickOrSlide); LineLayer.InvalidateVisual(); - } else if (ns.FinishPosition == ne.FinishPosition && !ns.IsHold && !ne.IsHold && !first.IsFlick) { + } else if (ns.FinishPosition == ne.FinishPosition && !ns.IsHold && !ne.IsHold && !first.IsFlick && !first.IsSlide && !second.IsSlide) { // hold var anyObstacles = Score.Notes.AnyNoteBetween(ns, ne); if (anyObstacles) { @@ -206,6 +208,74 @@ private void ScoreNote_MouseDoubleClick(object sender, MouseButtonEventArgs e) { e.Handled = true; } + private void ScoreNote_MouseEnter(object sender, MouseEventArgs e) { + var block = NoteInfoBlock; + if (block == null) { + return; + } + var scoreNote = (ScoreNote)sender; + var note = scoreNote.Note; + + block.Inlines.Add($"ID: {note.ID}"); + block.Inlines.Add(new LineBreak()); + block.Inlines.Add($"Timing: {note.HitTiming:0.000000}s"); + + string noteTypeString; + if (note.IsTap) { + noteTypeString = "Tap"; + } else if (note.IsFlick) { + noteTypeString = "Flick"; + } else if (note.IsHold) { + noteTypeString = "Hold"; + } else if (note.IsSlide) { + noteTypeString = "Slide"; + if (note.IsSlideStart) { + noteTypeString += " (start)"; + } else if (note.IsSlideContinuation) { + noteTypeString += " (continued)"; + } else if (note.IsSlideEnd) { + noteTypeString += " (end)"; + } + } else { + noteTypeString = "#ERR"; + } + string noteExtra = null; + if (note.IsSync || note.IsHoldEnd) { + var syncStr = note.IsSync ? "sync" : null; + var holdEndStr = note.IsHoldEnd ? "hold-end" : null; + var extras = new[] { syncStr, holdEndStr }; + noteExtra = extras.Aggregate((prev, val) => { + if (string.IsNullOrEmpty(prev)) { + return val; + } + if (string.IsNullOrEmpty(val)) { + return prev; + } + return prev + ", " + val; + }); + } + var flickStr = note.FlickType != NoteFlickType.Tap ? (note.FlickType == NoteFlickType.FlickLeft ? "left" : "right") : null; + block.Inlines.Add(new LineBreak()); + block.Inlines.Add($"Type: {noteTypeString}"); + if (!string.IsNullOrEmpty(noteExtra)) { + block.Inlines.Add(new LineBreak()); + block.Inlines.Add(noteExtra); + } + if (!string.IsNullOrEmpty(flickStr)) { + block.Inlines.Add(new LineBreak()); + block.Inlines.Add($"Flick: {flickStr}"); + } + + block.Inlines.Add(new LineBreak()); + block.Inlines.Add($"Start: {(int)note.StartPosition}"); + block.Inlines.Add(new LineBreak()); + block.Inlines.Add($"Finish: {(int)note.FinishPosition}"); + } + + private void ScoreNote_MouseLeave(object sender, MouseEventArgs e) { + NoteInfoBlock?.Inlines.Clear(); + } + private void ScoreEditor_OnMouseDown(object sender, MouseButtonEventArgs e) { UnselectAllScoreNotes(); UnselectAllScoreBars(); diff --git a/StarlightDirector/UI/Controls/ScorePreviewer.xaml.cs b/StarlightDirector/UI/Controls/ScorePreviewer.xaml.cs index 605fda8..6f98299 100644 --- a/StarlightDirector/UI/Controls/ScorePreviewer.xaml.cs +++ b/StarlightDirector/UI/Controls/ScorePreviewer.xaml.cs @@ -88,7 +88,7 @@ public void BeginPreview(Score score, double targetFps, int startTime, double ap continue; NoteDrawType drawType; - if (note.IsHoldStart) { + if (note.IsHoldStart || (note.IsHoldEnd && note.IsTap)) { drawType = NoteDrawType.Hold; } else if (note.ShouldBeRenderedAsFlick) { drawType = (NoteDrawType)note.FlickType; diff --git a/StarlightDirector/UI/Windows/MainWindow.Commands.Edit.Note.cs b/StarlightDirector/UI/Windows/MainWindow.Commands.Edit.Note.cs index fc47954..4455480 100644 --- a/StarlightDirector/UI/Windows/MainWindow.Commands.Edit.Note.cs +++ b/StarlightDirector/UI/Windows/MainWindow.Commands.Edit.Note.cs @@ -127,8 +127,35 @@ private void CmdEditNoteSetSlideTypeToFlick_Executed(object sender, ExecutedRout private void CmdEditNoteSetSlideTypeToSlide_CanExecute(object sender, CanExecuteRoutedEventArgs e) { var notes = Editor.GetSelectedScoreNotes(); - var scoreNotes = notes as ScoreNote[] ?? notes.Reverse().ToArray(); - e.CanExecute = scoreNotes.Any() && scoreNotes.All(t => (t.Note.IsFlick && !t.Note.IsHoldEnd) || t.Note.IsSlide); + var scoreNotes = notes as List ?? notes.ToList(); + if (scoreNotes.Count == 0) { + e.CanExecute = false; + return; + } + if (scoreNotes.Count == 1) { + var note = scoreNotes[0].Note; + if (note.HasPrevFlickOrSlide || note.HasNextFlickOrSlide) { + e.CanExecute = false; + return; + } + } + + Note groupPrevNote = null; + scoreNotes.Sort((c1, c2) => Note.TimingThenPositionComparison(c1.Note, c2.Note)); + foreach (var scoreNote in scoreNotes) { + var note = scoreNote.Note; + if (!note.IsFlick && !note.IsSlide || note.IsHoldEnd) { + e.CanExecute = false; + return; + } + var prevNote = note.PrevFlickOrSlideNote; + if (prevNote != null && prevNote != groupPrevNote) { + e.CanExecute = false; + return; + } + groupPrevNote = note; + } + e.CanExecute = true; } private void CmdEditNoteSetSlideTypeToSlide_Executed(object sender, ExecutedRoutedEventArgs e) { diff --git a/StarlightDirector/UI/Windows/MainWindow.xaml b/StarlightDirector/UI/Windows/MainWindow.xaml index 0be2dfc..5e15f8a 100644 --- a/StarlightDirector/UI/Windows/MainWindow.xaml +++ b/StarlightDirector/UI/Windows/MainWindow.xaml @@ -217,12 +217,26 @@ + + + + + + + + + + + - - + @@ -233,7 +247,8 @@ - diff --git a/appveyor.yml b/appveyor.yml index 0a71f86..94dd3c9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ # https://www.appveyor.com/docs/appveyor-yml/ -version: 0.7.0.{build} +version: 0.7.1.{build} branches: only: - master