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);
                        }
                    }
                }
            }
        }
예제 #3
0
            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);
                    }
                }
            };
        }
예제 #5
0
        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;
                }
            }
        }
예제 #6
0
        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;
        }
예제 #7
0
        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);
        }
예제 #8
0
 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);
                        }
                    }
                };
            }
        }
예제 #10
0
 public abstract object GetSource(ValidationProfileResult entry);
예제 #11
0
        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();
            }
        }