From 6bf587057f56404b226980769b0c07766dcee9dd Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Wed, 1 Jun 2022 19:35:18 +0200 Subject: [PATCH 1/8] [unity] Fixed Timeline SkeletonGraphic clip exception when DefaultMixDuration is disabled. Closes #2090. Same bugfix as in commit d796131 on 4.1-beta branch. --- .../SpineAnimationStateGraphicTrack.cs | 8 ++++++++ .../package-no-spine-unity-dependency.json | 2 +- .../com.esotericsoftware.spine.timeline/package.json | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/spine-unity/Modules/com.esotericsoftware.spine.timeline/Runtime/SpineAnimationState/SpineAnimationStateGraphicTrack.cs b/spine-unity/Modules/com.esotericsoftware.spine.timeline/Runtime/SpineAnimationState/SpineAnimationStateGraphicTrack.cs index 1c16f2f94..535110dd0 100644 --- a/spine-unity/Modules/com.esotericsoftware.spine.timeline/Runtime/SpineAnimationState/SpineAnimationStateGraphicTrack.cs +++ b/spine-unity/Modules/com.esotericsoftware.spine.timeline/Runtime/SpineAnimationState/SpineAnimationStateGraphicTrack.cs @@ -30,6 +30,7 @@ #if UNITY_EDITOR using System.ComponentModel; #endif +using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; @@ -45,6 +46,13 @@ namespace Spine.Unity.Playables { public int trackIndex = 0; public override Playable CreateTrackMixer (PlayableGraph graph, GameObject go, int inputCount) { + IEnumerable clips = this.GetClips(); + foreach (TimelineClip clip in clips) { + var animationStateClip = clip.asset as SpineAnimationStateClip; + if (animationStateClip != null) + animationStateClip.timelineClip = clip; + } + var scriptPlayable = ScriptPlayable.Create(graph, inputCount); var mixerBehaviour = scriptPlayable.GetBehaviour(); mixerBehaviour.trackIndex = this.trackIndex; diff --git a/spine-unity/Modules/com.esotericsoftware.spine.timeline/package-no-spine-unity-dependency.json b/spine-unity/Modules/com.esotericsoftware.spine.timeline/package-no-spine-unity-dependency.json index 2d6284d2c..9781f3752 100644 --- a/spine-unity/Modules/com.esotericsoftware.spine.timeline/package-no-spine-unity-dependency.json +++ b/spine-unity/Modules/com.esotericsoftware.spine.timeline/package-no-spine-unity-dependency.json @@ -2,7 +2,7 @@ "name": "com.esotericsoftware.spine.timeline", "displayName": "Spine Timeline Extensions", "description": "This plugin provides integration of spine-unity for the Unity Timeline.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime (via the spine-unity unitypackage), version 4.0.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)", - "version": "4.0.10", + "version": "4.0.11", "unity": "2018.3", "author": { "name": "Esoteric Software", diff --git a/spine-unity/Modules/com.esotericsoftware.spine.timeline/package.json b/spine-unity/Modules/com.esotericsoftware.spine.timeline/package.json index 60146b620..8be2cf592 100644 --- a/spine-unity/Modules/com.esotericsoftware.spine.timeline/package.json +++ b/spine-unity/Modules/com.esotericsoftware.spine.timeline/package.json @@ -2,7 +2,7 @@ "name": "com.esotericsoftware.spine.timeline", "displayName": "Spine Timeline Extensions", "description": "This plugin provides integration of spine-unity for the Unity Timeline.\n\nPrerequisites:\nIt requires a working installation of the spine-unity and spine-csharp runtimes as UPM packages (not as spine-unity unitypackage), version 4.0.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)", - "version": "4.0.10", + "version": "4.0.11", "unity": "2018.3", "author": { "name": "Esoteric Software", From 0c286734a7274b63ac07c9f494a2260b6e188819 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Thu, 9 Jun 2022 18:07:15 +0200 Subject: [PATCH 2/8] [unity] Fixed build crashing on Unity 2022.1.3 on PostprocessSpinePrefabMeshes() calling AssetDatabase.SaveAssets(). Closes #2093. --- .../Editor/Utility/SpineBuildProcessor.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineBuildProcessor.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineBuildProcessor.cs index 6b994b4cd..12d836ea5 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineBuildProcessor.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineBuildProcessor.cs @@ -36,6 +36,10 @@ #define HAS_ON_POSTPROCESS_PREFAB #endif +#if UNITY_2020_3_OR_NEWER +#define HAS_SAVE_ASSET_IF_DIRTY +#endif + using System.Collections.Generic; using UnityEditor; using UnityEditor.Build; @@ -80,13 +84,18 @@ namespace Spine.Unity.Editor { string assetPath = AssetDatabase.GUIDToAssetPath(asset); GameObject prefabGameObject = AssetDatabase.LoadAssetAtPath(assetPath); if (SpineEditorUtilities.CleanupSpinePrefabMesh(prefabGameObject)) { +#if HAS_SAVE_ASSET_IF_DIRTY + AssetDatabase.SaveAssetIfDirty(prefabGameObject); +#endif prefabsToRestore.Add(assetPath); } EditorUtility.UnloadUnusedAssetsImmediate(); } AssetDatabase.StopAssetEditing(); +#if !HAS_SAVE_ASSET_IF_DIRTY if (prefabAssets.Length > 0) AssetDatabase.SaveAssets(); +#endif } finally { BuildUtilities.IsInSkeletonAssetBuildPreProcessing = false; } @@ -98,9 +107,14 @@ namespace Spine.Unity.Editor { foreach (string assetPath in prefabsToRestore) { GameObject g = AssetDatabase.LoadAssetAtPath(assetPath); SpineEditorUtilities.SetupSpinePrefabMesh(g, null); +#if HAS_SAVE_ASSET_IF_DIRTY + AssetDatabase.SaveAssetIfDirty(g); +#endif } +#if !HAS_SAVE_ASSET_IF_DIRTY if (prefabsToRestore.Count > 0) AssetDatabase.SaveAssets(); +#endif prefabsToRestore.Clear(); } finally { @@ -121,11 +135,16 @@ namespace Spine.Unity.Editor { spriteAtlasTexturesToRestore[assetPath] = AssetDatabase.GetAssetPath(atlasAsset.materials[0].mainTexture); atlasAsset.materials[0].mainTexture = null; } +#if HAS_SAVE_ASSET_IF_DIRTY + AssetDatabase.SaveAssetIfDirty(atlasAsset); +#endif EditorUtility.UnloadUnusedAssetsImmediate(); } AssetDatabase.StopAssetEditing(); +#if !HAS_SAVE_ASSET_IF_DIRTY if (spriteAtlasAssets.Length > 0) AssetDatabase.SaveAssets(); +#endif } finally { BuildUtilities.IsInSpriteAtlasBuildPreProcessing = false; } @@ -141,9 +160,14 @@ namespace Spine.Unity.Editor { Texture atlasTexture = AssetDatabase.LoadAssetAtPath(pair.Value); atlasAsset.materials[0].mainTexture = atlasTexture; } +#if HAS_SAVE_ASSET_IF_DIRTY + AssetDatabase.SaveAssetIfDirty(atlasAsset); +#endif } +#if !HAS_SAVE_ASSET_IF_DIRTY if (spriteAtlasTexturesToRestore.Count > 0) AssetDatabase.SaveAssets(); +#endif spriteAtlasTexturesToRestore.Clear(); } finally { BuildUtilities.IsInSpriteAtlasBuildPostProcessing = false; From e39f74837a615e32e97ffac3b89eb692e3783ad6 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 13 Jun 2022 16:26:12 +0200 Subject: [PATCH 3/8] [unity] Fixed UPM package Index out of bounds exception in editor code. Closes #2095. --- .../spine-unity/Editor/Utility/SpineEditorUtilities.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineEditorUtilities.cs index 83195bfd6..f5c04df3d 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineEditorUtilities.cs @@ -172,11 +172,12 @@ namespace Spine.Unity.Editor { if (EditorApplication.isPlayingOrWillChangePlaymode) return; - string[] assets = AssetDatabase.FindAssets("t:script SpineEditorUtilities"); + string[] folders = { "Assets", "Packages" }; + string[] assets = AssetDatabase.FindAssets("t:script SpineEditorUtilities", folders); string assetPath = AssetDatabase.GUIDToAssetPath(assets[0]); editorPath = Path.GetDirectoryName(assetPath).Replace('\\', '/'); - assets = AssetDatabase.FindAssets("t:texture icon-subMeshRenderer"); + assets = AssetDatabase.FindAssets("t:texture icon-subMeshRenderer", folders); if (assets.Length > 0) { assetPath = AssetDatabase.GUIDToAssetPath(assets[0]); editorGUIPath = Path.GetDirectoryName(assetPath).Replace('\\', '/'); From a1e782a53308cf02a945ec2ca67ccb84381b1280 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Thu, 16 Jun 2022 11:19:51 -0400 Subject: [PATCH 4/8] [libgdx] Javadoc for skeleton transform properties. --- .../com/esotericsoftware/spine/Skeleton.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index d1ea1206b..b564e2daa 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -707,8 +707,9 @@ public class Skeleton { color.set(r, g, b, a); } - /** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale - * inheritance. */ + /** Scales the entire skeleton on the X axis. + *

