Add main mesh fixes

This commit is contained in:
Toomas Tamm
2021-02-23 02:13:14 +02:00
parent c89f326c37
commit 989424e659
139 changed files with 8101 additions and 2033 deletions

View File

@@ -0,0 +1,74 @@
using System;
using System.Linq;
namespace Asset_Cleaner {
[Serializable]
class AufSerializableData {
public const int CurrentVersion = 1;
public int Version;
public bool MarkRed;
public int RebuildCacheOnDemand;
public bool ShowInfoBox;
public string IgnorePathContainsCombined;
public bool IgnoreMaterial;
public bool IgnoreScriptable;
static int BoolToInt(bool val) {
return val ? 2 : 1;
}
static bool IntToBool(int val, bool defaultVal) {
switch (val) {
case 2:
return true;
case 1:
return false;
default:
return defaultVal;
}
}
public static AufSerializableData Default() {
return new AufSerializableData {
Version = CurrentVersion,
MarkRed = true,
ShowInfoBox = true,
IgnorePathContainsCombined = "Gizmos;Resources;Editor;Asset Cleaner;Asset Usage Finder;",
IgnoreMaterial = false,
IgnoreScriptable = true,
RebuildCacheOnDemand = 2,
};
}
public static void OnSerialize(in Config src, out AufSerializableData result) {
result = new AufSerializableData();
result.Version = CurrentVersion;
result.MarkRed = src.MarkRed;
result.ShowInfoBox = src.ShowInfoBox;
result.IgnorePathContainsCombined = src.IgnorePathContainsCombined;
result.IgnoreMaterial = src.IgnoreMaterial;
result.IgnoreScriptable = src.IgnoreScriptable;
result.RebuildCacheOnDemand = BoolToInt(src.RebuildCacheOnDemand);
}
public static void OnDeserialize(in AufSerializableData src, ref Config result) {
var def = Default();
result.MarkRed = src.MarkRed;
result.IgnorePathContainsCombined = src.IgnorePathContainsCombined;
result.ShowInfoBox = src.ShowInfoBox;
result.IgnorePathContains = result.IgnorePathContainsCombined
.Split(';')
.Select(s => s.Trim())
.Where(s => !string.IsNullOrWhiteSpace(s))
.ToArray();
result.IgnoreMaterial = src.IgnoreMaterial;
result.IgnoreScriptable = src.IgnoreScriptable;
result.RebuildCacheOnDemand = IntToBool(src.RebuildCacheOnDemand, def.RebuildCacheOnDemand == 2);
}
public bool Valid() {
return Version == CurrentVersion || IgnorePathContainsCombined == null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 14980ecc573d44c59b5f9323603c7bdf
timeCreated: 1588518687

View File

@@ -0,0 +1,105 @@
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
#pragma warning disable 649
namespace Asset_Cleaner {
class CleanerStyleAsset : ScriptableObject {
[Serializable]
public class Style {
public Color RedHighlight = new Color(1, 0, 0, 1f);
public GUIContent Lock;
public GUIStyle LockBtn = new GUIStyle();
public GUIStyle SampleBtn = new GUIStyle();
public GUIContent Unlock;
public GUIStyle UnlockBtn = new GUIStyle();
public GUIContent RemoveFile;
public GUIContent RemoveScene;
public GUIStyle RowMainAssetBtn = new GUIStyle();
public GUIStyle RemoveUnusedBtn = new GUIStyle();
public GUIStyle CurrentBtn = new GUIStyle();
public GUIContent ArrowL;
public GUIContent ArrowR;
public GUIStyle ArrowBtn = new GUIStyle();
public float SceneIndent1 = 20f;
public float SceneIndent2 = 20f;
public GUIStyle ProjectViewCounterLabel;
public GUIContent MultiSelect;
public static bool TryFindSelf(out Style value) {
const string typeName = nameof(CleanerStyleAsset);
var guids = AssetDatabase.FindAssets($"t:{typeName}");
if (!guids.Any()) {
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
}
Asr.IsTrue(guids.Length > 0, $"No '{typeName}' assets found");
var res = guids.Select(AssetDatabase.GUIDToAssetPath).Select(t => (CleanerStyleAsset) AssetDatabase.LoadAssetAtPath(t, typeof(CleanerStyleAsset))).FirstOrDefault();
if (res == null) {
value = default;
return false;
}
value = EditorGUIUtility.isProSkin ? res.Pro : res.Personal;
return value != null;
}
}
#pragma warning disable 0649
public Style Pro;
public Style Personal;
#pragma warning restore
[CustomEditor(typeof(CleanerStyleAsset))]
class Editor : UnityEditor.Editor {
public override void OnInspectorGUI() {
#if false
if (GUILayout.Button("Update Btn backgrounds")) {
var targ = (CleanerStyleAsset) target;
Set(targ.Pro);
}
#endif
EditorGUI.BeginChangeCheck();
base.OnInspectorGUI();
if (EditorGUI.EndChangeCheck())
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
}
#if false
static void Set(Style style) {
var st = style;
var sample = st.SampleBtn;
foreach (var btn in new[] {
st.LockBtn,
st.UnlockBtn,
st.RowMainAssetBtn,
st.RemoveUnusedBtn,
st.CurrentBtn,
st.ArrowBtn,
}) {
btn.normal = sample.normal;
btn.hover = sample.hover;
btn.active = sample.active;
btn.focused = sample.focused;
btn.onNormal = sample.onNormal;
btn.onHover = sample.onHover;
btn.onActive = sample.onActive;
btn.onFocused = sample.onFocused;
}
}
#endif
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
namespace Asset_Cleaner {
enum FindModeEnum {
None = 0,
File = 1,
Scene = 2,
Stage = 3,
}
}

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f94bcb0962724eeea17b007a6ddfd885
timeCreated: 1596213773

View File

@@ -0,0 +1,286 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditorInternal;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;
namespace Asset_Cleaner {
class BacklinkStore {
public bool Initialized { get; private set; }
public Dictionary<string, long> UnusedFiles { get; private set; }
public Dictionary<string, long> UnusedScenes { get; private set; }
public Dictionary<string, BwMeta> Backward { get; private set; }
public Dictionary<string, UnusedQty> FoldersWithQty { get; private set; }
Dictionary<string, FwMeta> _forward;
List<string> Folders { get; set; }
public void Init() {
FoldersWithQty = new Dictionary<string, UnusedQty>();
_forward = new Dictionary<string, FwMeta>();
Backward = new Dictionary<string, BwMeta>();
var defaultAss = typeof(DefaultAsset);
var asmdefAss = typeof(AssemblyDefinitionAsset);
var paths = AssetDatabase.GetAllAssetPaths()
.Distinct()
.Where(s => s.StartsWith("Assets") || s.StartsWith("ProjectSettings"))
.Where(p => {
var t = AssetDatabase.GetMainAssetTypeAtPath(p);
return !t.IsAssignableFromInverse(defaultAss) && !t.IsAssignableFromInverse(asmdefAss);
})
.ToArray();
var i = 0f;
var total = (float) paths.Length;
foreach (var path in paths) {
_FillFwAndBacklinks(path);
var percent = i * 100f / total;
if (Math.Abs(percent % 5f) < 0.01f) {
if (EditorUtility.DisplayCancelableProgressBar(
"Please wait...",
"Building the cache...", percent))
Debug.LogError("Cache build aborted");
}
i++;
}
EditorUtility.ClearProgressBar();
// FillFoldersWithQtyByPaths
List<string> foldersAll = new List<string>();
foreach (var path in paths) {
var folders = GetAllFoldersFromPath(path);
foldersAll.AddRange(folders);
}
Folders = foldersAll.Distinct().OrderBy(p => p).ToList();
UpdateUnusedAssets();
Initialized = true;
}
void _FillFwAndBacklinks(string path) {
var dependencies = _Dependencies(path);
var hs = new FwMeta {Dependencies = new HashSet<string>(dependencies)};
_forward.Add(path, hs);
foreach (var backPath in dependencies) {
if (!Backward.TryGetValue(backPath, out var val)) {
val = new BwMeta();
val.Lookup = new HashSet<string>();
Backward.Add(backPath, val);
}
val.Lookup.Add(path);
}
}
void UpdateFoldersWithQtyByPath(string path) {
var folders = GetAllFoldersFromPath(path);
foreach (var folder in folders) {
if (!Folders.Exists(p => p == folder))
Folders.Add(folder);
}
}
static List<string> GetAllFoldersFromPath(string p) {
var result = new List<string>();
var i = p.IndexOf('/', 0);
while (i > 0) {
var item = p.Substring(0, i);
result.Add(item);
i = p.IndexOf('/', i + 1);
}
return result.Distinct().ToList();
}
public void UpdateUnusedAssets() {
var all = new HashSet<string>(_forward.Keys);
var withBacklinks =
new HashSet<string>(Backward.Where(kv => kv.Value.Lookup.Count > 0).Select(kv => kv.Key));
all.ExceptWith(withBacklinks);
all.RemoveWhere(SearchUtils.IsFileIgrnoredBySettings);
var unusedAssets = all;
var scenes = unusedAssets.Where(s =>
AssetDatabase.GetMainAssetTypeAtPath(s).IsAssignableFromInverse(typeof(SceneAsset))).ToArray();
unusedAssets.ExceptWith(scenes);
var files = unusedAssets;
UnusedFiles = new Dictionary<string, long>();
foreach (var file in files) UnusedFiles[file] = CommonUtils.Size(file);
UnusedScenes = new Dictionary<string, long>();
foreach (var scene in scenes) UnusedScenes[scene] = CommonUtils.Size(scene);
// UpdateFoldersWithQty();
foreach (var folder in Folders) {
var unusedFilesQty = UnusedFiles.Count(p => p.Key.StartsWith(folder));
var unusedScenesQty = UnusedScenes.Count(p => p.Key.StartsWith(folder));
long size = 0;
size = UnusedFiles.Where((p => p.Key.StartsWith(folder))).Sum(p => p.Value);
size += UnusedScenes.Where(p => p.Key.StartsWith(folder)).Sum(p => p.Value);
FoldersWithQty.TryGetValue(folder, out var folderWithQty);
if (folderWithQty == null) {
FoldersWithQty.Add(folder, new UnusedQty(unusedFilesQty, unusedScenesQty, size));
}
else {
folderWithQty.UnusedFilesQty = unusedFilesQty;
folderWithQty.UnusedScenesQty = unusedScenesQty;
folderWithQty.UnusedSize = size;
}
}
}
public void Remove(string path) {
if (!_forward.TryGetValue(path, out var fwMeta))
return;
foreach (var dependency in fwMeta.Dependencies) {
if (!Backward.TryGetValue(dependency, out var dep)) continue;
dep.Lookup.Remove(path);
}
_forward.Remove(path);
UpdateFoldersWithQtyByPath(path);
}
public void Replace(string src, string dest) {
_Upd(_forward);
_Upd(Backward);
UpdateFoldersWithQtyByPath(dest);
void _Upd<T>(Dictionary<string, T> dic) {
if (!dic.TryGetValue(src, out var refs)) return;
dic.Remove(src);
dic.Add(dest, refs);
}
}
public void RebuildFor(string path, bool remove) {
if (!_forward.TryGetValue(path, out var fwMeta)) {
fwMeta = new FwMeta();
_forward.Add(path, fwMeta);
}
else if (remove) {
foreach (var dependency in fwMeta.Dependencies) {
if (!Backward.TryGetValue(dependency, out var backDep)) continue;
backDep.Lookup.Remove(path);
}
fwMeta.Dependencies = null;
}
var dependencies = _Dependencies(path);
fwMeta.Dependencies = new HashSet<string>(dependencies);
foreach (var backPath in dependencies) {
if (!Backward.TryGetValue(backPath, out var bwMeta)) {
bwMeta = new BwMeta {Lookup = new HashSet<string>()};
Backward.Add(backPath, bwMeta);
}
else if (remove)
bwMeta.Lookup.Remove(path);
bwMeta.Lookup.Add(path);
}
if (!remove) {
UpdateFoldersWithQtyByPath(path);
}
}
static string[] _Dependencies(string s) {
if (s[0] == 'A')
return AssetDatabase.GetDependencies(s, false);
var obj = LoadAllOrMain(s)[0];
return GetDependenciesManualPaths().ToArray();
Object[] LoadAllOrMain(string assetPath) {
// prevents error "Do not use readobjectthreaded on scene objects!"
return typeof(SceneAsset) == AssetDatabase.GetMainAssetTypeAtPath(assetPath)
? new[] {AssetDatabase.LoadMainAssetAtPath(assetPath)}
: AssetDatabase.LoadAllAssetsAtPath(assetPath);
}
IEnumerable<string> GetDependenciesManualPaths() {
if (obj is EditorBuildSettings) {
foreach (var scene in EditorBuildSettings.scenes)
yield return scene.path;
}
using (var so = new SerializedObject(obj)) {
var props = so.GetIterator();
while (props.Next(true)) {
switch (props.propertyType) {
case SerializedPropertyType.ObjectReference:
var propsObjectReferenceValue = props.objectReferenceValue;
if (!propsObjectReferenceValue) continue;
var assetPath = AssetDatabase.GetAssetPath(propsObjectReferenceValue);
yield return assetPath;
break;
#if later
case SerializedPropertyType.Generic:
case SerializedPropertyType.ExposedReference:
case SerializedPropertyType.ManagedReference:
break;
#endif
default:
continue;
}
}
}
}
}
class FwMeta {
public HashSet<string> Dependencies;
}
public class BwMeta {
public HashSet<string> Lookup;
}
public class UnusedQty {
public int UnusedFilesQty;
public int UnusedScenesQty;
public long UnusedSize;
public UnusedQty() {
Init(0, 0, 0);
}
public UnusedQty(int unusedFilesQty, int unusedScenesQty, long unusedSize) {
Init(unusedFilesQty, unusedScenesQty, unusedSize);
}
private void Init(int unusedFilesQty, int unusedScenesQty, long unusedSize) {
UnusedFilesQty = unusedFilesQty;
UnusedScenesQty = unusedScenesQty;
UnusedSize = unusedSize;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 004e5680782f4e679ae93027d2d40023
timeCreated: 1577106223

View File

@@ -0,0 +1,20 @@
namespace Asset_Cleaner {
class Config {
// serialized
public bool MarkRed;
public string IgnorePathContainsCombined;
public bool ShowInfoBox;
public bool RebuildCacheOnDemand;
// todo make type array
public bool IgnoreMaterial;
public bool IgnoreScriptable;
// serialized only while window is opened
public bool Locked;
// non-serialized
public string[] IgnorePathContains;
public string InitializationTime;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a6ff796e4dab4324887a303cba29eed4
timeCreated: 1577117228

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
namespace Asset_Cleaner {
[Serializable]
class PersistentUndoRedoState {
public List<SelectionEntry> History = new List<SelectionEntry>();
public int Id;
public void Deconstruct(out List<SelectionEntry> list, out int id) {
id = Id;
list = History;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5414db21dfea4d7eaff8ce4c8f106c8d
timeCreated: 1596213717

View File

@@ -0,0 +1,6 @@
namespace Asset_Cleaner {
class UndoRedoState {
public bool UndoEnabled;
public bool RedoEnabled;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c3ac9efa32c8491aa8a11749f8020d96
timeCreated: 1596213776

View File

@@ -0,0 +1,14 @@
using UnityEngine;
namespace Asset_Cleaner {
class WindowData {
public bool ExpandFiles;
public bool ExpandScenes;
public Vector2 ScrollPos;
public CleanerStyleAsset.Style Style;
public GUIContent SceneFoldout;
public PrevClick Click;
public AufWindow Window;
public FindModeEnum FindFrom;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8481f043b2414c08a45957dcd6035fbe
timeCreated: 1575305740

View File

@@ -0,0 +1,11 @@
using Leopotam.Ecs;
namespace Asset_Cleaner {
class InSceneResult : IEcsAutoReset {
public string ScenePath;
public void Reset() {
ScenePath = default;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 013577ffef1140109e8367f2a5f75fa6
timeCreated: 1577269723

View File

@@ -0,0 +1,18 @@
using UnityEngine;
namespace Asset_Cleaner {
public struct PrevClick {
const float DoubleClickTime = 0.5f;
Object _target;
float _timeClicked;
public PrevClick(Object target) {
_target = target;
_timeClicked = Time.realtimeSinceStartup;
}
public bool IsDoubleClick(Object o) {
return _target == o && Time.realtimeSinceStartup - _timeClicked < DoubleClickTime;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 31c0f204d1b044caaa02a0726f11a270
timeCreated: 1576087327

View File

@@ -0,0 +1,19 @@
using Leopotam.Ecs;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Asset_Cleaner {
class Result : IEcsAutoReset {
public string FilePath;
public Object File;
public Object MainFile;
public GameObject RootGo;
public void Reset() {
FilePath = default;
File = default;
MainFile = default;
RootGo = default;
}
}
}

View File

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

View File

@@ -0,0 +1,20 @@
using Leopotam.Ecs;
using UnityEngine.SceneManagement;
namespace Asset_Cleaner {
class SceneDetails : IEcsAutoReset {
public string Path;
public Scene Scene;
public bool SearchRequested;
public bool SearchDone;
public bool WasOpened;
public void Reset() {
Path = default;
Scene = default;
SearchRequested = default;
SearchDone = default;
WasOpened = default;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 14749f86c2c14febb592442508f8c23a
timeCreated: 1577266613

View File

@@ -0,0 +1,11 @@
using Leopotam.Ecs;
namespace Asset_Cleaner {
class SceneResult : IEcsAutoReset {
public string PathNicified;
public void Reset() {
PathNicified = default;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 338e9e86c9274f91808429753a912d4b
timeCreated: 1576083610

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using Leopotam.Ecs;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Asset_Cleaner {
class SearchArg : IEcsAutoReset {
public Object Target;
public Object Main;
public string FilePath;
public Option<Object[]> SubAssets;
public Scene Scene;
public List<string> UnusedAssetsFiltered;
public List<string> UnusedScenesFiltered;
public void Reset() {
UnusedAssetsFiltered = default;
UnusedScenesFiltered = default;
Target = default;
Main = default;
SubAssets = default;
Scene = default;
FilePath = default;
}
}
}

View File

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

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using Leopotam.Ecs;
using UnityEditor;
using UnityEngine;
namespace Asset_Cleaner {
class SearchResultGui : IEcsAutoReset {
public SerializedObject SerializedObject;
public List<PropertyData> Properties;
public GUIContent Label;
public string TransformPath;
public void Reset() {
SerializedObject?.Dispose();
SerializedObject = default;
if (Properties != default)
foreach (var propertyData in Properties) {
propertyData.Property.Dispose();
}
Properties = default;
Label = default;
TransformPath = default;
}
public class PropertyData {
public SerializedProperty Property;
public GUIContent Content;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 14f26ff078c04c5685fdbb3ec3f92382
timeCreated: 1576168925

View File

@@ -0,0 +1,17 @@
using Leopotam.Ecs;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Asset_Cleaner {
class SelectionChanged : IEcsAutoReset {
public Object Target;
public Scene Scene;
public FindModeEnum From;
public void Reset() {
Target = default;
Scene = default;
From = default;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1d0dc4d007bb4ebbbeea6626197d17b9
timeCreated: 1575365553

View File

@@ -0,0 +1,31 @@
using System;
using UnityEditor;
using Object = UnityEngine.Object;
namespace Asset_Cleaner {
[Serializable]
class SelectionEntry {
public bool IsGuids;
public string[] Guids;
public Object[] SceneObjects;
public bool Valid() {
if (IsGuids) {
foreach (var guid in Guids) {
var path = AssetDatabase.GUIDToAssetPath(guid);
if (!string.IsNullOrEmpty(path))
return true;
}
return false;
}
foreach (var sceneObject in SceneObjects)
if (sceneObject)
return true;
return false;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2b4476be23474ea4b20262c0ee59983c
timeCreated: 1596139978