Skip to content

Instantly share code, notes, and snippets.

@ruccho
Last active January 7, 2018 10:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ruccho/ec664c062e5344849e6070ced3fcefa1 to your computer and use it in GitHub Desktop.
Save ruccho/ec664c062e5344849e6070ced3fcefa1 to your computer and use it in GitHub Desktop.
ウディタ規格のオートタイルに対応したやつ
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.Tilemaps
{
[Serializable]
public class WolfAutoTile : TileBase
{
[SerializeField]
public Sprite[] m_RawTilesSprites;
public Sprite[] m_PatternedSprites;
public override void RefreshTile(Vector3Int location, ITilemap tileMap)
{
for (int yd = -1; yd <= 1; yd++)
for (int xd = -1; xd <= 1; xd++)
{
Vector3Int position = new Vector3Int(location.x + xd, location.y + yd, location.z);
if (TileValue(tileMap, position))
tileMap.RefreshTile(position);
}
}
public override void GetTileData(Vector3Int location, ITilemap tileMap, ref TileData tileData)
{
UpdateTile(location, tileMap, ref tileData);
return;
}
private void UpdateTile(Vector3Int location, ITilemap tileMap, ref TileData tileData)
{
if (m_PatternedSprites == null)
{
if (m_RawTilesSprites[0] && m_RawTilesSprites[1] && m_RawTilesSprites[2] && m_RawTilesSprites[3] && m_RawTilesSprites[4])
{
GeneratePatterns();
}
else
{
return;
}
}
tileData.transform = Matrix4x4.identity;
tileData.color = Color.white;
int mask = TileValue(tileMap, location + new Vector3Int(0, 1, 0)) ? 1 : 0;
mask += TileValue(tileMap, location + new Vector3Int(1, 1, 0)) ? 2 : 0;
mask += TileValue(tileMap, location + new Vector3Int(1, 0, 0)) ? 4 : 0;
mask += TileValue(tileMap, location + new Vector3Int(1, -1, 0)) ? 8 : 0;
mask += TileValue(tileMap, location + new Vector3Int(0, -1, 0)) ? 16 : 0;
mask += TileValue(tileMap, location + new Vector3Int(-1, -1, 0)) ? 32 : 0;
mask += TileValue(tileMap, location + new Vector3Int(-1, 0, 0)) ? 64 : 0;
mask += TileValue(tileMap, location + new Vector3Int(-1, 1, 0)) ? 128 : 0;
int index = GetIndex((byte)mask);
if (index >= 0 && index < m_PatternedSprites.Length && TileValue(tileMap, location))
{
tileData.sprite = m_PatternedSprites[index];
tileData.color = Color.white;
tileData.flags = (TileFlags.LockTransform | TileFlags.LockColor);
tileData.colliderType = Tile.ColliderType.Sprite;
}
}
private bool TileValue(ITilemap tileMap, Vector3Int position)
{
TileBase tile = tileMap.GetTile(position);
return (tile != null && tile == this);
}
private int GetIndex(byte mask)
{
string[] patternTexts = {
"x0x111x0",
"x11111x0",
"x111x0x0",
"x10111x0",
"x11101x0",
"01111111",
"11111101",
"x0x1x0x0",
"x0x11111",
"11111111",
"1111x0x1",
"x0x10111",
"1101x0x1",
"11011111",
"11110111",
"x0x1x0x1",
"x0x0x111",
"11x0x111",
"11x0x0x1",
"x0x11101",
"0111x0x1",
"01110111",
"11011101",
"x0x0x0x1",
"x0x101x0",
"x10101x0",
"x101x0x0",
"01x0x111",
"11x0x101",
"11010101",
"01010111",
"11010111",
"x0x10101",
"01010101",
"0101x0x1",
"11110101",
"01011111",
"01110101",
"01011101",
"01111101",
"x0x0x101",
"01x0x101",
"01x0x0x1",
"x0x0x1x0",
"x1x0x1x0",
"x1x0x0x0",
"x0x0x0x0"
};
int index = -1;
for (int j = 0; j < patternTexts.Length; j++)
{
bool flag = true;
for (int i = 0; i < 8; i++)
{
if (patternTexts[j][i] != 'x')
{
char currentBitChar = ((mask & (byte)Mathf.Pow(2, 7 - i)) != 0) ? '1' : '0';
if (patternTexts[j][i] != currentBitChar)
{
flag = false;
break;
}
}
}
if (flag)
{
index = j;
break;
}
}
return index;
}
Sprite[,] Segments = new Sprite[5, 4];
int[][] Patterns = new int[][]
{
new int[] {0,2,1,4},
new int[] {2,2,4,4},
new int[] {2,0,4,1},
new int[] {2,2,3,4},
new int[] {2,2,4,3},
new int[] {3,4,4,4},
new int[] {4,3,4,4},
new int[] {0,0,1,1},
new int[] {1,4,1,4},
new int[] {4,4,4,4},
new int[] {4,1,4,1},
new int[] {1,4,1,3},
new int[] {4,1,3,1},
new int[] {4,4,3,4},
new int[] {4,4,4,3},
new int[] {1,1,1,1},
new int[] {1,4,0,2},
new int[] {4,4,2,2},
new int[] {4,1,2,0},
new int[] {1,3,1,4},
new int[] {3,1,4,1},
new int[] {3,4,4,3},
new int[] {4,3,3,4},
new int[] {1,1,0,0},
new int[] {0,2,1,3},
new int[] {2,2,3,3},
new int[] {2,0,3,1},
new int[] {3,4,2,2},
new int[] {4,3,2,2},
new int[] {4,3,3,3},
new int[] {3,4,3,3},
new int[] {4,4,3,3},
new int[] {1,3,1,3},
new int[] {3,3,3,3},
new int[] {3,1,3,1},
new int[] {4,3,4,3},
new int[] {3,4,3,4},
new int[] {3,3,4,3},
new int[] {3,3,3,4},
new int[] {3,3,4,4},
new int[] {1,3,0,2},
new int[] {3,3,2,2},
new int[] {3,1,2,0},
new int[] {0,2,0,2},
new int[] {2,2,2,2},
new int[] {2,0,2,0},
new int[] {0,0,0,0}
};
public void GeneratePatterns()
{
for (int i = 0; i < 5; i++)
{
Texture2D tex = m_RawTilesSprites[i].texture;
int y = (int)m_RawTilesSprites[i].rect.y;
int x = (int)m_RawTilesSprites[i].rect.x;
int height = (int)m_RawTilesSprites[i].rect.height;
int width = (int)m_RawTilesSprites[i].rect.width;
int height_half = height / 2;
int width_half = width / 2;
Segments[i, 0] = Sprite.Create(tex, new Rect(x, y, width_half, height_half), Vector2.zero);
Segments[i, 1] = Sprite.Create(tex, new Rect(x + width_half, y, width_half, height_half), Vector2.zero);
Segments[i, 2] = Sprite.Create(tex, new Rect(x, y + height_half, width_half, height_half), Vector2.zero);
Segments[i, 3] = Sprite.Create(tex, new Rect(x + width_half, y + height_half, width_half, height_half), Vector2.zero);
}
m_PatternedSprites = new Sprite[47];
for (int i = 0; i < 47; i++)
{
m_PatternedSprites[i] = CombineTextures(Patterns[i]);
}
}
private Sprite CombineTextures(int[] TypeIndex)
{
int[] fixedArray = new int[4];
fixedArray[0] = TypeIndex[2];
fixedArray[1] = TypeIndex[3];
fixedArray[2] = TypeIndex[0];
fixedArray[3] = TypeIndex[1];
Color[][] texs = new Color[4][];
for (int i = 0; i < 4; i++)
{
int x = (int)Segments[fixedArray[i], i].rect.x;
int y = (int)Segments[fixedArray[i], i].rect.y;
int w = (int)Segments[fixedArray[i], i].rect.width;
int h = (int)Segments[fixedArray[i], i].rect.height;
texs[i] = Segments[fixedArray[i], i].texture.GetPixels(x, y, w, h);
}
int width_half = (int)Segments[0, 0].rect.width;
int height_half = (int)Segments[0, 0].rect.height;
int width = width_half * 2;
int height = height_half * 2;
Color[] texArray = new Color[width * height];
for (int i = 0; i < height_half; i++)
{
Array.Copy(texs[0], i * width_half, texArray, i * width, width_half);
}
for (int i = 0; i < height_half; i++)
{
Array.Copy(texs[1], i * width_half, texArray, i * width + width_half, width_half);
}
for (int i = 0; i < height_half; i++)
{
Array.Copy(texs[2], i * width_half, texArray, (i + height_half) * width, width_half);
}
for (int i = 0; i < height_half; i++)
{
Array.Copy(texs[3], i * width_half, texArray, (i + height_half) * width + width_half, width_half);
}
Texture2D ret = new Texture2D(width, height, TextureFormat.ARGB32, false);
ret.filterMode = FilterMode.Point;
ret.wrapMode = TextureWrapMode.Clamp;
ret.SetPixels(texArray);
return Sprite.Create(ret, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), width);
}
#if UNITY_EDITOR
[MenuItem("Assets/Create/WolfAuto Tile")]
public static void CreateTerrainTile()
{
string path = EditorUtility.SaveFilePanelInProject("Save WolfAuto Tile", "New WolfAuto Tile", "asset", "Save WolfAuto Tile", "Assets");
if (path == "")
return;
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<WolfAutoTile>(), path);
}
#endif
}
#if UNITY_EDITOR
[CustomEditor(typeof(WolfAutoTile))]
public class WolfAutoTileEditor : Editor
{
private WolfAutoTile tile { get { return (target as WolfAutoTile); } }
public void OnEnable()
{
if (tile.m_RawTilesSprites == null || tile.m_RawTilesSprites.Length != 15)
{
tile.m_RawTilesSprites = new Sprite[15];
EditorUtility.SetDirty(tile);
}
if (tile.m_RawTilesSprites[0] && tile.m_RawTilesSprites[1] && tile.m_RawTilesSprites[2] && tile.m_RawTilesSprites[3] && tile.m_RawTilesSprites[4])
{
tile.GeneratePatterns();
}
}
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("ウディタ規格のオートタイルチップを上から順番にスロットしてください。(アニメーション非対応)");
EditorGUILayout.Space();
float oldLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 210;
EditorGUI.BeginChangeCheck();
tile.m_RawTilesSprites[0] = (Sprite)EditorGUILayout.ObjectField("上下左右どこにもこのオートタイルがない(直角に配置したときの外側の角に現れる)", tile.m_RawTilesSprites[0], typeof(Sprite), false, null);
tile.m_RawTilesSprites[1] = (Sprite)EditorGUILayout.ObjectField("上下にこのオートタイルがある", tile.m_RawTilesSprites[1], typeof(Sprite), false, null);
tile.m_RawTilesSprites[2] = (Sprite)EditorGUILayout.ObjectField("左右にこのオートタイルがある", tile.m_RawTilesSprites[2], typeof(Sprite), false, null);
tile.m_RawTilesSprites[3] = (Sprite)EditorGUILayout.ObjectField("直角にこのオートタイルを配置したとき、内側の角に現れる", tile.m_RawTilesSprites[3], typeof(Sprite), false, null);
tile.m_RawTilesSprites[4] = (Sprite)EditorGUILayout.ObjectField("このオートタイルに周囲を全て囲まれている", tile.m_RawTilesSprites[4], typeof(Sprite), false, null);
if (EditorGUI.EndChangeCheck())
{
if (tile.m_RawTilesSprites[0] && tile.m_RawTilesSprites[1] && tile.m_RawTilesSprites[2] && tile.m_RawTilesSprites[3] && tile.m_RawTilesSprites[4])
{
tile.GeneratePatterns();
}
EditorUtility.SetDirty(tile);
}
EditorGUIUtility.labelWidth = oldLabelWidth;
}
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment