Ejemplo n.º 1
0
    /// <summary>
    /// Helper function that draws the old atlas texture to the new texture, and destroys the old AtlasTexture.
    /// Also updates sprite list of the atlas.
    /// If Atlas.spriteList is null or empty doesn't have effect.
    /// Requires:
    /// AtlasTexture is not null.
    /// Render target is set to newTexture.
    /// </summary>
    /// <param name="newTexture">Texture in which to write old atlas.</param>
    /// <param name="texturePositionFunc"> Function that returns position of old texture inside of the new texture, depending on order in Atlas.spriteList.</param>
    protected void DrawOldAtlas(RenderTexture newTexture, Func <int, Texture, Rect> texturePositionFunc)
    {
        if (Atlas.SpriteList == null || Atlas.SpriteList.Count == 0)
        {
            AtlasTexture = newTexture;
            return;
        }

        Vector2 newTextureSize = new Vector2(newTexture.width, newTexture.height);

        // We will use one mesh to draw everything
        Mesh mesh = new Mesh();

        // If we had made the atlas before, we will need to keep the old sprites intact
        // We will render the old part of the atlas as a single draw call, so we need some
        // variables to do this.
        // Initialize the data we need to fill
        int numberOfVertices = Atlas.SpriteList.Count * 4;

        Vector3[] positions = new Vector3[numberOfVertices];
        Vector2[] uvs       = new Vector2[numberOfVertices];
        int[]     triangles = new int[Atlas.SpriteList.Count * 6];

        // Update all old sprites positions, uvs and triangles
        for (int index = 0; index < Atlas.SpriteList.Count; index++)
        {
            // Set the UV coordinates of sprite in old atlas texture
            SetUvs(index, uvs);
            // Set the positions of vertices and sprite data
            // This will change positions in spriteData, SetUvs must be called before
            SetPosition(texturePositionFunc(index, newTexture), newTextureSize, Atlas.SpriteList[index], positions, index);
            // Set the triangles
            SetTriangles(index, triangles);
        }

        // Add the data to the mesh
        mesh.vertices  = positions;
        mesh.uv        = uvs;
        mesh.triangles = triangles;

        // Set the texture to the atlasing material
        AtlasingMaterial.mainTexture = AtlasTexture;
        // Activate the material
        AtlasingMaterial.SetPass(0);

        // Draw the mesh to the new atlas
        Graphics.DrawMeshNow(mesh, Matrix4x4.identity);

        Object.Destroy(mesh);

        Object.Destroy(AtlasTexture);

        AtlasTexture = newTexture;

        MarkTextureForReusage();
    }
