101 lines
3.8 KiB
C#
101 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);
|
|
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.Panel9(new Color(0.06f, 0.06f, 0.07f, 0.88f), 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;
|
|
}
|
|
}
|
|
}
|