A UI Panel Razor component that displays a list of subtitle lines. It subscribes to SubtitleBus.OnSubtitle, stores recent lines with expirations, renders speaker and text, limits to 3 lines, and removes expired lines each Tick.
@using System
@using System.Linq
@using System.Collections.Generic
@using Sandbox
@using Sandbox.UI
@namespace BrickJam.UI
@inherits Panel
<root>
@foreach ( var line in lines )
{
<div class="subtitle">
@if ( !string.IsNullOrEmpty( line.Speaker ) )
{
<span class="speaker">@line.Speaker:</span>
}
<span class="text">@line.Text</span>
</div>
}
</root>
@code {
private readonly List<(string Speaker, string Text, TimeUntil Expire)> lines = new();
public SubtitlesList()
{
SubtitleBus.OnSubtitle += Add;
}
public override void OnDeleted()
{
base.OnDeleted();
SubtitleBus.OnSubtitle -= Add;
}
private void Add( string speaker, string text, float duration )
{
lines.Add( (speaker, text, duration) );
if ( lines.Count > 3 )
lines.RemoveAt( 0 );
}
public override void Tick()
{
lines.RemoveAll( l => l.Expire );
}
protected override int BuildHash() => HashCode.Combine( lines.Count, lines.LastOrDefault().Text );
}
<style>
SubtitlesList {
position: absolute;
left: 0; right: 0;
bottom: 60px;
flex-direction: column;
align-items: center;
.subtitle {
flex-direction: row;
padding: 6px 16px;
margin-top: 4px;
background-color: rgba(0,0,0,0.6);
font-size: 26px;
text-shadow: 2px 2px 0px black;
.speaker { color: rgba(255,220,80,1); margin-right: 8px; }
.text { color: white; }
}
}
</style>