Wikipedia:Article wizard2.0

From Unify Community Wiki
Revision as of 22:30, 29 September 2010 by Rbn 3D (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


Author: Rubén Vallejo

Description

This wizard allows to save the state of your Beast Lightmaps (Tiling/Offset, GameObjects lightmap index etc), and restore it later.

You can merge several lightmapping sessions automatically with this.

Usage

To install, just place the script in Assets/Editor folder. To use, just Go to Window > Beast Helper.

C# - BeastHelper.cs

<csharp>using UnityEngine; using UnityEditor; using System; using System.IO; using System.Text; using System.Runtime.InteropServices;

public class BeastHelper : EditorWindow {

   int ArraySize = 10;
   Vector2 scrollpos1;
   static GameObject[] staticobjects; // Static Gameobjects Array
   static object[,,] arrayobjects = new object[255,50,3];  // array relative to baketex array, contains gamobject(s) and tiling info for each lightmap
   Texture2D[] baketex = new Texture2D[255]; //array of lightmaps
   //---------------------------------------------
   // Add menu named "My Window" to the Window menu
   [MenuItem("Window/Beast Helper")]
   static void Init()
   {
       // Get existing open window or if none, make a new one:
       BeastHelper window = (BeastHelper)EditorWindow.GetWindow(typeof(BeastHelper));
       window.autoRepaintOnSceneChange = true;
       window.title = "Beast Helper";
       window.Show();
       //-------------- Get Lightmapped geometry... ----------------
       GameObject[] gameobjects = (GameObject[])Resources.FindObjectsOfTypeAll(typeof(GameObject));
       int i1 = 0;
       foreach (GameObject g in gameobjects)
       {
           if (g.isStatic)
           {
               i1++;
           }
       }
       staticobjects = new GameObject[i1];
       int i2 = 0;
       foreach (GameObject g in gameobjects)
       {
           if (g.isStatic)
           {
               staticobjects.SetValue((GameObject)g, i2);
               i2++;
           }
       }
       Debug.Log("Static GameObjects count = " + i1);
       for (int i = 0; i < arrayobjects.GetLength(0); i++)
       {
           for (int i3 = 0; i3 < arrayobjects.GetLength(1); i3++)
           {
               arrayobjects[i, i3, 0] = null;
               arrayobjects[i, i3, 1] = (Vector4)new Vector4();
               arrayobjects[i, i3, 2] = (bool)false;
           }
       }
       //----------------------------------------------------------
   }
   void OnGUI()
   {
       GUILayout.Label("Stored Lightmaps", EditorStyles.boldLabel);
       ArraySize = EditorGUILayout.IntField("Array Size(" + ArraySize.ToString() + ")", ArraySize);
       GUILayoutOption[] layout1 = new GUILayoutOption[2];
       layout1[0] = (GUILayoutOption)GUILayout.Height(75);
       layout1[1] = (GUILayoutOption)GUILayout.Width(75);


       scrollpos1 = EditorGUILayout.BeginScrollView(scrollpos1);
       for (int i = 0; i < ArraySize; i++)
       {
           
           // Debug.Log("Loop1 i = " + i);
           EditorGUILayout.BeginHorizontal();
           EditorGUILayout.LabelField(i.ToString(),"", GUILayout.Width(20));
           baketex[i] = (Texture2D)EditorGUILayout.ObjectField((Texture2D)baketex.GetValue(i), typeof(Texture2D), layout1);
           
           //----------- Each GameObject whit [i] lightmap index go here -----------
           for (int i2 = 0; i2 < arrayobjects.GetLength(1); i2++)
           {
                   GUILayout.BeginVertical(GUILayout.Width(300));
                   EditorGUILayout.LabelField("GameObject: " + i2.ToString(), "", GUILayout.Width(300));
                   arrayobjects[i, i2, 0] = (GameObject)EditorGUILayout.ObjectField((GameObject)arrayobjects[i, i2, 0], typeof(GameObject), GUILayout.Width(300));
                   arrayobjects[i, i2, 1] = (Vector4)EditorGUILayout.Vector4Field("Tiling (X-Y) / Offset (X-Y)", (Vector4)arrayobjects[i, i2, 1], GUILayout.Width(300));
                   arrayobjects[i, i2, 2] = (bool)EditorGUILayout.Toggle("Use: ",(bool)arrayobjects[i, i2, 2], GUILayout.Width(300));
                   GUILayout.EndVertical();
           }


           //-------------------------------------------------------------------------


           EditorGUILayout.EndHorizontal();
       }
       EditorGUILayout.EndScrollView();
       Repaint();
       EditorGUILayout.BeginHorizontal();
       //-------------- Buttons -------------------
       if(GUILayout.Button("Read current maps"))
       {
           if (LightmapSettings.lightmaps.Length > ArraySize)
               ArraySize = LightmapSettings.lightmaps.Length;
           Repaint();
           for (int i = 0; i < LightmapSettings.lightmaps.Length; i++)
           {
               // Debug.Log("Loop2 i = " + i);
               baketex.SetValue(LightmapSettings.lightmaps[i].lightmapFar,i);
               //------------- Get objects with same lightmap index ---------
               if (baketex.GetValue(i) != null)
               {
                   var i2 = 0;
                   foreach (GameObject r in staticobjects)
                   {
                       if (r.renderer)
                       {
                           if (r.renderer.lightmapIndex == i)
                           {
                               arrayobjects[i, i2, 0] = (GameObject)r; // The real GameObject
                               arrayobjects[i, i2, 1] = (Vector4)r.renderer.lightmapTilingOffset; // Tiling Lightmap properties
                               arrayobjects[i, i2, 2] = (bool)true; // use it??
                               i2++;
                           }
                       }
                   }
               }
               //------------------------------------------------------------
           }
           Repaint();
       }
       if (GUILayout.Button("Load Maps info from Disk"))
       {
           string path = EditorUtility.OpenFilePanel("Select beast maps info file", Application.dataPath, "ini");
           if (path.Length > 0)
           {
               //-------------- Loading .ini file -------------
               cIni inifile = new cIni(path);
               string mapscountstr = inifile.ReadValue("MAPSCOUNT", "COUNT");
               int mapscount = 0;
               if (mapscountstr.Length > 0)
               {
                   mapscount = int.Parse(mapscountstr);
               }
               if (ArraySize < mapscount)
               {
                   ArraySize = mapscount;
                   Repaint();
               }
               int arrayofsset = 0;
               bool cancel = false;
               switch (EditorUtility.DisplayDialogComplex("Merge with current maps?", "If you choose merge, the loaded maps will be added after the current ones", "Merge", "Replace", "Cancel"))
               {
                   case 0:
                       {
                           for (int i = 0; i < ArraySize; i++)
                           {
                               if (baketex[i] != null)
                                   arrayofsset = i;
                           }
                           if (arrayofsset > 0)
                               arrayofsset++;
                           if ((arrayofsset + mapscount) > ArraySize)
                           {
                               ArraySize = arrayofsset + mapscount;
                           }
                       }
                       break;
                   case 1:
                       {
                           for (int i = 0; i < ArraySize; i++)
                           {
                               // Debug.Log("Loop2 i = " + i);
                               baketex.SetValue(null, i);
                               for (int i2 = 0; i2 < arrayobjects.GetLength(1); i2++)
                               {
                                   arrayobjects[i, i2, 0] = null;
                                   arrayobjects[i, i2, 1] = (Vector4)new Vector4();
                                   arrayobjects[i, i2, 2] = (bool)false;
                               }
                           }
                           Repaint(); 
                       }
                       break;
                   case 2:
                       {
                           cancel = true;
                       }
                       break;
               }
               if (cancel == false)
               {
                   int counter1 = 0;
                   for (int i = arrayofsset; i < ArraySize; i++)
                   {
                       string texpath = inifile.ReadValue("MAPS", counter1.ToString());
                       if (texpath.Length > 0)
                       {
                           baketex.SetValue((Texture2D)AssetDatabase.LoadAssetAtPath(texpath, typeof(Texture2D)), i);
                       }
                       counter1++;
                   }


                   for (int i2 = arrayofsset; i2 < ArraySize; i2++)
                   {
                       int counter2 = 0;
                       for (int i3 = 0; i3 < arrayobjects.GetLength(1); i3++)
                       {
                           string gpath = inifile.ReadValue("MAP" + counter2.ToString(), "GAMEOBJECT" + i3.ToString());
                           string gtiling = inifile.ReadValue("MAP" + counter2.ToString(), "TILING" + i3.ToString());
                           string guse = inifile.ReadValue("MAP" + counter2.ToString(), "USE" + i3.ToString());
                           if (gpath.Length > 0)
                           {
                               arrayobjects[i2, i3, 0] = (GameObject)GameObject.Find(gpath);


                               arrayobjects[i2, i3, 1] = (Vector4)vector4fromstring(gtiling);
                               arrayobjects[i2, i3, 2] = (bool)Convert.ToBoolean(guse);
                           }
                           counter2++;
                       }
                
                   }
               }
               //-----------------------------------------------
           }
       }
       if(GUILayout.Button("Store Maps info to Disk"))
       {
           EditorUtility.DisplayDialog("Important!", "If you want to start a new bake operation whitout lose current maps, move them to another folder in the project view! Beast will remove old maps otherwise!", "Ok");
           string path = EditorUtility.SaveFilePanel("Save beast maps info to file", Application.dataPath, "beast_info", "ini");
           if (path.Length > 0)
           {
               //-------------- Creating .ini file -------------
               if (File.Exists(path))
                   File.Delete(path); // Delete old ini file, otherwise files content will be merged.
               cIni inifile = new cIni(path);
               inifile.WriteValue("MAPSCOUNT", "COUNT", ArraySize.ToString());
               for (int i = 0; i < ArraySize; i++)
               {
                   inifile.WriteValue("MAPS",i.ToString(), AssetDatabase.GetAssetPath(baketex[i]));
               }
               for (int i2 = 0; i2 < ArraySize; i2++)
               {
                   for (int i3 = 0; i3 < arrayobjects.GetLength(1); i3++)
                   {
                       inifile.WriteValue("MAP" + i2.ToString(), "GAMEOBJECT" + i3.ToString(), GetHierarchy((GameObject)arrayobjects[i2,i3,0]));
                       Vector4 tiling = (Vector4)arrayobjects[i2, i3, 1];
                       inifile.WriteValue("MAP" + i2.ToString(), "TILING" + i3.ToString(), "(" + tiling.x.ToString() + "," + tiling.y.ToString() + "," + tiling.w.ToString() + "," + tiling.z.ToString() + ")");
                       inifile.WriteValue("MAP" + i2.ToString(), "USE" + i3.ToString(), arrayobjects[i2, i3, 2].ToString().ToLower());
                   }
                       
               }
               //-----------------------------------------------
           }


       }
       if(GUILayout.Button("Set actual Maps in Beast"))
       {
           bool cancel = false;


           if(!cancel)
           {
               if (EditorUtility.DisplayDialog("Do you want to apply these maps??", "If you have unsaved maps in beast, you will lose them", "Apply", "Cancel"))
               {
                   LightmapData[] maps = LightmapSettings.lightmaps;
                   Array.Resize(ref maps, ArraySize);


                   for (int c2 = 0; c2 < maps.Length; c2++)
                   {
                       maps.SetValue(new LightmapData(), c2);
                   }
                   for (int c1 = 0; c1 < ArraySize; c1++)
                   {
                       maps[c1].lightmapFar = baketex[c1];
                   }

                   LightmapSettings.lightmaps = maps;


                       for (int i2 = 0; i2 < ArraySize; i2++)
                       {
                           for (int i3 = 0; i3 < arrayobjects.GetLength(1); i3++)
                           {
                               bool use = (bool)arrayobjects[i2, i3, 2];
                               if (use == true)
                               {
                                   GameObject g = (GameObject)arrayobjects[i2, i3, 0];
                                   g.renderer.lightmapIndex = i3;
                                   g.renderer.lightmapTilingOffset = (Vector4)arrayobjects[i2, i3, 1];
                               }
                           }


                       }
    
               }
           }
       }
       //------------------------------------------
       EditorGUILayout.EndHorizontal();
       //--------------- Down Buttons -------------
       EditorGUILayout.BeginHorizontal();
       if (GUILayout.Button("Clear All"))
       {
           for (int i = 0; i < ArraySize; i++)
           {
               // Debug.Log("Loop2 i = " + i);
               baketex.SetValue(null, i);
               for (int i2 = 0; i2 < arrayobjects.GetLength(1); i2++)
               {
                   arrayobjects[i, i2, 0] = null;
                   arrayobjects[i, i2, 1] = (Vector4)new Vector4();
                   arrayobjects[i, i2, 2] = (bool)false;
               }
           }
           Repaint();
       }
       //if (GUILayout.Button("Reload Gameobject List"))
       //{
       //}
       if (GUILayout.Button("Close"))
       {
           Close();
       }
       EditorGUILayout.EndHorizontal();
       if (GUI.changed)
           Repaint();
   }
   // Class for handling .ini files...
   public class cIni
   {
       [DllImport("kernel32", SetLastError = true)]
       private static extern int WritePrivateProfileString(string pSection, string pKey, string pValue, string pFile);
       [DllImport("kernel32", SetLastError = true)]
       private static extern int WritePrivateProfileStruct(string pSection, string pKey, string pValue, int pValueLen, string pFile);
       [DllImport("kernel32", SetLastError = true)]
       private static extern int GetPrivateProfileString(string pSection, string pKey, string pDefault, byte[] prReturn, int pBufferLen, string pFile);
       [DllImport("kernel32", SetLastError = true)]
       private static extern int GetPrivateProfileStruct(string pSection, string pKey, byte[] prReturn, int pBufferLen, string pFile);
       private string ls_IniFilename;
       private int li_BufferLen = 256;
       /// <summary>
       /// cINI Constructor
       /// </summary>
       public cIni(string pIniFilename)
       {
           ls_IniFilename = pIniFilename;
       }
       /// <summary>
       /// INI filename (If no path is specifyed the function will look with-in the windows directory for the file)
       /// </summary>
       public string IniFile
       {
           get { return (ls_IniFilename); }
           set { ls_IniFilename = value; }
       }
       /// <summary>
       /// Max return length when reading data (Max: 32767)
       /// </summary>
       public int BufferLen
       {
           get { return li_BufferLen; }
           set
           {
               if (value > 32767) { li_BufferLen = 32767; }
               else if (value < 1) { li_BufferLen = 1; }
               else { li_BufferLen = value; }
           }
       }
       /// <summary>
       /// Read value from INI File
       /// </summary>
       public string ReadValue(string pSection, string pKey, string pDefault)
       {
           return (z_GetString(pSection, pKey, pDefault));
       }
       /// <summary>
       /// Read value from INI File, default = ""
       /// </summary>
       public string ReadValue(string pSection, string pKey)
       {
           return (z_GetString(pSection, pKey, ""));
       }
       /// <summary>
       /// Write value to INI File
       /// </summary>
       public void WriteValue(string pSection, string pKey, string pValue)
       {
           WritePrivateProfileString(pSection, pKey, pValue, this.ls_IniFilename);
       }
       /// <summary>
       /// Remove value from INI File
       /// </summary>
       public void RemoveValue(string pSection, string pKey)
       {
           WritePrivateProfileString(pSection, pKey, null, this.ls_IniFilename);
       }
       /// <summary>
       /// Read values in a section from INI File
       /// </summary>
       public void ReadValues(string pSection, ref Array pValues)
       {
           pValues = z_GetString(pSection, null, null).Split((char)0);
       }
       /// <summary>
       /// Read sections from INI File
       /// </summary>
       public void ReadSections(ref Array pSections)
       {
           pSections = z_GetString(null, null, null).Split((char)0);
       }
       /// <summary>
       /// Remove section from INI File
       /// </summary>
       public void RemoveSection(string pSection)
       {
           WritePrivateProfileString(pSection, null, null, this.ls_IniFilename);
       }
       /// <summary>
       /// Call GetPrivateProfileString / GetPrivateProfileStruct API
       /// </summary>
       private string z_GetString(string pSection, string pKey, string pDefault)
       {
           string sRet = pDefault; byte[] bRet = new byte[li_BufferLen];
           int i = GetPrivateProfileString(pSection, pKey, pDefault, bRet, li_BufferLen, ls_IniFilename);
           sRet = System.Text.Encoding.GetEncoding(1252).GetString(bRet, 0, i).TrimEnd((char)0);
           return (sRet);
       }
   }
   //Return the full hierarchy string of a gameObject, ready for use in GameObject.Find method later...
   string GetHierarchy(GameObject g)
   {
       if (!g || g == null)
       {
           return "";
       }
       string hierarchy = null;
       string gname = g.name;
       Transform parent = g.transform.parent;
       while (parent)
       {
           hierarchy += "/" + parent.gameObject.name;
           parent = parent.parent;
       }
       string inverse = gname + hierarchy;
       string[] arrayh = (string[])inverse.Split(new string[] { "/" }, StringSplitOptions.None);
       Array.Reverse(arrayh);
       return "/" + string.Join("/", arrayh);
   }
   Vector4 vector4fromstring(string vectorstring)
   {
       if (vectorstring == null || vectorstring.Length == 0)
           return new Vector4();
       vectorstring = vectorstring.Substring(1, vectorstring.Length - 2);
       string[] arrayvector = (string[])vectorstring.Split(new string[] { "," }, StringSplitOptions.None);
       Vector4 vectorfinal = new Vector4(float.Parse(arrayvector[0]), float.Parse(arrayvector[1]), float.Parse(arrayvector[2]), float.Parse(arrayvector[3]));
       return vectorfinal;
   }

}</csharp>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox