Refactor read assets

Generic PPtr
Misc
This commit is contained in:
Perfare
2018-11-21 15:37:56 +08:00
parent 8c749e21e1
commit bfaa207853
45 changed files with 1135 additions and 1055 deletions

View File

@ -62,6 +62,8 @@
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBit.cs" /> <Compile Include="7zip\Compress\RangeCoder\RangeCoderBit.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBitTree.cs" /> <Compile Include="7zip\Compress\RangeCoder\RangeCoderBitTree.cs" />
<Compile Include="7zip\ICoder.cs" /> <Compile Include="7zip\ICoder.cs" />
<Compile Include="Classes\RuntimeAnimatorController.cs" />
<Compile Include="ResourceReader.cs" />
<Compile Include="Utility\IImported.cs" /> <Compile Include="Utility\IImported.cs" />
<Compile Include="SerializedFile.cs" /> <Compile Include="SerializedFile.cs" />
<Compile Include="AssetsManager.cs" /> <Compile Include="AssetsManager.cs" />
@ -135,7 +137,6 @@
<Compile Include="Classes\PPtr.cs" /> <Compile Include="Classes\PPtr.cs" />
<Compile Include="Utility\Progress.cs" /> <Compile Include="Utility\Progress.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourcesHelper.cs" />
<Compile Include="SerializedFileHeader.cs" /> <Compile Include="SerializedFileHeader.cs" />
<Compile Include="SerializedType.cs" /> <Compile Include="SerializedType.cs" />
<Compile Include="SevenZipHelper.cs" /> <Compile Include="SevenZipHelper.cs" />

View File

@ -38,6 +38,7 @@ namespace AssetStudio
importFiles.Add(file); importFiles.Add(file);
importFilesHash.Add(Path.GetFileName(file).ToUpper()); importFilesHash.Add(Path.GetFileName(file).ToUpper());
} }
Progress.Reset(); Progress.Reset();
//use a for loop because list size can change //use a for loop because list size can change
for (var i = 0; i < importFiles.Count; i++) for (var i = 0; i < importFiles.Count; i++)
@ -45,9 +46,13 @@ namespace AssetStudio
LoadFile(importFiles[i]); LoadFile(importFiles[i]);
Progress.Report(i + 1, importFiles.Count); Progress.Report(i + 1, importFiles.Count);
} }
importFiles.Clear(); importFiles.Clear();
importFilesHash.Clear(); importFilesHash.Clear();
assetsfileListHash.Clear(); assetsfileListHash.Clear();
ReadAssets();
ProcessGameObject();
} }
private void LoadFile(string fullName) private void LoadFile(string fullName)
@ -118,7 +123,6 @@ namespace AssetStudio
var fileName = Path.GetFileName(fullName); var fileName = Path.GetFileName(fullName);
if (!assetsfileListHash.Contains(fileName.ToUpper())) if (!assetsfileListHash.Contains(fileName.ToUpper()))
{ {
Logger.Info($"Loading {fileName}");
var assetsFile = new SerializedFile(this, fullName, reader); var assetsFile = new SerializedFile(this, fullName, reader);
if (assetsFile.valid) if (assetsFile.valid)
{ {
@ -127,6 +131,7 @@ namespace AssetStudio
{ {
assetsFile.SetVersion(unityVersion); assetsFile.SetVersion(unityVersion);
} }
assetsFileList.Add(assetsFile); assetsFileList.Add(assetsFile);
assetsfileListHash.Add(assetsFile.upperFileName); assetsfileListHash.Add(assetsFile.upperFileName);
} }
@ -140,7 +145,7 @@ namespace AssetStudio
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null) private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
{ {
var fileName = Path.GetFileName(fullName); var fileName = Path.GetFileName(fullName);
Logger.Info("Decompressing " + fileName); Logger.Info("Loading " + fileName);
var bundleFile = new BundleFile(reader, fullName); var bundleFile = new BundleFile(reader, fullName);
reader.Dispose(); reader.Dispose();
foreach (var file in bundleFile.fileList) foreach (var file in bundleFile.fileList)
@ -178,15 +183,166 @@ namespace AssetStudio
{ {
foreach (var assetsFile in assetsFileList) foreach (var assetsFile in assetsFileList)
{ {
assetsFile.Objects.Clear();
assetsFile.reader.Close(); assetsFile.reader.Close();
} }
assetsFileList.Clear(); assetsFileList.Clear();
foreach (var resourceFileReader in resourceFileReaders) foreach (var resourceFileReader in resourceFileReaders)
{ {
resourceFileReader.Value.Close(); resourceFileReader.Value.Close();
} }
resourceFileReaders.Clear(); resourceFileReaders.Clear();
assetsFileIndexCache.Clear(); assetsFileIndexCache.Clear();
} }
private void ReadAssets()
{
Logger.Info("Read assets...");
var progressCount = assetsFileList.Sum(x => x.m_Objects.Count);
int i = 0;
Progress.Reset();
foreach (var assetsFile in assetsFileList)
{
assetsFile.Objects = new Dictionary<long, Object>(assetsFile.m_Objects.Count);
foreach (var objectInfo in assetsFile.m_Objects)
{
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
switch (objectReader.type)
{
case ClassIDType.Animation:
assetsFile.Objects.Add(objectInfo.m_PathID, new Animation(objectReader));
break;
case ClassIDType.AnimationClip:
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimationClip(objectReader));
break;
case ClassIDType.Animator:
assetsFile.Objects.Add(objectInfo.m_PathID, new Animator(objectReader));
break;
case ClassIDType.AnimatorController:
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimatorController(objectReader));
break;
case ClassIDType.AnimatorOverrideController:
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimatorOverrideController(objectReader));
break;
case ClassIDType.AssetBundle:
assetsFile.Objects.Add(objectInfo.m_PathID, new AssetBundle(objectReader));
break;
case ClassIDType.AudioClip:
assetsFile.Objects.Add(objectInfo.m_PathID, new AudioClip(objectReader));
break;
case ClassIDType.Avatar:
assetsFile.Objects.Add(objectInfo.m_PathID, new Avatar(objectReader));
break;
case ClassIDType.Font:
assetsFile.Objects.Add(objectInfo.m_PathID, new Font(objectReader));
break;
case ClassIDType.GameObject:
assetsFile.Objects.Add(objectInfo.m_PathID, new GameObject(objectReader));
break;
case ClassIDType.Material:
assetsFile.Objects.Add(objectInfo.m_PathID, new Material(objectReader));
break;
case ClassIDType.Mesh:
assetsFile.Objects.Add(objectInfo.m_PathID, new Mesh(objectReader));
break;
case ClassIDType.MeshFilter:
assetsFile.Objects.Add(objectInfo.m_PathID, new MeshFilter(objectReader));
break;
case ClassIDType.MeshRenderer:
assetsFile.Objects.Add(objectInfo.m_PathID, new MeshRenderer(objectReader));
break;
case ClassIDType.MonoBehaviour:
assetsFile.Objects.Add(objectInfo.m_PathID, new MonoBehaviour(objectReader));
break;
case ClassIDType.MonoScript:
assetsFile.Objects.Add(objectInfo.m_PathID, new MonoScript(objectReader));
break;
case ClassIDType.MovieTexture:
assetsFile.Objects.Add(objectInfo.m_PathID, new MovieTexture(objectReader));
break;
case ClassIDType.PlayerSettings:
assetsFile.Objects.Add(objectInfo.m_PathID, new PlayerSettings(objectReader));
break;
case ClassIDType.RectTransform:
assetsFile.Objects.Add(objectInfo.m_PathID, new RectTransform(objectReader));
break;
case ClassIDType.Shader:
assetsFile.Objects.Add(objectInfo.m_PathID, new Shader(objectReader));
break;
case ClassIDType.SkinnedMeshRenderer:
assetsFile.Objects.Add(objectInfo.m_PathID, new SkinnedMeshRenderer(objectReader));
break;
case ClassIDType.Sprite:
assetsFile.Objects.Add(objectInfo.m_PathID, new Sprite(objectReader));
break;
case ClassIDType.SpriteAtlas:
assetsFile.Objects.Add(objectInfo.m_PathID, new SpriteAtlas(objectReader));
break;
case ClassIDType.TextAsset:
assetsFile.Objects.Add(objectInfo.m_PathID, new TextAsset(objectReader));
break;
case ClassIDType.Texture2D:
assetsFile.Objects.Add(objectInfo.m_PathID, new Texture2D(objectReader));
break;
case ClassIDType.Transform:
assetsFile.Objects.Add(objectInfo.m_PathID, new Transform(objectReader));
break;
case ClassIDType.VideoClip:
assetsFile.Objects.Add(objectInfo.m_PathID, new VideoClip(objectReader));
break;
default:
assetsFile.Objects.Add(objectInfo.m_PathID, new Object(objectReader));
break;
}
Progress.Report(++i, progressCount);
}
}
}
private void ProcessGameObject()
{
Logger.Info("Process GameObject...");
foreach (var assetsFile in assetsFileList)
{
foreach (var obj in assetsFile.Objects.Values)
{
if (obj is GameObject m_GameObject)
{
foreach (var pptr in m_GameObject.m_Components)
{
if (pptr.TryGet(out var m_Component))
{
switch (m_Component)
{
case Transform m_Transform:
m_GameObject.m_Transform = m_Transform;
break;
case MeshRenderer m_MeshRenderer:
m_GameObject.m_MeshRenderer = m_MeshRenderer;
break;
case MeshFilter m_MeshFilter:
m_GameObject.m_MeshFilter = m_MeshFilter;
break;
case SkinnedMeshRenderer m_SkinnedMeshRenderer:
m_GameObject.m_SkinnedMeshRenderer = m_SkinnedMeshRenderer;
break;
case Animator m_Animator:
m_GameObject.m_Animator = m_Animator;
break;
case Animation m_Animation:
m_GameObject.m_Animation = m_Animation;
break;
}
}
}
}
}
}
}
} }
} }

View File

@ -7,16 +7,16 @@ namespace AssetStudio
{ {
public sealed class Animation : Behaviour public sealed class Animation : Behaviour
{ {
public List<PPtr> m_Animations; public List<PPtr<AnimationClip>> m_Animations;
public Animation(ObjectReader reader) : base(reader) public Animation(ObjectReader reader) : base(reader)
{ {
var m_Animation = reader.ReadPPtr(); var m_Animation = new PPtr<AnimationClip>(reader);
int numAnimations = reader.ReadInt32(); int numAnimations = reader.ReadInt32();
m_Animations = new List<PPtr>(numAnimations); m_Animations = new List<PPtr<AnimationClip>>(numAnimations);
for (int i = 0; i < numAnimations; i++) for (int i = 0; i < numAnimations; i++)
{ {
m_Animations.Add(reader.ReadPPtr()); m_Animations.Add(new PPtr<AnimationClip>(reader));
} }
} }
} }

View File

@ -293,7 +293,7 @@ namespace AssetStudio
public string attribute; public string attribute;
public string path; public string path;
public int classID; public int classID;
public PPtr script; public PPtr<MonoScript> script;
public FloatCurve(ObjectReader reader) public FloatCurve(ObjectReader reader)
@ -302,20 +302,20 @@ namespace AssetStudio
attribute = reader.ReadAlignedString(); attribute = reader.ReadAlignedString();
path = reader.ReadAlignedString(); path = reader.ReadAlignedString();
classID = reader.ReadInt32(); classID = reader.ReadInt32();
script = reader.ReadPPtr(); script = new PPtr<MonoScript>(reader);
} }
} }
public class PPtrKeyframe public class PPtrKeyframe
{ {
public float time; public float time;
public PPtr value; public PPtr<Object> value;
public PPtrKeyframe(ObjectReader reader) public PPtrKeyframe(ObjectReader reader)
{ {
time = reader.ReadSingle(); time = reader.ReadSingle();
value = reader.ReadPPtr(); value = new PPtr<Object>(reader);
} }
} }
@ -325,7 +325,7 @@ namespace AssetStudio
public string attribute; public string attribute;
public string path; public string path;
public int classID; public int classID;
public PPtr script; public PPtr<MonoScript> script;
public PPtrCurve(ObjectReader reader) public PPtrCurve(ObjectReader reader)
@ -340,7 +340,7 @@ namespace AssetStudio
attribute = reader.ReadAlignedString(); attribute = reader.ReadAlignedString();
path = reader.ReadAlignedString(); path = reader.ReadAlignedString();
classID = reader.ReadInt32(); classID = reader.ReadInt32();
script = reader.ReadPPtr(); script = new PPtr<MonoScript>(reader);
} }
} }
@ -757,7 +757,7 @@ namespace AssetStudio
{ {
public uint path; public uint path;
public uint attribute; public uint attribute;
public PPtr script; public PPtr<Object> script;
public ClassIDType typeID; public ClassIDType typeID;
public byte customType; public byte customType;
public byte isPPtrCurve; public byte isPPtrCurve;
@ -767,7 +767,7 @@ namespace AssetStudio
var version = reader.version; var version = reader.version;
path = reader.ReadUInt32(); path = reader.ReadUInt32();
attribute = reader.ReadUInt32(); attribute = reader.ReadUInt32();
script = reader.ReadPPtr(); script = new PPtr<Object>(reader);
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{ {
typeID = (ClassIDType)reader.ReadInt32(); typeID = (ClassIDType)reader.ReadInt32();
@ -785,7 +785,7 @@ namespace AssetStudio
public class AnimationClipBindingConstant public class AnimationClipBindingConstant
{ {
public List<GenericBinding> genericBindings; public List<GenericBinding> genericBindings;
public List<PPtr> pptrCurveMapping; public List<PPtr<Object>> pptrCurveMapping;
public AnimationClipBindingConstant(ObjectReader reader) public AnimationClipBindingConstant(ObjectReader reader)
{ {
@ -797,10 +797,10 @@ namespace AssetStudio
} }
int numMappings = reader.ReadInt32(); int numMappings = reader.ReadInt32();
pptrCurveMapping = new List<PPtr>(numMappings); pptrCurveMapping = new List<PPtr<Object>>(numMappings);
for (int i = 0; i < numMappings; i++) for (int i = 0; i < numMappings; i++)
{ {
pptrCurveMapping.Add(reader.ReadPPtr()); pptrCurveMapping.Add(new PPtr<Object>(reader));
} }
} }

View File

@ -7,14 +7,14 @@ namespace AssetStudio
{ {
public sealed class Animator : Behaviour public sealed class Animator : Behaviour
{ {
public PPtr m_Avatar; public PPtr<Avatar> m_Avatar;
public PPtr m_Controller; public PPtr<RuntimeAnimatorController> m_Controller;
public bool m_HasTransformHierarchy; public bool m_HasTransformHierarchy;
public Animator(ObjectReader reader) : base(reader) public Animator(ObjectReader reader) : base(reader)
{ {
m_Avatar = reader.ReadPPtr(); m_Avatar = new PPtr<Avatar>(reader);
m_Controller = reader.ReadPPtr(); m_Controller = new PPtr<RuntimeAnimatorController>(reader);
var m_CullingMode = reader.ReadInt32(); var m_CullingMode = reader.ReadInt32();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up

View File

@ -531,9 +531,9 @@ namespace AssetStudio
} }
} }
public sealed class AnimatorController : NamedObject public sealed class AnimatorController : RuntimeAnimatorController
{ {
public PPtr[] m_AnimationClips; public PPtr<AnimationClip>[] m_AnimationClips;
public AnimatorController(ObjectReader reader) : base(reader) public AnimatorController(ObjectReader reader) : base(reader)
{ {
@ -548,10 +548,10 @@ namespace AssetStudio
} }
int numClips = reader.ReadInt32(); int numClips = reader.ReadInt32();
m_AnimationClips = new PPtr[numClips]; m_AnimationClips = new PPtr<AnimationClip>[numClips];
for (int i = 0; i < numClips; i++) for (int i = 0; i < numClips; i++)
{ {
m_AnimationClips[i] = reader.ReadPPtr(); m_AnimationClips[i] = new PPtr<AnimationClip>(reader);
} }
} }
} }

View File

@ -7,24 +7,24 @@ namespace AssetStudio
{ {
public class AnimationClipOverride public class AnimationClipOverride
{ {
public PPtr m_OriginalClip; public PPtr<AnimationClip> m_OriginalClip;
public PPtr m_OverrideClip; public PPtr<AnimationClip> m_OverrideClip;
public AnimationClipOverride(ObjectReader reader) public AnimationClipOverride(ObjectReader reader)
{ {
m_OriginalClip = reader.ReadPPtr(); m_OriginalClip = new PPtr<AnimationClip>(reader);
m_OverrideClip = reader.ReadPPtr(); m_OverrideClip = new PPtr<AnimationClip>(reader);
} }
} }
public class AnimatorOverrideController : NamedObject public sealed class AnimatorOverrideController : RuntimeAnimatorController
{ {
public PPtr m_Controller; public PPtr<RuntimeAnimatorController> m_Controller;
public List<AnimationClipOverride> m_Clips; public List<AnimationClipOverride> m_Clips;
public AnimatorOverrideController(ObjectReader reader) : base(reader) public AnimatorOverrideController(ObjectReader reader) : base(reader)
{ {
m_Controller = reader.ReadPPtr(); m_Controller = new PPtr<RuntimeAnimatorController>(reader);
int numOverrides = reader.ReadInt32(); int numOverrides = reader.ReadInt32();
m_Clips = new List<AnimationClipOverride>(numOverrides); m_Clips = new List<AnimationClipOverride>(numOverrides);

View File

@ -9,28 +9,28 @@ namespace AssetStudio
{ {
public int preloadIndex; public int preloadIndex;
public int preloadSize; public int preloadSize;
public PPtr asset; public PPtr<Object> asset;
public AssetInfo(ObjectReader reader) public AssetInfo(ObjectReader reader)
{ {
preloadIndex = reader.ReadInt32(); preloadIndex = reader.ReadInt32();
preloadSize = reader.ReadInt32(); preloadSize = reader.ReadInt32();
asset = reader.ReadPPtr(); asset = new PPtr<Object>(reader);
} }
} }
public sealed class AssetBundle : NamedObject public sealed class AssetBundle : NamedObject
{ {
public List<PPtr> m_PreloadTable; public List<PPtr<Object>> m_PreloadTable;
public List<KeyValuePair<string, AssetInfo>> m_Container; public List<KeyValuePair<string, AssetInfo>> m_Container;
public AssetBundle(ObjectReader reader) : base(reader) public AssetBundle(ObjectReader reader) : base(reader)
{ {
var m_PreloadTableSize = reader.ReadInt32(); var m_PreloadTableSize = reader.ReadInt32();
m_PreloadTable = new List<PPtr>(m_PreloadTableSize); m_PreloadTable = new List<PPtr<Object>>(m_PreloadTableSize);
for (int i = 0; i < m_PreloadTableSize; i++) for (int i = 0; i < m_PreloadTableSize; i++)
{ {
m_PreloadTable.Add(reader.ReadPPtr()); m_PreloadTable.Add(new PPtr<Object>(reader));
} }
var m_ContainerSize = reader.ReadInt32(); var m_ContainerSize = reader.ReadInt32();

View File

@ -29,9 +29,9 @@ namespace AssetStudio
public string m_Source; public string m_Source;
public long m_Offset; public long m_Offset;
public long m_Size; public long m_Size;
public byte[] m_AudioData; public Lazy<byte[]> m_AudioData;
public AudioClip(ObjectReader reader, bool readData) : base(reader) public AudioClip(ObjectReader reader) : base(reader)
{ {
if (version[0] < 5) if (version[0] < 5)
{ {
@ -49,7 +49,7 @@ namespace AssetStudio
if (reader.byteSize + reader.byteStart - reader.Position != tsize) if (reader.byteSize + reader.byteStart - reader.Position != tsize)
{ {
m_Offset = reader.ReadInt32(); m_Offset = reader.ReadInt32();
m_Source = sourceFile.fullName + ".resS"; m_Source = assetsFile.fullName + ".resS";
} }
} }
else else
@ -79,18 +79,16 @@ namespace AssetStudio
m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32(); m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32();
} }
if (readData) ResourceReader resourceReader;
{
if (!string.IsNullOrEmpty(m_Source)) if (!string.IsNullOrEmpty(m_Source))
{ {
m_AudioData = ResourcesHelper.GetData(m_Source, sourceFile, m_Offset, (int)m_Size); resourceReader = new ResourceReader(m_Source, assetsFile, m_Offset, (int)m_Size);
} }
else else
{ {
if (m_Size > 0) resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
m_AudioData = reader.ReadBytes((int)m_Size);
}
} }
m_AudioData = new Lazy<byte[]>(resourceReader.GetData);
} }
} }

View File

@ -7,11 +7,11 @@ namespace AssetStudio
{ {
public abstract class Component : EditorExtension public abstract class Component : EditorExtension
{ {
public PPtr m_GameObject; public PPtr<GameObject> m_GameObject;
protected Component(ObjectReader reader) : base(reader) protected Component(ObjectReader reader) : base(reader)
{ {
m_GameObject = reader.ReadPPtr(); m_GameObject = new PPtr<GameObject>(reader);
} }
} }
} }

View File

@ -11,8 +11,8 @@ namespace AssetStudio
{ {
if (platform == BuildTarget.NoTarget) if (platform == BuildTarget.NoTarget)
{ {
var m_PrefabParentObject = reader.ReadPPtr(); var m_PrefabParentObject = new PPtr<EditorExtension>(reader);
var m_PrefabInternal = reader.ReadPPtr(); var m_PrefabInternal = new PPtr<Object>(reader); //PPtr<Prefab>
} }
} }
} }

View File

@ -14,9 +14,9 @@ namespace AssetStudio
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5 and up if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5 and up
{ {
var m_LineSpacing = reader.ReadSingle(); var m_LineSpacing = reader.ReadSingle();
var m_DefaultMaterial = reader.ReadPPtr(); var m_DefaultMaterial = new PPtr<Material>(reader);
var m_FontSize = reader.ReadSingle(); var m_FontSize = reader.ReadSingle();
var m_Texture = reader.ReadPPtr(); var m_Texture = new PPtr<Texture>(reader);
int m_AsciiStartOffset = reader.ReadInt32(); int m_AsciiStartOffset = reader.ReadInt32();
var m_Tracking = reader.ReadSingle(); var m_Tracking = reader.ReadSingle();
var m_CharacterSpacing = reader.ReadInt32(); var m_CharacterSpacing = reader.ReadInt32();
@ -68,7 +68,7 @@ namespace AssetStudio
} }
int m_ConvertCase = reader.ReadInt32(); int m_ConvertCase = reader.ReadInt32();
PPtr m_DefaultMaterial = reader.ReadPPtr(); var m_DefaultMaterial = new PPtr<Material>(reader);
int m_CharacterRects_size = reader.ReadInt32(); int m_CharacterRects_size = reader.ReadInt32();
for (int i = 0; i < m_CharacterRects_size; i++) for (int i = 0; i < m_CharacterRects_size; i++)
@ -93,7 +93,7 @@ namespace AssetStudio
} }
} }
PPtr m_Texture = reader.ReadPPtr(); var m_Texture = new PPtr<Texture>(reader);
int m_KerningValues_size = reader.ReadInt32(); int m_KerningValues_size = reader.ReadInt32();
for (int i = 0; i < m_KerningValues_size; i++) for (int i = 0; i < m_KerningValues_size; i++)

View File

@ -7,28 +7,30 @@ namespace AssetStudio
{ {
public sealed class GameObject : EditorExtension public sealed class GameObject : EditorExtension
{ {
public List<PPtr> m_Components; public List<PPtr<Component>> m_Components;
public string m_Name; public string m_Name;
public PPtr m_Transform;
public PPtr m_MeshRenderer; public Transform m_Transform;
public PPtr m_MeshFilter; public MeshRenderer m_MeshRenderer;
public PPtr m_SkinnedMeshRenderer; public MeshFilter m_MeshFilter;
public PPtr m_Animator; public SkinnedMeshRenderer m_SkinnedMeshRenderer;
public Animator m_Animator;
public Animation m_Animation;
public GameObject(ObjectReader reader) : base(reader) public GameObject(ObjectReader reader) : base(reader)
{ {
int m_Component_size = reader.ReadInt32(); int m_Component_size = reader.ReadInt32();
m_Components = new List<PPtr>(m_Component_size); m_Components = new List<PPtr<Component>>(m_Component_size);
for (int j = 0; j < m_Component_size; j++) for (int j = 0; j < m_Component_size; j++)
{ {
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5.0 and up if ((version[0] == 5 && version[1] >= 5) || version[0] > 5) //5.5.0 and up
{ {
m_Components.Add(reader.ReadPPtr()); m_Components.Add(new PPtr<Component>(reader));
} }
else else
{ {
int first = reader.ReadInt32(); int first = reader.ReadInt32();
m_Components.Add(reader.ReadPPtr()); m_Components.Add(new PPtr<Component>(reader));
} }
} }

View File

@ -8,7 +8,7 @@ namespace AssetStudio
public class TexEnv public class TexEnv
{ {
public string name; public string name;
public PPtr m_Texture; public PPtr<Texture> m_Texture;
public float[] m_Scale; public float[] m_Scale;
public float[] m_Offset; public float[] m_Offset;
} }
@ -27,7 +27,7 @@ namespace AssetStudio
public sealed class Material : NamedObject public sealed class Material : NamedObject
{ {
public PPtr m_Shader; public PPtr<Shader> m_Shader;
public string[] m_ShaderKeywords; public string[] m_ShaderKeywords;
public int m_CustomRenderQueue; public int m_CustomRenderQueue;
public TexEnv[] m_TexEnvs; public TexEnv[] m_TexEnvs;
@ -36,7 +36,7 @@ namespace AssetStudio
public Material(ObjectReader reader) : base(reader) public Material(ObjectReader reader) : base(reader)
{ {
m_Shader = reader.ReadPPtr(); m_Shader = new PPtr<Shader>(reader);
if (version[0] == 4 && (version[1] >= 2 || (version[1] == 1 && !buildType.IsAlpha))) if (version[0] == 4 && (version[1] >= 2 || (version[1] == 1 && !buildType.IsAlpha)))
{ {
@ -84,7 +84,7 @@ namespace AssetStudio
TexEnv m_TexEnv = new TexEnv() TexEnv m_TexEnv = new TexEnv()
{ {
name = reader.ReadAlignedString(), name = reader.ReadAlignedString(),
m_Texture = reader.ReadPPtr(), m_Texture = new PPtr<Texture>(reader),
m_Scale = new[] { reader.ReadSingle(), reader.ReadSingle() }, m_Scale = new[] { reader.ReadSingle(), reader.ReadSingle() },
m_Offset = new[] { reader.ReadSingle(), reader.ReadSingle() } m_Offset = new[] { reader.ReadSingle(), reader.ReadSingle() }
}; };

View File

@ -351,7 +351,7 @@ namespace AssetStudio
bool m_IsReadable = reader.ReadBoolean(); bool m_IsReadable = reader.ReadBoolean();
bool m_KeepVertices = reader.ReadBoolean(); bool m_KeepVertices = reader.ReadBoolean();
bool m_KeepIndices = reader.ReadBoolean(); bool m_KeepIndices = reader.ReadBoolean();
if (reader.HasStructMember("m_UsedForStaticMeshColliderOnly")) if (HasStructMember("m_UsedForStaticMeshColliderOnly"))
{ {
var m_UsedForStaticMeshColliderOnly = reader.ReadBoolean(); var m_UsedForStaticMeshColliderOnly = reader.ReadBoolean();
} }

View File

@ -8,11 +8,11 @@ namespace AssetStudio
public sealed class MeshFilter : Component public sealed class MeshFilter : Component
{ {
public long preloadIndex; public long preloadIndex;
public PPtr m_Mesh; public PPtr<Mesh> m_Mesh;
public MeshFilter(ObjectReader reader) : base(reader) public MeshFilter(ObjectReader reader) : base(reader)
{ {
m_Mesh = reader.ReadPPtr(); m_Mesh = new PPtr<Mesh>(reader);
} }
} }
} }

View File

@ -7,12 +7,12 @@ namespace AssetStudio
{ {
public sealed class MonoBehaviour : Behaviour public sealed class MonoBehaviour : Behaviour
{ {
public PPtr m_Script; public PPtr<MonoScript> m_Script;
public string m_Name; public string m_Name;
public MonoBehaviour(ObjectReader reader) : base(reader) public MonoBehaviour(ObjectReader reader) : base(reader)
{ {
m_Script = reader.ReadPPtr(); m_Script = new PPtr<MonoScript>(reader);
m_Name = reader.ReadAlignedString(); m_Name = reader.ReadAlignedString();
} }
} }

View File

@ -8,13 +8,13 @@ namespace AssetStudio
public sealed class MovieTexture : Texture public sealed class MovieTexture : Texture
{ {
public byte[] m_MovieData; public byte[] m_MovieData;
public PPtr<AudioClip> m_AudioClip;
public MovieTexture(ObjectReader reader) : base(reader) public MovieTexture(ObjectReader reader) : base(reader)
{ {
var m_Loop = reader.ReadBoolean(); var m_Loop = reader.ReadBoolean();
reader.AlignStream(4); reader.AlignStream(4);
//PPtr<AudioClip> m_AudioClip = new PPtr<AudioClip>(reader);
reader.ReadPPtr();
m_MovieData = reader.ReadBytes(reader.ReadInt32()); m_MovieData = reader.ReadBytes(reader.ReadInt32());
} }
} }

View File

@ -9,7 +9,7 @@ namespace AssetStudio
{ {
public string m_Name; public string m_Name;
public NamedObject(ObjectReader reader) : base(reader) protected NamedObject(ObjectReader reader) : base(reader)
{ {
m_Name = reader.ReadAlignedString(); m_Name = reader.ReadAlignedString();
} }

View File

@ -5,27 +5,58 @@ using System.Text;
namespace AssetStudio namespace AssetStudio
{ {
public abstract class Object public class Object
{ {
protected SerializedFile sourceFile; public SerializedFile assetsFile;
public ObjectReader reader; public ObjectReader reader;
public long m_PathID;
public int[] version; public int[] version;
protected BuildType buildType; protected BuildType buildType;
public BuildTarget platform; public BuildTarget platform;
public ClassIDType type;
public SerializedType serializedType;
public uint byteSize;
protected Object(ObjectReader reader) public Object(ObjectReader reader)
{ {
this.reader = reader; this.reader = reader;
reader.Reset(); reader.Reset();
sourceFile = reader.assetsFile; assetsFile = reader.assetsFile;
type = reader.type;
m_PathID = reader.m_PathID;
version = reader.version; version = reader.version;
buildType = reader.buildType; buildType = reader.buildType;
platform = reader.platform; platform = reader.platform;
serializedType = reader.serializedType;
byteSize = reader.byteSize;
if (platform == BuildTarget.NoTarget) if (platform == BuildTarget.NoTarget)
{ {
var m_ObjectHideFlags = reader.ReadUInt32(); var m_ObjectHideFlags = reader.ReadUInt32();
} }
} }
protected bool HasStructMember(string name)
{
return serializedType?.m_Nodes != null && serializedType.m_Nodes.Any(x => x.m_Name == name);
}
public string Dump()
{
reader.Reset();
if (serializedType?.m_Nodes != null)
{
var sb = new StringBuilder();
TypeTreeHelper.ReadTypeString(sb, serializedType.m_Nodes, reader);
return sb.ToString();
}
return null;
}
public byte[] GetRawData()
{
reader.Reset();
return reader.ReadBytes((int)byteSize);
}
} }
} }

View File

@ -1,12 +1,19 @@
namespace AssetStudio namespace AssetStudio
{ {
public class PPtr public sealed class PPtr<T> where T : Object
{ {
public int m_FileID; public int m_FileID;
public long m_PathID; public long m_PathID;
public SerializedFile assetsFile; private SerializedFile assetsFile;
public int index = -2; //-2 - Prepare, -1 - Missing private int index = -2; //-2 - Prepare, -1 - Missing
public PPtr(ObjectReader reader)
{
m_FileID = reader.ReadInt32();
m_PathID = reader.m_Version < 14 ? reader.ReadInt32() : reader.ReadInt64();
assetsFile = reader.assetsFile;
}
private bool TryGetAssetsFile(out SerializedFile result) private bool TryGetAssetsFile(out SerializedFile result)
{ {
@ -20,7 +27,7 @@
if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count) if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count)
{ {
var assetsManager = assetsFile.assetsManager; var assetsManager = assetsFile.assetsManager;
var assetsfileList = assetsManager.assetsFileList; var assetsFileList = assetsManager.assetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache; var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (index == -2) if (index == -2)
@ -29,14 +36,14 @@
var name = m_External.fileName.ToUpper(); var name = m_External.fileName.ToUpper();
if (!assetsFileIndexCache.TryGetValue(name, out index)) if (!assetsFileIndexCache.TryGetValue(name, out index))
{ {
index = assetsfileList.FindIndex(x => x.upperFileName == name); index = assetsFileList.FindIndex(x => x.upperFileName == name);
assetsFileIndexCache.Add(name, index); assetsFileIndexCache.Add(name, index);
} }
} }
if (index >= 0) if (index >= 0)
{ {
result = assetsfileList[index]; result = assetsFileList[index];
return true; return true;
} }
} }
@ -44,45 +51,39 @@
return false; return false;
} }
public bool TryGet(out ObjectReader result) public bool TryGet(out T result)
{ {
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
{
if (obj is T variable)
{
result = variable;
return true;
}
}
}
result = null; result = null;
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.ObjectReaders.TryGetValue(m_PathID, out result))
{
return true;
}
}
return false; return false;
} }
public bool TryGetTransform(out Transform m_Transform) public bool TryGet<T2>(out T2 result) where T2 : Object
{ {
if (TryGetAssetsFile(out var sourceFile)) if (TryGetAssetsFile(out var sourceFile))
{ {
if (sourceFile.Transforms.TryGetValue(m_PathID, out m_Transform)) if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
{ {
if (obj is T2 variable)
{
result = variable;
return true; return true;
} }
} }
m_Transform = null;
return false;
} }
public bool TryGetGameObject(out GameObject m_GameObject) result = null;
{
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.GameObjects.TryGetValue(m_PathID, out m_GameObject))
{
return true;
}
}
m_GameObject = null;
return false; return false;
} }
} }

View File

@ -13,7 +13,7 @@ namespace AssetStudio
public abstract class Renderer : Component public abstract class Renderer : Component
{ {
public PPtr[] m_Materials; public PPtr<Material>[] m_Materials;
public StaticBatchInfo m_StaticBatchInfo; public StaticBatchInfo m_StaticBatchInfo;
public uint[] m_SubsetIndices; public uint[] m_SubsetIndices;
@ -51,10 +51,10 @@ namespace AssetStudio
reader.Position += 16;//Vector4f m_LightmapTilingOffsetDynamic reader.Position += 16;//Vector4f m_LightmapTilingOffsetDynamic
} }
m_Materials = new PPtr[reader.ReadInt32()]; m_Materials = new PPtr<Material>[reader.ReadInt32()];
for (int m = 0; m < m_Materials.Length; m++) for (int m = 0; m < m_Materials.Length; m++)
{ {
m_Materials[m] = reader.ReadPPtr(); m_Materials[m] = new PPtr<Material>(reader);
} }
if (version[0] < 3) if (version[0] < 3)
@ -77,12 +77,12 @@ namespace AssetStudio
m_SubsetIndices = reader.ReadUInt32Array(numSubsetIndices); m_SubsetIndices = reader.ReadUInt32Array(numSubsetIndices);
} }
var m_StaticBatchRoot = reader.ReadPPtr(); var m_StaticBatchRoot = new PPtr<Transform>(reader);
if ((version[0] == 5 && version[1] >= 4) || version[0] > 5)//5.4.0 and up if ((version[0] == 5 && version[1] >= 4) || version[0] > 5)//5.4.0 and up
{ {
var m_ProbeAnchor = reader.ReadPPtr(); var m_ProbeAnchor = new PPtr<Transform>(reader);
var m_LightProbeVolumeOverride = reader.ReadPPtr(); var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader);
} }
else if (version[0] >= 4 || (version[0] == 3 && version[1] >= 5))//3.5 - 5.3 else if (version[0] >= 4 || (version[0] == 3 && version[1] >= 5))//3.5 - 5.3
{ {
@ -92,7 +92,7 @@ namespace AssetStudio
{ {
int m_ReflectionProbeUsage = reader.ReadInt32(); int m_ReflectionProbeUsage = reader.ReadInt32();
} }
var m_LightProbeAnchor = reader.ReadPPtr(); var m_LightProbeAnchor = new PPtr<Transform>(reader);
} }
if (version[0] >= 5 || (version[0] == 4 && version[1] >= 3))//4.3 and up if (version[0] >= 5 || (version[0] == 4 && version[1] >= 3))//4.3 and up

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public abstract class RuntimeAnimatorController : NamedObject
{
protected RuntimeAnimatorController(ObjectReader reader) : base(reader)
{
}
}
}

View File

@ -7,8 +7,8 @@ namespace AssetStudio
{ {
public sealed class SkinnedMeshRenderer : Renderer public sealed class SkinnedMeshRenderer : Renderer
{ {
public PPtr m_Mesh; public PPtr<Mesh> m_Mesh;
public PPtr[] m_Bones; public PPtr<Transform>[] m_Bones;
public List<float> m_BlendShapeWeights; public List<float> m_BlendShapeWeights;
public SkinnedMeshRenderer(ObjectReader reader) : base(reader) public SkinnedMeshRenderer(ObjectReader reader) : base(reader)
@ -20,15 +20,15 @@ namespace AssetStudio
if (version[0] == 2 && version[1] < 6)//2.6 down if (version[0] == 2 && version[1] < 6)//2.6 down
{ {
var m_DisableAnimationWhenOffscreen = reader.ReadPPtr(); var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader);
} }
m_Mesh = reader.ReadPPtr(); m_Mesh = new PPtr<Mesh>(reader);
m_Bones = new PPtr[reader.ReadInt32()]; m_Bones = new PPtr<Transform>[reader.ReadInt32()];
for (int b = 0; b < m_Bones.Length; b++) for (int b = 0; b < m_Bones.Length; b++)
{ {
m_Bones[b] = reader.ReadPPtr(); m_Bones[b] = new PPtr<Transform>(reader);
} }
if (version[0] < 3) if (version[0] < 3)

View File

@ -50,8 +50,8 @@ namespace AssetStudio
public float m_PixelsToUnits; public float m_PixelsToUnits;
public Vector2 m_Pivot; public Vector2 m_Pivot;
public Tuple<Guid, long> m_RenderDataKey; public Tuple<Guid, long> m_RenderDataKey;
public PPtr texture; public PPtr<Texture2D> texture;
public PPtr m_SpriteAtlas; public PPtr<SpriteAtlas> m_SpriteAtlas;
public RectangleF textureRect; public RectangleF textureRect;
public SpriteSettings settingsRaw; public SpriteSettings settingsRaw;
public PointF[][] m_PhysicsShape; //Vector2[][] public PointF[][] m_PhysicsShape; //Vector2[][]
@ -98,16 +98,16 @@ namespace AssetStudio
} }
//PPtr<SpriteAtlas> m_SpriteAtlas //PPtr<SpriteAtlas> m_SpriteAtlas
m_SpriteAtlas = reader.ReadPPtr(); m_SpriteAtlas = new PPtr<SpriteAtlas>(reader);
} }
//SpriteRenderData m_RD //SpriteRenderData m_RD
// PPtr<Texture2D> texture // PPtr<Texture2D> texture
texture = reader.ReadPPtr(); texture = new PPtr<Texture2D>(reader);
// PPtr<Texture2D> alphaTexture // PPtr<Texture2D> alphaTexture
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
{ {
var alphaTexture = reader.ReadPPtr(); var alphaTexture = new PPtr<Texture2D>(reader);
} }
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up

View File

@ -9,8 +9,8 @@ namespace AssetStudio
{ {
public class SpriteAtlasData public class SpriteAtlasData
{ {
public PPtr texture; public PPtr<Texture2D> texture;
public PPtr alphaTexture; public PPtr<Texture2D> alphaTexture;
public System.Drawing.RectangleF textureRect; public System.Drawing.RectangleF textureRect;
public Vector2 textureRectOffset; public Vector2 textureRectOffset;
public Vector2 atlasRectOffset; public Vector2 atlasRectOffset;
@ -21,8 +21,8 @@ namespace AssetStudio
public SpriteAtlasData(ObjectReader reader) public SpriteAtlasData(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
texture = reader.ReadPPtr(); texture = new PPtr<Texture2D>(reader);
alphaTexture = reader.ReadPPtr(); alphaTexture = new PPtr<Texture2D>(reader);
textureRect = reader.ReadRectangleF(); textureRect = reader.ReadRectangleF();
textureRectOffset = reader.ReadVector2(); textureRectOffset = reader.ReadVector2();
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
@ -44,7 +44,7 @@ namespace AssetStudio
var m_PackedSpritesSize = reader.ReadInt32(); var m_PackedSpritesSize = reader.ReadInt32();
for (int i = 0; i < m_PackedSpritesSize; i++) for (int i = 0; i < m_PackedSpritesSize; i++)
{ {
reader.ReadPPtr(); //PPtr<Sprite> data new PPtr<Sprite>(reader);
} }
var m_PackedSpriteNamesToIndexSize = reader.ReadInt32(); var m_PackedSpriteNamesToIndexSize = reader.ReadInt32();

View File

@ -28,13 +28,13 @@ namespace AssetStudio
public int m_ColorSpace; public int m_ColorSpace;
//image dataa //image dataa
public int image_data_size; public int image_data_size;
public byte[] image_data; public Lazy<byte[]> image_data;
//m_StreamData //m_StreamData
public uint offset; public uint offset;
public uint size; public uint size;
public string path; public string path;
public Texture2D(ObjectReader reader, bool readData) : base(reader) public Texture2D(ObjectReader reader) : base(reader)
{ {
m_Width = reader.ReadInt32(); m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32(); m_Height = reader.ReadInt32();
@ -58,11 +58,11 @@ namespace AssetStudio
{ {
var m_StreamingMipmapsPriority = reader.ReadInt32(); var m_StreamingMipmapsPriority = reader.ReadInt32();
} }
else if (reader.HasStructMember("m_StreamingMipmapsPriority")) //will fix in some patch version bundle else if (HasStructMember("m_StreamingMipmapsPriority")) //will fix in some patch version bundle
{ {
var m_StreamingMipmapsPriority = reader.ReadInt32(); var m_StreamingMipmapsPriority = reader.ReadInt32();
} }
if (reader.HasStructMember("m_StreamingGroupID")) //What the hell is this? if (HasStructMember("m_StreamingGroupID")) //What the hell is this?
{ {
var m_StreamingGroupID = reader.ReadUInt32(); var m_StreamingGroupID = reader.ReadUInt32();
} }
@ -101,17 +101,16 @@ namespace AssetStudio
path = reader.ReadAlignedString(); path = reader.ReadAlignedString();
} }
if (readData) ResourceReader resourceReader;
{
if (!string.IsNullOrEmpty(path)) if (!string.IsNullOrEmpty(path))
{ {
image_data = ResourcesHelper.GetData(path, sourceFile, offset, image_data_size); resourceReader = new ResourceReader(path, assetsFile, offset, image_data_size);
} }
else else
{ {
image_data = reader.ReadBytes(image_data_size); resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
}
} }
image_data = new Lazy<byte[]>(resourceReader.GetData);
} }
} }

View File

@ -11,8 +11,8 @@ namespace AssetStudio
public float[] m_LocalRotation; public float[] m_LocalRotation;
public float[] m_LocalPosition; public float[] m_LocalPosition;
public float[] m_LocalScale; public float[] m_LocalScale;
public List<PPtr> m_Children; public List<PPtr<Transform>> m_Children;
public PPtr m_Father; public PPtr<Transform> m_Father;
public Transform(ObjectReader reader) : base(reader) public Transform(ObjectReader reader) : base(reader)
{ {
@ -20,12 +20,12 @@ namespace AssetStudio
m_LocalPosition = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }; m_LocalPosition = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
m_LocalScale = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }; m_LocalScale = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
int m_ChildrenCount = reader.ReadInt32(); int m_ChildrenCount = reader.ReadInt32();
m_Children = new List<PPtr>(m_ChildrenCount); m_Children = new List<PPtr<Transform>>(m_ChildrenCount);
for (int j = 0; j < m_ChildrenCount; j++) for (int j = 0; j < m_ChildrenCount; j++)
{ {
m_Children.Add(reader.ReadPPtr()); m_Children.Add(new PPtr<Transform>(reader));
} }
m_Father = reader.ReadPPtr(); m_Father = new PPtr<Transform>(reader);
} }
} }
} }

View File

@ -8,12 +8,12 @@ namespace AssetStudio
{ {
public sealed class VideoClip : NamedObject public sealed class VideoClip : NamedObject
{ {
public byte[] m_VideoData; public Lazy<byte[]> m_VideoData;
public string m_OriginalPath; public string m_OriginalPath;
public string m_Source; public string m_Source;
public ulong m_Size; public ulong m_Size;
public VideoClip(ObjectReader reader, bool readData) : base(reader) public VideoClip(ObjectReader reader) : base(reader)
{ {
m_OriginalPath = reader.ReadAlignedString(); m_OriginalPath = reader.ReadAlignedString();
var m_ProxyWidth = reader.ReadUInt32(); var m_ProxyWidth = reader.ReadUInt32();
@ -47,18 +47,16 @@ namespace AssetStudio
m_Size = reader.ReadUInt64(); m_Size = reader.ReadUInt64();
var m_HasSplitAlpha = reader.ReadBoolean(); var m_HasSplitAlpha = reader.ReadBoolean();
if (readData) ResourceReader resourceReader;
{
if (!string.IsNullOrEmpty(m_Source)) if (!string.IsNullOrEmpty(m_Source))
{ {
m_VideoData = ResourcesHelper.GetData(m_Source, sourceFile, (long)m_Offset, (int)m_Size); resourceReader = new ResourceReader(m_Source, assetsFile, (long)m_Offset, (int)m_Size);
} }
else else
{ {
if (m_Size > 0) resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
m_VideoData = reader.ReadBytes((int)m_Size);
}
} }
m_VideoData = new Lazy<byte[]>(resourceReader.GetData);
} }
} }
} }

View File

@ -11,9 +11,7 @@ namespace AssetStudio
public uint byteSize; public uint byteSize;
public int typeID; public int typeID;
public int classID; public int classID;
public ushort isDestroyed;
//custom
public long m_PathID; public long m_PathID;
public SerializedType serializedType; public SerializedType serializedType;
} }

