- new streamlined and modular code for exporting assets

- improved export status messages
- support for DXTn Crunched textures (extract only)
This commit is contained in:
Radu 2015-11-23 22:33:42 +02:00
parent 17bfc966c8
commit 00966b2bce
7 changed files with 465 additions and 618 deletions

View File

@ -17,6 +17,7 @@ namespace Unity_Studio
public string TypeString; public string TypeString;
public int exportSize; public int exportSize;
public string InfoText; public string InfoText;
public string extension;
public AssetsFile sourceFile; public AssetsFile sourceFile;
public string uniqueID; public string uniqueID;

View File

@ -176,7 +176,6 @@ namespace Unity_Studio
} }
} }
asset.TypeString = asset.Type2.ToString();
if (UnityClassID.Names[asset.Type2] != null) if (UnityClassID.Names[asset.Type2] != null)
{ {
asset.TypeString = UnityClassID.Names[asset.Type2]; asset.TypeString = UnityClassID.Names[asset.Type2];

View File

@ -31,8 +31,6 @@ namespace Unity_Studio
public long m_Offset; public long m_Offset;
public long m_Size; public long m_Size;
public byte[] m_AudioData; public byte[] m_AudioData;
public string extension = "";
public AudioClip(AssetPreloadData preloadData, bool readSwitch) public AudioClip(AssetPreloadData preloadData, bool readSwitch)
{ {
@ -94,58 +92,7 @@ namespace Unity_Studio
m_Size = a_Stream.ReadInt64(); m_Size = a_Stream.ReadInt64();
m_CompressionFormat = a_Stream.ReadInt32(); m_CompressionFormat = a_Stream.ReadInt32();
} }
#region Info Text & extension
preloadData.InfoText = "Compression format: ";
switch (m_Type)
{
case 2:
extension = ".aif";
preloadData.InfoText += "AIFF";
break;
case 13:
extension = ".mp3";
preloadData.InfoText += "MP3";
break;
case 14:
extension = ".ogg";
preloadData.InfoText += "Ogg Vorbis";
break;
case 20:
extension = ".wav";
preloadData.InfoText += "WAV";
break;
case 22: //xbox encoding
extension = ".wav";
preloadData.InfoText += "Xbox360 WAV";
break;
}
switch (m_CompressionFormat)
{
case 0:
extension = ".fsb";
preloadData.InfoText += "PCM";
break;
case 1:
extension = ".fsb";
preloadData.InfoText += "Vorbis";
break;
case 2:
extension = ".fsb";
preloadData.InfoText += "ADPCM";
break;
case 3:
extension = ".fsb";
preloadData.InfoText += "MP3";//not sure
break;
}
if (extension == "") { preloadData.InfoText += "Unknown"; }
preloadData.InfoText += "\n3D: " + m_3D.ToString();
#endregion
if (readSwitch) if (readSwitch)
{ {
m_AudioData = new byte[m_Size]; m_AudioData = new byte[m_Size];
@ -164,6 +111,66 @@ namespace Unity_Studio
} }
} }
} }
else
{
preloadData.InfoText = "Compression format: ";
switch (m_Type)
{
case 2:
preloadData.extension = ".aif";
preloadData.InfoText += "AIFF";
break;
case 13:
preloadData.extension = ".mp3";
preloadData.InfoText += "MP3";
break;
case 14:
preloadData.extension = ".ogg";
preloadData.InfoText += "Ogg Vorbis";
break;
case 20:
preloadData.extension = ".wav";
preloadData.InfoText += "WAV";
break;
case 22: //xbox encoding
preloadData.extension = ".wav";
preloadData.InfoText += "Xbox360 WAV";
break;
}
switch (m_CompressionFormat)
{
case 0:
preloadData.extension = ".fsb";
preloadData.InfoText += "PCM";
break;
case 1:
preloadData.extension = ".fsb";
preloadData.InfoText += "Vorbis";
break;
case 2:
preloadData.extension = ".fsb";
preloadData.InfoText += "ADPCM";
break;
case 3:
preloadData.extension = ".fsb";
preloadData.InfoText += "MP3";//not sure
break;
}
if (preloadData.extension == "")
{
preloadData.extension = ".AudioClip";
preloadData.InfoText += "Unknown";
}
preloadData.InfoText += "\n3D: " + m_3D.ToString();
if (m_Name != "") { preloadData.Text = m_Name; }
else { preloadData.Text = preloadData.TypeString + " #" + preloadData.uniqueID; }
preloadData.exportSize = (int)m_Size;
preloadData.SubItems.AddRange(new string[] { preloadData.TypeString, m_Size.ToString() });
}
} }
} }
} }

View File

@ -9,9 +9,8 @@ namespace Unity_Studio
{ {
public string m_Name; public string m_Name;
public byte[] m_FontData; public byte[] m_FontData;
public string extension;
public unityFont(AssetPreloadData preloadData) public unityFont(AssetPreloadData preloadData, bool readSwitch)
{ {
var sourceFile = preloadData.sourceFile; var sourceFile = preloadData.sourceFile;
var a_Stream = preloadData.sourceFile.a_Stream; var a_Stream = preloadData.sourceFile.a_Stream;
@ -26,106 +25,115 @@ namespace Unity_Studio
m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32());
int m_AsciiStartOffset = a_Stream.ReadInt32(); if (readSwitch)
if (sourceFile.version[0] <= 3)
{ {
int m_FontCountX = a_Stream.ReadInt32(); int m_AsciiStartOffset = a_Stream.ReadInt32();
int m_FontCountY = a_Stream.ReadInt32();
}
float m_Kerning = a_Stream.ReadSingle(); if (sourceFile.version[0] <= 3)
float m_LineSpacing = a_Stream.ReadSingle();
if (sourceFile.version[0] <= 3)
{
int m_PerCharacterKerning_size = a_Stream.ReadInt32();
for (int i = 0; i < m_PerCharacterKerning_size; i++)
{ {
int first = a_Stream.ReadInt32(); int m_FontCountX = a_Stream.ReadInt32();
int m_FontCountY = a_Stream.ReadInt32();
}
float m_Kerning = a_Stream.ReadSingle();
float m_LineSpacing = a_Stream.ReadSingle();
if (sourceFile.version[0] <= 3)
{
int m_PerCharacterKerning_size = a_Stream.ReadInt32();
for (int i = 0; i < m_PerCharacterKerning_size; i++)
{
int first = a_Stream.ReadInt32();
float second = a_Stream.ReadSingle();
}
}
else
{
int m_CharacterSpacing = a_Stream.ReadInt32();
int m_CharacterPadding = a_Stream.ReadInt32();
}
int m_ConvertCase = a_Stream.ReadInt32();
PPtr m_DefaultMaterial = sourceFile.ReadPPtr();
int m_CharacterRects_size = a_Stream.ReadInt32();
for (int i = 0; i < m_CharacterRects_size; i++)
{
int index = a_Stream.ReadInt32();
//Rectf uv
float uvx = a_Stream.ReadSingle();
float uvy = a_Stream.ReadSingle();
float uvwidth = a_Stream.ReadSingle();
float uvheight = a_Stream.ReadSingle();
//Rectf vert
float vertx = a_Stream.ReadSingle();
float verty = a_Stream.ReadSingle();
float vertwidth = a_Stream.ReadSingle();
float vertheight = a_Stream.ReadSingle();
float width = a_Stream.ReadSingle();
if (sourceFile.version[0] >= 4)
{
bool flipped = a_Stream.ReadBoolean();
a_Stream.Position += 3;
}
}
PPtr m_Texture = sourceFile.ReadPPtr();
int m_KerningValues_size = a_Stream.ReadInt32();
for (int i = 0; i < m_KerningValues_size; i++)
{
int pairfirst = a_Stream.ReadInt16();
int pairsecond = a_Stream.ReadInt16();
float second = a_Stream.ReadSingle(); float second = a_Stream.ReadSingle();
} }
if (sourceFile.version[0] <= 3)
{
bool m_GridFont = a_Stream.ReadBoolean();
a_Stream.Position += 3; //4 byte alignment
}
else { float m_PixelScale = a_Stream.ReadSingle(); }
int m_FontData_size = a_Stream.ReadInt32();
if (m_FontData_size > 0)
{
m_FontData = new byte[m_FontData_size];
a_Stream.Read(m_FontData, 0, m_FontData_size);
if (m_FontData[0] == 79 && m_FontData[1] == 84 && m_FontData[2] == 84 && m_FontData[3] == 79)
{ preloadData.extension = ".otf"; }
else { preloadData.extension = ".ttf"; }
}
float m_FontSize = a_Stream.ReadSingle();//problem here in minifootball
float m_Ascent = a_Stream.ReadSingle();
uint m_DefaultStyle = a_Stream.ReadUInt32();
int m_FontNames = a_Stream.ReadInt32();
for (int i = 0; i < m_FontNames; i++)
{
string m_FontName = a_Stream.ReadAlignedString(a_Stream.ReadInt32());
}
if (sourceFile.version[0] >= 4)
{
int m_FallbackFonts = a_Stream.ReadInt32();
for (int i = 0; i < m_FallbackFonts; i++)
{
PPtr m_FallbackFont = sourceFile.ReadPPtr();
}
int m_FontRenderingMode = a_Stream.ReadInt32();
}
} }
else else
{ {
int m_CharacterSpacing = a_Stream.ReadInt32(); if (m_Name != "") { preloadData.Text = m_Name; }
int m_CharacterPadding = a_Stream.ReadInt32(); else { preloadData.Text = preloadData.TypeString + " #" + preloadData.uniqueID; }
} preloadData.SubItems.AddRange(new string[] { preloadData.TypeString, preloadData.exportSize.ToString() });
int m_ConvertCase = a_Stream.ReadInt32();
PPtr m_DefaultMaterial = sourceFile.ReadPPtr();
int m_CharacterRects_size = a_Stream.ReadInt32();
for (int i = 0; i < m_CharacterRects_size; i++)
{
int index = a_Stream.ReadInt32();
//Rectf uv
float uvx = a_Stream.ReadSingle();
float uvy = a_Stream.ReadSingle();
float uvwidth = a_Stream.ReadSingle();
float uvheight = a_Stream.ReadSingle();
//Rectf vert
float vertx = a_Stream.ReadSingle();
float verty = a_Stream.ReadSingle();
float vertwidth = a_Stream.ReadSingle();
float vertheight = a_Stream.ReadSingle();
float width = a_Stream.ReadSingle();
if (sourceFile.version[0] >= 4)
{
bool flipped = a_Stream.ReadBoolean();
a_Stream.Position += 3;
}
}
PPtr m_Texture = sourceFile.ReadPPtr();
int m_KerningValues_size = a_Stream.ReadInt32();
for (int i = 0; i < m_KerningValues_size; i++)
{
int pairfirst = a_Stream.ReadInt16();
int pairsecond = a_Stream.ReadInt16();
float second = a_Stream.ReadSingle();
}
if (sourceFile.version[0] <= 3)
{
bool m_GridFont = a_Stream.ReadBoolean();
a_Stream.Position += 3; //4 byte alignment
}
else { float m_PixelScale = a_Stream.ReadSingle(); }
int m_FontData_size = a_Stream.ReadInt32();
if (m_FontData_size > 0)
{
m_FontData = new byte[m_FontData_size];
a_Stream.Read(m_FontData, 0, m_FontData_size);
if (m_FontData[0] == 79 && m_FontData[1] == 84 && m_FontData[2] == 84 && m_FontData[3] == 79)
{ extension = ".otf"; }
else { extension = ".ttf"; }
}
float m_FontSize = a_Stream.ReadSingle();//problem here in minifootball
float m_Ascent = a_Stream.ReadSingle();
uint m_DefaultStyle = a_Stream.ReadUInt32();
int m_FontNames = a_Stream.ReadInt32();
for (int i = 0; i < m_FontNames; i++)
{
string m_FontName = a_Stream.ReadAlignedString(a_Stream.ReadInt32());
}
if (sourceFile.version[0] >= 4)
{
int m_FallbackFonts = a_Stream.ReadInt32();
for (int i = 0; i < m_FallbackFonts; i++)
{
PPtr m_FallbackFont = sourceFile.ReadPPtr();
}
int m_FontRenderingMode = a_Stream.ReadInt32();
} }
} }
} }

View File

