protected override void Initialize() { this.menuTreeWidth = this.GetPersistentValue <float>("menuTreeWidth", 380); this.columns = new List <ResizableColumn>() { ResizableColumn.FlexibleColumn(this.menuTreeWidth.Value, 80), ResizableColumn.DynamicColumn(0, 200) }; this.runner = new ValidationRunner(); this.overview = new ValidationOverview(); this.editor = this.ValueEntry.SmartValue; this.profile = this.editor.Profile; this.sourceProperty = this.Property.Children["selectedSourceTarget"]; this.validationProfileTree = new ValidationProfileTree(); this.overviewToggle = this.GetPersistentValue <bool>("overviewToggle", true); this.validationProfileTree.Selection.SelectionChanged += (x) => { if (x == SelectionChangedType.ItemAdded) { object value = this.validationProfileTree.Selection.SelectedValue; ValidationProfileResult result = value as ValidationProfileResult; if (result != null) { this.editor.SetTarget(result.GetSource()); } else { this.editor.SetTarget(value); } } }; this.overview.OnProfileResultSelected += result => { OdinMenuItem mi = this.validationProfileTree.GetMenuItemForObject(result); mi.Select(); object source = result.GetSource(); this.editor.SetTarget(source); }; this.validationProfileTree.AddProfileRecursive(this.ValueEntry.SmartValue.Profile); OdinMenuTree.ActiveMenuTree = this.validationProfileTree; if (this.editor.ScanProfileImmediatelyWhenOpening) { this.editor.ScanProfileImmediatelyWhenOpening = false; this.ScanProfile(this.editor.Profile); } }
private void DrawTopBarButtons() { string btnName = "Run " + this.profile.Name; float width = GUI.skin.button.CalcSize(GUIHelper.TempContent(btnName)).x + 10; Rect rect = GUIHelper.GetCurrentLayoutRect().AlignRight(width); rect.x -= 5; rect.y -= 26; rect.height = 18; GUIHelper.PushColor(Color.green); if (GUI.Button(rect, btnName)) { this.ScanProfile(this.profile); } GUIHelper.PopColor(); object selectedValue = this.validationProfileTree.Selection.SelectedValue; if (selectedValue is ValidationProfileResult) { ValidationProfileResult result = selectedValue as ValidationProfileResult; if (result != null) { // Draw top bar buttons Object source = result.GetSource() as UnityEngine.Object; if (source != null) { rect.x -= 100; rect.width = 90; if (GUI.Button(rect, "Select Object", SirenixGUIStyles.ButtonRight)) { GUIHelper.SelectObject(source); GUIHelper.PingObject(source); } rect.x -= 80; rect.width = 80; if (GUI.Button(rect, "Ping Object", SirenixGUIStyles.ButtonLeft)) { GUIHelper.PingObject(source); } } } } }
public ValidationInfoMenuItem(OdinMenuTree tree, ValidationResult validationResult, ValidationProfileResult profileResult, ResizableColumn[] columns, DisplayOptions displayOptions, int originalItemIndex) : base(tree, "", validationResult) { this.ValidationResult = validationResult; this.ProfileResult = profileResult; this.Columns = columns; this.DisplayOptions = displayOptions; this.OriginalItemIndex = originalItemIndex; if (this.ProfileResult.SourceRecoveryData is SceneValidationProfile.SceneAddress) { var address = (SceneValidationProfile.SceneAddress) this.ProfileResult.SourceRecoveryData; var sceneAsset = AssetDatabase.LoadAssetAtPath <SceneAsset>(address.ScenePath); this.SceneName = sceneAsset != null ? sceneAsset.name : ""; } else { this.SceneName = ""; } this.SearchString = string.Join(" ", AllDisplayOptions.Select(x => this.GetDisplayString(x)).ToArray()); }
public ValidationProfileTree() { this.Config.DrawSearchToolbar = true; this.Config.AutoHandleKeyboardNavigation = true; this.Config.UseCachedExpandedStates = false; this.DefaultMenuStyle = OdinMenuStyle.TreeViewStyle; this.childMenuItemLookup = new Dictionary <object, OdinMenuItem>(); this.Selection.SelectionConfirmed += (x) => { OdinMenuItem sel = x.FirstOrDefault(); if (sel != null && sel.Value is ValidationProfileResult) { ValidationProfileResult result = sel.Value as ValidationProfileResult; if (result != null) { UnityEngine.Object source = result.GetSource() as UnityEngine.Object; GUIHelper.SelectObject(source); } } }; }
public void AddResultToTree(ValidationProfileResult result) { if (result.Results == null) { return; } if (result.Results.Any(x => x.ResultType != ValidationResultType.Valid)) { var menuItem = new OdinMenuItem(this, result.Name, result); var scene = default(Scene); if (result.Source as UnityEngine.Object) { var component = result.Source as Component; var go = result.Source as GameObject; if (component) { go = component.gameObject; } if (go) { scene = go.scene; } } this.childMenuItemLookup[result] = menuItem; if (result.Profile != null && scene.IsValid() && !this.childMenuItemLookup.ContainsKey(scene.path) && this.childMenuItemLookup.ContainsKey(result.Profile)) { var sceneItem = new OdinMenuItem(this, scene.name, scene.path); sceneItem.IconGetter = () => EditorIcons.UnityLogo; sceneItem.Toggled = true; this.childMenuItemLookup.Add(scene.path, sceneItem); this.childMenuItemLookup[result.Profile].ChildMenuItems.Add(sceneItem); } if (scene.IsValid() && this.childMenuItemLookup.ContainsKey(scene.path)) { this.childMenuItemLookup[scene.path].ChildMenuItems.Add(menuItem); } else if (result.Profile == null || !this.childMenuItemLookup.ContainsKey(result.Profile)) { this.MenuItems.Add(menuItem); } else { this.childMenuItemLookup[result.Profile].ChildMenuItems.Add(menuItem); } if (result.Source != null) { var component = result.Source as UnityEngine.Component; if (component) { menuItem.Icon = GUIHelper.GetAssetThumbnail(component.gameObject, null, false); } else { menuItem.Icon = GUIHelper.GetAssetThumbnail(result.Source as UnityEngine.Object, result.Source.GetType(), false); } } else { menuItem.Icon = EditorIcons.Transparent.Active; } } }
public override IEnumerable <ValidationProfileResult> Validate(ValidationRunner runner) { if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { yield break; } var selection = Selection.objects; var scenesToTest = this.GetAllScenes().ToList(); var setup = EditorSceneManager.GetSceneManagerSetup(); var partialProgress = 0f; var partialProgressStepSize = 1f / (scenesToTest.Count + (this.IncludeAssetDependencies ? 1 : 0)); try { for (int i = 0; i < scenesToTest.Count; i++) { var scene = scenesToTest[i]; EditorSceneManager.OpenScene(scene, OpenSceneMode.Single); var gameObjectsToScan = Resources.FindObjectsOfTypeAll <Transform>() .Where(x => (x.gameObject.scene.IsValid() && (x.gameObject.hideFlags & HideFlags.HideInHierarchy) == 0)) //.SelectMany(x => x.GetComponents(typeof(Component)).Select(c => new { go = x.gameObject, component = c })) .ToList(); var step = 1f / gameObjectsToScan.Count; for (int j = 0; j < gameObjectsToScan.Count; j++) { var go = gameObjectsToScan[j].gameObject; var progress = j * step * partialProgressStepSize + partialProgress; { var result = runner.ValidateUnityObjectRecursively(go); var entry = new ValidationProfileResult() { Name = go.name, Profile = this, Source = go, Results = result, Progress = progress, SourceRecoveryData = this.GetRecoveryData(go, null, scene), }; yield return(entry); } var components = go.GetComponents <Component>(); for (int k = 0; k < components.Length; k++) { var component = components[k]; if (component == null) { var entry = new ValidationProfileResult() { Name = "Broken Component", Source = go, SourceRecoveryData = this.GetRecoveryData(go, component, scene), Profile = this, Progress = progress, Results = new List <ValidationResult>() { new ValidationResult() { Message = object.ReferenceEquals(component, null) ? "Broken Component (A component is null on the GameObject '" + go.name + "'! A script reference is likely broken.)" : "Broken Component (A component of type '" + component.GetType().GetNiceName() + "' is null on the GameObject '" + go.name + "'! A script reference is likely broken.)", ResultType = ValidationResultType.Error, } } }; yield return(entry); } else { var result = runner.ValidateUnityObjectRecursively(component); var entry = new ValidationProfileResult() { Name = go.name + " - " + component.GetType().GetNiceName().SplitPascalCase(), Profile = this, Source = component, Results = result, Progress = progress, SourceRecoveryData = this.GetRecoveryData(go, component, scene), }; yield return(entry); } } } partialProgress += partialProgressStepSize; } } finally { // Load a new empty scene that will be unloaded immediately, just to be sure we completely clear all changes made by the scan EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); if (setup.Length != 0) { EditorSceneManager.RestoreSceneManagerSetup(setup); } } if (this.IncludeAssetDependencies) { var scenes = scenesToTest .ToHashSet() .Select(x => AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(x)) .ToArray(); var dep = EditorUtility.CollectDependencies(scenes); var components = dep.OfType <Component>().ToList(); var scriptableObjects = dep.OfType <ScriptableObject>().ToList(); var allObjects = components.Cast <UnityEngine.Object>().Concat(scriptableObjects.Cast <UnityEngine.Object>()) .ToArray(); var step = 1f / allObjects.Length; for (int i = 0; i < allObjects.Length; i++) { var obj = allObjects[i]; var progress = i * step * partialProgressStepSize + partialProgress; var result = runner.ValidateUnityObjectRecursively(obj); var entry = new ValidationProfileResult() { Name = obj.name, Profile = this, Source = obj, Results = result, Progress = progress, }; yield return(entry); } } Selection.objects = selection; }
public override object GetSource(ValidationProfileResult entry) { if (entry.Source as UnityEngine.Object) { return(entry.Source); } var address = (SceneAddress)entry.SourceRecoveryData; // This should work. bool openScene = true; foreach (var setupScene in EditorSceneManager.GetSceneManagerSetup()) { if (setupScene.path == address.ScenePath) { openScene = false; if (!setupScene.isActive) { EditorSceneManager.SetActiveScene(EditorSceneManager.GetSceneByPath(setupScene.path)); } break; } } if (openScene) { if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { return(null); } EditorSceneManager.OpenScene(address.ScenePath, OpenSceneMode.Single); } var go = this.GetGameObjectFromIndexPath(address); if (go != null) { entry.Source = go; if (address.ComponentType != null) { Component component = null; var components = go.GetComponents(address.ComponentType); if (address.ComponentIndex >= 0 && address.ComponentIndex < components.Length) { component = components[address.ComponentIndex]; } if (component != null) { entry.Source = component; } } } return(entry.Source); }
public virtual object GetSource(ValidationProfileResult entry) { return(entry.Source); }
public void AddErrorAndWarningIcons() { Dictionary <OdinMenuItem, int> errorCount = new Dictionary <OdinMenuItem, int>(); Dictionary <OdinMenuItem, int> warningCount = new Dictionary <OdinMenuItem, int>(); int maxECount = 0; int maxWCount = 0; foreach (OdinMenuItem mi in this.EnumerateTree()) { ValidationProfileResult result = mi.Value as ValidationProfileResult; if (result == null || result.Results == null || result.Results.Count == 0) { continue; } int ec = result.Results.Count(x => x.ResultType == ValidationResultType.Error); int wc = result.Results.Count(x => x.ResultType == ValidationResultType.Warning); foreach (OdinMenuItem mm in mi.GetParentMenuItemsRecursive(true)) { if (!errorCount.ContainsKey(mm)) { errorCount[mm] = 0; } if (!warningCount.ContainsKey(mm)) { warningCount[mm] = 0; } maxECount = Math.Max(ec, errorCount[mm] += ec); maxWCount = Math.Max(wc, warningCount[mm] += wc); } } //var wStyle = new GUIStyle("sv_label_5"); //var eStyle = new GUIStyle("sv_label_6"); //wStyle.alignment = TextAnchor.MiddleCenter; //eStyle.alignment = TextAnchor.MiddleCenter; float eCountWidth = SirenixGUIStyles.LeftAlignedWhiteMiniLabel.CalcSize(new GUIContent(maxECount + " ")).x; float wCountWidth = SirenixGUIStyles.LeftAlignedWhiteMiniLabel.CalcSize(new GUIContent(maxWCount + " ")).x; wCountWidth = eCountWidth = Mathf.Max(eCountWidth, wCountWidth); foreach (OdinMenuItem mi in this.EnumerateTree()) { if (!errorCount.ContainsKey(mi)) { errorCount[mi] = 0; } if (!warningCount.ContainsKey(mi)) { warningCount[mi] = 0; } int ec = errorCount[mi]; int wc = warningCount[mi]; GUIContent ecl = new GUIContent(ec + ""); GUIContent wcl = new GUIContent(wc + ""); mi.OnDrawItem += (m) => { if (Event.current.type == EventType.Repaint) { Rect rect = m.Rect.Padding(10, 5); rect.height += 1; Rect errorRect = rect.AlignRight(eCountWidth); Rect warningRect = errorRect.SubX(wCountWidth - 1); warningRect.width = wCountWidth; bool hasErrors = ec > 0; if (hasErrors) { SirenixEditorGUI.DrawSolidRect(errorRect, red); //SirenixEditorGUI.DrawBorders(errorRect, 1); errorRect.y -= 1; errorRect.x -= 1; GUI.Label(errorRect, ecl, SirenixGUIStyles.CenteredWhiteMiniLabel); } bool hasWarnings = wc > 0; if (hasWarnings) { warningRect.x -= 1; SirenixEditorGUI.DrawSolidRect(warningRect, orange); //SirenixEditorGUI.DrawBorders(warningRect, 1); warningRect.y -= 1; GUI.Label(warningRect, wcl, SirenixGUIStyles.CenteredBlackMiniLabel); } } }; } }
public abstract object GetSource(ValidationProfileResult entry);
public void Update() { List <DisplayOptions> displayOptions = AllDisplayOptions.Where(option => (this.Display & option) == option).ToList(); // Create/adjust columns if (this.columns == null) { this.columns = new ResizableColumn[displayOptions.Count]; } else { Array.Resize(ref this.columns, displayOptions.Count); } for (int i = 0; i < displayOptions.Count; i++) { this.columns[i] = this.GetColumn(displayOptions[i]); } // Create tree { this.Tree = new OdinMenuTree(); this.Tree.Config.AutoHandleKeyboardNavigation = true; this.Tree.Config.UseCachedExpandedStates = false; this.Tree.Config.EXPERIMENTAL_INTERNAL_DrawFlatTreeFastNoLayout = true; this.Tree.DefaultMenuStyle = OdinMenuStyle.TreeViewStyle; int itemCount = 0; foreach (ValidationProfileResult profileResult in this.ProfileResults) { foreach (ValidationResult validationResult in profileResult.Results) { if (validationResult.ResultType != ValidationResultType.Error && validationResult.ResultType != ValidationResultType.Warning) { continue; } ValidationInfoMenuItem menuItem = new ValidationInfoMenuItem(this.Tree, validationResult, profileResult, this.columns, this.Display, itemCount++); this.Tree.MenuItems.Add(menuItem); } } this.Tree.Selection.SelectionChanged += changeEvent => { if (changeEvent != SelectionChangedType.ItemAdded) { return; } if (this.OnProfileResultSelected != null) { ValidationInfoMenuItem menuItem = this.Tree.Selection.Last() as ValidationInfoMenuItem; ValidationProfileResult profileResult = menuItem.ProfileResult; this.OnProfileResultSelected(profileResult); } }; } if (this.SortBy != DisplayOptions.None) { this.Sort(); } }