Files

102 lines
3.8 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace MSCO
{
/// <summary>
/// Kleine Hinweise oben rechts (unter der Ping-Anzeige), z.B. "Bob joined" / "Bob left".
/// Gleiten von rechts herein, bleiben ein paar Sekunden und blenden dann aus. Höchstens 4 gleichzeitig.
/// </summary>
public class Toasts
{
const float Lifetime = 4.5f;
const float SlideIn = 0.25f;
const float FadeOut = 0.6f;
const float Width = 250f;
const float Height = 36f;
const int MaxShown = 4;
class Toast
{
public string Text;
public string Detail;
public Color Dot;
public float Start;
}
readonly List<Toast> toasts = new List<Toast>();
GUIStyle box, title, detail;
Texture2D dotTex;
public void Add(string text, string detail, Color dot)
{
toasts.Add(new Toast { Text = text, Detail = detail, Dot = dot, Start = Time.realtimeSinceStartup });
if (toasts.Count > MaxShown) toasts.RemoveAt(0);
}
public void Draw()
{
if (toasts.Count == 0) return;
EnsureStyles();
float now = Time.realtimeSinceStartup;
toasts.RemoveAll(t => now - t.Start > Lifetime);
Color before = GUI.color;
float y = 40f; // unter der Ping-Anzeige
for (int i = toasts.Count - 1; i >= 0; i--) // neueste oben
{
Toast t = toasts[i];
float age = now - t.Start;
float slide = Mathf.Clamp01(age / SlideIn);
slide = 1f - (1f - slide) * (1f - slide); // weich abbremsen
float alpha = Mathf.Clamp01((Lifetime - age) / FadeOut);
var r = new Rect(Screen.width - 12 - Width + (1f - slide) * (Width + 20f), y, Width, Height);
GUI.color = new Color(1f, 1f, 1f, alpha);
UiTheme.DrawShadow(r);
GUI.Box(r, GUIContent.none, box);
GUI.color = new Color(t.Dot.r, t.Dot.g, t.Dot.b, alpha);
GUI.DrawTexture(new Rect(r.x + 14, r.y + Height / 2f - 4, 8, 8), dotTex);
GUI.color = new Color(1f, 1f, 1f, alpha);
GUI.Label(new Rect(r.x + 32, r.y, r.width - 40, Height), t.Text, title);
if (!string.IsNullOrEmpty(t.Detail))
{
float w = title.CalcSize(new GUIContent(t.Text)).x;
GUI.Label(new Rect(r.x + 32 + w + 6, r.y, r.width - 46 - w, Height), t.Detail, detail);
}
y += Height + 6f;
}
GUI.color = before;
}
void EnsureStyles()
{
if (box != null && box.normal.background != null) return;
box = UiTheme.Card(new Color(0.06f, 0.06f, 0.07f, 0.92f), 6);
title = new GUIStyle(GUI.skin.label) { fontSize = 13, fontStyle = FontStyle.Bold, alignment = TextAnchor.MiddleLeft };
title.normal.textColor = Color.white;
title.wordWrap = false;
detail = new GUIStyle(title) { fontStyle = FontStyle.Normal, fontSize = 12 };
detail.normal.textColor = UiTheme.Muted;
dotTex = RoundDot(16);
}
static Texture2D RoundDot(int size)
{
var t = new Texture2D(size, size, TextureFormat.ARGB32, false);
float c = (size - 1) / 2f;
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
{
float d = Mathf.Sqrt((x - c) * (x - c) + (y - c) * (y - c));
t.SetPixel(x, y, new Color(1f, 1f, 1f, Mathf.Clamp01(c + 0.5f - d)));
}
t.Apply();
t.hideFlags = HideFlags.HideAndDontSave;
return t;
}
}
}