UI/OMRScopeReticlePanel.cs
using Sandbox;
using Sandbox.UI;
using System;

namespace Sandbox.UI;

/// <summary>
/// Draws the scope reticle directly in the panel paint pass. This avoids relying
/// on four tiny Razor/CSS rectangles inside a scaled WorldPanel, which proved
/// vulnerable to hotload/layout quirks.
/// </summary>
public sealed class OMRScopeReticlePanel : Panel
{
	public OMRScopeReticleStyle ReticleStyle { get; set; } = OMRScopeReticleStyle.FineCross;
	public Color ReticleColor { get; set; } = Color.Black;
	public float Thickness { get; set; } = 1.5f;
	public float Gap { get; set; } = 8f;
	public float LineLength { get; set; } = 72f;
	public float DotSize { get; set; } = 3f;
	public float ReticleOpacity { get; set; } = 1f;
	public float OutlineWidth { get; set; } = 0f;
	public float OutlineOpacity { get; set; } = 0f;

	public override void OnDraw( Painter painter )
	{
		float opacity = MathX.Clamp( ReticleOpacity, 0f, 1f );
		if ( opacity <= 0.001f )
			return;

		float thickness = MathF.Max( Thickness, 0.5f );
		float gap = MathF.Max( Gap, 0f );
		float length = MathF.Max( LineLength, 1f );

		if ( ReticleStyle == OMRScopeReticleStyle.Duplex )
		{
			thickness *= 1.75f;
			gap *= 1.5f;
		}

		Vector2 center = new( painter.Bounds.Width * 0.5f, painter.Bounds.Height * 0.5f );
		Color main = ReticleColor.WithAlpha( ReticleColor.a * opacity );

		float outlineWidth = MathF.Max( OutlineWidth, 0f );
		float outlineOpacity = MathX.Clamp( OutlineOpacity, 0f, 1f ) * opacity;
		if ( outlineWidth > 0f && outlineOpacity > 0.001f )
		{
			Color outline = Color.White.WithAlpha( outlineOpacity );
			DrawCross( painter, center, thickness + outlineWidth * 2f, gap, length, outline );
		}

		DrawCross( painter, center, thickness, gap, length, main );

		if ( ReticleStyle == OMRScopeReticleStyle.DotCross && DotSize > 0f )
		{
			if ( outlineWidth > 0f && outlineOpacity > 0.001f )
			{
				painter.Fill = Color.White.WithAlpha( outlineOpacity );
				painter.Circle( center, (DotSize + outlineWidth * 2f) * 0.5f );
			}

			painter.Fill = main;
			painter.Circle( center, DotSize * 0.5f );
		}
	}

	private static void DrawCross( Painter painter, Vector2 center, float thickness, float gap, float length, Color color )
	{
		float halfThickness = thickness * 0.5f;
		painter.Fill = color;
		painter.Stroke = Stroke.None;

		painter.Rect( new Rect( center.x - gap - length, center.y - halfThickness, length, thickness ) );
		painter.Rect( new Rect( center.x + gap, center.y - halfThickness, length, thickness ) );
		painter.Rect( new Rect( center.x - halfThickness, center.y - gap - length, thickness, length ) );
		painter.Rect( new Rect( center.x - halfThickness, center.y + gap, thickness, length ) );
	}
}