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

View File

@ -38,6 +38,7 @@ namespace AssetStudio
importFiles.Add(file);
importFilesHash.Add(Path.GetFileName(file).ToUpper());
}
Progress.Reset();
//use a for loop because list size can change
for (var i = 0; i < importFiles.Count; i++)
@ -45,9 +46,13 @@ namespace AssetStudio
LoadFile(importFiles[i]);
Progress.Report(i + 1, importFiles.Count);
}
importFiles.Clear();
importFilesHash.Clear();
assetsfileListHash.Clear();
ReadAssets();
ProcessGameObject();
}
private void LoadFile(string fullName)
@ -118,7 +123,6 @@ namespace AssetStudio
var fileName = Path.GetFileName(fullName);
if (!assetsfileListHash.Contains(fileName.ToUpper()))
{
Logger.Info($"Loading {fileName}");
var assetsFile = new SerializedFile(this, fullName, reader);
if (assetsFile.valid)
{
@ -127,6 +131,7 @@ namespace AssetStudio
{
assetsFile.SetVersion(unityVersion);
}
assetsFileList.Add(assetsFile);
assetsfileListHash.Add(assetsFile.upperFileName);
}
@ -140,7 +145,7 @@ namespace AssetStudio
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Decompressing " + fileName);
Logger.Info("Loading " + fileName);
var bundleFile = new BundleFile(reader, fullName);
reader.Dispose();
foreach (var file in bundleFile.fileList)
@ -178,15 +183,166 @@ namespace AssetStudio
{
foreach (var assetsFile in assetsFileList)
{
assetsFile.Objects.Clear();
assetsFile.reader.Close();
}
assetsFileList.Clear();
foreach (var resourceFileReader in resourceFileReaders)
{
resourceFileReader.Value.Close();
}
resourceFileReaders.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 List<PPtr> m_Animations;
public List<PPtr<AnimationClip>> m_Animations;
public Animation(ObjectReader reader) : base(reader)
{
var m_Animation = reader.ReadPPtr();
var m_Animation = new PPtr<AnimationClip>(reader);
int numAnimations = reader.ReadInt32();
m_Animations = new List<PPtr>(numAnimations);
m_Animations = new List<PPtr<AnimationClip>>(numAnimations);
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 path;
public int classID;
public PPtr script;
public PPtr<MonoScript> script;
public FloatCurve(ObjectReader reader)
@ -302,20 +302,20 @@ namespace AssetStudio
attribute = reader.ReadAlignedString();
path = reader.ReadAlignedString();
classID = reader.ReadInt32();
script = reader.ReadPPtr();
script = new PPtr<MonoScript>(reader);
}
}
public class PPtrKeyframe
{
public float time;
public PPtr value;
public PPtr<Object> value;
public PPtrKeyframe(ObjectReader reader)
{
time = reader.ReadSingle();
value = reader.ReadPPtr();
value = new PPtr<Object>(reader);
}
}
@ -325,7 +325,7 @@ namespace AssetStudio
public string attribute;
public string path;
public int classID;
public PPtr script;
public PPtr<MonoScript> script;
public PPtrCurve(ObjectReader reader)
@ -340,7 +340,7 @@ namespace AssetStudio
attribute = reader.ReadAlignedString();
path = reader.ReadAlignedString();
classID = reader.ReadInt32();
script = reader.ReadPPtr();
script = new PPtr<MonoScript>(reader);
}
}
@ -757,7 +757,7 @@ namespace AssetStudio
{
public uint path;
public uint attribute;
public PPtr script;
public PPtr<Object> script;
public ClassIDType typeID;
public byte customType;
public byte isPPtrCurve;
@ -767,7 +767,7 @@ namespace AssetStudio
var version = reader.version;
path = 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
{
typeID = (ClassIDType)reader.ReadInt32();
@ -785,7 +785,7 @@ namespace AssetStudio
public class AnimationClipBindingConstant
{
public List<GenericBinding> genericBindings;
public List<PPtr> pptrCurveMapping;
public List<PPtr<Object>> pptrCurveMapping;
public AnimationClipBindingConstant(ObjectReader reader)
{
@ -797,10 +797,10 @@ namespace AssetStudio
}
int numMappings = reader.ReadInt32();
pptrCurveMapping = new List<PPtr>(numMappings);
pptrCurveMapping = new List<PPtr<Object>>(numMappings);
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 PPtr m_Avatar;
public PPtr m_Controller;
public PPtr<Avatar> m_Avatar;
public PPtr<RuntimeAnimatorController> m_Controller;
public bool m_HasTransformHierarchy;
public Animator(ObjectReader reader) : base(reader)
{
m_Avatar = reader.ReadPPtr();
m_Controller = reader.ReadPPtr();
m_Avatar = new PPtr<Avatar>(reader);
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
var m_CullingMode = reader.ReadInt32();
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)
{
@ -548,10 +548,10 @@ namespace AssetStudio
}
int numClips = reader.ReadInt32();
m_AnimationClips = new PPtr[numClips];
m_AnimationClips = new PPtr<AnimationClip>[numClips];
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 PPtr m_OriginalClip;
public PPtr m_OverrideClip;
public PPtr<AnimationClip> m_OriginalClip;
public PPtr<AnimationClip> m_OverrideClip;
public AnimationClipOverride(ObjectReader reader)
{
m_OriginalClip = reader.ReadPPtr();
m_OverrideClip = reader.ReadPPtr();
m_OriginalClip = new PPtr<AnimationClip>(reader);
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 AnimatorOverrideController(ObjectReader reader) : base(reader)
{
m_Controller = reader.ReadPPtr();
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
int numOverrides = reader.ReadInt32();
m_Clips = new List<AnimationClipOverride>(numOverrides);

View File

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

View File

@ -29,9 +29,9 @@ namespace AssetStudio
public string m_Source;
public long m_Offset;
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)
{
@ -49,7 +49,7 @@ namespace AssetStudio
if (reader.byteSize + reader.byteStart - reader.Position != tsize)
{
m_Offset = reader.ReadInt32();
m_Source = sourceFile.fullName + ".resS";
m_Source = assetsFile.fullName + ".resS";
}
}
else
@ -79,18 +79,16 @@ namespace AssetStudio
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);
}
else
{
if (m_Size > 0)
m_AudioData = reader.ReadBytes((int)m_Size);
}
resourceReader = new ResourceReader(m_Source, assetsFile, m_Offset, (int)m_Size);
}
else
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
}
m_AudioData = new Lazy<byte[]>(resourceReader.GetData);
}
}

View File

@ -7,11 +7,11 @@ namespace AssetStudio
{
public abstract class Component : EditorExtension
{
public PPtr m_GameObject;
public PPtr<GameObject> m_GameObject;
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)
{
var m_PrefabParentObject = reader.ReadPPtr();
var m_PrefabInternal = reader.ReadPPtr();
var m_PrefabParentObject = new PPtr<EditorExtension>(reader);
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
{
var m_LineSpacing = reader.ReadSingle();
var m_DefaultMaterial = reader.ReadPPtr();
var m_DefaultMaterial = new PPtr<Material>(reader);
var m_FontSize = reader.ReadSingle();
var m_Texture = reader.ReadPPtr();
var m_Texture = new PPtr<Texture>(reader);
int m_AsciiStartOffset = reader.ReadInt32();
var m_Tracking = reader.ReadSingle();
var m_CharacterSpacing = reader.ReadInt32();
@ -68,7 +68,7 @@ namespace AssetStudio
}
int m_ConvertCase = reader.ReadInt32();
PPtr m_DefaultMaterial = reader.ReadPPtr();
var m_DefaultMaterial = new PPtr<Material>(reader);
int m_CharacterRects_size = reader.ReadInt32();
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();
for (int i = 0; i < m_KerningValues_size; i++)

View File

@ -7,28 +7,30 @@ namespace AssetStudio
{
public sealed class GameObject : EditorExtension
{
public List<PPtr> m_Components;
public List<PPtr<Component>> m_Components;
public string m_Name;
public PPtr m_Transform;
public PPtr m_MeshRenderer;
public PPtr m_MeshFilter;
public PPtr m_SkinnedMeshRenderer;
public PPtr m_Animator;
public Transform m_Transform;
public MeshRenderer m_MeshRenderer;
public MeshFilter m_MeshFilter;
public SkinnedMeshRenderer m_SkinnedMeshRenderer;
public Animator m_Animator;
public Animation m_Animation;
public GameObject(ObjectReader reader) : base(reader)
{
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++)
{
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
{
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 string name;
public PPtr m_Texture;
public PPtr<Texture> m_Texture;
public float[] m_Scale;
public float[] m_Offset;
}
@ -27,7 +27,7 @@ namespace AssetStudio
public sealed class Material : NamedObject
{
public PPtr m_Shader;
public PPtr<Shader> m_Shader;
public string[] m_ShaderKeywords;
public int m_CustomRenderQueue;
public TexEnv[] m_TexEnvs;
@ -36,7 +36,7 @@ namespace AssetStudio
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)))
{
@ -84,7 +84,7 @@ namespace AssetStudio
TexEnv m_TexEnv = new TexEnv()
{
name = reader.ReadAlignedString(),
m_Texture = reader.ReadPPtr(),
m_Texture = new PPtr<Texture>(reader),
m_Scale = 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_KeepVertices = reader.ReadBoolean();
bool m_KeepIndices = reader.ReadBoolean();
if (reader.HasStructMember("m_UsedForStaticMeshColliderOnly"))
if (HasStructMember("m_UsedForStaticMeshColliderOnly"))
{
var m_UsedForStaticMeshColliderOnly = reader.ReadBoolean();
}

View File

@ -8,11 +8,11 @@ namespace AssetStudio
public sealed class MeshFilter : Component
{
public long preloadIndex;
public PPtr m_Mesh;
public PPtr<Mesh> m_Mesh;
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 PPtr m_Script;
public PPtr<MonoScript> m_Script;
public string m_Name;
public MonoBehaviour(ObjectReader reader) : base(reader)
{
m_Script = reader.ReadPPtr();
m_Script = new PPtr<MonoScript>(reader);
m_Name = reader.ReadAlignedString();
}
}

View File

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

View File

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

View File

@ -5,27 +5,58 @@ using System.Text;
namespace AssetStudio
{
public abstract class Object
public class Object
{
protected SerializedFile sourceFile;
public SerializedFile assetsFile;
public ObjectReader reader;
public long m_PathID;
public int[] version;
protected BuildType buildType;
public BuildTarget platform;
public ClassIDType type;
public SerializedType serializedType;
public uint byteSize;
protected Object(ObjectReader reader)
public Object(ObjectReader reader)
{
this.reader = reader;
reader.Reset();
sourceFile = reader.assetsFile;
assetsFile = reader.assetsFile;
type = reader.type;
m_PathID = reader.m_PathID;
version = reader.version;
buildType = reader.buildType;
platform = reader.platform;
serializedType = reader.serializedType;
byteSize = reader.byteSize;
if (platform == BuildTarget.NoTarget)
{
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
{
public class PPtr
public sealed class PPtr<T> where T : Object
{
public int m_FileID;
public long m_PathID;
public SerializedFile assetsFile;
public int index = -2; //-2 - Prepare, -1 - Missing
private SerializedFile assetsFile;
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)
{
@ -20,7 +27,7 @@
if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count)
{
var assetsManager = assetsFile.assetsManager;
var assetsfileList = assetsManager.assetsFileList;
var assetsFileList = assetsManager.assetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (index == -2)
@ -29,14 +36,14 @@
var name = m_External.fileName.ToUpper();
if (!assetsFileIndexCache.TryGetValue(name, out index))
{
index = assetsfileList.FindIndex(x => x.upperFileName == name);
index = assetsFileList.FindIndex(x => x.upperFileName == name);
assetsFileIndexCache.Add(name, index);
}
}
if (index >= 0)
{
result = assetsfileList[index];
result = assetsFileList[index];
return true;
}
}
@ -44,45 +51,39 @@
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;
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.ObjectReaders.TryGetValue(m_PathID, out result))
{
return true;
}
}
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 (sourceFile.Transforms.TryGetValue(m_PathID, out m_Transform))
if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
{
return true;
if (obj is T2 variable)
{
result = variable;
return true;
}
}
}
m_Transform = null;
return false;
}
public bool TryGetGameObject(out GameObject m_GameObject)
{
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.GameObjects.TryGetValue(m_PathID, out m_GameObject))
{
return true;
}
}
m_GameObject = null;
result = null;
return false;
}
}

View File

@ -13,7 +13,7 @@ namespace AssetStudio
public abstract class Renderer : Component
{
public PPtr[] m_Materials;
public PPtr<Material>[] m_Materials;
public StaticBatchInfo m_StaticBatchInfo;
public uint[] m_SubsetIndices;
@ -51,10 +51,10 @@ namespace AssetStudio
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++)
{
m_Materials[m] = reader.ReadPPtr();
m_Materials[m] = new PPtr<Material>(reader);
}
if (version[0] < 3)
@ -77,12 +77,12 @@ namespace AssetStudio
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
{
var m_ProbeAnchor = reader.ReadPPtr();
var m_LightProbeVolumeOverride = reader.ReadPPtr();
var m_ProbeAnchor = new PPtr<Transform>(reader);
var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader);
}
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();
}
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

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 PPtr m_Mesh;
public PPtr[] m_Bones;
public PPtr<Mesh> m_Mesh;
public PPtr<Transform>[] m_Bones;
public List<float> m_BlendShapeWeights;
public SkinnedMeshRenderer(ObjectReader reader) : base(reader)
@ -20,15 +20,15 @@ namespace AssetStudio
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++)
{
m_Bones[b] = reader.ReadPPtr();
m_Bones[b] = new PPtr<Transform>(reader);
}
if (version[0] < 3)

View File

@ -50,8 +50,8 @@ namespace AssetStudio
public float m_PixelsToUnits;
public Vector2 m_Pivot;
public Tuple<Guid, long> m_RenderDataKey;
public PPtr texture;
public PPtr m_SpriteAtlas;
public PPtr<Texture2D> texture;
public PPtr<SpriteAtlas> m_SpriteAtlas;
public RectangleF textureRect;
public SpriteSettings settingsRaw;
public PointF[][] m_PhysicsShape; //Vector2[][]
@ -98,16 +98,16 @@ namespace AssetStudio
}
//PPtr<SpriteAtlas> m_SpriteAtlas
m_SpriteAtlas = reader.ReadPPtr();
m_SpriteAtlas = new PPtr<SpriteAtlas>(reader);
}
//SpriteRenderData m_RD
// PPtr<Texture2D> texture
texture = reader.ReadPPtr();
texture = new PPtr<Texture2D>(reader);
// PPtr<Texture2D> alphaTexture
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

View File

@ -9,8 +9,8 @@ namespace AssetStudio
{
public class SpriteAtlasData
{
public PPtr texture;
public PPtr alphaTexture;
public PPtr<Texture2D> texture;
public PPtr<Texture2D> alphaTexture;
public System.Drawing.RectangleF textureRect;
public Vector2 textureRectOffset;
public Vector2 atlasRectOffset;
@ -21,8 +21,8 @@ namespace AssetStudio
public SpriteAtlasData(ObjectReader reader)
{
var version = reader.version;
texture = reader.ReadPPtr();
alphaTexture = reader.ReadPPtr();
texture = new PPtr<Texture2D>(reader);
alphaTexture = new PPtr<Texture2D>(reader);
textureRect = reader.ReadRectangleF();
textureRectOffset = reader.ReadVector2();
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();
for (int i = 0; i < m_PackedSpritesSize; i++)
{
reader.ReadPPtr(); //PPtr<Sprite> data
new PPtr<Sprite>(reader);
}
var m_PackedSpriteNamesToIndexSize = reader.ReadInt32();

View File

@ -28,13 +28,13 @@ namespace AssetStudio
public int m_ColorSpace;
//image dataa
public int image_data_size;
public byte[] image_data;
public Lazy<byte[]> image_data;
//m_StreamData
public uint offset;
public uint size;
public string path;
public Texture2D(ObjectReader reader, bool readData) : base(reader)
public Texture2D(ObjectReader reader) : base(reader)
{
m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32();
@ -58,11 +58,11 @@ namespace AssetStudio
{
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();
}
if (reader.HasStructMember("m_StreamingGroupID")) //What the hell is this?
if (HasStructMember("m_StreamingGroupID")) //What the hell is this?
{
var m_StreamingGroupID = reader.ReadUInt32();
}
@ -101,17 +101,16 @@ namespace AssetStudio
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);
}
else
{
image_data = reader.ReadBytes(image_data_size);
}
resourceReader = new ResourceReader(path, assetsFile, offset, image_data_size);
}
else
{
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_LocalPosition;
public float[] m_LocalScale;
public List<PPtr> m_Children;
public PPtr m_Father;
public List<PPtr<Transform>> m_Children;
public PPtr<Transform> m_Father;
public Transform(ObjectReader reader) : base(reader)
{
@ -20,12 +20,12 @@ namespace AssetStudio
m_LocalPosition = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
m_LocalScale = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
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++)
{
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 byte[] m_VideoData;
public Lazy<byte[]> m_VideoData;
public string m_OriginalPath;
public string m_Source;
public ulong m_Size;
public VideoClip(ObjectReader reader, bool readData) : base(reader)
public VideoClip(ObjectReader reader) : base(reader)
{
m_OriginalPath = reader.ReadAlignedString();
var m_ProxyWidth = reader.ReadUInt32();
@ -47,18 +47,16 @@ namespace AssetStudio
m_Size = reader.ReadUInt64();
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);
}
else
{
if (m_Size > 0)
m_VideoData = reader.ReadBytes((int)m_Size);
}
resourceReader = new ResourceReader(m_Source, assetsFile, (long)m_Offset, (int)m_Size);
}
else
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
}
m_VideoData = new Lazy<byte[]>(resourceReader.GetData);
}
}
}

View File

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

View File

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

View File

@ -8,7 +8,7 @@ namespace AssetStudio
{
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++)
{
@ -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 level = member.m_Level;
@ -153,7 +153,7 @@ namespace AssetStudio
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>();
for (int i = 0; i < members.Count; i++)
@ -165,7 +165,7 @@ namespace AssetStudio
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 level = member.m_Level;

View File

@ -15,6 +15,8 @@ using OpenTK;
using OpenTK.Graphics.OpenGL;
using AssetStudio;
using static AssetStudioGUI.Studio;
using Object = AssetStudio.Object;
using Font = AssetStudio.Font;
namespace AssetStudioGUI
{
@ -134,13 +136,13 @@ namespace AssetStudioGUI
}
var productName = string.Empty;
var tempDic = new Dictionary<ObjectReader, AssetItem>();
var tempDic = new Dictionary<Object, AssetItem>();
if (!dontLoadAssetsMenuItem.Checked)
{
BuildAssetList(tempDic, displayAll.Checked, displayOriginalName.Checked, out productName);
}
List<GameObjectTreeNode> treeNodeCollection = null;
List<TreeNode> treeNodeCollection = null;
if (!dontBuildHierarchyMenuItem.Checked)
{
treeNodeCollection = BuildTreeStructure(tempDic);
@ -651,457 +653,459 @@ namespace AssetStudioGUI
}
}
private void PreviewAsset(AssetItem asset)
private void PreviewAsset(AssetItem assetItem)
{
var reader = asset.reader;
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();
var m_Texture2D = new Texture2D(reader, true);
//Info
asset.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
switch (m_Texture2D.m_FilterMode)
{
case 0: asset.InfoText += "\nFilter Mode: Point "; break;
case 1: asset.InfoText += "\nFilter Mode: Bilinear "; break;
case 2: asset.InfoText += "\nFilter Mode: Trilinear "; break;
}
asset.InfoText += $"\nAnisotropic level: {m_Texture2D.m_Aniso}\nMip map bias: {m_Texture2D.m_MipBias}";
switch (m_Texture2D.m_WrapMode)
{
case 0: asset.InfoText += "\nWrap mode: Repeat"; break;
case 1: asset.InfoText += "\nWrap mode: Clamp"; break;
}
var converter = new Texture2DConverter(m_Texture2D);
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
{
StatusStripUpdate("Unsupported image for preview");
}
break;
}
case ClassIDType.AudioClip:
{
var m_AudioClip = new AudioClip(reader, true);
//Info
asset.InfoText = "Compression format: ";
if (m_AudioClip.version[0] < 5)
{
switch (m_AudioClip.m_Type)
{
case AudioType.ACC:
asset.InfoText += "Acc";
break;
case AudioType.AIFF:
asset.InfoText += "AIFF";
break;
case AudioType.IT:
asset.InfoText += "Impulse tracker";
break;
case AudioType.MOD:
asset.InfoText += "Protracker / Fasttracker MOD";
break;
case AudioType.MPEG:
asset.InfoText += "MP2/MP3 MPEG";
break;
case AudioType.OGGVORBIS:
asset.InfoText += "Ogg vorbis";
break;
case AudioType.S3M:
asset.InfoText += "ScreamTracker 3";
break;
case AudioType.WAV:
asset.InfoText += "Microsoft WAV";
break;
case AudioType.XM:
asset.InfoText += "FastTracker 2 XM";
break;
case AudioType.XMA:
asset.InfoText += "Xbox360 XMA";
break;
case AudioType.VAG:
asset.InfoText += "PlayStation Portable ADPCM";
break;
case AudioType.AUDIOQUEUE:
asset.InfoText += "iPhone";
break;
default:
asset.InfoText += "Unknown";
break;
}
}
else
{
switch (m_AudioClip.m_CompressionFormat)
{
case AudioCompressionFormat.PCM:
asset.InfoText += "PCM";
break;
case AudioCompressionFormat.Vorbis:
asset.InfoText += "Vorbis";
break;
case AudioCompressionFormat.ADPCM:
asset.InfoText += "ADPCM";
break;
case AudioCompressionFormat.MP3:
asset.InfoText += "MP3";
break;
case AudioCompressionFormat.VAG:
asset.InfoText += "PlayStation Portable ADPCM";
break;
case AudioCompressionFormat.HEVAG:
asset.InfoText += "PSVita ADPCM";
break;
case AudioCompressionFormat.XMA:
asset.InfoText += "Xbox360 XMA";
break;
case AudioCompressionFormat.AAC:
asset.InfoText += "AAC";
break;
case AudioCompressionFormat.GCADPCM:
asset.InfoText += "Nintendo 3DS/Wii DSP";
break;
case AudioCompressionFormat.ATRAC9:
asset.InfoText += "PSVita ATRAC9";
break;
default:
asset.InfoText += "Unknown";
break;
}
}
if (m_AudioClip.m_AudioData == null)
break;
FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO();
exinfo.cbsize = Marshal.SizeOf(exinfo);
exinfo.length = (uint)m_AudioClip.m_Size;
var result = system.createSound(m_AudioClip.m_AudioData, FMOD.MODE.OPENMEMORY | loopMode, ref exinfo, out sound);
if (ERRCHECK(result)) { break; }
result = sound.getSubSound(0, out var subsound);
if (result == FMOD.RESULT.OK)
{
sound = subsound;
}
result = sound.getLength(out FMODlenms, FMOD.TIMEUNIT.MS);
if (ERRCHECK(result)) { break; }
result = system.playSound(sound, null, true, out channel);
if (ERRCHECK(result)) { break; }
FMODpanel.Visible = true;
result = channel.getFrequency(out var frequency);
if (ERRCHECK(result)) { break; }
FMODinfoLabel.Text = frequency + " Hz";
FMODtimerLabel.Text = $"0:0.0 / {FMODlenms / 1000 / 60}:{FMODlenms / 1000 % 60}.{FMODlenms / 10 % 100}";
break;
}
case ClassIDType.Shader:
{
var m_Shader = new Shader(reader);
var str = ShaderConverter.Convert(m_Shader);
textPreviewBox.Text = str == null ? "Serialized Shader can't be read" : str.Replace("\n", "\r\n");
textPreviewBox.Text = str;
textPreviewBox.Visible = true;
break;
}
case ClassIDType.TextAsset:
else
{
TextAsset m_TextAsset = new TextAsset(reader);
string m_Script_Text = Encoding.UTF8.GetString(m_TextAsset.m_Script);
m_Script_Text = Regex.Replace(m_Script_Text, "(?<!\r)\n", "\r\n");
textPreviewBox.Text = m_Script_Text;
textPreviewBox.Visible = true;
break;
}
case ClassIDType.MonoBehaviour:
{
if (reader.serializedType?.m_Nodes != null)
{
textPreviewBox.Text = reader.Dump();
}
else
{
textPreviewBox.Text = GetScriptString(reader);
}
textPreviewBox.Visible = true;
break;
}
case ClassIDType.Font:
{
var m_Font = new AssetStudio.Font(reader);
if (m_Font.m_FontData != null)
{
IntPtr data = Marshal.AllocCoTaskMem(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;
var re = AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts);
if (re != IntPtr.Zero)
{
using (var pfc = new PrivateFontCollection())
{
pfc.AddMemoryFont(data, m_Font.m_FontData.Length);
Marshal.FreeCoTaskMem(data);
if (pfc.Families.Length > 0)
{
fontPreviewBox.SelectionStart = 0;
fontPreviewBox.SelectionLength = 80;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 16, FontStyle.Regular);
fontPreviewBox.SelectionStart = 81;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 12, FontStyle.Regular);
fontPreviewBox.SelectionStart = 138;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 18, FontStyle.Regular);
fontPreviewBox.SelectionStart = 195;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 24, FontStyle.Regular);
fontPreviewBox.SelectionStart = 252;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 36, FontStyle.Regular);
fontPreviewBox.SelectionStart = 309;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 48, FontStyle.Regular);
fontPreviewBox.SelectionStart = 366;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 60, FontStyle.Regular);
fontPreviewBox.SelectionStart = 423;
fontPreviewBox.SelectionLength = 55;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 72, FontStyle.Regular);
fontPreviewBox.Visible = true;
}
}
break;
}
}
StatusStripUpdate("Unsupported font for preview. Try to export.");
break;
}
case ClassIDType.Mesh:
{
var m_Mesh = new Mesh(reader);
if (m_Mesh.m_VertexCount > 0)
{
viewMatrixData = Matrix4.CreateRotationY(-(float)Math.PI / 4) * Matrix4.CreateRotationX(-(float)Math.PI / 6);
#region Vertices
if (m_Mesh.m_Vertices == null || m_Mesh.m_Vertices.Length == 0)
{
StatusStripUpdate("Mesh can't be previewed.");
return;
}
int count = 3;
if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4)
{
count = 4;
}
vertexData = new Vector3[m_Mesh.m_VertexCount];
// Calculate Bounding
float[] min = new float[3];
float[] max = new float[3];
for (int i = 0; i < 3; i++)
{
min[i] = m_Mesh.m_Vertices[i];
max[i] = m_Mesh.m_Vertices[i];
}
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
{
for (int i = 0; i < 3; i++)
{
min[i] = Math.Min(min[i], m_Mesh.m_Vertices[v * count + i]);
max[i] = Math.Max(max[i], m_Mesh.m_Vertices[v * count + i]);
}
vertexData[v] = new Vector3(
m_Mesh.m_Vertices[v * count],
m_Mesh.m_Vertices[v * count + 1],
m_Mesh.m_Vertices[v * count + 2]);
}
// Calculate modelMatrix
Vector3 dist = Vector3.One, offset = Vector3.Zero;
for (int i = 0; i < 3; i++)
{
dist[i] = max[i] - min[i];
offset[i] = (max[i] + min[i]) / 2;
}
float d = Math.Max(1e-5f, dist.Length);
modelMatrixData = Matrix4.CreateTranslation(-offset) * Matrix4.CreateScale(2f / d);
#endregion
#region Indicies
indiceData = new int[m_Mesh.m_Indices.Count];
for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3)
{
indiceData[i] = (int)m_Mesh.m_Indices[i];
indiceData[i + 1] = (int)m_Mesh.m_Indices[i + 1];
indiceData[i + 2] = (int)m_Mesh.m_Indices[i + 2];
}
#endregion
#region Normals
if (m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0)
{
if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3)
count = 3;
else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4)
count = 4;
normalData = new Vector3[m_Mesh.m_VertexCount];
for (int n = 0; n < m_Mesh.m_VertexCount; n++)
{
normalData[n] = new Vector3(
m_Mesh.m_Normals[n * count],
m_Mesh.m_Normals[n * count + 1],
m_Mesh.m_Normals[n * count + 2]);
}
}
else
normalData = null;
// calculate normal by ourself
normal2Data = new Vector3[m_Mesh.m_VertexCount];
int[] normalCalculatedCount = new int[m_Mesh.m_VertexCount];
for (int i = 0; i < m_Mesh.m_VertexCount; i++)
{
normal2Data[i] = Vector3.Zero;
normalCalculatedCount[i] = 0;
}
for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3)
{
Vector3 dir1 = vertexData[indiceData[i + 1]] - vertexData[indiceData[i]];
Vector3 dir2 = vertexData[indiceData[i + 2]] - vertexData[indiceData[i]];
Vector3 normal = Vector3.Cross(dir1, dir2);
normal.Normalize();
for (int j = 0; j < 3; j++)
{
normal2Data[indiceData[i + j]] += normal;
normalCalculatedCount[indiceData[i + j]]++;
}
}
for (int i = 0; i < m_Mesh.m_VertexCount; i++)
{
if (normalCalculatedCount[i] == 0)
normal2Data[i] = new Vector3(0, 1, 0);
else
normal2Data[i] /= normalCalculatedCount[i];
}
#endregion
#region Colors
if (m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3)
{
colorData = new Vector4[m_Mesh.m_VertexCount];
for (int c = 0; c < m_Mesh.m_VertexCount; c++)
{
colorData[c] = new Vector4(
m_Mesh.m_Colors[c * 3],
m_Mesh.m_Colors[c * 3 + 1],
m_Mesh.m_Colors[c * 3 + 2],
1.0f);
}
}
else if (m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 4)
{
colorData = new Vector4[m_Mesh.m_VertexCount];
for (int c = 0; c < m_Mesh.m_VertexCount; c++)
{
colorData[c] = new Vector4(
m_Mesh.m_Colors[c * 4],
m_Mesh.m_Colors[c * 4 + 1],
m_Mesh.m_Colors[c * 4 + 2],
m_Mesh.m_Colors[c * 4 + 3]);
}
}
else
{
colorData = new Vector4[m_Mesh.m_VertexCount];
for (int c = 0; c < m_Mesh.m_VertexCount; c++)
{
colorData[c] = new Vector4(0.5f, 0.5f, 0.5f, 1.0f);
}
}
#endregion
glControl1.Visible = true;
createVAO();
}
StatusStripUpdate("Using OpenGL Version: " + GL.GetString(StringName.Version) + "\n"
+ "'Mouse Left'=Rotate | 'Mouse Right'=Move | 'Mouse Wheel'=Zoom \n"
+ "'Ctrl W'=Wireframe | 'Ctrl S'=Shade | 'Ctrl N'=ReNormal ");
StatusStripUpdate("Only supported export the raw file.");
}
break;
case ClassIDType.VideoClip:
case ClassIDType.MovieTexture:
{
StatusStripUpdate("Only supported export.");
break;
}
case ClassIDType.Sprite:
{
imageTexture?.Dispose();
imageTexture = SpriteHelper.GetImageFromSprite(new Sprite(reader));
if (imageTexture != null)
{
asset.InfoText = $"Width: {imageTexture.Width}\nHeight: {imageTexture.Height}\n";
previewPanel.BackgroundImage = imageTexture;
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
else
previewPanel.BackgroundImageLayout = ImageLayout.Center;
}
else
{
StatusStripUpdate("Unsupported sprite for preview.");
}
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;
}
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}");
MessageBox.Show($"Preview {assetItem.Type}:{assetItem.Text} error\r\n{e.Message}\r\n{e.StackTrace}");
}
}
private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D)
{
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)
{
case 0: assetItem.InfoText += "\nFilter Mode: Point "; break;
case 1: assetItem.InfoText += "\nFilter Mode: Bilinear "; break;
case 2: assetItem.InfoText += "\nFilter Mode: Trilinear "; break;
}
assetItem.InfoText += $"\nAnisotropic level: {m_Texture2D.m_Aniso}\nMip map bias: {m_Texture2D.m_MipBias}";
switch (m_Texture2D.m_WrapMode)
{
case 0: assetItem.InfoText += "\nWrap mode: Repeat"; break;
case 1: assetItem.InfoText += "\nWrap mode: Clamp"; break;
}
PreviewTexture(bitmap);
}
else
{
StatusStripUpdate("Unsupported image for preview");
}
}
private void PreviewAudioClip(AssetItem assetItem, AudioClip m_AudioClip)
{
//Info
assetItem.InfoText = "Compression format: ";
if (m_AudioClip.version[0] < 5)
{
switch (m_AudioClip.m_Type)
{
case AudioType.ACC:
assetItem.InfoText += "Acc";
break;
case AudioType.AIFF:
assetItem.InfoText += "AIFF";
break;
case AudioType.IT:
assetItem.InfoText += "Impulse tracker";
break;
case AudioType.MOD:
assetItem.InfoText += "Protracker / Fasttracker MOD";
break;
case AudioType.MPEG:
assetItem.InfoText += "MP2/MP3 MPEG";
break;
case AudioType.OGGVORBIS:
assetItem.InfoText += "Ogg vorbis";
break;
case AudioType.S3M:
assetItem.InfoText += "ScreamTracker 3";
break;
case AudioType.WAV:
assetItem.InfoText += "Microsoft WAV";
break;
case AudioType.XM:
assetItem.InfoText += "FastTracker 2 XM";
break;
case AudioType.XMA:
assetItem.InfoText += "Xbox360 XMA";
break;
case AudioType.VAG:
assetItem.InfoText += "PlayStation Portable ADPCM";
break;
case AudioType.AUDIOQUEUE:
assetItem.InfoText += "iPhone";
break;
default:
assetItem.InfoText += "Unknown";
break;
}
}
else
{
switch (m_AudioClip.m_CompressionFormat)
{
case AudioCompressionFormat.PCM:
assetItem.InfoText += "PCM";
break;
case AudioCompressionFormat.Vorbis:
assetItem.InfoText += "Vorbis";
break;
case AudioCompressionFormat.ADPCM:
assetItem.InfoText += "ADPCM";
break;
case AudioCompressionFormat.MP3:
assetItem.InfoText += "MP3";
break;
case AudioCompressionFormat.VAG:
assetItem.InfoText += "PlayStation Portable ADPCM";
break;
case AudioCompressionFormat.HEVAG:
assetItem.InfoText += "PSVita ADPCM";
break;
case AudioCompressionFormat.XMA:
assetItem.InfoText += "Xbox360 XMA";
break;
case AudioCompressionFormat.AAC:
assetItem.InfoText += "AAC";
break;
case AudioCompressionFormat.GCADPCM:
assetItem.InfoText += "Nintendo 3DS/Wii DSP";
break;
case AudioCompressionFormat.ATRAC9:
assetItem.InfoText += "PSVita ATRAC9";
break;
default:
assetItem.InfoText += "Unknown";
break;
}
}
var m_AudioData = m_AudioClip.m_AudioData.Value;
if (m_AudioData == null || m_AudioData.Length == 0)
return;
FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO();
exinfo.cbsize = Marshal.SizeOf(exinfo);
exinfo.length = (uint)m_AudioClip.m_Size;
var result = system.createSound(m_AudioData, FMOD.MODE.OPENMEMORY | loopMode, ref exinfo, out sound);
if (ERRCHECK(result)) return;
result = sound.getSubSound(0, out var subsound);
if (result == FMOD.RESULT.OK)
{
sound = subsound;
}
result = sound.getLength(out FMODlenms, FMOD.TIMEUNIT.MS);
if (ERRCHECK(result)) return;
result = system.playSound(sound, null, true, out channel);
if (ERRCHECK(result)) return;
FMODpanel.Visible = true;
result = channel.getFrequency(out var frequency);
if (ERRCHECK(result)) return;
FMODinfoLabel.Text = frequency + " Hz";
FMODtimerLabel.Text = $"0:0.0 / {FMODlenms / 1000 / 60}:{FMODlenms / 1000 % 60}.{FMODlenms / 10 % 100}";
}
private void PreviewShader(Shader m_Shader)
{
var str = ShaderConverter.Convert(m_Shader);
PreviewText(str == null ? "Serialized Shader can't be read" : str.Replace("\n", "\r\n"));
}
private void PreviewTextAsset(TextAsset m_TextAsset)
{
var text = Encoding.UTF8.GetString(m_TextAsset.m_Script);
PreviewText(text.Replace("\n", "\r\n"));
}
private void PreviewMonoBehaviour(MonoBehaviour m_MonoBehaviour)
{
PreviewText(m_MonoBehaviour.Dump() ?? GetScriptString(m_MonoBehaviour.reader));
}
private void PreviewFont(Font m_Font)
{
if (m_Font.m_FontData != null)
{
var data = Marshal.AllocCoTaskMem(m_Font.m_FontData.Length);
Marshal.Copy(m_Font.m_FontData, 0, data, m_Font.m_FontData.Length);
uint cFonts = 0;
var re = AddFontMemResourceEx(data, (uint)m_Font.m_FontData.Length, IntPtr.Zero, ref cFonts);
if (re != IntPtr.Zero)
{
using (var pfc = new PrivateFontCollection())
{
pfc.AddMemoryFont(data, m_Font.m_FontData.Length);
Marshal.FreeCoTaskMem(data);
if (pfc.Families.Length > 0)
{
fontPreviewBox.SelectionStart = 0;
fontPreviewBox.SelectionLength = 80;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 16, FontStyle.Regular);
fontPreviewBox.SelectionStart = 81;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 12, FontStyle.Regular);
fontPreviewBox.SelectionStart = 138;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 18, FontStyle.Regular);
fontPreviewBox.SelectionStart = 195;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 24, FontStyle.Regular);
fontPreviewBox.SelectionStart = 252;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 36, FontStyle.Regular);
fontPreviewBox.SelectionStart = 309;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 48, FontStyle.Regular);
fontPreviewBox.SelectionStart = 366;
fontPreviewBox.SelectionLength = 56;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 60, FontStyle.Regular);
fontPreviewBox.SelectionStart = 423;
fontPreviewBox.SelectionLength = 55;
fontPreviewBox.SelectionFont = new System.Drawing.Font(pfc.Families[0], 72, FontStyle.Regular);
fontPreviewBox.Visible = true;
}
}
return;
}
}
StatusStripUpdate("Unsupported font for preview. Try to export.");
}
private void PreviewMesh(Mesh m_Mesh)
{
if (m_Mesh.m_VertexCount > 0)
{
viewMatrixData = Matrix4.CreateRotationY(-(float)Math.PI / 4) * Matrix4.CreateRotationX(-(float)Math.PI / 6);
#region Vertices
if (m_Mesh.m_Vertices == null || m_Mesh.m_Vertices.Length == 0)
{
StatusStripUpdate("Mesh can't be previewed.");
return;
}
int count = 3;
if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4)
{
count = 4;
}
vertexData = new Vector3[m_Mesh.m_VertexCount];
// Calculate Bounding
float[] min = new float[3];
float[] max = new float[3];
for (int i = 0; i < 3; i++)
{
min[i] = m_Mesh.m_Vertices[i];
max[i] = m_Mesh.m_Vertices[i];
}
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
{
for (int i = 0; i < 3; i++)
{
min[i] = Math.Min(min[i], m_Mesh.m_Vertices[v * count + i]);
max[i] = Math.Max(max[i], m_Mesh.m_Vertices[v * count + i]);
}
vertexData[v] = new Vector3(
m_Mesh.m_Vertices[v * count],
m_Mesh.m_Vertices[v * count + 1],
m_Mesh.m_Vertices[v * count + 2]);
}
// Calculate modelMatrix
Vector3 dist = Vector3.One, offset = Vector3.Zero;
for (int i = 0; i < 3; i++)
{
dist[i] = max[i] - min[i];
offset[i] = (max[i] + min[i]) / 2;
}
float d = Math.Max(1e-5f, dist.Length);
modelMatrixData = Matrix4.CreateTranslation(-offset) * Matrix4.CreateScale(2f / d);
#endregion
#region Indicies
indiceData = new int[m_Mesh.m_Indices.Count];
for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3)
{
indiceData[i] = (int)m_Mesh.m_Indices[i];
indiceData[i + 1] = (int)m_Mesh.m_Indices[i + 1];
indiceData[i + 2] = (int)m_Mesh.m_Indices[i + 2];
}
#endregion
#region Normals
if (m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0)
{
if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3)
count = 3;
else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4)
count = 4;
normalData = new Vector3[m_Mesh.m_VertexCount];
for (int n = 0; n < m_Mesh.m_VertexCount; n++)
{
normalData[n] = new Vector3(
m_Mesh.m_Normals[n * count],
m_Mesh.m_Normals[n * count + 1],
m_Mesh.m_Normals[n * count + 2]);
}
}
else
normalData = null;
// calculate normal by ourself
normal2Data = new Vector3[m_Mesh.m_VertexCount];
int[] normalCalculatedCount = new int[m_Mesh.m_VertexCount];
for (int i = 0; i < m_Mesh.m_VertexCount; i++)
{
normal2Data[i] = Vector3.Zero;
normalCalculatedCount[i] = 0;
}
for (int i = 0; i < m_Mesh.m_Indices.Count; i = i + 3)
{
Vector3 dir1 = vertexData[indiceData[i + 1]] - vertexData[indiceData[i]];
Vector3 dir2 = vertexData[indiceData[i + 2]] - vertexData[indiceData[i]];
Vector3 normal = Vector3.Cross(dir1, dir2);
normal.Normalize();
for (int j = 0; j < 3; j++)
{
normal2Data[indiceData[i + j]] += normal;
normalCalculatedCount[indiceData[i + j]]++;
}
}
for (int i = 0; i < m_Mesh.m_VertexCount; i++)
{
if (normalCalculatedCount[i] == 0)
normal2Data[i] = new Vector3(0, 1, 0);
else
normal2Data[i] /= normalCalculatedCount[i];
}
#endregion
#region Colors
if (m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3)
{
colorData = new Vector4[m_Mesh.m_VertexCount];
for (int c = 0; c < m_Mesh.m_VertexCount; c++)
{
colorData[c] = new Vector4(
m_Mesh.m_Colors[c * 3],
m_Mesh.m_Colors[c * 3 + 1],
m_Mesh.m_Colors[c * 3 + 2],
1.0f);
}
}
else if (m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 4)
{
colorData = new Vector4[m_Mesh.m_VertexCount];
for (int c = 0; c < m_Mesh.m_VertexCount; c++)
{
colorData[c] = new Vector4(
m_Mesh.m_Colors[c * 4],
m_Mesh.m_Colors[c * 4 + 1],
m_Mesh.m_Colors[c * 4 + 2],
m_Mesh.m_Colors[c * 4 + 3]);
}
}
else
{
colorData = new Vector4[m_Mesh.m_VertexCount];
for (int c = 0; c < m_Mesh.m_VertexCount; c++)
{
colorData[c] = new Vector4(0.5f, 0.5f, 0.5f, 1.0f);
}
}
#endregion
glControl1.Visible = true;
createVAO();
}
StatusStripUpdate("Using OpenGL Version: " + GL.GetString(StringName.Version) + "\n"
+ "'Mouse Left'=Rotate | 'Mouse Right'=Move | 'Mouse Wheel'=Zoom \n"
+ "'Ctrl W'=Wireframe | 'Ctrl S'=Shade | 'Ctrl N'=ReNormal ");
}
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
{
var bitmap = SpriteHelper.GetImageFromSprite(m_Sprite);
if (bitmap != null)
{
assetItem.InfoText = $"Width: {imageTexture.Width}\nHeight: {imageTexture.Height}\n";
PreviewTexture(bitmap);
}
else
{
StatusStripUpdate("Unsupported sprite for preview.");
}
}
private void PreviewTexture(Bitmap bitmap)
{
imageTexture?.Dispose();
imageTexture = bitmap;
previewPanel.BackgroundImage = imageTexture;
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
else
previewPanel.BackgroundImageLayout = ImageLayout.Center;
}
private void PreviewText(string text)
{
textPreviewBox.Text = text;
textPreviewBox.Visible = true;
}
private void FMODinit()
{
FMODreset();
@ -1683,6 +1687,7 @@ namespace AssetStudioGUI
classesListView.Items.Clear();
classesListView.Groups.Clear();
previewPanel.BackgroundImage = Properties.Resources.preview;
imageTexture?.Dispose();
previewPanel.BackgroundImageLayout = ImageLayout.Center;
assetInfoLabel.Visible = false;
assetInfoLabel.Text = null;
@ -1757,7 +1762,7 @@ namespace AssetStudioGUI
private void showOriginalFileToolStripMenuItem_Click(object sender, EventArgs e)
{
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);
Process.Start(pfi);
}

