/// <summary> /// Pack all of the specified sprites into a single texture, updating the outer and inner rects of the sprites as needed. /// </summary> static bool PackTextures(Texture2D tex, List <SpriteEntry> sprites) { Texture2D[] textures = new Texture2D[sprites.Count]; Rect[] rects; #if UNITY_3_5 || UNITY_4_0 int maxSize = 4096; #else int maxSize = SystemInfo.maxTextureSize; #endif #if UNITY_ANDROID || UNITY_IPHONE #if !UNITY_3_5 && !UNITY_4_0 if (PlayerSettings.targetGlesGraphics == TargetGlesGraphics.OpenGLES_1_x) { maxSize = Mathf.Min(maxSize, 1024); } else #endif { maxSize = Mathf.Min(maxSize, NGUISettings.allow4096 ? 4096 : 2048); } #endif if (NGUISettings.unityPacking) { for (int i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } rects = tex.PackTextures(textures, NGUISettings.atlasPadding, maxSize); } else { sprites.Sort(Compare); for (int i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } rects = UITexturePacker.PackTextures(tex, textures, 4, 4, NGUISettings.atlasPadding, maxSize); } for (int i = 0; i < sprites.Count; ++i) { Rect rect = NGUIMath.ConvertToPixels(rects[i], tex.width, tex.height, true); // Make sure that we don't shrink the textures if (Mathf.RoundToInt(rect.width) != textures[i].width) { return(false); } SpriteEntry se = sprites[i]; se.x = Mathf.RoundToInt(rect.x); se.y = Mathf.RoundToInt(rect.y); se.width = Mathf.RoundToInt(rect.width); se.height = Mathf.RoundToInt(rect.height); } return(true); }
/// <summary> /// Pack all of the specified sprites into a single texture, updating the outer and inner rects of the sprites as needed. /// </summary> static void PackTextures(Texture2D tex, List <SpriteEntry> sprites) { Texture2D[] textures = new Texture2D[sprites.Count]; Rect[] rects; if (NGUISettings.unityPacking) { for (int i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } rects = tex.PackTextures(textures, NGUISettings.atlasPadding, 4096); } else { sprites.Sort(Compare); for (int i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } rects = UITexturePacker.PackTextures(tex, textures, 4, 4, NGUISettings.atlasPadding, 4096); } for (int i = 0; i < sprites.Count; ++i) { sprites[i].rect = NGUIMath.ConvertToPixels(rects[i], tex.width, tex.height, true); //BleedTexture(tex, sprites[i].rect); } }
/// <summary> /// Pack all of the specified sprites into a single texture, updating the outer and inner rects of the sprites as needed. /// </summary> static bool PackTextures(Texture2D tex, List <SpriteEntry> sprites) { var textures = new Texture2D[sprites.Count]; Rect[] rects; #if UNITY_3_5 || UNITY_4_0 int maxSize = 4096; #else var maxSize = SystemInfo.maxTextureSize; #endif #if UNITY_ANDROID || UNITY_IPHONE maxSize = Mathf.Min(maxSize, NGUISettings.allow4096 ? 4096 : 2048); #endif if (NGUISettings.unityPacking) { for (var i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } rects = tex.PackTextures(textures, NGUISettings.atlasPadding, maxSize); } else { sprites.Sort(Compare); for (var i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } rects = UITexturePacker.PackTextures(tex, textures, 4, 4, NGUISettings.atlasPadding, maxSize); } for (var i = 0; i < sprites.Count; ++i) { var rect = NGUIMath.ConvertToPixels(rects[i], tex.width, tex.height, true); // Apparently Unity can take the liberty of destroying temporary textures without any warning if (textures[i] == null) { return(false); } // Make sure that we don't shrink the textures if (Mathf.RoundToInt(rect.width) != textures[i].width) { return(false); } var se = sprites[i]; se.x = Mathf.RoundToInt(rect.x); se.y = Mathf.RoundToInt(rect.y); se.width = Mathf.RoundToInt(rect.width); se.height = Mathf.RoundToInt(rect.height); } return(true); }
/// <summary> /// Pack all of the specified sprites into a single texture, updating the outer and inner rects of the sprites as needed. /// </summary> static void PackTextures(Texture2D tex, List <SpriteEntry> sprites) { Texture2D[] textures = new Texture2D[sprites.Count]; for (int i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } //Rect[] rects = tex.PackTextures(textures, 1, 4096); Rect[] rects = UITexturePacker.PackTextures(tex, textures, 4, 4, UISettings.atlasPadding, 4096); for (int i = 0; i < sprites.Count; ++i) { sprites[i].rect = NGUIMath.ConvertToPixels(rects[i], tex.width, tex.height, true); } }
{ //打包算法封装 public Rect[] Pack(Texture2D tex, Texture2D[] imgs, int padding, object config) { //打包纹理 Rect[] rects = null; #if UNITY_3_5 || UNITY_4_0 int maxSize = 4096; #else int maxSize = SystemInfo.maxTextureSize; #endif rects = UITexturePacker.PackTextures(tex, imgs, 4, 4, padding, maxSize); for (int i = 0; i < imgs.Length; ++i) { Rect rect = ConvertToPixels(rects[i], tex.width, tex.height, true); // Make sure that we don't shrink the textures if (Mathf.RoundToInt(rect.width) != imgs[i].width) { return(null); } } return(rects); }
/// <summary> /// Rebuilds the atlas texture. /// </summary> public void RebuildAtlas() { if (this.m_Instance == null) { Debug.LogError( "SPAtlasBuilder failed to rebuild the atlas, reason: Sprite Packer Instance reference is null."); return; } if (this.m_Instance.texture == null) { Debug.LogWarning( "Sprite Packer failed to rebuild the atlas, please make sure the atlas texture reference is set."); return; } // Make the atlas texture readable if (SPTools.TextureSetReadWriteEnabled(this.m_Instance.texture, true, false)) { // Get a list with the current sprites and applied actions List <SPSpriteInfo> spriteInfoList = this.m_Instance.GetSpriteListWithAppliedActions(); // Get the source textures asset paths string[] sourceTexturePaths = this.CollectSourceTextureAssetPaths(spriteInfoList); // Make the source textures readable if (!this.SetAssetsReadWriteEnabled(sourceTexturePaths, true)) { Debug.LogError( "Sprite Packer failed to make one or more of the source texture readable, please do it manually."); return; } // Make sure all the textures have the correct texture format this.CorrectTexturesFormat(spriteInfoList); // If we are using max rects packing, sort the sprite info list by size if (this.m_Instance.packingMethod == SPInstance.PackingMethod.MaxRects) { spriteInfoList.Sort(CompareBySize); } // Temporary textures array Texture2D[] textures = new Texture2D[spriteInfoList.Count]; // Create an array to contain the sprite import data SPSpriteImportData[] spritesImportData = new SPSpriteImportData[spriteInfoList.Count]; // Populate the textures and names arrays int ia = 0; foreach (SPSpriteInfo si in spriteInfoList) { // Temporary texture Texture2D texture = null; // Prepare the sprite import data SPSpriteImportData importData = new SPSpriteImportData(); // Prepare the sprite name importData.name = "Sprite_" + ia.ToString(); if (si.targetSprite != null) { importData.name = si.targetSprite.name; } else if (si.source != null && (si.source is Texture2D || si.source is Sprite)) { if (si.source is Texture2D) { importData.name = (si.source as Texture2D).name; } else { importData.name = (si.source as Sprite).name; } } // Prepare texture // In case the source texture is missing, rebuild from the already existing sprite if (si.source == null && si.targetSprite != null) { // Copy the sprite into the temporary texture texture = new Texture2D((int)si.targetSprite.rect.width, (int)si.targetSprite.rect.height, TextureFormat.ARGB32, false); Color[] pixels = si.targetSprite.texture.GetPixels((int)si.targetSprite.rect.x, (int)si.targetSprite.rect.y, (int)si.targetSprite.rect.width, (int)si.targetSprite.rect.height); texture.SetPixels(pixels); texture.Apply(); } // Handle texture source else if (si.source is Texture2D) { // Get as texture Texture2D sourceTex = si.source as Texture2D; // Check if we have as source texture if (sourceTex != null) { // Copy the source texture into the temp one texture = new Texture2D(sourceTex.width, sourceTex.height, TextureFormat.ARGB32, false); Color[] pixels = sourceTex.GetPixels(0, 0, sourceTex.width, sourceTex.height); texture.SetPixels(pixels); texture.Apply(); // Transfer the sprite data importData.border = Vector4.zero; importData.alignment = this.m_Instance.defaultPivot; importData.pivot = this.m_Instance.defaultCustomPivot; } } // Handle sprite source else if (si.source is Sprite) { // Get as sprite Sprite sourceSprite = si.source as Sprite; // Make sure we have the sprite if (sourceSprite != null) { // Copy the sprite into the temporary texture texture = new Texture2D((int)sourceSprite.rect.width, (int)sourceSprite.rect.height, TextureFormat.ARGB32, false); Color[] pixels = sourceSprite.texture.GetPixels((int)sourceSprite.rect.x, (int)sourceSprite.rect.y, (int)sourceSprite.rect.width, (int)sourceSprite.rect.height); texture.SetPixels(pixels); texture.Apply(); // Transfer the sprite data importData.border = sourceSprite.border; importData.alignment = SpriteAlignment.Custom; importData.pivot = new Vector2( (0f - sourceSprite.bounds.center.x / sourceSprite.bounds.extents.x / 2 + 0.5f), (0f - sourceSprite.bounds.center.y / sourceSprite.bounds.extents.y / 2 + 0.5f)); } } // Save the new texture into our array textures[ia] = (texture != null) ? texture : new Texture2D(1, 1); // Set the sprite import data spritesImportData[ia] = importData; // Increase the indexer ia++; } // Make the source textures assets non readable if (SPTools.GetEditorPrefBool(SPTools.Settings_DisableReadWriteEnabled)) { this.SetAssetsReadWriteEnabled(sourceTexturePaths, false); } // Clear the source textures asset paths System.Array.Clear(sourceTexturePaths, 0, sourceTexturePaths.Length); // Create a temporary texture for the packing Texture2D tempTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false); // UV coords array Rect[] uvs; // Pack the textures into the temporary if (this.m_Instance.packingMethod == SPInstance.PackingMethod.Unity) { uvs = tempTexture.PackTextures(textures, this.m_Instance.padding, this.m_Instance.maxSize); } else { uvs = UITexturePacker.PackTextures(tempTexture, textures, this.m_Instance.padding, this.m_Instance.maxSize); // Check if packing failed if (uvs == null) { Debug.LogError( "Sprite Packer texture packing failed, the textures might be exceeding the specified maximum size."); return; } } // Import and Configure the texture atlas (also disables Read/Write) SPTools.ImportAndConfigureAtlasTexture(this.m_Instance.texture, tempTexture, uvs, spritesImportData); // Clear the current sprite info list this.m_Instance.ClearSprites(); // Clear the actions list this.m_Instance.ClearActions(); // Destroy the textures from the temporary textures array for (int ib = 0; ib < textures.Length; ib++) { UnityEngine.Object.DestroyImmediate(textures[ib]); } // Destroy the temporary texture UnityEngine.Object.DestroyImmediate(tempTexture); // Convert the temporary sprite info into array SPSpriteInfo[] spriteInfoArray = spriteInfoList.ToArray(); // Clear the temporary sprite info list spriteInfoList.Clear(); // Apply the new sprite reff to the sprite info and add the sprite info to the sprites list for (int i = 0; i < spriteInfoArray.Length; i++) { SPSpriteInfo info = spriteInfoArray[i]; if (info.targetSprite == null) { info.targetSprite = SPTools.LoadSprite(this.m_Instance.texture, spritesImportData[i].name); } // Add to the instance sprite info list this.m_Instance.AddSprite(info); } // Clear the sprites import data array System.Array.Clear(spritesImportData, 0, spritesImportData.Length); // Set dirty EditorUtility.SetDirty(this.m_Instance); } else { Debug.LogError("Sprite Packer failed to make the atlas texture readable, please do it manually."); } }
private static bool CombineSpritesHelper(string path, string dpath, string name, int padding) { string file = dpath + "/" + name + ".png"; if (System.IO.File.Exists(file)) { System.IO.File.Delete(file); } string[] paths = AssetDatabase.FindAssets("t:sprite", new string[] { path }); List <Sprite> spriteList = new List <Sprite>(); List <Texture2D> texList = new List <Texture2D>(); foreach (var o in paths) { Sprite s = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(o), typeof(Sprite)) as Sprite; if (null != s) { spriteList.Add(s); texList.Add(s.texture); } } if (texList.Count > 0) { Texture2D tex = new Texture2D(m_maxWidth, m_maxHeight, TextureFormat.ARGB32, true); Rect[] uvs = UITexturePacker.PackTextures(tex, texList.ToArray(), 4, 4, padding, m_maxWidth); if (null == uvs) { EditorUtility.DisplayDialog(path, "图集超过1024,需要分组成多张图集", "点击退出"); Object.DestroyImmediate(tex); tex = null; return(false); } else { List <SpriteMetaData> metaList = new List <SpriteMetaData>(); for (int i = 0; i < uvs.Length; ++i) { SpriteMetaData data = new SpriteMetaData(); data.alignment = (int)SpriteAlignment.Center; data.border = spriteList[i].border; data.name = spriteList[i].name; data.pivot = spriteList[i].pivot; float width = UITexturePacker.currentTexSize.x; float height = UITexturePacker.currentTexSize.y; data.rect = new Rect(uvs[i].x * width, uvs[i].y * height, uvs[i].width * width, uvs[i].height * height); //data.rect = new Rect(uvs[i].x * tex.width, uvs[i].y * tex.height, uvs[i].width * tex.width, uvs[i].height * tex.height); metaList.Add(data); } System.IO.File.WriteAllBytes(file, tex.EncodeToPNG()); AssetDatabase.ImportAsset(file, ImportAssetOptions.ForceUpdate); TextureImporter importer = AssetImporter.GetAtPath(file) as TextureImporter; importer.spritesheet = metaList.ToArray(); importer.spriteImportMode = SpriteImportMode.Multiple; importer.textureType = TextureImporterType.Sprite; importer.textureCompression = TextureImporterCompression.Uncompressed; importer.mipmapEnabled = true; importer.isReadable = true; importer.mipmapFilter = TextureImporterMipFilter.BoxFilter; AssetDatabase.ImportAsset(file); AssetDatabase.Refresh(); m_bitmapFont = new BitmapFontData(); m_bitmapFont.name = name; m_bitmapFont.charCount = metaList.Count; m_bitmapFont.height = tex.height; m_bitmapFont.width = tex.width; m_bitmapFont.size = m_fontSize; m_bitmapFont.spriteList = metaList; m_bitmapFont.Save(); m_bitmapFont.CreateFont(); } } return(true); }
bool packTextures(int maxSize, bool unityPacking) //, ref ArrayList outSprites, ref Rect[] rects) { if (packTex != null) { DestroyImmediate(packTex, true); packTex = null; } refreshSelectedCount(); if (selectedCount == 0) { Debug.LogError("Please select some sprites, that need packe"); return(false); } packSprites.Clear(); List <Texture2D> listTexs = new List <Texture2D> (); for (int i = 0; i < mSpriteList.Count; i++) { Hashtable m = mSpriteList [i] as Hashtable; if (MapEx.getBool(m, "selected")) { Hashtable d = MapEx.getMap(m, "data"); string name = MapEx.getString(d, "name"); string path = MapEx.getString(d, "path"); Texture2D tex = ECLEditorUtl.getObjectByPath(path) as Texture2D; listTexs.Add(tex); packSprites.Add(m); } } if (sortSprite != SortSprite.none) { if (sortSprite == SortSprite.SortArea) { packSprites.Sort(CompareSprite); } else { packSprites.Sort(CompareSprite2); } listTexs.Clear(); for (int i = 0; i < packSprites.Count; i++) { Hashtable d = MapEx.getMap(packSprites [i], "data"); string path = MapEx.getString(d, "path"); setTextureReadable("Assets/" + path, TextureImporterFormat.RGBA32, TextureImporterCompression.Uncompressed, true); Texture2D tex = ECLEditorUtl.getObjectByPath(path) as Texture2D; listTexs.Add(tex); } } // for (int i = 0; i < listTexs.Count; i++) { // setTextureReadable (listTexs [i] as Texture, TextureImporterFormat.RGBA32, TextureImporterCompression.Uncompressed, true); // } packTex = new Texture2D(1, 1, TextureFormat.ARGB32, false); if (unityPacking) { packRects = packTex.PackTextures(listTexs.ToArray(), NGUISettings.atlasPadding, maxSize); } else { packRects = UITexturePacker.PackTextures(packTex, listTexs.ToArray(), 4, 4, NGUISettings.atlasPadding, maxSize); } _empty = new Texture2D(packTex.width, packTex.height, TextureFormat.ARGB32, false); bool ret = true; for (int i = 0; i < listTexs.Count; ++i) { Rect rect = NGUIMath.ConvertToPixels(packRects [i], packTex.width, packTex.height, true); packRects [i] = rect; // Apparently Unity can take the liberty of destroying temporary textures without any warning if (listTexs [i] == null) { Debug.LogWarning("Apparently Unity can take the liberty of destroying temporary textures without any warning"); ret = false; break; } // Make sure that we don't shrink the textures if (Mathf.RoundToInt(rect.width) != listTexs [i].width) { Debug.LogError(rect.width + "====" + listTexs [i].width); Debug.LogWarning("Make sure that we don't shrink the textures=" + listTexs [i].name); ret = false; break; } } // for (int i = 0; i < listTexs.Count; i++) { // setTextureReadable (listTexs [i] as Texture, TextureImporterFormat.Automatic, false); // } return(ret); }
/// <summary> /// Pack all of the specified sprites into a single texture, updating the outer and inner rects of the sprites as needed. /// </summary> static bool PackTextures(Texture2D tex, List <SpriteEntry> sprites) { Texture2D[] textures = new Texture2D[sprites.Count]; Rect[] rects; #if UNITY_3_5 || UNITY_4_0 int maxSize = 4096; #else int maxSize = SystemInfo.maxTextureSize; #endif #if UNITY_ANDROID || UNITY_IPHONE maxSize = Mathf.Min(maxSize, NGUISettings.allow4096 ? 4096 : 2048); #endif if (NGUISettings.unityPacking) { for (int i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } rects = tex.PackTextures(textures, Mathf.Max(NGUISettings.atlasPadding, (NGUISettings.atlasExtendPadding << 1)), maxSize); } else { sprites.Sort(Compare); for (int i = 0; i < sprites.Count; ++i) { textures[i] = sprites[i].tex; } rects = UITexturePacker.PackTextures(tex, textures, 4, 4, Mathf.Max(NGUISettings.atlasPadding, (NGUISettings.atlasExtendPadding << 1)), maxSize); } for (int i = 0; i < sprites.Count; ++i) { Rect rect = NGUIMath.ConvertToPixels(rects[i], tex.width, tex.height, true); // Apparently Unity can take the liberty of destroying temporary textures without any warning if (textures[i] == null) { return(false); } // Make sure that we don't shrink the textures if (Mathf.RoundToInt(rect.width) != textures[i].width) { return(false); } SpriteEntry se = sprites[i]; se.x = Mathf.RoundToInt(rect.x); se.y = Mathf.RoundToInt(rect.y); se.width = Mathf.RoundToInt(rect.width); se.height = Mathf.RoundToInt(rect.height); } if (NGUISettings.atlasExtendPadding > 0) { Color32[] colors = tex.GetPixels32(); int texWidth = tex.width; int texHeight = tex.height; for (int i = 0; i < sprites.Count; ++i) { SpriteEntry se = sprites[i]; int xMin = se.x; int xMax = se.x + se.width - 1; // Y-axis is inverted int yMin = texHeight - se.y - se.height; int yMax = texHeight - se.y - 1; for (int x = xMin - NGUISettings.atlasExtendPadding; x <= xMax + NGUISettings.atlasExtendPadding; ++x) { for (int y = yMin - NGUISettings.atlasExtendPadding; y <= yMax + NGUISettings.atlasExtendPadding; ++y) { if (x < 0 || x >= texWidth || y < 0 || y >= texHeight) { // Out of tex bounds continue; } if (x >= xMin && x <= xMax && y >= yMin && y <= yMax) { // In sprite bounds continue; } int baseX = Mathf.Clamp(x, xMin, xMax); int baseY = Mathf.Clamp(y, yMin, yMax); int index = y * texWidth + x; int baseIndex = baseY * texWidth + baseX; colors[index] = colors[baseIndex]; } } } tex.SetPixels32(colors); } return(true); }