Improve Sprite export

This commit is contained in:
Perfare 2018-02-28 19:10:36 +08:00
parent 351228e45c
commit 4ef160de34
3 changed files with 139 additions and 74 deletions

View File

@ -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<SpriteAtlas> m_SpriteAtlas
@ -67,66 +74,92 @@ namespace Unity_Studio
// PPtr<Texture2D> texture
texture = sourceFile.ReadPPtr();
// PPtr<Texture2D> 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
{

View File

@ -8,55 +8,56 @@ namespace Unity_Studio
{
class SpriteAtlas
{
public List<PPtr> m_PackedSprites = new List<PPtr>();
public List<PPtr> textures = new List<PPtr>();
public List<RectangleF> textureRects = new List<RectangleF>();
public List<Guid> guids = new List<Guid>();
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<Sprite> 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<Texture2D> texture
textures.Add(sourceFile.ReadPPtr());
// PPtr<Texture2D> 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

View File

@ -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;
}
}
}