Wikipedia:Article wizard2.0

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Allows to save the state of the Beast Lightmaps (Tiling/Offset, GameObjects lightmap index etc), and restore it later. Can merge different lightmap sessions!)
 
(content should have been removed as it was moved to Beast Helper)
Line 1: Line 1:
[[Category: Wizard]]
 
[[Category: ScriptableObject]]
 
[[Category: C Sharp]]
 
  
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>
 

Revision as of 17:32, 19 September 2011

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox