123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- #if ENABLE_ANIMATION_COLLECTION && ENABLE_ANIMATION_BURST
- #define ENABLE_ANIMATION_PERFORMANCE
- #endif
- using UnityEngine;
- using UnityEditorInternal;
- using UnityEngine.U2D.Animation;
- using UnityEditor.IMGUI.Controls;
- using UnityEngine.U2D;
- using UnityEngine.U2D.Common;
- namespace UnityEditor.U2D.Animation
- {
- [CustomEditor(typeof(SpriteSkin))]
- [CanEditMultipleObjects]
- class SpriteSkinEditor : Editor
- {
- private static class Contents
- {
- public static readonly GUIContent listHeaderLabel = new GUIContent("Bones", "GameObject Transform to represent the Bones defined by the Sprite that is currently used for deformation.");
- public static readonly GUIContent rootBoneLabel = new GUIContent("Root Bone", "GameObject Transform to represent the Root Bone.");
- public static readonly string spriteNotFound = L10n.Tr("Sprite not found in SpriteRenderer");
- public static readonly string spriteHasNoSkinningInformation = L10n.Tr("Sprite has no Bind Poses");
- public static readonly string spriteHasNoWeights = L10n.Tr("Sprite has no weights");
- public static readonly string rootTransformNotFound = L10n.Tr("Root Bone not set");
- public static readonly string rootTransformNotFoundInArray = L10n.Tr("Bone list doesn't contain a reference to the Root Bone");
- public static readonly string invalidTransformArray = L10n.Tr("Bone list is invalid");
- public static readonly string transformArrayContainsNull = L10n.Tr("Bone list contains unassigned references");
- public static readonly string invalidTransformArrayLength = L10n.Tr("The number of Sprite's Bind Poses and the number of Transforms should match");
- public static readonly GUIContent useManager = new GUIContent("Enable batching", "When enabled, SpriteSkin deformation will be done in batch to improve performance.");
- public static readonly GUIContent alwaysUpdate = new GUIContent("Always Update", "Executes deformation of SpriteSkin even when the associated SpriteRenderer has been culled and is not visible.");
- public static readonly string experimental = L10n.Tr("Experimental");
- }
- private static Color s_BoundingBoxHandleColor = new Color(255, 255, 255, 150) / 255;
- private SerializedProperty m_RootBoneProperty;
- private SerializedProperty m_BoneTransformsProperty;
- private SerializedProperty m_AlwaysUpdateProperty;
- private SpriteSkin m_SpriteSkin;
- private ReorderableList m_ReorderableList;
- private Sprite m_CurrentSprite;
- private BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle();
- private bool m_NeedsRebind = false;
- #if ENABLE_ANIMATION_PERFORMANCE
- private SerializedProperty m_UseBatching;
- private bool m_ExperimentalFold;
- #endif
- private bool m_BoneFold = true;
- private void OnEnable()
- {
- m_SpriteSkin = (SpriteSkin)target;
- m_SpriteSkin.OnEditorEnable();
- m_RootBoneProperty = serializedObject.FindProperty("m_RootBone");
- #if ENABLE_ANIMATION_PERFORMANCE
- m_UseBatching = serializedObject.FindProperty("m_UseBatching");
- #endif
- m_BoneTransformsProperty = serializedObject.FindProperty("m_BoneTransforms");
- m_AlwaysUpdateProperty = serializedObject.FindProperty("m_AlwaysUpdate");
- m_CurrentSprite = m_SpriteSkin.spriteRenderer.sprite;
- m_BoundsHandle.axes = BoxBoundsHandle.Axes.X | BoxBoundsHandle.Axes.Y;
- m_BoundsHandle.SetColor(s_BoundingBoxHandleColor);
- SetupReorderableList();
- Undo.undoRedoPerformed += UndoRedoPerformed;
- }
- private void OnDestroy()
- {
- Undo.undoRedoPerformed -= UndoRedoPerformed;
- }
- private void UndoRedoPerformed()
- {
- m_CurrentSprite = m_SpriteSkin.spriteRenderer.sprite;
- }
- private void SetupReorderableList()
- {
- m_ReorderableList = new ReorderableList(serializedObject, m_BoneTransformsProperty, false, true, false, false);
- m_ReorderableList.headerHeight = 1.0f;
- m_ReorderableList.elementHeightCallback = (int index) =>
- {
- return EditorGUIUtility.singleLineHeight + 6;
- };
- m_ReorderableList.drawElementCallback = (Rect rect, int index, bool isactive, bool isfocused) =>
- {
- var content = GUIContent.none;
- if (m_CurrentSprite != null)
- {
- var bones = m_CurrentSprite.GetBones();
- if (index < bones.Length)
- content = new GUIContent(bones[index].name);
- }
- rect.y += 2f;
- rect.height = EditorGUIUtility.singleLineHeight;
- SerializedProperty element = m_BoneTransformsProperty.GetArrayElementAtIndex(index);
- EditorGUI.PropertyField(rect, element, content);
- };
- }
- private void InitializeBoneTransformArray()
- {
- if (m_CurrentSprite)
- {
- var elementCount = m_BoneTransformsProperty.arraySize;
- var bindPoses = m_CurrentSprite.GetBindPoses();
- if (elementCount != bindPoses.Length)
- {
- m_BoneTransformsProperty.arraySize = bindPoses.Length;
- for (int i = elementCount; i < m_BoneTransformsProperty.arraySize; ++i)
- m_BoneTransformsProperty.GetArrayElementAtIndex(i).objectReferenceValue = null;
- m_NeedsRebind = true;
- }
- }
- }
- public override void OnInspectorGUI()
- {
- serializedObject.Update();
- EditorGUILayout.PropertyField(m_AlwaysUpdateProperty, Contents.alwaysUpdate);
- var sprite = m_SpriteSkin.spriteRenderer.sprite;
- var spriteChanged = m_CurrentSprite != sprite;
- if (m_ReorderableList == null || spriteChanged)
- {
- m_CurrentSprite = sprite;
- InitializeBoneTransformArray();
- SetupReorderableList();
- }
- EditorGUI.BeginChangeCheck();
- EditorGUILayout.PropertyField(m_RootBoneProperty, Contents.rootBoneLabel);
- if (EditorGUI.EndChangeCheck())
- {
- m_NeedsRebind = true;
- }
- m_BoneFold = EditorGUILayout.Foldout(m_BoneFold, Contents.listHeaderLabel, true);
- if (m_BoneFold)
- {
- EditorGUILayout.Space();
- if (!serializedObject.isEditingMultipleObjects)
- {
- EditorGUI.BeginDisabledGroup(m_SpriteSkin.rootBone == null);
- m_ReorderableList.DoLayoutList();
- EditorGUI.EndDisabledGroup();
- }
- }
- EditorGUILayout.BeginHorizontal();
- GUILayout.FlexibleSpace();
- EditorGUI.BeginDisabledGroup(!EnableCreateBones());
- DoGenerateBonesButton();
- EditorGUI.EndDisabledGroup();
- EditorGUI.BeginDisabledGroup(!EnableSetBindPose());
- DoResetBindPoseButton();
- EditorGUI.EndDisabledGroup();
- GUILayout.FlexibleSpace();
- EditorGUILayout.EndHorizontal();
- #if ENABLE_ANIMATION_PERFORMANCE
- m_ExperimentalFold = EditorGUILayout.Foldout(m_ExperimentalFold, Contents.experimental, true);
- if (m_ExperimentalFold)
- {
- EditorGUI.indentLevel++;
- EditorGUI.BeginChangeCheck();
- EditorGUILayout.PropertyField(m_UseBatching, Contents.useManager);
- if (EditorGUI.EndChangeCheck())
- {
- foreach (var obj in targets)
- {
- ((SpriteSkin)obj).UseBatching(m_UseBatching.boolValue);
- }
- }
- EditorGUI.indentLevel--;
- }
- #endif
- serializedObject.ApplyModifiedProperties();
- if (m_NeedsRebind)
- Rebind();
- if (spriteChanged && !m_SpriteSkin.ignoreNextSpriteChange)
- {
- ResetBounds(Undo.GetCurrentGroupName());
- m_SpriteSkin.ignoreNextSpriteChange = false;
- }
- DoValidationWarnings();
- }
- private void Rebind()
- {
- foreach (var t in targets)
- {
- var spriteSkin = t as SpriteSkin;
- if(spriteSkin.spriteRenderer.sprite == null || spriteSkin.rootBone == null)
- continue;
- spriteSkin.Rebind();
- ResetBoundsIfNeeded(spriteSkin);
- }
- m_NeedsRebind = false;
- }
- private void ResetBounds(string undoName = "Reset Bounds")
- {
- foreach (var t in targets)
- {
- var spriteSkin = t as SpriteSkin;
- if (!spriteSkin.isValid)
- continue;
- Undo.RegisterCompleteObjectUndo(spriteSkin, undoName);
- spriteSkin.CalculateBounds();
- EditorUtility.SetDirty(spriteSkin);
- }
- }
- private void ResetBoundsIfNeeded(SpriteSkin spriteSkin)
- {
- if (spriteSkin.isValid && spriteSkin.bounds == new Bounds())
- spriteSkin.CalculateBounds();
- }
- private bool EnableCreateBones()
- {
- foreach (var t in targets)
- {
- var spriteSkin = t as SpriteSkin;
- var sprite = spriteSkin.spriteRenderer.sprite;
- if (sprite != null && spriteSkin.rootBone == null)
- return true;
- }
- return false;
- }
- private bool EnableSetBindPose()
- {
- return IsAnyTargetValid();
- }
- private bool IsAnyTargetValid()
- {
- foreach (var t in targets)
- {
- var spriteSkin = t as SpriteSkin;
- if (spriteSkin.isValid)
- return true;
- }
- return false;
- }
- private void DoGenerateBonesButton()
- {
- if (GUILayout.Button("Create Bones", GUILayout.MaxWidth(125f)))
- {
- foreach (var t in targets)
- {
- var spriteSkin = t as SpriteSkin;
- var sprite = spriteSkin.spriteRenderer.sprite;
- if (sprite == null || spriteSkin.rootBone != null)
- continue;
- Undo.RegisterCompleteObjectUndo(spriteSkin, "Create Bones");
- spriteSkin.CreateBoneHierarchy();
- foreach (var transform in spriteSkin.boneTransforms)
- Undo.RegisterCreatedObjectUndo(transform.gameObject, "Create Bones");
- ResetBoundsIfNeeded(spriteSkin);
- EditorUtility.SetDirty(spriteSkin);
- }
- BoneGizmo.instance.boneGizmoController.OnSelectionChanged();
- }
- }
- private void DoResetBindPoseButton()
- {
- if (GUILayout.Button("Reset Bind Pose", GUILayout.MaxWidth(125f)))
- {
- foreach (var t in targets)
- {
- var spriteSkin = t as SpriteSkin;
- if (!spriteSkin.isValid)
- continue;
- Undo.RecordObjects(spriteSkin.boneTransforms, "Reset Bind Pose");
- spriteSkin.ResetBindPose();
- }
- }
- }
- private void DoValidationWarnings()
- {
- EditorGUILayout.Space();
- bool preAppendObjectName = targets.Length > 1;
- foreach (var t in targets)
- {
- var spriteSkin = t as SpriteSkin;
- var validationResult = spriteSkin.Validate();
- if (validationResult == SpriteSkinValidationResult.Ready)
- continue;
- var text = "";
- switch (validationResult)
- {
- case SpriteSkinValidationResult.SpriteNotFound:
- text = Contents.spriteNotFound;
- break;
- case SpriteSkinValidationResult.SpriteHasNoSkinningInformation:
- text = Contents.spriteHasNoSkinningInformation;
- break;
- case SpriteSkinValidationResult.SpriteHasNoWeights:
- text = Contents.spriteHasNoWeights;
- break;
- case SpriteSkinValidationResult.RootTransformNotFound:
- text = Contents.rootTransformNotFound;
- break;
- case SpriteSkinValidationResult.RootNotFoundInTransformArray:
- text = Contents.rootTransformNotFoundInArray;
- break;
- case SpriteSkinValidationResult.InvalidTransformArray:
- text = Contents.invalidTransformArray;
- break;
- case SpriteSkinValidationResult.InvalidTransformArrayLength:
- text = Contents.invalidTransformArrayLength;
- break;
- case SpriteSkinValidationResult.TransformArrayContainsNull:
- text = Contents.transformArrayContainsNull;
- break;
- }
- if (preAppendObjectName)
- text = spriteSkin.name + ": " + text;
- EditorGUILayout.HelpBox(text, MessageType.Warning);
- }
- }
- }
- }
|