Ver Fonte

Merge remote-tracking branch 'EsotericSoftware/3.6' into 3.6

Stephen Gowen há 7 anos atrás
pai
commit
d4fb19186b

+ 0 - 9
spine-unity/Assets/spine-unity/Asset Types/Editor.meta

@@ -1,9 +0,0 @@
-fileFormatVersion: 2
-guid: cbe5d97ed1d75964cab2e2882a52a200
-folderAsset: yes
-timeCreated: 1455489536
-licenseType: Free
-DefaultImporter:
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 

+ 1 - 1
spine-unity/Assets/spine-unity/BoneFollower.cs

@@ -73,7 +73,7 @@ namespace Spine.Unity {
 		bool skeletonTransformIsParent;
 
 		/// <summary>
-		/// Sets the target bone by its bone name. Returns false if no bone was found.</summary>
+		/// Sets the target bone by its bone name. Returns false if no bone was found. To set the bone by reference, use BoneFollower.bone directly.</summary>
 		public bool SetBone (string name) {
 			bone = skeletonRenderer.skeleton.FindBone(name);
 			if (bone == null) {

+ 366 - 366
spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs → spine-unity/Assets/spine-unity/Editor/AtlasAssetInspector.cs

@@ -1,366 +1,366 @@
-/******************************************************************************
- * Spine Runtimes Software License v2.5
- *
- * Copyright (c) 2013-2016, Esoteric Software
- * All rights reserved.
- *
- * You are granted a perpetual, non-exclusive, non-sublicensable, and
- * non-transferable license to use, install, execute, and perform the Spine
- * Runtimes software and derivative works solely for personal or internal
- * use. Without the written permission of Esoteric Software (see Section 2 of
- * the Spine Software License Agreement), you may not (a) modify, translate,
- * adapt, or develop new applications using the Spine Runtimes or otherwise
- * create derivative works or improvements of the Spine Runtimes or (b) remove,
- * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
- * or other intellectual property or proprietary rights notices on or in the
- * Software, including any copy thereof. Redistributions in binary or source
- * form must include this license and terms.
- *
- * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
- * USE, DATA, OR PROFITS) 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.
- *****************************************************************************/
-
-//#define BAKE_ALL_BUTTON
-//#define REGION_BAKING_MESH
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using UnityEditor;
-using UnityEngine;
-using Spine;
-
-namespace Spine.Unity.Editor {
-	using Event = UnityEngine.Event;
-
-	[CustomEditor(typeof(AtlasAsset)), CanEditMultipleObjects]
-	public class AtlasAssetInspector : UnityEditor.Editor {
-		SerializedProperty atlasFile, materials;
-		AtlasAsset atlasAsset;
-
-		GUIContent spriteSlicesLabel;
-		GUIContent SpriteSlicesLabel {
-			get {
-				if (spriteSlicesLabel == null) {
-					spriteSlicesLabel = new GUIContent(
-						"Apply Regions as Texture Sprite Slices",
-						SpineEditorUtilities.Icons.unity,
-						"Adds Sprite slices to atlas texture(s). " +
-						"Updates existing slices if ones with matching names exist. \n\n" +
-						"If your atlas was exported with Premultiply Alpha, " +
-						"your SpriteRenderer should use the generated Spine _Material asset (or any Material with a PMA shader) instead of Sprites-Default.");
-				}
-				return spriteSlicesLabel; 
-			}
-		}
-
-		static List<AtlasRegion> GetRegions (Atlas atlas) {
-			FieldInfo regionsField = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.NonPublic);
-			return (List<AtlasRegion>)regionsField.GetValue(atlas);
-		}
-
-		void OnEnable () {
-			SpineEditorUtilities.ConfirmInitialization();
-			atlasFile = serializedObject.FindProperty("atlasFile");
-			materials = serializedObject.FindProperty("materials");
-			materials.isExpanded = true;
-			atlasAsset = (AtlasAsset)target;
-			#if REGION_BAKING_MESH
-			UpdateBakedList();
-			#endif
-		}
-
-		#if REGION_BAKING_MESH
-		private List<bool> baked;
-		private List<GameObject> bakedObjects;
-
-		void UpdateBakedList () {
-			AtlasAsset asset = (AtlasAsset)target;
-			baked = new List<bool>();
-			bakedObjects = new List<GameObject>();
-			if (atlasFile.objectReferenceValue != null) {
-				List<AtlasRegion> regions = this.Regions;
-				string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
-				string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
-				string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
-				for (int i = 0; i < regions.Count; i++) {
-					AtlasRegion region = regions[i];
-					string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
-					GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
-					baked.Add(prefab != null);
-					bakedObjects.Add(prefab);
-				}
-			}
-		}
-		#endif
-
-		override public void OnInspectorGUI () {
-			if (serializedObject.isEditingMultipleObjects) {
-				DrawDefaultInspector();
-				return;
-			}
-
-			serializedObject.Update();
-			atlasAsset = atlasAsset ?? (AtlasAsset)target;
-			EditorGUI.BeginChangeCheck();
-			EditorGUILayout.PropertyField(atlasFile);
-			EditorGUILayout.PropertyField(materials, true);
-			if (EditorGUI.EndChangeCheck()) {
-				serializedObject.ApplyModifiedProperties();
-				atlasAsset.Clear();
-				atlasAsset.GetAtlas();
-			}
-
-			if (materials.arraySize == 0) {
-				EditorGUILayout.HelpBox("No materials", MessageType.Error);
-				return;
-			}
-
-			for (int i = 0; i < materials.arraySize; i++) {
-				SerializedProperty prop = materials.GetArrayElementAtIndex(i);
-				Material mat = (Material)prop.objectReferenceValue;
-				if (mat == null) {
-					EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
-					return;
-				}
-			}
-
-			EditorGUILayout.Space();
-			if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Set Mipmap Bias to " + SpineEditorUtilities.DEFAULT_MIPMAPBIAS))) {
-				foreach (var m in atlasAsset.materials) {
-					var texture = m.mainTexture;
-					texture.mipMapBias = SpineEditorUtilities.DEFAULT_MIPMAPBIAS;
-				}
-				Debug.Log("Texture mipmap bias set to " + SpineEditorUtilities.DEFAULT_MIPMAPBIAS);
-			}
-
-			EditorGUILayout.Space();
-			if (atlasFile.objectReferenceValue != null) {
-				if (SpineInspectorUtility.LargeCenteredButton(SpriteSlicesLabel)) {
-					var atlas = atlasAsset.GetAtlas();
-					foreach (var m in atlasAsset.materials)
-						UpdateSpriteSlices(m.mainTexture, atlas);
-				}
-			}
-
-			EditorGUILayout.Space();
-
-			#if REGION_BAKING_MESH
-			if (atlasFile.objectReferenceValue != null) {
-				Atlas atlas = asset.GetAtlas();
-				FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
-				List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
-				EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
-				EditorGUI.indentLevel++;
-				AtlasPage lastPage = null;
-				for (int i = 0; i < regions.Count; i++) {
-					if (lastPage != regions[i].page) {
-						if (lastPage != null) {
-							EditorGUILayout.Separator();
-							EditorGUILayout.Separator();
-						}
-						lastPage = regions[i].page;
-						Material mat = ((Material)lastPage.rendererObject);
-						if (mat != null) {
-							GUILayout.BeginHorizontal();
-							{
-								EditorGUI.BeginDisabledGroup(true);
-								EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
-								EditorGUI.EndDisabledGroup();
-							}
-							GUILayout.EndHorizontal();
-
-						} else {
-							EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
-						}
-					}
-					GUILayout.BeginHorizontal();
-					{
-						//EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
-						bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft("    " + regions[i].name, baked[i]);
-						if(baked[i]){
-							EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
-						}
-						if (result && !baked[i]) {
-							//bake
-							baked[i] = true;
-							bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
-							EditorGUIUtility.PingObject(bakedObjects[i]);
-						} else if (!result && baked[i]) {
-							//unbake
-							bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
-							switch (unbakeResult) {
-							case true:
-								//delete
-								string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
-								string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
-								string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
-								string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
-								AssetDatabase.DeleteAsset(bakedPrefabPath);
-								baked[i] = false;
-								break;
-							case false:
-								//do nothing
-								break;
-							}
-						}
-					}
-					GUILayout.EndHorizontal();
-				}
-				EditorGUI.indentLevel--;
-
-				#if BAKE_ALL_BUTTON
-				// Check state
-				bool allBaked = true;
-				bool allUnbaked = true;
-				for (int i = 0; i < regions.Count; i++) {
-					allBaked &= baked[i];
-					allUnbaked &= !baked[i];
-				}
-
-				if (!allBaked && GUILayout.Button("Bake All")) {
-					for (int i = 0; i < regions.Count; i++) {
-						if (!baked[i]) {
-							baked[i] = true;
-							bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
-						}
-					}
-
-				} else if (!allUnbaked && GUILayout.Button("Unbake All")) {
-					bool unbakeResult = EditorUtility.DisplayDialog("Delete All Baked Regions", "Are you sure you want to unbake all region prefabs? This cannot be undone.", "Yes", "Cancel");
-					switch (unbakeResult) {
-					case true:
-						//delete
-						for (int i = 0; i < regions.Count; i++) {
-							if (baked[i]) {
-								string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
-								string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
-								string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
-								string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
-								AssetDatabase.DeleteAsset(bakedPrefabPath);
-								baked[i] = false;
-							}
-						}
-						break;
-					case false:
-						//do nothing
-						break;
-					}
-
-				}
-				#endif
-				
-			}
-			#else
-			if (atlasFile.objectReferenceValue != null) {
-				EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
-				int baseIndent = EditorGUI.indentLevel;
-
-				var regions = AtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
-				AtlasPage lastPage = null;
-				for (int i = 0; i < regions.Count; i++) {
-					if (lastPage != regions[i].page) {
-						if (lastPage != null) {
-							EditorGUILayout.Separator();
-							EditorGUILayout.Separator();
-						}
-						lastPage = regions[i].page;
-						Material mat = ((Material)lastPage.rendererObject);
-						if (mat != null) {
-							EditorGUI.indentLevel = baseIndent;
-							using (new GUILayout.HorizontalScope())
-							using (new EditorGUI.DisabledGroupScope(true))
-								EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
-							EditorGUI.indentLevel = baseIndent + 1;
-						} else {
-							EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
-						}
-					}
-
-					EditorGUILayout.LabelField(new GUIContent(regions[i].name, SpineEditorUtilities.Icons.image));
-				}
-				EditorGUI.indentLevel = baseIndent;
-			}
-			#endif
-
-			if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
-				atlasAsset.Clear();
-		}
-
-		static public void UpdateSpriteSlices (Texture texture, Atlas atlas) {
-			string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
-			var t = (TextureImporter)TextureImporter.GetAtPath(texturePath);
-			t.spriteImportMode = SpriteImportMode.Multiple;
-			var spriteSheet = t.spritesheet;
-			var sprites = new List<SpriteMetaData>(spriteSheet);
-
-			var regions = AtlasAssetInspector.GetRegions(atlas);
-			char[] FilenameDelimiter = {'.'};
-			int updatedCount = 0;
-			int addedCount = 0;
-
-			foreach (var r in regions) {
-				string pageName = r.page.name.Split(FilenameDelimiter, StringSplitOptions.RemoveEmptyEntries)[0];
-				string textureName = texture.name;
-				bool pageMatch = string.Equals(pageName, textureName, StringComparison.Ordinal);
-
-//				if (pageMatch) {
-//					int pw = r.page.width;
-//					int ph = r.page.height;
-//					bool mismatchSize = pw != texture.width || pw > t.maxTextureSize || ph != texture.height || ph > t.maxTextureSize;
-//					if (mismatchSize)
-//						Debug.LogWarningFormat("Size mismatch found.\nExpected atlas size is {0}x{1}. Texture Import Max Size of texture '{2}'({4}x{5}) is currently set to {3}.", pw, ph, texture.name, t.maxTextureSize, texture.width, texture.height);
-//				}
-
-				int spriteIndex = pageMatch ? sprites.FindIndex(
-					(s) => string.Equals(s.name, r.name, StringComparison.Ordinal)
-				) : -1;
-				bool spriteNameMatchExists = spriteIndex >= 0;
-
-				if (pageMatch) {
-					Rect spriteRect = new Rect();
-
-					if (r.rotate) {
-						spriteRect.width = r.height;
-						spriteRect.height = r.width;
-					} else {
-						spriteRect.width = r.width;
-						spriteRect.height = r.height;
-					}
-					spriteRect.x = r.x;
-					spriteRect.y = r.page.height - spriteRect.height - r.y;
-
-					if (spriteNameMatchExists) {
-						var s = sprites[spriteIndex];
-						s.rect = spriteRect;
-						sprites[spriteIndex] = s;
-						updatedCount++;
-					} else {
-						sprites.Add(new SpriteMetaData {
-							name = r.name,
-							pivot = new Vector2(0.5f, 0.5f),
-							rect = spriteRect
-						});
-						addedCount++;
-					}
-				}
-
-			}
-
-			t.spritesheet = sprites.ToArray();
-			EditorUtility.SetDirty(t);
-			AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate);
-			EditorGUIUtility.PingObject(texture);
-			Debug.Log(string.Format("Applied sprite slices to {2}. {0} added. {1} updated.", addedCount, updatedCount, texture.name));
-		}
-	}
-
-}
+/******************************************************************************
+ * Spine Runtimes Software License v2.5
+ *
+ * Copyright (c) 2013-2016, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable, and
+ * non-transferable license to use, install, execute, and perform the Spine
+ * Runtimes software and derivative works solely for personal or internal
+ * use. Without the written permission of Esoteric Software (see Section 2 of
+ * the Spine Software License Agreement), you may not (a) modify, translate,
+ * adapt, or develop new applications using the Spine Runtimes or otherwise
+ * create derivative works or improvements of the Spine Runtimes or (b) remove,
+ * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
+ * USE, DATA, OR PROFITS) 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.
+ *****************************************************************************/
+
+//#define BAKE_ALL_BUTTON
+//#define REGION_BAKING_MESH
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEditor;
+using UnityEngine;
+using Spine;
+
+namespace Spine.Unity.Editor {
+	using Event = UnityEngine.Event;
+
+	[CustomEditor(typeof(AtlasAsset)), CanEditMultipleObjects]
+	public class AtlasAssetInspector : UnityEditor.Editor {
+		SerializedProperty atlasFile, materials;
+		AtlasAsset atlasAsset;
+
+		GUIContent spriteSlicesLabel;
+		GUIContent SpriteSlicesLabel {
+			get {
+				if (spriteSlicesLabel == null) {
+					spriteSlicesLabel = new GUIContent(
+						"Apply Regions as Texture Sprite Slices",
+						SpineEditorUtilities.Icons.unity,
+						"Adds Sprite slices to atlas texture(s). " +
+						"Updates existing slices if ones with matching names exist. \n\n" +
+						"If your atlas was exported with Premultiply Alpha, " +
+						"your SpriteRenderer should use the generated Spine _Material asset (or any Material with a PMA shader) instead of Sprites-Default.");
+				}
+				return spriteSlicesLabel; 
+			}
+		}
+
+		static List<AtlasRegion> GetRegions (Atlas atlas) {
+			FieldInfo regionsField = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.NonPublic);
+			return (List<AtlasRegion>)regionsField.GetValue(atlas);
+		}
+
+		void OnEnable () {
+			SpineEditorUtilities.ConfirmInitialization();
+			atlasFile = serializedObject.FindProperty("atlasFile");
+			materials = serializedObject.FindProperty("materials");
+			materials.isExpanded = true;
+			atlasAsset = (AtlasAsset)target;
+			#if REGION_BAKING_MESH
+			UpdateBakedList();
+			#endif
+		}
+
+		#if REGION_BAKING_MESH
+		private List<bool> baked;
+		private List<GameObject> bakedObjects;
+
+		void UpdateBakedList () {
+			AtlasAsset asset = (AtlasAsset)target;
+			baked = new List<bool>();
+			bakedObjects = new List<GameObject>();
+			if (atlasFile.objectReferenceValue != null) {
+				List<AtlasRegion> regions = this.Regions;
+				string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
+				string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
+				string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
+				for (int i = 0; i < regions.Count; i++) {
+					AtlasRegion region = regions[i];
+					string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
+					GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
+					baked.Add(prefab != null);
+					bakedObjects.Add(prefab);
+				}
+			}
+		}
+		#endif
+
+		override public void OnInspectorGUI () {
+			if (serializedObject.isEditingMultipleObjects) {
+				DrawDefaultInspector();
+				return;
+			}
+
+			serializedObject.Update();
+			atlasAsset = atlasAsset ?? (AtlasAsset)target;
+			EditorGUI.BeginChangeCheck();
+			EditorGUILayout.PropertyField(atlasFile);
+			EditorGUILayout.PropertyField(materials, true);
+			if (EditorGUI.EndChangeCheck()) {
+				serializedObject.ApplyModifiedProperties();
+				atlasAsset.Clear();
+				atlasAsset.GetAtlas();
+			}
+
+			if (materials.arraySize == 0) {
+				EditorGUILayout.HelpBox("No materials", MessageType.Error);
+				return;
+			}
+
+			for (int i = 0; i < materials.arraySize; i++) {
+				SerializedProperty prop = materials.GetArrayElementAtIndex(i);
+				var material = (Material)prop.objectReferenceValue;
+				if (material == null) {
+					EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
+					return;
+				}
+			}
+
+			EditorGUILayout.Space();
+			if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Set Mipmap Bias to " + SpineEditorUtilities.DEFAULT_MIPMAPBIAS))) {
+				foreach (var m in atlasAsset.materials) {
+					var texture = m.mainTexture;
+					texture.mipMapBias = SpineEditorUtilities.DEFAULT_MIPMAPBIAS;
+				}
+				Debug.Log("Texture mipmap bias set to " + SpineEditorUtilities.DEFAULT_MIPMAPBIAS);
+			}
+
+			EditorGUILayout.Space();
+			if (atlasFile.objectReferenceValue != null) {
+				if (SpineInspectorUtility.LargeCenteredButton(SpriteSlicesLabel)) {
+					var atlas = atlasAsset.GetAtlas();
+					foreach (var m in atlasAsset.materials)
+						UpdateSpriteSlices(m.mainTexture, atlas);
+				}
+			}
+
+			EditorGUILayout.Space();
+
+			#if REGION_BAKING_MESH
+			if (atlasFile.objectReferenceValue != null) {
+				Atlas atlas = asset.GetAtlas();
+				FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
+				List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
+				EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
+				EditorGUI.indentLevel++;
+				AtlasPage lastPage = null;
+				for (int i = 0; i < regions.Count; i++) {
+					if (lastPage != regions[i].page) {
+						if (lastPage != null) {
+							EditorGUILayout.Separator();
+							EditorGUILayout.Separator();
+						}
+						lastPage = regions[i].page;
+						Material mat = ((Material)lastPage.rendererObject);
+						if (mat != null) {
+							GUILayout.BeginHorizontal();
+							{
+								EditorGUI.BeginDisabledGroup(true);
+								EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
+								EditorGUI.EndDisabledGroup();
+							}
+							GUILayout.EndHorizontal();
+
+						} else {
+							EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
+						}
+					}
+					GUILayout.BeginHorizontal();
+					{
+						//EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
+						bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft("    " + regions[i].name, baked[i]);
+						if(baked[i]){
+							EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
+						}
+						if (result && !baked[i]) {
+							//bake
+							baked[i] = true;
+							bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
+							EditorGUIUtility.PingObject(bakedObjects[i]);
+						} else if (!result && baked[i]) {
+							//unbake
+							bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
+							switch (unbakeResult) {
+							case true:
+								//delete
+								string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
+								string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
+								string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
+								string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
+								AssetDatabase.DeleteAsset(bakedPrefabPath);
+								baked[i] = false;
+								break;
+							case false:
+								//do nothing
+								break;
+							}
+						}
+					}
+					GUILayout.EndHorizontal();
+				}
+				EditorGUI.indentLevel--;
+
+				#if BAKE_ALL_BUTTON
+				// Check state
+				bool allBaked = true;
+				bool allUnbaked = true;
+				for (int i = 0; i < regions.Count; i++) {
+					allBaked &= baked[i];
+					allUnbaked &= !baked[i];
+				}
+
+				if (!allBaked && GUILayout.Button("Bake All")) {
+					for (int i = 0; i < regions.Count; i++) {
+						if (!baked[i]) {
+							baked[i] = true;
+							bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
+						}
+					}
+
+				} else if (!allUnbaked && GUILayout.Button("Unbake All")) {
+					bool unbakeResult = EditorUtility.DisplayDialog("Delete All Baked Regions", "Are you sure you want to unbake all region prefabs? This cannot be undone.", "Yes", "Cancel");
+					switch (unbakeResult) {
+					case true:
+						//delete
+						for (int i = 0; i < regions.Count; i++) {
+							if (baked[i]) {
+								string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
+								string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
+								string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
+								string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
+								AssetDatabase.DeleteAsset(bakedPrefabPath);
+								baked[i] = false;
+							}
+						}
+						break;
+					case false:
+						//do nothing
+						break;
+					}
+
+				}
+				#endif
+				
+			}
+			#else
+			if (atlasFile.objectReferenceValue != null) {
+				EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
+				int baseIndent = EditorGUI.indentLevel;
+
+				var regions = AtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
+				AtlasPage lastPage = null;
+				for (int i = 0; i < regions.Count; i++) {
+					if (lastPage != regions[i].page) {
+						if (lastPage != null) {
+							EditorGUILayout.Separator();
+							EditorGUILayout.Separator();
+						}
+						lastPage = regions[i].page;
+						Material mat = ((Material)lastPage.rendererObject);
+						if (mat != null) {
+							EditorGUI.indentLevel = baseIndent;
+							using (new GUILayout.HorizontalScope())
+							using (new EditorGUI.DisabledGroupScope(true))
+								EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
+							EditorGUI.indentLevel = baseIndent + 1;
+						} else {
+							EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
+						}
+					}
+
+					EditorGUILayout.LabelField(new GUIContent(regions[i].name, SpineEditorUtilities.Icons.image));
+				}
+				EditorGUI.indentLevel = baseIndent;
+			}
+			#endif
+
+			if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
+				atlasAsset.Clear();
+		}
+
+		static public void UpdateSpriteSlices (Texture texture, Atlas atlas) {
+			string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
+			var t = (TextureImporter)TextureImporter.GetAtPath(texturePath);
+			t.spriteImportMode = SpriteImportMode.Multiple;
+			var spriteSheet = t.spritesheet;
+			var sprites = new List<SpriteMetaData>(spriteSheet);
+
+			var regions = AtlasAssetInspector.GetRegions(atlas);
+			char[] FilenameDelimiter = {'.'};
+			int updatedCount = 0;
+			int addedCount = 0;
+
+			foreach (var r in regions) {
+				string pageName = r.page.name.Split(FilenameDelimiter, StringSplitOptions.RemoveEmptyEntries)[0];
+				string textureName = texture.name;
+				bool pageMatch = string.Equals(pageName, textureName, StringComparison.Ordinal);
+
+//				if (pageMatch) {
+//					int pw = r.page.width;
+//					int ph = r.page.height;
+//					bool mismatchSize = pw != texture.width || pw > t.maxTextureSize || ph != texture.height || ph > t.maxTextureSize;
+//					if (mismatchSize)
+//						Debug.LogWarningFormat("Size mismatch found.\nExpected atlas size is {0}x{1}. Texture Import Max Size of texture '{2}'({4}x{5}) is currently set to {3}.", pw, ph, texture.name, t.maxTextureSize, texture.width, texture.height);
+//				}
+
+				int spriteIndex = pageMatch ? sprites.FindIndex(
+					(s) => string.Equals(s.name, r.name, StringComparison.Ordinal)
+				) : -1;
+				bool spriteNameMatchExists = spriteIndex >= 0;
+
+				if (pageMatch) {
+					Rect spriteRect = new Rect();
+
+					if (r.rotate) {
+						spriteRect.width = r.height;
+						spriteRect.height = r.width;
+					} else {
+						spriteRect.width = r.width;
+						spriteRect.height = r.height;
+					}
+					spriteRect.x = r.x;
+					spriteRect.y = r.page.height - spriteRect.height - r.y;
+
+					if (spriteNameMatchExists) {
+						var s = sprites[spriteIndex];
+						s.rect = spriteRect;
+						sprites[spriteIndex] = s;
+						updatedCount++;
+					} else {
+						sprites.Add(new SpriteMetaData {
+							name = r.name,
+							pivot = new Vector2(0.5f, 0.5f),
+							rect = spriteRect
+						});
+						addedCount++;
+					}
+				}
+
+			}
+
+			t.spritesheet = sprites.ToArray();
+			EditorUtility.SetDirty(t);
+			AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate);
+			EditorGUIUtility.PingObject(texture);
+			Debug.Log(string.Format("Applied sprite slices to {2}. {0} added. {1} updated.", addedCount, updatedCount, texture.name));
+		}
+	}
+
+}

+ 0 - 0
spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs.meta → spine-unity/Assets/spine-unity/Editor/AtlasAssetInspector.cs.meta


+ 0 - 0
spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs → spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs


+ 0 - 0
spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs.meta → spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs.meta


+ 7 - 1
spine-unity/Assets/spine-unity/ISkeletonAnimation.cs

@@ -37,10 +37,16 @@ namespace Spine.Unity {
 		event UpdateBonesDelegate UpdateWorld;
 		event UpdateBonesDelegate UpdateComplete;
 
-		void LateUpdate ();
+		//void LateUpdate ();
 		Skeleton Skeleton { get; }
 	}
 
+	/// <summary>Holds a reference to a SkeletonDataAsset.</summary>
+	public interface ISkeletonDataAssetComponent {
+		/// <summary>Gets the SkeletonDataAsset of the Spine Component.</summary>
+		SkeletonDataAsset SkeletonDataAsset { get; }
+	}
+
 	/// <summary>A Spine-Unity Component that manages a Spine.Skeleton instance, instantiated from a SkeletonDataAsset.</summary>
 	public interface ISkeletonComponent {
 		/// <summary>Gets the SkeletonDataAsset of the Spine Component.</summary>

+ 7 - 1
spine-unity/Assets/spine-unity/Mesh Generation/SpineMesh.cs

@@ -501,6 +501,7 @@ namespace Spine.Unity {
 
 				Color c = default(Color);
 
+				// Identify and prepare values.
 				var region = attachment as RegionAttachment;
 				if (region != null) {
 					region.ComputeWorldVertices(slot.bone, workingVerts, 0);
@@ -531,6 +532,9 @@ namespace Spine.Unity {
 								continue;
 							}
 						}
+
+						// If not any renderable attachment.
+						clipper.ClipEnd(slot);
 						continue;
 					}
 				}
@@ -557,6 +561,7 @@ namespace Spine.Unity {
 					uvs = clipper.clippedUVs.Items;
 				}
 
+				// Actually add slot/attachment data into buffers.
 				if (attachmentVertexCount != 0 && attachmentIndexCount != 0) {
 					if (tintBlack)
 						AddAttachmentTintBlack(slot.r2, slot.g2, slot.b2, attachmentVertexCount);
@@ -633,6 +638,7 @@ namespace Spine.Unity {
 							submeshItems[oldTriangleCount + i] = attachmentTriangleIndices[i] + ovc;
 					}
 				}
+
 				clipper.ClipEnd(slot);
 			}
 			clipper.ClipEnd();
@@ -1155,7 +1161,7 @@ namespace Spine.Unity {
 			doubleBufferedMesh = new DoubleBuffered<SmartMesh>();
 		}
 
-		public Material[] GetUpdatedShaderdMaterialsArray () {
+		public Material[] GetUpdatedSharedMaterialsArray () {
 			if (submeshMaterials.Count == sharedMaterials.Length)
 				submeshMaterials.CopyTo(sharedMaterials);
 			else

+ 1 - 0
spine-unity/Assets/spine-unity/Modules/AttachmentTools/AttachmentTools.cs

@@ -486,6 +486,7 @@ namespace Spine.Unity.Modules.AttachmentTools {
 		/// Creates and populates a duplicate skin with cloned attachments that are backed by a new packed texture atlas comprised of all the regions from the original skin.</summary>
 		/// <remarks>No Spine.Atlas object is created so there is no way to find AtlasRegions except through the Attachments using them.</remarks>
 		public static Skin GetRepackedSkin (this Skin o, string newName, Shader shader, out Material outputMaterial, out Texture2D outputTexture, int maxAtlasSize = 1024, int padding = 2, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps, Material materialPropertySource = null, bool clearCache = false) {
+			if (o == null) throw new System.NullReferenceException("Skin was null");
 			var skinAttachments = o.Attachments;
 			var newSkin = new Skin(newName);
 

+ 1 - 1
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs

@@ -35,7 +35,7 @@ using Spine;
 namespace Spine.Unity {
 	[ExecuteInEditMode, RequireComponent(typeof(CanvasRenderer), typeof(RectTransform)), DisallowMultipleComponent]
 	[AddComponentMenu("Spine/SkeletonGraphic (Unity UI Canvas)")]
-	public class SkeletonGraphic : MaskableGraphic, ISkeletonComponent, IAnimationStateComponent, ISkeletonAnimation {
+	public class SkeletonGraphic : MaskableGraphic, ISkeletonComponent, IAnimationStateComponent, ISkeletonAnimation, ISkeletonDataAssetComponent {
 
 		#region Inspector
 		public SkeletonDataAsset skeletonDataAsset;

+ 2 - 2
spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs

@@ -112,9 +112,9 @@ namespace Spine.Unity.Modules {
 				meshGenerator.FillVertexData(mesh);
 				if (updateTriangles) {
 					meshGenerator.FillTriangles(mesh);
-					meshRenderer.sharedMaterials = buffers.GetUpdatedShaderdMaterialsArray();
+					meshRenderer.sharedMaterials = buffers.GetUpdatedSharedMaterialsArray();
 				} else if (buffers.MaterialsChangedInLastUpdate()) {
-					meshRenderer.sharedMaterials = buffers.GetUpdatedShaderdMaterialsArray();
+					meshRenderer.sharedMaterials = buffers.GetUpdatedSharedMaterialsArray();
 				}
 			}
 

+ 5 - 0
spine-unity/Assets/spine-unity/SkeletonAnimation.cs

@@ -126,11 +126,16 @@ namespace Spine.Unity {
 		}
 		#endregion
 
+		/// <summary>
+		/// Clears the previously generated mesh, resets the skeleton's pose, and clears all previously active animations.</summary>
 		public override void ClearState () {
 			base.ClearState();
 			if (state != null) state.ClearTracks();
 		}
 
+		/// <summary>
+		/// Initialize this component. Attempts to load the SkeletonData and creates the internal Spine objects and buffers.</summary>
+		/// <param name="overwrite">If set to <c>true</c>, force overwrite an already initialized object.</param>
 		public override void Initialize (bool overwrite) {
 			if (valid && !overwrite)
 				return;

+ 10 - 3
spine-unity/Assets/spine-unity/SkeletonRenderer.cs

@@ -38,7 +38,7 @@ namespace Spine.Unity {
 	/// <summary>Renders a skeleton.</summary>
 	[ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer)), DisallowMultipleComponent]
 	[HelpURL("http://esotericsoftware.com/spine-unity-documentation#Rendering")]
-	public class SkeletonRenderer : MonoBehaviour, ISkeletonComponent {
+	public class SkeletonRenderer : MonoBehaviour, ISkeletonComponent, ISkeletonDataAssetComponent {
 
 		public delegate void SkeletonRendererDelegate (SkeletonRenderer skeletonRenderer);
 		public event SkeletonRendererDelegate OnRebuild;
@@ -163,12 +163,17 @@ namespace Spine.Unity {
 			valid = false;
 		}
 
+		/// <summary>
+		/// Clears the previously generated mesh and resets the skeleton's pose.</summary>
 		public virtual void ClearState () {
 			meshFilter.sharedMesh = null;
 			currentInstructions.Clear();
 			if (skeleton != null) skeleton.SetToSetupPose();
 		}
 
+		/// <summary>
+		/// Initialize this component. Attempts to load the SkeletonData and creates the internal Skeleton object and buffers.</summary>
+		/// <param name="overwrite">If set to <c>true</c>, it will overwrite internal objects if they were already generated. Otherwise, the initialized component will ignore subsequent calls to initialize.</param>
 		public virtual void Initialize (bool overwrite) {
 			if (valid && !overwrite)
 				return;
@@ -219,6 +224,8 @@ namespace Spine.Unity {
 				OnRebuild(this);
 		}
 
+		/// <summary>
+		/// Generates a new UnityEngine.Mesh from the internal Skeleton.</summary>
 		public virtual void LateUpdate () {
 			if (!valid) return;
 
@@ -305,9 +312,9 @@ namespace Spine.Unity {
 			rendererBuffers.UpdateSharedMaterials(workingSubmeshInstructions);
 			if (updateTriangles) { // Check if the triangles should also be updated.
 				meshGenerator.FillTriangles(currentMesh);
-				meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedShaderdMaterialsArray();
+				meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedSharedMaterialsArray();
 			} else if (rendererBuffers.MaterialsChangedInLastUpdate()) {
-				meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedShaderdMaterialsArray();
+				meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedSharedMaterialsArray();
 			}