UI/LobbyRoomPreview.cs
using Sandbox;
using Sandbox.UI;
using System.Linq;
namespace Prototype;
public sealed class LobbyRoomPreview : ScenePanel
{
    private CameraComponent _camera;
    private readonly GameObject[] _runners = new GameObject[4];
    public LobbyRoomPreview()
    {
        RenderScene = new Scene();
        using(RenderScene.Push())
        {
            var camera = _camera = new GameObject(true,"Lobby camera").Components.Create<CameraComponent>();
            camera.WorldPosition=new Vector3(390,0,115);
            camera.WorldRotation=Rotation.LookAt(new Vector3(0,0,55)-camera.WorldPosition);
            camera.Orthographic=true; camera.OrthographicHeight=230; camera.FieldOfView=65; camera.BackgroundColor=new Color(.025f,.04f,.065f);
            var stone=Material.Load("materials/prototype/ruin_stone.vmat");
            CreateStoneBox(new Vector3(80,0,-12),new Vector3(900,1500,24),stone);
            CreateStoneBox(new Vector3(-140,0,150),new Vector3(30,1500,324),stone);
            CreateStoneBox(new Vector3(-115,0,220),new Vector3(40,1500,24),stone);
            CreateStoneBox(new Vector3(-115,0,12),new Vector3(40,1500,24),stone);
            for(int i=0;i<4;i++)
            {
                float y=(i-1.5f)*100;
                _runners[i]=new GameObject(true,"Preview runner");
                _runners[i].WorldPosition=new Vector3(0,y,0);
                _runners[i].Components.Create<SkinnedModelRenderer>().Model=Model.Load("models/review/dasher_v003/body.vmdl");
                CreateStoneBox(new Vector3(-115,y,105),new Vector3(25,22,210),stone);
            }
            foreach(var y in new[]{-180f,180f})
            {
                var torch=new GameObject(true,"Lobby torch"); torch.WorldPosition=new Vector3(-122,y,108);
                torch.Components.Create<ModelRenderer>().Model=Model.Load("models/production/torch_v001/torch.vmdl");
                torch.Components.Create<BrazierFire>();
            }
            Light(new Vector3(160,0,200),new Color(.5f,.68f,1f)*.8f,700);
            new GameObject(true,"Ambient").Components.Create<AmbientLight>().Color=new Color(.2f,.23f,.3f);
        }
    }
    private void CreateStoneBox(Vector3 position,Vector3 scale,Material material)
    {
        var go=new GameObject(true,"Stone room"); go.WorldPosition=position;
        var renderer=go.Components.Create<ModelRenderer>();renderer.Model=Model.Load("models/dev/box.vmdl");renderer.MaterialOverride=material;
        var bounds=renderer.Model.Bounds; go.WorldScale=scale/bounds.Size; go.WorldPosition=position-bounds.Center*go.WorldScale;
    }
    private void Light(Vector3 position,Color color,float radius)
    {
        var go=new GameObject(true,"Lobby light");go.WorldPosition=position;
        var light=go.Components.Create<PointLight>();light.LightColor=color;light.Radius=radius;
    }
    public override void Tick()
    {
        base.Tick();
        var game=PrototypeGame.Instance;
        var count=game?.AllPartyRooms.FirstOrDefault(r=>r.Id==game.LocalPartyId).MemberCount ?? 1;
        count=System.Math.Max(1,count);
        var aspect=Box.Rect.Height>0 ? Box.Rect.Width/Box.Rect.Height : 1.6f;
        for(int i=0;i<4;i++)
        {
            _runners[i].Enabled=i<count;
            // Match the four equal UI columns, from camera-left to camera-right.
            _runners[i].WorldPosition=new Vector3(0,(i-1.5f)*.23f*_camera.OrthographicHeight*aspect,0);
        }
    }
    public override void OnDeleted() { RenderScene?.Destroy(); base.OnDeleted(); }
}