From 6629153f1a20a03793d136aef25ce1f3d797b26b Mon Sep 17 00:00:00 2001 From: MikiraSora Date: Sat, 24 Jun 2023 23:49:27 +0800 Subject: [PATCH] refatory DefaultWaveformDrawing and its option. --- .../CommonWaveformDrawingBase.cs | 6 +- .../DefaultImpls/DefaultWaveformDrawing.cs | 159 +++++++++--------- .../DefaultImpls/DefaultWaveformOption.cs | 27 +++ .../DefaultImpls/WaveformDrawingOptionBase.cs | 11 +- ...ayerToolViewerViewModel.WaveformDrawing.cs | 15 +- .../Views/AudioPlayerToolViewerView.xaml | 20 ++- .../FumenObjectPropertyBrowserViewModel.cs | 1 - .../FumenVisualEditor/TGridCalculator.cs | 4 +- 8 files changed, 150 insertions(+), 93 deletions(-) rename OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/{DefaultImpls => }/CommonWaveformDrawingBase.cs (79%) create mode 100644 OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/DefaultWaveformOption.cs diff --git a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/CommonWaveformDrawingBase.cs b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/CommonWaveformDrawingBase.cs similarity index 79% rename from OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/CommonWaveformDrawingBase.cs rename to OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/CommonWaveformDrawingBase.cs index 44c7b92d..87827fa7 100644 --- a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/CommonWaveformDrawingBase.cs +++ b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/CommonWaveformDrawingBase.cs @@ -1,15 +1,17 @@ -using OngekiFumenEditor.Kernel.Audio; +using OngekiFumenEditor.Base.Attributes; +using OngekiFumenEditor.Kernel.Audio; using OngekiFumenEditor.Kernel.Graphics; using OngekiFumenEditor.Kernel.Graphics.Drawing.DefaultDrawingImpl; using OpenTK.Mathematics; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using static OngekiFumenEditor.Kernel.Audio.ISamplePeak; -namespace OngekiFumenEditor.Modules.AudioPlayerToolViewer.Graphics.WaveformDrawing.DefaultImpls +namespace OngekiFumenEditor.Modules.AudioPlayerToolViewer.Graphics.WaveformDrawing { public abstract class CommonWaveformDrawingBase : CommonDrawingBase, IWaveformDrawing { diff --git a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/DefaultWaveformDrawing.cs b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/DefaultWaveformDrawing.cs index 4ff5f8d9..0f82a5fd 100644 --- a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/DefaultWaveformDrawing.cs +++ b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/DefaultWaveformDrawing.cs @@ -23,26 +23,8 @@ namespace OngekiFumenEditor.Modules.AudioPlayerToolViewer.Graphics.WaveformDrawing.DefaultImpls { [Export(typeof(IWaveformDrawing))] - public class DefaultWaveformDrawing : CommonWaveformDrawingBase + public partial class DefaultWaveformDrawing : CommonWaveformDrawingBase { - private class DefaultWaveformOption : WaveformDrawingOptionBase - { - private bool onlyShowContainsObjBeat = true; - public bool OnlyShowContainsObjBeat - { - get => onlyShowContainsObjBeat; - set => Set(ref onlyShowContainsObjBeat, value); - } - - - private bool showContainsObjBeat = true; - public bool ShowContainsObjBeat - { - get => showContainsObjBeat; - set => Set(ref showContainsObjBeat, value); - } - } - private readonly ISimpleLineDrawing lineDrawing; private readonly IStringDrawing stringDrawing; private readonly SoflanList dummySoflanList; @@ -52,7 +34,7 @@ public bool ShowContainsObjBeat private static readonly System.Numerics.Vector4 WhiteColor = new(1, 1, 1, 1); private static readonly System.Numerics.Vector4 IndirectorColor = new(1, 1, 0, 1); private static readonly System.Numerics.Vector4 BeatColor = new(1, 0, 0, 1); - private static readonly System.Numerics.Vector4 ContainsObjBeatColor = new(1, 1, 0, 1); + private static readonly System.Numerics.Vector4 ObjectPlaceColor = new(1, 1, 0, 1); private static readonly System.Numerics.Vector4 WaveformFillColor = new(100 / 255.0f, 149 / 255.0f, 237 / 255.0f, 1); private static readonly List<(float, string)> cachedPostDrawList = new(); @@ -119,34 +101,6 @@ public override void Draw(IWaveformDrawingContext target, PeakPointCollection pe var endTGrid = TGridCalculator.ConvertAudioTimeToTGrid(endTime, target.EditorViewModel); var curTGrid = TGridCalculator.ConvertAudioTimeToTGrid(curTime, target.EditorViewModel); - cachedObjTimeMap.Clear(); - - void applyObjCounting(IEnumerable timelineObjects) - { - foreach (var timeObj in timelineObjects) - { - var t = cachedObjTimeMap.TryGetValue(timeObj.TGrid, out var _t) ? _t : 0; - cachedObjTimeMap[timeObj.TGrid] = t + 1; - } - } - - var fumen = editor.Fumen; - applyObjCounting(fumen.Taps.BinaryFindRange(beginTGrid, endTGrid)); - applyObjCounting(fumen.Bullets.BinaryFindRange(beginTGrid, endTGrid)); - applyObjCounting(fumen.Bells.BinaryFindRange(beginTGrid, endTGrid)); - applyObjCounting(fumen.Beams.GetVisibleStartObjects(beginTGrid, endTGrid)); - applyObjCounting(fumen.Flicks.BinaryFindRange(beginTGrid, endTGrid)); - foreach (var hold in fumen.Holds.GetVisibleStartObjects(beginTGrid, endTGrid)) - { - var t = cachedObjTimeMap.TryGetValue(hold.TGrid, out var _t) ? _t : 0; - cachedObjTimeMap[hold.TGrid] = t + 1; - if (hold?.HoldEnd?.TGrid is TGrid et) - { - t = cachedObjTimeMap.TryGetValue(et, out _t) ? _t : 0; - cachedObjTimeMap[et] = t + 1; - } - } - var bpmList = editor.Fumen.BpmList; var tGridUnitLength = editor.Setting.TGridUnitLength; @@ -158,45 +112,92 @@ void applyObjCounting(IEnumerable timelineObjects) var prefixOffsetX = -Math.Min(0, fromTime.TotalMilliseconds) / target.DurationMsPerPixel; var xWidth = endX - beginX; - var beatColor = option.OnlyShowContainsObjBeat ? TransparentColor : BeatColor; - var containsObjBeatColor = option.ShowContainsObjBeat ? ContainsObjBeatColor : beatColor; - - lineDrawing.Begin(target, 2); + if (option.ShowObjectPlaceLine) { - var prevMeter = currentMeter; - var prevBpm = currentBpm; + void applyObjCounting(IEnumerable timelineObjects) + { + foreach (var timeObj in timelineObjects) + { + var t = cachedObjTimeMap.TryGetValue(timeObj.TGrid, out var _t) ? _t : 0; + cachedObjTimeMap[timeObj.TGrid] = t + 1; + } + } - foreach ((var tGrid, var bx, var beatIdx, var meter, var bpm) in TGridCalculator.GetVisbleTimelines_DesignMode(dummySoflanList, bpmList, - editor.Fumen.MeterChanges, beginX, endX, curX, editor.Setting.BeatSplit, 1.0f, editor.Setting.TGridUnitLength)) + var fumen = editor.Fumen; + applyObjCounting(fumen.Taps.BinaryFindRange(beginTGrid, endTGrid)); + applyObjCounting(fumen.Bullets.BinaryFindRange(beginTGrid, endTGrid)); + applyObjCounting(fumen.Bells.BinaryFindRange(beginTGrid, endTGrid)); + applyObjCounting(fumen.Beams.GetVisibleStartObjects(beginTGrid, endTGrid)); + applyObjCounting(fumen.Flicks.BinaryFindRange(beginTGrid, endTGrid)); + foreach (var hold in fumen.Holds.GetVisibleStartObjects(beginTGrid, endTGrid)) { - var x = (float)(prefixOffsetX + aWidth * ((bx - beginX) / xWidth) - width / 2); + var t = cachedObjTimeMap.TryGetValue(hold.TGrid, out var _t) ? _t : 0; + cachedObjTimeMap[hold.TGrid] = t + 1; + if (hold?.HoldEnd?.TGrid is TGrid et) + { + t = cachedObjTimeMap.TryGetValue(et, out _t) ? _t : 0; + cachedObjTimeMap[et] = t + 1; + } + } - var beatHeightWeight = beatIdx == 0 ? 1 : 0.85f; + lineDrawing.Begin(target, 2); + { + var beatHeightWeight = 0.85f; var topY = height / 2 * beatHeightWeight; var buttomY = -topY; - var color = beatColor; - if (cachedObjTimeMap.ContainsKey(tGrid)) - color = containsObjBeatColor; - - lineDrawing.PostPoint(new(x, buttomY), TransparentColor, VertexDash.Solider); - lineDrawing.PostPoint(new(x, buttomY), color, VertexDash.Solider); - lineDrawing.PostPoint(new(x, topY), color, VertexDash.Solider); - lineDrawing.PostPoint(new(x, topY), TransparentColor, VertexDash.Solider); - - var str = ""; - if (prevMeter != meter) - str += $"{meter.Bunbo}/{meter.BunShi}"; - if (prevBpm != bpm) - str += $" BPM:{bpm.BPM}"; - if (str.Length > 0) - cachedPostDrawList.Add((x + 2, str)); - - prevMeter = meter; - prevBpm = bpm; + foreach (var pair in cachedObjTimeMap) + { + var tGrid = pair.Key; + var bx = TGridCalculator.ConvertTGridToY_DesignMode(tGrid, dummySoflanList, bpmList, 1, editor.Setting.TGridUnitLength); + var x = (float)(prefixOffsetX + aWidth * ((bx - beginX) / xWidth) - width / 2); + + lineDrawing.PostPoint(new(x, buttomY), TransparentColor, VertexDash.Solider); + lineDrawing.PostPoint(new(x, buttomY), ObjectPlaceColor, VertexDash.Solider); + lineDrawing.PostPoint(new(x, topY), ObjectPlaceColor, VertexDash.Solider); + lineDrawing.PostPoint(new(x, topY), TransparentColor, VertexDash.Solider); + } } + lineDrawing.End(); + } + + if (option.ShowTimingLine) + { + lineDrawing.Begin(target, 2); + { + var prevMeter = currentMeter; + var prevBpm = currentBpm; + + foreach ((var tGrid, var bx, var beatIdx, var meter, var bpm) in TGridCalculator.GetVisbleTimelines_DesignMode(dummySoflanList, bpmList, + editor.Fumen.MeterChanges, beginX, endX, curX, editor.Setting.BeatSplit, 1.0f, editor.Setting.TGridUnitLength)) + { + var x = (float)(prefixOffsetX + aWidth * ((bx - beginX) / xWidth) - width / 2); + + var beatHeightWeight = beatIdx == 0 ? 1 : 0.85f; + var topY = height / 2 * beatHeightWeight; + var buttomY = -topY; + + var beatColor = cachedObjTimeMap.ContainsKey(tGrid) ? TransparentColor : BeatColor; + + lineDrawing.PostPoint(new(x, buttomY), TransparentColor, VertexDash.Solider); + lineDrawing.PostPoint(new(x, buttomY), beatColor, VertexDash.Solider); + lineDrawing.PostPoint(new(x, topY), beatColor, VertexDash.Solider); + lineDrawing.PostPoint(new(x, topY), TransparentColor, VertexDash.Solider); + + var str = ""; + if (prevMeter != meter) + str += $"{meter.Bunbo}/{meter.BunShi}"; + if (prevBpm != bpm) + str += $" BPM:{bpm.BPM}"; + if (str.Length > 0) + cachedPostDrawList.Add((x + 2, str)); + + prevMeter = meter; + prevBpm = bpm; + } + } + lineDrawing.End(); } - lineDrawing.End(); //绘制提示 foreach ((var x, var str) in cachedPostDrawList) @@ -213,6 +214,8 @@ void applyObjCounting(IEnumerable timelineObjects) target, default, out _); } + + cachedObjTimeMap.Clear(); } //绘制当前播放时间游标 diff --git a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/DefaultWaveformOption.cs b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/DefaultWaveformOption.cs new file mode 100644 index 00000000..9d339d9a --- /dev/null +++ b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/DefaultWaveformOption.cs @@ -0,0 +1,27 @@ +using OngekiFumenEditor.Base.Attributes; +using System.Runtime.CompilerServices; +using System.Text.Json.Serialization; + +namespace OngekiFumenEditor.Modules.AudioPlayerToolViewer.Graphics.WaveformDrawing.DefaultImpls +{ + public class DefaultWaveformOption : WaveformDrawingOptionBase + { + private bool showTimingLine = true; + [ObjectPropertyBrowserShow] + [JsonInclude] + public bool ShowTimingLine + { + get => showTimingLine; + set => Set(ref showTimingLine, value); + } + + private bool showObjectPlaceLine = true; + [ObjectPropertyBrowserShow] + [JsonInclude] + public bool ShowObjectPlaceLine + { + get => showObjectPlaceLine; + set => Set(ref showObjectPlaceLine, value); + } + } +} diff --git a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/WaveformDrawingOptionBase.cs b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/WaveformDrawingOptionBase.cs index fbd25967..d1f91899 100644 --- a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/WaveformDrawingOptionBase.cs +++ b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Graphics/WaveformDrawing/DefaultImpls/WaveformDrawingOptionBase.cs @@ -1,7 +1,9 @@ using Caliburn.Micro; +using OngekiFumenEditor.Base.Attributes; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; @@ -9,6 +11,13 @@ namespace OngekiFumenEditor.Modules.AudioPlayerToolViewer.Graphics.WaveformDrawi { public class WaveformDrawingOptionBase : PropertyChangedBase, IWaveformDrawingOption { - + [ObjectPropertyBrowserHide] + public override bool IsNotifying + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => base.IsNotifying; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set => base.IsNotifying = value; + } } } diff --git a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/ViewModels/AudioPlayerToolViewerViewModel.WaveformDrawing.cs b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/ViewModels/AudioPlayerToolViewerViewModel.WaveformDrawing.cs index 6d1e71ec..36fad520 100644 --- a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/ViewModels/AudioPlayerToolViewerViewModel.WaveformDrawing.cs +++ b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/ViewModels/AudioPlayerToolViewerViewModel.WaveformDrawing.cs @@ -34,7 +34,6 @@ public partial class AudioPlayerToolViewerViewModel : IWaveformDrawingContext private int renderViewHeight; private IPerfomenceMonitor performenceMonitor; private ISamplePeak samplePeak; - private IWaveformDrawing waveformDrawing; private CancellationTokenSource loadWaveformTask; private CancellationTokenSource resampleTaskCancelTokenSource; private TaskCompletionSource initTask = new TaskCompletionSource(); @@ -53,6 +52,16 @@ public partial class AudioPlayerToolViewerViewModel : IWaveformDrawingContext public TimeSpan CurrentTime { get; private set; } public TimeSpan AudioTotalDuration => AudioPlayer?.Duration ?? default; + private IWaveformDrawing waveformDrawing; + public IWaveformDrawing WaveformDrawing + { + get => waveformDrawing; + set + { + Set(ref waveformDrawing, value); + } + } + private int resampleSize = Properties.AudioPlayerToolViewerSetting.Default.ResampleSize; public int ResampleSize { @@ -152,7 +161,7 @@ public async void PrepareRender(GLWpfControl glView) private void InitRender() { samplePeak = IoC.Get(); - waveformDrawing = IoC.Get(); + WaveformDrawing = IoC.Get(); initTask.SetResult(); } @@ -217,7 +226,7 @@ public void Render(TimeSpan ts) UpdateDrawingContext(); if (usingPeakData is not null) - waveformDrawing.Draw(this, usingPeakData); + WaveformDrawing.Draw(this, usingPeakData); performenceMonitor.OnAfterRender(); } diff --git a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Views/AudioPlayerToolViewerView.xaml b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Views/AudioPlayerToolViewerView.xaml index 359948a6..67e183f1 100644 --- a/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Views/AudioPlayerToolViewerView.xaml +++ b/OngekiFumenEditor/Modules/AudioPlayerToolViewer/Views/AudioPlayerToolViewerView.xaml @@ -10,6 +10,7 @@ xmlns:local="clr-namespace:OngekiFumenEditor.Modules.FumenMetaInfoBrowser.Views" xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:objectinspector="clr-namespace:OngekiFumenEditor.UI.Controls.ObjectInspector" xmlns:vm="clr-namespace:OngekiFumenEditor.Modules.AudioPlayerToolViewer.ViewModels" xmlns:wpf="clr-namespace:OpenTK.Wpf;assembly=GLWpfControl" d:Background="White" @@ -30,6 +31,8 @@ + + - - + + @@ -73,9 +76,9 @@ Step="2.5"> + + + + + diff --git a/OngekiFumenEditor/Modules/FumenObjectPropertyBrowser/ViewModels/FumenObjectPropertyBrowserViewModel.cs b/OngekiFumenEditor/Modules/FumenObjectPropertyBrowser/ViewModels/FumenObjectPropertyBrowserViewModel.cs index af9de29a..bf5a1c89 100644 --- a/OngekiFumenEditor/Modules/FumenObjectPropertyBrowser/ViewModels/FumenObjectPropertyBrowserViewModel.cs +++ b/OngekiFumenEditor/Modules/FumenObjectPropertyBrowser/ViewModels/FumenObjectPropertyBrowserViewModel.cs @@ -46,7 +46,6 @@ private void OnObjectChanged() { if (x.PropertyInfo.GetCustomAttribute() is not null) return null; - if (x.PropertyInfo.CanWrite) return new UndoablePropertyInfoWrapper(x, referenceEditor); else if (x.PropertyInfo.GetCustomAttribute() is not null) diff --git a/OngekiFumenEditor/Modules/FumenVisualEditor/TGridCalculator.cs b/OngekiFumenEditor/Modules/FumenVisualEditor/TGridCalculator.cs index 2237ea05..ec6c1586 100644 --- a/OngekiFumenEditor/Modules/FumenVisualEditor/TGridCalculator.cs +++ b/OngekiFumenEditor/Modules/FumenVisualEditor/TGridCalculator.cs @@ -71,12 +71,12 @@ public static TGrid ConvertAudioTimeToTGrid(TimeSpan audioTime, BpmList bpmList, public static double ConvertTGridToY_DesignMode(TGrid tGrid, FumenVisualEditorViewModel editor) => ConvertTGridToY_DesignMode(tGrid, editor.Fumen.Soflans, editor.Fumen.BpmList, editor.Setting.VerticalDisplayScale, editor.Setting.TGridUnitLength); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static double ConvertTGridToY_DesignMode(TGrid tGrid, SoflanList soflanList, BpmList bpmList, double scale, int tUnitLength) + public static double ConvertTGridToY_DesignMode(TGrid tGrid, SoflanList soflanList, BpmList bpmList, double scale, int tUnitLength) => ConvertTGridUnitToY_DesignMode(tGrid.TotalUnit, soflanList, bpmList, scale, tUnitLength); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double ConvertTGridUnitToY_DesignMode(double tGridUnit, FumenVisualEditorViewModel editor) => ConvertTGridUnitToY_DesignMode(tGridUnit, editor.Fumen.Soflans, editor.Fumen.BpmList, editor.Setting.VerticalDisplayScale, editor.Setting.TGridUnitLength); - private static double ConvertTGridUnitToY_DesignMode(double tGridUnit, SoflanList soflanList, BpmList bpmList, double scale, int tUnitLength) + public static double ConvertTGridUnitToY_DesignMode(double tGridUnit, SoflanList soflanList, BpmList bpmList, double scale, int tUnitLength) { var positionBpmList = soflanList.GetCachedSoflanPositionList_DesignMode(tUnitLength, bpmList);