From 81cf14f3edf9845f330bca9af4e5df345813d37e Mon Sep 17 00:00:00 2001 From: Anna Date: Sat, 13 Mar 2021 16:10:23 -0500 Subject: [PATCH] feat: add selective field updates Also reverse Unknown4 to MeasuredFrom. Also rework UI slightly. --- HUD Manager/Configuration/Config.cs | 6 +- HUD Manager/Configuration/Migrator.cs | 98 +++++--- HUD Manager/Configuration/PositioningMode.cs | 6 + HUD Manager/Hud.cs | 45 ++-- HUD Manager/PluginUi.cs | 236 +++++++++++++++---- HUD Manager/Structs/Element.cs | 139 +++++++++++ HUD Manager/Structs/ElementKind.cs | 2 +- HUD Manager/Structs/MeasuredFrom.cs | 13 + HUD Manager/Structs/RawElement.cs | 75 ++---- 9 files changed, 481 insertions(+), 139 deletions(-) create mode 100755 HUD Manager/Configuration/PositioningMode.cs create mode 100755 HUD Manager/Structs/Element.cs create mode 100755 HUD Manager/Structs/MeasuredFrom.cs diff --git a/HUD Manager/Configuration/Config.cs b/HUD Manager/Configuration/Config.cs index a53654a..f6bf4ca 100644 --- a/HUD Manager/Configuration/Config.cs +++ b/HUD Manager/Configuration/Config.cs @@ -6,7 +6,9 @@ using Dalamud.Plugin; namespace HUD_Manager.Configuration { [Serializable] public class Config : IPluginConfiguration { - public int Version { get; set; } = 3; + public const int LatestVersion = 4; + + public int Version { get; set; } = LatestVersion; private DalamudPluginInterface Interface { get; set; } = null!; @@ -18,6 +20,8 @@ namespace HUD_Manager.Configuration { public HudSlot StagingSlot { get; set; } = HudSlot.Four; + public PositioningMode PositioningMode { get; set; } = PositioningMode.Percentage; + public Dictionary Layouts { get; } = new(); public List HudConditionMatches { get; } = new(); diff --git a/HUD Manager/Configuration/Migrator.cs b/HUD Manager/Configuration/Migrator.cs index 8e65bfd..37051ce 100755 --- a/HUD Manager/Configuration/Migrator.cs +++ b/HUD Manager/Configuration/Migrator.cs @@ -2,6 +2,7 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; +using Dalamud.Plugin; using HUD_Manager.Structs; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -31,7 +32,7 @@ namespace HUD_Manager.Configuration { return config; } - private static Config MigrateV2(JObject old) { + private static void WithEachElement(JObject old, Action action) { foreach (var property in old["Layouts"].Children()) { if (property.Name == "$type") { continue; @@ -46,26 +47,41 @@ namespace HUD_Manager.Configuration { } 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; + action(element); } } + } + + private static void MigrateV2(JObject old) { + WithEachElement(old, element => { + 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 void MigrateV3(JObject old) { + WithEachElement(old, element => { + var measuredFrom = element["Unknown4"].ToObject(); + element.Remove("Unknown4"); + element["MeasuredFrom"] = measuredFrom; + }); + + old["Version"] = 4; } private static string PluginConfig(string? pluginName = null) { @@ -99,22 +115,50 @@ namespace HUD_Manager.Configuration { } var config = JsonConvert.DeserializeObject(text); - uint version = 1; - if (config.TryGetValue("Version", out var token)) { - version = token.Value(); + + int GetVersion() { + if (config.TryGetValue("Version", out var token)) { + return token.Value(); + } + + return -1; } - switch (version) { - case 1: { - var v1 = config.ToObject(new JsonSerializer { - TypeNameHandling = TypeNameHandling.None, - }); + var version = GetVersion(); + if (version < 1) { + goto DefaultConfig; + } - return Migrate(v1); - } - case 2: { - return MigrateV2(config); + // v1 is a special case - this is an old HudSwap config that we can interpret as a memory chunk + // it does not need to go through migration steps after doing this, since it will be interpreted + // as the layout would be in memory, so the existing code can deal with it normally + if (version == 1) { + var v1 = config.ToObject(new JsonSerializer { + TypeNameHandling = TypeNameHandling.None, + }); + + return Migrate(v1); + } + + // otherwise, run migrations until done + while (version < Config.LatestVersion) { + switch (version) { + case 2: + MigrateV2(config); + break; + case 3: + MigrateV3(config); + break; + default: + PluginLog.Warning($"Tried to migration from an unknown version: {version}"); + goto DefaultConfig; } + + version = GetVersion(); + } + + if (version == Config.LatestVersion) { + return config.ToObject(); } DefaultConfig: diff --git a/HUD Manager/Configuration/PositioningMode.cs b/HUD Manager/Configuration/PositioningMode.cs new file mode 100755 index 0000000..6b3df5f --- /dev/null +++ b/HUD Manager/Configuration/PositioningMode.cs @@ -0,0 +1,6 @@ +namespace HUD_Manager.Configuration { + public enum PositioningMode { + Percentage, + Pixel, + } +} diff --git a/HUD Manager/Hud.cs b/HUD Manager/Hud.cs index dbcb8d2..4ebb164 100644 --- a/HUD Manager/Hud.cs +++ b/HUD Manager/Hud.cs @@ -114,16 +114,27 @@ namespace HUD_Manager { } private void WriteLayout(HudSlot slot, Layout layout, bool reloadIfNecessary = true) { - var slotPtr = this.GetLayoutPointer(slot); + this.WriteLayout(slot, layout.ToDictionary(), reloadIfNecessary); + } - var dict = layout.ToDictionary(); + private void WriteLayout(HudSlot slot, IReadOnlyDictionary dict, bool reloadIfNecessary = true) { + var slotPtr = this.GetLayoutPointer(slot); // update existing elements with saved data instead of wholesale overwriting var slotLayout = this.ReadLayout(slot); for (var i = 0; i < slotLayout.elements.Length; i++) { - if (dict.TryGetValue(slotLayout.elements[i].id, out var element)) { - slotLayout.elements[i] = new RawElement(element); + if (!dict.TryGetValue(slotLayout.elements[i].id, out var element)) { + continue; } + + // just replace the struct if all options are enabled + if (element.Enabled == Element.AllEnabled) { + slotLayout.elements[i] = new RawElement(element); + continue; + } + + // otherwise only replace the enabled options + slotLayout.elements[i].UpdateEnabled(element); } Marshal.StructureToPtr(slotLayout, slotPtr, false); @@ -154,26 +165,26 @@ namespace HUD_Manager { // get the ancestors and their elements for this node foreach (var ancestor in node.Ancestors().Reverse()) { foreach (var element in ancestor.Value.Elements) { - elements[element.Key] = element.Value; + if (element.Value.Enabled == Element.AllEnabled || !elements.ContainsKey(element.Key)) { + elements[element.Key] = element.Value.Clone(); + continue; + } + + elements[element.Key].UpdateEnabled(element.Value); } } // apply this node's elements foreach (var element in node.Value.Elements) { - elements[element.Key] = element.Value; + if (element.Value.Enabled == Element.AllEnabled || !elements.ContainsKey(element.Key)) { + elements[element.Key] = element.Value.Clone(); + continue; + } + + elements[element.Key].UpdateEnabled(element.Value); } - var elemList = elements.Values.ToList(); - - while (elemList.Count < InMemoryLayoutElements) { - elemList.Add(new Element(new RawElement())); - } - - var effective = new Layout { - elements = elemList.Select(elem => new RawElement(elem)).ToArray(), - }; - - this.WriteLayout(slot, effective); + this.WriteLayout(slot, elements); } } diff --git a/HUD Manager/PluginUi.cs b/HUD Manager/PluginUi.cs index c21f84f..346168a 100644 --- a/HUD Manager/PluginUi.cs +++ b/HUD Manager/PluginUi.cs @@ -306,18 +306,23 @@ namespace HUD_Manager { ImGui.Separator(); - ImGui.TextUnformatted("Search"); + if (ImGui.CollapsingHeader("Options##uimanager-options")) { + ImGui.DragFloat("Slider speed", ref this._dragSpeed, 0.01f, 0.01f, 10f); - ImGui.PushItemWidth(-1); - var search = this._editorSearch ?? string.Empty; - if (ImGui.InputText("##ui-editor-search", ref search, 100)) { - this._editorSearch = string.IsNullOrWhiteSpace(search) ? null : search; + if (ImGui.BeginCombo("Positioning mode", this.Plugin.Config.PositioningMode.ToString())) { + foreach (var mode in (PositioningMode[]) Enum.GetValues(typeof(PositioningMode))) { + if (!ImGui.Selectable($"{mode}##positioning", this.Plugin.Config.PositioningMode == mode)) { + continue; + } + + this.Plugin.Config.PositioningMode = mode; + this.Plugin.Config.Save(); + } + + ImGui.EndCombo(); + } } - ImGui.PopItemWidth(); - - ImGui.DragFloat("Slider speed", ref this._dragSpeed, 0.01f, 0.01f, 10f); - ImGui.Separator(); ImGui.TextUnformatted("HUD Elements"); @@ -348,6 +353,11 @@ namespace HUD_Manager { ImGui.EndPopup(); } + var search = this._editorSearch ?? string.Empty; + if (ImGui.InputText("Search##ui-editor-search", ref search, 100)) { + this._editorSearch = string.IsNullOrWhiteSpace(search) ? null : search; + } + if (ImGui.BeginChild("uimanager-layout-editor-elements", new Vector2(0, 0))) { var toRemove = new List(); @@ -363,19 +373,46 @@ namespace HUD_Manager { continue; } - var drawVisibility = !kind.IsJobGauge(); + var maxSettingWidth = 0f; - void DrawDelete() { - ImGui.SameLine(ImGui.GetContentRegionAvail().X - 30); - if (IconButton(FontAwesomeIcon.TrashAlt, $"uimanager-remove-element-{kind}")) { - toRemove.Add(kind); - } + void DrawSettingName(string name) { + maxSettingWidth = Math.Max(maxSettingWidth, ImGui.CalcTextSize(name).X); + ImGui.TextUnformatted(name); + ImGui.NextColumn(); } - if (drawVisibility) { - ImGui.TextUnformatted("Visibility"); + ImGui.Columns(3); + ImGui.SetColumnWidth(0, ImGui.CalcTextSize("Enabled").X + ImGui.GetStyle().ItemSpacing.X * 2); - DrawDelete(); + ImGui.TextUnformatted("Enabled"); + ImGui.NextColumn(); + + DrawSettingName("Setting"); + + ImGui.TextUnformatted("Control"); + + ImGui.SameLine(ImGui.GetContentRegionAvail().X - 30); + if (IconButton(FontAwesomeIcon.TrashAlt, $"uimanager-remove-element-{kind}")) { + toRemove.Add(kind); + } + + void DrawEnabledCheckbox(ElementKind kind, ElementComponent component) { + ImGui.NextColumn(); + + var enabled = element[component]; + if (ImGui.Checkbox($"###{component}-enabled-{kind}", ref enabled)) { + element[component] = enabled; + this.Plugin.Config.Save(); + + update = true; + } + + ImGui.NextColumn(); + } + + if (!kind.IsJobGauge()) { + DrawEnabledCheckbox(element.Id, ElementComponent.Visibility); + DrawSettingName("Visibility"); var keyboard = element[VisibilityFlags.Keyboard]; if (IconCheckbox(FontAwesomeIcon.Keyboard, ref keyboard, $"{kind}")) { @@ -391,24 +428,78 @@ namespace HUD_Manager { } } - var x = element.X; - if (ImGui.DragFloat($"X##{kind}", ref x, this._dragSpeed)) { - element.X = x; - update = true; + ImGui.NextColumn(); + ImGui.NextColumn(); + + DrawSettingName("Measured from"); + + ImGui.PushItemWidth(-1); + var measuredFrom = element.MeasuredFrom; + if (ImGui.BeginCombo($"##measured-from-{kind}", measuredFrom.ToString())) { + foreach (var measured in (MeasuredFrom[]) Enum.GetValues(typeof(MeasuredFrom))) { + if (!ImGui.Selectable($"{measured}##{kind}", measuredFrom == measured)) { + continue; + } + + element.MeasuredFrom = measured; + update = true; + } + + ImGui.EndCombo(); + } + ImGui.PopItemWidth(); + + DrawEnabledCheckbox(element.Id, ElementComponent.X); + DrawSettingName("X"); + + if (this.Plugin.Config.PositioningMode == PositioningMode.Percentage) { + ImGui.PushItemWidth(-1); + var x = element.X; + if (ImGui.DragFloat($"##x-{kind}", ref x, this._dragSpeed)) { + element.X = x; + update = true; + } + ImGui.PopItemWidth(); + + DrawEnabledCheckbox(element.Id, ElementComponent.Y); + DrawSettingName("Y"); + + ImGui.PushItemWidth(-1); + var y = element.Y; + if (ImGui.DragFloat($"##y-{kind}", ref y, this._dragSpeed)) { + element.Y = y; + update = true; + } + ImGui.PopItemWidth(); + } else { + var screen = ImGui.GetIO().DisplaySize; + + ImGui.PushItemWidth(-1); + var x = (int) Math.Truncate(element.X * screen.X / 100); + if (ImGui.InputInt($"##x-{kind}", ref x)) { + element.X = x / screen.X * 100; + update = true; + } + ImGui.PopItemWidth(); + + DrawEnabledCheckbox(element.Id, ElementComponent.Y); + DrawSettingName("Y"); + + ImGui.PushItemWidth(-1); + var y = (int) Math.Truncate(element.Y * screen.Y / 100); + if (ImGui.InputInt($"##y-{kind}", ref y)) { + element.Y = y / screen.Y * 100; + update = true; + } + ImGui.PopItemWidth(); } - if (!drawVisibility) { - DrawDelete(); - } - - var y = element.Y; - if (ImGui.DragFloat($"Y##{kind}", ref y, this._dragSpeed)) { - element.Y = y; - update = true; - } + DrawEnabledCheckbox(element.Id, ElementComponent.Scale); + DrawSettingName("Scale"); + ImGui.PushItemWidth(-1); var currentScale = $"{element.Scale * 100}%"; - if (ImGui.BeginCombo($"Scale##{kind}", currentScale)) { + if (ImGui.BeginCombo($"##scale-{kind}", currentScale)) { foreach (var scale in ScaleOptions) { if (!ImGui.Selectable($"{scale * 100}%")) { continue; @@ -420,29 +511,46 @@ namespace HUD_Manager { ImGui.EndCombo(); } + ImGui.PopItemWidth(); if (!kind.IsJobGauge()) { + DrawEnabledCheckbox(element.Id, ElementComponent.Opacity); + DrawSettingName("Opacity"); + + ImGui.PushItemWidth(-1); var opacity = (int) element.Opacity; - if (ImGui.DragInt($"Opacity##{kind}", ref opacity, 1, 1, 255)) { + if (ImGui.DragInt($"##opacity-{kind}", ref opacity, 1, 1, 255)) { element.Opacity = (byte) opacity; update = true; } + ImGui.PopItemWidth(); } if (kind == ElementKind.TargetBar) { var targetBarOpts = new TargetBarOptions(element.Options); + ImGui.NextColumn(); + ImGui.NextColumn(); + DrawSettingName("Display target information independently"); + + ImGui.PushItemWidth(-1); var independent = targetBarOpts.ShowIndependently; - if (ImGui.Checkbox("Display target information independently", ref independent)) { + if (ImGui.Checkbox($"##display-target-info-indep-{kind}", ref independent)) { targetBarOpts.ShowIndependently = independent; update = true; } + ImGui.PopItemWidth(); } if (kind == ElementKind.StatusEffects) { var statusOpts = new StatusOptions(element.Options); - if (ImGui.BeginCombo($"Style##{kind}", statusOpts.Style.ToString())) { + ImGui.NextColumn(); + ImGui.NextColumn(); + DrawSettingName("Style"); + + ImGui.PushItemWidth(-1); + if (ImGui.BeginCombo($"##style-{kind}", statusOpts.Style.ToString())) { foreach (var style in (StatusStyle[]) Enum.GetValues(typeof(StatusStyle))) { if (!ImGui.Selectable($"{style}##{kind}")) { continue; @@ -454,12 +562,18 @@ namespace HUD_Manager { ImGui.EndCombo(); } + ImGui.PopItemWidth(); } 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())) { + ImGui.NextColumn(); + ImGui.NextColumn(); + DrawSettingName("Layout"); + + ImGui.PushItemWidth(-1); + if (ImGui.BeginCombo($"##layout-{kind}", statusOpts.Layout.ToString())) { foreach (var sLayout in (StatusLayout[]) Enum.GetValues(typeof(StatusLayout))) { if (!ImGui.Selectable($"{sLayout}##{kind}")) { continue; @@ -471,8 +585,14 @@ namespace HUD_Manager { ImGui.EndCombo(); } + ImGui.PopItemWidth(); - if (ImGui.BeginCombo($"Alignment##{kind}", statusOpts.Alignment.ToString())) { + ImGui.NextColumn(); + ImGui.NextColumn(); + DrawSettingName("Alignment"); + + ImGui.PushItemWidth(-1); + if (ImGui.BeginCombo($"##alignment-{kind}", statusOpts.Alignment.ToString())) { foreach (var alignment in (StatusAlignment[]) Enum.GetValues(typeof(StatusAlignment))) { if (!ImGui.Selectable($"{alignment}##{kind}")) { continue; @@ -484,26 +604,45 @@ namespace HUD_Manager { ImGui.EndCombo(); } + ImGui.PopItemWidth(); + ImGui.NextColumn(); + ImGui.NextColumn(); + DrawSettingName("Focusable by gamepad"); + + ImGui.PushItemWidth(-1); var focusable = statusOpts.Gamepad == StatusGamepad.Focusable; - if (ImGui.Checkbox($"Focusable by gamepad##{kind}", ref focusable)) { + if (ImGui.Checkbox($"##focusable-by-gamepad-{kind}", ref focusable)) { statusOpts.Gamepad = focusable ? StatusGamepad.Focusable : StatusGamepad.NonFocusable; update = true; } + ImGui.PopItemWidth(); } 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)); + ImGui.NextColumn(); + ImGui.NextColumn(); + DrawSettingName("Hotbar number"); + + ImGui.PushItemWidth(-1); + var hotbarIndex = hotbarOpts.Index + 1; + if (ImGui.InputInt($"##hotbar-number-{kind}", ref hotbarIndex)) { + hotbarOpts.Index = (byte) Math.Max(0, Math.Min(9, hotbarIndex - 1)); update = true; } + ImGui.PopItemWidth(); } - if (ImGui.BeginCombo($"Hotbar layout##{kind}", hotbarOpts.Layout.ToString())) { + ImGui.NextColumn(); + ImGui.NextColumn(); + DrawSettingName("Hotbar layout"); + + + ImGui.PushItemWidth(-1); + if (ImGui.BeginCombo($"##hotbar-layout-{kind}", hotbarOpts.Layout.ToString())) { foreach (var hotbarLayout in (HotbarLayout[]) Enum.GetValues(typeof(HotbarLayout))) { if (!ImGui.Selectable($"{hotbarLayout}##{kind}")) { continue; @@ -515,17 +654,28 @@ namespace HUD_Manager { ImGui.EndCombo(); } + ImGui.PopItemWidth(); } if (kind.IsJobGauge()) { var gaugeOpts = new GaugeOptions(element.Options); + ImGui.NextColumn(); + ImGui.NextColumn(); + DrawSettingName("Simple"); + + ImGui.PushItemWidth(-1); var simple = gaugeOpts.Style == GaugeStyle.Simple; - if (ImGui.Checkbox($"Simple##{kind}", ref simple)) { + if (ImGui.Checkbox($"##simple-{kind}", ref simple)) { gaugeOpts.Style = simple ? GaugeStyle.Simple : GaugeStyle.Normal; update = true; } + ImGui.PopItemWidth(); } + + ImGui.SetColumnWidth(1, maxSettingWidth + ImGui.GetStyle().ItemSpacing.X * 2); + + ImGui.Columns(); } foreach (var remove in toRemove) { diff --git a/HUD Manager/Structs/Element.cs b/HUD Manager/Structs/Element.cs new file mode 100755 index 0000000..84eee76 --- /dev/null +++ b/HUD Manager/Structs/Element.cs @@ -0,0 +1,139 @@ +using System; + +namespace HUD_Manager.Structs { + [Serializable] + public class Element { + public const ElementComponent AllEnabled = ElementComponent.X + | ElementComponent.Y + | ElementComponent.Scale + | ElementComponent.Visibility + | ElementComponent.Opacity + | ElementComponent.Options; + + public ElementKind Id { get; set; } + + public ElementComponent Enabled { get; set; } = AllEnabled; + + public float X { get; set; } + + public float Y { get; set; } + + public float Scale { get; set; } + + public byte[] Options { get; set; } + + public ushort Width { get; set; } + + public ushort Height { get; set; } + + public MeasuredFrom MeasuredFrom { get; set; } + + public VisibilityFlags Visibility { get; set; } + + public byte Unknown6 { get; set; } + + public byte Opacity { get; set; } + + 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 bool this[ElementComponent component] { + get => (this.Enabled & component) > 0; + set { + if (value) { + this.Enabled |= component; + } else { + this.Enabled &= ~component; + } + } + } + + #pragma warning disable 8618 + private Element() { + } + #pragma warning restore 8618 + + 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.MeasuredFrom = raw.measuredFrom; + this.Visibility = raw.visibility; + this.Unknown6 = raw.unknown6; + this.Opacity = raw.opacity; + this.Unknown8 = raw.unknown8; + } + + public Element Clone() { + return new() { + Id = this.Id, + X = this.X, + Y = this.Y, + Scale = this.Scale, + Options = (byte[]) this.Options.Clone(), + Width = this.Width, + Height = this.Height, + MeasuredFrom = this.MeasuredFrom, + Visibility = this.Visibility, + Unknown6 = this.Unknown6, + Unknown8 = (byte[]) this.Unknown8.Clone(), + }; + } + + public void UpdateEnabled(Element other) { + if (other[ElementComponent.X]) { + this.X = other.X; + } + + if (other[ElementComponent.Y]) { + this.Y = other.Y; + } + + if (other[ElementComponent.Scale]) { + this.Scale = other.Scale; + } + + if (other[ElementComponent.Visibility]) { + this.Visibility = other.Visibility; + } + + if (other[ElementComponent.Opacity]) { + this.Opacity = other.Opacity; + } + + if (other[ElementComponent.Options]) { + this.Options = other.Options; + } + + this.Height = other.Height; + this.Width = other.Width; + this.MeasuredFrom = other.MeasuredFrom; + this.Unknown6 = other.Unknown6; + this.Unknown8 = other.Unknown8; + } + } + + [Flags] + public enum ElementComponent : uint { + X = 1 << 0, + Y = 1 << 1, + Scale = 1 << 2, + Visibility = 1 << 3, + Opacity = 1 << 4, + Options = 1 << 5, + } +} diff --git a/HUD Manager/Structs/ElementKind.cs b/HUD Manager/Structs/ElementKind.cs index c066a33..50a87c8 100755 --- a/HUD Manager/Structs/ElementKind.cs +++ b/HUD Manager/Structs/ElementKind.cs @@ -126,7 +126,7 @@ namespace HUD_Manager.Structs { ElementKind.SongGauge => 44, ElementKind.HealingGauge => 45, ElementKind.ElementalGauge => 46, - ElementKind.AetherflowGaugeSch => 47, // order? + ElementKind.AetherflowGaugeSch => 47, // order? - same name, so not sure which key is for which ElementKind.AetherflowGaugeSmn => 48, // order? ElementKind.TranceGauge => 49, ElementKind.FaerieGauge => 50, diff --git a/HUD Manager/Structs/MeasuredFrom.cs b/HUD Manager/Structs/MeasuredFrom.cs new file mode 100755 index 0000000..8221c6d --- /dev/null +++ b/HUD Manager/Structs/MeasuredFrom.cs @@ -0,0 +1,13 @@ +namespace HUD_Manager.Structs { + public enum MeasuredFrom : byte { + TopLeft = 0, + TopCentre = 1, + TopRight = 2, + MiddleLeft = 3, + Middle = 4, + MiddleRight = 5, + BottomLeft = 6, + BottomMiddle = 7, + BottomRight = 8, + } +} diff --git a/HUD Manager/Structs/RawElement.cs b/HUD Manager/Structs/RawElement.cs index c6d0d00..d55b3e4 100755 --- a/HUD Manager/Structs/RawElement.cs +++ b/HUD Manager/Structs/RawElement.cs @@ -18,7 +18,7 @@ namespace HUD_Manager.Structs { public ushort height; - public byte unknown4; + public MeasuredFrom measuredFrom; public VisibilityFlags visibility; @@ -26,6 +26,7 @@ namespace HUD_Manager.Structs { public byte opacity; + // last two bytes are padding [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] unknown8; @@ -37,63 +38,37 @@ namespace HUD_Manager.Structs { this.options = element.Options; this.width = element.Width; this.height = element.Height; - this.unknown4 = element.Unknown4; + this.measuredFrom = element.MeasuredFrom; this.visibility = element.Visibility; this.unknown6 = element.Unknown6; this.opacity = element.Opacity; this.unknown8 = element.Unknown8; } - } - public class Element { - public ElementKind Id { get; set; } - - public float X { get; set; } - - public float Y { get; set; } - - public float Scale { get; set; } - - public byte[] Options { 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; } - - public byte Opacity { get; set; } - - 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 void UpdateEnabled(Element element) { + if (element[ElementComponent.X]) { + this.x = element.X; } - } - 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; - this.Opacity = raw.opacity; - this.Unknown8 = raw.unknown8; + if (element[ElementComponent.Y]) { + this.y = element.Y; + } + + if (element[ElementComponent.Scale]) { + this.scale = element.Scale; + } + + if (element[ElementComponent.Visibility]) { + this.visibility = element.Visibility; + } + + if (element[ElementComponent.Opacity]) { + this.opacity = element.Opacity; + } + + if (element[ElementComponent.Options]) { + this.options = element.Options; + } } } }