Grid/CinematicProfile.cs
using Sandbox;
using System.Linq;
using static Sandbox.Tonemapping;

namespace SWB.Visuals;

public abstract class CinematicProfile : Component
{
    // ─────────────────────────────
    // TONEMAPPING
    // ─────────────────────────────

    public abstract TonemappingMode Tonemap { get; }

    // 🔑 FPS-pelissä lukitaan exposure
    public virtual float MinExposure => -1.0f;
    public virtual float MaxExposure => -1.0f;

    // ─────────────────────────────
    // BLOOM
    // ─────────────────────────────

    public abstract bool EnableBloom { get; }
    public abstract float BloomThreshold { get; }

    // ─────────────────────────────
    // COLOR ADJUSTMENTS
    // ─────────────────────────────

    public virtual float Brightness => 0f;
    public virtual float Contrast => 1f;
    public virtual float Saturation => 1f;

    protected override void OnStart()
    {
        ApplyPostProcess();
        ApplyLighting();
    }

    void ApplyPostProcess()
    {
        // ───────── Tonemapping ─────────
        var tonemap = Components.GetOrCreate<Tonemapping>();
        tonemap.Enabled = true;
        tonemap.Mode = Tonemap;
        tonemap.MinimumExposure = MinExposure;
        tonemap.MaximumExposure = MaxExposure;

        // ───────── Bloom ─────────
        var bloom = Components.GetOrCreate<Bloom>();
        bloom.Enabled = EnableBloom;
        bloom.Threshold = BloomThreshold;

        // ───────── Color grading ─────────
        var color = Components.GetOrCreate<ColorAdjustments>();
        color.Enabled = true;
        color.Brightness = Brightness;
        color.Contrast = Contrast;
        color.Saturation = Saturation;
    }

    // ─────────────────────────────
    // LIGHTING
    // ─────────────────────────────
    protected abstract void ApplyLighting();

    // ─────────────────────────────
    // LIGHT HELPER
    // ─────────────────────────────
    protected GameObject GetOrCreateLight(string name)
    {
        var go = Scene.Children.FirstOrDefault(x => x.Name == name);
        if (go == null)
        {
            go = Scene.CreateObject();
            go.Name = name;
        }

        return go;
    }
}