Passenger/driver sit still in moving cars: seat pose sent relative to the vehicle (backward-compatible), no backward pull; remote cars/traffic extrapolate in physics time and interpolate; UI polish (shadows, borders, gradient buttons, server list hover, fill bars, colored ping)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
33a415139b
commit
ce2fbdfc10
+46
-9
@@ -13,7 +13,7 @@ namespace MSCO
|
||||
enum Page { P2P, ServerBrowser, Favorites }
|
||||
|
||||
const float Width = 760f;
|
||||
const float Height = 460f;
|
||||
const float Height = 500f;
|
||||
const float SidebarWidth = 190f;
|
||||
const float StatusHeight = 36f;
|
||||
|
||||
@@ -51,6 +51,8 @@ namespace MSCO
|
||||
|
||||
bool stylesReady;
|
||||
Texture2D texBackground, texSidebar, texAccent, texOnline, texPending, texMuted, texRow;
|
||||
Texture2D texDivider, texGold, texBarBack, texBarFill, texBarFull;
|
||||
GUIStyle rowHoverBox, pingGoodStyle, pingMidStyle, pingBadStyle;
|
||||
List<ServerListEntry> shownAll, shownServers; // Stand des letzten Layout-Durchgangs
|
||||
string layoutError;
|
||||
GUIStyle dangerStyle;
|
||||
@@ -87,6 +89,7 @@ namespace MSCO
|
||||
|
||||
var window = new Rect((Screen.width - Width) / 2f, (Screen.height - Height) / 2f, Width, Height);
|
||||
ScreenRect = window;
|
||||
UiTheme.DrawShadow(window);
|
||||
GUI.Box(window, GUIContent.none, windowBox);
|
||||
|
||||
DrawSidebar(new Rect(window.x, window.y, SidebarWidth, Height - StatusHeight));
|
||||
@@ -120,6 +123,7 @@ namespace MSCO
|
||||
}
|
||||
GUI.Label(new Rect(textX, r.y + 24, r.xMax - textX, 40), "MSCO", logoStyle);
|
||||
GUI.Label(new Rect(r.x + 22, r.y + 70, r.width - 30, 20), "MY SUMMER CAR ONLINE", taglineStyle);
|
||||
GUI.DrawTexture(new Rect(r.x + 20, r.y + 98, r.width - 40, 1), texDivider);
|
||||
|
||||
float y = r.y + 110;
|
||||
if (NavButton(new Rect(r.x, y, r.width, 42), "P2P", page == Page.P2P)) page = Page.P2P;
|
||||
@@ -234,7 +238,7 @@ namespace MSCO
|
||||
GUI.Label(new Rect(header.x + header.width * 0.62f, header.y, 70, header.height), "TYPE", headerCellStyle);
|
||||
GUI.Label(new Rect(header.x + header.width * 0.76f, header.y, 50, header.height), "PING", headerCellStyle);
|
||||
|
||||
serverScroll = GUILayout.BeginScrollView(serverScroll, GUILayout.Height(140));
|
||||
serverScroll = GUILayout.BeginScrollView(serverScroll, GUILayout.Height(180));
|
||||
if (shownError != null) GUILayout.Label(shownError, textStyle);
|
||||
if (servers.Count == 0)
|
||||
GUILayout.Label(browser.Loading ? "Loading servers..." : all.Count > 0 ? "No servers match your filters." : "No servers online right now.", textStyle);
|
||||
@@ -242,7 +246,10 @@ namespace MSCO
|
||||
{
|
||||
Rect row = GUILayoutUtility.GetRect(10, 34, GUILayout.ExpandWidth(true));
|
||||
// Hervorgehobene Server (Keymaster-Admin) stehen oben - der Master liefert sie zuerst
|
||||
GUI.Box(new Rect(row.x, row.y + 2, row.width, row.height - 4), GUIContent.none, s.Featured ? featuredRowBox : rowBox);
|
||||
var rowRect = new Rect(row.x, row.y + 2, row.width, row.height - 4);
|
||||
bool hover = rowRect.Contains(Event.current.mousePosition);
|
||||
GUI.Box(rowRect, GUIContent.none, s.Featured ? featuredRowBox : hover ? rowHoverBox : rowBox);
|
||||
if (s.Featured) GUI.DrawTexture(new Rect(row.x, row.y + 8, 3, row.height - 16), texGold);
|
||||
|
||||
// Herz: als Favorit merken / entfernen (vor dem Zeilen-Knopf, damit es den Klick bekommt)
|
||||
Heart(new Rect(row.xMax - 58, row.y + 7, 20, 20), s);
|
||||
@@ -266,9 +273,14 @@ namespace MSCO
|
||||
nameX += Pill(nameX, row, "v" + s.Version, pillStyle); // abweichende Version
|
||||
}
|
||||
GUI.Label(new Rect(nameX, row.y, row.x + row.width * 0.49f - nameX, row.height), s.Name, rowNameStyle);
|
||||
GUI.Label(new Rect(row.x + row.width * 0.5f, row.y, 70, row.height), s.Players + "/" + s.MaxPlayers, rowNameStyle);
|
||||
// Spielerzahl mit Füllbalken (wie auf der Website)
|
||||
float px = row.x + row.width * 0.5f;
|
||||
GUI.Label(new Rect(px, row.y - 3, 70, row.height), s.Players + "/" + s.MaxPlayers, rowNameStyle);
|
||||
float fill = s.MaxPlayers > 0 ? Mathf.Clamp01((float)s.Players / s.MaxPlayers) : 0f;
|
||||
GUI.DrawTexture(new Rect(px, row.y + 24, 48, 3), texBarBack);
|
||||
GUI.DrawTexture(new Rect(px, row.y + 24, Mathf.Max(2f, 48 * fill), 3), fill >= 1f ? texBarFull : texBarFill);
|
||||
Pill(row.x + row.width * 0.62f, row, s.RequireSteam ? "STEAM" : "NO STEAM", s.RequireSteam ? pillStyle : pillMutedStyle);
|
||||
GUI.Label(new Rect(row.x + row.width * 0.76f, row.y, 50, row.height), s.Ping < 0 ? "..." : s.Ping + " ms", rowNameStyle);
|
||||
GUI.Label(new Rect(row.x + row.width * 0.76f, row.y, 60, row.height), s.Ping < 0 ? "..." : s.Ping + " ms", PingStyle(s.Ping));
|
||||
GUI.Label(new Rect(row.xMax - 30, row.y, 20, row.height), "›", headerCellStyle); // Hinweis: Profil öffnen
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
@@ -354,7 +366,7 @@ namespace MSCO
|
||||
GUILayout.Space(8);
|
||||
|
||||
List<Favorites.Favorite> favs = Favorites.All;
|
||||
favoritesScroll = GUILayout.BeginScrollView(favoritesScroll, GUILayout.Height(220));
|
||||
favoritesScroll = GUILayout.BeginScrollView(favoritesScroll, GUILayout.Height(250));
|
||||
if (favs.Count == 0)
|
||||
GUILayout.Label("No favorites yet. Click the heart next to a server in the Server Browser, or add one by address below.", textStyle);
|
||||
Favorites.Favorite remove = null;
|
||||
@@ -562,7 +574,7 @@ namespace MSCO
|
||||
InfoLine("VERSION", "v" + s.Version + (versionOk ? "" : " (you: v" + MSCO.ModVersion + ")"), versionOk ? rowNameStyle : badgeStyle);
|
||||
InfoLine("STEAM", s.RequireSteam ? "Required" : "Not required", rowNameStyle);
|
||||
InfoLine("ONLINE FOR", s.UptimeSeconds >= 0 ? FormatUptime(s.UptimeSeconds) : "-", rowNameStyle);
|
||||
InfoLine("PING", s.Ping < 0 ? "-" : s.Ping + " ms", rowNameStyle);
|
||||
InfoLine("PING", s.Ping < 0 ? "-" : s.Ping + " ms", PingStyle(s.Ping));
|
||||
InfoLine("ADDRESS", s.Address + ":" + s.Port, rowNameStyle);
|
||||
GUILayout.EndVertical();
|
||||
GUILayout.Space(16);
|
||||
@@ -617,6 +629,13 @@ namespace MSCO
|
||||
GUILayout.Space(2);
|
||||
}
|
||||
|
||||
/// <summary>Ping farbig: grün gut, gelb geht so, rot schlecht.</summary>
|
||||
GUIStyle PingStyle(int ping)
|
||||
{
|
||||
if (ping < 0) return rowNameStyle;
|
||||
return ping < 80 ? pingGoodStyle : ping < 160 ? pingMidStyle : pingBadStyle;
|
||||
}
|
||||
|
||||
static string FormatUptime(int seconds)
|
||||
{
|
||||
int days = seconds / 86400, hours = seconds / 3600 % 24, minutes = seconds / 60 % 60;
|
||||
@@ -698,6 +717,7 @@ namespace MSCO
|
||||
|
||||
var r = new Rect((Screen.width - PromptWidth) / 2f, (Screen.height - PromptHeight) / 2f, PromptWidth, PromptHeight);
|
||||
ScreenRect = new Rect(0, 0, Screen.width, Screen.height); // Spielmenü dahinter komplett sperren
|
||||
UiTheme.DrawShadow(r);
|
||||
GUI.Box(r, GUIContent.none, windowBox);
|
||||
string title = reconnecting
|
||||
? ((mp.ReconnectMessage ?? "").StartsWith("Switching") ? "SWITCHING SERVER" : "RECONNECTING")
|
||||
@@ -783,6 +803,7 @@ namespace MSCO
|
||||
{
|
||||
var r = new Rect((Screen.width - 220) / 2f, 0, 220, 30);
|
||||
ScreenRect = r;
|
||||
UiTheme.DrawShadow(r);
|
||||
GUI.Box(r, GUIContent.none, sidebarBox);
|
||||
GUI.Box(new Rect(r.x + 10, r.yMax - 3, r.width - 20, 3), GUIContent.none, accentBox);
|
||||
Texture2D dot = mp.IsFullyConnected ? texOnline : mp.IsInSession || mp.IsReconnecting ? texPending : texMuted;
|
||||
@@ -809,9 +830,16 @@ namespace MSCO
|
||||
texPending = UiTheme.Rounded(Pending, 4);
|
||||
texMuted = UiTheme.Rounded(Muted, 4);
|
||||
texRow = Solid(Field);
|
||||
windowBox = UiTheme.Panel9(Background, 10);
|
||||
sidebarBox = UiTheme.Panel9(Sidebar, 10);
|
||||
// Fenster und Seitenleiste mit feinem Rand (Seitenleiste: ihr Rand trennt sie vom Inhalt)
|
||||
windowBox = UiTheme.Card(Background, 10);
|
||||
sidebarBox = UiTheme.Card(Sidebar, 10);
|
||||
rowBox = UiTheme.Panel9(Field, UiTheme.Radius);
|
||||
rowHoverBox = UiTheme.Card(FieldFocus, UiTheme.Radius);
|
||||
texDivider = Solid(new Color(1f, 1f, 1f, 0.07f));
|
||||
texGold = Solid(Gold);
|
||||
texBarBack = Solid(new Color(1f, 1f, 1f, 0.1f));
|
||||
texBarFill = Solid(Online);
|
||||
texBarFull = Solid(UiTheme.Danger);
|
||||
accentBox = UiTheme.Panel9(Accent, 1);
|
||||
|
||||
pillStyle = UiTheme.Panel9(new Color(Accent.r, Accent.g, Accent.b, 0.18f), 4);
|
||||
@@ -846,6 +874,12 @@ namespace MSCO
|
||||
headerCellStyle.alignment = TextAnchor.MiddleLeft;
|
||||
rowNameStyle = Label(14, Color.white, FontStyle.Normal);
|
||||
rowNameStyle.alignment = TextAnchor.MiddleLeft;
|
||||
pingGoodStyle = new GUIStyle(rowNameStyle);
|
||||
pingGoodStyle.normal.textColor = Online;
|
||||
pingMidStyle = new GUIStyle(rowNameStyle);
|
||||
pingMidStyle.normal.textColor = Pending;
|
||||
pingBadStyle = new GUIStyle(rowNameStyle);
|
||||
pingBadStyle.normal.textColor = UiTheme.DangerHover;
|
||||
rowTagStyle = Label(11, Accent, FontStyle.Bold);
|
||||
rowTagStyle.alignment = TextAnchor.MiddleRight;
|
||||
badgeStyle = new GUIStyle(rowTagStyle);
|
||||
@@ -859,6 +893,7 @@ namespace MSCO
|
||||
toggleStyle.fontStyle = FontStyle.Bold;
|
||||
|
||||
navStyle = Button(Sidebar, Secondary, Muted, 14, FontStyle.Normal);
|
||||
navStyle.hover.textColor = Color.white; // Hover: Text hell (vorher blieb er grau)
|
||||
navStyle.alignment = TextAnchor.MiddleLeft;
|
||||
navStyle.padding = new RectOffset(26, 10, 0, 0);
|
||||
navActiveStyle = Button(Secondary, Secondary, Color.white, 14, FontStyle.Bold);
|
||||
@@ -866,9 +901,11 @@ namespace MSCO
|
||||
navActiveStyle.padding = new RectOffset(26, 10, 0, 0);
|
||||
|
||||
primaryStyle = Button(Accent, AccentHover, Color.white, 14, FontStyle.Bold);
|
||||
UiTheme.ApplyPrimaryGradient(primaryStyle);
|
||||
dangerStyle = Button(UiTheme.Danger, UiTheme.DangerHover, Color.white, 13, FontStyle.Bold);
|
||||
secondaryStyle = Button(Secondary, SecondaryHover, Color.white, 14, FontStyle.Bold);
|
||||
tabStyle = Button(Sidebar, Secondary, Muted, 11, FontStyle.Bold);
|
||||
tabStyle.hover.textColor = Color.white;
|
||||
|
||||
fieldStyle = UiTheme.Field(14);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user