240 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using UnityEditor.U2D.Layout;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace UnityEditor.U2D.Animation
 | |
| {
 | |
|     internal class SkeletonTool : BaseTool
 | |
|     {
 | |
|         [SerializeField]
 | |
|         SkeletonController m_SkeletonController;
 | |
|         SkeletonToolView m_SkeletonToolView;
 | |
|         RectBoneSelector m_RectBoneSelector = new RectBoneSelector();
 | |
|         RectSelectionTool<BoneCache> m_RectSelectionTool = new RectSelectionTool<BoneCache>();
 | |
|         UnselectTool<BoneCache> m_UnselectTool = new UnselectTool<BoneCache>();
 | |
| 
 | |
|         public bool enableBoneInspector { get; set; }
 | |
| 
 | |
|         public SkeletonMode mode
 | |
|         {
 | |
|             get => m_SkeletonController.view.mode;
 | |
|             set => m_SkeletonController.view.mode = value;
 | |
|         }
 | |
| 
 | |
|         public bool editBindPose
 | |
|         {
 | |
|             get => m_SkeletonController.editBindPose;
 | |
|             set => m_SkeletonController.editBindPose = value;
 | |
|         }
 | |
| 
 | |
|         public ISkeletonStyle skeletonStyle
 | |
|         {
 | |
|             get => m_SkeletonController.styleOverride;
 | |
|             set => m_SkeletonController.styleOverride = value;
 | |
|         }
 | |
| 
 | |
|         public override int defaultControlID => 0;
 | |
| 
 | |
|         public BoneCache hoveredBone => m_SkeletonController.hoveredBone;
 | |
| 
 | |
|         public SkeletonCache skeleton
 | |
|         {
 | |
|             get => m_SkeletonController.skeleton;
 | |
|             private set => m_SkeletonController.skeleton = value;
 | |
|         }
 | |
| 
 | |
|         internal override void OnCreate()
 | |
|         {
 | |
|             m_SkeletonController = new SkeletonController();
 | |
|             m_SkeletonController.view = new SkeletonView(new GUIWrapper());
 | |
|             m_SkeletonController.view.InvalidID = 0;
 | |
|             m_SkeletonController.selection = skinningCache.skeletonSelection;
 | |
|             m_SkeletonToolView = new SkeletonToolView();
 | |
|             m_SkeletonToolView.onBoneNameChanged += BoneNameChanged;
 | |
|             m_SkeletonToolView.onBoneDepthChanged += BoneDepthChanged;
 | |
|             m_SkeletonToolView.onBonePositionChanged += BonePositionChanged;
 | |
|             m_SkeletonToolView.onBoneRotationChanged += BoneRotationChanged;
 | |
|             m_SkeletonToolView.onBoneColorChanged += BoneColorChanged;
 | |
|             m_RectBoneSelector.selection = skinningCache.skeletonSelection;
 | |
|             m_RectSelectionTool.rectSelector = m_RectBoneSelector;
 | |
|             m_RectSelectionTool.cacheUndo = skinningCache;
 | |
|             m_RectSelectionTool.onSelectionUpdate += () =>
 | |
|             {
 | |
|                 skinningCache.events.boneSelectionChanged.Invoke();
 | |
|             };
 | |
|             m_UnselectTool.cacheUndo = skinningCache;
 | |
|             m_UnselectTool.selection = skinningCache.skeletonSelection;
 | |
|             m_UnselectTool.onUnselect += () =>
 | |
|             {
 | |
|                 skinningCache.events.boneSelectionChanged.Invoke();
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         public override void Initialize(LayoutOverlay layout)
 | |
|         {
 | |
|             m_SkeletonToolView.Initialize(layout);
 | |
|         }
 | |
| 
 | |
|         protected override void OnActivate()
 | |
|         {
 | |
|             SetupSkeleton(skinningCache.GetEffectiveSkeleton(skinningCache.selectedSprite));
 | |
|             UpdateBoneInspector();
 | |
|             skinningCache.events.skeletonTopologyChanged.AddListener(SkeletonTopologyChanged);
 | |
|             skinningCache.events.boneSelectionChanged.AddListener(BoneSelectionChanged);
 | |
|             skinningCache.events.selectedSpriteChanged.AddListener(SelectedSpriteChanged);
 | |
|             skinningCache.events.skinningModeChanged.AddListener(SkinningModeChanged);
 | |
|             skinningCache.events.boneDepthChanged.AddListener(BoneDataChanged);
 | |
|             skinningCache.events.boneNameChanged.AddListener(BoneDataChanged);
 | |
|             skinningCache.events.boneColorChanged.AddListener(BoneDataChanged);
 | |
|             skeletonStyle = null;
 | |
|         }
 | |
| 
 | |
|         protected override void OnDeactivate()
 | |
|         {
 | |
|             m_SkeletonToolView.Hide();
 | |
|             m_SkeletonController.Reset();
 | |
|             skinningCache.events.skeletonTopologyChanged.RemoveListener(SkeletonTopologyChanged);
 | |
|             skinningCache.events.boneSelectionChanged.RemoveListener(BoneSelectionChanged);
 | |
|             skinningCache.events.selectedSpriteChanged.RemoveListener(SelectedSpriteChanged);
 | |
|             skinningCache.events.skinningModeChanged.RemoveListener(SkinningModeChanged);
 | |
|             skinningCache.events.boneDepthChanged.RemoveListener(BoneDataChanged);
 | |
|             skinningCache.events.boneNameChanged.RemoveListener(BoneDataChanged);
 | |
|             skinningCache.events.boneColorChanged.RemoveListener(BoneDataChanged);
 | |
|             skeletonStyle = null;
 | |
|         }
 | |
| 
 | |
|         void SkeletonTopologyChanged(SkeletonCache skeletonCache)
 | |
|         {
 | |
|             if (skeleton == skeletonCache && skeleton != null)
 | |
|                 m_RectBoneSelector.bones = skeleton.bones;
 | |
|         }
 | |
| 
 | |
|         void BoneDataChanged(BoneCache bone)
 | |
|         {
 | |
|             if (m_SkeletonToolView.target == bone)
 | |
|                 m_SkeletonToolView.Update(bone.name, Mathf.RoundToInt(bone.depth), bone.position, bone.rotation.eulerAngles.z, bone.bindPoseColor);
 | |
|         }
 | |
| 
 | |
|         void SelectedSpriteChanged(SpriteCache sprite)
 | |
|         {
 | |
|             SetupSkeleton(skinningCache.GetEffectiveSkeleton(sprite));
 | |
|         }
 | |
| 
 | |
|         void BoneSelectionChanged()
 | |
|         {
 | |
|             UpdateBoneInspector();
 | |
|         }
 | |
| 
 | |
|         void UpdateBoneInspector()
 | |
|         {
 | |
|             BoneCache selectedBone = skinningCache.skeletonSelection.activeElement;
 | |
|             int selectionCount = skinningCache.skeletonSelection.Count;
 | |
| 
 | |
|             m_SkeletonToolView.Hide();
 | |
| 
 | |
|             if (enableBoneInspector && selectedBone != null && selectionCount == 1)
 | |
|             {
 | |
|                 m_SkeletonToolView.Update(selectedBone.name, Mathf.RoundToInt(selectedBone.depth), selectedBone.position, selectedBone.rotation.eulerAngles.z, selectedBone.bindPoseColor);
 | |
|                 bool isReadOnly = skinningCache.bonesReadOnly;
 | |
|                 m_SkeletonToolView.Show(selectedBone, isReadOnly);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void SkinningModeChanged(SkinningMode skinningMode)
 | |
|         {
 | |
|             SetupSkeleton(skinningCache.GetEffectiveSkeleton(skinningCache.selectedSprite));
 | |
|         }
 | |
| 
 | |
|         void SetupSkeleton(SkeletonCache sk)
 | |
|         {
 | |
|             m_RectBoneSelector.bones = null;
 | |
|             skeleton = sk;
 | |
| 
 | |
|             if (skeleton != null)
 | |
|                 m_RectBoneSelector.bones = skeleton.bones;
 | |
|         }
 | |
| 
 | |
|         protected override void OnGUI()
 | |
|         {
 | |
|             m_SkeletonController.view.defaultControlID = 0;
 | |
| 
 | |
|             if (skeleton != null && mode != SkeletonMode.Disabled)
 | |
|             {
 | |
|                 m_RectSelectionTool.OnGUI();
 | |
|                 m_SkeletonController.view.defaultControlID = m_RectSelectionTool.controlID;
 | |
|             }
 | |
| 
 | |
|             m_SkeletonController.OnGUI();
 | |
|             m_UnselectTool.OnGUI();
 | |
|         }
 | |
| 
 | |
|         void BoneColorChanged(BoneCache selectedBone, Color32 color)
 | |
|         {
 | |
|             if (selectedBone != null)
 | |
|             {
 | |
|                 skinningCache.BeginUndoOperation(TextContent.colorBoneChanged);
 | |
|                 selectedBone.bindPoseColor = color;
 | |
|                 skinningCache.events.boneColorChanged.Invoke(selectedBone);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void BonePositionChanged(BoneCache selectedBone, Vector2 position)
 | |
|         {
 | |
|             if (selectedBone != null)
 | |
|             {
 | |
|                 skinningCache.BeginUndoOperation(TextContent.moveBone);
 | |
|                 selectedBone.position = position;
 | |
|                 HandleUtility.Repaint();
 | |
|                 m_SkeletonController.InvokePoseChanged();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void BoneRotationChanged(BoneCache selectedBone, float rotation)
 | |
|         {
 | |
|             if (selectedBone != null)
 | |
|             {
 | |
|                 Vector3 euler = selectedBone.rotation.eulerAngles;
 | |
|                 euler.z = rotation;
 | |
|                 skinningCache.BeginUndoOperation(TextContent.rotateBone);
 | |
|                 selectedBone.rotation = Quaternion.Euler(euler);
 | |
|                 HandleUtility.Repaint();
 | |
|                 m_SkeletonController.InvokePoseChanged();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void BoneNameChanged(BoneCache selectedBone, string name)
 | |
|         {
 | |
|             if (selectedBone != null)
 | |
|             {
 | |
|                 if (string.Compare(selectedBone.name, name) == 0)
 | |
|                     return;
 | |
| 
 | |
|                 if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
 | |
|                     m_SkeletonToolView.Update(selectedBone.name, Mathf.RoundToInt(selectedBone.depth), selectedBone.position, selectedBone.rotation.eulerAngles.z, selectedBone.bindPoseColor);
 | |
|                 else
 | |
|                 {
 | |
|                     using (skinningCache.UndoScope(TextContent.boneName))
 | |
|                     {
 | |
|                         selectedBone.name = name;
 | |
|                         skinningCache.events.boneNameChanged.Invoke(selectedBone);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void BoneDepthChanged(BoneCache selectedBone, int depth)
 | |
|         {
 | |
|             if (selectedBone != null)
 | |
|             {
 | |
|                 if (Mathf.RoundToInt(selectedBone.depth) == depth)
 | |
|                     return;
 | |
| 
 | |
|                 using (skinningCache.UndoScope(TextContent.boneDepth))
 | |
|                 {
 | |
|                     selectedBone.depth = depth;
 | |
|                     skinningCache.events.boneDepthChanged.Invoke(selectedBone);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |