Skip to content

Commit

Permalink
It hurts
Browse files Browse the repository at this point in the history
  • Loading branch information
Kurochi51 committed Jan 28, 2024
1 parent 303b076 commit 235d986
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 30 deletions.
173 changes: 169 additions & 4 deletions TickTracker/Helpers/NativeUi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
using Dalamud.Interface;
using FFXIVClientStructs.FFXIV.Component.GUI;
using FFXIVClientStructs.FFXIV.Client.System.Memory;
using TickTracker.Windows;
using Dalamud.Plugin.Services;
using Lumina.Data.Files;
using System.Linq;

namespace TickTracker.Helpers;

Expand All @@ -12,7 +16,18 @@ public static unsafe class NativeUi
{
private static readonly Dictionary<string, uint> NodeIds = new(StringComparer.Ordinal);
private static readonly Dictionary<uint, string> NodeNames = new();
private static Dictionary<uint, string> TextureDictionary = new();
private static uint NodeIdBase = 0x5469636B;
private static int CurrentNodePartsListAmount = 0;

private static IDataManager? DataManager;
private static IPluginLog Log = null!;

public static void InitServices(IDataManager _dataManager, IPluginLog _log)
{
DataManager = _dataManager;
Log = _log;
}

public static uint Get(string name, int index = 0)
{
Expand Down Expand Up @@ -82,12 +97,162 @@ public static void FreeImageComponents(ref AtkImageNode* imageNode)
{
IMemorySpace.Free(imageNode->PartsList->Parts->UldAsset, (ulong)(sizeof(AtkUldAsset) * imageNode->PartsList->PartCount));
IMemorySpace.Free(imageNode->PartsList->Parts, (ulong)(sizeof(AtkUldPart) * imageNode->PartsList->PartCount));
IMemorySpace.Free(imageNode->PartsList, (ulong)sizeof(AtkUldPartsList));
IMemorySpace.Free(imageNode->PartsList, (ulong)(sizeof(AtkUldPartsList)* CurrentNodePartsListAmount));
imageNode->AtkResNode.Destroy(false);
IMemorySpace.Free(imageNode, (ulong)sizeof(AtkImageNode));
}

private static AtkUldPartsList* CreateAtkUldPartsList(UldWrapper uld, int partListIndex, string texturePath)
private static void PopulateTextureDictionary(UldFile uldFile)
{
if (DataManager is null)
{
return;
}
TextureDictionary.Clear();
for (var i = 0; i < uldFile.AssetData.Length; i++)
{
var rawTexturePath = uldFile.AssetData[i].Path;
if (rawTexturePath is null)
{
DevWindow.Print($"{rawTexturePath} was skipped");
continue;
}

var textureId = uldFile.AssetData[i].Id;
var texturePath = new string(rawTexturePath, 0, rawTexturePath.Length).Trim('\0').Trim();
var hqTexturePath = texturePath.Replace(".tex", "_hr1.tex");

if (DataManager.FileExists(hqTexturePath))
{
TextureDictionary.Add(textureId, hqTexturePath);
}
else if (DataManager.FileExists(texturePath))
{
TextureDictionary.Add(textureId, texturePath);
}
}
}

private static void ParseUldFile(UldFile uld, out int uldPartsListAmount, out uint uldPartAmount)
{
uldPartsListAmount = uld.Parts.Length;
uldPartAmount = 0;
for (var i = 0; i < uldPartsListAmount; i++)
{
var currentPartList = uld.Parts[i];
uldPartAmount += currentPartList.PartCount;
}
}

private static AtkUldPartsList* CreateCompleteAtkUldPartsList(UldWrapper uld)

Check warning on line 147 in TickTracker/Helpers/NativeUi.cs

View workflow job for this annotation

GitHub Actions / build

Method is too long (81 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)

Check warning on line 147 in TickTracker/Helpers/NativeUi.cs

View workflow job for this annotation

GitHub Actions / build

Method is too long (81 lines; maximum allowed: 60) (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md)
{
if (!uld.Valid || uld.Uld is null)
{
return null;
}
var uldFile = uld.Uld;
ParseUldFile(uldFile, out var uldPartsListAmount, out var uldPartAmount);
CurrentNodePartsListAmount = uldPartsListAmount;
PopulateTextureDictionary(uldFile);
if (TextureDictionary.Count is 0)
{
return null;
}

var atkPartsList = (AtkUldPartsList*)IMemorySpace.GetUISpace()->Malloc((ulong)(sizeof(AtkUldPartsList) * uldPartsListAmount), 8);
if (atkPartsList is null)
{
return null;
}
for (var i = 0; i < uldPartsListAmount; i++)
{
atkPartsList[i].Id = uldFile.Parts[i].Id;
atkPartsList[i].PartCount = uldFile.Parts[i].PartCount;
}

var atkUldPart = (AtkUldPart*)IMemorySpace.GetUISpace()->Malloc((ulong)(sizeof(AtkUldPart) * uldPartAmount), 8);
if (atkUldPart is null)
{
IMemorySpace.Free(atkPartsList, (ulong)(sizeof(AtkUldPartsList) * uldPartsListAmount));
return null;
}
for (var i = 0; i < uldPartsListAmount; i++)
{
for (var j = 0; j < atkPartsList[i].PartCount; j++)
{
// j + i uld part?
var currentUldPart = uldFile.Parts[i].Parts[j];
atkUldPart[j].U = currentUldPart.U;
atkUldPart[j].V = currentUldPart.V;
atkUldPart[j].Width = currentUldPart.W;
atkUldPart[j].Height = currentUldPart.H;
}
atkPartsList[i].Parts = atkUldPart;
}

var atkUldAsset = (AtkUldAsset*)IMemorySpace.GetUISpace()->Malloc((ulong)(sizeof(AtkUldAsset) * uldPartAmount), 8);
if (atkUldAsset is null)
{
IMemorySpace.Free(atkUldPart, (ulong)(sizeof(AtkUldPart) * uldPartAmount));
IMemorySpace.Free(atkPartsList, (ulong)(sizeof(AtkUldPartsList) * uldPartsListAmount));
return null;
}
for (var i = 0; i < uldPartsListAmount; i++)
{
var currentPartsList = &atkPartsList[i];
var currentUldPartsList = uldFile.Parts[i];
for (var j = 0; j < currentPartsList->PartCount; j++)
{
var currentPart = &currentPartsList->Parts[j];
var currentUldPart = currentUldPartsList.Parts[j];
atkUldAsset[j].Id = currentUldPart.TextureId;
atkUldAsset[j].AtkTexture.Ctor();
if (TextureDictionary.ContainsKey(atkUldAsset[j].Id))
{
var texturePath = TextureDictionary[atkUldAsset[j].Id];
Log.Debug("Loading texture {path}", texturePath);
atkUldAsset[j].AtkTexture.LoadTexture(texturePath);
}
currentPart->UldAsset = &atkUldAsset[j];
}
}

if (atkPartsList is null)
{
IMemorySpace.Free(atkUldAsset, (ulong)(sizeof(AtkUldAsset) * uldPartAmount));
IMemorySpace.Free(atkUldPart, (ulong)(sizeof(AtkUldPart) * uldPartAmount));
IMemorySpace.Free(atkPartsList, (ulong)(sizeof(AtkUldPartsList) * uldPartsListAmount));
return null;
}

return atkPartsList;
}

public static AtkImageNode* CreateCompleteImageNode(UldWrapper uld, uint ImageNodeID, AtkComponentNode* parent, AtkResNode* targetNode, bool visibility)
{
var imageNode = IMemorySpace.GetUISpace()->Create<AtkImageNode>();
if (imageNode is null)
{
return null;
}
var atkPartList = CreateCompleteAtkUldPartsList(uld);
imageNode->AtkResNode.Type = NodeType.Image;
imageNode->AtkResNode.NodeID = ImageNodeID;
imageNode->PartsList = atkPartList;
imageNode->PartId = 0;
imageNode->AtkResNode.NodeFlags = NodeFlags.AnchorTop | NodeFlags.AnchorLeft | NodeFlags.Enabled | NodeFlags.Visible | NodeFlags.EmitsEvents;
imageNode->AtkResNode.DrawFlags |= 1;
imageNode->WrapMode = 1;
imageNode->Flags = 0;
imageNode->AtkResNode.SetWidth(160);
imageNode->AtkResNode.SetHeight(20);
imageNode->AtkResNode.SetScale(1, 1);
imageNode->AtkResNode.ToggleVisibility(visibility);
LinkNodeAfterTargetNode(&imageNode->AtkResNode, parent, targetNode);
return imageNode;
}

private static AtkUldPartsList* CreateAtkUldPartsList(UldWrapper uld, int partListIndex)
{
if (!uld.Valid || uld.Uld is null)
{
Expand Down Expand Up @@ -134,7 +299,7 @@ public static void FreeImageComponents(ref AtkImageNode* imageNode)
atkUldAsset[i].AtkTexture.Ctor();
// Technically not a proper call, because the texturePath is blindly passed here
// Different parts can belong to different textures
atkUldAsset[i].AtkTexture.LoadTexture(texturePath);
//atkUldAsset[i].AtkTexture.LoadTexture(texturePath);
atkPartsList->Parts[i].UldAsset = &atkUldAsset[i];
}

Expand All @@ -148,7 +313,7 @@ public static void FreeImageComponents(ref AtkImageNode* imageNode)
{
return null;
}
var atkPartList = CreateAtkUldPartsList(uld, partListIndex, texturePath);
var atkPartList = CreateAtkUldPartsList(uld, partListIndex);
if (atkPartList is null)
{
IMemorySpace.Free(imageNode, (ulong)sizeof(AtkImageNode));
Expand Down
1 change: 1 addition & 0 deletions TickTracker/Helpers/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Dalamud.Interface.Windowing;
using TickTracker.Enums;
using TickTracker.Windows;
using Lumina.Data.Files;

namespace TickTracker.Helpers;

Expand Down
39 changes: 14 additions & 25 deletions TickTracker/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
using Dalamud.Game.ClientState.Objects.SubKinds;
using TickTracker.Windows;
using TickTracker.Helpers;
using static Lumina.Data.Parsing.Uld.NodeData;

namespace TickTracker;

Expand Down Expand Up @@ -88,6 +87,8 @@ public sealed class Plugin : IDalamudPlugin
private const float RegularTickInterval = 3, FastTickInterval = 1.5f;
private const uint DiscipleOfTheLand = 32, PugilistId = 2, LancerId = 4, ArcherId = 5, HPGaugeNodeId = 3, MPGaugeNodeId = 4, ParamFrameImageNode = 4;
private const byte NonCombatJob = 0, MeleeDPS = 3, PhysRangedDPS = 4;
private const string ParamWidgetUldPath = "ui/uld/parameter.uld";
private const string GatchaUldPath = "ui/uld/Gacha.uld";

private readonly List<BarWindowBase> barWindows;
private readonly uint mpTickerImageID = NativeUi.Get("TickerImageMP");
Expand All @@ -100,7 +101,6 @@ public sealed class Plugin : IDalamudPlugin
private Task? loadingTask;
private unsafe AtkUnitBase* NameplateAddon => (AtkUnitBase*)gameGui.GetAddonByName("NamePlate");
private unsafe AtkUnitBase* ParamWidget => (AtkUnitBase*)gameGui.GetAddonByName("_ParameterWidget");
private unsafe AtkUnitBase* ContentFinderAddon => (AtkUnitBase*)gameGui.GetAddonByName("ContentsFinder");
private unsafe AtkImageNode* hpTicker, mpTicker;

public Plugin(DalamudPluginInterface _pluginInterface,
Expand Down Expand Up @@ -135,6 +135,8 @@ public Plugin(DalamudPluginInterface _pluginInterface,
}
receiveActorUpdateHook.Enable();

NativeUi.InitServices(_dataManager, log);

config = pluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
utilities = new Utilities(pluginInterface, config, condition, _dataManager, clientState, log);

Expand Down Expand Up @@ -502,33 +504,14 @@ private unsafe void DevWindowThings(PlayerCharacter? player, double currentTime,
DevWindow.Print("Fast Value: " + fastValue.ToString(cultureFormat));
DevWindow.Print("Swapchain resolution: " + Resolution.X.ToString(cultureFormat) + "x" + Resolution.Y.ToString(cultureFormat));

var randomUld = pluginInterface.UiBuilder.LoadUld("ui/uld/Gacha.uld");
if (randomUld.Valid)
{
var uld = randomUld.Uld;
var partListCount = uld.Parts.Length;
var path = uld.FilePath.Path;
DevWindow.Print(path);
DevWindow.Print($"Gacha amount of PartLists? {partListCount}");
for (var i = 0; i < partListCount; i++)
{
var currentPartList = uld.Parts[i];
DevWindow.Print($"PartList {i} has {currentPartList.PartCount} parts");
for (var j = 0; j < currentPartList.PartCount; j++)
{
var currentPart = currentPartList.Parts[j];
DevWindow.Print($"Part texture id {currentPart.TextureId}");
}
}
}

if (!utilities.IsAddonReady(ParamWidget))
{
return;
}
var frameImageNode = NativeUi.GetNodeByID<AtkImageNode>(&ParamWidget->GetNodeById(HPGaugeNodeId)->GetComponent()->UldManager, mpTickerImageID);
var frameImageNode = NativeUi.GetNodeByID<AtkImageNode>(&ParamWidget->GetNodeById(MPGaugeNodeId)->GetComponent()->UldManager, mpTickerImageID);
if (frameImageNode is null)
{
DevWindow.Print("Image Node is... null?");
return;
}
DevWindow.Print($"NodeId: {frameImageNode->AtkResNode.NodeID}\n" +
Expand Down Expand Up @@ -619,6 +602,7 @@ private unsafe void HandleNativeNode(uint gaugeBarNodeId, uint frameImageId, uin
tickerNode->AtkResNode.MultiplyBlue = (byte)(255 * Color.Z);
tickerNode->AtkResNode.SetAlpha((byte)(255 * Color.W));
tickerNode->AtkResNode.ToggleVisibility(visibility);
tickerNode->PartId = (ushort)DevWindow.partId;

Check failure on line 605 in TickTracker/Plugin.cs

View workflow job for this annotation

GitHub Actions / build

An object reference is required for the non-static field, method, or property 'DevWindow.partId'

Check failure on line 605 in TickTracker/Plugin.cs

View workflow job for this annotation

GitHub Actions / build

An object reference is required for the non-static field, method, or property 'DevWindow.partId'
return;
}
var gaugeBarNode = ParamWidget->GetNodeById(gaugeBarNodeId);
Expand All @@ -644,14 +628,19 @@ private unsafe void HandleNativeNode(uint gaugeBarNodeId, uint frameImageId, uin

if (tickerNode is null && !failed)
{
tickerNode = NativeUi.CreateImageNode(pluginInterface.UiBuilder.LoadUld("ui/uld/parameter.uld"),
tickerNode = NativeUi.CreateCompleteImageNode(pluginInterface.UiBuilder.LoadUld(GatchaUldPath),
tickerImageId,
gaugeBarNode->GetAsAtkComponentNode(),
(AtkResNode*)frameImageNode,
visibility);
/*tickerNode = NativeUi.CreateImageNode(pluginInterface.UiBuilder.LoadUld("ui/uld/parameter.uld"),
0,
tickerImageId,
"ui/uld/Parameter_Gauge_hr1.tex",
0,
gaugeBarNode->GetAsAtkComponentNode(),
(AtkResNode*)frameImageNode,
visibility);
visibility);*/
if (tickerNode is null)
{
failed = true;
Expand Down
5 changes: 4 additions & 1 deletion TickTracker/Windows/DevWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public sealed class DevWindow : Window
{
private static readonly List<string> PrintLines = new();
public int partId;
public int partListIndex;

public DevWindow() : base("DevWindow")
{
Expand All @@ -28,11 +29,13 @@ public override void Draw()
ImGui.TextUnformatted(line);
}
PrintLines.Clear();
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X / 2);
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X / 3);
if (ImGui.InputInt("ImageNode PartId", ref partId, 1))
{
partId = Math.Clamp(partId, 0, 6);
}
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X / 3);
ImGui.InputInt("ImageNode PartsList Index", ref partListIndex, 1);
}

public static void Print(string text)
Expand Down

0 comments on commit 235d986

Please sign in to comment.