public static void DynamicField(FieldInfo fieldInfo, object obj)
        {
            string fieldName = fieldInfo.Name;

            fieldName = Regex.Replace(fieldName, "_([a-z])", m => m.Groups[1].ToString().ToUpper());
            fieldName = Regex.Replace(fieldName, "(\\B[A-Z])", " $1");
            fieldName = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(fieldName);

            if (fieldInfo.FieldType == typeof(string))
            {
                fieldInfo.SetValue(obj, EditorGUILayout.TextField(fieldName, (string)fieldInfo.GetValue(obj)));
            }
            else if (fieldInfo.FieldType == typeof(int))
            {
                fieldInfo.SetValue(obj, EditorGUILayout.IntField(fieldName, (int)fieldInfo.GetValue(obj)));
            }
            else if (fieldInfo.FieldType == typeof(float))
            {
                fieldInfo.SetValue(obj, EditorGUILayout.FloatField(fieldName, (float)fieldInfo.GetValue(obj)));
            }
            else if (fieldInfo.FieldType == typeof(bool))
            {
                fieldInfo.SetValue(obj, EditorGUILayout.Toggle(fieldName, (bool)fieldInfo.GetValue(obj)));
            }
            else if (fieldInfo.FieldType.IsClass)
            {
                object childFieldObj = fieldInfo.GetValue(obj);
                EditorGUILayout.LabelField(fieldInfo.Name + ": ");

                EditorGUI.indentLevel++;
                FieldInfo[] childFields = TypeUtil.GetInspectorFields(fieldInfo.FieldType);
                foreach (FieldInfo childField in childFields)
                {
                    EditorGUILayoutUtil.DynamicField(childField, childFieldObj);
                }
                EditorGUI.indentLevel--;
            }
        }
        private void DrawNodeInspector(Node node, NodeViewData nodeViewData)
        {
            nodeViewData.name = EditorGUILayout.TextField(nodeViewData.name);

            // Node Delegate Button + Fields
            EditorGUILayout.BeginVertical((GUIStyle)"InspectorBigBox");
            EditorGUILayout.LabelField("Node Delegates:");
            foreach (INodeDelegate nodeDelegate in node.GetNodeDelegates())
            {
                Type nodeDelegateType = nodeDelegate.GetType();
                EditorGUILayout.BeginVertical((GUIStyle)"InspectorBox");
                EditorGUILayout.LabelField(nodeDelegateType.Name, EditorStyles.boldLabel);

                FieldInfo[] fields = TypeUtil.GetInspectorFields(nodeDelegateType);
                foreach (FieldInfo field in fields)
                {
                    EditorGUILayoutUtil.DynamicField(field, nodeDelegate);
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.Space();
            }

            if (GUILayout.Button("", (GUIStyle)"AddButton", GUILayout.Width(20.0f), GUILayout.Height(20.0f)))
            {
                GenericMenu nodeDelegateMenu = new GenericMenu();
                foreach (Type nodeDelegateType in INodeDelegateUtil.ImplementationTypes)
                {
                    nodeDelegateMenu.AddItem(new GUIContent(nodeDelegateType.Name), false, this.AddNodeDelegateToNode, Tuple.Create(node, nodeDelegateType));
                }
                nodeDelegateMenu.ShowAsContext();
            }
            EditorGUILayout.EndVertical();

            EditorGUILayout.Space();

            // Node Transitions
            EditorGUILayout.BeginVertical((GUIStyle)"InspectorBigBox");
            EditorGUILayout.LabelField("Transitions:");
            IList <NodeTransition> nodeTransitions = this.TargetGraph.GetOutgoingTransitionsForNode(node);

            foreach (NodeTransition nodeTransition in nodeTransitions)
            {
                GUIStyle transitionStyle = this.IsNodeTransitionSelected(nodeTransition) ? (GUIStyle)"SelectedInspectorBox" : (GUIStyle)"InspectorBox";
                Rect     transitionRect  = EditorGUILayout.BeginVertical(transitionStyle, GUILayout.MinHeight(30.0f));
                string   targetText      = "";
                targetText += (nodeTransition.targets.Length > 1) ? "Targets: " : "Target: ";
                targetText += StringUtil.Join(", ", nodeTransition.targets.Select(id => this.GetViewDataForNode(this.TargetGraph.LoadNodeById(id)).name));

                EditorGUILayout.LabelField(targetText, GUILayout.Height(30.0f));

                Rect editButtonRect = new Rect(new Vector2(transitionRect.x + transitionRect.width - 25.0f,
                                                           transitionRect.y + 5.0f),
                                               new Vector2(20.0f, 20.0f));
                if (GUI.Button(editButtonRect, "", (GUIStyle)"EditButton"))
                {
                    this.StartEditingNodeTransition(node, nodeTransition);
                }

                Rect removeButtonRect = new Rect(new Vector2(transitionRect.x + transitionRect.width - 50.0f,
                                                             transitionRect.y + 5.0f),
                                                 new Vector2(20.0f, 20.0f));
                if (GUI.Button(removeButtonRect, "", (GUIStyle)"RemoveButton"))
                {
                    this.AddPendingNodeTransitionRemoval(node, nodeTransition);
                }

                EditorGUILayout.LabelField("Conditions: ");
                Transition transition = nodeTransition.transition;
                transition.WaitForManualExit = EditorGUILayout.Toggle("WaitForManualExit: ", transition.WaitForManualExit);
                foreach (ITransitionCondition transitionCondition in transition.GetTransitionConditions())
                {
                    EditorGUILayout.BeginVertical(transitionStyle);
                    Type transitionConditionType = transitionCondition.GetType();
                    EditorGUILayout.LabelField(transitionConditionType.Name, EditorStyles.boldLabel);

                    FieldInfo[] fields = TypeUtil.GetInspectorFields(transitionConditionType);
                    foreach (FieldInfo field in fields)
                    {
                        EditorGUILayoutUtil.DynamicField(field, transitionCondition);
                    }
                    EditorGUILayout.EndVertical();
                    EditorGUILayout.Space();
                }

                if (GUILayout.Button("", (GUIStyle)"AddButton", GUILayout.Width(20.0f), GUILayout.Height(20.0f)))
                {
                    GenericMenu nodeDelegateMenu = new GenericMenu();
                    foreach (Type transitionConditionType in TypeUtil.GetImplementationTypes(typeof(ITransitionCondition)))
                    {
                        nodeDelegateMenu.AddItem(new GUIContent(transitionConditionType.Name), false, this.AddTransitionCondition, Tuple.Create(nodeTransition, transitionConditionType));
                    }
                    nodeDelegateMenu.ShowAsContext();
                }
                EditorGUILayout.EndVertical();
                EditorGUILayout.Space();
            }

            if (GUILayout.Button("", (GUIStyle)"AddButton", GUILayout.Width(20.0f), GUILayout.Height(20.0f)))
            {
                this.MakeTransition(node);
            }
            EditorGUILayout.EndVertical();
            EditorGUILayout.Space();
        }