View File

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

View File

@ -11,10 +11,7 @@ namespace AssetStudioGUI
{
public static bool ExportTexture2D(AssetItem item, string exportPathName)
{
var m_Texture2D = new Texture2D(item.reader, true);
if (m_Texture2D.image_data == null || m_Texture2D.image_data.Length == 0)
return false;
var converter = new Texture2DConverter(m_Texture2D);
var converter = new Texture2DConverter((Texture2D)item.Asset);
var convertTexture = (bool)Properties.Settings.Default["convertTexture"];
if (convertTexture)
{
@ -54,8 +51,9 @@ namespace AssetStudioGUI
public static bool ExportAudioClip(AssetItem item, string exportPath)
{
var m_AudioClip = new AudioClip(item.reader, true);
if (m_AudioClip.m_AudioData == null)
var m_AudioClip = (AudioClip)item.Asset;
var m_AudioData = m_AudioClip.m_AudioData.Value;
if (m_AudioData == null || m_AudioData.Length == 0)
return false;
var convertAudio = (bool)Properties.Settings.Default["convertAudio"];
var converter = new AudioClipConverter(m_AudioClip);
@ -74,25 +72,24 @@ namespace AssetStudioGUI
var exportFullName = exportPath + item.Text + converter.GetExtensionName();
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, m_AudioClip.m_AudioData);
File.WriteAllBytes(exportFullName, m_AudioData);
}
return true;
}
public static bool ExportShader(AssetItem item, string exportPath)
{
var m_Shader = new Shader(item.reader);
var exportFullName = exportPath + item.Text + ".shader";
if (ExportFileExists(exportFullName))
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");
return true;
}
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";
if (ExportFileExists(exportFullName))
return false;
@ -105,23 +102,15 @@ namespace AssetStudioGUI
var exportFullName = exportPath + item.Text + ".txt";
if (ExportFileExists(exportFullName))
return false;
var reader = item.reader;
string str;
if (reader.serializedType?.m_Nodes != null)
{
str = reader.Dump();
}
else
{
str = Studio.GetScriptString(reader);
}
var m_MonoBehaviour = (MonoBehaviour)item.Asset;
var str = m_MonoBehaviour.Dump() ?? Studio.GetScriptString(item.Asset.reader);
File.WriteAllText(exportFullName, str);
return true;
}
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)
{
var extension = ".ttf";
@ -140,7 +129,7 @@ namespace AssetStudioGUI
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)
return false;
var exportFullName = exportPath + item.Text + ".obj";
@ -221,13 +210,14 @@ namespace AssetStudioGUI
public static bool ExportVideoClip(AssetItem item, string exportPath)
{
var m_VideoClip = new VideoClip(item.reader, true);
if (m_VideoClip.m_VideoData != null)
var m_VideoClip = (VideoClip)item.Asset;
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);
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, m_VideoClip.m_VideoData);
File.WriteAllBytes(exportFullName, m_VideoData);
return true;
}
return false;
@ -235,7 +225,7 @@ namespace AssetStudioGUI
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";
if (ExportFileExists(exportFullName))
return false;
@ -262,7 +252,7 @@ namespace AssetStudioGUI
var exportFullName = exportPath + item.Text + "." + type.ToLower();
if (ExportFileExists(exportFullName))
return false;
var bitmap = SpriteHelper.GetImageFromSprite(new Sprite(item.reader));
var bitmap = SpriteHelper.GetImageFromSprite((Sprite)item.Asset);
if (bitmap != null)
{
bitmap.Save(exportFullName, format);
@ -277,7 +267,7 @@ namespace AssetStudioGUI
var exportFullName = exportPath + item.Text + ".dat";
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, item.reader.GetRawData());
File.WriteAllBytes(exportFullName, item.Asset.GetRawData());
return true;
}
@ -293,15 +283,15 @@ namespace AssetStudioGUI
public static bool ExportAnimator(AssetItem item, string exportPath, List<AssetItem> animationList = null)
{
var m_Animator = new Animator(item.reader);
var convert = animationList != null ? new ModelConverter(m_Animator, animationList.Select(x => x.reader).ToArray()) : new ModelConverter(m_Animator);
var m_Animator = (Animator)item.Asset;
var convert = animationList != null ? new ModelConverter(m_Animator, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) : new ModelConverter(m_Animator);
exportPath = exportPath + item.Text + ".fbx";
return ExportFbx(convert, exportPath);
}
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";
return ExportFbx(convert, exportPath);
}

