Browse Source

Merge branch '3.8' of https://github.com/esotericsoftware/spine-runtimes into 3.8

badlogic 4 years ago
parent
commit
9bcb5c16c4
19 changed files with 147 additions and 32 deletions
  1. 2 2
      spine-ts/build/spine-all.js
  2. 0 0
      spine-ts/build/spine-all.js.map
  3. 2 2
      spine-ts/build/spine-player.js
  4. 0 0
      spine-ts/build/spine-player.js.map
  5. 2 2
      spine-ts/player/src/Player.ts
  6. 10 0
      spine-unity/Assets/Spine Examples/Scripts/Mix and Match Character Customize/EquipSystemExample.cs
  7. 6 1
      spine-unity/Assets/Spine Examples/Scripts/Mix and Match Character Customize/EquipsVisualsComponentExample.cs
  8. 6 1
      spine-unity/Assets/Spine Examples/Scripts/Mix and Match Character Customize/MixAndMatchSkinsExample.cs
  9. 8 0
      spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs
  10. 8 0
      spine-unity/Assets/Spine Examples/Scripts/MixAndMatchGraphic.cs
  11. 15 1
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/AnimationReferenceAssetEditor.cs
  12. 5 4
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/SkeletonDataAssetInspector.cs
  13. 3 4
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs
  14. 3 1
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SpinePreferences.cs
  15. 30 5
      spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs
  16. 8 0
      spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs
  17. 29 7
      spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs
  18. 6 1
      spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentCloneExtensions.cs
  19. 4 1
      spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentRegionExtensions.cs

+ 2 - 2
spine-ts/build/spine-all.js

@@ -12127,7 +12127,7 @@ var spine;
 					skeletonData = json.readSkeletonData(jsonText);
 				}
 				catch (e) {
-					this.showError("Error: could not load skeleton .json.<br><br>" + escapeHtml(JSON.stringify(e)));
+					this.showError("Error: could not load skeleton .json.<br><br>" + e.toString());
 					return;
 				}
 			}
@@ -12138,7 +12138,7 @@ var spine;
 					skeletonData = binary.readSkeletonData(binaryData);
 				}
 				catch (e) {
-					this.showError("Error: could not load skeleton .skel.<br><br>" + escapeHtml(JSON.stringify(e)));
+					this.showError("Error: could not load skeleton .skel.<br><br>" + e.toString());
 					return;
 				}
 			}

File diff suppressed because it is too large
+ 0 - 0
spine-ts/build/spine-all.js.map


+ 2 - 2
spine-ts/build/spine-player.js

@@ -11438,7 +11438,7 @@ var spine;
 					skeletonData = json.readSkeletonData(jsonText);
 				}
 				catch (e) {
-					this.showError("Error: could not load skeleton .json.<br><br>" + escapeHtml(JSON.stringify(e)));
+					this.showError("Error: could not load skeleton .json.<br><br>" + e.toString());
 					return;
 				}
 			}
@@ -11449,7 +11449,7 @@ var spine;
 					skeletonData = binary.readSkeletonData(binaryData);
 				}
 				catch (e) {
-					this.showError("Error: could not load skeleton .skel.<br><br>" + escapeHtml(JSON.stringify(e)));
+					this.showError("Error: could not load skeleton .skel.<br><br>" + e.toString());
 					return;
 				}
 			}

File diff suppressed because it is too large
+ 0 - 0
spine-ts/build/spine-player.js.map


+ 2 - 2
spine-ts/player/src/Player.ts

@@ -870,7 +870,7 @@ module spine {
 				try {
 					skeletonData = json.readSkeletonData(jsonText);
 				} catch (e) {
-					this.showError("Error: could not load skeleton .json.<br><br>" + escapeHtml(JSON.stringify(e)));
+					this.showError("Error: could not load skeleton .json.<br><br>" + e.toString());
 					return;
 				}
 			} else {
@@ -879,7 +879,7 @@ module spine {
 				try {
 					skeletonData = binary.readSkeletonData(binaryData);
 				} catch (e) {
-					this.showError("Error: could not load skeleton .skel.<br><br>" + escapeHtml(JSON.stringify(e)));
+					this.showError("Error: could not load skeleton .skel.<br><br>" + e.toString());
 					return;
 				}
 			}

+ 10 - 0
spine-unity/Assets/Spine Examples/Scripts/Mix and Match Character Customize/EquipSystemExample.cs

@@ -82,6 +82,8 @@ namespace Spine.Unity.Examples {
 				var templateSkin = skeletonData.FindSkin(templateSkinName);
 				Attachment templateAttachment = templateSkin.GetAttachment(slotIndex, templateAttachmentName);
 				attachment = templateAttachment.GetRemappedClone(asset.sprite, sourceMaterial, premultiplyAlpha: this.applyPMA);
+				// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
+				// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as shown in the method below.
 
 				cachedAttachments.Add(asset, attachment); // Cache this value for next time this asset is used.
 			}
@@ -91,6 +93,14 @@ namespace Spine.Unity.Examples {
 
 		public void Done () {
 			target.OptimizeSkin();
+			// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
+			// creates cached Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
+			// You can optionally clear the textures cache after multiple repack operations.
+			// Just be aware that while this cleanup frees up memory, it is also a costly operation
+			// and will likely cause a spike in the framerate.
+
+			//AtlasUtilities.ClearCache();
+			//Resources.UnloadUnusedAssets();
 		}
 
 	}

+ 6 - 1
spine-unity/Assets/Spine Examples/Scripts/Mix and Match Character Customize/EquipsVisualsComponentExample.cs

@@ -78,9 +78,14 @@ namespace Spine.Unity.Examples {
 				Destroy(runtimeMaterial);
 			if (runtimeAtlas)
 				Destroy(runtimeAtlas);
-			var repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial, out runtimeMaterial, out runtimeAtlas);
+			var repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial,
+				out runtimeMaterial, out runtimeAtlas, maxAtlasSize : 1024, clearCache: false);
 			collectedSkin.Clear();
 
+			// You can optionally clear the textures cache after each ore multiple repack operations are done.
+			//AtlasUtilities.ClearCache();
+			//Resources.UnloadUnusedAssets();
+
 			// 3. Use the repacked skin.
 			skeletonAnimation.Skeleton.Skin = repackedSkin;
 			RefreshSkeletonAttachments();

+ 6 - 1
spine-unity/Assets/Spine Examples/Scripts/Mix and Match Character Customize/MixAndMatchSkinsExample.cs

@@ -149,8 +149,13 @@ namespace Spine.Unity.Examples {
 			skeletonAnimation.Skeleton.SetSlotsToSetupPose();
 			skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton);
 
-			// You can optionally clear the cache after multiple repack operations.
+			// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
+			// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
+			// You can optionally clear the textures cache after multiple repack operations.
+			// Just be aware that while this cleanup frees up memory, it is also a costly operation
+			// and will likely cause a spike in the framerate.
 			AtlasUtilities.ClearCache();
+			Resources.UnloadUnusedAssets();
 		}
 
 		void UpdateCharacterSkin () {

+ 8 - 0
spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs

@@ -95,6 +95,8 @@ namespace Spine.Unity.Examples {
 			int visorSlotIndex = skeleton.FindSlotIndex(visorSlot); // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
 			Attachment templateAttachment = templateSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
 			Attachment newAttachment = templateAttachment.GetRemappedClone(visorSprite, sourceMaterial, pivotShiftsMeshUVCoords : false); // STEP 1.2 - 1.3
+			// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
+			// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as done in the method below.
 			customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
 
 			// And now for the gun.
@@ -136,6 +138,12 @@ namespace Spine.Unity.Examples {
 			skeleton.SetSlotsToSetupPose(); // Use the pose from setup pose.
 			skeletonAnimation.Update(0); // Use the pose in the currently active animation.
 
+			// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
+			// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
+			// You can optionally clear the textures cache after multiple repack operations.
+			// Just be aware that while this cleanup frees up memory, it is also a costly operation
+			// and will likely cause a spike in the framerate.
+			AtlasUtilities.ClearCache();
 			Resources.UnloadUnusedAssets();
 		}
 	}

+ 8 - 0
spine-unity/Assets/Spine Examples/Scripts/MixAndMatchGraphic.cs

@@ -96,6 +96,8 @@ namespace Spine.Unity.Examples {
 			int visorSlotIndex = skeleton.FindSlotIndex(visorSlot); // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
 			Attachment baseAttachment = baseSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
 			Attachment newAttachment = baseAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
+			// Note: Each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true` creates
+			// a cached Texture copy which can be cleared by calling AtlasUtilities.ClearCache() as done below.
 			customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
 
 			// And now for the gun.
@@ -135,6 +137,12 @@ namespace Spine.Unity.Examples {
 			skeletonGraphic.Update(0);
 			skeletonGraphic.OverrideTexture = runtimeAtlas;
 
+			// `GetRepackedSkin()` and each call to `GetRemappedClone()` with parameter `premultiplyAlpha` set to `true`
+			// cache necessarily created Texture copies which can be cleared by calling AtlasUtilities.ClearCache().
+			// You can optionally clear the textures cache after multiple repack operations.
+			// Just be aware that while this cleanup frees up memory, it is also a costly operation
+			// and will likely cause a spike in the framerate.
+			AtlasUtilities.ClearCache();
 			Resources.UnloadUnusedAssets();
 		}
 	}

+ 15 - 1
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/AnimationReferenceAssetEditor.cs

@@ -33,6 +33,7 @@ using UnityEngine;
 using UnityEditor;
 
 using System.Reflection;
+using System;
 
 namespace Spine.Unity.Editor {
 	using Editor = UnityEditor.Editor;
@@ -58,7 +59,11 @@ namespace Spine.Unity.Editor {
 		SkeletonData lastSkeletonData;
 
 		void OnEnable () { HandleOnEnablePreview(); }
-		void OnDestroy () { HandleOnDestroyPreview(); }
+		void OnDestroy () {
+			HandleOnDestroyPreview();
+			AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
+			EditorApplication.update -= preview.HandleEditorUpdate;
+		}
 
 		public override void OnInspectorGUI () {
 			animationNameProperty = animationNameProperty ?? serializedObject.FindProperty("animationName");
@@ -133,6 +138,11 @@ namespace Spine.Unity.Editor {
 		void HandleOnEnablePreview () {
 			if (ThisSkeletonDataAsset != null && ThisSkeletonDataAsset.skeletonJSON == null)
 				return;
+			SpineEditorUtilities.ConfirmInitialization();
+
+			// This handles the case where the managed editor assembly is unloaded before recompilation when code changes.
+			AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
+			AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;
 
 			preview.Initialize(this.Repaint, ThisSkeletonDataAsset, LastSkinName);
 			preview.PlayPauseAnimation(ThisAnimationName, true);
@@ -142,6 +152,10 @@ namespace Spine.Unity.Editor {
 			EditorApplication.update += preview.HandleEditorUpdate;
 		}
 
+		private void OnDomainUnload (object sender, EventArgs e) {
+			OnDestroy();
+		}
+
 		private void HandleOnSkinChanged (string skinName) {
 			EditorPrefs.SetString(LastSkinKey, skinName);
 			preview.PlayPauseAnimation(ThisAnimationName, true);

+ 5 - 4
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/SkeletonDataAssetInspector.cs

@@ -1158,7 +1158,7 @@ namespace Spine.Unity.Editor {
 			float lineRectWidth = lineRect.width;
 			TrackEntry t = skeletonAnimation.AnimationState.GetCurrent(0);
 
-			if (t != null) {
+			if (t != null && Icons.userEvent != null) { // when changing to play mode, Icons.userEvent  will not be reset
 				int loopCount = (int)(t.TrackTime / t.TrackEnd);
 				float currentTime = t.TrackTime - (t.TrackEnd * loopCount);
 				float normalizedTime = currentTime / t.Animation.Duration;
@@ -1176,14 +1176,15 @@ namespace Spine.Unity.Editor {
 				for (int i = 0; i < currentAnimationEvents.Count; i++) {
 					float eventTime = currentAnimationEventTimes[i];
 					var userEventIcon = Icons.userEvent;
+					float iconX = Mathf.Max(((eventTime / t.Animation.Duration) * lineRectWidth) - (userEventIcon.width / 2), barRect.x);
+					float iconY = barRect.y + userEventIcon.height;
 					var evRect = new Rect(barRect) {
-						x = Mathf.Max(((eventTime / t.Animation.Duration) * lineRectWidth) - (userEventIcon.width / 2), barRect.x),
-						y = barRect.y + userEventIcon.height,
+						x = iconX,
+						y = iconY,
 						width = userEventIcon.width,
 						height = userEventIcon.height
 					};
 					GUI.DrawTexture(evRect, userEventIcon);
-
 					Event ev = Event.current;
 					if (ev.type == EventType.Repaint) {
 						if (evRect.Contains(ev.mousePosition)) {

+ 3 - 4
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs

@@ -919,15 +919,14 @@ namespace Spine.Unity.Editor {
 						skeletonDataAsset.scale = SpineEditorUtilities.Preferences.defaultScale;
 						skeletonDataAsset.blendModeMaterials.applyAdditiveMaterial = !SpineEditorUtilities.Preferences.UsesPMAWorkflow;
 					}
-
 					AssetDatabase.CreateAsset(skeletonDataAsset, filePath);
-					AssetDatabase.SaveAssets();
 				} else {
 					skeletonDataAsset.atlasAssets = atlasAssets;
 					skeletonDataAsset.Clear();
-					var skeletonData = skeletonDataAsset.GetSkeletonData(true);
-					BlendModeMaterialsUtility.UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData);
 				}
+				var skeletonData = skeletonDataAsset.GetSkeletonData(true);
+				BlendModeMaterialsUtility.UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData);
+				AssetDatabase.SaveAssets();
 
 				return skeletonDataAsset;
 			} else {

+ 3 - 1
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SpinePreferences.cs

@@ -236,7 +236,9 @@ namespace Spine.Unity.Editor {
 					if (string.IsNullOrEmpty(textureSettingsRef.stringValue)) {
 						var pmaTextureSettingsReferenceGUIDS = AssetDatabase.FindAssets("PMATexturePreset");
 						if (pmaTextureSettingsReferenceGUIDS.Length > 0) {
-							textureSettingsRef.stringValue = AssetDatabase.GUIDToAssetPath(pmaTextureSettingsReferenceGUIDS[0]);
+							var assetPath = AssetDatabase.GUIDToAssetPath(pmaTextureSettingsReferenceGUIDS[0]);
+							if (!string.IsNullOrEmpty(assetPath))
+								textureSettingsRef.stringValue = assetPath;
 						}
 					}
 

+ 30 - 5
spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs

@@ -218,6 +218,11 @@ namespace Spine.Unity {
 			}
 		}
 
+		protected override void OnDestroy () {
+			Clear();
+			base.OnDestroy();
+		}
+
 		public override void Rebuild (CanvasUpdate update) {
 			base.Rebuild(update);
 			if (canvasRenderer.cull) return;
@@ -458,9 +463,8 @@ namespace Spine.Unity {
 
 			for (int i = 0; i < canvasRenderers.Count; ++i)
 				canvasRenderers[i].Clear();
-			foreach (var mesh in meshes)
-				Destroy(mesh);
-			meshes.Clear();
+			DestroyMeshes();
+			DisposeMeshBuffers();
 		}
 
 		public void TrimRenderers () {
@@ -562,6 +566,14 @@ namespace Spine.Unity {
 			}
 		}
 
+		protected void DisposeMeshBuffers () {
+			if (meshBuffers != null) {
+				meshBuffers.GetNext().Dispose();
+				meshBuffers.GetNext().Dispose();
+				meshBuffers = null;
+			}
+		}
+
 		protected void UpdateMeshSingleCanvasRenderer () {
 			if (canvasRenderers.Count > 0)
 				DisableUnusedCanvasRenderers(usedCount : 0);
@@ -724,9 +736,22 @@ namespace Spine.Unity {
 		protected void EnsureMeshesCount (int targetCount) {
 			int oldCount = meshes.Count;
 			meshes.EnsureCapacity(targetCount);
-			var meshesItems = meshes.Items;
 			for (int i = oldCount; i < targetCount; i++)
-				if (meshesItems[i] == null) meshesItems[i] = new Mesh();
+				meshes.Add(SpineMesh.NewSkeletonMesh());
+		}
+
+		protected void DestroyMeshes () {
+			foreach (var mesh in meshes) {
+#if UNITY_EDITOR
+				if (Application.isEditor && !Application.isPlaying)
+					UnityEngine.Object.DestroyImmediate(mesh);
+				else
+					UnityEngine.Object.Destroy(mesh);
+#else
+					UnityEngine.Object.Destroy(mesh);
+#endif
+			}
+			meshes.Clear();
 		}
 
 		protected void EnsureSeparatorPartCount () {

+ 8 - 0
spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs

@@ -27,6 +27,10 @@
  * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
+#if UNITY_2019_3_OR_NEWER
+#define MESH_SET_TRIANGLES_PROVIDES_LENGTH_PARAM
+#endif
+
 // Not for optimization. Do not disable.
 #define SPINE_TRIANGLECHECK // Avoid calling SetTriangles at the cost of checking for mesh differences (vertex counts, memberwise attachment list compare) every frame.
 //#define SPINE_DEBUG
@@ -1117,7 +1121,11 @@ namespace Spine.Unity {
 			mesh.subMeshCount = submeshCount;
 
 			for (int i = 0; i < submeshCount; i++)
+#if MESH_SET_TRIANGLES_PROVIDES_LENGTH_PARAM
+				mesh.SetTriangles(submeshesItems[i].Items, 0, submeshesItems[i].Count, i, false);
+#else
 				mesh.SetTriangles(submeshesItems[i].Items, i, false);
+#endif
 		}
 		#endregion
 

+ 29 - 7
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs

@@ -242,11 +242,17 @@ namespace Spine.Unity.AttachmentTools {
 		/// Fills the outputAttachments list with new attachment objects based on the attachments in sourceAttachments,
 		/// but mapped to a new single texture using the same material.</summary>
 		/// <remarks>Returned <c>Material</c> and <c>Texture</c> behave like <c>new Texture2D()</c>, thus you need to call <c>Destroy()</c>
-		/// to free resources.</remarks>
+		/// to free resources.
+		/// This method caches necessary Texture copies for later re-use, which might steadily increase the texture memory
+		/// footprint when used excessively. Set <paramref name="clearCache"/> to <c>true</c>
+		/// or call <see cref="AtlasUtilities.ClearCache()"/> to clear this texture cache.
+		/// You may want to call <c>Resources.UnloadUnusedAssets()</c> after that.
+		/// </remarks>
 		/// <param name="sourceAttachments">The list of attachments to be repacked.</param>
 		/// <param name = "outputAttachments">The List(Attachment) to populate with the newly created Attachment objects.</param>
-		///
 		/// <param name="materialPropertySource">May be null. If no Material property source is provided, no special </param>
+		/// <param name="clearCache">When set to <c>true</c>, <see cref="AtlasUtilities.ClearCache()"/> is called after
+		/// repacking to clear the texture cache. See remarks for additional info.</param>
 		public static void GetRepackedAttachments (List<Attachment> sourceAttachments, List<Attachment> outputAttachments, Material materialPropertySource, out Material outputMaterial, out Texture2D outputTexture, int maxAtlasSize = 1024, int padding = 2, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps, string newAssetName = "Repacked Attachments", bool clearCache = false, bool useOriginalNonrenderables = true) {
 			if (sourceAttachments == null) throw new System.ArgumentNullException("sourceAttachments");
 			if (outputAttachments == null) throw new System.ArgumentNullException("outputAttachments");
@@ -337,7 +343,14 @@ namespace Spine.Unity.AttachmentTools {
 		/// <remarks>GetRepackedSkin is an expensive operation, preferably call it at level load time.
 		/// No Spine.Atlas object is created so there is no way to find AtlasRegions except through the Attachments using them.
 		/// Returned <c>Material</c> and <c>Texture</c> behave like <c>new Texture2D()</c>, thus you need to call <c>Destroy()</c>
-		/// to free resources.</remarks>
+		/// to free resources.
+		/// This method caches necessary Texture copies for later re-use, which might steadily increase the texture memory
+		/// footprint when used excessively. Set <paramref name="clearCache"/> to <c>true</c>
+		/// or call <see cref="AtlasUtilities.ClearCache()"/> to clear this texture cache.
+		/// You may want to call <c>Resources.UnloadUnusedAssets()</c> after that.
+		/// </remarks>
+		/// <param name="clearCache">When set to <c>true</c>, <see cref="AtlasUtilities.ClearCache()"/> is called after
+		/// repacking to clear the texture cache. See remarks for additional info.</param>
 		/// <param name="additionalTexturePropertyIDsToCopy">Optional additional textures (such as normal maps) to copy while repacking.
 		/// To copy e.g. the main texture and normal maps, pass 'new int[] { Shader.PropertyToID("_BumpMap") }' at this parameter.</param>
 		/// <param name="additionalOutputTextures">When <c>additionalTexturePropertyIDsToCopy</c> is non-null,
@@ -368,10 +381,7 @@ namespace Spine.Unity.AttachmentTools {
 		/// <summary>
 		/// 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>GetRepackedSkin is an expensive operation, preferably call it at level load time.
-		/// No Spine.Atlas object is created so there is no way to find AtlasRegions except through the Attachments using them.
-		/// Returned <c>Material</c> and <c>Texture</c> behave like <c>new Texture2D()</c>, thus you need to call <c>Destroy()</c>
-		/// to free resources.</remarks>
+		/// See documentation of <see cref="GetRepackedSkin"/> for details.
 		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, bool useOriginalNonrenderables = true,
@@ -525,6 +535,18 @@ namespace Spine.Unity.AttachmentTools {
 		static Dictionary<IntAndAtlasRegionKey, Texture2D> CachedRegionTextures = new Dictionary<IntAndAtlasRegionKey, Texture2D>();
 		static List<Texture2D> CachedRegionTexturesList = new List<Texture2D>();
 
+		/// <summary>
+		/// Frees up textures cached by repacking and remapping operations.
+		///
+		/// Calling <see cref="AttachmentCloneExtensions.GetRemappedClone"/> with parameter <c>premultiplyAlpha=true</c>,
+		/// <see cref="GetRepackedAttachments"/> or <see cref="GetRepackedSkin"/> will cache textures for later re-use,
+		///	which might steadily increase the texture memory footprint when used excessively.
+		///	You can clear this Texture cache by calling <see cref="AtlasUtilities.ClearCache()"/>.
+		/// You may also want to call <c>Resources.UnloadUnusedAssets()</c> after that. Be aware that while this cleanup
+		/// frees up memory, it is also a costly operation and will likely cause a spike in the framerate.
+		/// Thus it is recommended to perform costly repacking and cleanup operations after e.g. a character customization
+		/// screen has been exited, and if required additionally after a certain number of <c>GetRemappedClone()</c> calls.
+		/// </summary>
 		public static void ClearCache () {
 			foreach (var t in CachedRegionTexturesList) {
 				UnityEngine.Object.Destroy(t);

+ 6 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentCloneExtensions.cs

@@ -80,7 +80,8 @@ namespace Spine.Unity.AttachmentTools {
 		/// <param name="o">The original attachment.</param>
 		/// <param name="sprite">The sprite whose texture to use.</param>
 		/// <param name="sourceMaterial">The source material used to copy the shader and material properties from.</param>
-		/// <param name="premultiplyAlpha">If <c>true</c>, a premultiply alpha clone of the original texture will be created.</param>
+		/// <param name="premultiplyAlpha">If <c>true</c>, a premultiply alpha clone of the original texture will be created.
+		/// See remarks below for additional info.</param>
 		/// <param name="cloneMeshAsLinked">If <c>true</c> MeshAttachments will be cloned as linked meshes and will inherit animation from the original attachment.</param>
 		/// <param name="useOriginalRegionSize">If <c>true</c> the size of the original attachment will be followed, instead of using the Sprite size.</param>
 		/// <param name="pivotShiftsMeshUVCoords">If <c>true</c> and the original Attachment is a MeshAttachment, then
@@ -89,6 +90,10 @@ namespace Spine.Unity.AttachmentTools {
 		///	<param name="useOriginalRegionScale">If <c>true</c> and the original Attachment is a RegionAttachment, then
 		///	the original region's scale value is used instead of the Sprite's pixels per unit property. Since uniform scale is used,
 		///	x scale of the original attachment (width scale) is used, scale in y direction (height scale) is ignored.</param>
+		///	<remarks>When parameter <c>premultiplyAlpha</c> is set to <c>true</c>, a premultiply alpha clone of the
+		///	original texture will be created. Additionally, this PMA Texture clone is cached for later re-use,
+		///	which might steadily increase the Texture memory footprint when used excessively.
+		///	See <see cref="AtlasUtilities.ClearCache()"/> on how to clear these cached textures.</remarks>
 		public static Attachment GetRemappedClone (this Attachment o, Sprite sprite, Material sourceMaterial,
 			bool premultiplyAlpha = true, bool cloneMeshAsLinked = true, bool useOriginalRegionSize = false,
 			bool pivotShiftsMeshUVCoords = true, bool useOriginalRegionScale = false) {

+ 4 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentRegionExtensions.cs

@@ -125,7 +125,10 @@ namespace Spine.Unity.AttachmentTools {
 		}
 
 		/// <summary>
-		/// Creates a Spine.AtlasRegion that uses a premultiplied alpha duplicate texture of the Sprite's texture data. Returns a RegionAttachment that uses it. Use this if you plan to use a premultiply alpha shader such as "Spine/Skeleton"</summary>
+		/// Creates a Spine.AtlasRegion that uses a premultiplied alpha duplicate texture of the Sprite's texture data.
+		/// Returns a RegionAttachment that uses it. Use this if you plan to use a premultiply alpha shader such as "Spine/Skeleton".</summary>
+		/// <remarks>The duplicate texture is cached for later re-use. See documentation of
+		/// <see cref="AttachmentCloneExtensions.GetRemappedClone"/> for additional details.</remarks>
 		public static RegionAttachment ToRegionAttachmentPMAClone (this Sprite sprite, Shader shader, TextureFormat textureFormat = AtlasUtilities.SpineTextureFormat, bool mipmaps = AtlasUtilities.UseMipMaps, Material materialPropertySource = null, float rotation = 0f) {
 			if (sprite == null) throw new System.ArgumentNullException("sprite");
 			if (shader == null) throw new System.ArgumentNullException("shader");

Some files were not shown because too many files changed in this diff