// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "ConeComponent.h"

#define CONEARCVERTEXCOUNT 50

// Sets default values for this component's properties
UConeComponent::UConeComponent(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
	ShapeColor = FColor(223, 149, 157, 255);
	bUseEditorCompositing = true;
}

void UConeComponent::BeginPlay()
{
	UpdateCapsule();
	Super::BeginPlay();
}

void UConeComponent::UpdateCapsule()
{
	SetCapsuleSize(coneRadius, 400);
}

// Create sceneproxy to show the cone in the editor
FPrimitiveSceneProxy* UConeComponent::CreateSceneProxy()
{
	class FDrawConeSceneProxy : public FPrimitiveSceneProxy
	{
	public:
		const UConeComponent* component;
		FDrawConeSceneProxy(const UConeComponent* InComponent)
			: FPrimitiveSceneProxy(InComponent)
			, bDrawOnlyIfSelected(InComponent->bDrawOnlyIfSelected)
			, component(InComponent)
		{
			bWillEverBeLit = false;
		}

		
		virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const
		{
			QUICK_SCOPE_CYCLE_COUNTER(STAT_GetDynamicMeshElements_DrawDynamicElements);
			
			for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
			{
			
				if (VisibilityMap & (1 << ViewIndex))
				{
					const FSceneView* View = Views[ViewIndex];
					const FLinearColor DrawCapsuleColor = GetViewSelectionColor(ShapeColor, *View, IsSelected(), IsHovered(), false, IsIndividuallySelected());
			
					FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);

					FTransform transform = component->GetComponentTransform();
					FVector base = transform.GetLocation();
					
					const float scale = 1.0f / 180.0f * PI;
					float baseRot = (360.0f - transform.GetRotation().Euler().Z) * scale;

					FVector scaleVec = transform.GetScale3D();
					FVector forward = FVector(scaleVec.X, 0, 0);
					FVector right = FVector(0, scaleVec.Y, 0);
					float angle = (component->coneAngle) / 180.0f * PI;

					FVector linePoints[CONEARCVERTEXCOUNT];
					float anglestep = (angle) / (CONEARCVERTEXCOUNT-1);

					float rot = baseRot - angle * 0.5f;
					for (int i = 0; i < CONEARCVERTEXCOUNT;i++)
					{
						float f = cosf(rot);
						float r = sinf(rot);
						linePoints[i] = base + (forward * f - right * r) * component->coneRadius;
						rot += anglestep;
					}

					for (int i = 0; i < CONEARCVERTEXCOUNT-1; i++)
					{

						PDI->DrawLine(linePoints[i], linePoints[i + 1], ShapeColor, SDPG_World);
					}
					PDI->DrawLine(base, linePoints[0], ShapeColor, SDPG_World);
					PDI->DrawLine(base, linePoints[CONEARCVERTEXCOUNT - 1], ShapeColor, SDPG_World);
				}
			}
		}

		virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
		{
			const bool bVisible = !bDrawOnlyIfSelected || IsSelected();
			FPrimitiveViewRelevance Result;
			Result.bDrawRelevance = IsShown(View) && bVisible;
			Result.bDynamicRelevance = true;
			Result.bShadowRelevance = IsShadowCast(View);
			Result.bEditorPrimitiveRelevance = UseEditorCompositing(View);
			return Result;
		}

		virtual uint32 GetMemoryFootprint(void) const override { return(sizeof(*this) + GetAllocatedSize()); }
		uint32 GetAllocatedSize(void) const { return(FPrimitiveSceneProxy::GetAllocatedSize()); }

	private:
		const uint32	bDrawOnlyIfSelected : 1;
		const FColor	ShapeColor = FColor(255,0,0,255);
		const FTransform transform;
	};
	return new FDrawConeSceneProxy(this);
}
