using System; using System.Collections.Generic; using System.Linq; namespace UnityEngine.Tilemaps { [Serializable] internal enum GridInformationType { Integer, String, Float, Double, UnityObject, Color } /// /// A simple MonoBehaviour that stores and provides information based on Grid positions and keywords. /// [Serializable] [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/GridInformation.html")] [AddComponentMenu("Tilemap/Grid Information")] public class GridInformation : MonoBehaviour, ISerializationCallbackReceiver { internal struct GridInformationValue { public GridInformationType type; public object data; } internal struct GridInformationKey : IEquatable { public Vector3Int position; public String name; public bool Equals(GridInformationKey key) { return position == key.position && name == key.name; } public override int GetHashCode() { var hashCode = position.GetHashCode(); hashCode = hashCode * 317 ^ name.GetHashCode(); return hashCode; } } private Dictionary m_PositionProperties = new Dictionary(); internal Dictionary PositionProperties { get { return m_PositionProperties; } } [SerializeField] [HideInInspector] private List m_PositionIntKeys = new List(); [SerializeField] [HideInInspector] private List m_PositionIntValues = new List(); [SerializeField] [HideInInspector] private List m_PositionStringKeys = new List(); [SerializeField] [HideInInspector] private List m_PositionStringValues = new List(); [SerializeField] [HideInInspector] private List m_PositionFloatKeys = new List(); [SerializeField] [HideInInspector] private List m_PositionFloatValues = new List(); [SerializeField] [HideInInspector] private List m_PositionDoubleKeys = new List(); [SerializeField] [HideInInspector] private List m_PositionDoubleValues = new List(); [SerializeField] [HideInInspector] private List m_PositionObjectKeys = new List(); [SerializeField] [HideInInspector] private List m_PositionObjectValues = new List(); [SerializeField] [HideInInspector] private List m_PositionColorKeys = new List(); [SerializeField] [HideInInspector] private List m_PositionColorValues = new List(); /// /// Callback before serializing this GridInformation /// void ISerializationCallbackReceiver.OnBeforeSerialize() { Grid grid = GetComponentInParent(); if (grid == null) return; m_PositionIntKeys.Clear(); m_PositionIntValues.Clear(); m_PositionStringKeys.Clear(); m_PositionStringValues.Clear(); m_PositionFloatKeys.Clear(); m_PositionFloatValues.Clear(); m_PositionDoubleKeys.Clear(); m_PositionDoubleValues.Clear(); m_PositionObjectKeys.Clear(); m_PositionObjectValues.Clear(); m_PositionColorKeys.Clear(); m_PositionColorValues.Clear(); foreach (var kvp in m_PositionProperties) { switch (kvp.Value.type) { case GridInformationType.Integer: m_PositionIntKeys.Add(kvp.Key); m_PositionIntValues.Add((int)kvp.Value.data); break; case GridInformationType.String: m_PositionStringKeys.Add(kvp.Key); m_PositionStringValues.Add(kvp.Value.data as String); break; case GridInformationType.Float: m_PositionFloatKeys.Add(kvp.Key); m_PositionFloatValues.Add((float)kvp.Value.data); break; case GridInformationType.Double: m_PositionDoubleKeys.Add(kvp.Key); m_PositionDoubleValues.Add((double)kvp.Value.data); break; case GridInformationType.Color: m_PositionColorKeys.Add(kvp.Key); m_PositionColorValues.Add((Color)kvp.Value.data); break; default: m_PositionObjectKeys.Add(kvp.Key); m_PositionObjectValues.Add(kvp.Value.data as Object); break; } } } /// /// Callback after deserializing this GridInformation /// void ISerializationCallbackReceiver.OnAfterDeserialize() { m_PositionProperties.Clear(); for (int i = 0; i != Math.Min(m_PositionIntKeys.Count, m_PositionIntValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.Integer; positionValue.data = m_PositionIntValues[i]; m_PositionProperties.Add(m_PositionIntKeys[i], positionValue); } for (int i = 0; i != Math.Min(m_PositionStringKeys.Count, m_PositionStringValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.String; positionValue.data = m_PositionStringValues[i]; m_PositionProperties.Add(m_PositionStringKeys[i], positionValue); } for (int i = 0; i != Math.Min(m_PositionFloatKeys.Count, m_PositionFloatValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.Float; positionValue.data = m_PositionFloatValues[i]; m_PositionProperties.Add(m_PositionFloatKeys[i], positionValue); } for (int i = 0; i != Math.Min(m_PositionDoubleKeys.Count, m_PositionDoubleValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.Double; positionValue.data = m_PositionDoubleValues[i]; m_PositionProperties.Add(m_PositionDoubleKeys[i], positionValue); } for (int i = 0; i != Math.Min(m_PositionObjectKeys.Count, m_PositionObjectValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.UnityObject; positionValue.data = m_PositionObjectValues[i]; m_PositionProperties.Add(m_PositionObjectKeys[i], positionValue); } for (int i = 0; i != Math.Min(m_PositionColorKeys.Count, m_PositionColorValues.Count); i++) { GridInformationValue positionValue; positionValue.type = GridInformationType.Color; positionValue.data = m_PositionColorValues[i]; m_PositionProperties.Add(m_PositionColorKeys[i], positionValue); } } /// /// This is not supported. /// /// Position to store information for /// Property name to store information for /// The information to be stored at the position /// Type of the information to set /// Whether the information was set /// This is not implemented as only concrete Types are supported public bool SetPositionProperty(Vector3Int position, String name, T positionProperty) { throw new NotImplementedException("Storing this type is not accepted in GridInformation"); } /// /// Stores int information at the given position with the given property name /// /// Position to store information for /// Property name to store information for /// The information to be stored at the position /// Whether the information was set public bool SetPositionProperty(Vector3Int position, String name, int positionProperty) { return SetPositionProperty(position, name, GridInformationType.Integer, positionProperty); } /// /// Stores string information at the given position with the given property name /// /// Position to store information for /// Property name to store information for /// The information to be stored at the position /// Whether the information was set public bool SetPositionProperty(Vector3Int position, String name, string positionProperty) { return SetPositionProperty(position, name, GridInformationType.String, positionProperty); } /// /// Stores float information at the given position with the given property name /// /// Position to store information for /// Property name to store information for /// The information to be stored at the position /// Whether the information was set public bool SetPositionProperty(Vector3Int position, String name, float positionProperty) { return SetPositionProperty(position, name, GridInformationType.Float, positionProperty); } /// /// Stores double information at the given position with the given property name /// /// Position to store information for /// Property name to store information for /// The information to be stored at the position /// Whether the information was set public bool SetPositionProperty(Vector3Int position, String name, double positionProperty) { return SetPositionProperty(position, name, GridInformationType.Double, positionProperty); } /// /// Stores UnityEngine.Object information at the given position with the given property name /// /// Position to store information for /// Property name to store information for /// The information to be stored at the position /// Whether the information was set public bool SetPositionProperty(Vector3Int position, String name, UnityEngine.Object positionProperty) { return SetPositionProperty(position, name, GridInformationType.UnityObject, positionProperty); } /// /// Stores color information at the given position with the given property name /// /// Position to store information for /// Property name to store information for /// The information to be stored at the position /// Whether the information was set public bool SetPositionProperty(Vector3Int position, String name, Color positionProperty) { return SetPositionProperty(position, name, GridInformationType.Color, positionProperty); } private bool SetPositionProperty(Vector3Int position, String name, GridInformationType dataType, System.Object positionProperty) { Grid grid = GetComponentInParent(); if (grid != null && positionProperty != null) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; positionValue.type = dataType; positionValue.data = positionProperty; m_PositionProperties[positionKey] = positionValue; return true; } return false; } /// /// Retrieves information stored at the given position with the given property name as the given Type /// /// Position to retrieve information for /// Property name to retrieve information for /// Default value if property does not exist at the given position /// Type of the information to retrieve /// The information stored at the position /// Thrown when information to be retrieved is not the given Type public T GetPositionProperty(Vector3Int position, String name, T defaultValue) where T : UnityEngine.Object { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.UnityObject) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return positionValue.data as T; } return defaultValue; } /// /// Retrieves int information stored at the given position with the given property name /// /// Position to retrieve information for /// Property name to retrieve information for /// Default int if property does not exist at the given position /// The int stored at the position /// Thrown when information to be retrieved is not a int public int GetPositionProperty(Vector3Int position, String name, int defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.Integer) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (int)positionValue.data; } return defaultValue; } /// /// Retrieves string information stored at the given position with the given property name /// /// Position to retrieve information for /// Property name to retrieve information for /// Default string if property does not exist at the given position /// The string stored at the position /// Thrown when information to be retrieved is not a string public string GetPositionProperty(Vector3Int position, String name, string defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.String) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (string)positionValue.data; } return defaultValue; } /// /// Retrieves float information stored at the given position with the given property name /// /// Position to retrieve information for /// Property name to retrieve information for /// Default float if property does not exist at the given position /// The float stored at the position /// Thrown when information to be retrieved is not a float public float GetPositionProperty(Vector3Int position, String name, float defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.Float) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (float)positionValue.data; } return defaultValue; } /// /// Retrieves double information stored at the given position with the given property name /// /// Position to retrieve information for /// Property name to retrieve information for /// Default double if property does not exist at the given position /// The double stored at the position /// Thrown when information to be retrieved is not a double public double GetPositionProperty(Vector3Int position, String name, double defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.Double) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (double)positionValue.data; } return defaultValue; } /// /// Retrieves Color information stored at the given position with the given property name /// /// Position to retrieve information for /// Property name to retrieve information for /// Default color if property does not exist at the given position /// The color stored at the position /// Thrown when information to be retrieved is not a Color public Color GetPositionProperty(Vector3Int position, String name, Color defaultValue) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; GridInformationValue positionValue; if (m_PositionProperties.TryGetValue(positionKey, out positionValue)) { if (positionValue.type != GridInformationType.Color) throw new InvalidCastException("Value stored in GridInformation is not of the right type"); return (Color)positionValue.data; } return defaultValue; } /// /// Erases information stored at the given position with the given property name /// /// Position to erase /// Property name to erase /// Whether the information was erased public bool ErasePositionProperty(Vector3Int position, String name) { GridInformationKey positionKey; positionKey.position = position; positionKey.name = name; return m_PositionProperties.Remove(positionKey); } /// /// Clears all information stored /// public virtual void Reset() { m_PositionProperties.Clear(); } /// /// Gets all positions with information with the given property name /// /// Property name to search for /// An array of all positions with the property name public Vector3Int[] GetAllPositions(string propertyName) { return m_PositionProperties.Keys.ToList().FindAll(x => x.name == propertyName).Select(x => x.position).ToArray(); } } }