Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility upgrade of scripts involving textures #1890

Merged
merged 5 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion UndertaleModCli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@
GetType().GetTypeInfo().Assembly,
typeof(JsonConvert).GetTypeInfo().Assembly,
typeof(System.Text.RegularExpressions.Regex).GetTypeInfo().Assembly,
typeof(TextureWorker).GetTypeInfo().Assembly)
typeof(TextureWorker).GetTypeInfo().Assembly,
typeof(ImageMagick.MagickImage).GetTypeInfo().Assembly)
// "WithEmitDebugInformation(true)" not only lets us to see a script line number which threw an exception,
// but also provides other useful debug info when we run UMT in "Debug".
.WithEmitDebugInformation(true);
Expand Down Expand Up @@ -731,7 +732,7 @@
/// Evaluates and executes given C# code.
/// </summary>
/// <param name="code">The C# string to execute</param>
/// <param name="scriptFile">The path to the script file where <see cref="code"/> was executed from.

Check warning on line 735 in UndertaleModCli/Program.cs

View workflow job for this annotation

GitHub Actions / publish_cli (macOS-latest, Debug, false)

XML comment has cref attribute 'code' that could not be resolved

Check warning on line 735 in UndertaleModCli/Program.cs

View workflow job for this annotation

GitHub Actions / publish_cli (macOS-latest, Debug, false)

XML comment has cref attribute 'code' that could not be resolved

Check warning on line 735 in UndertaleModCli/Program.cs

View workflow job for this annotation

GitHub Actions / publish_cli (ubuntu-latest, Debug, false)

XML comment has cref attribute 'code' that could not be resolved

Check warning on line 735 in UndertaleModCli/Program.cs

View workflow job for this annotation

GitHub Actions / publish_cli (ubuntu-latest, Debug, false)

XML comment has cref attribute 'code' that could not be resolved

Check warning on line 735 in UndertaleModCli/Program.cs

View workflow job for this annotation

GitHub Actions / publish_cli (windows-latest, Debug, false)

XML comment has cref attribute 'code' that could not be resolved

Check warning on line 735 in UndertaleModCli/Program.cs

View workflow job for this annotation

GitHub Actions / publish_cli (windows-latest, Debug, false)

XML comment has cref attribute 'code' that could not be resolved
/// Leave as null, if it wasn't executed from a script file</param>
private void RunCSharpCode(string code, string scriptFile = null)
{
Expand Down
6 changes: 3 additions & 3 deletions UndertaleModLib/Util/GMImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -849,12 +849,12 @@ public MagickImage GetMagickImage()
}

