MaximilianPs

CatalogueGenerator

Mar 8th, 2022 (edited)
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 17.14 KB | None | 0 0
  1. ///<summary> ========= READ ME ======================================================================================= ///
  2. ///                                                                                                                    ///
  3. ///     OK THIS IS HOW IT WORKS                                                                                        ///
  4. ///     Actually you can use it to picture it any kind of GameObject                                                   ///
  5. ///                                                                                                                    ///
  6. ///     You can child all of you assets inside a parent:                                                               ///
  7. ///         1) Select your parent, and in inspector lock it (on top right of inspector tab).                           ///
  8. ///         2) Add this component.                                                                                     ///
  9. ///         3) Select all of yours gameObjects from the Hierarchy tab.                                                 ///
  10. ///         4) Set the name of the folder where the pictures will be saved, no sub-folders sorry :P                    ///
  11. ///         5) Click on Start check-box.                                                                               ///
  12. ///                                                                                                                    ///
  13. ///     You can use Restore check-box to re-enable all of gameObject that gets disabled if something                   ///
  14. ///     goes wrong.                                                                                                    ///
  15. ///                                                                                                                    ///
  16. /// ========= Additional Informations for Devs and Curious =========================================================== ///
  17. ///                                                                                                                    ///
  18. ///     The SetCrator method will analyze the name looking for an ID (like armor_01_...)                               ///
  19. ///     and then try to search for other components that could be associated to it:                                    ///
  20. ///         ex.: _A01 or _01A_ or 01_A_                                                                                ///
  21. ///     So the Set will be composed with different gameObjects that will be Enabled for the screenshots.               ///
  22. ///     Also it will store all gameObjects enabled in a different list, on this way when the mainLoop will check       ///
  23. ///     for the GO that have been already shotted will skip it.                                                        ///
  24. ///                                                                                                                    ///
  25. ///                                                                                                                    ///
  26. ///////////////////////////////////////// In case of issue you can find me on Discord MaximilianPs#6061 /////// </summary>
  27.  
  28. using System;
  29. using System.Reflection;
  30. using System.Collections.Generic;
  31. using System.Linq;
  32. using UnityEditor;
  33. using UnityEngine;
  34.  
  35. namespace MaximilianPs.Utility
  36. {
  37.     [ExecuteInEditMode]
  38.     public class CatalogueGenerator : MonoBehaviour
  39.     {
  40.         [Header("SCREENSHOTS PARAMETER")]
  41.         [Tooltip("Screenshot Resolution")]
  42.         [SerializeField] int witdh = 512;
  43.         [SerializeField] int height = 512;
  44.         [Space]
  45.         [Tooltip("This is the folder starting from your Assets folder, " +
  46.                  "so leave it empty to save all of your screenshots inside the default Assets folder. NO SUBFOLDERS!")]
  47.         [SerializeField] string folderName = "Screenshots";
  48.         [Space]
  49.         [Header("SET YOUR TARGET")]
  50.         [Tooltip("Insert here all of your GameObjects")]
  51.         [SerializeField] List<GameObject> targets;
  52.         [Space]
  53.         [Tooltip("Insert a single (ONLY 1) character that split the name in various elements")]
  54.         [SerializeField] string separator = "_";
  55.         [Space]
  56.         [Tooltip("This words are used for specific type that you want to be shotted all together, CASE SENSITIVE!")]
  57.         [SerializeField] List<string> specificType = new List<string>{"naked", "plate", "leather","cloth"};
  58.         [Tooltip("Check it if you want to use specific types")]
  59.         [SerializeField] bool useSpecificType = false;
  60.         [Space]
  61.         [Tooltip("Check this if you want a screenshot per each item")]
  62.         [SerializeField] bool oneShotPerItem = false;
  63.         [Tooltip("This words are used for specific type that you want to be shotted all together, CASE SENSITIVE!")]
  64.         [SerializeField] List<string> removeWords = new List<string> { "body", "gauntlets", "legs", "boots", "cape"};
  65.         [Space]
  66.         [SerializeField] bool start = false;
  67.         [Space]
  68.         [Tooltip("Check this to re-enable all gameObjects")]
  69.         [SerializeField] bool restore = false;
  70.  
  71.         // Internal Lists used to store each Set of or anything that you would like to have a picture.
  72.         List<GameObject> currentSet = new List<GameObject>();
  73.         List<GameObject> unpairedSet = new List<GameObject>();
  74.         [Space]
  75.         [SerializeField] List<string> log = new List<string>();
  76.         private string setID = string.Empty;  // this is the Letter Identifier for the Set (_A_01, _A_02...)
  77.         private List<string> letters = new List<string> { "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
  78.  
  79.  
  80.  
  81.         private void Update()
  82.         {
  83.             if (start)
  84.             {
  85.                 Debug.Log("Let's start");
  86.                 log.Clear();
  87.                 separator = separator.Substring(0, 1); // Never know what the user can type xD
  88.  
  89.                 if (currentSet.Count > 0)
  90.                     currentSet.Clear();
  91.  
  92.                 int counter = 0;
  93.  
  94.                 // Disable each Game Object
  95.                 ToggleEnable(false);
  96.  
  97.                 if (useSpecificType && !oneShotPerItem)
  98.                 {
  99.                     UseSpecificType();
  100.                 }
  101.  
  102.                 for (int i = 0; i < targets.Count; i++)
  103.                 {
  104.                     if (log.Contains(targets[i].name))
  105.                         continue;
  106.  
  107.                     if(!oneShotPerItem)
  108.                     {
  109.                         if (SetCreator(i) > 0)
  110.                         {
  111.                             for (int x = 0; x < currentSet.Count; x++)
  112.                             {
  113.                                 Debug.Log("Added " + setID + "_" + i.ToString());
  114.                                 log.Add(currentSet[x].name);
  115.                                 currentSet[x].SetActive(true);
  116.                             }
  117.  
  118.                             counter++;
  119.                             Screenshot(NameCleaner(folderName), "Set_" + setID + "_" + NameCleaner(targets[i].name), witdh, height);
  120.                         }
  121.                         else
  122.                         {
  123.                             if (!log.Contains(targets[i].name))
  124.                                 unpairedSet.Add(targets[i]);
  125.                         }
  126.                     }
  127.                     else
  128.                     {
  129.                         unpairedSet.Add(targets[i]);
  130.                     }
  131.  
  132.                     ToggleEnable(false);
  133.                     currentSet.Clear();
  134.  
  135.                     // break; // just for testing purpose
  136.                 }
  137.  
  138.                 if (unpairedSet.Count > 0)
  139.                 {
  140.                     Debug.Log("We got elements in Unpaired Sets...");
  141.  
  142.                     foreach (GameObject equipment in unpairedSet)
  143.                     {
  144.                         if (log.Contains(equipment.name))
  145.                             continue;
  146.  
  147.                         equipment.SetActive(true);
  148.                         counter++;
  149.                         Screenshot(NameCleaner(folderName), NameCleaner("Set_" + counter.ToString("D2") + "_" + NameCleaner(equipment.name)), witdh, height);
  150.                         equipment.SetActive(false);
  151.                     }
  152.                 }
  153.  
  154.                 ToggleEnable(true);
  155.  
  156.                 currentSet.Clear();
  157.                 unpairedSet.Clear();
  158.                 start = false;
  159.                
  160.                 Debug.Log("Operation Complete, check you "+ folderName + " folder.");
  161.  
  162.             }
  163.  
  164.             if (restore)
  165.             {
  166.                 ToggleEnable(true);
  167.                 currentSet.Clear();
  168.                 log.Clear();
  169.                 restore = false;
  170.                 Debug.Log("Restore Complete");
  171.  
  172.             }
  173.         }
  174.  
  175.         private void UseSpecificType()
  176.         {
  177.             int targetID = -1;
  178.  
  179.             for (int i = 0; i < specificType.Count; i++)
  180.             {
  181.                 for (int x = 0; x < targets.Count; x++)
  182.                 {
  183.                     if(targetID == -1)
  184.                         targetID = GetID(targets[x].name); // Catch the number from the name.
  185.  
  186.                     if (targets[x].name.Contains(specificType[i]))
  187.                     {
  188.  
  189.                         log.Add(targets[x].name);
  190.                         currentSet.Add(targets[x]);
  191.                         targets[x].SetActive(true);
  192.                     }
  193.                 }
  194.  
  195.                 if(currentSet.Count > 0)
  196.                 {
  197.                     Screenshot(NameCleaner(folderName), "Set_" + targetID.ToString("D2") + "_" + NameCleaner(specificType[i]), witdh, height);
  198.                     currentSet.Clear();
  199.                     ToggleEnable(false);
  200.                 }
  201.             }
  202.  
  203.         }
  204.  
  205.         /// <summary>
  206.         /// Given a number (+1) will set a Set in the list CurrentSet.
  207.         /// </summary>
  208.         private int SetCreator(int id)
  209.         {
  210.             currentSet.Clear();
  211.  
  212.             int targetID = GetID(targets[id].name); // Catch the number from the name.
  213.  
  214.             if (targetID > -1)
  215.             {
  216.                 setID = SetIdentifier(targets[id].name, targetID, id); // Get the Identifier
  217.                 if (setID != string.Empty)
  218.                 {
  219.                     // Now we know we have the identifier A_01
  220.                     for (int i = 0; i < targets.Count; i++)
  221.                     {
  222.                         if (log.Contains(targets[i].name))
  223.                             continue;
  224.  
  225.                         if (targets[i].name.Contains(setID))
  226.                         {
  227.                             log.Add(targets[i].name);   // Adding GO to Log List
  228.                             currentSet.Add(targets[i]);
  229.                         }
  230.                     }
  231.                 }
  232.                 else // PROLLY we have a different Set for example, if Body_01 and Legs_01, means that we have sets identified by ID
  233.                 {
  234.                     currentSet.Clear();
  235.  
  236.                     for (int i = id; i < targets.Count; i++)
  237.                     {
  238.                         if (targets[i].name.Contains(targetID.ToString("D2")) && !log.Contains(targets[i].name))
  239.                         {
  240.                             log.Add(targets[i].name);
  241.                             currentSet.Add(targets[i]);
  242.                         }
  243.                     }
  244.                 }
  245.             }
  246.  
  247.             return currentSet.Count;
  248.         }
  249.  
  250.         /// <summary>
  251.         /// Search for any character that contain a number, and if the parse will success
  252.         /// return an int with the number converted, if fails return -1.
  253.         /// </summary>
  254.         private int GetID(string text)
  255.         {
  256.             int number = -1;
  257.             string tempStr = text; // the string that contain only the number
  258.  
  259.             List<string> tempStrings = text.Split(separator[0]).ToList<string>();
  260.            
  261.  
  262.             for (int i = 0; i < tempStrings.Count; i++)
  263.             {
  264.                 if (tempStrings[i].Any(char.IsLetter))
  265.                     continue; // Quit ASAP, 'cause if there is a letter, can't be our ID!
  266.                 else
  267.                     tempStr = tempStrings[i];
  268.             }
  269.  
  270.             tempStr = new string(tempStr.Where(char.IsDigit).ToArray());
  271.  
  272.             int.TryParse(tempStr, out number);
  273.  
  274.             if (number > -1)
  275.                 return number;
  276.             else
  277.                 return -1;
  278.         }
  279.  
  280.         private string SetIdentifier(string objectName, int id, int targetId)
  281.         {
  282.             // PT_Medieval_Female_Armor_01_A_body
  283.             char sep = separator[0];
  284.             List<string> tempStrings = objectName.Split(sep).ToList<string>();
  285.            
  286.             // Search for identifier
  287.             if (tempStrings.Count > 0)
  288.             {
  289.                 // cycle all elements found in the string
  290.                 for (int cnt = 0; cnt < tempStrings.Count; cnt++)       // For each sting part
  291.                 {
  292.                     for (int i = 0; i < letters.Count; i++)             // we check if a letter
  293.                     {
  294.                         if(letters[i].ToLower() == tempStrings[cnt].ToLower()) // is the same.
  295.                         {
  296.                             // we found the Set identifier
  297.                             string finalString = string.Empty;
  298.                             if (objectName.Contains(id.ToString() + sep + tempStrings[cnt]))
  299.                                 finalString = id.ToString("D2") + sep + tempStrings[cnt];    
  300.                            
  301.                             if (objectName.Contains(tempStrings[cnt] + sep + id.ToString()))
  302.                                 finalString = tempStrings[cnt] + sep + id.ToString("D2");
  303.  
  304.                             return finalString;
  305.                         }
  306.                     }
  307.                 }
  308.             }
  309.             return string.Empty;
  310.         }
  311.  
  312.         /// <summary>
  313.         /// Enable (true) or Disable (false) gameObjects
  314.         /// </summary>
  315.         private void ToggleEnable(bool toggle)
  316.         {
  317.             for (int i = 0; i < targets.Count; i++)
  318.             {
  319.                 //Debug.Log("Disabling " + targets[i]);
  320.                 targets[i].SetActive(toggle);
  321.             }
  322.         }
  323.  
  324.         /// <summary>
  325.         /// Clean from every unsafe character for a file or a folder
  326.         /// </summary>
  327.         /// <param name="fileName"></param>
  328.         /// <returns></returns>
  329.         private string NameCleaner(string fileName)
  330.         {
  331.             if(fileName.Length > 0)
  332.             {
  333.                 foreach (char c in System.IO.Path.GetInvalidFileNameChars())
  334.                 {
  335.                     fileName = fileName.Replace(c.ToString(), "");
  336.                 }
  337.  
  338.                 foreach (string word in removeWords)
  339.                 {
  340.                     if (fileName.Contains(word))
  341.                         fileName = fileName.Replace(separator + word, "");
  342.                 }
  343.  
  344.                 fileName.Replace("__", "_");
  345.  
  346.                 if (fileName[fileName.Length - 1] == '_')
  347.                     fileName = fileName[fileName.Length - 1].ToString();
  348.             }
  349.             else
  350.                 fileName = "NO_NAME_" + setID;
  351.  
  352.             return fileName;
  353.         }
  354.        
  355.         /// <summary>
  356.         /// Clean the AssetName so it's File/Folder name-safe.
  357.         /// </summary>
  358.         /// <param name="folder"></param>
  359.         private void CheckFolder(string folder)
  360.         {
  361.             if (!System.IO.Directory.Exists(Application.dataPath + "/" + folder))
  362.             {
  363.                 System.IO.Directory.CreateDirectory(Application.dataPath + "/" + folder);
  364.             }
  365.         }
  366.  
  367.         ///<summary>
  368.         /// It will take a screenshot from the main camera.
  369.         /// </summary>
  370.         public bool Screenshot(string path, string fileName, int resWidth = 512, int resHeight = 512)
  371.         {
  372.             Camera camera = Camera.main;
  373.             try
  374.             {
  375.                 RenderTexture rt = new RenderTexture(resWidth, resHeight, 24);
  376.                 camera.targetTexture = rt;
  377.                 Texture2D screenShot = new Texture2D(resWidth, resHeight, TextureFormat.RGB24, false);
  378.                 camera.Render();
  379.                 RenderTexture.active = rt;
  380.                 screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0);
  381.                 camera.targetTexture = null;
  382.                 RenderTexture.active = null; // JC: added to avoid errors
  383.                 DestroyImmediate(rt);
  384.  
  385.                 CheckFolder(path);
  386.  
  387.                 byte[] bytes = screenShot.EncodeToPNG();
  388.                 string filename = Application.dataPath + "/" + path + "/" + fileName + ".png";
  389.                 System.IO.File.WriteAllBytes(filename, bytes);
  390.                 // Debug.Log(string.Format("Took screenshot to: {0}", filename));
  391.  
  392.                 return true;
  393.             }
  394.             catch (System.Exception ex)
  395.             {
  396.                 Debug.LogError("Screenshot (" + resWidth + "x" + resHeight + ") failed on " + fileName + "<br/> Details: " + ex.Message);
  397.                 return false;
  398.             }
  399.  
  400.         }
  401.     }
  402. }
Add Comment
Please, Sign In to add comment