Răsfoiți Sursa

SpineUnity Import process enhancements
scaled down examples to match standard Unity practices
added spineboy movement example

Fenrisul 11 ani în urmă
părinte
comite
7f700eeb93
38 a modificat fișierele cu 1573 adăugiri și 5 ștergeri
  1. 5 0
      spine-unity/Assets/Gizmos.meta
  2. BIN
      spine-unity/Assets/Gizmos/SkeletonDataAsset Icon.png
  3. 46 0
      spine-unity/Assets/Gizmos/SkeletonDataAsset Icon.png.meta
  4. BIN
      spine-unity/Assets/examples/dragon/dragon Atlas.asset
  5. BIN
      spine-unity/Assets/examples/dragon/dragon SkeletonData.asset
  6. BIN
      spine-unity/Assets/examples/dragon/dragon.mat
  7. BIN
      spine-unity/Assets/examples/dragon/dragon.unity
  8. BIN
      spine-unity/Assets/examples/dragon/dragon2.mat
  9. BIN
      spine-unity/Assets/examples/goblins/goblins Atlas.asset
  10. BIN
      spine-unity/Assets/examples/goblins/goblins Material.mat
  11. BIN
      spine-unity/Assets/examples/goblins/goblins SkeletonData.asset
  12. BIN
      spine-unity/Assets/examples/goblins/goblins.unity
  13. 86 0
      spine-unity/Assets/examples/spineboy/SpineboyController.cs
  14. 8 0
      spine-unity/Assets/examples/spineboy/SpineboyController.cs.meta
  15. 1 0
      spine-unity/Assets/examples/spineboy/data/spineboy.png.meta
  16. BIN
      spine-unity/Assets/examples/spineboy/spineboy Atlas.asset
  17. BIN
      spine-unity/Assets/examples/spineboy/spineboy SkeletonData.asset
  18. BIN
      spine-unity/Assets/examples/spineboy/spineboy.mat
  19. BIN
      spine-unity/Assets/examples/spineboy/spineboy.unity
  20. 355 0
      spine-unity/Assets/examples/spineboy/spineboy_movement.unity
  21. 4 0
      spine-unity/Assets/examples/spineboy/spineboy_movement.unity.meta
  22. 5 0
      spine-unity/Assets/spine-unity/Editor/GUI.meta
  23. BIN
      spine-unity/Assets/spine-unity/Editor/GUI/icon-animation.png
  24. 46 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-animation.png.meta
  25. BIN
      spine-unity/Assets/spine-unity/Editor/GUI/icon-animationRoot.png
  26. 46 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-animationRoot.png.meta
  27. BIN
      spine-unity/Assets/spine-unity/Editor/GUI/icon-event.png
  28. 46 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-event.png.meta
  29. BIN
      spine-unity/Assets/spine-unity/Editor/GUI/icon-skeleton.png
  30. 46 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-skeleton.png.meta
  31. BIN
      spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png
  32. 46 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png.meta
  33. BIN
      spine-unity/Assets/spine-unity/Editor/GUI/icon-spine.png
  34. 46 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-spine.png.meta
  35. 493 4
      spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs
  36. 290 0
      spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs
  37. 4 1
      spine-unity/Assets/spine-unity/SkeletonRenderer.cs
  38. BIN
      spine-unity/Assets/spine-unity/SpineUnity_Readme.pdf

+ 5 - 0
spine-unity/Assets/Gizmos.meta

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

BIN
spine-unity/Assets/Gizmos/SkeletonDataAsset Icon.png


+ 46 - 0
spine-unity/Assets/Gizmos/SkeletonDataAsset Icon.png.meta

@@ -0,0 +1,46 @@
+fileFormatVersion: 2
+guid: 68defdbc95b30a74a9ad396bfc9a2277
+TextureImporter:
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-unity/Assets/examples/dragon/dragon Atlas.asset


BIN
spine-unity/Assets/examples/dragon/dragon SkeletonData.asset


BIN
spine-unity/Assets/examples/dragon/dragon.mat


BIN
spine-unity/Assets/examples/dragon/dragon.unity


BIN
spine-unity/Assets/examples/dragon/dragon2.mat


BIN
spine-unity/Assets/examples/goblins/goblins Atlas.asset


BIN
spine-unity/Assets/examples/goblins/goblins Material.mat


BIN
spine-unity/Assets/examples/goblins/goblins SkeletonData.asset


BIN
spine-unity/Assets/examples/goblins/goblins.unity


+ 86 - 0
spine-unity/Assets/examples/spineboy/SpineboyController.cs

@@ -0,0 +1,86 @@
+using UnityEngine;
+using System.Collections;
+
+[RequireComponent(typeof(SkeletonAnimation), typeof(Rigidbody2D))]
+public class SpineboyController : MonoBehaviour {
+
+	SkeletonAnimation skeletonAnimation;
+
+	public string idleAnimation = "idle";
+	public string walkAnimation = "walk";
+	public string runAnimation = "run";
+	public string hitAnimation = "hit";
+	public string deathAnimation = "death";
+
+	public float walkVelocity = 1;
+	public float runVelocity = 3;
+	public int hp = 10;
+
+	string currentAnimation = "";
+
+	bool hit = false;
+	bool dead = false;
+
+	void Start () {
+		skeletonAnimation = GetComponent<SkeletonAnimation>();
+	}
+
+
+	void Update(){
+		if(!dead){
+			float x = Input.GetAxis("Horizontal");
+			float absX = Mathf.Abs(x);
+
+			if(!hit){
+				if(x > 0)
+					skeletonAnimation.skeleton.FlipX = false;
+				else if(x < 0)
+					skeletonAnimation.skeleton.FlipX = true;
+
+				if(absX > 0.7f){
+					SetAnimation(runAnimation, true);
+					rigidbody2D.velocity = new Vector2( runVelocity * Mathf.Sign(x), rigidbody2D.velocity.y);
+				}
+				else if(absX > 0){
+					SetAnimation(walkAnimation, true);
+					rigidbody2D.velocity = new Vector2( walkVelocity * Mathf.Sign(x), rigidbody2D.velocity.y);
+				}
+				else{
+					SetAnimation(idleAnimation, true);
+					rigidbody2D.velocity = new Vector2( 0, rigidbody2D.velocity.y);
+				}
+			}
+			else{
+				if(skeletonAnimation.state.GetCurrent(0).Animation.Name != hitAnimation)
+					hit = false;
+			}
+		}
+	}
+
+
+	void SetAnimation(string anim, bool loop){
+		if(currentAnimation != anim){
+			skeletonAnimation.state.SetAnimation(0, anim, loop);
+			currentAnimation = anim;
+		}
+	}
+
+	void OnMouseUp(){
+
+		if(hp > 0){
+			hp--;
+
+			if(hp == 0){
+				SetAnimation(deathAnimation, false);
+				dead = true;
+			}
+			else{
+				skeletonAnimation.state.SetAnimation(0, hitAnimation, false);
+				skeletonAnimation.state.AddAnimation(0, currentAnimation, true, 0);
+				rigidbody2D.velocity = new Vector2( 0, rigidbody2D.velocity.y);
+				hit = true;
+			}
+
+		}
+	}
+}

+ 8 - 0
spine-unity/Assets/examples/spineboy/SpineboyController.cs.meta

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

+ 1 - 0
spine-unity/Assets/examples/spineboy/data/spineboy.png.meta

@@ -35,6 +35,7 @@ TextureImporter:
   spriteMeshType: 1
   alignment: 0
   spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
   spritePixelsToUnits: 100
   alphaIsTransparency: 0
   textureType: -1

BIN
spine-unity/Assets/examples/spineboy/spineboy Atlas.asset


BIN
spine-unity/Assets/examples/spineboy/spineboy SkeletonData.asset


BIN
spine-unity/Assets/examples/spineboy/spineboy.mat


BIN
spine-unity/Assets/examples/spineboy/spineboy.unity


+ 355 - 0
spine-unity/Assets/examples/spineboy/spineboy_movement.unity

@@ -0,0 +1,355 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!29 &1
+SceneSettings:
+  m_ObjectHideFlags: 0
+  m_PVSData: 
+  m_PVSObjectsArray: []
+  m_PVSPortalsArray: []
+  m_OcclusionBakeSettings:
+    smallestOccluder: 5
+    smallestHole: .25
+    backfaceThreshold: 100
+--- !u!104 &2
+RenderSettings:
+  m_Fog: 0
+  m_FogColor: {r: .5, g: .5, b: .5, a: 1}
+  m_FogMode: 3
+  m_FogDensity: .00999999978
+  m_LinearFogStart: 0
+  m_LinearFogEnd: 300
+  m_AmbientLight: {r: .200000003, g: .200000003, b: .200000003, a: 1}
+  m_SkyboxMaterial: {fileID: 0}
+  m_HaloStrength: .5
+  m_FlareStrength: 1
+  m_FlareFadeSpeed: 3
+  m_HaloTexture: {fileID: 0}
+  m_SpotCookie: {fileID: 0}
+  m_ObjectHideFlags: 0
+--- !u!127 &3
+LevelGameManager:
+  m_ObjectHideFlags: 0
+--- !u!157 &4
+LightmapSettings:
+  m_ObjectHideFlags: 0
+  m_LightProbes: {fileID: 0}
+  m_Lightmaps: []
+  m_LightmapsMode: 1
+  m_BakedColorSpace: 0
+  m_UseDualLightmapsInForward: 0
+  m_LightmapEditorSettings:
+    m_Resolution: 50
+    m_LastUsedResolution: 0
+    m_TextureWidth: 1024
+    m_TextureHeight: 1024
+    m_BounceBoost: 1
+    m_BounceIntensity: 1
+    m_SkyLightColor: {r: .860000014, g: .930000007, b: 1, a: 1}
+    m_SkyLightIntensity: 0
+    m_Quality: 0
+    m_Bounces: 1
+    m_FinalGatherRays: 1000
+    m_FinalGatherContrastThreshold: .0500000007
+    m_FinalGatherGradientThreshold: 0
+    m_FinalGatherInterpolationPoints: 15
+    m_AOAmount: 0
+    m_AOMaxDistance: .100000001
+    m_AOContrast: 1
+    m_LODSurfaceMappingDistance: 1
+    m_Padding: 0
+    m_TextureCompression: 0
+    m_LockAtlas: 0
+--- !u!196 &5
+NavMeshSettings:
+  m_ObjectHideFlags: 0
+  m_BuildSettings:
+    agentRadius: .5
+    agentHeight: 2
+    agentSlope: 45
+    agentClimb: .400000006
+    ledgeDropHeight: 0
+    maxJumpAcrossDistance: 0
+    accuratePlacement: 0
+    minRegionArea: 2
+    widthInaccuracy: 16.666666
+    heightInaccuracy: 10
+  m_NavMesh: {fileID: 0}
+--- !u!1 &103710462
+GameObject:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  serializedVersion: 4
+  m_Component:
+  - 4: {fileID: 103710467}
+  - 20: {fileID: 103710466}
+  - 92: {fileID: 103710465}
+  - 124: {fileID: 103710464}
+  - 81: {fileID: 103710463}
+  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 &103710463
+AudioListener:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 103710462}
+  m_Enabled: 1
+--- !u!124 &103710464
+Behaviour:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 103710462}
+  m_Enabled: 1
+--- !u!92 &103710465
+Behaviour:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 103710462}
+  m_Enabled: 1
+--- !u!20 &103710466
+Camera:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 103710462}
+  m_Enabled: 1
+  serializedVersion: 2
+  m_ClearFlags: 1
+  m_BackGroundColor: {r: .192156866, g: .301960796, b: .474509805, a: .0196078438}
+  m_NormalizedViewPortRect:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1
+    height: 1
+  near clip plane: .300000012
+  far clip plane: 1000
+  field of view: 60
+  orthographic: 0
+  orthographic size: 5
+  m_Depth: -1
+  m_CullingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+  m_RenderingPath: -1
+  m_TargetTexture: {fileID: 0}
+  m_TargetDisplay: 0
+  m_HDR: 0
+  m_OcclusionCulling: 1
+  m_StereoConvergence: 10
+  m_StereoSeparation: .0219999999
+--- !u!4 &103710467
+Transform:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 103710462}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 1, z: -10}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+--- !u!1 &498745350
+GameObject:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  serializedVersion: 4
+  m_Component:
+  - 4: {fileID: 498745355}
+  - 33: {fileID: 498745354}
+  - 23: {fileID: 498745353}
+  - 114: {fileID: 498745352}
+  - 114: {fileID: 498745351}
+  - 50: {fileID: 498745357}
+  - 61: {fileID: 498745356}
+  m_Layer: 0
+  m_Name: Spineboy
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &498745351
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 498745350}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: ef0903d879ea9ca49a1fd44d707beb9d, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  idleAnimation: idle
+  walkAnimation: walk
+  runAnimation: run
+  hitAnimation: hit
+  deathAnimation: death
+  walkVelocity: 2.5
+  runVelocity: 10
+  hp: 10
+--- !u!114 &498745352
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 498745350}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: d247ba06193faa74d9335f5481b2b56c, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  skeletonDataAsset: {fileID: 11400000, guid: d04edfd5d421496409ca795016a48045, type: 2}
+  initialSkinName: default
+  calculateNormals: 0
+  calculateTangents: 0
+  zSpacing: 0
+  renderMeshes: 1
+  immutableTriangles: 0
+  logErrors: 0
+  timeScale: 1
+  loop: 1
+  _animationName: idle
+--- !u!23 &498745353
+Renderer:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 498745350}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_LightmapIndex: 255
+  m_LightmapTilingOffset: {x: 1, y: 1, z: 0, w: 0}
+  m_Materials:
+  - {fileID: 0}
+  m_SubsetIndices: 
+  m_StaticBatchRoot: {fileID: 0}
+  m_UseLightProbes: 0
+  m_LightProbeAnchor: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+--- !u!33 &498745354
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 498745350}
+  m_Mesh: {fileID: 0}
+--- !u!4 &498745355
+Transform:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 498745350}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: .229821205, z: 0}
+  m_LocalScale: {x: .28331995, y: .28331995, z: .28331995}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 1
+--- !u!61 &498745356
+BoxCollider2D:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 498745350}
+  m_Enabled: 1
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Size: {x: 3.12331629, y: 6.97735691}
+  m_Center: {x: .0340548158, y: 3.36076927}
+--- !u!50 &498745357
+Rigidbody2D:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 498745350}
+  m_Mass: 1
+  m_LinearDrag: 0
+  m_AngularDrag: .0500000007
+  m_GravityScale: 1
+  m_FixedAngle: 0
+  m_IsKinematic: 0
+  m_Interpolate: 0
+  m_SleepingMode: 1
+  m_CollisionDetection: 0
+--- !u!1 &1415830073
+GameObject:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  serializedVersion: 4
+  m_Component:
+  - 4: {fileID: 1415830077}
+  - 33: {fileID: 1415830076}
+  - 23: {fileID: 1415830075}
+  - 61: {fileID: 1415830074}
+  m_Layer: 0
+  m_Name: Ground
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!61 &1415830074
+BoxCollider2D:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 1415830073}
+  m_Enabled: 1
+  m_Material: {fileID: 0}
+  m_IsTrigger: 0
+  m_Size: {x: 1, y: 1}
+  m_Center: {x: 0, y: 0}
+--- !u!23 &1415830075
+Renderer:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 1415830073}
+  m_Enabled: 1
+  m_CastShadows: 1
+  m_ReceiveShadows: 1
+  m_LightmapIndex: 255
+  m_LightmapTilingOffset: {x: 1, y: 1, z: 0, w: 0}
+  m_Materials:
+  - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0}
+  m_SubsetIndices: 
+  m_StaticBatchRoot: {fileID: 0}
+  m_UseLightProbes: 0
+  m_LightProbeAnchor: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+--- !u!33 &1415830076
+MeshFilter:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 1415830073}
+  m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!4 &1415830077
+Transform:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 0}
+  m_GameObject: {fileID: 1415830073}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: .132730573, y: -.602417529, z: 0}
+  m_LocalScale: {x: 29.7312527, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 2

+ 4 - 0
spine-unity/Assets/examples/spineboy/spineboy_movement.unity.meta

@@ -0,0 +1,4 @@
+fileFormatVersion: 2
+guid: ce8726553213c1d4d99db0a795765d85
+DefaultImporter:
+  userData: 

+ 5 - 0
spine-unity/Assets/spine-unity/Editor/GUI.meta

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

BIN
spine-unity/Assets/spine-unity/Editor/GUI/icon-animation.png


+ 46 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-animation.png.meta

@@ -0,0 +1,46 @@
+fileFormatVersion: 2
+guid: 52b12ec801461494185a4d3dc66f3d1d
+TextureImporter:
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-unity/Assets/spine-unity/Editor/GUI/icon-animationRoot.png


+ 46 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-animationRoot.png.meta

@@ -0,0 +1,46 @@
+fileFormatVersion: 2
+guid: 3d1be4ea889f3a14b864352fe49a1bde
+TextureImporter:
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-unity/Assets/spine-unity/Editor/GUI/icon-event.png


+ 46 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-event.png.meta

@@ -0,0 +1,46 @@
+fileFormatVersion: 2
+guid: d226a80acc775714aa78b85e16a00e9b
+TextureImporter:
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-unity/Assets/spine-unity/Editor/GUI/icon-skeleton.png


+ 46 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-skeleton.png.meta

@@ -0,0 +1,46 @@
+fileFormatVersion: 2
+guid: f2216037084d99d4481810cb521ed96f
+TextureImporter:
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png


+ 46 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png.meta

@@ -0,0 +1,46 @@
+fileFormatVersion: 2
+guid: 8bd14c7643597a74ba2edc10a5e4c4ed
+TextureImporter:
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-unity/Assets/spine-unity/Editor/GUI/icon-spine.png


+ 46 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-spine.png.meta

@@ -0,0 +1,46 @@
+fileFormatVersion: 2
+guid: 4e7c964fa5e07024c8bf1debecc3b7c8
+TextureImporter:
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

+ 493 - 4
spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs

@@ -29,7 +29,9 @@
  *****************************************************************************/
 
 using System;
+using System.Collections.Generic;
 using UnityEditor;
+using UnityEditor.AnimatedValues;
 using UnityEngine;
 using Spine;
 
@@ -37,6 +39,11 @@ using Spine;
 public class SkeletonDataAssetInspector : Editor {
 	private SerializedProperty atlasAsset, skeletonJSON, scale, fromAnimation, toAnimation, duration, defaultMix;
 	private bool showAnimationStateData = true;
+	private AnimBool m_showAnimationList = new AnimBool(true);
+
+	private bool m_initialized = false;
+	private SkeletonDataAsset m_skeletonDataAsset;
+	private string m_skeletonDataAssetGUID;
 
 	void OnEnable () {
 		atlasAsset = serializedObject.FindProperty("atlasAsset");
@@ -46,23 +53,44 @@ public class SkeletonDataAssetInspector : Editor {
 		toAnimation = serializedObject.FindProperty("toAnimation");
 		duration = serializedObject.FindProperty("duration");
 		defaultMix = serializedObject.FindProperty("defaultMix");
-	}
 
+		m_skeletonDataAsset = (SkeletonDataAsset)target;
+		m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath(m_skeletonDataAsset) );
+
+		EditorApplication.update += Update;
+	}
+	
+	void OnDestroy(){
+		m_initialized = false;
+		EditorApplication.update -= Update;
+		this.DestroyPreviewInstances();
+		if (this.m_previewUtility != null)
+		{
+			this.m_previewUtility.Cleanup();
+			this.m_previewUtility = null;
+		}
+	}
+	
 	override public void OnInspectorGUI () {
 		serializedObject.Update();
 		SkeletonDataAsset asset = (SkeletonDataAsset)target;
 
+		EditorGUI.BeginChangeCheck();
 		EditorGUILayout.PropertyField(atlasAsset);
 		EditorGUILayout.PropertyField(skeletonJSON);
 		EditorGUILayout.PropertyField(scale);
-		
+		if(EditorGUI.EndChangeCheck()){
+			m_previewUtility.Cleanup();
+			m_previewUtility = null;
+		}
+
 		SkeletonData skeletonData = asset.GetSkeletonData(asset.atlasAsset == null || asset.skeletonJSON == null);
 		if (skeletonData != null) {
 			showAnimationStateData = EditorGUILayout.Foldout(showAnimationStateData, "Animation State Data");
 			if (showAnimationStateData) {
 				EditorGUILayout.PropertyField(defaultMix);
 
-				// Animation names.
+				// Animation names
 				String[] animations = new String[skeletonData.Animations.Count];
 				for (int i = 0; i < animations.Length; i++)
 					animations[i] = skeletonData.Animations[i].Name;
@@ -92,6 +120,43 @@ public class SkeletonDataAssetInspector : Editor {
 				EditorGUILayout.Space();
 				EditorGUILayout.EndHorizontal();
 			}
+
+			if(GUILayout.Button(new GUIContent("Setup Pose", SpineEditorUtilities.Icons.skeleton),  GUILayout.Width(105), GUILayout.Height(18))){
+				StopAnimation();
+				m_skeletonAnimation.skeleton.SetToSetupPose();
+				m_requireRefresh = true;
+			}
+
+			m_showAnimationList.target = EditorGUILayout.Foldout(m_showAnimationList.target, new GUIContent("Animations", SpineEditorUtilities.Icons.animationRoot));
+
+			if(EditorGUILayout.BeginFadeGroup(m_showAnimationList.faded)){
+
+				EditorGUILayout.LabelField("Name", "Duration");
+				foreach(Spine.Animation a in skeletonData.Animations){
+					GUILayout.BeginHorizontal();
+
+					if(m_skeletonAnimation != null && m_skeletonAnimation.state != null){
+						if(m_skeletonAnimation.state.GetCurrent(0) != null && m_skeletonAnimation.state.GetCurrent(0).Animation == a){
+							GUI.contentColor = Color.black;
+							if(GUILayout.Button("\u25BA", GUILayout.Width(24))){
+								StopAnimation();
+							}
+							GUI.contentColor = Color.white;
+						}
+						else{
+							if(GUILayout.Button("\u25BA", GUILayout.Width(24))){
+								PlayAnimation(a.Name, true);
+							}
+						}
+					}
+					else{
+						GUILayout.Label("?", GUILayout.Width(24));
+					}
+					EditorGUILayout.LabelField(new GUIContent(a.Name, SpineEditorUtilities.Icons.animation), new GUIContent(a.Duration.ToString("f3") + "s" +  ("(" + (Mathf.RoundToInt(a.Duration * 30)) + ")").PadLeft(12, ' ')));
+					GUILayout.EndHorizontal();
+				}
+			}
+			EditorGUILayout.EndFadeGroup();
 		}
 		
 		if (!Application.isPlaying) {
@@ -102,4 +167,428 @@ public class SkeletonDataAssetInspector : Editor {
 			}
 		}
 	}
-}
+	
+	//preview window stuff
+	private PreviewRenderUtility m_previewUtility;
+	private GameObject m_previewInstance;
+	private Vector2 previewDir;
+	private SkeletonAnimation m_skeletonAnimation;
+	private SkeletonData m_skeletonData;
+
+	private static int sliderHash = "Slider".GetHashCode();
+	private float m_lastTime;
+	private bool m_playing;
+	private bool m_requireRefresh;
+
+	private Color m_originColor = new Color(0.3f,0.3f,0.3f, 1);
+
+	private void StopAnimation(){
+		m_skeletonAnimation.state.ClearTrack(0);
+		m_playing = false;
+	}
+
+
+	List<Spine.Event> m_animEvents = new List<Spine.Event>();
+	List<float> m_animEventFrames = new List<float>();
+	private void PlayAnimation(string animName, bool loop){
+		m_animEvents.Clear();
+		m_animEventFrames.Clear();
+
+		m_skeletonAnimation.state.SetAnimation(0, animName, loop);
+
+		Spine.Animation a = m_skeletonAnimation.state.GetCurrent(0).Animation;
+		foreach(Timeline t in a.Timelines){
+			if(t.GetType() == typeof(EventTimeline)){
+				EventTimeline et = (EventTimeline)t;
+
+				for(int i = 0; i < et.Events.Length; i++){
+					m_animEvents.Add(et.Events[i]);
+					m_animEventFrames.Add(et.Frames[i]);
+				}
+
+			}
+		}
+
+		m_playing = true;
+	}
+	
+	private void InitPreview()
+	{
+		if (this.m_previewUtility == null)
+		{
+			this.m_lastTime = Time.realtimeSinceStartup;
+			this.m_previewUtility = new PreviewRenderUtility(true);
+			this.m_previewUtility.m_Camera.isOrthoGraphic = true;
+			this.m_previewUtility.m_Camera.orthographicSize = 1;
+			this.m_previewUtility.m_Camera.cullingMask = -2147483648;
+			this.CreatePreviewInstances();
+		}
+	}
+
+	private void CreatePreviewInstances()
+	{
+		this.DestroyPreviewInstances();
+		if (this.m_previewInstance == null)
+		{
+			string skinName = EditorPrefs.GetString(m_skeletonDataAssetGUID + "_lastSkin", "");
+
+			m_previewInstance = SpineEditorUtilities.SpawnAnimatedSkeleton( (SkeletonDataAsset)target, skinName ).gameObject;
+			m_previewInstance.hideFlags = HideFlags.HideAndDontSave;
+			m_previewInstance.layer = 0x1f;
+
+
+			m_skeletonAnimation = m_previewInstance.GetComponent<SkeletonAnimation>();
+			m_skeletonAnimation.initialSkinName = skinName;
+			m_skeletonAnimation.LateUpdate();
+
+			m_skeletonData = m_skeletonAnimation.skeletonDataAsset.GetSkeletonData(true);
+
+			m_previewInstance.renderer.enabled = false;
+
+			m_initialized = true;
+			AdjustCameraGoals(true);
+		}
+	}
+
+	private void DestroyPreviewInstances()
+	{
+		if (this.m_previewInstance != null)
+		{
+			DestroyImmediate(this.m_previewInstance);
+			m_previewInstance = null;
+		}
+		m_initialized = false;
+	}
+
+	public override bool HasPreviewGUI ()
+	{
+		return true;
+	}
+
+	Texture m_previewTex = new Texture();
+	public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)
+	{
+		this.InitPreview();
+
+		if (UnityEngine.Event.current.type == EventType.Repaint)
+		{
+			if(m_requireRefresh){
+				this.m_previewUtility.BeginPreview(r, background);
+				this.DoRenderPreview(true);
+				this.m_previewTex = this.m_previewUtility.EndPreview();
+				m_requireRefresh = false;
+			}
+			if(this.m_previewTex != null)
+				GUI.DrawTexture(r, m_previewTex, ScaleMode.StretchToFill, false);
+		}
+
+		DrawSkinToolbar(r);
+		NormalizedTimeBar(r);
+		//TODO: implement panning
+//		this.previewDir = Drag2D(this.previewDir, r);
+		MouseScroll(r);
+	}
+
+	float m_orthoGoal = 1;
+	Vector3 m_posGoal = new Vector3(0,0,-10);
+	double m_adjustFrameEndTime = 0;
+	private void AdjustCameraGoals(bool calculateMixTime){
+		if(calculateMixTime){
+			if(m_skeletonAnimation.state.GetCurrent(0) != null){
+				m_adjustFrameEndTime = EditorApplication.timeSinceStartup + m_skeletonAnimation.state.GetCurrent(0).Mix;
+			}
+		}
+
+
+		GameObject go = this.m_previewInstance;
+		Bounds bounds = go.renderer.bounds;
+		m_orthoGoal = bounds.size.y;
+		
+		m_posGoal = bounds.center + new Vector3(0,0,-10);
+	}
+
+	private void AdjustCameraGoals(){
+		AdjustCameraGoals(false);
+	}
+
+	private void AdjustCamera(){
+		if(m_previewUtility == null)
+			return;
+
+
+		if(EditorApplication.timeSinceStartup < m_adjustFrameEndTime){
+			AdjustCameraGoals();
+		}
+
+		float orthoSet = Mathf.Lerp(this.m_previewUtility.m_Camera.orthographicSize, m_orthoGoal, 0.1f);
+
+		this.m_previewUtility.m_Camera.orthographicSize = orthoSet;
+
+		float dist = Vector3.Distance(m_previewUtility.m_Camera.transform.position, m_posGoal);
+		if(dist > 60f * ((SkeletonDataAsset)target).scale){
+			Vector3 pos = Vector3.Lerp(this.m_previewUtility.m_Camera.transform.position, m_posGoal, 0.1f);
+			pos.x = 0;
+			this.m_previewUtility.m_Camera.transform.position = pos;
+			this.m_previewUtility.m_Camera.transform.rotation = Quaternion.identity;
+			m_requireRefresh = true;
+		}
+	}
+
+	private void DoRenderPreview(bool drawHandles)
+	{
+		GameObject go = this.m_previewInstance;
+
+		if(m_requireRefresh){
+			go.renderer.enabled = true;
+
+			if(EditorApplication.isPlaying){
+				//do nothing
+			}
+			else{
+				m_skeletonAnimation.Update((Time.realtimeSinceStartup - m_lastTime));
+			}
+
+			m_lastTime = Time.realtimeSinceStartup;
+
+			if(!EditorApplication.isPlaying)
+				m_skeletonAnimation.LateUpdate();
+		
+			if(drawHandles){
+				Handles.SetCamera(m_previewUtility.m_Camera);
+				Handles.color = m_originColor;
+				
+				Handles.DrawLine(new Vector3(-1000 * m_skeletonDataAsset.scale,0,0), new Vector3(1000 * m_skeletonDataAsset.scale,0,0));
+				Handles.DrawLine(new Vector3(0,1000 * m_skeletonDataAsset.scale,0), new Vector3(0,-1000 * m_skeletonDataAsset.scale,0));
+			}
+			
+			this.m_previewUtility.m_Camera.Render();
+			go.renderer.enabled = false;
+		}
+
+
+	}
+
+	void Update(){
+		AdjustCamera();
+
+		if (m_playing) {
+			m_requireRefresh = true;
+			Repaint();
+		}
+		else if (m_requireRefresh) {
+			Repaint ();
+		}
+		else{
+			if(m_showAnimationList.isAnimating)
+				Repaint();
+		}
+	}
+
+	void DrawSkinToolbar(Rect r){
+		if(m_skeletonAnimation == null)
+			return;
+
+		if(m_skeletonAnimation.skeleton != null){
+			string label = (m_skeletonAnimation.skeleton != null && m_skeletonAnimation.skeleton.Skin != null) ? m_skeletonAnimation.skeleton.Skin.Name : "default";
+
+			Rect popRect = new Rect(r);
+			popRect.y += 32;
+			popRect.x += 4;
+			popRect.height = 24;
+			popRect.width = 40;
+			EditorGUI.DropShadowLabel(popRect, new GUIContent("Skin", SpineEditorUtilities.Icons.skinsRoot));
+
+			popRect.y += 11;
+			popRect.width = 150;
+			popRect.x += 44;
+
+			if(GUI.Button( popRect, label, EditorStyles.popup)){
+				SelectSkinContext();
+			}
+		}
+	}
+
+	void SelectSkinContext(){
+		GenericMenu menu = new GenericMenu();
+		
+		foreach(Skin s in m_skeletonData.Skins){
+			menu.AddItem( new GUIContent(s.Name), this.m_skeletonAnimation.skeleton.Skin == s, SetSkin, (object)s);
+		}
+
+		menu.ShowAsContext();
+	}
+	
+	void SetSkin(object o){
+		Skin skin = (Skin)o;
+
+		m_skeletonAnimation.initialSkinName = skin.Name;
+		m_skeletonAnimation.Reset();
+		m_requireRefresh = true;
+
+		EditorPrefs.SetString(m_skeletonDataAssetGUID + "_lastSkin", skin.Name);
+	}
+
+	void NormalizedTimeBar(Rect r){
+		Rect barRect = new Rect(r);
+		barRect.height = 32;
+		barRect.x += 4;
+		barRect.width -=4;
+
+		GUI.Box(barRect, "");
+
+		Rect lineRect = new Rect(barRect);
+		float width = lineRect.width;
+		TrackEntry t = m_skeletonAnimation.state.GetCurrent(0);
+
+		if(t != null){
+			int loopCount = (int)(t.Time / t.EndTime);
+			float currentTime = t.Time - (t.EndTime * loopCount);
+
+			float normalizedTime = currentTime / t.Animation.Duration;
+
+			lineRect.x = barRect.x + (width * normalizedTime) - 0.5f;
+			lineRect.width = 2;
+
+			GUI.color = Color.red;
+			GUI.DrawTexture(lineRect, EditorGUIUtility.whiteTexture);
+			GUI.color = Color.white;
+	
+			for(int i = 0; i < m_animEvents.Count; i++){
+				//TODO: Tooltip
+				//Spine.Event spev = animEvents[i];
+
+				float fr = m_animEventFrames[i];
+
+				Rect evRect = new Rect(barRect);
+				evRect.x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (SpineEditorUtilities.Icons._event.width/2), barRect.x, float.MaxValue);
+				evRect.width = SpineEditorUtilities.Icons._event.width;
+				evRect.height = SpineEditorUtilities.Icons._event.height;
+				evRect.y += SpineEditorUtilities.Icons._event.height;
+				GUI.DrawTexture(evRect, SpineEditorUtilities.Icons._event);
+
+
+				//TODO:  Tooltip
+				/*
+				UnityEngine.Event ev = UnityEngine.Event.current;
+				if(ev.isMouse){
+					if(evRect.Contains(ev.mousePosition)){
+						Rect tooltipRect = new Rect(evRect);
+						tooltipRect.width = 500;
+						tooltipRect.y -= 4;
+						tooltipRect.x += 4;
+						GUI.Label(tooltipRect, spev.Data.Name);
+					}
+				}
+				*/
+			}
+		}
+	}
+
+	void MouseScroll(Rect position){
+		UnityEngine.Event current = UnityEngine.Event.current;
+		int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
+
+		switch(current.GetTypeForControl(controlID)){
+		case EventType.ScrollWheel:
+			if(position.Contains(current.mousePosition)){
+
+				m_orthoGoal += current.delta.y * ((SkeletonDataAsset)target).scale * 10;
+				GUIUtility.hotControl = controlID;
+				current.Use();
+			}
+			break;
+		}
+
+	}
+
+	//TODO:  Implement preview panning
+	/*
+	static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
+	{
+		int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
+		UnityEngine.Event current = UnityEngine.Event.current;
+		switch (current.GetTypeForControl(controlID))
+		{
+		case EventType.MouseDown:
+			if (position.Contains(current.mousePosition) && (position.width > 50f))
+			{
+				GUIUtility.hotControl = controlID;
+				current.Use();
+				EditorGUIUtility.SetWantsMouseJumping(1);
+			}
+			return scrollPosition;
+			
+		case EventType.MouseUp:
+			if (GUIUtility.hotControl == controlID)
+			{
+				GUIUtility.hotControl = 0;
+			}
+			EditorGUIUtility.SetWantsMouseJumping(0);
+			return scrollPosition;
+			
+		case EventType.MouseMove:
+			return scrollPosition;
+			
+		case EventType.MouseDrag:
+			if (GUIUtility.hotControl == controlID)
+			{
+				scrollPosition -= (Vector2) (((current.delta * (!current.shift ? ((float) 1) : ((float) 3))) / Mathf.Min(position.width, position.height)) * 140f);
+				scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f);
+				current.Use();
+				GUI.changed = true;
+			}
+			return scrollPosition;
+		}
+		return scrollPosition;
+	}
+	*/
+
+	public override GUIContent GetPreviewTitle ()
+	{
+		return new GUIContent ("Preview");
+	}
+
+	public override void OnPreviewSettings ()
+	{
+		if(!m_initialized){
+			GUILayout.HorizontalSlider(0,0,2, GUILayout.MaxWidth(64));
+		}
+		else{
+			float speed = GUILayout.HorizontalSlider( m_skeletonAnimation.timeScale, 0, 2, GUILayout.MaxWidth(64));
+
+			//snap to nearest 0.25
+			float y = speed / 0.25f;
+			int q = Mathf.RoundToInt(y);
+			speed = q * 0.25f;
+
+			m_skeletonAnimation.timeScale = speed;
+		}
+	}
+
+	//TODO:  Fix first-import error
+	//TODO:  Update preview without thumbnail
+	public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height)
+	{
+		Texture2D tex = new Texture2D(width, height, TextureFormat.ARGB32, false);
+
+		this.InitPreview();
+
+		if(this.m_previewUtility.m_Camera == null)
+			return null;
+
+			m_requireRefresh = true;
+			this.DoRenderPreview(false);
+			AdjustCameraGoals(false);
+
+			this.m_previewUtility.m_Camera.orthographicSize = m_orthoGoal/2;
+			this.m_previewUtility.m_Camera.transform.position = m_posGoal;
+			this.m_previewUtility.BeginStaticPreview(new Rect(0,0,width,height));
+			this.DoRenderPreview(false);
+			Handles.SetCamera(this.m_previewUtility.m_Camera);
+			Handles.BeginGUI();
+			GUI.DrawTexture(new Rect(40,60,width,height), SpineEditorUtilities.Icons.spine, ScaleMode.StretchToFill);
+			Handles.EndGUI();
+			tex = this.m_previewUtility.EndStaticPreview();
+		return tex;
+	}
+}

