Skip to content
Snippets Groups Projects
Commit 75cc2e0b authored by David Gilbert's avatar David Gilbert :bug:
Browse files

Remove Calibratio from the toolkit, it will be a new reworked Plugin

parent 8201540f
No related branches found
No related tags found
1 merge request!35Remove Calibratio from the toolkit, it will be a new reworked Plugin
......@@ -15,15 +15,6 @@
"Installed": false,
"EnabledByDefault": true,
"Modules": [
{
"Name": "Calibratio",
"Type": "Runtime",
"LoadingPhase": "Default",
"WhitelistPlatforms": [
"Win64",
"Linux"
]
},
{
"Name": "RWTHVRCluster",
"Type": "Runtime",
......
using UnrealBuildTool;
public class Calibratio : ModuleRules
{
public Calibratio(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[]{}
);
PrivateIncludePaths.AddRange(
new string[]{}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core", "CoreUObject", "Engine", "UMG", "SlateCore", "DisplayCluster", "RWTHVRToolkit"
}
);
PrivateDependencyModuleNames.AddRange(
new string[]{}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]{}
);
}
}
#include "Calibratio.h"
#include "Kismet/GameplayStatics.h"
#include "IDisplayCluster.h"
#include "Cluster/DisplayClusterClusterEvent.h"
#include "Utility/VirtualRealityUtilities.h"
#define LOCTEXT_NAMESPACE "FCalibratioModule"
void FCalibratioModule::StartupModule ()
{
/* Registering console command */
CalibratioConsoleCommand = IConsoleManager::Get().RegisterConsoleCommand(TEXT("Calibratio"), TEXT("Spawn an instance of calibratio"),
FConsoleCommandWithArgsDelegate::CreateLambda([](const TArray< FString >&)
{
if(UVirtualRealityUtilities::IsRoomMountedMode()){
/* Emitting cluster event to spawn on all nodes in sync*/
FDisplayClusterClusterEventJson ClusterEvent;
ClusterEvent.Name = "CalibratioSpawn";
ClusterEvent.Category = "CalibratioSpawner";
IDisplayCluster::Get().GetClusterMgr()->EmitClusterEventJson(ClusterEvent, false);
} else {
SpawnCalibratio();
}
}));
/* Register cluster event listening */
IDisplayCluster* DisplayCluster = FModuleManager::LoadModulePtr<IDisplayCluster>(IDisplayCluster::ModuleName);
if (DisplayCluster && !ClusterEventListenerDelegate.IsBound())
{
ClusterEventListenerDelegate = FOnClusterEventJsonListener::CreateLambda([](const FDisplayClusterClusterEventJson& Event)
{
if (Event.Category.Equals("CalibratioSpawner") && Event.Name.Equals("CalibratioSpawn"))
{
SpawnCalibratio();
}
});
DisplayCluster->GetClusterMgr()->AddClusterEventJsonListener(ClusterEventListenerDelegate);
}
}
void FCalibratioModule::ShutdownModule()
{
IConsoleManager::Get().UnregisterConsoleObject(CalibratioConsoleCommand);
IDisplayCluster::Get().GetClusterMgr()->RemoveClusterEventJsonListener(ClusterEventListenerDelegate);
}
void FCalibratioModule::SpawnCalibratio()
{
if (UGameplayStatics::GetActorOfClass(GEngine->GetCurrentPlayWorld(), ACalibratioActor::StaticClass()) != nullptr) return;
GEngine->GetCurrentPlayWorld()->SpawnActor<ACalibratioActor>();
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FCalibratioModule, Calibratio)
\ No newline at end of file
#include "CalibratioActor.h"
#include "Components/StaticMeshComponent.h"
#include "Cluster/DisplayClusterClusterEvent.h"
#include "IDisplayCluster.h"
#include "TimerManager.h"
#include "CalibratioOverlay.h"
#include "GameFramework/InputSettings.h"
#include "Utility/VirtualRealityUtilities.h"
ACalibratioActor::ACalibratioActor()
{
PrimaryActorTick.bCanEverTick = true;
AutoReceiveInput = EAutoReceiveInput::Player0;
/* Loads needed Assets */
UStaticMesh* CylinderMesh = nullptr;
UVirtualRealityUtilities::LoadClass("WidgetBlueprint'/RWTHVRToolkit/Calibratio/CalibratioHud'", Overlay_Class);
UVirtualRealityUtilities::LoadAsset("StaticMesh'/RWTHVRToolkit/Calibratio/Cylinder'", CylinderMesh);
UVirtualRealityUtilities::LoadAsset("Material'/RWTHVRToolkit/Calibratio/CalibratioMaterial'", BaseMaterial);
/* Create Mesh component and initialize */
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
Mesh->SetupAttachment(RootComponent);
Mesh->SetStaticMesh(CylinderMesh);
Mesh->SetRelativeScale3D(FVector(1,1,0.1f)); //Make it a Disk
RootComponent = Mesh;
}
// Called when the game starts or when spawned
void ACalibratioActor::BeginPlay()
{
Super::BeginPlay();
/* Register cluster event listener */
IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
if (ClusterManager && !ClusterEventListenerDelegate.IsBound())
{
ClusterEventListenerDelegate = FOnClusterEventJsonListener::CreateUObject(this, &ACalibratioActor::HandleClusterEvent);
ClusterManager->AddClusterEventJsonListener(ClusterEventListenerDelegate);
}
/* Create Overlay */
Overlay = CreateWidget<UCalibratioOverlay>(GetWorld()->GetFirstPlayerController(), Overlay_Class);
Overlay->AddToViewport(0);
Overlay->SetThresholds(MinRotation, MaxRotation, Threshold);
Overlay->SetOwner(this);
/* Bind Buttons */
Overlay->ResettingButton->OnClicked.AddDynamic(this, &ACalibratioActor::ClusterReset);
Overlay->IncreaseThresholdButton->OnClicked.AddDynamic(this, &ACalibratioActor::ClusterIncreaseThreshold);
Overlay->DecreaseThresholdButton->OnClicked.AddDynamic(this, &ACalibratioActor::ClusterDecreaseThreshold);
/* Hide this overlay on all clients */
if (UVirtualRealityUtilities::IsSlave())
{
Overlay->SetVisibility(ESlateVisibility::Hidden);
}
}
void ACalibratioActor::PostInitializeComponents()
{
Super::PostInitializeComponents();
/* Create dynamic materials at runtime (Not constructor) */
DynamicMaterial = UMaterialInstanceDynamic::Create(BaseMaterial, RootComponent);
DynamicMaterial->SetVectorParameterValue("Color", FColor::Red);
Mesh->SetMaterial(0, DynamicMaterial);
}
void ACalibratioActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
/* Remove from Cluster events */
IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
if (ClusterManager && ClusterEventListenerDelegate.IsBound())
{
ClusterManager->RemoveClusterEventJsonListener(ClusterEventListenerDelegate);
}
Super::EndPlay(EndPlayReason);
/* Remove components */
GetWorld()->GetTimerManager().ClearTimer(ResetTimerHandle);
if(Overlay->IsInViewport()) Overlay->RemoveFromViewport();
}
void ACalibratioActor::HandleClusterEvent(const FDisplayClusterClusterEventJson& Event)
{
if(!Event.Category.Equals("Calibratio")) return; //Not our Business
if (Event.Name == "CalibratioReset")
{
LocalReset();
}
else if (Event.Name == "CalibratioSetThreshold" && Event.Parameters.Contains("NewThreshold"))
{
LocalSetThreshold(FCString::Atof(*Event.Parameters["NewThreshold"]));
}
else if (Event.Name == "CalibratioArmAndSetCalibration" && Event.Parameters.Contains("NewMin") && Event.Parameters.Contains("NewMax"))
{
LocalArmAndSetCalibration(FCString::Atof(*Event.Parameters["NewMin"]), FCString::Atof(*Event.Parameters["NewMax"]));
}
else if (Event.Name == "CalibratioDespawn")
{
LocalDespawn();
}
}
void ACalibratioActor::ClusterReset()
{
if(UVirtualRealityUtilities::IsRoomMountedMode())
{
IDisplayClusterClusterManager* const Manager = IDisplayCluster::Get().GetClusterMgr();
if (!Manager) return;
FDisplayClusterClusterEventJson ClusterEvent;
ClusterEvent.Name = "CalibratioReset";
ClusterEvent.Category = "Calibratio";
Manager->EmitClusterEventJson(ClusterEvent, true);
}
else if(UVirtualRealityUtilities::IsDesktopMode())
{
LocalReset();
}
}
void ACalibratioActor::LocalReset()
{
DynamicMaterial->SetVectorParameterValue("Color", FColor::Red);
CurrentCalibrationRuns = 0;
MaxRotation = -FLT_MAX;
MinRotation = FLT_MAX;
LastRotations.Empty();
LastRotations.Reserve(MaxCalibrationRuns);
}
void ACalibratioActor::ClusterIncreaseThreshold()
{
ClusterChangeThreshold(FMath::DegreesToRadians(0.1f));
}
void ACalibratioActor::ClusterDecreaseThreshold()
{
ClusterChangeThreshold(-FMath::DegreesToRadians(0.1f));
}
void ACalibratioActor::ClusterChangeThreshold(float Value)
{
const float NewThreshold = Threshold + Value;
if(UVirtualRealityUtilities::IsRoomMountedMode())
{
IDisplayClusterClusterManager* const Manager = IDisplayCluster::Get().GetClusterMgr();
if (!Manager) return;
FDisplayClusterClusterEventJson ClusterEvent;
ClusterEvent.Name = "CalibratioSetThreshold";
ClusterEvent.Category = "Calibratio";
ClusterEvent.Parameters.Add("NewThreshold",FString::SanitizeFloat(NewThreshold));
Manager->EmitClusterEventJson(ClusterEvent, true);
}
else if(UVirtualRealityUtilities::IsDesktopMode())
{
LocalSetThreshold(NewThreshold);
}
}
void ACalibratioActor::LocalSetThreshold(float NewValue)
{
Threshold = NewValue;
Overlay->SetThresholds(MinRotation, MaxRotation, Threshold);
}
void ACalibratioActor::ClusterArmAndSetCalibration(float MinAngle, float MaxAngle)
{
if(UVirtualRealityUtilities::IsRoomMountedMode())
{
IDisplayClusterClusterManager* const Manager = IDisplayCluster::Get().GetClusterMgr();
if (!Manager) return;
FDisplayClusterClusterEventJson ClusterEvent;
ClusterEvent.Name = "CalibratioArmAndSetCalibration";
ClusterEvent.Category = "Calibratio";
ClusterEvent.Parameters.Add("NewMin",FString::SanitizeFloat(MinAngle));
ClusterEvent.Parameters.Add("NewMax",FString::SanitizeFloat(MaxAngle));
Manager->EmitClusterEventJson(ClusterEvent, true);
}
else if(UVirtualRealityUtilities::IsDesktopMode())
{
LocalArmAndSetCalibration(MinAngle, MaxAngle);
}
}
void ACalibratioActor::LocalArmAndSetCalibration(float NewMin, float NewMax)
{
MinRotation = NewMin;
MaxRotation = NewMax;
Overlay->SetStatus(Waiting);
DynamicMaterial->SetVectorParameterValue("Color", FColor::Black);
CurrentCalibrationRuns = MaxCalibrationRuns + 1; //Arm
}
void ACalibratioActor::ClusterDespawn()
{
if (UVirtualRealityUtilities::IsRoomMountedMode())
{
IDisplayClusterClusterManager* const Manager = IDisplayCluster::Get().GetClusterMgr();
if (!Manager) return;
FDisplayClusterClusterEventJson ClusterEvent;
ClusterEvent.Name = "CalibratioDespawn";
ClusterEvent.Category = "Calibratio";
Manager->EmitClusterEventJson(ClusterEvent, true);
}
else if (UVirtualRealityUtilities::IsDesktopMode())
{
LocalDespawn();
}
}
void ACalibratioActor::LocalDespawn()
{
GetWorld()->DestroyActor(this); // Destroy ourself
}
void ACalibratioActor::Tick(const float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
/* Search for tracker */
if(!TrackedClusterComponent)
{
TrackedClusterComponent = UVirtualRealityUtilities::GetNamedClusterComponent(ENamedClusterComponent::NCC_CALIBRATIO);
} else
{
const FVector NewPos = TrackedClusterComponent->GetComponentLocation();
if(NewPos != LastVisiblePosition)
{
if(FirstPositionSet) LastTimeVisible = FDateTime::Now();
LastVisiblePosition = NewPos;
FirstPositionSet = true;
}
}
if (!IsTrackerCurrentlyVisible() || !TrackedClusterComponent)
{
Overlay->SetPhysicalStatus(NotFound);
Overlay->SetStatus(Waiting);
return;
}
/* Tracker is visible */
const float Rotation = TrackedClusterComponent->GetRelativeRotation().Yaw;
/* First run, place mesh */
if (CurrentCalibrationRuns == 0)
{
Mesh->SetRelativeLocation(TrackedClusterComponent->GetRelativeLocation());
}
/* More calibration runs to go */
if (CurrentCalibrationRuns < MaxCalibrationRuns)
{
Overlay->SetStatus(Calibrating);
if (IsDeviceMoving(Rotation))
{
Overlay->SetPhysicalStatus(Moving);
LocalReset();
}
else
{
Overlay->SetPhysicalStatus(Found);
CalibrationRun(Rotation);
}
}
/* Calibration finished */
else if (CurrentCalibrationRuns == MaxCalibrationRuns)
{
ClusterArmAndSetCalibration(MinRotation, MaxRotation); /* Sync to other nodes */
}
/* Actual Measuring */
else if (Rotation < MinRotation - Threshold || Rotation > MaxRotation + Threshold)
{
if (!GetWorld()->GetTimerManager().IsTimerActive(ResetTimerHandle))
{
DynamicMaterial->SetVectorParameterValue("Color", FColor::White);
Overlay->SetStatus(Triggered);
GetWorld()->GetTimerManager().SetTimer(ResetTimerHandle, this, &ACalibratioActor::ClusterReset, ResetTime, false);
}
}
}
/* Checks if last 10 calls to this function handed in roughly the same Angle */
bool ACalibratioActor::IsDeviceMoving(float Angle)
{
LastRotations.Add(Angle); /* Push into back */
if (LastRotations.Num() > 10) LastRotations.RemoveAt(0); /* Remove first one */
float Sum = 0.0f;
for (float& CurrentAngle : LastRotations)
{
Sum += CurrentAngle;
}
const float Average = Sum / LastRotations.Num();
return FMath::Abs(Average - Angle) > 5 * Threshold && LastRotations.Num() >= 10;
}
/* Adjusts min and max rotation values */
void ACalibratioActor::CalibrationRun(float Angle)
{
if(!UVirtualRealityUtilities::IsMaster()) return; //Not our Business
MinRotation = FMath::Min(MinRotation, Angle);
MaxRotation = FMath::Max(MaxRotation, Angle);
Overlay->SetThresholds(MinRotation, MaxRotation, Threshold);
CurrentCalibrationRuns++;
}
bool ACalibratioActor::IsTrackerCurrentlyVisible()
{
return (FDateTime::Now() - LastTimeVisible).GetTotalMilliseconds() <= AcceptedAbscenceTime;
}
#include "CalibratioOverlay.h"
bool UCalibratioOverlay::Initialize()
{
const bool Result = Super::Initialize();
DismissButton->OnClicked.AddDynamic(this, &UCalibratioOverlay::Dismiss);
return Result;
}
void UCalibratioOverlay::SetStatus(const ECalibratioProtocolStatus Status)
{
if(CurrentStatus == Status) return;
switch(Status)
{
case Calibrating:
StatusProtocol->SetText(FText::FromString(TEXT("Calibrating")));
break;
case Waiting:
StatusProtocol->SetText(FText::FromString(TEXT("Waiting")));
break;
case Triggered:
StatusProtocol->SetText(FText::FromString(TEXT("Triggered")));
break;
}
CurrentStatus = Status;
}
void UCalibratioOverlay::SetThresholds(const float Min, const float Max, const float Threshold)
{
MinAngle->SetText(FText::FromString(FString::Printf(TEXT("%.2f\u00B0"), FMath::Fmod(FMath::RadiansToDegrees(Min), 360))));
MaxAngle->SetText(FText::FromString(FString::Printf(TEXT("%.2f\u00B0"), FMath::Fmod(FMath::RadiansToDegrees(Max), 360))));
CurrentThreshold->SetText(FText::FromString(FString::Printf(TEXT("+-%.2f\u00B0s"), FMath::Fmod(FMath::RadiansToDegrees(Threshold), 360))));
}
void UCalibratioOverlay::SetPhysicalStatus(const ECalibratioPhysicalStatus Status)
{
if(CurrentPhysicalStatus == Status) return;
switch(Status)
{
case Found:
StatusCalibratio->SetText(FText::FromString(TEXT("Found")));
StatusCalibratio->SetColorAndOpacity(FSlateColor(FLinearColor::Green));
break;
case Unknown:
case NotFound:
StatusCalibratio->SetText(FText::FromString(TEXT("Not Found")));
StatusCalibratio->SetColorAndOpacity(FSlateColor(FLinearColor::Red));
break;
case Moving:
StatusCalibratio->SetText(FText::FromString(TEXT("Moving")));
StatusCalibratio->SetColorAndOpacity(FSlateColor(FLinearColor::Yellow));
break;
}
CurrentPhysicalStatus = Status;
}
void UCalibratioOverlay::Dismiss()
{
Owner->ClusterDespawn();
}
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
#include "CalibratioActor.h"
#include "Cluster/IDisplayClusterClusterManager.h"
class FCalibratioModule : public IModuleInterface
{
public:
virtual void StartupModule () override;
virtual void ShutdownModule() override;
public:
static void SpawnCalibratio();
private:
IConsoleCommand* CalibratioConsoleCommand = nullptr;
FOnClusterEventJsonListener ClusterEventListenerDelegate;
};
#pragma once
#include "CoreMinimal.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "Cluster/IDisplayClusterClusterManager.h"
#include "GameFramework/Actor.h"
#include "CalibratioActor.generated.h"
UCLASS()
class CALIBRATIO_API ACalibratioActor : public AActor
{
GENERATED_BODY()
public:
ACalibratioActor();
protected:
virtual void BeginPlay() override;
virtual void PostInitializeComponents() override;
virtual void Tick(float DeltaSeconds) override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
public:
UPROPERTY(VisibleAnywhere) UStaticMeshComponent* Mesh;
UPROPERTY(EditAnywhere) UMaterialInterface* BaseMaterial;
UPROPERTY(BlueprintReadWrite) float Threshold = FMath::DegreesToRadians(1.7f);
UPROPERTY(BlueprintReadWrite) float ResetTime = 1.5f;
UFUNCTION(Blueprintcallable) void ClusterDespawn();
private:
DECLARE_DELEGATE_OneParam(FThresholdDelegate, float);
FOnClusterEventJsonListener ClusterEventListenerDelegate;
void CalibrationRun(float Angle);
bool IsTrackerCurrentlyVisible();
void LocalSetThreshold(float NewValue);
void LocalArmAndSetCalibration(float NewMin, float NewMax);
void LocalDespawn();
bool IsDeviceMoving(float Angle);
void LocalReset();
// Handling Cluster events
UFUNCTION() void ClusterReset();
UFUNCTION() void ClusterIncreaseThreshold();
UFUNCTION() void ClusterDecreaseThreshold();
void ClusterChangeThreshold(float Value);
void ClusterArmAndSetCalibration(float MinAngle, float MaxAngle);
void HandleClusterEvent(const FDisplayClusterClusterEventJson& Event);
float MinRotation{0};
float MaxRotation{0};
int CurrentCalibrationRuns{0};
int MaxCalibrationRuns{60};
FTimerHandle ResetTimerHandle;
TArray<float> LastRotations;
UPROPERTY() UMaterialInstanceDynamic* DynamicMaterial = nullptr;
FDateTime LastTimeVisible = FDateTime::MinValue();
FVector LastVisiblePosition = FVector(NAN, NAN, NAN);
bool FirstPositionSet = false;
uint32 AcceptedAbscenceTime = 500u; // in Milliseconds
UPROPERTY() USceneComponent* TrackedClusterComponent = nullptr;
//Overlay
TSubclassOf<class UCalibratioOverlay> Overlay_Class;
UPROPERTY() UCalibratioOverlay* Overlay;
};
#pragma once
#include "CoreMinimal.h"
#include "CalibratioActor.h"
#include "Blueprint/UserWidget.h"
#include "Components/TextBlock.h"
#include "Components/Button.h"
#include "CalibratioOverlay.generated.h"
UENUM(BlueprintType)
enum ECalibratioProtocolStatus
{
Calibrating,
Waiting,
Triggered
};
UENUM(BlueprintType)
enum ECalibratioPhysicalStatus
{
Moving,
Found,
NotFound,
Unknown
};
/**
* This is the parent class for the Overlay that is used on the master.
* All declarations in it are magically bound to the UMG child class if they are named the same (see "meta = (BindWidget)")
*/
UCLASS()
class CALIBRATIO_API UCalibratioOverlay : public UUserWidget
{
GENERATED_BODY()
virtual bool Initialize() override;
public:
/* Public Buttons */
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UButton* ResettingButton;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UButton* IncreaseThresholdButton;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UButton* DecreaseThresholdButton;
protected:
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UButton* DismissButton;
/* Numbers: */
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UTextBlock* CurrentThreshold;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UTextBlock* MinAngle;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UTextBlock* MaxAngle;
/* Status: */
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UTextBlock* StatusProtocol;
UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UTextBlock* StatusCalibratio;
public:
UFUNCTION() void SetStatus(ECalibratioProtocolStatus Status);
UFUNCTION() void SetThresholds(float Min, float Max, float Threshold);
UFUNCTION() void SetPhysicalStatus(ECalibratioPhysicalStatus Status);
void SetOwner(ACalibratioActor* InOwner) {Owner = InOwner;}
UFUNCTION() void Dismiss();
private:
ECalibratioPhysicalStatus CurrentPhysicalStatus = Unknown;
ECalibratioProtocolStatus CurrentStatus = Calibrating;
UPROPERTY() ACalibratioActor* Owner;
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment