Compare commits
11 commits
038a4c1917
...
81e89b84fc
Author | SHA1 | Date | |
---|---|---|---|
81e89b84fc | |||
![]() |
6ec4691448 | ||
![]() |
349983498b | ||
![]() |
74e8f74385 | ||
![]() |
90bf7f24f3 | ||
![]() |
f26c349ed9 | ||
![]() |
39b8958d9c | ||
![]() |
c0ca4e1adc | ||
![]() |
e3c753b664 | ||
![]() |
a107b80c1d | ||
![]() |
47174b0e2f |
2 changed files with 110 additions and 49 deletions
|
@ -10,12 +10,15 @@ using System.Reflection;
|
|||
using UndertaleModLib.Models;
|
||||
using UndertaleModLib.Util;
|
||||
using UndertaleModLib.Decompiler;
|
||||
using Underanalyzer.Decompiler;
|
||||
|
||||
string GameName = Data.GeneralInfo.Name.ToString().Replace(@"""",""); //Name == "Project" -> Project
|
||||
int progress = 0;
|
||||
string projFolder = GetFolder(FilePath) + "Export_Project" + Path.DirectorySeparatorChar;
|
||||
TextureWorker worker = new TextureWorker();
|
||||
ThreadLocal<DecompileContext> DECOMPILE_CONTEXT = new ThreadLocal<DecompileContext>(() => new DecompileContext(Data, false));
|
||||
string projFolder = GetFolder(FilePath) + GameName + ".gmx" + Path.DirectorySeparatorChar;
|
||||
TextureWorker worker = new();
|
||||
GlobalDecompileContext decompileContext = new(Data);
|
||||
string gmxDeclaration = "This Document is generated by GameMaker, if you edit it by hand then you do so at your own risk!";
|
||||
string eol = "\n"; // Linux: "\n", Windows: "\r\n"
|
||||
|
||||
if (Directory.Exists(projFolder))
|
||||
{
|
||||
|
@ -68,7 +71,7 @@ await ExportTimelines();
|
|||
GenerateProjectFile();
|
||||
|
||||
// --------------- Export completed ---------------
|
||||
worker.Cleanup();
|
||||
worker.Dispose(); // worker.Cleanup()?
|
||||
HideProgressBar();
|
||||
ScriptMessage("Export Complete.\n\nLocation: " + projFolder);
|
||||
|
||||
|
@ -115,8 +118,7 @@ void ExportSprite(UndertaleSprite sprite)
|
|||
new XElement("For3D", "0"),
|
||||
new XElement("width", sprite.Width.ToString()),
|
||||
new XElement("height", sprite.Height.ToString()),
|
||||
new XElement("frames"),
|
||||
new XElement("bbox_right", sprite.MarginRight.ToString())
|
||||
new XElement("frames")
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -134,22 +136,14 @@ void ExportSprite(UndertaleSprite sprite)
|
|||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(projFolder + "/sprites/" + sprite.Name.Content + ".sprite.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + "/sprites/" + sprite.Name.Content + ".sprite.gmx", gmx.ToString() + eol);
|
||||
|
||||
// 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();
|
||||
worker.ExportAsPNG(sprite.Textures[i].Texture, projFolder + "/sprites/images/" + sprite.Name.Content + "_" + i + ".png", null, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,8 +163,8 @@ void ExportBackground(UndertaleBackground background)
|
|||
new XComment(gmxDeclaration),
|
||||
new XElement("background",
|
||||
new XElement("istileset", "-1"),
|
||||
new XElement("tilewidth", background.Texture.BoundingWidth.ToString()),
|
||||
new XElement("tileheight", background.Texture.BoundingHeight.ToString()),
|
||||
new XElement("tilewidth", background.Texture == null ? "0" : background.Texture.BoundingWidth.ToString()),
|
||||
new XElement("tileheight", background.Texture == null ? "0" : background.Texture.BoundingHeight.ToString()),
|
||||
new XElement("tilexoff", "0"),
|
||||
new XElement("tileyoff", "0"),
|
||||
new XElement("tilehsep", "0"),
|
||||
|
@ -181,16 +175,17 @@ void ExportBackground(UndertaleBackground background)
|
|||
new XElement("TextureGroup0", "0")
|
||||
),
|
||||
new XElement("For3D", "0"),
|
||||
new XElement("width", background.Texture.BoundingWidth.ToString()),
|
||||
new XElement("height", background.Texture.BoundingHeight.ToString()),
|
||||
new XElement("width", background.Texture == null ? "0" : background.Texture.BoundingWidth.ToString()),
|
||||
new XElement("height",background.Texture == null ? "0" : background.Texture.BoundingHeight.ToString()),
|
||||
new XElement("data", "images\\" + background.Name.Content + ".png")
|
||||
)
|
||||
);
|
||||
|
||||
File.WriteAllText(projFolder + "/background/" + background.Name.Content + ".background.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + "/background/" + background.Name.Content + ".background.gmx", gmx.ToString() + eol);
|
||||
|
||||
// Save background images
|
||||
worker.ExportAsPNG(background.Texture, projFolder + "/background/images/" + background.Name.Content + ".png");
|
||||
if (background.Texture != null)
|
||||
worker.ExportAsPNG(background.Texture, projFolder + "/background/images/" + background.Name.Content + ".png");
|
||||
}
|
||||
// --------------- Export Object ---------------
|
||||
async Task ExportGameObjects()
|
||||
|
@ -213,10 +208,36 @@ void ExportGameObject(UndertaleGameObject gameObject)
|
|||
new XElement("persistent", BoolToString(gameObject.Persistent)),
|
||||
new XElement("parentName", gameObject.ParentId is null ? "<undefined>" : gameObject.ParentId.Name.Content),
|
||||
new XElement("maskName", gameObject.TextureMaskId is null ? "<undefined>" : gameObject.TextureMaskId.Name.Content),
|
||||
new XElement("events")
|
||||
new XElement("events"),
|
||||
|
||||
//Physics
|
||||
new XElement("PhysicsObject", BoolToString(gameObject.UsesPhysics)),
|
||||
new XElement("PhysicsObjectSensor", BoolToString(gameObject.IsSensor)),
|
||||
new XElement("PhysicsObjectShape", (uint)gameObject.CollisionShape),
|
||||
new XElement("PhysicsObjectDensity", gameObject.Density),
|
||||
new XElement("PhysicsObjectRestitution", gameObject.Restitution),
|
||||
new XElement("PhysicsObjectGroup", gameObject.Group),
|
||||
new XElement("PhysicsObjectLinearDamping", gameObject.LinearDamping),
|
||||
new XElement("PhysicsObjectAngularDamping", gameObject.AngularDamping),
|
||||
new XElement("PhysicsObjectFriction", gameObject.Friction),
|
||||
new XElement("PhysicsObjectAwake", BoolToString(gameObject.Awake)),
|
||||
new XElement("PhysicsObjectKinematic", BoolToString(gameObject.Kinematic)),
|
||||
new XElement("PhysicsShapePoints")
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
// Loop through PhysicsShapePoints List
|
||||
for (int _point = 0; _point < gameObject.PhysicsVertices.Count; _point++)
|
||||
{
|
||||
var _x = gameObject.PhysicsVertices[_point].X;
|
||||
var _y = gameObject.PhysicsVertices[_point].Y;
|
||||
|
||||
var physicsPointsNode = gmx.Element("object").Element("PhysicsShapePoints");
|
||||
physicsPointsNode.Add(new XElement("points",_x.ToString() + "," + _y.ToString()));
|
||||
}
|
||||
|
||||
// Traversing the event type list
|
||||
for (int i = 0; i < gameObject.Events.Count; i++)
|
||||
{
|
||||
|
@ -249,6 +270,13 @@ void ExportGameObject(UndertaleGameObject gameObject)
|
|||
// Traversing the action list
|
||||
foreach (var k in j.Actions)
|
||||
{
|
||||
DecompileContext dec_context = new(decompileContext, k.CodeId, Data.ToolInfo.DecompilerSettings);
|
||||
XElement act_string = null;
|
||||
try {
|
||||
act_string = new XElement("string", (k.CodeId != null && dec_context != null) ? dec_context.DecompileToString() : "");
|
||||
} catch (DecompilerException) {
|
||||
act_string = new XElement("string", "");
|
||||
}
|
||||
actionNode.Add(
|
||||
new XElement("libid", k.LibID.ToString()),
|
||||
new XElement("id", k.ID.ToString()),
|
||||
|
@ -257,7 +285,7 @@ void ExportGameObject(UndertaleGameObject gameObject)
|
|||
new XElement("isquestion", BoolToString(k.IsQuestion)),
|
||||
new XElement("useapplyto", BoolToString(k.UseApplyTo)),
|
||||
new XElement("exetype", k.ExeType.ToString()),
|
||||
new XElement("functionname", k.ActionName.Content),
|
||||
new XElement("functionname", k.ActionName != null ? k.ActionName.Content : ""),
|
||||
new XElement("codestring", ""),
|
||||
new XElement("whoName", "self"),
|
||||
new XElement("relative", BoolToString(k.Relative)),
|
||||
|
@ -265,7 +293,7 @@ void ExportGameObject(UndertaleGameObject gameObject)
|
|||
new XElement("arguments",
|
||||
new XElement("argument",
|
||||
new XElement("kind", "1"),
|
||||
new XElement("string", k.CodeId != null ? Decompiler.Decompile(k.CodeId, DECOMPILE_CONTEXT.Value) : "")
|
||||
act_string
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -273,12 +301,11 @@ void ExportGameObject(UndertaleGameObject gameObject)
|
|||
eventNode.Add(actionNode);
|
||||
eventsNode.Add(eventNode);
|
||||
|
||||
// TODO:Physics
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(projFolder + "/objects/" + gameObject.Name.Content + ".object.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + "/objects/" + gameObject.Name.Content + ".object.gmx", gmx.ToString() + eol);
|
||||
}
|
||||
|
||||
// --------------- Export Room ---------------
|
||||
|
@ -304,13 +331,29 @@ void ExportRoom(UndertaleRoom room)
|
|||
new XElement("speed", room.Speed.ToString()),
|
||||
new XElement("persistent", BoolToString(room.Persistent)),
|
||||
new XElement("colour", room.BackgroundColor.ToString()),
|
||||
new XElement("code", room.CreationCodeId != null ? Decompiler.Decompile(room.CreationCodeId, DECOMPILE_CONTEXT.Value) : ""),
|
||||
new XElement("showcolour", BoolToString(room.DrawBackgroundColor)),
|
||||
new XElement("code", room.CreationCodeId != null ? new DecompileContext(decompileContext, room.CreationCodeId).DecompileToString() : ""),
|
||||
new XElement("enableViews", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.EnableViews))),
|
||||
new XElement("clearViewBackground", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ShowColor))),
|
||||
new XElement("clearDisplayBuffer", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ClearDisplayBuffer)))
|
||||
//new XElement("clearDisplayBuffer", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ClearDisplayBuffer))),
|
||||
new XElement("makerSettings",
|
||||
new XElement("isSet", 0),
|
||||
new XElement("w", 0),
|
||||
new XElement("h", 0),
|
||||
new XElement("showGrid", 0),
|
||||
new XElement("showObjects", 0),
|
||||
new XElement("showTiles", 0),
|
||||
new XElement("showBackgrounds", 0),
|
||||
new XElement("showForegrounds", 0),
|
||||
new XElement("showViews", 0),
|
||||
new XElement("deleteUnderlyingObj", 0),
|
||||
new XElement("deleteUnderlyingTiles", 0),
|
||||
new XElement("page", 0),
|
||||
new XElement("xoffset", 0),
|
||||
new XElement("yoffset", 0)
|
||||
)
|
||||
)
|
||||
);
|
||||
// TODO:MakerSettings
|
||||
|
||||
// Room backgrounds
|
||||
var backgroundsNode = new XElement("backgrounds");
|
||||
|
@ -322,8 +365,8 @@ void ExportRoom(UndertaleRoom room)
|
|||
new XAttribute("name", i.BackgroundDefinition is null ? "" : i.BackgroundDefinition.Name.Content),
|
||||
new XAttribute("x", i.X.ToString()),
|
||||
new XAttribute("y", i.Y.ToString()),
|
||||
new XAttribute("htiled", i.TileX.ToString()),
|
||||
new XAttribute("vtiled", i.TileY.ToString()),
|
||||
new XAttribute("htiled", i.X.ToString()),
|
||||
new XAttribute("vtiled", i.Y.ToString()),
|
||||
new XAttribute("hspeed", i.SpeedX.ToString()),
|
||||
new XAttribute("vspeed", i.SpeedY.ToString()),
|
||||
new XAttribute("stretch", "0")
|
||||
|
@ -341,7 +384,8 @@ void ExportRoom(UndertaleRoom room)
|
|||
new XAttribute("objName", i.ObjectId is null ? "<undefined>" : i.ObjectId.Name.Content),
|
||||
new XAttribute("xview", i.ViewX.ToString()),
|
||||
new XAttribute("yview", i.ViewY.ToString()),
|
||||
new XAttribute("wview", i.ViewHeight.ToString()),
|
||||
new XAttribute("wview", i.ViewWidth.ToString()),
|
||||
new XAttribute("hview", i.ViewHeight.ToString()),
|
||||
new XAttribute("xport", i.PortX.ToString()),
|
||||
new XAttribute("yport", i.PortY.ToString()),
|
||||
new XAttribute("wport", i.PortWidth.ToString()),
|
||||
|
@ -365,7 +409,7 @@ void ExportRoom(UndertaleRoom room)
|
|||
new XAttribute("y", i.Y.ToString()),
|
||||
new XAttribute("name", "inst_" + i.InstanceID.ToString("X")),
|
||||
new XAttribute("locked", "0"),
|
||||
new XAttribute("code", i.CreationCode != null ? Decompiler.Decompile(i.CreationCode, DECOMPILE_CONTEXT.Value) : ""),
|
||||
new XAttribute("code", i.CreationCode != null ? new DecompileContext(decompileContext, i.CreationCode).DecompileToString() : ""),
|
||||
new XAttribute("scaleX", i.ScaleX.ToString()),
|
||||
new XAttribute("scaleY", i.ScaleY.ToString()),
|
||||
new XAttribute("colour", i.Color.ToString()),
|
||||
|
@ -399,9 +443,20 @@ void ExportRoom(UndertaleRoom room)
|
|||
}
|
||||
gmx.Element("room").Add(tilesNode);
|
||||
|
||||
// TODO:Room physics
|
||||
//Room Physics
|
||||
|
||||
gmx.Element("room").Add(
|
||||
new XElement("PhysicsWorld", room.World),
|
||||
new XElement("PhysicsWorldTop", room.Top),
|
||||
new XElement("PhysicsWorldLeft", room.Left),
|
||||
new XElement("PhysicsWorldRight", room.Right),
|
||||
new XElement("PhysicsWorldBottom", room.Bottom),
|
||||
new XElement("PhysicsWorldGravityX", room.GravityX),
|
||||
new XElement("PhysicsWorldGravityY", room.GravityY),
|
||||
new XElement("PhysicsWorldPixToMeters", room.MetersPerPixel)
|
||||
);
|
||||
|
||||
File.WriteAllText(projFolder + "/rooms/" + room.Name.Content + ".room.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + "/rooms/" + room.Name.Content + ".room.gmx", gmx.ToString() + eol);
|
||||
}
|
||||
|
||||
// --------------- Export Sound ---------------
|
||||
|
@ -422,9 +477,13 @@ void ExportSound(UndertaleSound sound)
|
|||
new XElement("extension", Path.GetExtension(sound.File.Content)),
|
||||
new XElement("origname", "sound\\audio\\" + sound.File.Content),
|
||||
new XElement("effects", sound.Effects.ToString()),
|
||||
new XElement("volume", sound.Volume.ToString()),
|
||||
new XElement("volume",
|
||||
new XElement("volume", sound.Volume.ToString())
|
||||
),
|
||||
new XElement("pan", "0"),
|
||||
new XElement("bitRates", "192"),
|
||||
new XElement("bitRates",
|
||||
new XElement("bitRate", "192")
|
||||
),
|
||||
new XElement("sampleRates",
|
||||
new XElement("sampleRate", "44100")
|
||||
),
|
||||
|
@ -443,7 +502,7 @@ void ExportSound(UndertaleSound sound)
|
|||
)
|
||||
);
|
||||
|
||||
File.WriteAllText(projFolder + "/sound/" + sound.Name.Content + ".sound.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + "/sound/" + sound.Name.Content + ".sound.gmx", gmx.ToString() + eol);
|
||||
|
||||
// Save sound files
|
||||
if (sound.AudioFile != null)
|
||||
|
@ -461,7 +520,7 @@ void ExportScript(UndertaleScript script)
|
|||
UpdateProgressBar(null, $"Exporting script: {script.Name.Content}", progress++, resourceNum);
|
||||
|
||||
// Save GML files
|
||||
File.WriteAllText(projFolder + "/scripts/" + script.Name.Content + ".gml", (script.Code != null ? Decompiler.Decompile(script.Code, DECOMPILE_CONTEXT.Value) : ""));
|
||||
File.WriteAllText(projFolder + "/scripts/" + script.Name.Content + ".gml", script.Code != null ? new DecompileContext(decompileContext, script.Code).DecompileToString() : "");
|
||||
}
|
||||
|
||||
// --------------- Export Font ---------------
|
||||
|
@ -513,7 +572,7 @@ void ExportFont(UndertaleFont font)
|
|||
glyphsNode.Add(glyphNode);
|
||||
}
|
||||
|
||||
File.WriteAllText(projFolder + "/fonts/" + font.Name.Content + ".font.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + "/fonts/" + font.Name.Content + ".font.gmx", gmx.ToString() + eol);
|
||||
|
||||
// Save font textures
|
||||
worker.ExportAsPNG(font.Texture, projFolder + "/fonts/" + font.Name.Content + ".png");
|
||||
|
@ -550,7 +609,7 @@ void ExportPath(UndertalePath path)
|
|||
);
|
||||
}
|
||||
|
||||
File.WriteAllText(projFolder + "/paths/" + path.Name.Content + ".path.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + "/paths/" + path.Name.Content + ".path.gmx", gmx.ToString() + eol);
|
||||
}
|
||||
|
||||
// --------------- Export Timelines ---------------
|
||||
|
@ -571,9 +630,9 @@ void ExportTimeline(UndertaleTimeline timeline)
|
|||
foreach (var i in timeline.Moments)
|
||||
{
|
||||
var entryNode = new XElement("entry");
|
||||
entryNode.Add(new XElement("step", i.Item1));
|
||||
entryNode.Add(new XElement("step", i.Step));
|
||||
entryNode.Add(new XElement("event"));
|
||||
foreach (var j in i.Item2)
|
||||
foreach (var j in i.Event)
|
||||
{
|
||||
entryNode.Element("event").Add(
|
||||
new XElement("action",
|
||||
|
@ -592,7 +651,7 @@ void ExportTimeline(UndertaleTimeline timeline)
|
|||
new XElement("arguments",
|
||||
new XElement("argument",
|
||||
new XElement("kind", "1"),
|
||||
new XElement("string", j.CodeId != null ? Decompiler.Decompile(j.CodeId, DECOMPILE_CONTEXT.Value) : "")
|
||||
new XElement("string", j.CodeId != null ? new DecompileContext(decompileContext, j.CodeId).DecompileToString() : "")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -601,7 +660,7 @@ void ExportTimeline(UndertaleTimeline timeline)
|
|||
gmx.Element("timeline").Add(entryNode);
|
||||
}
|
||||
|
||||
File.WriteAllText(projFolder + "/timelines/" + timeline.Name.Content + ".timeline.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + "/timelines/" + timeline.Name.Content + ".timeline.gmx", gmx.ToString() + eol);
|
||||
}
|
||||
|
||||
|
||||
|
@ -626,7 +685,7 @@ void GenerateProjectFile()
|
|||
WriteIndexes<UndertalePath>(gmx.Element("assets"), "paths", "paths", Data.Paths, "path", "paths\\");
|
||||
WriteIndexes<UndertaleTimeline>(gmx.Element("assets"), "timelines", "timelines", Data.Timelines, "timeline", "timelines\\");
|
||||
|
||||
File.WriteAllText(projFolder + "Export_Project.project.gmx", gmx.ToString());
|
||||
File.WriteAllText(projFolder + GameName + ".project.gmx", gmx.ToString() + eol);
|
||||
}
|
||||
|
||||
void WriteIndexes<T>(XElement rootNode, string elementName, string attributeName, IList<T> dataList, string oneName, string resourcePath, string fileExtension = "")
|
||||
|
@ -640,4 +699,4 @@ void WriteIndexes<T>(XElement rootNode, string elementName, string attributeName
|
|||
resourcesNode.Add(resourceNode);
|
||||
}
|
||||
rootNode.Add(resourcesNode);
|
||||
}
|
||||
}
|
|
@ -2,4 +2,6 @@
|
|||
|
||||
This is a script for UndertaleModTool, which can export game files as project files of GameMaker Studio.
|
||||
|
||||
Currently compatible with gms1.4, will support gms2 in the future.
|
||||
Currently compatible with gms1.4, will support gms2 in the future.
|
||||
|
||||
Original repo: https://github.com/cubeww/UndertaleModTool-ExportToProjectScript
|
Loading…
Add table
Add a link
Reference in a new issue