From 3b73aea5c0ff97e075a788abd68f4e683ce92831 Mon Sep 17 00:00:00 2001 From: ww-rm Date: Sat, 12 Apr 2025 20:58:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B0=83=E8=AF=95=E9=AA=A8?= =?UTF-8?q?=E9=AA=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SpineObject/SpineObject21.cs | 63 +++++++--- .../SpineObject/SpineObject36.cs | 63 +++++++--- .../SpineObject/SpineObject37.cs | 63 +++++++--- .../SpineObject/SpineObject38.cs | 65 +++++++--- .../SpineObject/SpineObject40.cs | 63 +++++++--- .../SpineObject/SpineObject41.cs | 63 +++++++--- .../SpineObject/Spineobject42.cs | 63 +++++++--- SpineViewer/Spine/SpineObject.cs | 113 +++++++++++++++--- 8 files changed, 412 insertions(+), 144 deletions(-) diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs index 0a8d6ce..a666056 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs @@ -260,7 +260,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject protected override void draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) { - vertexArray.Clear(); + triangleVertices.Clear(); states.Texture = null; states.Shader = SFMLShader.GetSpineShader(usePma); @@ -329,13 +329,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject states.Texture ??= texture; if (states.BlendMode != blendMode || states.Texture != texture) { - if (vertexArray.VertexCount > 0) + if (triangleVertices.VertexCount > 0) { - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); - - vertexArray.Clear(); + target.Draw(triangleVertices, states); + triangleVertices.Clear(); } states.BlendMode = blendMode; states.Texture = texture; @@ -369,26 +366,56 @@ namespace SpineViewer.Spine.Implementations.SpineObject vertex.Position.Y = worldVertices[index + 1]; vertex.TexCoords.X = uvs[index] * textureSizeX; vertex.TexCoords.Y = uvs[index + 1] * textureSizeY; - vertexArray.Append(vertex); + triangleVertices.Append(vertex); } //clipping.ClipEnd(slot); } //clipping.ClipEnd(); - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); + target.Draw(triangleVertices, states); + } - // 包围盒 - if (isDebug && isSelected && debugBounds) + protected override void debugDraw(SFML.Graphics.RenderTarget target) + { + lineVertices.Clear(); + rectLineVertices.Clear(); + + // 调试包围盒 + if (debugBounds) { var b = bounds; - boundsVertices[0] = boundsVertices[4] = new(new(b.Left, b.Top), BoundsColor); - boundsVertices[1] = new(new(b.Right, b.Top), BoundsColor); - boundsVertices[2] = new(new(b.Right, b.Bottom), BoundsColor); - boundsVertices[3] = new(new(b.Left, b.Bottom), BoundsColor); - target.Draw(boundsVertices); + var v = new SFML.Graphics.Vertex() { Color = BoundsColor }; + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + v.Position = new(b.Right, b.Top); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Right, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + } + + if (debugBones) + { + var width = scale; + foreach (var bone in skeleton.Bones) + { + var boneLength = bone.Data.Length; + var p1 = new SFML.System.Vector2f(bone.WorldX, bone.WorldY); + var p2 = new SFML.System.Vector2f(bone.WorldX + boneLength * bone.M00, bone.WorldY + boneLength * bone.M10); + AddRectLine(p1, p2, BoneLineColor, width); + } + } + + target.Draw(lineVertices); + target.Draw(rectLineVertices); + + // 骨骼的点最后画, 层级处于上面 + if (debugBones) + { + var radius = scale; + foreach (var bone in skeleton.Bones) + { + DrawCirclePoint(target, new(bone.WorldX, bone.WorldY), BonePointColor, radius); + } } } } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs index 477a532..94550cf 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs @@ -219,7 +219,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject protected override void draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) { - vertexArray.Clear(); + triangleVertices.Clear(); states.Texture = null; states.Shader = SFMLShader.GetSpineShader(usePma); @@ -286,13 +286,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject states.Texture ??= texture; if (states.BlendMode != blendMode || states.Texture != texture) { - if (vertexArray.VertexCount > 0) + if (triangleVertices.VertexCount > 0) { - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); - - vertexArray.Clear(); + target.Draw(triangleVertices, states); + triangleVertices.Clear(); } states.BlendMode = blendMode; states.Texture = texture; @@ -326,26 +323,56 @@ namespace SpineViewer.Spine.Implementations.SpineObject vertex.Position.Y = worldVertices[index + 1]; vertex.TexCoords.X = uvs[index] * textureSizeX; vertex.TexCoords.Y = uvs[index + 1] * textureSizeY; - vertexArray.Append(vertex); + triangleVertices.Append(vertex); } clipping.ClipEnd(slot); } clipping.ClipEnd(); - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); + target.Draw(triangleVertices, states); + } - // 包围盒 - if (isDebug && isSelected && debugBounds) + protected override void debugDraw(SFML.Graphics.RenderTarget target) + { + lineVertices.Clear(); + rectLineVertices.Clear(); + + // 调试包围盒 + if (debugBounds) { var b = bounds; - boundsVertices[0] = boundsVertices[4] = new(new(b.Left, b.Top), BoundsColor); - boundsVertices[1] = new(new(b.Right, b.Top), BoundsColor); - boundsVertices[2] = new(new(b.Right, b.Bottom), BoundsColor); - boundsVertices[3] = new(new(b.Left, b.Bottom), BoundsColor); - target.Draw(boundsVertices); + var v = new SFML.Graphics.Vertex() { Color = BoundsColor }; + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + v.Position = new(b.Right, b.Top); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Right, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + } + + if (debugBones) + { + var width = scale; + foreach (var bone in skeleton.Bones) + { + var boneLength = bone.Data.Length; + var p1 = new SFML.System.Vector2f(bone.WorldX, bone.WorldY); + var p2 = new SFML.System.Vector2f(bone.WorldX + boneLength * bone.A, bone.WorldY + boneLength * bone.C); + AddRectLine(p1, p2, BoneLineColor, width); + } + } + + target.Draw(lineVertices); + target.Draw(rectLineVertices); + + // 骨骼的点最后画, 层级处于上面 + if (debugBones) + { + var radius = scale; + foreach (var bone in skeleton.Bones) + { + DrawCirclePoint(target, new(bone.WorldX, bone.WorldY), BonePointColor, radius); + } } } } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs index 4f1dff7..0ac774b 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs @@ -191,7 +191,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject protected override void draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) { - vertexArray.Clear(); + triangleVertices.Clear(); states.Texture = null; states.Shader = SFMLShader.GetSpineShader(usePma); @@ -258,13 +258,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject states.Texture ??= texture; if (states.BlendMode != blendMode || states.Texture != texture) { - if (vertexArray.VertexCount > 0) + if (triangleVertices.VertexCount > 0) { - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); - - vertexArray.Clear(); + target.Draw(triangleVertices, states); + triangleVertices.Clear(); } states.BlendMode = blendMode; states.Texture = texture; @@ -298,26 +295,56 @@ namespace SpineViewer.Spine.Implementations.SpineObject vertex.Position.Y = worldVertices[index + 1]; vertex.TexCoords.X = uvs[index] * textureSizeX; vertex.TexCoords.Y = uvs[index + 1] * textureSizeY; - vertexArray.Append(vertex); + triangleVertices.Append(vertex); } clipping.ClipEnd(slot); } clipping.ClipEnd(); - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); + target.Draw(triangleVertices, states); + } - // 包围盒 - if (isDebug && isSelected && debugBounds) + protected override void debugDraw(SFML.Graphics.RenderTarget target) + { + lineVertices.Clear(); + rectLineVertices.Clear(); + + // 调试包围盒 + if (debugBounds) { var b = bounds; - boundsVertices[0] = boundsVertices[4] = new(new(b.Left, b.Top), BoundsColor); - boundsVertices[1] = new(new(b.Right, b.Top), BoundsColor); - boundsVertices[2] = new(new(b.Right, b.Bottom), BoundsColor); - boundsVertices[3] = new(new(b.Left, b.Bottom), BoundsColor); - target.Draw(boundsVertices); + var v = new SFML.Graphics.Vertex() { Color = BoundsColor }; + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + v.Position = new(b.Right, b.Top); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Right, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + } + + if (debugBones) + { + var width = scale; + foreach (var bone in skeleton.Bones) + { + var boneLength = bone.Data.Length; + var p1 = new SFML.System.Vector2f(bone.WorldX, bone.WorldY); + var p2 = new SFML.System.Vector2f(bone.WorldX + boneLength * bone.A, bone.WorldY + boneLength * bone.C); + AddRectLine(p1, p2, BoneLineColor, width); + } + } + + target.Draw(lineVertices); + target.Draw(rectLineVertices); + + // 骨骼的点最后画, 层级处于上面 + if (debugBones) + { + var radius = scale; + foreach (var bone in skeleton.Bones) + { + DrawCirclePoint(target, new(bone.WorldX, bone.WorldY), BonePointColor, radius); + } } } } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs index d20dbe0..30f58a0 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs @@ -25,7 +25,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject texture.Smooth = true; if (page.uWrap == TextureWrap.Repeat && page.vWrap == TextureWrap.Repeat) texture.Repeated = true; - + page.rendererObject = texture; // 似乎是不需要设置的, 因为存在某些 png 和 atlas 大小不同的情况, 一般是有一些缩放, 如果设置了反而渲染异常 // page.width = (int)texture.Size.X; @@ -199,7 +199,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject protected override void draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) { - vertexArray.Clear(); + triangleVertices.Clear(); states.Texture = null; states.Shader = SFMLShader.GetSpineShader(usePma); @@ -209,7 +209,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject var attachment = slot.Attachment; SFML.Graphics.Texture texture; - + float[] worldVertices = worldVerticesBuffer; // 顶点世界坐标, 连续的 [x0, y0, x1, y1, ...] 坐标值 int worldVerticesCount; // 等于顶点数组的长度除以 2 int[] worldTriangleIndices; // 三角形索引, 从顶点坐标数组取的时候要乘以 2, 最大值是 worldVerticesCount - 1 @@ -266,13 +266,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject states.Texture ??= texture; if (states.BlendMode != blendMode || states.Texture != texture) { - if (vertexArray.VertexCount > 0) + if (triangleVertices.VertexCount > 0) { - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); - - vertexArray.Clear(); + target.Draw(triangleVertices, states); + triangleVertices.Clear(); } states.BlendMode = blendMode; states.Texture = texture; @@ -306,26 +303,56 @@ namespace SpineViewer.Spine.Implementations.SpineObject vertex.Position.Y = worldVertices[index + 1]; vertex.TexCoords.X = uvs[index] * textureSizeX; vertex.TexCoords.Y = uvs[index + 1] * textureSizeY; - vertexArray.Append(vertex); + triangleVertices.Append(vertex); } clipping.ClipEnd(slot); } clipping.ClipEnd(); - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); + target.Draw(triangleVertices, states); + } + + protected override void debugDraw(SFML.Graphics.RenderTarget target) + { + lineVertices.Clear(); + rectLineVertices.Clear(); // 调试包围盒 - if (isDebug && isSelected && debugBounds) + if (debugBounds) { var b = bounds; - boundsVertices[0] = boundsVertices[4] = new(new(b.Left, b.Top), BoundsColor); - boundsVertices[1] = new(new(b.Right, b.Top), BoundsColor); - boundsVertices[2] = new(new(b.Right, b.Bottom), BoundsColor); - boundsVertices[3] = new(new(b.Left, b.Bottom), BoundsColor); - target.Draw(boundsVertices); + var v = new SFML.Graphics.Vertex() { Color = BoundsColor }; + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + v.Position = new(b.Right, b.Top); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Right, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + } + + if (debugBones) + { + var width = scale; + foreach (var bone in skeleton.Bones) + { + var boneLength = bone.Data.Length; + var p1 = new SFML.System.Vector2f(bone.WorldX, bone.WorldY); + var p2 = new SFML.System.Vector2f(bone.WorldX + boneLength * bone.A, bone.WorldY + boneLength * bone.C); + AddRectLine(p1, p2, BoneLineColor, width); + } + } + + target.Draw(lineVertices); + target.Draw(rectLineVertices); + + // 骨骼的点最后画, 层级处于上面 + if (debugBones) + { + var radius = scale; + foreach (var bone in skeleton.Bones) + { + DrawCirclePoint(target, new(bone.WorldX, bone.WorldY), BonePointColor, radius); + } } } } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs index dadb71f..2042e41 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs @@ -195,7 +195,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject protected override void draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) { - vertexArray.Clear(); + triangleVertices.Clear(); states.Texture = null; states.Shader = SFMLShader.GetSpineShader(usePma); @@ -262,13 +262,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject states.Texture ??= texture; if (states.BlendMode != blendMode || states.Texture != texture) { - if (vertexArray.VertexCount > 0) + if (triangleVertices.VertexCount > 0) { - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); - - vertexArray.Clear(); + target.Draw(triangleVertices, states); + triangleVertices.Clear(); } states.BlendMode = blendMode; states.Texture = texture; @@ -302,26 +299,56 @@ namespace SpineViewer.Spine.Implementations.SpineObject vertex.Position.Y = worldVertices[index + 1]; vertex.TexCoords.X = uvs[index] * textureSizeX; vertex.TexCoords.Y = uvs[index + 1] * textureSizeY; - vertexArray.Append(vertex); + triangleVertices.Append(vertex); } clipping.ClipEnd(slot); } clipping.ClipEnd(); - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); + target.Draw(triangleVertices, states); + } - // 包围盒 - if (isDebug && isSelected && debugBounds) + protected override void debugDraw(SFML.Graphics.RenderTarget target) + { + lineVertices.Clear(); + rectLineVertices.Clear(); + + // 调试包围盒 + if (debugBounds) { var b = bounds; - boundsVertices[0] = boundsVertices[4] = new(new(b.Left, b.Top), BoundsColor); - boundsVertices[1] = new(new(b.Right, b.Top), BoundsColor); - boundsVertices[2] = new(new(b.Right, b.Bottom), BoundsColor); - boundsVertices[3] = new(new(b.Left, b.Bottom), BoundsColor); - target.Draw(boundsVertices); + var v = new SFML.Graphics.Vertex() { Color = BoundsColor }; + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + v.Position = new(b.Right, b.Top); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Right, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + } + + if (debugBones) + { + var width = scale; + foreach (var bone in skeleton.Bones) + { + var boneLength = bone.Data.Length; + var p1 = new SFML.System.Vector2f(bone.WorldX, bone.WorldY); + var p2 = new SFML.System.Vector2f(bone.WorldX + boneLength * bone.A, bone.WorldY + boneLength * bone.C); + AddRectLine(p1, p2, BoneLineColor, width); + } + } + + target.Draw(lineVertices); + target.Draw(rectLineVertices); + + // 骨骼的点最后画, 层级处于上面 + if (debugBones) + { + var radius = scale; + foreach (var bone in skeleton.Bones) + { + DrawCirclePoint(target, new(bone.WorldX, bone.WorldY), BonePointColor, radius); + } } } } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs index dc51404..1a26296 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs @@ -195,7 +195,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject protected override void draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) { - vertexArray.Clear(); + triangleVertices.Clear(); states.Texture = null; states.Shader = SFMLShader.GetSpineShader(usePma); @@ -262,13 +262,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject states.Texture ??= texture; if (states.BlendMode != blendMode || states.Texture != texture) { - if (vertexArray.VertexCount > 0) + if (triangleVertices.VertexCount > 0) { - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); - - vertexArray.Clear(); + target.Draw(triangleVertices, states); + triangleVertices.Clear(); } states.BlendMode = blendMode; states.Texture = texture; @@ -302,26 +299,56 @@ namespace SpineViewer.Spine.Implementations.SpineObject vertex.Position.Y = worldVertices[index + 1]; vertex.TexCoords.X = uvs[index] * textureSizeX; vertex.TexCoords.Y = uvs[index + 1] * textureSizeY; - vertexArray.Append(vertex); + triangleVertices.Append(vertex); } clipping.ClipEnd(slot); } clipping.ClipEnd(); - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); + target.Draw(triangleVertices, states); + } - // 包围盒 - if (isDebug && isSelected && debugBounds) + protected override void debugDraw(SFML.Graphics.RenderTarget target) + { + lineVertices.Clear(); + rectLineVertices.Clear(); + + // 调试包围盒 + if (debugBounds) { var b = bounds; - boundsVertices[0] = boundsVertices[4] = new(new(b.Left, b.Top), BoundsColor); - boundsVertices[1] = new(new(b.Right, b.Top), BoundsColor); - boundsVertices[2] = new(new(b.Right, b.Bottom), BoundsColor); - boundsVertices[3] = new(new(b.Left, b.Bottom), BoundsColor); - target.Draw(boundsVertices); + var v = new SFML.Graphics.Vertex() { Color = BoundsColor }; + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + v.Position = new(b.Right, b.Top); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Right, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + } + + if (debugBones) + { + var width = scale; + foreach (var bone in skeleton.Bones) + { + var boneLength = bone.Data.Length; + var p1 = new SFML.System.Vector2f(bone.WorldX, bone.WorldY); + var p2 = new SFML.System.Vector2f(bone.WorldX + boneLength * bone.A, bone.WorldY + boneLength * bone.C); + AddRectLine(p1, p2, BoneLineColor, width); + } + } + + target.Draw(lineVertices); + target.Draw(rectLineVertices); + + // 骨骼的点最后画, 层级处于上面 + if (debugBones) + { + var radius = scale; + foreach (var bone in skeleton.Bones) + { + DrawCirclePoint(target, new(bone.WorldX, bone.WorldY), BonePointColor, radius); + } } } } diff --git a/SpineViewer/Spine/Implementations/SpineObject/Spineobject42.cs b/SpineViewer/Spine/Implementations/SpineObject/Spineobject42.cs index d6431c1..f694a0d 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/Spineobject42.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/Spineobject42.cs @@ -195,7 +195,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject protected override void draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) { - vertexArray.Clear(); + triangleVertices.Clear(); states.Texture = null; states.Shader = SFMLShader.GetSpineShader(usePma); @@ -262,13 +262,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject states.Texture ??= texture; if (states.BlendMode != blendMode || states.Texture != texture) { - if (vertexArray.VertexCount > 0) + if (triangleVertices.VertexCount > 0) { - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); - - vertexArray.Clear(); + target.Draw(triangleVertices, states); + triangleVertices.Clear(); } states.BlendMode = blendMode; states.Texture = texture; @@ -302,26 +299,56 @@ namespace SpineViewer.Spine.Implementations.SpineObject vertex.Position.Y = worldVertices[index + 1]; vertex.TexCoords.X = uvs[index] * textureSizeX; vertex.TexCoords.Y = uvs[index + 1] * textureSizeY; - vertexArray.Append(vertex); + triangleVertices.Append(vertex); } clipping.ClipEnd(slot); } clipping.ClipEnd(); - // 调试纹理 - if (!isDebug || debugTexture) - target.Draw(vertexArray, states); + target.Draw(triangleVertices, states); + } - // 包围盒 - if (isDebug && isSelected && debugBounds) + protected override void debugDraw(SFML.Graphics.RenderTarget target) + { + lineVertices.Clear(); + rectLineVertices.Clear(); + + // 调试包围盒 + if (debugBounds) { var b = bounds; - boundsVertices[0] = boundsVertices[4] = new(new(b.Left, b.Top), BoundsColor); - boundsVertices[1] = new(new(b.Right, b.Top), BoundsColor); - boundsVertices[2] = new(new(b.Right, b.Bottom), BoundsColor); - boundsVertices[3] = new(new(b.Left, b.Bottom), BoundsColor); - target.Draw(boundsVertices); + var v = new SFML.Graphics.Vertex() { Color = BoundsColor }; + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + v.Position = new(b.Right, b.Top); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Right, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Bottom); lineVertices.Append(v); lineVertices.Append(v); + v.Position = new(b.Left, b.Top); lineVertices.Append(v); + } + + if (debugBones) + { + var width = scale; + foreach (var bone in skeleton.Bones) + { + var boneLength = bone.Data.Length; + var p1 = new SFML.System.Vector2f(bone.WorldX, bone.WorldY); + var p2 = new SFML.System.Vector2f(bone.WorldX + boneLength * bone.A, bone.WorldY + boneLength * bone.C); + AddRectLine(p1, p2, BoneLineColor, width); + } + } + + target.Draw(lineVertices); + target.Draw(rectLineVertices); + + // 骨骼的点最后画, 层级处于上面 + if (debugBones) + { + var radius = scale; + foreach (var bone in skeleton.Bones) + { + DrawCirclePoint(target, new(bone.WorldX, bone.WorldY), BonePointColor, radius); + } } } } diff --git a/SpineViewer/Spine/SpineObject.cs b/SpineViewer/Spine/SpineObject.cs index 5a033dd..5c4c2b7 100644 --- a/SpineViewer/Spine/SpineObject.cs +++ b/SpineViewer/Spine/SpineObject.cs @@ -103,7 +103,13 @@ namespace SpineViewer.Spine ~SpineObject() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } - protected virtual void Dispose(bool disposing) { Preview?.Dispose(); } + protected virtual void Dispose(bool disposing) + { + Preview?.Dispose(); + triangleVertices.Dispose(); + lineVertices.Dispose(); + rectLineVertices.Dispose(); + } /// /// 运行时唯一 ID @@ -233,7 +239,7 @@ namespace SpineViewer.Spine get { lock (_lock) return isDebug; } set { lock (_lock) { isDebug = value; update(0); } } } - protected bool isDebug = false; + private bool isDebug = false; /// /// 显示纹理 @@ -243,7 +249,7 @@ namespace SpineViewer.Spine get { lock (_lock) return debugTexture; } set { lock (_lock) { debugTexture = value; update(0); } } } - protected bool debugTexture = true; + private bool debugTexture = true; /// /// 显示包围盒 @@ -263,7 +269,7 @@ namespace SpineViewer.Spine get { lock (_lock) return debugBones; } set { lock (_lock) { debugBones = value; update(0); } } } - protected bool debugBones = false; + protected bool debugBones = true; /// /// 获取已加载的皮肤列表快照, 允许出现重复值 @@ -379,32 +385,100 @@ namespace SpineViewer.Spine #region SFML.Graphics.Drawable 接口实现 - /// - /// 顶点坐标缓冲区 - /// - protected float[] worldVerticesBuffer = new float[1024]; - - /// - /// 顶点缓冲区 - /// - protected readonly SFML.Graphics.VertexArray vertexArray = new(SFML.Graphics.PrimitiveType.Triangles); - /// /// 包围盒颜色 /// protected static readonly SFML.Graphics.Color BoundsColor = new(120, 200, 0); /// - /// 包围盒顶点数组 + /// 骨骼点颜色 /// - protected readonly SFML.Graphics.VertexArray boundsVertices = new(SFML.Graphics.PrimitiveType.LineStrip, 5); + protected static readonly SFML.Graphics.Color BonePointColor = new(0, 255, 0); + + /// + /// 骨骼线颜色 + /// + protected static readonly SFML.Graphics.Color BoneLineColor = new(255, 0, 0); + + /// + /// spine 顶点坐标缓冲区 + /// + protected float[] worldVerticesBuffer = new float[1024]; + + /// + /// 三角形顶点缓冲区 + /// + protected readonly SFML.Graphics.VertexArray triangleVertices = new(SFML.Graphics.PrimitiveType.Triangles); + + /// + /// 无面积线条缓冲区 + /// + protected readonly SFML.Graphics.VertexArray lineVertices = new(SFML.Graphics.PrimitiveType.Lines); + + /// + /// 有半径圆点临时缓存对象 + /// + private readonly SFML.Graphics.CircleShape circlePointShape = new(); + + /// + /// 有宽度线条缓冲区, 需要通过 添加顶点 + /// + protected readonly SFML.Graphics.VertexArray rectLineVertices = new(SFML.Graphics.PrimitiveType.Quads); + + /// + /// 绘制有半径的实心圆点, 随模型一起缩放大小 + /// + protected void DrawCirclePoint(SFML.Graphics.RenderTarget target, SFML.System.Vector2f p, SFML.Graphics.Color color, float radius = 1) + { + circlePointShape.Origin = new(radius, radius); + circlePointShape.Position = p; + circlePointShape.FillColor = color; + circlePointShape.Radius = radius; + target.Draw(circlePointShape); + } + + /// + /// 绘制有宽度的实心线, 会随模型一起缩放粗细, 顶点被存储在 数组内 + /// + protected void AddRectLine(SFML.System.Vector2f p1, SFML.System.Vector2f p2, SFML.Graphics.Color color, float width = 1) + { + var dx = p2.X - p1.X; + var dy = p2.Y - p1.Y; + var dt = (float)Math.Sqrt(dx * dx + dy * dy); + if (dt == 0) return; + + var cosTheta = -dy / dt; + var sinTheta = dx / dt; + var halfWidth = width / 2; + var t = new SFML.System.Vector2f(halfWidth * cosTheta, halfWidth * sinTheta); + var v = new SFML.Graphics.Vertex() { Color = color }; + + v.Position = p1 + t; rectLineVertices.Append(v); + v.Position = p2 + t; rectLineVertices.Append(v); + v.Position = p2 - t; rectLineVertices.Append(v); + v.Position = p1 - t; rectLineVertices.Append(v); + } /// /// SFML.Graphics.Drawable 接口实现 /// 这个渲染实现绘制出来的像素将是预乘的, 当渲染的背景透明度是 1 时, 则等价于非预乘的结果, 即正常画面, 否则画面偏暗 /// 可以用于 的渲染, 因为直接在窗口上绘制时窗口始终是不透明的 /// - public void Draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) { lock (_lock) draw(target, states); } + public void Draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states) + { + lock (_lock) + { + if (!isDebug) + { + draw(target, states); + } + else + { + if (debugTexture) draw(target, states); + debugDraw(target); + } + } + } /// /// 这个渲染实现绘制出来的像素将是预乘的, 当渲染的背景透明度是 1 时, 则等价于非预乘的结果, 即正常画面, 否则画面偏暗 @@ -412,6 +486,11 @@ namespace SpineViewer.Spine /// protected abstract void draw(SFML.Graphics.RenderTarget target, SFML.Graphics.RenderStates states); + /// + /// 渲染调试内容 + /// + protected abstract void debugDraw(SFML.Graphics.RenderTarget target); + #endregion } } \ No newline at end of file