diff --git a/Penumbra.Api/IPenumbraApi.cs b/Penumbra.Api/IPenumbraApi.cs
new file mode 100644
index 00000000..cdfa75c9
--- /dev/null
+++ b/Penumbra.Api/IPenumbraApi.cs
@@ -0,0 +1,32 @@
+using System;
+using Dalamud.Game.ClientState.Actors.Types;
+
+namespace Penumbra.Api
+{
+ public interface IPenumbraApiBase
+ {
+ public int ApiVersion { get; }
+ public bool Valid { get; }
+ }
+
+ public enum MouseButton
+ {
+ None,
+ Left,
+ Right,
+ Middle,
+ }
+
+ public delegate void ChangedItemHover( object? item );
+ public delegate void ChangedItemClick( MouseButton button, object? item );
+
+ public interface IPenumbraApi : IPenumbraApiBase
+ {
+ public event ChangedItemHover? ChangedItemTooltip;
+ public event ChangedItemClick? ChangedItemClicked;
+
+ public void RedrawActor( string name, RedrawType setting );
+ public void RedrawActor( Actor actor, RedrawType setting );
+ public void RedrawAll( RedrawType setting );
+ }
+}
\ No newline at end of file
diff --git a/Penumbra.Api/Penumbra.Api.csproj b/Penumbra.Api/Penumbra.Api.csproj
new file mode 100644
index 00000000..82aef2c2
--- /dev/null
+++ b/Penumbra.Api/Penumbra.Api.csproj
@@ -0,0 +1,41 @@
+
+
+ net472
+ preview
+ Penumbra.Api
+ absolute gangstas
+ Penumbra
+ Copyright © 2020
+ 1.0.0.0
+ 1.0.0.0
+ bin\$(Configuration)\
+ true
+ enable
+
+
+
+ full
+ DEBUG;TRACE
+
+
+
+ pdbonly
+
+
+
+ $(MSBuildWarningsAsMessages);MSB3277
+
+
+
+
+ $(DALAMUD_ROOT)\Dalamud.dll
+ ..\libs\Dalamud.dll
+ $(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll
+ False
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Penumbra.Api/RedrawType.cs b/Penumbra.Api/RedrawType.cs
new file mode 100644
index 00000000..372f8063
--- /dev/null
+++ b/Penumbra.Api/RedrawType.cs
@@ -0,0 +1,12 @@
+namespace Penumbra.Api
+{
+ public enum RedrawType
+ {
+ WithoutSettings,
+ WithSettings,
+ OnlyWithSettings,
+ Unload,
+ RedrawWithoutSettings,
+ RedrawWithSettings,
+ }
+}
\ No newline at end of file
diff --git a/Penumbra.sln b/Penumbra.sln
index 58df4bf5..07712e02 100644
--- a/Penumbra.sln
+++ b/Penumbra.sln
@@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Penumbra.GameData", "Penumbra.GameData\Penumbra.GameData.csproj", "{EE551E87-FDB3-4612-B500-DC870C07C605}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Penumbra.Api", "Penumbra.API\Penumbra.Api.csproj", "{EE8C148E-BF59-43FB-89FC-4CADC9047FDF}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Penumbra.PlayerWatch", "Penumbra.PlayerWatch\Penumbra.PlayerWatch.csproj", "{01685BD8-8847-4B49-BF90-1683B4C76B0E}"
EndProject
Global
@@ -28,6 +30,10 @@ Global
{EE551E87-FDB3-4612-B500-DC870C07C605}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE551E87-FDB3-4612-B500-DC870C07C605}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE551E87-FDB3-4612-B500-DC870C07C605}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EE8C148E-BF59-43FB-89FC-4CADC9047FDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EE8C148E-BF59-43FB-89FC-4CADC9047FDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EE8C148E-BF59-43FB-89FC-4CADC9047FDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EE8C148E-BF59-43FB-89FC-4CADC9047FDF}.Release|Any CPU.Build.0 = Release|Any CPU
{01685BD8-8847-4B49-BF90-1683B4C76B0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{01685BD8-8847-4B49-BF90-1683B4C76B0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{01685BD8-8847-4B49-BF90-1683B4C76B0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/Penumbra/API/ModsController.cs b/Penumbra/API/ModsController.cs
index 9edf64de..2453f862 100644
--- a/Penumbra/API/ModsController.cs
+++ b/Penumbra/API/ModsController.cs
@@ -6,7 +6,7 @@ using EmbedIO.WebApi;
using Penumbra.Mods;
using Penumbra.Util;
-namespace Penumbra.API
+namespace Penumbra.Api
{
public class ModsController : WebApiController
{
diff --git a/Penumbra/Api/PenumbraApi.cs b/Penumbra/Api/PenumbraApi.cs
new file mode 100644
index 00000000..ef00d18f
--- /dev/null
+++ b/Penumbra/Api/PenumbraApi.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Linq;
+using Dalamud.Game.ClientState.Actors.Types;
+using ImGuiNET;
+
+namespace Penumbra.Api
+{
+ public class PenumbraApi : IDisposable, IPenumbraApi
+ {
+ public int ApiVersion { get; } = 1;
+ private bool _initialized = false;
+ private readonly Plugin _plugin;
+
+ public PenumbraApi( Plugin penumbra )
+ {
+ _plugin = penumbra;
+ //_plugin.SettingsInterface.ChangedItemClicked += TriggerChangedItemClicked;
+ _initialized = true;
+ }
+
+ public void Dispose()
+ {
+ //_plugin.SettingsInterface.ChangedItemClicked -= TriggerChangedItemClicked;
+ _initialized = false;
+ }
+
+ public event ChangedItemClick? ChangedItemClicked;
+ public event ChangedItemHover? ChangedItemTooltip;
+
+ internal bool HasTooltip
+ => ChangedItemTooltip != null;
+
+ internal void InvokeTooltip( object? it )
+ => ChangedItemTooltip?.Invoke( it );
+
+ internal void InvokeClick( MouseButton button, object? it )
+ => ChangedItemClicked?.Invoke( button, it );
+
+
+ private void CheckInitialized()
+ {
+ if( !_initialized )
+ {
+ throw new Exception( "PluginShare is not initialized." );
+ }
+ }
+
+ public void RedrawActor( string name, RedrawType setting )
+ {
+ CheckInitialized();
+
+ _plugin.ActorRefresher.RedrawActor( name, setting );
+ }
+
+ public void RedrawActor( Actor? actor, RedrawType setting )
+ {
+ CheckInitialized();
+
+ _plugin.ActorRefresher.RedrawActor( actor, setting );
+ }
+
+ public void RedrawAll( RedrawType setting )
+ {
+ CheckInitialized();
+
+ _plugin.ActorRefresher.RedrawAll( setting );
+ }
+
+ public bool Valid
+ => _initialized;
+ }
+}
\ No newline at end of file
diff --git a/Penumbra/Interop/ActorRefresher.cs b/Penumbra/Interop/ActorRefresher.cs
index 082a30b3..6d1454c0 100644
--- a/Penumbra/Interop/ActorRefresher.cs
+++ b/Penumbra/Interop/ActorRefresher.cs
@@ -7,20 +7,11 @@ using System.Threading.Tasks;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Actors.Types;
using Dalamud.Plugin;
+using Penumbra.Api;
using Penumbra.Mods;
namespace Penumbra.Interop
{
- public enum Redraw
- {
- WithoutSettings,
- WithSettings,
- OnlyWithSettings,
- Unload,
- RedrawWithoutSettings,
- RedrawWithSettings,
- }
-
public class ActorRefresher : IDisposable
{
private delegate void ManipulateDraw( IntPtr actor );
@@ -43,14 +34,14 @@ namespace Penumbra.Interop
private readonly DalamudPluginInterface _pi;
private readonly ModManager _mods;
- private readonly Queue< (int actorId, string name, Redraw s) > _actorIds = new();
+ private readonly Queue< (int actorId, string name, RedrawType s) > _actorIds = new();
private int _currentFrame = 0;
private bool _changedSettings = false;
private int _currentActorId = -1;
private string? _currentActorName = null;
private LoadingFlags _currentActorStartState = 0;
- private Redraw _currentActorRedraw = Redraw.Unload;
+ private RedrawType _currentActorRedrawType = RedrawType.Unload;
public static IntPtr RenderPtr( Actor actor )
=> actor.Address + RenderModeOffset;
@@ -165,7 +156,7 @@ namespace Penumbra.Interop
var (id, name, s) = _actorIds.Dequeue();
_currentActorName = name;
_currentActorId = id;
- _currentActorRedraw = s;
+ _currentActorRedrawType = s;
var (actor, idx) = FindCurrentActor();
if( actor == null )
{
@@ -189,30 +180,30 @@ namespace Penumbra.Interop
return;
}
- switch( _currentActorRedraw )
+ switch( _currentActorRedrawType )
{
- case Redraw.Unload:
+ case RedrawType.Unload:
WriteInvisible( actor, idx );
_currentFrame = 0;
break;
- case Redraw.RedrawWithSettings:
+ case RedrawType.RedrawWithSettings:
ChangeSettings();
++_currentFrame;
break;
- case Redraw.RedrawWithoutSettings:
+ case RedrawType.RedrawWithoutSettings:
WriteVisible( actor, idx );
_currentFrame = 0;
break;
- case Redraw.WithoutSettings:
+ case RedrawType.WithoutSettings:
WriteInvisible( actor, idx );
++_currentFrame;
break;
- case Redraw.WithSettings:
+ case RedrawType.WithSettings:
ChangeSettings();
WriteInvisible( actor, idx );
++_currentFrame;
break;
- case Redraw.OnlyWithSettings:
+ case RedrawType.OnlyWithSettings:
ChangeSettings();
if( !_changedSettings )
{
@@ -283,7 +274,7 @@ namespace Penumbra.Interop
}
}
- private void RedrawActorIntern( int actorId, string actorName, Redraw settings )
+ private void RedrawActorIntern( int actorId, string actorName, RedrawType settings )
{
if( _actorIds.Contains( ( actorId, actorName, settings ) ) )
{
@@ -297,7 +288,7 @@ namespace Penumbra.Interop
}
}
- public void RedrawActor( Actor? actor, Redraw settings = Redraw.WithSettings )
+ public void RedrawActor( Actor? actor, RedrawType settings = RedrawType.WithSettings )
{
if( actor != null )
{
@@ -330,10 +321,10 @@ namespace Penumbra.Interop
};
}
- public void RedrawActor( string name, Redraw settings = Redraw.WithSettings )
+ public void RedrawActor( string name, RedrawType settings = RedrawType.WithSettings )
=> RedrawActor( GetName( name ), settings );
- public void RedrawAll( Redraw settings = Redraw.WithSettings )
+ public void RedrawAll( RedrawType settings = RedrawType.WithSettings )
{
Clear();
foreach( var actor in _pi.ClientState.Actors )
@@ -365,7 +356,7 @@ namespace Penumbra.Interop
Clear();
UnloadAll();
await Task.Delay( UnloadAllRedrawDelay );
- RedrawAll( Redraw.RedrawWithSettings );
+ RedrawAll( RedrawType.RedrawWithSettings );
}
public async void UnloadAtOnceRedrawWithoutSettings()
diff --git a/Penumbra/Penumbra.csproj b/Penumbra/Penumbra.csproj
index 3ea18e2a..1049ff78 100644
--- a/Penumbra/Penumbra.csproj
+++ b/Penumbra/Penumbra.csproj
@@ -74,6 +74,7 @@
+
diff --git a/Penumbra/Plugin.cs b/Penumbra/Plugin.cs
index 2ef25d7c..6e605c3e 100644
--- a/Penumbra/Plugin.cs
+++ b/Penumbra/Plugin.cs
@@ -2,7 +2,9 @@ using Dalamud.Game.Command;
using Dalamud.Plugin;
using EmbedIO;
using EmbedIO.WebApi;
-using Penumbra.API;
+using ImGuiNET;
+using Lumina.Excel.GeneratedSheets;
+using Penumbra.Api;
using Penumbra.Interop;
using Penumbra.Meta.Files;
using Penumbra.Mods;
@@ -32,6 +34,8 @@ namespace Penumbra
public MusicManager SoundShit { get; set; } = null!;
public ActorRefresher ActorRefresher { get; set; } = null!;
public IPlayerWatcher PlayerWatcher { get; set; } = null!;
+ public PenumbraApi Api { get; set; } = null!;
+
private WebServer? _webServer;
@@ -85,7 +89,28 @@ namespace Penumbra
PlayerWatcher.ActorChanged += a =>
{
PluginLog.Debug( "Triggered Redraw of {Actor}.", a.Name );
- ActorRefresher.RedrawActor( a, Redraw.OnlyWithSettings );
+ ActorRefresher.RedrawActor( a, RedrawType.OnlyWithSettings );
+ };
+
+ Api = new PenumbraApi( this );
+ SubscribeItemLinks();
+ }
+
+ private void SubscribeItemLinks()
+ {
+ Api.ChangedItemTooltip += it =>
+ {
+ if( it is Item )
+ {
+ ImGui.Text( "Left Click to create an item link in chat." );
+ }
+ };
+ Api.ChangedItemClicked += ( button, it ) =>
+ {
+ if( button == MouseButton.Left && it is Item item )
+ {
+ ChatUtil.LinkItem( item );
+ }
};
}
diff --git a/Penumbra/UI/MenuTabs/TabDebug.cs b/Penumbra/UI/MenuTabs/TabDebug.cs
index 0206f137..761f80f6 100644
--- a/Penumbra/UI/MenuTabs/TabDebug.cs
+++ b/Penumbra/UI/MenuTabs/TabDebug.cs
@@ -7,6 +7,7 @@ using System.Reflection;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Actors.Types;
using ImGuiNET;
+using Penumbra.Api;
using Penumbra.GameData;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
@@ -155,10 +156,10 @@ namespace Penumbra.UI
return;
}
- var queue = ( Queue< (int, string, Redraw) >? )_plugin.ActorRefresher.GetType()
+ var queue = ( Queue< (int, string, RedrawType) >? )_plugin.ActorRefresher.GetType()
.GetField( "_actorIds", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _plugin.ActorRefresher )
- ?? new Queue< (int, string, Redraw) >();
+ ?? new Queue< (int, string, RedrawType) >();
var currentFrame = ( int? )_plugin.ActorRefresher.GetType()
.GetField( "_currentFrame", BindingFlags.Instance | BindingFlags.NonPublic )
@@ -180,7 +181,7 @@ namespace Penumbra.UI
.GetField( "_currentActorStartState", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _plugin.ActorRefresher );
- var currentActorRedraw = ( Redraw? )_plugin.ActorRefresher.GetType()
+ var currentActorRedraw = ( RedrawType? )_plugin.ActorRefresher.GetType()
.GetField( "_currentActorRedraw", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _plugin.ActorRefresher );
diff --git a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetails.cs b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetails.cs
index 866e084d..99eaf40e 100644
--- a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetails.cs
+++ b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetails.cs
@@ -4,6 +4,7 @@ using System.Linq;
using Dalamud.Interface;
using ImGuiNET;
using Lumina.Excel.GeneratedSheets;
+using Penumbra.Api;
using Penumbra.GameData.Util;
using Penumbra.Meta;
using Penumbra.Mod;
@@ -178,21 +179,20 @@ namespace Penumbra.UI
{
foreach( var item in Mod.Data.ChangedItems )
{
- var ret = ImGui.Selectable( item.Key );
- var it = item.Value as Item;
- if( it == null )
+ var ret = ImGui.Selectable( item.Key ) ? MouseButton.Left : MouseButton.None;
+ ret = ImGui.IsItemClicked( ImGuiMouseButton.Right ) ? MouseButton.Right : ret;
+ ret = ImGui.IsItemClicked( ImGuiMouseButton.Middle ) ? MouseButton.Middle : ret;
+
+ if( ret != MouseButton.None )
{
- continue;
+ _base._plugin.Api.InvokeClick( ret, item.Value );
}
- if( ret )
+ if( _base._plugin.Api.HasTooltip && ImGui.IsItemHovered() )
{
- ChatUtil.LinkItem( it );
- }
-
- if( ImGui.IsItemHovered() )
- {
- ImGui.SetTooltip( "Left click to create link in chat." );
+ ImGui.BeginTooltip();
+ _base._plugin.Api.InvokeTooltip( item.Value );
+ ImGui.EndTooltip();
}
}
diff --git a/Penumbra/UI/MenuTabs/TabSettings.cs b/Penumbra/UI/MenuTabs/TabSettings.cs
index cf26c3c2..8aab2b1b 100644
--- a/Penumbra/UI/MenuTabs/TabSettings.cs
+++ b/Penumbra/UI/MenuTabs/TabSettings.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Text.RegularExpressions;
using Dalamud.Plugin;
using ImGuiNET;
+using Penumbra.Api;
using Penumbra.Interop;
using Penumbra.Mods;
using Penumbra.Util;
@@ -80,7 +81,7 @@ namespace Penumbra.UI
{
_config.IsEnabled = enabled;
_configChanged = true;
- _base._plugin.ActorRefresher.RedrawAll( enabled ? Redraw.WithSettings : Redraw.WithoutSettings );
+ _base._plugin.ActorRefresher.RedrawAll( enabled ? RedrawType.WithSettings : RedrawType.WithoutSettings );
if( _config.EnableActorWatch )
{
_base._plugin.PlayerWatcher.SetStatus( enabled );