Validator: Skipping textures in material, if marked as PerRendererData, HideInInspector or NonModifiableTextureData Validator: Fixed issue, where arrays weren't iterated correctly, which resulted in an exception Window: Added warning and error count
286 lines
No EOL
11 KiB
C#
286 lines
No EOL
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEditor.UIElements;
|
|
using UnityEngine.UIElements;
|
|
|
|
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<TreeViewItemData<Report.Entry>> _list = new();
|
|
private readonly List<TreeViewItemData<Report.Entry>> _filteredList = new();
|
|
|
|
public void CreateGUI()
|
|
{
|
|
var root = rootVisualElement;
|
|
var asset = EditorAssetUtility.LoadFirstAsset<VisualTreeAsset>("UxmlEditorProjectValidatorWindow");
|
|
root.styleSheets.Add(EditorAssetUtility.LoadFirstAsset<StyleSheet>("StyleSheetEditorProjectValidatorWindow"));
|
|
root.Add(asset.Instantiate());
|
|
|
|
_groupWarnings = root.Q<VisualElement>("status-warnings");
|
|
_labelWarnings = _groupWarnings.Q<Label>("label-warnings");
|
|
|
|
_groupErrors = root.Q<VisualElement>("status-errors");
|
|
_labelErrors = _groupErrors.Q<Label>("label-errors");
|
|
|
|
_groupWarnings.style.display = DisplayStyle.None;
|
|
_groupErrors.style.display = DisplayStyle.None;
|
|
|
|
root.Q<ToolbarButton>("button-run").clicked += OnToolbarButtonRunClicked;
|
|
root.Q<ToolbarButton>("button-clear").clicked += OnToolbarButtonClearClicked;
|
|
root.Q<ToolbarSearchField>().RegisterValueChangedCallback(OnToolbarSearchFieldChanged);
|
|
root.Q<ToolbarButton>("button-settings").clicked += OnToolbarButtonSettingsClicked;
|
|
|
|
_treeView = root.Q<MultiColumnTreeView>();
|
|
_treeView.columns["asset"].makeCell = CreateObjectField;
|
|
_treeView.columns["type"].makeCell = CreateLabel;
|
|
_treeView.columns["severity"].makeCell = CreateLabel;
|
|
_treeView.columns["severity-message"].makeCell = CreateLabel;
|
|
_treeView.columns["relative-path"].makeCell = CreateLabel;
|
|
_treeView.columns["field-path"].makeCell = CreateLabel;
|
|
|
|
_treeView.columns["asset"].bindCell = OnTreeViewBindCellAsset;
|
|
_treeView.columns["type"].bindCell = OnTreeViewBindCellType;
|
|
_treeView.columns["severity"].bindCell = OnTreeViewBindCellSeverity;
|
|
_treeView.columns["severity-message"].bindCell = OnTreeViewBindCellSeverityMessage;
|
|
_treeView.columns["relative-path"].bindCell = OnTreeViewBindCellRelativePath;
|
|
_treeView.columns["field-path"].bindCell = OnTreeViewBindCellFieldPath;
|
|
|
|
_treeView.columns["severity"].unbindCell = OnTreeViewUnbindCellSeverity;
|
|
|
|
_treeView.columns["asset"].comparison = OnTreeViewComparisonCellAsset;
|
|
_treeView.columns["type"].comparison = OnTreeViewComparisonCellType;
|
|
_treeView.columns["severity"].comparison = OnTreeViewComparisonCellSeverity;
|
|
_treeView.columns["severity-message"].comparison = OnTreeViewComparisonCellSeverityMessage;
|
|
_treeView.columns["relative-path"].comparison = OnTreeViewComparisonCellRelativePath;
|
|
_treeView.columns["field-path"].comparison = OnTreeViewComparisonCellFieldPath;
|
|
|
|
_treeView.selectionChanged += OnTreeViewSelectionChanged;
|
|
Rebuild();
|
|
}
|
|
|
|
public void Rebuild()
|
|
{
|
|
if (!Report.HasActive)
|
|
return;
|
|
|
|
_list.Clear();
|
|
|
|
var entries = Report.Active.Entries;
|
|
var warningCount = 0;
|
|
var errorCount = 0;
|
|
|
|
for (var i = 0; i < entries.Count; i++)
|
|
{
|
|
_list.Add(new TreeViewItemData<Report.Entry>(i, entries[i]));
|
|
|
|
if (entries[i].Severity == EValidatorSeverity.Warning)
|
|
warningCount++;
|
|
if (entries[i].Severity == EValidatorSeverity.Error)
|
|
errorCount++;
|
|
}
|
|
|
|
_groupWarnings.style.display = warningCount > 0 ? DisplayStyle.Flex : DisplayStyle.None;
|
|
_labelWarnings.text = warningCount.ToString();
|
|
|
|
_groupErrors.style.display = errorCount > 0 ? DisplayStyle.Flex : DisplayStyle.None;
|
|
_labelErrors.text = errorCount.ToString();
|
|
|
|
Filter();
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
_list.Clear();
|
|
Filter();
|
|
}
|
|
|
|
private void Filter()
|
|
{
|
|
_treeView.Clear();
|
|
|
|
if (string.IsNullOrEmpty(_searchFilter))
|
|
{
|
|
_treeView.SetRootItems(_list);
|
|
}
|
|
else
|
|
{
|
|
_filteredList.Clear();
|
|
|
|
for (var i = 0; i < _list.Count; i++)
|
|
{
|
|
if (_list[i].data.Filter(_searchFilter))
|
|
_filteredList.Add(_list[i]);
|
|
}
|
|
|
|
_treeView.SetRootItems(_filteredList);
|
|
}
|
|
|
|
_treeView.Rebuild();
|
|
}
|
|
|
|
private static VisualElement CreateLabel()
|
|
{
|
|
var label = new Label();
|
|
label.AddToClassList("tree-view-label");
|
|
return label;
|
|
}
|
|
|
|
private static VisualElement CreateObjectField()
|
|
{
|
|
return new ObjectField
|
|
{
|
|
objectType = typeof(UnityEngine.Object),
|
|
allowSceneObjects = true,
|
|
label = string.Empty
|
|
};
|
|
}
|
|
|
|
private void OnToolbarButtonRunClicked()
|
|
{
|
|
if (!ValidatorRunner.Run())
|
|
EditorUtility.DisplayDialog("Project Validator", "Failed to run validators, due to either project in play mode or compiling", "Ok");
|
|
}
|
|
|
|
private void OnToolbarButtonClearClicked()
|
|
{
|
|
_groupWarnings.style.display = DisplayStyle.None;
|
|
_groupErrors.style.display = DisplayStyle.None;
|
|
ValidatorRunner.Clear();
|
|
}
|
|
|
|
private void OnToolbarButtonSettingsClicked()
|
|
{
|
|
SettingsService.OpenProjectSettings(ProjectValidatorSettings.MenuPath);
|
|
}
|
|
|
|
private void OnToolbarSearchFieldChanged(ChangeEvent<string> evt)
|
|
{
|
|
_searchFilter = evt.newValue;
|
|
Filter();
|
|
}
|
|
|
|
private void OnTreeViewBindCellAsset(VisualElement ve, int index)
|
|
{
|
|
var objectField = (ObjectField)ve;
|
|
var entry = _treeView.GetItemDataForIndex<Report.Entry>(index);
|
|
|
|
if (!entry.AssetGuid.Empty())
|
|
{
|
|
objectField.value = AssetDatabase.LoadAssetByGUID(entry.AssetGuid, typeof(UnityEngine.Object));
|
|
objectField.style.display = DisplayStyle.Flex;
|
|
}
|
|
else
|
|
{
|
|
objectField.style.display = DisplayStyle.None;
|
|
}
|
|
}
|
|
|
|
private void OnTreeViewBindCellType(VisualElement ve, int index)
|
|
{
|
|
var label = (Label)ve;
|
|
var entry = _treeView.GetItemDataForIndex<Report.Entry>(index);
|
|
label.text = entry.Type;
|
|
}
|
|
|
|
private void OnTreeViewBindCellSeverity(VisualElement ve, int index)
|
|
{
|
|
var label = (Label)ve;
|
|
var entry = _treeView.GetItemDataForIndex<Report.Entry>(index);
|
|
label.text = entry.SeverityStr;
|
|
label.AddToClassList(entry.SeverityStr.ToLower());
|
|
}
|
|
|
|
private void OnTreeViewBindCellSeverityMessage(VisualElement ve, int index)
|
|
{
|
|
var label = (Label)ve;
|
|
var entry = _treeView.GetItemDataForIndex<Report.Entry>(index);
|
|
label.text = entry.SeverityResult;
|
|
}
|
|
|
|
private void OnTreeViewBindCellRelativePath(VisualElement ve, int index)
|
|
{
|
|
var label = (Label)ve;
|
|
var entry = _treeView.GetItemDataForIndex<Report.Entry>(index);
|
|
label.text = entry.RelativePathRichText;
|
|
}
|
|
|
|
private void OnTreeViewBindCellFieldPath(VisualElement ve, int index)
|
|
{
|
|
var label = (Label)ve;
|
|
var entry = _treeView.GetItemDataForIndex<Report.Entry>(index);
|
|
label.text = entry.FieldPathRichText;
|
|
}
|
|
|
|
private void OnTreeViewUnbindCellSeverity(VisualElement ve, int index)
|
|
{
|
|
var label = (Label)ve;
|
|
label.RemoveFromClassList("error");
|
|
label.RemoveFromClassList("warning");
|
|
}
|
|
|
|
private int OnTreeViewComparisonCellAsset(int index0, int index1)
|
|
{
|
|
var entry0 = _treeView.GetItemDataForIndex<Report.Entry>(index0);
|
|
var entry1 = _treeView.GetItemDataForIndex<Report.Entry>(index1);
|
|
|
|
var assetName0 = EditorAssetUtility.GetAssetName(entry0.AssetGuid);
|
|
var assetName1 = EditorAssetUtility.GetAssetName(entry1.AssetGuid);
|
|
return string.Compare(assetName0, assetName1, StringComparison.Ordinal);
|
|
}
|
|
|
|
private int OnTreeViewComparisonCellType(int index0, int index1)
|
|
{
|
|
var entry0 = _treeView.GetItemDataForIndex<Report.Entry>(index0);
|
|
var entry1 = _treeView.GetItemDataForIndex<Report.Entry>(index1);
|
|
return string.Compare(entry0.Type, entry1.Type, StringComparison.Ordinal);
|
|
}
|
|
|
|
private int OnTreeViewComparisonCellSeverity(int index0, int index1)
|
|
{
|
|
var entry0 = _treeView.GetItemDataForIndex<Report.Entry>(index0);
|
|
var entry1 = _treeView.GetItemDataForIndex<Report.Entry>(index1);
|
|
return entry0.Severity.CompareTo(entry1.Severity);
|
|
}
|
|
|
|
private int OnTreeViewComparisonCellSeverityMessage(int index0, int index1)
|
|
{
|
|
var entry0 = _treeView.GetItemDataForIndex<Report.Entry>(index0);
|
|
var entry1 = _treeView.GetItemDataForIndex<Report.Entry>(index1);
|
|
return string.Compare(entry0.SeverityResult, entry1.SeverityResult, StringComparison.Ordinal);
|
|
}
|
|
|
|
private int OnTreeViewComparisonCellRelativePath(int index0, int index1)
|
|
{
|
|
var entry0 = _treeView.GetItemDataForIndex<Report.Entry>(index0);
|
|
var entry1 = _treeView.GetItemDataForIndex<Report.Entry>(index1);
|
|
return string.Compare(entry0.RelativePath, entry1.RelativePath, StringComparison.Ordinal);
|
|
}
|
|
|
|
private int OnTreeViewComparisonCellFieldPath(int index0, int index1)
|
|
{
|
|
var entry0 = _treeView.GetItemDataForIndex<Report.Entry>(index0);
|
|
var entry1 = _treeView.GetItemDataForIndex<Report.Entry>(index1);
|
|
return string.Compare(entry0.FieldPath, entry1.FieldPath, StringComparison.Ordinal);
|
|
}
|
|
|
|
private void OnTreeViewSelectionChanged(IEnumerable<object> selection)
|
|
{
|
|
foreach (var obj in selection)
|
|
{
|
|
if (obj is Report.Entry entry)
|
|
ProjectValidatorUtility.PingObject(entry);
|
|
}
|
|
}
|
|
}
|
|
} |