UI/Foundation/OMRMainMenuLayout.cs
using Sandbox;
using System;

public enum OMRImageFit
{
	Cover,
	Contain,
	Fill
}

public enum OMRMenuShellMode
{
	Panel,
	FullScreenCanvas
}

public enum OMRTextHorizontalAlignment
{
	Left,
	Center,
	Right
}

/// <summary>
/// Developer-authored layout values for menu, lobby, settings and pause UI.
/// Values are expressed in ScreenPanel logical pixels unless noted otherwise.
/// </summary>
[AssetType(
	Name = "OMR Main Menu Layout",
	Extension = "omrmenu",
	Category = "One More Round/UI"
)]
public sealed partial class OMRMainMenuLayout : GameResource
{
	[Group( "Background" ), Title( "Image Fit" )]
	public OMRImageFit BackgroundFit { get; set; } = OMRImageFit.Cover;
	[Group( "Background" ), Range( 0f, 100f ), Title( "Zoom Origin X (%)" )]
	public float BackgroundPositionXPercent { get; set; } = 50f;

	[Group( "Background" ), Range( 0f, 100f ), Title( "Zoom Origin Y (%)" )]
	public float BackgroundPositionYPercent { get; set; } = 50f;

	[Group( "Background" ), Range( 100f, 200f ), Title( "Image Zoom (%)" )]
	public float BackgroundZoomPercent { get; set; } = 110f;

	[Group( "Background" ), Range( -600f, 600f ), Step( 1f ), Title( "Pan X (px)" )]
	public float BackgroundOffsetX { get; set; }

	[Group( "Background" ), Range( -400f, 400f ), Step( 1f ), Title( "Pan Y (px)" )]
	public float BackgroundOffsetY { get; set; }

	[Group( "Background" ), Title( "Show Screen Overlay" )]
	public bool ShowScreenOverlay { get; set; } = true;

	[Group( "Background" ), Range( 0f, 1f ), ShowIf( nameof( ShowScreenOverlay ), true ), Title( "Overlay Opacity" )]
	public float ScreenOverlayOpacity { get; set; } = 1f;

	[Group( "Shell" ), Title( "Layout Mode" )]
	public OMRMenuShellMode ShellMode { get; set; } = OMRMenuShellMode.Panel;

	[Group( "Shell" ), Range( 480f, 1400f ), Step( 10f ), Title( "Panel Width" )]
	public float ShellWidth { get; set; } = 780f;

	[Group( "Shell" ), Range( 40f, 100f ), Title( "Maximum Height (%)" )]
	public float ShellMaxHeightPercent { get; set; } = 90f;

	[Group( "Shell" ), Range( 0f, 100f )]
	public float ShellPadding { get; set; } = 36f;

	[Group( "Shell" ), Range( -600f, 600f ), Step( 1f ), Title( "Horizontal Offset" )]
	public float ShellOffsetX { get; set; }

	[Group( "Shell" ), Range( -400f, 400f ), Step( 1f ), Title( "Vertical Offset" )]
	public float ShellOffsetY { get; set; }

	[Group( "Shell" ), Title( "Show Shell Background / Border / Shadow" )]
	public bool ShowShellChrome { get; set; } = true;

	[Group( "Shell" ), Range( 0f, 1f ), ShowIf( nameof( ShowShellChrome ), true ), Title( "Shell Chrome Opacity" )]
	public float ShellChromeOpacity { get; set; } = 1f;

	[Hide]
	public float ShellBorderRadius { get; set; }

	[Group( "Brand" ), Title( "Show Brand Block" )]
	public bool ShowBrand { get; set; } = true;

	[Group( "Brand" ), Range( 0f, 1f ), ShowIf( nameof( ShowBrand ), true ), Title( "Brand Opacity" )]
	public float BrandOpacity { get; set; } = 1f;

	[Group( "Brand" ), Range( -500f, 500f ), Title( "Brand X Offset" )]
	public float BrandOffsetX { get; set; }

	[Group( "Brand" ), Range( -300f, 300f ), Title( "Brand Y Offset" )]
	public float BrandOffsetY { get; set; }

	[Group( "Brand" ), Title( "Show Logo" )]
	public bool ShowLogo { get; set; } = true;

