/// <summary> /// Installs the specified r2d to the specified export. Specify an asset name if you wish to use a specific asset in the RTexture2D object. /// </summary> /// <param name="r2d"></param> /// <param name="export"></param> /// <param name="asset"></param> public static void InstallTexture(RTexture2D r2d, ExportEntry export, string asset = null) { // If no asset was specified pick a random asset asset ??= r2d.FetchRandomTextureAsset(); // 2. Is this asset already parsed? if (r2d.InstantiatedItems.TryGetValue(asset, out var instantiated)) { // It's already been instantiated. Just use this data instead MERLog.Information($@"Writing out cached asset {asset} for {export.InstancedFullPath}"); export.WritePropertiesAndBinary(instantiated.props, instantiated.texData); } else { MERLog.Information($@"Installing texture asset {asset} for {export.InstancedFullPath}"); // 3. Asset has not been setup yet. Write out the precomputed data. export.WriteBinary(GetTextureAssetBinary(asset)); // 4. Read in the data so it's in the correct context. var ut2d = ObjectBinary.From <UTexture2D>(export); // 5. Move compressed mips to TFC foreach (var mip in ut2d.Mips) { if (mip.IsCompressed) { mip.DataOffset = TFCBuilder.WriteMip(r2d, mip.Mip); // If it's compressed it needs to be stored externally. if (mip.StorageType == StorageTypes.pccLZO) { mip.StorageType = StorageTypes.extLZO; } if (mip.StorageType == StorageTypes.pccZlib) { mip.StorageType = StorageTypes.extZlib; } } } // 6. Setup the properties var props = export.GetProperties(); props.AddOrReplaceProp(new IntProperty(ut2d.Mips.Count - 1, @"MipTailBaseIdx")); props.AddOrReplaceProp(new IntProperty(ut2d.Mips[0].SizeX, @"SizeX")); props.AddOrReplaceProp(new IntProperty(ut2d.Mips[0].SizeY, @"SizeY")); props.AddOrReplaceProp(r2d.PreMountTexture ? ActiveBuilder.BGTFCNameProp : ActiveBuilder.DLCTFCNameProp); props.AddOrReplaceProp(r2d.PreMountTexture ? ActiveBuilder.BGTFCGuidProp : ActiveBuilder.DLCTFCGuidProp); if (r2d.LODGroup != null) { // Write a new LOD property props.AddOrReplaceProp(r2d.LODGroup); } // 7. Commit the export export.WritePropertiesAndBinary(props, ut2d); // 8. Cache the work that's been done so we don't need to it again. r2d.InstantiatedItems[asset] = (props, ut2d); } }
public static void EndTFCs() { if (ActiveBuilder != null) { var usedBGTFC = ActiveBuilder.BGTfcStream.Position > 16; var usedDLCTFC = ActiveBuilder.DLCTfcStream.Position > 16; ActiveBuilder.BGTfcStream?.Close(); ActiveBuilder.DLCTfcStream?.Close(); if (!usedBGTFC) { File.Delete(MERFileSystem.GetTFCPath(false)); } if (!usedDLCTFC) { File.Delete(MERFileSystem.GetTFCPath(true)); } } ActiveBuilder = null; }
/// <summary> /// Opens a new TFC file for writing /// </summary> /// <param name="randomizations"></param> /// <param name="dlcTfcName"></param> public static void StartNewTFCs(List <RTexture2D> randomizations) { ActiveBuilder = new TFCBuilder(); ActiveBuilder.TextureRandomizations = randomizations; var dlcTFCPath = MERFileSystem.GetTFCPath(true); // DLC TFC ActiveBuilder.DLCTFCNameProp = new NameProperty(Path.GetFileNameWithoutExtension(dlcTFCPath), "TextureFileCacheName"); //Written into texture properties ActiveBuilder.DLCTFCGuid = Guid.NewGuid(); ActiveBuilder.DLCTFCGuidProp = StructProperty.FromGuid(ActiveBuilder.DLCTFCGuid, "TFCFileGuid"); //Written into texture properties ActiveBuilder.DLCTfcStream = new FileStream(MERFileSystem.GetTFCPath(true), FileMode.Create, FileAccess.ReadWrite); ActiveBuilder.DLCTfcStream.WriteGuid(ActiveBuilder.DLCTFCGuid); // PRELOAD TFC var bgTfcPath = MERFileSystem.GetTFCPath(false); ActiveBuilder.BGTFCNameProp = new NameProperty(Path.GetFileNameWithoutExtension(bgTfcPath), "TextureFileCacheName"); //Written into texture properties ActiveBuilder.BGTFCGuid = Guid.NewGuid(); ActiveBuilder.BGTFCGuidProp = StructProperty.FromGuid(ActiveBuilder.BGTFCGuid, "TFCFileGuid"); //Written into texture properties ActiveBuilder.BGTfcStream = new FileStream(bgTfcPath, FileMode.Create, FileAccess.ReadWrite); ActiveBuilder.BGTfcStream.WriteGuid(ActiveBuilder.BGTFCGuid); }