Rewrote spine-tk2d to match spine-unity.

This commit is contained in:
NathanSweet 2013-08-03 15:44:31 +02:00
parent 288e520b25
commit 335259f954
116 changed files with 896 additions and 639 deletions

9
.gitignore vendored
View File

@ -49,6 +49,15 @@ spine-unity/*.sln
Assembly-*.csproj
Assembly-*.pidb
spine-tk2d/Assets/Spine/spine-csharp
!spine-tk2d/Assets/Spine/spine-csharp/Place spine-csharp here.txt
spine-tk2d/ProjectSettings
spine-tk2d/Temp
spine-tk2d/Library
spine-tk2d/*.sln
spine-tk2d/Assets/TK2DROOT*
spine-tk2d/Assets/-tk2d*
spine-corona/spine-lua/
!spine-corona/spine-lua/Place spine-lua here.txt

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 1fdd5b9e3e0974d40b1b149ec5a15662
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: ad07f9d157ce0a1468016aa5b6683e2a
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,61 @@
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using Spine;
public class Menus {
[MenuItem("Assets/Create/Spine SkeletonData")]
static public void CreateSkeletonData () {
CreateAsset<SkeletonDataAsset>("New SkeletonData");
}
static private void CreateAsset <T> (String path) where T : ScriptableObject {
try {
path = Path.GetDirectoryName(AssetDatabase.GetAssetPath(Selection.activeObject)) + "/" + path;
} catch (Exception) {
path = "Assets/" + path;
}
ScriptableObject asset = ScriptableObject.CreateInstance<T>();
AssetDatabase.CreateAsset(asset, path + ".asset");
AssetDatabase.SaveAssets();
EditorUtility.FocusProjectWindow();
Selection.activeObject = asset;
}
[MenuItem("GameObject/Create Other/Spine SkeletonComponent")]
static public void CreateSkeletonComponentGameObject () {
GameObject gameObject = new GameObject("New SkeletonComponent", typeof(SkeletonComponent));
EditorUtility.FocusProjectWindow();
Selection.activeObject = gameObject;
}
[MenuItem("GameObject/Create Other/Spine SkeletonAnimation")]
static public void CreateSkeletonAnimationGameObject () {
GameObject gameObject = new GameObject("New SkeletonAnimation", typeof(SkeletonAnimation));
EditorUtility.FocusProjectWindow();
Selection.activeObject = gameObject;
}
[MenuItem("Component/Spine SkeletonComponent")]
static public void CreateSkeletonComponent () {
Selection.activeGameObject.AddComponent(typeof(SkeletonComponent));
}
[MenuItem("Component/Spine SkeletonAnimation")]
static public void CreateSkeletonAnimation () {
Selection.activeGameObject.AddComponent(typeof(SkeletonAnimation));
}
[MenuItem("Component/Spine SkeletonComponent", true)]
static public bool ValidateCreateSkeletonComponent () {
return Selection.activeGameObject != null
&& Selection.activeGameObject.GetComponent(typeof(SkeletonComponent)) == null
&& Selection.activeGameObject.GetComponent(typeof(SkeletonAnimation)) == null;
}
[MenuItem("Component/Spine SkeletonAnimation", true)]
static public bool ValidateCreateSkeletonAnimation () {
return ValidateCreateSkeletonComponent();
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: b2ccbecf56104874f886da59557ff3e4
guid: 1907c00e57244fd4c8ff68eee5a58761
MonoImporter:
serializedVersion: 2
defaultReferences: []

View File

@ -0,0 +1,117 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 System;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(SkeletonAnimation))]
public class SkeletonAnimationInspector : Editor {
private SerializedProperty skeletonDataAsset, animationName, loop, useAnimationName, initialSkinName, timeScale;
void OnEnable () {
skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset");
animationName = serializedObject.FindProperty("animationName");
loop = serializedObject.FindProperty("loop");
useAnimationName = serializedObject.FindProperty("useAnimationName");
initialSkinName = serializedObject.FindProperty("initialSkinName");
timeScale = serializedObject.FindProperty("timeScale");
}
override public void OnInspectorGUI () {
serializedObject.Update();
SkeletonComponent component = (SkeletonComponent)target;
EditorGUIUtility.LookLikeInspector();
EditorGUILayout.PropertyField(skeletonDataAsset);
if (component.skeleton != null) {
// Initial skin name.
String[] skins = new String[component.skeleton.Data.Skins.Count + 1];
int skinIndex = 0;
for (int i = 0; i < skins.Length - 1; i++) {
String name = component.skeleton.Data.Skins[i].Name;
skins[i] = name;
if (name == initialSkinName.stringValue)
skinIndex = i;
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Initial Skin");
EditorGUIUtility.LookLikeControls();
skinIndex = EditorGUILayout.Popup(skinIndex, skins);
EditorGUIUtility.LookLikeInspector();
EditorGUILayout.EndHorizontal();
initialSkinName.stringValue = skinIndex == 0 ? null : skins[skinIndex];
// Animation name.
String[] animations = new String[component.skeleton.Data.Animations.Count + 2];
animations[0] = "<No Change>";
animations[1] = "<None>";
int animationIndex = useAnimationName.boolValue ? 1 : 0;
for (int i = 0; i < animations.Length - 2; i++) {
String name = component.skeleton.Data.Animations[i].Name;
animations[i + 2] = name;
if (name == animationName.stringValue)
animationIndex = i + 2;
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Animation");
EditorGUIUtility.LookLikeControls();
animationIndex = EditorGUILayout.Popup(animationIndex, animations);
EditorGUIUtility.LookLikeInspector();
EditorGUILayout.EndHorizontal();
if (animationIndex == 0) {
animationName.stringValue = null;
useAnimationName.boolValue = false;
} else if (animationIndex == 1) {
animationName.stringValue = null;
useAnimationName.boolValue = true;
} else {
animationName.stringValue = animations[animationIndex];
useAnimationName.boolValue = true;
}
}
// Animation loop.
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Loop");
loop.boolValue = EditorGUILayout.Toggle(loop.boolValue);
EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(timeScale);
if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) {
if (!Application.isPlaying) {
component.Clear();
component.Update();
}
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c36a835202febaa4ba99b918635b1920
guid: a21294688dd7a7349a5ca17241fb40e0
MonoImporter:
serializedVersion: 2
defaultReferences: []

View File

@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 System;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(SkeletonComponent))]
public class SkeletonComponentInspector : Editor {
private SerializedProperty skeletonDataAsset, initialSkinName, timeScale;
void OnEnable () {
skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset");
initialSkinName = serializedObject.FindProperty("initialSkinName");
timeScale = serializedObject.FindProperty("timeScale");
}
override public void OnInspectorGUI () {
serializedObject.Update();
SkeletonComponent component = (SkeletonComponent)target;
EditorGUIUtility.LookLikeInspector();
EditorGUILayout.PropertyField(skeletonDataAsset);
if (component.skeleton != null) {
// Initial skin name.
String[] skins = new String[component.skeleton.Data.Skins.Count + 1];
int skinIndex = 0;
for (int i = 0; i < skins.Length - 1; i++) {
String name = component.skeleton.Data.Skins[i].Name;
skins[i] = name;
if (name == initialSkinName.stringValue)
skinIndex = i;
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Initial Skin");
EditorGUIUtility.LookLikeControls();
skinIndex = EditorGUILayout.Popup(skinIndex, skins);
EditorGUIUtility.LookLikeInspector();
EditorGUILayout.EndHorizontal();
initialSkinName.stringValue = skinIndex == 0 ? null : skins[skinIndex];
}
EditorGUILayout.PropertyField(timeScale);
if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) {
if (!Application.isPlaying) {
component.Clear();
component.Update();
}
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c62fe2307a465b14793b8fdde54fdbe4
guid: dbb89dadcac8d6b48869aeb81b0ae88f
MonoImporter:
serializedVersion: 2
defaultReferences: []

View File

@ -0,0 +1,101 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 System;
using UnityEditor;
using UnityEngine;
using Spine;
[CustomEditor(typeof(SkeletonDataAsset))]
public class SkeletonDataAssetInspector : Editor {
private SerializedProperty spriteCollection, skeletonJSON, scale, fromAnimation, toAnimation, duration;
private bool showAnimationStateData = true;
void OnEnable () {
spriteCollection = serializedObject.FindProperty("spriteCollection");
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
scale = serializedObject.FindProperty("scale");
fromAnimation = serializedObject.FindProperty("fromAnimation");
toAnimation = serializedObject.FindProperty("toAnimation");
duration = serializedObject.FindProperty("duration");
}
override public void OnInspectorGUI () {
serializedObject.Update();
SkeletonDataAsset asset = (SkeletonDataAsset)target;
EditorGUIUtility.LookLikeInspector();
tk2dSpriteCollection sprites = EditorGUILayout.ObjectField("Sprite Collection", asset.spriteCollection, typeof(tk2dSpriteCollection), false) as tk2dSpriteCollection;
if (sprites != null)
spriteCollection.objectReferenceValue = sprites.spriteCollection;
EditorGUILayout.PropertyField(skeletonJSON);
EditorGUILayout.PropertyField(scale);
SkeletonData skeletonData = asset.GetSkeletonData(true);
if (skeletonData != null) {
showAnimationStateData = EditorGUILayout.Foldout(showAnimationStateData, "Animation State Data");
if (showAnimationStateData) {
// Animation names.
String[] animations = new String[skeletonData.Animations.Count];
for (int i = 0; i < animations.Length; i++)
animations[i] = skeletonData.Animations[i].Name;
for (int i = 0; i < fromAnimation.arraySize; i++) {
SerializedProperty from = fromAnimation.GetArrayElementAtIndex(i);
SerializedProperty to = toAnimation.GetArrayElementAtIndex(i);
SerializedProperty durationProp = duration.GetArrayElementAtIndex(i);
EditorGUILayout.BeginHorizontal();
from.stringValue = animations[EditorGUILayout.Popup(Math.Max(Array.IndexOf(animations, from.stringValue), 0), animations)];
to.stringValue = animations[EditorGUILayout.Popup(Math.Max(Array.IndexOf(animations, to.stringValue), 0), animations)];
durationProp.floatValue = EditorGUILayout.FloatField(durationProp.floatValue);
if (GUILayout.Button("Delete")) {
duration.DeleteArrayElementAtIndex(i);
toAnimation.DeleteArrayElementAtIndex(i);
fromAnimation.DeleteArrayElementAtIndex(i);
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.Space();
if (GUILayout.Button("Add Mix")) {
duration.arraySize++;
toAnimation.arraySize++;
fromAnimation.arraySize++;
}
EditorGUILayout.Space();
EditorGUILayout.EndHorizontal();
}
}
if (!Application.isPlaying) {
if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) {
asset.Clear();
}
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 9b8ea7c2b29e5814eb0b4b692b828869
guid: cffb121e3cd80644d84c585b9c7448e8
MonoImporter:
serializedVersion: 2
defaultReferences: []

View File

@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using Spine;
/** Extends SkeletonComponent to apply an animation. */
[ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class SkeletonAnimation : SkeletonComponent {
public bool useAnimationName;
public String animationName;
public bool loop;
public Spine.AnimationState state;
override public void Initialize () {
base.Initialize(); // Call overridden method to initialize the skeleton.
state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());
}
override public void UpdateSkeleton () {
if (useAnimationName) {
// Keep AnimationState in sync with animationName and loop fields.
if (animationName == null || animationName.Length == 0) {
if (state.Animation != null)
state.ClearAnimation();
} else if (state.Animation == null || animationName != state.Animation.Name) {
Spine.Animation animation = skeleton.Data.FindAnimation(animationName);
if (animation != null)
state.SetAnimation(animation, loop);
}
state.Loop = loop;
}
// Apply the animation.
state.Update(Time.deltaTime * timeScale);
state.Apply(skeleton);
// Call overridden method to call skeleton Update and UpdateWorldTransform.
base.UpdateSkeleton();
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 41133952e6d5fe04ca82a24ed4c02990
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,252 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using Spine;
/** Renders a skeleton. Extend to apply animations, get bones and manipulate them, etc. */
[ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class SkeletonComponent : MonoBehaviour {
public SkeletonDataAsset skeletonDataAsset;
public Skeleton skeleton;
public String initialSkinName;
public float timeScale = 1;
private Mesh mesh;
private int lastVertexCount;
private Vector3[] vertices;
private Color32[] colors;
private Vector2[] uvs;
private float[] vertexPositions = new float[8];
private List<Material> submeshMaterials = new List<Material>();
private List<int[]> submeshIndexes = new List<int[]>();
private Material[] sharedMaterials = new Material[0];
public virtual void Clear () {
GetComponent<MeshFilter>().mesh = null;
DestroyImmediate(mesh);
mesh = null;
renderer.sharedMaterial = null;
skeleton = null;
}
public virtual void Initialize () {
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
mesh.name = "Skeleton Mesh";
mesh.hideFlags = HideFlags.HideAndDontSave;
mesh.MarkDynamic();
// BOZO
//renderer.sharedMaterial = skeletonDataAsset.atlasAsset.material;
vertices = new Vector3[0];
skeleton = new Skeleton(skeletonDataAsset.GetSkeletonData(false));
if (initialSkinName != null && initialSkinName.Length > 0) {
skeleton.SetSkin(initialSkinName);
skeleton.SetSlotsToSetupPose();
}
}
public virtual void UpdateSkeleton () {
skeleton.Update(Time.deltaTime * timeScale);
skeleton.UpdateWorldTransform();
}
public virtual void Update () {
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false);
// Clear fields if missing information to render.
if (skeletonDataAsset == null || skeletonData == null) {
Clear();
return;
}
// Initialize fields.
if (skeleton == null || skeleton.Data != skeletonData)
Initialize();
UpdateSkeleton();
// Count quads and submeshes.
int quadCount = 0, submeshQuadCount = 0;
Material lastMaterial = null;
submeshMaterials.Clear();
List<Slot> drawOrder = skeleton.DrawOrder;
for (int i = 0, n = drawOrder.Count; i < n; i++) {
RegionAttachment regionAttachment = drawOrder[i].Attachment as RegionAttachment;
if (regionAttachment == null)
continue;
// Add submesh when material changes.
Material material = (Material)regionAttachment.RendererObject;
if (lastMaterial != material && lastMaterial != null) {
addSubmesh(lastMaterial, quadCount, submeshQuadCount, false);
submeshQuadCount = 0;
}
lastMaterial = material;
quadCount++;
submeshQuadCount++;
}
addSubmesh(lastMaterial, quadCount, submeshQuadCount, false);
// Set materials.
if (submeshMaterials.Count == sharedMaterials.Length)
submeshMaterials.CopyTo(sharedMaterials);
else
sharedMaterials = submeshMaterials.ToArray();
renderer.sharedMaterials = sharedMaterials;
// Ensure mesh data is the right size.
Mesh mesh = this.mesh;
Vector3[] vertices = this.vertices;
int vertexCount = quadCount * 4;
bool newTriangles = vertexCount > vertices.Length;
if (newTriangles) {
// Not enough vertices, increase size.
this.vertices = vertices = new Vector3[vertexCount];
this.colors = new Color32[vertexCount];
this.uvs = new Vector2[vertexCount];
mesh.Clear();
} else {
// Too many vertices, zero the extra.
Vector3 zero = new Vector3(0, 0, 0);
for (int i = vertexCount, n = lastVertexCount; i < n; i++)
vertices[i] = zero;
}
lastVertexCount = vertexCount;
// Setup mesh.
float[] vertexPositions = this.vertexPositions;
Vector2[] uvs = this.uvs;
Color32[] colors = this.colors;
int vertexIndex = 0;
Color32 color = new Color32();
for (int i = 0, n = drawOrder.Count; i < n; i++) {
Slot slot = drawOrder[i];
RegionAttachment regionAttachment = slot.Attachment as RegionAttachment;
if (regionAttachment == null)
continue;
regionAttachment.ComputeVertices(skeleton.X, skeleton.Y, slot.Bone, vertexPositions);
vertices[vertexIndex] = new Vector3(vertexPositions[RegionAttachment.X1], vertexPositions[RegionAttachment.Y1], 0);
vertices[vertexIndex + 1] = new Vector3(vertexPositions[RegionAttachment.X4], vertexPositions[RegionAttachment.Y4], 0);
vertices[vertexIndex + 2] = new Vector3(vertexPositions[RegionAttachment.X2], vertexPositions[RegionAttachment.Y2], 0);
vertices[vertexIndex + 3] = new Vector3(vertexPositions[RegionAttachment.X3], vertexPositions[RegionAttachment.Y3], 0);
color.a = (byte)(skeleton.A * slot.A * 255);
color.r = (byte)(skeleton.R * slot.R * color.a);
color.g = (byte)(skeleton.G * slot.G * color.a);
color.b = (byte)(skeleton.B * slot.B * color.a);
colors[vertexIndex] = color;
colors[vertexIndex + 1] = color;
colors[vertexIndex + 2] = color;
colors[vertexIndex + 3] = color;
float[] regionUVs = regionAttachment.UVs;
uvs[vertexIndex] = new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1]);
uvs[vertexIndex + 1] = new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4]);
uvs[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2]);
uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]);
vertexIndex += 4;
}
mesh.vertices = vertices;
mesh.colors32 = colors;
mesh.uv = uvs;
mesh.subMeshCount = submeshMaterials.Count;
for (int i = 0; i < mesh.subMeshCount; ++i)
mesh.SetTriangles(submeshIndexes[i], i);
}
/** Adds a material. Adds submesh indexes if existing indexes aren't sufficient. */
private void addSubmesh (Material material, int endQuadCount, int submeshQuadCount, bool exact) {
int submeshIndex = submeshMaterials.Count;
submeshMaterials.Add(material);
// Return if the existing submesh is big enough.
int indexCount = submeshQuadCount * 6;
if (submeshIndexes.Count > submeshIndex) {
if (exact) {
if (submeshIndexes[submeshIndex].Length == indexCount)
return;
} else {
if (submeshIndexes[submeshIndex].Length >= indexCount)
return;
}
} else
submeshIndexes.Add(null);
int vertexIndex = (endQuadCount - submeshQuadCount) * 4;
int[] indexes = new int[indexCount];
for (int i = 0; i < indexCount; i += 6, vertexIndex += 4) {
indexes[i] = vertexIndex;
indexes[i + 1] = vertexIndex + 2;
indexes[i + 2] = vertexIndex + 1;
indexes[i + 3] = vertexIndex + 2;
indexes[i + 4] = vertexIndex + 3;
indexes[i + 5] = vertexIndex + 1;
}
submeshIndexes[submeshIndex] = indexes;
}
public virtual void OnEnable () {
Update();
}
#if UNITY_EDITOR
public virtual void OnDisable () {
Clear();
}
#endif
public virtual void Reset () {
Update();
}
#if UNITY_EDITOR
void OnDrawGizmos() {
Vector3 gizmosCenter = new Vector3();
Vector3 gizmosSize = new Vector3();
Vector3 min = new Vector3(float.MaxValue, float.MaxValue, 0f);
Vector3 max = new Vector3(float.MinValue, float.MinValue, 0f);
foreach (Vector3 vert in vertices) {
min = Vector3.Min (min, vert);
max = Vector3.Max (max, vert);
}
float width = max.x - min.x;
float height = max.y - min.y;
gizmosCenter = new Vector3(min.x + (width / 2f), min.y + (height / 2f), 0f);
gizmosSize = new Vector3(width, height, 1f);
Gizmos.color = Color.clear;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawCube(gizmosCenter, gizmosSize);
}
#endif
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9da572b571dc33444bd6622951ef62ba
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,90 @@
/*******************************************************************************
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 System;
using System.IO;
using UnityEngine;
using Spine;
public class SkeletonDataAsset : ScriptableObject {
public tk2dSpriteCollectionData spriteCollection;
public TextAsset skeletonJSON;
public float scale = 1;
public String[] fromAnimation;
public String[] toAnimation;
public float[] duration;
private SkeletonData skeletonData;
private AnimationStateData stateData;
public void Clear () {
skeletonData = null;
stateData = null;
}
public SkeletonData GetSkeletonData (bool quiet) {
if (spriteCollection == null) {
if (!quiet)
Debug.LogWarning("Sprite collection not set for skeleton data asset: " + name, this);
Clear();
return null;
}
if (skeletonJSON == null) {
if (!quiet)
Debug.LogWarning("Skeleton JSON file not set for skeleton data asset: " + name, this);
Clear();
return null;
}
if (skeletonData != null)
return skeletonData;
SkeletonJson json = new SkeletonJson(new SpriteCollectionAttachmentLoader(spriteCollection));
json.Scale = 1.0f / (spriteCollection.invOrthoSize * spriteCollection.halfTargetHeight) * scale;
try {
skeletonData = json.ReadSkeletonData(new StringReader(skeletonJSON.text));
} catch (Exception ex) {
Debug.Log("Error reading skeleton JSON file for skeleton data asset: " + name + "\n" +
ex.Message + "\n" + ex.StackTrace, this);
return null;
}
stateData = new AnimationStateData(skeletonData);
for (int i = 0, n = fromAnimation.Length; i < n; i++) {
if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0)
continue;
stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
}
return skeletonData;
}
public AnimationStateData GetAnimationStateData () {
if (stateData != null)
return stateData;
GetSkeletonData(false);
return stateData;
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1bdfe79e336474848808de1467defd7f
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -4,26 +4,32 @@ using Spine;
// TODO: handle TPackerCW flip mode (probably not swap uv horizontaly)
public class tk2dSpineAttachmentLoader : AttachmentLoader {
public class SpriteCollectionAttachmentLoader : AttachmentLoader {
private tk2dSpriteCollectionData sprites;
public tk2dSpineAttachmentLoader(tk2dSpriteCollectionData sprites) {
if (sprites == null) throw new ArgumentNullException("sprites cannot be null.");
public SpriteCollectionAttachmentLoader (tk2dSpriteCollectionData sprites) {
if (sprites == null)
throw new ArgumentNullException("sprites cannot be null.");
this.sprites = sprites;
}
public Attachment NewAttachment(Skin skin, AttachmentType type, String name) {
if (type != AttachmentType.region) throw new Exception("Unknown attachment type: " + type);
public Attachment NewAttachment (Skin skin, AttachmentType type, String name) {
if (type != AttachmentType.region)
throw new Exception("Unknown attachment type: " + type);
// Strip folder names.
int index = name.LastIndexOfAny(new char[] {'/', '\\'});
if (index != -1) name = name.Substring(index + 1);
if (index != -1)
name = name.Substring(index + 1);
tk2dSpriteDefinition def = sprites.GetSpriteDefinition(name);
if (def == null) throw new Exception("Sprite not found in atlas: " + name + " (" + type + ")");
if (def.complexGeometry) throw new NotImplementedException("Complex geometry is not supported: " + name + " (" + type + ")");
if (def.flipped == tk2dSpriteDefinition.FlipMode.TPackerCW) throw new NotImplementedException("Only 2D Toolkit atlases are supported: " + name + " (" + type + ")");
if (def == null)
throw new Exception("Sprite not found in atlas: " + name + " (" + type + ")");
if (def.complexGeometry)
throw new NotImplementedException("Complex geometry is not supported: " + name + " (" + type + ")");
if (def.flipped == tk2dSpriteDefinition.FlipMode.TPackerCW)
throw new NotImplementedException("Only 2D Toolkit atlases are supported: " + name + " (" + type + ")");
RegionAttachment attachment = new RegionAttachment(name);
@ -62,6 +68,8 @@ public class tk2dSpineAttachmentLoader : AttachmentLoader {
float y1 = def.boundsData[0].y - def.boundsData[1].y / 2;
attachment.RegionOffsetY = (int)((y1 - y0) / def.texelSize.y);
attachment.RendererObject = def.material;
return attachment;
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2ad5a031e905ab0469fe2e19ff1b94ee
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: afc6035066a4eb4478f706aa211ca644
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: ddc30294e8bdeb0469c854ccf66824fc
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: aafe437f17003ec449c178c2c329d221
folderAsset: yes
DefaultImporter:
userData:

View File

@ -1,13 +1,11 @@
using UnityEngine;
using System.Collections;
/*
*/
public class tk2dSpineboy : MonoBehaviour {
private tk2dSpineAnimation skeleton;
public class Spineboy : MonoBehaviour {
private SkeletonAnimation skeleton;
void Start() {
skeleton = GetComponent<tk2dSpineAnimation>();
skeleton = GetComponent<SkeletonAnimation>();
}
void LateUpdate() {

View File

@ -1,4 +1,5 @@
fileFormatVersion: 2
guid: ecf18700fc84ae94ca3cfa6d301b50c0
folderAsset: yes
DefaultImporter:
userData:

View File

@ -1,4 +1,4 @@
fileFormatVersion: 2
guid: 75ba18a107160134091f702a9e446567
guid: 4cd6560d5de81b240b7e7d9beaa3e2f0
NativeFormatImporter:
userData:

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 1
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: -1
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 1
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: -1
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 1
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: -1
buildTargetSettings: []
userData:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 59b6b8248068c5c48a322d8b794e27ba
folderAsset: yes
DefaultImporter:
userData:

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -30,6 +30,7 @@ TextureImporter:
nPOTScale: 0
lightmap: 0
compressionQuality: 50
alphaIsTransparency: 0
textureType: 5
buildTargetSettings: []
userData:

View File

@ -1,4 +1,4 @@
fileFormatVersion: 2
guid: a6669a1e8d1cb5c45b165fe92714942b
guid: 3e1554ca46e91194fb8d9ead0b21f6f7
DefaultImporter:
userData:

View File

@ -1,44 +0,0 @@
using UnityEngine;
using Spine;
// TODO: add events in animation component
[RequireComponent(typeof(tk2dSpineSkeleton))]
public class tk2dSpineAnimation : MonoBehaviour {
public string animationName;
public bool loop;
public float animationSpeed = 1;
public Spine.AnimationState state;
private tk2dSpineSkeleton cachedSpineSkeleton;
void Start () {
cachedSpineSkeleton = GetComponent<tk2dSpineSkeleton>();
state = new Spine.AnimationState(cachedSpineSkeleton.skeletonDataAsset.GetAnimationStateData());
}
void Update () {
UpdateAnimation();
}
private void UpdateAnimation() {
// Check if we need to stop current animation
if (state.Animation != null && animationName == null) {
state.ClearAnimation();
}
// Check for different animation name or animation end
else if (state.Animation == null || animationName != state.Animation.Name) {
Spine.Animation animation = cachedSpineSkeleton.skeleton.Data.FindAnimation(animationName);
if (animation != null) state.SetAnimation(animation,loop);
}
state.Loop = loop;
// Update animation
cachedSpineSkeleton.skeleton.Update(Time.deltaTime * animationSpeed);
state.Update(Time.deltaTime * animationSpeed);
state.Apply(cachedSpineSkeleton.skeleton);
}
}

View File

@ -1,237 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
using Spine;
[ExecuteInEditMode]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class tk2dSpineSkeleton : MonoBehaviour, tk2dRuntime.ISpriteCollectionForceBuild {
public tk2dSpineSkeletonDataAsset skeletonDataAsset;
public Skeleton skeleton;
private Mesh mesh;
private Vector3[] vertices;
private Color32[] colors;
private Vector2[] uvs;
private int cachedQuadCount;
private float[] vertexPositions;
private List<Material> submeshMaterials = new List<Material>();
private List<int[]> submeshIndices = new List<int[]>();
void Awake() {
vertexPositions = new float[8];
submeshMaterials = new List<Material>();
submeshIndices = new List<int[]>();
}
void Start () {
Initialize();
}
void Update () {
SkeletonData skeletonData = skeletonDataAsset == null ? null : skeletonDataAsset.GetSkeletonData();
if (skeletonData == null) {
Clear();
return;
}
if (skeleton == null || skeleton.Data != skeletonData) Initialize();
skeleton.UpdateWorldTransform();
UpdateCache();
UpdateMesh();
}
private void Clear() {
GetComponent<MeshFilter>().mesh = null;
DestroyImmediate(mesh);
mesh = null;
skeleton = null;
}
private void Initialize() {
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
mesh.name = "tk2dSkeleton Mesh";
mesh.hideFlags = HideFlags.HideAndDontSave;
if(skeletonDataAsset != null) {
skeleton = new Skeleton(skeletonDataAsset.GetSkeletonData());
}
}
private void UpdateMesh() {
int quadIndex = 0;
int drawCount = skeleton.DrawOrder.Count;
Color32 color = new Color32();
for (int i = 0; i < drawCount; i++) {
Slot slot = skeleton.DrawOrder[i];
Attachment attachment = slot.Attachment;
if (attachment is RegionAttachment) {
RegionAttachment regionAttachment = attachment as RegionAttachment;
regionAttachment.ComputeVertices(skeleton.X, skeleton.Y, slot.Bone, vertexPositions);
int vertexIndex = quadIndex * 4;
vertices[vertexIndex + 0] = new Vector3(vertexPositions[RegionAttachment.X1],vertexPositions[RegionAttachment.Y1],0);
vertices[vertexIndex + 1] = new Vector3(vertexPositions[RegionAttachment.X4],vertexPositions[RegionAttachment.Y4],0);
vertices[vertexIndex + 2] = new Vector3(vertexPositions[RegionAttachment.X2],vertexPositions[RegionAttachment.Y2],0);
vertices[vertexIndex + 3] = new Vector3(vertexPositions[RegionAttachment.X3],vertexPositions[RegionAttachment.Y3],0);
float[] regionUVs = regionAttachment.UVs;
uvs[vertexIndex + 0] = new Vector2(regionUVs[RegionAttachment.X1],regionUVs[RegionAttachment.Y1]);
uvs[vertexIndex + 1] = new Vector2(regionUVs[RegionAttachment.X4],regionUVs[RegionAttachment.Y4]);
uvs[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.X2],regionUVs[RegionAttachment.Y2]);
uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3],regionUVs[RegionAttachment.Y3]);
color.a = (byte)(skeleton.A * slot.A * 255);
color.r = (byte)(skeleton.R * slot.R * color.a);
color.g = (byte)(skeleton.G * slot.G * color.a);
color.b = (byte)(skeleton.B * slot.B * color.a);
colors[vertexIndex] = color;
colors[vertexIndex + 1] = color;
colors[vertexIndex + 2] = color;
colors[vertexIndex + 3] = color;
quadIndex++;
}
}
mesh.vertices = vertices;
mesh.colors32 = colors;
mesh.uv = uvs;
if (skeletonDataAsset.normalGenerationMode != tk2dSpriteCollection.NormalGenerationMode.None) {
mesh.RecalculateNormals();
if (skeletonDataAsset.normalGenerationMode == tk2dSpriteCollection.NormalGenerationMode.NormalsAndTangents) {
Vector4[] tangents = new Vector4[mesh.normals.Length];
for (int i = 0; i < tangents.Length; i++) {
tangents[i] = new Vector4(1, 0, 0, 1);
}
mesh.tangents = tangents;
}
}
#if UNITY_EDITOR
UpdateEditorGizmo();
#endif
}
private void UpdateCache() {
int quadCount = 0;
int drawCount = skeleton.DrawOrder.Count;
for (int i = 0; i < drawCount; i++) {
Attachment attachment = skeleton.DrawOrder[i].Attachment;
if (attachment is RegionAttachment) quadCount++;
}
#if UNITY_EDITOR
if (mesh.subMeshCount == submeshIndices.Count)
#endif
if (quadCount == cachedQuadCount) return;
cachedQuadCount = quadCount;
vertices = new Vector3[quadCount * 4];
uvs = new Vector2[quadCount * 4];
colors = new Color32[quadCount * 4];
UpdateSubmeshCache();
mesh.Clear();
mesh.vertices = vertices;
mesh.colors32 = colors;
mesh.uv = uvs;
mesh.subMeshCount = submeshIndices.Count;
for(int i = 0; i < mesh.subMeshCount; ++i) {
mesh.SetTriangles(submeshIndices[i],i);
}
}
private void UpdateSubmeshCache() {
submeshIndices.Clear();
submeshMaterials.Clear();
Material oldMaterial = null;
List<int> currentSubmesh = new List<int>();
int quadIndex = 0;
int drawCount = skeleton.DrawOrder.Count;
for (int i = 0; i < drawCount; i++) {
Attachment attachment = skeleton.DrawOrder[i].Attachment;
if (!(attachment is RegionAttachment)) continue;
Material currentMaterial = skeletonDataAsset.spritesData.GetSpriteDefinition(attachment.Name).material;
if (oldMaterial == null) oldMaterial = currentMaterial;
if (oldMaterial != currentMaterial) {
submeshIndices.Add(currentSubmesh.ToArray());
submeshMaterials.Add(oldMaterial);
currentSubmesh.Clear();
}
int vertexIndex = quadIndex * 4;
currentSubmesh.Add(vertexIndex);
currentSubmesh.Add(vertexIndex + 2);
currentSubmesh.Add(vertexIndex + 1);
currentSubmesh.Add(vertexIndex + 2);
currentSubmesh.Add(vertexIndex + 3);
currentSubmesh.Add(vertexIndex + 1);
quadIndex++;
oldMaterial = currentMaterial;
}
submeshIndices.Add(currentSubmesh.ToArray());
submeshMaterials.Add(oldMaterial);
renderer.sharedMaterials = submeshMaterials.ToArray();
}
public bool UsesSpriteCollection(tk2dSpriteCollectionData spriteCollection) {
return skeletonDataAsset.spritesData == spriteCollection;
}
public void ForceBuild() {
skeletonDataAsset.ForceUpdate();
skeleton = new Skeleton(skeletonDataAsset.GetSkeletonData());
UpdateSubmeshCache();
UpdateMesh();
}
#region Unity Editor
#if UNITY_EDITOR
Vector3 gizmosCenter = new Vector3();
Vector3 gizmosSize = new Vector3();
Vector3 min = new Vector3(float.MaxValue, float.MaxValue, 0f);
Vector3 max = new Vector3(float.MinValue, float.MinValue, 0f);
void UpdateEditorGizmo() {
//determine the minimums and maximums
foreach (Vector3 vert in vertices) {
min = Vector3.Min(min, vert);
max = Vector3.Max(max, vert);
}
float width = max.x - min.x;
float height = max.y - min.y;
gizmosCenter = new Vector3(min.x + (width / 2f), min.y + (height / 2f), 0f);
gizmosSize = new Vector3(width, height, 1f);
}
void OnDrawGizmos() {
Gizmos.color = Color.clear;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawCube(gizmosCenter, gizmosSize);
}
#endif
#endregion
}

