public override void OnGUI(SerializedNodeProperty property, BehaviourMachine.ActionNode node, GUIContent guiContent)
        {
            // Now draw the property as a Slider or an IntSlider based on whether it’s a float or integer.
            if ( property.type != typeof(MinMaxRangeSO) )
            Debug.LogWarning( "Use only with MinMaxRange type" );
            else
            {
                var range = attribute as MinMaxRangeSAttribute;
                var so=(MinMaxRangeSO)property.value;

                //set or reset to default full range
                if(so.rangeStart==so.rangeEnd){
                    so.rangeStart=range.minLimit;
                    so.rangeEnd=range.maxLimit;

                }

                var newMin =so.rangeStart;
                var newMax = so.rangeEnd;

            Rect position=	GUILayoutUtility.GetRect(Screen.width-32f,32f);

            var xDivision = position.width * 0.33f;
            var yDivision = position.height * 0.5f;
            EditorGUI.LabelField( new Rect( position.x, position.y, xDivision, yDivision )
                                 , guiContent );

            EditorGUI.LabelField( new Rect( position.x, position.y + yDivision, position.width, yDivision )
                                 , range.minLimit.ToString( "0.##" ) );
            EditorGUI.LabelField( new Rect( position.x + position.width -28f, position.y + yDivision, position.width, yDivision )
                                 , range.maxLimit.ToString( "0.##" ) );

            EditorGUI.MinMaxSlider( new Rect( position.x + 24f, position.y + yDivision, position.width -48f, yDivision )
                                   , ref newMin, ref newMax, range.minLimit, range.maxLimit );

            EditorGUI.LabelField( new Rect( position.x + xDivision, position.y, xDivision, yDivision )
                                 , "From: " );
            newMin = Mathf.Clamp( EditorGUI.FloatField( new Rect( position.x + xDivision + 30, position.y, xDivision -30, yDivision )
                                                       , newMin )
                                 , range.minLimit, newMax );
            EditorGUI.LabelField( new Rect( position.x + xDivision * 2f, position.y, xDivision, yDivision )
                                 , "To: " );
            newMax = Mathf.Clamp( EditorGUI.FloatField( new Rect( position.x + xDivision * 2f + 24, position.y, xDivision -24, yDivision )
                                                       , newMax )
                                 , newMin, range.maxLimit );

            so.rangeStart = newMin;
            so.rangeEnd = newMax;

                property.ValueChanged();

                property.ApplyModifiedValue();

                property.serializedNode.ApplyModifiedProperties();
            }
        }
        //
        // Methods
        //
        /// <summary>
        /// Handles the onGUI event.
        /// </summary>
        /// <param name="property">Property.</param>
        /// <param name="node">Node.</param>
        /// <param name="guiContent">GUI content.</param>
        public override void OnGUI(SerializedNodeProperty property, ActionNode node, GUIContent guiContent)
        {
            //if (animatorSerialized == null || aniController == null) {
                        if(aniController == null) {

                                //!!! Serialization never serialized Animator cos its initialized in Reset after
            //								NodePropertyIterator iter= property.serializedNode.GetIterator();
            //								iter.Find(attribute.animatorFieldName);
            //								 animatorSerialized=iter.current;
                                //				//								if(animatorSerialized==null || animatorSerialized.value==null){
                                //										Debug.LogError("AnimatorStateNodePropertyDrawer> No Animator component set on node parent GameObject");
                                //									return;
                                //								}

                                //runtimeContoller =( (Animator)animatorSerialized.value).runtimeAnimatorController;
                                Animator animator = node.GetType ().GetField (attribute.animatorFieldName).GetValue (node) as Animator;

                                RuntimeAnimatorController runtimeContoller;

                                runtimeContoller = animator.runtimeAnimatorController;

                                if (runtimeContoller is AnimatorOverrideController)
                                        aniController = ((AnimatorOverrideController)runtimeContoller).runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
                                else
                                        aniController = runtimeContoller as UnityEditor.Animations.AnimatorController;

                        }

                        animatorStateDisplayOptions = MecanimUtility.GetDisplayOptions (aniController);
                        animatorStateValues = MecanimUtility.GetAnimatorStates (aniController);

                        if(property.value!=null){

                            if(animatorStateValues.Length>0){
                                    animatorStateSelectedPrev=animatorStateSelected=animatorStateValues.FirstOrDefault((itm)=>itm.nameHash==((ws.winx.unity.AnimatorState)property.value).nameHash);

                            }
                        }

                        animatorStateSelected = EditorGUILayoutEx.CustomObjectPopup (guiContent, animatorStateSelected, animatorStateDisplayOptions, animatorStateValues);//,compare);

                        //TODO try Begin/End Check
                        if (animatorStateSelectedPrev != animatorStateSelected) {

                                NodePropertyIterator iter = property.serializedNode.GetIterator ();
                                iter.Find (attribute.layerIndexFieldName);
                                SerializedNodeProperty layerIndexSerialized = iter.current;

                                layerIndexSerialized.value = MecanimUtility.GetLayerIndex (aniController, animatorStateSelected);
                                layerIndexSerialized.ApplyModifiedValue ();

                                    ws.winx.unity.AnimatorState state=property.value as ws.winx.unity.AnimatorState;
                                    if(state==null) state=ScriptableObject.CreateInstance<ws.winx.unity.AnimatorState>();

                                    state.motion=animatorStateSelected.motion;
                                    state.nameHash=animatorStateSelected.nameHash;
                                    state.layer=(int)layerIndexSerialized.value;

                                    if(state.motion is UnityEditor.Animations.BlendTree){
                                        BlendTree tree =(BlendTree)state.motion;
                                        int blendParamsNum= tree.GetRecursiveBlendParamCount();

                                        state.blendParamsHashes=new int[blendParamsNum];

                                        for(int i=0;i<blendParamsNum;i++)
                                            state.blendParamsHashes[i]=Animator.StringToHash(tree.GetRecursiveBlendParam(i));

                                    }else{
                                            state.blendParamsHashes=null;
                                    }

                                    //property.value=state;
                                    property.ValueChanged();

                                property.ApplyModifiedValue ();

                                animatorStateSelectedPrev = animatorStateSelected;
                        }

                        if (animatorStateSelected.motion == null)
                                Debug.LogError ("Selected state doesn't have Motion set");
        }
        /// <summary>
        /// Draw the TextArea.
        /// </summary>
        public override void OnGUI (SerializedNodeProperty property, ActionNode node, GUIContent guiContent) {
            // The text to display
            string text;

            // string
            if (property.propertyType == NodePropertyType.String) {
                // Get the text
                text = property.value as string ?? string.Empty;
            }
            // StringVar
            else if (property.propertyType == NodePropertyType.Variable && property.type == typeof(StringVar)) {
                // Get the text
                var stringVar = property.value as StringVar;
                if (stringVar != null)
                    text = stringVar.Value as string ?? string.Empty;
                else
                    text = string.Empty;
            }
            // Not supported
            else {
                EditorGUILayout.LabelField(guiContent, new GUIContent("Use TextAreaAttribute with string or StringVar."));
                return;
            }

            // Create style?
            if (s_Styles == null)
                s_Styles = new NodeTextAreaDrawer.Styles();

            // Get the text area
            var textAreaAttr = (NodeTextAreaAttribute) attribute;

            // Store the current content color
            Color contentColor = GUI.contentColor;

            // The text is empty?
            if (string.IsNullOrEmpty(text)) {
                text = textAreaAttr.hint;
                Color textColor = EditorStyles.label.normal.textColor;
                textColor.a = .5f;
                GUI.contentColor = textColor;
            }

            // Draw the text area.
            EditorGUI.BeginChangeCheck ();


            #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
            string value = EditorGUILayout.TextArea (text, s_Styles.textArea, GUILayout.Height(16f * textAreaAttr.lines));
            #else
            string value = EditorGUILayout.TextArea (text, s_Styles.textArea, GUILayout.Height(EditorGUIUtility.singleLineHeight * textAreaAttr.lines));
            #endif
            

            // Check for changes
            if (EditorGUI.EndChangeCheck ()) {
                if (property.propertyType == NodePropertyType.String)
                    property.value = value;
                else {
                    // Get the text
                    var stringVar = property.value as StringVar;
                    if (stringVar != null) {
                        stringVar.Value = value;
                        property.ValueChanged();
                    }
                }
            }

            // Restore content color
            GUI.contentColor = contentColor;
        }
