mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
Attach to Penumbra via IPC, independently of API interface.
This commit is contained in:
parent
f10280d15d
commit
d4a00dca0c
4 changed files with 159 additions and 115 deletions
|
|
@ -106,7 +106,7 @@ namespace Glamourer.Gui
|
|||
save.Apply(player);
|
||||
if (_inGPose)
|
||||
save.Apply(fallback!);
|
||||
_plugin.UpdateActors(player, fallback);
|
||||
Glamourer.Penumbra.UpdateActors(player, fallback);
|
||||
}
|
||||
|
||||
private void DrawApplyToTargetButton(CharacterSave save)
|
||||
|
|
@ -122,7 +122,7 @@ namespace Glamourer.Gui
|
|||
save.Apply(player);
|
||||
if (fallBackActor != null)
|
||||
save.Apply(fallBackActor);
|
||||
_plugin.UpdateActors(player, fallBackActor);
|
||||
Glamourer.Penumbra.UpdateActors(player, fallBackActor);
|
||||
}
|
||||
|
||||
private void SaveNewDesign(CharacterSave save)
|
||||
|
|
@ -180,7 +180,7 @@ namespace Glamourer.Gui
|
|||
changes |= DrawMiscellaneous(_currentSave, _player);
|
||||
|
||||
if (_player != null && changes)
|
||||
_plugin.UpdateActors(_player);
|
||||
Glamourer.Penumbra.UpdateActors(_player);
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,10 +53,9 @@ namespace Glamourer.Gui
|
|||
return;
|
||||
}
|
||||
|
||||
if (ImGui.Button(buttonLabel) && Glamourer.GetPenumbra())
|
||||
if (ImGui.Button(buttonLabel))
|
||||
{
|
||||
_plugin.UnregisterFunctions();
|
||||
_plugin.RegisterFunctions();
|
||||
Glamourer.Penumbra.Reattach(true);
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
|
|
@ -88,12 +87,11 @@ namespace Glamourer.Gui
|
|||
cfg.AttachToPenumbra = v;
|
||||
if (v)
|
||||
{
|
||||
if (Glamourer.GetPenumbra())
|
||||
_plugin.RegisterFunctions();
|
||||
Glamourer.Penumbra.Reattach(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_plugin.UnregisterFunctions();
|
||||
Glamourer.Penumbra.Unattach();
|
||||
}
|
||||
});
|
||||
ImGui.SameLine();
|
||||
|
|
|
|||
|
|
@ -3,109 +3,32 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.FileSystem;
|
||||
using Glamourer.Gui;
|
||||
using ImGuiNET;
|
||||
using Penumbra.Api;
|
||||
using Penumbra.PlayerWatch;
|
||||
|
||||
namespace Glamourer
|
||||
{
|
||||
public class Glamourer : IDalamudPlugin
|
||||
{
|
||||
public const int RequiredPenumbraShareVersion = 3;
|
||||
|
||||
private const string HelpString = "[Copy|Apply|Save],[Name or PlaceHolder],<Name for Save>";
|
||||
|
||||
public string Name
|
||||
=> "Glamourer";
|
||||
|
||||
public static GlamourerConfig Config = null!;
|
||||
private Interface _interface = null!;
|
||||
public static ICustomizationManager Customization = null!;
|
||||
public DesignManager Designs = null!;
|
||||
public IPlayerWatcher PlayerWatcher = null!;
|
||||
public static GlamourerConfig Config = null!;
|
||||
public static IPlayerWatcher PlayerWatcher = null!;
|
||||
public static ICustomizationManager Customization = null!;
|
||||
private readonly Interface _interface;
|
||||
public DesignManager Designs;
|
||||
|
||||
public static string Version = string.Empty;
|
||||
|
||||
public static IPenumbraApi? Penumbra;
|
||||
|
||||
private static void PenumbraTooltip(object? it)
|
||||
{
|
||||
if (it is Lumina.Excel.GeneratedSheets.Item)
|
||||
ImGui.Text("Right click to apply to current Glamourer Set. [Glamourer]");
|
||||
}
|
||||
|
||||
private void PenumbraRightClick(MouseButton button, object? it)
|
||||
{
|
||||
if (button != MouseButton.Right || it is not Lumina.Excel.GeneratedSheets.Item item)
|
||||
return;
|
||||
|
||||
var gPose = Dalamud.Objects[Interface.GPoseActorId] as Character;
|
||||
var player = Dalamud.Objects[0] as Character;
|
||||
var writeItem = new Item(item, string.Empty);
|
||||
if (gPose != null)
|
||||
{
|
||||
writeItem.Write(gPose.Address);
|
||||
UpdateActors(gPose, player);
|
||||
}
|
||||
else if (player != null)
|
||||
{
|
||||
writeItem.Write(player.Address);
|
||||
UpdateActors(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterFunctions()
|
||||
{
|
||||
if (Penumbra == null || !Penumbra.Valid)
|
||||
return;
|
||||
|
||||
Penumbra!.ChangedItemTooltip += PenumbraTooltip;
|
||||
Penumbra!.ChangedItemClicked += PenumbraRightClick;
|
||||
}
|
||||
|
||||
public void UnregisterFunctions()
|
||||
{
|
||||
if (Penumbra == null || !Penumbra.Valid)
|
||||
return;
|
||||
|
||||
Penumbra!.ChangedItemTooltip -= PenumbraTooltip;
|
||||
Penumbra!.ChangedItemClicked -= PenumbraRightClick;
|
||||
}
|
||||
|
||||
internal static bool GetPenumbra()
|
||||
{
|
||||
try
|
||||
{
|
||||
var subscriber = Dalamud.PluginInterface.GetIpcSubscriber<IPenumbraApiBase>("Penumbra.Api");
|
||||
var penumbraApiBase = subscriber.InvokeFunc();
|
||||
if (penumbraApiBase.ApiVersion != RequiredPenumbraShareVersion)
|
||||
{
|
||||
PluginLog.Debug("Could not get Penumbra because API version {penumbraApiBase.ApiVersion} does not equal the required version {RequiredPenumbraShareVersion}.");
|
||||
Penumbra = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
Penumbra = penumbraApiBase as IPenumbraApi;
|
||||
}
|
||||
catch (IpcNotReadyError ipc)
|
||||
{
|
||||
Penumbra = null;
|
||||
PluginLog.Debug($"Could not get Penumbra because IPC not registered:\n{ipc}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Penumbra = null;
|
||||
PluginLog.Debug($"Could not get Penumbra for unknown reason:\n{e}");
|
||||
}
|
||||
|
||||
return Penumbra != null;
|
||||
}
|
||||
public static string Version = string.Empty;
|
||||
public static PenumbraAttach Penumbra = null!;
|
||||
|
||||
public Glamourer(DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
|
|
@ -114,8 +37,7 @@ namespace Glamourer
|
|||
Config = GlamourerConfig.Load();
|
||||
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
||||
Designs = new DesignManager();
|
||||
if (GetPenumbra() && Config.AttachToPenumbra)
|
||||
RegisterFunctions();
|
||||
Penumbra = new PenumbraAttach(Config.AttachToPenumbra);
|
||||
PlayerWatcher = PlayerWatchFactory.Create(Dalamud.Framework, Dalamud.ClientState, Dalamud.Objects);
|
||||
|
||||
Dalamud.Commands.AddHandler("/glamourer", new CommandInfo(OnGlamourer)
|
||||
|
|
@ -177,7 +99,7 @@ namespace Glamourer
|
|||
save = d.Data;
|
||||
|
||||
save?.Apply(actor);
|
||||
UpdateActors(actor);
|
||||
Penumbra.UpdateActors(actor);
|
||||
}
|
||||
|
||||
public void SaveCommand(Character actor, string path)
|
||||
|
|
@ -268,27 +190,11 @@ namespace Glamourer
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
PlayerWatcher?.Dispose();
|
||||
UnregisterFunctions();
|
||||
_interface?.Dispose();
|
||||
Penumbra.Dispose();
|
||||
PlayerWatcher.Dispose();
|
||||
_interface.Dispose();
|
||||
Dalamud.Commands.RemoveHandler("/glamour");
|
||||
Dalamud.Commands.RemoveHandler("/glamourer");
|
||||
}
|
||||
|
||||
// Update actors without triggering PlayerWatcher Events,
|
||||
// then manually redraw using Penumbra.
|
||||
public void UpdateActors(Character actor, Character? gPoseOriginalActor = null)
|
||||
{
|
||||
var newEquip = PlayerWatcher.UpdateActorWithoutEvent(actor);
|
||||
Penumbra?.RedrawObject(actor, RedrawType.WithSettings);
|
||||
|
||||
// Special case for carrying over changes to the gPose actor to the regular player actor, too.
|
||||
if (gPoseOriginalActor == null)
|
||||
return;
|
||||
|
||||
newEquip.Write(gPoseOriginalActor.Address);
|
||||
PlayerWatcher.UpdateActorWithoutEvent(gPoseOriginalActor);
|
||||
Penumbra?.RedrawObject(gPoseOriginalActor, RedrawType.AfterGPoseWithSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
140
Glamourer/PenumbraAttach.cs
Normal file
140
Glamourer/PenumbraAttach.cs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Gui;
|
||||
using ImGuiNET;
|
||||
using Penumbra.Api;
|
||||
using Penumbra.PlayerWatch;
|
||||
|
||||
namespace Glamourer
|
||||
{
|
||||
public class PenumbraAttach : IDisposable
|
||||
{
|
||||
public const int RequiredPenumbraShareVersion = 3;
|
||||
|
||||
private ICallGateSubscriber<object?, object>? TooltipSubscriber;
|
||||
private ICallGateSubscriber<int, object?, object>? ClickSubscriber;
|
||||
private ICallGateSubscriber<string, int, object>? RedrawSubscriberName;
|
||||
private ICallGateSubscriber<GameObject, int, object>? RedrawSubscriberObject;
|
||||
|
||||
public PenumbraAttach(bool attach)
|
||||
=> Reattach(attach);
|
||||
|
||||
public void Reattach(bool attach)
|
||||
{
|
||||
try
|
||||
{
|
||||
Unattach();
|
||||
|
||||
var versionSubscriber = Dalamud.PluginInterface.GetIpcSubscriber<int>("Penumbra.ApiVersion");
|
||||
var version = versionSubscriber.InvokeFunc();
|
||||
if (version != RequiredPenumbraShareVersion)
|
||||
throw new Exception($"Invalid Version {version}, required Version {RequiredPenumbraShareVersion}.");
|
||||
|
||||
RedrawSubscriberName = Dalamud.PluginInterface.GetIpcSubscriber<string, int, object>("Penumbra.RedrawObjectByName");
|
||||
RedrawSubscriberObject = Dalamud.PluginInterface.GetIpcSubscriber<GameObject, int, object>("Penumbra.RedrawObject");
|
||||
|
||||
if (!attach)
|
||||
return;
|
||||
|
||||
TooltipSubscriber = Dalamud.PluginInterface.GetIpcSubscriber<object?, object>("Penumbra.ChangedItemTooltip");
|
||||
ClickSubscriber = Dalamud.PluginInterface.GetIpcSubscriber<int, object?, object>("Penumbra.ChangedItemClick");
|
||||
TooltipSubscriber.Subscribe(PenumbraTooltip);
|
||||
ClickSubscriber.Subscribe(PenumbraRightClickWrapper);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Debug($"Could not attach to Penumbra:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Unattach()
|
||||
{
|
||||
TooltipSubscriber?.Unsubscribe(PenumbraTooltip);
|
||||
ClickSubscriber?.Unsubscribe(PenumbraRightClickWrapper);
|
||||
TooltipSubscriber = null;
|
||||
ClickSubscriber = null;
|
||||
RedrawSubscriberName = null;
|
||||
RedrawSubscriberObject = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
=> Unattach();
|
||||
|
||||
private static void PenumbraTooltip(object? it)
|
||||
{
|
||||
if (it is Lumina.Excel.GeneratedSheets.Item)
|
||||
ImGui.Text("Right click to apply to current Glamourer Set. [Glamourer]");
|
||||
}
|
||||
|
||||
private void PenumbraRightClick(MouseButton button, object? it)
|
||||
{
|
||||
if (button != MouseButton.Right || it is not Lumina.Excel.GeneratedSheets.Item item)
|
||||
return;
|
||||
|
||||
var gPose = Dalamud.Objects[Interface.GPoseActorId] as Character;
|
||||
var player = Dalamud.Objects[0] as Character;
|
||||
var writeItem = new Item(item, string.Empty);
|
||||
if (gPose != null)
|
||||
{
|
||||
writeItem.Write(gPose.Address);
|
||||
UpdateActors(gPose, player);
|
||||
}
|
||||
else if (player != null)
|
||||
{
|
||||
writeItem.Write(player.Address);
|
||||
UpdateActors(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void PenumbraRightClickWrapper(int button, object? it)
|
||||
=> PenumbraRightClick((MouseButton) button, it);
|
||||
|
||||
public void RedrawObject(GameObject actor, RedrawType settings, bool repeat)
|
||||
{
|
||||
if (RedrawSubscriberObject != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
RedrawSubscriberObject.InvokeFunc(actor, (int) settings);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (repeat)
|
||||
{
|
||||
Reattach(Glamourer.Config.AttachToPenumbra);
|
||||
RedrawObject(actor, settings, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLog.Debug($"Failure redrawing actor:\n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (repeat)
|
||||
{
|
||||
Reattach(Glamourer.Config.AttachToPenumbra);
|
||||
RedrawObject(actor, settings, false);
|
||||
}
|
||||
else
|
||||
PluginLog.Debug("Trying to redraw actor, but not attached to Penumbra.");
|
||||
}
|
||||
|
||||
// Update actors without triggering PlayerWatcher Events,
|
||||
// then manually redraw using Penumbra.
|
||||
public void UpdateActors(Character actor, Character? gPoseOriginalActor = null)
|
||||
{
|
||||
var newEquip = Glamourer.PlayerWatcher.UpdateActorWithoutEvent(actor);
|
||||
RedrawObject(actor, RedrawType.WithSettings, true);
|
||||
|
||||
// Special case for carrying over changes to the gPose actor to the regular player actor, too.
|
||||
if (gPoseOriginalActor == null)
|
||||
return;
|
||||
|
||||
newEquip.Write(gPoseOriginalActor.Address);
|
||||
Glamourer.PlayerWatcher.UpdateActorWithoutEvent(gPoseOriginalActor);
|
||||
RedrawObject(gPoseOriginalActor, RedrawType.AfterGPoseWithSettings, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue