Merge remote-tracking branch 'origin/master' into v9-rollup

This commit is contained in:
github-actions[bot] 2023-09-19 21:15:29 +00:00
commit b384216d9d
8 changed files with 725 additions and 72 deletions

View file

@ -1,3 +1,5 @@
using System;
namespace Dalamud.Configuration.Internal;
/// <summary>
@ -14,4 +16,9 @@ internal sealed class DevPluginSettings
/// Gets or sets a value indicating whether this plugin should automatically reload on file change.
/// </summary>
public bool AutomaticReloading { get; set; } = false;
/// <summary>
/// Gets or sets an ID uniquely identifying this specific instance of a devPlugin.
/// </summary>
public Guid WorkingPluginId { get; set; } = Guid.Empty;
}

View file

@ -13,6 +13,7 @@
<AssemblyVersion>$(DalamudVersion)</AssemblyVersion>
<Version>$(DalamudVersion)</Version>
<FileVersion>$(DalamudVersion)</FileVersion>
<PackageLicenseExpression>AGPL-3.0-or-later</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Label="Output">

View file

@ -63,7 +63,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
private delegate void AddonOnRequestedUpdateDelegate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData);
private delegate void AddonOnRefreshDelegate(AtkUnitManager* unitManager, AtkUnitBase* addon, uint valueCount, AtkValue* values);
private delegate byte AddonOnRefreshDelegate(AtkUnitManager* unitManager, AtkUnitBase* addon, uint valueCount, AtkValue* values);
/// <inheritdoc/>
public void Dispose()
@ -221,7 +221,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
}
}
private void OnAddonRefresh(AtkUnitManager* atkUnitManager, AtkUnitBase* addon, uint valueCount, AtkValue* values)
private byte OnAddonRefresh(AtkUnitManager* atkUnitManager, AtkUnitBase* addon, uint valueCount, AtkValue* values)
{
try
{
@ -232,7 +232,7 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
Log.Error(e, "Exception in OnAddonRefresh pre-refresh invoke.");
}
this.onAddonRefreshHook.Original(atkUnitManager, addon, valueCount, values);
var result = this.onAddonRefreshHook.Original(atkUnitManager, addon, valueCount, values);
try
{
@ -242,6 +242,8 @@ internal unsafe class AddonLifecycle : IDisposable, IServiceType
{
Log.Error(e, "Exception in OnAddonRefresh post-refresh invoke.");
}
return result;
}
private void OnRequestedUpdate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData)

View file

@ -172,6 +172,42 @@ internal class GameFontManager : IServiceType
fontPtr.BuildLookupTable();
}
/// <summary>
/// Create a glyph range for use with ImGui AddFont.
/// </summary>
/// <param name="family">Font family and size.</param>
/// <param name="mergeDistance">Merge two ranges into one if distance is below the value specified in this parameter.</param>
/// <returns>Glyph ranges.</returns>
public GCHandle ToGlyphRanges(GameFontFamilyAndSize family, int mergeDistance = 8)
{
var fdt = this.fdts[(int)family]!;
var ranges = new List<ushort>(fdt.Glyphs.Count)
{
checked((ushort)fdt.Glyphs[0].CharInt),
checked((ushort)fdt.Glyphs[0].CharInt),
};
foreach (var glyph in fdt.Glyphs.Skip(1))
{
var c32 = glyph.CharInt;
if (c32 >= 0x10000)
break;
var c16 = unchecked((ushort)c32);
if (ranges[^1] + mergeDistance >= c16 && c16 > ranges[^1])
{
ranges[^1] = c16;
}
else if (ranges[^1] + 1 < c16)
{
ranges.Add(c16);
ranges.Add(c16);
}
}
return GCHandle.Alloc(ranges.ToArray(), GCHandleType.Pinned);
}
/// <summary>
/// Creates a new GameFontHandle, and increases internal font reference counter, and if it's first time use, then the font will be loaded on next font building process.
/// </summary>

View file

@ -791,10 +791,10 @@ internal class InterfaceManager : IDisposable, IServiceType
}
else
{
var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned);
garbageList.Add(japaneseRangeHandle);
var rangeHandle = gameFontManager.ToGlyphRanges(GameFontFamilyAndSize.Axis12);
garbageList.Add(rangeHandle);
fontConfig.GlyphRanges = japaneseRangeHandle.AddrOfPinnedObject();
fontConfig.GlyphRanges = rangeHandle.AddrOfPinnedObject();
fontConfig.PixelSnapH = true;
DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontConfig.SizePixels, fontConfig);
this.loadedFontInfo[DefaultFont] = fontInfo;
@ -851,22 +851,19 @@ internal class InterfaceManager : IDisposable, IServiceType
foreach (var (fontSize, requests) in extraFontRequests)
{
List<Tuple<ushort, ushort>> codepointRanges = new();
codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint));
codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint));
// ImGui default ellipsis characters
codepointRanges.Add(Tuple.Create<ushort, ushort>(0x2026, 0x2026));
codepointRanges.Add(Tuple.Create<ushort, ushort>(0x0085, 0x0085));
List<(ushort, ushort)> codepointRanges = new(4 + requests.Sum(x => x.CodepointRanges.Count))
{
new(Fallback1Codepoint, Fallback1Codepoint),
new(Fallback2Codepoint, Fallback2Codepoint),
// ImGui default ellipsis characters
new(0x2026, 0x2026),
new(0x0085, 0x0085),
};
foreach (var request in requests)
{
foreach (var range in request.CodepointRanges)
codepointRanges.Add(range);
}
codepointRanges.Sort((x, y) => (x.Item1 == y.Item1 ? (x.Item2 < y.Item2 ? -1 : (x.Item2 == y.Item2 ? 0 : 1)) : (x.Item1 < y.Item1 ? -1 : 1)));
codepointRanges.AddRange(request.CodepointRanges.Select(x => (From: x.Item1, To: x.Item2)));
codepointRanges.Sort();
List<ushort> flattenedRanges = new();
foreach (var range in codepointRanges)
{

View file

@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@ -40,6 +41,22 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable
configuration.DevPluginSettings[dllFile.FullName] = this.devSettings = new DevPluginSettings();
configuration.QueueSave();
}
// Legacy dev plugins might not have this!
if (this.devSettings.WorkingPluginId == Guid.Empty)
{
this.devSettings.WorkingPluginId = Guid.NewGuid();
Log.Verbose("{InternalName} was assigned new devPlugin GUID {Guid}", this.InternalName, this.devSettings.WorkingPluginId);
configuration.QueueSave();
}
// If the ID in the manifest is wrong, force the good one
if (this.DevImposedWorkingPluginId != this.manifest.WorkingPluginId)
{
Debug.Assert(this.DevImposedWorkingPluginId != Guid.Empty, "Empty guid for devPlugin");
this.manifest.WorkingPluginId = this.DevImposedWorkingPluginId;
this.SaveManifest("dev imposed working plugin id");
}
if (this.AutomaticReload)
{
@ -76,6 +93,11 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable
}
}
}
/// <summary>
/// Gets an ID uniquely identifying this specific instance of a devPlugin.
/// </summary>
public Guid DevImposedWorkingPluginId => this.devSettings.WorkingPluginId;
/// <inheritdoc/>
public new void Dispose()

View file

@ -26,6 +26,13 @@ namespace Dalamud.Plugin.Internal.Types;
/// </summary>
internal class LocalPlugin : IDisposable
{
/// <summary>
/// The underlying manifest for this plugin.
/// </summary>
#pragma warning disable SA1401
protected LocalPluginManifest manifest;
#pragma warning restore SA1401
private static readonly ModuleLog Log = new("LOCALPLUGIN");
private readonly FileInfo manifestFile;
@ -39,8 +46,6 @@ internal class LocalPlugin : IDisposable
private Type? pluginType;
private IDalamudPlugin? instance;
private LocalPluginManifest manifest;
/// <summary>
/// Initializes a new instance of the <see cref="LocalPlugin"/> class.
/// </summary>
@ -659,9 +664,11 @@ internal class LocalPlugin : IDisposable
var manifestPath = LocalPluginManifest.GetManifestFile(this.DllFile);
if (manifestPath.Exists)
{
// var isDisabled = this.IsDisabled; // saving the internal state because it could have been deleted
// Save some state that we do actually want to carry over
var guid = this.manifest.WorkingPluginId;
this.manifest = LocalPluginManifest.Load(manifestPath) ?? throw new Exception("Could not reload manifest.");
// this.manifest.Disabled = isDisabled;
this.manifest.WorkingPluginId = guid;
this.SaveManifest("dev reload");
}
@ -686,6 +693,12 @@ internal class LocalPlugin : IDisposable
});
}
/// <summary>
/// Save this plugin manifest.
/// </summary>
/// <param name="reason">Why it should be saved.</param>
protected void SaveManifest(string reason) => this.manifest.Save(this.manifestFile, reason);
private static void SetupLoaderConfig(LoaderConfig config)
{
config.IsUnloadable = true;
@ -694,6 +707,4 @@ internal class LocalPlugin : IDisposable
config.SharedAssemblies.Add(typeof(Lumina.GameData).Assembly.GetName());
config.SharedAssemblies.Add(typeof(Lumina.Excel.ExcelSheetImpl).Assembly.GetName());
}
private void SaveManifest(string reason) => this.manifest.Save(this.manifestFile, reason);
}