整合SLSUtilities

This commit is contained in:
SoulliesOfficial
2026-01-17 11:35:49 -05:00
parent d94241f36c
commit 7ee2894a63
1338 changed files with 3051541 additions and 507034 deletions

View File

@@ -0,0 +1,19 @@
{
"name": "LunaWolfStudiosEditor.ScriptableSheets.Scanning",
"rootNamespace": "LunaWolfStudiosEditor.ScriptableSheets.Scanning",
"references": [
"GUID:b37e9192bd2da3f4cbecf27120ea8f63",
"GUID:da9a3cdcbea6eb84fa9a4e997b44b7b3"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 0442c8337274c4247bf01f0da6282230
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 284559
packageName: Scriptable Sheets
packageVersion: 1.8.0
assetPath: Packages/com.lunawolfstudios.scriptablesheets/Editor/Modules/Scanning/LunaWolfStudiosEditor.ScriptableSheets.Scanning.asmdef
uploadId: 823456

View File

@@ -0,0 +1,215 @@
using LunaWolfStudiosEditor.ScriptableSheets.Layout;
using LunaWolfStudiosEditor.ScriptableSheets.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace LunaWolfStudiosEditor.ScriptableSheets.Scanning
{
public class ObjectScanner
{
private const string ProgressBarTitle = "Scriptable Sheets - Object Scanner";
private readonly Dictionary<Type, List<Object>> m_ObjectsByType = new Dictionary<Type, List<Object>>();
public Dictionary<Type, List<Object>> ObjectsByType => m_ObjectsByType;
private Type[] m_ObjectTypes;
public Type[] ObjectTypes => m_ObjectTypes;
private string[] m_ObjectTypeNames;
public string[] ObjectTypeNames => m_ObjectTypeNames;
private string[] m_FriendlyObjectTypeNames;
public string[] FriendlyObjectTypeNames => m_FriendlyObjectTypeNames;
private readonly Dictionary<Type, Dictionary<Object, List<Object>>> m_SubAssetsByTypeAndMainAsset = new Dictionary<Type, Dictionary<Object, List<Object>>>();
public Dictionary<Type, Dictionary<Object, List<Object>>> SubAssetsByTypeAndMainAsset => m_SubAssetsByTypeAndMainAsset;
public void ScanObjects(ScanSettings settings, SheetAsset sheetAsset)
{
try
{
m_ObjectsByType.Clear();
m_SubAssetsByTypeAndMainAsset.Clear();
// Refresh incase new folders or assets were created.
AssetDatabase.Refresh();
// Unity does not consider the root Packages folder as a valid folder so we need to check it separately.
if (settings.PathOption == ScanPathOption.Default && !AssetDatabase.IsValidFolder(settings.Path) && settings.Path != UnityConstants.Packages)
{
settings.Path = UnityConstants.DefaultAssetPath;
}
var scanPaths = settings.GetScanPaths();
var joinedPaths = settings.GetJoinedScanPaths(scanPaths);
if (settings.ShowProgressBar)
{
EditorUtility.DisplayProgressBar(ProgressBarTitle, $"Scanning for assets of type {sheetAsset} at path(s) {joinedPaths}", 0.40f);
}
var guids = AssetDatabase.FindAssets($"t:{sheetAsset}", scanPaths);
if (settings.ShowProgressBar)
{
EditorUtility.DisplayProgressBar(ProgressBarTitle, $"Loading assets of type {sheetAsset} at path(s) {joinedPaths}", 0.80f);
}
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
var asset = AssetDatabase.LoadAssetAtPath<Object>(path);
if (asset == null)
{
continue;
}
var assetType = asset.GetType();
var nextAssetType = assetType;
// Map the asset to its type and base types.
while (nextAssetType.IsValidUnityObjectSubclass())
{
if (nextAssetType.IsValidConcreteType())
{
if (!m_ObjectsByType.TryGetValue(nextAssetType, out var objectsByType))
{
objectsByType = new List<Object>();
m_ObjectsByType[nextAssetType] = objectsByType;
}
objectsByType.Add(asset);
}
nextAssetType = nextAssetType.BaseType;
}
if (sheetAsset == SheetAsset.Scene)
{
continue;
}
var subAssets = AssetDatabase.LoadAllAssetsAtPath(path);
if (subAssets.Length <= 1)
{
continue;
}
foreach (var subAsset in subAssets)
{
if (subAsset == null || subAsset == asset)
{
continue;
}
if (sheetAsset == SheetAsset.Prefab)
{
if (subAsset is Component)
{
var subAssetGameObject = ((Component) subAsset).gameObject;
var isRootPrefab = asset == subAssetGameObject;
if (!settings.RootPrefabsOnly || isRootPrefab)
{
var subAssetType = subAsset.GetType();
if (!m_ObjectsByType.TryGetValue(subAssetType, out var objectsByType))
{
objectsByType = new List<Object>();
m_ObjectsByType[subAssetType] = objectsByType;
}
objectsByType.Add(subAsset);
}
}
}
else
{
if (AssetDatabase.IsSubAsset(subAsset))
{
var subAssetType = subAsset.GetType();
var nextSubAssetType = subAssetType;
while (nextSubAssetType.IsValidUnityObjectSubclass())
{
// For binary types like Textures we want to add all the valid subclass types.
// For ScriptableObjects it must be a scriptable object type.
if (sheetAsset != SheetAsset.ScriptableObject || nextSubAssetType.IsSubclassOf(typeof(ScriptableObject)))
{
if (!m_ObjectsByType.TryGetValue(nextSubAssetType, out var objectsByType))
{
objectsByType = new List<Object>();
m_ObjectsByType[nextSubAssetType] = objectsByType;
}
objectsByType.Add(subAsset);
if (!m_SubAssetsByTypeAndMainAsset.TryGetValue(nextSubAssetType, out var subAssetByMainAsset))
{
subAssetByMainAsset = new Dictionary<Object, List<Object>>();
m_SubAssetsByTypeAndMainAsset[nextSubAssetType] = subAssetByMainAsset;
}
if (!subAssetByMainAsset.TryGetValue(asset, out var subAssetList))
{
subAssetList = new List<Object>();
subAssetByMainAsset[asset] = subAssetList;
}
subAssetList.Add(subAsset);
}
nextSubAssetType = nextSubAssetType.BaseType;
}
}
}
}
}
if (settings.ShowProgressBar)
{
EditorUtility.DisplayProgressBar(ProgressBarTitle, $"Resolving {sheetAsset} types using {nameof(ScanOption)} {settings.Option}", 0.90f);
}
if (sheetAsset == SheetAsset.ScriptableObject && settings.Option == ScanOption.Assembly)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var objectTypes = new List<Type>();
foreach (var assembly in assemblies)
{
var types = assembly.GetTypes().Where
(
type => type.IsSubclassOf(typeof(ScriptableObject))
&& type.IsSerializable
&& type.IsValidConcreteType()
&& !type.IsSubclassOf(typeof(Editor))
&& !type.IsSubclassOf(typeof(EditorWindow))
&& !type.IsScriptableSingleton()
);
objectTypes.AddRange(types);
}
m_ObjectTypes = objectTypes.Concat(m_ObjectsByType.Keys).Distinct().OrderBy(type => type.FullName).ToArray();
}
else
{
m_ObjectTypes = m_ObjectsByType.Keys.OrderBy(type => type.FullName).ToArray();
}
if (settings.ShowProgressBar)
{
EditorUtility.DisplayProgressBar(ProgressBarTitle, $"Finalizing {sheetAsset} type names", 0.98f);
}
m_ObjectTypeNames = m_ObjectTypes.Select(type => type.FullName).ToArray();
// Submenu once we start having a lot of Objects.
var separator = '.';
if (m_ObjectTypeNames.Length > SheetLayout.SubMenuThreshold)
{
var newSeparator = '/';
m_ObjectTypeNames = m_ObjectTypeNames.Select(s => s.Replace(separator, newSeparator)).ToArray();
separator = newSeparator;
}
m_FriendlyObjectTypeNames = m_ObjectTypeNames.Select(s => s.Substring(s.LastIndexOf(separator) + 1)).ToArray();
}
catch (Exception ex)
{
Debug.LogError($"{nameof(ScanObjects)} for {nameof(SheetAsset)} {sheetAsset} failed with error: {ex}");
}
finally
{
EditorUtility.ClearProgressBar();
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: c4018a2d67bd0e64492cb3270615f6f3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 284559
packageName: Scriptable Sheets
packageVersion: 1.8.0
assetPath: Packages/com.lunawolfstudios.scriptablesheets/Editor/Modules/Scanning/ObjectScanner.cs
uploadId: 823456

View File

@@ -0,0 +1,8 @@
namespace LunaWolfStudiosEditor.ScriptableSheets.Scanning
{
public enum ScanOption
{
Default = 0,
Assembly = 1,
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3d706a65632dd3041952bb5c61225d0c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 284559
packageName: Scriptable Sheets
packageVersion: 1.8.0
assetPath: Packages/com.lunawolfstudios.scriptablesheets/Editor/Modules/Scanning/ScanOption.cs
uploadId: 823456

View File

@@ -0,0 +1,10 @@
namespace LunaWolfStudiosEditor.ScriptableSheets.Scanning
{
public enum ScanPathOption
{
Default = 0,
Assets = 1,
Packages = 2,
All = 3,
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 08d4b29bf4547d64cb4f0ffeaa043cff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 284559
packageName: Scriptable Sheets
packageVersion: 1.8.0
assetPath: Packages/com.lunawolfstudios.scriptablesheets/Editor/Modules/Scanning/ScanPathOption.cs
uploadId: 823456

View File

@@ -0,0 +1,63 @@
using LunaWolfStudiosEditor.ScriptableSheets.Shared;
using UnityEngine;
namespace LunaWolfStudiosEditor.ScriptableSheets.Scanning
{
[System.Serializable]
public class ScanSettings
{
[SerializeField]
private ScanOption m_Option = ScanOption.Default;
public ScanOption Option { get => m_Option; set => m_Option = value; }
[SerializeField]
private ScanPathOption m_PathOption = ScanPathOption.Default;
public ScanPathOption PathOption { get => m_PathOption; set => m_PathOption = value; }
[SerializeField]
private string m_Path = UnityConstants.DefaultAssetPath;
public string Path { get => m_Path; set => m_Path = value; }
[SerializeField]
private bool m_ShowProgressBar = true;
public bool ShowProgressBar { get => m_ShowProgressBar; set => m_ShowProgressBar = value; }
[SerializeField]
private bool m_RootPrefabsOnly = true;
public bool RootPrefabsOnly { get => m_RootPrefabsOnly; set => m_RootPrefabsOnly = value; }
public string[] GetScanPaths()
{
switch (m_PathOption)
{
case ScanPathOption.Default:
return new string[] { m_Path };
case ScanPathOption.Assets:
return new string[] { UnityConstants.DefaultAssetPath };
case ScanPathOption.Packages:
return new string[] { UnityConstants.Packages };
case ScanPathOption.All:
return new string[] { UnityConstants.DefaultAssetPath, UnityConstants.Packages };
default:
Debug.LogWarning($"Selected {nameof(ScanPathOption)} {m_PathOption} is not defined. Using default scan path {UnityConstants.DefaultAssetPath}.");
return new string[] { UnityConstants.DefaultAssetPath };
}
}
public string GetFirstScanPath()
{
return GetScanPaths()[0];
}
public string GetJoinedScanPaths()
{
var scanPaths = GetScanPaths();
return string.Join("\n", scanPaths);
}
public string GetJoinedScanPaths(string[] scanPaths)
{
return string.Join("\n", scanPaths);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: bd3149c94f78c61419a2b93cbbe23f68
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 284559
packageName: Scriptable Sheets
packageVersion: 1.8.0
assetPath: Packages/com.lunawolfstudios.scriptablesheets/Editor/Modules/Scanning/ScanSettings.cs
uploadId: 823456

View File

@@ -0,0 +1,79 @@
using System.Collections.Generic;
using UnityEngine;
namespace LunaWolfStudiosEditor.ScriptableSheets.Scanning
{
[System.Flags]
public enum SheetAsset
{
Default = 0,
ScriptableObject = 1 << 0,
AnimationClip = 1 << 1,
AnimatorController = 1 << 2,
AudioClip = 1 << 3,
AudioMixer = 1 << 4,
AvatarMask = 1 << 5,
Flare = 1 << 6,
Font = 1 << 7,
Material = 1 << 8,
Mesh = 1 << 9,
#if UNITY_6000_0_OR_NEWER
PhysicsMaterial = 1 << 10,
#else
PhysicMaterial = 1 << 10,
#endif
PhysicsMaterial2D = 1 << 11,
Prefab = 1 << 12,
Scene = 1 << 13,
Shader = 1 << 14,
Sprite = 1 << 15,
TerrainData = 1 << 16,
TextAsset = 1 << 17,
Texture = 1 << 18,
VideoClip = 1 << 19,
}
public static class SheetAssetExtensions
{
private static readonly Dictionary<SheetAsset, string> s_SheetAssetToType = new Dictionary<SheetAsset, string>()
{
{ SheetAsset.AnimationClip, "UnityEditor.AnimationClip" },
{ SheetAsset.AnimatorController, "UnityEditor.Animations.AnimatorController" },
{ SheetAsset.AudioClip, "UnityEditor.AudioClip" },
{ SheetAsset.AudioMixer, "UnityEditor.Audio.AudioMixerController" },
{ SheetAsset.AvatarMask, "UnityEngine.AvatarMask" },
{ SheetAsset.Flare, "UnityEngine.Flare" },
{ SheetAsset.Font, "UnityEngine.Font" },
{ SheetAsset.Material, "UnityEngine.Material" },
{ SheetAsset.Mesh, "UnityEngine.Mesh" },
#if UNITY_6000_0_OR_NEWER
{ SheetAsset.PhysicsMaterial, "UnityEngine.PhysicsMaterial" },
#else
{ SheetAsset.PhysicMaterial, "UnityEngine.PhysicMaterial" },
#endif
{ SheetAsset.PhysicsMaterial2D, "UnityEngine.PhysicsMaterial2D" },
{ SheetAsset.Prefab, "UnityEngine.GameObject" },
{ SheetAsset.Scene, "UnityEngine.SceneAsset" },
{ SheetAsset.ScriptableObject, "UnityEngine.ScriptableObject" },
{ SheetAsset.Shader, "UnityEngine.Shader" },
{ SheetAsset.Sprite, "UnityEngine.Sprite" },
{ SheetAsset.TerrainData, "UnityEngine.TerrainData" },
{ SheetAsset.TextAsset, "UnityEngine.TextAsset" },
{ SheetAsset.Texture, "UnityEngine.Texture2D" },
{ SheetAsset.VideoClip, "UnityEngine.Video.VideoClip" }
};
public static string GetDefaultType(this SheetAsset sheetAsset)
{
if (s_SheetAssetToType.TryGetValue(sheetAsset, out string type))
{
return type;
}
else
{
Debug.LogWarning($"{nameof(SheetAsset)} '{sheetAsset}' not found in dictionary {nameof(s_SheetAssetToType)}.");
return string.Empty;
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 9e4399e7732bb7d48b5420fb7bd9beaa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 284559
packageName: Scriptable Sheets
packageVersion: 1.8.0
assetPath: Packages/com.lunawolfstudios.scriptablesheets/Editor/Modules/Scanning/SheetAsset.cs
uploadId: 823456