diff --git a/AssetTools.NET/AssetsTools.NET.csproj b/AssetTools.NET/AssetsTools.NET.csproj index 81a47c6..2d35511 100644 --- a/AssetTools.NET/AssetsTools.NET.csproj +++ b/AssetTools.NET/AssetsTools.NET.csproj @@ -1,12 +1,13 @@  - netstandard2.0;net40 + netstandard2.0;net35;net40 Library false AnyCPU 8 True False + Disable bin\x64\Debug\ diff --git a/AssetTools.NET/AssetsTools.NET.nuspec b/AssetTools.NET/AssetsTools.NET.nuspec index 84c6970..95eea86 100644 --- a/AssetTools.NET/AssetsTools.NET.nuspec +++ b/AssetTools.NET/AssetsTools.NET.nuspec @@ -2,7 +2,7 @@ AssetsTools.NET - 3.0.0 + 3.0.3 nesrak1 nesrak1 false @@ -11,7 +11,7 @@ icon.png An assets/bundle library, inspired by UABE's AssetsTools An assets/bundle library, inspired by UABE's AssetsTools. Read and write assets and bundle files from engine versions 5.x and later. For most cases, you'll need the class data file which you can find in the AssetRipper/Tpk repo. See the wiki for usage and examples. - v3.0.0 - the complete overhaul of assetstools.net. bug fixes, new replacers, and more. + v3.0.3 - added back .net 3.5 support, fixed typetrees with unicode, added field iterator helper class https://github.com/nesrak1/AssetsTools.NET diff --git a/AssetTools.NET/Extra/AssetHelper.cs b/AssetTools.NET/Extra/AssetHelper.cs index e7004c1..4f6576d 100644 --- a/AssetTools.NET/Extra/AssetHelper.cs +++ b/AssetTools.NET/Extra/AssetHelper.cs @@ -66,7 +66,7 @@ public static string GetAssetNameFast(AssetsFile file, ClassDatabaseFile cldb, A if (file.Metadata.TypeTreeEnabled) { - ushort scriptId = file.GetScriptIndex(info); + ushort scriptId = info.GetScriptIndex(file); TypeTreeType ttType = file.Metadata.FindTypeTreeTypeByID(info.TypeId, scriptId); diff --git a/AssetTools.NET/Extra/AssetsManager/AssetsFileInstance.cs b/AssetTools.NET/Extra/AssetsManager/AssetsFileInstance.cs index 0d3672b..cff2896 100644 --- a/AssetTools.NET/Extra/AssetsManager/AssetsFileInstance.cs +++ b/AssetTools.NET/Extra/AssetsManager/AssetsFileInstance.cs @@ -1,5 +1,4 @@ -using System.Collections.Concurrent; -using System.IO; +using System.IO; using System.Linq; namespace AssetsTools.NET.Extra diff --git a/AssetTools.NET/Extra/AssetsManager/AssetsManager.Bundle.cs b/AssetTools.NET/Extra/AssetsManager/AssetsManager.Bundle.cs index d0af9b3..addb584 100644 --- a/AssetTools.NET/Extra/AssetsManager/AssetsManager.Bundle.cs +++ b/AssetTools.NET/Extra/AssetsManager/AssetsManager.Bundle.cs @@ -4,6 +4,11 @@ namespace AssetsTools.NET.Extra { public partial class AssetsManager { + public static string GetBundleLookupKey(string path) + { + return Path.GetFullPath(path); + } + /// /// Load a from a stream with a path. /// Use the version of this method to skip the path argument. @@ -17,7 +22,7 @@ public partial class AssetsManager public BundleFileInstance LoadBundleFile(Stream stream, string path, bool unpackIfPacked = true) { BundleFileInstance bunInst; - string lookupKey = GetFileLookupKey(path); + string lookupKey = GetBundleLookupKey(path); if (BundleLookup.TryGetValue(lookupKey, out bunInst)) return bunInst; @@ -68,7 +73,7 @@ public BundleFileInstance LoadBundleFile(string path, bool unpackIfPacked = true /// True if the file was found and closed, and false if it wasn't found. public bool UnloadBundleFile(string path) { - string lookupKey = GetFileLookupKey(path); + string lookupKey = GetBundleLookupKey(path); if (BundleLookup.TryGetValue(lookupKey, out BundleFileInstance bunInst)) { bunInst.file.Close(); @@ -109,7 +114,7 @@ public bool UnloadBundleFile(BundleFileInstance bunInst) if (Bundles.Contains(bunInst)) { - string lookupKey = GetFileLookupKey(bunInst.path); + string lookupKey = GetBundleLookupKey(bunInst.path); lock (BundleLookup) { lock (Bundles) diff --git a/AssetTools.NET/Extra/AssetsManager/AssetsManager.Deserialization.cs b/AssetTools.NET/Extra/AssetsManager/AssetsManager.Deserialization.cs index 5323d4e..c98e2e2 100644 --- a/AssetTools.NET/Extra/AssetsManager/AssetsManager.Deserialization.cs +++ b/AssetTools.NET/Extra/AssetsManager/AssetsManager.Deserialization.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.IO; namespace AssetsTools.NET.Extra @@ -58,26 +57,25 @@ public AssetTypeTemplateField GetTemplateBaseField( AssetsFileInstance inst, AssetsFileReader reader, long absByteStart, int typeId, ushort scriptIndex, AssetReadFlags readFlags) { - AssetsFile file = inst.file; AssetTypeTemplateField baseField = null; - bool hasTypeTree = inst.file.Metadata.TypeTreeEnabled; - - bool preferEditor = readFlags.HasFlag(AssetReadFlags.PreferEditor); - bool forceFromCldb = readFlags.HasFlag(AssetReadFlags.ForceFromCldb); - bool skipMonoBehaviourFields = readFlags.HasFlag(AssetReadFlags.SkipMonoBehaviourFields); // if non-monobehaviour type is in cache, return the cached item - if (UseTemplateFieldCache && typeId != (int)AssetClassID.MonoBehaviour && templateFieldCache.TryGetValue(typeId, out baseField)) + bool isMonoBehaviourTypeId = typeId == (int)AssetClassID.MonoBehaviour || typeId < 0; + if (UseTemplateFieldCache && !isMonoBehaviourTypeId && templateFieldCache.TryGetValue(typeId, out baseField)) { return baseField; } + AssetsFile file = inst.file; + bool hasTypeTree = file.Metadata.TypeTreeEnabled; + bool forceFromCldb = Net35Polyfill.HasFlag(readFlags, AssetReadFlags.ForceFromCldb); + // if there's a type tree AND we aren't forcing from a class database // (with the condition that we actually have a class database) then // load from that instead if (hasTypeTree && (!forceFromCldb || ClassDatabase == null)) { - if (UseMonoTemplateFieldCache && typeId == (int)AssetClassID.MonoBehaviour) + if (UseMonoTemplateFieldCache && isMonoBehaviourTypeId) { if (monoTypeTreeTemplateFieldCache.TryGetValue(inst, out ConcurrentDictionary templates) && templates.TryGetValue(scriptIndex, out baseField)) @@ -92,11 +90,11 @@ public AssetTypeTemplateField GetTemplateBaseField( baseField = new AssetTypeTemplateField(); baseField.FromTypeTree(ttType); - if (UseTemplateFieldCache && typeId != (int)AssetClassID.MonoBehaviour) + if (UseTemplateFieldCache && !isMonoBehaviourTypeId) { templateFieldCache[typeId] = baseField; } - else if (UseMonoTemplateFieldCache && typeId == (uint)AssetClassID.MonoBehaviour) + else if (UseMonoTemplateFieldCache && isMonoBehaviourTypeId) { if (!monoTypeTreeTemplateFieldCache.TryGetValue(inst, out ConcurrentDictionary templates)) { @@ -110,9 +108,9 @@ public AssetTypeTemplateField GetTemplateBaseField( } // if we cached a monobehaviour from a class database, clone a copy - if (UseTemplateFieldCache && UseMonoTemplateFieldCache && typeId == (int)AssetClassID.MonoBehaviour) + if (UseTemplateFieldCache && UseMonoTemplateFieldCache && isMonoBehaviourTypeId) { - if (templateFieldCache.TryGetValue(typeId, out baseField)) + if (templateFieldCache.TryGetValue((int)AssetClassID.MonoBehaviour, out baseField)) { baseField = baseField.Clone(); } @@ -128,24 +126,28 @@ public AssetTypeTemplateField GetTemplateBaseField( return null; } - ClassDatabaseType cldbType = ClassDatabase.FindAssetClassByID(typeId); + int fixedTypeId = isMonoBehaviourTypeId ? (int)AssetClassID.MonoBehaviour : typeId; + + ClassDatabaseType cldbType = ClassDatabase.FindAssetClassByID(fixedTypeId); if (cldbType == null) { return null; } + bool preferEditor = Net35Polyfill.HasFlag(readFlags, AssetReadFlags.PreferEditor); + baseField = new AssetTypeTemplateField(); baseField.FromClassDatabase(ClassDatabase, cldbType, preferEditor); if (UseTemplateFieldCache) { - if (typeId == (int)AssetClassID.MonoBehaviour) + if (fixedTypeId == (int)AssetClassID.MonoBehaviour) { - templateFieldCache[typeId] = baseField.Clone(); + templateFieldCache[fixedTypeId] = baseField.Clone(); } else { - templateFieldCache[typeId] = baseField; + templateFieldCache[fixedTypeId] = baseField; } } } @@ -155,7 +157,8 @@ public AssetTypeTemplateField GetTemplateBaseField( // can get the monoscript (we could also use the script index // but this is safer) and then passing the script from there to // the temp generator. we then append those fields to the base. - if (typeId == (int)AssetClassID.MonoBehaviour && MonoTempGenerator != null && !skipMonoBehaviourFields && reader != null) + bool skipMonoBehaviourFields = Net35Polyfill.HasFlag(readFlags, AssetReadFlags.SkipMonoBehaviourFields); + if (isMonoBehaviourTypeId && MonoTempGenerator != null && !skipMonoBehaviourFields && reader != null) { AssetTypeValueField mbBaseField = baseField.MakeValue(reader, absByteStart); AssetPPtr msPtr = AssetPPtr.FromField(mbBaseField["m_Script"]); @@ -280,7 +283,7 @@ public AssetTypeTemplateField CreateTemplateBaseField(AssetsFileInstance inst, i } else { - if (id != (int)AssetClassID.MonoBehaviour || scriptIndex == 0xffff) + if ((id != (int)AssetClassID.MonoBehaviour && id >= 0) || scriptIndex == 0xffff) { var cldbType = ClassDatabase.FindAssetClassByID(id); templateField.FromClassDatabase(ClassDatabase, cldbType); @@ -334,7 +337,7 @@ public AssetTypeValueField GetBaseField(AssetsFileInstance inst, AssetFileInfo i } else { - using MemoryStream assetDataStream = new MemoryStream(); + using MemoryStream assetDataStream = new MemoryStream((int)info.ByteSize); lock (inst.LockReader) { AssetsFileReader reader = inst.file.Reader; diff --git a/AssetTools.NET/Extra/AssetsManager/AssetsManager.cs b/AssetTools.NET/Extra/AssetsManager/AssetsManager.cs index ccac01b..d42338f 100644 --- a/AssetTools.NET/Extra/AssetsManager/AssetsManager.cs +++ b/AssetTools.NET/Extra/AssetsManager/AssetsManager.cs @@ -1,5 +1,4 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; +using System.Collections.Generic; namespace AssetsTools.NET.Extra { diff --git a/AssetTools.NET/Extra/AssetsManager/BundleFileInstance.cs b/AssetTools.NET/Extra/AssetsManager/BundleFileInstance.cs index 1708c11..e47dc07 100644 --- a/AssetTools.NET/Extra/AssetsManager/BundleFileInstance.cs +++ b/AssetTools.NET/Extra/AssetsManager/BundleFileInstance.cs @@ -9,6 +9,11 @@ public class BundleFileInstance public string name; public AssetBundleFile file; /// + /// Original compression type. If this bundle is decompressed, you might + /// use this value to compress it back to its original compression type. + /// + public AssetBundleCompressionType originalCompression; + /// /// List of loaded assets files for this bundle. /// /// @@ -24,12 +29,16 @@ public BundleFileInstance(Stream stream, string filePath, bool unpackIfPacked = { path = Path.GetFullPath(filePath); name = Path.GetFileName(path); + file = new AssetBundleFile(); file.Read(new AssetsFileReader(stream)); + + originalCompression = file.GetCompressionType(); if (file.Header != null && file.DataIsCompressed && unpackIfPacked) { file = BundleHelper.UnpackBundle(file); } + loadedAssetsFiles = new List(); } diff --git a/AssetTools.NET/Extra/MonoDeserializer/CommonMonoTemplateHelper.cs b/AssetTools.NET/Extra/MonoDeserializer/CommonMonoTemplateHelper.cs index 22f4141..f22e3e4 100644 --- a/AssetTools.NET/Extra/MonoDeserializer/CommonMonoTemplateHelper.cs +++ b/AssetTools.NET/Extra/MonoDeserializer/CommonMonoTemplateHelper.cs @@ -88,45 +88,19 @@ public static class CommonMonoTemplateHelper ["System.String"] = "string" }; - private static readonly Dictionary baseToAssetValueType = new Dictionary() - { - ["System.Boolean"] = AssetValueType.UInt8, - ["System.SByte"] = AssetValueType.Int8, - ["System.Byte"] = AssetValueType.UInt8, - ["System.Char"] = AssetValueType.UInt16, - ["System.Int16"] = AssetValueType.Int16, - ["System.UInt16"] = AssetValueType.UInt16, - ["System.Int32"] = AssetValueType.Int32, - ["System.UInt32"] = AssetValueType.UInt32, - ["System.Int64"] = AssetValueType.Int64, - ["System.UInt64"] = AssetValueType.UInt64, - ["System.Double"] = AssetValueType.Double, - ["System.Single"] = AssetValueType.Float, - ["System.String"] = AssetValueType.String - }; - - #endregion - - #region Checks - - public static string ConvertBaseToPrimitive(string name) { if (baseToPrimitive.TryGetValue(name, out string primitiveName)) { return primitiveName; } + return name; } - public static AssetValueType ConvertBaseToAssetValueType(string name) - { - if (baseToAssetValueType.TryGetValue(name, out AssetValueType value)) - { - return value; - } - return AssetValueType.None; - } + #endregion + + #region Checks public static bool IsSpecialUnityType(string fullName) { @@ -145,20 +119,18 @@ public static bool IsPrimitiveType(string fullName) public static bool TypeAligns(AssetValueType valueType) { - if (valueType.Equals(AssetValueType.Bool) || - valueType.Equals(AssetValueType.Int8) || - valueType.Equals(AssetValueType.UInt8) || - valueType.Equals(AssetValueType.Int16) || - valueType.Equals(AssetValueType.UInt16)) - return true; - return false; + return valueType.Equals(AssetValueType.Bool) + || valueType.Equals(AssetValueType.Int8) + || valueType.Equals(AssetValueType.UInt8) + || valueType.Equals(AssetValueType.Int16) + || valueType.Equals(AssetValueType.UInt16); } public static int GetSerializationLimit(UnityVersion unityVersion) { - if (unityVersion.major > 2020 || - (unityVersion.major == 2020 && (unityVersion.minor >= 2 || (unityVersion.minor == 1 && unityVersion.patch >= 4))) || - (unityVersion.major == 2019 && unityVersion.minor == 4 && unityVersion.patch >= 9)) + if (unityVersion.major > 2020 + || (unityVersion.major == 2020 && (unityVersion.minor > 1 || (unityVersion.minor == 1 && unityVersion.patch >= 4))) + || (unityVersion.major == 2019 && unityVersion.minor == 4 && unityVersion.patch >= 9)) { return 10; } @@ -210,13 +182,16 @@ public static List Array(AssetTypeTemplateField field) { Name = "Array", Type = "Array", - ValueType = field.ValueType == AssetValueType.UInt8 ? AssetValueType.ByteArray : AssetValueType.Array, + ValueType = field.ValueType == AssetValueType.UInt8 + ? AssetValueType.ByteArray + : AssetValueType.Array, IsArray = true, IsAligned = true, HasValue = true, Children = new List { - Int("size"), CreateTemplateField("data", field.Type, field.ValueType, field.Children) + Int("size"), + CreateTemplateField("data", field.Type, field.ValueType, field.Children) } }; @@ -232,10 +207,18 @@ public static List ManagedReference(UnityVersion unityVe { if (unityVersion.major > 2021 || (unityVersion.major == 2021 && unityVersion.minor >= 2)) { - return new List { Long("rid") }; + return new List + { + Long("rid") + }; + } + else + { + return new List + { + Int("id") + }; } - - return new List { Int("id") }; } public static AssetTypeTemplateField ManagedReferencesRegistry(string name, UnityVersion unityVersion) => @@ -244,10 +227,20 @@ public static List ManagedReferencesRegistry(UnityVersio { if (unityVersion.major > 2021 || (unityVersion.major == 2021 && unityVersion.minor >= 2)) { - return new List { Int("version"), Vector(ReferencedObject("RefIds", unityVersion)) }; + return new List + { + Int("version"), + Vector(ReferencedObject("RefIds", unityVersion)) + }; + } + else + { + return new List + { + Int("version"), + ReferencedObject("00000000", unityVersion) + }; } - - return new List { Int("version"), ReferencedObject("00000000", unityVersion) }; } public static AssetTypeTemplateField ReferencedObject(string name, UnityVersion unityVersion) => CreateTemplateField(name, "ReferencedObject", ReferencedObject(unityVersion)); @@ -255,16 +248,32 @@ public static List ReferencedObject(UnityVersion unityVe { if (unityVersion.major > 2021 || (unityVersion.major == 2021 && unityVersion.minor >= 2)) { - return new List { Long("rid"), ReferencedManagedType("type"), CreateTemplateField("data", "ReferencedObjectData", AssetValueType.None) }; + return new List + { + Long("rid"), + ReferencedManagedType("type"), + CreateTemplateField("data", "ReferencedObjectData", AssetValueType.None) + }; + } + else + { + return new List + { + ReferencedManagedType("type"), + CreateTemplateField("data", "ReferencedObjectData", AssetValueType.None) + }; } - - return new List { ReferencedManagedType("type"), CreateTemplateField("data", "ReferencedObjectData", AssetValueType.None) }; } public static AssetTypeTemplateField ReferencedManagedType(string name) => CreateTemplateField(name, "ReferencedManagedType", ReferencedManagedType()); public static List ReferencedManagedType() { - return new List { String("class"), String("ns"), String("asm") }; + return new List + { + String("class"), + String("ns"), + String("asm") + }; } #endregion @@ -274,131 +283,362 @@ public static List ReferencedManagedType() public static AssetTypeTemplateField Gradient(string name, UnityVersion unityVersion) => CreateTemplateField(name, "Gradient", Gradient(unityVersion)); public static List Gradient(UnityVersion unityVersion) { - if (unityVersion.major > 2022 || (unityVersion.major == 2022 && unityVersion.minor >= 2)) + if (unityVersion.major > 5 || (unityVersion.major == 5 && unityVersion.minor >= 6)) { - return new List { - RGBAf("key0"), RGBAf("key1"), RGBAf("key2"), RGBAf("key3"), RGBAf("key4"), RGBAf("key5"), RGBAf("key6"), RGBAf("key7"), - UShort("ctime0"), UShort("ctime1"), UShort("ctime2"), UShort("ctime3"), UShort("ctime4"), UShort("ctime5"), UShort("ctime6"), UShort("ctime7"), - UShort("atime0"), UShort("atime1"), UShort("atime2"), UShort("atime3"), UShort("atime4"), UShort("atime5"), UShort("atime6"), UShort("atime7"), - Byte("m_Mode"), SByte("m_ColorSpace"), Byte("m_NumColorKeys"), Byte("m_NumAlphaKeys", true) + List fields = new List + { + RGBAf("key0"), + RGBAf("key1"), + RGBAf("key2"), + RGBAf("key3"), + RGBAf("key4"), + RGBAf("key5"), + RGBAf("key6"), + RGBAf("key7"), + UShort("ctime0"), + UShort("ctime1"), + UShort("ctime2"), + UShort("ctime3"), + UShort("ctime4"), + UShort("ctime5"), + UShort("ctime6"), + UShort("ctime7"), + UShort("atime0"), + UShort("atime1"), + UShort("atime2"), + UShort("atime3"), + UShort("atime4"), + UShort("atime5"), + UShort("atime6"), + UShort("atime7") }; - } - return new List { - RGBAf("key0"), RGBAf("key1"), RGBAf("key2"), RGBAf("key3"), RGBAf("key4"), RGBAf("key5"), RGBAf("key6"), RGBAf("key7"), - UShort("ctime0"), UShort("ctime1"), UShort("ctime2"), UShort("ctime3"), UShort("ctime4"), UShort("ctime5"), UShort("ctime6"), UShort("ctime7"), - UShort("atime0"), UShort("atime1"), UShort("atime2"), UShort("atime3"), UShort("atime4"), UShort("atime5"), UShort("atime6"), UShort("atime7"), - Int("m_Mode"), Byte("m_NumColorKeys"), Byte("m_NumAlphaKeys", true) - }; + if (unityVersion.major > 2022 || (unityVersion.major == 2022 && unityVersion.minor >= 2)) + { + fields.Add(Byte("m_Mode")); + fields.Add(SByte("m_ColorSpace")); + } + else + { + fields.Add(Int("m_Mode")); + } + + fields.Add(Byte("m_NumColorKeys")); + fields.Add(Byte("m_NumAlphaKeys", true)); + + return fields; + } + else + { + return new List() + { + RGBAi("key0"), + RGBAi("key1"), + RGBAi("key2"), + RGBAi("key3"), + RGBAi("key4"), + RGBAi("key5"), + RGBAi("key6"), + RGBAi("key7") + }; + } } public static AssetTypeTemplateField AnimationCurve(string name, UnityVersion unityVersion) => CreateTemplateField(name, "AnimationCurve", AnimationCurve(unityVersion)); public static List AnimationCurve(UnityVersion unityVersion) { - return new List { - Vector(Keyframe("m_Curve", unityVersion)), Int("m_PreInfinity"), Int("m_PostInfinity"), Int("m_RotationOrder") + List fields = new List + { + Vector(Keyframe("m_Curve", unityVersion)), + Int("m_PreInfinity"), + Int("m_PostInfinity") }; + + if (unityVersion.major > 5 || (unityVersion.major == 5 && unityVersion.minor >= 3)) + { + fields.Add(Int("m_RotationOrder")); + } + + return fields; } - //only supports 2019 right now public static AssetTypeTemplateField GUIStyle(string name, UnityVersion unityVersion) => CreateTemplateField(name, "GUIStyle", GUIStyle(unityVersion)); public static List GUIStyle(UnityVersion unityVersion) { - return new List { + List fields = new List + { String("m_Name"), - GUIStyleState("m_Normal", unityVersion), GUIStyleState("m_Hover", unityVersion), GUIStyleState("m_Active", unityVersion), GUIStyleState("m_Focused", unityVersion), - GUIStyleState("m_OnNormal", unityVersion), GUIStyleState("m_OnHover", unityVersion), GUIStyleState("m_OnActive", unityVersion), GUIStyleState("m_OnFocused", unityVersion), - RectOffset("m_Border"), RectOffset("m_Margin"), RectOffset("m_Padding"), RectOffset("m_Overflow"), - PPtr("m_Font", "Font", unityVersion), Int("m_FontSize"), Int("m_FontStyle"), - Int("m_Alignment"), Bool("m_WordWrap"), Bool("m_RichText", true), - Int("m_TextClipping"), Int("m_ImagePosition"), Vector2f("m_ContentOffset"), - Float("m_FixedWidth"), Float("m_FixedHeight"), Bool("m_StretchWidth"), Bool("m_StretchHeight", true) + GUIStyleState("m_Normal", unityVersion), + GUIStyleState("m_Hover", unityVersion), + GUIStyleState("m_Active", unityVersion), + GUIStyleState("m_Focused", unityVersion), + GUIStyleState("m_OnNormal", unityVersion), + GUIStyleState("m_OnHover", unityVersion), + GUIStyleState("m_OnActive", unityVersion), + GUIStyleState("m_OnFocused", unityVersion), + RectOffset("m_Border"), }; + + if (unityVersion.major >= 4) + { + fields.Add(RectOffset("m_Margin")); + fields.Add(RectOffset("m_Padding")); + } + else + { + fields.Add(RectOffset("m_Padding")); + fields.Add(RectOffset("m_Margin")); + } + + fields.Add(RectOffset("m_Overflow")); + fields.Add(PPtr("m_Font", "Font", unityVersion)); + + if (unityVersion.major >= 4) + { + fields.Add(Int("m_FontSize")); + fields.Add(Int("m_FontStyle")); + fields.Add(Int("m_Alignment")); + fields.Add(Bool("m_WordWrap")); + fields.Add(Bool("m_RichText", true)); + } + else + { + fields.Add(Int("m_ImagePosition")); + fields.Add(Int("m_Alignment")); + fields.Add(Bool("m_WordWrap", true)); + } + + fields.Add(Int("m_TextClipping")); + + if (unityVersion.major >= 4) + { + fields.Add(Int("m_ImagePosition")); + } + + fields.Add(Vector2f("m_ContentOffset")); + + if (unityVersion.major < 4) + { + fields.Add(Vector2f("m_ClipOffset")); + } + + fields.Add(Float("m_FixedWidth")); + fields.Add(Float("m_FixedHeight")); + + if (unityVersion.major >= 4) + { + fields.Add(Bool("m_StretchWidth")); + } + else + { + fields.Add(Int("m_FontSize")); + fields.Add(Int("m_FontStyle")); + fields.Add(Bool("m_StretchWidth", true)); + } + + fields.Add(Bool("m_StretchHeight", true)); + + return fields; } public static AssetTypeTemplateField Keyframe(string name, UnityVersion unityVersion) => CreateTemplateField(name, "Keyframe", Keyframe(unityVersion)); public static List Keyframe(UnityVersion unityVersion) { + List fields = new List + { + Float("time"), + Float("value"), + Float("inSlope"), + Float("outSlope") + }; + if (unityVersion.major >= 2018) { - return new List { - Float("time"), Float("value"), Float("inSlope"), Float("outSlope"), - Int("weightedMode"), Float("inWeight"), Float("outWeight") - }; + fields.Add(Int("weightedMode")); + fields.Add(Float("inWeight")); + fields.Add(Float("outWeight")); } - return new List { Float("time"), Float("value"), Float("inSlope"), Float("outSlope") }; + + return fields; } public static AssetTypeTemplateField GUIStyleState(string name, UnityVersion unityVersion) => CreateTemplateField(name, "GUIStyleState", GUIStyleState(unityVersion)); public static List GUIStyleState(UnityVersion unityVersion) { - return new List { PPtr("m_Background", "Texture2D", unityVersion), RGBAf("m_TextColor") }; + return new List + { + PPtr("m_Background", "Texture2D", unityVersion), + RGBAf("m_TextColor") + }; + } + + public static AssetTypeTemplateField SphericalHarmonicsL2(string name, UnityVersion unityVersion) => CreateTemplateField(name, "SphericalHarmonicsL2", SphericalHarmonicsL2(unityVersion)); + public static List SphericalHarmonicsL2(UnityVersion unityVersion) + { + List fields = new List(); + + if (unityVersion.major >= 5) + { + fields.Add(Float("sh[ 0]")); + fields.Add(Float("sh[ 1]")); + fields.Add(Float("sh[ 2]")); + fields.Add(Float("sh[ 3]")); + fields.Add(Float("sh[ 4]")); + fields.Add(Float("sh[ 5]")); + fields.Add(Float("sh[ 6]")); + fields.Add(Float("sh[ 7]")); + fields.Add(Float("sh[ 8]")); + fields.Add(Float("sh[ 9]")); + } + else + { + fields.Add(Float("sh[0]")); + fields.Add(Float("sh[1]")); + fields.Add(Float("sh[2]")); + fields.Add(Float("sh[3]")); + fields.Add(Float("sh[4]")); + fields.Add(Float("sh[5]")); + fields.Add(Float("sh[6]")); + fields.Add(Float("sh[7]")); + fields.Add(Float("sh[8]")); + fields.Add(Float("sh[9]")); + } + + fields.Add(Float("sh[10]")); + fields.Add(Float("sh[11]")); + fields.Add(Float("sh[12]")); + fields.Add(Float("sh[13]")); + fields.Add(Float("sh[14]")); + fields.Add(Float("sh[15]")); + fields.Add(Float("sh[16]")); + fields.Add(Float("sh[17]")); + fields.Add(Float("sh[18]")); + fields.Add(Float("sh[19]")); + fields.Add(Float("sh[20]")); + fields.Add(Float("sh[21]")); + fields.Add(Float("sh[22]")); + fields.Add(Float("sh[23]")); + fields.Add(Float("sh[24]")); + fields.Add(Float("sh[25]")); + fields.Add(Float("sh[26]")); + + return fields; } public static AssetTypeTemplateField RGBAf(string name) => CreateTemplateField(name, "ColorRGBA", RGBAf()); public static List RGBAf() { - return new List { Float("r"), Float("g"), Float("b"), Float("a") }; + return new List + { + Float("r"), + Float("g"), + Float("b"), + Float("a") + }; } public static AssetTypeTemplateField RGBAi(string name) => CreateTemplateField(name, "ColorRGBA", RGBAi()); public static List RGBAi() { - return new List { UInt("rgba") }; + return new List + { + UInt("rgba") + }; } public static AssetTypeTemplateField AABB(string name) => CreateTemplateField(name, "AABB", AABB()); public static List AABB() { - return new List { Vector3f("m_Center"), Vector3f("m_Extent") }; + return new List + { + Vector3f("m_Center"), + Vector3f("m_Extent") + }; } public static AssetTypeTemplateField BoundsInt(string name) => CreateTemplateField(name, "BoundsInt", BoundsInt()); public static List BoundsInt() { - return new List { Vector3Int("m_Position"), Vector3Int("m_Size") }; + return new List + { + Vector3Int("m_Position"), + Vector3Int("m_Size") + }; } public static AssetTypeTemplateField BitField(string name) => CreateTemplateField(name, "BitField", BitField()); public static List BitField() { - return new List { UInt("m_Bits") }; + return new List + { + UInt("m_Bits") + }; } public static AssetTypeTemplateField Rectf(string name) => CreateTemplateField(name, "Rectf", Rectf()); public static List Rectf() { - return new List { Float("x"), Float("y"), Float("width"), Float("height") }; + return new List + { + Float("x"), + Float("y"), + Float("width"), + Float("height") + }; } public static AssetTypeTemplateField RectOffset(string name) => CreateTemplateField(name, "RectOffset", RectOffset()); public static List RectOffset() { - return new List { Int("m_Left"), Int("m_Right"), Int("m_Top"), Int("m_Bottom") }; + return new List + { + Int("m_Left"), + Int("m_Right"), + Int("m_Top"), + Int("m_Bottom") + }; } public static AssetTypeTemplateField Vector2Int(string name) => CreateTemplateField(name, "int2_storage", Vector2Int()); public static List Vector2Int() { - return new List { Int("x"), Int("y") }; + return new List + { + Int("x"), + Int("y") + }; } public static AssetTypeTemplateField Vector3Int(string name) => CreateTemplateField(name, "int3_storage", Vector3Int()); public static List Vector3Int() { - return new List { Int("x"), Int("y"), Int("z") }; + return new List + { + Int("x"), + Int("y"), + Int("z") + }; } public static AssetTypeTemplateField Vector2f(string name) => CreateTemplateField(name, "Vector2f", Vector2f()); public static List Vector2f() { - return new List { Float("x"), Float("y") }; + return new List + { + Float("x"), + Float("y") + }; } public static AssetTypeTemplateField Vector3f(string name) => CreateTemplateField(name, "Vector3f", Vector3f()); public static List Vector3f() { - return new List { Float("x"), Float("y"), Float("z") }; + return new List + { + Float("x"), + Float("y"), + Float("z") + }; } public static AssetTypeTemplateField PPtr(string name, string typeName, UnityVersion unityVersion) => CreateTemplateField(name, $"PPtr<{typeName}>", PPtr(unityVersion)); @@ -406,17 +646,49 @@ public static List PPtr(UnityVersion unityVersion) { if (unityVersion.major >= 5) { - return new List { Int("m_FileID"), Long("m_PathID") }; + return new List + { + Int("m_FileID"), + Long("m_PathID") + }; + } + else + { + return new List + { + Int("m_FileID"), + Int("m_PathID") + }; } - - return new List { Int("m_FileID"), Int("m_PathID") }; } - // yes, there is a double string here - public static AssetTypeTemplateField PropertyName(string name) => CreateTemplateField(name, "string", PropertyName()); - public static List PropertyName() + public static AssetTypeTemplateField PropertyName(string name, UnityVersion unityVersion) => CreateTemplateField(name, "string", PropertyName(unityVersion)); + public static List PropertyName(UnityVersion unityVersion) { - return new List { String("id") }; + if (unityVersion.major > 2020 + || (unityVersion.major == 2020 && + (unityVersion.minor > 2 || (unityVersion.minor == 2 && (unityVersion.type != "a" || unityVersion.typeNum >= 16)))) + || (unityVersion.major == 2020 && + (unityVersion.minor > 1 || (unityVersion.minor == 1 && unityVersion.type != "a" && (unityVersion.type != "b" || unityVersion.typeNum >= 15)))) + || (unityVersion.major == 2019 && + (unityVersion.minor > 4 || (unityVersion.minor == 4 && (unityVersion.type != "a" || unityVersion.patch >= 3)))) + || (unityVersion.major == 2018 && + (unityVersion.minor > 4 || (unityVersion.minor == 4 && (unityVersion.type != "a" || unityVersion.patch >= 25)))) + ) + { + // yes, there is a double string here + return new List + { + String("id") + }; + } + else + { + return new List + { + Int("id") + }; + } } #endregion diff --git a/AssetTools.NET/Extra/UnityVersion.cs b/AssetTools.NET/Extra/UnityVersion.cs index c46196b..d01bcda 100644 --- a/AssetTools.NET/Extra/UnityVersion.cs +++ b/AssetTools.NET/Extra/UnityVersion.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace AssetsTools.NET.Extra +namespace AssetsTools.NET.Extra { public class UnityVersion { @@ -16,11 +12,22 @@ public UnityVersion() { } public UnityVersion(string version) { + major = 0; + minor = 0; + patch = 0; + type = ""; + typeNum = 0; + string[] versionSplit = version.Split('.'); - major = int.Parse(versionSplit[0]); - minor = int.Parse(versionSplit[1]); - int verTypeIndex = versionSplit[2].IndexOfAny(new[] { 'f', 'p', 'a', 'b', 'c', 'x' }); + if (versionSplit.Length >= 1) + major = int.Parse(versionSplit[0]); + if (versionSplit.Length >= 2) + minor = int.Parse(versionSplit[1]); + if (versionSplit.Length <= 2) + return; + + int verTypeIndex = versionSplit[2].IndexOfAny(new[] { 'f', 'p', 'a', 'b', 'c', 't', 'x' }); if (verTypeIndex != -1) { type = versionSplit[2][verTypeIndex].ToString(); diff --git a/AssetTools.NET/Standard/AssetTypeClass/AssetTypeTemplateField.cs b/AssetTools.NET/Standard/AssetTypeClass/AssetTypeTemplateField.cs index 19bebf6..9df319e 100644 --- a/AssetTools.NET/Standard/AssetTypeClass/AssetTypeTemplateField.cs +++ b/AssetTools.NET/Standard/AssetTypeClass/AssetTypeTemplateField.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; namespace AssetsTools.NET { @@ -255,108 +256,136 @@ public AssetTypeValueField ReadType(AssetsFileReader reader, AssetTypeValueField } else { - if (type == AssetValueType.String) + ReadPrimitiveType(reader, valueField, type, refMan); + } + + } + return valueField; + } + + /// + /// Deserialize a single primtive field and its children. + /// This method only works for strings, numbers, and ManagedReferencesRegistry. + /// + /// The reader to use. + /// The empty base value field to use. + /// The value type of the template field. + /// The ref type manager to use, if reading a MonoBehaviour using a ref type. + /// The deserialized base field. +#if NETSTANDARD2_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public void ReadPrimitiveType(AssetsFileReader reader, AssetTypeValueField valueField, AssetValueType type, RefTypeManager refMan) + { + if (type == AssetValueType.String) + { + valueField.Children = new List(0); + int length = reader.ReadInt32(); + valueField.Value = new AssetTypeValue(reader.ReadBytes(length), true); + reader.Align(); + } + else if (type == AssetValueType.ManagedReferencesRegistry) + { + ReadManagedReferencesRegistryType(reader, valueField, refMan); + } + else + { + int childCount = valueField.TemplateField.Children.Count; + if (childCount == 0) + { + valueField.Children = new List(0); + switch (type) { - valueField.Children = new List(0); - int length = reader.ReadInt32(); - valueField.Value = new AssetTypeValue(reader.ReadBytes(length), true); - reader.Align(); + case AssetValueType.Int8: + valueField.Value = new AssetTypeValue(reader.ReadSByte()); + break; + case AssetValueType.UInt8: + valueField.Value = new AssetTypeValue(reader.ReadByte()); + break; + case AssetValueType.Bool: + valueField.Value = new AssetTypeValue(reader.ReadBoolean()); + break; + case AssetValueType.Int16: + valueField.Value = new AssetTypeValue(reader.ReadInt16()); + break; + case AssetValueType.UInt16: + valueField.Value = new AssetTypeValue(reader.ReadUInt16()); + break; + case AssetValueType.Int32: + valueField.Value = new AssetTypeValue(reader.ReadInt32()); + break; + case AssetValueType.UInt32: + valueField.Value = new AssetTypeValue(reader.ReadUInt32()); + break; + case AssetValueType.Int64: + valueField.Value = new AssetTypeValue(reader.ReadInt64()); + break; + case AssetValueType.UInt64: + valueField.Value = new AssetTypeValue(reader.ReadUInt64()); + break; + case AssetValueType.Float: + valueField.Value = new AssetTypeValue(reader.ReadSingle()); + break; + case AssetValueType.Double: + valueField.Value = new AssetTypeValue(reader.ReadDouble()); + break; } - else if (type == AssetValueType.ManagedReferencesRegistry) - { - // todo: error handling like in array - if (refMan == null) - throw new Exception("refMan MUST be set to deserialize objects with ref types!"); - valueField.Children = new List(0); - ManagedReferencesRegistry registry = new ManagedReferencesRegistry(); - valueField.Value = new AssetTypeValue(registry); - int registryChildCount = valueField.TemplateField.Children.Count; - if (registryChildCount != 2) - throw new Exception($"Expected ManagedReferencesRegistry to have two children, found {registryChildCount} instead!"); + if (valueField.TemplateField.IsAligned) + reader.Align(); + } + else if (type != AssetValueType.None) + { + throw new Exception("Cannot read value of field with children!"); + } + } + } + + /// + /// Deserialize a ManagedReferencesRegistry field. + /// + /// The reader to use. + /// The empty base value field to use. + /// The ref type manager to use, if reading a MonoBehaviour using a ref type. + /// The deserialized base field. + public void ReadManagedReferencesRegistryType(AssetsFileReader reader, AssetTypeValueField valueField, RefTypeManager refMan) + { + if (refMan == null) + throw new Exception($"{nameof(refMan)} must be non-null to deserialize objects with ref types."); + + valueField.Children = new List(0); + ManagedReferencesRegistry registry = new ManagedReferencesRegistry(); + valueField.Value = new AssetTypeValue(registry); + int registryChildCount = valueField.TemplateField.Children.Count; + if (registryChildCount != 2) + throw new Exception($"Expected ManagedReferencesRegistry to have two children, found {registryChildCount} instead!"); - registry.version = reader.ReadInt32(); - registry.references = new List(); + registry.version = reader.ReadInt32(); + registry.references = new List(); - if (registry.version == 1) - { - while (true) - { - // rid is consecutive starting at 0 - var refdObject = MakeReferencedObject(reader, registry.version, registry.references.Count, refMan); - if (refdObject.type.Equals(AssetTypeReference.TERMINUS)) - { - break; - } - registry.references.Add(refdObject); - } - } - else - { - int childCount = reader.ReadInt32(); - for (int i = 0; i < childCount; i++) - { - // rid is read from data - var refdObject = MakeReferencedObject(reader, registry.version, -1, refMan); - registry.references.Add(refdObject); - } - } - } - else + if (registry.version == 1) + { + while (true) + { + // rid is consecutive starting at 0 + var refdObject = MakeReferencedObject(reader, registry.version, registry.references.Count, refMan); + if (refdObject.type.Equals(AssetTypeReference.TERMINUS)) { - int childCount = valueField.TemplateField.Children.Count; - if (childCount == 0) - { - valueField.Children = new List(0); - switch (valueField.TemplateField.ValueType) - { - case AssetValueType.Int8: - valueField.Value = new AssetTypeValue(reader.ReadSByte()); - break; - case AssetValueType.UInt8: - valueField.Value = new AssetTypeValue(reader.ReadByte()); - break; - case AssetValueType.Bool: - valueField.Value = new AssetTypeValue(reader.ReadBoolean()); - break; - case AssetValueType.Int16: - valueField.Value = new AssetTypeValue(reader.ReadInt16()); - break; - case AssetValueType.UInt16: - valueField.Value = new AssetTypeValue(reader.ReadUInt16()); - break; - case AssetValueType.Int32: - valueField.Value = new AssetTypeValue(reader.ReadInt32()); - break; - case AssetValueType.UInt32: - valueField.Value = new AssetTypeValue(reader.ReadUInt32()); - break; - case AssetValueType.Int64: - valueField.Value = new AssetTypeValue(reader.ReadInt64()); - break; - case AssetValueType.UInt64: - valueField.Value = new AssetTypeValue(reader.ReadUInt64()); - break; - case AssetValueType.Float: - valueField.Value = new AssetTypeValue(reader.ReadSingle()); - break; - case AssetValueType.Double: - valueField.Value = new AssetTypeValue(reader.ReadDouble()); - break; - } - - if (valueField.TemplateField.IsAligned) - reader.Align(); - } - else if (valueField.TemplateField.ValueType != AssetValueType.None) - { - throw new Exception("Cannot read value of field with children!"); - } + break; } + registry.references.Add(refdObject); + } + } + else + { + int childCount = reader.ReadInt32(); + for (int i = 0; i < childCount; i++) + { + // rid is read from data + var refdObject = MakeReferencedObject(reader, registry.version, -1, refMan); + registry.references.Add(refdObject); } - } - return valueField; } public AssetTypeTemplateField this[string name] diff --git a/AssetTools.NET/Standard/AssetTypeClass/AssetTypeValueIterator.cs b/AssetTools.NET/Standard/AssetTypeClass/AssetTypeValueIterator.cs new file mode 100644 index 0000000..cfbdd58 --- /dev/null +++ b/AssetTools.NET/Standard/AssetTypeClass/AssetTypeValueIterator.cs @@ -0,0 +1,299 @@ +using System; +using System.Collections.Generic; + +namespace AssetsTools.NET +{ + public class AssetTypeValueIterator + { + private AssetTypeTemplateField baseTempField; + private AssetsFileReader reader; + private RefTypeManager refMan; + private readonly Stack> tempFieldStack; + + private AssetTypeValueField valueFieldCache; + private readonly long basePosition; + + public AssetTypeTemplateField TempField; + + public AssetTypeValueField ReadValueField() + { + if (valueFieldCache == null) + { + valueFieldCache = new AssetTypeValueField() + { + TemplateField = TempField + }; + + // rewind since we already read the length + if (TempField.IsArray && TempField.ValueType != AssetValueType.ByteArray) + { + reader.Position -= 4; + } + + TempField.ReadType(reader, valueFieldCache, refMan); + + // prevent iterating the children now that we've read it + if (TempField.Children.Count > 0 && TempField.ValueType != AssetValueType.String) + { + IEnumerator topItem = tempFieldStack.Peek(); + do + { + // special case for arrays: we need to align here rather than below + // because we create child iterators for arrays rather than depend + // on the template field. + if (topItem.Current != null + && topItem.Current.IsArray + && topItem.Current.ValueType != AssetValueType.ByteArray + && topItem.Current.IsAligned) + { + reader.Align(); + } + } while (topItem.MoveNext()); + } + } + return valueFieldCache; + } + + public List TempFieldStack + { + get + { + List stack = new List(tempFieldStack.Count); + foreach (IEnumerator stackItem in tempFieldStack) + { + stack.Add(stackItem.Current); + } + + return stack; + } + } + + public int Depth + { + get + { + bool canHaveChildren = TempField.ValueType switch + { + AssetValueType.None => true, + AssetValueType.Bool => false, + AssetValueType.Int8 => false, + AssetValueType.UInt8 => false, + AssetValueType.Int16 => false, + AssetValueType.UInt16 => false, + AssetValueType.Int32 => false, + AssetValueType.UInt32 => false, + AssetValueType.Int64 => false, + AssetValueType.UInt64 => false, + AssetValueType.Float => false, + AssetValueType.Double => false, + AssetValueType.String => false, + AssetValueType.Array => true, + AssetValueType.ByteArray => false, + AssetValueType.ManagedReferencesRegistry => false, + _ => throw new Exception("Invalid value type") + }; + return tempFieldStack.Count - (canHaveChildren ? 1 : 0); + } + } + + public int ReadPosition + { + get + { + return (int)(reader.Position - basePosition); + } + } + + /// + /// Create an AssetTypeValueIterator, which allows walking an asset's field tree without + /// allocating unnecessary values. If is locked behind a lock, you + /// should manually take the lock while using the iterator. The current iterating position + /// is not remembered by this iterator. Instead, the reader's position is relied on. + /// + /// The template base field to use. + /// The reader to use, set the correct position. + /// The ref type manager to use, if reading a MonoBehaviour using a ref type. + public AssetTypeValueIterator(AssetTypeTemplateField templateField, AssetsFileReader reader, RefTypeManager refMan = null) + { + baseTempField = templateField; + this.reader = reader; + this.refMan = refMan; + + basePosition = reader.Position; + + tempFieldStack = new Stack>(); + Reset(); + } + + /// + /// Create an AssetTypeValueIterator, which allows walking an asset's field tree without + /// allocating unnecessary values. If is locked behind a lock, you + /// should manually take the lock while using the iterator. The current iterating position + /// is not remembered by this iterator. Instead, the reader's position is relied on. + /// + /// The template base field to use. + /// The reader to use. + /// The position to start reading from. + /// The ref type manager to use, if reading a MonoBehaviour using a ref type. + public AssetTypeValueIterator(AssetTypeTemplateField templateField, AssetsFileReader reader, long position, RefTypeManager refMan = null) + : this(templateField, ReaderWithSetPos(reader, position), refMan) + { + } + + private static AssetsFileReader ReaderWithSetPos(AssetsFileReader reader, long position) + { + reader.Position = position; + return reader; + } + + public void Reset() + { + tempFieldStack.Clear(); + tempFieldStack.Push(baseTempField.Children.GetEnumerator()); + + TempField = baseTempField; + valueFieldCache = null; + } + + public void Reset(AssetTypeTemplateField templateField, AssetsFileReader reader, RefTypeManager refMan = null) + { + baseTempField = templateField; + this.reader = reader; + this.refMan = refMan; + + tempFieldStack.Clear(); + tempFieldStack.Push(baseTempField.Children.GetEnumerator()); + + TempField = baseTempField; + valueFieldCache = null; + } + + public bool ReadNext() + { + if (tempFieldStack.Count == 0) + { + return false; + } + + // move reader to next field if we didn't read it + if (valueFieldCache == null) + { + if (TempField.IsArray) + { + if (TempField.ValueType == AssetValueType.ByteArray) + { + int byteLen = reader.ReadInt32(); + reader.Position += byteLen; + + if (TempField.IsAligned) + { + reader.Align(); + } + } + } + else + { + if (TempField.ValueType != AssetValueType.None) + { + bool aligned = TempField.IsAligned; + switch (TempField.ValueType) + { + case AssetValueType.Bool: + case AssetValueType.Int8: + case AssetValueType.UInt8: + reader.Position += 1; + break; + case AssetValueType.Int16: + case AssetValueType.UInt16: + reader.Position += 2; + break; + case AssetValueType.Int32: + case AssetValueType.UInt32: + case AssetValueType.Float: + reader.Position += 4; + break; + case AssetValueType.Int64: + case AssetValueType.UInt64: + case AssetValueType.Double: + reader.Position += 8; + break; + case AssetValueType.String: + int stringLen = reader.ReadInt32(); + reader.Position += stringLen; + + if (TempField.Children.Count > 0) + aligned = TempField.Children[0].IsAligned; + else + aligned = true; + + break; + case AssetValueType.ManagedReferencesRegistry: + // this allocates, but I'm skipping writing code to do this the "right" way + AssetTypeValueField ignored = new AssetTypeValueField(); + TempField.ReadManagedReferencesRegistryType(reader, ignored, refMan); + break; + } + + if (aligned) + { + reader.Align(); + } + } + } + } + + IEnumerator topField = tempFieldStack.Peek(); + while (true) + { + // special case for arrays: we need to align here rather than below + // because we create child iterators for arrays rather than depend + // on the template field. + if (topField.Current != null + && (!topField.Current.IsArray || topField.Current.ValueType != AssetValueType.ByteArray) + && topField.Current.IsAligned) + { + reader.Align(); + } + + if (topField.MoveNext()) + { + break; + } + + tempFieldStack.Pop(); + if (tempFieldStack.Count == 0) + { + return false; + } + + topField = tempFieldStack.Peek(); + } + + AssetTypeTemplateField childField = topField.Current; + if (childField.IsArray && childField.ValueType != AssetValueType.ByteArray) + { + int arrChildCount = reader.ReadInt32(); + tempFieldStack.Push(GetArrayEnumerator(childField.Children[1], arrChildCount)); + } + else if (childField.ValueType == AssetValueType.None) + { + if (childField.Children.Count > 0) + { + tempFieldStack.Push(childField.Children.GetEnumerator()); + } + } + + TempField = childField; + valueFieldCache = null; + return true; + } + + private IEnumerator GetArrayEnumerator(AssetTypeTemplateField templateField, int times) + { + for (int i = 0; i < times; i++) + { + yield return templateField; + } + } + } +} diff --git a/AssetTools.NET/Standard/AssetTypeClass/RefTypeManager.cs b/AssetTools.NET/Standard/AssetTypeClass/RefTypeManager.cs index 859246f..30bd12a 100644 --- a/AssetTools.NET/Standard/AssetTypeClass/RefTypeManager.cs +++ b/AssetTools.NET/Standard/AssetTypeClass/RefTypeManager.cs @@ -46,12 +46,7 @@ public void FromTypeTree(AssetsFileMetadata metadata) AssetTypeTemplateField templateField = new AssetTypeTemplateField(); templateField.FromTypeTree(type); - // if ref type has fields with [SerializeReference] it can contain its own registry, - // but it shouldn't be there, as the registry is only available at the root type - if (templateField.Children.Count > 0 && templateField.Children[templateField.Children.Count - 1].ValueType == AssetValueType.ManagedReferencesRegistry) - { - templateField.Children.RemoveAt(templateField.Children.Count - 1); - } + RemoveRedundantRegistry(templateField); typeTreeLookup[type.TypeReference] = templateField; } @@ -112,6 +107,7 @@ public AssetTypeTemplateField GetTemplateField(AssetTypeReference type) templateField = monoTemplateGenerator.GetTemplateField(templateField, type.AsmName, type.Namespace, type.ClassName, unityVersion); if (templateField != null) { + RemoveRedundantRegistry(templateField); monoTemplateLookup[type] = templateField; return templateField; } @@ -119,5 +115,20 @@ public AssetTypeTemplateField GetTemplateField(AssetTypeReference type) return null; } + + private void RemoveRedundantRegistry(AssetTypeTemplateField templateField) + { + // if ref type has fields with [SerializeReference] it can contain its own registry, + // but it shouldn't be there, as the registry is only available at the root type + if (templateField.Children.Count == 0) + return; + + int lastChildIdx = templateField.Children.Count - 1; + AssetTypeTemplateField lastChild = templateField[lastChildIdx]; + if (lastChild.ValueType == AssetValueType.ManagedReferencesRegistry) + { + templateField.Children.RemoveAt(lastChildIdx); + } + } } } diff --git a/AssetTools.NET/Standard/AssetsBundleFileFormat/AssetBundleDirectoryInfo.cs b/AssetTools.NET/Standard/AssetsBundleFileFormat/AssetBundleDirectoryInfo.cs index 88abeea..973605d 100644 --- a/AssetTools.NET/Standard/AssetsBundleFileFormat/AssetBundleDirectoryInfo.cs +++ b/AssetTools.NET/Standard/AssetsBundleFileFormat/AssetBundleDirectoryInfo.cs @@ -16,7 +16,7 @@ public class AssetBundleDirectoryInfo /// 0x02: Entry is deleted. Unknown usage. /// 0x04: Entry is serialized file. Assets files should enable this, and other files like .resS or .resource(s) should disable this. /// - public uint Flags; + public uint Flags; // todo: this should have real flags /// /// Name of this entry. /// @@ -36,6 +36,10 @@ public class AssetBundleDirectoryInfo /// Is the replacer non-null and does the replacer has a preview? /// public bool IsReplacerPreviewable => Replacer != null && Replacer.HasPreview(); + /// + /// Is the file serialized? + /// + public bool IsSerialized => (Flags & 4) != 0; /// /// Sets the bytes used when the AssetBundleFile is written. diff --git a/AssetTools.NET/Standard/AssetsFileFormat/AssetsFile.cs b/AssetTools.NET/Standard/AssetsFileFormat/AssetsFile.cs index fd8742f..4174964 100644 --- a/AssetTools.NET/Standard/AssetsFileFormat/AssetsFile.cs +++ b/AssetTools.NET/Standard/AssetsFileFormat/AssetsFile.cs @@ -291,7 +291,7 @@ public static bool IsAssetsFile(AssetsFileReader reader, long offset, long lengt public List GetAssetsOfType(AssetClassID typeId) => Metadata.GetAssetsOfType(typeId); /// /// Get all assets of a specific type ID and script index. The script index of an asset can be - /// found from or . + /// found from or . /// /// The type ID to search for. /// The script index to search for. @@ -299,7 +299,7 @@ public static bool IsAssetsFile(AssetsFileReader reader, long offset, long lengt public List GetAssetsOfType(int typeId, ushort scriptIndex) => Metadata.GetAssetsOfType(typeId, scriptIndex); /// /// Get all assets of a specific type ID and script index. The script index of an asset can be - /// found from or . + /// found from or . /// /// The type ID to search for. /// The script index to search for. diff --git a/AssetTools.NET/Standard/AssetsFileFormat/AssetsFileMetadata.cs b/AssetTools.NET/Standard/AssetsFileFormat/AssetsFileMetadata.cs index 0636a49..d6d6688 100644 --- a/AssetTools.NET/Standard/AssetsFileFormat/AssetsFileMetadata.cs +++ b/AssetTools.NET/Standard/AssetsFileFormat/AssetsFileMetadata.cs @@ -285,14 +285,14 @@ public List GetAssetsOfType(int typeId) /// found from or . /// /// The type ID to search for. - /// The script index to search for. + /// The script index to search for, or for any. /// A list of infos for that type ID and script index. public List GetAssetsOfType(int typeId, ushort scriptIndex) { List infos = new List(); foreach (AssetFileInfo info in AssetInfos) { - if (scriptIndex != 0xffff) + if (scriptIndex != ushort.MaxValue) { if (info.TypeId < 0) { @@ -304,7 +304,14 @@ public List GetAssetsOfType(int typeId, ushort scriptIndex) } else if (info.TypeId == (int)AssetClassID.MonoBehaviour) { - if (FindTypeTreeTypeByID(info.TypeId, info.ScriptTypeIndex).ScriptTypeIndex != scriptIndex) + // we don't have access to the metadata or format version + // in this function. let's double check this is ver >= 16. + if (info.TypeIdOrIndex == info.TypeId) + continue; + + // we've confirmed at this point we're not ver < 16. if we + // were, we should have had TypeId < 0 + if (info.GetScriptIndex(this, 16) != scriptIndex) continue; if (typeId != (int)AssetClassID.MonoBehaviour) diff --git a/AssetTools.NET/Standard/AssetsFileFormat/TypeTreeNode.cs b/AssetTools.NET/Standard/AssetsFileFormat/TypeTreeNode.cs index 82218c5..8aebbc6 100644 --- a/AssetTools.NET/Standard/AssetsFileFormat/TypeTreeNode.cs +++ b/AssetTools.NET/Standard/AssetsFileFormat/TypeTreeNode.cs @@ -1,4 +1,4 @@ -using System.IO; +using System; using System.Text; namespace AssetsTools.NET @@ -86,6 +86,8 @@ public void Write(AssetsFileWriter writer, uint version) } } + // todo: these two GetXXXString methods should be using caching + /// /// Get the type name from the string table (from ). /// @@ -135,16 +137,8 @@ private string ReadStringTableString(byte[] stringTable, byte[] commonStringTabl stringTable = commonStringTable; } - using MemoryStream data = new MemoryStream(); - int pos = (int)offset; - byte b; - while ((b = stringTable[pos]) != 0x00) - { - data.WriteByte(b); - pos++; - } - - return Encoding.UTF8.GetString(data.ToArray()); + var endIdx = Array.IndexOf(stringTable, (byte)0, (int)offset); + return Encoding.UTF8.GetString(stringTable, (int)offset, (int)(endIdx - offset)); } } } diff --git a/AssetTools.NET/Standard/ConcurrentDictionary.cs b/AssetTools.NET/Standard/ConcurrentDictionary.cs new file mode 100644 index 0000000..5fc7dae --- /dev/null +++ b/AssetTools.NET/Standard/ConcurrentDictionary.cs @@ -0,0 +1,223 @@ +using System.Collections; +using System.Collections.Generic; + +namespace AssetsTools.NET +{ + internal sealed class ConcurrentDictionary : IDictionary + { +#if NET35 + private readonly Dictionary _dict = new Dictionary(); + private readonly object _lock = new object(); +#else + private readonly System.Collections.Concurrent.ConcurrentDictionary _dict = new System.Collections.Concurrent.ConcurrentDictionary(); +#endif + + public ICollection Keys + { + get + { +#if NET35 + lock (_lock) + { + return new List(_dict.Keys); + } +#else + return _dict.Keys; +#endif + } + } + + public ICollection Values + { + get + { +#if NET35 + lock (_lock) + { + return new List(_dict.Values); + } +#else + return _dict.Values; +#endif + } + } + + public int Count + { + get + { +#if NET35 + lock (_lock) + { + return _dict.Count; + } +#else + return _dict.Count; +#endif + } + } + + public bool IsReadOnly => false; + + public bool ContainsKey(TKey key) + { +#if NET35 + lock (_lock) + { + return _dict.ContainsKey(key); + } +#else + return _dict.ContainsKey(key); +#endif + } + + public IEnumerator> GetEnumerator() + { +#if NET35 + List> snapshot; + lock (_lock) + { + snapshot = new List>(_dict); + } + return snapshot.GetEnumerator(); +#else + return _dict.GetEnumerator(); +#endif + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public void Add(TKey key, TValue value) + { +#if NET35 + lock (_lock) + { + _dict.Add(key, value); + } +#else + ((IDictionary)_dict).Add(key, value); +#endif + } + + public bool Remove(TKey key) + { +#if NET35 + lock (_lock) + { + return _dict.Remove(key); + } +#else + return _dict.TryRemove(key, out _); +#endif + } + + public bool TryRemove(TKey key, out TValue value) + { +#if NET35 + lock (_lock) + { + if (_dict.TryGetValue(key, out value)) + { + _dict.Remove(key); + return true; + } + value = default; + return false; + } +#else + return _dict.TryRemove(key, out value); +#endif + } + + public bool TryGetValue(TKey key, out TValue value) + { +#if NET35 + lock (_lock) + { + return _dict.TryGetValue(key, out value); + } +#else + return _dict.TryGetValue(key, out value); +#endif + } + + public void Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } + + public void Clear() + { +#if NET35 + lock (_lock) + { + _dict.Clear(); + } +#else + _dict.Clear(); +#endif + } + + public bool Contains(KeyValuePair item) + { +#if NET35 + lock (_lock) + { + return ((IDictionary)_dict).Contains(item); + } +#else + return ((IDictionary)_dict).Contains(item); +#endif + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { +#if NET35 + lock (_lock) + { + ((IDictionary)_dict).CopyTo(array, arrayIndex); + } +#else + ((IDictionary)_dict).CopyTo(array, arrayIndex); +#endif + } + + public bool Remove(KeyValuePair item) + { +#if NET35 + lock (_lock) + { + return ((IDictionary)_dict).Remove(item); + } +#else + return ((IDictionary)_dict).Remove(item); +#endif + } + + public TValue this[TKey key] + { + get + { +#if NET35 + lock (_lock) + { + return _dict[key]; + } +#else + return _dict[key]; +#endif + } + set + { +#if NET35 + lock (_lock) + { + _dict[key] = value; + } +#else + _dict[key] = value; +#endif + } + } + } +} diff --git a/AssetTools.NET/Standard/IO/LZ4BlockStream.cs b/AssetTools.NET/Standard/IO/LZ4BlockStream.cs index fd52b7e..410a346 100644 --- a/AssetTools.NET/Standard/IO/LZ4BlockStream.cs +++ b/AssetTools.NET/Standard/IO/LZ4BlockStream.cs @@ -131,7 +131,7 @@ public override int Read(byte[] buffer, int offset, int count) BaseStream.Position = BaseOffset + blockPoses[blockIndex]; MemoryStream compressedStream = new MemoryStream(); - BaseStream.CopyToCompat(compressedStream, blockInfos[blockIndex].CompressedSize); + BaseStream.CopyToCompat(compressedStream, blockInfos[blockIndex].CompressedSize, (int)blockSize); compressedStream.Position = 0; byte compressionType = blockInfos[blockIndex].GetCompressionType(); diff --git a/AssetTools.NET/Standard/IO/SegmentStream.cs b/AssetTools.NET/Standard/IO/SegmentStream.cs index 24c5c33..6712521 100644 --- a/AssetTools.NET/Standard/IO/SegmentStream.cs +++ b/AssetTools.NET/Standard/IO/SegmentStream.cs @@ -54,32 +54,26 @@ public override void Flush() public override int Read(byte[] buffer, int offset, int count) { BaseStream.Position = BaseOffset + Position; - count = BaseStream.Read(buffer, offset, (int)Math.Min(count, Length - Position)); + + // fixed count for performance since .Length is expensive on FileStream base + var countFixed = length >= 0 + ? (int)Math.Min(count, length - Position) + : count; // read as much as possible. Read() will handle if we try to read too much. + + count = BaseStream.Read(buffer, offset, countFixed); Position += count; return count; } public override long Seek(long offset, SeekOrigin origin) { - long newPosition; - switch (origin) + var newPosition = origin switch { - case SeekOrigin.Begin: - newPosition = offset; - break; - - case SeekOrigin.Current: - newPosition = Position + offset; - break; - - case SeekOrigin.End: - newPosition = Position + Length + offset; - break; - - default: - throw new ArgumentException(); - } - + SeekOrigin.Begin => offset, + SeekOrigin.Current => Position + offset, + SeekOrigin.End => Position + Length + offset, + _ => throw new ArgumentException(), + }; if (newPosition < 0 || newPosition > Length) throw new ArgumentOutOfRangeException(nameof(offset)); diff --git a/AssetsTools.NET.Cpp2IL/AssetsTools.NET.Cpp2IL.csproj b/AssetsTools.NET.Cpp2IL/AssetsTools.NET.Cpp2IL.csproj index dd2434c..00e5769 100644 --- a/AssetsTools.NET.Cpp2IL/AssetsTools.NET.Cpp2IL.csproj +++ b/AssetsTools.NET.Cpp2IL/AssetsTools.NET.Cpp2IL.csproj @@ -3,6 +3,7 @@ netstandard2.0 9 + Disable diff --git a/AssetsTools.NET.Cpp2IL/AssetsTools.NET.Cpp2IL.nuspec b/AssetsTools.NET.Cpp2IL/AssetsTools.NET.Cpp2IL.nuspec index 02cb765..23621d8 100644 --- a/AssetsTools.NET.Cpp2IL/AssetsTools.NET.Cpp2IL.nuspec +++ b/AssetsTools.NET.Cpp2IL/AssetsTools.NET.Cpp2IL.nuspec @@ -2,7 +2,7 @@ AssetsTools.NET.Cpp2IL - 1.0.0 + 3.0.2 nesrak1 nesrak1 false @@ -11,7 +11,7 @@ icon.png Cpp2IL support for AssetsTools.NET Adds MonoBehaviour deserialization for AssetsTools.NET using Cpp2IL. - v1.0.0 - upgraded at. + v3.0.2 - updates with at https://github.com/nesrak1/AssetsTools.NET diff --git a/AssetsTools.NET.Cpp2IL/Cpp2IlTempGenerator.cs b/AssetsTools.NET.Cpp2IL/Cpp2IlTempGenerator.cs index f6a14f4..bc73ce0 100644 --- a/AssetsTools.NET.Cpp2IL/Cpp2IlTempGenerator.cs +++ b/AssetsTools.NET.Cpp2IL/Cpp2IlTempGenerator.cs @@ -3,6 +3,7 @@ using LibCpp2IL.Metadata; using LibCpp2IL.Reflection; using System; +using System.IO; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -14,16 +15,23 @@ namespace AssetsTools.NET.Cpp2IL { public class Cpp2IlTempGenerator : IMonoBehaviourTemplateGenerator { - private readonly string _globalMetadataPath; - private readonly string _assemblyPath; + private readonly byte[] _globalMetadataBytes; + private readonly byte[] _assemblyBytes; private ATUnityVersion _unityVersion; private bool _initialized; private bool _anyFieldIsManagedReference; public Cpp2IlTempGenerator(string globalMetadataPath, string assemblyPath) { - _globalMetadataPath = globalMetadataPath; - _assemblyPath = assemblyPath; + _globalMetadataBytes = File.ReadAllBytes(globalMetadataPath); + _assemblyBytes = File.ReadAllBytes(assemblyPath); + ResetCpp2IL(); + } + + public Cpp2IlTempGenerator(byte[] globalMetadataBytes, byte[] assemblyBytes) + { + _globalMetadataBytes = globalMetadataBytes; + _assemblyBytes = assemblyBytes; ResetCpp2IL(); } @@ -63,7 +71,7 @@ public void SetUnityVersion(int major, int minor, int patch) public void InitializeCpp2IL() { ARUnityVersion arUnityVersion = ARUnityVersion.Parse(_unityVersion.ToString()); - if (!LibCpp2IlMain.LoadFromFile(_assemblyPath, _globalMetadataPath, arUnityVersion)) + if (!LibCpp2IlMain.Initialize(_assemblyBytes, _globalMetadataBytes, arUnityVersion)) { throw new Exception("Cpp2Il initialization failed"); } @@ -502,7 +510,8 @@ private List SpecialUnity(TypeDefWithSelfRef type, int a "GUIStyle" => CommonMonoTemplateHelper.GUIStyle(_unityVersion), "Vector2Int" => CommonMonoTemplateHelper.Vector2Int(), "Vector3Int" => CommonMonoTemplateHelper.Vector3Int(), - "PropertyName" => CommonMonoTemplateHelper.PropertyName(), + "PropertyName" => CommonMonoTemplateHelper.PropertyName(_unityVersion), + "SphericalHarmonicsL2" => CommonMonoTemplateHelper.SphericalHarmonicsL2(_unityVersion), _ => Serialized(type, availableDepth) }; } diff --git a/AssetsTools.NET.MonoCecil/AssetsTools.NET.MonoCecil.csproj b/AssetsTools.NET.MonoCecil/AssetsTools.NET.MonoCecil.csproj index 47cc291..a47971f 100644 --- a/AssetsTools.NET.MonoCecil/AssetsTools.NET.MonoCecil.csproj +++ b/AssetsTools.NET.MonoCecil/AssetsTools.NET.MonoCecil.csproj @@ -3,6 +3,7 @@ netstandard2.0;net40 8 + Disable diff --git a/AssetsTools.NET.MonoCecil/AssetsTools.NET.MonoCecil.nuspec b/AssetsTools.NET.MonoCecil/AssetsTools.NET.MonoCecil.nuspec index 39f5427..c3d34f7 100644 --- a/AssetsTools.NET.MonoCecil/AssetsTools.NET.MonoCecil.nuspec +++ b/AssetsTools.NET.MonoCecil/AssetsTools.NET.MonoCecil.nuspec @@ -2,7 +2,7 @@ AssetsTools.NET.MonoCecil - 1.0.0 + 3.0.2 nesrak1 nesrak1 false @@ -11,14 +11,10 @@ icon.png Mono.Cecil support for AssetsTools.NET Adds MonoBehaviour deserialization for AssetsTools.NET using Mono.Cecil. - v1.0.0 - upgraded at. + v3.0.2 - updates with at, fix for the type name of string lists https://github.com/nesrak1/AssetsTools.NET - - - - @@ -32,8 +28,6 @@ - - diff --git a/AssetsTools.NET.MonoCecil/MonoCecilTempGenerator.cs b/AssetsTools.NET.MonoCecil/MonoCecilTempGenerator.cs index 47684ca..97ee6a7 100644 --- a/AssetsTools.NET.MonoCecil/MonoCecilTempGenerator.cs +++ b/AssetsTools.NET.MonoCecil/MonoCecilTempGenerator.cs @@ -9,7 +9,6 @@ namespace AssetsTools.NET.Extra public class MonoCecilTempGenerator : IMonoBehaviourTemplateGenerator { private UnityVersion unityVersion; - private bool anyFieldIsManagedReference; public string managedPath; public Dictionary loadedAssemblies = new Dictionary(); @@ -63,10 +62,18 @@ public List Read(string assemblyPath, string nameSpace, public List Read(AssemblyDefinition assembly, string nameSpace, string typeName, UnityVersion unityVersion) { this.unityVersion = unityVersion; - anyFieldIsManagedReference = false; + bool usingManagedReference = false; List children = new List(); - RecursiveTypeLoad(assembly.MainModule, nameSpace, typeName, children, CommonMonoTemplateHelper.GetSerializationLimit(unityVersion)); + RecursiveTypeLoad( + assembly.MainModule, nameSpace, typeName, children, + CommonMonoTemplateHelper.GetSerializationLimit(unityVersion), ref usingManagedReference); + + if (usingManagedReference) + { + children.Add(CommonMonoTemplateHelper.ManagedReferencesRegistry("references", unityVersion)); + } + return children; } @@ -100,7 +107,9 @@ private AssemblyDefinition GetAssemblyWithDependencies(string path) return asmDef; } - private void RecursiveTypeLoad(ModuleDefinition module, string nameSpace, string typeName, List attf, int availableDepth) + private void RecursiveTypeLoad( + ModuleDefinition module, string nameSpace, string typeName, List attf, + int availableDepth, ref bool usingManagedReference) { // TypeReference needed for TypeForwardedTo in UnityEngine (and others) TypeReference typeRef; @@ -125,10 +134,12 @@ private void RecursiveTypeLoad(ModuleDefinition module, string nameSpace, string type = typeRef.Resolve(); } - RecursiveTypeLoad(type, attf, availableDepth, true); + RecursiveTypeLoad(type, attf, availableDepth, true, ref usingManagedReference); } - private void RecursiveTypeLoad(TypeDefWithSelfRef type, List attf, int availableDepth, bool isRecursiveCall = false) + private void RecursiveTypeLoad( + TypeDefWithSelfRef type, List attf, int availableDepth, + bool isRecursiveCall, ref bool usingManagedReference) { if (!isRecursiveCall) { @@ -143,13 +154,13 @@ private void RecursiveTypeLoad(TypeDefWithSelfRef type, List ReadTypes(TypeDefWithSelfRef type, int availableDepth) + private List ReadTypes(TypeDefWithSelfRef type, int availableDepth, ref bool usingManagedReference) { List acceptableFields = GetAcceptableFields(type, availableDepth); List localChildren = new List(); @@ -202,7 +213,7 @@ private List ReadTypes(TypeDefWithSelfRef type, int avai } else if (isManagedReference = fieldDef.CustomAttributes.Any(a => a.AttributeType.Name == "SerializeReference")) { - anyFieldIsManagedReference = true; + usingManagedReference = true; field.Type = "managedReference"; } else @@ -220,7 +231,7 @@ private List ReadTypes(TypeDefWithSelfRef type, int avai } else if (CommonMonoTemplateHelper.IsSpecialUnityType(fieldTypeDef.typeDef.FullName)) { - field.Children = SpecialUnity(fieldTypeDef, availableDepth); + field.Children = SpecialUnity(fieldTypeDef, availableDepth, ref usingManagedReference); } else if (derivesFromUEObject) { @@ -232,7 +243,7 @@ private List ReadTypes(TypeDefWithSelfRef type, int avai } else if (fieldTypeDef.typeDef.IsSerializable) { - field.Children = Serialized(fieldTypeDef, availableDepth); + field.Children = Serialized(fieldTypeDef, availableDepth, ref usingManagedReference); } field.ValueType = AssetTypeValueField.GetValueTypeByTypeName(field.Type); @@ -253,11 +264,6 @@ private List ReadTypes(TypeDefWithSelfRef type, int avai localChildren.Add(field); } - if (anyFieldIsManagedReference && DerivesFromUEObject(type)) - { - localChildren.Add(CommonMonoTemplateHelper.ManagedReferencesRegistry("references", unityVersion)); - } - return localChildren; } @@ -395,14 +401,16 @@ private bool DerivesFromUEObject(TypeDefWithSelfRef typeDef) return false; } - private List Serialized(TypeDefWithSelfRef type, int availableDepth) + private List Serialized( + TypeDefWithSelfRef type, int availableDepth, ref bool usingManagedReference) { List types = new List(); - RecursiveTypeLoad(type, types, availableDepth); + RecursiveTypeLoad(type, types, availableDepth, false, ref usingManagedReference); return types; } - private List SpecialUnity(TypeDefWithSelfRef type, int availableDepth) + private List SpecialUnity( + TypeDefWithSelfRef type, int availableDepth, ref bool usingManagedReference) { return type.typeDef.Name switch { @@ -417,8 +425,9 @@ private List SpecialUnity(TypeDefWithSelfRef type, int a "GUIStyle" => CommonMonoTemplateHelper.GUIStyle(unityVersion), "Vector2Int" => CommonMonoTemplateHelper.Vector2Int(), "Vector3Int" => CommonMonoTemplateHelper.Vector3Int(), - "PropertyName" => CommonMonoTemplateHelper.PropertyName(), - _ => Serialized(type, availableDepth) + "PropertyName" => CommonMonoTemplateHelper.PropertyName(unityVersion), + "SphericalHarmonicsL2" => CommonMonoTemplateHelper.SphericalHarmonicsL2(unityVersion), + _ => Serialized(type, availableDepth, ref usingManagedReference) }; } } diff --git a/AssetsTools.NET.Texture/AssetsTools.NET.Texture.csproj b/AssetsTools.NET.Texture/AssetsTools.NET.Texture.csproj index 7aa415f..522b4f2 100644 --- a/AssetsTools.NET.Texture/AssetsTools.NET.Texture.csproj +++ b/AssetsTools.NET.Texture/AssetsTools.NET.Texture.csproj @@ -2,8 +2,9 @@ netstandard2.0;net6.0;net7.0;net8.0 - latest - true + latest + true + Disable diff --git a/AssetsTools.NET.Texture/AssetsTools.NET.Texture.nuspec b/AssetsTools.NET.Texture/AssetsTools.NET.Texture.nuspec index 84b4d33..8228e43 100644 --- a/AssetsTools.NET.Texture/AssetsTools.NET.Texture.nuspec +++ b/AssetsTools.NET.Texture/AssetsTools.NET.Texture.nuspec @@ -2,7 +2,7 @@ AssetsTools.NET.Texture - 1.0.0 + 3.0.2 nesrak1 nesrak1 false @@ -11,7 +11,7 @@ icon.png Texture support for AssetsTools.NET Adds Texture2D decoding for AssetsTools.NET using TextureDecoder. - v1.0.0 - upgraded at. + v3.0.2 - exposed more methods for working with textures https://github.com/nesrak1/AssetsTools.NET