444 lines
15 KiB
C#
444 lines
15 KiB
C#
|
using System;
|
||
|
using UnityEngine.U2D.Common;
|
||
|
using UnityEditor.U2D.Layout;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.UIElements;
|
||
|
|
||
|
namespace UnityEditor.U2D.Animation
|
||
|
{
|
||
|
internal class VisibilityToolWindow : VisualElement, IVisibilityToolWindow
|
||
|
{
|
||
|
public class CustomUxmlFactory : UxmlFactory<VisibilityToolWindow, UxmlTraits> {}
|
||
|
|
||
|
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()
|
||
|
{
|
||
|
var visualTree = ResourceLoader.Load<VisualTreeAsset>("SkinningModule/VisibilityToolWindow.uxml");
|
||
|
var ve = visualTree.CloneTree().Q("VisibilityToolWindow") as VisibilityToolWindow;
|
||
|
var 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)
|
||
|
{
|
||
|
var 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, Action onClick)
|
||
|
{
|
||
|
var tab = new Button()
|
||
|
{
|
||
|
text = name
|
||
|
};
|
||
|
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, 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;
|
||
|
var tool = m_Tools[i];
|
||
|
tool.SetAvailabilityChangeCallback(() => OnToolAvailabilityChange(index));
|
||
|
tool.Setup();
|
||
|
model.view.AddToolTab(tool.name, () => 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)
|
||
|
{
|
||
|
var 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);
|
||
|
}
|
||
|
}
|
||
|
}
|