🔍 s&box Package Code Search

Search C# source code, UI razor templates, shaders, and configs across s&box packages.

Showing code results for query: * (10 total matches found)
fwotsoft.lightinghelpers / Code/KelvinSliderAttribute.cs
Game library
using System;

namespace RotSoft.Lighting;

/// <summary>Marks a float property as a color temperature in kelvin; the inspector renders it with the kelvin gradient slider.</summary>
[AttributeUsage( AttributeTargets.Property )]
public sealed class KelvinSliderAttribute : Attribute
{
}
fwotsoft.lightinghelpers / Code/Helpers/TemperatureExtensions.cs
Game library
using Sandbox;
using System;

namespace RotSoft.Lighting;

/// <summary>Temperature to color conversions.</summary>
public static class TemperatureExtensions
{
	/// <summary>
	/// Converts this temperature to an sRGB color, clamped to <see cref="Temperature.MinTemperature"/>..<see cref="Temperature.MaxTemperature"/>.
	/// </summary>
	public static Color ToColor( this Temperature temperature )
	{
		float kelvin = Math.Clamp( temperature.Kelvin, Temperature.MinTemperature, Temperature.MaxTemperature );
		float temp = kelvin / 100f;
		float r, g, b;

		if ( temp <= 66f )
			r = 1f;
		else
			r = Math.Clamp( 1.29293618606f * MathF.Pow( temp - 60f, -0.1332047592f ), 0f, 1f );

		if ( temp <= 66f )
			g = Math.Clamp( 0.390081578769f * MathF.Log( temp ) - 0.63184144378f, 0f, 1f );
		else
			g = Math.Clamp( 1.12989086369f * MathF.Pow( temp - 60f, -0.0755148492f ), 0f, 1f );

		if ( temp >= 66f )
			b = 1f;
		else if ( temp <= 19f )
			b = 0f;
		else
			b = Math.Clamp( 0.54320678911f * MathF.Log( temp - 10f ) - 1.19625408914f, 0f, 1f );

		return new Color( r, g, b );
	}
}
fwotsoft.lightinghelpers / LightTemperature.cs
Game library
using Sandbox;

namespace RotSoft.Lighting;




/// <summary>
/// Adjusts the <see cref="Color"/> of a <see cref="Light"/> component using Color <see cref="Temperature"/> in Kelvin.
/// Applies once on add and whenever the temperature or brightness changes, so the light's color stays manually editable.
/// </summary>
[Title( "Light Temperature" )]
[Category( "Light" )]
[Icon( "thermostat" )]
[Alias( "Temperature", "Kelvin" )]
public sealed class LightTemperature : Component, Component.ExecuteInEditor
{
	/// <summary>Common light temperature presets in Kelvin.</summary>
	public enum LightTemperaturePreset
	{
		/// <summary>1000 K</summary>
		MatchFlame = 1700,
		/// <summary>2400 K</summary>
		Incandescent = 2400,
		/// <summary>2700 K</summary>
		WarmWhite = 3000,
		/// <summary>3200 K</summary>
		Studio = 3200,
		/// <summary>5000 K</summary>
		CoolWhite = 5000,
		/// <summary>6500 K</summary>
		Daylight = 6500,
		/// <summary>6500 K</summary>
		LCD = 9500,
		/// <summary>7500 K</summary>
		BlueSky = 15000,
		/// <summary>Custom value, set it with the Kelvin slider.</summary>
		Custom = 0,
	}

	LightTemperaturePreset _preset = LightTemperaturePreset.CoolWhite;
	float _kelvin = 5000f;
	float _brightness = 1f;
	bool _syncing;
	Light _light;

	/// <summary>Standard light temperature presets.</summary>
	[Property]
	public LightTemperaturePreset Preset
	{
		get => _preset;
		set
		{
			if ( _preset == value ) return;
			_preset = value;
			if ( value != LightTemperaturePreset.Custom )
			{
				_syncing = true;
				Kelvin = (float)(int)value;
				_syncing = false;
			}
			else
			{
				ApplyColor();
			}
		}
	}

	/// <summary>The color temperature in Kelvin.</summary>
	[Property, Title( "Temperature (K)" ), Range( 1500, 15000 ), KelvinSlider]
	public float Kelvin
	{
		get => _kelvin;
		set
		{
			if ( _kelvin == value ) return;
			_kelvin = value;
			if ( !_syncing && _preset != LightTemperaturePreset.Custom )
				_preset = LightTemperaturePreset.Custom;
			ApplyColor();
		}
	}

	/// <summary>The brightness (range) of the Light.</summary>
	[Property, Range( 0, 5f ), Step( 0.01f )]
	public float Brightness
	{
		get => _brightness;
		set
		{
			if ( _brightness == value ) return;
			_brightness = value;
			ApplyColor();
		}
	}

	/// <summary>Applies the current temperature and brightness to the <see cref="Light"/>'s color once on add.</summary>
	protected override void OnStart()
	{
		ApplyColor();
	}

	/// <summary>Sets the <see cref="Light"/>'s color from the current temperature and brightness, if a light is present.</summary>
	void ApplyColor()
	{
		_light ??= GetComponentInChildren<Light>( true );
		if ( _light is null ) return;
		_light.LightColor = new Temperature( Kelvin ).ToColor() * Brightness;
	}
}
fwotsoft.lightinghelpers / Temperature.cs
Game library
namespace RotSoft.Lighting;

/// <summary>
/// A color temperature in kelvin, converted to a color via <see cref="TemperatureExtensions.ToColor(Temperature)"/>.
/// </summary>
public struct Temperature
{
	/// <summary>Lowest valid temperature, in kelvin.</summary>
	public const float MinTemperature = 1500f;

	/// <summary>Highest valid temperature, in kelvin.</summary>
	public const float MaxTemperature = 15000f;

	/// <summary>Temperature in kelvin.</summary>
	public float Kelvin { get; set; }

	/// <summary>Creates a temperature from a kelvin value.</summary>
	public Temperature( float kelvin )
	{
		Kelvin = kelvin;
	}

	/// <summary>Implicitly converts a kelvin value to a <see cref="Temperature"/>.</summary>
	public static implicit operator Temperature( float kelvin ) => new( kelvin );

	/// <summary>Implicitly converts a <see cref="Temperature"/> back to its kelvin value.</summary>
	public static implicit operator float( Temperature temperature ) => temperature.Kelvin;

}
fwotsoft.lightinghelpers / Editor/KelvinFloatControlWidget.cs
Editor library
using System;
using Sandbox;
using RotSoft.Lighting;
using Editor;

namespace RotSoft.Lighting;

/// <summary>
/// A <see cref="FloatControlWidget"/> for float properties marked with <see cref="KelvinSliderAttribute"/>:
/// paints the kelvin (blackbody) gradient as the slider track, with a thermostat icon. The property's
/// <see cref="RangeAttribute"/> supplies the track bounds.
/// </summary>
[CustomEditor( typeof( float ), WithAllAttributes = new[] { typeof( KelvinSliderAttribute ) } )]
public class KelvinFloatControlWidget : FloatControlWidget
{
	/// <summary>Cached kelvin gradient strip, rebuilt only when the bar's width (or DPI) changes.</summary>
	Pixmap _gradient;

	/// <summary>Pixel size the gradient was baked at; rebuilt when width or DPI changes.</summary>
	Vector2 _gradientSize;

	public KelvinFloatControlWidget( SerializedProperty property ) : base( property )
	{
		Icon = "thermostat";
		RangeStep = 1f; // snap to whole kelvin so values stay integers, without the [Step] spin arrows

		SliderPaint = ( rect, _ ) =>
		{
			// A thin, full-width track strip (like the regular float slider's track), centered vertically.
			const float TrackHeight = 6f;
			const float ThumbWidth = 6f;
			const float ThumbHeight = 12f;

			var centerY = rect.Top + rect.Height / 2f;
			var track = new Rect( rect.Left, centerY - TrackHeight / 2f, rect.Width, TrackHeight );

			EnsureGradient( track.Width );
			if ( _gradient is not null )
				Paint.Draw( track, _gradient, 1f, TrackHeight / 2f );

			// White thumb at the value position, like the regular float slider.
			var current = SerializedProperty.GetValue<float>();
			var t = MathX.LerpInverse( current, Range.x, Range.y, true ).Clamp( 0f, 1f );
			var thumbX = rect.Left + t * (rect.Width - ThumbWidth);
			Paint.Antialiasing = true;

			// Even soft shadow ring around the thumb, so no bare thumb edge meets the bright gradient.
			Paint.ClearPen();
			Paint.Antialiasing = true;
			Paint.SetBrush( Color.Black.WithAlpha( 0.35f ) );
			Paint.DrawRect( new Rect( thumbX - 1f, centerY - ThumbHeight / 2f - 1f, ThumbWidth + 2f, ThumbHeight + 2f ), 2f );

			// Thumb itself.
			Paint.ClearPen();
			Paint.Antialiasing = true;
			Paint.SetBrush( Color.White.Darken( 0.1f ) );
			Paint.DrawRect( new Rect( thumbX, centerY - ThumbHeight / 2f, ThumbWidth, ThumbHeight ), 2f );
		};
	}

	/// <summary>Bakes the kelvin gradient into a cached pixmap, rebuilt only when the bar's width (or DPI) changes.</summary>
	void EnsureGradient( float width )
	{
		var dpi = DpiScale;
		var size = new Vector2( Math.Max( (int)(width * dpi), 1 ), Math.Max( (int)(10f * dpi), 1 ) );

		if ( _gradient is not null && _gradientSize == size ) return;

		_gradient = new Pixmap( size );
		_gradientSize = size;

		using ( Paint.ToPixmap( _gradient ) )
		{
			Paint.Antialiasing = true;
			Paint.ClearPen();

			int steps = (int)size.x;
			float denom = Math.Max( steps - 1, 1 );
			for ( int i = 0; i < steps; i++ )
			{
				float frac = i / denom;
				Paint.SetBrush( new Temperature( MathX.LerpTo( Range.x, Range.y, frac, true ) ).ToColor() );
				Paint.DrawRect( new Rect( i, 0, 1f, size.y ) );
			}
		}
	}
}
fwotsoft.lightinghelpers / Code/LightTemperature.cs
Game library
using Sandbox;

