Editor/SeamlessSuiteAboutDialog.cs
using System;
using System.IO;
using Editor;
using Sandbox;

public sealed class SeamlessSuiteAboutDialog : Dialog
{
	private const string VersionText = "0.1.0 editor preview";
	private const string AuthorText = "Forsomethings";
	private const string PackageText = "forsomethings.seamless";

	public SeamlessSuiteAboutDialog()
	{
		Window.WindowTitle = "About Seam-Less™ Material Suite";
		Window.Size = new Vector2( 540, 500 );
		Window.MinimumWidth = 480;
		Window.SetWindowIcon( "info" );

		Layout = Layout.Column();
		Layout.Margin = 18;
		Layout.Spacing = 12;

		var banner = new SeamlessSuiteBannerWidget( this );
		Layout.Add( banner );

		var text = new Label(
			"Seam-Less™ Material Suite is an editor toolkit for preparing game-ready PBR materials directly in s&box.\n\n" +
			"It includes a Seam-Less tool for helping make textures tile more cleanly, plus a PBR Generator for creating full stack PBR maps including albedo, height, normal, roughness, ambient occlusion, metallic, and ORM maps from a single image.\n\n" +
			"The generated PBR maps are practical estimates. They are meant to give you a useful starting point that can be adjusted, previewed, and exported quickly and are not ment to be perfect or as good as baked hand crafted maps.",
			this );
		text.WordWrap = true;
		text.TextSelectable = true;
		text.SetStyles( "font-size: 12px; color: #dddddd; line-height: 1.35;" );
		Layout.Add( text, 1 );

		var infoPanel = new Widget( this );
		infoPanel.Layout = Layout.Column();
		infoPanel.Layout.Margin = 10;
		infoPanel.Layout.Spacing = 5;
		infoPanel.SetStyles( "background-color: #202020; border: 1px solid #303030; border-radius: 4px;" );
		Layout.Add( infoPanel );

		AddInfoRow( infoPanel, "Author", AuthorText );
		AddInfoRow( infoPanel, "Version", VersionText );
		AddInfoRow( infoPanel, "Library", PackageText );

		var buttonRow = Layout.AddRow();
		buttonRow.AddStretchCell();

		var closeButton = new Button( "Close", this );
		closeButton.MinimumWidth = 90;
		closeButton.Clicked = () => Close();
		buttonRow.Add( closeButton );
	}

	private static void AddInfoRow( Widget parent, string labelText, string valueText )
	{
		var row = new Widget( parent );
		row.Layout = Layout.Row();
		row.Layout.Spacing = 8;

		var label = new Label( labelText, row );
		label.FixedWidth = 72;
		label.SetStyles( "font-size: 12px; color: #9f9f9f; font-weight: bold;" );
		row.Layout.Add( label );

		var value = new Label( valueText, row );
		value.TextSelectable = true;
		value.SetStyles( "font-size: 12px; color: #eeeeee;" );
		row.Layout.Add( value, 1 );

		parent.Layout.Add( row );
	}

}

internal sealed class SeamlessSuiteBannerWidget : Widget
{
	private const float BannerHeight = 150f;
	private const string BannerFileName = "seamlessLOGO-Banner.png";
	private const string FallbackTitle = "Seam-Less™ Material Suite";
	private readonly Pixmap bannerPixmap = LoadBannerPixmap();

	public SeamlessSuiteBannerWidget( Widget parent ) : base( parent )
	{
		FixedHeight = BannerHeight;
		MinimumHeight = BannerHeight;
		NoSystemBackground = true;
	}

	protected override void OnPaint()
	{
		if ( bannerPixmap == null )
		{
			Paint.ClearPen();
			Paint.SetBrush( new Color( 0.06f, 0.06f, 0.065f ) );
			Paint.DrawRect( LocalRect, 3 );
			Paint.SetDefaultFont( 18, 700, false, false );
			Paint.SetPen( Theme.TextLight );
			Paint.DrawText( LocalRect, FallbackTitle, TextFlag.Center );
			return;
		}

		var scale = MathF.Max(
			LocalRect.Width / Math.Max( 1f, bannerPixmap.Width ),
			LocalRect.Height / Math.Max( 1f, bannerPixmap.Height )
		);
		var width = bannerPixmap.Width * scale;
		var height = bannerPixmap.Height * scale;
		var imageRect = new Rect(
			(LocalRect.Width - width) * 0.5f,
			(LocalRect.Height - height) * 0.5f,
			width,
			height
		);

		Paint.BilinearFiltering = true;
		Paint.Draw( imageRect, bannerPixmap, 1f, 3 );
	}

	private static Pixmap LoadBannerPixmap()
	{
		try
		{
			var path = FindBannerPath();

			if ( string.IsNullOrWhiteSpace( path ) )
				return null;

			return Pixmap.FromBitmap( SeamlessSuiteImageUtility.LoadBitmapFromFile( path ) );
		}
		catch ( Exception ex )
		{
			Log.Info( $"Seam-Less: Falling back to text banner because the image could not be loaded: {ex.Message}" );
			return null;
		}
	}

	private static string FindBannerPath()
	{
		var projectRoot = Sandbox.Project.Current?.GetRootPath();

		if ( string.IsNullOrWhiteSpace( projectRoot ) )
			return null;

		var librariesFolder = Path.Combine( projectRoot, "Libraries" );

		if ( !Directory.Exists( librariesFolder ) )
			return null;

		foreach ( var libraryFolder in Directory.EnumerateDirectories( librariesFolder ) )
		{
			var path = Path.Combine( libraryFolder, "Assets", "UI", BannerFileName );

			if ( File.Exists( path ) )
				return path;
		}

		return null;
	}
}