mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 17:26:01 +08:00
[xna] Added SkeletonDebugRenderer, modified sample to reproduce clipping issue.
This commit is contained in:
parent
580b27c68d
commit
a5d2519f86
1
.gitignore
vendored
1
.gitignore
vendored
@ -55,6 +55,7 @@ spine-xna/obj
|
||||
spine-xna/example/bin
|
||||
spine-xna/example/obj
|
||||
spine-xna/example-content/obj/
|
||||
spine-xna/.vs/
|
||||
|
||||
spine-unity/Assets/spine-csharp*
|
||||
!spine-unity/Assets/spine-csharp/Place spine-csharp src here.*
|
||||
|
||||
@ -140,6 +140,7 @@
|
||||
* Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer`
|
||||
* Added support for two color tint. For it to work, you need to add the `SpineEffect.fx` file to your content project, then load it via `var effect = Content.Load<Effect>("SpineEffect");`, and set it on the `SkeletonRenderer`. See the example project for code.
|
||||
* Added support for any `Effect` to be used by `SkeletonRenderer`
|
||||
* Added `SkeletonDebugRenderer`
|
||||
|
||||
## Java
|
||||
* **Breaking changes**
|
||||
|
||||
@ -258,7 +258,7 @@ namespace Spine {
|
||||
return clipped;
|
||||
}
|
||||
|
||||
static void MakeClockwise (ExposedList<float> polygon) {
|
||||
public static void MakeClockwise (ExposedList<float> polygon) {
|
||||
float[] vertices = polygon.Items;
|
||||
int verticeslength = polygon.Count;
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
using System;
|
||||
|
||||
namespace Spine {
|
||||
internal class Triangulator {
|
||||
public class Triangulator {
|
||||
private readonly ExposedList<ExposedList<float>> convexPolygons = new ExposedList<ExposedList<float>>();
|
||||
private readonly ExposedList<ExposedList<int>> convexPolygonsIndices = new ExposedList<ExposedList<int>>();
|
||||
|
||||
|
||||
13
spine-xna/example/data/skeleton.atlas
Normal file
13
spine-xna/example/data/skeleton.atlas
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
skeleton.png
|
||||
size: 256,256
|
||||
format: RGBA8888
|
||||
filter: Linear,Linear
|
||||
repeat: none
|
||||
body
|
||||
rotate: false
|
||||
xy: 2, 2
|
||||
size: 192, 129
|
||||
orig: 192, 129
|
||||
offset: 0, 0
|
||||
index: -1
|
||||
3938
spine-xna/example/data/skeleton.json
Normal file
3938
spine-xna/example/data/skeleton.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
spine-xna/example/data/skeleton.png
Normal file
BIN
spine-xna/example/data/skeleton.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
@ -128,9 +128,18 @@
|
||||
<None Include="data\raptor.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="data\skeleton.atlas">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="data\skeleton.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="data\spineboy.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="data\skeleton.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\tank.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
@ -43,6 +43,7 @@ namespace Spine {
|
||||
public class Example : Microsoft.Xna.Framework.Game {
|
||||
GraphicsDeviceManager graphics;
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
SkeletonDebugRenderer skeletonDebugRenderer;
|
||||
Skeleton skeleton;
|
||||
Slot headSlot;
|
||||
AnimationState state;
|
||||
@ -79,11 +80,16 @@ namespace Spine {
|
||||
skeletonRenderer.PremultipliedAlpha = false;
|
||||
skeletonRenderer.Effect = spineEffect;
|
||||
|
||||
skeletonDebugRenderer = new SkeletonDebugRenderer(GraphicsDevice);
|
||||
skeletonDebugRenderer.DisableAll();
|
||||
skeletonDebugRenderer.DrawClipping = true;
|
||||
|
||||
// String name = "spineboy-ess";
|
||||
// String name = "goblins-pro";
|
||||
// String name = "raptor-pro";
|
||||
// String name = "tank-pro";
|
||||
String name = "coin-pro";
|
||||
// String name = "coin-pro";
|
||||
String name = "skeleton";
|
||||
String atlasName = name.Replace("-pro", "").Replace("-ess", "");
|
||||
bool binaryData = false;
|
||||
|
||||
@ -122,27 +128,34 @@ namespace Spine {
|
||||
state.Complete += Complete;
|
||||
state.Event += Event;
|
||||
|
||||
state.SetAnimation(0, "test", false);
|
||||
state.SetAnimation(0, "run", true);
|
||||
TrackEntry entry = state.AddAnimation(0, "jump", false, 0);
|
||||
entry.End += End; // Event handling for queued animations.
|
||||
state.AddAnimation(0, "run", true, 0);
|
||||
}
|
||||
else if (name == "raptor-pro") {
|
||||
state.SetAnimation(0, "walk", true);
|
||||
state.AddAnimation(1, "gungrab", false, 2);
|
||||
state.AddAnimation(1, "gun-grab", false, 2);
|
||||
}
|
||||
else if (name == "coin-pro") {
|
||||
state.SetAnimation(0, "rotate", true);
|
||||
}
|
||||
else if (name == "tank-pro") {
|
||||
skeleton.X += 300;
|
||||
state.SetAnimation(0, "drive", true);
|
||||
}
|
||||
else if (name == "skeleton") {
|
||||
skeleton.SetSkin("Pig_Normal");
|
||||
skeleton.FlipY = true;
|
||||
skeleton.Y -= 200;
|
||||
state.SetAnimation(0, "BattleIdle", true);
|
||||
}
|
||||
else {
|
||||
state.SetAnimation(0, "walk", true);
|
||||
}
|
||||
|
||||
skeleton.X = 400 + (name == "tank-pro" ? 300: 0);
|
||||
skeleton.Y = GraphicsDevice.Viewport.Height;
|
||||
skeleton.X += 400;
|
||||
skeleton.Y += GraphicsDevice.Viewport.Height;
|
||||
skeleton.UpdateWorldTransform();
|
||||
|
||||
headSlot = skeleton.FindSlot("head");
|
||||
@ -176,6 +189,11 @@ namespace Spine {
|
||||
skeletonRenderer.Draw(skeleton);
|
||||
skeletonRenderer.End();
|
||||
|
||||
skeletonDebugRenderer.Effect.Projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0);
|
||||
skeletonDebugRenderer.Begin();
|
||||
skeletonDebugRenderer.Draw(skeleton);
|
||||
skeletonDebugRenderer.End();
|
||||
|
||||
bounds.Update(skeleton, true);
|
||||
MouseState mouse = Mouse.GetState();
|
||||
if (headSlot != null) {
|
||||
|
||||
@ -110,6 +110,8 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="src\MeshBatcher.cs" />
|
||||
<Compile Include="src\ShapeRenderer.cs" />
|
||||
<Compile Include="src\SkeletonDebugRenderer.cs" />
|
||||
<Compile Include="src\XnaTextureLoader.cs" />
|
||||
<Compile Include="src\Util.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
167
spine-xna/src/ShapeRenderer.cs
Normal file
167
spine-xna/src/ShapeRenderer.cs
Normal file
@ -0,0 +1,167 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.3
|
||||
*
|
||||
* Copyright (c) 2013-2015, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to use, install, execute and perform the Spine
|
||||
* Runtimes Software (the "Software") and derivative works solely for personal
|
||||
* or internal use. Without the written permission of Esoteric Software (see
|
||||
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
||||
* translate, adapt or otherwise create derivative works, improvements of the
|
||||
* Software or develop new applications using the Software or (b) remove,
|
||||
* delete, alter or obscure any trademarks or any copyright, trademark, patent
|
||||
* or other intellectual property or proprietary rights notices on or in the
|
||||
* Software, including any copy thereof. Redistributions in binary or source
|
||||
* form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Spine {
|
||||
/// <summary>
|
||||
/// Batch drawing of lines and shapes that can be derrived from lines.
|
||||
///
|
||||
/// Call drawing methods in between Begin()/End()
|
||||
/// </summary>
|
||||
public class ShapeRenderer {
|
||||
GraphicsDevice device;
|
||||
List<VertexPositionColor> vertices = new List<VertexPositionColor>();
|
||||
Color color = Color.White;
|
||||
BasicEffect effect;
|
||||
public BasicEffect Effect { get { return effect; } set { effect = value; } }
|
||||
|
||||
public ShapeRenderer(GraphicsDevice device) {
|
||||
this.device = device;
|
||||
this.effect = new BasicEffect(device);
|
||||
effect.World = Matrix.Identity;
|
||||
effect.View = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up);
|
||||
effect.TextureEnabled = false;
|
||||
effect.VertexColorEnabled = true;
|
||||
}
|
||||
|
||||
public void SetColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public void Begin() {
|
||||
device.RasterizerState = new RasterizerState();
|
||||
device.BlendState = BlendState.AlphaBlend;
|
||||
}
|
||||
|
||||
public void Line(float x1, float y1, float x2, float y2) {
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x1, y1, 0), color));
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x2, y2, 0), color));
|
||||
}
|
||||
|
||||
/** Calls {@link #circle(float, float, float, int)} by estimating the number of segments needed for a smooth circle. */
|
||||
public void Circle(float x, float y, float radius) {
|
||||
Circle(x, y, radius, Math.Max(1, (int)(6 * (float)Math.Pow(radius, 1.0f / 3.0f))));
|
||||
}
|
||||
|
||||
/** Draws a circle using {@link ShapeType#Line} or {@link ShapeType#Filled}. */
|
||||
public void Circle(float x, float y, float radius, int segments) {
|
||||
if (segments <= 0) throw new ArgumentException("segments must be > 0.");
|
||||
float angle = 2 * MathUtils.PI / segments;
|
||||
float cos = MathUtils.Cos(angle);
|
||||
float sin = MathUtils.Sin(angle);
|
||||
float cx = radius, cy = 0;
|
||||
float temp = 0;
|
||||
|
||||
for (int i = 0; i < segments; i++) {
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x + cx, y + cy, 0), color));
|
||||
temp = cx;
|
||||
cx = cos * cx - sin * cy;
|
||||
cy = sin * temp + cos * cy;
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x + cx, y + cy, 0), color));
|
||||
}
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x + cx, y + cy, 0), color));
|
||||
|
||||
temp = cx;
|
||||
cx = radius;
|
||||
cy = 0;
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x + cx, y + cy, 0), color));
|
||||
}
|
||||
|
||||
public void Triangle(float x1, float y1, float x2, float y2, float x3, float y3) {
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x1, y1, 0), color));
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x2, y2, 0), color));
|
||||
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x2, y2, 0), color));
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x3, y3, 0), color));
|
||||
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x3, y3, 0), color));
|
||||
vertices.Add(new VertexPositionColor(new Vector3(x1, y1, 0), color));
|
||||
}
|
||||
|
||||
public void X(float x, float y, float len) {
|
||||
Line(x + len, y + len, x - len, y - len);
|
||||
Line(x - len, y + len, x + len, y - len);
|
||||
}
|
||||
|
||||
public void Polygon(float[] polygonVertices, int offset, int count) {
|
||||
if (count< 3) throw new ArgumentException("Polygon must contain at least 3 vertices");
|
||||
|
||||
offset <<= 1;
|
||||
count <<= 1;
|
||||
|
||||
var firstX = polygonVertices[offset];
|
||||
var firstY = polygonVertices[offset + 1];
|
||||
var last = offset + count;
|
||||
|
||||
for (int i = offset, n = offset + count - 2; i<n; i += 2) {
|
||||
var x1 = polygonVertices[i];
|
||||
var y1 = polygonVertices[i + 1];
|
||||
|
||||
var x2 = 0f;
|
||||
var y2 = 0f;
|
||||
|
||||
if (i + 2 >= last) {
|
||||
x2 = firstX;
|
||||
y2 = firstY;
|
||||
} else {
|
||||
x2 = polygonVertices[i + 2];
|
||||
y2 = polygonVertices[i + 3];
|
||||
}
|
||||
|
||||
Line(x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
public void Rect(float x, float y, float width, float height) {
|
||||
Line(x, y, x + width, y);
|
||||
Line(x + width, y, x + width, y + height);
|
||||
Line(x + width, y + height, x, y + height);
|
||||
Line(x, y + height, x, y);
|
||||
}
|
||||
|
||||
public void End() {
|
||||
var verticesArray = vertices.ToArray();
|
||||
|
||||
foreach (EffectPass pass in effect.CurrentTechnique.Passes) {
|
||||
pass.Apply();
|
||||
device.DrawUserPrimitives(PrimitiveType.LineList, verticesArray, 0, verticesArray.Length / 2);
|
||||
}
|
||||
|
||||
vertices.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
224
spine-xna/src/SkeletonDebugRenderer.cs
Normal file
224
spine-xna/src/SkeletonDebugRenderer.cs
Normal file
@ -0,0 +1,224 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.3
|
||||
*
|
||||
* Copyright (c) 2013-2015, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to use, install, execute and perform the Spine
|
||||
* Runtimes Software (the "Software") and derivative works solely for personal
|
||||
* or internal use. Without the written permission of Esoteric Software (see
|
||||
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
||||
* translate, adapt or otherwise create derivative works, improvements of the
|
||||
* Software or develop new applications using the Software or (b) remove,
|
||||
* delete, alter or obscure any trademarks or any copyright, trademark, patent
|
||||
* or other intellectual property or proprietary rights notices on or in the
|
||||
* Software, including any copy thereof. Redistributions in binary or source
|
||||
* form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Spine {
|
||||
public class SkeletonDebugRenderer {
|
||||
ShapeRenderer renderer;
|
||||
|
||||
private static Color boneLineColor = new Color(1f, 0f, 0f, 1f);
|
||||
private static Color boneOriginColor = new Color(0f, 1f, 0f, 1f);
|
||||
private static Color attachmentLineColor = new Color(0f, 0f, 1f, 0.5f);
|
||||
private static Color triangleLineColor = new Color(1f, 0.64f, 0f, 0.5f);
|
||||
private static Color pathColor = new Color(1f, 0.5f, 0f, 1f);
|
||||
private static Color clipColor = new Color(0.8f, 0f, 0f, 1f);
|
||||
private static Color aabbColor = new Color(0f, 1f, 0f, 0.5f);
|
||||
|
||||
public BasicEffect Effect { get { return renderer.Effect; } set { renderer.Effect = value; } }
|
||||
public bool DrawBones { get; set; }
|
||||
public bool DrawRegionAttachments { get; set; }
|
||||
public bool DrawBoundingBoxes { get; set; }
|
||||
public bool DrawMeshHull { get; set; }
|
||||
public bool DrawMeshTriangles { get; set; }
|
||||
public bool DrawPaths { get; set; }
|
||||
public bool DrawClipping { get; set; }
|
||||
public bool DrawSkeletonXY { get; set; }
|
||||
public void DisableAll() {
|
||||
DrawBones = false;
|
||||
DrawRegionAttachments = false;
|
||||
DrawBoundingBoxes = false;
|
||||
DrawMeshHull = false;
|
||||
DrawMeshTriangles = false;
|
||||
DrawPaths = false;
|
||||
DrawClipping = false;
|
||||
DrawSkeletonXY = false;
|
||||
}
|
||||
|
||||
public void EnableAll() {
|
||||
DrawBones = true;
|
||||
DrawRegionAttachments = true;
|
||||
DrawBoundingBoxes = true;
|
||||
DrawMeshHull = true;
|
||||
DrawMeshTriangles = true;
|
||||
DrawPaths = true;
|
||||
DrawClipping = true;
|
||||
DrawSkeletonXY = true;
|
||||
}
|
||||
|
||||
private float[] vertices = new float[1024 * 2];
|
||||
private SkeletonBounds bounds = new SkeletonBounds();
|
||||
private Triangulator triangulator = new Triangulator();
|
||||
|
||||
public SkeletonDebugRenderer (GraphicsDevice device) {
|
||||
renderer = new ShapeRenderer(device);
|
||||
EnableAll();
|
||||
}
|
||||
|
||||
public void Begin() {
|
||||
renderer.Begin();
|
||||
}
|
||||
|
||||
public void Draw(Skeleton skeleton) {
|
||||
var skeletonX = skeleton.X;
|
||||
var skeletonY = skeleton.Y;
|
||||
|
||||
var bones = skeleton.Bones;
|
||||
if (DrawBones) {
|
||||
renderer.SetColor(boneLineColor);
|
||||
for (int i = 0, n = bones.Count; i < n; i++) {
|
||||
var bone = bones.Items[i];
|
||||
if (bone.Parent == null) continue;
|
||||
var x = bone.Data.Length * bone.A + bone.WorldX;
|
||||
var y = bone.Data.Length * bone.C + bone.WorldY;
|
||||
renderer.Line(bone.WorldX, bone.WorldY, x, y);
|
||||
}
|
||||
if (DrawSkeletonXY) renderer.X(skeletonX, skeletonY, 4);
|
||||
}
|
||||
|
||||
if (DrawRegionAttachments) {
|
||||
renderer.SetColor(attachmentLineColor);
|
||||
var slots = skeleton.Slots;
|
||||
for (int i = 0, n = slots.Count; i < n; i++) {
|
||||
var slot = slots.Items[i];
|
||||
var attachment = slot.Attachment;
|
||||
if (attachment is RegionAttachment) {
|
||||
var regionAttachment = (RegionAttachment) attachment;
|
||||
var vertices = this.vertices;
|
||||
regionAttachment.ComputeWorldVertices(slot.Bone, vertices, 0, 2);
|
||||
renderer.Line(vertices[0], vertices[1], vertices[2], vertices[3]);
|
||||
renderer.Line(vertices[2], vertices[3], vertices[4], vertices[5]);
|
||||
renderer.Line(vertices[4], vertices[5], vertices[6], vertices[7]);
|
||||
renderer.Line(vertices[6], vertices[7], vertices[0], vertices[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DrawMeshHull || DrawMeshTriangles) {
|
||||
var slots = skeleton.Slots;
|
||||
for (int i = 0, n = slots.Count; i < n; i++) {
|
||||
var slot = slots.Items[i];
|
||||
var attachment = slot.Attachment;
|
||||
if (!(attachment is MeshAttachment)) continue;
|
||||
var mesh = (MeshAttachment)attachment;
|
||||
var world = vertices = vertices.Length < mesh.WorldVerticesLength ? new float[mesh.WorldVerticesLength] : vertices;
|
||||
mesh.ComputeWorldVertices(slot, 0, mesh.WorldVerticesLength, world, 0, 2);
|
||||
int[] triangles = mesh.Triangles;
|
||||
var hullLength = mesh.HullLength;
|
||||
if (DrawMeshTriangles) {
|
||||
renderer.SetColor(triangleLineColor);
|
||||
for (int ii = 0, nn = triangles.Count(); ii < nn; ii += 3) {
|
||||
int v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2;
|
||||
renderer.Triangle(world[v1], world[v1 + 1], //
|
||||
world[v2], world[v2 + 1], //
|
||||
world[v3], world[v3 + 1] //
|
||||
);
|
||||
}
|
||||
}
|
||||
if (DrawMeshHull && hullLength > 0) {
|
||||
renderer.SetColor(attachmentLineColor);
|
||||
hullLength = (hullLength >> 1) * 2;
|
||||
float lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1];
|
||||
for (int ii = 0, nn = hullLength; ii < nn; ii += 2) {
|
||||
float x = vertices[ii], y = vertices[ii + 1];
|
||||
renderer.Line(x, y, lastX, lastY);
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DrawBoundingBoxes) {
|
||||
var bounds = this.bounds;
|
||||
bounds.Update(skeleton, true);
|
||||
renderer.SetColor(aabbColor);
|
||||
renderer.Rect(bounds.MinX, bounds.MinY, bounds.Width, bounds.Height);
|
||||
var polygons = bounds.Polygons;
|
||||
var boxes = bounds.BoundingBoxes;
|
||||
for (int i = 0, n = polygons.Count; i < n; i++) {
|
||||
var polygon = polygons.Items[i];
|
||||
renderer.Polygon(polygon.Vertices, 0, polygon.Count);
|
||||
}
|
||||
}
|
||||
|
||||
if (DrawBones) {
|
||||
renderer.SetColor(boneOriginColor);
|
||||
for (int i = 0, n = bones.Count; i < n; i++) {
|
||||
var bone = bones.Items[i];
|
||||
renderer.Circle(bone.WorldX, bone.WorldY, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (DrawClipping) {
|
||||
var slots = skeleton.Slots;
|
||||
renderer.SetColor(clipColor);
|
||||
for (int i = 0, n = slots.Count; i < n; i++) {
|
||||
var slot = slots.Items[i];
|
||||
var attachment = slot.Attachment;
|
||||
if (!(attachment is ClippingAttachment)) continue;
|
||||
var clip = (ClippingAttachment)attachment;
|
||||
var nn = clip.WorldVerticesLength;
|
||||
var world = vertices = vertices.Length < nn ? new float[nn] : vertices;
|
||||
clip.ComputeWorldVertices(slot, 0, nn, world, 0, 2);
|
||||
ExposedList<float> clippingPolygon = new ExposedList<float>();
|
||||
for (int ii = 0; ii < nn; ii += 2) {
|
||||
var x = world[ii];
|
||||
var y = world[ii + 1];
|
||||
var x2 = world[(ii + 2) % nn];
|
||||
var y2 = world[(ii + 3) % nn];
|
||||
renderer.Line(x, y, x2, y2);
|
||||
clippingPolygon.Add(x);
|
||||
clippingPolygon.Add(y);
|
||||
}
|
||||
|
||||
if (!skeleton.FlipY) SkeletonClipping.MakeClockwise(clippingPolygon);
|
||||
var clippingPolygons = triangulator.Decompose(clippingPolygon, triangulator.Triangulate(clippingPolygon));
|
||||
foreach (var polygon in clippingPolygons) {
|
||||
if (!skeleton.FlipY) SkeletonClipping.MakeClockwise(polygon);
|
||||
polygon.Add(polygon.Items[0]);
|
||||
polygon.Add(polygon.Items[1]);
|
||||
renderer.Polygon(polygon.Items, 0, polygon.Count >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void End() {
|
||||
renderer.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user