Skip to content
Snippets Groups Projects
Select Git revision
  • d70232d3bd9abb4a5b930e70fdc7a70d05ecae75
  • master default protected
  • feature/refactor
  • 4.24
  • develop
  • Rendering
  • temp-optix-6
7 results

SelectableActorBase.cpp

Blame
  • SelectableActorBase.cpp 21.68 KiB
    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "SelectableActorBase.h"
    #include "UObject/ConstructorHelpers.h"
    #include "Runtime/Engine/Classes/Engine/StaticMesh.h"
    #include "Kismet/GameplayStatics.h"
    #include "Blueprint/UserWidget.h"
    #include "Runtime/Engine/Classes/Materials/MaterialInstanceDynamic.h"
    
    #include "OptiXVRPawn.h"
    
    ASelectableActorBase::ASelectableActorBase(const FObjectInitializer& ObjectInitializer)
    	: Super(ObjectInitializer)
    {
    
    	UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor Start"));
    
    	SetMobility(EComponentMobility::Movable);
    
    	GetStaticMeshComponent()->SetGenerateOverlapEvents(true);
    	GetStaticMeshComponent()->CastShadow = 0;
    
    	UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor Component Setup Start"));
    
    
    	Gizmo = CreateDefaultSubobject<USceneComponent>(TEXT("Gizmo"));
    	Gizmo->SetupAttachment(GetStaticMeshComponent());
    	Gizmo->SetHiddenInGame(true);
    
    	SupportWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("SupportWidget"));
    	SupportWidget->SetupAttachment(Gizmo);
    	static ConstructorHelpers::FClassFinder<UUserWidget> SupportWidgetClass(TEXT("/OptiX/UI/SupportSwapWidget2"));
    	SupportWidget->SetWidgetClass(SupportWidgetClass.Class);
    	SupportWidget->SetAbsolute(false, true, false);
    	SupportWidget->SetWorldScale3D(FVector(0.05, 0.05, 0.05));
    	SupportWidget->SetDrawSize(FVector2D(800, 2300));
    	SupportWidget->SetGenerateOverlapEvents(false);
    	SupportWidget->SetHiddenInGame(true);
    	SupportWidget->SetTwoSided(true);
    
    	UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 1/4"));
    
    
    	TranslationSupport = CreateDefaultSubobject<USceneComponent>(TEXT("TranslationSupport"));
    	TranslationSupport->SetupAttachment(Gizmo);
    
    	TranslateX = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateX"));
    	TranslateX->SetupAttachment(TranslationSupport);
    	static ConstructorHelpers::FObjectFinder<UStaticMesh> TranslateXMesh(TEXT("StaticMesh'/OptiX/UI/Translator/Arrowbody.Arrowbody'"));
    	TranslateX->SetStaticMesh(TranslateXMesh.Object);
    	TranslateX->SetAbsolute(false, true, false);
    	TranslateX->SetWorldScale3D(FVector(0.8f, 0.8f, 0.8f));
    	TranslateX->SetGenerateOverlapEvents(false);
    	TranslateX->SetHiddenInGame(true);
    
    	TranslateX->CastShadow = 0;
    	TranslateX->bVisibleInReflectionCaptures = false;
    	TranslateX->SetCanEverAffectNavigation(false);
    
    	ArrowX = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowX"));
    	ArrowX->SetupAttachment(TranslateX);
    	static ConstructorHelpers::FObjectFinder<UStaticMesh> TranslateArrow(TEXT("StaticMesh'/OptiX/UI/Translator/Arrowhead.Arrowhead'"));
    	ArrowX->SetStaticMesh(TranslateArrow.Object);
    	//ArrowX->SetAbsolute(false, true, false);
    	//ArrowX->SetWorldScale3D(FVector(0.8f, 0.8f, 0.8f));
    	ArrowX->SetRelativeLocation(FVector(39, 0, 0));
    	ArrowX->SetGenerateOverlapEvents(false);
    	ArrowX->SetHiddenInGame(true);
    	ArrowX->SetAbsolute(false, false, true);
    
    	ArrowX->CastShadow = 0;
    	ArrowX->bVisibleInReflectionCaptures = false;
    	ArrowX->SetCanEverAffectNavigation(false);
    
    	TranslateWidgetX = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetX"));
    	TranslateWidgetX->SetAbsolute(false, true, true);
    	TranslateWidgetX->SetupAttachment(ArrowX);
    	static ConstructorHelpers::FClassFinder<UUserWidget> PosWidgetClass(TEXT("/OptiX/UI/Translator/PositionCounter"));
    	TranslateWidgetX->SetWidgetClass(PosWidgetClass.Class);
    	//TranslateWidgetX->SetRelativeLocationAndRotation(FVector(0, 0, 0), FRotator(0, 90, 0));
    	//TranslateWidgetX->SetWorldRotation(FRotator());
    	TranslateWidgetX->SetRelativeScale3D(FVector(0.05, 0.05, 0.05));
    	TranslateWidgetX->SetDrawSize(FVector2D(300, 300));
    	TranslateWidgetX->SetHiddenInGame(true);
    	TranslateWidgetX->SetGenerateOverlapEvents(false);
    	//TranslateWidgetX->SetTwoSided(true);
    	// todo
    
    	TranslateY = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateY"));
    	TranslateY->SetupAttachment(TranslationSupport);
    	TranslateY->SetStaticMesh(TranslateXMesh.Object);
    	TranslateY->SetAbsolute(false, true, false);
    	TranslateY->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f));
    	TranslateY->SetGenerateOverlapEvents(false);
    	TranslateY->SetHiddenInGame(true);
    	TranslateY->SetWorldRotation(FRotator(0.f, 90.0f, 0.0f));
    
    	TranslateY->CastShadow = 0;
    	TranslateY->bVisibleInReflectionCaptures = false;
    	TranslateY->SetCanEverAffectNavigation(false);
    
    	ArrowY = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowY"));
    	ArrowY->SetupAttachment(TranslateY);
    	ArrowY->SetStaticMesh(TranslateArrow.Object);
    	//ArrowY->SetAbsolute(false, true, false);
    	ArrowY->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f));
    	ArrowY->SetRelativeLocation(FVector(39, 0, 0));
    	ArrowY->SetGenerateOverlapEvents(false);
    	ArrowY->SetHiddenInGame(true);
    	ArrowY->SetAbsolute(false, false, true);
    
    	ArrowY->CastShadow = 0;
    	ArrowY->bVisibleInReflectionCaptures = false;
    	ArrowY->SetCanEverAffectNavigation(false);
    
    	TranslateWidgetY = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetY"));	
    	TranslateWidgetY->SetAbsolute(false, true, true);
    	TranslateWidgetY->SetupAttachment(ArrowY);
    	TranslateWidgetY->SetWidgetClass(PosWidgetClass.Class);
    	//TranslateWidgetY->SetWorldRotation(FRotator());
    	TranslateWidgetY->SetRelativeScale3D(FVector(0.05, 0.05, 0.05));
    	TranslateWidgetY->SetDrawSize(FVector2D(300, 300));
    	TranslateWidgetY->SetHiddenInGame(true);
    	TranslateWidgetY->SetGenerateOverlapEvents(false);
    	//TranslateWidgetY->SetTwoSided(true);
    
    	TranslateZ = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateZ"));
    	TranslateZ->SetupAttachment(TranslationSupport);
    	TranslateZ->SetStaticMesh(TranslateXMesh.Object);
    	TranslateZ->SetAbsolute(false, true, false);
    	TranslateZ->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f));
    	TranslateZ->SetGenerateOverlapEvents(false);
    	TranslateZ->SetHiddenInGame(true);
    	TranslateZ->SetWorldRotation(FRotator(90.f, 0.0f, 0.0f));
    	TranslateZ->SetCanEverAffectNavigation(false);
    	TranslateZ->CastShadow = 0;
    	TranslateZ->bVisibleInReflectionCaptures = false;
    
    	ArrowZ = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowZ"));
    	ArrowZ->SetupAttachment(TranslateZ);
    	ArrowZ->SetStaticMesh(TranslateArrow.Object);
    	//ArrowZ->SetAbsolute(false, true, false);
    	ArrowZ->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f));
    	ArrowZ->SetRelativeLocation(FVector(39, 0, 0));
    	ArrowZ->SetGenerateOverlapEvents(false);
    	ArrowZ->SetHiddenInGame(true);
    	ArrowZ->SetAbsolute(false, false, true);
    	ArrowZ->SetCanEverAffectNavigation(false);
    	ArrowZ->CastShadow = 0;
    	ArrowZ->bVisibleInReflectionCaptures = false;
    
    	TranslateWidgetZ = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetZ"));
    	TranslateWidgetZ->SetAbsolute(false, true, true);
    	//TranslateWidgetZ->SetTwoSided(true);
    
    	TranslateWidgetZ->SetupAttachment(ArrowZ);
    	TranslateWidgetZ->SetWidgetClass(PosWidgetClass.Class);
    	//TranslateWidgetZ->SetWorldRotation(FRotator());
    	TranslateWidgetZ->SetRelativeScale3D(FVector(0.05, 0.05, 0.05));
    	TranslateWidgetZ->SetDrawSize(FVector2D(300, 300));
    	TranslateWidgetZ->SetRelativeLocation(FVector(8, 0, 0));
    
    	TranslateWidgetZ->SetHiddenInGame(true);
    	TranslateWidgetZ->SetGenerateOverlapEvents(false);
    
    	UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 2/4"));
    
    
    	RotationSupport = CreateDefaultSubobject<USceneComponent>(TEXT("RotationSupport"));
    	RotationSupport->SetupAttachment(Gizmo);
    
    	ScaleH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ScaleH"));
    	ScaleH->SetupAttachment(RotationSupport);
    	static ConstructorHelpers::FObjectFinder<UStaticMesh> ScaleMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/scale1.scale1'"));
    	ScaleH->SetStaticMesh(ScaleMesh.Object);
    	ScaleH->SetAbsolute(false, true, false);
    	ScaleH->SetGenerateOverlapEvents(false);
    	ScaleH->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    	ScaleH->SetHiddenInGame(true);
    	ScaleH->SetCanEverAffectNavigation(false);
    	ScaleH->CastShadow = 0;
    	ScaleH->bVisibleInReflectionCaptures = false;
    
    	ScaleV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ScaleV"));
    	ScaleV->SetupAttachment(RotationSupport);
    	ScaleV->SetStaticMesh(ScaleMesh.Object);
    	ScaleV->SetWorldRotation(FRotator(90, 0, 0));
    	ScaleV->SetAbsolute(false, true, false);
    	ScaleV->SetGenerateOverlapEvents(false);
    	ScaleV->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    	ScaleV->SetHiddenInGame(true);
    	ScaleV->SetCanEverAffectNavigation(false);
    	ScaleV->CastShadow = 0;
    	ScaleV->bVisibleInReflectionCaptures = false;
    
    	SupportH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportH"));
    	SupportH->SetupAttachment(RotationSupport);
    	static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/Cylinder_2.Cylinder_2'"));
    	SupportH->SetStaticMesh(SupportMesh.Object);
    	SupportH->SetWorldRotation(FRotator(-90, 0, 0));
    	SupportH->SetWorldScale3D(FVector(0.6, 0.6, 0.3));
    	SupportH->SetGenerateOverlapEvents(false);
    	SupportH->SetHiddenInGame(true);
    	//SupportH->SetWorldLocation(FVector(25, 0, 0));
    	SupportH->SetCanEverAffectNavigation(false);
    	SupportH->CastShadow = 0;
    	SupportH->bVisibleInReflectionCaptures = false;
    
    	SupportSphereH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportSphereH"));
    	SupportSphereH->SetupAttachment(SupportH);
    	static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportSphereMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/SelectorSphere.SelectorSphere'"));
    	SupportSphereH->SetStaticMesh(SupportSphereMesh.Object);
    	SupportSphereH->SetAbsolute(false, false, true);
    	SupportSphereH->SetWorldScale3D(FVector(0.03, 0.03, 0.03));
    	SupportSphereH->SetGenerateOverlapEvents(false);
    	SupportSphereH->SetHiddenInGame(true);
    	SupportSphereH->SetRelativeLocation(FVector(0, 0, 100));
    	SupportSphereH->SetCanEverAffectNavigation(false);
    	SupportSphereH->CastShadow = 0;
    	SupportSphereH->bVisibleInReflectionCaptures = false;
    
    	DegreeWidgetH = CreateDefaultSubobject<UWidgetComponent>(TEXT("DegreeWidgetH"));
    	DegreeWidgetH->SetupAttachment(SupportSphereH);
    	static ConstructorHelpers::FClassFinder<UUserWidget> DegreeWidgetClass(TEXT("/OptiX/UI/Rotator/DegreeCounter"));
    	DegreeWidgetH->SetWidgetClass(DegreeWidgetClass.Class);
    	DegreeWidgetH->SetRelativeLocationAndRotation(FVector(0, 0, -40), FRotator(0, 90, -90));
    	//DegreeWidgetH->SetRelativeScale3D(FVector(2.0, 2.0, 0.08));
    	DegreeWidgetH->SetDrawSize(FVector2D(200, 300));
    	DegreeWidgetH->SetHiddenInGame(true);
    	DegreeWidgetH->SetGenerateOverlapEvents(false);
    	//DegreeWidgetH->SetTwoSided(true);
    
    	SupportV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportV"));
    	SupportV->SetupAttachment(RotationSupport);
    	SupportV->SetStaticMesh(SupportMesh.Object);
    	SupportV->SetWorldRotation(FRotator(0.0f, 0.0f, 90.0f));
    	SupportV->SetWorldScale3D(FVector(0.6, 0.6, 0.3));
    	SupportV->SetGenerateOverlapEvents(false);
    	SupportV->SetHiddenInGame(true);
    	//SupportV->SetWorldLocation(FVector(0, 25, 0));
    	SupportV->SetCanEverAffectNavigation(false);
    	SupportV->CastShadow = 0;
    	SupportV->bVisibleInReflectionCaptures = false;
    
    	SupportSphereV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportSphereV"));
    	SupportSphereV->SetupAttachment(SupportV);
    	//static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportSphereMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/Sphere_2.Sphere_2'"));
    	SupportSphereV->SetStaticMesh(SupportSphereMesh.Object);
    	SupportSphereV->SetAbsolute(false, false, true);
    	SupportSphereV->SetWorldScale3D(FVector(0.03, 0.03, 0.03));
    	SupportSphereV->SetGenerateOverlapEvents(false);
    	SupportSphereV->SetHiddenInGame(true);
    	SupportSphereV->SetRelativeLocation(FVector(0, 0, 100));
    	SupportSphereV->SetCanEverAffectNavigation(false);
    	SupportSphereV->CastShadow = 0;
    	SupportSphereV->bVisibleInReflectionCaptures = false;
    
    	DegreeWidgetV = CreateDefaultSubobject<UWidgetComponent>(TEXT("DegreeWidgetV"));
    	DegreeWidgetV->SetupAttachment(SupportSphereV);
    	DegreeWidgetV->SetWidgetClass(DegreeWidgetClass.Class);
    	DegreeWidgetV->SetRelativeLocationAndRotation(FVector(0, 0, 40), FRotator(0, 0, -90));
    	//DegreeWidgetV->SetRelativeScale3D(FVector(2.0, 2.0, 0.08));
    	DegreeWidgetV->SetDrawSize(FVector2D(200, 300));
    	DegreeWidgetV->SetHiddenInGame(true);
    	DegreeWidgetV->SetGenerateOverlapEvents(false);
    	//DegreeWidgetV->SetTwoSided(true);
    
    	UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 3/4"));
    	   	 
    
    	// Rods	   	 
    
    	static ConstructorHelpers::FObjectFinder<UMaterial> MetalMaterial(TEXT("Material'/OptiX/Laser/MetalSilver.MetalSilver'"));
    	static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereMesh(TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));
    	static ConstructorHelpers::FObjectFinder<UStaticMesh> Cylinder2(TEXT("StaticMesh'/OptiX/UI/Rotator/Cylinder_2.Cylinder_2'"));
    
    	Socket = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SocketNew"));
    	Socket->SetAbsolute(false, false, true);
    
    	Socket->SetupAttachment(GetStaticMeshComponent());
    	Socket->SetStaticMesh(SphereMesh.Object);
    	Socket->SetGenerateOverlapEvents(false);
    	Socket->SetMaterial(0, MetalMaterial.Object);
    	Socket->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    	Socket->SetWorldScale3D(FVector(0.03, 0.03, 0.03));
    	//Socket->SetRelativeLocation(FVector(0, 0, 0));
    	Socket->SetCanEverAffectNavigation(false);
    	Socket->CastShadow = 0;
    	Socket->bVisibleInReflectionCaptures = false;
    
    	ConnectorV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ConnectorVNew"));
    	ConnectorV->SetAbsolute(false, true, true);
    
    	ConnectorV->SetupAttachment(Socket);
    	ConnectorV->SetStaticMesh(Cylinder2.Object);
    	ConnectorV->SetWorldScale3D(FVector(0.5, 0.5, -1));
    	ConnectorV->SetGenerateOverlapEvents(false);
    	ConnectorV->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    	ConnectorV->SetMaterial(0, MetalMaterial.Object);
    	ConnectorV->SetMaterial(1, MetalMaterial.Object);
    	ConnectorV->SetCanEverAffectNavigation(false);
    	ConnectorV->CastShadow = 0;
    	ConnectorV->bVisibleInReflectionCaptures = false;
    
    	Sphere = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SphereNew"));
    	Sphere->SetAbsolute(false, false, true);
    
    	Sphere->SetupAttachment(ConnectorV);
    	Sphere->SetStaticMesh(SphereMesh.Object);
    	Sphere->SetGenerateOverlapEvents(false);
    	Sphere->SetMaterial(0, MetalMaterial.Object);
    	Sphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    	Sphere->SetWorldScale3D(FVector(0.03, 0.03, 0.03));
    	Sphere->SetRelativeLocation(FVector(0, 0, 100));
    	Sphere->SetCanEverAffectNavigation(false);
    	Sphere->CastShadow = 0;
    	Sphere->bVisibleInReflectionCaptures = false;
    
    	ConnectorH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ConnectorHNew"));
    	ConnectorH->SetAbsolute(false, true, true);
    	ConnectorH->SetupAttachment(ConnectorV);
    	ConnectorH->SetStaticMesh(Cylinder2.Object);
    	ConnectorH->SetGenerateOverlapEvents(false);	
    	ConnectorH->SetRelativeLocation(FVector(0, 0, 100));
    	ConnectorH->SetWorldScale3D(FVector(0.5, 0.5, 1.0));
    	ConnectorH->SetMaterial(0, MetalMaterial.Object);
    	ConnectorH->SetMaterial(1, MetalMaterial.Object);
    	ConnectorH->SetGenerateOverlapEvents(false);
    	ConnectorH->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    	ConnectorH->SetCanEverAffectNavigation(false);
    	ConnectorH->CastShadow = 0;
    	ConnectorH->bVisibleInReflectionCaptures = false;
    
    	UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor End 4/4"));
    
    
    }
    
    void ASelectableActorBase::BeginPlay()
    {
    	Super::BeginPlay();
    
    	ArrowX->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowX->GetMaterial(0));
    	ArrowX->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowX->GetMaterial(1));
    	ArrowY->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowY->GetMaterial(0));
    	ArrowY->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowY->GetMaterial(1));
    	ArrowZ->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowZ->GetMaterial(0));
    	ArrowZ->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowZ->GetMaterial(1));
    
    	SupportSphereH->CreateAndSetMaterialInstanceDynamicFromMaterial(0, SupportSphereH->GetMaterial(0));
    	SupportSphereV->CreateAndSetMaterialInstanceDynamicFromMaterial(0, SupportSphereV->GetMaterial(0));
    
    
    	SupportSphereH->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin);
    	SupportSphereH->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd);
    
    	SupportSphereV->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin);
    	SupportSphereV->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd);
    
    	ArrowX->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin);
    	ArrowX->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd);
    
    	ArrowY->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin);
    	ArrowY->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd);
    
    	ArrowZ->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin);
    	ArrowZ->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd);
    }
    
    void ASelectableActorBase::Tick(float DeltaTime)
    {
    	Super::Tick(DeltaTime);
    	
    
    	FVector PlayerLocation = UGameplayStatics::GetPlayerPawn(GetWorld(), 0)->GetActorLocation();
    	{
    		FVector Diff = PlayerLocation - DegreeWidgetV->GetComponentTransform().GetLocation();
    		FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1));
    		DegreeWidgetV->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator());
    	}
    	{
    		FVector Diff = PlayerLocation - DegreeWidgetH->GetComponentTransform().GetLocation();
    		FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1));
    		DegreeWidgetH->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator());
    	}
    	{
    		FVector Diff = PlayerLocation - SupportWidget->GetComponentTransform().GetLocation();
    		FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1));
    		SupportWidget->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator());
    	}
    	{
    		FVector Diff = PlayerLocation - TranslateWidgetX->GetComponentTransform().GetLocation();
    		FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1));
    		TranslateWidgetX->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator());
    	} 
    	{
    		FVector Diff = PlayerLocation - TranslateWidgetY->GetComponentTransform().GetLocation();
    		FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1));
    		TranslateWidgetY->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator());
    	}
    	{
    		FVector Diff = PlayerLocation - TranslateWidgetZ->GetComponentTransform().GetLocation();
    		FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1));
    		TranslateWidgetZ->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator());
    	}
    
    }
    
    void ASelectableActorBase::SetScaleV(FRotator Rot)
    {
    	ScaleV->SetWorldRotation(Rot);
    }
    
    void ASelectableActorBase::SetScaleH(FRotator Rot)
    {
    	ScaleH->SetWorldRotation(Rot);
    }
    
    void ASelectableActorBase::EnableTranslation()
    {
    	TranslationSupport->SetHiddenInGame(false, true);
    	RotationSupport->SetHiddenInGame(true, true);
    
    	SupportSphereV->SetGenerateOverlapEvents(false);
    	SupportSphereH->SetGenerateOverlapEvents(false);
    	ArrowX->SetGenerateOverlapEvents(true);
    	ArrowY->SetGenerateOverlapEvents(true);
    	ArrowZ->SetGenerateOverlapEvents(true);
    
    	AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
    	if (OptiXVRPawn)
    	{
    		OptiXVRPawn->UIEventTranslation();
    	}
    
    }
    
    void ASelectableActorBase::EnableRotation()
    {
    	TranslationSupport->SetHiddenInGame(true, true);
    	RotationSupport->SetHiddenInGame(false, true);
    
    	SupportSphereV->SetGenerateOverlapEvents(true);
    	SupportSphereH->SetGenerateOverlapEvents(true);
    	ArrowX->SetGenerateOverlapEvents(false);
    	ArrowY->SetGenerateOverlapEvents(false);
    	ArrowZ->SetGenerateOverlapEvents(false);
    
    	AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
    	if (OptiXVRPawn)
    	{
    		OptiXVRPawn->UIEventRotation();
    	}
    }
    
    void ASelectableActorBase::DeselectActor()
    {
    	AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
    	if (OptiXVRPawn)
    	{
    		OptiXVRPawn->UIEventDeselect();
    	}
    	Deselect();
    }
    
    void ASelectableActorBase::DeleteActor()
    {
    	AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
    	if (OptiXVRPawn)
    	{
    		OptiXVRPawn->UIEventDelete();
    	}
    	Destroy();
    }
    
    
    void ASelectableActorBase::SetRodPosition(FVector TablePosition)
    {
    	FVector TableZero = TablePosition + FVector(0, 0, 95); // Table Height	
    
    	// Far away from the table or below table, make it go straight down
    	if ( (Socket->GetComponentLocation().Z <= TableZero.Z) || (Socket->GetComponentLocation() - TableZero).Size() > 200) 
    	{
    		ConnectorH->SetWorldScale3D(FVector(0, 0, 0));
    		ConnectorV->SetWorldScale3D(FVector(1, 1, -10));
    		return;
    	}
    
    
    	float ScaleFactorV = FMath::Abs(ConnectorV->GetComponentLocation().Z - TableZero.Z) / 100.0f;
    	ConnectorV->SetWorldScale3D(FVector(1, 1, -ScaleFactorV));
    
    	FVector DistanceToSphere = TableZero - Sphere->GetComponentLocation();
    	float ScaleFactorH = DistanceToSphere.Size() / 100.0f;
    	ConnectorH->SetWorldScale3D(FVector(1, 1, ScaleFactorH));
    
    	ConnectorH->SetWorldRotation(FRotationMatrix::MakeFromZ(DistanceToSphere).Rotator());
    
    }
    
    // TODO Material highlighting - swap material slots?
    void ASelectableActorBase::OnOverlapBegin(UPrimitiveComponent * OverlapComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
    {
    	//int32 N = OverlapComponent->GetNumMaterials();
    	//for (int32 i = 0; i < N; i++)
    	//{
    	//	Cast<UMaterialInstanceDynamic>(OverlapComponent->GetMaterial(i))->SetVectorParameterValue("Color", FLinearColor(0.5, 0.5, 0.8));
    	//}
    }
    
    void ASelectableActorBase::OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
    {
    	//int32 N = OverlappedComp->GetNumMaterials();
    	//for (int32 i = 0; i < N; i++)
    	//{
    	//	Cast<UMaterialInstanceDynamic>(OverlappedComp->GetMaterial(i))->SetVectorParameterValue("Color", FLinearColor(0.4, 0.4, 0.4));
    	//}
    }