Some more reworking.

This commit is contained in:
Ottermandias 2023-04-22 13:30:14 +02:00
parent e66d666d4d
commit a94c5ae7af
12 changed files with 245 additions and 137 deletions

View file

@ -23,6 +23,8 @@ using Penumbra.String;
using Penumbra.String.Classes; using Penumbra.String.Classes;
using Penumbra.Services; using Penumbra.Services;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Interop.Services;
using Penumbra.UI;
namespace Penumbra.Api; namespace Penumbra.Api;
@ -31,20 +33,29 @@ public class PenumbraApi : IDisposable, IPenumbraApi
public (int, int) ApiVersion public (int, int) ApiVersion
=> (4, 19); => (4, 19);
public event Action<string>? PreSettingsPanelDraw; public event Action<string>? PreSettingsPanelDraw
public event Action<string>? PostSettingsPanelDraw; {
add => _communicator.PreSettingsPanelDraw.Subscribe(value!);
remove => _communicator.PreSettingsPanelDraw.Unsubscribe(value!);
}
public event Action<string>? PostSettingsPanelDraw
{
add => _communicator.PostSettingsPanelDraw.Subscribe(value!);
remove => _communicator.PostSettingsPanelDraw.Unsubscribe(value!);
}
public event GameObjectRedrawnDelegate? GameObjectRedrawn public event GameObjectRedrawnDelegate? GameObjectRedrawn
{ {
add add
{ {
CheckInitialized(); CheckInitialized();
_penumbra!.RedrawService.GameObjectRedrawn += value; _redrawService.GameObjectRedrawn += value;
} }
remove remove
{ {
CheckInitialized(); CheckInitialized();
_penumbra!.RedrawService.GameObjectRedrawn -= value; _redrawService.GameObjectRedrawn -= value;
} }
} }
@ -91,10 +102,9 @@ public class PenumbraApi : IDisposable, IPenumbraApi
} }
public bool Valid public bool Valid
=> _penumbra != null; => _lumina != null;
private CommunicatorService _communicator; private CommunicatorService _communicator;
private Penumbra _penumbra;
private Lumina.GameData? _lumina; private Lumina.GameData? _lumina;
private ModManager _modManager; private ModManager _modManager;
@ -109,32 +119,39 @@ public class PenumbraApi : IDisposable, IPenumbraApi
private CutsceneService _cutsceneService; private CutsceneService _cutsceneService;
private ModImportManager _modImportManager; private ModImportManager _modImportManager;
private CollectionEditor _collectionEditor; private CollectionEditor _collectionEditor;
private RedrawService _redrawService;
private ModFileSystem _modFileSystem;
private ConfigWindow _configWindow;
public unsafe PenumbraApi(CommunicatorService communicator, Penumbra penumbra, ModManager modManager, ResourceLoader resourceLoader, public unsafe PenumbraApi(CommunicatorService communicator, ModManager modManager, ResourceLoader resourceLoader,
Configuration config, CollectionManager collectionManager, DalamudServices dalamud, TempCollectionManager tempCollections, Configuration config, CollectionManager collectionManager, DalamudServices dalamud, TempCollectionManager tempCollections,
TempModManager tempMods, ActorService actors, CollectionResolver collectionResolver, CutsceneService cutsceneService, ModImportManager modImportManager, CollectionEditor collectionEditor) TempModManager tempMods, ActorService actors, CollectionResolver collectionResolver, CutsceneService cutsceneService,
ModImportManager modImportManager, CollectionEditor collectionEditor, RedrawService redrawService, ModFileSystem modFileSystem,
ConfigWindow configWindow)
{ {
_communicator = communicator; _communicator = communicator;
_penumbra = penumbra; _modManager = modManager;
_modManager = modManager; _resourceLoader = resourceLoader;
_resourceLoader = resourceLoader; _config = config;
_config = config; _collectionManager = collectionManager;
_collectionManager = collectionManager; _dalamud = dalamud;
_dalamud = dalamud; _tempCollections = tempCollections;
_tempCollections = tempCollections; _tempMods = tempMods;
_tempMods = tempMods; _actors = actors;
_actors = actors; _collectionResolver = collectionResolver;
_collectionResolver = collectionResolver; _cutsceneService = cutsceneService;
_cutsceneService = cutsceneService; _modImportManager = modImportManager;
_modImportManager = modImportManager; _collectionEditor = collectionEditor;
_collectionEditor = collectionEditor; _redrawService = redrawService;
_modFileSystem = modFileSystem;
_configWindow = configWindow;
_lumina = (Lumina.GameData?)_dalamud.GameData.GetType() _lumina = (Lumina.GameData?)_dalamud.GameData.GetType()
.GetField("gameData", BindingFlags.Instance | BindingFlags.NonPublic) .GetField("gameData", BindingFlags.Instance | BindingFlags.NonPublic)
?.GetValue(_dalamud.GameData); ?.GetValue(_dalamud.GameData);
_resourceLoader.ResourceLoaded += OnResourceLoaded; _resourceLoader.ResourceLoaded += OnResourceLoaded;
_communicator.ModPathChanged.Subscribe(ModPathChangeSubscriber); _communicator.ModPathChanged.Subscribe(ModPathChangeSubscriber);
_communicator.ModSettingChanged.Subscribe(OnModSettingChange, -1000); _communicator.ModSettingChanged.Subscribe(OnModSettingChange, -1000);
} }
@ -144,11 +161,10 @@ public class PenumbraApi : IDisposable, IPenumbraApi
return; return;
_resourceLoader.ResourceLoaded -= OnResourceLoaded; _resourceLoader.ResourceLoaded -= OnResourceLoaded;
_communicator.ModPathChanged.Unsubscribe(ModPathChangeSubscriber); _communicator.ModPathChanged.Unsubscribe(ModPathChangeSubscriber);
_communicator.ModSettingChanged.Unsubscribe(OnModSettingChange); _communicator.ModSettingChanged.Unsubscribe(OnModSettingChange);
_lumina = null; _lumina = null;
_communicator = null!; _communicator = null!;
_penumbra = null!;
_modManager = null!; _modManager = null!;
_resourceLoader = null!; _resourceLoader = null!;
_config = null!; _config = null!;
@ -161,9 +177,16 @@ public class PenumbraApi : IDisposable, IPenumbraApi
_cutsceneService = null!; _cutsceneService = null!;
_modImportManager = null!; _modImportManager = null!;
_collectionEditor = null!; _collectionEditor = null!;
_redrawService = null!;
_modFileSystem = null!;
_configWindow = null!;
} }
public event ChangedItemClick? ChangedItemClicked; public event ChangedItemClick? ChangedItemClicked
{
add => _communicator.ChangedItemClick.Subscribe(new Action<MouseButton, object?>(value!));
remove => _communicator.ChangedItemClick.Unsubscribe(new Action<MouseButton, object?>(value!));
}
public string GetModDirectory() public string GetModDirectory()
{ {
@ -201,12 +224,12 @@ public class PenumbraApi : IDisposable, IPenumbraApi
add add
{ {
CheckInitialized(); CheckInitialized();
_penumbra!.EnabledChange += value; _communicator.EnabledChanged.Subscribe(value!, int.MinValue);
} }
remove remove
{ {
CheckInitialized(); CheckInitialized();
_penumbra!.EnabledChange -= value; _communicator.EnabledChanged.Unsubscribe(value!);
} }
} }
@ -216,27 +239,32 @@ public class PenumbraApi : IDisposable, IPenumbraApi
return JsonConvert.SerializeObject(_config, Formatting.Indented); return JsonConvert.SerializeObject(_config, Formatting.Indented);
} }
public event ChangedItemHover? ChangedItemTooltip; public event ChangedItemHover? ChangedItemTooltip
{
add => _communicator.ChangedItemHover.Subscribe(new Action<object?>(value!));
remove => _communicator.ChangedItemHover.Unsubscribe(new Action<object?>(value!));
}
public event GameObjectResourceResolvedDelegate? GameObjectResourceResolved; public event GameObjectResourceResolvedDelegate? GameObjectResourceResolved;
public PenumbraApiEc OpenMainWindow(TabType tab, string modDirectory, string modName) public PenumbraApiEc OpenMainWindow(TabType tab, string modDirectory, string modName)
{ {
CheckInitialized(); CheckInitialized();
if (_penumbra!.ConfigWindow == null) if (_configWindow == null)
return PenumbraApiEc.SystemDisposed; return PenumbraApiEc.SystemDisposed;
_penumbra!.ConfigWindow.IsOpen = true; _configWindow.IsOpen = true;
if (!Enum.IsDefined(tab)) if (!Enum.IsDefined(tab))
return PenumbraApiEc.InvalidArgument; return PenumbraApiEc.InvalidArgument;
if (tab != TabType.None) if (tab != TabType.None)
_penumbra!.ConfigWindow.SelectTab(tab); _configWindow.SelectTab(tab);
if (tab == TabType.Mods && (modDirectory.Length > 0 || modName.Length > 0)) if (tab == TabType.Mods && (modDirectory.Length > 0 || modName.Length > 0))
{ {
if (_modManager.TryGetMod(modDirectory, modName, out var mod)) if (_modManager.TryGetMod(modDirectory, modName, out var mod))
_penumbra!.ConfigWindow.SelectMod(mod); _configWindow.SelectMod(mod);
else else
return PenumbraApiEc.ModMissing; return PenumbraApiEc.ModMissing;
} }
@ -247,34 +275,34 @@ public class PenumbraApi : IDisposable, IPenumbraApi
public void CloseMainWindow() public void CloseMainWindow()
{ {
CheckInitialized(); CheckInitialized();
if (_penumbra!.ConfigWindow == null) if (_configWindow == null)
return; return;
_penumbra!.ConfigWindow.IsOpen = false; _configWindow.IsOpen = false;
} }
public void RedrawObject(int tableIndex, RedrawType setting) public void RedrawObject(int tableIndex, RedrawType setting)
{ {
CheckInitialized(); CheckInitialized();
_penumbra!.RedrawService.RedrawObject(tableIndex, setting); _redrawService.RedrawObject(tableIndex, setting);
} }
public void RedrawObject(string name, RedrawType setting) public void RedrawObject(string name, RedrawType setting)
{ {
CheckInitialized(); CheckInitialized();
_penumbra!.RedrawService.RedrawObject(name, setting); _redrawService.RedrawObject(name, setting);
} }
public void RedrawObject(GameObject? gameObject, RedrawType setting) public void RedrawObject(GameObject? gameObject, RedrawType setting)
{ {
CheckInitialized(); CheckInitialized();
_penumbra!.RedrawService.RedrawObject(gameObject, setting); _redrawService.RedrawObject(gameObject, setting);
} }
public void RedrawAll(RedrawType setting) public void RedrawAll(RedrawType setting)
{ {
CheckInitialized(); CheckInitialized();
_penumbra!.RedrawService.RedrawAll(setting); _redrawService.RedrawAll(setting);
} }
public string ResolveDefaultPath(string path) public string ResolveDefaultPath(string path)
@ -657,7 +685,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
{ {
CheckInitialized(); CheckInitialized();
if (!_modManager.TryGetMod(modDirectory, modName, out var mod) if (!_modManager.TryGetMod(modDirectory, modName, out var mod)
|| !_penumbra!.ModFileSystem.FindLeaf(mod, out var leaf)) || !_modFileSystem.FindLeaf(mod, out var leaf))
return (PenumbraApiEc.ModMissing, string.Empty, false); return (PenumbraApiEc.ModMissing, string.Empty, false);
var fullPath = leaf.FullName(); var fullPath = leaf.FullName();
@ -672,12 +700,12 @@ public class PenumbraApi : IDisposable, IPenumbraApi
return PenumbraApiEc.InvalidArgument; return PenumbraApiEc.InvalidArgument;
if (!_modManager.TryGetMod(modDirectory, modName, out var mod) if (!_modManager.TryGetMod(modDirectory, modName, out var mod)
|| !_penumbra!.ModFileSystem.FindLeaf(mod, out var leaf)) || !_modFileSystem.FindLeaf(mod, out var leaf))
return PenumbraApiEc.ModMissing; return PenumbraApiEc.ModMissing;
try try
{ {
_penumbra.ModFileSystem.RenameAndMove(leaf, newPath); _modFileSystem.RenameAndMove(leaf, newPath);
return PenumbraApiEc.Success; return PenumbraApiEc.Success;
} }
catch catch
@ -986,16 +1014,6 @@ public class PenumbraApi : IDisposable, IPenumbraApi
return Functions.ToCompressedBase64(set, MetaManipulation.CurrentVersion); return Functions.ToCompressedBase64(set, MetaManipulation.CurrentVersion);
} }
internal bool HasTooltip
=> ChangedItemTooltip != null;
internal void InvokeTooltip(object? it)
=> ChangedItemTooltip?.Invoke(it);
internal void InvokeClick(MouseButton button, object? it)
=> ChangedItemClicked?.Invoke(button, it);
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private void CheckInitialized() private void CheckInitialized()
{ {
@ -1117,12 +1135,6 @@ public class PenumbraApi : IDisposable, IPenumbraApi
return true; return true;
} }
public void InvokePreSettingsPanel(string modDirectory)
=> PreSettingsPanelDraw?.Invoke(modDirectory);
public void InvokePostSettingsPanel(string modDirectory)
=> PostSettingsPanelDraw?.Invoke(modDirectory);
// TODO: replace all usages with ActorIdentifier stuff when incrementing API // TODO: replace all usages with ActorIdentifier stuff when incrementing API
private ActorIdentifier NameToIdentifier(string name, ushort worldId) private ActorIdentifier NameToIdentifier(string name, ushort worldId)
{ {

View file

@ -1,4 +1,3 @@
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -11,7 +10,6 @@ using OtterGui;
using OtterGui.Log; using OtterGui.Log;
using Penumbra.Api; using Penumbra.Api;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.UI;
using Penumbra.Util; using Penumbra.Util;
using Penumbra.Collections; using Penumbra.Collections;
using Penumbra.Collections.Cache; using Penumbra.Collections.Cache;
@ -21,7 +19,7 @@ using Penumbra.Services;
using Penumbra.Interop.Services; using Penumbra.Interop.Services;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Mods; using Penumbra.UI.Tabs;
namespace Penumbra; namespace Penumbra;
@ -30,13 +28,8 @@ public class Penumbra : IDalamudPlugin
public string Name public string Name
=> "Penumbra"; => "Penumbra";
public static Logger Log { get; private set; } = null!; public static readonly Logger Log = new();
public static ChatService ChatService { get; private set; } = null!; public static ChatService ChatService { get; private set; } = null!;
public readonly RedrawService RedrawService;
public readonly ModFileSystem ModFileSystem;
public HttpApi HttpApi = null!;
internal ConfigWindow? ConfigWindow { get; private set; }
private readonly ValidityChecker _validityChecker; private readonly ValidityChecker _validityChecker;
private readonly ResidentResourceManager _residentResources; private readonly ResidentResourceManager _residentResources;
@ -46,30 +39,31 @@ public class Penumbra : IDalamudPlugin
private readonly CollectionManager _collectionManager; private readonly CollectionManager _collectionManager;
private readonly Configuration _config; private readonly Configuration _config;
private readonly CharacterUtility _characterUtility; private readonly CharacterUtility _characterUtility;
private readonly RedrawService _redrawService;
private readonly CommunicatorService _communicatorService;
private PenumbraWindowSystem? _windowSystem; private PenumbraWindowSystem? _windowSystem;
private bool _disposed; private bool _disposed;
private readonly PenumbraNew _tmp; private readonly ServiceManager _tmp;
public Penumbra(DalamudPluginInterface pluginInterface) public Penumbra(DalamudPluginInterface pluginInterface)
{ {
Log = PenumbraNew.Log;
try try
{ {
_tmp = new PenumbraNew(this, pluginInterface); _tmp = new ServiceManager(this, pluginInterface, Log);
ChatService = _tmp.Services.GetRequiredService<ChatService>(); ChatService = _tmp.Services.GetRequiredService<ChatService>();
_validityChecker = _tmp.Services.GetRequiredService<ValidityChecker>(); _validityChecker = _tmp.Services.GetRequiredService<ValidityChecker>();
_tmp.Services.GetRequiredService<BackupService>(); _tmp.Services.GetRequiredService<BackupService>(); // Initialize because not required anywhere else.
_config = _tmp.Services.GetRequiredService<Configuration>(); _config = _tmp.Services.GetRequiredService<Configuration>();
_characterUtility = _tmp.Services.GetRequiredService<CharacterUtility>(); _characterUtility = _tmp.Services.GetRequiredService<CharacterUtility>();
_tempMods = _tmp.Services.GetRequiredService<TempModManager>(); _tempMods = _tmp.Services.GetRequiredService<TempModManager>();
_residentResources = _tmp.Services.GetRequiredService<ResidentResourceManager>(); _residentResources = _tmp.Services.GetRequiredService<ResidentResourceManager>();
_tmp.Services.GetRequiredService<ResourceManagerService>(); _tmp.Services.GetRequiredService<ResourceManagerService>(); // Initialize because not required anywhere else.
_modManager = _tmp.Services.GetRequiredService<ModManager>(); _modManager = _tmp.Services.GetRequiredService<ModManager>();
_collectionManager = _tmp.Services.GetRequiredService<CollectionManager>(); _collectionManager = _tmp.Services.GetRequiredService<CollectionManager>();
_tempCollections = _tmp.Services.GetRequiredService<TempCollectionManager>(); _tempCollections = _tmp.Services.GetRequiredService<TempCollectionManager>();
ModFileSystem = _tmp.Services.GetRequiredService<ModFileSystem>(); _redrawService = _tmp.Services.GetRequiredService<RedrawService>();
RedrawService = _tmp.Services.GetRequiredService<RedrawService>(); _communicatorService = _tmp.Services.GetRequiredService<CommunicatorService>();
_tmp.Services.GetRequiredService<ResourceService>(); // Initialize because not required anywhere else. _tmp.Services.GetRequiredService<ResourceService>(); // Initialize because not required anywhere else.
_tmp.Services.GetRequiredService<ModCacheManager>(); // Initialize because not required anywhere else. _tmp.Services.GetRequiredService<ModCacheManager>(); // Initialize because not required anywhere else.
using (var t = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver)) using (var t = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver))
@ -100,7 +94,6 @@ public class Penumbra : IDalamudPlugin
{ {
using var timer = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.Api); using var timer = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.Api);
var api = _tmp.Services.GetRequiredService<IPenumbraApi>(); var api = _tmp.Services.GetRequiredService<IPenumbraApi>();
HttpApi = _tmp.Services.GetRequiredService<HttpApi>();
_tmp.Services.GetRequiredService<PenumbraIpcProviders>(); _tmp.Services.GetRequiredService<PenumbraIpcProviders>();
api.ChangedItemTooltip += it => api.ChangedItemTooltip += it =>
{ {
@ -120,22 +113,16 @@ public class Penumbra : IDalamudPlugin
{ {
using var tInterface = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.Interface); using var tInterface = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.Interface);
var system = _tmp.Services.GetRequiredService<PenumbraWindowSystem>(); var system = _tmp.Services.GetRequiredService<PenumbraWindowSystem>();
system.Window.Setup(this, _tmp.Services.GetRequiredService<ConfigTabBar>());
_tmp.Services.GetRequiredService<CommandHandler>(); _tmp.Services.GetRequiredService<CommandHandler>();
if (!_disposed) if (!_disposed)
{
_windowSystem = system; _windowSystem = system;
ConfigWindow = system.Window;
}
else else
{
system.Dispose(); system.Dispose();
}
} }
); );
} }
public event Action<bool>? EnabledChange;
public bool SetEnabled(bool enabled) public bool SetEnabled(bool enabled)
{ {
if (enabled == _config.EnableMods) if (enabled == _config.EnableMods)
@ -148,7 +135,7 @@ public class Penumbra : IDalamudPlugin
{ {
_collectionManager.Active.Default.SetFiles(_characterUtility); _collectionManager.Active.Default.SetFiles(_characterUtility);
_residentResources.Reload(); _residentResources.Reload();
RedrawService.RedrawAll(RedrawType.Redraw); _redrawService.RedrawAll(RedrawType.Redraw);
} }
} }
else else
@ -157,12 +144,12 @@ public class Penumbra : IDalamudPlugin
{ {
_characterUtility.ResetAll(); _characterUtility.ResetAll();
_residentResources.Reload(); _residentResources.Reload();
RedrawService.RedrawAll(RedrawType.Redraw); _redrawService.RedrawAll(RedrawType.Redraw);
} }
} }
_config.Save(); _config.Save();
EnabledChange?.Invoke(enabled); _communicatorService.EnabledChanged.Invoke(enabled);
return true; return true;
} }

View file

@ -1,10 +1,8 @@
using System;
using Dalamud.Plugin; using Dalamud.Plugin;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Log; using OtterGui.Log;
using Penumbra.Api; using Penumbra.Api;
using Penumbra.Collections;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.GameData.Data; using Penumbra.GameData.Data;
@ -27,22 +25,18 @@ using Penumbra.Meta;
namespace Penumbra; namespace Penumbra;
public class PenumbraNew public class ServiceManager
{ {
public string Name public readonly ServiceProvider Services;
=> "Penumbra";
public static readonly Logger Log = new(); public ServiceManager(Penumbra penumbra, DalamudPluginInterface pi, Logger log)
public readonly ServiceProvider Services;
public PenumbraNew(Penumbra penumbra, DalamudPluginInterface pi)
{ {
var startTimer = new StartTracker(); var startTimer = new StartTracker();
using var time = startTimer.Measure(StartTimeType.Total); using var time = startTimer.Measure(StartTimeType.Total);
var services = new ServiceCollection(); var services = new ServiceCollection();
// Add meta services. // Add meta services.
services.AddSingleton(Log) services.AddSingleton(log)
.AddSingleton(startTimer) .AddSingleton(startTimer)
.AddSingleton<ValidityChecker>() .AddSingleton<ValidityChecker>()
.AddSingleton<PerformanceTracker>() .AddSingleton<PerformanceTracker>()

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.Collections; using Penumbra.Collections;
@ -211,6 +210,90 @@ public sealed class CollectionInheritanceChanged : EventWrapper<Action<ModCollec
=> Invoke(this, collection, inherited); => Invoke(this, collection, inherited);
} }
/// <summary>
/// Triggered when the general Enabled state of Penumbra is changed.
/// <list type="number">
/// <item>Parameter is whether Penumbra is now Enabled (true) or Disabled (false). </item>
/// </list>
/// </summary>
public sealed class EnabledChanged : EventWrapper<Action<bool>>
{
public EnabledChanged()
: base(nameof(EnabledChanged))
{ }
public void Invoke(bool enabled)
=> Invoke(this, enabled);
}
/// <summary>
/// Triggered before the settings panel is drawn.
/// <list type="number">
/// <item>Parameter is the identifier (directory name) of the currently selected mod. </item>
/// </list>
/// </summary>
public sealed class PreSettingsPanelDraw : EventWrapper<Action<string>>
{
public PreSettingsPanelDraw()
: base(nameof(PreSettingsPanelDraw))
{ }
public void Invoke(string modDirectory)
=> Invoke(this, modDirectory);
}
/// <summary>
/// Triggered after the settings panel is drawn.
/// <list type="number">
/// <item>Parameter is the identifier (directory name) of the currently selected mod. </item>
/// </list>
/// </summary>
public sealed class PostSettingsPanelDraw : EventWrapper<Action<string>>
{
public PostSettingsPanelDraw()
: base(nameof(PostSettingsPanelDraw))
{ }
public void Invoke(string modDirectory)
=> Invoke(this, modDirectory);
}
/// <summary>
/// Triggered when a Changed Item in Penumbra is hovered.
/// <list type="number">
/// <item>Parameter is the hovered object data if any. </item>
/// </list>
/// </summary>
public sealed class ChangedItemHover : EventWrapper<Action<object?>>
{
public ChangedItemHover()
: base(nameof(ChangedItemHover))
{ }
public void Invoke(object? data)
=> Invoke(this, data);
public bool HasTooltip
=> HasSubscribers;
}
/// <summary>
/// Triggered when a Changed Item in Penumbra is clicked.
/// <list type="number">
/// <item>Parameter is the clicked mouse button. </item>
/// <item>Parameter is the clicked object data if any.. </item>
/// </list>
/// </summary>
public sealed class ChangedItemClick : EventWrapper<Action<MouseButton, object?>>
{
public ChangedItemClick()
: base(nameof(ChangedItemClick))
{ }
public void Invoke(MouseButton button, object? data)
=> Invoke(this, button, data);
}
public class CommunicatorService : IDisposable public class CommunicatorService : IDisposable
{ {
/// <inheritdoc cref="Services.CollectionChange"/> /// <inheritdoc cref="Services.CollectionChange"/>
@ -249,6 +332,21 @@ public class CommunicatorService : IDisposable
/// <inheritdoc cref="Services.CollectionInheritanceChanged"/> /// <inheritdoc cref="Services.CollectionInheritanceChanged"/>
public readonly CollectionInheritanceChanged CollectionInheritanceChanged = new(); public readonly CollectionInheritanceChanged CollectionInheritanceChanged = new();
/// <inheritdoc cref="Services.EnabledChanged"/>
public readonly EnabledChanged EnabledChanged = new();
/// <inheritdoc cref="Services.PreSettingsPanelDraw"/>
public readonly PreSettingsPanelDraw PreSettingsPanelDraw = new();
/// <inheritdoc cref="Services.PostSettingsPanelDraw"/>
public readonly PostSettingsPanelDraw PostSettingsPanelDraw = new();
/// <inheritdoc cref="Services.ChangedItemHover"/>
public readonly ChangedItemHover ChangedItemHover = new();
/// <inheritdoc cref="Services.ChangedItemClick"/>
public readonly ChangedItemClick ChangedItemClick = new();
public void Dispose() public void Dispose()
{ {
CollectionChange.Dispose(); CollectionChange.Dispose();
@ -263,5 +361,10 @@ public class CommunicatorService : IDisposable
ModPathChanged.Dispose(); ModPathChanged.Dispose();
ModSettingChanged.Dispose(); ModSettingChanged.Dispose();
CollectionInheritanceChanged.Dispose(); CollectionInheritanceChanged.Dispose();
EnabledChanged.Dispose();
PreSettingsPanelDraw.Dispose();
PostSettingsPanelDraw.Dispose();
ChangedItemHover.Dispose();
ChangedItemClick.Dispose();
} }
} }

View file

@ -9,7 +9,8 @@ using Penumbra.Api.Enums;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
using Penumbra.UI.Tabs; using Penumbra.UI.Tabs;
using Penumbra.Util; using Penumbra.Util;
namespace Penumbra.UI; namespace Penumbra.UI;
public sealed class ConfigWindow : Window public sealed class ConfigWindow : Window
@ -18,8 +19,8 @@ public sealed class ConfigWindow : Window
private readonly Configuration _config; private readonly Configuration _config;
private readonly PerformanceTracker _tracker; private readonly PerformanceTracker _tracker;
private readonly ValidityChecker _validityChecker; private readonly ValidityChecker _validityChecker;
private readonly Penumbra _penumbra; private Penumbra? _penumbra;
private readonly ConfigTabBar _configTabs; private ConfigTabBar _configTabs = null!;
private string? _lastException; private string? _lastException;
public void SelectTab(TabType tab) public void SelectTab(TabType tab)
@ -31,15 +32,13 @@ public sealed class ConfigWindow : Window
public ConfigWindow(PerformanceTracker tracker, DalamudPluginInterface pi, Configuration config, ValidityChecker checker, public ConfigWindow(PerformanceTracker tracker, DalamudPluginInterface pi, Configuration config, ValidityChecker checker,
TutorialService tutorial, Penumbra penumbra, ConfigTabBar configTabs) TutorialService tutorial)
: base(GetLabel(checker)) : base(GetLabel(checker))
{ {
_pluginInterface = pi; _pluginInterface = pi;
_config = config; _config = config;
_tracker = tracker; _tracker = tracker;
_validityChecker = checker; _validityChecker = checker;
_penumbra = penumbra;
_configTabs = configTabs;
RespectCloseHotkey = true; RespectCloseHotkey = true;
SizeConstraints = new WindowSizeConstraints() SizeConstraints = new WindowSizeConstraints()
@ -51,6 +50,15 @@ public sealed class ConfigWindow : Window
IsOpen = _config.DebugMode; IsOpen = _config.DebugMode;
} }
public void Setup(Penumbra penumbra, ConfigTabBar configTabs)
{
_penumbra = penumbra;
_configTabs = configTabs;
}
public override bool DrawConditions()
=> _penumbra != null;
public override void PreDraw() public override void PreDraw()
{ {
if (_config.FixMainWindow) if (_config.FixMainWindow)
@ -61,7 +69,7 @@ public sealed class ConfigWindow : Window
public override void Draw() public override void Draw()
{ {
using var timer = _tracker.Measure(PerformanceType.UiMainWindow); using var timer = _tracker.Measure(PerformanceType.UiMainWindow);
UiHelpers.SetupCommonSizes(); UiHelpers.SetupCommonSizes();
try try
{ {
@ -111,6 +119,7 @@ public sealed class ConfigWindow : Window
var text = e.ToString(); var text = e.ToString();
if (text == _lastException) if (text == _lastException)
return; return;
_lastException = text; _lastException = text;
} }
else else
@ -139,7 +148,7 @@ public sealed class ConfigWindow : Window
ImGui.NewLine(); ImGui.NewLine();
UiHelpers.DrawDiscordButton(0); UiHelpers.DrawDiscordButton(0);
ImGui.SameLine(); ImGui.SameLine();
UiHelpers.DrawSupportButton(_penumbra); UiHelpers.DrawSupportButton(_penumbra!);
ImGui.NewLine(); ImGui.NewLine();
ImGui.NewLine(); ImGui.NewLine();
} }

View file

@ -7,22 +7,22 @@ using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Api; using Penumbra.Api;
using Penumbra.Mods.Manager; using Penumbra.Services;
namespace Penumbra.UI.ModsTab; namespace Penumbra.UI.ModsTab;
public class ModPanelChangedItemsTab : ITab public class ModPanelChangedItemsTab : ITab
{ {
private readonly ModFileSystemSelector _selector; private readonly ModFileSystemSelector _selector;
private readonly PenumbraApi _api; private readonly CommunicatorService _communicator;
public ReadOnlySpan<byte> Label public ReadOnlySpan<byte> Label
=> "Changed Items"u8; => "Changed Items"u8;
public ModPanelChangedItemsTab(PenumbraApi api, ModFileSystemSelector selector) public ModPanelChangedItemsTab(ModFileSystemSelector selector, CommunicatorService communicator)
{ {
_api = api; _selector = selector;
_selector = selector; _communicator = communicator;
} }
public bool IsVisible public bool IsVisible
@ -36,6 +36,6 @@ public class ModPanelChangedItemsTab : ITab
var zipList = ZipList.FromSortedList((SortedList<string, object?>)_selector.Selected!.ChangedItems); var zipList = ZipList.FromSortedList((SortedList<string, object?>)_selector.Selected!.ChangedItems);
var height = ImGui.GetTextLineHeight(); var height = ImGui.GetTextLineHeight();
ImGuiClip.ClippedDraw(zipList, kvp => UiHelpers.DrawChangedItem(_api, kvp.Item1, kvp.Item2, true), height); ImGuiClip.ClippedDraw(zipList, kvp => UiHelpers.DrawChangedItem(_communicator, kvp.Item1, kvp.Item2, true), height);
} }
} }

View file

@ -5,7 +5,6 @@ using ImGuiNET;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui; using OtterGui;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Api;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.Collections; using Penumbra.Collections;
using Penumbra.Mods; using Penumbra.Mods;
@ -14,16 +13,17 @@ using Dalamud.Interface.Components;
using Dalamud.Interface; using Dalamud.Interface;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
using Penumbra.Services;
namespace Penumbra.UI.ModsTab; namespace Penumbra.UI.ModsTab;
public class ModPanelSettingsTab : ITab public class ModPanelSettingsTab : ITab
{ {
private readonly Configuration _config; private readonly Configuration _config;
private readonly CommunicatorService _communicator;
private readonly CollectionManager _collectionManager; private readonly CollectionManager _collectionManager;
private readonly ModFileSystemSelector _selector; private readonly ModFileSystemSelector _selector;
private readonly TutorialService _tutorial; private readonly TutorialService _tutorial;
private readonly PenumbraApi _api;
private readonly ModManager _modManager; private readonly ModManager _modManager;
private bool _inherited; private bool _inherited;
@ -33,13 +33,13 @@ public class ModPanelSettingsTab : ITab
private int? _currentPriority = null; private int? _currentPriority = null;
public ModPanelSettingsTab(CollectionManager collectionManager, ModManager modManager, ModFileSystemSelector selector, public ModPanelSettingsTab(CollectionManager collectionManager, ModManager modManager, ModFileSystemSelector selector,
TutorialService tutorial, PenumbraApi api, Configuration config) TutorialService tutorial, CommunicatorService communicator, Configuration config)
{ {
_collectionManager = collectionManager; _collectionManager = collectionManager;
_communicator = communicator;
_modManager = modManager; _modManager = modManager;
_selector = selector; _selector = selector;
_tutorial = tutorial; _tutorial = tutorial;
_api = api;
_config = config; _config = config;
} }
@ -65,7 +65,7 @@ public class ModPanelSettingsTab : ITab
DrawInheritedWarning(); DrawInheritedWarning();
UiHelpers.DefaultLineSpace(); UiHelpers.DefaultLineSpace();
_api.InvokePreSettingsPanel(_selector.Selected!.ModPath.Name); _communicator.PreSettingsPanelDraw.Invoke(_selector.Selected!.ModPath.Name);
DrawEnabledInput(); DrawEnabledInput();
_tutorial.OpenTutorial(BasicTutorialSteps.EnablingMods); _tutorial.OpenTutorial(BasicTutorialSteps.EnablingMods);
ImGui.SameLine(); ImGui.SameLine();
@ -102,7 +102,7 @@ public class ModPanelSettingsTab : ITab
} }
UiHelpers.DefaultLineSpace(); UiHelpers.DefaultLineSpace();
_api.InvokePostSettingsPanel(_selector.Selected!.ModPath.Name); _communicator.PostSettingsPanelDraw.Invoke(_selector.Selected!.ModPath.Name);
} }
/// <summary> Draw a big red bar if the current setting is inherited. </summary> /// <summary> Draw a big red bar if the current setting is inherited. </summary>

View file

@ -7,22 +7,22 @@ using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Api;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Services;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
namespace Penumbra.UI.Tabs; namespace Penumbra.UI.Tabs;
public class ChangedItemsTab : ITab public class ChangedItemsTab : ITab
{ {
private readonly CollectionManager _collectionManager; private readonly CollectionManager _collectionManager;
private readonly PenumbraApi _api; private readonly CommunicatorService _communicator;
public ChangedItemsTab(CollectionManager collectionManager, PenumbraApi api) public ChangedItemsTab(CollectionManager collectionManager, CommunicatorService communicator)
{ {
_collectionManager = collectionManager; _collectionManager = collectionManager;
_api = api; _communicator = communicator;
} }
public ReadOnlySpan<byte> Label public ReadOnlySpan<byte> Label
@ -81,7 +81,7 @@ public class ChangedItemsTab : ITab
private void DrawChangedItemColumn(KeyValuePair<string, (SingleArray<IMod>, object?)> item) private void DrawChangedItemColumn(KeyValuePair<string, (SingleArray<IMod>, object?)> item)
{ {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
UiHelpers.DrawChangedItem(_api, item.Key, item.Value.Item2, false); UiHelpers.DrawChangedItem(_communicator, item.Key, item.Value.Item2, false);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (item.Value.Item1.Count > 0) if (item.Value.Item1.Count > 0)
{ {

View file

@ -9,6 +9,7 @@ using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Api;
using Penumbra.Interop.Services; using Penumbra.Interop.Services;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
using Penumbra.Services; using Penumbra.Services;
@ -35,10 +36,11 @@ public class SettingsTab : ITab
private readonly CharacterUtility _characterUtility; private readonly CharacterUtility _characterUtility;
private readonly ResidentResourceManager _residentResources; private readonly ResidentResourceManager _residentResources;
private readonly DalamudServices _dalamud; private readonly DalamudServices _dalamud;
private readonly HttpApi _httpApi;
public SettingsTab(Configuration config, FontReloader fontReloader, TutorialService tutorial, Penumbra penumbra, public SettingsTab(Configuration config, FontReloader fontReloader, TutorialService tutorial, Penumbra penumbra,
FileDialogService fileDialog, ModManager modManager, ModFileSystemSelector selector, CharacterUtility characterUtility, FileDialogService fileDialog, ModManager modManager, ModFileSystemSelector selector, CharacterUtility characterUtility,
ResidentResourceManager residentResources, DalamudServices dalamud, ModExportManager modExportManager) ResidentResourceManager residentResources, DalamudServices dalamud, ModExportManager modExportManager, HttpApi httpApi)
{ {
_config = config; _config = config;
_fontReloader = fontReloader; _fontReloader = fontReloader;
@ -51,6 +53,7 @@ public class SettingsTab : ITab
_residentResources = residentResources; _residentResources = residentResources;
_dalamud = dalamud; _dalamud = dalamud;
_modExportManager = modExportManager; _modExportManager = modExportManager;
_httpApi = httpApi;
} }
public void DrawHeader() public void DrawHeader()
@ -630,7 +633,6 @@ public class SettingsTab : ITab
private void DrawAdvancedSettings() private void DrawAdvancedSettings()
{ {
var header = ImGui.CollapsingHeader("Advanced"); var header = ImGui.CollapsingHeader("Advanced");
_tutorial.OpenTutorial(BasicTutorialSteps.Deprecated1);
if (!header) if (!header)
return; return;
@ -657,9 +659,9 @@ public class SettingsTab : ITab
if (ImGui.Checkbox("##http", ref http)) if (ImGui.Checkbox("##http", ref http))
{ {
if (http) if (http)
_penumbra.HttpApi.CreateWebServer(); _httpApi.CreateWebServer();
else else
_penumbra.HttpApi.ShutdownWebServer(); _httpApi.ShutdownWebServer();
_config.EnableHttpApi = http; _config.EnableHttpApi = http;
_config.Save(); _config.Save();

View file

@ -47,10 +47,7 @@ public class TutorialService
public const string SelectedCollection = "Selected Collection"; public const string SelectedCollection = "Selected Collection";
public const string DefaultCollection = "Base Collection"; public const string DefaultCollection = "Base Collection";
public const string InterfaceCollection = "Interface Collection"; public const string InterfaceCollection = "Interface Collection";
public const string ActiveCollections = "Active Collections";
public const string AssignedCollections = "Assigned Collections"; public const string AssignedCollections = "Assigned Collections";
public const string GroupAssignment = "Group Assignment";
public const string IndividualAssignments = "Individual Assignments";
public const string SupportedRedrawModifiers = " - nothing, to redraw all characters\n" public const string SupportedRedrawModifiers = " - nothing, to redraw all characters\n"
+ " - 'self' or '<me>': your own character\n" + " - 'self' or '<me>': your own character\n"

View file

@ -13,6 +13,7 @@ using Penumbra.Api;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
using Penumbra.Services;
using Penumbra.String; using Penumbra.String;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
@ -60,7 +61,7 @@ public static class UiHelpers
/// Draw a changed item, invoking the Api-Events for clicks and tooltips. /// Draw a changed item, invoking the Api-Events for clicks and tooltips.
/// Also draw the item Id in grey if requested. /// Also draw the item Id in grey if requested.
/// </summary> /// </summary>
public static void DrawChangedItem(PenumbraApi api, string name, object? data, bool drawId) public static void DrawChangedItem(CommunicatorService communicator, string name, object? data, bool drawId)
{ {
name = ChangedItemName(name, data); name = ChangedItemName(name, data);
var ret = ImGui.Selectable(name) ? MouseButton.Left : MouseButton.None; var ret = ImGui.Selectable(name) ? MouseButton.Left : MouseButton.None;
@ -68,15 +69,15 @@ public static class UiHelpers
ret = ImGui.IsItemClicked(ImGuiMouseButton.Middle) ? MouseButton.Middle : ret; ret = ImGui.IsItemClicked(ImGuiMouseButton.Middle) ? MouseButton.Middle : ret;
if (ret != MouseButton.None) if (ret != MouseButton.None)
api.InvokeClick(ret, data); communicator.ChangedItemClick.Invoke(ret, data);
if (api.HasTooltip && ImGui.IsItemHovered()) if (communicator.ChangedItemHover.HasTooltip && ImGui.IsItemHovered())
{ {
// We can not be sure that any subscriber actually prints something in any case. // We can not be sure that any subscriber actually prints something in any case.
// Circumvent ugly blank tooltip with less-ugly useless tooltip. // Circumvent ugly blank tooltip with less-ugly useless tooltip.
using var tt = ImRaii.Tooltip(); using var tt = ImRaii.Tooltip();
using var group = ImRaii.Group(); using var group = ImRaii.Group();
api.InvokeTooltip(data); communicator.ChangedItemHover.Invoke(data);
group.Dispose(); group.Dispose();
if (ImGui.GetItemRectSize() == Vector2.Zero) if (ImGui.GetItemRectSize() == Vector2.Zero)
ImGui.TextUnformatted("No actions available."); ImGui.TextUnformatted("No actions available.");

View file

@ -9,6 +9,9 @@ public abstract class EventWrapper<T> : IDisposable where T : Delegate
private readonly string _name; private readonly string _name;
private readonly List<(object Subscriber, int Priority)> _event = new(); private readonly List<(object Subscriber, int Priority)> _event = new();
public bool HasSubscribers
=> _event.Count > 0;
protected EventWrapper(string name) protected EventWrapper(string name)
=> _name = name; => _name = name;