Files
HSUI/Config/Attributes/ConfigTypeAttributes.cs

683 lines
20 KiB
C#

using Dalamud.Interface;
using Dalamud.Interface.Utility;
using HSUI.Enums;
using HSUI.Helpers;
using HSUI.Interface.GeneralElements;
using Dalamud.Bindings.ImGui;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Reflection;
namespace HSUI.Config.Attributes
{
#region class attributes
[AttributeUsage(AttributeTargets.Class)]
public class ExportableAttribute : Attribute
{
public bool exportable;
public ExportableAttribute(bool exportable)
{
this.exportable = exportable;
}
}
public class ShareableAttribute : Attribute
{
public bool shareable;
public ShareableAttribute(bool shareable)
{
this.shareable = shareable;
}
}
public class ResettableAttribute : Attribute
{
public bool resettable;
public ResettableAttribute(bool resettable)
{
this.resettable = resettable;
}
}
[AttributeUsage(AttributeTargets.Class)]
public class DisableableAttribute : Attribute
{
public bool disableable;
public DisableableAttribute(bool disableable)
{
this.disableable = disableable;
}
}
[AttributeUsage(AttributeTargets.Class)]
public class DisableParentSettingsAttribute : Attribute
{
public readonly string[] DisabledFields;
public DisableParentSettingsAttribute(params string[] fields)
{
this.DisabledFields = fields;
}
}
#endregion
#region method attributes
[AttributeUsage(AttributeTargets.Method)]
public class ManualDrawAttribute : Attribute
{
}
#endregion
#region field attributes
[AttributeUsage(AttributeTargets.Field)]
public abstract class ConfigAttribute : Attribute
{
public string friendlyName;
public bool isMonitored = false;
public bool separator = false;
public bool spacing = false;
public string? help = null;
public ConfigAttribute(string friendlyName)
{
this.friendlyName = friendlyName;
}
public bool Draw(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader = false)
{
bool result = DrawField(field, config, ID, collapsingHeader);
if (help != null && ImGui.IsItemHovered())
{
ImGui.SetTooltip(help);
}
return result;
}
public abstract bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader = false);
protected string IDText(string? ID) => ID != null ? " ##" + ID : "";
protected void TriggerChangeEvent<T>(PluginConfigObject config, string fieldName, object value, ChangeType type = ChangeType.None)
{
if (!isMonitored || config is not IOnChangeEventArgs eventObject)
{
return;
}
eventObject.OnValueChanged(new OnChangeEventArgs<T>(fieldName, (T)value, type));
}
}
[AttributeUsage(AttributeTargets.Field)]
public class CheckboxAttribute : ConfigAttribute
{
public CheckboxAttribute(string friendlyName) : base(friendlyName) { }
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
var disableable = config.Disableable;
if (!disableable && friendlyName == "Enabled")
{
if (ID != null)
{
ImGui.Text(ID);
}
return false;
}
bool? fieldVal = (bool?)field.GetValue(config);
bool boolVal = fieldVal.HasValue ? fieldVal.Value : false;
if (ImGui.Checkbox(ID != null && friendlyName == "Enabled" && !collapsingHeader ? ID : friendlyName + IDText(ID), ref boolVal))
{
field.SetValue(config, boolVal);
TriggerChangeEvent<bool>(config, field.Name, boolVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class RadioSelector : ConfigAttribute
{
private string[] _options;
public string? Label { get; set; }
public RadioSelector(params string[] options) : base(string.Join("_", options))
{
_options = options;
}
public RadioSelector(Type enumType) : this(enumType.IsEnum ? Enum.GetNames(enumType) : Array.Empty<string>()) { }
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
bool changed = false;
object? fieldVal = field.GetValue(config);
int intVal = 0;
if (fieldVal != null)
{
intVal = (int)fieldVal;
}
string? label = Label ?? friendlyName;
if (!string.IsNullOrEmpty(label) && label != string.Join("_", _options))
{
ImGui.TextUnformatted(label);
ImGui.SameLine();
}
for (int i = 0; i < _options.Length; i++)
{
changed |= ImGui.RadioButton(_options[i], ref intVal, i);
if (i < _options.Length - 1)
{
ImGui.SameLine();
}
}
if (changed)
{
field.SetValue(config, intVal);
TriggerChangeEvent<int>(config, field.Name, intVal);
}
return changed;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class DragFloatAttribute : ConfigAttribute
{
public float min;
public float max;
public float velocity;
public DragFloatAttribute(string friendlyName) : base(friendlyName)
{
min = 1f;
max = 1000f;
velocity = 1f;
}
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
float? fieldVal = (float?)field.GetValue(config);
float floatVal = fieldVal.HasValue ? fieldVal.Value : 0;
if (ImGui.DragFloat(friendlyName + IDText(ID), ref floatVal, velocity, min, max))
{
field.SetValue(config, floatVal);
TriggerChangeEvent<float>(config, field.Name, floatVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class DragIntAttribute : ConfigAttribute
{
public int min;
public int max;
public float velocity;
public DragIntAttribute(string friendlyName) : base(friendlyName)
{
min = 1;
max = 1000;
velocity = 1;
}
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
int? fieldVal = (int?)field.GetValue(config);
int intVal = fieldVal.HasValue ? fieldVal.Value : 0;
if (ImGui.DragInt(friendlyName + IDText(ID), ref intVal, velocity, min, max))
{
field.SetValue(config, intVal);
TriggerChangeEvent<int>(config, field.Name, intVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class DragFloat2Attribute : ConfigAttribute
{
public float min;
public float max;
public float velocity;
public DragFloat2Attribute(string friendlyName) : base(friendlyName)
{
min = 1f;
max = 1000f;
velocity = 1f;
}
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
Vector2? fieldVal = (Vector2?)field.GetValue(config);
Vector2 vectorVal = fieldVal.HasValue ? fieldVal.Value : Vector2.Zero;
if (ImGui.DragFloat2(friendlyName + IDText(ID), ref vectorVal, velocity, min, max))
{
field.SetValue(config, vectorVal);
TriggerChangeEvent<Vector2>(config, field.Name, vectorVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class DragInt2Attribute : ConfigAttribute
{
public int min;
public int max;
public int velocity;
public DragInt2Attribute(string friendlyName) : base(friendlyName)
{
min = 1;
max = 1000;
velocity = 1;
}
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
Vector2? fieldVal = (Vector2?)field.GetValue(config);
Vector2 vectorVal = fieldVal.HasValue ? fieldVal.Value : Vector2.Zero;
if (ImGui.DragFloat2(friendlyName + IDText(ID), ref vectorVal, velocity, min, max))
{
field.SetValue(config, vectorVal);
TriggerChangeEvent<Vector2>(config, field.Name, vectorVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class InputTextAttribute : ConfigAttribute
{
public int maxLength;
public bool formattable = true;
private string _searchText = "";
public InputTextAttribute(string friendlyName) : base(friendlyName)
{
this.friendlyName = friendlyName;
maxLength = 999;
}
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
string? fieldVal = (string?)field.GetValue(config);
string stringVal = fieldVal ?? "";
string? finalValue = null;
string popupId = ID != null ? "DelvUI_TextTagsList " + ID : "DelvUI_TextTagsList ##" + friendlyName;
if (!formattable)
{
if (ImGui.InputText(friendlyName + IDText(ID), ref stringVal))
{
finalValue = stringVal;
}
}
else
{
float scale = ImGuiHelpers.GlobalScale;
float width = ImGui.CalcItemWidth();
float height = Math.Max(24 * scale, ImGui.CalcTextSize(stringVal, false, width).Y + 6 * scale);
Vector2 size = new Vector2(width, height);
if (ImGui.InputTextMultiline(friendlyName + IDText(ID), ref stringVal, maxLength, size, ImGuiInputTextFlags.AllowTabInput))
{
finalValue = stringVal;
}
// text tags
ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (ImGui.Button(FontAwesomeIcon.Pen.ToIconString() + "##" + ID))
{
ImGui.OpenPopup(popupId);
}
ImGui.PopFont();
ImGuiHelper.SetTooltip("Text Tags");
}
var selectedTag = ImGuiHelper.DrawTextTagsList(popupId, ref _searchText);
if (selectedTag != null)
{
finalValue = stringVal + selectedTag;
}
if (finalValue != null)
{
field.SetValue(config, finalValue);
TriggerChangeEvent<string>(config, field.Name, finalValue);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class ColorEdit4Attribute : ConfigAttribute
{
public ColorEdit4Attribute(string friendlyName) : base(friendlyName) { }
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
PluginConfigColor? colorVal = (PluginConfigColor?)field.GetValue(config);
Vector4 vector = (colorVal != null ? colorVal.Vector : Vector4.Zero);
if (ImGui.ColorEdit4(friendlyName + IDText(ID), ref vector, ImGuiColorEditFlags.AlphaPreview | ImGuiColorEditFlags.AlphaBar))
{
if (colorVal is null)
{
return false;
}
colorVal.Vector = vector;
field.SetValue(config, colorVal);
TriggerChangeEvent<PluginConfigColor>(config, field.Name, colorVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class ComboAttribute : ConfigAttribute
{
public string[] options;
public ComboAttribute(string friendlyName, params string[] options) : base(friendlyName)
{
this.options = options;
}
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
object? fieldVal = field.GetValue(config);
int intVal = 0;
if (fieldVal != null)
{
intVal = (int)fieldVal;
}
if (ImGui.Combo(friendlyName + IDText(ID), ref intVal, options, 4))
{
field.SetValue(config, intVal);
TriggerChangeEvent<int>(config, field.Name, intVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class DragDropHorizontalAttribute : ConfigAttribute
{
public string[] names;
public DragDropHorizontalAttribute(string friendlyName, params string[] names) : base(friendlyName)
{
this.names = names;
}
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
ImGui.Text(friendlyName);
int[]? fieldVal = (int[]?)field.GetValue(config);
int[] order = fieldVal ?? Array.Empty<int>();
for (int i = 0; i < order.Length; i++)
{
ImGui.SameLine();
ImGui.Button(names[order[i]], new Vector2(100, 25));
if (ImGui.IsItemActive())
{
float drag_dx = ImGui.GetMouseDragDelta(ImGuiMouseButton.Left).X;
if ((drag_dx > 80.0f && i < order.Length - 1))
{
var _curri = order[i];
order[i] = order[i + 1];
order[i + 1] = _curri;
field.SetValue(config, order);
ImGui.ResetMouseDragDelta();
}
else if ((drag_dx < -80.0f && i > 0))
{
var _curri = order[i];
order[i] = order[i - 1];
order[i - 1] = _curri;
field.SetValue(config, order);
ImGui.ResetMouseDragDelta();
}
TriggerChangeEvent<int[]>(config, field.Name, order);
return true;
}
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class FontAttribute : ConfigAttribute
{
public FontAttribute(string friendlyName = "Font and Size") : base(friendlyName) { }
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
var fontsConfig = ConfigurationManager.Instance.GetConfigObject<FontsConfig>();
if (fontsConfig == null)
{
return false;
}
string? stringVal = (string?)field.GetValue(config);
int index = stringVal == null || stringVal.Length == 0 || !fontsConfig.Fonts.ContainsKey(stringVal) ? -1 :
fontsConfig.Fonts.IndexOfKey(stringVal);
if (index == -1)
{
if (fontsConfig.Fonts.ContainsKey(FontsConfig.DefaultBigFontKey))
{
index = fontsConfig.Fonts.IndexOfKey(FontsConfig.DefaultBigFontKey);
}
else
{
index = 0;
}
}
var options = fontsConfig.Fonts.Values.Select(fontData => fontData.Name + " " + fontData.Size.ToString()).ToArray();
if (ImGui.Combo(friendlyName + IDText(ID), ref index, options, 4))
{
stringVal = fontsConfig.Fonts.Keys[index];
field.SetValue(config, stringVal);
TriggerChangeEvent<string>(config, field.Name, stringVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class BarTextureAttribute : ConfigAttribute
{
public BarTextureAttribute(string friendlyName = "Bar Texture") : base(friendlyName) { }
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
if (BarTexturesManager.Instance == null)
{
return false;
}
List<string> textures = BarTexturesManager.Instance.BarTextureNames.ToList();
string? stringVal = (string?)field.GetValue(config);
int index = 0;
if (stringVal != null && stringVal.Length > 0 && textures.Contains(stringVal))
{
index = textures.IndexOf(stringVal);
}
string[] options = textures.ToArray();
if (ImGui.Combo(friendlyName + IDText(ID), ref index, options, 10))
{
stringVal = options[index];
field.SetValue(config, stringVal);
TriggerChangeEvent<string>(config, field.Name, stringVal);
return true;
}
return false;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class AnchorAttribute : ComboAttribute
{
public AnchorAttribute(string friendlyName)
: base(friendlyName, new string[] { "Center", "Left", "Right", "Top", "TopLeft", "TopRight", "Bottom", "BottomLeft", "BottomRight" })
{
}
}
[AttributeUsage(AttributeTargets.Field)]
public class BarTextureDrawModeAttribute : ComboAttribute
{
public BarTextureDrawModeAttribute(string friendlyName)
: base(friendlyName, new string[] { "Stretch", "Repeat Horizontal", "Repeat Vertical", "Repeat" })
{
}
}
[AttributeUsage(AttributeTargets.Field)]
public class StrataLevelAttribute : ConfigAttribute
{
private string[] options = { "Lowest", "Low", "Mid-Low", "Mid", "Mid-High", "High", "Highest" };
public StrataLevelAttribute(string friendlyName) : base(friendlyName)
{
}
public override bool DrawField(FieldInfo field, PluginConfigObject config, string? ID, bool collapsingHeader)
{
object? fieldVal = field.GetValue(config);
int intVal = 0;
if (fieldVal != null)
{
intVal = (int)fieldVal;
}
if (ImGui.Combo(friendlyName + IDText(ID), ref intVal, options, 4))
{
field.SetValue(config, (StrataLevel?)intVal);
TriggerChangeEvent<int>(config, field.Name, intVal);
ConfigurationManager.Instance?.OnStrataLevelChanged(config);
return true;
}
return false;
}
}
#endregion
#region field ordering attributes
[AttributeUsage(AttributeTargets.Field)]
public class OrderAttribute : Attribute
{
public int pos;
public string? collapseWith = "Enabled";
public OrderAttribute(int pos)
{
this.pos = pos;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class NestedConfigAttribute : OrderAttribute
{
public string friendlyName;
public bool separator = false;
public bool spacing = true;
public bool nest = true;
public bool collapsingHeader = true;
public NestedConfigAttribute(string friendlyName, int pos) : base(pos)
{
this.friendlyName = friendlyName;
}
}
#endregion
}