Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ///<summary> ========= READ ME ======================================================================================= ///
- /// ///
- /// OK THIS IS HOW IT WORKS ///
- /// Actually you can use it to picture it any kind of GameObject ///
- /// ///
- /// You can child all of you assets inside a parent: ///
- /// 1) Select your parent, and in inspector lock it (on top right of inspector tab). ///
- /// 2) Add this component. ///
- /// 3) Select all of yours gameObjects from the Hierarchy tab. ///
- /// 4) Set the name of the folder where the pictures will be saved, no sub-folders sorry :P ///
- /// 5) Click on Start check-box. ///
- /// ///
- /// You can use Restore check-box to re-enable all of gameObject that gets disabled if something ///
- /// goes wrong. ///
- /// ///
- /// ========= Additional Informations for Devs and Curious =========================================================== ///
- /// ///
- /// The SetCrator method will analyze the name looking for an ID (like armor_01_...) ///
- /// and then try to search for other components that could be associated to it: ///
- /// ex.: _A01 or _01A_ or 01_A_ ///
- /// So the Set will be composed with different gameObjects that will be Enabled for the screenshots. ///
- /// Also it will store all gameObjects enabled in a different list, on this way when the mainLoop will check ///
- /// for the GO that have been already shotted will skip it. ///
- /// ///
- /// ///
- ///////////////////////////////////////// In case of issue you can find me on Discord MaximilianPs#6061 /////// </summary>
- using System;
- using System.Reflection;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEditor;
- using UnityEngine;
- namespace MaximilianPs.Utility
- {
- [ExecuteInEditMode]
- public class CatalogueGenerator : MonoBehaviour
- {
- [Header("SCREENSHOTS PARAMETER")]
- [Tooltip("Screenshot Resolution")]
- [SerializeField] int witdh = 512;
- [SerializeField] int height = 512;
- [Space]
- [Tooltip("This is the folder starting from your Assets folder, " +
- "so leave it empty to save all of your screenshots inside the default Assets folder. NO SUBFOLDERS!")]
- [SerializeField] string folderName = "Screenshots";
- [Space]
- [Header("SET YOUR TARGET")]
- [Tooltip("Insert here all of your GameObjects")]
- [SerializeField] List<GameObject> targets;
- [Space]
- [Tooltip("Insert a single (ONLY 1) character that split the name in various elements")]
- [SerializeField] string separator = "_";
- [Space]
- [Tooltip("This words are used for specific type that you want to be shotted all together, CASE SENSITIVE!")]
- [SerializeField] List<string> specificType = new List<string>{"naked", "plate", "leather","cloth"};
- [Tooltip("Check it if you want to use specific types")]
- [SerializeField] bool useSpecificType = false;
- [Space]
- [Tooltip("Check this if you want a screenshot per each item")]
- [SerializeField] bool oneShotPerItem = false;
- [Tooltip("This words are used for specific type that you want to be shotted all together, CASE SENSITIVE!")]
- [SerializeField] List<string> removeWords = new List<string> { "body", "gauntlets", "legs", "boots", "cape"};
- [Space]
- [SerializeField] bool start = false;
- [Space]
- [Tooltip("Check this to re-enable all gameObjects")]
- [SerializeField] bool restore = false;
- // Internal Lists used to store each Set of or anything that you would like to have a picture.
- List<GameObject> currentSet = new List<GameObject>();
- List<GameObject> unpairedSet = new List<GameObject>();
- [Space]
- [SerializeField] List<string> log = new List<string>();
- private string setID = string.Empty; // this is the Letter Identifier for the Set (_A_01, _A_02...)
- 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" };
- private void Update()
- {
- if (start)
- {
- Debug.Log("Let's start");
- log.Clear();
- separator = separator.Substring(0, 1); // Never know what the user can type xD
- if (currentSet.Count > 0)
- currentSet.Clear();
- int counter = 0;
- // Disable each Game Object
- ToggleEnable(false);
- if (useSpecificType && !oneShotPerItem)
- {
- UseSpecificType();
- }
- for (int i = 0; i < targets.Count; i++)
- {
- if (log.Contains(targets[i].name))
- continue;
- if(!oneShotPerItem)
- {
- if (SetCreator(i) > 0)
- {
- for (int x = 0; x < currentSet.Count; x++)
- {
- Debug.Log("Added " + setID + "_" + i.ToString());
- log.Add(currentSet[x].name);
- currentSet[x].SetActive(true);
- }
- counter++;
- Screenshot(NameCleaner(folderName), "Set_" + setID + "_" + NameCleaner(targets[i].name), witdh, height);
- }
- else
- {
- if (!log.Contains(targets[i].name))
- unpairedSet.Add(targets[i]);
- }
- }
- else
- {
- unpairedSet.Add(targets[i]);
- }
- ToggleEnable(false);
- currentSet.Clear();
- // break; // just for testing purpose
- }
- if (unpairedSet.Count > 0)
- {
- Debug.Log("We got elements in Unpaired Sets...");
- foreach (GameObject equipment in unpairedSet)
- {
- if (log.Contains(equipment.name))
- continue;
- equipment.SetActive(true);
- counter++;
- Screenshot(NameCleaner(folderName), NameCleaner("Set_" + counter.ToString("D2") + "_" + NameCleaner(equipment.name)), witdh, height);
- equipment.SetActive(false);
- }
- }
- ToggleEnable(true);
- currentSet.Clear();
- unpairedSet.Clear();
- start = false;
- Debug.Log("Operation Complete, check you "+ folderName + " folder.");
- }
- if (restore)
- {
- ToggleEnable(true);
- currentSet.Clear();
- log.Clear();
- restore = false;
- Debug.Log("Restore Complete");
- }
- }
- private void UseSpecificType()
- {
- int targetID = -1;
- for (int i = 0; i < specificType.Count; i++)
- {
- for (int x = 0; x < targets.Count; x++)
- {
- if(targetID == -1)
- targetID = GetID(targets[x].name); // Catch the number from the name.
- if (targets[x].name.Contains(specificType[i]))
- {
- log.Add(targets[x].name);
- currentSet.Add(targets[x]);
- targets[x].SetActive(true);
- }
- }
- if(currentSet.Count > 0)
- {
- Screenshot(NameCleaner(folderName), "Set_" + targetID.ToString("D2") + "_" + NameCleaner(specificType[i]), witdh, height);
- currentSet.Clear();
- ToggleEnable(false);
- }
- }
- }
- /// <summary>
- /// Given a number (+1) will set a Set in the list CurrentSet.
- /// </summary>
- private int SetCreator(int id)
- {
- currentSet.Clear();
- int targetID = GetID(targets[id].name); // Catch the number from the name.
- if (targetID > -1)
- {
- setID = SetIdentifier(targets[id].name, targetID, id); // Get the Identifier
- if (setID != string.Empty)
- {
- // Now we know we have the identifier A_01
- for (int i = 0; i < targets.Count; i++)
- {
- if (log.Contains(targets[i].name))
- continue;
- if (targets[i].name.Contains(setID))
- {
- log.Add(targets[i].name); // Adding GO to Log List
- currentSet.Add(targets[i]);
- }
- }
- }
- else // PROLLY we have a different Set for example, if Body_01 and Legs_01, means that we have sets identified by ID
- {
- currentSet.Clear();
- for (int i = id; i < targets.Count; i++)
- {
- if (targets[i].name.Contains(targetID.ToString("D2")) && !log.Contains(targets[i].name))
- {
- log.Add(targets[i].name);
- currentSet.Add(targets[i]);
- }
- }
- }
- }
- return currentSet.Count;
- }
- /// <summary>
- /// Search for any character that contain a number, and if the parse will success
- /// return an int with the number converted, if fails return -1.
- /// </summary>
- private int GetID(string text)
- {
- int number = -1;
- string tempStr = text; // the string that contain only the number
- List<string> tempStrings = text.Split(separator[0]).ToList<string>();
- for (int i = 0; i < tempStrings.Count; i++)
- {
- if (tempStrings[i].Any(char.IsLetter))
- continue; // Quit ASAP, 'cause if there is a letter, can't be our ID!
- else
- tempStr = tempStrings[i];
- }
- tempStr = new string(tempStr.Where(char.IsDigit).ToArray());
- int.TryParse(tempStr, out number);
- if (number > -1)
- return number;
- else
- return -1;
- }
- private string SetIdentifier(string objectName, int id, int targetId)
- {
- // PT_Medieval_Female_Armor_01_A_body
- char sep = separator[0];
- List<string> tempStrings = objectName.Split(sep).ToList<string>();
- // Search for identifier
- if (tempStrings.Count > 0)
- {
- // cycle all elements found in the string
- for (int cnt = 0; cnt < tempStrings.Count; cnt++) // For each sting part
- {
- for (int i = 0; i < letters.Count; i++) // we check if a letter
- {
- if(letters[i].ToLower() == tempStrings[cnt].ToLower()) // is the same.
- {
- // we found the Set identifier
- string finalString = string.Empty;
- if (objectName.Contains(id.ToString() + sep + tempStrings[cnt]))
- finalString = id.ToString("D2") + sep + tempStrings[cnt];
- if (objectName.Contains(tempStrings[cnt] + sep + id.ToString()))
- finalString = tempStrings[cnt] + sep + id.ToString("D2");
- return finalString;
- }
- }
- }
- }
- return string.Empty;
- }
- /// <summary>
- /// Enable (true) or Disable (false) gameObjects
- /// </summary>
- private void ToggleEnable(bool toggle)
- {
- for (int i = 0; i < targets.Count; i++)
- {
- //Debug.Log("Disabling " + targets[i]);
- targets[i].SetActive(toggle);
- }
- }
- /// <summary>
- /// Clean from every unsafe character for a file or a folder
- /// </summary>
- /// <param name="fileName"></param>
- /// <returns></returns>
- private string NameCleaner(string fileName)
- {
- if(fileName.Length > 0)
- {
- foreach (char c in System.IO.Path.GetInvalidFileNameChars())
- {
- fileName = fileName.Replace(c.ToString(), "");
- }
- foreach (string word in removeWords)
- {
- if (fileName.Contains(word))
- fileName = fileName.Replace(separator + word, "");
- }
- fileName.Replace("__", "_");
- if (fileName[fileName.Length - 1] == '_')
- fileName = fileName[fileName.Length - 1].ToString();
- }
- else
- fileName = "NO_NAME_" + setID;
- return fileName;
- }
- /// <summary>
- /// Clean the AssetName so it's File/Folder name-safe.
- /// </summary>
- /// <param name="folder"></param>
- private void CheckFolder(string folder)
- {
- if (!System.IO.Directory.Exists(Application.dataPath + "/" + folder))
- {
- System.IO.Directory.CreateDirectory(Application.dataPath + "/" + folder);
- }
- }
- ///<summary>
- /// It will take a screenshot from the main camera.
- /// </summary>
- public bool Screenshot(string path, string fileName, int resWidth = 512, int resHeight = 512)
- {
- Camera camera = Camera.main;
- try
- {
- RenderTexture rt = new RenderTexture(resWidth, resHeight, 24);
- camera.targetTexture = rt;
- Texture2D screenShot = new Texture2D(resWidth, resHeight, TextureFormat.RGB24, false);
- camera.Render();
- RenderTexture.active = rt;
- screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0);
- camera.targetTexture = null;
- RenderTexture.active = null; // JC: added to avoid errors
- DestroyImmediate(rt);
- CheckFolder(path);
- byte[] bytes = screenShot.EncodeToPNG();
- string filename = Application.dataPath + "/" + path + "/" + fileName + ".png";
- System.IO.File.WriteAllBytes(filename, bytes);
- // Debug.Log(string.Format("Took screenshot to: {0}", filename));
- return true;
- }
- catch (System.Exception ex)
- {
- Debug.LogError("Screenshot (" + resWidth + "x" + resHeight + ") failed on " + fileName + "<br/> Details: " + ex.Message);
- return false;
- }
- }
- }
- }
Add Comment
Please, Sign In to add comment