Avoid re-creating title version string every frame (#2117)

* Avoid re-creating title version string every frame

* Marked title version string that it has been changed by Dalamud by
  appending a newline payload with a string expression embedded within,
  which the game will ignore (effectively `<br(!Dalamud!)>`.)
* Added `PluginManager.LoadedPluginCount` which will count the number of
  loaded plugin without making a copy of the plugin list.
* Made TitleScreenMenuWindow.OnVersionStringDraw` update the title
  version text addon only if number of loaded plugin changes or the text
  is missing the custom suffix from the first point.

* Use OriginalTextPointer to determine if SetText(ROS) has been called
This commit is contained in:
srkizer 2024-11-26 10:09:43 +09:00 committed by GitHub
parent 4c9b2a1577
commit db4b6cea2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 48 additions and 16 deletions

View file

@ -10,7 +10,6 @@ using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using Dalamud.Game.ClientState;
using Dalamud.Game.Gui;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Interface.Animation.EasingFunctions;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.ManagedFontAtlas.Internals;
@ -19,16 +18,18 @@ using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Plugin.Services;
using Dalamud.Storage.Assets;
using Dalamud.Support;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Component.GUI;
using ImGuiNET;
using Lumina.Text.ReadOnly;
using LSeStringBuilder = Lumina.Text.SeStringBuilder;
namespace Dalamud.Interface.Internal.Windows;
/// <summary>
@ -59,6 +60,8 @@ internal class TitleScreenMenuWindow : Window, IDisposable
private InOutCubic? fadeOutEasing;
private State state = State.Hide;
private int lastLoadedPluginCount = -1;
/// <summary>
/// Initializes a new instance of the <see cref="TitleScreenMenuWindow"/> class.
@ -441,29 +444,37 @@ internal class TitleScreenMenuWindow : Window, IDisposable
textNode->TextFlags |= (byte)TextFlags.MultiLine;
textNode->AlignmentType = AlignmentType.TopLeft;
var containsDalamudVersionString = textNode->OriginalTextPointer == textNode->NodeText.StringPtr;
if (!this.configuration.ShowTsm || !this.showTsm.Value)
{
textNode->NodeText.SetString(addon->AtkValues[1].String);
if (containsDalamudVersionString)
textNode->SetText(addon->AtkValues[1].String);
this.lastLoadedPluginCount = -1;
return;
}
var pm = Service<PluginManager>.GetNullable();
var count = pm?.LoadedPluginCount ?? 0;
var pluginCount = pm?.InstalledPlugins.Count(c => c.State == PluginState.Loaded) ?? 0;
// Avoid rebuilding the string every frame.
if (containsDalamudVersionString && count == this.lastLoadedPluginCount)
return;
this.lastLoadedPluginCount = count;
var titleVersionText = new SeStringBuilder()
.AddText(addon->AtkValues[1].GetValueAsString())
.AddText("\n\n")
.AddUiGlow(701)
.AddUiForeground(SeIconChar.BoxedLetterD.ToIconString(), 539)
.AddUiGlowOff()
.AddText($" Dalamud: {Util.GetScmVersion()}")
.AddText($" - {pluginCount} {(pluginCount != 1 ? "plugins" : "plugin")} loaded");
var lssb = LSeStringBuilder.SharedPool.Get();
lssb.Append(new ReadOnlySeStringSpan(addon->AtkValues[1].String)).Append("\n\n");
lssb.PushEdgeColorType(701).PushColorType(539)
.Append(SeIconChar.BoxedLetterD.ToIconChar())
.PopColorType().PopEdgeColorType();
lssb.Append($" Dalamud: {Util.GetScmVersion()}");
if (pm?.SafeMode ?? false)
titleVersionText.AddUiForeground(" [SAFE MODE]", 17);
lssb.Append($" - {count} {(count != 1 ? "plugins" : "plugin")} loaded");
textNode->NodeText.SetString(titleVersionText.Build().EncodeWithNullTerminator());
if (pm?.SafeMode is true)
lssb.PushColorType(17).Append(" [SAFE MODE]").PopColorType();
textNode->SetText(lssb.GetViewAsSpan());
LSeStringBuilder.SharedPool.Return(lssb);
}
private void TitleScreenMenuEntryListChange() => this.privateAtlas.BuildFontsAsync();

View file

@ -162,6 +162,27 @@ internal class PluginManager : IInternalDisposableService
/// </summary>
public static int DalamudApiLevel { get; private set; }
/// <summary>
/// Gets the number of loaded plugins.
/// </summary>
public int LoadedPluginCount
{
get
{
var res = 0;
lock (this.pluginListLock)
{
foreach (var p in this.installedPluginsList)
{
if (p.State == PluginState.Loaded)
res++;
}
}
return res;
}
}
/// <summary>
/// Gets a copy of the list of all loaded plugins.
/// </summary>