From 5cb979c7ce8c4ef3d965d0d49450f333a689d04b Mon Sep 17 00:00:00 2001 From: badlogic Date: Tue, 22 Jan 2019 16:43:01 +0100 Subject: [PATCH 01/39] [libgdx] Fixed pom version. --- spine-libgdx/spine-libgdx/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-libgdx/spine-libgdx/pom.xml b/spine-libgdx/spine-libgdx/pom.xml index fc6f6b834..cb11287a6 100644 --- a/spine-libgdx/spine-libgdx/pom.xml +++ b/spine-libgdx/spine-libgdx/pom.xml @@ -10,7 +10,7 @@ com.esotericsoftware.spine spine-libgdx jar - 3.7.83.2-SNAPSHOT + 3.8.0.1-SNAPSHOT spine-libgdx From f6c4554647ccae38ba1514a7328af68c1b0f6f7b Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 23 Jan 2019 14:31:31 +0100 Subject: [PATCH 02/39] Updated CHANGELOG. --- CHANGELOG.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16614bc62..db5a6684f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,70 @@ +# 3.8 + +## AS3 +* **Breaking changes** + +* **Additions** + +### Starling + +## C +* **Breaking changes** + +* **Additions** + +### Cocos2d-Objc + +### SFML + +## C++ +* ** Additions ** + +* **Breaking changes** + +### Cocos2d-x +### SFML + +### UE4 + +## C# ## +* **Breaking changes** + +* **Additions** + +### Unity + +### XNA/MonoGame + +## Java +* **Breaking changes** + +* **Additions** + +### libGDX + +## Lua +* **Breaking changes** +* +* **Additions** + +### Love2D + +### Corona + +## Typescript/Javascript +* **Breaking changes** + +* **Additions** + +### WebGL backend + +### Canvas backend + +### Three.js backend + +### Player + + # 3.7 ## AS3 From 255bc753d175fd4a6c4da1936626e7f5862c879e Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 28 Jan 2019 16:28:28 +0100 Subject: [PATCH 03/39] [unity] Fixed SkeletonGraphic's 'Starting Animation' property being cleared upon saving under some circumstances, closes #1252. --- .../spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs index 620d2d940..bb666e21f 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs @@ -72,7 +72,6 @@ namespace Spine.Unity { } else if (skeletonDataAsset.GetSkeletonData(true) != skeleton.data) { Clear(); Initialize(true); - startingAnimation = ""; if (skeletonDataAsset.atlasAssets.Length > 1 || skeletonDataAsset.atlasAssets[0].MaterialCount > 1) Debug.LogError("Unity UI does not support multiple textures per Renderer. Your skeleton will not be rendered correctly. Recommend using SkeletonAnimation instead. This requires the use of a Screen space camera canvas."); } else { @@ -275,6 +274,9 @@ namespace Spine.Unity { } #endif } + else { + startingAnimation = string.Empty; + } } } From e6e699df080441a518711973de2e2b492590948c Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 28 Jan 2019 19:54:06 +0100 Subject: [PATCH 04/39] [unity] Changed default texture settings and added warning to prevent border artifacts when mip maps are enabled on PMA textures. Closes #1266. --- .../Editor/SpineEditorUtilities.cs | 74 ++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index 89b2aaa77..5c66ba6d7 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -228,6 +228,10 @@ namespace Spine.Unity.Editor { DataReloadHandler.OnPlaymodeStateChanged(); #endif + if (SpineEditorUtilities.Preferences.textureImporterWarning) { + IssueWarningsForUnrecommendedTextureSettings(); + } + initialized = true; } @@ -235,7 +239,40 @@ namespace Spine.Unity.Editor { if (!initialized || Icons.skeleton == null) Initialize(); } -#endregion + + public static void IssueWarningsForUnrecommendedTextureSettings() { + + string[] atlasDescriptionGUIDs = AssetDatabase.FindAssets("t:textasset .atlas"); // Note: finds .atlas.txt files + for (int i = 0; i < atlasDescriptionGUIDs.Length; ++i) { + string atlasDescriptionPath = AssetDatabase.GUIDToAssetPath(atlasDescriptionGUIDs[i]); + string texturePath = atlasDescriptionPath.Replace(".atlas.txt", ".png"); + + bool textureExists = IssueWarningsForUnrecommendedTextureSettings(texturePath); + if (!textureExists) { + texturePath = texturePath.Replace(".png", ".jpg"); + textureExists = IssueWarningsForUnrecommendedTextureSettings(texturePath); + } + if (!textureExists) { + continue; + } + } + } + + public static bool IssueWarningsForUnrecommendedTextureSettings(string texturePath) + { + TextureImporter texImporter = (TextureImporter)TextureImporter.GetAtPath(texturePath); + if (texImporter == null) { + return false; + } + + // 'sRGBTexture = true' generates incorrectly weighted mipmaps at PMA textures, + // causing white borders due to undesired custom weighting. + if (texImporter.sRGBTexture && texImporter.mipmapEnabled) { + Debug.LogWarningFormat("`{0}` : Incorrect Texture Settings found: When enabling `Generate Mip Maps`, it is strongly recommended to disable `sRGB (Color Texture)`. Otherwise you will receive white border artifacts on an atlas exported with default `Premultiply alpha` settings.\n(You can disable this warning in `Edit - Preferences - Spine`)", texturePath); + } + return true; + } + #endregion public static class Preferences { #if SPINE_TK2D @@ -272,7 +309,11 @@ namespace Spine.Unity.Editor { const bool DEFAULT_ATLASTXT_WARNING = true; const string ATLASTXT_WARNING_KEY = "SPINE_ATLASTXT_WARNING"; - public static bool atlasTxtImportWarning = DEFAULT_SET_TEXTUREIMPORTER_SETTINGS; + public static bool atlasTxtImportWarning = DEFAULT_ATLASTXT_WARNING; + + const bool DEFAULT_TEXTUREIMPORTER_WARNING = true; + const string TEXTUREIMPORTER_WARNING_KEY = "SPINE_TEXTUREIMPORTER_WARNING"; + public static bool textureImporterWarning = DEFAULT_TEXTUREIMPORTER_WARNING; internal const float DEFAULT_MIPMAPBIAS = -0.5f; @@ -297,6 +338,7 @@ namespace Spine.Unity.Editor { setTextureImporterSettings = EditorPrefs.GetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, DEFAULT_SET_TEXTUREIMPORTER_SETTINGS); autoReloadSceneSkeletons = EditorPrefs.GetBool(AUTO_RELOAD_SCENESKELETONS_KEY, DEFAULT_AUTO_RELOAD_SCENESKELETONS); atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, DEFAULT_ATLASTXT_WARNING); + textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, DEFAULT_TEXTUREIMPORTER_WARNING); SpineHandles.handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, DEFAULT_SCENE_ICONS_SCALE); preferencesLoaded = true; @@ -332,7 +374,13 @@ namespace Spine.Unity.Editor { EditorPrefs.SetString(DEFAULT_SHADER_KEY, defaultShader); SpineEditorUtilities.BoolPrefsField(ref setTextureImporterSettings, SET_TEXTUREIMPORTER_SETTINGS_KEY, new GUIContent("Apply Atlas Texture Settings", "Apply the recommended settings for Texture Importers.")); + } + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Warnings", EditorStyles.boldLabel); + { SpineEditorUtilities.BoolPrefsField(ref atlasTxtImportWarning, ATLASTXT_WARNING_KEY, new GUIContent("Atlas Extension Warning", "Log a warning and recommendation whenever a `.atlas` file is found.")); + SpineEditorUtilities.BoolPrefsField(ref textureImporterWarning, TEXTUREIMPORTER_WARNING_KEY, new GUIContent("Texture Settings Warning", "Log a warning and recommendation whenever Texture Import Settings are detected that could lead to undesired effects, e.g. white border artifacts.")); } EditorGUILayout.Space(); @@ -841,6 +889,10 @@ namespace Spine.Unity.Editor { continue; } + // Note: 'sRGBTexture = false' below might seem counter-intuitive, but prevents mipmaps from being + // generated incorrectly (causing white borders due to undesired custom weighting) for PMA textures + // when mipmaps are enabled later. + texImporter.sRGBTexture = false; texImporter.textureCompression = TextureImporterCompression.Uncompressed; texImporter.alphaSource = TextureImporterAlphaSource.FromInput; texImporter.mipmapEnabled = false; @@ -1740,6 +1792,24 @@ namespace Spine.Unity.Editor { } } + public class TextureModificationWarningProcessor : UnityEditor.AssetModificationProcessor + { + static string[] OnWillSaveAssets(string[] paths) + { + if (SpineEditorUtilities.Preferences.textureImporterWarning) { + foreach (string path in paths) { + if (path.EndsWith(".png.meta", System.StringComparison.Ordinal) || + path.EndsWith(".jpg.meta", System.StringComparison.Ordinal)) { + + string texturePath = System.IO.Path.ChangeExtension(path, null); + SpineEditorUtilities.IssueWarningsForUnrecommendedTextureSettings(texturePath); + } + } + } + return paths; + } + } + public static class SpineHandles { internal static float handleScale = 1f; public static Color BoneColor { get { return new Color(0.8f, 0.8f, 0.8f, 0.4f); } } From dba1055346319544f996ccef2cc027436319a038 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 28 Jan 2019 20:08:48 +0100 Subject: [PATCH 05/39] [unity] Fixed previous commit's texture settings warning code preventing border artifacts when mip maps are enabled on PMA textures. Now only issues warning on Spine atlas textures. See #1266. --- .../Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index 5c66ba6d7..d99f2b63a 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -1801,8 +1801,10 @@ namespace Spine.Unity.Editor { if (path.EndsWith(".png.meta", System.StringComparison.Ordinal) || path.EndsWith(".jpg.meta", System.StringComparison.Ordinal)) { - string texturePath = System.IO.Path.ChangeExtension(path, null); - SpineEditorUtilities.IssueWarningsForUnrecommendedTextureSettings(texturePath); + string texturePath = System.IO.Path.ChangeExtension(path, null); // .meta removed + string atlasPath = System.IO.Path.ChangeExtension(texturePath, "atlas.txt"); + if (System.IO.File.Exists(atlasPath)) + SpineEditorUtilities.IssueWarningsForUnrecommendedTextureSettings(texturePath); } } } From 6917302d1c1718c5e65173d8d7f1a32616c4ce19 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 29 Jan 2019 16:34:01 +0100 Subject: [PATCH 06/39] [unity] Added an additional warning when `Alpha Is Transparency` is enabled at PMA textures, which causes incorrect light ghosting in transparent areas. See #1266. --- .../spine-unity/Editor/SpineEditorUtilities.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index d99f2b63a..87732549c 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -167,6 +167,8 @@ namespace Spine.Unity.Editor { public static string editorGUIPath = ""; public static bool initialized; + static int STRAIGHT_ALPHA_PARAM_ID = Shader.PropertyToID("_StraightAlphaInput"); + // Preferences entry point [PreferenceItem("Spine")] static void PreferencesGUI () { @@ -270,6 +272,18 @@ namespace Spine.Unity.Editor { if (texImporter.sRGBTexture && texImporter.mipmapEnabled) { Debug.LogWarningFormat("`{0}` : Incorrect Texture Settings found: When enabling `Generate Mip Maps`, it is strongly recommended to disable `sRGB (Color Texture)`. Otherwise you will receive white border artifacts on an atlas exported with default `Premultiply alpha` settings.\n(You can disable this warning in `Edit - Preferences - Spine`)", texturePath); } + if (texImporter.alphaIsTransparency) { + int extensionPos = texturePath.LastIndexOf('.'); + string materialPath = texturePath.Substring(0, extensionPos) + "_Material.mat"; + Material material = AssetDatabase.LoadAssetAtPath(materialPath); + if (material != null) { + int straightAlphaValue = material.GetInt(STRAIGHT_ALPHA_PARAM_ID); + if (straightAlphaValue == 0) { + string materialName = System.IO.Path.GetFileName(materialPath); + Debug.LogWarningFormat("`{0}` and material `{1}` : Incorrect Texture / Material Settings found: It is strongly recommended to disable `Alpha Is Transparency` on `Premultiply alpha` textures.\nAssuming `Premultiply alpha` texture because `Straight Alpha Texture` is disabled at material). (You can disable this warning in `Edit - Preferences - Spine`)", texturePath, materialName); + } + } + } return true; } #endregion From 098f4b88d21347582e0aa981b1c65540e414a00b Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 29 Jan 2019 16:39:12 +0100 Subject: [PATCH 07/39] [unity] Updated changelog for added detection of incorrect material settings feature. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db5a6684f..6e5453e42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -198,6 +198,10 @@ * Dedicated straight alpha shaders were removed from the runtime. * `Spine/Straight Alpha/Skeleton Fill` * `Spine/Straight Alpha/Skeleton Tint` +* **Detection of incorrect Texture Settings** Especially when atlas textures are exported with setting `Premultiply alpha` enabled, it is important to configure Unity's texture import settings correctly. By default you will now receive warnings where texture settings are expected to cause incorrect rendering. The following rules apply: + * `sRGB (Color Texture)` must be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. + * `Alpha Is Transparency` must be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. + These warnings can be disabled in `Edit - Preferences - Spine`. ### XNA/MonoGame * Added support for any `Effect` to be used by `SkeletonRenderer` From efbb0b936a0887b6dcbfb0e045e60f7080839094 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 29 Jan 2019 17:01:43 +0100 Subject: [PATCH 08/39] [unity] Minor changelog text modification in section `Detection of Incorrect Texture Settings`. --- CHANGELOG.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e5453e42..bc94f3c8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -198,10 +198,11 @@ * Dedicated straight alpha shaders were removed from the runtime. * `Spine/Straight Alpha/Skeleton Fill` * `Spine/Straight Alpha/Skeleton Tint` -* **Detection of incorrect Texture Settings** Especially when atlas textures are exported with setting `Premultiply alpha` enabled, it is important to configure Unity's texture import settings correctly. By default you will now receive warnings where texture settings are expected to cause incorrect rendering. The following rules apply: - * `sRGB (Color Texture)` must be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. - * `Alpha Is Transparency` must be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. - These warnings can be disabled in `Edit - Preferences - Spine`. +* **Detection of Incorrect Texture Settings** Especially when atlas textures are exported with setting `Premultiply alpha` enabled, it is important to configure Unity's texture import settings correctly. By default, you will now receive warnings where texture settings are expected to cause incorrect rendering. + * The following rules apply: + * `sRGB (Color Texture)` shall be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. + * `Alpha Is Transparency` shall be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. + * These warnings can be disabled in `Edit - Preferences - Spine`. ### XNA/MonoGame * Added support for any `Effect` to be used by `SkeletonRenderer` From 1638aa2c5ff56be25f80bf544e7fbbdebf716155 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Thu, 31 Jan 2019 14:43:39 +0100 Subject: [PATCH 09/39] [unity] Fixed SkeletonGraphic related import error occurring occasionally on first import. Error message was usually 'Skeleton JSON file not set for SkeletonData asset'. Closes #1226. --- .../Editor/SpineEditorUtilities.cs | 32 ++++++++++++++++++- .../SkeletonGraphic/SkeletonGraphic.cs | 21 +++++++++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index 87732549c..acad6572a 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -453,6 +453,9 @@ namespace Spine.Unity.Editor { public static class DataReloadHandler { + + internal static Dictionary savedSkeletonDataAssetAtSKeletonGraphicID = new Dictionary(); + #if NEWPLAYMODECALLBACKS internal static void OnPlaymodeStateChanged (PlayModeStateChange stateChange) { #else @@ -462,6 +465,7 @@ namespace Spine.Unity.Editor { } public static void ReloadAllActiveSkeletonsEditMode () { + if (EditorApplication.isPaused) return; if (EditorApplication.isPlaying) return; if (EditorApplication.isCompiling) return; @@ -475,10 +479,20 @@ namespace Spine.Unity.Editor { if (skeletonDataAsset != null) skeletonDataAssetsToReload.Add(skeletonDataAsset); } + // Under some circumstances (e.g. on first import) SkeletonGraphic objects + // have their skeletonGraphic.skeletonDataAsset reference corrupted + // by the instance of the ScriptableObject being destroyed but still assigned. + // Here we save the skeletonGraphic.skeletonDataAsset asset path in order + // to restore it later. var activeSkeletonGraphics = GameObject.FindObjectsOfType(); foreach (var sg in activeSkeletonGraphics) { var skeletonDataAsset = sg.skeletonDataAsset; - if (skeletonDataAsset != null) skeletonDataAssetsToReload.Add(skeletonDataAsset); + if (skeletonDataAsset != null) { + var assetPath = AssetDatabase.GetAssetPath(skeletonDataAsset); + var sgID = sg.GetInstanceID(); + savedSkeletonDataAssetAtSKeletonGraphicID[sgID] = assetPath; + skeletonDataAssetsToReload.Add(skeletonDataAsset); + } } foreach (var sda in skeletonDataAssetsToReload) { @@ -780,6 +794,22 @@ namespace Spine.Unity.Editor { #endif } // Any post processing of images + + // Under some circumstances (e.g. on first import) SkeletonGraphic objects + // have their skeletonGraphic.skeletonDataAsset reference corrupted + // by the instance of the ScriptableObject being destroyed but still assigned. + // Here we restore broken skeletonGraphic.skeletonDataAsset references. + var skeletonGraphicObjects = Resources.FindObjectsOfTypeAll(typeof(SkeletonGraphic)) as SkeletonGraphic[]; + foreach (var skeletonGraphic in skeletonGraphicObjects) { + + if (skeletonGraphic.skeletonDataAsset == null) { + var skeletonGraphicID = skeletonGraphic.GetInstanceID(); + if (DataReloadHandler.savedSkeletonDataAssetAtSKeletonGraphicID.ContainsKey(skeletonGraphicID)) { + string assetPath = DataReloadHandler.savedSkeletonDataAssetAtSKeletonGraphicID[skeletonGraphicID]; + skeletonGraphic.skeletonDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(assetPath); + } + } + } } static void ReloadSkeletonData (string skeletonJSONPath) { diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs index bb666e21f..a195c5463 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs @@ -64,7 +64,7 @@ namespace Spine.Unity { protected override void OnValidate () { // This handles Scene View preview. base.OnValidate (); - if (this.IsValid) { + if (this.IsValid) { if (skeletonDataAsset == null) { Clear(); } else if (skeletonDataAsset.skeletonJSON == null) { @@ -100,12 +100,16 @@ namespace Spine.Unity { } } else { - if (skeletonDataAsset != null) + // Under some circumstances (e.g. sometimes on the first import) OnValidate is called + // before SpineEditorUtilities.ImportSpineContent, causing an unnecessary exception. + // The (skeletonDataAsset.skeletonJSON != null) condition serves to prevent this exception. + if (skeletonDataAsset != null && skeletonDataAsset.skeletonJSON != null) Initialize(true); - } + } } protected override void Reset () { + base.Reset(); if (material == null || material.shader != Shader.Find("Spine/SkeletonGraphic (Premultiply Alpha)")) Debug.LogWarning("SkeletonGraphic works best with the SkeletonGraphic material."); @@ -154,8 +158,17 @@ namespace Spine.Unity { } protected override void Awake () { + base.Awake (); if (!this.IsValid) { +#if UNITY_EDITOR + // workaround for special import case of open scene where OnValidate and Awake are + // called in wrong order, before setup of Spine assets. + if (!Application.isPlaying) { + if (this.skeletonDataAsset != null && this.skeletonDataAsset.skeletonJSON == null) + return; + } +#endif Initialize(false); Rebuild(CanvasUpdate.PreRender); } @@ -311,5 +324,5 @@ namespace Spine.Unity { //this.UpdateMaterial(); // TODO: This allocates memory. } #endregion - } + } } From b18d6574e8bec374ae926cce4d1253ec8543214e Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Fri, 1 Feb 2019 15:27:43 +0100 Subject: [PATCH 10/39] [unity] Fixed on more occurrence of SkeletonGraphic related import error. Error message was 'Skeleton JSON file not set for SkeletonData asset'. Closes #1226. --- .../Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs index 726f0ce9a..d8e2df613 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs @@ -132,6 +132,9 @@ namespace Spine.Unity.Editor { string LastSkinName { get { return EditorPrefs.GetString(LastSkinKey, ""); } } void HandleOnEnablePreview () { + if (ThisSkeletonDataAsset != null && ThisSkeletonDataAsset.skeletonJSON == null) + return; + preview.Initialize(this.Repaint, ThisSkeletonDataAsset, LastSkinName); preview.PlayPauseAnimation(ThisAnimationName, true); preview.OnSkinChanged -= HandleOnSkinChanged; From 0d09fffb4ce09dbbf4b48cdd123539af8d02321b Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 4 Feb 2019 18:54:42 +0100 Subject: [PATCH 11/39] [unity] Fixed compilation errors when TK2D define is set. Closes #1270. --- .../Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index acad6572a..d6de0651e 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -778,7 +778,7 @@ namespace Spine.Unity.Editor { string dir = Path.GetDirectoryName(skeletonPath); #if SPINE_TK2D - IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp), null); + IngestSpineProject(AssetDatabase.LoadAssetAtPath(skeletonPath), null); #else var localAtlases = FindAtlasesAtPath(dir); var requiredPaths = GetRequiredAtlasRegions(skeletonPath); @@ -1036,8 +1036,8 @@ namespace Spine.Unity.Editor { skeletonDataAsset.fromAnimation = new string[0]; skeletonDataAsset.toAnimation = new string[0]; skeletonDataAsset.duration = new float[0]; - skeletonDataAsset.defaultMix = defaultMix; - skeletonDataAsset.scale = defaultScale; + skeletonDataAsset.defaultMix = SpineEditorUtilities.Preferences.defaultMix; + skeletonDataAsset.scale = SpineEditorUtilities.Preferences.defaultScale; AssetDatabase.CreateAsset(skeletonDataAsset, filePath); AssetDatabase.SaveAssets(); From 009929bbc9a88a68b6d539cb3a8fc8102ec7ce98 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Wed, 6 Feb 2019 19:13:03 +0100 Subject: [PATCH 12/39] [unity] Fixed SkeletonPartsRenderer mesh tangent error. Also fixed another potential size mismatch at mesh normals or tangents vs vertices. Closes #1265. --- .../spine-unity/Mesh Generation/SpineMesh.cs | 25 +++++++++---------- .../SkeletonPartsRenderer.cs | 2 +- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/SpineMesh.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/SpineMesh.cs index 67a69c2b2..4108eef62 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/SpineMesh.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/SpineMesh.cs @@ -1009,19 +1009,18 @@ namespace Spine.Unity { } { - int vertexCount = this.vertexBuffer.Count; if (settings.addNormals) { int oldLength = 0; if (normals == null) - normals = new Vector3[vertexCount]; + normals = new Vector3[vbiLength]; else oldLength = normals.Length; - if (oldLength < vertexCount) { - Array.Resize(ref this.normals, vertexCount); + if (oldLength != vbiLength) { + Array.Resize(ref this.normals, vbiLength); var localNormals = this.normals; - for (int i = oldLength; i < vertexCount; i++) localNormals[i] = Vector3.back; + for (int i = oldLength; i < vbiLength; i++) localNormals[i] = Vector3.back; } mesh.normals = this.normals; } @@ -1029,7 +1028,7 @@ namespace Spine.Unity { if (settings.tintBlack) { if (uv2 != null) { // Sometimes, the vertex buffer becomes smaller. We need to trim the size of the tint black buffers to match. - if (vbiLength > uv2.Items.Length) { + if (vbiLength != uv2.Items.Length) { Array.Resize(ref uv2.Items, vbiLength); Array.Resize(ref uv3.Items, vbiLength); uv2.Count = uv3.Count = vbiLength; @@ -1049,7 +1048,7 @@ namespace Spine.Unity { var vbi = vertexBuffer.Items; var ubi = uvBuffer.Items; - MeshGenerator.SolveTangents2DEnsureSize(ref this.tangents, ref this.tempTanBuffer, vertexCount); + MeshGenerator.SolveTangents2DEnsureSize(ref this.tangents, ref this.tempTanBuffer, vertexCount, vbi.Length); for (int i = 0; i < submeshCount; i++) { var submesh = sbi[i].Items; int triangleCount = sbi[i].Count; @@ -1115,9 +1114,9 @@ namespace Spine.Unity { if (uv2 != null) uv2.TrimExcess(); if (uv3 != null) uv3.TrimExcess(); - int count = vertexBuffer.Count; - if (normals != null) Array.Resize(ref normals, count); - if (tangents != null) Array.Resize(ref tangents, count); + int vbiLength = vertexBuffer.Items.Length; + if (normals != null) Array.Resize(ref normals, vbiLength); + if (tangents != null) Array.Resize(ref tangents, vbiLength); } #region TangentSolver2D @@ -1127,9 +1126,9 @@ namespace Spine.Unity { /// Eventual Vector4[] tangent buffer to assign to Mesh.tangents. /// Temporary Vector2 buffer for calculating directions. /// Number of vertices that require tangents (or the size of the vertex array) - internal static void SolveTangents2DEnsureSize (ref Vector4[] tangentBuffer, ref Vector2[] tempTanBuffer, int vertexCount) { - if (tangentBuffer == null || tangentBuffer.Length < vertexCount) - tangentBuffer = new Vector4[vertexCount]; + internal static void SolveTangents2DEnsureSize (ref Vector4[] tangentBuffer, ref Vector2[] tempTanBuffer, int vertexCount, int vertexBufferLength) { + if (tangentBuffer == null || tangentBuffer.Length != vertexBufferLength) + tangentBuffer = new Vector4[vertexBufferLength]; if (tempTanBuffer == null || tempTanBuffer.Length < vertexCount * 2) tempTanBuffer = new Vector2[vertexCount * 2]; // two arrays in one. diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs index 3af331ca6..64a9a5a4b 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs @@ -116,8 +116,8 @@ namespace Spine.Unity.Modules { } else if (buffers.MaterialsChangedInLastUpdate()) { meshRenderer.sharedMaterials = buffers.GetUpdatedSharedMaterialsArray(); } + meshGenerator.FillLateVertexData(mesh); } - meshGenerator.FillLateVertexData(mesh); meshFilter.sharedMesh = mesh; smartMesh.instructionUsed.Set(currentInstructions); From 9d3c9dd443fd7ca01e054af1d136df0d13f9fb68 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Thu, 7 Feb 2019 22:22:56 +0100 Subject: [PATCH 13/39] [unity] SkeletonRenderSeparator now initializes added SkeletonPartsRenderer children correctly. Closes #1269. --- .../SkeletonRenderSeparatorInspector.cs | 22 +++++++++++++++++-- .../SkeletonRenderSeparator.cs | 4 ++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs index 0114cbbb5..26d56d348 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs @@ -51,6 +51,7 @@ namespace Spine.Unity.Modules { SerializedProperty separatorNamesProp; static bool skeletonRendererExpanded = true; bool slotsReapplyRequired = false; + bool partsRendererInitRequired = false; void OnEnable () { if (component == null) @@ -78,6 +79,14 @@ namespace Spine.Unity.Modules { } public override void OnInspectorGUI () { + + // Restore mesh part for undo logic after undo of "Add Parts Renderer". + // Triggers regeneration and assignment of the mesh filter's mesh. + if (component.GetComponent() && component.GetComponent().sharedMesh == null) { + component.OnDisable(); + component.OnEnable(); + } + var componentRenderers = component.partsRenderers; int totalParts; @@ -177,6 +186,7 @@ namespace Spine.Unity.Modules { if (GUILayout.Button(addMissingLabel, GUILayout.Height(40f))) { AddPartsRenderer(extraRenderersNeeded); DetectOrphanedPartsRenderers(component); + partsRendererInitRequired = true; } } } @@ -202,14 +212,22 @@ namespace Spine.Unity.Modules { } // (Button) Add Part Renderer button - if (GUILayout.Button("Add Parts Renderer")) - AddPartsRenderer(1); + if (GUILayout.Button("Add Parts Renderer")) { + AddPartsRenderer(1); + partsRendererInitRequired = true; + } } } } serializedObject.ApplyModifiedProperties(); + if (partsRendererInitRequired) { + Undo.RegisterCompleteObjectUndo(component.GetComponent(), "Add Parts Renderers"); + component.OnEnable(); + partsRendererInitRequired = false; + } + if (slotsReapplyRequired && UnityEngine.Event.current.type == EventType.Repaint) { component.SkeletonRenderer.ReapplySeparatorSlotNames(); component.SkeletonRenderer.LateUpdate(); diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs index 1c700c0ba..43bbce484 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs @@ -151,7 +151,7 @@ namespace Spine.Unity.Modules { } #endregion - void OnEnable () { + public void OnEnable () { if (skeletonRenderer == null) return; if (copiedBlock == null) copiedBlock = new MaterialPropertyBlock(); mainMeshRenderer = skeletonRenderer.GetComponent(); @@ -184,7 +184,7 @@ namespace Spine.Unity.Modules { } } - void OnDisable () { + public void OnDisable () { if (skeletonRenderer == null) return; #if SPINE_OPTIONAL_RENDEROVERRIDE skeletonRenderer.GenerateMeshOverride -= HandleRender; From 3151f1abbbab9c43844f02c3224c1d515b14982c Mon Sep 17 00:00:00 2001 From: Carlos Ibanez Date: Mon, 11 Feb 2019 13:33:50 -0300 Subject: [PATCH 14/39] - Added support for external tools. - Added UpdateRenderer method, that allows to pass a custom Skeleton and can be called externally. --- .../SpineSkeletonRendererComponent.cpp | 176 +++++++++--------- .../Public/SpineSkeletonRendererComponent.h | 3 + 2 files changed, 94 insertions(+), 85 deletions(-) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp index 588f700eb..3410b7dd6 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp @@ -76,94 +76,100 @@ void USpineSkeletonRendererComponent::TickComponent (float DeltaTime, ELevelTick UClass* skeletonClass = USpineSkeletonComponent::StaticClass(); USpineSkeletonComponent* skeleton = Cast(owner->GetComponentByClass(skeletonClass)); - if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->GetSkeleton() && skeleton->Atlas) { - skeleton->GetSkeleton()->getColor().set(Color.R, Color.G, Color.B, Color.A); - - if (atlasNormalBlendMaterials.Num() != skeleton->Atlas->atlasPages.Num()) { - atlasNormalBlendMaterials.SetNum(0); - pageToNormalBlendMaterial.Empty(); - atlasAdditiveBlendMaterials.SetNum(0); - pageToAdditiveBlendMaterial.Empty(); - atlasMultiplyBlendMaterials.SetNum(0); - pageToMultiplyBlendMaterial.Empty(); - atlasScreenBlendMaterials.SetNum(0); - pageToScreenBlendMaterial.Empty(); - - for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) { - AtlasPage* currPage = skeleton->Atlas->GetAtlas()->getPages()[i]; - - UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, owner); - material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]); - atlasNormalBlendMaterials.Add(material); - pageToNormalBlendMaterial.Add(currPage, material); - - material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, owner); - material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]); - atlasAdditiveBlendMaterials.Add(material); - pageToAdditiveBlendMaterial.Add(currPage, material); - - material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, owner); - material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]); - atlasMultiplyBlendMaterials.Add(material); - pageToMultiplyBlendMaterial.Add(currPage, material); - - material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, owner); - material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]); - atlasScreenBlendMaterials.Add(material); - pageToScreenBlendMaterial.Add(currPage, material); - } - } else { - pageToNormalBlendMaterial.Empty(); - pageToAdditiveBlendMaterial.Empty(); - pageToMultiplyBlendMaterial.Empty(); - pageToScreenBlendMaterial.Empty(); - - for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) { - AtlasPage* currPage = skeleton->Atlas->GetAtlas()->getPages()[i]; - - UTexture2D* texture = skeleton->Atlas->atlasPages[i]; - UTexture* oldTexture = nullptr; - - UMaterialInstanceDynamic* current = atlasNormalBlendMaterials[i]; - if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) { - UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, owner); - material->SetTextureParameterValue(TextureParameterName, texture); - atlasNormalBlendMaterials[i] = material; - } - pageToNormalBlendMaterial.Add(currPage, atlasNormalBlendMaterials[i]); - - current = atlasAdditiveBlendMaterials[i]; - if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) { - UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, owner); - material->SetTextureParameterValue(TextureParameterName, texture); - atlasAdditiveBlendMaterials[i] = material; - } - pageToAdditiveBlendMaterial.Add(currPage, atlasAdditiveBlendMaterials[i]); - - current = atlasMultiplyBlendMaterials[i]; - if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) { - UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, owner); - material->SetTextureParameterValue(TextureParameterName, texture); - atlasMultiplyBlendMaterials[i] = material; - } - pageToMultiplyBlendMaterial.Add(currPage, atlasMultiplyBlendMaterials[i]); - - current = atlasScreenBlendMaterials[i]; - if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) { - UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, owner); - material->SetTextureParameterValue(TextureParameterName, texture); - atlasScreenBlendMaterials[i] = material; - } - pageToScreenBlendMaterial.Add(currPage, atlasScreenBlendMaterials[i]); - } - } - UpdateMesh(skeleton->GetSkeleton()); - } else { - ClearAllMeshSections(); - } + UpdateRenderer(skeleton); } } +void USpineSkeletonRendererComponent::UpdateRenderer(USpineSkeletonComponent* skeleton) +{ + if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->GetSkeleton() && skeleton->Atlas) { + skeleton->GetSkeleton()->getColor().set(Color.R, Color.G, Color.B, Color.A); + + if (atlasNormalBlendMaterials.Num() != skeleton->Atlas->atlasPages.Num()) { + atlasNormalBlendMaterials.SetNum(0); + pageToNormalBlendMaterial.Empty(); + atlasAdditiveBlendMaterials.SetNum(0); + pageToAdditiveBlendMaterial.Empty(); + atlasMultiplyBlendMaterials.SetNum(0); + pageToMultiplyBlendMaterial.Empty(); + atlasScreenBlendMaterials.SetNum(0); + pageToScreenBlendMaterial.Empty(); + + for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) { + AtlasPage* currPage = skeleton->Atlas->GetAtlas()->getPages()[i]; + + UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, this); + material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]); + atlasNormalBlendMaterials.Add(material); + pageToNormalBlendMaterial.Add(currPage, material); + + material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, this); + material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]); + atlasAdditiveBlendMaterials.Add(material); + pageToAdditiveBlendMaterial.Add(currPage, material); + + material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, this); + material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]); + atlasMultiplyBlendMaterials.Add(material); + pageToMultiplyBlendMaterial.Add(currPage, material); + + material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, this); + material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]); + atlasScreenBlendMaterials.Add(material); + pageToScreenBlendMaterial.Add(currPage, material); + } + } + else { + pageToNormalBlendMaterial.Empty(); + pageToAdditiveBlendMaterial.Empty(); + pageToMultiplyBlendMaterial.Empty(); + pageToScreenBlendMaterial.Empty(); + + for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) { + AtlasPage* currPage = skeleton->Atlas->GetAtlas()->getPages()[i]; + + UTexture2D* texture = skeleton->Atlas->atlasPages[i]; + UTexture* oldTexture = nullptr; + + UMaterialInstanceDynamic* current = atlasNormalBlendMaterials[i]; + if (!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) { + UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, this); + material->SetTextureParameterValue(TextureParameterName, texture); + atlasNormalBlendMaterials[i] = material; + } + pageToNormalBlendMaterial.Add(currPage, atlasNormalBlendMaterials[i]); + + current = atlasAdditiveBlendMaterials[i]; + if (!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) { + UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, this); + material->SetTextureParameterValue(TextureParameterName, texture); + atlasAdditiveBlendMaterials[i] = material; + } + pageToAdditiveBlendMaterial.Add(currPage, atlasAdditiveBlendMaterials[i]); + + current = atlasMultiplyBlendMaterials[i]; + if (!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) { + UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, this); + material->SetTextureParameterValue(TextureParameterName, texture); + atlasMultiplyBlendMaterials[i] = material; + } + pageToMultiplyBlendMaterial.Add(currPage, atlasMultiplyBlendMaterials[i]); + + current = atlasScreenBlendMaterials[i]; + if (!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) { + UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, this); + material->SetTextureParameterValue(TextureParameterName, texture); + atlasScreenBlendMaterials[i] = material; + } + pageToScreenBlendMaterial.Add(currPage, atlasScreenBlendMaterials[i]); + } + } + UpdateMesh(skeleton->GetSkeleton()); + } + else { + ClearAllMeshSections(); + } +} void USpineSkeletonRendererComponent::Flush (int &Idx, TArray &Vertices, TArray &Indices, TArray &Uvs, TArray &Colors, TArray& Colors2, UMaterialInstanceDynamic* Material) { if (Vertices.Num() == 0) return; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h index d91375605..ffe71baa8 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h @@ -47,6 +47,9 @@ public: virtual void TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + /* Updates this skeleton renderer using the provided skeleton animation component. */ + void UpdateRenderer(USpineSkeletonComponent* Skeleton); + // Material Instance parents UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly) UMaterialInterface* NormalBlendMaterial; From c88d132406f02f298d67fa5164d2690588bc566d Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 11 Feb 2019 20:39:37 +0100 Subject: [PATCH 15/39] [csharp] Fixed AnimationState not respecting MixBlend.first for rotate timelines. See #1274. --- spine-csharp/src/AnimationState.cs | 53 +++++++++++++++++------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/spine-csharp/src/AnimationState.cs b/spine-csharp/src/AnimationState.cs index 5567c48d4..4094ff226 100644 --- a/spine-csharp/src/AnimationState.cs +++ b/spine-csharp/src/AnimationState.cs @@ -307,42 +307,51 @@ namespace Spine { return mix; } - static private void ApplyRotateTimeline (RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixBlend pose, + static private void ApplyRotateTimeline (RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixBlend blend, float[] timelinesRotation, int i, bool firstFrame) { if (firstFrame) timelinesRotation[i] = 0; if (alpha == 1) { - rotateTimeline.Apply(skeleton, 0, time, null, 1, pose, MixDirection.In); + rotateTimeline.Apply(skeleton, 0, time, null, 1, blend, MixDirection.In); return; } Bone bone = skeleton.bones.Items[rotateTimeline.boneIndex]; float[] frames = rotateTimeline.frames; - if (time < frames[0]) { - if (pose == MixBlend.Setup) bone.rotation = bone.data.rotation; - return; - } + float r1, r2; + if (time < frames[0]) { // Time is before first frame. + switch (blend) { + case MixBlend.Setup: + bone.rotation = bone.data.rotation; + return; + default: + return; + case MixBlend.First: + r1 = bone.rotation; + r2 = bone.data.rotation; + break; + } + } else { + r1 = blend == MixBlend.Setup ? bone.data.rotation : bone.rotation; + if (time >= frames[frames.Length - RotateTimeline.ENTRIES]) // Time is after last frame. + r2 = bone.data.rotation + frames[frames.Length + RotateTimeline.PREV_ROTATION]; + else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, RotateTimeline.ENTRIES); + float prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; + float frameTime = frames[frame]; + float percent = rotateTimeline.GetCurvePercent((frame >> 1) - 1, + 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); - float r2; - if (time >= frames[frames.Length - RotateTimeline.ENTRIES]) // Time is after last frame. - r2 = bone.data.rotation + frames[frames.Length + RotateTimeline.PREV_ROTATION]; - else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, RotateTimeline.ENTRIES); - float prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; - float frameTime = frames[frame]; - float percent = rotateTimeline.GetCurvePercent((frame >> 1) - 1, - 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); - - r2 = frames[frame + RotateTimeline.ROTATION] - prevRotation; - r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; - r2 = prevRotation + r2 * percent + bone.data.rotation; - r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + r2 = frames[frame + RotateTimeline.ROTATION] - prevRotation; + r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + r2 = prevRotation + r2 * percent + bone.data.rotation; + r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + } } // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. - float r1 = pose == MixBlend.Setup ? bone.data.rotation : bone.rotation; float total, diff = r2 - r1; diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; if (diff == 0) { From b90dd126b2d90a83495ff50ee3f4b50618fda687 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 11 Feb 2019 21:28:33 +0100 Subject: [PATCH 16/39] [unity] Fixed Unity Timeline editor errors after `Add Spine Animation State Clip Clip` due to unset Animation Reference. Closes #1257. --- .../SpineAnimationStateMixerBehaviour.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs index 6c94d2eb8..9e8604bd4 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs @@ -138,16 +138,16 @@ namespace Spine.Unity.Playables { if (lastOneWeight != 0 && inputCount > 1) { var fromClip = (ScriptPlayable)playable.GetInput(lastOneWeight - 1); var fromClipData = fromClip.GetBehaviour(); - fromAnimation = fromClipData.animationReference.Animation; + fromAnimation = fromClipData.animationReference != null ? fromClipData.animationReference.Animation : null; fromClipTime = (float)fromClip.GetTime(); fromClipLoop = fromClipData.loop; } - Animation toAnimation = clipData.animationReference.Animation; + Animation toAnimation = clipData.animationReference != null ? clipData.animationReference.Animation : null; float toClipTime = (float)inputPlayableClip.GetTime(); float mixDuration = clipData.mixDuration; - if (!clipData.customDuration && fromAnimation != null) { + if (!clipData.customDuration && fromAnimation != null && toAnimation != null) { mixDuration = spineComponent.AnimationState.Data.GetMix(fromAnimation, toAnimation); } @@ -163,21 +163,25 @@ namespace Spine.Unity.Playables { dummyAnimationState.ClearTracks(); fromTrack = dummyAnimationState.SetAnimation(0, fromAnimation, fromClipLoop); fromTrack.AllowImmediateQueue(); - toTrack = dummyAnimationState.SetAnimation(0, toAnimation, clipData.loop); + if (toAnimation != null) + toTrack = dummyAnimationState.SetAnimation(0, toAnimation, clipData.loop); } // Update track times. fromTrack.trackTime = fromClipTime; - toTrack.trackTime = toClipTime; - toTrack.mixTime = toClipTime; - + if (toTrack != null) { + toTrack.trackTime = toClipTime; + toTrack.mixTime = toClipTime; + } + // Apply Pose skeleton.SetToSetupPose(); dummyAnimationState.Update(0); dummyAnimationState.Apply(skeleton); } else { skeleton.SetToSetupPose(); - toAnimation.PoseSkeleton(skeleton, toClipTime, clipData.loop); + if (toAnimation != null) + toAnimation.PoseSkeleton(skeleton, toClipTime, clipData.loop); } } From 56fc291a40540221e0ac1dc9364be45495321986 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 12 Feb 2019 18:03:12 +0100 Subject: [PATCH 17/39] [unity] Updated Mix and Match documentation in code to mention that GetRepackedSkin() is expensive. --- spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs | 6 ++++-- .../spine-unity/Modules/AttachmentTools/AttachmentTools.cs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs b/spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs index eeebe0d4b..a905cb7da 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/MixAndMatch.cs @@ -111,11 +111,13 @@ namespace Spine.Unity.Examples { // To prevent fallback from happening, make sure the key is not defined in the default skin. // STEP 3: APPLY AND CLEAN UP. - // Recommended: REPACK THE CUSTOM SKIN TO MINIMIZE DRAW CALLS + // Recommended, preferably at level-load-time: REPACK THE CUSTOM SKIN TO MINIMIZE DRAW CALLS + // IMPORTANT NOTE: the GetRepackedSkin() operation is expensive - if multiple characters + // need to call it every few seconds the overhead will outweigh the draw call benefits. + // // Repacking requires that you set all source textures/sprites/atlases to be Read/Write enabled in the inspector. // Combine all the attachment sources into one skin. Usually this means the default skin and the custom skin. // call Skin.GetRepackedSkin to get a cloned skin with cloned attachments that all use one texture. - // Under the hood, this relies on if (repack) { var repackedSkin = new Skin("repacked skin"); repackedSkin.AddAttachments(skeleton.Data.DefaultSkin); // Include the "default" skin. (everything outside of skin placeholders) diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/AttachmentTools/AttachmentTools.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/AttachmentTools/AttachmentTools.cs index 766cec08b..918dda9e8 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/AttachmentTools/AttachmentTools.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/AttachmentTools/AttachmentTools.cs @@ -482,14 +482,14 @@ 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. - /// No Spine.Atlas object is created so there is no way to find AtlasRegions except through the Attachments using them. + /// 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. public static Skin GetRepackedSkin (this Skin o, string newName, Material materialPropertySource, out Material outputMaterial, out Texture2D outputTexture, int maxAtlasSize = 1024, int padding = 2, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps, bool useOriginalNonrenderables = true) { return GetRepackedSkin(o, newName, materialPropertySource.shader, out outputMaterial, out outputTexture, maxAtlasSize, padding, textureFormat, mipmaps, materialPropertySource, useOriginalNonrenderables); } /// /// 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. - /// No Spine.Atlas object is created so there is no way to find AtlasRegions except through the Attachments using them. + /// 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. 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) { if (o == null) throw new System.NullReferenceException("Skin was null"); var skinAttachments = o.Attachments; From e7030d640b3ae694a2f5c24f6ba545f42f4d1e0a Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Fri, 15 Feb 2019 13:04:22 +0100 Subject: [PATCH 18/39] [unity] Fixed compile errors with TK2D define due to asmdef files preventing dependency. Closes #1280. --- .../Editor/SpineEditorUtilities.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index d6de0651e..16ebf3490 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -1785,6 +1785,9 @@ namespace Spine.Unity.Editor { internal static void EnableTK2D () { bool added = false; + + DisableSpineAsmdefFiles(); + foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) { if (IsInvalidGroup(group)) continue; @@ -1811,6 +1814,9 @@ namespace Spine.Unity.Editor { internal static void DisableTK2D () { bool removed = false; + + EnableSpineAsmdefFiles(); + foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) { if (IsInvalidGroup(group)) continue; @@ -1833,6 +1839,31 @@ namespace Spine.Unity.Editor { Debug.LogWarning("Already Removed Scripting Define Symbol " + SPINE_TK2D_DEFINE); } } + + internal static void DisableSpineAsmdefFiles() { + SetAsmdefFileActive("spine-unity-editor", false); + SetAsmdefFileActive("spine-unity", false); + } + + internal static void EnableSpineAsmdefFiles() { + SetAsmdefFileActive("spine-unity-editor", true); + SetAsmdefFileActive("spine-unity", true); + } + + internal static void SetAsmdefFileActive(string filename, bool setActive) { + + string typeSearchString = setActive ? " t:textasset" : " t:asmdef"; + string[] guids = AssetDatabase.FindAssets(filename + typeSearchString); + foreach (string guid in guids) { + string currentPath = AssetDatabase.GUIDToAssetPath(guid); + string targetPath = System.IO.Path.ChangeExtension(currentPath, setActive ? "asmdef" : "txt"); + if (System.IO.File.Exists(currentPath)) { + System.IO.File.Copy(currentPath, targetPath); + System.IO.File.Copy(currentPath + ".meta", targetPath + ".meta"); + } + AssetDatabase.DeleteAsset(currentPath); + } + } } } From 32ac918f8033f36713c75ae016843dcc11758005 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 19 Feb 2019 18:54:55 +0100 Subject: [PATCH 19/39] [unity] Added support for Unity's SpriteMask to SkeletonAnimation and SkeletonMecanim. All mask interaction modes supported. See #941. --- .../Editor/SkeletonRendererInspector.cs | 126 ++++++++- .../spine-unity/Editor/SpineMaskUtilities.cs | 243 ++++++++++++++++++ .../Editor/SpineMaskUtilities.cs.meta | 12 + .../Components/SkeletonRenderer.cs | 79 ++++++ .../Spine-Special-Skeleton-Ghost.shader | 8 + .../Shaders/Spine-Skeleton-Fill.shader | 8 + .../Shaders/Spine-Skeleton-Tint.shader | 8 + .../Spine-Special-Skeleton-Grayscale.shader | 8 + .../Shaders/Sprite/SpritesPixelLit.shader | 8 + .../Shaders/Sprite/SpritesUnlit.shader | 8 + .../Shaders/Sprite/SpritesVertexLit.shader | 8 + .../Spine-Skeleton-PMA-Additive.shader | 8 + .../Spine-Skeleton-PMA-Multiply.shader | 8 + .../Spine-Skeleton-PMA-Screen.shader | 8 + .../Shaders/Spine-Skeleton-TintBlack.shader | 8 + .../spine-unity/Shaders/Spine-Skeleton.shader | 8 + .../Shaders/Spine-SkeletonLit.shader | 8 + 17 files changed, 562 insertions(+), 2 deletions(-) create mode 100644 spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs create mode 100644 spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs.meta diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs index 021ba4ff0..f777addc4 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs @@ -54,14 +54,23 @@ namespace Spine.Unity.Editor { protected SerializedProperty initialFlipX, initialFlipY; protected SerializedProperty singleSubmesh, separatorSlotNames, clearStateOnDisable, immutableTriangles; protected SerializedProperty normals, tangents, zSpacing, pmaVertexColors, tintBlack; // MeshGenerator settings + protected SerializedProperty maskInteraction; + protected SerializedProperty maskMaterialsNone, maskMaterialsInside, maskMaterialsOutside; protected SpineInspectorUtility.SerializedSortingProperties sortingProperties; protected bool isInspectingPrefab; protected bool forceReloadQueued = false; + protected bool setMaskNoneMaterialsQueued = false; + protected bool setInsideMaskMaterialsQueued = false; + protected bool setOutsideMaskMaterialsQueued = false; + protected bool deleteInsideMaskMaterialsQueued = false; + protected bool deleteOutsideMaskMaterialsQueued = false; protected GUIContent SkeletonDataAssetLabel, SkeletonUtilityButtonContent; protected GUIContent PMAVertexColorsLabel, ClearStateOnDisableLabel, ZSpacingLabel, ImmubleTrianglesLabel, TintBlackLabel, SingleSubmeshLabel; - protected GUIContent NormalsLabel, TangentsLabel; + protected GUIContent NormalsLabel, TangentsLabel, MaskInteractionLabel; + protected GUIContent MaskMaterialsHeadingLabel, MaskMaterialsNoneLabel, MaskMaterialsInsideLabel, MaskMaterialsOutsideLabel; + protected GUIContent SetMaterialButtonLabel, ClearMaterialButtonLabel, DeleteMaterialButtonLabel; const string ReloadButtonString = "Reload"; static GUILayoutOption reloadButtonWidth; @@ -104,6 +113,14 @@ namespace Spine.Unity.Editor { TangentsLabel = new GUIContent("Solve Tangents", "Calculates the tangents per frame. Use this if you are using lit shaders (usually with normal maps) that require vertex tangents."); TintBlackLabel = new GUIContent("Tint Black (!)", "Adds black tint vertex data to the mesh as UV2 and UV3. Black tinting requires that the shader interpret UV2 and UV3 as black tint colors for this effect to work. You may also use the default [Spine/Skeleton Tint Black] shader.\n\nIf you only need to tint the whole skeleton and not individual parts, the [Spine/Skeleton Tint] shader is recommended for better efficiency and changing/animating the _Black material property via MaterialPropertyBlock."); SingleSubmeshLabel = new GUIContent("Use Single Submesh", "Simplifies submesh generation by assuming you are only using one Material and need only one submesh. This is will disable multiple materials, render separation, and custom slot materials."); + MaskInteractionLabel = new GUIContent("Mask Interaction", "SkeletonRenderer's interaction with a Sprite Mask."); + MaskMaterialsHeadingLabel = new GUIContent("Mask Interaction Materials", "Materials used for different interaction with sprite masks."); + MaskMaterialsNoneLabel = new GUIContent("Normal Materials", "Normal materials used when Mask Interaction is set to None."); + MaskMaterialsInsideLabel = new GUIContent("Inside Mask", "Materials used when Mask Interaction is set to Inside Mask."); + MaskMaterialsOutsideLabel = new GUIContent("Outside Mask", "Materials used when Mask Interaction is set to Outside Mask."); + SetMaterialButtonLabel = new GUIContent("Set", "Prepares material references for switching to the corresponding Mask Interaction mode at runtime. Creates the required materials if they do not exist."); + ClearMaterialButtonLabel = new GUIContent("Clear", "Clears unused material references. Note: when switching to the corresponding Mask Interaction mode at runtime, a new material is generated on the fly."); + DeleteMaterialButtonLabel = new GUIContent("Delete", "Clears unused material references and deletes the corresponding assets. Note: when switching to the corresponding Mask Interaction mode at runtime, a new material is generated on the fly."); var so = this.serializedObject; skeletonDataAsset = so.FindProperty("skeletonDataAsset"); @@ -117,6 +134,10 @@ namespace Spine.Unity.Editor { clearStateOnDisable = so.FindProperty("clearStateOnDisable"); tintBlack = so.FindProperty("tintBlack"); singleSubmesh = so.FindProperty("singleSubmesh"); + maskInteraction = so.FindProperty("maskInteraction"); + maskMaterialsNone = so.FindProperty("maskMaterials.materialsMaskDisabled"); + maskMaterialsInside = so.FindProperty("maskMaterials.materialsInsideMask"); + maskMaterialsOutside = so.FindProperty("maskMaterials.materialsOutsideMask"); separatorSlotNames = so.FindProperty("separatorSlotNames"); separatorSlotNames.isExpanded = true; @@ -139,7 +160,8 @@ namespace Spine.Unity.Editor { override public void OnInspectorGUI () { bool multi = serializedObject.isEditingMultipleObjects; DrawInspectorGUI(multi); - if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current)) { + if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current) || + AreAnyMaskMaterialsMissing()) { if (!Application.isPlaying) { if (multi) { foreach (var o in targets) EditorForceInitializeComponent((SkeletonRenderer)o); @@ -193,6 +215,33 @@ namespace Spine.Unity.Editor { } } + if (setMaskNoneMaterialsQueued) { + setMaskNoneMaterialsQueued = false; + foreach (var c in targets) + EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.None); + } + if (setInsideMaskMaterialsQueued) { + setInsideMaskMaterialsQueued = false; + foreach (var c in targets) + EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleInsideMask); + } + if (setOutsideMaskMaterialsQueued) { + setOutsideMaskMaterialsQueued = false; + foreach (var c in targets) + EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleOutsideMask); + } + + if (deleteInsideMaskMaterialsQueued) { + deleteInsideMaskMaterialsQueued = false; + foreach (var c in targets) + EditorDeleteMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleInsideMask); + } + if (deleteOutsideMaskMaterialsQueued) { + deleteOutsideMaskMaterialsQueued = false; + foreach (var c in targets) + EditorDeleteMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleOutsideMask); + } + #if NO_PREFAB_MESH if (isInspectingPrefab) { if (multi) { @@ -255,6 +304,8 @@ namespace Spine.Unity.Editor { // Sorting Layers SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true); + if (maskInteraction != null) EditorGUILayout.PropertyField(maskInteraction, MaskInteractionLabel); + if (!valid) return; @@ -311,6 +362,21 @@ namespace Spine.Unity.Editor { if (tangents != null) EditorGUILayout.PropertyField(tangents, TangentsLabel); } + EditorGUILayout.Space(); + if (maskMaterialsNone.arraySize > 0 || maskMaterialsInside.arraySize > 0 || maskMaterialsOutside.arraySize > 0) { + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Mask Interaction Materials", SpineInspectorUtility.UnityIcon()), EditorStyles.boldLabel); + bool differentMaskModesSelected = maskInteraction.hasMultipleDifferentValues; + int activeMaskInteractionValue = differentMaskModesSelected ? -1 : maskInteraction.intValue; + + bool ignoredParam = true; + MaskMaterialsEditingField(ref setMaskNoneMaterialsQueued, ref ignoredParam, maskMaterialsNone, MaskMaterialsNoneLabel, + differentMaskModesSelected, allowDelete : false, isActiveMaterial : activeMaskInteractionValue == (int)SpriteMaskInteraction.None); + MaskMaterialsEditingField(ref setInsideMaskMaterialsQueued, ref deleteInsideMaskMaterialsQueued, maskMaterialsInside, MaskMaterialsInsideLabel, + differentMaskModesSelected, allowDelete: true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleInsideMask); + MaskMaterialsEditingField(ref setOutsideMaskMaterialsQueued, ref deleteOutsideMaskMaterialsQueued, maskMaterialsOutside, MaskMaterialsOutsideLabel, + differentMaskModesSelected, allowDelete : true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleOutsideMask); + } + EditorGUILayout.Space(); if (valid && !isInspectingPrefab) { @@ -388,6 +454,38 @@ namespace Spine.Unity.Editor { } } + public void MaskMaterialsEditingField(ref bool wasSetRequested, ref bool wasDeleteRequested, + SerializedProperty maskMaterials, GUIContent label, + bool differentMaskModesSelected, bool allowDelete, bool isActiveMaterial) { + using (new EditorGUILayout.HorizontalScope()) { + + EditorGUILayout.LabelField(label, isActiveMaterial ? EditorStyles.boldLabel : EditorStyles.label, GUILayout.MinWidth(80f), GUILayout.MaxWidth(140)); + EditorGUILayout.LabelField(maskMaterials.hasMultipleDifferentValues ? "-" : maskMaterials.arraySize.ToString(), EditorStyles.miniLabel, GUILayout.Width(42f)); + + bool enableSetButton = differentMaskModesSelected || maskMaterials.arraySize == 0; + bool enableClearButtons = differentMaskModesSelected || (maskMaterials.arraySize != 0 && !isActiveMaterial); + + EditorGUI.BeginDisabledGroup(!enableSetButton); + if (GUILayout.Button(SetMaterialButtonLabel, EditorStyles.miniButtonLeft, GUILayout.Width(46f))) { + wasSetRequested = true; + } + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup(!enableClearButtons); + { + if (GUILayout.Button(ClearMaterialButtonLabel, allowDelete ? EditorStyles.miniButtonMid : EditorStyles.miniButtonRight, GUILayout.Width(46f))) { + maskMaterials.ClearArray(); + } + else if (allowDelete && GUILayout.Button(DeleteMaterialButtonLabel, EditorStyles.miniButtonRight, GUILayout.Width(46f))) { + wasDeleteRequested = true; + } + if (!allowDelete) + GUILayout.Space(46f); + } + EditorGUI.EndDisabledGroup(); + } + } + static bool UpdateIfSkinMismatch (SkeletonRenderer skeletonRenderer) { if (!skeletonRenderer.valid) return false; @@ -427,12 +525,36 @@ namespace Spine.Unity.Editor { if (component == null) return; if (!SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return; component.Initialize(true); + SpineMaskUtilities.EditorAssignSpriteMaskMaterials(component); component.LateUpdate(); } + bool AreAnyMaskMaterialsMissing() { + foreach (var o in targets) { + var component = (SkeletonRenderer)o; + if (!component.valid) + continue; + if (SpineMaskUtilities.AreMaskMaterialsMissing(component)) + return true; + } + return false; + } + static bool SkeletonDataAssetIsValid (SkeletonDataAsset asset) { return asset != null && asset.GetSkeletonData(quiet: true) != null; } + static void EditorSetMaskMaterials(SkeletonRenderer component, SpriteMaskInteraction maskType) + { + if (component == null) return; + if (!SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return; + SpineMaskUtilities.EditorInitMaskMaterials(component, component.maskMaterials, maskType); + } + + static void EditorDeleteMaskMaterials(SkeletonRenderer component, SpriteMaskInteraction maskType) { + if (component == null) return; + if (!SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return; + SpineMaskUtilities.EditorDeleteMaskMaterials(component.maskMaterials, maskType); + } } } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs new file mode 100644 index 000000000..9781bb0cc --- /dev/null +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs @@ -0,0 +1,243 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2019, 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. + *****************************************************************************/ + +#pragma warning disable 0219 + +#define SPINE_SKELETONMECANIM + +#if UNITY_2017_2_OR_NEWER +#define NEWPLAYMODECALLBACKS +#endif + +#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER +#define NEW_PREFAB_SYSTEM +#endif + +#if UNITY_2018 || UNITY_2019 || UNITY_2018_3_OR_NEWER +#define NEWHIERARCHYWINDOWCALLBACKS +#endif + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Linq; +using System.Reflection; + +namespace Spine.Unity.Editor { + + public class SpineMaskUtilities { + + private const string MATERIAL_FILENAME_SUFFIX_INSIDE_MASK = "_InsideMask"; + private const string MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK = "_OutsideMask"; + + public static void EditorAssignSpriteMaskMaterials(SkeletonRenderer skeleton) { + var maskMaterials = skeleton.maskMaterials; + var maskInteraction = skeleton.maskInteraction; + var meshRenderer = skeleton.GetComponent(); + + if (maskMaterials.materialsMaskDisabled.Length > 0 && maskMaterials.materialsMaskDisabled[0] != null && + maskInteraction == SpriteMaskInteraction.None) { + meshRenderer.materials = maskMaterials.materialsMaskDisabled; + } + else if (maskInteraction == SpriteMaskInteraction.VisibleInsideMask) { + if (maskMaterials.materialsInsideMask.Length == 0 || maskMaterials.materialsInsideMask[0] == null) + EditorInitSpriteMaskMaterialsInsideMask(skeleton); + meshRenderer.materials = maskMaterials.materialsInsideMask; + } + else if (maskInteraction == SpriteMaskInteraction.VisibleOutsideMask) { + if (maskMaterials.materialsOutsideMask.Length == 0 || maskMaterials.materialsOutsideMask[0] == null) + EditorInitSpriteMaskMaterialsOutsideMask(skeleton); + meshRenderer.materials = maskMaterials.materialsOutsideMask; + } + } + + public static bool AreMaskMaterialsMissing(SkeletonRenderer skeleton) { + var maskMaterials = skeleton.maskMaterials; + var maskInteraction = skeleton.maskInteraction; + + if (maskInteraction == SpriteMaskInteraction.None) { + return (maskMaterials.materialsMaskDisabled.Length == 0 || maskMaterials.materialsMaskDisabled[0] == null); + } + else if (maskInteraction == SpriteMaskInteraction.VisibleInsideMask) { + return (maskMaterials.materialsInsideMask.Length == 0 || maskMaterials.materialsInsideMask[0] == null); + } + else if (maskInteraction == SpriteMaskInteraction.VisibleOutsideMask) { + return (maskMaterials.materialsOutsideMask.Length == 0 || maskMaterials.materialsOutsideMask[0] == null); + } + return false; + } + + public static void EditorInitMaskMaterials(SkeletonRenderer skeleton, SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials, SpriteMaskInteraction maskType) { + if (maskType == SpriteMaskInteraction.None) { + EditorConfirmDisabledMaskMaterialsInit(skeleton); + } + else if (maskType == SpriteMaskInteraction.VisibleInsideMask) { + EditorInitSpriteMaskMaterialsInsideMask(skeleton); + } + else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) { + EditorInitSpriteMaskMaterialsOutsideMask(skeleton); + } + } + + public static void EditorDeleteMaskMaterials(SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials, SpriteMaskInteraction maskType) { + Material[] targetMaterials; + if (maskType == SpriteMaskInteraction.VisibleInsideMask) { + targetMaterials = maskMaterials.materialsInsideMask; + } + else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) { + targetMaterials = maskMaterials.materialsOutsideMask; + } + else { + Debug.LogWarning("EditorDeleteMaskMaterials: Normal materials are kept as a reference and shall never be deleted."); + return; + } + + for (int i = 0; i < targetMaterials.Length; ++i) { + var material = targetMaterials[i]; + if (material != null) { + string materialPath = UnityEditor.AssetDatabase.GetAssetPath(material); + UnityEditor.AssetDatabase.DeleteAsset(materialPath); + Debug.Log(string.Concat("Deleted material '", materialPath, "'")); + } + } + + if (maskType == SpriteMaskInteraction.VisibleInsideMask) { + maskMaterials.materialsInsideMask = new Material[0]; + } + else if (maskType == SpriteMaskInteraction.VisibleOutsideMask) { + maskMaterials.materialsOutsideMask = new Material[0]; + } + } + + private static void EditorInitSpriteMaskMaterialsInsideMask(SkeletonRenderer skeleton) { + var maskMaterials = skeleton.maskMaterials; + EditorInitSpriteMaskMaterialsForMaskType(skeleton, SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE, + ref maskMaterials.materialsInsideMask); + } + + private static void EditorInitSpriteMaskMaterialsOutsideMask(SkeletonRenderer skeleton) { + var maskMaterials = skeleton.maskMaterials; + EditorInitSpriteMaskMaterialsForMaskType(skeleton, SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_OUTSIDE, + ref maskMaterials.materialsOutsideMask); + } + + private static void EditorInitSpriteMaskMaterialsForMaskType(SkeletonRenderer skeleton, UnityEngine.Rendering.CompareFunction maskFunction, + ref Material[] materialsToFill) { + if (!EditorConfirmDisabledMaskMaterialsInit(skeleton)) + return; + + var maskMaterials = skeleton.maskMaterials; + var originalMaterials = maskMaterials.materialsMaskDisabled; + materialsToFill = new Material[originalMaterials.Length]; + for (int i = 0; i < originalMaterials.Length; i++) { + Material newMaterial = null; + + if (!Application.isPlaying) { + newMaterial = EditorCreateOrLoadMaskMaterialAsset(maskMaterials, maskFunction, originalMaterials[i]); + } + if (newMaterial == null) { + newMaterial = new Material(originalMaterials[i]); + newMaterial.SetFloat(SkeletonRenderer.STENCIL_COMP_PARAM_ID, (int)maskFunction); + } + materialsToFill[i] = newMaterial; + } + } + + private static bool EditorConfirmDisabledMaskMaterialsInit(SkeletonRenderer skeleton) { + var maskMaterials = skeleton.maskMaterials; + if (maskMaterials.materialsMaskDisabled.Length > 0 && maskMaterials.materialsMaskDisabled[0] != null) { + return true; + } + + var meshRenderer = skeleton.GetComponent(); + Material[] currentMaterials = meshRenderer.sharedMaterials; + + if (currentMaterials.Length == 0 || currentMaterials[0] == null) { + Debug.LogWarning("No materials found assigned at " + skeleton.name); + return false; + } + + // We have to be sure that there has not been a recompilation or similar events that led to + // inside- or outside-mask materials being assigned to meshRenderer.sharedMaterials. + string firstMaterialPath = UnityEditor.AssetDatabase.GetAssetPath(currentMaterials[0]); + if (firstMaterialPath.Contains(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK) || + firstMaterialPath.Contains(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK)) { + + maskMaterials.materialsMaskDisabled = new Material[currentMaterials.Length]; + for (int i = 0; i < currentMaterials.Length; ++i) { + string path = UnityEditor.AssetDatabase.GetAssetPath(currentMaterials[i]); + string correctPath = null; + if (path.Contains(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK)) { + correctPath = path.Replace(MATERIAL_FILENAME_SUFFIX_INSIDE_MASK, ""); + } + else if (path.Contains(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK)) { + correctPath = path.Replace(MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK, ""); + } + + if (correctPath != null) { + Material material = UnityEditor.AssetDatabase.LoadAssetAtPath(correctPath); + if (material == null) + Debug.LogWarning("No original ignore-mask material found for path " + correctPath); + maskMaterials.materialsMaskDisabled[i] = material; + } + } + } + else { + maskMaterials.materialsMaskDisabled = currentMaterials; + } + return true; + } + + public static Material EditorCreateOrLoadMaskMaterialAsset(SkeletonRenderer.SpriteMaskInteractionMaterials maskMaterials, + UnityEngine.Rendering.CompareFunction maskFunction, Material originalMaterial) { + string originalMaterialPath = UnityEditor.AssetDatabase.GetAssetPath(originalMaterial); + int posOfExtensionDot = originalMaterialPath.LastIndexOf('.'); + string materialPath = (maskFunction == SkeletonRenderer.STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE) ? + originalMaterialPath.Insert(posOfExtensionDot, MATERIAL_FILENAME_SUFFIX_INSIDE_MASK) : + originalMaterialPath.Insert(posOfExtensionDot, MATERIAL_FILENAME_SUFFIX_OUTSIDE_MASK); + + Material material = UnityEditor.AssetDatabase.LoadAssetAtPath(materialPath); + if (material != null) { + return material; + } + + material = new Material(originalMaterial); + material.SetFloat(SkeletonRenderer.STENCIL_COMP_PARAM_ID, (int)maskFunction); + + UnityEditor.AssetDatabase.CreateAsset(material, materialPath); + Debug.Log(string.Concat("Created material '", materialPath, "' for mask interaction based on '", originalMaterialPath, "'.")); + UnityEditor.EditorUtility.SetDirty(material); + UnityEditor.AssetDatabase.SaveAssets(); + return material; + } + } +} diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs.meta b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs.meta new file mode 100644 index 000000000..7d3b80bd3 --- /dev/null +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7c1b3a9ddacb550458bb86affdf77bf5 +timeCreated: 1550564907 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs index 83817e787..a57bab908 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs @@ -91,6 +91,32 @@ namespace Spine.Unity { /// If true, tangents are calculated every frame and added to the Mesh. Enable this when using a shader that uses lighting that requires tangents. public bool calculateTangents = false; + + /// This enum controls the mode under which the sprite will interact with the masking system. + /// Interaction modes with components are identical to Unity's , + /// see https://docs.unity3d.com/ScriptReference/SpriteMaskInteraction.html. + public SpriteMaskInteraction maskInteraction = SpriteMaskInteraction.None; + + [System.Serializable] + public class SpriteMaskInteractionMaterials { + /// Material references for switching material sets at runtime when changes to . + public Material[] materialsMaskDisabled = new Material[0]; + /// Material references for switching material sets at runtime when changes to . + public Material[] materialsInsideMask = new Material[0]; + /// Material references for switching material sets at runtime when changes to . + public Material[] materialsOutsideMask = new Material[0]; + } + /// Material references for switching material sets at runtime when changes. + public SpriteMaskInteractionMaterials maskMaterials = new SpriteMaskInteractionMaterials(); + + /// Shader property ID used for the Stencil comparison function. + public static readonly int STENCIL_COMP_PARAM_ID = Shader.PropertyToID("_StencilComp"); + /// Shader property value used as Stencil comparison function for . + public const UnityEngine.Rendering.CompareFunction STENCIL_COMP_MASKINTERACTION_NONE = UnityEngine.Rendering.CompareFunction.Disabled; + /// Shader property value used as Stencil comparison function for . + public const UnityEngine.Rendering.CompareFunction STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE = UnityEngine.Rendering.CompareFunction.LessEqual; + /// Shader property value used as Stencil comparison function for . + public const UnityEngine.Rendering.CompareFunction STENCIL_COMP_MASKINTERACTION_VISIBLE_OUTSIDE = UnityEngine.Rendering.CompareFunction.Greater; #endregion #region Overrides @@ -373,6 +399,10 @@ namespace Spine.Unity { // STEP 4. The UnityEngine.Mesh is ready. Set it as the MeshFilter's mesh. Store the instructions used for that mesh. =========== meshFilter.sharedMesh = currentMesh; currentSmartMesh.instructionUsed.Set(currentInstructions); + + if (meshRenderer != null) { + AssignSpriteMaskMaterials(); + } } public void FindAndApplySeparatorSlots (string startsWith, bool clearExistingSeparators = true, bool updateStringArray = false) { @@ -435,5 +465,54 @@ namespace Spine.Unity { } } + private void AssignSpriteMaskMaterials() + { + if (maskMaterials.materialsMaskDisabled.Length > 0 && maskMaterials.materialsMaskDisabled[0] != null && + maskInteraction == SpriteMaskInteraction.None) { + this.meshRenderer.materials = maskMaterials.materialsMaskDisabled; + } + else if (maskInteraction == SpriteMaskInteraction.VisibleInsideMask) { + if (maskMaterials.materialsInsideMask.Length == 0 || maskMaterials.materialsInsideMask[0] == null) { + if (!InitSpriteMaskMaterialsInsideMask()) + return; + } + this.meshRenderer.materials = maskMaterials.materialsInsideMask; + } + else if (maskInteraction == SpriteMaskInteraction.VisibleOutsideMask) { + if (maskMaterials.materialsOutsideMask.Length == 0 || maskMaterials.materialsOutsideMask[0] == null) { + if (!InitSpriteMaskMaterialsOutsideMask()) + return; + } + this.meshRenderer.materials = maskMaterials.materialsOutsideMask; + } + } + + private bool InitSpriteMaskMaterialsInsideMask() + { + return InitSpriteMaskMaterialsForMaskType(STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE, ref maskMaterials.materialsInsideMask); + } + + private bool InitSpriteMaskMaterialsOutsideMask() + { + return InitSpriteMaskMaterialsForMaskType(STENCIL_COMP_MASKINTERACTION_VISIBLE_OUTSIDE, ref maskMaterials.materialsOutsideMask); + } + + private bool InitSpriteMaskMaterialsForMaskType(UnityEngine.Rendering.CompareFunction maskFunction, ref Material[] materialsToFill) + { + #if UNITY_EDITOR + if (!Application.isPlaying) { + return false; + } + #endif + + var originalMaterials = maskMaterials.materialsMaskDisabled; + materialsToFill = new Material[originalMaterials.Length]; + for (int i = 0; i < originalMaterials.Length; i++) { + Material newMaterial = new Material(originalMaterials[i]); + newMaterial.SetFloat(STENCIL_COMP_PARAM_ID, (int)maskFunction); + materialsToFill[i] = newMaterial; + } + return true; + } } } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ghost/Shaders/Spine-Special-Skeleton-Ghost.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ghost/Shaders/Spine-Special-Skeleton-Ghost.shader index 235d76cb8..bd529e3fc 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ghost/Shaders/Spine-Special-Skeleton-Ghost.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ghost/Shaders/Spine-Special-Skeleton-Ghost.shader @@ -7,6 +7,8 @@ Shader "Spine/Special/SkeletonGhost" { _Color ("Main Color", Color) = (1,1,1,1) [NoScaleOffset] _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {} _TextureFade ("Texture Fade Out", Range(0,1)) = 0 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { Tags { @@ -18,6 +20,12 @@ Shader "Spine/Special/SkeletonGhost" { Blend One OneMinusSrcAlpha ZWrite Off Cull Off + + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } Pass { CGPROGRAM diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Fill.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Fill.shader index 1fc6da2a7..12001cd57 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Fill.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Fill.shader @@ -9,6 +9,8 @@ Shader "Spine/Skeleton Fill" { [NoScaleOffset] _MainTex ("MainTex", 2D) = "white" {} _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } @@ -17,6 +19,12 @@ Shader "Spine/Skeleton Fill" { ZWrite Off Lighting Off + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { CGPROGRAM #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Tint.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Tint.shader index 0cba285cb..638e09c6f 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Tint.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Tint.shader @@ -11,6 +11,8 @@ Shader "Spine/Skeleton Tint" { [NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {} [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { @@ -22,6 +24,12 @@ Shader "Spine/Skeleton Tint" { Blend One OneMinusSrcAlpha Lighting Off + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { CGPROGRAM #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Special-Skeleton-Grayscale.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Special-Skeleton-Grayscale.shader index 112c46ebb..80f30d38a 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Special-Skeleton-Grayscale.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Special-Skeleton-Grayscale.shader @@ -8,6 +8,8 @@ Shader "Spine/Special/Skeleton Grayscale" { [NoScaleOffset] _MainTex ("MainTex", 2D) = "white" {} _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } @@ -16,6 +18,12 @@ Shader "Spine/Special/Skeleton Grayscale" { ZWrite Off Lighting Off + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { CGPROGRAM #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesPixelLit.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesPixelLit.shader index fca34de2f..8ee4d2c09 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesPixelLit.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesPixelLit.shader @@ -44,6 +44,8 @@ Shader "Spine/Sprite/Pixel Lit" [HideInInspector] _DstBlend ("__dst", Float) = 0.0 [HideInInspector] _RenderQueue ("__queue", Float) = 0.0 [HideInInspector] _Cull ("__cull", Float) = 0.0 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader @@ -51,6 +53,12 @@ Shader "Spine/Sprite/Pixel Lit" Tags { "Queue"="Transparent" "RenderType"="Sprite" "AlphaDepth"="False" "CanUseSpriteAtlas"="True" "IgnoreProjector"="True" } LOD 200 + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { Name "FORWARD" diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesUnlit.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesUnlit.shader index 807a4c270..56521c4ee 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesUnlit.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesUnlit.shader @@ -26,6 +26,8 @@ Shader "Spine/Sprite/Unlit" [HideInInspector] _DstBlend ("__dst", Float) = 0.0 [HideInInspector] _RenderQueue ("__queue", Float) = 0.0 [HideInInspector] _Cull ("__cull", Float) = 0.0 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader @@ -33,6 +35,12 @@ Shader "Spine/Sprite/Unlit" Tags { "Queue"="Transparent" "RenderType"="Sprite" "AlphaDepth"="False" "CanUseSpriteAtlas"="True" "IgnoreProjector"="True" } LOD 100 + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { Blend [_SrcBlend] [_DstBlend] diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesVertexLit.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesVertexLit.shader index 7137b0d32..7e7ebe415 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesVertexLit.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Sprite/SpritesVertexLit.shader @@ -44,12 +44,20 @@ Shader "Spine/Sprite/Vertex Lit" [HideInInspector] _DstBlend ("__dst", Float) = 0.0 [HideInInspector] _RenderQueue ("__queue", Float) = 0.0 [HideInInspector] _Cull ("__cull", Float) = 0.0 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { Tags { "Queue"="Transparent" "RenderType"="Sprite" "AlphaDepth"="False" "CanUseSpriteAtlas"="True" "IgnoreProjector"="True" } LOD 150 + + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } Pass { diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Additive.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Additive.shader index 0e83f229f..0b79b5364 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Additive.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Additive.shader @@ -11,6 +11,8 @@ Shader "Spine/Blend Modes/Skeleton PMA Additive" { [NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {} [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { @@ -23,6 +25,12 @@ Shader "Spine/Blend Modes/Skeleton PMA Additive" { Blend One One Lighting Off + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { CGPROGRAM #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Multiply.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Multiply.shader index ffd84418c..3d16848c6 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Multiply.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Multiply.shader @@ -11,6 +11,8 @@ Shader "Spine/Blend Modes/Skeleton PMA Multiply" { [NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {} [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { @@ -23,6 +25,12 @@ Shader "Spine/Blend Modes/Skeleton PMA Multiply" { Blend DstColor OneMinusSrcAlpha Lighting Off + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { CGPROGRAM #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader index 5c3322c33..1a1dfbf1c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/BlendModes/Spine-Skeleton-PMA-Screen.shader @@ -11,6 +11,8 @@ Shader "Spine/Blend Modes/Skeleton PMA Screen" { [NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {} [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { @@ -23,6 +25,12 @@ Shader "Spine/Blend Modes/Skeleton PMA Screen" { Blend One OneMinusSrcColor Lighting Off + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { CGPROGRAM #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-TintBlack.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-TintBlack.shader index 1e5c040c7..f67810e52 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-TintBlack.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton-TintBlack.shader @@ -13,6 +13,8 @@ Shader "Spine/Skeleton Tint Black" { [NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {} [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { @@ -25,6 +27,12 @@ Shader "Spine/Skeleton Tint Black" { Blend One OneMinusSrcAlpha Lighting Off + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { CGPROGRAM #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton.shader index 661f279c3..3050d089c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-Skeleton.shader @@ -3,6 +3,8 @@ Shader "Spine/Skeleton" { _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 [NoScaleOffset] _MainTex ("Main Texture", 2D) = "black" {} [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { @@ -14,6 +16,12 @@ Shader "Spine/Skeleton" { Blend One OneMinusSrcAlpha Lighting Off + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } + Pass { CGPROGRAM #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-SkeletonLit.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-SkeletonLit.shader index a4f9b34d6..228a41566 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-SkeletonLit.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Shaders/Spine-SkeletonLit.shader @@ -7,6 +7,8 @@ Shader "Spine/Skeleton Lit" { _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 [NoScaleOffset] _MainTex ("Main Texture", 2D) = "black" {} [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 + [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0 + [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default } SubShader { @@ -16,6 +18,12 @@ Shader "Spine/Skeleton Lit" { Cull Off ZWrite Off Blend One OneMinusSrcAlpha + + Stencil { + Ref[_StencilRef] + Comp[_StencilComp] + Pass Keep + } // Pass { // Tags { "LightMode"="Vertex" } From 7110e709c4d3ec7e7331f84dc1723994c4591c49 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 19 Feb 2019 19:03:15 +0100 Subject: [PATCH 20/39] [unity] Changelog documentation updated for added support for Unity's SpriteMask. See #941. --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc94f3c8c..83fe0294e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -203,6 +203,21 @@ * `sRGB (Color Texture)` shall be disabled when `Generate Mip Maps` is enabled, otherwise you will receive white border outlines. * `Alpha Is Transparency` shall be disabled on `Premultiply alpha` textures, otherwise you will receive light ghosting artifacts in transparent areas. * These warnings can be disabled in `Edit - Preferences - Spine`. +* **Sprite Mask Support for all Included Shaders** The `Skeleton Animation` and `Skeleton Mecanim` components now provide an additional `Mask Interaction` field in the Inspector, covering identical functionality as Unity's built in `Sprite Renderer` component: + * `Mask Interaction` modes: + * `None` - The sprite will not interact with the masking system. Default behavior. + * `Visible Inside Mask` - The sprite will be visible only in areas where a mask is present. + * `Visible Outside Mask` - The sprite will be visible only in areas where no mask is present. + * `Automatically Generated Materials` When switching `Mask Interaction` modes in the Inspector outside of Play mode, the required additional material assets are generated for the respective `Stencil Compare` parameters - with file suffixes `'_InsideMask'` and `'_OutsideMask'`, placed in the same folder as the original materials. By default all generated materials are kept as references by the `Skeleton Animation` component for switching at runtime. + These materials can be managed and optimized via the `SkeletonAnimation`'s `Advanced` section: + * Using the `Clear` button you can clear the reference to unneeded materials, + * Using the `Delete` button the respective assets are deleted as well as references cleared. Note that other `Skeleton Animation` GameObjects might still reference the materials, so use with caution! + * With the `Set` button you can again assign a link to the respective materials to prepare them for runtime use. If the materials were not present or have been deleted, they are generated again based on the default materials. + * When switching `Mask Interaction` mode at runtime, the previously prepared materials are switched active automatically. When the respective materials have not been prepared, material copies of the default materials are created on the fly. Note that these materials are not shared between similar `Skeleton Animation` GameObjects, so it is recommended to use the generated material assets where possible. + * **Every shader now exposes the `Stencil Compare` parameter** for further customization. This way you have maximum flexibility to use custom mechanisms to switch materials at runtime if you should ever need more than the three materials generated by `Skeleton Animation`'s `Mask Interaction` parameter. Reference `Stencil Compare` values are: + * `CompareFunction.Disabled` for `Mask Interaction - None` + * `CompareFunction.LessEqual` for `Mask Interaction - Visible Inside Mask` + * `CompareFunction.Greater` for `Mask Interaction - Visible Outside Mask` ### XNA/MonoGame * Added support for any `Effect` to be used by `SkeletonRenderer` From 8b1359db0ba628bd013f93caf59e74bdbb394fd8 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 19 Feb 2019 19:41:00 +0100 Subject: [PATCH 21/39] [unity] Added #if guards for Unity 5.x compatibility before Unity added SpriteMasks. See #941. --- .../Editor/SkeletonRendererInspector.cs | 28 +++++++++++++++---- .../spine-unity/Editor/SpineMaskUtilities.cs | 7 +++++ .../Components/SkeletonRenderer.cs | 11 ++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs index f777addc4..66ae5331a 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs @@ -34,6 +34,10 @@ #define NO_PREFAB_MESH #endif +#if UNITY_2017_OR_NEWER +#define BUILT_IN_SPRITE_MASK_COMPONENT +#endif + using UnityEditor; using System.Collections.Generic; using UnityEngine; @@ -215,6 +219,7 @@ namespace Spine.Unity.Editor { } } + #if BUILT_IN_SPRITE_MASK_COMPONENT if (setMaskNoneMaterialsQueued) { setMaskNoneMaterialsQueued = false; foreach (var c in targets) @@ -241,8 +246,9 @@ namespace Spine.Unity.Editor { foreach (var c in targets) EditorDeleteMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleOutsideMask); } + #endif - #if NO_PREFAB_MESH +#if NO_PREFAB_MESH if (isInspectingPrefab) { if (multi) { foreach (var c in targets) { @@ -258,7 +264,7 @@ namespace Spine.Unity.Editor { meshFilter.sharedMesh = null; } } - #endif +#endif } bool valid = TargetIsValid; @@ -362,6 +368,7 @@ namespace Spine.Unity.Editor { if (tangents != null) EditorGUILayout.PropertyField(tangents, TangentsLabel); } + #if BUILT_IN_SPRITE_MASK_COMPONENT EditorGUILayout.Space(); if (maskMaterialsNone.arraySize > 0 || maskMaterialsInside.arraySize > 0 || maskMaterialsOutside.arraySize > 0) { EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Mask Interaction Materials", SpineInspectorUtility.UnityIcon()), EditorStyles.boldLabel); @@ -376,6 +383,7 @@ namespace Spine.Unity.Editor { MaskMaterialsEditingField(ref setOutsideMaskMaterialsQueued, ref deleteOutsideMaskMaterialsQueued, maskMaterialsOutside, MaskMaterialsOutsideLabel, differentMaskModesSelected, allowDelete : true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleOutsideMask); } + #endif EditorGUILayout.Space(); @@ -525,11 +533,20 @@ namespace Spine.Unity.Editor { if (component == null) return; if (!SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return; component.Initialize(true); + + #if BUILT_IN_SPRITE_MASK_COMPONENT SpineMaskUtilities.EditorAssignSpriteMaskMaterials(component); + #endif + component.LateUpdate(); } + static bool SkeletonDataAssetIsValid (SkeletonDataAsset asset) { + return asset != null && asset.GetSkeletonData(quiet: true) != null; + } + bool AreAnyMaskMaterialsMissing() { + #if BUILT_IN_SPRITE_MASK_COMPONENT foreach (var o in targets) { var component = (SkeletonRenderer)o; if (!component.valid) @@ -537,13 +554,11 @@ namespace Spine.Unity.Editor { if (SpineMaskUtilities.AreMaskMaterialsMissing(component)) return true; } + #endif return false; } - static bool SkeletonDataAssetIsValid (SkeletonDataAsset asset) { - return asset != null && asset.GetSkeletonData(quiet: true) != null; - } - + #if BUILT_IN_SPRITE_MASK_COMPONENT static void EditorSetMaskMaterials(SkeletonRenderer component, SpriteMaskInteraction maskType) { if (component == null) return; @@ -556,5 +571,6 @@ namespace Spine.Unity.Editor { if (!SkeletonDataAssetIsValid(component.SkeletonDataAsset)) return; SpineMaskUtilities.EditorDeleteMaskMaterials(component.maskMaterials, maskType); } + #endif } } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs index 9781bb0cc..4b1e3e8cc 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs @@ -44,6 +44,12 @@ #define NEWHIERARCHYWINDOWCALLBACKS #endif +#if UNITY_2017_OR_NEWER +#define BUILT_IN_SPRITE_MASK_COMPONENT +#endif + +#if BUILT_IN_SPRITE_MASK_COMPONENT + using UnityEngine; using UnityEditor; using System.Collections.Generic; @@ -241,3 +247,4 @@ namespace Spine.Unity.Editor { } } } +#endif // BUILT_IN_SPRITE_MASK_COMPONENT diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs index a57bab908..85108f899 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs @@ -31,6 +31,11 @@ #if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER #define NEW_PREFAB_SYSTEM #endif + +#if UNITY_2017_OR_NEWER +#define BUILT_IN_SPRITE_MASK_COMPONENT +#endif + #define SPINE_OPTIONAL_RENDEROVERRIDE #define SPINE_OPTIONAL_MATERIALOVERRIDE @@ -92,6 +97,7 @@ namespace Spine.Unity { /// If true, tangents are calculated every frame and added to the Mesh. Enable this when using a shader that uses lighting that requires tangents. public bool calculateTangents = false; + #if BUILT_IN_SPRITE_MASK_COMPONENT /// This enum controls the mode under which the sprite will interact with the masking system. /// Interaction modes with components are identical to Unity's , /// see https://docs.unity3d.com/ScriptReference/SpriteMaskInteraction.html. @@ -117,6 +123,7 @@ namespace Spine.Unity { public const UnityEngine.Rendering.CompareFunction STENCIL_COMP_MASKINTERACTION_VISIBLE_INSIDE = UnityEngine.Rendering.CompareFunction.LessEqual; /// Shader property value used as Stencil comparison function for . public const UnityEngine.Rendering.CompareFunction STENCIL_COMP_MASKINTERACTION_VISIBLE_OUTSIDE = UnityEngine.Rendering.CompareFunction.Greater; + #endif // #if BUILT_IN_SPRITE_MASK_COMPONENT #endregion #region Overrides @@ -400,9 +407,11 @@ namespace Spine.Unity { meshFilter.sharedMesh = currentMesh; currentSmartMesh.instructionUsed.Set(currentInstructions); + #if BUILT_IN_SPRITE_MASK_COMPONENT if (meshRenderer != null) { AssignSpriteMaskMaterials(); } + #endif } public void FindAndApplySeparatorSlots (string startsWith, bool clearExistingSeparators = true, bool updateStringArray = false) { @@ -465,6 +474,7 @@ namespace Spine.Unity { } } + #if BUILT_IN_SPRITE_MASK_COMPONENT private void AssignSpriteMaskMaterials() { if (maskMaterials.materialsMaskDisabled.Length > 0 && maskMaterials.materialsMaskDisabled[0] != null && @@ -514,5 +524,6 @@ namespace Spine.Unity { } return true; } + #endif //#if BUILT_IN_SPRITE_MASK_COMPONENT } } From 638e176f595ba8786f223f19a06ef4f90b78d5bc Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 19 Feb 2019 19:54:59 +0100 Subject: [PATCH 22/39] [unity] Corrected #if guards for Unity 5.x compatibility before Unity added SpriteMasks. See #941. --- .../Editor/spine-unity/Editor/SkeletonRendererInspector.cs | 2 +- .../Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs | 2 +- .../Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs index 66ae5331a..f43307360 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs @@ -34,7 +34,7 @@ #define NO_PREFAB_MESH #endif -#if UNITY_2017_OR_NEWER +#if UNITY_2017_1_OR_NEWER #define BUILT_IN_SPRITE_MASK_COMPONENT #endif diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs index 4b1e3e8cc..0986fedf8 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineMaskUtilities.cs @@ -44,7 +44,7 @@ #define NEWHIERARCHYWINDOWCALLBACKS #endif -#if UNITY_2017_OR_NEWER +#if UNITY_2017_1_OR_NEWER #define BUILT_IN_SPRITE_MASK_COMPONENT #endif diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs index 85108f899..46db07887 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs @@ -32,7 +32,7 @@ #define NEW_PREFAB_SYSTEM #endif -#if UNITY_2017_OR_NEWER +#if UNITY_2017_1_OR_NEWER #define BUILT_IN_SPRITE_MASK_COMPONENT #endif From 37cc09537577cf6cbfa21cb5ee25231a4b2c2c39 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Thu, 21 Feb 2019 19:10:14 +0100 Subject: [PATCH 23/39] [unity] SkeletonGraphic now supports Unity RectMask2D. Closes #1283. --- .../Shaders/Spine-SkeletonGraphic-TintBlack.shader | 2 +- .../SkeletonGraphic/Shaders/Spine-SkeletonGraphic.shader | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/Shaders/Spine-SkeletonGraphic-TintBlack.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/Shaders/Spine-SkeletonGraphic-TintBlack.shader index 14d0eda28..f31d0a20e 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/Shaders/Spine-SkeletonGraphic-TintBlack.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/Shaders/Spine-SkeletonGraphic-TintBlack.shader @@ -111,7 +111,7 @@ Shader "Spine/SkeletonGraphic Tint Black" texColor.rgb *= texColor.a; #endif - texColor.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); + texColor *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); #ifdef UNITY_UI_ALPHACLIP clip (texColor.a - 0.001); diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/Shaders/Spine-SkeletonGraphic.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/Shaders/Spine-SkeletonGraphic.shader index 87ede06cd..c570c6585 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/Shaders/Spine-SkeletonGraphic.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/Shaders/Spine-SkeletonGraphic.shader @@ -109,7 +109,7 @@ Shader "Spine/SkeletonGraphic" half4 color = (texColor + _TextureSampleAdd) * IN.color; - color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); + color *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); #ifdef UNITY_UI_ALPHACLIP clip (color.a - 0.001); From 15be5feeead8da5bd94b241a7ecd872388cf2ecf Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Thu, 21 Feb 2019 19:24:43 +0100 Subject: [PATCH 24/39] [unity] Added changelog entry for SkeletonGraphic now supporting RectMask2D. See #1283. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83fe0294e..a9f32a492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -218,6 +218,7 @@ * `CompareFunction.Disabled` for `Mask Interaction - None` * `CompareFunction.LessEqual` for `Mask Interaction - Visible Inside Mask` * `CompareFunction.Greater` for `Mask Interaction - Visible Outside Mask` +* **RectMask2D Support for SkeletonGraphic** Both `SkeletonGraphic` shaders '`Spine/SkeletonGraphic`' and '`Spine/SkeletonGraphic Tint Black`' now respect masking areas defined via Unity's `RectMask2D` component. ### XNA/MonoGame * Added support for any `Effect` to be used by `SkeletonRenderer` From 8ca94c2da4dacb69984b548a64825f70cafc3664 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Tue, 26 Feb 2019 16:55:03 +0100 Subject: [PATCH 25/39] [unity] Fixed another occurrence of compile errors in Unity 2017.3 when enabling TK2D define due to asmdef files. See #1280. --- .../Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index 16ebf3490..da07e5eb2 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -1852,12 +1852,12 @@ namespace Spine.Unity.Editor { internal static void SetAsmdefFileActive(string filename, bool setActive) { - string typeSearchString = setActive ? " t:textasset" : " t:asmdef"; + string typeSearchString = setActive ? " t:TextAsset" : " t:AssemblyDefinitionAsset"; string[] guids = AssetDatabase.FindAssets(filename + typeSearchString); foreach (string guid in guids) { string currentPath = AssetDatabase.GUIDToAssetPath(guid); string targetPath = System.IO.Path.ChangeExtension(currentPath, setActive ? "asmdef" : "txt"); - if (System.IO.File.Exists(currentPath)) { + if (System.IO.File.Exists(currentPath) && !System.IO.File.Exists(targetPath)) { System.IO.File.Copy(currentPath, targetPath); System.IO.File.Copy(currentPath + ".meta", targetPath + ".meta"); } From b5e8d49cb20e24b65cba30410447bfe2b392996c Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 4 Mar 2019 18:27:57 +0100 Subject: [PATCH 26/39] [unity] Fixed material being cleared to null when MeshRenderer is disabled in the editor. Closes #1288. --- .../Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs index 46db07887..1102f26cc 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs @@ -268,7 +268,7 @@ namespace Spine.Unity { meshFilter.sharedMesh = null; meshRenderer = GetComponent(); - if (meshRenderer != null) meshRenderer.sharedMaterial = null; + if (meshRenderer != null && meshRenderer.enabled) meshRenderer.sharedMaterial = null; currentInstructions.Clear(); rendererBuffers.Clear(); From 930d4b40154038429d83cd7e3116183bc6a6beeb Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Mon, 4 Mar 2019 18:45:14 +0100 Subject: [PATCH 27/39] [unity] corrected version number in version.txt file of 3.8-beta branch. --- spine-unity/Assets/Spine/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-unity/Assets/Spine/version.txt b/spine-unity/Assets/Spine/version.txt index a51afb747..b3935ff70 100644 --- a/spine-unity/Assets/Spine/version.txt +++ b/spine-unity/Assets/Spine/version.txt @@ -1 +1 @@ -This Spine-Unity runtime works with data exported from Spine Editor version: 3.7.xx \ No newline at end of file +This Spine-Unity runtime works with data exported from Spine Editor version: 3.8.xx \ No newline at end of file From 15547e1e0c580a17448c2bb239bc0fbecca366bd Mon Sep 17 00:00:00 2001 From: Nick Peterson Date: Wed, 6 Mar 2019 02:14:27 -0800 Subject: [PATCH 28/39] TrackEntry now resets renderer object (#1293) --- spine-cpp/spine-cpp/src/spine/AnimationState.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 849d50649..c3cdcc172 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -171,6 +171,8 @@ void TrackEntry::reset() { _mixingFrom = NULL; _mixingTo = NULL; + setRendererObject(NULL); + _timelineMode.clear(); _timelineHoldMix.clear(); _timelinesRotation.clear(); From af0b285c7301a244c735abfe05bb8aa5d378cab2 Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 12:01:24 +0100 Subject: [PATCH 29/39] [ue4] Fix formatting. --- .../Source/SpinePlugin/Public/SpineSkeletonDataAsset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h index 442dc49b7..b9940a534 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h @@ -46,7 +46,7 @@ public: FString To; UPROPERTY(EditAnywhere, BlueprintReadWrite) - float Mix = 0; + float Mix = 0; }; UCLASS(BlueprintType, ClassGroup=(Spine)) From 75f21f846c6870b9ba5a514409d185938a89589f Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 15:11:24 +0100 Subject: [PATCH 30/39] [ue4] Query methods for SpineSkeletonComponent and UTrackEntry. Closes #1289. --- .../Private/SpineSkeletonComponent.cpp | 83 +++++++++++++++++-- .../Public/SpineSkeletonAnimationComponent.h | 11 ++- .../Public/SpineSkeletonComponent.h | 28 ++++++- 3 files changed, 112 insertions(+), 10 deletions(-) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp index c078910ae..5547ae43f 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp @@ -42,7 +42,7 @@ USpineSkeletonComponent::USpineSkeletonComponent () { bAutoActivate = true; } -bool USpineSkeletonComponent::SetSkin(const FString& skinName) { +bool USpineSkeletonComponent::SetSkin (const FString skinName) { CheckState(); if (skeleton) { Skin* skin = skeleton->getData()->findSkin(TCHAR_TO_UTF8(*skinName)); @@ -53,7 +53,24 @@ bool USpineSkeletonComponent::SetSkin(const FString& skinName) { else return false; } -bool USpineSkeletonComponent::SetAttachment (const FString& slotName, const FString& attachmentName) { +void USpineSkeletonComponent::GetSkins (TArray &Skins) { + CheckState(); + if (skeleton) { + for (size_t i = 0, n = skeleton->getData()->getSkins().size(); i < n; i++) { + Skins.Add(skeleton->getData()->getSkins()[i]->getName().buffer()); + } + } +} + +bool USpineSkeletonComponent::HasSkin (const FString skinName) { + CheckState(); + if (skeleton) { + return skeleton->getData()->findAnimation(TCHAR_TO_UTF8(*skinName)) != nullptr; + } + return false; +} + +bool USpineSkeletonComponent::SetAttachment (const FString slotName, const FString attachmentName) { CheckState(); if (skeleton) { if (!skeleton->getAttachment(TCHAR_TO_UTF8(*slotName), TCHAR_TO_UTF8(*attachmentName))) return false; @@ -127,7 +144,7 @@ void USpineSkeletonComponent::SetBoneWorldPosition (const FString& BoneName, con } } -void USpineSkeletonComponent::UpdateWorldTransform() { +void USpineSkeletonComponent::UpdateWorldTransform () { CheckState(); if (skeleton) { skeleton->updateWorldTransform(); @@ -154,24 +171,24 @@ void USpineSkeletonComponent::SetScaleX (float scaleX) { if (skeleton) skeleton->setScaleX(scaleX); } -float USpineSkeletonComponent::GetScaleX() { +float USpineSkeletonComponent::GetScaleX () { CheckState(); if (skeleton) return skeleton->getScaleX(); return 1; } -void USpineSkeletonComponent::SetScaleY(float scaleY) { +void USpineSkeletonComponent::SetScaleY (float scaleY) { CheckState(); if (skeleton) skeleton->setScaleY(scaleY); } -float USpineSkeletonComponent::GetScaleY() { +float USpineSkeletonComponent::GetScaleY () { CheckState(); if (skeleton) return skeleton->getScaleY(); return 1; } -void USpineSkeletonComponent::GetBones(TArray &Bones) { +void USpineSkeletonComponent::GetBones (TArray &Bones) { CheckState(); if (skeleton) { for (size_t i = 0, n = skeleton->getBones().size(); i < n; i++) { @@ -180,6 +197,58 @@ void USpineSkeletonComponent::GetBones(TArray &Bones) { } } +bool USpineSkeletonComponent::HasBone (const FString BoneName) { + CheckState(); + if (skeleton) { + return skeleton->getData()->findBone(TCHAR_TO_UTF8(*BoneName)) != nullptr; + } + return false; +} + +void USpineSkeletonComponent::GetSlots (TArray &Slots) { + CheckState(); + if (skeleton) { + for (size_t i = 0, n = skeleton->getSlots().size(); i < n; i++) { + Slots.Add(skeleton->getSlots()[i]->getData().getName().buffer()); + } + } +} + +bool USpineSkeletonComponent::HasSlot (const FString SlotName) { + CheckState(); + if (skeleton) { + return skeleton->getData()->findSlot(TCHAR_TO_UTF8(*SlotName)) != nullptr; + } + return false; +} + +void USpineSkeletonComponent::GetAnimations(TArray &Animations) { + CheckState(); + if (skeleton) { + for (size_t i = 0, n = skeleton->getData()->getAnimations().size(); i < n; i++) { + Animations.Add(skeleton->getData()->getAnimations()[i]->getName().buffer()); + } + } +} + +bool USpineSkeletonComponent::HasAnimation(FString AnimationName) { + CheckState(); + if (skeleton) { + return skeleton->getData()->findAnimation(TCHAR_TO_UTF8(*AnimationName)) != nullptr; + } + return false; +} + +float USpineSkeletonComponent::GetAnimationDuration(FString AnimationName) { + CheckState(); + if (skeleton) { + Animation *animation = skeleton->getData()->findAnimation(TCHAR_TO_UTF8(*AnimationName)); + if (animation == nullptr) return 0; + else return animation->getDuration(); + } + return 0; +} + void USpineSkeletonComponent::BeginPlay() { Super::BeginPlay(); } diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h index 303d11efc..eac35678a 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h @@ -90,7 +90,7 @@ public: UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry") bool GetLoop () { return entry ? entry->getLoop() : false; } UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry") - void SetLoop(bool loop) { if (entry) entry->setLoop(loop); } + void SetLoop(bool loop) { if (entry) entry->setLoop(loop); } UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry") float GetEventThreshold () { return entry ? entry->getEventThreshold() : 0; } @@ -157,6 +157,15 @@ public: UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry") void SetMixDuration(float mixDuration) { if (entry) entry->setMixDuration(mixDuration); } + UFUNCTION(BlueprintCallable, Category = "Components|Spine|TrackEntry") + FString getAnimationName() { return entry ? entry->getAnimation()->getName().buffer() : ""; } + + UFUNCTION(BlueprintCallable, Category = "Components|Spine|TrackEntry") + float getAnimationDuration() { return entry ? entry->getAnimation()->getDuration(): 0; } + + UFUNCTION(BlueprintCallable, Category = "Components|Spine|TrackEntry") + float isValidAnimation() { return entry != nullptr; } + UPROPERTY(BlueprintAssignable, Category = "Components|Spine|TrackEntry") FSpineAnimationStartDelegate AnimationStart; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h index 45a494579..376a8a93c 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h @@ -53,12 +53,18 @@ public: USpineSkeletonDataAsset* SkeletonData; spine::Skeleton* GetSkeleton () { return skeleton; }; + + UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton") + void GetSkins(TArray &Skins); UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton") - bool SetSkin (const FString& SkinName); + bool SetSkin (const FString SkinName); + + UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton") + bool HasSkin(const FString SkinName); UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton") - bool SetAttachment (const FString& slotName, const FString& attachmentName); + bool SetAttachment (const FString slotName, const FString attachmentName); UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton") FTransform GetBoneWorldTransform (const FString& BoneName); @@ -92,6 +98,24 @@ public: UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton") void GetBones(TArray &Bones); + + UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton") + bool HasBone(const FString BoneName); + + UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton") + void GetSlots(TArray &Slots); + + UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton") + bool HasSlot(const FString SlotName); + + UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton") + void GetAnimations(TArray &Animations); + + UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton") + bool HasAnimation(FString AnimationName); + + UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton") + float GetAnimationDuration(FString AnimationName); UPROPERTY(BlueprintAssignable, Category = "Components|Spine|Skeleton") FSpineBeforeUpdateWorldTransformDelegate BeforeUpdateWorldTransform; From 1629c7e7abfb6e76436f965b1f05bd9187f5f66d Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 15:14:43 +0100 Subject: [PATCH 31/39] [unity][libgdx] Fix versions after merging in beta branch... --- spine-libgdx/spine-libgdx/pom.xml | 2 +- spine-unity/Assets/Spine/version.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-libgdx/spine-libgdx/pom.xml b/spine-libgdx/spine-libgdx/pom.xml index cb11287a6..8a784273c 100644 --- a/spine-libgdx/spine-libgdx/pom.xml +++ b/spine-libgdx/spine-libgdx/pom.xml @@ -10,7 +10,7 @@ com.esotericsoftware.spine spine-libgdx jar - 3.8.0.1-SNAPSHOT + 3.7.92.1-SNAPSHOT spine-libgdx diff --git a/spine-unity/Assets/Spine/version.txt b/spine-unity/Assets/Spine/version.txt index b3935ff70..a51afb747 100644 --- a/spine-unity/Assets/Spine/version.txt +++ b/spine-unity/Assets/Spine/version.txt @@ -1 +1 @@ -This Spine-Unity runtime works with data exported from Spine Editor version: 3.8.xx \ No newline at end of file +This Spine-Unity runtime works with data exported from Spine Editor version: 3.7.xx \ No newline at end of file From 28b3cd71f9e007d71bbe29b842b3fcd35c7baa52 Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 15:21:13 +0100 Subject: [PATCH 32/39] Updated CHANGELOG. --- CHANGELOG.md | 68 +--------------------------------------------------- 1 file changed, 1 insertion(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 112481d5e..a40e112e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,70 +1,3 @@ -# 3.8 - -## AS3 -* **Breaking changes** - -* **Additions** - -### Starling - -## C -* **Breaking changes** - -* **Additions** - -### Cocos2d-Objc - -### SFML - -## C++ -* ** Additions ** - -* **Breaking changes** - -### Cocos2d-x -### SFML - -### UE4 - -## C# ## -* **Breaking changes** - -* **Additions** - -### Unity - -### XNA/MonoGame - -## Java -* **Breaking changes** - -* **Additions** - -### libGDX - -## Lua -* **Breaking changes** -* -* **Additions** - -### Love2D - -### Corona - -## Typescript/Javascript -* **Breaking changes** - -* **Additions** - -### WebGL backend - -### Canvas backend - -### Three.js backend - -### Player - - # 3.7 ## AS3 @@ -166,6 +99,7 @@ * Updated to Unreal Engine 4.20 (samples require 4.17+), see the `spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.build.cs` file on how to compile in 4.20 with the latest UBT API changes. * Updated to Unreal Engine 4.21 (samples require 4.21). * **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175 +* Added query methods for slots, bones, skins and animations to `SpineSkeletonComponent` and `UTrackEntry`. These allow you to query these objects by name in both C++ and blueprints. ## C# ## * **Breaking changes** From 444f604df3c0c0cb9bcc143c0fcb3cb4e4ce0d96 Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 15:25:34 +0100 Subject: [PATCH 33/39] Fixed README of spine-cpp. --- spine-cpp/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spine-cpp/README.md b/spine-cpp/README.md index f4f5a523e..abd5ce3b1 100644 --- a/spine-cpp/README.md +++ b/spine-cpp/README.md @@ -8,7 +8,7 @@ This spine Runtime may only be used for personal or internal use, typically to e The spine Runtimes are developed with the intent to be used with data exported from spine. By purchasing spine, `Section 2` of the [spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the spine Runtimes. -## spine version +## Spine version spine-cpp works with data exported from spine 3.7.xx. @@ -19,6 +19,9 @@ spine-cpp supports all spine features. 1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above. 2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. +## Usage +### [Please see the spine-cpp guide for full documentation](http://esotericsoftware.com/spine-cpp) + ## Extension Extending spine-cpp requires implementing both the `SpineExtension` class and the TextureLoader class: From 4ba46d76e88621d6f127202d9ef199d40c794e3c Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 16:20:32 +0100 Subject: [PATCH 34/39] [ue4] Extended skeleton data editor preview. It now shows bones, slots, animations, and skins. Closes #1047. --- .../Private/SpineSkeletonDataAsset.cpp | 73 +++++++++++++++++++ .../Public/SpineSkeletonDataAsset.h | 14 ++++ 2 files changed, 87 insertions(+) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp index 5d1c378ee..94919b6cb 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp @@ -76,6 +76,7 @@ void USpineSkeletonDataAsset::Serialize (FArchive& Ar) { Super::Serialize(Ar); if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_ASSET_IMPORT_DATA_AS_JSON && !importData) importData = NewObject(this, TEXT("AssetImportData")); + LoadInfo(); } #endif @@ -92,13 +93,85 @@ void USpineSkeletonDataAsset::BeginDestroy () { Super::BeginDestroy(); } +class SP_API NullAttachmentLoader : public AttachmentLoader { +public: + + virtual RegionAttachment* newRegionAttachment(Skin& skin, const String& name, const String& path) { + return new(__FILE__, __LINE__) RegionAttachment(name); + } + + virtual MeshAttachment* newMeshAttachment(Skin& skin, const String& name, const String& path) { + return new(__FILE__, __LINE__) MeshAttachment(name); + } + + virtual BoundingBoxAttachment* newBoundingBoxAttachment(Skin& skin, const String& name) { + return new(__FILE__, __LINE__) BoundingBoxAttachment(name); + } + + virtual PathAttachment* newPathAttachment(Skin& skin, const String& name) { + return new(__FILE__, __LINE__) PathAttachment(name); + } + + virtual PointAttachment* newPointAttachment(Skin& skin, const String& name) { + return new(__FILE__, __LINE__) PointAttachment(name); + } + + virtual ClippingAttachment* newClippingAttachment(Skin& skin, const String& name) { + return new(__FILE__, __LINE__) ClippingAttachment(name); + } + + virtual void configureAttachment(Attachment* attachment) { + + } +}; + +void USpineSkeletonDataAsset::LoadInfo() { +#if WITH_EDITORONLY_DATA + int dataLen = rawData.Num(); + NullAttachmentLoader loader; + SkeletonData* skeletonData = nullptr; + if (skeletonDataFileName.GetPlainNameString().Contains(TEXT(".json"))) { + SkeletonJson* json = new (__FILE__, __LINE__) SkeletonJson(&loader); + skeletonData = json->readSkeletonData((const char*)rawData.GetData()); + if (!skeletonData) { + FMessageDialog::Debugf(FText::FromString(UTF8_TO_TCHAR(json->getError().buffer()))); + UE_LOG(SpineLog, Error, TEXT("Couldn't load skeleton data and atlas: %s"), UTF8_TO_TCHAR(json->getError().buffer())); + } + delete json; + } else { + SkeletonBinary* binary = new (__FILE__, __LINE__) SkeletonBinary(&loader); + skeletonData = binary->readSkeletonData((const unsigned char*)rawData.GetData(), (int)rawData.Num()); + if (!skeletonData) { + FMessageDialog::Debugf(FText::FromString(UTF8_TO_TCHAR(binary->getError().buffer()))); + UE_LOG(SpineLog, Error, TEXT("Couldn't load skeleton data and atlas: %s"), UTF8_TO_TCHAR(binary->getError().buffer())); + } + delete binary; + } + if (skeletonData) { + Bones.Empty(); + for (int i = 0; i < skeletonData->getBones().size(); i++) + Bones.Add(skeletonData->getBones()[i]->getName().buffer()); + Skins.Empty(); + for (int i = 0; i < skeletonData->getSkins().size(); i++) + Skins.Add(skeletonData->getSkins()[i]->getName().buffer()); + Animations.Empty(); + for (int i = 0; i < skeletonData->getAnimations().size(); i++) + Animations.Add(skeletonData->getAnimations()[i]->getName().buffer()); + delete skeletonData; + } +#endif +} + void USpineSkeletonDataAsset::SetRawData(TArray &Data) { this->rawData.Empty(); this->rawData.Append(Data); + if (skeletonData) { delete skeletonData; skeletonData = nullptr; } + + LoadInfo(); } SkeletonData* USpineSkeletonDataAsset::GetSkeletonData (Atlas* Atlas) { diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h index b9940a534..c94a896ce 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h @@ -70,6 +70,18 @@ public: UPROPERTY(EditAnywhere, BlueprintReadWrite) TArray MixData; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Bones; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Slots; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Skins; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Animations; protected: UPROPERTY() @@ -94,4 +106,6 @@ protected: virtual void GetAssetRegistryTags(TArray& OutTags) const override; virtual void Serialize (FArchive& Ar) override; #endif + + void LoadInfo(); }; From cef191f6c671d6c239d2b57a1781072738af931e Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 16:54:47 +0100 Subject: [PATCH 35/39] [ue4] Fixed segfault in SpineSkeletonDataAsset. Added PreviewAnimation and PreviewSkin to SpineSkeletonAnimationComponent. Enter the name of an animation or skin and it will be previewed live in the editor view. Use an empty string to reset the animation or skin. --- .../Private/SpineSkeletonAnimationComponent.cpp | 11 +++++++++++ .../SpinePlugin/Private/SpineSkeletonDataAsset.cpp | 1 + .../Public/SpineSkeletonAnimationComponent.h | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp index 8dabf4250..cb62ac8be 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp @@ -96,6 +96,17 @@ void USpineSkeletonAnimationComponent::InternalTick(float DeltaTime, bool CallDe CheckState(); if (state && bAutoPlaying) { + if (lastPreviewAnimation != PreviewAnimation) { + if (PreviewAnimation != "") SetAnimation(0, TCHAR_TO_UTF8(*PreviewAnimation), true); + else SetEmptyAnimation(0, 0); + lastPreviewAnimation = PreviewAnimation; + } + + if (lastPreviewSkin != PreviewSkin) { + if (PreviewSkin != "") SetSkin(TCHAR_TO_UTF8(*PreviewSkin)); + else SetSkin("default"); + lastPreviewSkin = PreviewSkin; + } state->update(DeltaTime); state->apply(*skeleton); if (CallDelegates) BeforeUpdateWorldTransform.Broadcast(this); diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp index 94919b6cb..34423f537 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp @@ -128,6 +128,7 @@ public: void USpineSkeletonDataAsset::LoadInfo() { #if WITH_EDITORONLY_DATA int dataLen = rawData.Num(); + if (dataLen == 0) return; NullAttachmentLoader loader; SkeletonData* skeletonData = nullptr; if (skeletonDataFileName.GetPlainNameString().Contains(TEXT(".json"))) { diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h index eac35678a..3403d1fca 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h @@ -259,6 +259,12 @@ public: UPROPERTY(BlueprintAssignable, Category="Components|Spine|Animation") FSpineAnimationDisposeDelegate AnimationDispose; + + UPROPERTY(Transient, EditAnywhere) + FString PreviewAnimation; + + UPROPERTY(Transient, EditAnywhere) + FString PreviewSkin; // used in C event callback. Needs to be public as we can't call // protected methods from plain old C function. @@ -279,4 +285,7 @@ private: /* If the animation should update automatically. */ UPROPERTY() bool bAutoPlaying; + + FString lastPreviewAnimation; + FString lastPreviewSkin; }; From dd85819c5014e486773d7bb5b6d57159ad60cff6 Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 16:57:01 +0100 Subject: [PATCH 36/39] Updated CHANGELOG. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a40e112e9..11b2a97b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -100,6 +100,7 @@ * Updated to Unreal Engine 4.21 (samples require 4.21). * **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175 * Added query methods for slots, bones, skins and animations to `SpineSkeletonComponent` and `UTrackEntry`. These allow you to query these objects by name in both C++ and blueprints. +* Added `Preview Animation` and `Preview Skin` properties to `SpineSkeletonAnimationComponent`. Enter an animation or skin name to live-preview it in the editor. Enter an empty string to reset the animation or skin. ## C# ## * **Breaking changes** From dcce71416f314d902eb76b64b91dd634f2f7a22f Mon Sep 17 00:00:00 2001 From: badlogic Date: Thu, 7 Mar 2019 16:31:15 +0100 Subject: [PATCH 37/39] [ue4] Fixed call order of SpineSkeletonImportFactory, asset file name must be set before setting raw data. Fixes issue with importing .json files. See #1291. --- .../Private/SpineSkeletonImportFactory.cpp | 2 +- .../Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp | 6 ++++++ .../Source/SpinePlugin/Public/SpineSkeletonDataAsset.h | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpineEditorPlugin/Private/SpineSkeletonImportFactory.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpineEditorPlugin/Private/SpineSkeletonImportFactory.cpp index 75f49a7cc..40e638fd1 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpineEditorPlugin/Private/SpineSkeletonImportFactory.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpineEditorPlugin/Private/SpineSkeletonImportFactory.cpp @@ -81,9 +81,9 @@ UObject* USpineSkeletonAssetFactory::FactoryCreateFile (UClass * InClass, UObjec if (!FFileHelper::LoadFileToArray(rawData, *Filename, 0)) { return nullptr; } + asset->SetSkeletonDataFileName(FName(*Filename)); asset->SetRawData(rawData); - asset->SetSkeletonDataFileName(FName(*Filename)); const FString longPackagePath = FPackageName::GetLongPackagePath(asset->GetOutermost()->GetPathName()); LoadAtlas(Filename, longPackagePath); return asset; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp index 34423f537..0968f173b 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp @@ -155,9 +155,15 @@ void USpineSkeletonDataAsset::LoadInfo() { Skins.Empty(); for (int i = 0; i < skeletonData->getSkins().size(); i++) Skins.Add(skeletonData->getSkins()[i]->getName().buffer()); + Slots.Empty(); + for (int i = 0; i < skeletonData->getSlots().size(); i++) + Slots.Add(skeletonData->getSlots()[i]->getName().buffer()); Animations.Empty(); for (int i = 0; i < skeletonData->getAnimations().size(); i++) Animations.Add(skeletonData->getAnimations()[i]->getName().buffer()); + Events.Empty(); + for (int i = 0; i < skeletonData->getEvents().size(); i++) + Events.Add(skeletonData->getEvents()[i]->getName().buffer()); delete skeletonData; } #endif diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h index c94a896ce..48dd58492 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h @@ -82,6 +82,9 @@ public: UPROPERTY(Transient, VisibleAnywhere) TArray Animations; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Events; protected: UPROPERTY() From 8185418319e3f536bc70fa73b0dbf081b0e464f4 Mon Sep 17 00:00:00 2001 From: badlogic Date: Thu, 7 Mar 2019 17:22:10 +0100 Subject: [PATCH 38/39] [ue4] Fixed encoding of strings where necessary. Closes #1291. --- .../Private/SpineSkeletonAnimationComponent.cpp | 4 ++-- .../SpinePlugin/Private/SpineSkeletonDataAsset.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp index cb62ac8be..a9edb99dd 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp @@ -97,13 +97,13 @@ void USpineSkeletonAnimationComponent::InternalTick(float DeltaTime, bool CallDe if (state && bAutoPlaying) { if (lastPreviewAnimation != PreviewAnimation) { - if (PreviewAnimation != "") SetAnimation(0, TCHAR_TO_UTF8(*PreviewAnimation), true); + if (PreviewAnimation != "") SetAnimation(0, PreviewAnimation, true); else SetEmptyAnimation(0, 0); lastPreviewAnimation = PreviewAnimation; } if (lastPreviewSkin != PreviewSkin) { - if (PreviewSkin != "") SetSkin(TCHAR_TO_UTF8(*PreviewSkin)); + if (PreviewSkin != "") SetSkin(PreviewSkin); else SetSkin("default"); lastPreviewSkin = PreviewSkin; } diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp index 0968f173b..8b101866f 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp @@ -151,19 +151,19 @@ void USpineSkeletonDataAsset::LoadInfo() { if (skeletonData) { Bones.Empty(); for (int i = 0; i < skeletonData->getBones().size(); i++) - Bones.Add(skeletonData->getBones()[i]->getName().buffer()); + Bones.Add(UTF8_TO_TCHAR(skeletonData->getBones()[i]->getName().buffer())); Skins.Empty(); for (int i = 0; i < skeletonData->getSkins().size(); i++) - Skins.Add(skeletonData->getSkins()[i]->getName().buffer()); + Skins.Add(UTF8_TO_TCHAR(skeletonData->getSkins()[i]->getName().buffer())); Slots.Empty(); for (int i = 0; i < skeletonData->getSlots().size(); i++) - Slots.Add(skeletonData->getSlots()[i]->getName().buffer()); + Slots.Add(UTF8_TO_TCHAR(skeletonData->getSlots()[i]->getName().buffer())); Animations.Empty(); for (int i = 0; i < skeletonData->getAnimations().size(); i++) - Animations.Add(skeletonData->getAnimations()[i]->getName().buffer()); + Animations.Add(UTF8_TO_TCHAR(skeletonData->getAnimations()[i]->getName().buffer())); Events.Empty(); for (int i = 0; i < skeletonData->getEvents().size(); i++) - Events.Add(skeletonData->getEvents()[i]->getName().buffer()); + Events.Add(UTF8_TO_TCHAR(skeletonData->getEvents()[i]->getName().buffer())); delete skeletonData; } #endif From 8018bdfa23dd25eb34012ba02e31dda07fca686e Mon Sep 17 00:00:00 2001 From: badlogic Date: Thu, 7 Mar 2019 18:10:19 +0100 Subject: [PATCH 39/39] [ue4] Rename category of preview properties. --- .../SpinePlugin/Public/SpineSkeletonAnimationComponent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h index 3403d1fca..f11ddd07f 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h @@ -260,10 +260,10 @@ public: UPROPERTY(BlueprintAssignable, Category="Components|Spine|Animation") FSpineAnimationDisposeDelegate AnimationDispose; - UPROPERTY(Transient, EditAnywhere) + UPROPERTY(Transient, EditAnywhere, Category=Spine) FString PreviewAnimation; - UPROPERTY(Transient, EditAnywhere) + UPROPERTY(Transient, EditAnywhere, Category=Spine) FString PreviewSkin; // used in C event callback. Needs to be public as we can't call