feat: add element previews that can be dragged
This commit is contained in:
parent
ac4739a05d
commit
6125c60ab8
|
@ -61,6 +61,9 @@ namespace HUD_Manager {
|
|||
private HudConditionMatch? _editingCondition;
|
||||
private bool _scrollToAdd;
|
||||
|
||||
private HashSet<ElementKind> Previews { get; } = new();
|
||||
private HashSet<ElementKind> UpdatePreviews { get; } = new();
|
||||
|
||||
public PluginUi(Plugin plugin) {
|
||||
this.Plugin = plugin;
|
||||
}
|
||||
|
@ -69,6 +72,175 @@ namespace HUD_Manager {
|
|||
this.SettingsVisible = true;
|
||||
}
|
||||
|
||||
private static Tuple<Vector2, Vector2> CalcPosAndSize(Element element) {
|
||||
// get X & Y coords from the element, which are percentages (0 - 100)
|
||||
var percentagePos = new Vector2(element.X, element.Y);
|
||||
|
||||
// get size in pixels
|
||||
var size = new Vector2(element.Width, element.Height);
|
||||
// scale size according to the element's scale
|
||||
size.X = (float) Math.Round(size.X * element.Scale);
|
||||
size.Y = (float) Math.Round(size.Y * element.Scale);
|
||||
|
||||
// convert the percentages into pixels
|
||||
var screen = ImGui.GetIO().DisplaySize;
|
||||
var pixelPos = new Vector2(
|
||||
(float) Math.Round(percentagePos.X * screen.X / 100),
|
||||
(float) Math.Round(percentagePos.Y * screen.Y / 100)
|
||||
);
|
||||
|
||||
// split the measured from into x and y parts
|
||||
var (xMeasure, yMeasure) = element.MeasuredFrom.ToParts();
|
||||
|
||||
// determine subtraction values to make the coords point to the top left
|
||||
var subX = xMeasure switch {
|
||||
MeasuredX.Left => 0,
|
||||
MeasuredX.Middle => size.X / 2,
|
||||
MeasuredX.Right => size.X,
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
|
||||
var subY = yMeasure switch {
|
||||
MeasuredY.Top => 0,
|
||||
MeasuredY.Middle => size.Y / 2,
|
||||
MeasuredY.Bottom => size.Y,
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
|
||||
// transform coords to top left for ImGui
|
||||
pixelPos.X -= subX;
|
||||
pixelPos.Y -= subY;
|
||||
|
||||
// round the coords
|
||||
pixelPos.X = (float) Math.Round(pixelPos.X);
|
||||
pixelPos.Y = (float) Math.Round(pixelPos.Y);
|
||||
|
||||
return Tuple.Create(pixelPos, size);
|
||||
}
|
||||
|
||||
private static Vector2 ConvertImGuiPos(Element element, Vector2 im) {
|
||||
// get the coordinates in pixels
|
||||
var pos = new Vector2(im.X, im.Y);
|
||||
|
||||
// get the size of the element
|
||||
var size = new Vector2(element.Width, element.Height);
|
||||
// scale the size of the element
|
||||
size.X = (float) Math.Round(size.X * element.Scale);
|
||||
size.Y = (float) Math.Round(size.Y * element.Scale);
|
||||
|
||||
// split the measured from into x and y parts
|
||||
var (xMeasure, yMeasure) = element.MeasuredFrom.ToParts();
|
||||
|
||||
// determine how much to add to convert top left coords into the element's system
|
||||
var addX = xMeasure switch {
|
||||
MeasuredX.Left => 0,
|
||||
MeasuredX.Middle => size.X / 2,
|
||||
MeasuredX.Right => size.X,
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
|
||||
var addY = yMeasure switch {
|
||||
MeasuredY.Top => 0,
|
||||
MeasuredY.Middle => size.Y / 2,
|
||||
MeasuredY.Bottom => size.Y,
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
|
||||
// convert from top left to given type
|
||||
pos.X += addX;
|
||||
pos.Y += addY;
|
||||
|
||||
// switch (element.MeasuredFrom) {
|
||||
// case MeasuredFrom.TopLeft:
|
||||
// // already top left
|
||||
// break;
|
||||
// case MeasuredFrom.TopMiddle:
|
||||
// pos.X += size.X / 2;
|
||||
// break;
|
||||
// case MeasuredFrom.TopRight:
|
||||
// pos.X += size.X;
|
||||
// break;
|
||||
// case MeasuredFrom.MiddleLeft:
|
||||
// pos.Y += size.Y / 2;
|
||||
// break;
|
||||
// case MeasuredFrom.Middle:
|
||||
// pos.X += size.X / 2;
|
||||
// pos.Y += size.Y / 2;
|
||||
// break;
|
||||
// case MeasuredFrom.MiddleRight:
|
||||
// pos.X += size.X;
|
||||
// pos.Y += size.Y / 2;
|
||||
// break;
|
||||
// case MeasuredFrom.BottomLeft:
|
||||
// pos.Y += size.Y;
|
||||
// break;
|
||||
// case MeasuredFrom.BottomMiddle:
|
||||
// pos.X += size.X / 2;
|
||||
// pos.Y += size.Y;
|
||||
// break;
|
||||
// case MeasuredFrom.BottomRight:
|
||||
// pos.X += size.X;
|
||||
// pos.Y += size.Y;
|
||||
// break;
|
||||
// default:
|
||||
// throw new ArgumentOutOfRangeException();
|
||||
// }
|
||||
|
||||
// convert the pixels into percentages
|
||||
var screen = ImGui.GetIO().DisplaySize;
|
||||
pos.X /= screen.X / 100;
|
||||
pos.Y /= screen.Y / 100;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
private void DrawPreviews(ref bool update) {
|
||||
const float tolerance = 0.0001f;
|
||||
const ImGuiWindowFlags flags = ImGuiWindowFlags.NoTitleBar
|
||||
| ImGuiWindowFlags.NoResize
|
||||
| ImGuiWindowFlags.NoFocusOnAppearing
|
||||
| ImGuiWindowFlags.NoScrollbar;
|
||||
|
||||
if (this._selectedEditLayout == Guid.Empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.Plugin.Config.Layouts.TryGetValue(this._selectedEditLayout, out var layout)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var element in layout.Elements.Values) {
|
||||
if (!this.Previews.Contains(element.Id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var (pos, size) = CalcPosAndSize(element);
|
||||
if (this.UpdatePreviews.Remove(element.Id)) {
|
||||
ImGui.SetNextWindowPos(pos);
|
||||
} else {
|
||||
ImGui.SetNextWindowPos(pos, ImGuiCond.Appearing);
|
||||
}
|
||||
|
||||
ImGui.SetNextWindowSize(size);
|
||||
|
||||
if (!ImGui.Begin($"##uimanager-preview-{element.Id}", flags)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted(element.Id.LocalisedName(this.Plugin.Interface.Data));
|
||||
|
||||
// determine if the window has moved and update if it has
|
||||
var newPos = ConvertImGuiPos(element, ImGui.GetWindowPos());
|
||||
if (Math.Abs(newPos.X - element.X) > tolerance || Math.Abs(newPos.Y - element.Y) > tolerance) {
|
||||
element.X = newPos.X;
|
||||
element.Y = newPos.Y;
|
||||
update = true;
|
||||
}
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSettings() {
|
||||
if (!this.SettingsVisible) {
|
||||
return;
|
||||
|
@ -198,6 +370,8 @@ namespace HUD_Manager {
|
|||
|
||||
var update = false;
|
||||
|
||||
this.DrawPreviews(ref update);
|
||||
|
||||
ImGui.TextUnformatted("Layout");
|
||||
|
||||
var nodes = Node<SavedLayout>.BuildTree(this.Plugin.Config.Layouts);
|
||||
|
@ -397,7 +571,16 @@ namespace HUD_Manager {
|
|||
|
||||
ImGui.TextUnformatted("Control");
|
||||
|
||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X - 30);
|
||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetStyle().ItemSpacing.X * 6);
|
||||
if (IconButton(FontAwesomeIcon.Search, $"uimanager-preview-element-{kind}")) {
|
||||
if (this.Previews.Contains(kind)) {
|
||||
this.Previews.Remove(kind);
|
||||
} else {
|
||||
this.Previews.Add(kind);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X * 3);
|
||||
if (IconButton(FontAwesomeIcon.TrashAlt, $"uimanager-remove-element-{kind}")) {
|
||||
toRemove.Add(kind);
|
||||
}
|
||||
|
@ -455,6 +638,7 @@ namespace HUD_Manager {
|
|||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
DrawEnabledCheckbox(element.Id, ElementComponent.X);
|
||||
|
@ -466,7 +650,11 @@ namespace HUD_Manager {
|
|||
if (ImGui.DragFloat($"##x-{kind}", ref x, this._dragSpeed)) {
|
||||
element.X = x;
|
||||
update = true;
|
||||
if (this.Previews.Contains(kind)) {
|
||||
this.UpdatePreviews.Add(kind);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
DrawEnabledCheckbox(element.Id, ElementComponent.Y);
|
||||
|
@ -477,7 +665,11 @@ namespace HUD_Manager {
|
|||
if (ImGui.DragFloat($"##y-{kind}", ref y, this._dragSpeed)) {
|
||||
element.Y = y;
|
||||
update = true;
|
||||
if (this.Previews.Contains(kind)) {
|
||||
this.UpdatePreviews.Add(kind);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
} else {
|
||||
var screen = ImGui.GetIO().DisplaySize;
|
||||
|
@ -487,7 +679,11 @@ namespace HUD_Manager {
|
|||
if (ImGui.InputInt($"##x-{kind}", ref x)) {
|
||||
element.X = x / screen.X * 100;
|
||||
update = true;
|
||||
if (this.Previews.Contains(kind)) {
|
||||
this.UpdatePreviews.Add(kind);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
DrawEnabledCheckbox(element.Id, ElementComponent.Y);
|
||||
|
@ -498,7 +694,11 @@ namespace HUD_Manager {
|
|||
if (ImGui.InputInt($"##y-{kind}", ref y)) {
|
||||
element.Y = y / screen.Y * 100;
|
||||
update = true;
|
||||
if (this.Previews.Contains(kind)) {
|
||||
this.UpdatePreviews.Add(kind);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
}
|
||||
|
||||
|
@ -519,6 +719,7 @@ namespace HUD_Manager {
|
|||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
if (!kind.IsJobGauge()) {
|
||||
|
@ -531,6 +732,7 @@ namespace HUD_Manager {
|
|||
element.Opacity = (byte) opacity;
|
||||
update = true;
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
}
|
||||
|
||||
|
@ -547,6 +749,7 @@ namespace HUD_Manager {
|
|||
targetBarOpts.ShowIndependently = independent;
|
||||
update = true;
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
}
|
||||
|
||||
|
@ -570,6 +773,7 @@ namespace HUD_Manager {
|
|||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
}
|
||||
|
||||
|
@ -593,6 +797,7 @@ namespace HUD_Manager {
|
|||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
ImGui.NextColumn();
|
||||
|
@ -612,6 +817,7 @@ namespace HUD_Manager {
|
|||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
ImGui.NextColumn();
|
||||
|
@ -624,6 +830,7 @@ namespace HUD_Manager {
|
|||
statusOpts.Gamepad = focusable ? StatusGamepad.Focusable : StatusGamepad.NonFocusable;
|
||||
update = true;
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
}
|
||||
|
||||
|
@ -641,6 +848,7 @@ namespace HUD_Manager {
|
|||
hotbarOpts.Index = (byte) Math.Max(0, Math.Min(9, hotbarIndex - 1));
|
||||
update = true;
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
}
|
||||
|
||||
|
@ -662,6 +870,7 @@ namespace HUD_Manager {
|
|||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
}
|
||||
|
||||
|
@ -678,6 +887,7 @@ namespace HUD_Manager {
|
|||
gaugeOpts.Style = simple ? GaugeStyle.Simple : GaugeStyle.Normal;
|
||||
update = true;
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace HUD_Manager.Structs {
|
||||
using System;
|
||||
|
||||
namespace HUD_Manager.Structs {
|
||||
public enum MeasuredFrom : byte {
|
||||
TopLeft = 0,
|
||||
TopMiddle = 1,
|
||||
|
@ -10,4 +12,33 @@
|
|||
BottomMiddle = 7,
|
||||
BottomRight = 8,
|
||||
}
|
||||
|
||||
public static class MeasureFromExt {
|
||||
public static Tuple<MeasuredX, MeasuredY> ToParts(this MeasuredFrom measured) {
|
||||
return measured switch {
|
||||
MeasuredFrom.TopLeft => Tuple.Create(MeasuredX.Left, MeasuredY.Top),
|
||||
MeasuredFrom.TopMiddle => Tuple.Create(MeasuredX.Middle, MeasuredY.Top),
|
||||
MeasuredFrom.TopRight => Tuple.Create(MeasuredX.Right, MeasuredY.Top),
|
||||
MeasuredFrom.MiddleLeft => Tuple.Create(MeasuredX.Left, MeasuredY.Middle),
|
||||
MeasuredFrom.Middle => Tuple.Create(MeasuredX.Middle, MeasuredY.Middle),
|
||||
MeasuredFrom.MiddleRight => Tuple.Create(MeasuredX.Right, MeasuredY.Middle),
|
||||
MeasuredFrom.BottomLeft => Tuple.Create(MeasuredX.Left, MeasuredY.Bottom),
|
||||
MeasuredFrom.BottomMiddle => Tuple.Create(MeasuredX.Middle, MeasuredY.Bottom),
|
||||
MeasuredFrom.BottomRight => Tuple.Create(MeasuredX.Right, MeasuredY.Bottom),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(measured), measured, null),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum MeasuredX {
|
||||
Left,
|
||||
Middle,
|
||||
Right,
|
||||
}
|
||||
|
||||
public enum MeasuredY {
|
||||
Top,
|
||||
Middle,
|
||||
Bottom,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue