public override void OnInspectorGUI()
    {
        this.serializedObject.Update();

        GUIContent content;

        EditorGUI.indentLevel = 0;

        EditorGUIUtility.labelWidth = PGEditorUtils.CONTROLS_DEFAULT_LABEL_WIDTH;

        Object[] targetObjs = this.serializedObject.targetObjects;

        CompoundTargetTracker curEditTarget;

        EditorGUILayout.PropertyField(this.numberOfTargets, new GUIContent("Targets (-1 for all)"));

        EditorGUI.BeginChangeCheck();
        content = new GUIContent("Sorting Style", "The style of sorting to use");
        EditorGUILayout.PropertyField(this.sortingStyle, content);

        var sortingStyle = (TargetTracker.SORTING_STYLES) this.sortingStyle.enumValueIndex;

        // If changed, trigger the property setter for all objects being edited
        if (EditorGUI.EndChangeCheck())
        {
            for (int i = 0; i < targetObjs.Length; i++)
            {
                curEditTarget = (CompoundTargetTracker)targetObjs[i];

                Undo.RecordObject(curEditTarget, targetObjs[0].GetType() + " sortingStyle");

                curEditTarget.sortingStyle = sortingStyle;
            }
        }

        if (sortingStyle != TargetTracker.SORTING_STYLES.None)
        {
            EditorGUI.indentLevel += 1;

            content = new GUIContent(
                "Minimum Interval",
                "How often the target list will be sorted. If set to 0, " +
                "sorting will only be triggered when Targets enter or exit range."
                );
            EditorGUILayout.PropertyField(this.updateInterval, content);

            EditorGUI.indentLevel -= 1;
        }

        GUILayout.Space(8);

        // If multi-selected, use Unity's display. Much easier in this case.
        if (serializedObject.isEditingMultipleObjects)
        {
            content = new GUIContent
                      (
                "TargetTrackers",
                "The TargetTrackers whos targets will be combined by this CompoundTargetTracker."
                      );
            EditorGUILayout.PropertyField(this.targetTrackers, content, true);
        }
        else
        {
            curEditTarget = (CompoundTargetTracker)targetObjs[0];

            // Track changes so we only register undo entries when needed.
            EditorGUI.BeginChangeCheck();

            var targetTrackersCopy = new List <TargetTracker>(curEditTarget.targetTrackers);
            PGEditorUtils.FoldOutObjList <TargetTracker>
            (
                "TargetTrackers",
                targetTrackersCopy,
                true
            );

            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(curEditTarget, targetObjs[0].GetType() + " targetTrackers");

                curEditTarget.targetTrackers.Clear();
                curEditTarget.targetTrackers.AddRange(targetTrackersCopy);
            }
        }

        GUILayout.Space(4);

        EditorGUILayout.BeginHorizontal();

        content = new GUIContent
                  (
            "Show All Gizmos",
            "Click to force all TargetTracker gizmos to be visibile to visualize the Area " +
            "in the Editor."
                  );
        this.GizmoVisibilityButton(targetObjs, content, true);

        content = new GUIContent
                  (
            "Hide All Gizmos",
            "Click to force all TargetTracker gizmos to be hidden."
                  );
        this.GizmoVisibilityButton(targetObjs, content, false);

        EditorGUILayout.EndHorizontal();

        GUILayout.Space(8);

        content = new GUIContent("Debug Level", "Set it higher to see more verbose information.");
        EditorGUILayout.PropertyField(this.debugLevel, content);

        serializedObject.ApplyModifiedProperties();

        // Flag Unity to save the changes to to the prefab to disk
        //   This is needed to make the gizmos update immediatly.
        if (GUI.changed)
        {
            EditorUtility.SetDirty(target);
        }
    }
    public override void OnInspectorGUI()
    {
        this.serializedObject.Update();
        Object[] targetObjs = this.serializedObject.targetObjects;

        GUIContent content;

        EditorGUIUtility.labelWidth = PGEditorUtils.CONTROLS_DEFAULT_LABEL_WIDTH;

        EditorGUI.indentLevel = 1;

        // Build a cache dict to use after the control is displayed for user input
        var               ignoreCache = new Dictionary <IgnoreModifier, List <Targetable> >();
        IgnoreModifier    curEditTarget;
        List <Targetable> curIgnoreCacheList;

        for (int i = 0; i < targetObjs.Length; i++)
        {
            curEditTarget      = (IgnoreModifier)targetObjs[i];
            curIgnoreCacheList = new List <Targetable>();

            // Update the cache to compare later
            curIgnoreCacheList.AddRange(curEditTarget._ignoreList);

            // Store to cache dict
            ignoreCache[curEditTarget] = curIgnoreCacheList;
        }

        // If multiple objects are being edited display the default control. Otherwise
        //   The pretty control is displayed below when there is only 1 object in the targetObjs
        if (this.serializedObject.isEditingMultipleObjects)
        {
            content = new GUIContent
                      (
                "Targetables to ignore",
                "Drag and drop Targetables to make the TargetTracker ignore them."
                      );
            EditorGUILayout.PropertyField(this.ignoreList, content, true);

            // Update the backing list or the cache handling won't do anything below.
            this.serializedObject.ApplyModifiedProperties();
        }


        foreach (KeyValuePair <IgnoreModifier, List <Targetable> > kvp in ignoreCache)
        {
            curEditTarget      = kvp.Key;
            curIgnoreCacheList = kvp.Value;

            // See the note above on editing multi objects and control visibility
            //   Note: If this is true then there will only be 1 item I the cache dict here.
            if (!this.serializedObject.isEditingMultipleObjects)
            {
                GUILayout.Space(4);
                PGEditorUtils.FoldOutObjList <Targetable>
                (
                    "Targetables to ignore",
                    curEditTarget._ignoreList,
                    true                      // Force the fold-out state
                );
            }

            // Detect a change to trigger ignore refresh logic if the game is playing
            //	 Note: Don't use counts since new item can be null then later
            //	       drag&dropped, skipping logic.
            if (Application.isPlaying)
            {
                // Sync newly added
                foreach (Targetable targetable in new List <Targetable>(curEditTarget._ignoreList))
                {
                    if (targetable == null)
                    {
                        continue;
                    }

                    if (!curIgnoreCacheList.Contains(targetable))
                    {
                        curEditTarget.Add(targetable);
                    }
                }

                // Sync newly removed
                foreach (Targetable targetable in new List <Targetable>(curIgnoreCacheList))
                {
                    if (targetable == null)
                    {
                        continue;
                    }

                    if (!curEditTarget._ignoreList.Contains(targetable))
                    {
                        curEditTarget.Remove(targetable);
                    }
                }
            }
        }
        GUILayout.Space(4);

        content = new GUIContent
                  (
            "Debug Level", "Set it higher to see more verbose information."
                  );
        EditorGUILayout.PropertyField(this.debugLevel, content);

        serializedObject.ApplyModifiedProperties();

        // Flag Unity to save the changes to to the prefab to disk
        //   This is needed to make the gizmos update immediatly.
        if (GUI.changed)
        {
            EditorUtility.SetDirty(target);
        }
    }