	[Group( "Brand" ), Range( 0f, 700f ), Step( 2f ), ShowIf( nameof( ShowLogo ), true )]
	public float LogoWidth { get; set; } = 360f;

	[Group( "Brand" ), Title( "Logo Image Fit" )]
	public OMRImageFit LogoFit { get; set; } = OMRImageFit.Contain;

	[Group( "Brand" ), Range( 0f, 400f ), Step( 2f )]
	public float LogoHeight { get; set; } = 120f;

	[Group( "Brand" ), Range( -500f, 500f ), Step( 1f ), Title( "Logo X Offset" )]
	public float LogoOffsetX { get; set; }

	[Group( "Brand" ), Range( -300f, 300f ), Step( 1f ), Title( "Logo Y Offset" )]
	public float LogoOffsetY { get; set; }

	[Group( "Brand" ), Range( 0f, 100f ), Title( "Logo Bottom Spacing" )]
	public float LogoBottomSpacing { get; set; } = 8f;

	[Group( "Brand" ), Range( 0f, 1f ), Title( "Logo Opacity" )]
	public float LogoOpacity { get; set; } = 1f;

	[Group( "Brand" ), Title( "Show Title" )]
	public bool ShowTitle { get; set; } = true;

	[Group( "Brand" ), Range( 0f, 1f ), ShowIf( nameof( ShowTitle ), true ), Title( "Title Opacity" )]
	public float TitleOpacity { get; set; } = 1f;

	[Group( "Brand" ), Title( "Show Subtitle" )]
	public bool ShowSubtitle { get; set; } = true;

	[Group( "Brand" ), Range( 0f, 1f ), ShowIf( nameof( ShowSubtitle ), true ), Title( "Subtitle Opacity" )]
	public float SubtitleOpacity { get; set; } = 0.42f;

	[Group( "Brand" ), Range( 18f, 140f )]
	public float TitleSize { get; set; } = 62f;

	[Group( "Brand" ), Range( 0f, 20f )]
	public float TitleLetterSpacing { get; set; } = 3f;

	[Group( "Brand" ), Range( -500f, 500f ), Step( 1f ), Title( "Title X Offset" )]
	public float TitleOffsetX { get; set; }

	[Group( "Brand" ), Range( -300f, 300f ), Step( 1f ), Title( "Title Y Offset" )]
	public float TitleOffsetY { get; set; }

	[Group( "Brand" ), Title( "Title Alignment" )]
	public OMRTextHorizontalAlignment TitleAlignment { get; set; } = OMRTextHorizontalAlignment.Center;

	[Group( "Brand" ), Range( 0f, 200f ), Step( 1f ), Title( "Title Indent" )]
	public float TitleIndent { get; set; }

	[Group( "Brand" ), Range( 8f, 48f )]
	public float SubtitleSize { get; set; } = 14f;

	[Group( "Brand" ), Range( 0f, 20f )]
	public float SubtitleLetterSpacing { get; set; } = 5f;

	[Group( "Brand" ), Range( -500f, 500f ), Title( "Subtitle X Offset" )]
	public float SubtitleOffsetX { get; set; }

	[Group( "Brand" ), Range( -300f, 300f ), Title( "Subtitle Y Offset" )]
	public float SubtitleOffsetY { get; set; }

	[Group( "Brand" ), Title( "Subtitle Alignment" )]
	public OMRTextHorizontalAlignment SubtitleAlignment { get; set; } = OMRTextHorizontalAlignment.Center;

	[Group( "Brand" ), Range( 0f, 200f ), Step( 1f ), Title( "Subtitle Indent" )]
	public float SubtitleIndent { get; set; }

	[Group( "Brand" ), Range( 0f, 80f )]
	public float BrandBottomSpacing { get; set; } = 24f;

	[Group( "Navigation" ), Range( -500f, 500f ), Step( 1f ), Title( "Whole Page Stack X Offset" )]
	public float NavigationOffsetX { get; set; }

	[Group( "Navigation" ), Range( -300f, 300f ), Step( 1f ), Title( "Whole Page Stack Y Offset" )]
	public float NavigationOffsetY { get; set; }

	[Group( "Navigation" ), Title( "Show Routed Page Content" )]
	public bool ShowNavigation { get; set; } = true;

	[Group( "Navigation" ), Range( 0f, 1f ), ShowIf( nameof( ShowNavigation ), true ), Title( "Routed Page Opacity" )]
	public float NavigationOpacity { get; set; } = 1f;

	[Group( "Navigation" ), Title( "Page Element Alignment" )]
	public OMRTextHorizontalAlignment NavigationContentAlignment { get; set; } = OMRTextHorizontalAlignment.Center;

	[Group( "Buttons" ), Title( "Show Button Background / Border" )]
	public bool ShowButtonChrome { get; set; } = true;

	[Group( "Buttons" ), Title( "Show Button Descriptions" )]
	public bool ShowButtonDescriptions { get; set; } = true;

	[Group( "Buttons" ), Range( 240f, 1000f ), Step( 10f )]
	public float ButtonWidth { get; set; } = 500f;

	[Group( "Buttons" ), Range( 40f, 180f )]
	public float ButtonHeight { get; set; } = 88f;

	[Group( "Buttons" ), Range( 100f, 120f ), Step( 0.1f ), Title( "Hover Scale (%)" )]
	public float ButtonHoverScalePercent { get; set; } = 101.5f;

	[Group( "Buttons" ), Range( -60f, 60f ), Step( 1f ), Title( "Hover X Shift" )]
	public float ButtonHoverOffsetX { get; set; }

	[Group( "Buttons" ), Range( -60f, 60f ), Step( 1f ), Title( "Hover Y Shift" )]
	public float ButtonHoverOffsetY { get; set; }

	[Group( "Buttons" ), Range( 80f, 100f ), Step( 0.1f ), Title( "Pressed Scale (%)" )]
	public float ButtonPressedScalePercent { get; set; } = 98.5f;

	[Group( "Buttons" ), Range( 10f, 60f )]
	public float ButtonTitleSize { get; set; } = 25f;

	[Group( "Buttons" ), Range( 8f, 32f )]
	public float ButtonDescriptionSize { get; set; } = 14f;

	[Group( "Buttons" ), Range( -200f, 200f ), Title( "Button Title X Offset" )]
	public float ButtonTitleOffsetX { get; set; }

	[Group( "Buttons" ), Range( -100f, 100f ), Title( "Button Title Y Offset" )]
	public float ButtonTitleOffsetY { get; set; }

	[Group( "Buttons" ), Title( "Button Title Alignment" )]
	public OMRTextHorizontalAlignment ButtonTitleAlignment { get; set; } = OMRTextHorizontalAlignment.Left;

	[Group( "Buttons" ), Range( 0f, 180f ), Step( 1f ), Title( "Button Title Indent" )]
	public float ButtonTitleIndent { get; set; }

	[Group( "Buttons" ), Range( -200f, 200f ), Title( "Button Description X Offset" )]
	public float ButtonDescriptionOffsetX { get; set; }

	[Group( "Buttons" ), Range( -100f, 100f ), Title( "Button Description Y Offset" )]
	public float ButtonDescriptionOffsetY { get; set; }

	[Group( "Buttons" ), Title( "Button Description Alignment" )]
	public OMRTextHorizontalAlignment ButtonDescriptionAlignment { get; set; } = OMRTextHorizontalAlignment.Left;

	[Group( "Buttons" ), Range( 0f, 180f ), Step( 1f ), Title( "Button Description Indent" )]
	public float ButtonDescriptionIndent { get; set; }

	[Group( "Buttons" ), Title( "Small Action Text Alignment" )]
	public OMRTextHorizontalAlignment ActionTextAlignment { get; set; } = OMRTextHorizontalAlignment.Center;

	[Group( "Buttons" ), Range( 0f, 120f ), Step( 1f ), Title( "Small Action Text Indent" )]
	public float ActionTextIndent { get; set; }

	[Group( "Shared Borders" ), Range( 0f, 8f ), Title( "All UI Borders" )]
	public float BorderWidth { get; set; } = 1f;

	[Group( "Pages" ), Range( 0f, 60f ), Title( "Page Element Gap" )]
	public float ButtonGap { get; set; } = 14f;

	[Group( "Pages" ), Title( "Show Page Copy / Descriptions" )]
	public bool ShowPageCopy { get; set; } = true;

