Exemple #1
0
    /// <summary>
    /// copies component values into the default state's preset.
    /// if needed, creates & adds default state to the state list.
    /// to be called on app startup and statemanager recombine
    /// </summary>
#if UNITY_EDITOR
    public void RefreshInitialState()
    {
        m_InitialState        = null;
        m_InitialState        = new vp_AIState(GetType().Name, "Internal_Initial", null);
        m_InitialState.Preset = new vp_AIComponentPreset();
        m_InitialState.Preset.InitFromComponent(this);
    }
Exemple #2
0
 /// <summary>
 /// adds a state to the list of states that blocks this one
 /// </summary>
 public void AddBlocker(vp_AIState blocker)
 {
     if (!CurrentlyBlockedBy.Contains(blocker))
     {
         CurrentlyBlockedBy.Add(blocker);
     }
 }
    /// <summary>
    /// restores the int block list onto all states by name, by
    /// fetching block lists in string-list format from the
    /// backup dictionary and converting them back to int-lists
    /// to be set on the components
    /// </summary>
    static void RestoreBlockLists(vp_AIComponent component)
    {
        foreach (string s in m_BlockListBackups.Keys)
        {
            vp_AIState blocker = GetState(component, s);
            if (blocker == null)
            {
                continue;
            }

            List <string> stringBlockList;
            if (!m_BlockListBackups.TryGetValue(s, out stringBlockList))
            {
                continue;
            }

            List <int> intBlockList = new List <int>();
            foreach (string b in stringBlockList)
            {
                int blockee = GetStateId(component, b);
                if (blockee != -1)
                {
                    intBlockList.Add(GetStateId(component, b));
                }
            }

            blocker.StatesToBlock = intBlockList;
        }
    }
Exemple #4
0
 /// <summary>
 /// removes a state from the list of states that blocks this one
 /// </summary>
 public void RemoveBlocker(vp_AIState blocker)
 {
     if (CurrentlyBlockedBy.Contains(blocker))
     {
         CurrentlyBlockedBy.Remove(blocker);
     }
 }
    /// <summary>
    /// gets a random audio clip for the specified state
    /// </summary>
    protected virtual AudioClip OnMessage_GetAudioClipForState(object obj)
    {
        if (obj == null)
        {
            return(null);
        }

        if (obj.GetType() != typeof(vp_AIState))
        {
            return(null);
        }

        vp_AIState state = (vp_AIState)obj;

        if (state == null)
        {
            return(null);
        }

        if (state.AudioClips == null)
        {
            return(null);
        }

        if (state.AudioClips.Count == 0)
        {
            return(null);
        }

reroll:
        AudioClip clip = state.AudioClips[Random.Range(0, state.AudioClips.Count)];

        if (clip == null)
        {
            return(null);
        }

        if (clip == null)
        {
            return(null);
        }

        // if the animation was the last one played, reroll for another animation
        if (clip == state.LastAudioClip && state.AudioClips.Count > 1)
        {
            goto reroll;
        }

        if (state.AudioProbability > 0)
        {
            if ((float)Random.Range(0f, 1f) > state.AudioProbability)
            {
                return(null);
            }
        }

        return(clip);
    }
