From 4ef160de34b26cff43ce06c770981e619a43d111 Mon Sep 17 00:00:00 2001 From: Perfare Date: Wed, 28 Feb 2018 19:10:36 +0800 Subject: [PATCH] Improve Sprite export --- Unity Studio/Unity Classes/Sprite.cs | 125 +++++++++++------- Unity Studio/Unity Classes/SpriteAtlas.cs | 29 ++-- .../Unity Studio Classes/UnityStudio.cs | 59 +++++++-- 3 files changed, 139 insertions(+), 74 deletions(-) diff --git a/Unity Studio/Unity Classes/Sprite.cs b/Unity Studio/Unity Classes/Sprite.cs index da80958..5f2bc0b 100644 --- a/Unity Studio/Unity Classes/Sprite.cs +++ b/Unity Studio/Unity Classes/Sprite.cs @@ -9,54 +9,61 @@ namespace Unity_Studio class Sprite { public string m_Name; + public RectangleF m_Rect; + public float m_PixelsToUnits; + public PointF m_Pivot; + public Guid first; public PPtr texture; public PPtr m_SpriteAtlas; public RectangleF textureRect; + public PointF[][] m_PhysicsShape; public Sprite(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.a_Stream; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.sourceFile.a_Stream; + reader.Position = preloadData.Offset; + var version = sourceFile.version; - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (readSwitch) { //Rectf m_Rect - var m_Rect = new RectangleF(a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle()); + m_Rect = new RectangleF(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); //Vector2f m_Offset - a_Stream.Position += 8; - if (sourceFile.version[0] > 4 || (sourceFile.version[0] == 4 && sourceFile.version[1] >= 2)) //4.2 and up + reader.Position += 8; + if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up { //Vector4f m_Border - a_Stream.Position += 16; + reader.Position += 16; } - var m_PixelsToUnits = a_Stream.ReadSingle(); - if (sourceFile.version[0] > 5 - || (sourceFile.version[0] == 5 && sourceFile.version[1] > 4) - || (sourceFile.version[0] == 5 && sourceFile.version[1] == 4 && sourceFile.version[2] >= 2)) //5.4.2 and up + m_PixelsToUnits = reader.ReadSingle(); + if (version[0] > 5 + || (version[0] == 5 && version[1] > 4) + || (version[0] == 5 && version[1] == 4 && version[2] >= 2)) //5.4.2 and up { //Vector2f m_Pivot - a_Stream.Position += 8; + m_Pivot = new PointF(reader.ReadSingle(), reader.ReadSingle()); } - var m_Extrude = a_Stream.ReadUInt32(); - if (sourceFile.version[0] > 5 || (sourceFile.version[0] == 5 && sourceFile.version[1] >= 3)) //5.3 and up TODO need more test + var m_Extrude = reader.ReadUInt32(); + if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up TODO need more test { - var m_IsPolygon = a_Stream.ReadBoolean(); - a_Stream.AlignStream(4); + var m_IsPolygon = reader.ReadBoolean(); + reader.AlignStream(4); } - if (sourceFile.version[0] >= 2017) //2017 and up + if (version[0] >= 2017) //2017 and up { //pair m_RenderDataKey - a_Stream.Position += 24; + first = new Guid(reader.ReadBytes(16)); + var second = reader.ReadInt64(); //vector m_AtlasTags - var size = a_Stream.ReadInt32(); + var size = reader.ReadInt32(); for (int i = 0; i < size; i++) { - var data = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + var data = reader.ReadAlignedString(reader.ReadInt32()); } //PPtr m_SpriteAtlas @@ -67,66 +74,92 @@ namespace Unity_Studio // PPtr texture texture = sourceFile.ReadPPtr(); // PPtr alphaTexture - if (sourceFile.version[0] >= 5) //5.0 and up + if (version[0] >= 5) //5.0 and up { var alphaTexture = sourceFile.ReadPPtr(); } - if (sourceFile.version[0] > 5 || (sourceFile.version[0] == 5 && sourceFile.version[1] >= 6)) //5.6 and up + if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up { // vector m_SubMeshes - var size = a_Stream.ReadInt32(); + var size = reader.ReadInt32(); // SubMesh data - if (sourceFile.version[0] > 2017 || (sourceFile.version[0] == 2017 && sourceFile.version[1] >= 3)) //2017.3 and up + if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up { - a_Stream.Position += 48 * size; + reader.Position += 48 * size; } else { - a_Stream.Position += 44 * size; + reader.Position += 44 * size; } // vector m_IndexBuffer - size = a_Stream.ReadInt32(); - a_Stream.Position += size; //UInt8 data - a_Stream.AlignStream(4); + size = reader.ReadInt32(); + reader.Position += size; //UInt8 data + reader.AlignStream(4); // VertexData m_VertexData - var m_CurrentChannels = a_Stream.ReadInt32(); - var m_VertexCount = a_Stream.ReadUInt32(); + var m_CurrentChannels = reader.ReadInt32(); + var m_VertexCount = reader.ReadUInt32(); // vector m_Channels - size = a_Stream.ReadInt32(); - a_Stream.Position += size * 4; //ChannelInfo data + size = reader.ReadInt32(); + reader.Position += size * 4; //ChannelInfo data // TypelessData m_DataSize - size = a_Stream.ReadInt32(); - a_Stream.Position += size; //UInt8 data - a_Stream.AlignStream(4); + size = reader.ReadInt32(); + reader.Position += size; //UInt8 data + reader.AlignStream(4); } else { // vector vertices - var size = a_Stream.ReadInt32(); + var size = reader.ReadInt32(); for (int i = 0; i < size; i++) { //SpriteVertex data - a_Stream.Position += 12; //Vector3f pos - if (sourceFile.version[0] < 4 || (sourceFile.version[0] == 4 && sourceFile.version[1] <= 1)) //4.1 and down - a_Stream.Position += 8; //Vector2f uv + reader.Position += 12; //Vector3f pos + if (version[0] < 4 || (version[0] == 4 && version[1] <= 1)) //4.1 and down + reader.Position += 8; //Vector2f uv } // vector indices - size = a_Stream.ReadInt32(); - a_Stream.Position += 2 * size; //UInt16 data - a_Stream.AlignStream(4); + size = reader.ReadInt32(); + reader.Position += 2 * size; //UInt16 data + reader.AlignStream(4); } // Rectf textureRect - textureRect = new RectangleF(a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle()); + textureRect = new RectangleF(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); // Vector2f textureRectOffset + reader.Position += 8; // Vector2f atlasRectOffset - 5.6 and up + if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up + { + reader.Position += 8; + } // unsigned int settingsRaw + reader.Position += 4; // Vector4f uvTransform - 4.2 and up - // float downscaleMultiplier - 2017 and up - //vector m_PhysicsShape - 2017 and up + if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up + { + reader.Position += 16; + } + if (version[0] >= 2017) //2017 and up + { + // float downscaleMultiplier - 2017 and up + reader.Position += 4; + //vector m_PhysicsShape - 2017 and up + var m_PhysicsShape_size = reader.ReadInt32(); + m_PhysicsShape = new PointF[m_PhysicsShape_size][]; + for (int i = 0; i < m_PhysicsShape_size; i++) + { + var data_size = reader.ReadInt32(); + //Vector2f + m_PhysicsShape[i] = new PointF[data_size]; + for (int j = 0; j < data_size; j++) + { + m_PhysicsShape[i][j] = new PointF(reader.ReadSingle(), reader.ReadSingle()); + } + } + } } else { diff --git a/Unity Studio/Unity Classes/SpriteAtlas.cs b/Unity Studio/Unity Classes/SpriteAtlas.cs index 5e0f782..f62297a 100644 --- a/Unity Studio/Unity Classes/SpriteAtlas.cs +++ b/Unity Studio/Unity Classes/SpriteAtlas.cs @@ -8,55 +8,56 @@ namespace Unity_Studio { class SpriteAtlas { - public List m_PackedSprites = new List(); public List textures = new List(); public List textureRects = new List(); + public List guids = new List(); public SpriteAtlas(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.a_Stream; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.sourceFile.a_Stream; + reader.Position = preloadData.Offset; - var m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + var m_Name = reader.ReadAlignedString(reader.ReadInt32()); //vector m_PackedSprites - var size = a_Stream.ReadInt32(); + var size = reader.ReadInt32(); for (int i = 0; i < size; i++) { //PPtr data - m_PackedSprites.Add(sourceFile.ReadPPtr()); + sourceFile.ReadPPtr(); } //vector m_PackedSpriteNamesToIndex - size = a_Stream.ReadInt32(); + size = reader.ReadInt32(); for (int i = 0; i < size; i++) { - var data = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + var data = reader.ReadAlignedString(reader.ReadInt32()); } //map m_RenderDataMap - size = a_Stream.ReadInt32(); + size = reader.ReadInt32(); for (int i = 0; i < size; i++) { //pair first - a_Stream.Position += 24; + guids.Add(new Guid(reader.ReadBytes(16))); + var second = reader.ReadInt64(); //SpriteAtlasData second // PPtr texture textures.Add(sourceFile.ReadPPtr()); // PPtr alphaTexture var alphaTexture = sourceFile.ReadPPtr(); // Rectf textureRect - textureRects.Add(new RectangleF(a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle())); + textureRects.Add(new RectangleF(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle())); // Vector2f textureRectOffset - a_Stream.Position += 8; + reader.Position += 8; if (sourceFile.version[0] > 2017 || (sourceFile.version[0] == 2017 && sourceFile.version[1] >= 2))//2017.2 and up { // Vector2f atlasRectOffset - a_Stream.Position += 8; + reader.Position += 8; } // Vector4f uvTransform // float downscaleMultiplier // unsigned int settingsRaw - a_Stream.Position += 24; + reader.Position += 24; } //string m_Tag //bool m_IsVariant diff --git a/Unity Studio/Unity Studio Classes/UnityStudio.cs b/Unity Studio/Unity Studio Classes/UnityStudio.cs index a4ee3b6..76b59df 100644 --- a/Unity Studio/Unity Studio Classes/UnityStudio.cs +++ b/Unity Studio/Unity Studio Classes/UnityStudio.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.IO; @@ -1909,28 +1910,18 @@ namespace Unity_Studio return selectFile.Distinct().ToArray(); } - //TODO Tight方式的Sprite需要读取多边形信息进行绘图 public static Bitmap GetImageFromSprite(AssetPreloadData asset) { if (spriteCache.TryGetValue(asset, out var bitmap)) return (Bitmap)bitmap.Clone(); var m_Sprite = new Sprite(asset, true); - if (m_Sprite.m_SpriteAtlas != null && assetsfileList.TryGetPD(m_Sprite.m_SpriteAtlas, out var assetPreloadData)) + if (assetsfileList.TryGetPD(m_Sprite.m_SpriteAtlas, out var assetPreloadData)) { var m_SpriteAtlas = new SpriteAtlas(assetPreloadData); - bool find = false; - int index = 0; - for (; index < m_SpriteAtlas.m_PackedSprites.Count; index++) + var index = m_SpriteAtlas.guids.FindIndex(x => x == m_Sprite.first); + if (index >= 0 && assetsfileList.TryGetPD(m_SpriteAtlas.textures[index], out assetPreloadData)) { - if (assetsfileList.TryGetPD(m_SpriteAtlas.m_PackedSprites[index], out assetPreloadData) && assetPreloadData == asset) - { - find = true; - break; - } - } - if (find && assetsfileList.TryGetPD(m_SpriteAtlas.textures[index], out assetPreloadData)) - { - return CutImage(asset, assetPreloadData, m_SpriteAtlas.textureRects[index]); + return CutImage(asset, assetPreloadData, m_SpriteAtlas.textureRects[index], m_Sprite); } } else @@ -1964,5 +1955,45 @@ namespace Unity_Studio return null; } + + private static Bitmap CutImage(AssetPreloadData asset, AssetPreloadData texture2DAsset, RectangleF textureRect, Sprite sprite) + { + var texture2D = new Texture2D(texture2DAsset, true); + using (var originalImage = texture2D.ConvertToBitmap(false)) + { + if (originalImage != null) + { + var info = texture2DAsset.InfoText; + var start = info.IndexOf("Format"); + info = info.Substring(start, info.Length - start); + asset.InfoText = $"Width: {textureRect.Width}\nHeight: {textureRect.Height}\n" + info; + var spriteImage = originalImage.Clone(textureRect, PixelFormat.Format32bppArgb); + using (var brush = new TextureBrush(spriteImage)) + { + using (var path = new GraphicsPath()) + { + foreach (var p in sprite.m_PhysicsShape) + path.AddPolygon(p); + using (var matr = new Matrix()) + { + matr.Translate(sprite.m_Rect.Width * sprite.m_Pivot.X, sprite.m_Rect.Height * sprite.m_Pivot.Y); + matr.Scale(sprite.m_PixelsToUnits, sprite.m_PixelsToUnits); + path.Flatten(matr); + var bitmap = new Bitmap((int)textureRect.Width, (int)textureRect.Height); + using (var graphic = Graphics.FromImage(bitmap)) + { + graphic.FillPath(brush, path); + bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); + spriteCache.Add(asset, bitmap); + return (Bitmap)bitmap.Clone(); + } + } + } + } + } + } + + return null; + } } }