mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-22 02:06:03 +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/bin
|
||||||
spine-xna/example/obj
|
spine-xna/example/obj
|
||||||
spine-xna/example-content/obj/
|
spine-xna/example-content/obj/
|
||||||
|
spine-xna/.vs/
|
||||||
|
|
||||||
spine-unity/Assets/spine-csharp*
|
spine-unity/Assets/spine-csharp*
|
||||||
!spine-unity/Assets/spine-csharp/Place spine-csharp src here.*
|
!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 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 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 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
|
## Java
|
||||||
* **Breaking changes**
|
* **Breaking changes**
|
||||||
|
|||||||
@ -28,6 +28,10 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* 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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -44,7 +48,7 @@ namespace Spine {
|
|||||||
List<AtlasRegion> regions = new List<AtlasRegion>();
|
List<AtlasRegion> regions = new List<AtlasRegion>();
|
||||||
TextureLoader textureLoader;
|
TextureLoader textureLoader;
|
||||||
|
|
||||||
#if !(UNITY_5 || UNITY_4 || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1) // !UNITY
|
#if !(IS_UNITY)
|
||||||
#if WINDOWS_STOREAPP
|
#if WINDOWS_STOREAPP
|
||||||
private async Task ReadFile(string path, TextureLoader textureLoader) {
|
private async Task ReadFile(string path, TextureLoader textureLoader) {
|
||||||
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
|
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
|
||||||
@ -82,7 +86,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
#endif // WINDOWS_STOREAPP
|
#endif // WINDOWS_STOREAPP
|
||||||
|
|
||||||
#endif // !(UNITY)
|
#endif
|
||||||
|
|
||||||
public Atlas (TextReader reader, string dir, TextureLoader textureLoader) {
|
public Atlas (TextReader reader, string dir, TextureLoader textureLoader) {
|
||||||
Load(reader, dir, textureLoader);
|
Load(reader, dir, textureLoader);
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* 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
|
#define IS_UNITY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -180,9 +180,9 @@ namespace Spine {
|
|||||||
if (clippingArea.Count % 4 >= 2) {
|
if (clippingArea.Count % 4 >= 2) {
|
||||||
input = output;
|
input = output;
|
||||||
output = scratch;
|
output = scratch;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
input = scratch;
|
input = scratch;
|
||||||
|
}
|
||||||
|
|
||||||
input.Clear();
|
input.Clear();
|
||||||
input.Add(x1);
|
input.Add(x1);
|
||||||
@ -251,14 +251,14 @@ namespace Spine {
|
|||||||
for (int i = 0, n = output.Count - 2; i < n; i++) {
|
for (int i = 0, n = output.Count - 2; i < n; i++) {
|
||||||
originalOutput.Add(output.Items[i]);
|
originalOutput.Add(output.Items[i]);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
originalOutput.Resize(originalOutput.Count - 2);
|
originalOutput.Resize(originalOutput.Count - 2);
|
||||||
|
}
|
||||||
|
|
||||||
return clipped;
|
return clipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MakeClockwise (ExposedList<float> polygon) {
|
public static void MakeClockwise (ExposedList<float> polygon) {
|
||||||
float[] vertices = polygon.Items;
|
float[] vertices = polygon.Items;
|
||||||
int verticeslength = polygon.Count;
|
int verticeslength = polygon.Count;
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Spine {
|
namespace Spine {
|
||||||
internal class Triangulator {
|
public class Triangulator {
|
||||||
private readonly ExposedList<ExposedList<float>> convexPolygons = new ExposedList<ExposedList<float>>();
|
private readonly ExposedList<ExposedList<float>> convexPolygons = new ExposedList<ExposedList<float>>();
|
||||||
private readonly ExposedList<ExposedList<int>> convexPolygonsIndices = new ExposedList<ExposedList<int>>();
|
private readonly ExposedList<ExposedList<int>> convexPolygonsIndices = new ExposedList<ExposedList<int>>();
|
||||||
|
|
||||||
@ -84,6 +84,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
outer:
|
||||||
|
|
||||||
if (next == 0) {
|
if (next == 0) {
|
||||||
do {
|
do {
|
||||||
@ -97,7 +98,6 @@ namespace Spine {
|
|||||||
i = next;
|
i = next;
|
||||||
next = (next + 1) % vertexCount;
|
next = (next + 1) % vertexCount;
|
||||||
}
|
}
|
||||||
outer:
|
|
||||||
|
|
||||||
// Cut ear tip.
|
// Cut ear tip.
|
||||||
triangles.Add(indices[(vertexCount + i - 1) % vertexCount]);
|
triangles.Add(indices[(vertexCount + i - 1) % vertexCount]);
|
||||||
|
|||||||
@ -56,7 +56,8 @@ public class SkeletonClipping {
|
|||||||
float[] vertices = clippingPolygon.setSize(n);
|
float[] vertices = clippingPolygon.setSize(n);
|
||||||
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
|
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
|
||||||
makeClockwise(clippingPolygon);
|
makeClockwise(clippingPolygon);
|
||||||
clippingPolygons = triangulator.decompose(clippingPolygon, triangulator.triangulate(clippingPolygon));
|
ShortArray triangles = triangulator.triangulate(clippingPolygon);
|
||||||
|
clippingPolygons = triangulator.decompose(clippingPolygon, triangles);
|
||||||
for (FloatArray polygon : clippingPolygons) {
|
for (FloatArray polygon : clippingPolygons) {
|
||||||
makeClockwise(polygon);
|
makeClockwise(polygon);
|
||||||
polygon.add(polygon.items[0]);
|
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.
|
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)
|
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.
|
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
|
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.
|
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
|
#region Inspector
|
||||||
[SpineSkin]
|
[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.
|
public Material sourceMaterial; // This will be used as the basis for shader and material property settings.
|
||||||
|
|
||||||
[Header("Visor")]
|
[Header("Visor")]
|
||||||
@ -83,26 +83,25 @@ namespace Spine.Unity.Examples {
|
|||||||
// STEP 0: PREPARE SKINS
|
// 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.
|
// 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 ?? 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
|
//customSkin = customSkin ?? skeleton.UnshareSkin(true, false, skeletonAnimation.AnimationState); // use this if you are not customizing on the default skin.
|
||||||
// Next let's
|
var templateSkin = skeleton.Data.FindSkin(templateAttachmentsSkin);
|
||||||
var baseSkin = skeleton.Data.FindSkin(baseSkinName);
|
|
||||||
|
|
||||||
// STEP 1: "EQUIP" ITEMS USING SPRITES
|
// STEP 1: "EQUIP" ITEMS USING SPRITES
|
||||||
// STEP 1.1 Find the original attachment.
|
// STEP 1.1 Find the original/template attachment.
|
||||||
// Step 1.2 Get a clone of the original attachment.
|
// Step 1.2 Get a clone of the original/template attachment.
|
||||||
// Step 1.3 Apply the Sprite image to the clone.
|
// Step 1.3 Apply the Sprite image to the clone.
|
||||||
// Step 1.4 Add the remapped clone to the new custom skin.
|
// Step 1.4 Add the remapped clone to the new custom skin.
|
||||||
|
|
||||||
// Let's do this for the visor.
|
// 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.
|
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 templateAttachment = templateSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
|
||||||
Attachment newAttachment = baseAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
|
Attachment newAttachment = templateAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||||
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
|
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
|
||||||
|
|
||||||
// And now for the gun.
|
// And now for the gun.
|
||||||
int gunSlotIndex = skeleton.FindSlotIndex(gunSlot);
|
int gunSlotIndex = skeleton.FindSlotIndex(gunSlot);
|
||||||
Attachment baseGun = baseSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
|
Attachment templateGun = templateSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
|
||||||
Attachment newGun = baseGun.GetRemappedClone(gunSprite, sourceMaterial); // STEP 1.2 - 1.3
|
Attachment newGun = templateGun.GetRemappedClone(gunSprite, sourceMaterial); // STEP 1.2 - 1.3
|
||||||
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
|
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
|
||||||
|
|
||||||
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
|
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
|
||||||
@ -119,17 +118,17 @@ namespace Spine.Unity.Examples {
|
|||||||
// Under the hood, this relies on
|
// Under the hood, this relies on
|
||||||
if (repack) {
|
if (repack) {
|
||||||
var repackedSkin = new Skin("repacked skin");
|
var repackedSkin = new Skin("repacked skin");
|
||||||
repackedSkin.Append(skeleton.Data.DefaultSkin);
|
repackedSkin.Append(skeleton.Data.DefaultSkin); // Include the "default" skin. (everything outside of skin placeholders)
|
||||||
repackedSkin.Append(customSkin);
|
repackedSkin.Append(customSkin); // Include your new custom skin.
|
||||||
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas);
|
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas); // Pack all the items in the skin.
|
||||||
skeleton.SetSkin(repackedSkin);
|
skeleton.SetSkin(repackedSkin); // Assign the repacked skin to your Skeleton.
|
||||||
if (bbFollower != null) bbFollower.Initialize(true);
|
if (bbFollower != null) bbFollower.Initialize(true);
|
||||||
} else {
|
} else {
|
||||||
skeleton.SetSkin(customSkin);
|
skeleton.SetSkin(customSkin); // Just use the custom skin directly.
|
||||||
}
|
}
|
||||||
|
|
||||||
skeleton.SetSlotsToSetupPose();
|
skeleton.SetSlotsToSetupPose(); // Use the pose from setup pose.
|
||||||
skeletonAnimation.Update(0);
|
skeletonAnimation.Update(0); // Use the pose in the currently active animation.
|
||||||
|
|
||||||
Resources.UnloadUnusedAssets();
|
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:
|
m_EditorClassIdentifier:
|
||||||
atlasAssets:
|
atlasAssets:
|
||||||
- {fileID: 11400000, guid: 6f86779b1deba7c4aaec1f5895510b57, type: 2}
|
- {fileID: 11400000, guid: 6f86779b1deba7c4aaec1f5895510b57, type: 2}
|
||||||
skeletonJSON: {fileID: 4900000, guid: 95c98e245823e2243a1d8e7a1ef16c51, type: 3}
|
|
||||||
scale: 0.01
|
scale: 0.01
|
||||||
|
skeletonJSON: {fileID: 4900000, guid: 95c98e245823e2243a1d8e7a1ef16c51, type: 3}
|
||||||
fromAnimation: []
|
fromAnimation: []
|
||||||
toAnimation: []
|
toAnimation: []
|
||||||
duration: []
|
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>
|
/// <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>
|
/// 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) {
|
public static AtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Material materialPropertySource, bool initialize) {
|
||||||
if (shader == null)
|
|
||||||
shader = Shader.Find("Spine/Skeleton");
|
|
||||||
|
|
||||||
// Get atlas page names.
|
// Get atlas page names.
|
||||||
string atlasString = atlasText.text;
|
string atlasString = atlasText.text;
|
||||||
atlasString = atlasString.Replace("\r", "");
|
atlasString = atlasString.Replace("\r", "");
|
||||||
@ -84,7 +81,7 @@ namespace Spine.Unity {
|
|||||||
for (int j = 0, m = textures.Length; j < m; j++) {
|
for (int j = 0, m = textures.Length; j < m; j++) {
|
||||||
if (string.Equals(pageName, textures[j].name, System.StringComparison.OrdinalIgnoreCase)) {
|
if (string.Equals(pageName, textures[j].name, System.StringComparison.OrdinalIgnoreCase)) {
|
||||||
// Match found.
|
// Match found.
|
||||||
mat = new Material(shader);
|
mat = new Material(materialPropertySource);
|
||||||
mat.mainTexture = textures[j];
|
mat.mainTexture = textures[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -102,14 +99,12 @@ namespace Spine.Unity {
|
|||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// 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) {
|
public static AtlasAsset CreateRuntimeInstance (TextAsset atlasText, Texture2D[] textures, Shader shader, bool initialize) {
|
||||||
var shader = materialPropertySource.shader;
|
if (shader == null)
|
||||||
var oa = CreateRuntimeInstance(atlasText, textures, shader, initialize);
|
shader = Shader.Find("Spine/Skeleton");
|
||||||
|
|
||||||
foreach (var m in oa.materials) {
|
Material materialProperySource = new Material(shader);
|
||||||
m.CopyPropertiesFromMaterial(materialPropertySource);
|
var oa = CreateRuntimeInstance(atlasText, textures, materialProperySource, initialize);
|
||||||
m.shaderKeywords = materialPropertySource.shaderKeywords;
|
|
||||||
}
|
|
||||||
|
|
||||||
return oa;
|
return oa;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1213,7 +1213,7 @@ namespace Spine.Unity.Editor {
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Checking Methods
|
#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 isFixVersionRequired = false;
|
||||||
|
|
||||||
static bool CheckForValidSkeletonData (string skeletonJSONPath) {
|
static bool CheckForValidSkeletonData (string skeletonJSONPath) {
|
||||||
@ -1272,10 +1272,10 @@ namespace Spine.Unity.Editor {
|
|||||||
|
|
||||||
// Version warning
|
// Version warning
|
||||||
if (isSpineData) {
|
if (isSpineData) {
|
||||||
string runtimeVersion = compatibleVersions[0][0] + "." + compatibleVersions[0][1];
|
string runtimeVersionDebugString = compatibleVersions[0][0] + "." + compatibleVersions[0][1];
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(rawVersion)) {
|
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 {
|
} else {
|
||||||
string[] versionSplit = rawVersion.Split('.');
|
string[] versionSplit = rawVersion.Split('.');
|
||||||
bool match = false;
|
bool match = false;
|
||||||
@ -1292,7 +1292,7 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!match)
|
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
|
#region TK2D Support
|
||||||
const string SPINE_TK2D_DEFINE = "SPINE_TK2D";
|
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 () {
|
static void EnableTK2D () {
|
||||||
bool added = false;
|
bool added = false;
|
||||||
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
|
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
|
||||||
int gi = (int)group;
|
if (IsInvalidGroup(group))
|
||||||
if (gi == 15 || gi == 16 || group == BuildTargetGroup.Unknown)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||||
@ -1506,8 +1513,7 @@ namespace Spine.Unity.Editor {
|
|||||||
static void DisableTK2D () {
|
static void DisableTK2D () {
|
||||||
bool removed = false;
|
bool removed = false;
|
||||||
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
|
foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) {
|
||||||
int gi = (int)group;
|
if (IsInvalidGroup(group))
|
||||||
if (gi == 15 || gi == 16 || group == BuildTargetGroup.Unknown)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||||
|
|||||||
@ -502,16 +502,16 @@ namespace Spine.Unity {
|
|||||||
} else {
|
} else {
|
||||||
var mesh = attachment as MeshAttachment;
|
var mesh = attachment as MeshAttachment;
|
||||||
if (mesh != null) {
|
if (mesh != null) {
|
||||||
int meshVertexCount = mesh.worldVerticesLength;
|
int meshVerticesLength = mesh.worldVerticesLength;
|
||||||
if (workingVerts.Length < meshVertexCount) {
|
if (workingVerts.Length < meshVerticesLength) {
|
||||||
workingVerts = new float[meshVertexCount];
|
workingVerts = new float[meshVerticesLength];
|
||||||
this.tempVerts = workingVerts;
|
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;
|
uvs = mesh.uvs;
|
||||||
attachmentTriangleIndices = mesh.triangles;
|
attachmentTriangleIndices = mesh.triangles;
|
||||||
c.r = mesh.r; c.g = mesh.g; c.b = mesh.b; c.a = mesh.a;
|
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;
|
attachmentIndexCount = mesh.triangles.Length;
|
||||||
} else {
|
} else {
|
||||||
if (useClipping) {
|
if (useClipping) {
|
||||||
|
|||||||
@ -469,9 +469,9 @@ namespace Spine.Unity.Modules.AttachmentTools {
|
|||||||
a.SetRegion(repackedRegions[regionIndexes[i]]);
|
a.SetRegion(repackedRegions[regionIndexes[i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up
|
// // Clean up
|
||||||
foreach (var ttp in texturesToPack)
|
// foreach (var ttp in texturesToPack)
|
||||||
UnityEngine.Object.Destroy(ttp);
|
// UnityEngine.Object.Destroy(ttp);
|
||||||
|
|
||||||
t = newTexture;
|
t = newTexture;
|
||||||
m = newMaterial;
|
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);
|
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.
|
/// <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>
|
/// 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) {
|
public static Texture2D ToTexture (this AtlasRegion ar, bool applyImmediately = true, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps) {
|
||||||
|
Texture2D output;
|
||||||
|
|
||||||
|
CachedRegionTextures.TryGetValue(ar, out output);
|
||||||
|
if (output == null) {
|
||||||
Texture2D sourceTexture = ar.GetMainTexture();
|
Texture2D sourceTexture = ar.GetMainTexture();
|
||||||
Rect r = ar.GetUnityRect(sourceTexture.height);
|
Rect r = ar.GetUnityRect(sourceTexture.height);
|
||||||
int width = (int)r.width;
|
int width = (int)r.width;
|
||||||
int height = (int)r.height;
|
int height = (int)r.height;
|
||||||
Texture2D output = new Texture2D(width, height, textureFormat, mipmaps);
|
output = new Texture2D(width, height, textureFormat, mipmaps);
|
||||||
output.name = ar.name;
|
output.name = ar.name;
|
||||||
Color[] pixelBuffer = sourceTexture.GetPixels((int)r.x, (int)r.y, width, height);
|
Color[] pixelBuffer = sourceTexture.GetPixels((int)r.x, (int)r.y, width, height);
|
||||||
output.SetPixels(pixelBuffer);
|
output.SetPixels(pixelBuffer);
|
||||||
|
CachedRegionTextures.Add(ar, output);
|
||||||
|
CachedRegionTexturesList.Add(output);
|
||||||
|
|
||||||
if (applyImmediately)
|
if (applyImmediately)
|
||||||
output.Apply();
|
output.Apply();
|
||||||
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -122,6 +122,9 @@
|
|||||||
<None Include="data\coin-pro.skel">
|
<None Include="data\coin-pro.skel">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="data\goblins-mesh.atlas">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
<None Include="data\goblins.png">
|
<None Include="data\goblins.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
@ -195,9 +198,6 @@
|
|||||||
<None Include="data\coin-pro.json">
|
<None Include="data\coin-pro.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="data\goblins-mesh.atlas">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Include="data\goblins-pro.json">
|
<None Include="data\goblins-pro.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
|||||||
@ -43,6 +43,7 @@ namespace Spine {
|
|||||||
public class Example : Microsoft.Xna.Framework.Game {
|
public class Example : Microsoft.Xna.Framework.Game {
|
||||||
GraphicsDeviceManager graphics;
|
GraphicsDeviceManager graphics;
|
||||||
SkeletonRenderer skeletonRenderer;
|
SkeletonRenderer skeletonRenderer;
|
||||||
|
SkeletonDebugRenderer skeletonDebugRenderer;
|
||||||
Skeleton skeleton;
|
Skeleton skeleton;
|
||||||
Slot headSlot;
|
Slot headSlot;
|
||||||
AnimationState state;
|
AnimationState state;
|
||||||
@ -79,12 +80,17 @@ namespace Spine {
|
|||||||
skeletonRenderer.PremultipliedAlpha = false;
|
skeletonRenderer.PremultipliedAlpha = false;
|
||||||
skeletonRenderer.Effect = spineEffect;
|
skeletonRenderer.Effect = spineEffect;
|
||||||
|
|
||||||
|
skeletonDebugRenderer = new SkeletonDebugRenderer(GraphicsDevice);
|
||||||
|
skeletonDebugRenderer.DisableAll();
|
||||||
|
skeletonDebugRenderer.DrawClipping = true;
|
||||||
|
|
||||||
// String name = "spineboy-ess";
|
// String name = "spineboy-ess";
|
||||||
// String name = "goblins-pro";
|
String name = "goblins-pro";
|
||||||
// String name = "raptor-pro";
|
// String name = "raptor-pro";
|
||||||
// String name = "tank-pro";
|
// String name = "tank-pro";
|
||||||
String name = "coin-pro";
|
// String name = "coin-pro";
|
||||||
String atlasName = name.Replace("-pro", "").Replace("-ess", "");
|
String atlasName = name.Replace("-pro", "").Replace("-ess", "");
|
||||||
|
if (name == "goblins-pro") atlasName = "goblins-mesh";
|
||||||
bool binaryData = false;
|
bool binaryData = false;
|
||||||
|
|
||||||
Atlas atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice));
|
Atlas atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice));
|
||||||
@ -122,27 +128,28 @@ namespace Spine {
|
|||||||
state.Complete += Complete;
|
state.Complete += Complete;
|
||||||
state.Event += Event;
|
state.Event += Event;
|
||||||
|
|
||||||
state.SetAnimation(0, "test", false);
|
state.SetAnimation(0, "run", true);
|
||||||
TrackEntry entry = state.AddAnimation(0, "jump", false, 0);
|
TrackEntry entry = state.AddAnimation(0, "jump", false, 0);
|
||||||
entry.End += End; // Event handling for queued animations.
|
entry.End += End; // Event handling for queued animations.
|
||||||
state.AddAnimation(0, "run", true, 0);
|
state.AddAnimation(0, "run", true, 0);
|
||||||
}
|
}
|
||||||
else if (name == "raptor-pro") {
|
else if (name == "raptor-pro") {
|
||||||
state.SetAnimation(0, "walk", true);
|
state.SetAnimation(0, "walk", true);
|
||||||
state.AddAnimation(1, "gungrab", false, 2);
|
state.AddAnimation(1, "gun-grab", false, 2);
|
||||||
}
|
}
|
||||||
else if (name == "coin-pro") {
|
else if (name == "coin-pro") {
|
||||||
state.SetAnimation(0, "rotate", true);
|
state.SetAnimation(0, "rotate", true);
|
||||||
}
|
}
|
||||||
else if (name == "tank-pro") {
|
else if (name == "tank-pro") {
|
||||||
|
skeleton.X += 300;
|
||||||
state.SetAnimation(0, "drive", true);
|
state.SetAnimation(0, "drive", true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
state.SetAnimation(0, "walk", true);
|
state.SetAnimation(0, "walk", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
skeleton.X = 400 + (name == "tank-pro" ? 300: 0);
|
skeleton.X += 400;
|
||||||
skeleton.Y = GraphicsDevice.Viewport.Height;
|
skeleton.Y += GraphicsDevice.Viewport.Height;
|
||||||
skeleton.UpdateWorldTransform();
|
skeleton.UpdateWorldTransform();
|
||||||
|
|
||||||
headSlot = skeleton.FindSlot("head");
|
headSlot = skeleton.FindSlot("head");
|
||||||
@ -176,6 +183,11 @@ namespace Spine {
|
|||||||
skeletonRenderer.Draw(skeleton);
|
skeletonRenderer.Draw(skeleton);
|
||||||
skeletonRenderer.End();
|
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);
|
bounds.Update(skeleton, true);
|
||||||
MouseState mouse = Mouse.GetState();
|
MouseState mouse = Mouse.GetState();
|
||||||
if (headSlot != null) {
|
if (headSlot != null) {
|
||||||
|
|||||||
@ -111,6 +111,8 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="src\MeshBatcher.cs" />
|
<Compile Include="src\MeshBatcher.cs" />
|
||||||
<Compile Include="src\VertexEffect.cs" />
|
<Compile Include="src\VertexEffect.cs" />
|
||||||
|
<Compile Include="src\ShapeRenderer.cs" />
|
||||||
|
<Compile Include="src\SkeletonDebugRenderer.cs" />
|
||||||
<Compile Include="src\XnaTextureLoader.cs" />
|
<Compile Include="src\XnaTextureLoader.cs" />
|
||||||
<Compile Include="src\Util.cs" />
|
<Compile Include="src\Util.cs" />
|
||||||
</ItemGroup>
|
</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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user