View File

@ -15,7 +15,7 @@ namespace AssetStudio
public ClassIDType type; public ClassIDType type;
public SerializedType serializedType; public SerializedType serializedType;
public BuildTarget platform; public BuildTarget platform;
private uint m_Version; public uint m_Version;
public int[] version => assetsFile.version; public int[] version => assetsFile.version;
public BuildType buildType => assetsFile.buildType; public BuildType buildType => assetsFile.buildType;
@ -43,38 +43,5 @@ namespace AssetStudio
{ {
Position = byteStart; Position = byteStart;
} }
public string Dump()
{
Reset();
if (serializedType?.m_Nodes != null)
{
var sb = new StringBuilder();
TypeTreeHelper.ReadTypeString(sb, serializedType.m_Nodes, this);
return sb.ToString();
}
return null;
}
public bool HasStructMember(string name)
{
return serializedType?.m_Nodes != null && serializedType.m_Nodes.Any(x => x.m_Name == name);
}
public PPtr ReadPPtr()
{
return new PPtr
{
m_FileID = ReadInt32(),
m_PathID = m_Version < 14 ? ReadInt32() : ReadInt64(),
assetsFile = assetsFile
};
}
public byte[] GetRawData()
{
Reset();
return ReadBytes((int)byteSize);
}
} }
} }

View File

@ -0,0 +1,69 @@
using System.IO;
namespace AssetStudio
{
public class ResourceReader
{
private bool needSearch;
private string path;
private SerializedFile assetsFile;
private long offset;
private int size;
private BinaryReader reader;
public ResourceReader(string path, SerializedFile assetsFile, long offset, int size)
{
needSearch = true;
this.path = path;
this.assetsFile = assetsFile;
this.offset = offset;
this.size = size;
}
public ResourceReader(BinaryReader reader, long offset, int size)
{
this.reader = reader;
this.offset = offset;
this.size = size;
}
public byte[] GetData()
{
if (needSearch)
{
var resourceFileName = Path.GetFileName(path);
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader))
{
reader.Position = offset;
return reader.ReadBytes(size);
}
var currentDirectory = Path.GetDirectoryName(assetsFile.fullName);
var resourceFilePath = currentDirectory + "\\" + resourceFileName;
if (!File.Exists(resourceFilePath))
{
var findFiles = Directory.GetFiles(currentDirectory, resourceFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
resourceFilePath = findFiles[0];
}
}
if (File.Exists(resourceFilePath))
{
using (var resourceReader = new BinaryReader(File.OpenRead(resourceFilePath)))
{
resourceReader.BaseStream.Position = offset;
return resourceReader.ReadBytes(size);
}
}
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
}
reader.BaseStream.Position = offset;
return reader.ReadBytes(size);
}
}
}

View File

@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace AssetStudio
{
internal static class ResourcesHelper
{
public static byte[] GetData(string path, SerializedFile assetsFile, long offset, int size)
{
var resourceFileName = Path.GetFileName(path);
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader))
{
reader.Position = offset;
return reader.ReadBytes(size);
}
var currentDirectory = Path.GetDirectoryName(assetsFile.fullName);
var resourceFilePath = currentDirectory + "\\" + resourceFileName;
if (!File.Exists(resourceFilePath))
{
var findFiles = Directory.GetFiles(currentDirectory, resourceFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
resourceFilePath = findFiles[0];
}
}
if (File.Exists(resourceFilePath))
{
using (var resourceReader = new BinaryReader(File.OpenRead(resourceFilePath)))
{
resourceReader.BaseStream.Position = offset;
return resourceReader.ReadBytes(size);
}
}
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
}
}
}

View File

@ -17,9 +17,7 @@ namespace AssetStudio
public int[] version = { 0, 0, 0, 0 }; public int[] version = { 0, 0, 0, 0 };
public BuildType buildType; public BuildType buildType;
public bool valid; public bool valid;
public Dictionary<long, ObjectReader> ObjectReaders = new Dictionary<long, ObjectReader>(); public Dictionary<long, Object> Objects;
public Dictionary<long, GameObject> GameObjects = new Dictionary<long, GameObject>();
public Dictionary<long, Transform> Transforms = new Dictionary<long, Transform>();
public SerializedFileHeader header; public SerializedFileHeader header;
private EndianType m_FileEndianess; private EndianType m_FileEndianess;
@ -27,7 +25,7 @@ namespace AssetStudio
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform; public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
private bool m_EnableTypeTree = true; private bool m_EnableTypeTree = true;
public List<SerializedType> m_Types; public List<SerializedType> m_Types;
private List<ObjectInfo> m_Objects; public List<ObjectInfo> m_Objects;
private List<LocalSerializedObjectIdentifier> m_ScriptTypes; private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
public List<FileIdentifier> m_Externals; public List<FileIdentifier> m_Externals;
@ -118,7 +116,7 @@ namespace AssetStudio
{ {
objectInfo.classID = reader.ReadUInt16(); objectInfo.classID = reader.ReadUInt16();
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID); objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
objectInfo.isDestroyed = reader.ReadUInt16(); var isDestroyed = reader.ReadUInt16();
} }
else else
{ {
@ -131,10 +129,6 @@ namespace AssetStudio
var stripped = reader.ReadByte(); var stripped = reader.ReadByte();
} }
m_Objects.Add(objectInfo); m_Objects.Add(objectInfo);
//Create Reader
var objectReader = new ObjectReader(reader, this, objectInfo);
ObjectReaders.Add(objectInfo.m_PathID, objectReader);
} }
if (header.m_Version >= 11) if (header.m_Version >= 11)

View File