	[Group( "Pages" ), Range( 12f, 72f )]
	public float PageHeadingSize { get; set; } = 31f;

	[Group( "Pages" ), Range( 8f, 32f )]
	public float PageCopySize { get; set; } = 14f;

	[Group( "Pages" ), Range( -400f, 400f ), Title( "Page Heading X Offset" )]
	public float PageHeadingOffsetX { get; set; }

	[Group( "Pages" ), Range( -250f, 250f ), Title( "Page Heading Y Offset" )]
	public float PageHeadingOffsetY { get; set; }

	[Group( "Pages" ), Title( "Page Heading Alignment" )]
	public OMRTextHorizontalAlignment PageHeadingAlignment { get; set; } = OMRTextHorizontalAlignment.Center;

	[Group( "Pages" ), Range( 0f, 200f ), Step( 1f ), Title( "Page Heading Indent" )]
	public float PageHeadingIndent { get; set; }

	[Group( "Pages" ), Range( -400f, 400f ), Title( "Page Copy X Offset" )]
	public float PageCopyOffsetX { get; set; }

	[Group( "Pages" ), Range( -250f, 250f ), Title( "Page Copy Y Offset" )]
	public float PageCopyOffsetY { get; set; }

	[Group( "Pages" ), Title( "Page Copy Alignment" )]
	public OMRTextHorizontalAlignment PageCopyAlignment { get; set; } = OMRTextHorizontalAlignment.Center;

	[Group( "Pages" ), Range( 0f, 200f ), Step( 1f ), Title( "Page Copy Indent" )]
	public float PageCopyIndent { get; set; }

	[Group( "Cards & Settings" ), Title( "Show Player Card Chrome" )]
	public bool ShowPlayerCardChrome { get; set; } = true;

	[Group( "Cards & Settings" ), Title( "Show Settings / Setup Chrome" )]
	public bool ShowSettingsChrome { get; set; } = true;

	[Group( "Cards & Settings" ), Range( 180f, 500f )]
	public float PlayerCardWidth { get; set; } = 270f;

	[Group( "Cards & Settings" ), Range( 70f, 260f )]
	public float PlayerCardHeight { get; set; } = 125f;

	[Group( "Cards & Settings" ), Range( 55f, 180f )]
	public float SettingRowHeight { get; set; } = 82f;

	[Group( "Pause Menu" ), Range( 480f, 1200f )]
	public float PauseWidth { get; set; } = 760f;

	[Group( "Pause Menu" ), Title( "Show Screen Overlay" )]
	public bool ShowPauseOverlay { get; set; } = true;
	[Group( "Pause Menu" ), Range( 0f, 1f ), ShowIf( nameof( ShowPauseOverlay ), true ), Title( "Overlay Opacity" )]
	public float PauseOverlayOpacity { get; set; } = 1f;
	[Group( "Pause Menu" ), Title( "Show Panel Background / Border / Shadow" )]
	public bool ShowPauseChrome { get; set; } = true;
	[Group( "Pause Menu" ), Range( 0f, 1f ), ShowIf( nameof( ShowPauseChrome ), true ), Title( "Panel Chrome Opacity" )]
	public float PauseChromeOpacity { get; set; } = 1f;
	[Group( "Pause Menu" ), Range( -400f, 400f ), Title( "Panel X Offset" )]
	public float PauseOffsetX { get; set; }
	[Group( "Pause Menu" ), Range( -300f, 300f ), Title( "Panel Y Offset" )]
	public float PauseOffsetY { get; set; }

	[Group( "Pause Menu" ), Range( 0f, 100f )]
	public float PausePadding { get; set; } = 32f;

	[Group( "Pause Menu" ), Range( 18f, 80f )]
	public float PauseTitleSize { get; set; } = 36f;

	[Group( "Pause Menu" ), Range( 40f, 140f )]
	public float PauseButtonHeight { get; set; } = 64f;

