音乐效果

This commit is contained in:
SoulliesOfficial
2025-05-21 02:23:25 -04:00
parent 1d176a606b
commit 9a02c62ac4
148 changed files with 243171 additions and 839 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 7f1ed5d1134de134a9e052ef368e3a84
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,304 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace vietlabs.fr2
{
public class AssetType
{
// ------------------------------- STATIC -----------------------------
internal static readonly AssetType[] FILTERS =
{
new AssetType("Scene", ".unity"),
new AssetType("Prefab", ".prefab"),
new AssetType("Model", ".3df", ".3dm", ".3dmf", ".3dv", ".3dx", ".c5d", ".lwo", ".lws", ".ma", ".mb",
".mesh", ".vrl", ".wrl", ".wrz", ".fbx", ".dae", ".3ds", ".dxf", ".obj", ".skp", ".max", ".blend"),
new AssetType("Material", ".mat", ".cubemap", ".physicsmaterial"),
new AssetType("Texture", ".ai", ".apng", ".png", ".bmp", ".cdr", ".dib", ".eps", ".exif", ".ico", ".icon",
".j", ".j2c", ".j2k", ".jas", ".jiff", ".jng", ".jp2", ".jpc", ".jpe", ".jpeg", ".jpf", ".jpg", "jpw",
"jpx", "jtf", ".mac", ".omf", ".qif", ".qti", "qtif", ".tex", ".tfw", ".tga", ".tif", ".tiff", ".wmf",
".psd", ".exr", ".rendertexture"),
new AssetType("Video", ".asf", ".asx", ".avi", ".dat", ".divx", ".dvx", ".mlv", ".m2l", ".m2t", ".m2ts",
".m2v", ".m4e", ".m4v", "mjp", ".mov", ".movie", ".mp21", ".mp4", ".mpe", ".mpeg", ".mpg", ".mpv2",
".ogm", ".qt", ".rm", ".rmvb", ".wmv", ".xvid", ".flv"),
new AssetType("Audio", ".mp3", ".wav", ".ogg", ".aif", ".aiff", ".mod", ".it", ".s3m", ".xm"),
new AssetType("Script", ".cs", ".js", ".boo", ".h"),
new AssetType("Text", ".txt", ".json", ".xml", ".bytes", ".sql"),
new AssetType("Shader", ".shader", ".cginc"),
new AssetType("Animation", ".anim", ".controller", ".overridecontroller", ".mask"),
new AssetType("Unity Asset", ".asset", ".guiskin", ".flare", ".fontsettings", ".prefs"),
new AssetType("Others") //
};
private static FR2_Ignore _ignore;
public HashSet<string> extension;
public string name;
public AssetType(string name, params string[] exts)
{
this.name = name;
extension = new HashSet<string>();
for (var i = 0; i < exts.Length; i++)
{
extension.Add(exts[i]);
}
}
private static FR2_Ignore ignore
{
get
{
if (_ignore == null)
{
_ignore = new FR2_Ignore();
}
return _ignore;
}
}
public static int GetIndex(string ext)
{
for (var i = 0; i < FILTERS.Length - 1; i++)
{
if (FILTERS[i].extension.Contains(ext))
{
return i;
}
}
return FILTERS.Length - 1; //Others
}
public static bool DrawSearchFilter()
{
int n = FILTERS.Length;
var nCols = 4;
int nRows = Mathf.CeilToInt(n / (float)nCols);
var result = false;
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
{
if (GUILayout.Button("All", EditorStyles.toolbarButton) && !FR2_Setting.IsIncludeAllType())
{
FR2_Setting.IncludeAllType();
result = true;
}
if (GUILayout.Button("None", EditorStyles.toolbarButton) && FR2_Setting.GetExcludeType() != -1)
{
FR2_Setting.ExcludeAllType();
result = true;
}
}
EditorGUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
for (var i = 0; i < nCols; i++)
{
GUILayout.BeginVertical();
for (var j = 0; j < nRows; j++)
{
int idx = i * nCols + j;
if (idx >= n)
{
break;
}
bool s = !FR2_Setting.IsTypeExcluded(idx);
bool s1 = GUILayout.Toggle(s, FILTERS[idx].name);
if (s1 != s)
{
result = true;
FR2_Setting.ToggleTypeExclude(idx);
}
}
GUILayout.EndVertical();
if ((i + 1) * nCols >= n)
{
break;
}
}
GUILayout.EndHorizontal();
return result;
}
public static void SetDirtyIgnore()
{
ignore.SetDirty();
}
public static bool DrawIgnoreFolder()
{
var change = false;
ignore.Draw();
// FR2_Helper.GuiLine();
// List<string> lst = FR2_Setting.IgnoreFolder.ToList();
// bool change = false;
// pos = EditorGUILayout.BeginScrollView(pos);
// for(int i =0; i < lst.Count; i++)
// {
// GUILayout.BeginHorizontal();
// {
// if(GUILayout.Button("X", GUILayout.Width(30)))
// {
// change = true;
// FR2_Setting.RemoveIgnore(lst[i]);
// }
// GUILayout.Label(lst[i]);
// }GUILayout.EndHorizontal();
// }
// EditorGUILayout.EndScrollView();
return change;
}
private class FR2_Ignore
{
public readonly FR2_TreeUI2.GroupDrawer groupIgnore;
private bool dirty;
private Dictionary<string, FR2_Ref> refs;
public FR2_Ignore()
{
groupIgnore = new FR2_TreeUI2.GroupDrawer(DrawGroup, DrawItem);
groupIgnore.hideGroupIfPossible = false;
ApplyFiter();
}
private void DrawItem(Rect r, string guid)
{
FR2_Ref rf;
if (!refs.TryGetValue(guid, out rf))
{
return;
}
if (rf.depth == 1) //mode != Mode.Dependency &&
{
Color c = GUI.color;
GUI.color = Color.blue;
GUI.DrawTexture(new Rect(r.x - 4f, r.y + 2f, 2f, 2f), EditorGUIUtility.whiteTexture);
GUI.color = c;
}
rf.asset.Draw(r, false,
true,
false, false, false, false, null);
Rect drawR = r;
drawR.x = drawR.x + drawR.width - 50f; // (groupDrawer.TreeNoScroll() ? 60f : 70f) ;
drawR.width = 30;
drawR.y += 1;
drawR.height -= 2;
if (GUI.Button(drawR, "X", EditorStyles.miniButton))
{
FR2_Setting.RemoveIgnore(rf.asset.assetPath);
}
}
private void DrawGroup(Rect r, string id, int childCound)
{
GUI.Label(r, id, EditorStyles.boldLabel);
if (childCound <= 1)
{
return;
}
Rect drawR = r;
drawR.x = drawR.x + drawR.width - 50f; // (groupDrawer.TreeNoScroll() ? 60f : 70f) ;
drawR.width = 30;
drawR.y += 1;
drawR.height -= 2;
}
public void SetDirty()
{
dirty = true;
}
//private float sizeRatio {
// get{
// if(FR2_Window.window != null)
// return FR2_Window.window.sizeRatio;
// return .3f;
// }
//}
public void Draw()
{
if (dirty)
{
ApplyFiter();
}
GUILayout.BeginHorizontal();
{
GUILayout.Space(4f);
var drops = GUI2.DropZone("Drag & Drop folders here to exclude", 100, 95);
if (drops != null && drops.Length > 0)
{
for (var i = 0; i < drops.Length; i++)
{
string path = AssetDatabase.GetAssetPath(drops[i]);
if (path.Equals(FR2_Cache.DEFAULT_CACHE_PATH))
{
continue;
}
FR2_Setting.AddIgnore(path);
}
}
groupIgnore.DrawLayout();
}
GUILayout.EndHorizontal();
}
private void ApplyFiter()
{
dirty = false;
refs = new Dictionary<string, FR2_Ref>();
//foreach (KeyValuePair<string, List<string>> item in FR2_Setting.IgnoreFiltered)
foreach (string item2 in FR2_Setting.s.listIgnore)
{
string guid = AssetDatabase.AssetPathToGUID(item2);
if (string.IsNullOrEmpty(guid))
{
continue;
}
FR2_Asset asset = FR2_Cache.Api.Get(guid, true);
var r = new FR2_Ref(0, 0, asset, null, "Ignore");
refs.Add(guid, r);
}
groupIgnore.Reset
(
refs.Values.ToList(),
rf => rf.asset != null ? rf.asset.guid : "",
GetGroup,
SortGroup
);
}
private string GetGroup(FR2_Ref rf)
{
return "Ignore";
}
private void SortGroup(List<string> groups) { }
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: af50e16ff6b530b4b808183a3ae0722b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,257 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace vietlabs.fr2
{
public class FR2_Bookmark : IRefDraw
{
internal static HashSet<string> guidSet = new HashSet<string>();
internal static HashSet<string> instSet = new HashSet<string>(); // Do not reference directly to SceneObject (which might be destroyed anytime)
public static int Count
{
get { return guidSet.Count + instSet.Count; }
}
public static bool Contains(string guidOrInstID)
{
return guidSet.Contains(guidOrInstID) || instSet.Contains(guidOrInstID);
}
public static bool Contains(UnityObject sceneObject)
{
var id = sceneObject.GetInstanceID().ToString();
return instSet.Contains(id);
}
public static bool Contains(FR2_Ref rf)
{
if (rf.isSceneRef)
{
if (instSet == null) return false;
return instSet.Contains(rf.component.GetInstanceID().ToString());
}
else
{
if (guidSet == null) return false;
return guidSet.Contains(rf.asset.guid);
}
}
public static void Add(UnityObject sceneObject)
{
if (sceneObject == null) return;
var id = sceneObject.GetInstanceID().ToString();
instSet.Add(id); // hashset does not need to check exist before add
dirty = true;
}
public static void Add(string guid)
{
if (guidSet.Contains(guid)) return;
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(assetPath))
{
Debug.LogWarning("Invalid GUID: " + guid);
return;
}
guidSet.Add(guid);
dirty = true;
//Debug.Log(instSet.Count + " : " + guidSet.Count);
}
public static void Remove(UnityObject sceneObject)
{
if (sceneObject == null) return;
var id = sceneObject.GetInstanceID().ToString();
instSet.Remove(id);
dirty = true;
}
public static void Remove(string guidOrInstID)
{
guidSet.Remove(guidOrInstID);
instSet.Remove(guidOrInstID);
dirty = true;
}
public static void Clear()
{
guidSet.Clear();
instSet.Clear();
dirty = true;
}
public static void Add(FR2_Ref rf)
{
if (rf.isSceneRef)
{
//Debug.Log("add " + rf.component);
Add(rf.component);
}
else
{
Add(rf.asset.guid);
}
}
public static void Remove(FR2_Ref rf)
{
if (rf.isSceneRef)
{
//Debug.Log("remove: " + rf.component);
Remove(rf.component);
}
else
{
Remove(rf.asset.guid);
}
}
public static void Commit()
{
var list = new List<Object>();
foreach (string guid in guidSet)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(Object));
if (obj != null) list.Add(obj);
}
foreach (string instID in instSet)
{
var id = int.Parse(instID);
var obj = EditorUtility.InstanceIDToObject(id);
if (obj != null) list.Add(obj);
}
Selection.objects = list.ToArray();
}
// ------------ instance
//private readonly FR2_TreeUI2.GroupDrawer groupDrawer;
private static bool dirty;
private readonly FR2_RefDrawer drawer;
internal Dictionary<string, FR2_Ref> refs = new Dictionary<string, FR2_Ref>();
public FR2_Bookmark(IWindow window)
{
this.window = window;
drawer = new FR2_RefDrawer(window);
drawer.messageNoRefs = "Do bookmark something!";
drawer.groupDrawer.hideGroupIfPossible = true;
drawer.forceHideDetails = true;
drawer.level0Group = string.Empty;
dirty = true;
drawer.SetDirty();
}
public IWindow window { get; set; }
public int ElementCount()
{
return refs == null ? 0 : refs.Count;
}
public bool DrawLayout()
{
if (dirty) RefreshView();
return drawer.DrawLayout();
}
public bool Draw(Rect rect)
{
if (dirty) RefreshView();
if (refs == null)
{
Debug.Log("Refs is null!");
return false;
}
var bottomRect = new Rect(rect.x + 1f, rect.yMax - 16f, rect.width - 2f, 16f);
DrawButtons(bottomRect);
rect.yMax -= 16f;
return drawer.Draw(rect);
}
public void SetDirty()
{
drawer.SetDirty();
}
void DrawButtons(Rect rect)
{
if (Count == 0) return;
GUILayout.BeginArea(rect);
{
GUILayout.BeginHorizontal();
{
if (GUILayout.Button("Select"))
{
Commit();
window.WillRepaint = true;
}
if (GUILayout.Button("Clear"))
{
Clear();
window.WillRepaint = true;
}
if (GUILayout.Button("CSV"))
{
FR2_Export.ExportCSV(refs.Values.ToArray());
}
if (GUILayout.Button("Delete"))
{
FR2_Unity.BackupAndDeleteAssets(refs.Values.ToArray());
Clear();
GUIUtility.ExitGUI();
}
}
GUILayout.EndHorizontal();
}
GUILayout.EndArea();
}
public void RefreshView()
{
if (refs == null) refs = new Dictionary<string, FR2_Ref>();
refs.Clear();
foreach (var guid in guidSet)
{
var asset = FR2_Cache.Api.Get(guid, false);
refs.Add(guid, new FR2_Ref(0, 0, asset, null));
}
foreach (var instId in instSet)
{
refs.Add(instId, new FR2_SceneRef(0, EditorUtility.InstanceIDToObject(int.Parse(instId))));
}
drawer.SetRefs(refs);
//Debug.Log("RefreshView: " + refs.Count);
dirty = false;
}
internal void RefreshSort()
{
drawer.RefreshSort();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 83d267126bcce4c9495361e0502fd04c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEditor;
using UnityEngine;
using vietlabs.fr2;
public class FR2_CSV
{
private const string SEPARATOR = ",";
public static string GetCSVRow(FR2_Ref r, params string[] suffixes)
{
var asset = r.asset;
var sr = r.isSceneRef ? (FR2_SceneRef)r : null;
var go = (GameObject)null;
if (sr != null)
{
if (sr.component is Component)
{
go = ((Component)sr.component).gameObject;
}
if (sr.component is GameObject)
{
go = (GameObject)sr.component;
}
}
var sb = new StringBuilder();
sb.Append(r.depth);
sb.Append(SEPARATOR);
sb.Append(r.isSceneRef ? sr.component.name : asset.assetName);
sb.Append(SEPARATOR);
sb.Append(r.isSceneRef ? FR2_SceneRef.FindUsageScene(new[] { go }, false).Count : asset.UsageCount());
sb.Append(SEPARATOR);
sb.Append(r.isSceneRef ? string.Empty : asset.extension);
sb.Append(SEPARATOR);
sb.Append(r.isSceneRef ? "0" : asset.fileSize.ToString());
sb.Append(SEPARATOR);
var type = r.isSceneRef ? "SceneObject" : "(missing)";
if (!r.isSceneRef)
{
var obj = AssetDatabase.GetMainAssetTypeAtPath(asset.assetPath);
if (obj != null) type = obj.ToString();
if (type.StartsWith("UnityEngine.") || type.StartsWith("UnityEditor."))
{
var idx = type.LastIndexOf(".", StringComparison.Ordinal) + 1;
type = type.Substring(idx, type.Length - idx);
}
}
sb.Append(type);
sb.Append(SEPARATOR);
sb.Append(r.isSceneRef ? string.Empty : asset.guid);
sb.Append(SEPARATOR);
sb.Append(r.isSceneRef ? string.Empty : asset.AtlasName);
sb.Append(SEPARATOR);
sb.Append(r.isSceneRef ? string.Empty : asset.AssetBundleName);
sb.Append(SEPARATOR);
sb.Append(r.group);
sb.Append(SEPARATOR);
sb.Append(r.isSceneRef ? sr.sceneFullPath : asset.assetPath);
foreach (var t in suffixes)
{
sb.Append(SEPARATOR);
sb.Append(t);
}
return sb.ToString();
}
public static string GetCSVTitle()
{
var sb = new StringBuilder();
sb.Append("depth");
sb.Append(SEPARATOR);
sb.Append("name");
sb.Append(SEPARATOR);
sb.Append("usage count");
sb.Append(SEPARATOR);
sb.Append("extension");
sb.Append(SEPARATOR);
sb.Append("size");
sb.Append(SEPARATOR);
sb.Append("type");
sb.Append(SEPARATOR);
sb.Append("guid");
sb.Append(SEPARATOR);
sb.Append("atlas");
sb.Append(SEPARATOR);
sb.Append("assetbundle");
sb.Append(SEPARATOR);
sb.Append("group");
sb.Append(SEPARATOR);
sb.Append("full path");
return sb.ToString();
}
public static string GetCSVRows(FR2_Ref[] source)
{
if (source == null)
{
//Debug.LogWarning("source should not be null!");
return string.Empty;
}
var sb = new StringBuilder();
sb.AppendLine(GetCSVTitle());
foreach (var s in source)
{
if (s == null) continue;
sb.AppendLine(GetCSVRow(s));
}
return sb.ToString();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ff73dd2521fff4f7d83012da98db1b89
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 933e0cc22e789714c87e348a699023d7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using UnityEditor;
using UnityEngine;
using vietlabs.fr2;
[CustomEditor(typeof(FR2_Cache))]
internal class FR2_CacheEditor : Editor
{
private static string inspectGUID;
private static int index;
public override void OnInspectorGUI()
{
var c = (FR2_Cache)target;
GUILayout.Label("Total : " + c.AssetList.Count);
FR2_Cache.DrawPriorityGUI();
Object s = Selection.activeObject;
if (s == null)
{
return;
}
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(s));
if (inspectGUID != guid)
{
inspectGUID = guid;
index = c.AssetList.FindIndex(item => item.guid == guid);
}
if (index != -1)
{
if (index >= c.AssetList.Count)
{
index = 0;
}
serializedObject.Update();
SerializedProperty prop = serializedObject.FindProperty("AssetList").GetArrayElementAtIndex(index);
EditorGUILayout.PropertyField(prop, true);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f9b9c04ea6b703343b8aff08a26cf9aa
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,831 @@
//#define FR2_DEBUG
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using CBParams = System.Collections.Generic.List<System.Collections.Generic.List<string>>;
using Object = UnityEngine.Object;
namespace vietlabs.fr2
{
internal class FR2_DuplicateTree2 : IRefDraw
{
private const float TimeDelayDelete = .5f;
private static readonly FR2_FileCompare fc = new FR2_FileCompare();
private readonly FR2_TreeUI2.GroupDrawer groupDrawer;
private CBParams cacheAssetList;
public bool caseSensitive = false;
private Dictionary<string, List<FR2_Ref>> dicIndex; //index, list
private bool dirty;
private int excludeCount;
private string guidPressDelete;
internal List<FR2_Ref> list;
internal Dictionary<string, FR2_Ref> refs;
public int scanExcludeByIgnoreCount;
public int scanExcludeByTypeCount;
private string searchTerm = "";
private float TimePressDelete;
public FR2_DuplicateTree2(IWindow window)
{
this.window = window;
groupDrawer = new FR2_TreeUI2.GroupDrawer(DrawGroup, DrawAsset);
}
public IWindow window { get; set; }
public bool Draw(Rect rect)
{
return false;
}
public bool DrawLayout()
{
if (dirty)
{
RefreshView(cacheAssetList);
}
if (fc.nChunks2 > 0 && fc.nScaned < fc.nChunks2)
{
Rect rect = GUILayoutUtility.GetRect(1, Screen.width, 18f, 18f);
float p = fc.nScaned / (float)fc.nChunks2;
EditorGUI.ProgressBar(rect, p, string.Format("Scanning {0} / {1}", fc.nScaned, fc.nChunks2));
GUILayout.FlexibleSpace();
return true;
}
if (groupDrawer.hasValidTree)
{
groupDrawer.tree.itemPaddingRight = 60f;
}
groupDrawer.DrawLayout();
DrawHeader();
return false;
}
public int ElementCount()
{
return list == null ? 0 : list.Count;
}
private void DrawAsset(Rect r, string guid)
{
FR2_Ref rf;
if (!refs.TryGetValue(guid, out rf))
{
return;
}
rf.asset.Draw(r, false,
FR2_Setting.GroupMode != FR2_RefDrawer.Mode.Folder,
FR2_Setting.ShowFileSize,
FR2_Setting.s.displayAssetBundleName,
FR2_Setting.s.displayAtlasName,
FR2_Setting.s.showUsedByClassed,
window);
Texture tex = AssetDatabase.GetCachedIcon(rf.asset.assetPath);
if (tex == null)
{
return;
}
Rect drawR = r;
drawR.x = drawR.x + drawR.width; // (groupDrawer.TreeNoScroll() ? 60f : 70f) ;
drawR.width = 40f;
drawR.y += 1;
drawR.height -= 2;
if (GUI.Button(drawR, "Use", EditorStyles.miniButton))
{
if (FR2_Export.IsMergeProcessing)
{
Debug.LogWarning("Previous merge is processing");
}
else
{
//AssetDatabase.SaveAssets();
//EditorGUIUtility.systemCopyBuffer = rf.asset.guid;
//EditorGUIUtility.systemCopyBuffer = rf.asset.guid;
// Debug.Log("guid: " + rf.asset.guid + " systemCopyBuffer " + EditorGUIUtility.systemCopyBuffer);
int index = rf.index;
Selection.objects = list.Where(x => x.index == index)
.Select(x => FR2_Unity.LoadAssetAtPath<Object>(x.asset.assetPath)).ToArray();
FR2_Export.MergeDuplicate(rf.asset.guid);
}
}
if (rf.asset.UsageCount() > 0)
{
return;
}
drawR.x -= 25;
drawR.width = 20;
if (wasPreDelete(guid))
{
Color col = GUI.color;
GUI.color = Color.red;
if (GUI.Button(drawR, "X", EditorStyles.miniButton))
{
guidPressDelete = null;
AssetDatabase.DeleteAsset(rf.asset.assetPath);
}
GUI.color = col;
window.WillRepaint = true;
}
else
{
if (GUI.Button(drawR, "X", EditorStyles.miniButton))
{
guidPressDelete = guid;
TimePressDelete = Time.realtimeSinceStartup;
window.WillRepaint = true;
}
}
}
private bool wasPreDelete(string guid)
{
if (guidPressDelete == null || guid != guidPressDelete)
{
return false;
}
if (Time.realtimeSinceStartup - TimePressDelete < TimeDelayDelete)
{
return true;
}
guidPressDelete = null;
return false;
}
private void DrawGroup(Rect r, string label, int childCount)
{
// GUI.Label(r, label + " (" + childCount + ")", EditorStyles.boldLabel);
FR2_Asset asset = dicIndex[label][0].asset;
Texture tex = AssetDatabase.GetCachedIcon(asset.assetPath);
Rect rect = r;
if (tex != null)
{
rect.width = 16f;
GUI.DrawTexture(rect, tex);
}
rect = r;
rect.xMin += 16f;
GUI.Label(rect, asset.assetName, EditorStyles.boldLabel);
rect = r;
rect.xMin += rect.width - 50f;
GUI.Label(rect, FR2_Helper.GetfileSizeString(asset.fileSize), EditorStyles.miniLabel);
rect = r;
rect.xMin += rect.width - 70f;
GUI.Label(rect, childCount.ToString(), EditorStyles.miniLabel);
rect = r;
rect.xMin += rect.width - 70f;
}
// private List<FR2_DuplicateFolder> duplicated;
public void Reset(CBParams assetList)
{
fc.Reset(assetList, OnUpdateView, RefreshView);
}
private void OnUpdateView(CBParams assetList) { }
public bool isExclueAnyItem()
{
return excludeCount > 0 || scanExcludeByTypeCount > 0;
}
public bool isExclueAnyItemByIgnoreFolder()
{
return scanExcludeByIgnoreCount > 0;
}
// void OnActive
private void RefreshView(CBParams assetList)
{
cacheAssetList = assetList;
dirty = false;
list = new List<FR2_Ref>();
refs = new Dictionary<string, FR2_Ref>();
dicIndex = new Dictionary<string, List<FR2_Ref>>();
if (assetList == null)
{
return;
}
int minScore = searchTerm.Length;
string term1 = searchTerm;
if (!caseSensitive)
{
term1 = term1.ToLower();
}
string term2 = term1.Replace(" ", string.Empty);
excludeCount = 0;
for (var i = 0; i < assetList.Count; i++)
{
var lst = new List<FR2_Ref>();
for (var j = 0; j < assetList[i].Count; j++)
{
var path = assetList[i][j];
if (!path.StartsWith("Assets/"))
{
Debug.LogWarning("Ignore asset: " + path);
continue;
}
string guid = AssetDatabase.AssetPathToGUID(path);
if (string.IsNullOrEmpty(guid))
{
continue;
}
if (refs.ContainsKey(guid))
{
continue;
}
FR2_Asset asset = FR2_Cache.Api.Get(guid);
if (asset == null) continue;
if (!asset.assetPath.StartsWith("Assets/")) continue; // ignore builtin, packages, ...
var fr2 = new FR2_Ref(i, 0, asset, null);
if (FR2_Setting.IsTypeExcluded(fr2.type))
{
excludeCount++;
continue; //skip this one
}
if (string.IsNullOrEmpty(searchTerm))
{
fr2.matchingScore = 0;
list.Add(fr2);
lst.Add(fr2);
refs.Add(guid, fr2);
continue;
}
//calculate matching score
string name1 = fr2.asset.assetName;
if (!caseSensitive)
{
name1 = name1.ToLower();
}
string name2 = name1.Replace(" ", string.Empty);
int score1 = FR2_Unity.StringMatch(term1, name1);
int score2 = FR2_Unity.StringMatch(term2, name2);
fr2.matchingScore = Mathf.Max(score1, score2);
if (fr2.matchingScore > minScore)
{
list.Add(fr2);
lst.Add(fr2);
refs.Add(guid, fr2);
}
}
dicIndex.Add(i.ToString(), lst);
}
ResetGroup();
}
private void ResetGroup()
{
groupDrawer.Reset(list,
rf => rf.asset.guid
, GetGroup, SortGroup);
if (window != null)
{
window.Repaint();
}
}
private string GetGroup(FR2_Ref rf)
{
return rf.index.ToString();
}
private void SortGroup(List<string> groups)
{
// groups.Sort( (item1, item2) =>
// {
// if (item1 == "Others" || item2 == "Selection") return 1;
// if (item2 == "Others" || item1 == "Selection") return -1;
// return item1.CompareTo(item2);
// });
}
public void SetDirty()
{
dirty = true;
}
public void RefreshSort() { }
private void DrawHeader()
{
var text = groupDrawer.hasValidTree ? "Rescan" : "Scan";
if (GUILayout.Button(text))
{
// if (FR2_Cache)
{
OnCacheReady();
return;
}
// FR2_Cache.onReady -= OnCacheReady;
// FR2_Cache.onReady += OnCacheReady;
// FR2_Cache.Api.Check4Changes(false);
}
}
private void OnCacheReady()
{
scanExcludeByTypeCount = 0;
Reset(FR2_Cache.Api.ScanSimilar(IgnoreTypeWhenScan, IgnoreFolderWhenScan));
FR2_Cache.onReady -= OnCacheReady;
}
private void IgnoreTypeWhenScan()
{
scanExcludeByTypeCount++;
}
private void IgnoreFolderWhenScan()
{
scanExcludeByIgnoreCount++;
}
}
internal class FR2_FileCompare
{
public static HashSet<FR2_Chunk> HashChunksNotComplete;
internal static int streamClosedCount;
private CBParams cacheList;
public List<FR2_Head> deads = new List<FR2_Head>();
public List<FR2_Head> heads = new List<FR2_Head>();
public int nChunks;
public int nChunks2;
public int nScaned;
public Action<CBParams> OnCompareComplete;
public Action<CBParams> OnCompareUpdate;
// private int streamCount;
public void Reset(CBParams list, Action<CBParams> onUpdate, Action<CBParams> onComplete)
{
nChunks = 0;
nScaned = 0;
nChunks2 = 0;
// streamCount = streamClosedCount = 0;
HashChunksNotComplete = new HashSet<FR2_Chunk>();
if (heads.Count > 0)
{
for (var i = 0; i < heads.Count; i++)
{
heads[i].CloseChunk();
}
}
deads.Clear();
heads.Clear();
OnCompareUpdate = onUpdate;
OnCompareComplete = onComplete;
if (list.Count <= 0)
{
OnCompareComplete(new CBParams());
return;
}
cacheList = list;
for (var i = 0; i < list.Count; i++)
{
var file = new FileInfo(list[i][0]);
int nChunk = Mathf.CeilToInt(file.Length / (float)FR2_Head.chunkSize);
nChunks2 += nChunk;
}
// for(int i =0;i< list.Count;i++)
// {
// AddHead(list[i]);
// }
AddHead(cacheList[cacheList.Count - 1]);
cacheList.RemoveAt(cacheList.Count - 1);
EditorApplication.update -= ReadChunkAsync;
EditorApplication.update += ReadChunkAsync;
}
public FR2_FileCompare AddHead(List<string> files)
{
if (files.Count < 2)
{
Debug.LogWarning("Something wrong ! head should not contains < 2 elements");
}
var chunkList = new List<FR2_Chunk>();
for (var i = 0; i < files.Count; i++)
{
// streamCount++;
// try
// {
// Debug.Log("new stream ");
// stream = new FileStream(files[i], FileMode.Open, FileAccess.Read);
// }
// catch (Exception e)
// {
// Debug.LogWarning(e + "\nCan not open file: " + files[i]);
// if (stream != null) stream.Close();
// continue;
// }
chunkList.Add(new FR2_Chunk
{
file = files[i],
buffer = new byte[FR2_Head.chunkSize]
});
}
var file = new FileInfo(files[0]);
int nChunk = Mathf.CeilToInt(file.Length / (float)FR2_Head.chunkSize);
heads.Add(new FR2_Head
{
fileSize = file.Length,
currentChunk = 0,
nChunk = nChunk,
chunkList = chunkList
});
nChunks += nChunk;
return this;
}
// private bool checkCompleteAllCurFile()
// {
// return streamClosedCount + HashChunksNotComplete.Count >= streamCount; //-1 for safe
// }
private void ReadChunkAsync()
{
bool alive = ReadChunk();
if (alive)
{
return;
}
if (cacheList.Count > 0)
{
AddHead(cacheList[cacheList.Count - 1]);
cacheList.RemoveAt(cacheList.Count - 1);
}
var update = false;
for (int i = heads.Count - 1; i >= 0; i--)
{
FR2_Head h = heads[i];
if (!h.isDead) continue;
h.CloseChunk();
heads.RemoveAt(i);
if (h.chunkList.Count > 1)
{
update = true;
deads.Add(h);
}
}
if (update)
{
Trigger(OnCompareUpdate);
}
if (!alive && cacheList.Count <= 0) //&& cacheList.Count <= 0 complete all chunk and cache list empty
{
foreach (FR2_Chunk item in HashChunksNotComplete)
{
if (item.stream != null && item.stream.CanRead)
{
Debug.Log("Close Stream!");
item.stream.Close();
item.stream = null;
}
}
HashChunksNotComplete.Clear();
// Debug.Log("complete ");
nScaned = nChunks;
EditorApplication.update -= ReadChunkAsync;
Trigger(OnCompareComplete);
}
}
private void Trigger(Action<CBParams> cb)
{
if (cb == null)
{
return;
}
CBParams list = deads.Select(item => item.GetFiles()).ToList();
//#if FR2_DEBUG
// Debug.Log("Callback ! " + deads.Count + ":" + heads.Count);
//#endif
cb(list);
}
private bool ReadChunk()
{
var alive = false;
for (var i = 0; i < heads.Count; i++)
{
FR2_Head h = heads[i];
if (h.isDead)
{
//Debug.LogWarning("Should never be here : " + h.chunkList[0].file);
continue;
}
nScaned++;
alive = true;
h.ReadChunk();
h.CompareChunk(heads);
break;
}
//if (!alive) return false;
//alive = false;
//for (var i = 0; i < heads.Count; i++)
//{
// var h = heads[i];
// if (h.isDead) continue;
// h.CompareChunk(heads);
// alive |= !h.isDead;
//}
return alive;
}
}
internal class FR2_Head
{
public const int chunkSize = 10240;
public List<FR2_Chunk> chunkList;
public int currentChunk;
public long fileSize;
public int nChunk;
public int size; //last stream read size
public bool isDead
{
get { return currentChunk == nChunk || chunkList.Count == 1; }
}
public List<string> GetFiles()
{
return chunkList.Select(item => item.file).ToList();
}
public void AddToDict(byte b, FR2_Chunk chunk, Dictionary<byte, List<FR2_Chunk>> dict)
{
List<FR2_Chunk> list;
if (!dict.TryGetValue(b, out list))
{
list = new List<FR2_Chunk>();
dict.Add(b, list);
}
list.Add(chunk);
}
public void CloseChunk()
{
for (var i = 0; i < chunkList.Count; i++)
{
FR2_FileCompare.streamClosedCount++;
if (chunkList[i].stream != null)
{
#if FR2_DEBUG
Debug.Log("stream close: " + chunkList[i].file);
#endif
chunkList[i].stream.Close();
chunkList[i].stream = null;
}
}
}
public void ReadChunk()
{
#if FR2_DEBUG
if (currentChunk == 0) Debug.LogWarning("Read <" + chunkList[0].file + "> " + currentChunk + ":" + nChunk);
#endif
if (currentChunk == nChunk)
{
Debug.LogWarning("Something wrong, should dead <" + isDead + ">");
return;
}
int from = currentChunk * chunkSize;
size = (int)Mathf.Min(fileSize - from, chunkSize);
for (var i = 0; i < chunkList.Count; i++)
{
FR2_Chunk chunk = chunkList[i];
if (chunk.streamError) continue;
chunk.size = size;
if (chunk.streamInited == false)
{
chunk.streamInited = true;
try
{
#if FR2_DEBUG
Debug.Log("New chunk: " + chunk.file);
#endif
chunk.stream = new FileStream(chunk.file, FileMode.Open, FileAccess.Read);
}
#if FR2_DEBUG
catch (Exception e)
{
Debug.LogWarning("Exception: " + e + "\n" + chunk.file + "\n" + chunk.stream);
#else
catch {
#endif
chunk.streamError = true;
if (chunk.stream != null) // just to make sure we close the stream
{
chunk.stream.Close();
chunk.stream = null;
}
}
if (chunk.stream == null)
{
chunk.streamError = true;
continue;
}
}
try
{
chunk.stream.Read(chunk.buffer, 0, size);
}
catch (Exception e)
{
Debug.LogWarning(e + "\n" + chunk.file);
chunk.streamError = true;
chunk.stream.Close();
}
}
// clean up dead chunks
for (var i = chunkList.Count-1; i>=0; i--)
{
if (chunkList[i].streamError) chunkList.RemoveAt(i);
}
if (chunkList.Count == 1)
{
Debug.LogWarning("No more chunk in list");
}
currentChunk++;
}
public void CompareChunk(List<FR2_Head> heads)
{
int idx = chunkList.Count;
byte[] buffer = chunkList[idx - 1].buffer;
while (--idx >= 0)
{
FR2_Chunk chunk = chunkList[idx];
int diff = FirstDifferentIndex(buffer, chunk.buffer, size);
if (diff == -1)
{
continue;
}
#if FR2_DEBUG
Debug.Log(string.Format(
" --> Different found at : idx={0} diff={1} size={2} chunk={3}",
idx, diff, size, currentChunk));
#endif
byte v = buffer[diff];
var d = new Dictionary<byte, List<FR2_Chunk>>(); //new heads
chunkList.RemoveAt(idx);
FR2_FileCompare.HashChunksNotComplete.Add(chunk);
AddToDict(chunk.buffer[diff], chunk, d);
for (int j = idx - 1; j >= 0; j--)
{
FR2_Chunk tChunk = chunkList[j];
byte tValue = tChunk.buffer[diff];
if (tValue == v)
{
continue;
}
idx--;
FR2_FileCompare.HashChunksNotComplete.Add(tChunk);
chunkList.RemoveAt(j);
AddToDict(tChunk.buffer[diff], tChunk, d);
}
foreach (KeyValuePair<byte, List<FR2_Chunk>> item in d)
{
List<FR2_Chunk> list = item.Value;
if (list.Count == 1)
{
#if FR2_DEBUG
Debug.Log(" --> Dead head found for : " + list[0].file);
#endif
if (list[0].stream != null) list[0].stream.Close();
}
else if (list.Count > 1) // 1 : dead head
{
#if FR2_DEBUG
Debug.Log(" --> NEW HEAD : " + list[0].file);
#endif
heads.Add(new FR2_Head
{
nChunk = nChunk,
fileSize = fileSize,
currentChunk = currentChunk - 1,
chunkList = list
});
}
}
}
}
internal static int FirstDifferentIndex(byte[] arr1, byte[] arr2, int maxIndex)
{
for (var i = 0; i < maxIndex; i++)
{
if (arr1[i] != arr2[i])
{
return i;
}
}
return -1;
}
}
internal class FR2_Chunk
{
public byte[] buffer;
public string file;
public long size;
public bool streamInited = false;
public bool streamError = false;
public FileStream stream;
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d5c2f1d0a3c6acc4a9cf0d8f013f14d3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,643 @@
//#define REPLACE_SAME_TYPE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;
namespace vietlabs.fr2
{
public class FR2_Export
{
// private static int processIndex;
private const int maxThread = 5;
//[MenuItem("Assets/FR2/Tools/Merge Duplicates")]
private static Dictionary<string, ProcessReplaceData> listReplace;
private static HashSet<string> cacheSelection;
private static List<Thread> lstThreads;
public static bool IsMergeProcessing { get; private set; }
public static void ExportCSV(FR2_Ref[] csvSource)
{
var result = FR2_CSV.GetCSVRows(csvSource);
if (result.Length > 0)
{
EditorGUIUtility.systemCopyBuffer = result;
Debug.Log("[FR2] CSV file content (" + csvSource.Length + " assets) copied to clipboard!");
}
else
{
Debug.LogWarning("[FR2] Nothing to export!");
}
}
[MenuItem("Assets/FR2/Toggle Ignore", false, 19)]
private static void Ignore()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return;
}
Object[] actives = Selection.objects;
for (var i = 0; i < actives.Length; i++)
{
string path = AssetDatabase.GetAssetPath(actives[i]);
if (path.Equals(FR2_Cache.DEFAULT_CACHE_PATH))
{
continue;
}
if (FR2_Setting.IgnoreAsset.Contains(path))
{
FR2_Setting.RemoveIgnore(path);
}
else
{
FR2_Setting.AddIgnore(path);
}
}
}
[MenuItem("Assets/FR2/Copy GUID", false, 20)]
private static void CopyGUID()
{
EditorGUIUtility.systemCopyBuffer = AssetDatabase.AssetPathToGUID(
AssetDatabase.GetAssetPath(Selection.activeObject)
);
}
[MenuItem("Assets/FR2/Export Selection", false, 21)]
private static void ExportSelection()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return;
}
FR2_Unity.ExportSelection();
}
[MenuItem("Assets/FR2/Select Dependencies (assets I use)", false, 22)]
private static void SelectDependencies_wtme()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return;
}
SelectDependencies(false);
}
[MenuItem("Assets/FR2/Refresh")]
public static void ForceRefreshSelection()
{
var guids = Selection.assetGUIDs;
if (!FR2_Cache.isReady) return; // cache not ready!
for (var i = 0; i < guids.Length; i++)
{
string guid = guids[i];
if (guid == FR2_Cache.CachePath)
{
continue;
}
if (!FR2_Asset.IsValidGUID(guid))
{
continue;
}
if (FR2_Cache.Api.AssetMap.ContainsKey(guid))
{
FR2_Cache.Api.RefreshAsset(guid, true);
#if FR2_DEBUG
UnityEngine.Debug.Log("Changed : " + guids[i]);
#endif
continue;
}
FR2_Cache.Api.AddAsset(guid);
}
FR2_Cache.Api.Check4Work();
}
[MenuItem("Assets/FR2/Select Dependencies included me", false, 23)]
private static void SelectDependencies_wme()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return;
}
SelectDependencies(true);
}
//[MenuItem("Assets/FR2/Select")]
[MenuItem("Assets/FR2/Select Used (assets used me)", false, 24)]
private static void SelectUsed_wtme()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return;
}
SelectUsed(false);
}
[MenuItem("Assets/FR2/Select Used included me", false, 25)]
private static void SelectUsed_wme()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return;
}
SelectUsed(true);
}
[MenuItem("Assets/FR2/Export Dependencies", false, 40)]
private static void ExportDependencies()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return;
}
var deps = GetSelectionDependencies();
if (deps == null) return;
Selection.objects = deps.ToArray();
FR2_Unity.ExportSelection();
}
[MenuItem("Assets/FR2/Export Assets (no scripts)", false, 41)]
private static void ExportAsset()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return;
}
List<Object> list = GetSelectionDependencies();
for (int i = list.Count - 1; i >= 0; i--)
{
if (list[i] is MonoScript)
{
list.RemoveAt(i);
}
}
//Debug.Log(i + ":" + list[i] + ":" + list[i].GetType());
Selection.objects = list.ToArray();
FR2_Unity.ExportSelection();
}
public static void MergeDuplicate(string guid_file)
{
// for (int i = 0; i < Selection.objects.Length; i++)
// {
// Object item = Selection.objects[i];
// Debug.Log(item.name);
// }
//string guid_file = EditorGUIUtility.systemCopyBuffer;
long toFileId = 0;
var string_arr = guid_file.Split('/');
if (string_arr.Length > 1)
{
toFileId = long.Parse(string_arr[1]);
}
string guid = string_arr[0];
// var wat = new System.Diagnostics.Stopwatch();
// wat.Start();
//validate clipboard guid
string gPath = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(gPath) || !gPath.StartsWith("Assets/"))
{
Debug.LogWarning("Invalid guid <" + guid + "> in clipboard, can not replace !");
return;
}
var temp = FR2_Unity.Selection_AssetGUIDs;//cheat refresh selection, DO NOT delete
HashSet<string> guids_files = FR2_Unity._Selection_AssetGUIDs;
var realKey = "";
foreach (var item in guids_files)
{
if (item.StartsWith(guid_file, System.StringComparison.Ordinal))
{
realKey = item;
}
}
if (string.IsNullOrEmpty(realKey))
{
Debug.LogWarning("Clipboard guid <" + guid +
"> not found in Selection, you may not intentionally replace selection assets by clipboard guid");
// foreach (var item in guids_files) {
// Debug.Log ("item: " + item);
// }
return;
}
guids_files.Remove(realKey);
cacheSelection = new HashSet<string>();
foreach (var item in cacheSelection)
{
cacheSelection.Add(item);
}
if (guids_files.Count == 0)
{
Debug.LogWarning("No new asset selected to replace, must select all duplications to replace");
return;
}
//check asset type, only replace same type
#if REPLACE_SAME_TYPE
var type1 = AssetDatabase.GetMainAssetTypeAtPath(gPath);
var importType1 = AssetImporter.GetAtPath(gPath);
#endif
List<FR2_Asset> assetList = new List<FR2_Asset>();
var lstFind = new List<string>();
foreach (var item in guids_files)
{
var arr = item.Split('/');
string g = arr[0];
#if REPLACE_SAME_TYPE
var p2 = AssetDatabase.GUIDToAssetPath(g);
var type2 = AssetDatabase.GetMainAssetTypeAtPath(p2);
if(type1 != type2)
{
Debug.LogWarning("Cannot replace asset: " + p2 + " becase difference type");
continue;
}
if(type1 == typeof(UnityEngine.Texture2D))
{
var importType2 = AssetImporter.GetAtPath(p2) as TextureImporter;
var textureImportType1 = importType1 as TextureImporter;
if (importType2 == null || textureImportType1 == null)
{
Debug.LogWarning("Cannot replace asset: " + p2 + " becase difference type");
continue;
}
if(textureImportType1.textureType != importType2.textureType)
{
Debug.LogWarning("Cannot replace asset: " + p2 + " becase difference type");
continue;
}
if (textureImportType1.textureType == TextureImporterType.Sprite)
{
if (textureImportType1.spriteImportMode != importType2.spriteImportMode)
{
Debug.LogWarning("Cannot replace asset: " + p2 + " becase difference type");
continue;
}
}
//Debug.Log("import type " + mainImportType);
}
//Debug.Log("type: " + mainType);
#endif
lstFind.Add(g);
// if (arr.Length > 1)
// {
// long file = long.Parse(arr[1]);
//
// }
}
if (lstFind.Count == 0)
{
Debug.LogWarning("No new asset selected to replace, must select all duplications to replace");
return;
}
assetList = FR2_Cache.Api.FindAssets(lstFind.ToArray(), false);
//replace one by one
listReplace = new Dictionary<string, ProcessReplaceData>();
lstThreads = new List<Thread>();
for (int i = assetList.Count - 1; i >= 0; i--)
{
//Debug.Log("FR2 Replace GUID : " + assetList[i].guid + " ---> " + guid + " : " + assetList[i].UsedByMap.Count + " assets updated");
string fromId = assetList[i].guid;
List<FR2_Asset> arr = assetList[i].UsedByMap.Values.ToList();
for (var j = 0; j < arr.Count; j++)
{
FR2_Asset a = arr[j];
if (!listReplace.ContainsKey(a.assetPath))
{
listReplace.Add(a.assetPath, new ProcessReplaceData());
}
listReplace[a.assetPath].datas.Add(new ReplaceData
{
from = fromId,
to = guid,
asset = a,
toFileId = toFileId
});
}
}
foreach (KeyValuePair<string, ProcessReplaceData> item in listReplace)
{
item.Value.processIndex = item.Value.datas.Count - 1;
}
IsMergeProcessing = true;
EditorApplication.update -= ApplicationUpdate;
EditorApplication.update += ApplicationUpdate;
// for (var i = assetList.Count - 1; i >= 0; i--)
// {
// // Debug.Log("FR2 Replace GUID : " + assetList[i].guid + " ---> " + guid + " : " + assetList[i].UsedByMap.Count + " assets updated");
// var from = assetList[i].guid;
// var arr = assetList[i].UsedByMap.Values.ToList();
// for (var j = 0; j < arr.Count; j ++)
// {
// var a = arr[j];
// var result = a.ReplaceReference(from, guid);
// if (result && !dictAsset.ContainsKey(a.guid))
// {
// dictAsset.Add(a.guid, 1);
// }
// }
// }
// Debug.Log("Time replace guid " + wat.ElapsedMilliseconds);
// wat = new System.Diagnostics.Stopwatch();
// wat.Start();
// var listRefresh = dictAsset.Keys.ToList();
// for (var i = 0; i < listRefresh.Count; i++)
// {
// FR2_Cache.Api.RefreshAsset(listRefresh[i], true);
// }
// FR2_Cache.Api.RefreshSelection();
// FR2_Cache.Api.Check4Usage();
// AssetDatabase.Refresh();
// Debug.Log("Time replace guid " + wat.ElapsedMilliseconds);
}
private static void ApplicationUpdate()
{
bool notComplete = listReplace.Where(x => x.Value.processIndex >= 0).Count() > 0;
if (lstThreads.Count <= 0 && notComplete)
{
foreach (KeyValuePair<string, ProcessReplaceData> item in listReplace)
{
if (item.Value.processIndex >= 0)
{
ReplaceData a = item.Value.datas[item.Value.processIndex--];
a.isTerrian = a.asset.type == FR2_AssetType.TERRAIN;
if (a.isTerrian)
{
a.terrainData =
AssetDatabase.LoadAssetAtPath(a.asset.assetPath, typeof(Object)) as TerrainData;
}
a.isSucess = a.asset.ReplaceReference(a.from, a.to, a.toFileId, a.terrainData);
}
}
}
for (int i = lstThreads.Count - 1; i >= 0; i--)
{
if (!lstThreads[i].IsAlive)
{
lstThreads.RemoveAt(i);
}
}
//if (lstThreads.Count <= 0 && !notComplete) //complete
{
foreach (KeyValuePair<string, ProcessReplaceData> item in listReplace)
{
List<ReplaceData> lst = item.Value.datas;
for (var i = 0; i < lst.Count; i++)
{
ReplaceData data = lst[i];
if (!data.isUpdated && data.isSucess)
{
data.isUpdated = true;
if (data.isTerrian)
{
EditorUtility.SetDirty(data.terrainData);
AssetDatabase.SaveAssets();
data.terrainData = null;
FR2_Unity.UnloadUnusedAssets();
}
else
{
try
{
AssetDatabase.ImportAsset(data.asset.assetPath, ImportAssetOptions.Default);
}
catch (Exception e)
{
Debug.LogWarning(data.asset.assetPath + "\n" + e);
}
}
}
}
}
var guidsRefreshed = new HashSet<string>();
EditorApplication.update -= ApplicationUpdate;
foreach (KeyValuePair<string, ProcessReplaceData> item in listReplace)
{
List<ReplaceData> lst = item.Value.datas;
for (var i = 0; i < lst.Count; i++)
{
ReplaceData data = lst[i];
if (data.isSucess && !guidsRefreshed.Contains(data.asset.guid))
{
guidsRefreshed.Add(data.asset.guid);
FR2_Cache.Api.RefreshAsset(data.asset.guid, true);
}
}
}
lstThreads = null;
listReplace = null;
FR2_Cache.Api.RefreshSelection();
FR2_Cache.Api.Check4Work();
AssetDatabase.Refresh();
IsMergeProcessing = false;
}
}
//[MenuItem("Assets/FR2/Tools/Fix Model Import Material")]
//public static void FixModelImportMaterial(){
// if (Selection.activeObject == null) return;
// CreatePrefabReplaceModel((GameObject)Selection.activeObject);
//}
//[MenuItem("GameObject/FR2/Paste Materials", false, 10)]
//public static void PasteMaterials(){
// if (Selection.activeObject == null) return;
// var r = Selection.activeGameObject.GetComponent<Renderer>();
// Undo.RecordObject(r, "Replace Materials");
// r.materials = model_materials;
// EditorUtility.SetDirty(r);
//}
//[MenuItem("GameObject/FR2/Copy Materials", false, 10)]
//public static void CopyMaterials(){
// if (Selection.activeObject == null) return;
// var r = Selection.activeGameObject.GetComponent<Renderer>();
// if (r == null) return;
// model_materials = r.sharedMaterials;
//}
//-------------------------- APIs ----------------------
private static void SelectDependencies(bool includeMe)
{
List<FR2_Asset> list = FR2_Cache.Api.FindAssets(FR2_Unity.Selection_AssetGUIDs, false);
var dict = new Dictionary<string, Object>();
if (includeMe)
{
AddToDict(dict, list.ToArray());
}
for (var i = 0; i < list.Count; i++)
{
AddToDict(dict, FR2_Asset.FindUsage(list[i]).ToArray());
}
Selection.objects = dict.Values.ToArray();
}
private static void SelectUsed(bool includeMe)
{
List<FR2_Asset> list = FR2_Cache.Api.FindAssets(FR2_Unity.Selection_AssetGUIDs, false);
var dict = new Dictionary<string, Object>();
if (includeMe)
{
AddToDict(dict, list.ToArray());
}
for (var i = 0; i < list.Count; i++)
{
AddToDict(dict, list[i].UsedByMap.Values.ToArray());
}
Selection.objects = dict.Values.ToArray();
}
//-------------------------- UTILS ---------------------
internal static void AddToDict(Dictionary<string, Object> dict, params FR2_Asset[] list)
{
for (var j = 0; j < list.Length; j++)
{
string guid = list[j].guid;
if (!dict.ContainsKey(guid))
{
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
dict.Add(guid, FR2_Unity.LoadAssetAtPath<Object>(assetPath));
}
}
}
private static List<Object> GetSelectionDependencies()
{
if (!FR2_Cache.isReady)
{
Debug.LogWarning("FR2 cache not yet ready, please open Window > FR2_Window and hit scan project!");
return null;
}
return FR2_Cache.FindUsage(FR2_Unity.Selection_AssetGUIDs).Select(
guid =>
{
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
return FR2_Unity.LoadAssetAtPath<Object>(assetPath);
}
).ToList();
}
private class ProcessReplaceData
{
public readonly List<ReplaceData> datas = new List<ReplaceData>();
public int processIndex;
}
private class ReplaceData
{
public FR2_Asset asset;
public string from;
public bool isSucess;
public bool isTerrian;
public bool isUpdated;
public TerrainData terrainData;
public string to;
public long toFileId;
}
// AssetDatabase.ImportAsset(oAssetPath, ImportAssetOptions.Default);
// importer.importMaterials = false;
// var importer = AssetImporter.GetAtPath(oAssetPath) as ModelImporter;
// var nModel = AssetDatabase.LoadAssetAtPath<GameObject>(oAssetPath);
// // Reimport model with importMaterial = false
// var extension = Path.GetExtension(oAssetPath);
// model_materials = model.GetComponent<Renderer>().sharedMaterials;
// var oGUID = AssetDatabase.AssetPathToGUID(oAssetPath);
// var oAssetPath = AssetDatabase.GetAssetPath(model);
// if (model == null) return;
//{
//static void CreatePrefabReplaceModel(GameObject model)
//static Material[] model_materials;
// //create prefab from new model
// var prefabPath = oAssetPath.Replace(extension, ".prefab");
// var clone = (GameObject)Object.Instantiate(nModel);
// clone.GetComponent<Renderer>().sharedMaterials = model_materials;
// PrefabUtility.CreatePrefab(prefabPath, clone, ReplacePrefabOptions.ReplaceNameBased);
// AssetDatabase.SaveAssets();
// GameObject.DestroyImmediate(clone);
//}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: b543c2ce7dc56c2418505cbb6cb7852d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,211 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace vietlabs.fr2
{
public class FR2_Helper
{
internal static readonly AssetType[] FILTERS =
{
new AssetType("Scene", ".unity"),
new AssetType("Prefab", ".prefab"),
new AssetType("Model", ".3df", ".3dm", ".3dmf", ".3dv", ".3dx", ".c5d", ".lwo", ".lws", ".ma", ".mb",
".mesh", ".vrl", ".wrl", ".wrz", ".fbx", ".dae", ".3ds", ".dxf", ".obj", ".skp", ".max", ".blend"),
new AssetType("Material", ".mat", ".cubemap", ".physicsmaterial"),
new AssetType("Texture", ".ai", ".apng", ".png", ".bmp", ".cdr", ".dib", ".eps", ".exif", ".ico", ".icon",
".j", ".j2c", ".j2k", ".jas", ".jiff", ".jng", ".jp2", ".jpc", ".jpe", ".jpeg", ".jpf", ".jpg", "jpw",
"jpx", "jtf", ".mac", ".omf", ".qif", ".qti", "qtif", ".tex", ".tfw", ".tga", ".tif", ".tiff", ".wmf",
".psd", ".exr", ".rendertexture"),
new AssetType("Video", ".asf", ".asx", ".avi", ".dat", ".divx", ".dvx", ".mlv", ".m2l", ".m2t", ".m2ts",
".m2v", ".m4e", ".m4v", "mjp", ".mov", ".movie", ".mp21", ".mp4", ".mpe", ".mpeg", ".mpg", ".mpv2",
".ogm", ".qt", ".rm", ".rmvb", ".wmv", ".xvid", ".flv"),
new AssetType("Audio", ".mp3", ".wav", ".ogg", ".aif", ".aiff", ".mod", ".it", ".s3m", ".xm"),
new AssetType("Script", ".cs", ".js", ".boo"),
new AssetType("Text", ".txt", ".json", ".xml", ".bytes", ".sql"),
new AssetType("Shader", ".shader", ".cginc"),
new AssetType("Animation", ".anim", ".controller", ".overridecontroller", ".mask"),
new AssetType("Unity Asset", ".asset", ".guiskin", ".flare", ".fontsettings", ".prefs"),
new AssetType("Others") //
};
public static IEnumerable<GameObject> getAllObjsInCurScene()
{
// foreach (GameObject obj in Object.FindObjectsOfType(typeof(GameObject)))
// {
// yield return obj;
// }
for (var j = 0; j < SceneManager.sceneCount; j++)
{
Scene scene = SceneManager.GetSceneAt(j);
foreach (GameObject item in GetGameObjectsInScene(scene))
{
yield return item;
}
}
if (EditorApplication.isPlaying)
{
//dont destroy scene
GameObject temp = null;
try
{
temp = new GameObject();
Object.DontDestroyOnLoad(temp);
Scene dontDestroyOnLoad = temp.scene;
Object.DestroyImmediate(temp);
temp = null;
foreach (GameObject item in GetGameObjectsInScene(dontDestroyOnLoad))
{
yield return item;
}
}
finally
{
if (temp != null)
{
Object.DestroyImmediate(temp);
}
}
}
}
private static IEnumerable<GameObject> GetGameObjectsInScene(Scene scene)
{
var rootObjects = new List<GameObject>();
scene.GetRootGameObjects(rootObjects);
// iterate root objects and do something
for (var i = 0; i < rootObjects.Count; ++i)
{
GameObject gameObject = rootObjects[i];
foreach (GameObject item in getAllChild(gameObject))
{
yield return item;
}
yield return gameObject;
}
}
public static IEnumerable<GameObject> getAllChild(GameObject target)
{
if (target.transform.childCount > 0)
{
for (var i = 0; i < target.transform.childCount; i++)
{
yield return target.transform.GetChild(i).gameObject;
foreach (GameObject item in getAllChild(target.transform.GetChild(i).gameObject))
{
yield return item;
}
}
}
}
public static IEnumerable<Object> GetAllRefObjects(GameObject obj)
{
Component[] components = obj.GetComponents<Component>();
foreach (Component com in components)
{
if (com == null)
{
continue;
}
var serialized = new SerializedObject(com);
SerializedProperty it = serialized.GetIterator().Copy();
while (it.NextVisible(true))
{
if (it.propertyType != SerializedPropertyType.ObjectReference)
{
continue;
}
if (it.objectReferenceValue == null)
{
continue;
}
yield return it.objectReferenceValue;
}
}
}
public static int StringMatch(string pattern, string input)
{
if (input == pattern)
{
return int.MaxValue;
}
if (input.Contains(pattern))
{
return int.MaxValue - 1;
}
var pidx = 0;
var score = 0;
var tokenScore = 0;
for (var i = 0; i < input.Length; i++)
{
char ch = input[i];
if (ch == pattern[pidx])
{
tokenScore += tokenScore + 1; //increasing score for continuos token
pidx++;
if (pidx >= pattern.Length)
{
break;
}
}
else
{
tokenScore = 0;
}
score += tokenScore;
}
return score;
}
public static int GetIndex(string ext)
{
for (var i = 0; i < FILTERS.Length - 1; i++)
{
if (FILTERS[i].extension.Contains(ext))
{
return i;
}
}
return FILTERS.Length - 1; //Others
}
public static void GuiLine(int i_height = 1)
{
Rect rect = EditorGUILayout.GetControlRect(false, i_height);
rect.height = i_height;
EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 1));
}
public static string GetfileSizeString(long fileSize)
{
return fileSize <= 1024
? fileSize + " B"
: fileSize <= 1024 * 1024
? Mathf.RoundToInt(fileSize / 1024f) + " KB"
: Mathf.RoundToInt(fileSize / 1024f / 1024f) + " MB";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d3ba0d9bfe79ff94ca52a3bd6b6870d4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 6db5b6c2e2bbb4f2093a7cd892ececca
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,389 @@
#if UNITY_2018_3_OR_NEWER
#define SUPPORT_NESTED_PREFAB
#endif
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_2017_1_OR_NEWER
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
#endif
#if SUPPORT_NESTED_PREFAB
using UnityEditor.Experimental.SceneManagement;
#endif
namespace vietlabs.fr2
{
public class FR2_SceneCache
{
private static FR2_SceneCache _api;
public static Action onReady;
public static bool ready = true;
private Dictionary<Component, HashSet<HashValue>> _cache = new Dictionary<Component, HashSet<HashValue>>();
public int current;
public Dictionary<string, HashSet<Component>> folderCache = new Dictionary<string, HashSet<Component>>();
private List<GameObject> listGO;
//public HashSet<string> prefabDependencies = new HashSet<string>();
public Dictionary<GameObject, HashSet<string>> prefabDependencies =
new Dictionary<GameObject, HashSet<string>>();
public int total;
private IWindow window;
public FR2_SceneCache()
{
#if UNITY_2018_1_OR_NEWER
EditorApplication.hierarchyChanged -= OnSceneChanged;
EditorApplication.hierarchyChanged += OnSceneChanged;
#else
EditorApplication.hierarchyWindowChanged -= OnSceneChanged;
EditorApplication.hierarchyWindowChanged += OnSceneChanged;
#endif
#if UNITY_2018_2_OR_NEWER
EditorSceneManager.activeSceneChangedInEditMode -= OnSceneChanged;
EditorSceneManager.activeSceneChangedInEditMode += OnSceneChanged;
#endif
#if UNITY_2017_1_OR_NEWER
SceneManager.activeSceneChanged -= OnSceneChanged;
SceneManager.activeSceneChanged += OnSceneChanged;
SceneManager.sceneLoaded -= OnSceneChanged;
SceneManager.sceneLoaded += OnSceneChanged;
Undo.postprocessModifications -= OnModify;
Undo.postprocessModifications += OnModify;
#endif
#if SUPPORT_NESTED_PREFAB
PrefabStage.prefabStageOpened -= prefabOnpen;
PrefabStage.prefabStageClosing += prefabClose;
PrefabStage.prefabStageOpened -= prefabOnpen;
PrefabStage.prefabStageClosing += prefabClose;
#endif
}
public static FR2_SceneCache Api
{
get
{
if (_api == null)
{
_api = new FR2_SceneCache();
}
return _api;
}
}
private bool _dirty = true;
public bool Dirty
{
get { return _dirty; }
set { _dirty = value; }
}
public Dictionary<Component, HashSet<HashValue>> cache
{
get
{
if (_cache == null)
{
refreshCache(window);
}
return _cache;
}
}
public void refreshCache(IWindow window)
{
if (window == null)
{
return;
}
// if(!ready) return;
this.window = window;
_cache = new Dictionary<Component, HashSet<HashValue>>();
folderCache = new Dictionary<string, HashSet<Component>>();
prefabDependencies = new Dictionary<GameObject, HashSet<string>>();
ready = false;
List<GameObject> listRootGO = null;
#if SUPPORT_NESTED_PREFAB
if (PrefabStageUtility.GetCurrentPrefabStage() != null)
{
GameObject rootPrefab = PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot;
if (rootPrefab != null)
{
listRootGO = new List<GameObject> { rootPrefab };
}
}
#else
#endif
if (listRootGO == null)
{
listGO = FR2_Unity.getAllObjsInCurScene().ToList();
}
else
{
listGO = new List<GameObject>();
foreach (GameObject item in listRootGO)
{
listGO.AddRange(FR2_Unity.getAllChild(item, true));
}
}
total = listGO.Count;
current = 0;
// Debug.Log("refresh cache total " + total);
EditorApplication.update -= OnUpdate;
EditorApplication.update += OnUpdate;
// foreach (var item in FR2_Helper.getAllObjsInCurScene())
// {
// // Debug.Log("object in scene: " + item.name);
// Component[] components = item.GetComponents<Component>();
// foreach (var com in components)
// {
// if(com == null) continue;
// SerializedObject serialized = new SerializedObject(com);
// SerializedProperty it = serialized.GetIterator().Copy();
// while (it.NextVisible(true))
// {
// if (it.propertyType != SerializedPropertyType.ObjectReference) continue;
// if (it.objectReferenceValue == null) continue;
// if(!_cache.ContainsKey(com)) _cache.Add(com, new HashSet<SerializedProperty>());
// if(!_cache[com].Contains(it))
// _cache[com].Add(it.Copy());
// }
// }
// }
Dirty = false;
}
private void OnUpdate()
{
for (var i = 0; i < 5 * FR2_Cache.priority; i++)
{
if (listGO == null || listGO.Count <= 0)
{
//done
// Debug.Log("done");
EditorApplication.update -= OnUpdate;
ready = true;
Dirty = false;
listGO = null;
if (onReady != null)
{
onReady();
}
if (window != null)
{
window.OnSelectionChange();
}
return;
}
int index = listGO.Count - 1;
GameObject go = listGO[index];
if (go == null)
{
continue;
}
string prefabGUID = FR2_Unity.GetPrefabParent(go);
if (!string.IsNullOrEmpty(prefabGUID))
{
Transform parent = go.transform.parent;
while (parent != null)
{
GameObject g = parent.gameObject;
if (!prefabDependencies.ContainsKey(g))
{
prefabDependencies.Add(g, new HashSet<string>());
}
prefabDependencies[g].Add(prefabGUID);
parent = parent.parent;
}
}
Component[] components = go.GetComponents<Component>();
foreach (Component com in components)
{
if (com == null)
{
continue;
}
var serialized = new SerializedObject(com);
SerializedProperty it = serialized.GetIterator().Copy();
while (it.NextVisible(true))
{
if (it.propertyType != SerializedPropertyType.ObjectReference)
{
continue;
}
if (it.objectReferenceValue == null)
{
continue;
}
var isSceneObject = true;
string path = AssetDatabase.GetAssetPath(it.objectReferenceValue);
if (!string.IsNullOrEmpty(path))
{
string dir = Path.GetDirectoryName(path);
if (!string.IsNullOrEmpty(dir))
{
isSceneObject = false;
if (!folderCache.ContainsKey(dir))
{
folderCache.Add(dir, new HashSet<Component>());
}
if (!folderCache[dir].Contains(com))
{
folderCache[dir].Add(com);
}
}
}
if (!_cache.ContainsKey(com))
{
_cache.Add(com, new HashSet<HashValue>());
}
_cache[com].Add(new HashValue
{ target = it.objectReferenceValue, isSceneObject = isSceneObject });
// if (!_cache.ContainsKey(com)) _cache.Add(com, new HashSet<SerializedProperty>());
// if (!_cache[com].Contains(it))
// _cache[com].Add(it.Copy());
// string path = AssetDatabase.GetAssetPath(it.objectReferenceValue);
// if (string.IsNullOrEmpty(path)) continue;
// string dir = System.IO.Path.GetDirectoryName(path);
// if (string.IsNullOrEmpty(dir)) continue;
// if (!folderCache.ContainsKey(dir)) folderCache.Add(dir, new HashSet<Component>());
// if (!folderCache[dir].Contains(com))
// folderCache[dir].Add(com);
}
}
listGO.RemoveAt(index);
current++;
}
}
private void OnSceneChanged()
{
if (!Application.isPlaying)
{
Api.refreshCache(window);
return;
}
SetDirty();
}
#if UNITY_2017_1_OR_NEWER
private UndoPropertyModification[] OnModify(UndoPropertyModification[] modifications)
{
for (var i = 0; i < modifications.Length; i++)
{
if (modifications[i].currentValue.objectReference != null)
{
SetDirty();
break;
}
}
return modifications;
}
#endif
public void SetDirty()
{
Dirty = true;
}
public class HashValue
{
public bool isSceneObject;
public Object target;
//public SerializedProperty pro;
// public HashValue(SerializedProperty pro, bool isSceneObject)
// {
// //this.pro = pro;
// this.isSceneObject = isSceneObject;
// }
}
#if SUPPORT_NESTED_PREFAB
private void prefabClose(PrefabStage obj)
{
if (!Application.isPlaying)
{
Api.refreshCache(window);
return;
}
SetDirty();
}
private void prefabOnpen(PrefabStage obj)
{
if (!Application.isPlaying)
{
Api.refreshCache(window);
return;
}
SetDirty();
}
#endif
#if UNITY_2017_1_OR_NEWER
private void OnSceneChanged(Scene scene, LoadSceneMode mode)
{
OnSceneChanged();
}
private void OnSceneChanged(Scene arg0, Scene arg1)
{
OnSceneChanged();
}
#endif
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 658977c5b6e84344581803c8025947d3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,215 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace vietlabs.fr2
{
public class FR2_Selection : IRefDraw
{
internal HashSet<string> guidSet = new HashSet<string>();
internal HashSet<string> instSet = new HashSet<string>(); // Do not reference directly to SceneObject (which might be destroyed anytime)
public int Count
{
get { return guidSet.Count + instSet.Count; }
}
public bool Contains(string guidOrInstID)
{
return guidSet.Contains(guidOrInstID) || instSet.Contains(guidOrInstID);
}
public bool Contains(UnityObject sceneObject)
{
var id = sceneObject.GetInstanceID().ToString();
return instSet.Contains(id);
}
public void Add(UnityObject sceneObject)
{
if (sceneObject == null) return;
var id = sceneObject.GetInstanceID().ToString();
instSet.Add(id); // hashset does not need to check exist before add
dirty = true;
}
public void AddRange(params UnityObject[] sceneObjects)
{
foreach (var go in sceneObjects)
{
var id = go.GetInstanceID().ToString();
instSet.Add(id); // hashset does not need to check exist before add
}
dirty = true;
}
public void Add(string guid)
{
if (guidSet.Contains(guid)) return;
var assetPath = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrEmpty(assetPath))
{
Debug.LogWarning("Invalid GUID: " + guid);
return;
}
guidSet.Add(guid);
dirty = true;
}
public void AddRange(params string[] guids)
{
foreach (var id in guids)
{
Add(id);
}
dirty = true;
}
public void Remove(UnityObject sceneObject)
{
if (sceneObject == null) return;
var id = sceneObject.GetInstanceID().ToString();
instSet.Remove(id);
dirty = true;
}
public void Remove(string guidOrInstID)
{
guidSet.Remove(guidOrInstID);
instSet.Remove(guidOrInstID);
dirty = true;
}
public void Clear()
{
guidSet.Clear();
instSet.Clear();
dirty = true;
}
public bool isSelectingAsset
{
get { return instSet.Count == 0; }
}
public void Add(FR2_Ref rf)
{
if (rf.isSceneRef)
{
Add(rf.component);
}
else
{
Add(rf.asset.guid);
}
}
public void Remove(FR2_Ref rf)
{
if (rf.isSceneRef)
{
Remove(rf.component);
}
else
{
Remove(rf.asset.guid);
}
}
// ------------ instance
private bool dirty;
private readonly FR2_RefDrawer drawer;
internal Dictionary<string, FR2_Ref> refs;
internal bool isLock;
public FR2_Selection(IWindow window)
{
this.window = window;
drawer = new FR2_RefDrawer(window);
drawer.groupDrawer.hideGroupIfPossible = true;
drawer.forceHideDetails = true;
drawer.level0Group = string.Empty;
dirty = true;
drawer.SetDirty();
}
public IWindow window { get; set; }
public int ElementCount()
{
return refs == null ? 0 : refs.Count;
}
public bool DrawLayout()
{
if (dirty) RefreshView();
return drawer.DrawLayout();
}
public bool Draw(Rect rect)
{
if (dirty) RefreshView();
if (refs == null) return false;
DrawLock(new Rect(rect.xMax - 12f, rect.yMin - 12f, 16f, 16f));
return drawer.Draw(rect);
}
public void SetDirty()
{
drawer.SetDirty();
}
private static readonly Color PRO = new Color(0.8f, 0.8f, 0.8f, 1f);
private static readonly Color INDIE = new Color(0.1f, 0.1f, 0.1f, 1f);
public void DrawLock(Rect rect)
{
GUI2.ContentColor(() =>
{
var icon = isLock ? FR2_Icon.Lock : FR2_Icon.Unlock;
if (GUI2.Toggle(rect, ref isLock, icon))
{
window.WillRepaint = true;
window.OnSelectionChange();
}
}, GUI2.Theme(PRO, INDIE));
}
public void RefreshView()
{
if (refs == null) refs = new Dictionary<string, FR2_Ref>();
refs.Clear();
if (instSet.Count > 0)
{
foreach (var instId in instSet)
{
refs.Add(instId, new FR2_SceneRef(0, EditorUtility.InstanceIDToObject(int.Parse(instId))));
}
}
else
{
foreach (var guid in guidSet)
{
var asset = FR2_Cache.Api.Get(guid, false);
refs.Add(guid, new FR2_Ref(0, 0, asset, null)
{
isSceneRef = false
});
}
}
drawer.SetRefs(refs);
dirty = false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9a9a5bbf1fb9c4a1b9a0013057b1f59d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,417 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace vietlabs.fr2
{
public class FR2_TreeUI2
{
internal Drawer drawer;
private Vector2 position;
private TreeItem rootItem;
internal Rect visibleRect;
public float itemPaddingRight = 0f;
public FR2_TreeUI2(Drawer drawer)
{
this.drawer = drawer;
}
public void Reset(params string[] root)
{
position = Vector2.zero;
rootItem = new TreeItem
{
tree = this,
id = "$root",
height = 0,
depth = -1,
_isOpen = true,
highlight = false,
childCount = root.Length
};
rootItem.RefreshChildren(root);
rootItem.DeepOpen();
}
public void Draw(Rect rect)
{
if (rect.width > 0)
{
visibleRect = rect;
}
var contentRect = new Rect(0f, 0f, 1f, rootItem.childrenHeight);
bool noScroll = contentRect.height < visibleRect.height;
if (noScroll)
{
position = Vector2.zero;
}
var minY = (int)position.y;
var maxY = (int)(position.y + visibleRect.height);
contentRect.x -= FR2_Setting.TreeIndent;
TreeItem.DrawCall = 0;
TreeItem.DrawRender = 0;
position = GUI.BeginScrollView(visibleRect, position, contentRect);
{
var r = new Rect(0, 0, rect.width - (noScroll ? 4f : 18f) - itemPaddingRight, 16f);
var index = 0;
rootItem.Draw(ref index, ref r, minY, maxY);
}
GUI.EndScrollView();
}
public void DrawLayout()
{
EventType evtType = Event.current.type;
Rect r = GUILayoutUtility.GetRect(1f, Screen.width, 16f, Screen.height);
if (evtType != EventType.Layout)
{
visibleRect = r;
}
Draw(visibleRect);
}
public bool NoScroll()
{
return rootItem.childrenHeight < visibleRect.height;
}
// ------------------------ DELEGATE --------------
public class Drawer
{
public virtual int GetHeight(string id)
{
return 16;
}
public virtual int GetChildCount(string id)
{
return 0;
}
public virtual string[] GetChildren(string id)
{
return null;
}
public virtual void Draw(Rect r, TreeItem item)
{
GUI.Label(r, item.id);
}
}
public class GroupDrawer : Drawer
{
public Action<Rect, string, int> drawGroup;
public Action<Rect, string> drawItem;
private Dictionary<string, List<string>> groupDict;
internal FR2_TreeUI2 tree;
public GroupDrawer(Action<Rect, string, int> drawGroup, Action<Rect, string> drawItem)
{
this.drawItem = drawItem;
this.drawGroup = drawGroup;
}
// ----------------- TREE WRAPPER ------------------
public bool TreeNoScroll()
{
return tree.NoScroll();
}
public bool hideGroupIfPossible;
public void Reset<T>(List<T> items, Func<T, string> idFunc, Func<T, string> groupFunc,
Action<List<string>> customGroupSort = null)
{
groupDict = new Dictionary<string, List<string>>();
for (var i = 0; i < items.Count; i++)
{
List<string> list;
string groupName = groupFunc(items[i]);
if (groupName == null) continue; // do not exclude groupName string.Empty
string itemId = idFunc(items[i]);
if (string.IsNullOrEmpty(itemId)) continue; // ignore items without id
if (!groupDict.TryGetValue(groupName, out list))
{
list = new List<string>();
groupDict.Add(groupName, list);
}
list.Add(itemId);
}
if (tree == null)
{
tree = new FR2_TreeUI2(this);
}
List<string> groups = groupDict.Keys.ToList();
if (hideGroupIfPossible && groups.Count == 1) //single group : Flat list
{
var v = groupDict[groups[0]];
tree.Reset(v.ToArray());
groupDict.Clear();
}
else
{ //multiple groups
if (customGroupSort != null)
{
customGroupSort(groups);
}
else
{
groups.Sort();
}
tree.Reset(groups.ToArray());
}
}
public void Draw(Rect r)
{
if (tree != null) tree.Draw(r);
}
public bool hasChildren
{
get
{
return tree != null && tree.rootItem.childCount > 0;
}
}
public bool hasValidTree
{
get { return groupDict != null && tree != null; }
}
public void DrawLayout()
{
if (tree != null) tree.DrawLayout();
}
// ----------------- DRAWER WRAPPER ------------------
public override int GetChildCount(string id)
{
if (string.IsNullOrEmpty(id)) return 0;
List<string> group;
if (groupDict.TryGetValue(id, out group))
{
return group.Count;
}
return 0;
}
public override string[] GetChildren(string id)
{
List<string> group;
if (groupDict.TryGetValue(id, out group))
{
return group.ToArray();
}
return null;
}
public override void Draw(Rect r, TreeItem item)
{
List<string> group;
if (groupDict.TryGetValue(item.id, out group))
{
drawGroup(r, item.id, item.childCount);
return;
}
drawItem(r, item.id);
}
}
// ------------------------ TreeItem2 --------------
public class TreeItem
{
public static int DrawCall;
public static int DrawRender;
internal bool _isOpen;
public int childCount;
public List<TreeItem> children;
public int childrenHeight;
public int depth; // item depth
public int height;
public bool highlight;
public string id; // item id
internal TreeItem parent;
//static Color COLOR = new Color(0f, 0f, 0f, 0.05f);
internal FR2_TreeUI2 tree;
public bool IsOpen
{
get { return _isOpen; }
set
{
if (_isOpen == value || childCount == 0)
{
return;
}
_isOpen = value;
if (_isOpen)
{
if (children == null)
{
RefreshChildren(tree.drawer.GetChildren(id));
}
//Update height for all parents
TreeItem p = parent;
while (p != null)
{
p.childrenHeight += childrenHeight;
p = p.parent;
}
}
else
{
//Update height for all parents
TreeItem p = parent;
while (p != null)
{
p.childrenHeight -= childrenHeight;
p = p.parent;
}
}
}
}
internal void DeepOpen()
{
IsOpen = true;
if (children == null)
{
return;
}
for (var i = 0; i < children.Count; i++)
{
children[i].DeepOpen();
}
}
internal void Draw(ref int index, ref Rect rect, int minY, int maxY)
{
DrawCall++;
// if (DrawCall < 10)
// {
// Debug.Log(index + ":" + rect + ":" + minY + ":" + maxY + ":" + height + ":" + childrenHeight);
// }
//var skipDraw = (rect.y >= maxY) || (height <=0);
float min = rect.y;
float max = rect.y + height;
bool interMin = min >= minY && min <= maxY;
bool interMax = max >= minY && max <= maxY;
if (height > 0 && (interMin || interMax))
{
DrawRender++;
rect.height = height;
if (index % 2 == 1 && FR2_Setting.AlternateRowColor)
{
Color o = GUI.color;
GUI.color = FR2_Setting.RowColor;
// GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture);
GUI.DrawTexture(new Rect(rect.x - FR2_Setting.TreeIndent, rect.y, rect.width, rect.height),
EditorGUIUtility.whiteTexture);
GUI.color = o;
}
float x = (depth + 1) * 16f;
tree.drawer.Draw(new Rect(x, rect.y, rect.width - x, rect.height), this);
if (childCount > 0)
{
IsOpen = GUI.Toggle(new Rect(rect.x + x - 16f, rect.y, 16f, 16f), IsOpen, string.Empty,
EditorStyles.foldout);
}
index++;
rect.y += height;
}
else
{
rect.y += height;
}
if (_isOpen && rect.y <= maxY) //draw children
{
for (var i = 0; i < children.Count; i++)
{
children[i].Draw(ref index, ref rect, minY, maxY);
if (rect.y > maxY)
{
break;
}
}
}
}
internal void RefreshChildren(string[] childrenIDs)
{
childCount = childrenIDs.Length;
childrenHeight = 0;
children = new List<TreeItem>();
for (var i = 0; i < childCount; i++)
{
string itemId = childrenIDs[i];
var item = new TreeItem
{
tree = tree,
parent = this,
id = itemId,
depth = depth + 1,
highlight = false,
height = tree.drawer.GetHeight(itemId),
childCount = tree.drawer.GetChildCount(itemId)
};
childrenHeight += item.height;
children.Add(item);
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c0367155479c84189ad956f35f707b7c
timeCreated: 1493613697
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 7d62736a417e747e481e3aa85951cd18
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,144 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace vietlabs.fr2
{
public class FR2_UsedInBuild : IRefDraw
{
private readonly FR2_TreeUI2.GroupDrawer groupDrawer;
private bool dirty;
private readonly FR2_RefDrawer drawer;
internal Dictionary<string, FR2_Ref> refs;
public FR2_UsedInBuild(IWindow window)
{
this.window = window;
drawer = new FR2_RefDrawer(window);
dirty = true;
drawer.SetDirty();
}
public IWindow window { get; set; }
public int ElementCount()
{
return refs == null ? 0 : refs.Count;
}
public bool Draw(Rect rect)
{
if (dirty)
{
RefreshView();
}
return drawer.Draw(rect);
}
public bool DrawLayout()
{
//Debug.Log("draw");
if (dirty)
{
RefreshView();
}
return drawer.DrawLayout();
}
public void SetDirty()
{
dirty = true;
drawer.SetDirty();
}
public void RefreshView()
{
var scenes = new HashSet<string>();
// string[] scenes = new string[sceneCount];
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if (scene == null)
{
continue;
}
if (scene.enabled == false)
{
continue;
}
string sce = AssetDatabase.AssetPathToGUID(scene.path);
if (scenes.Contains(sce))
{
continue;
}
scenes.Add(sce);
}
refs = FR2_Ref.FindUsage(scenes.ToArray());
foreach (string VARIABLE in scenes)
{
FR2_Ref asset = null;
if (!refs.TryGetValue(VARIABLE, out asset))
{
continue;
}
asset.depth = 1;
}
List<FR2_Asset> list = FR2_Cache.Api.AssetList;
int count = list.Count;
for (var i = 0; i < count; i++)
{
FR2_Asset item = list[i];
if (item.inEditor) continue;
if (item.inPlugins)
{
if (item.type == FR2_AssetType.SCENE) continue;
}
if (item.inResources || item.inStreamingAsset || item.inPlugins)
{
if (refs.ContainsKey(item.guid))
{
continue;
}
refs.Add(item.guid, new FR2_Ref(0, 1, item, null));
}
}
// remove ignored items
var vals = refs.Values.ToArray();
foreach (var item in vals)
{
foreach (var ig in FR2_Setting.s.listIgnore)
{
if (!item.asset.assetPath.StartsWith(ig)) continue;
refs.Remove(item.asset.guid);
//Debug.Log("Remove: " + item.asset.assetPath + "\n" + ig);
break;
}
}
drawer.SetRefs(refs);
dirty = false;
}
internal void RefreshSort()
{
drawer.RefreshSort();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e0eebac9e6cbe431ca16d9cb27500785
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,947 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_5_3_OR_NEWER
#endif
namespace vietlabs.fr2
{
// filter, ignore anh huong ket qua thi hien mau do
// optimize lag duplicate khi use
public class FR2_WindowAll : FR2_WindowBase, IHasCustomMenu
{
[MenuItem("Window/Find Reference 2")]
private static void ShowWindow()
{
var _window = CreateInstance<FR2_WindowAll>();
_window.InitIfNeeded();
FR2_Unity.SetWindowTitle(_window, "FR2");
_window.Show();
}
[NonSerialized] internal FR2_Bookmark bookmark;
[NonSerialized] internal FR2_Selection selection;
[NonSerialized] internal FR2_UsedInBuild UsedInBuild;
[NonSerialized] internal FR2_DuplicateTree2 Duplicated;
[NonSerialized] internal FR2_RefDrawer RefUnUse;
[NonSerialized] internal FR2_RefDrawer UsesDrawer; // [Selected Assets] are [USING] (depends on / contains reference to) ---> those assets
[NonSerialized] internal FR2_RefDrawer UsedByDrawer; // [Selected Assets] are [USED BY] <---- those assets
[NonSerialized] internal FR2_RefDrawer SceneToAssetDrawer; // [Selected GameObjects in current Scene] are [USING] ---> those assets
[NonSerialized] internal FR2_RefDrawer RefInScene; // [Selected Assets] are [USED BY] <---- those components in current Scene
[NonSerialized] internal FR2_RefDrawer SceneUsesDrawer; // [Selected GameObjects] are [USING] ---> those components / GameObjects in current scene
[NonSerialized] internal FR2_RefDrawer RefSceneInScene; // [Selected GameObjects] are [USED BY] <---- those components / GameObjects in current scene
internal int level;
private Vector2 scrollPos;
private string tempGUID;
private Object tempObject;
protected bool lockSelection
{
get { return selection != null && selection.isLock; }
}
private void OnEnable()
{
Repaint();
}
protected void InitIfNeeded()
{
if (UsesDrawer != null) return;
UsesDrawer = new FR2_RefDrawer(this)
{
messageEmpty = "[Selected Assets] are not [USING] (depends on / contains reference to) any other assets!"
};
UsedByDrawer = new FR2_RefDrawer(this)
{
messageEmpty = "[Selected Assets] are not [USED BY] any other assets!"
};
Duplicated = new FR2_DuplicateTree2(this);
SceneToAssetDrawer = new FR2_RefDrawer(this)
{
messageEmpty = "[Selected GameObjects] (in current open scenes) are not [USING] any assets!"
};
RefUnUse = new FR2_RefDrawer(this);
RefUnUse.groupDrawer.hideGroupIfPossible = true;
UsedInBuild = new FR2_UsedInBuild(this);
bookmark = new FR2_Bookmark(this);
selection = new FR2_Selection(this);
SceneUsesDrawer = new FR2_RefDrawer(this)
{
messageEmpty = "[Selected GameObjects] are not [USING] any other GameObjects in scenes"
};
RefInScene = new FR2_RefDrawer(this)
{
messageEmpty = "[Selected Assets] are not [USED BY] any GameObjects in opening scenes!"
};
RefSceneInScene = new FR2_RefDrawer(this)
{
messageEmpty = "[Selected GameObjects] are not [USED BY] by any GameObjects in opening scenes!"
};
#if UNITY_2018_OR_NEWER
UnityEditor.SceneManagement.EditorSceneManager.activeSceneChangedInEditMode -= OnSceneChanged;
UnityEditor.SceneManagement.EditorSceneManager.activeSceneChangedInEditMode += OnSceneChanged;
#elif UNITY_2017_OR_NEWER
UnityEditor.SceneManagement.EditorSceneManager.activeSceneChanged -= OnSceneChanged;
UnityEditor.SceneManagement.EditorSceneManager.activeSceneChanged += OnSceneChanged;
#endif
FR2_Cache.onReady -= OnReady;
FR2_Cache.onReady += OnReady;
FR2_Setting.OnIgnoreChange -= OnIgnoreChanged;
FR2_Setting.OnIgnoreChange += OnIgnoreChanged;
Repaint();
}
#if UNITY_2018_OR_NEWER
private void OnSceneChanged(Scene arg0, Scene arg1)
{
if (IsFocusingFindInScene || IsFocusingSceneToAsset || IsFocusingSceneInScene)
{
OnSelectionChange();
}
}
#endif
protected void OnIgnoreChanged()
{
RefUnUse.ResetUnusedAsset();
UsedInBuild.SetDirty();
OnSelectionChange();
}
protected void OnCSVClick()
{
FR2_Ref[] csvSource = null;
var drawer = GetAssetDrawer();
if (drawer != null) csvSource = drawer.source;
if (IsFocusingUnused && csvSource == null)
{
csvSource = RefUnUse.source;
//if (csvSource != null) Debug.Log("d : " + csvSource.Length);
}
if (IsFocusingUsedInBuild && csvSource == null)
{
csvSource = FR2_Ref.FromDict(UsedInBuild.refs);
//if (csvSource != null) Debug.Log("e : " + csvSource.Length);
}
if (IsFocusingDuplicate && csvSource == null)
{
csvSource = FR2_Ref.FromList(Duplicated.list);
//if (csvSource != null) Debug.Log("f : " + csvSource.Length);
}
FR2_Export.ExportCSV(csvSource);
}
protected void OnReady()
{
OnSelectionChange();
}
public override void OnSelectionChange()
{
Repaint();
isNoticeIgnore = false;
if (!FR2_Cache.isReady)
{
return;
}
if (focusedWindow == null)
{
return;
}
if (SceneUsesDrawer == null)
{
InitIfNeeded();
}
if (UsesDrawer == null)
{
InitIfNeeded();
}
if (!lockSelection)
{
ids = FR2_Unity.Selection_AssetGUIDs;
selection.Clear();
//ignore selection on asset when selected any object in scene
if (Selection.gameObjects.Length > 0 && !FR2_Unity.IsInAsset(Selection.gameObjects[0]))
{
ids = new string[0];
selection.AddRange(Selection.gameObjects);
}
else
{
selection.AddRange(ids);
}
level = 0;
if (selection.isSelectingAsset)
{
UsesDrawer.Reset(ids, true);
UsedByDrawer.Reset(ids, false);
RefInScene.Reset(ids, this as IWindow);
}
else
{
RefSceneInScene.ResetSceneInScene(Selection.gameObjects);
SceneToAssetDrawer.Reset(Selection.gameObjects, true, true);
SceneUsesDrawer.ResetSceneUseSceneObjects(Selection.gameObjects);
}
// auto disable enable scene / asset
if (IsFocusingUses)
{
sp2.splits[0].visible = !selection.isSelectingAsset;
sp2.splits[1].visible = true;
sp2.CalculateWeight();
}
if (IsFocusingUsedBy)
{
sp2.splits[0].visible = true;
sp2.splits[1].visible = selection.isSelectingAsset;
sp2.CalculateWeight();
}
}
if (IsFocusingGUIDs)
{
//objs = new Object[ids.Length];
objs = new Dictionary<string, Object>();
var objects = Selection.objects;
for (var i = 0; i < objects.Length; i++)
{
var item = objects[i];
#if UNITY_2018_1_OR_NEWER
{
var guid = "";
long fileid = -1;
try
{
if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(item, out guid, out fileid))
{
objs.Add(guid + "/" + fileid, objects[i]);
//Debug.Log("guid: " + guid + " fileID: " + fileid);
}
}
catch { }
}
#else
{
var path = AssetDatabase.GetAssetPath(item);
if (string.IsNullOrEmpty(path)) continue;
var guid = AssetDatabase.AssetPathToGUID(path);
System.Reflection.PropertyInfo inspectorModeInfo =
typeof(SerializedObject).GetProperty("inspectorMode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
SerializedObject serializedObject = new SerializedObject(item);
inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);
SerializedProperty localIdProp =
serializedObject.FindProperty("m_LocalIdentfierInFile"); //note the misspelling!
var localId = localIdProp.longValue;
if (localId <= 0)
{
localId = localIdProp.intValue;
}
if (localId <= 0)
{
continue;
}
if (!string.IsNullOrEmpty(guid)) objs.Add(guid + "/" + localId, objects[i]);
}
#endif
}
}
if (IsFocusingUnused)
{
RefUnUse.ResetUnusedAsset();
}
if (FR2_SceneCache.Api.Dirty && !Application.isPlaying)
{
FR2_SceneCache.Api.refreshCache(this);
}
EditorApplication.delayCall -= Repaint;
EditorApplication.delayCall += Repaint;
}
public FR2_SplitView sp1; // container : Selection / sp2 / Bookmark
public FR2_SplitView sp2; // Scene / Assets
void InitPanes()
{
sp2 = new FR2_SplitView(this)
{
isHorz = false,
splits = new List<FR2_SplitView.Info>()
{
new FR2_SplitView.Info(){ title = new GUIContent("Scene", FR2_Icon.Scene.image), draw = DrawScene },
new FR2_SplitView.Info(){ title = new GUIContent("Assets", FR2_Icon.Asset.image), draw = DrawAsset },
}
};
sp2.CalculateWeight();
sp1 = new FR2_SplitView(this)
{
isHorz = true,
splits = new List<FR2_SplitView.Info>()
{
new FR2_SplitView.Info(){ title = new GUIContent("Selection", FR2_Icon.Selection.image), weight = 0.4f, visible = false, draw = (rect) => selection.Draw(rect) },
new FR2_SplitView.Info(){ draw = (r) =>
{
if (IsFocusingUses || IsFocusingUsedBy)
{
sp2.Draw(r);
}
else
{
DrawTools(r);
}
} },
new FR2_SplitView.Info(){ title = new GUIContent("Details", FR2_Icon.Details.image), weight = 0.4f, visible = true, draw = (rect) =>
{
var assetDrawer = GetAssetDrawer();
if (assetDrawer != null)
{
assetDrawer.DrawDetails(rect);
}
}},
new FR2_SplitView.Info(){ title = new GUIContent("Bookmark", FR2_Icon.Favorite.image), weight = 0.4f, visible = false, draw = (rect) => bookmark.Draw(rect) }
}
};
sp1.CalculateWeight();
}
private FR2_TabView tabs;
private FR2_TabView bottomTabs;
private FR2_SearchView search;
void DrawScene(Rect rect)
{
FR2_RefDrawer drawer = IsFocusingUses
? (selection.isSelectingAsset ? null : SceneUsesDrawer)
: (selection.isSelectingAsset ? RefInScene : RefSceneInScene);
if (drawer == null) return;
if (!FR2_SceneCache.ready)
{
var rr = rect;
rr.height = 16f;
int cur = FR2_SceneCache.Api.current, total = FR2_SceneCache.Api.total;
EditorGUI.ProgressBar(rr, cur * 1f / total, string.Format("{0} / {1}", cur, total));
WillRepaint = true;
return;
}
drawer.Draw(rect);
var refreshRect = new Rect(rect.xMax - 16f, rect.yMin - 14f, 18f, 18f);
if (GUI2.ColorIconButton(refreshRect, FR2_Icon.Refresh.image,
FR2_SceneCache.Api.Dirty ? (Color?)GUI2.lightRed : null))
{
FR2_SceneCache.Api.refreshCache(drawer.window);
}
}
FR2_RefDrawer GetAssetDrawer()
{
if (IsFocusingUses)
{
return selection.isSelectingAsset ? UsesDrawer : SceneToAssetDrawer;
}
if (IsFocusingUsedBy)
{
return selection.isSelectingAsset ? UsedByDrawer : null;
}
return null;
}
void DrawAsset(Rect rect)
{
var drawer = GetAssetDrawer();
if (drawer != null) drawer.Draw(rect);
}
void DrawSearch()
{
if (search == null) search = new FR2_SearchView();
search.DrawLayout();
}
protected override void OnGUI()
{
OnGUI2();
}
protected bool CheckDrawImport()
{
if (EditorApplication.isCompiling)
{
EditorGUILayout.HelpBox("Compiling scripts, please wait!", MessageType.Warning);
Repaint();
return false;
}
if (EditorApplication.isUpdating)
{
EditorGUILayout.HelpBox("Importing assets, please wait!", MessageType.Warning);
Repaint();
return false;
}
InitIfNeeded();
if (EditorSettings.serializationMode != SerializationMode.ForceText)
{
EditorGUILayout.HelpBox("FR2 requires serialization mode set to FORCE TEXT!", MessageType.Warning);
if (GUILayout.Button("FORCE TEXT"))
{
EditorSettings.serializationMode = SerializationMode.ForceText;
}
return false;
}
if (FR2_Cache.hasCache && !FR2_Cache.CheckSameVersion())
{
EditorGUILayout.HelpBox("Incompatible cache version found!!!\nFR2 will need a full refresh and this may take quite some time to finish but you would be able to work normally while the scan works in background!",
MessageType.Warning);
FR2_Cache.DrawPriorityGUI();
if (GUILayout.Button("Scan project"))
{
FR2_Cache.DeleteCache();
FR2_Cache.CreateCache();
}
return false;
}
if (!FR2_Cache.isReady)
{
if (!FR2_Cache.hasCache)
{
EditorGUILayout.HelpBox(
"FR2 cache not found!\nFirst scan may takes quite some time to finish but you would be able to work normally while the scan works in background...",
MessageType.Warning);
FR2_Cache.DrawPriorityGUI();
if (GUILayout.Button("Scan project"))
{
FR2_Cache.CreateCache();
Repaint();
}
return false;
}
else
{
FR2_Cache.DrawPriorityGUI();
}
if (!DrawEnable())
{
return false;
}
FR2_Cache api = FR2_Cache.Api;
string text = "Refreshing ... " + (int)(api.progress * api.workCount) + " / " + api.workCount;
Rect rect = GUILayoutUtility.GetRect(1f, Screen.width, 18f, 18f);
EditorGUI.ProgressBar(rect, api.progress, text);
Repaint();
return false;
}
if (!DrawEnable())
{
return false;
}
return true;
}
protected bool IsFocusingUses { get { return tabs != null && tabs.current == 0; } }
protected bool IsFocusingUsedBy { get { return tabs != null && tabs.current == 1; } }
protected bool IsFocusingDuplicate { get { return tabs != null && tabs.current == 2; } }
protected bool IsFocusingGUIDs { get { return tabs != null && tabs.current == 3; } }
protected bool IsFocusingUnused { get { return tabs != null && tabs.current == 4; } }
protected bool IsFocusingUsedInBuild { get { return tabs != null && tabs.current == 5; } }
void OnTabChange()
{
if (deleteUnused != null) deleteUnused.hasConfirm = false;
if (UsedInBuild != null) UsedInBuild.SetDirty();
}
void InitTabs()
{
tabs = FR2_TabView.Create(this, false,
"Uses", "Used By", "Duplicate", "GUIDs", "Unused Assets", "Uses in Build"
);
tabs.onTabChange = OnTabChange;
tabs.callback = new DrawCallback()
{
BeforeDraw = () =>
{
if (GUI2.ToolbarToggle(ref selection.isLock,
selection.isLock ? FR2_Icon.Lock.image : FR2_Icon.Unlock.image,
new Vector2(-1, 2), "Lock Selection"))
{
WillRepaint = true;
}
},
AfterDraw = () =>
{
//GUILayout.Space(16f);
if (GUI2.ToolbarToggle(ref sp1.isHorz, FR2_Icon.Panel.image, Vector2.zero, "Layout"))
{
sp1.CalculateWeight();
Repaint();
}
if (GUI2.ToolbarToggle(ref sp1.splits[0].visible, FR2_Icon.Selection.image, Vector2.zero, "Show / Hide Selection"))
{
sp1.CalculateWeight();
Repaint();
}
if (GUI2.ToolbarToggle(ref sp2.splits[0].visible, FR2_Icon.Scene.image, Vector2.zero, "Show / Hide Scene References"))
{
sp2.CalculateWeight();
Repaint();
}
if (GUI2.ToolbarToggle(ref sp2.splits[1].visible, FR2_Icon.Asset.image, Vector2.zero, "Show / Hide Asset References"))
{
sp2.CalculateWeight();
Repaint();
}
if (GUI2.ToolbarToggle(ref sp1.splits[2].visible, FR2_Icon.Details.image, Vector2.zero, "Show / Hide Details"))
{
sp1.CalculateWeight();
Repaint();
}
if (GUI2.ToolbarToggle(ref sp1.splits[3].visible, FR2_Icon.Favorite.image, Vector2.zero, "Show / Hide Bookmarks"))
{
sp1.CalculateWeight();
Repaint();
}
}
};
}
protected bool DrawHeader()
{
if (tabs == null) InitTabs();
if (bottomTabs == null)
{
bottomTabs = FR2_TabView.Create(this, true,
new GUIContent(FR2_Icon.Setting.image, "Settings"),
new GUIContent(FR2_Icon.Ignore.image, "Ignore"),
new GUIContent(FR2_Icon.Filter.image, "Filter by Type")
);
bottomTabs.current = -1;
}
tabs.DrawLayout();
return true;
}
protected bool DrawFooter()
{
GUILayout.BeginHorizontal(EditorStyles.toolbar);
{
bottomTabs.DrawLayout();
GUILayout.FlexibleSpace();
DrawAssetViewSettings();
GUILayout.FlexibleSpace();
DrawViewModes();
}
GUILayout.EndHorizontal();
return false;
}
void DrawAssetViewSettings()
{
var isDisable = !sp2.splits[1].visible;
EditorGUI.BeginDisabledGroup(isDisable);
{
GUI2.ToolbarToggle(ref FR2_Setting.s.displayAssetBundleName, FR2_Icon.AssetBundle.image, Vector2.zero, "Show / Hide Assetbundle Names");
#if UNITY_2017_1_OR_NEWER
GUI2.ToolbarToggle(ref FR2_Setting.s.displayAtlasName, FR2_Icon.Atlas.image, Vector2.zero, "Show / Hide Atlas packing tags");
#endif
GUI2.ToolbarToggle(ref FR2_Setting.s.showUsedByClassed, FR2_Icon.Material.image, Vector2.zero, "Show / Hide usage icons");
GUI2.ToolbarToggle(ref FR2_Setting.s.displayFileSize, FR2_Icon.Filesize.image, Vector2.zero, "Show / Hide file size");
if (GUILayout.Button("CSV", EditorStyles.toolbarButton))
{
OnCSVClick();
}
}
EditorGUI.EndDisabledGroup();
}
void DrawViewModes()
{
var gMode = FR2_Setting.GroupMode;
if (GUI2.EnumPopup(ref gMode, new GUIContent(FR2_Icon.Group.image, "Group by"), EditorStyles.toolbarPopup, GUILayout.Width(80f)))
{
FR2_Setting.GroupMode = gMode;
markDirty();
}
GUILayout.Space(16f);
var sMode = FR2_Setting.SortMode;
if (GUI2.EnumPopup(ref sMode, new GUIContent(FR2_Icon.Sort.image, "Sort by"), EditorStyles.toolbarPopup, GUILayout.Width(50f)))
{
FR2_Setting.SortMode = sMode;
RefreshSort();
}
}
protected void OnGUI2()
{
if (!CheckDrawImport())
{
return;
}
if (sp1 == null) InitPanes();
DrawHeader();
sp1.DrawLayout();
DrawSettings();
DrawFooter();
if (WillRepaint)
{
Repaint();
}
}
private FR2_DeleteButton deleteUnused;
void DrawTools(Rect rect)
{
if (IsFocusingDuplicate)
{
rect = GUI2.Padding(rect, 2f, 2f);
GUILayout.BeginArea(rect);
Duplicated.DrawLayout();
GUILayout.EndArea();
return;
}
if (IsFocusingUnused)
{
rect = GUI2.Padding(rect, 2f, 2f);
if ((RefUnUse.refs != null && RefUnUse.refs.Count == 0))
{
GUILayout.BeginArea(rect);
{
EditorGUILayout.HelpBox("Wow! So clean!?", MessageType.Info);
EditorGUILayout.HelpBox("Your project does not has have any unused assets, or have you just hit DELETE ALL?", MessageType.Info);
EditorGUILayout.HelpBox("Your backups are placed at Library/FR2/ just in case you want your assets back!", MessageType.Info);
}
GUILayout.EndArea();
}
else
{
rect.yMax -= 40f;
GUILayout.BeginArea(rect);
RefUnUse.DrawLayout();
GUILayout.EndArea();
var toolRect = rect;
toolRect.yMin = toolRect.yMax;
var lineRect = toolRect;
lineRect.height = 1f;
GUI2.Rect(lineRect, Color.black, 0.5f);
toolRect.xMin += 2f;
toolRect.xMax -= 2f;
toolRect.height = 40f;
if (deleteUnused == null)
{
deleteUnused = new FR2_DeleteButton()
{
warningMessage = "It's absolutely safe to delete them all!\nA backup (.unitypackage) will be created so you can import it back later!",
deleteLabel = new GUIContent("DELETE ASSETS", FR2_Icon.Delete.image),
confirmMessage = "Create backup at Library/FR2/"
};
}
GUILayout.BeginArea(toolRect);
deleteUnused.Draw(() => { FR2_Unity.BackupAndDeleteAssets(RefUnUse.source); });
GUILayout.EndArea();
}
return;
}
if (IsFocusingUsedInBuild)
{
UsedInBuild.Draw(rect);
return;
}
if (IsFocusingGUIDs)
{
rect = GUI2.Padding(rect, 2f, 2f);
GUILayout.BeginArea(rect);
DrawGUIDs();
GUILayout.EndArea();
return;
}
}
void DrawSettings()
{
if (bottomTabs.current == -1) return;
GUILayout.BeginVertical(GUILayout.Height(100f));
{
GUILayout.Space(2f);
switch (bottomTabs.current)
{
case 0:
{
FR2_Setting.s.DrawSettings();
break;
}
case 1:
{
if (AssetType.DrawIgnoreFolder())
{
markDirty();
}
break;
}
case 2:
{
if (AssetType.DrawSearchFilter())
{
markDirty();
}
break;
}
}
}
GUILayout.EndVertical();
var rect = GUILayoutUtility.GetLastRect();
rect.height = 1f;
GUI2.Rect(rect, Color.black, 0.4f);
}
protected void markDirty()
{
UsedByDrawer.SetDirty();
UsesDrawer.SetDirty();
Duplicated.SetDirty();
SceneToAssetDrawer.SetDirty();
RefUnUse.SetDirty();
RefInScene.SetDirty();
RefSceneInScene.SetDirty();
SceneUsesDrawer.SetDirty();
UsedInBuild.SetDirty();
WillRepaint = true;
}
protected void RefreshSort()
{
UsedByDrawer.RefreshSort();
UsesDrawer.RefreshSort();
Duplicated.RefreshSort();
SceneToAssetDrawer.RefreshSort();
RefUnUse.RefreshSort();
UsedInBuild.RefreshSort();
}
// public bool isExcludeByFilter;
protected bool checkNoticeFilter()
{
var rsl = false;
if (IsFocusingUsedBy && !rsl)
{
rsl = UsedByDrawer.isExclueAnyItem();
}
if (IsFocusingDuplicate)
{
return Duplicated.isExclueAnyItem();
}
if (IsFocusingUses && rsl == false)
{
rsl = UsesDrawer.isExclueAnyItem();
}
//tab use by
return rsl;
}
protected bool checkNoticeIgnore()
{
bool rsl = isNoticeIgnore;
return rsl;
}
private Dictionary<string, Object> objs;
private string[] ids;
private void DrawGUIDs()
{
GUILayout.Label("GUID to Object", EditorStyles.boldLabel);
GUILayout.BeginHorizontal();
{
string guid = EditorGUILayout.TextField(tempGUID ?? string.Empty);
EditorGUILayout.ObjectField(tempObject, typeof(Object), false, GUILayout.Width(120f));
if (GUILayout.Button("Paste", EditorStyles.miniButton, GUILayout.Width(70f)))
{
guid = EditorGUIUtility.systemCopyBuffer;
}
if (guid != tempGUID && !string.IsNullOrEmpty(guid))
{
tempGUID = guid;
tempObject = FR2_Unity.LoadAssetAtPath<Object>
(
AssetDatabase.GUIDToAssetPath(tempGUID)
);
}
}
GUILayout.EndHorizontal();
GUILayout.Space(10f);
if (objs == null)// || ids == null)
{
return;
}
//GUILayout.Label("Selection", EditorStyles.boldLabel);
//if (ids.Length == objs.Count)
{
scrollPos = GUILayout.BeginScrollView(scrollPos);
{
//for (var i = 0; i < ids.Length; i++)
foreach (var item in objs)
{
//if (!objs.ContainsKey(ids[i])) continue;
GUILayout.BeginHorizontal();
{
//var obj = objs[ids[i]];
var obj = item.Value;
EditorGUILayout.ObjectField(obj, typeof(Object), false, GUILayout.Width(150));
string idi = item.Key;
GUILayout.TextField(idi, GUILayout.Width(240f));
if (GUILayout.Button("Copy", EditorStyles.miniButton, GUILayout.Width(50f)))
{
tempObject = obj;
//EditorGUIUtility.systemCopyBuffer = tempGUID = item.Key;
tempGUID = item.Key;
//string guid = "";
//long file = -1;
//if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(obj, out guid, out file))
//{
// EditorGUIUtility.systemCopyBuffer = tempGUID = idi + "/" + file;
// if (!string.IsNullOrEmpty(tempGUID))
// {
// tempObject = obj;
// }
//}
}
}
GUILayout.EndHorizontal();
}
}
GUILayout.EndScrollView();
}
GUILayout.BeginHorizontal();
if (GUILayout.Button("Merge Selection To"))
{
FR2_Export.MergeDuplicate(tempGUID);
}
EditorGUILayout.ObjectField(tempObject, typeof(Object), false, GUILayout.Width(120f));
GUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59de5c9b86a054d2bba67e3b35d00a6d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace vietlabs.fr2
{
public interface IWindow
{
bool WillRepaint { get; set; }
void Repaint();
void OnSelectionChange();
}
internal interface IRefDraw
{
IWindow window { get; }
int ElementCount();
bool DrawLayout();
bool Draw(Rect rect);
}
public abstract class FR2_WindowBase : EditorWindow, IWindow
{
public bool WillRepaint { get; set; }
protected bool showFilter, showIgnore;
//[NonSerialized] protected bool lockSelection;
//[NonSerialized] internal List<FR2_Asset> Selected;
public static bool isNoticeIgnore;
public void AddItemsToMenu(GenericMenu menu)
{
FR2_Cache api = FR2_Cache.Api;
if (api == null)
{
return;
}
menu.AddDisabledItem(new GUIContent("FR2 - v2.5.2"));
menu.AddSeparator(string.Empty);
menu.AddItem(new GUIContent("Enable"), !api.disabled, () => { api.disabled = !api.disabled; });
menu.AddItem(new GUIContent("Refresh"), false, () =>
{
//FR2_Asset.lastRefreshTS = Time.realtimeSinceStartup;
Resources.UnloadUnusedAssets();
EditorUtility.UnloadUnusedAssetsImmediate();
FR2_Cache.Api.Check4Changes(true);
FR2_SceneCache.Api.SetDirty();
});
#if FR2_DEV
menu.AddItem(new GUIContent("Refresh Usage"), false, () => FR2_Cache.Api.Check4Usage());
menu.AddItem(new GUIContent("Refresh Selected"), false, ()=> FR2_Cache.Api.RefreshSelection());
menu.AddItem(new GUIContent("Clear Cache"), false, () => FR2_Cache.Api.Clear());
#endif
}
public abstract void OnSelectionChange();
protected abstract void OnGUI();
#if UNITY_2018_OR_NEWER
protected void OnSceneChanged(Scene arg0, Scene arg1)
{
if (IsFocusingFindInScene || IsFocusingSceneToAsset || IsFocusingSceneInScene)
{
OnSelectionChange();
}
}
#endif
protected bool DrawEnable()
{
FR2_Cache api = FR2_Cache.Api;
if (api == null)
{
return false;
}
bool v = api.disabled;
if (v)
{
EditorGUILayout.HelpBox("Find References 2 is disabled!", MessageType.Warning);
if (GUILayout.Button("Enable"))
{
api.disabled = !api.disabled;
Repaint();
}
return !api.disabled;
}
return !api.disabled;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 846de4aca6426f74c8cacda9de44511f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ecd25f71eac2146a58139581a59c8ad1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using System;
using UnityEditor;
using UnityEngine;
using vietlabs.fr2;
public class FR2_DeleteButton
{
public string warningMessage;
public string confirmMessage;
public GUIContent deleteLabel;
public bool hasConfirm;
public bool Draw(Action onConfirmDelete)
{
GUILayout.BeginHorizontal();
{
EditorGUILayout.HelpBox(warningMessage, MessageType.Warning);
GUILayout.BeginVertical();
{
GUILayout.Space(2f);
hasConfirm = GUILayout.Toggle(hasConfirm, confirmMessage);
EditorGUI.BeginDisabledGroup(!hasConfirm);
{
GUI2.BackgroundColor(() =>
{
if (GUILayout.Button(deleteLabel, EditorStyles.miniButton))
{
hasConfirm = false;
onConfirmDelete();
GUIUtility.ExitGUI();
}
}, GUI2.darkRed, 0.8f);
}
EditorGUI.EndDisabledGroup();
}
GUILayout.EndVertical();
}
GUILayout.EndHorizontal();
return false;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6f0672714ae60486a8fa4a6c0bf5a614
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public static class FR2_Icon
{
public static GUIContent Lock { get { return TryGet("LockIcon-On"); } }
public static GUIContent Unlock { get { return TryGet("LockIcon"); } }
#if UNITY_2019_3_OR_NEWER
public static GUIContent Refresh { get { return TryGet("d_Refresh@2x"); } }
#else
public static GUIContent Refresh { get { return TryGet("LookDevResetEnv"); } }
#endif
public static GUIContent Selection { get { return TryGet("d_RectTransformBlueprint"); } }
public static GUIContent Details { get { return TryGet("d_UnityEditor.SceneHierarchyWindow"); } }
public static GUIContent Favorite { get { return TryGet("d_Favorite"); } }
public static GUIContent Setting { get { return TryGet("d_SettingsIcon"); } }
public static GUIContent Ignore { get { return TryGet("ShurikenCheckMarkMixed"); } }
public static GUIContent Plus
{
get { return TryGet("ShurikenPlus"); }
}
public static GUIContent Visibility { get { return TryGet("ClothInspector.ViewValue"); } }
#if UNITY_2019_3_OR_NEWER
public static GUIContent Panel { get { return TryGet("VerticalSplit"); } }
#else
public static GUIContent Panel { get { return TryGet("d_LookDevSideBySide"); } }
#endif
public static GUIContent Layout { get { return TryGet("FreeformLayoutGroup Icon"); } }
public static GUIContent Sort { get { return TryGet("AlphabeticalSorting"); } } //d_DefaultSorting
#if UNITY_2019_3_OR_NEWER
public static GUIContent Filter { get { return TryGet("d_ToggleUVOverlay@2x"); } }
#else
public static GUIContent Filter { get { return TryGet("LookDevSplit"); } }
#endif
public static GUIContent Group { get { return TryGet("EditCollider"); } }
public static GUIContent Delete { get { return TryGet("d_TreeEditor.Trash"); } }
public static GUIContent Split { get { return TryGet("VerticalSplit"); } }
public static GUIContent Close { get { return TryGet("LookDevClose"); } }
public static GUIContent Prefab { get { return TryGet("d_Prefab Icon"); } }
public static GUIContent Asset { get { return TryGet("Folder Icon"); } }
public static GUIContent Filesize { get { return TryGet("SavePassive"); } }
public static GUIContent AssetBundle { get { return TryGet("CloudConnect"); } }
public static GUIContent Script { get { return TryGet("dll Script Icon"); } }
public static GUIContent Material { get { return TryGet("d_TreeEditor.Material"); } }
public static GUIContent Scene { get { return TryGet("SceneAsset Icon"); } }
#if UNITY_2017_1_OR_NEWER
public static GUIContent Atlas { get { return TryGet("SpriteAtlas Icon"); } }
#endif
public static GUIContent Folder { get { return TryGet("Project"); } }
public static GUIContent Hierarchy { get { return TryGet("UnityEditor.HierarchyWindow"); } }
private static readonly Dictionary<string, GUIContent> _cache = new Dictionary<string, GUIContent>();
static GUIContent TryGet(string id)
{
GUIContent result;
if (_cache.TryGetValue(id, out result)) return result ?? GUIContent.none;
var icon = EditorGUIUtility.IconContent(id) ?? new GUIContent(Texture2D.whiteTexture);
_cache.Add(id, icon);
return icon;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cac8d1a32d8a04fa3a1fe89aed0f5e56
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using UnityEditor;
using UnityEngine;
namespace vietlabs.fr2
{
public class FR2_SearchView
{
private bool caseSensitive;
private string searchTerm = string.Empty;
public static GUIStyle toolbarSearchField;
public static GUIStyle toolbarSearchFieldCancelButton;
public static GUIStyle toolbarSearchFieldCancelButtonEmpty;
public static void InitSearchStyle()
{
toolbarSearchField = "ToolbarSeachTextFieldPopup";
toolbarSearchFieldCancelButton = "ToolbarSeachCancelButton";
toolbarSearchFieldCancelButtonEmpty = "ToolbarSeachCancelButtonEmpty";
}
public bool DrawLayout()
{
bool dirty = false;
if (toolbarSearchField == null)
{
InitSearchStyle();
}
GUILayout.BeginHorizontal(EditorStyles.toolbar);
{
bool v = GUILayout.Toggle(caseSensitive, "Aa", EditorStyles.toolbarButton, GUILayout.Width(24f));
if (v != caseSensitive)
{
caseSensitive = v;
dirty = true;
}
GUILayout.Space(2f);
string value = GUILayout.TextField(searchTerm, toolbarSearchField, GUILayout.Width(140f));
if (searchTerm != value)
{
searchTerm = value;
dirty = true;
}
GUIStyle style = string.IsNullOrEmpty(searchTerm)
? toolbarSearchFieldCancelButtonEmpty
: toolbarSearchFieldCancelButton;
if (GUILayout.Button("Cancel", style))
{
searchTerm = string.Empty;
dirty = true;
}
}
GUILayout.EndHorizontal();
return dirty;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c5c27d8e961e4de6ab683161c6d53584
timeCreated: 1579769248

View File

@@ -0,0 +1,252 @@
//#define FR2_DEBUG
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Experimental.Rendering;
namespace vietlabs.fr2
{
public class FR2_SplitView
{
private const float SPLIT_SIZE = 2f;
private IWindow window;
private bool dirty;
public FR2_SplitView(IWindow w)
{
this.window = w;
}
[Serializable]
public class Info
{
public GUIContent title;
#if FR2_DEBUG
public Color color;
#endif
public Rect rect;
public float normWeight;
public int stIndex;
public bool visible = true;
public float weight = 1f;
public Action<Rect> draw;
public void DoDraw()
{
#if FR2_DEBUG
GUI2.Rect(rect, Color.white, 0.1f);
#endif
var drawRect = rect;
if (title != null)
{
var titleRect = new Rect(rect.x, rect.y, rect.width, 16f);
GUI2.Rect(titleRect, Color.black, 0.2f);
titleRect.xMin += 4f;
GUI.Label(titleRect, title, EditorStyles.boldLabel);
drawRect.yMin += 16f;
}
draw(drawRect);
}
}
public bool isHorz;
public List<Info> splits = new List<Info>();
public bool isVisible
{
get { return _visibleCount > 0; }
}
private int _visibleCount;
private Rect _rect;
public void CalculateWeight()
{
_visibleCount = 0;
var _totalWeight = 0f;
for (var i = 0; i < splits.Count; i++)
{
var info = splits[i];
if (!info.visible) continue;
info.stIndex = _visibleCount;
_totalWeight += info.weight;
_visibleCount++;
}
if (_visibleCount == 0 || _totalWeight == 0)
{
//Debug.LogWarning("Nothing visible!");
return;
}
var cWeight = 0f;
for (var i = 0; i < splits.Count; i++)
{
var info = splits[i];
if (!info.visible) continue;
cWeight += info.weight;
info.normWeight = info.weight / _totalWeight;
}
}
public void Draw(Rect rect)
{
if (rect.width > 0 || rect.height > 0)
{
_rect = rect;
}
if (dirty)
{
dirty = false;
CalculateWeight();
}
var sz = (_visibleCount - 1) * SPLIT_SIZE;
var dx = _rect.x;
var dy = _rect.y;
for (var i = 0; i < splits.Count; i++)
{
var info = splits[i];
if (!info.visible) continue;
var rr = new Rect
(
dx, dy,
isHorz ? (_rect.width - sz) * info.normWeight : _rect.width,
isHorz ? _rect.height : (_rect.height - sz) * info.normWeight
);
if (rr.width > 0 && rr.height > 0)
{
info.rect = rr;
}
if (info.draw != null) info.DoDraw();
if (info.stIndex < _visibleCount - 1)
{
DrawSpliter(i, isHorz ? info.rect.xMax : info.rect.yMax);
}
if (isHorz)
{
dx += info.rect.width + SPLIT_SIZE;
}
else
{
dy += info.rect.height + SPLIT_SIZE;
}
}
}
public void DrawLayout()
{
var rect = StartLayout(isHorz);
{
Draw(rect);
}
EndLayout(isHorz);
}
private int resizeIndex = -1;
void RefreshSpliterPos(int index, float px)
{
var sp1 = splits[index];
var sp2 = splits[index + 1];
var r1 = sp1.rect;
var r2 = sp2.rect;
var w1 = sp1.weight;
var w2 = sp2.weight;
var tt = w1 + w2;
var dd = isHorz ? (r2.xMax - r1.xMin) : (r2.yMax - r1.yMin) - SPLIT_SIZE;
var m = isHorz ? (Event.current.mousePosition.x - r1.x) : (Event.current.mousePosition.y - r1.y);
var pct = Mathf.Min(0.9f, Mathf.Max(0.1f, m / dd));
sp1.weight = tt * pct;
sp2.weight = tt * (1 - pct);
dirty = true;
if (window != null) window.WillRepaint = true;
}
void DrawSpliter(int index, float px)
{
var dRect = _rect;
if (isHorz)
{
dRect.x = px + SPLIT_SIZE;
dRect.width = SPLIT_SIZE;
}
else
{
dRect.y = px;
dRect.height = SPLIT_SIZE;
}
if (Event.current.type == EventType.Repaint || Event.current.type == EventType.MouseMove)
{
GUI2.Rect(dRect, Color.black, 0.4f);
}
var dRect2 = GUI2.Padding(dRect, -2f, -2f);
EditorGUIUtility.AddCursorRect(dRect2, isHorz ? MouseCursor.ResizeHorizontal : MouseCursor.ResizeVertical);
if (Event.current.type == EventType.MouseDown && dRect2.Contains(Event.current.mousePosition))
{
resizeIndex = index;
RefreshSpliterPos(index, px);
}
if (resizeIndex == index)
{
RefreshSpliterPos(index, px);
}
if (Event.current.type == EventType.MouseUp)
{
resizeIndex = -1;
}
}
Rect StartLayout(bool horz)
{
return horz
? EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true))
: EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
}
void EndLayout(bool horz)
{
if (horz)
{
EditorGUILayout.EndHorizontal();
}
else
{
EditorGUILayout.EndVertical();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f43fafd1663c45d1b2520859c66c6ee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace vietlabs.fr2
{
public class DrawCallback
{
public Action BeforeDraw;
public Action AfterDraw;
}
public class FR2_TabView
{
public int current;
public GUIContent[] labels;
public IWindow window;
public Action onTabChange;
public DrawCallback callback;
public bool canDeselectAll; // can there be no active tabs
public FR2_TabView(IWindow w, bool canDeselectAll)
{
this.window = w;
this.canDeselectAll = canDeselectAll;
}
public bool DrawLayout()
{
bool result = false;
GUILayout.BeginHorizontal(EditorStyles.toolbar);
{
if (callback != null && callback.BeforeDraw != null) callback.BeforeDraw();
for (var i = 0; i < labels.Length; i++)
{
var isActive = (i == current);
var lb = labels[i];
var clicked = (lb.image != null)
? GUI2.ToolbarToggle(ref isActive, lb.image, Vector2.zero, lb.tooltip)
: GUI2.Toggle(ref isActive, lb, EditorStyles.toolbarButton);
if (!clicked) continue;
current = (!isActive && canDeselectAll) ? -1 : i;
result = true;
if (onTabChange != null) onTabChange();
if (window == null) continue;
window.OnSelectionChange(); // force refresh tabs
window.WillRepaint = true;
}
if (callback != null && callback.AfterDraw != null) callback.AfterDraw();
}
GUILayout.EndHorizontal();
return result;
}
public static FR2_TabView FromEnum(Type enumType, IWindow w, bool canDeselectAll = false)
{
var values = Enum.GetValues(enumType);
var labels = new List<GUIContent>();
foreach (var item in values)
{
labels.Add(new GUIContent(item.ToString()));
}
return new FR2_TabView(w, canDeselectAll) { current = 0, labels = labels.ToArray() };
}
public static GUIContent GetGUIContent(object tex)
{
if (tex is GUIContent) return (GUIContent)tex;
if (tex is Texture) return new GUIContent((Texture)tex);
if (tex is string) return new GUIContent((string)tex);
return GUIContent.none;
}
public static FR2_TabView Create(IWindow w, bool canDeselectAll = false, params object[] titles)
{
var labels = new List<GUIContent>();
foreach (var item in titles)
{
labels.Add(GetGUIContent(item));
}
return new FR2_TabView(w, canDeselectAll) { current = 0, labels = labels.ToArray() };
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ea85064796024a07b975d9ebf1ed2fcc
timeCreated: 1579764674

View File

@@ -0,0 +1,279 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Vector2 = UnityEngine.Vector2;
namespace vietlabs.fr2
{
public interface IDrawer
{
bool Draw(Rect rect);
bool DrawLayout();
}
public static class GUI2
{
public static void Color(Action a, Color c, float? alpha = null)
{
if (a == null) return;
var cColor = GUI.color;
if (alpha != null) c.a = alpha.Value;
GUI.color = c;
a();
GUI.color = cColor;
}
public static void ContentColor(Action a, Color c, float? alpha = null)
{
if (a == null) return;
var cColor = GUI.contentColor;
if (alpha != null) c.a = alpha.Value;
GUI.contentColor = c;
a();
GUI.contentColor = cColor;
}
public static void BackgroundColor(Action a, Color c, float? alpha = null)
{
if (a == null) return;
var cColor = GUI.backgroundColor;
if (alpha != null) c.a = alpha.Value;
GUI.backgroundColor = c;
a();
GUI.backgroundColor = cColor;
}
public static Color Theme(Color proColor, Color indieColor)
{
return EditorGUIUtility.isProSkin ? proColor : indieColor;
}
public static Color Alpha(Color c, float a)
{
c.a = a;
return c;
}
public static void Rect(Rect r, Color c, float? alpha = null)
{
var cColor = GUI.color;
if (alpha != null) c.a = alpha.Value;
GUI.color = c;
GUI.DrawTexture(r, Texture2D.whiteTexture);
GUI.color = cColor;
}
public static UnityEngine.Object[] DropZone(string title, float w, float h)
{
var rect = GUILayoutUtility.GetRect(w, h);
GUI.Box(rect, GUIContent.none, EditorStyles.textArea);
var cx = rect.x + w / 2f;
var cy = rect.y + h / 2f;
var pz = w / 3f; // plus size
var plusRect = new Rect(cx - pz / 2f, (cy - pz / 2f), pz, pz);
GUI2.Color(() => { GUI.DrawTexture(plusRect, FR2_Icon.Plus.image, ScaleMode.ScaleToFit); }, UnityEngine.Color.white, 0.1f);
GUI.Label(rect, title, EditorStyles.wordWrappedMiniLabel);
EventType eventType = Event.current.type;
bool isAccepted = false;
if (eventType == EventType.DragUpdated || eventType == EventType.DragPerform)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if (eventType == EventType.DragPerform)
{
DragAndDrop.AcceptDrag();
isAccepted = true;
}
Event.current.Use();
}
return isAccepted ? DragAndDrop.objectReferences : null;
}
// public static bool ColorIconButton(Rect r, Texture icon, Vector2? iconOffset, Color? c)
// {
// if (c != null) Rect(r, c.Value);
//
// // align center
// if (iconOffset != null)
// {
// r.x += iconOffset.Value.x;
// r.y += iconOffset.Value.y;
// }
//
// return GUI.Button(r, icon, GUIStyle.none);
// }
public static bool ColorIconButton(Rect r, Texture icon, Color? c)
{
var oColor = GUI.color;
if (c != null) GUI.color = c.Value;
var result = GUI.Button(r, icon, GUIStyle.none);
GUI.color = oColor;
return result;
}
public static bool Toggle(ref bool value, string label, GUIStyle style, params GUILayoutOption[] options)
{
var vv = GUILayout.Toggle(value, label, style, options);
if (vv == value) return false;
value = vv;
return true;
}
public static bool Toggle(ref bool value, Texture2D tex, GUIStyle style, params GUILayoutOption[] options)
{
var vv = GUILayout.Toggle(value, tex, style, options);
if (vv == value) return false;
value = vv;
return true;
}
public static bool Toggle(ref bool value, GUIContent tex, GUIStyle style, params GUILayoutOption[] options)
{
var vv = GUILayout.Toggle(value, tex, style, options);
if (vv == value) return false;
value = vv;
return true;
}
public static bool Toggle(Rect rect, ref bool value, GUIContent tex)
{
var vv = GUI.Toggle(rect, value, tex, GUIStyle.none);
if (vv == value) return false;
value = vv;
return true;
}
public static bool Toggle(Rect rect, ref bool value)
{
var vv = GUI.Toggle(rect, value, GUIContent.none);
if (vv == value) return false;
value = vv;
return true;
}
internal static bool Toggle(bool v, string label, Action<bool> setter)
{
var v1 = GUILayout.Toggle(v, label);
if (v1 == v) return false;
if (setter != null) setter(v1);
return true;
}
internal static Dictionary<string, GUIContent> tooltipCache = new Dictionary<string, GUIContent>();
internal static GUIContent GetTooltip(string tooltip)
{
if (string.IsNullOrEmpty(tooltip)) return GUIContent.none;
GUIContent result;
if (tooltipCache.TryGetValue(tooltip, out result)) return result;
result = new GUIContent(string.Empty, tooltip);
tooltipCache.Add(tooltip, result);
return result;
}
internal static bool ToolbarToggle(ref bool value, Texture icon, Vector2 padding, string tooltip = null)
{
var vv = GUILayout.Toggle(value, GetTooltip(tooltip), EditorStyles.toolbarButton, GUILayout.Width(22f));
if (icon != null)
{
var rect = GUILayoutUtility.GetLastRect();
rect = Padding(rect, padding.x, padding.y);
GUI.DrawTexture(rect, icon, ScaleMode.ScaleToFit);
}
if (vv == value) return false;
value = vv;
return true;
}
// TODO : optimize for performance
public static bool EnumPopup<T>(ref T mode, string label, float labelWidth, GUIStyle style, params GUILayoutOption[] options)
{
var sz = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = labelWidth;
{
var obj = (Enum)(object)mode;
var vv = EditorGUILayout.EnumPopup(label, obj, style, options);
if (Equals(vv, obj))
{
EditorGUIUtility.labelWidth = sz;
return false;
}
mode = (T)(object)vv;
}
EditorGUIUtility.labelWidth = sz;
return true;
}
public static bool EnumPopup<T>(ref T mode, GUIContent icon, GUIStyle style, params GUILayoutOption[] options)
{
var obj = (Enum)(object)mode;
var cRect = GUILayoutUtility.GetRect(16f, 16f);
cRect.xMin -= 2f;
cRect.yMin += 2f;
GUI.Label(cRect, icon);
var vv = EditorGUILayout.EnumPopup(obj, style, options);
if (Equals(vv, obj))
{
return false;
}
mode = (T)(object)vv;
return true;
}
public static Rect Padding(Rect r, float x, float y)
{
return new Rect(r.x + x, r.y + y, r.width - 2 * x, r.height - 2 * y);
}
public static Rect LeftRect(float w, ref Rect rect)
{
rect.x += w;
rect.width -= w;
return new Rect(rect.x - w, rect.y, w, rect.height);
}
public static Rect RightRect(float w, ref Rect rect)
{
rect.width -= w;
return new Rect(rect.x + rect.width, rect.y, w, rect.height);
}
// -----------------------
private static GUIStyle _miniLabelAlignRight;
public static GUIStyle miniLabelAlignRight
{
get
{
return _miniLabelAlignRight ?? (
_miniLabelAlignRight = new GUIStyle(EditorStyles.miniLabel) { alignment = TextAnchor.MiddleRight }
);
}
}
public static Color darkRed = new Color(0.5f, .0f, 0f, 1f);
public static Color darkGreen = new Color(0, .5f, 0f, 1f);
public static Color darkBlue = new Color(0, .0f, 0.5f, 1f);
public static Color lightRed = new Color(1f, 0.5f, 0.5f, 1f);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9fa484b2aa858464fb8254e4bbf1f6ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: