using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace Luneraria.UI
{
/// The plate styles of the HUD panels (Godot "panel" styleboxes of lune_ui_theme.gd and the menu theme).
public static class LunePanels
{
public static readonly LunePlateStyle Hud = LunePlateStyle.Hud(LuneUiTheme.SlateTop, LuneUiTheme.SlateBottom, LuneUiTheme.Edge, 1f, 6f, 12f, 10f);
public static readonly LunePlateStyle HudTight = LunePlateStyle.Hud(LuneUiTheme.SlateTop, LuneUiTheme.SlateBottom, LuneUiTheme.Edge, 1f, 5f, 8f, 6f);
public static readonly LunePlateStyle Modal = LunePlateStyle.Hud(new Color(.07f, .09f, .125f, .98f), new Color(.045f, .06f, .085f, .98f), LuneUiTheme.Hex("5c4a33"), 1.5f, 10f, 22f, 18f)
.WithShadow(new Color(0f, 0f, 0f, .55f), 16f);
public static readonly LunePlateStyle BannerDanger = LunePlateStyle.Hud(new Color(.16f, .075f, .05f, .94f), new Color(.11f, .05f, .035f, .95f), LuneUiTheme.Hex("a0523a"), 1.5f, 6f, 16f, 8f);
public static readonly LunePlateStyle BannerOwn = LunePlateStyle.Hud(new Color(.07f, .1f, .16f, .94f), new Color(.05f, .07f, .11f, .95f), LuneUiTheme.Hex("5f86b8"), 1.5f, 6f, 16f, 8f);
public static readonly LunePlateStyle Tooltip = LunePlateStyle.Hud(new Color(.06f, .08f, .11f, .98f), new Color(.045f, .06f, .085f, .98f), LuneUiTheme.Hex("6b5a44"), 1f, 6f, 12f, 9f)
.WithShadow(new Color(0f, 0f, 0f, .5f), 8f);
public static readonly LunePlateStyle Menu = MenuPlate();
static LunePlateStyle MenuPlate()
{
LunePlateStyle style = LunePlateStyle.Menu(new Color(.078f, .094f, .114f, .95f), new Color(.055f, .066f, .08f, .96f), LuneUiTheme.Hex("5c4a33"), 1.5f, 12f, 30f, 26f)
.WithShadow(new Color(0f, 0f, 0f, .45f), 18f);
style.Ornaments = true;
style.OrnamentColor = LuneUiTheme.Hex("8a6a3c");
return style;
}
}
/// A panel with a drawn plate background (Godot PanelContainer with a ForgedStyle).
public class LunePanel : VisualElement
{
LunePlateStyle _plate;
public LunePanel(LunePlateStyle plate, bool stopsMouse = true)
{
pickingMode = stopsMouse ? PickingMode.Position : PickingMode.Ignore;
Plate = plate;
generateVisualContent += context =>
{
if (_plate != null)
LunePlates.Draw(context, new Rect(0f, 0f, layout.width, layout.height), _plate);
};
}
public LunePlateStyle Plate
{
get { return _plate; }
set
{
if (value == _plate)
return;
_plate = value;
value?.ApplyPadding(this);
MarkDirtyRepaint();
}
}
}
/// Look of a button variation: plates per state and the text colours (Godot Button theme items).
public sealed class LuneButtonLook
{
public LunePlateStyle Normal;
public LunePlateStyle Hover;
public LunePlateStyle Pressed;
public LunePlateStyle Disabled;
public LunePlateStyle HoverPressed;
/// Flat tab look: background and bottom line per state instead of plates.
public bool Tab;
public string TextVariation = "HudText";
public float TextSize = 15f;
public Color Text = LuneUiTheme.Text;
public Color TextHover = Color.white;
public Color? TextPressed;
public Color? TextHoverPressed;
public Color TextDisabled = LuneUiTheme.Faint;
public LunePlateStyle PlateFor(bool disabled, bool pressed, bool hover)
{
if (disabled)
return Disabled ?? Normal;
if (pressed && hover)
return HoverPressed ?? Pressed ?? Normal;
if (pressed)
return Pressed ?? Normal;
if (hover)
return Hover ?? Normal;
return Normal;
}
public Color TextFor(bool disabled, bool pressed, bool hover)
{
if (disabled)
return TextDisabled;
if (pressed && hover)
return TextHoverPressed ?? TextPressed ?? TextHover;
if (pressed)
return TextPressed ?? Text;
return hover ? TextHover : Text;
}
}
/// The button variations of lune_ui_theme.gd and the menu theme.
public static class LuneButtons
{
static LunePlateStyle P(string top, string bottom, Color edge, float width, float cut, float x, float y)
{
return LunePlateStyle.Hud(LuneUiTheme.Hex(top), LuneUiTheme.Hex(bottom), edge, width, cut, x, y);
}
static LunePlateStyle P(Color top, Color bottom, Color edge, float width, float cut, float x, float y)
{
return LunePlateStyle.Hud(top, bottom, edge, width, cut, x, y);
}
static LunePlateStyle M(string top, string bottom, Color edge, float width, float cut, float x, float y)
{
return LunePlateStyle.Menu(LuneUiTheme.Hex(top), LuneUiTheme.Hex(bottom), edge, width, cut, x, y);
}
static Color H(string hex) { return LuneUiTheme.Hex(hex); }
public static readonly LuneButtonLook HudButton = new LuneButtonLook
{
Normal = P("1b232d", "131920", H("4a5a6c"), 1f, 5f, 12f, 7f), Hover = P("26303c", "1a212a", LuneUiTheme.BronzeLight, 1f, 5f, 12f, 7f),
Pressed = P("10151b", "171d25", LuneUiTheme.Bronze, 1.5f, 5f, 12f, 7f), Disabled = P("141a20", "10141a", H("2c333c"), 1f, 5f, 12f, 7f),
TextSize = 15f,
};
public static readonly LuneButtonLook HudIconButton = new LuneButtonLook
{
Normal = P("1b232d", "131920", H("3c4a5a"), 1f, 5f, 9f, 6f), Hover = P("26303c", "1a212a", LuneUiTheme.BronzeLight, 1f, 5f, 9f, 6f),
Pressed = P("10151b", "171d25", LuneUiTheme.Bronze, 1.5f, 5f, 9f, 6f), Disabled = P("141a20", "10141a", H("2c333c"), 1f, 5f, 9f, 6f),
TextSize = 15f,
};
public static readonly LuneButtonLook HudPrimary = new LuneButtonLook
{
Normal = M("e8c47e", "b98a4a", H("fff0cc"), 1.5f, 7f, 16f, 8f), Hover = M("f6d898", "cc9c56", Color.white, 1.5f, 7f, 16f, 8f),
Pressed = M("b98a4a", "d5aa66", H("fff0cc"), 2f, 7f, 16f, 8f), Disabled = M("4a4234", "3a3328", H("6a5c46"), 1f, 7f, 16f, 8f),
TextVariation = "HudPrimary", TextSize = 16f, Text = LuneUiTheme.Ink, TextHover = LuneUiTheme.Ink, TextPressed = LuneUiTheme.Ink, TextDisabled = H("9c8f78"),
};
/// Godot PrimaryButton of the menu theme (Bereit, Neue Partie).
public static readonly LuneButtonLook Primary = new LuneButtonLook
{
Normal = M("e8c47e", "b98a4a", H("fff0cc"), 1.5f, 9f, 30f, 15f), Hover = M("f6d898", "cc9c56", Color.white, 1.5f, 9f, 30f, 15f),
Pressed = M("b98a4a", "d5aa66", H("fff0cc"), 2f, 9f, 30f, 15f), Disabled = M("5a4c38", "463a2a", H("7d6a4c"), 1.5f, 9f, 30f, 15f),
TextVariation = "PrimaryButton", TextSize = 22f, Text = LuneUiTheme.Ink, TextHover = LuneUiTheme.Ink, TextPressed = LuneUiTheme.Ink, TextDisabled = H("2a2218"),
};
/// Godot Button of the menu theme (secondary).
public static readonly LuneButtonLook Secondary = new LuneButtonLook
{
Normal = M("1d232b", "141920", H("6b5a44"), 1.5f, 7f, 20f, 11f), Hover = M("27303a", "1a2028", LuneUiTheme.BronzeLight, 1.5f, 7f, 20f, 11f),
Pressed = M("10141a", "171c23", LuneUiTheme.Bronze, 2f, 7f, 20f, 11f), Disabled = M("15191e", "111418", H("3a352e"), 1.5f, 7f, 20f, 11f),
TextSize = 17f, Text = LuneUiTheme.Parchment,
};
public static readonly LuneButtonLook HudCard = Card(new LuneButtonLook
{
Normal = P("19222c", "10161d", H("34424f"), 1f, 7f, 6f, 6f), Hover = P("212c38", "141b23", LuneUiTheme.Bronze, 1.5f, 7f, 6f, 6f),
Pressed = P("2a2820", "17171a", LuneUiTheme.BronzeLight, 2f, 7f, 6f, 6f), Disabled = P("12171d", "0d1116", H("252c34"), 1f, 7f, 6f, 6f),
});
public static readonly LuneButtonLook HudChampionCard = Card(new LuneButtonLook
{
Normal = P("261c14", "15100c", H("6e4a2c"), 1f, 7f, 6f, 6f), Hover = P("302216", "1b140e", LuneUiTheme.Champion, 1.5f, 7f, 6f, 6f),
Pressed = P("3a2818", "1e150e", H("ffc88c"), 2f, 7f, 6f, 6f), Disabled = P("16110d", "0f0c0a", H("3a2c20"), 1f, 7f, 6f, 6f),
});
public static readonly LuneButtonLook HudChip = Card(new LuneButtonLook
{
Normal = P("1a232d", "11171e", H("33404d"), 1f, 4f, 2f, 2f), Hover = P("222d39", "151c24", LuneUiTheme.Bronze, 1f, 4f, 2f, 2f),
Pressed = P("2c2a22", "17171a", LuneUiTheme.BronzeLight, 2f, 4f, 2f, 2f), Disabled = P("12171d", "0d1116", H("252c34"), 1f, 4f, 2f, 2f),
});
public static readonly LuneButtonLook HudRow = new LuneButtonLook
{
Normal = P(new Color(.09f, .12f, .16f, .55f), new Color(.06f, .08f, .11f, .55f), H("2a3645"), 1f, 5f, 10f, 7f),
Hover = P(new Color(.13f, .17f, .22f, .75f), new Color(.08f, .11f, .15f, .75f), LuneUiTheme.Bronze, 1f, 5f, 10f, 7f),
Pressed = P(new Color(.16f, .15f, .12f, .8f), new Color(.09f, .09f, .1f, .8f), LuneUiTheme.BronzeLight, 1.5f, 5f, 10f, 7f),
Disabled = P(new Color(.09f, .12f, .16f, .55f), new Color(.06f, .08f, .11f, .55f), H("2a3645"), 1f, 5f, 10f, 7f),
};
public static readonly LuneButtonLook HudToggle = Toggle();
static LuneButtonLook Toggle()
{
LunePlateStyle on = P("3a3222", "262117", LuneUiTheme.BronzeLight, 1.5f, 5f, 10f, 6f).WithInner(LuneUiTheme.WithAlpha(LuneUiTheme.BronzeLight, .35f));
return new LuneButtonLook
{
Normal = P("171e27", "11161d", H("3a4756"), 1f, 5f, 10f, 6f), Hover = P("212a35", "171d25", LuneUiTheme.Bronze, 1f, 5f, 10f, 6f),
Pressed = on, HoverPressed = on, Disabled = P("11151a", "0e1115", H("242a31"), 1f, 5f, 10f, 6f),
TextVariation = "HudBadge", TextSize = 14f, Text = H("cfd5dc"), TextHover = Color.white, TextPressed = H("fff4dc"), TextHoverPressed = H("fff4dc"), TextDisabled = H("59616b"),
};
}
public static readonly LuneButtonLook HudTab = new LuneButtonLook
{
Tab = true, TextVariation = "HudCaps", TextSize = 14f, Text = LuneUiTheme.Muted, TextHover = LuneUiTheme.Text, TextPressed = LuneUiTheme.BronzeLight,
TextHoverPressed = LuneUiTheme.BronzeLight, TextDisabled = LuneUiTheme.Faint,
};
static LuneButtonLook Card(LuneButtonLook look)
{
look.HoverPressed = look.Pressed;
return look;
}
}
///
/// Button of the HUD (Godot Button with a theme variation). Draws the plate of its state;
/// `Disabled` greys it out and blocks clicks but keeps hover, so tooltips can say why (as
/// in G3). Toggle buttons keep their pressed state.
///
public class LuneButton : VisualElement
{
public event Action Clicked;
public readonly Label TextLabel;
public bool ToggleMode;
LuneButtonLook _look;
bool _hover;
bool _down;
bool _on;
bool _disabled;
public LuneButton(string text, LuneButtonLook look, VisualElement parent = null)
{
_look = look;
focusable = false;
style.flexDirection = FlexDirection.Row;
style.alignItems = Align.Center;
style.justifyContent = Justify.Center;
if (text != null)
{
TextLabel = LuneUi.Label(text, look.TextVariation, this, look.TextSize);
TextLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
}
ApplyPadding();
generateVisualContent += Draw;
RegisterCallback(_ => SetHover(true));
RegisterCallback(_ => SetHover(false));
RegisterCallback(OnDown);
RegisterCallback(OnUp);
RegisterCallback(_ => { _down = false; Refresh(); });
Refresh();
parent?.Add(this);
}
public LuneButtonLook Look
{
get { return _look; }
set
{
if (value == _look)
return;
_look = value;
if (TextLabel != null)
LuneUi.Apply(TextLabel, value.TextVariation, value.TextSize);
ApplyPadding();
Refresh();
}
}
public string Text
{
get { return TextLabel != null ? TextLabel.text : ""; }
set
{
if (TextLabel != null && TextLabel.text != value)
TextLabel.text = value;
}
}
public bool Disabled
{
get { return _disabled; }
set
{
if (value == _disabled)
return;
_disabled = value;
Refresh();
}
}
/// Pressed state of a toggle (Godot set_pressed_no_signal).
public bool On
{
get { return _on; }
set
{
if (value == _on)
return;
_on = value;
Refresh();
}
}
public bool Hovered { get { return _hover; } }
void ApplyPadding()
{
if (_look.Tab)
{
style.paddingLeft = 12f;
style.paddingRight = 12f;
style.paddingTop = 6f;
style.paddingBottom = 6f;
}
else
{
_look.Normal?.ApplyPadding(this);
}
}
void SetHover(bool value)
{
_hover = value;
Refresh();
}
void OnDown(PointerDownEvent evt)
{
if (evt.button != 0 || _disabled)
return;
_down = true;
this.CapturePointer(evt.pointerId);
Refresh();
evt.StopPropagation();
}
void OnUp(PointerUpEvent evt)
{
if (evt.button != 0 || !_down)
return;
_down = false;
this.ReleasePointer(evt.pointerId);
bool inside = ContainsPoint(evt.localPosition);
Refresh();
evt.StopPropagation();
if (inside && !_disabled)
Click();
}
/// Godot `pressed`: toggles first, then raises Clicked (also for tests and hotkeys).
public void Click()
{
if (_disabled)
return;
if (ToggleMode)
On = !_on;
Clicked?.Invoke();
}
void Refresh()
{
bool pressed = _down || _on;
if (TextLabel != null)
LuneUi.SetColor(TextLabel, _look.TextFor(_disabled, pressed, _hover));
MarkDirtyRepaint();
}
void Draw(MeshGenerationContext context)
{
var rect = new Rect(0f, 0f, layout.width, layout.height);
bool pressed = _down || _on;
if (_look.Tab)
{
Painter2D painter = context.painter2D;
Color fill = pressed ? LuneUiTheme.WithAlpha(LuneUiTheme.BronzeLight, .08f) : _hover && !_disabled ? new Color(1f, 1f, 1f, .04f) : Color.clear;
Color line = pressed ? LuneUiTheme.BronzeLight : _hover && !_disabled ? LuneUiTheme.WithAlpha(LuneUiTheme.Bronze, .5f) : Color.clear;
if (fill.a > 0f)
LunePlates.Polygon(painter, new[] { rect.min, new Vector2(rect.xMax, rect.yMin), rect.max, new Vector2(rect.xMin, rect.yMax) }, fill);
if (line.a > 0f)
LunePlates.Line(painter, new Vector2(rect.xMin, rect.yMax - 1f), new Vector2(rect.xMax, rect.yMax - 1f), line, 2f);
return;
}
LunePlateStyle plate = _look.PlateFor(_disabled, pressed, _hover && !_disabled);
if (plate != null)
LunePlates.Draw(context, rect, plate);
}
}
/// A LuneGlyphs symbol as an element (Godot LuneGlyph). Ignores the mouse.
public sealed class LuneGlyphElement : VisualElement
{
string _glyph;
Color _color;
public Color Accent;
public LuneGlyphElement(string glyph, Color color, float edge = 18f)
{
_glyph = glyph;
_color = color;
pickingMode = PickingMode.Ignore;
style.width = edge;
style.height = edge;
style.flexShrink = 0f;
style.alignSelf = Align.Center;
generateVisualContent += context =>
{
if (!string.IsNullOrEmpty(_glyph))
LuneGlyphs.Draw(context.painter2D, _glyph, new Rect(0f, 0f, layout.width, layout.height), _color, Accent);
};
}
public string Glyph
{
get { return _glyph; }
set
{
if (value == _glyph)
return;
_glyph = value;
MarkDirtyRepaint();
}
}
public Color Color
{
get { return _color; }
set
{
if (value == _color)
return;
_color = value;
MarkDirtyRepaint();
}
}
public float Edge
{
set
{
style.width = value;
style.height = value;
}
}
}
/// Thin value bar drawn directly: dark track, fill, a top highlight and optional ticks (Godot LuneHpBar).
public sealed class LuneHpBar : VisualElement
{
float _fraction = 1f;
Color _fill = LuneUiTheme.Good;
public int Ticks;
public Color Track = new Color(0f, 0f, 0f, .55f);
public LuneHpBar(float width = 60f, float height = 6f)
{
pickingMode = PickingMode.Ignore;
style.minWidth = width;
style.height = height;
style.flexShrink = 0f;
generateVisualContent += Draw;
}
public float Fraction
{
get { return _fraction; }
set
{
value = Mathf.Clamp01(value);
if (Mathf.Abs(value - _fraction) <= .0005f)
return;
_fraction = value;
MarkDirtyRepaint();
}
}
public Color Fill
{
get { return _fill; }
set
{
if (value == _fill)
return;
_fill = value;
MarkDirtyRepaint();
}
}
void Draw(MeshGenerationContext context)
{
Painter2D painter = context.painter2D;
var rect = new Rect(0f, 0f, layout.width, layout.height);
LunePlates.Polygon(painter, Corners(rect), Track);
if (_fraction > 0f)
{
var filled = new Rect(0f, 0f, Mathf.Max(1f, rect.width * _fraction), rect.height);
LunePlates.Polygon(painter, Corners(filled), _fill);
LunePlates.Line(painter, new Vector2(0f, .5f), new Vector2(filled.width, .5f), new Color(1f, 1f, 1f, .28f), 1f);
}
for (int index = 1; index < Ticks; index++)
{
float x = Mathf.Round(rect.width * index / Ticks);
LunePlates.Line(painter, new Vector2(x, 0f), new Vector2(x, rect.height), new Color(0f, 0f, 0f, .45f), 1f);
}
LunePlates.Outline(painter, Corners(new Rect(.5f, .5f, rect.width - 1f, rect.height - 1f)), new Color(1f, 1f, 1f, .12f), 1f);
}
public static Vector2[] Corners(Rect rect)
{
return new[] { rect.min, new Vector2(rect.xMax, rect.yMin), rect.max, new Vector2(rect.xMin, rect.yMax) };
}
/// Green above 60 %, amber above 30 %, red below; the team colour when given.
public static Color HealthColor(float value, Color? baseColor = null)
{
if (value > .6f)
return baseColor ?? LuneUiTheme.Good;
if (value > .3f)
return LuneUiTheme.Warn;
return LuneUiTheme.Danger;
}
}
///
/// One building as a symbol in the team's shape language (round = Blau, angular = Rot) with its
/// HP as a bar underneath (Godot LuneTowerIndicator). Destroyed buildings remain as a hollow
/// outline with a cross.
///
public sealed class LuneTowerIndicator : VisualElement
{
public int Team;
public string Tier = "outer";
public bool Alive = true;
public float Fraction = 1f;
public bool Attackable;
public LuneTowerIndicator(float width = 22f, float height = 27f)
{
pickingMode = PickingMode.Position;
style.width = width;
style.height = height;
style.flexShrink = 0f;
generateVisualContent += Draw;
}
public bool SetState(bool alive, float fraction, bool attackable)
{
float value = Mathf.Round(Mathf.Clamp01(fraction) * 100f) / 100f;
if (alive == Alive && Mathf.Approximately(value, Fraction) && attackable == Attackable)
return false;
Alive = alive;
Fraction = value;
Attackable = attackable;
MarkDirtyRepaint();
return true;
}
void Draw(MeshGenerationContext context)
{
Painter2D painter = context.painter2D;
float edge = Mathf.Min(layout.width, layout.height - 5f);
var box = new Rect((layout.width - edge) * .5f, 0f, edge, edge);
Color tint = LuneUiTheme.TeamColor(Team);
string shape = "shape_" + Mathf.Clamp(Team, 0, 1);
if (Alive)
{
LuneGlyphs.Draw(painter, shape, box, LuneUiTheme.Lightened(LuneUiTheme.TeamDark[Mathf.Clamp(Team, 0, 1)], .1f));
LuneGlyphs.Draw(painter, shape, Grow(box, -edge * .08f), LuneUiTheme.WithAlpha(tint, .35f));
LuneGlyphs.Draw(painter, Tier == "core" ? "ancient" : "tower", Grow(box, -edge * .24f), LuneUiTheme.Hex("f4efe4"));
var bar = new Rect(box.x + 1f, layout.height - 3f, box.width - 2f, 3f);
LunePlates.Polygon(painter, LuneHpBar.Corners(bar), new Color(0f, 0f, 0f, .6f));
if (Fraction > 0f)
LunePlates.Polygon(painter, LuneHpBar.Corners(new Rect(bar.x, bar.y, bar.width * Fraction, bar.height)), LuneHpBar.HealthColor(Fraction, tint));
}
else
{
LuneGlyphs.Draw(painter, shape, box, new Color(0f, 0f, 0f, .35f));
LuneGlyphs.Draw(painter, "close", Grow(box, -edge * .18f), new Color(.5f, .52f, .55f, .8f));
}
}
static Rect Grow(Rect rect, float amount)
{
return new Rect(rect.x - amount, rect.y - amount, rect.width + amount * 2f, rect.height + amount * 2f);
}
}
///
/// Small labelled state (RUHIG, KRITISCH, BEREIT, BOT …; Godot LuneStatusBadge). Always colour
/// plus text and, where it helps, a symbol; never colour alone.
///
public sealed class LuneStatusBadge : VisualElement
{
readonly LuneGlyphElement _glyph;
readonly Label _label;
public string Text { get; private set; } = "";
Color _color;
bool _filled;
public LuneStatusBadge()
{
pickingMode = PickingMode.Ignore;
style.flexDirection = FlexDirection.Row;
style.alignItems = Align.Center;
style.alignSelf = Align.Center;
style.flexShrink = 0f;
style.paddingLeft = 7f;
style.paddingRight = 7f;
style.paddingTop = 1f;
style.paddingBottom = 1f;
style.borderTopLeftRadius = 4f;
style.borderTopRightRadius = 4f;
style.borderBottomLeftRadius = 4f;
style.borderBottomRightRadius = 4f;
style.borderLeftWidth = 1f;
style.borderRightWidth = 1f;
style.borderTopWidth = 1f;
style.borderBottomWidth = 1f;
_glyph = LuneUi.Glyph("", Color.white, 12f, this);
_glyph.style.marginRight = 4f;
LuneUi.Show(_glyph, false);
_label = LuneUi.Label("", "HudBadge", this);
}
public void SetState(string text, Color color, string glyph = "", bool filled = false)
{
if (text == Text && color == _color && filled == _filled && glyph == _glyph.Glyph)
return;
Text = text;
_color = color;
_filled = filled;
_label.text = text;
Color ink = filled ? LuneUiTheme.Hex("15110b") : LuneUiTheme.Lightened(color, .15f);
LuneUi.SetColor(_label, ink);
LuneUi.Show(_glyph, !string.IsNullOrEmpty(glyph));
_glyph.Glyph = glyph;
_glyph.Color = ink;
Color background = filled ? LuneUiTheme.WithAlpha(color, .92f) : LuneUiTheme.WithAlpha(LuneUiTheme.Darkened(color, .75f), .85f);
Color border = filled ? LuneUiTheme.Lightened(color, .2f) : color;
style.backgroundColor = background;
style.borderLeftColor = border;
style.borderRightColor = border;
style.borderTopColor = border;
style.borderBottomColor = border;
}
}
/// Tabs with a bronze underline for the open one (Godot LuneTabBar). Select changes only the display; TabChanged fires on input.
public sealed class LuneTabBar : VisualElement
{
public event Action TabChanged;
public int Current { get; private set; }
public readonly System.Collections.Generic.List Tabs = new System.Collections.Generic.List();
public LuneTabBar()
{
pickingMode = PickingMode.Ignore;
style.flexDirection = FlexDirection.Row;
}
public LuneButton AddTab(string title, string tipTitle = "", string tipText = "")
{
var tab = new LuneButton(title, LuneButtons.HudTab, this);
int index = Tabs.Count;
if (index > 0)
tab.style.marginLeft = 2f;
tab.Clicked += () =>
{
Select(index);
TabChanged?.Invoke(index);
};
if (tipTitle.Length > 0)
LuneTooltip.Attach(tab, () => new LuneTip { Title = tipTitle, Text = tipText });
Tabs.Add(tab);
tab.On = index == 0;
return tab;
}
public void Select(int index)
{
Current = Mathf.Clamp(index, 0, Tabs.Count - 1);
for (int i = 0; i < Tabs.Count; i++)
Tabs[i].On = i == Current;
}
}
}