🔍 s&box Package Code Search

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

Showing code results for query: * (7 total matches found)
notathreat.crosshairbuilder / Editor/MyEditorMenu.cs
Editor library
using Editor;

public static class MyEditorMenu
{
	[Menu( "Editor", "CrosshairBuilder/My Menu Option" )]
	public static void OpenMyMenu()
	{
		EditorUtility.DisplayDialog( "It worked!", "This is being called from your library's editor code!" );
	}
}
notathreat.crosshairbuilder / Code/CrosshairBuilder.razor
Game library
@using System;
@using Sandbox;
@using Sandbox.UI;
@inherits PanelComponent

<root>
    <div class="crosshair" style="
		position: absolute;
		left: @( IsPercentage ? $"{Position.x}%"  : Position.x );
		top: @( IsPercentage ? $"{Position.y}%" : Position.y );
		transform: translate(-50%, -50%);
	">
		<div class="center-dot-border-wrapper" style="
			display: @(CenterDot ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
			z-index: 100;
		">
			<div class="center-dot" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(CenterDotOpacity));
				padding: @(CenterDotThickness)px;
			"></div>
		</div>
		<div class="inner-top-border-wrapper" style="
			position: absolute;
    		top: -@(InnerLinesOffset)px;
    		left: 50%;
    		transform: translateX(-50%);
			display:@(ShowInnerLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="inner-line top" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));
				padding-left: @(InnerLineThickness)px;
    			padding-top: @(InnerLineLenght)px;
			"></div>
		</div>
		<div class="inner-bottom-border-wrapper" style="
			position: absolute;
    		bottom: -@(InnerLinesOffset)px;
    		left: 50%;
    		transform: translateX(-50%);
			display:@(ShowInnerLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="inner-line bottom" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));
				padding-left: @(InnerLineThickness)px;
    			padding-bottom: @(InnerLineLenght)px;
			"></div>
		</div>
		<div class="inner-left-border-wrapper" style="
			position: absolute;
			left: -@(InnerLinesOffset)px;
			top: 50%;
			transform: translateY(-50%);
			display:@(ShowInnerLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="inner-line left" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));
				padding-top: @(InnerLineThickness)px;
				padding-left: @(InnerLineLenght)px;
			"></div>
		</div>
		<div class="inner-right-border-wrapper" style="
			position: absolute;
			right: -@(InnerLinesOffset)px;
			top: 50%;
			transform: translateY(-50%);
			display: @(ShowInnerLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="inner-line right" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));
				padding-top: @(InnerLineThickness)px;
				padding-right: @(InnerLineLenght)px;
			"></div>
		</div>
		<div class="outer-top-border-wrapper" style="
			position: absolute;
			top: -@(OuterLineOffset)px;
			left: 50%;
			transform: translateX(-50%);
			display: @(ShowOuterLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="outer-line top" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));
				padding-left: @(OuterLineThickness)px;
				padding-top: @(OuterLineLenght)px;
			"></div>
		</div>
		<div class="outer-bottom-border-wrapper" style="
			position: absolute;
			bottom: -@(OuterLineOffset)px;
			left: 50%;
			transform: translateX(-50%);
			display: @(ShowOuterLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="outer-line bottom" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));
				padding-left: @(OuterLineThickness)px;
				padding-bottom: @(OuterLineLenght)px;
			"></div>
		</div>
		<div class="outer-left-border-wrapper" style="
			position: absolute;
			left: -@(OuterLineOffset)px;
			top: 50%;
			transform: translateY(-50%);
			display: @(ShowOuterLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="outer-line left" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));
				padding-top: @(OuterLineThickness)px;
				padding-left: @(OuterLineLenght)px;
			"></div>
		</div>
		<div class="outer-right-border-wrapper" style="
			position: absolute;
			right: -@(OuterLineOffset)px;
			top: 50%;
			transform: translateY(-50%);
			display: @(ShowOuterLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="outer-line right" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));
				padding-top: @(OuterLineThickness)px;
				padding-right: @(OuterLineLenght)px;
			"></div>
		</div>
    </div>
</root>

