UndertaleModTool-ExportToPr.../ExportToProject.csx
2019-11-02 19:25:11 +08:00

891 lines
31 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Drawing;
using UndertaleModLib.Models;
using UndertaleModLib.Util;
using UndertaleModLib.Decompiler;
int progress = 0;
string projFolder = GetFolder(FilePath) + "Export_Project" + Path.DirectorySeparatorChar;
var context = new DecompileContext(Data, true);
TextureWorker worker = new TextureWorker();
ThreadLocal<DecompileContext> DECOMPILE_CONTEXT = new ThreadLocal<DecompileContext>(() => new DecompileContext(Data, false));
if (Directory.Exists(projFolder))
{
ScriptError("A project export already exists. Please remove it.", "Error");
return;
}
Directory.CreateDirectory(projFolder);
// --------------- Start exporting ---------------
// Export sprites
UpdateProgressBar(null, "Exporting sprites...", progress++, 8);
await ExportSprites();
// Export backgrounds
UpdateProgressBar(null, "Exporting backgrounds...", progress++, 8);
await ExportBackground();
// Export objects
UpdateProgressBar(null, "Exporting objects...", progress++, 8);
await ExportGameObjects();
// Export rooms
UpdateProgressBar(null, "Exporting rooms...", progress++, 8);
await ExportRooms();
// Export sounds
UpdateProgressBar(null, "Exporting sounds...", progress++, 8);
await ExportSounds();
// Export scripts
UpdateProgressBar(null, "Exporting scripts...", progress++, 8);
await ExportScripts();
// Export fonts
UpdateProgressBar(null, "Exporting fonts...", progress++, 8);
await ExportFonts();
// Generate project file
UpdateProgressBar(null, "Generating project file...", progress++, 8);
ExportProjectFile();
// --------------- Export completed ---------------
worker.Cleanup();
HideProgressBar();
ScriptMessage("Export Complete.\n\nLocation: " + projFolder);
string GetFolder(string path)
{
return Path.GetDirectoryName(path) + Path.DirectorySeparatorChar;
}
string BoolToString(bool value)
{
// In the GMX file, -1 is true and 0 is false.
return value ? "-1" : "0";
}
// --------------- Export Sprite ---------------
async Task ExportSprites()
{
Directory.CreateDirectory(projFolder + "/sprites/images");
await Task.Run(() => Parallel.ForEach(Data.Sprites, ExportSprite));
}
void ExportSprite(UndertaleSprite sprite)
{
// Save the sprite GMX
var xmlWriter = XmlWriter.Create(projFolder + "/sprites/" + sprite.Name.Content + ".sprite.gmx");
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("sprite");
xmlWriter.WriteStartElement("type");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("xorig");
xmlWriter.WriteString(sprite.OriginX.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("yorigin");
xmlWriter.WriteString(sprite.OriginY.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("colkind");
xmlWriter.WriteString(sprite.BBoxMode.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("coltolerance");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("sepmasks");
xmlWriter.WriteString(sprite.SepMasks.ToString("D"));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("bboxmode");
xmlWriter.WriteString(sprite.BBoxMode.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("bbox_left");
xmlWriter.WriteString(sprite.MarginLeft.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("bbox_right");
xmlWriter.WriteString(sprite.MarginRight.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("bbox_top");
xmlWriter.WriteString(sprite.MarginTop.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("bbox_bottom");
xmlWriter.WriteString(sprite.MarginBottom.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("HTile");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("VTile");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("TextureGroups");
xmlWriter.WriteStartElement("TextureGroup0");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("For3D");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("width");
xmlWriter.WriteString(sprite.Width.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("height");
xmlWriter.WriteString(sprite.Height.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("frames");
for (int i = 0; i < sprite.Textures.Count; i++)
{
if (sprite.Textures[i]?.Texture != null)
{
xmlWriter.WriteStartElement("frame");
xmlWriter.WriteAttributeString("index", i.ToString());
xmlWriter.WriteString("images\\" + sprite.Name.Content + "_" + i + ".png");
xmlWriter.WriteEndElement();
}
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
// Save sprite images
for (int i = 0; i < sprite.Textures.Count; i++)
if (sprite.Textures[i]?.Texture != null)
{
// Fix sprite size
var bitmapNew = new Bitmap((int)sprite.Width,(int)sprite.Height);
var bitmapOrigin = worker.GetTextureFor(sprite.Textures[i].Texture, Path.GetFileNameWithoutExtension(projFolder + "/sprites/images/" + sprite.Name.Content + "_" + i + ".png"));
//worker.ExportAsPNG(sprite.Textures[i].Texture, projFolder + "/sprites/images/" + sprite.Name.Content + "_" + i + ".png");
var g = Graphics.FromImage(bitmapNew);
g.DrawImage(bitmapOrigin, (int)sprite.Textures[i].Texture.TargetX, (int)sprite.Textures[i].Texture.TargetY);
bitmapNew.Save(projFolder + "/sprites/images/" + sprite.Name.Content + "_" + i + ".png");
bitmapNew.Dispose();
bitmapOrigin.Dispose();
}
}
// --------------- Export Background ---------------
async Task ExportBackground()
{
Directory.CreateDirectory(projFolder + "/background/images");
await Task.Run(() => Parallel.ForEach(Data.Backgrounds, ExportBackground));
}
void ExportBackground(UndertaleBackground background)
{
// Save the backgound GMX
var xmlWriter = XmlWriter.Create(projFolder + "/background/" + background.Name.Content + ".background.gmx");
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("background");
xmlWriter.WriteStartElement("istileset");
xmlWriter.WriteString("-1");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("tilewidth");
xmlWriter.WriteString(background.Texture.BoundingWidth.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("tileheight");
xmlWriter.WriteString(background.Texture.BoundingHeight.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("tilexoff");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("tileyoff");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("tilehsep");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("tilevsep");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("HTile");
xmlWriter.WriteString("-1");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("VTile");
xmlWriter.WriteString("-1");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("TextureGroups");
xmlWriter.WriteStartElement("TextureGroup0");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("For3D");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("width");
xmlWriter.WriteString(background.Texture.BoundingWidth.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("height");
xmlWriter.WriteString(background.Texture.BoundingHeight.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("data");
xmlWriter.WriteString("images\\" + background.Name.Content + ".png");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
// Save background images
worker.ExportAsPNG(background.Texture, projFolder + "/background/images/" + background.Name.Content + ".png");
}
// --------------- Export Object ---------------
async Task ExportGameObjects()
{
Directory.CreateDirectory(projFolder + "/objects");
await Task.Run(() => Parallel.ForEach(Data.GameObjects, ExportGameObject));
}
void ExportGameObject(UndertaleGameObject gameObject)
{
// Save the object GMX
var xmlWriter = XmlWriter.Create(projFolder + "/objects/" + gameObject.Name.Content + ".object.gmx");
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("object");
xmlWriter.WriteStartElement("spriteName");
xmlWriter.WriteString(gameObject.Sprite is null ? "<undefined>" : gameObject.Sprite.Name.Content);
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("solid");
xmlWriter.WriteString(BoolToString(gameObject.Solid));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("visible");
xmlWriter.WriteString(BoolToString(gameObject.Visible));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("depth");
xmlWriter.WriteString(gameObject.Depth.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("persistent");
xmlWriter.WriteString(BoolToString(gameObject.Persistent));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("parentName");
xmlWriter.WriteString(gameObject.ParentId is null ? "<undefined>" : gameObject.ParentId.Name.Content);
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("maskName");
xmlWriter.WriteString(gameObject.TextureMaskId is null ? "<undefined>" : gameObject.TextureMaskId.Name.Content);
xmlWriter.WriteEndElement();
// Save events
xmlWriter.WriteStartElement("events");
// Traversing the event type list
for (int i = 0; i < gameObject.Events.Count; i++)
{
// Determine if an event is empty
if (gameObject.Events[i].Count > 0)
{
// Traversing event list
foreach (var j in gameObject.Events[i])
{
xmlWriter.WriteStartElement("event");
xmlWriter.WriteAttributeString("eventtype", i.ToString());
if (j.EventSubtype == 4)
{
// To get the actual name of the collision object when the event type is a collision event
xmlWriter.WriteAttributeString("ename", Data.GameObjects[(int)j.EventSubtype].Name.Content);
}
else
{
// Get the sub-event number directly
xmlWriter.WriteAttributeString("enumb", j.EventSubtype.ToString());
}
// Save action
xmlWriter.WriteStartElement("action");
// Traversing the action list
foreach (var k in j.Actions)
{
xmlWriter.WriteStartElement("libid");
xmlWriter.WriteString(k.LibID.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("id");
xmlWriter.WriteString(k.ID.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("kind");
xmlWriter.WriteString(k.Kind.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("userelative");
xmlWriter.WriteString(BoolToString(k.UseRelative));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("isquestion");
xmlWriter.WriteString(BoolToString(k.IsQuestion));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("useapplyto");
xmlWriter.WriteString(BoolToString(k.UseApplyTo));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("exetype");
xmlWriter.WriteString(k.ExeType.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("functionname");
xmlWriter.WriteString(k.ActionName.Content);
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("codestring");
xmlWriter.WriteString("");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("whoName");
// All DND actions in data.win are converted to assembly code, automatically processing the performer
xmlWriter.WriteString("self");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("relative");
xmlWriter.WriteString(BoolToString(k.Relative));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("isnot");
xmlWriter.WriteString(BoolToString(k.IsNot));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("arguments");
xmlWriter.WriteStartElement("argument");
xmlWriter.WriteStartElement("kind");
xmlWriter.WriteString("1");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("string");
xmlWriter.WriteString(k.CodeId != null ? Decompiler.Decompile(k.CodeId, DECOMPILE_CONTEXT.Value) : "");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
}
// TODOPhysics
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
}
}
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
}
// --------------- Export Room ---------------
async Task ExportRooms()
{
Directory.CreateDirectory(projFolder + "/rooms");
await Task.Run(() => Parallel.ForEach(Data.Rooms, ExportRoom));
}
void ExportRoom(UndertaleRoom room)
{
// Save the room GMX
var xmlWriter = XmlWriter.Create(projFolder + "/rooms/" + room.Name.Content + ".room.gmx");
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("room");
// Room settings
xmlWriter.WriteStartElement("caption");
xmlWriter.WriteString(room.Caption.Content);
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("width");
xmlWriter.WriteString(room.Width.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("height");
xmlWriter.WriteString(room.Height.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("vsnap");
xmlWriter.WriteString("32");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("hsnap");
xmlWriter.WriteString("32");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("isometric");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("speed");
xmlWriter.WriteString(room.Speed.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("persistent");
xmlWriter.WriteString(BoolToString(room.Persistent));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("colour");
xmlWriter.WriteString(room.BackgroundColor.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("showcolour");
xmlWriter.WriteString(BoolToString(room.DrawBackgroundColor));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("code");
xmlWriter.WriteString(room.CreationCodeId is null ? "" : Decompiler.Decompile(room.CreationCodeId, context));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("enableViews");
xmlWriter.WriteString(BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.EnableViews)));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("clearViewBackground");
xmlWriter.WriteString(BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ShowColor)));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("clearDisplayBuffer");
xmlWriter.WriteString(BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ClearDisplayBuffer)));
xmlWriter.WriteEndElement();
// TODOMakerSettings
// Room backgrounds
xmlWriter.WriteStartElement("backgrounds");
foreach (var i in room.Backgrounds)
{
xmlWriter.WriteStartElement("background");
xmlWriter.WriteAttributeString("visible", BoolToString(i.Enabled));
xmlWriter.WriteAttributeString("foreground", BoolToString(i.Foreground));
xmlWriter.WriteAttributeString("name", i.BackgroundDefinition is null ? "" : i.BackgroundDefinition.Name.Content);
xmlWriter.WriteAttributeString("x", i.X.ToString());
xmlWriter.WriteAttributeString("y", i.Y.ToString());
xmlWriter.WriteAttributeString("htiled", i.TileX.ToString());
xmlWriter.WriteAttributeString("vtiled", i.TileY.ToString());
xmlWriter.WriteAttributeString("hspeed", i.SpeedX.ToString());
xmlWriter.WriteAttributeString("vspeed", i.SpeedY.ToString());
// TODOStretch
xmlWriter.WriteAttributeString("stretch", "0");
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
// Room views
xmlWriter.WriteStartElement("views");
foreach (var i in room.Views)
{
xmlWriter.WriteStartElement("view");
xmlWriter.WriteAttributeString("visible", BoolToString(i.Enabled));
xmlWriter.WriteAttributeString("objName", i.ObjectId is null ? "<undefined>" : i.ObjectId.Name.Content);
xmlWriter.WriteAttributeString("xview", i.ViewX.ToString());
xmlWriter.WriteAttributeString("yview", i.ViewY.ToString());
xmlWriter.WriteAttributeString("wview", i.ViewWidth.ToString());
xmlWriter.WriteAttributeString("hview", i.ViewHeight.ToString());
xmlWriter.WriteAttributeString("xport", i.PortX.ToString());
xmlWriter.WriteAttributeString("yport", i.PortY.ToString());
xmlWriter.WriteAttributeString("wport", i.PortWidth.ToString());
xmlWriter.WriteAttributeString("hport", i.PortHeight.ToString());
xmlWriter.WriteAttributeString("hborder", i.BorderX.ToString());
xmlWriter.WriteAttributeString("vborder", i.BorderY.ToString());
xmlWriter.WriteAttributeString("hspeed", i.SpeedX.ToString());
xmlWriter.WriteAttributeString("vspeed", i.SpeedY.ToString());
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
// Room instances
xmlWriter.WriteStartElement("instances");
foreach (var i in room.GameObjects)
{
xmlWriter.WriteStartElement("instance");
xmlWriter.WriteAttributeString("objName", i.ObjectDefinition.Name.Content);
xmlWriter.WriteAttributeString("x", i.X.ToString());
xmlWriter.WriteAttributeString("y", i.Y.ToString());
xmlWriter.WriteAttributeString("name", "inst_" + i.InstanceID.ToString("X"));
// TODOLocked
xmlWriter.WriteAttributeString("locked", "0");
xmlWriter.WriteAttributeString("code", i.CreationCode != null ? Decompiler.Decompile(i.CreationCode, DECOMPILE_CONTEXT.Value) : "");
xmlWriter.WriteAttributeString("scaleX", i.ScaleX.ToString());
xmlWriter.WriteAttributeString("scaleY", i.ScaleY.ToString());
xmlWriter.WriteAttributeString("colour", i.Color.ToString());
xmlWriter.WriteAttributeString("rotation", i.Rotation.ToString());
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
// Room tiles
xmlWriter.WriteStartElement("tiles");
foreach (var i in room.Tiles)
{
xmlWriter.WriteStartElement("tile");
xmlWriter.WriteAttributeString("bgName", i.BackgroundDefinition.Name.Content);
xmlWriter.WriteAttributeString("x", i.X.ToString());
xmlWriter.WriteAttributeString("y", i.Y.ToString());
xmlWriter.WriteAttributeString("w", i.Width.ToString());
xmlWriter.WriteAttributeString("h", i.Height.ToString());
xmlWriter.WriteAttributeString("xo", i.SourceX.ToString());
xmlWriter.WriteAttributeString("yo", i.SourceY.ToString());
xmlWriter.WriteAttributeString("id", i.InstanceID.ToString());
xmlWriter.WriteAttributeString("name", "inst_" + i.InstanceID.ToString("X"));
xmlWriter.WriteAttributeString("depth", i.TileDepth.ToString());
// TODOLocked
xmlWriter.WriteAttributeString("locked", "0");
xmlWriter.WriteAttributeString("colour", i.Color.ToString());
xmlWriter.WriteAttributeString("scaleX", i.ScaleX.ToString());
xmlWriter.WriteAttributeString("scaleY", i.ScaleY.ToString());
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
// TODORoom physics
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
}
// --------------- Export Sound ---------------
async Task ExportSounds()
{
Directory.CreateDirectory(projFolder + "/sound/audio");
await Task.Run(() => Parallel.ForEach(Data.Sounds, ExportSound));
}
void ExportSound(UndertaleSound sound)
{
// Save the sound GMX
var xmlWriter = XmlWriter.Create(projFolder + "/sound/" + sound.Name.Content + ".sound.gmx");
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("sound");
xmlWriter.WriteStartElement("kind");
// Inferred by file extension
xmlWriter.WriteString(Path.GetExtension(sound.File.Content) == ".ogg" ? "3" : "0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("extension");
xmlWriter.WriteString(Path.GetExtension(sound.File.Content));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("origname");
xmlWriter.WriteString("sound\\audio\\" + sound.File.Content);
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("effects");
xmlWriter.WriteString(sound.Effects.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("volume");
xmlWriter.WriteString(sound.Volume.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("pan");
// TODOPan
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("bitRates");
// TODOBitRates
xmlWriter.WriteString("192");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("sampleRates");
// TODOSampleRates
xmlWriter.WriteStartElement("sampleRate");
xmlWriter.WriteString("44100");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("types");
// TODOTypes
xmlWriter.WriteStartElement("type");
xmlWriter.WriteString("1");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("bitDepths");
// TODOBitDepths
xmlWriter.WriteStartElement("bitDepth");
xmlWriter.WriteString("16");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("preload");
// TODOPreload
xmlWriter.WriteString("-1");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("data");
xmlWriter.WriteString(Path.GetFileName(sound.File.Content));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("compressed");
// Inferred by file extension
xmlWriter.WriteString(Path.GetExtension(sound.File.Content) == ".ogg" ? "1" : "0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("streamed");
// Inferred by file extension
xmlWriter.WriteString(Path.GetExtension(sound.File.Content) == ".ogg" ? "1" : "0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("uncompressOnLoad");
// TODOUncompressOnLoad
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("audioGroup");
// TODOAudioGroup
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
// Save sound files
if (sound.AudioFile != null)
File.WriteAllBytes(projFolder + "/sound/audio/" + sound.File.Content, sound.AudioFile.Data);
}
// --------------- Export Script ---------------
async Task ExportScripts()
{
Directory.CreateDirectory(projFolder + "/scripts/");
await Task.Run(() => Parallel.ForEach(Data.Scripts, ExportScript));
}
void ExportScript(UndertaleScript script)
{
// Save GML files
File.WriteAllText(projFolder + "/scripts/" + script.Name.Content + ".gml", (script.Code != null ? Decompiler.Decompile(script.Code, DECOMPILE_CONTEXT.Value) : ""));
}
// --------------- Export Font ---------------
async Task ExportFonts()
{
Directory.CreateDirectory(projFolder + "/fonts/");
await Task.Run(() => Parallel.ForEach(Data.Fonts, ExportFont));
}
void ExportFont(UndertaleFont font)
{
// Save the font GMX
var xmlWriter = XmlWriter.Create(projFolder + "/fonts/" + font.Name.Content + ".font.gmx");
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("font");
xmlWriter.WriteStartElement("name");
xmlWriter.WriteString(font.Name.Content);
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("size");
xmlWriter.WriteString(font.EmSize.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("bold");
xmlWriter.WriteString(BoolToString(font.Bold));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("renderhq");
xmlWriter.WriteString("-1");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("italic");
xmlWriter.WriteString(BoolToString(font.Italic));
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("charset");
xmlWriter.WriteString(font.Charset.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("aa");
xmlWriter.WriteString(font.AntiAliasing.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("includeTTF");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("TTFName");
xmlWriter.WriteString("");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("texgroups");
xmlWriter.WriteStartElement("texgroup");
xmlWriter.WriteString("0");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("ranges");
xmlWriter.WriteStartElement("range0");
xmlWriter.WriteString(font.RangeStart.ToString() + "," + font.RangeEnd.ToString());
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("glyphs");
foreach (var i in font.Glyphs)
{
xmlWriter.WriteStartElement("glyph");
xmlWriter.WriteAttributeString("character", i.Character.ToString());
xmlWriter.WriteAttributeString("x", i.SourceX.ToString());
xmlWriter.WriteAttributeString("y", i.SourceY.ToString());
xmlWriter.WriteAttributeString("w", i.SourceWidth.ToString());
xmlWriter.WriteAttributeString("h", i.SourceHeight.ToString());
xmlWriter.WriteAttributeString("shift", i.Shift.ToString());
xmlWriter.WriteAttributeString("offset", i.Offset.ToString());
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("kerningPairs");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("image");
xmlWriter.WriteString(font.Name.Content + ".png");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
// Save font textures
worker.ExportAsPNG(font.Texture, projFolder + "/fonts/" + font.Name.Content + ".png");
}
// --------------- Generate project file ---------------
void ExportProjectFile()
{
// Write all resource indexes to project.gmx
var xmlWriter = XmlWriter.Create(projFolder + "Export_Project.project.gmx");
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("assets");
xmlWriter.WriteStartElement("sounds");
xmlWriter.WriteAttributeString("name", "sound");
foreach (var i in Data.Sounds)
{
xmlWriter.WriteStartElement("sound");
xmlWriter.WriteString("sound\\" + i.Name.Content);
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("sprites");
xmlWriter.WriteAttributeString("name", "sprites");
foreach (var i in Data.Sprites)
{
xmlWriter.WriteStartElement("sprite");
xmlWriter.WriteString("sprites\\" + i.Name.Content);
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("backgrounds");
xmlWriter.WriteAttributeString("name", "background");
foreach (var i in Data.Backgrounds)
{
xmlWriter.WriteStartElement("background");
xmlWriter.WriteString("background\\" + i.Name.Content);
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("scripts");
xmlWriter.WriteAttributeString("name", "scripts");
foreach (var i in Data.Scripts)
{
xmlWriter.WriteStartElement("script");
xmlWriter.WriteString("scripts\\" + i.Name.Content + ".gml");
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("fonts");
xmlWriter.WriteAttributeString("name", "fonts");
foreach (var i in Data.Fonts)
{
xmlWriter.WriteStartElement("font");
xmlWriter.WriteString("fonts\\" + i.Name.Content);
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("objects");
xmlWriter.WriteAttributeString("name", "objects");
foreach (var i in Data.GameObjects)
{
xmlWriter.WriteStartElement("object");
xmlWriter.WriteString("objects\\" + i.Name.Content);
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("rooms");
xmlWriter.WriteAttributeString("name", "rooms");
foreach (var i in Data.Rooms)
{
xmlWriter.WriteStartElement("room");
xmlWriter.WriteString("rooms\\" + i.Name.Content);
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
}