Exemple #6
0
    /// <summary>
    /// Refreshes a state from the States and Presets section
    /// </summary>
    public virtual vp_AIState RefreshState(vp_AIState state)
    {
        if (state.Name == null)
        {
            return(null);
        }

        return(States.Find(s => s.Name == state.Name));
    }
    /// <summary>
    /// draws a button showing if a state is on or off, allowing
    /// the user to toggle states at runtime. will also show
    /// a text saying if the state is currently disallowed
    /// </summary>
    public static void RunTimeStateField(vp_AIComponent component, vp_AIState state, List <vp_AIState> stateList)
    {
        EditorGUILayout.BeginHorizontal();

        GUI.color = m_ColorTransparentWhite;
        if (!state.Enabled)
        {
            GUILayout.Space(20);
            GUI.enabled = true;
            GUILayout.Label((stateList.Count - stateList.IndexOf(state) - 1).ToString() + ":", vp_EditorGUIUtility.RightAlignedPathStyle, GUILayout.MinWidth(20), GUILayout.MaxWidth(20));
            GUILayout.BeginHorizontal();
            if (GUILayout.Button(state.Name, vp_EditorGUIUtility.CenteredBoxStyle, GUILayout.MinWidth(90), GUILayout.MaxWidth(90)))
            {
                vp_AIComponent[] compos = component.gameObject.GetComponentsInChildren <vp_AIComponent>();
                foreach (vp_AIComponent c in compos)
                {
                    c.StateManager.SetState(state.Name, true);
                    c.Refresh();
                }
            }
            GUILayout.EndHorizontal();
            GUI.color = m_ColorTransparentWhite;
        }
        else
        {
            GUILayout.Space(20);
            GUILayout.Label((stateList.Count - stateList.IndexOf(state) - 1).ToString() + ":", vp_EditorGUIUtility.RightAlignedPathStyle, GUILayout.MinWidth(20), GUILayout.MaxWidth(20));
            if (GUILayout.Button(state.Name,
                                 ((!state.Blocked) ? vp_EditorGUIUtility.CenteredBoxStyleBold : vp_EditorGUIUtility.CenteredStyleBold)
                                 , GUILayout.MinWidth(90), GUILayout.MaxWidth(90)))
            {
                vp_AIComponent[] compos = component.gameObject.GetComponentsInChildren <vp_AIComponent>();
                foreach (vp_AIComponent c in compos)
                {
                    c.StateManager.SetState(state.Name, false);
                    c.Refresh();
                }
            }
        }
        if (state.Name != "Default")
        {
            if (state.Blocked)
            {
                GUILayout.TextField("(Blocked on " + component.GetType().ToString() + "(" + state.BlockCount + "))", vp_EditorGUIUtility.NoteStyle, GUILayout.MinWidth(100));
            }

            if ((state.TextAsset == null) && (!state.Blocked))
            {
                GUILayout.TextField("(No preset)", vp_EditorGUIUtility.NoteStyle, GUILayout.MinWidth(100));
            }
        }

        EditorGUILayout.EndHorizontal();
    }
Exemple #8
0
    /// <summary>
    /// Returns a popup list with enabled audio states
    /// </summary>
    public static vp_AIState GetAudioState(string title, vp_AIState state, string tooltip = "")
    {
        List <vp_AIState> states = m_AI.States.Where(s => s.Name != "Default" && s.IsAudioState).ToList();

        states.Insert(0, null);
        state = states.FirstOrDefault(s => s != null && s.Name == state.Name);
        int selected = state == null ? 0 : states.IndexOf(state);

        GUILayout.BeginHorizontal();
        EditorGUILayout.LabelField(new GUIContent(title, title + "\n\n" + tooltip), GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
        selected = EditorGUILayout.Popup(selected, AudioStateNames);
        GUILayout.EndHorizontal();
        return(selected == -1 ? null : states[selected]);
    }
Exemple #9
0
    /// <summary>
    /// sees if the component has a default state. if so, makes
    /// sure it's in index zero of the list, if not, creates it.
    /// </summary>
    public void RefreshDefaultState()
    {
        vp_AIState defaultState = null;

        if (States.Count == 0)
        {
            // there are no states, so create default state
            defaultState = new vp_AIState(GetType().Name, "Default", null);
            States.Add(defaultState);
        }
        else
        {
            for (int v = States.Count - 1; v > -1; v--)
            {
                if (States[v].Name == "Default")
                {
                    // found default state, make sure it's in the back
                    defaultState = States[v];
                    States.Remove(defaultState);
                    States.Add(defaultState);
                }
            }
            if (defaultState == null)
            {
                // there are states, but no default state so create it
                defaultState = new vp_AIState(GetType().Name, "Default", null);
                States.Add(defaultState);
            }
        }

        if (defaultState.Preset == null || defaultState.Preset.ComponentType == null)
        {
            defaultState.Preset = new vp_AIComponentPreset();
        }

        if (defaultState.TextAsset == null)
        {
            defaultState.Preset.InitFromComponent(this);
        }

        defaultState.Enabled = true;            // default state is always enabled

        m_DefaultState = defaultState;
    }
    /// <summary>
    /// draws a slot to which the user can drag a preset TextAsset
    /// </summary>
    private static void PresetField(vp_AIState state)
    {
        TextAsset orig = state.TextAsset;

        state.TextAsset = (TextAsset)EditorGUILayout.ObjectField(state.TextAsset, typeof(TextAsset), false);
        if (state.TextAsset != orig)
        {
            if (state.TextAsset != null)
            {
                if ((vp_AIComponentPreset.GetFileTypeFromAsset(state.TextAsset) == null ||
                     vp_AIComponentPreset.GetFileTypeFromAsset(state.TextAsset).Name != state.TypeName))
                {
                    vp_MessageBox.Create(vp_MessageBox.Mode.OK, "Error", "Error: The file '" + state.TextAsset.name + " ' does not contain a preset of type '" + state.TypeName + "'.");
                    state.TextAsset = orig;
                    return;
                }
            }
        }
    }
    /// <summary>
    /// draws a disabled preset field for the built-in default
    /// state, making the user aware of the state
    /// </summary>
    public static void DefaultStateField(vp_AIState state)
    {
        EditorGUILayout.BeginHorizontal();

        GUI.enabled = false;
        GUILayout.Label("Default", "Textfield", GUILayout.MinWidth(90), GUILayout.MaxWidth(90));

        PresetField(state);

        GUILayout.TextField("(editor)", vp_EditorGUIUtility.NoteStyle, GUILayout.MinWidth(100));

        EditorGUILayout.Space();
        GUI.color = Color.clear;
        GUILayout.Button("...", GUILayout.MinWidth(24), GUILayout.MaxWidth(24));
        GUILayout.Button("X", GUILayout.MinWidth(24), GUILayout.MaxWidth(24));
        GUI.color   = Color.white;
        GUI.enabled = true;

        EditorGUILayout.EndHorizontal();
    }
Exemple #12
0
    /// <summary>
    /// removes this state from the 'CurrentlyBlockedBy' list of
    /// all states in this state's 'StatesToBlock' list
    /// </summary>
    public void RelaxBlockingList(vp_AIState blocker)
    {
        if (blocker == null)
        {
            return;
        }

        if (blocker.StatesToBlock == null)
        {
            return;
        }

        if (m_States == null)
        {
            return;
        }

        foreach (int blockee in blocker.StatesToBlock)
        {
            m_States[blockee].RemoveBlocker(blocker);
        }
    }
    /// <summary>
    /// draws a row displaying a preset state name, a path and
    /// buttons for browsing the path + deleting the state
    /// </summary>
    public static void StateField(vp_AIState state, List <vp_AIState> stateList, vp_AIComponent component)
    {
        GUI.enabled = !Application.isPlaying;           // only allow preset field interaction in 'stopped' mode

        EditorGUILayout.BeginHorizontal();

        string orig = state.Name;

        if (state.Name == "Default")
        {
            GUI.enabled = false;
            EditorGUILayout.TextField(state.Name, GUILayout.MinWidth(90), GUILayout.MaxWidth(90));
            GUI.enabled = true;
        }
        else
        {
            if (m_ShowBlockListFor != null)
            {
                if (!component.States.Contains(m_ShowBlockListFor))
                {
                    m_ShowBlockListFor = null;
                }
                else if (m_ShowBlockListFor.StatesToBlock.Contains(component.States.IndexOf(state)))
                {
                    GUI.color = m_ColorGrayYellow;
                }
            }
            state.Name = EditorGUILayout.TextField(state.Name, GUILayout.MinWidth(90), GUILayout.MaxWidth(90));
            GUI.color  = Color.white;
        }

        if (orig != state.Name)
        {
            int collisions = -1;
            foreach (vp_AIState s in stateList)
            {
                if (s.Name == state.Name)
                {
                    collisions++;
                }
            }

            if (state.Name == "Default")
            {
                vp_MessageBox.Create(vp_MessageBox.Mode.OK, "Error", "'Default' is a reserved state name.");
                state.Name = orig;
            }
            else if (state.Name.Length == 0)
            {
                vp_MessageBox.Create(vp_MessageBox.Mode.OK, "Error", "State name can't be empty.");
                state.Name = orig;
            }
            else if (collisions > 0)
            {
                vp_MessageBox.Create(vp_MessageBox.Mode.OK, "Error", "There is already a state named '" + state.Name + "'.\nTIP: If you need a similar state name, begin by adding numbers at the end.");
                state.Name = orig;
            }
            else
            {
                EditorUtility.SetDirty(component);
            }
        }

        PresetField(state);

        if (state.Name == "Default")
        {
            if (state.TextAsset == null)
            {
                GUI.enabled = false;
                GUILayout.TextField("(Inspector)", vp_EditorGUIUtility.NoteStyle, GUILayout.MinWidth(60));
            }
            else
            {
                GUI.enabled = true;
                if (GUILayout.Button("Unlock", vp_EditorGUIUtility.SmallButtonStyle, GUILayout.MinWidth(30), GUILayout.MinHeight(15)))
                {
                    state.TextAsset = null;
                    EditorUtility.SetDirty(component);
                }
            }
        }
        else
        {
            if (stateList.IndexOf(state) == 0)
            {
                GUI.enabled = false;
            }

            GUI.SetNextControlName("state");
            if (GUILayout.Button("^", vp_EditorGUIUtility.SmallButtonStyle, GUILayout.MinWidth(15), GUILayout.MaxWidth(15), GUILayout.MinHeight(16)))
            {
                BackupBlockLists(component);
                int i = stateList.IndexOf(state);
                if (i != 0)
                {
                    stateList.Remove(state);
                    stateList.Insert(i - 1, state);
                }
                RestoreBlockLists(component);

                // focus this button to get rid of possible textfield focus,
                // or the textfields won't update properly when moving state
                GUI.FocusControl("state");
                EditorUtility.SetDirty(component);
            }

            GUI.enabled = true;

            if (GUILayout.Button(new GUIContent(state.IsAnimationState ? m_AnimationTexture : m_AnimationOffTexture, "Enable/Disable Animation State for " + state.Name), SmallButtonStyle, GUILayout.MinWidth(15), GUILayout.MaxWidth(15), GUILayout.MinHeight(11)))
            {
                state.IsAnimationState = !state.IsAnimationState;
            }

            GUI.color = state.IsAudioState ? m_ColorYellow : Color.white;
            if (UnityEditorInternal.InternalEditorUtility.HasPro())
            {
                GUI.color = state.IsAudioState ? m_ColorYellowPro : Color.white;
            }
            if (GUILayout.Button(new GUIContent(m_SoundTexture, "Enable/Disable Audio State for " + state.Name), SmallButtonStyle, GUILayout.MinWidth(15), GUILayout.MaxWidth(15), GUILayout.MinHeight(11)))
            {
                state.IsAudioState = !state.IsAudioState;
            }
            GUI.color = Color.white;

            if (state.StatesToBlock != null)
            {
                if ((state.StatesToBlock.Count > 0) && ((m_ShowBlockListFor == null) || (!component.States.Contains(m_ShowBlockListFor)) || m_ShowBlockListFor == state))
                {
                    GUI.color = m_ColorGrayYellow;
                }
            }

            GUI.enabled = (component.States.Count > 2);
            if (GUILayout.Button("B", SmallButtonStyle, GUILayout.MinWidth(15), GUILayout.MaxWidth(15), GUILayout.MinHeight(16)))
            {
                if (m_ShowBlockListFor == state)
                {
                    m_ShowBlockListFor = null;
                }
                else
                {
                    m_ShowBlockListFor = state;
                }
                EditorUtility.SetDirty(component);
            }
            GUI.enabled = true;
            GUI.color   = Color.white;

            if (GUILayout.Button("X", vp_EditorGUIUtility.SmallButtonStyle, GUILayout.MinWidth(15), GUILayout.MaxWidth(15), GUILayout.MinHeight(16)))
            {
                vp_MessageBox.Create(vp_MessageBox.Mode.YesNo, "Confirm", "Are you sure you want to delete the state '" + state.Name + "'?", delegate(vp_MessageBox.Answer answer)
                {
                    if (answer == vp_MessageBox.Answer.Yes)
                    {
                        BackupBlockLists(component);
                        stateList.Remove(state);
                        RestoreBlockLists(component);
                        EditorUtility.SetDirty(component);
                    }
                });

                EditorUtility.SetDirty(component);
            }
        }

        GUI.enabled = true;

        EditorGUILayout.EndHorizontal();
    }
    /// <summary>
    /// chooses a random sound to play from the list of sounds
    /// provided for this state
    /// </summary>
    protected virtual bool OnMessage_PlaySound(object obj)
    {
        if (m_Audio.isPlaying)
        {
            return(false);
        }

        if (obj == null)
        {
            return(false);
        }

        if (obj.GetType() != typeof(vp_AIState))
        {
            return(false);
        }

        vp_AIState state = (vp_AIState)obj;

        if (state == null)
        {
            return(false);
        }

        if (state.AudioClips == null)
        {
            return(false);
        }

        if (state.AudioClips.Count == 0)
        {
            return(false);
        }

        if (Time.time < state.LastTimeAudioPlayed)
        {
            return(false);
        }

        state.LastTimeAudioPlayed = Time.time + state.AudioPlayInterval;

reroll:
        AudioClip clip = state.AudioClips[Random.Range(0, state.AudioClips.Count)];

        if (clip == null)
        {
            return(false);
        }

        if (clip == null)
        {
            return(false);
        }

        // if the animation was the last one played, reroll for another animation
        if (clip == state.LastAudioClip && state.AudioClips.Count > 1)
        {
            goto reroll;
        }

        if (state.AudioProbability < 1)
        {
            if ((float)Random.Range(0f, 1f) > state.AudioProbability)
            {
                return(false);
            }
        }

        m_Audio.pitch = Random.Range(state.AudioPitch.x, state.AudioPitch.y) * Time.timeScale;

        m_Audio.clip = clip;
        m_Audio.Play();
        state.LastAudioClip = clip;

        return(true);
    }
    public static void AudioStates()
    {
        List <vp_AIState> states = m_AI.States.Where(s => s.Name != "Default" && s.IsAudioState).ToList();

        if (states.Count == 0)
        {
            GUILayout.Space(10);
            GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            if (m_AI.States.Count == 1)
            {
                EditorGUILayout.HelpBox("No states have been added. Please add some states in the States and Presets section below.", MessageType.Info);
            }
            else
            {
                EditorGUILayout.HelpBox("No states have been marked for audio. Please click the Audio button next to a state to add it here.", MessageType.Info);
            }
            GUILayout.Space(20);
            GUILayout.EndHorizontal();
        }

        for (int i = 0; i < states.Count; ++i)
        {
            vp_AIState state = states[i];

            state.AudioClipsFoldout = EditorGUILayout.Foldout(state.AudioClipsFoldout, state.Name, state.AudioClipsFoldout ? SubFoldoutStyle : new GUIStyle("Foldout"));
            if (state.AudioClipsFoldout)
            {
                EditorGUI.indentLevel++;

                for (int n = 0; n < state.AudioClips.Count; n++)
                {
                    GUILayout.BeginHorizontal();
                    state.AudioClips[n] = (AudioClip)EditorGUILayout.ObjectField(state.AudioClips[n], typeof(AudioClip), false);
                    if (state.AudioClips.Count > 1)
                    {
                        if (GUILayout.Button("Remove", vp_EditorGUIUtility.SmallButtonStyle, GUILayout.MinWidth(50), GUILayout.MaxWidth(50), GUILayout.MinHeight(15)))
                        {
                            state.AudioClips.RemoveAt(n);
                            --n;
                            return;
                        }
                    }
                    GUILayout.EndHorizontal();
                }
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button(new GUIContent("Add Audio Clip", "Add a new audio clip for this state"), GUILayout.MinWidth(150), GUILayout.MaxWidth(150)))
                {
                    state.AudioClips.Add(null);
                }
                GUILayout.EndHorizontal();

                EditorGUILayout.LabelField(new GUIContent("Pitch (Min:Max)", "random pitch range the sound will play at"));
                GUILayout.Space(-20);
                state.AudioPitch        = EditorGUILayout.Vector2Field("", state.AudioPitch);
                state.AudioProbability  = EditorGUILayout.Slider(new GUIContent("Probability " + (state.AudioProbability == 1 ? "(always)" : ""), "probability at which the sound will play. 1 will always play the sound."), state.AudioProbability, 0, 1);
                state.AudioPlayInterval = EditorGUILayout.Slider(new GUIContent("Play Interval", "Interval in seconds at which this state plays sounds"), state.AudioPlayInterval, 0, 10);

                GUILayout.Space(5);

                GUI.backgroundColor = Color.white;

                EditorGUI.indentLevel--;
            }

            states[i] = state;
        }
    }
    public static void Animation()
    {
        Animation oldAnimation = m_AI.Animation.Animation;

        if (m_AI.Animation.Animation == null)
        {
            foreach (Animation anim in m_AI.gameObject.GetComponentsInChildren <Animation>(true))
            {
                m_AI.Animation.Animation = (Animation)EditorGUILayout.ObjectField(new GUIContent("Animation Object", "The object with an Animation component that has animations for this AI"), anim, typeof(Animation), true);
            }
        }
        else
        {
            m_AI.Animation.Animation = (Animation)EditorGUILayout.ObjectField(new GUIContent("Animation Object", "The object with an Animation component that has animations for this AI"), m_AI.Animation.Animation, typeof(Animation), true);
        }

        if (m_AI.Animation.Animation != oldAnimation)
        {
            Reset();
        }

        if (m_AI.Animation.Animation == null)
        {
            GUILayout.Space(10);
            m_AI.Animation.Animation = (Animation)EditorGUILayout.ObjectField(new GUIContent("Animation Object", "The object with an Animation component that has animations for this AI"), m_AI.Animation.Animation, typeof(Animation), true);
            GUILayout.BeginHorizontal();
            GUILayout.Space(20);
            EditorGUILayout.HelpBox("An Animation component could not be found. Please add an animation component above.", MessageType.Info);
            GUILayout.Space(20);
            GUILayout.EndHorizontal();
        }
        else
        {
            List <vp_AIState> states = m_AI.States.Where(s => s.Name != "Default" && s.IsAnimationState).ToList();
            if (states.Count == 0)
            {
                GUILayout.Space(10);
                GUILayout.BeginHorizontal();
                GUILayout.Space(20);
                if (m_AI.States.Count == 1)
                {
                    EditorGUILayout.HelpBox("No states have been added. Please add some states in the States and Presets section below.", MessageType.Info);
                }
                else
                {
                    EditorGUILayout.HelpBox("No states have been marked for animation. Please click the Animation button next to a state to add it here.", MessageType.Info);
                }
                GUILayout.Space(20);
                GUILayout.EndHorizontal();
            }

            for (int i = 0; i < states.Count; ++i)
            {
                vp_AIState state = states[i];

                state.AnimationFoldout = EditorGUILayout.Foldout(state.AnimationFoldout, state.Name, state.AnimationFoldout ? SubFoldoutStyle : new GUIStyle("Foldout"));
                if (state.AnimationFoldout)
                {
                    EditorGUI.indentLevel++;
                    state.AutoPlayAnimations = EditorGUILayout.Toggle(new GUIContent("Auto Play Animations", "Whether or not animations should play automatically while this state is active. If disabled, animations can be played with code."), state.AutoPlayAnimations);

                    if (state.AnimationClips.Count == 0)
                    {
                        state.AnimationClips.Add(new vp_AIState.vp_AnimationState());
                    }

                    for (int n = 0; n < state.AnimationClips.Count; n++)
                    {
                        GUILayout.BeginHorizontal();
                        if (n > state.AnimationClips.Count - 1)
                        {
                            state.AnimationClips.RemoveAt(n);
                            return;
                        }

                        state.AnimationClips[n].Foldout = EditorGUILayout.Foldout(state.AnimationClips[n].Foldout, state.AnimationClips[n].Clip == null ? state.Name + " Animation Clip " + (n + 1).ToString() : state.AnimationClips[n].Clip.name);
                        if (state.AnimationClips.Count > 1)
                        {
                            if (GUILayout.Button("Remove", vp_EditorGUIUtility.SmallButtonStyle, GUILayout.MinWidth(50), GUILayout.MaxWidth(50), GUILayout.MinHeight(15)))
                            {
                                state.AnimationClips.RemoveAt(n);
                                --n;
                                return;
                            }
                        }
                        GUILayout.EndHorizontal();


                        if (state.AnimationClips[n].Foldout)
                        {
                            EditorGUI.indentLevel++;
                            GUILayout.BeginHorizontal();
                            List <AnimationClip> animationClips = new List <AnimationClip>();
                            animationClips.Add(null);
                            foreach (AnimationState s in m_AI.Animation.Animation)
                            {
                                animationClips.Add(s.clip);
                            }

                            if (!animationClips.Contains(state.AnimationClips[n].Clip))
                            {
                                state.AnimationClips[n].Clip = null;
                            }

                            int index = 0;
                            if (state.AnimationClips[n].Clip != null)
                            {
                                index = animationClips.IndexOf(state.AnimationClips[n].Clip);
                            }

                            string[] animationNames = new string[animationClips.Count];
                            for (int z = 0; z < animationNames.Length; z++)
                            {
                                animationNames[z] = z == 0 ? "None" : animationClips[z].name;
                            }

                            index = EditorGUILayout.Popup(index, animationNames);

                            state.AnimationClips[n].Clip = animationClips[index];

                            GUI.enabled = false;
                            state.AnimationClips[n].Clip = (AnimationClip)EditorGUILayout.ObjectField(state.AnimationClips[n].Clip, typeof(AnimationClip), false);
                            GUI.enabled = true;
                            GUILayout.Space(5);
                            GUILayout.EndHorizontal();

                            state.AnimationClips[n].WrapMode        = (WrapMode)EditorGUILayout.EnumPopup(new GUIContent("Wrap Mode", "WrapMode for this animation"), state.AnimationClips[n].WrapMode);
                            state.AnimationClips[n].AnimationSpeed  = EditorGUILayout.Slider(new GUIContent("Animation Speed", "Speed at which to play this animation. 1 is normal speed."), state.AnimationClips[n].AnimationSpeed, 0, 10);
                            state.AnimationClips[n].CrossfadeLength = EditorGUILayout.Slider(new GUIContent("Crossfade Length", "Speed at which to crossfade to this animation. 0.3 is default."), state.AnimationClips[n].CrossfadeLength, 0, 3);
                            state.AnimationClips[n].Layer           = EditorGUILayout.IntSlider(new GUIContent("Layer", "Layer for this animation. 0 is default."), state.AnimationClips[n].Layer, -100, 100);
                            state.AnimationClips[n].PlayMode        = (PlayMode)EditorGUILayout.EnumPopup(new GUIContent("Play Mode", "Play Mode for this animation. Stop Same Layer is default."), state.AnimationClips[n].PlayMode);
                            EditorGUI.indentLevel--;
                        }
                    }

                    GUILayout.BeginHorizontal();
                    GUILayout.FlexibleSpace();
                    if (GUILayout.Button(new GUIContent("Add Animation", "Add a new animation for this state"), GUILayout.MinWidth(100), GUILayout.MaxWidth(100)))
                    {
                        state.AnimationClips.Add(new vp_AIState.vp_AnimationState());
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.Space(5);

                    GUI.backgroundColor = Color.white;

                    EditorGUI.indentLevel--;
                }

                states[i] = state;
            }
        }
    }
Exemple #17
0
    /// <summary>
    /// performs an animation for the AI and returns
    /// whether or not the animation was successfully executed
    /// </summary>
    protected virtual bool OnMessage_Animate(object obj)
    {
        if (obj == null)
        {
            return(false);
        }

        if (obj.GetType() != typeof(vp_AIState))
        {
            return(false);
        }

        vp_AIState state = (vp_AIState)obj;

        if (state == null)
        {
            return(false);
        }

        if (state.AnimationClips == null)
        {
            return(false);
        }

        if (state.AnimationClips.Count == 0)
        {
            return(false);
        }

reroll:
        vp_AIState.vp_AnimationState clip = state.AnimationClips[Random.Range(0, state.AnimationClips.Count)];

        if (clip == null)
        {
            return(false);
        }

        if (clip.Clip == null)
        {
            return(false);
        }

        if (Animation.GetClip(clip.Clip.name) == null)
        {
            return(false);
        }

        // if the animation was the last one played, reroll for another animation
        if (clip == state.LastAnimationClip && state.AnimationClips.Count > 1)
        {
            goto reroll;
        }

        Animation[clip.Clip.name].layer    = clip.Layer;
        Animation[clip.Clip.name].speed    = clip.AnimationSpeed;
        Animation[clip.Clip.name].wrapMode = clip.WrapMode;

        state.LastAnimationClip       = clip;
        state.LastAnimationClipLength = Animation[clip.Clip.name].length / Animation[clip.Clip.name].speed;

        Animation.CrossFade(clip.Clip.name, clip.CrossfadeLength, clip.PlayMode);

        return(true);
    }
    /// <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);
    }
    /// <summary>
    ///
    /// </summary>
    static void StateBlockList(vp_AIComponent component, vp_AIState blocker)
    {
        GUILayout.BeginHorizontal();
        GUILayout.Space(20);
        GUILayout.BeginVertical();

        string componentName = component.GetType().ToString();

        if (componentName.Contains("vp_"))
        {
            componentName = componentName.Substring(3);
        }

        EditorGUILayout.HelpBox("'" + blocker.Name + "' blocks " + ((blocker.StatesToBlock.Count > 0) ? blocker.StatesToBlock.Count.ToString() : "no") + " state" + ((blocker.StatesToBlock.Count == 1) ? "" : "s") + " on this " + componentName + ".", MessageType.None);

        GUILayout.BeginVertical();
        int e = 0;

        foreach (vp_AIState blockee in component.States)
        {
            if (blockee == blocker)
            {
                continue;
            }

            if (blockee.Name == "Default")
            {
                continue;
            }

            int i = component.States.IndexOf(blockee);

            if (component.States[i].StatesToBlock.Contains(component.States.IndexOf(blocker)))
            {
                GUI.enabled = false;
            }

            if (e % 2 == 0)
            {
                GUILayout.BeginHorizontal();
            }
            GUILayout.Space(20);
            bool before = blocker.StatesToBlock.Contains(i);
            bool after  = before;

            after = GUILayout.Toggle(after, blockee.Name);

            if (before != after)
            {
                if (!before)
                {
                    blocker.StatesToBlock.Add(i);
                }
                else
                {
                    blocker.StatesToBlock.Remove(i);
                }

                EditorUtility.SetDirty(component);
            }
            if (e % 2 == 1)
            {
                GUILayout.Space(10);
                GUILayout.EndHorizontal();
            }

            e++;
            GUI.enabled = true;
        }
        if (e % 2 == 1)
        {
            GUILayout.EndHorizontal();
        }

        GUILayout.EndVertical();

        GUILayout.BeginHorizontal();
        EditorGUILayout.HelpBox("Select states to be disallowed on this " + componentName + " while the '" + blocker.Name + "' state is enabled. A state can not block itself, a state that blocks it or the Default state.", MessageType.Info);
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Close", GUILayout.MinWidth(100), GUILayout.MaxWidth(50)))
        {
            m_ShowBlockListFor = null;
            EditorUtility.SetDirty(component);
        }

        GUILayout.EndVertical();
        GUILayout.EndHorizontal();
        GUILayout.Space(10);
        GUILayout.EndHorizontal();
        GUILayout.Space(10);
    }