mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
Initial commit
This commit is contained in:
commit
3c7cc0c973
8391 changed files with 704313 additions and 0 deletions
|
@ -0,0 +1,470 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.U2D;
|
||||
using UnityEngine.U2D.Animation;
|
||||
using UnityEngine.U2D.Common;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
//Make sure Bone Gizmo registers callbacks before anyone else
|
||||
[InitializeOnLoad]
|
||||
internal class BoneGizmoInitializer
|
||||
{
|
||||
static BoneGizmoInitializer()
|
||||
{
|
||||
BoneGizmo.instance.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
internal class BoneGizmo : ScriptableSingleton<BoneGizmo>
|
||||
{
|
||||
private BoneGizmoController m_BoneGizmoController;
|
||||
|
||||
internal BoneGizmoController boneGizmoController { get { return m_BoneGizmoController; } }
|
||||
|
||||
internal void Initialize()
|
||||
{
|
||||
m_BoneGizmoController = new BoneGizmoController(new SkeletonView(new GUIWrapper()), new UnityEngineUndo(), new BoneGizmoToggle());
|
||||
RegisterCallbacks();
|
||||
}
|
||||
|
||||
internal void ClearSpriteBoneCache()
|
||||
{
|
||||
boneGizmoController.ClearSpriteBoneCache();
|
||||
}
|
||||
|
||||
private void RegisterCallbacks()
|
||||
{
|
||||
Selection.selectionChanged += OnSelectionChanged;
|
||||
SceneView.duringSceneGui += OnSceneGUI;
|
||||
AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload;
|
||||
EditorApplication.playModeStateChanged += PlayModeStateChanged;
|
||||
}
|
||||
|
||||
private void OnSceneGUI(SceneView sceneView)
|
||||
{
|
||||
boneGizmoController.OnGUI();
|
||||
}
|
||||
|
||||
private void OnSelectionChanged()
|
||||
{
|
||||
boneGizmoController.OnSelectionChanged();
|
||||
}
|
||||
|
||||
private void OnAfterAssemblyReload()
|
||||
{
|
||||
boneGizmoController.OnSelectionChanged();
|
||||
}
|
||||
|
||||
private void PlayModeStateChanged(PlayModeStateChange stateChange)
|
||||
{
|
||||
if (stateChange == PlayModeStateChange.EnteredPlayMode ||
|
||||
stateChange == PlayModeStateChange.EnteredEditMode)
|
||||
boneGizmoController.OnSelectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
internal class BoneGizmoController
|
||||
{
|
||||
private Dictionary<Sprite, UnityEngine.U2D.SpriteBone[]> m_SpriteBones = new Dictionary<Sprite, UnityEngine.U2D.SpriteBone[]>();
|
||||
private Dictionary<Transform, Vector2> m_BoneData = new Dictionary<Transform, Vector2>();
|
||||
private HashSet<SpriteSkin> m_SkinComponents = new HashSet<SpriteSkin>();
|
||||
private HashSet<Transform> m_CachedBones = new HashSet<Transform>();
|
||||
private HashSet<Transform> m_SelectionRoots = new HashSet<Transform>();
|
||||
private ISkeletonView view;
|
||||
private IUndo m_Undo;
|
||||
private Tool m_PreviousTool = Tool.None;
|
||||
private IBoneGizmoToggle m_BoneGizmoToggle;
|
||||
|
||||
internal IBoneGizmoToggle boneGizmoToggle { get { return m_BoneGizmoToggle; } set { m_BoneGizmoToggle = value; } }
|
||||
|
||||
public Transform hoveredBone
|
||||
{
|
||||
get { return GetBone(view.hoveredBoneID); }
|
||||
}
|
||||
public Transform hoveredTail
|
||||
{
|
||||
get { return GetBone(view.hoveredTailID); }
|
||||
}
|
||||
public Transform hoveredBody
|
||||
{
|
||||
get { return GetBone(view.hoveredBodyID); }
|
||||
}
|
||||
public Transform hoveredJoint
|
||||
{
|
||||
get { return GetBone(view.hoveredJointID); }
|
||||
}
|
||||
public Transform hotBone
|
||||
{
|
||||
get { return GetBone(view.hotBoneID); }
|
||||
}
|
||||
|
||||
private Transform GetBone(int instanceID)
|
||||
{
|
||||
return EditorUtility.InstanceIDToObject(instanceID) as Transform;
|
||||
}
|
||||
|
||||
public BoneGizmoController(ISkeletonView view, IUndo undo, IBoneGizmoToggle toggle)
|
||||
{
|
||||
this.view = view;
|
||||
view.mode = SkeletonMode.EditPose;
|
||||
view.InvalidID = 0;
|
||||
m_Undo = undo;
|
||||
m_BoneGizmoToggle = toggle;
|
||||
}
|
||||
|
||||
internal void OnSelectionChanged()
|
||||
{
|
||||
m_SelectionRoots.Clear();
|
||||
|
||||
foreach (var selectedTransform in Selection.transforms)
|
||||
{
|
||||
var prefabRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(selectedTransform.gameObject);
|
||||
var animator = default(Animator);
|
||||
|
||||
if (prefabRoot != null)
|
||||
m_SelectionRoots.Add(prefabRoot.transform);
|
||||
else if ((animator = selectedTransform.GetComponentInParent<Animator>()) != null)
|
||||
m_SelectionRoots.Add(animator.transform);
|
||||
else
|
||||
m_SelectionRoots.Add(selectedTransform.root);
|
||||
}
|
||||
|
||||
if (m_PreviousTool == Tool.None && Selection.activeTransform != null && m_BoneData.ContainsKey(Selection.activeTransform))
|
||||
{
|
||||
m_PreviousTool = UnityEditor.Tools.current;
|
||||
UnityEditor.Tools.current = Tool.None;
|
||||
}
|
||||
|
||||
if (m_PreviousTool != Tool.None && (Selection.activeTransform == null || !m_BoneData.ContainsKey(Selection.activeTransform)))
|
||||
{
|
||||
if (UnityEditor.Tools.current == Tool.None)
|
||||
UnityEditor.Tools.current = m_PreviousTool;
|
||||
|
||||
m_PreviousTool = Tool.None;
|
||||
}
|
||||
|
||||
FindSkinComponents();
|
||||
}
|
||||
|
||||
internal void OnGUI()
|
||||
{
|
||||
m_BoneGizmoToggle.OnGUI();
|
||||
|
||||
if (!m_BoneGizmoToggle.enableGizmos)
|
||||
return;
|
||||
|
||||
PrepareBones();
|
||||
DoBoneGUI();
|
||||
}
|
||||
|
||||
internal void FindSkinComponents()
|
||||
{
|
||||
m_SkinComponents.Clear();
|
||||
|
||||
foreach (var root in m_SelectionRoots)
|
||||
{
|
||||
var components = root.GetComponentsInChildren<SpriteSkin>(false);
|
||||
|
||||
foreach (var component in components)
|
||||
m_SkinComponents.Add(component);
|
||||
}
|
||||
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
internal void ClearSpriteBoneCache()
|
||||
{
|
||||
m_SpriteBones.Clear();
|
||||
}
|
||||
|
||||
private void PrepareBones()
|
||||
{
|
||||
if (!view.CanLayout())
|
||||
return;
|
||||
|
||||
if (view.IsActionHot(SkeletonAction.None))
|
||||
m_CachedBones.Clear();
|
||||
|
||||
m_BoneData.Clear();
|
||||
|
||||
foreach (var skinComponent in m_SkinComponents)
|
||||
{
|
||||
if (skinComponent == null)
|
||||
continue;
|
||||
|
||||
PrepareBones(skinComponent);
|
||||
}
|
||||
}
|
||||
|
||||
private UnityEngine.U2D.SpriteBone[] GetSpriteBones(SpriteSkin spriteSkin)
|
||||
{
|
||||
Debug.Assert(spriteSkin.isValid);
|
||||
|
||||
var sprite = spriteSkin.spriteRenderer.sprite;
|
||||
UnityEngine.U2D.SpriteBone[] spriteBones;
|
||||
if (!m_SpriteBones.TryGetValue(sprite, out spriteBones))
|
||||
{
|
||||
spriteBones = sprite.GetBones();
|
||||
m_SpriteBones[sprite] = sprite.GetBones();
|
||||
}
|
||||
|
||||
return spriteBones;
|
||||
}
|
||||
|
||||
private void PrepareBones(SpriteSkin spriteSkin)
|
||||
{
|
||||
Debug.Assert(spriteSkin != null);
|
||||
Debug.Assert(view.CanLayout());
|
||||
|
||||
if (!spriteSkin.isActiveAndEnabled || !spriteSkin.isValid || !spriteSkin.spriteRenderer.enabled)
|
||||
return;
|
||||
|
||||
var sprite = spriteSkin.spriteRenderer.sprite;
|
||||
var boneTransforms = spriteSkin.boneTransforms;
|
||||
var spriteBones = GetSpriteBones(spriteSkin);
|
||||
var alpha = 1f;
|
||||
|
||||
if (spriteBones == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < boneTransforms.Length; ++i)
|
||||
{
|
||||
var boneTransform = boneTransforms[i];
|
||||
|
||||
if (boneTransform == null || m_BoneData.ContainsKey(boneTransform))
|
||||
continue;
|
||||
|
||||
var bone = spriteBones[i];
|
||||
|
||||
if (view.IsActionHot(SkeletonAction.None))
|
||||
m_CachedBones.Add(boneTransform);
|
||||
|
||||
m_BoneData.Add(boneTransform, new Vector2(bone.length, alpha));
|
||||
}
|
||||
}
|
||||
|
||||
private void DoBoneGUI()
|
||||
{
|
||||
view.BeginLayout();
|
||||
|
||||
if (view.CanLayout())
|
||||
LayoutBones();
|
||||
|
||||
view.EndLayout();
|
||||
|
||||
HandleSelectBone();
|
||||
HandleRotateBone();
|
||||
HandleMoveBone();
|
||||
DrawBones();
|
||||
DrawCursors();
|
||||
}
|
||||
|
||||
private void LayoutBones()
|
||||
{
|
||||
foreach (var bone in m_CachedBones)
|
||||
{
|
||||
if (bone == null)
|
||||
continue;
|
||||
|
||||
Vector2 value;
|
||||
if (!m_BoneData.TryGetValue(bone, out value))
|
||||
continue;
|
||||
|
||||
var length = value.x;
|
||||
|
||||
if (bone != hotBone)
|
||||
view.LayoutBone(bone.GetInstanceID(), bone.position, bone.position + bone.GetScaledRight() * length, bone.forward, bone.up, bone.right, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleSelectBone()
|
||||
{
|
||||
int instanceID;
|
||||
bool additive;
|
||||
if (view.DoSelectBone(out instanceID, out additive))
|
||||
{
|
||||
var bone = GetBone(instanceID);
|
||||
|
||||
if (!additive)
|
||||
{
|
||||
if (!Selection.Contains(bone.gameObject))
|
||||
Selection.activeTransform = bone;
|
||||
}
|
||||
else
|
||||
{
|
||||
var objectList = new List<Object>(Selection.objects);
|
||||
|
||||
if(objectList.Contains(bone.gameObject))
|
||||
objectList.Remove(bone.gameObject);
|
||||
else
|
||||
objectList.Add(bone.gameObject);
|
||||
|
||||
Selection.objects = objectList.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleRotateBone()
|
||||
{
|
||||
var pivot = hoveredBone;
|
||||
|
||||
if (view.IsActionHot(SkeletonAction.RotateBone))
|
||||
pivot = hotBone;
|
||||
|
||||
if (pivot == null)
|
||||
return;
|
||||
|
||||
FindPivotTransform(pivot, out pivot);
|
||||
|
||||
if (pivot == null)
|
||||
return;
|
||||
|
||||
float deltaAngle;
|
||||
if (view.DoRotateBone(pivot.position, pivot.forward, out deltaAngle))
|
||||
SetBoneRotation(deltaAngle);
|
||||
}
|
||||
|
||||
private void HandleMoveBone()
|
||||
{
|
||||
Vector3 deltaPosition;
|
||||
if (view.DoMoveBone(out deltaPosition))
|
||||
SetBonePosition(deltaPosition);
|
||||
}
|
||||
|
||||
private bool FindPivotTransform(Transform transform, out Transform selectedTransform)
|
||||
{
|
||||
selectedTransform = transform;
|
||||
var selectedRoots = Selection.transforms;
|
||||
|
||||
foreach(var selectedRoot in selectedRoots)
|
||||
{
|
||||
if(transform.IsDescendentOf(selectedRoot))
|
||||
{
|
||||
selectedTransform = selectedRoot;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetBonePosition(Vector3 deltaPosition)
|
||||
{
|
||||
foreach (var selectedTransform in Selection.transforms)
|
||||
{
|
||||
if(!m_BoneData.ContainsKey(selectedTransform))
|
||||
continue;
|
||||
|
||||
var boneTransform = selectedTransform;
|
||||
|
||||
m_Undo.RecordObject(boneTransform, TextContent.moveBone);
|
||||
boneTransform.position += deltaPosition;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBoneRotation(float deltaAngle)
|
||||
{
|
||||
foreach(var selectedGameObject in Selection.gameObjects)
|
||||
{
|
||||
if(!m_BoneData.ContainsKey(selectedGameObject.transform))
|
||||
continue;
|
||||
|
||||
var boneTransform = selectedGameObject.transform;
|
||||
|
||||
m_Undo.RecordObject(boneTransform, TextContent.rotateBone);
|
||||
boneTransform.Rotate(boneTransform.forward, deltaAngle, Space.World);
|
||||
InternalEngineBridge.SetLocalEulerHint(boneTransform);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBones()
|
||||
{
|
||||
if (!view.IsRepainting())
|
||||
return;
|
||||
|
||||
var selectedOutlineColor = SelectionOutlineSettings.outlineColor;
|
||||
var selectedOutlineSize = SelectionOutlineSettings.selectedBoneOutlineSize;
|
||||
var defaultOutlineColor = Color.black.AlphaMultiplied(0.5f);
|
||||
|
||||
//Draw bone outlines
|
||||
foreach (var boneData in m_BoneData)
|
||||
{
|
||||
var bone = boneData.Key;
|
||||
|
||||
if (bone == null)
|
||||
continue;
|
||||
|
||||
var value = boneData.Value;
|
||||
var length = value.x;
|
||||
var alpha = value.y;
|
||||
|
||||
if (alpha == 0f || !bone.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
|
||||
var color = defaultOutlineColor;
|
||||
var outlineSize = 1.25f;
|
||||
|
||||
var isSelected = Selection.Contains(bone.gameObject);
|
||||
var isHovered = hoveredBody == bone && view.IsActionHot(SkeletonAction.None);
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
color = selectedOutlineColor;
|
||||
outlineSize = selectedOutlineSize * 0.5f + 1f;
|
||||
}
|
||||
else if (isHovered)
|
||||
color = Handles.preselectionColor;
|
||||
|
||||
DrawBoneOutline(bone, length, color, outlineSize);
|
||||
}
|
||||
|
||||
//Draw bones
|
||||
foreach (var boneData in m_BoneData)
|
||||
{
|
||||
var bone = boneData.Key;
|
||||
|
||||
if (bone == null)
|
||||
continue;
|
||||
|
||||
var value = boneData.Value;
|
||||
var length = value.x;
|
||||
var alpha = value.y;
|
||||
|
||||
if (alpha == 0f || !bone.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
|
||||
DrawBone(bone, length, Color.white);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBone(Transform bone, float length, Color color)
|
||||
{
|
||||
var isSelected = Selection.Contains(bone.gameObject);
|
||||
var isJointHovered = view.IsActionHot(SkeletonAction.None) && hoveredJoint == bone;
|
||||
var isTailHovered = view.IsActionHot(SkeletonAction.None) && hoveredTail == bone;
|
||||
|
||||
view.DrawBone(bone.position, bone.GetScaledRight(), bone.forward, length, color, false, isSelected, isJointHovered, isTailHovered, bone == hotBone);
|
||||
}
|
||||
|
||||
private void DrawBoneOutline(Transform bone, float length, Color color, float outlineScale)
|
||||
{
|
||||
view.DrawBoneOutline(bone.position, bone.GetScaledRight(), bone.forward, length, color, outlineScale);
|
||||
}
|
||||
|
||||
private void DrawCursors()
|
||||
{
|
||||
if (!view.IsRepainting())
|
||||
return;
|
||||
|
||||
view.DrawCursors(true);
|
||||
}
|
||||
|
||||
private bool HasParentBone(Transform transform)
|
||||
{
|
||||
Debug.Assert(transform != null);
|
||||
|
||||
return transform.parent != null && m_BoneData.ContainsKey(transform.parent);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d0bd0aa54cffc442b82bc92946537e05
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,58 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.U2D.Animation;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal interface IBoneGizmoToggle
|
||||
{
|
||||
bool enableGizmos { get; }
|
||||
void OnGUI();
|
||||
}
|
||||
|
||||
internal class BoneGizmoToggle : IBoneGizmoToggle
|
||||
{
|
||||
private bool m_EnableGizmos;
|
||||
private bool m_CurrentEnableGizmoState;
|
||||
|
||||
public bool enableGizmos
|
||||
{
|
||||
get { return m_CurrentEnableGizmoState; }
|
||||
}
|
||||
|
||||
public BoneGizmoToggle()
|
||||
{
|
||||
SpriteSkin.onDrawGizmos.AddListener(OnDrawGizmos);
|
||||
}
|
||||
|
||||
~BoneGizmoToggle()
|
||||
{
|
||||
SpriteSkin.onDrawGizmos.RemoveListener(OnDrawGizmos);
|
||||
}
|
||||
|
||||
//This callback will be called before OnSceneGUI in a Repaint event
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
m_EnableGizmos = true;
|
||||
|
||||
//One time is enough
|
||||
SpriteSkin.onDrawGizmos.RemoveListener(OnDrawGizmos);
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
//Ignore events other than Repaint
|
||||
if (Event.current.type != EventType.Repaint)
|
||||
return;
|
||||
|
||||
if (m_CurrentEnableGizmoState != m_EnableGizmos)
|
||||
SceneView.RepaintAll();
|
||||
|
||||
m_CurrentEnableGizmoState = m_EnableGizmos;
|
||||
|
||||
//Assume the Gizmo toggle is disabled and listen to the event again
|
||||
m_EnableGizmos = false;
|
||||
SpriteSkin.onDrawGizmos.RemoveListener(OnDrawGizmos);
|
||||
SpriteSkin.onDrawGizmos.AddListener(OnDrawGizmos);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 627558f812b9bb944851932d0a8d80d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,35 @@
|
|||
#if ENABLE_ANIMATION_COLLECTION && ENABLE_ANIMATION_BURST
|
||||
using UnityEngine;
|
||||
using UnityEngine.U2D.Animation;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal class SpriteSkinCompositeDebugWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("internal:Window/2D/SpritSkinCompositeDebug")]
|
||||
static void Launch()
|
||||
{
|
||||
EditorWindow.GetWindow<SpriteSkinCompositeDebugWindow>().Show();
|
||||
}
|
||||
|
||||
Vector2 m_ScrollPos = Vector2.zero;
|
||||
string m_DebugLog = "";
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
if (GUILayout.Button("Reset Sprite SkinComposite"))
|
||||
SpriteSkinComposite.instance.ResetComposite();
|
||||
|
||||
if (GUILayout.Button("Show Debug"))
|
||||
{
|
||||
m_DebugLog = SpriteSkinComposite.instance.GetDebugLog();
|
||||
}
|
||||
|
||||
m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos);
|
||||
GUILayout.TextArea(m_DebugLog);
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 44669af070a82b748b20b2a0fa6482d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,369 @@
|
|||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5c4ca39dfae364d0cabfa9898d2acfa1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,19 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
|
||||
#if ENABLE_ENTITIES
|
||||
|
||||
[CustomEditor(typeof(SpriteSkinEntity))]
|
||||
[CanEditMultipleObjects]
|
||||
class SpriteSkinEntityEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 22525e1e29f10a14db7e0bdf3b9f2a11
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,35 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal static class TransformExtensions
|
||||
{
|
||||
public static Vector3 GetScaledRight(this Transform transform)
|
||||
{
|
||||
return transform.localToWorldMatrix.MultiplyVector(Vector3.right);
|
||||
}
|
||||
|
||||
public static Vector3 GetScaledUp(this Transform transform)
|
||||
{
|
||||
return transform.localToWorldMatrix.MultiplyVector(Vector3.up);
|
||||
}
|
||||
|
||||
public static bool IsDescendentOf(this Transform transform, Transform ancestor)
|
||||
{
|
||||
if (ancestor != null)
|
||||
{
|
||||
var parent = transform.parent;
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
if (parent == ancestor)
|
||||
return true;
|
||||
|
||||
parent = parent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 47d4401cb6fd9f54b9c33acc7881703d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue