From 64d6afab6210d6814671f5b5194cbad5a1564815 Mon Sep 17 00:00:00 2001 From: MikiraSora Date: Sat, 28 Sep 2024 09:15:50 +0800 Subject: [PATCH] add VisibleTGridRange::TryMerge()/Merge() and fix playback soflan in DrawPlayFieldInternal() --- .../SoflanList_CachedPositionList.cs | 17 ++++++- .../Drawing/Editors/DrawPlayableAreaHelper.cs | 47 +++++++++++++++++-- OngekiFumenEditor/OngekiFumenEditor.csproj | 1 + 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/OngekiFumenEditor/Base/Collections/SoflanList_CachedPositionList.cs b/OngekiFumenEditor/Base/Collections/SoflanList_CachedPositionList.cs index 95d8845e..ba76d3e7 100644 --- a/OngekiFumenEditor/Base/Collections/SoflanList_CachedPositionList.cs +++ b/OngekiFumenEditor/Base/Collections/SoflanList_CachedPositionList.cs @@ -37,7 +37,22 @@ public SoflanPoint(double y, TGrid tGrid, double speed, BPMChange bpm) private List cachedSoflanPositionList_DesignMode = new(); private List cachedSoflanPositionList_PreviewMode = new(); - public record VisibleTGridRange(TGrid minTGrid, TGrid maxTGrid); + public record VisibleTGridRange(TGrid minTGrid, TGrid maxTGrid) + { + public bool TryMerge(VisibleTGridRange another, out VisibleTGridRange mergedResult) + { + mergedResult = Merge(another); + return mergedResult != default; + } + + public VisibleTGridRange Merge(VisibleTGridRange another) + { + if ((minTGrid <= another.minTGrid && another.minTGrid <= maxTGrid) || + another.minTGrid <= minTGrid && minTGrid <= another.maxTGrid) + return new(MathUtils.Min(minTGrid, another.minTGrid), MathUtils.Max(maxTGrid, another.maxTGrid)); + return default; + } + } public record SoflanSegment(int curIdx, SoflanPoint cur, SoflanPoint next); private IIntervalTree cachePostionList_PreviewMode; diff --git a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayableAreaHelper.cs b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayableAreaHelper.cs index a02ef28b..aaac7e46 100644 --- a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayableAreaHelper.cs +++ b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayableAreaHelper.cs @@ -12,7 +12,6 @@ using OngekiFumenEditor.Utils.ObjectPool; using EarcutNet; using System.Drawing; -using Microsoft.CodeAnalysis; namespace OngekiFumenEditor.Modules.FumenVisualEditor.Graphics.Drawing.Editors { @@ -83,6 +82,48 @@ public void DrawPlayField(IFumenEditorDrawingContext target, TGrid minTGrid, TGr if (target.Editor.IsDesignMode || !enablePlayFieldDrawing) return; + var fumen = target.Editor.Fumen; + var soflanList = fumen.Soflans.GetCachedSoflanPositionList_PreviewMode(fumen.BpmList); + + var minIdx = soflanList.LastOrDefaultIndexByBinarySearch(minTGrid, x => x.TGrid); + var maxIdx = soflanList.LastOrDefaultIndexByBinarySearch(maxTGrid, x => x.TGrid); + + // ---|------o----|-----------------------------|---o------|--- + // x x x x + + var curSoflanPoint = soflanList[minIdx]; + var rangeInfos = ObjectPool>.Get(); + rangeInfos.Clear(); + rangeInfos.Add((minTGrid, soflanList[minIdx].Speed)); + + for (int i = minIdx + 1; i <= maxIdx; i++) + { + var soflanPoint = soflanList[i]; + + if (soflanPoint.Speed * rangeInfos[^1].speed < 0) + rangeInfos.Add((soflanPoint.TGrid, soflanPoint.Speed)); + + curSoflanPoint = soflanPoint; + } + + if (rangeInfos[^1].tGrid != maxTGrid) + rangeInfos.Add((maxTGrid, rangeInfos[^1].speed)); + + for (int i = 0; i < rangeInfos.Count - 1; i++) + { + var segMinTGrid = rangeInfos[i].tGrid; + var segMaxTGrid = rangeInfos[i + 1].tGrid; + + var isPlayback = rangeInfos[i].speed < 0; + + DrawPlayFieldInternal(target, segMinTGrid, segMaxTGrid, isPlayback); + } + + ObjectPool>.Return(rangeInfos); + } + + public void DrawPlayFieldInternal(IFumenEditorDrawingContext target, TGrid minTGrid, TGrid maxTGrid, bool isPlaybackSoflan) + { /* 画游戏(黑色可移动)区域 1. 计算一组轨道,每个轨道的节点都算一个point,如果存在轨道相交,那么相交点也算point @@ -404,7 +445,7 @@ void appendPoint(List list, XGrid xGrid, float y) polygonDrawing.End(); -#if DEBUG +#if PLAYFIELD_DEBUG playFieldForegroundColor.W = 0.4f; lineDrawing.Draw(target, leftPoints.Select(p => new LineVertex(p, debugLeftColor, VertexDash.Solider)), 6); lineDrawing.Draw(target, rightPoints.Select(p => new LineVertex(p, debugRightColor, VertexDash.Solider)), 6); @@ -656,7 +697,7 @@ bool tryExchange(int li, int ri) tryExchange(leftIdx, rightIdx); } -#if DEBUG +#if PLAYFIELD_DEBUG circleDrawing.Begin(target); circleDrawing.Post(intersectionPoint, isCross ? new(1, 1, 0, 0.75f) : new(0, 153 / 255f, 153 / 255f, 0.75f), false, 30); circleDrawing.End(); diff --git a/OngekiFumenEditor/OngekiFumenEditor.csproj b/OngekiFumenEditor/OngekiFumenEditor.csproj index 0752f118..101cb7b5 100644 --- a/OngekiFumenEditor/OngekiFumenEditor.csproj +++ b/OngekiFumenEditor/OngekiFumenEditor.csproj @@ -14,6 +14,7 @@ full + $(DefineConstants);PLAYFIELD_DEBUG