merge master into profiles

This commit is contained in:
goat 2023-05-28 16:06:05 +02:00
commit fe6196d0ad
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
57 changed files with 1118 additions and 287 deletions

View file

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace Dalamud.Interface.ImGuiFileDialog;
/// <summary>
/// A drive list loader. Thread-safety guaranteed.
/// </summary>
internal class DriveListLoader
{
/// <summary>
/// Initializes a new instance of the <see cref="DriveListLoader"/> class.
/// </summary>
public DriveListLoader()
{
this.Drives = Array.Empty<DriveInfo>();
}
/// <summary>
/// Gets the drive list. This may be incomplete if the loader is still loading.
/// </summary>
public IReadOnlyList<DriveInfo> Drives { get; private set; }
/// <summary>
/// Gets a value indicating whether or not the loader is loading.
/// </summary>
public bool Loading { get; private set; }
/// <summary>
/// Loads the drive list, asynchronously.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task LoadDrivesAsync()
{
this.Loading = true;
try
{
await this.InitDrives();
}
finally
{
this.Loading = false;
}
}
private async Task InitDrives()
{
// Force async to avoid this being invoked synchronously unless it's awaited.
await Task.Yield();
this.Drives = DriveInfo.GetDrives();
}
}

View file

@ -12,11 +12,13 @@ public partial class FileDialog
{
private readonly object filesLock = new();
private readonly DriveListLoader driveListLoader = new();
private List<FileStruct> files = new();
private List<FileStruct> filteredFiles = new();
private SortingField currentSortingField = SortingField.FileName;
private bool[] sortDescending = new[] { false, false, false, false };
private bool[] sortDescending = { false, false, false, false };
private enum FileStructType
{
@ -296,12 +298,14 @@ public partial class FileDialog
}
}
private IEnumerable<SideBarItem> GetDrives()
{
return this.driveListLoader.Drives.Select(drive => new SideBarItem(drive.Name, drive.Name, FontAwesomeIcon.Server));
}
private void SetupSideBar()
{
foreach (var drive in DriveInfo.GetDrives())
{
this.drives.Add(new SideBarItem(drive.Name, drive.Name, FontAwesomeIcon.Server));
}
_ = this.driveListLoader.LoadDrivesAsync();
var personal = Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Personal));

View file

@ -31,7 +31,6 @@ public partial class FileDialog
this.Text = text;
this.Location = location;
this.Icon = icon;
this.Exists = !this.Location.IsNullOrEmpty() && Directory.Exists(this.Location);
}
public string Text { get; init; }
@ -40,8 +39,6 @@ public partial class FileDialog
public FontAwesomeIcon Icon { get; init; }
public bool Exists { get; init; }
public bool CheckExistence()
=> !this.Location.IsNullOrEmpty() && Directory.Exists(this.Location);
}

View file

@ -3,6 +3,7 @@ using System.IO;
using System.Linq;
using System.Numerics;
using Dalamud.Utility;
using ImGuiNET;
namespace Dalamud.Interface.ImGuiFileDialog;
@ -316,7 +317,7 @@ public partial class FileDialog
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + Scaled(5));
var idx = 0;
foreach (var qa in this.drives.Concat(this.quickAccess).Where(qa => qa.Exists))
foreach (var qa in this.GetDrives().Concat(this.quickAccess).Where(qa => !qa.Location.IsNullOrEmpty()))
{
ImGui.PushID(idx++);
ImGui.SetCursorPosX(Scaled(25));

View file

@ -52,7 +52,6 @@ public partial class FileDialog
private float footerHeight = 0;
private string selectedSideBar = string.Empty;
private List<SideBarItem> drives = new();
private List<SideBarItem> quickAccess = new();
/// <summary>
@ -259,6 +258,7 @@ public partial class FileDialog
private void SetPath(string path)
{
this.searchBuffer = string.Empty;
this.selectedSideBar = string.Empty;
this.currentPath = path;
this.files.Clear();

View file

@ -517,7 +517,7 @@ internal class DalamudInterface : IDisposable, IServiceType
}
catch (Exception ex)
{
PluginLog.Error(ex, "Error during OnDraw");
Log.Error(ex, "Error during OnDraw");
}
}
@ -877,7 +877,7 @@ internal class DalamudInterface : IDisposable, IServiceType
foreach (var plugin in pluginManager.InstalledPlugins)
{
// TODO: some more here, state maybe?
PluginLog.Information($"{plugin.Name}");
Log.Information($"{plugin.Name}");
}
}

View file

@ -20,12 +20,12 @@ using Dalamud.Interface.Internal.ManagedAsserts;
using Dalamud.Interface.Internal.Notifications;
using Dalamud.Interface.Style;
using Dalamud.Interface.Windowing;
using Dalamud.Logging.Internal;
using Dalamud.Utility;
using Dalamud.Utility.Timing;
using ImGuiNET;
using ImGuiScene;
using PInvoke;
using Serilog;
// general dev notes, here because it's easiest
@ -47,6 +47,8 @@ namespace Dalamud.Interface.Internal;
[ServiceManager.BlockingEarlyLoadedService]
internal class InterfaceManager : IDisposable, IServiceType
{
private static ModuleLog Log = new ModuleLog("IM");
private const float DefaultFontSizePt = 12.0f;
private const float DefaultFontSizePx = DefaultFontSizePt * 4.0f / 3.0f;
private const ushort Fallback1Codepoint = 0x3013; // Geta mark; FFXIV uses this to indicate that a glyph is missing.
@ -76,16 +78,41 @@ internal class InterfaceManager : IDisposable, IServiceType
private bool isOverrideGameCursor = true;
[ServiceManager.ServiceConstructor]
private InterfaceManager()
private InterfaceManager(SigScanner sigScanner)
{
Log.Information("ctor called");
this.dispatchMessageWHook = Hook<DispatchMessageWDelegate>.FromImport(
null, "user32.dll", "DispatchMessageW", 0, this.DispatchMessageWDetour);
this.setCursorHook = Hook<SetCursorDelegate>.FromImport(
null, "user32.dll", "SetCursor", 0, this.SetCursorDetour);
Log.Information("Import hooks applied");
this.fontBuildSignal = new ManualResetEvent(false);
this.address = new SwapChainVtableResolver();
this.address.Setup();
Log.Information("Resolver setup complete");
Log.Information("===== S W A P C H A I N =====");
Log.Information($"Is ReShade: {this.address.IsReshade}");
Log.Information($"Present address 0x{this.address.Present.ToInt64():X}");
Log.Information($"ResizeBuffers address 0x{this.address.ResizeBuffers.ToInt64():X}");
this.presentHook = Hook<PresentDelegate>.FromAddress(this.address.Present, this.PresentDetour);
this.resizeBuffersHook = Hook<ResizeBuffersDelegate>.FromAddress(this.address.ResizeBuffers, this.ResizeBuffersDetour);
Log.Information("Present and ResizeBuffers hooked");
var wndProcAddress = sigScanner.ScanText("E8 ?? ?? ?? ?? 80 7C 24 ?? ?? 74 ?? B8");
Log.Information($"WndProc address 0x{wndProcAddress.ToInt64():X}");
this.processMessageHook = Hook<ProcessMessageDelegate>.FromAddress(wndProcAddress, this.ProcessMessageDetour);
this.setCursorHook.Enable();
this.presentHook.Enable();
this.resizeBuffersHook.Enable();
this.dispatchMessageWHook.Enable();
this.processMessageHook.Enable();
Log.Information("Hooks enabled");
}
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
@ -982,10 +1009,9 @@ internal class InterfaceManager : IDisposable, IServiceType
}
[ServiceManager.CallWhenServicesReady]
private void ContinueConstruction(SigScanner sigScanner, Framework framework)
private void ContinueConstruction()
{
this.address.Setup(sigScanner);
framework.RunOnFrameworkThread(() =>
this.framework.RunOnFrameworkThread(() =>
{
while ((this.GameWindowHandle = NativeFunctions.FindWindowEx(IntPtr.Zero, this.GameWindowHandle, "FFXIVGAME", IntPtr.Zero)) != IntPtr.Zero)
{
@ -1004,23 +1030,6 @@ internal class InterfaceManager : IDisposable, IServiceType
{
Log.Error(ex, "Could not enable immersive mode");
}
this.presentHook = Hook<PresentDelegate>.FromAddress(this.address.Present, this.PresentDetour);
this.resizeBuffersHook = Hook<ResizeBuffersDelegate>.FromAddress(this.address.ResizeBuffers, this.ResizeBuffersDetour);
Log.Verbose("===== S W A P C H A I N =====");
Log.Verbose($"Present address 0x{this.presentHook!.Address.ToInt64():X}");
Log.Verbose($"ResizeBuffers address 0x{this.resizeBuffersHook!.Address.ToInt64():X}");
var wndProcAddress = sigScanner.ScanText("E8 ?? ?? ?? ?? 80 7C 24 ?? ?? 74 ?? B8");
Log.Verbose($"WndProc address 0x{wndProcAddress.ToInt64():X}");
this.processMessageHook = Hook<ProcessMessageDelegate>.FromAddress(wndProcAddress, this.ProcessMessageDetour);
this.setCursorHook.Enable();
this.presentHook.Enable();
this.resizeBuffersHook.Enable();
this.dispatchMessageWHook.Enable();
this.processMessageHook.Enable();
});
}

View file

@ -19,7 +19,6 @@ internal unsafe class UiDebug
{
private const int UnitListCount = 18;
private readonly GetAtkStageSingleton getAtkStageSingleton;
private readonly bool[] selectedInList = new bool[UnitListCount];
private readonly string[] listNames = new string[UnitListCount]
{
@ -52,9 +51,6 @@ internal unsafe class UiDebug
/// </summary>
public UiDebug()
{
var sigScanner = Service<SigScanner>.Get();
var getSingletonAddr = sigScanner.ScanText("E8 ?? ?? ?? ?? 41 B8 01 00 00 00 48 8D 15 ?? ?? ?? ?? 48 8B 48 20 E8 ?? ?? ?? ?? 48 8B CF");
this.getAtkStageSingleton = Marshal.GetDelegateForFunctionPointer<GetAtkStageSingleton>(getSingletonAddr);
}
private delegate AtkStage* GetAtkStageSingleton();
@ -445,7 +441,7 @@ internal unsafe class UiDebug
{
var foundSelected = false;
var noResults = true;
var stage = this.getAtkStageSingleton();
var stage = AtkStage.GetSingleton();
var unitManagers = &stage->RaptureAtkUnitManager->AtkUnitManager.DepthLayerOneList;

View file

@ -3,13 +3,13 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
using Dalamud.Configuration.Internal;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Windowing;
using Dalamud.Networking.Http;
using ImGuiNET;
using Newtonsoft.Json;
@ -40,7 +40,7 @@ public class BranchSwitcherWindow : Window
{
Task.Run(async () =>
{
using var client = new HttpClient();
var client = Service<HappyHttpClient>.Get().SharedHttpClient;
this.branches = await client.GetFromJsonAsync<Dictionary<string, VersionEntry>>(BranchInfoUrl);
Debug.Assert(this.branches != null, "this.branches != null");

View file

@ -8,6 +8,7 @@ using System.Threading;
using System.Threading.Tasks;
using Dalamud.Game;
using Dalamud.Networking.Http;
using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Utility;
@ -48,6 +49,9 @@ internal class PluginImageCache : IDisposable, IServiceType
[ServiceManager.ServiceDependency]
private readonly InterfaceManager.InterfaceManagerWithScene imWithScene = Service<InterfaceManager.InterfaceManagerWithScene>.Get();
[ServiceManager.ServiceDependency]
private readonly HappyHttpClient happyHttpClient = Service<HappyHttpClient>.Get();
private readonly BlockingCollection<Tuple<ulong, Func<Task>>> downloadQueue = new();
private readonly BlockingCollection<Func<Task>> loadQueue = new();
private readonly CancellationTokenSource cancelToken = new();
@ -535,7 +539,7 @@ internal class PluginImageCache : IDisposable, IServiceType
var bytes = await this.RunInDownloadQueue<byte[]?>(
async () =>
{
var data = await Util.HttpClient.GetAsync(url);
var data = await this.happyHttpClient.SharedHttpClient.GetAsync(url);
if (data.StatusCode == HttpStatusCode.NotFound)
return null;
@ -627,7 +631,9 @@ internal class PluginImageCache : IDisposable, IServiceType
var bytes = await this.RunInDownloadQueue<byte[]?>(
async () =>
{
var data = await Util.HttpClient.GetAsync(url);
var httpClient = Service<HappyHttpClient>.Get().SharedHttpClient;
var data = await httpClient.GetAsync(url);
if (data.StatusCode == HttpStatusCode.NotFound)
return null;

View file

@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Networking.Http;
using Dalamud.Plugin.Internal;
using Dalamud.Utility;
using Serilog;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller;
@ -42,7 +39,7 @@ internal class DalamudChangelogManager
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task ReloadChangelogAsync()
{
using var client = new HttpClient();
var client = Service<HappyHttpClient>.Get().SharedHttpClient;
this.Changelogs = null;
var dalamudChangelogs = await client.GetFromJsonAsync<List<DalamudChangelog>>(DalamudChangelogUrl);

View file

@ -2294,7 +2294,8 @@ internal class PluginInstallerWindow : Window, IDisposable
disabled = disabled || (plugin.IsOrphaned && !plugin.IsLoaded);
// Disable everything if the plugin failed to load
disabled = disabled || plugin.State == PluginState.LoadError || plugin.State == PluginState.DependencyResolutionFailed;
// Now handled by the first case below
// disabled = disabled || plugin.State == PluginState.LoadError || plugin.State == PluginState.DependencyResolutionFailed;
// Disable everything if we're loading plugins
disabled = disabled || plugin.State == PluginState.Loading || plugin.State == PluginState.Unloading;
@ -2360,7 +2361,7 @@ internal class PluginInstallerWindow : Window, IDisposable
ImGui.EndPopup();
}
if (plugin.State == PluginState.UnloadError && !plugin.IsDev)
if (plugin.State is PluginState.UnloadError or PluginState.LoadError or PluginState.DependencyResolutionFailed && !plugin.IsDev)
{
ImGuiComponents.DisabledButton(FontAwesomeIcon.Frown);
@ -3182,7 +3183,7 @@ internal class PluginInstallerWindow : Window, IDisposable
public static string PluginButtonToolTip_UpdateSingle(string version) => Loc.Localize("InstallerUpdateSingle", "Update to {0}").Format(version);
public static string PluginButtonToolTip_UnloadFailed => Loc.Localize("InstallerUnloadFailedTooltip", "Plugin unload failed, please restart your game and try again.");
public static string PluginButtonToolTip_UnloadFailed => Loc.Localize("InstallerLoadUnloadFailedTooltip", "Plugin load/unload failed, please restart your game and try again.");
public static string PluginButtonToolTip_NeedsToBeInDefault => Loc.Localize("InstallerUnloadNeedsToBeInDefault", "This plugin is in one or more collections. If you want to enable or disable it, please do so by enabling or disabling the collections it is in.\nIf you want to manage it manually, remove it from all collections.");

View file

@ -50,6 +50,12 @@ public class SettingsTabGeneral : SettingsTab
c => c.DutyFinderChatMessage,
(v, c) => c.DutyFinderChatMessage = v),
new SettingsEntry<bool>(
Loc.Localize("DalamudSettingsPrintDalamudWelcomeMsg", "Display Dalamud's welcome message"),
Loc.Localize("DalamudSettingsPrintDalamudWelcomeMsgHint", "Display Dalamud's welcome message in FFXIV chat when logging in with a character."),
c => c.PrintDalamudWelcomeMsg,
(v, c) => c.PrintDalamudWelcomeMsg = v),
new SettingsEntry<bool>(
Loc.Localize("DalamudSettingsPrintPluginsWelcomeMsg", "Display loaded plugins in the welcome message"),
Loc.Localize("DalamudSettingsPrintPluginsWelcomeMsgHint", "Display loaded plugins in FFXIV chat when logging in with a character."),

View file

@ -156,6 +156,14 @@ public class SettingsTabLook : SettingsTab
interfaceManager.RebuildFonts();
}
ImGui.SameLine();
if (ImGui.Button("24pt##DalamudSettingsGlobalUiScaleReset24"))
{
this.globalUiScale = 24.0f / 12.0f;
ImGui.GetIO().FontGlobalScale = this.globalUiScale;
interfaceManager.RebuildFonts();
}
ImGui.SameLine();
if (ImGui.Button("36pt##DalamudSettingsGlobalUiScaleReset36"))
{

View file

@ -67,7 +67,7 @@ public class DevPluginsSettingsEntry : SettingsEntry
}
}
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsDevPluginLocationsHint", "Add additional dev plugin load locations.\nThese can be either the directory or DLL path."));
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsDevPluginLocationsHint", "Add dev plugin load locations.\nThese can be either the directory or DLL path."));
ImGuiHelpers.ScaledDummy(5);