| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- public class Canvas3DImpl : Singleton<Canvas3DImpl>
- {
- private Dictionary<int, Sprite3D> m_childSprites = new Dictionary<int, Sprite3D>();
- private Dictionary<int, TextMesh> m_childText = new Dictionary<int, TextMesh>();
- private int m_depth = 0;
- private bool m_needRefreshLayout = false;
- private Dictionary<string, AutoAtlasInfo> m_atlas = new Dictionary<string, AutoAtlasInfo>();
- private bool m_needRebuildAtlas = false;
- private class AutoAtlasInfo
- {
- private static int[] textureSize =
- {
- 128,
- 256,
- 512,
- 1024
- };
- private int counter = 1;
- private Dictionary<int, AtlasInfo.UVDetail> textures = new Dictionary<int, AtlasInfo.UVDetail>(); //Texture的GUID和uv的映射关系
- public bool needRebuildAtlas = false;
- private bool needCompress = false;
- private int padding = 0;
- private HashSet<Sprite3D> sprites = new HashSet<Sprite3D>();
- public Texture2D atlas = null;
- public Texture2D altasAlpha = null; //做纹理压缩用的
- private Material mat = null;
- private Dictionary<int, Texture2D> waitForCombineTextures = new Dictionary<int, Texture2D>();
- public void Register(Sprite3D sprite)
- {
- if (null == sprite || null == sprite.texture)
- {
- return;
- }
- int id = sprite.texture.GetNativeTextureID();
- sprite.m_textureGUID = id;
- AtlasInfo.UVDetail uv = null;
- padding = Mathf.Max(padding, sprite.padding);
- needCompress = needCompress | sprite.compress;
- if (textures.TryGetValue(id, out uv))
- {
- sprites.Add(sprite);
- if (null != mat)
- {
- sprite.SetMaterial(mat);
- }
- sprite.SetAutoAtlas(atlas, uv);
- return;
- }
- else
- {
- uv = new AtlasInfo.UVDetail();
- uv.width = 0;
- uv.height = 0;
- uv.width = sprite.texture.width;
- uv.height = sprite.texture.height;
- uv.rotate = false;
- textures.Add(id, uv);
- waitForCombineTextures.Add(id, sprite.texture);
- }
- needRebuildAtlas = true;
- sprites.Add(sprite);
- }
- public void Unregister(Sprite3D sprite)
- {
- sprites.Remove(sprite);
- if (sprites.Count == 0)
- {
- textures.Clear();
- if (mat != null)
- {
- Object.Destroy(mat);
- }
- mat = null;
- if (atlas != null)
- {
- Object.Destroy(atlas);
- }
- atlas = null;
- }
- }
- public void Rebuild()
- {
- needRebuildAtlas = false;
- bool succ = false;
- for (int i = 0; i < textureSize.Length; ++i)
- {
- if (atlas != null && textureSize[i] < atlas.width)
- {
- continue;
- }
- succ = Pack(textureSize[i]);
- if (succ)
- {
- break;
- }
- }
- if (!succ)
- {
- var it = sprites.GetEnumerator();
- it.MoveNext();
- Debug.LogError("Dynamic Combine Atlas Failed, maybe too many pictures of atlas tag:\"" + it.Current.autoAtlasTag + "\"");
- }
- }
- private bool Pack(int size)
- {
- int columnPosition = 0;
- int x = 0;
- int y = 0;
- int spacing = padding;
- Vector2 atlasSize = Vector2.zero;
- Dictionary<int, AtlasInfo.UVDetail> tmp = new Dictionary<int, AtlasInfo.UVDetail>();
- var iter = textures.GetEnumerator();
- while (iter.MoveNext())
- {
- int width = iter.Current.Value.width;
- int height = iter.Current.Value.height;
- AtlasInfo.UVDetail uv = new AtlasInfo.UVDetail();
- uv.rotate = false;
- tmp.Add(iter.Current.Key, uv);
- if (y + height + spacing <= size && x + width + spacing <= size)
- {
- uv.x = x;
- uv.y = y;
- uv.width = width;
- uv.height = height;
- y += height + spacing;
- if (columnPosition < x + width + spacing)
- columnPosition = x + width + spacing;
- }
- else if (columnPosition + width <= size && height <= size)
- {
- x = columnPosition;
- uv.x = x;
- uv.y = 0;
- uv.width = width;
- uv.height = height;
- y = height + spacing;
- columnPosition = x + width + spacing;
- }
- else
- {
- return false;
- }
- }
- TextureFormat format = TextureFormat.ARGB32;
- if (needCompress)
- {
- #if UNITY_ANDROID && !UNITY_EDITOR
- format = TextureFormat.ARGB32; //format = TextureFormat.ETC_RGB4;
- #elif UNITY_IOS && !UNITY_EDITOR
- format = TextureFormat.ARGB32; //format = TextureFormat.PVRTC_RGBA4;
- #else
- format = TextureFormat.ARGB32;
- #endif
- }
- Texture2D newTex = new Texture2D(size, size, format, false);
- Color[] clearColor = new Color[newTex.width * newTex.height]; //默认全是0
- newTex.SetPixels(clearColor);
- newTex.name = "Auto_UI3D_Atlas_" + size + "_" + counter + "_format" + format.ToString();
- counter++;
- iter = textures.GetEnumerator();
- while (iter.MoveNext())
- {
- Texture2D tex = null;
- if (!waitForCombineTextures.TryGetValue(iter.Current.Key, out tex))
- {
- tex = this.atlas;
- }
- var uv = iter.Current.Value;
- var uvNew = tmp[iter.Current.Key];
- Color[] orig = tex.GetPixels(uv.x, uv.y, uv.width, uv.height);
- newTex.SetPixels(uvNew.x, uvNew.y, uv.width, uv.height, orig);
- newTex.Apply(false, false);
- uvNew.uvTL = new Vector2((float)uvNew.x / newTex.width, (float)(uvNew.y + uvNew.height) / newTex.height);
- uvNew.uvTR = new Vector2((float)(uvNew.x + uvNew.width) / newTex.width, (float)(uvNew.y + uvNew.height) / newTex.height);
- uvNew.uvBL = new Vector2((float)uvNew.x / newTex.width, (float)(uvNew.y) / newTex.height);
- uvNew.uvBR = new Vector2((float)(uvNew.x + uvNew.width) / newTex.width, (float)(uvNew.y) / newTex.height);
- }
- textures = tmp;
- Object.Destroy(atlas);
- atlas = newTex;
- //Shader shader = CResourceManager.GetInstance().GetResource("Shaders/UI/UI3D.shader", typeof(Shader), enResourceType.BattleScene, true, true).m_content as Shader;
- //todo bhy
- Shader shader = Shader.Find("UI/UI3D");
- mat = new Material(shader);
- mat.SetTexture("_MainTex", atlas);
- var iterSprites = sprites.GetEnumerator();
- while (iterSprites.MoveNext())
- {
- iterSprites.Current.SetMaterial(mat);
- iterSprites.Current.SetAutoAtlas(atlas, textures[iterSprites.Current.m_textureGUID]);
- }
- var iterWaitForRelease = waitForCombineTextures.GetEnumerator();
- waitForCombineTextures.Clear();
- //todo bhy
- //CResourceManager.GetInstance().UnloadUnusedAssets();
- return true;
- }
- }
- public void Reset()
- {
- m_childSprites.Clear();
- m_childText.Clear();
- #if UNITY_EDITOR
- var iter = m_atlas.GetEnumerator();
- while (iter.MoveNext())
- {
- if (iter.Current.Value.atlas != null)
- {
- Debug.LogError("还有3D UI自动生成的altas没有清理干净!");
- }
- }
- #endif
- m_atlas.Clear();
-
- //todo bhy
- //CResourceManager.GetInstance().UnloadUnusedAssets();
- }
- public void Update(Transform root)
- {
- if (m_needRefreshLayout)
- {
- _DoRefreshLayout(root);
- m_needRefreshLayout = false;
- }
- if (m_needRebuildAtlas)
- {
- _DoRebuildAtlas();
- m_needRebuildAtlas = true;
- }
- }
- public void registerAutoAtlas(Sprite3D sprite)
- {
- if (sprite.texture == null)
- {
- return;
- }
- #if UNITY_EDITOR
- //非运行时也不做任何合并工作
- if (string.IsNullOrEmpty(sprite.autoAtlasTag) || !UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
- #else
- if (string.IsNullOrEmpty(sprite.autoAtlasTag))
- #endif
- {
- //不打图集的直接就生成uv了
- AtlasInfo.UVDetail uv = new AtlasInfo.UVDetail();
- uv.uvBL = new Vector2(0, 0);
- uv.uvTL = new Vector2(0, 1);
- uv.uvBR = new Vector2(1, 0);
- uv.uvTR = new Vector2(1, 1);
- uv.rotate = false;
- uv.x = 0;
- uv.y = 0;
- uv.width = sprite.texture.width;
- uv.height = sprite.texture.height;
- sprite.SetUV(uv);
- return;
- }
- AutoAtlasInfo info = null;
- if (!m_atlas.TryGetValue(sprite.autoAtlasTag, out info))
- {
- info = new AutoAtlasInfo();
- m_atlas.Add(sprite.autoAtlasTag, info);
- }
- info.Register(sprite);
- m_needRebuildAtlas = true;
- }
- public void registerSprite3D(Sprite3D sprite)
- {
- if (!m_childSprites.ContainsKey(sprite.transform.GetInstanceID()))
- {
- m_childSprites.Add(sprite.transform.GetInstanceID(), sprite);
- }
- }
- public void unregisterSprite3d(Sprite3D sprite)
- {
- m_childSprites.Remove(sprite.transform.GetInstanceID());
- }
- public void unregisterAutoAtlas(Sprite3D sprite)
- {
- if (sprite.texture == null || string.IsNullOrEmpty(sprite.autoAtlasTag))
- {
- return;
- }
- AutoAtlasInfo info = null;
- if (!m_atlas.TryGetValue(sprite.autoAtlasTag, out info))
- {
- return;
- }
- info.Unregister(sprite);
- }
- private void _DoRebuildAtlas()
- {
- var iter = m_atlas.GetEnumerator();
- while (iter.MoveNext())
- {
- AutoAtlasInfo info = iter.Current.Value;
- if (!info.needRebuildAtlas)
- {
- continue;
- }
- info.Rebuild();
- }
- }
- private void RefreshHierachy(Transform root)
- {
- if (root == null) return;
- if (!root.gameObject.activeSelf)
- {
- return;
- }
- for (int i = root.childCount - 1; i >= 0; --i)
- {
- RefreshHierachy(root.GetChild(i));
- }
- Sprite3D sprite = null;
- if (m_childSprites.TryGetValue(root.GetInstanceID(), out sprite))
- {
- if (null != sprite)
- {
- ++m_depth;
- #if UNITY_EDITOR
- if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
- {
- sprite.PrepareMesh();
- registerAutoAtlas(sprite);
- sprite.GenerateMesh();
- sprite.RefreshAtlasMaterial();
- sprite.RefreshAutoAtlasMaterial();
- }
- #endif
- sprite.depth = m_depth;
- }
- }
- else
- {
- #if UNITY_EDITOR
- if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
- {
- //Debug.LogError("GameObject \"" + root.name + "\" with Sprite3D is not registered in Canvas3D!");
- }
- #endif
- sprite = root.GetComponent<Sprite3D>();
- m_childSprites.Add(root.GetInstanceID(), sprite);
- if (null != sprite)
- {
- ++m_depth;
- #if UNITY_EDITOR
- if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
- {
- #if UNITY_EDITOR
- if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
- {
- sprite.PrepareMesh();
- registerAutoAtlas(sprite);
- sprite.GenerateMesh();
- sprite.RefreshAtlasMaterial();
- sprite.RefreshAutoAtlasMaterial();
- }
- #endif
- }
- #endif
- sprite.depth = m_depth;
- }
- }
- TextMesh text = null;
- //针对文本的排序
- if (sprite == null)
- {
- if (m_childText.TryGetValue(root.GetInstanceID(), out text))
- {
- if (null != text)
- {
- ++m_depth;
- text.offsetZ = (float)m_depth / 10;
- }
- }
- else
- {
- text = root.GetComponent<TextMesh>();
- m_childText.Add(root.GetInstanceID(), text);
- if (null != text)
- {
- ++m_depth;
- text.offsetZ = (float)m_depth / 10;
- }
- }
- }
- }
- public void RebuildAtlasImmediately()
- {
- _DoRebuildAtlas();
- }
- public void RefreshLayout(Transform root = null)
- {
- m_needRefreshLayout = true;
- #if UNITY_EDITOR
- if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
- {
- _DoRefreshLayout(root);
- }
- #endif
- }
- private void _DoRefreshLayout(Transform root)
- {
- m_depth = 0;
- RefreshHierachy(root);
- }
- }
|