	public int ContentHash()
	{
		HashCode hash = new();
		hash.Add( BackgroundFit );

		hash.Add( BackgroundPositionXPercent );
		hash.Add( BackgroundPositionYPercent );
		hash.Add( BackgroundZoomPercent );
		hash.Add( BackgroundOffsetX );
		hash.Add( BackgroundOffsetY );
		hash.Add( ShowScreenOverlay );
		hash.Add( ScreenOverlayOpacity );
		hash.Add( ShellMode );
		hash.Add( ShellWidth );
		hash.Add( ShellMaxHeightPercent );
		hash.Add( ShellPadding );
		hash.Add( ShellOffsetX );
		hash.Add( ShellOffsetY );
		hash.Add( ShowShellChrome );
		hash.Add( ShellChromeOpacity );
		hash.Add( ShellBorderRadius );
		hash.Add( ShowBrand );
		hash.Add( BrandOpacity );
		hash.Add( BrandOffsetX );
		hash.Add( BrandOffsetY );
		hash.Add( ShowLogo );
		hash.Add( LogoWidth );
		hash.Add( LogoFit );
		hash.Add( LogoHeight );
		hash.Add( LogoOffsetX );
		hash.Add( LogoOffsetY );
		hash.Add( LogoBottomSpacing );
		hash.Add( LogoOpacity );
		hash.Add( ShowTitle );
		hash.Add( TitleOpacity );
		hash.Add( ShowSubtitle );
		hash.Add( SubtitleOpacity );
		hash.Add( TitleSize );
		hash.Add( TitleLetterSpacing );
		hash.Add( TitleOffsetX );
		hash.Add( TitleOffsetY );
		hash.Add( TitleAlignment );
		hash.Add( TitleIndent );
		hash.Add( SubtitleSize );
		hash.Add( SubtitleLetterSpacing );
		hash.Add( SubtitleOffsetX );
		hash.Add( SubtitleOffsetY );
		hash.Add( SubtitleAlignment );
		hash.Add( SubtitleIndent );
		hash.Add( BrandBottomSpacing );
		hash.Add( NavigationOffsetX );
		hash.Add( NavigationOffsetY );
		hash.Add( ShowNavigation );
		hash.Add( NavigationOpacity );
		hash.Add( NavigationContentAlignment );
		hash.Add( ShowButtonChrome );
		hash.Add( ShowButtonDescriptions );
		hash.Add( ButtonWidth );
		hash.Add( ButtonHeight );
		hash.Add( ButtonHoverScalePercent );
		hash.Add( ButtonHoverOffsetX );
		hash.Add( ButtonHoverOffsetY );
		hash.Add( ButtonPressedScalePercent );
		hash.Add( ButtonGap );
		hash.Add( ButtonTitleSize );
		hash.Add( ButtonDescriptionSize );
		hash.Add( ButtonTitleOffsetX );
		hash.Add( ButtonTitleOffsetY );
		hash.Add( ButtonTitleAlignment );
		hash.Add( ButtonTitleIndent );
		hash.Add( ButtonDescriptionOffsetX );
		hash.Add( ButtonDescriptionOffsetY );
		hash.Add( ButtonDescriptionAlignment );
		hash.Add( ButtonDescriptionIndent );
		hash.Add( ActionTextAlignment );
		hash.Add( ActionTextIndent );
		hash.Add( BorderWidth );
		hash.Add( ShowPageCopy );
		hash.Add( PageHeadingSize );
		hash.Add( PageCopySize );
		hash.Add( PageHeadingOffsetX );
		hash.Add( PageHeadingOffsetY );
		hash.Add( PageHeadingAlignment );
		hash.Add( PageHeadingIndent );
		hash.Add( PageCopyOffsetX );
		hash.Add( PageCopyOffsetY );
		hash.Add( PageCopyAlignment );
		hash.Add( PageCopyIndent );
		hash.Add( ShowPlayerCardChrome );
		hash.Add( ShowSettingsChrome );
		hash.Add( PlayerCardWidth );
		hash.Add( PlayerCardHeight );
		hash.Add( SettingRowHeight );
		hash.Add( PauseWidth );
		hash.Add( ShowPauseOverlay );
		hash.Add( PauseOverlayOpacity );
		hash.Add( ShowPauseChrome );
		hash.Add( PauseChromeOpacity );
		hash.Add( PauseOffsetX );
		hash.Add( PauseOffsetY );
		hash.Add( PausePadding );
		hash.Add( PauseTitleSize );
		hash.Add( PauseButtonHeight );

		return hash.ToHashCode();
	}
}