/// <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(); }
/// <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); }
/// <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); }