diff --git a/Editor/Hierarchy/EditorProjectValidatorHierarchy.cs b/Editor/Hierarchy/EditorProjectValidatorHierarchy.cs index cacd52c..a41dbc3 100644 --- a/Editor/Hierarchy/EditorProjectValidatorHierarchy.cs +++ b/Editor/Hierarchy/EditorProjectValidatorHierarchy.cs @@ -10,32 +10,19 @@ namespace Module.ProjectValidator.Editor { static EditorProjectValidatorHierarchy() { -#if UNITY_6000_4_OR_NEWER - EditorApplication.hierarchyWindowItemByEntityIdOnGUI -= OnHierarchyWindowItemByEntityIdOnGUI; - EditorApplication.hierarchyWindowItemByEntityIdOnGUI += OnHierarchyWindowItemByEntityIdOnGUI; -#else EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemOnGUI; EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowItemOnGUI; -#endif EditorSceneManager.sceneOpened -= OnSceneOpened; EditorSceneManager.sceneOpened += OnSceneOpened; } -#if UNITY_6000_4_OR_NEWER - private static void OnHierarchyWindowItemByEntityIdOnGUI(EntityId entityId, Rect selectionRect) - { - if (Report.HasActive && Report.Active.TryGetSeverityFor(entityId, out var instance) && instance.Severity != EValidatorSeverity.Valid) - EditorIconUtility.Draw(new Rect(selectionRect.x, selectionRect.y, selectionRect.height, selectionRect.height), instance.Severity, instance.IsRedirect); - } -#else private static void OnHierarchyWindowItemOnGUI(int instanceID, Rect selectionRect) { if (Report.HasActive && Report.Active.TryGetSeverityFor(instanceID, out var instance) && instance.Severity != EValidatorSeverity.Valid) EditorIconUtility.Draw(new Rect(selectionRect.x, selectionRect.y, selectionRect.height, selectionRect.height), instance.Severity, instance.IsRedirect); } -#endif - + private static void OnSceneOpened(Scene scene, OpenSceneMode mode) { if (Report.HasActive && ProjectValidatorUtility.IsValidForRun()) diff --git a/Editor/Icons/editor_project_validator_settings.png b/Editor/Icons/editor_project_validator_settings.png deleted file mode 100644 index f938577..0000000 Binary files a/Editor/Icons/editor_project_validator_settings.png and /dev/null differ diff --git a/Editor/Icons/editor_project_validator_settings.png.meta b/Editor/Icons/editor_project_validator_settings.png.meta deleted file mode 100644 index 524687d..0000000 --- a/Editor/Icons/editor_project_validator_settings.png.meta +++ /dev/null @@ -1,117 +0,0 @@ -fileFormatVersion: 2 -guid: a6c61d5fbd310894d8159ba6af32d7e3 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 13 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 0 - wrapV: 0 - wrapW: 0 - nPOTScale: 1 - lightmap: 0 - compressionQuality: 50 - spriteMode: 0 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 0 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 4 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 4 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - customData: - physicsShape: [] - bones: [] - spriteID: - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spriteCustomMetadata: - entries: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/Objects/Report.cs b/Editor/Objects/Report.cs index 5b68f9f..dae4e6c 100644 --- a/Editor/Objects/Report.cs +++ b/Editor/Objects/Report.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using UnityEditor; -using UnityEngine; namespace Module.ProjectValidator.Editor { @@ -12,28 +11,23 @@ namespace Module.ProjectValidator.Editor public readonly List Entries = new(); private readonly Dictionary _assetToSeverityMapping = new(); - -#if UNITY_6000_4_OR_NEWER - private readonly Dictionary _instanceToSeverityMapping = new(); -#else private readonly Dictionary _instanceToSeverityMapping = new(); -#endif - public void Add(GUID assetGuid, string relativePath, string fieldPath, Attribute attribute, EValidatorSeverity severity, string message) + public void Add(GUID assetGuid, string scenePath, string fieldPath, Attribute attribute, EValidatorSeverity severity, string message) { var type = ProjectValidatorUtility.GetAttributeShortName(attribute); - Add(assetGuid, relativePath, fieldPath, type, severity, message); + Add(assetGuid, scenePath, fieldPath, type, severity, message); } - public void Add(GUID assetGuid, string relativePath, string fieldPath, string type, EValidatorSeverity severity, string message) + public void Add(GUID assetGuid, string scenePath, string fieldPath, string type, EValidatorSeverity severity, string message) { Entries.Add(new Entry { AssetGuid = assetGuid, AssetName = EditorAssetUtility.GetAssetName(assetGuid), - RelativePath = relativePath, + ScenePath = scenePath, FieldPath = fieldPath, - RelativePathRichText = ProjectValidatorUtility.ApplyRichTextToRelativePath(relativePath), + ScenePathRichText = ProjectValidatorUtility.ApplyRichTextToScenePath(scenePath), FieldPathRichText = ProjectValidatorUtility.ApplyRichTextToFieldPath(fieldPath), Type = type, Severity = severity, @@ -70,17 +64,7 @@ namespace Module.ProjectValidator.Editor mapping = new MappingEntry(); return false; } - -#if UNITY_6000_4_OR_NEWER - public bool TryGetSeverityFor(EntityId entityId, out MappingEntry mapping) - { - if (_instanceToSeverityMapping.TryGetValue(entityId, out mapping)) - return true; - - mapping = new MappingEntry(); - return false; - } -#else + public bool TryGetSeverityFor(int instanceId, out MappingEntry mapping) { if (_instanceToSeverityMapping.TryGetValue(instanceId, out mapping)) @@ -89,9 +73,8 @@ namespace Module.ProjectValidator.Editor mapping = new MappingEntry(); return false; } -#endif - public bool TryGetSeverityFor(GUID assetGuid, string relativePath, out MappingEntry mapping) + public bool TryGetSeverityFor(GUID assetGuid, string scenePath, out MappingEntry mapping) { if (!_assetToSeverityMapping.TryGetValue(assetGuid, out mapping)) return false; @@ -100,7 +83,7 @@ namespace Module.ProjectValidator.Editor for (var i = 0; i < Entries.Count; i++) { - if (Entries[i].AssetGuid != assetGuid || Entries[i].RelativePath != relativePath || Entries[i].Severity <= mapping.Severity) + if (Entries[i].AssetGuid != assetGuid || Entries[i].ScenePath != scenePath || Entries[i].Severity <= mapping.Severity) continue; mapping = new MappingEntry(Entries[i].Severity, false); @@ -127,10 +110,10 @@ namespace Module.ProjectValidator.Editor public GUID AssetGuid; public string AssetName; - public string RelativePath; + public string ScenePath; public string FieldPath; - public string RelativePathRichText; + public string ScenePathRichText; public string FieldPathRichText; public string Type; @@ -141,7 +124,7 @@ namespace Module.ProjectValidator.Editor public bool Filter(string filter) { return AssetName.Contains(filter, StringComparison.InvariantCultureIgnoreCase) || - RelativePath.Contains(filter, StringComparison.InvariantCultureIgnoreCase) || + ScenePath.Contains(filter, StringComparison.InvariantCultureIgnoreCase) || FieldPath.Contains(filter, StringComparison.InvariantCultureIgnoreCase) || Type.Contains(filter, StringComparison.InvariantCultureIgnoreCase) || SeverityResult.Contains(filter, StringComparison.InvariantCultureIgnoreCase) || diff --git a/Editor/Objects/TypeTree.cs b/Editor/Objects/TypeTree.cs index 4cddc30..5b69e0c 100644 --- a/Editor/Objects/TypeTree.cs +++ b/Editor/Objects/TypeTree.cs @@ -31,16 +31,9 @@ namespace Module.ProjectValidator.Editor if (!IsFieldSerializable(fi)) continue; - var fieldAttributes = fi.GetCustomAttributes(); - var fieldTypeAttributes = fi.FieldType.GetCustomAttributes(); + var attributes = fi.GetCustomAttributes(); - foreach (var attribute in fieldAttributes) - { - if (validatorList.TryGetAttributeValidator(attribute.GetType(), out var validator)) - entry.AddField(fi, attribute, validator); - } - - foreach (var attribute in fieldTypeAttributes) + foreach (var attribute in attributes) { if (validatorList.TryGetAttributeValidator(attribute.GetType(), out var validator)) entry.AddField(fi, attribute, validator); @@ -171,7 +164,7 @@ namespace Module.ProjectValidator.Editor return Components == null && Fields == null && Entries == null; } } - + public sealed class ValidatorField { public readonly FieldInfo FieldInfo; diff --git a/Editor/Objects/ValidatorList.cs b/Editor/Objects/ValidatorList.cs index 39221ff..d75a061 100644 --- a/Editor/Objects/ValidatorList.cs +++ b/Editor/Objects/ValidatorList.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Runtime.Serialization; using UnityEngine; @@ -11,8 +10,6 @@ namespace Module.ProjectValidator.Editor { private readonly Dictionary _attributeValidators = new(); private readonly Dictionary> _componentValidators = new(); - public readonly List GameObjectValidators = new(); - public readonly Dictionary> AssetValidators = new(); public void AddAttribute(Type type) { @@ -62,49 +59,6 @@ namespace Module.ProjectValidator.Editor } } - public void AddGameObject(Type type) - { - if (type.IsInterface || type.IsAbstract) - return; - - try - { - var instance = (IGameObjectValidator)FormatterServices.GetUninitializedObject(type); - GameObjectValidators.Add(instance); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - - public void AddAsset(Type type) - { - if (type.IsInterface || type.IsAbstract) - return; - - var typeValidator = type.GetInterfaces().FirstOrDefault(typeInterface => typeInterface.IsGenericType && typeInterface.GetGenericTypeDefinition() == typeof(IAssetValidator<>)); - var componentType = typeValidator?.GetGenericArguments()[0]; - - if (componentType == null) - return; - - try - { - var instance = FormatterServices.GetUninitializedObject(type); - var validator = new AssetValidator(instance); - - if (AssetValidators.TryGetValue(componentType, out var list)) - list.Add(validator); - else - AssetValidators.Add(componentType, new List { validator }); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - public bool TryGetAttributeValidator(Type type, out object validatorInstance) { return _attributeValidators.TryGetValue(type, out validatorInstance); @@ -114,17 +68,5 @@ namespace Module.ProjectValidator.Editor { return _componentValidators.TryGetValue(type, out validatorInstances); } - - public sealed class AssetValidator - { - public readonly object Validator; - public readonly MethodInfo ValidatorMethod; - - public AssetValidator(object validator) - { - Validator = validator; - ValidatorMethod = validator.GetType().GetMethod("Validate"); - } - } } } \ No newline at end of file diff --git a/Editor/Settings/ProjectValidatorSettings.cs b/Editor/Settings/ProjectValidatorSettings.cs index ec2893f..b526db7 100644 --- a/Editor/Settings/ProjectValidatorSettings.cs +++ b/Editor/Settings/ProjectValidatorSettings.cs @@ -1,36 +1,27 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; using UnityEditor.UIElements; using UnityEditorInternal; -using UnityEngine.Pool; -using Object = UnityEngine.Object; namespace Module.ProjectValidator.Editor { internal sealed class ProjectValidatorSettings : ScriptableObject { public List assemblies = new(); - [NonReorderable] - public List validators = new(); - - public const string MenuPath = "Project/Project Validator"; + private const string AssetPath = "ProjectSettings/ProjectValidatorSettings.asset"; private const string StyleSheetName = "StyleSheetProjectValidatorSettings"; internal static ProjectValidatorSettings GetOrCreate() { var objects = InternalEditorUtility.LoadSerializedFileAndForget(AssetPath); - ProjectValidatorSettings settings; if (objects.Length != 0) - settings = (ProjectValidatorSettings)objects[0]; - else - settings = CreateInstance(); + return (ProjectValidatorSettings)objects[0]; - PopulateValidatorList(settings); + var settings = CreateInstance(); InternalEditorUtility.SaveToSerializedFileAndForget(new Object[] { settings }, AssetPath, true); return settings; } @@ -38,7 +29,7 @@ namespace Module.ProjectValidator.Editor [SettingsProvider] public static SettingsProvider CreateProvider() { - return new SettingsProvider(MenuPath, SettingsScope.Project) + return new SettingsProvider("Project/Project Validator", SettingsScope.Project) { label = "Project Validator", activateHandler = (_, root) => @@ -46,79 +37,16 @@ namespace Module.ProjectValidator.Editor var settings = GetOrCreate(); var serializedObject = new SerializedObject(settings); var container = new VisualElement { style = { flexDirection = FlexDirection.Column } }; - - var assemblyField = new PropertyField(serializedObject.FindProperty(nameof(assemblies)), "Assemblies"); - container.Add(assemblyField); - - var enabledField = new PropertyField(serializedObject.FindProperty(nameof(validators)), "Validators"); - container.Add(enabledField); - + var propertyField = new PropertyField(serializedObject.FindProperty("assemblies"), "Assemblies"); + propertyField.RegisterCallback>(_ => InternalEditorUtility.SaveToSerializedFileAndForget(new[] { serializedObject.targetObject }, AssetPath, true)); + propertyField.RegisterValueChangeCallback(_ => InternalEditorUtility.SaveToSerializedFileAndForget(new[] { serializedObject.targetObject }, AssetPath, true)); + container.Add(propertyField); root.Add(container); root.Bind(serializedObject); - root.RegisterCallback(_ => InternalEditorUtility.SaveToSerializedFileAndForget(new[] { serializedObject.targetObject }, AssetPath, true)); - root.RegisterCallback(_ => InternalEditorUtility.SaveToSerializedFileAndForget(new[] { serializedObject.targetObject }, AssetPath, true)); root.styleSheets.Add(EditorAssetUtility.LoadFirstAsset(StyleSheetName)); }, keywords = new HashSet(new[] { "Project", "Validator", "Assemblies" }) }; } - - private static void PopulateValidatorList(ProjectValidatorSettings settings) - { - using var pool0 = ListPool.Get(out var list); - using var pool1 = ListPool.Get(out var temp); - - FetchValidatorsOfType(typeof(IAssetValidator<>), list); - FetchValidatorsOfType(typeof(IAttributeValidator<>), list); - FetchValidatorsOfType(typeof(IComponentValidator<>), list); - FetchValidatorsOfType(typeof(IGameObjectValidator), list); - - for (var i = 0; i < settings.validators.Count; i++) - { - temp.Add(settings.validators[i].assemblyQualifiedName); - } - - for (var i = 0; i < list.Count; i++) - { - if (temp.Contains(list[i])) - continue; - - var type = Type.GetType(list[i]); - var name = type != null ? type.Name : "Unknown Type"; - settings.validators.Add(new ValidatorEnabled(name, list[i], true)); - } - - for (var i = temp.Count - 1; i >= 0; i--) - { - if (!list.Contains(temp[i])) - settings.validators.RemoveAt(i); - } - } - - private static void FetchValidatorsOfType(Type type, List typeNames) - { - var types = TypeCache.GetTypesDerivedFrom(type); - - for (var i = 0; i < types.Count; i++) - { - if (!types[i].IsInterface && !types[i].IsAbstract) - typeNames.Add(types[i].AssemblyQualifiedName); - } - } - - [Serializable] - public sealed class ValidatorEnabled - { - public string name; - public string assemblyQualifiedName; - public bool enabled; - - public ValidatorEnabled(string name, string assemblyQualifiedName, bool enabled) - { - this.name = name; - this.assemblyQualifiedName = assemblyQualifiedName; - this.enabled = enabled; - } - } } } \ No newline at end of file diff --git a/Editor/Utilities/EditorAssetUtility.cs b/Editor/Utilities/EditorAssetUtility.cs index e3c0ea4..fc956b4 100644 --- a/Editor/Utilities/EditorAssetUtility.cs +++ b/Editor/Utilities/EditorAssetUtility.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; -using Object = UnityEngine.Object; namespace Module.ProjectValidator.Editor { @@ -31,39 +29,22 @@ namespace Module.ProjectValidator.Editor return list.ToArray(); } - public static Object[] LoadAllAssets(Type type) - { - var guids = AssetDatabase.FindAssetGUIDs($"a:assets t:{type.Name}"); - var list = new List(guids.Length); - - foreach (var guid in guids) - { - var asset = AssetDatabase.LoadAssetByGUID(guid, type); - - if (asset != null) - list.Add(asset); - } - - return list.ToArray(); - } - internal static GUID GetAssetGuid(Object obj) { - var assetPath = string.Empty; - + var assetGuid = new GUID(); + if (obj is GameObject gameObject) { if (gameObject.scene.isLoaded) - assetPath = gameObject.scene.path; + GUID.TryParse(AssetDatabase.AssetPathToGUID(gameObject.scene.path), out assetGuid); else if (PrefabUtility.IsPartOfPrefabAsset(gameObject)) - assetPath = AssetDatabase.GetAssetPath(gameObject); + GUID.TryParse(AssetDatabase.AssetPathToGUID(gameObject.scene.path), out assetGuid); } else { - assetPath = AssetDatabase.GetAssetPath(obj); + GUID.TryParse(AssetDatabase.GetAssetPath(obj), out assetGuid); } - GUID.TryParse(AssetDatabase.AssetPathToGUID(assetPath), out var assetGuid); return assetGuid; } diff --git a/Editor/Utilities/ProjectValidatorUtility.cs b/Editor/Utilities/ProjectValidatorUtility.cs index 10d6eef..c1f0c2f 100644 --- a/Editor/Utilities/ProjectValidatorUtility.cs +++ b/Editor/Utilities/ProjectValidatorUtility.cs @@ -37,30 +37,6 @@ namespace Module.ProjectValidator.Editor window.titleContent = new GUIContent("Project Validator"); return window; } - - public static string GetAssetValidatorName(object validator) - { - var str = validator.GetType().Name; - str = str.Replace("AssetValidator", string.Empty); - str = ObjectNames.NicifyVariableName(str); - return str; - } - - internal static string GetGameObjectValidatorName(IGameObjectValidator validator) - { - var str = validator.GetType().Name; - str = str.Replace("GameObjectValidator", string.Empty); - str = ObjectNames.NicifyVariableName(str); - return str; - } - - internal static string GetComponentValidatorShortName(object obj) - { - var str = obj.GetType().Name; - str = str.Replace("ComponentValidator", string.Empty); - str = ObjectNames.NicifyVariableName(str); - return str; - } internal static string GetAttributeShortName(Attribute attribute) { @@ -69,18 +45,23 @@ namespace Module.ProjectValidator.Editor str = ObjectNames.NicifyVariableName(str); return str; } - - internal static void AppendToRelativePath(GameObject gameObject, ref string relativePath, bool initial) + + internal static string GetComponentValidatorShortName(object obj) { - if (string.IsNullOrEmpty(relativePath)) - relativePath = gameObject.name; - else - relativePath = initial ? $"{relativePath}{gameObject.name}" : $"{relativePath}/{gameObject.name}"; + var str = obj.GetType().Name; + str = str.Replace("ComponentValidator", string.Empty); + str = ObjectNames.NicifyVariableName(str); + return str; + } + + internal static void AppendToScenePath(GameObject gameObject, ref string scenePath) + { + scenePath = string.IsNullOrEmpty(scenePath) ? gameObject.name : $"{scenePath}/{gameObject.name}"; } - internal static string ApplyRichTextToRelativePath(string relativePath) + internal static string ApplyRichTextToScenePath(string scenePath) { - return relativePath.Replace("/", "/"); + return scenePath.Replace("/", "/"); } public static void AppendToFieldPath(FieldInfo fieldInfo, ref string fieldPath) @@ -116,7 +97,7 @@ namespace Module.ProjectValidator.Editor { var scene = SceneManager.GetSceneByPath(assetPath); - if (scene.isLoaded && TryFindSceneObjectByPath(scene, entry.RelativePath, out var gameObject)) + if (scene.isLoaded && TryFindSceneObjectByPath(scene, entry.ScenePath, out var gameObject)) EditorGUIUtility.PingObject(gameObject); else EditorGUIUtility.PingObject(asset); @@ -127,14 +108,14 @@ namespace Module.ProjectValidator.Editor } } - private static bool TryFindSceneObjectByPath(Scene scene, string relativePath, out GameObject gameObject) + private static bool TryFindSceneObjectByPath(Scene scene, string scenePath, out GameObject gameObject) { using var _ = ListPool.Get(out var rootObjects); scene.GetRootGameObjects(rootObjects); - var index = relativePath.IndexOf('/'); - var rootName = index != -1 ? relativePath[..index] : relativePath; - var childPath = index != -1 ? relativePath[(index + 1)..] : string.Empty; + var index = scenePath.IndexOf('/'); + var rootName = index != -1 ? scenePath[..index] : scenePath; + var childPath = index != -1 ? scenePath[(index + 1)..] : string.Empty; for (var i = 0; i < rootObjects.Count; i++) { @@ -204,93 +185,6 @@ namespace Module.ProjectValidator.Editor } } -#if UNITY_6000_4_OR_NEWER - internal static void RebuildSceneInstanceMapping(Report report, Dictionary dictMapping) - { - dictMapping.Clear(); - using var _ = ListPool.Get(out var rootObjects); - - for (var i = 0; i < SceneManager.sceneCount; i++) - { - var scene = SceneManager.GetSceneAt(i); - - if (!scene.isLoaded) - continue; - - var strAssetGuid = AssetDatabase.AssetPathToGUID(scene.path); - GUID.TryParse(strAssetGuid, out var assetGuid); - scene.GetRootGameObjects(rootObjects); - - for (var j = 0; j < rootObjects.Count; j++) - { - var rootObject = rootObjects[j]; - var relativePath = string.Empty; - RebuildSceneInstanceMapping(report, dictMapping, rootObject, assetGuid, relativePath, true); - } - } - - RebuildForAllParents(dictMapping); - } - - - private static void RebuildSceneInstanceMapping(Report report, Dictionary dictMapping, GameObject gameObject, GUID assetGuid, string relativePath, bool initial) - { - var transform = gameObject.transform; - AppendToRelativePath(gameObject, ref relativePath, initial); - - if (report.TryGetSeverityFor(assetGuid, relativePath, out var mapping)) - dictMapping.Add(gameObject.GetEntityId(), new Report.MappingEntry(mapping.Severity, false)); - - for (var i = 0; i < transform.childCount; i++) - { - RebuildSceneInstanceMapping(report, dictMapping, transform.GetChild(i).gameObject, assetGuid, relativePath, false); - } - } - - private static void RebuildForAllParents(Dictionary dictMapping) - { - using var _ = DictionaryPool.Get(out var newMappings); - - foreach (var pair in dictMapping) - { - var obj = EditorUtility.EntityIdToObject(pair.Key); - - if (obj is not GameObject gameObject) - continue; - - var severity = pair.Value.Severity; - var transform = gameObject.transform.parent; - - while (transform != null) - { - gameObject = transform.gameObject; - var entityId = gameObject.GetEntityId(); - - if (dictMapping.TryGetValue(entityId, out var parentMapping)) - { - if (severity < parentMapping.Severity) - severity = parentMapping.Severity; - } - else if (newMappings.TryGetValue(entityId, out var currentMapping)) - { - if (currentMapping.Severity < severity) - newMappings[entityId] = new Report.MappingEntry(severity, true); - } - else - { - newMappings.Add(entityId, new Report.MappingEntry(severity, true)); - } - - transform = transform.parent; - } - } - - foreach (var pair in newMappings) - { - dictMapping.Add(pair.Key, pair.Value); - } - } -#else internal static void RebuildSceneInstanceMapping(Report report, Dictionary dictMapping) { dictMapping.Clear(); @@ -310,26 +204,25 @@ namespace Module.ProjectValidator.Editor for (var j = 0; j < rootObjects.Count; j++) { var rootObject = rootObjects[j]; - var relativePath = string.Empty; - RebuildSceneInstanceMapping(report, dictMapping, rootObject, assetGuid, relativePath, true); + var scenePath = string.Empty; + RebuildSceneInstanceMapping(report, dictMapping, rootObject, assetGuid, scenePath); } } RebuildForAllParents(dictMapping); } - - private static void RebuildSceneInstanceMapping(Report report, Dictionary dictMapping, GameObject gameObject, GUID assetGuid, string relativePath, bool initial) + private static void RebuildSceneInstanceMapping(Report report, Dictionary dictMapping, GameObject gameObject, GUID assetGuid, string scenePath) { var transform = gameObject.transform; - AppendToRelativePath(gameObject, ref relativePath, initial); + AppendToScenePath(gameObject, ref scenePath); - if (report.TryGetSeverityFor(assetGuid, relativePath, out var mapping)) + if (report.TryGetSeverityFor(assetGuid, scenePath, out var mapping)) dictMapping.Add(gameObject.GetInstanceID(), new Report.MappingEntry(mapping.Severity, false)); for (var i = 0; i < transform.childCount; i++) { - RebuildSceneInstanceMapping(report, dictMapping, transform.GetChild(i).gameObject, assetGuid, relativePath, false); + RebuildSceneInstanceMapping(report, dictMapping, transform.GetChild(i).gameObject, assetGuid, scenePath); } } @@ -376,7 +269,6 @@ namespace Module.ProjectValidator.Editor dictMapping.Add(pair.Key, pair.Value); } } -#endif internal static void RefreshUnityWindows() { diff --git a/Editor/ValidatorRunner.cs b/Editor/ValidatorRunner.cs index b69797a..af9cdd4 100644 --- a/Editor/ValidatorRunner.cs +++ b/Editor/ValidatorRunner.cs @@ -13,6 +13,7 @@ namespace Module.ProjectValidator.Editor { internal static class ValidatorRunner { + private static bool _initialized; private static ValidatorList _validatorList; private static TypeTree _typeTree; @@ -29,7 +30,6 @@ namespace Module.ProjectValidator.Editor var report = new Report(); ValidateAllScenes(report); ValidateAllAssets(report); - ValidateAllPrefabs(report); report.RebuildAssetMapping(); report.RebuildInstanceMapping(); report.SetAsActive(); @@ -40,7 +40,7 @@ namespace Module.ProjectValidator.Editor ProjectValidatorUtility.OpenWindow(); stopwatch.Stop(); - Debug.Log($"Validator took {stopwatch.Elapsed.TotalMilliseconds}ms"); + Debug.Log(stopwatch.Elapsed.TotalMilliseconds + "ms"); return true; } @@ -55,19 +55,20 @@ namespace Module.ProjectValidator.Editor private static void Initialize() { + if (_initialized) + return; + var settings = ProjectValidatorSettings.GetOrCreate(); var assemblies = GetAssembliesFrom(settings); - var enabled = GetEnabledValidators(settings); - + _validatorList = new ValidatorList(); _typeTree = new TypeTree(); - - FetchAllGameObjectValidators(enabled); - FetchAllComponentValidators(enabled); - FetchAllAttributeValidators(enabled); - FetchAllAssetValidators(enabled); + + FetchAllAttributeValidators(); + FetchAllComponentValidators(); FetchAllTypesWithValidators(assemblies); FetchAllTypesWithValidators(assemblies); + _initialized = true; } private static Assembly[] GetAssembliesFrom(ProjectValidatorSettings settings) @@ -90,72 +91,23 @@ namespace Module.ProjectValidator.Editor return assemblies.ToArray(); } - private static HashSet GetEnabledValidators(ProjectValidatorSettings settings) - { - var enabled = new HashSet(settings.validators.Count); - - for (var i = 0; i < settings.validators.Count; i++) - { - try - { - if (!settings.validators[i].enabled) - continue; - - var type = Type.GetType(settings.validators[i].assemblyQualifiedName); - - if (type != null) - enabled.Add(type); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - - return enabled; - } - - private static void FetchAllAttributeValidators(HashSet enabled) + private static void FetchAllAttributeValidators() { var types = TypeCache.GetTypesDerivedFrom(typeof(IAttributeValidator<>)); for (var i = 0; i < types.Count; i++) { - if (enabled.Contains(types[i])) - _validatorList.AddAttribute(types[i]); - } - } - - private static void FetchAllGameObjectValidators(HashSet enabled) - { - var types = TypeCache.GetTypesDerivedFrom(typeof(IGameObjectValidator)); - - for (var i = 0; i < types.Count; i++) - { - if (enabled.Contains(types[i])) - _validatorList.AddGameObject(types[i]); + _validatorList.AddAttribute(types[i]); } } - private static void FetchAllComponentValidators(HashSet enabled) + private static void FetchAllComponentValidators() { var types = TypeCache.GetTypesDerivedFrom(typeof(IComponentValidator<>)); for (var i = 0; i < types.Count; i++) { - if (enabled.Contains(types[i])) - _validatorList.AddComponent(types[i]); - } - } - - private static void FetchAllAssetValidators(HashSet enabled) - { - var types = TypeCache.GetTypesDerivedFrom(typeof(IAssetValidator<>)); - - for (var i = 0; i < types.Count; i++) - { - if (enabled.Contains(types[i])) - _validatorList.AddAsset(types[i]); + _validatorList.AddComponent(types[i]); } } @@ -179,12 +131,12 @@ namespace Module.ProjectValidator.Editor for (var i = 0; i < assets.Length; i++) { - var assetPath = AssetDatabase.GetAssetPath(assets[i]); - var scene = SceneManager.GetSceneByPath(assetPath); - var isLoaded = scene.isLoaded; - try { + var assetPath = AssetDatabase.GetAssetPath(assets[i]); + var scene = SceneManager.GetSceneByPath(assetPath); + var isLoaded = scene.isLoaded; + if (!isLoaded) scene = EditorSceneManager.OpenScene(assetPath, OpenSceneMode.Additive); @@ -192,60 +144,22 @@ namespace Module.ProjectValidator.Editor for (var j = 0; j < rootObjects.Count; j++) { - ValidateGameObject(rootObjects[j], string.Empty, report, true); + ValidateGameObject(rootObjects[j], string.Empty, report); } + + if (!isLoaded) + EditorSceneManager.CloseScene(scene, true); } catch (Exception e) { Debug.LogException(e); } - finally - { - if (!isLoaded && scene.isLoaded) - EditorSceneManager.CloseScene(scene, true); - } } } private static void ValidateAllAssets(Report report) { ValidateAssetsBytype(report); - - foreach (var pair in _validatorList.AssetValidators) - { - var assets = EditorAssetUtility.LoadAllAssets(pair.Key); - - for (var i = 0; i < assets.Length; i++) - { - try - { - var assetPath = AssetDatabase.GetAssetPath(assets[i]); - var assetGuid = AssetDatabase.GUIDFromAssetPath(assetPath); - ValidateAsset(assets[i], assetGuid, assetPath, pair.Value, report); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - } - } - - private static void ValidateAllPrefabs(Report report) - { - var assets = EditorAssetUtility.LoadAllAssets(); - - for (var i = 0; i < assets.Length; i++) - { - try - { - ValidateGameObject(assets[i], string.Empty, report, true); - } - catch (Exception e) - { - Debug.LogException(e); - } - } } private static void ValidateAssetsBytype(Report report) where T : UnityEngine.Object @@ -268,83 +182,39 @@ namespace Module.ProjectValidator.Editor private static void ValidateUnityObject(UnityEngine.Object obj, Report report) { var assetGuid = EditorAssetUtility.ObjectToAssetGuid(obj); - var assetPath = AssetDatabase.GUIDToAssetPath(assetGuid); - Validate(assetGuid, assetPath, obj, report); + Validate(assetGuid, string.Empty, obj, report); } - private static void ValidateGameObject(GameObject gameObject, string relativePath, Report report, bool initial) + private static void ValidateGameObject(GameObject gameObject, string scenePath, Report report) { - ProjectValidatorUtility.AppendToRelativePath(gameObject, ref relativePath, initial); - - var assetGuid = EditorAssetUtility.GetAssetGuid(gameObject); - using var _ = ListPool.Get(out var results); - - for (var i = 0; i < _validatorList.GameObjectValidators.Count; i++) - { - results.Clear(); - - _validatorList.GameObjectValidators[i].Validate(gameObject, results); - var type = ProjectValidatorUtility.GetGameObjectValidatorName(_validatorList.GameObjectValidators[i]); - - for (var j = 0; j < results.Count; j++) - { - var result = results[j]; - - if (result.Severity != EValidatorSeverity.Valid) - report.Add(assetGuid, relativePath, string.Empty, type, result.Severity, result.Message); - } - } - - ValidateComponents(gameObject, assetGuid, relativePath, report); - ValidateChildren(gameObject, relativePath, report); + ProjectValidatorUtility.AppendToScenePath(gameObject, ref scenePath); + ValidateComponents(gameObject, scenePath, report); + ValidateChildren(gameObject, scenePath, report); } - private static void ValidateComponents(GameObject gameObject, GUID assetGuid, string relativePath, Report report) + private static void ValidateComponents(GameObject gameObject, string scenePath, Report report) { using var _ = ListPool.Get(out var components); + var assetGuid = EditorAssetUtility.GetAssetGuid(gameObject); gameObject.GetComponents(components); for (var i = 0; i < components.Count; i++) { - if (components[i] != null) - Validate(assetGuid, relativePath, components[i], report); - } - } - - private static void ValidateAsset(UnityEngine.Object obj, GUID assetGuid, string relativePath, List validators, Report report) - { - using var _ = ListPool.Get(out var results); - - for (var i = 0; i < validators.Count; i++) - { - results.Clear(); - var validator = validators[i]; - validator.ValidatorMethod.Invoke(validator.Validator, new object[] { obj, results }); - - for (var j = 0; j < results.Count; j++) - { - var result = results[j]; - - if (result.Severity == EValidatorSeverity.Valid) - continue; - - var validatorName = ProjectValidatorUtility.GetAssetValidatorName(validator.Validator); - report.Add(assetGuid, relativePath, string.Empty, validatorName, result.Severity, result.Message); - } + Validate(assetGuid, scenePath, components[i], report); } } - private static void ValidateChildren(GameObject gameObject, string relativePath, Report report) + private static void ValidateChildren(GameObject gameObject, string scenePath, Report report) { var transform = gameObject.transform; for (var i = 0; i < transform.childCount; i++) { - ValidateGameObject(transform.GetChild(i).gameObject, relativePath, report, false); + ValidateGameObject(transform.GetChild(i).gameObject, scenePath, report); } } - private static void Validate(GUID assetGuid, string relativePath, object obj, Report report) + private static void Validate(GUID assetGuid, string scenePath, object obj, Report report) { var type = obj.GetType(); @@ -352,10 +222,10 @@ namespace Module.ProjectValidator.Editor return; var fieldPath = obj.GetType().Name; - Validate(assetGuid, relativePath, fieldPath, obj, entry, report); + Validate(assetGuid, scenePath, fieldPath, obj, entry, report); } - private static void Validate(GUID assetGuid, string relativePath, string parentFieldPath, object obj, TypeTree.Entry entry, Report report) + private static void Validate(GUID assetGuid, string scenePath, string parentFieldPath, object obj, TypeTree.Entry entry, Report report) { if (obj == null) return; @@ -367,7 +237,7 @@ namespace Module.ProjectValidator.Editor try { var component = entry.Components[i]; - ValidateComponent(component, obj, assetGuid, relativePath, report); + ValidateComponent(component, obj, assetGuid, scenePath, report); } catch (Exception e) { @@ -396,13 +266,13 @@ namespace Module.ProjectValidator.Editor { var fieldPathArrElement = fieldPath; ProjectValidatorUtility.AppendToFieldPath(idx, ref fieldPathArrElement); - ValidateField(field, eObj, assetGuid, relativePath, fieldPathArrElement, report); + ValidateField(field, eObj, assetGuid, scenePath, fieldPathArrElement, report); idx++; } } else { - ValidateField(field, value, assetGuid, relativePath, fieldPath, report); + ValidateField(field, value, assetGuid, scenePath, fieldPath, report); } } catch (Exception e) @@ -423,18 +293,8 @@ namespace Module.ProjectValidator.Editor var fieldPath = parentFieldPath; ProjectValidatorUtility.AppendToFieldPath(e.FieldInfo, ref fieldPath); - - if (value is Array arr) - { - for (var j = 0; j < arr.Length; j++) - { - var eObj = arr.GetValue(j); - var fieldPathArrElement = fieldPath; - ProjectValidatorUtility.AppendToFieldPath(j, ref fieldPathArrElement); - Validate(assetGuid, relativePath, fieldPathArrElement, eObj, e.Entry, report); - } - } - else if (value is IEnumerable ie) + + if (value is IEnumerable ie) { var idx = 0; @@ -442,13 +302,13 @@ namespace Module.ProjectValidator.Editor { var fieldPathArrElement = fieldPath; ProjectValidatorUtility.AppendToFieldPath(idx, ref fieldPathArrElement); - Validate(assetGuid, relativePath, fieldPathArrElement, eObj, e.Entry, report); + Validate(assetGuid, scenePath, fieldPathArrElement, eObj, e.Entry, report); idx++; } } else { - Validate(assetGuid, relativePath, fieldPath, value, e.Entry, report); + Validate(assetGuid, scenePath, fieldPath, value, e.Entry, report); } } catch (Exception e) @@ -459,15 +319,15 @@ namespace Module.ProjectValidator.Editor } } - private static void ValidateField(TypeTree.ValidatorField field, object value, GUID assetGuid, string relativePath, string fieldPath, Report report) + private static void ValidateField(TypeTree.ValidatorField field, object value, GUID assetGuid, string scenePath, string fieldPath, Report report) { var result = (ValidatorResult)field.ValidatorMethod.Invoke(field.Validator, new[] { field.Attribute, value }); if (result.Severity != EValidatorSeverity.Valid) - report.Add(assetGuid, relativePath, fieldPath, field.Attribute, result.Severity, result.Message); + report.Add(assetGuid, scenePath, fieldPath, field.Attribute, result.Severity, result.Message); } - private static void ValidateComponent(TypeTree.ValidatorComponent component, object value, GUID assetGuid, string relativePath, Report report) + private static void ValidateComponent(TypeTree.ValidatorComponent component, object value, GUID assetGuid, string scenePath, Report report) { using var _ = ListPool.Get(out var results); component.ValidatorMethod.Invoke(component.Validator, new[] { value, results }); @@ -478,7 +338,7 @@ namespace Module.ProjectValidator.Editor var result = results[i]; if (result.Severity != EValidatorSeverity.Valid) - report.Add(assetGuid, relativePath, string.Empty, type, result.Severity, result.Message); + report.Add(assetGuid, scenePath, string.Empty, type, result.Severity, result.Message); } } } diff --git a/Editor/Validators/Assets.meta b/Editor/Validators/Assets.meta deleted file mode 100644 index a1c08b2..0000000 --- a/Editor/Validators/Assets.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: ddbf30cd5a674751be0c125c1f4e917b -timeCreated: 1779623970 \ No newline at end of file diff --git a/Editor/Validators/Assets/AssetValidatorMaterialShader.cs b/Editor/Validators/Assets/AssetValidatorMaterialShader.cs deleted file mode 100644 index f6e072f..0000000 --- a/Editor/Validators/Assets/AssetValidatorMaterialShader.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using UnityEngine.Rendering; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class AssetValidatorMaterialShader : IAssetValidator - { - public void Validate(Material obj, List results) - { - if (obj.shader == null) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, "Shader is Null")); - else if (!IsCompatible(obj.shader)) - results.Add(ValidatorResult.Create(EValidatorSeverity.Warning, $"Shader '{obj.shader.name}' is not compatible with render pipeline")); - else if (!obj.shader.isSupported) - results.Add(ValidatorResult.Create(EValidatorSeverity.Warning, $"Shader '{obj.shader.name}' is not supported")); - else if (ShaderUtil.ShaderHasError(obj.shader)) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, $"Shader '{obj.shader.name}' has compile errors")); - } - - private static bool IsCompatible(Shader shader) - { - var pipeline = GraphicsSettings.currentRenderPipeline; - - if (pipeline == null) - return true; - - var tagSearch = new ShaderTagId("RenderPipeline"); - var tagPipeline = new ShaderTagId(pipeline.renderPipelineShaderTag); - var hasKeyword = false; - - for (var i = 0; i < shader.passCount; i++) - { - var tagPass = shader.FindPassTagValue(i, tagSearch); - - if (tagPass != ShaderTagId.none) - hasKeyword = true; - - if (tagPass == tagPipeline) - return true; - } - - return !hasKeyword; - } - } -} \ No newline at end of file diff --git a/Editor/Validators/Assets/AssetValidatorMaterialShader.cs.meta b/Editor/Validators/Assets/AssetValidatorMaterialShader.cs.meta deleted file mode 100644 index a1eceb1..0000000 --- a/Editor/Validators/Assets/AssetValidatorMaterialShader.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 2218d247daff44bf84629756b63ea650 -timeCreated: 1779623986 \ No newline at end of file diff --git a/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs b/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs deleted file mode 100644 index 37097fa..0000000 --- a/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Rendering; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class AssetValidatorMaterialTexture : IAssetValidator - { - public void Validate(Material obj, List results) - { - if (obj.shader == null) - return; - - var count = obj.shader.GetPropertyCount(); - - for (var i = 0; i < count; i++) - { - var propertyType = obj.shader.GetPropertyType(i); - var propertyFlags = obj.shader.GetPropertyFlags(i); - - if (propertyType != ShaderPropertyType.Texture) - continue; - if ((propertyFlags & (ShaderPropertyFlags.PerRendererData | ShaderPropertyFlags.HideInInspector | ShaderPropertyFlags.NonModifiableTextureData)) != 0) - continue; - - var propertyName = obj.shader.GetPropertyName(i); - var propertyValue = obj.GetTexture(propertyName); - - if (propertyValue == null) - results.Add(ValidatorResult.Create(EValidatorSeverity.Warning, $"Texture property '{propertyName}' is Null")); - } - } - } -} \ No newline at end of file diff --git a/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs.meta b/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs.meta deleted file mode 100644 index d975053..0000000 --- a/Editor/Validators/Assets/AssetValidatorMaterialTexture.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: cfeb4b29a9cd4ea79c1e9325b8122e17 -timeCreated: 1779627240 \ No newline at end of file diff --git a/Editor/Validators/Attributes.meta b/Editor/Validators/Attributes.meta deleted file mode 100644 index 7b92af6..0000000 --- a/Editor/Validators/Attributes.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 0aa1d741049f4074bb863b76ed604d07 -timeCreated: 1779214748 \ No newline at end of file diff --git a/Editor/Validators/Attributes/AttributeValidatorMin.cs b/Editor/Validators/Attributes/AttributeValidatorMin.cs deleted file mode 100644 index 59b7c1e..0000000 --- a/Editor/Validators/Attributes/AttributeValidatorMin.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UnityEngine; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class AttributeValidatorMin : IAttributeValidator - { - public ValidatorResult Validate(MinAttribute attribute, object value) - { - if (value is int iValue) - { - if (iValue < attribute.min) - return ValidatorResult.Create(EValidatorSeverity.Error, $"Value {iValue} is less than minimum value of {attribute.min}"); - } - else if (value is float fValue) - { - if (fValue < attribute.min) - return ValidatorResult.Create(EValidatorSeverity.Error, $"Value {fValue} is less than minimum value of {attribute.min}"); - } - - return ValidatorResult.Valid; - } - } -} \ No newline at end of file diff --git a/Editor/Validators/Attributes/AttributeValidatorMin.cs.meta b/Editor/Validators/Attributes/AttributeValidatorMin.cs.meta deleted file mode 100644 index 7b95df1..0000000 --- a/Editor/Validators/Attributes/AttributeValidatorMin.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 2015106b3c9b450e9efb1333e5239033 -timeCreated: 1779214761 \ No newline at end of file diff --git a/Editor/Validators/Attributes/AttributeValidatorObsolete.cs b/Editor/Validators/Attributes/AttributeValidatorObsolete.cs deleted file mode 100644 index 0eb3c19..0000000 --- a/Editor/Validators/Attributes/AttributeValidatorObsolete.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class AttributeValidatorObsolete : IAttributeValidator - { - public ValidatorResult Validate(ObsoleteAttribute attribute, object value) - { - return ValidatorResult.Create(EValidatorSeverity.Error, "Obsolete"); - } - } -} \ No newline at end of file diff --git a/Editor/Validators/Attributes/AttributeValidatorObsolete.cs.meta b/Editor/Validators/Attributes/AttributeValidatorObsolete.cs.meta deleted file mode 100644 index 2a54b7b..0000000 --- a/Editor/Validators/Attributes/AttributeValidatorObsolete.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 982ac4e898cc2ca438e98a2f0034a8d3 \ No newline at end of file diff --git a/Editor/Validators/Attributes/AttributeValidatorRange.cs b/Editor/Validators/Attributes/AttributeValidatorRange.cs deleted file mode 100644 index b52c1f9..0000000 --- a/Editor/Validators/Attributes/AttributeValidatorRange.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UnityEngine; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class AttributeValidatorRange : IAttributeValidator - { - public ValidatorResult Validate(RangeAttribute attribute, object value) - { - if (value is int iValue) - { - if (iValue < attribute.min || iValue > attribute.max) - return ValidatorResult.Create(EValidatorSeverity.Error, $"Value {iValue} is not in the range [{attribute.min};{attribute.max}]"); - } - else if (value is float fValue) - { - if (fValue < attribute.min || fValue > attribute.max) - return ValidatorResult.Create(EValidatorSeverity.Error, $"Value {fValue} is not in the range [{attribute.min};{attribute.max}]"); - } - - return ValidatorResult.Valid; - } - } -} \ No newline at end of file diff --git a/Editor/Validators/Attributes/AttributeValidatorRange.cs.meta b/Editor/Validators/Attributes/AttributeValidatorRange.cs.meta deleted file mode 100644 index 531db6b..0000000 --- a/Editor/Validators/Attributes/AttributeValidatorRange.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 3115c26bccfe4b1e964f784a3f9fdd55 -timeCreated: 1779214908 \ No newline at end of file diff --git a/Editor/Validators/Component/ComponentValidatorSkinnedMeshRenderer.cs b/Editor/Validators/Component/ComponentValidatorSkinnedMeshRenderer.cs deleted file mode 100644 index ca2d231..0000000 --- a/Editor/Validators/Component/ComponentValidatorSkinnedMeshRenderer.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class ComponentValidatorSkinnedMeshRenderer : IComponentValidator - { - public void Validate(SkinnedMeshRenderer component, List results) - { - var materials = component.sharedMaterials; - - for (var i = 0; i < materials.Length; i++) - { - if (materials[i] == null) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, $"Missing material in slot #{i}")); - } - - if (component.sharedMesh == null) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, "Missing mesh")); - } - } -} diff --git a/Editor/Validators/Component/ComponentValidatorSkinnedMeshRenderer.cs.meta b/Editor/Validators/Component/ComponentValidatorSkinnedMeshRenderer.cs.meta deleted file mode 100644 index 1080734..0000000 --- a/Editor/Validators/Component/ComponentValidatorSkinnedMeshRenderer.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 1610561c53a0aa84aaa903e5dde29694 diff --git a/Editor/Validators/GameObject.meta b/Editor/Validators/GameObject.meta deleted file mode 100644 index 736bf79..0000000 --- a/Editor/Validators/GameObject.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 45fa253dcfa349d5b1e9bd56ebac7c98 -timeCreated: 1779133809 \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorBrokenPrefab.cs b/Editor/Validators/GameObject/GameObjectValidatorBrokenPrefab.cs deleted file mode 100644 index 8cd9270..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorBrokenPrefab.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class GameObjectValidatorBrokenPrefab : IGameObjectValidator - { - public void Validate(GameObject gameObject, List results) - { - if (PrefabUtility.IsPrefabAssetMissing(gameObject)) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, "GameObject is missing prefab asset")); - } - } -} \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorBrokenPrefab.cs.meta b/Editor/Validators/GameObject/GameObjectValidatorBrokenPrefab.cs.meta deleted file mode 100644 index d2ad050..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorBrokenPrefab.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 8fd1dfcd3d564622a918e2175499318d -timeCreated: 1779133864 \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs b/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs deleted file mode 100644 index eaf89a1..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; -using UnityEngine.Pool; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class GameObjectValidatorDuplicateComponents : IGameObjectValidator - { - public void Validate(GameObject gameObject, List results) - { - using var _ = ListPool.Get(out var list); - gameObject.GetComponents(list); - list.Sort((c0, c1) => c0.GetType().GetHashCode().CompareTo(c1.GetType().GetHashCode())); - - if (list.Count == 0) - return; - - var type = list[0].GetType(); - var count = 1; - - for (var i = 1; i < list.Count; i++) - { - var t = list[i].GetType(); - - if (type == t) - { - count++; - } - else - { - if (count > 1 && IsMultipleComponentsAllowed(type)) - results.Add(ValidatorResult.Create(EValidatorSeverity.Warning, $"GameObject has duplicate '{type.Name}' ({count}) components")); - - type = t; - count = 1; - } - } - - if (count > 1 && IsMultipleComponentsAllowed(type)) - results.Add(ValidatorResult.Create(EValidatorSeverity.Warning, $"GameObject has duplicate '{type.Name}' ({count}) components")); - } - - private static bool IsMultipleComponentsAllowed(Type type) - { - return type.GetCustomAttribute(true) == null; - } - } -} \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs.meta b/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs.meta deleted file mode 100644 index 9947888..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorDuplicateComponents.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b27a4e96523d4d3d97c11b32814f29d3 -timeCreated: 1779213834 \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorMissingComponents.cs b/Editor/Validators/GameObject/GameObjectValidatorMissingComponents.cs deleted file mode 100644 index dd43633..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorMissingComponents.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class GameObjectValidatorMissingComponents : IGameObjectValidator - { - public void Validate(GameObject gameObject, List results) - { - var count = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(gameObject); - - if (count != 0) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, $"GameObject is missing {count} component(s)")); - } - } -} \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorMissingComponents.cs.meta b/Editor/Validators/GameObject/GameObjectValidatorMissingComponents.cs.meta deleted file mode 100644 index 47d826d..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorMissingComponents.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 66cbc43729ec4e81a9e353e537b3ccf0 -timeCreated: 1779133947 \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorObsoleteComponents.cs b/Editor/Validators/GameObject/GameObjectValidatorObsoleteComponents.cs deleted file mode 100644 index d6be9b0..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorObsoleteComponents.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; -using UnityEngine.Pool; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class GameObjectValidatorObsoleteComponents : IGameObjectValidator - { - public void Validate(GameObject gameObject, List results) - { - using var _ = ListPool.Get(out var list); - gameObject.GetComponents(list); - - for (var i = 0; i < list.Count; i++) - { - var type = list[i].GetType(); - - if (type.GetCustomAttribute(typeof(ObsoleteAttribute)) != null) - results.Add(ValidatorResult.Create(EValidatorSeverity.Warning, $"GameObject has obsolete '{type.Name}' component")); - } - } - } -} \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorObsoleteComponents.cs.meta b/Editor/Validators/GameObject/GameObjectValidatorObsoleteComponents.cs.meta deleted file mode 100644 index 9a9d755..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorObsoleteComponents.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: ca678bbf72fa4c8f8c9b945535aacf44 -timeCreated: 1779214145 \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorTransform.cs b/Editor/Validators/GameObject/GameObjectValidatorTransform.cs deleted file mode 100644 index 58b6f92..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorTransform.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; - -namespace Module.ProjectValidator.Editor -{ - internal sealed class GameObjectValidatorTransform : IGameObjectValidator - { - public void Validate(GameObject gameObject, List results) - { - var transform = gameObject.transform; - var lp = transform.localPosition; - var lr = transform.localRotation; - var ls = transform.localScale; - - if (IsInvalid(lp.x) || IsInvalid(lp.y) || IsInvalid(lp.z)) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, $"Local position '{lp}' is invalid")); - if (IsInvalid(lr.x) || IsInvalid(lr.y) || IsInvalid(lr.z) || IsInvalid(lr.w)) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, $"Local rotation '{lr}' is invalid")); - if (IsInvalid(ls.x) || IsInvalid(ls.y) || IsInvalid(ls.z)) - results.Add(ValidatorResult.Create(EValidatorSeverity.Error, $"Local scale '{ls}' is invalid")); - } - - private static bool IsInvalid(float value) - { - return float.IsNaN(value) || float.IsInfinity(value); - } - } -} \ No newline at end of file diff --git a/Editor/Validators/GameObject/GameObjectValidatorTransform.cs.meta b/Editor/Validators/GameObject/GameObjectValidatorTransform.cs.meta deleted file mode 100644 index 89d7bda..0000000 --- a/Editor/Validators/GameObject/GameObjectValidatorTransform.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 727d5de59b004deb8c192337bcee132e -timeCreated: 1779628852 \ No newline at end of file diff --git a/Editor/Window/EditorProjectValidatorWindow.cs b/Editor/Window/EditorProjectValidatorWindow.cs index 1d01017..1a1451c 100644 --- a/Editor/Window/EditorProjectValidatorWindow.cs +++ b/Editor/Window/EditorProjectValidatorWindow.cs @@ -8,18 +8,12 @@ namespace Module.ProjectValidator.Editor { internal sealed class EditorProjectValidatorWindow : EditorWindow { - private VisualElement _groupWarnings; - private Label _labelWarnings; - - private VisualElement _groupErrors; - private Label _labelErrors; - private MultiColumnTreeView _treeView; private string _searchFilter; - + private readonly List> _list = new(); private readonly List> _filteredList = new(); - + public void CreateGUI() { var root = rootVisualElement; @@ -27,33 +21,23 @@ namespace Module.ProjectValidator.Editor root.styleSheets.Add(EditorAssetUtility.LoadFirstAsset("StyleSheetEditorProjectValidatorWindow")); root.Add(asset.Instantiate()); - _groupWarnings = root.Q("status-warnings"); - _labelWarnings = _groupWarnings.Q