diff --git a/OngekiFumenEditor/AppBootstrapper.cs b/OngekiFumenEditor/AppBootstrapper.cs
index 5ca814fa..73e98696 100644
--- a/OngekiFumenEditor/AppBootstrapper.cs
+++ b/OngekiFumenEditor/AppBootstrapper.cs
@@ -378,7 +378,7 @@ void exceptionDump(Exception e, int level = 0)
exceptionHandling = true;
Environment.Exit(-1);
#else
- throw exception;
+ throw new Exception(exception.Message, exception);
#endif
}
diff --git a/OngekiFumenEditor/Kernel/Graphics/IDrawingContext.cs b/OngekiFumenEditor/Kernel/Graphics/IDrawingContext.cs
index 15c4ed7f..9b882535 100644
--- a/OngekiFumenEditor/Kernel/Graphics/IDrawingContext.cs
+++ b/OngekiFumenEditor/Kernel/Graphics/IDrawingContext.cs
@@ -5,47 +5,50 @@
namespace OngekiFumenEditor.Kernel.Graphics
{
- public interface IDrawingContext
- {
- ///
- /// 左手坐标系为世界坐标系的可视区域
- ///
- public struct VisibleRect
- {
- public VisibleRect(Vector2 buttomRight, Vector2 topLeft)
- {
- TopLeft = topLeft;
- ButtomRight = buttomRight;
- }
+ public interface IDrawingContext
+ {
+ ///
+ /// 左手坐标系为世界坐标系的可视区域
+ ///
+ public struct VisibleRect
+ {
+ public VisibleRect(Vector2 buttomRight, Vector2 topLeft)
+ {
+ TopLeft = topLeft;
+ ButtomRight = buttomRight;
+ }
- public Vector2 TopLeft { get; init; }
- public Vector2 ButtomRight { get; init; }
+ public Vector2 TopLeft { get; init; }
+ public Vector2 ButtomRight { get; init; }
- public float Width => ButtomRight.X - TopLeft.X;
- public float Height => TopLeft.Y - ButtomRight.Y;
+ public float Width => ButtomRight.X - TopLeft.X;
+ public float Height => TopLeft.Y - ButtomRight.Y;
- public float MinY => ButtomRight.Y;
- public float MaxY => TopLeft.Y;
+ public float MinY => ButtomRight.Y;
+ public float MaxY => TopLeft.Y;
- public float MinX => TopLeft.X;
- public float MaxX => ButtomRight.X;
- }
+ public float CenterX => (ButtomRight.X + TopLeft.X) / 2;
+ public float CenterY => (ButtomRight.Y + TopLeft.Y) / 2;
- //values are updating by frame
- public VisibleRect Rect { get; }
+ public float MinX => TopLeft.X;
+ public float MaxX => ButtomRight.X;
+ }
- public float ViewWidth => Rect.Width;
- public float ViewHeight => Rect.Height;
+ //values are updating by frame
+ public VisibleRect Rect { get; }
- Matrix4 ProjectionMatrix { get; }
- Matrix4 ViewMatrix { get; }
- Matrix4 ViewProjectionMatrix { get; }
+ public float ViewWidth => Rect.Width;
+ public float ViewHeight => Rect.Height;
- IPerfomenceMonitor PerfomenceMonitor { get; }
+ Matrix4 ProjectionMatrix { get; }
+ Matrix4 ViewMatrix { get; }
+ Matrix4 ViewProjectionMatrix { get; }
- void PrepareEditorLoop(GLWpfControl glView);
- void OnRenderSizeChanged(GLWpfControl glView, SizeChangedEventArgs e);
+ IPerfomenceMonitor PerfomenceMonitor { get; }
- void Render(TimeSpan ts);
- }
+ void PrepareEditorLoop(GLWpfControl glView);
+ void OnRenderSizeChanged(GLWpfControl glView, SizeChangedEventArgs e);
+
+ void Render(TimeSpan ts);
+ }
}
diff --git a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayableAreaHelper.cs b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayableAreaHelper.cs
index 08e17690..a67d9242 100644
--- a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayableAreaHelper.cs
+++ b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayableAreaHelper.cs
@@ -19,14 +19,21 @@
using Xv2CoreLib.HslColor;
using OngekiFumenEditor.Modules.FumenVisualEditor.Graphics.Drawing.TargetImpl.Lane;
using System.Windows.Documents;
+using System.Runtime.CompilerServices;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.Header;
+using NAudio.Gui;
namespace OngekiFumenEditor.Modules.FumenVisualEditor.Graphics.Drawing.Editors
{
public class DrawPlayableAreaHelper
{
+ static readonly Vector4 debugLeftColor = new Vector4(1, 51f / 255, 51f / 255, 0.75f);
+ static readonly Vector4 debugRightColor = new Vector4(0, 204f / 255, 102f / 255, 0.75f);
+
private ILineDrawing lineDrawing;
private IPolygonDrawing polygonDrawing;
private ICircleDrawing circleDrawing;
+ private IStringDrawing stringDrawing;
private Vector4 playFieldForegroundColor;
private bool enablePlayFieldDrawing;
@@ -38,6 +45,7 @@ public DrawPlayableAreaHelper()
lineDrawing = IoC.Get();
polygonDrawing = IoC.Get();
circleDrawing = IoC.Get();
+ stringDrawing = IoC.Get();
UpdateProps();
Properties.EditorGlobalSetting.Default.PropertyChanged += Default_PropertyChanged;
@@ -379,7 +387,7 @@ void appendPoint(List list, XGrid xGrid, float y)
EnumeratePoints(true, rightPoints);
//解决左右墙交叉处理问题
- AdjustLaneIntersection(leftPoints, rightPoints);
+ AdjustLaneIntersection(target, leftPoints, rightPoints);
//合并提交,准备进行三角剖分
foreach (var pos in leftPoints)
@@ -398,7 +406,6 @@ void appendPoint(List list, XGrid xGrid, float y)
Earcut.Tessellate(tessellatePoints, idxList, tessellateList);
polygonDrawing.Begin(target, OpenTK.Graphics.OpenGL.PrimitiveType.Triangles);
-
foreach (var seq in tessellateList.SequenceWrap(3))
{
foreach (var idx in seq)
@@ -409,16 +416,12 @@ void appendPoint(List list, XGrid xGrid, float y)
}
}
polygonDrawing.End();
-#if DEBUG
- var leftColor = new Vector4(1, 51f / 255, 51f / 255, 0.9f);
- var rightColor = new Vector4(0, 204f / 255, 102f / 255, 0.9f);
- //print WallLane
- lineDrawing.Draw(target, leftPoints
- .Select(p => new LineVertex(p, leftColor, VertexDash.Solider)), 6);
- lineDrawing.Draw(target, rightPoints
- .Select(p => new LineVertex(p, rightColor, VertexDash.Solider)), 6);
+#if 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);
var i = 0;
foreach (var seq in tessellateList.SequenceWrap(3))
@@ -432,20 +435,47 @@ void appendPoint(List list, XGrid xGrid, float y)
i += 3;
}
- void printPoints(IEnumerable data, Vector4 color)
+ void printPoints(IEnumerable data, Vector4 color, bool isRight)
{
- BeginDebugPrint(target);
- data.ForEach(x => DebugPrintPoint(x, color, 10));
- EndDebugPrint();
+ color.W = 1;
+ circleDrawing.Begin(target);
+ foreach (var pos in data)
+ circleDrawing.Post(pos, color, false, 10);
+ circleDrawing.End();
+ var prevY = 0f;
+ var prevR = 0;
+ foreach (var pos in data)
+ {
+ if (prevY == pos.Y)
+ prevR = prevR switch { 1 => 0, 0 => 1 };
+ else
+ prevR = 0;
+ prevY = pos.Y;
+
+ stringDrawing.Draw(
+ $"({pos.X}, {pos.Y})",
+ pos - new Vector2(isRight ? -10 : 10, -prevR * 10),
+ Vector2.One,
+ 15,
+ 0,
+ color,
+ new(isRight ? 0 : 1, prevR),
+ default,
+ target,
+ default,
+ out _
+ );
+ }
}
- printPoints(leftPoints, leftColor);
- printPoints(rightPoints, rightColor);
+ printPoints(leftPoints, debugLeftColor, false);
+ printPoints(rightPoints, debugRightColor, true);
#endif
+
ObjectPool>.Return(tessellateList);
}
- private void AdjustLaneIntersection(List leftPoints, List rightPoints)
+ private void AdjustLaneIntersection(IDrawingContext target, List leftPoints, List rightPoints)
{
Vector2? GetIntersection(Vector2 p1, Vector2 p2, Vector2 q1, Vector2 q2)
{
@@ -460,9 +490,7 @@ private void AdjustLaneIntersection(List leftPoints, List righ
float t = ((q1.X - p1.X) * s.Y - (q1.Y - p1.Y) * s.X) / cross_r_s;
float u = ((q1.X - p1.X) * r.Y - (q1.Y - p1.Y) * r.X) / cross_r_s;
- //不允许交叉点在两个线端点重合
- //if (t >= 0 && t <= 1 && u >= 0 && u <= 1)
- if (t > 0 && t < 1 && u > 0 && u < 1)
+ if (t >= 0 && t <= 1 && u >= 0 && u <= 1)
return new Vector2(p1.X + t * r.X, p1.Y + t * r.Y);
return null;
@@ -473,18 +501,35 @@ private void AdjustLaneIntersection(List leftPoints, List righ
using var d = ObjectPool>.GetWithUsingDisposable(out var tempLeft, out _);
using var d2 = ObjectPool>.GetWithUsingDisposable(out var tempRight, out _);
+ using var d3 = ObjectPool>.GetWithUsingDisposable(out var intersectionPoints, out _);
+ intersectionPoints.Clear();
if (leftPoints.FirstOrDefault().X > rightPoints.FirstOrDefault().X)
- exchange(0, 0);
+ tryExchange(0, 0);
var leftIdx = 1;
var rightIdx = 1;
- void exchange(int li, int ri)
+ void tryExchange(int li, int ri)
{
tempLeft.Clear();
tempRight.Clear();
+ var lp = leftPoints[li];
+ var rp = rightPoints[ri];
+
+ /*while*/
+ if (lp == rp)
+ {
+ if (li + 1 < leftPoints.Count)
+ lp = leftPoints[li + 1];
+ if (ri + 1 < rightPoints.Count)
+ rp = rightPoints[ri + 1];
+ }
+
+ if (lp.X < rp.X)
+ return;
+
tempLeft.AddRange(leftPoints[li..]);
tempRight.AddRange(rightPoints[ri..]);
@@ -500,15 +545,101 @@ void exchange(int li, int ri)
(Vector2 from, Vector2 to) leftLine = (leftPoints[leftIdx - 1], leftPoints[leftIdx]);
(Vector2 from, Vector2 to) rightLine = (rightPoints[rightIdx - 1], rightPoints[rightIdx]);
- if (GetIntersection(leftLine.from, leftLine.to, rightLine.from, rightLine.to) is Vector2 intersectionPoint)
+ if (GetIntersection(leftLine.from, leftLine.to, rightLine.from, rightLine.to) is Vector2 intersectionPoint && !intersectionPoints.Contains(intersectionPoint))
{
- exchange(leftIdx, rightIdx);
+ intersectionPoints.Add(intersectionPoint);
+
+ circleDrawing.Begin(target);
+ circleDrawing.Post(intersectionPoint, new(1, 1, 0, 1), false, 30);
+ circleDrawing.End();
+ stringDrawing.Draw(
+ $"[{leftIdx}, {rightIdx}]",
+ intersectionPoint - new Vector2(intersectionPoint.X <= target.Rect.CenterX ? -10 : 10, 10),
+ Vector2.One,
+ 15,
+ 0,
+ new(1, 1, 0, 1),
+ new(intersectionPoint.X <= target.Rect.CenterX ? 0 : 1, 1),
+ default,
+ target,
+ default,
+ out _
+ );
- leftPoints.Insert(leftIdx, intersectionPoint);
- rightPoints.Insert(rightIdx, intersectionPoint);
+ var isCross = !(intersectionPoint == leftLine.from ||
+ intersectionPoint == leftLine.to ||
+ intersectionPoint == rightLine.from ||
+ intersectionPoint == rightLine.to);
- leftIdx++;
- rightIdx++;
+
+ if (rightLine.to == intersectionPoint && intersectionPoint == leftLine.to)
+ isCross = true;
+
+ if (!(rightLine.from.Y == rightLine.to.Y || leftLine.from.Y == leftLine.to.Y))
+ isCross &= true;
+
+ if (isCross)
+ {
+ //check cross
+
+ tryExchange(leftIdx, rightIdx);
+
+ leftPoints.Insert(leftIdx, intersectionPoint);
+ rightPoints.Insert(rightIdx, intersectionPoint);
+
+ leftIdx++;
+ rightIdx++;
+ }
+ else
+ {
+ var isRightIntersected = intersectionPoint == rightLine.from ||
+ intersectionPoint == rightLine.to;
+ var isLeftIntersected = intersectionPoint == leftLine.from ||
+ intersectionPoint == leftLine.to;
+ var isFromIntersected = intersectionPoint == (isRightIntersected ? rightLine : leftLine).from;
+
+ var insertLeftIdx = leftIdx;
+ var insertRightIdx = rightIdx;
+
+ if (isRightIntersected && isLeftIntersected)
+ {
+ if (leftLine.from.Y != leftLine.to.Y)
+ {
+ insertLeftIdx = leftIdx - 1;
+ }
+ if (rightLine.from.Y != rightLine.to.Y)
+ {
+ insertRightIdx = rightIdx - 1;
+ }
+ }
+ else
+ {
+ if (isFromIntersected)
+ {
+ if (isRightIntersected)
+ {
+ insertRightIdx = rightIdx - 1;
+ }
+ else
+ {
+ insertLeftIdx = leftIdx - 1;
+ }
+ }
+ else
+ {
+ if (isRightIntersected)
+ {
+ insertRightIdx = rightIdx + 1;
+ }
+ else
+ {
+ insertLeftIdx = leftIdx + 1;
+ }
+ }
+ }
+
+ tryExchange(insertLeftIdx, insertRightIdx);
+ }
}
//看看哪一边idx需要递增
@@ -516,38 +647,19 @@ void exchange(int li, int ri)
{
//left的末端在right范围内,那么left需要递增
leftIdx++;
- continue;
}
-
- if (leftLine.from.Y <= rightLine.to.Y && rightLine.to.Y <= leftLine.to.Y)
+ else if (leftLine.from.Y <= rightLine.to.Y && rightLine.to.Y <= leftLine.to.Y)
{
rightIdx++;
- continue;
}
-
- leftIdx++;
- rightIdx++;
+ else
+ {
+ leftIdx++;
+ rightIdx++;
+ }
}
}
- [Conditional("DEBUG")]
- private void DebugPrintPoint(Vector2 p, Vector4 color, int v2)
- {
- circleDrawing.Post(p, color, false, v2);
- }
-
- [Conditional("DEBUG")]
- private void BeginDebugPrint(IFumenEditorDrawingContext target)
- {
- circleDrawing.Begin(target);
- }
-
- [Conditional("DEBUG")]
- private void EndDebugPrint()
- {
- circleDrawing.End();
- }
-
public static (float r, float g, float b) Hsl2Rgb(float h, float s, float l)
{
// Ensure the Hue is in the range of 0 to 360