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();
}
}
}