/// --------------------------------------------- /// Ultimate Character Controller /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.UltimateCharacterController.StateSystem { using Opsive.Shared.Utility; using System.Collections.Generic; using UnityEngine; /// /// A State contains a preset which can change property values at runtime. The state has a name associated with it which allows for easy reference to it. /// [System.Serializable] public class State { [Tooltip("The name of the state.")] [SerializeField] protected string m_Name; [Tooltip("The preset used by the state.")] [SerializeField] protected Preset m_Preset; [Tooltip("A list of other states that the current state can prevent from being enabled if the current state is enabled.")] [SerializeField] protected string[] m_BlockList; [Tooltip("Is the state the default state?")] [SerializeField] protected bool m_Default; [Tooltip("Is the state active?")] [System.NonSerialized] [SerializeField] protected bool m_Active; private IStateOwner m_Owner; public IStateOwner Owner { get { return m_Owner; } } public string Name { get { return m_Name; } #if UNITY_EDITOR set { m_Name = value; } #endif } public Preset Preset { get { return m_Preset; } set { m_Preset = value; } } #if UNITY_EDITOR public string[] BlockList { get { return m_BlockList; } set { m_BlockList = value; } } #endif public bool Default { get { return m_Default; } #if UNITY_EDITOR set { m_Default = value; } #endif } public bool Active { get { return m_Active; } set { m_Active = value; } } [System.NonSerialized] private State[] m_BlockStates; /// /// Default constructor for State. /// public State() { } /// /// Constructor for State. Used by the component inspector. /// /// The name of the state. /// Is the state the default state? public State(string name, bool defaultState) { m_Name = name; m_Default = defaultState; } /// /// Constructor for State. Used by the State Configuration. /// /// The name of the state. /// The preset that the state uses. /// The list of blocked states. public State(string name, Preset preset, string[] blockList) { m_Name = name; m_Preset = preset; m_BlockList = blockList; } /// /// Initializes the state - binds the object and applies any blocking rules. /// /// The object which is bound to the state. /// A mapping between the state name and the state object. public void Initialize(IStateOwner owner, Dictionary nameStateMap) { // The preset can be null if the Component has no valid properties that can be changed. if (m_Preset != null) { // The preset may be used by another object of the same type. // Initialize a new preset to prevent the delegates from conflicting with each other. if (m_Preset.IsInitialized) { m_Preset = Object.Instantiate(m_Preset); } m_Preset.Initialize(owner, MemberVisibility.Public); } m_Owner = owner; UpdateBlockList(nameStateMap); } /// /// Update the block list to point to the state object. /// /// A mapping between the state name and the state object. private void UpdateBlockList(Dictionary nameStateMap) { if (m_BlockList != null && m_BlockList.Length > 0) { m_BlockStates = new State[m_BlockList.Length]; State state; var count = 0; for (int i = 0; i < m_BlockList.Length; ++i) { if (m_BlockList[i] == null) { continue; } if (nameStateMap.TryGetValue(m_BlockList[count], out state)) { m_BlockStates[count] = state; } else { Debug.LogWarning("Error: Unable to find block state with name \"" + m_BlockList[count] + "\" within state " + m_Name + " on object " + m_Owner); } count++; } if (m_BlockList.Length != count) { System.Array.Resize(ref m_BlockList, count); System.Array.Resize(ref m_BlockStates, count); } } } /// /// Is the state blocked by another enabed state? /// /// True if the state is blocked. public bool IsBlocked() { if (m_BlockStates != null) { for (int i = 0; i < m_BlockStates.Length; ++i) { if (m_BlockStates[i] != null && m_BlockStates[i].Active && !m_BlockStates[i].IsBlocked()) { return true; } } } return false; } /// /// Applies the values to the component specified within the preset object. /// public void ApplyValues() { if (m_Preset != null) { m_Preset.ApplyValues(); } } /// /// Applies the values to the component specified within the preset object. /// public void ApplyValues(Preset.BaseDelegate[] delegates) { if (m_Preset != null) { m_Preset.ApplyValues(delegates); } } } }