+ 290 - 0
spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs

@@ -0,0 +1,290 @@
+using UnityEngine;
+using UnityEditor;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Spine;
+
+[InitializeOnLoad]
+public static class SpineEditorUtilities {
+
+	public static class Icons{
+		public static Texture2D skeleton;
+		public static Texture2D nullBone;
+		public static Texture2D bone;
+		public static Texture2D boneNib;
+		public static Texture2D slot;
+		public static Texture2D skinPlaceholder;
+		public static Texture2D image;
+		public static Texture2D boundingBox;
+		public static Texture2D mesh;
+		public static Texture2D skin;
+		public static Texture2D skinsRoot;
+		public static Texture2D animation;
+		public static Texture2D animationRoot;
+		public static Texture2D spine;
+		public static Texture2D _event;
+
+		public static Mesh boneMesh{
+			get{
+				if(_boneMesh == null){
+					_boneMesh = new Mesh();
+					_boneMesh.vertices = new Vector3[4]{Vector3.zero, new Vector3(-0.1f,0.1f,0), Vector3.up, new Vector3(0.1f,0.1f,0)};
+					_boneMesh.uv = new Vector2[4];
+					_boneMesh.triangles = new int[6]{0,1,2,2,3,0};
+					_boneMesh.RecalculateBounds();
+					_boneMesh.RecalculateNormals();
+				}
+
+				return _boneMesh;
+			}
+		}
+		internal static Mesh _boneMesh;
+
+
+		public static Material boneMaterial{
+			get{
+				if(_boneMaterial == null){
+					_boneMaterial = new Material(Shader.Find("Spine/Bones"));
+					_boneMaterial.SetColor("_Color", new Color(0.4f, 0.4f, 0.4f, 0.25f));
+				}
+
+				return _boneMaterial;
+			}
+		}
+		internal static Material _boneMaterial;
+
+		public static void Initialize(){
+			skeleton = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-skeleton.png");
+			nullBone = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-null.png");
+			bone = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-bone.png");
+			boneNib = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-boneNib.png");
+			slot = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-slot.png");
+			skinPlaceholder = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-skinPlaceholder.png");
+			image = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-image.png");
+			boundingBox = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-boundingBox.png");
+			mesh = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-mesh.png");
+			skin = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-skinPlaceholder.png");
+			skinsRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-skinsRoot.png");
+			animation = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-animation.png");
+			animationRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-animationRoot.png");
+			spine = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-spine.png");
+			_event = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-event.png");
+		}
+
+	}
+
+
+
+	public static string editorPath = "";
+	public static string editorGUIPath = "";
+
+	static List<int> skeletonRendererInstanceIDs;
+
+	public static float defaultScale = 0.01f;
+	public static float defaultMix = 0.2f;
+	public static string defaultShader = "Spine/Skeleton";
+	
+	static SpineEditorUtilities(){
+		DirectoryInfo rootDir = new DirectoryInfo(Application.dataPath);
+		FileInfo[] files = rootDir.GetFiles("SpineEditorUtilities.cs", SearchOption.AllDirectories);
+		editorPath = Path.GetDirectoryName(files[0].FullName.Replace("\\", "/").Replace(Application.dataPath, "Assets"));
+		editorGUIPath = editorPath + "/GUI";	
+
+		Icons.Initialize();
+
+		skeletonRendererInstanceIDs = new List<int>();
+
+		EditorApplication.hierarchyWindowChanged += HierarchyWindowChanged;
+		EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
+
+		HierarchyWindowChanged();
+	}
+
+	static void HierarchyWindowChanged(){
+		skeletonRendererInstanceIDs.Clear();
+
+		SkeletonRenderer[] arr = Object.FindObjectsOfType<SkeletonRenderer>();
+
+		foreach(SkeletonRenderer r in arr)
+			skeletonRendererInstanceIDs.Add(r.gameObject.GetInstanceID());
+	}
+
+	static void HierarchyWindowItemOnGUI(int instanceId, Rect selectionRect){
+		if(skeletonRendererInstanceIDs.Contains(instanceId)){
+			Rect r = new Rect (selectionRect); 
+			r.x = r.width - 15;
+			r.width = 15;
+
+			GUI.Label(r, Icons.spine);
+		}
+	}
+	
+	[MenuItem("Assets/Spine/Ingest")]
+	static void IngestSpineProject(){
+		TextAsset spineJson = null;
+		TextAsset atlasText = null;
+		
+		foreach(UnityEngine.Object o in Selection.objects){
+			if(o.GetType() != typeof(TextAsset))
+				continue;
+			
+			string fileName = Path.GetFileName(AssetDatabase.GetAssetPath(o));
+			
+			if(fileName.EndsWith(".json"))
+				spineJson = (TextAsset)o;
+			else if(fileName.EndsWith(".atlas.txt"))
+				atlasText = (TextAsset)o;
+		}
+		
+		if(spineJson == null){
+			EditorUtility.DisplayDialog("Error!", "Spine JSON file not found in selection!", "OK");
+			return;
+		}
+		
+		string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
+		string assetPath = Path.GetDirectoryName( AssetDatabase.GetAssetPath(spineJson));
+		
+		if(atlasText == null){
+			string atlasPath = assetPath + "/" + primaryName + ".atlas.txt";
+			atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(TextAsset));
+		}
+		
+		if(spineJson != null && atlasText != null){
+			
+			AssetPreview.GetMiniTypeThumbnail(typeof(bool));
+			
+			AtlasAsset atlasAsset = AtlasAsset.CreateInstance<AtlasAsset>();
+			atlasAsset.atlasFile = atlasText;
+
+
+
+			
+			string[] atlasLines = atlasText.text.Split('\n');
+			List<string> pageFiles = new List<string>();
+			for(int i = 0; i < atlasLines.Length-1; i++){
+				if(atlasLines[i].Length == 0)
+					pageFiles.Add(atlasLines[i+1]);
+			}
+
+			atlasAsset.materials = new Material[pageFiles.Count];
+
+			for(int i = 0; i < pageFiles.Count; i++){
+				string texturePath = assetPath + "/" + pageFiles[i];
+				Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D));
+				
+				TextureImporter texImporter = (TextureImporter)TextureImporter.GetAtPath(texturePath);
+				texImporter.textureFormat = TextureImporterFormat.AutomaticTruecolor;
+				texImporter.mipmapEnabled = false;
+				EditorUtility.SetDirty(texImporter);
+				AssetDatabase.ImportAsset(texturePath);
+				AssetDatabase.SaveAssets();
+
+				string pageName = Path.GetFileNameWithoutExtension(pageFiles[i]);
+
+				//because this looks silly
+				if(pageName == primaryName && pageFiles.Count == 1)
+					pageName = "Material";
+
+				string materialPath = assetPath + "/" + primaryName + "_" + pageName + ".mat";
+
+				Material mat = new Material(Shader.Find(defaultShader));
+
+				mat.mainTexture = texture;
+				
+				AssetDatabase.CreateAsset(mat, materialPath);
+				AssetDatabase.SaveAssets();
+				
+				atlasAsset.materials[i] = mat;
+			}
+			
+			AssetDatabase.CreateAsset(atlasAsset, assetPath + "/" + primaryName + "_Atlas.asset");
+			AssetDatabase.SaveAssets();
+			
+			SkeletonDataAsset skelDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>();
+			skelDataAsset.atlasAsset = atlasAsset;
+			skelDataAsset.skeletonJSON = spineJson;
+			skelDataAsset.fromAnimation = new string[0];
+			skelDataAsset.toAnimation = new string[0];
+			skelDataAsset.duration = new float[0];
+			skelDataAsset.defaultMix = defaultMix;
+			skelDataAsset.scale = defaultScale;
+
+			AssetDatabase.CreateAsset(skelDataAsset, assetPath + "/" + primaryName + "_SkeletonData.asset");
+			AssetDatabase.SaveAssets();
+		}
+		else{
+			EditorUtility.DisplayDialog("Error!", "Atlas file not found in selection!", "OK");
+			return;
+		}
+	}
+
+	[MenuItem("Assets/Spine/Spawn")]
+	static void SpawnAnimatedSkeleton(){
+		Object[] arr = Selection.objects;
+
+		foreach(Object o in arr){
+
+			string guid = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( o ) );
+			string skinName = EditorPrefs.GetString(guid + "_lastSkin", "");
+
+			SpawnAnimatedSkeleton((SkeletonDataAsset)o, skinName);
+			SceneView.RepaintAll();
+		}
+	}
+
+	[MenuItem("Assets/Spine/Spawn", true)]
+	static bool ValidateSpawnAnimatedSkeleton(){
+		Object[] arr = Selection.objects;
+		
+		if(arr.Length == 0)
+			return false;
+		
+		foreach(Object o in arr){
+			if(o.GetType() != typeof(SkeletonDataAsset))
+				return false;
+		}
+		
+		return true;
+	}
+
+	public static SkeletonAnimation SpawnAnimatedSkeleton(SkeletonDataAsset skeletonDataAsset, string skinName){
+		return SpawnAnimatedSkeleton(skeletonDataAsset, skeletonDataAsset.GetSkeletonData(true).FindSkin(skinName));
+	}
+
+	public static SkeletonAnimation SpawnAnimatedSkeleton(SkeletonDataAsset skeletonDataAsset, Skin skin = null){
+		
+		GameObject go = new GameObject(skeletonDataAsset.name.Replace("_SkeletonData", ""), typeof(MeshFilter), typeof(MeshRenderer), typeof(SkeletonAnimation));
+		SkeletonAnimation anim = go.GetComponent<SkeletonAnimation>();
+		anim.skeletonDataAsset = skeletonDataAsset;
+
+		bool requiresNormals = false;
+
+		foreach(Material m in anim.skeletonDataAsset.atlasAsset.materials){
+			if(m.shader.name.Contains("Lit")){
+				requiresNormals = true;
+				break;
+			}
+		}
+
+		anim.calculateNormals = requiresNormals;
+
+		if(skin == null)
+			skin = skeletonDataAsset.GetSkeletonData(true).DefaultSkin;
+
+		anim.Reset();
+		
+		anim.skeleton.SetSkin(skin);
+		anim.initialSkinName = skin.Name;
+		
+		anim.skeleton.Update(1);
+		anim.state.Update(1);
+		anim.state.Apply(anim.skeleton);
+		anim.skeleton.UpdateWorldTransform();
+
+		return anim;
+	}
+
+
+}

+ 4 - 1
spine-unity/Assets/spine-unity/SkeletonRenderer.cs

@@ -47,6 +47,7 @@ public class SkeletonRenderer : MonoBehaviour {
 	public bool calculateNormals, calculateTangents;
 	public float zSpacing;
 	public bool renderMeshes = true, immutableTriangles;
+	public bool logErrors = false;
 	
 	private MeshFilter meshFilter;
 	private Mesh mesh, mesh1, mesh2;
@@ -78,7 +79,9 @@ public class SkeletonRenderer : MonoBehaviour {
 
 		valid = false;
 		if (!skeletonDataAsset) {
-			Debug.LogError("Missing SkeletonData asset.", this);
+			if(logErrors)
+				Debug.LogError("Missing SkeletonData asset.", this);
+
 			return;
 		}
 		SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false);

BIN
spine-unity/Assets/spine-unity/SpineUnity_Readme.pdf