View File

@ -1,64 +0,0 @@
using System;
using System.IO;
using UnityEngine;
using Spine;
public class tk2dSpineSkeletonDataAsset : ScriptableObject {
public tk2dSpriteCollectionData spritesData;
public tk2dSpriteCollection.NormalGenerationMode normalGenerationMode = tk2dSpriteCollection.NormalGenerationMode.None;
public TextAsset skeletonJSON;
public string[] fromAnimation;
public string[] toAnimation;
public float[] duration;
private SkeletonData skeletonData;
private AnimationStateData stateData;
public SkeletonData GetSkeletonData() {
if (skeletonData != null) return skeletonData;
MakeSkeletonAndAnimationData();
return skeletonData;
}
public AnimationStateData GetAnimationStateData () {
if (stateData != null) return stateData;
MakeSkeletonAndAnimationData();
return stateData;
}
private void MakeSkeletonAndAnimationData() {
if (spritesData == null) {
Debug.LogWarning("Sprite collection not set for skeleton data asset: " + name,this);
return;
}
if (skeletonJSON == null) {
Debug.LogWarning("Skeleton JSON file not set for skeleton data asset: " + name,this);
return;
}
SkeletonJson json = new SkeletonJson(new tk2dSpineAttachmentLoader(spritesData));
json.Scale = 1.0f / (spritesData.invOrthoSize * spritesData.halfTargetHeight);
try {
skeletonData = json.ReadSkeletonData(new StringReader(skeletonJSON.text));
} catch (Exception ex) {
Debug.Log("Error reading skeleton JSON file for skeleton data asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace,this);
return;
}
stateData = new AnimationStateData(skeletonData);
for (int i = 0, n = fromAnimation.Length; i < n; i++) {
if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0) continue;
stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
}
}
public void ForceUpdate() {
MakeSkeletonAndAnimationData();
}
}

