mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-29 17:44:09 -04:00
172 lines
4.4 KiB
C#
172 lines
4.4 KiB
C#
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
|
using System;
|
|
using System.Drawing;
|
|
|
|
namespace ClassicalSharp.Gui.Widgets {
|
|
public abstract class PlayerListWidget : Widget {
|
|
|
|
protected readonly Font font;
|
|
public PlayerListWidget(Game game, Font font) : base(game) {
|
|
HorizontalAnchor = Anchor.Centre;
|
|
VerticalAnchor = Anchor.Centre;
|
|
this.font = font;
|
|
}
|
|
|
|
protected int columnPadding = 5;
|
|
protected int elementOffset = 0;
|
|
|
|
protected const int boundsSize = 10;
|
|
protected const int namesPerColumn = 20;
|
|
protected int namesCount = 0;
|
|
protected Texture[] textures;
|
|
protected int columns;
|
|
protected int xMin, xMax, yHeight;
|
|
protected static FastColour tableCol = new FastColour(50, 50, 50, 205);
|
|
|
|
public override void Init() {
|
|
CreateInitialPlayerInfo();
|
|
SortPlayerInfo();
|
|
}
|
|
|
|
public abstract string GetNameUnder(int mouseX, int mouseY);
|
|
|
|
public override void Render(double delta) {
|
|
gfx.Texturing = false;
|
|
gfx.Draw2DQuad(X, Y, Width, Height, tableCol);
|
|
gfx.Texturing = true;
|
|
for (int i = 0; i < namesCount; i++) {
|
|
Texture texture = textures[i];
|
|
if (texture.IsValid)
|
|
texture.Render(gfx);
|
|
}
|
|
}
|
|
|
|
public override void Dispose() {
|
|
for (int i = 0; i < namesCount; i++) {
|
|
Texture tex = textures[i];
|
|
gfx.DeleteTexture(ref tex);
|
|
textures[i] = tex;
|
|
}
|
|
}
|
|
|
|
protected void UpdateTableDimensions() {
|
|
int width = xMax - xMin;
|
|
X = xMin - boundsSize;
|
|
Y = game.Height / 2 - yHeight / 2 - boundsSize;
|
|
Width = width + boundsSize * 2;
|
|
Height = yHeight + boundsSize * 2;
|
|
}
|
|
|
|
protected void CalcMaxColumnHeight() {
|
|
yHeight = 0;
|
|
for (int col = 0; col < columns; col++) {
|
|
yHeight = Math.Max(GetColumnHeight(col), yHeight);
|
|
}
|
|
}
|
|
|
|
protected int GetColumnWidth(int column) {
|
|
int i = column * namesPerColumn;
|
|
int maxWidth = 0;
|
|
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
|
|
|
|
for (; i < maxIndex; i++)
|
|
maxWidth = Math.Max(maxWidth, textures[i].Width);
|
|
return maxWidth + columnPadding + elementOffset;
|
|
}
|
|
|
|
protected int GetColumnHeight(int column) {
|
|
int i = column * namesPerColumn;
|
|
int total = 0;
|
|
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
|
|
|
|
for (; i < maxIndex; i++)
|
|
total += textures[i].Height + 1;
|
|
return total;
|
|
}
|
|
|
|
protected void SetColumnPos(int column, int x, int y) {
|
|
int i = column * namesPerColumn;
|
|
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
|
|
|
|
for (; i < maxIndex; i++) {
|
|
Texture tex = textures[i];
|
|
tex.X1 = x; tex.Y1 = y;
|
|
|
|
y += tex.Height + 1;
|
|
if (ShouldOffset(i))
|
|
tex.X1 += elementOffset;
|
|
textures[i] = tex;
|
|
}
|
|
}
|
|
|
|
protected virtual bool ShouldOffset(int i) { return true; }
|
|
|
|
public void RecalcYOffset() {
|
|
YOffset = -Math.Max(0, game.Height / 4 - Height / 2);
|
|
}
|
|
|
|
public override void CalculatePosition() {
|
|
int oldX = X, oldY = Y;
|
|
base.CalculatePosition();
|
|
|
|
for (int i = 0; i < namesCount; i++) {
|
|
textures[i].X1 += X - oldX;
|
|
textures[i].Y1 += Y - oldY;
|
|
}
|
|
}
|
|
|
|
protected abstract void CreateInitialPlayerInfo();
|
|
|
|
protected abstract void SortInfoList();
|
|
|
|
protected void RemoveInfoAt<T>(T[] info, int i) {
|
|
Texture tex = textures[i];
|
|
gfx.DeleteTexture(ref tex);
|
|
RemoveItemAt(info, i);
|
|
RemoveItemAt(textures, i);
|
|
namesCount--;
|
|
SortPlayerInfo();
|
|
}
|
|
|
|
protected void RemoveItemAt<T>(T[] array, int index) {
|
|
for (int i = index; i < namesCount - 1; i++) {
|
|
array[i] = array[i + 1];
|
|
}
|
|
array[namesCount - 1] = default(T);
|
|
}
|
|
|
|
protected void SortPlayerInfo() {
|
|
columns = Utils.CeilDiv(namesCount, namesPerColumn);
|
|
SortInfoList();
|
|
columns = Utils.CeilDiv(namesCount, namesPerColumn);
|
|
CalcMaxColumnHeight();
|
|
int y = game.Height / 2 - yHeight / 2;
|
|
int midCol = columns / 2;
|
|
|
|
int centreX = game.Width / 2;
|
|
int offset = 0;
|
|
if (columns % 2 != 0) {
|
|
// For an odd number of columns, the middle column is centred.
|
|
offset = Utils.CeilDiv(GetColumnWidth(midCol), 2);
|
|
}
|
|
|
|
xMin = centreX - offset;
|
|
for (int col = midCol - 1; col >= 0; col--) {
|
|
xMin -= GetColumnWidth(col);
|
|
SetColumnPos(col, xMin, y);
|
|
}
|
|
xMax = centreX - offset;
|
|
for (int col = midCol; col < columns; col++) {
|
|
SetColumnPos(col, xMax, y);
|
|
xMax += GetColumnWidth(col);
|
|
}
|
|
|
|
OnSort();
|
|
UpdateTableDimensions();
|
|
RecalcYOffset();
|
|
CalculatePosition();
|
|
}
|
|
|
|
protected virtual void OnSort() { }
|
|
}
|
|
} |