[unity] Reorganize folders for asmdef compatibility. Remove old files.

This commit is contained in:
pharan 2018-05-29 12:58:49 +08:00
parent b7da77b894
commit 065a10f4b3
390 changed files with 7523 additions and 7482 deletions

View File

@ -1,7 +1,7 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 0cb4e560224445d44affd8e57c1ae8b1 guid: 30918bcaadaaecc42bc215ff52f75b21
folderAsset: yes folderAsset: yes
timeCreated: 1495071888 timeCreated: 1488288531
licenseType: Free licenseType: Free
DefaultImporter: DefaultImporter:
userData: userData:

View File

@ -1,7 +1,7 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: fc5fac7eface2ba4fbb6146017e41192 guid: ad14d5a4cd7a0444286d315541ee0495
folderAsset: yes folderAsset: yes
timeCreated: 1500876410 timeCreated: 1527569319
licenseType: Free licenseType: Free
DefaultImporter: DefaultImporter:
userData: userData:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 83fbec88df35fe34bab43a5dde6788af
folderAsset: yes
timeCreated: 1527569675
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,51 +1,51 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes Software License v2.5 * Spine Runtimes Software License v2.5
* *
* Copyright (c) 2013-2016, Esoteric Software * Copyright (c) 2013-2016, Esoteric Software
* All rights reserved. * All rights reserved.
* *
* You are granted a perpetual, non-exclusive, non-sublicensable, and * You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine * non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal * Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of * use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate, * the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise * adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove, * create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent, * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the * or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source * Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms. * form must include this license and terms.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
using UnityEngine; using UnityEngine;
namespace Spine.Unity.Editor { namespace Spine.Unity.Editor {
public static class AssetDatabaseAvailabilityDetector { public static class AssetDatabaseAvailabilityDetector {
const string MARKER_RESOURCE_NAME = "SpineAssetDatabaseMarker"; const string MARKER_RESOURCE_NAME = "SpineAssetDatabaseMarker";
private static bool _isMarkerLoaded; private static bool _isMarkerLoaded;
public static bool IsAssetDatabaseAvailable (bool forceCheck = false) { public static bool IsAssetDatabaseAvailable (bool forceCheck = false) {
if (!forceCheck && _isMarkerLoaded) if (!forceCheck && _isMarkerLoaded)
return true; return true;
TextAsset markerTextAsset = Resources.Load<TextAsset>(MARKER_RESOURCE_NAME); TextAsset markerTextAsset = Resources.Load<TextAsset>(MARKER_RESOURCE_NAME);
_isMarkerLoaded = markerTextAsset != null; _isMarkerLoaded = markerTextAsset != null;
if (markerTextAsset != null) { if (markerTextAsset != null) {
Resources.UnloadAsset(markerTextAsset); Resources.UnloadAsset(markerTextAsset);
} }
return _isMarkerLoaded; return _isMarkerLoaded;
} }
} }
} }

View File

@ -1,208 +1,208 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes Software License v2.5 * Spine Runtimes Software License v2.5
* *
* Copyright (c) 2013-2016, Esoteric Software * Copyright (c) 2013-2016, Esoteric Software
* All rights reserved. * All rights reserved.
* *
* You are granted a perpetual, non-exclusive, non-sublicensable, and * You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine * non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal * Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of * use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate, * the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise * adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove, * create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent, * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the * or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source * Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms. * form must include this license and terms.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace Spine.Unity.Editor { namespace Spine.Unity.Editor {
using Editor = UnityEditor.Editor; using Editor = UnityEditor.Editor;
using Event = UnityEngine.Event; using Event = UnityEngine.Event;
[CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects] [CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects]
public class BoneFollowerInspector : Editor { public class BoneFollowerInspector : Editor {
SerializedProperty boneName, skeletonRenderer, followZPosition, followBoneRotation, followLocalScale, followSkeletonFlip; SerializedProperty boneName, skeletonRenderer, followZPosition, followBoneRotation, followLocalScale, followSkeletonFlip;
BoneFollower targetBoneFollower; BoneFollower targetBoneFollower;
bool needsReset; bool needsReset;
#region Context Menu Item #region Context Menu Item
[MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")] [MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) { static void AddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer; var skeletonRenderer = cmd.context as SkeletonRenderer;
var go = new GameObject("BoneFollower"); var go = new GameObject("BoneFollower");
var t = go.transform; var t = go.transform;
t.SetParent(skeletonRenderer.transform); t.SetParent(skeletonRenderer.transform);
t.localPosition = Vector3.zero; t.localPosition = Vector3.zero;
var f = go.AddComponent<BoneFollower>(); var f = go.AddComponent<BoneFollower>();
f.skeletonRenderer = skeletonRenderer; f.skeletonRenderer = skeletonRenderer;
EditorGUIUtility.PingObject(t); EditorGUIUtility.PingObject(t);
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollower"); Undo.RegisterCreatedObjectUndo(go, "Add BoneFollower");
} }
// Validate // Validate
[MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject", true)] [MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject", true)]
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) { static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
var skeletonRenderer = cmd.context as SkeletonRenderer; var skeletonRenderer = cmd.context as SkeletonRenderer;
return skeletonRenderer.valid; return skeletonRenderer.valid;
} }
#endregion #endregion
void OnEnable () { void OnEnable () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer"); skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
boneName = serializedObject.FindProperty("boneName"); boneName = serializedObject.FindProperty("boneName");
followBoneRotation = serializedObject.FindProperty("followBoneRotation"); followBoneRotation = serializedObject.FindProperty("followBoneRotation");
followZPosition = serializedObject.FindProperty("followZPosition"); followZPosition = serializedObject.FindProperty("followZPosition");
followLocalScale = serializedObject.FindProperty("followLocalScale"); followLocalScale = serializedObject.FindProperty("followLocalScale");
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip"); followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
targetBoneFollower = (BoneFollower)target; targetBoneFollower = (BoneFollower)target;
if (targetBoneFollower.SkeletonRenderer != null) if (targetBoneFollower.SkeletonRenderer != null)
targetBoneFollower.SkeletonRenderer.Initialize(false); targetBoneFollower.SkeletonRenderer.Initialize(false);
if (!targetBoneFollower.valid || needsReset) { if (!targetBoneFollower.valid || needsReset) {
targetBoneFollower.Initialize(); targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate(); targetBoneFollower.LateUpdate();
needsReset = false; needsReset = false;
SceneView.RepaintAll(); SceneView.RepaintAll();
} }
} }
public void OnSceneGUI () { public void OnSceneGUI () {
var tbf = target as BoneFollower; var tbf = target as BoneFollower;
var skeletonRendererComponent = tbf.skeletonRenderer; var skeletonRendererComponent = tbf.skeletonRenderer;
if (skeletonRendererComponent == null) return; if (skeletonRendererComponent == null) return;
var transform = skeletonRendererComponent.transform; var transform = skeletonRendererComponent.transform;
var skeleton = skeletonRendererComponent.skeleton; var skeleton = skeletonRendererComponent.skeleton;
if (string.IsNullOrEmpty(boneName.stringValue)) { if (string.IsNullOrEmpty(boneName.stringValue)) {
SpineHandles.DrawBones(transform, skeleton); SpineHandles.DrawBones(transform, skeleton);
SpineHandles.DrawBoneNames(transform, skeleton); SpineHandles.DrawBoneNames(transform, skeleton);
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox); Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
} else { } else {
var targetBone = tbf.bone; var targetBone = tbf.bone;
if (targetBone == null) return; if (targetBone == null) return;
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor); SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor);
Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle); Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle);
} }
} }
override public void OnInspectorGUI () { override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) { if (serializedObject.isEditingMultipleObjects) {
if (needsReset) { if (needsReset) {
needsReset = false; needsReset = false;
foreach (var o in targets) { foreach (var o in targets) {
var bf = (BoneFollower)o; var bf = (BoneFollower)o;
bf.Initialize(); bf.Initialize();
bf.LateUpdate(); bf.LateUpdate();
} }
SceneView.RepaintAll(); SceneView.RepaintAll();
} }
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
DrawDefaultInspector(); DrawDefaultInspector();
needsReset |= EditorGUI.EndChangeCheck(); needsReset |= EditorGUI.EndChangeCheck();
return; return;
} }
if (needsReset && Event.current.type == EventType.Layout) { if (needsReset && Event.current.type == EventType.Layout) {
targetBoneFollower.Initialize(); targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate(); targetBoneFollower.LateUpdate();
needsReset = false; needsReset = false;
SceneView.RepaintAll(); SceneView.RepaintAll();
} }
serializedObject.Update(); serializedObject.Update();
// Find Renderer // Find Renderer
if (skeletonRenderer.objectReferenceValue == null) { if (skeletonRenderer.objectReferenceValue == null) {
SkeletonRenderer parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonRenderer>(); SkeletonRenderer parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonRenderer>();
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) { if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
skeletonRenderer.objectReferenceValue = parentRenderer; skeletonRenderer.objectReferenceValue = parentRenderer;
Debug.Log("Inspector automatically assigned BoneFollower.SkeletonRenderer"); Debug.Log("Inspector automatically assigned BoneFollower.SkeletonRenderer");
} }
} }
EditorGUILayout.PropertyField(skeletonRenderer); EditorGUILayout.PropertyField(skeletonRenderer);
var skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer; var skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
if (skeletonRendererReference != null) { if (skeletonRendererReference != null) {
if (skeletonRendererReference.gameObject == targetBoneFollower.gameObject) { if (skeletonRendererReference.gameObject == targetBoneFollower.gameObject) {
skeletonRenderer.objectReferenceValue = null; skeletonRenderer.objectReferenceValue = null;
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok"); EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
} }
} }
if (!targetBoneFollower.valid) { if (!targetBoneFollower.valid) {
needsReset = true; needsReset = true;
} }
if (targetBoneFollower.valid) { if (targetBoneFollower.valid) {
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(boneName); EditorGUILayout.PropertyField(boneName);
needsReset |= EditorGUI.EndChangeCheck(); needsReset |= EditorGUI.EndChangeCheck();
EditorGUILayout.PropertyField(followBoneRotation); EditorGUILayout.PropertyField(followBoneRotation);
EditorGUILayout.PropertyField(followZPosition); EditorGUILayout.PropertyField(followZPosition);
EditorGUILayout.PropertyField(followLocalScale); EditorGUILayout.PropertyField(followLocalScale);
EditorGUILayout.PropertyField(followSkeletonFlip); EditorGUILayout.PropertyField(followSkeletonFlip);
BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower); BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
} else { } else {
var boneFollowerSkeletonRenderer = targetBoneFollower.skeletonRenderer; var boneFollowerSkeletonRenderer = targetBoneFollower.skeletonRenderer;
if (boneFollowerSkeletonRenderer == null) { if (boneFollowerSkeletonRenderer == null) {
EditorGUILayout.HelpBox("SkeletonRenderer is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonAnimator).", MessageType.Warning); EditorGUILayout.HelpBox("SkeletonRenderer is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonAnimator).", MessageType.Warning);
} else { } else {
boneFollowerSkeletonRenderer.Initialize(false); boneFollowerSkeletonRenderer.Initialize(false);
if (boneFollowerSkeletonRenderer.skeletonDataAsset == null) if (boneFollowerSkeletonRenderer.skeletonDataAsset == null)
EditorGUILayout.HelpBox("Assigned SkeletonRenderer does not have SkeletonData assigned to it.", MessageType.Warning); EditorGUILayout.HelpBox("Assigned SkeletonRenderer does not have SkeletonData assigned to it.", MessageType.Warning);
if (!boneFollowerSkeletonRenderer.valid) if (!boneFollowerSkeletonRenderer.valid)
EditorGUILayout.HelpBox("Assigned SkeletonRenderer is invalid. Check target SkeletonRenderer, its SkeletonDataAsset or the console for other errors.", MessageType.Warning); EditorGUILayout.HelpBox("Assigned SkeletonRenderer is invalid. Check target SkeletonRenderer, its SkeletonDataAsset or the console for other errors.", MessageType.Warning);
} }
} }
var current = Event.current; var current = Event.current;
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed"); bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
if (wasUndo) if (wasUndo)
targetBoneFollower.Initialize(); targetBoneFollower.Initialize();
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
internal static void RecommendRigidbodyButton (Component component) { internal static void RecommendRigidbodyButton (Component component) {
bool hasCollider2D = component.GetComponent<Collider2D>() != null || component.GetComponent<BoundingBoxFollower>() != null; bool hasCollider2D = component.GetComponent<Collider2D>() != null || component.GetComponent<BoundingBoxFollower>() != null;
bool hasCollider3D = !hasCollider2D && component.GetComponent<Collider>(); bool hasCollider3D = !hasCollider2D && component.GetComponent<Collider>();
bool missingRigidBody = (hasCollider2D && component.GetComponent<Rigidbody2D>() == null) || (hasCollider3D && component.GetComponent<Rigidbody>() == null); bool missingRigidBody = (hasCollider2D && component.GetComponent<Rigidbody2D>() == null) || (hasCollider3D && component.GetComponent<Rigidbody>() == null);
if (missingRigidBody) { if (missingRigidBody) {
using (new SpineInspectorUtility.BoxScope()) { using (new SpineInspectorUtility.BoxScope()) {
EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the parent Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning); EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the parent Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning);
var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody); var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody);
string rbLabel = string.Format("Add {0}", rbType.Name); string rbLabel = string.Format("Add {0}", rbType.Name);
var rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Physics body parent of the attached collider."); var rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Physics body parent of the attached collider.");
if (SpineInspectorUtility.CenteredButton(rbContent)) component.gameObject.AddComponent(rbType); if (SpineInspectorUtility.CenteredButton(rbContent)) component.gameObject.AddComponent(rbType);
} }
} }
} }
} }
} }

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 515 B

