Editor/SuperShotMenu.cs

Editor UI menu builder for the SuperShot tool. It constructs a custom "Supershot" menu in the editor, adds submenus and options for quick captures, package thumbnails, editor window, Discord posting populated at runtime, opening the output folder, and uploading artwork.

File AccessHttp Calls
using Editor;
using Editor.SuperShot;
using Sandbox;

// Built by hand (not [Menu] reflection) so "Post to Discord" can be a real hover submenu populated at runtime.
public static class SuperShotMenu
{
	[Event( "refresh" )]
	public static void BuildMenu()
	{
		var bar = Sandbox.Internal.GlobalToolsNamespace.EditorWindow?.MenuBar;
		if ( bar is null || !bar.IsValid )
			return;

		var root = bar.FindOrCreateMenu( "Supershot" );
		if ( root is null )
			return;

		root.Clear();

		var quick = root.AddMenu( "Quick Capture" );
		quick.AddOption( "1080p", null, () => SuperShotService.QuickCapture( ShotResolution.HD1080 ) );
		quick.AddOption( "1440p", null, () => SuperShotService.QuickCapture( ShotResolution.QHD1440 ) );
		quick.AddOption( "4K", null, () => SuperShotService.QuickCapture( ShotResolution.UHD4K ) );
		quick.AddOption( "8K", null, () => SuperShotService.QuickCapture( ShotResolution.UHD8K ) );

		var pkg = root.AddMenu( "s&box Package" );
		pkg.AddOption( "Square (512x512)", null, () => SuperShotService.QuickCapture( ShotResolution.PackageSquare ) );
		pkg.AddOption( "Wide (910x512)", null, () => SuperShotService.QuickCapture( ShotResolution.PackageWide ) );
		pkg.AddOption( "Tall (512x910)", null, () => SuperShotService.QuickCapture( ShotResolution.PackageTall ) );
		pkg.AddOption( "Capture All Three", null, () => SuperShotService.CaptureAllPackageThumbnails() );

		root.AddOption( "Editor", null, () => SuperShotWindow.Open() );

		var discord = root.AddMenu( "Post to Discord" );
		discord.AboutToShow += () => PopulateDiscordMenu( discord );

		root.AddOption( "Open Output Folder", null, OpenOutputFolder );
		root.AddOption( "Upload Your s&box Artwork", null, () => SuperShotService.CaptureAndUploadToArtPage() );
	}

	static void PopulateDiscordMenu( Menu menu )
	{
		if ( menu is null || !menu.IsValid )
			return;

		menu.Clear();

		var share = SuperShotSettings.Current.Share;
		var configured = share.Webhooks.FindAll( w => w is not null && w.IsConfigured );

		if ( configured.Count == 0 )
		{
			var none = menu.AddOption( "No Discord channels configured" );
			none.Enabled = false;
			menu.AddSeparator();
			menu.AddOption( "Open Discord tab", null, () => SuperShotWindow.Open() );
			return;
		}

		if ( SuperShotService.EnabledWebhooks( share ).Count > 0 )
		{
			menu.AddOption( "Post to all Discord Channels", null, () =>
				_ = new MessagePromptDialog(
					"Post to all Discord Channels",
					"Add an optional message for this post (leave blank to post without one):",
					msg => _ = SuperShotService.CaptureAndPostAll( msg ) ) );
			menu.AddSeparator();
		}

		var favorites = configured.FindAll( w => w.Favorite );
		if ( favorites.Count > 0 )
		{
			var heading = menu.AddOption( "Favorites" );
			heading.Enabled = false;

			foreach ( var wh in favorites )
			{
				var target = wh;
				menu.AddOption( wh.Name, "star", () => _ = SuperShotService.CaptureAndPostTo( target ) );
			}

			menu.AddSeparator();
		}

		foreach ( var wh in configured.FindAll( w => !w.Favorite ) )
		{
			var target = wh;
			menu.AddOption( wh.Name, null, () => _ = SuperShotService.CaptureAndPostTo( target ) );
		}
	}

	static void OpenOutputFolder()
	{
		SuperShotService.RevealInExplorer( SuperShotSettings.Current.Output.ResolveFolder() );
	}
}