Skip to content
Open
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
153 changes: 150 additions & 3 deletions UndertaleModTool/Scripts/Resource Exporters/ExportAllFonts.csx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,165 @@ using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Controls;
using UndertaleModLib.Util;
using System.Linq;

EnsureDataLoaded();

string fntFolder = PromptChooseDirectory();
if (fntFolder is null)
{
return;

class FontEntry
{
public FontEntry(UndertaleFont font, bool @checked)
{
Font = font;
FontNameSafe = font.Name?.Content?.Replace("_", "__");
Checked = @checked;
}

public UndertaleFont Font { get; }
public string FontNameSafe { get; }
public bool Checked { get; set; }
}

SetProgressBar(null, "Fonts", 0, Data.Fonts.Count);
public UndertaleFont[] SelectFonts()
{
double minWidth = 420;
double minHeight = 430;
Window window = new()
{
MinWidth = minWidth,
MinHeight = minHeight,
Width = minWidth,
Height = minHeight,
Title = "Select fonts to export"
};
window.IsVisibleChanged += (_, _) =>
{
// There is no check for `IsVisible` or `IsLoaded`,
// because, apparently, it works differently for programmatically created window

if (Settings.Instance.EnableDarkMode)
MainWindow.SetDarkTitleBarForWindow(window, true, false);
};

FontEntry[] fonts = Data.Fonts?.Select(x => new FontEntry(x, true)).ToArray();

Grid contentGrid = new();
contentGrid.RowDefinitions.Add(new() { Height = new(1, GridUnitType.Star), MinHeight = 300 });
contentGrid.RowDefinitions.Add(new() { Height = GridLength.Auto });
contentGrid.RowDefinitions.Add(new() { Height = GridLength.Auto });

ListBox fontListBox = new()
{
ItemsSource = fonts,
Margin = new(10, 10, 10, 0),
MinWidth = 380,
SelectionMode = SelectionMode.Multiple
};
var appResources = Application.Current.Resources;
var bgBrush = (appResources?[SystemColors.ControlBrushKey]) as SolidColorBrush;
if (bgBrush is not null)
fontListBox.Background = bgBrush;

Style itemContStyle = new(typeof(ListBoxItem));
itemContStyle.Setters.Add(new Setter(ListBoxItem.IsSelectedProperty, new Binding("Checked") { Mode = BindingMode.TwoWay }));
fontListBox.ItemContainerStyle = itemContStyle;

// Microsoft recommends to use `XAMLReader.Load()`,
// but it sucks in two ways:
// 1) It's difficult to modify, as there is no syntax highlighting, error checking, and auto-indentation.
// 2) In order to add the event listeners, you have to add them later, by accessing each element by name.
//
// When `FrameworkElementFactory` will be removed from C#, then any AI assistant (e.g. ChatGPT, DeepSeek)
// can generate XAML code from this C# code easily, with some minor tweaks (I've checked it).
// I mean even for the whole window.
DataTemplate fontTemplate = new();
FrameworkElementFactory templateFactory = new(typeof(CheckBox));
templateFactory.SetValue(CheckBox.IsCheckedProperty, new Binding("Checked") { Mode = BindingMode.TwoWay });
templateFactory.SetValue(CheckBox.ContentProperty, new Binding("FontNameSafe") { Mode = BindingMode.OneTime });
fontTemplate.VisualTree = templateFactory;
fontListBox.ItemTemplate = fontTemplate;

StackPanel selectStackPanel = new()
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(10, 7, 0, 0)
};
ButtonDark selectAllButton = new()
{
Content = "Select all",
Height = 26,
Width = 63
};
selectAllButton.Click += (_, _) => fontListBox.SelectAll();
ButtonDark deselectAllButton = new()
{
Content = "Deselect all",
Margin = new Thickness(5, 0, 0, 0),
Height = 26,
Width = 71
};
deselectAllButton.Click += (_, _) => fontListBox.UnselectAll();
selectStackPanel.Children.Add(selectAllButton);
selectStackPanel.Children.Add(deselectAllButton);

ButtonDark okButton = new()
{
Content = "OK",
Margin = new Thickness(0, 16, 0, 16),
Width = 80,
Height = 32,
FontSize = 16
};
okButton.Click += (_, _) =>
{
var checkedFonts = fonts.Where(f => f.Checked)
.Select(f => f.Font)
.ToArray();
if (checkedFonts.Length == 0)
{
window.ShowError("No fonts are selected.");
return;
}

window.Tag = checkedFonts;
window.DialogResult = true;
window.Close();
};

contentGrid.Children.Add(fontListBox);
contentGrid.Children.Add(selectStackPanel);
contentGrid.Children.Add(okButton);
Grid.SetRow(fontListBox, 0);
Grid.SetRow(selectStackPanel, 1);
Grid.SetRow(okButton, 2);

window.Content = contentGrid;

if (window.ShowDialog() == true)
{
var selectedFonts = window.Tag as UndertaleFont[];
if (selectedFonts is null)
return null; // Shouldn't happen

return selectedFonts;
}

return null;
}

var selectedFonts = SelectFonts();
if (selectedFonts is null)
return;

SetProgressBar(null, "Fonts", 0, selectedFonts.Length);
StartProgressBarUpdater();

TextureWorker worker = null;
Expand All @@ -28,7 +175,7 @@ HideProgressBar();

async Task DumpFonts()
{
await Task.Run(() => Parallel.ForEach(Data.Fonts, DumpFont));
await Task.Run(() => Parallel.ForEach(selectedFonts, DumpFont));
}

void DumpFont(UndertaleFont font)
Expand Down