Ejemplo n.º 1
0
    private int m_TargetId  = 0;        // id of the last modified state (for triggering enable / disable callbacks)


    /// <summary>
    /// manages a list of states and corresponding presets for a
    /// component. loads the presets into memory on startup, and
    /// allows applying them from memory to the component.
    /// states are enabled in a layered manner, that is: the
    /// default state is always alive, and any enabled states are
    /// applied on top of it in the order of which they were enabled.
    ///
    /// this class doesn't store any preset data between sessions.
    /// it is merely used to manipulate the component using a list
    /// of states that is sent along at startup. it is very silent
    /// and forgiving; it won't complain if a state isn't found
    /// (since providing a certain state should not be considered
    /// mandatory for a component, and states can be set recursively).
    /// it will also ignore empty presets
    /// </summary>
    public vp_AIStateManager(vp_AIComponent component, List <vp_AIState> states)
    {
        m_States    = states;
        m_Component = component;

        // create default state and add it to the list
        m_Component.RefreshDefaultState();

        // refresh the initial state, needed for being able to save
        // partial presets in the editor
#if UNITY_EDITOR
        m_Component.RefreshInitialState();
#endif

        // load states and initialize the state id dictionary
        m_StateIds = new Dictionary <string, int>(System.StringComparer.CurrentCulture);
        foreach (vp_AIState s in m_States)
        {
            s.StateManager = this;

            // store the name and list index of each state in a dictionary for
            // fast lookup. IMPORTANT: the state list (m_States) must never be
            // modified at runtime (i.e. have states reordered, added, renamed
            // or removed) or the dictionary (m_StateIds) will be out of date
            if (!m_StateIds.ContainsKey(s.Name))
            {
                m_StateIds.Add(s.Name, m_States.IndexOf(s));
            }
            else
            {
                Debug.LogWarning("Warning: " + m_Component.GetType() + " on '" + m_Component.name + "' has more than one state named: '" + s.Name + "'. Only the topmost one will be used.");
                m_States[m_DefaultId].StatesToBlock.Add(m_States.IndexOf(s));
            }

            // load up the preset of each user assigned state and
            if (s.Preset == null)
            {
                s.Preset = new vp_AIComponentPreset();
            }
            if (s.TextAsset != null)
            {
                s.Preset.LoadFromTextAsset(s.TextAsset);
            }
        }

        // the default state of a component is always the last one in the list
        m_DefaultId = m_States.Count - 1;
    }
    /// <summary>
    /// draws a field allowing the user to create, reorganize,
    /// name, assign presets to and delete states on a component
    /// </summary>
    public static bool StateFoldout(bool foldout, vp_AIComponent component, List <vp_AIState> stateList, vp_AIComponentPersister persister = null)
    {
        bool before = foldout;

        foldout = EditorGUILayout.Foldout(foldout,
                                          (foldout && !Application.isPlaying) ? "State             Preset" : "States"
                                          );

        if (foldout != before)
        {
            m_ShowBlockListFor = null;
            component.RefreshDefaultState();
        }

        if (foldout)
        {
            if (m_ShowBlockListFor != null)
            {
                if (!stateList.Contains(m_ShowBlockListFor))
                {
                    foldout = false;
                }
            }
        }

        if (foldout)
        {
            for (int v = 0; v < stateList.Count; v++)
            {
                vp_AIState s = stateList[v];
                if (!Application.isPlaying)
                {
                    vp_AIPresetEditorGUIUtility.StateField(s, stateList, component);
                    if ((m_ShowBlockListFor != null) && m_ShowBlockListFor == s)
                    {
                        StateBlockList(component, s);
                    }
                }
                else
                {
                    vp_AIPresetEditorGUIUtility.RunTimeStateField(component, s, stateList);
                }
            }

            GUILayout.BeginHorizontal();
            if (!Application.isPlaying)
            {
                if (GUILayout.Button("Add State", GUILayout.MinWidth(90), GUILayout.MaxWidth(90)))
                {
                    m_ShowBlockListFor = null;
                    string newStateName = "Untitled";
                    int    n            = 1;
                    while (GetStateId(component, newStateName) != -1)
                    {
                        n++;
                        newStateName = newStateName.Substring(0, 8) + (n < 10?"0":"") + n.ToString();
                    }

                    stateList.Add(new vp_AIState(component.GetType().Name, newStateName, ""));
                    component.RefreshDefaultState();
                    EditorUtility.SetDirty(component);
                }
            }
            else
            {
                GUI.color = Color.clear;
                GUILayout.Button("", GUILayout.MinWidth(36), GUILayout.MaxWidth(36));
                GUI.color = Color.white;
            }
            if (!Application.isPlaying)
            {
                GUILayout.EndHorizontal();
            }
            if (persister != null)
            {
                vp_AIPresetEditorGUIUtility.PersistToggle(persister);
            }
            if (Application.isPlaying)
            {
                GUILayout.EndHorizontal();
            }

            vp_EditorGUIUtility.Separator();
        }

        return(foldout);
    }