Example #1
0
        public override void DrawInspector(IPlanVisualizer visualizer)
        {
            if (m_Plan.TryGetStateInfo(StateKey, out var stateInfo))
            {
                base.DrawInspector(visualizer);

                EditorGUILayout.LabelField("Estimated Total Reward", $"{stateInfo.CumulativeRewardEstimate}", EditorStyles.whiteLabel);
                EditorGUILayout.LabelField("Subplan Is Complete", $"{stateInfo.SubplanIsComplete}", EditorStyles.whiteLabel);

                if (m_Plan.TryGetOptimalAction(StateKey, out var optimalActionKey))
                {
                    EditorGUILayout.LabelField("Best Action", m_PlanExecutor.GetActionName(optimalActionKey), EditorStyles.whiteLabel);
                }

                if (string.IsNullOrEmpty(m_CachedStateString))
                {
                    m_CachedStateString = m_Plan.GetStateData(StateKey)?.ToString();
                }

                if (string.IsNullOrEmpty(m_CachedStateString)) // State may no longer exist but be selected as an override.
                {
                    return;
                }

                if (!m_RootState || active)
                {
                    s_ActionsGUIFoldout = EditorStyleHelper.DrawSubHeader(new GUIContent("Actions"), s_ActionsGUIFoldout);
                    if (s_ActionsGUIFoldout)
                    {
                        using (new EditorGUI.IndentLevelScope())
                        {
                            m_Plan.GetActions(StateKey, s_Actions);
                            SortSuccessorActions(s_Actions, ref s_Successors, out _, out _);

                            for (var i = 0; i < s_Successors.Count; i++)
                            {
                                var successor = s_Successors[i];
                                var actionKey = successor.ActionKey;
                                if (m_Plan.TryGetActionInfo(StateKey, actionKey, out var actionInfo))
                                {
                                    var rect = EditorGUILayout.BeginHorizontal();

                                    var  stateActionKey = (StateKey, actionKey);
                                    bool toggle         = i < visualizer.MaxChildrenNodes || visualizer.ForcedExpandedNodes.Contains(stateActionKey);

                                    if (i < visualizer.MaxChildrenNodes)
                                    {
                                        GUI.enabled = false;
                                    }

                                    EditorGUI.BeginChangeCheck();
                                    toggle = GUI.Toggle(rect, toggle, string.Empty);

                                    if (EditorGUI.EndChangeCheck())
                                    {
                                        if (toggle)
                                        {
                                            visualizer.ForcedExpandedNodes.Add(stateActionKey);
                                        }
                                        else
                                        {
                                            visualizer.ForcedExpandedNodes.Remove(stateActionKey);
                                        }
                                    }
                                    GUI.enabled = true;

                                    EditorGUILayout.LabelField(new GUIContent(m_PlanExecutor.GetActionName(actionKey)), new GUIContent($"{actionInfo.CumulativeRewardEstimate.Average:0.000}", $"{actionInfo.CumulativeRewardEstimate}"), EditorStyles.whiteLabel);
                                    EditorGUILayout.EndHorizontal();

                                    using (new EditorGUI.IndentLevelScope())
                                    {
                                        var parameters = m_PlanExecutor.GetActionParametersInfo(StateKey, actionKey);
                                        foreach (var param in parameters)
                                        {
                                            EditorGUILayout.LabelField(new GUIContent(param.ParameterName), new GUIContent(param.TraitObjectName, $"Object: {param.TraitObjectId}"), EditorStyles.whiteMiniLabel);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                EditorGUILayout.Space();
                s_StateGUIFoldout = EditorStyleHelper.DrawSubHeader(new GUIContent("State information"), s_StateGUIFoldout);
                var displayString = m_CachedStateString;

                if (s_StateGUIFoldout)
                {
                    using (new EditorGUI.IndentLevelScope())
                    {
                        EditorGUI.BeginChangeCheck();
                        s_StateFilter = EditorGUILayout.DelayedTextField(s_StateFilter);
                        if (EditorGUI.EndChangeCheck())
                        {
                            m_CachedFilterString = string.Empty;
                        }

                        if (!string.IsNullOrEmpty(s_StateFilter))
                        {
                            if (string.IsNullOrEmpty(m_CachedFilterString))
                            {
                                var stateStringSplit = m_CachedStateString.Split('\n');
                                var linesToInclude   = new SortedSet <int>();
                                var lastEmptyLine    = 0;
                                for (var i = 0; i < stateStringSplit.Length; i++)
                                {
                                    var stateStringLine = stateStringSplit[i];
                                    if (string.IsNullOrWhiteSpace(stateStringLine))
                                    {
                                        lastEmptyLine = i;
                                    }
                                    else if (stateStringLine.IndexOf(s_StateFilter, StringComparison.OrdinalIgnoreCase) >= 0)
                                    {
                                        var nextEmptyLine = i;
                                        while (!string.IsNullOrWhiteSpace(stateStringSplit[nextEmptyLine]))
                                        {
                                            nextEmptyLine++;
                                            if (nextEmptyLine == stateStringSplit.Length - 1)
                                            {
                                                break;
                                            }
                                        }

                                        for (var j = lastEmptyLine; j < nextEmptyLine; j++)
                                        {
                                            linesToInclude.Add(j);
                                        }
                                    }
                                }

                                var sb = new StringBuilder();
                                foreach (var line in linesToInclude)
                                {
                                    sb.AppendLine(stateStringSplit[line]);
                                }
                                m_CachedFilterString = sb.ToString();
                            }

                            displayString = m_CachedFilterString;
                        }

                        EditorGUILayout.LabelField(displayString, EditorStyleHelper.inspectorStyleLabel);
                    }
                }

                if (GUILayout.Button("Copy State", EditorStyles.miniButton))
                {
                    displayString.CopyToClipboard();
                }
            }
        }
        public static GUIContent GetOperandDisplayContent(SerializedProperty operand, SerializedProperty @operator,
                                                          IList <ParameterDefinition> parameters, float width, GUIStyle style)
        {
            var          normalColor = EditorGUIUtility.isProSkin ? "white" : "black";
            const string errorColor  = "#EF2526";

            var parameterProperty       = operand.FindPropertyRelative("m_Parameter").stringValue;
            var traitDefinitionProperty = operand.FindPropertyRelative("m_Trait").objectReferenceValue as TraitDefinition;
            var enumProperty            = operand.FindPropertyRelative("m_Enum").objectReferenceValue as EnumDefinition;
            var valueProperty           = operand.FindPropertyRelative("m_Value").stringValue;

            var operandString = string.Empty;


            if (!string.IsNullOrEmpty(parameterProperty))
            {
                // Check if the specified parameter exist
                bool validParameter = parameters.Any(p => p.Name == parameterProperty);

                operandString += EditorStyleHelper.RichText(parameterProperty, validParameter ? normalColor: errorColor, true);
            }

            if (traitDefinitionProperty != null)
            {
                bool validTrait      = true;
                var  parentParameter = parameters.FirstOrDefault(p => p.Name == parameterProperty);
                if (parentParameter != null)
                {
                    // Check if the selected Parameter contains this trait
                    validTrait = parentParameter.RequiredTraits.Any(t => t == traitDefinitionProperty);
                }

                var traitName = traitDefinitionProperty.name;
                operandString = AppendOperand(operandString, EditorStyleHelper.RichText(traitName, validTrait ? normalColor : errorColor));

                var traitProperty = operand.GetValue <OperandValue>().TraitProperty;
                // Check if the value is a field of the selected Trait
                bool validTraitValue = traitProperty != default && traitProperty.PropertyId != -1;
                var  displayedTrait  = validTraitValue ? traitProperty.Name : "undefined";

                operandString = AppendOperand(operandString, EditorStyleHelper.RichText(displayedTrait, validTraitValue ? normalColor : errorColor));

                if (IsListOperand(operand) && IsListComparisonOperator(@operator) && !IsListAssignment(@operator))
                {
                    operandString = AppendOperand(operandString, "Length");
                }
            }
            else
            {
                bool validValue = true;
                if (enumProperty != null)
                {
                    operandString = EditorStyleHelper.RichText(enumProperty.name, normalColor, true);

                    validValue = enumProperty.Elements.Any(p => p.Name == valueProperty);
                }

                if (!string.IsNullOrEmpty(valueProperty))
                {
                    foreach (var valuePart in valueProperty.Split('.'))
                    {
                        operandString = AppendOperand(operandString, EditorStyleHelper.RichText(valuePart, validValue ? normalColor : errorColor));
                    }
                }
            }

            if (Event.current.type == EventType.Repaint)
            {
                // Simplify display for parameter properties if the text doesn't fit
                Vector2 contentSize = style.CalcSize(new GUIContent(operandString));
                if (contentSize.x > width)
                {
                    var operandParts = operandString.Split('.');
                    if (operandParts.Length == 3)
                    {
                        operandString = $"{operandParts[0]}...{operandParts[2]}";

                        contentSize = style.CalcSize(new GUIContent(operandString));
                        if (contentSize.x > width)
                        {
                            operandString = $"...{operandParts[2]}";
                        }
                    }
                    else if (operandParts.Length == 2)
                    {
                        operandString = $"...{operandParts[1]}";
                    }
                }
            }

            return(new GUIContent(string.IsNullOrEmpty(operandString) ? "..." : operandString));;
        }