+ * Bones that do not inherit scale are still affected by this property. */ public float getScaleX () { return scaleX; } @@ -717,8 +718,9 @@ public class Skeleton { this.scaleX = scaleX; } - /** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale - * inheritance. */ + /** Scales the entire skeleton on the Y axis. + *

+ * Bones that do not inherit scale are still affected by this property. */ public float getScaleY () { return scaleY; } @@ -727,12 +729,17 @@ public class Skeleton { this.scaleY = scaleY; } + /** Scales the entire skeleton on the X and Y axes. + *

+ * Bones that do not inherit scale are still affected by this property. */ public void setScale (float scaleX, float scaleY) { this.scaleX = scaleX; this.scaleY = scaleY; } - /** Sets the skeleton X position, which is added to the root bone worldX position. */ + /** Sets the skeleton X position, which is added to the root bone worldX position. + *

+ * Bones that do not inherit translation are still affected by this property. */ public float getX () { return x; } @@ -741,7 +748,9 @@ public class Skeleton { this.x = x; } - /** Sets the skeleton Y position, which is added to the root bone worldY position. */ + /** Sets the skeleton Y position, which is added to the root bone worldY position. + *

+ * Bones that do not inherit translation are still affected by this property. */ public float getY () { return y; } @@ -750,7 +759,9 @@ public class Skeleton { this.y = y; } - /** Sets the skeleton X and Y position, which is added to the root bone worldX and worldY position. */ + /** Sets the skeleton X and Y position, which is added to the root bone worldX and worldY position. + *

+ * Bones that do not inherit translation are still affected by this property. */ public void setPosition (float x, float y) { this.x = x; this.y = y; From 81baef0b5bb181376d15b0208697db8dabce095e Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Sat, 18 Jun 2022 13:45:13 -0400 Subject: [PATCH 5/8] [libgdx] Fixed crash when a pingpong sequence has 1 frame. --- .../src/com/esotericsoftware/spine/Animation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 3c4bc14cd..e3e45a533 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -2496,7 +2496,7 @@ public class Animation { break; case pingpong: { int n = (count << 1) - 2; - index %= n; + index = n == 0 ? 0 : index % n; if (index >= count) index = n - index; break; } @@ -2508,7 +2508,7 @@ public class Animation { break; case pingpongReverse: int n = (count << 1) - 2; - index = (index + count - 1) % n; + index = n == 0 ? 0 : (index + count - 1) % n; if (index >= count) index = n - index; } } From 4efd63f89cb995cbe4f30358d268a9d0eaf0c9be Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Sat, 18 Jun 2022 18:48:26 -0400 Subject: [PATCH 6/8] [libgdx] Use linked mesh sequence properties when inheriting a sequence timeline. Also allow a linked mesh with no sequence when the source mesh has one. --- .../src/com/esotericsoftware/spine/Animation.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index e3e45a533..3bd8bf011 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -2471,6 +2471,8 @@ public class Animation { if (!(slotAttachment instanceof VertexAttachment) || ((VertexAttachment)slotAttachment).getTimelineAttachment() != attachment) return; } + Sequence sequence = ((HasTextureRegion)slotAttachment).getSequence(); + if (sequence == null) return; float[] frames = this.frames; if (time < frames[0]) { // Time is before first frame. @@ -2483,7 +2485,7 @@ public class Animation { int modeAndIndex = (int)frames[i + MODE]; float delay = frames[i + DELAY]; - int index = modeAndIndex >> 4, count = attachment.getSequence().getRegions().length; + int index = modeAndIndex >> 4, count = sequence.getRegions().length; SequenceMode mode = SequenceMode.values[modeAndIndex & 0xf]; if (mode != SequenceMode.hold) { index += (time - before) / delay + 0.00001f; From 5b6c220bf6849d87500ed25b094c533a6e55ca77 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 20 Jun 2022 11:26:35 +0200 Subject: [PATCH 7/8] [csharp] Port of commits 81baef0 and 4efd63f: Fixed crash when a pingpong sequence has 1 frame. Use linked mesh sequence properties when inheriting a sequence timeline. --- spine-csharp/src/Animation.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/spine-csharp/src/Animation.cs b/spine-csharp/src/Animation.cs index ee66aabf4..58851447d 100644 --- a/spine-csharp/src/Animation.cs +++ b/spine-csharp/src/Animation.cs @@ -2642,6 +2642,8 @@ namespace Spine { if ((vertexAttachment == null) || vertexAttachment.TimelineAttachment != attachment) return; } + Sequence sequence = ((IHasTextureRegion)slotAttachment).Sequence; + if (sequence == null) return; float[] frames = this.frames; if (time < frames[0]) { // Time is before first frame. @@ -2654,7 +2656,7 @@ namespace Spine { int modeAndIndex = (int)frames[i + MODE]; float delay = frames[i + DELAY]; - int index = modeAndIndex >> 4, count = attachment.Sequence.Regions.Length; + int index = modeAndIndex >> 4, count = sequence.Regions.Length; SequenceMode mode = (SequenceMode)(modeAndIndex & 0xf); if (mode != SequenceMode.Hold) { index += (int)((time - before) / delay + 0.00001f); @@ -2667,7 +2669,7 @@ namespace Spine { break; case SequenceMode.Pingpong: { int n = (count << 1) - 2; - index %= n; + index = n == 0 ? 0 : index % n; if (index >= count) index = n - index; break; } @@ -2679,7 +2681,7 @@ namespace Spine { break; case SequenceMode.PingpongReverse: { int n = (count << 1) - 2; - index = (index + count - 1) % n; + index = n == 0 ? 0 : (index + count - 1) % n; if (index >= count) index = n - index; break; } // end case From ca75d3605e069898a3e014cede75405920b8d78c Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 20 Jun 2022 15:39:33 +0200 Subject: [PATCH 8/8] [c][cpp] Port of 4efd63f89cb995cbe4f30358d268a9d0eaf0c9be and 81baef0b5bb181376d15b0208697db8dabce095e --- spine-c/spine-c/src/spine/Animation.c | 5 +++-- spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/spine-c/spine-c/src/spine/Animation.c b/spine-c/spine-c/src/spine/Animation.c index 2135a8704..65b02a3d1 100644 --- a/spine-c/spine-c/src/spine/Animation.c +++ b/spine-c/spine-c/src/spine/Animation.c @@ -2042,6 +2042,7 @@ void _spSequenceTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float if (self->attachment->type == SP_ATTACHMENT_REGION) sequence = ((spRegionAttachment *) self->attachment)->sequence; if (self->attachment->type == SP_ATTACHMENT_MESH) sequence = ((spMeshAttachment *) self->attachment)->sequence; + if (!sequence) return; index = modeAndIndex >> 4; count = sequence->regions->size; mode = modeAndIndex & 0xf; @@ -2056,7 +2057,7 @@ void _spSequenceTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float break; case SP_SEQUENCE_MODE_PINGPONG: { int n = (count << 1) - 2; - index %= n; + index = n == 0 ? 0 : index % n; if (index >= count) index = n - index; break; } @@ -2068,7 +2069,7 @@ void _spSequenceTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float break; case SP_SEQUENCE_MODE_PINGPONGREVERSE: { int n = (count << 1) - 2; - index = (index + count - 1) % n; + index = n == 0 ? 0 : (index + count - 1) % n; if (index >= count) index = n - index; } } diff --git a/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp b/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp index 2740de80b..652def340 100644 --- a/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp @@ -89,6 +89,7 @@ void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec Sequence *sequence = NULL; if (_attachment->getRTTI().instanceOf(RegionAttachment::rtti)) sequence = ((RegionAttachment *) _attachment)->getSequence(); if (_attachment->getRTTI().instanceOf(MeshAttachment::rtti)) sequence = ((MeshAttachment *) _attachment)->getSequence(); + if (!sequence) return; int index = modeAndIndex >> 4, count = (int) sequence->getRegions().size(); int mode = modeAndIndex & 0xf; if (mode != SequenceMode::hold) { @@ -102,7 +103,7 @@ void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec break; case SequenceMode::pingpong: { int n = (count << 1) - 2; - index %= n; + index = n == 0 ? 0 : index % n; if (index >= count) index = n - index; break; } @@ -114,10 +115,10 @@ void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec break; case SequenceMode::pingpongReverse: { int n = (count << 1) - 2; - index = (index + count - 1) % n; + index = n == 0 ? 0 : (index + count - 1) % n; if (index >= count) index = n - index; } } } slot->setSequenceIndex(index); -} \ No newline at end of file +}