diff --git a/Unity Studio/Unity Classes/AssetBundle.cs b/Unity Studio/Unity Classes/AssetBundle.cs index c68ed8e..f853326 100644 --- a/Unity Studio/Unity Classes/AssetBundle.cs +++ b/Unity Studio/Unity Classes/AssetBundle.cs @@ -27,23 +27,22 @@ namespace Unity_Studio public AssetBundle(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; - var m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - var size = a_Stream.ReadInt32(); + var m_Name = reader.ReadAlignedString(reader.ReadInt32()); + var size = reader.ReadInt32(); for (int i = 0; i < size; i++) { sourceFile.ReadPPtr(); } - size = a_Stream.ReadInt32(); + size = reader.ReadInt32(); for (int i = 0; i < size; i++) { var temp = new ContainerData(); - temp.first = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + temp.first = reader.ReadAlignedString(reader.ReadInt32()); temp.second = new AssetInfo(); - temp.second.preloadIndex = a_Stream.ReadInt32(); - temp.second.preloadSize = a_Stream.ReadInt32(); + temp.second.preloadIndex = reader.ReadInt32(); + temp.second.preloadSize = reader.ReadInt32(); temp.second.asset = sourceFile.ReadPPtr(); m_Container.Add(temp); } diff --git a/Unity Studio/Unity Classes/AudioClip.cs b/Unity Studio/Unity Classes/AudioClip.cs index 80d3aa9..177b103 100644 --- a/Unity Studio/Unity Classes/AudioClip.cs +++ b/Unity Studio/Unity Classes/AudioClip.cs @@ -38,64 +38,63 @@ namespace Unity_Studio public AudioClip(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); version5 = sourceFile.version[0] >= 5; if (sourceFile.version[0] < 5) { - m_Format = a_Stream.ReadInt32(); //channels? - m_Type = (AudioType)a_Stream.ReadInt32(); - m_3D = a_Stream.ReadBoolean(); - m_UseHardware = a_Stream.ReadBoolean(); - a_Stream.Position += 2; //4 byte alignment + m_Format = reader.ReadInt32(); //channels? + m_Type = (AudioType)reader.ReadInt32(); + m_3D = reader.ReadBoolean(); + m_UseHardware = reader.ReadBoolean(); + reader.Position += 2; //4 byte alignment if (sourceFile.version[0] >= 4 || (sourceFile.version[0] == 3 && sourceFile.version[1] >= 2)) //3.2.0 to 5 { - int m_Stream = a_Stream.ReadInt32(); - m_Size = a_Stream.ReadInt32(); + int m_Stream = reader.ReadInt32(); + m_Size = reader.ReadInt32(); var tsize = m_Size % 4 != 0 ? m_Size + 4 - m_Size % 4 : m_Size; //TODO: Need more test - if (preloadData.Size + preloadData.Offset - a_Stream.Position != tsize) + if (preloadData.Size + preloadData.Offset - reader.Position != tsize) { - m_Offset = a_Stream.ReadInt32(); + m_Offset = reader.ReadInt32(); m_Source = sourceFile.filePath + ".resS"; } } else { - m_Size = a_Stream.ReadInt32(); + m_Size = reader.ReadInt32(); } } else { - m_LoadType = a_Stream.ReadInt32(); //Decompress on load, Compressed in memory, Streaming - m_Channels = a_Stream.ReadInt32(); - m_Frequency = a_Stream.ReadInt32(); - m_BitsPerSample = a_Stream.ReadInt32(); - m_Length = a_Stream.ReadSingle(); - m_IsTrackerFormat = a_Stream.ReadBoolean(); - a_Stream.Position += 3; - m_SubsoundIndex = a_Stream.ReadInt32(); - m_PreloadAudioData = a_Stream.ReadBoolean(); - m_LoadInBackground = a_Stream.ReadBoolean(); - m_Legacy3D = a_Stream.ReadBoolean(); - a_Stream.Position += 1; + m_LoadType = reader.ReadInt32(); //Decompress on load, Compressed in memory, Streaming + m_Channels = reader.ReadInt32(); + m_Frequency = reader.ReadInt32(); + m_BitsPerSample = reader.ReadInt32(); + m_Length = reader.ReadSingle(); + m_IsTrackerFormat = reader.ReadBoolean(); + reader.Position += 3; + m_SubsoundIndex = reader.ReadInt32(); + m_PreloadAudioData = reader.ReadBoolean(); + m_LoadInBackground = reader.ReadBoolean(); + m_Legacy3D = reader.ReadBoolean(); + reader.Position += 1; m_3D = m_Legacy3D; - m_Source = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - m_Offset = a_Stream.ReadInt64(); - m_Size = a_Stream.ReadInt64(); - m_CompressionFormat = (AudioCompressionFormat)a_Stream.ReadInt32(); + m_Source = reader.ReadAlignedString(reader.ReadInt32()); + m_Offset = reader.ReadInt64(); + m_Size = reader.ReadInt64(); + m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32(); } if (readSwitch) @@ -114,18 +113,18 @@ namespace Unity_Studio } if (File.Exists(resourceFilePath)) { - using (var reader = new BinaryReader(File.OpenRead(resourceFilePath))) + using (var resourceReader = new BinaryReader(File.OpenRead(resourceFilePath))) { - reader.BaseStream.Position = m_Offset; - m_AudioData = reader.ReadBytes((int)m_Size); + resourceReader.BaseStream.Position = m_Offset; + m_AudioData = resourceReader.ReadBytes((int)m_Size); } } else { - if (UnityStudio.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader)) + if (UnityStudio.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var resourceReader)) { - reader.Position = m_Offset; - m_AudioData = reader.ReadBytes((int)m_Size); + resourceReader.Position = m_Offset; + m_AudioData = resourceReader.ReadBytes((int)m_Size); } else { @@ -136,7 +135,7 @@ namespace Unity_Studio else { if (m_Size > 0) - m_AudioData = a_Stream.ReadBytes((int)m_Size); + m_AudioData = reader.ReadBytes((int)m_Size); } } else diff --git a/Unity Studio/Unity Classes/BuildSettings.cs b/Unity Studio/Unity Classes/BuildSettings.cs index 10def65..4a82d44 100644 --- a/Unity Studio/Unity Classes/BuildSettings.cs +++ b/Unity Studio/Unity Classes/BuildSettings.cs @@ -12,27 +12,26 @@ namespace Unity_Studio public BuildSettings(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; - int levels = a_Stream.ReadInt32(); - for (int l = 0; l < levels; l++) { string level = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); } + int levels = reader.ReadInt32(); + for (int l = 0; l < levels; l++) { string level = reader.ReadAlignedString(reader.ReadInt32()); } if (sourceFile.version[0] == 5) { - int preloadedPlugins = a_Stream.ReadInt32(); - for (int l = 0; l < preloadedPlugins; l++) { string preloadedPlugin = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); } + int preloadedPlugins = reader.ReadInt32(); + for (int l = 0; l < preloadedPlugins; l++) { string preloadedPlugin = reader.ReadAlignedString(reader.ReadInt32()); } } - a_Stream.Position += 4; //bool flags - if (sourceFile.fileGen >= 8) { a_Stream.Position += 4; } //bool flags - if (sourceFile.fileGen >= 9) { a_Stream.Position += 4; } //bool flags + reader.Position += 4; //bool flags + if (sourceFile.fileGen >= 8) { reader.Position += 4; } //bool flags + if (sourceFile.fileGen >= 9) { reader.Position += 4; } //bool flags if (sourceFile.version[0] == 5 || (sourceFile.version[0] == 4 && (sourceFile.version[1] >= 3 || (sourceFile.version[1] == 2 && sourceFile.buildType[0] != "a")))) - { a_Stream.Position += 4; } //bool flags + { reader.Position += 4; } //bool flags - m_Version = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Version = reader.ReadAlignedString(reader.ReadInt32()); } } } diff --git a/Unity Studio/Unity Classes/Font.cs b/Unity Studio/Unity Classes/Font.cs index e03ed5b..4dce1be 100644 --- a/Unity Studio/Unity Classes/Font.cs +++ b/Unity Studio/Unity Classes/Font.cs @@ -5,73 +5,72 @@ using System.Text; namespace Unity_Studio { - class unityFont + class UnityFont { public string m_Name; public byte[] m_FontData; - public unityFont(AssetPreloadData preloadData, bool readSwitch) + public UnityFont(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (readSwitch) { if ((sourceFile.version[0] == 5 && sourceFile.version[1] >= 5) || sourceFile.version[0] > 5) { - var m_LineSpacing = a_Stream.ReadSingle(); + var m_LineSpacing = reader.ReadSingle(); var m_DefaultMaterial = sourceFile.ReadPPtr(); - var m_FontSize = a_Stream.ReadSingle(); + var m_FontSize = reader.ReadSingle(); var m_Texture = sourceFile.ReadPPtr(); - int m_AsciiStartOffset = a_Stream.ReadInt32(); - var m_Tracking = a_Stream.ReadSingle(); - var m_CharacterSpacing = a_Stream.ReadInt32(); - var m_CharacterPadding = a_Stream.ReadInt32(); - var m_ConvertCase = a_Stream.ReadInt32(); - int m_CharacterRects_size = a_Stream.ReadInt32(); + int m_AsciiStartOffset = reader.ReadInt32(); + var m_Tracking = reader.ReadSingle(); + var m_CharacterSpacing = reader.ReadInt32(); + var m_CharacterPadding = reader.ReadInt32(); + var m_ConvertCase = reader.ReadInt32(); + int m_CharacterRects_size = reader.ReadInt32(); for (int i = 0; i < m_CharacterRects_size; i++) { - int index = a_Stream.ReadInt32(); + int index = reader.ReadInt32(); //Rectf uv - float uvx = a_Stream.ReadSingle(); - float uvy = a_Stream.ReadSingle(); - float uvwidth = a_Stream.ReadSingle(); - float uvheight = a_Stream.ReadSingle(); + float uvx = reader.ReadSingle(); + float uvy = reader.ReadSingle(); + float uvwidth = reader.ReadSingle(); + float uvheight = reader.ReadSingle(); //Rectf vert - float vertx = a_Stream.ReadSingle(); - float verty = a_Stream.ReadSingle(); - float vertwidth = a_Stream.ReadSingle(); - float vertheight = a_Stream.ReadSingle(); - float width = a_Stream.ReadSingle(); + float vertx = reader.ReadSingle(); + float verty = reader.ReadSingle(); + float vertwidth = reader.ReadSingle(); + float vertheight = reader.ReadSingle(); + float width = reader.ReadSingle(); if (sourceFile.version[0] >= 4) { - bool flipped = a_Stream.ReadBoolean(); - a_Stream.Position += 3; + bool flipped = reader.ReadBoolean(); + reader.Position += 3; } } - int m_KerningValues_size = a_Stream.ReadInt32(); + int m_KerningValues_size = reader.ReadInt32(); for (int i = 0; i < m_KerningValues_size; i++) { - int pairfirst = a_Stream.ReadInt16(); - int pairsecond = a_Stream.ReadInt16(); - float second = a_Stream.ReadSingle(); + int pairfirst = reader.ReadInt16(); + int pairsecond = reader.ReadInt16(); + float second = reader.ReadSingle(); } - var m_PixelScale = a_Stream.ReadSingle(); - int m_FontData_size = a_Stream.ReadInt32(); + var m_PixelScale = reader.ReadSingle(); + int m_FontData_size = reader.ReadInt32(); if (m_FontData_size > 0) { - m_FontData = a_Stream.ReadBytes(m_FontData_size); + m_FontData = reader.ReadBytes(m_FontData_size); if (m_FontData[0] == 79 && m_FontData[1] == 84 && m_FontData[2] == 84 && m_FontData[3] == 79) { preloadData.extension = ".otf"; } @@ -80,79 +79,79 @@ namespace Unity_Studio } else { - int m_AsciiStartOffset = a_Stream.ReadInt32(); + int m_AsciiStartOffset = reader.ReadInt32(); if (sourceFile.version[0] <= 3) { - int m_FontCountX = a_Stream.ReadInt32(); - int m_FontCountY = a_Stream.ReadInt32(); + int m_FontCountX = reader.ReadInt32(); + int m_FontCountY = reader.ReadInt32(); } - float m_Kerning = a_Stream.ReadSingle(); - float m_LineSpacing = a_Stream.ReadSingle(); + float m_Kerning = reader.ReadSingle(); + float m_LineSpacing = reader.ReadSingle(); if (sourceFile.version[0] <= 3) { - int m_PerCharacterKerning_size = a_Stream.ReadInt32(); + int m_PerCharacterKerning_size = reader.ReadInt32(); for (int i = 0; i < m_PerCharacterKerning_size; i++) { - int first = a_Stream.ReadInt32(); - float second = a_Stream.ReadSingle(); + int first = reader.ReadInt32(); + float second = reader.ReadSingle(); } } else { - int m_CharacterSpacing = a_Stream.ReadInt32(); - int m_CharacterPadding = a_Stream.ReadInt32(); + int m_CharacterSpacing = reader.ReadInt32(); + int m_CharacterPadding = reader.ReadInt32(); } - int m_ConvertCase = a_Stream.ReadInt32(); + int m_ConvertCase = reader.ReadInt32(); PPtr m_DefaultMaterial = sourceFile.ReadPPtr(); - int m_CharacterRects_size = a_Stream.ReadInt32(); + int m_CharacterRects_size = reader.ReadInt32(); for (int i = 0; i < m_CharacterRects_size; i++) { - int index = a_Stream.ReadInt32(); + int index = reader.ReadInt32(); //Rectf uv - float uvx = a_Stream.ReadSingle(); - float uvy = a_Stream.ReadSingle(); - float uvwidth = a_Stream.ReadSingle(); - float uvheight = a_Stream.ReadSingle(); + float uvx = reader.ReadSingle(); + float uvy = reader.ReadSingle(); + float uvwidth = reader.ReadSingle(); + float uvheight = reader.ReadSingle(); //Rectf vert - float vertx = a_Stream.ReadSingle(); - float verty = a_Stream.ReadSingle(); - float vertwidth = a_Stream.ReadSingle(); - float vertheight = a_Stream.ReadSingle(); - float width = a_Stream.ReadSingle(); + float vertx = reader.ReadSingle(); + float verty = reader.ReadSingle(); + float vertwidth = reader.ReadSingle(); + float vertheight = reader.ReadSingle(); + float width = reader.ReadSingle(); if (sourceFile.version[0] >= 4) { - bool flipped = a_Stream.ReadBoolean(); - a_Stream.Position += 3; + bool flipped = reader.ReadBoolean(); + reader.Position += 3; } } PPtr m_Texture = sourceFile.ReadPPtr(); - int m_KerningValues_size = a_Stream.ReadInt32(); + int m_KerningValues_size = reader.ReadInt32(); for (int i = 0; i < m_KerningValues_size; i++) { - int pairfirst = a_Stream.ReadInt16(); - int pairsecond = a_Stream.ReadInt16(); - float second = a_Stream.ReadSingle(); + int pairfirst = reader.ReadInt16(); + int pairsecond = reader.ReadInt16(); + float second = reader.ReadSingle(); } if (sourceFile.version[0] <= 3) { - bool m_GridFont = a_Stream.ReadBoolean(); - a_Stream.Position += 3; //4 byte alignment + bool m_GridFont = reader.ReadBoolean(); + reader.Position += 3; //4 byte alignment } - else { float m_PixelScale = a_Stream.ReadSingle(); } + else { float m_PixelScale = reader.ReadSingle(); } - int m_FontData_size = a_Stream.ReadInt32(); + int m_FontData_size = reader.ReadInt32(); if (m_FontData_size > 0) { - m_FontData = a_Stream.ReadBytes(m_FontData_size); + m_FontData = reader.ReadBytes(m_FontData_size); if (m_FontData[0] == 79 && m_FontData[1] == 84 && m_FontData[2] == 84 && m_FontData[3] == 79) { preloadData.extension = ".otf"; } @@ -160,25 +159,25 @@ namespace Unity_Studio } - float m_FontSize = a_Stream.ReadSingle();//problem here in minifootball - float m_Ascent = a_Stream.ReadSingle(); - uint m_DefaultStyle = a_Stream.ReadUInt32(); + float m_FontSize = reader.ReadSingle();//problem here in minifootball + float m_Ascent = reader.ReadSingle(); + uint m_DefaultStyle = reader.ReadUInt32(); - int m_FontNames = a_Stream.ReadInt32(); + int m_FontNames = reader.ReadInt32(); for (int i = 0; i < m_FontNames; i++) { - string m_FontName = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + string m_FontName = reader.ReadAlignedString(reader.ReadInt32()); } if (sourceFile.version[0] >= 4) { - int m_FallbackFonts = a_Stream.ReadInt32(); + int m_FallbackFonts = reader.ReadInt32(); for (int i = 0; i < m_FallbackFonts; i++) { PPtr m_FallbackFont = sourceFile.ReadPPtr(); } - int m_FontRenderingMode = a_Stream.ReadInt32(); + int m_FontRenderingMode = reader.ReadInt32(); } } } diff --git a/Unity Studio/Unity Classes/GameObject.cs b/Unity Studio/Unity Classes/GameObject.cs index cb04981..97273e2 100644 --- a/Unity Studio/Unity Classes/GameObject.cs +++ b/Unity Studio/Unity Classes/GameObject.cs @@ -25,19 +25,18 @@ namespace Unity_Studio if (preloadData != null) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; uniqueID = preloadData.uniqueID; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - int m_Component_size = a_Stream.ReadInt32(); + int m_Component_size = reader.ReadInt32(); for (int j = 0; j < m_Component_size; j++) { if ((sourceFile.version[0] == 5 && sourceFile.version[1] >= 5) || sourceFile.version[0] > 5)//5.5.0 and up @@ -46,16 +45,16 @@ namespace Unity_Studio } else { - int first = a_Stream.ReadInt32(); + int first = reader.ReadInt32(); m_Components.Add(sourceFile.ReadPPtr()); } } - m_Layer = a_Stream.ReadInt32(); - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Layer = reader.ReadInt32(); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (m_Name == "") { m_Name = "GameObject #" + uniqueID; } - m_Tag = a_Stream.ReadUInt16(); - m_IsActive = a_Stream.ReadBoolean(); + m_Tag = reader.ReadUInt16(); + m_IsActive = reader.ReadBoolean(); Text = m_Name; preloadData.Text = m_Name; diff --git a/Unity Studio/Unity Classes/Material.cs b/Unity Studio/Unity Classes/Material.cs index 39c3785..fc56c7a 100644 --- a/Unity Studio/Unity Classes/Material.cs +++ b/Unity Studio/Unity Classes/Material.cs @@ -5,9 +5,28 @@ using System.Text; namespace Unity_Studio { + class TexEnv + { + public string name; + public PPtr m_Texture; + public float[] m_Scale; + public float[] m_Offset; + } + + class strFloatPair + { + public string first; + public float second; + } + + class strColorPair + { + public string first; + public float[] second; + } + class Material { - public string m_Name; public PPtr m_Shader; public string[] m_ShaderKeywords; @@ -19,90 +38,89 @@ namespace Unity_Studio public Material(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); m_Shader = sourceFile.ReadPPtr(); if (sourceFile.version[0] == 4 && (sourceFile.version[1] >= 2 || (sourceFile.version[1] == 1 && sourceFile.buildType[0] != "a"))) { - m_ShaderKeywords = new string[a_Stream.ReadInt32()]; + m_ShaderKeywords = new string[reader.ReadInt32()]; for (int i = 0; i < m_ShaderKeywords.Length; i++) { - m_ShaderKeywords[i] = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_ShaderKeywords[i] = reader.ReadAlignedString(reader.ReadInt32()); } } else if (sourceFile.version[0] >= 5)//5.0 and up { - m_ShaderKeywords = new[] { a_Stream.ReadAlignedString(a_Stream.ReadInt32()) }; - uint m_LightmapFlags = a_Stream.ReadUInt32(); + m_ShaderKeywords = new[] { reader.ReadAlignedString(reader.ReadInt32()) }; + uint m_LightmapFlags = reader.ReadUInt32(); if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 6 || sourceFile.version[0] > 5)//5.6.0 and up { - var m_EnableInstancingVariants = a_Stream.ReadBoolean(); + var m_EnableInstancingVariants = reader.ReadBoolean(); //var m_DoubleSidedGI = a_Stream.ReadBoolean();//2017.x - a_Stream.AlignStream(4); + reader.AlignStream(4); } } - if (sourceFile.version[0] > 4 || sourceFile.version[0] == 4 && sourceFile.version[1] >= 3) { m_CustomRenderQueue = a_Stream.ReadInt32(); } + if (sourceFile.version[0] > 4 || sourceFile.version[0] == 4 && sourceFile.version[1] >= 3) { m_CustomRenderQueue = reader.ReadInt32(); } if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 1 || sourceFile.version[0] > 5)//5.1 and up { - string[][] stringTagMap = new string[a_Stream.ReadInt32()][]; + string[][] stringTagMap = new string[reader.ReadInt32()][]; for (int i = 0; i < stringTagMap.Length; i++) { - stringTagMap[i] = new[] { a_Stream.ReadAlignedString(a_Stream.ReadInt32()), a_Stream.ReadAlignedString(a_Stream.ReadInt32()) }; + stringTagMap[i] = new[] { reader.ReadAlignedString(reader.ReadInt32()), reader.ReadAlignedString(reader.ReadInt32()) }; } } //disabledShaderPasses if ((sourceFile.version[0] == 5 && sourceFile.version[1] >= 6) || sourceFile.version[0] > 5)//5.6.0 and up { - var size = a_Stream.ReadInt32(); + var size = reader.ReadInt32(); for (int i = 0; i < size; i++) { - a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + reader.ReadAlignedString(reader.ReadInt32()); } } //m_SavedProperties - m_TexEnvs = new TexEnv[a_Stream.ReadInt32()]; + m_TexEnvs = new TexEnv[reader.ReadInt32()]; for (int i = 0; i < m_TexEnvs.Length; i++) { TexEnv m_TexEnv = new TexEnv() { - name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()), + name = reader.ReadAlignedString(reader.ReadInt32()), m_Texture = sourceFile.ReadPPtr(), - m_Scale = new[] { a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - m_Offset = new[] { a_Stream.ReadSingle(), a_Stream.ReadSingle() } + m_Scale = new[] { reader.ReadSingle(), reader.ReadSingle() }, + m_Offset = new[] { reader.ReadSingle(), reader.ReadSingle() } }; m_TexEnvs[i] = m_TexEnv; } - m_Floats = new strFloatPair[a_Stream.ReadInt32()]; + m_Floats = new strFloatPair[reader.ReadInt32()]; for (int i = 0; i < m_Floats.Length; i++) { strFloatPair m_Float = new strFloatPair() { - first = a_Stream.ReadAlignedString(a_Stream.ReadInt32()), - second = a_Stream.ReadSingle() + first = reader.ReadAlignedString(reader.ReadInt32()), + second = reader.ReadSingle() }; m_Floats[i] = m_Float; } - m_Colors = new strColorPair[a_Stream.ReadInt32()]; + m_Colors = new strColorPair[reader.ReadInt32()]; for (int i = 0; i < m_Colors.Length; i++) { strColorPair m_Color = new strColorPair() { - first = a_Stream.ReadAlignedString(a_Stream.ReadInt32()), - second = new[] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } + first = reader.ReadAlignedString(reader.ReadInt32()), + second = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() } }; m_Colors[i] = m_Color; } diff --git a/Unity Studio/Unity Classes/Mesh.cs b/Unity Studio/Unity Classes/Mesh.cs index 0d7c189..feb5e99 100644 --- a/Unity Studio/Unity Classes/Mesh.cs +++ b/Unity Studio/Unity Classes/Mesh.cs @@ -102,7 +102,7 @@ namespace Unity_Studio { public class Mesh { - private EndianBinaryReader a_Stream; + private EndianBinaryReader reader; public string m_Name; public List m_SubMeshes = new List(); public List m_Indices = new List(); //use a list because I don't always know the facecount for triangle strips @@ -169,7 +169,7 @@ namespace Unity_Studio public float bytesToFloat(byte[] inputBytes) { float result = 0; - if (a_Stream.endian == EndianType.BigEndian) { Array.Reverse(inputBytes); } + if (reader.endian == EndianType.BigEndian) { Array.Reverse(inputBytes); } switch (inputBytes.Length) { @@ -331,69 +331,69 @@ namespace Unity_Studio //Stream = new EndianStream(File.OpenRead(sourceFile.filePath), sourceFile.endianType); //Stream.endian = sourceFile.endianType; var version = MeshPD.sourceFile.version; - a_Stream = MeshPD.sourceFile.assetsFileReader; - a_Stream.Position = MeshPD.Offset; + reader = MeshPD.Reader; + bool m_Use16BitIndices = true; //3.5.0 and newer always uses 16bit indices uint m_MeshCompression = 0; if (MeshPD.sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = MeshPD.sourceFile.ReadPPtr(); PPtr m_PrefabInternal = MeshPD.sourceFile.ReadPPtr(); } - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (readSwitch) { if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) { - m_Use16BitIndices = a_Stream.ReadBoolean(); - a_Stream.Position += 3; + m_Use16BitIndices = reader.ReadBoolean(); + reader.Position += 3; } #region Index Buffer for 2.5.1 and earlier if (version[0] == 2 && version[1] <= 5) { - int m_IndexBuffer_size = a_Stream.ReadInt32(); + int m_IndexBuffer_size = reader.ReadInt32(); if (m_Use16BitIndices) { m_IndexBuffer = new uint[m_IndexBuffer_size / 2]; - for (int i = 0; i < m_IndexBuffer_size / 2; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt16(); } - a_Stream.AlignStream(4); + for (int i = 0; i < m_IndexBuffer_size / 2; i++) { m_IndexBuffer[i] = reader.ReadUInt16(); } + reader.AlignStream(4); } else { m_IndexBuffer = new uint[m_IndexBuffer_size / 4]; - for (int i = 0; i < m_IndexBuffer_size / 4; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt32(); } + for (int i = 0; i < m_IndexBuffer_size / 4; i++) { m_IndexBuffer[i] = reader.ReadUInt32(); } } } #endregion #region subMeshes - int m_SubMeshes_size = a_Stream.ReadInt32(); + int m_SubMeshes_size = reader.ReadInt32(); for (int s = 0; s < m_SubMeshes_size; s++) { m_SubMeshes.Add(new SubMesh()); - m_SubMeshes[s].firstByte = a_Stream.ReadUInt32(); - m_SubMeshes[s].indexCount = a_Stream.ReadUInt32(); //what is this in case of triangle strips? - m_SubMeshes[s].topology = a_Stream.ReadInt32(); //isTriStrip + m_SubMeshes[s].firstByte = reader.ReadUInt32(); + m_SubMeshes[s].indexCount = reader.ReadUInt32(); //what is this in case of triangle strips? + m_SubMeshes[s].topology = reader.ReadInt32(); //isTriStrip if (version[0] < 4) { - m_SubMeshes[s].triangleCount = a_Stream.ReadUInt32(); + m_SubMeshes[s].triangleCount = reader.ReadUInt32(); } if (version[0] >= 3) { if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3))//2017.3 and up { - var baseVertex = a_Stream.ReadUInt32(); + var baseVertex = reader.ReadUInt32(); } - m_SubMeshes[s].firstVertex = a_Stream.ReadUInt32(); - m_SubMeshes[s].vertexCount = a_Stream.ReadUInt32(); - a_Stream.Position += 24; //Axis-Aligned Bounding Box + m_SubMeshes[s].firstVertex = reader.ReadUInt32(); + m_SubMeshes[s].vertexCount = reader.ReadUInt32(); + reader.Position += 24; //Axis-Aligned Bounding Box } } #endregion @@ -402,93 +402,93 @@ namespace Unity_Studio if (version[0] == 4 && ((version[1] == 1 && MeshPD.sourceFile.buildType[0] != "a") || (version[1] > 1 && version[1] <= 2))) { - int m_Shapes_size = a_Stream.ReadInt32(); + int m_Shapes_size = reader.ReadInt32(); if (m_Shapes_size > 0) { //bool stop = true; } for (int s = 0; s < m_Shapes_size; s++) //untested { - string shape_name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - a_Stream.Position += 36; //uint firstVertex, vertexCount; Vector3f aabbMinDelta, aabbMaxDelta; bool hasNormals, hasTangents + string shape_name = reader.ReadAlignedString(reader.ReadInt32()); + reader.Position += 36; //uint firstVertex, vertexCount; Vector3f aabbMinDelta, aabbMaxDelta; bool hasNormals, hasTangents } - int m_ShapeVertices_size = a_Stream.ReadInt32(); - a_Stream.Position += m_ShapeVertices_size * 40; //vertex positions, normals, tangents & uint index + int m_ShapeVertices_size = reader.ReadInt32(); + reader.Position += m_ShapeVertices_size * 40; //vertex positions, normals, tangents & uint index } #endregion #region BlendShapeData and BindPose for 4.3.0 and later else if (version[0] >= 5 || (version[0] == 4 && version[1] >= 3)) { - int m_ShapeVertices_size = a_Stream.ReadInt32(); + int m_ShapeVertices_size = reader.ReadInt32(); if (m_ShapeVertices_size > 0) { //bool stop = true; } - a_Stream.Position += m_ShapeVertices_size * 40; //vertex positions, normals, tangents & uint index + reader.Position += m_ShapeVertices_size * 40; //vertex positions, normals, tangents & uint index - int shapes_size = a_Stream.ReadInt32(); - a_Stream.Position += shapes_size * 12; //uint firstVertex, vertexCount; bool hasNormals, hasTangents + int shapes_size = reader.ReadInt32(); + reader.Position += shapes_size * 12; //uint firstVertex, vertexCount; bool hasNormals, hasTangents - int channels_size = a_Stream.ReadInt32(); + int channels_size = reader.ReadInt32(); for (int c = 0; c < channels_size; c++) { - string channel_name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - a_Stream.Position += 12; //uint nameHash; int frameIndex, frameCount + string channel_name = reader.ReadAlignedString(reader.ReadInt32()); + reader.Position += 12; //uint nameHash; int frameIndex, frameCount } - int fullWeights_size = a_Stream.ReadInt32(); - a_Stream.Position += fullWeights_size * 4; //floats + int fullWeights_size = reader.ReadInt32(); + reader.Position += fullWeights_size * 4; //floats - m_BindPose = new float[a_Stream.ReadInt32()][,]; + m_BindPose = new float[reader.ReadInt32()][,]; for (int i = 0; i < m_BindPose.Length; i++) { m_BindPose[i] = new[,] { - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } }; + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() } }; } - int m_BoneNameHashes_size = a_Stream.ReadInt32(); - a_Stream.Position += m_BoneNameHashes_size * 4; //uints + int m_BoneNameHashes_size = reader.ReadInt32(); + reader.Position += m_BoneNameHashes_size * 4; //uints - uint m_RootBoneNameHash = a_Stream.ReadUInt32(); + uint m_RootBoneNameHash = reader.ReadUInt32(); } #endregion #region Index Buffer for 2.6.0 and later if (version[0] >= 3 || (version[0] == 2 && version[1] >= 6)) { - m_MeshCompression = a_Stream.ReadByte(); + m_MeshCompression = reader.ReadByte(); if (version[0] >= 4) { - if (version[0] < 5) { uint m_StreamCompression = a_Stream.ReadByte(); } - bool m_IsReadable = a_Stream.ReadBoolean(); - bool m_KeepVertices = a_Stream.ReadBoolean(); - bool m_KeepIndices = a_Stream.ReadBoolean(); + if (version[0] < 5) { uint m_StreamCompression = reader.ReadByte(); } + bool m_IsReadable = reader.ReadBoolean(); + bool m_KeepVertices = reader.ReadBoolean(); + bool m_KeepIndices = reader.ReadBoolean(); } - a_Stream.AlignStream(4); + reader.AlignStream(4); if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3))//2017.3 and up { - if(m_MeshCompression == 0) - { - var m_IndexFormat = a_Stream.ReadInt32(); - } + if (m_MeshCompression == 0) + { + var m_IndexFormat = reader.ReadInt32(); + } } - int m_IndexBuffer_size = a_Stream.ReadInt32(); + int m_IndexBuffer_size = reader.ReadInt32(); if (m_Use16BitIndices) { m_IndexBuffer = new uint[m_IndexBuffer_size / 2]; - for (int i = 0; i < m_IndexBuffer_size / 2; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt16(); } - a_Stream.AlignStream(4); + for (int i = 0; i < m_IndexBuffer_size / 2; i++) { m_IndexBuffer[i] = reader.ReadUInt16(); } + reader.AlignStream(4); } else { m_IndexBuffer = new uint[m_IndexBuffer_size / 4]; - for (int i = 0; i < m_IndexBuffer_size / 4; i++) { m_IndexBuffer[i] = a_Stream.ReadUInt32(); } - a_Stream.AlignStream(4);//untested + for (int i = 0; i < m_IndexBuffer_size / 4; i++) { m_IndexBuffer[i] = reader.ReadUInt32(); } + reader.AlignStream(4);//untested } } #endregion @@ -496,17 +496,17 @@ namespace Unity_Studio #region Vertex Buffer for 3.4.2 and earlier if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) { - m_VertexCount = a_Stream.ReadInt32(); + m_VertexCount = reader.ReadInt32(); m_Vertices = new float[m_VertexCount * 3]; - for (int v = 0; v < m_VertexCount * 3; v++) { m_Vertices[v] = a_Stream.ReadSingle(); } + for (int v = 0; v < m_VertexCount * 3; v++) { m_Vertices[v] = reader.ReadSingle(); } - m_Skin = new List[a_Stream.ReadInt32()]; + m_Skin = new List[reader.ReadInt32()]; //m_Skin = new Dictionary[a_Stream.ReadInt32()]; for (int s = 0; s < m_Skin.Length; s++) { m_Skin[s] = new List(); - for (int i = 0; i < 4; i++) { m_Skin[s].Add(new BoneInfluence() { weight = a_Stream.ReadSingle() }); } - for (int i = 0; i < 4; i++) { m_Skin[s][i].boneIndex = a_Stream.ReadInt32(); } + for (int i = 0; i < 4; i++) { m_Skin[s].Add(new BoneInfluence() { weight = reader.ReadSingle() }); } + for (int i = 0; i < 4; i++) { m_Skin[s][i].boneIndex = reader.ReadInt32(); } /*m_Skin[s] = new Dictionary(); float[] weights = new float[4] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; @@ -517,44 +517,44 @@ namespace Unity_Studio }*/ } - m_BindPose = new float[a_Stream.ReadInt32()][,]; + m_BindPose = new float[reader.ReadInt32()][,]; for (int i = 0; i < m_BindPose.Length; i++) { m_BindPose[i] = new[,] { - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } }; + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() } }; } - int m_UV1_size = a_Stream.ReadInt32(); + int m_UV1_size = reader.ReadInt32(); m_UV1 = new float[m_UV1_size * 2]; - for (int v = 0; v < m_UV1_size * 2; v++) { m_UV1[v] = a_Stream.ReadSingle(); } + for (int v = 0; v < m_UV1_size * 2; v++) { m_UV1[v] = reader.ReadSingle(); } - int m_UV2_size = a_Stream.ReadInt32(); + int m_UV2_size = reader.ReadInt32(); m_UV2 = new float[m_UV2_size * 2]; - for (int v = 0; v < m_UV2_size * 2; v++) { m_UV2[v] = a_Stream.ReadSingle(); } + for (int v = 0; v < m_UV2_size * 2; v++) { m_UV2[v] = reader.ReadSingle(); } if (version[0] == 2 && version[1] <= 5) { - int m_TangentSpace_size = a_Stream.ReadInt32(); + int m_TangentSpace_size = reader.ReadInt32(); m_Normals = new float[m_TangentSpace_size * 3]; for (int v = 0; v < m_TangentSpace_size; v++) { - m_Normals[v * 3] = a_Stream.ReadSingle(); - m_Normals[v * 3 + 1] = a_Stream.ReadSingle(); - m_Normals[v * 3 + 2] = a_Stream.ReadSingle(); - a_Stream.Position += 16; //Vector3f tangent & float handedness + m_Normals[v * 3] = reader.ReadSingle(); + m_Normals[v * 3 + 1] = reader.ReadSingle(); + m_Normals[v * 3 + 2] = reader.ReadSingle(); + reader.Position += 16; //Vector3f tangent & float handedness } } else //2.6.0 and later { - int m_Tangents_size = a_Stream.ReadInt32(); - a_Stream.Position += m_Tangents_size * 16; //Vector4f + int m_Tangents_size = reader.ReadInt32(); + reader.Position += m_Tangents_size * 16; //Vector4f - int m_Normals_size = a_Stream.ReadInt32(); + int m_Normals_size = reader.ReadInt32(); m_Normals = new float[m_Normals_size * 3]; - for (int v = 0; v < m_Normals_size * 3; v++) { m_Normals[v] = a_Stream.ReadSingle(); } + for (int v = 0; v < m_Normals_size * 3; v++) { m_Normals[v] = reader.ReadSingle(); } } } #endregion @@ -562,13 +562,13 @@ namespace Unity_Studio else { #region read vertex stream - m_Skin = new List[a_Stream.ReadInt32()]; + m_Skin = new List[reader.ReadInt32()]; //m_Skin = new Dictionary[a_Stream.ReadInt32()]; for (int s = 0; s < m_Skin.Length; s++) { m_Skin[s] = new List(); - for (int i = 0; i < 4; i++) { m_Skin[s].Add(new BoneInfluence() { weight = a_Stream.ReadSingle() }); } - for (int i = 0; i < 4; i++) { m_Skin[s][i].boneIndex = a_Stream.ReadInt32(); } + for (int i = 0; i < 4; i++) { m_Skin[s].Add(new BoneInfluence() { weight = reader.ReadSingle() }); } + for (int i = 0; i < 4; i++) { m_Skin[s][i].boneIndex = reader.ReadInt32(); } /*m_Skin[s] = new Dictionary(); float[] weights = new float[4] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; @@ -582,19 +582,19 @@ namespace Unity_Studio if (version[0] == 3 || (version[0] == 4 && version[1] <= 2)) { - m_BindPose = new float[a_Stream.ReadInt32()][,]; + m_BindPose = new float[reader.ReadInt32()][,]; for (int i = 0; i < m_BindPose.Length; i++) { m_BindPose[i] = new[,] { - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }, - { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() } }; + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }, + { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() } }; } } - BitArray m_CurrentChannels = new BitArray(new int[1] { a_Stream.ReadInt32() }); - m_VertexCount = a_Stream.ReadInt32(); + BitArray m_CurrentChannels = new BitArray(new int[1] { reader.ReadInt32() }); + m_VertexCount = reader.ReadInt32(); //int singleStreamStride = 0;//used tor unity 5 int streamCount = 0; @@ -603,7 +603,7 @@ namespace Unity_Studio { if (m_MeshCompression != 0 && version[2] == 0) //special case not just on platform 9 { - a_Stream.Position += 12; + reader.Position += 12; } else { @@ -611,10 +611,10 @@ namespace Unity_Studio for (int s = 0; s < 4; s++) { m_Streams[s] = new StreamInfo(); - m_Streams[s].channelMask = new BitArray(new int[1] { a_Stream.ReadInt32() }); - m_Streams[s].offset = a_Stream.ReadInt32(); - m_Streams[s].stride = a_Stream.ReadInt32(); - m_Streams[s].align = a_Stream.ReadUInt32(); + m_Streams[s].channelMask = new BitArray(new int[1] { reader.ReadInt32() }); + m_Streams[s].offset = reader.ReadInt32(); + m_Streams[s].stride = reader.ReadInt32(); + m_Streams[s].align = reader.ReadUInt32(); } } } @@ -622,14 +622,14 @@ namespace Unity_Studio #region channels and streams for 4.0.0 and later else { - m_Channels = new ChannelInfo[a_Stream.ReadInt32()]; + m_Channels = new ChannelInfo[reader.ReadInt32()]; for (int c = 0; c < m_Channels.Length; c++) { m_Channels[c] = new ChannelInfo(); - m_Channels[c].stream = a_Stream.ReadByte(); - m_Channels[c].offset = a_Stream.ReadByte(); - m_Channels[c].format = a_Stream.ReadByte(); - m_Channels[c].dimension = a_Stream.ReadByte(); + m_Channels[c].stream = reader.ReadByte(); + m_Channels[c].offset = reader.ReadByte(); + m_Channels[c].format = reader.ReadByte(); + m_Channels[c].dimension = reader.ReadByte(); //calculate stride for Unity 5 //singleStreamStride += m_Channels[c].dimension * (4 / (int)Math.Pow(2, m_Channels[c].format)); @@ -639,23 +639,23 @@ namespace Unity_Studio if (version[0] < 5) { - m_Streams = new StreamInfo[a_Stream.ReadInt32()]; + m_Streams = new StreamInfo[reader.ReadInt32()]; for (int s = 0; s < m_Streams.Length; s++) { m_Streams[s] = new StreamInfo(); - m_Streams[s].channelMask = new BitArray(new int[1] { a_Stream.ReadInt32() }); - m_Streams[s].offset = a_Stream.ReadInt32(); - m_Streams[s].stride = a_Stream.ReadByte(); - m_Streams[s].dividerOp = a_Stream.ReadByte(); - m_Streams[s].frequency = a_Stream.ReadUInt16(); + m_Streams[s].channelMask = new BitArray(new int[1] { reader.ReadInt32() }); + m_Streams[s].offset = reader.ReadInt32(); + m_Streams[s].stride = reader.ReadByte(); + m_Streams[s].dividerOp = reader.ReadByte(); + m_Streams[s].frequency = reader.ReadUInt16(); } } } #endregion //actual Vertex Buffer - byte[] m_DataSize = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_DataSize, 0, m_DataSize.Length); + byte[] m_DataSize = new byte[reader.ReadInt32()]; + reader.Read(m_DataSize, 0, m_DataSize.Length); if (version[0] >= 5) //create streams { @@ -856,14 +856,14 @@ namespace Unity_Studio #region m_Vertices PackedBitVector m_Vertices_Packed = new PackedBitVector(); - m_Vertices_Packed.m_NumItems = a_Stream.ReadInt32(); - m_Vertices_Packed.m_Range = a_Stream.ReadSingle(); - m_Vertices_Packed.m_Start = a_Stream.ReadSingle(); - m_Vertices_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Vertices_Packed.m_Data, 0, m_Vertices_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_Vertices_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_Vertices_Packed.m_NumItems = reader.ReadInt32(); + m_Vertices_Packed.m_Range = reader.ReadSingle(); + m_Vertices_Packed.m_Start = reader.ReadSingle(); + m_Vertices_Packed.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_Vertices_Packed.m_Data, 0, m_Vertices_Packed.m_Data.Length); + reader.AlignStream(4); + m_Vertices_Packed.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_Vertices_Packed.m_NumItems > 0) { @@ -881,14 +881,14 @@ namespace Unity_Studio #region m_UV PackedBitVector m_UV_Packed = new PackedBitVector(); //contains all channels - m_UV_Packed.m_NumItems = a_Stream.ReadInt32(); - m_UV_Packed.m_Range = a_Stream.ReadSingle(); - m_UV_Packed.m_Start = a_Stream.ReadSingle(); - m_UV_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_UV_Packed.m_Data, 0, m_UV_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_UV_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_UV_Packed.m_NumItems = reader.ReadInt32(); + m_UV_Packed.m_Range = reader.ReadSingle(); + m_UV_Packed.m_Start = reader.ReadSingle(); + m_UV_Packed.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_UV_Packed.m_Data, 0, m_UV_Packed.m_Data.Length); + reader.AlignStream(4); + m_UV_Packed.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_UV_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportUVs"]) { @@ -936,14 +936,14 @@ namespace Unity_Studio if (version[0] < 5) { PackedBitVector m_BindPoses_Packed = new PackedBitVector(); - m_BindPoses_Packed.m_NumItems = a_Stream.ReadInt32(); - m_BindPoses_Packed.m_Range = a_Stream.ReadSingle(); - m_BindPoses_Packed.m_Start = a_Stream.ReadSingle(); - m_BindPoses_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_BindPoses_Packed.m_Data, 0, m_BindPoses_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_BindPoses_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_BindPoses_Packed.m_NumItems = reader.ReadInt32(); + m_BindPoses_Packed.m_Range = reader.ReadSingle(); + m_BindPoses_Packed.m_Start = reader.ReadSingle(); + m_BindPoses_Packed.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_BindPoses_Packed.m_Data, 0, m_BindPoses_Packed.m_Data.Length); + reader.AlignStream(4); + m_BindPoses_Packed.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_BindPoses_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportDeformers"]) { @@ -969,41 +969,41 @@ namespace Unity_Studio #endregion PackedBitVector m_Normals_Packed = new PackedBitVector(); - m_Normals_Packed.m_NumItems = a_Stream.ReadInt32(); - m_Normals_Packed.m_Range = a_Stream.ReadSingle(); - m_Normals_Packed.m_Start = a_Stream.ReadSingle(); - m_Normals_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Normals_Packed.m_Data, 0, m_Normals_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_Normals_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_Normals_Packed.m_NumItems = reader.ReadInt32(); + m_Normals_Packed.m_Range = reader.ReadSingle(); + m_Normals_Packed.m_Start = reader.ReadSingle(); + m_Normals_Packed.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_Normals_Packed.m_Data, 0, m_Normals_Packed.m_Data.Length); + reader.AlignStream(4); + m_Normals_Packed.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment PackedBitVector m_Tangents_Packed = new PackedBitVector(); - m_Tangents_Packed.m_NumItems = a_Stream.ReadInt32(); - m_Tangents_Packed.m_Range = a_Stream.ReadSingle(); - m_Tangents_Packed.m_Start = a_Stream.ReadSingle(); - m_Tangents_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Tangents_Packed.m_Data, 0, m_Tangents_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_Tangents_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_Tangents_Packed.m_NumItems = reader.ReadInt32(); + m_Tangents_Packed.m_Range = reader.ReadSingle(); + m_Tangents_Packed.m_Start = reader.ReadSingle(); + m_Tangents_Packed.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_Tangents_Packed.m_Data, 0, m_Tangents_Packed.m_Data.Length); + reader.AlignStream(4); + m_Tangents_Packed.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment PackedBitVector m_Weights = new PackedBitVector(); - m_Weights.m_NumItems = a_Stream.ReadInt32(); - m_Weights.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Weights.m_Data, 0, m_Weights.m_Data.Length); - a_Stream.AlignStream(4); - m_Weights.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_Weights.m_NumItems = reader.ReadInt32(); + m_Weights.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_Weights.m_Data, 0, m_Weights.m_Data.Length); + reader.AlignStream(4); + m_Weights.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment #region m_Normals PackedBitVector m_NormalSigns_packed = new PackedBitVector(); - m_NormalSigns_packed.m_NumItems = a_Stream.ReadInt32(); - m_NormalSigns_packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_NormalSigns_packed.m_Data, 0, m_NormalSigns_packed.m_Data.Length); - a_Stream.AlignStream(4); - m_NormalSigns_packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_NormalSigns_packed.m_NumItems = reader.ReadInt32(); + m_NormalSigns_packed.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_NormalSigns_packed.m_Data, 0, m_NormalSigns_packed.m_Data.Length); + reader.AlignStream(4); + m_NormalSigns_packed.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_Normals_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportNormals"]) { @@ -1024,12 +1024,12 @@ namespace Unity_Studio #region m_Tangents PackedBitVector m_TangentSigns_packed = new PackedBitVector(); - m_TangentSigns_packed.m_NumItems = a_Stream.ReadInt32(); - m_TangentSigns_packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_TangentSigns_packed.m_Data, 0, m_TangentSigns_packed.m_Data.Length); - a_Stream.AlignStream(4); - m_TangentSigns_packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_TangentSigns_packed.m_NumItems = reader.ReadInt32(); + m_TangentSigns_packed.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_TangentSigns_packed.m_Data, 0, m_TangentSigns_packed.m_Data.Length); + reader.AlignStream(4); + m_TangentSigns_packed.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_Tangents_Packed.m_NumItems > 0 && (bool)Properties.Settings.Default["exportTangents"]) { @@ -1052,14 +1052,14 @@ namespace Unity_Studio if (version[0] >= 5) { PackedBitVector m_FloatColors = new PackedBitVector(); - m_FloatColors.m_NumItems = a_Stream.ReadInt32(); - m_FloatColors.m_Range = a_Stream.ReadSingle(); - m_FloatColors.m_Start = a_Stream.ReadSingle(); - m_FloatColors.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_FloatColors.m_Data, 0, m_FloatColors.m_Data.Length); - a_Stream.AlignStream(4); - m_FloatColors.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_FloatColors.m_NumItems = reader.ReadInt32(); + m_FloatColors.m_Range = reader.ReadSingle(); + m_FloatColors.m_Start = reader.ReadSingle(); + m_FloatColors.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_FloatColors.m_Data, 0, m_FloatColors.m_Data.Length); + reader.AlignStream(4); + m_FloatColors.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_FloatColors.m_NumItems > 0 && (bool)Properties.Settings.Default["exportColors"]) { @@ -1079,12 +1079,12 @@ namespace Unity_Studio #region m_Skin PackedBitVector m_BoneIndices = new PackedBitVector(); - m_BoneIndices.m_NumItems = a_Stream.ReadInt32(); - m_BoneIndices.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_BoneIndices.m_Data, 0, m_BoneIndices.m_Data.Length); - a_Stream.AlignStream(4); - m_BoneIndices.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_BoneIndices.m_NumItems = reader.ReadInt32(); + m_BoneIndices.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_BoneIndices.m_Data, 0, m_BoneIndices.m_Data.Length); + reader.AlignStream(4); + m_BoneIndices.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_BoneIndices.m_NumItems > 0 && (bool)Properties.Settings.Default["exportDeformers"]) { @@ -1166,12 +1166,12 @@ namespace Unity_Studio #endregion PackedBitVector m_Triangles = new PackedBitVector(); - m_Triangles.m_NumItems = a_Stream.ReadInt32(); - m_Triangles.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Triangles.m_Data, 0, m_Triangles.m_Data.Length); - a_Stream.AlignStream(4); - m_Triangles.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_Triangles.m_NumItems = reader.ReadInt32(); + m_Triangles.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_Triangles.m_Data, 0, m_Triangles.m_Data.Length); + reader.AlignStream(4); + m_Triangles.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_Triangles.m_NumItems > 0) { m_IndexBuffer = UnpackBitVector(m_Triangles); } } @@ -1180,14 +1180,14 @@ namespace Unity_Studio #region Colors & Collision triangles for 3.4.2 and earlier if (version[0] <= 2 || (version[0] == 3 && version[1] <= 4)) // { - a_Stream.Position += 24; //Axis-Aligned Bounding Box - int m_Colors_size = a_Stream.ReadInt32(); + reader.Position += 24; //Axis-Aligned Bounding Box + int m_Colors_size = reader.ReadInt32(); m_Colors = new float[m_Colors_size * 4]; - for (int v = 0; v < m_Colors_size * 4; v++) { m_Colors[v] = (float)(a_Stream.ReadByte()) / 0xFF; } + for (int v = 0; v < m_Colors_size * 4; v++) { m_Colors[v] = (float)(reader.ReadByte()) / 0xFF; } - int m_CollisionTriangles_size = a_Stream.ReadInt32(); - a_Stream.Position += m_CollisionTriangles_size * 4; //UInt32 indices - int m_CollisionVertexCount = a_Stream.ReadInt32(); + int m_CollisionTriangles_size = reader.ReadInt32(); + reader.Position += m_CollisionTriangles_size * 4; //UInt32 indices + int m_CollisionVertexCount = reader.ReadInt32(); } #endregion #region Compressed colors & Local AABB for 3.5.0 to 4.x.x @@ -1196,12 +1196,12 @@ namespace Unity_Studio if (version[0] < 5) { PackedBitVector m_Colors_Packed = new PackedBitVector(); - m_Colors_Packed.m_NumItems = a_Stream.ReadInt32(); - m_Colors_Packed.m_Data = new byte[a_Stream.ReadInt32()]; - a_Stream.Read(m_Colors_Packed.m_Data, 0, m_Colors_Packed.m_Data.Length); - a_Stream.AlignStream(4); - m_Colors_Packed.m_BitSize = a_Stream.ReadByte(); - a_Stream.Position += 3; //4 byte alignment + m_Colors_Packed.m_NumItems = reader.ReadInt32(); + m_Colors_Packed.m_Data = new byte[reader.ReadInt32()]; + reader.Read(m_Colors_Packed.m_Data, 0, m_Colors_Packed.m_Data.Length); + reader.AlignStream(4); + m_Colors_Packed.m_BitSize = reader.ReadByte(); + reader.Position += 3; //4 byte alignment if (m_Colors_Packed.m_NumItems > 0) { @@ -1227,13 +1227,13 @@ namespace Unity_Studio } } } - else { uint m_UVInfo = a_Stream.ReadUInt32(); } + else { uint m_UVInfo = reader.ReadUInt32(); } - a_Stream.Position += 24; //Axis-Aligned Bounding Box + reader.Position += 24; //Axis-Aligned Bounding Box } #endregion - int m_MeshUsageFlags = a_Stream.ReadInt32(); + int m_MeshUsageFlags = reader.ReadInt32(); if (version[0] >= 5) { diff --git a/Unity Studio/Unity Classes/MeshFilter.cs b/Unity Studio/Unity Classes/MeshFilter.cs index e1c181a..79b92bb 100644 --- a/Unity Studio/Unity Classes/MeshFilter.cs +++ b/Unity Studio/Unity Classes/MeshFilter.cs @@ -14,12 +14,11 @@ namespace Unity_Studio public MeshFilter(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } diff --git a/Unity Studio/Unity Classes/MeshRenderer.cs b/Unity Studio/Unity Classes/MeshRenderer.cs index 2c6ea9b..dfdbe54 100644 --- a/Unity Studio/Unity Classes/MeshRenderer.cs +++ b/Unity Studio/Unity Classes/MeshRenderer.cs @@ -18,12 +18,11 @@ namespace Unity_Studio public MeshRenderer(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } @@ -32,27 +31,27 @@ namespace Unity_Studio if (sourceFile.version[0] < 5) { - m_Enabled = a_Stream.ReadBoolean(); - m_CastShadows = a_Stream.ReadByte(); - m_ReceiveShadows = a_Stream.ReadBoolean(); - m_LightmapIndex = a_Stream.ReadByte(); + m_Enabled = reader.ReadBoolean(); + m_CastShadows = reader.ReadByte(); + m_ReceiveShadows = reader.ReadBoolean(); + m_LightmapIndex = reader.ReadByte(); } else { - m_Enabled = a_Stream.ReadBoolean(); - a_Stream.AlignStream(4); - m_CastShadows = a_Stream.ReadByte(); - m_ReceiveShadows = a_Stream.ReadBoolean(); - a_Stream.AlignStream(4); + m_Enabled = reader.ReadBoolean(); + reader.AlignStream(4); + m_CastShadows = reader.ReadByte(); + m_ReceiveShadows = reader.ReadBoolean(); + reader.AlignStream(4); - m_LightmapIndex = a_Stream.ReadUInt16(); - m_LightmapIndexDynamic = a_Stream.ReadUInt16(); + m_LightmapIndex = reader.ReadUInt16(); + m_LightmapIndexDynamic = reader.ReadUInt16(); } - if (sourceFile.version[0] >= 3) { a_Stream.Position += 16; } //Vector4f m_LightmapTilingOffset - if (sourceFile.version[0] >= 5) { a_Stream.Position += 16; } //Vector4f m_LightmapTilingOffsetDynamic + if (sourceFile.version[0] >= 3) { reader.Position += 16; } //Vector4f m_LightmapTilingOffset + if (sourceFile.version[0] >= 5) { reader.Position += 16; } //Vector4f m_LightmapTilingOffsetDynamic - m_Materials = new PPtr[a_Stream.ReadInt32()]; + m_Materials = new PPtr[reader.ReadInt32()]; for (int m = 0; m < m_Materials.Length; m++) { m_Materials[m] = sourceFile.ReadPPtr(); diff --git a/Unity Studio/Unity Classes/MonoBehaviour.cs b/Unity Studio/Unity Classes/MonoBehaviour.cs index 34fcfe7..f1e2c63 100644 --- a/Unity Studio/Unity Classes/MonoBehaviour.cs +++ b/Unity Studio/Unity Classes/MonoBehaviour.cs @@ -12,14 +12,13 @@ namespace Unity_Studio public MonoBehaviour(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; var m_GameObject = sourceFile.ReadPPtr(); - var m_Enabled = a_Stream.ReadByte(); - a_Stream.AlignStream(4); + var m_Enabled = reader.ReadByte(); + reader.AlignStream(4); var m_Script = sourceFile.ReadPPtr(); - var m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + var m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (readSwitch) { if ((serializedText = preloadData.ViewStruct()) == null) diff --git a/Unity Studio/Unity Classes/MovieTexture.cs b/Unity Studio/Unity Classes/MovieTexture.cs index 1ff4390..fd37f0b 100644 --- a/Unity Studio/Unity Classes/MovieTexture.cs +++ b/Unity Studio/Unity Classes/MovieTexture.cs @@ -13,19 +13,18 @@ namespace Unity_Studio public MovieTexture(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (readSwitch) { - var m_Loop = a_Stream.ReadBoolean(); - a_Stream.AlignStream(4); + var m_Loop = reader.ReadBoolean(); + reader.AlignStream(4); //PPtr sourceFile.ReadPPtr(); - var size = a_Stream.ReadInt32(); - m_MovieData = a_Stream.ReadBytes(size); - var m_ColorSpace = a_Stream.ReadInt32(); + var size = reader.ReadInt32(); + m_MovieData = reader.ReadBytes(size); + var m_ColorSpace = reader.ReadInt32(); } else { diff --git a/Unity Studio/Unity Classes/PlayerSettings.cs b/Unity Studio/Unity Classes/PlayerSettings.cs index 0e3d6bc..09705f4 100644 --- a/Unity Studio/Unity Classes/PlayerSettings.cs +++ b/Unity Studio/Unity Classes/PlayerSettings.cs @@ -13,45 +13,44 @@ namespace Unity_Studio public PlayerSettings(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if ((sourceFile.version[0] == 5 && sourceFile.version[1] >= 4) || sourceFile.version[0] > 5)//5.4.0 nad up { //productGUID - a_Stream.ReadInt32(); - a_Stream.ReadInt32(); - a_Stream.ReadInt32(); - a_Stream.ReadInt32(); + reader.ReadInt32(); + reader.ReadInt32(); + reader.ReadInt32(); + reader.ReadInt32(); } if (sourceFile.version[0] >= 3) { - if (sourceFile.version[0] == 3 && sourceFile.version[1] < 2) { string AndroidLicensePublicKey = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); } - else { bool AndroidProfiler = a_Stream.ReadBoolean(); a_Stream.AlignStream(4); } + if (sourceFile.version[0] == 3 && sourceFile.version[1] < 2) { string AndroidLicensePublicKey = reader.ReadAlignedString(reader.ReadInt32()); } + else { bool AndroidProfiler = reader.ReadBoolean(); reader.AlignStream(4); } - int defaultScreenOrientation = a_Stream.ReadInt32(); - int targetDevice = a_Stream.ReadInt32(); + int defaultScreenOrientation = reader.ReadInt32(); + int targetDevice = reader.ReadInt32(); if (sourceFile.version[0] < 5 || (sourceFile.version[0] == 5 && sourceFile.version[1] < 1)) - { int targetGlesGraphics = a_Stream.ReadInt32(); } + { int targetGlesGraphics = reader.ReadInt32(); } if ((sourceFile.version[0] == 5 && sourceFile.version[1] < 1) || (sourceFile.version[0] == 4 && sourceFile.version[1] == 6 && sourceFile.version[2] >= 3)) - { int targetIOSGraphics = a_Stream.ReadInt32(); } + { int targetIOSGraphics = reader.ReadInt32(); } if (sourceFile.version[0] >= 5 || sourceFile.version[0] == 5 && (sourceFile.version[1] > 2 || (sourceFile.version[1] == 2 && sourceFile.version[2] >= 1))) - { bool useOnDemandResources = a_Stream.ReadBoolean(); a_Stream.AlignStream(4); } + { bool useOnDemandResources = reader.ReadBoolean(); reader.AlignStream(4); } if (sourceFile.version[0] < 5 || (sourceFile.version[0] == 5 && sourceFile.version[1] < 3)) - { int targetResolution = a_Stream.ReadInt32(); } + { int targetResolution = reader.ReadInt32(); } - if (sourceFile.version[0] == 3 && sourceFile.version[1] <= 1) { bool OverrideIPodMusic = a_Stream.ReadBoolean(); a_Stream.AlignStream(4); } + if (sourceFile.version[0] == 3 && sourceFile.version[1] <= 1) { bool OverrideIPodMusic = reader.ReadBoolean(); reader.AlignStream(4); } else if (sourceFile.version[0] == 3 && sourceFile.version[1] <= 4) { } - else { int accelerometerFrequency = a_Stream.ReadInt32(); }//3.5.0 and up + else { int accelerometerFrequency = reader.ReadInt32(); }//3.5.0 and up } //fail in Unity 5 beta - companyName = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - productName = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + companyName = reader.ReadAlignedString(reader.ReadInt32()); + productName = reader.ReadAlignedString(reader.ReadInt32()); } } } diff --git a/Unity Studio/Unity Classes/Shader.cs b/Unity Studio/Unity Classes/Shader.cs index 7d4b540..6051659 100644 --- a/Unity Studio/Unity Classes/Shader.cs +++ b/Unity Studio/Unity Classes/Shader.cs @@ -16,17 +16,16 @@ namespace Unity_Studio public Shader(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (readSwitch) { @@ -43,23 +42,23 @@ namespace Unity_Studio } else { - a_Stream.Position = preloadData.Offset; + reader.Position = preloadData.Offset; var sb = new StringBuilder(); var members = new JavaScriptSerializer().Deserialize>(str); - ClassStructHelper.ReadClassStruct(sb, members, a_Stream); + ClassStructHelper.ReadClassStruct(sb, members, reader); m_Script = Encoding.UTF8.GetBytes(sb.ToString()); //m_Script = ReadSerializedShader(members, a_Stream); } } else { - m_Script = a_Stream.ReadBytes(a_Stream.ReadInt32()); + m_Script = reader.ReadBytes(reader.ReadInt32()); if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 3) //5.3 - 5.4 { - a_Stream.AlignStream(4); - a_Stream.ReadAlignedString(a_Stream.ReadInt32());//m_PathName - var decompressedSize = a_Stream.ReadUInt32(); - var m_SubProgramBlob = a_Stream.ReadBytes(a_Stream.ReadInt32()); + reader.AlignStream(4); + reader.ReadAlignedString(reader.ReadInt32());//m_PathName + var decompressedSize = reader.ReadUInt32(); + var m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32()); var decompressedBytes = new byte[decompressedSize]; using (var mstream = new MemoryStream(m_SubProgramBlob)) { diff --git a/Unity Studio/Unity Classes/SkinnedMeshRenderer.cs b/Unity Studio/Unity Classes/SkinnedMeshRenderer.cs index 3a0e4ce..42b28ce 100644 --- a/Unity Studio/Unity Classes/SkinnedMeshRenderer.cs +++ b/Unity Studio/Unity Classes/SkinnedMeshRenderer.cs @@ -21,12 +21,11 @@ namespace Unity_Studio { var sourceFile = preloadData.sourceFile; var version = preloadData.sourceFile.version; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } @@ -34,27 +33,27 @@ namespace Unity_Studio m_GameObject = sourceFile.ReadPPtr(); if (sourceFile.version[0] < 5) { - m_Enabled = a_Stream.ReadBoolean(); - m_CastShadows = a_Stream.ReadByte();//bool - m_ReceiveShadows = a_Stream.ReadBoolean(); - m_LightmapIndex = a_Stream.ReadByte(); + m_Enabled = reader.ReadBoolean(); + m_CastShadows = reader.ReadByte();//bool + m_ReceiveShadows = reader.ReadBoolean(); + m_LightmapIndex = reader.ReadByte(); } else { - m_Enabled = a_Stream.ReadBoolean(); - a_Stream.AlignStream(4); - m_CastShadows = a_Stream.ReadByte(); - m_ReceiveShadows = a_Stream.ReadBoolean(); - a_Stream.AlignStream(4); + m_Enabled = reader.ReadBoolean(); + reader.AlignStream(4); + m_CastShadows = reader.ReadByte(); + m_ReceiveShadows = reader.ReadBoolean(); + reader.AlignStream(4); - m_LightmapIndex = a_Stream.ReadUInt16(); - m_LightmapIndexDynamic = a_Stream.ReadUInt16(); + m_LightmapIndex = reader.ReadUInt16(); + m_LightmapIndexDynamic = reader.ReadUInt16(); } - if (version[0] >= 3) { a_Stream.Position += 16; } //m_LightmapTilingOffset vector4d - if (sourceFile.version[0] >= 5) { a_Stream.Position += 16; } //Vector4f m_LightmapTilingOffsetDynamic + if (version[0] >= 3) { reader.Position += 16; } //m_LightmapTilingOffset vector4d + if (sourceFile.version[0] >= 5) { reader.Position += 16; } //Vector4f m_LightmapTilingOffsetDynamic - m_Materials = new PPtr[a_Stream.ReadInt32()]; + m_Materials = new PPtr[reader.ReadInt32()]; for (int m = 0; m < m_Materials.Length; m++) { m_Materials[m] = sourceFile.ReadPPtr(); @@ -62,18 +61,18 @@ namespace Unity_Studio if (version[0] < 3) { - a_Stream.Position += 16;//m_LightmapTilingOffset vector4d + reader.Position += 16;//m_LightmapTilingOffset vector4d } else { if ((sourceFile.version[0] == 5 && sourceFile.version[1] >= 5) || sourceFile.version[0] > 5)//5.5.0 and up { - a_Stream.Position += 4;//m_StaticBatchInfo + reader.Position += 4;//m_StaticBatchInfo } else { - int m_SubsetIndices_size = a_Stream.ReadInt32(); - a_Stream.Position += m_SubsetIndices_size * 4; + int m_SubsetIndices_size = reader.ReadInt32(); + reader.Position += m_SubsetIndices_size * 4; } PPtr m_StaticBatchRoot = sourceFile.ReadPPtr(); @@ -84,27 +83,27 @@ namespace Unity_Studio } else if (version[0] >= 4 || (version[0] == 3 && version[1] >= 5)) { - bool m_UseLightProbes = a_Stream.ReadBoolean(); - a_Stream.Position += 3; //alignment - if (version[0] == 5) { int m_ReflectionProbeUsage = a_Stream.ReadInt32(); } + bool m_UseLightProbes = reader.ReadBoolean(); + reader.Position += 3; //alignment + if (version[0] == 5) { int m_ReflectionProbeUsage = reader.ReadInt32(); } //did I ever check if the anchor is conditioned by the bool? PPtr m_LightProbeAnchor = sourceFile.ReadPPtr(); } if (version[0] >= 5 || (version[0] == 4 && version[1] >= 3)) { - if (version[0] == 4 && version[1] <= 3) { int m_SortingLayer = a_Stream.ReadInt16(); } - else { int m_SortingLayer = a_Stream.ReadInt32(); } + if (version[0] == 4 && version[1] <= 3) { int m_SortingLayer = reader.ReadInt16(); } + else { int m_SortingLayer = reader.ReadInt32(); } - int m_SortingOrder = a_Stream.ReadInt16(); - a_Stream.AlignStream(4); + int m_SortingOrder = reader.ReadInt16(); + reader.AlignStream(4); } } - int m_Quality = a_Stream.ReadInt32(); - bool m_UpdateWhenOffscreen = a_Stream.ReadBoolean(); - bool m_SkinNormals = a_Stream.ReadBoolean(); //3.1.0 and below - a_Stream.Position += 2; + int m_Quality = reader.ReadInt32(); + bool m_UpdateWhenOffscreen = reader.ReadBoolean(); + bool m_SkinNormals = reader.ReadBoolean(); //3.1.0 and below + reader.Position += 2; if (version[0] == 2 && version[1] < 6) { @@ -114,7 +113,7 @@ namespace Unity_Studio m_Mesh = sourceFile.ReadPPtr(); - m_Bones = new PPtr[a_Stream.ReadInt32()]; + m_Bones = new PPtr[reader.ReadInt32()]; for (int b = 0; b < m_Bones.Length; b++) { m_Bones[b] = sourceFile.ReadPPtr(); @@ -122,15 +121,15 @@ namespace Unity_Studio if (version[0] < 3) { - int m_BindPose = a_Stream.ReadInt32(); - a_Stream.Position += m_BindPose * 16 * 4;//Matrix4x4f + int m_BindPose = reader.ReadInt32(); + reader.Position += m_BindPose * 16 * 4;//Matrix4x4f } else { if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) { - int m_BlendShapeWeights = a_Stream.ReadInt32(); - a_Stream.Position += m_BlendShapeWeights * 4; //floats + int m_BlendShapeWeights = reader.ReadInt32(); + reader.Position += m_BlendShapeWeights * 4; //floats } if (version[0] > 4 || (version[0] >= 3 && version[1] >= 5)) @@ -141,9 +140,9 @@ namespace Unity_Studio if (version[0] > 4 || (version[0] == 3 && version[1] >= 4)) { //AABB - float[] m_Center = { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; - float[] m_Extent = { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; - bool m_DirtyAABB = a_Stream.ReadBoolean(); + float[] m_Center = { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }; + float[] m_Extent = { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }; + bool m_DirtyAABB = reader.ReadBoolean(); } } } diff --git a/Unity Studio/Unity Classes/Sprite.cs b/Unity Studio/Unity Classes/Sprite.cs index 83d5d9e..c79af8b 100644 --- a/Unity Studio/Unity Classes/Sprite.cs +++ b/Unity Studio/Unity Classes/Sprite.cs @@ -21,8 +21,7 @@ namespace Unity_Studio public Sprite(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.sourceFile.assetsFileReader; - reader.Position = preloadData.Offset; + var reader = preloadData.Reader; var version = sourceFile.version; m_Name = reader.ReadAlignedString(reader.ReadInt32()); @@ -163,7 +162,6 @@ namespace Unity_Studio } else { - preloadData.extension = ".png"; preloadData.Text = m_Name; } } diff --git a/Unity Studio/Unity Classes/SpriteAtlas.cs b/Unity Studio/Unity Classes/SpriteAtlas.cs index 66c1fde..e323af3 100644 --- a/Unity Studio/Unity Classes/SpriteAtlas.cs +++ b/Unity Studio/Unity Classes/SpriteAtlas.cs @@ -16,8 +16,7 @@ namespace Unity_Studio public SpriteAtlas(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var reader = preloadData.sourceFile.assetsFileReader; - reader.Position = preloadData.Offset; + var reader = preloadData.Reader; var m_Name = reader.ReadAlignedString(reader.ReadInt32()); //vector m_PackedSprites diff --git a/Unity Studio/Unity Classes/TextAsset.cs b/Unity Studio/Unity Classes/TextAsset.cs index fe9023a..6770733 100644 --- a/Unity Studio/Unity Classes/TextAsset.cs +++ b/Unity Studio/Unity Classes/TextAsset.cs @@ -14,21 +14,20 @@ namespace Unity_Studio public TextAsset(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (readSwitch) { - m_Script = a_Stream.ReadBytes(a_Stream.ReadInt32()); + m_Script = reader.ReadBytes(reader.ReadInt32()); } else { diff --git a/Unity Studio/Unity Classes/Texture2D.cs b/Unity Studio/Unity Classes/Texture2D.cs index 5360b47..78dd9ee 100644 --- a/Unity Studio/Unity Classes/Texture2D.cs +++ b/Unity Studio/Unity Classes/Texture2D.cs @@ -91,61 +91,60 @@ namespace Unity_Studio public Texture2D(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; version = sourceFile.version; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3))//2017.3 and up { - var m_ForcedFallbackFormat = a_Stream.ReadInt32(); - var m_DownscaleFallback = a_Stream.ReadBoolean(); - a_Stream.AlignStream(4); + var m_ForcedFallbackFormat = reader.ReadInt32(); + var m_DownscaleFallback = reader.ReadBoolean(); + reader.AlignStream(4); } - m_Width = a_Stream.ReadInt32(); - m_Height = a_Stream.ReadInt32(); - m_CompleteImageSize = a_Stream.ReadInt32(); - m_TextureFormat = (TextureFormat)a_Stream.ReadInt32(); + m_Width = reader.ReadInt32(); + m_Height = reader.ReadInt32(); + m_CompleteImageSize = reader.ReadInt32(); + m_TextureFormat = (TextureFormat)reader.ReadInt32(); if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) - { m_MipMap = a_Stream.ReadBoolean(); } + { m_MipMap = reader.ReadBoolean(); } else { dwFlags += 0x20000; - dwMipMapCount = a_Stream.ReadInt32();//is this with or without main image? + dwMipMapCount = reader.ReadInt32();//is this with or without main image? dwCaps += 0x400008; } - m_IsReadable = a_Stream.ReadBoolean(); //2.6.0 and up - m_ReadAllowed = a_Stream.ReadBoolean(); //3.0.0 - 5.4 - a_Stream.AlignStream(4); + m_IsReadable = reader.ReadBoolean(); //2.6.0 and up + m_ReadAllowed = reader.ReadBoolean(); //3.0.0 - 5.4 + reader.AlignStream(4); - m_ImageCount = a_Stream.ReadInt32(); - m_TextureDimension = a_Stream.ReadInt32(); + m_ImageCount = reader.ReadInt32(); + m_TextureDimension = reader.ReadInt32(); //m_TextureSettings - m_FilterMode = a_Stream.ReadInt32(); - m_Aniso = a_Stream.ReadInt32(); - m_MipBias = a_Stream.ReadSingle(); - m_WrapMode = a_Stream.ReadInt32(); + m_FilterMode = reader.ReadInt32(); + m_Aniso = reader.ReadInt32(); + m_MipBias = reader.ReadSingle(); + m_WrapMode = reader.ReadInt32(); if (version[0] >= 2017)//2017.x and up { - int m_WrapV = a_Stream.ReadInt32(); - int m_WrapW = a_Stream.ReadInt32(); + int m_WrapV = reader.ReadInt32(); + int m_WrapW = reader.ReadInt32(); } if (version[0] >= 3) { - m_LightmapFormat = a_Stream.ReadInt32(); - if (version[0] >= 4 || version[1] >= 5) { m_ColorSpace = a_Stream.ReadInt32(); } //3.5.0 and up + m_LightmapFormat = reader.ReadInt32(); + if (version[0] >= 4 || version[1] >= 5) { m_ColorSpace = reader.ReadInt32(); } //3.5.0 and up } - image_data_size = a_Stream.ReadInt32(); + image_data_size = reader.ReadInt32(); if (m_MipMap) { @@ -156,10 +155,10 @@ namespace Unity_Studio if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up { - offset = a_Stream.ReadUInt32(); - size = a_Stream.ReadUInt32(); + offset = reader.ReadUInt32(); + size = reader.ReadUInt32(); image_data_size = (int)size; - path = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + path = reader.ReadAlignedString(reader.ReadInt32()); } if (readSwitch) @@ -178,18 +177,18 @@ namespace Unity_Studio } if (File.Exists(resourceFilePath)) { - using (var reader = new BinaryReader(File.OpenRead(resourceFilePath))) + using (var resourceReader = new BinaryReader(File.OpenRead(resourceFilePath))) { - reader.BaseStream.Position = offset; - image_data = reader.ReadBytes(image_data_size); + resourceReader.BaseStream.Position = offset; + image_data = resourceReader.ReadBytes(image_data_size); } } else { - if (UnityStudio.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader)) + if (UnityStudio.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var resourceReader)) { - reader.Position = offset; - image_data = reader.ReadBytes(image_data_size); + resourceReader.Position = offset; + image_data = resourceReader.ReadBytes(image_data_size); } else { @@ -199,7 +198,7 @@ namespace Unity_Studio } else { - image_data = a_Stream.ReadBytes(image_data_size); + image_data = reader.ReadBytes(image_data_size); } switch (m_TextureFormat) @@ -776,187 +775,4 @@ namespace Unity_Studio dwABitMask = -16777216; } } -} - -public static class KTXHeader -{ - public static byte[] IDENTIFIER = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }; - public static byte[] ENDIANESS_LE = { 1, 2, 3, 4 }; - public static byte[] ENDIANESS_BE = { 4, 3, 2, 1 }; - - // constants for glInternalFormat - public static int GL_ETC1_RGB8_OES = 0x8D64; - - public static int GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; - public static int GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; - public static int GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; - public static int GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; - - public static int GL_ATC_RGB_AMD = 0x8C92; - public static int GL_ATC_RGBA_EXPLICIT_ALPHA_AMD = 0x8C93; - public static int GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD = 0x87EE; - - public static int GL_COMPRESSED_RGB8_ETC2 = 0x9274; - public static int GL_COMPRESSED_SRGB8_ETC2 = 0x9275; - public static int GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276; - public static int GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277; - public static int GL_COMPRESSED_RGBA8_ETC2_EAC = 0x9278; - public static int GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279; - public static int GL_COMPRESSED_R11_EAC = 0x9270; - public static int GL_COMPRESSED_SIGNED_R11_EAC = 0x9271; - public static int GL_COMPRESSED_RG11_EAC = 0x9272; - public static int GL_COMPRESSED_SIGNED_RG11_EAC = 0x9273; - - public static int GL_COMPRESSED_RED_RGTC1 = 0x8DBB; - public static int GL_COMPRESSED_RG_RGTC2 = 0x8DBD; - public static int GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F; - public static int GL_COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C; - - public static int GL_R16F = 0x822D; - public static int GL_RG16F = 0x822F; - public static int GL_RGBA16F = 0x881A; - public static int GL_R32F = 0x822E; - public static int GL_RG32F = 0x8230; - public static int GL_RGBA32F = 0x8814; - - // constants for glBaseInternalFormat - public static int GL_RED = 0x1903; - public static int GL_GREEN = 0x1904; - public static int GL_BLUE = 0x1905; - public static int GL_ALPHA = 0x1906; - public static int GL_RGB = 0x1907; - public static int GL_RGBA = 0x1908; - public static int GL_RG = 0x8227; -} - -//from TextureConverter.h -public enum QFORMAT -{ - // General formats - Q_FORMAT_RGBA_8UI = 1, - Q_FORMAT_RGBA_8I, - Q_FORMAT_RGB5_A1UI, - Q_FORMAT_RGBA_4444, - Q_FORMAT_RGBA_16UI, - Q_FORMAT_RGBA_16I, - Q_FORMAT_RGBA_32UI, - Q_FORMAT_RGBA_32I, - - Q_FORMAT_PALETTE_8_RGBA_8888, - Q_FORMAT_PALETTE_8_RGBA_5551, - Q_FORMAT_PALETTE_8_RGBA_4444, - Q_FORMAT_PALETTE_4_RGBA_8888, - Q_FORMAT_PALETTE_4_RGBA_5551, - Q_FORMAT_PALETTE_4_RGBA_4444, - Q_FORMAT_PALETTE_1_RGBA_8888, - Q_FORMAT_PALETTE_8_RGB_888, - Q_FORMAT_PALETTE_8_RGB_565, - Q_FORMAT_PALETTE_4_RGB_888, - Q_FORMAT_PALETTE_4_RGB_565, - - Q_FORMAT_R2_GBA10UI, - Q_FORMAT_RGB10_A2UI, - Q_FORMAT_RGB10_A2I, - Q_FORMAT_RGBA_F, - Q_FORMAT_RGBA_HF, - - Q_FORMAT_RGB9_E5, // Last five bits are exponent bits (Read following section in GLES3 spec: "3.8.17 Shared Exponent Texture Color Conversion") - Q_FORMAT_RGB_8UI, - Q_FORMAT_RGB_8I, - Q_FORMAT_RGB_565, - Q_FORMAT_RGB_16UI, - Q_FORMAT_RGB_16I, - Q_FORMAT_RGB_32UI, - Q_FORMAT_RGB_32I, - - Q_FORMAT_RGB_F, - Q_FORMAT_RGB_HF, - Q_FORMAT_RGB_11_11_10_F, - - Q_FORMAT_RG_F, - Q_FORMAT_RG_HF, - Q_FORMAT_RG_32UI, - Q_FORMAT_RG_32I, - Q_FORMAT_RG_16I, - Q_FORMAT_RG_16UI, - Q_FORMAT_RG_8I, - Q_FORMAT_RG_8UI, - Q_FORMAT_RG_S88, - - Q_FORMAT_R_32UI, - Q_FORMAT_R_32I, - Q_FORMAT_R_F, - Q_FORMAT_R_16F, - Q_FORMAT_R_16I, - Q_FORMAT_R_16UI, - Q_FORMAT_R_8I, - Q_FORMAT_R_8UI, - - Q_FORMAT_LUMINANCE_ALPHA_88, - Q_FORMAT_LUMINANCE_8, - Q_FORMAT_ALPHA_8, - - Q_FORMAT_LUMINANCE_ALPHA_F, - Q_FORMAT_LUMINANCE_F, - Q_FORMAT_ALPHA_F, - Q_FORMAT_LUMINANCE_ALPHA_HF, - Q_FORMAT_LUMINANCE_HF, - Q_FORMAT_ALPHA_HF, - Q_FORMAT_DEPTH_16, - Q_FORMAT_DEPTH_24, - Q_FORMAT_DEPTH_24_STENCIL_8, - Q_FORMAT_DEPTH_32, - - Q_FORMAT_BGR_565, - Q_FORMAT_BGRA_8888, - Q_FORMAT_BGRA_5551, - Q_FORMAT_BGRX_8888, - Q_FORMAT_BGRA_4444, - // Compressed formats - Q_FORMAT_ATITC_RGBA, - Q_FORMAT_ATC_RGBA_EXPLICIT_ALPHA = Q_FORMAT_ATITC_RGBA, - Q_FORMAT_ATITC_RGB, - Q_FORMAT_ATC_RGB = Q_FORMAT_ATITC_RGB, - Q_FORMAT_ATC_RGBA_INTERPOLATED_ALPHA, - Q_FORMAT_ETC1_RGB8, - Q_FORMAT_3DC_X, - Q_FORMAT_3DC_XY, - - Q_FORMAT_ETC2_RGB8, - Q_FORMAT_ETC2_RGBA8, - Q_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1, - Q_FORMAT_ETC2_SRGB8, - Q_FORMAT_ETC2_SRGB8_ALPHA8, - Q_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, - Q_FORMAT_EAC_R_SIGNED, - Q_FORMAT_EAC_R_UNSIGNED, - Q_FORMAT_EAC_RG_SIGNED, - Q_FORMAT_EAC_RG_UNSIGNED, - - Q_FORMAT_S3TC_DXT1_RGB, - Q_FORMAT_S3TC_DXT1_RGBA, - Q_FORMAT_S3TC_DXT3_RGBA, - Q_FORMAT_S3TC_DXT5_RGBA, - - // YUV formats - Q_FORMAT_AYUV_32, - Q_FORMAT_I444_24, - Q_FORMAT_YUYV_16, - Q_FORMAT_UYVY_16, - Q_FORMAT_I420_12, - Q_FORMAT_YV12_12, - Q_FORMAT_NV21_12, - Q_FORMAT_NV12_12, - - // ASTC Format - Q_FORMAT_ASTC_8, - Q_FORMAT_ASTC_16, -}; - -public enum texgenpack_texturetype -{ - RGTC1, - RGTC2, - BPTC_FLOAT, - BPTC } \ No newline at end of file diff --git a/Unity Studio/Unity Classes/Transform.cs b/Unity Studio/Unity Classes/Transform.cs index b30ec2a..9f60038 100644 --- a/Unity Studio/Unity Classes/Transform.cs +++ b/Unity Studio/Unity Classes/Transform.cs @@ -17,21 +17,20 @@ namespace Unity_Studio public Transform(AssetPreloadData preloadData) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; if (sourceFile.platform == -2) { - uint m_ObjectHideFlags = a_Stream.ReadUInt32(); + uint m_ObjectHideFlags = reader.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } m_GameObject = sourceFile.ReadPPtr(); - m_LocalRotation = new[] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; - m_LocalPosition = new[] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; - m_LocalScale = new[] { a_Stream.ReadSingle(), a_Stream.ReadSingle(), a_Stream.ReadSingle() }; - int m_ChildrenCount = a_Stream.ReadInt32(); + m_LocalRotation = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }; + m_LocalPosition = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }; + m_LocalScale = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }; + int m_ChildrenCount = reader.ReadInt32(); for (int j = 0; j < m_ChildrenCount; j++) { m_Children.Add(sourceFile.ReadPPtr()); diff --git a/Unity Studio/Unity Classes/VideoClip.cs b/Unity Studio/Unity Classes/VideoClip.cs index 32da4a2..dacd716 100644 --- a/Unity Studio/Unity Classes/VideoClip.cs +++ b/Unity Studio/Unity Classes/VideoClip.cs @@ -15,41 +15,40 @@ namespace Unity_Studio public VideoClip(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; - var a_Stream = preloadData.sourceFile.assetsFileReader; - a_Stream.Position = preloadData.Offset; + var reader = preloadData.Reader; - m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - var m_OriginalPath = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - var m_ProxyWidth = a_Stream.ReadUInt32(); - var m_ProxyHeight = a_Stream.ReadUInt32(); - var Width = a_Stream.ReadUInt32(); - var Height = a_Stream.ReadUInt32(); + m_Name = reader.ReadAlignedString(reader.ReadInt32()); + var m_OriginalPath = reader.ReadAlignedString(reader.ReadInt32()); + var m_ProxyWidth = reader.ReadUInt32(); + var m_ProxyHeight = reader.ReadUInt32(); + var Width = reader.ReadUInt32(); + var Height = reader.ReadUInt32(); if (sourceFile.version[0] >= 2017)//2017.x and up { - var m_PixelAspecRatioNum = a_Stream.ReadUInt32(); - var m_PixelAspecRatioDen = a_Stream.ReadUInt32(); + var m_PixelAspecRatioNum = reader.ReadUInt32(); + var m_PixelAspecRatioDen = reader.ReadUInt32(); } - var m_FrameRate = a_Stream.ReadDouble(); - var m_FrameCount = a_Stream.ReadUInt64(); - var m_Format = a_Stream.ReadInt32(); + var m_FrameRate = reader.ReadDouble(); + var m_FrameCount = reader.ReadUInt64(); + var m_Format = reader.ReadInt32(); //m_AudioChannelCount - var size = a_Stream.ReadInt32(); - a_Stream.Position += size * 2; - a_Stream.AlignStream(4); + var size = reader.ReadInt32(); + reader.Position += size * 2; + reader.AlignStream(4); //m_AudioSampleRate - size = a_Stream.ReadInt32(); - a_Stream.Position += size * 4; + size = reader.ReadInt32(); + reader.Position += size * 4; //m_AudioLanguage - size = a_Stream.ReadInt32(); + size = reader.ReadInt32(); for (int i = 0; i < size; i++) { - a_Stream.ReadAlignedString(a_Stream.ReadInt32()); + reader.ReadAlignedString(reader.ReadInt32()); } //StreamedResource m_ExternalResources - var m_Source = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - var m_Offset = a_Stream.ReadUInt64(); - var m_Size = a_Stream.ReadUInt64(); - var m_HasSplitAlpha = a_Stream.ReadBoolean(); + var m_Source = reader.ReadAlignedString(reader.ReadInt32()); + var m_Offset = reader.ReadUInt64(); + var m_Size = reader.ReadUInt64(); + var m_HasSplitAlpha = reader.ReadBoolean(); if (readSwitch) { @@ -67,18 +66,18 @@ namespace Unity_Studio } if (File.Exists(resourceFilePath)) { - using (var reader = new BinaryReader(File.OpenRead(resourceFilePath))) + using (var resourceReader = new BinaryReader(File.OpenRead(resourceFilePath))) { - reader.BaseStream.Position = (long)m_Offset; - m_VideoData = reader.ReadBytes((int)m_Size); + resourceReader.BaseStream.Position = (long)m_Offset; + m_VideoData = resourceReader.ReadBytes((int)m_Size); } } else { - if (UnityStudio.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader)) + if (UnityStudio.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var resourceReader)) { - reader.Position = (long)m_Offset; - m_VideoData = reader.ReadBytes((int)m_Size); + resourceReader.Position = (long)m_Offset; + m_VideoData = resourceReader.ReadBytes((int)m_Size); } else { @@ -89,7 +88,7 @@ namespace Unity_Studio else { if (m_Size > 0) - m_VideoData = a_Stream.ReadBytes((int)m_Size); + m_VideoData = reader.ReadBytes((int)m_Size); } } else diff --git a/Unity Studio/Unity Studio Classes/AssetPreloadData.cs b/Unity Studio/Unity Studio Classes/AssetPreloadData.cs index a9d5688..56d7c94 100644 --- a/Unity Studio/Unity Studio Classes/AssetPreloadData.cs +++ b/Unity Studio/Unity Studio Classes/AssetPreloadData.cs @@ -21,5 +21,15 @@ namespace Unity_Studio public AssetsFile sourceFile; public string uniqueID; + + public EndianBinaryReader Reader + { + get + { + var reader = sourceFile.assetsFileReader; + reader.Position = Offset; + return reader; + } + } } } diff --git a/Unity Studio/Unity Studio Classes/ClassStruct.cs b/Unity Studio/Unity Studio Classes/ClassStruct.cs index 68bac55..d192939 100644 --- a/Unity Studio/Unity Studio Classes/ClassStruct.cs +++ b/Unity Studio/Unity Studio Classes/ClassStruct.cs @@ -41,18 +41,17 @@ namespace Unity_Studio { public static string ViewStruct(this AssetPreloadData asset) { - var a_Stream = asset.sourceFile.assetsFileReader; - a_Stream.Position = asset.Offset; + var reader = asset.Reader; if (asset.sourceFile.ClassStructures.TryGetValue(asset.Type1, out var classStructure)) { var sb = new StringBuilder(); - ReadClassStruct(sb, classStructure.members, a_Stream); + ReadClassStruct(sb, classStructure.members, reader); return sb.ToString(); } return null; } - public static void ReadClassStruct(StringBuilder sb, List members, EndianBinaryReader a_Stream) + public static void ReadClassStruct(StringBuilder sb, List members, EndianBinaryReader reader) { for (int i = 0; i < members.Count; i++) { @@ -64,97 +63,96 @@ namespace Unity_Studio var align = (member.Flag & 0x4000) != 0; var append = true; if (member.alignBefore) - a_Stream.AlignStream(4); - if (varTypeStr == "SInt8")//sbyte + reader.AlignStream(4); + switch (varTypeStr) { - value = a_Stream.ReadSByte(); - } - else if (varTypeStr == "UInt8")//byte - { - value = a_Stream.ReadByte(); - } - else if (varTypeStr == "short" || varTypeStr == "SInt16")//Int16 - { - value = a_Stream.ReadInt16(); - } - else if (varTypeStr == "UInt16" || varTypeStr == "unsigned short")//UInt16 - { - value = a_Stream.ReadUInt16(); - } - else if (varTypeStr == "int" || varTypeStr == "SInt32")//Int32 - { - value = a_Stream.ReadInt32(); - } - else if (varTypeStr == "UInt32" || varTypeStr == "unsigned int" || varTypeStr == "Type*")//UInt32 - { - value = a_Stream.ReadUInt32(); - } - else if (varTypeStr == "long long" || varTypeStr == "SInt64")//Int64 - { - value = a_Stream.ReadInt64(); - } - else if (varTypeStr == "UInt64" || varTypeStr == "unsigned long long")//UInt64 - { - value = a_Stream.ReadUInt64(); - } - else if (varTypeStr == "float")//float - { - value = a_Stream.ReadSingle(); - } - else if (varTypeStr == "double")//double - { - value = a_Stream.ReadDouble(); - } - else if (varTypeStr == "bool")//bool - { - value = a_Stream.ReadBoolean(); - } - else if (varTypeStr == "string")//string - { - append = false; - var str = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); - sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str); - i += 3;//skip - } - else if (varTypeStr == "Array")//Array - { - append = false; - if ((members[i - 1].Flag & 0x4000) != 0) - align = true; - sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); - var size = a_Stream.ReadInt32(); - sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), "int", "size", size); - var array = ReadArray(members, level, i); - for (int j = 0; j < size; j++) - { - sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 1)), j); - ReadClassStruct(sb, array, a_Stream); - } - i += array.Count + 1;//skip - } - else if (varTypeStr == "TypelessData") - { - append = false; - var size = a_Stream.ReadInt32(); - a_Stream.ReadBytes(size); - i += 2; - sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); - sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), "int", "size", size); - } - else - { - append = false; - if (align) - { - align = false; - SetAlignBefore(members, level, i + 1); - } - sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); + case "SInt8": + value = reader.ReadSByte(); + break; + case "UInt8": + value = reader.ReadByte(); + break; + case "short": + case "SInt16": + value = reader.ReadInt16(); + break; + case "UInt16": + case "unsigned short": + value = reader.ReadUInt16(); + break; + case "int": + case "SInt32": + value = reader.ReadInt32(); + break; + case "UInt32": + case "unsigned int": + case "Type*": + value = reader.ReadUInt32(); + break; + case "long long": + case "SInt64": + value = reader.ReadInt64(); + break; + case "UInt64": + case "unsigned long long": + value = reader.ReadUInt64(); + break; + case "float": + value = reader.ReadSingle(); + break; + case "double": + value = reader.ReadDouble(); + break; + case "bool": + value = reader.ReadBoolean(); + break; + case "string": + append = false; + var str = reader.ReadAlignedString(reader.ReadInt32()); + sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str); + i += 3;//skip + break; + case "Array": + { + append = false; + if ((members[i - 1].Flag & 0x4000) != 0) + align = true; + sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); + var size = reader.ReadInt32(); + sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), "int", "size", size); + var array = ReadArray(members, level, i); + for (int j = 0; j < size; j++) + { + sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 1)), j); + ReadClassStruct(sb, array, reader); + } + i += array.Count + 1;//skip + break; + } + case "TypelessData": + { + append = false; + var size = reader.ReadInt32(); + reader.ReadBytes(size); + i += 2; + sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); + sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), "int", "size", size); + break; + } + default: + append = false; + if (align) + { + align = false; + SetAlignBefore(members, level, i + 1); + } + sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); + break; } if (append) sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), varTypeStr, varNameStr, value); if (align) - a_Stream.AlignStream(4); + reader.AlignStream(4); } } diff --git a/Unity Studio/Unity Studio Classes/FBXExporter.cs b/Unity Studio/Unity Studio Classes/FBXExporter.cs new file mode 100644 index 0000000..9f3c9fc --- /dev/null +++ b/Unity Studio/Unity Studio Classes/FBXExporter.cs @@ -0,0 +1,1137 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using static Unity_Studio.UnityStudio; +using static Unity_Studio.UnityExporter; + +namespace Unity_Studio +{ + static class FBXExporter + { + public static void WriteFBX(string FBXfile, bool allNodes) + { + var timestamp = DateTime.Now; + + using (StreamWriter FBXwriter = new StreamWriter(FBXfile)) + { + StringBuilder fbx = new StringBuilder(); + StringBuilder ob = new StringBuilder(); //Objects builder + StringBuilder cb = new StringBuilder(); //Connections builder + StringBuilder mb = new StringBuilder(); //Materials builder to get texture count in advance + StringBuilder cb2 = new StringBuilder(); //and keep connections ordered + cb.Append("\n}\n");//Objects end + cb.Append("\nConnections: {"); + + HashSet GameObjects = new HashSet(); + HashSet LimbNodes = new HashSet(); + HashSet Skins = new HashSet(); + HashSet Meshes = new HashSet();//MeshFilters are not unique!! + HashSet Materials = new HashSet(); + HashSet Textures = new HashSet(); + + int DeformerCount = 0; + /* + uniqueIDs can begin with zero, so they are preceded by a number specific to their type + this will also make it easier to debug FBX files + 1: Model + 2: NodeAttribute + 3: Geometry + 4: Deformer + 5: CollectionExclusive + 6: Material + 7: Texture + 8: Video + 9: + */ + + #region loop nodes and collect objects for export + foreach (var assetsFile in assetsfileList) + { + foreach (var m_GameObject in assetsFile.GameObjectList.Values) + { + if (m_GameObject.Checked || allNodes) + { + GameObjects.Add(m_GameObject); + + if (assetsfileList.TryGetPD(m_GameObject.m_MeshFilter, out var MeshFilterPD)) + { + //MeshFilters are not unique! + //MeshFilters.Add(MeshFilterPD); + MeshFilter m_MeshFilter = new MeshFilter(MeshFilterPD); + if (assetsfileList.TryGetPD(m_MeshFilter.m_Mesh, out var MeshPD)) + { + Meshes.Add(MeshPD); + + //write connections here and Mesh objects separately without having to backtrack through their MEshFilter to het the GameObject ID + //also note that MeshFilters are not unique, they cannot be used for instancing geometry + cb2.AppendFormat("\n\n\t;Geometry::, Model::{0}", m_GameObject.m_Name); + cb2.AppendFormat("\n\tC: \"OO\",3{0},1{1}", MeshPD.uniqueID, m_GameObject.uniqueID); + } + } + + #region get Renderer + if (assetsfileList.TryGetPD(m_GameObject.m_MeshRenderer, out var RendererPD)) + { + MeshRenderer m_Renderer = new MeshRenderer(RendererPD); + + foreach (var MaterialPPtr in m_Renderer.m_Materials) + { + if (assetsfileList.TryGetPD(MaterialPPtr, out var MaterialPD)) + { + Materials.Add(MaterialPD); + cb2.AppendFormat("\n\n\t;Material::, Model::{0}", m_GameObject.m_Name); + cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", MaterialPD.uniqueID, m_GameObject.uniqueID); + } + } + } + + #endregion + + #region get SkinnedMeshRenderer + if (assetsfileList.TryGetPD(m_GameObject.m_SkinnedMeshRenderer, out var SkinnedMeshPD)) + { + Skins.Add(SkinnedMeshPD); + + SkinnedMeshRenderer m_SkinnedMeshRenderer = new SkinnedMeshRenderer(SkinnedMeshPD); + + foreach (var MaterialPPtr in m_SkinnedMeshRenderer.m_Materials) + { + if (assetsfileList.TryGetPD(MaterialPPtr, out var MaterialPD)) + { + Materials.Add(MaterialPD); + cb2.AppendFormat("\n\n\t;Material::, Model::{0}", m_GameObject.m_Name); + cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", MaterialPD.uniqueID, m_GameObject.uniqueID); + } + } + + if ((bool)Properties.Settings.Default["exportDeformers"]) + { + DeformerCount += m_SkinnedMeshRenderer.m_Bones.Length; + + //collect skeleton dummies to make sure they are exported + foreach (var bonePPtr in m_SkinnedMeshRenderer.m_Bones) + { + if (assetsfileList.TryGetTransform(bonePPtr, out var b_Transform)) + { + if (assetsfileList.TryGetGameObject(b_Transform.m_GameObject, out var m_Bone)) + { + LimbNodes.Add(m_Bone); + //also collect the root bone + if (m_Bone.Parent.Level > 0) { LimbNodes.Add((GameObject)m_Bone.Parent); } + //should I collect siblings? + } + + #region collect children because m_SkinnedMeshRenderer.m_Bones doesn't contain terminations + foreach (var ChildPPtr in b_Transform.m_Children) + { + if (assetsfileList.TryGetTransform(ChildPPtr, out var ChildTR)) + { + if (assetsfileList.TryGetGameObject(ChildTR.m_GameObject, out var m_Child)) + { + //check that the Model doesn't contain a Mesh, although this won't ensure it's part of the skeleton + if (m_Child.m_MeshFilter == null && m_Child.m_SkinnedMeshRenderer == null) + { + LimbNodes.Add(m_Child); + } + } + } + } + #endregion + } + } + } + } + #endregion + } + } + } + + //if ((bool)Properties.Settings.Default["convertDummies"]) { GameObjects.Except(LimbNodes); } + //else { GameObjects.UnionWith(LimbNodes); LimbNodes.Clear(); } + //add either way and use LimbNodes to test if a node is Null or LimbNode + GameObjects.UnionWith(LimbNodes); + #endregion + + #region write Materials, collect Texture objects + //StatusStripUpdate("Writing Materials"); + foreach (var MaterialPD in Materials) + { + Material m_Material = new Material(MaterialPD); + + mb.AppendFormat("\n\tMaterial: 6{0}, \"Material::{1}\", \"\" {{", MaterialPD.uniqueID, m_Material.m_Name); + mb.Append("\n\t\tVersion: 102"); + mb.Append("\n\t\tShadingModel: \"phong\""); + mb.Append("\n\t\tMultiLayer: 0"); + mb.Append("\n\t\tProperties70: {"); + mb.Append("\n\t\t\tP: \"ShadingModel\", \"KString\", \"\", \"\", \"phong\""); + + #region write material colors + foreach (var m_Color in m_Material.m_Colors) + { + switch (m_Color.first) + { + case "_Color": + case "gSurfaceColor": + mb.AppendFormat("\n\t\t\tP: \"DiffuseColor\", \"Color\", \"\", \"A\",{0},{1},{2}", m_Color.second[0], m_Color.second[1], m_Color.second[2]); + break; + case "_SpecularColor"://then what is _SpecColor?? + mb.AppendFormat("\n\t\t\tP: \"SpecularColor\", \"Color\", \"\", \"A\",{0},{1},{2}", m_Color.second[0], m_Color.second[1], m_Color.second[2]); + break; + case "_ReflectColor": + mb.AppendFormat("\n\t\t\tP: \"AmbientColor\", \"Color\", \"\", \"A\",{0},{1},{2}", m_Color.second[0], m_Color.second[1], m_Color.second[2]); + break; + default: + mb.AppendFormat("\n;\t\t\tP: \"{3}\", \"Color\", \"\", \"A\",{0},{1},{2}", m_Color.second[0], m_Color.second[1], m_Color.second[2], m_Color.first);//commented out + break; + } + } + #endregion + + #region write material parameters + foreach (var m_Float in m_Material.m_Floats) + { + switch (m_Float.first) + { + case "_Shininess": + mb.AppendFormat("\n\t\t\tP: \"ShininessExponent\", \"Number\", \"\", \"A\",{0}", m_Float.second); + mb.AppendFormat("\n\t\t\tP: \"Shininess\", \"Number\", \"\", \"A\",{0}", m_Float.second); + break; + case "_Transparency": + mb.Append("\n\t\t\tP: \"TransparentColor\", \"Color\", \"\", \"A\",1,1,1"); + mb.AppendFormat("\n\t\t\tP: \"TransparencyFactor\", \"Number\", \"\", \"A\",{0}", m_Float.second); + mb.AppendFormat("\n\t\t\tP: \"Opacity\", \"Number\", \"\", \"A\",{0}", (1 - m_Float.second)); + break; + default: + mb.AppendFormat("\n;\t\t\tP: \"{0}\", \"Number\", \"\", \"A\",{1}", m_Float.first, m_Float.second); + break; + } + } + #endregion + + //mb.Append("\n\t\t\tP: \"SpecularFactor\", \"Number\", \"\", \"A\",0"); + mb.Append("\n\t\t}"); + mb.Append("\n\t}"); + + #region write texture connections + foreach (var m_TexEnv in m_Material.m_TexEnvs) + { + #region get Porsche material from json + if (!assetsfileList.TryGetPD(m_TexEnv.m_Texture, out var TexturePD) && jsonMats != null) + { + if (jsonMats.TryGetValue(m_Material.m_Name, out var matProp)) + { + if (matProp.TryGetValue(m_TexEnv.name, out var texName)) + { + foreach (var asset in exportableAssets) + { + if (asset.Type2 == 28 && asset.Text == texName) + { + TexturePD = asset; + break; + } + } + } + } + } + #endregion + + if (TexturePD != null && TexturePD.Type2 == 28) + { + Textures.Add(TexturePD); + + cb2.AppendFormat("\n\n\t;Texture::, Material::{0}", m_Material.m_Name); + cb2.AppendFormat("\n\tC: \"OP\",7{0},6{1}, \"", TexturePD.uniqueID, MaterialPD.uniqueID); + + switch (m_TexEnv.name) + { + case "_MainTex": + case "gDiffuseSampler": + cb2.Append("DiffuseColor\""); + break; + case "_SpecularMap": + case "gSpecularSampler": + cb2.Append("SpecularColor\""); + break; + case "_NormalMap": + case "gNormalSampler": + cb2.Append("NormalMap\""); + break; + case "_BumpMap": + cb2.Append("Bump\""); + break; + default: + cb2.AppendFormat("{0}\"", m_TexEnv.name); + break; + } + } + } + #endregion + } + #endregion + + #region write generic FBX data after everything was collected + fbx.Append("; FBX 7.1.0 project file"); + fbx.Append("\nFBXHeaderExtension: {\n\tFBXHeaderVersion: 1003\n\tFBXVersion: 7100\n\tCreationTimeStamp: {\n\t\tVersion: 1000"); + fbx.Append("\n\t\tYear: " + timestamp.Year); + fbx.Append("\n\t\tMonth: " + timestamp.Month); + fbx.Append("\n\t\tDay: " + timestamp.Day); + fbx.Append("\n\t\tHour: " + timestamp.Hour); + fbx.Append("\n\t\tMinute: " + timestamp.Minute); + fbx.Append("\n\t\tSecond: " + timestamp.Second); + fbx.Append("\n\t\tMillisecond: " + timestamp.Millisecond); + fbx.Append("\n\t}\n\tCreator: \"Unity Studio by Chipicao\"\n}\n"); + + fbx.Append("\nGlobalSettings: {"); + fbx.Append("\n\tVersion: 1000"); + fbx.Append("\n\tProperties70: {"); + fbx.Append("\n\t\tP: \"UpAxis\", \"int\", \"Integer\", \"\",1"); + fbx.Append("\n\t\tP: \"UpAxisSign\", \"int\", \"Integer\", \"\",1"); + fbx.Append("\n\t\tP: \"FrontAxis\", \"int\", \"Integer\", \"\",2"); + fbx.Append("\n\t\tP: \"FrontAxisSign\", \"int\", \"Integer\", \"\",1"); + fbx.Append("\n\t\tP: \"CoordAxis\", \"int\", \"Integer\", \"\",0"); + fbx.Append("\n\t\tP: \"CoordAxisSign\", \"int\", \"Integer\", \"\",1"); + fbx.Append("\n\t\tP: \"OriginalUpAxis\", \"int\", \"Integer\", \"\",1"); + fbx.Append("\n\t\tP: \"OriginalUpAxisSign\", \"int\", \"Integer\", \"\",1"); + fbx.AppendFormat("\n\t\tP: \"UnitScaleFactor\", \"double\", \"Number\", \"\",{0}", Properties.Settings.Default["scaleFactor"]); + fbx.Append("\n\t\tP: \"OriginalUnitScaleFactor\", \"double\", \"Number\", \"\",1.0"); + //fbx.Append("\n\t\tP: \"AmbientColor\", \"ColorRGB\", \"Color\", \"\",0,0,0"); + //fbx.Append("\n\t\tP: \"DefaultCamera\", \"KString\", \"\", \"\", \"Producer Perspective\""); + //fbx.Append("\n\t\tP: \"TimeMode\", \"enum\", \"\", \"\",6"); + //fbx.Append("\n\t\tP: \"TimeProtocol\", \"enum\", \"\", \"\",2"); + //fbx.Append("\n\t\tP: \"SnapOnFrameMode\", \"enum\", \"\", \"\",0"); + //fbx.Append("\n\t\tP: \"TimeSpanStart\", \"KTime\", \"Time\", \"\",0"); + //fbx.Append("\n\t\tP: \"TimeSpanStop\", \"KTime\", \"Time\", \"\",153953860000"); + //fbx.Append("\n\t\tP: \"CustomFrameRate\", \"double\", \"Number\", \"\",-1"); + //fbx.Append("\n\t\tP: \"TimeMarker\", \"Compound\", \"\", \"\""); + //fbx.Append("\n\t\tP: \"CurrentTimeMarker\", \"int\", \"Integer\", \"\",-1"); + fbx.Append("\n\t}\n}\n"); + + fbx.Append("\nDocuments: {"); + fbx.Append("\n\tCount: 1"); + fbx.Append("\n\tDocument: 1234567890, \"\", \"Scene\" {"); + fbx.Append("\n\t\tProperties70: {"); + fbx.Append("\n\t\t\tP: \"SourceObject\", \"object\", \"\", \"\""); + fbx.Append("\n\t\t\tP: \"ActiveAnimStackName\", \"KString\", \"\", \"\", \"\""); + fbx.Append("\n\t\t}"); + fbx.Append("\n\t\tRootNode: 0"); + fbx.Append("\n\t}\n}\n"); + fbx.Append("\nReferences: {\n}\n"); + + fbx.Append("\nDefinitions: {"); + fbx.Append("\n\tVersion: 100"); + fbx.AppendFormat("\n\tCount: {0}", 1 + 2 * GameObjects.Count + Materials.Count + 2 * Textures.Count + ((bool)Properties.Settings.Default["exportDeformers"] ? Skins.Count + DeformerCount + Skins.Count + 1 : 0)); + + fbx.Append("\n\tObjectType: \"GlobalSettings\" {"); + fbx.Append("\n\t\tCount: 1"); + fbx.Append("\n\t}"); + + fbx.Append("\n\tObjectType: \"Model\" {"); + fbx.AppendFormat("\n\t\tCount: {0}", GameObjects.Count); + fbx.Append("\n\t}"); + + fbx.Append("\n\tObjectType: \"NodeAttribute\" {"); + fbx.AppendFormat("\n\t\tCount: {0}", GameObjects.Count - Meshes.Count - Skins.Count); + fbx.Append("\n\t\tPropertyTemplate: \"FbxNull\" {"); + fbx.Append("\n\t\t\tProperties70: {"); + fbx.Append("\n\t\t\t\tP: \"Color\", \"ColorRGB\", \"Color\", \"\",0.8,0.8,0.8"); + fbx.Append("\n\t\t\t\tP: \"Size\", \"double\", \"Number\", \"\",100"); + fbx.Append("\n\t\t\t\tP: \"Look\", \"enum\", \"\", \"\",1"); + fbx.Append("\n\t\t\t}\n\t\t}\n\t}"); + + fbx.Append("\n\tObjectType: \"Geometry\" {"); + fbx.AppendFormat("\n\t\tCount: {0}", Meshes.Count + Skins.Count); + fbx.Append("\n\t}"); + + fbx.Append("\n\tObjectType: \"Material\" {"); + fbx.AppendFormat("\n\t\tCount: {0}", Materials.Count); + fbx.Append("\n\t}"); + + fbx.Append("\n\tObjectType: \"Texture\" {"); + fbx.AppendFormat("\n\t\tCount: {0}", Textures.Count); + fbx.Append("\n\t}"); + + fbx.Append("\n\tObjectType: \"Video\" {"); + fbx.AppendFormat("\n\t\tCount: {0}", Textures.Count); + fbx.Append("\n\t}"); + + if ((bool)Properties.Settings.Default["exportDeformers"]) + { + fbx.Append("\n\tObjectType: \"CollectionExclusive\" {"); + fbx.AppendFormat("\n\t\tCount: {0}", Skins.Count); + fbx.Append("\n\t\tPropertyTemplate: \"FbxDisplayLayer\" {"); + fbx.Append("\n\t\t\tProperties70: {"); + fbx.Append("\n\t\t\t\tP: \"Color\", \"ColorRGB\", \"Color\", \"\",0.8,0.8,0.8"); + fbx.Append("\n\t\t\t\tP: \"Show\", \"bool\", \"\", \"\",1"); + fbx.Append("\n\t\t\t\tP: \"Freeze\", \"bool\", \"\", \"\",0"); + fbx.Append("\n\t\t\t\tP: \"LODBox\", \"bool\", \"\", \"\",0"); + fbx.Append("\n\t\t\t}"); + fbx.Append("\n\t\t}"); + fbx.Append("\n\t}"); + + fbx.Append("\n\tObjectType: \"Deformer\" {"); + fbx.AppendFormat("\n\t\tCount: {0}", DeformerCount + Skins.Count); + fbx.Append("\n\t}"); + + fbx.Append("\n\tObjectType: \"Pose\" {"); + fbx.Append("\n\t\tCount: 1"); + fbx.Append("\n\t}"); + } + + fbx.Append("\n}\n"); + fbx.Append("\nObjects: {"); + + FBXwriter.Write(fbx); + fbx.Clear(); + #endregion + + #region write Model nodes and connections + //StatusStripUpdate("Writing Nodes and hierarchy"); + foreach (var m_GameObject in GameObjects) + { + if (m_GameObject.m_MeshFilter == null && m_GameObject.m_SkinnedMeshRenderer == null) + { + if ((bool)Properties.Settings.Default["exportDeformers"] && (bool)Properties.Settings.Default["convertDummies"] && LimbNodes.Contains(m_GameObject)) + { + ob.AppendFormat("\n\tNodeAttribute: 2{0}, \"NodeAttribute::\", \"LimbNode\" {{", m_GameObject.uniqueID); + ob.Append("\n\t\tTypeFlags: \"Skeleton\""); + ob.Append("\n\t}"); + + ob.AppendFormat("\n\tModel: 1{0}, \"Model::{1}\", \"LimbNode\" {{", m_GameObject.uniqueID, m_GameObject.m_Name); + } + else + { + ob.AppendFormat("\n\tNodeAttribute: 2{0}, \"NodeAttribute::\", \"Null\" {{", m_GameObject.uniqueID); + ob.Append("\n\t\tTypeFlags: \"Null\""); + ob.Append("\n\t}"); + + ob.AppendFormat("\n\tModel: 1{0}, \"Model::{1}\", \"Null\" {{", m_GameObject.uniqueID, m_GameObject.m_Name); + } + + //connect NodeAttribute to Model + cb.AppendFormat("\n\n\t;NodeAttribute::, Model::{0}", m_GameObject.m_Name); + cb.AppendFormat("\n\tC: \"OO\",2{0},1{0}", m_GameObject.uniqueID); + } + else + { + ob.AppendFormat("\n\tModel: 1{0}, \"Model::{1}\", \"Mesh\" {{", m_GameObject.uniqueID, m_GameObject.m_Name); + } + + ob.Append("\n\t\tVersion: 232"); + ob.Append("\n\t\tProperties70: {"); + ob.Append("\n\t\t\tP: \"InheritType\", \"enum\", \"\", \"\",1"); + ob.Append("\n\t\t\tP: \"ScalingMax\", \"Vector3D\", \"Vector\", \"\",0,0,0"); + ob.Append("\n\t\t\tP: \"DefaultAttributeIndex\", \"int\", \"Integer\", \"\",0"); + + if (assetsfileList.TryGetTransform(m_GameObject.m_Transform, out var m_Transform)) + { + float[] m_EulerRotation = QuatToEuler(new[] { m_Transform.m_LocalRotation[0], -m_Transform.m_LocalRotation[1], -m_Transform.m_LocalRotation[2], m_Transform.m_LocalRotation[3] }); + + ob.AppendFormat("\n\t\t\tP: \"Lcl Translation\", \"Lcl Translation\", \"\", \"A\",{0},{1},{2}", -m_Transform.m_LocalPosition[0], m_Transform.m_LocalPosition[1], m_Transform.m_LocalPosition[2]); + ob.AppendFormat("\n\t\t\tP: \"Lcl Rotation\", \"Lcl Rotation\", \"\", \"A\",{0},{1},{2}", m_EulerRotation[0], m_EulerRotation[1], m_EulerRotation[2]);//handedness is switched in quat + ob.AppendFormat("\n\t\t\tP: \"Lcl Scaling\", \"Lcl Scaling\", \"\", \"A\",{0},{1},{2}", m_Transform.m_LocalScale[0], m_Transform.m_LocalScale[1], m_Transform.m_LocalScale[2]); + } + + //mb.Append("\n\t\t\tP: \"UDP3DSMAX\", \"KString\", \"\", \"U\", \"MapChannel:1 = UVChannel_1&cr;&lf;MapChannel:2 = UVChannel_2&cr;&lf;\""); + //mb.Append("\n\t\t\tP: \"MaxHandle\", \"int\", \"Integer\", \"UH\",24"); + ob.Append("\n\t\t}"); + ob.Append("\n\t\tShading: T"); + ob.Append("\n\t\tCulling: \"CullingOff\"\n\t}"); + + //connect Model to parent + GameObject parentObject = (GameObject)m_GameObject.Parent; + if (GameObjects.Contains(parentObject)) + { + cb.AppendFormat("\n\n\t;Model::{0}, Model::{1}", m_GameObject.m_Name, parentObject.m_Name); + cb.AppendFormat("\n\tC: \"OO\",1{0},1{1}", m_GameObject.uniqueID, parentObject.uniqueID); + } + else + { + cb.AppendFormat("\n\n\t;Model::{0}, Model::RootNode", m_GameObject.m_Name); + cb.AppendFormat("\n\tC: \"OO\",1{0},0", m_GameObject.uniqueID); + } + + + } + #endregion + + #region write non-skinnned Geometry + //StatusStripUpdate("Writing Geometry"); + foreach (var MeshPD in Meshes) + { + Mesh m_Mesh = new Mesh(MeshPD, true); + MeshFBX(m_Mesh, MeshPD.uniqueID, ob); + + //write data 8MB at a time + if (ob.Length > (8 * 0x100000)) + { FBXwriter.Write(ob); ob.Clear(); } + } + #endregion + + #region write Deformer objects and skinned Geometry + StringBuilder pb = new StringBuilder(); + //generate unique ID for BindPose + pb.Append("\n\tPose: 5123456789, \"Pose::BIND_POSES\", \"BindPose\" {"); + pb.Append("\n\t\tType: \"BindPose\""); + pb.Append("\n\t\tVersion: 100"); + pb.AppendFormat("\n\t\tNbPoseNodes: {0}", Skins.Count + LimbNodes.Count); + + foreach (var SkinnedMeshPD in Skins) + { + SkinnedMeshRenderer m_SkinnedMeshRenderer = new SkinnedMeshRenderer(SkinnedMeshPD); + if (assetsfileList.TryGetGameObject(m_SkinnedMeshRenderer.m_GameObject, out var m_GameObject) && assetsfileList.TryGetPD(m_SkinnedMeshRenderer.m_Mesh, out var MeshPD)) + { + //generate unique Geometry ID for instanced mesh objects + //instanced skinned geometry is possible in FBX, but all instances are linked to the same skeleton nodes + //TODO: create instances if deformer option is not selected + //find a way to test if a mesh instance was loaded previously and if it uses the same skeleton, then create instance or copy + var keepID = MeshPD.uniqueID; + MeshPD.uniqueID = SkinnedMeshPD.uniqueID; + Mesh m_Mesh = new Mesh(MeshPD, true); + MeshFBX(m_Mesh, MeshPD.uniqueID, ob); + + //write data 8MB at a time + if (ob.Length > (8 * 0x100000)) + { FBXwriter.Write(ob); ob.Clear(); } + + cb2.AppendFormat("\n\n\t;Geometry::, Model::{0}", m_GameObject.m_Name); + cb2.AppendFormat("\n\tC: \"OO\",3{0},1{1}", MeshPD.uniqueID, m_GameObject.uniqueID); + + if ((bool)Properties.Settings.Default["exportDeformers"]) + { + //add BindPose node + pb.Append("\n\t\tPoseNode: {"); + pb.AppendFormat("\n\t\t\tNode: 1{0}", m_GameObject.uniqueID); + //pb.Append("\n\t\t\tMatrix: *16 {"); + //pb.Append("\n\t\t\t\ta: "); + //pb.Append("\n\t\t\t} "); + pb.Append("\n\t\t}"); + + ob.AppendFormat("\n\tCollectionExclusive: 5{0}, \"DisplayLayer::{1}\", \"DisplayLayer\" {{", SkinnedMeshPD.uniqueID, m_GameObject.m_Name); + ob.Append("\n\t\tProperties70: {"); + ob.Append("\n\t\t}"); + ob.Append("\n\t}"); + + //connect Model to DisplayLayer + cb2.AppendFormat("\n\n\t;Model::{0}, DisplayLayer::", m_GameObject.m_Name); + cb2.AppendFormat("\n\tC: \"OO\",1{0},5{1}", m_GameObject.uniqueID, SkinnedMeshPD.uniqueID); + + //write Deformers + if (m_Mesh.m_Skin.Length > 0 && m_Mesh.m_BindPose.Length >= m_SkinnedMeshRenderer.m_Bones.Length) + { + //write main Skin Deformer + ob.AppendFormat("\n\tDeformer: 4{0}, \"Deformer::\", \"Skin\" {{", SkinnedMeshPD.uniqueID); + ob.Append("\n\t\tVersion: 101"); + ob.Append("\n\t\tLink_DeformAcuracy: 50"); + ob.Append("\n\t}"); //Deformer end + + //connect Skin Deformer to Geometry + cb2.Append("\n\n\t;Deformer::, Geometry::"); + cb2.AppendFormat("\n\tC: \"OO\",4{0},3{1}", SkinnedMeshPD.uniqueID, MeshPD.uniqueID); + + for (int b = 0; b < m_SkinnedMeshRenderer.m_Bones.Length; b++) + { + if (assetsfileList.TryGetTransform(m_SkinnedMeshRenderer.m_Bones[b], out var m_Transform)) + { + if (assetsfileList.TryGetGameObject(m_Transform.m_GameObject, out var m_Bone)) + { + int influences = 0, ibSplit = 0, wbSplit = 0; + StringBuilder ib = new StringBuilder();//indices (vertex) + StringBuilder wb = new StringBuilder();//weights + + for (int index = 0; index < m_Mesh.m_Skin.Length; index++) + { + if (m_Mesh.m_Skin[index][0].weight == 0 && (m_Mesh.m_Skin[index].All(x => x.weight == 0) || //if all weights (and indicces) are 0, bone0 has full control + m_Mesh.m_Skin[index][1].weight > 0)) //this implies a second bone exists, so bone0 has control too (otherwise it wouldn't be the first in the series) + { m_Mesh.m_Skin[index][0].weight = 1; } + + var influence = m_Mesh.m_Skin[index].Find(x => x.boneIndex == b && x.weight > 0); + if (influence != null) + { + influences++; + ib.AppendFormat("{0},", index); + wb.AppendFormat("{0},", influence.weight); + + if (ib.Length - ibSplit > 2000) { ib.Append("\n"); ibSplit = ib.Length; } + if (wb.Length - wbSplit > 2000) { wb.Append("\n"); wbSplit = wb.Length; } + } + + /*float weight; + if (m_Mesh.m_Skin[index].TryGetValue(b, out weight)) + { + if (weight > 0) + { + influences++; + ib.AppendFormat("{0},", index); + wb.AppendFormat("{0},", weight); + } + else if (m_Mesh.m_Skin[index].Keys.Count == 1)//m_Mesh.m_Skin[index].Values.All(x => x == 0) + { + influences++; + ib.AppendFormat("{0},", index); + wb.AppendFormat("{0},", 1); + } + + if (ib.Length - ibSplit > 2000) { ib.Append("\n"); ibSplit = ib.Length; } + if (wb.Length - wbSplit > 2000) { wb.Append("\n"); wbSplit = wb.Length; } + }*/ + } + if (influences > 0) + { + ib.Length--;//remove last comma + wb.Length--;//remove last comma + } + + //SubDeformer objects need unique IDs because 2 or more deformers can be linked to the same bone + ob.AppendFormat("\n\tDeformer: 4{0}{1}, \"SubDeformer::\", \"Cluster\" {{", b, SkinnedMeshPD.uniqueID); + ob.Append("\n\t\tVersion: 100"); + ob.Append("\n\t\tUserData: \"\", \"\""); + + ob.AppendFormat("\n\t\tIndexes: *{0} {{\n\t\t\ta: ", influences); + ob.Append(ib); + ob.Append("\n\t\t}"); + ib.Clear(); + + ob.AppendFormat("\n\t\tWeights: *{0} {{\n\t\t\ta: ", influences); + ob.Append(wb); + ob.Append("\n\t\t}"); + wb.Clear(); + + ob.Append("\n\t\tTransform: *16 {\n\t\t\ta: "); + //ob.Append(string.Join(",", m_Mesh.m_BindPose[b])); + var m = m_Mesh.m_BindPose[b]; + ob.AppendFormat("{0},{1},{2},{3},", m[0, 0], -m[1, 0], -m[2, 0], m[3, 0]); + ob.AppendFormat("{0},{1},{2},{3},", -m[0, 1], m[1, 1], m[2, 1], m[3, 1]); + ob.AppendFormat("{0},{1},{2},{3},", -m[0, 2], m[1, 2], m[2, 2], m[3, 2]); + ob.AppendFormat("{0},{1},{2},{3},", -m[0, 3], m[1, 3], m[2, 3], m[3, 3]); + ob.Append("\n\t\t}"); + + ob.Append("\n\t}"); //SubDeformer end + + //connect SubDeformer to Skin Deformer + cb2.Append("\n\n\t;SubDeformer::, Deformer::"); + cb2.AppendFormat("\n\tC: \"OO\",4{0}{1},4{1}", b, SkinnedMeshPD.uniqueID); + + //connect dummy Model to SubDeformer + cb2.AppendFormat("\n\n\t;Model::{0}, SubDeformer::", m_Bone.m_Name); + cb2.AppendFormat("\n\tC: \"OO\",1{0},4{1}{2}", m_Bone.uniqueID, b, SkinnedMeshPD.uniqueID); + } + } + } + } + } + + MeshPD.uniqueID = keepID; + } + } + + if ((bool)Properties.Settings.Default["exportDeformers"]) + { + foreach (var m_Bone in LimbNodes) + { + //add BindPose node + pb.Append("\n\t\tPoseNode: {"); + pb.AppendFormat("\n\t\t\tNode: 1{0}", m_Bone.uniqueID); + //pb.Append("\n\t\t\tMatrix: *16 {"); + //pb.Append("\n\t\t\t\ta: "); + //pb.Append("\n\t\t\t} "); + pb.Append("\n\t\t}"); + } + pb.Append("\n\t}"); //BindPose end + ob.Append(pb); pb.Clear(); + } + #endregion + + ob.Append(mb); mb.Clear(); + cb.Append(cb2); cb2.Clear(); + + #region write & extract Textures + foreach (var TexturePD in Textures) + { + //TODO check texture type and set path accordingly; eg. CubeMap, Texture3D + string texPathName = Path.GetDirectoryName(FBXfile) + "\\Texture2D\\"; + ExportTexture2D(TexturePD, texPathName, false); + texPathName = Path.GetFullPath(Path.Combine(texPathName, $"{TexturePD.Text}.png"));//必须是png文件 + ob.AppendFormat("\n\tTexture: 7{0}, \"Texture::{1}\", \"\" {{", TexturePD.uniqueID, TexturePD.Text); + ob.Append("\n\t\tType: \"TextureVideoClip\""); + ob.Append("\n\t\tVersion: 202"); + ob.AppendFormat("\n\t\tTextureName: \"Texture::{0}\"", TexturePD.Text); + ob.Append("\n\t\tProperties70: {"); + ob.Append("\n\t\t\tP: \"UVSet\", \"KString\", \"\", \"\", \"UVChannel_0\""); + ob.Append("\n\t\t\tP: \"UseMaterial\", \"bool\", \"\", \"\",1"); + ob.Append("\n\t\t}"); + ob.AppendFormat("\n\t\tMedia: \"Video::{0}\"", TexturePD.Text); + ob.AppendFormat("\n\t\tFileName: \"{0}\"", texPathName); + ob.AppendFormat("\n\t\tRelativeFilename: \"{0}\"", texPathName.Replace($"{Path.GetDirectoryName(FBXfile)}\\", "")); + ob.Append("\n\t}"); + + ob.AppendFormat("\n\tVideo: 8{0}, \"Video::{1}\", \"Clip\" {{", TexturePD.uniqueID, TexturePD.Text); + ob.Append("\n\t\tType: \"Clip\""); + ob.Append("\n\t\tProperties70: {"); + ob.AppendFormat("\n\t\t\tP: \"Path\", \"KString\", \"XRefUrl\", \"\", \"{0}\"", texPathName); + ob.Append("\n\t\t}"); + ob.AppendFormat("\n\t\tFileName: \"{0}\"", texPathName); + ob.AppendFormat("\n\t\tRelativeFilename: \"{0}\"", texPathName.Replace($"{Path.GetDirectoryName(FBXfile)}\\", "")); + ob.Append("\n\t}"); + + //connect video to texture + cb.AppendFormat("\n\n\t;Video::{0}, Texture::{0}", TexturePD.Text); + cb.AppendFormat("\n\tC: \"OO\",8{0},7{1}", TexturePD.uniqueID, TexturePD.uniqueID); + } + #endregion + + FBXwriter.Write(ob); + ob.Clear(); + + cb.Append("\n}");//Connections end + FBXwriter.Write(cb); + cb.Clear(); + + StatusStripUpdate("Finished exporting " + Path.GetFileName(FBXfile)); + } + } + + private static void MeshFBX(Mesh m_Mesh, string MeshID, StringBuilder ob) + { + if (m_Mesh.m_VertexCount > 0)//general failsafe + { + //StatusStripUpdate("Writing Geometry: " + m_Mesh.m_Name); + + ob.AppendFormat("\n\tGeometry: 3{0}, \"Geometry::\", \"Mesh\" {{", MeshID); + ob.Append("\n\t\tProperties70: {"); + var randomColor = RandomColorGenerator(m_Mesh.m_Name); + ob.AppendFormat("\n\t\t\tP: \"Color\", \"ColorRGB\", \"Color\", \"\",{0},{1},{2}", ((float)randomColor[0] / 255), ((float)randomColor[1] / 255), ((float)randomColor[2] / 255)); + ob.Append("\n\t\t}"); + + #region Vertices + ob.AppendFormat("\n\t\tVertices: *{0} {{\n\t\t\ta: ", m_Mesh.m_VertexCount * 3); + + int c = 3;//vertex components + //skip last component in vector4 + if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4) { c++; } //haha + + int lineSplit = ob.Length; + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + ob.AppendFormat("{0},{1},{2},", -m_Mesh.m_Vertices[v * c], m_Mesh.m_Vertices[v * c + 1], m_Mesh.m_Vertices[v * c + 2]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + ob.Append("\n\t\t}"); + #endregion + + #region Indices + //in order to test topology for triangles/quads we need to store submeshes and write each one as geometry, then link to Mesh Node + ob.AppendFormat("\n\t\tPolygonVertexIndex: *{0} {{\n\t\t\ta: ", m_Mesh.m_Indices.Count); + + lineSplit = ob.Length; + for (int f = 0; f < m_Mesh.m_Indices.Count / 3; f++) + { + ob.AppendFormat("{0},{1},{2},", m_Mesh.m_Indices[f * 3], m_Mesh.m_Indices[f * 3 + 2], (-m_Mesh.m_Indices[f * 3 + 1] - 1)); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + + ob.Append("\n\t\t}"); + ob.Append("\n\t\tGeometryVersion: 124"); + #endregion + + #region Normals + if ((bool)Properties.Settings.Default["exportNormals"] && m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0) + { + ob.Append("\n\t\tLayerElementNormal: 0 {"); + ob.Append("\n\t\t\tVersion: 101"); + ob.Append("\n\t\t\tName: \"\""); + ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); + ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); + ob.AppendFormat("\n\t\t\tNormals: *{0} {{\n\t\t\ta: ", (m_Mesh.m_VertexCount * 3)); + + if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3) { c = 3; } + else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4) { c = 4; } + + lineSplit = ob.Length; + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + ob.AppendFormat("{0},{1},{2},", -m_Mesh.m_Normals[v * c], m_Mesh.m_Normals[v * c + 1], m_Mesh.m_Normals[v * c + 2]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + ob.Append("\n\t\t\t}\n\t\t}"); + } + #endregion + + #region Tangents + if ((bool)Properties.Settings.Default["exportTangents"] && m_Mesh.m_Tangents != null && m_Mesh.m_Tangents.Length > 0) + { + ob.Append("\n\t\tLayerElementTangent: 0 {"); + ob.Append("\n\t\t\tVersion: 101"); + ob.Append("\n\t\t\tName: \"\""); + ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); + ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); + ob.AppendFormat("\n\t\t\tTangents: *{0} {{\n\t\t\ta: ", (m_Mesh.m_VertexCount * 3)); + + if (m_Mesh.m_Tangents.Length == m_Mesh.m_VertexCount * 3) { c = 3; } + else if (m_Mesh.m_Tangents.Length == m_Mesh.m_VertexCount * 4) { c = 4; } + + lineSplit = ob.Length; + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + ob.AppendFormat("{0},{1},{2},", -m_Mesh.m_Tangents[v * c], m_Mesh.m_Tangents[v * c + 1], m_Mesh.m_Tangents[v * c + 2]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + ob.Append("\n\t\t\t}\n\t\t}"); + } + #endregion + + #region Colors + if ((bool)Properties.Settings.Default["exportColors"] && m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length > 0) + { + ob.Append("\n\t\tLayerElementColor: 0 {"); + ob.Append("\n\t\t\tVersion: 101"); + ob.Append("\n\t\t\tName: \"\""); + //ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); + //ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); + ob.Append("\n\t\t\tMappingInformationType: \"ByPolygonVertex\""); + ob.Append("\n\t\t\tReferenceInformationType: \"IndexToDirect\""); + ob.AppendFormat("\n\t\t\tColors: *{0} {{\n\t\t\ta: ", m_Mesh.m_Colors.Length); + //ob.Append(string.Join(",", m_Mesh.m_Colors)); + + lineSplit = ob.Length; + if (m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3) + { + for (int i = 0; i < m_Mesh.m_VertexCount; i++) + { + ob.AppendFormat("{0},{1},{2},{3},", m_Mesh.m_Colors[i * 3], m_Mesh.m_Colors[i * 3 + 1], m_Mesh.m_Colors[i * 3 + 2], 1.0f); + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + } + else + { + for (int i = 0; i < m_Mesh.m_VertexCount; i++) + { + ob.AppendFormat("{0},{1},{2},{3},", m_Mesh.m_Colors[i * 4], m_Mesh.m_Colors[i * 4 + 1], m_Mesh.m_Colors[i * 4 + 2], m_Mesh.m_Colors[i * 4 + 3]); + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + } + ob.Length--;//remove last comma + + ob.Append("\n\t\t\t}"); + ob.AppendFormat("\n\t\t\tColorIndex: *{0} {{\n\t\t\ta: ", m_Mesh.m_Indices.Count); + + lineSplit = ob.Length; + for (int f = 0; f < m_Mesh.m_Indices.Count / 3; f++) + { + ob.AppendFormat("{0},{1},{2},", m_Mesh.m_Indices[f * 3], m_Mesh.m_Indices[f * 3 + 2], m_Mesh.m_Indices[f * 3 + 1]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + + ob.Append("\n\t\t\t}\n\t\t}"); + } + #endregion + + #region UV1 + //does FBX support UVW coordinates? + if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length > 0) + { + ob.Append("\n\t\tLayerElementUV: 0 {"); + ob.Append("\n\t\t\tVersion: 101"); + ob.Append("\n\t\t\tName: \"UVChannel_1\""); + ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); + ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); + ob.AppendFormat("\n\t\t\tUV: *{0} {{\n\t\t\ta: ", m_Mesh.m_UV1.Length); + + lineSplit = ob.Length; + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + ob.AppendFormat("{0},{1},", m_Mesh.m_UV1[v * 2], 1 - m_Mesh.m_UV1[v * 2 + 1]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + ob.Append("\n\t\t\t}\n\t\t}"); + } + #endregion + #region UV2 + if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV2 != null && m_Mesh.m_UV2.Length > 0) + { + ob.Append("\n\t\tLayerElementUV: 1 {"); + ob.Append("\n\t\t\tVersion: 101"); + ob.Append("\n\t\t\tName: \"UVChannel_2\""); + ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); + ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); + ob.AppendFormat("\n\t\t\tUV: *{0} {{\n\t\t\ta: ", m_Mesh.m_UV2.Length); + + lineSplit = ob.Length; + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + ob.AppendFormat("{0},{1},", m_Mesh.m_UV2[v * 2], 1 - m_Mesh.m_UV2[v * 2 + 1]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + ob.Append("\n\t\t\t}\n\t\t}"); + } + #endregion + #region UV3 + if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV3 != null && m_Mesh.m_UV3.Length > 0) + { + ob.Append("\n\t\tLayerElementUV: 2 {"); + ob.Append("\n\t\t\tVersion: 101"); + ob.Append("\n\t\t\tName: \"UVChannel_3\""); + ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); + ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); + ob.AppendFormat("\n\t\t\tUV: *{0} {{\n\t\t\ta: ", m_Mesh.m_UV3.Length); + + lineSplit = ob.Length; + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + ob.AppendFormat("{0},{1},", m_Mesh.m_UV3[v * 2], 1 - m_Mesh.m_UV3[v * 2 + 1]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + ob.Append("\n\t\t\t}\n\t\t}"); + } + #endregion + #region UV4 + if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV4 != null && m_Mesh.m_UV4.Length > 0) + { + ob.Append("\n\t\tLayerElementUV: 3 {"); + ob.Append("\n\t\t\tVersion: 101"); + ob.Append("\n\t\t\tName: \"UVChannel_4\""); + ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); + ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); + ob.AppendFormat("\n\t\t\tUV: *{0} {{\n\t\t\ta: ", m_Mesh.m_UV4.Length); + + lineSplit = ob.Length; + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + ob.AppendFormat("{0},{1},", m_Mesh.m_UV4[v * 2], 1 - m_Mesh.m_UV4[v * 2 + 1]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + ob.Append("\n\t\t\t}\n\t\t}"); + } + #endregion + + #region Material + ob.Append("\n\t\tLayerElementMaterial: 0 {"); + ob.Append("\n\t\t\tVersion: 101"); + ob.Append("\n\t\t\tName: \"\""); + ob.Append("\n\t\t\tMappingInformationType: \""); + ob.Append(m_Mesh.m_SubMeshes.Count == 1 ? "AllSame\"" : "ByPolygon\""); + ob.Append("\n\t\t\tReferenceInformationType: \"IndexToDirect\""); + ob.AppendFormat("\n\t\t\tMaterials: *{0} {{", m_Mesh.m_materialIDs.Count); + ob.Append("\n\t\t\t\ta: "); + if (m_Mesh.m_materialIDs.Count == 1) { ob.Append("0"); } + else + { + lineSplit = ob.Length; + for (int i = 0; i < m_Mesh.m_materialIDs.Count; i++) + { + ob.AppendFormat("{0},", m_Mesh.m_materialIDs[i]); + + if (ob.Length - lineSplit > 2000) + { + ob.Append("\n"); + lineSplit = ob.Length; + } + } + ob.Length--;//remove last comma + } + ob.Append("\n\t\t\t}\n\t\t}"); + #endregion + + #region Layers + ob.Append("\n\t\tLayer: 0 {"); + ob.Append("\n\t\t\tVersion: 100"); + if ((bool)Properties.Settings.Default["exportNormals"] && m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0) + { + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementNormal\""); + ob.Append("\n\t\t\t\tTypedIndex: 0"); + ob.Append("\n\t\t\t}"); + } + if ((bool)Properties.Settings.Default["exportTangents"] && m_Mesh.m_Tangents != null && m_Mesh.m_Tangents.Length > 0) + { + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementTangent\""); + ob.Append("\n\t\t\t\tTypedIndex: 0"); + ob.Append("\n\t\t\t}"); + } + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementMaterial\""); + ob.Append("\n\t\t\t\tTypedIndex: 0"); + ob.Append("\n\t\t\t}"); + // + /*ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementTexture\""); + ob.Append("\n\t\t\t\tTypedIndex: 0"); + ob.Append("\n\t\t\t}"); + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementBumpTextures\""); + ob.Append("\n\t\t\t\tTypedIndex: 0"); + ob.Append("\n\t\t\t}");*/ + if ((bool)Properties.Settings.Default["exportColors"] && m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length > 0) + { + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementColor\""); + ob.Append("\n\t\t\t\tTypedIndex: 0"); + ob.Append("\n\t\t\t}"); + } + if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length > 0) + { + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementUV\""); + ob.Append("\n\t\t\t\tTypedIndex: 0"); + ob.Append("\n\t\t\t}"); + } + ob.Append("\n\t\t}"); //Layer 0 end + + if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV2 != null && m_Mesh.m_UV2.Length > 0) + { + ob.Append("\n\t\tLayer: 1 {"); + ob.Append("\n\t\t\tVersion: 100"); + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementUV\""); + ob.Append("\n\t\t\t\tTypedIndex: 1"); + ob.Append("\n\t\t\t}"); + ob.Append("\n\t\t}"); //Layer 1 end + } + + if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV3 != null && m_Mesh.m_UV3.Length > 0) + { + ob.Append("\n\t\tLayer: 2 {"); + ob.Append("\n\t\t\tVersion: 100"); + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementUV\""); + ob.Append("\n\t\t\t\tTypedIndex: 2"); + ob.Append("\n\t\t\t}"); + ob.Append("\n\t\t}"); //Layer 2 end + } + + if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV4 != null && m_Mesh.m_UV4.Length > 0) + { + ob.Append("\n\t\tLayer: 3 {"); + ob.Append("\n\t\t\tVersion: 100"); + ob.Append("\n\t\t\tLayerElement: {"); + ob.Append("\n\t\t\t\tType: \"LayerElementUV\""); + ob.Append("\n\t\t\t\tTypedIndex: 3"); + ob.Append("\n\t\t\t}"); + ob.Append("\n\t\t}"); //Layer 3 end + } + #endregion + + ob.Append("\n\t}"); //Geometry end + } + } + + private static float[] QuatToEuler(float[] q) + { + double eax = 0; + double eay = 0; + double eaz = 0; + + float qx = q[0]; + float qy = q[1]; + float qz = q[2]; + float qw = q[3]; + + double[,] M = new double[4, 4]; + + double Nq = qx * qx + qy * qy + qz * qz + qw * qw; + double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0; + double xs = qx * s, ys = qy * s, zs = qz * s; + double wx = qw * xs, wy = qw * ys, wz = qw * zs; + double xx = qx * xs, xy = qx * ys, xz = qx * zs; + double yy = qy * ys, yz = qy * zs, zz = qz * zs; + + M[0, 0] = 1.0 - (yy + zz); M[0, 1] = xy - wz; M[0, 2] = xz + wy; + M[1, 0] = xy + wz; M[1, 1] = 1.0 - (xx + zz); M[1, 2] = yz - wx; + M[2, 0] = xz - wy; M[2, 1] = yz + wx; M[2, 2] = 1.0 - (xx + yy); + M[3, 0] = M[3, 1] = M[3, 2] = M[0, 3] = M[1, 3] = M[2, 3] = 0.0; M[3, 3] = 1.0; + + double test = Math.Sqrt(M[0, 0] * M[0, 0] + M[1, 0] * M[1, 0]); + if (test > 16 * 1.19209290E-07F)//FLT_EPSILON + { + eax = Math.Atan2(M[2, 1], M[2, 2]); + eay = Math.Atan2(-M[2, 0], test); + eaz = Math.Atan2(M[1, 0], M[0, 0]); + } + else + { + eax = Math.Atan2(-M[1, 2], M[1, 1]); + eay = Math.Atan2(-M[2, 0], test); + eaz = 0; + } + + return new[] { (float)(eax * 180 / Math.PI), (float)(eay * 180 / Math.PI), (float)(eaz * 180 / Math.PI) }; + } + + private static byte[] RandomColorGenerator(string name) + { + int nameHash = name.GetHashCode(); + Random r = new Random(nameHash); + //Random r = new Random(DateTime.Now.Millisecond); + + byte red = (byte)r.Next(0, 255); + byte green = (byte)r.Next(0, 255); + byte blue = (byte)r.Next(0, 255); + + return new[] { red, green, blue }; + } + } +} diff --git a/Unity Studio/Unity Studio Classes/Helpers.cs b/Unity Studio/Unity Studio Classes/PPtrHelpers.cs similarity index 52% rename from Unity Studio/Unity Studio Classes/Helpers.cs rename to Unity Studio/Unity Studio Classes/PPtrHelpers.cs index 921e918..7a3cf08 100644 --- a/Unity Studio/Unity Studio Classes/Helpers.cs +++ b/Unity Studio/Unity Studio Classes/PPtrHelpers.cs @@ -2,10 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Text.RegularExpressions; using static Unity_Studio.UnityStudio; - namespace Unity_Studio { public class PPtr @@ -88,79 +86,5 @@ namespace Unity_Studio return false; } - - public static void ParseGameObject(this List assetsfileList, GameObject m_GameObject) - { - foreach (var m_Component in m_GameObject.m_Components) - { - if (m_Component.m_FileID >= 0 && m_Component.m_FileID < assetsfileList.Count) - { - AssetsFile sourceFile = assetsfileList[m_Component.m_FileID]; - if (sourceFile.preloadTable.TryGetValue(m_Component.m_PathID, out var asset)) - { - switch (asset.Type2) - { - case 4: //Transform - { - m_GameObject.m_Transform = m_Component; - break; - } - case 23: //MeshRenderer - { - m_GameObject.m_MeshRenderer = m_Component; - break; - } - case 33: //MeshFilter - { - m_GameObject.m_MeshFilter = m_Component; - break; - } - case 137: //SkinnedMeshRenderer - { - m_GameObject.m_SkinnedMeshRenderer = m_Component; - break; - } - } - } - } - } - } - } - - class TexEnv - { - public string name; - public PPtr m_Texture; - public float[] m_Scale; - public float[] m_Offset; - } - - class strFloatPair - { - public string first; - public float second; - } - - class strColorPair - { - public string first; - public float[] second; - } - - public static class StringExtensions - { - /// - /// Compares the string against a given pattern. - /// - /// The string. - /// The pattern to match, where "*" means any sequence of characters, and "?" means any single character. - /// true if the string matches the given pattern; otherwise false. - public static bool Like(this string str, string pattern) - { - return new Regex( - "^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", - RegexOptions.IgnoreCase | RegexOptions.Singleline - ).IsMatch(str); - } } } diff --git a/Unity Studio/Unity Studio Classes/SpriteHelper.cs b/Unity Studio/Unity Studio Classes/SpriteHelper.cs new file mode 100644 index 0000000..8b6a638 --- /dev/null +++ b/Unity Studio/Unity Studio Classes/SpriteHelper.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Linq; +using System.Text; +using static Unity_Studio.UnityStudio; + +namespace Unity_Studio +{ + static class SpriteHelper + { + private static Dictionary spriteCache = new Dictionary(); + + public static Bitmap GetImageFromSprite(AssetPreloadData asset) + { + if (spriteCache.TryGetValue(asset, out var bitmap)) + return (Bitmap)bitmap.Clone(); + var m_Sprite = new Sprite(asset, true); + if (assetsfileList.TryGetPD(m_Sprite.m_SpriteAtlas, out var assetPreloadData)) + { + var m_SpriteAtlas = new SpriteAtlas(assetPreloadData); + var index = m_SpriteAtlas.guids.FindIndex(x => x == m_Sprite.first); + if (index >= 0 && assetsfileList.TryGetPD(m_SpriteAtlas.textures[index], out assetPreloadData)) + { + return CutImage(asset, assetPreloadData, m_SpriteAtlas.textureRects[index], m_Sprite); + } + } + else + { + if (assetsfileList.TryGetPD(m_Sprite.texture, out assetPreloadData)) + { + return CutImage(asset, assetPreloadData, m_Sprite.textureRect); + } + } + + return null; + } + + private static Bitmap CutImage(AssetPreloadData asset, AssetPreloadData texture2DAsset, RectangleF textureRect) + { + var texture2D = new Texture2D(texture2DAsset, true); + using (var originalImage = texture2D.ConvertToBitmap(false)) + { + if (originalImage != null) + { + var info = texture2DAsset.InfoText; + var start = info.IndexOf("Format"); + info = info.Substring(start, info.Length - start); + asset.InfoText = $"Width: {textureRect.Width}\nHeight: {textureRect.Height}\n" + info; + var spriteImage = originalImage.Clone(textureRect, PixelFormat.Format32bppArgb); + spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipY); + spriteCache.Add(asset, spriteImage); + return (Bitmap)spriteImage.Clone(); + } + } + + return null; + } + + private static Bitmap CutImage(AssetPreloadData asset, AssetPreloadData texture2DAsset, RectangleF textureRect, Sprite sprite) + { + var texture2D = new Texture2D(texture2DAsset, true); + using (var originalImage = texture2D.ConvertToBitmap(false)) + { + if (originalImage != null) + { + var info = texture2DAsset.InfoText; + var start = info.IndexOf("Format"); + info = info.Substring(start, info.Length - start); + asset.InfoText = $"Width: {textureRect.Width}\nHeight: {textureRect.Height}\n" + info; + var spriteImage = originalImage.Clone(textureRect, PixelFormat.Format32bppArgb); + using (var brush = new TextureBrush(spriteImage)) + { + using (var path = new GraphicsPath()) + { + foreach (var p in sprite.m_PhysicsShape) + path.AddPolygon(p); + using (var matr = new Matrix()) + { + matr.Translate(sprite.m_Rect.Width * sprite.m_Pivot.X, sprite.m_Rect.Height * sprite.m_Pivot.Y); + matr.Scale(sprite.m_PixelsToUnits, sprite.m_PixelsToUnits); + path.Transform(matr); + var bitmap = new Bitmap((int)textureRect.Width, (int)textureRect.Height); + using (var graphic = Graphics.FromImage(bitmap)) + { + graphic.FillPath(brush, path); + bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); + spriteCache.Add(asset, bitmap); + return (Bitmap)bitmap.Clone(); + } + } + } + } + } + } + + return null; + } + } +} diff --git a/Unity Studio/Unity Studio Classes/StringExtensions.cs b/Unity Studio/Unity Studio Classes/StringExtensions.cs new file mode 100644 index 0000000..f7ff908 --- /dev/null +++ b/Unity Studio/Unity Studio Classes/StringExtensions.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace Unity_Studio +{ + public static class StringExtensions + { + /// + /// Compares the string against a given pattern. + /// + /// The string. + /// The pattern to match, where "*" means any sequence of characters, and "?" means any single character. + /// true if the string matches the given pattern; otherwise false. + public static bool Like(this string str, string pattern) + { + return new Regex( + "^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$", + RegexOptions.IgnoreCase | RegexOptions.Singleline + ).IsMatch(str); + } + } +} diff --git a/Unity Studio/Unity Studio Classes/Texture2DConverter.cs b/Unity Studio/Unity Studio Classes/Texture2DConverter.cs index 5068725..ba40b1d 100644 --- a/Unity Studio/Unity Studio Classes/Texture2DConverter.cs +++ b/Unity Studio/Unity Studio Classes/Texture2DConverter.cs @@ -354,4 +354,187 @@ namespace Unity_Studio return bitmap; } } + + public static class KTXHeader + { + public static byte[] IDENTIFIER = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }; + public static byte[] ENDIANESS_LE = { 1, 2, 3, 4 }; + public static byte[] ENDIANESS_BE = { 4, 3, 2, 1 }; + + // constants for glInternalFormat + public static int GL_ETC1_RGB8_OES = 0x8D64; + + public static int GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; + public static int GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; + public static int GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; + public static int GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; + + public static int GL_ATC_RGB_AMD = 0x8C92; + public static int GL_ATC_RGBA_EXPLICIT_ALPHA_AMD = 0x8C93; + public static int GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD = 0x87EE; + + public static int GL_COMPRESSED_RGB8_ETC2 = 0x9274; + public static int GL_COMPRESSED_SRGB8_ETC2 = 0x9275; + public static int GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276; + public static int GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277; + public static int GL_COMPRESSED_RGBA8_ETC2_EAC = 0x9278; + public static int GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279; + public static int GL_COMPRESSED_R11_EAC = 0x9270; + public static int GL_COMPRESSED_SIGNED_R11_EAC = 0x9271; + public static int GL_COMPRESSED_RG11_EAC = 0x9272; + public static int GL_COMPRESSED_SIGNED_RG11_EAC = 0x9273; + + public static int GL_COMPRESSED_RED_RGTC1 = 0x8DBB; + public static int GL_COMPRESSED_RG_RGTC2 = 0x8DBD; + public static int GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F; + public static int GL_COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C; + + public static int GL_R16F = 0x822D; + public static int GL_RG16F = 0x822F; + public static int GL_RGBA16F = 0x881A; + public static int GL_R32F = 0x822E; + public static int GL_RG32F = 0x8230; + public static int GL_RGBA32F = 0x8814; + + // constants for glBaseInternalFormat + public static int GL_RED = 0x1903; + public static int GL_GREEN = 0x1904; + public static int GL_BLUE = 0x1905; + public static int GL_ALPHA = 0x1906; + public static int GL_RGB = 0x1907; + public static int GL_RGBA = 0x1908; + public static int GL_RG = 0x8227; + } + + //from TextureConverter.h + public enum QFORMAT + { + // General formats + Q_FORMAT_RGBA_8UI = 1, + Q_FORMAT_RGBA_8I, + Q_FORMAT_RGB5_A1UI, + Q_FORMAT_RGBA_4444, + Q_FORMAT_RGBA_16UI, + Q_FORMAT_RGBA_16I, + Q_FORMAT_RGBA_32UI, + Q_FORMAT_RGBA_32I, + + Q_FORMAT_PALETTE_8_RGBA_8888, + Q_FORMAT_PALETTE_8_RGBA_5551, + Q_FORMAT_PALETTE_8_RGBA_4444, + Q_FORMAT_PALETTE_4_RGBA_8888, + Q_FORMAT_PALETTE_4_RGBA_5551, + Q_FORMAT_PALETTE_4_RGBA_4444, + Q_FORMAT_PALETTE_1_RGBA_8888, + Q_FORMAT_PALETTE_8_RGB_888, + Q_FORMAT_PALETTE_8_RGB_565, + Q_FORMAT_PALETTE_4_RGB_888, + Q_FORMAT_PALETTE_4_RGB_565, + + Q_FORMAT_R2_GBA10UI, + Q_FORMAT_RGB10_A2UI, + Q_FORMAT_RGB10_A2I, + Q_FORMAT_RGBA_F, + Q_FORMAT_RGBA_HF, + + Q_FORMAT_RGB9_E5, // Last five bits are exponent bits (Read following section in GLES3 spec: "3.8.17 Shared Exponent Texture Color Conversion") + Q_FORMAT_RGB_8UI, + Q_FORMAT_RGB_8I, + Q_FORMAT_RGB_565, + Q_FORMAT_RGB_16UI, + Q_FORMAT_RGB_16I, + Q_FORMAT_RGB_32UI, + Q_FORMAT_RGB_32I, + + Q_FORMAT_RGB_F, + Q_FORMAT_RGB_HF, + Q_FORMAT_RGB_11_11_10_F, + + Q_FORMAT_RG_F, + Q_FORMAT_RG_HF, + Q_FORMAT_RG_32UI, + Q_FORMAT_RG_32I, + Q_FORMAT_RG_16I, + Q_FORMAT_RG_16UI, + Q_FORMAT_RG_8I, + Q_FORMAT_RG_8UI, + Q_FORMAT_RG_S88, + + Q_FORMAT_R_32UI, + Q_FORMAT_R_32I, + Q_FORMAT_R_F, + Q_FORMAT_R_16F, + Q_FORMAT_R_16I, + Q_FORMAT_R_16UI, + Q_FORMAT_R_8I, + Q_FORMAT_R_8UI, + + Q_FORMAT_LUMINANCE_ALPHA_88, + Q_FORMAT_LUMINANCE_8, + Q_FORMAT_ALPHA_8, + + Q_FORMAT_LUMINANCE_ALPHA_F, + Q_FORMAT_LUMINANCE_F, + Q_FORMAT_ALPHA_F, + Q_FORMAT_LUMINANCE_ALPHA_HF, + Q_FORMAT_LUMINANCE_HF, + Q_FORMAT_ALPHA_HF, + Q_FORMAT_DEPTH_16, + Q_FORMAT_DEPTH_24, + Q_FORMAT_DEPTH_24_STENCIL_8, + Q_FORMAT_DEPTH_32, + + Q_FORMAT_BGR_565, + Q_FORMAT_BGRA_8888, + Q_FORMAT_BGRA_5551, + Q_FORMAT_BGRX_8888, + Q_FORMAT_BGRA_4444, + // Compressed formats + Q_FORMAT_ATITC_RGBA, + Q_FORMAT_ATC_RGBA_EXPLICIT_ALPHA = Q_FORMAT_ATITC_RGBA, + Q_FORMAT_ATITC_RGB, + Q_FORMAT_ATC_RGB = Q_FORMAT_ATITC_RGB, + Q_FORMAT_ATC_RGBA_INTERPOLATED_ALPHA, + Q_FORMAT_ETC1_RGB8, + Q_FORMAT_3DC_X, + Q_FORMAT_3DC_XY, + + Q_FORMAT_ETC2_RGB8, + Q_FORMAT_ETC2_RGBA8, + Q_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1, + Q_FORMAT_ETC2_SRGB8, + Q_FORMAT_ETC2_SRGB8_ALPHA8, + Q_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, + Q_FORMAT_EAC_R_SIGNED, + Q_FORMAT_EAC_R_UNSIGNED, + Q_FORMAT_EAC_RG_SIGNED, + Q_FORMAT_EAC_RG_UNSIGNED, + + Q_FORMAT_S3TC_DXT1_RGB, + Q_FORMAT_S3TC_DXT1_RGBA, + Q_FORMAT_S3TC_DXT3_RGBA, + Q_FORMAT_S3TC_DXT5_RGBA, + + // YUV formats + Q_FORMAT_AYUV_32, + Q_FORMAT_I444_24, + Q_FORMAT_YUYV_16, + Q_FORMAT_UYVY_16, + Q_FORMAT_I420_12, + Q_FORMAT_YV12_12, + Q_FORMAT_NV21_12, + Q_FORMAT_NV12_12, + + // ASTC Format + Q_FORMAT_ASTC_8, + Q_FORMAT_ASTC_16, + }; + + public enum texgenpack_texturetype + { + RGTC1, + RGTC2, + BPTC_FLOAT, + BPTC + } } diff --git a/Unity Studio/Unity Studio Classes/UnityExporter.cs b/Unity Studio/Unity Studio Classes/UnityExporter.cs new file mode 100644 index 0000000..947ba19 --- /dev/null +++ b/Unity Studio/Unity Studio Classes/UnityExporter.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections.Generic; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using static Unity_Studio.SpriteHelper; + +namespace Unity_Studio +{ + static class UnityExporter + { + public static bool ExportTexture2D(AssetPreloadData asset, string exportPathName, bool flip) + { + var m_Texture2D = new Texture2D(asset, true); + if (m_Texture2D.image_data == null) + return false; + var convert = (bool)Properties.Settings.Default["convertTexture"]; + var bitmap = m_Texture2D.ConvertToBitmap(flip); + if (convert && bitmap != null) + { + ImageFormat format = null; + var ext = (string)Properties.Settings.Default["convertType"]; + switch (ext) + { + case "BMP": + format = ImageFormat.Bmp; + break; + case "PNG": + format = ImageFormat.Png; + break; + case "JPEG": + format = ImageFormat.Jpeg; + break; + } + var exportFullName = exportPathName + asset.Text + "." + ext.ToLower(); + if (ExportFileExists(exportFullName)) + return false; + bitmap.Save(exportFullName, format); + bitmap.Dispose(); + return true; + } + if (!convert) + { + var exportFullName = exportPathName + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + File.WriteAllBytes(exportFullName, m_Texture2D.ConvertToContainer()); + return true; + } + return false; + } + + public static bool ExportAudioClip(AssetPreloadData asset, string exportPath) + { + var m_AudioClip = new AudioClip(asset, true); + if (m_AudioClip.m_AudioData == null) + return false; + var convertAudio = (bool)Properties.Settings.Default["convertAudio"]; + if (convertAudio && m_AudioClip.IsFMODSupport) + { + var exportFullName = exportPath + asset.Text + ".wav"; + if (ExportFileExists(exportFullName)) + return false; + FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO(); + var result = FMOD.Factory.System_Create(out var system); + if (result != FMOD.RESULT.OK) + return false; + result = system.init(1, FMOD.INITFLAGS.NORMAL, IntPtr.Zero); + if (result != FMOD.RESULT.OK) + return false; + 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); + if (result != FMOD.RESULT.OK) + return false; + result = sound.getSubSound(0, out var subsound); + if (result != FMOD.RESULT.OK) + return false; + result = subsound.getFormat(out var type, out var format, out int NumChannels, out int BitsPerSample); + if (result != FMOD.RESULT.OK) + return false; + result = subsound.getDefaults(out var frequency, out int priority); + if (result != FMOD.RESULT.OK) + return false; + var SampleRate = (int)frequency; + result = subsound.getLength(out var length, FMOD.TIMEUNIT.PCMBYTES); + if (result != FMOD.RESULT.OK) + return false; + result = subsound.@lock(0, length, out var ptr1, out var ptr2, out var len1, out var len2); + if (result != FMOD.RESULT.OK) + return false; + byte[] buffer = new byte[len1 + 44]; + //添加wav头 + Encoding.UTF8.GetBytes("RIFF").CopyTo(buffer, 0); + BitConverter.GetBytes(len1 + 36).CopyTo(buffer, 4); + Encoding.UTF8.GetBytes("WAVEfmt ").CopyTo(buffer, 8); + BitConverter.GetBytes(16).CopyTo(buffer, 16); + BitConverter.GetBytes((short)1).CopyTo(buffer, 20); + BitConverter.GetBytes((short)NumChannels).CopyTo(buffer, 22); + BitConverter.GetBytes(SampleRate).CopyTo(buffer, 24); + BitConverter.GetBytes(SampleRate * NumChannels * BitsPerSample / 8).CopyTo(buffer, 28); + BitConverter.GetBytes((short)(NumChannels * BitsPerSample / 8)).CopyTo(buffer, 32); + BitConverter.GetBytes((short)BitsPerSample).CopyTo(buffer, 34); + Encoding.UTF8.GetBytes("data").CopyTo(buffer, 36); + BitConverter.GetBytes(len1).CopyTo(buffer, 40); + Marshal.Copy(ptr1, buffer, 44, (int)len1); + File.WriteAllBytes(exportFullName, buffer); + result = subsound.unlock(ptr1, ptr2, len1, len2); + if (result != FMOD.RESULT.OK) + return false; + subsound.release(); + sound.release(); + system.release(); + } + else + { + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + File.WriteAllBytes(exportFullName, m_AudioClip.m_AudioData); + } + return true; + } + + public static bool ExportShader(AssetPreloadData asset, string exportPath) + { + var m_Shader = new Shader(asset, true); + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + File.WriteAllBytes(exportFullName, m_Shader.m_Script); + return true; + } + + public static bool ExportTextAsset(AssetPreloadData asset, string exportPath) + { + var m_TextAsset = new TextAsset(asset, true); + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + File.WriteAllBytes(exportFullName, m_TextAsset.m_Script); + return true; + } + + public static bool ExportMonoBehaviour(AssetPreloadData asset, string exportPath) + { + var m_MonoBehaviour = new MonoBehaviour(asset, true); + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + File.WriteAllText(exportFullName, m_MonoBehaviour.serializedText); + return true; + } + + public static bool ExportFont(AssetPreloadData asset, string exportPath) + { + var m_Font = new UnityFont(asset, true); + if (m_Font.m_FontData != null) + { + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + File.WriteAllBytes(exportFullName, m_Font.m_FontData); + return true; + } + return false; + } + + public static bool ExportMesh(AssetPreloadData asset, string exportPath) + { + var m_Mesh = new Mesh(asset, true); + if (m_Mesh.m_VertexCount <= 0) + return false; + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + var sb = new StringBuilder(); + sb.AppendLine("g " + m_Mesh.m_Name); + #region Vertices + int c = 3; + if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4) + { + c = 4; + } + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + sb.AppendFormat("v {0} {1} {2}\r\n", -m_Mesh.m_Vertices[v * c], m_Mesh.m_Vertices[v * c + 1], m_Mesh.m_Vertices[v * c + 2]); + } + #endregion + + #region UV + if (m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length == m_Mesh.m_VertexCount * 2) + { + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV1[v * 2], m_Mesh.m_UV1[v * 2 + 1]); + } + } + else if (m_Mesh.m_UV2 != null && m_Mesh.m_UV2.Length == m_Mesh.m_VertexCount * 2) + { + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV2[v * 2], m_Mesh.m_UV2[v * 2 + 1]); + } + } + #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) + { + c = 3; + } + else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4) + { + c = 4; + } + for (int v = 0; v < m_Mesh.m_VertexCount; v++) + { + sb.AppendFormat("vn {0} {1} {2}\r\n", -m_Mesh.m_Normals[v * c], m_Mesh.m_Normals[v * c + 1], m_Mesh.m_Normals[v * c + 2]); + } + } + #endregion + + #region Face + int sum = 0; + for (var i = 0; i < m_Mesh.m_SubMeshes.Count; i++) + { + sb.AppendLine($"g {m_Mesh.m_Name}_{i}"); + int indexCount = (int)m_Mesh.m_SubMeshes[i].indexCount; + var end = sum + indexCount / 3; + for (int f = sum; f < end; f++) + { + sb.AppendFormat("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\r\n", m_Mesh.m_Indices[f * 3 + 2] + 1, m_Mesh.m_Indices[f * 3 + 1] + 1, m_Mesh.m_Indices[f * 3] + 1); + } + sum = end; + } + #endregion + + sb.Replace("NaN", "0"); + File.WriteAllText(exportFullName, sb.ToString()); + return true; + } + + public static bool ExportVideoClip(AssetPreloadData asset, string exportPath) + { + var m_VideoClip = new VideoClip(asset, true); + if (m_VideoClip.m_VideoData != null) + { + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + File.WriteAllBytes(exportFullName, m_VideoClip.m_VideoData); + return true; + } + return false; + } + + public static bool ExportMovieTexture(AssetPreloadData asset, string exportPath) + { + var m_MovieTexture = new MovieTexture(asset, true); + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + File.WriteAllBytes(exportFullName, m_MovieTexture.m_MovieData); + return true; + } + + public static bool ExportSprite(AssetPreloadData asset, string exportPath) + { + ImageFormat format = null; + var type = (string)Properties.Settings.Default["convertType"]; + switch (type) + { + case "BMP": + format = ImageFormat.Bmp; + break; + case "PNG": + format = ImageFormat.Png; + break; + case "JPEG": + format = ImageFormat.Jpeg; + break; + } + var exportFullName = exportPath + asset.Text + "." + type.ToLower(); + if (ExportFileExists(exportFullName)) + return false; + var bitmap = GetImageFromSprite(asset); + if (bitmap != null) + { + bitmap.Save(exportFullName, format); + return true; + } + return false; + } + + public static bool ExportRawFile(AssetPreloadData asset, string exportPath) + { + var exportFullName = exportPath + asset.Text + asset.extension; + if (ExportFileExists(exportFullName)) + return false; + var bytes = asset.Reader.ReadBytes(asset.Size); + File.WriteAllBytes(exportFullName, bytes); + return true; + } + + private static bool ExportFileExists(string filename) + { + if (File.Exists(filename)) + { + return true; + } + Directory.CreateDirectory(Path.GetDirectoryName(filename)); + return false; + } + } +} diff --git a/Unity Studio/Unity Studio Classes/UnityImporter.cs b/Unity Studio/Unity Studio Classes/UnityImporter.cs new file mode 100644 index 0000000..8d66ac4 --- /dev/null +++ b/Unity Studio/Unity Studio Classes/UnityImporter.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using static Unity_Studio.UnityStudio; + +namespace Unity_Studio +{ + static class UnityImporter + { + public static List unityFiles = new List(); //files to load + public static HashSet unityFilesHash = new HashSet(); //to improve the loading speed + public static HashSet assetsfileListHash = new HashSet(); //to improve the loading speed + + public static void LoadFile(string fullName) + { + if (CheckBundleFile(fullName, out var reader)) + { + LoadBundleFile(fullName, reader); + } + else + { + LoadAssetsFile(fullName, reader); + } + } + + private static void LoadAssetsFile(string fullName, EndianBinaryReader reader) + { + var fileName = Path.GetFileName(fullName); + StatusStripUpdate("Loading " + fileName); + if (!assetsfileListHash.Contains(fileName.ToUpper())) + { + var assetsFile = new AssetsFile(fullName, reader); + if (assetsFile.valid) + { + assetsfileList.Add(assetsFile); + assetsfileListHash.Add(assetsFile.upperFileName); + + #region for 2.6.x find mainData and get string version + if (assetsFile.fileGen == 6 && fileName != "mainData") + { + var mainDataFile = assetsfileList.Find(aFile => aFile.fileName == "mainData"); + if (mainDataFile != null) + { + assetsFile.m_Version = mainDataFile.m_Version; + assetsFile.version = mainDataFile.version; + assetsFile.buildType = mainDataFile.buildType; + } + else if (File.Exists(Path.GetDirectoryName(fullName) + "\\mainData")) + { + mainDataFile = new AssetsFile(Path.GetDirectoryName(fullName) + "\\mainData", new EndianBinaryReader(File.OpenRead(Path.GetDirectoryName(fullName) + "\\mainData"))); + assetsFile.m_Version = mainDataFile.m_Version; + assetsFile.version = mainDataFile.version; + assetsFile.buildType = mainDataFile.buildType; + } + } + #endregion + + int value = 0; + foreach (var sharedFile in assetsFile.sharedAssetsList) + { + var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName; + var sharedFileName = sharedFile.fileName; + + if (!unityFilesHash.Contains(sharedFileName.ToUpper())) + { + if (!File.Exists(sharedFilePath)) + { + var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories); + if (findFiles.Length > 0) + { + sharedFilePath = findFiles[0]; + } + } + + if (File.Exists(sharedFilePath)) + { + unityFiles.Add(sharedFilePath); + unityFilesHash.Add(sharedFileName.ToUpper()); + value++; + } + } + } + if (value > 0) + ProgressBarMaximumAdd(value); + } + } + } + + private static void LoadBundleFile(string fullName, EndianBinaryReader reader) + { + var fileName = Path.GetFileName(fullName); + StatusStripUpdate("Decompressing " + fileName); + var bundleFile = new BundleFile(reader); + foreach (var memFile in bundleFile.MemoryAssetsFileList) + { + if (!assetsfileListHash.Contains(memFile.fileName.ToUpper())) + { + StatusStripUpdate("Loading " + memFile.fileName); + var assetsFile = new AssetsFile(Path.GetDirectoryName(fullName) + "\\" + memFile.fileName, new EndianBinaryReader(memFile.memStream)); + if (assetsFile.valid) + { + assetsFile.bundlePath = fullName; + + if (assetsFile.fileGen == 6) //2.6.x and earlier don't have a string version before the preload table + { + //make use of the bundle file version + assetsFile.m_Version = bundleFile.versionEngine; + assetsFile.version = Array.ConvertAll((from Match m in Regex.Matches(assetsFile.m_Version, @"[0-9]") select m.Value).ToArray(), int.Parse); + assetsFile.buildType = bundleFile.versionEngine.Split(AssetsFile.buildTypeSplit, StringSplitOptions.RemoveEmptyEntries); + } + + assetsfileList.Add(assetsFile); + assetsfileListHash.Add(assetsFile.upperFileName); + } + else + { + resourceFileReaders.Add(assetsFile.upperFileName, assetsFile.assetsFileReader); + } + } + } + reader.Dispose(); + } + + public static void MergeSplitAssets(string dirPath) + { + string[] splitFiles = Directory.GetFiles(dirPath, "*.split0"); + foreach (var splitFile in splitFiles) + { + string destFile = Path.GetFileNameWithoutExtension(splitFile); + string destPath = Path.GetDirectoryName(splitFile) + "\\"; + var destFull = destPath + destFile; + if (!File.Exists(destFull)) + { + string[] splitParts = Directory.GetFiles(destPath, destFile + ".split*"); + using (var destStream = File.Create(destFull)) + { + for (int i = 0; i < splitParts.Length; i++) + { + string splitPart = destFull + ".split" + i; + using (var sourceStream = File.OpenRead(splitPart)) + sourceStream.CopyTo(destStream); + } + } + } + } + } + } +} diff --git a/Unity Studio/Unity Studio Classes/UnityStudio.cs b/Unity Studio/Unity Studio Classes/UnityStudio.cs index ff36fcf..81ad526 100644 --- a/Unity Studio/Unity Studio Classes/UnityStudio.cs +++ b/Unity Studio/Unity Studio Classes/UnityStudio.cs @@ -1,36 +1,25 @@ using System; using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Linq; -using System.Text; using System.IO; -using System.Runtime.InteropServices; -using System.Text.RegularExpressions; -using System.Drawing.Imaging; +using System.Linq; using System.Web.Script.Serialization; - namespace Unity_Studio { internal static class UnityStudio { - public static List unityFiles = new List(); //files to load - public static HashSet unityFilesHash = new HashSet(); //to improve the loading speed public static List assetsfileList = new List(); //loaded files - public static HashSet assetsfileListHash = new HashSet(); //to improve the loading speed public static Dictionary sharedFileIndex = new Dictionary(); //to improve the loading speed public static Dictionary resourceFileReaders = new Dictionary(); //use for read res files public static List exportableAssets = new List(); //used to hold all assets while the ListView is filtered private static HashSet exportableAssetsHash = new HashSet(); //avoid the same name asset public static List visibleAssets = new List(); //used to build the ListView from all or filtered assets - private static Dictionary spriteCache = new Dictionary(); public static string productName = ""; public static string mainPath = ""; public static List fileNodes = new List(); - private static Dictionary> jsonMats; + public static Dictionary> jsonMats; public static Dictionary> AllClassStructures = new Dictionary>(); //UI @@ -40,139 +29,6 @@ namespace Unity_Studio public static Action StatusStripUpdate; public static Action ProgressBarMaximumAdd; - public static void LoadFile(string fullName) - { - if (CheckBundleFile(fullName, out var reader)) - { - LoadBundleFile(fullName, reader); - } - else - { - LoadAssetsFile(fullName, reader); - } - } - - private static void LoadAssetsFile(string fullName, EndianBinaryReader reader) - { - var fileName = Path.GetFileName(fullName); - StatusStripUpdate("Loading " + fileName); - if (!assetsfileListHash.Contains(fileName.ToUpper())) - { - var assetsFile = new AssetsFile(fullName, reader); - if (assetsFile.valid) - { - assetsfileList.Add(assetsFile); - assetsfileListHash.Add(assetsFile.upperFileName); - - #region for 2.6.x find mainData and get string version - if (assetsFile.fileGen == 6 && fileName != "mainData") - { - var mainDataFile = assetsfileList.Find(aFile => aFile.fileName == "mainData"); - if (mainDataFile != null) - { - assetsFile.m_Version = mainDataFile.m_Version; - assetsFile.version = mainDataFile.version; - assetsFile.buildType = mainDataFile.buildType; - } - else if (File.Exists(Path.GetDirectoryName(fullName) + "\\mainData")) - { - mainDataFile = new AssetsFile(Path.GetDirectoryName(fullName) + "\\mainData", new EndianBinaryReader(File.OpenRead(Path.GetDirectoryName(fullName) + "\\mainData"))); - assetsFile.m_Version = mainDataFile.m_Version; - assetsFile.version = mainDataFile.version; - assetsFile.buildType = mainDataFile.buildType; - } - } - #endregion - - int value = 0; - foreach (var sharedFile in assetsFile.sharedAssetsList) - { - var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName; - var sharedFileName = sharedFile.fileName; - - if (!unityFilesHash.Contains(sharedFileName.ToUpper())) - { - if (!File.Exists(sharedFilePath)) - { - var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories); - if (findFiles.Length > 0) - { - sharedFilePath = findFiles[0]; - } - } - - if (File.Exists(sharedFilePath)) - { - unityFiles.Add(sharedFilePath); - unityFilesHash.Add(sharedFileName.ToUpper()); - value++; - } - } - } - if (value > 0) - ProgressBarMaximumAdd(value); - } - } - } - - private static void LoadBundleFile(string fullName, EndianBinaryReader reader) - { - var fileName = Path.GetFileName(fullName); - StatusStripUpdate("Decompressing " + fileName); - var bundleFile = new BundleFile(reader); - foreach (var memFile in bundleFile.MemoryAssetsFileList) - { - if (!assetsfileListHash.Contains(memFile.fileName.ToUpper())) - { - StatusStripUpdate("Loading " + memFile.fileName); - var assetsFile = new AssetsFile(Path.GetDirectoryName(fullName) + "\\" + memFile.fileName, new EndianBinaryReader(memFile.memStream)); - if (assetsFile.valid) - { - assetsFile.bundlePath = fullName; - - if (assetsFile.fileGen == 6) //2.6.x and earlier don't have a string version before the preload table - { - //make use of the bundle file version - assetsFile.m_Version = bundleFile.versionEngine; - assetsFile.version = Array.ConvertAll((from Match m in Regex.Matches(assetsFile.m_Version, @"[0-9]") select m.Value).ToArray(), int.Parse); - assetsFile.buildType = bundleFile.versionEngine.Split(AssetsFile.buildTypeSplit, StringSplitOptions.RemoveEmptyEntries); - } - - assetsfileList.Add(assetsFile); - assetsfileListHash.Add(assetsFile.upperFileName); - } - else - { - resourceFileReaders.Add(assetsFile.upperFileName, assetsFile.assetsFileReader); - } - } - } - reader.Dispose(); - } - - public static void MergeSplitAssets(string dirPath) - { - string[] splitFiles = Directory.GetFiles(dirPath, "*.split0"); - foreach (var splitFile in splitFiles) - { - string destFile = Path.GetFileNameWithoutExtension(splitFile); - string destPath = Path.GetDirectoryName(splitFile) + "\\"; - var destFull = destPath + destFile; - if (!File.Exists(destFull)) - { - string[] splitParts = Directory.GetFiles(destPath, destFile + ".split*"); - using (var destStream = File.Create(destFull)) - { - for (int i = 0; i < splitParts.Length; i++) - { - string splitPart = destFull + ".split" + i; - using (var sourceStream = File.OpenRead(splitPart)) - sourceStream.CopyTo(destStream); - } - } - } - } - } public static int ExtractBundleFile(string bundleFileName) { @@ -280,7 +136,7 @@ namespace Unity_Studio } case 128: //Font { - unityFont m_Font = new unityFont(asset, false); + UnityFont m_Font = new UnityFont(asset, false); exportable = true; break; } @@ -397,7 +253,41 @@ namespace Unity_Studio foreach (var m_GameObject in assetsFile.GameObjectList.Values) { - assetsfileList.ParseGameObject(m_GameObject); + //ParseGameObject + foreach (var m_Component in m_GameObject.m_Components) + { + if (m_Component.m_FileID >= 0 && m_Component.m_FileID < assetsfileList.Count) + { + var sourceFile = assetsfileList[m_Component.m_FileID]; + if (sourceFile.preloadTable.TryGetValue(m_Component.m_PathID, out var asset)) + { + switch (asset.Type2) + { + case 4: //Transform + { + m_GameObject.m_Transform = m_Component; + break; + } + case 23: //MeshRenderer + { + m_GameObject.m_MeshRenderer = m_Component; + break; + } + case 33: //MeshFilter + { + m_GameObject.m_MeshFilter = m_Component; + break; + } + case 137: //SkinnedMeshRenderer + { + m_GameObject.m_SkinnedMeshRenderer = m_Component; + break; + } + } + } + } + } + // var parentNode = fileNode; @@ -459,1430 +349,13 @@ namespace Unity_Studio #endregion } - public static void WriteFBX(string FBXfile, bool allNodes) - { - var timestamp = DateTime.Now; - - using (StreamWriter FBXwriter = new StreamWriter(FBXfile)) - { - StringBuilder fbx = new StringBuilder(); - StringBuilder ob = new StringBuilder(); //Objects builder - StringBuilder cb = new StringBuilder(); //Connections builder - StringBuilder mb = new StringBuilder(); //Materials builder to get texture count in advance - StringBuilder cb2 = new StringBuilder(); //and keep connections ordered - cb.Append("\n}\n");//Objects end - cb.Append("\nConnections: {"); - - HashSet GameObjects = new HashSet(); - HashSet LimbNodes = new HashSet(); - HashSet Skins = new HashSet(); - HashSet Meshes = new HashSet();//MeshFilters are not unique!! - HashSet Materials = new HashSet(); - HashSet Textures = new HashSet(); - - int DeformerCount = 0; - /* - uniqueIDs can begin with zero, so they are preceded by a number specific to their type - this will also make it easier to debug FBX files - 1: Model - 2: NodeAttribute - 3: Geometry - 4: Deformer - 5: CollectionExclusive - 6: Material - 7: Texture - 8: Video - 9: - */ - - #region loop nodes and collect objects for export - foreach (var assetsFile in assetsfileList) - { - foreach (var m_GameObject in assetsFile.GameObjectList.Values) - { - if (m_GameObject.Checked || allNodes) - { - GameObjects.Add(m_GameObject); - - if (assetsfileList.TryGetPD(m_GameObject.m_MeshFilter, out var MeshFilterPD)) - { - //MeshFilters are not unique! - //MeshFilters.Add(MeshFilterPD); - MeshFilter m_MeshFilter = new MeshFilter(MeshFilterPD); - if (assetsfileList.TryGetPD(m_MeshFilter.m_Mesh, out var MeshPD)) - { - Meshes.Add(MeshPD); - - //write connections here and Mesh objects separately without having to backtrack through their MEshFilter to het the GameObject ID - //also note that MeshFilters are not unique, they cannot be used for instancing geometry - cb2.AppendFormat("\n\n\t;Geometry::, Model::{0}", m_GameObject.m_Name); - cb2.AppendFormat("\n\tC: \"OO\",3{0},1{1}", MeshPD.uniqueID, m_GameObject.uniqueID); - } - } - - #region get Renderer - if (assetsfileList.TryGetPD(m_GameObject.m_MeshRenderer, out var RendererPD)) - { - MeshRenderer m_Renderer = new MeshRenderer(RendererPD); - - foreach (var MaterialPPtr in m_Renderer.m_Materials) - { - if (assetsfileList.TryGetPD(MaterialPPtr, out var MaterialPD)) - { - Materials.Add(MaterialPD); - cb2.AppendFormat("\n\n\t;Material::, Model::{0}", m_GameObject.m_Name); - cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", MaterialPD.uniqueID, m_GameObject.uniqueID); - } - } - } - - #endregion - - #region get SkinnedMeshRenderer - if (assetsfileList.TryGetPD(m_GameObject.m_SkinnedMeshRenderer, out var SkinnedMeshPD)) - { - Skins.Add(SkinnedMeshPD); - - SkinnedMeshRenderer m_SkinnedMeshRenderer = new SkinnedMeshRenderer(SkinnedMeshPD); - - foreach (var MaterialPPtr in m_SkinnedMeshRenderer.m_Materials) - { - if (assetsfileList.TryGetPD(MaterialPPtr, out var MaterialPD)) - { - Materials.Add(MaterialPD); - cb2.AppendFormat("\n\n\t;Material::, Model::{0}", m_GameObject.m_Name); - cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", MaterialPD.uniqueID, m_GameObject.uniqueID); - } - } - - if ((bool)Properties.Settings.Default["exportDeformers"]) - { - DeformerCount += m_SkinnedMeshRenderer.m_Bones.Length; - - //collect skeleton dummies to make sure they are exported - foreach (var bonePPtr in m_SkinnedMeshRenderer.m_Bones) - { - if (assetsfileList.TryGetTransform(bonePPtr, out var b_Transform)) - { - if (assetsfileList.TryGetGameObject(b_Transform.m_GameObject, out var m_Bone)) - { - LimbNodes.Add(m_Bone); - //also collect the root bone - if (m_Bone.Parent.Level > 0) { LimbNodes.Add((GameObject)m_Bone.Parent); } - //should I collect siblings? - } - - #region collect children because m_SkinnedMeshRenderer.m_Bones doesn't contain terminations - foreach (var ChildPPtr in b_Transform.m_Children) - { - if (assetsfileList.TryGetTransform(ChildPPtr, out var ChildTR)) - { - if (assetsfileList.TryGetGameObject(ChildTR.m_GameObject, out var m_Child)) - { - //check that the Model doesn't contain a Mesh, although this won't ensure it's part of the skeleton - if (m_Child.m_MeshFilter == null && m_Child.m_SkinnedMeshRenderer == null) - { - LimbNodes.Add(m_Child); - } - } - } - } - #endregion - } - } - } - } - #endregion - } - } - } - - //if ((bool)Properties.Settings.Default["convertDummies"]) { GameObjects.Except(LimbNodes); } - //else { GameObjects.UnionWith(LimbNodes); LimbNodes.Clear(); } - //add either way and use LimbNodes to test if a node is Null or LimbNode - GameObjects.UnionWith(LimbNodes); - #endregion - - #region write Materials, collect Texture objects - //StatusStripUpdate("Writing Materials"); - foreach (var MaterialPD in Materials) - { - Material m_Material = new Material(MaterialPD); - - mb.AppendFormat("\n\tMaterial: 6{0}, \"Material::{1}\", \"\" {{", MaterialPD.uniqueID, m_Material.m_Name); - mb.Append("\n\t\tVersion: 102"); - mb.Append("\n\t\tShadingModel: \"phong\""); - mb.Append("\n\t\tMultiLayer: 0"); - mb.Append("\n\t\tProperties70: {"); - mb.Append("\n\t\t\tP: \"ShadingModel\", \"KString\", \"\", \"\", \"phong\""); - - #region write material colors - foreach (var m_Color in m_Material.m_Colors) - { - switch (m_Color.first) - { - case "_Color": - case "gSurfaceColor": - mb.AppendFormat("\n\t\t\tP: \"DiffuseColor\", \"Color\", \"\", \"A\",{0},{1},{2}", m_Color.second[0], m_Color.second[1], m_Color.second[2]); - break; - case "_SpecularColor"://then what is _SpecColor?? - mb.AppendFormat("\n\t\t\tP: \"SpecularColor\", \"Color\", \"\", \"A\",{0},{1},{2}", m_Color.second[0], m_Color.second[1], m_Color.second[2]); - break; - case "_ReflectColor": - mb.AppendFormat("\n\t\t\tP: \"AmbientColor\", \"Color\", \"\", \"A\",{0},{1},{2}", m_Color.second[0], m_Color.second[1], m_Color.second[2]); - break; - default: - mb.AppendFormat("\n;\t\t\tP: \"{3}\", \"Color\", \"\", \"A\",{0},{1},{2}", m_Color.second[0], m_Color.second[1], m_Color.second[2], m_Color.first);//commented out - break; - } - } - #endregion - - #region write material parameters - foreach (var m_Float in m_Material.m_Floats) - { - switch (m_Float.first) - { - case "_Shininess": - mb.AppendFormat("\n\t\t\tP: \"ShininessExponent\", \"Number\", \"\", \"A\",{0}", m_Float.second); - mb.AppendFormat("\n\t\t\tP: \"Shininess\", \"Number\", \"\", \"A\",{0}", m_Float.second); - break; - case "_Transparency": - mb.Append("\n\t\t\tP: \"TransparentColor\", \"Color\", \"\", \"A\",1,1,1"); - mb.AppendFormat("\n\t\t\tP: \"TransparencyFactor\", \"Number\", \"\", \"A\",{0}", m_Float.second); - mb.AppendFormat("\n\t\t\tP: \"Opacity\", \"Number\", \"\", \"A\",{0}", (1 - m_Float.second)); - break; - default: - mb.AppendFormat("\n;\t\t\tP: \"{0}\", \"Number\", \"\", \"A\",{1}", m_Float.first, m_Float.second); - break; - } - } - #endregion - - //mb.Append("\n\t\t\tP: \"SpecularFactor\", \"Number\", \"\", \"A\",0"); - mb.Append("\n\t\t}"); - mb.Append("\n\t}"); - - #region write texture connections - foreach (var m_TexEnv in m_Material.m_TexEnvs) - { - #region get Porsche material from json - if (!assetsfileList.TryGetPD(m_TexEnv.m_Texture, out var TexturePD) && jsonMats != null) - { - if (jsonMats.TryGetValue(m_Material.m_Name, out var matProp)) - { - if (matProp.TryGetValue(m_TexEnv.name, out var texName)) - { - foreach (var asset in exportableAssets) - { - if (asset.Type2 == 28 && asset.Text == texName) - { - TexturePD = asset; - break; - } - } - } - } - } - #endregion - - if (TexturePD != null && TexturePD.Type2 == 28) - { - Textures.Add(TexturePD); - - cb2.AppendFormat("\n\n\t;Texture::, Material::{0}", m_Material.m_Name); - cb2.AppendFormat("\n\tC: \"OP\",7{0},6{1}, \"", TexturePD.uniqueID, MaterialPD.uniqueID); - - switch (m_TexEnv.name) - { - case "_MainTex": - case "gDiffuseSampler": - cb2.Append("DiffuseColor\""); - break; - case "_SpecularMap": - case "gSpecularSampler": - cb2.Append("SpecularColor\""); - break; - case "_NormalMap": - case "gNormalSampler": - cb2.Append("NormalMap\""); - break; - case "_BumpMap": - cb2.Append("Bump\""); - break; - default: - cb2.AppendFormat("{0}\"", m_TexEnv.name); - break; - } - } - } - #endregion - } - #endregion - - #region write generic FBX data after everything was collected - fbx.Append("; FBX 7.1.0 project file"); - fbx.Append("\nFBXHeaderExtension: {\n\tFBXHeaderVersion: 1003\n\tFBXVersion: 7100\n\tCreationTimeStamp: {\n\t\tVersion: 1000"); - fbx.Append("\n\t\tYear: " + timestamp.Year); - fbx.Append("\n\t\tMonth: " + timestamp.Month); - fbx.Append("\n\t\tDay: " + timestamp.Day); - fbx.Append("\n\t\tHour: " + timestamp.Hour); - fbx.Append("\n\t\tMinute: " + timestamp.Minute); - fbx.Append("\n\t\tSecond: " + timestamp.Second); - fbx.Append("\n\t\tMillisecond: " + timestamp.Millisecond); - fbx.Append("\n\t}\n\tCreator: \"Unity Studio by Chipicao\"\n}\n"); - - fbx.Append("\nGlobalSettings: {"); - fbx.Append("\n\tVersion: 1000"); - fbx.Append("\n\tProperties70: {"); - fbx.Append("\n\t\tP: \"UpAxis\", \"int\", \"Integer\", \"\",1"); - fbx.Append("\n\t\tP: \"UpAxisSign\", \"int\", \"Integer\", \"\",1"); - fbx.Append("\n\t\tP: \"FrontAxis\", \"int\", \"Integer\", \"\",2"); - fbx.Append("\n\t\tP: \"FrontAxisSign\", \"int\", \"Integer\", \"\",1"); - fbx.Append("\n\t\tP: \"CoordAxis\", \"int\", \"Integer\", \"\",0"); - fbx.Append("\n\t\tP: \"CoordAxisSign\", \"int\", \"Integer\", \"\",1"); - fbx.Append("\n\t\tP: \"OriginalUpAxis\", \"int\", \"Integer\", \"\",1"); - fbx.Append("\n\t\tP: \"OriginalUpAxisSign\", \"int\", \"Integer\", \"\",1"); - fbx.AppendFormat("\n\t\tP: \"UnitScaleFactor\", \"double\", \"Number\", \"\",{0}", Properties.Settings.Default["scaleFactor"]); - fbx.Append("\n\t\tP: \"OriginalUnitScaleFactor\", \"double\", \"Number\", \"\",1.0"); - //fbx.Append("\n\t\tP: \"AmbientColor\", \"ColorRGB\", \"Color\", \"\",0,0,0"); - //fbx.Append("\n\t\tP: \"DefaultCamera\", \"KString\", \"\", \"\", \"Producer Perspective\""); - //fbx.Append("\n\t\tP: \"TimeMode\", \"enum\", \"\", \"\",6"); - //fbx.Append("\n\t\tP: \"TimeProtocol\", \"enum\", \"\", \"\",2"); - //fbx.Append("\n\t\tP: \"SnapOnFrameMode\", \"enum\", \"\", \"\",0"); - //fbx.Append("\n\t\tP: \"TimeSpanStart\", \"KTime\", \"Time\", \"\",0"); - //fbx.Append("\n\t\tP: \"TimeSpanStop\", \"KTime\", \"Time\", \"\",153953860000"); - //fbx.Append("\n\t\tP: \"CustomFrameRate\", \"double\", \"Number\", \"\",-1"); - //fbx.Append("\n\t\tP: \"TimeMarker\", \"Compound\", \"\", \"\""); - //fbx.Append("\n\t\tP: \"CurrentTimeMarker\", \"int\", \"Integer\", \"\",-1"); - fbx.Append("\n\t}\n}\n"); - - fbx.Append("\nDocuments: {"); - fbx.Append("\n\tCount: 1"); - fbx.Append("\n\tDocument: 1234567890, \"\", \"Scene\" {"); - fbx.Append("\n\t\tProperties70: {"); - fbx.Append("\n\t\t\tP: \"SourceObject\", \"object\", \"\", \"\""); - fbx.Append("\n\t\t\tP: \"ActiveAnimStackName\", \"KString\", \"\", \"\", \"\""); - fbx.Append("\n\t\t}"); - fbx.Append("\n\t\tRootNode: 0"); - fbx.Append("\n\t}\n}\n"); - fbx.Append("\nReferences: {\n}\n"); - - fbx.Append("\nDefinitions: {"); - fbx.Append("\n\tVersion: 100"); - fbx.AppendFormat("\n\tCount: {0}", 1 + 2 * GameObjects.Count + Materials.Count + 2 * Textures.Count + ((bool)Properties.Settings.Default["exportDeformers"] ? Skins.Count + DeformerCount + Skins.Count + 1 : 0)); - - fbx.Append("\n\tObjectType: \"GlobalSettings\" {"); - fbx.Append("\n\t\tCount: 1"); - fbx.Append("\n\t}"); - - fbx.Append("\n\tObjectType: \"Model\" {"); - fbx.AppendFormat("\n\t\tCount: {0}", GameObjects.Count); - fbx.Append("\n\t}"); - - fbx.Append("\n\tObjectType: \"NodeAttribute\" {"); - fbx.AppendFormat("\n\t\tCount: {0}", GameObjects.Count - Meshes.Count - Skins.Count); - fbx.Append("\n\t\tPropertyTemplate: \"FbxNull\" {"); - fbx.Append("\n\t\t\tProperties70: {"); - fbx.Append("\n\t\t\t\tP: \"Color\", \"ColorRGB\", \"Color\", \"\",0.8,0.8,0.8"); - fbx.Append("\n\t\t\t\tP: \"Size\", \"double\", \"Number\", \"\",100"); - fbx.Append("\n\t\t\t\tP: \"Look\", \"enum\", \"\", \"\",1"); - fbx.Append("\n\t\t\t}\n\t\t}\n\t}"); - - fbx.Append("\n\tObjectType: \"Geometry\" {"); - fbx.AppendFormat("\n\t\tCount: {0}", Meshes.Count + Skins.Count); - fbx.Append("\n\t}"); - - fbx.Append("\n\tObjectType: \"Material\" {"); - fbx.AppendFormat("\n\t\tCount: {0}", Materials.Count); - fbx.Append("\n\t}"); - - fbx.Append("\n\tObjectType: \"Texture\" {"); - fbx.AppendFormat("\n\t\tCount: {0}", Textures.Count); - fbx.Append("\n\t}"); - - fbx.Append("\n\tObjectType: \"Video\" {"); - fbx.AppendFormat("\n\t\tCount: {0}", Textures.Count); - fbx.Append("\n\t}"); - - if ((bool)Properties.Settings.Default["exportDeformers"]) - { - fbx.Append("\n\tObjectType: \"CollectionExclusive\" {"); - fbx.AppendFormat("\n\t\tCount: {0}", Skins.Count); - fbx.Append("\n\t\tPropertyTemplate: \"FbxDisplayLayer\" {"); - fbx.Append("\n\t\t\tProperties70: {"); - fbx.Append("\n\t\t\t\tP: \"Color\", \"ColorRGB\", \"Color\", \"\",0.8,0.8,0.8"); - fbx.Append("\n\t\t\t\tP: \"Show\", \"bool\", \"\", \"\",1"); - fbx.Append("\n\t\t\t\tP: \"Freeze\", \"bool\", \"\", \"\",0"); - fbx.Append("\n\t\t\t\tP: \"LODBox\", \"bool\", \"\", \"\",0"); - fbx.Append("\n\t\t\t}"); - fbx.Append("\n\t\t}"); - fbx.Append("\n\t}"); - - fbx.Append("\n\tObjectType: \"Deformer\" {"); - fbx.AppendFormat("\n\t\tCount: {0}", DeformerCount + Skins.Count); - fbx.Append("\n\t}"); - - fbx.Append("\n\tObjectType: \"Pose\" {"); - fbx.Append("\n\t\tCount: 1"); - fbx.Append("\n\t}"); - } - - fbx.Append("\n}\n"); - fbx.Append("\nObjects: {"); - - FBXwriter.Write(fbx); - fbx.Clear(); - #endregion - - #region write Model nodes and connections - //StatusStripUpdate("Writing Nodes and hierarchy"); - foreach (var m_GameObject in GameObjects) - { - if (m_GameObject.m_MeshFilter == null && m_GameObject.m_SkinnedMeshRenderer == null) - { - if ((bool)Properties.Settings.Default["exportDeformers"] && (bool)Properties.Settings.Default["convertDummies"] && LimbNodes.Contains(m_GameObject)) - { - ob.AppendFormat("\n\tNodeAttribute: 2{0}, \"NodeAttribute::\", \"LimbNode\" {{", m_GameObject.uniqueID); - ob.Append("\n\t\tTypeFlags: \"Skeleton\""); - ob.Append("\n\t}"); - - ob.AppendFormat("\n\tModel: 1{0}, \"Model::{1}\", \"LimbNode\" {{", m_GameObject.uniqueID, m_GameObject.m_Name); - } - else - { - ob.AppendFormat("\n\tNodeAttribute: 2{0}, \"NodeAttribute::\", \"Null\" {{", m_GameObject.uniqueID); - ob.Append("\n\t\tTypeFlags: \"Null\""); - ob.Append("\n\t}"); - - ob.AppendFormat("\n\tModel: 1{0}, \"Model::{1}\", \"Null\" {{", m_GameObject.uniqueID, m_GameObject.m_Name); - } - - //connect NodeAttribute to Model - cb.AppendFormat("\n\n\t;NodeAttribute::, Model::{0}", m_GameObject.m_Name); - cb.AppendFormat("\n\tC: \"OO\",2{0},1{0}", m_GameObject.uniqueID); - } - else - { - ob.AppendFormat("\n\tModel: 1{0}, \"Model::{1}\", \"Mesh\" {{", m_GameObject.uniqueID, m_GameObject.m_Name); - } - - ob.Append("\n\t\tVersion: 232"); - ob.Append("\n\t\tProperties70: {"); - ob.Append("\n\t\t\tP: \"InheritType\", \"enum\", \"\", \"\",1"); - ob.Append("\n\t\t\tP: \"ScalingMax\", \"Vector3D\", \"Vector\", \"\",0,0,0"); - ob.Append("\n\t\t\tP: \"DefaultAttributeIndex\", \"int\", \"Integer\", \"\",0"); - - if (assetsfileList.TryGetTransform(m_GameObject.m_Transform, out var m_Transform)) - { - float[] m_EulerRotation = QuatToEuler(new[] { m_Transform.m_LocalRotation[0], -m_Transform.m_LocalRotation[1], -m_Transform.m_LocalRotation[2], m_Transform.m_LocalRotation[3] }); - - ob.AppendFormat("\n\t\t\tP: \"Lcl Translation\", \"Lcl Translation\", \"\", \"A\",{0},{1},{2}", -m_Transform.m_LocalPosition[0], m_Transform.m_LocalPosition[1], m_Transform.m_LocalPosition[2]); - ob.AppendFormat("\n\t\t\tP: \"Lcl Rotation\", \"Lcl Rotation\", \"\", \"A\",{0},{1},{2}", m_EulerRotation[0], m_EulerRotation[1], m_EulerRotation[2]);//handedness is switched in quat - ob.AppendFormat("\n\t\t\tP: \"Lcl Scaling\", \"Lcl Scaling\", \"\", \"A\",{0},{1},{2}", m_Transform.m_LocalScale[0], m_Transform.m_LocalScale[1], m_Transform.m_LocalScale[2]); - } - - //mb.Append("\n\t\t\tP: \"UDP3DSMAX\", \"KString\", \"\", \"U\", \"MapChannel:1 = UVChannel_1&cr;&lf;MapChannel:2 = UVChannel_2&cr;&lf;\""); - //mb.Append("\n\t\t\tP: \"MaxHandle\", \"int\", \"Integer\", \"UH\",24"); - ob.Append("\n\t\t}"); - ob.Append("\n\t\tShading: T"); - ob.Append("\n\t\tCulling: \"CullingOff\"\n\t}"); - - //connect Model to parent - GameObject parentObject = (GameObject)m_GameObject.Parent; - if (GameObjects.Contains(parentObject)) - { - cb.AppendFormat("\n\n\t;Model::{0}, Model::{1}", m_GameObject.m_Name, parentObject.m_Name); - cb.AppendFormat("\n\tC: \"OO\",1{0},1{1}", m_GameObject.uniqueID, parentObject.uniqueID); - } - else - { - cb.AppendFormat("\n\n\t;Model::{0}, Model::RootNode", m_GameObject.m_Name); - cb.AppendFormat("\n\tC: \"OO\",1{0},0", m_GameObject.uniqueID); - } - - - } - #endregion - - #region write non-skinnned Geometry - //StatusStripUpdate("Writing Geometry"); - foreach (var MeshPD in Meshes) - { - Mesh m_Mesh = new Mesh(MeshPD, true); - MeshFBX(m_Mesh, MeshPD.uniqueID, ob); - - //write data 8MB at a time - if (ob.Length > (8 * 0x100000)) - { FBXwriter.Write(ob); ob.Clear(); } - } - #endregion - - #region write Deformer objects and skinned Geometry - StringBuilder pb = new StringBuilder(); - //generate unique ID for BindPose - pb.Append("\n\tPose: 5123456789, \"Pose::BIND_POSES\", \"BindPose\" {"); - pb.Append("\n\t\tType: \"BindPose\""); - pb.Append("\n\t\tVersion: 100"); - pb.AppendFormat("\n\t\tNbPoseNodes: {0}", Skins.Count + LimbNodes.Count); - - foreach (var SkinnedMeshPD in Skins) - { - SkinnedMeshRenderer m_SkinnedMeshRenderer = new SkinnedMeshRenderer(SkinnedMeshPD); - if (assetsfileList.TryGetGameObject(m_SkinnedMeshRenderer.m_GameObject, out var m_GameObject) && assetsfileList.TryGetPD(m_SkinnedMeshRenderer.m_Mesh, out var MeshPD)) - { - //generate unique Geometry ID for instanced mesh objects - //instanced skinned geometry is possible in FBX, but all instances are linked to the same skeleton nodes - //TODO: create instances if deformer option is not selected - //find a way to test if a mesh instance was loaded previously and if it uses the same skeleton, then create instance or copy - var keepID = MeshPD.uniqueID; - MeshPD.uniqueID = SkinnedMeshPD.uniqueID; - Mesh m_Mesh = new Mesh(MeshPD, true); - MeshFBX(m_Mesh, MeshPD.uniqueID, ob); - - //write data 8MB at a time - if (ob.Length > (8 * 0x100000)) - { FBXwriter.Write(ob); ob.Clear(); } - - cb2.AppendFormat("\n\n\t;Geometry::, Model::{0}", m_GameObject.m_Name); - cb2.AppendFormat("\n\tC: \"OO\",3{0},1{1}", MeshPD.uniqueID, m_GameObject.uniqueID); - - if ((bool)Properties.Settings.Default["exportDeformers"]) - { - //add BindPose node - pb.Append("\n\t\tPoseNode: {"); - pb.AppendFormat("\n\t\t\tNode: 1{0}", m_GameObject.uniqueID); - //pb.Append("\n\t\t\tMatrix: *16 {"); - //pb.Append("\n\t\t\t\ta: "); - //pb.Append("\n\t\t\t} "); - pb.Append("\n\t\t}"); - - ob.AppendFormat("\n\tCollectionExclusive: 5{0}, \"DisplayLayer::{1}\", \"DisplayLayer\" {{", SkinnedMeshPD.uniqueID, m_GameObject.m_Name); - ob.Append("\n\t\tProperties70: {"); - ob.Append("\n\t\t}"); - ob.Append("\n\t}"); - - //connect Model to DisplayLayer - cb2.AppendFormat("\n\n\t;Model::{0}, DisplayLayer::", m_GameObject.m_Name); - cb2.AppendFormat("\n\tC: \"OO\",1{0},5{1}", m_GameObject.uniqueID, SkinnedMeshPD.uniqueID); - - //write Deformers - if (m_Mesh.m_Skin.Length > 0 && m_Mesh.m_BindPose.Length >= m_SkinnedMeshRenderer.m_Bones.Length) - { - //write main Skin Deformer - ob.AppendFormat("\n\tDeformer: 4{0}, \"Deformer::\", \"Skin\" {{", SkinnedMeshPD.uniqueID); - ob.Append("\n\t\tVersion: 101"); - ob.Append("\n\t\tLink_DeformAcuracy: 50"); - ob.Append("\n\t}"); //Deformer end - - //connect Skin Deformer to Geometry - cb2.Append("\n\n\t;Deformer::, Geometry::"); - cb2.AppendFormat("\n\tC: \"OO\",4{0},3{1}", SkinnedMeshPD.uniqueID, MeshPD.uniqueID); - - for (int b = 0; b < m_SkinnedMeshRenderer.m_Bones.Length; b++) - { - if (assetsfileList.TryGetTransform(m_SkinnedMeshRenderer.m_Bones[b], out var m_Transform)) - { - if (assetsfileList.TryGetGameObject(m_Transform.m_GameObject, out var m_Bone)) - { - int influences = 0, ibSplit = 0, wbSplit = 0; - StringBuilder ib = new StringBuilder();//indices (vertex) - StringBuilder wb = new StringBuilder();//weights - - for (int index = 0; index < m_Mesh.m_Skin.Length; index++) - { - if (m_Mesh.m_Skin[index][0].weight == 0 && (m_Mesh.m_Skin[index].All(x => x.weight == 0) || //if all weights (and indicces) are 0, bone0 has full control - m_Mesh.m_Skin[index][1].weight > 0)) //this implies a second bone exists, so bone0 has control too (otherwise it wouldn't be the first in the series) - { m_Mesh.m_Skin[index][0].weight = 1; } - - var influence = m_Mesh.m_Skin[index].Find(x => x.boneIndex == b && x.weight > 0); - if (influence != null) - { - influences++; - ib.AppendFormat("{0},", index); - wb.AppendFormat("{0},", influence.weight); - - if (ib.Length - ibSplit > 2000) { ib.Append("\n"); ibSplit = ib.Length; } - if (wb.Length - wbSplit > 2000) { wb.Append("\n"); wbSplit = wb.Length; } - } - - /*float weight; - if (m_Mesh.m_Skin[index].TryGetValue(b, out weight)) - { - if (weight > 0) - { - influences++; - ib.AppendFormat("{0},", index); - wb.AppendFormat("{0},", weight); - } - else if (m_Mesh.m_Skin[index].Keys.Count == 1)//m_Mesh.m_Skin[index].Values.All(x => x == 0) - { - influences++; - ib.AppendFormat("{0},", index); - wb.AppendFormat("{0},", 1); - } - - if (ib.Length - ibSplit > 2000) { ib.Append("\n"); ibSplit = ib.Length; } - if (wb.Length - wbSplit > 2000) { wb.Append("\n"); wbSplit = wb.Length; } - }*/ - } - if (influences > 0) - { - ib.Length--;//remove last comma - wb.Length--;//remove last comma - } - - //SubDeformer objects need unique IDs because 2 or more deformers can be linked to the same bone - ob.AppendFormat("\n\tDeformer: 4{0}{1}, \"SubDeformer::\", \"Cluster\" {{", b, SkinnedMeshPD.uniqueID); - ob.Append("\n\t\tVersion: 100"); - ob.Append("\n\t\tUserData: \"\", \"\""); - - ob.AppendFormat("\n\t\tIndexes: *{0} {{\n\t\t\ta: ", influences); - ob.Append(ib); - ob.Append("\n\t\t}"); - ib.Clear(); - - ob.AppendFormat("\n\t\tWeights: *{0} {{\n\t\t\ta: ", influences); - ob.Append(wb); - ob.Append("\n\t\t}"); - wb.Clear(); - - ob.Append("\n\t\tTransform: *16 {\n\t\t\ta: "); - //ob.Append(string.Join(",", m_Mesh.m_BindPose[b])); - var m = m_Mesh.m_BindPose[b]; - ob.AppendFormat("{0},{1},{2},{3},", m[0, 0], -m[1, 0], -m[2, 0], m[3, 0]); - ob.AppendFormat("{0},{1},{2},{3},", -m[0, 1], m[1, 1], m[2, 1], m[3, 1]); - ob.AppendFormat("{0},{1},{2},{3},", -m[0, 2], m[1, 2], m[2, 2], m[3, 2]); - ob.AppendFormat("{0},{1},{2},{3},", -m[0, 3], m[1, 3], m[2, 3], m[3, 3]); - ob.Append("\n\t\t}"); - - ob.Append("\n\t}"); //SubDeformer end - - //connect SubDeformer to Skin Deformer - cb2.Append("\n\n\t;SubDeformer::, Deformer::"); - cb2.AppendFormat("\n\tC: \"OO\",4{0}{1},4{1}", b, SkinnedMeshPD.uniqueID); - - //connect dummy Model to SubDeformer - cb2.AppendFormat("\n\n\t;Model::{0}, SubDeformer::", m_Bone.m_Name); - cb2.AppendFormat("\n\tC: \"OO\",1{0},4{1}{2}", m_Bone.uniqueID, b, SkinnedMeshPD.uniqueID); - } - } - } - } - } - - MeshPD.uniqueID = keepID; - } - } - - if ((bool)Properties.Settings.Default["exportDeformers"]) - { - foreach (var m_Bone in LimbNodes) - { - //add BindPose node - pb.Append("\n\t\tPoseNode: {"); - pb.AppendFormat("\n\t\t\tNode: 1{0}", m_Bone.uniqueID); - //pb.Append("\n\t\t\tMatrix: *16 {"); - //pb.Append("\n\t\t\t\ta: "); - //pb.Append("\n\t\t\t} "); - pb.Append("\n\t\t}"); - } - pb.Append("\n\t}"); //BindPose end - ob.Append(pb); pb.Clear(); - } - #endregion - - ob.Append(mb); mb.Clear(); - cb.Append(cb2); cb2.Clear(); - - #region write & extract Textures - foreach (var TexturePD in Textures) - { - //TODO check texture type and set path accordingly; eg. CubeMap, Texture3D - string texPathName = Path.GetDirectoryName(FBXfile) + "\\Texture2D\\"; - ExportTexture2D(TexturePD, texPathName, false); - texPathName = Path.GetFullPath(Path.Combine(texPathName, $"{TexturePD.Text}.png"));//必须是png文件 - ob.AppendFormat("\n\tTexture: 7{0}, \"Texture::{1}\", \"\" {{", TexturePD.uniqueID, TexturePD.Text); - ob.Append("\n\t\tType: \"TextureVideoClip\""); - ob.Append("\n\t\tVersion: 202"); - ob.AppendFormat("\n\t\tTextureName: \"Texture::{0}\"", TexturePD.Text); - ob.Append("\n\t\tProperties70: {"); - ob.Append("\n\t\t\tP: \"UVSet\", \"KString\", \"\", \"\", \"UVChannel_0\""); - ob.Append("\n\t\t\tP: \"UseMaterial\", \"bool\", \"\", \"\",1"); - ob.Append("\n\t\t}"); - ob.AppendFormat("\n\t\tMedia: \"Video::{0}\"", TexturePD.Text); - ob.AppendFormat("\n\t\tFileName: \"{0}\"", texPathName); - ob.AppendFormat("\n\t\tRelativeFilename: \"{0}\"", texPathName.Replace($"{Path.GetDirectoryName(FBXfile)}\\", "")); - ob.Append("\n\t}"); - - ob.AppendFormat("\n\tVideo: 8{0}, \"Video::{1}\", \"Clip\" {{", TexturePD.uniqueID, TexturePD.Text); - ob.Append("\n\t\tType: \"Clip\""); - ob.Append("\n\t\tProperties70: {"); - ob.AppendFormat("\n\t\t\tP: \"Path\", \"KString\", \"XRefUrl\", \"\", \"{0}\"", texPathName); - ob.Append("\n\t\t}"); - ob.AppendFormat("\n\t\tFileName: \"{0}\"", texPathName); - ob.AppendFormat("\n\t\tRelativeFilename: \"{0}\"", texPathName.Replace($"{Path.GetDirectoryName(FBXfile)}\\", "")); - ob.Append("\n\t}"); - - //connect video to texture - cb.AppendFormat("\n\n\t;Video::{0}, Texture::{0}", TexturePD.Text); - cb.AppendFormat("\n\tC: \"OO\",8{0},7{1}", TexturePD.uniqueID, TexturePD.uniqueID); - } - #endregion - - FBXwriter.Write(ob); - ob.Clear(); - - cb.Append("\n}");//Connections end - FBXwriter.Write(cb); - cb.Clear(); - - StatusStripUpdate("Finished exporting " + Path.GetFileName(FBXfile)); - } - } - - private static void MeshFBX(Mesh m_Mesh, string MeshID, StringBuilder ob) - { - if (m_Mesh.m_VertexCount > 0)//general failsafe - { - //StatusStripUpdate("Writing Geometry: " + m_Mesh.m_Name); - - ob.AppendFormat("\n\tGeometry: 3{0}, \"Geometry::\", \"Mesh\" {{", MeshID); - ob.Append("\n\t\tProperties70: {"); - var randomColor = RandomColorGenerator(m_Mesh.m_Name); - ob.AppendFormat("\n\t\t\tP: \"Color\", \"ColorRGB\", \"Color\", \"\",{0},{1},{2}", ((float)randomColor[0] / 255), ((float)randomColor[1] / 255), ((float)randomColor[2] / 255)); - ob.Append("\n\t\t}"); - - #region Vertices - ob.AppendFormat("\n\t\tVertices: *{0} {{\n\t\t\ta: ", m_Mesh.m_VertexCount * 3); - - int c = 3;//vertex components - //skip last component in vector4 - if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4) { c++; } //haha - - int lineSplit = ob.Length; - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - ob.AppendFormat("{0},{1},{2},", -m_Mesh.m_Vertices[v * c], m_Mesh.m_Vertices[v * c + 1], m_Mesh.m_Vertices[v * c + 2]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - ob.Append("\n\t\t}"); - #endregion - - #region Indices - //in order to test topology for triangles/quads we need to store submeshes and write each one as geometry, then link to Mesh Node - ob.AppendFormat("\n\t\tPolygonVertexIndex: *{0} {{\n\t\t\ta: ", m_Mesh.m_Indices.Count); - - lineSplit = ob.Length; - for (int f = 0; f < m_Mesh.m_Indices.Count / 3; f++) - { - ob.AppendFormat("{0},{1},{2},", m_Mesh.m_Indices[f * 3], m_Mesh.m_Indices[f * 3 + 2], (-m_Mesh.m_Indices[f * 3 + 1] - 1)); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - - ob.Append("\n\t\t}"); - ob.Append("\n\t\tGeometryVersion: 124"); - #endregion - - #region Normals - if ((bool)Properties.Settings.Default["exportNormals"] && m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0) - { - ob.Append("\n\t\tLayerElementNormal: 0 {"); - ob.Append("\n\t\t\tVersion: 101"); - ob.Append("\n\t\t\tName: \"\""); - ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); - ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); - ob.AppendFormat("\n\t\t\tNormals: *{0} {{\n\t\t\ta: ", (m_Mesh.m_VertexCount * 3)); - - if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3) { c = 3; } - else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4) { c = 4; } - - lineSplit = ob.Length; - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - ob.AppendFormat("{0},{1},{2},", -m_Mesh.m_Normals[v * c], m_Mesh.m_Normals[v * c + 1], m_Mesh.m_Normals[v * c + 2]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - ob.Append("\n\t\t\t}\n\t\t}"); - } - #endregion - - #region Tangents - if ((bool)Properties.Settings.Default["exportTangents"] && m_Mesh.m_Tangents != null && m_Mesh.m_Tangents.Length > 0) - { - ob.Append("\n\t\tLayerElementTangent: 0 {"); - ob.Append("\n\t\t\tVersion: 101"); - ob.Append("\n\t\t\tName: \"\""); - ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); - ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); - ob.AppendFormat("\n\t\t\tTangents: *{0} {{\n\t\t\ta: ", (m_Mesh.m_VertexCount * 3)); - - if (m_Mesh.m_Tangents.Length == m_Mesh.m_VertexCount * 3) { c = 3; } - else if (m_Mesh.m_Tangents.Length == m_Mesh.m_VertexCount * 4) { c = 4; } - - lineSplit = ob.Length; - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - ob.AppendFormat("{0},{1},{2},", -m_Mesh.m_Tangents[v * c], m_Mesh.m_Tangents[v * c + 1], m_Mesh.m_Tangents[v * c + 2]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - ob.Append("\n\t\t\t}\n\t\t}"); - } - #endregion - - #region Colors - if ((bool)Properties.Settings.Default["exportColors"] && m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length > 0) - { - ob.Append("\n\t\tLayerElementColor: 0 {"); - ob.Append("\n\t\t\tVersion: 101"); - ob.Append("\n\t\t\tName: \"\""); - //ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); - //ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); - ob.Append("\n\t\t\tMappingInformationType: \"ByPolygonVertex\""); - ob.Append("\n\t\t\tReferenceInformationType: \"IndexToDirect\""); - ob.AppendFormat("\n\t\t\tColors: *{0} {{\n\t\t\ta: ", m_Mesh.m_Colors.Length); - //ob.Append(string.Join(",", m_Mesh.m_Colors)); - - lineSplit = ob.Length; - if (m_Mesh.m_Colors.Length == m_Mesh.m_VertexCount * 3) - { - for (int i = 0; i < m_Mesh.m_VertexCount; i++) - { - ob.AppendFormat("{0},{1},{2},{3},", m_Mesh.m_Colors[i * 3], m_Mesh.m_Colors[i * 3 + 1], m_Mesh.m_Colors[i * 3 + 2], 1.0f); - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - } - else - { - for (int i = 0; i < m_Mesh.m_VertexCount; i++) - { - ob.AppendFormat("{0},{1},{2},{3},", m_Mesh.m_Colors[i * 4], m_Mesh.m_Colors[i * 4 + 1], m_Mesh.m_Colors[i * 4 + 2], m_Mesh.m_Colors[i * 4 + 3]); - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - } - ob.Length--;//remove last comma - - ob.Append("\n\t\t\t}"); - ob.AppendFormat("\n\t\t\tColorIndex: *{0} {{\n\t\t\ta: ", m_Mesh.m_Indices.Count); - - lineSplit = ob.Length; - for (int f = 0; f < m_Mesh.m_Indices.Count / 3; f++) - { - ob.AppendFormat("{0},{1},{2},", m_Mesh.m_Indices[f * 3], m_Mesh.m_Indices[f * 3 + 2], m_Mesh.m_Indices[f * 3 + 1]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - - ob.Append("\n\t\t\t}\n\t\t}"); - } - #endregion - - #region UV1 - //does FBX support UVW coordinates? - if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length > 0) - { - ob.Append("\n\t\tLayerElementUV: 0 {"); - ob.Append("\n\t\t\tVersion: 101"); - ob.Append("\n\t\t\tName: \"UVChannel_1\""); - ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); - ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); - ob.AppendFormat("\n\t\t\tUV: *{0} {{\n\t\t\ta: ", m_Mesh.m_UV1.Length); - - lineSplit = ob.Length; - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - ob.AppendFormat("{0},{1},", m_Mesh.m_UV1[v * 2], 1 - m_Mesh.m_UV1[v * 2 + 1]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - ob.Append("\n\t\t\t}\n\t\t}"); - } - #endregion - #region UV2 - if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV2 != null && m_Mesh.m_UV2.Length > 0) - { - ob.Append("\n\t\tLayerElementUV: 1 {"); - ob.Append("\n\t\t\tVersion: 101"); - ob.Append("\n\t\t\tName: \"UVChannel_2\""); - ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); - ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); - ob.AppendFormat("\n\t\t\tUV: *{0} {{\n\t\t\ta: ", m_Mesh.m_UV2.Length); - - lineSplit = ob.Length; - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - ob.AppendFormat("{0},{1},", m_Mesh.m_UV2[v * 2], 1 - m_Mesh.m_UV2[v * 2 + 1]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - ob.Append("\n\t\t\t}\n\t\t}"); - } - #endregion - #region UV3 - if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV3 != null && m_Mesh.m_UV3.Length > 0) - { - ob.Append("\n\t\tLayerElementUV: 2 {"); - ob.Append("\n\t\t\tVersion: 101"); - ob.Append("\n\t\t\tName: \"UVChannel_3\""); - ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); - ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); - ob.AppendFormat("\n\t\t\tUV: *{0} {{\n\t\t\ta: ", m_Mesh.m_UV3.Length); - - lineSplit = ob.Length; - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - ob.AppendFormat("{0},{1},", m_Mesh.m_UV3[v * 2], 1 - m_Mesh.m_UV3[v * 2 + 1]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - ob.Append("\n\t\t\t}\n\t\t}"); - } - #endregion - #region UV4 - if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV4 != null && m_Mesh.m_UV4.Length > 0) - { - ob.Append("\n\t\tLayerElementUV: 3 {"); - ob.Append("\n\t\t\tVersion: 101"); - ob.Append("\n\t\t\tName: \"UVChannel_4\""); - ob.Append("\n\t\t\tMappingInformationType: \"ByVertice\""); - ob.Append("\n\t\t\tReferenceInformationType: \"Direct\""); - ob.AppendFormat("\n\t\t\tUV: *{0} {{\n\t\t\ta: ", m_Mesh.m_UV4.Length); - - lineSplit = ob.Length; - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - ob.AppendFormat("{0},{1},", m_Mesh.m_UV4[v * 2], 1 - m_Mesh.m_UV4[v * 2 + 1]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - ob.Append("\n\t\t\t}\n\t\t}"); - } - #endregion - - #region Material - ob.Append("\n\t\tLayerElementMaterial: 0 {"); - ob.Append("\n\t\t\tVersion: 101"); - ob.Append("\n\t\t\tName: \"\""); - ob.Append("\n\t\t\tMappingInformationType: \""); - ob.Append(m_Mesh.m_SubMeshes.Count == 1 ? "AllSame\"" : "ByPolygon\""); - ob.Append("\n\t\t\tReferenceInformationType: \"IndexToDirect\""); - ob.AppendFormat("\n\t\t\tMaterials: *{0} {{", m_Mesh.m_materialIDs.Count); - ob.Append("\n\t\t\t\ta: "); - if (m_Mesh.m_materialIDs.Count == 1) { ob.Append("0"); } - else - { - lineSplit = ob.Length; - for (int i = 0; i < m_Mesh.m_materialIDs.Count; i++) - { - ob.AppendFormat("{0},", m_Mesh.m_materialIDs[i]); - - if (ob.Length - lineSplit > 2000) - { - ob.Append("\n"); - lineSplit = ob.Length; - } - } - ob.Length--;//remove last comma - } - ob.Append("\n\t\t\t}\n\t\t}"); - #endregion - - #region Layers - ob.Append("\n\t\tLayer: 0 {"); - ob.Append("\n\t\t\tVersion: 100"); - if ((bool)Properties.Settings.Default["exportNormals"] && m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0) - { - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementNormal\""); - ob.Append("\n\t\t\t\tTypedIndex: 0"); - ob.Append("\n\t\t\t}"); - } - if ((bool)Properties.Settings.Default["exportTangents"] && m_Mesh.m_Tangents != null && m_Mesh.m_Tangents.Length > 0) - { - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementTangent\""); - ob.Append("\n\t\t\t\tTypedIndex: 0"); - ob.Append("\n\t\t\t}"); - } - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementMaterial\""); - ob.Append("\n\t\t\t\tTypedIndex: 0"); - ob.Append("\n\t\t\t}"); - // - /*ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementTexture\""); - ob.Append("\n\t\t\t\tTypedIndex: 0"); - ob.Append("\n\t\t\t}"); - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementBumpTextures\""); - ob.Append("\n\t\t\t\tTypedIndex: 0"); - ob.Append("\n\t\t\t}");*/ - if ((bool)Properties.Settings.Default["exportColors"] && m_Mesh.m_Colors != null && m_Mesh.m_Colors.Length > 0) - { - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementColor\""); - ob.Append("\n\t\t\t\tTypedIndex: 0"); - ob.Append("\n\t\t\t}"); - } - if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length > 0) - { - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementUV\""); - ob.Append("\n\t\t\t\tTypedIndex: 0"); - ob.Append("\n\t\t\t}"); - } - ob.Append("\n\t\t}"); //Layer 0 end - - if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV2 != null && m_Mesh.m_UV2.Length > 0) - { - ob.Append("\n\t\tLayer: 1 {"); - ob.Append("\n\t\t\tVersion: 100"); - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementUV\""); - ob.Append("\n\t\t\t\tTypedIndex: 1"); - ob.Append("\n\t\t\t}"); - ob.Append("\n\t\t}"); //Layer 1 end - } - - if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV3 != null && m_Mesh.m_UV3.Length > 0) - { - ob.Append("\n\t\tLayer: 2 {"); - ob.Append("\n\t\t\tVersion: 100"); - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementUV\""); - ob.Append("\n\t\t\t\tTypedIndex: 2"); - ob.Append("\n\t\t\t}"); - ob.Append("\n\t\t}"); //Layer 2 end - } - - if ((bool)Properties.Settings.Default["exportUVs"] && m_Mesh.m_UV4 != null && m_Mesh.m_UV4.Length > 0) - { - ob.Append("\n\t\tLayer: 3 {"); - ob.Append("\n\t\t\tVersion: 100"); - ob.Append("\n\t\t\tLayerElement: {"); - ob.Append("\n\t\t\t\tType: \"LayerElementUV\""); - ob.Append("\n\t\t\t\tTypedIndex: 3"); - ob.Append("\n\t\t\t}"); - ob.Append("\n\t\t}"); //Layer 3 end - } - #endregion - - ob.Append("\n\t}"); //Geometry end - } - } - - private static float[] QuatToEuler(float[] q) - { - double eax = 0; - double eay = 0; - double eaz = 0; - - float qx = q[0]; - float qy = q[1]; - float qz = q[2]; - float qw = q[3]; - - double[,] M = new double[4, 4]; - - double Nq = qx * qx + qy * qy + qz * qz + qw * qw; - double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0; - double xs = qx * s, ys = qy * s, zs = qz * s; - double wx = qw * xs, wy = qw * ys, wz = qw * zs; - double xx = qx * xs, xy = qx * ys, xz = qx * zs; - double yy = qy * ys, yz = qy * zs, zz = qz * zs; - - M[0, 0] = 1.0 - (yy + zz); M[0, 1] = xy - wz; M[0, 2] = xz + wy; - M[1, 0] = xy + wz; M[1, 1] = 1.0 - (xx + zz); M[1, 2] = yz - wx; - M[2, 0] = xz - wy; M[2, 1] = yz + wx; M[2, 2] = 1.0 - (xx + yy); - M[3, 0] = M[3, 1] = M[3, 2] = M[0, 3] = M[1, 3] = M[2, 3] = 0.0; M[3, 3] = 1.0; - - double test = Math.Sqrt(M[0, 0] * M[0, 0] + M[1, 0] * M[1, 0]); - if (test > 16 * 1.19209290E-07F)//FLT_EPSILON - { - eax = Math.Atan2(M[2, 1], M[2, 2]); - eay = Math.Atan2(-M[2, 0], test); - eaz = Math.Atan2(M[1, 0], M[0, 0]); - } - else - { - eax = Math.Atan2(-M[1, 2], M[1, 1]); - eay = Math.Atan2(-M[2, 0], test); - eaz = 0; - } - - return new[] { (float)(eax * 180 / Math.PI), (float)(eay * 180 / Math.PI), (float)(eaz * 180 / Math.PI) }; - } - - private static byte[] RandomColorGenerator(string name) - { - int nameHash = name.GetHashCode(); - Random r = new Random(nameHash); - //Random r = new Random(DateTime.Now.Millisecond); - - byte red = (byte)r.Next(0, 255); - byte green = (byte)r.Next(0, 255); - byte blue = (byte)r.Next(0, 255); - - return new[] { red, green, blue }; - } - - public static bool ExportTexture2D(AssetPreloadData asset, string exportPathName, bool flip) - { - var m_Texture2D = new Texture2D(asset, true); - if (m_Texture2D.image_data == null) - return false; - var convert = (bool)Properties.Settings.Default["convertTexture"]; - var bitmap = m_Texture2D.ConvertToBitmap(flip); - if (convert && bitmap != null) - { - ImageFormat format = null; - var ext = (string)Properties.Settings.Default["convertType"]; - switch (ext) - { - case "BMP": - format = ImageFormat.Bmp; - break; - case "PNG": - format = ImageFormat.Png; - break; - case "JPEG": - format = ImageFormat.Jpeg; - break; - } - var exportFullName = exportPathName + asset.Text + "." + ext.ToLower(); - if (ExportFileExists(exportFullName)) - return false; - bitmap.Save(exportFullName, format); - bitmap.Dispose(); - return true; - } - if (!convert) - { - var exportFullName = exportPathName + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - File.WriteAllBytes(exportFullName, m_Texture2D.ConvertToContainer()); - return true; - } - return false; - } - - public static bool ExportAudioClip(AssetPreloadData asset, string exportPath) - { - var m_AudioClip = new AudioClip(asset, true); - if (m_AudioClip.m_AudioData == null) - return false; - var convertAudio = (bool)Properties.Settings.Default["convertAudio"]; - if (convertAudio && m_AudioClip.IsFMODSupport) - { - var exportFullName = exportPath + asset.Text + ".wav"; - if (ExportFileExists(exportFullName)) - return false; - FMOD.CREATESOUNDEXINFO exinfo = new FMOD.CREATESOUNDEXINFO(); - var result = FMOD.Factory.System_Create(out var system); - if (result != FMOD.RESULT.OK) - return false; - result = system.init(1, FMOD.INITFLAGS.NORMAL, IntPtr.Zero); - if (result != FMOD.RESULT.OK) - return false; - 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); - if (result != FMOD.RESULT.OK) - return false; - result = sound.getSubSound(0, out var subsound); - if (result != FMOD.RESULT.OK) - return false; - result = subsound.getFormat(out var type, out var format, out int NumChannels, out int BitsPerSample); - if (result != FMOD.RESULT.OK) - return false; - result = subsound.getDefaults(out var frequency, out int priority); - if (result != FMOD.RESULT.OK) - return false; - var SampleRate = (int)frequency; - result = subsound.getLength(out var length, FMOD.TIMEUNIT.PCMBYTES); - if (result != FMOD.RESULT.OK) - return false; - result = subsound.@lock(0, length, out var ptr1, out var ptr2, out var len1, out var len2); - if (result != FMOD.RESULT.OK) - return false; - byte[] buffer = new byte[len1 + 44]; - //添加wav头 - Encoding.UTF8.GetBytes("RIFF").CopyTo(buffer, 0); - BitConverter.GetBytes(len1 + 36).CopyTo(buffer, 4); - Encoding.UTF8.GetBytes("WAVEfmt ").CopyTo(buffer, 8); - BitConverter.GetBytes(16).CopyTo(buffer, 16); - BitConverter.GetBytes((short)1).CopyTo(buffer, 20); - BitConverter.GetBytes((short)NumChannels).CopyTo(buffer, 22); - BitConverter.GetBytes(SampleRate).CopyTo(buffer, 24); - BitConverter.GetBytes(SampleRate * NumChannels * BitsPerSample / 8).CopyTo(buffer, 28); - BitConverter.GetBytes((short)(NumChannels * BitsPerSample / 8)).CopyTo(buffer, 32); - BitConverter.GetBytes((short)BitsPerSample).CopyTo(buffer, 34); - Encoding.UTF8.GetBytes("data").CopyTo(buffer, 36); - BitConverter.GetBytes(len1).CopyTo(buffer, 40); - Marshal.Copy(ptr1, buffer, 44, (int)len1); - File.WriteAllBytes(exportFullName, buffer); - result = subsound.unlock(ptr1, ptr2, len1, len2); - if (result != FMOD.RESULT.OK) - return false; - subsound.release(); - sound.release(); - system.release(); - } - else - { - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - File.WriteAllBytes(exportFullName, m_AudioClip.m_AudioData); - } - return true; - } - - public static bool ExportShader(AssetPreloadData asset, string exportPath) - { - var m_Shader = new Shader(asset, true); - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - File.WriteAllBytes(exportFullName, m_Shader.m_Script); - return true; - } - - public static bool ExportTextAsset(AssetPreloadData asset, string exportPath) - { - var m_TextAsset = new TextAsset(asset, true); - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - File.WriteAllBytes(exportFullName, m_TextAsset.m_Script); - return true; - } - - public static bool ExportMonoBehaviour(AssetPreloadData asset, string exportPath) - { - var m_MonoBehaviour = new MonoBehaviour(asset, true); - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - File.WriteAllText(exportFullName, m_MonoBehaviour.serializedText); - return true; - } - - public static bool ExportFont(AssetPreloadData asset, string exportPath) - { - var m_Font = new unityFont(asset, true); - if (m_Font.m_FontData != null) - { - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - File.WriteAllBytes(exportFullName, m_Font.m_FontData); - return true; - } - return false; - } - - public static bool ExportMesh(AssetPreloadData asset, string exportPath) - { - var m_Mesh = new Mesh(asset, true); - if (m_Mesh.m_VertexCount <= 0) - return false; - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - var sb = new StringBuilder(); - sb.AppendLine("g " + m_Mesh.m_Name); - #region Vertices - int c = 3; - if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4) - { - c = 4; - } - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - sb.AppendFormat("v {0} {1} {2}\r\n", -m_Mesh.m_Vertices[v * c], m_Mesh.m_Vertices[v * c + 1], m_Mesh.m_Vertices[v * c + 2]); - } - #endregion - - #region UV - if (m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length == m_Mesh.m_VertexCount * 2) - { - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV1[v * 2], m_Mesh.m_UV1[v * 2 + 1]); - } - } - else if (m_Mesh.m_UV2 != null && m_Mesh.m_UV2.Length == m_Mesh.m_VertexCount * 2) - { - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV2[v * 2], m_Mesh.m_UV2[v * 2 + 1]); - } - } - #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) - { - c = 3; - } - else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4) - { - c = 4; - } - for (int v = 0; v < m_Mesh.m_VertexCount; v++) - { - sb.AppendFormat("vn {0} {1} {2}\r\n", -m_Mesh.m_Normals[v * c], m_Mesh.m_Normals[v * c + 1], m_Mesh.m_Normals[v * c + 2]); - } - } - #endregion - - #region Face - int sum = 0; - for (var i = 0; i < m_Mesh.m_SubMeshes.Count; i++) - { - sb.AppendLine($"g {m_Mesh.m_Name}_{i}"); - int indexCount = (int)m_Mesh.m_SubMeshes[i].indexCount; - var end = sum + indexCount / 3; - for (int f = sum; f < end; f++) - { - sb.AppendFormat("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\r\n", m_Mesh.m_Indices[f * 3 + 2] + 1, m_Mesh.m_Indices[f * 3 + 1] + 1, m_Mesh.m_Indices[f * 3] + 1); - } - sum = end; - } - #endregion - - sb.Replace("NaN", "0"); - File.WriteAllText(exportFullName, sb.ToString()); - return true; - } - - public static bool ExportVideoClip(AssetPreloadData asset, string exportPath) - { - var m_VideoClip = new VideoClip(asset, true); - if (m_VideoClip.m_VideoData != null) - { - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - File.WriteAllBytes(exportFullName, m_VideoClip.m_VideoData); - return true; - } - return false; - } - - public static bool ExportMovieTexture(AssetPreloadData asset, string exportPath) - { - var m_MovieTexture = new MovieTexture(asset, true); - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - File.WriteAllBytes(exportFullName, m_MovieTexture.m_MovieData); - return true; - } - - public static bool ExportSprite(AssetPreloadData asset, string exportPath) - { - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - var bitmap = GetImageFromSprite(asset); - if (bitmap != null) - { - bitmap.Save(exportFullName, ImageFormat.Png); - return true; - } - return false; - } - - public static bool ExportRawFile(AssetPreloadData asset, string exportPath) - { - var exportFullName = exportPath + asset.Text + asset.extension; - if (ExportFileExists(exportFullName)) - return false; - asset.sourceFile.assetsFileReader.Position = asset.Offset; - var bytes = asset.sourceFile.assetsFileReader.ReadBytes(asset.Size); - File.WriteAllBytes(exportFullName, bytes); - return true; - } - - public static bool ExportFileExists(string filename) - { - if (File.Exists(filename)) - { - return true; - } - Directory.CreateDirectory(Path.GetDirectoryName(filename)); - return false; - } - public static string FixFileName(string str) { if (str.Length >= 260) return Path.GetRandomFileName(); return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_')); } - private static bool CheckBundleFile(string fileName, out EndianBinaryReader reader) + public static bool CheckBundleFile(string fileName, out EndianBinaryReader reader) { reader = new EndianBinaryReader(File.OpenRead(fileName)); var signature = reader.ReadStringToNull(); @@ -1915,91 +388,5 @@ namespace Unity_Studio } return selectFile.Distinct().ToArray(); } - - public static Bitmap GetImageFromSprite(AssetPreloadData asset) - { - if (spriteCache.TryGetValue(asset, out var bitmap)) - return (Bitmap)bitmap.Clone(); - var m_Sprite = new Sprite(asset, true); - if (assetsfileList.TryGetPD(m_Sprite.m_SpriteAtlas, out var assetPreloadData)) - { - var m_SpriteAtlas = new SpriteAtlas(assetPreloadData); - var index = m_SpriteAtlas.guids.FindIndex(x => x == m_Sprite.first); - if (index >= 0 && assetsfileList.TryGetPD(m_SpriteAtlas.textures[index], out assetPreloadData)) - { - return CutImage(asset, assetPreloadData, m_SpriteAtlas.textureRects[index], m_Sprite); - } - } - else - { - if (assetsfileList.TryGetPD(m_Sprite.texture, out assetPreloadData)) - { - return CutImage(asset, assetPreloadData, m_Sprite.textureRect); - } - } - - return null; - } - - private static Bitmap CutImage(AssetPreloadData asset, AssetPreloadData texture2DAsset, RectangleF textureRect) - { - var texture2D = new Texture2D(texture2DAsset, true); - using (var originalImage = texture2D.ConvertToBitmap(false)) - { - if (originalImage != null) - { - var info = texture2DAsset.InfoText; - var start = info.IndexOf("Format"); - info = info.Substring(start, info.Length - start); - asset.InfoText = $"Width: {textureRect.Width}\nHeight: {textureRect.Height}\n" + info; - var spriteImage = originalImage.Clone(textureRect, PixelFormat.Format32bppArgb); - spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipY); - spriteCache.Add(asset, spriteImage); - return (Bitmap)spriteImage.Clone(); - } - } - - return null; - } - - private static Bitmap CutImage(AssetPreloadData asset, AssetPreloadData texture2DAsset, RectangleF textureRect, Sprite sprite) - { - var texture2D = new Texture2D(texture2DAsset, true); - using (var originalImage = texture2D.ConvertToBitmap(false)) - { - if (originalImage != null) - { - var info = texture2DAsset.InfoText; - var start = info.IndexOf("Format"); - info = info.Substring(start, info.Length - start); - asset.InfoText = $"Width: {textureRect.Width}\nHeight: {textureRect.Height}\n" + info; - var spriteImage = originalImage.Clone(textureRect, PixelFormat.Format32bppArgb); - using (var brush = new TextureBrush(spriteImage)) - { - using (var path = new GraphicsPath()) - { - foreach (var p in sprite.m_PhysicsShape) - path.AddPolygon(p); - using (var matr = new Matrix()) - { - matr.Translate(sprite.m_Rect.Width * sprite.m_Pivot.X, sprite.m_Rect.Height * sprite.m_Pivot.Y); - matr.Scale(sprite.m_PixelsToUnits, sprite.m_PixelsToUnits); - path.Transform(matr); - var bitmap = new Bitmap((int)textureRect.Width, (int)textureRect.Height); - using (var graphic = Graphics.FromImage(bitmap)) - { - graphic.FillPath(brush, path); - bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); - spriteCache.Add(asset, bitmap); - return (Bitmap)bitmap.Clone(); - } - } - } - } - } - } - - return null; - } } } diff --git a/Unity Studio/Unity Studio-x86.csproj b/Unity Studio/Unity Studio-x86.csproj index 4c109b4..565180a 100644 --- a/Unity Studio/Unity Studio-x86.csproj +++ b/Unity Studio/Unity Studio-x86.csproj @@ -146,9 +146,14 @@ + + + + + @@ -168,7 +173,7 @@ - + diff --git a/Unity Studio/Unity Studio.csproj b/Unity Studio/Unity Studio.csproj index 24556cc..69250bf 100644 --- a/Unity Studio/Unity Studio.csproj +++ b/Unity Studio/Unity Studio.csproj @@ -146,8 +146,13 @@ + + + + + @@ -168,7 +173,7 @@ - + diff --git a/Unity Studio/UnityStudioForm.cs b/Unity Studio/UnityStudioForm.cs index e45c2bf..bc46b46 100644 --- a/Unity Studio/UnityStudioForm.cs +++ b/Unity Studio/UnityStudioForm.cs @@ -14,6 +14,10 @@ using System.Drawing.Text; using OpenTK; using OpenTK.Graphics.OpenGL; using static Unity_Studio.UnityStudio; +using static Unity_Studio.FBXExporter; +using static Unity_Studio.UnityImporter; +using static Unity_Studio.UnityExporter; +using static Unity_Studio.SpriteHelper; namespace Unity_Studio { @@ -821,7 +825,7 @@ namespace Unity_Studio #region Font case 128: //Font { - unityFont m_Font = new unityFont(asset, true); + UnityFont m_Font = new UnityFont(asset, true); if (m_Font.m_FontData != null) { IntPtr data = Marshal.AllocCoTaskMem(m_Font.m_FontData.Length);