├── .gitignore
├── AssetDataUtil.cs
├── AssetStudio
├── BigArrayPool.cs
├── Math
│ ├── Color.cs
│ ├── Half.cs
│ ├── HalfHelper.cs
│ ├── Matrix4x4.cs
│ ├── Quaternion.cs
│ ├── Vector2.cs
│ ├── Vector3.cs
│ └── Vector4.cs
└── Texture2DDecoder
│ ├── T2DDll.cs
│ ├── TextureDecoder.PInvoke.cs
│ └── TextureDecoder.cs
├── AssetStudioExporter.csproj
├── AssetStudioExporter.sln
├── AssetTypeManager.cs
├── AssetTypes
├── AssetBundle.cs
├── AudioClip.cs
├── Component.cs
├── Feature
│ ├── IAssetTypeExporter.cs
│ ├── IAssetTypeReader.cs
│ └── INamedObject.cs
├── Font.cs
├── GameObject.cs
├── IAssetType.cs
├── MonoBehaviour.cs
├── MonoBehaviourCollection.cs
├── MonoScript.cs
├── Object.cs
├── PPtr.cs
├── ResourceManager.cs
├── Sprite.cs
├── SpriteAtlas.cs
├── TextAsset.cs
├── Texture2D.cs
└── ValueObject
│ ├── AABB.cs
│ ├── MeshHelper.cs
│ ├── MeshTypes.cs
│ ├── Rectf.cs
│ └── SpriteTypes.cs
├── Export
├── AudioClipConverter.cs
├── SpriteHelper.cs
└── Texture2DConverter.cs
├── ExporterSetting.cs
├── Formats.cs
├── Internal
└── VersionCache.cs
├── Native
├── DllLoader.cs
├── DllLoaderNative.cs
└── FMOD
│ ├── fmod.cs
│ ├── fmod_dsp.cs
│ └── fmod_errors.cs
├── README.md
├── TextureDecoderType.cs
├── Util
├── AssetTypeValueFieldExtensions.cs
└── UnityVersionExtensions.cs
└── lib
├── x64
├── Texture2DDecoderNative.dll
├── fmod.dll
├── libfmod.dylib
└── libfmod.so
└── x86
├── Texture2DDecoderNative.dll
├── fmod.dll
└── libfmod.so
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015/2017 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # Visual Studio 2017 auto generated files
33 | Generated\ Files/
34 |
35 | # MSTest test Results
36 | [Tt]est[Rr]esult*/
37 | [Bb]uild[Ll]og.*
38 |
39 | # NUNIT
40 | *.VisualState.xml
41 | TestResult.xml
42 |
43 | # Build Results of an ATL Project
44 | [Dd]ebugPS/
45 | [Rr]eleasePS/
46 | dlldata.c
47 |
48 | # Benchmark Results
49 | BenchmarkDotNet.Artifacts/
50 |
51 | # .NET Core
52 | project.lock.json
53 | project.fragment.lock.json
54 | artifacts/
55 | **/Properties/launchSettings.json
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_i.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.pch
68 | *.pdb
69 | *.pgc
70 | *.pgd
71 | *.rsp
72 | *.sbr
73 | *.tlb
74 | *.tli
75 | *.tlh
76 | *.tmp
77 | *.tmp_proj
78 | *.log
79 | *.vspscc
80 | *.vssscc
81 | .builds
82 | *.pidb
83 | *.svclog
84 | *.scc
85 |
86 | # Chutzpah Test files
87 | _Chutzpah*
88 |
89 | # Visual C++ cache files
90 | ipch/
91 | *.aps
92 | *.ncb
93 | *.opendb
94 | *.opensdf
95 | *.sdf
96 | *.cachefile
97 | *.VC.db
98 | *.VC.VC.opendb
99 |
100 | # Visual Studio profiler
101 | *.psess
102 | *.vsp
103 | *.vspx
104 | *.sap
105 |
106 | # Visual Studio Trace Files
107 | *.e2e
108 |
109 | # TFS 2012 Local Workspace
110 | $tf/
111 |
112 | # Guidance Automation Toolkit
113 | *.gpState
114 |
115 | # ReSharper is a .NET coding add-in
116 | _ReSharper*/
117 | *.[Rr]e[Ss]harper
118 | *.DotSettings.user
119 |
120 | # JustCode is a .NET coding add-in
121 | .JustCode
122 |
123 | # TeamCity is a build add-in
124 | _TeamCity*
125 |
126 | # DotCover is a Code Coverage Tool
127 | *.dotCover
128 |
129 | # AxoCover is a Code Coverage Tool
130 | .axoCover/*
131 | !.axoCover/settings.json
132 |
133 | # Visual Studio code coverage results
134 | *.coverage
135 | *.coveragexml
136 |
137 | # NCrunch
138 | _NCrunch_*
139 | .*crunch*.local.xml
140 | nCrunchTemp_*
141 |
142 | # MightyMoose
143 | *.mm.*
144 | AutoTest.Net/
145 |
146 | # Web workbench (sass)
147 | .sass-cache/
148 |
149 | # Installshield output folder
150 | [Ee]xpress/
151 |
152 | # DocProject is a documentation generator add-in
153 | DocProject/buildhelp/
154 | DocProject/Help/*.HxT
155 | DocProject/Help/*.HxC
156 | DocProject/Help/*.hhc
157 | DocProject/Help/*.hhk
158 | DocProject/Help/*.hhp
159 | DocProject/Help/Html2
160 | DocProject/Help/html
161 |
162 | # Click-Once directory
163 | publish/
164 |
165 | # Publish Web Output
166 | *.[Pp]ublish.xml
167 | *.azurePubxml
168 | # Note: Comment the next line if you want to checkin your web deploy settings,
169 | # but database connection strings (with potential passwords) will be unencrypted
170 | *.pubxml
171 | *.publishproj
172 |
173 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
174 | # checkin your Azure Web App publish settings, but sensitive information contained
175 | # in these scripts will be unencrypted
176 | PublishScripts/
177 |
178 | # NuGet Packages
179 | *.nupkg
180 | # The packages folder can be ignored because of Package Restore
181 | **/[Pp]ackages/*
182 | # except build/, which is used as an MSBuild target.
183 | !**/[Pp]ackages/build/
184 | # Uncomment if necessary however generally it will be regenerated when needed
185 | #!**/[Pp]ackages/repositories.config
186 | # NuGet v3's project.json files produces more ignorable files
187 | *.nuget.props
188 | *.nuget.targets
189 |
190 | # Microsoft Azure Build Output
191 | csx/
192 | *.build.csdef
193 |
194 | # Microsoft Azure Emulator
195 | ecf/
196 | rcf/
197 |
198 | # Windows Store app package directories and files
199 | AppPackages/
200 | BundleArtifacts/
201 | Package.StoreAssociation.xml
202 | _pkginfo.txt
203 | *.appx
204 |
205 | # Visual Studio cache files
206 | # files ending in .cache can be ignored
207 | *.[Cc]ache
208 | # but keep track of directories ending in .cache
209 | !*.[Cc]ache/
210 |
211 | # Others
212 | ClientBin/
213 | ~$*
214 | *~
215 | *.dbmdl
216 | *.dbproj.schemaview
217 | *.jfm
218 | *.pfx
219 | *.publishsettings
220 | orleans.codegen.cs
221 |
222 | # Including strong name files can present a security risk
223 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
224 | #*.snk
225 |
226 | # Since there are multiple workflows, uncomment next line to ignore bower_components
227 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
228 | #bower_components/
229 |
230 | # RIA/Silverlight projects
231 | Generated_Code/
232 |
233 | # Backup & report files from converting an old project file
234 | # to a newer Visual Studio version. Backup files are not needed,
235 | # because we have git ;-)
236 | _UpgradeReport_Files/
237 | Backup*/
238 | UpgradeLog*.XML
239 | UpgradeLog*.htm
240 | ServiceFabricBackup/
241 |
242 | # SQL Server files
243 | *.mdf
244 | *.ldf
245 | *.ndf
246 |
247 | # Business Intelligence projects
248 | *.rdl.data
249 | *.bim.layout
250 | *.bim_*.settings
251 | *.rptproj.rsuser
252 |
253 | # Microsoft Fakes
254 | FakesAssemblies/
255 |
256 | # GhostDoc plugin setting file
257 | *.GhostDoc.xml
258 |
259 | # Node.js Tools for Visual Studio
260 | .ntvs_analysis.dat
261 | node_modules/
262 |
263 | # Visual Studio 6 build log
264 | *.plg
265 |
266 | # Visual Studio 6 workspace options file
267 | *.opt
268 |
269 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
270 | *.vbw
271 |
272 | # Visual Studio LightSwitch build output
273 | **/*.HTMLClient/GeneratedArtifacts
274 | **/*.DesktopClient/GeneratedArtifacts
275 | **/*.DesktopClient/ModelManifest.xml
276 | **/*.Server/GeneratedArtifacts
277 | **/*.Server/ModelManifest.xml
278 | _Pvt_Extensions
279 |
280 | # Paket dependency manager
281 | .paket/paket.exe
282 | paket-files/
283 |
284 | # FAKE - F# Make
285 | .fake/
286 |
287 | # JetBrains Rider
288 | .idea/
289 | *.sln.iml
290 |
291 | # CodeRush
292 | .cr/
293 |
294 | # Python Tools for Visual Studio (PTVS)
295 | __pycache__/
296 | *.pyc
297 |
298 | # Cake - Uncomment if you are using it
299 | # tools/**
300 | # !tools/packages.config
301 |
302 | # Tabs Studio
303 | *.tss
304 |
305 | # Telerik's JustMock configuration file
306 | *.jmconfig
307 |
308 | # BizTalk build output
309 | *.btp.cs
310 | *.btm.cs
311 | *.odx.cs
312 | *.xsd.cs
313 |
314 | # OpenCover UI analysis results
315 | OpenCover/
316 |
317 | # Azure Stream Analytics local run output
318 | ASALocalRun/
319 |
320 | # MSBuild Binary and Structured Log
321 | *.binlog
322 |
323 | # NVidia Nsight GPU debugger configuration file
324 | *.nvuser
325 |
326 | # Zip releases
327 | *.zip
328 |
329 | !lib/x86
330 | !lib/x64
--------------------------------------------------------------------------------
/AssetDataUtil.cs:
--------------------------------------------------------------------------------
1 | using AssetsTools.NET;
2 | using AssetsTools.NET.Extra;
3 | using AssetStudio;
4 | using AssetStudioExporter.AssetTypes;
5 | using AssetStudioExporter.Internal;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace AssetStudio;
13 |
14 | public static class AssetDataUtil
15 | {
16 | ///
17 | /// 根据资源路径、大小和偏移量读取AssetBundle中的数据
18 | ///
19 | /// AssetsFileInstance
20 | /// 资源路径
21 | /// 大小
22 | /// 偏移量
23 | /// 资源的原始二进制数据
24 | /// 找不到对应的资源
25 | public static byte[] GetAssetData(this AssetsFileInstance inst, string path, uint size, long offset = 0)
26 | {
27 | byte[] data = Array.Empty();
28 | if (path != null && inst.parentBundle != null)
29 | {
30 | string text = path;
31 | if (path.StartsWith("archive:/"))
32 | {
33 | text = text[9..];
34 | }
35 | text = Path.GetFileName(text);
36 | AssetBundleFile file = inst.parentBundle.file;
37 | AssetsFileReader dataReader = file.DataReader;
38 | var directoryInfos = file.BlockAndDirInfo.DirectoryInfos;
39 | bool foundFile = false;
40 | foreach (AssetBundleDirectoryInfo assetBundleDirectoryInfo in directoryInfos)
41 | {
42 | if (assetBundleDirectoryInfo.Name == text)
43 | {
44 | dataReader.Position = assetBundleDirectoryInfo.Offset + offset;
45 | data = dataReader.ReadBytes((int)size);
46 | foundFile = true;
47 | break;
48 | }
49 | }
50 | if (!foundFile)
51 | {
52 | throw new FileNotFoundException("resS was detected but no file was found in bundle");
53 | }
54 | }
55 | return data;
56 | }
57 |
58 | public static UnityVersion GetVersion(this AssetsFileInstance inst)
59 | {
60 | //return VersionCache.GetVersion(inst);
61 | return new UnityVersion(inst.file.Metadata.UnityVersion);
62 | }
63 |
64 | ///
65 | /// 获取AssetBundle或ResourceManager的Container
66 | ///
67 | /// AssetsFileInstance
68 | /// Container字典
69 | public static Dictionary GetContainers(this AssetsFileInstance inst, AssetsManager am)
70 | {
71 | var isAB = true;
72 | var ab = inst.file.AssetInfos.FirstOrDefault(f => f.TypeId == (uint)AssetClassID.AssetBundle);
73 | if (ab is null)
74 | {
75 | ab = inst.file.AssetInfos.FirstOrDefault(f => f.TypeId == (uint)AssetClassID.ResourceManager);
76 | isAB = false;
77 | if (ab is null)
78 | {
79 | return new Dictionary();
80 | }
81 | }
82 | var bf = am.GetBaseField(inst, ab);
83 | var version = VersionCache.GetVersion(inst);
84 | if (isAB)
85 | {
86 | var assetBundle = AssetBundle.Read(bf, version);
87 | return assetBundle.m_Container
88 | .Select(p => new KeyValuePair(p.Key, p.Value.asset))
89 | .ToDictionary(p => p.Key, p => p.Value);
90 | } else
91 | {
92 | var resourceManager = ResourceManager.Read(bf, version);
93 | return resourceManager.m_Container
94 | .Select(p => new KeyValuePair(p.Key, p.Value))
95 | .ToDictionary(p => p.Key, p => p.Value);
96 | }
97 | }
98 |
99 | public static object? DeserializeMonoBehaviour(AssetTypeValueField monoBehaviour) =>
100 | monoBehaviour.Value switch
101 | {
102 | AssetTypeValue v => v.ValueType switch
103 | {
104 | AssetValueType.Bool => v.AsBool,
105 | AssetValueType.Int8 => v.AsByte,
106 | AssetValueType.UInt8 => v.AsSByte,
107 | AssetValueType.Int16 => v.AsShort,
108 | AssetValueType.UInt16 => v.AsUShort,
109 | AssetValueType.Int32 => v.AsInt,
110 | AssetValueType.UInt32 => v.AsUInt,
111 | AssetValueType.Int64 => v.AsLong,
112 | AssetValueType.UInt64 => v.AsULong,
113 | AssetValueType.Float => v.AsFloat,
114 | AssetValueType.Double => v.AsDouble,
115 | AssetValueType.String => v.AsString,
116 | AssetValueType.Array => monoBehaviour.Children
117 | .Select(DeserializeMonoBehaviour)
118 | .ToArray(),
119 | AssetValueType.ByteArray => v.AsByteArray,
120 | _ => null
121 | },
122 | null => monoBehaviour.Children
123 | .Aggregate(new Dictionary(), (obj, c) =>
124 | {
125 | var key = c.TemplateField.Name;
126 | var value = DeserializeMonoBehaviour(c);
127 | obj[key] = value;
128 | return obj;
129 | })
130 | };
131 |
132 | public static AssetTypeValueField SerializeMonoBehaviour(object? obj, AssetTypeTemplateField templateField)
133 | {
134 | var ret = new AssetTypeValueField();
135 | ret.TemplateField = templateField;
136 |
137 | ret.Value = obj switch
138 | {
139 | null => new AssetTypeValue(AssetValueType.None, null),
140 | bool b => new AssetTypeValue(AssetValueType.Bool, b),
141 | sbyte int8 => new AssetTypeValue(AssetValueType.Int8, int8),
142 | byte uint8 => new AssetTypeValue(AssetValueType.UInt8, uint8),
143 | short int16 => new AssetTypeValue(AssetValueType.Int16, int16),
144 | ushort uint16 => new AssetTypeValue(AssetValueType.UInt16, uint16),
145 | int int32 => new AssetTypeValue(AssetValueType.Int32, int32),
146 | uint uint32 => new AssetTypeValue(AssetValueType.UInt32, uint32),
147 | long int64 => new AssetTypeValue(AssetValueType.Int64, int64),
148 | ulong uint64 => new AssetTypeValue(AssetValueType.UInt64, uint64),
149 | float f => new AssetTypeValue(AssetValueType.Float, f),
150 | double d => new AssetTypeValue(AssetValueType.Double, d),
151 | string s => new AssetTypeValue(AssetValueType.String, s),
152 | IEnumerable barr => new AssetTypeValue(
153 | AssetValueType.ByteArray,
154 | barr.ToArray()),
155 | _ => null
156 | };
157 |
158 | if (ret.Value is not null)
159 | {
160 | return ret;
161 | }
162 |
163 |
164 | if (obj is IDictionary dict)
165 | {
166 | ret.Value = null;
167 | ret.Children = dict.Select(p =>
168 | {
169 | var temp = templateField.Children.First(f => f.Name == p.Key);
170 | AssetTypeValueField child = SerializeMonoBehaviour(p.Value, temp);
171 | return child;
172 | }).ToList();
173 | }
174 | else if (obj is IList arr)
175 | {
176 | var array = new AssetTypeArrayInfo(arr.Count);
177 | ret.Children =arr
178 | .Select(x =>
179 | {
180 | var temp = templateField.Children[1];// [0]为size
181 | return (AssetTypeValueField)SerializeMonoBehaviour(x, temp);
182 | })
183 | .ToList();
184 | ret.Value = new AssetTypeValue(AssetValueType.Array, array);
185 | }
186 | else
187 | {
188 | ret.Value = null;
189 | Type type = obj!.GetType();
190 | ret.Children = type.GetFields().Select(f =>
191 | {
192 | var key = f.Name;
193 | var temp = templateField.Children.First(f => f.Name == key);
194 | AssetTypeValueField child = SerializeMonoBehaviour(f.GetValue(obj), temp);
195 | return child;
196 | }).ToList();
197 | }
198 |
199 |
200 | return ret;
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/AssetStudio/BigArrayPool.cs:
--------------------------------------------------------------------------------
1 | using System.Buffers;
2 |
3 | namespace AssetStudio
4 | {
5 | public static class BigArrayPool
6 | {
7 | private static readonly ArrayPool s_shared = ArrayPool.Create(64 * 1024 * 1024, 3);
8 | public static ArrayPool Shared => s_shared;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/AssetStudio/Math/Color.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace AssetStudio
6 | {
7 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
8 | public struct Color : IEquatable
9 | {
10 | public float R;
11 | public float G;
12 | public float B;
13 | public float A;
14 |
15 | public Color(float r, float g, float b, float a)
16 | {
17 | R = r;
18 | G = g;
19 | B = b;
20 | A = a;
21 | }
22 |
23 | public override int GetHashCode()
24 | {
25 | return ((Vector4)this).GetHashCode();
26 | }
27 |
28 | public override bool Equals(object other)
29 | {
30 | if (!(other is Color))
31 | return false;
32 | return Equals((Color)other);
33 | }
34 |
35 | public bool Equals(Color other)
36 | {
37 | return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);
38 | }
39 |
40 | public static Color operator +(Color a, Color b)
41 | {
42 | return new Color(a.R + b.R, a.G + b.G, a.B + b.B, a.A + b.A);
43 | }
44 |
45 | public static Color operator -(Color a, Color b)
46 | {
47 | return new Color(a.R - b.R, a.G - b.G, a.B - b.B, a.A - b.A);
48 | }
49 |
50 | public static Color operator *(Color a, Color b)
51 | {
52 | return new Color(a.R * b.R, a.G * b.G, a.B * b.B, a.A * b.A);
53 | }
54 |
55 | public static Color operator *(Color a, float b)
56 | {
57 | return new Color(a.R * b, a.G * b, a.B * b, a.A * b);
58 | }
59 |
60 | public static Color operator *(float b, Color a)
61 | {
62 | return new Color(a.R * b, a.G * b, a.B * b, a.A * b);
63 | }
64 |
65 | public static Color operator /(Color a, float b)
66 | {
67 | return new Color(a.R / b, a.G / b, a.B / b, a.A / b);
68 | }
69 |
70 | public static bool operator ==(Color lhs, Color rhs)
71 | {
72 | return (Vector4)lhs == (Vector4)rhs;
73 | }
74 |
75 | public static bool operator !=(Color lhs, Color rhs)
76 | {
77 | return !(lhs == rhs);
78 | }
79 |
80 | public static implicit operator Vector4(Color c)
81 | {
82 | return new Vector4(c.R, c.G, c.B, c.A);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/AssetStudio/Math/HalfHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace AssetStudio
5 | {
6 | ///
7 | /// Helper class for Half conversions and some low level operations.
8 | /// This class is internally used in the Half class.
9 | ///
10 | ///
11 | /// References:
12 | /// - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
13 | ///
14 | [ComVisible(false)]
15 | internal static class HalfHelper
16 | {
17 | private static uint[] mantissaTable = GenerateMantissaTable();
18 | private static uint[] exponentTable = GenerateExponentTable();
19 | private static ushort[] offsetTable = GenerateOffsetTable();
20 | private static ushort[] baseTable = GenerateBaseTable();
21 | private static sbyte[] shiftTable = GenerateShiftTable();
22 |
23 | // Transforms the subnormal representation to a normalized one.
24 | private static uint ConvertMantissa(int i)
25 | {
26 | uint m = (uint)(i << 13); // Zero pad mantissa bits
27 | uint e = 0; // Zero exponent
28 |
29 | // While not normalized
30 | while ((m & 0x00800000) == 0)
31 | {
32 | e -= 0x00800000; // Decrement exponent (1<<23)
33 | m <<= 1; // Shift mantissa
34 | }
35 | m &= unchecked((uint)~0x00800000); // Clear leading 1 bit
36 | e += 0x38800000; // Adjust bias ((127-14)<<23)
37 | return m | e; // Return combined number
38 | }
39 |
40 | private static uint[] GenerateMantissaTable()
41 | {
42 | uint[] mantissaTable = new uint[2048];
43 | mantissaTable[0] = 0;
44 | for (int i = 1; i < 1024; i++)
45 | {
46 | mantissaTable[i] = ConvertMantissa(i);
47 | }
48 | for (int i = 1024; i < 2048; i++)
49 | {
50 | mantissaTable[i] = (uint)(0x38000000 + ((i - 1024) << 13));
51 | }
52 |
53 | return mantissaTable;
54 | }
55 | private static uint[] GenerateExponentTable()
56 | {
57 | uint[] exponentTable = new uint[64];
58 | exponentTable[0] = 0;
59 | for (int i = 1; i < 31; i++)
60 | {
61 | exponentTable[i] = (uint)(i << 23);
62 | }
63 | exponentTable[31] = 0x47800000;
64 | exponentTable[32] = 0x80000000;
65 | for (int i = 33; i < 63; i++)
66 | {
67 | exponentTable[i] = (uint)(0x80000000 + ((i - 32) << 23));
68 | }
69 | exponentTable[63] = 0xc7800000;
70 |
71 | return exponentTable;
72 | }
73 | private static ushort[] GenerateOffsetTable()
74 | {
75 | ushort[] offsetTable = new ushort[64];
76 | offsetTable[0] = 0;
77 | for (int i = 1; i < 32; i++)
78 | {
79 | offsetTable[i] = 1024;
80 | }
81 | offsetTable[32] = 0;
82 | for (int i = 33; i < 64; i++)
83 | {
84 | offsetTable[i] = 1024;
85 | }
86 |
87 | return offsetTable;
88 | }
89 | private static ushort[] GenerateBaseTable()
90 | {
91 | ushort[] baseTable = new ushort[512];
92 | for (int i = 0; i < 256; ++i)
93 | {
94 | sbyte e = (sbyte)(127 - i);
95 | if (e > 24)
96 | { // Very small numbers map to zero
97 | baseTable[i | 0x000] = 0x0000;
98 | baseTable[i | 0x100] = 0x8000;
99 | }
100 | else if (e > 14)
101 | { // Small numbers map to denorms
102 | baseTable[i | 0x000] = (ushort)(0x0400 >> (18 + e));
103 | baseTable[i | 0x100] = (ushort)((0x0400 >> (18 + e)) | 0x8000);
104 | }
105 | else if (e >= -15)
106 | { // Normal numbers just lose precision
107 | baseTable[i | 0x000] = (ushort)((15 - e) << 10);
108 | baseTable[i | 0x100] = (ushort)(((15 - e) << 10) | 0x8000);
109 | }
110 | else if (e > -128)
111 | { // Large numbers map to Infinity
112 | baseTable[i | 0x000] = 0x7c00;
113 | baseTable[i | 0x100] = 0xfc00;
114 | }
115 | else
116 | { // Infinity and NaN's stay Infinity and NaN's
117 | baseTable[i | 0x000] = 0x7c00;
118 | baseTable[i | 0x100] = 0xfc00;
119 | }
120 | }
121 |
122 | return baseTable;
123 | }
124 | private static sbyte[] GenerateShiftTable()
125 | {
126 | sbyte[] shiftTable = new sbyte[512];
127 | for (int i = 0; i < 256; ++i)
128 | {
129 | sbyte e = (sbyte)(127 - i);
130 | if (e > 24)
131 | { // Very small numbers map to zero
132 | shiftTable[i | 0x000] = 24;
133 | shiftTable[i | 0x100] = 24;
134 | }
135 | else if (e > 14)
136 | { // Small numbers map to denorms
137 | shiftTable[i | 0x000] = (sbyte)(e - 1);
138 | shiftTable[i | 0x100] = (sbyte)(e - 1);
139 | }
140 | else if (e >= -15)
141 | { // Normal numbers just lose precision
142 | shiftTable[i | 0x000] = 13;
143 | shiftTable[i | 0x100] = 13;
144 | }
145 | else if (e > -128)
146 | { // Large numbers map to Infinity
147 | shiftTable[i | 0x000] = 24;
148 | shiftTable[i | 0x100] = 24;
149 | }
150 | else
151 | { // Infinity and NaN's stay Infinity and NaN's
152 | shiftTable[i | 0x000] = 13;
153 | shiftTable[i | 0x100] = 13;
154 | }
155 | }
156 |
157 | return shiftTable;
158 | }
159 |
160 | /*public static unsafe float HalfToSingle(Half half)
161 | {
162 | uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
163 | return *((float*)&result);
164 | }
165 | public static unsafe Half SingleToHalf(float single)
166 | {
167 | uint value = *((uint*)&single);
168 |
169 | ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
170 | return Half.ToHalf(result);
171 | }*/
172 | public static float HalfToSingle(Half half)
173 | {
174 | uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
175 | byte[] uintBytes = BitConverter.GetBytes(result);
176 | return BitConverter.ToSingle(uintBytes, 0);
177 | }
178 | public static Half SingleToHalf(float single)
179 | {
180 | byte[] singleBytes = BitConverter.GetBytes(single);
181 | uint value = BitConverter.ToUInt32(singleBytes, 0);
182 | ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
183 | return Half.ToHalf(result);
184 | }
185 |
186 | public static Half Negate(Half half)
187 | {
188 | return Half.ToHalf((ushort)(half.value ^ 0x8000));
189 | }
190 | public static Half Abs(Half half)
191 | {
192 | return Half.ToHalf((ushort)(half.value & 0x7fff));
193 | }
194 |
195 | public static bool IsNaN(Half half)
196 | {
197 | return ((half.value & 0x7fff) > 0x7c00);
198 | }
199 | public static bool IsInfinity(Half half)
200 | {
201 | return ((half.value & 0x7fff) == 0x7c00);
202 | }
203 | public static bool IsPositiveInfinity(Half half)
204 | {
205 | return (half.value == 0x7c00);
206 | }
207 | public static bool IsNegativeInfinity(Half half)
208 | {
209 | return (half.value == 0xfc00);
210 | }
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/AssetStudio/Math/Matrix4x4.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace AssetStudio
5 | {
6 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
7 | public struct Matrix4x4 : IEquatable
8 | {
9 | public float M00;
10 | public float M10;
11 | public float M20;
12 | public float M30;
13 |
14 | public float M01;
15 | public float M11;
16 | public float M21;
17 | public float M31;
18 |
19 | public float M02;
20 | public float M12;
21 | public float M22;
22 | public float M32;
23 |
24 | public float M03;
25 | public float M13;
26 | public float M23;
27 | public float M33;
28 |
29 | public Matrix4x4(float[] values)
30 | {
31 | if (values == null)
32 | throw new ArgumentNullException(nameof(values));
33 | if (values.Length != 16)
34 | throw new ArgumentOutOfRangeException(nameof(values), "There must be sixteen and only sixteen input values for Matrix.");
35 |
36 | M00 = values[0];
37 | M10 = values[1];
38 | M20 = values[2];
39 | M30 = values[3];
40 |
41 | M01 = values[4];
42 | M11 = values[5];
43 | M21 = values[6];
44 | M31 = values[7];
45 |
46 | M02 = values[8];
47 | M12 = values[9];
48 | M22 = values[10];
49 | M32 = values[11];
50 |
51 | M03 = values[12];
52 | M13 = values[13];
53 | M23 = values[14];
54 | M33 = values[15];
55 | }
56 |
57 | public float this[int row, int column]
58 | {
59 | get => this[row + column * 4];
60 |
61 | set => this[row + column * 4] = value;
62 | }
63 |
64 | public float this[int index]
65 | {
66 | get
67 | {
68 | switch (index)
69 | {
70 | case 0: return M00;
71 | case 1: return M10;
72 | case 2: return M20;
73 | case 3: return M30;
74 | case 4: return M01;
75 | case 5: return M11;
76 | case 6: return M21;
77 | case 7: return M31;
78 | case 8: return M02;
79 | case 9: return M12;
80 | case 10: return M22;
81 | case 11: return M32;
82 | case 12: return M03;
83 | case 13: return M13;
84 | case 14: return M23;
85 | case 15: return M33;
86 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Matrix4x4 index!");
87 | }
88 | }
89 |
90 | set
91 | {
92 | switch (index)
93 | {
94 | case 0: M00 = value; break;
95 | case 1: M10 = value; break;
96 | case 2: M20 = value; break;
97 | case 3: M30 = value; break;
98 | case 4: M01 = value; break;
99 | case 5: M11 = value; break;
100 | case 6: M21 = value; break;
101 | case 7: M31 = value; break;
102 | case 8: M02 = value; break;
103 | case 9: M12 = value; break;
104 | case 10: M22 = value; break;
105 | case 11: M32 = value; break;
106 | case 12: M03 = value; break;
107 | case 13: M13 = value; break;
108 | case 14: M23 = value; break;
109 | case 15: M33 = value; break;
110 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Matrix4x4 index!");
111 | }
112 | }
113 | }
114 |
115 | public override int GetHashCode()
116 | {
117 | return GetColumn(0).GetHashCode() ^ (GetColumn(1).GetHashCode() << 2) ^ (GetColumn(2).GetHashCode() >> 2) ^ (GetColumn(3).GetHashCode() >> 1);
118 | }
119 |
120 | public override bool Equals(object other)
121 | {
122 | if (!(other is Matrix4x4))
123 | return false;
124 | return Equals((Matrix4x4)other);
125 | }
126 |
127 | public bool Equals(Matrix4x4 other)
128 | {
129 | return GetColumn(0).Equals(other.GetColumn(0))
130 | && GetColumn(1).Equals(other.GetColumn(1))
131 | && GetColumn(2).Equals(other.GetColumn(2))
132 | && GetColumn(3).Equals(other.GetColumn(3));
133 | }
134 |
135 | public Vector4 GetColumn(int index)
136 | {
137 | switch (index)
138 | {
139 | case 0: return new Vector4(M00, M10, M20, M30);
140 | case 1: return new Vector4(M01, M11, M21, M31);
141 | case 2: return new Vector4(M02, M12, M22, M32);
142 | case 3: return new Vector4(M03, M13, M23, M33);
143 | default: throw new IndexOutOfRangeException("Invalid column index!");
144 | }
145 | }
146 |
147 | public Vector4 GetRow(int index)
148 | {
149 | switch (index)
150 | {
151 | case 0: return new Vector4(M00, M01, M02, M03);
152 | case 1: return new Vector4(M10, M11, M12, M13);
153 | case 2: return new Vector4(M20, M21, M22, M23);
154 | case 3: return new Vector4(M30, M31, M32, M33);
155 | default: throw new IndexOutOfRangeException("Invalid row index!");
156 | }
157 | }
158 |
159 | public static Matrix4x4 operator *(Matrix4x4 lhs, Matrix4x4 rhs)
160 | {
161 | Matrix4x4 res;
162 | res.M00 = lhs.M00 * rhs.M00 + lhs.M01 * rhs.M10 + lhs.M02 * rhs.M20 + lhs.M03 * rhs.M30;
163 | res.M01 = lhs.M00 * rhs.M01 + lhs.M01 * rhs.M11 + lhs.M02 * rhs.M21 + lhs.M03 * rhs.M31;
164 | res.M02 = lhs.M00 * rhs.M02 + lhs.M01 * rhs.M12 + lhs.M02 * rhs.M22 + lhs.M03 * rhs.M32;
165 | res.M03 = lhs.M00 * rhs.M03 + lhs.M01 * rhs.M13 + lhs.M02 * rhs.M23 + lhs.M03 * rhs.M33;
166 |
167 | res.M10 = lhs.M10 * rhs.M00 + lhs.M11 * rhs.M10 + lhs.M12 * rhs.M20 + lhs.M13 * rhs.M30;
168 | res.M11 = lhs.M10 * rhs.M01 + lhs.M11 * rhs.M11 + lhs.M12 * rhs.M21 + lhs.M13 * rhs.M31;
169 | res.M12 = lhs.M10 * rhs.M02 + lhs.M11 * rhs.M12 + lhs.M12 * rhs.M22 + lhs.M13 * rhs.M32;
170 | res.M13 = lhs.M10 * rhs.M03 + lhs.M11 * rhs.M13 + lhs.M12 * rhs.M23 + lhs.M13 * rhs.M33;
171 |
172 | res.M20 = lhs.M20 * rhs.M00 + lhs.M21 * rhs.M10 + lhs.M22 * rhs.M20 + lhs.M23 * rhs.M30;
173 | res.M21 = lhs.M20 * rhs.M01 + lhs.M21 * rhs.M11 + lhs.M22 * rhs.M21 + lhs.M23 * rhs.M31;
174 | res.M22 = lhs.M20 * rhs.M02 + lhs.M21 * rhs.M12 + lhs.M22 * rhs.M22 + lhs.M23 * rhs.M32;
175 | res.M23 = lhs.M20 * rhs.M03 + lhs.M21 * rhs.M13 + lhs.M22 * rhs.M23 + lhs.M23 * rhs.M33;
176 |
177 | res.M30 = lhs.M30 * rhs.M00 + lhs.M31 * rhs.M10 + lhs.M32 * rhs.M20 + lhs.M33 * rhs.M30;
178 | res.M31 = lhs.M30 * rhs.M01 + lhs.M31 * rhs.M11 + lhs.M32 * rhs.M21 + lhs.M33 * rhs.M31;
179 | res.M32 = lhs.M30 * rhs.M02 + lhs.M31 * rhs.M12 + lhs.M32 * rhs.M22 + lhs.M33 * rhs.M32;
180 | res.M33 = lhs.M30 * rhs.M03 + lhs.M31 * rhs.M13 + lhs.M32 * rhs.M23 + lhs.M33 * rhs.M33;
181 |
182 | return res;
183 | }
184 |
185 | public static bool operator ==(Matrix4x4 lhs, Matrix4x4 rhs)
186 | {
187 | return lhs.GetColumn(0) == rhs.GetColumn(0)
188 | && lhs.GetColumn(1) == rhs.GetColumn(1)
189 | && lhs.GetColumn(2) == rhs.GetColumn(2)
190 | && lhs.GetColumn(3) == rhs.GetColumn(3);
191 | }
192 |
193 | public static bool operator !=(Matrix4x4 lhs, Matrix4x4 rhs)
194 | {
195 | return !(lhs == rhs);
196 | }
197 |
198 | public static Matrix4x4 Scale(Vector3 vector)
199 | {
200 | Matrix4x4 m;
201 | m.M00 = vector.X; m.M01 = 0F; m.M02 = 0F; m.M03 = 0F;
202 | m.M10 = 0F; m.M11 = vector.Y; m.M12 = 0F; m.M13 = 0F;
203 | m.M20 = 0F; m.M21 = 0F; m.M22 = vector.Z; m.M23 = 0F;
204 | m.M30 = 0F; m.M31 = 0F; m.M32 = 0F; m.M33 = 1F;
205 | return m;
206 | }
207 |
208 | public static Matrix4x4 Translate(Vector3 vector)
209 | {
210 | Matrix4x4 m;
211 | m.M00 = 1F; m.M01 = 0F; m.M02 = 0F; m.M03 = vector.X;
212 | m.M10 = 0F; m.M11 = 1F; m.M12 = 0F; m.M13 = vector.Y;
213 | m.M20 = 0F; m.M21 = 0F; m.M22 = 1F; m.M23 = vector.Z;
214 | m.M30 = 0F; m.M31 = 0F; m.M32 = 0F; m.M33 = 1F;
215 | return m;
216 | }
217 |
218 | public static Matrix4x4 Rotate(Quaternion q)
219 | {
220 | float x = q.X * 2.0F;
221 | float y = q.Y * 2.0F;
222 | float z = q.Z * 2.0F;
223 | float xx = q.X * x;
224 | float yy = q.Y * y;
225 | float zz = q.Z * z;
226 | float xy = q.X * y;
227 | float xz = q.X * z;
228 | float yz = q.Y * z;
229 | float wx = q.W * x;
230 | float wy = q.W * y;
231 | float wz = q.W * z;
232 |
233 | Matrix4x4 m;
234 | m.M00 = 1.0f - (yy + zz); m.M10 = xy + wz; m.M20 = xz - wy; m.M30 = 0.0F;
235 | m.M01 = xy - wz; m.M11 = 1.0f - (xx + zz); m.M21 = yz + wx; m.M31 = 0.0F;
236 | m.M02 = xz + wy; m.M12 = yz - wx; m.M22 = 1.0f - (xx + yy); m.M32 = 0.0F;
237 | m.M03 = 0.0F; m.M13 = 0.0F; m.M23 = 0.0F; m.M33 = 1.0F;
238 | return m;
239 | }
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/AssetStudio/Math/Quaternion.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace AssetStudio
5 | {
6 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
7 | public struct Quaternion : IEquatable
8 | {
9 | public float X;
10 | public float Y;
11 | public float Z;
12 | public float W;
13 |
14 | public Quaternion(float x, float y, float z, float w)
15 | {
16 | X = x;
17 | Y = y;
18 | Z = z;
19 | W = w;
20 | }
21 |
22 | public float this[int index]
23 | {
24 | get
25 | {
26 | switch (index)
27 | {
28 | case 0: return X;
29 | case 1: return Y;
30 | case 2: return Z;
31 | case 3: return W;
32 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Quaternion index!");
33 | }
34 | }
35 |
36 | set
37 | {
38 | switch (index)
39 | {
40 | case 0: X = value; break;
41 | case 1: Y = value; break;
42 | case 2: Z = value; break;
43 | case 3: W = value; break;
44 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Quaternion index!");
45 | }
46 | }
47 | }
48 |
49 | public override int GetHashCode()
50 | {
51 | return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1);
52 | }
53 |
54 | public override bool Equals(object other)
55 | {
56 | if (!(other is Quaternion))
57 | return false;
58 | return Equals((Quaternion)other);
59 | }
60 |
61 | public bool Equals(Quaternion other)
62 | {
63 | return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);
64 | }
65 |
66 | public static Quaternion Zero => new Quaternion(0, 0, 0, 1);
67 | public static float Dot(Quaternion a, Quaternion b)
68 | {
69 | return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;
70 | }
71 |
72 | private static bool IsEqualUsingDot(float dot)
73 | {
74 | return dot > 1.0f - kEpsilon;
75 | }
76 |
77 | public static bool operator ==(Quaternion lhs, Quaternion rhs)
78 | {
79 | return IsEqualUsingDot(Dot(lhs, rhs));
80 | }
81 |
82 | public static bool operator !=(Quaternion lhs, Quaternion rhs)
83 | {
84 | return !(lhs == rhs);
85 | }
86 |
87 | private const float kEpsilon = 0.000001F;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/AssetStudio/Math/Vector2.cs:
--------------------------------------------------------------------------------
1 | using AssetsTools.NET;
2 | using AssetStudioExporter.AssetTypes;
3 | using System;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace AssetStudio
7 | {
8 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
9 | public struct Vector2 : IEquatable
10 | {
11 | public float X;
12 | public float Y;
13 |
14 | public Vector2(float x, float y)
15 | {
16 | X = x;
17 | Y = y;
18 | }
19 |
20 | public float this[int index]
21 | {
22 | get
23 | {
24 | switch (index)
25 | {
26 | case 0: return X;
27 | case 1: return Y;
28 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector2 index!");
29 | }
30 | }
31 |
32 | set
33 | {
34 | switch (index)
35 | {
36 | case 0: X = value; break;
37 | case 1: Y = value; break;
38 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector2 index!");
39 | }
40 | }
41 | }
42 |
43 | public override int GetHashCode()
44 | {
45 | return X.GetHashCode() ^ (Y.GetHashCode() << 2);
46 | }
47 |
48 | public override bool Equals(object other)
49 | {
50 | if (!(other is Vector2))
51 | return false;
52 | return Equals((Vector2)other);
53 | }
54 |
55 | public bool Equals(Vector2 other)
56 | {
57 | return X.Equals(other.X) && Y.Equals(other.Y);
58 | }
59 |
60 | public void Normalize()
61 | {
62 | var length = Length();
63 | if (length > kEpsilon)
64 | {
65 | var invNorm = 1.0f / length;
66 | X *= invNorm;
67 | Y *= invNorm;
68 | }
69 | else
70 | {
71 | X = 0;
72 | Y = 0;
73 | }
74 | }
75 |
76 | public float Length()
77 | {
78 | return (float)Math.Sqrt(LengthSquared());
79 | }
80 |
81 | public float LengthSquared()
82 | {
83 | return X * X + Y * Y;
84 | }
85 |
86 | public static Vector2 Zero => new Vector2();
87 |
88 | public static Vector2 operator +(Vector2 a, Vector2 b)
89 | {
90 | return new Vector2(a.X + b.X, a.Y + b.Y);
91 | }
92 |
93 | public static Vector2 operator -(Vector2 a, Vector2 b)
94 | {
95 | return new Vector2(a.X - b.X, a.Y - b.Y);
96 | }
97 |
98 | public static Vector2 operator *(Vector2 a, Vector2 b)
99 | {
100 | return new Vector2(a.X * b.X, a.Y * b.Y);
101 | }
102 |
103 | public static Vector2 operator /(Vector2 a, Vector2 b)
104 | {
105 | return new Vector2(a.X / b.X, a.Y / b.Y);
106 | }
107 |
108 | public static Vector2 operator -(Vector2 a)
109 | {
110 | return new Vector2(-a.X, -a.Y);
111 | }
112 |
113 | public static Vector2 operator *(Vector2 a, float d)
114 | {
115 | return new Vector2(a.X * d, a.Y * d);
116 | }
117 |
118 | public static Vector2 operator *(float d, Vector2 a)
119 | {
120 | return new Vector2(a.X * d, a.Y * d);
121 | }
122 |
123 | public static Vector2 operator /(Vector2 a, float d)
124 | {
125 | return new Vector2(a.X / d, a.Y / d);
126 | }
127 |
128 | public static bool operator ==(Vector2 lhs, Vector2 rhs)
129 | {
130 | return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
131 | }
132 |
133 | public static bool operator !=(Vector2 lhs, Vector2 rhs)
134 | {
135 | return !(lhs == rhs);
136 | }
137 |
138 | public static implicit operator Vector3(Vector2 v)
139 | {
140 | return new Vector3(v.X, v.Y, 0);
141 | }
142 |
143 | public static implicit operator Vector4(Vector2 v)
144 | {
145 | return new Vector4(v.X, v.Y, 0.0F, 0.0F);
146 | }
147 |
148 | private const float kEpsilon = 0.00001F;
149 |
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/AssetStudio/Math/Vector3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace AssetStudio
5 | {
6 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
7 | public struct Vector3 : IEquatable
8 | {
9 | public float X;
10 | public float Y;
11 | public float Z;
12 |
13 | public Vector3(float x, float y, float z)
14 | {
15 | X = x;
16 | Y = y;
17 | Z = z;
18 | }
19 |
20 | public float this[int index]
21 | {
22 | get
23 | {
24 | switch (index)
25 | {
26 | case 0: return X;
27 | case 1: return Y;
28 | case 2: return Z;
29 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector3 index!");
30 | }
31 | }
32 |
33 | set
34 | {
35 | switch (index)
36 | {
37 | case 0: X = value; break;
38 | case 1: Y = value; break;
39 | case 2: Z = value; break;
40 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector3 index!");
41 | }
42 | }
43 | }
44 |
45 | public override int GetHashCode()
46 | {
47 | return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2);
48 | }
49 |
50 | public override bool Equals(object other)
51 | {
52 | if (!(other is Vector3))
53 | return false;
54 | return Equals((Vector3)other);
55 | }
56 |
57 | public bool Equals(Vector3 other)
58 | {
59 | return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);
60 | }
61 |
62 | public void Normalize()
63 | {
64 | var length = Length();
65 | if (length > kEpsilon)
66 | {
67 | var invNorm = 1.0f / length;
68 | X *= invNorm;
69 | Y *= invNorm;
70 | Z *= invNorm;
71 | }
72 | else
73 | {
74 | X = 0;
75 | Y = 0;
76 | Z = 0;
77 | }
78 | }
79 |
80 | public float Length()
81 | {
82 | return (float)Math.Sqrt(LengthSquared());
83 | }
84 |
85 | public float LengthSquared()
86 | {
87 | return X * X + Y * Y + Z * Z;
88 | }
89 |
90 |
91 | public static Vector3 Zero => new Vector3();
92 |
93 | public static Vector3 One => new Vector3(1.0f, 1.0f, 1.0f);
94 |
95 | public static Vector3 operator +(Vector3 a, Vector3 b)
96 | {
97 | return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
98 | }
99 |
100 | public static Vector3 operator -(Vector3 a, Vector3 b)
101 | {
102 | return new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
103 | }
104 |
105 | public static Vector3 operator -(Vector3 a)
106 | {
107 | return new Vector3(-a.X, -a.Y, -a.Z);
108 | }
109 |
110 | public static Vector3 operator *(Vector3 a, float d)
111 | {
112 | return new Vector3(a.X * d, a.Y * d, a.Z * d);
113 | }
114 |
115 | public static Vector3 operator *(float d, Vector3 a)
116 | {
117 | return new Vector3(a.X * d, a.Y * d, a.Z * d);
118 | }
119 |
120 | public static Vector3 operator /(Vector3 a, float d)
121 | {
122 | return new Vector3(a.X / d, a.Y / d, a.Z / d);
123 | }
124 |
125 | public static bool operator ==(Vector3 lhs, Vector3 rhs)
126 | {
127 | return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
128 | }
129 |
130 | public static bool operator !=(Vector3 lhs, Vector3 rhs)
131 | {
132 | return !(lhs == rhs);
133 | }
134 |
135 | public static implicit operator Vector2(Vector3 v)
136 | {
137 | return new Vector2(v.X, v.Y);
138 | }
139 |
140 | public static implicit operator Vector4(Vector3 v)
141 | {
142 | return new Vector4(v.X, v.Y, v.Z, 0.0F);
143 | }
144 |
145 | private const float kEpsilon = 0.00001F;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/AssetStudio/Math/Vector4.cs:
--------------------------------------------------------------------------------
1 | using AssetsTools.NET;
2 | using AssetStudioExporter.AssetTypes;
3 | using System;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace AssetStudio
7 | {
8 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
9 | public struct Vector4 : IEquatable
10 | {
11 | public float X;
12 | public float Y;
13 | public float Z;
14 | public float W;
15 |
16 | public Vector4(float x, float y, float z, float w)
17 | {
18 | X = x;
19 | Y = y;
20 | Z = z;
21 | W = w;
22 | }
23 |
24 | public Vector4(Vector3 value, float w)
25 | {
26 | X = value.X;
27 | Y = value.Y;
28 | Z = value.Z;
29 | W = w;
30 | }
31 |
32 | public float this[int index]
33 | {
34 | get
35 | {
36 | switch (index)
37 | {
38 | case 0: return X;
39 | case 1: return Y;
40 | case 2: return Z;
41 | case 3: return W;
42 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector4 index!");
43 | }
44 | }
45 |
46 | set
47 | {
48 | switch (index)
49 | {
50 | case 0: X = value; break;
51 | case 1: Y = value; break;
52 | case 2: Z = value; break;
53 | case 3: W = value; break;
54 | default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector4 index!");
55 | }
56 | }
57 | }
58 |
59 | public override int GetHashCode()
60 | {
61 | return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1);
62 | }
63 |
64 | public override bool Equals(object other)
65 | {
66 | if (!(other is Vector4))
67 | return false;
68 | return Equals((Vector4)other);
69 | }
70 |
71 | public bool Equals(Vector4 other)
72 | {
73 | return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);
74 | }
75 |
76 | public void Normalize()
77 | {
78 | var length = Length();
79 | if (length > kEpsilon)
80 | {
81 | var invNorm = 1.0f / length;
82 | X *= invNorm;
83 | Y *= invNorm;
84 | Z *= invNorm;
85 | W *= invNorm;
86 | }
87 | else
88 | {
89 | X = 0;
90 | Y = 0;
91 | Z = 0;
92 | W = 0;
93 | }
94 | }
95 |
96 | public float Length()
97 | {
98 | return (float)Math.Sqrt(LengthSquared());
99 | }
100 |
101 | public float LengthSquared()
102 | {
103 | return X * X + Y * Y + Z * Z + W * W;
104 | }
105 |
106 | public static Vector4 Zero => new Vector4();
107 |
108 | public static Vector4 operator +(Vector4 a, Vector4 b)
109 | {
110 | return new Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);
111 | }
112 |
113 | public static Vector4 operator -(Vector4 a, Vector4 b)
114 | {
115 | return new Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);
116 | }
117 |
118 | public static Vector4 operator -(Vector4 a)
119 | {
120 | return new Vector4(-a.X, -a.Y, -a.Z, -a.W);
121 | }
122 |
123 | public static Vector4 operator *(Vector4 a, float d)
124 | {
125 | return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d);
126 | }
127 |
128 | public static Vector4 operator *(float d, Vector4 a)
129 | {
130 | return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d);
131 | }
132 |
133 | public static Vector4 operator /(Vector4 a, float d)
134 | {
135 | return new Vector4(a.X / d, a.Y / d, a.Z / d, a.W / d);
136 | }
137 |
138 | public static bool operator ==(Vector4 lhs, Vector4 rhs)
139 | {
140 | return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
141 | }
142 |
143 | public static bool operator !=(Vector4 lhs, Vector4 rhs)
144 | {
145 | return !(lhs == rhs);
146 | }
147 |
148 | public static implicit operator Vector2(Vector4 v)
149 | {
150 | return new Vector2(v.X, v.Y);
151 | }
152 |
153 | public static implicit operator Vector3(Vector4 v)
154 | {
155 | return new Vector3(v.X, v.Y, v.Z);
156 | }
157 |
158 | public static implicit operator Color(Vector4 v)
159 | {
160 | return new Color(v.X, v.Y, v.Z, v.W);
161 | }
162 |
163 | private const float kEpsilon = 0.00001F;
164 |
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/AssetStudio/Texture2DDecoder/T2DDll.cs:
--------------------------------------------------------------------------------
1 | namespace Texture2DDecoder
2 | {
3 | internal static class T2DDll
4 | {
5 |
6 | internal const string DllName = "Texture2DDecoderNative";
7 |
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/AssetStudio/Texture2DDecoder/TextureDecoder.PInvoke.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using AssetStudioExporter.Native;
3 |
4 | namespace Texture2DDecoder
5 | {
6 | unsafe partial class TextureDecoder
7 | {
8 |
9 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
10 | [return: MarshalAs(UnmanagedType.Bool)]
11 | private static extern bool DecodeDXT1(void* data, int width, int height, void* image);
12 |
13 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
14 | [return: MarshalAs(UnmanagedType.Bool)]
15 | private static extern bool DecodeDXT5(void* data, int width, int height, void* image);
16 |
17 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
18 | [return: MarshalAs(UnmanagedType.Bool)]
19 | private static extern bool DecodePVRTC(void* data, int width, int height, void* image, [MarshalAs(UnmanagedType.Bool)] bool is2bpp);
20 |
21 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
22 | [return: MarshalAs(UnmanagedType.Bool)]
23 | private static extern bool DecodeETC1(void* data, int width, int height, void* image);
24 |
25 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
26 | [return: MarshalAs(UnmanagedType.Bool)]
27 | private static extern bool DecodeETC2(void* data, int width, int height, void* image);
28 |
29 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
30 | [return: MarshalAs(UnmanagedType.Bool)]
31 | private static extern bool DecodeETC2A1(void* data, int width, int height, void* image);
32 |
33 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
34 | [return: MarshalAs(UnmanagedType.Bool)]
35 | private static extern bool DecodeETC2A8(void* data, int width, int height, void* image);
36 |
37 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
38 | [return: MarshalAs(UnmanagedType.Bool)]
39 | private static extern bool DecodeEACR(void* data, int width, int height, void* image);
40 |
41 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
42 | [return: MarshalAs(UnmanagedType.Bool)]
43 | private static extern bool DecodeEACRSigned(void* data, int width, int height, void* image);
44 |
45 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
46 | [return: MarshalAs(UnmanagedType.Bool)]
47 | private static extern bool DecodeEACRG(void* data, int width, int height, void* image);
48 |
49 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
50 | [return: MarshalAs(UnmanagedType.Bool)]
51 | private static extern bool DecodeEACRGSigned(void* data, int width, int height, void* image);
52 |
53 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
54 | [return: MarshalAs(UnmanagedType.Bool)]
55 | private static extern bool DecodeBC4(void* data, int width, int height, void* image);
56 |
57 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
58 | [return: MarshalAs(UnmanagedType.Bool)]
59 | private static extern bool DecodeBC5(void* data, int width, int height, void* image);
60 |
61 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
62 | [return: MarshalAs(UnmanagedType.Bool)]
63 | private static extern bool DecodeBC6(void* data, int width, int height, void* image);
64 |
65 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
66 | [return: MarshalAs(UnmanagedType.Bool)]
67 | private static extern bool DecodeBC7(void* data, int width, int height, void* image);
68 |
69 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
70 | [return: MarshalAs(UnmanagedType.Bool)]
71 | private static extern bool DecodeATCRGB4(void* data, int width, int height, void* image);
72 |
73 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
74 | [return: MarshalAs(UnmanagedType.Bool)]
75 | private static extern bool DecodeATCRGBA8(void* data, int width, int height, void* image);
76 |
77 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
78 | [return: MarshalAs(UnmanagedType.Bool)]
79 | private static extern bool DecodeASTC(void* data, int width, int height, int blockWidth, int blockHeight, void* image);
80 |
81 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
82 | private static extern void DisposeBuffer(ref void* ppBuffer);
83 |
84 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
85 | private static extern void UnpackCrunch(void* data, uint dataSize, out void* result, out uint resultSize);
86 |
87 | [DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
88 | private static extern void UnpackUnityCrunch(void* data, uint dataSize, out void* result, out uint resultSize);
89 |
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/AssetStudio/Texture2DDecoder/TextureDecoder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using AssetStudioExporter.Native;
4 |
5 | namespace Texture2DDecoder
6 | {
7 | public static unsafe partial class TextureDecoder
8 | {
9 |
10 | static TextureDecoder()
11 | {
12 | DllLoaderNative.PreloadDll(T2DDll.DllName);
13 | }
14 |
15 | public static bool DecodeDXT1(byte[] data, int width, int height, byte[] image)
16 | {
17 | fixed (byte* pData = data)
18 | {
19 | fixed (byte* pImage = image)
20 | {
21 | return DecodeDXT1(pData, width, height, pImage);
22 | }
23 | }
24 | }
25 |
26 | public static bool DecodeDXT5(byte[] data, int width, int height, byte[] image)
27 | {
28 | fixed (byte* pData = data)
29 | {
30 | fixed (byte* pImage = image)
31 | {
32 | return DecodeDXT5(pData, width, height, pImage);
33 | }
34 | }
35 | }
36 |
37 | public static bool DecodePVRTC(byte[] data, int width, int height, byte[] image, bool is2bpp)
38 | {
39 | fixed (byte* pData = data)
40 | {
41 | fixed (byte* pImage = image)
42 | {
43 | return DecodePVRTC(pData, width, height, pImage, is2bpp);
44 | }
45 | }
46 | }
47 |
48 | public static bool DecodeETC1(byte[] data, int width, int height, byte[] image)
49 | {
50 | fixed (byte* pData = data)
51 | {
52 | fixed (byte* pImage = image)
53 | {
54 | return DecodeETC1(pData, width, height, pImage);
55 | }
56 | }
57 | }
58 |
59 | public static bool DecodeETC2(byte[] data, int width, int height, byte[] image)
60 | {
61 | fixed (byte* pData = data)
62 | {
63 | fixed (byte* pImage = image)
64 | {
65 | return DecodeETC2(pData, width, height, pImage);
66 | }
67 | }
68 | }
69 |
70 | public static bool DecodeETC2A1(byte[] data, int width, int height, byte[] image)
71 | {
72 | fixed (byte* pData = data)
73 | {
74 | fixed (byte* pImage = image)
75 | {
76 | return DecodeETC2A1(pData, width, height, pImage);
77 | }
78 | }
79 | }
80 |
81 | public static bool DecodeETC2A8(byte[] data, int width, int height, byte[] image)
82 | {
83 | fixed (byte* pData = data)
84 | {
85 | fixed (byte* pImage = image)
86 | {
87 | return DecodeETC2A8(pData, width, height, pImage);
88 | }
89 | }
90 | }
91 |
92 | public static bool DecodeEACR(byte[] data, int width, int height, byte[] image)
93 | {
94 | fixed (byte* pData = data)
95 | {
96 | fixed (byte* pImage = image)
97 | {
98 | return DecodeEACR(pData, width, height, pImage);
99 | }
100 | }
101 | }
102 |
103 | public static bool DecodeEACRSigned(byte[] data, int width, int height, byte[] image)
104 | {
105 | fixed (byte* pData = data)
106 | {
107 | fixed (byte* pImage = image)
108 | {
109 | return DecodeEACRSigned(pData, width, height, pImage);
110 | }
111 | }
112 | }
113 |
114 | public static bool DecodeEACRG(byte[] data, int width, int height, byte[] image)
115 | {
116 | fixed (byte* pData = data)
117 | {
118 | fixed (byte* pImage = image)
119 | {
120 | return DecodeEACRG(pData, width, height, pImage);
121 | }
122 | }
123 | }
124 |
125 | public static bool DecodeEACRGSigned(byte[] data, int width, int height, byte[] image)
126 | {
127 | fixed (byte* pData = data)
128 | {
129 | fixed (byte* pImage = image)
130 | {
131 | return DecodeEACRGSigned(pData, width, height, pImage);
132 | }
133 | }
134 | }
135 |
136 | public static bool DecodeBC4(byte[] data, int width, int height, byte[] image)
137 | {
138 | fixed (byte* pData = data)
139 | {
140 | fixed (byte* pImage = image)
141 | {
142 | return DecodeBC4(pData, width, height, pImage);
143 | }
144 | }
145 | }
146 |
147 | public static bool DecodeBC5(byte[] data, int width, int height, byte[] image)
148 | {
149 | fixed (byte* pData = data)
150 | {
151 | fixed (byte* pImage = image)
152 | {
153 | return DecodeBC5(pData, width, height, pImage);
154 | }
155 | }
156 | }
157 |
158 | public static bool DecodeBC6(byte[] data, int width, int height, byte[] image)
159 | {
160 | fixed (byte* pData = data)
161 | {
162 | fixed (byte* pImage = image)
163 | {
164 | return DecodeBC6(pData, width, height, pImage);
165 | }
166 | }
167 | }
168 |
169 | public static bool DecodeBC7(byte[] data, int width, int height, byte[] image)
170 | {
171 | fixed (byte* pData = data)
172 | {
173 | fixed (byte* pImage = image)
174 | {
175 | return DecodeBC7(pData, width, height, pImage);
176 | }
177 | }
178 | }
179 |
180 | public static bool DecodeATCRGB4(byte[] data, int width, int height, byte[] image)
181 | {
182 | fixed (byte* pData = data)
183 | {
184 | fixed (byte* pImage = image)
185 | {
186 | return DecodeATCRGB4(pData, width, height, pImage);
187 | }
188 | }
189 | }
190 |
191 | public static bool DecodeATCRGBA8(byte[] data, int width, int height, byte[] image)
192 | {
193 | fixed (byte* pData = data)
194 | {
195 | fixed (byte* pImage = image)
196 | {
197 | return DecodeATCRGBA8(pData, width, height, pImage);
198 | }
199 | }
200 | }
201 |
202 | public static bool DecodeASTC(byte[] data, int width, int height, int blockWidth, int blockHeight, byte[] image)
203 | {
204 | fixed (byte* pData = data)
205 | {
206 | fixed (byte* pImage = image)
207 | {
208 | return DecodeASTC(pData, width, height, blockWidth, blockHeight, pImage);
209 | }
210 | }
211 | }
212 |
213 | public static byte[] UnpackCrunch(byte[] data)
214 | {
215 | void* pBuffer;
216 | uint bufferSize;
217 |
218 | fixed (byte* pData = data)
219 | {
220 | UnpackCrunch(pData, (uint)data.Length, out pBuffer, out bufferSize);
221 | }
222 |
223 | if (pBuffer == null)
224 | {
225 | return null;
226 | }
227 |
228 | var result = new byte[bufferSize];
229 |
230 | Marshal.Copy(new IntPtr(pBuffer), result, 0, (int)bufferSize);
231 |
232 | DisposeBuffer(ref pBuffer);
233 |
234 | return result;
235 | }
236 |
237 | public static byte[] UnpackUnityCrunch(byte[] data)
238 | {
239 | void* pBuffer;
240 | uint bufferSize;
241 |
242 | fixed (byte* pData = data)
243 | {
244 | UnpackUnityCrunch(pData, (uint)data.Length, out pBuffer, out bufferSize);
245 | }
246 |
247 | if (pBuffer == null)
248 | {
249 | return null;
250 | }
251 |
252 | var result = new byte[bufferSize];
253 |
254 | Marshal.Copy(new IntPtr(pBuffer), result, 0, (int)bufferSize);
255 |
256 | DisposeBuffer(ref pBuffer);
257 |
258 | return result;
259 | }
260 |
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/AssetStudioExporter.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | enable
6 | enable
7 | 0.23.2.0
8 | AnyCPU
9 | x64;x86
10 | true
11 | 12.0
12 | True
13 | True
14 |
15 |
16 |
17 |
18 | PreserveNewest
19 | x64/fmod.dll
20 |
21 |
22 | PreserveNewest
23 | x86/fmod.dll
24 |
25 |
26 | PreserveNewest
27 | x64/libfmod.so
28 |
29 |
30 | PreserveNewest
31 | x86/libfmod.so
32 |
33 |
34 | PreserveNewest
35 | x64/Texture2DDecoderNative.dll
36 |
37 |
38 | PreserveNewest
39 | x86/Texture2DDecoderNative.dll
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/AssetStudioExporter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.6.33801.468
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioExporter", "AssetStudioExporter.csproj", "{C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}.Debug|x64.ActiveCfg = Debug|x64
17 | {C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}.Debug|x64.Build.0 = Debug|x64
18 | {C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}.Debug|x86.ActiveCfg = Debug|x86
19 | {C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}.Debug|x86.Build.0 = Debug|x86
20 | {C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}.Release|x64.ActiveCfg = Release|x64
21 | {C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}.Release|x64.Build.0 = Release|x64
22 | {C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}.Release|x86.ActiveCfg = Release|x86
23 | {C08A03AC-E4A4-44B8-8213-736FF3BBE2ED}.Release|x86.Build.0 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {D1D98A9A-CE49-478A-B70B-06FEC46E4A6D}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/AssetTypeManager.cs:
--------------------------------------------------------------------------------
1 | using AssetsTools.NET;
2 | using AssetsTools.NET.Extra;
3 | using AssetStudio;
4 | using AssetStudioExporter.AssetTypes;
5 | using AssetStudioExporter.AssetTypes.Feature;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Diagnostics.CodeAnalysis;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Text.RegularExpressions;
12 | using System.Threading.Tasks;
13 | using Object = AssetStudioExporter.AssetTypes.Object;
14 |
15 | namespace AssetStudioExporter;
16 | public class AssetTypeManager
17 | {
18 | public string VersionString => Version.ToString();
19 | public UnityVersion Version { get; }
20 |
21 | readonly AssetsManager am;
22 | public AssetTypeManager(string version, AssetsManager manager)
23 | {
24 | Version = new UnityVersion(version);
25 | am = manager;
26 | }
27 |
28 | public T ReadAsset(AssetTypeValueField valueField) where T : IAssetType
29 | {
30 | var type = T.AssetClassID;
31 | return (T)ReadAsset(type, valueField);
32 | }
33 |
34 | public IAssetType ReadAsset(AssetClassID type, AssetTypeValueField valueField)
35 | {
36 | return type switch
37 | {
38 | AssetClassID.Object => Object.EmptyObject.Read(valueField, Version),//0
39 | AssetClassID.GameObject => GameObject.Read(valueField, Version),//1
40 | AssetClassID.Component => Component.Read(valueField, Version),//2
41 |
42 | AssetClassID.Texture2D => Texture2D.Read(valueField, Version),//28
43 | AssetClassID.TextAsset => TextAsset.Read(valueField, Version),//49
44 | AssetClassID.AudioClip => AudioClip.Read(valueField, Version),//83
45 | AssetClassID.MonoBehaviour => MonoBehaviour.Read(valueField, Version),//114
46 | AssetClassID.MonoScript => MonoScript.Read(valueField, Version),//115
47 | AssetClassID.Font => Font.Read(valueField, Version),//128
48 |
49 | AssetClassID.AssetBundle => AssetBundle.Read(valueField, Version),//142
50 | AssetClassID.ResourceManager => ResourceManager.Read(valueField, Version),//147
51 |
52 | AssetClassID.Sprite => Sprite.Read(valueField, Version),//213
53 |
54 | AssetClassID.SpriteAtlas => SpriteAtlas.Read(valueField, Version),//687078895
55 |
56 | _ => Object.EmptyObject.Read(valueField, Version),
57 | };
58 | }
59 |
60 | public T ReadObject(AssetTypeValueField valueField) where T : IAssetTypeReader
61 | {
62 | return T.Read(valueField, Version);
63 | }
64 |
65 | public bool TryGetExporter(IAssetType asset, [NotNullWhen(true)]out IAssetTypeExporter? exporter)
66 | {
67 | exporter = null;
68 | if (asset is IAssetTypeExporter exporterSelf)
69 | exporter = exporterSelf;
70 | else if (asset is Sprite sprite)
71 | exporter = sprite.CreateExporter(am);
72 | else
73 | return false;
74 |
75 | return true;
76 | }
77 |
78 | public static bool CanExport()
79 | {
80 | return typeof(T).IsAssignableTo(typeof(IAssetTypeExporter));
81 | }
82 |
83 | public static bool CanExport(IAssetType asset)
84 | {
85 | return asset.GetType().IsAssignableTo(typeof(IAssetTypeExporter));
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/AssetTypes/AssetBundle.cs:
--------------------------------------------------------------------------------
1 | using AssetsTools.NET;
2 | using AssetsTools.NET.Extra;
3 | using AssetStudioExporter.AssetTypes.Feature;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace AssetStudioExporter.AssetTypes;
11 |
12 |
13 | public class AssetInfo
14 | {
15 | public int preloadIndex;
16 | public int preloadSize;
17 | public PPtr