A game about forced loneliness, made by TACStudios
1using System.Collections.Generic;
2using UnityEngine;
3using UnityEditor.IMGUI.Controls;
4using System;
5using System.Linq;
6using UnityEngine.UIElements;
7
8namespace UnityEditor.U2D.Animation
9{
10 internal class MeshVisibilityTool : IVisibilityTool
11 {
12 MeshVisibilityToolView m_View;
13 MeshVisibilityToolModel m_Model;
14 public SkinningCache skinningCache { get; }
15
16 public MeshVisibilityTool(SkinningCache s)
17 {
18 skinningCache = s;
19 }
20
21 public void Setup()
22 {
23 m_Model = skinningCache.CreateCache<MeshVisibilityToolModel>();
24 m_View = new MeshVisibilityToolView(skinningCache)
25 {
26 getModel = () => m_Model,
27 setAllVisibility = SetAllVisibility,
28 getAllVisibility = GetAllVisibility
29 };
30 }
31
32 public void Dispose() { }
33
34 public VisualElement view => m_View;
35 public string name => "Mesh";
36
37 public void Activate()
38 {
39 skinningCache.events.selectedSpriteChanged.AddListener(OnSelectionChange);
40 skinningCache.events.skinningModeChanged.AddListener(OnViewModeChanged);
41 OnViewModeChanged(skinningCache.mode);
42 if (m_Model.previousVisibility != m_Model.allVisibility)
43 {
44 SetAllMeshVisibility();
45 m_Model.previousVisibility = m_Model.allVisibility;
46 }
47 }
48
49 public void Deactivate()
50 {
51 skinningCache.events.selectedSpriteChanged.RemoveListener(OnSelectionChange);
52 skinningCache.events.skinningModeChanged.RemoveListener(OnViewModeChanged);
53 }
54
55 public bool isAvailable => false;
56
57 public void SetAvailabilityChangeCallback(Action callback) {}
58
59 void OnViewModeChanged(SkinningMode characterMode)
60 {
61 if (characterMode == SkinningMode.Character)
62 {
63 m_View.Setup(skinningCache.GetSprites());
64 }
65 else
66 {
67 m_View.Setup(new[] { skinningCache.selectedSprite });
68 }
69 }
70
71 void OnSelectionChange(SpriteCache sprite)
72 {
73 OnViewModeChanged(skinningCache.mode);
74 SetAllMeshVisibility();
75 }
76
77 void SetAllVisibility(bool visibility)
78 {
79 using (skinningCache.UndoScope(TextContent.meshVisibility))
80 {
81 m_Model.allVisibility = visibility;
82 SetAllMeshVisibility();
83 }
84 }
85
86 void SetAllMeshVisibility()
87 {
88 SpriteCache[] sprites;
89 if (skinningCache.mode == SkinningMode.Character)
90 sprites = skinningCache.GetSprites();
91 else
92 sprites = new[] { skinningCache.selectedSprite };
93
94 foreach (var spr in sprites)
95 {
96 if (spr != null)
97 MeshVisibilityToolModel.SetMeshVisibility(spr, m_Model.allVisibility);
98 }
99 }
100
101 bool GetAllVisibility()
102 {
103 return m_Model.allVisibility;
104 }
105 }
106
107 internal class MeshVisibilityToolModel : SkinningObject
108 {
109 [SerializeField]
110 bool m_AllVisibility = true;
111
112 public bool allVisibility
113 {
114 get => m_AllVisibility;
115 set => m_AllVisibility = value;
116 }
117
118 public static void SetMeshVisibility(SpriteCache sprite, bool visibility) { }
119
120 public static bool GetMeshVisibility(SpriteCache sprite)
121 {
122 return false;
123 }
124
125 public bool ShouldDisable(SpriteCache sprite)
126 {
127 var mesh = sprite.GetMesh();
128 return mesh == null || mesh.vertices.Length == 0;
129 }
130
131 public bool previousVisibility { get; set; } = true;
132 }
133
134 internal class MeshVisibilityToolView : VisibilityToolViewBase
135 {
136 public Func<MeshVisibilityToolModel> getModel = () => null;
137 public Action<bool> setAllVisibility = (b) => {};
138 public Func<bool> getAllVisibility = () => true;
139 public SkinningCache skinningCache { get; set; }
140
141 public MeshVisibilityToolView(SkinningCache s)
142 {
143 skinningCache = s;
144 var columns = new MultiColumnHeaderState.Column[2];
145 columns[0] = new MultiColumnHeaderState.Column
146 {
147 headerContent = new GUIContent(TextContent.name),
148 headerTextAlignment = TextAlignment.Center,
149 width = 200,
150 minWidth = 130,
151 autoResize = true,
152 allowToggleVisibility = false
153 };
154 columns[1] = new MultiColumnHeaderState.Column
155 {
156 headerContent = new GUIContent(EditorGUIUtility.FindTexture("visibilityOn")),
157 headerTextAlignment = TextAlignment.Center,
158 width = 32,
159 minWidth = 32,
160 maxWidth = 32,
161 autoResize = false,
162 allowToggleVisibility = true
163 };
164 var multiColumnHeaderState = new MultiColumnHeaderState(columns);
165 var multiColumnHeader = new VisibilityToolColumnHeader(multiColumnHeaderState)
166 {
167 GetAllVisibility = InternalGetAllVisibility,
168 SetAllVisibility = InternalSetAllVisibility,
169 canSort = false,
170 height = 20,
171 visibilityColumn = 1
172 };
173 m_TreeView = new MeshTreeView(m_TreeViewState, multiColumnHeader)
174 {
175 GetModel = InternalGetModel
176 };
177 SetupSearchField();
178 }
179
180 MeshVisibilityToolModel InternalGetModel()
181 {
182 return getModel();
183 }
184
185 public void Setup(SpriteCache[] sprites)
186 {
187 ((MeshTreeView)m_TreeView).Setup(sprites);
188 ((MeshTreeView)m_TreeView).SetSelection(skinningCache.selectedSprite);
189 }
190
191 bool InternalGetAllVisibility()
192 {
193 return getAllVisibility();
194 }
195
196 void InternalSetAllVisibility(bool visibility)
197 {
198 setAllVisibility(visibility);
199 }
200 }
201
202 class MeshTreeView : VisibilityTreeViewBase
203 {
204 private List<SpriteCache> m_Sprites = new List<SpriteCache>();
205
206 public MeshTreeView(TreeViewState treeViewState, MultiColumnHeader header)
207 : base(treeViewState, header)
208 {
209 this.showAlternatingRowBackgrounds = true;
210 this.useScrollView = true;
211 Reload();
212 }
213
214 public Func<MeshVisibilityToolModel> GetModel = () => null;
215
216 public void Setup(SpriteCache[] sprites)
217 {
218 m_Sprites.Clear();
219 m_Sprites.AddRange(sprites);
220 Reload();
221 }
222
223 private static TreeViewItem CreateTreeViewItem(SpriteCache part)
224 {
225 return new TreeViewItemBase<SpriteCache>(part.GetInstanceID(), -1, part.name, part);
226 }
227
228 private void AddTreeViewItem(IList<TreeViewItem> rows, SpriteCache part)
229 {
230 if (string.IsNullOrEmpty(searchString) || part.name.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
231 {
232 var item = CreateTreeViewItem(part);
233 rows.Add(item);
234 rootItem.AddChild(item);
235 }
236 }
237
238 private void CellGUI(Rect cellRect, TreeViewItem item, int column, ref RowGUIArgs args)
239 {
240 CenterRectUsingSingleLineHeight(ref cellRect);
241 switch (column)
242 {
243 case 0:
244 DrawNameCell(cellRect, item, ref args);
245 break;
246 case 1:
247 DrawVisibilityCell(cellRect, item);
248 break;
249 }
250 }
251
252 private void DrawVisibilityCell(Rect cellRect, TreeViewItem item)
253 {
254 GUIStyle style = MultiColumnHeader.DefaultStyles.columnHeaderCenterAligned;
255 var itemView = item as TreeViewItemBase<SpriteCache>;
256 var shouldDisable = GetModel().ShouldDisable(itemView.customData);
257 using (new EditorGUI.DisabledScope(shouldDisable))
258 {
259 EditorGUI.BeginChangeCheck();
260 bool visible = MeshVisibilityToolModel.GetMeshVisibility(itemView.customData);
261 visible = GUI.Toggle(cellRect, visible, visible ? VisibilityIconStyle.visibilityOnIcon : VisibilityIconStyle.visibilityOffIcon, style);
262 if (EditorGUI.EndChangeCheck())
263 MeshVisibilityToolModel.SetMeshVisibility(itemView.customData, visible);
264 }
265 }
266
267 private void DrawNameCell(Rect cellRect, TreeViewItem item, ref RowGUIArgs args)
268 {
269 args.rowRect = cellRect;
270 base.RowGUI(args);
271 }
272
273 protected override void RowGUI(RowGUIArgs args)
274 {
275 var item = args.item;
276
277 for (int i = 0; i < args.GetNumVisibleColumns(); ++i)
278 {
279 CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);
280 }
281 }
282
283 protected override void SelectionChanged(IList<int> selectedIds)
284 {
285 SpriteCache newSelected = null;
286 if (selectedIds.Count > 0)
287 {
288 var selected = GetRows().FirstOrDefault(x => ((TreeViewItemBase<SpriteCache>)x).customData.GetInstanceID() == selectedIds[0]) as TreeViewItemBase<SpriteCache>;
289 if (selected != null)
290 newSelected = selected.customData;
291 }
292
293 var skinningCache = newSelected.skinningCache;
294
295 using (skinningCache.UndoScope(TextContent.selectionChange))
296 {
297 skinningCache.events.selectedSpriteChanged.Invoke(newSelected);
298 }
299 }
300
301 public void SetSelection(SpriteCache sprite)
302 {
303 var rows = GetRows();
304 for (int i = 0; rows != null && i < rows.Count; ++i)
305 {
306 var r = (TreeViewItemBase<SpriteCache>)rows[i];
307 if (r.customData == sprite)
308 {
309 SetSelection(new[] { r.customData.GetInstanceID() }, TreeViewSelectionOptions.RevealAndFrame);
310 break;
311 }
312 }
313 }
314
315 protected override IList<TreeViewItem> BuildRows(TreeViewItem root)
316 {
317 var rows = GetRows() ?? new List<TreeViewItem>(200);
318 rows.Clear();
319
320 m_Sprites.RemoveAll(s => s == null);
321
322 foreach (var sprite in m_Sprites)
323 AddTreeViewItem(rows, sprite);
324
325 SetupDepthsFromParentsAndChildren(root);
326 return rows;
327 }
328 }
329}