private static void ExtractBlobs(KWAD kwad, string outputPath) { var namedBlobList = (from aliasInfo in kwad.GetAliasInfoList() where kwad.GetResourceInfoList()[(int) aliasInfo.ResourceIdx].GetType().SequenceEqual(KLEIResource.SIGNATURE_KLEI_BLOB_4) select new {name = aliasInfo.AliasPath.GetString(), blob = kwad.GetResourceAt<KLEIBlob>((int) aliasInfo.ResourceIdx)}).ToList(); Console.WriteLine("Extracting {0} blobs...", namedBlobList.Count); foreach (var namedBlob in namedBlobList) { Console.WriteLine(namedBlob.name); var path = Path.GetFullPath(Path.Combine(outputPath, namedBlob.name)); var parentDirectory = Path.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(parentDirectory)) { Directory.CreateDirectory(parentDirectory); } using (var fileStream = File.Open(path, FileMode.Create)) { var blobData = namedBlob.blob.GetData(); fileStream.Write(blobData, 0, blobData.Length); } } }
private static void ExtractBlobs(KWAD kwad, string outputPath) { var namedBlobList = (from aliasInfo in kwad.GetAliasInfoList() where kwad.GetResourceInfoList()[(int)aliasInfo.ResourceIdx].GetType().SequenceEqual(KLEIBlob.KLEI_TYPE) select new { name = aliasInfo.AliasPath.GetString(), blob = kwad.GetResourceAt <KLEIBlob>((int)aliasInfo.ResourceIdx) }).ToList(); Console.WriteLine("Extracting {0} blobs...", namedBlobList.Count); foreach (var namedBlob in namedBlobList) { Console.WriteLine(namedBlob.name); var path = Path.GetFullPath(Path.Combine(outputPath, namedBlob.name.TrimStart(@"\/".ToCharArray()))); var parentDirectory = Path.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(parentDirectory)) { Directory.CreateDirectory(parentDirectory); } using (var fileStream = File.Open(path, FileMode.Create)) { var blobData = namedBlob.blob.GetData(); fileStream.Write(blobData, 0, blobData.Length); } } }
private static void ExtractAnims(KWAD kwad, string outputBasePath, string texturesPath) { var animBundleList = (from aliasInfo in kwad.GetAliasInfoList() where kwad.GetResourceInfoList()[(int)aliasInfo.ResourceIdx].GetType().SequenceEqual(KLEIAnimation.KLEI_TYPE) select new { name = Path.GetFileNameWithoutExtension(aliasInfo.AliasPath.GetString()), path = Path.GetDirectoryName(aliasInfo.AliasPath.GetString()), //animDef = kwad.GetResourceAt<KLEIAnimation>((int)aliasInfo.ResourceIdx), animBld = kwad.GetResourceByAlias <KLEIBuild>(Path.ChangeExtension(aliasInfo.AliasPath.GetString(), ".abld")) //namedTextureList = (from innerAliasInfo in kwad.GetAliasInfoList() // where kwad.GetResourceInfoList()[(int) innerAliasInfo.ResourceIdx].GetType().SequenceEqual(KLEITexture.KLEI_TYPE) && // // ReSharper disable once PossibleNullReferenceException // Path.GetDirectoryName(innerAliasInfo.AliasPath.GetString()).Equals( // Path.GetDirectoryName(Path.Combine(Path.ChangeExtension(aliasInfo.AliasPath.GetString(), ".anim"), "dummy")), // //GetDirectoryName has a side effect of changing separator character. // //That is why it is used on a second path to effect both. // StringComparison.InvariantCultureIgnoreCase) // select new // { // name = Path.GetFileName(innerAliasInfo.AliasPath.GetString()), // texture = kwad.GetResourceAt<KLEITexture>((int) innerAliasInfo.ResourceIdx) // }).ToList() }).ToList(); Console.WriteLine("Extracting {0} animation bundles...", animBundleList.Count); foreach (var animBundle in animBundleList) { //TODO: log any issues for a current animBundle to a corresponding log.txt file in that animBundle directory var animBuildOutputPath = Path.Combine(outputBasePath, animBundle.path, animBundle.name + ".anim"); if (!string.IsNullOrWhiteSpace(animBuildOutputPath)) { Directory.CreateDirectory(animBuildOutputPath); } if (animBundle.animBld != null) { ExtractAnimationBuild(kwad, animBundle.animBld, animBuildOutputPath, texturesPath); //ZipFile.CreateFromDirectory(tempOutputPath, Path.Combine(Path.GetFullPath(outputPath), animBundle.path, animBundle.name + ".anmbdl")); } } }
private static void ExtractTextures(KWAD kwad, string outputPath) { var namedTextureList = (from aliasInfo in kwad.GetAliasInfoList() where kwad.GetResourceInfoList()[(int) aliasInfo.ResourceIdx].GetType().SequenceEqual(KLEIResource.SIGNATURE_KLEI_TEXTURE_4) select new {name = aliasInfo.AliasPath.GetString(), texture = kwad.GetResourceAt<KLEITexture>((int) aliasInfo.ResourceIdx)}).ToList(); Console.WriteLine("Extracting {0} textures...", namedTextureList.Count); var groupedNamedTexture = namedTextureList.GroupBy(namedTexture => namedTexture.texture.ParentSurfaceResourceIdx); foreach (var surfaceGroup in groupedNamedTexture) { var surfaceName = kwad.GetAliasInfoList() .First(aliasInfo => aliasInfo.ResourceIdx == surfaceGroup.Key) .AliasPath.GetString(); Console.WriteLine(surfaceName + ":"); var surface = kwad.GetResourceAt<KLEISurface>((int) surfaceGroup.Key); var mipmap = surface.GetMipmaps()[0]; var imageData = DecompressMipmap(mipmap); if (surface.IsDXTCompressed) { imageData = Squish.DecompressImage(imageData, (int) mipmap.Width, (int) mipmap.Height, SquishFlags.Dxt5); } RgbaToBgra(imageData); GCHandle pinnedImageData = GCHandle.Alloc(imageData, GCHandleType.Pinned); try { IntPtr imageDataIntPtr = pinnedImageData.AddrOfPinnedObject(); using (Bitmap image = new Bitmap((int) mipmap.Width, (int) mipmap.Height, (int) mipmap.Width * 4, PixelFormat.Format32bppArgb, imageDataIntPtr)) { foreach (var namedTexture in surfaceGroup) { var texture = namedTexture.texture; Console.WriteLine("\t{0}", namedTexture.name); var path = Path.GetFullPath(Path.Combine(outputPath, namedTexture.name)); var parentDirectory = Path.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(parentDirectory)) { Directory.CreateDirectory(parentDirectory); } using (var fileStream = File.Open(path, FileMode.Create)) { // ReSharper disable CompareOfFloatsByEqualityOperator if (texture.Affine2d.TranslateX == 0 && texture.Affine2d.TranslateY == 0 && texture.Affine2d.C1R2 == 0 && texture.Affine2d.C2R1 == 0 && texture.Affine2d.ScaleX == 1 && texture.Affine2d.ScaleY == 1) { image.Save(fileStream, ImageFormat.Png); } else { image.Clone(new RectangleF(texture.Affine2d.TranslateX * mipmap.Width, texture.Affine2d.TranslateY * mipmap.Height, texture.Width, texture.Height), image.PixelFormat).Save(fileStream, ImageFormat.Png); } } } } } finally { pinnedImageData.Free(); } } }
private static void ExtractTextures(KWAD kwad, string outputPath) { var namedTextureList = (from aliasInfo in kwad.GetAliasInfoList() where kwad.GetResourceInfoList()[(int)aliasInfo.ResourceIdx].GetType().SequenceEqual(KLEITexture.KLEI_TYPE) select new { name = aliasInfo.AliasPath.GetString(), texture = kwad.GetResourceAt <KLEITexture>((int)aliasInfo.ResourceIdx) }).ToList(); Console.WriteLine("Extracting {0} textures...", namedTextureList.Count); var groupedNamedTexture = namedTextureList.GroupBy(namedTexture => namedTexture.texture.ParentSurfaceResourceIdx); foreach (var surfaceGroup in groupedNamedTexture) { var surfaceName = kwad.GetAliasInfoList() .First(aliasInfo => aliasInfo.ResourceIdx == surfaceGroup.Key) .AliasPath.GetString(); Console.WriteLine(surfaceName + ":"); var surface = kwad.GetResourceAt <KLEISurface>((int)surfaceGroup.Key); var mipmap = surface.GetMipmaps()[0]; var imageData = mipmap.CompressedSize > 0 ? DecompressMipmap(mipmap) : mipmap.GetData(); if (surface.IsDXTCompressed) { imageData = Squish.DecompressImage(imageData, (int)mipmap.Width, (int)mipmap.Height, SquishFlags.Dxt5); } RgbaToBgra(imageData); GCHandle pinnedImageData = GCHandle.Alloc(imageData, GCHandleType.Pinned); try { IntPtr imageDataIntPtr = pinnedImageData.AddrOfPinnedObject(); using (Bitmap image = new Bitmap((int)mipmap.Width, (int)mipmap.Height, (int)mipmap.Width * 4, PixelFormat.Format32bppArgb, imageDataIntPtr)) { foreach (var namedTexture in surfaceGroup) { var texture = namedTexture.texture; Console.WriteLine("\t{0}", namedTexture.name); var path = Path.GetFullPath(Path.Combine(outputPath, namedTexture.name.TrimStart(@"\/".ToCharArray()))); var parentDirectory = Path.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(parentDirectory)) { Directory.CreateDirectory(parentDirectory); } using (var fileStream = File.Open(path, FileMode.Create)) { // ReSharper disable CompareOfFloatsByEqualityOperator if (texture.Affine2d.TranslateX == 0 && texture.Affine2d.TranslateY == 0 && texture.Affine2d.C1R2 == 0 && texture.Affine2d.C2R1 == 0 && texture.Affine2d.ScaleX == 1 && texture.Affine2d.ScaleY == 1) { image.Save(fileStream, ImageFormat.Png); } else { image.Clone(new RectangleF(texture.Affine2d.TranslateX * mipmap.Width, texture.Affine2d.TranslateY * mipmap.Height, texture.Width, texture.Height), image.PixelFormat).Save(fileStream, ImageFormat.Png); } } } } } finally { pinnedImageData.Free(); } } }
private static void ExtractAnims(KWAD kwad, string outputBasePath, string texturesPath) { var animBundleList = (from aliasInfo in kwad.GetAliasInfoList() where kwad.GetResourceInfoList()[(int)aliasInfo.ResourceIdx].GetType().SequenceEqual(KLEIAnimation.KLEI_TYPE) select new { name = Path.GetFileNameWithoutExtension(aliasInfo.AliasPath.GetString()), path = Path.GetDirectoryName(aliasInfo.AliasPath.GetString()), animDef = kwad.GetResourceAt <KLEIAnimation>((int)aliasInfo.ResourceIdx), animBld = kwad.GetResourceByAlias <KLEIBuild>(Path.ChangeExtension(aliasInfo.AliasPath.GetString(), ".abld")) }).ToList(); Console.WriteLine("Extracting {0} animation bundles...", animBundleList.Count); int buildCount = 0; int animCount = 0; foreach (var animBundle in animBundleList) { if (animBundle.animBld != null) { buildCount++; } if (animBundle.animDef != null) { animCount++; } } Console.WriteLine("Extracting {0} animation builds...", buildCount); foreach (var animBundle in animBundleList) { //TODO: log any issues for a current animBundle to a corresponding log.txt file in that animBundle directory var animBuildOutputPath = Path.Combine(outputBasePath, animBundle.path, animBundle.name + ".anim"); if (!string.IsNullOrWhiteSpace(animBuildOutputPath)) { Directory.CreateDirectory(animBuildOutputPath); } if (animBundle.animBld != null) { ExtractAnimationBuild(kwad, animBundle.animBld, animBuildOutputPath, texturesPath); //ZipFile.CreateFromDirectory(tempOutputPath, Path.Combine(Path.GetFullPath(outputPath), animBundle.path, animBundle.name + ".anmbdl")); } } Console.WriteLine("Extracting {0} animation definitions...", animCount); foreach (var animBundle in animBundleList) { //TODO: log any issues for a current animBundle to a corresponding log.txt file in that animBundle directory var animBuildOutputPath = Path.Combine(outputBasePath, animBundle.path, animBundle.name + ".anim"); if (!string.IsNullOrWhiteSpace(animBuildOutputPath)) { Directory.CreateDirectory(animBuildOutputPath); } if (animBundle.animDef != null) { Console.WriteLine(string.Format("\tAnimation Def \"{0}\"", animBundle.name + ".anim")); ExtractAnimationDef(kwad, animBundle.animDef, animBuildOutputPath); } } }