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 +} 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 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..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; @@ -2496,7 +2498,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 +2510,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; } } 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 38b75a85b..91bf4a147 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -758,8 +758,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; } @@ -768,8 +769,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; } @@ -778,12 +780,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; } @@ -792,7 +799,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; } @@ -801,7 +810,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; 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; 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 cbaffaa51..781b06bb3 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('\\', '/');