testss
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using UnityEditor.U2D.Layout;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal class BoneReparentToolController : BoneTreeWidgetController
|
||||
{
|
||||
public BoneReparentToolController(IBoneTreeViewModel model, SkinningEvents eventSystem) : base(model, eventSystem)
|
||||
{}
|
||||
|
||||
public override bool CanDrag()
|
||||
{
|
||||
m_SkinningEvents.boneVisibility.Invoke("drag");
|
||||
return (m_Model.hasCharacter && m_Model.mode == SkinningMode.Character) ||
|
||||
(!m_Model.hasCharacter && m_Model.mode == SkinningMode.SpriteSheet);
|
||||
}
|
||||
|
||||
public override bool CanRename()
|
||||
{
|
||||
m_SkinningEvents.boneVisibility.Invoke("rename");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal class BoneReparentToolModel : BoneTreeWidgetModel
|
||||
{
|
||||
public BoneReparentToolModel(SkinningCache cache, IBoneVisibilityToolView view)
|
||||
{
|
||||
m_SkinningCache = cache;
|
||||
m_View = view;
|
||||
m_Data = skinningCache.CreateCache<BoneVisibilityToolData>();
|
||||
}
|
||||
}
|
||||
|
||||
internal class BoneReparentTool : SkeletonToolWrapper
|
||||
{
|
||||
BoneReparentToolWindow m_View;
|
||||
BoneReparentToolModel m_Model;
|
||||
private BoneReparentToolController m_Controller;
|
||||
|
||||
|
||||
public override void Initialize(LayoutOverlay layout)
|
||||
{
|
||||
if (m_View == null)
|
||||
{
|
||||
m_View = BoneReparentToolWindow.CreateFromUXML();
|
||||
}
|
||||
m_Model = new BoneReparentToolModel(skinningCache, m_View);
|
||||
m_Controller = new BoneReparentToolController(m_Model, skinningCache.events);
|
||||
m_View.GetController = () => m_Controller;
|
||||
m_View.GetModel = () => m_Model;
|
||||
layout.rightOverlay.Add(m_View);
|
||||
m_View.SetHiddenFromLayout(true);
|
||||
}
|
||||
|
||||
protected override void OnActivate()
|
||||
{
|
||||
m_View.SetHiddenFromLayout(false);
|
||||
m_Controller.Activate();
|
||||
skeletonTool.Activate();
|
||||
}
|
||||
|
||||
protected override void OnDeactivate()
|
||||
{
|
||||
m_View.SetHiddenFromLayout(true);
|
||||
m_Controller.Deactivate();
|
||||
skeletonTool.Deactivate();
|
||||
}
|
||||
|
||||
protected override void OnGUI()
|
||||
{
|
||||
skeletonTool.mode = mode;
|
||||
skeletonTool.editBindPose = editBindPose;
|
||||
skeletonTool.DoGUI();
|
||||
}
|
||||
}
|
||||
|
||||
internal class BoneReparentToolWindow : VisualElement, IBoneVisibilityToolView
|
||||
{
|
||||
public class CustomUxmlFactory : UxmlFactory<BoneReparentToolWindow, UxmlTraits> {}
|
||||
BoneReparentToolView m_ToolView;
|
||||
public Func<IBoneTreeViewModel> GetModel = () => null;
|
||||
public Func<BoneTreeWidgetController> GetController = () => null;
|
||||
|
||||
static internal BoneReparentToolWindow CreateFromUXML()
|
||||
{
|
||||
var visualTree = ResourceLoader.Load<VisualTreeAsset>("SkinningModule/BoneReparentWindow.uxml");
|
||||
var ve = visualTree.CloneTree().Q("BoneReparentToolWindow") as BoneReparentToolWindow;
|
||||
ve.BindElements();
|
||||
return ve;
|
||||
}
|
||||
|
||||
internal void BindElements()
|
||||
{
|
||||
m_ToolView = this.Q<BoneReparentToolView>();
|
||||
m_ToolView.GetModel = InternalGetModel;
|
||||
m_ToolView.GetController = InternalGetController;
|
||||
this.styleSheets.Add(ResourceLoader.Load<StyleSheet>("SkinningModule/BoneReparentStyle.uss"));
|
||||
}
|
||||
|
||||
IBoneTreeViewModel InternalGetModel()
|
||||
{
|
||||
return GetModel();
|
||||
}
|
||||
|
||||
BoneTreeWidgetController InternalGetController()
|
||||
{
|
||||
return GetController();
|
||||
}
|
||||
|
||||
public void OnBoneSelectionChange(SkeletonSelection skeleton)
|
||||
{
|
||||
((IBoneVisibilityToolView)toolView).OnBoneSelectionChange(skeleton);
|
||||
}
|
||||
|
||||
public void OnBoneExpandedChange(BoneCache[] bones)
|
||||
{
|
||||
((IBoneVisibilityToolView)toolView).OnBoneExpandedChange(bones);
|
||||
}
|
||||
|
||||
public void OnBoneNameChanged(BoneCache bone)
|
||||
{
|
||||
((IBoneVisibilityToolView)toolView).OnBoneNameChanged(bone);
|
||||
}
|
||||
|
||||
public void OnSelectionChange(SkeletonCache skeleton)
|
||||
{
|
||||
((IBoneVisibilityToolView)toolView).OnSelectionChange(skeleton);
|
||||
}
|
||||
|
||||
BoneReparentToolView toolView { get {return m_ToolView; } }
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
toolView.Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
internal class BoneReparentToolView : BoneVisibilityToolView
|
||||
{
|
||||
public class CustomUxmlFactory : UxmlFactory<BoneReparentToolView, CustomUxmlTraits> {}
|
||||
public class CustomUxmlTraits : UxmlTraits {}
|
||||
|
||||
protected override VisibilityToolColumnHeader SetupToolColumnHeader()
|
||||
{
|
||||
var columns = new MultiColumnHeaderState.Column[3];
|
||||
columns[0] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = VisibilityTreeViewBase.VisibilityIconStyle.visibilityOnIcon,
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 32,
|
||||
minWidth = 32,
|
||||
maxWidth = 32,
|
||||
autoResize = false,
|
||||
allowToggleVisibility = true
|
||||
};
|
||||
columns[1] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = EditorGUIUtility.TrTextContent(TextContent.bone),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 130,
|
||||
minWidth = 130,
|
||||
autoResize = true,
|
||||
allowToggleVisibility = false
|
||||
};
|
||||
|
||||
columns[2] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = EditorGUIUtility.TrTextContent(TextContent.depth),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 50,
|
||||
minWidth = 50,
|
||||
maxWidth = 50,
|
||||
autoResize = true,
|
||||
allowToggleVisibility = true
|
||||
};
|
||||
var multiColumnHeaderState = new MultiColumnHeaderState(columns);
|
||||
return new VisibilityToolColumnHeader(multiColumnHeaderState)
|
||||
{
|
||||
GetAllVisibility = GetAllVisibility,
|
||||
SetAllVisibility = SetAllVisibility,
|
||||
canSort = false,
|
||||
height = 20,
|
||||
visibilityColumn = 0
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,280 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal class BoneTreeWidgetController
|
||||
{
|
||||
protected IBoneTreeViewModel m_Model;
|
||||
protected SkinningEvents m_SkinningEvents;
|
||||
|
||||
public BoneTreeWidgetController(IBoneTreeViewModel model, SkinningEvents eventSystem)
|
||||
{
|
||||
m_Model = model;
|
||||
m_SkinningEvents = eventSystem;
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
SetupSkeleton();
|
||||
|
||||
m_SkinningEvents.selectedSpriteChanged.AddListener(OnSelectionChange);
|
||||
m_SkinningEvents.skinningModeChanged.AddListener(OnSkinningModuleModeChanged);
|
||||
m_SkinningEvents.boneSelectionChanged.AddListener(OnBoneSelectionChanged);
|
||||
m_SkinningEvents.boneNameChanged.AddListener(OnBoneNameChanged);
|
||||
m_SkinningEvents.skeletonTopologyChanged.AddListener(SkeletonTopologyChanged);
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
m_SkinningEvents.selectedSpriteChanged.RemoveListener(OnSelectionChange);
|
||||
m_SkinningEvents.skinningModeChanged.RemoveListener(OnSkinningModuleModeChanged);
|
||||
m_SkinningEvents.boneSelectionChanged.RemoveListener(OnBoneSelectionChanged);
|
||||
m_SkinningEvents.boneNameChanged.RemoveListener(OnBoneNameChanged);
|
||||
m_SkinningEvents.skeletonTopologyChanged.RemoveListener(SkeletonTopologyChanged);
|
||||
if (m_Model.view != null)
|
||||
m_Model.view.Deactivate();
|
||||
}
|
||||
|
||||
private void OnSelectionChange(SpriteCache sprite)
|
||||
{
|
||||
SetupSkeleton();
|
||||
m_Model.SetAllVisibility(null, true);
|
||||
}
|
||||
|
||||
private void OnBoneSelectionChanged()
|
||||
{
|
||||
m_Model.view.OnBoneSelectionChange(m_Model.GetBoneSelection());
|
||||
}
|
||||
|
||||
private void OnBoneNameChanged(BoneCache bone)
|
||||
{
|
||||
m_Model.view.OnBoneNameChanged(bone);
|
||||
}
|
||||
|
||||
private void OnSkinningModuleModeChanged(SkinningMode mode)
|
||||
{
|
||||
SetupSkeleton();
|
||||
m_Model.SetAllVisibility(null, true);
|
||||
}
|
||||
|
||||
private void SetupSkeleton()
|
||||
{
|
||||
m_Model.view.OnSelectionChange(m_Model.GetSelectedSkeleton());
|
||||
m_Model.view.OnBoneExpandedChange(m_Model.GetExpandedBones());
|
||||
m_Model.view.OnBoneSelectionChange(m_Model.GetBoneSelection());
|
||||
}
|
||||
|
||||
public void SetAllVisibility(bool visibility)
|
||||
{
|
||||
var skeleton = m_Model.GetSelectedSkeleton();
|
||||
if (skeleton != null)
|
||||
{
|
||||
using (m_Model.UndoScope(TextContent.boneVisibility))
|
||||
{
|
||||
m_Model.SetAllVisibility(skeleton, visibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SkeletonTopologyChanged(SkeletonCache skeleton)
|
||||
{
|
||||
m_Model.view.OnSelectionChange(skeleton);
|
||||
}
|
||||
|
||||
public List<TreeViewItem> BuildTreeView()
|
||||
{
|
||||
var rows = new List<TreeViewItem>();
|
||||
var skeleton = m_Model.GetSelectedSkeleton();
|
||||
if (skeleton != null)
|
||||
{
|
||||
var bones = skeleton.bones;
|
||||
var children = bones.Where(x => x.parentBone == null).ToArray();
|
||||
Array.Sort(children, (a, b) => a.siblingIndex.CompareTo(b.siblingIndex));
|
||||
|
||||
foreach (var bone in children)
|
||||
AddTreeViewItem(rows, bone, bones, 0);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
private static void AddTreeViewItem(IList<TreeViewItem> rows, BoneCache bone, BoneCache[] bones, int depth)
|
||||
{
|
||||
var item = new TreeViewItemBase<BoneCache>(bone.GetInstanceID(), depth, bone.name, bone);
|
||||
rows.Add(item);
|
||||
|
||||
var children = bones.Where(x => x.parentBone == bone).ToArray();
|
||||
Array.Sort(children, (a, b) => a.siblingIndex.CompareTo(b.siblingIndex));
|
||||
|
||||
foreach (var childBone in children)
|
||||
AddTreeViewItem(rows, childBone, bones, depth + 1);
|
||||
}
|
||||
|
||||
public List<int> GetIDsToExpand(BoneCache[] bones)
|
||||
{
|
||||
var result = new List<int>();
|
||||
if (bones != null)
|
||||
{
|
||||
foreach (var bone in bones)
|
||||
{
|
||||
if (bone != null)
|
||||
{
|
||||
var parent = bone.parentBone;
|
||||
while (parent != null)
|
||||
{
|
||||
int parentId = parent.GetInstanceID();
|
||||
result.Add(parentId);
|
||||
parent = parent.parentBone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int[] GetIDsToSelect(BoneCache[] bones)
|
||||
{
|
||||
return bones == null ? new int[0] : Array.ConvertAll(bones, x => x != null ? x.GetInstanceID() : 0);
|
||||
}
|
||||
|
||||
public void SelectBones(IList<int> selectedIds, IList<TreeViewItem> items)
|
||||
{
|
||||
var selectedBones = items.Where(x => selectedIds.Contains(x.id)).Select(y => ((TreeViewItemBase<BoneCache>)y).customData).ToArray();
|
||||
using (m_Model.UndoScope(TextContent.boneSelection))
|
||||
{
|
||||
m_Model.SelectBones(selectedBones);
|
||||
m_SkinningEvents.boneSelectionChanged.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public void ExpandBones(IList<int> expandedIds, IList<TreeViewItem> items)
|
||||
{
|
||||
var expandedBones = items.Where(x => expandedIds.Contains(x.id)).Select(y => ((TreeViewItemBase<BoneCache>)y).customData).ToArray();
|
||||
using (m_Model.UndoScope(TextContent.expandBones))
|
||||
{
|
||||
m_Model.SetExpandedBones(expandedBones);
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetTreeItemVisibility(TreeViewItemBase<BoneCache> item)
|
||||
{
|
||||
return m_Model.GetVisibility(item.customData);
|
||||
}
|
||||
|
||||
public void SetTreeItemVisibility(TreeViewItemBase<BoneCache> item, bool visible, bool includeChildren)
|
||||
{
|
||||
var bone = item.customData;
|
||||
if (bone != null && bone.isVisible != visible)
|
||||
{
|
||||
using (m_Model.UndoScope(TextContent.visibilityChange))
|
||||
{
|
||||
m_Model.SetVisibility(item.customData, visible);
|
||||
if (includeChildren)
|
||||
{
|
||||
// toggle all children as well
|
||||
SetChildrenVisibility(item, visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetChildrenVisibility(TreeViewItemBase<BoneCache> bone, bool visible)
|
||||
{
|
||||
if (bone.children == null)
|
||||
return;
|
||||
foreach (var childBone in bone.children)
|
||||
{
|
||||
var cb = childBone as TreeViewItemBase<BoneCache>;
|
||||
SetChildrenVisibility(cb, visible);
|
||||
m_Model.SetVisibility(cb.customData, visible);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetTreeItemDepthValue(TreeViewItemBase<BoneCache> bone)
|
||||
{
|
||||
return m_Model.GetDepth(bone.customData);
|
||||
}
|
||||
|
||||
public void SetTreeItemDepthValue(TreeViewItemBase<BoneCache> bone, int value)
|
||||
{
|
||||
if (bone != null && bone.customData != null)
|
||||
{
|
||||
using (m_Model.UndoScope(TextContent.boneDepth))
|
||||
{
|
||||
m_Model.SetDepth(bone.customData, value);
|
||||
m_SkinningEvents.boneNameChanged.Invoke(bone.customData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTreeViewBoneName(IList<TreeViewItem> items, BoneCache bone)
|
||||
{
|
||||
var treeBone = items.FirstOrDefault(x => ((TreeViewItemBase<BoneCache>)x).customData == bone);
|
||||
if (treeBone != null)
|
||||
treeBone.displayName = bone.name;
|
||||
}
|
||||
|
||||
public void TreeViewItemRename(IList<TreeViewItem> rows, int itemID, string newName)
|
||||
{
|
||||
var item = rows.FirstOrDefault(x => x.id == itemID) as TreeViewItemBase<BoneCache>;
|
||||
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
if (item.customData != null && item.customData.name != newName && !string.IsNullOrEmpty(newName)
|
||||
&& !string.IsNullOrWhiteSpace(newName))
|
||||
{
|
||||
item.displayName = newName;
|
||||
using (m_Model.UndoScope(TextContent.boneName))
|
||||
{
|
||||
m_Model.SetName(item.customData, newName);
|
||||
m_SkinningEvents.boneNameChanged.Invoke(item.customData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanReparent(TreeViewItemBase<BoneCache> parent, List<TreeViewItem> draggedItems)
|
||||
{
|
||||
TreeViewItemBase<BoneCache> currentParent = parent;
|
||||
while (currentParent != null)
|
||||
{
|
||||
if (draggedItems.Contains(currentParent))
|
||||
return false;
|
||||
currentParent = currentParent.parent as TreeViewItemBase<BoneCache>;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ReparentItems(TreeViewItemBase<BoneCache> newParent, List<TreeViewItem> draggedItems, int insertAtIndex)
|
||||
{
|
||||
if ((m_Model.hasCharacter && m_Model.mode != SkinningMode.Character) ||
|
||||
(!m_Model.hasCharacter && m_Model.mode == SkinningMode.Character))
|
||||
return;
|
||||
|
||||
var parent = newParent != null ? newParent.customData : null;
|
||||
using (m_Model.UndoScope(TextContent.setParentBone))
|
||||
{
|
||||
for (var i = draggedItems.Count - 1; i >= 0; --i)
|
||||
{
|
||||
var bone = ((TreeViewItemBase<BoneCache>)draggedItems[i]).customData;
|
||||
m_Model.SetBoneParent(parent, bone, insertAtIndex);
|
||||
m_SkinningEvents.skeletonTopologyChanged.Invoke(bone.skeleton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool CanDrag()
|
||||
{
|
||||
m_SkinningEvents.boneVisibility.Invoke("drag");
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool CanRename()
|
||||
{
|
||||
m_SkinningEvents.boneVisibility.Invoke("rename");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,175 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal class BoneVisibilityToolData : CacheObject
|
||||
{
|
||||
[SerializeField]
|
||||
bool m_AllVisibility = true;
|
||||
bool m_PreviousVisibility = true;
|
||||
|
||||
public bool allVisibility
|
||||
{
|
||||
get { return m_AllVisibility; }
|
||||
set { m_AllVisibility = value; }
|
||||
}
|
||||
public bool previousVisiblity
|
||||
{
|
||||
get { return m_PreviousVisibility; }
|
||||
set { m_PreviousVisibility = value; }
|
||||
}
|
||||
}
|
||||
|
||||
internal class BoneTreeWidgetModel : IBoneTreeViewModel
|
||||
{
|
||||
protected SkinningCache m_SkinningCache;
|
||||
protected IBoneVisibilityToolView m_View;
|
||||
protected BoneVisibilityToolData m_Data;
|
||||
|
||||
public SkinningCache skinningCache
|
||||
{
|
||||
get { return m_SkinningCache; }
|
||||
}
|
||||
|
||||
public IBoneVisibilityToolView view
|
||||
{
|
||||
get { return m_View; }
|
||||
}
|
||||
|
||||
public virtual bool GetAllVisibility()
|
||||
{
|
||||
return m_Data.allVisibility;
|
||||
}
|
||||
|
||||
public SkeletonSelection GetBoneSelection()
|
||||
{
|
||||
return skinningCache.skeletonSelection;
|
||||
}
|
||||
|
||||
public BoneCache[] GetExpandedBones()
|
||||
{
|
||||
return skinningCache.GetExpandedBones();
|
||||
}
|
||||
|
||||
public int GetDepth(BoneCache bone)
|
||||
{
|
||||
return (int)bone.depth;
|
||||
}
|
||||
|
||||
public SkeletonCache GetSelectedSkeleton()
|
||||
{
|
||||
return skinningCache.GetEffectiveSkeleton(skinningCache.selectedSprite);
|
||||
}
|
||||
|
||||
public bool GetVisibility(BoneCache bone)
|
||||
{
|
||||
return bone.isVisible;
|
||||
}
|
||||
|
||||
public void SelectBones(BoneCache[] bones)
|
||||
{
|
||||
skinningCache.skeletonSelection.elements = bones.ToCharacterIfNeeded();
|
||||
}
|
||||
|
||||
public void SetExpandedBones(BoneCache[] bones)
|
||||
{
|
||||
skinningCache.BoneExpansionChanged(bones);
|
||||
}
|
||||
|
||||
public virtual void SetAllVisibility(SkeletonCache skeleton, bool visibility)
|
||||
{
|
||||
m_Data.allVisibility = visibility;
|
||||
SetAllBoneVisibility(skeleton, visibility);
|
||||
UpdateVisibilityFromPersistentState();
|
||||
}
|
||||
|
||||
public static void SetAllBoneVisibility(SkeletonCache skeleton, bool visibility)
|
||||
{
|
||||
if (skeleton != null)
|
||||
{
|
||||
foreach (var bone in skeleton.bones)
|
||||
bone.isVisible = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBoneParent(BoneCache newParent, BoneCache bone, int insertAtIndex)
|
||||
{
|
||||
TransformCache parent = newParent;
|
||||
|
||||
if (newParent == null)
|
||||
parent = bone.skeleton;
|
||||
|
||||
skinningCache.RestoreBindPose();
|
||||
bone.SetParent(parent, true);
|
||||
|
||||
if (insertAtIndex == -1)
|
||||
insertAtIndex = parent.ChildCount;
|
||||
|
||||
bone.siblingIndex = insertAtIndex;
|
||||
bone.SetDefaultPose();
|
||||
}
|
||||
|
||||
public void SetDepth(BoneCache bone, int depth)
|
||||
{
|
||||
var characterBone = bone.ToCharacterIfNeeded();
|
||||
characterBone.depth = depth;
|
||||
|
||||
if (characterBone != bone || skinningCache.mode == SkinningMode.Character)
|
||||
skinningCache.SyncSpriteSheetSkeletons();
|
||||
|
||||
skinningCache.events.boneDepthChanged.Invoke(bone);
|
||||
}
|
||||
|
||||
public void SetName(BoneCache bone, string name)
|
||||
{
|
||||
var characterBone = bone.ToCharacterIfNeeded();
|
||||
characterBone.name = name;
|
||||
if (characterBone != bone || skinningCache.mode == SkinningMode.Character)
|
||||
{
|
||||
skinningCache.SyncSpriteSheetSkeletons();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetVisibility(BoneCache bone, bool visibility)
|
||||
{
|
||||
bone.isVisible = visibility;
|
||||
UpdateVisibilityFromPersistentState();
|
||||
}
|
||||
|
||||
public UndoScope UndoScope(string value)
|
||||
{
|
||||
return skinningCache.UndoScope(value);
|
||||
}
|
||||
|
||||
private void UpdateVisibilityFromPersistentState()
|
||||
{
|
||||
skinningCache.BoneVisibilityChanged(GetSelectedSkeleton());
|
||||
}
|
||||
|
||||
public bool hasCharacter {get { return skinningCache.hasCharacter; } }
|
||||
public SkinningMode mode {get { return skinningCache.mode; } }
|
||||
}
|
||||
|
||||
|
||||
internal interface IBoneTreeViewModel
|
||||
{
|
||||
void SetVisibility(BoneCache bone, bool visibility);
|
||||
bool GetVisibility(BoneCache bone);
|
||||
void SetName(BoneCache bone, string name);
|
||||
void SetBoneParent(BoneCache newParent, BoneCache bone, int insertAtIndex);
|
||||
int GetDepth(BoneCache bone);
|
||||
void SetDepth(BoneCache bone, int depth);
|
||||
void SetAllVisibility(SkeletonCache skeleton, bool visibility);
|
||||
bool GetAllVisibility();
|
||||
void SelectBones(BoneCache[] bones);
|
||||
void SetExpandedBones(BoneCache[] bones);
|
||||
IBoneVisibilityToolView view { get; }
|
||||
SkeletonSelection GetBoneSelection();
|
||||
BoneCache[] GetExpandedBones();
|
||||
SkeletonCache GetSelectedSkeleton();
|
||||
bool hasCharacter { get; }
|
||||
SkinningMode mode { get; }
|
||||
UndoScope UndoScope(string value);
|
||||
}
|
||||
}
|
@@ -0,0 +1,350 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal class BoneVisibilityTool : BoneTreeWidgetModel, IVisibilityTool
|
||||
{
|
||||
private BoneTreeWidgetController m_Controller;
|
||||
|
||||
VisualElement IVisibilityTool.view { get { return (VisualElement)m_View; } }
|
||||
public string name { get { return "Bone"; } }
|
||||
public bool isAvailable
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public BoneVisibilityTool(SkinningCache s)
|
||||
{
|
||||
m_SkinningCache = s;
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
m_Data = skinningCache.CreateCache<BoneVisibilityToolData>();
|
||||
m_Controller = new BoneReparentToolController(this, skinningCache.events);//new BoneTreeWidgetController(this, skinningCache.events);
|
||||
m_View = new BoneReparentToolView()
|
||||
{
|
||||
GetModel = () => this,
|
||||
GetController = () => m_Controller
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
m_Controller.Activate();
|
||||
if (m_Data.previousVisiblity != m_Data.allVisibility)
|
||||
{
|
||||
m_Data.previousVisiblity = m_Data.allVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
m_Controller.Deactivate();
|
||||
}
|
||||
|
||||
public void SetAvailabilityChangeCallback(Action callback)
|
||||
{}
|
||||
}
|
||||
|
||||
|
||||
internal class BoneVisibilityToolView : VisibilityToolViewBase, IBoneVisibilityToolView
|
||||
{
|
||||
public Func<BoneTreeWidgetController> GetController = () => null;
|
||||
public Func<IBoneTreeViewModel> GetModel = () => null;
|
||||
|
||||
public BoneVisibilityToolView()
|
||||
{
|
||||
m_TreeView = new BoneTreeView(m_TreeViewState, SetupToolColumnHeader())
|
||||
{
|
||||
GetController = InternalGetController
|
||||
};
|
||||
SetupSearchField();
|
||||
}
|
||||
|
||||
protected virtual VisibilityToolColumnHeader SetupToolColumnHeader()
|
||||
{
|
||||
var columns = new MultiColumnHeaderState.Column[2];
|
||||
columns[0] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = VisibilityTreeViewBase.VisibilityIconStyle.visibilityOnIcon,
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 32,
|
||||
minWidth = 32,
|
||||
maxWidth = 32,
|
||||
autoResize = false,
|
||||
allowToggleVisibility = true
|
||||
};
|
||||
columns[1] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = EditorGUIUtility.TrTextContent(TextContent.bone),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 200,
|
||||
minWidth = 130,
|
||||
autoResize = true,
|
||||
allowToggleVisibility = false
|
||||
};
|
||||
var multiColumnHeaderState = new MultiColumnHeaderState(columns);
|
||||
return new VisibilityToolColumnHeader(multiColumnHeaderState)
|
||||
{
|
||||
GetAllVisibility = GetAllVisibility,
|
||||
SetAllVisibility = SetAllVisibility,
|
||||
canSort = false,
|
||||
height = 20,
|
||||
visibilityColumn = 0
|
||||
};
|
||||
}
|
||||
|
||||
BoneTreeWidgetController InternalGetController()
|
||||
{
|
||||
return GetController();
|
||||
}
|
||||
|
||||
protected void SetAllVisibility(bool visibility)
|
||||
{
|
||||
GetController().SetAllVisibility(visibility);
|
||||
}
|
||||
|
||||
protected bool GetAllVisibility()
|
||||
{
|
||||
return GetModel() != null && GetModel().GetAllVisibility();
|
||||
}
|
||||
|
||||
public void OnSelectionChange(SkeletonCache skeleton)
|
||||
{
|
||||
((BoneTreeView)m_TreeView).SetupHierarchy();
|
||||
}
|
||||
|
||||
public void OnBoneSelectionChange(SkeletonSelection bones)
|
||||
{
|
||||
((BoneTreeView)m_TreeView).OnBoneSelectionChanged(bones);
|
||||
}
|
||||
|
||||
public void OnBoneExpandedChange(BoneCache[] bones)
|
||||
{
|
||||
((BoneTreeView)m_TreeView).OnBoneExpandedChanged(bones);
|
||||
}
|
||||
|
||||
public void OnBoneNameChanged(BoneCache bone)
|
||||
{
|
||||
((BoneTreeView)m_TreeView).OnBoneNameChanged(bone);
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
if (m_TreeView.HasSelection())
|
||||
m_TreeView.EndRename();
|
||||
}
|
||||
}
|
||||
|
||||
class BoneTreeView : VisibilityTreeViewBase
|
||||
{
|
||||
public Func<BoneTreeWidgetController> GetController = () => null;
|
||||
|
||||
public BoneTreeView(TreeViewState treeViewState, MultiColumnHeader columnHeader)
|
||||
: base(treeViewState, columnHeader)
|
||||
{
|
||||
columnIndexForTreeFoldouts = 1;
|
||||
ReloadView();
|
||||
}
|
||||
|
||||
public void SetupHierarchy()
|
||||
{
|
||||
ReloadView();
|
||||
}
|
||||
|
||||
private void ReloadView()
|
||||
{
|
||||
Reload();
|
||||
}
|
||||
|
||||
public void OnBoneSelectionChanged(SkeletonSelection boneSelection)
|
||||
{
|
||||
var bones = boneSelection.elements.ToSpriteSheetIfNeeded();
|
||||
var ids = GetController().GetIDsToSelect(bones);
|
||||
var result = GetController().GetIDsToExpand(bones);
|
||||
var expandIds = GetExpanded().ToList();
|
||||
|
||||
if (result.Count > 0)
|
||||
expandIds = expandIds.Union(result).ToList();
|
||||
SetExpanded(expandIds);
|
||||
SetSelection(ids);
|
||||
}
|
||||
|
||||
public void OnBoneExpandedChanged(BoneCache[] bones)
|
||||
{
|
||||
var expandIds = GetController().GetIDsToSelect(bones);
|
||||
if (expandIds.Length == 0)
|
||||
return;
|
||||
|
||||
SetExpanded(expandIds.Union(GetExpanded()).ToList());
|
||||
}
|
||||
|
||||
public void OnBoneNameChanged(BoneCache bone)
|
||||
{
|
||||
GetController().SetTreeViewBoneName(GetRows(), bone);
|
||||
}
|
||||
|
||||
protected override void SelectionChanged(IList<int> selectedIds)
|
||||
{
|
||||
GetController().SelectBones(selectedIds, GetRows());
|
||||
}
|
||||
|
||||
protected override void ExpandedStateChanged()
|
||||
{
|
||||
GetController().ExpandBones(GetExpanded(), GetRows());
|
||||
}
|
||||
|
||||
protected override float GetCustomRowHeight(int row, TreeViewItem item)
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight * 1.1f;
|
||||
}
|
||||
|
||||
void CellGUI(Rect cellRect, TreeViewItem item, int column, ref RowGUIArgs args)
|
||||
{
|
||||
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||
switch (column)
|
||||
{
|
||||
case 0:
|
||||
DrawVisibilityCell(cellRect, item);
|
||||
break;
|
||||
case 1:
|
||||
DrawNameCell(cellRect, item, ref args);
|
||||
break;
|
||||
case 2:
|
||||
DrawDepthCell(cellRect, item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawDepthCell(Rect cellRect, TreeViewItem item)
|
||||
{
|
||||
var boneItemView = item as TreeViewItemBase<BoneCache>;
|
||||
int depth = GetController().GetTreeItemDepthValue(boneItemView);
|
||||
const int width = 30;
|
||||
cellRect.height = EditorGUIUtility.singleLineHeight;
|
||||
cellRect.x += (cellRect.width - width) * 0.5f;
|
||||
cellRect.width = width;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
depth = EditorGUI.IntField(cellRect, depth);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
GetController().SetTreeItemDepthValue(boneItemView, depth);
|
||||
}
|
||||
|
||||
void DrawVisibilityCell(Rect cellRect, TreeViewItem item)
|
||||
{
|
||||
GUIStyle style = MultiColumnHeader.DefaultStyles.columnHeaderCenterAligned;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var boneItemView = item as TreeViewItemBase<BoneCache>;
|
||||
bool visible = GetController().GetTreeItemVisibility(boneItemView);
|
||||
visible = GUI.Toggle(cellRect, visible, visible ? VisibilityIconStyle.visibilityOnIcon : VisibilityIconStyle.visibilityOffIcon, style);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
GetController().SetTreeItemVisibility(boneItemView, visible, Event.current.alt);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawNameCell(Rect cellRect, TreeViewItem item, ref RowGUIArgs args)
|
||||
{
|
||||
args.rowRect = cellRect;
|
||||
base.RowGUI(args);
|
||||
}
|
||||
|
||||
protected override Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item)
|
||||
{
|
||||
Rect cellRect = GetCellRectForTreeFoldouts(rowRect);
|
||||
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||
return base.GetRenameRect(cellRect, row, item);
|
||||
}
|
||||
|
||||
protected override void RowGUI(RowGUIArgs args)
|
||||
{
|
||||
var item = args.item;
|
||||
|
||||
for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
|
||||
{
|
||||
CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);
|
||||
}
|
||||
}
|
||||
|
||||
protected override TreeViewItem BuildRoot()
|
||||
{
|
||||
var root = new TreeViewItem {id = 0, depth = -1, displayName = "Root"};
|
||||
List<TreeViewItem> rows = GetController() != null ? GetController().BuildTreeView() : new List<TreeViewItem>();
|
||||
SetupParentsAndChildrenFromDepths(root, rows);
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override bool CanRename(TreeViewItem item)
|
||||
{
|
||||
return GetController().CanRename();
|
||||
}
|
||||
|
||||
protected override void RenameEnded(RenameEndedArgs args)
|
||||
{
|
||||
var rows = GetRows();
|
||||
GetController().TreeViewItemRename(rows, args.itemID, args.newName);
|
||||
base.RenameEnded(args);
|
||||
}
|
||||
|
||||
// dragging
|
||||
const string k_GenericDragID = "GenericDragColumnDragging";
|
||||
protected override bool CanStartDrag(CanStartDragArgs args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void SetupDragAndDrop(SetupDragAndDropArgs args)
|
||||
{
|
||||
if (GetController().CanDrag() && !hasSearch)
|
||||
{
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
var draggedRows = GetRows().Where(item => args.draggedItemIDs.Contains(item.id)).ToList();
|
||||
DragAndDrop.SetGenericData(k_GenericDragID, draggedRows);
|
||||
DragAndDrop.objectReferences = new UnityEngine.Object[] {}; // this IS required for dragging to work
|
||||
string title = draggedRows.Count == 1 ? draggedRows[0].displayName : "< Multiple >";
|
||||
DragAndDrop.StartDrag(title);
|
||||
}
|
||||
}
|
||||
|
||||
protected override DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args)
|
||||
{
|
||||
// Check if we can handle the current drag data (could be dragged in from other areas/windows in the editor)
|
||||
var draggedRows = DragAndDrop.GetGenericData(k_GenericDragID) as List<TreeViewItem>;
|
||||
if (draggedRows == null)
|
||||
return DragAndDropVisualMode.None;
|
||||
|
||||
// Parent item is null when dragging outside any tree view items.
|
||||
switch (args.dragAndDropPosition)
|
||||
{
|
||||
case DragAndDropPosition.UponItem:
|
||||
case DragAndDropPosition.OutsideItems:
|
||||
case DragAndDropPosition.BetweenItems:
|
||||
{
|
||||
var newParent = args.parentItem as TreeViewItemBase<BoneCache>;
|
||||
bool validDrag = false;
|
||||
validDrag = GetController().CanReparent(newParent, draggedRows);
|
||||
if (args.performDrop && validDrag)
|
||||
{
|
||||
GetController().ReparentItems(newParent, draggedRows, args.insertAtIndex);
|
||||
Reload();
|
||||
var selectedIDs = draggedRows.ConvertAll(b => b.id);
|
||||
SetSelection(selectedIDs, TreeViewSelectionOptions.RevealAndFrame);
|
||||
SelectionChanged(selectedIDs);
|
||||
}
|
||||
return validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
return DragAndDropVisualMode.None;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal interface IBoneVisibilityToolView
|
||||
{
|
||||
void OnBoneSelectionChange(SkeletonSelection skeleton);
|
||||
void OnBoneExpandedChange(BoneCache[] bones);
|
||||
void OnBoneNameChanged(BoneCache bone);
|
||||
void OnSelectionChange(SkeletonCache skeleton);
|
||||
void Deactivate();
|
||||
}
|
||||
}
|
@@ -0,0 +1,345 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal class MeshVisibilityTool : IVisibilityTool
|
||||
{
|
||||
private MeshVisibilityToolView m_View;
|
||||
private MeshVisibilityToolModel m_Model;
|
||||
private SkinningCache m_SkinningCache;
|
||||
public SkinningCache skinningCache { get { return m_SkinningCache; } }
|
||||
|
||||
public MeshVisibilityTool(SkinningCache s)
|
||||
{
|
||||
m_SkinningCache = s;
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
m_Model = skinningCache.CreateCache<MeshVisibilityToolModel>();
|
||||
m_View = new MeshVisibilityToolView(skinningCache)
|
||||
{
|
||||
GetModel = () => m_Model,
|
||||
SetAllVisibility = SetAllVisibility,
|
||||
GetAllVisibility = GetAllVisibility
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public VisualElement view { get { return m_View; } }
|
||||
public string name { get { return "Mesh"; } }
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
skinningCache.events.selectedSpriteChanged.AddListener(OnSelectionChange);
|
||||
skinningCache.events.skinningModeChanged.AddListener(OnViewModeChanged);
|
||||
OnViewModeChanged(skinningCache.mode);
|
||||
if (m_Model.previousVisiblity != m_Model.allVisibility)
|
||||
{
|
||||
SetAllMeshVisibility();
|
||||
m_Model.previousVisiblity = m_Model.allVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
skinningCache.events.selectedSpriteChanged.RemoveListener(OnSelectionChange);
|
||||
skinningCache.events.skinningModeChanged.RemoveListener(OnViewModeChanged);
|
||||
}
|
||||
|
||||
public bool isAvailable
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SetAvailabilityChangeCallback(Action callback)
|
||||
{}
|
||||
|
||||
private void OnViewModeChanged(SkinningMode characterMode)
|
||||
{
|
||||
if (characterMode == SkinningMode.Character)
|
||||
{
|
||||
m_View.Setup(skinningCache.GetSprites());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_View.Setup(new[] { skinningCache.selectedSprite });
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSelectionChange(SpriteCache sprite)
|
||||
{
|
||||
OnViewModeChanged(skinningCache.mode);
|
||||
SetAllMeshVisibility();
|
||||
}
|
||||
|
||||
void SetAllVisibility(bool visibility)
|
||||
{
|
||||
using (skinningCache.UndoScope(TextContent.meshVisibility))
|
||||
{
|
||||
m_Model.allVisibility = visibility;
|
||||
SetAllMeshVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void SetAllMeshVisibility()
|
||||
{
|
||||
SpriteCache[] sprites;
|
||||
if (skinningCache.mode == SkinningMode.Character)
|
||||
sprites = skinningCache.GetSprites();
|
||||
else
|
||||
sprites = new[] { skinningCache.selectedSprite };
|
||||
|
||||
foreach (var spr in sprites)
|
||||
{
|
||||
if (spr != null)
|
||||
m_Model.SetMeshVisibility(spr, m_Model.allVisibility);
|
||||
}
|
||||
}
|
||||
|
||||
bool GetAllVisibility()
|
||||
{
|
||||
return m_Model.allVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
internal class MeshVisibilityToolModel : SkinningObject
|
||||
{
|
||||
[SerializeField]
|
||||
bool m_AllVisibility = true;
|
||||
bool m_PreviousVisibility = true;
|
||||
|
||||
public bool allVisibility
|
||||
{
|
||||
get {return m_AllVisibility; }
|
||||
set { m_AllVisibility = value; }
|
||||
}
|
||||
|
||||
public void SetMeshVisibility(SpriteCache sprite, bool visibility)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool GetMeshVisibility(SpriteCache sprite)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ShouldDisable(SpriteCache sprite)
|
||||
{
|
||||
var mesh = sprite.GetMesh();
|
||||
return mesh == null || mesh.vertices.Count == 0;
|
||||
}
|
||||
|
||||
public bool previousVisiblity
|
||||
{
|
||||
get { return m_PreviousVisibility; }
|
||||
set { m_PreviousVisibility = value; }
|
||||
}
|
||||
}
|
||||
|
||||
internal class MeshVisibilityToolView : VisibilityToolViewBase
|
||||
{
|
||||
public Func<MeshVisibilityToolModel> GetModel = () => null;
|
||||
public Action<bool> SetAllVisibility = (b) => {};
|
||||
public Func<bool> GetAllVisibility = () => true;
|
||||
public SkinningCache skinningCache { get; set; }
|
||||
|
||||
public MeshVisibilityToolView(SkinningCache s)
|
||||
{
|
||||
skinningCache = s;
|
||||
var columns = new MultiColumnHeaderState.Column[2];
|
||||
columns[0] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = EditorGUIUtility.TrTextContent(TextContent.name),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 200,
|
||||
minWidth = 130,
|
||||
autoResize = true,
|
||||
allowToggleVisibility = false
|
||||
};
|
||||
columns[1] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = new GUIContent(EditorGUIUtility.FindTexture("visibilityOn")),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 32,
|
||||
minWidth = 32,
|
||||
maxWidth = 32,
|
||||
autoResize = false,
|
||||
allowToggleVisibility = true
|
||||
};
|
||||
var multiColumnHeaderState = new MultiColumnHeaderState(columns);
|
||||
var multiColumnHeader = new VisibilityToolColumnHeader(multiColumnHeaderState)
|
||||
{
|
||||
GetAllVisibility = InternalGetAllVisibility,
|
||||
SetAllVisibility = InternalSetAllVisibility,
|
||||
canSort = false,
|
||||
height = 20,
|
||||
visibilityColumn = 1
|
||||
};
|
||||
m_TreeView = new MeshTreeView(m_TreeViewState, multiColumnHeader)
|
||||
{
|
||||
GetModel = InternalGetModel
|
||||
};
|
||||
SetupSearchField();
|
||||
}
|
||||
|
||||
MeshVisibilityToolModel InternalGetModel()
|
||||
{
|
||||
return GetModel();
|
||||
}
|
||||
|
||||
public void Setup(SpriteCache[] sprites)
|
||||
{
|
||||
((MeshTreeView)m_TreeView).Setup(sprites);
|
||||
((MeshTreeView)m_TreeView).SetSelection(skinningCache.selectedSprite);
|
||||
}
|
||||
|
||||
bool InternalGetAllVisibility()
|
||||
{
|
||||
return GetAllVisibility();
|
||||
}
|
||||
|
||||
void InternalSetAllVisibility(bool visibility)
|
||||
{
|
||||
SetAllVisibility(visibility);
|
||||
}
|
||||
}
|
||||
|
||||
class MeshTreeView : VisibilityTreeViewBase
|
||||
{
|
||||
private List<SpriteCache> m_Sprites = new List<SpriteCache>();
|
||||
|
||||
public MeshTreeView(TreeViewState treeViewState, MultiColumnHeader header)
|
||||
: base(treeViewState, header)
|
||||
{
|
||||
this.showAlternatingRowBackgrounds = true;
|
||||
this.useScrollView = true;
|
||||
Reload();
|
||||
}
|
||||
|
||||
public Func<MeshVisibilityToolModel> GetModel = () => null;
|
||||
|
||||
public void Setup(SpriteCache[] sprites)
|
||||
{
|
||||
m_Sprites.Clear();
|
||||
m_Sprites.AddRange(sprites);
|
||||
Reload();
|
||||
}
|
||||
|
||||
private static TreeViewItem CreateTreeViewItem(SpriteCache part)
|
||||
{
|
||||
return new TreeViewItemBase<SpriteCache>(part.GetInstanceID(), -1, part.name, part);
|
||||
}
|
||||
|
||||
private void AddTreeViewItem(IList<TreeViewItem> rows, SpriteCache part)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchString) || part.name.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
var item = CreateTreeViewItem(part);
|
||||
rows.Add(item);
|
||||
rootItem.AddChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void CellGUI(Rect cellRect, TreeViewItem item, int column, ref RowGUIArgs args)
|
||||
{
|
||||
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||
switch (column)
|
||||
{
|
||||
case 0:
|
||||
DrawNameCell(cellRect, item, ref args);
|
||||
break;
|
||||
case 1:
|
||||
DrawVisibilityCell(cellRect, item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVisibilityCell(Rect cellRect, TreeViewItem item)
|
||||
{
|
||||
GUIStyle style = MultiColumnHeader.DefaultStyles.columnHeaderCenterAligned;
|
||||
var itemView = item as TreeViewItemBase<SpriteCache>;
|
||||
var shouldDisable = GetModel().ShouldDisable(itemView.customData);
|
||||
using (new EditorGUI.DisabledScope(shouldDisable))
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool visible = GetModel().GetMeshVisibility(itemView.customData);
|
||||
visible = GUI.Toggle(cellRect, visible, visible ? VisibilityIconStyle.visibilityOnIcon : VisibilityIconStyle.visibilityOffIcon, style);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
GetModel().SetMeshVisibility(itemView.customData, visible);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawNameCell(Rect cellRect, TreeViewItem item, ref RowGUIArgs args)
|
||||
{
|
||||
args.rowRect = cellRect;
|
||||
base.RowGUI(args);
|
||||
}
|
||||
|
||||
protected override void RowGUI(RowGUIArgs args)
|
||||
{
|
||||
var item = args.item;
|
||||
|
||||
for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
|
||||
{
|
||||
CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SelectionChanged(IList<int> selectedIds)
|
||||
{
|
||||
SpriteCache newSelected = null;
|
||||
if (selectedIds.Count > 0)
|
||||
{
|
||||
var selected = GetRows().FirstOrDefault(x => ((TreeViewItemBase<SpriteCache>)x).customData.GetInstanceID() == selectedIds[0]) as TreeViewItemBase<SpriteCache>;
|
||||
if (selected != null)
|
||||
newSelected = selected.customData;
|
||||
}
|
||||
|
||||
var skinningCache = newSelected.skinningCache;
|
||||
|
||||
using (skinningCache.UndoScope(TextContent.selectionChange))
|
||||
{
|
||||
skinningCache.events.selectedSpriteChanged.Invoke(newSelected);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSelection(SpriteCache sprite)
|
||||
{
|
||||
var rows = GetRows();
|
||||
for (int i = 0; rows != null && i < rows.Count; ++i)
|
||||
{
|
||||
var r = (TreeViewItemBase<SpriteCache>)rows[i];
|
||||
if (r.customData == sprite)
|
||||
{
|
||||
SetSelection(new[] { r.customData.GetInstanceID() }, TreeViewSelectionOptions.RevealAndFrame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override IList<TreeViewItem> BuildRows(TreeViewItem root)
|
||||
{
|
||||
var rows = GetRows() ?? new List<TreeViewItem>(200);
|
||||
rows.Clear();
|
||||
|
||||
m_Sprites.RemoveAll(s => s == null);
|
||||
|
||||
foreach (var sprite in m_Sprites)
|
||||
AddTreeViewItem(rows, sprite);
|
||||
|
||||
SetupDepthsFromParentsAndChildren(root);
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,598 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal interface ISpriteVisibilityToolModel
|
||||
{
|
||||
ISpriteVisibilityToolView view { get; }
|
||||
CharacterCache character { get; }
|
||||
bool previousVisibility { get; set; }
|
||||
bool allVisibility { get; set; }
|
||||
SkinningMode mode { get; }
|
||||
bool hasCharacter { get; }
|
||||
UndoScope UndoScope(string description);
|
||||
SpriteCache selectedSprite { get; }
|
||||
}
|
||||
|
||||
internal interface ISpriteVisibilityToolView
|
||||
{
|
||||
void Setup();
|
||||
void SetSelection(SpriteCache sprite);
|
||||
void SetSelectionIds(IList<int> selectedIds);
|
||||
}
|
||||
|
||||
internal class SpriteVisibilityToolData : CacheObject
|
||||
{
|
||||
[SerializeField]
|
||||
bool m_AllVisibility = true;
|
||||
bool m_PreviousVisibility = true;
|
||||
|
||||
public bool allVisibility
|
||||
{
|
||||
get { return m_AllVisibility; }
|
||||
set { m_PreviousVisibility = m_AllVisibility = value; }
|
||||
}
|
||||
|
||||
public bool previousVisibility
|
||||
{
|
||||
get { return m_PreviousVisibility; }
|
||||
set { m_PreviousVisibility = value; }
|
||||
}
|
||||
}
|
||||
|
||||
internal class SpriteVisibilityToolController
|
||||
{
|
||||
bool m_UpdateViewOnSelection = true;
|
||||
|
||||
internal interface ISpriteVisibilityItem
|
||||
{
|
||||
bool visibility { get; set; }
|
||||
ICharacterOrder characterOrder { get;}
|
||||
}
|
||||
|
||||
internal class SpriteVisibilityGroupItem : ISpriteVisibilityItem
|
||||
{
|
||||
public CharacterGroupCache group;
|
||||
public ISpriteVisibilityItem[] childItems;
|
||||
bool ISpriteVisibilityItem.visibility
|
||||
{
|
||||
get { return group.isVisible; }
|
||||
set
|
||||
{
|
||||
if (childItems != null)
|
||||
{
|
||||
foreach (var item in childItems)
|
||||
item.visibility = value;
|
||||
}
|
||||
group.isVisible = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ICharacterOrder characterOrder { get { return group; } }
|
||||
}
|
||||
|
||||
internal class SpriteVisibilitySpriteItem : ISpriteVisibilityItem
|
||||
{
|
||||
public CharacterPartCache sprite;
|
||||
bool ISpriteVisibilityItem.visibility
|
||||
{
|
||||
get { return sprite.isVisible; }
|
||||
set { sprite.isVisible = value; }
|
||||
}
|
||||
public ICharacterOrder characterOrder { get { return sprite; } }
|
||||
}
|
||||
|
||||
ISpriteVisibilityToolModel m_Model;
|
||||
SkinningEvents m_Events;
|
||||
public event Action OnAvailabilityChangeListeners = () => {};
|
||||
|
||||
public SpriteVisibilityToolController(ISpriteVisibilityToolModel model, SkinningEvents events)
|
||||
{
|
||||
m_Model = model;
|
||||
m_Events = events;
|
||||
m_Events.skinningModeChanged.AddListener(OnViewModeChanged);
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
m_Events.selectedSpriteChanged.AddListener(OnSpriteSelectedChanged);
|
||||
m_Model.view.Setup();
|
||||
m_Model.view.SetSelection(m_Model.selectedSprite);
|
||||
if (m_Model.previousVisibility != m_Model.allVisibility)
|
||||
{
|
||||
SetAllCharacterSpriteVisibility();
|
||||
m_Model.previousVisibility = m_Model.allVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
m_Events.selectedSpriteChanged.RemoveListener(OnSpriteSelectedChanged);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
m_Events.skinningModeChanged.RemoveListener(OnViewModeChanged);
|
||||
}
|
||||
|
||||
void OnViewModeChanged(SkinningMode mode)
|
||||
{
|
||||
OnAvailabilityChangeListeners();
|
||||
if (isAvailable && m_Model.previousVisibility != m_Model.allVisibility)
|
||||
SetAllCharacterSpriteVisibility();
|
||||
}
|
||||
|
||||
private void OnSpriteSelectedChanged(SpriteCache sprite)
|
||||
{
|
||||
if (m_UpdateViewOnSelection)
|
||||
m_Model.view.SetSelection(sprite);
|
||||
m_UpdateViewOnSelection = true;
|
||||
}
|
||||
|
||||
public bool isAvailable
|
||||
{
|
||||
get { return m_Model.mode == SkinningMode.Character; }
|
||||
}
|
||||
|
||||
void SetAllCharacterSpriteVisibility()
|
||||
{
|
||||
if (m_Model.hasCharacter)
|
||||
{
|
||||
using (m_Model.UndoScope(TextContent.spriteVisibility))
|
||||
{
|
||||
var parts = m_Model.character.parts;
|
||||
|
||||
foreach (var part in parts)
|
||||
part.isVisible = m_Model.allVisibility;
|
||||
|
||||
var groups = m_Model.character.groups;
|
||||
foreach (var group in groups)
|
||||
group.isVisible = m_Model.allVisibility;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAllVisibility(bool visibility)
|
||||
{
|
||||
using (m_Model.UndoScope(TextContent.spriteVisibility))
|
||||
{
|
||||
m_Model.allVisibility = visibility;
|
||||
SetAllCharacterSpriteVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetAllVisibility()
|
||||
{
|
||||
return m_Model.allVisibility;
|
||||
}
|
||||
|
||||
public List<TreeViewItem> BuildTreeView()
|
||||
{
|
||||
var rows = new List<TreeViewItem>();
|
||||
var character = m_Model.character;
|
||||
if (character != null)
|
||||
{
|
||||
var parts = character.parts;
|
||||
var groups = character.groups;
|
||||
var items = CreateTreeGroup(-1, groups, parts, 0);
|
||||
foreach (var item in items)
|
||||
rows.Add(item);
|
||||
var groupParts = parts.Where(x => x.parentGroup < 0);
|
||||
foreach (var part in groupParts)
|
||||
{
|
||||
var ii = CreateTreeViewItem(part, groups, 0);
|
||||
rows.Add(ii);
|
||||
}
|
||||
}
|
||||
rows.Sort((x, y) =>
|
||||
{
|
||||
var x1 = (TreeViewItemBase<ISpriteVisibilityItem>)x;
|
||||
var y1 = (TreeViewItemBase<ISpriteVisibilityItem>)y;
|
||||
return SpriteVisibilityItemOrderSort(x1.customData, y1.customData);
|
||||
});
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
int SpriteVisibilityItemOrderSort(ISpriteVisibilityItem x, ISpriteVisibilityItem y)
|
||||
{
|
||||
return x.characterOrder.order.CompareTo(y.characterOrder.order);
|
||||
}
|
||||
|
||||
private List<TreeViewItem> CreateTreeGroup(int level, CharacterGroupCache[] groups, CharacterPartCache[] parts, int depth)
|
||||
{
|
||||
var items = new List<TreeViewItem>();
|
||||
for (int j = 0; j < groups.Length; ++j)
|
||||
{
|
||||
if (groups[j].parentGroup == level)
|
||||
{
|
||||
var item = new TreeViewItemBase<ISpriteVisibilityItem>(groups[j].GetInstanceID(), depth, groups[j].name, new SpriteVisibilityGroupItem()
|
||||
{
|
||||
group = groups[j],
|
||||
});
|
||||
items.Add(item);
|
||||
var children = new List<ISpriteVisibilityItem>();
|
||||
// find all sprite that has this group
|
||||
var groupParts = parts.Where(x => x.parentGroup == j);
|
||||
foreach (var part in groupParts)
|
||||
{
|
||||
var ii = CreateTreeViewItem(part, groups, depth + 1);
|
||||
items.Add(ii);
|
||||
var visibilityItem = ii as TreeViewItemBase<ISpriteVisibilityItem>;
|
||||
if (visibilityItem != null)
|
||||
children.Add(visibilityItem.customData);
|
||||
}
|
||||
|
||||
var childItemes = CreateTreeGroup(j, groups, parts, depth + 1);
|
||||
foreach (var iii in childItemes)
|
||||
{
|
||||
items.Add(iii);
|
||||
var visibilityItem = iii as TreeViewItemBase<ISpriteVisibilityItem>;
|
||||
if (visibilityItem != null)
|
||||
children.Add(visibilityItem.customData);
|
||||
}
|
||||
(item.customData as SpriteVisibilityGroupItem).childItems = children.ToArray();
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private TreeViewItem CreateTreeViewItem(CharacterPartCache part, CharacterGroupCache[] groups, int depth)
|
||||
{
|
||||
var name = part.sprite.name;
|
||||
return new TreeViewItemBase<ISpriteVisibilityItem>(part.sprite.GetInstanceID(), depth, name,
|
||||
new SpriteVisibilitySpriteItem()
|
||||
{
|
||||
sprite = part,
|
||||
});
|
||||
}
|
||||
|
||||
public bool GetCharacterPartVisibility(TreeViewItem item)
|
||||
{
|
||||
var i = item as TreeViewItemBase<ISpriteVisibilityItem>;
|
||||
if (i != null)
|
||||
return i.customData.visibility;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetCharacterPartVisibility(TreeViewItem item, bool visible, bool isolate)
|
||||
{
|
||||
var i = item as TreeViewItemBase<ISpriteVisibilityItem>;
|
||||
if (i != null)
|
||||
{
|
||||
var characterPart = i.customData;
|
||||
var character = m_Model.character;
|
||||
using (m_Model.UndoScope(TextContent.spriteVisibility))
|
||||
{
|
||||
if (isolate)
|
||||
{
|
||||
foreach (var cpart in character.parts)
|
||||
{
|
||||
cpart.isVisible = visible;
|
||||
}
|
||||
characterPart.visibility = !visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
characterPart.visibility = visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSelectedSprite(IList<TreeViewItem> rows, IList<int> selectedIds)
|
||||
{
|
||||
SpriteCache newSelected = null;
|
||||
if (selectedIds.Count > 0)
|
||||
{
|
||||
var selected = rows.FirstOrDefault(x =>
|
||||
{
|
||||
var item = ((TreeViewItemBase<ISpriteVisibilityItem>)x).customData as SpriteVisibilitySpriteItem;
|
||||
if (item != null && item.sprite.sprite.GetInstanceID() == selectedIds[0])
|
||||
return true;
|
||||
return false;
|
||||
}) as TreeViewItemBase<ISpriteVisibilityItem>;
|
||||
if (selected != null)
|
||||
newSelected = ((SpriteVisibilitySpriteItem)selected.customData).sprite.sprite;
|
||||
}
|
||||
|
||||
using (m_Model.UndoScope(TextContent.selectionChange))
|
||||
{
|
||||
m_UpdateViewOnSelection = false;
|
||||
m_Events.selectedSpriteChanged.Invoke(newSelected);
|
||||
if (newSelected == null)
|
||||
m_Model.view.SetSelectionIds(selectedIds);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetTreeViewSelectionID(SpriteCache sprite)
|
||||
{
|
||||
if (sprite != null)
|
||||
return sprite.GetInstanceID();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal class SpriteVisibilityTool : IVisibilityTool, ISpriteVisibilityToolModel
|
||||
{
|
||||
SpriteVisibilityToolView m_View;
|
||||
SpriteVisibilityToolController m_Controller;
|
||||
|
||||
private SpriteVisibilityToolData m_Data;
|
||||
private SkinningCache m_SkinningCache;
|
||||
public SkinningCache skinningCache { get { return m_SkinningCache; } }
|
||||
|
||||
public SpriteVisibilityTool(SkinningCache s)
|
||||
{
|
||||
m_SkinningCache = s;
|
||||
m_Data = skinningCache.CreateCache<SpriteVisibilityToolData>();
|
||||
m_Controller = new SpriteVisibilityToolController(this, skinningCache.events);
|
||||
m_View = new SpriteVisibilityToolView()
|
||||
{
|
||||
GetController = () => m_Controller
|
||||
};
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
m_Controller.Dispose();
|
||||
}
|
||||
|
||||
public VisualElement view { get { return m_View; } }
|
||||
public string name { get { return L10n.Tr(TextContent.sprite); } }
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
m_Controller.Activate();
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
m_Controller.Deactivate();
|
||||
}
|
||||
|
||||
public bool isAvailable
|
||||
{
|
||||
get { return m_Controller.isAvailable; }
|
||||
}
|
||||
|
||||
|
||||
public void SetAvailabilityChangeCallback(Action callback)
|
||||
{
|
||||
m_Controller.OnAvailabilityChangeListeners += callback;
|
||||
}
|
||||
|
||||
ISpriteVisibilityToolView ISpriteVisibilityToolModel.view { get {return m_View;} }
|
||||
|
||||
bool ISpriteVisibilityToolModel.hasCharacter { get { return skinningCache.hasCharacter; } }
|
||||
SpriteCache ISpriteVisibilityToolModel.selectedSprite { get { return skinningCache.selectedSprite; } }
|
||||
CharacterCache ISpriteVisibilityToolModel.character { get { return skinningCache.character; } }
|
||||
bool ISpriteVisibilityToolModel.previousVisibility { get { return m_Data.previousVisibility; } set { m_Data.previousVisibility = value; } }
|
||||
bool ISpriteVisibilityToolModel.allVisibility { get { return m_Data.allVisibility; } set { m_Data.allVisibility = value; } }
|
||||
SkinningMode ISpriteVisibilityToolModel.mode { get { return skinningCache.mode; } }
|
||||
|
||||
UndoScope ISpriteVisibilityToolModel.UndoScope(string description)
|
||||
{
|
||||
return skinningCache.UndoScope(description);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SpriteVisibilityToolView : VisibilityToolViewBase, ISpriteVisibilityToolView
|
||||
{
|
||||
public Func<SpriteVisibilityToolController> GetController = () => null;
|
||||
|
||||
public SpriteVisibilityToolView()
|
||||
{
|
||||
var columns = new MultiColumnHeaderState.Column[2];
|
||||
columns[0] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = VisibilityTreeViewBase.VisibilityIconStyle.visibilityOnIcon,
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 32,
|
||||
minWidth = 32,
|
||||
maxWidth = 32,
|
||||
autoResize = false,
|
||||
allowToggleVisibility = true
|
||||
};
|
||||
columns[1] = new MultiColumnHeaderState.Column
|
||||
{
|
||||
headerContent = EditorGUIUtility.TrTextContent(TextContent.name),
|
||||
headerTextAlignment = TextAlignment.Center,
|
||||
width = 230,
|
||||
minWidth = 100,
|
||||
autoResize = true,
|
||||
allowToggleVisibility = false
|
||||
};
|
||||
var multiColumnHeaderState = new MultiColumnHeaderState(columns);
|
||||
var multiColumnHeader = new VisibilityToolColumnHeader(multiColumnHeaderState)
|
||||
{
|
||||
GetAllVisibility = InternalGetAllVisibility,
|
||||
SetAllVisibility = InternalSetAllVisibility,
|
||||
canSort = false,
|
||||
height = 20,
|
||||
visibilityColumn = 0
|
||||
};
|
||||
|
||||
m_TreeView = new SpriteTreeView(m_TreeViewState, multiColumnHeader)
|
||||
{
|
||||
GetController = InternalGetController
|
||||
};
|
||||
SetupSearchField();
|
||||
}
|
||||
|
||||
SpriteVisibilityToolController InternalGetController()
|
||||
{
|
||||
return GetController();
|
||||
}
|
||||
|
||||
bool InternalGetAllVisibility()
|
||||
{
|
||||
return GetController().GetAllVisibility();
|
||||
}
|
||||
|
||||
void InternalSetAllVisibility(bool visibility)
|
||||
{
|
||||
GetController().SetAllVisibility(visibility);
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
((SpriteTreeView)m_TreeView).Setup();
|
||||
}
|
||||
|
||||
public void SetSelection(SpriteCache sprite)
|
||||
{
|
||||
((SpriteTreeView)m_TreeView).SetSelection(sprite);
|
||||
}
|
||||
|
||||
public void SetSelectionIds(IList<int> selectedIds)
|
||||
{
|
||||
((SpriteTreeView)m_TreeView).SetSelectionIds(selectedIds);
|
||||
}
|
||||
}
|
||||
|
||||
class SpriteTreeView : VisibilityTreeViewBase
|
||||
{
|
||||
public Func<SpriteVisibilityToolController> GetController = () => null;
|
||||
public GUIStyle m_Style;
|
||||
private TreeViewItem m_CurrentEdittingItem;
|
||||
|
||||
public SpriteTreeView(TreeViewState treeViewState, MultiColumnHeader multiColumnHeader)
|
||||
: base(treeViewState, multiColumnHeader)
|
||||
{
|
||||
columnIndexForTreeFoldouts = 1;
|
||||
}
|
||||
|
||||
void SkinInit()
|
||||
{
|
||||
if (m_Style == null)
|
||||
{
|
||||
GUIStyle foldOut = "IN Foldout";
|
||||
m_Style = new GUIStyle(foldOut);
|
||||
m_Style.stretchWidth = false;
|
||||
m_Style.richText = false;
|
||||
m_Style.border = new RectOffset(-800, -10, 0, -10);
|
||||
m_Style.padding = new RectOffset(11, 16, 2, 2);
|
||||
m_Style.fixedWidth = 0;
|
||||
m_Style.alignment = TextAnchor.MiddleCenter;
|
||||
m_Style.clipping = TextClipping.Clip;
|
||||
m_Style.normal.background = foldOut.onFocused.background;
|
||||
m_Style.normal.scaledBackgrounds = foldOut.onFocused.scaledBackgrounds;
|
||||
m_Style.normal.textColor = foldOut.normal.textColor;
|
||||
m_Style.onNormal.background = m_Style.normal.background;
|
||||
m_Style.onNormal.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
|
||||
m_Style.onNormal.textColor = m_Style.normal.textColor;
|
||||
m_Style.onActive.background = m_Style.normal.background;
|
||||
m_Style.onActive.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
|
||||
m_Style.onActive.textColor = m_Style.normal.textColor;
|
||||
m_Style.active.background = m_Style.normal.background;
|
||||
m_Style.active.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
|
||||
m_Style.active.textColor = m_Style.normal.textColor;
|
||||
m_Style.onFocused.background = m_Style.normal.background;
|
||||
m_Style.onFocused.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
|
||||
m_Style.onFocused.textColor = m_Style.normal.textColor;
|
||||
m_Style.focused.background = m_Style.normal.background;
|
||||
m_Style.focused.scaledBackgrounds = m_Style.normal.scaledBackgrounds;
|
||||
m_Style.focused.textColor = m_Style.normal.textColor;
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
Reload();
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect rect)
|
||||
{
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
SkinInit();
|
||||
|
||||
base.OnGUI(rect);
|
||||
}
|
||||
|
||||
void CellGUI(Rect cellRect, TreeViewItem item, int column, ref RowGUIArgs args)
|
||||
{
|
||||
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||
switch (column)
|
||||
{
|
||||
case 0:
|
||||
DrawVisibilityCell(cellRect, item);
|
||||
break;
|
||||
case 1:
|
||||
DrawNameCell(cellRect, item, ref args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawVisibilityCell(Rect cellRect, TreeViewItem item)
|
||||
{
|
||||
var style = MultiColumnHeader.DefaultStyles.columnHeaderCenterAligned;
|
||||
var characterPartVisibility = GetController().GetCharacterPartVisibility(item);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
var visible = GUI.Toggle(cellRect, characterPartVisibility, characterPartVisibility ? VisibilityIconStyle.visibilityOnIcon : VisibilityIconStyle.visibilityOffIcon, style);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
GetController().SetCharacterPartVisibility(item, visible, Event.current.alt);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawNameCell(Rect cellRect, TreeViewItem item, ref RowGUIArgs args)
|
||||
{
|
||||
args.rowRect = cellRect;
|
||||
base.RowGUI(args);
|
||||
}
|
||||
|
||||
|
||||
protected override void RowGUI(RowGUIArgs args)
|
||||
{
|
||||
var item = args.item;
|
||||
|
||||
for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
|
||||
{
|
||||
CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item)
|
||||
{
|
||||
Rect cellRect = GetCellRectForTreeFoldouts(rowRect);
|
||||
CenterRectUsingSingleLineHeight(ref cellRect);
|
||||
return base.GetRenameRect(cellRect, row, item);
|
||||
}
|
||||
|
||||
protected override TreeViewItem BuildRoot()
|
||||
{
|
||||
var root = new TreeViewItem {id = 0, depth = -1, displayName = "Root"};
|
||||
var rows = GetController() != null ? GetController().BuildTreeView() : new List<TreeViewItem>();
|
||||
SetupParentsAndChildrenFromDepths(root, rows);
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override void SelectionChanged(IList<int> selectedIds)
|
||||
{
|
||||
GetController().SetSelectedSprite(GetRows(), selectedIds);
|
||||
}
|
||||
|
||||
public void SetSelectionIds(IList<int> selectedIds)
|
||||
{
|
||||
SetSelection(selectedIds, TreeViewSelectionOptions.RevealAndFrame);
|
||||
}
|
||||
|
||||
public void SetSelection(SpriteCache sprite)
|
||||
{
|
||||
var id = GetController().GetTreeViewSelectionID(sprite);
|
||||
SetSelection(new[] { id }, TreeViewSelectionOptions.RevealAndFrame);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,442 @@
|
||||
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.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.visibililtyToolIndex;
|
||||
}
|
||||
set
|
||||
{
|
||||
skinningCache.visibililtyToolIndex = 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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal interface IVisibilityTool
|
||||
{
|
||||
VisualElement view { get; }
|
||||
string name { get; }
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
bool isAvailable { get; }
|
||||
void SetAvailabilityChangeCallback(Action callback);
|
||||
void Setup();
|
||||
void Dispose();
|
||||
}
|
||||
|
||||
internal class VisibilityToolViewBase : VisualElement
|
||||
{
|
||||
IMGUIContainer m_Container;
|
||||
SearchField m_SearchField;
|
||||
protected TreeView m_TreeView;
|
||||
protected TreeViewState m_TreeViewState = new TreeViewState();
|
||||
|
||||
public Action<float> SetOpacityValue = null;
|
||||
public Func<float> GetOpacityValue = null;
|
||||
|
||||
protected static class Styles
|
||||
{
|
||||
public static readonly GUIStyle preLabel = "preLabel";
|
||||
public static readonly GUIStyle preSlider = "preSlider";
|
||||
public static readonly GUIStyle preSliderThumb = "preSliderThumb";
|
||||
}
|
||||
|
||||
public VisibilityToolViewBase()
|
||||
{
|
||||
m_Container = new IMGUIContainer(OnGUI);
|
||||
this.Add(m_Container);
|
||||
m_TreeViewState.searchString = "";
|
||||
}
|
||||
|
||||
protected void SetupSearchField()
|
||||
{
|
||||
m_SearchField = new SearchField();
|
||||
m_SearchField.downOrUpArrowKeyPressed += m_TreeView.SetFocusAndEnsureSelectedItem;
|
||||
}
|
||||
|
||||
void DoSearchField()
|
||||
{
|
||||
m_SearchField.downOrUpArrowKeyPressed += m_TreeView.SetFocusAndEnsureSelectedItem;
|
||||
GUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||
m_TreeView.searchString = m_SearchField.OnToolbarGUI(m_TreeView.searchString);
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
void DoOpacitySlider()
|
||||
{
|
||||
if (GetOpacityValue != null && SetOpacityValue != null)
|
||||
{
|
||||
GUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var opacity = GUILayout.HorizontalSlider(GetOpacityValue(), 0, 1, Styles.preSlider, Styles.preSliderThumb);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
SetOpacityValue(opacity);
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.BeginVertical();
|
||||
DoSearchField();
|
||||
GUILayout.EndVertical();
|
||||
Rect rect = GUILayoutUtility.GetRect(0, 100000, 0, 100000);
|
||||
m_TreeView.OnGUI(rect);
|
||||
DoOpacitySlider();
|
||||
}
|
||||
}
|
||||
|
||||
internal class TreeViewItemBase<T> : TreeViewItem
|
||||
{
|
||||
public T customData;
|
||||
|
||||
public TreeViewItemBase(int id, int depth, string name, T data) : base(id, depth, name)
|
||||
{
|
||||
customData = data;
|
||||
}
|
||||
}
|
||||
|
||||
internal class VisibilityTreeViewBase : TreeView
|
||||
{
|
||||
static internal class VisibilityIconStyle
|
||||
{
|
||||
public static readonly GUIContent visibilityOnIcon = new GUIContent(IconUtility.LoadIconResource("Visibility_Tool", IconUtility.k_LightIconResourcePath, IconUtility.k_DarkIconResourcePath), L10n.Tr("On"));
|
||||
public static readonly GUIContent visibilityOffIcon = new GUIContent(IconUtility.LoadIconResource("Visibility_Hidded", IconUtility.k_LightIconResourcePath, IconUtility.k_DarkIconResourcePath), L10n.Tr("Off"));
|
||||
}
|
||||
|
||||
|
||||
public VisibilityTreeViewBase(TreeViewState treeViewState, MultiColumnHeader multiColumn)
|
||||
: base(treeViewState, multiColumn)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
public VisibilityTreeViewBase(TreeViewState treeViewState)
|
||||
: base(treeViewState)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
this.showAlternatingRowBackgrounds = true;
|
||||
this.useScrollView = true;
|
||||
}
|
||||
|
||||
protected override TreeViewItem BuildRoot()
|
||||
{
|
||||
return new TreeViewItem { id = 0, depth = -1 };
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.U2D.Animation
|
||||
{
|
||||
internal class VisibilityToolColumnHeader : MultiColumnHeader
|
||||
{
|
||||
public Action<bool> SetAllVisibility = (b) => {};
|
||||
public Func<bool> GetAllVisibility = () => true;
|
||||
|
||||
public VisibilityToolColumnHeader(MultiColumnHeaderState state)
|
||||
: base(state)
|
||||
{
|
||||
visibilityColumn = -1;
|
||||
}
|
||||
|
||||
public int visibilityColumn { private get; set; }
|
||||
|
||||
protected override void ColumnHeaderGUI(MultiColumnHeaderState.Column column, Rect headerRect, int columnIndex)
|
||||
{
|
||||
if (columnIndex == visibilityColumn)
|
||||
{
|
||||
GUIStyle style = DefaultStyles.columnHeaderCenterAligned;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var visibility = GetAllVisibility();
|
||||
visibility = GUI.Toggle(headerRect, visibility, visibility ? VisibilityTreeViewBase.VisibilityIconStyle.visibilityOnIcon : VisibilityTreeViewBase.VisibilityIconStyle.visibilityOffIcon, style);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
SetAllVisibility(visibility);
|
||||
}
|
||||
else
|
||||
base.ColumnHeaderGUI(column, headerRect, columnIndex);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UnityEditor.U2D.Layout
|
||||
{
|
||||
internal class VisibilityToolResizer : MouseManipulator
|
||||
{
|
||||
private Vector2 m_Start;
|
||||
private VisualElement m_Root;
|
||||
protected bool m_Active;
|
||||
private Rect m_StartPos;
|
||||
|
||||
public VisibilityToolResizer()
|
||||
{
|
||||
activators.Add(new ManipulatorActivationFilter {button = MouseButton.LeftMouse});
|
||||
m_Active = false;
|
||||
}
|
||||
|
||||
protected override void RegisterCallbacksOnTarget()
|
||||
{
|
||||
target.RegisterCallback<MouseDownEvent>(OnMouseDown);
|
||||
target.RegisterCallback<MouseMoveEvent>(OnMouseMove);
|
||||
target.RegisterCallback<MouseUpEvent>(OnMouseUp);
|
||||
}
|
||||
|
||||
protected override void UnregisterCallbacksFromTarget()
|
||||
{
|
||||
target.UnregisterCallback<MouseDownEvent>(OnMouseDown);
|
||||
target.UnregisterCallback<MouseMoveEvent>(OnMouseMove);
|
||||
target.UnregisterCallback<MouseUpEvent>(OnMouseUp);
|
||||
}
|
||||
|
||||
protected void OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
if (m_Active)
|
||||
{
|
||||
e.StopImmediatePropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (CanStartManipulation(e))
|
||||
{
|
||||
m_Root = target;
|
||||
while (m_Root.parent != null)
|
||||
m_Root = m_Root.parent;
|
||||
m_Start = target.ChangeCoordinatesTo(m_Root, e.localMousePosition);
|
||||
m_StartPos = target.parent.layout;
|
||||
m_Active = true;
|
||||
target.CaptureMouse();
|
||||
e.StopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
if (m_Active)
|
||||
{
|
||||
var ce = target.parent;
|
||||
Vector2 diff = target.ChangeCoordinatesTo(m_Root, e.localMousePosition) - m_Start;
|
||||
var newSize = new Vector2(m_StartPos.width - diff.x, m_StartPos.height - diff.y);
|
||||
float minWidth = ce.resolvedStyle.minWidth == StyleKeyword.Auto ? 0 : ce.resolvedStyle.minWidth.value;
|
||||
float minHeight = ce.resolvedStyle.minHeight == StyleKeyword.Auto ? 0 : ce.resolvedStyle.minHeight.value;
|
||||
float maxWidth = ce.resolvedStyle.maxWidth == StyleKeyword.None ? float.MaxValue : ce.resolvedStyle.maxWidth.value;
|
||||
float maxHeight = ce.resolvedStyle.maxHeight == StyleKeyword.None ? float.MaxValue : ce.resolvedStyle.maxHeight.value;
|
||||
|
||||
newSize.x = (newSize.x < minWidth) ? minWidth : ((newSize.x > maxWidth) ? maxWidth : newSize.x);
|
||||
newSize.y = (newSize.y < minHeight) ? minHeight : ((newSize.y > maxHeight) ? maxHeight : newSize.y);
|
||||
ce.style.width = newSize.x;
|
||||
e.StopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
if (m_Active)
|
||||
{
|
||||
if (CanStopManipulation(e))
|
||||
{
|
||||
m_Active = false;
|
||||
target.ReleaseMouse();
|
||||
e.StopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user