Author Topic: [NGUI 3] Feature addition. Sprite extraction.  (Read 3228 times)

Smiley

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 10
    • View Profile
[NGUI 3] Feature addition. Sprite extraction.
« on: November 27, 2014, 09:15:41 AM »
First of all, as far as we are aware, this feature does not exist in NGUI.
We had some old projects in which the NGUI atlas was there, but the original images were lost. We wanted to make edits to the originals and update them in NGUI.
For this purpose a developer here created a small editor windows that allows us to do exactly that. Since we didn't need padding, original padding is not accounted for in this code, but it might be of some use to someone. and it is a really easy feature to add into the NGUI feature list.
I hope people are interested and that this will be added to NGUI at some point.

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEditor;
  5. using System.IO;
  6.  
  7. public class ExtractSprite : EditorWindow {
  8.         //UIAtlas selectedAtlas;
  9.         string path;
  10.  
  11.  
  12.         // Add menu named "My Window" to the Window menu
  13.         [MenuItem ("NGUI/Extract Sprites")]
  14.         static void Init () {
  15.                 // Get existing open window or if none, make a new one:
  16.                 ExtractSprite window = (ExtractSprite)EditorWindow.GetWindow (typeof (ExtractSprite));
  17.         }
  18.  
  19.         void OnSelectAtlas (MonoBehaviour obj)
  20.         {
  21.                 path = AssetDatabase.GetAssetPath (obj);
  22.  
  23.                 path = path.Substring (0, path.LastIndexOf ("/"));
  24.                 path = path.Substring (6);
  25.                 Debug.Log(path);
  26.  
  27.                 NGUISettings.atlas = obj as UIAtlas;
  28.                 Repaint();
  29.         }
  30.        
  31.         void OnGUI () {
  32.                 bool extract = false;
  33.  
  34.                 GUILayout.Label ("Select atlas", EditorStyles.boldLabel);
  35.  
  36.                 ComponentSelector.Draw<UIAtlas>("Select", NGUISettings.atlas, OnSelectAtlas);
  37.                 extract = GUILayout.Button("Extract", GUILayout.Width(76f));
  38.  
  39.                 if (extract) {
  40.                         List<SpriteEntry> sprites = new List<SpriteEntry>();
  41.                         ExtractSprites(NGUISettings.atlas, sprites, path);
  42.                 }
  43.  
  44.         }
  45.  
  46.         class SpriteEntry : UISpriteData
  47.         {
  48.                 // Sprite texture -- original texture or a temporary texture
  49.                 public Texture2D tex;
  50.                
  51.                 // Whether the texture is temporary and should be deleted
  52.                 public bool temporaryTexture = false;
  53.         }
  54.  
  55.  
  56.         static void ExtractSprites (UIAtlas atlas, List<SpriteEntry> finalSprites, string _path)
  57.         {
  58.                 // Make the atlas texture readable
  59.                 Texture2D atlasTex = NGUIEditorTools.ImportTexture(atlas.texture, true, false, !atlas.premultipliedAlpha);
  60.                
  61.                 if (atlasTex != null)
  62.                 {
  63.                         Color32[] oldPixels = null;
  64.                         int oldWidth = atlasTex.width;
  65.                         int oldHeight = atlasTex.height;
  66.                         List<UISpriteData> existingSprites = atlas.spriteList;
  67.  
  68.  
  69.  
  70.                         foreach (UISpriteData es in existingSprites)
  71.                         {
  72.                                 bool found = false;
  73.                                
  74.                                 foreach (SpriteEntry fs in finalSprites)
  75.                                 {
  76.  
  77.                                         if (es.name == fs.name)
  78.                                         {
  79.                                                 fs.CopyBorderFrom(es);
  80.                                                 found = true;
  81.                                                 break;
  82.                                         }
  83.                                 }
  84.                                
  85.                                 if (!found)
  86.                                 {
  87.  
  88.  
  89.                                         // Read the atlas
  90.                                         if (oldPixels == null) oldPixels = atlasTex.GetPixels32();
  91.                                        
  92.                                         int xmin = Mathf.Clamp(es.x, 0, oldWidth);
  93.                                         int ymin = Mathf.Clamp(es.y, 0, oldHeight);
  94.                                         int newWidth = Mathf.Clamp(es.width, 0, oldWidth);
  95.                                         int newHeight = Mathf.Clamp(es.height, 0, oldHeight);
  96.                                         if (newWidth == 0 || newHeight == 0) continue;
  97.                                        
  98.                                         Color32[] newPixels = new Color32[newWidth * newHeight];
  99.                                        
  100.                                         for (int y = 0; y < newHeight; ++y)
  101.                                         {
  102.                                                 for (int x = 0; x < newWidth; ++x)
  103.                                                 {
  104.                                                         int newIndex = (newHeight - 1 - y) * newWidth + x;
  105.                                                         int oldIndex = (oldHeight - 1 - (ymin + y)) * oldWidth + (xmin + x);
  106.                                                         newPixels[newIndex] = oldPixels[oldIndex];
  107.                                                 }
  108.                                         }
  109.                                        
  110.                                         // Create a new sprite
  111.                                         SpriteEntry sprite = new SpriteEntry();
  112.                                         sprite.CopyFrom(es);
  113.                                         sprite.SetRect(0, 0, newWidth, newHeight);
  114.                                         //sprite.temporaryTexture = true;
  115.                                         sprite.temporaryTexture = false;
  116.                                         sprite.tex = new Texture2D(newWidth, newHeight);
  117.                                         sprite.tex.SetPixels32(newPixels);
  118.                                         sprite.tex.Apply();
  119.                                         finalSprites.Add(sprite);
  120.  
  121.  
  122.                                         // Encode texture into PNG
  123.                                         var bytes = sprite.tex.EncodeToPNG();
  124.                                         // For testing purposes, also write to a file in the project folder
  125.                                         File.WriteAllBytes(Application.dataPath + _path + "/" +es.name+".png", bytes);
  126.                                 }
  127.                         }
  128.                 }
  129.                
  130.                 // The atlas no longer needs to be readable
  131.                 NGUIEditorTools.ImportTexture(atlas.texture, false, false, !atlas.premultipliedAlpha);
  132.         }
  133.  
  134. }

Sincerely,
Smiley

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: [NGUI 3] Feature addition. Sprite extraction.
« Reply #1 on: November 27, 2014, 08:44:14 PM »
You can already do this with NGUI. Select the atlas, choose the sprite, and use the Save As button.

Smiley

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 10
    • View Profile
Re: [NGUI 3] Feature addition. Sprite extraction.
« Reply #2 on: November 28, 2014, 06:04:25 AM »
So it does! However, in a big atlas like we had, youd have to repeat that process about 100 times.