Initial release: HSUI v1.0.0.0 - HUD replacement with configurable hotbars
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
using HSUI.Config;
|
||||
using HSUI.Config.Attributes;
|
||||
using System.Numerics;
|
||||
using HSUI.Interface.GeneralElements;
|
||||
using HSUI.Enums;
|
||||
|
||||
namespace HSUI.Interface.Bars
|
||||
{
|
||||
[Exportable(false)]
|
||||
public class BarConfig : AnchorablePluginConfigObject
|
||||
{
|
||||
[ColorEdit4("Background Color")]
|
||||
[Order(16)]
|
||||
public PluginConfigColor BackgroundColor = new PluginConfigColor(new Vector4(0f / 255f, 0f / 255f, 0f / 255f, 50f / 100f));
|
||||
|
||||
[ColorEdit4("Fill Color")]
|
||||
[Order(25)]
|
||||
public PluginConfigColor FillColor;
|
||||
|
||||
[Combo("Fill Direction", new string[] { "Left", "Right", "Up", "Down" })]
|
||||
[Order(30)]
|
||||
public BarDirection FillDirection;
|
||||
|
||||
[BarTexture("Bar Texture", spacing = true, help = "Default means the bar will be drawn using the global gradient configuration for bars found in Colors > Misc.")]
|
||||
[Order(31)]
|
||||
public string BarTextureName = "";
|
||||
|
||||
[BarTextureDrawMode("Draw Mode")]
|
||||
[Order(32)]
|
||||
public BarTextureDrawMode BarTextureDrawMode = BarTextureDrawMode.Stretch;
|
||||
|
||||
[Checkbox("Show Border", spacing = true)]
|
||||
[Order(35)]
|
||||
public bool DrawBorder = true;
|
||||
|
||||
[ColorEdit4("Border Color")]
|
||||
[Order(36, collapseWith = nameof(DrawBorder))]
|
||||
public PluginConfigColor BorderColor = new PluginConfigColor(new Vector4(0f / 255f, 0f / 255f, 0f / 255f, 100f / 100f));
|
||||
|
||||
[DragInt("Border Thickness", min = 1, max = 10)]
|
||||
[Order(37, collapseWith = nameof(DrawBorder))]
|
||||
public int BorderThickness = 1;
|
||||
|
||||
[NestedConfig("Shadow", 40, spacing = true)]
|
||||
public ShadowConfig ShadowConfig = new ShadowConfig() { Enabled = false };
|
||||
|
||||
[Checkbox("Hide When Inactive", spacing = true)]
|
||||
[Order(41)]
|
||||
public bool HideWhenInactive = false;
|
||||
|
||||
public BarConfig(Vector2 position, Vector2 size, PluginConfigColor fillColor, BarDirection fillDirection = BarDirection.Right)
|
||||
{
|
||||
Position = position;
|
||||
Size = size;
|
||||
FillColor = fillColor;
|
||||
FillDirection = fillDirection;
|
||||
}
|
||||
}
|
||||
|
||||
[Exportable(false)]
|
||||
public class BarGlowConfig : PluginConfigObject
|
||||
{
|
||||
[ColorEdit4("Color")]
|
||||
[Order(5)]
|
||||
public PluginConfigColor Color = new PluginConfigColor(new Vector4(255f / 255f, 255f / 255f, 255f / 255f, 50f / 100f));
|
||||
|
||||
[DragInt("Size", min = 1, max = 100)]
|
||||
[Order(25)]
|
||||
public int Size = 1;
|
||||
}
|
||||
|
||||
public enum BarDirection
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using HSUI.Config;
|
||||
using HSUI.Enums;
|
||||
using HSUI.Helpers;
|
||||
using HSUI.Interface.GeneralElements;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HSUI.Interface.Bars
|
||||
{
|
||||
public class BarHud
|
||||
{
|
||||
private string ID { get; set; }
|
||||
|
||||
private Rect BackgroundRect { get; set; } = new Rect();
|
||||
|
||||
private List<Rect> ForegroundRects { get; set; } = new List<Rect>();
|
||||
|
||||
private List<LabelHud> LabelHuds { get; set; } = new List<LabelHud>();
|
||||
|
||||
private bool DrawBorder { get; set; }
|
||||
|
||||
private PluginConfigColor? BorderColor { get; set; }
|
||||
|
||||
private int BorderThickness { get; set; }
|
||||
|
||||
private DrawAnchor Anchor { get; set; }
|
||||
|
||||
private IGameObject? Actor { get; set; }
|
||||
|
||||
private PluginConfigColor? GlowColor { get; set; }
|
||||
|
||||
private int GlowSize { get; set; }
|
||||
|
||||
private float? Current;
|
||||
private float? Max;
|
||||
|
||||
private ShadowConfig? ShadowConfig { get; set; }
|
||||
|
||||
private string? BarTextureName { get; set; }
|
||||
private BarTextureDrawMode BarTextureDrawMode { get; set; }
|
||||
|
||||
public bool NeedsInputs = false;
|
||||
|
||||
public BarHud(
|
||||
string id,
|
||||
bool drawBorder = true,
|
||||
PluginConfigColor? borderColor = null,
|
||||
int borderThickness = 1,
|
||||
DrawAnchor anchor = DrawAnchor.TopLeft,
|
||||
IGameObject? actor = null,
|
||||
PluginConfigColor? glowColor = null,
|
||||
int? glowSize = 1,
|
||||
float? current = null,
|
||||
float? max = null,
|
||||
ShadowConfig? shadowConfig = null,
|
||||
string? barTextureName = null,
|
||||
BarTextureDrawMode barTextureDrawMode = BarTextureDrawMode.Stretch)
|
||||
{
|
||||
ID = id;
|
||||
DrawBorder = drawBorder;
|
||||
BorderColor = borderColor;
|
||||
BorderThickness = borderThickness;
|
||||
Anchor = anchor;
|
||||
Actor = actor;
|
||||
GlowColor = glowColor;
|
||||
GlowSize = glowSize ?? 1;
|
||||
Current = current;
|
||||
Max = max;
|
||||
ShadowConfig = shadowConfig;
|
||||
BarTextureName = barTextureName;
|
||||
BarTextureDrawMode = barTextureDrawMode;
|
||||
}
|
||||
|
||||
public BarHud(BarConfig config, IGameObject? actor = null, BarGlowConfig? glowConfig = null, float? current = null, float? max = null)
|
||||
: this(config.ID,
|
||||
config.DrawBorder,
|
||||
config.BorderColor,
|
||||
config.BorderThickness,
|
||||
config.Anchor,
|
||||
actor,
|
||||
glowConfig?.Color,
|
||||
glowConfig?.Size,
|
||||
current,
|
||||
max,
|
||||
null,
|
||||
config.BarTextureName,
|
||||
config.BarTextureDrawMode)
|
||||
{
|
||||
BackgroundRect = new Rect(config.Position, config.Size, config.BackgroundColor);
|
||||
ShadowConfig = config.ShadowConfig;
|
||||
}
|
||||
|
||||
public BarHud SetBackground(Rect rect)
|
||||
{
|
||||
BackgroundRect = rect;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BarHud AddForegrounds(params Rect[] rects)
|
||||
{
|
||||
ForegroundRects.AddRange(rects);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BarHud AddLabels(params LabelConfig[]? labels)
|
||||
{
|
||||
if (labels != null)
|
||||
{
|
||||
foreach (LabelConfig config in labels)
|
||||
{
|
||||
var labelHud = new LabelHud(config);
|
||||
LabelHuds.Add(labelHud);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public BarHud SetGlow(PluginConfigColor color, int size = 1)
|
||||
{
|
||||
GlowColor = color;
|
||||
GlowSize = size;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Draw(Vector2 origin)
|
||||
{
|
||||
var barPos = Utils.GetAnchoredPosition(origin, BackgroundRect.Size, Anchor);
|
||||
var backgroundPos = barPos + BackgroundRect.Position;
|
||||
|
||||
DrawRects(barPos, backgroundPos);
|
||||
|
||||
// labels
|
||||
foreach (LabelHud label in LabelHuds)
|
||||
{
|
||||
label.Draw(backgroundPos, BackgroundRect.Size, Actor, null, (uint?)Current, (uint?)Max);
|
||||
}
|
||||
}
|
||||
|
||||
public List<(StrataLevel, Action)> GetDrawActions(Vector2 origin, StrataLevel strataLevel)
|
||||
{
|
||||
List<(StrataLevel, Action)> drawActions = new List<(StrataLevel, Action)>();
|
||||
|
||||
var barPos = Utils.GetAnchoredPosition(origin, BackgroundRect.Size, Anchor);
|
||||
var backgroundPos = barPos + BackgroundRect.Position;
|
||||
|
||||
drawActions.Add((strataLevel, () =>
|
||||
{
|
||||
DrawRects(barPos, backgroundPos);
|
||||
}
|
||||
));
|
||||
|
||||
// labels
|
||||
foreach (LabelHud label in LabelHuds)
|
||||
{
|
||||
drawActions.Add((label.GetConfig().StrataLevel, () =>
|
||||
{
|
||||
label.Draw(backgroundPos, BackgroundRect.Size, Actor, null, (uint?)Current, (uint?)Max);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
return drawActions;
|
||||
}
|
||||
|
||||
private void DrawRects(Vector2 barPos, Vector2 backgroundPos)
|
||||
{
|
||||
DrawHelper.DrawInWindow(ID, backgroundPos, BackgroundRect.Size, NeedsInputs, (drawList) =>
|
||||
{
|
||||
// Draw background
|
||||
drawList.AddRectFilled(backgroundPos, backgroundPos + BackgroundRect.Size, BackgroundRect.Color.Base);
|
||||
|
||||
// Draw Shadow
|
||||
if (ShadowConfig != null && ShadowConfig.Enabled)
|
||||
{
|
||||
// Right Side
|
||||
drawList.AddRectFilled(backgroundPos + new Vector2(BackgroundRect.Size.X, ShadowConfig.Offset), backgroundPos + BackgroundRect.Size + new Vector2(ShadowConfig.Offset, ShadowConfig.Offset) + new Vector2(ShadowConfig.Thickness - 1, ShadowConfig.Thickness - 1), ShadowConfig.Color.Base);
|
||||
|
||||
// Bottom Size
|
||||
drawList.AddRectFilled(backgroundPos + new Vector2(ShadowConfig.Offset, BackgroundRect.Size.Y), backgroundPos + BackgroundRect.Size + new Vector2(ShadowConfig.Offset, ShadowConfig.Offset) + new Vector2(ShadowConfig.Thickness - 1, ShadowConfig.Thickness - 1), ShadowConfig.Color.Base);
|
||||
}
|
||||
|
||||
// Draw foregrounds
|
||||
foreach (Rect rect in ForegroundRects)
|
||||
{
|
||||
DrawHelper.DrawBarTexture(barPos + rect.Position, rect.Size, rect.Color, BarTextureName, BarTextureDrawMode, drawList);
|
||||
}
|
||||
|
||||
// Draw Border
|
||||
if (DrawBorder)
|
||||
{
|
||||
drawList.AddRect(backgroundPos, backgroundPos + BackgroundRect.Size, BorderColor?.Base ?? 0xFF000000, 0, ImDrawFlags.None, BorderThickness);
|
||||
}
|
||||
|
||||
// Draw Glow
|
||||
if (GlowColor != null)
|
||||
{
|
||||
var glowPosition = new Vector2(backgroundPos.X - 1, backgroundPos.Y - 1);
|
||||
var glowSize = new Vector2(BackgroundRect.Size.X + 2, BackgroundRect.Size.Y + 2);
|
||||
|
||||
drawList.AddRect(glowPosition, glowPosition + glowSize, GlowColor.Base, 0, ImDrawFlags.None, GlowSize);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,441 @@
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Game.ClientState.Statuses;
|
||||
using HSUI.Config;
|
||||
using HSUI.Enums;
|
||||
using HSUI.Helpers;
|
||||
using HSUI.Interface.GeneralElements;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HSUI.Interface.Bars
|
||||
{
|
||||
public class BarUtilities
|
||||
{
|
||||
public static BarHud GetProgressBar(ProgressBarConfig config, float current, float max, float min = 0f, IGameObject? actor = null, PluginConfigColor? fillColor = null, BarGlowConfig? barGlowConfig = null)
|
||||
{
|
||||
return GetProgressBar(config, config.ThresholdConfig, new LabelConfig[] { config.Label }, current, max, min, actor, fillColor, barGlowConfig);
|
||||
}
|
||||
|
||||
public static BarHud GetProgressBar(
|
||||
BarConfig config,
|
||||
ThresholdConfig? thresholdConfig,
|
||||
LabelConfig[]? labelConfigs,
|
||||
float current,
|
||||
float max,
|
||||
float min = 0f,
|
||||
IGameObject? actor = null,
|
||||
PluginConfigColor? fillColor = null,
|
||||
BarGlowConfig? glowConfig = null,
|
||||
PluginConfigColor? backgroundColor = null
|
||||
)
|
||||
{
|
||||
BarHud bar = new(config, actor, glowConfig, current, max);
|
||||
|
||||
PluginConfigColor color = fillColor ?? config.FillColor;
|
||||
if (thresholdConfig != null)
|
||||
{
|
||||
color = thresholdConfig.ChangeColor && thresholdConfig.IsActive(current) ? thresholdConfig.Color : color;
|
||||
}
|
||||
|
||||
Rect foreground = GetFillRect(config.Position, config.Size, config.FillDirection, color, current, max, min);
|
||||
bar.AddForegrounds(foreground);
|
||||
bar.AddLabels(labelConfigs);
|
||||
|
||||
if (backgroundColor != null)
|
||||
{
|
||||
Rect bg = new Rect(config.Position, config.Size, backgroundColor);
|
||||
bar.SetBackground(bg);
|
||||
}
|
||||
|
||||
AddThresholdMarker(bar, config, thresholdConfig, max, min);
|
||||
|
||||
return bar;
|
||||
}
|
||||
|
||||
public static BarHud? GetProcBar(
|
||||
ProgressBarConfig config,
|
||||
IPlayerCharacter player,
|
||||
uint statusId,
|
||||
float maxDuration,
|
||||
bool trackDuration = true)
|
||||
{
|
||||
return GetProcBar(config, player, new List<uint> { statusId }, new List<float> { maxDuration }, trackDuration);
|
||||
}
|
||||
|
||||
public static BarHud? GetProcBar(
|
||||
ProgressBarConfig config,
|
||||
IPlayerCharacter player,
|
||||
List<uint> statusIDs,
|
||||
List<float> maxDurations,
|
||||
bool trackDuration = true)
|
||||
{
|
||||
if (statusIDs.Count == 0 || maxDurations.Count == 0) { return null; }
|
||||
|
||||
IStatus? status = Utils.StatusListForBattleChara(player).FirstOrDefault(o => statusIDs.Contains(o.StatusId));
|
||||
if (status == null && config.HideWhenInactive)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
float duration = Math.Abs(status?.RemainingTime ?? 0);
|
||||
|
||||
if (trackDuration)
|
||||
{
|
||||
int index = status != null ? statusIDs.IndexOf(status.StatusId) : 0;
|
||||
config.Label.SetValue(duration);
|
||||
return GetProgressBar(config, duration, maxDurations[index], 0, player);
|
||||
}
|
||||
|
||||
config.Label.SetText("");
|
||||
return GetBar(config, duration <= 0 ? 0 : 1, 1, 0);
|
||||
}
|
||||
|
||||
public static BarHud? GetDoTBar(
|
||||
ProgressBarConfig config,
|
||||
IPlayerCharacter player,
|
||||
IGameObject? target,
|
||||
uint statusId,
|
||||
float maxDuration)
|
||||
{
|
||||
return GetDoTBar(config, player, target, new List<uint> { statusId }, new List<float> { maxDuration });
|
||||
}
|
||||
|
||||
public static BarHud? GetDoTBar(
|
||||
ProgressBarConfig config,
|
||||
IPlayerCharacter player,
|
||||
IGameObject? target,
|
||||
List<uint> statusIDs,
|
||||
List<float> maxDurations)
|
||||
{
|
||||
if (statusIDs.Count == 0 || maxDurations.Count == 0) { return null; }
|
||||
|
||||
IStatus? status = null;
|
||||
|
||||
if (target != null && target is IBattleChara targetChara)
|
||||
{
|
||||
status = Utils.StatusListForBattleChara(targetChara).FirstOrDefault(o => o.SourceId == player.GameObjectId && statusIDs.Contains(o.StatusId));
|
||||
}
|
||||
|
||||
if (status == null && config.HideWhenInactive)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int index = status != null ? statusIDs.IndexOf(status.StatusId) : 0;
|
||||
float duration = Math.Abs(status?.RemainingTime ?? 0);
|
||||
float maxDuration = maxDurations[index];
|
||||
|
||||
config.Label.SetValue(duration);
|
||||
return GetProgressBar(config, duration, maxDuration, 0, player);
|
||||
}
|
||||
|
||||
private static void AddThresholdMarker(BarHud bar, BarConfig config, ThresholdConfig? thresholdConfig, float max, float min)
|
||||
{
|
||||
if (thresholdConfig == null || !thresholdConfig.Enabled || !thresholdConfig.ShowMarker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float thresholdPercent = Math.Clamp(thresholdConfig.Value / (max - min), 0f, 1f);
|
||||
Vector2 offset = GetFillDirectionOffset(
|
||||
new Vector2(config.Size.X * thresholdPercent, config.Size.Y * thresholdPercent),
|
||||
config.FillDirection
|
||||
);
|
||||
|
||||
Vector2 markerSize = config.FillDirection.IsHorizontal() ?
|
||||
new Vector2(thresholdConfig.MarkerSize, config.Size.Y) :
|
||||
new Vector2(config.Size.X, thresholdConfig.MarkerSize);
|
||||
|
||||
Vector2 markerPos = config.FillDirection.IsInverted() ?
|
||||
config.Position + GetFillDirectionOffset(config.Size, config.FillDirection) - offset :
|
||||
config.Position + offset;
|
||||
|
||||
Vector2 anchoredPos = Utils.GetAnchoredPosition(markerPos, markerSize, config.FillDirection.IsHorizontal() ? DrawAnchor.Top : DrawAnchor.Left);
|
||||
Rect marker = new(anchoredPos, markerSize, thresholdConfig.MarkerColor);
|
||||
bar.AddForegrounds(marker);
|
||||
}
|
||||
|
||||
// Tuple is <foregroundColor, percent fill, labels>
|
||||
public static BarHud[] GetChunkedBars(
|
||||
ChunkedBarConfig config,
|
||||
Tuple<PluginConfigColor, float, LabelConfig?>[] chunks,
|
||||
IGameObject? actor,
|
||||
BarGlowConfig glowConfig)
|
||||
{
|
||||
List<bool> chunksToGlowList = new();
|
||||
for (int i = 0; i < chunks.Length; i++)
|
||||
{
|
||||
chunksToGlowList.Add(chunks[i].Item2 >= 1f);
|
||||
}
|
||||
|
||||
return GetChunkedBars(config, chunks, actor, glowConfig, chunksToGlowList.ToArray());
|
||||
}
|
||||
|
||||
public static BarHud[] GetChunkedBars(
|
||||
ChunkedBarConfig config,
|
||||
Tuple<PluginConfigColor, float, LabelConfig?>[] chunks,
|
||||
IGameObject? actor,
|
||||
BarGlowConfig? glowConfig = null,
|
||||
bool[]? chunksToGlow = null)
|
||||
{
|
||||
BarHud[] bars = new BarHud[chunks.Length];
|
||||
Vector2 pos = Utils.GetAnchoredPosition(config.Position, config.Size, config.Anchor);
|
||||
|
||||
for (int i = 0; i < chunks.Length; i++)
|
||||
{
|
||||
Vector2 chunkPos, chunkSize;
|
||||
if (config.FillDirection.IsHorizontal())
|
||||
{
|
||||
chunkSize = new Vector2((config.Size.X - config.Padding * (chunks.Length - 1)) / chunks.Length, config.Size.Y);
|
||||
chunkPos = pos + new Vector2((chunkSize.X + config.Padding) * i, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
chunkSize = new Vector2(config.Size.X, (config.Size.Y - config.Padding * (chunks.Length - 1)) / chunks.Length);
|
||||
chunkPos = pos + new Vector2(0, (chunkSize.Y + config.Padding) * i);
|
||||
}
|
||||
|
||||
Rect background = new(chunkPos, chunkSize, config.BackgroundColor);
|
||||
Rect foreground = GetFillRect(chunkPos, chunkSize, config.FillDirection, chunks[i].Item1, chunks[i].Item2, 1f, 0f);
|
||||
BarGlowConfig? glow = (glowConfig?.Enabled == true && chunksToGlow?[i] == true) ? glowConfig : null;
|
||||
|
||||
bars[i] = new BarHud(config.ID + i,
|
||||
config.DrawBorder,
|
||||
config.BorderColor,
|
||||
config.BorderThickness,
|
||||
actor: actor,
|
||||
glowColor: glow?.Color,
|
||||
glowSize: glow?.Size,
|
||||
barTextureName: config.BarTextureName,
|
||||
barTextureDrawMode: config.BarTextureDrawMode,
|
||||
shadowConfig: config.ShadowConfig
|
||||
);
|
||||
bars[i].SetBackground(background);
|
||||
bars[i].AddForegrounds(foreground);
|
||||
|
||||
LabelConfig? label = chunks[i].Item3;
|
||||
if (label is not null)
|
||||
{
|
||||
bars[i].AddLabels(label);
|
||||
}
|
||||
}
|
||||
|
||||
return bars;
|
||||
}
|
||||
|
||||
public static BarHud[] GetChunkedBars(
|
||||
ChunkedBarConfig config,
|
||||
int chunks,
|
||||
float current,
|
||||
float max,
|
||||
float min = 0f,
|
||||
IGameObject? actor = null,
|
||||
LabelConfig?[]? labels = null,
|
||||
PluginConfigColor? fillColor = null,
|
||||
PluginConfigColor? partialFillColor = null,
|
||||
BarGlowConfig? glowConfig = null,
|
||||
bool[]? chunksToGlow = null)
|
||||
{
|
||||
float chunkRange = (max - min) / chunks;
|
||||
|
||||
var barChunks = new Tuple<PluginConfigColor, float, LabelConfig?>[chunks];
|
||||
for (int i = 0; i < chunks; i++)
|
||||
{
|
||||
int barIndex = config.FillDirection.IsInverted() ? chunks - i - 1 : i;
|
||||
float chunkMin = min + chunkRange * i;
|
||||
float chunkMax = min + chunkRange * (i + 1);
|
||||
float chunkPercent = Math.Clamp((current - chunkMin) / (chunkMax - chunkMin), 0f, 1f);
|
||||
|
||||
PluginConfigColor chunkColor = partialFillColor != null && current < chunkMax ? partialFillColor : fillColor ?? config.FillColor;
|
||||
barChunks[barIndex] = new Tuple<PluginConfigColor, float, LabelConfig?>(chunkColor, chunkPercent, labels?[i]);
|
||||
}
|
||||
|
||||
if (glowConfig != null && chunksToGlow == null)
|
||||
{
|
||||
return GetChunkedBars(config, barChunks, actor, glowConfig);
|
||||
}
|
||||
|
||||
return GetChunkedBars(config, barChunks, actor, glowConfig, chunksToGlow);
|
||||
}
|
||||
|
||||
public static BarHud[] GetChunkedProgressBars(
|
||||
ChunkedProgressBarConfig config,
|
||||
int chunks,
|
||||
float current,
|
||||
float max,
|
||||
float min = 0f,
|
||||
IGameObject? actor = null,
|
||||
BarGlowConfig? glowConfig = null,
|
||||
PluginConfigColor? fillColor = null,
|
||||
int thresholdChunk = 1,
|
||||
bool[]? chunksToGlow = null,
|
||||
int forceLabelIndex = -1)
|
||||
{
|
||||
var color = fillColor ?? config.FillColor;
|
||||
|
||||
if (config.UseChunks)
|
||||
{
|
||||
NumericLabelConfig?[] labels = new NumericLabelConfig?[chunks];
|
||||
for (int i = 0; i < chunks; i++)
|
||||
{
|
||||
float chunkRange = (max - min) / chunks;
|
||||
float chunkMin = min + chunkRange * i;
|
||||
float chunkMax = min + chunkRange * (i + 1);
|
||||
float chunkPercent = Math.Clamp((current - chunkMin) / (chunkMax - chunkMin), 0f, 1f);
|
||||
|
||||
NumericLabelConfig? label = config.Label;
|
||||
if (forceLabelIndex == -1)
|
||||
{
|
||||
switch (config.LabelMode)
|
||||
{
|
||||
case LabelMode.AllChunks:
|
||||
label = config.Label.Clone(i);
|
||||
label.SetValue(Math.Clamp(current - chunkMin, 0, chunkRange));
|
||||
break;
|
||||
case LabelMode.ActiveChunk:
|
||||
label = chunkPercent < 1f && chunkPercent > 0f ? config.Label.Clone(i) : null;
|
||||
break;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
label = forceLabelIndex == i ? config.Label : null;
|
||||
}
|
||||
|
||||
labels[i] = label;
|
||||
}
|
||||
|
||||
var partialColor = config.UsePartialFillColor ? config.PartialFillColor : null;
|
||||
return GetChunkedBars(config, chunks, current, max, min, actor, labels, color, partialColor, glowConfig, chunksToGlow);
|
||||
}
|
||||
|
||||
var threshold = GetThresholdConfigForChunk(config, thresholdChunk, chunks, min, max);
|
||||
BarHud bar = GetProgressBar(config, threshold, new LabelConfig[] { config.Label }, current, max, min, actor, color, glowConfig);
|
||||
return new BarHud[] { bar };
|
||||
}
|
||||
|
||||
public static Rect[] GetShieldForeground(
|
||||
ShieldConfig shieldConfig,
|
||||
Vector2 pos,
|
||||
Vector2 size,
|
||||
Vector2 healthFillSize,
|
||||
BarDirection fillDirection,
|
||||
float shieldPercent,
|
||||
float currentHp,
|
||||
float maxHp,
|
||||
PluginConfigColor? color = null)
|
||||
{
|
||||
float shieldValue = shieldPercent * maxHp;
|
||||
float overshield = shieldConfig.FillHealthFirst ? Math.Max(shieldValue + currentHp - maxHp, 0f) : shieldValue;
|
||||
float shieldSize = shieldConfig.Height;
|
||||
PluginConfigColor c = color ?? shieldConfig.Color;
|
||||
|
||||
if (!shieldConfig.HeightInPixels)
|
||||
{
|
||||
shieldSize = (fillDirection.IsHorizontal() ? size.Y : size.X) * shieldConfig.Height / 100f;
|
||||
}
|
||||
|
||||
var overshieldSize = fillDirection.IsHorizontal()
|
||||
? new Vector2(size.X, Math.Min(shieldSize, size.Y))
|
||||
: new Vector2(Math.Min(shieldSize, size.X), size.Y);
|
||||
|
||||
Rect overshieldFill = GetFillRect(pos, overshieldSize, fillDirection, c, overshield, maxHp);
|
||||
|
||||
if (shieldConfig.FillHealthFirst && currentHp < maxHp)
|
||||
{
|
||||
var shieldPos = fillDirection.IsInverted() ? pos : pos + GetFillDirectionOffset(healthFillSize, fillDirection);
|
||||
var shieldFillSize = size - GetFillDirectionOffset(healthFillSize, fillDirection);
|
||||
var healthFillShieldSize = fillDirection.IsHorizontal()
|
||||
? new Vector2(shieldFillSize.X, Math.Min(shieldSize, size.Y))
|
||||
: new Vector2(Math.Min(shieldSize, size.X), shieldFillSize.Y);
|
||||
|
||||
Rect shieldFill = GetFillRect(shieldPos, healthFillShieldSize, fillDirection, c, shieldValue - overshield, maxHp - currentHp, 0f);
|
||||
return new[] { overshieldFill, shieldFill };
|
||||
}
|
||||
|
||||
return new[] { overshieldFill };
|
||||
}
|
||||
|
||||
public static BarHud GetBar(
|
||||
BarConfig Config,
|
||||
float current,
|
||||
float max,
|
||||
float min = 0f,
|
||||
IGameObject? actor = null,
|
||||
PluginConfigColor? fillColor = null,
|
||||
BarGlowConfig? glowConfig = null,
|
||||
LabelConfig[]? labels = null)
|
||||
{
|
||||
Rect foreground = GetFillRect(Config.Position, Config.Size, Config.FillDirection, fillColor ?? Config.FillColor, current, max, min);
|
||||
|
||||
BarHud bar = new BarHud(Config, actor, glowConfig);
|
||||
bar.AddForegrounds(foreground);
|
||||
bar.AddLabels(labels);
|
||||
|
||||
return bar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the horizonal or vertical offset depending on the fill direction.
|
||||
/// </summary>
|
||||
public static Vector2 GetFillDirectionOffset(Vector2 size, BarDirection fillDirection)
|
||||
{
|
||||
return fillDirection.IsHorizontal() ? new(size.X, 0) : new(0, size.Y);
|
||||
}
|
||||
|
||||
public static Rect GetFillRect(Vector2 pos, Vector2 size, BarDirection fillDirection, PluginConfigColor color, float current, float max, float min = 0f)
|
||||
{
|
||||
float fillPercent = max == 0 ? 1f : Math.Clamp((current - min) / (max - min), 0f, 1f);
|
||||
|
||||
Vector2 fillPos = Vector2.Zero;
|
||||
Vector2 fillSize = fillDirection.IsHorizontal() ? new(size.X * fillPercent, size.Y) : new(size.X, size.Y * fillPercent);
|
||||
if (fillDirection == BarDirection.Left)
|
||||
{
|
||||
fillPos = Utils.GetAnchoredPosition(new(size.X, 0), fillSize, DrawAnchor.TopRight);
|
||||
}
|
||||
else if (fillDirection == BarDirection.Up)
|
||||
{
|
||||
fillPos = Utils.GetAnchoredPosition(new(0, size.Y), fillSize, DrawAnchor.BottomLeft);
|
||||
}
|
||||
|
||||
return new Rect(pos + fillPos, fillSize, color);
|
||||
}
|
||||
|
||||
public static ThresholdConfig GetThresholdConfigForChunk(ChunkedProgressBarConfig config, int chunk, int chunks, float min, float max) =>
|
||||
new ThresholdConfig
|
||||
{
|
||||
ThresholdType = ThresholdType.Below,
|
||||
Color = config.PartialFillColor,
|
||||
Enabled = config.UsePartialFillColor,
|
||||
Value = (max - min) / chunks * chunk,
|
||||
ChangeColor = true,
|
||||
ShowMarker = false
|
||||
};
|
||||
|
||||
public static void AddShield(BarHud bar, BarConfig config, ShieldConfig shieldConfig, ICharacter character, Vector2 fillSize, PluginConfigColor? color = null)
|
||||
{
|
||||
if (shieldConfig.Enabled)
|
||||
{
|
||||
float shield = Utils.ActorShieldValue(character);
|
||||
if (shield > 0f)
|
||||
{
|
||||
bar.AddForegrounds(
|
||||
GetShieldForeground(
|
||||
shieldConfig,
|
||||
config.Position,
|
||||
config.Size,
|
||||
fillSize,
|
||||
config.FillDirection,
|
||||
shield,
|
||||
character.CurrentHp,
|
||||
character.MaxHp,
|
||||
color)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using HSUI.Config;
|
||||
using HSUI.Config.Attributes;
|
||||
using HSUI.Enums;
|
||||
using HSUI.Interface.GeneralElements;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HSUI.Interface.Bars
|
||||
{
|
||||
[Exportable(false)]
|
||||
public class ChunkedBarConfig : BarConfig
|
||||
{
|
||||
[DragInt("Padding", min = -4000, max = 4000)]
|
||||
[Order(45)]
|
||||
public int Padding = 2;
|
||||
|
||||
public ChunkedBarConfig(
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
PluginConfigColor fillColor,
|
||||
int padding = 2) : base(position, size, fillColor)
|
||||
{
|
||||
Padding = padding;
|
||||
}
|
||||
}
|
||||
|
||||
[Exportable(false)]
|
||||
public class ChunkedProgressBarConfig : ChunkedBarConfig
|
||||
{
|
||||
[Checkbox("Show In Chunks", spacing = true)]
|
||||
[Order(46)]
|
||||
public bool UseChunks = true;
|
||||
|
||||
[RadioSelector("Show Text on All Chunks", "Show Text on Active Chunk")]
|
||||
[Order(47, collapseWith = nameof(UseChunks))]
|
||||
public LabelMode LabelMode;
|
||||
|
||||
[Checkbox("Use Partial Fill Color", spacing = true)]
|
||||
[Order(50)]
|
||||
public bool UsePartialFillColor = false;
|
||||
|
||||
[ColorEdit4("Partial Fill Color")]
|
||||
[Order(55, collapseWith = nameof(UsePartialFillColor))]
|
||||
public PluginConfigColor PartialFillColor;
|
||||
|
||||
[NestedConfig("Bar Text", 1000, separator = false, spacing = true)]
|
||||
public NumericLabelConfig Label;
|
||||
|
||||
public ChunkedProgressBarConfig(
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
PluginConfigColor fillColor,
|
||||
int padding = 2,
|
||||
PluginConfigColor? partialFillColor = null) : base(position, size, fillColor, padding)
|
||||
{
|
||||
Label = new NumericLabelConfig(Vector2.Zero, "", DrawAnchor.Center, DrawAnchor.Center);
|
||||
Label.Enabled = false;
|
||||
|
||||
PartialFillColor = partialFillColor ?? new PluginConfigColor(new(180f / 255f, 180f / 255f, 180f / 255f, 100f / 100f));
|
||||
}
|
||||
}
|
||||
|
||||
[DisableParentSettings("LabelMode", "UsePartialFillColor", "PartialFillColor")]
|
||||
[Exportable(false)]
|
||||
public class StacksWithDurationBarConfig : ChunkedProgressBarConfig
|
||||
{
|
||||
public StacksWithDurationBarConfig(
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
PluginConfigColor fillColor,
|
||||
int padding = 2,
|
||||
PluginConfigColor? partialFillColor = null) : base(position, size, fillColor, padding)
|
||||
{
|
||||
UseChunks = true;
|
||||
UsePartialFillColor = false;
|
||||
}
|
||||
}
|
||||
|
||||
public enum LabelMode
|
||||
{
|
||||
AllChunks,
|
||||
ActiveChunk
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using HSUI.Config;
|
||||
using HSUI.Config.Attributes;
|
||||
using HSUI.Enums;
|
||||
using HSUI.Interface.GeneralElements;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HSUI.Interface.Bars
|
||||
{
|
||||
[Exportable(false)]
|
||||
public class ProgressBarConfig : BarConfig
|
||||
{
|
||||
[NestedConfig("Threshold", 45)]
|
||||
public ThresholdConfig ThresholdConfig = new ThresholdConfig();
|
||||
|
||||
[NestedConfig("Bar Text", 1000)]
|
||||
public NumericLabelConfig Label;
|
||||
|
||||
public ProgressBarConfig(
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
PluginConfigColor fillColor,
|
||||
BarDirection fillDirection = BarDirection.Right,
|
||||
PluginConfigColor? threshHoldColor = null,
|
||||
float threshold = 0f) : base(position, size, fillColor, fillDirection)
|
||||
{
|
||||
Label = new NumericLabelConfig(Vector2.Zero, "", DrawAnchor.Center, DrawAnchor.Center);
|
||||
ThresholdConfig.Color = threshHoldColor ?? ThresholdConfig.Color;
|
||||
ThresholdConfig.Value = threshold;
|
||||
}
|
||||
}
|
||||
|
||||
[Exportable(false)]
|
||||
public class ThresholdConfig : PluginConfigObject
|
||||
{
|
||||
[DragFloat("Threshold Value", min = 0f, max = 10000f)]
|
||||
[Order(10)]
|
||||
public float Value = 0f;
|
||||
|
||||
[Checkbox("Change Color")]
|
||||
[Order(15)]
|
||||
public bool ChangeColor = true;
|
||||
|
||||
[Combo("Activate Above/Below Threshold", "Above", "Below")]
|
||||
[Order(20, collapseWith = nameof(ChangeColor))]
|
||||
public ThresholdType ThresholdType = ThresholdType.Below;
|
||||
|
||||
[ColorEdit4("Color")]
|
||||
[Order(25, collapseWith = nameof(ChangeColor))]
|
||||
public PluginConfigColor Color = new PluginConfigColor(new(230f / 255f, 33f / 255f, 33f / 255f, 100f / 100f));
|
||||
|
||||
[Checkbox("Show Threshold Marker")]
|
||||
[Order(30)]
|
||||
public bool ShowMarker = false;
|
||||
|
||||
[DragInt("Threshold Marker Size", min = 0, max = 10000)]
|
||||
[Order(35, collapseWith = nameof(ShowMarker))]
|
||||
public int MarkerSize = 2;
|
||||
|
||||
[ColorEdit4("Threshold Marker Color")]
|
||||
[Order(40, collapseWith = nameof(ShowMarker))]
|
||||
public PluginConfigColor MarkerColor = new PluginConfigColor(new Vector4(0f / 255f, 0f / 255f, 0f / 255f, 100f / 100f));
|
||||
|
||||
public bool IsActive(float current)
|
||||
{
|
||||
return Enabled && (ThresholdType == ThresholdType.Below && current < Value ||
|
||||
ThresholdType == ThresholdType.Above && current > Value);
|
||||
}
|
||||
|
||||
public ThresholdConfig()
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ThresholdType
|
||||
{
|
||||
Above,
|
||||
Below
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using HSUI.Config;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HSUI.Interface.Bars
|
||||
{
|
||||
public class Rect
|
||||
{
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public Vector2 Size { get; set; }
|
||||
|
||||
public PluginConfigColor Color { get; set; }
|
||||
|
||||
public Rect(Vector2 pos, Vector2 size, PluginConfigColor? color = null)
|
||||
{
|
||||
Position = pos;
|
||||
Size = size;
|
||||
Color = color ?? new PluginConfigColor(new(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
public Rect() : this(new(0, 0), new(0, 0), new PluginConfigColor(new(0, 0, 0, 0))) { }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user