View File

@ -1,74 +0,0 @@
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using Spine;
/*
*/
public class tk2dSpineMenus {
/*
*/
[MenuItem("Assets/Create/tk2d/Spine Skeleton Data")]
static public void CreateSkeletonData() {
string path = "";
try {
path = Path.GetDirectoryName(AssetDatabase.GetAssetPath(Selection.activeObject)) + "/";
} catch (Exception) {
path = "Assets/";
}
ScriptableObject asset = ScriptableObject.CreateInstance<tk2dSpineSkeletonDataAsset>();
AssetDatabase.CreateAsset(asset,path + "New Spine Skeleton Data.asset");
AssetDatabase.SaveAssets();
EditorUtility.FocusProjectWindow();
Selection.activeObject = asset;
}
/*
*/
[MenuItem("GameObject/Create Other/tk2d/Spine Skeleton")]
static public void CreateSkeletonGameObject() {
GameObject gameObject = new GameObject("New tk2d Spine Skeleton",typeof(tk2dSpineSkeleton));
EditorUtility.FocusProjectWindow();
Selection.activeObject = gameObject;
}
/*
*/
[MenuItem("GameObject/Create Other/tk2d/Spine Animated Skeleton")]
static public void CreateAnimatedSkeletonGameObject() {
GameObject gameObject = new GameObject("New tk2d Spine Animated Skeleton",typeof(tk2dSpineAnimation));
EditorUtility.FocusProjectWindow();
Selection.activeObject = gameObject;
}
/*
*/
[MenuItem("Component/2D Toolkit/Spine Skeleton")]
static public void CreateSkeletonComponent() {
Selection.activeGameObject.AddComponent(typeof(tk2dSpineSkeleton));
}
/*
*/
[MenuItem("Component/2d Toolkit/Spine Skeleton",true)]
static public bool ValidateCreateSkeletonComponent() {
return Selection.activeGameObject != null && Selection.activeGameObject.GetComponent(typeof(tk2dSpineSkeleton)) == null;
}
/*
*/
[MenuItem("Component/2D Toolkit/Spine Animation")]
static public void CreateAnimationComponent() {
Selection.activeGameObject.AddComponent(typeof(tk2dSpineAnimation));
}
/*
*/
[MenuItem("Component/2d Toolkit/Spine Animation",true)]
static public bool ValidateCreateAnimationComponent() {
return Selection.activeGameObject != null && Selection.activeGameObject.GetComponent(typeof(tk2dSpineAnimation)) == null;
}
}

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 5673189c5c1030b4783c8945f5a5f52e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -1,113 +0,0 @@
using System;
using UnityEditor;
using UnityEngine;
using Spine;
/*
*/
[CustomEditor(typeof(tk2dSpineSkeletonDataAsset))]
public class tk2dSpineSkeletonDataAssetInspector : Editor {
/*
*/
private SerializedProperty skeletonJSON;
private SerializedProperty fromAnimation;
private SerializedProperty toAnimation;
private SerializedProperty duration;
private bool showAnimationStateData = true;
private tk2dSpriteCollection sprites;
/*
*/
void OnEnable () {
tk2dSpineSkeletonDataAsset skeletonDataAsset = target as tk2dSpineSkeletonDataAsset;
if (skeletonDataAsset != null) {
tk2dSpriteCollectionData spritesData = skeletonDataAsset.spritesData;
if (spritesData != null) {
sprites = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath(spritesData.spriteCollectionGUID), typeof(tk2dSpriteCollection) ) as tk2dSpriteCollection;
}
}
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
fromAnimation = serializedObject.FindProperty("fromAnimation");
toAnimation = serializedObject.FindProperty("toAnimation");
duration = serializedObject.FindProperty("duration");
}
/*
*/
public override void OnInspectorGUI () {
serializedObject.Update();
tk2dSpineSkeletonDataAsset asset = target as tk2dSpineSkeletonDataAsset;
EditorGUIUtility.LookLikeInspector();
sprites = EditorGUILayout.ObjectField("Sprites", sprites, typeof(tk2dSpriteCollection), false) as tk2dSpriteCollection;
if (sprites != null) {
SerializedProperty spritesData = serializedObject.FindProperty("spritesData");
spritesData.objectReferenceValue = sprites.spriteCollection;
SerializedProperty normalGenerationMode = serializedObject.FindProperty("normalGenerationMode");
normalGenerationMode.enumValueIndex = (int)sprites.normalGenerationMode;
} else {
SerializedProperty spritesData = serializedObject.FindProperty("spritesData");
spritesData.objectReferenceValue = null;
SerializedProperty normalGenerationMode = serializedObject.FindProperty("normalGenerationMode");
normalGenerationMode.enumValueIndex = (int)tk2dSpriteCollection.NormalGenerationMode.None;
}
EditorGUILayout.PropertyField(skeletonJSON);
SkeletonData skeletonData = asset.GetSkeletonData();
if(skeletonData != null) {
showAnimationStateData = EditorGUILayout.Foldout(showAnimationStateData,"Animation State Data");
if(showAnimationStateData) {
String[] animations = new String[skeletonData.Animations.Count];
for (int i = 0; i < animations.Length; i++) {
animations[i] = skeletonData.Animations[i].Name;
}
for(int i = 0; i < fromAnimation.arraySize; i++) {
SerializedProperty from = fromAnimation.GetArrayElementAtIndex(i);
SerializedProperty to = toAnimation.GetArrayElementAtIndex(i);
SerializedProperty durationProp = duration.GetArrayElementAtIndex(i);
EditorGUILayout.BeginHorizontal();
from.stringValue = animations[EditorGUILayout.Popup(Math.Max(Array.IndexOf(animations,from.stringValue),0),animations)];
to.stringValue = animations[EditorGUILayout.Popup(Math.Max(Array.IndexOf(animations,to.stringValue),0),animations)];
durationProp.floatValue = EditorGUILayout.FloatField(durationProp.floatValue);
if(GUILayout.Button("Delete")) {
duration.DeleteArrayElementAtIndex(i);
toAnimation.DeleteArrayElementAtIndex(i);
fromAnimation.DeleteArrayElementAtIndex(i);
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.Space();
if(GUILayout.Button("Add Mix")) {
duration.arraySize++;
toAnimation.arraySize++;
fromAnimation.arraySize++;
}
EditorGUILayout.Space();
EditorGUILayout.EndHorizontal();
}
}
serializedObject.ApplyModifiedProperties();
}
}

Some files were not shown because too many files have changed in this diff Show More