feat: add selective field updates
Also reverse Unknown4 to MeasuredFrom. Also rework UI slightly.
This commit is contained in:
parent
2aaf87f7b4
commit
c967299fb0
|
@ -6,7 +6,9 @@ using Dalamud.Plugin;
|
||||||
namespace HUD_Manager.Configuration {
|
namespace HUD_Manager.Configuration {
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class Config : IPluginConfiguration {
|
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!;
|
private DalamudPluginInterface Interface { get; set; } = null!;
|
||||||
|
|
||||||
|
@ -18,6 +20,8 @@ namespace HUD_Manager.Configuration {
|
||||||
|
|
||||||
public HudSlot StagingSlot { get; set; } = HudSlot.Four;
|
public HudSlot StagingSlot { get; set; } = HudSlot.Four;
|
||||||
|
|
||||||
|
public PositioningMode PositioningMode { get; set; } = PositioningMode.Percentage;
|
||||||
|
|
||||||
public Dictionary<Guid, SavedLayout> Layouts { get; } = new();
|
public Dictionary<Guid, SavedLayout> Layouts { get; } = new();
|
||||||
|
|
||||||
public List<HudConditionMatch> HudConditionMatches { get; } = new();
|
public List<HudConditionMatch> HudConditionMatches { get; } = new();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Dalamud.Plugin;
|
||||||
using HUD_Manager.Structs;
|
using HUD_Manager.Structs;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
@ -31,7 +32,7 @@ namespace HUD_Manager.Configuration {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Config MigrateV2(JObject old) {
|
private static void WithEachElement(JObject old, Action<JObject> action) {
|
||||||
foreach (var property in old["Layouts"].Children<JProperty>()) {
|
foreach (var property in old["Layouts"].Children<JProperty>()) {
|
||||||
if (property.Name == "$type") {
|
if (property.Name == "$type") {
|
||||||
continue;
|
continue;
|
||||||
|
@ -46,26 +47,41 @@ namespace HUD_Manager.Configuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
var element = (JObject) elementProp.Value;
|
var element = (JObject) elementProp.Value;
|
||||||
var bytes = element["Unknown4"].ToObject<byte[]>();
|
|
||||||
|
|
||||||
var options = new byte[4];
|
action(element);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MigrateV2(JObject old) {
|
||||||
|
WithEachElement(old, element => {
|
||||||
|
var bytes = element["Unknown4"].ToObject<byte[]>();
|
||||||
|
|
||||||
|
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;
|
old["Version"] = 3;
|
||||||
|
}
|
||||||
|
|
||||||
return old.ToObject<Config>();
|
private static void MigrateV3(JObject old) {
|
||||||
|
WithEachElement(old, element => {
|
||||||
|
var measuredFrom = element["Unknown4"].ToObject<byte>();
|
||||||
|
element.Remove("Unknown4");
|
||||||
|
element["MeasuredFrom"] = measuredFrom;
|
||||||
|
});
|
||||||
|
|
||||||
|
old["Version"] = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string PluginConfig(string? pluginName = null) {
|
private static string PluginConfig(string? pluginName = null) {
|
||||||
|
@ -99,22 +115,50 @@ namespace HUD_Manager.Configuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = JsonConvert.DeserializeObject<JObject>(text);
|
var config = JsonConvert.DeserializeObject<JObject>(text);
|
||||||
uint version = 1;
|
|
||||||
if (config.TryGetValue("Version", out var token)) {
|
int GetVersion() {
|
||||||
version = token.Value<uint>();
|
if (config.TryGetValue("Version", out var token)) {
|
||||||
|
return token.Value<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (version) {
|
var version = GetVersion();
|
||||||
case 1: {
|
if (version < 1) {
|
||||||
var v1 = config.ToObject<ConfigV1>(new JsonSerializer {
|
goto DefaultConfig;
|
||||||
TypeNameHandling = TypeNameHandling.None,
|
}
|
||||||
});
|
|
||||||
|
|
||||||
return Migrate(v1);
|
// 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
|
||||||
case 2: {
|
// as the layout would be in memory, so the existing code can deal with it normally
|
||||||
return MigrateV2(config);
|
if (version == 1) {
|
||||||
|
var v1 = config.ToObject<ConfigV1>(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<Config>();
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultConfig:
|
DefaultConfig:
|
||||||
|
|
6
HUD Manager/Configuration/PositioningMode.cs
Executable file
6
HUD Manager/Configuration/PositioningMode.cs
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
namespace HUD_Manager.Configuration {
|
||||||
|
public enum PositioningMode {
|
||||||
|
Percentage,
|
||||||
|
Pixel,
|
||||||
|
}
|
||||||
|
}
|
|
@ -114,16 +114,27 @@ namespace HUD_Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteLayout(HudSlot slot, Layout layout, bool reloadIfNecessary = true) {
|
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<ElementKind, Element> dict, bool reloadIfNecessary = true) {
|
||||||
|
var slotPtr = this.GetLayoutPointer(slot);
|
||||||
|
|
||||||
// update existing elements with saved data instead of wholesale overwriting
|
// update existing elements with saved data instead of wholesale overwriting
|
||||||
var slotLayout = this.ReadLayout(slot);
|
var slotLayout = this.ReadLayout(slot);
|
||||||
for (var i = 0; i < slotLayout.elements.Length; i++) {
|
for (var i = 0; i < slotLayout.elements.Length; i++) {
|
||||||
if (dict.TryGetValue(slotLayout.elements[i].id, out var element)) {
|
if (!dict.TryGetValue(slotLayout.elements[i].id, out var element)) {
|
||||||
slotLayout.elements[i] = new RawElement(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);
|
Marshal.StructureToPtr(slotLayout, slotPtr, false);
|
||||||
|
@ -154,26 +165,26 @@ namespace HUD_Manager {
|
||||||
// get the ancestors and their elements for this node
|
// get the ancestors and their elements for this node
|
||||||
foreach (var ancestor in node.Ancestors().Reverse()) {
|
foreach (var ancestor in node.Ancestors().Reverse()) {
|
||||||
foreach (var element in ancestor.Value.Elements) {
|
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
|
// apply this node's elements
|
||||||
foreach (var element in node.Value.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();
|
this.WriteLayout(slot, elements);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -306,18 +306,23 @@ namespace HUD_Manager {
|
||||||
|
|
||||||
ImGui.Separator();
|
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);
|
if (ImGui.BeginCombo("Positioning mode", this.Plugin.Config.PositioningMode.ToString())) {
|
||||||
var search = this._editorSearch ?? string.Empty;
|
foreach (var mode in (PositioningMode[]) Enum.GetValues(typeof(PositioningMode))) {
|
||||||
if (ImGui.InputText("##ui-editor-search", ref search, 100)) {
|
if (!ImGui.Selectable($"{mode}##positioning", this.Plugin.Config.PositioningMode == mode)) {
|
||||||
this._editorSearch = string.IsNullOrWhiteSpace(search) ? null : search;
|
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.Separator();
|
||||||
|
|
||||||
ImGui.TextUnformatted("HUD Elements");
|
ImGui.TextUnformatted("HUD Elements");
|
||||||
|
@ -348,6 +353,11 @@ namespace HUD_Manager {
|
||||||
ImGui.EndPopup();
|
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))) {
|
if (ImGui.BeginChild("uimanager-layout-editor-elements", new Vector2(0, 0))) {
|
||||||
var toRemove = new List<ElementKind>();
|
var toRemove = new List<ElementKind>();
|
||||||
|
|
||||||
|
@ -363,19 +373,46 @@ namespace HUD_Manager {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var drawVisibility = !kind.IsJobGauge();
|
var maxSettingWidth = 0f;
|
||||||
|
|
||||||
void DrawDelete() {
|
void DrawSettingName(string name) {
|
||||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X - 30);
|
maxSettingWidth = Math.Max(maxSettingWidth, ImGui.CalcTextSize(name).X);
|
||||||
if (IconButton(FontAwesomeIcon.TrashAlt, $"uimanager-remove-element-{kind}")) {
|
ImGui.TextUnformatted(name);
|
||||||
toRemove.Add(kind);
|
ImGui.NextColumn();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawVisibility) {
|
ImGui.Columns(3);
|
||||||
ImGui.TextUnformatted("Visibility");
|
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];
|
var keyboard = element[VisibilityFlags.Keyboard];
|
||||||
if (IconCheckbox(FontAwesomeIcon.Keyboard, ref keyboard, $"{kind}")) {
|
if (IconCheckbox(FontAwesomeIcon.Keyboard, ref keyboard, $"{kind}")) {
|
||||||
|
@ -391,24 +428,78 @@ namespace HUD_Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var x = element.X;
|
ImGui.NextColumn();
|
||||||
if (ImGui.DragFloat($"X##{kind}", ref x, this._dragSpeed)) {
|
ImGui.NextColumn();
|
||||||
element.X = x;
|
|
||||||
update = true;
|
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) {
|
DrawEnabledCheckbox(element.Id, ElementComponent.Scale);
|
||||||
DrawDelete();
|
DrawSettingName("Scale");
|
||||||
}
|
|
||||||
|
|
||||||
var y = element.Y;
|
|
||||||
if (ImGui.DragFloat($"Y##{kind}", ref y, this._dragSpeed)) {
|
|
||||||
element.Y = y;
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ImGui.PushItemWidth(-1);
|
||||||
var currentScale = $"{element.Scale * 100}%";
|
var currentScale = $"{element.Scale * 100}%";
|
||||||
if (ImGui.BeginCombo($"Scale##{kind}", currentScale)) {
|
if (ImGui.BeginCombo($"##scale-{kind}", currentScale)) {
|
||||||
foreach (var scale in ScaleOptions) {
|
foreach (var scale in ScaleOptions) {
|
||||||
if (!ImGui.Selectable($"{scale * 100}%")) {
|
if (!ImGui.Selectable($"{scale * 100}%")) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -420,29 +511,46 @@ namespace HUD_Manager {
|
||||||
|
|
||||||
ImGui.EndCombo();
|
ImGui.EndCombo();
|
||||||
}
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
|
|
||||||
if (!kind.IsJobGauge()) {
|
if (!kind.IsJobGauge()) {
|
||||||
|
DrawEnabledCheckbox(element.Id, ElementComponent.Opacity);
|
||||||
|
DrawSettingName("Opacity");
|
||||||
|
|
||||||
|
ImGui.PushItemWidth(-1);
|
||||||
var opacity = (int) element.Opacity;
|
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;
|
element.Opacity = (byte) opacity;
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind == ElementKind.TargetBar) {
|
if (kind == ElementKind.TargetBar) {
|
||||||
var targetBarOpts = new TargetBarOptions(element.Options);
|
var targetBarOpts = new TargetBarOptions(element.Options);
|
||||||
|
|
||||||
|
ImGui.NextColumn();
|
||||||
|
ImGui.NextColumn();
|
||||||
|
DrawSettingName("Display target information independently");
|
||||||
|
|
||||||
|
ImGui.PushItemWidth(-1);
|
||||||
var independent = targetBarOpts.ShowIndependently;
|
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;
|
targetBarOpts.ShowIndependently = independent;
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind == ElementKind.StatusEffects) {
|
if (kind == ElementKind.StatusEffects) {
|
||||||
var statusOpts = new StatusOptions(element.Options);
|
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))) {
|
foreach (var style in (StatusStyle[]) Enum.GetValues(typeof(StatusStyle))) {
|
||||||
if (!ImGui.Selectable($"{style}##{kind}")) {
|
if (!ImGui.Selectable($"{style}##{kind}")) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -454,12 +562,18 @@ namespace HUD_Manager {
|
||||||
|
|
||||||
ImGui.EndCombo();
|
ImGui.EndCombo();
|
||||||
}
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind == ElementKind.StatusInfoEnhancements || kind == ElementKind.StatusInfoEnfeeblements || kind == ElementKind.StatusInfoOther) {
|
if (kind == ElementKind.StatusInfoEnhancements || kind == ElementKind.StatusInfoEnfeeblements || kind == ElementKind.StatusInfoOther) {
|
||||||
var statusOpts = new StatusInfoOptions(kind, element.Options);
|
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))) {
|
foreach (var sLayout in (StatusLayout[]) Enum.GetValues(typeof(StatusLayout))) {
|
||||||
if (!ImGui.Selectable($"{sLayout}##{kind}")) {
|
if (!ImGui.Selectable($"{sLayout}##{kind}")) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -471,8 +585,14 @@ namespace HUD_Manager {
|
||||||
|
|
||||||
ImGui.EndCombo();
|
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))) {
|
foreach (var alignment in (StatusAlignment[]) Enum.GetValues(typeof(StatusAlignment))) {
|
||||||
if (!ImGui.Selectable($"{alignment}##{kind}")) {
|
if (!ImGui.Selectable($"{alignment}##{kind}")) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -484,26 +604,45 @@ namespace HUD_Manager {
|
||||||
|
|
||||||
ImGui.EndCombo();
|
ImGui.EndCombo();
|
||||||
}
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
|
|
||||||
|
ImGui.NextColumn();
|
||||||
|
ImGui.NextColumn();
|
||||||
|
DrawSettingName("Focusable by gamepad");
|
||||||
|
|
||||||
|
ImGui.PushItemWidth(-1);
|
||||||
var focusable = statusOpts.Gamepad == StatusGamepad.Focusable;
|
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;
|
statusOpts.Gamepad = focusable ? StatusGamepad.Focusable : StatusGamepad.NonFocusable;
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind.IsHotbar()) {
|
if (kind.IsHotbar()) {
|
||||||
var hotbarOpts = new HotbarOptions(element.Options);
|
var hotbarOpts = new HotbarOptions(element.Options);
|
||||||
|
|
||||||
if (kind != ElementKind.PetHotbar) {
|
if (kind != ElementKind.PetHotbar) {
|
||||||
var hotbarIndex = (int) hotbarOpts.Index;
|
ImGui.NextColumn();
|
||||||
if (ImGui.InputInt($"Hotbar number##{kind}", ref hotbarIndex)) {
|
ImGui.NextColumn();
|
||||||
hotbarOpts.Index = (byte) Math.Max(0, Math.Min(9, hotbarIndex));
|
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;
|
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))) {
|
foreach (var hotbarLayout in (HotbarLayout[]) Enum.GetValues(typeof(HotbarLayout))) {
|
||||||
if (!ImGui.Selectable($"{hotbarLayout}##{kind}")) {
|
if (!ImGui.Selectable($"{hotbarLayout}##{kind}")) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -515,17 +654,28 @@ namespace HUD_Manager {
|
||||||
|
|
||||||
ImGui.EndCombo();
|
ImGui.EndCombo();
|
||||||
}
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind.IsJobGauge()) {
|
if (kind.IsJobGauge()) {
|
||||||
var gaugeOpts = new GaugeOptions(element.Options);
|
var gaugeOpts = new GaugeOptions(element.Options);
|
||||||
|
|
||||||
|
ImGui.NextColumn();
|
||||||
|
ImGui.NextColumn();
|
||||||
|
DrawSettingName("Simple");
|
||||||
|
|
||||||
|
ImGui.PushItemWidth(-1);
|
||||||
var simple = gaugeOpts.Style == GaugeStyle.Simple;
|
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;
|
gaugeOpts.Style = simple ? GaugeStyle.Simple : GaugeStyle.Normal;
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
ImGui.PopItemWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.SetColumnWidth(1, maxSettingWidth + ImGui.GetStyle().ItemSpacing.X * 2);
|
||||||
|
|
||||||
|
ImGui.Columns();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var remove in toRemove) {
|
foreach (var remove in toRemove) {
|
||||||
|
|
139
HUD Manager/Structs/Element.cs
Executable file
139
HUD Manager/Structs/Element.cs
Executable file
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
|
@ -126,7 +126,7 @@ namespace HUD_Manager.Structs {
|
||||||
ElementKind.SongGauge => 44,
|
ElementKind.SongGauge => 44,
|
||||||
ElementKind.HealingGauge => 45,
|
ElementKind.HealingGauge => 45,
|
||||||
ElementKind.ElementalGauge => 46,
|
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.AetherflowGaugeSmn => 48, // order?
|
||||||
ElementKind.TranceGauge => 49,
|
ElementKind.TranceGauge => 49,
|
||||||
ElementKind.FaerieGauge => 50,
|
ElementKind.FaerieGauge => 50,
|
||||||
|
|
13
HUD Manager/Structs/MeasuredFrom.cs
Executable file
13
HUD Manager/Structs/MeasuredFrom.cs
Executable file
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,7 @@ namespace HUD_Manager.Structs {
|
||||||
|
|
||||||
public ushort height;
|
public ushort height;
|
||||||
|
|
||||||
public byte unknown4;
|
public MeasuredFrom measuredFrom;
|
||||||
|
|
||||||
public VisibilityFlags visibility;
|
public VisibilityFlags visibility;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ namespace HUD_Manager.Structs {
|
||||||
|
|
||||||
public byte opacity;
|
public byte opacity;
|
||||||
|
|
||||||
|
// last two bytes are padding
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||||
public byte[] unknown8;
|
public byte[] unknown8;
|
||||||
|
|
||||||
|
@ -37,63 +38,37 @@ namespace HUD_Manager.Structs {
|
||||||
this.options = element.Options;
|
this.options = element.Options;
|
||||||
this.width = element.Width;
|
this.width = element.Width;
|
||||||
this.height = element.Height;
|
this.height = element.Height;
|
||||||
this.unknown4 = element.Unknown4;
|
this.measuredFrom = element.MeasuredFrom;
|
||||||
this.visibility = element.Visibility;
|
this.visibility = element.Visibility;
|
||||||
this.unknown6 = element.Unknown6;
|
this.unknown6 = element.Unknown6;
|
||||||
this.opacity = element.Opacity;
|
this.opacity = element.Opacity;
|
||||||
this.unknown8 = element.Unknown8;
|
this.unknown8 = element.Unknown8;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class Element {
|
public void UpdateEnabled(Element element) {
|
||||||
public ElementKind Id { get; set; }
|
if (element[ElementComponent.X]) {
|
||||||
|
this.x = element.X;
|
||||||
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 Element(RawElement raw) {
|
if (element[ElementComponent.Y]) {
|
||||||
this.Id = raw.id;
|
this.y = element.Y;
|
||||||
this.X = raw.x;
|
}
|
||||||
this.Y = raw.y;
|
|
||||||
this.Scale = raw.scale;
|
if (element[ElementComponent.Scale]) {
|
||||||
this.Options = raw.options;
|
this.scale = element.Scale;
|
||||||
this.Width = raw.width;
|
}
|
||||||
this.Height = raw.height;
|
|
||||||
this.Unknown4 = raw.unknown4;
|
if (element[ElementComponent.Visibility]) {
|
||||||
this.Visibility = raw.visibility;
|
this.visibility = element.Visibility;
|
||||||
this.Unknown6 = raw.unknown6;
|
}
|
||||||
this.Opacity = raw.opacity;
|
|
||||||
this.Unknown8 = raw.unknown8;
|
if (element[ElementComponent.Opacity]) {
|
||||||
|
this.opacity = element.Opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element[ElementComponent.Options]) {
|
||||||
|
this.options = element.Options;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user