Exemple #4
0
        /// <summary>
        /// Draws a variable field on the GUI.
        /// <param name= "guiContent">The GUI content to draw the property.</param>
        /// <param name= "property">The variable property.</param>
        /// <param name= "node">The node that owns the variable to be drawn.</param>
        /// </summary>
        public static void VariableField(GUIContent guiContent, SerializedNodeProperty property, ActionNode node)
        {
            var variable   = property.value as Variable;
            var isNone     = variable == null || variable.isNone;
            var isConstant = !isNone && variable.isConstant;
            VariableInfoAttribute variableInfo = property.variableInfo;
            string  popupName    = string.Empty;
            Texture popupTexture = null;


            #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
            var rect = GUILayoutUtility.GetRect(guiContent, EditorStyles.popup);
            #else
            var rect = EditorGUILayout.GetControlRect();
            #endif

            var id = GUIUtility.GetControlID(FocusType.Keyboard);

            // Set label color
            if (isNone && variableInfo.requiredField)
            {
                EditorStyles.label.normal.textColor = Color.red;
            }
            // Draw label
            rect = EditorGUI.PrefixLabel(rect, id, guiContent);
            // Restore label color
            EditorStyles.label.normal.textColor = s_Styles.labelTextColor;

            if (isNone)
            {
                popupName    = variableInfo.nullLabel;
                popupTexture = s_Styles.noneTexture;
            }
            else if (isConstant)
            {
                if (property.isConcreteVariable)
                {
                    popupName    = "Constant";
                    popupTexture = s_Styles.constantTexture;
                }
                else
                {
                    popupName    = variable.GetType().Name;
                    popupTexture = IconUtility.GetIcon(variable.GetType());
                }
            }
            else
            {
                popupName = variable.name;
                // Its a global var?
                popupTexture = variable.isGlobal ? s_Styles.globalBlackboardTexture : popupTexture = s_Styles.blackboardTexture;;
            }

            // Popup button
            if (GUIHelper.EditorButton(rect, id, new GUIContent(popupName, popupTexture), s_Styles.popup))
            {
                // Set keyboard focus to the label
                GUIUtility.keyboardControl = id;
                // Create the menu and the list of unique names
                var menu  = new GenericMenu();
                var names = new List <string>()
                {
                };

                // None
                names.Add(variableInfo.nullLabel);
                menu.AddItem(new GUIContent(variableInfo.nullLabel), isNone, delegate {
                    if (isConstant && property.isConcreteVariable)
                    {
                        variable.SetAsNone();
                        property.ValueChanged();
                    }
                    else if (!isNone)
                    {
                        object noneVariable;
                        if (property.type == typeof(GameObjectVar))
                        {
                            noneVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(property.type), new object[] { node.self });
                        }
                        else if (property.type.IsAbstract)
                        {
                            noneVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(property.type));
                        }
                        else
                        {
                            noneVariable = Activator.CreateInstance(property.type);
                        }
                        property.value = noneVariable;
                    }
                });

                // Create the anonymous function to set constants
                GenericMenu.MenuFunction2 createConstant = delegate(object userData) {
                    // Get the desired variable type
                    var type = userData as System.Type;

                    // its not a constant or its an "ex global" var (an ex global var does not have a GlobalBlackboard)?
                    if (variable == null || variable.isInvalid || property.type == typeof(BehaviourMachine.Variable))
                    {
                        // Create a constant
                        Variable newVariable;
                        if (property.type == typeof(GameObjectVar))
                        {
                            newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type), new object[] { node.self }) as Variable;
                        }
                        else if (type.IsAbstract)
                        {
                            newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type)) as Variable;
                        }
                        else
                        {
                            newVariable = Activator.CreateInstance(type) as Variable;
                        }

                        newVariable.SetAsConstant();
                        property.value = newVariable;
                        property.ValueChanged();
                    }
                    else if (isNone)
                    {
                        variable.SetAsConstant();
                        property.ValueChanged();
                    }
                    else if ((isConstant && !property.isConcreteVariable) || !isConstant)
                    {
                        // Create a concrete variable type and update the field value!
                        Variable newVariable;

                        if (type == typeof(GameObjectVar))
                        {
                            newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type), new object[] { node.self }) as Variable;
                        }
                        else if (type.IsAbstract)
                        {
                            newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type)) as Variable;
                        }
                        else
                        {
                            newVariable = Activator.CreateInstance(type) as Variable;
                        }

                        newVariable.SetAsConstant();
                        property.value = newVariable;
                    }
                };

                // Add the Constant name to the list
                names.Add("Constant");

                // Can be constant?
                if (variableInfo.canBeConstant && property.type != typeof(BehaviourMachine.FsmEvent) && property.type != typeof(BehaviourMachine.DynamicList))
                {
                    if (property.type != typeof(BehaviourMachine.Variable))
                    {
                        menu.AddItem(new GUIContent("Constant"), isConstant && property.isConcreteVariable, createConstant, property.type);
                    }
                    else
                    {
                        bool variableNotNull = variable != null;
                        // If its a Variable type then add options for all concrete variables
                        if (!variableInfo.fixedType)
                        {
                            menu.AddItem(new GUIContent("Constant/Variable"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.Variable), createConstant, typeof(BehaviourMachine.Variable));
                            menu.AddItem(new GUIContent("Constant/FloatVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteFloatVar), createConstant, typeof(BehaviourMachine.ConcreteFloatVar));
                            menu.AddItem(new GUIContent("Constant/IntVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteIntVar), createConstant, typeof(BehaviourMachine.ConcreteIntVar));
                            menu.AddItem(new GUIContent("Constant/BoolVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteBoolVar), createConstant, typeof(BehaviourMachine.ConcreteBoolVar));
                            menu.AddItem(new GUIContent("Constant/StringVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteStringVar), createConstant, typeof(BehaviourMachine.ConcreteStringVar));
                            menu.AddItem(new GUIContent("Constant/Vector3Var"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteVector3Var), createConstant, typeof(BehaviourMachine.ConcreteVector3Var));
                            menu.AddItem(new GUIContent("Constant/RectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteRectVar), createConstant, typeof(BehaviourMachine.ConcreteRectVar));
                            menu.AddItem(new GUIContent("Constant/ColorVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteColorVar), createConstant, typeof(BehaviourMachine.ConcreteColorVar));
                            menu.AddItem(new GUIContent("Constant/QuaternionVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteQuaternionVar), createConstant, typeof(BehaviourMachine.ConcreteQuaternionVar));
                            menu.AddItem(new GUIContent("Constant/GameObjectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteGameObjectVar), createConstant, typeof(BehaviourMachine.ConcreteGameObjectVar));
                            menu.AddItem(new GUIContent("Constant/MaterialVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteMaterialVar), createConstant, typeof(BehaviourMachine.ConcreteMaterialVar));
                            menu.AddItem(new GUIContent("Constant/TextureVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteTextureVar), createConstant, typeof(BehaviourMachine.ConcreteTextureVar));
                            menu.AddItem(new GUIContent("Constant/ObjectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteObjectVar), createConstant, typeof(BehaviourMachine.ConcreteObjectVar));
                        }
                        else if (variable != null)
                        {
                            // Get the base type
                            System.Type baseType = BehaviourMachine.TypeUtility.GetBaseType(variable.GetType());
                            if (baseType == typeof(Variable))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.Variable), createConstant, typeof(BehaviourMachine.Variable));
                            }
                            else if (baseType == typeof(FloatVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteFloatVar), createConstant, typeof(BehaviourMachine.ConcreteFloatVar));
                            }
                            else if (baseType == typeof(IntVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteIntVar), createConstant, typeof(BehaviourMachine.ConcreteIntVar));
                            }
                            else if (baseType == typeof(BoolVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteBoolVar), createConstant, typeof(BehaviourMachine.ConcreteBoolVar));
                            }
                            else if (baseType == typeof(StringVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteStringVar), createConstant, typeof(BehaviourMachine.ConcreteStringVar));
                            }
                            else if (baseType == typeof(Vector3Var))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteVector3Var), createConstant, typeof(BehaviourMachine.ConcreteVector3Var));
                            }
                            else if (baseType == typeof(RectVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteRectVar), createConstant, typeof(BehaviourMachine.ConcreteRectVar));
                            }
                            else if (baseType == typeof(ColorVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteColorVar), createConstant, typeof(BehaviourMachine.ConcreteColorVar));
                            }
                            else if (baseType == typeof(QuaternionVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteQuaternionVar), createConstant, typeof(BehaviourMachine.ConcreteQuaternionVar));
                            }
                            else if (baseType == typeof(GameObjectVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteGameObjectVar), createConstant, typeof(BehaviourMachine.ConcreteGameObjectVar));
                            }
                            else if (baseType == typeof(MaterialVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteMaterialVar), createConstant, typeof(BehaviourMachine.ConcreteMaterialVar));
                            }
                            else if (baseType == typeof(TextureVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteTextureVar), createConstant, typeof(BehaviourMachine.ConcreteTextureVar));
                            }
                            else if (baseType == typeof(ObjectVar))
                            {
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteObjectVar), createConstant, typeof(BehaviourMachine.ConcreteObjectVar));
                            }
                        }
                    }
                }
                else
                {
                    menu.AddDisabledItem(new GUIContent("Constant"));
                }

                // Custom variables
                if (property.type != null)
                {
                    System.Type[] customVars = CustomVariableUtility.GetCustomVariables(variableInfo.fixedType && variable != null ? BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()) : property.type);

                    // if (customVars.Length > 0) {
                    //     menu.AddSeparator(string.Empty);
                    // }

                    for (int i = 0; i < customVars.Length; i++)
                    {
                        // Get the type of the custom variable
                        System.Type customVarType = customVars[i];
                        // Get a unique name
                        string uniqueName = StringHelper.GetUniqueNameInList(names, "Custom/" + customVarType.Name);
                        names.Add(uniqueName);
                        // Add to the menu
                        menu.AddItem(new GUIContent(uniqueName), isConstant && variable != null && variable.GetType() == customVarType, delegate {
                            try {
                                var newVariable = Activator.CreateInstance(customVarType, new object[] { node.self }) as Variable;
                                if (newVariable != null)
                                {
                                    newVariable.SetAsConstant();
                                    property.value = newVariable;
                                }
                            }
                            catch (Exception e) {
                                Print.LogError(e.ToString());
                            }
                        });
                    }
                }

                // Boolean used to know if the variables separator was already added to the menu.
                bool separatorAdded = false;

                // Blackboard variables
                var variables = node.self.GetComponent <InternalBlackboard>().GetVariables(variable != null && variableInfo.fixedType ? BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()) : property.type);

                // Add separator?
                if (variables.Count > 0)
                {
                    menu.AddSeparator(string.Empty);
                    separatorAdded = true;
                }

                // Blackboard variables
                for (int i = 0; i < variables.Count; i++)
                {
                    var v    = variables[i];
                    var name = StringHelper.GetUniqueNameInList(names, v.name);
                    names.Add(name);
                    menu.AddItem(new GUIContent(name), variable == v, delegate { property.value = v; });
                }

                // Global variables
                if (InternalGlobalBlackboard.Instance != null)
                {
                    var globalVariables = InternalGlobalBlackboard.Instance.GetVariables(property.type);

                    // Add separator?
                    if (!separatorAdded && globalVariables.Count > 0)
                    {
                        menu.AddSeparator(string.Empty);
                        separatorAdded = true;
                    }

                    for (int i = 0; i < globalVariables.Count; i++)
                    {
                        var v    = globalVariables[i];
                        var name = StringHelper.GetUniqueNameInList(names, "Global/" + v.name);
                        names.Add(name);
                        menu.AddItem(new GUIContent(name), variable == v, delegate { property.value = v; });
                    }
                }

                // Show menu
                menu.DropDown(rect);
                // Set GUI as not changed
                GUI.changed = false;
            }

            // Draw constant properties
            if (isConstant)
            {
                // Get children
                var children = property.children;

                // The variable is an ObjectVar?
                var         objectVar = variable as ObjectVar;
                System.Type objType   = objectVar != null ? objectVar.ObjectType : null;

                // Draw properties
                if (children.Length > 0)
                {
                    EditorGUI.indentLevel++;

                    if (property.isConcreteVariable)
                    {
                        for (int i = 0; i < children.Length; i++)
                        {
                            SerializedNodeProperty childProperty = children[i];
                            if (!childProperty.hideInInspector)
                            {
                                if (childProperty.propertyType == NodePropertyType.Vector3 || childProperty.propertyType == NodePropertyType.Quaternion || childProperty.propertyType == NodePropertyType.Vector2)
                                {
                                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                                    GUILayout.Space(-20f);
                                    EditorGUI.indentLevel--;
                                    #endif

                                    DrawNodeProperty(GUIContent.none, childProperty, node, objType);

                                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                                    EditorGUI.indentLevel++;
                                    #endif
                                }
                                else if (childProperty.propertyType == NodePropertyType.Rect)
                                {
                                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                                    GUILayout.Space(-20f);
                                    EditorGUI.indentLevel--;
                                    #endif

                                    DrawNodeProperty(GUIContent.none, childProperty, node, objType);

                                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                                    GUILayout.Space(20f);
                                    EditorGUI.indentLevel++;
                                    #endif
                                }
                                else
                                {
                                    DrawNodeProperty(new GUIContent(childProperty.label, childProperty.tooltip), childProperty, node, objType);
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < children.Length; i++)
                        {
                            SerializedNodeProperty childProperty = children[i];
                            if (!childProperty.hideInInspector)
                            {
                                DrawNodeProperty(new GUIContent(childProperty.label, childProperty.tooltip), childProperty, node, objType);
                            }
                        }
                    }

                    EditorGUI.indentLevel--;
                }
            }
        }
        /// <summary>
        /// Draw the TextArea.
        /// </summary>
        public override void OnGUI(SerializedNodeProperty property, ActionNode node, GUIContent guiContent)
        {
            // The text to display
            string text;

            // string
            if (property.propertyType == NodePropertyType.String)
            {
                // Get the text
                text = property.value as string ?? string.Empty;
            }
            // StringVar
            else if (property.propertyType == NodePropertyType.Variable && property.type == typeof(StringVar))
            {
                // Get the text
                var stringVar = property.value as StringVar;
                if (stringVar != null)
                {
                    text = stringVar.Value as string ?? string.Empty;
                }
                else
                {
                    text = string.Empty;
                }
            }
            // Not supported
            else
            {
                EditorGUILayout.LabelField(guiContent, new GUIContent("Use TextAreaAttribute with string or StringVar."));
                return;
            }

            // Create style?
            if (s_Styles == null)
            {
                s_Styles = new NodeTextAreaDrawer.Styles();
            }

            // Get the text area
            var textAreaAttr = (NodeTextAreaAttribute)attribute;

            // Store the current content color
            Color contentColor = GUI.contentColor;

            // The text is empty?
            if (string.IsNullOrEmpty(text))
            {
                text = textAreaAttr.hint;
                Color textColor = EditorStyles.label.normal.textColor;
                textColor.a      = .5f;
                GUI.contentColor = textColor;
            }

            // Draw the text area.
            EditorGUI.BeginChangeCheck();


            #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
            string value = EditorGUILayout.TextArea(text, s_Styles.textArea, GUILayout.Height(16f * textAreaAttr.lines));
            #else
            string value = EditorGUILayout.TextArea(text, s_Styles.textArea, GUILayout.Height(EditorGUIUtility.singleLineHeight * textAreaAttr.lines));
            #endif


            // Check for changes
            if (EditorGUI.EndChangeCheck())
            {
                if (property.propertyType == NodePropertyType.String)
                {
                    property.value = value;
                }
                else
                {
                    // Get the text
                    var stringVar = property.value as StringVar;
                    if (stringVar != null)
                    {
                        stringVar.Value = value;
                        property.ValueChanged();
                    }
                }
            }

            // Restore content color
            GUI.contentColor = contentColor;
        }
        /// <summary>
        /// Draws a variable field on the GUI.
        /// <param name= "guiContent">The GUI content to draw the property.</param>
        /// <param name= "property">The variable property.</param>
        /// <param name= "node">The node that owns the variable to be drawn.</param>
        /// </summary>
        public static void VariableField (GUIContent guiContent, SerializedNodeProperty property, ActionNode node) {
            var variable = property.value as Variable;
            var isNone = variable == null || variable.isNone;
            var isConstant = !isNone && variable.isConstant;
            VariableInfoAttribute variableInfo = property.variableInfo;
            string popupName = string.Empty;
            Texture popupTexture = null;


            #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
            var rect = GUILayoutUtility.GetRect(guiContent, EditorStyles.popup);
            #else
            var rect = EditorGUILayout.GetControlRect();
            #endif

            var id = GUIUtility.GetControlID(FocusType.Keyboard);

            // Set label color
            if (isNone && variableInfo.requiredField)
                EditorStyles.label.normal.textColor = Color.red;
            // Draw label
            rect = EditorGUI.PrefixLabel(rect, id, guiContent);
            // Restore label color
            EditorStyles.label.normal.textColor = s_Styles.labelTextColor;
                
            if (isNone) {
                popupName = variableInfo.nullLabel;
                popupTexture = s_Styles.noneTexture;
            }
            else if (isConstant) {
                if (property.isConcreteVariable) {
                    popupName = "Constant";
                    popupTexture = s_Styles.constantTexture;
                }
                else {
                    popupName = variable.GetType().Name;
                    popupTexture = IconUtility.GetIcon(variable.GetType());
                }
            }
            else {
                popupName = variable.name;
                // Its a global var?
                popupTexture = variable.isGlobal ? s_Styles.globalBlackboardTexture : popupTexture = s_Styles.blackboardTexture;;
            }

            // Popup button
            if (GUIHelper.EditorButton(rect, id, new GUIContent(popupName, popupTexture), s_Styles.popup)) {
                // Set keyboard focus to the label
                GUIUtility.keyboardControl = id;
                // Create the menu and the list of unique names
                var menu = new GenericMenu();
                var names = new List<string>() {};

                // None
                names.Add(variableInfo.nullLabel);
                menu.AddItem(new GUIContent(variableInfo.nullLabel), isNone , delegate {
                    if (isConstant && property.isConcreteVariable) {
                        variable.SetAsNone();
                        property.ValueChanged();
                    }
                    else if (!isNone) {
                        object noneVariable;
                        if (property.type == typeof(GameObjectVar))
                            noneVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(property.type), new object[] {node.self});
                        else if (property.type.IsAbstract)
                            noneVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(property.type));
                        else
                            noneVariable = Activator.CreateInstance(property.type);
                        property.value = noneVariable;
                    }
                });

                // Create the anonymous function to set constants
                GenericMenu.MenuFunction2 createConstant = delegate (object userData) {
                    // Get the desired variable type
                    var type = userData as System.Type;
                    
                    // its not a constant or its an "ex global" var (an ex global var does not have a GlobalBlackboard)?
                    if (variable == null || variable.isInvalid || property.type == typeof(BehaviourMachine.Variable)) {
                        // Create a constant
                        Variable newVariable;
                        if (property.type == typeof(GameObjectVar))
                            newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type), new object[] {node.self}) as Variable;
                        else if (type.IsAbstract)
                            newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type)) as Variable;
                        else
                            newVariable = Activator.CreateInstance(type) as Variable;

                        newVariable.SetAsConstant();
                        property.value = newVariable;
                        property.ValueChanged();
                    }
                    else if (isNone) {
                        variable.SetAsConstant();
                        property.ValueChanged();
                    }
                    else if ((isConstant && !property.isConcreteVariable) || !isConstant) {
                        // Create a concrete variable type and update the field value!
                        Variable newVariable;
                        
                        if (type == typeof(GameObjectVar))
                            newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type), new object[] {node.self}) as Variable;
                        else if (type.IsAbstract)
                            newVariable = Activator.CreateInstance(TypeUtility.GetConcreteType(type)) as Variable;
                        else
                            newVariable = Activator.CreateInstance(type) as Variable;
                        
                        newVariable.SetAsConstant();
                        property.value = newVariable;
                    }
                };

                // Add the Constant name to the list
                names.Add("Constant");

                // Can be constant?
                if (variableInfo.canBeConstant && property.type != typeof(BehaviourMachine.FsmEvent) && property.type != typeof(BehaviourMachine.DynamicList)) {
                    if (property.type != typeof(BehaviourMachine.Variable)) {
                        menu.AddItem(new GUIContent("Constant"), isConstant && property.isConcreteVariable, createConstant, property.type);
                    }
                    else {
                        bool variableNotNull = variable != null;
                        // If its a Variable type then add options for all concrete variables
                        if (!variableInfo.fixedType) {
                            menu.AddItem(new GUIContent("Constant/Variable"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.Variable), createConstant, typeof(BehaviourMachine.Variable));
                            menu.AddItem(new GUIContent("Constant/FloatVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteFloatVar), createConstant, typeof(BehaviourMachine.ConcreteFloatVar));
                            menu.AddItem(new GUIContent("Constant/IntVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteIntVar), createConstant, typeof(BehaviourMachine.ConcreteIntVar));
                            menu.AddItem(new GUIContent("Constant/BoolVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteBoolVar), createConstant, typeof(BehaviourMachine.ConcreteBoolVar));
                            menu.AddItem(new GUIContent("Constant/StringVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteStringVar), createConstant, typeof(BehaviourMachine.ConcreteStringVar));
                            menu.AddItem(new GUIContent("Constant/Vector3Var"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteVector3Var), createConstant, typeof(BehaviourMachine.ConcreteVector3Var));
                            menu.AddItem(new GUIContent("Constant/RectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteRectVar), createConstant, typeof(BehaviourMachine.ConcreteRectVar));
                            menu.AddItem(new GUIContent("Constant/ColorVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteColorVar), createConstant, typeof(BehaviourMachine.ConcreteColorVar));
                            menu.AddItem(new GUIContent("Constant/QuaternionVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteQuaternionVar), createConstant, typeof(BehaviourMachine.ConcreteQuaternionVar));
                            menu.AddItem(new GUIContent("Constant/GameObjectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteGameObjectVar), createConstant, typeof(BehaviourMachine.ConcreteGameObjectVar));
                            menu.AddItem(new GUIContent("Constant/MaterialVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteMaterialVar), createConstant, typeof(BehaviourMachine.ConcreteMaterialVar));
                            menu.AddItem(new GUIContent("Constant/TextureVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteTextureVar), createConstant, typeof(BehaviourMachine.ConcreteTextureVar));
                            menu.AddItem(new GUIContent("Constant/ObjectVar"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteObjectVar), createConstant, typeof(BehaviourMachine.ConcreteObjectVar));
                        }
                        else if (variable != null) {
                            // Get the base type
                            System.Type baseType = BehaviourMachine.TypeUtility.GetBaseType(variable.GetType());
                            if (baseType == typeof(Variable))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.Variable), createConstant, typeof(BehaviourMachine.Variable));
                            else if (baseType == typeof(FloatVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteFloatVar), createConstant, typeof(BehaviourMachine.ConcreteFloatVar));
                            else if (baseType == typeof(IntVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteIntVar), createConstant, typeof(BehaviourMachine.ConcreteIntVar));
                            else if (baseType == typeof(BoolVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteBoolVar), createConstant, typeof(BehaviourMachine.ConcreteBoolVar));
                            else if (baseType == typeof(StringVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteStringVar), createConstant, typeof(BehaviourMachine.ConcreteStringVar));
                            else if (baseType == typeof(Vector3Var))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteVector3Var), createConstant, typeof(BehaviourMachine.ConcreteVector3Var));
                            else if (baseType == typeof(RectVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteRectVar), createConstant, typeof(BehaviourMachine.ConcreteRectVar));
                            else if (baseType == typeof(ColorVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteColorVar), createConstant, typeof(BehaviourMachine.ConcreteColorVar));
                            else if (baseType == typeof(QuaternionVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteQuaternionVar), createConstant, typeof(BehaviourMachine.ConcreteQuaternionVar));
                            else if (baseType == typeof(GameObjectVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteGameObjectVar), createConstant, typeof(BehaviourMachine.ConcreteGameObjectVar));
                            else if (baseType == typeof(MaterialVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteMaterialVar), createConstant, typeof(BehaviourMachine.ConcreteMaterialVar));
                            else if (baseType == typeof (TextureVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteTextureVar), createConstant, typeof(BehaviourMachine.ConcreteTextureVar));
                            else if (baseType == typeof (ObjectVar))
                                menu.AddItem(new GUIContent("Constant"), isConstant && variableNotNull && variable.GetType() == typeof(BehaviourMachine.ConcreteObjectVar), createConstant, typeof(BehaviourMachine.ConcreteObjectVar));
                        }
                    }
                }
                else {
                    menu.AddDisabledItem(new GUIContent("Constant"));
                }

                // Custom variables
                if (property.type != null) {
                    System.Type[] customVars = CustomVariableUtility.GetCustomVariables(variableInfo.fixedType && variable != null ? BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()) : property.type);

                    // if (customVars.Length > 0) {
                    //     menu.AddSeparator(string.Empty);
                    // }

                    for (int i = 0; i < customVars.Length; i++) {
                        // Get the type of the custom variable
                        System.Type customVarType = customVars[i];
                        // Get a unique name
                        string uniqueName = StringHelper.GetUniqueNameInList(names, "Custom/" + customVarType.Name);
                        names.Add(uniqueName);
                        // Add to the menu
                        menu.AddItem(new GUIContent(uniqueName), isConstant && variable != null && variable.GetType() == customVarType, delegate {
                            try {
                                var newVariable = Activator.CreateInstance(customVarType, new object[] {node.self}) as Variable;
                                if (newVariable != null) {
                                    newVariable.SetAsConstant();
                                    property.value = newVariable;
                                }
                            }
                            catch (Exception e) {
                                Print.LogError(e.ToString());
                            }
                        });
                    }
                }

                // Boolean used to know if the variables separator was already added to the menu.
                bool separatorAdded = false;

                // Blackboard variables
                var variables = node.self.GetComponent<InternalBlackboard>().GetVariables(variable != null && variableInfo.fixedType ? BehaviourMachine.TypeUtility.GetBaseType(variable.GetType()) : property.type);

                // Add separator?
                if (variables.Count > 0) {
                    menu.AddSeparator(string.Empty);
                    separatorAdded = true;
                }

                // Blackboard variables
                for (int i = 0; i < variables.Count; i++) {
                    var v = variables[i];
                    var name = StringHelper.GetUniqueNameInList(names, v.name);
                    names.Add(name);
                    menu.AddItem(new GUIContent(name), variable == v , delegate {property.value = v;});
                }

                // Global variables
                if (InternalGlobalBlackboard.Instance != null) {
                    var globalVariables = InternalGlobalBlackboard.Instance.GetVariables(property.type);

                    // Add separator?
                    if (!separatorAdded && globalVariables.Count > 0) {
                        menu.AddSeparator(string.Empty);
                        separatorAdded = true;
                    }

                    for (int i = 0; i < globalVariables.Count; i++) {
                        var v = globalVariables[i];
                        var name = StringHelper.GetUniqueNameInList(names, "Global/" + v.name);
                        names.Add(name);
                        menu.AddItem(new GUIContent(name), variable == v ,  delegate {property.value = v;});
                    }
                }

                // Show menu
                menu.DropDown(rect);
                // Set GUI as not changed
                GUI.changed = false;
            }

            // Draw constant properties
            if (isConstant) {
                // Get children
                var children = property.children;

                // The variable is an ObjectVar?
                var objectVar = variable as ObjectVar;
                System.Type objType = objectVar != null ? objectVar.ObjectType : null;

                // Draw properties
                if (children.Length > 0) {
                    EditorGUI.indentLevel++;

                    if (property.isConcreteVariable) {
                        for (int i = 0; i < children.Length; i++) {
                            SerializedNodeProperty childProperty = children[i];
                            if (!childProperty.hideInInspector) {
                                if (childProperty.propertyType == NodePropertyType.Vector3 || childProperty.propertyType == NodePropertyType.Quaternion || childProperty.propertyType == NodePropertyType.Vector2) {
                                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                                    GUILayout.Space(-20f);
                                    EditorGUI.indentLevel--;
                                    #endif
                                    
                                    DrawNodeProperty(GUIContent.none, childProperty, node, objType);
                                    
                                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                                    EditorGUI.indentLevel++;
                                    #endif
                                }
                                else if (childProperty.propertyType == NodePropertyType.Rect) {
                                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                                    GUILayout.Space(-20f);
                                    EditorGUI.indentLevel--;
                                    #endif
                                   
                                    DrawNodeProperty(GUIContent.none, childProperty, node, objType);
                                   
                                    #if UNITY_4_0_0 || UNITY_4_1 || UNITY_4_2
                                    GUILayout.Space(20f);
                                    EditorGUI.indentLevel++;
                                    #endif
                                }
                                else
                                    DrawNodeProperty(new GUIContent(childProperty.label, childProperty.tooltip), childProperty, node, objType);
                            }
                        }
                    }
                    else {
                        for (int i = 0; i < children.Length; i++) {
                            SerializedNodeProperty childProperty = children[i];
                            if (!childProperty.hideInInspector)
                                DrawNodeProperty(new GUIContent(childProperty.label, childProperty.tooltip), childProperty, node, objType);
                        }
                    }
                    
                    EditorGUI.indentLevel--;
                }
            }
        }