After

Width:  |  Height:  |  Size: 515 B

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 587 B

After

Width:  |  Height:  |  Size: 587 B

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 603 B

After

Width:  |  Height:  |  Size: 603 B

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 519 B

After

Width:  |  Height:  |  Size: 519 B

View File

Before

Width:  |  Height:  |  Size: 687 B

After

Width:  |  Height:  |  Size: 687 B

View File

Before

Width:  |  Height:  |  Size: 555 B

After

Width:  |  Height:  |  Size: 555 B

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 634 B

After

Width:  |  Height:  |  Size: 634 B

View File

Before

Width:  |  Height:  |  Size: 672 B

After

Width:  |  Height:  |  Size: 672 B

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 649 B

After

Width:  |  Height:  |  Size: 649 B

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 698 B

After

Width:  |  Height:  |  Size: 698 B

View File

@ -1,84 +1,84 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes Software License v2.5 * Spine Runtimes Software License v2.5
* *
* Copyright (c) 2013-2016, Esoteric Software * Copyright (c) 2013-2016, Esoteric Software
* All rights reserved. * All rights reserved.
* *
* You are granted a perpetual, non-exclusive, non-sublicensable, and * You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine * non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal * Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of * use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate, * the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise * adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove, * create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent, * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the * or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source * Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms. * form must include this license and terms.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
using System; using System;
using System.IO; using System.IO;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace Spine.Unity.Editor { namespace Spine.Unity.Editor {
public static class Menus { public static class Menus {
[MenuItem("Assets/Create/Spine/Atlas Asset")] [MenuItem("Assets/Create/Spine/Atlas Asset")]
static public void CreateAtlas () { static public void CreateAtlas () {
CreateAsset<AtlasAsset>("New Atlas"); CreateAsset<AtlasAsset>("New Atlas");
} }
[MenuItem("Assets/Create/Spine/SkeletonData Asset")] [MenuItem("Assets/Create/Spine/SkeletonData Asset")]
static public void CreateSkeletonData () { static public void CreateSkeletonData () {
CreateAsset<SkeletonDataAsset>("New SkeletonData"); CreateAsset<SkeletonDataAsset>("New SkeletonData");
} }
static void CreateAsset<T> (String name) where T : ScriptableObject { static void CreateAsset<T> (String name) where T : ScriptableObject {
var dir = "Assets/"; var dir = "Assets/";
var selected = Selection.activeObject; var selected = Selection.activeObject;
if (selected != null) { if (selected != null) {
var assetDir = AssetDatabase.GetAssetPath(selected.GetInstanceID()); var assetDir = AssetDatabase.GetAssetPath(selected.GetInstanceID());
if (assetDir.Length > 0 && Directory.Exists(assetDir)) if (assetDir.Length > 0 && Directory.Exists(assetDir))
dir = assetDir + "/"; dir = assetDir + "/";
} }
ScriptableObject asset = ScriptableObject.CreateInstance<T>(); ScriptableObject asset = ScriptableObject.CreateInstance<T>();
AssetDatabase.CreateAsset(asset, dir + name + ".asset"); AssetDatabase.CreateAsset(asset, dir + name + ".asset");
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
EditorUtility.FocusProjectWindow(); EditorUtility.FocusProjectWindow();
Selection.activeObject = asset; Selection.activeObject = asset;
} }
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)] [MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
static public void CreateSkeletonRendererGameObject () { static public void CreateSkeletonRendererGameObject () {
CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer"); CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
} }
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)] [MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
static public void CreateSkeletonAnimationGameObject () { static public void CreateSkeletonAnimationGameObject () {
CreateSpineGameObject<SkeletonAnimation>("New SkeletonAnimation"); CreateSpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
} }
static void CreateSpineGameObject<T> (string name) where T : MonoBehaviour { static void CreateSpineGameObject<T> (string name) where T : MonoBehaviour {
var parentGameObject = Selection.activeObject as GameObject; var parentGameObject = Selection.activeObject as GameObject;
var parentTransform = parentGameObject == null ? null : parentGameObject.transform; var parentTransform = parentGameObject == null ? null : parentGameObject.transform;
var gameObject = new GameObject(name, typeof(T)); var gameObject = new GameObject(name, typeof(T));
gameObject.transform.SetParent(parentTransform, false); gameObject.transform.SetParent(parentTransform, false);
EditorUtility.FocusProjectWindow(); EditorUtility.FocusProjectWindow();
Selection.activeObject = gameObject; Selection.activeObject = gameObject;
EditorGUIUtility.PingObject(Selection.activeObject); EditorGUIUtility.PingObject(Selection.activeObject);
} }
} }
} }

View File

