mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +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);
|
save.Apply(player);
|
||||||
if (_inGPose)
|
if (_inGPose)
|
||||||
save.Apply(fallback!);
|
save.Apply(fallback!);
|
||||||
_plugin.UpdateActors(player, fallback);
|
Glamourer.Penumbra.UpdateActors(player, fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawApplyToTargetButton(CharacterSave save)
|
private void DrawApplyToTargetButton(CharacterSave save)
|
||||||
|
|
@ -122,7 +122,7 @@ namespace Glamourer.Gui
|
||||||
save.Apply(player);
|
save.Apply(player);
|
||||||
if (fallBackActor != null)
|
if (fallBackActor != null)
|
||||||
save.Apply(fallBackActor);
|
save.Apply(fallBackActor);
|
||||||
_plugin.UpdateActors(player, fallBackActor);
|
Glamourer.Penumbra.UpdateActors(player, fallBackActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveNewDesign(CharacterSave save)
|
private void SaveNewDesign(CharacterSave save)
|
||||||
|
|
@ -180,7 +180,7 @@ namespace Glamourer.Gui
|
||||||
changes |= DrawMiscellaneous(_currentSave, _player);
|
changes |= DrawMiscellaneous(_currentSave, _player);
|
||||||
|
|
||||||
if (_player != null && changes)
|
if (_player != null && changes)
|
||||||
_plugin.UpdateActors(_player);
|
Glamourer.Penumbra.UpdateActors(_player);
|
||||||
ImGui.EndChild();
|
ImGui.EndChild();
|
||||||
ImGui.EndGroup();
|
ImGui.EndGroup();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,9 @@ namespace Glamourer.Gui
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.Button(buttonLabel) && Glamourer.GetPenumbra())
|
if (ImGui.Button(buttonLabel))
|
||||||
{
|
{
|
||||||
_plugin.UnregisterFunctions();
|
Glamourer.Penumbra.Reattach(true);
|
||||||
_plugin.RegisterFunctions();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
|
|
@ -88,12 +87,11 @@ namespace Glamourer.Gui
|
||||||
cfg.AttachToPenumbra = v;
|
cfg.AttachToPenumbra = v;
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
if (Glamourer.GetPenumbra())
|
Glamourer.Penumbra.Reattach(true);
|
||||||
_plugin.RegisterFunctions();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_plugin.UnregisterFunctions();
|
Glamourer.Penumbra.Unattach();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
|
||||||
|
|
@ -3,109 +3,32 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Dalamud.Game.Command;
|
using Dalamud.Game.Command;
|
||||||
using Dalamud.Logging;
|
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Glamourer.Customization;
|
using Glamourer.Customization;
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.FileSystem;
|
using Glamourer.FileSystem;
|
||||||
using Glamourer.Gui;
|
using Glamourer.Gui;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Penumbra.Api;
|
|
||||||
using Penumbra.PlayerWatch;
|
using Penumbra.PlayerWatch;
|
||||||
|
|
||||||
namespace Glamourer
|
namespace Glamourer
|
||||||
{
|
{
|
||||||
public class Glamourer : IDalamudPlugin
|
public class Glamourer : IDalamudPlugin
|
||||||
{
|
{
|
||||||
public const int RequiredPenumbraShareVersion = 3;
|
|
||||||
|
|
||||||
private const string HelpString = "[Copy|Apply|Save],[Name or PlaceHolder],<Name for Save>";
|
private const string HelpString = "[Copy|Apply|Save],[Name or PlaceHolder],<Name for Save>";
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
=> "Glamourer";
|
=> "Glamourer";
|
||||||
|
|
||||||
public static GlamourerConfig Config = null!;
|
public static GlamourerConfig Config = null!;
|
||||||
private Interface _interface = null!;
|
public static IPlayerWatcher PlayerWatcher = null!;
|
||||||
public static ICustomizationManager Customization = null!;
|
public static ICustomizationManager Customization = null!;
|
||||||
public DesignManager Designs = null!;
|
private readonly Interface _interface;
|
||||||
public IPlayerWatcher PlayerWatcher = null!;
|
public DesignManager Designs;
|
||||||
|
|
||||||
|
|
||||||
public static string Version = string.Empty;
|
public static string Version = string.Empty;
|
||||||
|
public static PenumbraAttach Penumbra = null!;
|
||||||
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 Glamourer(DalamudPluginInterface pluginInterface)
|
public Glamourer(DalamudPluginInterface pluginInterface)
|
||||||
{
|
{
|
||||||
|
|
@ -114,8 +37,7 @@ namespace Glamourer
|
||||||
Config = GlamourerConfig.Load();
|
Config = GlamourerConfig.Load();
|
||||||
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
||||||
Designs = new DesignManager();
|
Designs = new DesignManager();
|
||||||
if (GetPenumbra() && Config.AttachToPenumbra)
|
Penumbra = new PenumbraAttach(Config.AttachToPenumbra);
|
||||||
RegisterFunctions();
|
|
||||||
PlayerWatcher = PlayerWatchFactory.Create(Dalamud.Framework, Dalamud.ClientState, Dalamud.Objects);
|
PlayerWatcher = PlayerWatchFactory.Create(Dalamud.Framework, Dalamud.ClientState, Dalamud.Objects);
|
||||||
|
|
||||||
Dalamud.Commands.AddHandler("/glamourer", new CommandInfo(OnGlamourer)
|
Dalamud.Commands.AddHandler("/glamourer", new CommandInfo(OnGlamourer)
|
||||||
|
|
@ -177,7 +99,7 @@ namespace Glamourer
|
||||||
save = d.Data;
|
save = d.Data;
|
||||||
|
|
||||||
save?.Apply(actor);
|
save?.Apply(actor);
|
||||||
UpdateActors(actor);
|
Penumbra.UpdateActors(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveCommand(Character actor, string path)
|
public void SaveCommand(Character actor, string path)
|
||||||
|
|
@ -268,27 +190,11 @@ namespace Glamourer
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
PlayerWatcher?.Dispose();
|
Penumbra.Dispose();
|
||||||
UnregisterFunctions();
|
PlayerWatcher.Dispose();
|
||||||
_interface?.Dispose();
|
_interface.Dispose();
|
||||||
Dalamud.Commands.RemoveHandler("/glamour");
|
Dalamud.Commands.RemoveHandler("/glamour");
|
||||||
Dalamud.Commands.RemoveHandler("/glamourer");
|
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