View File

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

View File

@ -15,6 +15,9 @@ namespace AssetStudio
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 result = FMOD.Factory.System_Create(out var system);
if (result != FMOD.RESULT.OK)
@ -24,7 +27,7 @@ namespace AssetStudio
return null;
exinfo.cbsize = Marshal.SizeOf(exinfo);
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)
return null;
result = sound.getSubSound(0, out var subsound);

View File

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

View File

@ -13,9 +13,8 @@ namespace AssetStudio
{
var m_MonoBehaviour = new MonoBehaviour(reader);
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))
{
return sb.ToString();
@ -150,7 +149,7 @@ namespace AssetStudio
}
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}}}");
return;
}
@ -291,19 +290,24 @@ namespace AssetStudio
{
switch (typeDef.FullName)
{
case "UnityEngine.Vector2":
case "UnityEngine.Vector3":
case "UnityEngine.Vector4":
case "UnityEngine.Rect":
case "UnityEngine.Quaternion":
case "UnityEngine.Matrix4x4":
case "UnityEngine.AnimationCurve":
case "UnityEngine.Bounds":
case "UnityEngine.BoundsInt":
case "UnityEngine.Color":
case "UnityEngine.Color32":
case "UnityEngine.LayerMask":
case "UnityEngine.AnimationCurve":
case "UnityEngine.Gradient":
case "UnityEngine.RectOffset":
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;
default:
return false;

View File

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

View File

@ -8,27 +8,26 @@ namespace AssetStudio
{
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 objectReader))
if (m_SpriteAtlas.m_RenderDataMap.TryGetValue(m_Sprite.m_RenderDataKey, out var spriteAtlasData) && spriteAtlasData.texture.TryGet(out var m_Texture2D))
{
return CutImage(objectReader, spriteAtlasData.textureRect, m_Sprite, spriteAtlasData.settingsRaw);
return CutImage(m_Texture2D, spriteAtlasData.textureRect, m_Sprite, spriteAtlasData.settingsRaw);
}
}
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;
}
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);
if (originalImage != null)
{

View File

@ -87,7 +87,7 @@ namespace AssetStudio
public Texture2DConverter(Texture2D m_Texture2D)
{
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_Height = m_Texture2D.m_Height;
m_TextureFormat = m_Texture2D.m_TextureFormat;
@ -913,7 +913,7 @@ namespace AssetStudio
buff = new byte[stride * m_Height];
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