// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Serialization; namespace Microsoft.MixedReality.Toolkit.UI { /// /// States scriptableObject for storing available states and related state model /// [CreateAssetMenu(fileName = "States", menuName = "Mixed Reality/Toolkit/State", order = 1)] public class States : ScriptableObject { [FormerlySerializedAs("StateList")] [SerializeField] private List stateList = new List(); /// /// List of available states defined by asset /// public List StateList { get { return stateList; } set { stateList = value; } } [FormerlySerializedAs("DefaultIndex")] [SerializeField] private int defaultIndex = 0; /// /// Default index into state list /// public int DefaultIndex { get { return defaultIndex; } set { defaultIndex = value; } } /// /// Defines the type of State Model to associate with this States asset. Type must be a class that extends InteractableStateModel /// public Type StateModelType { get { if (stateModelType == null) { if (string.IsNullOrEmpty(AssemblyQualifiedName)) { return null; } stateModelType = Type.GetType(AssemblyQualifiedName); } return stateModelType; } set { if (!value.IsSubclassOf(typeof(BaseStateModel))) { Debug.LogWarning($"Cannot assign type {value} that does not extend {typeof(BaseStateModel)} to ThemeDefinition"); return; } if (stateModelType != value) { stateModelType = value; StateModelClassName = stateModelType.Name; AssemblyQualifiedName = stateModelType.AssemblyQualifiedName; } } } // Unity cannot serialize System.Type, thus must save AssemblyQualifiedName // Field here for Runtime use private Type stateModelType; [FormerlySerializedAs("StateLogicName")] [SerializeField] private string StateModelClassName; [SerializeField] private string AssemblyQualifiedName; public States() { // Set default type StateModelType = typeof(InteractableStates); } [System.Obsolete("Use the StateList property instead")] public State[] GetStates() { return StateList.ToArray(); } /// /// Test whether the current States object and the argument States object have the same internal values and configurations /// /// other States object to compare against self /// true if internal list of state values and class configuration matches other, false otherwise public bool Equals(States other) { if (this.StateList.Count != other.StateList.Count || this.StateModelType != other.StateModelType || this.DefaultIndex != other.DefaultIndex) { return false; } for (int i = 0; i < this.StateList.Count; i++) { if (!this.StateList[i].CompareState(other.StateList[i])) { return false; } } return true; } /// /// Create a State Model class and initialize it with the configuration data from this States ScriptableObject /// /// BaseStateModel or inherited class implementation object initialized with the StateList in this ScriptableObject public BaseStateModel CreateStateModel() { BaseStateModel stateLogic = (BaseStateModel)Activator.CreateInstance(StateModelType, StateList[DefaultIndex]); List stateListCopy = new List(); foreach (State s in StateList) { stateListCopy.Add(s.Copy()); } stateLogic.ImportStates(stateListCopy); return stateLogic; } } }