private bool _has_method_parameters = false; //If the variable is binded with a method without input parameters, the input selection menu is blocked

        //Constructors ====================
        public Variable_GS_Editor(Variable_GS new_variable, Blackboard_GS new_bb)
        {
            //Set target variable
            _target_variable = new_variable;
            //Set target bb
            _target_blackboard = new_bb;
            //Initialize dropdowns data
            _variable_dropdown_data = new ProTools.DropDownData_GS();
            _method_dropdown_data   = new ProTools.DropDownData_GS();
            //Check for binded method parameters
            if (string.IsNullOrEmpty(_target_variable.binded_method_path) == false)
            {
                _has_method_parameters = ProTools.FindMethodFromPath(_target_variable.binded_method_path, _target_variable.system_type, _target_blackboard.target_agent.gameObject).Key.GetParameters().Length > 0;
            }
        }
        //Functionality Methods =======
        protected void SetGoal(string variable_name, OperatorType operator_type, object variable_value, VariableLocation location = VariableLocation._local)
        {
            //First check if the variable exists in the current world state
            Variable_GS target_variable = null;

            if (location == VariableLocation._local)
            {
                target_variable = _agent.blackboard.GetObjectVariable(variable_name);
            }
            else
            {
                target_variable = GlobalBlackboard_GS.blackboard.GetObjectVariable(variable_name);
            }

            if (target_variable == null)
            {
                //In null case goal set is cancelled
                Debug.LogError("Variable: " + variable_name + " does not exist and can't be setted as goal");
                return;
            }

            //Check of the new goal value uses the correct type
            if (variable_value.GetType() != target_variable.value.GetType())
            {
                //In different types case the goal is not valid
                Debug.LogError("Behaviour " + _name + " is trying to set a " + variable_value.GetType() + "goal to a " + target_variable.value.GetType() + "variable");
                return;
            }

            string prefixed_name = (location == VariableLocation._local ? "Local/" : "Global/") + variable_name;

            //Check if the new goal is already defined in the goal world state
            Property_GS already_existing_property = null;

            if (agent.goal_world_state.properties.TryGetValue(prefixed_name, out already_existing_property))
            {
                //If the goal already exists we only change the goal value
                already_existing_property.value = variable_value;
            }
            else
            {
                //In correct and new goal case we simply add it to the goal world state
                agent.goal_world_state.SetGoal(prefixed_name, new Property_GS(prefixed_name, variable_value.GetType().ToVariableType(), operator_type, variable_value, target_variable.planning_value));
            }
        }
        //Functionality methods ===========
        public void AddVariableEditor(Variable_GS new_variable)
        {
            //Check if we need to allocate more items in the array
            if (_variable_editors_num == _variable_editors.Length)
            {
                //Double array capacity
                Variable_GS_Editor[] new_array = new Variable_GS_Editor[_variable_editors_num * 2];
                //Copy values
                for (int k = 0; k < _variable_editors_num; k++)
                {
                    new_array[k] = _variable_editors[k];
                }
                _variable_editors = new_array;
            }

            //Generate new variable editor
            Variable_GS_Editor new_variable_editor = new Variable_GS_Editor(new_variable, _target_blackboard);

            //Add it to the array
            _variable_editors[_variable_editors_num] = new_variable_editor;
            //Update variable editors num
            _variable_editors_num += 1;
        }
        //Loop Methods ================
        public override void OnGUI(Rect rect)
        {
            //Menu title
            GUILayout.BeginHorizontal("Box");
            GUILayout.FlexibleSpace();
            GUILayout.Label("Variable Select", UIConfig_GS.Instance.select_menu_title_style, GUILayout.ExpandWidth(true));
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            //Separator
            EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);

            //Variable name field
            GUILayout.BeginHorizontal();
            GUILayout.Label("Name", GUILayout.ExpandWidth(true));
            _variable_name = EditorGUILayout.TextField(_variable_name, GUILayout.ExpandWidth(true));
            GUILayout.EndHorizontal();

            //Variable type field
            GUILayout.BeginHorizontal();
            GUILayout.Label("Type", GUILayout.ExpandWidth(true));
            VariableType current_type = _variable_type;

            _variable_type = (VariableType)EditorGUILayout.EnumPopup(_variable_type, GUILayout.Width(150), GUILayout.ExpandWidth(true));
            //Check if var type is changed
            if (current_type != _variable_type)
            {
                //Allocate value from variable type
                ProTools.AllocateFromVariableType(_variable_type, ref _variable_value);

                //Get all the properties in the agent gameobject
                PropertyInfo[] _properties_info = ProTools.FindConcretePropertiesInGameObject(NodeEditor_GS.Instance.selected_agent.gameObject, _variable_type.ToSystemType());
                //Get all fields in th agent gameobject
                FieldInfo[] _fields_info = ProTools.FindConcreteFieldsInGameObject(NodeEditor_GS.Instance.selected_agent.gameObject, _variable_type.ToSystemType());

                //Allocate strings arrays
                _variable_dropdown_data.paths         = new string[_properties_info.Length + _fields_info.Length];
                _variable_dropdown_data.display_paths = new string[_properties_info.Length + _fields_info.Length];
                //Generate properties paths
                for (int k = 0; k < _properties_info.Length; k++)
                {
                    _variable_dropdown_data.paths[k]         = string.Format("{0}.{1}", _properties_info[k].ReflectedType.FullName, _properties_info[k].Name);
                    _variable_dropdown_data.display_paths[k] = _variable_dropdown_data.paths[k].Replace('.', '/');
                }
                //Generate fields paths
                int fields_k = 0; //Index to iterate fields info array
                for (int k = _properties_info.Length; k < _properties_info.Length + _fields_info.Length; k++)
                {
                    _variable_dropdown_data.paths[k]         = string.Format("{0}.{1}", _fields_info[fields_k].ReflectedType.FullName, _fields_info[fields_k].Name);
                    _variable_dropdown_data.display_paths[k] = _variable_dropdown_data.paths[k].Replace('.', '/');
                    fields_k += 1;//Update fields index
                }
            }
            GUILayout.EndHorizontal();

            //Custom field value
            if (_variable_type != VariableType._undefined_var_type)
            {
                GUILayout.BeginVertical();

                //Show variable value or info label if the variable is binded
                if (_variable_dropdown_data.selected_index != -1)
                {
                    GUILayout.Label("Value=" + bind_selected_display_path, UIConfig_GS.Instance.node_elements_style, GUILayout.ExpandWidth(true));
                }
                else
                {
                    //Define horizontal area
                    GUILayout.BeginHorizontal(GUILayout.MaxWidth(150.0f));

                    //Value label
                    GUILayout.Label("Value", GUILayout.MaxWidth(40.0f));

                    //Generate an input field adapted to the type of the variable
                    ProTools.ValueFieldByVariableType(_variable_type, ref _variable_value);

                    GUILayout.EndHorizontal();
                }

                //Bind variable
                GUILayout.BeginHorizontal();
                //Generate bind selection dropdown

                /*ProTools.GenerateButtonDropdownMenu(ref _variable_dropdown_data.selected_index, _variable_dropdown_data.display_paths, "Bind", false, 90.0f, _variable_dropdown_data.dropdown_slot);
                 * //UnBind button
                 * if (GUILayout.Button("UnBind"))
                 * {
                 *  //Reset variable dropdown
                 *  ProTools.SetDropdownIndex(_variable_dropdown_data.dropdown_slot, -1);
                 * }
                 * GUILayout.EndHorizontal();
                 *
                 * //Show selected bind path
                 * if (_variable_dropdown_data.selected_index == -1) GUILayout.Label(bind_selected_display_path);*/

                GUILayout.EndVertical();
            }

            //Separation
            GUILayout.FlexibleSpace();

            GUILayout.BeginHorizontal();
            //Add button
            if (GUILayout.Button("Add", UIConfig_GS.Instance.node_modify_button_style, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)))
            {
                //Add the new variable if the data is correct
                if (!string.IsNullOrEmpty(_variable_name) && _variable_type != VariableType._undefined_var_type && _variable_value != null)
                {
                    //Send info to the bb to generate the variable
                    Variable_GS new_variable = null;
                    //Local case
                    if (_global_blackboard == false)
                    {
                        new_variable = NodeEditor_GS.Instance.selected_agent.blackboard.AddVariable(_variable_name, _variable_type, _variable_value);
                    }
                    //Global case
                    else
                    {
                        new_variable = GlobalBlackboard_GS.blackboard.AddVariable(_variable_name, _variable_type, _variable_value);
                    }

                    //If add var return null is because the name is invalid(exists a variable with the same name)
                    if (new_variable != null)
                    {
                        //Check if var have to be bind
                        if (_variable_dropdown_data.selected_index != -1)
                        {
                            //Bind new variable
                            new_variable.BindField(_variable_dropdown_data.paths[_variable_dropdown_data.selected_index]);
                        }
                        //Send the new variable to the blackboard editor to generate the variable editor
                        //Local case
                        if (_global_blackboard == false)
                        {
                            NodeEditor_GS.Instance.blackboard_editor.AddVariableEditor(new_variable);
                        }
                        //Global case
                        else
                        {
                            GlobalBlackboard_GS_Editor.blackboard_editor.AddVariableEditor(new_variable);
                        }
                        //Close this popup and updat bb window
                        editorWindow.Close();
                        NodeEditor_GS.Instance.Repaint();
                    }
                    else
                    {
                        //Add a rep prefix to the variable name, so the user can see that the name is repeated
                        _variable_name = "Rep:" + _variable_name;
                    }
                }
            }
            //Close button
            if (GUILayout.Button("Close", UIConfig_GS.Instance.node_modify_button_style, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)))
            {
                editorWindow.Close();
            }
            GUILayout.EndHorizontal();
        }
        //Constructor =================
        public MethodSelectMenu_GS(Variable_GS target_variable)
        {
            //Set the target variable
            _target_variable = target_variable;
            //Get method info
            _target_method = ProTools.FindMethodFromPath(_target_variable.binded_method_path, target_variable.system_type, NodeEditor_GS.Instance.selected_agent.gameObject).Key;
            //Get method parameters
            method_parameters = _target_method.GetParameters();
            //Allocate input array in null case
            if (_target_variable.binded_method_input == null)
            {
                _target_variable.binded_method_input = new KeyValuePair <string, object> [method_parameters.Length];
                //Allocate input data from type

                for (int k = 0; k < method_parameters.Length; k++)
                {
                    KeyValuePair <string, object> input = _target_variable.binded_method_input[k];
                    if (string.IsNullOrEmpty(input.Key) && input.Value == null)
                    {
                        object temp_value = new object();
                        ProTools.AllocateFromVariableType(method_parameters[k].ParameterType.ToVariableType(), ref temp_value);
                        _target_variable.binded_method_input[k] = new KeyValuePair <string, object>("", temp_value);
                    }
                }
            }
            //Allocate editor values and dropdowns
            local_values    = new object[method_parameters.Length];
            input_dropdowns = new ProTools.DropDownData_GS[method_parameters.Length];
            for (int k = 0; k < method_parameters.Length; k++)
            {
                //Initialize local value
                if (_target_variable.binded_method_input[k].Value != null)
                {
                    local_values[k] = _target_variable.binded_method_input[k].Value;
                }
                else
                {
                    ProTools.AllocateFromVariableType(method_parameters[k].ParameterType.ToVariableType(), ref local_values[k]);
                }

                //Generate the new dropdown data
                ProTools.DropDownData_GS new_dropdown = new ProTools.DropDownData_GS();
                new_dropdown.dropdown_slot = ProTools.GetDropdownSlot();

                //Get local and global variables
                string[] local_keys  = NodeEditor_GS.Instance.selected_agent.blackboard.GetKeysByVariableType(method_parameters[k].ParameterType.ToVariableType());
                string[] global_keys = GlobalBlackboard_GS.blackboard.GetKeysByVariableType(method_parameters[k].ParameterType.ToVariableType());

                //Generate dropdown paths
                new_dropdown.paths         = new string[local_keys.Length + global_keys.Length];
                new_dropdown.display_paths = new string[local_keys.Length + global_keys.Length];

                //Add the local keys with a prefix for the dropdown
                for (int j = 0; j < local_keys.Length; j++)
                {
                    new_dropdown.display_paths[j] = "Local/" + local_keys[j];
                    new_dropdown.paths[j]         = local_keys[j];
                }

                //Add the global keys with a prefix for the dropdown
                for (int j = local_keys.Length, s = 0; j < new_dropdown.paths.Length; j++, s++)
                {
                    new_dropdown.display_paths[j] = "Global/" + global_keys[s];
                    new_dropdown.paths[j]         = global_keys[s];
                }

                //Add the generated dropdown
                input_dropdowns[k] = new_dropdown;
            }
        }