From 2b46397e8ec3fa6a33bf8e48e45d2e305aefd8ca Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 26 Jul 2021 15:56:09 +0200 Subject: [PATCH] Create a interface for a basic API to use the ActorRefresh and register actions to clicks on changed items (for now). --- Penumbra.Api/IPenumbraApi.cs | 32 +++++++++ Penumbra.Api/Penumbra.Api.csproj | 41 +++++++++++ Penumbra.Api/RedrawType.cs | 12 ++++ Penumbra.sln | 6 ++ Penumbra/API/ModsController.cs | 2 +- Penumbra/Api/PenumbraApi.cs | 72 +++++++++++++++++++ Penumbra/Interop/ActorRefresher.cs | 41 +++++------ Penumbra/Penumbra.csproj | 1 + Penumbra/Plugin.cs | 29 +++++++- Penumbra/UI/MenuTabs/TabDebug.cs | 7 +- .../TabInstalled/TabInstalledDetails.cs | 22 +++--- Penumbra/UI/MenuTabs/TabSettings.cs | 3 +- 12 files changed, 225 insertions(+), 43 deletions(-) create mode 100644 Penumbra.Api/IPenumbraApi.cs create mode 100644 Penumbra.Api/Penumbra.Api.csproj create mode 100644 Penumbra.Api/RedrawType.cs create mode 100644 Penumbra/Api/PenumbraApi.cs 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 );