VRTowerDef/Plugins/MetaXR/Source/OculusXRAnchors/Private/OculusXRAnchorBPFunctionLib...

226 lines
8.9 KiB
C++

// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRHMD.h"
#include "OculusXRSpatialAnchorComponent.h"
#include "OculusXRAnchorsPrivate.h"
#include "OculusXRRoomLayoutManager.h"
#include "OculusXRAnchorManager.h"
#include "Kismet/BlueprintFunctionLibrary.h"
AActor* UOculusXRAnchorBPFunctionLibrary::SpawnActorWithAnchorHandle(UObject* WorldContextObject, FOculusXRUInt64 Handle, FOculusXRUUID UUID, EOculusXRSpaceStorageLocation Location, UClass* ActorClass,
AActor* Owner, APawn* Instigator, ESpawnActorCollisionHandlingMethod CollisionHandlingMethod)
{
FActorSpawnParameters SpawnInfo;
SpawnInfo.Owner = Owner;
SpawnInfo.Instigator = Instigator;
SpawnInfo.ObjectFlags |= RF_Transient;
SpawnInfo.SpawnCollisionHandlingOverride = CollisionHandlingMethod;
UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
if (World == nullptr)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid WorldContext Object for SpawnActorWithAnchorHandle."));
return nullptr;
}
AActor* NewSpatialAnchorActor = World->SpawnActor(ActorClass, nullptr, nullptr, SpawnInfo);
if (NewSpatialAnchorActor == nullptr)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to spawn Actor in SpawnActorWithAnchorHandle"));
return nullptr;
}
UOculusXRSpatialAnchorComponent* SpatialAnchorComponent = NewSpatialAnchorActor->FindComponentByClass<UOculusXRSpatialAnchorComponent>();
if (SpatialAnchorComponent == nullptr)
{
SpatialAnchorComponent = Cast<UOculusXRSpatialAnchorComponent>(NewSpatialAnchorActor->AddComponentByClass(UOculusXRSpatialAnchorComponent::StaticClass(), false, FTransform::Identity, false));
}
if (!IsValid(SpatialAnchorComponent))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to find or spawn Spatial Anchor component in SpawnActorWithAnchorHandle"));
return nullptr;
}
SpatialAnchorComponent->SetHandle(Handle);
SpatialAnchorComponent->SetUUID(UUID);
SpatialAnchorComponent->SetStoredLocation(Location, true);
return NewSpatialAnchorActor;
}
AActor* UOculusXRAnchorBPFunctionLibrary::SpawnActorWithAnchorQueryResults(UObject* WorldContextObject, const FOculusXRSpaceQueryResult& QueryResult, UClass* ActorClass, AActor* Owner, APawn* Instigator, ESpawnActorCollisionHandlingMethod CollisionHandlingMethod)
{
return SpawnActorWithAnchorHandle(WorldContextObject, QueryResult.Space, QueryResult.UUID, QueryResult.Location, ActorClass, Owner, Instigator, CollisionHandlingMethod);
}
bool UOculusXRAnchorBPFunctionLibrary::GetAnchorComponentStatus(AActor* TargetActor, EOculusXRSpaceComponentType ComponentType, bool& bIsEnabled)
{
UOculusXRAnchorComponent* AnchorComponent = Cast<UOculusXRAnchorComponent>(TargetActor->GetComponentByClass(UOculusXRAnchorComponent::StaticClass()));
if (!IsValid(AnchorComponent))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid Anchor Component provided to GetAnchorComponentStatus"));
bIsEnabled = false;
return false;
}
bool bOutIsEnabled = false;
bool bIsChangePending = false;
EOculusXRAnchorResult::Type AnchorResult;
bool bDidCallStart = OculusXRAnchors::FOculusXRAnchors::GetAnchorComponentStatus(AnchorComponent, ComponentType, bOutIsEnabled, bIsChangePending, AnchorResult);
if (!bDidCallStart)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start call to internal GetAnchorComponentStatus"));
bIsEnabled = false;
return false;
}
bIsEnabled = bOutIsEnabled;
return bIsEnabled;
}
bool UOculusXRAnchorBPFunctionLibrary::GetAnchorTransformByHandle(const FOculusXRUInt64& Handle, FTransform& OutTransform)
{
FOculusXRAnchorLocationFlags AnchorFlags(0);
return TryGetAnchorTransformByHandle(Handle, OutTransform, AnchorFlags);
}
bool UOculusXRAnchorBPFunctionLibrary::TryGetAnchorTransformByHandle(const FOculusXRUInt64& Handle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags)
{
OculusXRHMD::FOculusXRHMD* OutHMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
if (!OutHMD)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve OculusXRHMD, cannot calculate anchor transform."));
return false;
}
ovrpTrackingOrigin ovrpOrigin = ovrpTrackingOrigin_EyeLevel;
const bool bTrackingOriginSuccess = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetTrackingOriginType2(&ovrpOrigin));
if (!bTrackingOriginSuccess)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to get tracking origin, cannot calculate anchor transform."));
return false;
}
OutTransform = FTransform::Identity;
OutLocationFlags = FOculusXRAnchorLocationFlags(0);
const ovrpUInt64 ovrpSpace = Handle.GetValue();
ovrpSpaceLocationf ovrpSpaceLocation;
const bool bSuccess = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().LocateSpace2(&ovrpSpaceLocation, &ovrpSpace, ovrpOrigin));
if (bSuccess)
{
OutLocationFlags = FOculusXRAnchorLocationFlags(ovrpSpaceLocation.locationFlags);
if (OutLocationFlags.IsValid())
{
OculusXRHMD::FPose Pose;
OutHMD->ConvertPose(ovrpSpaceLocation.pose, Pose);
const FTransform trackingToWorld = OutHMD->GetLastTrackingToWorld();
OutTransform.SetLocation(trackingToWorld.TransformPosition(Pose.Position));
OutTransform.SetRotation(FRotator(trackingToWorld.TransformRotation(FQuat(Pose.Orientation))).Quaternion());
}
else
{
return false;
}
}
return bSuccess;
}
FString UOculusXRAnchorBPFunctionLibrary::AnchorHandleToString(const FOculusXRUInt64 Value)
{
return FString::Printf(TEXT("%llu"), Value.Value);
}
FString UOculusXRAnchorBPFunctionLibrary::AnchorUUIDToString(const FOculusXRUUID& Value)
{
return Value.ToString();
}
FOculusXRUUID UOculusXRAnchorBPFunctionLibrary::StringToAnchorUUID(const FString& Value)
{
// Static size for the max length of the string, two chars per hex digit, 16 digits.
checkf(Value.Len() == 32, TEXT("'%s' is not a valid UUID"), *Value);
ovrpUuid newID;
HexToBytes(Value, newID.data);
return FOculusXRUUID(newID.data);
}
bool UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(EOculusXRAnchorResult::Type result)
{
#if OCULUS_HMD_SUPPORTED_PLATFORMS
return OVRP_SUCCESS(result);
#endif
return false;
}
const UOculusXRBaseAnchorComponent* UOculusXRAnchorBPFunctionLibrary::GetAnchorComponent(const FOculusXRSpaceQueryResult& QueryResult, EOculusXRSpaceComponentType ComponentType, UObject* Outer)
{
switch (ComponentType)
{
case EOculusXRSpaceComponentType::Locatable:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRLocatableAnchorComponent>(QueryResult.Space.Value, Outer);
case EOculusXRSpaceComponentType::ScenePlane:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRPlaneAnchorComponent>(QueryResult.Space.Value, Outer);
case EOculusXRSpaceComponentType::SceneVolume:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRVolumeAnchorComponent>(QueryResult.Space.Value, Outer);
case EOculusXRSpaceComponentType::SemanticClassification:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRSemanticClassificationAnchorComponent>(QueryResult.Space.Value, Outer);
case EOculusXRSpaceComponentType::RoomLayout:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRRoomLayoutAnchorComponent>(QueryResult.Space.Value, Outer);
case EOculusXRSpaceComponentType::SpaceContainer:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRSpaceContainerAnchorComponent>(QueryResult.Space.Value, Outer);
case EOculusXRSpaceComponentType::Sharable:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRSharableAnchorComponent>(QueryResult.Space.Value, Outer);
case EOculusXRSpaceComponentType::Storable:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRStorableAnchorComponent>(QueryResult.Space.Value, Outer);
case EOculusXRSpaceComponentType::TriangleMesh:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRTriangleMeshAnchorComponent>(QueryResult.Space.Value, Outer);
default:
return nullptr;
}
}
bool UOculusXRAnchorBPFunctionLibrary::GetRoomLayout(FOculusXRUInt64 Space, FOculusXRRoomLayout& RoomLayoutOut, int32 MaxWallsCapacity)
{
if (MaxWallsCapacity <= 0)
{
return false;
}
FOculusXRUUID OutCeilingUuid;
FOculusXRUUID OutFloorUuid;
TArray<FOculusXRUUID> OutWallsUuid;
const bool bSuccess = OculusXRAnchors::FOculusXRRoomLayoutManager::GetSpaceRoomLayout(Space.Value, static_cast<uint32>(MaxWallsCapacity), OutCeilingUuid, OutFloorUuid, OutWallsUuid);
if (bSuccess)
{
RoomLayoutOut.CeilingUuid = OutCeilingUuid;
RoomLayoutOut.FloorUuid = OutFloorUuid;
RoomLayoutOut.WallsUuid.InsertZeroed(0, OutWallsUuid.Num());
for (int32 i = 0; i < OutWallsUuid.Num(); ++i)
{
RoomLayoutOut.WallsUuid[i] = OutWallsUuid[i];
}
TArray<FOculusXRUUID> spaceUUIDs;
EOculusXRAnchorResult::Type result = OculusXRAnchors::FOculusXRAnchorManager::GetSpaceContainerUUIDs(Space, spaceUUIDs);
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(result))
{
RoomLayoutOut.RoomObjectUUIDs = spaceUUIDs;
}
}
return bSuccess;
}