forked from AwfulNasty/UndertaleModTool
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix igms2fd to work with the new changes
- Loading branch information
1 parent
4c8133b
commit 008425a
Showing
1 changed file
with
190 additions
and
190 deletions.
There are no files selected for viewing
380 changes: 190 additions & 190 deletions
380
UndertaleModTool/Scripts/Community Scripts/ImportGMS2FontData.csx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,190 +1,190 @@ | ||
// ImportGMS2FontData by Dobby233Liu | ||
|
||
using System; | ||
using System.IO; | ||
using System.Drawing; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using UndertaleModLib; | ||
using UndertaleModLib.Util; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
|
||
EnsureDataLoaded(); | ||
|
||
ScriptMessage(@"ImportGMS2FontData by Dobby233Liu | ||
This script can import GM font asset data to your mod | ||
(Designed for the data IDE v2022.6.0.23 generates) | ||
Select the .yy file of the GM font asset you want to import" | ||
); | ||
|
||
string importFile = PromptLoadFile("yy", "GameMaker Studio 2 files (.yy)|*.yy|All files|*"); | ||
if (importFile == null) | ||
{ | ||
ScriptError("Import cancelled."); | ||
return; | ||
} | ||
|
||
JObject fontData = null; | ||
using (StreamReader file = File.OpenText(importFile)) | ||
{ | ||
using (JsonTextReader reader = new JsonTextReader(file)) | ||
{ | ||
fontData = JObject.Load(reader); | ||
} | ||
} | ||
|
||
string fontPath = Path.GetDirectoryName(importFile); | ||
string yyFilename = Path.GetFileNameWithoutExtension(importFile); | ||
string fontName = (string)fontData["name"] ?? yyFilename; | ||
string fontTexturePath = Path.Combine(fontPath, yyFilename + ".png"); | ||
// Failsafe to use font name | ||
if (!File.Exists(fontTexturePath)) | ||
fontTexturePath = Path.Combine(fontPath, fontName + ".png"); | ||
// If we still can't find the texture | ||
if (!File.Exists(fontTexturePath)) | ||
throw new ScriptException( | ||
$@"Could not find a texture file for the selected font. | ||
Try renaming the correct texture file to | ||
{yyFilename}.png | ||
and putting it in the same directory as the .yy file." | ||
); | ||
|
||
/* | ||
If true, the script will attempt to add the new font (if any) and the new font glyph texture that it created to a texture group | ||
This was an attempt to get fonts that this script creates appear in a specific 2022.3 game, but was proved unnecessary, as the problem was caused by something else | ||
*/ | ||
bool attemptToFixFontNotAppearing = false; // Data.GM2022_3; | ||
// Default to putting the font into the default texgroup | ||
UndertaleTextureGroupInfo fontTexGroup = Data.TextureGroupInfo.ByName("Default"); | ||
|
||
UndertaleFont font = Data.Fonts.ByName(fontName); | ||
if (font == null) | ||
{ | ||
font = new UndertaleFont() | ||
{ | ||
Name = Data.Strings.MakeString(fontName) | ||
}; | ||
Data.Fonts.Add(font); | ||
|
||
if (attemptToFixFontNotAppearing) | ||
{ | ||
if (fontTexGroup == null) | ||
throw new ScriptException("The default texture group doesn't exist??? (this shouldn't happen)"); | ||
fontTexGroup.Fonts.Add(new UndertaleResourceById<UndertaleFont, UndertaleChunkFONT>() { Resource = font }); | ||
} | ||
} | ||
else if (attemptToFixFontNotAppearing) | ||
{ | ||
// Try to find the texgroup that the font belongs to | ||
// Scariest LINQ query I've ever written (yet) | ||
fontTexGroup = Data.TextureGroupInfo | ||
.Where(t => t.Fonts.Any(f => f.Resource == font)) | ||
.DefaultIfEmpty(fontTexGroup) | ||
.FirstOrDefault(); | ||
if (fontTexGroup == null) | ||
throw new ScriptException("Existing font doesn't belong to any texture group AND the default texture group doesn't exist??? (this shouldn't happen)"); | ||
// Failsafe - put it in Default if it's not in there | ||
if (!fontTexGroup.Fonts.Any(f => f.Resource == font)) | ||
fontTexGroup.Fonts.Add(new UndertaleResourceById<UndertaleFont, UndertaleChunkFONT>() { Resource = font }); | ||
} | ||
|
||
// Prepare font texture | ||
Bitmap textureBitmap = new Bitmap(fontTexturePath); | ||
// Make the DPI exactly 96 for this bitmap | ||
textureBitmap.SetResolution(96.0F, 96.0F); | ||
|
||
UndertaleEmbeddedTexture texture = new UndertaleEmbeddedTexture(); | ||
// ??? Why? | ||
texture.Name = new UndertaleString("Texture " + Data.EmbeddedTextures.Count); | ||
texture.TextureData.TextureBlob = File.ReadAllBytes(fontTexturePath); | ||
Data.EmbeddedTextures.Add(texture); | ||
if (attemptToFixFontNotAppearing) | ||
fontTexGroup.TexturePages.Add(new UndertaleResourceById<UndertaleEmbeddedTexture, UndertaleChunkTXTR>() { Resource = texture }); | ||
|
||
UndertaleTexturePageItem texturePageItem = new UndertaleTexturePageItem(); | ||
// ??? Same as above | ||
texturePageItem.Name = new UndertaleString("PageItem " + Data.TexturePageItems.Count); | ||
texturePageItem.TexturePage = texture; | ||
texturePageItem.SourceX = 0; | ||
texturePageItem.SourceY = 0; | ||
texturePageItem.SourceWidth = (ushort)textureBitmap.Width; | ||
texturePageItem.SourceHeight = (ushort)textureBitmap.Height; | ||
texturePageItem.TargetX = 0; | ||
texturePageItem.TargetY = 0; | ||
texturePageItem.TargetWidth = (ushort)textureBitmap.Width; | ||
texturePageItem.TargetHeight = (ushort)textureBitmap.Height; | ||
texturePageItem.BoundingWidth = (ushort)textureBitmap.Width; | ||
texturePageItem.BoundingHeight = (ushort)textureBitmap.Height; | ||
Data.TexturePageItems.Add(texturePageItem); | ||
|
||
font.DisplayName = Data.Strings.MakeString((string)fontData["fontName"]); | ||
font.Texture = texturePageItem; | ||
font.Bold = (bool)fontData["bold"]; | ||
font.Italic = (bool)fontData["italic"]; | ||
// FIXME: Potentially causes float precision to be lost | ||
font.EmSize = (uint)fontData["size"]; | ||
// Save font size as a float in GMS2.3+ (shouldn't UML always save EmSize as a float for GMS2.3+ games??) | ||
font.EmSizeIsFloat = Data.IsVersionAtLeast(2, 3); | ||
font.Charset = (byte)fontData["charset"]; | ||
font.AntiAliasing = (byte)fontData["AntiAlias"]; | ||
// FIXME: ??? All YY files I've saw don't contain this | ||
font.ScaleX = 1; | ||
font.ScaleY = 1; | ||
// Ascender is GM2022.2+ | ||
if (fontData.ContainsKey("ascender")) | ||
font.Ascender = (uint)fontData["ascender"]; | ||
if (fontData.ContainsKey("ascenderOffset")) | ||
font.AscenderOffset = (int)fontData["ascenderOffset"]; | ||
|
||
// FIXME: Too complicated? | ||
List<int> charRangesUppersAndLowers = new(); | ||
foreach (JObject range in fontData["ranges"].Values<JObject>()) | ||
{ | ||
charRangesUppersAndLowers.Add((int)range["upper"]); | ||
charRangesUppersAndLowers.Add((int)range["lower"]); | ||
} | ||
charRangesUppersAndLowers.Sort(); | ||
// FIXME: Check the range by ourselves if ranges don't have it probably | ||
font.RangeStart = (ushort)charRangesUppersAndLowers.DefaultIfEmpty(0).FirstOrDefault(); | ||
font.RangeEnd = (uint)charRangesUppersAndLowers.DefaultIfEmpty(0xFFFF).LastOrDefault(); | ||
|
||
List<UndertaleFont.Glyph> glyphs = new(); | ||
// From what I've seen, the keys of the objects in glyphs is just the character property of the object itself but in string form | ||
foreach (KeyValuePair<string, JToken> glyphKVEntry in (JObject)fontData["glyphs"]) | ||
{ | ||
var glyphData = (JObject)glyphKVEntry.Value; | ||
glyphs.Add(new UndertaleFont.Glyph() | ||
{ | ||
Character = (ushort)glyphData["character"], | ||
SourceX = (ushort)glyphData["x"], | ||
SourceY = (ushort)glyphData["y"], | ||
SourceWidth = (ushort)glyphData["w"], | ||
SourceHeight = (ushort)glyphData["h"], | ||
Shift = (short)glyphData["shift"], | ||
Offset = (short)glyphData["offset"], | ||
}); | ||
} | ||
// Sort glyphs like UndertaleFontEditor to be safe | ||
glyphs.Sort((x, y) => x.Character.CompareTo(y.Character)); | ||
font.Glyphs.Clear(); | ||
foreach (var glyph in glyphs) | ||
font.Glyphs.Add(glyph); | ||
|
||
// TODO: Does this always exist? | ||
glyphs = font.Glyphs.ToList(); | ||
foreach (JObject kerningPair in fontData["kerningPairs"]?.Values<JObject>()) | ||
{ | ||
// Why do I need to do this. Thanks YoYo | ||
var first = (ushort)kerningPair["first"]; | ||
var glyph = glyphs.Find(x => x.Character == first); | ||
glyph.Kerning.Add(new UndertaleFont.Glyph.GlyphKerning() | ||
{ | ||
Other = (short)kerningPair["second"], | ||
Amount = (short)kerningPair["amount"], | ||
}); | ||
} | ||
|
||
ScriptMessage("Import complete."); | ||
// ImportGMS2FontData by Dobby233Liu | ||
|
||
using System; | ||
using System.IO; | ||
using System.Drawing; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using UndertaleModLib; | ||
using UndertaleModLib.Util; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
|
||
EnsureDataLoaded(); | ||
|
||
ScriptMessage(@"ImportGMS2FontData by Dobby233Liu | ||
This script can import GM font asset data to your mod | ||
(Designed for the data IDE v2022.6.0.23 generates) | ||
Select the .yy file of the GM font asset you want to import" | ||
); | ||
|
||
string importFile = PromptLoadFile("yy", "GameMaker Studio 2 files (.yy)|*.yy|All files|*"); | ||
if (importFile == null) | ||
{ | ||
ScriptError("Import cancelled."); | ||
return; | ||
} | ||
|
||
JObject fontData = null; | ||
using (StreamReader file = File.OpenText(importFile)) | ||
{ | ||
using (JsonTextReader reader = new JsonTextReader(file)) | ||
{ | ||
fontData = JObject.Load(reader); | ||
} | ||
} | ||
|
||
string fontPath = Path.GetDirectoryName(importFile); | ||
string yyFilename = Path.GetFileNameWithoutExtension(importFile); | ||
string fontName = (string)fontData["name"] ?? yyFilename; | ||
string fontTexturePath = Path.Combine(fontPath, yyFilename + ".png"); | ||
// Failsafe to use font name | ||
if (!File.Exists(fontTexturePath)) | ||
fontTexturePath = Path.Combine(fontPath, fontName + ".png"); | ||
// If we still can't find the texture | ||
if (!File.Exists(fontTexturePath)) | ||
throw new ScriptException( | ||
$@"Could not find a texture file for the selected font. | ||
Try renaming the correct texture file to | ||
{yyFilename}.png | ||
and putting it in the same directory as the .yy file." | ||
); | ||
|
||
/* | ||
If true, the script will attempt to add the new font (if any) and the new font glyph texture that it created to a texture group | ||
This was an attempt to get fonts that this script creates appear in a specific 2022.3 game, but was proved unnecessary, as the problem was caused by something else | ||
*/ | ||
bool attemptToFixFontNotAppearing = false; // Data.GM2022_3; | ||
// Default to putting the font into the default texgroup | ||
UndertaleTextureGroupInfo fontTexGroup = Data.TextureGroupInfo.ByName("Default"); | ||
|
||
UndertaleFont font = Data.Fonts.ByName(fontName); | ||
if (font == null) | ||
{ | ||
font = new UndertaleFont() | ||
{ | ||
Name = Data.Strings.MakeString(fontName) | ||
}; | ||
Data.Fonts.Add(font); | ||
|
||
if (attemptToFixFontNotAppearing) | ||
{ | ||
if (fontTexGroup == null) | ||
throw new ScriptException("The default texture group doesn't exist??? (this shouldn't happen)"); | ||
fontTexGroup.Fonts.Add(new UndertaleResourceById<UndertaleFont, UndertaleChunkFONT>() { Resource = font }); | ||
} | ||
} | ||
else if (attemptToFixFontNotAppearing) | ||
{ | ||
// Try to find the texgroup that the font belongs to | ||
// Scariest LINQ query I've ever written (yet) | ||
fontTexGroup = Data.TextureGroupInfo | ||
.Where(t => t.Fonts.Any(f => f.Resource == font)) | ||
.DefaultIfEmpty(fontTexGroup) | ||
.FirstOrDefault(); | ||
if (fontTexGroup == null) | ||
throw new ScriptException("Existing font doesn't belong to any texture group AND the default texture group doesn't exist??? (this shouldn't happen)"); | ||
// Failsafe - put it in Default if it's not in there | ||
if (!fontTexGroup.Fonts.Any(f => f.Resource == font)) | ||
fontTexGroup.Fonts.Add(new UndertaleResourceById<UndertaleFont, UndertaleChunkFONT>() { Resource = font }); | ||
} | ||
|
||
// Prepare font texture | ||
Bitmap textureBitmap = new Bitmap(fontTexturePath); | ||
// Make the DPI exactly 96 for this bitmap | ||
textureBitmap.SetResolution(96.0F, 96.0F); | ||
|
||
UndertaleEmbeddedTexture texture = new UndertaleEmbeddedTexture(); | ||
// ??? Why? | ||
texture.Name = new UndertaleString("Texture " + Data.EmbeddedTextures.Count); | ||
texture.TextureData.TextureBlob = File.ReadAllBytes(fontTexturePath); | ||
Data.EmbeddedTextures.Add(texture); | ||
if (attemptToFixFontNotAppearing) | ||
fontTexGroup.TexturePages.Add(new UndertaleResourceById<UndertaleEmbeddedTexture, UndertaleChunkTXTR>() { Resource = texture }); | ||
|
||
UndertaleTexturePageItem texturePageItem = new UndertaleTexturePageItem(); | ||
// ??? Same as above | ||
texturePageItem.Name = new UndertaleString("PageItem " + Data.TexturePageItems.Count); | ||
texturePageItem.TexturePage = texture; | ||
texturePageItem.SourceX = 0; | ||
texturePageItem.SourceY = 0; | ||
texturePageItem.SourceWidth = (ushort)textureBitmap.Width; | ||
texturePageItem.SourceHeight = (ushort)textureBitmap.Height; | ||
texturePageItem.TargetX = 0; | ||
texturePageItem.TargetY = 0; | ||
texturePageItem.TargetWidth = (ushort)textureBitmap.Width; | ||
texturePageItem.TargetHeight = (ushort)textureBitmap.Height; | ||
texturePageItem.BoundingWidth = (ushort)textureBitmap.Width; | ||
texturePageItem.BoundingHeight = (ushort)textureBitmap.Height; | ||
Data.TexturePageItems.Add(texturePageItem); | ||
|
||
font.DisplayName = Data.Strings.MakeString((string)fontData["fontName"]); | ||
font.Texture = texturePageItem; | ||
font.Bold = (bool)fontData["bold"]; | ||
font.Italic = (bool)fontData["italic"]; | ||
// FIXME: Potentially causes float precision to be lost | ||
font.EmSize = (uint)fontData["size"]; | ||
// Save font size as a float in GMS2.3+ (shouldn't UML always save EmSize as a float for GMS2.3+ games??) | ||
font.EmSizeIsFloat = Data.IsVersionAtLeast(2, 3); | ||
font.Charset = (byte)fontData["charset"]; | ||
font.AntiAliasing = (byte)fontData["AntiAlias"]; | ||
// FIXME: ??? All YY files I've saw don't contain this | ||
font.ScaleX = 1; | ||
font.ScaleY = 1; | ||
// Ascender is GM2022.2+ | ||
if (fontData.ContainsKey("ascender")) | ||
font.Ascender = (uint)fontData["ascender"]; | ||
if (fontData.ContainsKey("ascenderOffset")) | ||
font.AscenderOffset = (int)fontData["ascenderOffset"]; | ||
// TODO: SDFSpread | ||
|
||
// FIXME: Too complicated? | ||
List<int> charRangesUppersAndLowers = new(); | ||
foreach (JObject range in fontData["ranges"].Values<JObject>()) | ||
{ | ||
charRangesUppersAndLowers.Add((int)range["upper"]); | ||
charRangesUppersAndLowers.Add((int)range["lower"]); | ||
} | ||
charRangesUppersAndLowers.Sort(); | ||
// FIXME: Check the range by ourselves if ranges don't have it probably | ||
font.RangeStart = (ushort)charRangesUppersAndLowers.DefaultIfEmpty(0).FirstOrDefault(); | ||
font.RangeEnd = (uint)charRangesUppersAndLowers.DefaultIfEmpty(0xFFFF).LastOrDefault(); | ||
|
||
List<UndertaleFont.Glyph> glyphs = new(); | ||
// From what I've seen, the keys of the objects in glyphs is just the character property of the object itself but in string form | ||
foreach (KeyValuePair<string, JToken> glyphKVEntry in (JObject)fontData["glyphs"]) | ||
{ | ||
var glyphData = (JObject)glyphKVEntry.Value; | ||
glyphs.Add(new UndertaleFont.Glyph() | ||
{ | ||
Character = (ushort)glyphData["character"], | ||
SourceX = (ushort)glyphData["x"], | ||
SourceY = (ushort)glyphData["y"], | ||
SourceWidth = (ushort)glyphData["w"], | ||
SourceHeight = (ushort)glyphData["h"], | ||
Shift = (short)glyphData["shift"], | ||
Offset = (short)glyphData["offset"], | ||
}); | ||
} | ||
// Sort glyphs like UndertaleFontEditor to be safe | ||
glyphs.Sort((x, y) => x.Character.CompareTo(y.Character)); | ||
font.Glyphs.Clear(); | ||
foreach (var glyph in glyphs) | ||
font.Glyphs.Add(glyph); | ||
|
||
glyphs = font.Glyphs.ToList(); | ||
foreach (JObject kerningPair in fontData["kerningPairs"]?.Values<JObject>()) | ||
{ | ||
// Why do I need to do this. Thanks YoYo | ||
var first = (ushort)kerningPair["first"]; | ||
var glyph = glyphs.Find(x => x.Character == first); | ||
glyph.Kerning.Add(new UndertaleFont.Glyph.GlyphKerning() | ||
{ | ||
Character = (short)kerningPair["second"], | ||
ShiftModifier = (short)kerningPair["amount"], | ||
}); | ||
} | ||
|
||
ScriptMessage("Import complete."); |