namespace RotSoft.Lighting;




/// <summary>
/// Adjusts the <see cref="Color"/> of a <see cref="Light"/> component using Color <see cref="Temperature"/> in Kelvin.
/// Applies once on add and whenever the temperature or brightness changes, so the light's color stays manually editable.
/// </summary>
[Title( "Light Temperature" )]
[Category( "Light" )]
[Icon( "thermostat" )]
[Alias( "Temperature", "Kelvin" )]
public sealed class LightTemperature : Component, Component.ExecuteInEditor
{
	/// <summary>Common light temperature presets in Kelvin.</summary>
	public enum LightTemperaturePreset
	{
		/// <summary>1000 K</summary>
		MatchFlame = 1700,
		/// <summary>2400 K</summary>
		Incandescent = 2400,
		/// <summary>2700 K</summary>
		WarmWhite = 3000,
		/// <summary>3200 K</summary>
		Studio = 3200,
		/// <summary>5000 K</summary>
		CoolWhite = 5000,
		/// <summary>6500 K</summary>
		Daylight = 6500,
		/// <summary>6500 K</summary>
		LCD = 9500,
		/// <summary>7500 K</summary>
		BlueSky = 15000,
		/// <summary>Custom value, set it with the Kelvin slider.</summary>
		Custom = 0,
	}

	LightTemperaturePreset _preset = LightTemperaturePreset.CoolWhite;
	float _kelvin = 5000f;
	float _brightness = 1f;
	bool _syncing;
	Light _light;

	/// <summary>Standard light temperature presets.</summary>
	[Property]
	public LightTemperaturePreset Preset
	{
		get => _preset;
		set
		{
			if ( _preset == value ) return;
			_preset = value;
			if ( value != LightTemperaturePreset.Custom )
			{
				_syncing = true;
				Kelvin = (float)(int)value;
				_syncing = false;
			}
			else
			{
				ApplyColor();
			}
		}
	}

	/// <summary>The color temperature in Kelvin.</summary>
	[Property, Title( "Temperature (K)" ), Range( 1500, 15000 ), KelvinSlider]
	public float Kelvin
	{
		get => _kelvin;
		set
		{
			if ( _kelvin == value ) return;
			_kelvin = value;
			if ( !_syncing && _preset != LightTemperaturePreset.Custom )
				_preset = LightTemperaturePreset.Custom;
			ApplyColor();
		}
	}

	/// <summary>The brightness (range) of the Light.</summary>
	[Property, Range( 0, 5f ), Step( 0.01f )]
	public float Brightness
	{
		get => _brightness;
		set
		{
			if ( _brightness == value ) return;
			_brightness = value;
			ApplyColor();
		}
	}

	/// <summary>Applies the current temperature and brightness to the <see cref="Light"/>'s color once on add.</summary>
	protected override void OnStart()
	{
		ApplyColor();
	}

	/// <summary>Sets the <see cref="Light"/>'s color from the current temperature and brightness, if a light is present.</summary>
	void ApplyColor()
	{
		_light ??= GetComponentInChildren<Light>( true );
		if ( _light is null ) return;
		_light.LightColor = new Temperature( Kelvin ).ToColor() * Brightness;
	}
}
fwotsoft.lightinghelpers / Helpers/TemperatureExtensions.cs
Game library
using Sandbox;
using System;

namespace RotSoft.Lighting;

/// <summary>Temperature to color conversions.</summary>
public static class TemperatureExtensions
{
	/// <summary>
	/// Converts this temperature to an sRGB color, clamped to <see cref="Temperature.MinTemperature"/>..<see cref="Temperature.MaxTemperature"/>.
	/// </summary>
	public static Color ToColor( this Temperature temperature )
	{
		float kelvin = Math.Clamp( temperature.Kelvin, Temperature.MinTemperature, Temperature.MaxTemperature );
		float temp = kelvin / 100f;
		float r, g, b;

		if ( temp <= 66f )
			r = 1f;
		else
			r = Math.Clamp( 1.29293618606f * MathF.Pow( temp - 60f, -0.1332047592f ), 0f, 1f );

		if ( temp <= 66f )
			g = Math.Clamp( 0.390081578769f * MathF.Log( temp ) - 0.63184144378f, 0f, 1f );
		else
			g = Math.Clamp( 1.12989086369f * MathF.Pow( temp - 60f, -0.0755148492f ), 0f, 1f );

		if ( temp >= 66f )
			b = 1f;
		else if ( temp <= 19f )
			b = 0f;
		else
			b = Math.Clamp( 0.54320678911f * MathF.Log( temp - 10f ) - 1.19625408914f, 0f, 1f );

		return new Color( r, g, b );
	}
}
fwotsoft.lightinghelpers / Code/Temperature.cs
Game library
namespace RotSoft.Lighting;

/// <summary>
/// A color temperature in kelvin, converted to a color via <see cref="TemperatureExtensions.ToColor(Temperature)"/>.
/// </summary>
public struct Temperature
{
	/// <summary>Lowest valid temperature, in kelvin.</summary>
	public const float MinTemperature = 1500f;

	/// <summary>Highest valid temperature, in kelvin.</summary>
	public const float MaxTemperature = 15000f;

	/// <summary>Temperature in kelvin.</summary>
	public float Kelvin { get; set; }

	/// <summary>Creates a temperature from a kelvin value.</summary>
	public Temperature( float kelvin )
	{
		Kelvin = kelvin;
	}

	/// <summary>Implicitly converts a kelvin value to a <see cref="Temperature"/>.</summary>
	public static implicit operator Temperature( float kelvin ) => new( kelvin );

	/// <summary>Implicitly converts a <see cref="Temperature"/> back to its kelvin value.</summary>
	public static implicit operator float( Temperature temperature ) => temperature.Kelvin;

}
fwotsoft.lightinghelpers / KelvinSliderAttribute.cs
Game library
using System;

namespace RotSoft.Lighting;

/// <summary>Marks a float property as a color temperature in kelvin; the inspector renders it with the kelvin gradient slider.</summary>
[AttributeUsage( AttributeTargets.Property )]
public sealed class KelvinSliderAttribute : Attribute
{
}
fwotsoft.lightinghelpers / .obj/__compiler_extra.cs
Game library
global using static Sandbox.Internal.GlobalGameNamespace;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Rendering;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "Lighting Helpers" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "lightinghelpers" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "fwotsoft" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "fwotsoft.lightinghelpers" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "28" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]

[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "2026-08-27T09:20:31.5361275Z" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.120.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.120.0")]
Debug: View Raw JSON Response
{
    "TotalCount": 10,
    "Files": [
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "Code/KelvinSliderAttribute.cs",
            "FileName": "KelvinSliderAttribute.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "using System;\r\n\r\nnamespace RotSoft.Lighting;\r\n\r\n/// <summary>Marks a float property as a color temperature in kelvin; the inspector renders it with the kelvin gradient slider.</summary>\r\n[AttributeUsage( AttributeTargets.Property )]\r\npublic sealed class KelvinSliderAttribute : Attribute\r\n{\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "Code/Helpers/TemperatureExtensions.cs",
            "FileName": "TemperatureExtensions.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "using Sandbox;\r\nusing System;\r\n\r\nnamespace RotSoft.Lighting;\r\n\r\n/// <summary>Temperature to color conversions.</summary>\r\npublic static class TemperatureExtensions\r\n{\r\n\t/// <summary>\r\n\t/// Converts this temperature to an sRGB color, clamped to <see cref=\"Temperature.MinTemperature\"/>..<see cref=\"Temperature.MaxTemperature\"/>.\r\n\t/// </summary>\r\n\tpublic static Color ToColor( this Temperature temperature )\r\n\t{\r\n\t\tfloat kelvin = Math.Clamp( temperature.Kelvin, Temperature.MinTemperature, Temperature.MaxTemperature );\r\n\t\tfloat temp = kelvin / 100f;\r\n\t\tfloat r, g, b;\r\n\r\n\t\tif ( temp <= 66f )\r\n\t\t\tr = 1f;\r\n\t\telse\r\n\t\t\tr = Math.Clamp( 1.29293618606f * MathF.Pow( temp - 60f, -0.1332047592f ), 0f, 1f );\r\n\r\n\t\tif ( temp <= 66f )\r\n\t\t\tg = Math.Clamp( 0.390081578769f * MathF.Log( temp ) - 0.63184144378f, 0f, 1f );\r\n\t\telse\r\n\t\t\tg = Math.Clamp( 1.12989086369f * MathF.Pow( temp - 60f, -0.0755148492f ), 0f, 1f );\r\n\r\n\t\tif ( temp >= 66f )\r\n\t\t\tb = 1f;\r\n\t\telse if ( temp <= 19f )\r\n\t\t\tb = 0f;\r\n\t\telse\r\n\t\t\tb = Math.Clamp( 0.54320678911f * MathF.Log( temp - 10f ) - 1.19625408914f, 0f, 1f );\r\n\r\n\t\treturn new Color( r, g, b );\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "LightTemperature.cs",
            "FileName": "LightTemperature.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "using Sandbox;\r\n\r\nnamespace RotSoft.Lighting;\r\n\r\n\r\n\r\n\r\n/// <summary>\r\n/// Adjusts the <see cref=\"Color\"/> of a <see cref=\"Light\"/> component using Color <see cref=\"Temperature\"/> in Kelvin.\r\n/// Applies once on add and whenever the temperature or brightness changes, so the light's color stays manually editable.\r\n/// </summary>\r\n[Title( \"Light Temperature\" )]\r\n[Category( \"Light\" )]\r\n[Icon( \"thermostat\" )]\r\n[Alias( \"Temperature\", \"Kelvin\" )]\r\npublic sealed class LightTemperature : Component, Component.ExecuteInEditor\r\n{\r\n\t/// <summary>Common light temperature presets in Kelvin.</summary>\r\n\tpublic enum LightTemperaturePreset\r\n\t{\r\n\t\t/// <summary>1000 K</summary>\r\n\t\tMatchFlame = 1700,\r\n\t\t/// <summary>2400 K</summary>\r\n\t\tIncandescent = 2400,\r\n\t\t/// <summary>2700 K</summary>\r\n\t\tWarmWhite = 3000,\r\n\t\t/// <summary>3200 K</summary>\r\n\t\tStudio = 3200,\r\n\t\t/// <summary>5000 K</summary>\r\n\t\tCoolWhite = 5000,\r\n\t\t/// <summary>6500 K</summary>\r\n\t\tDaylight = 6500,\r\n\t\t/// <summary>6500 K</summary>\r\n\t\tLCD = 9500,\r\n\t\t/// <summary>7500 K</summary>\r\n\t\tBlueSky = 15000,\r\n\t\t/// <summary>Custom value, set it with the Kelvin slider.</summary>\r\n\t\tCustom = 0,\r\n\t}\r\n\r\n\tLightTemperaturePreset _preset = LightTemperaturePreset.CoolWhite;\r\n\tfloat _kelvin = 5000f;\r\n\tfloat _brightness = 1f;\r\n\tbool _syncing;\r\n\tLight _light;\r\n\r\n\t/// <summary>Standard light temperature presets.</summary>\r\n\t[Property]\r\n\tpublic LightTemperaturePreset Preset\r\n\t{\r\n\t\tget => _preset;\r\n\t\tset\r\n\t\t{\r\n\t\t\tif ( _preset == value ) return;\r\n\t\t\t_preset = value;\r\n\t\t\tif ( value != LightTemperaturePreset.Custom )\r\n\t\t\t{\r\n\t\t\t\t_syncing = true;\r\n\t\t\t\tKelvin = (float)(int)value;\r\n\t\t\t\t_syncing = false;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tApplyColor();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/// <summary>The color temperature in Kelvin.</summary>\r\n\t[Property, Title( \"Temperature (K)\" ), Range( 1500, 15000 ), KelvinSlider]\r\n\tpublic float Kelvin\r\n\t{\r\n\t\tget => _kelvin;\r\n\t\tset\r\n\t\t{\r\n\t\t\tif ( _kelvin == value ) return;\r\n\t\t\t_kelvin = value;\r\n\t\t\tif ( !_syncing && _preset != LightTemperaturePreset.Custom )\r\n\t\t\t\t_preset = LightTemperaturePreset.Custom;\r\n\t\t\tApplyColor();\r\n\t\t}\r\n\t}\r\n\r\n\t/// <summary>The brightness (range) of the Light.</summary>\r\n\t[Property, Range( 0, 5f ), Step( 0.01f )]\r\n\tpublic float Brightness\r\n\t{\r\n\t\tget => _brightness;\r\n\t\tset\r\n\t\t{\r\n\t\t\tif ( _brightness == value ) return;\r\n\t\t\t_brightness = value;\r\n\t\t\tApplyColor();\r\n\t\t}\r\n\t}\r\n\r\n\t/// <summary>Applies the current temperature and brightness to the <see cref=\"Light\"/>'s color once on add.</summary>\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tApplyColor();\r\n\t}\r\n\r\n\t/// <summary>Sets the <see cref=\"Light\"/>'s color from the current temperature and brightness, if a light is present.</summary>\r\n\tvoid ApplyColor()\r\n\t{\r\n\t\t_light ??= GetComponentInChildren<Light>( true );\r\n\t\tif ( _light is null ) return;\r\n\t\t_light.LightColor = new Temperature( Kelvin ).ToColor() * Brightness;\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "Temperature.cs",
            "FileName": "Temperature.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "namespace RotSoft.Lighting;\r\n\r\n/// <summary>\r\n/// A color temperature in kelvin, converted to a color via <see cref=\"TemperatureExtensions.ToColor(Temperature)\"/>.\r\n/// </summary>\r\npublic struct Temperature\r\n{\r\n\t/// <summary>Lowest valid temperature, in kelvin.</summary>\r\n\tpublic const float MinTemperature = 1500f;\r\n\r\n\t/// <summary>Highest valid temperature, in kelvin.</summary>\r\n\tpublic const float MaxTemperature = 15000f;\r\n\r\n\t/// <summary>Temperature in kelvin.</summary>\r\n\tpublic float Kelvin { get; set; }\r\n\r\n\t/// <summary>Creates a temperature from a kelvin value.</summary>\r\n\tpublic Temperature( float kelvin )\r\n\t{\r\n\t\tKelvin = kelvin;\r\n\t}\r\n\r\n\t/// <summary>Implicitly converts a kelvin value to a <see cref=\"Temperature\"/>.</summary>\r\n\tpublic static implicit operator Temperature( float kelvin ) => new( kelvin );\r\n\r\n\t/// <summary>Implicitly converts a <see cref=\"Temperature\"/> back to its kelvin value.</summary>\r\n\tpublic static implicit operator float( Temperature temperature ) => temperature.Kelvin;\r\n\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "Editor/KelvinFloatControlWidget.cs",
            "FileName": "KelvinFloatControlWidget.cs",
            "PackageType": "library",
            "CodeKind": "Editor",
            "AssetVersionId": 355266,
            "Code": "using System;\r\nusing Sandbox;\r\nusing RotSoft.Lighting;\r\nusing Editor;\r\n\r\nnamespace RotSoft.Lighting;\r\n\r\n/// <summary>\r\n/// A <see cref=\"FloatControlWidget\"/> for float properties marked with <see cref=\"KelvinSliderAttribute\"/>:\r\n/// paints the kelvin (blackbody) gradient as the slider track, with a thermostat icon. The property's\r\n/// <see cref=\"RangeAttribute\"/> supplies the track bounds.\r\n/// </summary>\r\n[CustomEditor( typeof( float ), WithAllAttributes = new[] { typeof( KelvinSliderAttribute ) } )]\r\npublic class KelvinFloatControlWidget : FloatControlWidget\r\n{\r\n\t/// <summary>Cached kelvin gradient strip, rebuilt only when the bar's width (or DPI) changes.</summary>\r\n\tPixmap _gradient;\r\n\r\n\t/// <summary>Pixel size the gradient was baked at; rebuilt when width or DPI changes.</summary>\r\n\tVector2 _gradientSize;\r\n\r\n\tpublic KelvinFloatControlWidget( SerializedProperty property ) : base( property )\r\n\t{\r\n\t\tIcon = \"thermostat\";\r\n\t\tRangeStep = 1f; // snap to whole kelvin so values stay integers, without the [Step] spin arrows\r\n\r\n\t\tSliderPaint = ( rect, _ ) =>\r\n\t\t{\r\n\t\t\t// A thin, full-width track strip (like the regular float slider's track), centered vertically.\r\n\t\t\tconst float TrackHeight = 6f;\r\n\t\t\tconst float ThumbWidth = 6f;\r\n\t\t\tconst float ThumbHeight = 12f;\r\n\r\n\t\t\tvar centerY = rect.Top + rect.Height / 2f;\r\n\t\t\tvar track = new Rect( rect.Left, centerY - TrackHeight / 2f, rect.Width, TrackHeight );\r\n\r\n\t\t\tEnsureGradient( track.Width );\r\n\t\t\tif ( _gradient is not null )\r\n\t\t\t\tPaint.Draw( track, _gradient, 1f, TrackHeight / 2f );\r\n\r\n\t\t\t// White thumb at the value position, like the regular float slider.\r\n\t\t\tvar current = SerializedProperty.GetValue<float>();\r\n\t\t\tvar t = MathX.LerpInverse( current, Range.x, Range.y, true ).Clamp( 0f, 1f );\r\n\t\t\tvar thumbX = rect.Left + t * (rect.Width - ThumbWidth);\r\n\t\t\tPaint.Antialiasing = true;\r\n\r\n\t\t\t// Even soft shadow ring around the thumb, so no bare thumb edge meets the bright gradient.\r\n\t\t\tPaint.ClearPen();\r\n\t\t\tPaint.Antialiasing = true;\r\n\t\t\tPaint.SetBrush( Color.Black.WithAlpha( 0.35f ) );\r\n\t\t\tPaint.DrawRect( new Rect( thumbX - 1f, centerY - ThumbHeight / 2f - 1f, ThumbWidth + 2f, ThumbHeight + 2f ), 2f );\r\n\r\n\t\t\t// Thumb itself.\r\n\t\t\tPaint.ClearPen();\r\n\t\t\tPaint.Antialiasing = true;\r\n\t\t\tPaint.SetBrush( Color.White.Darken( 0.1f ) );\r\n\t\t\tPaint.DrawRect( new Rect( thumbX, centerY - ThumbHeight / 2f, ThumbWidth, ThumbHeight ), 2f );\r\n\t\t};\r\n\t}\r\n\r\n\t/// <summary>Bakes the kelvin gradient into a cached pixmap, rebuilt only when the bar's width (or DPI) changes.</summary>\r\n\tvoid EnsureGradient( float width )\r\n\t{\r\n\t\tvar dpi = DpiScale;\r\n\t\tvar size = new Vector2( Math.Max( (int)(width * dpi), 1 ), Math.Max( (int)(10f * dpi), 1 ) );\r\n\r\n\t\tif ( _gradient is not null && _gradientSize == size ) return;\r\n\r\n\t\t_gradient = new Pixmap( size );\r\n\t\t_gradientSize = size;\r\n\r\n\t\tusing ( Paint.ToPixmap( _gradient ) )\r\n\t\t{\r\n\t\t\tPaint.Antialiasing = true;\r\n\t\t\tPaint.ClearPen();\r\n\r\n\t\t\tint steps = (int)size.x;\r\n\t\t\tfloat denom = Math.Max( steps - 1, 1 );\r\n\t\t\tfor ( int i = 0; i < steps; i++ )\r\n\t\t\t{\r\n\t\t\t\tfloat frac = i / denom;\r\n\t\t\t\tPaint.SetBrush( new Temperature( MathX.LerpTo( Range.x, Range.y, frac, true ) ).ToColor() );\r\n\t\t\t\tPaint.DrawRect( new Rect( i, 0, 1f, size.y ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "Code/LightTemperature.cs",
            "FileName": "LightTemperature.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "using Sandbox;\r\n\r\nnamespace RotSoft.Lighting;\r\n\r\n\r\n\r\n\r\n/// <summary>\r\n/// Adjusts the <see cref=\"Color\"/> of a <see cref=\"Light\"/> component using Color <see cref=\"Temperature\"/> in Kelvin.\r\n/// Applies once on add and whenever the temperature or brightness changes, so the light's color stays manually editable.\r\n/// </summary>\r\n[Title( \"Light Temperature\" )]\r\n[Category( \"Light\" )]\r\n[Icon( \"thermostat\" )]\r\n[Alias( \"Temperature\", \"Kelvin\" )]\r\npublic sealed class LightTemperature : Component, Component.ExecuteInEditor\r\n{\r\n\t/// <summary>Common light temperature presets in Kelvin.</summary>\r\n\tpublic enum LightTemperaturePreset\r\n\t{\r\n\t\t/// <summary>1000 K</summary>\r\n\t\tMatchFlame = 1700,\r\n\t\t/// <summary>2400 K</summary>\r\n\t\tIncandescent = 2400,\r\n\t\t/// <summary>2700 K</summary>\r\n\t\tWarmWhite = 3000,\r\n\t\t/// <summary>3200 K</summary>\r\n\t\tStudio = 3200,\r\n\t\t/// <summary>5000 K</summary>\r\n\t\tCoolWhite = 5000,\r\n\t\t/// <summary>6500 K</summary>\r\n\t\tDaylight = 6500,\r\n\t\t/// <summary>6500 K</summary>\r\n\t\tLCD = 9500,\r\n\t\t/// <summary>7500 K</summary>\r\n\t\tBlueSky = 15000,\r\n\t\t/// <summary>Custom value, set it with the Kelvin slider.</summary>\r\n\t\tCustom = 0,\r\n\t}\r\n\r\n\tLightTemperaturePreset _preset = LightTemperaturePreset.CoolWhite;\r\n\tfloat _kelvin = 5000f;\r\n\tfloat _brightness = 1f;\r\n\tbool _syncing;\r\n\tLight _light;\r\n\r\n\t/// <summary>Standard light temperature presets.</summary>\r\n\t[Property]\r\n\tpublic LightTemperaturePreset Preset\r\n\t{\r\n\t\tget => _preset;\r\n\t\tset\r\n\t\t{\r\n\t\t\tif ( _preset == value ) return;\r\n\t\t\t_preset = value;\r\n\t\t\tif ( value != LightTemperaturePreset.Custom )\r\n\t\t\t{\r\n\t\t\t\t_syncing = true;\r\n\t\t\t\tKelvin = (float)(int)value;\r\n\t\t\t\t_syncing = false;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tApplyColor();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/// <summary>The color temperature in Kelvin.</summary>\r\n\t[Property, Title( \"Temperature (K)\" ), Range( 1500, 15000 ), KelvinSlider]\r\n\tpublic float Kelvin\r\n\t{\r\n\t\tget => _kelvin;\r\n\t\tset\r\n\t\t{\r\n\t\t\tif ( _kelvin == value ) return;\r\n\t\t\t_kelvin = value;\r\n\t\t\tif ( !_syncing && _preset != LightTemperaturePreset.Custom )\r\n\t\t\t\t_preset = LightTemperaturePreset.Custom;\r\n\t\t\tApplyColor();\r\n\t\t}\r\n\t}\r\n\r\n\t/// <summary>The brightness (range) of the Light.</summary>\r\n\t[Property, Range( 0, 5f ), Step( 0.01f )]\r\n\tpublic float Brightness\r\n\t{\r\n\t\tget => _brightness;\r\n\t\tset\r\n\t\t{\r\n\t\t\tif ( _brightness == value ) return;\r\n\t\t\t_brightness = value;\r\n\t\t\tApplyColor();\r\n\t\t}\r\n\t}\r\n\r\n\t/// <summary>Applies the current temperature and brightness to the <see cref=\"Light\"/>'s color once on add.</summary>\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tApplyColor();\r\n\t}\r\n\r\n\t/// <summary>Sets the <see cref=\"Light\"/>'s color from the current temperature and brightness, if a light is present.</summary>\r\n\tvoid ApplyColor()\r\n\t{\r\n\t\t_light ??= GetComponentInChildren<Light>( true );\r\n\t\tif ( _light is null ) return;\r\n\t\t_light.LightColor = new Temperature( Kelvin ).ToColor() * Brightness;\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "Helpers/TemperatureExtensions.cs",
            "FileName": "TemperatureExtensions.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "using Sandbox;\r\nusing System;\r\n\r\nnamespace RotSoft.Lighting;\r\n\r\n/// <summary>Temperature to color conversions.</summary>\r\npublic static class TemperatureExtensions\r\n{\r\n\t/// <summary>\r\n\t/// Converts this temperature to an sRGB color, clamped to <see cref=\"Temperature.MinTemperature\"/>..<see cref=\"Temperature.MaxTemperature\"/>.\r\n\t/// </summary>\r\n\tpublic static Color ToColor( this Temperature temperature )\r\n\t{\r\n\t\tfloat kelvin = Math.Clamp( temperature.Kelvin, Temperature.MinTemperature, Temperature.MaxTemperature );\r\n\t\tfloat temp = kelvin / 100f;\r\n\t\tfloat r, g, b;\r\n\r\n\t\tif ( temp <= 66f )\r\n\t\t\tr = 1f;\r\n\t\telse\r\n\t\t\tr = Math.Clamp( 1.29293618606f * MathF.Pow( temp - 60f, -0.1332047592f ), 0f, 1f );\r\n\r\n\t\tif ( temp <= 66f )\r\n\t\t\tg = Math.Clamp( 0.390081578769f * MathF.Log( temp ) - 0.63184144378f, 0f, 1f );\r\n\t\telse\r\n\t\t\tg = Math.Clamp( 1.12989086369f * MathF.Pow( temp - 60f, -0.0755148492f ), 0f, 1f );\r\n\r\n\t\tif ( temp >= 66f )\r\n\t\t\tb = 1f;\r\n\t\telse if ( temp <= 19f )\r\n\t\t\tb = 0f;\r\n\t\telse\r\n\t\t\tb = Math.Clamp( 0.54320678911f * MathF.Log( temp - 10f ) - 1.19625408914f, 0f, 1f );\r\n\r\n\t\treturn new Color( r, g, b );\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "Code/Temperature.cs",
            "FileName": "Temperature.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "namespace RotSoft.Lighting;\r\n\r\n/// <summary>\r\n/// A color temperature in kelvin, converted to a color via <see cref=\"TemperatureExtensions.ToColor(Temperature)\"/>.\r\n/// </summary>\r\npublic struct Temperature\r\n{\r\n\t/// <summary>Lowest valid temperature, in kelvin.</summary>\r\n\tpublic const float MinTemperature = 1500f;\r\n\r\n\t/// <summary>Highest valid temperature, in kelvin.</summary>\r\n\tpublic const float MaxTemperature = 15000f;\r\n\r\n\t/// <summary>Temperature in kelvin.</summary>\r\n\tpublic float Kelvin { get; set; }\r\n\r\n\t/// <summary>Creates a temperature from a kelvin value.</summary>\r\n\tpublic Temperature( float kelvin )\r\n\t{\r\n\t\tKelvin = kelvin;\r\n\t}\r\n\r\n\t/// <summary>Implicitly converts a kelvin value to a <see cref=\"Temperature\"/>.</summary>\r\n\tpublic static implicit operator Temperature( float kelvin ) => new( kelvin );\r\n\r\n\t/// <summary>Implicitly converts a <see cref=\"Temperature\"/> back to its kelvin value.</summary>\r\n\tpublic static implicit operator float( Temperature temperature ) => temperature.Kelvin;\r\n\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": "KelvinSliderAttribute.cs",
            "FileName": "KelvinSliderAttribute.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "using System;\r\n\r\nnamespace RotSoft.Lighting;\r\n\r\n/// <summary>Marks a float property as a color temperature in kelvin; the inspector renders it with the kelvin gradient slider.</summary>\r\n[AttributeUsage( AttributeTargets.Property )]\r\npublic sealed class KelvinSliderAttribute : Attribute\r\n{\r\n}\r\n"
        },
        {
            "Ident": "fwotsoft.lightinghelpers",
            "Path": ".obj/__compiler_extra.cs",
            "FileName": "__compiler_extra.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 355266,
            "Code": "global using static Sandbox.Internal.GlobalGameNamespace;\r\nglobal using Microsoft.AspNetCore.Components;\r\nglobal using Microsoft.AspNetCore.Components.Rendering;\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"AddonTitle\", \"Lighting Helpers\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"AddonIdent\", \"lightinghelpers\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"OrgIdent\", \"fwotsoft\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"Ident\", \"fwotsoft.lightinghelpers\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"EngineVersion\", \"28\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"EngineMinorVersion\", \"1\" )]\r\n\r\n[assembly: System.Runtime.Versioning.TargetFramework( \".NETCoreApp,Version=v9.0\", FrameworkDisplayName = \".NET 9.0\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"CompileTime\", \"2026-08-27T09:20:31.5361275Z\" )]\r\n[assembly: global::System.Reflection.AssemblyVersion(\"0.0.120.0\")]\r\n[assembly: global::System.Reflection.AssemblyFileVersion(\"0.0.120.0\")]"
        }
    ]
}