Editor/UpgradedShaderGraph/Core/ComboDeclaration.cs

Data types for shader combo declarations used by an upgraded shader graph editor. Defines small wrapper structs for combo names/groups, enums for combo type/mode, and ComboDeclaration which stores combo metadata, validates it, and builds HLSL-related variable/feature names.

Reflection
namespace Editor.ShaderGraphExtras;
public struct ComboName
{
	[Hide]
	public string Name { get; set; }

	public static implicit operator string( ComboName comboName ) => comboName.Name;
	public static implicit operator ComboName( string name ) => new ComboName { Name = name };

	public override string ToString() => Name ?? "";
}
public struct ComboGroup
{
	[Hide]
	public string Group { get; set; }

	public static implicit operator string( ComboGroup comboGroup ) => comboGroup.Group;
	public static implicit operator ComboGroup( string name ) => new ComboGroup { Group = name };

	public override string ToString() => Group ?? "";
}
public enum ComboType
{
	Bool,
	Enum
}
public enum ComboMode
{
	Static,
	Dynamic
}
public class ComboDeclaration
{
	public string HLSLName { get; set; }
	public string DisplayName { get; set; }
	public string Group { get; set; }
	public ComboType Type { get; set; }
	public ComboMode Mode { get; set; }
	public int Range { get; set; }
	public string[] Labels { get; set; }
	public int Value { get; set; }
	public bool IsValid()
	{
		if ( string.IsNullOrWhiteSpace( HLSLName ) || !IsValidHLSLIdentifier( HLSLName ) )
			return false;

		if ( string.IsNullOrWhiteSpace( DisplayName ) )
			return false;

		if ( Type == ComboType.Enum && Range < 1 )
			return false;

		int maxValue = Type == ComboType.Bool ? 1 : Range;
		if ( Value < 0 || Value > maxValue )
			return false;

		if ( Labels != null && Labels.Length > 0 )
		{
			int expectedLabels = Type == ComboType.Bool ? 2 : (Range + 1);
			if ( Labels.Length != expectedLabels )
				return false;
		}

		return true;
	}

	private static bool IsValidHLSLIdentifier( string name )
	{
		if ( string.IsNullOrWhiteSpace( name ) )
			return false;

		if ( !char.IsLetter( name[0] ) && name[0] != '_' )
			return false;

		return name.All( c => char.IsLetterOrDigit( c ) || c == '_' );
	}

	public string GetComboVariableName()
	{
		return Mode == ComboMode.Static ? $"S_{HLSLName}" : $"D_{HLSLName}";
	}

	public string GetFeatureName()
	{
		return $"F_{HLSLName}";
	}
}