@ -1,143 +1,143 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes Software License v2.5 * Spine Runtimes Software License v2.5
* *
* Copyright (c) 2013-2016, Esoteric Software * Copyright (c) 2013-2016, Esoteric Software
* All rights reserved. * All rights reserved.
* *
* You are granted a perpetual, non-exclusive, non-sublicensable, and * You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine * non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal * Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of * use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate, * the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise * adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove, * create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent, * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the * or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source * Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms. * form must include this license and terms.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using Spine; using Spine;
namespace Spine.Unity.Editor { namespace Spine.Unity.Editor {
[CustomEditor(typeof(SkeletonAnimation))] [CustomEditor(typeof(SkeletonAnimation))]
[CanEditMultipleObjects] [CanEditMultipleObjects]
public class SkeletonAnimationInspector : SkeletonRendererInspector { public class SkeletonAnimationInspector : SkeletonRendererInspector {
protected SerializedProperty animationName, loop, timeScale, autoReset; protected SerializedProperty animationName, loop, timeScale, autoReset;
protected bool wasAnimationNameChanged; protected bool wasAnimationNameChanged;
protected bool requireRepaint; protected bool requireRepaint;
readonly GUIContent LoopLabel = new GUIContent("Loop", "Whether or not .AnimationName should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected."); readonly GUIContent LoopLabel = new GUIContent("Loop", "Whether or not .AnimationName should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.");
readonly GUIContent TimeScaleLabel = new GUIContent("Time Scale", "The rate at which animations progress over time. 1 means normal speed. 0.5 means 50% speed."); readonly GUIContent TimeScaleLabel = new GUIContent("Time Scale", "The rate at which animations progress over time. 1 means normal speed. 0.5 means 50% speed.");
protected override void OnEnable () { protected override void OnEnable () {
base.OnEnable(); base.OnEnable();
animationName = serializedObject.FindProperty("_animationName"); animationName = serializedObject.FindProperty("_animationName");
loop = serializedObject.FindProperty("loop"); loop = serializedObject.FindProperty("loop");
timeScale = serializedObject.FindProperty("timeScale"); timeScale = serializedObject.FindProperty("timeScale");
} }
protected override void DrawInspectorGUI (bool multi) { protected override void DrawInspectorGUI (bool multi) {
base.DrawInspectorGUI(multi); base.DrawInspectorGUI(multi);
if (!TargetIsValid) return; if (!TargetIsValid) return;
bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject); bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject);
if (multi) { if (multi) {
foreach (var o in targets) foreach (var o in targets)
TrySetAnimation(o, multi); TrySetAnimation(o, multi);
EditorGUILayout.Space(); EditorGUILayout.Space();
if (!sameData) { if (!sameData) {
#if UNITY_5_3_OR_NEWER #if UNITY_5_3_OR_NEWER
EditorGUILayout.DelayedTextField(animationName); EditorGUILayout.DelayedTextField(animationName);
#else #else
animationName.stringValue = EditorGUILayout.TextField(animationName.displayName, animationName.stringValue); animationName.stringValue = EditorGUILayout.TextField(animationName.displayName, animationName.stringValue);
#endif #endif
} else { } else {
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(animationName); EditorGUILayout.PropertyField(animationName);
wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update. wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
} }
EditorGUILayout.PropertyField(loop); EditorGUILayout.PropertyField(loop);
EditorGUILayout.PropertyField(timeScale); EditorGUILayout.PropertyField(timeScale);
foreach (var o in targets) { foreach (var o in targets) {
var component = o as SkeletonAnimation; var component = o as SkeletonAnimation;
component.timeScale = Mathf.Max(component.timeScale, 0); component.timeScale = Mathf.Max(component.timeScale, 0);
} }
} else { } else {
TrySetAnimation(target, multi); TrySetAnimation(target, multi);
EditorGUILayout.Space(); EditorGUILayout.Space();
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(animationName); EditorGUILayout.PropertyField(animationName);
wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update. wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
EditorGUILayout.PropertyField(loop, LoopLabel); EditorGUILayout.PropertyField(loop, LoopLabel);
EditorGUILayout.PropertyField(timeScale, TimeScaleLabel); EditorGUILayout.PropertyField(timeScale, TimeScaleLabel);
var component = (SkeletonAnimation)target; var component = (SkeletonAnimation)target;
component.timeScale = Mathf.Max(component.timeScale, 0); component.timeScale = Mathf.Max(component.timeScale, 0);
EditorGUILayout.Space(); EditorGUILayout.Space();
} }
if (!isInspectingPrefab) { if (!isInspectingPrefab) {
if (requireRepaint) { if (requireRepaint) {
SceneView.RepaintAll(); SceneView.RepaintAll();
requireRepaint = false; requireRepaint = false;
} }
} }
} }
protected void TrySetAnimation (Object o, bool multi) { protected void TrySetAnimation (Object o, bool multi) {
var skeletonAnimation = o as SkeletonAnimation; var skeletonAnimation = o as SkeletonAnimation;
if (skeletonAnimation == null) return; if (skeletonAnimation == null) return;
if (!skeletonAnimation.valid) if (!skeletonAnimation.valid)
return; return;
if (!isInspectingPrefab) { if (!isInspectingPrefab) {
if (wasAnimationNameChanged) { if (wasAnimationNameChanged) {
if (!Application.isPlaying) { if (!Application.isPlaying) {
if (skeletonAnimation.state != null) skeletonAnimation.state.ClearTrack(0); if (skeletonAnimation.state != null) skeletonAnimation.state.ClearTrack(0);
skeletonAnimation.skeleton.SetToSetupPose(); skeletonAnimation.skeleton.SetToSetupPose();
} }
Spine.Animation animationToUse = skeletonAnimation.skeleton.Data.FindAnimation(animationName.stringValue); Spine.Animation animationToUse = skeletonAnimation.skeleton.Data.FindAnimation(animationName.stringValue);
if (!Application.isPlaying) { if (!Application.isPlaying) {
if (animationToUse != null) animationToUse.PoseSkeleton(skeletonAnimation.Skeleton, 0f); if (animationToUse != null) animationToUse.PoseSkeleton(skeletonAnimation.Skeleton, 0f);
skeletonAnimation.Update(0); skeletonAnimation.Update(0);
skeletonAnimation.LateUpdate(); skeletonAnimation.LateUpdate();
requireRepaint = true; requireRepaint = true;
} else { } else {
if (animationToUse != null) if (animationToUse != null)
skeletonAnimation.state.SetAnimation(0, animationToUse, loop.boolValue); skeletonAnimation.state.SetAnimation(0, animationToUse, loop.boolValue);
else else
skeletonAnimation.state.ClearTrack(0); skeletonAnimation.state.ClearTrack(0);
} }
wasAnimationNameChanged = false; wasAnimationNameChanged = false;
} }
// Reflect animationName serialized property in the inspector even if SetAnimation API was used. // Reflect animationName serialized property in the inspector even if SetAnimation API was used.
if (!multi && Application.isPlaying) { if (!multi && Application.isPlaying) {
TrackEntry current = skeletonAnimation.state.GetCurrent(0); TrackEntry current = skeletonAnimation.state.GetCurrent(0);
if (current != null) { if (current != null) {
if (skeletonAnimation.AnimationName != animationName.stringValue) if (skeletonAnimation.AnimationName != animationName.stringValue)
animationName.stringValue = current.Animation.Name; animationName.stringValue = current.Animation.Name;
} }
} }
} }
} }
} }
} }

View File

