Singularity/Library/PackageCache/com.unity.2d.animation@7.0.10/Editor/SkinningModule/VisibilityTool/SpriteVisibilityTool.cs
2024-05-06 11:45:45 -07:00

596 lines
21 KiB
C#

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 characterPartCache in character.parts)
characterPartCache.isVisible = !visible;
foreach (var group in character.groups)
group.isVisible = !visible;
}
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 => m_View;
public string name => 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 = new GUIContent(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);
}
}
}