382 lines
14 KiB
C#
382 lines
14 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using UnityEngine.Scripting.APIUpdating;
|
|||
|
|
|||
|
#if UNITY_EDITOR
|
|||
|
using UnityEditor;
|
|||
|
#endif
|
|||
|
|
|||
|
namespace UnityEngine.Tilemaps
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Rule Override Tiles are Tiles which can override a subset of Rules for a given Rule Tile to provide specialised behaviour while keeping most of the Rules originally set in the Rule Tile.
|
|||
|
/// </summary>
|
|||
|
[MovedFrom(true, "UnityEngine")]
|
|||
|
[Serializable]
|
|||
|
[HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/RuleOverrideTile.html")]
|
|||
|
public class RuleOverrideTile : TileBase
|
|||
|
{
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// A data structure storing the Sprite overriding the original RuleTile Sprite
|
|||
|
/// </summary>
|
|||
|
[Serializable]
|
|||
|
public class TileSpritePair
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Original Sprite from the original RuleTile.
|
|||
|
/// </summary>
|
|||
|
public Sprite m_OriginalSprite;
|
|||
|
/// <summary>
|
|||
|
/// Overriding Sprite for the Original Sprite.
|
|||
|
/// </summary>
|
|||
|
public Sprite m_OverrideSprite;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// A data structure storing the GameObject overriding the original RuleTile GameObject
|
|||
|
/// </summary>
|
|||
|
[Serializable]
|
|||
|
public class TileGameObjectPair
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Original GameObject from the original RuleTile.
|
|||
|
/// </summary>
|
|||
|
public GameObject m_OriginalGameObject;
|
|||
|
/// <summary>
|
|||
|
/// Overriding GameObject for the Original Sprite.
|
|||
|
/// </summary>
|
|||
|
public GameObject m_OverrideGameObject;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the overriding Sprite of a given Sprite.
|
|||
|
/// </summary>
|
|||
|
/// <param name="originalSprite">The original Sprite that is overridden</param>
|
|||
|
public Sprite this[Sprite originalSprite]
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
foreach (TileSpritePair spritePair in m_Sprites)
|
|||
|
{
|
|||
|
if (spritePair.m_OriginalSprite == originalSprite)
|
|||
|
{
|
|||
|
return spritePair.m_OverrideSprite;
|
|||
|
}
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
if (value == null)
|
|||
|
{
|
|||
|
m_Sprites = m_Sprites.Where(spritePair => spritePair.m_OriginalSprite != originalSprite).ToList();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
foreach (TileSpritePair spritePair in m_Sprites)
|
|||
|
{
|
|||
|
if (spritePair.m_OriginalSprite == originalSprite)
|
|||
|
{
|
|||
|
spritePair.m_OverrideSprite = value;
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
m_Sprites.Add(new TileSpritePair()
|
|||
|
{
|
|||
|
m_OriginalSprite = originalSprite,
|
|||
|
m_OverrideSprite = value,
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the overriding GameObject of a given GameObject.
|
|||
|
/// </summary>
|
|||
|
/// <param name="originalGameObject">The original GameObject that is overridden</param>
|
|||
|
public GameObject this[GameObject originalGameObject]
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
foreach (TileGameObjectPair gameObjectPair in m_GameObjects)
|
|||
|
{
|
|||
|
if (gameObjectPair.m_OriginalGameObject == originalGameObject)
|
|||
|
{
|
|||
|
return gameObjectPair.m_OverrideGameObject;
|
|||
|
}
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
if (value == null)
|
|||
|
{
|
|||
|
m_GameObjects = m_GameObjects.Where(gameObjectPair => gameObjectPair.m_OriginalGameObject != originalGameObject).ToList();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
foreach (TileGameObjectPair gameObjectPair in m_GameObjects)
|
|||
|
{
|
|||
|
if (gameObjectPair.m_OriginalGameObject == originalGameObject)
|
|||
|
{
|
|||
|
gameObjectPair.m_OverrideGameObject = value;
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
m_GameObjects.Add(new TileGameObjectPair()
|
|||
|
{
|
|||
|
m_OriginalGameObject = originalGameObject,
|
|||
|
m_OverrideGameObject = value,
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The RuleTile to override
|
|||
|
/// </summary>
|
|||
|
public RuleTile m_Tile;
|
|||
|
/// <summary>
|
|||
|
/// A list of Sprite Overrides
|
|||
|
/// </summary>
|
|||
|
public List<TileSpritePair> m_Sprites = new List<TileSpritePair>();
|
|||
|
/// <summary>
|
|||
|
/// A list of GameObject Overrides
|
|||
|
/// </summary>
|
|||
|
public List<TileGameObjectPair> m_GameObjects = new List<TileGameObjectPair>();
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Returns the Rule Tile for retrieving TileData
|
|||
|
/// </summary>
|
|||
|
[HideInInspector] public RuleTile m_InstanceTile;
|
|||
|
|
|||
|
private void CreateInstanceTile()
|
|||
|
{
|
|||
|
var t = m_Tile.GetType();
|
|||
|
RuleTile instanceTile = CreateInstance(t) as RuleTile;
|
|||
|
instanceTile.hideFlags = HideFlags.NotEditable;
|
|||
|
instanceTile.name = m_Tile.name + " (Override)";
|
|||
|
m_InstanceTile = instanceTile;
|
|||
|
|
|||
|
#if UNITY_EDITOR
|
|||
|
if(AssetDatabase.Contains(this))
|
|||
|
AssetDatabase.AddObjectToAsset(instanceTile, this);
|
|||
|
EditorUtility.SetDirty(this);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Applies overrides to this
|
|||
|
/// </summary>
|
|||
|
/// <param name="overrides">A list of overrides to apply</param>
|
|||
|
/// <exception cref="ArgumentNullException">The input overrides list is not valid</exception>
|
|||
|
public void ApplyOverrides(IList<KeyValuePair<Sprite, Sprite>> overrides)
|
|||
|
{
|
|||
|
if (overrides == null)
|
|||
|
throw new ArgumentNullException("overrides");
|
|||
|
|
|||
|
for (int i = 0; i < overrides.Count; i++)
|
|||
|
this[overrides[i].Key] = overrides[i].Value;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Applies overrides to this
|
|||
|
/// </summary>
|
|||
|
/// <param name="overrides">A list of overrides to apply</param>
|
|||
|
/// <exception cref="ArgumentNullException">The input overrides list is not valid</exception>
|
|||
|
public void ApplyOverrides(IList<KeyValuePair<GameObject, GameObject>> overrides)
|
|||
|
{
|
|||
|
if (overrides == null)
|
|||
|
throw new ArgumentNullException("overrides");
|
|||
|
|
|||
|
for (int i = 0; i < overrides.Count; i++)
|
|||
|
this[overrides[i].Key] = overrides[i].Value;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets overrides for this
|
|||
|
/// </summary>
|
|||
|
/// <param name="overrides">A list of overrides to fill</param>
|
|||
|
/// <param name="validCount">Returns the number of valid overrides for Sprites</param>
|
|||
|
/// <exception cref="ArgumentNullException">The input overrides list is not valid</exception>
|
|||
|
public void GetOverrides(List<KeyValuePair<Sprite, Sprite>> overrides, ref int validCount)
|
|||
|
{
|
|||
|
if (overrides == null)
|
|||
|
throw new ArgumentNullException("overrides");
|
|||
|
|
|||
|
overrides.Clear();
|
|||
|
|
|||
|
List<Sprite> originalSprites = new List<Sprite>();
|
|||
|
|
|||
|
if (m_Tile)
|
|||
|
{
|
|||
|
if (m_Tile.m_DefaultSprite)
|
|||
|
originalSprites.Add(m_Tile.m_DefaultSprite);
|
|||
|
|
|||
|
foreach (RuleTile.TilingRule rule in m_Tile.m_TilingRules)
|
|||
|
foreach (Sprite sprite in rule.m_Sprites)
|
|||
|
if (sprite && !originalSprites.Contains(sprite))
|
|||
|
originalSprites.Add(sprite);
|
|||
|
}
|
|||
|
|
|||
|
validCount = originalSprites.Count;
|
|||
|
|
|||
|
foreach (var pair in m_Sprites)
|
|||
|
if (!originalSprites.Contains(pair.m_OriginalSprite))
|
|||
|
originalSprites.Add(pair.m_OriginalSprite);
|
|||
|
|
|||
|
foreach (Sprite sprite in originalSprites)
|
|||
|
overrides.Add(new KeyValuePair<Sprite, Sprite>(sprite, this[sprite]));
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets overrides for this
|
|||
|
/// </summary>
|
|||
|
/// <param name="overrides">A list of overrides to fill</param>
|
|||
|
/// <param name="validCount">Returns the number of valid overrides for GameObjects</param>
|
|||
|
/// <exception cref="ArgumentNullException">The input overrides list is not valid</exception>
|
|||
|
public void GetOverrides(List<KeyValuePair<GameObject, GameObject>> overrides, ref int validCount)
|
|||
|
{
|
|||
|
if (overrides == null)
|
|||
|
throw new ArgumentNullException("overrides");
|
|||
|
|
|||
|
overrides.Clear();
|
|||
|
|
|||
|
List<GameObject> originalGameObjects = new List<GameObject>();
|
|||
|
|
|||
|
if (m_Tile)
|
|||
|
{
|
|||
|
if (m_Tile.m_DefaultGameObject)
|
|||
|
originalGameObjects.Add(m_Tile.m_DefaultGameObject);
|
|||
|
|
|||
|
foreach (RuleTile.TilingRule rule in m_Tile.m_TilingRules)
|
|||
|
if (rule.m_GameObject && !originalGameObjects.Contains(rule.m_GameObject))
|
|||
|
originalGameObjects.Add(rule.m_GameObject);
|
|||
|
}
|
|||
|
|
|||
|
validCount = originalGameObjects.Count;
|
|||
|
|
|||
|
foreach (var pair in m_GameObjects)
|
|||
|
if (!originalGameObjects.Contains(pair.m_OriginalGameObject))
|
|||
|
originalGameObjects.Add(pair.m_OriginalGameObject);
|
|||
|
|
|||
|
foreach (GameObject gameObject in originalGameObjects)
|
|||
|
overrides.Add(new KeyValuePair<GameObject, GameObject>(gameObject, this[gameObject]));
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Updates the Rules with the Overrides set for this RuleOverrideTile
|
|||
|
/// </summary>
|
|||
|
public virtual void Override()
|
|||
|
{
|
|||
|
if (!m_Tile)
|
|||
|
return;
|
|||
|
|
|||
|
if (!m_InstanceTile)
|
|||
|
CreateInstanceTile();
|
|||
|
|
|||
|
PrepareOverride();
|
|||
|
|
|||
|
var tile = m_InstanceTile;
|
|||
|
|
|||
|
tile.m_DefaultSprite = this[tile.m_DefaultSprite] ?? tile.m_DefaultSprite;
|
|||
|
tile.m_DefaultGameObject = this[tile.m_DefaultGameObject] ?? tile.m_DefaultGameObject;
|
|||
|
|
|||
|
foreach (var rule in tile.m_TilingRules)
|
|||
|
{
|
|||
|
for (int i = 0; i < rule.m_Sprites.Length; i++)
|
|||
|
{
|
|||
|
Sprite sprite = rule.m_Sprites[i];
|
|||
|
rule.m_Sprites[i] = this[sprite] ?? sprite;
|
|||
|
}
|
|||
|
|
|||
|
rule.m_GameObject = this[rule.m_GameObject] ?? rule.m_GameObject;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Prepares the Overrides set for this RuleOverrideTile
|
|||
|
/// </summary>
|
|||
|
public void PrepareOverride()
|
|||
|
{
|
|||
|
// Create clone of instanceTile to keep data from collections being overridden by JsonUtility
|
|||
|
var tempTile = Instantiate(m_InstanceTile);
|
|||
|
|
|||
|
var customData = m_InstanceTile.GetCustomFields(true)
|
|||
|
.ToDictionary(field => field, field => field.GetValue(tempTile));
|
|||
|
|
|||
|
JsonUtility.FromJsonOverwrite(JsonUtility.ToJson(m_Tile), m_InstanceTile);
|
|||
|
|
|||
|
foreach (var kvp in customData)
|
|||
|
kvp.Key.SetValue(m_InstanceTile, kvp.Value);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Retrieves any tile animation data from the scripted tile.
|
|||
|
/// </summary>
|
|||
|
/// <param name="position">Position of the Tile on the Tilemap.</param>
|
|||
|
/// <param name="tilemap">The Tilemap the tile is present on.</param>
|
|||
|
/// <param name="tileAnimationData">Data to run an animation on the tile.</param>
|
|||
|
/// <returns>Whether the call was successful.</returns>
|
|||
|
public override bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, ref TileAnimationData tileAnimationData)
|
|||
|
{
|
|||
|
if (!m_InstanceTile)
|
|||
|
return false;
|
|||
|
return m_InstanceTile.GetTileAnimationData(position, tilemap, ref tileAnimationData);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Retrieves any tile rendering data from the scripted tile.
|
|||
|
/// </summary>
|
|||
|
/// <param name="position">Position of the Tile on the Tilemap.</param>
|
|||
|
/// <param name="tilemap">The Tilemap the tile is present on.</param>
|
|||
|
/// <param name="tileData">Data to render the tile.</param>
|
|||
|
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
|
|||
|
{
|
|||
|
if (!m_InstanceTile)
|
|||
|
return;
|
|||
|
m_InstanceTile.GetTileData(position, tilemap, ref tileData);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// This method is called when the tile is refreshed.
|
|||
|
/// </summary>
|
|||
|
/// <param name="position">Position of the Tile on the Tilemap.</param>
|
|||
|
/// <param name="tilemap">The Tilemap the tile is present on.</param>
|
|||
|
public override void RefreshTile(Vector3Int position, ITilemap tilemap)
|
|||
|
{
|
|||
|
if (!m_InstanceTile)
|
|||
|
return;
|
|||
|
m_InstanceTile.RefreshTile(position, tilemap);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// StartUp is called on the first frame of the running Scene.
|
|||
|
/// </summary>
|
|||
|
/// <param name="position">Position of the Tile on the Tilemap.</param>
|
|||
|
/// <param name="tilemap">The Tilemap the tile is present on.</param>
|
|||
|
/// <param name="go">The GameObject instantiated for the Tile.</param>
|
|||
|
/// <returns>Whether StartUp was successful</returns>
|
|||
|
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
|
|||
|
{
|
|||
|
if (!m_InstanceTile)
|
|||
|
return true;
|
|||
|
return m_InstanceTile.StartUp(position, tilemap, go);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Callback when the tile is enabled
|
|||
|
/// </summary>
|
|||
|
public void OnEnable()
|
|||
|
{
|
|||
|
if (m_Tile == null)
|
|||
|
return;
|
|||
|
|
|||
|
if (m_InstanceTile == null)
|
|||
|
Override();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|