From d5d937247e80325b80c6867cde332fdd59cb0955 Mon Sep 17 00:00:00 2001 From: Perfare Date: Fri, 6 Apr 2018 23:57:36 +0800 Subject: [PATCH] Add animation related classes --- AssetStudio/AssetStudio-x86.csproj | 20 +- AssetStudio/AssetStudio.csproj | 20 +- AssetStudio/Classes/Animation.cs | 31 + AssetStudio/Classes/AnimationClip.cs | 763 ++++++++++++++++++ AssetStudio/Classes/Animator.cs | 27 + AssetStudio/Classes/AnimatorController.cs | 560 +++++++++++++ .../Classes/AnimatorOverrideController.cs | 33 + AssetStudio/Classes/AssetBundle.cs | 6 +- AssetStudio/Classes/AudioClip.cs | 6 +- AssetStudio/Classes/Avatar.cs | 251 ++++++ AssetStudio/Classes/BuildSettings.cs | 8 +- AssetStudio/Classes/Font.cs | 6 +- AssetStudio/Classes/GameObject.cs | 4 +- AssetStudio/Classes/Material.cs | 18 +- AssetStudio/Classes/Mesh.cs | 8 +- AssetStudio/Classes/MeshFilter.cs | 2 +- AssetStudio/Classes/MeshRenderer.cs | 2 +- AssetStudio/Classes/MonoBehaviour.cs | 4 +- AssetStudio/Classes/MovieTexture.cs | 4 +- AssetStudio/Classes/PlayerSettings.cs | 8 +- AssetStudio/Classes/Shader.cs | 6 +- AssetStudio/Classes/SkinnedMeshRenderer.cs | 2 +- AssetStudio/Classes/Sprite.cs | 6 +- AssetStudio/Classes/SpriteAtlas.cs | 6 +- AssetStudio/Classes/TextAsset.cs | 4 +- AssetStudio/Classes/Texture2D.cs | 6 +- AssetStudio/Classes/Transform.cs | 2 +- AssetStudio/Classes/VideoClip.cs | 10 +- AssetStudio/Library/SharpDX.Mathematics.dll | Bin 0 -> 220672 bytes AssetStudio/StudioClasses/AssetPreloadData.cs | 11 +- AssetStudio/StudioClasses/AssetsFile.cs | 115 +-- .../StudioClasses/BinaryReaderExtensions.cs | 128 +++ .../StudioClasses/BinaryWriterExtensions.cs | 24 + AssetStudio/StudioClasses/ClassStruct.cs | 4 +- .../StudioClasses/EndianBinaryReader.cs | 33 - AssetStudio/StudioClasses/Exporter.cs | 2 +- 36 files changed, 1974 insertions(+), 166 deletions(-) create mode 100644 AssetStudio/Classes/Animation.cs create mode 100644 AssetStudio/Classes/AnimationClip.cs create mode 100644 AssetStudio/Classes/Animator.cs create mode 100644 AssetStudio/Classes/AnimatorController.cs create mode 100644 AssetStudio/Classes/AnimatorOverrideController.cs create mode 100644 AssetStudio/Classes/Avatar.cs create mode 100644 AssetStudio/Library/SharpDX.Mathematics.dll create mode 100644 AssetStudio/StudioClasses/BinaryReaderExtensions.cs create mode 100644 AssetStudio/StudioClasses/BinaryWriterExtensions.cs diff --git a/AssetStudio/AssetStudio-x86.csproj b/AssetStudio/AssetStudio-x86.csproj index 356cc54..fa8e70a 100644 --- a/AssetStudio/AssetStudio-x86.csproj +++ b/AssetStudio/AssetStudio-x86.csproj @@ -58,24 +58,28 @@ False - library\BrotliSharpLib.dll + Library\BrotliSharpLib.dll False False - library\OpenTK.dll + Library\OpenTK.dll False False - library\OpenTK.GLControl.dll + Library\OpenTK.GLControl.dll + False + + + Library\SharpDX.Mathematics.dll False False - library\System.Half.dll + Library\System.Half.dll False @@ -142,6 +146,12 @@ AssetStudioForm.cs + + + + + + @@ -151,6 +161,8 @@ + + diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj index 052d503..6f1e6c6 100644 --- a/AssetStudio/AssetStudio.csproj +++ b/AssetStudio/AssetStudio.csproj @@ -58,24 +58,28 @@ False - library\BrotliSharpLib.dll + Library\BrotliSharpLib.dll False False - library\OpenTK.dll + Library\OpenTK.dll False False - library\OpenTK.GLControl.dll + Library\OpenTK.GLControl.dll + False + + + Library\SharpDX.Mathematics.dll False False - library\System.Half.dll + Library\System.Half.dll False @@ -136,7 +140,15 @@ Code + + + + + + + + diff --git a/AssetStudio/Classes/Animation.cs b/AssetStudio/Classes/Animation.cs new file mode 100644 index 0000000..5cf4160 --- /dev/null +++ b/AssetStudio/Classes/Animation.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace AssetStudio +{ + class Animation + { + public PPtr m_GameObject; + public List m_Animations; + + public Animation(AssetPreloadData preloadData) + { + var sourceFile = preloadData.sourceFile; + var reader = preloadData.InitReader(); + reader.Position = preloadData.Offset; + + m_GameObject = sourceFile.ReadPPtr(); + var m_Enabled = reader.ReadByte(); + reader.AlignStream(4); + var m_Animation = sourceFile.ReadPPtr(); + int numAnimations = reader.ReadInt32(); + m_Animations = new List(numAnimations); + for (int i = 0; i < numAnimations; i++) + { + m_Animations.Add(sourceFile.ReadPPtr()); + } + } + } +} diff --git a/AssetStudio/Classes/AnimationClip.cs b/AssetStudio/Classes/AnimationClip.cs new file mode 100644 index 0000000..2aacd8a --- /dev/null +++ b/AssetStudio/Classes/AnimationClip.cs @@ -0,0 +1,763 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using SharpDX; + +namespace AssetStudio +{ + public class Keyframe + { + public float time { get; set; } + public T value { get; set; } + public T inSlope { get; set; } + public T outSlope { get; set; } + + public Keyframe(EndianBinaryReader reader, Func readerFunc) + { + time = reader.ReadSingle(); + value = readerFunc(); + inSlope = readerFunc(); + outSlope = readerFunc(); + } + } + + public class AnimationCurve + { + public List> m_Curve { get; set; } + public int m_PreInfinity { get; set; } + public int m_PostInfinity { get; set; } + public int m_RotationOrder { get; set; } + + public AnimationCurve(EndianBinaryReader reader, Func readerFunc, int[] version) + { + int numCurves = reader.ReadInt32(); + m_Curve = new List>(numCurves); + for (int i = 0; i < numCurves; i++) + { + m_Curve.Add(new Keyframe(reader, readerFunc)); + } + + m_PreInfinity = reader.ReadInt32(); + m_PostInfinity = reader.ReadInt32(); + if (version[0] >= 5)//5.0 and up + { + m_RotationOrder = reader.ReadInt32(); + } + } + } + + public class QuaternionCurve + { + public AnimationCurve curve { get; set; } + public string path { get; set; } + + public QuaternionCurve(EndianBinaryReader reader, int[] version) + { + curve = new AnimationCurve(reader, reader.ReadQuaternion, version); + path = reader.ReadAlignedString(); + } + } + + public class PackedBitVector + { + public uint m_NumItems { get; set; } + public float m_Range { get; set; } + public float m_Start { get; set; } + public byte[] m_Data { get; set; } + public byte m_BitSize { get; set; } + + public PackedBitVector(EndianBinaryReader reader) + { + m_NumItems = reader.ReadUInt32(); + m_Range = reader.ReadSingle(); + m_Start = reader.ReadSingle(); + + int numData = reader.ReadInt32(); + m_Data = reader.ReadBytes(numData); + reader.AlignStream(4); + + m_BitSize = reader.ReadByte(); + reader.AlignStream(4); + } + } + + public class PackedBitVector2 + { + public uint m_NumItems { get; set; } + public byte[] m_Data { get; set; } + public byte m_BitSize { get; set; } + + public PackedBitVector2(EndianBinaryReader reader) + { + m_NumItems = reader.ReadUInt32(); + + int numData = reader.ReadInt32(); + m_Data = reader.ReadBytes(numData); + reader.AlignStream(4); + + m_BitSize = reader.ReadByte(); + reader.AlignStream(4); + } + } + + public class PackedBitVector3 + { + public uint m_NumItems { get; set; } + public byte[] m_Data { get; set; } + + public PackedBitVector3(EndianBinaryReader reader) + { + m_NumItems = reader.ReadUInt32(); + + int numData = reader.ReadInt32(); + m_Data = reader.ReadBytes(numData); + + reader.AlignStream(4); + } + } + + public class CompressedAnimationCurve + { + public string m_Path { get; set; } + public PackedBitVector2 m_Times { get; set; } + public PackedBitVector3 m_Values { get; set; } + public PackedBitVector m_Slopes { get; set; } + public int m_PreInfinity { get; set; } + public int m_PostInfinity { get; set; } + + public CompressedAnimationCurve(EndianBinaryReader reader) + { + m_Path = reader.ReadAlignedString(); + m_Times = new PackedBitVector2(reader); + m_Values = new PackedBitVector3(reader); + m_Slopes = new PackedBitVector(reader); + m_PreInfinity = reader.ReadInt32(); + m_PostInfinity = reader.ReadInt32(); + } + } + + public class Vector3Curve + { + public AnimationCurve curve { get; set; } + public string path { get; set; } + + public Vector3Curve(EndianBinaryReader reader, int[] version) + { + curve = new AnimationCurve(reader, reader.ReadVector3, version); + path = reader.ReadAlignedString(); + } + } + + public class FloatCurve + { + public AnimationCurve curve { get; set; } + public string attribute { get; set; } + public string path { get; set; } + public int classID { get; set; } + public PPtr script { get; set; } + + + public FloatCurve(AssetPreloadData preloadData) + { + var reader = preloadData.sourceFile.assetsFileReader; + curve = new AnimationCurve(reader, reader.ReadSingle, preloadData.sourceFile.version); + attribute = reader.ReadAlignedString(); + path = reader.ReadAlignedString(); + classID = reader.ReadInt32(); + script = preloadData.sourceFile.ReadPPtr(); + } + } + + public class PPtrKeyframe + { + public float time { get; set; } + public PPtr value { get; set; } + + + public PPtrKeyframe(AssetPreloadData preloadData) + { + var reader = preloadData.sourceFile.assetsFileReader; + time = reader.ReadSingle(); + value = preloadData.sourceFile.ReadPPtr(); + } + } + + public class PPtrCurve + { + public List curve { get; set; } + public string attribute { get; set; } + public string path { get; set; } + public int classID { get; set; } + public PPtr script { get; set; } + + + public PPtrCurve(AssetPreloadData preloadData) + { + var reader = preloadData.sourceFile.assetsFileReader; + + int numCurves = reader.ReadInt32(); + curve = new List(numCurves); + for (int i = 0; i < numCurves; i++) + { + curve.Add(new PPtrKeyframe(preloadData)); + } + + attribute = reader.ReadAlignedString(); + path = reader.ReadAlignedString(); + classID = reader.ReadInt32(); + script = preloadData.sourceFile.ReadPPtr(); + } + } + + public class AABB + { + public Vector3 m_Center { get; set; } + public Vector3 m_Extend { get; set; } + + public AABB(EndianBinaryReader reader) + { + m_Center = reader.ReadVector3(); + m_Extend = reader.ReadVector3(); + } + } + + public class xform + { + public object t { get; set; } + public Quaternion q { get; set; } + public object s { get; set; } + + public xform(EndianBinaryReader reader, int[] version) + { + t = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up + q = reader.ReadQuaternion(); + s = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up + } + } + + public class HandPose + { + public xform m_GrabX { get; set; } + public float[] m_DoFArray { get; set; } + public float m_Override { get; set; } + public float m_CloseOpen { get; set; } + public float m_InOut { get; set; } + public float m_Grab { get; set; } + + public HandPose(EndianBinaryReader reader, int[] version) + { + m_GrabX = new xform(reader, version); + + int numDoFs = reader.ReadInt32(); + m_DoFArray = reader.ReadSingleArray(numDoFs); + + m_Override = reader.ReadSingle(); + m_CloseOpen = reader.ReadSingle(); + m_InOut = reader.ReadSingle(); + m_Grab = reader.ReadSingle(); + } + } + + public class HumanGoal + { + public xform m_X { get; set; } + public float m_WeightT { get; set; } + public float m_WeightR { get; set; } + public object m_HintT { get; set; } + public float m_HintWeightT { get; set; } + + public HumanGoal(EndianBinaryReader reader, int[] version) + { + m_X = new xform(reader, version); + m_WeightT = reader.ReadSingle(); + m_WeightR = reader.ReadSingle(); + if (version[0] >= 5)//5.0 and up + { + m_HintT = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up + m_HintWeightT = reader.ReadSingle(); + } + } + } + + public class HumanPose + { + public xform m_RootX { get; set; } + public object m_LookAtPosition { get; set; } + public Vector4 m_LookAtWeight { get; set; } + public List m_GoalArray { get; set; } + public HandPose m_LeftHandPose { get; set; } + public HandPose m_RightHandPose { get; set; } + public float[] m_DoFArray { get; set; } + public object[] m_TDoFArray { get; set; } + + public HumanPose(EndianBinaryReader reader, int[] version) + { + m_RootX = new xform(reader, version); + m_LookAtPosition = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up + m_LookAtWeight = reader.ReadVector4(); + + int numGoals = reader.ReadInt32(); + m_GoalArray = new List(numGoals); + for (int i = 0; i < numGoals; i++) + { + m_GoalArray.Add(new HumanGoal(reader, version)); + } + + m_LeftHandPose = new HandPose(reader, version); + m_RightHandPose = new HandPose(reader, version); + + int numDoFs = reader.ReadInt32(); + m_DoFArray = reader.ReadSingleArray(numDoFs); + + if (version[0] >= 5)//5.0 and up + { + int numTDof = reader.ReadInt32(); + m_TDoFArray = new object[numTDof]; + for (int i = 0; i < numTDof; i++) + { + m_TDoFArray[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up + } + } + } + } + + public class StreamedClip + { + public uint[] data { get; set; } + public uint curveCount { get; set; } + + public StreamedClip(EndianBinaryReader reader) + { + int numData = reader.ReadInt32(); + data = reader.ReadUInt32Array(numData); + curveCount = reader.ReadUInt32(); + } + + public class StreamedCurveKey + { + public int index { get; set; } + public Vector3 tcb { get; set; } + public float value { get; set; } + public StreamedCurveKey(BinaryReader reader) + { + index = reader.ReadInt32(); + tcb = reader.ReadVector3(); + value = reader.ReadSingle(); + } + } + + public class StreamedFrame + { + public float time { get; set; } + public List keyList { get; set; } + + public StreamedFrame(BinaryReader reader) + { + time = reader.ReadSingle(); + + int numKeys = reader.ReadInt32(); + keyList = new List(numKeys); + for (int i = 0; i < numKeys; i++) + { + keyList.Add(new StreamedCurveKey(reader)); + } + } + } + + public List ReadData() + { + List frameList = new List(); + using (Stream stream = new MemoryStream()) + { + BinaryWriter writer = new BinaryWriter(stream); + writer.Write(data); + stream.Position = 0; + while (stream.Position < stream.Length) + { + frameList.Add(new StreamedFrame(new BinaryReader(stream))); + } + } + return frameList; + } + } + + public class DenseClip + { + public int m_FrameCount { get; set; } + public uint m_CurveCount { get; set; } + public float m_SampleRate { get; set; } + public float m_BeginTime { get; set; } + public float[] m_SampleArray { get; set; } + + public DenseClip(EndianBinaryReader reader) + { + m_FrameCount = reader.ReadInt32(); + m_CurveCount = reader.ReadUInt32(); + m_SampleRate = reader.ReadSingle(); + m_BeginTime = reader.ReadSingle(); + + int numSamples = reader.ReadInt32(); + m_SampleArray = reader.ReadSingleArray(numSamples); + } + } + + public class ConstantClip + { + public float[] data { get; set; } + + public ConstantClip(EndianBinaryReader reader) + { + int numData = reader.ReadInt32(); + data = reader.ReadSingleArray(numData); + } + } + + public class ValueConstant + { + public uint m_ID { get; set; } + public uint m_TypeID { get; set; } + public uint m_Type { get; set; } + public uint m_Index { get; set; } + + public ValueConstant(EndianBinaryReader reader, int[] version) + { + m_ID = reader.ReadUInt32(); + if (version[0] < 5 || (version[0] == 5 && version[1] < 5))//5.5 down + { + m_TypeID = reader.ReadUInt32(); + } + m_Type = reader.ReadUInt32(); + m_Index = reader.ReadUInt32(); + } + } + + public class ValueArrayConstant + { + public List m_ValueArray { get; set; } + + public ValueArrayConstant(EndianBinaryReader reader, int[] version) + { + int numVals = reader.ReadInt32(); + m_ValueArray = new List(numVals); + for (int i = 0; i < numVals; i++) + { + m_ValueArray.Add(new ValueConstant(reader, version)); + } + } + } + + public class Clip + { + public StreamedClip m_StreamedClip { get; set; } + public DenseClip m_DenseClip { get; set; } + public ConstantClip m_ConstantClip { get; set; } + public ValueArrayConstant m_Binding { get; set; } + + public Clip(EndianBinaryReader reader, int[] version) + { + m_StreamedClip = new StreamedClip(reader); + m_DenseClip = new DenseClip(reader); + m_ConstantClip = new ConstantClip(reader); + m_Binding = new ValueArrayConstant(reader, version); + } + } + + public class ValueDelta + { + public float m_Start { get; set; } + public float m_Stop { get; set; } + + public ValueDelta(EndianBinaryReader reader) + { + m_Start = reader.ReadSingle(); + m_Stop = reader.ReadSingle(); + } + } + + public class ClipMuscleConstant + { + public HumanPose m_DeltaPose { get; set; } + public xform m_StartX { get; set; } + public xform m_StopX { get; set; } + public xform m_LeftFootStartX { get; set; } + public xform m_RightFootStartX { get; set; } + public xform m_MotionStartX { get; set; } + public xform m_MotionStopX { get; set; } + public object m_AverageSpeed { get; set; } + public Clip m_Clip { get; set; } + public float m_StartTime { get; set; } + public float m_StopTime { get; set; } + public float m_OrientationOffsetY { get; set; } + public float m_Level { get; set; } + public float m_CycleOffset { get; set; } + public float m_AverageAngularSpeed { get; set; } + public int[] m_IndexArray { get; set; } + public List m_ValueArrayDelta { get; set; } + public float[] m_ValueArrayReferencePose { get; set; } + public bool m_Mirror { get; set; } + public bool m_LoopTime { get; set; } + public bool m_LoopBlend { get; set; } + public bool m_LoopBlendOrientation { get; set; } + public bool m_LoopBlendPositionY { get; set; } + public bool m_LoopBlendPositionXZ { get; set; } + public bool m_StartAtOrigin { get; set; } + public bool m_KeepOriginalOrientation { get; set; } + public bool m_KeepOriginalPositionY { get; set; } + public bool m_KeepOriginalPositionXZ { get; set; } + public bool m_HeightFromFeet { get; set; } + + public ClipMuscleConstant(EndianBinaryReader reader, int[] version) + { + m_DeltaPose = new HumanPose(reader, version); + m_StartX = new xform(reader, version); + if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up + { + m_StopX = new xform(reader, version); + } + m_LeftFootStartX = new xform(reader, version); + m_RightFootStartX = new xform(reader, version); + if (version[0] < 5)//5.0 down + { + m_MotionStartX = new xform(reader, version); + m_MotionStopX = new xform(reader, version); + } + m_AverageSpeed = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up + m_Clip = new Clip(reader, version); + m_StartTime = reader.ReadSingle(); + m_StopTime = reader.ReadSingle(); + m_OrientationOffsetY = reader.ReadSingle(); + m_Level = reader.ReadSingle(); + m_CycleOffset = reader.ReadSingle(); + m_AverageAngularSpeed = reader.ReadSingle(); + + int numIndices = reader.ReadInt32(); + m_IndexArray = reader.ReadInt32Array(numIndices); + + int numDeltas = reader.ReadInt32(); + m_ValueArrayDelta = new List(numDeltas); + for (int i = 0; i < numDeltas; i++) + { + m_ValueArrayDelta.Add(new ValueDelta(reader)); + } + if (version[0] >= 5)//5.0 and up + { + m_ValueArrayReferencePose = reader.ReadSingleArray(reader.ReadInt32()); + } + + m_Mirror = reader.ReadBoolean(); + m_LoopTime = reader.ReadBoolean(); + m_LoopBlend = reader.ReadBoolean(); + m_LoopBlendOrientation = reader.ReadBoolean(); + m_LoopBlendPositionY = reader.ReadBoolean(); + m_LoopBlendPositionXZ = reader.ReadBoolean(); + if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up + { + m_StartAtOrigin = reader.ReadBoolean(); + } + m_KeepOriginalOrientation = reader.ReadBoolean(); + m_KeepOriginalPositionY = reader.ReadBoolean(); + m_KeepOriginalPositionXZ = reader.ReadBoolean(); + m_HeightFromFeet = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class GenericBinding + { + public uint path { get; set; } + public uint attribute { get; set; } + public PPtr script { get; set; } + public int typeID { get; set; } + public byte customType { get; set; } + public byte isPPtrCurve { get; set; } + + public GenericBinding(AssetPreloadData preloadData) + { + var reader = preloadData.sourceFile.assetsFileReader; + var version = preloadData.sourceFile.version; + path = reader.ReadUInt32(); + attribute = reader.ReadUInt32(); + script = preloadData.sourceFile.ReadPPtr(); + if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up + { + typeID = reader.ReadInt32(); + } + else + { + typeID = reader.ReadUInt16(); + } + customType = reader.ReadByte(); + isPPtrCurve = reader.ReadByte(); + reader.AlignStream(4); + } + } + + public class AnimationClipBindingConstant + { + public List genericBindings { get; set; } + public List pptrCurveMapping { get; set; } + + public AnimationClipBindingConstant(AssetPreloadData preloadData) + { + var reader = preloadData.sourceFile.assetsFileReader; + int numBindings = reader.ReadInt32(); + genericBindings = new List(numBindings); + for (int i = 0; i < numBindings; i++) + { + genericBindings.Add(new GenericBinding(preloadData)); + } + + int numMappings = reader.ReadInt32(); + pptrCurveMapping = new List(numMappings); + for (int i = 0; i < numMappings; i++) + { + pptrCurveMapping.Add(preloadData.sourceFile.ReadPPtr()); + } + } + + public GenericBinding FindBinding(int index) + { + int curves = 0; + for (int i = 0; i < genericBindings.Count; i++) + { + GenericBinding b = genericBindings[i]; + curves += b.attribute == 2 ? 4 : b.attribute <= 4 ? 3 : 1; + if (curves > index) + { + return b; + } + } + + return null; + } + + public GenericBinding FindBinding(uint path, uint attribute) + { + return genericBindings.Find + ( + delegate (GenericBinding b) + { + return b.path == path && b.attribute == attribute; + } + ); + } + } + + public class AnimationClip + { + public string m_Name { get; set; } + public int m_AnimationType { get; set; } + public bool m_Legacy { get; set; } + public bool m_Compressed { get; set; } + public bool m_UseHighQualityCurve { get; set; } + public List m_RotationCurves { get; set; } + public List m_CompressedRotationCurves { get; set; } + public List m_EulerCurves { get; set; } + public List m_PositionCurves { get; set; } + public List m_ScaleCurves { get; set; } + public List m_FloatCurves { get; set; } + public List m_PPtrCurves { get; set; } + public float m_SampleRate { get; set; } + public int m_WrapMode { get; set; } + public AABB m_Bounds { get; set; } + public uint m_MuscleClipSize { get; set; } + public ClipMuscleConstant m_MuscleClip { get; set; } + public AnimationClipBindingConstant m_ClipBindingConstant { get; set; } + //public List m_Events { get; set; } + + + public AnimationClip(AssetPreloadData preloadData) + { + var sourceFile = preloadData.sourceFile; + var version = sourceFile.version; + var reader = preloadData.InitReader(); + reader.Position = preloadData.Offset; + + m_Name = reader.ReadAlignedString(); + if (version[0] >= 5)//5.0 and up + { + m_Legacy = reader.ReadBoolean(); + } + else + { + m_AnimationType = reader.ReadInt32(); + } + m_Compressed = reader.ReadBoolean(); + m_UseHighQualityCurve = reader.ReadBoolean(); + reader.AlignStream(4); + if (m_Compressed) + { + //TODO + } + + int numRCurves = reader.ReadInt32(); + m_RotationCurves = new List(numRCurves); + for (int i = 0; i < numRCurves; i++) + { + m_RotationCurves.Add(new QuaternionCurve(reader, version)); + } + + int numCRCurves = reader.ReadInt32(); + m_CompressedRotationCurves = new List(numCRCurves); + for (int i = 0; i < numCRCurves; i++) + { + m_CompressedRotationCurves.Add(new CompressedAnimationCurve(reader)); + } + + if (version[0] >= 5)//5.0 and up + { + int numEulerCurves = reader.ReadInt32(); + m_EulerCurves = new List(numEulerCurves); + for (int i = 0; i < numEulerCurves; i++) + { + m_EulerCurves.Add(new Vector3Curve(reader, version)); + } + } + + int numPCurves = reader.ReadInt32(); + m_PositionCurves = new List(numPCurves); + for (int i = 0; i < numPCurves; i++) + { + m_PositionCurves.Add(new Vector3Curve(reader, version)); + } + + int numSCurves = reader.ReadInt32(); + m_ScaleCurves = new List(numSCurves); + for (int i = 0; i < numSCurves; i++) + { + m_ScaleCurves.Add(new Vector3Curve(reader, version)); + } + + int numFCurves = reader.ReadInt32(); + m_FloatCurves = new List(numFCurves); + for (int i = 0; i < numFCurves; i++) + { + m_FloatCurves.Add(new FloatCurve(preloadData)); + } + + int numPtrCurves = reader.ReadInt32(); + m_PPtrCurves = new List(numPtrCurves); + for (int i = 0; i < numPtrCurves; i++) + { + m_PPtrCurves.Add(new PPtrCurve(preloadData)); + } + + m_SampleRate = reader.ReadSingle(); + m_WrapMode = reader.ReadInt32(); + m_Bounds = new AABB(reader); + m_MuscleClipSize = reader.ReadUInt32(); + m_MuscleClip = new ClipMuscleConstant(reader, version); + m_ClipBindingConstant = new AnimationClipBindingConstant(preloadData); + + /*int numEvents = reader.ReadInt32(); + m_Events = new List(numEvents); + for (int i = 0; i < numEvents; i++) + { + m_Events.Add(new AnimationEvent(stream, file.Version[0] - '0')); + }*/ + } + } +} diff --git a/AssetStudio/Classes/Animator.cs b/AssetStudio/Classes/Animator.cs new file mode 100644 index 0000000..ac7e962 --- /dev/null +++ b/AssetStudio/Classes/Animator.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace AssetStudio +{ + class Animator + { + public PPtr m_GameObject; + public PPtr m_Avatar; + public PPtr m_Controller; + + public Animator(AssetPreloadData preloadData) + { + var sourceFile = preloadData.sourceFile; + var reader = preloadData.InitReader(); + reader.Position = preloadData.Offset; + + m_GameObject = sourceFile.ReadPPtr(); + var m_Enabled = reader.ReadByte(); + reader.AlignStream(4); + m_Avatar = sourceFile.ReadPPtr(); + m_Controller = sourceFile.ReadPPtr(); + } + } +} diff --git a/AssetStudio/Classes/AnimatorController.cs b/AssetStudio/Classes/AnimatorController.cs new file mode 100644 index 0000000..bd21e51 --- /dev/null +++ b/AssetStudio/Classes/AnimatorController.cs @@ -0,0 +1,560 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SharpDX; + +namespace AssetStudio +{ + public class HumanPoseMask + { + public uint word0 { get; set; } + public uint word1 { get; set; } + public uint word2 { get; set; } + + public HumanPoseMask(EndianBinaryReader reader, int[] version) + { + word0 = reader.ReadUInt32(); + word1 = reader.ReadUInt32(); + if (version[0] >= 5) //5.0 and up + { + word2 = reader.ReadUInt32(); + } + } + } + + public class SkeletonMaskElement + { + public uint m_PathHash { get; set; } + public float m_Weight { get; set; } + + public SkeletonMaskElement(EndianBinaryReader reader) + { + m_PathHash = reader.ReadUInt32(); + m_Weight = reader.ReadSingle(); + } + } + + public class SkeletonMask + { + public SkeletonMaskElement[] m_Data { get; set; } + + public SkeletonMask(EndianBinaryReader reader) + { + int numElements = reader.ReadInt32(); + m_Data = new SkeletonMaskElement[numElements]; + for (int i = 0; i < numElements; i++) + { + m_Data[i] = new SkeletonMaskElement(reader); + } + } + } + + public class LayerConstant + { + public uint m_StateMachineIndex { get; set; } + public uint m_StateMachineMotionSetIndex { get; set; } + public HumanPoseMask m_BodyMask { get; set; } + public SkeletonMask m_SkeletonMask { get; set; } + public uint m_Binding { get; set; } + public int m_LayerBlendingMode { get; set; } + public float m_DefaultWeight { get; set; } + public bool m_IKPass { get; set; } + public bool m_SyncedLayerAffectsTiming { get; set; } + + public LayerConstant(EndianBinaryReader reader, int[] version) + { + m_StateMachineIndex = reader.ReadUInt32(); + m_StateMachineMotionSetIndex = reader.ReadUInt32(); + m_BodyMask = new HumanPoseMask(reader, version); + m_SkeletonMask = new SkeletonMask(reader); + m_Binding = reader.ReadUInt32(); + m_LayerBlendingMode = reader.ReadInt32(); + m_DefaultWeight = reader.ReadSingle(); + m_IKPass = reader.ReadBoolean(); + m_SyncedLayerAffectsTiming = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class ConditionConstant + { + public uint m_ConditionMode { get; set; } + public uint m_EventID { get; set; } + public float m_EventThreshold { get; set; } + public float m_ExitTime { get; set; } + + public ConditionConstant(EndianBinaryReader reader) + { + m_ConditionMode = reader.ReadUInt32(); + m_EventID = reader.ReadUInt32(); + m_EventThreshold = reader.ReadSingle(); + m_ExitTime = reader.ReadSingle(); + } + } + + public class TransitionConstant + { + public ConditionConstant[] m_ConditionConstantArray { get; set; } + public uint m_DestinationState { get; set; } + public uint m_FullPathID { get; set; } + public uint m_ID { get; set; } + public uint m_UserID { get; set; } + public float m_TransitionDuration { get; set; } + public float m_TransitionOffset { get; set; } + public float m_ExitTime { get; set; } + public bool m_HasExitTime { get; set; } + public bool m_HasFixedDuration { get; set; } + public int m_InterruptionSource { get; set; } + public bool m_OrderedInterruption { get; set; } + public bool m_Atomic { get; set; } + public bool m_CanTransitionToSelf { get; set; } + + public TransitionConstant(EndianBinaryReader reader, int[] version) + { + int numConditions = reader.ReadInt32(); + m_ConditionConstantArray = new ConditionConstant[numConditions]; + for (int i = 0; i < numConditions; i++) + { + m_ConditionConstantArray[i] = new ConditionConstant(reader); + } + + m_DestinationState = reader.ReadUInt32(); + if (version[0] >= 5) //5.0 and up + { + m_FullPathID = reader.ReadUInt32(); + } + + m_ID = reader.ReadUInt32(); + m_UserID = reader.ReadUInt32(); + m_TransitionDuration = reader.ReadSingle(); + m_TransitionOffset = reader.ReadSingle(); + if (version[0] >= 5) //5.0 and up + { + m_ExitTime = reader.ReadSingle(); + m_HasExitTime = reader.ReadBoolean(); + m_HasFixedDuration = reader.ReadBoolean(); + reader.AlignStream(4); + m_InterruptionSource = reader.ReadInt32(); + m_OrderedInterruption = reader.ReadBoolean(); + } + else + { + m_Atomic = reader.ReadBoolean(); + } + + m_CanTransitionToSelf = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class LeafInfoConstant + { + public uint[] m_IDArray { get; set; } + public uint m_IndexOffset { get; set; } + + public LeafInfoConstant(EndianBinaryReader reader) + { + m_IDArray = reader.ReadUInt32Array(reader.ReadInt32()); + m_IndexOffset = reader.ReadUInt32(); + } + } + + public class MotionNeighborList + { + public uint[] m_NeighborArray { get; set; } + + public MotionNeighborList(EndianBinaryReader reader) + { + m_NeighborArray = reader.ReadUInt32Array(reader.ReadInt32()); + } + } + + public class Blend2dDataConstant + { + public Vector2[] m_ChildPositionArray { get; set; } + public float[] m_ChildMagnitudeArray { get; set; } + public Vector2[] m_ChildPairVectorArray { get; set; } + public float[] m_ChildPairAvgMagInvArray { get; set; } + public MotionNeighborList[] m_ChildNeighborListArray { get; set; } + + public Blend2dDataConstant(EndianBinaryReader reader) + { + m_ChildPositionArray = reader.ReadVector2Array(reader.ReadInt32()); + m_ChildMagnitudeArray = reader.ReadSingleArray(reader.ReadInt32()); + m_ChildPairVectorArray = reader.ReadVector2Array(reader.ReadInt32()); + m_ChildPairAvgMagInvArray = reader.ReadSingleArray(reader.ReadInt32()); + + int numNeighbours = reader.ReadInt32(); + m_ChildNeighborListArray = new MotionNeighborList[numNeighbours]; + for (int i = 0; i < numNeighbours; i++) + { + m_ChildNeighborListArray[i] = new MotionNeighborList(reader); + } + } + } + + public class Blend1dDataConstant // wrong labeled + { + public float[] m_ChildThresholdArray { get; set; } + + public Blend1dDataConstant(EndianBinaryReader reader) + { + m_ChildThresholdArray = reader.ReadSingleArray(reader.ReadInt32()); + } + } + + public class BlendDirectDataConstant + { + public uint[] m_ChildBlendEventIDArray { get; set; } + public bool m_NormalizedBlendValues { get; set; } + + public BlendDirectDataConstant(EndianBinaryReader reader) + { + m_ChildBlendEventIDArray = reader.ReadUInt32Array(reader.ReadInt32()); + m_NormalizedBlendValues = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class BlendTreeNodeConstant + { + public uint m_BlendType { get; set; } + public uint m_BlendEventID { get; set; } + public uint m_BlendEventYID { get; set; } + public uint[] m_ChildIndices { get; set; } + public Blend1dDataConstant m_Blend1dData { get; set; } + public Blend2dDataConstant m_Blend2dData { get; set; } + public BlendDirectDataConstant m_BlendDirectData { get; set; } + public uint m_ClipID { get; set; } + public uint m_ClipIndex { get; set; } + public float m_Duration { get; set; } + public float m_CycleOffset { get; set; } + public bool m_Mirror { get; set; } + + public BlendTreeNodeConstant(EndianBinaryReader reader, int[] version) + { + m_BlendType = reader.ReadUInt32(); + m_BlendEventID = reader.ReadUInt32(); + m_BlendEventYID = reader.ReadUInt32(); + m_ChildIndices = reader.ReadUInt32Array(reader.ReadInt32()); + m_Blend1dData = new Blend1dDataConstant(reader); + m_Blend2dData = new Blend2dDataConstant(reader); + if (version[0] >= 5) //5.0 and up + { + m_BlendDirectData = new BlendDirectDataConstant(reader); + } + + m_ClipID = reader.ReadUInt32(); + if (version[0] < 5) //5.0 down + { + m_ClipIndex = reader.ReadUInt32(); + } + + m_Duration = reader.ReadSingle(); + m_CycleOffset = reader.ReadSingle(); + m_Mirror = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class BlendTreeConstant + { + public BlendTreeNodeConstant[] m_NodeArray { get; set; } + + public BlendTreeConstant(EndianBinaryReader reader, int[] version) + { + int numNodes = reader.ReadInt32(); + m_NodeArray = new BlendTreeNodeConstant[numNodes]; + for (int i = 0; i < numNodes; i++) + { + m_NodeArray[i] = new BlendTreeNodeConstant(reader, version); + } + } + } + + + public class StateConstant + { + public TransitionConstant[] m_TransitionConstantArray { get; set; } + public int[] m_BlendTreeConstantIndexArray { get; set; } + public LeafInfoConstant[] m_LeafInfoArray { get; set; } + public BlendTreeConstant[] m_BlendTreeConstantArray { get; set; } + public uint m_NameID { get; set; } + public uint m_PathID { get; set; } + public uint m_FullPathID { get; set; } + public uint m_TagID { get; set; } + public uint m_SpeedParamID { get; set; } + public uint m_MirrorParamID { get; set; } + public uint m_CycleOffsetParamID { get; set; } + public float m_Speed { get; set; } + public float m_CycleOffset { get; set; } + public bool m_IKOnFeet { get; set; } + public bool m_WriteDefaultValues { get; set; } + public bool m_Loop { get; set; } + public bool m_Mirror { get; set; } + + public StateConstant(EndianBinaryReader reader, int[] version) + { + int numTransistions = reader.ReadInt32(); + m_TransitionConstantArray = new TransitionConstant[numTransistions]; + for (int i = 0; i < numTransistions; i++) + { + m_TransitionConstantArray[i] = new TransitionConstant(reader, version); + } + + int numBlendIndices = reader.ReadInt32(); + m_BlendTreeConstantIndexArray = new int[numBlendIndices]; + for (int i = 0; i < numBlendIndices; i++) + { + m_BlendTreeConstantIndexArray[i] = reader.ReadInt32(); + } + + if (version[0] < 5) //5.0 down + { + int numInfos = reader.ReadInt32(); + m_LeafInfoArray = new LeafInfoConstant[numInfos]; + for (int i = 0; i < numInfos; i++) + { + m_LeafInfoArray[i] = new LeafInfoConstant(reader); + } + } + + int numBlends = reader.ReadInt32(); + m_BlendTreeConstantArray = new BlendTreeConstant[numBlends]; + for (int i = 0; i < numBlends; i++) + { + m_BlendTreeConstantArray[i] = new BlendTreeConstant(reader, version); + } + + m_NameID = reader.ReadUInt32(); + m_PathID = reader.ReadUInt32(); + if (version[0] >= 5) //5.0 and up + { + m_FullPathID = reader.ReadUInt32(); + } + + m_TagID = reader.ReadUInt32(); + if (version[0] >= 5) //5.0 and up + { + m_SpeedParamID = reader.ReadUInt32(); + m_MirrorParamID = reader.ReadUInt32(); + m_CycleOffsetParamID = reader.ReadUInt32(); + } + + if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up + { + var m_TimeParamID = reader.ReadUInt32(); + } + + m_Speed = reader.ReadSingle(); + m_CycleOffset = reader.ReadSingle(); + m_IKOnFeet = reader.ReadBoolean(); + if (version[0] >= 5) //5.0 and up + { + m_WriteDefaultValues = reader.ReadBoolean(); + } + + m_Loop = reader.ReadBoolean(); + m_Mirror = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class SelectorTransitionConstant + { + public uint m_Destination { get; set; } + public ConditionConstant[] m_ConditionConstantArray { get; set; } + + public SelectorTransitionConstant(EndianBinaryReader reader) + { + m_Destination = reader.ReadUInt32(); + + int numConditions = reader.ReadInt32(); + m_ConditionConstantArray = new ConditionConstant[numConditions]; + for (int i = 0; i < numConditions; i++) + { + m_ConditionConstantArray[i] = new ConditionConstant(reader); + } + } + } + + public class SelectorStateConstant + { + public SelectorTransitionConstant[] m_TransitionConstantArray { get; set; } + public uint m_FullPathID { get; set; } + public bool m_isEntry { get; set; } + + public SelectorStateConstant(EndianBinaryReader reader) + { + int numTransitions = reader.ReadInt32(); + m_TransitionConstantArray = new SelectorTransitionConstant[numTransitions]; + for (int i = 0; i < numTransitions; i++) + { + m_TransitionConstantArray[i] = new SelectorTransitionConstant(reader); + } + + m_FullPathID = reader.ReadUInt32(); + m_isEntry = reader.ReadBoolean(); + reader.AlignStream(4); + } + } + + public class StateMachineConstant + { + public StateConstant[] m_StateConstantArray { get; set; } + public TransitionConstant[] m_AnyStateTransitionConstantArray { get; set; } + public SelectorStateConstant[] m_SelectorStateConstantArray { get; set; } + public uint m_DefaultState { get; set; } + public uint m_MotionSetCount { get; set; } + + public StateMachineConstant(EndianBinaryReader reader, int[] version) + { + int numStates = reader.ReadInt32(); + m_StateConstantArray = new StateConstant[numStates]; + for (int i = 0; i < numStates; i++) + { + m_StateConstantArray[i] = new StateConstant(reader, version); + } + + int numAnyStates = reader.ReadInt32(); + m_AnyStateTransitionConstantArray = new TransitionConstant[numAnyStates]; + for (int i = 0; i < numAnyStates; i++) + { + m_AnyStateTransitionConstantArray[i] = new TransitionConstant(reader, version); + } + + if (version[0] >= 5) //5.0 and up + { + int numSelectors = reader.ReadInt32(); + m_SelectorStateConstantArray = new SelectorStateConstant[numSelectors]; + for (int i = 0; i < numSelectors; i++) + { + m_SelectorStateConstantArray[i] = new SelectorStateConstant(reader); + } + } + + m_DefaultState = reader.ReadUInt32(); + m_MotionSetCount = reader.ReadUInt32(); + } + } + + public class ValueArray + { + public bool[] m_BoolValues { get; set; } + public int[] m_IntValues { get; set; } + public float[] m_FloatValues { get; set; } + public object[] m_PositionValues { get; set; } + public Vector4[] m_QuaternionValues { get; set; } + public object[] m_ScaleValues { get; set; } + + public ValueArray(EndianBinaryReader reader, int[] version) + { + if (version[0] < 5 || (version[0] == 5 && version[1] < 5)) //5.5 down + { + int numBools = reader.ReadInt32(); + m_BoolValues = new bool[numBools]; + for (int i = 0; i < numBools; i++) + { + m_BoolValues[i] = reader.ReadBoolean(); + } + + reader.AlignStream(4); + + m_IntValues = reader.ReadInt32Array(reader.ReadInt32()); + m_FloatValues = reader.ReadSingleArray(reader.ReadInt32()); + } + + int numPosValues = reader.ReadInt32(); + m_PositionValues = new object[numPosValues]; + for (int i = 0; i < numPosValues; i++) + { + m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4(); //5.4 and up + } + + m_QuaternionValues = reader.ReadVector4Array(reader.ReadInt32()); + + int numScaleValues = reader.ReadInt32(); + m_ScaleValues = new object[numScaleValues]; + for (int i = 0; i < numScaleValues; i++) + { + m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4(); //5.4 adn up + } + + if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up + { + m_FloatValues = reader.ReadSingleArray(reader.ReadInt32()); + m_IntValues = reader.ReadInt32Array(reader.ReadInt32()); + + int numBools = reader.ReadInt32(); + m_BoolValues = new bool[numBools]; + for (int i = 0; i < numBools; i++) + { + m_BoolValues[i] = reader.ReadBoolean(); + } + + reader.AlignStream(4); + } + } + } + + public class ControllerConstant + { + public LayerConstant[] m_LayerArray { get; set; } + public StateMachineConstant[] m_StateMachineArray { get; set; } + public ValueArrayConstant m_Values { get; set; } + public ValueArray m_DefaultValues { get; set; } + + public ControllerConstant(EndianBinaryReader reader, int[] version) + { + int numLayers = reader.ReadInt32(); + m_LayerArray = new LayerConstant[numLayers]; + for (int i = 0; i < numLayers; i++) + { + m_LayerArray[i] = new LayerConstant(reader, version); + } + + int numStates = reader.ReadInt32(); + m_StateMachineArray = new StateMachineConstant[numStates]; + for (int i = 0; i < numStates; i++) + { + m_StateMachineArray[i] = new StateMachineConstant(reader, version); + } + + m_Values = new ValueArrayConstant(reader, version); + m_DefaultValues = new ValueArray(reader, version); + } + } + + public class AnimatorController + { + public string m_Name; + public PPtr[] m_AnimationClips; + + public AnimatorController(AssetPreloadData preloadData) + { + var sourceFile = preloadData.sourceFile; + var version = preloadData.sourceFile.version; + var reader = preloadData.InitReader(); + reader.Position = preloadData.Offset; + + m_Name = reader.ReadAlignedString(); + var m_ControllerSize = reader.ReadUInt32(); + var m_Controller = new ControllerConstant(reader, version); + + int tosSize = reader.ReadInt32(); + var m_TOS = new List>(tosSize); + for (int i = 0; i < tosSize; i++) + { + m_TOS.Add(new KeyValuePair(reader.ReadUInt32(), reader.ReadAlignedString())); + } + + int numClips = reader.ReadInt32(); + m_AnimationClips = new PPtr[numClips]; + for (int i = 0; i < numClips; i++) + { + m_AnimationClips[i] = sourceFile.ReadPPtr(); + } + } + } +} diff --git a/AssetStudio/Classes/AnimatorOverrideController.cs b/AssetStudio/Classes/AnimatorOverrideController.cs new file mode 100644 index 0000000..4fe8fbb --- /dev/null +++ b/AssetStudio/Classes/AnimatorOverrideController.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace AssetStudio +{ + class AnimatorOverrideController + { + public string m_Name; + public PPtr m_Controller; + public PPtr[][] m_Clips; + + public AnimatorOverrideController(AssetPreloadData preloadData) + { + var sourceFile = preloadData.sourceFile; + var reader = preloadData.InitReader(); + reader.Position = preloadData.Offset; + + m_Name = reader.ReadAlignedString(); + m_Controller = sourceFile.ReadPPtr(); + + int numOverrides = reader.ReadInt32(); + m_Clips = new PPtr[numOverrides][]; + for (int i = 0; i < numOverrides; i++) + { + m_Clips[i] = new PPtr[2]; + m_Clips[i][0] = sourceFile.ReadPPtr(); + m_Clips[i][1] = sourceFile.ReadPPtr(); + } + } + } +} diff --git a/AssetStudio/Classes/AssetBundle.cs b/AssetStudio/Classes/AssetBundle.cs index a99f78b..64d8537 100644 --- a/AssetStudio/Classes/AssetBundle.cs +++ b/AssetStudio/Classes/AssetBundle.cs @@ -27,9 +27,9 @@ namespace AssetStudio public AssetBundle(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); - var m_Name = reader.ReadAlignedString(reader.ReadInt32()); + var m_Name = reader.ReadAlignedString(); var size = reader.ReadInt32(); for (int i = 0; i < size; i++) { @@ -39,7 +39,7 @@ namespace AssetStudio for (int i = 0; i < size; i++) { var temp = new ContainerData(); - temp.first = reader.ReadAlignedString(reader.ReadInt32()); + temp.first = reader.ReadAlignedString(); temp.second = new AssetInfo(); temp.second.preloadIndex = reader.ReadInt32(); temp.second.preloadSize = reader.ReadInt32(); diff --git a/AssetStudio/Classes/AudioClip.cs b/AssetStudio/Classes/AudioClip.cs index 13f16d2..9a4a7b2 100644 --- a/AssetStudio/Classes/AudioClip.cs +++ b/AssetStudio/Classes/AudioClip.cs @@ -38,7 +38,7 @@ namespace AssetStudio public AudioClip(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { @@ -47,7 +47,7 @@ namespace AssetStudio PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); version5 = sourceFile.version[0] >= 5; if (sourceFile.version[0] < 5) { @@ -91,7 +91,7 @@ namespace AssetStudio reader.Position += 1; m_3D = m_Legacy3D; - m_Source = reader.ReadAlignedString(reader.ReadInt32()); + m_Source = reader.ReadAlignedString(); m_Offset = reader.ReadInt64(); m_Size = reader.ReadInt64(); m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32(); diff --git a/AssetStudio/Classes/Avatar.cs b/AssetStudio/Classes/Avatar.cs new file mode 100644 index 0000000..cff9081 --- /dev/null +++ b/AssetStudio/Classes/Avatar.cs @@ -0,0 +1,251 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace AssetStudio +{ + class Avatar + { + public string m_Name; + private List> m_TOS; + + public Avatar(AssetPreloadData preloadData) + { + var sourceFile = preloadData.sourceFile; + var version = sourceFile.version; + var reader = preloadData.InitReader(); + reader.Position = preloadData.Offset; + + m_Name = reader.ReadAlignedString(); + var m_AvatarSize = reader.ReadUInt32(); + //AvatarConstant m_Avatar + //- OffsetPtr m_AvatarSkeleton + //-- Skeleton data + //--- vector m_Node + var numNodes = reader.ReadInt32(); + for (int i = 0; i < numNodes; i++) + { + reader.Position += 8; + } + //--- vector m_ID + int numIDs = reader.ReadInt32(); + for (int i = 0; i < numIDs; i++) + { + reader.Position += 4; + } + //--- vector m_AxesArray + int numAxes = reader.ReadInt32(); + for (int i = 0; i < numAxes; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 76; + else + reader.Position += 88; + } + //- OffsetPtr m_AvatarSkeletonPose + //-- SkeletonPose data + int numXforms = reader.ReadInt32(); + for (int i = 0; i < numXforms; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 40; + else + reader.Position += 48; + } + //- OffsetPtr m_DefaultPose + //-- SkeletonPose data + numXforms = reader.ReadInt32(); + for (int i = 0; i < numXforms; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 40; + else + reader.Position += 48; + } + //- vector m_SkeletonNameIDArray + numIDs = reader.ReadInt32(); + for (int i = 0; i < numIDs; i++) + { + reader.Position += 4; + } + //- OffsetPtr m_Human + //-- Human data + //--- xform m_RootX + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 40; + else + reader.Position += 48; + //--- OffsetPtr m_Skeleton + //---- Skeleton data + numNodes = reader.ReadInt32(); + for (int i = 0; i < numNodes; i++) + { + reader.Position += 8; + } + //--- vector m_ID + numIDs = reader.ReadInt32(); + for (int i = 0; i < numIDs; i++) + { + reader.Position += 4; + } + //--- vector m_AxesArray + numAxes = reader.ReadInt32(); + for (int i = 0; i < numAxes; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 76; + else + reader.Position += 88; + } + //--- OffsetPtr m_SkeletonPose + //---- SkeletonPose data + numXforms = reader.ReadInt32(); + for (int i = 0; i < numXforms; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 40; + else + reader.Position += 48; + } + //--- OffsetPtr m_LeftHand + //---- Hand data + //----- staticvector m_HandBoneIndex + int numIndexes = reader.ReadInt32(); + for (int i = 0; i < numIndexes; i++) + { + reader.Position += 4; + } + //--- OffsetPtr m_RightHand + numIndexes = reader.ReadInt32(); + for (int i = 0; i < numIndexes; i++) + { + reader.Position += 4; + } + //--- vector m_Handles + int numHandles = reader.ReadInt32(); + for (int i = 0; i < numHandles; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 48; + else + reader.Position += 56; + } + //--- vector m_ColliderArray + int numColliders = reader.ReadInt32(); + for (int i = 0; i < numColliders; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 72; + else + reader.Position += 80; + } + //--- staticvector m_HumanBoneIndex + numIndexes = reader.ReadInt32(); + for (int i = 0; i < numIndexes; i++) + { + reader.Position += 4; + } + //--- staticvector m_HumanBoneMass + int numMasses = reader.ReadInt32(); + for (int i = 0; i < numMasses; i++) + { + reader.Position += 4; + } + //--- staticvector m_ColliderIndex + int numColliderIndexes = reader.ReadInt32(); + for (int i = 0; i < numColliderIndexes; i++) + { + reader.Position += 4; + } + var m_Scale = reader.ReadSingle(); + var m_ArmTwist = reader.ReadSingle(); + var m_ForeArmTwist = reader.ReadSingle(); + var m_UpperLegTwist = reader.ReadSingle(); + var m_LegTwist = reader.ReadSingle(); + var m_ArmStretch = reader.ReadSingle(); + var m_LegStretch = reader.ReadSingle(); + var m_FeetSpacing = reader.ReadSingle(); + var m_HasLeftHand = reader.ReadBoolean(); + var m_HasRightHand = reader.ReadBoolean(); + var m_HasTDoF = reader.ReadBoolean(); + reader.AlignStream(4); + //- vector m_HumanSkeletonIndexArray + numIndexes = reader.ReadInt32(); + for (int i = 0; i < numIndexes; i++) + { + reader.Position += 4; + } + //- vector m_HumanSkeletonReverseIndexArray + int numReverseIndexes = reader.ReadInt32(); + for (int i = 0; i < numReverseIndexes; i++) + { + reader.Position += 4; + } + var m_RootMotionBoneIndex = reader.ReadInt32(); + //- xform m_RootMotionBoneX + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 40; + else + reader.Position += 48; + //- OffsetPtr m_RootMotionSkeleton + //-- Skeleton data + //--- vector m_Node + numNodes = reader.ReadInt32(); + for (int i = 0; i < numNodes; i++) + { + reader.Position += 8; + } + //--- vector m_ID + numIDs = reader.ReadInt32(); + for (int i = 0; i < numIDs; i++) + { + reader.Position += 4; + } + //--- vector m_AxesArray + numAxes = reader.ReadInt32(); + for (int i = 0; i < numAxes; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 76; + else + reader.Position += 88; + } + //- OffsetPtr m_RootMotionSkeletonPose + //-- SkeletonPose data + numXforms = reader.ReadInt32(); + for (int i = 0; i < numXforms; i++) + { + if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up + reader.Position += 40; + else + reader.Position += 48; + } + //- vector m_RootMotionSkeletonIndexArray + int numMotionIndexes = reader.ReadInt32(); + for (int i = 0; i < numMotionIndexes; i++) + { + reader.Position += 4; + } + //map m_TOS + int numTOS = reader.ReadInt32(); + m_TOS = new List>(numTOS); + for (int i = 0; i < numTOS; i++) + { + m_TOS.Add(new KeyValuePair(reader.ReadUInt32(), reader.ReadAlignedString())); + } + } + + public string FindBoneName(uint hash) + { + foreach (var pair in m_TOS) + { + if (pair.Key == hash) + { + return pair.Value.Substring(pair.Value.LastIndexOf('/') + 1); + } + } + return null; + } + } +} diff --git a/AssetStudio/Classes/BuildSettings.cs b/AssetStudio/Classes/BuildSettings.cs index d6f0473..911fe8e 100644 --- a/AssetStudio/Classes/BuildSettings.cs +++ b/AssetStudio/Classes/BuildSettings.cs @@ -12,15 +12,15 @@ namespace AssetStudio public BuildSettings(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); int levels = reader.ReadInt32(); - for (int l = 0; l < levels; l++) { string level = reader.ReadAlignedString(reader.ReadInt32()); } + for (int l = 0; l < levels; l++) { string level = reader.ReadAlignedString(); } if (sourceFile.version[0] == 5) { int preloadedPlugins = reader.ReadInt32(); - for (int l = 0; l < preloadedPlugins; l++) { string preloadedPlugin = reader.ReadAlignedString(reader.ReadInt32()); } + for (int l = 0; l < preloadedPlugins; l++) { string preloadedPlugin = reader.ReadAlignedString(); } } reader.Position += 4; //bool flags @@ -31,7 +31,7 @@ namespace AssetStudio (sourceFile.version[1] == 2 && sourceFile.buildType[0] != "a")))) { reader.Position += 4; } //bool flags - m_Version = reader.ReadAlignedString(reader.ReadInt32()); + m_Version = reader.ReadAlignedString(); } } } diff --git a/AssetStudio/Classes/Font.cs b/AssetStudio/Classes/Font.cs index 5d84fa9..c35f997 100644 --- a/AssetStudio/Classes/Font.cs +++ b/AssetStudio/Classes/Font.cs @@ -13,7 +13,7 @@ namespace AssetStudio public UFont(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { @@ -22,7 +22,7 @@ namespace AssetStudio PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); if (readSwitch) { @@ -166,7 +166,7 @@ namespace AssetStudio int m_FontNames = reader.ReadInt32(); for (int i = 0; i < m_FontNames; i++) { - string m_FontName = reader.ReadAlignedString(reader.ReadInt32()); + string m_FontName = reader.ReadAlignedString(); } if (sourceFile.version[0] >= 4) diff --git a/AssetStudio/Classes/GameObject.cs b/AssetStudio/Classes/GameObject.cs index 3e8a548..2360ada 100644 --- a/AssetStudio/Classes/GameObject.cs +++ b/AssetStudio/Classes/GameObject.cs @@ -25,7 +25,7 @@ namespace AssetStudio if (preloadData != null) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); uniqueID = preloadData.uniqueID; @@ -51,7 +51,7 @@ namespace AssetStudio } m_Layer = reader.ReadInt32(); - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); if (m_Name == "") { m_Name = "GameObject #" + uniqueID; } m_Tag = reader.ReadUInt16(); m_IsActive = reader.ReadBoolean(); diff --git a/AssetStudio/Classes/Material.cs b/AssetStudio/Classes/Material.cs index d12e4bb..d6d999c 100644 --- a/AssetStudio/Classes/Material.cs +++ b/AssetStudio/Classes/Material.cs @@ -38,7 +38,7 @@ namespace AssetStudio public Material(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { @@ -47,7 +47,7 @@ namespace AssetStudio PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); m_Shader = sourceFile.ReadPPtr(); if (sourceFile.version[0] == 4 && (sourceFile.version[1] >= 2 || (sourceFile.version[1] == 1 && sourceFile.buildType[0] != "a"))) @@ -55,12 +55,12 @@ namespace AssetStudio m_ShaderKeywords = new string[reader.ReadInt32()]; for (int i = 0; i < m_ShaderKeywords.Length; i++) { - m_ShaderKeywords[i] = reader.ReadAlignedString(reader.ReadInt32()); + m_ShaderKeywords[i] = reader.ReadAlignedString(); } } else if (sourceFile.version[0] >= 5)//5.0 and up { - m_ShaderKeywords = new[] { reader.ReadAlignedString(reader.ReadInt32()) }; + m_ShaderKeywords = new[] { reader.ReadAlignedString() }; uint m_LightmapFlags = reader.ReadUInt32(); if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 6 || sourceFile.version[0] > 5)//5.6.0 and up { @@ -77,7 +77,7 @@ namespace AssetStudio string[][] stringTagMap = new string[reader.ReadInt32()][]; for (int i = 0; i < stringTagMap.Length; i++) { - stringTagMap[i] = new[] { reader.ReadAlignedString(reader.ReadInt32()), reader.ReadAlignedString(reader.ReadInt32()) }; + stringTagMap[i] = new[] { reader.ReadAlignedString(), reader.ReadAlignedString() }; } } //disabledShaderPasses @@ -86,7 +86,7 @@ namespace AssetStudio var size = reader.ReadInt32(); for (int i = 0; i < size; i++) { - reader.ReadAlignedString(reader.ReadInt32()); + reader.ReadAlignedString(); } } //m_SavedProperties @@ -95,7 +95,7 @@ namespace AssetStudio { TexEnv m_TexEnv = new TexEnv() { - name = reader.ReadAlignedString(reader.ReadInt32()), + name = reader.ReadAlignedString(), m_Texture = sourceFile.ReadPPtr(), m_Scale = new[] { reader.ReadSingle(), reader.ReadSingle() }, m_Offset = new[] { reader.ReadSingle(), reader.ReadSingle() } @@ -108,7 +108,7 @@ namespace AssetStudio { strFloatPair m_Float = new strFloatPair() { - first = reader.ReadAlignedString(reader.ReadInt32()), + first = reader.ReadAlignedString(), second = reader.ReadSingle() }; m_Floats[i] = m_Float; @@ -119,7 +119,7 @@ namespace AssetStudio { strColorPair m_Color = new strColorPair() { - first = reader.ReadAlignedString(reader.ReadInt32()), + first = reader.ReadAlignedString(), second = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() } }; m_Colors[i] = m_Color; diff --git a/AssetStudio/Classes/Mesh.cs b/AssetStudio/Classes/Mesh.cs index 15f9316..e64f49b 100644 --- a/AssetStudio/Classes/Mesh.cs +++ b/AssetStudio/Classes/Mesh.cs @@ -331,7 +331,7 @@ namespace AssetStudio //Stream = new EndianStream(File.OpenRead(sourceFile.filePath), sourceFile.endianType); //Stream.endian = sourceFile.endianType; var version = MeshPD.sourceFile.version; - reader = MeshPD.Reader; + reader = MeshPD.InitReader(); bool m_Use16BitIndices = true; //3.5.0 and newer always uses 16bit indices uint m_MeshCompression = 0; @@ -343,7 +343,7 @@ namespace AssetStudio PPtr m_PrefabInternal = MeshPD.sourceFile.ReadPPtr(); } - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); if (readSwitch) { @@ -409,7 +409,7 @@ namespace AssetStudio } for (int s = 0; s < m_Shapes_size; s++) //untested { - string shape_name = reader.ReadAlignedString(reader.ReadInt32()); + string shape_name = reader.ReadAlignedString(); reader.Position += 36; //uint firstVertex, vertexCount; Vector3f aabbMinDelta, aabbMaxDelta; bool hasNormals, hasTangents } @@ -433,7 +433,7 @@ namespace AssetStudio int channels_size = reader.ReadInt32(); for (int c = 0; c < channels_size; c++) { - string channel_name = reader.ReadAlignedString(reader.ReadInt32()); + string channel_name = reader.ReadAlignedString(); reader.Position += 12; //uint nameHash; int frameIndex, frameCount } diff --git a/AssetStudio/Classes/MeshFilter.cs b/AssetStudio/Classes/MeshFilter.cs index ef45f2f..aafa0d9 100644 --- a/AssetStudio/Classes/MeshFilter.cs +++ b/AssetStudio/Classes/MeshFilter.cs @@ -14,7 +14,7 @@ namespace AssetStudio public MeshFilter(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { diff --git a/AssetStudio/Classes/MeshRenderer.cs b/AssetStudio/Classes/MeshRenderer.cs index fa58249..c1d2f61 100644 --- a/AssetStudio/Classes/MeshRenderer.cs +++ b/AssetStudio/Classes/MeshRenderer.cs @@ -18,7 +18,7 @@ namespace AssetStudio public MeshRenderer(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { diff --git a/AssetStudio/Classes/MonoBehaviour.cs b/AssetStudio/Classes/MonoBehaviour.cs index aff8518..a575fef 100644 --- a/AssetStudio/Classes/MonoBehaviour.cs +++ b/AssetStudio/Classes/MonoBehaviour.cs @@ -12,13 +12,13 @@ namespace AssetStudio public MonoBehaviour(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); var m_GameObject = sourceFile.ReadPPtr(); var m_Enabled = reader.ReadByte(); reader.AlignStream(4); var m_Script = sourceFile.ReadPPtr(); - var m_Name = reader.ReadAlignedString(reader.ReadInt32()); + var m_Name = reader.ReadAlignedString(); if (readSwitch) { if ((serializedText = preloadData.ViewStruct()) == null) diff --git a/AssetStudio/Classes/MovieTexture.cs b/AssetStudio/Classes/MovieTexture.cs index 9849d9b..5b7e657 100644 --- a/AssetStudio/Classes/MovieTexture.cs +++ b/AssetStudio/Classes/MovieTexture.cs @@ -13,9 +13,9 @@ namespace AssetStudio public MovieTexture(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); if (readSwitch) { var m_Loop = reader.ReadBoolean(); diff --git a/AssetStudio/Classes/PlayerSettings.cs b/AssetStudio/Classes/PlayerSettings.cs index b8e9afd..0a7c010 100644 --- a/AssetStudio/Classes/PlayerSettings.cs +++ b/AssetStudio/Classes/PlayerSettings.cs @@ -13,7 +13,7 @@ namespace AssetStudio public PlayerSettings(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if ((sourceFile.version[0] == 5 && sourceFile.version[1] >= 4) || sourceFile.version[0] > 5)//5.4.0 nad up @@ -26,7 +26,7 @@ namespace AssetStudio } if (sourceFile.version[0] >= 3) { - if (sourceFile.version[0] == 3 && sourceFile.version[1] < 2) { string AndroidLicensePublicKey = reader.ReadAlignedString(reader.ReadInt32()); } + if (sourceFile.version[0] == 3 && sourceFile.version[1] < 2) { string AndroidLicensePublicKey = reader.ReadAlignedString(); } else { bool AndroidProfiler = reader.ReadBoolean(); reader.AlignStream(4); } int defaultScreenOrientation = reader.ReadInt32(); @@ -49,8 +49,8 @@ namespace AssetStudio else { int accelerometerFrequency = reader.ReadInt32(); }//3.5.0 and up } //fail in version 5 beta - companyName = reader.ReadAlignedString(reader.ReadInt32()); - productName = reader.ReadAlignedString(reader.ReadInt32()); + companyName = reader.ReadAlignedString(); + productName = reader.ReadAlignedString(); } } } diff --git a/AssetStudio/Classes/Shader.cs b/AssetStudio/Classes/Shader.cs index a60f988..48e85b3 100644 --- a/AssetStudio/Classes/Shader.cs +++ b/AssetStudio/Classes/Shader.cs @@ -16,7 +16,7 @@ namespace AssetStudio public Shader(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { @@ -25,7 +25,7 @@ namespace AssetStudio PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); if (readSwitch) { @@ -56,7 +56,7 @@ namespace AssetStudio if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 3) //5.3 - 5.4 { reader.AlignStream(4); - reader.ReadAlignedString(reader.ReadInt32());//m_PathName + reader.ReadAlignedString();//m_PathName var decompressedSize = reader.ReadUInt32(); var m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32()); var decompressedBytes = new byte[decompressedSize]; diff --git a/AssetStudio/Classes/SkinnedMeshRenderer.cs b/AssetStudio/Classes/SkinnedMeshRenderer.cs index 28a34e2..e9b7441 100644 --- a/AssetStudio/Classes/SkinnedMeshRenderer.cs +++ b/AssetStudio/Classes/SkinnedMeshRenderer.cs @@ -21,7 +21,7 @@ namespace AssetStudio { var sourceFile = preloadData.sourceFile; var version = preloadData.sourceFile.version; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { diff --git a/AssetStudio/Classes/Sprite.cs b/AssetStudio/Classes/Sprite.cs index e01397b..8e652df 100644 --- a/AssetStudio/Classes/Sprite.cs +++ b/AssetStudio/Classes/Sprite.cs @@ -21,10 +21,10 @@ namespace AssetStudio public Sprite(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); var version = sourceFile.version; - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); if (readSwitch) { //Rectf m_Rect @@ -62,7 +62,7 @@ namespace AssetStudio var size = reader.ReadInt32(); for (int i = 0; i < size; i++) { - var data = reader.ReadAlignedString(reader.ReadInt32()); + var data = reader.ReadAlignedString(); } //PPtr m_SpriteAtlas diff --git a/AssetStudio/Classes/SpriteAtlas.cs b/AssetStudio/Classes/SpriteAtlas.cs index fbf8be0..8241eb3 100644 --- a/AssetStudio/Classes/SpriteAtlas.cs +++ b/AssetStudio/Classes/SpriteAtlas.cs @@ -16,9 +16,9 @@ namespace AssetStudio public SpriteAtlas(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); - var m_Name = reader.ReadAlignedString(reader.ReadInt32()); + var m_Name = reader.ReadAlignedString(); //vector m_PackedSprites var size = reader.ReadInt32(); for (int i = 0; i < size; i++) @@ -30,7 +30,7 @@ namespace AssetStudio size = reader.ReadInt32(); for (int i = 0; i < size; i++) { - var data = reader.ReadAlignedString(reader.ReadInt32()); + var data = reader.ReadAlignedString(); } //map m_RenderDataMap size = reader.ReadInt32(); diff --git a/AssetStudio/Classes/TextAsset.cs b/AssetStudio/Classes/TextAsset.cs index 5c7f063..89fabfe 100644 --- a/AssetStudio/Classes/TextAsset.cs +++ b/AssetStudio/Classes/TextAsset.cs @@ -14,7 +14,7 @@ namespace AssetStudio public TextAsset(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { @@ -23,7 +23,7 @@ namespace AssetStudio PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); if (readSwitch) { diff --git a/AssetStudio/Classes/Texture2D.cs b/AssetStudio/Classes/Texture2D.cs index bfd659d..d54191e 100644 --- a/AssetStudio/Classes/Texture2D.cs +++ b/AssetStudio/Classes/Texture2D.cs @@ -91,7 +91,7 @@ namespace AssetStudio public Texture2D(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); version = sourceFile.version; if (sourceFile.platform == -2) @@ -101,7 +101,7 @@ namespace AssetStudio PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3))//2017.3 and up { var m_ForcedFallbackFormat = reader.ReadInt32(); @@ -158,7 +158,7 @@ namespace AssetStudio offset = reader.ReadUInt32(); size = reader.ReadUInt32(); image_data_size = (int)size; - path = reader.ReadAlignedString(reader.ReadInt32()); + path = reader.ReadAlignedString(); } if (readSwitch) diff --git a/AssetStudio/Classes/Transform.cs b/AssetStudio/Classes/Transform.cs index fbe8c28..41cb3fd 100644 --- a/AssetStudio/Classes/Transform.cs +++ b/AssetStudio/Classes/Transform.cs @@ -17,7 +17,7 @@ namespace AssetStudio public Transform(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); if (sourceFile.platform == -2) { diff --git a/AssetStudio/Classes/VideoClip.cs b/AssetStudio/Classes/VideoClip.cs index d54ee65..360385d 100644 --- a/AssetStudio/Classes/VideoClip.cs +++ b/AssetStudio/Classes/VideoClip.cs @@ -15,10 +15,10 @@ namespace AssetStudio public VideoClip(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.Reader; + var reader = preloadData.InitReader(); - m_Name = reader.ReadAlignedString(reader.ReadInt32()); - var m_OriginalPath = reader.ReadAlignedString(reader.ReadInt32()); + m_Name = reader.ReadAlignedString(); + var m_OriginalPath = reader.ReadAlignedString(); var m_ProxyWidth = reader.ReadUInt32(); var m_ProxyHeight = reader.ReadUInt32(); var Width = reader.ReadUInt32(); @@ -42,10 +42,10 @@ namespace AssetStudio size = reader.ReadInt32(); for (int i = 0; i < size; i++) { - reader.ReadAlignedString(reader.ReadInt32()); + reader.ReadAlignedString(); } //StreamedResource m_ExternalResources - var m_Source = reader.ReadAlignedString(reader.ReadInt32()); + var m_Source = reader.ReadAlignedString(); var m_Offset = reader.ReadUInt64(); var m_Size = reader.ReadUInt64(); var m_HasSplitAlpha = reader.ReadBoolean(); diff --git a/AssetStudio/Library/SharpDX.Mathematics.dll b/AssetStudio/Library/SharpDX.Mathematics.dll new file mode 100644 index 0000000000000000000000000000000000000000..4c0da9c7c75a378117809b06c961c2e6e0695c1d GIT binary patch literal 220672 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�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 - //build Class Structures - assetsFileReader.Position -= varCount * 24 + stringSize; - for (int i = 0; i < varCount; i++) + using (var stringReader = new BinaryReader(new MemoryStream(assetsFileReader.ReadBytes(stringSize)))) { - ushort num0 = assetsFileReader.ReadUInt16(); - byte level = assetsFileReader.ReadByte(); - bool isArray = assetsFileReader.ReadBoolean(); + string className = ""; + var classVar = new List(); + //build Class Structures + assetsFileReader.Position -= varCount * 24 + stringSize; + for (int i = 0; i < varCount; i++) + { + ushort num0 = assetsFileReader.ReadUInt16(); + byte level = assetsFileReader.ReadByte(); + bool isArray = assetsFileReader.ReadBoolean(); - ushort varTypeIndex = assetsFileReader.ReadUInt16(); - ushort test = assetsFileReader.ReadUInt16(); - string varTypeStr; - if (test == 0) //varType is an offset in the string block - { - stringReader.Position = varTypeIndex; - varTypeStr = stringReader.ReadStringToNull(); - } - else //varType is an index in an internal strig array - { - varTypeStr = baseStrings.ContainsKey(varTypeIndex) ? baseStrings[varTypeIndex] : varTypeIndex.ToString(); - } - - ushort varNameIndex = assetsFileReader.ReadUInt16(); - test = assetsFileReader.ReadUInt16(); - string varNameStr; - if (test == 0) - { - stringReader.Position = varNameIndex; - varNameStr = stringReader.ReadStringToNull(); - } - else - { - varNameStr = baseStrings.ContainsKey(varNameIndex) ? baseStrings[varNameIndex] : varNameIndex.ToString(); - } - - int size = assetsFileReader.ReadInt32(); - int index = assetsFileReader.ReadInt32(); - int flag = assetsFileReader.ReadInt32(); - - if (index == 0) { className = varTypeStr + " " + varNameStr; } - else - { - classVar.Add(new ClassMember + ushort varTypeIndex = assetsFileReader.ReadUInt16(); + ushort test = assetsFileReader.ReadUInt16(); + string varTypeStr; + if (test == 0) //varType is an offset in the string block { - Level = level - 1, - Type = varTypeStr, - Name = varNameStr, - Size = size, - Flag = flag - }); - } - } - stringReader.Dispose(); - assetsFileReader.Position += stringSize; + stringReader.BaseStream.Position = varTypeIndex; + varTypeStr = stringReader.ReadStringToNull(); + } + else //varType is an index in an internal strig array + { + varTypeStr = baseStrings.ContainsKey(varTypeIndex) ? baseStrings[varTypeIndex] : varTypeIndex.ToString(); + } - var aClass = new ClassStruct { ID = classID, Text = className, members = classVar }; - aClass.SubItems.Add(classID.ToString()); - ClassStructures[classID] = aClass; + ushort varNameIndex = assetsFileReader.ReadUInt16(); + test = assetsFileReader.ReadUInt16(); + string varNameStr; + if (test == 0) + { + stringReader.BaseStream.Position = varNameIndex; + varNameStr = stringReader.ReadStringToNull(); + } + else + { + varNameStr = baseStrings.ContainsKey(varNameIndex) ? baseStrings[varNameIndex] : varNameIndex.ToString(); + } + + int size = assetsFileReader.ReadInt32(); + int index = assetsFileReader.ReadInt32(); + int flag = assetsFileReader.ReadInt32(); + + if (index == 0) + { + className = varTypeStr + " " + varNameStr; + } + else + { + classVar.Add(new ClassMember + { + Level = level - 1, + Type = varTypeStr, + Name = varNameStr, + Size = size, + Flag = flag + }); + } + } + assetsFileReader.Position += stringSize; + var aClass = new ClassStruct { ID = classID, Text = className, members = classVar }; + aClass.SubItems.Add(classID.ToString()); + ClassStructures[classID] = aClass; + } } } } diff --git a/AssetStudio/StudioClasses/BinaryReaderExtensions.cs b/AssetStudio/StudioClasses/BinaryReaderExtensions.cs new file mode 100644 index 0000000..8c8f1f0 --- /dev/null +++ b/AssetStudio/StudioClasses/BinaryReaderExtensions.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using SharpDX; + +namespace AssetStudio +{ + public static class BinaryReaderExtensions + { + public static void AlignStream(this BinaryReader reader, int alignment) + { + var pos = reader.BaseStream.Position; + var mod = pos % alignment; + if (mod != 0) + { + reader.BaseStream.Position += alignment - mod; + } + } + + public static string ReadAlignedString(this BinaryReader reader) + { + return ReadAlignedString(reader, reader.ReadInt32()); + } + + public static string ReadAlignedString(this BinaryReader reader, int length) + { + if (length > 0 && length < (reader.BaseStream.Length - reader.BaseStream.Position)) + { + var stringData = reader.ReadBytes(length); + var result = Encoding.UTF8.GetString(stringData); + reader.AlignStream(4); + return result; + } + return ""; + } + + public static string ReadStringToNull(this BinaryReader reader) + { + var bytes = new List(); + byte b; + while (reader.BaseStream.Position != reader.BaseStream.Length && (b = reader.ReadByte()) != 0) + bytes.Add(b); + return Encoding.UTF8.GetString(bytes.ToArray()); + } + + public static Quaternion ReadQuaternion(this BinaryReader reader) + { + var q = new Quaternion + { + X = reader.ReadSingle(), + Y = reader.ReadSingle(), + Z = reader.ReadSingle(), + W = reader.ReadSingle() + }; + return q; + } + + public static Vector2 ReadVector2(this BinaryReader reader) + { + Vector2 v = new Vector2 + { + X = reader.ReadSingle(), + Y = reader.ReadSingle() + }; + return v; + } + + public static Vector3 ReadVector3(this BinaryReader reader) + { + var v = new Vector3 + { + X = reader.ReadSingle(), + Y = reader.ReadSingle(), + Z = reader.ReadSingle() + }; + return v; + } + + public static Vector4 ReadVector4(this BinaryReader reader) + { + var v = new Vector4 + { + X = reader.ReadSingle(), + Y = reader.ReadSingle(), + Z = reader.ReadSingle(), + W = reader.ReadSingle() + }; + return v; + } + + private static T[] ReadArray(Func del, int length) + { + var array = new T[length]; + for (int i = 0; i < array.Length; i++) + { + array[i] = del(); + } + return array; + } + + public static int[] ReadInt32Array(this BinaryReader reader, int length) + { + return ReadArray(reader.ReadInt32, length); + } + + public static uint[] ReadUInt32Array(this BinaryReader reader, int length) + { + return ReadArray(reader.ReadUInt32, length); + } + + public static float[] ReadSingleArray(this BinaryReader reader, int length) + { + return ReadArray(reader.ReadSingle, length); + } + + public static Vector2[] ReadVector2Array(this BinaryReader reader, int length) + { + return ReadArray(reader.ReadVector2, length); + } + + public static Vector4[] ReadVector4Array(this BinaryReader reader, int length) + { + return ReadArray(reader.ReadVector4, length); + } + } +} diff --git a/AssetStudio/StudioClasses/BinaryWriterExtensions.cs b/AssetStudio/StudioClasses/BinaryWriterExtensions.cs new file mode 100644 index 0000000..017d077 --- /dev/null +++ b/AssetStudio/StudioClasses/BinaryWriterExtensions.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace AssetStudio +{ + public static class BinaryWriterExtensions + { + private static void WriteArray(Action del, T[] array) + { + foreach (var item in array) + { + del(item); + } + } + + public static void Write(this BinaryWriter writer, uint[] array) + { + WriteArray(writer.Write, array); + } + } +} diff --git a/AssetStudio/StudioClasses/ClassStruct.cs b/AssetStudio/StudioClasses/ClassStruct.cs index 303dc9e..47f2d5e 100644 --- a/AssetStudio/StudioClasses/ClassStruct.cs +++ b/AssetStudio/StudioClasses/ClassStruct.cs @@ -41,7 +41,7 @@ namespace AssetStudio { public static string ViewStruct(this AssetPreloadData asset) { - var reader = asset.Reader; + var reader = asset.InitReader(); if (asset.sourceFile.ClassStructures.TryGetValue(asset.Type1, out var classStructure)) { var sb = new StringBuilder(); @@ -108,7 +108,7 @@ namespace AssetStudio break; case "string": append = false; - var str = reader.ReadAlignedString(reader.ReadInt32()); + var str = reader.ReadAlignedString(); sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str); i += 3;//skip break; diff --git a/AssetStudio/StudioClasses/EndianBinaryReader.cs b/AssetStudio/StudioClasses/EndianBinaryReader.cs index 751a834..1ee5197 100644 --- a/AssetStudio/StudioClasses/EndianBinaryReader.cs +++ b/AssetStudio/StudioClasses/EndianBinaryReader.cs @@ -115,38 +115,5 @@ namespace AssetStudio } return base.ReadDouble(); } - - public string ReadASCII(int length) - { - return Encoding.ASCII.GetString(ReadBytes(length)); - } - - public void AlignStream(int alignment) - { - var pos = BaseStream.Position; - var mod = pos % alignment; - if (mod != 0) { BaseStream.Position += alignment - mod; } - } - - public string ReadAlignedString(int length) - { - if (length > 0 && length < (BaseStream.Length - BaseStream.Position)) - { - var stringData = ReadBytes(length); - var result = Encoding.UTF8.GetString(stringData); - AlignStream(4); - return result; - } - return ""; - } - - public string ReadStringToNull() - { - var bytes = new List(); - byte b; - while (BaseStream.Position != BaseStream.Length && (b = ReadByte()) != 0) - bytes.Add(b); - return Encoding.UTF8.GetString(bytes.ToArray()); - } } } diff --git a/AssetStudio/StudioClasses/Exporter.cs b/AssetStudio/StudioClasses/Exporter.cs index 04f7c71..cc33be9 100644 --- a/AssetStudio/StudioClasses/Exporter.cs +++ b/AssetStudio/StudioClasses/Exporter.cs @@ -302,7 +302,7 @@ namespace AssetStudio var exportFullName = exportPath + asset.Text + asset.extension; if (ExportFileExists(exportFullName)) return false; - var bytes = asset.Reader.ReadBytes(asset.Size); + var bytes = asset.InitReader().ReadBytes(asset.Size); File.WriteAllBytes(exportFullName, bytes); return true; }