Ejemplo n.º 2
0
    /// <summary>
    /// Draws all new textures on atlas texture and creates/updates list of sprite data.
    /// Requires:
    /// textures is not null or empty; texturePositions contain position for every texture starting from indexOfFirstTexturePosition.
    /// Render target is set to desired texture.
    /// </summary>
    /// <param name="textures">Textures to be added to atlas texture.</param>
    /// <param name="texturePositionsFunc">This func should return positions of new textures in AtlasTexture and it will be called with index of element and atlas texture. Positions of new textures to be added should start from index specified by third argument.</param>
    /// <param name="indexOfFirstTexturePosition">Index of position of first texture in texturePositions list.</param>
    /// <param name="fillUnusedPlaces">Whether unused sprites should be swapped with new textures.</param>
    protected void DrawNewTextures(List <Texture> textures, Func <int, Texture, Rect> texturePositionsFunc, int indexOfFirstTexturePosition,
                                   bool fillUnusedPlaces)
    {
        // Mesh we will write to.
        Mesh mesh = new Mesh();

        mesh.MarkDynamic();

        // Initialize the data we need to fill
        Vector3[] positions = new Vector3[4];
        Vector2[] uvs       = new Vector2[4];
        int[]     triangles = new int[6];

        int j = 0;

        for (int i = 0; i < textures.Count; i++)
        {
            DynamicSpriteData spriteData = null;

            if (fillUnusedPlaces)
            {
                // first fill empty places, if there is no more empty places fill unused places
                Rect spritePosition = texturePositionsFunc(i + indexOfFirstTexturePosition, AtlasTexture);
                if (spritePosition.xMax > AtlasTexture.width || spritePosition.yMax > AtlasTexture.height)
                {
                    spriteData = FindFirstUnusedSprite(ref j);
                }
            }

            if (spriteData != null)
            {
                // unused sprite found
                numberOfUnused--;
                Atlas.RenameSprite(spriteData.Name, textures[i].name);
                SetPosition(texturePositionsFunc(j - 1, AtlasTexture), TextureSize, spriteData, positions, 0);
                indexOfFirstTexturePosition--;
            }
            else
            {
                spriteData = new DynamicSpriteData(textures[i].name);
                Atlas.AddSprite(spriteData);

                // Set the positions, and sprite data.
                SetPosition(texturePositionsFunc(i + indexOfFirstTexturePosition, AtlasTexture), TextureSize, spriteData, positions, 0);
            }

            spriteData.Reset();
            spriteData.Acquire();

            // Set the UVs
            SetupUvs(uvs, textures[i]);

            // Set the triangles
            SetTriangles(0, triangles);

            mesh.Clear();
            // Add the data to the mesh
            mesh.vertices  = positions;
            mesh.uv        = uvs;
            mesh.triangles = triangles;

            // Set the texture to render to the new atlas
            AtlasingMaterial.mainTexture = textures[i];
            // Activate the material
            AtlasingMaterial.SetPass(0);

            // Draw the texture to the atlas
            Graphics.DrawMeshNow(mesh, Matrix4x4.identity);
            MarkTextureForReusage();
        }

        // Cleanup the mesh, otherwise it will leak, unity won't do this on his own
        Object.Destroy(mesh);
    }
Ejemplo n.º 3
0
    /// <summary>
    /// Overwrites textures in atlas by provided textures.
    /// Provided textures should have same name as textures from atlas.
    /// </summary>
    public void OverwriteOldTextures(List <Texture> textures)
    {
        // Get ready to render
        Graphics.SetRenderTarget(AtlasTexture as RenderTexture);

        // Mesh we will write to.
        Mesh mesh = new Mesh();

        mesh.MarkDynamic();

        // Initialize the data we need to fill
        Vector3[] positions = new Vector3[4];
        Vector2[] uvs       = new Vector2[4];
        int[]     triangles = new int[6];

        for (int i = 0; i < textures.Count; i++)
        {
            var spriteData = Atlas.GetSprite(textures[i].name) as DynamicSpriteData;

            if (spriteData == null)
            {
                Debug.LogWarning("Can not find sprite with name: " + textures[i].name + " in atlas while trying to overwrite it");
                continue;
            }

            if (!spriteData.IsUsed())
            {
                numberOfUnused--;
            }

            spriteData.Acquire();

            if (!spriteData.SpriteLost)
            {
                // someone already regenerated this sprite
                continue;
            }

            spriteData.SpriteLost = false;

            SetPosition(new Rect(spriteData.X - Padding, spriteData.Y - Padding, spriteData.Width + Padding, spriteData.Height + Padding),
                        TextureSize, spriteData, positions, 0);

            // Set the UVs
            SetupUvs(uvs, textures[i]);

            // Set the triangles
            SetTriangles(0, triangles);

            mesh.Clear();
            // Add the data to the mesh
            mesh.vertices  = positions;
            mesh.uv        = uvs;
            mesh.triangles = triangles;

            // Set the texture to render to the new atlas
            AtlasingMaterial.mainTexture = textures[i];
            // Activate the material
            AtlasingMaterial.SetPass(0);

            // Draw the texture to the atlas
            Graphics.DrawMeshNow(mesh, Matrix4x4.identity);
            MarkTextureForReusage();
        }

        // Cleanup the mesh, otherwise it will leak, unity won't do this on his own
        Object.Destroy(mesh);

        // Remove the render target
        Graphics.SetRenderTarget(null);
    }