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,322 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HSUI.Helpers
|
||||
{
|
||||
public struct LayoutInfo
|
||||
{
|
||||
public readonly uint TotalRowCount;
|
||||
public readonly uint TotalColCount;
|
||||
public readonly uint RealRowCount;
|
||||
public readonly uint RealColCount;
|
||||
public readonly Vector2 ContentSize;
|
||||
|
||||
public LayoutInfo(uint totalRowCount, uint totalColCount, uint realRowCount, uint realColCount, Vector2 contentSize)
|
||||
{
|
||||
TotalRowCount = totalRowCount;
|
||||
TotalColCount = totalColCount;
|
||||
RealRowCount = realRowCount;
|
||||
RealColCount = realColCount;
|
||||
ContentSize = contentSize;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LayoutHelper
|
||||
{
|
||||
// Calculates rows and columns. Used for status effect lists and party frames.
|
||||
public static LayoutInfo CalculateLayout(
|
||||
Vector2 maxSize,
|
||||
Vector2 itemSize,
|
||||
uint count,
|
||||
Vector2 padding,
|
||||
bool fillRowsFirst
|
||||
)
|
||||
{
|
||||
uint rowCount = 1;
|
||||
uint colCount = 1;
|
||||
uint realRowCount = 1;
|
||||
uint realColCount = 1;
|
||||
|
||||
if (maxSize.X < itemSize.X)
|
||||
{
|
||||
colCount = count;
|
||||
realColCount = count;
|
||||
}
|
||||
else if (maxSize.Y < itemSize.Y)
|
||||
{
|
||||
rowCount = count;
|
||||
realRowCount = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fillRowsFirst)
|
||||
{
|
||||
float remainingWidth = maxSize.X;
|
||||
colCount = 0;
|
||||
while (remainingWidth > 0)
|
||||
{
|
||||
remainingWidth -= (itemSize.X + padding.X);
|
||||
colCount++;
|
||||
}
|
||||
|
||||
if (itemSize.X * colCount + padding.X * (colCount - 1) > maxSize.X)
|
||||
{
|
||||
colCount = Math.Max(1, colCount - 1);
|
||||
}
|
||||
|
||||
rowCount = (uint)Math.Ceiling((double)count / colCount);
|
||||
|
||||
int remaining = (int)(count - colCount);
|
||||
while (remaining > 0)
|
||||
{
|
||||
realRowCount++;
|
||||
remaining -= (int)colCount;
|
||||
}
|
||||
|
||||
realColCount = Math.Min(count, colCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
float remainingHeight = maxSize.Y;
|
||||
rowCount = 0;
|
||||
while (remainingHeight > 0)
|
||||
{
|
||||
remainingHeight -= (itemSize.Y + padding.Y);
|
||||
rowCount++;
|
||||
}
|
||||
|
||||
if (itemSize.Y * rowCount + padding.Y * (rowCount - 1) > maxSize.Y)
|
||||
{
|
||||
rowCount = Math.Max(1, rowCount - 1);
|
||||
}
|
||||
|
||||
colCount = (uint)Math.Ceiling((double)count / rowCount);
|
||||
|
||||
int remaining = (int)(count - rowCount);
|
||||
while (remaining > 0)
|
||||
{
|
||||
realColCount++;
|
||||
remaining -= (int)rowCount;
|
||||
}
|
||||
|
||||
realRowCount = Math.Min(count, rowCount);
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 contentSize = new Vector2(
|
||||
realColCount * itemSize.X + (realColCount - 1) * padding.X,
|
||||
realRowCount * itemSize.Y + (realRowCount - 1) * padding.Y
|
||||
);
|
||||
|
||||
return new LayoutInfo(rowCount, colCount, realRowCount, realColCount, contentSize);
|
||||
}
|
||||
|
||||
private static List<GrowthDirections> DirectionOptionsValues = new List<GrowthDirections>()
|
||||
{
|
||||
GrowthDirections.Right | GrowthDirections.Down,
|
||||
GrowthDirections.Right | GrowthDirections.Up,
|
||||
GrowthDirections.Left | GrowthDirections.Down,
|
||||
GrowthDirections.Left | GrowthDirections.Up,
|
||||
GrowthDirections.Centered | GrowthDirections.Up,
|
||||
GrowthDirections.Centered | GrowthDirections.Down,
|
||||
GrowthDirections.Centered | GrowthDirections.Left,
|
||||
GrowthDirections.Centered | GrowthDirections.Right
|
||||
};
|
||||
public static GrowthDirections GrowthDirectionsFromIndex(int index)
|
||||
{
|
||||
if (index > 0 && index < DirectionOptionsValues.Count)
|
||||
{
|
||||
return DirectionOptionsValues[index];
|
||||
}
|
||||
|
||||
return DirectionOptionsValues[0];
|
||||
}
|
||||
|
||||
public static int IndexFromGrowthDirections(GrowthDirections directions)
|
||||
{
|
||||
int index = DirectionOptionsValues.FindIndex(d => d == directions);
|
||||
|
||||
return index > 0 ? index : 0;
|
||||
}
|
||||
|
||||
public static bool GetFillsRowsFirst(bool fallback, GrowthDirections directions)
|
||||
{
|
||||
if ((directions & GrowthDirections.Centered) != 0)
|
||||
{
|
||||
if ((directions & GrowthDirections.Up) != 0 || (directions & GrowthDirections.Down) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if ((directions & GrowthDirections.Left) != 0 || (directions & GrowthDirections.Right) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
public static void CalculateAxisDirections(
|
||||
GrowthDirections growthDirections,
|
||||
int row,
|
||||
int col,
|
||||
uint elementCount,
|
||||
Vector2 size,
|
||||
Vector2 iconSize,
|
||||
Vector2 iconPadding,
|
||||
out Vector2 direction,
|
||||
out Vector2 offset)
|
||||
{
|
||||
if ((growthDirections & GrowthDirections.Centered) != 0)
|
||||
{
|
||||
if ((growthDirections & GrowthDirections.Up) != 0 || (growthDirections & GrowthDirections.Down) != 0)
|
||||
{
|
||||
int elementsPerRow = (int)(size.X / (iconSize.X + iconPadding.X));
|
||||
long elementsInRow = Math.Min(elementsPerRow, elementCount - (elementsPerRow * row));
|
||||
|
||||
direction.X = 1;
|
||||
direction.Y = (growthDirections & GrowthDirections.Down) != 0 ? 1 : -1;
|
||||
offset.X = -(iconSize.X + iconPadding.X) * elementsInRow / 2f;
|
||||
offset.Y = direction.Y == 1 ? 0 : -iconSize.Y;
|
||||
}
|
||||
|
||||
else// if ((growthDirections & GrowthDirections.Left) != 0 || (growthDirections & GrowthDirections.Right) != 0)
|
||||
{
|
||||
int elementsPerCol = (int)(size.Y / (iconSize.Y + iconPadding.Y));
|
||||
long elementsInCol = Math.Min(elementsPerCol, elementCount - (elementsPerCol * col));
|
||||
|
||||
direction.X = (growthDirections & GrowthDirections.Left) != 0 ? -1 : 1;
|
||||
direction.Y = 1;
|
||||
offset.X = direction.X == 1 ? 0 : -iconSize.X;
|
||||
offset.Y = -(iconSize.Y + iconPadding.Y) * elementsInCol / 2f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
direction.X = (growthDirections & GrowthDirections.Right) != 0 ? 1 : -1;
|
||||
direction.Y = (growthDirections & GrowthDirections.Down) != 0 ? 1 : -1;
|
||||
offset.X = direction.X == 1 ? 0 : -iconSize.X;
|
||||
offset.Y = direction.Y == 1 ? 0 : -iconSize.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector2 CalculateStartPosition(Vector2 position, Vector2 size, GrowthDirections growthDirections)
|
||||
{
|
||||
Vector2 area = size;
|
||||
if ((growthDirections & GrowthDirections.Left) != 0)
|
||||
{
|
||||
area.X = -area.X;
|
||||
}
|
||||
|
||||
if ((growthDirections & GrowthDirections.Up) != 0)
|
||||
{
|
||||
area.Y = -area.Y;
|
||||
}
|
||||
|
||||
Vector2 startPos = position;
|
||||
if ((growthDirections & GrowthDirections.Centered) != 0)
|
||||
{
|
||||
if ((growthDirections & GrowthDirections.Up) != 0 || (growthDirections & GrowthDirections.Down) != 0)
|
||||
{
|
||||
startPos.X = position.X - size.X / 2f;
|
||||
}
|
||||
else if ((growthDirections & GrowthDirections.Left) != 0 || (growthDirections & GrowthDirections.Right) != 0)
|
||||
{
|
||||
startPos.Y = position.Y - size.Y / 2f;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 endPos = position + area;
|
||||
|
||||
if (endPos.X < position.X)
|
||||
{
|
||||
startPos.X = endPos.X;
|
||||
}
|
||||
|
||||
if (endPos.Y < position.Y)
|
||||
{
|
||||
startPos.Y = endPos.Y;
|
||||
}
|
||||
|
||||
return startPos;
|
||||
}
|
||||
|
||||
public static (List<Vector2>, Vector2, Vector2) CalculateIconPositions(
|
||||
GrowthDirections directions,
|
||||
uint count,
|
||||
Vector2 position,
|
||||
Vector2 size,
|
||||
Vector2 iconSize,
|
||||
Vector2 iconPadding,
|
||||
bool fillRowsFirst,
|
||||
LayoutInfo layoutInfo)
|
||||
{
|
||||
List<Vector2> list = new List<Vector2>();
|
||||
Vector2 minPos = new Vector2(float.MaxValue, float.MaxValue);
|
||||
Vector2 maxPos = Vector2.Zero;
|
||||
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
CalculateAxisDirections(
|
||||
directions,
|
||||
row,
|
||||
col,
|
||||
count,
|
||||
size,
|
||||
iconSize,
|
||||
iconPadding,
|
||||
out Vector2 direction,
|
||||
out Vector2 offset
|
||||
);
|
||||
|
||||
Vector2 pos = new Vector2(
|
||||
position.X + offset.X + iconSize.X * col * direction.X + iconPadding.X * col * direction.X,
|
||||
position.Y + offset.Y + iconSize.Y * row * direction.Y + iconPadding.Y * row * direction.Y
|
||||
);
|
||||
|
||||
minPos.X = Math.Min(pos.X, minPos.X);
|
||||
minPos.Y = Math.Min(pos.Y, minPos.Y);
|
||||
maxPos.X = Math.Max(pos.X + iconSize.X, maxPos.X);
|
||||
maxPos.Y = Math.Max(pos.Y + iconSize.Y, maxPos.Y);
|
||||
|
||||
list.Add(pos);
|
||||
|
||||
// rows / columns
|
||||
if (fillRowsFirst)
|
||||
{
|
||||
col += 1;
|
||||
if (col >= layoutInfo.TotalColCount)
|
||||
{
|
||||
col = 0;
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
row += 1;
|
||||
if (row >= layoutInfo.TotalRowCount)
|
||||
{
|
||||
row = 0;
|
||||
col += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (list, minPos, maxPos);
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum GrowthDirections : short
|
||||
{
|
||||
Up = 1,
|
||||
Down = 2,
|
||||
Left = 4,
|
||||
Right = 8,
|
||||
Centered = 16,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user