/// <summary>
/// Creates a new raw format <see cref="GMImage"/> with the contents of the provided <see cref="MagickImage"/>.
/// Creates a new raw format <see cref="GMImage"/> with the contents of the provided <see cref="IMagickImage"/>.
/// </summary>
/// <remarks>
/// This modifies the image format of the provided <see cref="MagickImage"/> to avoid unnecessary copies.
/// This modifies the image format of the provided <see cref="IMagickImage"/> to avoid unnecessary copies.
/// </remarks>
public static GMImage FromMagickImage(MagickImage image)
public static GMImage FromMagickImage(IMagickImage<byte> image)
{
image.Format = MagickFormat.Bgra;
image.SetCompression(CompressionMethod.NoCompression);
Expand Down
9 changes: 5 additions & 4 deletions UndertaleModLib/Util/TextureWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public IMagickImage<byte> GetTextureFor(UndertaleTexturePageItem texPageItem, st
IMagickImage<byte> returnImage = croppedImage;
if (includePadding)
{
returnImage = new MagickImage(MagickColor.FromRgba(0, 0, 0, 0), exportWidth, exportHeight);
returnImage = new MagickImage(MagickColors.Transparent, exportWidth, exportHeight);
returnImage.Composite(croppedImage, texPageItem.TargetX, texPageItem.TargetY, CompositeOperator.Copy);
croppedImage.Dispose();
}
Expand Down Expand Up @@ -122,13 +122,14 @@ public static MagickImage ReadBGRAImageFromFile(string filePath)
}

/// <summary>
/// Performs a resize of the given image, if required, using bilinear interpolation. Always returns a new image.
/// Performs a resize of the given image, if required, using the specified interpolation (bilinear by default). Always returns a new image.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

considering people usually make pixel games in GM, are we sure we don't want to use NN as the default instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure. I believe the old method used wasn't nearest-neighbor, and there could be a benefit of it being very obvious you just tried to upscale a sprite on accident. In NN it can be slightly less obvious, especially if the aspect ratio only slightly differs. This would mostly affect the GUI though, which probably uses the default parameters currently.

/// </summary>
/// <param name="image">Image to be resized (without being modified).</param>
/// <param name="width">Desired width to resize to.</param>
/// <param name="height">Desired height to resize to.</param>
/// <param name="interpolateMethod">Pixel interpolation method to use, or specify none to use bilinear interpolation.</param>
/// <returns>A copy of the provided image, which is resized to the given dimensions when required.</returns>
public static IMagickImage<byte> ResizeImage(IMagickImage<byte> image, int width, int height)
public static IMagickImage<byte> ResizeImage(IMagickImage<byte> image, int width, int height, PixelInterpolateMethod interpolateMethod = PixelInterpolateMethod.Bilinear)
{
// Clone image
IMagickImage<byte> newImage = image.Clone();
Expand All @@ -140,7 +141,7 @@ public static IMagickImage<byte> ResizeImage(IMagickImage<byte> image, int width
}

// Resize using bilinear interpolation
newImage.InterpolativeResize(width, height, PixelInterpolateMethod.Bilinear);
newImage.InterpolativeResize(width, height, interpolateMethod);
return newImage;
}

Expand Down
48 changes: 28 additions & 20 deletions UndertaleModTool/Editors/UndertaleTexturePageItemEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,35 +74,43 @@ private void SwitchDataContext(object sender, DependencyPropertyChangedEventArgs

private void ReloadTexturePage(object sender, PropertyChangedEventArgs e)
{
UndertaleTexturePageItem item = (DataContext as UndertaleTexturePageItem);
if (item is null)
return;
// Invoke dispatcher to only perform updates on UI thread
Dispatcher.Invoke(() =>
{
UndertaleTexturePageItem item = (DataContext as UndertaleTexturePageItem);
if (item is null)
return;

if (e.PropertyName != nameof(UndertaleTexturePageItem.TexturePage))
return;
if (e.PropertyName != nameof(UndertaleTexturePageItem.TexturePage))
return;

UpdateImages(item);
UpdateImages(item);

// Start listening for (new) texture image updates
if (_textureDataContext is not null)
{
_textureDataContext.PropertyChanged -= ReloadTextureImage;
}
_textureDataContext = item.TexturePage.TextureData;
_textureDataContext.PropertyChanged += ReloadTextureImage;
// Start listening for (new) texture image updates
if (_textureDataContext is not null)
{
_textureDataContext.PropertyChanged -= ReloadTextureImage;
}
_textureDataContext = item.TexturePage.TextureData;
_textureDataContext.PropertyChanged += ReloadTextureImage;
});
}

private void ReloadTextureImage(object sender, PropertyChangedEventArgs e)
{
UndertaleTexturePageItem item = (DataContext as UndertaleTexturePageItem);
if (item is null)
return;
// Invoke dispatcher to only perform updates on UI thread
Dispatcher.Invoke(() =>
{
UndertaleTexturePageItem item = (DataContext as UndertaleTexturePageItem);
if (item is null)
return;

if (e.PropertyName != nameof(UndertaleEmbeddedTexture.TexData.Image))
return;
if (e.PropertyName != nameof(UndertaleEmbeddedTexture.TexData.Image))
return;

// If the texture's image was updated, reload it
UpdateImages(item);
// If the texture's image was updated, reload it
UpdateImages(item);
});
}

private void UnloadTexture(object sender, RoutedEventArgs e)
Expand Down
3 changes: 2 additions & 1 deletion UndertaleModTool/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@
.AddReferences(typeof(UndertaleObject).GetTypeInfo().Assembly,
GetType().GetTypeInfo().Assembly,
typeof(JsonConvert).GetTypeInfo().Assembly,
typeof(System.Text.RegularExpressions.Regex).GetTypeInfo().Assembly)
typeof(System.Text.RegularExpressions.Regex).GetTypeInfo().Assembly,
typeof(ImageMagick.MagickImage).GetTypeInfo().Assembly)
.WithEmitDebugInformation(true); //when script throws an exception, add a exception location (line number)
});

Expand Down Expand Up @@ -3093,7 +3094,7 @@
};
SetProgressBar();

using (WebClient webClient = new())

Check warning on line 3097 in UndertaleModTool/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, true)

'WebClient.WebClient()' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 3097 in UndertaleModTool/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, true)

'WebClient.WebClient()' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 3097 in UndertaleModTool/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, false)

'WebClient.WebClient()' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 3097 in UndertaleModTool/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, false)

'WebClient.WebClient()' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)
{
bool end = false;
bool ended = false;
Expand Down
50 changes: 27 additions & 23 deletions UndertaleModTool/Scripts/Builtin Scripts/BorderEnabler.csx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Imports and unlocks border images into PC version of the game

using UndertaleModLib.Util;

EnsureDataLoaded();

if (Data?.GeneralInfo?.DisplayName?.Content.ToLower() == "deltarune chapter 1 & 2")
Expand All @@ -20,37 +22,37 @@ else if (Data?.GeneralInfo?.DisplayName?.Content.ToLower() == "deltarune chapter
ScriptMessage("Border enabler (1080p edition)\nby krzys_h");

// Change os_type == 14 checks in scr_draw_screen_border to always pass
ReplaceTextInGML(("gml_Script_scr_draw_screen_border"), @"os_type == os_psvita", "0", true);
ReplaceTextInGML(("gml_Script_scr_draw_screen_border"), @"os_type == os_ps4", "1", true);
ReplaceTextInGML("gml_Script_scr_draw_screen_border", @"os_type == os_psvita", "0", true);
ReplaceTextInGML("gml_Script_scr_draw_screen_border", @"os_type == os_ps4", "1", true);

// Same for the code that calls it
ReplaceTextInGML(("gml_Object_obj_time_Draw_77"), @"global.osflavor >= 3", "1", true);
ReplaceTextInGML("gml_Object_obj_time_Draw_77", @"global.osflavor >= 3", "1", true);

//Remove checks from obj_time creation event
ReplaceTextInGML(("gml_Object_obj_time_Create_0"), @"os_type == os_psvita", "0", true);
ReplaceTextInGML(("gml_Object_obj_time_Create_0"), @"os_type == os_ps4", "1", true);
ReplaceTextInGML(("gml_Object_obj_time_Create_0"), @"global.osflavor >= 4", "1", true);
ReplaceTextInGML(("gml_Object_obj_time_Create_0"), @"global.osflavor >= 3", "1", true);
ReplaceTextInGML("gml_Object_obj_time_Create_0", @"os_type == os_psvita", "0", true);
ReplaceTextInGML("gml_Object_obj_time_Create_0", @"os_type == os_ps4", "1", true);
ReplaceTextInGML("gml_Object_obj_time_Create_0", @"global.osflavor >= 4", "1", true);
ReplaceTextInGML("gml_Object_obj_time_Create_0", @"global.osflavor >= 3", "1", true);

//Now patch out the check for the window scale, make it always be true
ReplaceTextInGML(("gml_Object_obj_time_Draw_76"), @"global.osflavor >= 4", "1", true);
ReplaceTextInGML(("gml_Object_obj_time_Draw_76"), @"os_type == os_switch_beta", "1", true);
ReplaceTextInGML("gml_Object_obj_time_Draw_76", @"global.osflavor >= 4", "1", true);
ReplaceTextInGML("gml_Object_obj_time_Draw_76", @"os_type == os_switch_beta", "1", true);
//Attempt border display fix in gml_Object_obj_time_Draw_76

//Patch out the OS checks for gml_Script_scr_draw_background_ps4, make PS Vita always false, and PS4 always true, simplifying code.
ReplaceTextInGML(("gml_Script_scr_draw_background_ps4"), @"os_type == os_psvita", "0", true);
ReplaceTextInGML(("gml_Script_scr_draw_background_ps4"), @"os_type == os_ps4", "1", true);
ReplaceTextInGML("gml_Script_scr_draw_background_ps4", @"os_type == os_psvita", "0", true);
ReplaceTextInGML("gml_Script_scr_draw_background_ps4", @"os_type == os_ps4", "1", true);

// Now, patch the settings menu!
ReplaceTextInGML(("gml_Object_obj_settingsmenu_Draw_0"), @"obj_time.j_ch > 0", "0", true);
ReplaceTextInGML(("gml_Object_obj_settingsmenu_Draw_0"), @"global.osflavor <= 2", "0", true);
ReplaceTextInGML(("gml_Object_obj_settingsmenu_Draw_0"), @"global.osflavor >= 4", "1", true);
ReplaceTextInGML("gml_Object_obj_settingsmenu_Draw_0", @"obj_time.j_ch > 0", "0", true);
ReplaceTextInGML("gml_Object_obj_settingsmenu_Draw_0", @"global.osflavor <= 2", "0", true);
ReplaceTextInGML("gml_Object_obj_settingsmenu_Draw_0", @"global.osflavor >= 4", "1", true);

//Remove code not applicable (PS Vita, Windows, <=2) and make some code always true (global.osflavor >= 4)
ReplaceTextInGML(("gml_Object_obj_time_Step_1"), @"os_type == os_psvita", "0", true);
ReplaceTextInGML(("gml_Object_obj_time_Step_1"), @"global.osflavor <= 2", "0", true);
ReplaceTextInGML(("gml_Object_obj_time_Step_1"), @"global.osflavor == 1", "0", true);
ReplaceTextInGML(("gml_Object_obj_time_Step_1"), @"global.osflavor >= 4", "1", true);
ReplaceTextInGML("gml_Object_obj_time_Step_1", @"os_type == os_psvita", "0", true);
ReplaceTextInGML("gml_Object_obj_time_Step_1", @"global.osflavor <= 2", "0", true);
ReplaceTextInGML("gml_Object_obj_time_Step_1", @"global.osflavor == 1", "0", true);
ReplaceTextInGML("gml_Object_obj_time_Step_1", @"global.osflavor >= 4", "1", true);

// Also resize the window so that the border can be seen without going fullscreen
Data.Functions.EnsureDefined("window_set_size", Data.Strings);
Expand All @@ -72,21 +74,23 @@ int lastTextPageItem = Data.TexturePageItems.Count - 1;
foreach (var path in Directory.EnumerateFiles(bordersPath))
{
UndertaleEmbeddedTexture newtex = new UndertaleEmbeddedTexture();
newtex.Name = new UndertaleString("Texture " + ++lastTextPage);
newtex.TextureData.TextureBlob = File.ReadAllBytes(path);
newtex.Name = new UndertaleString($"Texture {++lastTextPage}");
newtex.TextureData.Image = GMImage.FromPng(File.ReadAllBytes(path)); // Possibly other formats than PNG in the future, but no Undertale versions currently have them
Data.EmbeddedTextures.Add(newtex);
textures.Add(Path.GetFileName(path), newtex);
}

// Create texture fragments and assign them to existing (but empty) backgrounds
Action<string, UndertaleEmbeddedTexture, ushort, ushort, ushort, ushort> AssignBorderBackground = (name, tex, x, y, width, height) => {
Action<string, UndertaleEmbeddedTexture, ushort, ushort, ushort, ushort> AssignBorderBackground = (name, tex, x, y, width, height) =>
{
var bg = Data.Backgrounds.ByName(name);
if (bg == null) {
if (bg is null)
{
// The anime border does not exist on PC yet ;)
return;
}
UndertaleTexturePageItem tpag = new UndertaleTexturePageItem();
tpag.Name = new UndertaleString("PageItem " + ++lastTextPageItem);
tpag.Name = new UndertaleString($"PageItem {++lastTextPageItem}");
tpag.SourceX = x; tpag.SourceY = y; tpag.SourceWidth = width; tpag.SourceHeight = height;
tpag.TargetX = 0; tpag.TargetY = 0; tpag.TargetWidth = width; tpag.TargetHeight = height;
tpag.BoundingWidth = width; tpag.BoundingHeight = height;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.IO;
using System;
using System.Drawing;
using System.Windows.Forms;
using UndertaleModLib.Util;

Expand All @@ -25,10 +24,10 @@ else if (GameName == "deltarune chapter 1&2")
}
if (Data.GeneralInfo.Name.Content == "NXTALE" || Data.GeneralInfo.Name.Content.StartsWith("UNDERTALE"))
{
if (!ScriptQuestion("Would you like to apply this mod?"))
{
return;
}
if (!ScriptQuestion("Would you like to apply this mod?"))
{
return;
}
}
else if (Data.GeneralInfo.DisplayName.Content == "SURVEY_PROGRAM" || Data.GeneralInfo.DisplayName.Content == "DELTARUNE Chapter 1")
{
Expand Down
22 changes: 11 additions & 11 deletions UndertaleModTool/Scripts/Community Scripts/BorderEnablerv1_11.csx
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@ by Jockeholm, based off krzys_h's original script.
Converted to be more efficient by Grossley.");

// Show the border settings on PC.
ReplaceTextInGML(("gml_Object_obj_settingsmenu_Draw_0"), @"if (global.osflavor <= 2)
ReplaceTextInGML("gml_Object_obj_settingsmenu_Draw_0", @"if (global.osflavor <= 2)
{
menu_max = 2
if (obj_time.j_ch == 0)
menu_max = 1
}", "", true);
ReplaceTextInGML(("gml_Object_obj_settingsmenu_Draw_0"), @"if (global.osflavor >= 4)", "if (global.osflavor >= 1)", true);
ReplaceTextInGML("gml_Object_obj_settingsmenu_Draw_0", @"if (global.osflavor >= 4)", "if (global.osflavor >= 1)", true);

ReplaceTextInGML(("gml_Script_scr_draw_background_ps4"), @"if (os_type == os_ps4 || os_type == os_switch_beta)", "if (os_type == os_ps4 || os_type == os_switch_beta || os_type == os_windows)", true);
ReplaceTextInGML("gml_Script_scr_draw_background_ps4", @"if (os_type == os_ps4 || os_type == os_switch_beta)", "if (os_type == os_ps4 || os_type == os_switch_beta || os_type == os_windows)", true);

ReplaceTextInGML(("gml_Script_scr_draw_screen_border"), @"if (os_type == os_ps4 || os_type == os_switch_beta)", "if (os_type == os_ps4 || os_type == os_switch_beta || os_type == os_windows)", true);
ReplaceTextInGML("gml_Script_scr_draw_screen_border", @"if (os_type == os_ps4 || os_type == os_switch_beta)", "if (os_type == os_ps4 || os_type == os_switch_beta || os_type == os_windows)", true);

ReplaceTextInGML(("gml_Script_scr_draw_screen_border"), @"if (os_type == os_switch_beta)", "if (os_type == os_switch_beta || os_type == os_windows)", true);
ReplaceTextInGML("gml_Script_scr_draw_screen_border", @"if (os_type == os_switch_beta)", "if (os_type == os_switch_beta || os_type == os_windows)", true);

// Enable the dog border unlock
ReplaceTextInGML(("gml_Object_obj_rarependant_Step_1"), @"if (global.osflavor == 5)", "if (global.osflavor >= 1)", true);
ReplaceTextInGML("gml_Object_obj_rarependant_Step_1", @"if (global.osflavor == 5)", "if (global.osflavor >= 1)", true);

// Load borders
ReplaceTextInGML(("gml_Object_obj_time_Step_1"), @"scr_enable_screen_border(global.osflavor >= 4)", "scr_enable_screen_border(global.osflavor >= 1)", true);
ReplaceTextInGML("gml_Object_obj_time_Step_1", @"scr_enable_screen_border(global.osflavor >= 4)", "scr_enable_screen_border(global.osflavor >= 1)", true);

// Resize the game window to account for the borders
//Data.GeneralInfo.DefaultWindowWidth = 1920; // This setup prevents the game from starting??
Expand All @@ -51,12 +51,12 @@ Data.Code.ByName("gml_Script_SCR_GAMESTART").AppendGML(@"
window_set_size(960, 540)
", Data);

ReplaceTextInGML(("gml_Object_obj_time_Draw_77"), @"else
ReplaceTextInGML("gml_Object_obj_time_Draw_77", @"else
{
global.window_xofs = 0
global.window_yofs = 0
}", "", true);
ReplaceTextInGML(("gml_Object_obj_time_Draw_77"), @"if (global.osflavor >= 3)", "if (true)", true);
ReplaceTextInGML(("gml_Object_obj_time_Create_0"), @"if (global.osflavor >= 3)", "if (global.osflavor >= 1)", true);
ReplaceTextInGML(("gml_Object_obj_time_Draw_76"), @"else if (global.osflavor >= 4)", "else if (global.osflavor >= 1)", true);
ReplaceTextInGML("gml_Object_obj_time_Draw_77", @"if (global.osflavor >= 3)", "if (true)", true);
ReplaceTextInGML("gml_Object_obj_time_Create_0", @"if (global.osflavor >= 3)", "if (global.osflavor >= 1)", true);
ReplaceTextInGML("gml_Object_obj_time_Draw_76", @"else if (global.osflavor >= 4)", "else if (global.osflavor >= 1)", true);
ScriptMessage("Finished.");
Loading
Loading