using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using ModTool.Shared;
namespace ModTool.Editor
{
///
/// A window for selecting shared assets.
///
public class AssetSelector : SelectionWindow
{
protected override string title => "Shared Assets";
protected override string message => "Select assets to be included with the mod exporter package.";
private List selected => ModToolSettings.sharedAssets;
private FileNode root;
protected override void Init()
{
root = new FileNode(new DirectoryInfo(Application.dataPath + "/"));
SelectAssets(selected);
ExpandSelected(root);
}
protected override void RenderItems()
{
List nodes = new List();
GetExpandedNodes(root, nodes);
Rect rect = EditorGUILayout.GetControlRect(false, nodes.Count * 16);
List selectedChildren = new List();
for (int i = 0; i < nodes.Count; i++)
{
var node = nodes[i];
Rect nodeRect = new Rect(rect.x + (node.depth - 1) * 18, rect.y + i * 16, 20, 20);
if (node.isDirectory && node.children.Count > 0)
node.expanded = GUI.Toggle(nodeRect, node.expanded, GUIContent.none, "IN foldout");
nodeRect.x += 18;
if (node.isDirectory)
{
bool selected = node.selected;
using (new EditorGUI.DisabledGroupScope(node.children.Count == 0))
node.selected = GUI.Toggle(nodeRect, selected, GUIContent.none);
if (node.selected != selected)
SelectChildren(node, node.selected);
selectedChildren.Clear();
GetSelectedNodes(node, selectedChildren);
node.selected = selectedChildren.Count > 0;
}
else
node.selected = GUI.Toggle(nodeRect, node.selected, GUIContent.none);
nodeRect.x += 16;
node.RenderNode(nodeRect);
}
}
protected override void SelectItems()
{
selected.Clear();
GetSelectedNodes(root, selected);
EditorUtility.SetDirty(ModToolSettings.instance);
}
private void SelectAssets(List toBeSelected)
{
List selected = new List();
GetNodesByName(root, selected, toBeSelected);
foreach (var node in selected)
{
node.selected = true;
node.expanded = true;
}
}
private void GetNodesByName(FileNode root, List nodes, List names)
{
foreach (var node in root.children)
{
if (names.Contains(node.relativePath))
nodes.Add(node);
GetNodesByName(node, nodes, names);
}
}
private void GetSelectedNodes(FileNode root, List nodes)
{
foreach (var node in root.children)
{
if (node.selected)
nodes.Add(node);
GetSelectedNodes(node, nodes);
}
}
private void GetSelectedNodes(FileNode root, List selected)
{
foreach (var node in root.children)
{
if (!node.isDirectory && node.selected)
selected.Add(node.relativePath);
GetSelectedNodes(node, selected);
}
}
private void GetExpandedNodes(FileNode root, List nodes)
{
foreach (var node in root.children)
{
nodes.Add(node);
if (node.expanded)
GetExpandedNodes(node, nodes);
}
}
private void SelectChildren(FileNode root, bool select)
{
foreach (var node in root.children)
{
node.selected = select;
SelectChildren(node, select);
}
}
private void ExpandSelected(FileNode root)
{
List selected = new List();
GetSelectedNodes(root, selected);
if (selected.Count > 0)
root.expanded = true;
foreach (var node in root.children)
{
if (node.isDirectory)
ExpandSelected(node);
}
}
private class AlphabeticComparer : IComparer
{
public int Compare(FileNode a, FileNode b) => a.relativePath.CompareTo(b.relativePath);
}
private class FileNode
{
public bool selected { get; set; }
public bool expanded { get; set; }
public bool isDirectory { get; private set; }
public int depth { get; private set; }
public string name { get; private set; }
public string fullPath { get; private set; }
public string relativePath { get; private set; }
public List children { get; private set; }
private static IComparer alphabeticalComparer = new AlphabeticComparer();
private Texture icon;
public FileNode(FileSystemInfo fileInfo, int depth = 0)
{
fullPath = fileInfo.FullName;
name = fileInfo.Name;
this.depth = depth;
relativePath = "Assets/" + fullPath.Substring(Application.dataPath.Length + 1);
relativePath = relativePath.Replace("\\", "/");
children = new List();
if (fileInfo is DirectoryInfo)
{
icon = EditorGUIUtility.FindTexture("Folder Icon");
isDirectory = true;
foreach (FileSystemInfo fileSystemInfo in (fileInfo as DirectoryInfo).GetFileSystemInfos())
{
if (fileSystemInfo.Name.EndsWith(".meta") || fileSystemInfo.Name == "ModTool")
continue;
FileNode fileNode = new FileNode(fileSystemInfo, depth + 1);
children.Add(fileNode);
}
children.Sort(alphabeticalComparer);
}
else
{
icon = (AssetDatabase.GetCachedIcon(relativePath) as Texture2D);
if (icon)
return;
icon = EditorGUIUtility.ObjectContent(null, typeof(MonoBehaviour)).image;
}
}
public void RenderIconText()
{
GUILayout.Label(icon, GUILayout.Height(20f), GUILayout.Width(20f));
GUILayout.Label(name, GUILayout.Height(15f));
GUILayout.FlexibleSpace();
}
public void RenderNode(Rect rect)
{
rect.width = 20;
GUI.Label(rect, icon);
rect.x += 17;
rect.width = 200;
GUI.Label(rect, name);
}
}
}
}