public void OnEnable()
        {
            Instance = (TextureArrayCreatorAsset)target;

            m_so                 = serializedObject;
            m_selectedSize       = m_so.FindProperty("m_selectedSize");
            m_lockRatio          = m_so.FindProperty("m_lockRatio");
            m_sizeX              = m_so.FindProperty("m_sizeX");
            m_sizeY              = m_so.FindProperty("m_sizeY");
            m_tex3DMode          = m_so.FindProperty("m_tex3DMode");
            m_linearMode         = m_so.FindProperty("m_linearMode");
            m_mipMaps            = m_so.FindProperty("m_mipMaps");
            m_wrapMode           = m_so.FindProperty("m_wrapMode");
            m_filterMode         = m_so.FindProperty("m_filterMode");
            m_anisoLevel         = m_so.FindProperty("m_anisoLevel");
            m_selectedFormatEnum = m_so.FindProperty("m_selectedFormatEnum");
            m_quality            = m_so.FindProperty("m_quality");
            m_folderPath         = m_so.FindProperty("m_folderPath");
            m_fileName           = m_so.FindProperty("m_fileName");
            m_filenameChanged    = m_so.FindProperty("m_filenameChanged");
            m_allTextures        = m_so.FindProperty("m_allTextures");

            if (m_listTextures == null)
            {
                m_listTextures = new ReorderableList(m_so, m_allTextures, true, true, true, true);
                m_listTextures.elementHeight = 16;

                m_listTextures.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
                {
                    m_allTextures.GetArrayElementAtIndex(index).objectReferenceValue = (Texture2D)EditorGUI.ObjectField(rect, "Texture " + index, m_allTextures.GetArrayElementAtIndex(index).objectReferenceValue, typeof(Texture2D), false);
                };

                m_listTextures.drawHeaderCallback = ( Rect rect ) =>
                {
                    m_previewSize = EditorGUI.IntSlider(rect, "Texture List", m_previewSize, 16, 64);
                    if ((float)m_previewSize != m_listTextures.elementHeight)
                    {
                        m_listTextures.elementHeight = m_previewSize;
                    }
                };

                m_listTextures.onAddCallback = (list) =>
                {
                    m_allTextures.InsertArrayElementAtIndex(m_allTextures.arraySize);
                    m_allTextures.GetArrayElementAtIndex(m_allTextures.arraySize - 1).objectReferenceValue = null;
                };

                m_listTextures.onRemoveCallback = (list) =>
                {
                    m_allTextures.GetArrayElementAtIndex(list.index).objectReferenceValue = null;
                    m_allTextures.DeleteArrayElementAtIndex(list.index);
                };
            }

            m_dragAndDropTool = new DragAndDropTool();
            m_dragAndDropTool.OnValidDropObjectEvt += OnValidObjectsDropped;
        }
        private void BuildArray(TextureArrayCreatorAsset asset)
        {
            int sizeX = asset.SizeX;
            int sizeY = asset.SizeY;

            Texture2DArray textureArray = new Texture2DArray(sizeX, sizeY, asset.AllTextures.Count, asset.SelectedFormatEnum, asset.MipMaps, asset.LinearMode);

            textureArray.wrapMode   = asset.WrapMode;
            textureArray.filterMode = asset.FilterMode;
            textureArray.anisoLevel = asset.AnisoLevel;
            textureArray.Apply(false);
            RenderTexture cache = RenderTexture.active;
            RenderTexture rt    = new RenderTexture(sizeX, sizeY, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Default);

            rt.Create();
            for (int i = 0; i < asset.AllTextures.Count; i++)
            {
                // build report
                int widthChanges = asset.AllTextures[i].width <sizeX ? -1 : asset.AllTextures[i].width> sizeX ? 1 : 0;
                int heightChanges = asset.AllTextures[i].height <sizeY ? -1 : asset.AllTextures[i].height> sizeY ? 1 : 0;
                if ((widthChanges < 0 && heightChanges <= 0) || (widthChanges <= 0 && heightChanges < 0))
                {
                    m_message += asset.AllTextures[i].name + " was upscaled\n";
                }
                else if ((widthChanges > 0 && heightChanges >= 0) || (widthChanges >= 0 && heightChanges > 0))
                {
                    m_message += asset.AllTextures[i].name + " was downscaled\n";
                }
                else if ((widthChanges > 0 && heightChanges < 0) || (widthChanges < 0 && heightChanges > 0))
                {
                    m_message += asset.AllTextures[i].name + " changed dimensions\n";
                }

                // blit image to upscale or downscale the image to any size
                RenderTexture.active = rt;

                bool cachedsrgb = GL.sRGBWrite;
                GL.sRGBWrite = !asset.LinearMode;
                Graphics.Blit(asset.AllTextures[i], rt);
                GL.sRGBWrite = cachedsrgb;

                Texture2D t2d = new Texture2D(sizeX, sizeY, asset.SelectedFormatEnum, asset.MipMaps, asset.LinearMode);
                t2d.ReadPixels(new Rect(0, 0, sizeX, sizeY), 0, 0, asset.MipMaps);
                RenderTexture.active = null;

                bool isCompressed = UncompressedFormats.FindIndex(x => x.Equals(asset.SelectedFormatEnum)) < 0;
                if (isCompressed)
                {
                    EditorUtility.CompressTexture(t2d, asset.SelectedFormatEnum, asset.Quality);
                    t2d.Apply(false);
                }

                if (asset.MipMaps)
                {
                    int maxSize   = Mathf.Max(sizeX, sizeY);
                    int numLevels = 1 + (int)Mathf.Floor(Mathf.Log(maxSize, 2));
                    for (int mip = 0; mip < numLevels; mip++)
                    {
                        CopyToArray(ref t2d, ref textureArray, i, mip, isCompressed);
                    }
                }
                else
                {
                    CopyToArray(ref t2d, ref textureArray, i, 0, isCompressed);
                }
            }

            rt.Release();
            RenderTexture.active = cache;
            if (m_message.Length > 0)
            {
                m_message = m_message.Substring(0, m_message.Length - 1);
            }

            string         path    = asset.FolderPath + asset.FileName + ".asset";
            Texture2DArray outfile = AssetDatabase.LoadMainAssetAtPath(path) as Texture2DArray;

            if (outfile != null)
            {
                EditorUtility.CopySerialized(textureArray, outfile);
                AssetDatabase.SaveAssets();
                EditorGUIUtility.PingObject(outfile);
                m_lastSaved = outfile;
            }
            else
            {
                AssetDatabase.CreateAsset(textureArray, path);
                EditorGUIUtility.PingObject(textureArray);
                m_lastSaved = textureArray;
            }
        }
        void OnGUI()
        {
            TextureArrayCreatorAsset currentAsset = null;

            if (m_asset != null)
            {
                currentAsset = m_asset;
            }
            else
            {
                if (m_dummyAsset == null)
                {
                    m_dummyAsset      = ScriptableObject.CreateInstance <TextureArrayCreatorAsset>();
                    m_dummyAsset.name = "Dummy";
                }
                currentAsset = m_dummyAsset;
            }

            m_scrollPos = EditorGUILayout.BeginScrollView(m_scrollPos, GUILayout.Height(position.height));
            float cachedWidth = EditorGUIUtility.labelWidth;

            EditorGUIUtility.labelWidth = 100;
            EditorGUILayout.BeginVertical(m_contentStyle);

            string buildButtonStr = currentAsset.Tex3DMode ? BuildTexture3DMessage : BuildArrayMessage;

            // build button
            EditorGUILayout.BeginHorizontal();
            EditorGUI.BeginDisabledGroup(currentAsset.AllTextures.Count <= 0);
            if (GUILayout.Button(buildButtonStr, "prebutton", GUILayout.Height(20)))
            {
                bool showWarning = false;
                for (int i = 0; i < currentAsset.AllTextures.Count; i++)
                {
                    if (currentAsset.AllTextures[i].width != currentAsset.SizeX || currentAsset.AllTextures[i].height != currentAsset.SizeY)
                    {
                        showWarning = true;
                    }
                }

                if (!showWarning)
                {
                    m_message = string.Empty;
                    if (currentAsset.Tex3DMode)
                    {
                        BuildTexture3D(currentAsset);
                    }
                    else
                    {
                        BuildArray(currentAsset);
                    }
                }
                else if (EditorUtility.DisplayDialog("Warning!", "Some textures need to be resized to fit the selected size. Do you want to continue?", "Yes", "No"))
                {
                    m_message = string.Empty;
                    if (currentAsset.Tex3DMode)
                    {
                        BuildTexture3D(currentAsset);
                    }
                    else
                    {
                        BuildArray(currentAsset);
                    }
                }
            }
            EditorGUI.EndDisabledGroup();
            EditorGUI.BeginDisabledGroup(m_lastSaved == null);
            GUIContent icon = EditorGUIUtility.IconContent("icons/d_ViewToolZoom.png");

            if (GUILayout.Button(icon, "prebutton", GUILayout.Width(28), GUILayout.Height(20)))
            {
                EditorGUIUtility.PingObject(m_lastSaved);
            }
            EditorGUI.EndDisabledGroup();
            EditorGUILayout.EndHorizontal();

            // message
            if (!string.IsNullOrEmpty(m_message))
            {
                if (GUILayout.Button("BUILD REPORT (click to hide):\n\n" + m_message, "helpbox"))
                {
                    m_message = string.Empty;
                }
            }

            // asset
            EditorGUILayout.BeginHorizontal();
            m_asset = EditorGUILayout.ObjectField("Asset Preset", m_asset, typeof(TextureArrayCreatorAsset), false) as TextureArrayCreatorAsset;
            if (GUILayout.Button(m_asset != null ? "Save" : "Create", "minibutton", GUILayout.Width(50)))
            {
                string defaultName = "ArrayPreset";
                if (m_asset != null)
                {
                    defaultName = m_asset.name;
                }

                string path = EditorUtility.SaveFilePanelInProject("Save as", defaultName, "asset", string.Empty);
                if (!string.IsNullOrEmpty(path))
                {
                    TextureArrayCreatorAsset outfile = AssetDatabase.LoadMainAssetAtPath(path) as TextureArrayCreatorAsset;
                    if (outfile != null)
                    {
                        EditorUtility.CopySerialized(currentAsset, outfile);
                        AssetDatabase.SaveAssets();
                        Selection.activeObject = outfile;
                        EditorGUIUtility.PingObject(outfile);
                    }
                    else
                    {
                        if (m_asset != null)
                        {
                            currentAsset = ScriptableObject.CreateInstance <TextureArrayCreatorAsset>();
                            EditorUtility.CopySerialized(m_asset, currentAsset);
                        }
                        AssetDatabase.CreateAsset(currentAsset, path);
                        Selection.activeObject = currentAsset;
                        EditorGUIUtility.PingObject(currentAsset);
                        m_asset = currentAsset;
                    }
                }
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Separator();

            if (Event.current.type == EventType.Layout)
            {
                if (m_editor == null)
                {
                    m_editor = Editor.CreateEditor(currentAsset, typeof(TextureArrayCreatorAssetEditor)) as TextureArrayCreatorAssetEditor;
                }
                else
                {
                    if (m_editor.Instance != currentAsset)
                    {
                        DestroyImmediate(m_editor);
                        m_editor = Editor.CreateEditor(currentAsset, typeof(TextureArrayCreatorAssetEditor)) as TextureArrayCreatorAssetEditor;
                    }
                }
            }
            if (m_editor != null)
            {
                m_editor.OnInspectorGUI();
            }

            GUILayout.Space(20);
            EditorGUILayout.EndVertical();
            EditorGUIUtility.labelWidth = cachedWidth;
            EditorGUILayout.EndScrollView();
        }
        private void BuildTexture3D(TextureArrayCreatorAsset asset)
        {
            int sizeX = asset.SizeX;
            int sizeY = asset.SizeY;

            Texture3D texture3D = new Texture3D(sizeX, sizeY, asset.AllTextures.Count, asset.SelectedFormatEnum, asset.MipMaps);

            texture3D.wrapMode   = asset.WrapMode;
            texture3D.filterMode = asset.FilterMode;
            texture3D.anisoLevel = asset.AnisoLevel;
            //texture3D.Apply( false );
            RenderTexture cache = RenderTexture.active;
            RenderTexture rt    = new RenderTexture(sizeX, sizeY, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);

            rt.Create();
            List <Texture2D> textures = new List <Texture2D>(asset.AllTextures.Count);

            for (int i = 0; i < asset.AllTextures.Count; i++)
            {
                // build report
                int widthChanges = asset.AllTextures[i].width <sizeX ? -1 : asset.AllTextures[i].width> sizeX ? 1 : 0;
                int heightChanges = asset.AllTextures[i].height <sizeY ? -1 : asset.AllTextures[i].height> sizeY ? 1 : 0;
                if ((widthChanges < 0 && heightChanges <= 0) || (widthChanges <= 0 && heightChanges < 0))
                {
                    m_message += asset.AllTextures[i].name + " was upscaled\n";
                }
                else if ((widthChanges > 0 && heightChanges >= 0) || (widthChanges >= 0 && heightChanges > 0))
                {
                    m_message += asset.AllTextures[i].name + " was downscaled\n";
                }
                else if ((widthChanges > 0 && heightChanges < 0) || (widthChanges < 0 && heightChanges > 0))
                {
                    m_message += asset.AllTextures[i].name + " changed dimensions\n";
                }

                // blit image to upscale or downscale the image to any size
                RenderTexture.active = rt;

                bool cachedsrgb = GL.sRGBWrite;
                GL.sRGBWrite = !asset.LinearMode;
                Graphics.Blit(asset.AllTextures[i], rt);
                GL.sRGBWrite = cachedsrgb;

                textures.Add(new Texture2D(sizeX, sizeY, TextureFormat.ARGB32, asset.MipMaps, asset.LinearMode));
                textures[i].ReadPixels(new Rect(0, 0, sizeX, sizeY), 0, 0, asset.MipMaps);
                RenderTexture.active = null;

                bool isCompressed = UncompressedFormats.FindIndex(x => x.Equals(asset.SelectedFormatEnum)) < 0;
                if (isCompressed)
                {
                    EditorUtility.CompressTexture(textures[i], asset.SelectedFormatEnum, asset.Quality);
                    //	t2d.Apply( false );
                }
                textures[i].Apply(false);
            }

            rt.Release();
            RenderTexture.active = cache;

            if (m_message.Length > 0)
            {
                m_message = m_message.Substring(0, m_message.Length - 1);
            }

            int sizeZ = textures.Count;

            Color[] colors = new Color[sizeX * sizeY * sizeZ];
            int     idx    = 0;

            for (int z = 0; z < sizeZ; z++)
            {
                for (int y = 0; y < sizeY; y++)
                {
                    for (int x = 0; x < sizeX; x++, idx++)
                    {
                        colors[idx] = textures[z].GetPixel(x, y);
                    }
                }
            }

            texture3D.SetPixels(colors);
            texture3D.Apply();

            string    path    = asset.FolderPath + asset.FileName + ".asset";
            Texture3D outfile = AssetDatabase.LoadMainAssetAtPath(path) as Texture3D;

            if (outfile != null)
            {
                EditorUtility.CopySerialized(texture3D, outfile);
                AssetDatabase.SaveAssets();
                EditorGUIUtility.PingObject(outfile);
                m_lastSaved = outfile;
            }
            else
            {
                AssetDatabase.CreateAsset(texture3D, path);
                EditorGUIUtility.PingObject(texture3D);
                m_lastSaved = texture3D;
            }
        }
        private void BuildTexture3D(TextureArrayCreatorAsset asset)
        {
            int sizeX     = asset.SizeX;
            int sizeY     = asset.SizeY;
            int numLevels = 1 + (int)Mathf.Floor(Mathf.Log(Mathf.Max(sizeX, sizeY), 2));
            int mipCount  = asset.MipMaps ? numLevels : 1;

            Texture3D texture3D = new Texture3D(sizeX, sizeY, asset.AllTextures.Count, asset.SelectedFormatEnum, asset.MipMaps);

            texture3D.wrapMode   = asset.WrapMode;
            texture3D.filterMode = asset.FilterMode;
            texture3D.anisoLevel = asset.AnisoLevel;
            texture3D.Apply(false);
            RenderTexture cache = RenderTexture.active;
            RenderTexture rt    = new RenderTexture(sizeX, sizeY, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Default);

            rt.Create();
            List <List <Color> > mipColor = new List <List <Color> >();

            if (asset.MipMaps)
            {
                for (int i = 0; i < mipCount; i++)
                {
                    mipColor.Add(new List <Color>());
                }
            }
            else
            {
                mipColor.Add(new List <Color>());
            }

            for (int i = 0; i < asset.AllTextures.Count; i++)
            {
                // build report
                int widthChanges = asset.AllTextures[i].width <sizeX ? -1 : asset.AllTextures[i].width> sizeX ? 1 : 0;
                int heightChanges = asset.AllTextures[i].height <sizeY ? -1 : asset.AllTextures[i].height> sizeY ? 1 : 0;
                if ((widthChanges < 0 && heightChanges <= 0) || (widthChanges <= 0 && heightChanges < 0))
                {
                    m_message += asset.AllTextures[i].name + " was upscaled\n";
                }
                else if ((widthChanges > 0 && heightChanges >= 0) || (widthChanges >= 0 && heightChanges > 0))
                {
                    m_message += asset.AllTextures[i].name + " was downscaled\n";
                }
                else if ((widthChanges > 0 && heightChanges < 0) || (widthChanges < 0 && heightChanges > 0))
                {
                    m_message += asset.AllTextures[i].name + " changed dimensions\n";
                }

                // blit image to upscale or downscale the image to any size
                RenderTexture.active = rt;

                bool cachedsrgb = GL.sRGBWrite;
                GL.sRGBWrite = !asset.LinearMode;
                Graphics.Blit(asset.AllTextures[i], rt);
                GL.sRGBWrite = cachedsrgb;

                bool          isCompressed          = UncompressedFormats.FindIndex(x => x.Equals(asset.SelectedFormatEnum)) < 0;
                TextureFormat validReadPixelsFormat = isCompressed ? TextureFormat.RGBAFloat : asset.SelectedFormatEnum;
                Texture2D     t2d = new Texture2D(sizeX, sizeY, validReadPixelsFormat, asset.MipMaps, asset.LinearMode);
                t2d.ReadPixels(new Rect(0, 0, sizeX, sizeY), 0, 0, asset.MipMaps);
                RenderTexture.active = null;

                if (isCompressed)
                {
                    EditorUtility.CompressTexture(t2d, asset.SelectedFormatEnum, asset.Quality);
                    //	t2d.Apply( false );
                }
                t2d.Apply(false);

                if (asset.MipMaps)
                {
                    for (int mip = 0; mip < mipCount; mip++)
                    {
                        mipColor[mip].AddRange(t2d.GetPixels(mip));
                    }
                }
                else
                {
                    mipColor[0].AddRange(t2d.GetPixels(0));
                }
            }

            rt.Release();
            RenderTexture.active = cache;

            if (m_message.Length > 0)
            {
                m_message = m_message.Substring(0, m_message.Length - 1);
            }

            for (int i = 0; i < mipCount; i++)
            {
                texture3D.SetPixels(mipColor[i].ToArray(), i);
            }

            texture3D.Apply(false);

            string    path    = asset.FolderPath + asset.FileName + ".asset";
            Texture3D outfile = AssetDatabase.LoadMainAssetAtPath(path) as Texture3D;

            if (outfile != null)
            {
                EditorUtility.CopySerialized(texture3D, outfile);
                AssetDatabase.SaveAssets();
                EditorGUIUtility.PingObject(outfile);
                m_lastSaved = outfile;
            }
            else
            {
                AssetDatabase.CreateAsset(texture3D, path);
                EditorGUIUtility.PingObject(texture3D);
                m_lastSaved = texture3D;
            }
        }