fix: prevent vfx from spawning invisible

This commit is contained in:
Anna 2024-07-08 23:44:26 -04:00
parent 689984ee3e
commit 8d8cf0b99b
Signed by: anna
GPG Key ID: D0943384CD9F87D1
3 changed files with 89 additions and 37 deletions

View File

@ -1,3 +1,4 @@
using System.Numerics;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using ImGuiNET; using ImGuiNET;
using OrangeGuidanceTomestone.Ui; using OrangeGuidanceTomestone.Ui;
@ -102,11 +103,11 @@ public class PluginUi : IDisposable {
var label = msg.Id.ToString("N"); var label = msg.Id.ToString("N");
var size = ImGui.CalcTextSize(label); var size = ImGui.CalcTextSize(label);
ImGui.GetBackgroundDrawList().AddRectFilled( ImGui.GetBackgroundDrawList().AddRectFilled(
screen, screen - Vector2.One * 4 * ImGuiHelpers.GlobalScale,
screen + size, screen + size + Vector2.One * 4 * ImGuiHelpers.GlobalScale,
0xff000000 0xff000000
); );
ImGui.GetForegroundDrawList().AddText(screen, 0xffffffff, label); ImGui.GetBackgroundDrawList().AddText(screen, 0xffffffff, label);
} }
} }
} }

View File

@ -4,6 +4,7 @@ using Dalamud.Utility;
using ImGuiNET; using ImGuiNET;
using Lumina.Excel.GeneratedSheets; using Lumina.Excel.GeneratedSheets;
using OrangeGuidanceTomestone.Helpers; using OrangeGuidanceTomestone.Helpers;
using OrangeGuidanceTomestone.Util;
namespace OrangeGuidanceTomestone.Ui.MainWindowTabs; namespace OrangeGuidanceTomestone.Ui.MainWindowTabs;
@ -21,6 +22,7 @@ internal class Settings : ITab {
private IReadOnlyList<(string, DrawSettingsDelegate)> Tabs { get; } private IReadOnlyList<(string, DrawSettingsDelegate)> Tabs { get; }
private string _filter = string.Empty; private string _filter = string.Empty;
private string _debugFilter = string.Empty;
internal Settings(Plugin plugin) { internal Settings(Plugin plugin) {
this.Plugin = plugin; this.Plugin = plugin;
@ -230,6 +232,47 @@ internal class Settings : ITab {
private void DrawDebug(ref bool anyChanged, ref bool vfx) { private void DrawDebug(ref bool anyChanged, ref bool vfx) {
ImGui.Checkbox("Show debug information", ref this.Plugin.Ui.Debug); ImGui.Checkbox("Show debug information", ref this.Plugin.Ui.Debug);
ImGui.InputText("Filter", ref this._debugFilter, 64);
if (ImGui.BeginTable("###debug-info", 2)) {
using var endTable = new OnDispose(ImGui.EndTable);
ImGui.TableSetupColumn("ID", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableSetupColumn("VFX pointer");
ImGui.TableHeadersRow();
using var guard = this.Plugin.Vfx.Mutex.With();
foreach (var (id, ptr) in this.Plugin.Vfx.Spawned) {
var idLabel = id.ToString("N");
var ptrLabel = ptr.ToString("X");
if (!string.IsNullOrWhiteSpace(this._debugFilter)) {
if (
!idLabel.Contains(this._debugFilter, StringComparison.CurrentCultureIgnoreCase)
&& !ptrLabel.Contains(this._debugFilter, StringComparison.CurrentCultureIgnoreCase)
) {
continue;
}
}
ImGui.TableNextRow();
if (ImGui.TableSetColumnIndex(0)) {
ImGui.TextUnformatted(id.ToString("N"));
if (ImGui.IsItemClicked()) {
ImGui.SetClipboardText(id.ToString("N"));
}
}
if (ImGui.TableSetColumnIndex(1)) {
ImGui.TextUnformatted(ptr.ToString("X"));
if (ImGui.IsItemClicked()) {
ImGui.SetClipboardText(ptr.ToString("X"));
}
}
}
}
} }
private void ExtraCodeInput() { private void ExtraCodeInput() {

View File

@ -1,3 +1,4 @@
using System.Diagnostics;
using System.Numerics; using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@ -21,15 +22,11 @@ internal unsafe class Vfx : IDisposable {
private readonly delegate* unmanaged<VfxStruct*, nint> _staticVfxRemove; private readonly delegate* unmanaged<VfxStruct*, nint> _staticVfxRemove;
private Plugin Plugin { get; } private Plugin Plugin { get; }
private SemaphoreSlim Mutex { get; } = new(1, 1); internal SemaphoreSlim Mutex { get; } = new(1, 1);
private Dictionary<Guid, nint> Spawned { get; } = []; internal Dictionary<Guid, nint> Spawned { get; } = [];
private Queue<IQueueAction> Queue { get; } = []; private Queue<IQueueAction> Queue { get; } = [];
private bool _disposed; private bool _disposed;
private readonly Stopwatch _queueTimer = Stopwatch.StartNew();
private enum Mode {
Add,
Remove,
}
internal Vfx(Plugin plugin) { internal Vfx(Plugin plugin) {
this.Plugin = plugin; this.Plugin = plugin;
@ -49,39 +46,44 @@ internal unsafe class Vfx : IDisposable {
} }
private void HandleQueues(IFramework framework) { private void HandleQueues(IFramework framework) {
if (!this.Queue.TryDequeue(out var action)) { this._queueTimer.Restart();
return;
}
switch (action) { while (this._queueTimer.Elapsed < TimeSpan.FromMilliseconds(1)) {
case AddQueueAction add: { if (!this.Queue.TryDequeue(out var action)) {
using var guard = this.Mutex.With(); return;
Plugin.Log.Debug($"adding vfx for {add.Id}");
if (this.Spawned.Remove(add.Id, out var existing)) {
Plugin.Log.Warning($"vfx for {add.Id} already exists, queuing remove");
this.Queue.Enqueue(new RemoveRawQueueAction(existing));
}
var vfx = this.SpawnStatic(add.Id, add.Path, add.Position, add.Rotation);
this.Spawned[add.Id] = (nint) vfx;
break;
} }
case RemoveQueueAction remove: { switch (action) {
using var guard = this.Mutex.With(); case AddQueueAction add: {
Plugin.Log.Debug($"removing vfx for {remove.Id}"); using var guard = this.Mutex.With();
if (!this.Spawned.Remove(remove.Id, out var ptr)) { Plugin.Log.Debug($"adding vfx for {add.Id}");
if (this.Spawned.Remove(add.Id, out var existing)) {
Plugin.Log.Warning($"vfx for {add.Id} already exists, queuing remove");
this.Queue.Enqueue(new RemoveRawQueueAction(existing));
}
var vfx = this.SpawnStatic(add.Path, add.Position, add.Rotation);
this.Spawned[add.Id] = (nint) vfx;
break; break;
} }
this.RemoveStatic((VfxStruct*) ptr); case RemoveQueueAction remove: {
break; using var guard = this.Mutex.With();
}; Plugin.Log.Debug($"removing vfx for {remove.Id}");
if (!this.Spawned.Remove(remove.Id, out var ptr)) {
break;
}
case RemoveRawQueueAction remove: { this.RemoveStatic((VfxStruct*) ptr);
Plugin.Log.Debug($"removing raw vfx at {remove.Pointer:X}"); break;
this.RemoveStatic((VfxStruct*) remove.Pointer); }
break; ;
case RemoveRawQueueAction remove: {
Plugin.Log.Debug($"removing raw vfx at {remove.Pointer:X}");
this.RemoveStatic((VfxStruct*) remove.Pointer);
break;
}
} }
} }
} }
@ -114,7 +116,7 @@ internal unsafe class Vfx : IDisposable {
} }
} }
private VfxStruct* SpawnStatic(Guid id, string path, Vector3 pos, Quaternion rotation) { private VfxStruct* SpawnStatic(string path, Vector3 pos, Quaternion rotation) {
VfxStruct* vfx; VfxStruct* vfx;
fixed (byte* p = Encoding.UTF8.GetBytes(path).NullTerminate()) { fixed (byte* p = Encoding.UTF8.GetBytes(path).NullTerminate()) {
fixed (byte* pool = Pool) { fixed (byte* pool = Pool) {
@ -131,6 +133,9 @@ internal unsafe class Vfx : IDisposable {
// update rotation // update rotation
vfx->Rotation = new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W); vfx->Rotation = new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W);
// remove flag that sometimes causes vfx to not appear?
vfx->SomeFlags &= 0xF7;
// update // update
vfx->Flags |= 2; vfx->Flags |= 2;
@ -168,6 +173,9 @@ internal unsafe class Vfx : IDisposable {
[FieldOffset(0x1C0)] [FieldOffset(0x1C0)]
public int StaticTarget; public int StaticTarget;
[FieldOffset(0x248)]
public byte SomeFlags;
} }
} }