Example #1
0
    void AddNewTexture(TextureAtlas textureAtlas)
    {
        // load atlas texture from disk
        Texture2D atlasTexture = (Texture2D)AssetDatabase.LoadAssetAtPath(textureAtlas.texturePath, typeof(Texture2D));

        // cut texture rects from atlas texture
        Dictionary <Texture2D, Rect> textureAtlasRects = TextureAtlasHelper.CutTexturesFromAtlasRects(textureAtlas.atlasRects, atlasTexture);

        textureAtlas.atlasRects.Add(_newTextureName, new Rect(0, 0, _newTexture.width, _newTexture.height));

        // update atlas rects
        int size;

        textureAtlas.atlasRects = TextureAtlasHelper.RepackRects(textureAtlas.atlasRects, out size, (_enableAtlasResize) ? _minAtlasSize : textureAtlas.size, (_enableAtlasResize) ? _maxAtlasSize : textureAtlas.size);

        // update atlas size
        textureAtlas.size = size;

        // add new texture to texture rects
        textureAtlasRects.Add(_newTexture, textureAtlas.atlasRects [_newTextureName]);

        TextureAtlasHelper.EnableReading(_newTexture);

        // recreate atlas texture
        TextureAtlasHelper.CreateTexture(textureAtlasRects, textureAtlas.size, textureAtlas.texturePath);

        // save atlas file to disk
        string atlasPath = AssetDatabase.GetAssetPath(_atlasFile);

        textureAtlas.Save(atlasPath);
        AssetDatabase.Refresh();
    }
Example #2
0
    void Generate()
    {
        List <GameObject> prefabs = new List <GameObject> ();

        try {
            // ==================
            // BUILD DICTIONARIES
            // ==================

            Dictionary <Texture2D, HashSet <MeshFilter> >  meshFiltersPerTexture = new Dictionary <Texture2D, HashSet <MeshFilter> > ();
            Dictionary <GameObject, HashSet <MeshFilter> > meshFiltersPerPrefab  = new Dictionary <GameObject, HashSet <MeshFilter> > ();
            HashSet <Texture2D> textures = new HashSet <Texture2D> ();
            for (int i = 0; i < _prefabsNames.Count; i++)
            {
                if (!_prefabSelection [i])
                {
                    continue;
                }
                string     prefabName = _prefabsNames [i];
                GameObject prefab     = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath(string.Format(PREFAB_FILE_PATTERN, _inputFolder, prefabName), typeof(GameObject)));
                PrefabUtility.DisconnectPrefabInstance(prefab);
                prefabs.Add(prefab);

                MeshFilter[] childMeshFilters = prefab.GetComponentsInChildren <MeshFilter> ();
                foreach (MeshFilter meshFilter in childMeshFilters)
                {
                    Renderer renderer = FindRenderer(meshFilter.gameObject);

                    if (renderer == null)
                    {
                        Debug.LogWarning("renderer is null (prefab: " + prefabName + ")");
                        continue;
                    }

                    Material material = renderer.sharedMaterial;

                    if (material.mainTexture == null)
                    {
                        Debug.LogWarning("main texture is null (material: " + material.name + ", prefab: " + prefabName + ")");
                        continue;
                    }

                    Texture2D texture = (Texture2D)material.mainTexture;

                    textures.Add(texture);

                    HashSet <MeshFilter> prefabMeshFilters;
                    if (!meshFiltersPerPrefab.TryGetValue(prefab, out prefabMeshFilters))
                    {
                        prefabMeshFilters = new HashSet <MeshFilter> ();
                        meshFiltersPerPrefab.Add(prefab, prefabMeshFilters);
                    }
                    prefabMeshFilters.Add(meshFilter);

                    HashSet <MeshFilter> textureMeshFilters;
                    if (!meshFiltersPerTexture.TryGetValue(texture, out textureMeshFilters))
                    {
                        textureMeshFilters = new HashSet <MeshFilter> ();
                        meshFiltersPerTexture.Add(texture, textureMeshFilters);
                    }
                    textureMeshFilters.Add(meshFilter);
                }
            }

            // ====================
            // CHANGE READ SETTINGS
            // ====================

            TextureAtlasHelper.EnableReading(textures);

            // ==================
            // CREATE ATLAS RECTS
            // ==================

            int size;
            Dictionary <Texture2D, Rect> atlasRectsPerTexture = TextureAtlasHelper.PackTextures(textures, out size, _minAtlasSize, _maxAtlasSize);
            Dictionary <string, Rect>    atlasRects           = new Dictionary <string, Rect> ();
            foreach (KeyValuePair <Texture2D, Rect> textureAtlasRect in atlasRectsPerTexture)
            {
                string textureName = TextureAtlasHelper.GetAtlasRectId(textureAtlasRect.Key);

                if (atlasRects.ContainsKey(textureName))
                {
                    int    attemptToRename = 1;
                    string newTextureName;
                    while (true)
                    {
                        newTextureName = string.Format("{0} ({1})", textureName, attemptToRename);
                        if (!atlasRects.ContainsKey(newTextureName))
                        {
                            break;
                        }
                        attemptToRename++;
                    }
                    Debug.LogWarning("different textures with same name (newTextureName: " + newTextureName + ")");
                    textureName = newTextureName;
                }

                atlasRects.Add(textureName, textureAtlasRect.Value);
            }

            // ====================
            // CREATE ATLAS TEXTURE
            // ====================

            string atlasTexturePath = string.Format(TEXTURE_FILE_PATTERN, _texturesFolder, _atlasName);

            AssetDatabase.DeleteAsset(atlasTexturePath);
            Texture2D atlasTexture = TextureAtlasHelper.CreateTexture(atlasRectsPerTexture, size, atlasTexturePath);

            // =================
            // UPDATE MESHES UVS
            // =================

            Dictionary <Mesh, Mesh> newMeshes = new Dictionary <Mesh, Mesh> ();
            foreach (KeyValuePair <Texture2D, Rect> textureAtlasRect in atlasRectsPerTexture)
            {
                HashSet <MeshFilter> meshFilters = meshFiltersPerTexture [textureAtlasRect.Key];
                Vector2 scale     = new Vector2(textureAtlasRect.Value.width / (float)size, textureAtlasRect.Value.height / (float)size);
                Vector2 translate = new Vector2(textureAtlasRect.Value.x / (float)size, textureAtlasRect.Value.y / (float)size);
                foreach (MeshFilter meshFilter in meshFilters)
                {
                    Mesh newMesh = new Mesh();
                    Mesh mesh    = meshFilter.sharedMesh;

                    if (mesh == null)
                    {
                        throw new Exception("mesh is null: " + meshFilter.name);
                    }

                    newMesh.name     = mesh.name;
                    newMesh.vertices = mesh.vertices;
                    newMesh.normals  = mesh.normals;

                    Vector2[] newUv = new Vector2[mesh.uv.Length];
                    for (int i = 0; i < mesh.uv.Length; i++)
                    {
                        Vector2 uv = mesh.uv [i];
                        newUv [i] = translate + new Vector2(uv.x * scale.x, uv.y * scale.y);
                    }
                    newMesh.uv = newUv;

                    newMesh.triangles = mesh.triangles;
                    newMesh.tangents  = mesh.tangents;

                    if (_combineChildMeshes)
                    {
                        string         meshName       = meshFilter.name;
                        ColorMaskGroup colorMaskGroup = null;
                        for (int i = 0; i < _colorMaskGroups.Count; i++)
                        {
                            if (meshName.Contains(_colorMaskGroups [i].meshNameFilter))
                            {
                                colorMaskGroup = _colorMaskGroups [i];
                                break;
                            }
                        }

                        if (colorMaskGroup != null)
                        {
                            newMesh.colors = FillColorBuffer(colorMaskGroup.colorMask, mesh.vertices.Length);
                        }
                        else
                        {
                            newMesh.colors = FillColorBuffer(_defaultColor, mesh.vertices.Length);
                        }
                    }

                    newMesh.RecalculateBounds();

                    newMeshes.Add(mesh, newMesh);
                }
            }

            // ====================
            // BUILD ATLAS MATERIAL
            // ====================

            Material atlasMaterial     = new Material(_defaultShader);
            string   atlasMaterialPath = string.Format(MATERIAL_FILE_PATTERN, _materialsFolder, _atlasName);
            AssetDatabase.DeleteAsset(atlasMaterialPath);
            AssetDatabase.CreateAsset(atlasMaterial, atlasMaterialPath);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            atlasMaterial             = (Material)AssetDatabase.LoadAssetAtPath(atlasMaterialPath, typeof(Material));
            atlasMaterial.mainTexture = atlasTexture;

            // ===============
            // SAVE NEW MESHES
            // ===============

            if (_cleanOutputFolder)
            {
                CleanUpFolder("Assets/" + _outputFolder);
                CleanUpFolder("Assets/" + _meshesFolder);
            }

            foreach (KeyValuePair <GameObject, HashSet <MeshFilter> > prefabMeshFilters in meshFiltersPerPrefab)
            {
                GameObject           prefab      = prefabMeshFilters.Key;
                HashSet <MeshFilter> meshFilters = prefabMeshFilters.Value;
                if (_combineChildMeshes)
                {
                    MeshFilter meshFilter;
                    meshFilter = prefab.GetComponent <MeshFilter> ();

                    Mesh sharedMesh = MergeAll(meshFilters, meshFilter, newMeshes);

                    foreach (MeshFilter meshFilter2 in meshFilters)
                    {
                        if (meshFilter2 != meshFilter)
                        {
                            DestroyImmediate(meshFilter2.gameObject);
                        }
                    }

                    if (meshFilter == null)
                    {
                        meshFilter = prefab.AddComponent <MeshFilter> ();
                    }

                    meshFilter.sharedMesh = sharedMesh;

                    Renderer renderer;
                    if ((renderer = FindRenderer(prefab)) == null)
                    {
                        renderer = prefab.AddComponent <MeshRenderer> ();
                    }

                    renderer.sharedMaterial = atlasMaterial;

                    AssetDatabase.CreateAsset(sharedMesh, string.Format(COMBINED_MESH_FILE_PATTERN, _meshesFolder, Guid.NewGuid().ToString()));
                }
                else
                {
                    foreach (MeshFilter meshFilter in meshFilters)
                    {
                        Mesh newMesh = newMeshes [meshFilter.sharedMesh];

                        meshFilter.sharedMesh = newMesh;
                        FindRenderer(meshFilter.gameObject).sharedMaterial = atlasMaterial;

                        AssetDatabase.CreateAsset(newMesh, string.Format(NEW_MESH_FILE_PATTERN, _meshesFolder, newMesh.name, Guid.NewGuid().ToString()));
                    }
                }

                UnityEngine.Object newPrefab = PrefabUtility.CreateEmptyPrefab(string.Format(PREFAB_FILE_PATTERN, _outputFolder, prefab.name));
                PrefabUtility.ReplacePrefab(prefab, newPrefab, ReplacePrefabOptions.ConnectToPrefab);
                DestroyImmediate(prefab);
            }

            // ===============
            // SAVE ATLAS FILE
            // ===============

            TextureAtlas textureAtlas = new TextureAtlas();
            textureAtlas.name        = _atlasName;
            textureAtlas.size        = size;
            textureAtlas.texturePath = atlasTexturePath;
            textureAtlas.atlasRects  = atlasRects;

            textureAtlas.Save(string.Format(ATLAS_FILE_PATTERN, _atlasesFolder, _atlasName));

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        } catch (Exception e) {
            Debug.LogException(e);

            foreach (GameObject prefab in prefabs)
            {
                DestroyImmediate(prefab);
            }
        }
    }