An asset type representing a saved Breakout level (.level). It stores display name, grid layout, cell sizing and renders a thumbnail bitmap by drawing a rounded-rect colored cell for each character using a BlockPalette.
using System;
using Sandbox;
using Sandbox.UI;
namespace Breakout;
/// <summary>
/// A saved level, stored as a .level asset. Layout is the grid of characters, where each character
/// maps to a brick through the spawner's palette. RenderThumbnail draws a small preview of that
/// layout, so the asset shows the actual board in the editor's asset browser.
/// </summary>
[AssetType( Name = "Breakout Level", Extension = "level", Category = "Breakout" )]
public sealed class LevelResource : GameResource
{
[Property] public string DisplayName { get; set; }
[Hide] public List<string> Layout { get; set; } = new();
[Property] public float TopOffset { get; set; } = 80f;
[Property, Group( "Grid" )] public float CellWidth { get; set; } = 0f;
[Property, Group( "Grid" )] public float CellHeight { get; set; } = 0f;
/// <summary>
/// Draws the small preview image the editor shows for this .level asset, rendering the brick layout so the board is recognisable in the asset browser.
/// </summary>
public override Bitmap RenderThumbnail( ThumbnailOptions options )
{
if ( Layout is null || Layout.Count == 0 )
return null;
int rows = Layout.Count;
int cols = 0;
foreach ( var row in Layout )
cols = Math.Max( cols, row?.Length ?? 0 );
if ( cols == 0 )
return null;
int width = options.Width > 0 ? options.Width : 256;
int height = options.Height > 0 ? options.Height : 256;
var bitmap = new Bitmap( width, height );
bitmap.SetAntialias( true );
bitmap.Clear( BlockPalette.Background );
float pad = width * 0.06f;
float cell = MathF.Min( (width - pad * 2f) / cols, (height - pad * 2f) / rows );
float startX = (width - cell * cols) * 0.5f;
float startY = (height - cell * rows) * 0.5f;
float inset = MathF.Max( 1f, cell * 0.06f );
float radius = MathF.Max( 1.5f, cell * 0.16f );
for ( int r = 0; r < rows; r++ )
{
var row = Layout[r];
for ( int c = 0; c < cols; c++ )
{
char symbol = row is not null && c < row.Length ? row[c] : '.';
float x = startX + c * cell;
float y = startY + r * cell;
bitmap.SetFill( BlockPalette.ColorFor( symbol ) );
bitmap.DrawRoundRect( new Rect( x + inset, y + inset, cell - inset * 2f, cell - inset * 2f ), new Margin( radius ) );
}
}
return bitmap;
}
}