@ -1,398 +1,398 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes Software License v2.5 * Spine Runtimes Software License v2.5
* *
* Copyright (c) 2013-2016, Esoteric Software * Copyright (c) 2013-2016, Esoteric Software
* All rights reserved. * All rights reserved.
* *
* You are granted a perpetual, non-exclusive, non-sublicensable, and * You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine * non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal * Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of * use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate, * the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise * adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove, * create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent, * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the * or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source * Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms. * form must include this license and terms.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#define NO_PREFAB_MESH #define NO_PREFAB_MESH
using UnityEditor; using UnityEditor;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace Spine.Unity.Editor { namespace Spine.Unity.Editor {
using Event = UnityEngine.Event; using Event = UnityEngine.Event;
using Icons = SpineEditorUtilities.Icons; using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(SkeletonRenderer))] [CustomEditor(typeof(SkeletonRenderer))]
[CanEditMultipleObjects] [CanEditMultipleObjects]
public class SkeletonRendererInspector : UnityEditor.Editor { public class SkeletonRendererInspector : UnityEditor.Editor {
public static bool advancedFoldout; public static bool advancedFoldout;
protected SerializedProperty skeletonDataAsset, initialSkinName; protected SerializedProperty skeletonDataAsset, initialSkinName;
protected SerializedProperty initialFlipX, initialFlipY; protected SerializedProperty initialFlipX, initialFlipY;
protected SerializedProperty singleSubmesh, separatorSlotNames, clearStateOnDisable, immutableTriangles; protected SerializedProperty singleSubmesh, separatorSlotNames, clearStateOnDisable, immutableTriangles;
protected SerializedProperty normals, tangents, meshes, zSpacing, pmaVertexColors, tintBlack; // MeshGenerator settings protected SerializedProperty normals, tangents, meshes, zSpacing, pmaVertexColors, tintBlack; // MeshGenerator settings
protected SpineInspectorUtility.SerializedSortingProperties sortingProperties; protected SpineInspectorUtility.SerializedSortingProperties sortingProperties;
protected bool isInspectingPrefab; protected bool isInspectingPrefab;
protected GUIContent SkeletonDataAssetLabel, SkeletonUtilityButtonContent; protected GUIContent SkeletonDataAssetLabel, SkeletonUtilityButtonContent;
protected GUIContent PMAVertexColorsLabel, ClearStateOnDisableLabel, ZSpacingLabel, MeshesLabel, ImmubleTrianglesLabel, TintBlackLabel, SingleSubmeshLabel; protected GUIContent PMAVertexColorsLabel, ClearStateOnDisableLabel, ZSpacingLabel, MeshesLabel, ImmubleTrianglesLabel, TintBlackLabel, SingleSubmeshLabel;
protected GUIContent NormalsLabel, TangentsLabel; protected GUIContent NormalsLabel, TangentsLabel;
const string ReloadButtonLabel = "Reload"; const string ReloadButtonLabel = "Reload";
protected bool TargetIsValid { protected bool TargetIsValid {
get { get {
if (serializedObject.isEditingMultipleObjects) { if (serializedObject.isEditingMultipleObjects) {
foreach (var o in targets) { foreach (var o in targets) {
var component = (SkeletonRenderer)o; var component = (SkeletonRenderer)o;
if (!component.valid) if (!component.valid)
return false; return false;
} }
return true; return true;
} else { } else {
var component = (SkeletonRenderer)target; var component = (SkeletonRenderer)target;
return component.valid; return component.valid;
} }
} }
} }
protected virtual void OnEnable () { protected virtual void OnEnable () {
isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab); isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
SpineEditorUtilities.ConfirmInitialization(); SpineEditorUtilities.ConfirmInitialization();
// Labels // Labels
SkeletonDataAssetLabel = new GUIContent("SkeletonData Asset", Icons.spine); SkeletonDataAssetLabel = new GUIContent("SkeletonData Asset", Icons.spine);
SkeletonUtilityButtonContent = new GUIContent("Add Skeleton Utility", Icons.skeletonUtility); SkeletonUtilityButtonContent = new GUIContent("Add Skeleton Utility", Icons.skeletonUtility);
MeshesLabel = new GUIContent("Render MeshAttachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments"); MeshesLabel = new GUIContent("Render MeshAttachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments");
ImmubleTrianglesLabel = new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"); ImmubleTrianglesLabel = new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility");
PMAVertexColorsLabel = new GUIContent("PMA Vertex Colors", "Use this if you are using the default Spine/Skeleton shader or any premultiply-alpha shader."); PMAVertexColorsLabel = new GUIContent("PMA Vertex Colors", "Use this if you are using the default Spine/Skeleton shader or any premultiply-alpha shader.");
ClearStateOnDisableLabel = new GUIContent("Clear State On Disable", "Use this if you are pooling or enabling/disabling your Spine GameObject."); ClearStateOnDisableLabel = new GUIContent("Clear State On Disable", "Use this if you are pooling or enabling/disabling your Spine GameObject.");
ZSpacingLabel = new GUIContent("Z Spacing", "A value other than 0 adds a space between each rendered attachment to prevent Z Fighting when using shaders that read or write to the depth buffer. Large values may cause unwanted parallax and spaces depending on camera setup."); ZSpacingLabel = new GUIContent("Z Spacing", "A value other than 0 adds a space between each rendered attachment to prevent Z Fighting when using shaders that read or write to the depth buffer. Large values may cause unwanted parallax and spaces depending on camera setup.");
NormalsLabel = new GUIContent("Add Normals", "Use this if your shader requires vertex normals. A more efficient solution for 2D setups is to modify the shader to assume a single normal value for the whole mesh."); NormalsLabel = new GUIContent("Add Normals", "Use this if your shader requires vertex normals. A more efficient solution for 2D setups is to modify the shader to assume a single normal value for the whole mesh.");
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."); 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."); 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 determination by assuming you are only using one Material and need only one submesh. This is will disable render separation and custom slot materials."); SingleSubmeshLabel = new GUIContent("Use Single Submesh", "Simplifies submesh determination by assuming you are only using one Material and need only one submesh. This is will disable render separation and custom slot materials.");
var so = this.serializedObject; var so = this.serializedObject;
skeletonDataAsset = so.FindProperty("skeletonDataAsset"); skeletonDataAsset = so.FindProperty("skeletonDataAsset");
initialSkinName = so.FindProperty("initialSkinName"); initialSkinName = so.FindProperty("initialSkinName");
initialFlipX = so.FindProperty("initialFlipX"); initialFlipX = so.FindProperty("initialFlipX");
initialFlipY = so.FindProperty("initialFlipY"); initialFlipY = so.FindProperty("initialFlipY");
normals = so.FindProperty("addNormals"); normals = so.FindProperty("addNormals");
tangents = so.FindProperty("calculateTangents"); tangents = so.FindProperty("calculateTangents");
meshes = so.FindProperty("renderMeshes"); meshes = so.FindProperty("renderMeshes");
immutableTriangles = so.FindProperty("immutableTriangles"); immutableTriangles = so.FindProperty("immutableTriangles");
pmaVertexColors = so.FindProperty("pmaVertexColors"); pmaVertexColors = so.FindProperty("pmaVertexColors");
clearStateOnDisable = so.FindProperty("clearStateOnDisable"); clearStateOnDisable = so.FindProperty("clearStateOnDisable");
tintBlack = so.FindProperty("tintBlack"); tintBlack = so.FindProperty("tintBlack");
singleSubmesh = so.FindProperty("singleSubmesh"); singleSubmesh = so.FindProperty("singleSubmesh");
separatorSlotNames = so.FindProperty("separatorSlotNames"); separatorSlotNames = so.FindProperty("separatorSlotNames");
separatorSlotNames.isExpanded = true; separatorSlotNames.isExpanded = true;
zSpacing = so.FindProperty("zSpacing"); zSpacing = so.FindProperty("zSpacing");
SerializedObject rso = SpineInspectorUtility.GetRenderersSerializedObject(serializedObject); SerializedObject rso = SpineInspectorUtility.GetRenderersSerializedObject(serializedObject);
sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(rso); sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(rso);
} }
public static void ReapplySeparatorSlotNames (SkeletonRenderer skeletonRenderer) { public static void ReapplySeparatorSlotNames (SkeletonRenderer skeletonRenderer) {
if (!skeletonRenderer.valid) return; if (!skeletonRenderer.valid) return;
var separatorSlots = skeletonRenderer.separatorSlots; var separatorSlots = skeletonRenderer.separatorSlots;
var separatorSlotNames = skeletonRenderer.separatorSlotNames; var separatorSlotNames = skeletonRenderer.separatorSlotNames;
var skeleton = skeletonRenderer.skeleton; var skeleton = skeletonRenderer.skeleton;
separatorSlots.Clear(); separatorSlots.Clear();
for (int i = 0, n = separatorSlotNames.Length; i < n; i++) { for (int i = 0, n = separatorSlotNames.Length; i < n; i++) {
var slot = skeleton.FindSlot(separatorSlotNames[i]); var slot = skeleton.FindSlot(separatorSlotNames[i]);
if (slot != null) { if (slot != null) {
separatorSlots.Add(slot); separatorSlots.Add(slot);
} else { } else {
Debug.LogWarning(separatorSlotNames[i] + " is not a slot in " + skeletonRenderer.skeletonDataAsset.skeletonJSON.name); Debug.LogWarning(separatorSlotNames[i] + " is not a slot in " + skeletonRenderer.skeletonDataAsset.skeletonJSON.name);
} }
} }
} }
GUIContent[] skins; GUIContent[] skins;
ExposedList<Skin> loadedSkinList; ExposedList<Skin> loadedSkinList;
protected virtual void DrawInspectorGUI (bool multi) { protected virtual void DrawInspectorGUI (bool multi) {
bool valid = TargetIsValid; bool valid = TargetIsValid;
var reloadWidth = GUILayout.Width(GUI.skin.label.CalcSize(new GUIContent(ReloadButtonLabel)).x + 20); var reloadWidth = GUILayout.Width(GUI.skin.label.CalcSize(new GUIContent(ReloadButtonLabel)).x + 20);
var reloadButtonStyle = EditorStyles.miniButtonRight; var reloadButtonStyle = EditorStyles.miniButtonRight;
if (multi) { if (multi) {
using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) { using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) {
SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel); SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel);
if (GUILayout.Button(ReloadButtonLabel, reloadButtonStyle, reloadWidth)) { if (GUILayout.Button(ReloadButtonLabel, reloadButtonStyle, reloadWidth)) {
foreach (var c in targets) { foreach (var c in targets) {
var component = c as SkeletonRenderer; var component = c as SkeletonRenderer;
if (component.skeletonDataAsset != null) { if (component.skeletonDataAsset != null) {
foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets) { foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets) {
if (aa != null) if (aa != null)
aa.Clear(); aa.Clear();
} }
component.skeletonDataAsset.Clear(); component.skeletonDataAsset.Clear();
} }
component.Initialize(true); component.Initialize(true);
} }
} }
} }
foreach (var c in targets) { foreach (var c in targets) {
var component = c as SkeletonRenderer; var component = c as SkeletonRenderer;
if (!component.valid) { if (!component.valid) {
if (Event.current.type == EventType.Layout) { if (Event.current.type == EventType.Layout) {
component.Initialize(true); component.Initialize(true);
component.LateUpdate(); component.LateUpdate();
} }
if (!component.valid) if (!component.valid)
continue; continue;
} }
#if NO_PREFAB_MESH #if NO_PREFAB_MESH
if (isInspectingPrefab) { if (isInspectingPrefab) {
MeshFilter meshFilter = component.GetComponent<MeshFilter>(); MeshFilter meshFilter = component.GetComponent<MeshFilter>();
if (meshFilter != null && meshFilter.sharedMesh != null) if (meshFilter != null && meshFilter.sharedMesh != null)
meshFilter.sharedMesh = null; meshFilter.sharedMesh = null;
} }
#endif #endif
} }
if (valid) if (valid)
EditorGUILayout.PropertyField(initialSkinName); EditorGUILayout.PropertyField(initialSkinName);
} else { } else {
var component = (SkeletonRenderer)target; var component = (SkeletonRenderer)target;
if (!component.valid && Event.current.type == EventType.Layout) { if (!component.valid && Event.current.type == EventType.Layout) {
component.Initialize(true); component.Initialize(true);
component.LateUpdate(); component.LateUpdate();
} }
using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) { using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) {
SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel); SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel);
if (component.valid) { if (component.valid) {
if (GUILayout.Button(ReloadButtonLabel, reloadButtonStyle, reloadWidth)) { if (GUILayout.Button(ReloadButtonLabel, reloadButtonStyle, reloadWidth)) {
if (component.skeletonDataAsset != null) { if (component.skeletonDataAsset != null) {
foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets) { foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets) {
if (aa != null) if (aa != null)
aa.Clear(); aa.Clear();
} }
component.skeletonDataAsset.Clear(); component.skeletonDataAsset.Clear();
} }
component.Initialize(true); component.Initialize(true);
} }
} }
} }
if (component.skeletonDataAsset == null) { if (component.skeletonDataAsset == null) {
EditorGUILayout.HelpBox("Skeleton Data Asset required", MessageType.Warning); EditorGUILayout.HelpBox("Skeleton Data Asset required", MessageType.Warning);
return; return;
} }
#if NO_PREFAB_MESH #if NO_PREFAB_MESH
if (isInspectingPrefab) { if (isInspectingPrefab) {
MeshFilter meshFilter = component.GetComponent<MeshFilter>(); MeshFilter meshFilter = component.GetComponent<MeshFilter>();
if (meshFilter != null && meshFilter.sharedMesh != null) if (meshFilter != null && meshFilter.sharedMesh != null)
meshFilter.sharedMesh = null; meshFilter.sharedMesh = null;
} }
#endif #endif
// Initial skin name. // Initial skin name.
if (component.valid) { if (component.valid) {
var skeletonDataSkins = component.skeleton.Data.Skins; var skeletonDataSkins = component.skeleton.Data.Skins;
int skinCount = skeletonDataSkins.Count; int skinCount = skeletonDataSkins.Count;
if (loadedSkinList != skeletonDataSkins) { if (loadedSkinList != skeletonDataSkins) {
skins = new GUIContent[skinCount]; skins = new GUIContent[skinCount];
loadedSkinList = skeletonDataSkins; loadedSkinList = skeletonDataSkins;
for (int i = 0; i < skins.Length; i++) { for (int i = 0; i < skins.Length; i++) {
string skinNameString = skeletonDataSkins.Items[i].Name; string skinNameString = skeletonDataSkins.Items[i].Name;
skins[i] = new GUIContent(skinNameString, Icons.skin); skins[i] = new GUIContent(skinNameString, Icons.skin);
} }
} }
int skinIndex = 0; int skinIndex = 0;
for (int i = 0; i < skins.Length; i++) { for (int i = 0; i < skins.Length; i++) {
string skinNameString = skeletonDataSkins.Items[i].Name; string skinNameString = skeletonDataSkins.Items[i].Name;
if (skinNameString == initialSkinName.stringValue) if (skinNameString == initialSkinName.stringValue)
skinIndex = i; skinIndex = i;
} }
skinIndex = EditorGUILayout.Popup(SpineInspectorUtility.TempContent("Initial Skin"), skinIndex, skins); skinIndex = EditorGUILayout.Popup(SpineInspectorUtility.TempContent("Initial Skin"), skinIndex, skins);
if (skins.Length > 0) // Support attachmentless/skinless SkeletonData. if (skins.Length > 0) // Support attachmentless/skinless SkeletonData.
initialSkinName.stringValue = skins[skinIndex].text; initialSkinName.stringValue = skins[skinIndex].text;
} }
} }
EditorGUILayout.Space(); EditorGUILayout.Space();
// Sorting Layers // Sorting Layers
SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true); SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true);
if (!TargetIsValid) return; if (!TargetIsValid) return;
// More Render Options... // More Render Options...
using (new SpineInspectorUtility.BoxScope()) { using (new SpineInspectorUtility.BoxScope()) {
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5)); EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced"); advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
if (advancedFoldout) { if (advancedFoldout) {
EditorGUILayout.Space(); EditorGUILayout.Space();
if (GUILayout.Button("Debug", EditorStyles.miniButton, GUILayout.Width(65f))) if (GUILayout.Button("Debug", EditorStyles.miniButton, GUILayout.Width(65f)))
SkeletonDebugWindow.Init(); SkeletonDebugWindow.Init();
} else { } else {
EditorGUILayout.Space(); EditorGUILayout.Space();
} }
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
if (advancedFoldout) { if (advancedFoldout) {
using (new SpineInspectorUtility.IndentScope()) { using (new SpineInspectorUtility.IndentScope()) {
using (new EditorGUILayout.HorizontalScope()) { using (new EditorGUILayout.HorizontalScope()) {
initialFlipX.boolValue = EditorGUILayout.ToggleLeft(initialFlipX.displayName, initialFlipX.boolValue, GUILayout.Width(120f)); initialFlipX.boolValue = EditorGUILayout.ToggleLeft(initialFlipX.displayName, initialFlipX.boolValue, GUILayout.Width(120f));
initialFlipY.boolValue = EditorGUILayout.ToggleLeft(initialFlipY.displayName, initialFlipY.boolValue, GUILayout.Width(120f)); initialFlipY.boolValue = EditorGUILayout.ToggleLeft(initialFlipY.displayName, initialFlipY.boolValue, GUILayout.Width(120f));
EditorGUILayout.Space(); EditorGUILayout.Space();
} }
EditorGUILayout.Space(); EditorGUILayout.Space();
EditorGUILayout.LabelField("Renderer Settings", EditorStyles.boldLabel); EditorGUILayout.LabelField("Renderer Settings", EditorStyles.boldLabel);
using (new SpineInspectorUtility.LabelWidthScope()) { using (new SpineInspectorUtility.LabelWidthScope()) {
// Optimization options // Optimization options
if (singleSubmesh != null) EditorGUILayout.PropertyField(singleSubmesh, SingleSubmeshLabel); if (singleSubmesh != null) EditorGUILayout.PropertyField(singleSubmesh, SingleSubmeshLabel);
//if (meshes != null) EditorGUILayout.PropertyField(meshes, MeshesLabel); //if (meshes != null) EditorGUILayout.PropertyField(meshes, MeshesLabel);
if (immutableTriangles != null) EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel); if (immutableTriangles != null) EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel);
EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel); EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel);
EditorGUILayout.Space(); EditorGUILayout.Space();
} }
SeparatorsField(separatorSlotNames); SeparatorsField(separatorSlotNames);
EditorGUILayout.Space(); EditorGUILayout.Space();
// Render options // Render options
const float MinZSpacing = -0.1f; const float MinZSpacing = -0.1f;
const float MaxZSpacing = 0f; const float MaxZSpacing = 0f;
EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing, ZSpacingLabel); EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing, ZSpacingLabel);
EditorGUILayout.Space(); EditorGUILayout.Space();
using (new SpineInspectorUtility.LabelWidthScope()) { using (new SpineInspectorUtility.LabelWidthScope()) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon<MeshFilter>()), EditorStyles.boldLabel); EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon<MeshFilter>()), EditorStyles.boldLabel);
if (pmaVertexColors != null) EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel); if (pmaVertexColors != null) EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel);
EditorGUILayout.PropertyField(tintBlack, TintBlackLabel); EditorGUILayout.PropertyField(tintBlack, TintBlackLabel);
// Optional fields. May be disabled in SkeletonRenderer. // Optional fields. May be disabled in SkeletonRenderer.
if (normals != null) EditorGUILayout.PropertyField(normals, NormalsLabel); if (normals != null) EditorGUILayout.PropertyField(normals, NormalsLabel);
if (tangents != null) EditorGUILayout.PropertyField(tangents, TangentsLabel); if (tangents != null) EditorGUILayout.PropertyField(tangents, TangentsLabel);
} }
EditorGUILayout.Space(); EditorGUILayout.Space();
if (TargetIsValid && !isInspectingPrefab) { if (TargetIsValid && !isInspectingPrefab) {
if (multi) { if (multi) {
// Support multi-edit SkeletonUtility button. // Support multi-edit SkeletonUtility button.
// EditorGUILayout.Space(); // EditorGUILayout.Space();
// bool addSkeletonUtility = GUILayout.Button(buttonContent, GUILayout.Height(30)); // bool addSkeletonUtility = GUILayout.Button(buttonContent, GUILayout.Height(30));
// foreach (var t in targets) { // foreach (var t in targets) {
// var component = t as Component; // var component = t as Component;
// if (addSkeletonUtility && component.GetComponent<SkeletonUtility>() == null) // if (addSkeletonUtility && component.GetComponent<SkeletonUtility>() == null)
// component.gameObject.AddComponent<SkeletonUtility>(); // component.gameObject.AddComponent<SkeletonUtility>();
// } // }
} else { } else {
var component = (Component)target; var component = (Component)target;
if (component.GetComponent<SkeletonUtility>() == null) { if (component.GetComponent<SkeletonUtility>() == null) {
if (SpineInspectorUtility.CenteredButton(SkeletonUtilityButtonContent, 21, true, 200f)) if (SpineInspectorUtility.CenteredButton(SkeletonUtilityButtonContent, 21, true, 200f))
component.gameObject.AddComponent<SkeletonUtility>(); component.gameObject.AddComponent<SkeletonUtility>();
} }
} }
} }
EditorGUILayout.Space(); EditorGUILayout.Space();
} }
} }
if (EditorGUI.EndChangeCheck()) if (EditorGUI.EndChangeCheck())
SceneView.RepaintAll(); SceneView.RepaintAll();
} }
} }
public static void SeparatorsField (SerializedProperty separatorSlotNames) { public static void SeparatorsField (SerializedProperty separatorSlotNames) {
bool multi = separatorSlotNames.serializedObject.isEditingMultipleObjects; bool multi = separatorSlotNames.serializedObject.isEditingMultipleObjects;
bool hasTerminalSlot = false; bool hasTerminalSlot = false;
if (!multi) { if (!multi) {
var sr = separatorSlotNames.serializedObject.targetObject as ISkeletonComponent; var sr = separatorSlotNames.serializedObject.targetObject as ISkeletonComponent;
var skeleton = sr.Skeleton; var skeleton = sr.Skeleton;
int lastSlot = skeleton.Slots.Count - 1; int lastSlot = skeleton.Slots.Count - 1;
if (skeleton != null) { if (skeleton != null) {
for (int i = 0, n = separatorSlotNames.arraySize; i < n; i++) { for (int i = 0, n = separatorSlotNames.arraySize; i < n; i++) {
int index = skeleton.FindSlotIndex(separatorSlotNames.GetArrayElementAtIndex(i).stringValue); int index = skeleton.FindSlotIndex(separatorSlotNames.GetArrayElementAtIndex(i).stringValue);
if (index == 0 || index == lastSlot) { if (index == 0 || index == lastSlot) {
hasTerminalSlot = true; hasTerminalSlot = true;
break; break;
} }
} }
} }
} }
string terminalSlotWarning = hasTerminalSlot ? " (!)" : ""; string terminalSlotWarning = hasTerminalSlot ? " (!)" : "";
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
const string SeparatorsDescription = "Stored names of slots where the Skeleton's render will be split into different batches. This is used by separate components that split the render into different MeshRenderers or GameObjects."; const string SeparatorsDescription = "Stored names of slots where the Skeleton's render will be split into different batches. This is used by separate components that split the render into different MeshRenderers or GameObjects.";
if (separatorSlotNames.isExpanded) { if (separatorSlotNames.isExpanded) {
EditorGUILayout.PropertyField(separatorSlotNames, SpineInspectorUtility.TempContent(separatorSlotNames.displayName + terminalSlotWarning, Icons.slotRoot, SeparatorsDescription), true); EditorGUILayout.PropertyField(separatorSlotNames, SpineInspectorUtility.TempContent(separatorSlotNames.displayName + terminalSlotWarning, Icons.slotRoot, SeparatorsDescription), true);
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
if (GUILayout.Button("+", GUILayout.MaxWidth(28f), GUILayout.MaxHeight(15f))) { if (GUILayout.Button("+", GUILayout.MaxWidth(28f), GUILayout.MaxHeight(15f))) {
separatorSlotNames.arraySize++; separatorSlotNames.arraySize++;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
EditorGUILayout.Space(); EditorGUILayout.Space();
} else } else
EditorGUILayout.PropertyField(separatorSlotNames, new GUIContent(separatorSlotNames.displayName + string.Format("{0} [{1}]", terminalSlotWarning, separatorSlotNames.arraySize), SeparatorsDescription), true); EditorGUILayout.PropertyField(separatorSlotNames, new GUIContent(separatorSlotNames.displayName + string.Format("{0} [{1}]", terminalSlotWarning, separatorSlotNames.arraySize), SeparatorsDescription), true);
} }
} }
public void OnSceneGUI () { public void OnSceneGUI () {
var skeletonRenderer = (SkeletonRenderer)target; var skeletonRenderer = (SkeletonRenderer)target;
var skeleton = skeletonRenderer.skeleton; var skeleton = skeletonRenderer.skeleton;
var transform = skeletonRenderer.transform; var transform = skeletonRenderer.transform;
if (skeleton == null) return; if (skeleton == null) return;
SpineHandles.DrawBones(transform, skeleton); SpineHandles.DrawBones(transform, skeleton);
} }
override public void OnInspectorGUI () { override public void OnInspectorGUI () {
//serializedObject.Update(); //serializedObject.Update();
bool multi = serializedObject.isEditingMultipleObjects; bool multi = serializedObject.isEditingMultipleObjects;
DrawInspectorGUI(multi); DrawInspectorGUI(multi);
if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current)) { if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current)) {
if (!Application.isPlaying) { if (!Application.isPlaying) {
if (multi) if (multi)
foreach (var o in targets) foreach (var o in targets)
((SkeletonRenderer)o).Initialize(true); ((SkeletonRenderer)o).Initialize(true);
else else
((SkeletonRenderer)target).Initialize(true); ((SkeletonRenderer)target).Initialize(true);
} }
} }
} }
} }
} }

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