#if PROBUILDER_DEBUG using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using UnityEngine; using UnityEditor; using UnityEditor.IMGUI.Controls; namespace UnityEngine.ProBuilder.AssetIdRemapUtility { sealed class AssetIdRemapBuilderTreeView : TreeView { AssetIdRemapObject m_RemapObject = null; const float k_RowHeight = 20f; const float k_RowHeightSearching = 76f; public bool isDirty = false; public AssetIdRemapObject remapObject { get { return m_RemapObject; } set { m_RemapObject = value; } } public AssetIdRemapBuilderTreeView(TreeViewState state, MultiColumnHeader header) : base(state, header) { rowHeight = 20f; showAlternatingRowBackgrounds = true; showBorder = true; extraSpaceBeforeIconAndLabel = 18f; } protected override TreeViewItem BuildRoot() { StringTupleTreeElement root = new StringTupleTreeElement(0, -1, -1, "Root", "", ""); var all = new List(); int index = 1; for (int i = 0, c = remapObject.map.Count; i < c; i++) { all.Add(new StringTupleTreeElement(index++, 0, i, "Remap Entry", remapObject[i].source.name, remapObject[i].destination.name)); all.Add(new StringTupleTreeElement(index++, 1, i, "Local Path", remapObject[i].source.localPath, remapObject[i].destination.localPath)); all.Add(new StringTupleTreeElement(index++, 1, i, "GUID", remapObject[i].source.guid, remapObject[i].destination.guid)); all.Add(new StringTupleTreeElement(index++, 1, i, "File ID", remapObject[i].source.fileId, remapObject[i].destination.fileId)); all.Add(new StringTupleTreeElement(index++, 1, i, "Type", remapObject[i].source.type, remapObject[i].destination.type)); } SetupParentsAndChildrenFromDepths(root, all); return root; } public void SetRowHeight() { rowHeight = hasSearch ? k_RowHeightSearching : k_RowHeight; } protected override void RowGUI(RowGUIArgs args) { StringTupleTreeElement item = args.item as StringTupleTreeElement; for (int i = 0; i < args.GetNumVisibleColumns(); ++i) { CellGUI(args.GetCellRect(i), item, i, ref args); } } GUIContent m_CellContents = new GUIContent(); void CellGUI(Rect rect, StringTupleTreeElement item, int visibleColumn, ref RowGUIArgs args) { if (hasSearch) { AssetId id = visibleColumn == 0 ? m_RemapObject[item.index].source : m_RemapObject[item.index].destination; m_CellContents.text = "Name: " + id.name + "\nPath: " + id.localPath + "\nGuid: " + id.guid + "\nFileId: " + id.fileId + "\nType: " + id.type + (string.IsNullOrEmpty(id.assetType) ? "" : " (" + id.assetType + ")"); } else { m_CellContents.text = item.GetLabel(visibleColumn); } rect.x += foldoutWidth + 4; rect.width -= (foldoutWidth + 4); if (hasSearch) { float textHeight = GUI.skin.label.CalcHeight(m_CellContents, rect.width); rect.y += (rect.height - textHeight) * .5f; rect.height = textHeight; } else { CenterRectUsingSingleLineHeight(ref rect); } GUI.skin.label.richText = true; GUI.Label(rect, m_CellContents); } protected override bool DoesItemMatchSearch(TreeViewItem element, string search) { StringTupleTreeElement tup = element as StringTupleTreeElement; if (tup == null || tup.depth > 0) return false; var o = m_RemapObject[tup.index]; try { var patterns = search.Split(new[] { "\\&" }, StringSplitOptions.None).Select(x => new Regex(x)); foreach (var pattern in patterns) { if (!(pattern.IsMatch(o.source.localPath) || pattern.IsMatch(o.source.guid) || pattern.IsMatch(o.source.fileId) || pattern.IsMatch(o.source.type) || pattern.IsMatch(o.destination.localPath) || pattern.IsMatch(o.destination.guid) || pattern.IsMatch(o.destination.fileId) || pattern.IsMatch(o.destination.type))) return false; } return true; } catch { return o.source.localPath.Contains(search) || o.source.guid.Contains(search) || o.source.fileId.Contains(search) || o.source.type.Contains(search) || o.destination.localPath.Contains(search) || o.destination.guid.Contains(search) || o.destination.fileId.Contains(search) || o.destination.type.Contains(search); } } protected override void ContextClicked() { GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("Combine", ""), false, () => { m_RemapObject.Merge(GetAssetIdSelection()); isDirty = true; Reload(); SetSelection(new int[] {}); }); menu.ShowAsContext(); } IEnumerable GetAssetIdSelection() { return GetSelection().Select(x => m_RemapObject[((StringTupleTreeElement)FindItem(x, rootItem)).index]); } protected override void CommandEventHandling() { var evt = Event.current; var selected = GetSelection(); if (selected.Count > 0) { if (evt.type == EventType.ValidateCommand) { if (evt.commandName.Equals("SoftDelete")) evt.Use(); } else if (evt.type == EventType.ExecuteCommand) { if (evt.commandName.Equals("SoftDelete") && EditorUtility.DisplayDialog("Delete", "Delete Selected Entries?", "Delete", "Cancel")) { m_RemapObject.Delete(GetAssetIdSelection()); evt.Use(); Reload(); isDirty = true; SetSelection(new int[] {}); } } } base.CommandEventHandling(); } } class StringTupleTreeElement : TreeViewItem { public string item1; public string item2; public int index; public StringTupleTreeElement(int id, int depth, int sourceIndex, string displayName, string key, string value) : base(id, depth, displayName) { item1 = key; item2 = value; index = sourceIndex; } public string GetLabel(int column) { return column < 1 ? item1 : item2; } } } #endif