diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj
index d1aa770..9781fef 100644
--- a/AssetStudio/AssetStudio.csproj
+++ b/AssetStudio/AssetStudio.csproj
@@ -65,6 +65,7 @@
+
diff --git a/AssetStudio/Classes/Avatar.cs b/AssetStudio/Classes/Avatar.cs
index 842b43e..97505ab 100644
--- a/AssetStudio/Classes/Avatar.cs
+++ b/AssetStudio/Classes/Avatar.cs
@@ -300,6 +300,8 @@ namespace AssetStudio
{
m_TOS[i] = new KeyValuePair(reader.ReadUInt32(), reader.ReadAlignedString());
}
+
+ //HumanDescription m_HumanDescription 2019 and up
}
public string FindBonePath(uint hash)
diff --git a/AssetStudio/Classes/Mesh.cs b/AssetStudio/Classes/Mesh.cs
index 9e8e0a6..7bf2dac 100644
--- a/AssetStudio/Classes/Mesh.cs
+++ b/AssetStudio/Classes/Mesh.cs
@@ -1,10 +1,23 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
namespace AssetStudio
{
+ public class MinMaxAABB
+ {
+ public Vector3 m_Min;
+ public Vector3 m_Max;
+
+ public MinMaxAABB(BinaryReader reader)
+ {
+ m_Min = reader.ReadVector3();
+ m_Max = reader.ReadVector3();
+ }
+ }
+
public class CompressedMesh
{
public PackedFloatVector m_Vertices;
@@ -490,8 +503,20 @@ namespace AssetStudio
var m_RootBoneNameHash = reader.ReadUInt32();
}
- if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and later
+ if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
{
+ if (version[0] >= 2019) //2019 and up
+ {
+ var m_BonesAABBSize = reader.ReadInt32();
+ var m_BonesAABB = new MinMaxAABB[m_BonesAABBSize];
+ for (int i = 0; i < m_BonesAABBSize; i++)
+ {
+ m_BonesAABB[i] = new MinMaxAABB(reader);
+ }
+
+ var m_VariableBoneCountWeights = reader.ReadUInt32Array();
+ }
+
var m_MeshCompression = reader.ReadByte();
if (version[0] >= 4)
{
@@ -719,7 +744,7 @@ namespace AssetStudio
int[] componentsIntArray = null;
float[] componentsFloatArray = null;
- if (m_Channel.format == 11)
+ if (m_Channel.format == 10 || m_Channel.format == 11)
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes);
else
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, componentByteSize);
@@ -1075,6 +1100,10 @@ namespace AssetStudio
return 1u;
case 3: //kChannelFormatByte
return 1u;
+ case 4: //kChannelFormatUInt32
+ return 4u;
+ case 10: //kChannelFormatInt32
+ return 4u;
case 11: //kChannelFormatInt32
return 4u;
default:
diff --git a/AssetStudio/Classes/Shader.cs b/AssetStudio/Classes/Shader.cs
index 5c658e6..8c98b3a 100644
--- a/AssetStudio/Classes/Shader.cs
+++ b/AssetStudio/Classes/Shader.cs
@@ -473,11 +473,22 @@ namespace AssetStudio
m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader);
- m_KeywordIndices = reader.ReadUInt16Array();
- if (version[0] >= 2017) //2017 and up
+ if (version[0] >= 2019) //2019 and up
{
+ var m_GlobalKeywordIndices = reader.ReadUInt16Array();
+ reader.AlignStream();
+ var m_LocalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
}
+ else
+ {
+ m_KeywordIndices = reader.ReadUInt16Array();
+ if (version[0] >= 2017) //2017 and up
+ {
+ reader.AlignStream();
+ }
+ }
+
m_ShaderHardwareTier = reader.ReadSByte();
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
reader.AlignStream();
diff --git a/AssetStudio/Classes/Sprite.cs b/AssetStudio/Classes/Sprite.cs
index 7500a52..8083908 100644
--- a/AssetStudio/Classes/Sprite.cs
+++ b/AssetStudio/Classes/Sprite.cs
@@ -1,9 +1,22 @@
using System;
using System.Collections.Generic;
using System.Drawing;
+using System.IO;
namespace AssetStudio
{
+ public class SecondarySpriteTexture
+ {
+ public PPtr texture;
+ public string name;
+
+ public SecondarySpriteTexture(ObjectReader reader)
+ {
+ texture = new PPtr(reader);
+ name = reader.ReadStringToNull();
+ }
+ }
+
public enum SpritePackingRotation
{
kSPRNone = 0,
@@ -27,7 +40,7 @@ namespace AssetStudio
public SpritePackingMode packingMode;
public SpritePackingRotation packingRotation;
- public SpriteSettings(ObjectReader reader)
+ public SpriteSettings(BinaryReader reader)
{
settingsRaw = reader.ReadUInt32();
@@ -61,6 +74,7 @@ namespace AssetStudio
{
public PPtr texture;
public PPtr alphaTexture;
+ public SecondarySpriteTexture[] secondaryTextures;
public SubMesh[] m_SubMeshes;
public byte[] m_IndexBuffer;
public VertexData m_VertexData;
@@ -85,6 +99,16 @@ namespace AssetStudio
alphaTexture = new PPtr(reader);
}
+ if (version[0] >= 2019) //2019 and up
+ {
+ var secondaryTexturesSize = reader.ReadInt32();
+ secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
+ for (int i = 0; i < secondaryTexturesSize; i++)
+ {
+ secondaryTextures[i] = new SecondarySpriteTexture(reader);
+ }
+ }
+
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{
var m_SubMeshesSize = reader.ReadInt32();
diff --git a/AssetStudio/CommonString.cs b/AssetStudio/CommonString.cs
index 0fc0d60..965c3da 100644
--- a/AssetStudio/CommonString.cs
+++ b/AssetStudio/CommonString.cs
@@ -4,7 +4,7 @@ namespace AssetStudio
{
public static class CommonString
{
- public static readonly Dictionary StringBuffer = new Dictionary
+ public static readonly Dictionary StringBuffer = new Dictionary
{
{0, "AABB"},
{5, "AnimationClip"},
@@ -110,7 +110,9 @@ namespace AssetStudio
{1057, "int2_storage"},
{1070, "int3_storage"},
{1083, "BoundsInt"},
- {1093, "m_CorrespondingSourceObject"}
+ {1093, "m_CorrespondingSourceObject"},
+ {1121, "m_PrefabInstance"},
+ {1138, "m_PrefabAsset"}
};
}
}
diff --git a/AssetStudio/SerializedFile.cs b/AssetStudio/SerializedFile.cs
index 53c8302..c1fa189 100644
--- a/AssetStudio/SerializedFile.cs
+++ b/AssetStudio/SerializedFile.cs
@@ -227,11 +227,11 @@ namespace AssetStudio
return type;
}
- private void ReadTypeTree(List typeTree, int depth = 0)
+ private void ReadTypeTree(List typeTree, int level = 0)
{
var typeTreeNode = new TypeTreeNode();
typeTree.Add(typeTreeNode);
- typeTreeNode.m_Level = depth;
+ typeTreeNode.m_Level = level;
typeTreeNode.m_Type = reader.ReadStringToNull();
typeTreeNode.m_Name = reader.ReadStringToNull();
typeTreeNode.m_ByteSize = reader.ReadInt32();
@@ -253,7 +253,7 @@ namespace AssetStudio
int childrenCount = reader.ReadInt32();
for (int i = 0; i < childrenCount; i++)
{
- ReadTypeTree(typeTree, depth + 1);
+ ReadTypeTree(typeTree, level + 1);
}
}
@@ -262,10 +262,15 @@ namespace AssetStudio
int numberOfNodes = reader.ReadInt32();
int stringBufferSize = reader.ReadInt32();
- reader.Position += numberOfNodes * 24;
+ var nodeSize = 24;
+ if (header.m_Version > 17)
+ {
+ nodeSize = 32;
+ }
+ reader.Position += numberOfNodes * nodeSize;
using (var stringBufferReader = new BinaryReader(new MemoryStream(reader.ReadBytes(stringBufferSize))))
{
- reader.Position -= numberOfNodes * 24 + stringBufferSize;
+ reader.Position -= numberOfNodes * nodeSize + stringBufferSize;
for (int i = 0; i < numberOfNodes; i++)
{
var typeTreeNode = new TypeTreeNode();
@@ -273,37 +278,38 @@ namespace AssetStudio
typeTreeNode.m_Version = reader.ReadUInt16();
typeTreeNode.m_Level = reader.ReadByte();
typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0;
-
- var m_TypeStrOffset = reader.ReadUInt16();
- var temp = reader.ReadUInt16();
- if (temp == 0)
- {
- stringBufferReader.BaseStream.Position = m_TypeStrOffset;
- typeTreeNode.m_Type = stringBufferReader.ReadStringToNull();
- }
- else
- {
- typeTreeNode.m_Type = CommonString.StringBuffer.ContainsKey(m_TypeStrOffset) ? CommonString.StringBuffer[m_TypeStrOffset] : m_TypeStrOffset.ToString();
- }
-
- var m_NameStrOffset = reader.ReadUInt16();
- temp = reader.ReadUInt16();
- if (temp == 0)
- {
- stringBufferReader.BaseStream.Position = m_NameStrOffset;
- typeTreeNode.m_Name = stringBufferReader.ReadStringToNull();
- }
- else
- {
- typeTreeNode.m_Name = CommonString.StringBuffer.ContainsKey(m_NameStrOffset) ? CommonString.StringBuffer[m_NameStrOffset] : m_NameStrOffset.ToString();
- }
-
+ typeTreeNode.m_TypeStrOffset = reader.ReadUInt32();
+ typeTreeNode.m_NameStrOffset = reader.ReadUInt32();
typeTreeNode.m_ByteSize = reader.ReadInt32();
typeTreeNode.m_Index = reader.ReadInt32();
typeTreeNode.m_MetaFlag = reader.ReadInt32();
+
+ if (header.m_Version > 17)
+ {
+ reader.Position += 8;
+ }
+
+ typeTreeNode.m_Type = ReadString(stringBufferReader, typeTreeNode.m_TypeStrOffset);
+ typeTreeNode.m_Name = ReadString(stringBufferReader, typeTreeNode.m_NameStrOffset);
}
reader.Position += stringBufferSize;
}
+
+ string ReadString(BinaryReader stringBufferReader, uint value)
+ {
+ var isOffset = (value & 0x80000000) == 0;
+ if (isOffset)
+ {
+ stringBufferReader.BaseStream.Position = value;
+ return stringBufferReader.ReadStringToNull();
+ }
+ var offset = value & 0x7FFFFFFF;
+ if (CommonString.StringBuffer.TryGetValue(offset, out var str))
+ {
+ return str;
+ }
+ return offset.ToString();
+ }
}
}
}
diff --git a/AssetStudio/TypeTreeHelper.cs b/AssetStudio/TypeTreeHelper.cs
index bbfedec..8e9cb82 100644
--- a/AssetStudio/TypeTreeHelper.cs
+++ b/AssetStudio/TypeTreeHelper.cs
@@ -153,10 +153,10 @@ namespace AssetStudio
reader.AlignStream();
}
- public static Dictionary ReadBoxingType(List members, BinaryReader reader)
+ public static UType ReadUType(List members, BinaryReader reader)
{
- var obj = new Dictionary();
- for (int i = 0; i < members.Count; i++)
+ var obj = new UType();
+ for (int i = 1; i < members.Count; i++)
{
var member = members[i];
var varNameStr = member.m_Name;
@@ -218,23 +218,6 @@ namespace AssetStudio
value = reader.ReadAlignedString();
i += 3;
break;
- case "vector":
- {
- if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
- align = true;
- var size = reader.ReadInt32();
- var list = new List