├── .gitattributes ├── .gitignore ├── UE4View.sln └── UE4View ├── Properties └── AssemblyInfo.cs ├── UE4 ├── FArchive.cs ├── FPropertyTag.cs ├── LinkerData │ ├── FEngineVersion.cs │ ├── FGatherableTextData.cs │ ├── FGenerationInfo.cs │ ├── FLocMetadataObject.cs │ ├── FLocMetadataValue.cs │ ├── FNameEntrySerialized.cs │ ├── FObjectExport.cs │ ├── FObjectImport.cs │ ├── FPackageFileSummary.cs │ ├── FTextSourceData.cs │ └── FTextSourceSiteContext.cs ├── ObjectVersion.cs ├── Pak │ ├── FFileIndex.cs │ ├── FPakEntry.cs │ ├── FPakFile.cs │ ├── FPakInfo.cs │ └── PakExplorer.cs ├── UAsset │ ├── Export │ │ └── UDataTable.cs │ ├── ExportTypes.cs │ └── UAsset.cs ├── USerializable.cs └── VorbisBank │ ├── BankExplorer.cs │ ├── BankFile.cs │ └── Xml │ ├── SoundBank.cs │ ├── SoundBankInfo.cs │ └── SoundFile.cs ├── UE4View.csproj ├── UE4ViewCommand.cs └── packages.config /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /UE4View.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2005 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UE4View", "UE4View\UE4View.csproj", "{59960912-35AE-4370-B8E4-F3ADD93D4DD0}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {59960912-35AE-4370-B8E4-F3ADD93D4DD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {59960912-35AE-4370-B8E4-F3ADD93D4DD0}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {59960912-35AE-4370-B8E4-F3ADD93D4DD0}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {59960912-35AE-4370-B8E4-F3ADD93D4DD0}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B6644161-4614-46B7-8269-4FFB5C465063} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /UE4View/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FarPakView")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FarPakView")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("59960912-35ae-4370-b8e4-f3add93d4dd0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /UE4View/UE4/FArchive.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace UE4View.UE4 7 | { 8 | public class FArchive 9 | { 10 | int offset; 11 | byte[] Buffer; 12 | public FArchive(byte[] Data) 13 | { 14 | Buffer = Data; 15 | offset = 0; 16 | } 17 | public virtual string ToName() 18 | { 19 | return "INDEX_NONE"; 20 | } 21 | public string ToFString() 22 | { 23 | var len = ToInt32(); 24 | if (len != 0) 25 | { 26 | var str = Encoding.UTF8.GetString(Buffer, offset, len - 1); 27 | offset += len; 28 | return str; 29 | } 30 | return string.Empty; 31 | } 32 | public string ToFString(Encoding enc, int? Length = null) 33 | { 34 | var len = Length != null ? Length.Value : ToInt32(); 35 | if (len != 0) 36 | { 37 | var str = enc.GetString(Buffer, offset, len - enc.GetByteCount(" ")); 38 | offset += len; 39 | return str; 40 | } 41 | return string.Empty; 42 | } 43 | public string ToFText() 44 | { 45 | ToByteArray(0x9); 46 | var LocalizationGuid = ToFString(); 47 | var result = ToFString(); 48 | return result; 49 | 50 | //if (Version < (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_FTEXT_HISTORY) 51 | //{ 52 | // var str = ToFString(); 53 | // if (Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_ADDED_NAMESPACE_AND_KEY_DATA_TO_FTEXT) 54 | // { 55 | // var Namespace = ToFString(); 56 | // var Key = ToFString(); 57 | // } 58 | // return str; 59 | //} 60 | //var Flags = ToUInt32(); 61 | 62 | //if (Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_FTEXT_HISTORY) 63 | //{ 64 | // var HistoryType = ToByte(); 65 | // bool bSerializeHistory = true; 66 | // if(HistoryType > 11) // FTextHistoryType determining 67 | // { 68 | // bSerializeHistory = false; 69 | // } 70 | 71 | // if(bSerializeHistory) 72 | // { 73 | // // HistoryType object -> serialize 74 | // } 75 | //} 76 | 77 | //// Value.Rebuild() 78 | 79 | //// check localization? 80 | 81 | //return string.Empty; 82 | } 83 | public byte[] ToByteArray(int ArraySize) 84 | { 85 | var data = new byte[ArraySize]; 86 | Array.Copy(Buffer, offset, data, 0, ArraySize); 87 | offset += ArraySize; 88 | return data; 89 | } 90 | public List ToArray() where T : USerializable, new() 91 | { 92 | var len = ToInt32(); 93 | if (len > 0) 94 | { 95 | var items = new List(len); 96 | foreach (var i in Enumerable.Range(0, len)) 97 | items.Add(ToObject()); 98 | 99 | return items; 100 | } 101 | return null; 102 | } 103 | public T ToObject() where T : USerializable, new() 104 | { 105 | var obj = new T(); 106 | obj.Serialize(this); 107 | return obj; 108 | } 109 | public Guid ToGuid() 110 | { 111 | var data = new byte[16]; 112 | Array.Copy(Buffer, offset, data, 0, 16); 113 | offset += 16; 114 | return new Guid(data); 115 | } 116 | public long ToInt64() 117 | { 118 | var val = BitConverter.ToInt64(Buffer, offset); 119 | offset += sizeof(long); 120 | return val; 121 | } 122 | public ulong ToUInt64() 123 | { 124 | var val = BitConverter.ToUInt64(Buffer, offset); 125 | offset += sizeof(ulong); 126 | return val; 127 | } 128 | public int ToInt32() 129 | { 130 | var val = BitConverter.ToInt32(Buffer, offset); 131 | offset += sizeof(int); 132 | return val; 133 | } 134 | public uint ToUInt32() 135 | { 136 | var val = BitConverter.ToUInt32(Buffer, offset); 137 | offset += sizeof(uint); 138 | return val; 139 | } 140 | public short ToInt16() 141 | { 142 | var val = BitConverter.ToInt16(Buffer, offset); 143 | offset += sizeof(short); 144 | return val; 145 | } 146 | public ushort ToUInt16() 147 | { 148 | var val = BitConverter.ToUInt16(Buffer, offset); 149 | offset += sizeof(ushort); 150 | return val; 151 | } 152 | public byte ToByte() 153 | { 154 | return Buffer[offset++]; 155 | } 156 | public bool ToBoolean() 157 | { 158 | return ToInt32() != 0; 159 | } 160 | public float ToFloat() 161 | { 162 | var val = BitConverter.ToSingle(Buffer, offset); 163 | offset += sizeof(float); 164 | return val; 165 | } 166 | public double ToDouble() 167 | { 168 | var val = BitConverter.ToDouble(Buffer, offset); 169 | offset += sizeof(double); 170 | return val; 171 | } 172 | 173 | 174 | public FArchive Skip(int len) 175 | { 176 | offset += len; 177 | return this; 178 | } 179 | public FArchive Seek(int off) 180 | { 181 | offset = off; 182 | return this; 183 | } 184 | public int Tell() 185 | { 186 | return offset; 187 | } 188 | public int Length() 189 | { 190 | return Buffer.Length; 191 | } 192 | 193 | public int Version { get; set; } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /UE4View/UE4/FPropertyTag.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UE4View.UE4 4 | { 5 | class FPropertyTag : USerializable 6 | { 7 | public string Name; // Name of property 8 | public string Type; // Type of property 9 | public byte BoolVal; // a boolean property's value (never need to serialize data for bool properties except here) 10 | public string StructName; // Struct name if UStructProperty 11 | public string EnumName; // Enum name if UByteProperty or UEnumProperty 12 | public string InnerType; // Inner type if UArrayProperty, USetProperty, or UMapProperty 13 | public string ValueType; // Value type if UMapPropery 14 | public int Size; // Property size. 15 | public int ArrayIndex; // Index if an array; else 0 16 | public long SizeOffset; // location in stream of tag size member 17 | public Guid StructGuid; 18 | public byte HasPropertyGuid; 19 | public Guid PropertyGuid; 20 | 21 | public int PropertyStartOffset; 22 | 23 | public override FArchive Serialize(FArchive reader) 24 | { 25 | Name = reader.ToName(); 26 | if (Name == "None") 27 | return reader; 28 | 29 | SizeOffset = reader.Tell(); 30 | Type = reader.ToName(); 31 | Size = reader.ToInt32(); 32 | ArrayIndex = reader.ToInt32(); 33 | 34 | PropertyStartOffset = reader.Tell(); 35 | 36 | if(Type == "StructProperty") 37 | { 38 | StructName = reader.ToName(); 39 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_STRUCT_GUID_IN_PROPERTY_TAG) 40 | { 41 | StructGuid = reader.ToGuid(); 42 | } 43 | } 44 | else if (Type == "BoolProperty") 45 | { 46 | BoolVal = reader.ToByte(); 47 | } 48 | else if (Type == "ByteProperty" || Type == "EnumProperty") 49 | { 50 | EnumName = reader.ToName(); 51 | } 52 | else if (Type == "ArrayProperty") 53 | { 54 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VAR_UE4_ARRAY_PROPERTY_INNER_TAGS) 55 | { 56 | InnerType = reader.ToName(); 57 | } 58 | } 59 | 60 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_PROPERTY_TAG_SET_MAP_SUPPORT) 61 | { 62 | if (Type == "SetProperty") 63 | { 64 | InnerType = reader.ToName(); 65 | } 66 | else if (Type == "MapProperty") 67 | { 68 | InnerType = reader.ToName(); 69 | ValueType = reader.ToName(); 70 | } 71 | } 72 | 73 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_PROPERTY_GUID_IN_PROPERTY_TAG) 74 | { 75 | HasPropertyGuid = reader.ToByte(); 76 | if(HasPropertyGuid != 0) 77 | { 78 | PropertyGuid = reader.ToGuid(); 79 | } 80 | } 81 | 82 | return reader; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FEngineVersion.cs: -------------------------------------------------------------------------------- 1 | namespace UE4View.UE4 2 | { 3 | public class FEngineVersion : USerializable 4 | { 5 | public ushort Major; 6 | public ushort Minor; 7 | public ushort Patch; 8 | public uint Changelist; 9 | public string Branch; 10 | 11 | public override FArchive Serialize(FArchive reader) 12 | { 13 | Major = reader.ToUInt16(); 14 | Minor = reader.ToUInt16(); 15 | Patch = reader.ToUInt16(); 16 | Changelist = reader.ToUInt32(); 17 | Branch = reader.ToFString(); 18 | return reader; 19 | } 20 | 21 | public void Set(ushort Major, ushort Minor, ushort Patch, uint Changelist, string Branch) 22 | { 23 | this.Major = Major; 24 | this.Minor = Minor; 25 | this.Patch = Patch; 26 | this.Changelist = Changelist; 27 | this.Branch = Branch; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FGatherableTextData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | 4 | namespace UE4View.UE4 5 | { 6 | class FGatherableTextData : USerializable 7 | { 8 | public string NamespaceName; 9 | public FTextSourceData SourceData = new FTextSourceData(); 10 | public List SourceSiteContexts; 11 | 12 | public override FArchive Serialize(FArchive reader) 13 | { 14 | NamespaceName = reader.ToFString(Encoding.UTF8); 15 | SourceData.Serialize(reader); 16 | SourceSiteContexts = reader.ToArray(); 17 | return reader; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FGenerationInfo.cs: -------------------------------------------------------------------------------- 1 | namespace UE4View.UE4 2 | { 3 | public class FGenerationInfo : USerializable 4 | { 5 | public int ExportCount; 6 | public int NameCount; 7 | 8 | public override FArchive Serialize(FArchive reader) 9 | { 10 | ExportCount = reader.ToInt32(); 11 | NameCount = reader.ToInt32(); 12 | return reader; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FLocMetadataObject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace UE4View.UE4 5 | { 6 | class FLocMetadataObject : USerializable 7 | { 8 | Dictionary Values = new Dictionary(); 9 | public override FArchive Serialize(FArchive reader) 10 | { 11 | var count = reader.ToInt32(); 12 | foreach(var i in Enumerable.Range(0, count)) 13 | { 14 | string Key = reader.ToFString(); 15 | var value = new FLocMetadataValue(); 16 | value.Serialize(reader); 17 | Values.Add(Key, value); 18 | } 19 | return reader; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FLocMetadataValue.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace UE4View.UE4 4 | { 5 | class FLocMetadataValue : USerializable 6 | { 7 | public override FArchive Serialize(FArchive reader) 8 | { 9 | int MetaDataTypeAsInt = reader.ToInt32(); 10 | // E:\Source\UnrealEngine\Engine\Source\Runtime\Core\Private\Internationalization\InternationalizationMetadata.cpp:276 11 | Debugger.Break(); 12 | return reader; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FNameEntrySerialized.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace UE4View.UE4 4 | { 5 | public class FNameEntrySerialized : USerializable 6 | { 7 | public string Name; 8 | public ushort NonCasePreservingHash; 9 | public ushort CasePreservingHash; 10 | public override FArchive Serialize(FArchive reader) 11 | { 12 | var len = reader.ToInt32(); 13 | // Negative length denotes UTF16 14 | if (len < 0) 15 | { 16 | len = -len; 17 | Name = reader.ToFString(Encoding.Unicode, len*2); 18 | } 19 | else 20 | Name = reader.ToFString(Encoding.UTF8, len); 21 | 22 | // Not implemented for older versions 23 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_NAME_HASHES_SERIALIZED) 24 | { 25 | NonCasePreservingHash = reader.ToUInt16(); 26 | CasePreservingHash = reader.ToUInt16(); 27 | } 28 | 29 | return reader; 30 | } 31 | 32 | public override string ToString() 33 | { 34 | return Name; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FObjectExport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UE4View.UE4 4 | { 5 | public class FObjectExport : USerializable 6 | { 7 | public int ClassIndex; 8 | public int SuperIndex; 9 | public int OuterIndex; 10 | public string ObjectName; 11 | public int Save; 12 | public long SerialSize; 13 | public long SerialOffset; 14 | public bool bForcedExport; 15 | public bool bNotForClient; 16 | public bool bNotForServer; 17 | public Guid PackageGuid; 18 | public uint PackageFlags; 19 | public bool bNotAlwaysLoadedForEditorGame; 20 | public bool bIsAsset; 21 | public int FirstExportDependency; 22 | public int SerializationBeforeSerializationDependencies; 23 | public int CreateBeforeSerializationDependencies; 24 | public int SerializationBeforeCreateDependencies; 25 | public int CreateBeforeCreateDependencies; 26 | 27 | public override FArchive Serialize(FArchive reader) 28 | { 29 | ClassIndex = reader.ToInt32(); 30 | SuperIndex = reader.ToInt32(); 31 | 32 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_TemplateIndex_IN_COOKED_EXPORTS) 33 | { 34 | var TemplateIndex = reader.ToInt32(); 35 | } 36 | OuterIndex = reader.ToInt32(); 37 | ObjectName = reader.ToName(); 38 | 39 | Save = reader.ToInt32(); 40 | // Object flags here 41 | 42 | if(reader.Version < (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_64BIT_EXPORTMAP_SERIALSIZES) 43 | { 44 | SerialSize = reader.ToInt32(); 45 | SerialOffset = reader.ToInt32(); 46 | } 47 | else 48 | { 49 | SerialSize = reader.ToInt64(); 50 | SerialOffset = reader.ToInt64(); 51 | } 52 | 53 | bForcedExport = reader.ToBoolean(); 54 | bNotForClient = reader.ToBoolean(); 55 | bNotForServer = reader.ToBoolean(); 56 | PackageGuid = reader.ToGuid(); 57 | PackageFlags = reader.ToUInt32(); 58 | 59 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_LOAD_FOR_EDITOR_GAME) 60 | bNotAlwaysLoadedForEditorGame = reader.ToBoolean(); 61 | 62 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_COOKED_ASSETS_IN_EDITOR_SUPPORT) 63 | bIsAsset = reader.ToBoolean(); 64 | 65 | if (reader.Version >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_PRELOAD_DEPENDENCIES_IN_COOKED_EXPORTS) 66 | { 67 | FirstExportDependency = reader.ToInt32(); 68 | SerializationBeforeSerializationDependencies = reader.ToInt32(); 69 | CreateBeforeSerializationDependencies = reader.ToInt32(); 70 | SerializationBeforeCreateDependencies = reader.ToInt32(); 71 | CreateBeforeCreateDependencies = reader.ToInt32(); 72 | } 73 | return reader; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FObjectImport.cs: -------------------------------------------------------------------------------- 1 | namespace UE4View.UE4 2 | { 3 | public class FObjectImport : USerializable 4 | { 5 | public string ClassPackage; 6 | public string ClassName; 7 | public int OuterIndex; 8 | public string ObjectName; 9 | public object XObject; 10 | public object SourceLinker; 11 | public int SourceIndex; 12 | public override FArchive Serialize(FArchive reader) 13 | { 14 | ClassPackage = reader.ToName(); 15 | ClassName = reader.ToName(); 16 | OuterIndex = reader.ToInt32(); 17 | ObjectName = reader.ToName(); 18 | 19 | XObject = SourceLinker = null; 20 | SourceIndex = 0; 21 | return reader; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FPackageFileSummary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | 6 | namespace UE4View.UE4 7 | { 8 | public class FPackageFileSummary : USerializable 9 | { 10 | const long PACKAGE_TAG_MAGIC = 0x9E2A83C1; 11 | const long PACKAGE_TAG_MAGIC_SWAPPED = 0xC1832A9E; 12 | 13 | public uint Tag; 14 | public int FileVersionUE4; 15 | public int FileVersionLicenseeUE4; 16 | // public FCustomVersionContainer CustomVersionContainer; 17 | public int TotalHeaderSize; 18 | public uint PackageFlags; 19 | public string FolderName; 20 | public int NameCount; 21 | public int NameOffset; 22 | public int GatherableTextDataCount; 23 | public int GatherableTextDataOffset; 24 | public int ExportCount; 25 | public int ExportOffset; 26 | public int ImportCount; 27 | public int ImportOffset; 28 | public int DependsOffset; 29 | public int StringAssetReferencesCount; 30 | public int StringAssetReferencesOffset; 31 | public int ThumbnailTableOffset; 32 | public Guid Guid; 33 | public List Generations = new List(); 34 | public FEngineVersion SavedByEngineVersion = new FEngineVersion(); 35 | public FEngineVersion CompatibleWithEngineVersion = new FEngineVersion(); 36 | public uint CompressionFlags; 37 | public uint PackageSource; 38 | // public TArray CompressedChunks; 39 | // public TArray AdditionalPackagesToCook; 40 | public bool bUnversioned; 41 | // public TArray TextureAllocations; 42 | public int AssetRegistryDataOffset; 43 | public long BulkDataStartOffset; 44 | public int WorldTileInfoDataOffset; 45 | // public TArray ChunkIDs; 46 | 47 | public override FArchive Serialize(FArchive reader) 48 | { 49 | const long MinimumPackageSize = 32; 50 | if (reader.Length() < MinimumPackageSize) 51 | return reader; 52 | 53 | Tag = reader.ToUInt32(); 54 | if (Tag != PACKAGE_TAG_MAGIC) 55 | return reader; 56 | 57 | const int CurrentLegacyFileVersion = -6; 58 | int LegacyFileVersion = reader.ToInt32(); 59 | if (LegacyFileVersion < 0) 60 | { 61 | if (LegacyFileVersion < CurrentLegacyFileVersion) 62 | { 63 | FileVersionUE4 = 0; 64 | FileVersionLicenseeUE4 = 0; 65 | return reader; 66 | } 67 | 68 | if (LegacyFileVersion != -4) 69 | { 70 | // skip legacy ue3 version 71 | reader.ToInt32(); 72 | } 73 | 74 | FileVersionUE4 = reader.ToInt32(); 75 | FileVersionLicenseeUE4 = reader.ToInt32(); 76 | 77 | if (LegacyFileVersion <= -2) 78 | { 79 | // custom version container 80 | var count = reader.ToInt32(); 81 | // it's TSet, count + new elements[count] 82 | if (count > 0) 83 | Debugger.Break(); 84 | } 85 | 86 | if (FileVersionUE4 == 0 && FileVersionLicenseeUE4 == 0 && reader.Version == 0) 87 | { 88 | #if !DEBUG 89 | // no version information 90 | var input = FarNet.Far.Api.CreateListMenu(); 91 | input.Title = "This file is unversioned, select version"; 92 | input.Bottom = "Gaps mean no changes"; 93 | input.NoInfo = false; 94 | input.ShowAmpersands = true; 95 | 96 | var values = ObjectVersion.VersionDictionary; 97 | foreach (var name in values) 98 | input.Add(name.Key); 99 | 100 | input.Show(); 101 | 102 | if (input.Selected != -1) 103 | FileVersionUE4 = (int)values.ElementAt(input.Selected).Value; 104 | else 105 | FileVersionUE4 = (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_AUTOMATIC_VERSION; 106 | #else 107 | 108 | FileVersionUE4 = (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_COMPRESSED_SHADER_RESOURCES; // 4.13 for now 109 | #endif 110 | FileVersionLicenseeUE4 = 0; 111 | bUnversioned = true; 112 | } 113 | else 114 | { 115 | FileVersionUE4 = reader.Version; // version read from config file 116 | } 117 | } 118 | else 119 | { 120 | FileVersionUE4 = FileVersionLicenseeUE4 = 0; 121 | } 122 | TotalHeaderSize = reader.ToInt32(); 123 | FolderName = reader.ToFString(); 124 | PackageFlags = reader.ToUInt32(); 125 | 126 | // PackageFlags modifications here, doesn't matter for me 127 | 128 | NameCount = reader.ToInt32(); 129 | NameOffset = reader.ToInt32(); 130 | 131 | if (FileVersionUE4 >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_SERIALIZE_TEXT_IN_PACKAGES) 132 | { 133 | GatherableTextDataCount = reader.ToInt32(); 134 | GatherableTextDataOffset = reader.ToInt32(); 135 | } 136 | 137 | ExportCount = reader.ToInt32(); 138 | ExportOffset = reader.ToInt32(); 139 | ImportCount = reader.ToInt32(); 140 | ImportOffset = reader.ToInt32(); 141 | DependsOffset = reader.ToInt32(); 142 | 143 | if (FileVersionUE4 < (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_OLDEST_LOADABLE_PACKAGE) 144 | return reader; 145 | 146 | if (FileVersionUE4 >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_ADD_STRING_ASSET_REFERENCES_MAP) 147 | { 148 | StringAssetReferencesCount = reader.ToInt32(); 149 | StringAssetReferencesOffset = reader.ToInt32(); 150 | } 151 | 152 | ThumbnailTableOffset = reader.ToInt32(); 153 | Guid = reader.ToGuid(); 154 | 155 | var GenerationCount = reader.ToInt32(); 156 | foreach (var i in Enumerable.Range(0, GenerationCount)) 157 | { 158 | var gen = new FGenerationInfo(); 159 | gen.Serialize(reader); 160 | Generations.Add(gen); 161 | } 162 | 163 | if (FileVersionUE4 >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_ENGINE_VERSION_OBJECT) 164 | SavedByEngineVersion.Serialize(reader); 165 | else 166 | { 167 | var EngineChangelist = reader.ToUInt32(); 168 | SavedByEngineVersion.Set(4, 0, 0, EngineChangelist, string.Empty); 169 | } 170 | 171 | if (FileVersionUE4 >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_PACKAGE_SUMMARY_HAS_COMPATIBLE_ENGINE_VERSION) 172 | CompatibleWithEngineVersion.Serialize(reader); 173 | else 174 | CompatibleWithEngineVersion = SavedByEngineVersion; 175 | 176 | CompressionFlags = reader.ToUInt32(); 177 | 178 | var CompressedChunks = reader.ToInt32(); 179 | if (CompressedChunks != 0) 180 | return reader; 181 | 182 | PackageSource = reader.ToUInt32(); 183 | 184 | var packages = reader.ToInt32(); 185 | 186 | if(LegacyFileVersion > -7) 187 | { 188 | var NumTextureAllocations = reader.ToInt32(); 189 | if (NumTextureAllocations != 0) // Not supported 190 | return reader; 191 | } 192 | 193 | AssetRegistryDataOffset = reader.ToInt32(); 194 | BulkDataStartOffset = reader.ToInt64(); 195 | 196 | if (FileVersionUE4 >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_WORLD_LEVEL_INFO) 197 | WorldTileInfoDataOffset = reader.ToInt32(); 198 | 199 | if (FileVersionUE4 >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_CHANGED_CHUNKID_TO_BE_AN_ARRAY_OF_CHUNKIDS) 200 | { 201 | var ChunkIDs = reader.ToInt32(); // Hopefully 0, if not I'll need to implement ToArray() 202 | if (ChunkIDs != 0) 203 | Debugger.Break(); 204 | } 205 | else if (FileVersionUE4 >= (int)ObjectVersion.EUnrealEngineObjectUE4Version.VER_UE4_ADDED_CHUNKID_TO_ASSETDATA_AND_UPACKAGE) 206 | { 207 | // Single Element Array; 208 | } 209 | 210 | // VER_UE4_PRELOAD_DEPENDENCIES_IN_COOKED_EXPORTS stuff here 211 | //if (Ar.IsSaving() || Sum.FileVersionUE4 >= VER_UE4_PRELOAD_DEPENDENCIES_IN_COOKED_EXPORTS) 212 | //{ 213 | // Ar << Sum.PreloadDependencyCount << Sum.PreloadDependencyOffset; 214 | //} 215 | //else 216 | //{ 217 | // Sum.PreloadDependencyCount = -1; 218 | // Sum.PreloadDependencyOffset = 0; 219 | //} 220 | return reader; 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FTextSourceData.cs: -------------------------------------------------------------------------------- 1 | namespace UE4View.UE4 2 | { 3 | class FTextSourceData : USerializable 4 | { 5 | public string SourceString; 6 | public FLocMetadataObject SourceStringMetaData = new FLocMetadataObject(); 7 | public override FArchive Serialize(FArchive reader) 8 | { 9 | SourceString = reader.ToFString(); 10 | SourceStringMetaData.Serialize(reader); 11 | return reader; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /UE4View/UE4/LinkerData/FTextSourceSiteContext.cs: -------------------------------------------------------------------------------- 1 | namespace UE4View.UE4 2 | { 3 | class FTextSourceSiteContext : USerializable 4 | { 5 | public string KeyName; 6 | public string SiteDescription; 7 | public bool IsEditorOnly; 8 | public bool IsOptional; 9 | public FLocMetadataObject InfoMetaData = new FLocMetadataObject(); 10 | public FLocMetadataObject KeyMetaData = new FLocMetadataObject(); 11 | public override FArchive Serialize(FArchive reader) 12 | { 13 | KeyName = reader.ToFString(); 14 | SiteDescription = reader.ToFString(); 15 | IsEditorOnly = reader.ToBoolean(); 16 | IsOptional = reader.ToBoolean(); 17 | InfoMetaData.Serialize(reader); 18 | KeyMetaData.Serialize(reader); 19 | return reader; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /UE4View/UE4/ObjectVersion.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UE4View.UE4 4 | { 5 | public class ObjectVersion 6 | { 7 | 8 | public static Dictionary VersionDictionary { get => versionDictionary; set => versionDictionary = value; } 9 | 10 | public enum EUnrealEngineObjectUE4Version 11 | { 12 | VER_UE4_OLDEST_LOADABLE_PACKAGE = 214, 13 | 14 | // Removed restriction on blueprint-exposed variables from being read-only 15 | VER_UE4_BLUEPRINT_VARS_NOT_READ_ONLY, 16 | // Added manually serialized element to UStaticMesh (precalculated nav collision) 17 | VER_UE4_STATIC_MESH_STORE_NAV_COLLISION, 18 | // Changed property name for atmospheric fog 19 | VER_UE4_ATMOSPHERIC_FOG_DECAY_NAME_CHANGE, 20 | // Change many properties/functions from Translation to Location 21 | VER_UE4_SCENECOMP_TRANSLATION_TO_LOCATION, 22 | // Material attributes reordering 23 | VER_UE4_MATERIAL_ATTRIBUTES_REORDERING, 24 | // Collision Profile setting has been added, and all components that exists has to be properly upgraded 25 | VER_UE4_COLLISION_PROFILE_SETTING, 26 | // Making the blueprint's skeleton class transient 27 | VER_UE4_BLUEPRINT_SKEL_TEMPORARY_TRANSIENT, 28 | // Making the blueprint's skeleton class serialized again 29 | VER_UE4_BLUEPRINT_SKEL_SERIALIZED_AGAIN, 30 | // Blueprint now controls replication settings again 31 | VER_UE4_BLUEPRINT_SETS_REPLICATION, 32 | // Added level info used by World browser 33 | VER_UE4_WORLD_LEVEL_INFO, 34 | // Changed capsule height to capsule half-height (afterwards) 35 | VER_UE4_AFTER_CAPSULE_HALF_HEIGHT_CHANGE, 36 | // Added Namepace, GUID (Key) and Flags to FText 37 | VER_UE4_ADDED_NAMESPACE_AND_KEY_DATA_TO_FTEXT, 38 | // Attenuation shapes 39 | VER_UE4_ATTENUATION_SHAPES, 40 | // Use IES texture multiplier even when IES brightness is not being used 41 | VER_UE4_LIGHTCOMPONENT_USE_IES_TEXTURE_MULTIPLIER_ON_NON_IES_BRIGHTNESS, 42 | // Removed InputComponent as a blueprint addable component 43 | VER_UE4_REMOVE_INPUT_COMPONENTS_FROM_BLUEPRINTS, 44 | // Use an FMemberReference struct in UK2Node_Variable 45 | VER_UE4_VARK2NODE_USE_MEMBERREFSTRUCT, 46 | // Refactored material expression inputs for UMaterialExpressionSceneColor and UMaterialExpressionSceneDepth 47 | VER_UE4_REFACTOR_MATERIAL_EXPRESSION_SCENECOLOR_AND_SCENEDEPTH_INPUTS, 48 | // Spline meshes changed from Z forwards to configurable 49 | VER_UE4_SPLINE_MESH_ORIENTATION, 50 | // Added ReverbEffect asset type 51 | VER_UE4_REVERB_EFFECT_ASSET_TYPE, 52 | // changed max texcoords from 4 to 8 53 | VER_UE4_MAX_TEXCOORD_INCREASED, 54 | // static meshes changed to support SpeedTrees 55 | VER_UE4_SPEEDTREE_STATICMESH, 56 | // Landscape component reference between landscape component and collision component 57 | VER_UE4_LANDSCAPE_COMPONENT_LAZY_REFERENCES, 58 | // Refactored UK2Node_CallFunction to use FMemberReference 59 | VER_UE4_SWITCH_CALL_NODE_TO_USE_MEMBER_REFERENCE, 60 | // Added fixup step to remove skeleton class references from blueprint objects 61 | VER_UE4_ADDED_SKELETON_ARCHIVER_REMOVAL, 62 | // See above, take 2. 63 | VER_UE4_ADDED_SKELETON_ARCHIVER_REMOVAL_SECOND_TIME, 64 | // Making the skeleton class on blueprints transient 65 | VER_UE4_BLUEPRINT_SKEL_CLASS_TRANSIENT_AGAIN, 66 | // UClass knows if it's been cooked 67 | VER_UE4_ADD_COOKED_TO_UCLASS, 68 | // Deprecated static mesh thumbnail properties were removed 69 | VER_UE4_DEPRECATED_STATIC_MESH_THUMBNAIL_PROPERTIES_REMOVED, 70 | // Added collections in material shader map ids 71 | VER_UE4_COLLECTIONS_IN_SHADERMAPID, 72 | // Renamed some Movement Component properties, added PawnMovementComponent 73 | VER_UE4_REFACTOR_MOVEMENT_COMPONENT_HIERARCHY, 74 | // Swap UMaterialExpressionTerrainLayerSwitch::LayerUsed/LayerNotUsed the correct way round 75 | VER_UE4_FIX_TERRAIN_LAYER_SWITCH_ORDER, 76 | // Remove URB_ConstraintSetup 77 | VER_UE4_ALL_PROPS_TO_CONSTRAINTINSTANCE, 78 | // Low quality directional lightmaps 79 | VER_UE4_LOW_QUALITY_DIRECTIONAL_LIGHTMAPS, 80 | // Added NoiseEmitterComponent and removed related Pawn properties. 81 | VER_UE4_ADDED_NOISE_EMITTER_COMPONENT, 82 | // Add text component vertical alignment 83 | VER_UE4_ADD_TEXT_COMPONENT_VERTICAL_ALIGNMENT, 84 | // Added AssetImportData for FBX asset types, deprecating SourceFilePath and SourceFileTimestamp 85 | VER_UE4_ADDED_FBX_ASSET_IMPORT_DATA, 86 | // Remove LevelBodySetup from ULevel 87 | VER_UE4_REMOVE_LEVELBODYSETUP, 88 | // Refactor character crouching 89 | VER_UE4_REFACTOR_CHARACTER_CROUCH, 90 | // Trimmed down material shader debug information. 91 | VER_UE4_SMALLER_DEBUG_MATERIALSHADER_UNIFORM_EXPRESSIONS, 92 | // APEX Clothing 93 | VER_UE4_APEX_CLOTH, 94 | // Change Collision Channel to save only modified ones than all of them 95 | // @note!!! once we pass this CL, we can rename FCollisionResponseContainer enum values 96 | // we should rename to match ECollisionChannel 97 | VER_UE4_SAVE_COLLISIONRESPONSE_PER_CHANNEL, 98 | // Added Landscape Spline editor meshes 99 | VER_UE4_ADDED_LANDSCAPE_SPLINE_EDITOR_MESH, 100 | // Fixup input expressions for reading from refraction material attributes. 101 | VER_UE4_CHANGED_MATERIAL_REFACTION_TYPE, 102 | // Refactor projectile movement, along with some other movement component work. 103 | VER_UE4_REFACTOR_PROJECTILE_MOVEMENT, 104 | // Remove PhysicalMaterialProperty and replace with user defined enum 105 | VER_UE4_REMOVE_PHYSICALMATERIALPROPERTY, 106 | // Removed all compile outputs from FMaterial 107 | VER_UE4_PURGED_FMATERIAL_COMPILE_OUTPUTS, 108 | // Ability to save cooked PhysX meshes to Landscape 109 | VER_UE4_ADD_COOKED_TO_LANDSCAPE, 110 | // Change how input component consumption works 111 | VER_UE4_CONSUME_INPUT_PER_BIND, 112 | // Added new Graph based SoundClass Editor 113 | VER_UE4_SOUND_CLASS_GRAPH_EDITOR, 114 | // Fixed terrain layer node guids which was causing artifacts 115 | VER_UE4_FIXUP_TERRAIN_LAYER_NODES, 116 | // Added clamp min/max swap check to catch older materials 117 | VER_UE4_RETROFIT_CLAMP_EXPRESSIONS_SWAP, 118 | // Remove static/movable/stationary light classes 119 | VER_UE4_REMOVE_LIGHT_MOBILITY_CLASSES, 120 | // Refactor the way physics blending works to allow partial blending 121 | VER_UE4_REFACTOR_PHYSICS_BLENDING, 122 | // WorldLevelInfo: Added reference to parent level and streaming distance 123 | VER_UE4_WORLD_LEVEL_INFO_UPDATED, 124 | // Fixed cooking of skeletal/static meshes due to bad serialization logic 125 | VER_UE4_STATIC_SKELETAL_MESH_SERIALIZATION_FIX, 126 | // Removal of InterpActor and PhysicsActor 127 | VER_UE4_REMOVE_STATICMESH_MOBILITY_CLASSES, 128 | // Refactor physics transforms 129 | VER_UE4_REFACTOR_PHYSICS_TRANSFORMS, 130 | // Remove zero triangle sections from static meshes and compact material indices. 131 | VER_UE4_REMOVE_ZERO_TRIANGLE_SECTIONS, 132 | // Add param for deceleration in character movement instead of using acceleration. 133 | VER_UE4_CHARACTER_MOVEMENT_DECELERATION, 134 | // Made ACameraActor use a UCameraComponent for parameter storage, etc... 135 | VER_UE4_CAMERA_ACTOR_USING_CAMERA_COMPONENT, 136 | // Deprecated some pitch/roll properties in CharacterMovementComponent 137 | VER_UE4_CHARACTER_MOVEMENT_DEPRECATE_PITCH_ROLL, 138 | // Rebuild texture streaming data on load for uncooked builds 139 | VER_UE4_REBUILD_TEXTURE_STREAMING_DATA_ON_LOAD, 140 | // Add support for 32 bit index buffers for static meshes. 141 | VER_UE4_SUPPORT_32BIT_STATIC_MESH_INDICES, 142 | // Added streaming install ChunkID to AssetData and UPackage 143 | VER_UE4_ADDED_CHUNKID_TO_ASSETDATA_AND_UPACKAGE, 144 | // Add flag to control whether Character blueprints receive default movement bindings. 145 | VER_UE4_CHARACTER_DEFAULT_MOVEMENT_BINDINGS, 146 | // APEX Clothing LOD Info 147 | VER_UE4_APEX_CLOTH_LOD, 148 | // Added atmospheric fog texture data to be general 149 | VER_UE4_ATMOSPHERIC_FOG_CACHE_DATA, 150 | // Arrays serialize their inner's tags 151 | VAR_UE4_ARRAY_PROPERTY_INNER_TAGS, 152 | // Skeletal mesh index data is kept in memory in game to support mesh merging. 153 | VER_UE4_KEEP_SKEL_MESH_INDEX_DATA, 154 | // Added compatibility for the body instance collision change 155 | VER_UE4_BODYSETUP_COLLISION_CONVERSION, 156 | // Reflection capture cooking 157 | VER_UE4_REFLECTION_CAPTURE_COOKING, 158 | // Removal of DynamicTriggerVolume, DynamicBlockingVolume, DynamicPhysicsVolume 159 | VER_UE4_REMOVE_DYNAMIC_VOLUME_CLASSES, 160 | // Store an additional flag in the BodySetup to indicate whether there is any cooked data to load 161 | VER_UE4_STORE_HASCOOKEDDATA_FOR_BODYSETUP, 162 | // Changed name of RefractionBias to RefractionDepthBias. 163 | VER_UE4_REFRACTION_BIAS_TO_REFRACTION_DEPTH_BIAS, 164 | // Removal of SkeletalPhysicsActor 165 | VER_UE4_REMOVE_SKELETALPHYSICSACTOR, 166 | // PlayerController rotation input refactor 167 | VER_UE4_PC_ROTATION_INPUT_REFACTOR, 168 | // Landscape Platform Data cooking 169 | VER_UE4_LANDSCAPE_PLATFORMDATA_COOKING, 170 | // Added call for linking classes in CreateExport to ensure memory is initialized properly 171 | VER_UE4_CREATEEXPORTS_CLASS_LINKING_FOR_BLUEPRINTS, 172 | // Remove native component nodes from the blueprint SimpleConstructionScript 173 | VER_UE4_REMOVE_NATIVE_COMPONENTS_FROM_BLUEPRINT_SCS, 174 | // Removal of Single Node Instance 175 | VER_UE4_REMOVE_SINGLENODEINSTANCE, 176 | // Character movement braking changes 177 | VER_UE4_CHARACTER_BRAKING_REFACTOR, 178 | // Supported low quality lightmaps in volume samples 179 | VER_UE4_VOLUME_SAMPLE_LOW_QUALITY_SUPPORT, 180 | // Split bEnableTouchEvents out from bEnableClickEvents 181 | VER_UE4_SPLIT_TOUCH_AND_CLICK_ENABLES, 182 | // Health/Death refactor 183 | VER_UE4_HEALTH_DEATH_REFACTOR, 184 | // Moving USoundNodeEnveloper from UDistributionFloatConstantCurve to FRichCurve 185 | VER_UE4_SOUND_NODE_ENVELOPER_CURVE_CHANGE, 186 | // Moved SourceRadius to UPointLightComponent 187 | VER_UE4_POINT_LIGHT_SOURCE_RADIUS, 188 | // Scene capture actors based on camera actors. 189 | VER_UE4_SCENE_CAPTURE_CAMERA_CHANGE, 190 | // Moving SkeletalMesh shadow casting flag from LoD details to material 191 | VER_UE4_MOVE_SKELETALMESH_SHADOWCASTING, 192 | // Changing bytecode operators for creating arrays 193 | VER_UE4_CHANGE_SETARRAY_BYTECODE, 194 | // Material Instances overriding base material properties. 195 | VER_UE4_MATERIAL_INSTANCE_BASE_PROPERTY_OVERRIDES, 196 | // Combined top/bottom lightmap textures 197 | VER_UE4_COMBINED_LIGHTMAP_TEXTURES, 198 | // Forced material lightmass guids to be regenerated 199 | VER_UE4_BUMPED_MATERIAL_EXPORT_GUIDS, 200 | // Allow overriding of parent class input bindings 201 | VER_UE4_BLUEPRINT_INPUT_BINDING_OVERRIDES, 202 | // Fix up convex invalid transform 203 | VER_UE4_FIXUP_BODYSETUP_INVALID_CONVEX_TRANSFORM, 204 | // Fix up scale of physics stiffness and damping value 205 | VER_UE4_FIXUP_STIFFNESS_AND_DAMPING_SCALE, 206 | // Convert USkeleton and FBoneContrainer to using FReferenceSkeleton. 207 | VER_UE4_REFERENCE_SKELETON_REFACTOR, 208 | // Adding references to variable, function, and macro nodes to be able to update to renamed values 209 | VER_UE4_K2NODE_REFERENCEGUIDS, 210 | // Fix up the 0th bone's parent bone index. 211 | VER_UE4_FIXUP_ROOTBONE_PARENT, 212 | //Allow setting of TextRenderComponents size in world space. 213 | VER_UE4_TEXT_RENDER_COMPONENTS_WORLD_SPACE_SIZING, 214 | // Material Instances overriding base material properties #2. 215 | VER_UE4_MATERIAL_INSTANCE_BASE_PROPERTY_OVERRIDES_PHASE_2, 216 | // CLASS_Placeable becomes CLASS_NotPlaceable 217 | VER_UE4_CLASS_NOTPLACEABLE_ADDED, 218 | // Added LOD info list to a world tile description 219 | VER_UE4_WORLD_LEVEL_INFO_LOD_LIST, 220 | // CharacterMovement variable naming refactor 221 | VER_UE4_CHARACTER_MOVEMENT_VARIABLE_RENAMING_1, 222 | // FName properties containing sound names converted to FSlateSound properties 223 | VER_UE4_FSLATESOUND_CONVERSION, 224 | // Added ZOrder to a world tile description 225 | VER_UE4_WORLD_LEVEL_INFO_ZORDER, 226 | // Added flagging of localization gather requirement to packages 227 | VER_UE4_PACKAGE_REQUIRES_LOCALIZATION_GATHER_FLAGGING, 228 | // Preventing Blueprint Actor variables from having default values 229 | VER_UE4_BP_ACTOR_VARIABLE_DEFAULT_PREVENTING, 230 | // Preventing Blueprint Actor variables from having default values 231 | VER_UE4_TEST_ANIMCOMP_CHANGE, 232 | // Class as primary asset, name convention changed 233 | VER_UE4_EDITORONLY_BLUEPRINTS, 234 | // Custom serialization for FEdGraphPinType 235 | VER_UE4_EDGRAPHPINTYPE_SERIALIZATION, 236 | // Stop generating 'mirrored' cooked mesh for Brush and Model components 237 | VER_UE4_NO_MIRROR_BRUSH_MODEL_COLLISION, 238 | // Changed ChunkID to be an array of IDs. 239 | VER_UE4_CHANGED_CHUNKID_TO_BE_AN_ARRAY_OF_CHUNKIDS, 240 | // Worlds have been renamed from "TheWorld" to be named after the package containing them 241 | VER_UE4_WORLD_NAMED_AFTER_PACKAGE, 242 | // Added sky light component 243 | VER_UE4_SKY_LIGHT_COMPONENT, 244 | // Added Enable distance streaming flag to FWorldTileLayer 245 | VER_UE4_WORLD_LAYER_ENABLE_DISTANCE_STREAMING, 246 | // Remove visibility/zone information from UModel 247 | VER_UE4_REMOVE_ZONES_FROM_MODEL, 248 | // Fix base pose serialization 249 | VER_UE4_FIX_ANIMATIONBASEPOSE_SERIALIZATION, 250 | // Support for up to 8 skinning influences per vertex on skeletal meshes (on non-gpu vertices) 251 | VER_UE4_SUPPORT_8_BONE_INFLUENCES_SKELETAL_MESHES, 252 | // Add explicit bOverrideGravity to world settings 253 | VER_UE4_ADD_OVERRIDE_GRAVITY_FLAG, 254 | // Support for up to 8 skinning influences per vertex on skeletal meshes (on gpu vertices) 255 | VER_UE4_SUPPORT_GPUSKINNING_8_BONE_INFLUENCES, 256 | // Supporting nonuniform scale animation 257 | VER_UE4_ANIM_SUPPORT_NONUNIFORM_SCALE_ANIMATION, 258 | // Engine version is stored as a FEngineVersion object rather than changelist number 259 | VER_UE4_ENGINE_VERSION_OBJECT, 260 | // World assets now have RF_Public 261 | VER_UE4_PUBLIC_WORLDS, 262 | // Skeleton Guid 263 | VER_UE4_SKELETON_GUID_SERIALIZATION, 264 | // Character movement WalkableFloor refactor 265 | VER_UE4_CHARACTER_MOVEMENT_WALKABLE_FLOOR_REFACTOR, 266 | // Lights default to inverse squared 267 | VER_UE4_INVERSE_SQUARED_LIGHTS_DEFAULT, 268 | // Disabled SCRIPT_LIMIT_BYTECODE_TO_64KB 269 | VER_UE4_DISABLED_SCRIPT_LIMIT_BYTECODE, 270 | // Made remote role private, exposed bReplicates 271 | VER_UE4_PRIVATE_REMOTE_ROLE, 272 | // Fix up old foliage components to have static mobility (superseded by VER_UE4_FOLIAGE_MOVABLE_MOBILITY) 273 | VER_UE4_FOLIAGE_STATIC_MOBILITY, 274 | // Change BuildScale from a float to a vector 275 | VER_UE4_BUILD_SCALE_VECTOR, 276 | // After implementing foliage collision, need to disable collision on old foliage instances 277 | VER_UE4_FOLIAGE_COLLISION, 278 | // Added sky bent normal to indirect lighting cache 279 | VER_UE4_SKY_BENT_NORMAL, 280 | // Added cooking for landscape collision data 281 | VER_UE4_LANDSCAPE_COLLISION_DATA_COOKING, 282 | // Convert CPU tangent Z delta to vector from PackedNormal since we don't get any benefit other than memory 283 | // we still convert all to FVector in CPU time whenever any calculation 284 | VER_UE4_MORPHTARGET_CPU_TANGENTZDELTA_FORMATCHANGE, 285 | // Soft constraint limits will implicitly use the mass of the bodies 286 | VER_UE4_SOFT_CONSTRAINTS_USE_MASS, 287 | // Reflection capture data saved in packages 288 | VER_UE4_REFLECTION_DATA_IN_PACKAGES, 289 | // Fix up old foliage components to have movable mobility (superseded by VER_UE4_FOLIAGE_STATIC_LIGHTING_SUPPORT) 290 | VER_UE4_FOLIAGE_MOVABLE_MOBILITY, 291 | // Undo BreakMaterialAttributes changes as it broke old content 292 | VER_UE4_UNDO_BREAK_MATERIALATTRIBUTES_CHANGE, 293 | // Now Default custom profile name isn't NONE anymore due to copy/paste not working properly with it 294 | VER_UE4_ADD_CUSTOMPROFILENAME_CHANGE, 295 | // Permanently flip and scale material expression coordinates 296 | VER_UE4_FLIP_MATERIAL_COORDS, 297 | // PinSubCategoryMemberReference added to FEdGraphPinType 298 | VER_UE4_MEMBERREFERENCE_IN_PINTYPE, 299 | // Vehicles use Nm for Torque instead of cm and RPM instead of rad/s 300 | VER_UE4_VEHICLES_UNIT_CHANGE, 301 | // removes NANs from all animations when loaded 302 | // now importing should detect NaNs, so we should not have NaNs in source data 303 | VER_UE4_ANIMATION_REMOVE_NANS, 304 | // Change skeleton preview attached assets property type 305 | VER_UE4_SKELETON_ASSET_PROPERTY_TYPE_CHANGE, 306 | // Fix some blueprint variables that have the CPF_DisableEditOnTemplate flag set 307 | // when they shouldn't 308 | VER_UE4_FIX_BLUEPRINT_VARIABLE_FLAGS, 309 | // Vehicles use Nm for Torque instead of cm and RPM instead of rad/s part two (missed conversion for some variables 310 | VER_UE4_VEHICLES_UNIT_CHANGE2, 311 | // Changed order of interface class serialization 312 | VER_UE4_UCLASS_SERIALIZE_INTERFACES_AFTER_LINKING, 313 | // Change from LOD distances to display factors 314 | VER_UE4_STATIC_MESH_SCREEN_SIZE_LODS, 315 | // Requires test of material coords to ensure they're saved correctly 316 | VER_UE4_FIX_MATERIAL_COORDS, 317 | // Changed SpeedTree wind presets to v7 318 | VER_UE4_SPEEDTREE_WIND_V7, 319 | // NeedsLoadForEditorGame added 320 | VER_UE4_LOAD_FOR_EDITOR_GAME, 321 | // Manual serialization of FRichCurveKey to save space 322 | VER_UE4_SERIALIZE_RICH_CURVE_KEY, 323 | // Change the outer of ULandscapeMaterialInstanceConstants and Landscape-related textures to the level in which they reside 324 | VER_UE4_MOVE_LANDSCAPE_MICS_AND_TEXTURES_WITHIN_LEVEL, 325 | // FTexts have creation history data, removed Key, Namespaces, and SourceString 326 | VER_UE4_FTEXT_HISTORY, 327 | // Shift comments to the left to contain expressions properly 328 | VER_UE4_FIX_MATERIAL_COMMENTS, 329 | // Bone names stored as FName means that we can't guarantee the correct case on export, now we store a separate string for export purposes only 330 | VER_UE4_STORE_BONE_EXPORT_NAMES, 331 | // changed mesh emitter initial orientation to distribution 332 | VER_UE4_MESH_EMITTER_INITIAL_ORIENTATION_DISTRIBUTION, 333 | // Foliage on blueprints causes crashes 334 | VER_UE4_DISALLOW_FOLIAGE_ON_BLUEPRINTS, 335 | // change motors to use revolutions per second instead of rads/second 336 | VER_UE4_FIXUP_MOTOR_UNITS, 337 | // deprecated MovementComponent functions including "ModifiedMaxSpeed" et al 338 | VER_UE4_DEPRECATED_MOVEMENTCOMPONENT_MODIFIED_SPEEDS, 339 | // rename CanBeCharacterBase 340 | VER_UE4_RENAME_CANBECHARACTERBASE, 341 | // Change GameplayTagContainers to have FGameplayTags instead of FNames; Required to fix-up native serialization 342 | VER_UE4_GAMEPLAY_TAG_CONTAINER_TAG_TYPE_CHANGE, 343 | // Change from UInstancedFoliageSettings to UFoliageType, and change the api from being keyed on UStaticMesh* to UFoliageType* 344 | VER_UE4_FOLIAGE_SETTINGS_TYPE, 345 | // Lights serialize static shadow depth maps 346 | VER_UE4_STATIC_SHADOW_DEPTH_MAPS, 347 | // Add RF_Transactional to data assets, fixing undo problems when editing them 348 | VER_UE4_ADD_TRANSACTIONAL_TO_DATA_ASSETS, 349 | // Change LB_AlphaBlend to LB_WeightBlend in ELandscapeLayerBlendType 350 | VER_UE4_ADD_LB_WEIGHTBLEND, 351 | // Add root component to an foliage actor, all foliage cluster components will be attached to a root 352 | VER_UE4_ADD_ROOTCOMPONENT_TO_FOLIAGEACTOR, 353 | // FMaterialInstanceBasePropertyOverrides didn't use proper UObject serialize 354 | VER_UE4_FIX_MATERIAL_PROPERTY_OVERRIDE_SERIALIZE, 355 | // Addition of linear color sampler. color sample type is changed to linear sampler if source texture !sRGB 356 | VER_UE4_ADD_LINEAR_COLOR_SAMPLER, 357 | // Added StringAssetReferencesMap to support renames of FStringAssetReference properties. 358 | VER_UE4_ADD_STRING_ASSET_REFERENCES_MAP, 359 | // Apply scale from SCS RootComponent details in the Blueprint Editor to new actor instances at construction time 360 | VER_UE4_BLUEPRINT_USE_SCS_ROOTCOMPONENT_SCALE, 361 | // Changed level streaming to have a linear color since the visualization doesn't gamma correct. 362 | VER_UE4_LEVEL_STREAMING_DRAW_COLOR_TYPE_CHANGE, 363 | // Cleared end triggers from non-state anim notifies 364 | VER_UE4_CLEAR_NOTIFY_TRIGGERS, 365 | // Convert old curve names stored in anim assets into skeleton smartnames 366 | VER_UE4_SKELETON_ADD_SMARTNAMES, 367 | // Added the currency code field to FTextHistory_AsCurrency 368 | VER_UE4_ADDED_CURRENCY_CODE_TO_FTEXT, 369 | // Added support for C++11 enum classes 370 | VER_UE4_ENUM_CLASS_SUPPORT, 371 | // Fixup widget animation class 372 | VER_UE4_FIXUP_WIDGET_ANIMATION_CLASS, 373 | // USoundWave objects now contain details about compression scheme used. 374 | VER_UE4_SOUND_COMPRESSION_TYPE_ADDED, 375 | // Bodies will automatically weld when attached 376 | VER_UE4_AUTO_WELDING, 377 | // Rename UCharacterMovementComponent::bCrouchMovesCharacterDown 378 | VER_UE4_RENAME_CROUCHMOVESCHARACTERDOWN, 379 | // Lightmap parameters in FMeshBuildSettings 380 | VER_UE4_LIGHTMAP_MESH_BUILD_SETTINGS, 381 | // Rename SM3 to ES3_1 and updates featurelevel material node selector 382 | VER_UE4_RENAME_SM3_TO_ES3_1, 383 | // Deprecated separate style assets for use in UMG 384 | VER_UE4_DEPRECATE_UMG_STYLE_ASSETS, 385 | // Duplicating Blueprints will regenerate NodeGuids after this version 386 | VER_UE4_POST_DUPLICATE_NODE_GUID, 387 | // Rename USpringArmComponent::bUseControllerViewRotation to bUsePawnViewRotation, 388 | // Rename UCameraComponent::bUseControllerViewRotation to bUsePawnViewRotation (and change the default value) 389 | VER_UE4_RENAME_CAMERA_COMPONENT_VIEW_ROTATION, 390 | // Changed FName to be case preserving 391 | VER_UE4_CASE_PRESERVING_FNAME, 392 | // Rename USpringArmComponent::bUsePawnViewRotation to bUsePawnControlRotation 393 | // Rename UCameraComponent::bUsePawnViewRotation to bUsePawnControlRotation 394 | VER_UE4_RENAME_CAMERA_COMPONENT_CONTROL_ROTATION, 395 | // Fix bad refraction material attribute masks 396 | VER_UE4_FIX_REFRACTION_INPUT_MASKING, 397 | // A global spawn rate for emitters. 398 | VER_UE4_GLOBAL_EMITTER_SPAWN_RATE_SCALE, 399 | // Cleanup destructible mesh settings 400 | VER_UE4_CLEAN_DESTRUCTIBLE_SETTINGS, 401 | // CharacterMovementComponent refactor of AdjustUpperHemisphereImpact and deprecation of some associated vars. 402 | VER_UE4_CHARACTER_MOVEMENT_UPPER_IMPACT_BEHAVIOR, 403 | // Changed Blueprint math equality functions for vectors and rotators to operate as a "nearly" equals rather than "exact" 404 | VER_UE4_BP_MATH_VECTOR_EQUALITY_USES_EPSILON, 405 | // Static lighting support was re-added to foliage, and mobility was returned to static 406 | VER_UE4_FOLIAGE_STATIC_LIGHTING_SUPPORT, 407 | // Added composite fonts to Slate font info 408 | VER_UE4_SLATE_COMPOSITE_FONTS, 409 | // Remove UDEPRECATED_SaveGameSummary, required for UWorld::Serialize 410 | VER_UE4_REMOVE_SAVEGAMESUMMARY, 411 | 412 | //Remove bodyseutp serialization from skeletal mesh component 413 | VER_UE4_REMOVE_SKELETALMESH_COMPONENT_BODYSETUP_SERIALIZATION, 414 | // Made Slate font data use bulk data to store the embedded font data 415 | VER_UE4_SLATE_BULK_FONT_DATA, 416 | // Add new friction behavior in ProjectileMovementComponent. 417 | VER_UE4_ADD_PROJECTILE_FRICTION_BEHAVIOR, 418 | // Add axis settings enum to MovementComponent. 419 | VER_UE4_MOVEMENTCOMPONENT_AXIS_SETTINGS, 420 | // Switch to new interactive comments, requires boundry conversion to preserve previous states 421 | VER_UE4_GRAPH_INTERACTIVE_COMMENTBUBBLES, 422 | // Landscape serializes physical materials for collision objects 423 | VER_UE4_LANDSCAPE_SERIALIZE_PHYSICS_MATERIALS, 424 | // Rename Visiblity on widgets to Visibility 425 | VER_UE4_RENAME_WIDGET_VISIBILITY, 426 | // add track curves for animation 427 | VER_UE4_ANIMATION_ADD_TRACKCURVES, 428 | // Removed BranchingPoints from AnimMontages and converted them to regular AnimNotifies. 429 | VER_UE4_MONTAGE_BRANCHING_POINT_REMOVAL, 430 | // Enforce const-correctness in Blueprint implementations of native C++ const class methods 431 | VER_UE4_BLUEPRINT_ENFORCE_CONST_IN_FUNCTION_OVERRIDES, 432 | // Added pivot to widget components, need to load old versions as a 0,0 pivot, new default is 0.5,0.5 433 | VER_UE4_ADD_PIVOT_TO_WIDGET_COMPONENT, 434 | // Added finer control over when AI Pawns are automatically possessed. Also renamed Pawn.AutoPossess to Pawn.AutoPossessPlayer indicate this was a setting for players and not AI. 435 | VER_UE4_PAWN_AUTO_POSSESS_AI, 436 | // Added serialization of timezone to FTextHistory for AsDate operations. 437 | VER_UE4_FTEXT_HISTORY_DATE_TIMEZONE, 438 | // Sort ActiveBoneIndices on lods so that we can avoid doing it at run time 439 | VER_UE4_SORT_ACTIVE_BONE_INDICES, 440 | // Added per-frame material uniform expressions 441 | VER_UE4_PERFRAME_MATERIAL_UNIFORM_EXPRESSIONS, 442 | // Make MikkTSpace the default tangent space calculation method for static meshes. 443 | VER_UE4_MIKKTSPACE_IS_DEFAULT, 444 | // Only applies to cooked files, grass cooking support. 445 | VER_UE4_LANDSCAPE_GRASS_COOKING, 446 | // Fixed code for using the bOrientMeshEmitters property. 447 | VER_UE4_FIX_SKEL_VERT_ORIENT_MESH_PARTICLES, 448 | // Do not change landscape section offset on load under world composition 449 | VER_UE4_LANDSCAPE_STATIC_SECTION_OFFSET, 450 | // New options for navigation data runtime generation (static, modifiers only, dynamic) 451 | VER_UE4_ADD_MODIFIERS_RUNTIME_GENERATION, 452 | // Tidied up material's handling of masked blend mode. 453 | VER_UE4_MATERIAL_MASKED_BLENDMODE_TIDY, 454 | // Original version of VER_UE4_MERGED_ADD_MODIFIERS_RUNTIME_GENERATION_TO_4_7; renumbered to prevent blocking promotion in main. 455 | VER_UE4_MERGED_ADD_MODIFIERS_RUNTIME_GENERATION_TO_4_7_DEPRECATED, 456 | // Original version of VER_UE4_AFTER_MERGED_ADD_MODIFIERS_RUNTIME_GENERATION_TO_4_7; renumbered to prevent blocking promotion in main. 457 | VER_UE4_AFTER_MERGED_ADD_MODIFIERS_RUNTIME_GENERATION_TO_4_7_DEPRECATED, 458 | // After merging VER_UE4_ADD_MODIFIERS_RUNTIME_GENERATION into 4.7 branch 459 | VER_UE4_MERGED_ADD_MODIFIERS_RUNTIME_GENERATION_TO_4_7, 460 | // After merging VER_UE4_ADD_MODIFIERS_RUNTIME_GENERATION into 4.7 branch 461 | VER_UE4_AFTER_MERGING_ADD_MODIFIERS_RUNTIME_GENERATION_TO_4_7, 462 | // Landscape grass weightmap data is now generated in the editor and serialized. 463 | VER_UE4_SERIALIZE_LANDSCAPE_GRASS_DATA, 464 | // New property to optionally prevent gpu emitters clearing existing particles on Init(). 465 | VER_UE4_OPTIONALLY_CLEAR_GPU_EMITTERS_ON_INIT, 466 | // Also store the Material guid with the landscape grass data 467 | VER_UE4_SERIALIZE_LANDSCAPE_GRASS_DATA_MATERIAL_GUID, 468 | // Make sure that all template components from blueprint generated classes are flagged as public 469 | VER_UE4_BLUEPRINT_GENERATED_CLASS_COMPONENT_TEMPLATES_PUBLIC, 470 | // Split out creation method on ActorComponents to distinguish between native, instance, and simple or user construction script 471 | VER_UE4_ACTOR_COMPONENT_CREATION_METHOD, 472 | // K2Node_Event now uses FMemberReference for handling references 473 | VER_UE4_K2NODE_EVENT_MEMBER_REFERENCE, 474 | // FPropertyTag stores GUID of struct 475 | VER_UE4_STRUCT_GUID_IN_PROPERTY_TAG, 476 | // Remove unused UPolys from UModel cooked content 477 | VER_UE4_REMOVE_UNUSED_UPOLYS_FROM_UMODEL, 478 | // This doesn't do anything except trigger a rebuild on HISMC cluster trees, in this case to get a good "occlusion query" level 479 | VER_UE4_REBUILD_HIERARCHICAL_INSTANCE_TREES, 480 | // Package summary includes an CompatibleWithEngineVersion field, separately to the version it's saved with 481 | VER_UE4_PACKAGE_SUMMARY_HAS_COMPATIBLE_ENGINE_VERSION, 482 | // Track UCS modified properties on Actor Components 483 | VER_UE4_TRACK_UCS_MODIFIED_PROPERTIES, 484 | // Allowed landscape spline meshes to be stored into landscape streaming levels rather than the spline's level 485 | VER_UE4_LANDSCAPE_SPLINE_CROSS_LEVEL_MESHES, 486 | // Deprecate the variables used for sizing in the designer on UUserWidget 487 | VER_UE4_DEPRECATE_USER_WIDGET_DESIGN_SIZE, 488 | // Make the editor views array dynamically sized 489 | VER_UE4_ADD_EDITOR_VIEWS, 490 | // Updated foliage to work with either FoliageType assets or blueprint classes 491 | VER_UE4_FOLIAGE_WITH_ASSET_OR_CLASS, 492 | // Allows PhysicsSerializer to serialize shapes and actors for faster load times 493 | VER_UE4_BODYINSTANCE_BINARY_SERIALIZATION, 494 | // Added fastcall data serialization directly in UFunction 495 | VER_UE4_SERIALIZE_BLUEPRINT_EVENTGRAPH_FASTCALLS_IN_UFUNCTION, 496 | // Changes to USplineComponent and FInterpCurve 497 | VER_UE4_INTERPCURVE_SUPPORTS_LOOPING, 498 | // Material Instances overriding base material LOD transitions 499 | VER_UE4_MATERIAL_INSTANCE_BASE_PROPERTY_OVERRIDES_DITHERED_LOD_TRANSITION, 500 | // Serialize ES2 textures separately rather than overwriting the properties used on other platforms 501 | VER_UE4_SERIALIZE_LANDSCAPE_ES2_TEXTURES, 502 | // Constraint motor velocity is broken into per-component 503 | VER_UE4_CONSTRAINT_INSTANCE_MOTOR_FLAGS, 504 | // Serialize bIsConst in FEdGraphPinType 505 | VER_UE4_SERIALIZE_PINTYPE_CONST, 506 | // Change UMaterialFunction::LibraryCategories to LibraryCategoriesText (old assets were saved before auto-conversion of UArrayProperty was possible) 507 | VER_UE4_LIBRARY_CATEGORIES_AS_FTEXT, 508 | // Check for duplicate exports while saving packages. 509 | VER_UE4_SKIP_DUPLICATE_EXPORTS_ON_SAVE_PACKAGE, 510 | // Pre-gathering of gatherable, localizable text in packages to optimize text gathering operation times 511 | VER_UE4_SERIALIZE_TEXT_IN_PACKAGES, 512 | // Added pivot to widget components, need to load old versions as a 0,0 pivot, new default is 0.5,0.5 513 | VER_UE4_ADD_BLEND_MODE_TO_WIDGET_COMPONENT, 514 | // Added lightmass primitive setting 515 | VER_UE4_NEW_LIGHTMASS_PRIMITIVE_SETTING, 516 | // Deprecate NoZSpring property on spring nodes to be replaced with TranslateZ property 517 | VER_UE4_REPLACE_SPRING_NOZ_PROPERTY, 518 | // Keep enums tight and serialize their values as pairs of FName and value. Don't insert dummy values. 519 | VER_UE4_TIGHTLY_PACKED_ENUMS, 520 | // Changed Asset import data to serialize file meta data as JSON 521 | VER_UE4_ASSET_IMPORT_DATA_AS_JSON, 522 | // Legacy gamma support for textures. 523 | VER_UE4_TEXTURE_LEGACY_GAMMA, 524 | // Added WithSerializer for basic native structures like FVector, FColor etc to improve serialization performance 525 | VER_UE4_ADDED_NATIVE_SERIALIZATION_FOR_IMMUTABLE_STRUCTURES, 526 | // Deprecated attributes that override the style on UMG widgets 527 | VER_UE4_DEPRECATE_UMG_STYLE_OVERRIDES, 528 | // Shadowmap penumbra size stored 529 | VER_UE4_STATIC_SHADOWMAP_PENUMBRA_SIZE, 530 | // Fix BC on Niagara effects from the data object and dev UI changes. 531 | VER_UE4_NIAGARA_DATA_OBJECT_DEV_UI_FIX, 532 | // Fixed the default orientation of widget component so it faces down +x 533 | VER_UE4_FIXED_DEFAULT_ORIENTATION_OF_WIDGET_COMPONENT, 534 | // Removed bUsedWithUI flag from UMaterial and replaced it with a new material domain for UI 535 | VER_UE4_REMOVED_MATERIAL_USED_WITH_UI_FLAG, 536 | // Added braking friction separate from turning friction. 537 | VER_UE4_CHARACTER_MOVEMENT_ADD_BRAKING_FRICTION, 538 | // Removed TTransArrays from UModel 539 | VER_UE4_BSP_UNDO_FIX, 540 | // Added default value to dynamic parameter. 541 | VER_UE4_DYNAMIC_PARAMETER_DEFAULT_VALUE, 542 | // Added ExtendedBounds to StaticMesh 543 | VER_UE4_STATIC_MESH_EXTENDED_BOUNDS, 544 | // Added non-linear blending to anim transitions, deprecating old types 545 | VER_UE4_ADDED_NON_LINEAR_TRANSITION_BLENDS, 546 | // AO Material Mask texture 547 | VER_UE4_AO_MATERIAL_MASK, 548 | // Replaced navigation agents selection with single structure 549 | VER_UE4_NAVIGATION_AGENT_SELECTOR, 550 | // Mesh particle collisions consider particle size. 551 | VER_UE4_MESH_PARTICLE_COLLISIONS_CONSIDER_PARTICLE_SIZE, 552 | // Adjacency buffer building no longer automatically handled based on triangle count, user-controlled 553 | VER_UE4_BUILD_MESH_ADJ_BUFFER_FLAG_EXPOSED, 554 | // Change the default max angular velocity 555 | VER_UE4_MAX_ANGULAR_VELOCITY_DEFAULT, 556 | // Build Adjacency index buffer for clothing tessellation 557 | VER_UE4_APEX_CLOTH_TESSELLATION, 558 | // Added DecalSize member, solved backward compatibility 559 | VER_UE4_DECAL_SIZE, 560 | // Keep only package names in StringAssetReferencesMap 561 | VER_UE4_KEEP_ONLY_PACKAGE_NAMES_IN_STRING_ASSET_REFERENCES_MAP, 562 | // Support sound cue not saving out editor only data 563 | VER_UE4_COOKED_ASSETS_IN_EDITOR_SUPPORT, 564 | // Updated dialogue wave localization gathering logic. 565 | VER_UE4_DIALOGUE_WAVE_NAMESPACE_AND_CONTEXT_CHANGES, 566 | // Renamed MakeRot MakeRotator and rearranged parameters. 567 | VER_UE4_MAKE_ROT_RENAME_AND_REORDER, 568 | // K2Node_Variable will properly have the VariableReference Guid set if available 569 | VER_UE4_K2NODE_VAR_REFERENCEGUIDS, 570 | // Added support for sound concurrency settings structure and overrides 571 | VER_UE4_SOUND_CONCURRENCY_PACKAGE, 572 | // Changing the default value for focusable user widgets to false 573 | VER_UE4_USERWIDGET_DEFAULT_FOCUSABLE_FALSE, 574 | // Custom event nodes implicitly set 'const' on array and non-array pass-by-reference input params 575 | VER_UE4_BLUEPRINT_CUSTOM_EVENT_CONST_INPUT, 576 | // Renamed HighFrequencyGain to LowPassFilterFrequency 577 | VER_UE4_USE_LOW_PASS_FILTER_FREQ, 578 | // UAnimBlueprintGeneratedClass can be replaced by a dynamic class. Use TSubclassOf instead. 579 | VER_UE4_NO_ANIM_BP_CLASS_IN_GAMEPLAY_CODE, 580 | // The SCS keeps a list of all nodes in its hierarchy rather than recursively building it each time it is requested 581 | VER_UE4_SCS_STORES_ALLNODES_ARRAY, 582 | // Moved StartRange and EndRange in UFbxAnimSequenceImportData to use FInt32Interval 583 | VER_UE4_FBX_IMPORT_DATA_RANGE_ENCAPSULATION, 584 | // Adding a new root scene component to camera component 585 | VER_UE4_CAMERA_COMPONENT_ATTACH_TO_ROOT, 586 | // Updating custom material expression nodes for instanced stereo implementation 587 | VER_UE4_INSTANCED_STEREO_UNIFORM_UPDATE, 588 | // Texture streaming min and max distance to handle HLOD 589 | VER_UE4_STREAMABLE_TEXTURE_MIN_MAX_DISTANCE, 590 | // Fixing up invalid struct-to-struct pin connections by injecting available conversion nodes 591 | VER_UE4_INJECT_BLUEPRINT_STRUCT_PIN_CONVERSION_NODES, 592 | // Saving tag data for Array Property's inner property 593 | VER_UE4_INNER_ARRAY_TAG_INFO, 594 | // Fixed duplicating slot node names in skeleton due to skeleton preload on compile 595 | VER_UE4_FIX_SLOT_NAME_DUPLICATION, 596 | // Texture streaming using AABBs instead of Spheres 597 | VER_UE4_STREAMABLE_TEXTURE_AABB, 598 | // FPropertyTag stores GUID of property 599 | VER_UE4_PROPERTY_GUID_IN_PROPERTY_TAG, 600 | // Name table hashes are calculated and saved out rather than at load time 601 | VER_UE4_NAME_HASHES_SERIALIZED, 602 | // Updating custom material expression nodes for instanced stereo implementation refactor 603 | VER_UE4_INSTANCED_STEREO_UNIFORM_REFACTOR, 604 | // Added compression to the shader resource for memory savings 605 | VER_UE4_COMPRESSED_SHADER_RESOURCES, 606 | // Cooked files contain the dependency graph for the event driven loader (the serialization is largely independent of the use of the new loader) 607 | VER_UE4_PRELOAD_DEPENDENCIES_IN_COOKED_EXPORTS, 608 | // Cooked files contain the TemplateIndex used by the event driven loader (the serialization is largely independent of the use of the new loader, i.e. this will be null if cooking for the old loader) 609 | VER_UE4_TemplateIndex_IN_COOKED_EXPORTS, // 4.14 base version 610 | // FPropertyTag includes contained type(s) for Set and Map properties: 611 | VER_UE4_PROPERTY_TAG_SET_MAP_SUPPORT, 612 | // Added SearchableNames to the package summary and asset registry 613 | VER_UE4_ADDED_SEARCHABLE_NAMES, 614 | // Increased size of SerialSize and SerialOffset in export map entries to 64 bit, allow support for bigger files 615 | VER_UE4_64BIT_EXPORTMAP_SERIALSIZES, 616 | // Sky light stores IrradianceMap for mobile renderer. 617 | VER_UE4_SKYLIGHT_MOBILE_IRRADIANCE_MAP, 618 | // Added flag to control sweep behavior while walking in UCharacterMovementComponent. 619 | VER_UE4_ADDED_SWEEP_WHILE_WALKING_FLAG, 620 | // StringAssetReference changed to SoftObjectPath and swapped to serialize as a name+string instead of a string 621 | VER_UE4_ADDED_SOFT_OBJECT_PATH, 622 | 623 | // ------------------------------------------------------ 624 | // - this needs to be the last line (see note below) 625 | VER_UE4_AUTOMATIC_VERSION_PLUS_ONE, 626 | VER_UE4_AUTOMATIC_VERSION = VER_UE4_AUTOMATIC_VERSION_PLUS_ONE - 1 627 | }; 628 | 629 | 630 | private static Dictionary versionDictionary = new Dictionary() 631 | { 632 | { "4.0", EUnrealEngineObjectUE4Version.VER_UE4_PRIVATE_REMOTE_ROLE }, 633 | { "4.1", EUnrealEngineObjectUE4Version.VER_UE4_UNDO_BREAK_MATERIALATTRIBUTES_CHANGE }, 634 | { "4.2", EUnrealEngineObjectUE4Version.VER_UE4_FIX_MATERIAL_COORDS }, 635 | { "4.3", EUnrealEngineObjectUE4Version.VER_UE4_FIX_MATERIAL_PROPERTY_OVERRIDE_SERIALIZE }, 636 | { "4.4", EUnrealEngineObjectUE4Version.VER_UE4_BLUEPRINT_USE_SCS_ROOTCOMPONENT_SCALE }, 637 | { "4.5", EUnrealEngineObjectUE4Version.VER_UE4_RENAME_CAMERA_COMPONENT_CONTROL_ROTATION }, 638 | { "4.6", EUnrealEngineObjectUE4Version.VER_UE4_MOVEMENTCOMPONENT_AXIS_SETTINGS }, 639 | { "4.7", EUnrealEngineObjectUE4Version.VER_UE4_AFTER_MERGING_ADD_MODIFIERS_RUNTIME_GENERATION_TO_4_7 }, // in 4.7 that's VER_UE4_MOVEMENTCOMPONENT_UPDATEDSCENECOMPONENT 640 | { "4.8", EUnrealEngineObjectUE4Version.VER_UE4_SERIALIZE_BLUEPRINT_EVENTGRAPH_FASTCALLS_IN_UFUNCTION }, 641 | { "4.9", EUnrealEngineObjectUE4Version.VER_UE4_APEX_CLOTH_TESSELLATION }, 642 | // { "4.10", EUnrealEngineObjectUE4Version.VER_UE4_APEX_CLOTH_TESSELLATION }, 643 | { "4.11", EUnrealEngineObjectUE4Version.VER_UE4_STREAMABLE_TEXTURE_MIN_MAX_DISTANCE }, 644 | { "4.12", EUnrealEngineObjectUE4Version.VER_UE4_NAME_HASHES_SERIALIZED }, 645 | { "4.13", EUnrealEngineObjectUE4Version.VER_UE4_INSTANCED_STEREO_UNIFORM_REFACTOR }, 646 | { "4.14", EUnrealEngineObjectUE4Version.VER_UE4_TemplateIndex_IN_COOKED_EXPORTS }, 647 | { "4.15", EUnrealEngineObjectUE4Version.VER_UE4_ADDED_SEARCHABLE_NAMES }, 648 | { "4.16", EUnrealEngineObjectUE4Version.VER_UE4_ADDED_SWEEP_WHILE_WALKING_FLAG }, 649 | // { "4.17", EUnrealEngineObjectUE4Version.VER_UE4_ADDED_SWEEP_WHILE_WALKING_FLAG }, 650 | // { "4.18", EUnrealEngineObjectUE4Version.VER_UE4_ADDED_SOFT_OBJECT_PATH }, 651 | }; 652 | } 653 | } 654 | -------------------------------------------------------------------------------- /UE4View/UE4/Pak/FFileIndex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | 6 | namespace UE4View.UE4.Pak 7 | { 8 | public class FFileIndex 9 | { 10 | public FFileIndex Add(string Dir, FPakEntry Entry) 11 | { 12 | var paths = Dir.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); 13 | if (paths.Length > 1) 14 | { 15 | if (!Directories.ContainsKey(paths[0])) 16 | Directories.Add(paths[0], new FFileIndex()); 17 | 18 | Directories[paths[0]].Add(Path.Combine(paths.Skip(1).ToArray()), Entry); 19 | } 20 | else 21 | Files.Add(Dir, Entry); 22 | return this; 23 | } 24 | 25 | public SortedDictionary Directories = new SortedDictionary(); 26 | 27 | public SortedDictionary Files = new SortedDictionary(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /UE4View/UE4/Pak/FPakEntry.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UE4View.UE4.Pak 4 | { 5 | public class FPakEntry : USerializable 6 | { 7 | public enum ECompressionFlags 8 | { 9 | /** No compression */ 10 | COMPRESS_None = 0x00, 11 | /** Compress with ZLIB */ 12 | COMPRESS_ZLIB = 0x01, 13 | /** Compress with GZIP */ 14 | COMPRESS_GZIP = 0x02, 15 | /** Prefer compression that compresses smaller (ONLY VALID FOR COMPRESSION) */ 16 | COMPRESS_BiasMemory = 0x10, 17 | /** Prefer compression that compresses faster (ONLY VALID FOR COMPRESSION) */ 18 | COMPRESS_BiasSpeed = 0x20, 19 | }; 20 | public class FPakCompressedBlock : USerializable 21 | { 22 | public long CompressionStart; 23 | public long CompressionEnd; 24 | 25 | public override FArchive Serialize(FArchive reader) 26 | { 27 | CompressionStart = reader.ToInt64(); 28 | CompressionEnd = reader.ToInt64(); 29 | return reader; 30 | } 31 | } 32 | /** Offset into pak file where the file is stored.*/ 33 | public long Offset; 34 | /** Serialized file size. */ 35 | public long Size; 36 | /** Uncompressed file size. */ 37 | public long UncompressedSize; 38 | /** Compression method. */ 39 | public ECompressionFlags CompressionMethod; 40 | /** File SHA1 value. */ 41 | byte[] Hash = new byte[20]; 42 | /** Array of compression blocks that describe how to decompress this pak entry. */ 43 | public List CompressionBlocks; 44 | /** Size of a compressed block in the file. */ 45 | public uint CompressionBlockSize; 46 | /** True is file is encrypted. */ 47 | public byte bEncrypted; 48 | 49 | public long GetSerializedSize(int version) 50 | { 51 | long SerializedSize = sizeof(long) + sizeof(long) + sizeof(long) + sizeof(int) + 20; 52 | if(version >= (int)FPakInfo.PakVersion.CompressionEncryption) 53 | { 54 | SerializedSize += sizeof(byte) + sizeof(uint); 55 | if(CompressionMethod != ECompressionFlags.COMPRESS_None) 56 | { 57 | // Size += sizeof(FPakCompressedBlock) * BlockCount + ArrayProperty -> Count 58 | SerializedSize += (sizeof(long) * 2) * CompressionBlocks.Count + sizeof(int); 59 | } 60 | } 61 | if(version < (int)FPakInfo.PakVersion.NoTimestamps) 62 | { 63 | SerializedSize += sizeof(long); 64 | } 65 | return SerializedSize; 66 | } 67 | 68 | public override FArchive Serialize(FArchive reader) 69 | { 70 | Offset = reader.ToInt64() + GetSerializedSize(reader.Version); // Offset + PakHeader -> OffsetInPak 71 | Size = reader.ToInt64(); 72 | UncompressedSize = reader.ToInt64(); 73 | CompressionMethod = (ECompressionFlags)reader.ToInt32(); 74 | if (reader.Version <= (int)FPakInfo.PakVersion.Initial) 75 | { 76 | reader.ToInt64(); // FDateTime Timestamp 77 | } 78 | reader.ToByteArray(20).CopyTo(Hash, 0); 79 | if (reader.Version >= (int)FPakInfo.PakVersion.CompressionEncryption) 80 | { 81 | if (CompressionMethod != ECompressionFlags.COMPRESS_None) 82 | CompressionBlocks = reader.ToArray(); 83 | 84 | bEncrypted = reader.ToByte(); 85 | CompressionBlockSize = reader.ToUInt32(); 86 | } 87 | return reader; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /UE4View/UE4/Pak/FPakFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | 6 | namespace UE4View.UE4.Pak 7 | { 8 | public class FPakFile 9 | { 10 | public FPakFile(string FileName) 11 | { 12 | if (File.Exists(FileName)) 13 | { 14 | OriginalFileName = Path.GetFileName(FileName); 15 | CreationTime = File.GetCreationTime(FileName); 16 | AccessTime = File.GetLastAccessTime(FileName); 17 | WriteTime = File.GetLastWriteTime(FileName); 18 | stream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read); 19 | if(stream != null) 20 | { 21 | ReadPakInfo(); 22 | if (Info.Magic == FPakInfo.PakFile_Magic && Info.bEncryptedIndex == false) 23 | { 24 | ReadPakIndex(); 25 | } 26 | } 27 | } 28 | } 29 | 30 | private byte[] ReadStreamData(long Offset, long Size) 31 | { 32 | if (stream != null) 33 | { 34 | var data = new byte[Size]; 35 | int streamoffset = 0; 36 | stream.Seek(Offset, Offset < 0 ? SeekOrigin.End : SeekOrigin.Begin); 37 | do 38 | { 39 | streamoffset += stream.Read(data, streamoffset, (int)Size); 40 | if (streamoffset == 0) 41 | break; 42 | } while (streamoffset != Size); 43 | 44 | return data; 45 | } 46 | return null; 47 | } 48 | 49 | private void ReadPakInfo() 50 | { 51 | var InfoSize = FPakInfo.GetSerializedSize(); 52 | var InfoData = ReadStreamData(-InfoSize, InfoSize); 53 | stream.Seek(0, SeekOrigin.Begin); 54 | Info = new FPakInfo(InfoData); 55 | } 56 | private void ReadPakIndex() 57 | { 58 | var IndexData = ReadStreamData(Info.IndexOffset, Info.IndexSize); 59 | var reader = new FArchive(IndexData); 60 | reader.Version = Info.Version; 61 | MountPoint = reader.ToFString(); 62 | int NumEntries = reader.ToInt32(); 63 | for (int i = 0; i < NumEntries; i++) 64 | { 65 | string FileName = reader.ToFString(); 66 | var entry = new FPakEntry(); 67 | entry.Serialize(reader); 68 | AbsoluteIndex.Add(FileName, entry); 69 | Index.Add(FileName, entry); 70 | } 71 | return; 72 | } 73 | 74 | public byte[] ReadEntry(object entry) 75 | { 76 | return ReadEntry(entry as FPakEntry); 77 | } 78 | public byte[] ReadEntry(FPakEntry entry) 79 | { 80 | if (entry != null) 81 | { 82 | if(entry.CompressionMethod == FPakEntry.ECompressionFlags.COMPRESS_None) 83 | return ReadStreamData(entry.Offset, entry.Size); 84 | else 85 | { 86 | var decompressed = new byte[entry.UncompressedSize]; 87 | int Index = 0; 88 | int offset = 0; 89 | foreach(var block in entry.CompressionBlocks) 90 | { 91 | var CompressedBlockSize = block.CompressionEnd - block.CompressionStart; 92 | var UncompressedBlockSize = Math.Min(entry.UncompressedSize - entry.CompressionBlockSize*Index, entry.CompressionBlockSize); 93 | var data = ReadStreamData(block.CompressionStart, CompressedBlockSize); 94 | 95 | if (entry.CompressionMethod == FPakEntry.ECompressionFlags.COMPRESS_ZLIB) 96 | { 97 | using (var compressed = new MemoryStream(data, 2, data.Length - 2)) // skip 2 bytes for zlib specification 98 | { 99 | using (var decstream = new System.IO.Compression.DeflateStream(compressed, System.IO.Compression.CompressionMode.Decompress)) 100 | { 101 | offset += decstream.Read(decompressed, offset, (int)UncompressedBlockSize); 102 | } 103 | } 104 | } 105 | // TODO: Test if GZip decompresses fine. 106 | else if (entry.CompressionMethod == FPakEntry.ECompressionFlags.COMPRESS_GZIP) 107 | { 108 | using (var compressed = new MemoryStream(data)) // skip 2 bytes for zlib specification 109 | { 110 | using (var decstream = new System.IO.Compression.GZipStream(compressed, System.IO.Compression.CompressionMode.Decompress)) 111 | { 112 | offset += decstream.Read(decompressed, offset, (int)UncompressedBlockSize); 113 | } 114 | } 115 | } 116 | Index++; 117 | } 118 | return decompressed; 119 | } 120 | } 121 | return null; 122 | } 123 | 124 | /// 125 | /// Retrieves asset contents by its full path. Supports wildcard '*'. 126 | /// 127 | /// Path to asset 128 | /// Requested asset content as byte array if found. Null otherwise 129 | public byte[] ReadEntryByName(string name) 130 | { 131 | var pathparts = name.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); 132 | return ReadEntry(RecursiveSearch(pathparts, Index)); 133 | } 134 | public byte[] ReadEntryByAbsoluteName(string name) 135 | { 136 | if (AbsoluteIndex.ContainsKey(name)) 137 | return ReadEntry(AbsoluteIndex[name]); 138 | else 139 | return null; 140 | } 141 | 142 | private FPakEntry RecursiveSearch(string[] parts, FFileIndex dir) 143 | { 144 | if (parts.Length == 1) 145 | { 146 | // final path element 147 | if (parts[0] != "*") 148 | { 149 | return dir.Files 150 | .Where(kv => kv.Key == parts[0]) 151 | .Select(kv => kv.Value) 152 | .SingleOrDefault(); 153 | } 154 | 155 | 156 | } 157 | else if (parts[0] == "*") 158 | { 159 | foreach (var kv in dir.Directories) 160 | { 161 | var found = RecursiveSearch(parts.Skip(1).ToArray(), kv.Value); 162 | if (found != null) 163 | return found; 164 | } 165 | } 166 | else 167 | { 168 | var idx = dir.Directories 169 | .Where(kv => kv.Key == parts[0]) 170 | .Select(kv => kv.Value) 171 | .SingleOrDefault(); 172 | return RecursiveSearch(parts.Skip(1).ToArray(), idx); 173 | } 174 | return null; 175 | } 176 | 177 | public void Close() 178 | { 179 | stream.Close(); 180 | } 181 | public string OriginalFileName { get; private set; } 182 | 183 | public FPakInfo Info { get; private set; } 184 | public FFileIndex Index { get; } = new FFileIndex(); 185 | public Dictionary AbsoluteIndex { get; } = new Dictionary(); 186 | public string MountPoint { get; private set; } 187 | 188 | public DateTime CreationTime { get; private set; } 189 | public DateTime AccessTime { get; private set; } 190 | public DateTime WriteTime { get; private set; } 191 | 192 | internal FileStream stream = null; 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /UE4View/UE4/Pak/FPakInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UE4View.UE4.Pak 4 | { 5 | public class FPakInfo 6 | { 7 | /** Magic number to use in header */ 8 | public const long PakFile_Magic = 0x5A6F12E1; 9 | /** Size of cached data. */ 10 | const long MaxChunkDataSize = 64 * 1024; 11 | 12 | /** Version numbers. */ 13 | public enum PakVersion 14 | { 15 | Initial = 1, 16 | NoTimestamps = 2, 17 | CompressionEncryption = 3, 18 | IndexEncryption = 4, 19 | 20 | Latest = IndexEncryption 21 | }; 22 | 23 | /** Pak file magic value. */ 24 | public uint Magic; 25 | /** Pak file version. */ 26 | public int Version; 27 | /** Offset to pak file index. */ 28 | public long IndexOffset; 29 | /** Size (in bytes) of pak file index. */ 30 | public long IndexSize; 31 | /** Index SHA1 value. */ 32 | public byte[] IndexHash = new byte[20]; 33 | /** Flag indicating if the pak index has been encrypted. */ 34 | public bool bEncryptedIndex; 35 | 36 | public static long GetSerializedSize() 37 | { 38 | return 45; 39 | } 40 | 41 | public FPakInfo(byte[] bytes) 42 | { 43 | if (bytes != null && bytes.Length < GetSerializedSize()) 44 | { 45 | Magic = 0; 46 | return; 47 | } 48 | 49 | bEncryptedIndex = BitConverter.ToBoolean(bytes, 0); 50 | Magic = BitConverter.ToUInt32(bytes, 1); 51 | Version = BitConverter.ToInt32(bytes, 5); 52 | IndexOffset = BitConverter.ToInt64(bytes, 9); 53 | IndexSize = BitConverter.ToInt64(bytes, 17); 54 | Array.Copy(bytes, 25, IndexHash, 0, 20); 55 | 56 | if (Version < (int)PakVersion.IndexEncryption) 57 | bEncryptedIndex = false; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /UE4View/UE4/Pak/PakExplorer.cs: -------------------------------------------------------------------------------- 1 | using FarNet; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Xml; 9 | using UE4View.UE4.Pak; 10 | using UE4View.UE4.UAsset; 11 | using UE4View.UE4.VorbisBank.Xml; 12 | 13 | namespace UE4View 14 | { 15 | public class PakExplorer : Explorer 16 | { 17 | public static FPakFile InspectedFile; 18 | Panel PakViewPanel; 19 | 20 | Explorer Parent = null; 21 | List _files = new List(); 22 | 23 | public PakExplorer(FPakFile Pak) : this(null, Pak.Index, Pak.OriginalFileName) 24 | { 25 | InspectedFile = Pak; 26 | } 27 | PakExplorer(Explorer Parent, FFileIndex Index, string Loc) : this(Parent, Loc) 28 | { 29 | Task.Run(() => ParseFileIndex(Index)); 30 | } 31 | PakExplorer(Explorer Parent, string Loc) : this() 32 | { 33 | this.Parent = Parent; 34 | this.Location = Path.Combine(Parent?.Location ?? string.Empty, Loc); 35 | } 36 | PakExplorer() : base(new Guid("dc1d3a1f-22da-4aae-954b-cf07f971cf01")) 37 | { 38 | CanOpenFile = true; 39 | CanGetContent = true; 40 | CanExportFiles = true; 41 | CanExploreLocation = true; 42 | } 43 | 44 | 45 | public override Explorer ExploreRoot(ExploreRootEventArgs args) 46 | { 47 | var exp = this.Parent as PakExplorer; 48 | while(exp != null && exp.Parent is PakExplorer Parent) 49 | exp = Parent; 50 | 51 | return exp; 52 | } 53 | 54 | public override void GetContent(GetContentEventArgs args) 55 | { 56 | var filedata = args.File.Data ?? GetFileData(args.File); 57 | var data = InspectedFile.ReadEntry(filedata); 58 | File.WriteAllBytes(args.FileName, data ?? new byte[0]); 59 | } 60 | 61 | public override Explorer OpenFile(OpenFileEventArgs args) 62 | { 63 | var filedata = args.File.Data ?? GetFileData(args.File); 64 | if (args.File.Name.EndsWith(".bnk") && filedata is FPakEntry entry) 65 | { 66 | var data = InspectedFile.ReadEntry(entry); 67 | var bankinfo = _files.Where(f => f.Name == "SoundbanksInfo.xml").SingleOrDefault(); 68 | if (bankinfo != null) 69 | { 70 | var bankData = InspectedFile.ReadEntry(bankinfo.Data); 71 | var doc = new XmlDocument(); 72 | var xml = Encoding.UTF8.GetString(bankData); 73 | doc.LoadXml(xml); 74 | var info = new SoundBankInfo(doc); 75 | return new UE4.VorbisBank.BankExplorer(new UE4.VorbisBank.BankFile(data, info)); 76 | } 77 | else 78 | return new UE4.VorbisBank.BankExplorer(new UE4.VorbisBank.BankFile(data)); 79 | } 80 | else if (args.File.Name.EndsWith(".uasset") && filedata is FPakEntry asset) 81 | { 82 | var data = InspectedFile.ReadEntry(filedata); 83 | new UAsset(data, GetCookedAssetVersion()); 84 | return null; 85 | } 86 | else 87 | return null; 88 | } 89 | 90 | public override Explorer ExploreLocation(ExploreLocationEventArgs args) 91 | { 92 | var dirs = args.Location.Replace(this.Location, string.Empty).Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); 93 | var exp = this; 94 | foreach(var dir in dirs) 95 | { 96 | var file = exp._files.Where(f => f.IsDirectory && f.Name == dir).SingleOrDefault(); 97 | if (file != null && file.Data is PakExplorer found) 98 | exp = found; 99 | else if (dir == "..") 100 | { 101 | exp = exp.ExploreParent(new ExploreParentEventArgs(args.Mode)) as PakExplorer; 102 | if (exp == null) 103 | break; 104 | } 105 | else 106 | break; 107 | 108 | } 109 | return exp == this ? null : exp; 110 | } 111 | 112 | public override Explorer ExploreParent(ExploreParentEventArgs args) 113 | { 114 | if (Parent != null) 115 | args.PostData = this; 116 | else 117 | { 118 | args.PostName = InspectedFile.OriginalFileName; 119 | InspectedFile.Close(); 120 | PakViewPanel.Close(); 121 | } 122 | return Parent; 123 | } 124 | 125 | public override void ExportFiles(ExportFilesEventArgs args) 126 | { 127 | foreach (var file in args.Files) 128 | ExportFileEntry(file, Path.Combine(args.DirectoryName, file.Name)); 129 | } 130 | 131 | private void ParseFileIndex(FFileIndex Index) 132 | { 133 | _files.AddRange(Index.Directories.Select(dir => 134 | new SetFile() 135 | { 136 | Name = dir.Key, 137 | Data = new PakExplorer(this, dir.Value, dir.Key), 138 | IsDirectory = true, 139 | })); 140 | _files.AddRange(Index.Files.Select(entry => 141 | new SetFile() 142 | { 143 | Name = entry.Key, 144 | Data = entry.Value, 145 | Length = entry.Value.Size, 146 | })); 147 | 148 | // Should never happen, but who knows... 149 | _files.ForEach(f => 150 | { 151 | if (FarNet.Works.Kit.IsInvalidFileName(f.Name)) 152 | f.Name = FarNet.Works.Kit.FixInvalidFileName(f.Name); 153 | }); 154 | } 155 | 156 | private void ExportFileEntry(FarFile file, string Dir) 157 | { 158 | var filedata = file.Data ?? GetFileData(file); 159 | if (file.IsDirectory) 160 | { 161 | Directory.CreateDirectory(Dir); 162 | if (filedata is PakExplorer index) 163 | index._files.ForEach(f => ExportFileEntry(f, Path.Combine(Dir, f.Name))); 164 | } 165 | else if (file.Name.EndsWith(".bnk") && filedata is FPakEntry entry) 166 | { 167 | UE4.VorbisBank.BankFile bank = null; 168 | var data = InspectedFile.ReadEntry(entry); 169 | var bankinfo = _files.Where(f => f.Name == "SoundbanksInfo.xml").SingleOrDefault(); 170 | if (bankinfo != null) 171 | { 172 | var bankData = InspectedFile.ReadEntry(bankinfo.Data); 173 | var doc = new XmlDocument(); 174 | var xml = Encoding.UTF8.GetString(bankData); 175 | doc.LoadXml(xml); 176 | var info = new SoundBankInfo(doc); 177 | bank = new UE4.VorbisBank.BankFile(data, info); 178 | } 179 | else 180 | bank = new UE4.VorbisBank.BankFile(data); 181 | 182 | File.WriteAllBytes(Dir, data); 183 | var folder = Path.Combine(Path.GetDirectoryName(Dir), Path.GetFileNameWithoutExtension(Dir)); 184 | Directory.CreateDirectory(folder); 185 | bank.Files.ForEach(track => File.WriteAllBytes(Path.Combine(folder, track.Name), bank.ReadTrack(track))); 186 | } 187 | else 188 | { 189 | var data = InspectedFile.ReadEntry(filedata); 190 | if (data != null) 191 | File.WriteAllBytes(Dir, data); 192 | } 193 | } 194 | 195 | private int GetCookedAssetVersion() 196 | { 197 | var entry = InspectedFile.ReadEntryByName("*/CookedIniVersion.txt"); 198 | if (entry != null) 199 | { 200 | var content = Encoding.UTF8.GetString(entry).Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 201 | var line = content.Where(str => str.Contains("VersionedIniParams=PackageFileVersions")).SingleOrDefault(); 202 | if (line != null) 203 | return int.Parse(line.Split(':')[1]); 204 | } 205 | return 0; 206 | } 207 | 208 | public override Panel CreatePanel() 209 | { 210 | if (InspectedFile.Info.Magic == FPakInfo.PakFile_Magic) 211 | { 212 | if (InspectedFile.Info.bEncryptedIndex == false) 213 | { 214 | PakViewPanel = new Panel(this) 215 | { 216 | Title = InspectedFile.OriginalFileName, 217 | SortMode = PanelSortMode.Name, 218 | ViewMode = PanelViewMode.Wide, 219 | DotsMode = PanelDotsMode.Dots, 220 | UseSortGroups = true, 221 | }; 222 | return PakViewPanel; 223 | } 224 | else 225 | Far.Api.Message("This PAK file is encrypted!!!"); 226 | } 227 | else 228 | Far.Api.Message("Not an UE4 PAK file format"); 229 | 230 | return null; 231 | } 232 | 233 | private object GetFileData(FarFile file) => _files.Where(f => f.Name == file.Name).Single().Data; 234 | 235 | public override IList GetFiles(GetFilesEventArgs args) => _files; 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /UE4View/UE4/UAsset/Export/UDataTable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace UE4View.UE4.UAsset.Export 8 | { 9 | class UDataTable : UAsset 10 | { 11 | public UDataTable(byte[] data, int version) : base(data, version) 12 | { 13 | Seek((int)ExportMap[0].SerialOffset); 14 | 15 | var RowStruct = ToObject(); 16 | var RowClass = ToInt32(); // ObjectProperty of RowStruct -> ImportMap 17 | var Separator = ToName(); // Probably other properties of UDataTable, meh 18 | var UnknownData = ToByteArray(0x4); 19 | return; 20 | } 21 | 22 | public void ReadRows(StreamWriter str) 23 | { 24 | var RowCount = ToInt32(); 25 | 26 | foreach (var i in Enumerable.Range(0, RowCount)) 27 | { 28 | ReadDataTableRow(str); 29 | } 30 | } 31 | 32 | private void ReadDataTableRow(StreamWriter str) 33 | { 34 | // TODO: Still need to change this to actual property system 35 | var RowName = ToName(); 36 | str.WriteLine("\nRow {0}:", RowName); 37 | var Prop = ToObject(); 38 | while (Prop.Name != "None") 39 | { 40 | str.Write("{0}: ", Prop.Name); 41 | if (Prop.Type == "StrProperty" || Prop.Type == "NameProperty" || Prop.Type == "TextProperty" || Prop.Type == "IntProperty" || Prop.Type == "AssetObjectProperty") 42 | { 43 | if (Prop.Type == "StrProperty" || Prop.Type == "AssetObjectProperty") 44 | str.WriteLine(ToFString()); 45 | else if (Prop.Type == "NameProperty") 46 | str.WriteLine(ToName()); 47 | else if (Prop.Type == "TextProperty") 48 | str.WriteLine(ToFText()); 49 | else if (Prop.Type == "IntProperty") 50 | str.WriteLine(ToInt32()); 51 | } 52 | else if (Prop.Type == "ArrayProperty") 53 | { 54 | if (Prop.InnerType == "StructProperty") 55 | { 56 | str.WriteLine("Skipped"); 57 | Skip(Prop.Size); 58 | continue; 59 | } 60 | var ArrayCount = ToInt32(); 61 | str.Write(" [ "); 62 | foreach (var i in Enumerable.Range(0, ArrayCount)) 63 | { 64 | if (Prop.InnerType == "ByteProperty" || Prop.InnerType == "NameProperty") 65 | str.Write(ToName()); 66 | else if (Prop.InnerType == "IntProperty") 67 | str.Write(ToInt32()); 68 | else if (Prop.InnerType == "FloatProperty") 69 | str.Write(ToFloat()); 70 | else if (Prop.InnerType == "StrProperty") 71 | str.Write(ToFString()); 72 | else 73 | break; 74 | 75 | if (i < ArrayCount - 1) 76 | str.Write(", "); 77 | } 78 | str.WriteLine(" ]"); 79 | } 80 | else if (Prop.Type == "ByteProperty") 81 | { 82 | var DataSize = ToInt64(); 83 | var EnumType = ToName(); 84 | ToByte(); 85 | var EnumValue = ToName(); 86 | str.WriteLine("{0}", EnumValue); 87 | } 88 | else if (Prop.Type == "FloatProperty") 89 | { 90 | var Value = ToFloat(); 91 | str.WriteLine(Value); 92 | } 93 | else if (Prop.Type == "BoolProperty") 94 | { 95 | str.WriteLine(Prop.BoolVal); 96 | } 97 | else if (Prop.Type == "StructProperty") 98 | { 99 | Debugger.Break(); 100 | str.WriteLine(); 101 | } 102 | else 103 | throw new ArgumentException($"Unknown type \"{Prop.Type}\", implement handling for that shit."); 104 | } 105 | 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /UE4View/UE4/UAsset/ExportTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace UE4View.UE4.UAsset 6 | { 7 | class ExportTypes 8 | { 9 | static List Types = typeof(ExportTypes).Assembly.GetTypes() 10 | .Where(t => t.IsSubclassOf(typeof(USerializable))) // TODO: Change which type I'm gonna use? Or should I just use namespace? 11 | .ToList(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /UE4View/UE4/UAsset/UAsset.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | 6 | 7 | namespace UE4View.UE4.UAsset 8 | { 9 | public class UAsset : FArchive 10 | { 11 | protected FPackageFileSummary Summary; 12 | List NameMap; 13 | protected List ExportMap; 14 | protected List ImportMap; 15 | List GatherableTextDataMap; 16 | List StringAssetReferences; 17 | 18 | public UAsset(byte[] data, int version) : base(data) 19 | { 20 | Version = version; 21 | ReadSummary(); 22 | 23 | Seek(Summary.NameOffset); 24 | foreach (var i in Enumerable.Range(0, Summary.NameCount)) 25 | { 26 | var entry = new FNameEntrySerialized(); 27 | entry.Serialize(this); 28 | NameMap.Add(entry.Name); 29 | } 30 | Seek(Summary.GatherableTextDataOffset); 31 | foreach (var i in Enumerable.Range(0, Summary.GatherableTextDataCount)) 32 | { 33 | Debugger.Break(); 34 | // check whether it reads stuff properly 35 | var gatherable = new FGatherableTextData(); 36 | gatherable.Serialize(this); 37 | GatherableTextDataMap.Add(gatherable); 38 | } 39 | Seek(Summary.ImportOffset); 40 | foreach (var i in Enumerable.Range(0, Summary.ImportCount)) 41 | { 42 | var imp = new FObjectImport(); 43 | imp.Serialize(this); 44 | ImportMap.Add(imp); 45 | } 46 | Seek(Summary.ExportOffset); 47 | foreach (var i in Enumerable.Range(0, Summary.ExportCount)) 48 | { 49 | var exp = new FObjectExport(); 50 | exp.Serialize(this); 51 | ExportMap.Add(exp); 52 | } 53 | Seek(Summary.StringAssetReferencesOffset); 54 | foreach (var i in Enumerable.Range(0, Summary.StringAssetReferencesCount)) 55 | { 56 | StringAssetReferences.Add(ToFString()); 57 | } 58 | 59 | // TODO: Fixup import, fixup exports, match exports with exporter object 60 | } 61 | 62 | public UAsset(byte[] data) : this(data, 0) 63 | { 64 | } 65 | 66 | private void ReadSummary() 67 | { 68 | Summary = new FPackageFileSummary(); 69 | Summary.Serialize(this); 70 | Version = Summary.FileVersionUE4; 71 | NameMap = new List(Summary.NameCount); 72 | ExportMap = new List(Summary.ExportCount); 73 | ImportMap = new List(Summary.ImportCount); 74 | GatherableTextDataMap = new List(Summary.GatherableTextDataCount); 75 | StringAssetReferences = new List(Summary.StringAssetReferencesCount); 76 | } 77 | 78 | public override string ToName() 79 | { 80 | var NameIndex = ToInt32(); 81 | if (NameMap.Count > NameIndex && NameIndex >= 0) 82 | { 83 | var Number = ToInt32(); 84 | return NameMap[NameIndex]; 85 | } 86 | throw new ArgumentOutOfRangeException(nameof(NameIndex)); 87 | //return base.ToName(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /UE4View/UE4/USerializable.cs: -------------------------------------------------------------------------------- 1 | namespace UE4View.UE4 2 | { 3 | public abstract class USerializable 4 | { 5 | public abstract FArchive Serialize(FArchive reader); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /UE4View/UE4/VorbisBank/BankExplorer.cs: -------------------------------------------------------------------------------- 1 | using FarNet; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace UE4View.UE4.VorbisBank 8 | { 9 | class BankExplorer : Explorer 10 | { 11 | BankFile InspectedBank; 12 | List _files = new List(); 13 | 14 | public BankExplorer(BankFile bank) : base(new Guid("dc1d3a1f-22da-4aae-954b-cf07f971cf02")) 15 | { 16 | InspectedBank = bank; 17 | CanGetContent = true; 18 | Location = "SoundBank"; 19 | _files.AddRange(bank.Files.Select(f => new SetFile() 20 | { 21 | Name = f.Name, 22 | Length = f.Length, 23 | Data = f 24 | })); 25 | } 26 | 27 | public override void EnterPanel(Panel panel) 28 | { 29 | panel.Title = "SoundBank View"; 30 | panel.CurrentLocation = this.Location; 31 | base.EnterPanel(panel); 32 | } 33 | 34 | public override void GetContent(GetContentEventArgs args) 35 | { 36 | File.WriteAllBytes(args.FileName, InspectedBank.ReadTrack(args.File.Data as BankFile.BankTrack)); 37 | } 38 | 39 | public override IList GetFiles(GetFilesEventArgs args) 40 | { 41 | return _files; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /UE4View/UE4/VorbisBank/BankFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UE4View.UE4.VorbisBank.Xml; 5 | 6 | namespace UE4View.UE4.VorbisBank 7 | { 8 | 9 | // TODO: Cleanup the code, it's really messy because I didn't believe it would be that simple. 10 | class BankFile 11 | { 12 | int offset; 13 | byte[] Buffer; 14 | 15 | public int Magic; 16 | public int HeaderLength; 17 | public int Version; 18 | public uint SoundBankId; 19 | 20 | public int DIDXMagic; 21 | public int ChunkLength; 22 | 23 | public class BankTrack 24 | { 25 | public uint Id; 26 | public int Offset; 27 | public int Length; 28 | public string Name; 29 | } 30 | 31 | public List Files; 32 | 33 | BankFile() 34 | { 35 | offset = 0; 36 | // Buffer = Data; 37 | } 38 | public BankFile(byte[] Data, SoundBankInfo info = null) : this() 39 | { 40 | Buffer = Data; 41 | 42 | Magic = ToInt32(); 43 | if (Magic == 0x44484B42) 44 | { 45 | HeaderLength = ToInt32(); 46 | var HeaderEnd = Tell(); 47 | Version = ToInt32(); 48 | SoundBankId = ToUInt32(); 49 | 50 | Seek(HeaderEnd + HeaderLength); 51 | 52 | DIDXMagic = ToInt32(); 53 | if (DIDXMagic == 0x58444944) 54 | { 55 | ChunkLength = ToInt32(); 56 | var filecount = ChunkLength / 12; 57 | Files = new List(filecount); 58 | foreach (var i in Enumerable.Range(0, filecount)) 59 | { 60 | var trackId = ToUInt32(); 61 | Files.Add(new BankTrack() 62 | { 63 | Id = trackId, 64 | Offset = ToInt32(), 65 | Length = ToInt32(), 66 | Name = info != null ? info.GetTrackName(SoundBankId, trackId) : trackId.ToString() + ".wem" 67 | }); 68 | } 69 | } 70 | 71 | var DataMagic = ToInt32(); 72 | var DataLen = ToInt32(); 73 | } 74 | } 75 | public byte[] ReadTrack(BankTrack track) 76 | { 77 | var data = new byte[track.Length]; 78 | Array.Copy(Buffer, offset + track.Offset, data, 0, track.Length); 79 | return data; 80 | } 81 | public int ToInt32() 82 | { 83 | var val = BitConverter.ToInt32(Buffer, offset); 84 | offset += sizeof(int); 85 | return val; 86 | } 87 | public uint ToUInt32() 88 | { 89 | var val = BitConverter.ToUInt32(Buffer, offset); 90 | offset += sizeof(uint); 91 | return val; 92 | } 93 | 94 | public BankFile Skip(int len) 95 | { 96 | offset += len; 97 | return this; 98 | } 99 | public BankFile Seek(int off) 100 | { 101 | offset = off; 102 | return this; 103 | } 104 | public int Tell() 105 | { 106 | return offset; 107 | } 108 | public int Length() 109 | { 110 | return Buffer.Length; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /UE4View/UE4/VorbisBank/Xml/SoundBank.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Xml; 5 | 6 | namespace UE4View.UE4.VorbisBank.Xml 7 | { 8 | public class SoundBank : SoundFile 9 | { 10 | public SoundBank(XmlNode node) : base(node) 11 | { 12 | if (node == null) 13 | throw new ArgumentNullException(nameof(node)); 14 | 15 | var files = node.SelectNodes(".//IncludedMemoryFiles/*"); 16 | MemoryFiles = new List(files.Count); 17 | foreach (XmlNode file in files) 18 | MemoryFiles.Add(new SoundFile(file)); 19 | } 20 | 21 | public SoundFile GetFile(uint trackId) 22 | { 23 | return MemoryFiles.Where(file => file.Id == trackId).Single(); 24 | } 25 | 26 | List MemoryFiles; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /UE4View/UE4/VorbisBank/Xml/SoundBankInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Xml; 6 | 7 | namespace UE4View.UE4.VorbisBank.Xml 8 | { 9 | public class SoundBankInfo 10 | { 11 | public SoundBankInfo(XmlDocument doc) 12 | { 13 | if (doc == null) 14 | throw new ArgumentNullException(nameof(doc)); 15 | 16 | // Not parsing not interesing stuff like original paths, events 17 | var files = doc.SelectNodes(".//StreamedFiles/*"); 18 | StreamedFiles = new List(files.Count); 19 | foreach (XmlNode file in files) 20 | StreamedFiles.Add(new SoundFile(file)); 21 | 22 | var media = doc.SelectNodes(".//MediaFilesNotInAnyBank/*"); 23 | if (media.Count > 0) 24 | { 25 | Debugger.Break(); // Break to verify whether it actually looks like that, DBD doesn't have it 26 | MediaFilesNotInAnyBank = new List(media.Count); 27 | foreach (XmlNode file in media) 28 | MediaFilesNotInAnyBank.Add(new SoundFile(file)); 29 | } 30 | 31 | var banks = doc.SelectNodes(".//SoundBanks/*"); 32 | SoundBanks = new List(banks.Count); 33 | foreach (XmlNode bank in banks) 34 | SoundBanks.Add(new SoundBank(bank)); 35 | } 36 | 37 | List StreamedFiles; 38 | List MediaFilesNotInAnyBank; 39 | List SoundBanks; 40 | 41 | public string GetTrackName(uint bankId, uint trackId) 42 | { 43 | var Bank = SoundBanks.Where(bank => bank.Id == bankId).Single(); 44 | return Bank.GetFile(trackId).GetExtractName(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /UE4View/UE4/VorbisBank/Xml/SoundFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Xml; 4 | 5 | namespace UE4View.UE4.VorbisBank.Xml 6 | { 7 | public class SoundFile 8 | { 9 | public SoundFile(XmlNode node) 10 | { 11 | if (node == null) 12 | throw new ArgumentNullException(nameof(node)); 13 | 14 | Id = uint.Parse(node.Attributes["Id"].Value); 15 | ShortName = node["ShortName"].InnerText; 16 | FilePath = node["Path"].InnerText; 17 | } 18 | 19 | public uint Id; 20 | public string ShortName; 21 | public string FilePath; 22 | 23 | public string GetExtractName() 24 | { 25 | return Path.GetFileNameWithoutExtension(ShortName) + Path.GetExtension(FilePath); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /UE4View/UE4View.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {59960912-35AE-4370-B8E4-F3ADD93D4DD0} 8 | Library 9 | Properties 10 | UE4View 11 | UE4View 12 | v4.5.2 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | False 36 | ..\packages\FarNet.5.2.8\tools\FarHome\FarNet\FarNet.dll 37 | 38 | 39 | ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Designer 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | copy "$(TargetPath)" /B "D:/Programs/Far Manager/FarNet/Modules/UE4View/UE4View.dll" /B 95 | 96 | -------------------------------------------------------------------------------- /UE4View/UE4ViewCommand.cs: -------------------------------------------------------------------------------- 1 | using FarNet; 2 | using System.IO; 3 | using System.Linq; 4 | using UE4View.UE4.Pak; 5 | using UE4View.UE4.UAsset; 6 | using UE4View.UE4.VorbisBank; 7 | 8 | namespace UE4View 9 | { 10 | // Demo tool with an item in the plugin menu. 11 | [System.Runtime.InteropServices.Guid("dc1d3a1f-22da-4aae-954b-cf07f971cf00")] 12 | [ModuleCommand(Name = "UE4 Viewer", Prefix = "UE4View")] 13 | public class UE4ViewCommand : ModuleCommand 14 | { 15 | private int GetCookedAssetVersion() 16 | { 17 | var dir = Path.Combine(Far.Api.CurrentDirectory, "CookedIniVersion.txt"); 18 | if (File.Exists(dir)) 19 | { 20 | var FileContent = File.ReadAllLines(dir); 21 | var verline = FileContent?.Where(line => line.Contains("VersionedIniParams=PackageFileVersions")).SingleOrDefault(); 22 | if (verline != null) 23 | return int.Parse(verline.Split(':')[1]); 24 | } 25 | return 0; 26 | } 27 | public override void Invoke(object sender, ModuleCommandEventArgs e) 28 | { 29 | var filename = e.Command; 30 | if (filename.EndsWith(".pak")) 31 | { 32 | new PakExplorer(new FPakFile(filename)).OpenPanel(); 33 | } 34 | else if (filename.EndsWith(".bnk")) 35 | { 36 | new BankExplorer(new BankFile(File.ReadAllBytes(filename))).OpenPanel(); 37 | } 38 | else if (filename.EndsWith(".uasset")) 39 | { 40 | //var viewer = Far.Api.CreateViewer(); 41 | //viewer.DeleteSource = DeleteSource.File; 42 | //viewer.DisableHistory = true; 43 | //viewer.FileName = Path.GetTempFileName(); 44 | //viewer.Switching = Switching.Disabled; 45 | //viewer.Title = filename; 46 | //viewer.ViewMode = ViewerViewMode.Text; 47 | //viewer.WordWrapMode = true; 48 | // TODO: Write data to viewer.FileName 49 | //viewer.Open(OpenMode.Modal); 50 | if (false) 51 | { 52 | var files = Directory.GetFiles(Far.Api.CurrentDirectory, "*.uasset", SearchOption.AllDirectories); 53 | foreach(var file in files) 54 | { 55 | bool bDelete = false; 56 | using (var stream = File.CreateText(file + ".log")) 57 | { 58 | try 59 | { 60 | new UAsset(File.ReadAllBytes(file), 506); 61 | } 62 | catch 63 | { 64 | bDelete = true; 65 | } 66 | finally 67 | { 68 | File.Delete(file); 69 | } 70 | } 71 | if (bDelete) 72 | File.Delete(file + ".log"); 73 | } 74 | } 75 | else 76 | new UAsset(File.ReadAllBytes(filename), GetCookedAssetVersion()); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /UE4View/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | --------------------------------------------------------------------------------