Marker3dPanel.razor
@using Sandbox;
@using Sandbox.UI;
@inherits PanelComponent
@namespace Marker3d

<style>
	Marker3dPanel {
		position: absolute;
		left: 0;
		right: 0;
		top: 0;
		bottom: 0;
		overflow: visible;

		.collection {
			position: absolute;
			left: 0;
			right: 0;
			top: 0;
			bottom: 0;
			overflow: visible;
		}

		.container {
			position: absolute;
			width: 0px;
			height: 0px;
			align-content: center;
			justify-content: center;
			align-items: center;
		}

		.element {
			align-self: center;
			flex-shrink: 0;
			width: 32px;
			height: 32px;
		}
	}
</style>

<root>
	<div class="collection" @ref="Centers">
		@foreach(var marker in Marker3ds) {
			<div class="container" style="left: @(marker.CenterPosition.x * 100f)%; top: @(marker.CenterPosition.y * 100f)%;">
				<img class="element" style="transform: scale(@(marker.CenterScale)); background-image-tint: @(marker.CenterTint.Hex);">
			</div>
		}
	</div>
	<div class="collection" @ref="Arrows">
		@foreach(var marker in Marker3ds) {
			if (marker.ShowArrow) {
				<div class="container" style="left: @(marker.CenterPosition.x * 100f)%; top: @(marker.CenterPosition.y * 100f)%;">
					<img class="element" style="transform: translate(@(marker.ArrowOffset.x)px, @(marker.ArrowOffset.y)px) rotate(@(marker.ArrowRotation)deg) scale(@(marker.ArrowScale.x)) scaleY(@(marker.ArrowScale.y / marker.ArrowScale.x)) rotate(@(marker.ArrowLocalRotation)deg); background-image-tint: @(marker.ArrowTint.Hex);">
				</div>
			}
		}
	</div>
</root>

@code
{
	public IEnumerable<Marker3d.Data> Marker3ds => Scene.GetAllComponents<Marker3d>().SelectWhere(x => x.GetData());
	public Panel Centers { get; set; }
	public Panel Arrows { get; set; }

	protected override void OnTreeBuilt() {
		foreach ((var container, var marker3d) in Centers.Children.Zip(Marker3ds)) {
			var center = (Image)container.Children.First();
			center.Texture = marker3d.Center;
		}
		
		foreach ((var container, var marker3d) in Arrows.Children.Zip(Marker3ds).Where(x => x.Item2.ShowArrow)) {
			var arrow = (Image)container.Children.First();
			arrow.Texture = marker3d.Arrow;
		}
	}

	protected override int BuildHash() => System.HashCode.Combine( Marker3ds.HashCombine() );
}