feat: add selective field updates
Also reverse Unknown4 to MeasuredFrom. Also rework UI slightly.
This commit is contained in:
parent
fc64403b89
commit
81cf14f3ed
|
@ -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<Guid, SavedLayout> Layouts { get; } = new();
|
||||
|
||||
public List<HudConditionMatch> HudConditionMatches { get; } = new();
|
||||
|
|
|
@ -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<JObject> action) {
|
||||
foreach (var property in old["Layouts"].Children<JProperty>()) {
|
||||
if (property.Name == "$type") {
|
||||
continue;
|
||||
|
@ -46,26 +47,41 @@ namespace HUD_Manager.Configuration {
|
|||
}
|
||||
|
||||
var element = (JObject) elementProp.Value;
|
||||
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;
|
||||
action(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -99,22 +115,50 @@ namespace HUD_Manager.Configuration {
|
|||
}
|
||||
|
||||
var config = JsonConvert.DeserializeObject<JObject>(text);
|
||||
uint version = 1;
|
||||
if (config.TryGetValue("Version", out var token)) {
|
||||
version = token.Value<uint>();
|
||||
|
||||
int GetVersion() {
|
||||
if (config.TryGetValue("Version", out var token)) {
|
||||
return token.Value<int>();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (version) {
|
||||
case 1: {
|
||||
var v1 = config.ToObject<ConfigV1>(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<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:
|
||||
|
|
|
@ -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) {
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ElementKind>();
|
||||
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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.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,
|
||||
|
|
|
@ -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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue