From 9415725a4442a8f85a5b6b0d2a577f40604078d0 Mon Sep 17 00:00:00 2001 From: Anna Date: Thu, 11 Mar 2021 14:14:34 -0500 Subject: [PATCH] feat: add element options and fix ctd Prevent changing layouts while the Character Configuration window is open. Also fix visibility to show both keyboard and gamepad checkboxes. --- HUD Manager/Configuration/Config.cs | 2 +- HUD Manager/Configuration/Migrator.cs | 66 ++++- HUD Manager/Hud.cs | 53 ++-- HUD Manager/PluginUi.cs | 229 ++++++++++++++---- HUD Manager/Structs/ElementKind.cs | 50 ++++ HUD Manager/Structs/Options/GaugeOptions.cs | 19 ++ HUD Manager/Structs/Options/HotbarOptions.cs | 28 +++ HUD Manager/Structs/Options/StatusOptions.cs | 116 +++++++++ .../Structs/Options/TargetBarOptions.cs | 14 ++ HUD Manager/Structs/RawElement.cs | 39 ++- HUD Manager/Structs/Visibility.cs | 6 - HUD Manager/Structs/VisibilityBits.cs | 9 + 12 files changed, 547 insertions(+), 84 deletions(-) create mode 100755 HUD Manager/Structs/Options/GaugeOptions.cs create mode 100755 HUD Manager/Structs/Options/HotbarOptions.cs create mode 100755 HUD Manager/Structs/Options/StatusOptions.cs create mode 100755 HUD Manager/Structs/Options/TargetBarOptions.cs delete mode 100755 HUD Manager/Structs/Visibility.cs create mode 100755 HUD Manager/Structs/VisibilityBits.cs diff --git a/HUD Manager/Configuration/Config.cs b/HUD Manager/Configuration/Config.cs index 2a61ac8..a53654a 100644 --- a/HUD Manager/Configuration/Config.cs +++ b/HUD Manager/Configuration/Config.cs @@ -6,7 +6,7 @@ using Dalamud.Plugin; namespace HUD_Manager.Configuration { [Serializable] public class Config : IPluginConfiguration { - public int Version { get; set; } = 2; + public int Version { get; set; } = 3; private DalamudPluginInterface Interface { get; set; } = null!; diff --git a/HUD Manager/Configuration/Migrator.cs b/HUD Manager/Configuration/Migrator.cs index e51722a..8e65bfd 100755 --- a/HUD Manager/Configuration/Migrator.cs +++ b/HUD Manager/Configuration/Migrator.cs @@ -31,6 +31,43 @@ namespace HUD_Manager.Configuration { return config; } + private static Config MigrateV2(JObject old) { + foreach (var property in old["Layouts"].Children()) { + if (property.Name == "$type") { + continue; + } + + var layout = (JObject) property.Value; + var elements = (JObject) layout["Elements"]; + + foreach (var elementProp in elements.Children()) { + if (elementProp.Name == "$type") { + continue; + } + + var element = (JObject) elementProp.Value; + var bytes = element["Unknown4"].ToObject(); + + var options = new byte[4]; + Buffer.BlockCopy(bytes, 0, options, 0, 4); + + var width = BitConverter.ToUInt16(bytes, 4); + var height = BitConverter.ToUInt16(bytes, 6); + var unknown4 = bytes[8]; + + element.Remove("Unknown4"); + element["Options"] = options; + element["Width"] = width; + element["Height"] = height; + element["Unknown4"] = unknown4; + } + } + + old["Version"] = 3; + + return old.ToObject(); + } + private static string PluginConfig(string? pluginName = null) { pluginName ??= Assembly.GetAssembly(typeof(Plugin)).GetName().Name; return Path.Combine(new[] { @@ -44,27 +81,40 @@ namespace HUD_Manager.Configuration { public static Config LoadConfig(Plugin plugin) { var managerPath = PluginConfig(); + string? text = null; if (File.Exists(managerPath)) { - goto DefaultConfig; + text = File.ReadAllText(managerPath); + goto CheckVersion; } var hudSwapPath = PluginConfig("HudSwap"); if (File.Exists(hudSwapPath)) { - var oldText = File.ReadAllText(hudSwapPath); - var config = JsonConvert.DeserializeObject(oldText); - uint version = 1; - if (config.TryGetValue("Version", out var token)) { - version = token.Value(); - } + text = File.ReadAllText(hudSwapPath); + } - if (version == 1) { + CheckVersion: + if (text == null) { + goto DefaultConfig; + } + + var config = JsonConvert.DeserializeObject(text); + uint version = 1; + if (config.TryGetValue("Version", out var token)) { + version = token.Value(); + } + + switch (version) { + case 1: { var v1 = config.ToObject(new JsonSerializer { TypeNameHandling = TypeNameHandling.None, }); return Migrate(v1); } + case 2: { + return MigrateV2(config); + } } DefaultConfig: diff --git a/HUD Manager/Hud.cs b/HUD Manager/Hud.cs index 05479ca..dbcb8d2 100644 --- a/HUD Manager/Hud.cs +++ b/HUD Manager/Hud.cs @@ -11,9 +11,11 @@ namespace HUD_Manager { public class Hud { // Updated 5.45 public const int InMemoryLayoutElements = 81; + // Updated 5.45 // Each element is 32 bytes in ADDON.DAT, but they're 36 bytes when loaded into memory. private const int LayoutSize = InMemoryLayoutElements * 36; + // Updated 5.4 private const int SlotOffset = 0x59e8; @@ -54,27 +56,32 @@ namespace HUD_Manager { goto Return; } - var currentSlotPtr = this.GetDataPointer() + SlotOffset; - // read the current slot - var currentSlot = (uint) Marshal.ReadInt32(currentSlotPtr); - // change it to a different slot - if (currentSlot == (uint) slot) { - if (currentSlot < 3) { - currentSlot += 1; - } else { - currentSlot = 0; - } + unsafe { + var currentSlotPtr = (uint*) (this.GetDataPointer() + SlotOffset); + // read the current slot + var currentSlot = *currentSlotPtr; + // if the current slot is the slot we want to change to, we can force a reload by + // telling the game it's on a different slot and swapping back to the desired slot + if (currentSlot == (uint) slot) { + var backupSlot = currentSlot; + if (backupSlot < 3) { + backupSlot += 1; + } else { + backupSlot = 0; + } - // back up this different slot - var backup = this.ReadLayout((HudSlot) currentSlot); - // change the current slot in memory - Marshal.WriteInt32(currentSlotPtr, (int) currentSlot); - // ask the game to change slot to our desired slot - // for some reason, this overwrites the current slot, so this is why we back up - this._setHudLayout.Invoke(file, (uint) slot, 0, 1); - // restore the backup - this.WriteLayout((HudSlot) currentSlot, backup); - return; + // back up this different slot + var backup = this.ReadLayout((HudSlot) backupSlot); + // change the current slot in memory + *currentSlotPtr = backupSlot; + + // ask the game to change slot to our desired slot + // for some reason, this overwrites the current slot, so this is why we back up + this._setHudLayout.Invoke(file, (uint) slot, 0, 1); + // restore the backup + this.WriteLayout((HudSlot) backupSlot, backup, false); + return; + } } Return: @@ -106,7 +113,7 @@ namespace HUD_Manager { return Marshal.PtrToStructure(slotPtr); } - private void WriteLayout(HudSlot slot, Layout layout) { + private void WriteLayout(HudSlot slot, Layout layout, bool reloadIfNecessary = true) { var slotPtr = this.GetLayoutPointer(slot); var dict = layout.ToDictionary(); @@ -124,6 +131,10 @@ namespace HUD_Manager { // copy directly over // Marshal.StructureToPtr(layout, slotPtr, false); + if (!reloadIfNecessary) { + return; + } + var currentSlot = this.GetActiveHudSlot(); if (currentSlot == slot) { this.SelectSlot(currentSlot, true); diff --git a/HUD Manager/PluginUi.cs b/HUD Manager/PluginUi.cs index 9b9aa00..fa2fdbd 100644 --- a/HUD Manager/PluginUi.cs +++ b/HUD Manager/PluginUi.cs @@ -7,6 +7,7 @@ using Dalamud.Interface; using Dalamud.Plugin; using HUD_Manager.Configuration; using HUD_Manager.Structs; +using HUD_Manager.Structs.Options; using HUD_Manager.Tree; using ImGuiNET; using Lumina.Excel.GeneratedSheets; @@ -38,19 +39,6 @@ namespace HUD_Manager { 0.6f, }; - private static readonly string[] ScaleOptionsNames = { - "200%", - "180%", - "160%", - "140%", - "120%", - "110%", - "100%", - "90%", - "80%", - "60%", - }; - private Plugin Plugin { get; } private bool _settingsVisible; @@ -64,14 +52,11 @@ namespace HUD_Manager { private float _dragSpeed = 1.0f; private string? _importName; - private Guid _selectedLayoutId = Guid.Empty; private string? _newLayoutName; private string? _renameLayout; private Guid _selectedEditLayout = Guid.Empty; - private SavedLayout? SelectedSavedLayout => this._selectedLayoutId == Guid.Empty ? null : this.Plugin.Config.Layouts[this._selectedLayoutId]; - private int _editingConditionIndex = -1; private HudConditionMatch? _editingCondition; private bool _scrollToAdd; @@ -205,6 +190,12 @@ namespace HUD_Manager { goto EndTabItem; } + var charConfig = this.Plugin.Interface.Framework.Gui.GetAddonByName("ConfigCharacter", 1); + if (charConfig != null && charConfig.Visible) { + ImGui.TextUnformatted("Please close the Character Configuration window before continuing."); + goto EndTabItem; + } + var update = false; ImGui.TextUnformatted("Layout"); @@ -357,57 +348,181 @@ namespace HUD_Manager { if (ImGui.BeginChild("uimanager-layout-editor-elements", new Vector2(0, 0))) { var toRemove = new List(); - foreach (var entry in layout.Elements) { - var name = entry.Key.LocalisedName(this.Plugin.Interface.Data); - + var sortedElements = layout.Elements + .Select(entry => Tuple.Create(entry.Key, entry.Value, entry.Key.LocalisedName(this.Plugin.Interface.Data))) + .OrderBy(tuple => tuple.Item3); + foreach (var (kind, element, name) in sortedElements) { if (this._editorSearch != null && !name.ContainsIgnoreCase(this._editorSearch)) { continue; } - ImGui.TextUnformatted(name); - - var element = entry.Value; - - var visible = element.Visibility == Visibility.Visible; - if (ImGui.Checkbox($"Visible##{entry.Key}", ref visible)) { - element.Visibility = visible ? Visibility.Visible : Visibility.Hidden; - update = true; + if (!ImGui.CollapsingHeader(name)) { + continue; } - ImGui.SameLine(); - if (IconButton(FontAwesomeIcon.TrashAlt, $"uimanager-remove-element-{entry.Key}")) { - toRemove.Add(entry.Key); + var drawVisibility = !kind.IsJobGauge(); + + void DrawDelete() { + ImGui.SameLine(ImGui.GetContentRegionAvail().X - 30); + if (IconButton(FontAwesomeIcon.TrashAlt, $"uimanager-remove-element-{kind}")) { + toRemove.Add(kind); + } + } + + if (drawVisibility) { + ImGui.TextUnformatted("Visibility"); + + DrawDelete(); + + var keyboard = element[VisibilityFlags.Keyboard]; + if (IconCheckbox(FontAwesomeIcon.Keyboard, ref keyboard, $"{kind}")) { + element[VisibilityFlags.Keyboard] = keyboard; + update = true; + } + + ImGui.SameLine(); + var gamepad = element[VisibilityFlags.Gamepad]; + if (IconCheckbox(FontAwesomeIcon.Gamepad, ref gamepad, $"{kind}")) { + element[VisibilityFlags.Gamepad] = gamepad; + update = true; + } } var x = element.X; - if (ImGui.DragFloat($"X##{entry.Key}", ref x, this._dragSpeed)) { + if (ImGui.DragFloat($"X##{kind}", ref x, this._dragSpeed)) { element.X = x; update = true; } + if (!drawVisibility) { + DrawDelete(); + } + var y = element.Y; - if (ImGui.DragFloat($"Y##{entry.Key}", ref y, this._dragSpeed)) { + if (ImGui.DragFloat($"Y##{kind}", ref y, this._dragSpeed)) { element.Y = y; update = true; } - var scaleIdx = Array.IndexOf(ScaleOptions, element.Scale); - if (scaleIdx == -1) { - scaleIdx = 6; + var currentScale = $"{element.Scale * 100}%"; + if (ImGui.BeginCombo($"Scale##{kind}", currentScale)) { + foreach (var scale in ScaleOptions) { + if (!ImGui.Selectable($"{scale * 100}%")) { + continue; + } + + element.Scale = scale; + update = true; + } + + ImGui.EndCombo(); } - if (ImGui.Combo($"Scale##{entry.Key}", ref scaleIdx, ScaleOptionsNames, ScaleOptionsNames.Length)) { - element.Scale = ScaleOptions[scaleIdx]; - update = true; + if (!kind.IsJobGauge()) { + var opacity = (int) element.Opacity; + if (ImGui.DragInt($"Opacity##{kind}", ref opacity, 1, 1, 255)) { + element.Opacity = (byte) opacity; + update = true; + } } - var opacity = (int) element.Opacity; - if (ImGui.DragInt($"Opacity##{entry.Key}", ref opacity, 1, 1, 255)) { - element.Opacity = (byte) opacity; - update = true; + if (kind == ElementKind.TargetBar) { + var targetBarOpts = new TargetBarOptions(element.Options); + + var independent = targetBarOpts.ShowIndependently; + if (ImGui.Checkbox("Display target information independently", ref independent)) { + targetBarOpts.ShowIndependently = independent; + update = true; + } } - ImGui.Separator(); + if (kind == ElementKind.StatusEffects) { + var statusOpts = new StatusOptions(element.Options); + + if (ImGui.BeginCombo($"Style##{kind}", statusOpts.Style.ToString())) { + foreach (var style in (StatusStyle[]) Enum.GetValues(typeof(StatusStyle))) { + if (!ImGui.Selectable($"{style}##{kind}")) { + continue; + } + + statusOpts.Style = style; + update = true; + } + + ImGui.EndCombo(); + } + } + + if (kind == ElementKind.StatusInfoEnhancements || kind == ElementKind.StatusInfoEnfeeblements || kind == ElementKind.StatusInfoOther) { + var statusOpts = new StatusInfoOptions(kind, element.Options); + + if (ImGui.BeginCombo($"Layout##{kind}", statusOpts.Layout.ToString())) { + foreach (var sLayout in (StatusLayout[]) Enum.GetValues(typeof(StatusLayout))) { + if (!ImGui.Selectable($"{sLayout}##{kind}")) { + continue; + } + + statusOpts.Layout = sLayout; + update = true; + } + + ImGui.EndCombo(); + } + + if (ImGui.BeginCombo($"Alignment##{kind}", statusOpts.Alignment.ToString())) { + foreach (var alignment in (StatusAlignment[]) Enum.GetValues(typeof(StatusAlignment))) { + if (!ImGui.Selectable($"{alignment}##{kind}")) { + continue; + } + + statusOpts.Alignment = alignment; + update = true; + } + + ImGui.EndCombo(); + } + + var focusable = statusOpts.Gamepad == StatusGamepad.Focusable; + if (ImGui.Checkbox($"Focusable by gamepad##{kind}", ref focusable)) { + statusOpts.Gamepad = focusable ? StatusGamepad.Focusable : StatusGamepad.NonFocusable; + update = true; + } + } + + if (kind.IsHotbar()) { + var hotbarOpts = new HotbarOptions(element.Options); + + if (kind != ElementKind.PetHotbar) { + var hotbarIndex = (int) hotbarOpts.Index; + if (ImGui.InputInt($"Hotbar number##{kind}", ref hotbarIndex)) { + hotbarOpts.Index = (byte) Math.Max(0, Math.Min(9, hotbarIndex)); + update = true; + } + } + + if (ImGui.BeginCombo($"Hotbar layout##{kind}", hotbarOpts.Layout.ToString())) { + foreach (var hotbarLayout in (HotbarLayout[]) Enum.GetValues(typeof(HotbarLayout))) { + if (!ImGui.Selectable($"{hotbarLayout}##{kind}")) { + continue; + } + + hotbarOpts.Layout = hotbarLayout; + update = true; + } + + ImGui.EndCombo(); + } + } + + if (kind.IsJobGauge()) { + var gaugeOpts = new GaugeOptions(element.Options); + + var simple = gaugeOpts.Style == GaugeStyle.Simple; + if (ImGui.Checkbox($"Simple##{kind}", ref simple)) { + gaugeOpts.Style = simple ? GaugeStyle.Simple : GaugeStyle.Normal; + update = true; + } + } } foreach (var remove in toRemove) { @@ -697,6 +812,19 @@ namespace HUD_Manager { } } + if (ImGui.Button("Print current slot")) { + var slot = this.Plugin.Hud.GetActiveHudSlot(); + this.Plugin.Interface.Framework.Gui.Chat.Print($"{slot}"); + } + + var current = this.Plugin.Hud.ReadLayout(this.Plugin.Hud.GetActiveHudSlot()); + foreach (var element in current.elements) { + ImGui.TextUnformatted(element.id.LocalisedName(this.Plugin.Interface.Data)); + ImGui.TextUnformatted($"Width: {element.width}"); + ImGui.TextUnformatted($"Height: {element.height}"); + ImGui.Separator(); + } + ImGui.EndTabItem(); } #endif @@ -911,6 +1039,21 @@ namespace HUD_Manager { return result; } + public static bool IconCheckbox(FontAwesomeIcon icon, ref bool value, string? id = null) { + ImGui.PushFont(UiBuilder.IconFont); + + var text = icon.ToIconString(); + if (id != null) { + text += $"##{id}"; + } + + var result = ImGui.Checkbox(text, ref value); + + ImGui.PopFont(); + + return result; + } + private static void HoverTooltip(string text) { if (!ImGui.IsItemHovered()) { return; diff --git a/HUD Manager/Structs/ElementKind.cs b/HUD Manager/Structs/ElementKind.cs index 6a3f250..c066a33 100755 --- a/HUD Manager/Structs/ElementKind.cs +++ b/HUD Manager/Structs/ElementKind.cs @@ -187,5 +187,55 @@ namespace HUD_Manager.Structs { return name; } + + public static bool IsJobGauge(this ElementKind kind) { + switch (kind) { + case ElementKind.AetherflowGaugeSch: + case ElementKind.AetherflowGaugeSmn: + case ElementKind.ArcanaGauge: + case ElementKind.BalanceGauge: + case ElementKind.BeastGauge: + case ElementKind.BloodGauge: + case ElementKind.ChakraGauge: + case ElementKind.DarksideGauge: + case ElementKind.DragonGauge: + case ElementKind.ElementalGauge: + case ElementKind.FaerieGauge: + case ElementKind.FourfoldFeathers: + case ElementKind.HealingGauge: + case ElementKind.HeatGauge: + case ElementKind.HutonGauge: + case ElementKind.KenkiGauge: + case ElementKind.NinkiGauge: + case ElementKind.OathGauge: + case ElementKind.PowderGauge: + case ElementKind.SenGauge: + case ElementKind.SongGauge: + case ElementKind.StepGauge: + case ElementKind.TranceGauge: + return true; + default: + return false; + } + } + + public static bool IsHotbar(this ElementKind kind) { + switch (kind) { + case ElementKind.Hotbar1: + case ElementKind.Hotbar2: + case ElementKind.Hotbar3: + case ElementKind.Hotbar4: + case ElementKind.Hotbar5: + case ElementKind.Hotbar6: + case ElementKind.Hotbar7: + case ElementKind.Hotbar8: + case ElementKind.Hotbar9: + case ElementKind.Hotbar10: + case ElementKind.PetHotbar: + return true; + default: + return false; + } + } } } diff --git a/HUD Manager/Structs/Options/GaugeOptions.cs b/HUD Manager/Structs/Options/GaugeOptions.cs new file mode 100755 index 0000000..4ce329d --- /dev/null +++ b/HUD Manager/Structs/Options/GaugeOptions.cs @@ -0,0 +1,19 @@ +namespace HUD_Manager.Structs.Options { + public class GaugeOptions { + private readonly byte[] _options; + + public GaugeStyle Style { + get => (GaugeStyle) this._options[0]; + set => this._options[0] = (byte) value; + } + + public GaugeOptions(byte[] options) { + this._options = options; + } + } + + public enum GaugeStyle : byte { + Normal = 0, + Simple = 1, + } +} diff --git a/HUD Manager/Structs/Options/HotbarOptions.cs b/HUD Manager/Structs/Options/HotbarOptions.cs new file mode 100755 index 0000000..91ecb27 --- /dev/null +++ b/HUD Manager/Structs/Options/HotbarOptions.cs @@ -0,0 +1,28 @@ +namespace HUD_Manager.Structs.Options { + public class HotbarOptions { + private readonly byte[] _options; + + public byte Index { + get => this._options[0]; + set => this._options[0] = value; + } + + public HotbarLayout Layout { + get => (HotbarLayout) this._options[1]; + set => this._options[1] = (byte) value; + } + + public HotbarOptions(byte[] options) { + this._options = options; + } + } + + public enum HotbarLayout : byte { + TwelveByOne = 1, + SixByTwo = 2, + FourByThree = 3, + ThreeByFour = 4, + TwoBySix = 5, + OneByTwelve = 6, + } +} diff --git a/HUD Manager/Structs/Options/StatusOptions.cs b/HUD Manager/Structs/Options/StatusOptions.cs new file mode 100755 index 0000000..a6414f7 --- /dev/null +++ b/HUD Manager/Structs/Options/StatusOptions.cs @@ -0,0 +1,116 @@ +using System; + +namespace HUD_Manager.Structs.Options { + public class StatusOptions { + private readonly byte[] _options; + + public StatusStyle Style { + get => (StatusStyle) this._options[0]; + set => this._options[0] = (byte) value; + } + + public StatusOptions(byte[] options) { + this._options = options; + } + } + + public enum StatusStyle : byte { + Normal = 1, + NormalLeftJustified1 = 11, + NormalLeftJustified2 = 21, + NormalLeftJustified3 = 31, + ThreeGroups = 0, + } + + public class StatusInfoOptions { + private const int GamepadBit = 1 << 4; + + private readonly ElementKind _kind; + private readonly byte[] _options; + + public StatusLayout Layout { + get => this.ExtractStyle().Item1; + set => this._options[0] = this.ComputeStyle(value, this.Alignment, this.Gamepad); + } + + public StatusAlignment Alignment { + get => this.ExtractStyle().Item2; + set => this._options[0] = this.ComputeStyle(this.Layout, value, this.Gamepad); + } + + public StatusGamepad Gamepad { + get => this.ExtractStyle().Item3; + set => this._options[0] = this.ComputeStyle(this.Layout, this.Alignment, value); + } + + public StatusInfoOptions(ElementKind kind, byte[] options) { + this._kind = kind; + this._options = options; + } + + private byte ComputeStyle(StatusLayout layout, StatusAlignment alignment, StatusGamepad gamepad) { + byte result = layout switch { + StatusLayout.TenByTwo => 0, + StatusLayout.TwentyByOne => 1, + StatusLayout.SevenByThree => 2, + StatusLayout.FiveByFour => 3, + _ => throw new ArgumentOutOfRangeException(nameof(layout), layout, null), + }; + + if (alignment == StatusAlignment.RightJustified) { + result += 4; + } + + if (this._kind != ElementKind.StatusInfoOther && gamepad == StatusGamepad.NonFocusable) { + result |= GamepadBit; + } + + if (this._kind == ElementKind.StatusInfoOther && gamepad == StatusGamepad.Focusable) { + result |= GamepadBit; + } + + return result; + } + + private Tuple ExtractStyle() { + var gamepadBitSet = (this._options[0] & GamepadBit) > 0; + var gamepad = this._kind == ElementKind.StatusInfoOther + ? gamepadBitSet + ? StatusGamepad.Focusable + : StatusGamepad.NonFocusable + : gamepadBitSet + ? StatusGamepad.NonFocusable + : StatusGamepad.Focusable; + var basic = this._options[0] & ~GamepadBit; + + var alignment = basic < 4 ? StatusAlignment.LeftJustified : StatusAlignment.RightJustified; + + var layout = (basic % 4) switch { + 0 => StatusLayout.TenByTwo, + 1 => StatusLayout.TwentyByOne, + 2 => StatusLayout.SevenByThree, + 3 => StatusLayout.FiveByFour, + _ => throw new ArgumentOutOfRangeException(), + }; + + return Tuple.Create(layout, alignment, gamepad); + } + } + + public enum StatusLayout { + TwentyByOne, + TenByTwo, + SevenByThree, + FiveByFour, + } + + public enum StatusAlignment { + LeftJustified, + RightJustified, + } + + public enum StatusGamepad { + Focusable, + NonFocusable, + } +} diff --git a/HUD Manager/Structs/Options/TargetBarOptions.cs b/HUD Manager/Structs/Options/TargetBarOptions.cs new file mode 100755 index 0000000..7efb614 --- /dev/null +++ b/HUD Manager/Structs/Options/TargetBarOptions.cs @@ -0,0 +1,14 @@ +namespace HUD_Manager.Structs.Options { + public class TargetBarOptions { + private readonly byte[] _options; + + public bool ShowIndependently { + get => this._options[0] == 1; + set => this._options[0] = value ? 1 : 0; + } + + public TargetBarOptions(byte[] options) { + this._options = options; + } + } +} diff --git a/HUD Manager/Structs/RawElement.cs b/HUD Manager/Structs/RawElement.cs index 6d26899..c6d0d00 100755 --- a/HUD Manager/Structs/RawElement.cs +++ b/HUD Manager/Structs/RawElement.cs @@ -11,10 +11,16 @@ namespace HUD_Manager.Structs { public float scale; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] - public byte[] unknown4; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] options; - public Visibility visibility; + public ushort width; + + public ushort height; + + public byte unknown4; + + public VisibilityFlags visibility; public byte unknown6; @@ -28,6 +34,9 @@ namespace HUD_Manager.Structs { this.x = element.X; this.y = element.Y; this.scale = element.Scale; + this.options = element.Options; + this.width = element.Width; + this.height = element.Height; this.unknown4 = element.Unknown4; this.visibility = element.Visibility; this.unknown6 = element.Unknown6; @@ -45,9 +54,15 @@ namespace HUD_Manager.Structs { public float Scale { get; set; } - public byte[] Unknown4 { get; set; } + public byte[] Options { get; set; } - public Visibility Visibility { get; set; } + public ushort Width { get; set; } + + public ushort Height { get; set; } + + public byte Unknown4 { get; set; } + + public VisibilityFlags Visibility { get; set; } public byte Unknown6 { get; set; } @@ -55,11 +70,25 @@ namespace HUD_Manager.Structs { public byte[] Unknown8 { get; set; } + public bool this[VisibilityFlags flags] { + get => (this.Visibility & flags) > 0; + set { + if (value) { + this.Visibility |= flags; + } else { + this.Visibility &= ~flags; + } + } + } + public Element(RawElement raw) { this.Id = raw.id; this.X = raw.x; this.Y = raw.y; this.Scale = raw.scale; + this.Options = raw.options; + this.Width = raw.width; + this.Height = raw.height; this.Unknown4 = raw.unknown4; this.Visibility = raw.visibility; this.Unknown6 = raw.unknown6; diff --git a/HUD Manager/Structs/Visibility.cs b/HUD Manager/Structs/Visibility.cs deleted file mode 100755 index 061c0c3..0000000 --- a/HUD Manager/Structs/Visibility.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace HUD_Manager.Structs { - public enum Visibility : byte { - Hidden = 1, - Visible = 3, - } -} diff --git a/HUD Manager/Structs/VisibilityBits.cs b/HUD Manager/Structs/VisibilityBits.cs new file mode 100755 index 0000000..7b302e1 --- /dev/null +++ b/HUD Manager/Structs/VisibilityBits.cs @@ -0,0 +1,9 @@ +using System; + +namespace HUD_Manager.Structs { + [Flags] + public enum VisibilityFlags : byte { + Keyboard = 1 << 0, + Gamepad = 1 << 1, + } +}