/// <summary> /// Extract sprites from the atlas, adding them to the list. /// </summary> static public void ExtractSprites(UIAtlas atlas, List <SpriteEntry> finalSprites) { ShowProgress(0f); TextureAlphaSpliter.UseRgbaTex(atlas); // Make the atlas texture readable Texture2D tex = NGUIEditorTools.ImportTexture(atlas.texture, true, true, false); if (tex != null) { Color32[] pixels = null; int width = tex.width; int height = tex.height; List <UISpriteData> sprites = atlas.spriteList; float count = sprites.Count; int index = 0; foreach (UISpriteData es in sprites) { ShowProgress((index++) / count); bool found = false; foreach (SpriteEntry fs in finalSprites) { if (es.name == fs.name) { fs.CopyBorderFrom(es); found = true; break; } } if (!found) { if (pixels == null) { pixels = tex.GetPixels32(); } SpriteEntry sprite = ExtractSprite(es, pixels, width, height); if (sprite != null) { finalSprites.Add(sprite); } } } } // The atlas no longer needs to be readable NGUIEditorTools.ImportTexture(atlas.texture, false, false, !atlas.premultipliedAlpha); ShowProgress(1f); }
/// <summary> /// Update the sprite atlas, keeping only the sprites that are on the specified list. /// </summary> static public void UpdateAtlas(UIAtlas atlas, List <SpriteEntry> sprites) { if (sprites.Count > 0) { // Combine all sprites into a single texture and save it if (UpdateTexture(atlas, sprites)) { // Replace the sprites within the atlas ReplaceSprites(atlas, sprites); } // Release the temporary textures ReleaseSprites(sprites); EditorUtility.ClearProgressBar(); //process through seperating rgb and a Texture rgb, alpha; TextureAlphaSpliter.SplitAlpha(atlas.texture, false, out rgb, out alpha); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); Debug.Log("分离为rgb+alpha 贴图"); //update mat var rgba = atlas.texture; var mat = atlas.spriteMaterial; mat.shader = Shader.Find("Unlit/Transparent Colored Alpha"); mat.SetTexture("_AlphaTex", alpha); mat.SetTexture("_MainTex", rgb); Debug.Log("重设material"); //save src pic var src = AssetDatabase.GetAssetPath(rgba); TextureAlphaSpliter.SaveUIRgbaTexture(src); Debug.Log("保存rgba"); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); return; } else { atlas.spriteList.Clear(); string path = NGUIEditorTools.GetSaveableTexturePath(atlas); atlas.spriteMaterial.mainTexture = null; if (!string.IsNullOrEmpty(path)) { AssetDatabase.DeleteAsset(path); } } atlas.MarkAsChanged(); Selection.activeGameObject = (NGUISettings.atlas != null) ? NGUISettings.atlas.gameObject : null; EditorUtility.ClearProgressBar(); }
void OnGUI() { if (mLastAtlas != NGUISettings.atlas) { mLastAtlas = NGUISettings.atlas; } bool update = false; bool replace = false; NGUIEditorTools.SetLabelWidth(84f); GUILayout.Space(3f); NGUIEditorTools.DrawHeader("Input", true); NGUIEditorTools.BeginContents(false); GUILayout.BeginHorizontal(); { ComponentSelector.Draw <UIAtlas>("Atlas", NGUISettings.atlas, OnSelectAtlas, true, GUILayout.MinWidth(80f)); EditorGUI.BeginDisabledGroup(NGUISettings.atlas == null); if (GUILayout.Button("New", GUILayout.Width(40f))) { NGUISettings.atlas = null; } EditorGUI.EndDisabledGroup(); } GUILayout.EndHorizontal(); List <Texture> textures = GetSelectedTextures(); if (NGUISettings.atlas != null) { Material mat = NGUISettings.atlas.spriteMaterial; Texture tex = NGUISettings.atlas.texture; if (cachedRgba == null || (tex != null && !tex.name.Contains(cachedRgba.name))) { cachedRgba = TextureAlphaSpliter.GetUIRgbaTex(tex); } // Material information GUILayout.BeginHorizontal(); { if (mat != null) { if (GUILayout.Button("Material", GUILayout.Width(76f))) { Selection.activeObject = mat; } GUILayout.Label(" " + mat.name); } else { GUI.color = Color.grey; GUILayout.Button("Material", GUILayout.Width(76f)); GUI.color = Color.white; GUILayout.Label(" N/A"); } } GUILayout.EndHorizontal(); // Texture atlas information GUILayout.BeginHorizontal(); { if (tex != null) { if (GUILayout.Button("Texture", GUILayout.Width(76f))) { Selection.activeObject = tex; } GUILayout.Label(" " + tex.width + "x" + tex.height); } else { GUI.color = Color.grey; GUILayout.Button("Texture", GUILayout.Width(76f)); GUI.color = Color.white; GUILayout.Label(" N/A"); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (cachedRgba != null) { if (GUILayout.Button("原图", GUILayout.Width(76f))) { Selection.activeObject = cachedRgba; } GUILayout.Label(" " + cachedRgba.width + "x" + cachedRgba.height); } GUILayout.EndHorizontal(); } GUILayout.BeginHorizontal(); NGUISettings.atlasPadding = Mathf.Clamp(EditorGUILayout.IntField("Padding", NGUISettings.atlasPadding, GUILayout.Width(100f)), 0, 8); GUILayout.Label((NGUISettings.atlasPadding == 1 ? "pixel" : "pixels") + " between sprites"); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); NGUISettings.atlasTrimming = EditorGUILayout.Toggle("Trim Alpha", NGUISettings.atlasTrimming, GUILayout.Width(100f)); GUILayout.Label("Remove empty space"); GUILayout.EndHorizontal(); bool fixedShader = false; if (NGUISettings.atlas != null) { Material mat = NGUISettings.atlas.spriteMaterial; if (mat != null) { Shader shader = mat.shader; if (shader != null) { if (shader.name == "Unlit/Transparent Colored") { NGUISettings.atlasPMA = false; fixedShader = true; } else if (shader.name == "Unlit/Premultiplied Colored") { NGUISettings.atlasPMA = true; fixedShader = true; } } } } if (!fixedShader) { GUILayout.BeginHorizontal(); NGUISettings.atlasPMA = EditorGUILayout.Toggle("PMA Shader", NGUISettings.atlasPMA, GUILayout.Width(100f)); GUILayout.Label("Pre-multiplied alpha", GUILayout.MinWidth(70f)); GUILayout.EndHorizontal(); } //GUILayout.BeginHorizontal(); //NGUISettings.keepPadding = EditorGUILayout.Toggle("Keep Padding", NGUISettings.keepPadding, GUILayout.Width(100f)); //GUILayout.Label("or replace with trimmed pixels", GUILayout.MinWidth(70f)); //GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); NGUISettings.unityPacking = EditorGUILayout.Toggle("Unity Packer", NGUISettings.unityPacking, GUILayout.Width(100f)); GUILayout.Label("or custom packer", GUILayout.MinWidth(70f)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); NGUISettings.trueColorAtlas = EditorGUILayout.Toggle("Truecolor", NGUISettings.trueColorAtlas, GUILayout.Width(100f)); GUILayout.Label("force ARGB32 textures", GUILayout.MinWidth(70f)); GUILayout.EndHorizontal(); if (!NGUISettings.unityPacking) { GUILayout.BeginHorizontal(); NGUISettings.forceSquareAtlas = EditorGUILayout.Toggle("Force Square", NGUISettings.forceSquareAtlas, GUILayout.Width(100f)); GUILayout.Label("if on, forces a square atlas texture", GUILayout.MinWidth(70f)); GUILayout.EndHorizontal(); } #if UNITY_IPHONE || UNITY_ANDROID GUILayout.BeginHorizontal(); NGUISettings.allow4096 = EditorGUILayout.Toggle("4096x4096", NGUISettings.allow4096, GUILayout.Width(100f)); GUILayout.Label("if off, limit atlases to 2048x2048"); GUILayout.EndHorizontal(); #endif NGUIEditorTools.EndContents(); if (NGUISettings.atlas != null) { GUILayout.BeginHorizontal(); GUILayout.Space(20f); if (textures.Count > 0) { update = GUILayout.Button("Add/Update"); } else if (GUILayout.Button("View Sprites")) { SpriteSelector.ShowSelected(); } GUILayout.Space(20f); GUILayout.EndHorizontal(); } else { EditorGUILayout.HelpBox("You can create a new atlas by selecting one or more textures in the Project View window, then clicking \"Create\".", MessageType.Info); EditorGUI.BeginDisabledGroup(textures.Count == 0); GUILayout.BeginHorizontal(); GUILayout.Space(20f); bool create = GUILayout.Button("Create"); GUILayout.Space(20f); GUILayout.EndHorizontal(); EditorGUI.EndDisabledGroup(); if (create) { string path = EditorUtility.SaveFilePanelInProject("Save As", "New Atlas.prefab", "prefab", "Save atlas as...", NGUISettings.currentPath); if (!string.IsNullOrEmpty(path)) { NGUISettings.currentPath = System.IO.Path.GetDirectoryName(path); GameObject go = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject; string matPath = path.Replace(".prefab", ".mat"); replace = true; // Try to load the material Material mat = AssetDatabase.LoadAssetAtPath(matPath, typeof(Material)) as Material; // If the material doesn't exist, create it if (mat == null) { Shader shader = Shader.Find(NGUISettings.atlasPMA ? "Unlit/Premultiplied Colored" : "Unlit/Transparent Colored"); mat = new Material(shader); // Save the material AssetDatabase.CreateAsset(mat, matPath); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); // Load the material so it's usable mat = AssetDatabase.LoadAssetAtPath(matPath, typeof(Material)) as Material; } // Create a new prefab for the atlas Object prefab = (go != null) ? go : PrefabUtility.CreateEmptyPrefab(path); // Create a new game object for the atlas string atlasName = path.Replace(".prefab", ""); atlasName = atlasName.Substring(path.LastIndexOfAny(new char[] { '/', '\\' }) + 1); go = new GameObject(atlasName); go.AddComponent <UIAtlas>().spriteMaterial = mat; // Update the prefab PrefabUtility.ReplacePrefab(go, prefab); DestroyImmediate(go); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); // Select the atlas go = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject; NGUISettings.atlas = go.GetComponent <UIAtlas>(); Selection.activeGameObject = go; } } } string selection = null; Dictionary <string, int> spriteList = GetSpriteList(textures); if (spriteList.Count > 0) { NGUIEditorTools.DrawHeader("Sprites", true); { GUILayout.BeginHorizontal(); GUILayout.Space(3f); GUILayout.BeginVertical(); mScroll = GUILayout.BeginScrollView(mScroll); bool delete = false; int index = 0; foreach (KeyValuePair <string, int> iter in spriteList) { ++index; GUILayout.Space(-1f); bool highlight = (UIAtlasInspector.instance != null) && (NGUISettings.selectedSprite == iter.Key); GUI.backgroundColor = highlight ? Color.white : new Color(0.8f, 0.8f, 0.8f); GUILayout.BeginHorizontal("AS TextArea", GUILayout.MinHeight(20f)); GUI.backgroundColor = Color.white; GUILayout.Label(index.ToString(), GUILayout.Width(24f)); if (GUILayout.Button(iter.Key, "OL TextField", GUILayout.Height(20f))) { selection = iter.Key; } if (iter.Value == 2) { GUI.color = Color.green; GUILayout.Label("Add", GUILayout.Width(27f)); GUI.color = Color.white; } else if (iter.Value == 1) { GUI.color = Color.cyan; GUILayout.Label("Update", GUILayout.Width(45f)); GUI.color = Color.white; } else { if (mDelNames.Contains(iter.Key)) { GUI.backgroundColor = Color.red; if (GUILayout.Button("Delete", GUILayout.Width(60f))) { delete = true; } GUI.backgroundColor = Color.green; if (GUILayout.Button("X", GUILayout.Width(22f))) { mDelNames.Remove(iter.Key); delete = false; } GUI.backgroundColor = Color.white; } else { // If we have not yet selected a sprite for deletion, show a small "X" button if (GUILayout.Button("X", GUILayout.Width(22f))) { mDelNames.Add(iter.Key); } } } GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); GUILayout.EndVertical(); GUILayout.Space(3f); GUILayout.EndHorizontal(); // If this sprite was marked for deletion, remove it from the atlas if (delete) { List <SpriteEntry> sprites = new List <SpriteEntry>(); ExtractSprites(NGUISettings.atlas, sprites); for (int i = sprites.Count; i > 0;) { SpriteEntry ent = sprites[--i]; if (mDelNames.Contains(ent.name)) { sprites.RemoveAt(i); } } UpdateAtlas(NGUISettings.atlas, sprites); mDelNames.Clear(); NGUIEditorTools.RepaintSprites(); } else if (update) { UpdateAtlas(textures, true); } else if (replace) { UpdateAtlas(textures, false); } if (NGUISettings.atlas != null && !string.IsNullOrEmpty(selection)) { NGUIEditorTools.SelectSprite(selection); } else if (update || replace) { NGUIEditorTools.UpgradeTexturesToSprites(NGUISettings.atlas); NGUIEditorTools.RepaintSprites(); } } } if (NGUISettings.atlas != null && textures.Count == 0) { EditorGUILayout.HelpBox("You can reveal more options by selecting one or more textures in the Project View window.", MessageType.Info); } // Uncomment this line if you want to be able to force-sort the atlas //if (NGUISettings.atlas != null && GUILayout.Button("Sort Alphabetically")) NGUISettings.atlas.SortAlphabetically(); }
/// <summary> /// Combine all sprites into a single texture and save it to disk. /// </summary> static public bool UpdateTexture(UIAtlas atlas, List <SpriteEntry> sprites) { // Get the texture for the atlas Texture2D tex = atlas.texture as Texture2D; bool success = TextureAlphaSpliter.UseRgbaTex(atlas); if (success) { tex = atlas.texture as Texture2D; } //bool isRGB = tex != null && tex.name.Contains("(rgb)"); //if (isRGB) //{ // var srcTex = TextureAlphaSpliter.GetUIRgbaTex(tex); // if (srcTex != null) { // tex = srcTex; // atlas.spriteMaterial.SetTexture("_MainTex", tex); // } // else // { // Debug.LogErrorFormat("找不到图集={0}的原图(rgba)", atlas.name); // } //} string oldPath = (tex != null) ? AssetDatabase.GetAssetPath(tex.GetInstanceID()) : ""; string newPath = NGUIEditorTools.GetSaveableTexturePath(atlas); // Clear the read-only flag in texture file attributes if (System.IO.File.Exists(newPath)) { #if !UNITY_4_1 && !UNITY_4_0 && !UNITY_3_5 if (!AssetDatabase.IsOpenForEdit(newPath)) { Debug.LogError(newPath + " is not editable. Did you forget to do a check out?"); return(false); } #endif System.IO.FileAttributes newPathAttrs = System.IO.File.GetAttributes(newPath); newPathAttrs &= ~System.IO.FileAttributes.ReadOnly; System.IO.File.SetAttributes(newPath, newPathAttrs); } bool newTexture = (tex == null || oldPath != newPath); if (newTexture) { // Create a new texture for the atlas tex = new Texture2D(1, 1, TextureFormat.ARGB32, false); } else { // Make the atlas readable so we can save it tex = NGUIEditorTools.ImportTexture(oldPath, true, false, false); } // Pack the sprites into this texture if (PackTextures(tex, sprites)) { byte[] bytes = tex.EncodeToPNG(); System.IO.File.WriteAllBytes(newPath, bytes); bytes = null; // Load the texture we just saved as a Texture2D AssetDatabase.SaveAssets(); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); tex = NGUIEditorTools.ImportTexture(newPath, false, true, !atlas.premultipliedAlpha); // Update the atlas texture if (newTexture) { if (tex == null) { Debug.LogError("Failed to load the created atlas saved as " + newPath); } else { atlas.spriteMaterial.mainTexture = tex; } ReleaseSprites(sprites); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); } return(true); } else { if (!newTexture) { NGUIEditorTools.ImportTexture(oldPath, false, true, !atlas.premultipliedAlpha); } //Debug.LogError("Operation canceled: The selected sprites can't fit into the atlas.\n" + // "Keep large sprites outside the atlas (use UITexture), and/or use multiple atlases instead."); EditorUtility.DisplayDialog("Operation Canceled", "The selected sprites can't fit into the atlas.\n" + "Keep large sprites outside the atlas (use UITexture), and/or use multiple atlases instead", "OK"); return(false); } }