Author Topic: Creating UIAtlas dynamically  (Read 3483 times)

MoProductions

  • Newbie
  • *
  • Thank You
  • -Given: 3
  • -Receive: 0
  • Posts: 45
    • View Profile
Creating UIAtlas dynamically
« on: May 12, 2014, 03:39:36 PM »
So my project is one of those "need to download new images for use in our UI" situations where logos will be replaced on the fly.
I've come up with 3 solutions:

1) GetPixel/SetPixel on the atlas to replace the source texture.  Took some finagling with read/write ability but got it to work, but then read on the forums that this is a big no-no.

2) Use a UITexture.  This is very simple, but unfortunately I can't guarantee that our images will have power of 2 dimensions, and I noticed that non power of 2 looks blurry when used to replace the texture, even if MakePixelPerfect() is called.

3) Create my own new atlas.  Took some digging, but this appears to work out fine, though I'm not sure if there's anything I'm missing.  And if not, then hey, maybe someone else can make use of this code.  Here's how I do it, with an array of Texture2D's, one of which is named "auburn":

  1. public Texture2D[] textures; // this is set up in the Inspector for now. Will be replaced later by downloaded images.
  2. public UIPanel panel;
  3. void CreateAtlas()
  4. {
  5.         GameObject go = new GameObject("Atlas");
  6.         go.layer = LayerMask.NameToLayer( "UI" );
  7.         go.AddComponent("UIAtlas");
  8.         UIAtlas atlas = go.GetComponent<UIAtlas>();
  9.         Rect[] rects;
  10.         Texture2D tex = new Texture2D(1, 1, TextureFormat.ARGB32, false);
  11.         int maxSize = 2048;
  12.         rects = tex.PackTextures(textures, 1, maxSize);
  13.         atlas.spriteMaterial = new Material(Shader.Find ("Unlit/Transparent Colored"));
  14.         atlas.spriteMaterial.mainTexture = tex;
  15.         List<UISpriteData> list = new List<UISpriteData>();
  16.         for( int i=0; i<textures.Length; i++)
  17.         {
  18.                 UISpriteData data = new UISpriteData();
  19.                 Rect rect = NGUIMath.ConvertToPixels (rects[i], tex.width, tex.height, true );
  20.                 data.x = Mathf.RoundToInt(rect.x);
  21.                 data.y = Mathf.RoundToInt(rect.y);
  22.                 data.width = Mathf.RoundToInt(rect.width);
  23.                 data.height = Mathf.RoundToInt(rect.height);
  24.                 data.name = textures[i].name;
  25.                 list.Add(data);
  26.         }
  27.         atlas.spriteList = list;
  28.         UISprite sprite = NGUITools.AddWidget<UISprite>(panel.gameObject);
  29.         sprite.atlas = atlas;
  30.         sprite.spriteName = "auburn";
  31.         sprite.MakePixelPerfect();
  32. }

Another reason I was curious if that was ok is because the UIAtlasMaker.cs file that I got most of this from uses things like NGUISettings and SpriteEntry (which I think is Editor only).
Thanks!  Hope this stuff is useful elsewhere heh.
« Last Edit: May 12, 2014, 03:46:37 PM by MoProductions »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Creating UIAtlas dynamically
« Reply #1 on: May 13, 2014, 08:28:21 AM »
Quote
2) Use a UITexture.  This is very simple, but unfortunately I can't guarantee that our images will have power of 2 dimensions, and I noticed that non power of 2 looks blurry when used to replace the texture, even if MakePixelPerfect() is called.
Did you allow the texture to be non-power-of-two? What was the final dimension of the created texture, and what format did you use for it?

Rather than creating an entire atlas, just create a sprite sheet. For example, if you know that your sub-textures will always be 50x50, then you can easily use one single large 1024x1024 texture divided into a grid of cells, each 50x50. Keep a list that tells you what index represents what sub-texture, and there you go. Use UITexture to draw it.