标签:
texturepack有开源的工具可以导出json文件,然后倒入sprite。但是很多游戏使用的是plist打包,比如cocos2d。我们做demo可能需要这些资源来用用。所以有此需求。
首先是解析plist。自己xml解析是在麻烦,网上找到个,使用c#的XDocument类,解析成自己的plist类型。代码基本没变,因为plist的<!DOCTYPE>那行总是解析出错,所以在外面载入好字符串,然后去掉这一行。
public void LoadText(string text)
{
Clear();
XDocument doc = XDocument.Parse(text);
XElement plist = doc.Element("plist");
XElement dict = plist.Element("dict");
var dictElements = dict.Elements();
Parse(this, dictElements);
}
然后读取数据载入到自己的TPAtlas类里面(本来想通过这个类,直接缓存读取),然后是写入到textureImporter.spritesheet里,再AssetDatabase.ImportAsset就OK。这里有个问题,就设置sheet后,要重写textureType和spriteImportMode后面ImportAsset才有效,不然内存是改了,但是不会保存到meta文件,下次打开就没了,可能是unity的bug
[MenuItem("Assets/Texture/PLisToSprites(SelectPList)")] static void ConvertSprite() { //EditorUtility.DisplayDialog("MyTool", "Do It in C# !", "OK", ""); Object selobj = Selection.activeObject; string selectionPath = AssetDatabase.GetAssetPath(Selection.activeObject); if (!selectionPath.EndsWith(".plist")) { EditorUtility.DisplayDialog("Error", "Please select a plist file!", "OK", ""); return; } Debug.LogWarning("#PLisToSprites start:" + selectionPath); string fileContent = string.Empty; using (FileStream file = new FileStream(selectionPath, FileMode.Open)) { byte[] str = new byte[(int)file.Length]; file.Read(str, 0, str.Length); fileContent = GetUTF8String(str); Debug.Log(fileContent); file.Close(); file.Dispose(); } //去掉<!DOCTYPE>,不然异常 int delStart = fileContent.IndexOf("<!DOCTYPE"); int delEnd = fileContent.IndexOf("\n", delStart); fileContent = fileContent.Remove(delStart, delEnd - delStart); Debug.Log(fileContent); //解析文件 PList plist = new PList(); plist.LoadText(fileContent);//Load(selectionPath); TPAtlas at = new TPAtlas(); at.LoadX(plist); //重写meta string texPath = Path.GetDirectoryName(selectionPath) + "/" + at.realTextureFileName; Texture2D selTex = AssetDatabase.LoadAssetAtPath(texPath, typeof(Texture2D)) as Texture2D; Debug.Log("texture:" + texPath); Debug.Log("write texture:" + selTex.name+ " size:"+selTex.texelSize); TextureImporter textureImporter = AssetImporter.GetAtPath(texPath) as TextureImporter; if (textureImporter.textureType != TextureImporterType.Sprite && textureImporter.textureType != TextureImporterType.Advanced) { EditorUtility.DisplayDialog("Error", "Texture‘type must be sprite or Advanced!", "OK", ""); return; } if (textureImporter.spriteImportMode!=SpriteImportMode.Multiple) { EditorUtility.DisplayDialog("Error", "spriteImportMode must be Multiple!", "OK", ""); return; } SpriteMetaData[] sheetMetas = new SpriteMetaData[at.sheets.Count]; for (int i = 0; i < at.sheets.Count; i++) { var frameData = at.sheets[i]; sheetMetas[i].alignment = 0; sheetMetas[i].border = new Vector4(0, 0, 0, 0); sheetMetas[i].name = frameData.name; sheetMetas[i].pivot = new Vector2(0.5f, 0.5f); sheetMetas[i].rect = new Rect(frameData.frame.x, at.size.y - frameData.frame.y -frameData.frame.height, frameData.frame.width,frameData.frame.height);//这里原点在左下角,y相反 //Debug.Log("do sprite:" + frameData.name); } //textureImporter.spriteImportMode = SpriteImportMode.Multiple; textureImporter.spritesheet = sheetMetas; //save textureImporter.textureType = TextureImporterType.Sprite; //bug? textureImporter.spriteImportMode = SpriteImportMode.Multiple; //不加这两句会导致无法保存meta AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate); Debug.LogWarning("#PLisToSprites end:" + texPath); }
有些图是ui用unity的sprite做ui目前不太靠谱,所以我们还是使用ngui等插件自己打图,所以要拆分。
还是使用万能的TextureImporter类,拿到sheet然后,每个sheet写入到新图片。
[MenuItem("Assets/Texture/Output Sprites(SelectTexture)")]
static void OutputSprite()
{
string selectionPath = AssetDatabase.GetAssetPath(Selection.activeObject);
Texture2D selTex = Selection.activeObject as Texture2D;
string rootPath = Path.GetDirectoryName(selectionPath) +"/"+ Selection.activeObject.name;
TextureImporter textureImporter = AssetImporter.GetAtPath(selectionPath) as TextureImporter;
//textureImporter.textureType = TextureImporterType.Advanced;
//textureImporter.isReadable = true;
Object[] selected = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
if (!Directory.Exists(rootPath))
Directory.CreateDirectory(rootPath);
Debug.Log("output dir :" + rootPath);
//foreach (var item in selected)
//{
// Sprite sprite = item as Sprite;
// if (sprite == null)
// return;
// string path = rootPath + "/" + sprite.name + ".png";
// Debug.Log("output :" + path);
// SaveSpriteToPNG(sprite, path);
//}
foreach (var spmeta in textureImporter.spritesheet)
{
string path = rootPath + "/" + spmeta.name + ".png";
string subDir = Path.GetDirectoryName(path);
if (!Directory.Exists(subDir))
{
Directory.CreateDirectory(subDir);
}
Debug.Log("output :" + path);
SavePriteToPNG_Meta(selTex, spmeta, path);
}
AssetDatabase.Refresh();
}
static bool SaveSpriteToPNG(Sprite sprite, string outPath)
{
// 创建单独的纹理
Texture2D tex = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height, sprite.texture.format, false);
tex.SetPixels(sprite.texture.GetPixels((int)sprite.rect.xMin, (int)sprite.rect.yMin,
(int)sprite.rect.width, (int)sprite.rect.height));
tex.Apply();
// 写入成PNG文件
File.WriteAllBytes(outPath, tex.EncodeToPNG());
return true;
}
static bool SavePriteToPNG_Meta(Texture2D sourceImg,SpriteMetaData metaData, string outPath)
{
Texture2D myimage = new Texture2D((int)metaData.rect.width, (int)metaData.rect.height, sourceImg.format,false);
Color[] pixs = sourceImg.GetPixels((int)metaData.rect.x, (int)metaData.rect.y,(int)metaData.rect.width, (int)metaData.rect.height);
myimage.SetPixels(pixs);
myimage.Apply();
//AssetDatabase.CreateAsset(myimage, rootPath + "/" + image.name + "/" + metaData.name + ".PNG");
File.WriteAllBytes(outPath, myimage.EncodeToPNG());
return true;
}
代码工程:http://pan.baidu.com/s/1hLqYM
使用注意事项:
plist转sprite要选中plist文件右击操作。元图要改成sprite的multi格式。里面数据名字可能有区别,主要看texture的名字和每个子图的rect,我兼容了两种版本,有其他格式自己改代码吧。还有plist要改成utf8格式,utf8+有时候无效。
拆小图要选中png图右击操作。格式要改成rgba32,不压缩的,类型advanced ,勾上read/write enable。还有size不能小于元图大小。
unity资源texturepack导入和拆图-plist2sprite
标签:
原文地址:http://www.cnblogs.com/magicsea/p/4241120.html