Skip to content

Commit df2f3f0

Browse files
committed
nameplate ready to ship now aswell
1 parent 286517b commit df2f3f0

8 files changed

Lines changed: 3268 additions & 30 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
// Exposes internal pure solve helpers (spine chain placement, remote bone chain composition, etc.)
22
// to the editor sweep/test assembly so the offline sweeps exercise the real runtime math.
33
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("BasisEditor")]
4+
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Basis.Framework.IK.Tests")]

Basis/Packages/com.basis.framework/Tests/Editor/Basis.Framework.IK.Tests.asmdef

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"Basis Framework",
66
"BasisCommon",
77
"BasisGizmos",
8+
"Unity.TextMeshPro",
89
"Unity.Collections",
910
"Unity.Mathematics",
1011
"Unity.Burst",
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
using Basis.Scripts.Device_Management;
2+
using Basis.Scripts.UI.NamePlate;
3+
using NUnit.Framework;
4+
using TMPro;
5+
using UnityEngine;
6+
7+
namespace Basis.Tests.IK
8+
{
9+
/// <summary>
10+
/// End-to-end regression tests for the nameplate avatar-loading display: a real
11+
/// BasisRemoteNamePlate component with a real TMP label and SpriteRenderer bar,
12+
/// driven through the real <see cref="BasisRemoteNamePlate.ProgressReport"/> path —
13+
/// including the BasisDeviceManagement main-thread queue the reports marshal
14+
/// through (drained manually here since no event driver runs in edit mode).
15+
/// Pins show-on-first-report, bar sizing every report, quantized label rewrites,
16+
/// hide-on-completion, the culled state tracking without object writes, and the
17+
/// (pre-existing) inactive-plate guard.
18+
/// </summary>
19+
public class BasisNamePlateLoadingDisplayTests
20+
{
21+
private GameObject _root;
22+
private BasisRemoteNamePlate _plate;
23+
private Texture2D _texture;
24+
private Sprite _sprite;
25+
26+
[SetUp]
27+
public void SetUp()
28+
{
29+
DrainMainThreadQueue();
30+
31+
_root = new GameObject("PlateUnderTest");
32+
_plate = _root.AddComponent<BasisRemoteNamePlate>();
33+
34+
GameObject textGo = new GameObject("LoadingText");
35+
textGo.transform.SetParent(_root.transform, false);
36+
_plate.LoadingText = textGo.AddComponent<TextMeshPro>();
37+
38+
GameObject barGo = new GameObject("LoadingBar");
39+
barGo.transform.SetParent(_root.transform, false);
40+
SpriteRenderer bar = barGo.AddComponent<SpriteRenderer>();
41+
_texture = new Texture2D(4, 4);
42+
_sprite = Sprite.Create(_texture, new Rect(0, 0, 4, 4), new Vector2(0.5f, 0.5f));
43+
bar.sprite = _sprite;
44+
bar.drawMode = SpriteDrawMode.Sliced;
45+
_plate.LoadingBar = bar;
46+
47+
// Mirror the prefab's resting state: overlays hidden until a report shows them.
48+
textGo.SetActive(false);
49+
barGo.SetActive(false);
50+
}
51+
52+
[TearDown]
53+
public void TearDown()
54+
{
55+
DrainMainThreadQueue();
56+
if (_root != null) Object.DestroyImmediate(_root);
57+
if (_sprite != null) Object.DestroyImmediate(_sprite);
58+
if (_texture != null) Object.DestroyImmediate(_texture);
59+
}
60+
61+
private static void DrainMainThreadQueue()
62+
{
63+
while (BasisDeviceManagement.mainThreadActions.TryDequeue(out System.Action action))
64+
{
65+
action?.Invoke();
66+
}
67+
}
68+
69+
private void Report(float progress, string info)
70+
{
71+
_plate.ProgressReport("test", progress, info);
72+
DrainMainThreadQueue();
73+
}
74+
75+
[Test]
76+
public void MidLoadReport_ShowsBarAndText()
77+
{
78+
Report(50f, "Downloading 50%");
79+
80+
Assert.IsTrue(_plate.HasProgressBarVisible);
81+
Assert.IsTrue(_plate.LoadingText.gameObject.activeSelf);
82+
Assert.IsTrue(_plate.LoadingBar.gameObject.activeSelf);
83+
Assert.AreEqual("Downloading 50%", _plate.LoadingText.text);
84+
Assert.AreEqual(25f, _plate.LoadingBar.size.x, 1e-3f);
85+
}
86+
87+
[Test]
88+
public void BarTracksEveryReport_TextRewritesPerBucket()
89+
{
90+
Report(41f, "Downloading 41%");
91+
Assert.AreEqual("Downloading 41%", _plate.LoadingText.text);
92+
Assert.AreEqual(20.5f, _plate.LoadingBar.size.x, 1e-3f);
93+
94+
// Same 5% bucket: the bar moves, the label deliberately does not re-tessellate.
95+
Report(44f, "Downloading 44%");
96+
Assert.AreEqual("Downloading 41%", _plate.LoadingText.text);
97+
Assert.AreEqual(22f, _plate.LoadingBar.size.x, 1e-3f);
98+
99+
// New bucket: label catches up.
100+
Report(46f, "Downloading 46%");
101+
Assert.AreEqual("Downloading 46%", _plate.LoadingText.text);
102+
}
103+
104+
[Test]
105+
public void CompletionReport_HidesBoth()
106+
{
107+
Report(50f, "Downloading 50%");
108+
Report(100f, "Avatar ready");
109+
110+
Assert.IsFalse(_plate.HasProgressBarVisible);
111+
Assert.IsFalse(_plate.LoadingText.gameObject.activeSelf);
112+
Assert.IsFalse(_plate.LoadingBar.gameObject.activeSelf);
113+
}
114+
115+
[Test]
116+
public void InstantLoad_OnlyCompletionReport_StaysHidden()
117+
{
118+
Report(100f, "Avatar ready");
119+
120+
Assert.IsFalse(_plate.HasProgressBarVisible);
121+
Assert.IsFalse(_plate.LoadingText.gameObject.activeSelf);
122+
Assert.IsFalse(_plate.LoadingBar.gameObject.activeSelf);
123+
}
124+
125+
[Test]
126+
public void NewLoadAfterCompletion_ShowsAgainWithFreshText()
127+
{
128+
Report(60f, "Downloading 60%");
129+
Report(100f, "Avatar ready");
130+
Report(10f, "Downloading 10%");
131+
132+
Assert.IsTrue(_plate.LoadingText.gameObject.activeSelf);
133+
Assert.IsTrue(_plate.LoadingBar.gameObject.activeSelf);
134+
Assert.AreEqual("Downloading 10%", _plate.LoadingText.text);
135+
Assert.AreEqual(5f, _plate.LoadingBar.size.x, 1e-3f);
136+
}
137+
138+
[Test]
139+
public void CulledPlate_TracksStateWithoutTouchingObjects_ThenShowsOnReadmission()
140+
{
141+
Report(30f, "Downloading 30%");
142+
Assert.IsTrue(_plate.LoadingBar.gameObject.activeSelf);
143+
144+
_plate.SetLoadingOverlayCulled(true);
145+
Assert.IsFalse(_plate.LoadingText.gameObject.activeSelf);
146+
Assert.IsFalse(_plate.LoadingBar.gameObject.activeSelf);
147+
148+
// Culled: state advances, objects stay untouched.
149+
Report(70f, "Downloading 70%");
150+
Assert.IsTrue(_plate.HasProgressBarVisible);
151+
Assert.IsFalse(_plate.LoadingBar.gameObject.activeSelf);
152+
Assert.AreEqual("Downloading 30%", _plate.LoadingText.text);
153+
154+
// Readmitted: objects return and the next report refreshes the stale label.
155+
_plate.SetLoadingOverlayCulled(false);
156+
Assert.IsTrue(_plate.LoadingText.gameObject.activeSelf);
157+
Assert.IsTrue(_plate.LoadingBar.gameObject.activeSelf);
158+
Report(72f, "Downloading 72%");
159+
Assert.AreEqual("Downloading 72%", _plate.LoadingText.text);
160+
Assert.AreEqual(36f, _plate.LoadingBar.size.x, 1e-3f);
161+
}
162+
163+
[Test]
164+
public void InactivePlate_SkipsReports()
165+
{
166+
// Pre-existing guard: reports for a deactivated plate are dropped, not queued.
167+
_root.SetActive(false);
168+
Report(50f, "Downloading 50%");
169+
170+
Assert.IsFalse(_plate.HasProgressBarVisible);
171+
Assert.IsFalse(_plate.LoadingText.gameObject.activeSelf);
172+
}
173+
}
174+
}

Basis/Packages/com.basis.framework/Tests/Editor/BasisNamePlateLoadingDisplayTests.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Basis/Packages/com.basis.framework/UI/NamePlate/BasisNamePlateOverlayLimiter.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@ public static class BasisNamePlateOverlayLimiter
1818
/// <summary>Chat bubbles rendered at once — the nearest win.</summary>
1919
public static int MaxVisibleChatBubbles = 24;
2020

21-
/// <summary>Avatar-loading texts + bars rendered at once — the nearest win.</summary>
22-
public static int MaxVisibleLoadingDisplays = 16;
21+
/// <summary>
22+
/// Avatar-loading texts + bars rendered at once — the nearest win. Generous on
23+
/// purpose: the bucket quantization already bounds the TMP rebuild cost, so this
24+
/// only limits draw calls, and a mass join legitimately has dozens of players
25+
/// loading at once — capping tighter reads as "the loading bar is broken".
26+
/// </summary>
27+
public static int MaxVisibleLoadingDisplays = 64;
2328

2429
/// <summary>
2530
/// Seconds a created-but-empty chat display may idle before its TMP + bubble objects

Basis/Packages/com.basis.sdk/Fonts/Inter_24pt-Bold SDF.asset

Lines changed: 1216 additions & 10 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)