@code
{
	// Position properties
	[Property] 
	[Category("Position")] public bool IsPercentage { get; set; } = true;
	[Property]
	[Category("Position")] public Vector2 Position { get; set; } = new Vector2(50, 50);

	// Crosshair properties
	[Property]
	[Category("Crosshair")] public Color Color { get; set; } = Color.FromRgb(0x2EFF00);
	[Property]
	[Category("Crosshair")] public bool Outline { get; set; } = true;
	[Property]
	[Range(0f, 1f, 0.001f)]
	[Category("Crosshair")] public float OutlineOpacity { get; set; } = 1f;
	[Property]
	[Range(1, 10, 1)]
	[Category("Crosshair")] public int OutlineThickness { get; set; } = 2;
	[Property]
	[Category("Crosshair")] public bool CenterDot { get; set; } = true;
	[Property]
	[Range(0f, 1f, 0.001f)]
	[Category("Crosshair")] public float CenterDotOpacity { get; set; } = 1f;
	[Property]
	[Range(1, 10, 1)]
	[Category("Crosshair")] public int CenterDotThickness { get; set; } = 1;

	// Inner Lines properties
	[Property]
	[Category("Inner Lines")] public bool ShowInnerLines { get; set; } = true;
	[Property]
	[Range(0f, 1f, 0.001f)]
	[Category("Inner Lines")] public float InnerLineOpacity { get; set; } = 1f;
	[Property]
	[Range(0, 20, 1)]
	[Category("Inner Lines")] public int InnerLineLenght { get; set; } = 10;
	[Property]
	[Range(0, 10, 1)]
	[Category("Inner Lines")] public int InnerLineThickness { get; set; } = 1;
	[Property]
	[Range(0, 20, 1)]
	[Category("Inner Lines")] public int InnerLinesOffset { get; set; } = 2;

	// Outer Lines properties
	[Property]
	[Category("Outer Lines")] public bool ShowOuterLines { get; set; } = false;
	[Property]
	[Range(0f, 1f, 0.001f)]
	[Category("Outer Lines")] public float OuterLineOpacity { get; set; } = 0.5f;
	[Property]
	[Range(0, 20, 1)]
	[Category("Outer Lines")] public int OuterLineLenght { get; set; }
	[Property]
	[Range(0, 10, 1)]
	[Category("Outer Lines")] public int OuterLineThickness { get; set; }
	[Property]
	[Range(0, 20, 1)]
	[Category("Outer Lines")] public int OuterLineOffset { get; set; }

	// Code properties
	[Property]
	[Category("Code")] public string Code { get; set; }

	// Member variables
	private string _cachedCode = null;

	public string EncodeCrosshairParameters()
	{
		// Convert boolean values to 1 or 0
		string EncodeBool(bool value) => value ? "1" : "0";
		// Convert float values to a shortened string representation (up to 2 decimal places)
		string EncodeFloat(float value) => Math.Round(value, 2).ToString("0.##");
		// Convert integers directly to string
		string EncodeInt(int value) => value.ToString();

		// Concatenate all parameters into a shortened format
		var parameters = $"{EncodeBool(IsPercentage)}," +
							$"{EncodeFloat(Position.x)},{EncodeFloat(Position.y)}," +
							$"{EncodeFloat(Color.r)},{EncodeFloat(Color.g)},{EncodeFloat(Color.b)}," +
							$"{EncodeBool(Outline)},{EncodeFloat(OutlineOpacity)},{EncodeInt(OutlineThickness)}," +
							$"{EncodeBool(CenterDot)},{EncodeFloat(CenterDotOpacity)},{EncodeInt(CenterDotThickness)}," +
							$"{EncodeBool(ShowInnerLines)},{EncodeFloat(InnerLineOpacity)},{EncodeInt(InnerLineLenght)}," +
							$"{EncodeInt(InnerLineThickness)},{EncodeInt(InnerLinesOffset)}," +
							$"{EncodeBool(ShowOuterLines)},{EncodeFloat(OuterLineOpacity)},{EncodeInt(OuterLineLenght)}," +
							$"{EncodeInt(OuterLineThickness)},{EncodeInt(OuterLineOffset)}";
		return parameters;
	}

	public void DecodeCrosshairParameters(string encodedString)
	{
		var parameters = encodedString.Split(',');

		// Convert "1" or "0" back to boolean
		bool DecodeBool(string value) => value == "1";
		// Convert string back to float
		float DecodeFloat(string value) => float.Parse(value);
		// Convert string back to int
		int DecodeInt(string value) => int.Parse(value);

		// Assign the decoded values back to the properties
		IsPercentage = DecodeBool(parameters[0]);
		Position = new Vector2(DecodeFloat(parameters[1]), DecodeFloat(parameters[2]));
		Color = new Color(DecodeFloat(parameters[3]), DecodeFloat(parameters[4]), DecodeFloat(parameters[5]));
		Outline = DecodeBool(parameters[6]);
		OutlineOpacity = DecodeFloat(parameters[7]);
		OutlineThickness = DecodeInt(parameters[8]);
		CenterDot = DecodeBool(parameters[9]);
		CenterDotOpacity = DecodeFloat(parameters[10]);
		CenterDotThickness = DecodeInt(parameters[11]);
		ShowInnerLines = DecodeBool(parameters[12]);
		InnerLineOpacity = DecodeFloat(parameters[13]);
		InnerLineLenght = DecodeInt(parameters[14]);
		InnerLineThickness = DecodeInt(parameters[15]);
		InnerLinesOffset = DecodeInt(parameters[16]);
		ShowOuterLines = DecodeBool(parameters[17]);
		OuterLineOpacity = DecodeFloat(parameters[18]);
		OuterLineLenght = DecodeInt(parameters[19]);
		OuterLineThickness = DecodeInt(parameters[20]);
		OuterLineOffset = DecodeInt(parameters[21]);
	}

	protected override void OnStart()
	{
		if (Code == null)
		{
			Code = EncodeCrosshairParameters();
		}
		DecodeCrosshairParameters(Code);
		_cachedCode = Code;
	}

	protected override void OnUpdate()
	{
		if (Code != _cachedCode)
		{
			DecodeCrosshairParameters(Code);
		}
		Code = EncodeCrosshairParameters();
		_cachedCode = Code;
	}

	/// <summary>
	/// the hash determines if the system should be rebuilt. If it changes, it will be rebuilt
	/// </summary>
	protected override int BuildHash()
	{
		var positionHash = System.HashCode.Combine( 
			IsPercentage,
			Position
		);

		var crosshairHash = System.HashCode.Combine( 
			Color,
			Outline,
			OutlineOpacity,
			OutlineThickness,
			CenterDot,
			CenterDotOpacity,
			CenterDotThickness
		);

		var innerLinesHash = System.HashCode.Combine(
			ShowInnerLines,
			InnerLineOpacity,
			InnerLineLenght,
			InnerLineThickness,
			InnerLinesOffset
		);

		var outerLinesHash = System.HashCode.Combine(
			ShowOuterLines,
			OuterLineOpacity,
			OuterLineLenght,
			OuterLineThickness,
			OuterLineOffset
		);

		var codeHash = Code.GetHashCode();
		
		return System.HashCode.Combine(
			positionHash,
			crosshairHash,
			innerLinesHash,
			outerLinesHash,
			codeHash
		);
	}
}
notathreat.crosshairbuilder / CrosshairBuilder.razor
Game library
@using System;
@using Sandbox;
@using Sandbox.UI;
@inherits PanelComponent

<root>
    <div class="crosshair" style="
		position: absolute;
		left: @( IsPercentage ? $"{Position.x}%"  : Position.x );
		top: @( IsPercentage ? $"{Position.y}%" : Position.y );
		transform: translate(-50%, -50%);
	">
		<div class="center-dot-border-wrapper" style="
			display: @(CenterDot ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
			z-index: 100;
		">
			<div class="center-dot" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(CenterDotOpacity));
				padding: @(CenterDotThickness)px;
			"></div>
		</div>
		<div class="inner-top-border-wrapper" style="
			position: absolute;
    		top: -@(InnerLinesOffset)px;
    		left: 50%;
    		transform: translateX(-50%);
			display:@(ShowInnerLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="inner-line top" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));
				padding-left: @(InnerLineThickness)px;
    			padding-top: @(InnerLineLenght)px;
			"></div>
		</div>
		<div class="inner-bottom-border-wrapper" style="
			position: absolute;
    		bottom: -@(InnerLinesOffset)px;
    		left: 50%;
    		transform: translateX(-50%);
			display:@(ShowInnerLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="inner-line bottom" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));
				padding-left: @(InnerLineThickness)px;
    			padding-bottom: @(InnerLineLenght)px;
			"></div>
		</div>
		<div class="inner-left-border-wrapper" style="
			position: absolute;
			left: -@(InnerLinesOffset)px;
			top: 50%;
			transform: translateY(-50%);
			display:@(ShowInnerLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="inner-line left" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));
				padding-top: @(InnerLineThickness)px;
				padding-left: @(InnerLineLenght)px;
			"></div>
		</div>
		<div class="inner-right-border-wrapper" style="
			position: absolute;
			right: -@(InnerLinesOffset)px;
			top: 50%;
			transform: translateY(-50%);
			display: @(ShowInnerLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="inner-line right" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));
				padding-top: @(InnerLineThickness)px;
				padding-right: @(InnerLineLenght)px;
			"></div>
		</div>
		<div class="outer-top-border-wrapper" style="
			position: absolute;
			top: -@(OuterLineOffset)px;
			left: 50%;
			transform: translateX(-50%);
			display: @(ShowOuterLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="outer-line top" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));
				padding-left: @(OuterLineThickness)px;
				padding-top: @(OuterLineLenght)px;
			"></div>
		</div>
		<div class="outer-bottom-border-wrapper" style="
			position: absolute;
			bottom: -@(OuterLineOffset)px;
			left: 50%;
			transform: translateX(-50%);
			display: @(ShowOuterLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="outer-line bottom" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));
				padding-left: @(OuterLineThickness)px;
				padding-bottom: @(OuterLineLenght)px;
			"></div>
		</div>
		<div class="outer-left-border-wrapper" style="
			position: absolute;
			left: -@(OuterLineOffset)px;
			top: 50%;
			transform: translateY(-50%);
			display: @(ShowOuterLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="outer-line left" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));
				padding-top: @(OuterLineThickness)px;
				padding-left: @(OuterLineLenght)px;
			"></div>
		</div>
		<div class="outer-right-border-wrapper" style="
			position: absolute;
			right: -@(OuterLineOffset)px;
			top: 50%;
			transform: translateY(-50%);
			display: @(ShowOuterLines ? "flex" : "none");
			border: @(Outline ? $"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})" : "none");
		">
			<div class="outer-line right" style="
				background-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));
				padding-top: @(OuterLineThickness)px;
				padding-right: @(OuterLineLenght)px;
			"></div>
		</div>
    </div>
</root>

@code
{
	// Position properties
	[Property] 
	[Category("Position")] public bool IsPercentage { get; set; } = true;
	[Property]
	[Category("Position")] public Vector2 Position { get; set; } = new Vector2(50, 50);

	// Crosshair properties
	[Property]
	[Category("Crosshair")] public Color Color { get; set; } = Color.FromRgb(0x2EFF00);
	[Property]
	[Category("Crosshair")] public bool Outline { get; set; } = true;
	[Property]
	[Range(0f, 1f, 0.001f)]
	[Category("Crosshair")] public float OutlineOpacity { get; set; } = 1f;
	[Property]
	[Range(1, 10, 1)]
	[Category("Crosshair")] public int OutlineThickness { get; set; } = 2;
	[Property]
	[Category("Crosshair")] public bool CenterDot { get; set; } = true;
	[Property]
	[Range(0f, 1f, 0.001f)]
	[Category("Crosshair")] public float CenterDotOpacity { get; set; } = 1f;
	[Property]
	[Range(1, 10, 1)]
	[Category("Crosshair")] public int CenterDotThickness { get; set; } = 1;

	// Inner Lines properties
	[Property]
	[Category("Inner Lines")] public bool ShowInnerLines { get; set; } = true;
	[Property]
	[Range(0f, 1f, 0.001f)]
	[Category("Inner Lines")] public float InnerLineOpacity { get; set; } = 1f;
	[Property]
	[Range(0, 20, 1)]
	[Category("Inner Lines")] public int InnerLineLenght { get; set; } = 10;
	[Property]
	[Range(0, 10, 1)]
	[Category("Inner Lines")] public int InnerLineThickness { get; set; } = 1;
	[Property]
	[Range(0, 20, 1)]
	[Category("Inner Lines")] public int InnerLinesOffset { get; set; } = 2;

	// Outer Lines properties
	[Property]
	[Category("Outer Lines")] public bool ShowOuterLines { get; set; } = false;
	[Property]
	[Range(0f, 1f, 0.001f)]
	[Category("Outer Lines")] public float OuterLineOpacity { get; set; } = 0.5f;
	[Property]
	[Range(0, 20, 1)]
	[Category("Outer Lines")] public int OuterLineLenght { get; set; }
	[Property]
	[Range(0, 10, 1)]
	[Category("Outer Lines")] public int OuterLineThickness { get; set; }
	[Property]
	[Range(0, 20, 1)]
	[Category("Outer Lines")] public int OuterLineOffset { get; set; }

	// Code properties
	[Property]
	[Category("Code")] public string Code { get; set; }

	// Member variables
	private string _cachedCode = null;

	public string EncodeCrosshairParameters()
	{
		// Convert boolean values to 1 or 0
		string EncodeBool(bool value) => value ? "1" : "0";
		// Convert float values to a shortened string representation (up to 2 decimal places)
		string EncodeFloat(float value) => Math.Round(value, 2).ToString("0.##");
		// Convert integers directly to string
		string EncodeInt(int value) => value.ToString();

		// Concatenate all parameters into a shortened format
		var parameters = $"{EncodeBool(IsPercentage)}," +
							$"{EncodeFloat(Position.x)},{EncodeFloat(Position.y)}," +
							$"{EncodeFloat(Color.r)},{EncodeFloat(Color.g)},{EncodeFloat(Color.b)}," +
							$"{EncodeBool(Outline)},{EncodeFloat(OutlineOpacity)},{EncodeInt(OutlineThickness)}," +
							$"{EncodeBool(CenterDot)},{EncodeFloat(CenterDotOpacity)},{EncodeInt(CenterDotThickness)}," +
							$"{EncodeBool(ShowInnerLines)},{EncodeFloat(InnerLineOpacity)},{EncodeInt(InnerLineLenght)}," +
							$"{EncodeInt(InnerLineThickness)},{EncodeInt(InnerLinesOffset)}," +
							$"{EncodeBool(ShowOuterLines)},{EncodeFloat(OuterLineOpacity)},{EncodeInt(OuterLineLenght)}," +
							$"{EncodeInt(OuterLineThickness)},{EncodeInt(OuterLineOffset)}";
		return parameters;
	}

	public void DecodeCrosshairParameters(string encodedString)
	{
		var parameters = encodedString.Split(',');

		// Convert "1" or "0" back to boolean
		bool DecodeBool(string value) => value == "1";
		// Convert string back to float
		float DecodeFloat(string value) => float.Parse(value);
		// Convert string back to int
		int DecodeInt(string value) => int.Parse(value);

		// Assign the decoded values back to the properties
		IsPercentage = DecodeBool(parameters[0]);
		Position = new Vector2(DecodeFloat(parameters[1]), DecodeFloat(parameters[2]));
		Color = new Color(DecodeFloat(parameters[3]), DecodeFloat(parameters[4]), DecodeFloat(parameters[5]));
		Outline = DecodeBool(parameters[6]);
		OutlineOpacity = DecodeFloat(parameters[7]);
		OutlineThickness = DecodeInt(parameters[8]);
		CenterDot = DecodeBool(parameters[9]);
		CenterDotOpacity = DecodeFloat(parameters[10]);
		CenterDotThickness = DecodeInt(parameters[11]);
		ShowInnerLines = DecodeBool(parameters[12]);
		InnerLineOpacity = DecodeFloat(parameters[13]);
		InnerLineLenght = DecodeInt(parameters[14]);
		InnerLineThickness = DecodeInt(parameters[15]);
		InnerLinesOffset = DecodeInt(parameters[16]);
		ShowOuterLines = DecodeBool(parameters[17]);
		OuterLineOpacity = DecodeFloat(parameters[18]);
		OuterLineLenght = DecodeInt(parameters[19]);
		OuterLineThickness = DecodeInt(parameters[20]);
		OuterLineOffset = DecodeInt(parameters[21]);
	}

	protected override void OnStart()
	{
		if (Code == null)
		{
			Code = EncodeCrosshairParameters();
		}
		DecodeCrosshairParameters(Code);
		_cachedCode = Code;
	}

	protected override void OnUpdate()
	{
		if (Code != _cachedCode)
		{
			DecodeCrosshairParameters(Code);
		}
		Code = EncodeCrosshairParameters();
		_cachedCode = Code;
	}

	/// <summary>
	/// the hash determines if the system should be rebuilt. If it changes, it will be rebuilt
	/// </summary>
	protected override int BuildHash()
	{
		var positionHash = System.HashCode.Combine( 
			IsPercentage,
			Position
		);

		var crosshairHash = System.HashCode.Combine( 
			Color,
			Outline,
			OutlineOpacity,
			OutlineThickness,
			CenterDot,
			CenterDotOpacity,
			CenterDotThickness
		);

		var innerLinesHash = System.HashCode.Combine(
			ShowInnerLines,
			InnerLineOpacity,
			InnerLineLenght,
			InnerLineThickness,
			InnerLinesOffset
		);

		var outerLinesHash = System.HashCode.Combine(
			ShowOuterLines,
			OuterLineOpacity,
			OuterLineLenght,
			OuterLineThickness,
			OuterLineOffset
		);

		var codeHash = Code.GetHashCode();
		
		return System.HashCode.Combine(
			positionHash,
			crosshairHash,
			innerLinesHash,
			outerLinesHash,
			codeHash
		);
	}
}
notathreat.crosshairbuilder / UnitTests/LibraryTest.cs
UnitTest library
using Sandbox;

[TestClass]
public partial class LibraryTests
{
	[TestMethod]
	public void SceneTest()
	{
		var scene = new Scene();
		using ( scene.Push() )
		{
			var go = new GameObject();

			Assert.AreEqual( 1, scene.Directory.GameObjectCount );
		}
	}

}
notathreat.crosshairbuilder / __gen_RazorNamespace.cs
Game library
global using Microsoft.AspNetCore.Components; 
global using Microsoft.AspNetCore.Components.Rendering;
notathreat.crosshairbuilder / .obj/__compiler_extra.cs
Game library
global using static Sandbox.Internal.GlobalGameNamespace;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "CrosshairBuilder" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "crosshairbuilder" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "notathreat" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "notathreat.crosshairbuilder" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "8/19/2024 3:47:41 PM" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "17" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]

[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v7.0", FrameworkDisplayName = ".NET 7.0" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.121.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.121.0")]
notathreat.crosshairbuilder / UnitTests/UnitTest.cs
UnitTest library
global using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class TestInit
{
	[AssemblyInitialize]
	public static void ClassInitialize( TestContext context )
	{
		Sandbox.Application.InitUnitTest();
	}
}
Debug: View Raw JSON Response
{
    "TotalCount": 7,
    "Files": [
        {
            "Ident": "notathreat.crosshairbuilder",
            "Path": "Editor/MyEditorMenu.cs",
            "FileName": "MyEditorMenu.cs",
            "PackageType": "library",
            "CodeKind": "Editor",
            "AssetVersionId": 67301,
            "Code": "using Editor;\r\n\r\npublic static class MyEditorMenu\r\n{\r\n\t[Menu( \"Editor\", \"CrosshairBuilder/My Menu Option\" )]\r\n\tpublic static void OpenMyMenu()\r\n\t{\r\n\t\tEditorUtility.DisplayDialog( \"It worked!\", \"This is being called from your library's editor code!\" );\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "notathreat.crosshairbuilder",
            "Path": "Code/CrosshairBuilder.razor",
            "FileName": "CrosshairBuilder.razor",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 67301,
            "Code": "@using System;\r\n@using Sandbox;\r\n@using Sandbox.UI;\r\n@inherits PanelComponent\r\n\r\n<root>\r\n    <div class=\"crosshair\" style=\"\r\n\t\tposition: absolute;\r\n\t\tleft: @( IsPercentage ? $\"{Position.x}%\"  : Position.x );\r\n\t\ttop: @( IsPercentage ? $\"{Position.y}%\" : Position.y );\r\n\t\ttransform: translate(-50%, -50%);\r\n\t\">\r\n\t\t<div class=\"center-dot-border-wrapper\" style=\"\r\n\t\t\tdisplay: @(CenterDot ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\tz-index: 100;\r\n\t\t\">\r\n\t\t\t<div class=\"center-dot\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(CenterDotOpacity));\r\n\t\t\t\tpadding: @(CenterDotThickness)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"inner-top-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n    \t\ttop: -@(InnerLinesOffset)px;\r\n    \t\tleft: 50%;\r\n    \t\ttransform: translateX(-50%);\r\n\t\t\tdisplay:@(ShowInnerLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"inner-line top\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));\r\n\t\t\t\tpadding-left: @(InnerLineThickness)px;\r\n    \t\t\tpadding-top: @(InnerLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"inner-bottom-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n    \t\tbottom: -@(InnerLinesOffset)px;\r\n    \t\tleft: 50%;\r\n    \t\ttransform: translateX(-50%);\r\n\t\t\tdisplay:@(ShowInnerLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"inner-line bottom\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));\r\n\t\t\t\tpadding-left: @(InnerLineThickness)px;\r\n    \t\t\tpadding-bottom: @(InnerLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"inner-left-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tleft: -@(InnerLinesOffset)px;\r\n\t\t\ttop: 50%;\r\n\t\t\ttransform: translateY(-50%);\r\n\t\t\tdisplay:@(ShowInnerLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"inner-line left\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));\r\n\t\t\t\tpadding-top: @(InnerLineThickness)px;\r\n\t\t\t\tpadding-left: @(InnerLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"inner-right-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tright: -@(InnerLinesOffset)px;\r\n\t\t\ttop: 50%;\r\n\t\t\ttransform: translateY(-50%);\r\n\t\t\tdisplay: @(ShowInnerLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"inner-line right\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));\r\n\t\t\t\tpadding-top: @(InnerLineThickness)px;\r\n\t\t\t\tpadding-right: @(InnerLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"outer-top-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\ttop: -@(OuterLineOffset)px;\r\n\t\t\tleft: 50%;\r\n\t\t\ttransform: translateX(-50%);\r\n\t\t\tdisplay: @(ShowOuterLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"outer-line top\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));\r\n\t\t\t\tpadding-left: @(OuterLineThickness)px;\r\n\t\t\t\tpadding-top: @(OuterLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"outer-bottom-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tbottom: -@(OuterLineOffset)px;\r\n\t\t\tleft: 50%;\r\n\t\t\ttransform: translateX(-50%);\r\n\t\t\tdisplay: @(ShowOuterLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"outer-line bottom\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));\r\n\t\t\t\tpadding-left: @(OuterLineThickness)px;\r\n\t\t\t\tpadding-bottom: @(OuterLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"outer-left-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tleft: -@(OuterLineOffset)px;\r\n\t\t\ttop: 50%;\r\n\t\t\ttransform: translateY(-50%);\r\n\t\t\tdisplay: @(ShowOuterLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"outer-line left\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));\r\n\t\t\t\tpadding-top: @(OuterLineThickness)px;\r\n\t\t\t\tpadding-left: @(OuterLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"outer-right-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tright: -@(OuterLineOffset)px;\r\n\t\t\ttop: 50%;\r\n\t\t\ttransform: translateY(-50%);\r\n\t\t\tdisplay: @(ShowOuterLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"outer-line right\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));\r\n\t\t\t\tpadding-top: @(OuterLineThickness)px;\r\n\t\t\t\tpadding-right: @(OuterLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n    </div>\r\n</root>\r\n\r\n@code\r\n{\r\n\t// Position properties\r\n\t[Property] \r\n\t[Category(\"Position\")] public bool IsPercentage { get; set; } = true;\r\n\t[Property]\r\n\t[Category(\"Position\")] public Vector2 Position { get; set; } = new Vector2(50, 50);\r\n\r\n\t// Crosshair properties\r\n\t[Property]\r\n\t[Category(\"Crosshair\")] public Color Color { get; set; } = Color.FromRgb(0x2EFF00);\r\n\t[Property]\r\n\t[Category(\"Crosshair\")] public bool Outline { get; set; } = true;\r\n\t[Property]\r\n\t[Range(0f, 1f, 0.001f)]\r\n\t[Category(\"Crosshair\")] public float OutlineOpacity { get; set; } = 1f;\r\n\t[Property]\r\n\t[Range(1, 10, 1)]\r\n\t[Category(\"Crosshair\")] public int OutlineThickness { get; set; } = 2;\r\n\t[Property]\r\n\t[Category(\"Crosshair\")] public bool CenterDot { get; set; } = true;\r\n\t[Property]\r\n\t[Range(0f, 1f, 0.001f)]\r\n\t[Category(\"Crosshair\")] public float CenterDotOpacity { get; set; } = 1f;\r\n\t[Property]\r\n\t[Range(1, 10, 1)]\r\n\t[Category(\"Crosshair\")] public int CenterDotThickness { get; set; } = 1;\r\n\r\n\t// Inner Lines properties\r\n\t[Property]\r\n\t[Category(\"Inner Lines\")] public bool ShowInnerLines { get; set; } = true;\r\n\t[Property]\r\n\t[Range(0f, 1f, 0.001f)]\r\n\t[Category(\"Inner Lines\")] public float InnerLineOpacity { get; set; } = 1f;\r\n\t[Property]\r\n\t[Range(0, 20, 1)]\r\n\t[Category(\"Inner Lines\")] public int InnerLineLenght { get; set; } = 10;\r\n\t[Property]\r\n\t[Range(0, 10, 1)]\r\n\t[Category(\"Inner Lines\")] public int InnerLineThickness { get; set; } = 1;\r\n\t[Property]\r\n\t[Range(0, 20, 1)]\r\n\t[Category(\"Inner Lines\")] public int InnerLinesOffset { get; set; } = 2;\r\n\r\n\t// Outer Lines properties\r\n\t[Property]\r\n\t[Category(\"Outer Lines\")] public bool ShowOuterLines { get; set; } = false;\r\n\t[Property]\r\n\t[Range(0f, 1f, 0.001f)]\r\n\t[Category(\"Outer Lines\")] public float OuterLineOpacity { get; set; } = 0.5f;\r\n\t[Property]\r\n\t[Range(0, 20, 1)]\r\n\t[Category(\"Outer Lines\")] public int OuterLineLenght { get; set; }\r\n\t[Property]\r\n\t[Range(0, 10, 1)]\r\n\t[Category(\"Outer Lines\")] public int OuterLineThickness { get; set; }\r\n\t[Property]\r\n\t[Range(0, 20, 1)]\r\n\t[Category(\"Outer Lines\")] public int OuterLineOffset { get; set; }\r\n\r\n\t// Code properties\r\n\t[Property]\r\n\t[Category(\"Code\")] public string Code { get; set; }\r\n\r\n\t// Member variables\r\n\tprivate string _cachedCode = null;\r\n\r\n\tpublic string EncodeCrosshairParameters()\r\n\t{\r\n\t\t// Convert boolean values to 1 or 0\r\n\t\tstring EncodeBool(bool value) => value ? \"1\" : \"0\";\r\n\t\t// Convert float values to a shortened string representation (up to 2 decimal places)\r\n\t\tstring EncodeFloat(float value) => Math.Round(value, 2).ToString(\"0.##\");\r\n\t\t// Convert integers directly to string\r\n\t\tstring EncodeInt(int value) => value.ToString();\r\n\r\n\t\t// Concatenate all parameters into a shortened format\r\n\t\tvar parameters = $\"{EncodeBool(IsPercentage)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeFloat(Position.x)},{EncodeFloat(Position.y)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeFloat(Color.r)},{EncodeFloat(Color.g)},{EncodeFloat(Color.b)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeBool(Outline)},{EncodeFloat(OutlineOpacity)},{EncodeInt(OutlineThickness)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeBool(CenterDot)},{EncodeFloat(CenterDotOpacity)},{EncodeInt(CenterDotThickness)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeBool(ShowInnerLines)},{EncodeFloat(InnerLineOpacity)},{EncodeInt(InnerLineLenght)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeInt(InnerLineThickness)},{EncodeInt(InnerLinesOffset)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeBool(ShowOuterLines)},{EncodeFloat(OuterLineOpacity)},{EncodeInt(OuterLineLenght)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeInt(OuterLineThickness)},{EncodeInt(OuterLineOffset)}\";\r\n\t\treturn parameters;\r\n\t}\r\n\r\n\tpublic void DecodeCrosshairParameters(string encodedString)\r\n\t{\r\n\t\tvar parameters = encodedString.Split(',');\r\n\r\n\t\t// Convert \"1\" or \"0\" back to boolean\r\n\t\tbool DecodeBool(string value) => value == \"1\";\r\n\t\t// Convert string back to float\r\n\t\tfloat DecodeFloat(string value) => float.Parse(value);\r\n\t\t// Convert string back to int\r\n\t\tint DecodeInt(string value) => int.Parse(value);\r\n\r\n\t\t// Assign the decoded values back to the properties\r\n\t\tIsPercentage = DecodeBool(parameters[0]);\r\n\t\tPosition = new Vector2(DecodeFloat(parameters[1]), DecodeFloat(parameters[2]));\r\n\t\tColor = new Color(DecodeFloat(parameters[3]), DecodeFloat(parameters[4]), DecodeFloat(parameters[5]));\r\n\t\tOutline = DecodeBool(parameters[6]);\r\n\t\tOutlineOpacity = DecodeFloat(parameters[7]);\r\n\t\tOutlineThickness = DecodeInt(parameters[8]);\r\n\t\tCenterDot = DecodeBool(parameters[9]);\r\n\t\tCenterDotOpacity = DecodeFloat(parameters[10]);\r\n\t\tCenterDotThickness = DecodeInt(parameters[11]);\r\n\t\tShowInnerLines = DecodeBool(parameters[12]);\r\n\t\tInnerLineOpacity = DecodeFloat(parameters[13]);\r\n\t\tInnerLineLenght = DecodeInt(parameters[14]);\r\n\t\tInnerLineThickness = DecodeInt(parameters[15]);\r\n\t\tInnerLinesOffset = DecodeInt(parameters[16]);\r\n\t\tShowOuterLines = DecodeBool(parameters[17]);\r\n\t\tOuterLineOpacity = DecodeFloat(parameters[18]);\r\n\t\tOuterLineLenght = DecodeInt(parameters[19]);\r\n\t\tOuterLineThickness = DecodeInt(parameters[20]);\r\n\t\tOuterLineOffset = DecodeInt(parameters[21]);\r\n\t}\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tif (Code == null)\r\n\t\t{\r\n\t\t\tCode = EncodeCrosshairParameters();\r\n\t\t}\r\n\t\tDecodeCrosshairParameters(Code);\r\n\t\t_cachedCode = Code;\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif (Code != _cachedCode)\r\n\t\t{\r\n\t\t\tDecodeCrosshairParameters(Code);\r\n\t\t}\r\n\t\tCode = EncodeCrosshairParameters();\r\n\t\t_cachedCode = Code;\r\n\t}\r\n\r\n\t/// <summary>\r\n\t/// the hash determines if the system should be rebuilt. If it changes, it will be rebuilt\r\n\t/// </summary>\r\n\tprotected override int BuildHash()\r\n\t{\r\n\t\tvar positionHash = System.HashCode.Combine( \r\n\t\t\tIsPercentage,\r\n\t\t\tPosition\r\n\t\t);\r\n\r\n\t\tvar crosshairHash = System.HashCode.Combine( \r\n\t\t\tColor,\r\n\t\t\tOutline,\r\n\t\t\tOutlineOpacity,\r\n\t\t\tOutlineThickness,\r\n\t\t\tCenterDot,\r\n\t\t\tCenterDotOpacity,\r\n\t\t\tCenterDotThickness\r\n\t\t);\r\n\r\n\t\tvar innerLinesHash = System.HashCode.Combine(\r\n\t\t\tShowInnerLines,\r\n\t\t\tInnerLineOpacity,\r\n\t\t\tInnerLineLenght,\r\n\t\t\tInnerLineThickness,\r\n\t\t\tInnerLinesOffset\r\n\t\t);\r\n\r\n\t\tvar outerLinesHash = System.HashCode.Combine(\r\n\t\t\tShowOuterLines,\r\n\t\t\tOuterLineOpacity,\r\n\t\t\tOuterLineLenght,\r\n\t\t\tOuterLineThickness,\r\n\t\t\tOuterLineOffset\r\n\t\t);\r\n\r\n\t\tvar codeHash = Code.GetHashCode();\r\n\t\t\r\n\t\treturn System.HashCode.Combine(\r\n\t\t\tpositionHash,\r\n\t\t\tcrosshairHash,\r\n\t\t\tinnerLinesHash,\r\n\t\t\touterLinesHash,\r\n\t\t\tcodeHash\r\n\t\t);\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "notathreat.crosshairbuilder",
            "Path": "CrosshairBuilder.razor",
            "FileName": "CrosshairBuilder.razor",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 67301,
            "Code": "@using System;\r\n@using Sandbox;\r\n@using Sandbox.UI;\r\n@inherits PanelComponent\r\n\r\n<root>\r\n    <div class=\"crosshair\" style=\"\r\n\t\tposition: absolute;\r\n\t\tleft: @( IsPercentage ? $\"{Position.x}%\"  : Position.x );\r\n\t\ttop: @( IsPercentage ? $\"{Position.y}%\" : Position.y );\r\n\t\ttransform: translate(-50%, -50%);\r\n\t\">\r\n\t\t<div class=\"center-dot-border-wrapper\" style=\"\r\n\t\t\tdisplay: @(CenterDot ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\tz-index: 100;\r\n\t\t\">\r\n\t\t\t<div class=\"center-dot\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(CenterDotOpacity));\r\n\t\t\t\tpadding: @(CenterDotThickness)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"inner-top-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n    \t\ttop: -@(InnerLinesOffset)px;\r\n    \t\tleft: 50%;\r\n    \t\ttransform: translateX(-50%);\r\n\t\t\tdisplay:@(ShowInnerLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"inner-line top\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));\r\n\t\t\t\tpadding-left: @(InnerLineThickness)px;\r\n    \t\t\tpadding-top: @(InnerLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"inner-bottom-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n    \t\tbottom: -@(InnerLinesOffset)px;\r\n    \t\tleft: 50%;\r\n    \t\ttransform: translateX(-50%);\r\n\t\t\tdisplay:@(ShowInnerLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"inner-line bottom\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));\r\n\t\t\t\tpadding-left: @(InnerLineThickness)px;\r\n    \t\t\tpadding-bottom: @(InnerLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"inner-left-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tleft: -@(InnerLinesOffset)px;\r\n\t\t\ttop: 50%;\r\n\t\t\ttransform: translateY(-50%);\r\n\t\t\tdisplay:@(ShowInnerLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"inner-line left\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));\r\n\t\t\t\tpadding-top: @(InnerLineThickness)px;\r\n\t\t\t\tpadding-left: @(InnerLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"inner-right-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tright: -@(InnerLinesOffset)px;\r\n\t\t\ttop: 50%;\r\n\t\t\ttransform: translateY(-50%);\r\n\t\t\tdisplay: @(ShowInnerLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"inner-line right\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(InnerLineOpacity));\r\n\t\t\t\tpadding-top: @(InnerLineThickness)px;\r\n\t\t\t\tpadding-right: @(InnerLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"outer-top-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\ttop: -@(OuterLineOffset)px;\r\n\t\t\tleft: 50%;\r\n\t\t\ttransform: translateX(-50%);\r\n\t\t\tdisplay: @(ShowOuterLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"outer-line top\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));\r\n\t\t\t\tpadding-left: @(OuterLineThickness)px;\r\n\t\t\t\tpadding-top: @(OuterLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"outer-bottom-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tbottom: -@(OuterLineOffset)px;\r\n\t\t\tleft: 50%;\r\n\t\t\ttransform: translateX(-50%);\r\n\t\t\tdisplay: @(ShowOuterLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"outer-line bottom\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));\r\n\t\t\t\tpadding-left: @(OuterLineThickness)px;\r\n\t\t\t\tpadding-bottom: @(OuterLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"outer-left-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tleft: -@(OuterLineOffset)px;\r\n\t\t\ttop: 50%;\r\n\t\t\ttransform: translateY(-50%);\r\n\t\t\tdisplay: @(ShowOuterLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"outer-line left\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));\r\n\t\t\t\tpadding-top: @(OuterLineThickness)px;\r\n\t\t\t\tpadding-left: @(OuterLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n\t\t<div class=\"outer-right-border-wrapper\" style=\"\r\n\t\t\tposition: absolute;\r\n\t\t\tright: -@(OuterLineOffset)px;\r\n\t\t\ttop: 50%;\r\n\t\t\ttransform: translateY(-50%);\r\n\t\t\tdisplay: @(ShowOuterLines ? \"flex\" : \"none\");\r\n\t\t\tborder: @(Outline ? $\"{OutlineThickness}px solid rgba(0, 0, 0, {OutlineOpacity})\" : \"none\");\r\n\t\t\">\r\n\t\t\t<div class=\"outer-line right\" style=\"\r\n\t\t\t\tbackground-color: rgba(@(Color.r * 255), @(Color.g * 255), @(Color.b * 255), @(OuterLineOpacity));\r\n\t\t\t\tpadding-top: @(OuterLineThickness)px;\r\n\t\t\t\tpadding-right: @(OuterLineLenght)px;\r\n\t\t\t\"></div>\r\n\t\t</div>\r\n    </div>\r\n</root>\r\n\r\n@code\r\n{\r\n\t// Position properties\r\n\t[Property] \r\n\t[Category(\"Position\")] public bool IsPercentage { get; set; } = true;\r\n\t[Property]\r\n\t[Category(\"Position\")] public Vector2 Position { get; set; } = new Vector2(50, 50);\r\n\r\n\t// Crosshair properties\r\n\t[Property]\r\n\t[Category(\"Crosshair\")] public Color Color { get; set; } = Color.FromRgb(0x2EFF00);\r\n\t[Property]\r\n\t[Category(\"Crosshair\")] public bool Outline { get; set; } = true;\r\n\t[Property]\r\n\t[Range(0f, 1f, 0.001f)]\r\n\t[Category(\"Crosshair\")] public float OutlineOpacity { get; set; } = 1f;\r\n\t[Property]\r\n\t[Range(1, 10, 1)]\r\n\t[Category(\"Crosshair\")] public int OutlineThickness { get; set; } = 2;\r\n\t[Property]\r\n\t[Category(\"Crosshair\")] public bool CenterDot { get; set; } = true;\r\n\t[Property]\r\n\t[Range(0f, 1f, 0.001f)]\r\n\t[Category(\"Crosshair\")] public float CenterDotOpacity { get; set; } = 1f;\r\n\t[Property]\r\n\t[Range(1, 10, 1)]\r\n\t[Category(\"Crosshair\")] public int CenterDotThickness { get; set; } = 1;\r\n\r\n\t// Inner Lines properties\r\n\t[Property]\r\n\t[Category(\"Inner Lines\")] public bool ShowInnerLines { get; set; } = true;\r\n\t[Property]\r\n\t[Range(0f, 1f, 0.001f)]\r\n\t[Category(\"Inner Lines\")] public float InnerLineOpacity { get; set; } = 1f;\r\n\t[Property]\r\n\t[Range(0, 20, 1)]\r\n\t[Category(\"Inner Lines\")] public int InnerLineLenght { get; set; } = 10;\r\n\t[Property]\r\n\t[Range(0, 10, 1)]\r\n\t[Category(\"Inner Lines\")] public int InnerLineThickness { get; set; } = 1;\r\n\t[Property]\r\n\t[Range(0, 20, 1)]\r\n\t[Category(\"Inner Lines\")] public int InnerLinesOffset { get; set; } = 2;\r\n\r\n\t// Outer Lines properties\r\n\t[Property]\r\n\t[Category(\"Outer Lines\")] public bool ShowOuterLines { get; set; } = false;\r\n\t[Property]\r\n\t[Range(0f, 1f, 0.001f)]\r\n\t[Category(\"Outer Lines\")] public float OuterLineOpacity { get; set; } = 0.5f;\r\n\t[Property]\r\n\t[Range(0, 20, 1)]\r\n\t[Category(\"Outer Lines\")] public int OuterLineLenght { get; set; }\r\n\t[Property]\r\n\t[Range(0, 10, 1)]\r\n\t[Category(\"Outer Lines\")] public int OuterLineThickness { get; set; }\r\n\t[Property]\r\n\t[Range(0, 20, 1)]\r\n\t[Category(\"Outer Lines\")] public int OuterLineOffset { get; set; }\r\n\r\n\t// Code properties\r\n\t[Property]\r\n\t[Category(\"Code\")] public string Code { get; set; }\r\n\r\n\t// Member variables\r\n\tprivate string _cachedCode = null;\r\n\r\n\tpublic string EncodeCrosshairParameters()\r\n\t{\r\n\t\t// Convert boolean values to 1 or 0\r\n\t\tstring EncodeBool(bool value) => value ? \"1\" : \"0\";\r\n\t\t// Convert float values to a shortened string representation (up to 2 decimal places)\r\n\t\tstring EncodeFloat(float value) => Math.Round(value, 2).ToString(\"0.##\");\r\n\t\t// Convert integers directly to string\r\n\t\tstring EncodeInt(int value) => value.ToString();\r\n\r\n\t\t// Concatenate all parameters into a shortened format\r\n\t\tvar parameters = $\"{EncodeBool(IsPercentage)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeFloat(Position.x)},{EncodeFloat(Position.y)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeFloat(Color.r)},{EncodeFloat(Color.g)},{EncodeFloat(Color.b)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeBool(Outline)},{EncodeFloat(OutlineOpacity)},{EncodeInt(OutlineThickness)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeBool(CenterDot)},{EncodeFloat(CenterDotOpacity)},{EncodeInt(CenterDotThickness)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeBool(ShowInnerLines)},{EncodeFloat(InnerLineOpacity)},{EncodeInt(InnerLineLenght)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeInt(InnerLineThickness)},{EncodeInt(InnerLinesOffset)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeBool(ShowOuterLines)},{EncodeFloat(OuterLineOpacity)},{EncodeInt(OuterLineLenght)},\" +\r\n\t\t\t\t\t\t\t$\"{EncodeInt(OuterLineThickness)},{EncodeInt(OuterLineOffset)}\";\r\n\t\treturn parameters;\r\n\t}\r\n\r\n\tpublic void DecodeCrosshairParameters(string encodedString)\r\n\t{\r\n\t\tvar parameters = encodedString.Split(',');\r\n\r\n\t\t// Convert \"1\" or \"0\" back to boolean\r\n\t\tbool DecodeBool(string value) => value == \"1\";\r\n\t\t// Convert string back to float\r\n\t\tfloat DecodeFloat(string value) => float.Parse(value);\r\n\t\t// Convert string back to int\r\n\t\tint DecodeInt(string value) => int.Parse(value);\r\n\r\n\t\t// Assign the decoded values back to the properties\r\n\t\tIsPercentage = DecodeBool(parameters[0]);\r\n\t\tPosition = new Vector2(DecodeFloat(parameters[1]), DecodeFloat(parameters[2]));\r\n\t\tColor = new Color(DecodeFloat(parameters[3]), DecodeFloat(parameters[4]), DecodeFloat(parameters[5]));\r\n\t\tOutline = DecodeBool(parameters[6]);\r\n\t\tOutlineOpacity = DecodeFloat(parameters[7]);\r\n\t\tOutlineThickness = DecodeInt(parameters[8]);\r\n\t\tCenterDot = DecodeBool(parameters[9]);\r\n\t\tCenterDotOpacity = DecodeFloat(parameters[10]);\r\n\t\tCenterDotThickness = DecodeInt(parameters[11]);\r\n\t\tShowInnerLines = DecodeBool(parameters[12]);\r\n\t\tInnerLineOpacity = DecodeFloat(parameters[13]);\r\n\t\tInnerLineLenght = DecodeInt(parameters[14]);\r\n\t\tInnerLineThickness = DecodeInt(parameters[15]);\r\n\t\tInnerLinesOffset = DecodeInt(parameters[16]);\r\n\t\tShowOuterLines = DecodeBool(parameters[17]);\r\n\t\tOuterLineOpacity = DecodeFloat(parameters[18]);\r\n\t\tOuterLineLenght = DecodeInt(parameters[19]);\r\n\t\tOuterLineThickness = DecodeInt(parameters[20]);\r\n\t\tOuterLineOffset = DecodeInt(parameters[21]);\r\n\t}\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tif (Code == null)\r\n\t\t{\r\n\t\t\tCode = EncodeCrosshairParameters();\r\n\t\t}\r\n\t\tDecodeCrosshairParameters(Code);\r\n\t\t_cachedCode = Code;\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif (Code != _cachedCode)\r\n\t\t{\r\n\t\t\tDecodeCrosshairParameters(Code);\r\n\t\t}\r\n\t\tCode = EncodeCrosshairParameters();\r\n\t\t_cachedCode = Code;\r\n\t}\r\n\r\n\t/// <summary>\r\n\t/// the hash determines if the system should be rebuilt. If it changes, it will be rebuilt\r\n\t/// </summary>\r\n\tprotected override int BuildHash()\r\n\t{\r\n\t\tvar positionHash = System.HashCode.Combine( \r\n\t\t\tIsPercentage,\r\n\t\t\tPosition\r\n\t\t);\r\n\r\n\t\tvar crosshairHash = System.HashCode.Combine( \r\n\t\t\tColor,\r\n\t\t\tOutline,\r\n\t\t\tOutlineOpacity,\r\n\t\t\tOutlineThickness,\r\n\t\t\tCenterDot,\r\n\t\t\tCenterDotOpacity,\r\n\t\t\tCenterDotThickness\r\n\t\t);\r\n\r\n\t\tvar innerLinesHash = System.HashCode.Combine(\r\n\t\t\tShowInnerLines,\r\n\t\t\tInnerLineOpacity,\r\n\t\t\tInnerLineLenght,\r\n\t\t\tInnerLineThickness,\r\n\t\t\tInnerLinesOffset\r\n\t\t);\r\n\r\n\t\tvar outerLinesHash = System.HashCode.Combine(\r\n\t\t\tShowOuterLines,\r\n\t\t\tOuterLineOpacity,\r\n\t\t\tOuterLineLenght,\r\n\t\t\tOuterLineThickness,\r\n\t\t\tOuterLineOffset\r\n\t\t);\r\n\r\n\t\tvar codeHash = Code.GetHashCode();\r\n\t\t\r\n\t\treturn System.HashCode.Combine(\r\n\t\t\tpositionHash,\r\n\t\t\tcrosshairHash,\r\n\t\t\tinnerLinesHash,\r\n\t\t\touterLinesHash,\r\n\t\t\tcodeHash\r\n\t\t);\r\n\t}\r\n}\r\n"
        },
        {
            "Ident": "notathreat.crosshairbuilder",
            "Path": "UnitTests/LibraryTest.cs",
            "FileName": "LibraryTest.cs",
            "PackageType": "library",
            "CodeKind": "UnitTest",
            "AssetVersionId": 67301,
            "Code": "using Sandbox;\r\n\r\n[TestClass]\r\npublic partial class LibraryTests\r\n{\r\n\t[TestMethod]\r\n\tpublic void SceneTest()\r\n\t{\r\n\t\tvar scene = new Scene();\r\n\t\tusing ( scene.Push() )\r\n\t\t{\r\n\t\t\tvar go = new GameObject();\r\n\r\n\t\t\tAssert.AreEqual( 1, scene.Directory.GameObjectCount );\r\n\t\t}\r\n\t}\r\n\r\n}\r\n"
        },
        {
            "Ident": "notathreat.crosshairbuilder",
            "Path": "__gen_RazorNamespace.cs",
            "FileName": "__gen_RazorNamespace.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 67301,
            "Code": "global using Microsoft.AspNetCore.Components; \nglobal using Microsoft.AspNetCore.Components.Rendering;\n"
        },
        {
            "Ident": "notathreat.crosshairbuilder",
            "Path": ".obj/__compiler_extra.cs",
            "FileName": "__compiler_extra.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 67301,
            "Code": "global using static Sandbox.Internal.GlobalGameNamespace;\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"AddonTitle\", \"CrosshairBuilder\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"AddonIdent\", \"crosshairbuilder\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"OrgIdent\", \"notathreat\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"Ident\", \"notathreat.crosshairbuilder\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"CompileTime\", \"8/19/2024 3:47:41 PM\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"EngineVersion\", \"17\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"EngineMinorVersion\", \"1\" )]\r\n\r\n[assembly: System.Runtime.Versioning.TargetFramework( \".NETCoreApp,Version=v7.0\", FrameworkDisplayName = \".NET 7.0\" )]\r\n[assembly: global::System.Reflection.AssemblyVersion(\"0.0.121.0\")]\r\n[assembly: global::System.Reflection.AssemblyFileVersion(\"0.0.121.0\")]"
        },
        {
            "Ident": "notathreat.crosshairbuilder",
            "Path": "UnitTests/UnitTest.cs",
            "FileName": "UnitTest.cs",
            "PackageType": "library",
            "CodeKind": "UnitTest",
            "AssetVersionId": 67301,
            "Code": "global using Microsoft.VisualStudio.TestTools.UnitTesting;\r\n\r\n[TestClass]\r\npublic class TestInit\r\n{\r\n\t[AssemblyInitialize]\r\n\tpublic static void ClassInitialize( TestContext context )\r\n\t{\r\n\t\tSandbox.Application.InitUnitTest();\r\n\t}\r\n}\r\n"
        }
    ]
}