public static void AnalyzeFileName(out string name, out string compiledFileName, string fileName, string nameSpace = "models") { var match = CompiledFileNameAnalyzer.Match(fileName); if (match.Success) { name = match.Groups[1].Value; compiledFileName = match.Groups[2].Value + AssetUtil.CrcNamespace(nameSpace).ToString("X8", CultureInfo.InvariantCulture); } else { name = fileName; compiledFileName = AssetUtil.CrcFullName(fileName, nameSpace); } }
public string Generate(string path) { var models = new ESOModel[4]; for (short x = 0; x < level.Size.Width; x++) { for (short y = 0; y < level.Size.Length; y++) { for (short z = 0; z < level.Size.Height; z++) { var info = GetInformation(x, y, z); if (info.Height < 0) { continue; } var theme = themes[info.Theme]; if (models[theme] == null) { models[theme] = new ESOModel(ESOModel.Flags.Normals | ESOModel.Flags.TexCoords) { MaterialAsset = AssetHash.Parse(Materials[theme] + ModelsNamespace) } } ; var model = models[theme]; short x1 = (short)(x + 1), y1 = (short)(y + 1), z1 = (short)(z + 1); float texY1 = 1 - z * 0.25F, texY = texY1 - 0.25F; if (GetInformation(x, y, z1).Height < 1 && (Math.Abs(x - level.ExitPoint.X) > 1 || Math.Abs(y - level.ExitPoint.Y) > 1 || z1 != level.ExitPoint.Z)) { model.Vertices.Add(Transform(new Vec3(x, z1, y))); model.Vertices.Add(Transform(new Vec3(x1, z1, y))); model.Vertices.Add(Transform(new Vec3(x, z1, y1))); model.Vertices.Add(Transform(new Vec3(x, z1, y1))); model.Vertices.Add(Transform(new Vec3(x1, z1, y))); model.Vertices.Add(Transform(new Vec3(x1, z1, y1))); model.Normals.AddRange(YNormals); float texX = ((x + y) & 1) == 0 ? 0.51F : 0.76F, texX1 = texX + 0.23F; model.TexCoords.Add(new Vec2(texX, texY)); model.TexCoords.Add(new Vec2(texX1, texY)); model.TexCoords.Add(new Vec2(texX, texY1)); model.TexCoords.Add(new Vec2(texX, texY1)); model.TexCoords.Add(new Vec2(texX1, texY)); model.TexCoords.Add(new Vec2(texX1, texY1)); } if (info.Height <= 0) { continue; } var zB = z1 - info.Height; texY1 -= 0.25F * (1 - info.Height); if (GetInformation(x1, y, z).Height < info.Height) { model.Vertices.Add(Transform(new Vec3(x1, zB, y))); model.Vertices.Add(Transform(new Vec3(x1, zB, y1))); model.Vertices.Add(Transform(new Vec3(x1, z1, y))); model.Vertices.Add(Transform(new Vec3(x1, zB, y1))); model.Vertices.Add(Transform(new Vec3(x1, z1, y1))); model.Vertices.Add(Transform(new Vec3(x1, z1, y))); model.Normals.AddRange(XNormals); model.TexCoords.Add(new Vec2(0.49F, texY1)); model.TexCoords.Add(new Vec2(0.26F, texY1)); model.TexCoords.Add(new Vec2(0.49F, texY)); model.TexCoords.Add(new Vec2(0.26F, texY1)); model.TexCoords.Add(new Vec2(0.26F, texY)); model.TexCoords.Add(new Vec2(0.49F, texY)); } if (GetInformation(x, y1, z).Height < info.Height) { model.Vertices.Add(Transform(new Vec3(x, zB, y1))); model.Vertices.Add(Transform(new Vec3(x, z1, y1))); model.Vertices.Add(Transform(new Vec3(x1, zB, y1))); model.Vertices.Add(Transform(new Vec3(x, z1, y1))); model.Vertices.Add(Transform(new Vec3(x1, z1, y1))); model.Vertices.Add(Transform(new Vec3(x1, zB, y1))); model.Normals.AddRange(ZNormals); model.TexCoords.Add(new Vec2(0.01F, texY1)); model.TexCoords.Add(new Vec2(0.01F, texY)); model.TexCoords.Add(new Vec2(0.24F, texY1)); model.TexCoords.Add(new Vec2(0.01F, texY)); model.TexCoords.Add(new Vec2(0.24F, texY)); model.TexCoords.Add(new Vec2(0.24F, texY1)); } } } } string fileName = Path.GetFileNameWithoutExtension(path) + ".rmdl", result; models = models.Where(model => model != null).ToArray(); new ESO { AssetHeader = new AssetHeader(AssetUtil.EngineVersion.Version1804Edge, fileName, "models"), Models = models, Header = new ESOHeader { V01 = 1, V02 = 4096, V20 = 1, NumModels = models.Length, ScaleXYZ = 1, Scale = new Vec3(0.1F, 0.1F, 0.1F), Translate = Translates[themes[0]], NodeChild = AssetHash.Parse(ChildModels[themes[0]] + ModelsNamespace), BoundingMin = Transform(new Vec3()), BoundingMax = Transform(new Vec3(level.Size.Width, level.Size.Height, level.Size.Length)) } }.Save(result = Path.Combine(Path.GetDirectoryName(path), AssetUtil.CrcFullName(fileName, "models") + ".eso")); return(result); } }
public static Tuple <Exception, string, List <FileEntry> > Compile(bool exFormat, string file, string directory = null) { var list = new List <FileEntry>(); var fileName = Path.GetFileNameWithoutExtension(file); if (string.IsNullOrWhiteSpace(directory)) { directory = Path.GetDirectoryName(file); } string inputPath = Path.Combine(Path.GetDirectoryName(file), fileName), outputPath = Path.Combine(directory, fileName); Warning.Start(); try { switch ((Path.GetExtension(file) ?? string.Empty).ToLowerInvariant()) { case ".bin": switch (fileName.ToLowerInvariant()) { case "cos": var array = new short[181]; using (var stream = File.OpenRead(file)) using (var reader = new BinaryReader(stream)) for (var i = 0; i <= 180; i++) { array[i] = reader.ReadInt16(); } File.WriteAllText(outputPath += ".txt", string.Join(Environment.NewLine, array.Select(value => value / 256.0))); list.Add(new FileEntry(outputPath, "cos.txt")); break; case "font": DecompileFont(file, ref outputPath); list.Add(new FileEntry(outputPath, "font.xml")); break; default: { var index = 0; foreach (var path in Level.CreateFromCompiled(file).Decompile(outputPath)) { list.Add(new FileEntry(path, index == 0 ? "level.xml" : index == 1 ? "level.png" : "level.z.png")); index++; } break; } } break; case ".xml": var root = XHelper.Load(file).Elements().First(); switch (root.Name.LocalName.ToLowerInvariant()) { case "level": { var index = 0; foreach (var path in Level.CreateFromDecompiled(inputPath) .Compile(outputPath + ".bin")) { list.Add(new FileEntry(path, index == 0 ? "level.bin" : "model.eso")); index++; } break; } case "animation": AssetHelper.ParseEan(root, fileName).Save(outputPath = Path.Combine(directory, AssetUtil.CrcFullName(fileName, "models") + ".ean")); list.Add(new FileEntry(outputPath, "animation.ean")); break; case "material": { string name; Helper.AnalyzeFileName(out name, out outputPath, fileName); var ema = AssetHelper.ParseEma(root, name); ema.Save(Path.Combine(directory, outputPath += ".ema")); list.Add(new FileEntry(outputPath, "material.ema")); break; } case "models": { string name; Helper.AnalyzeFileName(out name, out outputPath, fileName); var eso = AssetHelper.ParseEso(root, name); eso.Save(Path.Combine(directory, outputPath += ".eso")); list.Add(new FileEntry(outputPath, "model.eso")); break; } case "font": { CompileFont(inputPath, out outputPath, root); list.Add(new FileEntry(outputPath, "font.bin")); break; } } break; case ".loc": LOC.FromFile(file).SaveXls(outputPath += ".xls"); list.Add(new FileEntry(outputPath, "text.xls")); break; case ".xls": LocHelper.FromXls(file).Save(outputPath += ".loc"); list.Add(new FileEntry(outputPath, "text.loc")); break; case ".etx": var etx = ETX.FromFile(file); etx.GetBitmap().Save(outputPath = Path.Combine(directory, etx.AssetHeader.Name + ".png")); list.Add(new FileEntry(outputPath, "texture.png")); break; case ".png": { var name = AssetUtil.CrcFullName(fileName, "textures") + ".etx"; (exFormat ? (ETX)ETX1804.CreateFromImage(file) : ETX1803.CreateFromImage(file)) .Save(outputPath = Path.Combine(directory, name)); list.Add(new FileEntry(outputPath, "texture.etx")); break; } case ".ean": var ean = EAN.FromFile(file); File.WriteAllText(outputPath = Path.Combine(directory, Helper.GetDecompiledFileName(fileName, ean) + ".xml"), AssetHelper.GetEanElement(ean).ToString()); list.Add(new FileEntry(outputPath, "animation.xml")); break; case ".ema": { var ema = EMA.FromFile(file); File.WriteAllText(outputPath = Path.Combine(directory, Helper.GetDecompiledFileName(fileName, ema) + ".xml"), AssetHelper.GetEmaElement(ema).ToString()); list.Add(new FileEntry(outputPath, "material.xml")); break; } case ".eso": { var eso = ESO.FromFile(file); File.WriteAllText(outputPath = Path.Combine(directory, Helper.GetDecompiledFileName(fileName, eso) + ".xml"), AssetHelper.GetEsoElement(eso).ToString()); list.Add(new FileEntry(outputPath, "model.xml")); break; } case ".txt": using (var stream = new FileStream(outputPath += ".bin", FileMode.Create, FileAccess.Write, FileShare.Read)) { var writer = new BinaryWriter(stream); foreach (var num in File.ReadAllText(file) .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) .Select(double.Parse)) { writer.Write((short)Math.Round(num * 256)); } } list.Add(new FileEntry(outputPath, "cos.bin")); break; default: switch (Path.GetFileName(file)) { case "audio": if (Directory.Exists(outputPath = Path.Combine(directory, "sfx"))) { Directory.Delete(outputPath, true); } Directory.CreateDirectory(outputPath); string xsb = Path.Combine(file, "sfx.xsb"), xwb = Path.Combine(file, "sfx.xwb"); int offset; using (var stream = new FileStream(xsb, FileMode.Open)) { stream.Position = 0x2A; using (var reader = new BinaryReader(stream)) offset = reader.ReadInt32(); } var unxwb = new Process { StartInfo = new ProcessStartInfo( Path.Combine(CurrentApp.Directory, "Resources/Libraries/unxwb.exe"), FormattableString.Invariant($"-d \"{outputPath}\" -b \"{xsb}\" {offset} \"{xwb}\"")) { UseShellExecute = false, CreateNoWindow = true } }; unxwb.Start(); unxwb.WaitForExit(); list.Add(new FileEntry(outputPath, "sfx")); break; case "sfx": Directory.CreateDirectory(outputPath = Path.Combine(directory, "audio")); string tempPath = Helper.GetRandomDirectory(), tempInputPath = Path.Combine(tempPath, "sfx"), tempOutputPath = Path.Combine(tempPath, "audio"); /************************************************************************************ * create temp input dir because it's still occupied for unknown reason; * * create temp output dir because COMException will be thrown if output dir and * * temp input dir is not under the same drive. * ************************************************************************************/ Directory.CreateDirectory(tempInputPath); var projectPath = GenerateXactProject(file, tempInputPath); using (var project = new CXACTMasterProject()) { project.Create(); project.Load(projectPath, new CXACTMasterProjectCallback(), 0); project.Build(new CXACTMasterProjectCallback(), tempOutputPath, false, false); } foreach (var path in Directory.EnumerateFiles(tempOutputPath)) { var target = Path.Combine(outputPath, Path.GetFileName(path)); File.Delete(target); File.Move(path, target); } try { Directory.Delete(tempPath, true); } catch { Trace.WriteLine(tempPath, "Delete tempPath failed"); } list.Add(new FileEntry(outputPath, "audio")); break; default: throw new NotSupportedException(Localization.DecompileUnrecognizedFile); } break; } return(new Tuple <Exception, string, List <FileEntry> >(null, Warning.Fetch(), list)); } catch (Exception exc) { return(new Tuple <Exception, string, List <FileEntry> >(exc, Warning.Fetch(), list)); } finally { Warning.Clear(); } }