OMRVisualFoundation.Subjects.cs
using Sandbox;

/// <summary>
/// Independent first-person viewmodel presentation controls.
///
/// Historical note: this partial originally also owned character/player tint
/// controls. Those experimental subject controls have been removed. The file
/// name is retained to make this update drop-in safe without requiring a delete
/// step in existing projects.
/// </summary>
public sealed partial class OMRVisualFoundation
{
    [Property, Group( "Viewmodel Look" ), Title( "Enable Viewmodel Look" )]
    [Description( "Master switch for the dedicated first-person viewmodel treatment. The viewmodel remains visible when disabled; only its stylization is bypassed." )]
    public bool EnableViewModelLook { get; set; } = false;

    [Property, Group( "Viewmodel Look" ), Range( 0f, 1f ), Title( "Blend Weight" )]
    [Description( "Blends between the untreated viewmodel render target and the independently treated result." )]
    public float ViewModelBlendWeight { get; set; } = 1f;

    [Button, Group( "Viewmodel Look" ), Title( "Reset Viewmodel Look" )]
    public void ResetViewModelLook()
    {
        EnableViewModelLook = false;
        ViewModelBlendWeight = 1f;
        EnableViewModelPixelate = false;
        ViewModelPixelateScale = 0f;
        EnableViewModelColorAdjustments = false;
        ViewModelBrightness = 1f;
        ViewModelContrast = 1f;
        ViewModelSaturation = 1f;
        ViewModelHueRotate = 0f;
        ViewModelTint = Color.White;
        ViewModelTintStrength = 0f;
        EnableViewModelFilmGrain = false;
        ViewModelFilmGrainIntensity = 0f;
        ViewModelFilmGrainResponse = 0.5f;
    }

    [Property, Group( "Viewmodel Look/Pixelate" ), Title( "Enable Pixelate" )]
    public bool EnableViewModelPixelate { get; set; } = false;

    [Property, Group( "Viewmodel Look/Pixelate" ), Range( 0f, 1f ), Title( "Pixelate Scale" )]
    public float ViewModelPixelateScale { get; set; } = 0f;

    [Property, Group( "Viewmodel Look/Color" ), Title( "Enable Color Adjustments" )]
    public bool EnableViewModelColorAdjustments { get; set; } = false;

    [Property, Group( "Viewmodel Look/Color" ), Range( 0f, 2f ), Title( "Brightness" )]
    public float ViewModelBrightness { get; set; } = 1f;

    [Property, Group( "Viewmodel Look/Color" ), Range( 0f, 2f ), Title( "Contrast" )]
    public float ViewModelContrast { get; set; } = 1f;

    [Property, Group( "Viewmodel Look/Color" ), Range( 0f, 2f ), Title( "Saturation" )]
    public float ViewModelSaturation { get; set; } = 1f;

    [Property, Group( "Viewmodel Look/Color" ), Range( -180f, 180f ), Title( "Hue Rotate" )]
    public float ViewModelHueRotate { get; set; } = 0f;

    [Property, Group( "Viewmodel Look/Color" ), Title( "Tint" )]
    public Color ViewModelTint { get; set; } = Color.White;

    [Property, Group( "Viewmodel Look/Color" ), Range( 0f, 1f ), Title( "Tint Strength" )]
    public float ViewModelTintStrength { get; set; } = 0f;

    [Property, Group( "Viewmodel Look/Film Grain" ), Title( "Enable Film Grain" )]
    public bool EnableViewModelFilmGrain { get; set; } = false;

    [Property, Group( "Viewmodel Look/Film Grain" ), Range( 0f, 1f ), Title( "Intensity" )]
    public float ViewModelFilmGrainIntensity { get; set; } = 0f;

    [Property, Group( "Viewmodel Look/Film Grain" ), Range( 0f, 1f ), Title( "Tonal Response" )]
    [Description( "0 = uniform grain strength. Higher values bias the legacy procedural grain toward darker image regions." )]
    public float ViewModelFilmGrainResponse { get; set; } = 0.5f;

    public float EffectiveViewModelLookBlend =>
        EnableViewModelLook
            ? MathX.Clamp( ViewModelBlendWeight, 0f, 1f )
            : 0f;

    public float EffectiveViewModelPixelateScale =>
        EnableViewModelLook && EnableViewModelPixelate
            ? MathX.Clamp( ViewModelPixelateScale, 0f, 1f )
            : 0f;

    public bool EffectiveViewModelColorAdjustmentsEnabled =>
        EnableViewModelLook && EnableViewModelColorAdjustments;

    public float EffectiveViewModelBrightness =>
        MathX.Clamp( ViewModelBrightness, 0f, 2f );

    public float EffectiveViewModelContrast =>
        MathX.Clamp( ViewModelContrast, 0f, 2f );

    public float EffectiveViewModelSaturation =>
        MathX.Clamp( ViewModelSaturation, 0f, 2f );

    public float EffectiveViewModelHueRotate =>
        MathX.Clamp( ViewModelHueRotate, -180f, 180f );

    public Color EffectiveViewModelTint => ViewModelTint;

    public float EffectiveViewModelTintStrength =>
        EnableViewModelLook
            ? MathX.Clamp( ViewModelTintStrength, 0f, 1f )
            : 0f;

    public float EffectiveViewModelFilmGrainIntensity =>
        EnableViewModelLook && EnableViewModelFilmGrain
            ? MathX.Clamp( ViewModelFilmGrainIntensity, 0f, 1f )
            : 0f;

    public float EffectiveViewModelFilmGrainResponse =>
        MathX.Clamp( ViewModelFilmGrainResponse, 0f, 1f );
}