Advertisement
Guest User

Image To Level

a guest
Dec 25th, 2020
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.33 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.Tilemaps;
  4.  
  5. public class ImageToLevel : MonoBehaviour
  6. {
  7.     public Texture2D analyzeImage;
  8.     public bool advancedMode;
  9.     public Vector2Int tileSize = new Vector2Int(16, 16);
  10.     public Tilemap copyMap;
  11.  
  12.     public CompareTileset tileset;
  13.  
  14.     //Parallel arrays
  15.     public Sprite[] compareSprites;
  16.     public TileBase[] compareTiles;
  17.  
  18.     [Range(0f, 100f)]
  19.     public float precision = 99.9f;
  20.  
  21.     public bool autoClean = true;
  22.     public TileBase[] cleanTiles;
  23.  
  24.     public int AnalyzeImage()
  25.     {
  26.         if (tileset != null)
  27.         {
  28.             compareSprites = tileset.compareSprites;
  29.             compareTiles = tileset.tiles;
  30.             cleanTiles = tileset.tilesForRemoval;
  31.         }
  32.         //Figure out how many tiles are on the map, assume the image is formatted properly
  33.  
  34.         int validTiles = 0;
  35.         List<Vector3Int> positions = new List<Vector3Int>();
  36.         List<TileBase> tiles = new List<TileBase>();
  37.         List<Matrix4x4> rotations = new List<Matrix4x4>();
  38.  
  39.         for (int y = 0; y < analyzeImage.height / tileSize.y; y++)
  40.         {
  41.             for (int x = 0; x < analyzeImage.width / tileSize.x; x++)
  42.             {
  43.                 TileAnalyzeData data = AnalyzeTile(x, y);
  44.                 if (data != null)
  45.                 {
  46.                     positions.Add(new Vector3Int(x, y, 0));
  47.                     tiles.Add(data.tile);
  48.                     rotations.Add(data.matrix);
  49.                     //copyMap.SetTile(new Vector3Int(x, y, 0), data.tile);
  50.                     //copyMap.SetTransformMatrix(new Vector3Int(x, y, 0), data.matrix);
  51.                     validTiles++;
  52.                 }
  53.             }
  54.         }
  55.         copyMap.SetTiles(positions.ToArray(), tiles.ToArray());
  56.         for (int i = 0; i < rotations.Count; i++)
  57.             copyMap.SetTransformMatrix(positions[i], rotations[i]);
  58.         return validTiles;
  59.     }
  60.  
  61.     private TileAnalyzeData AnalyzeTile(int xTile, int yTile)
  62.     {
  63.         //Debug.Log("Analyzing tile " + new Vector2Int(xTile, yTile));
  64.         //TODO: Rotate tile for checking        
  65.         for (int i = 0; i < compareTiles.Length; i++)
  66.         {
  67.             bool valid = true;
  68.             //Normal
  69.             for (int y = 0; y < tileSize.y; y++)
  70.             {
  71.                 if (valid)
  72.                     for (int x = 0; x < tileSize.x; x++)
  73.                     {
  74.  
  75.                         Color imageColor = analyzeImage.GetPixel(xTile * tileSize.x + x, yTile * tileSize.y + y);
  76.  
  77.                         Texture2D texture = compareSprites[i].texture;
  78.                         Vector2Int textureLocation = new Vector2Int((int)compareSprites[i].rect.x + x, (int)compareSprites[i].rect.y + y);
  79.                         Color tileColor = texture.GetPixel(textureLocation.x, textureLocation.y);
  80.  
  81.                         if (!CompareColor(imageColor, tileColor))
  82.                         {
  83.                             valid = false;
  84.                             break;
  85.                         }
  86.                     }
  87.             }
  88.             if (valid)
  89.             {
  90.                 Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 0f), Vector3.one);
  91.                 return new TileAnalyzeData(compareTiles[i], matrix);
  92.             }
  93.  
  94.             //Rotated left
  95.             valid = true;
  96.             for (int y = 0; y < tileSize.y; y++)
  97.             {
  98.                 if (valid)
  99.                     for (int x = 0; x < tileSize.x; x++)
  100.                     {
  101.  
  102.                         Color imageColor = analyzeImage.GetPixel(xTile * tileSize.x + x, yTile * tileSize.y + y);
  103.  
  104.                         Texture2D texture = compareSprites[i].texture;
  105.                         Vector2Int textureLocation = new Vector2Int((int)compareSprites[i].rect.x + y, (int)compareSprites[i].rect.y + (tileSize.x - 1 - x));
  106.                         Color tileColor = texture.GetPixel(textureLocation.x, textureLocation.y);
  107.  
  108.                         if (!CompareColor(imageColor, tileColor))
  109.                         {
  110.                             valid = false;
  111.                             break;
  112.                         }
  113.                     }
  114.             }
  115.             if (valid)
  116.             {
  117.                 Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 90f), Vector3.one);
  118.                 return new TileAnalyzeData(compareTiles[i], matrix);
  119.             }
  120.  
  121.             //Rotated around
  122.             valid = true;
  123.             for (int y = 0; y < tileSize.y; y++)
  124.             {
  125.                 if (valid)
  126.                     for (int x = 0; x < tileSize.x; x++)
  127.                     {
  128.  
  129.                         Color imageColor = analyzeImage.GetPixel(xTile * tileSize.x + x, yTile * tileSize.y + y);
  130.  
  131.                         Texture2D texture = compareSprites[i].texture;
  132.                         Vector2Int textureLocation = new Vector2Int((int)compareSprites[i].rect.x + (tileSize.x - 1 - x), (int)compareSprites[i].rect.y + (tileSize.y - 1 - y));
  133.                         Color tileColor = texture.GetPixel(textureLocation.x, textureLocation.y);
  134.  
  135.                         if (!CompareColor(imageColor, tileColor))
  136.                         {
  137.                             valid = false;
  138.                             break;
  139.                         }
  140.                     }
  141.             }
  142.             if (valid)
  143.             {
  144.                 Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 180f), Vector3.one);
  145.                 return new TileAnalyzeData(compareTiles[i], matrix);
  146.             }
  147.  
  148.             //Rotated right
  149.             valid = true;
  150.             for (int y = 0; y < tileSize.y; y++)
  151.             {
  152.                 if (valid)
  153.                     for (int x = 0; x < tileSize.x; x++)
  154.                     {
  155.  
  156.                         Color imageColor = analyzeImage.GetPixel(xTile * tileSize.x + x, yTile * tileSize.y + y);
  157.  
  158.                         Texture2D texture = compareSprites[i].texture;
  159.                         Vector2Int textureLocation = new Vector2Int((int)compareSprites[i].rect.x + (tileSize.x - 1 - x), (int)compareSprites[i].rect.y + x);
  160.                         Color tileColor = texture.GetPixel(textureLocation.x, textureLocation.y);
  161.  
  162.                         if (!CompareColor(imageColor, tileColor))
  163.                         {
  164.                             valid = false;
  165.                             break;
  166.                         }
  167.                     }
  168.             }
  169.             if (valid)
  170.             {
  171.                 Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 270f), Vector3.one);
  172.                 return new TileAnalyzeData(compareTiles[i], matrix);
  173.             }
  174.  
  175.             //Flipped
  176.             valid = true;
  177.             for (int y = 0; y < tileSize.y; y++)
  178.             {
  179.                 if (valid)
  180.                     for (int x = 0; x < tileSize.x; x++)
  181.                     {
  182.  
  183.                         Color imageColor = analyzeImage.GetPixel(xTile * tileSize.x + x, yTile * tileSize.y + y);
  184.  
  185.                         Texture2D texture = compareSprites[i].texture;
  186.                         Vector2Int textureLocation = new Vector2Int((int)compareSprites[i].rect.x + (tileSize.x - 1 - x), (int)compareSprites[i].rect.y + y);
  187.                         Color tileColor = texture.GetPixel(textureLocation.x, textureLocation.y);
  188.  
  189.                         if (!CompareColor(imageColor, tileColor))
  190.                         {
  191.                             valid = false;
  192.                             break;
  193.                         }
  194.                     }
  195.             }
  196.             if (valid)
  197.             {
  198.                 Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 0f), new Vector3(-1, 1, 1));
  199.                 return new TileAnalyzeData(compareTiles[i], matrix);
  200.             }
  201.  
  202.             //Flipped, Rotated left
  203.             valid = true;
  204.             for (int y = 0; y < tileSize.y; y++)
  205.             {
  206.                 if (valid)
  207.                     for (int x = 0; x < tileSize.x; x++)
  208.                     {
  209.  
  210.                         Color imageColor = analyzeImage.GetPixel(xTile * tileSize.x + x, yTile * tileSize.y + y);
  211.  
  212.                         Texture2D texture = compareSprites[i].texture;
  213.                         Vector2Int textureLocation = new Vector2Int((int)compareSprites[i].rect.x + y, (int)compareSprites[i].rect.y + (tileSize.x - 1 - x));
  214.                         Color tileColor = texture.GetPixel(textureLocation.x, textureLocation.y);
  215.  
  216.                         if (!CompareColor(imageColor, tileColor))
  217.                         {
  218.                             valid = false;
  219.                             break;
  220.                         }
  221.                     }
  222.             }
  223.             if (valid)
  224.             {
  225.                 Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 270f), new Vector3(-1, 1, 1));
  226.                 return new TileAnalyzeData(compareTiles[i], matrix);
  227.             }
  228.  
  229.             //Flipped, Rotated around
  230.             valid = true;
  231.             for (int y = 0; y < tileSize.y; y++)
  232.             {
  233.                 if (valid)
  234.                     for (int x = 0; x < tileSize.x; x++)
  235.                     {
  236.  
  237.                         Color imageColor = analyzeImage.GetPixel(xTile * tileSize.x + x, yTile * tileSize.y + y);
  238.  
  239.                         Texture2D texture = compareSprites[i].texture;
  240.                         Vector2Int textureLocation = new Vector2Int((int)compareSprites[i].rect.x + x, (int)compareSprites[i].rect.y + (tileSize.y - 1 - y));
  241.                         Color tileColor = texture.GetPixel(textureLocation.x, textureLocation.y);
  242.  
  243.                         if (!CompareColor(imageColor, tileColor))
  244.                         {
  245.                             valid = false;
  246.                             break;
  247.                         }
  248.                     }
  249.             }
  250.             if (valid)
  251.             {
  252.                 Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 180f), new Vector3(-1, 1, 1));
  253.                 return new TileAnalyzeData(compareTiles[i], matrix);
  254.             }
  255.  
  256.             //Flipped, Rotated right
  257.             valid = true;
  258.             for (int y = 0; y < tileSize.y; y++)
  259.             {
  260.                 if (valid)
  261.                     for (int x = 0; x < tileSize.x; x++)
  262.                     {
  263.  
  264.                         Color imageColor = analyzeImage.GetPixel(xTile * tileSize.x + x, yTile * tileSize.y + y);
  265.  
  266.                         Texture2D texture = compareSprites[i].texture;
  267.                         Vector2Int textureLocation = new Vector2Int((int)compareSprites[i].rect.x + (tileSize.y - 1 - y), (int)compareSprites[i].rect.y + x);
  268.                         Color tileColor = texture.GetPixel(textureLocation.x, textureLocation.y);
  269.  
  270.                         if (!CompareColor(imageColor, tileColor))
  271.                         {
  272.                             valid = false;
  273.                             break;
  274.                         }
  275.                     }
  276.             }
  277.             if (valid)
  278.             {
  279.                 Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 90f), new Vector3(-1, 1, 1));
  280.                 return new TileAnalyzeData(compareTiles[i], matrix);
  281.             }
  282.         }
  283.  
  284.         return null;
  285.     }
  286.  
  287.     //TODO: Ignore alpha in calculations? Include alpha as ignoring?
  288.     private bool CompareColor(Color color1, Color color2, bool includeAlpha = false)
  289.     {
  290.         if (AlmostEqualRelative(color1.r, color2.r) &&
  291.             AlmostEqualRelative(color1.g, color2.g) &&
  292.             AlmostEqualRelative(color1.b, color2.b) &&
  293.             (includeAlpha ? AlmostEqualRelative(color1.a, color2.a) : true))
  294.             return true;
  295.  
  296.         return false;
  297.     }
  298.  
  299.     bool AlmostEqualRelative(float A, float B)
  300.     {
  301.         float epsilon = (100f - precision) / 100f;
  302.         // Calculate the difference.
  303.         float diff = Mathf.Abs(A - B);
  304.         A = Mathf.Abs(A);
  305.         B = Mathf.Abs(B);
  306.         // Find the largest
  307.         float largest = (B > A) ? B : A;
  308.  
  309.         if (diff <= largest * epsilon)
  310.             return true;
  311.         return false;
  312.     }
  313.  
  314.     /*public Texture2D singleTexture;
  315.     public Sprite singleSprite;
  316.     public void AnalyzeSprite()
  317.     {
  318.         bool valid = singleTexture.width == (int)singleSprite.rect.width && singleTexture.height == (int)singleSprite.rect.height;
  319.         for (int y = 0; y < singleTexture.height; y++)
  320.         {
  321.             if (valid)
  322.                 for (int x = 0; x < singleTexture.width; x++)
  323.                 {
  324.                     Color imageColor = singleTexture.GetPixel(x, y);
  325.                     Color spriteColor = singleSprite.texture.GetPixel((int)singleSprite.rect.x + x, (int)singleSprite.rect.y + y);
  326.                     //Debug.Log("Image color: " + imageColor + ", spriteColor: " + spriteColor);
  327.  
  328.                     if (!imageColor.Equals(spriteColor))
  329.                     {
  330.                         valid = false;
  331.                         break;
  332.                     }
  333.                 }
  334.         }
  335.  
  336.         Debug.Log("Texture size: " + new Vector2Int(singleTexture.width, singleTexture.height) + ", Sprite size: " + singleSprite.rect.size +
  337.             ", these images are" + (valid ? "" : " not") + " the same");
  338.     }*/
  339.        
  340.     public void CleanMap()
  341.     {
  342.         for (int y = copyMap.cellBounds.yMin; y <= copyMap.cellBounds.yMax; y++)
  343.         {
  344.             for (int x = copyMap.cellBounds.xMin; x <= copyMap.cellBounds.xMax; x++)
  345.             {
  346.                 TileBase mapTile = copyMap.GetTile(new Vector3Int(x, y, 0));
  347.                 foreach (TileBase compareTile in cleanTiles)
  348.                     if (mapTile == compareTile)
  349.                         copyMap.SetTile(new Vector3Int(x, y, 0), null);
  350.             }
  351.         }
  352.     }
  353.  
  354.     public void ClearMap()
  355.     {
  356.         copyMap.ClearAllTiles();
  357.     }
  358. }
  359.  
  360. public class TileAnalyzeData
  361. {
  362.     public TileBase tile;
  363.     public Matrix4x4 matrix;
  364.  
  365.     public TileAnalyzeData(TileBase tile, Matrix4x4 matrix)
  366.     {
  367.         this.tile = tile;
  368.         this.matrix = matrix;
  369.     }
  370. }
  371.  
  372. [CustomEditor(typeof(ImageToLevel))]
  373. public class ImageToLevelEditor : Editor
  374. {
  375.     public override void OnInspectorGUI()
  376.     {
  377.         ImageToLevel itl = target as ImageToLevel;
  378.         if (GUILayout.Button(new GUIContent("Analyze", "Analyze the image and convert it to a level")))
  379.         {
  380.             if (itl.autoClean)
  381.                 itl.ClearMap();
  382.  
  383.             double time = EditorApplication.timeSinceStartup;
  384.             int validTiles = itl.AnalyzeImage();
  385.             time = EditorApplication.timeSinceStartup - time;
  386.             float truncatedTime = (float)(Math.Truncate(time * 100.0) / 100.0);
  387.  
  388.             Debug.Log("Placed " + validTiles + " tiles in " + truncatedTime + " seconds");
  389.             if (itl.autoClean)
  390.                 itl.CleanMap();
  391.         }
  392.         DrawDefaultInspector();
  393.         //if (GUILayout.Button(new GUIContent("Analyze single", "Analyze a sprite's data")))
  394.         //    t.AnalyzeSprite();
  395.         if (GUILayout.Button(new GUIContent("Clean Tilemap", "Remove selected tiles from the map")))
  396.             itl.CleanMap();
  397.         if (GUILayout.Button(new GUIContent("Clear Tilemap", "Clears the attached tilemap")))
  398.             itl.ClearMap();
  399.     }
  400. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement