diff --git a/spine-csharp/src/SkeletonBinary.cs b/spine-csharp/src/SkeletonBinary.cs index f4d3a7e4b..04d65bfa2 100644 --- a/spine-csharp/src/SkeletonBinary.cs +++ b/spine-csharp/src/SkeletonBinary.cs @@ -86,7 +86,13 @@ namespace Spine { using (var input = new BufferedStream(Microsoft.Xna.Framework.TitleContainer.OpenStream(path))) { #else - using (var input = new BufferedStream(new FileStream(path, FileMode.Open))) { +#if UNITY_WP8 || UNITY_WP8_1 + using (var input = new FileStream(path, FileMode.Open)) + { +#else + using (var input = new BufferedStream(new FileStream(path, FileMode.Open))) + { +#endif #endif SkeletonData skeletonData = ReadSkeletonData(input); skeletonData.name = Path.GetFileNameWithoutExtension(path); diff --git a/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs b/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs index f15e773fc..8599c9598 100644 --- a/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs +++ b/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs @@ -18,7 +18,11 @@ public class RaggedySpineboy : MonoBehaviour { void AddRigidbody () { var rb = gameObject.AddComponent(); +#if UNITY_5_1 + rb.freezeRotation = true; +#else rb.fixedAngle = true; +#endif naturalCollider.enabled = true; } diff --git a/spine-unity/Assets/spine-unity/Editor/AssetDatabaseAvailabilityDetector.cs b/spine-unity/Assets/spine-unity/Editor/AssetDatabaseAvailabilityDetector.cs new file mode 100644 index 000000000..5b8c7a4ab --- /dev/null +++ b/spine-unity/Assets/spine-unity/Editor/AssetDatabaseAvailabilityDetector.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +namespace Spine { + public static class AssetDatabaseAvailabilityDetector { + const string MARKER_RESOURCE_NAME = "SpineAssetDatabaseMarker"; + private static bool _isMarkerLoaded; + + public static bool IsAssetDatabaseAvailable (bool forceCheck = false) { + if (!forceCheck && _isMarkerLoaded) + return true; + + TextAsset markerTextAsset = Resources.Load(MARKER_RESOURCE_NAME); + _isMarkerLoaded = markerTextAsset != null; + if (markerTextAsset != null) { + Resources.UnloadAsset(markerTextAsset); + } + + return _isMarkerLoaded; + } + } +} diff --git a/spine-unity/Assets/spine-unity/Editor/AssetDatabaseAvailabilityDetector.cs.meta b/spine-unity/Assets/spine-unity/Editor/AssetDatabaseAvailabilityDetector.cs.meta new file mode 100644 index 000000000..00b99c134 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Editor/AssetDatabaseAvailabilityDetector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 25086cd81e3158b439761b73d7366c47 +timeCreated: 1444587791 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Editor/Resources.meta b/spine-unity/Assets/spine-unity/Editor/Resources.meta new file mode 100644 index 000000000..8d1a705d5 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Editor/Resources.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 24903fdac57ee784b9597fcb751ec22f +folderAsset: yes +timeCreated: 1444565388 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Editor/Resources/SpineAssetDatabaseMarker.txt b/spine-unity/Assets/spine-unity/Editor/Resources/SpineAssetDatabaseMarker.txt new file mode 100644 index 000000000..1a3c1a3ea --- /dev/null +++ b/spine-unity/Assets/spine-unity/Editor/Resources/SpineAssetDatabaseMarker.txt @@ -0,0 +1 @@ +DO NOT MOVE OR DELETE THIS FILE \ No newline at end of file diff --git a/spine-unity/Assets/spine-unity/Editor/Resources/SpineAssetDatabaseMarker.txt.meta b/spine-unity/Assets/spine-unity/Editor/Resources/SpineAssetDatabaseMarker.txt.meta new file mode 100644 index 000000000..7569884b2 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Editor/Resources/SpineAssetDatabaseMarker.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57281c00bdd90ad4392f811f2b9f0da1 +timeCreated: 1444565392 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs index 36dc47ae3..b2ea647ae 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs @@ -149,6 +149,7 @@ public class SpineEditorUtilities : AssetPostprocessor { public static string editorPath = ""; public static string editorGUIPath = ""; + static HashSet assetsImportedInWrongState; static Dictionary skeletonRendererTable; static Dictionary skeletonUtilityBoneTable; static Dictionary boundingBoxFollowerTable; @@ -173,6 +174,7 @@ public class SpineEditorUtilities : AssetPostprocessor { Icons.Initialize(); + assetsImportedInWrongState = new HashSet(); skeletonRendererTable = new Dictionary(); skeletonUtilityBoneTable = new Dictionary(); boundingBoxFollowerTable = new Dictionary(); @@ -254,8 +256,34 @@ public class SpineEditorUtilities : AssetPostprocessor { } static void OnPostprocessAllAssets (string[] imported, string[] deleted, string[] moved, string[] movedFromAssetPaths) { - ImportSpineContent(imported, false); + if (imported.Length == 0) + return; + + // In case user used "Assets -> Reimport All", during the import process, + // asset database is not initialized until some point. During that period, + // all attempts to load any assets using API (i.e. AssetDatabase.LoadAssetAtPath) + // will return null, and as result, assets won't be loaded even if they actually exists, + // which may lead to numerous importing errors. + // This situation also happens if Library folder is deleted from the project, which is a pretty + // common case, since when using version control systems, the Library folder must be excluded. + // + // So to avoid this, in case asset database is not available, we delay loading the assets + // until next time. + // + // Unity *always* reimports some internal assets after the process is done, so this method + // is always called once again in a state when asset database is available. + // + // Checking whether AssetDatabase is initialized is done by attempting to load + // a known "marker" asset that should always be available. Failing to load this asset + // means that AssetDatabase is not initialized. + assetsImportedInWrongState.UnionWith(imported); + if (AssetDatabaseAvailabilityDetector.IsAssetDatabaseAvailable()) { + string[] combinedAssets = assetsImportedInWrongState.ToArray(); + assetsImportedInWrongState.Clear(); + ImportSpineContent(combinedAssets); + } } + public static void ImportSpineContent (string[] imported, bool reimport = false) { List atlasPaths = new List(); List imagePaths = new List(); @@ -408,14 +436,34 @@ public class SpineEditorUtilities : AssetPostprocessor { skeletonDataAsset.Reset(); string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(skeletonDataAsset)); - string lastHash = EditorPrefs.GetString(guid + "_hash"); - - if (lastHash != skeletonDataAsset.GetSkeletonData(true).Hash) { + string lastHash = EditorPrefs.GetString(guid + "_hash"); + + // For some weird reason sometimes Unity loses the internal Object pointer, + // and as a result, all comparisons with null returns true. + // But the C# wrapper is still alive, so we can "restore" the object + // by reloading it from its Instance ID. + AtlasAsset[] skeletonDataAtlasAssets = skeletonDataAsset.atlasAssets; + if (skeletonDataAtlasAssets != null) { + for (int i = 0; i < skeletonDataAtlasAssets.Length; i++) { + if (!ReferenceEquals(null, skeletonDataAtlasAssets[i]) && + skeletonDataAtlasAssets[i].Equals(null) && + skeletonDataAtlasAssets[i].GetInstanceID() != 0 + ) { + skeletonDataAtlasAssets[i] = EditorUtility.InstanceIDToObject(skeletonDataAtlasAssets[i].GetInstanceID()) as AtlasAsset; + } + } + } + + SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true); + string currentHash = skeletonData != null ? skeletonData.Hash : null; + if (currentHash == null || lastHash != currentHash) { //do any upkeep on synchronized assets UpdateMecanimClips(skeletonDataAsset); } - EditorPrefs.SetString(guid + "_hash", skeletonDataAsset.GetSkeletonData(true).Hash); + if (currentHash != null) { + EditorPrefs.SetString(guid + "_hash", currentHash); + } } } } diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs index cd8d7726a..0fb1b9482 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs @@ -102,7 +102,8 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { if (mode == MixMode.AlwaysMix) { //always use Mix instead of Applying the first non-zero weighted clip - foreach (var info in clipInfo) { + for (int c = 0; c < clipInfo.Length; c++) { + var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue; @@ -111,13 +112,16 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); } - foreach (var info in nextClipInfo) { - float weight = info.weight * layerWeight; - if (weight == 0) - continue; + if (nextStateInfo.fullPathHash != 0) { + for (int c = 0; c < nextClipInfo.Length; c++) { + var info = nextClipInfo[c]; + float weight = info.weight * layerWeight; + if (weight == 0) + continue; - float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); + float time = nextStateInfo.normalizedTime * info.clip.length; + animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); + } } } else if (mode >= MixMode.MixNext) { //apply first non-zero weighted clip @@ -147,8 +151,22 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { c = 0; - //apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights) - if (mode == MixMode.SpineStyle) { + if (nextStateInfo.fullPathHash != 0) { + //apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights) + if (mode == MixMode.SpineStyle) { + for (; c < nextClipInfo.Length; c++) { + var info = nextClipInfo[c]; + float weight = info.weight * layerWeight; + if (weight == 0) + continue; + + float time = nextStateInfo.normalizedTime * info.clip.length; + animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null); + break; + } + } + + //mix the rest for (; c < nextClipInfo.Length; c++) { var info = nextClipInfo[c]; float weight = info.weight * layerWeight; @@ -156,21 +174,9 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null); - break; + animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); } } - - //mix the rest - for (; c < nextClipInfo.Length; c++) { - var info = nextClipInfo[c]; - float weight = info.weight * layerWeight; - if (weight == 0) - continue; - - float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); - } } } diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index 3a36eded3..de919317e 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -71,7 +71,7 @@ public class SkeletonRenderer : MonoBehaviour { private readonly ExposedList submeshMaterials = new ExposedList(); private readonly ExposedList submeshes = new ExposedList(); private SkeletonUtilitySubmeshRenderer[] submeshRenderers; - private LastState lastState = new LastState(); + private MeshState meshState = new MeshState(); public virtual void Reset () { if (meshFilter != null) @@ -94,7 +94,7 @@ public class SkeletonRenderer : MonoBehaviour { DestroyImmediate(mesh2); } - lastState = new LastState(); + meshState = new MeshState(); mesh1 = null; mesh2 = null; vertices = null; @@ -193,15 +193,11 @@ public class SkeletonRenderer : MonoBehaviour { bool renderMeshes = this.renderMeshes; // Clear last state of attachments and submeshes - ExposedList attachmentsTriangleCountTemp = lastState.attachmentsTriangleCountTemp; - attachmentsTriangleCountTemp.GrowIfNeeded(drawOrderCount); - attachmentsTriangleCountTemp.Count = drawOrderCount; - ExposedList attachmentsFlipStateTemp = lastState.attachmentsFlipStateTemp; - attachmentsFlipStateTemp.GrowIfNeeded(drawOrderCount); - attachmentsFlipStateTemp.Count = drawOrderCount; + MeshState.SingleMeshState stateTemp = meshState.stateTemp; + stateTemp.attachments.Clear(true); + stateTemp.UpdateDrawOrderCount(drawOrderCount); - ExposedList addSubmeshArgumentsTemp = lastState.addSubmeshArgumentsTemp; - addSubmeshArgumentsTemp.Clear(false); + stateTemp.addSubmeshArguments.Clear(false); for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; Bone bone = slot.bone; @@ -214,9 +210,9 @@ public class SkeletonRenderer : MonoBehaviour { bool worldScaleIsSameSigns = (worldScaleXIsPositive && worldScaleYIsPositive) || (!worldScaleXIsPositive && !worldScaleYIsPositive); bool flip = frontFacing && ((bone.worldFlipX != bone.worldFlipY) == worldScaleIsSameSigns); - attachmentsFlipStateTemp.Items[i] = flip; + stateTemp.attachmentsFlipState.Items[i] = flip; - attachmentsTriangleCountTemp.Items[i] = -1; + stateTemp.attachments.Items[i] = attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { rendererObject = regionAttachment.RendererObject; @@ -249,8 +245,8 @@ public class SkeletonRenderer : MonoBehaviour { #endif if ((lastMaterial != null && lastMaterial.GetInstanceID() != material.GetInstanceID()) || (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) { - addSubmeshArgumentsTemp.Add( - new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false) + stateTemp.addSubmeshArguments.Add( + new MeshState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false) ); submeshTriangleCount = 0; submeshFirstVertex = vertexCount; @@ -260,18 +256,16 @@ public class SkeletonRenderer : MonoBehaviour { submeshTriangleCount += attachmentTriangleCount; vertexCount += attachmentVertexCount; - - attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount; } - addSubmeshArgumentsTemp.Add( - new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true) + stateTemp.addSubmeshArguments.Add( + new MeshState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true) ); - bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(attachmentsTriangleCountTemp, attachmentsFlipStateTemp, addSubmeshArgumentsTemp); + bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(stateTemp.attachments, stateTemp.attachmentsFlipState, stateTemp.addSubmeshArguments); if (mustUpdateMeshStructure) { submeshMaterials.Clear(); - for (int i = 0, n = addSubmeshArgumentsTemp.Count; i < n; i++) { - LastState.AddSubmeshArguments arguments = addSubmeshArgumentsTemp.Items[i]; + for (int i = 0, n = stateTemp.addSubmeshArguments.Count; i < n; i++) { + MeshState.AddSubmeshArguments arguments = stateTemp.addSubmeshArguments.Items[i]; AddSubmesh( arguments.material, arguments.startSlot, @@ -279,7 +273,7 @@ public class SkeletonRenderer : MonoBehaviour { arguments.triangleCount, arguments.firstVertex, arguments.lastSubmesh, - attachmentsFlipStateTemp + stateTemp.attachmentsFlipState ); } @@ -305,10 +299,10 @@ public class SkeletonRenderer : MonoBehaviour { } else { // Too many vertices, zero the extra. Vector3 zero = Vector3.zero; - for (int i = vertexCount, n = lastState.vertexCount; i < n; i++) + for (int i = vertexCount, n = meshState.vertexCount; i < n; i++) vertices[i] = zero; } - lastState.vertexCount = vertexCount; + meshState.vertexCount = vertexCount; // Setup mesh. float zSpacing = this.zSpacing; @@ -534,32 +528,21 @@ public class SkeletonRenderer : MonoBehaviour { } // Update previous state - ExposedList attachmentsTriangleCountCurrentMesh; - ExposedList attachmentsFlipStateCurrentMesh; - ExposedList addSubmeshArgumentsCurrentMesh; - if (useMesh1) { - attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1; - addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1; - attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1; - lastState.immutableTrianglesMesh1 = immutableTriangles; - } else { - attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2; - addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2; - attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2; - lastState.immutableTrianglesMesh2 = immutableTriangles; - } + MeshState.SingleMeshState currentMeshState = useMesh1 ? meshState.stateMesh1 : meshState.stateMesh2; + currentMeshState.immutableTriangles = immutableTriangles; - attachmentsTriangleCountCurrentMesh.GrowIfNeeded(attachmentsTriangleCountTemp.Capacity); - attachmentsTriangleCountCurrentMesh.Count = attachmentsTriangleCountTemp.Count; - attachmentsTriangleCountTemp.CopyTo(attachmentsTriangleCountCurrentMesh.Items, 0); + currentMeshState.attachments.Clear(true); + currentMeshState.attachments.GrowIfNeeded(stateTemp.attachments.Capacity); + currentMeshState.attachments.Count = stateTemp.attachments.Count; + stateTemp.attachments.CopyTo(currentMeshState.attachments.Items); - attachmentsFlipStateCurrentMesh.GrowIfNeeded(attachmentsFlipStateTemp.Capacity); - attachmentsFlipStateCurrentMesh.Count = attachmentsFlipStateTemp.Count; - attachmentsFlipStateTemp.CopyTo(attachmentsFlipStateCurrentMesh.Items, 0); + currentMeshState.attachmentsFlipState.GrowIfNeeded(stateTemp.attachmentsFlipState.Capacity); + currentMeshState.attachmentsFlipState.Count = stateTemp.attachmentsFlipState.Count; + stateTemp.attachmentsFlipState.CopyTo(currentMeshState.attachmentsFlipState.Items); - addSubmeshArgumentsCurrentMesh.GrowIfNeeded(addSubmeshArgumentsTemp.Count); - addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count; - addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items); + currentMeshState.addSubmeshArguments.GrowIfNeeded(stateTemp.addSubmeshArguments.Capacity); + currentMeshState.addSubmeshArguments.Count = stateTemp.addSubmeshArguments.Count; + stateTemp.addSubmeshArguments.CopyTo(currentMeshState.addSubmeshArguments.Items); if (submeshRenderers.Length > 0) { for (int i = 0; i < submeshRenderers.Length; i++) { @@ -575,39 +558,33 @@ public class SkeletonRenderer : MonoBehaviour { useMesh1 = !useMesh1; } - private bool CheckIfMustUpdateMeshStructure (ExposedList attachmentsTriangleCountTemp, ExposedList attachmentsFlipStateTemp, ExposedList addSubmeshArgumentsTemp) { + private bool CheckIfMustUpdateMeshStructure (ExposedList attachmentsTemp, ExposedList attachmentsFlipStateTemp, ExposedList addSubmeshArgumentsTemp) { +#if UNITY_EDITOR + if (!Application.isPlaying) + return true; +#endif + // Check if any mesh settings were changed bool mustUpdateMeshStructure = - immutableTriangles != (useMesh1 ? lastState.immutableTrianglesMesh1 : lastState.immutableTrianglesMesh2); -#if UNITY_EDITOR - mustUpdateMeshStructure |= !Application.isPlaying; -#endif + immutableTriangles != (useMesh1 ? meshState.stateMesh1.immutableTriangles : meshState.stateMesh2.immutableTriangles); if (mustUpdateMeshStructure) return true; // Check if any attachments were enabled/disabled // or submesh structures has changed - ExposedList attachmentsTriangleCountCurrentMesh; - ExposedList attachmentsFlipStateCurrentMesh; - ExposedList addSubmeshArgumentsCurrentMesh; - if (useMesh1) { - attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1; - addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1; - attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1; - } else { - attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2; - addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2; - attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2; - } + MeshState.SingleMeshState currentMeshState = useMesh1 ? meshState.stateMesh1 : meshState.stateMesh2; + ExposedList attachmentsCurrentMesh = currentMeshState.attachments; + ExposedList addSubmeshArgumentsCurrentMesh = currentMeshState.addSubmeshArguments; + ExposedList attachmentsFlipStateCurrentMesh = currentMeshState.attachmentsFlipState; // Check attachments - int attachmentCount = attachmentsTriangleCountTemp.Count; - if (attachmentsTriangleCountCurrentMesh.Count != attachmentCount) + int attachmentCount = attachmentsTemp.Count; + if (attachmentsCurrentMesh.Count != attachmentCount) return true; for (int i = 0; i < attachmentCount; i++) { - if (attachmentsTriangleCountCurrentMesh.Items[i] != attachmentsTriangleCountTemp.Items[i]) + if (attachmentsCurrentMesh.Items[i] != attachmentsTemp.Items[i]) return true; } @@ -749,19 +726,26 @@ public class SkeletonRenderer : MonoBehaviour { } #endif - private class LastState { - public bool immutableTrianglesMesh1; - public bool immutableTrianglesMesh2; + private class MeshState { public int vertexCount; - public readonly ExposedList attachmentsFlipStateTemp = new ExposedList(); - public readonly ExposedList attachmentsFlipStateMesh1 = new ExposedList(); - public readonly ExposedList attachmentsFlipStateMesh2 = new ExposedList(); - public readonly ExposedList attachmentsTriangleCountTemp = new ExposedList(); - public readonly ExposedList attachmentsTriangleCountMesh1 = new ExposedList(); - public readonly ExposedList attachmentsTriangleCountMesh2 = new ExposedList(); - public readonly ExposedList addSubmeshArgumentsTemp = new ExposedList(); - public readonly ExposedList addSubmeshArgumentsMesh1 = new ExposedList(); - public readonly ExposedList addSubmeshArgumentsMesh2 = new ExposedList(); + public readonly SingleMeshState stateTemp = new SingleMeshState(); + public readonly SingleMeshState stateMesh1 = new SingleMeshState(); + public readonly SingleMeshState stateMesh2 = new SingleMeshState(); + + public class SingleMeshState { + public bool immutableTriangles; + public readonly ExposedList attachments = new ExposedList(); + public readonly ExposedList attachmentsFlipState = new ExposedList(); + public readonly ExposedList addSubmeshArguments = new ExposedList(); + + public void UpdateDrawOrderCount(int drawOrderCount) { + attachmentsFlipState.GrowIfNeeded(drawOrderCount); + attachmentsFlipState.Count = drawOrderCount; + + attachments.GrowIfNeeded(drawOrderCount); + attachments.Count = drawOrderCount; + } + } public struct AddSubmeshArguments { public Material material; diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs index 371b5f170..2b8837eac 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs @@ -71,6 +71,7 @@ public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint { protected override void OnEnable () { base.OnEnable(); + lastHitY = transform.position.y; } protected override void OnDisable () {