A game about forced loneliness, made by TACStudios
1using System;
2using System.Linq;
3using System.Collections.Generic;
4using UnityEngine;
5using UnityEditor.IMGUI.Controls;
6
7namespace UnityEditor.U2D.Animation
8{
9 internal class BoneTreeWidgetController
10 {
11 protected IBoneTreeViewModel m_Model;
12 protected SkinningEvents m_SkinningEvents;
13
14 public BoneTreeWidgetController(IBoneTreeViewModel model, SkinningEvents eventSystem)
15 {
16 m_Model = model;
17 m_SkinningEvents = eventSystem;
18 }
19
20 public void Activate()
21 {
22 SetupSkeleton();
23
24 m_SkinningEvents.selectedSpriteChanged.AddListener(OnSelectionChange);
25 m_SkinningEvents.skinningModeChanged.AddListener(OnSkinningModuleModeChanged);
26 m_SkinningEvents.boneSelectionChanged.AddListener(OnBoneSelectionChanged);
27 m_SkinningEvents.boneNameChanged.AddListener(OnBoneNameChanged);
28 m_SkinningEvents.skeletonTopologyChanged.AddListener(SkeletonTopologyChanged);
29 }
30
31 public void Deactivate()
32 {
33 m_SkinningEvents.selectedSpriteChanged.RemoveListener(OnSelectionChange);
34 m_SkinningEvents.skinningModeChanged.RemoveListener(OnSkinningModuleModeChanged);
35 m_SkinningEvents.boneSelectionChanged.RemoveListener(OnBoneSelectionChanged);
36 m_SkinningEvents.boneNameChanged.RemoveListener(OnBoneNameChanged);
37 m_SkinningEvents.skeletonTopologyChanged.RemoveListener(SkeletonTopologyChanged);
38 if (m_Model.view != null)
39 m_Model.view.Deactivate();
40 }
41
42 private void OnSelectionChange(SpriteCache sprite)
43 {
44 SetupSkeleton();
45 m_Model.SetAllVisibility(null, true);
46 }
47
48 private void OnBoneSelectionChanged()
49 {
50 m_Model.view.OnBoneSelectionChange(m_Model.GetBoneSelection());
51 }
52
53 private void OnBoneNameChanged(BoneCache bone)
54 {
55 m_Model.view.OnBoneNameChanged(bone);
56 }
57
58 private void OnSkinningModuleModeChanged(SkinningMode mode)
59 {
60 SetupSkeleton();
61 m_Model.SetAllVisibility(null, true);
62 }
63
64 private void SetupSkeleton()
65 {
66 m_Model.view.OnSelectionChange(m_Model.GetSelectedSkeleton());
67 m_Model.view.OnBoneExpandedChange(m_Model.GetExpandedBones());
68 m_Model.view.OnBoneSelectionChange(m_Model.GetBoneSelection());
69 }
70
71 public void SetAllVisibility(bool visibility)
72 {
73 var skeleton = m_Model.GetSelectedSkeleton();
74 if (skeleton != null)
75 {
76 using (m_Model.UndoScope(TextContent.boneVisibility))
77 {
78 m_Model.SetAllVisibility(skeleton, visibility);
79 }
80 }
81 }
82
83 private void SkeletonTopologyChanged(SkeletonCache skeleton)
84 {
85 m_Model.view.OnSelectionChange(skeleton);
86 }
87
88 public List<TreeViewItem> BuildTreeView()
89 {
90 var rows = new List<TreeViewItem>();
91 var skeleton = m_Model.GetSelectedSkeleton();
92 if (skeleton != null)
93 {
94 var bones = skeleton.bones;
95 var children = bones.Where(x => x.parentBone == null).ToArray();
96 Array.Sort(children, (a, b) => a.siblingIndex.CompareTo(b.siblingIndex));
97
98 foreach (var bone in children)
99 AddTreeViewItem(rows, bone, bones, 0);
100 }
101 return rows;
102 }
103
104 private static void AddTreeViewItem(IList<TreeViewItem> rows, BoneCache bone, BoneCache[] bones, int depth)
105 {
106 var item = new TreeViewItemBase<BoneCache>(bone.GetInstanceID(), depth, bone.name, bone);
107 rows.Add(item);
108
109 var children = bones.Where(x => x.parentBone == bone).ToArray();
110 Array.Sort(children, (a, b) => a.siblingIndex.CompareTo(b.siblingIndex));
111
112 foreach (var childBone in children)
113 AddTreeViewItem(rows, childBone, bones, depth + 1);
114 }
115
116 public List<int> GetIDsToExpand(BoneCache[] bones)
117 {
118 var result = new List<int>();
119 if (bones != null)
120 {
121 foreach (var bone in bones)
122 {
123 if (bone != null)
124 {
125 var parent = bone.parentBone;
126 while (parent != null)
127 {
128 int parentId = parent.GetInstanceID();
129 result.Add(parentId);
130 parent = parent.parentBone;
131 }
132 }
133 }
134 }
135 return result;
136 }
137
138 public int[] GetIDsToSelect(BoneCache[] bones)
139 {
140 return bones == null ? new int[0] : Array.ConvertAll(bones, x => x != null ? x.GetInstanceID() : 0);
141 }
142
143 public void SelectBones(IList<int> selectedIds, IList<TreeViewItem> items)
144 {
145 var selectedBones = items.Where(x => selectedIds.Contains(x.id)).Select(y => ((TreeViewItemBase<BoneCache>)y).customData).ToArray();
146 using (m_Model.UndoScope(TextContent.boneSelection))
147 {
148 m_Model.SelectBones(selectedBones);
149 m_SkinningEvents.boneSelectionChanged.Invoke();
150 }
151 }
152
153 public void ExpandBones(IList<int> expandedIds, IList<TreeViewItem> items)
154 {
155 var expandedBones = items.Where(x => expandedIds.Contains(x.id)).Select(y => ((TreeViewItemBase<BoneCache>)y).customData).ToArray();
156 using (m_Model.UndoScope(TextContent.expandBones))
157 {
158 m_Model.SetExpandedBones(expandedBones);
159 }
160 }
161
162 public bool GetTreeItemVisibility(TreeViewItemBase<BoneCache> item)
163 {
164 return m_Model.GetVisibility(item.customData);
165 }
166
167 public void SetTreeItemVisibility(TreeViewItemBase<BoneCache> item, bool visible, bool includeChildren)
168 {
169 var bone = item.customData;
170 if (bone != null && bone.isVisible != visible)
171 {
172 using (m_Model.UndoScope(TextContent.visibilityChange))
173 {
174 m_Model.SetVisibility(item.customData, visible);
175 if (includeChildren)
176 {
177 // toggle all children as well
178 SetChildrenVisibility(item, visible);
179 }
180 }
181 }
182 }
183
184 void SetChildrenVisibility(TreeViewItemBase<BoneCache> bone, bool visible)
185 {
186 if (bone.children == null)
187 return;
188 foreach (var childBone in bone.children)
189 {
190 var cb = childBone as TreeViewItemBase<BoneCache>;
191 SetChildrenVisibility(cb, visible);
192 m_Model.SetVisibility(cb.customData, visible);
193 }
194 }
195
196 public int GetTreeItemDepthValue(TreeViewItemBase<BoneCache> bone)
197 {
198 return m_Model.GetDepth(bone.customData);
199 }
200
201 public void SetTreeItemDepthValue(TreeViewItemBase<BoneCache> bone, int value)
202 {
203 if (bone != null && bone.customData != null)
204 {
205 using (m_Model.UndoScope(TextContent.boneDepth))
206 {
207 m_Model.SetDepth(bone.customData, value);
208 m_SkinningEvents.boneDepthChanged.Invoke(bone.customData);
209 }
210 }
211 }
212
213 public Color GetTreeItemColorValue(TreeViewItemBase<BoneCache> bone)
214 {
215 return m_Model.GetBoneColor(bone.customData);
216 }
217
218 public void SetTreeItemColorValue(TreeViewItemBase<BoneCache> bone, Color color)
219 {
220 if (bone != null && bone.customData != null)
221 {
222 using (m_Model.UndoScope(TextContent.boneColor))
223 {
224 m_Model.SetBoneColor(bone.customData, color);
225 m_SkinningEvents.boneColorChanged.Invoke(bone.customData);
226 }
227 }
228 }
229
230 public void SetTreeViewBoneName(IList<TreeViewItem> items, BoneCache bone)
231 {
232 var treeBone = items.FirstOrDefault(x => ((TreeViewItemBase<BoneCache>)x).customData == bone);
233 if (treeBone != null)
234 treeBone.displayName = bone.name;
235 }
236
237 public void TreeViewItemRename(IList<TreeViewItem> rows, int itemID, string newName)
238 {
239 var item = rows.FirstOrDefault(x => x.id == itemID) as TreeViewItemBase<BoneCache>;
240
241 if (item == null)
242 return;
243
244 if (item.customData != null && item.customData.name != newName && !string.IsNullOrEmpty(newName)
245 && !string.IsNullOrWhiteSpace(newName))
246 {
247 item.displayName = newName;
248 using (m_Model.UndoScope(TextContent.boneName))
249 {
250 m_Model.SetName(item.customData, newName);
251 m_SkinningEvents.boneNameChanged.Invoke(item.customData);
252 }
253 }
254 }
255
256 public bool CanReparent(TreeViewItemBase<BoneCache> parent, List<TreeViewItem> draggedItems)
257 {
258 TreeViewItemBase<BoneCache> currentParent = parent;
259 while (currentParent != null)
260 {
261 if (draggedItems.Contains(currentParent))
262 return false;
263 currentParent = currentParent.parent as TreeViewItemBase<BoneCache>;
264 }
265 return true;
266 }
267
268 public void ReparentItems(TreeViewItemBase<BoneCache> newParent, List<TreeViewItem> draggedItems, int insertAtIndex)
269 {
270 if ((m_Model.hasCharacter && m_Model.mode != SkinningMode.Character) ||
271 (!m_Model.hasCharacter && m_Model.mode == SkinningMode.Character))
272 return;
273
274 var parent = newParent != null ? newParent.customData : null;
275 using (m_Model.UndoScope(TextContent.setParentBone))
276 {
277 for (var i = draggedItems.Count - 1; i >= 0; --i)
278 {
279 var bone = ((TreeViewItemBase<BoneCache>)draggedItems[i]).customData;
280 m_Model.SetBoneParent(parent, bone, insertAtIndex);
281 m_SkinningEvents.skeletonTopologyChanged.Invoke(bone.skeleton);
282 }
283 }
284 }
285
286 public virtual bool CanDrag()
287 {
288 m_SkinningEvents.boneVisibility.Invoke("drag");
289 return false;
290 }
291
292 public virtual bool CanRename()
293 {
294 m_SkinningEvents.boneVisibility.Invoke("rename");
295 return false;
296 }
297 }
298}