443 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			443 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using System.Collections.Generic; | ||
|  | using UnityEditor.U2D.Common; | ||
|  | using UnityEditor.U2D.Layout; | ||
|  | using UnityEngine.U2D.Common; | ||
|  | using UnityEngine.UIElements; | ||
|  | 
 | ||
|  | namespace UnityEditor.U2D.Animation | ||
|  | { | ||
|  | #if ENABLE_UXML_SERIALIZED_DATA | ||
|  |     [UxmlElement] | ||
|  | #endif | ||
|  |     internal partial class VisibilityToolWindow : VisualElement, IVisibilityToolWindow | ||
|  |     { | ||
|  | #if ENABLE_UXML_TRAITS | ||
|  |         public class CustomUxmlFactory : UxmlFactory<VisibilityToolWindow, UxmlTraits> { } | ||
|  | #endif | ||
|  | 
 | ||
|  |         VisualElement m_SelectorContainer; | ||
|  |         VisualElement m_Container; | ||
|  |         Slider m_BoneOpacitySlider; | ||
|  |         Slider m_MeshOpacitySlider; | ||
|  |         private LayoutOverlay m_Layout; | ||
|  | 
 | ||
|  |         List<Button> m_Tabs; | ||
|  |         int m_CurrentSelectedTab = 0; | ||
|  | 
 | ||
|  |         public event Action<float> onBoneOpacitySliderChange = (f) => { }; | ||
|  |         public event Action<float> onMeshOpacitySliderChange = (f) => { }; | ||
|  |         public event Action onBoneOpacitySliderChangeBegin = () => { }; | ||
|  |         public event Action onBoneOpacitySliderChangeEnd = () => { }; | ||
|  |         public event Action onMeshOpacitySliderChangeBegin = () => { }; | ||
|  |         public event Action onMeshOpacitySliderChangeEnd = () => { }; | ||
|  | 
 | ||
|  |         public static VisibilityToolWindow CreateFromUXML() | ||
|  |         { | ||
|  |             VisualTreeAsset visualTree = ResourceLoader.Load<VisualTreeAsset>("SkinningModule/VisibilityToolWindow.uxml"); | ||
|  |             VisibilityToolWindow ve = visualTree.CloneTree().Q("VisibilityToolWindow") as VisibilityToolWindow; | ||
|  |             VisualElement resizer = ve.Q("Resizer"); | ||
|  |             resizer.AddManipulator(new VisibilityToolResizer()); | ||
|  |             ve.styleSheets.Add(ResourceLoader.Load<StyleSheet>("SkinningModule/VisibilityTool.uss")); | ||
|  |             if (EditorGUIUtility.isProSkin) | ||
|  |                 ve.AddToClassList("Dark"); | ||
|  |             ve.LocalizeTextInChildren(); | ||
|  |             ve.BindElements(); | ||
|  |             return ve; | ||
|  |         } | ||
|  | 
 | ||
|  |         public void BindElements() | ||
|  |         { | ||
|  |             m_SelectorContainer = this.Q("VisibilityToolSelection"); | ||
|  |             m_Container = this.Q("VisibilityToolContainer"); | ||
|  |             m_BoneOpacitySlider = this.Q<Slider>("BoneOpacitySlider"); | ||
|  |             m_BoneOpacitySlider.RegisterValueChangedCallback(OnBoneOpacitySliderValueChangd); | ||
|  |             m_MeshOpacitySlider = this.Q<Slider>("MeshOpacitySlider"); | ||
|  |             m_MeshOpacitySlider.RegisterValueChangedCallback(OnMeshOpacitySliderValueChangd); | ||
|  |             RegisterCallback<MouseDownEvent>(OpacityChangeBegin, TrickleDown.TrickleDown); | ||
|  |             RegisterCallback<MouseCaptureOutEvent>(OpacityChangeEnd, TrickleDown.TrickleDown); | ||
|  | 
 | ||
|  |             // case 1200857 StopPropagation when bubbling up so that main IMGUI doesn't get the event | ||
|  |             RegisterCallback<MouseDownEvent>(evt => evt.StopPropagation()); | ||
|  |             m_Tabs = new List<Button>(); | ||
|  |             m_SelectorContainer.Clear(); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void Initialize(LayoutOverlay layout) | ||
|  |         { | ||
|  |             m_Layout = layout; | ||
|  |             layout.rightOverlay.Add(this); | ||
|  |             Hide(); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void Show() | ||
|  |         { | ||
|  |             m_Container.Clear(); | ||
|  |             this.SetHiddenFromLayout(false); | ||
|  |             m_Layout.VisibilityWindowOn(true); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void Hide() | ||
|  |         { | ||
|  |             m_Container.Clear(); | ||
|  |             this.SetHiddenFromLayout(true); | ||
|  |             m_Layout.VisibilityWindowOn(false); | ||
|  |         } | ||
|  | 
 | ||
|  |         bool IsOpacityTarget(IEventHandler target, VisualElement opacityTarget) | ||
|  |         { | ||
|  |             VisualElement ve = target as VisualElement; | ||
|  |             while (ve != null && ve != this) | ||
|  |             { | ||
|  |                 if (ve == opacityTarget) | ||
|  |                     return true; | ||
|  |                 ve = ve.parent; | ||
|  |             } | ||
|  | 
 | ||
|  |             return false; | ||
|  |         } | ||
|  | 
 | ||
|  |         void OpacityChangeBegin(MouseDownEvent evt) | ||
|  |         { | ||
|  |             if (IsOpacityTarget(evt.target, m_BoneOpacitySlider)) | ||
|  |                 onBoneOpacitySliderChangeBegin(); | ||
|  |             else if (IsOpacityTarget(evt.target, m_MeshOpacitySlider)) | ||
|  |                 onMeshOpacitySliderChangeBegin(); | ||
|  |         } | ||
|  | 
 | ||
|  |         void OpacityChangeEnd(MouseCaptureOutEvent evt) | ||
|  |         { | ||
|  |             if (IsOpacityTarget(evt.target, m_BoneOpacitySlider)) | ||
|  |                 onBoneOpacitySliderChangeEnd(); | ||
|  |             else if (IsOpacityTarget(evt.target, m_MeshOpacitySlider)) | ||
|  |                 onMeshOpacitySliderChangeEnd(); | ||
|  |         } | ||
|  | 
 | ||
|  |         void OnBoneOpacitySliderValueChangd(ChangeEvent<float> evt) | ||
|  |         { | ||
|  |             onBoneOpacitySliderChange(evt.newValue); | ||
|  |         } | ||
|  | 
 | ||
|  |         void OnMeshOpacitySliderValueChangd(ChangeEvent<float> evt) | ||
|  |         { | ||
|  |             onMeshOpacitySliderChange(evt.newValue); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void SetBoneOpacitySliderValue(float value) | ||
|  |         { | ||
|  |             m_BoneOpacitySlider.value = value; | ||
|  |             m_BoneOpacitySlider.MarkDirtyRepaint(); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void SetMeshOpacitySliderValue(float value) | ||
|  |         { | ||
|  |             m_MeshOpacitySlider.value = value; | ||
|  |             m_MeshOpacitySlider.MarkDirtyRepaint(); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void AddToolTab(string name, string tooltip, Action onClick) | ||
|  |         { | ||
|  |             Button tab = new Button() | ||
|  |             { | ||
|  |                 text = name, | ||
|  |                 tooltip = tooltip | ||
|  |             }; | ||
|  |             tab.AddToClassList("visibilityToolTab"); | ||
|  |             if (EditorGUIUtility.isProSkin) | ||
|  |                 tab.AddToClassList("visibilityToolTabDark"); | ||
|  |             m_SelectorContainer.Add(tab); | ||
|  |             m_Tabs.Add(tab); | ||
|  |             tab.clickable.clicked += onClick; | ||
|  |         } | ||
|  | 
 | ||
|  |         public void SetActiveTab(int toolIndex) | ||
|  |         { | ||
|  |             if (m_Tabs.Count > toolIndex && toolIndex >= 0) | ||
|  |             { | ||
|  |                 m_Tabs[m_CurrentSelectedTab].SetChecked(false); | ||
|  |                 m_Tabs[toolIndex].SetChecked(true); | ||
|  |                 m_CurrentSelectedTab = toolIndex; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public void SetContent(VisualElement content) | ||
|  |         { | ||
|  |             m_Container.Clear(); | ||
|  |             m_Container.Add(content); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void SetToolAvailable(int toolIndex, bool available) | ||
|  |         { | ||
|  |             if (m_Tabs.Count > toolIndex && toolIndex >= 0) | ||
|  |             { | ||
|  |                 m_Tabs[toolIndex].SetHiddenFromLayout(!available); | ||
|  |                 if (available == false && toolIndex == m_CurrentSelectedTab) | ||
|  |                     m_Container.Clear(); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     internal class VisibilityTool : BaseTool, IVisibilityToolModel | ||
|  |     { | ||
|  |         private VisibilityToolWindow m_ToolView; | ||
|  | 
 | ||
|  |         private MeshPreviewBehaviour m_MeshPreviewBehaviour = new MeshPreviewBehaviour(); | ||
|  |         public SkeletonTool skeletonTool { set; private get; } | ||
|  | 
 | ||
|  |         VisibilityToolController m_Controller; | ||
|  | 
 | ||
|  |         internal override void OnCreate() | ||
|  |         { | ||
|  |             m_ToolView = VisibilityToolWindow.CreateFromUXML(); | ||
|  |             m_Controller = new VisibilityToolController(this, new IVisibilityTool[] | ||
|  |                 { | ||
|  |                     new BoneVisibilityTool(skinningCache), | ||
|  |                     new SpriteVisibilityTool(skinningCache) | ||
|  |                 }, | ||
|  |                 () => skeletonTool, | ||
|  |                 () => previewBehaviour); | ||
|  |         } | ||
|  | 
 | ||
|  |         public override IMeshPreviewBehaviour previewBehaviour | ||
|  |         { | ||
|  |             get { return m_MeshPreviewBehaviour; } | ||
|  |         } | ||
|  | 
 | ||
|  |         public override void Initialize(LayoutOverlay layout) | ||
|  |         { | ||
|  |             m_ToolView.Initialize(layout); | ||
|  |         } | ||
|  | 
 | ||
|  |         protected override void OnGUI() | ||
|  |         { | ||
|  |             skeletonTool.skeletonStyle = SkeletonStyles.WeightMap; | ||
|  |             skeletonTool.mode = SkeletonMode.EditPose; | ||
|  |             skeletonTool.editBindPose = false; | ||
|  |             skeletonTool.DoGUI(); | ||
|  |         } | ||
|  | 
 | ||
|  |         protected override void OnActivate() | ||
|  |         { | ||
|  |             m_MeshPreviewBehaviour.showWeightMap = true; | ||
|  |             m_Controller.Activate(); | ||
|  |         } | ||
|  | 
 | ||
|  |         protected override void OnDeactivate() | ||
|  |         { | ||
|  |             m_Controller.Deactivate(); | ||
|  |         } | ||
|  | 
 | ||
|  |         int IVisibilityToolModel.currentToolIndex | ||
|  |         { | ||
|  |             get { return skinningCache.visibilityToolIndex; } | ||
|  |             set { skinningCache.visibilityToolIndex = value; } | ||
|  |         } | ||
|  | 
 | ||
|  |         float IVisibilityToolModel.boneOpacityValue | ||
|  |         { | ||
|  |             get { return VisibilityToolSettings.boneOpacity; } | ||
|  |             set { VisibilityToolSettings.boneOpacity = value; } | ||
|  |         } | ||
|  | 
 | ||
|  |         float IVisibilityToolModel.meshOpacityValue | ||
|  |         { | ||
|  |             get { return VisibilityToolSettings.meshOpacity; } | ||
|  |             set { VisibilityToolSettings.meshOpacity = value; } | ||
|  |         } | ||
|  | 
 | ||
|  |         UndoScope IVisibilityToolModel.UndoScope(string value) | ||
|  |         { | ||
|  |             return skinningCache.UndoScope(value); | ||
|  |         } | ||
|  | 
 | ||
|  |         void IVisibilityToolModel.BeginUndoOperation(string value) | ||
|  |         { | ||
|  |             skinningCache.BeginUndoOperation(value); | ||
|  |         } | ||
|  | 
 | ||
|  |         IVisibilityToolWindow IVisibilityToolModel.view | ||
|  |         { | ||
|  |             get { return m_ToolView; } | ||
|  |         } | ||
|  | 
 | ||
|  |         SkinningCache IVisibilityToolModel.skinningCache | ||
|  |         { | ||
|  |             get { return skinningCache; } | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     internal interface IVisibilityToolModel | ||
|  |     { | ||
|  |         int currentToolIndex { get; set; } | ||
|  |         float meshOpacityValue { get; set; } | ||
|  |         float boneOpacityValue { get; set; } | ||
|  |         UndoScope UndoScope(string value); | ||
|  |         void BeginUndoOperation(string value); | ||
|  |         IVisibilityToolWindow view { get; } | ||
|  |         SkinningCache skinningCache { get; } | ||
|  |     } | ||
|  | 
 | ||
|  |     internal interface IVisibilityToolWindow | ||
|  |     { | ||
|  |         void AddToolTab(string name, string tooltip, Action callback); | ||
|  |         void SetToolAvailable(int i, bool available); | ||
|  |         void SetBoneOpacitySliderValue(float value); | ||
|  |         void SetMeshOpacitySliderValue(float value); | ||
|  |         event Action<float> onBoneOpacitySliderChange; | ||
|  |         event Action<float> onMeshOpacitySliderChange; | ||
|  |         event Action onBoneOpacitySliderChangeBegin; | ||
|  |         event Action onBoneOpacitySliderChangeEnd; | ||
|  |         event Action onMeshOpacitySliderChangeBegin; | ||
|  |         event Action onMeshOpacitySliderChangeEnd; | ||
|  |         void Show(); | ||
|  |         void Hide(); | ||
|  |         void SetActiveTab(int index); | ||
|  |         void SetContent(VisualElement content); | ||
|  |     } | ||
|  | 
 | ||
|  |     internal class VisibilityToolController | ||
|  |     { | ||
|  |         IVisibilityTool[] m_Tools; | ||
|  |         IVisibilityToolModel m_Model; | ||
|  |         Func<SkeletonTool> m_SkeletonTool; | ||
|  |         Func<IMeshPreviewBehaviour> m_MeshPreviewBehaviour; | ||
|  |         bool m_DeactivateBoneaTool = false; | ||
|  | 
 | ||
|  |         private IVisibilityTool currentTool | ||
|  |         { | ||
|  |             get { return m_Model.currentToolIndex == -1 ? null : m_Tools[m_Model.currentToolIndex]; } | ||
|  |             set { m_Model.currentToolIndex = value == null ? -1 : Array.FindIndex(m_Tools, x => x == value); } | ||
|  |         } | ||
|  | 
 | ||
|  |         private IVisibilityTool defaultTool | ||
|  |         { | ||
|  |             get { return Array.Find(m_Tools, t => t.isAvailable); } | ||
|  |         } | ||
|  | 
 | ||
|  |         public VisibilityToolController(IVisibilityToolModel model, IVisibilityTool[] tools, Func<SkeletonTool> skeletonTool = null, Func<IMeshPreviewBehaviour> meshPreviewBehaviour = null) | ||
|  |         { | ||
|  |             m_Model = model; | ||
|  |             m_Tools = tools; | ||
|  |             for (int i = 0; i < m_Tools.Length; ++i) | ||
|  |             { | ||
|  |                 int index = i; | ||
|  |                 IVisibilityTool tool = m_Tools[i]; | ||
|  |                 tool.SetAvailabilityChangeCallback(() => OnToolAvailabilityChange(index)); | ||
|  |                 tool.Setup(); | ||
|  |                 model.view.AddToolTab(tool.name, tool.tooltip, () => ActivateToolWithUndo(tool)); | ||
|  |                 model.view.SetToolAvailable(i, tool.isAvailable); | ||
|  |             } | ||
|  | 
 | ||
|  |             m_SkeletonTool = skeletonTool; | ||
|  |             m_MeshPreviewBehaviour = meshPreviewBehaviour; | ||
|  |         } | ||
|  | 
 | ||
|  |         public void Activate() | ||
|  |         { | ||
|  |             m_Model.view.Show(); | ||
|  | 
 | ||
|  |             if (currentTool == null) | ||
|  |                 currentTool = defaultTool; | ||
|  |             ActivateTool(currentTool); | ||
|  | 
 | ||
|  |             m_Model.view.SetBoneOpacitySliderValue(m_Model.boneOpacityValue); | ||
|  |             m_Model.view.SetMeshOpacitySliderValue(m_Model.meshOpacityValue); | ||
|  |             m_Model.view.onBoneOpacitySliderChange -= OnBoneOpacityChange; | ||
|  |             m_Model.view.onMeshOpacitySliderChange -= OnMeshOpacityChange; | ||
|  |             m_Model.view.onBoneOpacitySliderChange += OnBoneOpacityChange; | ||
|  |             m_Model.view.onMeshOpacitySliderChange += OnMeshOpacityChange; | ||
|  |             m_Model.view.onBoneOpacitySliderChangeBegin -= OnBoneOpacityChangeBegin; | ||
|  |             m_Model.view.onBoneOpacitySliderChangeBegin += OnBoneOpacityChangeBegin; | ||
|  |             m_Model.view.onBoneOpacitySliderChangeEnd -= OnBoneOpacityChangeEnd; | ||
|  |             m_Model.view.onBoneOpacitySliderChangeEnd += OnBoneOpacityChangeEnd; | ||
|  |             m_Model.view.onMeshOpacitySliderChangeBegin -= OnMeshOpacityChangeBegin; | ||
|  |             m_Model.view.onMeshOpacitySliderChangeBegin += OnMeshOpacityChangeBegin; | ||
|  |             m_Model.view.onMeshOpacitySliderChangeEnd -= OnMeshOpacityChangeEnd; | ||
|  |             m_Model.view.onMeshOpacitySliderChangeEnd += OnMeshOpacityChangeEnd; | ||
|  |         } | ||
|  | 
 | ||
|  |         public void Deactivate() | ||
|  |         { | ||
|  |             m_Model.view.Hide(); | ||
|  | 
 | ||
|  |             if (currentTool != null) | ||
|  |                 currentTool.Deactivate(); | ||
|  | 
 | ||
|  |             m_Model.view.onBoneOpacitySliderChange -= OnBoneOpacityChange; | ||
|  |             m_Model.view.onMeshOpacitySliderChange -= OnMeshOpacityChange; | ||
|  |             m_Model.view.onBoneOpacitySliderChangeBegin -= OnBoneOpacityChangeBegin; | ||
|  |             m_Model.view.onBoneOpacitySliderChangeEnd -= OnBoneOpacityChangeEnd; | ||
|  |             m_Model.view.onMeshOpacitySliderChangeBegin -= OnMeshOpacityChangeBegin; | ||
|  |             m_Model.view.onMeshOpacitySliderChangeEnd -= OnMeshOpacityChangeEnd; | ||
|  |         } | ||
|  | 
 | ||
|  |         void OnBoneOpacityChangeBegin() | ||
|  |         { | ||
|  |             if (m_SkeletonTool != null && m_SkeletonTool() != null && !m_SkeletonTool().isActive) | ||
|  |             { | ||
|  |                 m_SkeletonTool().Activate(); | ||
|  |                 m_DeactivateBoneaTool = true; | ||
|  |             } | ||
|  | 
 | ||
|  |         } | ||
|  | 
 | ||
|  |         void OnBoneOpacityChangeEnd() | ||
|  |         { | ||
|  |             if (m_SkeletonTool != null && m_SkeletonTool() != null && m_SkeletonTool().isActive && m_DeactivateBoneaTool) | ||
|  |                 m_SkeletonTool().Deactivate(); | ||
|  |         } | ||
|  | 
 | ||
|  |         void OnMeshOpacityChangeBegin() | ||
|  |         { | ||
|  |             m_Model.skinningCache.events.meshPreviewBehaviourChange.Invoke(m_MeshPreviewBehaviour()); | ||
|  |         } | ||
|  | 
 | ||
|  |         void OnMeshOpacityChangeEnd() | ||
|  |         { | ||
|  |             m_Model.skinningCache.events.meshPreviewBehaviourChange.Invoke(null); | ||
|  |         } | ||
|  | 
 | ||
|  |         private void OnBoneOpacityChange(float value) | ||
|  |         { | ||
|  |             m_Model.boneOpacityValue = value; | ||
|  |         } | ||
|  | 
 | ||
|  |         private void OnMeshOpacityChange(float value) | ||
|  |         { | ||
|  |             m_Model.meshOpacityValue = value; | ||
|  |         } | ||
|  | 
 | ||
|  |         private void OnToolAvailabilityChange(int toolIndex) | ||
|  |         { | ||
|  |             IVisibilityTool toolChanged = m_Tools[toolIndex]; | ||
|  |             m_Model.view.SetToolAvailable(toolIndex, toolChanged.isAvailable); | ||
|  |             if (toolChanged == currentTool && toolChanged.isAvailable == false) | ||
|  |                 ActivateTool(defaultTool); | ||
|  |         } | ||
|  | 
 | ||
|  |         private void ActivateToolWithUndo(IVisibilityTool tool) | ||
|  |         { | ||
|  |             if (currentTool != tool && tool.isAvailable) | ||
|  |             { | ||
|  |                 m_Model.BeginUndoOperation(TextContent.visibilityTab); | ||
|  |                 ActivateTool(tool); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         private void ActivateTool(IVisibilityTool tool) | ||
|  |         { | ||
|  |             if (tool.isAvailable == false) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             if (currentTool != null) | ||
|  |                 currentTool.Deactivate(); | ||
|  | 
 | ||
|  |             currentTool = tool; | ||
|  |             currentTool.Activate(); | ||
|  | 
 | ||
|  |             m_Model.view.SetActiveTab(m_Model.currentToolIndex); | ||
|  |             m_Model.view.SetContent(currentTool.view); | ||
|  |         } | ||
|  |     } | ||
|  | } |