From d60bc9241ceab9b4e0ac29aa46a29fd0459f5416 Mon Sep 17 00:00:00 2001 From: Fenrisul Date: Fri, 23 Jan 2015 00:01:32 -0800 Subject: [PATCH] more attributes more bug fixes more helper menus even more examples --- .../Scenes/Attributes and AtlasRegions.unity | Bin 20844 -> 23236 bytes .../Examples/Scenes/Mix and Match.unity | Bin 18572 -> 21156 bytes .../Examples/Scenes/Spineboy Movement.unity | Bin 9078 -> 21588 bytes .../Scripts/BasicPlatformerController.cs | 12 +- .../Assets/Examples/Scripts/Chimera.cs | 38 +++- .../Examples/Scripts/DynamicSpineBone.cs | 66 ++++++ .../Examples/Scripts/DynamicSpineBone.cs.meta | 8 + .../Examples/Scripts/FootSoldierExample.cs | 40 +++- .../Examples/Scripts/SpineboyController.cs | 36 +++- .../Spine/Spineboy/spineboy_Atlas.asset | Bin 531 -> 4184 bytes spine-unity/Assets/spine-unity/CustomSkin.cs | 36 ++++ .../Assets/spine-unity/CustomSkin.cs.meta | 8 + .../spine-unity/Editor/AtlasAssetInspector.cs | 18 ++ .../Editor/GUI/icon-weights.png.meta | 2 +- .../Editor/SkeletonDataAssetInspector.cs | 36 +++- .../Editor/SpineAttributeDrawers.cs | 191 +++++++++++++++--- .../Editor/SpineEditorUtilities.cs | 56 ++++- .../Assets/spine-unity/SpineAttributes.cs | 159 +++++++++++---- 18 files changed, 620 insertions(+), 86 deletions(-) create mode 100644 spine-unity/Assets/Examples/Scripts/DynamicSpineBone.cs create mode 100644 spine-unity/Assets/Examples/Scripts/DynamicSpineBone.cs.meta create mode 100644 spine-unity/Assets/spine-unity/CustomSkin.cs create mode 100644 spine-unity/Assets/spine-unity/CustomSkin.cs.meta diff --git a/spine-unity/Assets/Examples/Scenes/Attributes and AtlasRegions.unity b/spine-unity/Assets/Examples/Scenes/Attributes and AtlasRegions.unity index eadbc4873f48ce5994ef8c347e10bb2864c072c0..cc0f39f32e3b0e7df6ea0d5cfaa6a71699067dfc 100644 GIT binary patch delta 1235 zcmaKre@IhN6vyw=xml^XNZT^l~LQ1rv1f{36W6!d3MRDT9hL_hxOpP(Q1J#+I%e|X@$d+z6+opbIvci%24 z&+aJ=jOiK14n1RxErWd?E8E_Nm?dzAX2R?Z(dtzj4Xm2 z&|6{W{dO6#jAhFkC0@y!oo-uXvbGtaRJjNn$$2H^m}hmws%JfW6Shbv64ubHd%cXh zybam3P-8JMB<$Hz6qJIS=Y(t)fZpD4JfL{wWMFViFZ)>4gaZSZ&PgL+Q!sjA(^W_Z z>kl>j1Un16;Fkb9Q^Xht+nd)U*p)mx0Y-Wh>_wg(#-8*T*ykcPmUCDQKsp4NC|;bn zb#mWa{DA*e0$A>W$ zu*u0-J?ss6?F5U0E$l)U*nO}le17Kx`oKJ{#cX2Po1qaf0lz}g=fK{BEsR&X0}gXi zK4+m7$$s0gN4I3nWM-6$coHv#W8PNQj)}B%_KdsVe);kG;-4|_Xkdy7Sx!G+zqE)6s9;N8cli&wMDV3K)Jyq0u5^7h$_Q~&|Bl50R zDGzH0+!!c(KRTWBqK`v9*T&o!%OdKOePPRmo-w|H<90RjQ+Qn7YIDe~L8olg);Ce% z3*%s$6T19vVZ`wde+uoy{JRiEW$Z%N^0#%Z2)0gkXk|+V=(OUaj7>d(;)mz|58$CT z`wDHQ@lxs3LAO9!Np}>tx-Ce4zTd5z7G=ZcJqW diff --git a/spine-unity/Assets/Examples/Scenes/Mix and Match.unity b/spine-unity/Assets/Examples/Scenes/Mix and Match.unity index 06731d193734e3c12f259376965aca7553d6fc76..775cb6bf7db3097d97bbac2b472558eca9a6248c 100644 GIT binary patch delta 1003 zcmZ9K%TE+R5Ql5_1?aAV5ilII35$Z^5kL(=<+TsMCyGW6Bs%O4I}_PiGt+zUks$G+ z2?w>~^PsDNg9-|+s0R=0fy6`)c*2W@#6&&9AAoDs?x2gERJ!V$>i*SK_1Fz*d_t-O zI4}utd>jA@&`;qGyXyATH4HVt?{qp{i1A9YCV$d7<891;xuIK1J}7u(vuV2Macf0= zXEnW7)(kMw(KS6HQjXo?j;mO#bGna0K3xaUrRa*Gh1lVk9)qyVWx$)$TeBZQqWvm> z9XFF3cnO%XxDir1IG00eRMB}Rf1CL1st}`|Q=-dLB2`c%dBw7uNtI%~vs~IP9=glK z5s$0zzk@q6sa2WO>P+g+Wpii|LxX&Ux zX9M8qQ)`I5M)nKY8T3mndxNYSf5wY(xn*zZEV2_AJ1lFt`@QOe9Y)|Df>q(Y2vy7& zK(=Cu?4v|vxx)LAwL8}ew<1d*%N1^;v&eFVpG+^-GZ(d zx7a0QWRu92EJj6=O(84H%YNUCG1+ru*OBE4V+io$Fc3)bA81vJ#!aIXzl?1 z+cV0yh2{3C)W^q__h-I{mCkOl&{-pbzD>zNUr_3&9#TJPQIDzLv}gu23tBXzRi9=^ ztPCv@8ywbjvo@-jDy#CvO&*Ifdc4&DV#(j^phqBT0?dxX6bA$4tu!T7k;5Bt4=Y1* ze3;iq;yM`=Av3gy%9$$bVWx2<${LYjTfkH`WjHK4d}Y}?#{xX-ID!LN=e^Inh2$_f zXI*Y6x~r*l(d%>E3_3+^Ag_oDSUmsY@3nc! IK%mS12To%KVE_OC delta 371 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 diff --git a/spine-unity/Assets/Examples/Scripts/BasicPlatformerController.cs b/spine-unity/Assets/Examples/Scripts/BasicPlatformerController.cs index 071dc48cc..761ac31af 100644 --- a/spine-unity/Assets/Examples/Scripts/BasicPlatformerController.cs +++ b/spine-unity/Assets/Examples/Scripts/BasicPlatformerController.cs @@ -71,17 +71,17 @@ public class BasicPlatformerController : MonoBehaviour { #if UNITY_4_5 [Header("Animation")] #endif - [SpineAnimation(dataSource: "skeletonAnimation")] + [SpineAnimation(dataField: "skeletonAnimation")] public string walkName = "Walk"; - [SpineAnimation(dataSource: "skeletonAnimation")] + [SpineAnimation(dataField: "skeletonAnimation")] public string runName = "Run"; - [SpineAnimation(dataSource: "skeletonAnimation")] + [SpineAnimation(dataField: "skeletonAnimation")] public string idleName = "Idle"; - [SpineAnimation(dataSource: "skeletonAnimation")] + [SpineAnimation(dataField: "skeletonAnimation")] public string jumpName = "Jump"; - [SpineAnimation(dataSource: "skeletonAnimation")] + [SpineAnimation(dataField: "skeletonAnimation")] public string fallName = "Fall"; - [SpineAnimation(dataSource: "skeletonAnimation")] + [SpineAnimation(dataField: "skeletonAnimation")] public string crouchName = "Crouch"; #if UNITY_4_5 diff --git a/spine-unity/Assets/Examples/Scripts/Chimera.cs b/spine-unity/Assets/Examples/Scripts/Chimera.cs index 35cab0362..27f831f86 100644 --- a/spine-unity/Assets/Examples/Scripts/Chimera.cs +++ b/spine-unity/Assets/Examples/Scripts/Chimera.cs @@ -1,11 +1,45 @@ -using UnityEngine; +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * 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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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. + *****************************************************************************/ + +/***************************************************************************** + * Basic Platformer Controller created by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ +using UnityEngine; using System.Collections; public class Chimera : MonoBehaviour { public SkeletonDataAsset skeletonDataSource; - [SpineAttachment(currentSkinOnly: false, returnFullPath: true, dataSource: "skeletonDataSource")] + [SpineAttachment(currentSkinOnly: false, returnAttachmentPath: true, dataField: "skeletonDataSource")] public string attachmentPath; [SpineSlot] diff --git a/spine-unity/Assets/Examples/Scripts/DynamicSpineBone.cs b/spine-unity/Assets/Examples/Scripts/DynamicSpineBone.cs new file mode 100644 index 000000000..c638f696e --- /dev/null +++ b/spine-unity/Assets/Examples/Scripts/DynamicSpineBone.cs @@ -0,0 +1,66 @@ +using UnityEngine; +using System.Collections; + +public class DynamicSpineBone : MonoBehaviour { + + public Transform speedReference; + + [SpineBone] + public string boneName; + + [Range(-90, 90)] + public float minRotation = -45; + [Range(-90, 90)] + public float maxRotation = 45; + + [Range(-2000, 2000)] + public float rotationFactor = 300; + + [Range(5, 30)] + public float returnSpeed = 10; + + [Range(100, 1000)] + public float boneSpeed = 300; + + public float returnThreshhold = 0.01f; + + public bool useAcceleration; + + + SkeletonAnimation skeletonAnimation; + float goalRotation; + Spine.Bone bone; + Vector3 velocity; + Vector3 acceleration; + Vector3 lastPosition; + + void Start() { + if (speedReference == null) + speedReference = transform; + + skeletonAnimation = GetComponent(); + bone = SpineBone.GetBone(boneName, skeletonAnimation); + skeletonAnimation.UpdateLocal += UpdateLocal; + lastPosition = speedReference.position; + } + + void FixedUpdate() { + acceleration = (speedReference.position - lastPosition) - velocity; + velocity = speedReference.position - lastPosition; + lastPosition = speedReference.position; + } + + void UpdateLocal(SkeletonAnimation animation) { + Vector3 vec = useAcceleration ? acceleration : velocity; + + if (Mathf.Abs(vec.x) < returnThreshhold) + goalRotation = Mathf.Lerp(goalRotation, 0, returnSpeed * Time.deltaTime); + else + goalRotation += vec.x * rotationFactor * Time.deltaTime * (bone.WorldFlipX ? -1 : 1); + + goalRotation = Mathf.Clamp(goalRotation, minRotation, maxRotation); + + bone.Rotation = Mathf.Lerp(bone.Rotation, bone.Rotation + goalRotation, boneSpeed * Time.deltaTime); + + } +} diff --git a/spine-unity/Assets/Examples/Scripts/DynamicSpineBone.cs.meta b/spine-unity/Assets/Examples/Scripts/DynamicSpineBone.cs.meta new file mode 100644 index 000000000..6aac53582 --- /dev/null +++ b/spine-unity/Assets/Examples/Scripts/DynamicSpineBone.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7dae3f4db9a24bf4abe2059526bfd689 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/spine-unity/Assets/Examples/Scripts/FootSoldierExample.cs b/spine-unity/Assets/Examples/Scripts/FootSoldierExample.cs index d85f99847..655445869 100644 --- a/spine-unity/Assets/Examples/Scripts/FootSoldierExample.cs +++ b/spine-unity/Assets/Examples/Scripts/FootSoldierExample.cs @@ -1,4 +1,38 @@ -using UnityEngine; +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * 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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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. + *****************************************************************************/ + +/***************************************************************************** + * FootSoldierExample created by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ +using UnityEngine; using System.Collections; public class FootSoldierExample : MonoBehaviour { @@ -11,10 +45,10 @@ public class FootSoldierExample : MonoBehaviour { [SpineSlot] public string eyesSlot; - [SpineAttachment(currentSkinOnly: true, slot: "eyesSlot")] + [SpineAttachment(currentSkinOnly: true, slotField: "eyesSlot")] public string eyesOpenAttachment; - [SpineAttachment(currentSkinOnly: true, slot: "eyesSlot")] + [SpineAttachment(currentSkinOnly: true, slotField: "eyesSlot")] public string blinkAttachment; [Range(0, 0.2f)] diff --git a/spine-unity/Assets/Examples/Scripts/SpineboyController.cs b/spine-unity/Assets/Examples/Scripts/SpineboyController.cs index 4cebc7de3..064152df4 100644 --- a/spine-unity/Assets/Examples/Scripts/SpineboyController.cs +++ b/spine-unity/Assets/Examples/Scripts/SpineboyController.cs @@ -1,4 +1,38 @@ -using UnityEngine; +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * 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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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. + *****************************************************************************/ + +/***************************************************************************** + * SpineboyController created by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ +using UnityEngine; using System.Collections; [RequireComponent(typeof(SkeletonAnimation), typeof(Rigidbody2D))] diff --git a/spine-unity/Assets/Examples/Spine/Spineboy/spineboy_Atlas.asset b/spine-unity/Assets/Examples/Spine/Spineboy/spineboy_Atlas.asset index ae8491bec74d3e193f738ff88d2696e58fc2fd32..ae6be64dcb8048658a50f8f7e43c6b46ddc7e000 100644 GIT binary patch literal 4184 zcmeHKJ8u&~5FP^w@An(?NRc{HB!nnXWGC2Qqy$TVL`Agrt?iBMyJ&Y4*;M`mh#HB) z1uddQ)Je@>;6Ko%z|7-ppY5ZezOj7!`ex^wZ}v`i01Mv%F1-bS)7WAI@NnhP%4%a3 z{tSo19FDOWZbo6Wu3Ku~M0*z2mD4=Uc)Sn{`T%FK*$bU%hB{a>p@+`)%i4~v`{yRm z<+f@%IDrs`$L*+Jt$O>U6c``bQrBzTBnsEiziM?u)vC(s(92$M3SE!kpN!md_@l7| zESt8jJmomY34t~OQC~n+epM!LZH0j*{d{# zmPCxnh;kck2?B?ix2Hwo$jQ7_VK9^S?DOd>5OVS79*bkQb^KrR*bti zH`X{oYh0>(Gn>#*Qr(P$tx460?)@2XYLX8UpnoR0lmenD;#&Cql~?IGOvlY)OOaqF zU-{V2AC*6S-pIWx94*Te?Qn2d?+t>j53alTCFDTyEEdx)$}ei}Wc#tMZ~cIC#N0nF06Tr0ur*(Hklti71I)JdxLKi#5wG>2^(s;lJC37?&7(XwuHS zc{4M9o2?%anUZMyI$NSqH$onEqN}YxCgoH$`w7K_h$xQZ9wmgKn{eU&MC+z*ZuL8S z+NN_NLTJBzmLFRA2V3ez1-n)teE!}zZ9s0o>Dpf?0(}`<>D7IpoCcg#?X|0+`in1N zum78!*B~oh3PjFQ^V0gp{c-W4oIUt~G9mn&WP)~`4bzZHQZSR_ToN!TD+*O4j9|?% z1H|o~V*h%6YCSXBbi{B^Vjf M@=Wp{O?ryH0X8w6y8r+H diff --git a/spine-unity/Assets/spine-unity/CustomSkin.cs b/spine-unity/Assets/spine-unity/CustomSkin.cs new file mode 100644 index 000000000..5b98ad66c --- /dev/null +++ b/spine-unity/Assets/spine-unity/CustomSkin.cs @@ -0,0 +1,36 @@ +using UnityEngine; +using System.Collections; +using Spine; + +public class CustomSkin : MonoBehaviour { + + + [System.Serializable] + public class SkinPair { + [SpineAttachment(currentSkinOnly: false, returnAttachmentPath: true, dataField: "skinSource")] + public string sourceAttachment; + [SpineSlot] + public string targetSlot; + [SpineAttachment(currentSkinOnly: true, placeholdersOnly: true)] + public string targetAttachment; + } + + public SkeletonDataAsset skinSource; + public SkinPair[] skinning; + public Skin customSkin; + + SkeletonRenderer skeletonRenderer; + void Start() { + skeletonRenderer = GetComponent(); + Skeleton skeleton = skeletonRenderer.skeleton; + + customSkin = new Skin("CustomSkin"); + + foreach (var pair in skinning) { + var attachment = SpineAttachment.GetAttachment(pair.sourceAttachment, skinSource); + customSkin.AddAttachment(skeleton.FindSlotIndex(pair.targetSlot), pair.targetAttachment, attachment); + } + + skeleton.SetSkin(customSkin); + } +} diff --git a/spine-unity/Assets/spine-unity/CustomSkin.cs.meta b/spine-unity/Assets/spine-unity/CustomSkin.cs.meta new file mode 100644 index 000000000..3a7ba7a9d --- /dev/null +++ b/spine-unity/Assets/spine-unity/CustomSkin.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6e55c8477eccddc4cb5c3551a3945ca7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/spine-unity/Assets/spine-unity/Editor/AtlasAssetInspector.cs b/spine-unity/Assets/spine-unity/Editor/AtlasAssetInspector.cs index fc07c6fae..a58fc9340 100644 --- a/spine-unity/Assets/spine-unity/Editor/AtlasAssetInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/AtlasAssetInspector.cs @@ -50,9 +50,27 @@ public class AtlasAssetInspector : Editor { serializedObject.Update(); AtlasAsset asset = (AtlasAsset)target; + EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(atlasFile); EditorGUILayout.PropertyField(materials, true); + if (EditorGUI.EndChangeCheck()) + serializedObject.ApplyModifiedProperties(); + if (materials.arraySize == 0) { + EditorGUILayout.LabelField(new GUIContent("Error: Missing materials", SpineEditorUtilities.Icons.warning)); + return; + } + + for (int i = 0; i < materials.arraySize; i++) { + SerializedProperty prop = materials.GetArrayElementAtIndex(i); + Material mat = (Material)prop.objectReferenceValue; + if (mat == null) { + EditorGUILayout.LabelField(new GUIContent("Error: Materials cannot be null", SpineEditorUtilities.Icons.warning)); + return; + } + } + + if (atlasFile.objectReferenceValue != null) { Atlas atlas = asset.GetAtlas(); diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-weights.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-weights.png.meta index fa7031fc0..067337d4f 100644 --- a/spine-unity/Assets/spine-unity/Editor/GUI/icon-weights.png.meta +++ b/spine-unity/Assets/spine-unity/Editor/GUI/icon-weights.png.meta @@ -21,7 +21,7 @@ TextureImporter: grayScaleToAlpha: 0 generateCubemap: 0 seamlessCubemap: 0 - textureFormat: -1 + textureFormat: -3 maxTextureSize: 1024 textureSettings: filterMode: -1 diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs index 0edf206e6..d2dfb0dbe 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs @@ -102,12 +102,18 @@ public class SkeletonDataAssetInspector : Editor { EditorGUILayout.PropertyField(skeletonJSON); EditorGUILayout.PropertyField(scale); if (EditorGUI.EndChangeCheck()) { - if (m_previewUtility != null) { - m_previewUtility.Cleanup(); - m_previewUtility = null; - } + if (serializedObject.ApplyModifiedProperties()) { - RepopulateWarnings(); + if (m_previewUtility != null) { + m_previewUtility.Cleanup(); + m_previewUtility = null; + } + + RepopulateWarnings(); + OnEnable(); + return; + } + } @@ -118,6 +124,8 @@ public class SkeletonDataAssetInspector : Editor { DrawSlotList(); } else { + + DrawReimportButton(); //Show Warnings foreach (var str in warnings) EditorGUILayout.LabelField(new GUIContent(str, SpineEditorUtilities.Icons.warning)); @@ -132,6 +140,24 @@ public class SkeletonDataAssetInspector : Editor { } } + void DrawReimportButton() { + EditorGUI.BeginDisabledGroup(skeletonJSON.objectReferenceValue == null); + if (GUILayout.Button(new GUIContent("Attempt Reimport", SpineEditorUtilities.Icons.warning))) { + SpineEditorUtilities.ImportSpineContent(new string[] { AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue) }, true); + + if (m_previewUtility != null) { + m_previewUtility.Cleanup(); + m_previewUtility = null; + } + + RepopulateWarnings(); + OnEnable(); + return; + + } + EditorGUI.EndDisabledGroup(); + } + void DrawAnimationStateInfo() { showAnimationStateData = EditorGUILayout.Foldout(showAnimationStateData, "Animation State Data"); if (!showAnimationStateData) diff --git a/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs b/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs index cdc9a0e37..9d9e3b3d2 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs @@ -1,4 +1,38 @@ -using UnityEngine; +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * 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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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. + *****************************************************************************/ + +/***************************************************************************** + * Spine Attribute Drawers created by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ +using UnityEngine; using UnityEditor; using System.Collections; using System.Collections.Generic; @@ -32,13 +66,13 @@ public class SpineSlotDrawer : PropertyDrawer { SpineSlot attrib = (SpineSlot)attribute; - var skeletonDataAssetProperty = property.serializedObject.FindProperty(attrib.dataSource); + var dataProperty = property.serializedObject.FindProperty(attrib.dataField); - if (skeletonDataAssetProperty != null) { - if (skeletonDataAssetProperty.objectReferenceValue is SkeletonDataAsset) { - skeletonDataAsset = (SkeletonDataAsset)skeletonDataAssetProperty.objectReferenceValue; - } else if (skeletonDataAssetProperty.objectReferenceValue is SkeletonRenderer) { - var renderer = (SkeletonRenderer)skeletonDataAssetProperty.objectReferenceValue; + if (dataProperty != null) { + if (dataProperty.objectReferenceValue is SkeletonDataAsset) { + skeletonDataAsset = (SkeletonDataAsset)dataProperty.objectReferenceValue; + } else if (dataProperty.objectReferenceValue is SkeletonRenderer) { + var renderer = (SkeletonRenderer)dataProperty.objectReferenceValue; if (renderer != null) skeletonDataAsset = renderer.skeletonDataAsset; } else { @@ -102,7 +136,6 @@ public class SpineSlotDrawer : PropertyDrawer { public class SpineSkinDrawer : PropertyDrawer { SkeletonDataAsset skeletonDataAsset; - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { if (property.propertyType != SerializedPropertyType.String) { EditorGUI.LabelField(position, "ERROR:", "May only apply to type string"); @@ -111,13 +144,13 @@ public class SpineSkinDrawer : PropertyDrawer { SpineSkin attrib = (SpineSkin)attribute; - var skeletonDataAssetProperty = property.serializedObject.FindProperty(attrib.dataSource); + var dataProperty = property.serializedObject.FindProperty(attrib.dataField); - if (skeletonDataAssetProperty != null) { - if (skeletonDataAssetProperty.objectReferenceValue is SkeletonDataAsset) { - skeletonDataAsset = (SkeletonDataAsset)skeletonDataAssetProperty.objectReferenceValue; - } else if (skeletonDataAssetProperty.objectReferenceValue is SkeletonRenderer) { - var renderer = (SkeletonRenderer)skeletonDataAssetProperty.objectReferenceValue; + if (dataProperty != null) { + if (dataProperty.objectReferenceValue is SkeletonDataAsset) { + skeletonDataAsset = (SkeletonDataAsset)dataProperty.objectReferenceValue; + } else if (dataProperty.objectReferenceValue is SkeletonRenderer) { + var renderer = (SkeletonRenderer)dataProperty.objectReferenceValue; if (renderer != null) skeletonDataAsset = renderer.skeletonDataAsset; } else { @@ -256,13 +289,13 @@ public class SpineAnimationDrawer : PropertyDrawer { SpineAnimation attrib = (SpineAnimation)attribute; - var skeletonDataAssetProperty = property.serializedObject.FindProperty(attrib.dataSource); + var dataProperty = property.serializedObject.FindProperty(attrib.dataField); - if (skeletonDataAssetProperty != null) { - if (skeletonDataAssetProperty.objectReferenceValue is SkeletonDataAsset) { - skeletonDataAsset = (SkeletonDataAsset)skeletonDataAssetProperty.objectReferenceValue; - } else if (skeletonDataAssetProperty.objectReferenceValue is SkeletonRenderer) { - var renderer = (SkeletonRenderer)skeletonDataAssetProperty.objectReferenceValue; + if (dataProperty != null) { + if (dataProperty.objectReferenceValue is SkeletonDataAsset) { + skeletonDataAsset = (SkeletonDataAsset)dataProperty.objectReferenceValue; + } else if (dataProperty.objectReferenceValue is SkeletonRenderer) { + var renderer = (SkeletonRenderer)dataProperty.objectReferenceValue; if (renderer != null) skeletonDataAsset = renderer.skeletonDataAsset; } else { @@ -332,13 +365,13 @@ public class SpineAttachmentDrawer : PropertyDrawer { SpineAttachment attrib = (SpineAttachment)attribute; - var skeletonDataAssetProperty = property.serializedObject.FindProperty(attrib.dataSource); + var dataProperty = property.serializedObject.FindProperty(attrib.dataField); - if (skeletonDataAssetProperty != null) { - if (skeletonDataAssetProperty.objectReferenceValue is SkeletonDataAsset) { - skeletonDataAsset = (SkeletonDataAsset)skeletonDataAssetProperty.objectReferenceValue; - } else if (skeletonDataAssetProperty.objectReferenceValue is SkeletonRenderer) { - var renderer = (SkeletonRenderer)skeletonDataAssetProperty.objectReferenceValue; + if (dataProperty != null) { + if (dataProperty.objectReferenceValue is SkeletonDataAsset) { + skeletonDataAsset = (SkeletonDataAsset)dataProperty.objectReferenceValue; + } else if (dataProperty.objectReferenceValue is SkeletonRenderer) { + var renderer = (SkeletonRenderer)dataProperty.objectReferenceValue; if (renderer != null) skeletonDataAsset = renderer.skeletonDataAsset; else { @@ -381,8 +414,11 @@ public class SpineAttachmentDrawer : PropertyDrawer { List validSkins = new List(); if (skeletonRenderer != null && attrib.currentSkinOnly) { - if (skeletonRenderer.skeleton.Skin != null) + if (skeletonRenderer.skeleton.Skin != null) { validSkins.Add(skeletonRenderer.skeleton.Skin); + } else { + validSkins.Add(data.Skins[0]); + } } else { foreach (Skin skin in data.Skins) { if (skin != null) @@ -392,6 +428,8 @@ public class SpineAttachmentDrawer : PropertyDrawer { GenericMenu menu = new GenericMenu(); List attachmentNames = new List(); + List placeholderNames = new List(); + string prefix = ""; if (skeletonRenderer != null && attrib.currentSkinOnly) @@ -405,7 +443,7 @@ public class SpineAttachmentDrawer : PropertyDrawer { Skin defaultSkin = data.Skins[0]; - SerializedProperty slotProperty = property.serializedObject.FindProperty(attrib.slotSource); + SerializedProperty slotProperty = property.serializedObject.FindProperty(attrib.slotField); string slotMatch = ""; if (slotProperty != null) { if (slotProperty.propertyType == SerializedPropertyType.String) { @@ -424,18 +462,31 @@ public class SpineAttachmentDrawer : PropertyDrawer { continue; attachmentNames.Clear(); + placeholderNames.Clear(); + skin.FindNamesForSlot(i, attachmentNames); - if (skin != defaultSkin) + if (skin != defaultSkin) { defaultSkin.FindNamesForSlot(i, attachmentNames); + skin.FindNamesForSlot(i, placeholderNames); + } + for (int a = 0; a < attachmentNames.Count; a++) { + string attachmentPath = attachmentNames[a]; string menuPath = prefix + data.Slots[i].Name + "/" + attachmentPath; string name = attachmentNames[a]; - if (attrib.returnFullPath) + if (attrib.returnAttachmentPath) name = skin.Name + "/" + data.Slots[i].Name + "/" + attachmentPath; - menu.AddItem(new GUIContent(menuPath), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property)); + + if (attrib.placeholdersOnly && placeholderNames.Contains(attachmentPath) == false) { + menu.AddDisabledItem(new GUIContent(menuPath)); + } else { + menu.AddItem(new GUIContent(menuPath), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property)); + } + + } } } @@ -454,3 +505,81 @@ public class SpineAttachmentDrawer : PropertyDrawer { return 18; } } + +[CustomPropertyDrawer(typeof(SpineBone))] +public class SpineBoneDrawer : PropertyDrawer { + SkeletonDataAsset skeletonDataAsset; + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { + if (property.propertyType != SerializedPropertyType.String) { + EditorGUI.LabelField(position, "ERROR:", "May only apply to type string"); + return; + } + + SpineBone attrib = (SpineBone)attribute; + + var dataProperty = property.serializedObject.FindProperty(attrib.dataField); + + if (dataProperty != null) { + if (dataProperty.objectReferenceValue is SkeletonDataAsset) { + skeletonDataAsset = (SkeletonDataAsset)dataProperty.objectReferenceValue; + } else if (dataProperty.objectReferenceValue is SkeletonRenderer) { + var renderer = (SkeletonRenderer)dataProperty.objectReferenceValue; + if (renderer != null) + skeletonDataAsset = renderer.skeletonDataAsset; + } else { + EditorGUI.LabelField(position, "ERROR:", "Invalid reference type"); + return; + } + + } else if (property.serializedObject.targetObject is Component) { + var component = (Component)property.serializedObject.targetObject; + if (component.GetComponent() != null) { + var skeletonRenderer = component.GetComponent(); + skeletonDataAsset = skeletonRenderer.skeletonDataAsset; + } + } + + if (skeletonDataAsset == null) { + EditorGUI.LabelField(position, "ERROR:", "Must have reference to a SkeletonDataAsset"); + return; + } + + position = EditorGUI.PrefixLabel(position, label); + + if (GUI.Button(position, property.stringValue, EditorStyles.popup)) { + Selector(property); + } + + } + + void Selector(SerializedProperty property) { + SpineBone attrib = (SpineBone)attribute; + SkeletonData data = skeletonDataAsset.GetSkeletonData(true); + if (data == null) + return; + + GenericMenu menu = new GenericMenu(); + + menu.AddDisabledItem(new GUIContent(skeletonDataAsset.name)); + menu.AddSeparator(""); + + for (int i = 0; i < data.Bones.Count; i++) { + string name = data.Bones[i].Name; + if (name.StartsWith(attrib.startsWith)) + menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property)); + } + + menu.ShowAsContext(); + } + + void HandleSelect(object val) { + var pair = (SpineDrawerValuePair)val; + pair.property.stringValue = pair.str; + pair.property.serializedObject.ApplyModifiedProperties(); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { + return 18; + } +} diff --git a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs index f939ce455..428860341 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs @@ -209,8 +209,10 @@ public class SpineEditorUtilities : AssetPostprocessor { } - static void OnPostprocessAllAssets(string[] imported, string[] deleted, string[] moved, string[] movedFromAssetPaths) { + ImportSpineContent(imported, false); + } + public static void ImportSpineContent(string[] imported, bool reimport = false) { List atlasPaths = new List(); List imagePaths = new List(); @@ -242,6 +244,9 @@ public class SpineEditorUtilities : AssetPostprocessor { //import atlases first foreach (string ap in atlasPaths) { + if (!reimport && CheckForValidAtlas(ap)) + continue; + TextAsset atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(ap, typeof(TextAsset)); AtlasAsset atlas = IngestSpineAtlas(atlasText); atlases.Add(atlas); @@ -250,7 +255,14 @@ public class SpineEditorUtilities : AssetPostprocessor { //import skeletons and match them with atlases bool abortSkeletonImport = false; foreach (string sp in skeletonPaths) { + if (!reimport && CheckForValidSkeletonData(sp)) { + Debug.Log("Automatically skipping: " + sp); + continue; + } + + string dir = Path.GetDirectoryName(sp); + var localAtlases = FindAtlasesAtPath(dir); var requiredPaths = GetRequiredAtlasRegions(sp); var atlasMatch = GetMatchingAtlas(requiredPaths, localAtlases); @@ -307,6 +319,48 @@ public class SpineEditorUtilities : AssetPostprocessor { //TODO: any post processing of images } + static bool CheckForValidSkeletonData(string skeletonJSONPath) { + + string dir = Path.GetDirectoryName(skeletonJSONPath); + TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonJSONPath, typeof(TextAsset)); + DirectoryInfo dirInfo = new DirectoryInfo(dir); + + FileInfo[] files = dirInfo.GetFiles("*.asset"); + + foreach (var f in files) { + string localPath = dir + "/" + f.Name; + var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object)); + if (obj is SkeletonDataAsset) { + var skeletonDataAsset = (SkeletonDataAsset)obj; + if (skeletonDataAsset.skeletonJSON == textAsset) + return true; + } + } + + return false; + } + + static bool CheckForValidAtlas(string atlasPath) { + + string dir = Path.GetDirectoryName(atlasPath); + TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(TextAsset)); + DirectoryInfo dirInfo = new DirectoryInfo(dir); + + FileInfo[] files = dirInfo.GetFiles("*.asset"); + + foreach (var f in files) { + string localPath = dir + "/" + f.Name; + var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object)); + if (obj is AtlasAsset) { + var atlasAsset = (AtlasAsset)obj; + if (atlasAsset.atlasFile == textAsset) + return true; + } + } + + return false; + } + static List MultiAtlasDialog(List requiredPaths, string initialDirectory, string header = "") { List atlasAssets = new List(); diff --git a/spine-unity/Assets/spine-unity/SpineAttributes.cs b/spine-unity/Assets/spine-unity/SpineAttributes.cs index 727196d49..1bf15bca2 100644 --- a/spine-unity/Assets/spine-unity/SpineAttributes.cs +++ b/spine-unity/Assets/spine-unity/SpineAttributes.cs @@ -1,87 +1,138 @@ -using UnityEngine; +/****************************************************************************** + * Spine Runtimes Software License + * Version 2.1 + * + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable and + * non-transferable license to install, execute and perform the Spine Runtimes + * Software (the "Software") solely for internal use. Without the written + * permission of Esoteric Software (typically granted by licensing Spine), you + * may not (a) modify, translate, adapt or otherwise create derivative works, + * improvements of the Software or develop new applications using the Software + * 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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) 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. + *****************************************************************************/ + +/***************************************************************************** + * Spine Attributes created by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ +using UnityEngine; using System.Collections; public class SpineSlot : PropertyAttribute { public string startsWith = ""; - public string dataSource = ""; + public string dataField = ""; /// - /// + /// Smart popup menu for Spine Slots /// - /// - /// SerializedProperty name containing a reference to either a SkeletonRenderer or a SkeletonDataAsset - public SpineSlot(string startsWith = "", string dataSource = "") { + /// Filters popup results to elements that begin with supplied string. + /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results. + /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives). + /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback. + /// + public SpineSlot(string startsWith = "", string dataField = "") { this.startsWith = startsWith; - this.dataSource = dataSource; + this.dataField = dataField; } } public class SpineSkin : PropertyAttribute { public string startsWith = ""; - public string dataSource = ""; + public string dataField = ""; /// - /// + /// Smart popup menu for Spine Skins /// - /// - /// SerializedProperty name containing a reference to either a SkeletonRenderer or a SkeletonDataAsset - public SpineSkin(string startsWith = "", string dataSource = "") { + /// Filters popup results to elements that begin with supplied string. + /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results. + /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives) + /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback. + /// + public SpineSkin(string startsWith = "", string dataField = "") { this.startsWith = startsWith; - this.dataSource = dataSource; + this.dataField = dataField; } } - -public class SpineAtlasRegion : PropertyAttribute { - -} - public class SpineAnimation : PropertyAttribute { public string startsWith = ""; - public string dataSource = ""; + public string dataField = ""; /// - /// + /// Smart popup menu for Spine Animations /// - /// - /// SerializedProperty name containing a reference to either a SkeletonRenderer or a SkeletonDataAsset - public SpineAnimation(string startsWith = "", string dataSource = "") { + /// Filters popup results to elements that begin with supplied string. + /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results. + /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives) + /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback. + /// + public SpineAnimation(string startsWith = "", string dataField = "") { this.startsWith = startsWith; - this.dataSource = dataSource; + this.dataField = dataField; } } public class SpineAttachment : PropertyAttribute { - public bool returnFullPath; - public bool currentSkinOnly; - public string dataSource = ""; - public string slotSource = ""; + public bool returnAttachmentPath = false; + public bool currentSkinOnly = false; + public bool placeholdersOnly = false; + public string dataField = ""; + public string slotField = ""; public SpineAttachment() { } - public SpineAttachment(bool currentSkinOnly = true, bool returnFullPath = false, string slot = "", string dataSource = "") { + /// + /// Smart popup menu for Spine Attachments + /// + /// Filters popup results to only include the current Skin. Only valid when a SkeletonRenderer is the data source. + /// Returns a fully qualified path for an Attachment in the format "Skin/Slot/AttachmentName" + /// Filters popup results to exclude attachments that are not children of Skin Placeholders + /// If specified, a locally scoped field with the name supplied by in slotField will be used to limit the popup results to children of a named slot + /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results. + /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives) + /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback. + /// + public SpineAttachment(bool currentSkinOnly = true, bool returnAttachmentPath = false, bool placeholdersOnly = false, string slotField = "", string dataField = "") { this.currentSkinOnly = currentSkinOnly; - this.returnFullPath = returnFullPath; - this.slotSource = slot; - this.dataSource = dataSource; + this.returnAttachmentPath = returnAttachmentPath; + this.placeholdersOnly = placeholdersOnly; + this.slotField = slotField; + this.dataField = dataField; } public static Hierarchy GetHierarchy(string fullPath) { return new Hierarchy(fullPath); } - public static Spine.Attachment GetAttachment(string fullPath, Spine.SkeletonData skeletonData) { - var hierarchy = SpineAttachment.GetHierarchy(fullPath); + public static Spine.Attachment GetAttachment(string attachmentPath, Spine.SkeletonData skeletonData) { + var hierarchy = SpineAttachment.GetHierarchy(attachmentPath); if (hierarchy.name == "") return null; return skeletonData.FindSkin(hierarchy.skin).GetAttachment(skeletonData.FindSlotIndex(hierarchy.slot), hierarchy.name); } - public static Spine.Attachment GetAttachment(string fullPath, SkeletonDataAsset skeletonDataAsset) { - return GetAttachment(fullPath, skeletonDataAsset.GetSkeletonData(true)); + public static Spine.Attachment GetAttachment(string attachmentPath, SkeletonDataAsset skeletonDataAsset) { + return GetAttachment(attachmentPath, skeletonDataAsset.GetSkeletonData(true)); } public struct Hierarchy { @@ -108,4 +159,40 @@ public class SpineAttachment : PropertyAttribute { } } } +} + +public class SpineBone : PropertyAttribute { + public string startsWith = ""; + public string dataField = ""; + + /// + /// Smart popup menu for Spine Bones + /// + /// Filters popup results to elements that begin with supplied string. + /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results. + /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives) + /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback. + /// + public SpineBone(string startsWith = "", string dataField = "") { + this.startsWith = startsWith; + this.dataField = dataField; + } + + public static Spine.Bone GetBone(string boneName, SkeletonRenderer renderer) { + if (renderer.skeleton == null) + return null; + + return renderer.skeleton.FindBone(boneName); + } + + public static Spine.BoneData GetBoneData(string boneName, SkeletonDataAsset skeletonDataAsset) { + var data = skeletonDataAsset.GetSkeletonData(true); + + return data.FindBone(boneName); + } +} + +public class SpineAtlasRegion : PropertyAttribute { + //TODO: Standardize with Skeleton attributes + //NOTE: For now, relies on locally scoped field named "atlasAsset" for source. } \ No newline at end of file