public override void OnInspectorGUI()
        {
            EditorGUILayout.Separator();

            serializedObject.Update();

            var parametersProperty = serializedObject.FindProperty("m_Parameters");

            parametersProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.parameters, parametersProperty.isExpanded);
            if (parametersProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                m_ParameterList.AdjustElementHeight(m_ParameterList.count == 0 ? 1 : 3);
                m_ParameterList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            var criteriaProperty = serializedObject.FindProperty("m_Criteria");

            criteriaProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.criteria, criteriaProperty.isExpanded);

            if (criteriaProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                m_CriteriaList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }
            EditorGUILayout.EndFoldoutHeaderGroup();

            var customRewards = serializedObject.FindProperty("m_CustomTerminalRewards");

            if (customRewards != null)
            {
                customRewards.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.terminalRewards, customRewards.isExpanded);
                if (customRewards.isExpanded)
                {
                    GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                    EditorGUILayout.PropertyField(serializedObject.FindProperty("m_TerminalReward"), new GUIContent("Base Value"));

                    GUILayout.Label(EditorStyleHelper.rewardModifiers);
                    m_RewardModifiers.AdjustElementHeight(m_RewardModifiers.count == 0 ? 1 : 2);
                    m_RewardModifiers.DoLayoutList();

                    GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
                }
            }

            serializedObject.ApplyModifiedProperties();

            base.OnInspectorGUI();
        }
Exemple #2
0
        public override void OnInspectorGUI()
        {
            var trait = (OldTraitDefinition)target;

            serializedObject.Update();

            EditorGUILayout.Space();

            m_FieldList.serializedProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.fields, m_FieldList.serializedProperty.isExpanded);
            if (m_FieldList.serializedProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                m_FieldList.AdjustElementHeight(m_FieldList.count == 0?1:3);
                m_FieldList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            m_ExpandAssetUsage = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.usages, m_ExpandAssetUsage);
            if (m_ExpandAssetUsage)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                EditorGUILayout.BeginVertical(GUI.skin.box);

                GUI.enabled = false;
                var used = IsTraitUsed(trait);
                GUI.enabled = true;

                if (!used)
                {
                    GUILayout.Label("None", EditorStyles.miniLabel);
                }

                GUILayout.EndVertical();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            serializedObject.ApplyModifiedProperties();

            base.OnInspectorGUI();
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUILayout.Space();

            m_EnumList.serializedProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.values, m_EnumList.serializedProperty.isExpanded);
            if (m_EnumList.serializedProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                m_EnumList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            serializedObject.ApplyModifiedProperties();

            base.OnInspectorGUI();
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            var definition = serializedObject.FindProperty("m_ProblemDefinition");

            if (!definition.objectReferenceValue)
            {
                AssignPlanGUI(definition);
                serializedObject.ApplyModifiedProperties();
                return;
            }

            definition.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.settings, definition.isExpanded, AIPlannerPreferences.displayControllerAdvancedSettings, value => AIPlannerPreferences.displayControllerAdvancedSettings = value);
            if (definition.isExpanded)
            {
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.PropertyField(definition);
                if (EditorGUI.EndChangeCheck())
                {
                    serializedObject.FindProperty("m_ActionExecuteInfos").ClearArray();
                }

                EditorGUILayout.PropertyField(serializedObject.FindProperty("m_InitializeOnStart"));
                EditorGUILayout.PropertyField(serializedObject.FindProperty("m_AutoUpdate"));
                serializedObject.ApplyModifiedProperties();

                if (AIPlannerPreferences.displayControllerAdvancedSettings)
                {
                    EditorGUILayout.PropertyField(serializedObject.FindProperty("m_PlannerSettings"));
                    EditorGUILayout.PropertyField(serializedObject.FindProperty("m_ExecutionSettings"));
                }

                EditorGUILayout.Space();
            }

            if (definition.objectReferenceValue != null)
            {
                var actionMappingArray = serializedObject.FindProperty("m_ActionExecuteInfos");
                actionMappingArray.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.actionExecution, actionMappingArray.isExpanded);
                if (actionMappingArray.isExpanded)
                {
                    var plan = definition.objectReferenceValue as ProblemDefinition;
                    if (plan != null && plan.ActionDefinitions != null)
                    {
                        // Remove actionInfo for actions not present in the plan
                        for (int i = actionMappingArray.arraySize - 1; i >= 0; i--)
                        {
                            var actionInfoProperty = actionMappingArray.GetArrayElementAtIndex(i);
                            var actionName         = actionInfoProperty.FindPropertyRelative("m_ActionName").stringValue;

                            if (plan.ActionDefinitions.FirstOrDefault(a => a.Name == actionName) == default)
                            {
                                actionMappingArray.DeleteArrayElementAtIndex(i);
                            }
                        }

                        foreach (var actionDefinition in plan.ActionDefinitions)
                        {
                            if (actionDefinition == null)
                            {
                                continue;
                            }

                            EditorGUILayout.BeginVertical("Box");
                            EditorGUILayout.LabelField(actionDefinition.Name, EditorStyleHelper.namedObjectLabel);
                            var actionMappingProperty = actionMappingArray.FindPropertyInArray(property => property.FindPropertyRelative("m_ActionName").stringValue == actionDefinition.Name);

                            if (actionMappingProperty == null)
                            {
                                actionMappingProperty = actionMappingArray.InsertArrayElement();
                                actionMappingProperty.FindPropertyRelative("m_ActionName").stringValue      = actionDefinition.Name;
                                actionMappingProperty.FindPropertyRelative("m_Source").objectReferenceValue = null;
                            }

                            var sourceGameObjectProperty = actionMappingProperty.FindPropertyRelative("m_SourceGameObject");
                            if (sourceGameObjectProperty.objectReferenceValue == null)
                            {
                                using (new EditorGUI.IndentLevelScope())
                                {
                                    EditorGUILayout.Space();
                                    EditorGUILayout.HelpBox("Drag a GameObject to the field below (or use the selection icon) to match a planner action to a callback that will cause an effect in the world", MessageType.Info);
                                    sourceGameObjectProperty.objectReferenceValue = EditorGUILayout.ObjectField(GUIContent.none, sourceGameObjectProperty.objectReferenceValue, typeof(GameObject), true);
                                    EditorGUILayout.Space();
                                }
                            }
                            else
                            {
                                EditorGUI.BeginChangeCheck();
                                sourceGameObjectProperty.objectReferenceValue = EditorGUILayout.ObjectField(EditorStyleHelper.onActionStart, sourceGameObjectProperty.objectReferenceValue, typeof(GameObject), true);

                                if (EditorGUI.EndChangeCheck())
                                {
                                    if (sourceGameObjectProperty.objectReferenceValue == null)
                                    {
                                        // Reset serialized data, when source object reference is removed
                                        actionMappingProperty.FindPropertyRelative("m_Source").objectReferenceValue = null;
                                        actionMappingProperty.FindPropertyRelative("m_Method").stringValue          = String.Empty;
                                        actionMappingProperty.FindPropertyRelative("m_Arguments").ClearArray();
                                    }
                                }

                                var sourceGameObject = sourceGameObjectProperty.objectReferenceValue as GameObject;
                                if (sourceGameObject)
                                {
                                    var components     = sourceGameObject.GetComponents <MonoBehaviour>();
                                    var sourceProperty = actionMappingProperty.FindPropertyRelative("m_Source");

                                    using (new EditorGUI.IndentLevelScope())
                                    {
                                        var component = sourceProperty.objectReferenceValue as Component;

                                        MethodInfo selectedMethod = null;
                                        var        methods        = components.Where(c => c != null)
                                                                    .SelectMany(c => c.GetType()
                                                                                .GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)
                                                                                .Where(m => !m.IsSpecialName)
                                                                                .Select(m => ((Component)c, m))).Prepend((default, default)).ToArray();;
Exemple #5
0
        internal static void PropertyField(Rect rect, IList <ParameterDefinition> parameters, SerializedProperty precondition, Type[] types)
        {
            const int operatorSize = 65;
            const int spacer       = 5;

            var w          = rect.width;
            var buttonSize = (w - operatorSize - 3 * spacer) / 2;

            rect.x    += spacer;
            rect.y    += EditorGUIUtility.standardVerticalSpacing;
            rect.width = buttonSize;

            var @operator = precondition.FindPropertyRelative("m_Operator");

            switch (@operator.stringValue)
            {
            case nameof(Operation.SpecialOperators.Custom):
                rect.width = w - spacer;
                var customType = precondition.FindPropertyRelative("m_CustomOperatorType").stringValue;
                EditorStyleHelper.CustomMethodField(rect, customType, types);
                break;

            default:
            {
                var operandA = precondition.FindPropertyRelative("m_OperandA");
                var operandB = precondition.FindPropertyRelative("m_OperandB");

                TraitGUIUtility.DrawOperandSelectorField(rect, operandA, @operator, parameters, true, false, property =>
                    {
                        TraitGUIUtility.ClearOperandProperty(operandB);
                    });

                var validLeftOperand = !string.IsNullOrEmpty(operandA.FindPropertyRelative("m_Parameter").stringValue);

                rect.x    += buttonSize + spacer;
                rect.width = operatorSize;

                if (validLeftOperand)
                {
                    var operators = GetComparisonOperators(operandA);
                    var opIndex   = EditorGUI.Popup(rect, Array.IndexOf(operators, @operator.stringValue),
                                                    operators, EditorStyleHelper.listPopupStyleBold);

                    @operator.stringValue = operators[Math.Max(0, opIndex)];
                }
                else
                {
                    // No operand available
                    GUI.enabled = false;
                    GUI.Button(rect, string.Empty, EditorStyleHelper.listPopupStyle);
                    GUI.enabled = true;
                }

                rect.x    += operatorSize + spacer;
                rect.width = buttonSize;

                if (validLeftOperand)
                {
                    string unknownType = default;
                    TraitGUIUtility.DrawOperandSelectorField(rect, operandB, @operator, parameters,
                                                             TraitGUIUtility.GetOperandValuePropertyType(operandA, @operator, ref unknownType), unknownType);
                }
                else
                {
                    // No operand available
                    GUI.enabled = false;
                    GUI.Button(rect, string.Empty, EditorStyleHelper.listPopupStyle);
                    GUI.enabled = true;
                }
            }
            break;
            }
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUILayout.Space();

            var parametersProperty = serializedObject.FindProperty("m_Parameters");

            parametersProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.parameters, parametersProperty.isExpanded, AIPlannerPreferences.displayActionDefinitionAdvancedSettings, toggle => AIPlannerPreferences.displayActionDefinitionAdvancedSettings = toggle);

            if (parametersProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                if (m_ParameterList.count >= ActionKey.MaxLength)
                {
                    EditorGUILayout.HelpBox(EditorStyleHelper.maxParametersReached);
                }

                m_ParameterList.AdjustElementHeight(m_ParameterList.count == 0 ? 1 : AIPlannerPreferences.displayActionDefinitionAdvancedSettings?4:3);
                m_ParameterList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            m_PreconditionList.serializedProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.preconditions, m_PreconditionList.serializedProperty.isExpanded);
            if (m_PreconditionList.serializedProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                m_PreconditionList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            m_ObjectCreatedList.serializedProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.effects, m_ObjectCreatedList.serializedProperty.isExpanded);
            if (m_ObjectCreatedList.serializedProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                GUILayout.Label(EditorStyleHelper.objectsCreated);
                m_ObjectCreatedList.AdjustElementHeight(m_ObjectCreatedList.count == 0 ? 1 : 2);
                m_ObjectCreatedList.DoLayoutList();

                GUILayout.Label(EditorStyleHelper.objectsChanged);
                m_ObjectModifierList.DoLayoutList();

                GUILayout.Label(EditorStyleHelper.objectsRemoved);
                m_ObjectRemovedList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            var customRewards = serializedObject.FindProperty("m_CustomRewards");

            customRewards.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.rewards, customRewards.isExpanded);
            if (customRewards.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Reward"), new GUIContent("Base Value"));

                GUILayout.Label(EditorStyleHelper.rewardModifiers);
                m_RewardModifierList.AdjustElementHeight(m_RewardModifierList.count == 0 ? 1 : 2);
                m_RewardModifierList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            serializedObject.ApplyModifiedProperties();

            base.OnInspectorGUI();
        }
        void DrawObjectModifierListElement(Rect rect, int index, bool isActive, bool isFocused)
        {
            var actionDefinition = (target as ActionDefinition);

            if (actionDefinition == null)
            {
                return;
            }

            const int operatorSize = 50;
            const int spacer       = 5;

            var parameters        = actionDefinition.Parameters.ToList();
            var effectsParameters = actionDefinition.CreatedObjects.ToList();

            parameters.AddRange(effectsParameters);

            var w          = rect.width;
            var buttonSize = (w - operatorSize - 3 * spacer) / 2;

            rect.x    += spacer;
            rect.y    += EditorGUIUtility.standardVerticalSpacing;
            rect.width = buttonSize;

            var list   = m_ObjectModifierList.serializedProperty;
            var effect = list.GetArrayElementAtIndex(index);

            var @operator = effect.FindPropertyRelative("m_Operator");
            var operandA  = effect.FindPropertyRelative("m_OperandA");
            var operandB  = effect.FindPropertyRelative("m_OperandB");

            switch (@operator.stringValue)
            {
            case nameof(Operation.SpecialOperators.Add):
            case nameof(Operation.SpecialOperators.Remove):
            {
                TraitGUIUtility.DrawParameterSelectorField(rect, operandA.FindPropertyRelative("m_Parameter"), parameters);

                rect.x    += buttonSize + spacer;
                rect.width = operatorSize;

                EditorGUI.LabelField(rect, (@operator.stringValue == nameof(Operation.SpecialOperators.Add))?"Add":"Remove", EditorStyleHelper.listValueStyle);

                rect.x    += operatorSize + spacer;
                rect.width = buttonSize;

                var traitDefinitions = PlannerAssetDatabase.TraitDefinitions.ToArray();
                var traitNames       = traitDefinitions.Select(t => t?.name).ToArray();

                var traitIndex = Array.IndexOf(traitDefinitions, operandB.FindPropertyRelative("m_Trait").objectReferenceValue as TraitDefinition);
                EditorGUI.BeginChangeCheck();
                traitIndex = EditorGUI.Popup(rect, traitIndex, traitNames, EditorStyleHelper.listPopupStyle);

                if (EditorGUI.EndChangeCheck())
                {
                    TraitGUIUtility.ClearOperandProperty(operandB);
                    operandB.FindPropertyRelative("m_Trait").objectReferenceValue = traitDefinitions[traitIndex];
                }
            }
            break;

            case nameof(Operation.SpecialOperators.Custom):
                rect.width = w - spacer;
                var customType = effect.FindPropertyRelative("m_CustomOperatorType").stringValue;
                EditorStyleHelper.CustomMethodField(rect, customType, PlannerCustomTypeCache.ActionEffectTypes);
                break;

            default:
            {
                TraitGUIUtility.DrawOperandSelectorField(rect, operandA, null, parameters, modified =>
                    {
                        TraitGUIUtility.ClearOperandProperty(operandB);
                    });

                var validLeftOperand = !string.IsNullOrEmpty(operandA.FindPropertyRelative("m_Parameter").stringValue);

                rect.x    += buttonSize + spacer;
                rect.width = operatorSize;

                if (validLeftOperand)
                {
                    var operators = GetAssignmentOperators(operandA);
                    var opIndex   = EditorGUI.Popup(rect, Array.IndexOf(operators, @operator.stringValue),
                                                    operators, EditorStyleHelper.listPopupStyleBold);
                    var operatorSelected = operators[Math.Max(0, opIndex)];
                    if (@operator.stringValue != operatorSelected)
                    {
                        if (TraitGUIUtility.IsListOperand(operandA) && TraitGUIUtility.IsListUnaryOperator(@operator))
                        {
                            TraitGUIUtility.ClearOperandProperty(operandB);
                        }

                        @operator.stringValue = operatorSelected;
                    }
                }
                else
                {
                    // No operand available
                    GUI.enabled = false;
                    GUI.Button(rect, string.Empty, EditorStyleHelper.listPopupStyle);
                    GUI.enabled = true;
                }

                var showRightOperand = !TraitGUIUtility.IsListOperand(operandA) || !TraitGUIUtility.IsListUnaryOperator(@operator);

                rect.x    += operatorSize + spacer;
                rect.width = buttonSize;

                if (validLeftOperand && showRightOperand)
                {
                    string unknownType = default;
                    TraitGUIUtility.DrawOperandSelectorField(rect, operandB, @operator, parameters,
                                                             TraitGUIUtility.GetOperandValuePropertyType(operandA, @operator, ref unknownType), unknownType);
                }
                else
                {
                    // No operand available
                    GUI.enabled = false;
                    GUI.Button(rect, string.Empty, EditorStyleHelper.listPopupStyle);
                    GUI.enabled = true;
                }
            }
            break;
            }
        }
        internal static void PropertyField(Rect rect, IList<ParameterDefinition> target, SerializedProperty rewardElement, Type[] rewardTypes)
        {
            const int operatorSize = 60;
            const int spacer = 5;

            var w = rect.width;
            rect.width = operatorSize;
            rect.y += EditorGUIUtility.standardVerticalSpacing;

            var @operator = rewardElement.FindPropertyRelative("m_Operator");
            var opIndex = EditorGUI.Popup(rect, Array.IndexOf(k_RewardOperators, @operator.stringValue),
                k_RewardOperators, EditorStyleHelper.listPopupStyle);

            if (k_RewardOperators.Length > 0)
                @operator.stringValue = k_RewardOperators[Math.Max(0, opIndex)];

            rect.x += operatorSize;
            rect.width = w - operatorSize;
            rect.height = EditorGUIUtility.singleLineHeight;
            var methodName = rewardElement.FindPropertyRelative("m_Typename");
            var customRewardFullNames = rewardTypes.Select(t => t.FullName).ToArray();

            rect.x += spacer;
            EditorStyleHelper.CustomMethodField(rect, methodName.stringValue, rewardTypes);

            var customRewardIndex = Array.IndexOf(customRewardFullNames, methodName.stringValue);
            if (customRewardIndex >= 0)
            {
                rect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;

                var rewardType = rewardTypes[customRewardIndex];

                var rewardParametersInfo = rewardType.GetMethod(k_RewardModifierMethodName)?.GetParameters();
                if (rewardParametersInfo != null)
                {
                    if (rewardParametersInfo[0].ParameterType.GetInterfaces().Contains(typeof(IStateData)))
                    {
                        GUI.Label(rect, "No parameters", EditorStyleHelper.italicGrayLabel);
                    }
                    else
                    {
                        var parameterProperties = rewardElement.FindPropertyRelative("m_Parameters");

                        var customParamCount = rewardParametersInfo.Length;
                        if (parameterProperties.arraySize != customParamCount)
                        {
                            parameterProperties.arraySize = customParamCount;
                        }

                        if (customParamCount >= 0)
                        {
                            float paramWidth = rect.width / customParamCount;
                            rect.width = paramWidth;

                            for (var i = 0; i < customParamCount; i++)
                            {
                                var parameterType = rewardParametersInfo[i].ParameterType;

                                TraitGUIUtility.DrawParameterSelectorField(rect, parameterProperties.GetArrayElementAtIndex(i), target, parameterType);
                                rect.x += paramWidth;
                            }
                        }
                    }
                }
                else
                {
                    GUI.Label(rect, "Invalid reward type", EditorStyleHelper.errorTextField);
                }
            }
        }
Exemple #9
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            m_ActionList.serializedProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.actions, m_ActionList.serializedProperty.isExpanded);
            if (m_ActionList.serializedProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                m_ActionList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            m_TerminationList.serializedProperty.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.terminations, m_TerminationList.serializedProperty.isExpanded);
            if (m_TerminationList.serializedProperty.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                m_TerminationList.DoLayoutList();

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            var customCumulativeRewardEstimator = serializedObject.FindProperty("m_CustomCumulativeRewardEstimator");

            customCumulativeRewardEstimator.isExpanded = EditorStyleHelper.DrawSubHeader(EditorStyleHelper.plannerSettings, customCumulativeRewardEstimator.isExpanded, AIPlannerPreferences.displayProblemDefinitionAdvancedSettings, value => AIPlannerPreferences.displayProblemDefinitionAdvancedSettings = value);
            if (customCumulativeRewardEstimator.isExpanded)
            {
                GUILayout.Space(EditorStyleHelper.subHeaderPaddingTop);

                var rewardEstimatorTypeNames      = PlannerCustomTypeCache.CumulativeRewardEstimatorTypes.Select(t => t.FullName).Prepend(string.Empty).ToArray();
                var rewardEstimatorTypeShortNames = PlannerCustomTypeCache.CumulativeRewardEstimatorTypes.Select(t => t.Name).Prepend(k_Default).ToArray();

                var rewardEstimatorIndex = Array.IndexOf(rewardEstimatorTypeNames, customCumulativeRewardEstimator.stringValue);
                EditorGUI.BeginChangeCheck();

                if (rewardEstimatorIndex == -1 && !string.IsNullOrEmpty(customCumulativeRewardEstimator.stringValue))
                {
                    GUI.backgroundColor           = Color.red;
                    rewardEstimatorTypeShortNames = rewardEstimatorTypeShortNames.Append($"Unknown type {customCumulativeRewardEstimator.stringValue}").ToArray();
                    rewardEstimatorIndex          = rewardEstimatorTypeShortNames.Length - 1;
                }

                rewardEstimatorIndex = EditorGUILayout.Popup(EditorStyleHelper.cumulativeRewardEstimator, rewardEstimatorIndex, rewardEstimatorTypeShortNames);

                if (EditorGUI.EndChangeCheck())
                {
                    if (rewardEstimatorIndex < rewardEstimatorTypeNames.Length)
                    {
                        customCumulativeRewardEstimator.stringValue = rewardEstimatorTypeNames[rewardEstimatorIndex];
                    }
                }
                GUI.backgroundColor = Color.white;

                if (rewardEstimatorIndex == 0)
                {
                    EditorGUILayout.BeginHorizontal();
                    using (new EditorGUI.IndentLevelScope())
                    {
                        EditorGUILayout.PrefixLabel("Bounds");
                    }

                    var lowerEstimate   = serializedObject.FindProperty("m_DefaultEstimateLower");
                    var averageEstimate = serializedObject.FindProperty("m_DefaultEstimateAverage");
                    var upperEstimate   = serializedObject.FindProperty("m_DefaultEstimateUpper");
                    lowerEstimate.intValue   = EditorGUILayout.IntField(lowerEstimate.intValue);
                    averageEstimate.intValue = EditorGUILayout.IntField(averageEstimate.intValue);
                    upperEstimate.intValue   = EditorGUILayout.IntField(upperEstimate.intValue);
                    EditorGUILayout.EndHorizontal();
                }

                if (AIPlannerPreferences.displayProblemDefinitionAdvancedSettings)
                {
                    var discountFactor = serializedObject.FindProperty("DiscountFactor");
                    EditorGUILayout.PropertyField(discountFactor);
                }

                GUILayout.Space(EditorStyleHelper.subHeaderPaddingBottom);
            }

            serializedObject.ApplyModifiedProperties();

            base.OnInspectorGUI();
        }