@ -11,14 +11,12 @@ namespace Unity_Studio
public byte[] m_Script; public byte[] m_Script;
public string m_PathName; public string m_PathName;
public int exportSize;
public string extension = ".txt";
public TextAsset(AssetPreloadData preloadData, bool readSwitch) public TextAsset(AssetPreloadData preloadData, bool readSwitch)
{ {
var sourceFile = preloadData.sourceFile; var sourceFile = preloadData.sourceFile;
var a_Stream = preloadData.sourceFile.a_Stream; var a_Stream = preloadData.sourceFile.a_Stream;
a_Stream.Position = preloadData.Offset; a_Stream.Position = preloadData.Offset;
preloadData.extension = ".txt";
if (sourceFile.platform == -2) if (sourceFile.platform == -2)
{ {
@ -37,7 +35,7 @@ namespace Unity_Studio
a_Stream.Read(m_Script, 0, m_Script_size); a_Stream.Read(m_Script, 0, m_Script_size);
if (m_Script[0] == 93) { m_Script = SevenZip.Compression.LZMA.SevenZipHelper.Decompress(m_Script); } if (m_Script[0] == 93) { m_Script = SevenZip.Compression.LZMA.SevenZipHelper.Decompress(m_Script); }
if (m_Script[0] == 60 || (m_Script[0] == 239 && m_Script[1] == 187 && m_Script[2] == 191 && m_Script[3] == 60)) { extension = ".xml"; } if (m_Script[0] == 60 || (m_Script[0] == 239 && m_Script[1] == 187 && m_Script[2] == 191 && m_Script[3] == 60)) { preloadData.extension = ".xml"; }
} }
else else
{ {
@ -45,12 +43,16 @@ namespace Unity_Studio
if (lzmaTest == 93) if (lzmaTest == 93)
{ {
a_Stream.Position += 4; a_Stream.Position += 4;
exportSize = a_Stream.ReadInt32(); //actualy int64 preloadData.exportSize = a_Stream.ReadInt32(); //actualy int64
a_Stream.Position -= 8; a_Stream.Position -= 8;
} }
else { exportSize = m_Script_size; } else { preloadData.exportSize = m_Script_size; }
a_Stream.Position += m_Script_size - 1; a_Stream.Position += m_Script_size - 1;
if (m_Name != "") { preloadData.Text = m_Name; }
else { preloadData.Text = preloadData.TypeString + " #" + preloadData.uniqueID; }
preloadData.SubItems.AddRange(new string[] { preloadData.TypeString, preloadData.exportSize.ToString() });
} }
a_Stream.AlignStream(4); a_Stream.AlignStream(4);

View File

@ -26,6 +26,7 @@ namespace Unity_Studio
public int m_ColorSpace; public int m_ColorSpace;
public byte[] image_data; public byte[] image_data;
public int dwFlags = 0x1 + 0x2 + 0x4 + 0x1000; public int dwFlags = 0x1 + 0x2 + 0x4 + 0x1000;
//public int dwHeight; //public int dwHeight;
//public int dwWidth; //public int dwWidth;
@ -56,7 +57,6 @@ namespace Unity_Studio
public int pvrMetaDataSize = 0x0; public int pvrMetaDataSize = 0x0;
public int image_data_size; public int image_data_size;
string extension;
public Texture2D(AssetPreloadData preloadData, bool readSwitch) public Texture2D(AssetPreloadData preloadData, bool readSwitch)
{ {
@ -77,10 +77,6 @@ namespace Unity_Studio
m_CompleteImageSize = a_Stream.ReadInt32(); m_CompleteImageSize = a_Stream.ReadInt32();
m_TextureFormat = a_Stream.ReadInt32(); m_TextureFormat = a_Stream.ReadInt32();
if (m_TextureFormat < 30) { extension = ".dds"; }
else if (m_TextureFormat < 35) { extension = ".pvr"; }
else { extension = "_" + m_Width.ToString() + "x" + m_Height.ToString() + "." + m_TextureFormat.ToString() + ".tex"; }
if (sourceFile.version[0] < 5 || (sourceFile.version[0] == 5 && sourceFile.version[1] < 2)) if (sourceFile.version[0] < 5 || (sourceFile.version[0] == 5 && sourceFile.version[1] < 2))
{ m_MipMap = a_Stream.ReadBoolean(); } { m_MipMap = a_Stream.ReadBoolean(); }
else else
@ -235,7 +231,7 @@ namespace Unity_Studio
image_data[i * 2 + 1] = b0; image_data[i * 2 + 1] = b0;
} }
} }
dwFlags2 = 0x40; dwFlags2 = 0x40;
dwRGBBitCount = 0x10; dwRGBBitCount = 0x10;
dwRBitMask = 0xF800; dwRBitMask = 0xF800;
@ -305,6 +301,9 @@ namespace Unity_Studio
dwABitMask = 0xF000; dwABitMask = 0xF000;
break; break;
} }
case 28: //DXT1 Crunched
case 29: //DXT1 Crunched
break;
case 30: //PVRTC_RGB2 case 30: //PVRTC_RGB2
{ {
pvrPixelFormat = 0x0; pvrPixelFormat = 0x0;
@ -332,6 +331,52 @@ namespace Unity_Studio
} }
} }
} }
else
{
preloadData.InfoText = "Width: " + m_Width.ToString() + "\nHeight: " + m_Height.ToString() + "\nFormat: ";
preloadData.exportSize = image_data_size;
switch (m_TextureFormat)
{
case 1: preloadData.InfoText += "Alpha8"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 2: preloadData.InfoText += "ARGB 4.4.4.4"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 3: preloadData.InfoText += "BGR 8.8.8"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 4: preloadData.InfoText += "GRAB 8.8.8.8"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 5: preloadData.InfoText += "BGRA 8.8.8.8"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 7: preloadData.InfoText += "RGB 5.6.5"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 10: preloadData.InfoText += "DXT1"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 12: preloadData.InfoText += "DXT5"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 13: preloadData.InfoText += "RGBA 4.4.4.4"; preloadData.extension = ".dds"; preloadData.exportSize += 128; break;
case 28: preloadData.InfoText += "DXT1 Crunched"; preloadData.extension = ".crn"; break;
case 29: preloadData.InfoText += "DXT5 Crunched"; preloadData.extension = ".crn"; break;
case 30: preloadData.InfoText += "PVRTC_RGB2"; preloadData.extension = ".pvr"; preloadData.exportSize += 52; break;
case 31: preloadData.InfoText += "PVRTC_RGBA2"; preloadData.extension = ".pvr"; preloadData.exportSize += 52; break;
case 32: preloadData.InfoText += "PVRTC_RGB4"; preloadData.extension = ".pvr"; preloadData.exportSize += 52; break;
case 33: preloadData.InfoText += "PVRTC_RGBA4"; preloadData.extension = ".pvr"; preloadData.exportSize += 52; break;
case 34: preloadData.InfoText += "ETC_RGB4"; preloadData.extension = ".pvr"; preloadData.exportSize += 52; break;
default: preloadData.InfoText += "unknown"; preloadData.extension = ".tex"; break;
}
switch (m_FilterMode)
{
case 0: preloadData.InfoText += "\nFilter Mode: Point "; break;
case 1: preloadData.InfoText += "\nFilter Mode: Bilinear "; break;
case 2: preloadData.InfoText += "\nFilter Mode: Trilinear "; break;
}
preloadData.InfoText += "\nAnisotropic level: " + m_Aniso.ToString() + "\nMip map bias: " + m_MipBias.ToString();
switch (m_WrapMode)
{
case 0: preloadData.InfoText += "\nWrap mode: Repeat"; break;
case 1: preloadData.InfoText += "\nWrap mode: Clamp"; break;
}
if (m_Name != "") { preloadData.Text = m_Name; }
else { preloadData.Text = preloadData.TypeString + " #" + preloadData.uniqueID; }
preloadData.SubItems.AddRange(new string[] { preloadData.TypeString, preloadData.exportSize.ToString() });
}
} }
} }
} }

View File

