mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 09:16:01 +08:00
Merge branch '3.6' into 3.7-beta
This commit is contained in:
commit
f5965b0fdf
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.*
|
||||
|
||||
@ -142,6 +142,7 @@
|
||||
* 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 support for `IVertexEffect` to modify vertices of skeletons on the CPU. `IVertexEffect` instances can be set on the `SkeletonRenderer`. See example project.
|
||||
* Added `SkeletonDebugRenderer`
|
||||
|
||||
## Java
|
||||
* **Breaking changes**
|
||||
|
||||
@ -28,6 +28,10 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if (UNITY_5 || UNITY_5_3_OR_NEWER || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
|
||||
#define IS_UNITY
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@ -44,7 +48,7 @@ namespace Spine {
|
||||
List<AtlasRegion> regions = new List<AtlasRegion>();
|
||||
TextureLoader textureLoader;
|
||||
|
||||
#if !(UNITY_5 || UNITY_4 || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1) // !UNITY
|
||||
#if !(IS_UNITY)
|
||||
#if WINDOWS_STOREAPP
|
||||
private async Task ReadFile(string path, TextureLoader textureLoader) {
|
||||
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
|
||||
@ -82,7 +86,7 @@ namespace Spine {
|
||||
}
|
||||
#endif // WINDOWS_STOREAPP
|
||||
|
||||
#endif // !(UNITY)
|
||||
#endif
|
||||
|
||||
public Atlas (TextReader reader, string dir, TextureLoader textureLoader) {
|
||||
Load(reader, dir, textureLoader);
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if (UNITY_5 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
|
||||
#if (UNITY_5 || UNITY_5_3_OR_NEWER || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
|
||||
#define IS_UNITY
|
||||
#endif
|
||||
|
||||
|
||||
@ -154,7 +154,7 @@ namespace Spine {
|
||||
clippedUVsItems[s + 2] = u2;
|
||||
clippedUVsItems[s + 3] = v2;
|
||||
clippedUVsItems[s + 4] = u3;
|
||||
clippedUVsItems[s + 5] = v3;
|
||||
clippedUVsItems[s + 5] = v3;
|
||||
|
||||
s = clippedTriangles.Count;
|
||||
int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3).Items;
|
||||
@ -180,9 +180,9 @@ namespace Spine {
|
||||
if (clippingArea.Count % 4 >= 2) {
|
||||
input = output;
|
||||
output = scratch;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
input = scratch;
|
||||
}
|
||||
|
||||
input.Clear();
|
||||
input.Add(x1);
|
||||
@ -251,14 +251,14 @@ namespace Spine {
|
||||
for (int i = 0, n = output.Count - 2; i < n; i++) {
|
||||
originalOutput.Add(output.Items[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
originalOutput.Resize(originalOutput.Count - 2);
|
||||
}
|
||||
|
||||
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>>();
|
||||
|
||||
@ -84,6 +84,7 @@ namespace Spine {
|
||||
}
|
||||
break;
|
||||
}
|
||||
outer:
|
||||
|
||||
if (next == 0) {
|
||||
do {
|
||||
@ -97,7 +98,6 @@ namespace Spine {
|
||||
i = next;
|
||||
next = (next + 1) % vertexCount;
|
||||
}
|
||||
outer:
|
||||
|
||||
// Cut ear tip.
|
||||
triangles.Add(indices[(vertexCount + i - 1) % vertexCount]);
|
||||
|
||||
@ -56,7 +56,8 @@ public class SkeletonClipping {
|
||||
float[] vertices = clippingPolygon.setSize(n);
|
||||
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
|
||||
makeClockwise(clippingPolygon);
|
||||
clippingPolygons = triangulator.decompose(clippingPolygon, triangulator.triangulate(clippingPolygon));
|
||||
ShortArray triangles = triangulator.triangulate(clippingPolygon);
|
||||
clippingPolygons = triangulator.decompose(clippingPolygon, triangles);
|
||||
for (FloatArray polygon : clippingPolygons) {
|
||||
makeClockwise(polygon);
|
||||
polygon.add(polygon.items[0]);
|
||||
|
||||
@ -21,7 +21,7 @@ spine-ue4 does not support multiply and screen blending. spine-ue4 does not supp
|
||||
1. Create a new Unreal Engine code project. You don't need to write C++, but the code project is needed for the plugin to compile. See the [Unreal Engine documentation](https://docs.unrealengine.com/latest/INT/) or have a look at the example in this repository.
|
||||
2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
|
||||
3. Copy the `Plugins` folder from this directory to your new project's root directory.
|
||||
4. Copy the `spine-c` folder from this repositories root directory to your project's `Plugins/SpinePlugin/Sources/SpinePlugin/Public/` directory.
|
||||
4. Copy the folder `spine-runtimes/spine-c/spine-c` to your project's `Plugins/SpinePlugin/Source/SpinePlugin/Public/` folder.
|
||||
5. Open the Unreal Project in the Unreal Editor
|
||||
|
||||
See the [Spine Runtimes documentation](http://esotericsoftware.com/spine-documentation#runtimesTitle) on how to use the APIs or check out the Spine UE4 example.
|
||||
|
||||
@ -0,0 +1,288 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 8
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 3
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 9
|
||||
m_GIWorkflowMode: 1
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_TemporalCoherenceThreshold: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 8
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_TextureWidth: 1024
|
||||
m_TextureHeight: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 256
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 3
|
||||
m_BakeBackend: 0
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 500
|
||||
m_PVRBounces: 2
|
||||
m_PVRFiltering: 0
|
||||
m_PVRFilteringMode: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousColorSigma: 1
|
||||
m_PVRFilteringAtrousNormalSigma: 1
|
||||
m_PVRFilteringAtrousPositionSigma: 1
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_ShadowMaskMode: 2
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &433620963
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 433620968}
|
||||
- component: {fileID: 433620967}
|
||||
- component: {fileID: 433620966}
|
||||
- component: {fileID: 433620965}
|
||||
- component: {fileID: 433620964}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &433620964
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
m_Enabled: 1
|
||||
--- !u!124 &433620965
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
m_Enabled: 1
|
||||
--- !u!92 &433620966
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &433620967
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 1
|
||||
orthographic size: 5
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 1
|
||||
m_AllowMSAA: 1
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
m_StereoMirrorMode: 0
|
||||
--- !u!4 &433620968
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 433620963}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &651278528
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 651278530}
|
||||
- component: {fileID: 651278529}
|
||||
m_Layer: 0
|
||||
m_Name: 2 DataAssets from Exports
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &651278529
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 651278528}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: bb0837af7345d504db63d0c662fd12dc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
skeletonJson: {fileID: 4900000, guid: e3b64d7eaf0de4e45a00b7065166554d, type: 3}
|
||||
atlasText: {fileID: 4900000, guid: 5c0a5c36970a46e4d8378760ab4a4cfc, type: 3}
|
||||
textures:
|
||||
- {fileID: 2800000, guid: 49bb65eefe08e424bbf7a38bc98ec638, type: 3}
|
||||
materialPropertySource: {fileID: 2100000, guid: 365eb017d7ae7134d820c8b808eeb121,
|
||||
type: 2}
|
||||
--- !u!4 &651278530
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 651278528}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1807176298
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 1807176300}
|
||||
- component: {fileID: 1807176299}
|
||||
m_Layer: 0
|
||||
m_Name: 1 Spawn from SkeletonData
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1807176299
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1807176298}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7193e2e00836b124191dcae19e6c9741, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
skeletonDataAsset: {fileID: 11400000, guid: 57484171e9b9c7243aa3117bc663e7b9, type: 2}
|
||||
count: 50
|
||||
startingAnimation: animation
|
||||
--- !u!4 &1807176300
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1807176298}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59dc5776e19e2f041b1cac961a86924f
|
||||
timeCreated: 1500249265
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,44 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class DataAssetsFromExportsExample : MonoBehaviour {
|
||||
|
||||
public TextAsset skeletonJson;
|
||||
public TextAsset atlasText;
|
||||
public Texture2D[] textures;
|
||||
public Material materialPropertySource;
|
||||
|
||||
AtlasAsset runtimeAtlasAsset;
|
||||
SkeletonDataAsset runtimeSkeletonDataAsset;
|
||||
SkeletonAnimation runtimeSkeletonAnimation;
|
||||
|
||||
void CreateRuntimeAssetsAndGameObject () {
|
||||
// 1. Create the AtlasAsset (needs atlas text asset and textures, and materials/shader);
|
||||
// 2. Create SkeletonDataAsset (needs json or binary asset file, and an AtlasAsset)
|
||||
// 3. Create SkeletonAnimation (needs a valid SkeletonDataAsset)
|
||||
|
||||
runtimeAtlasAsset = AtlasAsset.CreateRuntimeInstance(atlasText, textures, materialPropertySource, true);
|
||||
runtimeSkeletonDataAsset = SkeletonDataAsset.CreateRuntimeInstance(skeletonJson, runtimeAtlasAsset, true);
|
||||
}
|
||||
|
||||
IEnumerator Start () {
|
||||
CreateRuntimeAssetsAndGameObject();
|
||||
runtimeSkeletonDataAsset.GetSkeletonData(false); // preload.
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
runtimeSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(runtimeSkeletonDataAsset);
|
||||
|
||||
// Extra Stuff
|
||||
runtimeSkeletonAnimation.Initialize(false);
|
||||
runtimeSkeletonAnimation.Skeleton.SetSkin("base");
|
||||
runtimeSkeletonAnimation.Skeleton.SetSlotsToSetupPose();
|
||||
runtimeSkeletonAnimation.AnimationState.SetAnimation(0, "run", true);
|
||||
runtimeSkeletonAnimation.GetComponent<MeshRenderer>().sortingOrder = 10;
|
||||
runtimeSkeletonAnimation.transform.Translate(Vector3.down * 2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb0837af7345d504db63d0c662fd12dc
|
||||
timeCreated: 1500249349
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -39,7 +39,7 @@ namespace Spine.Unity.Examples {
|
||||
|
||||
#region Inspector
|
||||
[SpineSkin]
|
||||
public string baseSkinName = "base";
|
||||
public string templateAttachmentsSkin = "base";
|
||||
public Material sourceMaterial; // This will be used as the basis for shader and material property settings.
|
||||
|
||||
[Header("Visor")]
|
||||
@ -83,26 +83,25 @@ namespace Spine.Unity.Examples {
|
||||
// STEP 0: PREPARE SKINS
|
||||
// Let's prepare a new skin to be our custom skin with equips/customizations. We get a clone so our original skins are unaffected.
|
||||
customSkin = customSkin ?? new Skin("custom skin"); // This requires that all customizations are done with skin placeholders defined in Spine.
|
||||
//customSkin = customSkin ?? skeleton.UnshareSkin(true, false, skeletonAnimation.AnimationState); // use this if you are not customizing on the default skin and don't plan to remove
|
||||
// Next let's
|
||||
var baseSkin = skeleton.Data.FindSkin(baseSkinName);
|
||||
//customSkin = customSkin ?? skeleton.UnshareSkin(true, false, skeletonAnimation.AnimationState); // use this if you are not customizing on the default skin.
|
||||
var templateSkin = skeleton.Data.FindSkin(templateAttachmentsSkin);
|
||||
|
||||
// STEP 1: "EQUIP" ITEMS USING SPRITES
|
||||
// STEP 1.1 Find the original attachment.
|
||||
// Step 1.2 Get a clone of the original attachment.
|
||||
// STEP 1.1 Find the original/template attachment.
|
||||
// Step 1.2 Get a clone of the original/template attachment.
|
||||
// Step 1.3 Apply the Sprite image to the clone.
|
||||
// Step 1.4 Add the remapped clone to the new custom skin.
|
||||
|
||||
// Let's do this for the visor.
|
||||
int visorSlotIndex = skeleton.FindSlotIndex(visorSlot); // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
|
||||
Attachment baseAttachment = baseSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
|
||||
Attachment newAttachment = baseAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||
Attachment templateAttachment = templateSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
|
||||
Attachment newAttachment = templateAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
|
||||
|
||||
// And now for the gun.
|
||||
int gunSlotIndex = skeleton.FindSlotIndex(gunSlot);
|
||||
Attachment baseGun = baseSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
|
||||
Attachment newGun = baseGun.GetRemappedClone(gunSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||
Attachment templateGun = templateSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
|
||||
Attachment newGun = templateGun.GetRemappedClone(gunSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
|
||||
|
||||
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
|
||||
@ -119,17 +118,17 @@ namespace Spine.Unity.Examples {
|
||||
// Under the hood, this relies on
|
||||
if (repack) {
|
||||
var repackedSkin = new Skin("repacked skin");
|
||||
repackedSkin.Append(skeleton.Data.DefaultSkin);
|
||||
repackedSkin.Append(customSkin);
|
||||
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas);
|
||||
skeleton.SetSkin(repackedSkin);
|
||||
repackedSkin.Append(skeleton.Data.DefaultSkin); // Include the "default" skin. (everything outside of skin placeholders)
|
||||
repackedSkin.Append(customSkin); // Include your new custom skin.
|
||||
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas); // Pack all the items in the skin.
|
||||
skeleton.SetSkin(repackedSkin); // Assign the repacked skin to your Skeleton.
|
||||
if (bbFollower != null) bbFollower.Initialize(true);
|
||||
} else {
|
||||
skeleton.SetSkin(customSkin);
|
||||
skeleton.SetSkin(customSkin); // Just use the custom skin directly.
|
||||
}
|
||||
|
||||
skeleton.SetSlotsToSetupPose();
|
||||
skeletonAnimation.Update(0);
|
||||
|
||||
skeleton.SetSlotsToSetupPose(); // Use the pose from setup pose.
|
||||
skeletonAnimation.Update(0); // Use the pose in the currently active animation.
|
||||
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class SpawnFromSkeletonDataExample : MonoBehaviour {
|
||||
|
||||
public SkeletonDataAsset skeletonDataAsset;
|
||||
[Range(0, 100)]
|
||||
public int count = 20;
|
||||
|
||||
[SpineAnimation(dataField:"skeletonDataAsset")]
|
||||
public string startingAnimation;
|
||||
|
||||
IEnumerator Start () {
|
||||
if (skeletonDataAsset == null) yield break;
|
||||
skeletonDataAsset.GetSkeletonData(false); // Preload SkeletonDataAsset.
|
||||
yield return new WaitForSeconds(1f); // Pretend stuff is happening.
|
||||
|
||||
var spineAnimation = skeletonDataAsset.GetSkeletonData(false).FindAnimation(startingAnimation);
|
||||
for (int i = 0; i < count; i++) {
|
||||
var sa = SkeletonAnimation.NewSkeletonAnimationGameObject(skeletonDataAsset); // Spawn a new SkeletonAnimation GameObject.
|
||||
DoExtraStuff(sa, spineAnimation); // optional stuff for fun.
|
||||
sa.gameObject.name = i.ToString();
|
||||
yield return new WaitForSeconds(1f/8f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DoExtraStuff (SkeletonAnimation sa, Spine.Animation spineAnimation) {
|
||||
sa.transform.localPosition = Random.insideUnitCircle * 6f;
|
||||
sa.transform.SetParent(this.transform, false);
|
||||
|
||||
if (spineAnimation != null) {
|
||||
sa.Initialize(false);
|
||||
sa.AnimationState.SetAnimation(0, spineAnimation, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7193e2e00836b124191dcae19e6c9741
|
||||
timeCreated: 1500249330
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -13,8 +13,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
atlasAssets:
|
||||
- {fileID: 11400000, guid: 6f86779b1deba7c4aaec1f5895510b57, type: 2}
|
||||
skeletonJSON: {fileID: 4900000, guid: 95c98e245823e2243a1d8e7a1ef16c51, type: 3}
|
||||
scale: 0.01
|
||||
skeletonJSON: {fileID: 4900000, guid: 95c98e245823e2243a1d8e7a1ef16c51, type: 3}
|
||||
fromAnimation: []
|
||||
toAnimation: []
|
||||
duration: []
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: Runtime Template Material
|
||||
m_Shader: {fileID: 4800000, guid: 1e8a610c9e01c3648bac42585e5fc676, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 365eb017d7ae7134d820c8b808eeb121
|
||||
timeCreated: 1500250447
|
||||
licenseType: Free
|
||||
NativeFormatImporter:
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -60,10 +60,7 @@ namespace Spine.Unity {
|
||||
|
||||
/// <summary>
|
||||
/// Creates a runtime AtlasAsset. Only providing the textures is slower because it has to search for atlas page matches. <seealso cref="Spine.Unity.AtlasAsset.CreateRuntimeInstance(TextAsset, Material[], bool)"/></summary>
|
||||
public static AtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Shader shader, bool initialize) {
|
||||
if (shader == null)
|
||||
shader = Shader.Find("Spine/Skeleton");
|
||||
|
||||
public static AtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Material materialPropertySource, bool initialize) {
|
||||
// Get atlas page names.
|
||||
string atlasString = atlasText.text;
|
||||
atlasString = atlasString.Replace("\r", "");
|
||||
@ -84,7 +81,7 @@ namespace Spine.Unity {
|
||||
for (int j = 0, m = textures.Length; j < m; j++) {
|
||||
if (string.Equals(pageName, textures[j].name, System.StringComparison.OrdinalIgnoreCase)) {
|
||||
// Match found.
|
||||
mat = new Material(shader);
|
||||
mat = new Material(materialPropertySource);
|
||||
mat.mainTexture = textures[j];
|
||||
break;
|
||||
}
|
||||
@ -102,14 +99,12 @@ namespace Spine.Unity {
|
||||
|
||||
/// <summary>
|
||||
/// Creates a runtime AtlasAsset. Only providing the textures is slower because it has to search for atlas page matches. <seealso cref="Spine.Unity.AtlasAsset.CreateRuntimeInstance(TextAsset, Material[], bool)"/></summary>
|
||||
public static AtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Material materialPropertySource, bool initialize) {
|
||||
var shader = materialPropertySource.shader;
|
||||
var oa = CreateRuntimeInstance(atlasText, textures, shader, initialize);
|
||||
public static AtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Shader shader, bool initialize) {
|
||||
if (shader == null)
|
||||
shader = Shader.Find("Spine/Skeleton");
|
||||
|
||||
foreach (var m in oa.materials) {
|
||||
m.CopyPropertiesFromMaterial(materialPropertySource);
|
||||
m.shaderKeywords = materialPropertySource.shaderKeywords;
|
||||
}
|
||||
Material materialProperySource = new Material(shader);
|
||||
var oa = CreateRuntimeInstance(atlasText, textures, materialProperySource, initialize);
|
||||
|
||||
return oa;
|
||||
}
|
||||
|
||||
@ -1213,7 +1213,7 @@ namespace Spine.Unity.Editor {
|
||||
#endregion
|
||||
|
||||
#region Checking Methods
|
||||
static int[][] compatibleVersions = { new[] {3, 6, 0} };
|
||||
static int[][] compatibleVersions = { new[] {3, 6, 0}, new[] {3, 5, 0} };
|
||||
//static bool isFixVersionRequired = false;
|
||||
|
||||
static bool CheckForValidSkeletonData (string skeletonJSONPath) {
|
||||
@ -1272,10 +1272,10 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
// Version warning
|
||||
if (isSpineData) {
|
||||
string runtimeVersion = compatibleVersions[0][0] + "." + compatibleVersions[0][1];
|
||||
string runtimeVersionDebugString = compatibleVersions[0][0] + "." + compatibleVersions[0][1];
|
||||
|
||||
if (string.IsNullOrEmpty(rawVersion)) {
|
||||
Debug.LogWarningFormat("Skeleton '{0}' has no version information. It may be incompatible with your runtime version: spine-unity v{1}", asset.name, runtimeVersion);
|
||||
Debug.LogWarningFormat("Skeleton '{0}' has no version information. It may be incompatible with your runtime version: spine-unity v{1}", asset.name, runtimeVersionDebugString);
|
||||
} else {
|
||||
string[] versionSplit = rawVersion.Split('.');
|
||||
bool match = false;
|
||||
@ -1292,7 +1292,7 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
|
||||
if (!match)
|
||||
Debug.LogWarningFormat("Skeleton '{0}' (exported with Spine {1}) may be incompatible with your runtime version: spine-unity v{2}", asset.name, rawVersion, runtimeVersion);
|
||||
Debug.LogWarningFormat("Skeleton '{0}' (exported with Spine {1}) may be incompatible with your runtime version: spine-unity v{2}", asset.name, rawVersion, runtimeVersionDebugString);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1476,11 +1476,18 @@ namespace Spine.Unity.Editor {
|
||||
#region TK2D Support
|
||||
const string SPINE_TK2D_DEFINE = "SPINE_TK2D";
|
||||
|
||||
static bool IsInvalidGroup (BuildTargetGroup group) {
|
||||
int gi = (int)group;
|
||||
return
|
||||
gi == 15 || gi == 16
|
||||
||
|
||||
group == BuildTargetGroup.Unknown;
|
||||
}
|
||||
|
||||
static void EnableTK2D () {
|
||||
bool added = false;
|
||||
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
|
||||
int gi = (int)group;
|
||||
if (gi == 15 || gi == 16 || group == BuildTargetGroup.Unknown)
|
||||
if (IsInvalidGroup(group))
|
||||
continue;
|
||||
|
||||
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||
@ -1506,8 +1513,7 @@ namespace Spine.Unity.Editor {
|
||||
static void DisableTK2D () {
|
||||
bool removed = false;
|
||||
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
|
||||
int gi = (int)group;
|
||||
if (gi == 15 || gi == 16 || group == BuildTargetGroup.Unknown)
|
||||
if (IsInvalidGroup(group))
|
||||
continue;
|
||||
|
||||
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||
|
||||
@ -502,16 +502,16 @@ namespace Spine.Unity {
|
||||
} else {
|
||||
var mesh = attachment as MeshAttachment;
|
||||
if (mesh != null) {
|
||||
int meshVertexCount = mesh.worldVerticesLength;
|
||||
if (workingVerts.Length < meshVertexCount) {
|
||||
workingVerts = new float[meshVertexCount];
|
||||
int meshVerticesLength = mesh.worldVerticesLength;
|
||||
if (workingVerts.Length < meshVerticesLength) {
|
||||
workingVerts = new float[meshVerticesLength];
|
||||
this.tempVerts = workingVerts;
|
||||
}
|
||||
mesh.ComputeWorldVertices(slot, 0, meshVertexCount, workingVerts, 0); //meshAttachment.ComputeWorldVertices(slot, tempVerts);
|
||||
mesh.ComputeWorldVertices(slot, 0, meshVerticesLength, workingVerts, 0); //meshAttachment.ComputeWorldVertices(slot, tempVerts);
|
||||
uvs = mesh.uvs;
|
||||
attachmentTriangleIndices = mesh.triangles;
|
||||
c.r = mesh.r; c.g = mesh.g; c.b = mesh.b; c.a = mesh.a;
|
||||
attachmentVertexCount = meshVertexCount >> 1; // meshVertexCount / 2;
|
||||
attachmentVertexCount = meshVerticesLength >> 1; // meshVertexCount / 2;
|
||||
attachmentIndexCount = mesh.triangles.Length;
|
||||
} else {
|
||||
if (useClipping) {
|
||||
|
||||
@ -469,9 +469,9 @@ namespace Spine.Unity.Modules.AttachmentTools {
|
||||
a.SetRegion(repackedRegions[regionIndexes[i]]);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
foreach (var ttp in texturesToPack)
|
||||
UnityEngine.Object.Destroy(ttp);
|
||||
// // Clean up
|
||||
// foreach (var ttp in texturesToPack)
|
||||
// UnityEngine.Object.Destroy(ttp);
|
||||
|
||||
t = newTexture;
|
||||
m = newMaterial;
|
||||
@ -482,20 +482,38 @@ namespace Spine.Unity.Modules.AttachmentTools {
|
||||
return Sprite.Create(ar.GetMainTexture(), ar.GetUnityRect(), new Vector2(0.5f, 0.5f), pixelsPerUnit);
|
||||
}
|
||||
|
||||
static Dictionary<AtlasRegion, Texture2D> CachedRegionTextures = new Dictionary<AtlasRegion, Texture2D>();
|
||||
static List<Texture2D> CachedRegionTexturesList = new List<Texture2D>();
|
||||
|
||||
public static void ClearCache () {
|
||||
foreach (var t in CachedRegionTexturesList) {
|
||||
UnityEngine.Object.Destroy(t);
|
||||
}
|
||||
CachedRegionTextures.Clear();
|
||||
CachedRegionTexturesList.Clear();
|
||||
}
|
||||
|
||||
/// <summary>Creates a new Texture2D object based on an AtlasRegion.
|
||||
/// If applyImmediately is true, Texture2D.Apply is called immediately after the Texture2D is filled with data.</summary>
|
||||
public static Texture2D ToTexture (this AtlasRegion ar, bool applyImmediately = true, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps) {
|
||||
Texture2D sourceTexture = ar.GetMainTexture();
|
||||
Rect r = ar.GetUnityRect(sourceTexture.height);
|
||||
int width = (int)r.width;
|
||||
int height = (int)r.height;
|
||||
Texture2D output = new Texture2D(width, height, textureFormat, mipmaps);
|
||||
output.name = ar.name;
|
||||
Color[] pixelBuffer = sourceTexture.GetPixels((int)r.x, (int)r.y, width, height);
|
||||
output.SetPixels(pixelBuffer);
|
||||
Texture2D output;
|
||||
|
||||
if (applyImmediately)
|
||||
output.Apply();
|
||||
CachedRegionTextures.TryGetValue(ar, out output);
|
||||
if (output == null) {
|
||||
Texture2D sourceTexture = ar.GetMainTexture();
|
||||
Rect r = ar.GetUnityRect(sourceTexture.height);
|
||||
int width = (int)r.width;
|
||||
int height = (int)r.height;
|
||||
output = new Texture2D(width, height, textureFormat, mipmaps);
|
||||
output.name = ar.name;
|
||||
Color[] pixelBuffer = sourceTexture.GetPixels((int)r.x, (int)r.y, width, height);
|
||||
output.SetPixels(pixelBuffer);
|
||||
CachedRegionTextures.Add(ar, output);
|
||||
CachedRegionTexturesList.Add(output);
|
||||
|
||||
if (applyImmediately)
|
||||
output.Apply();
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -122,6 +122,9 @@
|
||||
<None Include="data\coin-pro.skel">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="data\goblins-mesh.atlas">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="data\goblins.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
@ -195,9 +198,6 @@
|
||||
<None Include="data\coin-pro.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="data\goblins-mesh.atlas">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="data\goblins-pro.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
@ -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,12 +80,17 @@ 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 = "goblins-pro";
|
||||
// String name = "raptor-pro";
|
||||
// String name = "tank-pro";
|
||||
String name = "coin-pro";
|
||||
// String name = "coin-pro";
|
||||
String atlasName = name.Replace("-pro", "").Replace("-ess", "");
|
||||
if (name == "goblins-pro") atlasName = "goblins-mesh";
|
||||
bool binaryData = false;
|
||||
|
||||
Atlas atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice));
|
||||
@ -122,27 +128,28 @@ 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 {
|
||||
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 +183,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) {
|
||||
|
||||
@ -111,6 +111,8 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="src\MeshBatcher.cs" />
|
||||
<Compile Include="src\VertexEffect.cs" />
|
||||
<Compile Include="src\ShapeRenderer.cs" />
|
||||
<Compile Include="src\SkeletonDebugRenderer.cs" />
|
||||
<Compile Include="src\XnaTextureLoader.cs" />
|
||||
<Compile Include="src\Util.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
168
spine-xna/src/ShapeRenderer.cs
Normal file
168
spine-xna/src/ShapeRenderer.cs
Normal file
@ -0,0 +1,168 @@
|
||||
/******************************************************************************
|
||||
* 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() {
|
||||
if (vertices.Count == 0) return;
|
||||
var verticesArray = vertices.ToArray();
|
||||
|
||||
foreach (EffectPass pass in effect.CurrentTechnique.Passes) {
|
||||
pass.Apply();
|
||||
device.DrawUserPrimitives(PrimitiveType.LineList, verticesArray, 0, verticesArray.Length / 2);
|
||||
}
|
||||
|
||||
vertices.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
230
spine-xna/src/SkeletonDebugRenderer.cs
Normal file
230
spine-xna/src/SkeletonDebugRenderer.cs
Normal file
@ -0,0 +1,230 @@
|
||||
/******************************************************************************
|
||||
* 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 clipDecomposedColor = new Color(0.8f, 0.8f, 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 DrawClippingDecomposed { 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 (DrawClippingDecomposed) {
|
||||
SkeletonClipping.MakeClockwise(clippingPolygon);
|
||||
var triangles = triangulator.Triangulate(clippingPolygon);
|
||||
var clippingPolygons = triangulator.Decompose(clippingPolygon, triangles);
|
||||
renderer.SetColor(clipDecomposedColor);
|
||||
foreach (var polygon in clippingPolygons) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,8 +27,8 @@
|
||||
* 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 System;
|
||||
using System.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
@ -79,4 +79,4 @@ namespace Spine {
|
||||
return Texture2D.FromStream(device, input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user