• tag打图下的图集预览


    因为新的项目(Unity4.7的版本环境)使用UI2DSprite的缘故,Atlas的build方式改成了tag的方式,图集也不再实时可见,每次打图优化图集的时间成本变得比较高,没办法,懒癌又起。。。

    using UnityEngine;
    using System.Collections.Generic;
    using System.Collections;
    using UnityEditor;
    using System.IO;
    using System.Linq;
    
    public class PreviewTextureAtlasWinEditor : EditorWindow
    {
    	private SortedDictionary<string, List<string>> texTagPathMap = new SortedDictionary<string, List<string>>();
    	private List<Texture2D> texLst = new List<Texture2D>();
    	private string textureAtlasTagToPreview = "";
    	private bool needRefresh = false;
    	private float scaleRate = 1f;
    
    	private float minScaleRate = 0.3f;
    	private float maxScaleRate = 2f;
    
    	private static PreviewTextureAtlasWinEditor win;
    	[MenuItem("AtlasOptimize/图集预览 %#p", false, 10)]
    	public static void PreviewTextureAtlas()
    	{
    		win = GetWindow<PreviewTextureAtlasWinEditor>(true, "预览图集", true);
    		win.Show();
    
    		win.refreshTagMap();
    	}
    
    	private int lastSelectedIndex = 0;
    	private string[] tagArr;
    	private bool useTag;
    	void OnGUI()
    	{
    		EditorGUILayout.BeginHorizontal();
    		needRefresh = EditorGUILayout.Toggle("ForceRefresh:", needRefresh);
    		useTag = EditorGUILayout.Toggle("UseTag:", useTag);
    
    		if(useTag && tagArr != null && tagArr.Length != 0)
    		{
    			lastSelectedIndex = EditorGUILayout.Popup("AtlasTag", lastSelectedIndex, tagArr);
    			textureAtlasTagToPreview = tagArr[lastSelectedIndex];
    		}
    		else
    		{
    			textureAtlasTagToPreview = EditorGUILayout.TextField("当前搜索图集:", textureAtlasTagToPreview);
    		}
    
    		EditorGUILayout.EndHorizontal();
    
    		if (GUILayout.Button("预览图集")) 
    		{
    			findEnd = false;
    			findTexWithTag(textureAtlasTagToPreview);
    		}
    		if(findEnd)
    		{
    			float tLeft = 0f;
    			float tTop = 70f;
    			int tWidth = Mathf.IsPowerOfTwo(previewAtlas.width) ? previewAtlas.width : Mathf.NextPowerOfTwo(previewAtlas.width);
    			int tHeight = Mathf.IsPowerOfTwo(previewAtlas.height) ? previewAtlas.height : Mathf.NextPowerOfTwo(previewAtlas.height);
    			EditorGUI.DrawTextureTransparent(new Rect(tLeft, tTop, tWidth * scaleRate, tHeight * scaleRate), previewAtlas);
    
    			EditorGUILayout.BeginHorizontal();
    
    			EditorGUILayout.BeginHorizontal();
    			EditorGUILayout.LabelField("Width:", GUILayout.Width(45));
    			EditorGUILayout.LabelField(tWidth.ToString(), GUILayout.Width(60));
    			EditorGUILayout.EndHorizontal();
    
    			EditorGUILayout.Space();
    
    			EditorGUILayout.BeginHorizontal();
    			EditorGUILayout.LabelField("Height:", GUILayout.Width(45));
    			EditorGUILayout.LabelField(tHeight.ToString(), GUILayout.Width(60));
    			EditorGUILayout.EndHorizontal();
    
    			EditorGUILayout.Space();
    
    			EditorGUILayout.BeginHorizontal();
    			EditorGUILayout.LabelField("图元数:", GUILayout.Width(45));
    			EditorGUILayout.LabelField(rectArr.Length.ToString(), GUILayout.Width(60));
    			EditorGUILayout.EndHorizontal();
    			
    			EditorGUILayout.Space();
    
    			scaleRate = EditorGUILayout.Slider("Scale", scaleRate, minScaleRate, maxScaleRate);
    			EditorGUILayout.EndHorizontal();
    
    			if (Event.current.type == EventType.MouseDown)
    			{
    				var tMousePos = Event.current.mousePosition;
    				var tWinPos = win.position;
    				Vector2 tPos = new Vector2((tMousePos.x - tLeft) / (tWidth * scaleRate), 1f - (tMousePos.y - tTop) / (tHeight * scaleRate));	//屏幕坐标系与uv坐标系
    
    				for(int i = 0; i < rectArr.Length; i++)
    				{
    					if(rectArr[i].Contains(tPos))
    					{
    						var tAssetPath = texTagPathMap[textureAtlasTagToPreview][i];
    						//EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(tAssetPath, typeof(Texture)));
    						Selection.activeObject = AssetDatabase.LoadAssetAtPath(tAssetPath, typeof(Texture));
    						break;
    					}
    				}
    			}
    			if (Event.current.type == EventType.ScrollWheel)
    			{
    				float tDeltaScale = Event.current.delta.y / 150f;
    				scaleRate += tDeltaScale;
    				if(scaleRate < minScaleRate)
    				{
    					scaleRate = minScaleRate;
    				}
    				if(scaleRate > maxScaleRate)
    				{
    					scaleRate = maxScaleRate;
    				}
    				win.Repaint();
    			}
    		}
    
    		if (Event.current.type == EventType.KeyDown && tagArr != null && tagArr.Length != 0)
    		{
    			if(Event.current.keyCode == KeyCode.LeftArrow)
    			{
    				lastSelectedIndex--;
    				if(lastSelectedIndex < 0)
    				{
    					lastSelectedIndex = tagArr.Length + lastSelectedIndex;
    				}
    
    				findEnd = false;
    				win.Repaint();
    			}
    			else if(Event.current.keyCode == KeyCode.RightArrow)
    			{
    				lastSelectedIndex++;
    				if(lastSelectedIndex >= tagArr.Length)
    				{
    					lastSelectedIndex = lastSelectedIndex - tagArr.Length;
    				}
    
    				findEnd = false;
    				win.Repaint();
    			}
    		}
    	}
    
    	private void refreshTagMap()
    	{
    		var tAllTextureAssetsGUID = AssetDatabase.FindAssets("t:Texture").ToList<string>();
    		string tAssetPath;
    		TextureImporter tTexImporter;
    		
    		for(int i = 0; i < tAllTextureAssetsGUID.Count; i++)	//过滤
    		{
    			tAssetPath = AssetDatabase.GUIDToAssetPath(tAllTextureAssetsGUID[i]);
    			for(int m = 0; m < filterString.Count; m++)
    			{
    				if(tAssetPath.Contains(filterString[m]))
    				{
    					tAllTextureAssetsGUID.RemoveAt(i);
    					i--;
    					break;
    				}
    			}
    		}
    		
    		if(needRefresh || texTagPathMap.Count == 0)
    		{
    			needRefresh = false;
    			texTagPathMap.Clear();
    			
    			//缓存
    			for (int i = 0; i < tAllTextureAssetsGUID.Count; ++i) 
    			{
    				tAssetPath = AssetDatabase.GUIDToAssetPath(tAllTextureAssetsGUID[i]);
    				tTexImporter = TextureImporter.GetAtPath(tAssetPath) as TextureImporter;
    				
    				if(string.IsNullOrEmpty(tTexImporter.spritePackingTag))
    				{
    					continue;
    				}
    				if(!texTagPathMap.ContainsKey(tTexImporter.spritePackingTag))
    				{
    					texTagPathMap[tTexImporter.spritePackingTag] = new List<string>();
    				}
    				texTagPathMap[tTexImporter.spritePackingTag].Add(tAssetPath);
    				
    				if (EditorUtility.DisplayCancelableProgressBar("CacheTagPathing", tAssetPath, ((i + 1) * 1.0f) / tAllTextureAssetsGUID.Count))
    				{
    					EditorUtility.ClearProgressBar();
    					return;
    				}
    			}
    			EditorUtility.ClearProgressBar();
    			
    			tagArr = texTagPathMap.Keys.ToArray();
    		}
    	}
    
    	private bool findEnd = false;
    	IList<string> filterString = new List<string>()
    	{
    		"Resources", "Editor",  "Plugins", //各种带过滤插件等
    	};
    	private void findTexWithTag(string _tag)
    	{
    		string tAssetPath;
    		TextureImporter tTexImporter;
    
    		refreshTagMap();
    
    		if(texTagPathMap.ContainsKey(textureAtlasTagToPreview))
    		{
    			texLst.Clear();
    			int tCount = texTagPathMap[textureAtlasTagToPreview].Count;
    			bool[] tReadableArr = new bool[tCount];	//状态备份
    			for(int i = 0; i < tCount; i++)
    			{
    				tAssetPath = texTagPathMap[textureAtlasTagToPreview][i];
    
    				tTexImporter = TextureImporter.GetAtPath(tAssetPath) as TextureImporter;
    				tReadableArr[i] = tTexImporter.isReadable;
    				tTexImporter.isReadable = true;
    				AssetDatabase.SaveAssets();
    				AssetDatabase.ImportAsset(tAssetPath);	//强制刷新
    
    				var tTex2D = AssetDatabase.LoadAssetAtPath(tAssetPath, typeof(Texture2D)) as Texture2D;
    				texLst.Add(tTex2D);
    
    				if (EditorUtility.DisplayCancelableProgressBar("PreviewAtlasing", tAssetPath, ((i + 1) * 1.0f) / tCount))
    				{
    					EditorUtility.ClearProgressBar();
    					return;
    				}
    			}
    			PackAtlas(texLst.ToArray());
    
    			EditorUtility.ClearProgressBar();
    			findEnd = true;
    
    			//状态还原
    			for(int i = 0; i < tCount; i++)
    			{
    				tAssetPath = texTagPathMap[textureAtlasTagToPreview][i];
    				
    				tTexImporter = TextureImporter.GetAtPath(tAssetPath) as TextureImporter;
    				tTexImporter.isReadable = tReadableArr[i];
    				AssetDatabase.SaveAssets();
    				AssetDatabase.ImportAsset(tAssetPath);
    			}
    		}
    	}
    
    	private Texture2D previewAtlas = new Texture2D(1, 1);
    	private Rect[] rectArr;
    	public void PackAtlas(Texture2D[] _texArr, int _maxAtlasSize = 2048, int _padding = 0)
    	{
    		previewAtlas.Resize(1, 1);
    		rectArr = previewAtlas.PackTextures(_texArr, _padding, _maxAtlasSize);
    	}
    }
    

      其中,做预览时,迫不得已,考虑到工程的股友问题已经成型,策划、美术对项目的修改标准已经稍乱,年底的时间,项目推进度、改bug,无奈,考虑到各种svn的状态修改与提交成本,只好先做状态备份预还原(此时时间会有所消耗),只好待项目版本告一段落,再开项目总结会议,重新再压一遍标准,标准若能严格执行,则又可省时一大步了。

      考虑到美术或策划或下面的某执行程序可能再增加新的资源时,希望预览到新增美术资源的打图效果及图集大小,于是再进一步:

    public class PreviewTextureAtlasByHandWinEditor : EditorWindow
    {
    	private SortedDictionary<string, List<string>> texTagPathMap = new SortedDictionary<string, List<string>>();
    	private List<Texture2D> texLst = new List<Texture2D>();
    	private List<string> texPathLst = new List<string>();
    	private float scaleRate = 1f;
    	
    	private float minScaleRate = 0.3f;
    	private float maxScaleRate = 2f;
    	
    	private static PreviewTextureAtlasByHandWinEditor win;
    	[MenuItem("AtlasOptimize/预览图集ByHand", false, 11)]
    	public static void PreviewTextureAtlas()
    	{
    		win = GetWindow<PreviewTextureAtlasByHandWinEditor>(true, "预览图集", true);
    		win.Show();
    	}
    
    	private Texture2D previewAtlas = new Texture2D(64, 64);
    	private Rect[] rectArr = new Rect[0];
    	public void PackAtlas(Texture2D[] _texArr, int _maxAtlasSize = 2048, int _padding = 0)
    	{
    		previewAtlas.Resize(1, 1);
    		rectArr = previewAtlas.PackTextures(_texArr, _padding, _maxAtlasSize);
    	}
    
    	private Vector2 lastMousePos = Vector2.zero;
    	private string selectAssetPath;
    	void OnGUI()
    	{
    		float tLeft = 0f;
    		float tTop = 20f;
    		int tWidth = Mathf.IsPowerOfTwo(previewAtlas.width) ? previewAtlas.width : Mathf.NextPowerOfTwo(previewAtlas.width);
    		int tHeight = Mathf.IsPowerOfTwo(previewAtlas.height) ? previewAtlas.height : Mathf.NextPowerOfTwo(previewAtlas.height);
    		var tRect = new Rect(tLeft, tTop, tWidth * scaleRate, tHeight * scaleRate);
    		EditorGUI.DrawTextureTransparent(tRect, previewAtlas);
    		
    		EditorGUILayout.BeginHorizontal();
    		
    		EditorGUILayout.BeginHorizontal();
    		EditorGUILayout.LabelField("Width:", GUILayout.Width(45));
    		EditorGUILayout.LabelField(tWidth.ToString(), GUILayout.Width(60));
    		EditorGUILayout.EndHorizontal();
    		
    		EditorGUILayout.Space();
    		
    		EditorGUILayout.BeginHorizontal();
    		EditorGUILayout.LabelField("Height:", GUILayout.Width(45));
    		EditorGUILayout.LabelField(tHeight.ToString(), GUILayout.Width(60));
    		EditorGUILayout.EndHorizontal();
    		
    		EditorGUILayout.Space();
    		
    		EditorGUILayout.BeginHorizontal();
    		EditorGUILayout.LabelField("图元数:", GUILayout.Width(45));
    		EditorGUILayout.LabelField(rectArr.Length.ToString(), GUILayout.Width(60));
    		EditorGUILayout.EndHorizontal();
    		
    		EditorGUILayout.Space();
    		
    		scaleRate = EditorGUILayout.Slider("Scale", scaleRate, minScaleRate, maxScaleRate);
    		EditorGUILayout.EndHorizontal();
    		
    		if (Event.current.type == EventType.MouseDown)
    		{
    			var tMousePos = Event.current.mousePosition;
    			var tWinPos = win.position;
    			Vector2 tPos = new Vector2((tMousePos.x - tLeft) / (tWidth * scaleRate), 1f - (tMousePos.y - tTop) / (tHeight * scaleRate));	//屏幕坐标系与uv坐标系
    			
    			for(int i = 0; i < rectArr.Length; i++)
    			{
    				if(rectArr[i].Contains(tPos))
    				{
    					selectAssetPath = texPathLst[i];
    					//EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(selectAssetPath, typeof(Texture)));
    					Selection.activeObject = AssetDatabase.LoadAssetAtPath(selectAssetPath, typeof(Texture));
    					break;
    				}
    			}
    		}
    		if(!string.IsNullOrEmpty(selectAssetPath) && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Delete)
    		{
    			packTex(false, selectAssetPath);
    			selectAssetPath = "";
    			win.Repaint();
    		}
    		if (Event.current.type == EventType.ScrollWheel)
    		{
    			float tDeltaScale = Event.current.delta.y / 150f;
    			scaleRate += tDeltaScale;
    			if(scaleRate < minScaleRate)
    			{
    				scaleRate = minScaleRate;
    			}
    			if(scaleRate > maxScaleRate)
    			{
    				scaleRate = maxScaleRate;
    			}
    			win.Repaint();
    		}
    
    		if (Event.current.type == EventType.DragUpdated)	//DragExited触发时,鼠标位置会突变,暂未定位原因
    		{
    			lastMousePos = Event.current.mousePosition;
    			DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
    		}
    		if (Event.current.type == EventType.DragExited)		//动态拖入添加,删除texture
    		{
    			if(!tRect.Contains(lastMousePos))
    			{
    				return;
    			}
    			if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)
    			{
    				packTex(true, DragAndDrop.paths);		//todo: 过滤非texture、文件夹
    				win.Repaint();
    			}
    		}
    	}
    
    	private void packTex(bool _isAppend, params string[] _assetPath)
    	{
    		bool tIsDirty = false;
    		if(_isAppend)
    		{
    			for(int i = 0; i < _assetPath.Length; i++)
    			{
    				if(texPathLst.Contains(_assetPath[i]))
    				{
    					continue;
    				}
    				texPathLst.Add(_assetPath[i]);
    				tIsDirty = true;
    			}
    		}
    		else
    		{
    			for(int i = 0; i < _assetPath.Length; i++)
    			{
    				if(!texPathLst.Contains(_assetPath[i]))
    				{
    					continue;
    				}
    				texPathLst.Remove(_assetPath[i]);
    				tIsDirty = true;
    			}
    		}
    		if(!tIsDirty)
    		{
    			return;
    		}
    
    		bool[] tReadableState = new bool[texPathLst.Count];
    		TextureImporter tTexImporter;
    		texLst.Clear();
    		for(int i = 0; i < texPathLst.Count; i++)
    		{
    			tTexImporter = TextureImporter.GetAtPath(texPathLst[i]) as TextureImporter;
    			tReadableState[i] = tTexImporter.isReadable;    //状态备份
    			tTexImporter.isReadable = true;
    			AssetDatabase.SaveAssets();
    			AssetDatabase.ImportAsset(texPathLst[i]);
    
    			var tTex2D = AssetDatabase.LoadAssetAtPath(texPathLst[i], typeof(Texture2D)) as Texture2D;
    			texLst.Add(tTex2D);
    		}
    
    		PackAtlas(texLst.ToArray());
    		
    		//还原状态
    		for(int i = 0; i < texPathLst.Count; i++)
    		{
    			tTexImporter = TextureImporter.GetAtPath(texPathLst[i]) as TextureImporter;
    			tTexImporter.isReadable = tReadableState[i];
    			AssetDatabase.SaveAssets();
    			AssetDatabase.ImportAsset(texPathLst[i]);
    		}
    	}
    }
    

      为方便定位图集中的每个图元,两种工具都添加了图集到图元的索引(与unity自带的spritepacker相反,可以适当配合使用),都只是做了简单的预览优化之用,未突破unit已提供的不同打图选项设置。目前初版而已,待稍后标准重建,效率自然不成问题。

  • 相关阅读:
    node之body-parser的使用
    node解决跨域问题
    node之post提交上传
    HDU 6397(容斥原理)
    HDU 3374(最小最大表示法+KMP)
    HDU 6396(优先队列+思维)
    HDU 6395(矩阵快速幂)
    HDU 6370(并查集)
    HDU 6356(线段树)
    HDU 6354(计算几何)
  • 原文地址:https://www.cnblogs.com/wayland/p/8287171.html
Copyright © 2020-2023  润新知