@ -15,7 +15,6 @@ using System.Web.Script.Serialization;
/*TODO /*TODO
Load parent nodes even if they are not selected to provide transformations?
For extracting bundles, first check if file exists then decompress For extracting bundles, first check if file exists then decompress
Double-check channelgroup argument in new FMOD Studio API system.playSound method Double-check channelgroup argument in new FMOD Studio API system.playSound method
Font index error in Dreamfall Chapters Font index error in Dreamfall Chapters
@ -67,6 +66,7 @@ namespace Unity_Studio
[DllImport("gdi32.dll")] [DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts); private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);
System.Drawing.Text.PrivateFontCollection pfc = new System.Drawing.Text.PrivateFontCollection();
//[DllImport("PVRTexLib.dll")] //[DllImport("PVRTexLib.dll")]
//private static extern void test(); //private static extern void test();
@ -620,10 +620,6 @@ namespace Unity_Studio
{ {
StatusStripUpdate("Building asset list from " + Path.GetFileName(assetsFile.filePath)); StatusStripUpdate("Building asset list from " + Path.GetFileName(assetsFile.filePath));
var a_Stream = assetsFile.a_Stream;
var fileGen = assetsFile.fileGen;
//var m_version = assetsFile.m_version;
var version = assetsFile.version;
string fileID = assetsfileList.IndexOf(assetsFile).ToString(fileIDfmt); string fileID = assetsfileList.IndexOf(assetsFile).ToString(fileIDfmt);
//ListViewGroup assetGroup = new ListViewGroup(Path.GetFileName(assetsFile.filePath)); //ListViewGroup assetGroup = new ListViewGroup(Path.GetFileName(assetsFile.filePath));
@ -632,7 +628,6 @@ namespace Unity_Studio
foreach (var asset in assetsFile.preloadTable.Values) foreach (var asset in assetsFile.preloadTable.Values)
{ {
asset.uniqueID = fileID + asset.uniqueID; asset.uniqueID = fileID + asset.uniqueID;
a_Stream.Position = asset.Offset;
switch (asset.Type2) switch (asset.Type2)
{ {
@ -659,75 +654,26 @@ namespace Unity_Studio
case 28: //Texture2D case 28: //Texture2D
{ {
Texture2D m_Texture2D = new Texture2D(asset, false); Texture2D m_Texture2D = new Texture2D(asset, false);
asset.Text = m_Texture2D.m_Name;
asset.exportSize = 128 + m_Texture2D.image_data_size;
#region Get Info Text
asset.InfoText = "Width: " + m_Texture2D.m_Width.ToString() + "\nHeight: " + m_Texture2D.m_Height.ToString() + "\nFormat: ";
switch (m_Texture2D.m_TextureFormat)
{
case 1: asset.InfoText += "Alpha8"; break;
case 2: asset.InfoText += "ARGB 4.4.4.4"; break;
case 3: asset.InfoText += "BGR 8.8.8"; break;
case 4: asset.InfoText += "GRAB 8.8.8.8"; break;
case 5: asset.InfoText += "BGRA 8.8.8.8"; break;
case 7: asset.InfoText += "RGB 5.6.5"; break;
case 10: asset.InfoText += "RGB DXT1"; break;
case 12: asset.InfoText += "ARGB DXT5"; break;
case 13: asset.InfoText += "RGBA 4.4.4.4"; break;
case 30: asset.InfoText += "PVRTC_RGB2"; asset.exportSize -= 76; break;
case 31: asset.InfoText += "PVRTC_RGBA2"; asset.exportSize -= 76; break;
case 32: asset.InfoText += "PVRTC_RGB4"; asset.exportSize = 52; break;
case 33: asset.InfoText += "PVRTC_RGBA4"; asset.exportSize -= 76; break;
case 34: asset.InfoText += "ETC_RGB4"; asset.exportSize -= 76; break;
default: asset.InfoText += "unknown"; asset.exportSize -= 128; break;
}
switch (m_Texture2D.m_FilterMode)
{
case 0: asset.InfoText += "\nFilter Mode: Point "; break;
case 1: asset.InfoText += "\nFilter Mode: Bilinear "; break;
case 2: asset.InfoText += "\nFilter Mode: Trilinear "; break;
}
asset.InfoText += "\nAnisotropic level: " + m_Texture2D.m_Aniso.ToString() + "\nMip map bias: " + m_Texture2D.m_MipBias.ToString();
switch (m_Texture2D.m_WrapMode)
{
case 0: asset.InfoText += "\nWrap mode: Repeat"; break;
case 1: asset.InfoText += "\nWrap mode: Clamp"; break;
}
#endregion
assetsFile.exportableAssets.Add(asset); assetsFile.exportableAssets.Add(asset);
break; break;
} }
case 48: //Shader
case 49: //TextAsset case 49: //TextAsset
{ {
TextAsset m_TextAsset = new TextAsset(asset, false); TextAsset m_TextAsset = new TextAsset(asset, false);
asset.Text = m_TextAsset.m_Name;
asset.exportSize = m_TextAsset.exportSize;
assetsFile.exportableAssets.Add(asset); assetsFile.exportableAssets.Add(asset);
break; break;
} }
case 83: //AudioClip case 83: //AudioClip
{ {
AudioClip m_AudioClip = new AudioClip(asset, false); AudioClip m_AudioClip = new AudioClip(asset, false);
asset.Text = m_AudioClip.m_Name;
asset.exportSize = (int)m_AudioClip.m_Size;
assetsFile.exportableAssets.Add(asset); assetsFile.exportableAssets.Add(asset);
break; break;
} }
case 48: //Shader //case 89: //CubeMap
case 89: //CubeMap
case 128: //Font case 128: //Font
{ {
asset.Text = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); unityFont m_Font = new unityFont(asset, false);
assetsFile.exportableAssets.Add(asset); assetsFile.exportableAssets.Add(asset);
break; break;
} }
@ -738,12 +684,11 @@ namespace Unity_Studio
base.Text = "Unity Studio - " + productName + " - " + assetsFile.m_Version + " - " + assetsFile.platformStr; base.Text = "Unity Studio - " + productName + " - " + assetsFile.m_Version + " - " + assetsFile.platformStr;
break; break;
} }
case 0:
break;
} }
if (asset.Text == "") { asset.Text = asset.TypeString + " #" + asset.uniqueID; }
asset.SubItems.AddRange(new string[] { asset.TypeString, asset.exportSize.ToString() });
progressBar1.PerformStep(); progressBar1.PerformStep();
} }
@ -859,7 +804,8 @@ namespace Unity_Studio
progressBar1.Value = 0; progressBar1.Value = 0;
treeSearch.Select(); treeSearch.Select();
TexEnv dsd = new TexEnv();
saveFolderDialog1.InitialDirectory = mainPath;
} }
private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
@ -1094,6 +1040,7 @@ namespace Unity_Studio
assetInfoLabel.Text = null; assetInfoLabel.Text = null;
textPreviewBox.Visible = false; textPreviewBox.Visible = false;
fontPreviewBox.Visible = false; fontPreviewBox.Visible = false;
pfc.Dispose();
FMODpanel.Visible = false; FMODpanel.Visible = false;
lastLoadedAsset = null; lastLoadedAsset = null;
StatusStripUpdate(""); StatusStripUpdate("");
@ -1229,48 +1176,51 @@ namespace Unity_Studio
#region Font #region Font
case 128: //Font case 128: //Font
{ {
unityFont m_Font = new unityFont(asset); unityFont m_Font = new unityFont(asset, true);
if (m_Font.extension != ".otf" && m_Font.m_FontData != null) if (asset.extension != ".otf" && m_Font.m_FontData != null)
{ {
IntPtr data = Marshal.AllocCoTaskMem(m_Font.m_FontData.Length); IntPtr data = Marshal.AllocCoTaskMem(m_Font.m_FontData.Length);
Marshal.Copy(m_Font.m_FontData, 0, data, m_Font.m_FontData.Length); Marshal.Copy(m_Font.m_FontData, 0, data, m_Font.m_FontData.Length);
System.Drawing.Text.PrivateFontCollection pfc = new System.Drawing.Text.PrivateFontCollection();
// We HAVE to do this to register the font to the system (Weird .NET bug !) // We HAVE to do this to register the font to the system (Weird .NET bug !)
uint cFonts = 0; uint cFonts = 0;
AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts); AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts);
pfc = new System.Drawing.Text.PrivateFontCollection();
pfc.AddMemoryFont(data, m_Font.m_FontData.Length); pfc.AddMemoryFont(data, m_Font.m_FontData.Length);
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(data); Marshal.FreeCoTaskMem(data);
//textPreviewBox.Font = new Font(pfc.Families[0], 16, FontStyle.Regular); if (pfc.Families.Length > 0)
//textPreviewBox.Text = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ\r\n1234567890.:,;'\"(!?)+-*/=\r\nThe quick brown fox jumps over the lazy dog. 1234567890"; {
fontPreviewBox.SelectionStart = 0; //textPreviewBox.Font = new Font(pfc.Families[0], 16, FontStyle.Regular);
fontPreviewBox.SelectionLength = 80; //textPreviewBox.Text = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ\r\n1234567890.:,;'\"(!?)+-*/=\r\nThe quick brown fox jumps over the lazy dog. 1234567890";
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 16, FontStyle.Regular); fontPreviewBox.SelectionStart = 0;
fontPreviewBox.SelectionStart = 81; fontPreviewBox.SelectionLength = 80;
fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 16, FontStyle.Regular);
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 12, FontStyle.Regular); fontPreviewBox.SelectionStart = 81;
fontPreviewBox.SelectionStart = 138; fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 12, FontStyle.Regular);
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 18, FontStyle.Regular); fontPreviewBox.SelectionStart = 138;
fontPreviewBox.SelectionStart = 195; fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 18, FontStyle.Regular);
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 24, FontStyle.Regular); fontPreviewBox.SelectionStart = 195;
fontPreviewBox.SelectionStart = 252; fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 24, FontStyle.Regular);
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 36, FontStyle.Regular); fontPreviewBox.SelectionStart = 252;
fontPreviewBox.SelectionStart = 309; fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 36, FontStyle.Regular);
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 48, FontStyle.Regular); fontPreviewBox.SelectionStart = 309;
fontPreviewBox.SelectionStart = 366; fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionLength = 56; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 48, FontStyle.Regular);
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 60, FontStyle.Regular); fontPreviewBox.SelectionStart = 366;
fontPreviewBox.SelectionStart = 423; fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionLength = 55; fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 60, FontStyle.Regular);
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 72, FontStyle.Regular); fontPreviewBox.SelectionStart = 423;
fontPreviewBox.Visible = true; fontPreviewBox.SelectionLength = 55;
fontPreviewBox.SelectionFont = new Font(pfc.Families[0], 72, FontStyle.Regular);
fontPreviewBox.Visible = true;
}
} }
else { StatusStripUpdate("Unsupported font for preview. Try to export."); } else { StatusStripUpdate("Unsupported font for preview. Try to export."); }
@ -2158,7 +2108,9 @@ namespace Unity_Studio
if (assetsfileList.TryGetGameObject(m_SkinnedMeshRenderer.m_GameObject, out m_GameObject) && assetsfileList.TryGetPD(m_SkinnedMeshRenderer.m_Mesh, out MeshPD)) if (assetsfileList.TryGetGameObject(m_SkinnedMeshRenderer.m_GameObject, out m_GameObject) && assetsfileList.TryGetPD(m_SkinnedMeshRenderer.m_Mesh, out MeshPD))
{ {
//generate unique Geometry ID for instanced mesh objects //generate unique Geometry ID for instanced mesh objects
//I should find a way to preserve instances at least when exportDeformers is not selected //instanced skinned geometry is possible in FBX, but all instances are linked to the same skeleton nodes
//TODO: create instances if deformer option is not selected
//find a way to test if a mesh instance was loaded previously and if it uses the same skeleton, then create instance or copy
var keepID = MeshPD.uniqueID; var keepID = MeshPD.uniqueID;
MeshPD.uniqueID = SkinnedMeshPD.uniqueID; MeshPD.uniqueID = SkinnedMeshPD.uniqueID;
Mesh m_Mesh = new Mesh(MeshPD); Mesh m_Mesh = new Mesh(MeshPD);
@ -2331,55 +2283,21 @@ namespace Unity_Studio
foreach (var TexturePD in Textures) foreach (var TexturePD in Textures)
{ {
Texture2D m_Texture2D = new Texture2D(TexturePD, true); Texture2D m_Texture2D = new Texture2D(TexturePD, true);
#region extract texture
string texPath = Path.GetDirectoryName(FBXfile) + "\\Texture2D\\" + TexturePD.Text;
//TODO check texture type and set path accordingly; eg. CubeMap, Texture3D
if (uniqueNames.Checked) { texPath += " #" + TexturePD.uniqueID; }
if (m_Texture2D.m_TextureFormat < 30) { texPath += ".dds"; }
else if (m_Texture2D.m_TextureFormat < 35) { texPath += ".pvr"; }
else { texPath += "_" + m_Texture2D.m_Width.ToString() + "x" + m_Texture2D.m_Height.ToString() + "." + m_Texture2D.m_TextureFormat.ToString() + ".tex"; }
if (File.Exists(texPath)) //TODO check texture type and set path accordingly; eg. CubeMap, Texture3D
string texFilename = Path.GetDirectoryName(FBXfile) + "\\Texture2D\\" + TexturePD.Text;
if (uniqueNames.Checked) { texFilename += " #" + TexturePD.uniqueID; }
texFilename += TexturePD.extension;
if (File.Exists(texFilename))
{ {
StatusStripUpdate("Texture file " + Path.GetFileName(texPath) + " already exists"); StatusStripUpdate("Texture file " + Path.GetFileName(texFilename) + " already exists");
} }
else else
{ {
StatusStripUpdate("Exporting Texture2D: " + Path.GetFileName(texPath)); StatusStripUpdate("Exporting Texture2D: " + Path.GetFileName(texFilename));
ExportTexture(m_Texture2D, texFilename);
switch (m_Texture2D.m_TextureFormat)
{
case 1: //Alpha8
case 2: //A4R4G4B4
case 3: //B8G8R8 //confirmed on X360, iOS //PS3 unsure
case 4: //G8R8A8B8 //confirmed on X360, iOS
case 5: //B8G8R8A8 //confirmed on X360, PS3, Web, iOS
case 7: //R5G6B5 //confirmed switched on X360; confirmed on iOS
case 10: //DXT1
case 12: //DXT5
case 13: //R4G4B4A4, iOS (only?)
WriteDDS(texPath, m_Texture2D);
break;
case 30: //PVRTC_RGB2
case 31: //PVRTC_RGBA2
case 32: //PVRTC_RGB4
case 33: //PVRTC_RGBA4
case 34: //ETC_RGB4
WritePVR(texPath, m_Texture2D);
break;
default:
{
using (BinaryWriter writer = new BinaryWriter(File.Open(texPath, FileMode.Create)))
{
writer.Write(m_Texture2D.image_data);
writer.Close();
}
break;
}
}
} }
#endregion
ob.AppendFormat("\n\tTexture: 7{0}, \"Texture::{1}\", \"\" {{", TexturePD.uniqueID, TexturePD.Text); ob.AppendFormat("\n\tTexture: 7{0}, \"Texture::{1}\", \"\" {{", TexturePD.uniqueID, TexturePD.Text);
ob.Append("\n\t\tType: \"TextureVideoClip\""); ob.Append("\n\t\tType: \"TextureVideoClip\"");
@ -2390,17 +2308,17 @@ namespace Unity_Studio
ob.Append("\n\t\t\tP: \"UseMaterial\", \"bool\", \"\", \"\",1"); ob.Append("\n\t\t\tP: \"UseMaterial\", \"bool\", \"\", \"\",1");
ob.Append("\n\t\t}"); ob.Append("\n\t\t}");
ob.AppendFormat("\n\t\tMedia: \"Video::{0}\"", TexturePD.Text); ob.AppendFormat("\n\t\tMedia: \"Video::{0}\"", TexturePD.Text);
ob.AppendFormat("\n\t\tFileName: \"{0}\"", texPath); ob.AppendFormat("\n\t\tFileName: \"{0}\"", texFilename);
ob.AppendFormat("\n\t\tRelativeFilename: \"Texture2D\\{0}\"", Path.GetFileName(texPath)); ob.AppendFormat("\n\t\tRelativeFilename: \"Texture2D\\{0}\"", Path.GetFileName(texFilename));
ob.Append("\n\t}"); ob.Append("\n\t}");
ob.AppendFormat("\n\tVideo: 8{0}, \"Video::{1}\", \"Clip\" {{", TexturePD.uniqueID, TexturePD.Text); ob.AppendFormat("\n\tVideo: 8{0}, \"Video::{1}\", \"Clip\" {{", TexturePD.uniqueID, TexturePD.Text);
ob.Append("\n\t\tType: \"Clip\""); ob.Append("\n\t\tType: \"Clip\"");
ob.Append("\n\t\tProperties70: {"); ob.Append("\n\t\tProperties70: {");
ob.AppendFormat("\n\t\t\tP: \"Path\", \"KString\", \"XRefUrl\", \"\", \"{0}\"", texPath); ob.AppendFormat("\n\t\t\tP: \"Path\", \"KString\", \"XRefUrl\", \"\", \"{0}\"", texFilename);
ob.Append("\n\t\t}"); ob.Append("\n\t\t}");
ob.AppendFormat("\n\t\tFileName: \"{0}\"", texPath); ob.AppendFormat("\n\t\tFileName: \"{0}\"", texFilename);
ob.AppendFormat("\n\t\tRelativeFilename: \"Texture2D\\{0}\"", Path.GetFileName(texPath)); ob.AppendFormat("\n\t\tRelativeFilename: \"Texture2D\\{0}\"", Path.GetFileName(texFilename));
ob.Append("\n\t}"); ob.Append("\n\t}");
//connect video to texture //connect video to texture
@ -2853,35 +2771,86 @@ namespace Unity_Studio
private void ExportAssets_Click(object sender, EventArgs e) private void ExportAssets_Click(object sender, EventArgs e)
{ {
if (exportableAssets.Count > 0) if (exportableAssets.Count > 0 && saveFolderDialog1.ShowDialog() == DialogResult.OK)
{ {
saveFolderDialog1.InitialDirectory = mainPath; var savePath = saveFolderDialog1.FileName;
if (saveFolderDialog1.ShowDialog() == DialogResult.OK) if (Path.GetFileName(savePath) == "Select folder or write folder name to create")
{ savePath = Path.GetDirectoryName(saveFolderDialog1.FileName); }
bool exportAll = ((ToolStripItem)sender).Name == "exportAllAssetsMenuItem";
bool exportFiltered = ((ToolStripItem)sender).Name == "exportFilteredAssetsMenuItem";
bool exportSelected = ((ToolStripItem)sender).Name == "exportSelectedAssetsMenuItem";
int toExport = 0;
int exportedCount = 0;
//looping assetsFiles will optimize HDD access
//but will also have a small performance impact when exporting only a couple of selected assets
foreach (var assetsFile in assetsfileList)
{ {
var savePath = saveFolderDialog1.FileName; string exportpath = savePath + "\\";
if (Path.GetFileName(savePath) == "Select folder or write folder name to create") if (assetGroupOptions.SelectedIndex == 1) { exportpath += Path.GetFileNameWithoutExtension(assetsFile.filePath) + "_export\\"; }
{ savePath = Path.GetDirectoryName(saveFolderDialog1.FileName); }
//Directory.CreateDirectory(saveFolderDialog1.FileName);//this will be created later, when grouping is determined
switch (((ToolStripItem)sender).Name) foreach (var asset in assetsFile.exportableAssets)
{ {
case "exportAllAssetsMenuItem": if (exportAll ||
ExportAll(savePath, assetGroupOptions.SelectedIndex); visibleAssets.Exists(x => x.uniqueID == asset.uniqueID) && (exportFiltered ||
break; exportSelected && asset.Index >= 0 && assetListView.SelectedIndices.Contains(asset.Index)))
case "exportFilteredAssetsMenuItem": {
ExportFiltered(visibleAssets, savePath, assetGroupOptions.SelectedIndex); toExport++;
break; if (assetGroupOptions.SelectedIndex == 0) { exportpath = savePath + "\\" + asset.TypeString + "\\"; }
case "exportSelectedAssetsMenuItem":
List<AssetPreloadData> selectedAssetList = new List<AssetPreloadData>();
var selIndices = assetListView.SelectedIndices;
foreach (int index in selIndices) { selectedAssetList.Add((AssetPreloadData)assetListView.Items[index]); }
ExportFiltered(selectedAssetList, savePath, assetGroupOptions.SelectedIndex);
break;
}
if (openAfterExport.Checked) { System.Diagnostics.Process.Start(savePath); } //AudioClip and Texture2D extensions are set when the list is built
//so their overwrite tests can be done without loading them again
switch (asset.Type2)
{
case 28:
if (!ExportFileExists(exportpath + asset.Text + asset.extension, asset.TypeString))
{ ExportTexture(new Texture2D(asset, true), exportpath + asset.Text + asset.extension); exportedCount++; }
break;
case 83:
if (!ExportFileExists(exportpath + asset.Text + asset.extension, asset.TypeString))
{ ExportAudioClip(new AudioClip(asset, true), exportpath + asset.Text + asset.extension); exportedCount++; }
break;
case 48:
if (!ExportFileExists(exportpath + asset.Text + ".txt", asset.TypeString))
{ ExportText(new TextAsset(asset, true), exportpath + asset.Text + ".txt"); exportedCount++; }
break;
case 49:
TextAsset m_TextAsset = new TextAsset(asset, true);
if (!ExportFileExists(exportpath + asset.Text + asset.extension, asset.TypeString))
{ ExportText(m_TextAsset, exportpath + asset.Text + asset.extension); exportedCount++; }
break;
case 128:
unityFont m_Font = new unityFont(asset, true);
if (!ExportFileExists(exportpath + asset.Text + asset.extension, asset.TypeString))
{ ExportFont(m_Font, exportpath + asset.Text + asset.extension); exportedCount++; }
break;
}
}
}
} }
string statusText = "";
switch (exportedCount)
{
case 0:
statusText = "Nothing exported.";
break;
case 1:
statusText = toolStripStatusLabel1.Text + " finished.";
break;
default:
statusText = "Finished exporting " + exportedCount.ToString() + " assets.";
break;
}
if (toExport > exportedCount) { statusText += " " + (toExport - exportedCount).ToString() + " assets skipped (not extractable or files already exist)"; }
StatusStripUpdate(statusText);
if (openAfterExport.Checked && exportedCount > 0) { System.Diagnostics.Process.Start(savePath); }
} }
else else
{ {
@ -2889,311 +2858,133 @@ namespace Unity_Studio
} }
} }
private void ExportAll(string selectedPath, int groupFiles) private void ExportTexture (Texture2D m_Texture2D, string exportFilename)
{ {
int exportedCount = 0; switch (m_Texture2D.m_TextureFormat)
foreach (var assetsFile in assetsfileList)
{ {
if (assetsFile.exportableAssets.Count > 0) #region DDS
{ case 1: //Alpha8
string exportpath = selectedPath; case 2: //A4R4G4B4
if (groupFiles == 1) { exportpath += "\\" + Path.GetFileNameWithoutExtension(assetsFile.filePath) + "_export"; } case 3: //B8G8R8 //confirmed on X360, iOS //PS3 unsure
Directory.CreateDirectory(exportpath); case 4: //G8R8A8B8 //confirmed on X360, iOS
case 5: //B8G8R8A8 //confirmed on X360, PS3, Web, iOS
foreach (var asset in assetsFile.exportableAssets) case 7: //R5G6B5 //confirmed switched on X360; confirmed on iOS
case 10: //DXT1
case 12: //DXT5
case 13: //R4G4B4A4, iOS (only?)
using (BinaryWriter writer = new BinaryWriter(File.Open(exportFilename, FileMode.Create)))
{ {
if (groupFiles == 0) writer.Write(0x20534444);
{ writer.Write(0x7C);
switch (asset.Type2) writer.Write(m_Texture2D.dwFlags);
{ writer.Write(m_Texture2D.m_Height);
case 28: writer.Write(m_Texture2D.m_Width);
exportpath = selectedPath + "\\Texture2D"; writer.Write(m_Texture2D.dwPitchOrLinearSize); //should be main tex size without mips);
break; writer.Write((int)0); //dwDepth not implemented
case 83: writer.Write(m_Texture2D.dwMipMapCount);
exportpath = selectedPath + "\\AudioClip"; writer.Write(new byte[44]); //dwReserved1[11]
break; writer.Write(m_Texture2D.dwSize);
case 48: writer.Write(m_Texture2D.dwFlags2);
exportpath = selectedPath + "\\Shader"; writer.Write(m_Texture2D.dwFourCC);
break; writer.Write(m_Texture2D.dwRGBBitCount);
case 49: writer.Write(m_Texture2D.dwRBitMask);
exportpath = selectedPath + "\\TextAsset"; writer.Write(m_Texture2D.dwGBitMask);
break; writer.Write(m_Texture2D.dwBBitMask);
case 128: writer.Write(m_Texture2D.dwABitMask);
exportpath = selectedPath + "\\Font"; writer.Write(m_Texture2D.dwCaps);
break; writer.Write(m_Texture2D.dwCaps2);
} writer.Write(new byte[12]); //dwCaps3&4 & dwReserved2
Directory.CreateDirectory(exportpath);
} writer.Write(m_Texture2D.image_data);
exportedCount += ExportAsset(asset, exportpath); writer.Close();
} }
} break;
#endregion
#region PVR
case 30: //PVRTC_RGB2
case 31: //PVRTC_RGBA2
case 32: //PVRTC_RGB4
case 33: //PVRTC_RGBA4
case 34: //ETC_RGB4
using (BinaryWriter writer = new BinaryWriter(File.Open(exportFilename, FileMode.Create)))
{
writer.Write(m_Texture2D.pvrVersion);
writer.Write(m_Texture2D.pvrFlags);
writer.Write(m_Texture2D.pvrPixelFormat);
writer.Write(m_Texture2D.pvrColourSpace);
writer.Write(m_Texture2D.pvrChannelType);
writer.Write(m_Texture2D.m_Height);
writer.Write(m_Texture2D.m_Width);
writer.Write(m_Texture2D.pvrDepth);
writer.Write(m_Texture2D.pvrNumSurfaces);
writer.Write(m_Texture2D.pvrNumFaces);
writer.Write(m_Texture2D.dwMipMapCount);
writer.Write(m_Texture2D.pvrMetaDataSize);
writer.Write(m_Texture2D.image_data);
writer.Close();
}
break;
#endregion
case 28: //DXT1 Crunched
case 29: //DXT1 Crunched
default:
using (BinaryWriter writer = new BinaryWriter(File.Open(exportFilename, FileMode.Create)))
{
writer.Write(m_Texture2D.image_data);
writer.Close();
}
break;
}
}
private void ExportAudioClip(AudioClip m_AudioClip, string exportFilename)
{
using (BinaryWriter writer = new BinaryWriter(File.Open(exportFilename, FileMode.Create)))
{
writer.Write(m_AudioClip.m_AudioData);
writer.Close();
} }
string statusText = "Finished exporting " + exportedCount.ToString() + " assets.";
if ((exportableAssets.Count - exportedCount) > 0) { statusText += " " + (exportableAssets.Count - exportedCount).ToString() + " assets skipped (not extractable or files already exist)"; }
StatusStripUpdate(statusText);
} }
private void ExportFiltered(List<AssetPreloadData> filteredAssetList, string selectedPath, int groupFiles) private void ExportText(TextAsset m_TextAsset, string exportFilename)
{ {
if (filteredAssetList.Count > 0) using (BinaryWriter writer = new BinaryWriter(File.Open(exportFilename, FileMode.Create)))
{ {
int exportedCount = 0; writer.Write(m_TextAsset.m_Script);
writer.Close();
}
}
foreach (var asset in filteredAssetList) private void ExportFont(unityFont m_Font, string exportFilename)
{ {
string exportpath = selectedPath; using (BinaryWriter writer = new BinaryWriter(File.Open(exportFilename, FileMode.Create)))
if (groupFiles == 1) { exportpath += "\\" + Path.GetFileNameWithoutExtension(asset.sourceFile.filePath) + "_export"; } {
else if (groupFiles == 0) writer.Write(m_Font.m_FontData);
{ writer.Close();
switch (asset.Type2) }
{ }
case 28:
exportpath = selectedPath + "\\Texture2D";
break;
case 83:
exportpath = selectedPath + "\\AudioClip";
break;
case 48:
exportpath = selectedPath + "\\Shader";
break;
case 49:
exportpath = selectedPath + "\\TextAsset";
break;
case 128:
exportpath = selectedPath + "\\Font";
break;
}
}
Directory.CreateDirectory(exportpath); private bool ExportFileExists(string filename, string assetType)
exportedCount += ExportAsset(asset, exportpath); {
} if (File.Exists(filename))
{
string statusText = "Finished exporting " + exportedCount.ToString() + " assets."; StatusStripUpdate(assetType + " file " + Path.GetFileName(filename) + " already exists");
if ((filteredAssetList.Count - exportedCount) > 0) { statusText += " " + (filteredAssetList.Count - exportedCount).ToString() + " assets skipped (not extractable or files already exist)"; } return true;
StatusStripUpdate(statusText);
} }
else else
{ {
StatusStripUpdate("No exportable assets selected or filtered"); Directory.CreateDirectory(Path.GetDirectoryName(filename));
StatusStripUpdate("Exporting " + assetType + Path.GetFileName(filename));
return false;
} }
} }
private int ExportAsset(AssetPreloadData asset, string exportPath) public void StatusStripUpdate(string statusText)
{ {
int exportCount = 0; toolStripStatusLabel1.Text = statusText;
statusStrip1.Update();
switch (asset.Type2)
{
#region Texture2D
case 28: //Texture2D
{
Texture2D m_Texture2D = new Texture2D(asset, true);
string texPath = exportPath + "\\" + asset.Text;
if (uniqueNames.Checked) { texPath += " #" + asset.uniqueID; }
if (m_Texture2D.m_TextureFormat < 30) { texPath += ".dds"; }
else if (m_Texture2D.m_TextureFormat < 35) { texPath += ".pvr"; }
else { texPath += "_" + m_Texture2D.m_Width.ToString() + "x" + m_Texture2D.m_Height.ToString() + "." + m_Texture2D.m_TextureFormat.ToString() + ".tex"; }
if (File.Exists(texPath))
{
StatusStripUpdate("Texture file " + Path.GetFileName(texPath) + " already exists");
}
else
{
StatusStripUpdate("Exporting Texture2D: " + Path.GetFileName(texPath));
exportCount += 1;
switch (m_Texture2D.m_TextureFormat)
{
case 1: //Alpha8
case 2: //A4R4G4B4
case 3: //B8G8R8 //confirmed on X360, iOS //PS3 unsure
case 4: //G8R8A8B8 //confirmed on X360, iOS
case 5: //B8G8R8A8 //confirmed on X360, PS3, Web, iOS
case 7: //R5G6B5 //confirmed switched on X360; confirmed on iOS
case 10: //DXT1
case 12: //DXT5
case 13: //R4G4B4A4, iOS (only?)
WriteDDS(texPath, m_Texture2D);
break;
case 30: //PVRTC_RGB2
case 31: //PVRTC_RGBA2
case 32: //PVRTC_RGB4
case 33: //PVRTC_RGBA4
case 34: //ETC_RGB4
WritePVR(texPath, m_Texture2D);
break;
default:
{
using (BinaryWriter writer = new BinaryWriter(File.Open(texPath, FileMode.Create)))
{
writer.Write(m_Texture2D.image_data);
writer.Close();
}
break;
}
}
}
break;
}
#endregion
#region AudioClip
case 83: //AudioClip
{
AudioClip m_AudioClip = new AudioClip(asset, true);
string audPath = exportPath + "\\" + asset.Text;
if (uniqueNames.Checked) { audPath += " #" + asset.uniqueID; }
audPath += m_AudioClip.extension;
if (File.Exists(audPath))
{
StatusStripUpdate("Audio file " + Path.GetFileName(audPath) + " already exists");
}
else
{
StatusStripUpdate("Exporting AudioClip: " + Path.GetFileName(audPath));
exportCount += 1;
using (BinaryWriter writer = new BinaryWriter(File.Open(audPath, FileMode.Create)))
{
writer.Write(m_AudioClip.m_AudioData);
writer.Close();
}
}
break;
}
#endregion
#region Shader & TextAsset
case 48: //Shader
case 49: //TextAsset
{
TextAsset m_TextAsset = new TextAsset(asset, true);
string textAssetPath = exportPath + "\\" + asset.Text;
if (uniqueNames.Checked) { textAssetPath += " #" + asset.uniqueID; }
textAssetPath += m_TextAsset.extension;
if (File.Exists(textAssetPath))
{
StatusStripUpdate("TextAsset file " + Path.GetFileName(textAssetPath) + " already exists");
}
else
{
StatusStripUpdate("Exporting TextAsset: " + Path.GetFileName(textAssetPath));
exportCount += 1;
using (BinaryWriter writer = new BinaryWriter(File.Open(textAssetPath, FileMode.Create)))
{
writer.Write(m_TextAsset.m_Script);
writer.Close();
}
}
break;
}
#endregion
#region Font
case 128: //Font
{
unityFont m_Font = new unityFont(asset);
if (m_Font.m_FontData != null)
{
string fontPath = exportPath + "\\" + asset.Text;
if (uniqueNames.Checked) { fontPath += " #" + asset.uniqueID; }
fontPath += m_Font.extension;
if (File.Exists(fontPath))
{
StatusStripUpdate("Font file " + Path.GetFileName(fontPath) + " already exists");
}
else
{
StatusStripUpdate("Exporting Font: " + Path.GetFileName(fontPath));
using (BinaryWriter writer = new BinaryWriter(File.Open(fontPath, FileMode.Create)))
{
writer.Write(m_Font.m_FontData);
writer.Close();
}
exportCount += 1;
}
}
break;
}
#endregion
/*default:
{
string assetPath = exportPath + "\\" + asset.Name + "." + asset.TypeString;
byte[] assetData = new byte[asset.Size];
Stream.Read(assetData, 0, asset.Size);
using (BinaryWriter writer = new BinaryWriter(File.Open(assetPath, FileMode.Create)))
{
writer.Write(assetData);
writer.Close();
}
exportCount += 1;
break;
}*/
}
return exportCount;
}
private void WriteDDS(string DDSfile, Texture2D m_Texture2D)
{
using (BinaryWriter writer = new BinaryWriter(File.Open(DDSfile, FileMode.Create)))
{
writer.Write(0x20534444);
writer.Write(0x7C);
writer.Write(m_Texture2D.dwFlags);
writer.Write(m_Texture2D.m_Height);
writer.Write(m_Texture2D.m_Width);
writer.Write(m_Texture2D.dwPitchOrLinearSize); //should be main tex size without mips);
writer.Write((int)0); //dwDepth not implemented
writer.Write(m_Texture2D.dwMipMapCount);
writer.Write(new byte[44]); //dwReserved1[11]
writer.Write(m_Texture2D.dwSize);
writer.Write(m_Texture2D.dwFlags2);
writer.Write(m_Texture2D.dwFourCC);
writer.Write(m_Texture2D.dwRGBBitCount);
writer.Write(m_Texture2D.dwRBitMask);
writer.Write(m_Texture2D.dwGBitMask);
writer.Write(m_Texture2D.dwBBitMask);
writer.Write(m_Texture2D.dwABitMask);
writer.Write(m_Texture2D.dwCaps);
writer.Write(m_Texture2D.dwCaps2);
writer.Write(new byte[12]); //dwCaps3&4 & dwReserved2
writer.Write(m_Texture2D.image_data);
writer.Close();
}
}
private void WritePVR(string PVRfile, Texture2D m_Texture2D)
{
using (BinaryWriter writer = new BinaryWriter(File.Open(PVRfile, FileMode.Create)))
{
writer.Write(m_Texture2D.pvrVersion);
writer.Write(m_Texture2D.pvrFlags);
writer.Write(m_Texture2D.pvrPixelFormat);
writer.Write(m_Texture2D.pvrColourSpace);
writer.Write(m_Texture2D.pvrChannelType);
writer.Write(m_Texture2D.m_Height);
writer.Write(m_Texture2D.m_Width);
writer.Write(m_Texture2D.pvrDepth);
writer.Write(m_Texture2D.pvrNumSurfaces);
writer.Write(m_Texture2D.pvrNumFaces);
writer.Write(m_Texture2D.dwMipMapCount);
writer.Write(m_Texture2D.pvrMetaDataSize);
writer.Write(m_Texture2D.image_data);
writer.Close();
}
} }
@ -3259,11 +3050,5 @@ namespace Unity_Studio
foreach (var assetsFile in assetsfileList) { assetsFile.a_Stream.Dispose(); } //is this needed?*/ foreach (var assetsFile in assetsfileList) { assetsFile.a_Stream.Dispose(); } //is this needed?*/
} }
public void StatusStripUpdate(string statusText)
{
toolStripStatusLabel1.Text = statusText;
statusStrip1.Update();
}
} }
} }