@ -8,7 +8,7 @@ namespace AssetStudio
{ {
public static class TypeTreeHelper public static class TypeTreeHelper
{ {
public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, EndianBinaryReader reader) public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader)
{ {
for (int i = 0; i < members.Count; i++) for (int i = 0; i < members.Count; i++)
{ {
@ -16,7 +16,7 @@ namespace AssetStudio
} }
} }
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> members, EndianBinaryReader reader, ref int i) private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader, ref int i)
{ {
var member = members[i]; var member = members[i];
var level = member.m_Level; var level = member.m_Level;
@ -153,7 +153,7 @@ namespace AssetStudio
reader.AlignStream(4); reader.AlignStream(4);
} }
public static Dictionary<string, object> ReadBoxingType(List<TypeTreeNode> members, EndianBinaryReader reader) public static Dictionary<string, object> ReadBoxingType(List<TypeTreeNode> members, BinaryReader reader)
{ {
var obj = new Dictionary<string, object>(); var obj = new Dictionary<string, object>();
for (int i = 0; i < members.Count; i++) for (int i = 0; i < members.Count; i++)
@ -165,7 +165,7 @@ namespace AssetStudio
return obj; return obj;
} }
private static object ReadValue(List<TypeTreeNode> members, EndianBinaryReader reader, ref int i) private static object ReadValue(List<TypeTreeNode> members, BinaryReader reader, ref int i)
{ {
var member = members[i]; var member = members[i];
var level = member.m_Level; var level = member.m_Level;

View File

@ -15,6 +15,8 @@ using OpenTK;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using AssetStudio; using AssetStudio;
using static AssetStudioGUI.Studio; using static AssetStudioGUI.Studio;
using Object = AssetStudio.Object;
using Font = AssetStudio.Font;
namespace AssetStudioGUI namespace AssetStudioGUI
{ {
@ -134,13 +136,13 @@ namespace AssetStudioGUI
} }
var productName = string.Empty; var productName = string.Empty;
var tempDic = new Dictionary<ObjectReader, AssetItem>(); var tempDic = new Dictionary<Object, AssetItem>();
if (!dontLoadAssetsMenuItem.Checked) if (!dontLoadAssetsMenuItem.Checked)
{ {
BuildAssetList(tempDic, displayAll.Checked, displayOriginalName.Checked, out productName); BuildAssetList(tempDic, displayAll.Checked, displayOriginalName.Checked, out productName);
} }
List<GameObjectTreeNode> treeNodeCollection = null; List<TreeNode> treeNodeCollection = null;
if (!dontBuildHierarchyMenuItem.Checked) if (!dontBuildHierarchyMenuItem.Checked)
{ {
treeNodeCollection = BuildTreeStructure(tempDic); treeNodeCollection = BuildTreeStructure(tempDic);
@ -651,97 +653,140 @@ namespace AssetStudioGUI
} }
} }
private void PreviewAsset(AssetItem asset) private void PreviewAsset(AssetItem assetItem)
{ {
var reader = asset.reader;
try try
{ {
switch (asset.Type) switch (assetItem.Asset)
{ {
case ClassIDType.Texture2D: case Texture2D m_Texture2D:
PreviewTexture2D(assetItem, m_Texture2D);
break;
case AudioClip m_AudioClip:
PreviewAudioClip(assetItem, m_AudioClip);
break;
case Shader m_Shader:
PreviewShader(m_Shader);
break;
case TextAsset m_TextAsset:
PreviewTextAsset(m_TextAsset);
break;
case MonoBehaviour m_MonoBehaviour:
PreviewMonoBehaviour(m_MonoBehaviour);
break;
case Font m_Font:
PreviewFont(m_Font);
break;
case Mesh m_Mesh:
PreviewMesh(m_Mesh);
break;
case VideoClip _:
case MovieTexture _:
StatusStripUpdate("Only supported export.");
break;
case Sprite m_Sprite:
PreviewSprite(assetItem, m_Sprite);
break;
case Animator _:
StatusStripUpdate("Can be exported to FBX file.");
break;
case AnimationClip _:
StatusStripUpdate("Can be exported with Animator or Objects");
break;
default:
var str = assetItem.Asset.Dump();
if (str != null)
{ {
imageTexture?.Dispose(); textPreviewBox.Text = str;
var m_Texture2D = new Texture2D(reader, true); textPreviewBox.Visible = true;
}
else
{
StatusStripUpdate("Only supported export the raw file.");
}
break;
}
}
catch (Exception e)
{
MessageBox.Show($"Preview {assetItem.Type}:{assetItem.Text} error\r\n{e.Message}\r\n{e.StackTrace}");
}
}
//Info private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D)
asset.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}"; {
var converter = new Texture2DConverter(m_Texture2D);
var bitmap = converter.ConvertToBitmap(true);
if (bitmap != null)
{
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
switch (m_Texture2D.m_FilterMode) switch (m_Texture2D.m_FilterMode)
{ {
case 0: asset.InfoText += "\nFilter Mode: Point "; break; case 0: assetItem.InfoText += "\nFilter Mode: Point "; break;
case 1: asset.InfoText += "\nFilter Mode: Bilinear "; break; case 1: assetItem.InfoText += "\nFilter Mode: Bilinear "; break;
case 2: asset.InfoText += "\nFilter Mode: Trilinear "; break; case 2: assetItem.InfoText += "\nFilter Mode: Trilinear "; break;
} }
asset.InfoText += $"\nAnisotropic level: {m_Texture2D.m_Aniso}\nMip map bias: {m_Texture2D.m_MipBias}"; assetItem.InfoText += $"\nAnisotropic level: {m_Texture2D.m_Aniso}\nMip map bias: {m_Texture2D.m_MipBias}";
switch (m_Texture2D.m_WrapMode) switch (m_Texture2D.m_WrapMode)
{ {
case 0: asset.InfoText += "\nWrap mode: Repeat"; break; case 0: assetItem.InfoText += "\nWrap mode: Repeat"; break;
case 1: asset.InfoText += "\nWrap mode: Clamp"; break; case 1: assetItem.InfoText += "\nWrap mode: Clamp"; break;
} }
var converter = new Texture2DConverter(m_Texture2D); PreviewTexture(bitmap);
imageTexture = converter.ConvertToBitmap(true);
if (imageTexture != null)
{
previewPanel.BackgroundImage = imageTexture;
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
else
previewPanel.BackgroundImageLayout = ImageLayout.Center;
} }
else else
{ {
StatusStripUpdate("Unsupported image for preview"); StatusStripUpdate("Unsupported image for preview");
} }
break;
} }
case ClassIDType.AudioClip:
{
var m_AudioClip = new AudioClip(reader, true);
private void PreviewAudioClip(AssetItem assetItem, AudioClip m_AudioClip)
{
//Info //Info
asset.InfoText = "Compression format: "; assetItem.InfoText = "Compression format: ";
if (m_AudioClip.version[0] < 5) if (m_AudioClip.version[0] < 5)
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case AudioType.ACC: case AudioType.ACC:
asset.InfoText += "Acc"; assetItem.InfoText += "Acc";
break; break;
case AudioType.AIFF: case AudioType.AIFF:
asset.InfoText += "AIFF"; assetItem.InfoText += "AIFF";
break; break;
case AudioType.IT: case AudioType.IT:
asset.InfoText += "Impulse tracker"; assetItem.InfoText += "Impulse tracker";
break; break;
case AudioType.MOD: case AudioType.MOD:
asset.InfoText += "Protracker / Fasttracker MOD"; assetItem.InfoText += "Protracker / Fasttracker MOD";
break; break;
case AudioType.MPEG: case AudioType.MPEG:
asset.InfoText += "MP2/MP3 MPEG"; assetItem.InfoText += "MP2/MP3 MPEG";
break; break;
case AudioType.OGGVORBIS: case AudioType.OGGVORBIS:
asset.InfoText += "Ogg vorbis"; assetItem.InfoText += "Ogg vorbis";
break; break;
case AudioType.S3M: case AudioType.S3M:
asset.InfoText += "ScreamTracker 3"; assetItem.InfoText += "ScreamTracker 3";
break; break;
case AudioType.WAV: case AudioType.WAV:
asset.InfoText += "Microsoft WAV"; assetItem.InfoText += "Microsoft WAV";
break; break;
case AudioType.XM: case AudioType.XM:
asset.InfoText += "FastTracker 2 XM"; assetItem.InfoText += "FastTracker 2 XM";
break; break;
case AudioType.XMA: case AudioType.XMA:
asset.InfoText += "Xbox360 XMA"; assetItem.InfoText += "Xbox360 XMA";
break; break;
case AudioType.VAG: case AudioType.VAG:
asset.InfoText += "PlayStation Portable ADPCM"; assetItem.InfoText += "PlayStation Portable ADPCM";
break; break;
case AudioType.AUDIOQUEUE: case AudioType.AUDIOQUEUE:
asset.InfoText += "iPhone"; assetItem.InfoText += "iPhone";
break; break;
default: default:
asset.InfoText += "Unknown"; assetItem.InfoText += "Unknown";
break; break;
} }
} }
@ -750,50 +795,51 @@ namespace AssetStudioGUI
switch (m_AudioClip.m_CompressionFormat) switch (m_AudioClip.m_CompressionFormat)
{ {
case AudioCompressionFormat.PCM: case AudioCompressionFormat.PCM:
asset.InfoText += "PCM"; assetItem.InfoText += "PCM";
break; break;
case AudioCompressionFormat.Vorbis: case AudioCompressionFormat.Vorbis:
asset.InfoText += "Vorbis"; assetItem.InfoText += "Vorbis";
break; break;
case AudioCompressionFormat.ADPCM: case AudioCompressionFormat.ADPCM:
asset.InfoText += "ADPCM"; assetItem.InfoText += "ADPCM";
break; break;
case AudioCompressionFormat.MP3: case AudioCompressionFormat.MP3:
asset.InfoText += "MP3"; assetItem.InfoText += "MP3";
break; break;
case AudioCompressionFormat.VAG: case AudioCompressionFormat.VAG:
asset.InfoText += "PlayStation Portable ADPCM"; assetItem.InfoText += "PlayStation Portable ADPCM";
break; break;
case AudioCompressionFormat.HEVAG: case AudioCompressionFormat.HEVAG:
asset.InfoText += "PSVita ADPCM"; assetItem.InfoText += "PSVita ADPCM";
break; break;
case AudioCompressionFormat.XMA: case AudioCompressionFormat.XMA:
asset.InfoText += "Xbox360 XMA"; assetItem.InfoText += "Xbox360 XMA";
break; break;
case AudioCompressionFormat.AAC: case AudioCompressionFormat.AAC:
asset.InfoText += "AAC"; assetItem.InfoText += "AAC";
break; break;
case AudioCompressionFormat.GCADPCM: case AudioCompressionFormat.GCADPCM:
asset.InfoText += "Nintendo 3DS/Wii DSP"; assetItem.InfoText += "Nintendo 3DS/Wii DSP";
break; break;
case AudioCompressionFormat.ATRAC9: case AudioCompressionFormat.ATRAC9:
asset.InfoText += "PSVita ATRAC9"; assetItem.InfoText += "PSVita ATRAC9";
break; break;
default: default:
asset.InfoText += "Unknown"; assetItem.InfoText += "Unknown";
break; break;
} }
} }
if (m_AudioClip.m_AudioData == null) var m_AudioData = m_AudioClip.m_AudioData.Value;
break; if (m_AudioData == null || m_AudioData.Length == 0)
return;
FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO(); FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO();
exinfo.cbsize = Marshal.SizeOf(exinfo); exinfo.cbsize = Marshal.SizeOf(exinfo);
exinfo.length = (uint)m_AudioClip.m_Size; exinfo.length = (uint)m_AudioClip.m_Size;
var result = system.createSound(m_AudioClip.m_AudioData, FMOD.MODE.OPENMEMORY | loopMode, ref exinfo, out sound); var result = system.createSound(m_AudioData, FMOD.MODE.OPENMEMORY | loopMode, ref exinfo, out sound);
if (ERRCHECK(result)) { break; } if (ERRCHECK(result)) return;
result = sound.getSubSound(0, out var subsound); result = sound.getSubSound(0, out var subsound);
if (result == FMOD.RESULT.OK) if (result == FMOD.RESULT.OK)
@ -802,62 +848,44 @@ namespace AssetStudioGUI
} }
result = sound.getLength(out FMODlenms, FMOD.TIMEUNIT.MS); result = sound.getLength(out FMODlenms, FMOD.TIMEUNIT.MS);
if (ERRCHECK(result)) { break; } if (ERRCHECK(result)) return;
result = system.playSound(sound, null, true, out channel); result = system.playSound(sound, null, true, out channel);
if (ERRCHECK(result)) { break; } if (ERRCHECK(result)) return;
FMODpanel.Visible = true; FMODpanel.Visible = true;
result = channel.getFrequency(out var frequency); result = channel.getFrequency(out var frequency);
if (ERRCHECK(result)) { break; } if (ERRCHECK(result)) return;
FMODinfoLabel.Text = frequency + " Hz"; FMODinfoLabel.Text = frequency + " Hz";
FMODtimerLabel.Text = $"0:0.0 / {FMODlenms / 1000 / 60}:{FMODlenms / 1000 % 60}.{FMODlenms / 10 % 100}"; FMODtimerLabel.Text = $"0:0.0 / {FMODlenms / 1000 / 60}:{FMODlenms / 1000 % 60}.{FMODlenms / 10 % 100}";
break;
} }
case ClassIDType.Shader:
private void PreviewShader(Shader m_Shader)
{ {
var m_Shader = new Shader(reader);
var str = ShaderConverter.Convert(m_Shader); var str = ShaderConverter.Convert(m_Shader);
textPreviewBox.Text = str == null ? "Serialized Shader can't be read" : str.Replace("\n", "\r\n"); PreviewText(str == null ? "Serialized Shader can't be read" : str.Replace("\n", "\r\n"));
textPreviewBox.Visible = true;
break;
} }
case ClassIDType.TextAsset:
{
TextAsset m_TextAsset = new TextAsset(reader);
string m_Script_Text = Encoding.UTF8.GetString(m_TextAsset.m_Script); private void PreviewTextAsset(TextAsset m_TextAsset)
m_Script_Text = Regex.Replace(m_Script_Text, "(?<!\r)\n", "\r\n"); {
textPreviewBox.Text = m_Script_Text; var text = Encoding.UTF8.GetString(m_TextAsset.m_Script);
textPreviewBox.Visible = true; PreviewText(text.Replace("\n", "\r\n"));
}
break; private void PreviewMonoBehaviour(MonoBehaviour m_MonoBehaviour)
}
case ClassIDType.MonoBehaviour:
{ {
if (reader.serializedType?.m_Nodes != null) PreviewText(m_MonoBehaviour.Dump() ?? GetScriptString(m_MonoBehaviour.reader));
{
textPreviewBox.Text = reader.Dump();
} }
else
{
textPreviewBox.Text = GetScriptString(reader);
}
textPreviewBox.Visible = true;
break; private void PreviewFont(Font m_Font)
}
case ClassIDType.Font:
{ {
var m_Font = new AssetStudio.Font(reader);
if (m_Font.m_FontData != null) if (m_Font.m_FontData != null)
{ {
IntPtr data = Marshal.AllocCoTaskMem(m_Font.m_FontData.Length); var 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);
// We HAVE to do this to register the font to the system (Weird .NET bug !)
uint cFonts = 0; uint cFonts = 0;
var re = AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts); var re = AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts);
if (re != IntPtr.Zero) if (re != IntPtr.Zero)
@ -895,15 +923,14 @@ namespace AssetStudioGUI
fontPreviewBox.Visible = true; fontPreviewBox.Visible = true;
} }
} }
break; return;
} }
} }
StatusStripUpdate("Unsupported font for preview. Try to export."); StatusStripUpdate("Unsupported font for preview. Try to export.");
break;
} }
case ClassIDType.Mesh:
private void PreviewMesh(Mesh m_Mesh)
{ {
var m_Mesh = new Mesh(reader);
if (m_Mesh.m_VertexCount > 0) if (m_Mesh.m_VertexCount > 0)
{ {
viewMatrixData = Matrix4.CreateRotationY(-(float)Math.PI / 4) * Matrix4.CreateRotationX(-(float)Math.PI / 6); viewMatrixData = Matrix4.CreateRotationY(-(float)Math.PI / 4) * Matrix4.CreateRotationX(-(float)Math.PI / 6);
@ -1046,61 +1073,38 @@ namespace AssetStudioGUI
+ "'Mouse Left'=Rotate | 'Mouse Right'=Move | 'Mouse Wheel'=Zoom \n" + "'Mouse Left'=Rotate | 'Mouse Right'=Move | 'Mouse Wheel'=Zoom \n"
+ "'Ctrl W'=Wireframe | 'Ctrl S'=Shade | 'Ctrl N'=ReNormal "); + "'Ctrl W'=Wireframe | 'Ctrl S'=Shade | 'Ctrl N'=ReNormal ");
} }
break;
case ClassIDType.VideoClip: private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
case ClassIDType.MovieTexture:
{ {
StatusStripUpdate("Only supported export."); var bitmap = SpriteHelper.GetImageFromSprite(m_Sprite);
break; if (bitmap != null)
{
assetItem.InfoText = $"Width: {imageTexture.Width}\nHeight: {imageTexture.Height}\n";
PreviewTexture(bitmap);
} }
case ClassIDType.Sprite: else
{
StatusStripUpdate("Unsupported sprite for preview.");
}
}
private void PreviewTexture(Bitmap bitmap)
{ {
imageTexture?.Dispose(); imageTexture?.Dispose();
imageTexture = SpriteHelper.GetImageFromSprite(new Sprite(reader)); imageTexture = bitmap;
if (imageTexture != null)
{
asset.InfoText = $"Width: {imageTexture.Width}\nHeight: {imageTexture.Height}\n";
previewPanel.BackgroundImage = imageTexture; previewPanel.BackgroundImage = imageTexture;
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height) if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
previewPanel.BackgroundImageLayout = ImageLayout.Zoom; previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
else else
previewPanel.BackgroundImageLayout = ImageLayout.Center; previewPanel.BackgroundImageLayout = ImageLayout.Center;
} }
else
private void PreviewText(string text)
{ {
StatusStripUpdate("Unsupported sprite for preview."); textPreviewBox.Text = text;
}
break;
}
case ClassIDType.Animator:
{
StatusStripUpdate("Can be exported to FBX file.");
break;
}
case ClassIDType.AnimationClip:
{
StatusStripUpdate("Can be exported with Animator or objects");
break;
}
default:
{
var str = reader.Dump();
if (str != null)
{
textPreviewBox.Text = str;
textPreviewBox.Visible = true; textPreviewBox.Visible = true;
} }
else
StatusStripUpdate("Only supported export the raw file.");
break;
}
}
}
catch (Exception e)
{
MessageBox.Show($"Preview {asset.Type}:{asset.Text} error\r\n{e.Message}\r\n{e.StackTrace}");
}
}
private void FMODinit() private void FMODinit()
{ {
@ -1683,6 +1687,7 @@ namespace AssetStudioGUI
classesListView.Items.Clear(); classesListView.Items.Clear();
classesListView.Groups.Clear(); classesListView.Groups.Clear();
previewPanel.BackgroundImage = Properties.Resources.preview; previewPanel.BackgroundImage = Properties.Resources.preview;
imageTexture?.Dispose();
previewPanel.BackgroundImageLayout = ImageLayout.Center; previewPanel.BackgroundImageLayout = ImageLayout.Center;
assetInfoLabel.Visible = false; assetInfoLabel.Visible = false;
assetInfoLabel.Text = null; assetInfoLabel.Text = null;
@ -1757,7 +1762,7 @@ namespace AssetStudioGUI
private void showOriginalFileToolStripMenuItem_Click(object sender, EventArgs e) private void showOriginalFileToolStripMenuItem_Click(object sender, EventArgs e)
{ {
var selectasset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]]; var selectasset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];
var args = $"/select, \"{selectasset.sourceFile.originalPath ?? selectasset.sourceFile.fullName}\""; var args = $"/select, \"{selectasset.SourceFile.originalPath ?? selectasset.SourceFile.fullName}\"";
var pfi = new ProcessStartInfo("explorer.exe", args); var pfi = new ProcessStartInfo("explorer.exe", args);
Process.Start(pfi); Process.Start(pfi);
} }

View File

@ -5,21 +5,22 @@ namespace AssetStudioGUI
{ {
internal class AssetItem : ListViewItem internal class AssetItem : ListViewItem
{ {
public SerializedFile sourceFile; public Object Asset;
public ObjectReader reader; public SerializedFile SourceFile;
public long FullSize; public long FullSize;
public ClassIDType Type; public ClassIDType Type;
public string TypeString; public string TypeString;
public string InfoText; public string InfoText;
public string UniqueID; public string UniqueID;
public GameObjectTreeNode TreeNode; public GameObjectTreeNode TreeNode;
public AssetItem(ObjectReader reader) public AssetItem(Object asset)
{ {
sourceFile = reader.assetsFile; Asset = asset;
this.reader = reader; SourceFile = asset.assetsFile;
FullSize = reader.byteSize; FullSize = asset.byteSize;
Type = reader.type; Type = asset.type;
TypeString = Type.ToString(); TypeString = Type.ToString();
} }
} }

View File

@ -11,10 +11,7 @@ namespace AssetStudioGUI
{ {
public static bool ExportTexture2D(AssetItem item, string exportPathName) public static bool ExportTexture2D(AssetItem item, string exportPathName)
{ {
var m_Texture2D = new Texture2D(item.reader, true); var converter = new Texture2DConverter((Texture2D)item.Asset);
if (m_Texture2D.image_data == null || m_Texture2D.image_data.Length == 0)
return false;
var converter = new Texture2DConverter(m_Texture2D);
var convertTexture = (bool)Properties.Settings.Default["convertTexture"]; var convertTexture = (bool)Properties.Settings.Default["convertTexture"];
if (convertTexture) if (convertTexture)
{ {
@ -54,8 +51,9 @@ namespace AssetStudioGUI
public static bool ExportAudioClip(AssetItem item, string exportPath) public static bool ExportAudioClip(AssetItem item, string exportPath)
{ {
var m_AudioClip = new AudioClip(item.reader, true); var m_AudioClip = (AudioClip)item.Asset;
if (m_AudioClip.m_AudioData == null) var m_AudioData = m_AudioClip.m_AudioData.Value;
if (m_AudioData == null || m_AudioData.Length == 0)
return false; return false;
var convertAudio = (bool)Properties.Settings.Default["convertAudio"]; var convertAudio = (bool)Properties.Settings.Default["convertAudio"];
var converter = new AudioClipConverter(m_AudioClip); var converter = new AudioClipConverter(m_AudioClip);
@ -74,25 +72,24 @@ namespace AssetStudioGUI
var exportFullName = exportPath + item.Text + converter.GetExtensionName(); var exportFullName = exportPath + item.Text + converter.GetExtensionName();
if (ExportFileExists(exportFullName)) if (ExportFileExists(exportFullName))
return false; return false;
File.WriteAllBytes(exportFullName, m_AudioClip.m_AudioData); File.WriteAllBytes(exportFullName, m_AudioData);
} }
return true; return true;
} }
public static bool ExportShader(AssetItem item, string exportPath) public static bool ExportShader(AssetItem item, string exportPath)
{ {
var m_Shader = new Shader(item.reader);
var exportFullName = exportPath + item.Text + ".shader"; var exportFullName = exportPath + item.Text + ".shader";
if (ExportFileExists(exportFullName)) if (ExportFileExists(exportFullName))
return false; return false;
var str = ShaderConverter.Convert(m_Shader); var str = ShaderConverter.Convert((Shader)item.Asset);
File.WriteAllText(exportFullName, str ?? "Serialized Shader can't be read"); File.WriteAllText(exportFullName, str ?? "Serialized Shader can't be read");
return true; return true;
} }
public static bool ExportTextAsset(AssetItem item, string exportPath) public static bool ExportTextAsset(AssetItem item, string exportPath)
{ {
var m_TextAsset = new TextAsset(item.reader); var m_TextAsset = (TextAsset)(item.Asset);
var exportFullName = exportPath + item.Text + ".txt"; var exportFullName = exportPath + item.Text + ".txt";
if (ExportFileExists(exportFullName)) if (ExportFileExists(exportFullName))
return false; return false;
@ -105,23 +102,15 @@ namespace AssetStudioGUI
var exportFullName = exportPath + item.Text + ".txt"; var exportFullName = exportPath + item.Text + ".txt";
if (ExportFileExists(exportFullName)) if (ExportFileExists(exportFullName))
return false; return false;
var reader = item.reader; var m_MonoBehaviour = (MonoBehaviour)item.Asset;
string str; var str = m_MonoBehaviour.Dump() ?? Studio.GetScriptString(item.Asset.reader);
if (reader.serializedType?.m_Nodes != null)
{
str = reader.Dump();
}
else
{
str = Studio.GetScriptString(reader);
}
File.WriteAllText(exportFullName, str); File.WriteAllText(exportFullName, str);
return true; return true;
} }
public static bool ExportFont(AssetItem item, string exportPath) public static bool ExportFont(AssetItem item, string exportPath)
{ {
var m_Font = new Font(item.reader); var m_Font = (Font)item.Asset;
if (m_Font.m_FontData != null) if (m_Font.m_FontData != null)
{ {
var extension = ".ttf"; var extension = ".ttf";
@ -140,7 +129,7 @@ namespace AssetStudioGUI
public static bool ExportMesh(AssetItem item, string exportPath) public static bool ExportMesh(AssetItem item, string exportPath)
{ {
var m_Mesh = new Mesh(item.reader); var m_Mesh = (Mesh)item.Asset;
if (m_Mesh.m_VertexCount <= 0) if (m_Mesh.m_VertexCount <= 0)
return false; return false;
var exportFullName = exportPath + item.Text + ".obj"; var exportFullName = exportPath + item.Text + ".obj";
@ -221,13 +210,14 @@ namespace AssetStudioGUI
public static bool ExportVideoClip(AssetItem item, string exportPath) public static bool ExportVideoClip(AssetItem item, string exportPath)
{ {
var m_VideoClip = new VideoClip(item.reader, true); var m_VideoClip = (VideoClip)item.Asset;
if (m_VideoClip.m_VideoData != null) var m_VideoData = m_VideoClip.m_VideoData.Value;
if (m_VideoData != null && m_VideoData.Length != 0)
{ {
var exportFullName = exportPath + item.Text + Path.GetExtension(m_VideoClip.m_OriginalPath); var exportFullName = exportPath + item.Text + Path.GetExtension(m_VideoClip.m_OriginalPath);
if (ExportFileExists(exportFullName)) if (ExportFileExists(exportFullName))
return false; return false;
File.WriteAllBytes(exportFullName, m_VideoClip.m_VideoData); File.WriteAllBytes(exportFullName, m_VideoData);
return true; return true;
} }
return false; return false;
@ -235,7 +225,7 @@ namespace AssetStudioGUI
public static bool ExportMovieTexture(AssetItem item, string exportPath) public static bool ExportMovieTexture(AssetItem item, string exportPath)
{ {
var m_MovieTexture = new MovieTexture(item.reader); var m_MovieTexture = (MovieTexture)item.Asset;
var exportFullName = exportPath + item.Text + ".ogv"; var exportFullName = exportPath + item.Text + ".ogv";
if (ExportFileExists(exportFullName)) if (ExportFileExists(exportFullName))
return false; return false;
@ -262,7 +252,7 @@ namespace AssetStudioGUI
var exportFullName = exportPath + item.Text + "." + type.ToLower(); var exportFullName = exportPath + item.Text + "." + type.ToLower();
if (ExportFileExists(exportFullName)) if (ExportFileExists(exportFullName))
return false; return false;
var bitmap = SpriteHelper.GetImageFromSprite(new Sprite(item.reader)); var bitmap = SpriteHelper.GetImageFromSprite((Sprite)item.Asset);
if (bitmap != null) if (bitmap != null)
{ {
bitmap.Save(exportFullName, format); bitmap.Save(exportFullName, format);
@ -277,7 +267,7 @@ namespace AssetStudioGUI
var exportFullName = exportPath + item.Text + ".dat"; var exportFullName = exportPath + item.Text + ".dat";
if (ExportFileExists(exportFullName)) if (ExportFileExists(exportFullName))
return false; return false;
File.WriteAllBytes(exportFullName, item.reader.GetRawData()); File.WriteAllBytes(exportFullName, item.Asset.GetRawData());
return true; return true;
} }
@ -293,15 +283,15 @@ namespace AssetStudioGUI
public static bool ExportAnimator(AssetItem item, string exportPath, List<AssetItem> animationList = null) public static bool ExportAnimator(AssetItem item, string exportPath, List<AssetItem> animationList = null)
{ {
var m_Animator = new Animator(item.reader); var m_Animator = (Animator)item.Asset;
var convert = animationList != null ? new ModelConverter(m_Animator, animationList.Select(x => x.reader).ToArray()) : new ModelConverter(m_Animator); var convert = animationList != null ? new ModelConverter(m_Animator, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) : new ModelConverter(m_Animator);
exportPath = exportPath + item.Text + ".fbx"; exportPath = exportPath + item.Text + ".fbx";
return ExportFbx(convert, exportPath); return ExportFbx(convert, exportPath);
} }
public static bool ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null) public static bool ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
{ {
var convert = animationList != null ? new ModelConverter(gameObject, animationList.Select(x => x.reader).ToArray()) : new ModelConverter(gameObject); var convert = animationList != null ? new ModelConverter(gameObject, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) : new ModelConverter(gameObject);
exportPath = exportPath + Studio.FixFileName(gameObject.m_Name) + ".fbx"; exportPath = exportPath + Studio.FixFileName(gameObject.m_Name) + ".fbx";
return ExportFbx(convert, exportPath); return ExportFbx(convert, exportPath);
} }

View File

@ -9,6 +9,7 @@ using System.Windows.Forms;
using AssetStudio; using AssetStudio;
using dnlib.DotNet; using dnlib.DotNet;
using static AssetStudioGUI.Exporter; using static AssetStudioGUI.Exporter;
using Object = AssetStudio.Object;
namespace AssetStudioGUI namespace AssetStudioGUI
{ {
@ -92,114 +93,71 @@ namespace AssetStudioGUI
return extractedCount; return extractedCount;
} }
public static void BuildAssetList(Dictionary<ObjectReader, AssetItem> tempDic, bool displayAll, bool displayOriginalName, out string productName) public static void BuildAssetList(Dictionary<Object, AssetItem> tempDic, bool displayAll, bool displayOriginalName, out string productName)
{ {
Logger.Info("Building asset list..."); Logger.Info("Building asset list...");
productName = string.Empty; productName = string.Empty;
var assetsNameHash = new HashSet<string>(); var assetsNameHash = new HashSet<string>();
var progressCount = assetsManager.assetsFileList.Sum(x => x.ObjectReaders.Count); var progressCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
int j = 0; int j = 0;
Progress.Reset(); Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList) foreach (var assetsFile in assetsManager.assetsFileList)
{ {
var tempExportableAssets = new List<AssetItem>(); var tempExportableAssets = new List<AssetItem>();
AssetBundle ab = null; AssetBundle ab = null;
foreach (var objectReader in assetsFile.ObjectReaders.Values) foreach (var asset in assetsFile.Objects.Values)
{ {
var assetItem = new AssetItem(objectReader); var assetItem = new AssetItem(asset);
tempDic.Add(objectReader, assetItem); tempDic.Add(asset, assetItem);
assetItem.UniqueID = " #" + j; assetItem.UniqueID = " #" + j;
var exportable = false; var exportable = false;
switch (assetItem.Type) switch (asset)
{ {
case ClassIDType.GameObject: case GameObject m_GameObject:
{
var m_GameObject = new GameObject(objectReader);
assetItem.Text = m_GameObject.m_Name; assetItem.Text = m_GameObject.m_Name;
assetsFile.GameObjects.Add(objectReader.m_PathID, m_GameObject);
break; break;
} case Texture2D m_Texture2D:
case ClassIDType.Transform:
{
var m_Transform = new Transform(objectReader);
assetsFile.Transforms.Add(objectReader.m_PathID, m_Transform);
break;
}
case ClassIDType.RectTransform:
{
var m_Rect = new RectTransform(objectReader);
assetsFile.Transforms.Add(objectReader.m_PathID, m_Rect);
break;
}
case ClassIDType.Texture2D:
{
var m_Texture2D = new Texture2D(objectReader, false);
if (!string.IsNullOrEmpty(m_Texture2D.path)) if (!string.IsNullOrEmpty(m_Texture2D.path))
assetItem.FullSize = objectReader.byteSize + m_Texture2D.size; assetItem.FullSize = asset.byteSize + m_Texture2D.size;
assetItem.Text = m_Texture2D.m_Name; assetItem.Text = m_Texture2D.m_Name;
exportable = true; exportable = true;
break; break;
} case AudioClip m_AudioClip:
case ClassIDType.AudioClip:
{
var m_AudioClip = new AudioClip(objectReader, false);
if (!string.IsNullOrEmpty(m_AudioClip.m_Source)) if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
assetItem.FullSize = objectReader.byteSize + m_AudioClip.m_Size; assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size;
assetItem.Text = m_AudioClip.m_Name; assetItem.Text = m_AudioClip.m_Name;
exportable = true; exportable = true;
break; break;
} case VideoClip m_VideoClip:
case ClassIDType.VideoClip:
{
var m_VideoClip = new VideoClip(objectReader, false);
if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath)) if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath))
assetItem.FullSize = objectReader.byteSize + (long)m_VideoClip.m_Size; assetItem.FullSize = asset.byteSize + (long)m_VideoClip.m_Size;
assetItem.Text = m_VideoClip.m_Name; assetItem.Text = m_VideoClip.m_Name;
exportable = true; exportable = true;
break; break;
} case Shader m_Shader:
case ClassIDType.Shader:
{
var m_Shader = new Shader(objectReader);
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name; assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
exportable = true; exportable = true;
break; break;
} case Mesh _:
case ClassIDType.Mesh: case TextAsset _:
case ClassIDType.TextAsset: case AnimationClip _:
case ClassIDType.AnimationClip: case Font _:
case ClassIDType.Font: case MovieTexture _:
case ClassIDType.MovieTexture: case Sprite _:
case ClassIDType.Sprite: assetItem.Text = ((NamedObject)asset).m_Name;
{
var obj = new NamedObject(objectReader);
assetItem.Text = obj.m_Name;
exportable = true; exportable = true;
break; break;
} case Animator m_Animator:
case ClassIDType.Avatar: if (m_Animator.m_GameObject.TryGet(out var gameObject))
case ClassIDType.AnimatorController:
case ClassIDType.AnimatorOverrideController:
case ClassIDType.Material:
case ClassIDType.MonoScript:
case ClassIDType.SpriteAtlas:
{ {
var obj = new NamedObject(objectReader); assetItem.Text = gameObject.m_Name;
assetItem.Text = obj.m_Name;
break;
} }
case ClassIDType.Animator:
{
exportable = true; exportable = true;
break; break;
} case MonoBehaviour m_MonoBehaviour:
case ClassIDType.MonoBehaviour: if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{ {
var m_MonoBehaviour = new MonoBehaviour(objectReader);
if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var script))
{
var m_Script = new MonoScript(script);
assetItem.Text = m_Script.m_ClassName; assetItem.Text = m_Script.m_ClassName;
} }
else else
@ -208,19 +166,16 @@ namespace AssetStudioGUI
} }
exportable = true; exportable = true;
break; break;
} case PlayerSettings m_PlayerSettings:
case ClassIDType.PlayerSettings: productName = m_PlayerSettings.productName;
{
var plSet = new PlayerSettings(objectReader);
productName = plSet.productName;
break; break;
} case AssetBundle m_AssetBundle:
case ClassIDType.AssetBundle: ab = m_AssetBundle;
{
ab = new AssetBundle(objectReader);
assetItem.Text = ab.m_Name; assetItem.Text = ab.m_Name;
break; break;
} case NamedObject m_NamedObject:
assetItem.Text = m_NamedObject.m_Name;
break;
} }
if (assetItem.Text == "") if (assetItem.Text == "")
{ {
@ -247,18 +202,18 @@ namespace AssetStudioGUI
} }
if (displayOriginalName && ab != null) if (displayOriginalName && ab != null)
{ {
foreach (var asset in tempExportableAssets) foreach (var item in tempExportableAssets)
{ {
var originalPath = ab.m_Container.Find(y => y.Value.asset.m_PathID == asset.reader.m_PathID).Key; var originalPath = ab.m_Container.Find(y => y.Value.asset.m_PathID == item.Asset.m_PathID).Key;
if (!string.IsNullOrEmpty(originalPath)) if (!string.IsNullOrEmpty(originalPath))
{ {
var extension = Path.GetExtension(originalPath); var extension = Path.GetExtension(originalPath);
if (!string.IsNullOrEmpty(extension) && asset.Type == ClassIDType.TextAsset) if (!string.IsNullOrEmpty(extension) && item.Type == ClassIDType.TextAsset)
{ {
//asset.Extension = extension; //TODO //asset.Extension = extension; //TODO
} }
asset.Text = Path.GetDirectoryName(originalPath) + "\\" + asset.Text; item.Text = Path.GetDirectoryName(originalPath) + "\\" + item.Text;
} }
} }
} }
@ -270,21 +225,22 @@ namespace AssetStudioGUI
assetsNameHash.Clear(); assetsNameHash.Clear();
} }
public static List<GameObjectTreeNode> BuildTreeStructure(Dictionary<ObjectReader, AssetItem> tempDic) public static List<TreeNode> BuildTreeStructure(Dictionary<Object, AssetItem> tempDic)
{
var treeNodeCollection = new List<GameObjectTreeNode>();
var gameObjectCount = assetsManager.assetsFileList.Sum(x => x.GameObjects.Count);
if (gameObjectCount > 0)
{ {
Logger.Info("Building tree structure..."); Logger.Info("Building tree structure...");
var treeNodeCollection = new List<TreeNode>();
var treeNodeDictionary = new Dictionary<GameObject, GameObjectTreeNode>(); var treeNodeDictionary = new Dictionary<GameObject, GameObjectTreeNode>();
var progressCount = assetsManager.assetsFileList.Count;
int i = 0; int i = 0;
Progress.Reset(); Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList) foreach (var assetsFile in assetsManager.assetsFileList)
{ {
var fileNode = new GameObjectTreeNode(assetsFile.fileName); //RootNode var fileNode = new GameObjectTreeNode(assetsFile.fileName); //RootNode
foreach (var m_GameObject in assetsFile.GameObjects.Values) foreach (var obj in assetsFile.Objects.Values)
{
if (obj is GameObject m_GameObject)
{ {
if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode)) if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode))
{ {
@ -292,68 +248,31 @@ namespace AssetStudioGUI
treeNodeDictionary.Add(m_GameObject, currentNode); treeNodeDictionary.Add(m_GameObject, currentNode);
} }
foreach (var m_Component in m_GameObject.m_Components) if (m_GameObject.m_MeshFilter != null)
{ {
if (m_Component.TryGet(out var asset)) if (m_GameObject.m_MeshFilter.m_Mesh.TryGet(out var m_Mesh))
{ {
switch (asset.type) var item = tempDic[m_Mesh];
{
case ClassIDType.Transform:
{
m_GameObject.m_Transform = m_Component;
break;
}
case ClassIDType.MeshRenderer:
{
m_GameObject.m_MeshRenderer = m_Component;
break;
}
case ClassIDType.MeshFilter:
{
m_GameObject.m_MeshFilter = m_Component;
if (m_Component.TryGet(out var objectReader))
{
var m_MeshFilter = new MeshFilter(objectReader);
if (m_MeshFilter.m_Mesh.TryGet(out objectReader))
{
var item = tempDic[objectReader];
item.TreeNode = currentNode; item.TreeNode = currentNode;
} }
} }
break;
} if (m_GameObject.m_SkinnedMeshRenderer != null)
case ClassIDType.SkinnedMeshRenderer:
{ {
m_GameObject.m_SkinnedMeshRenderer = m_Component; if (m_GameObject.m_SkinnedMeshRenderer.m_Mesh.TryGet(out var m_Mesh))
if (m_Component.TryGet(out var objectReader))
{ {
var m_SkinnedMeshRenderer = new SkinnedMeshRenderer(objectReader); var item = tempDic[m_Mesh];
if (m_SkinnedMeshRenderer.m_Mesh.TryGet(out objectReader))
{
var item = tempDic[objectReader];
item.TreeNode = currentNode; item.TreeNode = currentNode;
} }
} }
break;
}
case ClassIDType.Animator:
{
m_GameObject.m_Animator = m_Component;
var item = tempDic[asset];
item.Text = tempDic[m_GameObject.reader].Text;
break;
}
}
}
}
var parentNode = fileNode; var parentNode = fileNode;
if (m_GameObject.m_Transform != null && m_GameObject.m_Transform.TryGetTransform(out var m_Transform)) if (m_GameObject.m_Transform != null)
{ {
if (m_Transform.m_Father.TryGetTransform(out var m_Father)) if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father))
{ {
if (m_Father.m_GameObject.TryGetGameObject(out var parentGameObject)) if (m_Father.m_GameObject.TryGet(out var parentGameObject))
{ {
if (!treeNodeDictionary.TryGetValue(parentGameObject, out parentNode)) if (!treeNodeDictionary.TryGetValue(parentGameObject, out parentNode))
{ {
@ -365,18 +284,18 @@ namespace AssetStudioGUI
} }
parentNode.Nodes.Add(currentNode); parentNode.Nodes.Add(currentNode);
}
Progress.Report(++i, gameObjectCount);
} }
if (fileNode.Nodes.Count > 0) if (fileNode.Nodes.Count > 0)
{ {
treeNodeCollection.Add(fileNode); treeNodeCollection.Add(fileNode);
} }
Progress.Report(++i, progressCount);
} }
treeNodeDictionary.Clear(); treeNodeDictionary.Clear();
}
return treeNodeCollection; return treeNodeCollection;
} }
@ -435,7 +354,7 @@ namespace AssetStudioGUI
var exportpath = savePath + "\\"; var exportpath = savePath + "\\";
if (assetGroupSelectedIndex == 1) if (assetGroupSelectedIndex == 1)
{ {
exportpath += Path.GetFileNameWithoutExtension(asset.sourceFile.fullName) + "_export\\"; exportpath += Path.GetFileNameWithoutExtension(asset.SourceFile.fullName) + "_export\\";
} }
else if (assetGroupSelectedIndex == 0) else if (assetGroupSelectedIndex == 0)
{ {

View File

@ -15,6 +15,9 @@ namespace AssetStudio
public byte[] ConvertToWav() public byte[] ConvertToWav()
{ {
var m_AudioData = m_AudioClip.m_AudioData.Value;
if (m_AudioData == null || m_AudioData.Length == 0)
return null;
var exinfo = new FMOD.CREATESOUNDEXINFO(); var exinfo = new FMOD.CREATESOUNDEXINFO();
var result = FMOD.Factory.System_Create(out var system); var result = FMOD.Factory.System_Create(out var system);
if (result != FMOD.RESULT.OK) if (result != FMOD.RESULT.OK)
@ -24,7 +27,7 @@ namespace AssetStudio
return null; return null;
exinfo.cbsize = Marshal.SizeOf(exinfo); exinfo.cbsize = Marshal.SizeOf(exinfo);
exinfo.length = (uint)m_AudioClip.m_Size; exinfo.length = (uint)m_AudioClip.m_Size;
result = system.createSound(m_AudioClip.m_AudioData, FMOD.MODE.OPENMEMORY, ref exinfo, out var sound); result = system.createSound(m_AudioData, FMOD.MODE.OPENMEMORY, ref exinfo, out var sound);
if (result != FMOD.RESULT.OK) if (result != FMOD.RESULT.OK)
return null; return null;
result = sound.getSubSound(0, out var subsound); result = sound.getSubSound(0, out var subsound);

View File

@ -19,29 +19,27 @@ namespace AssetStudio
private Avatar avatar; private Avatar avatar;
private Dictionary<uint, string> morphChannelInfo = new Dictionary<uint, string>(); private Dictionary<uint, string> morphChannelInfo = new Dictionary<uint, string>();
private HashSet<ObjectReader> animationClipHashSet = new HashSet<ObjectReader>(); private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>();
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>(); private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
private Dictionary<ObjectReader, string> textureNameDictionary = new Dictionary<ObjectReader, string>(); private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();
public ModelConverter(GameObject m_GameObject) public ModelConverter(GameObject m_GameObject)
{ {
if (m_GameObject.m_Animator != null && m_GameObject.m_Animator.TryGet(out var m_Animator)) if (m_GameObject.m_Animator != null)
{ {
var animator = new Animator(m_Animator); InitWithAnimator(m_GameObject.m_Animator);
InitWithAnimator(animator); CollectAnimationClip(m_GameObject.m_Animator);
CollectAnimationClip(animator);
} }
else else
InitWithGameObject(m_GameObject); InitWithGameObject(m_GameObject);
ConvertAnimations(); ConvertAnimations();
} }
public ModelConverter(GameObject m_GameObject, ObjectReader[] animationList) public ModelConverter(GameObject m_GameObject, AnimationClip[] animationList)
{ {
if (m_GameObject.m_Animator != null && m_GameObject.m_Animator.TryGet(out var m_Animator)) if (m_GameObject.m_Animator != null)
{ {
var animator = new Animator(m_Animator); InitWithAnimator(m_GameObject.m_Animator);
InitWithAnimator(animator);
} }
else else
InitWithGameObject(m_GameObject); InitWithGameObject(m_GameObject);
@ -59,7 +57,7 @@ namespace AssetStudio
ConvertAnimations(); ConvertAnimations();
} }
public ModelConverter(Animator m_Animator, ObjectReader[] animationList) public ModelConverter(Animator m_Animator, AnimationClip[] animationList)
{ {
InitWithAnimator(m_Animator); InitWithAnimator(m_Animator);
foreach (var animationClip in animationList) foreach (var animationClip in animationList)
@ -72,27 +70,26 @@ namespace AssetStudio
private void InitWithAnimator(Animator m_Animator) private void InitWithAnimator(Animator m_Animator)
{ {
if (m_Animator.m_Avatar.TryGet(out var m_Avatar)) if (m_Animator.m_Avatar.TryGet(out var m_Avatar))
avatar = new Avatar(m_Avatar); avatar = m_Avatar;
m_Animator.m_GameObject.TryGetGameObject(out var m_GameObject); m_Animator.m_GameObject.TryGet(out var m_GameObject);
InitWithGameObject(m_GameObject, m_Animator.m_HasTransformHierarchy); InitWithGameObject(m_GameObject, m_Animator.m_HasTransformHierarchy);
} }
private void InitWithGameObject(GameObject m_GameObject, bool hasTransformHierarchy = true) private void InitWithGameObject(GameObject m_GameObject, bool hasTransformHierarchy = true)
{ {
m_GameObject.m_Transform.TryGetTransform(out var m_Transform); var m_Transform = m_GameObject.m_Transform;
var rootTransform = m_Transform;
if (!hasTransformHierarchy) if (!hasTransformHierarchy)
{ {
var rootFrame = ConvertFrame(rootTransform); var rootFrame = ConvertFrame(m_Transform);
FrameList.Add(rootFrame); FrameList.Add(rootFrame);
DeoptimizeTransformHierarchy(); DeoptimizeTransformHierarchy();
} }
else else
{ {
var frameList = new List<ImportedFrame>(); var frameList = new List<ImportedFrame>();
var tempTransform = rootTransform; var tempTransform = m_Transform;
while (tempTransform.m_Father.TryGetTransform(out var m_Father)) while (tempTransform.m_Father.TryGet(out var m_Father))
{ {
frameList.Add(ConvertFrame(m_Father)); frameList.Add(ConvertFrame(m_Father));
tempTransform = m_Father; tempTransform = m_Father;
@ -113,7 +110,7 @@ namespace AssetStudio
ConvertFrames(m_Transform, null); ConvertFrames(m_Transform, null);
} }
CreateBonePathHash(rootTransform); CreateBonePathHash(m_Transform);
} }
ConvertMeshRenderer(m_Transform); ConvertMeshRenderer(m_Transform);
@ -121,82 +118,67 @@ namespace AssetStudio
private void ConvertMeshRenderer(Transform m_Transform) private void ConvertMeshRenderer(Transform m_Transform)
{ {
m_Transform.m_GameObject.TryGetGameObject(out var m_GameObject); m_Transform.m_GameObject.TryGet(out var m_GameObject);
foreach (var m_Component in m_GameObject.m_Components)
if (m_GameObject.m_MeshRenderer != null)
{ {
if (m_Component.TryGet(out var objectReader)) ConvertMeshRenderer(m_GameObject.m_MeshRenderer);
{
switch (objectReader.type)
{
case ClassIDType.MeshRenderer:
{
var m_Renderer = new MeshRenderer(objectReader);
ConvertMeshRenderer(m_Renderer);
break;
} }
case ClassIDType.SkinnedMeshRenderer:
if (m_GameObject.m_SkinnedMeshRenderer != null)
{ {
var m_SkinnedMeshRenderer = new SkinnedMeshRenderer(objectReader); ConvertMeshRenderer(m_GameObject.m_SkinnedMeshRenderer);
ConvertMeshRenderer(m_SkinnedMeshRenderer);
break;
} }
case ClassIDType.Animation:
if (m_GameObject.m_Animation != null)
{ {
var m_Animation = new Animation(objectReader); foreach (var animation in m_GameObject.m_Animation.m_Animations)
foreach (var animation in m_Animation.m_Animations)
{ {
if (animation.TryGet(out var animationClip)) if (animation.TryGet(out var animationClip))
{ {
animationClipHashSet.Add(animationClip); animationClipHashSet.Add(animationClip);
} }
} }
break;
}
}
}
} }
foreach (var pptr in m_Transform.m_Children) foreach (var pptr in m_Transform.m_Children)
{ {
if (pptr.TryGetTransform(out var child)) if (pptr.TryGet(out var child))
ConvertMeshRenderer(child); ConvertMeshRenderer(child);
} }
} }
private void CollectAnimationClip(Animator m_Animator) private void CollectAnimationClip(Animator m_Animator)
{ {
if (m_Animator.m_Controller.TryGet(out var objectReader)) if (m_Animator.m_Controller.TryGet(out var m_Controller))
{ {
if (objectReader.type == ClassIDType.AnimatorOverrideController) switch (m_Controller)
{ {
var m_AnimatorOverrideController = new AnimatorOverrideController(objectReader); case AnimatorOverrideController m_AnimatorOverrideController:
if (m_AnimatorOverrideController.m_Controller.TryGet(out objectReader))
{ {
var m_AnimatorController = new AnimatorController(objectReader); if (m_AnimatorOverrideController.m_Controller.TryGet<AnimatorController>(out var m_AnimatorController))
foreach (var m_AnimationClip in m_AnimatorController.m_AnimationClips)
{ {
if (m_AnimationClip.TryGet(out objectReader)) foreach (var pptr in m_AnimatorController.m_AnimationClips)
{ {
animationClipHashSet.Add(objectReader); if (pptr.TryGet(out var m_AnimationClip))
{
animationClipHashSet.Add(m_AnimationClip);
} }
} }
} }
/*foreach (var clip in m_AnimatorOverrideController.m_Clips) break;
{
if (assetsfileList.TryGetPD(clip[1], out assetPreloadData))
{
animationList.Add(new AnimationClip(assetPreloadData));
} }
}*/
case AnimatorController m_AnimatorController:
{
foreach (var pptr in m_AnimatorController.m_AnimationClips)
{
if (pptr.TryGet(out var m_AnimationClip))
{
animationClipHashSet.Add(m_AnimationClip);
} }
else if (objectReader.type == ClassIDType.AnimatorController)
{
var m_AnimatorController = new AnimatorController(objectReader);
foreach (var m_AnimationClip in m_AnimatorController.m_AnimationClips)
{
if (m_AnimationClip.TryGet(out objectReader))
{
animationClipHashSet.Add(objectReader);
} }
break;
} }
} }
} }
@ -205,7 +187,7 @@ namespace AssetStudio
private ImportedFrame ConvertFrame(Transform trans) private ImportedFrame ConvertFrame(Transform trans)
{ {
var frame = new ImportedFrame(); var frame = new ImportedFrame();
trans.m_GameObject.TryGetGameObject(out var m_GameObject); trans.m_GameObject.TryGet(out var m_GameObject);
frame.Name = m_GameObject.m_Name; frame.Name = m_GameObject.m_Name;
frame.InitChildren(trans.m_Children.Count); frame.InitChildren(trans.m_Children.Count);
var m_EulerRotation = QuatToEuler(new[] { trans.m_LocalRotation[0], -trans.m_LocalRotation[1], -trans.m_LocalRotation[2], trans.m_LocalRotation[3] }); var m_EulerRotation = QuatToEuler(new[] { trans.m_LocalRotation[0], -trans.m_LocalRotation[1], -trans.m_LocalRotation[2], trans.m_LocalRotation[3] });
@ -243,7 +225,7 @@ namespace AssetStudio
} }
foreach (var pptr in trans.m_Children) foreach (var pptr in trans.m_Children)
{ {
if (pptr.TryGetTransform(out var child)) if (pptr.TryGet(out var child))
ConvertFrames(child, frame); ConvertFrames(child, frame);
} }
} }
@ -254,9 +236,8 @@ namespace AssetStudio
if (mesh == null) if (mesh == null)
return; return;
var iMesh = new ImportedMesh(); var iMesh = new ImportedMesh();
meshR.m_GameObject.TryGetGameObject(out var m_GameObject2); meshR.m_GameObject.TryGet(out var m_GameObject2);
m_GameObject2.m_Transform.TryGetTransform(out var meshTransform); iMesh.Name = GetMeshPath(m_GameObject2.m_Transform);
iMesh.Name = GetMeshPath(meshTransform);
iMesh.SubmeshList = new List<ImportedSubmesh>(); iMesh.SubmeshList = new List<ImportedSubmesh>();
var subHashSet = new HashSet<int>(); var subHashSet = new HashSet<int>();
var combine = false; var combine = false;
@ -294,9 +275,9 @@ namespace AssetStudio
Material mat = null; Material mat = null;
if (i - firstSubMesh < meshR.m_Materials.Length) if (i - firstSubMesh < meshR.m_Materials.Length)
{ {
if (meshR.m_Materials[i - firstSubMesh].TryGet(out var MaterialPD)) if (meshR.m_Materials[i - firstSubMesh].TryGet(out var m_Material))
{ {
mat = new Material(MaterialPD); mat = m_Material;
} }
} }
ImportedMaterial iMat = ConvertMaterial(mat); ImportedMaterial iMat = ConvertMaterial(mat);
@ -431,9 +412,9 @@ namespace AssetStudio
for (int i = 0; i < sMesh.m_Bones.Length; i++) for (int i = 0; i < sMesh.m_Bones.Length; i++)
{ {
var bone = new ImportedBone(); var bone = new ImportedBone();
if (sMesh.m_Bones[i].TryGetTransform(out var m_Transform)) if (sMesh.m_Bones[i].TryGet(out var m_Transform))
{ {
if (m_Transform.m_GameObject.TryGetGameObject(out var m_GameObject)) if (m_Transform.m_GameObject.TryGet(out var m_GameObject))
{ {
bone.Name = m_GameObject.m_Name; bone.Name = m_GameObject.m_Name;
} }
@ -538,7 +519,7 @@ namespace AssetStudio
//TODO combine mesh //TODO combine mesh
if (combine) if (combine)
{ {
meshR.m_GameObject.TryGetGameObject(out var m_GameObject); meshR.m_GameObject.TryGet(out var m_GameObject);
var frame = ImportedHelpers.FindChildOrRoot(m_GameObject.m_Name, FrameList[0]); var frame = ImportedHelpers.FindChildOrRoot(m_GameObject.m_Name, FrameList[0]);
if (frame?.Parent != null) if (frame?.Parent != null)
{ {
@ -567,26 +548,19 @@ namespace AssetStudio
{ {
if (meshR is SkinnedMeshRenderer sMesh) if (meshR is SkinnedMeshRenderer sMesh)
{ {
if (sMesh.m_Mesh.TryGet(out var MeshPD)) if (sMesh.m_Mesh.TryGet(out var m_Mesh))
{ {
return new Mesh(MeshPD); return m_Mesh;
} }
} }
else else
{ {
meshR.m_GameObject.TryGetGameObject(out var m_GameObject); meshR.m_GameObject.TryGet(out var m_GameObject);
foreach (var m_Component in m_GameObject.m_Components) if (m_GameObject.m_MeshFilter != null)
{ {
if (m_Component.TryGet(out var objectReader)) if (m_GameObject.m_MeshFilter.m_Mesh.TryGet(out var m_Mesh))
{ {
if (objectReader.type == ClassIDType.MeshFilter) return m_Mesh;
{
var m_MeshFilter = new MeshFilter(objectReader);
if (m_MeshFilter.m_Mesh.TryGet(out var MeshPD))
{
return new Mesh(MeshPD);
}
}
} }
} }
} }
@ -596,7 +570,7 @@ namespace AssetStudio
private string GetMeshPath(Transform meshTransform) private string GetMeshPath(Transform meshTransform)
{ {
meshTransform.m_GameObject.TryGetGameObject(out var m_GameObject); meshTransform.m_GameObject.TryGet(out var m_GameObject);
var curFrame = ImportedHelpers.FindChildOrRoot(m_GameObject.m_Name, FrameList[0]); var curFrame = ImportedHelpers.FindChildOrRoot(m_GameObject.m_Name, FrameList[0]);
var path = curFrame.Name; var path = curFrame.Name;
while (curFrame.Parent != null) while (curFrame.Parent != null)
@ -610,8 +584,8 @@ namespace AssetStudio
private string GetTransformPath(Transform transform) private string GetTransformPath(Transform transform)
{ {
transform.m_GameObject.TryGetGameObject(out var m_GameObject); transform.m_GameObject.TryGet(out var m_GameObject);
if (transform.m_Father.TryGetTransform(out var father)) if (transform.m_Father.TryGet(out var father))
{ {
return GetTransformPath(father) + "/" + m_GameObject.m_Name; return GetTransformPath(father) + "/" + m_GameObject.m_Name;
} }
@ -675,9 +649,9 @@ namespace AssetStudio
foreach (var texEnv in mat.m_TexEnvs) foreach (var texEnv in mat.m_TexEnvs)
{ {
Texture2D m_Texture2D = null; Texture2D m_Texture2D = null;
if (texEnv.m_Texture.TryGet(out var m_Texture) && m_Texture.type == ClassIDType.Texture2D) //TODO other Texture if (texEnv.m_Texture.TryGet<Texture2D>(out var m_Texture)) //TODO other Texture
{ {
m_Texture2D = new Texture2D(m_Texture, true); m_Texture2D = m_Texture;
} }
if (m_Texture2D == null) if (m_Texture2D == null)
@ -758,9 +732,8 @@ namespace AssetStudio
private void ConvertAnimations() private void ConvertAnimations()
{ {
foreach (var assetPreloadData in animationClipHashSet) foreach (var animationClip in animationClipHashSet)
{ {
var animationClip = new AnimationClip(assetPreloadData);
var iAnim = new ImportedKeyframedAnimation(); var iAnim = new ImportedKeyframedAnimation();
AnimationList.Add(iAnim); AnimationList.Add(iAnim);
iAnim.Name = animationClip.m_Name; iAnim.Name = animationClip.m_Name;
@ -1027,7 +1000,7 @@ namespace AssetStudio
} }
foreach (var pptr in m_Transform.m_Children) foreach (var pptr in m_Transform.m_Children)
{ {
if (pptr.TryGetTransform(out var child)) if (pptr.TryGet(out var child))
CreateBonePathHash(child); CreateBonePathHash(child);
} }
} }

View File

@ -13,9 +13,8 @@ namespace AssetStudio
{ {
var m_MonoBehaviour = new MonoBehaviour(reader); var m_MonoBehaviour = new MonoBehaviour(reader);
var sb = CreateMonoBehaviourHeader(m_MonoBehaviour); var sb = CreateMonoBehaviourHeader(m_MonoBehaviour);
if (m_MonoBehaviour.m_Script.TryGet(out var script)) if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{ {
var m_Script = new MonoScript(script);
if (!moduleDic.TryGetValue(m_Script.m_AssemblyName, out var module)) if (!moduleDic.TryGetValue(m_Script.m_AssemblyName, out var module))
{ {
return sb.ToString(); return sb.ToString();
@ -150,7 +149,7 @@ namespace AssetStudio
} }
if (indent != -1 && IsAssignFromUnityObject(typeDef)) if (indent != -1 && IsAssignFromUnityObject(typeDef))
{ {
var pptr = reader.ReadPPtr(); var pptr = new PPtr<Object>(reader);
sb.AppendLine($"{new string('\t', indent)}PPtr<{typeDef.Name}> {name} = {{fileID: {pptr.m_FileID}, pathID: {pptr.m_PathID}}}"); sb.AppendLine($"{new string('\t', indent)}PPtr<{typeDef.Name}> {name} = {{fileID: {pptr.m_FileID}, pathID: {pptr.m_PathID}}}");
return; return;
} }
@ -291,19 +290,24 @@ namespace AssetStudio
{ {
switch (typeDef.FullName) switch (typeDef.FullName)
{ {
case "UnityEngine.Vector2": case "UnityEngine.AnimationCurve":
case "UnityEngine.Vector3": case "UnityEngine.Bounds":
case "UnityEngine.Vector4": case "UnityEngine.BoundsInt":
case "UnityEngine.Rect":
case "UnityEngine.Quaternion":
case "UnityEngine.Matrix4x4":
case "UnityEngine.Color": case "UnityEngine.Color":
case "UnityEngine.Color32": case "UnityEngine.Color32":
case "UnityEngine.LayerMask":
case "UnityEngine.AnimationCurve":
case "UnityEngine.Gradient": case "UnityEngine.Gradient":
case "UnityEngine.RectOffset":
case "UnityEngine.GUIStyle": case "UnityEngine.GUIStyle":
case "UnityEngine.LayerMask":
case "UnityEngine.Matrix4x4":
case "UnityEngine.Quaternion":
case "UnityEngine.Rect":
case "UnityEngine.RectInt":
case "UnityEngine.RectOffset":
case "UnityEngine.Vector2":
case "UnityEngine.Vector2Int":
case "UnityEngine.Vector3":
case "UnityEngine.Vector3Int":
case "UnityEngine.Vector4":
return true; return true;
default: default:
return false; return false;

View File

@ -42,7 +42,7 @@ namespace AssetStudio
new ShaderProgram(blobReader); new ShaderProgram(blobReader);
} }
}*/ }*/
return shader.reader.Dump(); return shader.Dump();
} }
return Encoding.UTF8.GetString(shader.m_Script); return Encoding.UTF8.GetString(shader.m_Script);
} }

View File

@ -8,27 +8,26 @@ namespace AssetStudio
{ {
public static Bitmap GetImageFromSprite(Sprite m_Sprite) public static Bitmap GetImageFromSprite(Sprite m_Sprite)
{ {
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var objectReader)) if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
{ {
var m_SpriteAtlas = new SpriteAtlas(objectReader); if (m_SpriteAtlas.m_RenderDataMap.TryGetValue(m_Sprite.m_RenderDataKey, out var spriteAtlasData) && spriteAtlasData.texture.TryGet(out var m_Texture2D))
if (m_SpriteAtlas.m_RenderDataMap.TryGetValue(m_Sprite.m_RenderDataKey, out var spriteAtlasData) && spriteAtlasData.texture.TryGet(out objectReader))
{ {
return CutImage(objectReader, spriteAtlasData.textureRect, m_Sprite, spriteAtlasData.settingsRaw); return CutImage(m_Texture2D, spriteAtlasData.textureRect, m_Sprite, spriteAtlasData.settingsRaw);
} }
} }
else else
{ {
if (m_Sprite.texture.TryGet(out objectReader)) if (m_Sprite.texture.TryGet(out var m_Texture2D))
{ {
return CutImage(objectReader, m_Sprite.textureRect, m_Sprite, m_Sprite.settingsRaw); return CutImage(m_Texture2D, m_Sprite.textureRect, m_Sprite, m_Sprite.settingsRaw);
} }
} }
return null; return null;
} }
private static Bitmap CutImage(ObjectReader texture2DAsset, RectangleF textureRect, Sprite m_Sprite, SpriteSettings settingsRaw) private static Bitmap CutImage(Texture2D m_Texture2D, RectangleF textureRect, Sprite m_Sprite, SpriteSettings settingsRaw)
{ {
var texture2D = new Texture2DConverter(new Texture2D(texture2DAsset, true)); var texture2D = new Texture2DConverter(m_Texture2D);
var originalImage = texture2D.ConvertToBitmap(false); var originalImage = texture2D.ConvertToBitmap(false);
if (originalImage != null) if (originalImage != null)
{ {

View File

@ -87,7 +87,7 @@ namespace AssetStudio
public Texture2DConverter(Texture2D m_Texture2D) public Texture2DConverter(Texture2D m_Texture2D)
{ {
image_data_size = m_Texture2D.image_data_size; image_data_size = m_Texture2D.image_data_size;
image_data = m_Texture2D.image_data; image_data = m_Texture2D.image_data.Value;
m_Width = m_Texture2D.m_Width; m_Width = m_Texture2D.m_Width;
m_Height = m_Texture2D.m_Height; m_Height = m_Texture2D.m_Height;
m_TextureFormat = m_Texture2D.m_TextureFormat; m_TextureFormat = m_Texture2D.m_TextureFormat;
@ -913,7 +913,7 @@ namespace AssetStudio
buff = new byte[stride * m_Height]; buff = new byte[stride * m_Height];
for (int i = 0; i < m_Height; i++) for (int i = 0; i < m_Height; i++)
{ {
Array.Copy(image_data, i * m_Width * 2, buff, i * stride, m_Width * 2); Buffer.BlockCopy(image_data, i * m_Width * 2, buff, i * stride, m_Width * 2);
} }
} }
else else