Android build settings + metaxr

This commit is contained in:
2025-05-14 14:00:02 +03:00
parent 6a2bb7475e
commit d5aa21f55c
594 changed files with 200530 additions and 2 deletions

View File

@@ -0,0 +1,48 @@
// @lint-ignore-every LICENSELINT
// Copyright Epic Games, Inc. All Rights Reserved.
namespace UnrealBuildTool.Rules
{
public class OculusXRAnchors : ModuleRules
{
public OculusXRAnchors(ReadOnlyTargetRules Target) : base(Target)
{
bUseUnity = false;
PrivateDependencyModuleNames.AddRange(
new string[]
{
"Core",
"CoreUObject",
"Engine",
"HeadMountedDisplay",
"OculusXRHMD",
"OVRPluginXR",
"XRBase",
"OpenXR",
"OpenXRHMD",
"ProceduralMeshComponent",
});
PublicDependencyModuleNames.AddRange(
new string[]
{
"OculusXRAsyncRequest",
"KhronosOpenXRHeaders",
});
PrivateIncludePaths.AddRange(
new string[] {
// Relative to Engine\Plugins\Runtime\Oculus\OculusVR\Source
"OculusXRHMD/Private",
});
PublicIncludePaths.AddRange(
new string[] {
"Runtime/Engine/Classes/Components",
});
AddEngineThirdPartyPrivateStaticDependencies(Target, "OpenXR");
}
}
}

View File

@@ -0,0 +1,131 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "Engine/GameEngine.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRHMD.h"
#include "OculusXRSpatialAnchorComponent.h"
#include "OculusXRAnchorsPrivate.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, EOculusXRAnchorSpace Space)
{
auto result = OculusXRAnchors::FOculusXRAnchorManager::TryGetAnchorTransform(Handle, OutTransform, OutLocationFlags, Space);
return IsAnchorResultSuccess(result);
}
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);
#else
return false;
#endif
}
const UOculusXRBaseAnchorComponent* UOculusXRAnchorBPFunctionLibrary::GetAnchorComponent(const FOculusXRSpaceQueryResult& QueryResult, EOculusXRSpaceComponentType ComponentType, UObject* Outer)
{
auto& anchorsModule = FModuleManager::GetModuleChecked<IOculusXRAnchorsModule>("OculusXRAnchors");
return anchorsModule.CreateAnchorComponent(QueryResult.Space.Value, ComponentType, Outer);
}

View File

@@ -0,0 +1,209 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorComponent.h"
#include "OculusXRAnchors.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRHMD.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRAnchorsPrivate.h"
#include "GameFramework/PlayerController.h"
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
static TAutoConsoleVariable<int32> CVarOculusXRVerboseAnchorDebugXR(
TEXT("ovr.OculusXRVerboseAnchorDebug"),
0,
TEXT("Enables or disables verbose logging for Oculus anchors.\n")
TEXT("<=0: disabled (no printing)\n")
TEXT(" 1: enabled (verbose logging)\n"));
#endif
UOculusXRAnchorComponent::UOculusXRAnchorComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
, bUpdateHeadSpaceTransform(true)
, AnchorHandle(0)
, StorageLocations(0)
{
AnchorHandle = 0;
PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = true;
PrimaryComponentTick.TickGroup = TG_PostUpdateWork;
}
void UOculusXRAnchorComponent::BeginPlay()
{
Super::BeginPlay();
UWorld* World = GetWorld();
if (IsValid(World))
{
APlayerController* PlayerController = World->GetFirstPlayerController();
if (IsValid(PlayerController))
{
PlayerCameraManager = PlayerController->PlayerCameraManager;
}
}
}
void UOculusXRAnchorComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
UpdateAnchorTransform();
}
void UOculusXRAnchorComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
if (HasValidHandle())
{
EOculusXRAnchorResult::Type AnchorResult;
OculusXRAnchors::FOculusXRAnchors::DestroyAnchor(AnchorHandle.GetValue(), AnchorResult);
}
}
FOculusXRUInt64 UOculusXRAnchorComponent::GetHandle() const
{
return AnchorHandle;
}
void UOculusXRAnchorComponent::SetHandle(FOculusXRUInt64 Handle)
{
AnchorHandle = Handle;
}
bool UOculusXRAnchorComponent::HasValidHandle() const
{
return AnchorHandle != FOculusXRUInt64(0);
}
FOculusXRUUID UOculusXRAnchorComponent::GetUUID() const
{
return AnchorUUID;
}
void UOculusXRAnchorComponent::SetUUID(FOculusXRUUID NewUUID)
{
if (AnchorUUID.IsValidUUID())
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Anchor component already has valid UUID, cannot re-assign a new UUID. Component: %s -- Space: %llu -- UUID: %s"),
*GetName(), AnchorHandle.GetValue(), *AnchorUUID.ToString());
return;
}
if (!NewUUID.IsValidUUID())
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("New UUID provided to component is invalid, cannot assign. Component: %s -- Space: %llu"), *GetName(), AnchorHandle.GetValue());
return;
}
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Assigned new Oculus UUID: %s"), *NewUUID.ToString());
AnchorUUID = NewUUID;
}
bool UOculusXRAnchorComponent::IsStoredAtLocation(EOculusXRSpaceStorageLocation Location) const
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Anchor UUID: %s - Saved Local: %d - Saved Cloud: %d"),
*GetUUID().ToString(),
StorageLocations & static_cast<int32>(EOculusXRSpaceStorageLocation::Local),
StorageLocations & static_cast<int32>(EOculusXRSpaceStorageLocation::Cloud));
return (StorageLocations & static_cast<int32>(Location)) > 0;
}
void UOculusXRAnchorComponent::SetStoredLocation(EOculusXRSpaceStorageLocation Location, bool Stored)
{
if (Stored)
{
StorageLocations |= static_cast<int32>(Location);
}
else
{
StorageLocations = StorageLocations & ~static_cast<int32>(Location);
}
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Anchor UUID: %s - Saved Local: %d - Saved Cloud: %d"),
*GetUUID().ToString(),
StorageLocations & static_cast<int32>(EOculusXRSpaceStorageLocation::Local),
StorageLocations & static_cast<int32>(EOculusXRSpaceStorageLocation::Cloud));
}
bool UOculusXRAnchorComponent::IsSaved() const
{
return StorageLocations > 0;
}
void UOculusXRAnchorComponent::UpdateAnchorTransform() const
{
if (GetWorld() == nullptr)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve World Context"));
return;
}
AActor* Parent = GetOwner();
if (Parent)
{
if (AnchorHandle.Value)
{
FTransform OutTransform;
if (UOculusXRAnchorBPFunctionLibrary::GetAnchorTransformByHandle(AnchorHandle, OutTransform))
{
#if WITH_EDITOR
// Link only head-space transform update
if (bUpdateHeadSpaceTransform && PlayerCameraManager != nullptr)
{
FTransform MainCameraTransform;
MainCameraTransform.SetLocation(PlayerCameraManager->GetCameraLocation());
MainCameraTransform.SetRotation(FQuat(PlayerCameraManager->GetCameraRotation()));
if (!ToWorldSpacePose(MainCameraTransform, OutTransform))
{
UE_LOG(LogOculusXRAnchors, Display, TEXT("Was not able to transform anchor to world space pose"));
}
}
#endif
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (CVarOculusXRVerboseAnchorDebugXR.GetValueOnGameThread() > 0)
{
UE_LOG(LogOculusXRAnchors, Display, TEXT("UpdateAnchor Pos %s"), *OutTransform.GetLocation().ToString());
UE_LOG(LogOculusXRAnchors, Display, TEXT("UpdateAnchor Rot %s"), *OutTransform.GetRotation().ToString());
}
#endif
Parent->SetActorLocationAndRotation(OutTransform.GetLocation(), OutTransform.GetRotation(), false, 0, ETeleportType::ResetPhysics);
}
}
}
}
bool UOculusXRAnchorComponent::ToWorldSpacePose(FTransform CameraTransform, FTransform& OutTrackingSpaceTransform) const
{
OculusXRHMD::FOculusXRHMD* OculusXRHMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
if (!OculusXRHMD)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve OculusXRHMD, cannot calculate anchor world space pose."));
return false;
}
OculusXRHMD::FPose MainCameraPose(CameraTransform.GetRotation(), CameraTransform.GetLocation());
OculusXRHMD::FPose TrackingSpacePose(OutTrackingSpaceTransform.GetRotation(), OutTrackingSpaceTransform.GetLocation());
FVector OutHeadPosition;
FQuat OutHeadOrientation;
const bool bGetPose = OculusXRHMD->GetCurrentPose(OculusXRHMD->HMDDeviceId, OutHeadOrientation, OutHeadPosition);
if (!bGetPose)
return false;
OculusXRHMD::FPose HeadPose(OutHeadOrientation, OutHeadPosition);
OculusXRHMD::FPose poseInHeadSpace = HeadPose.Inverse() * TrackingSpacePose;
// To world space pose
const OculusXRHMD::FPose WorldTrackingSpacePose = MainCameraPose * poseInHeadSpace;
OutTrackingSpaceTransform.SetLocation(WorldTrackingSpacePose.Position);
OutTrackingSpaceTransform.SetRotation(WorldTrackingSpacePose.Orientation);
return true;
}

View File

@@ -0,0 +1,51 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorComponents.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRAnchorManager.h"
#include "OculusXRSpatialAnchorComponent.h"
bool UOculusXRBaseAnchorComponent::IsComponentEnabled() const
{
bool OutEnabled;
bool OutChangePending;
auto OutResult = OculusXRAnchors::FOculusXRAnchorManager::GetAnchorComponentStatus(Space, Type, OutEnabled, OutChangePending);
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult) && OutEnabled;
}
EOculusXRSpaceComponentType UOculusXRBaseAnchorComponent::GetType() const
{
return Type;
}
uint64 UOculusXRBaseAnchorComponent::GetSpace() const
{
return Space;
}
bool UOculusXRLocatableAnchorComponent::GetTransform(FTransform& outTransform) const
{
ensure(IsComponentEnabled());
if (!UOculusXRAnchorBPFunctionLibrary::GetAnchorTransformByHandle(Space, outTransform))
{
UE_LOG(LogOculusSpatialAnchor, Warning, TEXT("Fetching transform failed."));
return false;
}
return true;
}
bool UOculusXRSpaceContainerAnchorComponent::GetUUIDs(TArray<FOculusXRUUID>& outUUIDs) const
{
ensure(IsComponentEnabled());
if (!OculusXRAnchors::FOculusXRAnchorManager::GetAnchorContainerUUIDs(Space, outUUIDs))
{
UE_LOG(LogOculusSpatialAnchor, Warning, TEXT("Fetching container uuids failed."));
return false;
}
return true;
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorDelegates.h"
FOculusXRAnchorEventDelegates::FOculusXRSpatialAnchorCreateCompleteDelegate FOculusXRAnchorEventDelegates::OculusSpatialAnchorCreateComplete;
FOculusXRAnchorEventDelegates::FOculusXRSpaceSetComponentStatusCompleteDelegate FOculusXRAnchorEventDelegates::OculusSpaceSetComponentStatusComplete;
FOculusXRAnchorEventDelegates::FOculusXRSpaceQueryResultsDelegate FOculusXRAnchorEventDelegates::OculusSpaceQueryResults;
FOculusXRAnchorEventDelegates::FOculusXRSpaceQueryResultDelegate FOculusXRAnchorEventDelegates::OculusSpaceQueryResult;
FOculusXRAnchorEventDelegates::FOculusXRSpaceQueryCompleteDelegate FOculusXRAnchorEventDelegates::OculusSpaceQueryComplete;
FOculusXRAnchorEventDelegates::FOculusXRSpaceSaveCompleteDelegate FOculusXRAnchorEventDelegates::OculusSpaceSaveComplete;
FOculusXRAnchorEventDelegates::FOculusXRSpaceListSaveCompleteDelegate FOculusXRAnchorEventDelegates::OculusSpaceListSaveComplete;
FOculusXRAnchorEventDelegates::FOculusXRSpaceEraseCompleteDelegate FOculusXRAnchorEventDelegates::OculusSpaceEraseComplete;
FOculusXRAnchorEventDelegates::FOculusXRSpaceShareCompleteDelegate FOculusXRAnchorEventDelegates::OculusSpaceShareComplete;
FOculusXRAnchorEventDelegates::FOculusXRAnchorsDiscoverCompleteDelegate FOculusXRAnchorEventDelegates::OculusAnchorsDiscoverComplete;
FOculusXRAnchorEventDelegates::FOculusXRAnchorsDiscoverResultsDelegate FOculusXRAnchorEventDelegates::OculusAnchorsDiscoverResults;
FOculusXRAnchorEventDelegates::FOculusXRAnchorsSaveCompleteDelegate FOculusXRAnchorEventDelegates::OculusAnchorsSaveComplete;
FOculusXRAnchorEventDelegates::FOculusXRAnchorsEraseCompleteDelegate FOculusXRAnchorEventDelegates::OculusAnchorsEraseComplete;
FOculusXRAnchorEventDelegates::FOculusXRShareAnchorsCompleteDelegate FOculusXRAnchorEventDelegates::OculusShareAnchorsComplete;

View File

@@ -0,0 +1,612 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorFunctionsOVR.h"
#include "OculusXRHMD.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRAnchorDelegates.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRAnchorTypesPrivate.h"
#include "OculusXRAnchorsUtil.h"
ovrpSpaceQueryInfo2 ToOvrpSpaceQuery(const FOculusXRSpaceQueryInfo& UEQueryInfo)
{
static const int32 MaxIdsInFilter = 1024;
static const int32 MaxComponentTypesInFilter = 1;
ovrpSpaceQueryInfo2 Result = {};
Result.queryType = ovrpSpaceQueryType_Action;
Result.actionType = ovrpSpaceQueryActionType_Load;
Result.maxQuerySpaces = UEQueryInfo.MaxQuerySpaces;
Result.timeout = static_cast<double>(UEQueryInfo.Timeout);
switch (UEQueryInfo.Location)
{
case EOculusXRSpaceStorageLocation::Invalid:
Result.location = ovrpSpaceStorageLocation_Invalid;
break;
case EOculusXRSpaceStorageLocation::Local:
Result.location = ovrpSpaceStorageLocation_Local;
break;
case EOculusXRSpaceStorageLocation::Cloud:
Result.location = ovrpSpaceStorageLocation_Cloud;
break;
}
switch (UEQueryInfo.FilterType)
{
case EOculusXRSpaceQueryFilterType::None:
Result.filterType = ovrpSpaceQueryFilterType_None;
break;
case EOculusXRSpaceQueryFilterType::FilterByIds:
Result.filterType = ovrpSpaceQueryFilterType_Ids;
break;
case EOculusXRSpaceQueryFilterType::FilterByComponentType:
Result.filterType = ovrpSpaceQueryFilterType_Components;
break;
case EOculusXRSpaceQueryFilterType::FilterByGroup:
Result.filterType = ovrpSpaceQueryFilterType_GroupUuid;
break;
}
Result.IdInfo.numIds = FMath::Min(MaxIdsInFilter, UEQueryInfo.IDFilter.Num());
for (int i = 0; i < Result.IdInfo.numIds; ++i)
{
ovrpUuid OvrUuid;
FMemory::Memcpy(OvrUuid.data, UEQueryInfo.IDFilter[i].UUIDBytes);
Result.IdInfo.ids[i] = OvrUuid;
}
if (UEQueryInfo.ComponentFilter.Num() > 1)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Query info has more than one component. Using first component only."));
}
Result.componentsInfo.numComponents = FMath::Min(MaxComponentTypesInFilter, UEQueryInfo.ComponentFilter.Num());
for (int i = 0; i < Result.componentsInfo.numComponents; ++i)
{
Result.componentsInfo.components[i] = ConvertToOvrpComponentType(UEQueryInfo.ComponentFilter[i]);
}
FMemory::Memcpy(Result.groupUuidInfo.groupUuid.data, UEQueryInfo.GroupUUIDFilter.UUIDBytes);
return Result;
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform)
{
OculusXRHMD::FOculusXRHMD* HMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
if (!HMD)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusAnchorManager::CreateAnchor failed to retrieve HMD."));
return EOculusXRAnchorResult::Failure;
}
ovrpTrackingOrigin TrackingOriginType;
ovrpPosef Posef;
double Time = 0;
const FTransform TrackingToWorld = HMD->GetLastTrackingToWorld();
// convert to tracking space
const FQuat TrackingSpaceOrientation = TrackingToWorld.Inverse().TransformRotation(InTransform.Rotator().Quaternion());
const FVector TrackingSpacePosition = TrackingToWorld.Inverse().TransformPosition(InTransform.GetLocation());
const OculusXRHMD::FPose TrackingSpacePose(TrackingSpaceOrientation, TrackingSpacePosition);
#if WITH_EDITOR
// Link only head space position update
FVector OutHeadPosition;
FQuat OutHeadOrientation;
const bool bGetPose = HMD->GetCurrentPose(HMD->HMDDeviceId, OutHeadOrientation, OutHeadPosition);
if (!bGetPose)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusAnchorManager::CreateAnchor failed to get current headset pose."));
return EOculusXRAnchorResult::Failure;
}
OculusXRHMD::FPose HeadPose(OutHeadOrientation, OutHeadPosition);
OculusXRHMD::FPose MainCameraPose(CameraTransform.GetRotation(), CameraTransform.GetLocation());
OculusXRHMD::FPose PoseInHeadSpace = MainCameraPose.Inverse() * TrackingSpacePose;
// To world space pose
OculusXRHMD::FPose WorldPose = HeadPose * PoseInHeadSpace;
const bool bConverted = HMD->ConvertPose(WorldPose, Posef);
#else
const bool bConverted = HMD->ConvertPose(TrackingSpacePose, Posef);
#endif
if (!bConverted)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusAnchorManager::CreateAnchor failed to convert pose."));
return EOculusXRAnchorResult::Failure;
}
FOculusXRHMDModule::GetPluginWrapper().GetTrackingOriginType2(&TrackingOriginType);
FOculusXRHMDModule::GetPluginWrapper().GetTimeInSeconds(&Time);
const ovrpSpatialAnchorCreateInfo SpatialAnchorCreateInfo = {
TrackingOriginType,
Posef,
Time
};
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().CreateSpatialAnchor(&SpatialAnchorCreateInfo, &OutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("CreateAnchor Request ID: %llu"), OutRequestId);
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Error, TEXT("FOculusAnchorManager::CreateAnchor failed. Result: %d"), Result);
}
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::DestroyAnchor(uint64 AnchorHandle)
{
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().DestroySpace(static_cast<ovrpSpace*>(&AnchorHandle));
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("DestroyAnchor -- ID: %llu"), AnchorHandle);
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::TryGetAnchorTransform(uint64 AnchorHandle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space)
{
OculusXRHMD::FOculusXRHMD* OutHMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
if (!OutHMD)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve OculusXRHMD, cannot calculate anchor transform."));
return EOculusXRAnchorResult::Failure_InvalidOperation;
}
ovrpTrackingOrigin ovrpOrigin = ovrpTrackingOrigin_EyeLevel;
const bool bTrackingOriginSuccess = OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetTrackingOriginType2(&ovrpOrigin));
if (!bTrackingOriginSuccess)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to get tracking origin, cannot calculate anchor transform."));
return EOculusXRAnchorResult::Failure_InvalidOperation;
}
OutTransform = FTransform::Identity;
OutLocationFlags = FOculusXRAnchorLocationFlags(0);
const ovrpUInt64 ovrpSpace = AnchorHandle;
ovrpSpaceLocationf ovrpSpaceLocation{};
const ovrpResult result = FOculusXRHMDModule::GetPluginWrapper().LocateSpace2(&ovrpSpaceLocation, &ovrpSpace, ovrpOrigin);
if (OVRP_SUCCESS(result))
{
OutLocationFlags = FOculusXRAnchorLocationFlags(ovrpSpaceLocation.locationFlags);
if (OutLocationFlags.IsValid())
{
OculusXRHMD::FPose Pose;
OutHMD->ConvertPose(ovrpSpaceLocation.pose, Pose);
switch (Space)
{
case EOculusXRAnchorSpace::World:
{
const FTransform trackingToWorld = OutHMD->GetLastTrackingToWorld();
OutTransform.SetLocation(trackingToWorld.TransformPosition(Pose.Position));
OutTransform.SetRotation(FRotator(trackingToWorld.TransformRotation(FQuat(Pose.Orientation))).Quaternion());
}
break;
case EOculusXRAnchorSpace::Tracking:
{
OutTransform.SetLocation(Pose.Position);
OutTransform.SetRotation(FRotator(FQuat(Pose.Orientation)).Quaternion());
}
break;
};
}
else
{
return EOculusXRAnchorResult::Failure_OperationFailed;
}
}
return OculusXRAnchors::GetResultFromOVRResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::SetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool Enable, float Timeout, uint64& OutRequestId)
{
ovrpSpaceComponentType ovrpType = ConvertToOvrpComponentType(ComponentType);
const ovrpUInt64 OVRPSpace = AnchorHandle;
// validate existing status
ovrpBool isEnabled = false;
ovrpBool changePending = false;
const ovrpResult getComponentStatusResult = FOculusXRHMDModule::GetPluginWrapper().GetSpaceComponentStatus(&OVRPSpace, ovrpType, &isEnabled, &changePending);
bool isStatusChangingOrSame = (static_cast<bool>(isEnabled) == Enable && !changePending) || (static_cast<bool>(isEnabled) != Enable && changePending);
if (OVRP_SUCCESS(getComponentStatusResult) && isStatusChangingOrSame)
{
return EOculusXRAnchorResult::Success;
}
// set status
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SetSpaceComponentStatus(
&OVRPSpace,
ovrpType,
Enable,
Timeout,
&OutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("SetSpaceComponentStatus Request ID: %llu"), OutRequestId);
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::GetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool& OutEnabled, bool& OutChangePending)
{
const ovrpUInt64 OVRPSpace = AnchorHandle;
ovrpBool OutOvrpEnabled = ovrpBool_False;
ovrpBool OutOvrpChangePending = ovrpBool_False;
ovrpSpaceComponentType ovrpType = ConvertToOvrpComponentType(ComponentType);
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceComponentStatus(
&OVRPSpace,
ovrpType,
&OutOvrpEnabled,
&OutOvrpChangePending);
OutEnabled = (OutOvrpEnabled == ovrpBool_True);
OutChangePending = (OutOvrpChangePending == ovrpBool_True);
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::GetSupportedAnchorComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes)
{
ovrpSpace ovrSpace = AnchorHandle;
TArray<ovrpSpaceComponentType> ovrComponentTypes;
ovrpUInt32 input = 0;
ovrpUInt32 output = 0;
ovrpResult enumerateResult = FOculusXRHMDModule::GetPluginWrapper().EnumerateSpaceSupportedComponents(&ovrSpace, input, &output, nullptr);
if (!OVRP_SUCCESS(enumerateResult))
{
return OculusXRAnchors::GetResultFromOVRResult(enumerateResult);
}
input = output;
ovrComponentTypes.SetNumZeroed(output);
enumerateResult = FOculusXRHMDModule::GetPluginWrapper().EnumerateSpaceSupportedComponents(&ovrSpace, input, &output, ovrComponentTypes.GetData());
if (!OVRP_SUCCESS(enumerateResult))
{
return OculusXRAnchors::GetResultFromOVRResult(enumerateResult);
}
OutSupportedTypes.SetNumZeroed(ovrComponentTypes.Num());
for (int i = 0; i < ovrComponentTypes.Num(); ++i)
{
OutSupportedTypes[i] = ConvertToUEComponentType(ovrComponentTypes[i]);
}
return OculusXRAnchors::GetResultFromOVRResult(enumerateResult);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::GetAnchorContainerUUIDs(uint64 AnchorHandle, TArray<FOculusXRUUID>& OutUUIDs)
{
TArray<ovrpUuid> ovrUuidArray;
// Get the number of elements in the container
ovrpSpaceContainer ovrSpaceContainer = {};
ovrSpaceContainer.uuidCapacityInput = 0;
ovrSpaceContainer.uuidCountOutput = 0;
ovrSpaceContainer.uuids = nullptr;
ovrpResult result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&AnchorHandle, &ovrSpaceContainer);
if (OVRP_FAILURE(result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space container %d"), result);
return OculusXRAnchors::GetResultFromOVRResult(result);
}
// Retrieve the actual array of UUIDs
ovrUuidArray.SetNum(ovrSpaceContainer.uuidCountOutput);
ovrSpaceContainer.uuidCapacityInput = ovrSpaceContainer.uuidCountOutput;
ovrSpaceContainer.uuids = ovrUuidArray.GetData();
result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&AnchorHandle, &ovrSpaceContainer);
if (OVRP_FAILURE(result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space container %d"), result);
return OculusXRAnchors::GetResultFromOVRResult(result);
}
// Write out the remaining UUIDs
OutUUIDs.Reserve(ovrUuidArray.Num());
for (auto& it : ovrUuidArray)
{
OutUUIDs.Add(FOculusXRUUID(it.data));
}
return EOculusXRAnchorResult::Success;
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::SaveAnchor(uint64 AnchorHandle,
EOculusXRSpaceStorageLocation StorageLocation,
EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId)
{
ovrpSpaceStorageLocation OvrpStorageLocation = ovrpSpaceStorageLocation_Local;
switch (StorageLocation)
{
case EOculusXRSpaceStorageLocation::Invalid:
OvrpStorageLocation = ovrpSpaceStorageLocation_Invalid;
break;
case EOculusXRSpaceStorageLocation::Local:
OvrpStorageLocation = ovrpSpaceStorageLocation_Local;
break;
case EOculusXRSpaceStorageLocation::Cloud:
OvrpStorageLocation = ovrpSpaceStorageLocation_Cloud;
break;
default:
break;
}
ovrpSpaceStoragePersistenceMode OvrpStoragePersistenceMode = ovrpSpaceStoragePersistenceMode_Invalid;
switch (StoragePersistenceMode)
{
case EOculusXRSpaceStoragePersistenceMode::Invalid:
OvrpStoragePersistenceMode = ovrpSpaceStoragePersistenceMode_Invalid;
break;
case EOculusXRSpaceStoragePersistenceMode::Indefinite:
OvrpStoragePersistenceMode = ovrpSpaceStoragePersistenceMode_Indefinite;
break;
default:
break;
}
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SaveSpace(&AnchorHandle, OvrpStorageLocation, OvrpStoragePersistenceMode, &OutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Saving anchor with, ID: %llu -- Location: %d -- Persistence: %d -- OutID: %llu"), AnchorHandle, OvrpStorageLocation, OvrpStoragePersistenceMode, OutRequestId);
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusXRHMD::SaveAnchor failed with, ID: %llu -- Location: %d -- Persistence: %d"), AnchorHandle, OvrpStorageLocation, OvrpStoragePersistenceMode);
}
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::SaveAnchorList(const TArray<uint64>& AnchorHandles, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId)
{
ovrpSpaceStorageLocation OvrpStorageLocation = ovrpSpaceStorageLocation_Local;
switch (StorageLocation)
{
case EOculusXRSpaceStorageLocation::Invalid:
OvrpStorageLocation = ovrpSpaceStorageLocation_Invalid;
break;
case EOculusXRSpaceStorageLocation::Local:
OvrpStorageLocation = ovrpSpaceStorageLocation_Local;
break;
case EOculusXRSpaceStorageLocation::Cloud:
OvrpStorageLocation = ovrpSpaceStorageLocation_Cloud;
break;
default:
break;
}
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SaveSpaceList(AnchorHandles.GetData(), AnchorHandles.Num(), OvrpStorageLocation, &OutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Saving space list: Location: %d -- OutID: %llu"), OvrpStorageLocation, OutRequestId);
for (auto& it : AnchorHandles)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("\tSpaceID: %llu"), it);
}
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("SaveSpaceList failed -- Result: %d"), Result);
}
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::SaveAnchors(const TArray<uint64>& AnchorHandles, uint64& OutRequestId)
{
if (AnchorHandles.Num() == 0)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusXRAnchorFunctionsOVR::SaveAnchors has empty handle array"));
}
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SaveSpaces(AnchorHandles.Num(), AnchorHandles.GetData(), &OutRequestId);
if (!OVRP_SUCCESS(Result))
{
UE_LOG(LogOculusXRAnchors, Error, TEXT("FOculusXRAnchorFunctionsOVR::SaveAnchors failed, result: %d"), Result);
}
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, uint64& OutRequestId)
{
uint32 FiltersCount = (uint32)DiscoveryInfo.Filters.Num();
ovrpSpaceDiscoveryInfo OvrDiscoveryInfo = {};
OvrDiscoveryInfo.FilterCount = FiltersCount;
UE_LOG(LogOculusXRAnchors, Display, TEXT("Staring discovery with %d filter(s)"), FiltersCount);
TArray<const ovrpSpaceDiscoveryFilterHeader*> filters;
filters.SetNumZeroed(FiltersCount);
for (uint32 i = 0; i < FiltersCount; ++i)
{
ensure(DiscoveryInfo.Filters[i] != nullptr);
filters[i] = DiscoveryInfo.Filters[i]->GenerateOVRPFilter();
}
OvrDiscoveryInfo.Filters = filters.GetData();
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().DiscoverSpaces(&OvrDiscoveryInfo, &OutRequestId);
if (!OVRP_SUCCESS(Result))
{
UE_LOG(LogOculusXRAnchors, Error, TEXT("FOculusXRAnchorFunctionsOVR::DiscoverAnchors failed -- Result: %d"), Result);
}
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::QueryAnchors(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId)
{
ovrpResult QuerySpacesResult = ovrpFailure;
ovrpSpaceQueryInfo2 ovrQueryInfo = ToOvrpSpaceQuery(QueryInfo);
QuerySpacesResult = FOculusXRHMDModule::GetPluginWrapper().QuerySpaces2(&ovrQueryInfo, &OutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Query Spaces\n ovrpSpaceQueryInfo:\n\tQueryType: %d\n\tMaxQuerySpaces: %d\n\tTimeout: %f\n\tLocation: %d\n\tActionType: %d\n\tFilterType: %d\n\n\tRequest ID: %llu"),
ovrQueryInfo.queryType, ovrQueryInfo.maxQuerySpaces, (float)ovrQueryInfo.timeout, ovrQueryInfo.location, ovrQueryInfo.actionType, ovrQueryInfo.filterType, OutRequestId);
if (QueryInfo.FilterType == EOculusXRSpaceQueryFilterType::FilterByIds)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Query contains %d UUIDs"), QueryInfo.IDFilter.Num());
for (auto& it : QueryInfo.IDFilter)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("UUID: %s"), *it.ToString());
}
}
else if (QueryInfo.FilterType == EOculusXRSpaceQueryFilterType::FilterByComponentType)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Query contains %d Component Types"), QueryInfo.ComponentFilter.Num());
for (auto& it : QueryInfo.ComponentFilter)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ComponentType: %s"), *UEnum::GetValueAsString(it));
}
}
else if (QueryInfo.FilterType == EOculusXRSpaceQueryFilterType::FilterByGroup)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Query contains group filter - UUID: %s"), *QueryInfo.GroupUUIDFilter.ToString());
}
return OculusXRAnchors::GetResultFromOVRResult(QuerySpacesResult);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::ShareAnchors(const TArray<uint64>& AchorHandles, const TArray<uint64>& UserIds, uint64& OutRequestId)
{
TArray<const char*> stringStorage;
TArray<ovrpUser> OvrpUsers;
for (const auto& UserId : UserIds)
{
ovrpUser OvrUser;
ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().CreateSpaceUser(&UserId, &OvrUser);
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to create space user from ID - %llu"), UserId);
continue;
}
OvrpUsers.Add(OvrUser);
}
const ovrpResult ShareSpacesResult = FOculusXRHMDModule::GetPluginWrapper().ShareSpaces(AchorHandles.GetData(), AchorHandles.Num(), OvrpUsers.GetData(), OvrpUsers.Num(), &OutRequestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Sharing space list -- OutID: %llu"), OutRequestId);
for (auto& User : OvrpUsers)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("\tOvrpUser: %llu"), User);
ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().DestroySpaceUser(&User);
if (OVRP_FAILURE(Result))
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Failed to destroy space user: %llu"), User);
continue;
}
}
for (auto& it : AchorHandles)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("\tSpaceID: %llu"), it);
}
return OculusXRAnchors::GetResultFromOVRResult(ShareSpacesResult);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, uint64& OutRequestId)
{
TArray<ovrpUuid> groupUuids;
groupUuids.Reserve(Groups.Num());
for (auto& it : Groups)
{
ovrpUuid uuid;
FMemory::Memcpy(uuid.data, it.UUIDBytes);
groupUuids.Add(uuid);
}
TSharedPtr<ovrpShareSpacesGroupRecipientInfo> groupRecipientInfo = MakeShared<ovrpShareSpacesGroupRecipientInfo>();
groupRecipientInfo->GroupCount = groupUuids.Num();
groupRecipientInfo->GroupUuids = groupUuids.GetData();
ovrpShareSpacesInfo shareInfo;
shareInfo.SpaceCount = AnchorHandles.Num();
shareInfo.Spaces = (ovrpSpace*)AnchorHandles.GetData();
shareInfo.RecipientType = ovrpShareSpacesRecipientType_Group;
shareInfo.RecipientInfo = groupRecipientInfo.Get();
ovrpResult result = FOculusXRHMDModule::GetPluginWrapper().ShareSpaces2(&shareInfo, &OutRequestId);
return OculusXRAnchors::GetResultFromOVRResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::EraseAnchor(uint64 AnchorHandle,
EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId)
{
ovrpSpaceStorageLocation ovrpStorageLocation = ovrpSpaceStorageLocation_Local;
switch (StorageLocation)
{
case EOculusXRSpaceStorageLocation::Invalid:
ovrpStorageLocation = ovrpSpaceStorageLocation_Invalid;
break;
case EOculusXRSpaceStorageLocation::Local:
ovrpStorageLocation = ovrpSpaceStorageLocation_Local;
break;
case EOculusXRSpaceStorageLocation::Cloud:
ovrpStorageLocation = ovrpSpaceStorageLocation_Cloud;
break;
default:;
}
ovrpUInt64 OvrpOutRequestId = 0;
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().EraseSpace(&AnchorHandle, ovrpStorageLocation, &OvrpOutRequestId);
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
UE_LOG(LogOculusXRAnchors, Log, TEXT("Erasing anchor -- Handle: %llu -- Location: %d -- OutID: %llu"), AnchorHandle, ovrpStorageLocation, OvrpOutRequestId);
return OculusXRAnchors::GetResultFromOVRResult(Result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOVR::EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& UUIDs, uint64& OutRequestId)
{
if (AnchorHandles.IsEmpty() && UUIDs.IsEmpty())
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusXRAnchorFunctionsOVR::EraseAnchors - You cannot have an empty handle and uuid array. At least one array must have elements."));
return EOculusXRAnchorResult::Failure_InvalidParameter;
}
TArray<ovrpSpace> ovrpHandles;
for (auto& handle : AnchorHandles)
{
ovrpHandles.Add(handle.GetValue());
}
TArray<ovrpUuid> ovrpUUIDs;
for (auto& id : UUIDs)
{
ovrpUuid OvrUuid;
FMemory::Memcpy(OvrUuid.data, id.UUIDBytes);
ovrpUUIDs.Add(OvrUuid);
}
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().EraseSpaces(ovrpHandles.Num(), ovrpHandles.GetData(), ovrpUUIDs.Num(), ovrpUUIDs.GetData(), &OutRequestId);
if (!OVRP_SUCCESS(Result))
{
UE_LOG(LogOculusXRAnchors, Error, TEXT("FOculusXRAnchorFunctionsOVR::EraseAnchors failed -- Result: %d"), Result);
}
return OculusXRAnchors::GetResultFromOVRResult(Result);
}

View File

@@ -0,0 +1,30 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAnchorFunctions.h"
class OCULUSXRANCHORS_API FOculusXRAnchorFunctionsOVR : public IOculusXRAnchorFunctions
{
public:
virtual EOculusXRAnchorResult::Type CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform) override;
virtual EOculusXRAnchorResult::Type DestroyAnchor(uint64 AnchorHandle) override;
virtual EOculusXRAnchorResult::Type TryGetAnchorTransform(uint64 AnchorHandle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space) override;
virtual EOculusXRAnchorResult::Type SetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool Enable, float Timeout, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type GetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool& OutEnabled, bool& OutChangePending) override;
virtual EOculusXRAnchorResult::Type GetSupportedAnchorComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes) override;
virtual EOculusXRAnchorResult::Type GetAnchorContainerUUIDs(uint64 AnchorHandle, TArray<FOculusXRUUID>& OutUUIDs) override;
virtual EOculusXRAnchorResult::Type SaveAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type SaveAnchorList(const TArray<uint64>& AnchorHandles, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type SaveAnchors(const TArray<uint64>& AnchorHandles, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type QueryAnchors(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<uint64>& UserIds, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type EraseAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& UUIDs, uint64& OutRequestId) override;
};

View File

@@ -0,0 +1,108 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorFunctionsOpenXR.h"
#include "OculusXRHMD.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRAnchorDelegates.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRAnchorTypesPrivate.h"
#include "OculusXRAnchorsUtil.h"
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->CreateSpatialAnchor(InTransform, OutRequestId, CameraTransform);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::DestroyAnchor(uint64 AnchorHandle)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->DestroySpatialAnchor(AnchorHandle);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::TryGetAnchorTransform(uint64 AnchorHandle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->TryGetAnchorTransform(AnchorHandle, OutTransform, OutLocationFlags, Space);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::SetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool Enable, float Timeout, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->SetAnchorComponentStatus(AnchorHandle, ComponentType, Enable, Timeout, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::GetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool& OutEnabled, bool& OutChangePending)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->GetAnchorComponentStatus(AnchorHandle, ComponentType, OutEnabled, OutChangePending);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::GetSupportedAnchorComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->GetSupportedAnchorComponents(AnchorHandle, OutSupportedTypes);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::GetAnchorContainerUUIDs(uint64 AnchorHandle, TArray<FOculusXRUUID>& OutUUIDs)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->GetAnchorContainerUUIDs(AnchorHandle, OutUUIDs);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::SaveAnchor(uint64 AnchorHandle,
EOculusXRSpaceStorageLocation StorageLocation,
EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->SaveAnchor(AnchorHandle, StorageLocation, StoragePersistenceMode, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::SaveAnchorList(const TArray<uint64>& AnchorHandles, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->SaveAnchorList(AnchorHandles, StorageLocation, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::SaveAnchors(const TArray<uint64>& AnchorHandles, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->SaveAnchors(AnchorHandles, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->DiscoverAnchors(DiscoveryInfo, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::QueryAnchors(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->QueryAnchors(QueryInfo, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<uint64>& UserIds, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->ShareAnchors(AnchorHandles, UserIds, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->ShareAnchorsWithGroups(AnchorHandles, Groups, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::EraseAnchor(uint64 AnchorHandle,
EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->EraseAnchor(AnchorHandle, StorageLocation, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}
EOculusXRAnchorResult::Type FOculusXRAnchorFunctionsOpenXR::EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& UUIDs, uint64& OutRequestId)
{
auto result = FOculusXRAnchorsModule::Get().GetXrAnchors()->EraseAnchors(AnchorHandles, UUIDs, OutRequestId);
return OculusXRAnchors::GetResultFromXrResult(result);
}

View File

@@ -0,0 +1,30 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAnchorFunctions.h"
class OCULUSXRANCHORS_API FOculusXRAnchorFunctionsOpenXR : public IOculusXRAnchorFunctions
{
public:
virtual EOculusXRAnchorResult::Type CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform) override;
virtual EOculusXRAnchorResult::Type DestroyAnchor(uint64 AnchorHandle) override;
virtual EOculusXRAnchorResult::Type TryGetAnchorTransform(uint64 AnchorHandle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space) override;
virtual EOculusXRAnchorResult::Type SetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool Enable, float Timeout, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type GetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool& OutEnabled, bool& OutChangePending) override;
virtual EOculusXRAnchorResult::Type GetSupportedAnchorComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes) override;
virtual EOculusXRAnchorResult::Type GetAnchorContainerUUIDs(uint64 AnchorHandle, TArray<FOculusXRUUID>& OutUUIDs) override;
virtual EOculusXRAnchorResult::Type SaveAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type SaveAnchorList(const TArray<uint64>& AnchorHandles, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type SaveAnchors(const TArray<uint64>& AnchorHandles, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type QueryAnchors(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<uint64>& UserIds, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type EraseAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId) override;
virtual EOculusXRAnchorResult::Type EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& UUIDs, uint64& OutRequestId) override;
};

View File

@@ -0,0 +1,846 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorLatentActions.h"
#include "OculusXRAnchorsPrivate.h"
#include "OculusXRHMD.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRAnchorDelegates.h"
#include "OculusXRAnchorsModule.h"
//
// Create Spatial Anchor
//
void UOculusXRAsyncAction_CreateSpatialAnchor::Activate()
{
if (!IsValid(TargetActor))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid Target Actor passed to CreateSpatialAnchor latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::CreateSpatialAnchor(
AnchorTransform,
TargetActor,
FOculusXRSpatialAnchorCreateDelegate::CreateUObject(this, &UOculusXRAsyncAction_CreateSpatialAnchor::HandleCreateComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for CreateSpatialAnchor latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_CreateSpatialAnchor* UOculusXRAsyncAction_CreateSpatialAnchor::OculusXRAsyncCreateSpatialAnchor(AActor* TargetActor, const FTransform& AnchorTransform)
{
UOculusXRAsyncAction_CreateSpatialAnchor* Action = NewObject<UOculusXRAsyncAction_CreateSpatialAnchor>();
Action->TargetActor = TargetActor;
Action->AnchorTransform = AnchorTransform;
if (IsValid(TargetActor))
{
Action->RegisterWithGameInstance(TargetActor->GetWorld());
}
else
{
Action->RegisterWithGameInstance(GWorld);
}
return Action;
}
void UOculusXRAsyncAction_CreateSpatialAnchor::HandleCreateComplete(EOculusXRAnchorResult::Type CreateResult, UOculusXRAnchorComponent* Anchor)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(CreateResult))
{
Success.Broadcast(Anchor, CreateResult);
}
else
{
Failure.Broadcast(CreateResult);
}
SetReadyToDestroy();
}
//
// Erase Space
//
void UOculusXRAsyncAction_EraseAnchor::Activate()
{
if (!IsValid(TargetActor))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid Target Actor passed to EraseSpace latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
UOculusXRAnchorComponent* AnchorComponent = TargetActor->FindComponentByClass<UOculusXRAnchorComponent>();
if (AnchorComponent == nullptr)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("No anchor on actor in EraseSpace latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::EraseAnchor(
AnchorComponent,
FOculusXRAnchorEraseDelegate::CreateUObject(this, &UOculusXRAsyncAction_EraseAnchor::HandleEraseAnchorComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for EraseSpace latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_EraseAnchor* UOculusXRAsyncAction_EraseAnchor::OculusXRAsyncEraseAnchor(AActor* TargetActor)
{
UOculusXRAsyncAction_EraseAnchor* Action = NewObject<UOculusXRAsyncAction_EraseAnchor>();
Action->TargetActor = TargetActor;
if (IsValid(TargetActor))
{
Action->RegisterWithGameInstance(TargetActor->GetWorld());
}
else
{
Action->RegisterWithGameInstance(GWorld);
}
return Action;
}
void UOculusXRAsyncAction_EraseAnchor::HandleEraseAnchorComplete(EOculusXRAnchorResult::Type EraseResult, FOculusXRUUID UUID)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(EraseResult))
{
Success.Broadcast(TargetActor, UUID, EraseResult);
}
else
{
Failure.Broadcast(EraseResult);
}
SetReadyToDestroy();
}
//
// Save Space
//
void UOculusXRAsyncAction_SaveAnchor::Activate()
{
if (!IsValid(TargetActor))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid Target Actor passed to SaveSpace latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
UOculusXRAnchorComponent* AnchorComponent = TargetActor->FindComponentByClass<UOculusXRAnchorComponent>();
if (AnchorComponent == nullptr)
{
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
UE_LOG(LogOculusXRAnchors, Log, TEXT("Attempting to save anchor: %s to location %s"), IsValid(AnchorComponent) ? *AnchorComponent->GetName() : TEXT("INVALID ANCHOR"), *UEnum::GetValueAsString(StorageLocation));
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::SaveAnchor(
AnchorComponent,
StorageLocation,
FOculusXRAnchorSaveDelegate::CreateUObject(this, &UOculusXRAsyncAction_SaveAnchor::HandleSaveAnchorComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for SaveSpace latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_SaveAnchor* UOculusXRAsyncAction_SaveAnchor::OculusXRAsyncSaveAnchor(AActor* TargetActor, EOculusXRSpaceStorageLocation StorageLocation)
{
UOculusXRAsyncAction_SaveAnchor* Action = NewObject<UOculusXRAsyncAction_SaveAnchor>();
Action->TargetActor = TargetActor;
Action->StorageLocation = StorageLocation;
if (IsValid(TargetActor))
{
Action->RegisterWithGameInstance(TargetActor->GetWorld());
}
else
{
Action->RegisterWithGameInstance(GWorld);
}
return Action;
}
void UOculusXRAsyncAction_SaveAnchor::HandleSaveAnchorComplete(EOculusXRAnchorResult::Type SaveResult, UOculusXRAnchorComponent* Anchor)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(SaveResult))
{
Success.Broadcast(Anchor, SaveResult);
}
else
{
Failure.Broadcast(SaveResult);
}
SetReadyToDestroy();
}
//
// Save Anchor List
//
void UOculusXRAsyncAction_SaveAnchorList::Activate()
{
if (TargetAnchors.Num() == 0)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Empty Target Actor array passed to SaveSpaces latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::SaveAnchorList(
TargetAnchors,
StorageLocation,
FOculusXRAnchorSaveListDelegate::CreateUObject(this, &UOculusXRAsyncAction_SaveAnchorList::HandleSaveAnchorListComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for SaveSpaceList latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_SaveAnchorList* UOculusXRAsyncAction_SaveAnchorList::OculusXRAsyncSaveAnchorList(const TArray<AActor*>& TargetActors, EOculusXRSpaceStorageLocation StorageLocation)
{
UOculusXRAsyncAction_SaveAnchorList* Action = NewObject<UOculusXRAsyncAction_SaveAnchorList>();
auto ValidActorPtr = TargetActors.FindByPredicate([](AActor* Actor) { return IsValid(Actor); });
for (auto& it : TargetActors)
{
if (!IsValid(it))
{
continue;
}
UOculusXRAnchorComponent* AnchorComponent = it->FindComponentByClass<UOculusXRAnchorComponent>();
Action->TargetAnchors.Add(AnchorComponent);
}
Action->StorageLocation = StorageLocation;
if (ValidActorPtr != nullptr)
{
Action->RegisterWithGameInstance(*ValidActorPtr);
}
return Action;
}
void UOculusXRAsyncAction_SaveAnchorList::HandleSaveAnchorListComplete(EOculusXRAnchorResult::Type SaveResult, const TArray<UOculusXRAnchorComponent*>& SavedSpaces)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(SaveResult))
{
Success.Broadcast(SavedSpaces, SaveResult);
}
else
{
Failure.Broadcast(SaveResult);
}
SetReadyToDestroy();
}
//
// Query Spaces
//
void UOculusXRAsyncAction_QueryAnchors::Activate()
{
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::QueryAnchorsAdvanced(
QueryInfo,
FOculusXRAnchorQueryDelegate::CreateUObject(this, &UOculusXRAsyncAction_QueryAnchors::HandleQueryAnchorsResults),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for QuerySpaces latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_QueryAnchors* UOculusXRAsyncAction_QueryAnchors::OculusXRAsyncQueryAnchors(EOculusXRSpaceStorageLocation Location, const TArray<FOculusXRUUID>& UUIDs)
{
FOculusXRSpaceQueryInfo QueryInfo;
QueryInfo.FilterType = EOculusXRSpaceQueryFilterType::FilterByIds;
QueryInfo.IDFilter = UUIDs;
QueryInfo.Location = Location;
QueryInfo.MaxQuerySpaces = UUIDs.Num();
UOculusXRAsyncAction_QueryAnchors* Action = NewObject<UOculusXRAsyncAction_QueryAnchors>();
Action->QueryInfo = QueryInfo;
return Action;
}
UOculusXRAsyncAction_QueryAnchors* UOculusXRAsyncAction_QueryAnchors::OculusXRAsyncQueryAnchorsAdvanced(const FOculusXRSpaceQueryInfo& QueryInfo)
{
UOculusXRAsyncAction_QueryAnchors* Action = NewObject<UOculusXRAsyncAction_QueryAnchors>();
Action->QueryInfo = QueryInfo;
return Action;
}
void UOculusXRAsyncAction_QueryAnchors::HandleQueryAnchorsResults(EOculusXRAnchorResult::Type QueryResult, const TArray<FOculusXRSpaceQueryResult>& Results)
{
QueryResults = Results;
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(QueryResult))
{
Success.Broadcast(QueryResults, QueryResult);
}
else
{
Failure.Broadcast(QueryResult);
}
SetReadyToDestroy();
}
//
// Set Component Status with Anchor Actor
//
void UOculusXRAsyncAction_SetAnchorComponentStatus::Activate()
{
if (!IsValid(TargetActor))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid Target Actor passed to SetComponentStatus latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
TargetAnchorComponent = TargetActor->FindComponentByClass<UOculusXRAnchorComponent>();
if (TargetAnchorComponent == nullptr)
{
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::SetAnchorComponentStatus(
TargetAnchorComponent,
ComponentType,
bEnabled,
0,
FOculusXRAnchorSetComponentStatusDelegate::CreateUObject(this, &UOculusXRAsyncAction_SetAnchorComponentStatus::HandleSetComponentStatusComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for SetComponentStatus latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_SetAnchorComponentStatus* UOculusXRAsyncAction_SetAnchorComponentStatus::OculusXRAsyncSetAnchorComponentStatus(AActor* TargetActor, EOculusXRSpaceComponentType ComponentType, bool bEnabled)
{
UOculusXRAsyncAction_SetAnchorComponentStatus* Action = NewObject<UOculusXRAsyncAction_SetAnchorComponentStatus>();
Action->TargetActor = TargetActor;
Action->ComponentType = ComponentType;
Action->bEnabled = bEnabled;
if (IsValid(TargetActor))
{
Action->RegisterWithGameInstance(TargetActor->GetWorld());
}
else
{
Action->RegisterWithGameInstance(GWorld);
}
return Action;
}
void UOculusXRAsyncAction_SetAnchorComponentStatus::HandleSetComponentStatusComplete(EOculusXRAnchorResult::Type SetStatusResult, uint64 AnchorHandle, EOculusXRSpaceComponentType SpaceComponentType, bool bResultEnabled)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(SetStatusResult))
{
Success.Broadcast(TargetAnchorComponent, SpaceComponentType, bResultEnabled, SetStatusResult);
}
else
{
Failure.Broadcast(SetStatusResult);
}
SetReadyToDestroy();
}
//
// Set Component Status
//
void UOculusXRAsyncAction_SetComponentStatus::Activate()
{
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::SetComponentStatus(
Component->GetSpace(),
Component->GetType(),
bEnabled,
0,
FOculusXRAnchorSetComponentStatusDelegate::CreateUObject(this, &UOculusXRAsyncAction_SetComponentStatus::HandleSetComponentStatusComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for SetComponentStatus latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_SetComponentStatus* UOculusXRAsyncAction_SetComponentStatus::OculusXRAsyncSetComponentStatus(UOculusXRBaseAnchorComponent* Component, bool bEnabled)
{
UOculusXRAsyncAction_SetComponentStatus* Action = NewObject<UOculusXRAsyncAction_SetComponentStatus>();
Action->Component = Component;
Action->bEnabled = bEnabled;
Action->RegisterWithGameInstance(GWorld);
return Action;
}
void UOculusXRAsyncAction_SetComponentStatus::HandleSetComponentStatusComplete(EOculusXRAnchorResult::Type SetStatusResult, uint64 AnchorHandle, EOculusXRSpaceComponentType SpaceComponentType, bool bResultEnabled)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(SetStatusResult))
{
Success.Broadcast(Component, SetStatusResult);
}
else
{
Failure.Broadcast(SetStatusResult);
}
SetReadyToDestroy();
}
//
// Share Spaces
//
void UOculusXRAsyncAction_ShareAnchors::Activate()
{
if (TargetAnchors.Num() == 0)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Empty Target Actors array passed to ShareSpaces latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
if (ToShareWithIds.Num() == 0)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Empty Target Player IDs array passed to ShareSpaces latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::ShareAnchors(
TargetAnchors,
ToShareWithIds,
FOculusXRAnchorShareDelegate::CreateUObject(this, &UOculusXRAsyncAction_ShareAnchors::HandleShareAnchorsComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for ShareSpaces latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_ShareAnchors* UOculusXRAsyncAction_ShareAnchors::OculusXRAsyncShareAnchors(const TArray<AActor*>& TargetActors, const TArray<FString>& ToShareWithIds)
{
UOculusXRAsyncAction_ShareAnchors* Action = NewObject<UOculusXRAsyncAction_ShareAnchors>();
for (const auto& UserIDString : ToShareWithIds)
{
uint64 UserId = FCString::Strtoui64(*UserIDString, nullptr, 10);
if (UserId == 0)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("UserID provided to share anchors was invalid or unconvertable: %s"), *UserIDString);
}
Action->ToShareWithIds.Add(UserId);
}
for (auto& it : TargetActors)
{
if (!IsValid(it))
{
continue;
}
UOculusXRAnchorComponent* AnchorComponent = it->FindComponentByClass<UOculusXRAnchorComponent>();
Action->TargetAnchors.Add(AnchorComponent);
}
auto ValidActorPtr = TargetActors.FindByPredicate([](AActor* Actor) { return IsValid(Actor); });
if (ValidActorPtr != nullptr)
{
Action->RegisterWithGameInstance(*ValidActorPtr);
}
else
{
Action->RegisterWithGameInstance(GWorld);
}
return Action;
}
void UOculusXRAsyncAction_ShareAnchors::HandleShareAnchorsComplete(EOculusXRAnchorResult::Type ShareResult, const TArray<UOculusXRAnchorComponent*>& SharedAnchors, const TArray<uint64>& OculusUserIDs)
{
TArray<FString> OculusUserIDStrings;
for (const auto& it : OculusUserIDs)
{
OculusUserIDStrings.Add(FString::Printf(TEXT("%llu"), it));
}
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(ShareResult))
{
Success.Broadcast(SharedAnchors, OculusUserIDStrings, ShareResult);
}
else
{
Failure.Broadcast(ShareResult);
}
// Unbind and mark for destruction
SetReadyToDestroy();
}
//
// Save Anchors
//
void UOculusXRAsyncAction_SaveAnchors::Activate()
{
if (TargetAnchors.Num() == 0)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Empty Target Actor array passed to SaveSpaces latent action."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::SaveAnchors(
TargetAnchors,
FOculusXRSaveAnchorsDelegate::CreateUObject(this, &UOculusXRAsyncAction_SaveAnchors::HandleSaveAnchorsComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for SaveSpaces latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_SaveAnchors* UOculusXRAsyncAction_SaveAnchors::OculusXRAsyncSaveAnchors(const TArray<AActor*>& TargetActors)
{
UOculusXRAsyncAction_SaveAnchors* Action = NewObject<UOculusXRAsyncAction_SaveAnchors>();
auto ValidActorPtr = TargetActors.FindByPredicate([](AActor* Actor) { return IsValid(Actor); });
for (auto& it : TargetActors)
{
if (!IsValid(it))
{
continue;
}
UOculusXRAnchorComponent* AnchorComponent = it->FindComponentByClass<UOculusXRAnchorComponent>();
Action->TargetAnchors.Add(AnchorComponent);
}
if (ValidActorPtr != nullptr)
{
Action->RegisterWithGameInstance(*ValidActorPtr);
}
return Action;
}
void UOculusXRAsyncAction_SaveAnchors::HandleSaveAnchorsComplete(EOculusXRAnchorResult::Type SaveResult, const TArray<UOculusXRAnchorComponent*>& SavedSpaces)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(SaveResult))
{
Success.Broadcast(SavedSpaces, SaveResult);
}
else
{
Failure.Broadcast(SaveResult);
}
SetReadyToDestroy();
}
//
// Erase Anchors
//
void UOculusXRAsyncAction_EraseAnchors::Activate()
{
if (TargetAnchorHandles.IsEmpty() && TargetUUIDs.IsEmpty())
{
UE_LOG(LogOculusXRAnchors, Error, TEXT("Empty UUID and Anchor Handles arrays passed to erase anchors. Check that at least one of the anchors, handles, and UUIDs arrays provided have valid elements."));
Failure.Broadcast(EOculusXRAnchorResult::Failure);
return;
}
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::EraseAnchors(
TargetAnchorHandles,
TargetUUIDs,
FOculusXREraseAnchorsDelegate::CreateUObject(this, &UOculusXRAsyncAction_EraseAnchors::HandleEraseAnchorsComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for EraseSpace latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_EraseAnchors* UOculusXRAsyncAction_EraseAnchors::OculusXRAsyncEraseAnchors(const TArray<AActor*>& TargetActors, const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& AnchorUUIDs)
{
UOculusXRAsyncAction_EraseAnchors* Action = NewObject<UOculusXRAsyncAction_EraseAnchors>();
Action->TargetAnchorHandles = AnchorHandles;
Action->TargetUUIDs = AnchorUUIDs;
auto ValidActorPtr = TargetActors.FindByPredicate([](AActor* Actor) { return IsValid(Actor); });
for (auto& it : TargetActors)
{
if (!IsValid(it))
{
continue;
}
UOculusXRAnchorComponent* AnchorComponent = it->FindComponentByClass<UOculusXRAnchorComponent>();
if (!IsValid(it))
{
continue;
}
Action->TargetAnchors.Add(AnchorComponent);
auto UUID = AnchorComponent->GetUUID();
Action->TargetUUIDs.Add(UUID);
}
if (ValidActorPtr != nullptr)
{
Action->RegisterWithGameInstance(*ValidActorPtr);
}
else
{
Action->RegisterWithGameInstance(GWorld);
}
return Action;
}
void UOculusXRAsyncAction_EraseAnchors::HandleEraseAnchorsComplete(EOculusXRAnchorResult::Type EraseResult, const TArray<UOculusXRAnchorComponent*>& ErasedAnchorComponents, const TArray<FOculusXRUInt64>& ErasedAnchorHandles, const TArray<FOculusXRUUID>& ErasedAnchorUUIDs)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(EraseResult))
{
Success.Broadcast(TargetAnchors, ErasedAnchorHandles, ErasedAnchorUUIDs, EraseResult);
}
else
{
Failure.Broadcast(EraseResult);
}
SetReadyToDestroy();
}
//
// Anchors Discovery
//
void UOculusXRAsyncAction_DiscoverAnchors::Activate()
{
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::DiscoverAnchors(
DiscoveryInfo,
FOculusXRDiscoverAnchorsResultsDelegate::CreateUObject(this, &UOculusXRAsyncAction_DiscoverAnchors::HandleDiscoverResult),
FOculusXRDiscoverAnchorsCompleteDelegate::CreateUObject(this, &UOculusXRAsyncAction_DiscoverAnchors::HandleDiscoverComplete),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for DiscoverAnchors latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_DiscoverAnchors* UOculusXRAsyncAction_DiscoverAnchors::OculusXRAsyncDiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo)
{
UOculusXRAsyncAction_DiscoverAnchors* Action = NewObject<UOculusXRAsyncAction_DiscoverAnchors>();
Action->DiscoveryInfo = DiscoveryInfo;
return Action;
}
void UOculusXRAsyncAction_DiscoverAnchors::HandleDiscoverResult(const TArray<FOculusXRAnchorsDiscoverResult>& DiscoveredAnchors)
{
Discovered.Broadcast(DiscoveredAnchors);
}
void UOculusXRAsyncAction_DiscoverAnchors::HandleDiscoverComplete(EOculusXRAnchorResult::Type CompleteResult)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(CompleteResult))
{
Complete.Broadcast(CompleteResult);
}
else
{
Failure.Broadcast(CompleteResult);
}
SetReadyToDestroy();
}
//
// Get Shared Anchors
//
void UOculusXRAsyncAction_GetSharedAnchors::Activate()
{
EOculusXRAnchorResult::Type Result;
bool bStartedAsync = OculusXRAnchors::FOculusXRAnchors::GetSharedAnchors(
Anchors,
FOculusXRGetSharedAnchorsDelegate::CreateUObject(this, &UOculusXRAsyncAction_GetSharedAnchors::HandleGetSharedAnchorsResult),
Result);
if (!bStartedAsync)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async OVR Plugin call for DiscoverAnchors latent action."));
Failure.Broadcast(Result);
}
}
UOculusXRAsyncAction_GetSharedAnchors* UOculusXRAsyncAction_GetSharedAnchors::OculusXRAsyncGetSharedAnchors(const TArray<FOculusXRUUID>& AnchorUUIDs)
{
UOculusXRAsyncAction_GetSharedAnchors* Action = NewObject<UOculusXRAsyncAction_GetSharedAnchors>();
Action->Anchors = AnchorUUIDs;
return Action;
}
void UOculusXRAsyncAction_GetSharedAnchors::HandleGetSharedAnchorsResult(EOculusXRAnchorResult::Type Result, const TArray<FOculusXRAnchorsDiscoverResult>& SharedAnchors)
{
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(Result))
{
Success.Broadcast(SharedAnchors, Result);
}
else
{
Failure.Broadcast(Result);
}
}
//
// Share with groups
//
void UOculusXRAsyncAction_ShareAnchorsWithGroups::Activate()
{
OculusXRAnchors::FOculusXRAnchors::ShareAnchorsAsync(
AnchorHandles,
GroupUUIDs,
OculusXRAnchors::FShareAnchorsWithGroups::FCompleteDelegate::CreateUObject(
this,
&UOculusXRAsyncAction_ShareAnchorsWithGroups::HandleShareComplete));
}
UOculusXRAsyncAction_ShareAnchorsWithGroups* UOculusXRAsyncAction_ShareAnchorsWithGroups::OculusXRShareAnchorsWithGroupsAsync(const TArray<FOculusXRUUID>& GroupUUIDs, const TArray<FOculusXRUInt64>& AnchorHandles)
{
UOculusXRAsyncAction_ShareAnchorsWithGroups* Action = NewObject<UOculusXRAsyncAction_ShareAnchorsWithGroups>();
Action->GroupUUIDs = GroupUUIDs;
Action->AnchorHandles = AnchorHandles;
Action->RegisterWithGameInstance(GWorld);
return Action;
}
void UOculusXRAsyncAction_ShareAnchorsWithGroups::HandleShareComplete(const OculusXRAnchors::FShareAnchorsWithGroups::FResultType& Result)
{
if (Result.IsSuccess())
{
Complete.Broadcast(Result.IsSuccess(), GroupUUIDs, AnchorHandles, Result.GetStatus());
}
else
{
Complete.Broadcast(Result.IsSuccess(), TArray<FOculusXRUUID>(), TArray<FOculusXRUInt64>(), Result.GetStatus());
}
SetReadyToDestroy();
}
//
// Get shared anchors from group
//
void UOculusXRAsyncAction_GetSharedAnchorsFromGroup::Activate()
{
OculusXRAnchors::FOculusXRAnchors::GetSharedAnchorsAsync(
GroupUuid,
Anchors,
OculusXRAnchors::FGetAnchorsSharedWithGroup::FCompleteDelegate::CreateUObject(
this,
&UOculusXRAsyncAction_GetSharedAnchorsFromGroup::HandleGetSharedAnchorsComplete));
}
UOculusXRAsyncAction_GetSharedAnchorsFromGroup* UOculusXRAsyncAction_GetSharedAnchorsFromGroup::OculusXRGetSharedAnchorsFromGroupAsync(const FOculusXRUUID& GroupUuid, const TArray<FOculusXRUUID>& AnchorUUIDs)
{
UOculusXRAsyncAction_GetSharedAnchorsFromGroup* Action = NewObject<UOculusXRAsyncAction_GetSharedAnchorsFromGroup>();
Action->GroupUuid = GroupUuid;
Action->Anchors = AnchorUUIDs;
Action->RegisterWithGameInstance(GWorld);
return Action;
}
void UOculusXRAsyncAction_GetSharedAnchorsFromGroup::HandleGetSharedAnchorsComplete(const OculusXRAnchors::FGetAnchorsSharedWithGroup::FResultType& Result)
{
if (Result.IsSuccess())
{
Complete.Broadcast(Result.IsSuccess(), Result.GetValue(), Result.GetStatus());
}
else
{
Complete.Broadcast(Result.IsSuccess(), OculusXRAnchors::FGetAnchorsSharedWithGroup::FResultValueType(), Result.GetStatus());
}
SetReadyToDestroy();
}

View File

@@ -0,0 +1,124 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorManager.h"
#include <vector>
#include "OculusXRHMD.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRAnchorDelegates.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRAnchorTypesPrivate.h"
#include "OculusXRAnchorFunctionsOVR.h"
#include "OculusXRAnchorFunctionsOpenXR.h"
namespace OculusXRAnchors
{
EOculusXRAnchorResult::Type FOculusXRAnchorManager::CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform)
{
return GetOculusXRAnchorFunctionsImpl()->CreateAnchor(InTransform, OutRequestId, CameraTransform);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::DestroyAnchor(uint64 AnchorHandle)
{
return GetOculusXRAnchorFunctionsImpl()->DestroyAnchor(AnchorHandle);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::TryGetAnchorTransform(uint64 AnchorHandle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space)
{
return GetOculusXRAnchorFunctionsImpl()->TryGetAnchorTransform(AnchorHandle, OutTransform, OutLocationFlags, Space);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool Enable, float Timeout, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->SetAnchorComponentStatus(AnchorHandle, ComponentType, Enable, Timeout, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool& OutEnabled, bool& OutChangePending)
{
return GetOculusXRAnchorFunctionsImpl()->GetAnchorComponentStatus(AnchorHandle, ComponentType, OutEnabled, OutChangePending);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSupportedAnchorComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes)
{
return GetOculusXRAnchorFunctionsImpl()->GetSupportedAnchorComponents(AnchorHandle, OutSupportedTypes);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetAnchorContainerUUIDs(uint64 AnchorHandle, TArray<FOculusXRUUID>& OutUUIDs)
{
return GetOculusXRAnchorFunctionsImpl()->GetAnchorContainerUUIDs(AnchorHandle, OutUUIDs);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SaveAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->SaveAnchor(AnchorHandle, StorageLocation, StoragePersistenceMode, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SaveAnchorList(const TArray<uint64>& AnchorHandles, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->SaveAnchorList(AnchorHandles, StorageLocation, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SaveAnchors(const TArray<uint64>& AnchorHandles, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->SaveAnchors(AnchorHandles, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->DiscoverAnchors(DiscoveryInfo, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::QueryAnchors(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->QueryAnchors(QueryInfo, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<uint64>& UserIds, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->ShareAnchors(AnchorHandles, UserIds, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::ShareAnchors(const TArray<uint64>& AnchorHandles, FOculusXRUUID GroupId, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->ShareAnchors(AnchorHandles, { GroupId }, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->ShareAnchors(AnchorHandles, Groups, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::EraseAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->EraseAnchor(AnchorHandle, StorageLocation, OutRequestId);
}
EOculusXRAnchorResult::Type FOculusXRAnchorManager::EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& UUIDs, uint64& OutRequestId)
{
return GetOculusXRAnchorFunctionsImpl()->EraseAnchors(AnchorHandles, UUIDs, OutRequestId);
}
TSharedPtr<IOculusXRAnchorFunctions> FOculusXRAnchorManager::AnchorFunctionsImpl = nullptr;
TSharedPtr<IOculusXRAnchorFunctions> FOculusXRAnchorManager::GetOculusXRAnchorFunctionsImpl()
{
if (AnchorFunctionsImpl == nullptr)
{
const FName SystemName(TEXT("OpenXR"));
const bool IsOpenXR = GEngine->XRSystem.IsValid() && (GEngine->XRSystem->GetSystemName() == SystemName);
if (OculusXRHMD::FOculusXRHMD::GetOculusXRHMD() != nullptr)
{
AnchorFunctionsImpl = MakeShared<FOculusXRAnchorFunctionsOVR>();
}
else if (IsOpenXR)
{
AnchorFunctionsImpl = MakeShared<FOculusXRAnchorFunctionsOpenXR>();
}
}
check(AnchorFunctionsImpl);
return AnchorFunctionsImpl;
}
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,42 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "CoreMinimal.h"
#include "OculusXRAnchorComponent.h"
#include "OculusXRHMDPrivate.h"
#include "OVR_Plugin_Types.h"
#include "OculusXRAnchorFunctions.h"
namespace OculusXRAnchors
{
struct OCULUSXRANCHORS_API FOculusXRAnchorManager
{
public:
static EOculusXRAnchorResult::Type CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform);
static EOculusXRAnchorResult::Type DestroyAnchor(uint64 AnchorHandle);
static EOculusXRAnchorResult::Type TryGetAnchorTransform(uint64 AnchorHandle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space);
static EOculusXRAnchorResult::Type SetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool Enable, float Timeout, uint64& OutRequestId);
static EOculusXRAnchorResult::Type GetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool& OutEnabled, bool& OutChangePending);
static EOculusXRAnchorResult::Type GetSupportedAnchorComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes);
static EOculusXRAnchorResult::Type GetAnchorContainerUUIDs(uint64 AnchorHandle, TArray<FOculusXRUUID>& OutUUIDs);
static EOculusXRAnchorResult::Type SaveAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId);
static EOculusXRAnchorResult::Type SaveAnchorList(const TArray<uint64>& AnchorHandles, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId);
static EOculusXRAnchorResult::Type SaveAnchors(const TArray<uint64>& AnchorHandles, uint64& OutRequestId);
static EOculusXRAnchorResult::Type DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, uint64& OutRequestId);
static EOculusXRAnchorResult::Type QueryAnchors(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId);
static EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<uint64>& UserIds, uint64& OutRequestId);
static EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, FOculusXRUUID GroupId, uint64& OutRequestId);
static EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, uint64& OutRequestId);
static EOculusXRAnchorResult::Type EraseAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId);
static EOculusXRAnchorResult::Type EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& UUIDs, uint64& OutRequestId);
private:
static TSharedPtr<IOculusXRAnchorFunctions> GetOculusXRAnchorFunctionsImpl();
static TSharedPtr<IOculusXRAnchorFunctions> AnchorFunctionsImpl;
};
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,151 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorsRequests.h"
#include "OculusXRAnchorsUtil.h"
#include "OculusXRHMDModule.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRAnchorManager.h"
#include "OculusXRAnchorDelegates.h"
namespace OculusXRAnchors
{
OculusXR::FAsyncRequestBase::RequestId DetermineRequestId(EOculusXRAnchorResult::Type Result, uint64 Id)
{
return OVRP_SUCCESS(Result) ? OculusXR::FAsyncRequestBase::RequestId(Id) : OculusXR::FAsyncRequestBase::RequestId(OculusXR::INVALID_TASK_REQUEST_ID);
}
FShareAnchorsWithGroups::FShareAnchorsWithGroups(const TArray<FOculusXRUUID>& TargetGroups, const TArray<FOculusXRUInt64>& AnchorsToShare)
: Groups(TargetGroups)
, Anchors(AnchorsToShare)
{
CallbackHandle = FOculusXRAnchorEventDelegates::OculusShareAnchorsComplete.AddStatic(&FShareAnchorsWithGroups::OnShareComplete);
}
FShareAnchorsWithGroups::~FShareAnchorsWithGroups()
{
FOculusXRAnchorEventDelegates::OculusShareAnchorsComplete.Remove(CallbackHandle);
}
void FShareAnchorsWithGroups::OnInitRequest()
{
TArray<uint64> anchorHandles;
Algo::Transform(Anchors, anchorHandles, [](const FOculusXRUInt64& In) { return In.GetValue(); });
uint64 requestId;
auto result = FOculusXRAnchorManager::ShareAnchors(anchorHandles, Groups, requestId);
SetRequestId(DetermineRequestId(result, requestId));
SetInitialResult(result);
UE_LOG(LogOculusXRAnchors, Log, TEXT("Started FShareAnchorsWithGroups: RequestId: %llu -- EventId: %llu -- Result: %s"),
GetRequestId().Id, GetEventId().Id, *GetStringFromResult(result));
}
void FShareAnchorsWithGroups::OnShareComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result)
{
auto taskPtr = OculusXR::FAsyncRequestSystem::GetRequest<FShareAnchorsWithGroups>(
OculusXR::FAsyncRequestBase::RequestId{ RequestId });
if (taskPtr.IsValid())
{
OculusXR::FAsyncRequestSystem::CompleteRequest<FShareAnchorsWithGroups>(
taskPtr->GetEventId(),
FShareAnchorsWithGroups::FResultType::FromResult(
Result,
FShareAnchorsWithGroups::FResultValueType(taskPtr->GetGroups(), taskPtr->GetAnchors())));
}
}
FGetAnchorsSharedWithGroup::FGetAnchorsSharedWithGroup(const FOculusXRUUID& TargetGroup, const TArray<FOculusXRUUID>& WantedAnchors)
: Group(TargetGroup)
, RequestedAnchors(WantedAnchors)
{
CallbackHandleComplete = FOculusXRAnchorEventDelegates::OculusSpaceQueryComplete.AddStatic(&FGetAnchorsSharedWithGroup::OnQueryComplete);
CallbackHandleResults = FOculusXRAnchorEventDelegates::OculusSpaceQueryResult.AddStatic(&FGetAnchorsSharedWithGroup::OnQueryResultAvailable);
}
FGetAnchorsSharedWithGroup::~FGetAnchorsSharedWithGroup()
{
FOculusXRAnchorEventDelegates::OculusSpaceQueryComplete.Remove(CallbackHandleComplete);
FOculusXRAnchorEventDelegates::OculusSpaceQueryResult.Remove(CallbackHandleResults);
}
void FGetAnchorsSharedWithGroup::OnResultsAvailable(const TArray<FOculusXRAnchor>& Results)
{
RetrievedAnchors += Results;
}
void FGetAnchorsSharedWithGroup::OnInitRequest()
{
constexpr int32 maxSpaces = 1024;
constexpr double timeout = 0;
FOculusXRSpaceQueryInfo queryInfo;
queryInfo.FilterType = EOculusXRSpaceQueryFilterType::FilterByGroup;
queryInfo.GroupUUIDFilter = Group;
queryInfo.Location = EOculusXRSpaceStorageLocation::Cloud;
queryInfo.MaxQuerySpaces = maxSpaces;
queryInfo.Timeout = timeout;
queryInfo.IDFilter = RequestedAnchors;
uint64 requestId;
auto result = FOculusXRAnchorManager::QueryAnchors(queryInfo, requestId);
SetRequestId(DetermineRequestId(result, requestId));
SetInitialResult(result);
UE_LOG(LogOculusXRAnchors, Log, TEXT("Started FGetAnchorsSharedWithGroup: RequestId: %llu -- EventId: %llu -- Result: %s"),
GetRequestId().Id, GetEventId().Id, *GetStringFromResult(result));
}
void FGetAnchorsSharedWithGroup::OnQueryComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result)
{
auto taskPtr = OculusXR::FAsyncRequestSystem::GetRequest<FGetAnchorsSharedWithGroup>(
OculusXR::FAsyncRequestBase::RequestId{ RequestId.GetValue() });
// If there is a valid get shared anchors request we can complete and exit without firing legacy event delegates
if (taskPtr.IsValid())
{
OculusXR::FAsyncRequestSystem::CompleteRequest<FGetAnchorsSharedWithGroup>(
taskPtr->GetEventId(),
FGetAnchorsSharedWithGroup::FResultType::FromResult(Result, taskPtr->GetRetrievedAnchors()));
return;
}
}
void FGetAnchorsSharedWithGroup::OnQueryResultAvailable(FOculusXRUInt64 RequestId, FOculusXRUInt64 AnchorHandle, FOculusXRUUID AnchorUuid)
{
auto taskPtr = OculusXR::FAsyncRequestSystem::GetRequest<FGetAnchorsSharedWithGroup>(
OculusXR::FAsyncRequestBase::RequestId{ RequestId.GetValue() });
if (taskPtr.IsValid())
{
TArray<EOculusXRSpaceComponentType> supportedTypes;
UE_LOG(LogOculusXRAnchors, Verbose, TEXT(" Found Element: Space: %llu -- UUID: %s"), AnchorHandle.Value, *AnchorUuid.ToString());
uint64 tempOut;
FOculusXRAnchorManager::GetSupportedAnchorComponents(AnchorHandle, supportedTypes);
if (supportedTypes.Contains(EOculusXRSpaceComponentType::Locatable))
{
FOculusXRAnchorManager::SetAnchorComponentStatus(AnchorHandle, EOculusXRSpaceComponentType::Locatable, true, 0.0f, tempOut);
}
if (supportedTypes.Contains(EOculusXRSpaceComponentType::Sharable))
{
FOculusXRAnchorManager::SetAnchorComponentStatus(AnchorHandle, EOculusXRSpaceComponentType::Sharable, true, 0.0f, tempOut);
}
if (supportedTypes.Contains(EOculusXRSpaceComponentType::Storable))
{
FOculusXRAnchorManager::SetAnchorComponentStatus(AnchorHandle, EOculusXRSpaceComponentType::Storable, true, 0.0f, tempOut);
}
taskPtr->OnResultsAvailable({ FOculusXRAnchor(AnchorHandle, AnchorUuid) });
return;
}
}
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,134 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorTypes.h"
#include "OculusXRHMDPrivate.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRAnchorTypesPrivate.h"
bool FOculusXRUInt64::operator==(const FOculusXRUInt64& Right) const
{
return IsEqual(Right);
}
bool FOculusXRUInt64::operator!=(const FOculusXRUInt64& Right) const
{
return !IsEqual(Right);
}
FOculusXRUUID::FOculusXRUUID()
{
FMemory::Memzero(&UUIDBytes, OCULUSXR_UUID_SIZE);
}
FOculusXRUUID::FOculusXRUUID(const UuidArray& In)
{
FMemory::Memcpy(UUIDBytes, In);
}
bool FOculusXRUUID::operator==(const FOculusXRUUID& Right) const
{
return IsEqual(Right);
}
bool FOculusXRUUID::operator!=(const FOculusXRUUID& Right) const
{
return !IsEqual(Right);
}
bool FOculusXRUUID::IsValidUUID() const
{
static uint8 InvalidUUID[OCULUSXR_UUID_SIZE] = { 0 };
return FMemory::Memcmp(UUIDBytes, InvalidUUID, OCULUSXR_UUID_SIZE) != 0;
}
bool FOculusXRUUID::IsEqual(const FOculusXRUUID& Other) const
{
return FMemory::Memcmp(UUIDBytes, Other.UUIDBytes, OCULUSXR_UUID_SIZE) == 0;
}
bool FOculusXRUUID::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
uint8 data[16] = { 0 };
for (uint8 i = 0; i < OCULUSXR_UUID_SIZE; ++i)
{
data[i] = UUIDBytes[i];
};
for (uint8 i = 0; i < OCULUSXR_UUID_SIZE; ++i)
{
Ar << data[i];
};
for (uint8 i = 0; i < OCULUSXR_UUID_SIZE; ++i)
{
UUIDBytes[i] = data[i];
};
bOutSuccess = true;
return true;
}
FArchive& operator<<(FArchive& Ar, FOculusXRUUID& UUID)
{
bool bOutSuccess = false;
UUID.NetSerialize(Ar, nullptr, bOutSuccess);
return Ar;
}
bool FOculusXRUUID::Serialize(FArchive& Ar)
{
Ar << *this;
return true;
}
FString FOculusXRUUID::ToString() const
{
return BytesToHex(UUIDBytes, OCULUSXR_UUID_SIZE);
}
void ovrpSpaceDiscoveryFilterIdsDelete::operator()(ovrpSpaceDiscoveryFilterIds* ptr) const
{
if (ptr != nullptr)
{
delete ptr;
ptr = nullptr;
}
}
const ovrpSpaceDiscoveryFilterHeader* UOculusXRSpaceDiscoveryIdsFilter::GenerateOVRPFilter()
{
uint32 IdsCount = (uint32)Uuids.Num();
wrappedUUIDs.SetNumZeroed(IdsCount);
OVRPFilterIds.reset(new ovrpSpaceDiscoveryFilterIds{ ovrpSpaceDiscoveryFilterType_Ids, IdsCount });
UE_LOG(LogOculusXRAnchors, Display, TEXT("UUID discovery filter:"));
for (uint32 i = 0; i < IdsCount; ++i)
{
FMemory::Memcpy(wrappedUUIDs[i].data, Uuids[i].UUIDBytes);
UE_LOG(LogOculusXRAnchors, Display, TEXT("\t%s"), *Uuids[i].ToString());
}
OVRPFilterIds->Uuids = reinterpret_cast<ovrpUuid*>(wrappedUUIDs.GetData());
return (const ovrpSpaceDiscoveryFilterHeader*)OVRPFilterIds.get();
}
void ovrpSpaceDiscoveryFilterComponentsDelete::operator()(ovrpSpaceDiscoveryFilterComponents* ptr) const
{
if (ptr != nullptr)
{
delete ptr;
ptr = nullptr;
}
}
const ovrpSpaceDiscoveryFilterHeader* UOculusXRSpaceDiscoveryComponentsFilter::GenerateOVRPFilter()
{
OVRPFilterComponent.reset(new ovrpSpaceDiscoveryFilterComponents{ ovrpSpaceDiscoveryFilterType_Components, ConvertToOvrpComponentType(ComponentType) });
UE_LOG(LogOculusXRAnchors, Display, TEXT("Component discovery filter %d"), ComponentType);
return (const ovrpSpaceDiscoveryFilterHeader*)OVRPFilterComponent.get();
}

View File

@@ -0,0 +1,79 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorTypesPrivate.h"
ovrpSpaceComponentType ConvertToOvrpComponentType(const EOculusXRSpaceComponentType ComponentType)
{
ovrpSpaceComponentType ovrpType = ovrpSpaceComponentType_Max;
switch (ComponentType)
{
case EOculusXRSpaceComponentType::Locatable:
ovrpType = ovrpSpaceComponentType_Locatable;
break;
case EOculusXRSpaceComponentType::Sharable:
ovrpType = ovrpSpaceComponentType_Sharable;
break;
case EOculusXRSpaceComponentType::Storable:
ovrpType = ovrpSpaceComponentType_Storable;
break;
case EOculusXRSpaceComponentType::ScenePlane:
ovrpType = ovrpSpaceComponentType_Bounded2D;
break;
case EOculusXRSpaceComponentType::SceneVolume:
ovrpType = ovrpSpaceComponentType_Bounded3D;
break;
case EOculusXRSpaceComponentType::SemanticClassification:
ovrpType = ovrpSpaceComponentType_SemanticLabels;
break;
case EOculusXRSpaceComponentType::RoomLayout:
ovrpType = ovrpSpaceComponentType_RoomLayout;
break;
case EOculusXRSpaceComponentType::SpaceContainer:
ovrpType = ovrpSpaceComponentType_SpaceContainer;
break;
case EOculusXRSpaceComponentType::TriangleMesh:
ovrpType = ovrpSpaceComponentType_TriangleMesh;
break;
default:;
}
return ovrpType;
}
EOculusXRSpaceComponentType ConvertToUEComponentType(const ovrpSpaceComponentType ComponentType)
{
EOculusXRSpaceComponentType ueComponentType = EOculusXRSpaceComponentType::Undefined;
switch (ComponentType)
{
case ovrpSpaceComponentType_Locatable:
ueComponentType = EOculusXRSpaceComponentType::Locatable;
break;
case ovrpSpaceComponentType_Sharable:
ueComponentType = EOculusXRSpaceComponentType::Sharable;
break;
case ovrpSpaceComponentType_Storable:
ueComponentType = EOculusXRSpaceComponentType::Storable;
break;
case ovrpSpaceComponentType_Bounded2D:
ueComponentType = EOculusXRSpaceComponentType::ScenePlane;
break;
case ovrpSpaceComponentType_Bounded3D:
ueComponentType = EOculusXRSpaceComponentType::SceneVolume;
break;
case ovrpSpaceComponentType_SemanticLabels:
ueComponentType = EOculusXRSpaceComponentType::SemanticClassification;
break;
case ovrpSpaceComponentType_RoomLayout:
ueComponentType = EOculusXRSpaceComponentType::RoomLayout;
break;
case ovrpSpaceComponentType_SpaceContainer:
ueComponentType = EOculusXRSpaceComponentType::SpaceContainer;
break;
case ovrpSpaceComponentType_TriangleMesh:
ueComponentType = EOculusXRSpaceComponentType::TriangleMesh;
break;
default:;
}
return ueComponentType;
}

View File

@@ -0,0 +1,8 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAnchorTypes.h"
#include "OVR_Plugin_Types.h"
ovrpSpaceComponentType ConvertToOvrpComponentType(const EOculusXRSpaceComponentType ComponentType);
EOculusXRSpaceComponentType ConvertToUEComponentType(const ovrpSpaceComponentType ComponentType);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,355 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorsEventPolling.h"
#include "OculusXRHMD.h"
#include "OculusXRAnchorsModule.h"
#include "OculusXRAnchorManager.h"
#include "OculusXRAnchorDelegates.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
#include "OculusXRAnchorTypesPrivate.h"
#include "OculusXRAnchorsUtil.h"
#include "Engine/Engine.h"
#include <vector>
namespace OculusXRAnchors
{
template <typename T>
void GetEventDataAs(ovrpEventDataBuffer& Buffer, T& OutEventData)
{
memcpy(&OutEventData, reinterpret_cast<uint8*>(&Buffer), sizeof(T));
}
// For template specializations that use the legacy event padding
constexpr size_t LegacyOffset = 8;
template <typename T>
void GetLegacyEventDataAs(ovrpEventDataBuffer& Buffer, T& OutEventData)
{
OutEventData.EventType = Buffer.EventType;
memcpy(((uint8*)&OutEventData) + LegacyOffset, Buffer.EventData, sizeof(T) - LegacyOffset);
}
#define DECLARE_EVENT_DATA_CAST_SPECIALIZATION(T) \
template <> \
void GetEventDataAs(ovrpEventDataBuffer& Buffer, T& OutEventData) \
{ \
GetLegacyEventDataAs<T>(Buffer, OutEventData); \
}
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventDataSpatialAnchorCreateComplete);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventDataSpaceSetStatusComplete);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpaceQueryResults);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpaceQueryComplete);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpaceStorageSaveResult);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpaceListSaveResult);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpaceStorageEraseResult);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpaceShareResult);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventDataSpaceDiscoveryComplete);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpaceDiscoveryResults);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpacesSaveResult);
DECLARE_EVENT_DATA_CAST_SPECIALIZATION(ovrpEventSpacesEraseResult);
void FOculusXRAnchorsEventPolling::OnPollEvent(ovrpEventDataBuffer* EventDataBuffer, bool& EventPollResult)
{
ovrpEventDataBuffer& buf = *EventDataBuffer;
EventPollResult = true;
switch (buf.EventType)
{
case ovrpEventType_SpatialAnchorCreateComplete:
{
ovrpEventDataSpatialAnchorCreateComplete AnchorCreateEvent;
GetEventDataAs(buf, AnchorCreateEvent);
const FOculusXRUInt64 RequestId(AnchorCreateEvent.requestId);
const FOculusXRUInt64 Space(AnchorCreateEvent.space);
const FOculusXRUUID BPUUID(AnchorCreateEvent.uuid.data);
FOculusXRAnchorEventDelegates::OculusSpatialAnchorCreateComplete.Broadcast(
RequestId,
GetResultFromOVRResult(AnchorCreateEvent.result),
Space,
BPUUID);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpatialAnchorCreateComplete Request ID: %llu -- Space: %llu -- UUID: %s -- Result: %d"),
RequestId.GetValue(),
Space.GetValue(),
*BPUUID.ToString(),
AnchorCreateEvent.result);
break;
}
case ovrpEventType_SpaceSetComponentStatusComplete:
{
ovrpEventDataSpaceSetStatusComplete SetStatusEvent;
GetEventDataAs(buf, SetStatusEvent);
// translate to BP types
const FOculusXRUInt64 RequestId(SetStatusEvent.requestId);
const FOculusXRUInt64 Space(SetStatusEvent.space);
EOculusXRSpaceComponentType BPSpaceComponentType = ConvertToUEComponentType(SetStatusEvent.componentType);
const FOculusXRUUID BPUUID(SetStatusEvent.uuid.data);
const bool bEnabled = (SetStatusEvent.enabled == ovrpBool_True);
FOculusXRAnchorEventDelegates::OculusSpaceSetComponentStatusComplete.Broadcast(
RequestId,
GetResultFromOVRResult(SetStatusEvent.result),
Space,
BPUUID,
BPSpaceComponentType,
bEnabled);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceSetComponentStatusComplete Request ID: %llu -- Type: %d -- Enabled: %d -- Space: %llu -- Result: %d"),
SetStatusEvent.requestId,
SetStatusEvent.componentType,
SetStatusEvent.enabled,
SetStatusEvent.space,
SetStatusEvent.result);
break;
}
case ovrpEventType_SpaceQueryResults:
{
ovrpEventSpaceQueryResults QueryEvent;
GetEventDataAs(buf, QueryEvent);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceQueryResults Request ID: %llu"), QueryEvent.requestId);
ovrpUInt32 ovrpOutCapacity = 0;
auto getCapacityResult = FOculusXRHMDModule::GetPluginWrapper().RetrieveSpaceQueryResults(&QueryEvent.requestId, 0, &ovrpOutCapacity, nullptr);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Space Query Results: Capacity Request -- Request ID: %llu -- Capacity: %d -- Result: %s"),
QueryEvent.requestId,
ovrpOutCapacity,
*GetStringFromResult(GetResultFromOVRResult(getCapacityResult)));
std::vector<ovrpSpaceQueryResult> spaceQueryResults(ovrpOutCapacity);
auto getQueryResult = FOculusXRHMDModule::GetPluginWrapper().RetrieveSpaceQueryResults(&QueryEvent.requestId, spaceQueryResults.size(), &ovrpOutCapacity, spaceQueryResults.data());
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Space Query Results: Retrieved Elements -- Request ID: %llu -- Result: %s"),
QueryEvent.requestId,
*GetStringFromResult(GetResultFromOVRResult(getQueryResult)));
if (OVRP_FAILURE(getCapacityResult) || OVRP_FAILURE(getQueryResult))
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to retrieve anchor data from space query results -- Request ID: %llu"), QueryEvent.requestId);
return;
}
FOculusXRUInt64 RequestId(QueryEvent.requestId);
FOculusXRAnchorEventDelegates::OculusSpaceQueryResults.Broadcast(RequestId);
for (const auto& queryResultElement : spaceQueryResults)
{
FOculusXRUInt64 anchorHandle(queryResultElement.space);
FOculusXRUUID uuid(queryResultElement.uuid.data);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceQueryResult -- Space: %llu -- UUID: %s"), anchorHandle.Value, *uuid.ToString());
FOculusXRAnchorEventDelegates::OculusSpaceQueryResult.Broadcast(RequestId, anchorHandle, uuid);
}
break;
}
case ovrpEventType_SpaceQueryComplete:
{
ovrpEventSpaceQueryComplete QueryCompleteEvent;
GetEventDataAs(buf, QueryCompleteEvent);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceQueryComplete Request ID: %llu -- Result: %d"), QueryCompleteEvent.requestId, QueryCompleteEvent.result);
// translate to BP types
const FOculusXRUInt64 RequestId(QueryCompleteEvent.requestId);
const bool bSucceeded = QueryCompleteEvent.result >= 0;
FOculusXRAnchorEventDelegates::OculusSpaceQueryComplete.Broadcast(
RequestId,
GetResultFromOVRResult(QueryCompleteEvent.result));
break;
}
case ovrpEventType_SpaceSaveComplete:
{
ovrpEventSpaceStorageSaveResult StorageResult;
GetEventDataAs(buf, StorageResult);
// translate to BP types
const FOculusXRUUID uuid(StorageResult.uuid.data);
const FOculusXRUInt64 FSpace(StorageResult.space);
const FOculusXRUInt64 FRequest(StorageResult.requestId);
const bool bResult = StorageResult.result >= 0;
FOculusXRAnchorEventDelegates::OculusSpaceSaveComplete.Broadcast(
FRequest,
FSpace,
bResult,
GetResultFromOVRResult(StorageResult.result),
uuid);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceSaveComplete Request ID: %llu -- Space: %llu -- Result: %d"), StorageResult.requestId, StorageResult.space, StorageResult.result);
break;
}
case ovrpEventType_SpaceListSaveResult:
{
ovrpEventSpaceListSaveResult SpaceListSaveResult;
GetEventDataAs(buf, SpaceListSaveResult);
FOculusXRUInt64 RequestId(SpaceListSaveResult.requestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceListSaveResult Request ID: %llu -- Result: %d"), SpaceListSaveResult.requestId, SpaceListSaveResult.result);
FOculusXRAnchorEventDelegates::OculusSpaceListSaveComplete.Broadcast(
RequestId,
GetResultFromOVRResult(SpaceListSaveResult.result));
break;
}
case ovrpEventType_SpaceEraseComplete:
{
ovrpEventSpaceStorageEraseResult SpaceEraseEvent;
GetEventDataAs(buf, SpaceEraseEvent);
// translate to BP types
const FOculusXRUUID uuid(SpaceEraseEvent.uuid.data);
const FOculusXRUInt64 FRequestId(SpaceEraseEvent.requestId);
const EOculusXRSpaceStorageLocation BPLocation = (SpaceEraseEvent.location == ovrpSpaceStorageLocation_Local) ? EOculusXRSpaceStorageLocation::Local : EOculusXRSpaceStorageLocation::Invalid;
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceEraseComplete Request ID: %llu -- Result: %d -- UUID: %s"),
SpaceEraseEvent.requestId,
SpaceEraseEvent.result,
*UOculusXRAnchorBPFunctionLibrary::AnchorUUIDToString(SpaceEraseEvent.uuid.data));
FOculusXRAnchorEventDelegates::OculusSpaceEraseComplete.Broadcast(
FRequestId,
GetResultFromOVRResult(SpaceEraseEvent.result),
uuid,
BPLocation);
break;
}
case ovrpEventType_SpaceShareResult:
{
ovrpEventSpaceShareResult SpaceShareSpaceResult;
GetEventDataAs(buf, SpaceShareSpaceResult);
FOculusXRUInt64 RequestId(SpaceShareSpaceResult.requestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceShareSpaceResult Request ID: %llu -- Result: %d"),
SpaceShareSpaceResult.requestId,
SpaceShareSpaceResult.result);
FOculusXRAnchorEventDelegates::OculusSpaceShareComplete.Broadcast(
RequestId,
GetResultFromOVRResult(SpaceShareSpaceResult.result));
break;
}
case ovrpEventType_SpaceDiscoveryComplete:
{
ovrpEventDataSpaceDiscoveryComplete SpaceDiscoveryCompleteEvent;
GetEventDataAs(buf, SpaceDiscoveryCompleteEvent);
FOculusXRUInt64 RequestId(SpaceDiscoveryCompleteEvent.requestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceDiscoveryComplete Request ID: %llu -- Result: %d"),
RequestId.GetValue(),
SpaceDiscoveryCompleteEvent.result);
FOculusXRAnchorEventDelegates::OculusAnchorsDiscoverComplete.Broadcast(
RequestId,
GetResultFromOVRResult(SpaceDiscoveryCompleteEvent.result));
break;
}
case ovrpEventType_SpaceDiscoveryResultsAvailable:
{
ovrpEventSpaceDiscoveryResults SpaceDiscoveryResultsEvent;
GetEventDataAs(buf, SpaceDiscoveryResultsEvent);
FOculusXRUInt64 RequestId(SpaceDiscoveryResultsEvent.requestId);
ovrpSpaceDiscoveryResults OVRPResults = { 0, 0, nullptr };
// get capacity
bool GetCapacityResult = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().RetrieveSpaceDiscoveryResults(RequestId, &OVRPResults));
UE_LOG(LogOculusXRAnchors, Log, TEXT("ovrpEventType_SpaceDiscoveryResultsAvailable Request ID: %llu -- Capacity: %d -- Result: %d"),
uint64(RequestId), OVRPResults.ResultCountOutput, GetCapacityResult);
// get data
OVRPResults.ResultCapacityInput = OVRPResults.ResultCountOutput;
std::vector<ovrpSpaceDiscoveryResult> ResultsData(OVRPResults.ResultCountOutput);
OVRPResults.Results = ResultsData.data();
bool GetDiscoveryResult = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().RetrieveSpaceDiscoveryResults(RequestId, &OVRPResults));
TArray<FOculusXRAnchorsDiscoverResult> SpaceDiscoveryResults;
for (auto& Element : ResultsData)
{
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceDiscoveryResultsAvailable Space: %llu -- Result: %d"),
Element.Space,
GetDiscoveryResult);
SpaceDiscoveryResults.Add(FOculusXRAnchorsDiscoverResult(Element.Space, Element.Uuid.data));
}
FOculusXRAnchorEventDelegates::OculusAnchorsDiscoverResults.Broadcast(RequestId, SpaceDiscoveryResults);
break;
}
case ovrpEventType_SpacesSaveResult:
{
ovrpEventSpacesSaveResult SpacesSaveEvent;
GetEventDataAs(buf, SpacesSaveEvent);
FOculusXRUInt64 RequestId(SpacesSaveEvent.requestId);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpacesSaveResult Request ID: %llu -- Result: %d"),
RequestId.GetValue(),
SpacesSaveEvent.result);
FOculusXRAnchorEventDelegates::OculusAnchorsSaveComplete.Broadcast(
RequestId,
GetResultFromOVRResult(SpacesSaveEvent.result));
break;
}
case ovrpEventType_SpacesEraseResult:
{
ovrpEventSpacesEraseResult SpacesEraseEvent;
GetEventDataAs(buf, SpacesEraseEvent);
FOculusXRUInt64 RequestId(SpacesEraseEvent.requestId);
FOculusXRUInt64 Result(SpacesEraseEvent.result);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpacesEraseResult Request ID: %llu -- Result: %d"),
RequestId.GetValue(),
SpacesEraseEvent.result);
FOculusXRAnchorEventDelegates::OculusAnchorsEraseComplete.Broadcast(
RequestId,
GetResultFromOVRResult(SpacesEraseEvent.result));
break;
}
case ovrpEventType_ShareSpacesComplete:
{
ovrpEventShareSpacesComplete EventData;
GetEventDataAs(buf, EventData);
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_ShareSpacesComplete Request ID: %llu -- Result: %s"),
EventData.RequestId,
*GetStringFromResult(GetResultFromOVRResult(EventData.Result)));
FOculusXRAnchorEventDelegates::OculusShareAnchorsComplete.Broadcast(
EventData.RequestId,
GetResultFromOVRResult(EventData.Result));
break;
}
case ovrpEventType_None:
default:
{
EventPollResult = false;
break;
}
}
}
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,16 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAnchorTypes.h"
#include "OculusXRPluginWrapper.h"
namespace OculusXRAnchors
{
struct FOculusXRAnchorsEventPolling
{
public:
static void OnPollEvent(ovrpEventDataBuffer* EventDataBuffer, bool& EventPollResult);
};
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,109 @@
// @lint-ignore-every LICENSELINT
// Copyright Epic Games, Inc. All Rights Reserved.
#include "OculusXRAnchorsModule.h"
#if OCULUS_ANCHORS_SUPPORTED_PLATFORMS
#include "OculusXRHMDModule.h"
#include "OculusXRHMD.h"
#include "OculusXRAnchors.h"
#include "OculusXRAnchorsEventPolling.h"
#include "OculusXRAnchorComponents.h"
DEFINE_LOG_CATEGORY(LogOculusXRAnchors);
#define LOCTEXT_NAMESPACE "OculusXRAnchors"
//-------------------------------------------------------------------------------------------------
// FOculusXRAnchorsModule
//-------------------------------------------------------------------------------------------------
void FOculusXRAnchorsModule::StartupModule()
{
AnchorsXR = MakeShareable(new XRAnchors::FAnchorsXR());
AnchorsXR->RegisterAsOpenXRExtension();
AddCreateAnchorComponentInterface(this);
Anchors.Initialize();
FCoreDelegates::OnPostEngineInit.AddRaw(this, &FOculusXRAnchorsModule::OnPostEngineInit);
}
void FOculusXRAnchorsModule::ShutdownModule()
{
Anchors.Teardown();
}
void FOculusXRAnchorsModule::OnPostEngineInit()
{
if (IsRunningCommandlet())
{
return;
}
if (!GEngine)
{
return;
}
OculusXRHMD::FOculusXRHMD* HMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
if (!HMD)
{
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve OculusXRHMD, cannot add event polling delegates."));
return;
}
HMD->AddEventPollingDelegate(OculusXRHMD::FOculusXRHMDEventPollingDelegate::CreateStatic(&OculusXRAnchors::FOculusXRAnchorsEventPolling::OnPollEvent));
}
void FOculusXRAnchorsModule::AddCreateAnchorComponentInterface(IOculusXRCreateAnchorComponent* CastInterface)
{
CreateComponentInterfaces.AddUnique(CastInterface);
}
void FOculusXRAnchorsModule::RemoveCreateAnchorComponentInterface(IOculusXRCreateAnchorComponent* CastInterface)
{
CreateComponentInterfaces.Remove(CastInterface);
}
UOculusXRBaseAnchorComponent* FOculusXRAnchorsModule::CreateAnchorComponent(uint64 AnchorHandle, EOculusXRSpaceComponentType Type, UObject* Outer)
{
for (auto& it : CreateComponentInterfaces)
{
auto comp = it->TryCreateAnchorComponent(AnchorHandle, Type, Outer);
if (IsValid(comp))
{
return comp;
}
}
return nullptr;
}
UOculusXRBaseAnchorComponent* FOculusXRAnchorsModule::TryCreateAnchorComponent(uint64 AnchorHandle, EOculusXRSpaceComponentType Type, UObject* Outer)
{
switch (Type)
{
case EOculusXRSpaceComponentType::Locatable:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRLocatableAnchorComponent>(AnchorHandle, Outer);
case EOculusXRSpaceComponentType::SpaceContainer:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRSpaceContainerAnchorComponent>(AnchorHandle, Outer);
case EOculusXRSpaceComponentType::Sharable:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRSharableAnchorComponent>(AnchorHandle, Outer);
case EOculusXRSpaceComponentType::Storable:
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRStorableAnchorComponent>(AnchorHandle, Outer);
default:
return nullptr;
}
}
OculusXRAnchors::FOculusXRAnchors* FOculusXRAnchorsModule::GetOculusAnchors()
{
FOculusXRAnchorsModule& Module = FModuleManager::LoadModuleChecked<FOculusXRAnchorsModule>(TEXT("OculusXRAnchors"));
return &Module.Anchors;
}
#endif // OCULUS_ANCHORS_SUPPORTED_PLATFORMS
IMPLEMENT_MODULE(FOculusXRAnchorsModule, OculusXRAnchors)
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,63 @@
// @lint-ignore-every LICENSELINT
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "IOculusXRAnchorsModule.h"
#include "OculusXRAnchors.h"
#include "openxr/OculusXRAnchorsXR.h"
#define LOCTEXT_NAMESPACE "OculusAnchors"
//-------------------------------------------------------------------------------------------------
// FOculusXRAnchorsModule
//-------------------------------------------------------------------------------------------------
#if OCULUS_ANCHORS_SUPPORTED_PLATFORMS
DECLARE_LOG_CATEGORY_EXTERN(LogOculusXRAnchors, Log, All);
typedef TSharedPtr<XRAnchors::FAnchorsXR, ESPMode::ThreadSafe> FAnchorsXRPtr;
class FOculusXRAnchorsModule : public IOculusXRAnchorsModule, IOculusXRCreateAnchorComponent
{
public:
static inline FOculusXRAnchorsModule& Get()
{
return FModuleManager::LoadModuleChecked<FOculusXRAnchorsModule>("OculusXRAnchors");
}
virtual ~FOculusXRAnchorsModule() = default;
// IModuleInterface interface
virtual void StartupModule() override;
virtual void ShutdownModule() override;
void OnPostEngineInit();
// IOculusXRAnchorsModule
virtual void AddCreateAnchorComponentInterface(IOculusXRCreateAnchorComponent* CastInterface) override;
virtual void RemoveCreateAnchorComponentInterface(IOculusXRCreateAnchorComponent* CastInterface) override;
virtual UOculusXRBaseAnchorComponent* CreateAnchorComponent(uint64 AnchorHandle, EOculusXRSpaceComponentType Type, UObject* Outer) override;
// IOculusXRAnchorComponentCaster
virtual UOculusXRBaseAnchorComponent* TryCreateAnchorComponent(uint64 AnchorHandle, EOculusXRSpaceComponentType Type, UObject* Outer) override;
static OculusXRAnchors::FOculusXRAnchors* GetOculusAnchors();
FAnchorsXRPtr GetXrAnchors() { return AnchorsXR; }
private:
TArray<IOculusXRCreateAnchorComponent*> CreateComponentInterfaces;
OculusXRAnchors::FOculusXRAnchors Anchors;
FAnchorsXRPtr AnchorsXR;
};
#else // OCULUS_ANCHORS_SUPPORTED_PLATFORMS
class FOculusXRAnchorsModule : public FDefaultModuleImpl
{
};
#endif // OCULUS_ANCHORS_SUPPORTED_PLATFORMS
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,5 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAnchorsModule.h"

View File

@@ -0,0 +1,240 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRAnchorsUtil.h"
#include <khronos/openxr/openxr.h>
namespace OculusXRAnchors
{
EOculusXRAnchorResult::Type GetResultFromOVRResult(ovrpResult OVRResult)
{
switch (OVRResult)
{
case ovrpSuccess:
return EOculusXRAnchorResult::Success;
case ovrpWarning_BoundaryVisibilitySuppressionNotAllowed:
return EOculusXRAnchorResult::Warning_BoundaryVisibilitySuppressionNotAllowed;
case ovrpFailure:
return EOculusXRAnchorResult::Failure;
case ovrpFailure_InvalidParameter:
return EOculusXRAnchorResult::Failure_InvalidParameter;
case ovrpFailure_NotInitialized:
return EOculusXRAnchorResult::Failure_NotInitialized;
case ovrpFailure_InvalidOperation:
return EOculusXRAnchorResult::Failure_InvalidOperation;
case ovrpFailure_Unsupported:
return EOculusXRAnchorResult::Failure_Unsupported;
case ovrpFailure_NotYetImplemented:
return EOculusXRAnchorResult::Failure_NotYetImplemented;
case ovrpFailure_OperationFailed:
return EOculusXRAnchorResult::Failure_OperationFailed;
case ovrpFailure_InsufficientSize:
return EOculusXRAnchorResult::Failure_InsufficientSize;
case ovrpFailure_DataIsInvalid:
return EOculusXRAnchorResult::Failure_DataIsInvalid;
case ovrpFailure_DeprecatedOperation:
return EOculusXRAnchorResult::Failure_DeprecatedOperation;
case ovrpFailure_ErrorLimitReached:
return EOculusXRAnchorResult::Failure_ErrorLimitReached;
case ovrpFailure_ErrorInitializationFailed:
return EOculusXRAnchorResult::Failure_ErrorInitializationFailed;
// Query Spaces
case ovrpFailure_SpaceCloudStorageDisabled:
return EOculusXRAnchorResult::Failure_SpaceCloudStorageDisabled;
case ovrpFailure_SpaceMappingInsufficient:
return EOculusXRAnchorResult::Failure_SpaceMappingInsufficient;
case ovrpFailure_SpaceLocalizationFailed:
return EOculusXRAnchorResult::Failure_SpaceLocalizationFailed;
case ovrpFailure_SpaceNetworkTimeout:
return EOculusXRAnchorResult::Failure_SpaceNetworkTimeout;
case ovrpFailure_SpaceNetworkRequestFailed:
return EOculusXRAnchorResult::Failure_SpaceNetworkRequestFailed;
// APD
case ovrpFailure_SpaceInsufficientResources:
return EOculusXRAnchorResult::Failure_SpaceInsufficientResources;
case ovrpFailure_SpaceStorageAtCapacity:
return EOculusXRAnchorResult::Failure_SpaceStorageAtCapacity;
case ovrpFailure_SpaceInsufficientView:
return EOculusXRAnchorResult::Failure_SpaceInsufficientView;
case ovrpFailure_SpacePermissionInsufficient:
return EOculusXRAnchorResult::Failure_SpacePermissionInsufficient;
case ovrpFailure_SpaceRateLimited:
return EOculusXRAnchorResult::Failure_SpaceRateLimited;
case ovrpFailure_SpaceTooDark:
return EOculusXRAnchorResult::Failure_SpaceTooDark;
case ovrpFailure_SpaceTooBright:
return EOculusXRAnchorResult::Failure_SpaceTooBright;
default:
return OVRP_SUCCESS(OVRResult) ? EOculusXRAnchorResult::Success : EOculusXRAnchorResult::Failure;
}
}
EOculusXRAnchorResult::Type GetResultFromXrResult(XrResult Result)
{
switch (Result)
{
case XR_SUCCESS:
return EOculusXRAnchorResult::Success;
// case XR_BOUNDARY_VISIBILITY_SUPPRESSION_NOT_ALLOWED_META:
// return EOculusXRAnchorResult::Warning_BoundaryVisibilitySuppressionNotAllowed;
case XR_ERROR_VALIDATION_FAILURE:
return EOculusXRAnchorResult::Failure_InvalidParameter;
case XR_ERROR_RUNTIME_FAILURE:
return EOculusXRAnchorResult::Failure_OperationFailed;
case XR_ERROR_FEATURE_UNSUPPORTED:
return EOculusXRAnchorResult::Failure_Unsupported;
case XR_ERROR_FUNCTION_UNSUPPORTED:
return EOculusXRAnchorResult::Failure_NotYetImplemented;
case XR_ERROR_SIZE_INSUFFICIENT:
return EOculusXRAnchorResult::Failure_InsufficientSize;
case XR_ERROR_LIMIT_REACHED:
return EOculusXRAnchorResult::Failure_ErrorLimitReached;
case XR_ERROR_INITIALIZATION_FAILED:
return EOculusXRAnchorResult::Failure_ErrorInitializationFailed;
// Query Spaces
case XR_ERROR_SPACE_CLOUD_STORAGE_DISABLED_FB:
return EOculusXRAnchorResult::Failure_SpaceCloudStorageDisabled;
case XR_ERROR_SPACE_MAPPING_INSUFFICIENT_FB:
return EOculusXRAnchorResult::Failure_SpaceMappingInsufficient;
case XR_ERROR_SPACE_LOCALIZATION_FAILED_FB:
return EOculusXRAnchorResult::Failure_SpaceLocalizationFailed;
case XR_ERROR_SPACE_NETWORK_TIMEOUT_FB:
return EOculusXRAnchorResult::Failure_SpaceNetworkTimeout;
case XR_ERROR_SPACE_NETWORK_REQUEST_FAILED_FB:
return EOculusXRAnchorResult::Failure_SpaceNetworkRequestFailed;
// APD
case XR_ERROR_SPACE_INSUFFICIENT_RESOURCES_META:
return EOculusXRAnchorResult::Failure_SpaceInsufficientResources;
case XR_ERROR_SPACE_STORAGE_AT_CAPACITY_META:
return EOculusXRAnchorResult::Failure_SpaceStorageAtCapacity;
case XR_ERROR_SPACE_INSUFFICIENT_VIEW_META:
return EOculusXRAnchorResult::Failure_SpaceInsufficientView;
case XR_ERROR_SPACE_PERMISSION_INSUFFICIENT_META:
return EOculusXRAnchorResult::Failure_SpacePermissionInsufficient;
case XR_ERROR_SPACE_RATE_LIMITED_META:
return EOculusXRAnchorResult::Failure_SpaceRateLimited;
case XR_ERROR_SPACE_TOO_DARK_META:
return EOculusXRAnchorResult::Failure_SpaceTooDark;
case XR_ERROR_SPACE_TOO_BRIGHT_META:
return EOculusXRAnchorResult::Failure_SpaceTooBright;
default:
return XR_SUCCEEDED(Result) ? EOculusXRAnchorResult::Success : EOculusXRAnchorResult::Failure;
}
}
EOculusXRSpaceComponentType ToComponentType(XrSpaceComponentTypeFB XrType)
{
switch (XrType)
{
case XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB:
return EOculusXRSpaceComponentType::Locatable;
case XR_SPACE_COMPONENT_TYPE_STORABLE_FB:
return EOculusXRSpaceComponentType::Storable;
case XR_SPACE_COMPONENT_TYPE_SHARABLE_FB:
return EOculusXRSpaceComponentType::Sharable;
case XR_SPACE_COMPONENT_TYPE_BOUNDED_2D_FB:
return EOculusXRSpaceComponentType::ScenePlane;
case XR_SPACE_COMPONENT_TYPE_BOUNDED_3D_FB:
return EOculusXRSpaceComponentType::SceneVolume;
case XR_SPACE_COMPONENT_TYPE_SEMANTIC_LABELS_FB:
return EOculusXRSpaceComponentType::SemanticClassification;
case XR_SPACE_COMPONENT_TYPE_ROOM_LAYOUT_FB:
return EOculusXRSpaceComponentType::RoomLayout;
case XR_SPACE_COMPONENT_TYPE_SPACE_CONTAINER_FB:
return EOculusXRSpaceComponentType::SpaceContainer;
case XR_SPACE_COMPONENT_TYPE_TRIANGLE_MESH_META:
return EOculusXRSpaceComponentType::TriangleMesh;
default:
return EOculusXRSpaceComponentType::Undefined;
}
}
XrSpaceComponentTypeFB ToComponentType(EOculusXRSpaceComponentType ComponentType)
{
switch (ComponentType)
{
case EOculusXRSpaceComponentType::Locatable:
return XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB;
case EOculusXRSpaceComponentType::Storable:
return XR_SPACE_COMPONENT_TYPE_STORABLE_FB;
case EOculusXRSpaceComponentType::Sharable:
return XR_SPACE_COMPONENT_TYPE_SHARABLE_FB;
case EOculusXRSpaceComponentType::ScenePlane:
return XR_SPACE_COMPONENT_TYPE_BOUNDED_2D_FB;
case EOculusXRSpaceComponentType::SceneVolume:
return XR_SPACE_COMPONENT_TYPE_BOUNDED_3D_FB;
case EOculusXRSpaceComponentType::SemanticClassification:
return XR_SPACE_COMPONENT_TYPE_SEMANTIC_LABELS_FB;
case EOculusXRSpaceComponentType::RoomLayout:
return XR_SPACE_COMPONENT_TYPE_ROOM_LAYOUT_FB;
case EOculusXRSpaceComponentType::SpaceContainer:
return XR_SPACE_COMPONENT_TYPE_SPACE_CONTAINER_FB;
case EOculusXRSpaceComponentType::TriangleMesh:
return XR_SPACE_COMPONENT_TYPE_TRIANGLE_MESH_META;
default:
return XR_SPACE_COMPONENT_TYPE_MAX_ENUM_FB;
}
}
EOculusXRSpaceStorageLocation ToStorageLocation(XrSpaceStorageLocationFB XrStorageLocation)
{
switch (XrStorageLocation)
{
case XR_SPACE_STORAGE_LOCATION_LOCAL_FB:
return EOculusXRSpaceStorageLocation::Local;
case XR_SPACE_STORAGE_LOCATION_CLOUD_FB:
return EOculusXRSpaceStorageLocation::Cloud;
default:
return EOculusXRSpaceStorageLocation::Invalid;
}
}
XrSpaceStorageLocationFB ToStorageLocation(EOculusXRSpaceStorageLocation StorageLocation)
{
switch (StorageLocation)
{
case EOculusXRSpaceStorageLocation::Local:
return XR_SPACE_STORAGE_LOCATION_LOCAL_FB;
case EOculusXRSpaceStorageLocation::Cloud:
return XR_SPACE_STORAGE_LOCATION_CLOUD_FB;
default:
return XR_SPACE_STORAGE_LOCATION_INVALID_FB;
}
}
FOculusXRUUID ToUuid(const XrUuidEXT& XrUuid)
{
return FOculusXRUUID(XrUuid.data);
}
XrUuidEXT ToUuid(const FOculusXRUUID& Uuid)
{
XrUuidEXT result;
FMemory::Memcpy(result.data, Uuid.UUIDBytes);
return result;
}
FString GetStringFromResult(EOculusXRAnchorResult::Type Result)
{
return UEnum::GetDisplayValueAsText(Result).ToString();
}
FString ToString(EOculusXRSpaceComponentType ComponentType)
{
// Todo: More performant to use const strings and a case statement?
return UEnum::GetDisplayValueAsText(ComponentType).ToString();
}
FString ToString(EOculusXRSpaceStorageLocation StorageLocation)
{
// Todo: More performant to use const strings and a case statement?
return UEnum::GetDisplayValueAsText(StorageLocation).ToString();
}
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,26 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "openxr/OculusXRAnchorsXRIncludes.h"
#include "OculusXRAnchorTypes.h"
#include "OculusXRHMDPrivate.h"
namespace OculusXRAnchors
{
OCULUSXRANCHORS_API EOculusXRAnchorResult::Type GetResultFromOVRResult(ovrpResult OVRResult);
OCULUSXRANCHORS_API EOculusXRAnchorResult::Type GetResultFromXrResult(XrResult Result);
OCULUSXRANCHORS_API EOculusXRSpaceComponentType ToComponentType(XrSpaceComponentTypeFB XrComponentType);
OCULUSXRANCHORS_API XrSpaceComponentTypeFB ToComponentType(EOculusXRSpaceComponentType ComponentType);
OCULUSXRANCHORS_API EOculusXRSpaceStorageLocation ToStorageLocation(XrSpaceStorageLocationFB XrStorageLocation);
OCULUSXRANCHORS_API XrSpaceStorageLocationFB ToStorageLocation(EOculusXRSpaceStorageLocation StorageLocation);
OCULUSXRANCHORS_API FOculusXRUUID ToUuid(const XrUuidEXT& XrUuid);
OCULUSXRANCHORS_API XrUuidEXT ToUuid(const FOculusXRUUID& Uuid);
OCULUSXRANCHORS_API FString GetStringFromResult(EOculusXRAnchorResult::Type Result);
OCULUSXRANCHORS_API FString ToString(EOculusXRSpaceComponentType ComponentType);
OCULUSXRANCHORS_API FString ToString(EOculusXRSpaceStorageLocation StorageLocation);
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,28 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRSpatialAnchorComponent.h"
DEFINE_LOG_CATEGORY(LogOculusSpatialAnchor);
UOculusXRSpatialAnchorComponent::UOculusXRSpatialAnchorComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
bool UOculusXRSpatialAnchorComponent::Create(const FTransform& NewAnchorTransform, AActor* OwningActor, const FOculusXRSpatialAnchorCreateDelegate& Callback)
{
EOculusXRAnchorResult::Type AnchorResult;
return OculusXRAnchors::FOculusXRAnchors::CreateSpatialAnchor(NewAnchorTransform, OwningActor, Callback, AnchorResult);
}
bool UOculusXRSpatialAnchorComponent::Erase(const FOculusXRAnchorEraseDelegate& Callback)
{
EOculusXRAnchorResult::Type AnchorResult;
return OculusXRAnchors::FOculusXRAnchors::EraseAnchor(this, Callback, AnchorResult);
}
bool UOculusXRSpatialAnchorComponent::Save(EOculusXRSpaceStorageLocation Location, const FOculusXRAnchorSaveDelegate& Callback)
{
EOculusXRAnchorResult::Type AnchorResult;
return OculusXRAnchors::FOculusXRAnchors::SaveAnchor(this, Location, Callback, AnchorResult);
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#include "OculusXRSpatialAnchorManager.h"
#include "OculusXRAnchorBPFunctionLibrary.h"
namespace OculusXRAnchors
{
bool FOculusXRSpatialAnchorManager::CreateSpatialAnchor(const FTransform& InTransform, uint64& OutRequestId)
{
EOculusXRAnchorResult::Type Result = CreateAnchor(InTransform, OutRequestId, FTransform::Identity);
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(Result);
}
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,19 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "CoreMinimal.h"
#include "OculusXRAnchorManager.h"
namespace OculusXRAnchors
{
struct FOculusXRSpatialAnchorManager : FOculusXRAnchorManager
{
FOculusXRSpatialAnchorManager()
: FOculusXRAnchorManager()
{
}
static bool CreateSpatialAnchor(const FTransform& InTransform, uint64& OutRequestId);
};
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,24 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRTelemetry.h"
namespace OculusXRTelemetry::Events
{
using FAnchorsCreate = TMarker<191967648>;
using FAnchorsCreateRequest = TScopedMarker<FAnchorsCreate, EScopeMode::Start>;
using FAnchorsCreateResponse = TScopedMarker<FAnchorsCreate, EScopeMode::End>;
using FAnchorsSetComponentStatus = TMarker<191962330>;
using FAnchorsSetComponentStatusRequest = TScopedMarker<FAnchorsSetComponentStatus, EScopeMode::Start>;
using FAnchorsSetComponentStatusResponse = TScopedMarker<FAnchorsSetComponentStatus, EScopeMode::End>;
using FAnchorsSave = TMarker<191961984>;
using FAnchorsSaveRequest = TScopedMarker<FAnchorsSave, EScopeMode::Start>;
using FAnchorsSaveResponse = TScopedMarker<FAnchorsSave, EScopeMode::End>;
using FAnchorsQuery = TMarker<191959258>;
using FAnchorsQueryRequest = TScopedMarker<FAnchorsQuery, EScopeMode::Start>;
using FAnchorsQueryResponse = TScopedMarker<FAnchorsQuery, EScopeMode::End>;
using FAnchorsErase = TMarker<191960591>;
using FAnchorsEraseRequest = TScopedMarker<FAnchorsErase, EScopeMode::Start>;
using FAnchorsEraseResponse = TScopedMarker<FAnchorsErase, EScopeMode::End>;
} // namespace OculusXRTelemetry::Events

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,110 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAnchorsXRIncludes.h"
#include "IOpenXRExtensionPlugin.h"
#include "OculusXRAnchorTypes.h"
#define LOCTEXT_NAMESPACE "OculusXRAnchors"
class FOpenXRHMD;
namespace XRAnchors
{
extern PFN_xrCreateSpatialAnchorFB xrCreateSpatialAnchorFB;
extern PFN_xrSetSpaceComponentStatusFB xrSetSpaceComponentStatusFB;
extern PFN_xrGetSpaceComponentStatusFB xrGetSpaceComponentStatusFB;
extern PFN_xrEnumerateSpaceSupportedComponentsFB xrEnumerateSpaceSupportedComponentsFB;
extern PFN_xrGetSpaceUuidFB xrGetSpaceUuidFB;
extern PFN_xrGetSpaceContainerFB xrGetSpaceContainerFB;
extern PFN_xrQuerySpacesFB xrQuerySpacesFB;
extern PFN_xrRetrieveSpaceQueryResultsFB xrRetrieveSpaceQueryResultsFB;
extern PFN_xrShareSpacesFB xrShareSpacesFB;
extern PFN_xrShareSpacesMETA xrShareSpacesMETA;
extern PFN_xrSaveSpaceFB xrSaveSpaceFB;
extern PFN_xrEraseSpaceFB xrEraseSpaceFB;
extern PFN_xrSaveSpaceListFB xrSaveSpaceListFB;
extern PFN_xrCreateSpaceUserFB xrCreateSpaceUserFB;
extern PFN_xrDestroySpaceUserFB xrDestroySpaceUserFB;
extern PFN_xrGetSpaceUserIdFB xrGetSpaceUserIdFB;
extern PFN_xrSaveSpacesMETA xrSaveSpacesMETA;
extern PFN_xrEraseSpacesMETA xrEraseSpacesMETA;
extern PFN_xrDiscoverSpacesMETA xrDiscoverSpacesMETA;
extern PFN_xrRetrieveSpaceDiscoveryResultsMETA xrRetrieveSpaceDiscoveryResultsMETA;
class FAnchorsXR : public IOpenXRExtensionPlugin
{
public:
// IOculusXROpenXRHMDPlugin
virtual bool GetRequiredExtensions(TArray<const ANSICHAR*>& OutExtensions) override;
virtual bool GetOptionalExtensions(TArray<const ANSICHAR*>& OutExtensions) override;
virtual const void* OnCreateInstance(class IOpenXRHMDModule* InModule, const void* InNext) override;
virtual const void* OnCreateSession(XrInstance InInstance, XrSystemId InSystem, const void* InNext) override;
virtual void OnDestroySession(XrSession InSession) override;
virtual void OnEvent(XrSession InSession, const XrEventDataBaseHeader* InHeader) override;
public:
FAnchorsXR();
virtual ~FAnchorsXR();
void RegisterAsOpenXRExtension();
bool IsAnchorExtensionSupported() const { return bExtAnchorsEnabled; }
bool IsContainerExtensionSupported() const { return bExtContainerEnabled; }
bool IsQueryExtensionSupported() const { return bExtQueryEnabled; }
bool IsSharingExtensionSupported() const { return bExtSharingEnabled; }
bool IsStorageExtensionSupported() const { return bExtStorageEnabled; }
bool IsStorageBatchExtensionSupported() const { return bExtStorageBatchEnabled; }
bool IsUserExtensionSupported() const { return bExtUserEnabled; }
bool IsDiscoveryExtensionSupported() const { return bExtDiscoveryEnabled; }
bool IsPersistenceExtensionSupported() const { return bExtPersistenceEnabled; }
bool IsSharingMetaExtensionSupported() const { return bExtSharingMetaEnabled; }
bool IsGroupSharingExtensionSupported() const { return bExtGroupSharingEnabled; }
XrResult CreateSpatialAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform);
XrResult DestroySpatialAnchor(uint64 AnchorHandle);
XrResult TryGetAnchorTransform(uint64 AnchorHandle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space);
XrResult SetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool Enable, float Timeout, uint64& OutRequestId);
XrResult GetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool& OutEnabled, bool& OutChangePending);
XrResult GetSupportedAnchorComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes);
XrResult GetAnchorContainerUUIDs(uint64 AnchorHandle, TArray<FOculusXRUUID>& OutUUIDs);
XrResult SaveAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId);
XrResult SaveAnchorList(const TArray<uint64>& AnchorHandles, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId);
XrResult SaveAnchors(const TArray<uint64>& AnchorHandles, uint64& OutRequestId);
XrResult DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, uint64& OutRequestId);
XrResult QueryAnchors(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId);
XrResult ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<uint64>& UserIds, uint64& OutRequestId);
XrResult ShareAnchorsWithGroups(const TArray<uint64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, uint64& OutRequestId);
XrResult CreateSpaceUser(uint64 SpaceUserId, SpaceUser& OutUser);
XrResult GetSpaceUserId(const SpaceUser& User, uint64& OutId);
XrResult DestroySpaceUser(const SpaceUser& User);
XrResult EraseAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId);
XrResult EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& UUIDs, uint64& OutRequestId);
private:
void InitOpenXRFunctions(XrInstance InInstance);
bool bExtAnchorsEnabled;
bool bExtContainerEnabled;
bool bExtQueryEnabled;
bool bExtSharingEnabled;
bool bExtStorageEnabled;
bool bExtStorageBatchEnabled;
bool bExtUserEnabled;
bool bExtDiscoveryEnabled;
bool bExtPersistenceEnabled;
bool bExtSharingMetaEnabled;
bool bExtGroupSharingEnabled;
FOpenXRHMD* OpenXRHMD;
};
} // namespace XRAnchors
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,9 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include <khronos/openxr/openxr.h>
#include <khronos/openxr/meta_openxr_preview/meta_spatial_entity_discovery.h>
#include <khronos/openxr/meta_openxr_preview/meta_spatial_entity_persistence.h>
#include <khronos/openxr/meta_openxr_preview/meta_spatial_entity_sharing.h>
#include <khronos/openxr/meta_openxr_preview/meta_spatial_entity_group_sharing.h>

View File

@@ -0,0 +1,50 @@
// @lint-ignore-every LICENSELINT
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Modules/ModuleManager.h"
#include "OculusXRAnchorTypes.h"
#include "OculusXRAnchorComponents.h"
#define OCULUS_ANCHORS_SUPPORTED_PLATFORMS (PLATFORM_WINDOWS && WINVER > 0x0502) || (PLATFORM_ANDROID_ARM || PLATFORM_ANDROID_ARM64 || PLATFORM_ANDROID_X64)
class UOculusXRBaseAnchorComponent;
class IOculusXRCreateAnchorComponent
{
public:
virtual UOculusXRBaseAnchorComponent* TryCreateAnchorComponent(uint64 AnchorHandle, EOculusXRSpaceComponentType Type, UObject* Outer) = 0;
};
/**
* The public interface to this module. In most cases, this interface is only public to sibling modules
* within this plugin.
*/
class IOculusXRAnchorsModule : public IModuleInterface
{
public:
/**
* Singleton-like access to this module's interface. This is just for convenience!
* Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
*
* @return Returns singleton instance, loading the module on demand if needed
*/
static inline IOculusXRAnchorsModule& Get()
{
return FModuleManager::LoadModuleChecked<IOculusXRAnchorsModule>("OculusXRAnchors");
}
/**
* Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true.
*
* @return True if the module is loaded and ready to use
*/
static inline bool IsAvailable()
{
return FModuleManager::Get().IsModuleLoaded("OculusXRAnchors");
}
virtual void AddCreateAnchorComponentInterface(IOculusXRCreateAnchorComponent* CastInterface) = 0;
virtual void RemoveCreateAnchorComponentInterface(IOculusXRCreateAnchorComponent* CastInterface) = 0;
virtual UOculusXRBaseAnchorComponent* CreateAnchorComponent(uint64 AnchorHandle, EOculusXRSpaceComponentType Type, UObject* Outer) = 0;
};

View File

@@ -0,0 +1,62 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "OculusXRAnchorTypes.h"
#include "OculusXRAnchorComponents.h"
#include "OculusXRAnchorBPFunctionLibrary.generated.h"
// Helper
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAnchorBPFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Spawn Oculus Anchor Actor", WorldContext = "WorldContextObject", UnsafeDuringActorConstruction = "true"), Category = "OculusXR|SpatialAnchor")
static AActor* SpawnActorWithAnchorHandle(UObject* WorldContextObject, FOculusXRUInt64 Handle, FOculusXRUUID UUID, EOculusXRSpaceStorageLocation AnchorLocation, UClass* ActorClass, AActor* Owner, APawn* Instigator, ESpawnActorCollisionHandlingMethod CollisionHandlingMethod);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Spawn Oculus Anchor Actor From Query", WorldContext = "WorldContextObject", UnsafeDuringActorConstruction = "true"), Category = "OculusXR|SpatialAnchor")
static AActor* SpawnActorWithAnchorQueryResults(UObject* WorldContextObject, const FOculusXRSpaceQueryResult& QueryResult, UClass* ActorClass, AActor* Owner, APawn* Instigator, ESpawnActorCollisionHandlingMethod CollisionHandlingMethod);
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
static bool GetAnchorComponentStatus(AActor* TargetActor, EOculusXRSpaceComponentType ComponentType, bool& bIsEnabled);
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
static bool GetAnchorTransformByHandle(const FOculusXRUInt64& Handle, FTransform& OutTransform);
/**
* Try to get the anchors transform. The transform may not always be a available.
*
* @param Handle The Anchor handle.
* @param OutTransform (out) The anchors transform.
* @param OutLocationFlags (out) The location flags.
* @param Space The space in which this transform should be returned.
*
* @return Whether or not the transform could be retrieved.
*/
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
static bool TryGetAnchorTransformByHandle(const FOculusXRUInt64& Handle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space = EOculusXRAnchorSpace::World);
UFUNCTION(BlueprintPure, meta = (DisplayName = "FOculusXRUInt64 To String", CompactNodeTitle = "->", BlueprintAutocast), Category = "OculusXR|SpatialAnchor")
static FString AnchorHandleToString(const FOculusXRUInt64 Value);
UFUNCTION(BlueprintPure, meta = (DisplayName = "FOculusXRUUID To String", CompactNodeTitle = "->", BlueprintAutocast), Category = "OculusXR|SpatialAnchor")
static FString AnchorUUIDToString(const FOculusXRUUID& Value);
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
static FOculusXRUUID StringToAnchorUUID(const FString& Value);
UFUNCTION(BlueprintPure, meta = (DisplayName = "FOculusXRUInt64 equal", CompactNodeTitle = "==", Keywords = "equal", BlueprintAutocast), Category = "OculusXR|SpatialAnchor")
static bool IsEqual_FOculusXRUInt64(const FOculusXRUInt64 Left, const FOculusXRUInt64 Right) { return Left == Right; };
UFUNCTION(BlueprintPure, meta = (DisplayName = "FOculusXRUUID equal", CompactNodeTitle = "==", Keywords = "equal", BlueprintAutocast), Category = "OculusXR|SpatialAnchor")
static bool IsEqual_FOculusXRUUID(const FOculusXRUUID& Left, const FOculusXRUUID& Right) { return Left.IsEqual(Right); };
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
static bool IsAnchorResultSuccess(EOculusXRAnchorResult::Type result);
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
static const UOculusXRBaseAnchorComponent* GetAnchorComponent(const FOculusXRSpaceQueryResult& QueryResult, EOculusXRSpaceComponentType ComponentType, UObject* Outer);
};

View File

@@ -0,0 +1,56 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAnchorTypes.h"
#include "Components/ActorComponent.h"
#include "OculusXRAnchorComponent.generated.h"
UCLASS(meta = (DisplayName = "Oculus Anchor Component"))
class OCULUSXRANCHORS_API UOculusXRAnchorComponent : public UActorComponent
{
GENERATED_BODY()
public:
UOculusXRAnchorComponent(const FObjectInitializer& ObjectInitializer);
virtual void BeginPlay() override;
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
UFUNCTION(BlueprintPure, Category = "OculusXR|Anchor", meta = (DefaultToSelf = Target))
FOculusXRUInt64 GetHandle() const;
UFUNCTION(BlueprintCallable, Category = "OculusXR|Anchor", meta = (DefaultToSelf = Target))
void SetHandle(FOculusXRUInt64 Handle);
UFUNCTION(BlueprintPure, Category = "OculusXR|Anchor", meta = (DefaultToSelf = Target))
bool HasValidHandle() const;
UFUNCTION(BlueprintPure, Category = "OculusXR|Anchor", meta = (DefaultToSelf = Target))
FOculusXRUUID GetUUID() const;
void SetUUID(FOculusXRUUID NewUUID);
UFUNCTION(BlueprintPure, Category = "OculusXR|Anchor", meta = (DefaultToSelf = Target))
bool IsStoredAtLocation(EOculusXRSpaceStorageLocation Location) const;
// Not exposed to BP because this is managed in code
void SetStoredLocation(EOculusXRSpaceStorageLocation Location, bool Stored);
UFUNCTION(BlueprintPure, Category = "OculusXR|Anchor", meta = (DefaultToSelf = Target))
bool IsSaved() const;
protected:
bool bUpdateHeadSpaceTransform;
private:
FOculusXRUInt64 AnchorHandle;
FOculusXRUUID AnchorUUID;
int32 StorageLocations;
UPROPERTY()
class APlayerCameraManager* PlayerCameraManager;
void UpdateAnchorTransform() const;
bool ToWorldSpacePose(FTransform CameraTransform, FTransform& OutTrackingSpaceTransform) const;
};

View File

@@ -0,0 +1,82 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "UObject/Class.h"
#include "OculusXRAnchorTypes.h"
#include "OculusXRAnchorComponents.generated.h"
UCLASS(Blueprintable)
class OCULUSXRANCHORS_API UOculusXRBaseAnchorComponent : public UObject
{
GENERATED_BODY()
public:
template <typename T>
static T* FromSpace(uint64 space, UObject* Outer)
{
T* Component = NewObject<T>(Outer);
Component->Space = space;
return Component;
}
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
bool IsComponentEnabled() const;
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
EOculusXRSpaceComponentType GetType() const;
uint64 GetSpace() const;
protected:
uint64 Space;
EOculusXRSpaceComponentType Type = EOculusXRSpaceComponentType::Undefined;
};
UCLASS(Blueprintable)
class OCULUSXRANCHORS_API UOculusXRLocatableAnchorComponent : public UOculusXRBaseAnchorComponent
{
GENERATED_BODY()
public:
UOculusXRLocatableAnchorComponent()
{
Type = EOculusXRSpaceComponentType::Locatable;
}
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
bool GetTransform(FTransform& outTransform) const;
};
UCLASS(Blueprintable)
class OCULUSXRANCHORS_API UOculusXRSpaceContainerAnchorComponent : public UOculusXRBaseAnchorComponent
{
GENERATED_BODY()
public:
UOculusXRSpaceContainerAnchorComponent()
{
Type = EOculusXRSpaceComponentType::SpaceContainer;
}
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
bool GetUUIDs(TArray<FOculusXRUUID>& outUUIDs) const;
};
UCLASS(Blueprintable)
class OCULUSXRANCHORS_API UOculusXRSharableAnchorComponent : public UOculusXRBaseAnchorComponent
{
GENERATED_BODY()
public:
UOculusXRSharableAnchorComponent()
{
Type = EOculusXRSpaceComponentType::Sharable;
}
};
UCLASS(Blueprintable)
class OCULUSXRANCHORS_API UOculusXRStorableAnchorComponent : public UOculusXRBaseAnchorComponent
{
GENERATED_BODY()
public:
UOculusXRStorableAnchorComponent()
{
Type = EOculusXRSpaceComponentType::Storable;
}
};

View File

@@ -0,0 +1,165 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "CoreTypes.h"
#include "OculusXRAnchorTypes.h"
#include "Delegates/Delegate.h"
class FOculusXRAnchorEventDelegates
{
public:
/* ovrpEventType_SpatialAnchorCreateComplete
*
* SpatialAnchorCreateComplete
* Prefix:
* FOculusXRSpatialAnchorCreateComplete
* Suffix:
* FOculusXRSpatialAnchorCreateCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_FourParams(FOculusXRSpatialAnchorCreateCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/, FOculusXRUInt64 /*space*/, FOculusXRUUID /*uuid*/);
static OCULUSXRANCHORS_API FOculusXRSpatialAnchorCreateCompleteDelegate OculusSpatialAnchorCreateComplete;
/* ovrpEventType_SpaceSetComponentStatusComplete
*
* SpaceSetComponentStatusComplete
* Prefix:
* FOculusXRSpaceSetComponentStatusComplete
* Suffix:
* FOculusXRSpaceSetComponentStatusCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_SixParams(FOculusXRSpaceSetComponentStatusCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/, FOculusXRUInt64 /*space*/, FOculusXRUUID /*uuid*/, EOculusXRSpaceComponentType /*componenttype */, bool /*enabled*/);
static OCULUSXRANCHORS_API FOculusXRSpaceSetComponentStatusCompleteDelegate OculusSpaceSetComponentStatusComplete;
/* ovrpEventType_SpaceQueryResults
*
* SpaceQueryResults
* Prefix:
* FOculusXRSpaceQueryResults
* Suffix:
* FOculusXRSpaceQueryResultsDelegate
*/
DECLARE_MULTICAST_DELEGATE_OneParam(FOculusXRSpaceQueryResultsDelegate, FOculusXRUInt64 /*requestId*/);
static OCULUSXRANCHORS_API FOculusXRSpaceQueryResultsDelegate OculusSpaceQueryResults;
/* SpaceQueryResult (no ovrp event type)
*
* SpaceQueryResult
* Prefix:
* FOculusXRSpaceQueryResult
* Suffix:
* FOculusXRSpaceQueryResultDelegate
*/
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOculusXRSpaceQueryResultDelegate, FOculusXRUInt64 /*requestId*/, FOculusXRUInt64 /* space*/, FOculusXRUUID /*uuid*/);
static OCULUSXRANCHORS_API FOculusXRSpaceQueryResultDelegate OculusSpaceQueryResult;
/* ovrpEventType_SpaceQueryComplete
*
* SpaceQueryComplete
* Prefix:
* FOculusXRSpaceQueryComplete
* Suffix:
* FOculusXRSpaceQueryCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRSpaceQueryCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/);
static OCULUSXRANCHORS_API FOculusXRSpaceQueryCompleteDelegate OculusSpaceQueryComplete;
/* ovrpEventType_SpaceSaveComplete
*
* SpaceSaveComplete
* Prefix:
* FOculusXRSpaceSaveComplete
* Suffix:
* FOculusXRSpaceSaveCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_FiveParams(FOculusXRSpaceSaveCompleteDelegate, FOculusXRUInt64 /*requestId*/, FOculusXRUInt64 /* space*/, bool /* sucess*/, EOculusXRAnchorResult::Type /*result*/, FOculusXRUUID /*uuid*/);
static OCULUSXRANCHORS_API FOculusXRSpaceSaveCompleteDelegate OculusSpaceSaveComplete;
/* ovrpEventType_SpaceListSaveResult
*
* SpaceListSaveComplete
* Prefix:
* FOculusSpaceListSaveComplete
* Suffix:
* FOculusSpaceListSaveCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRSpaceListSaveCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/);
static OCULUSXRANCHORS_API FOculusXRSpaceListSaveCompleteDelegate OculusSpaceListSaveComplete;
/* ovrpEventType_SpaceEraseComplete
*
* SpaceEraseComplete
* Prefix:
* FOculusXRSpaceEraseComplete
* Suffix:
* FOculusXRSpaceEraseCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_FourParams(FOculusXRSpaceEraseCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /* result*/, FOculusXRUUID /*uuid*/, EOculusXRSpaceStorageLocation /*location*/);
static OCULUSXRANCHORS_API FOculusXRSpaceEraseCompleteDelegate OculusSpaceEraseComplete;
/* ovrpEventType_SpaceShareSpaceResult
*
* SpaceShareComplete
* Prefix:
* FOculusSpaceShareSpacesComplete
* Suffix:
* FOculusSpaceShareSpacesCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRSpaceShareCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/);
static OCULUSXRANCHORS_API FOculusXRSpaceShareCompleteDelegate OculusSpaceShareComplete;
/* ovrpEventType_SpaceDiscoveryComplete
*
* SpaceDiscoveryComplete
* Prefix:
* FOculusXRSpaceDiscoveryComplete
* Suffix:
* FOculusXRDiscoverSpacesCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRAnchorsDiscoverCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/);
static OCULUSXRANCHORS_API FOculusXRAnchorsDiscoverCompleteDelegate OculusAnchorsDiscoverComplete;
/* ovrpEventType_SpaceDiscoveryResultsAvailable
*
* SpaceDiscoveryResults
* Prefix:
* FOculusXRAnchorsDiscoverResults
* Suffix:
* FOculusXRAnchorsDiscoverResultsDelegate
*/
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRAnchorsDiscoverResultsDelegate, FOculusXRUInt64 /*requestId*/, const TArray<FOculusXRAnchorsDiscoverResult>& /*results*/);
static OCULUSXRANCHORS_API FOculusXRAnchorsDiscoverResultsDelegate OculusAnchorsDiscoverResults;
/* ovrpEventType_SpacesSaveResult
*
* SpacesSaveComplete
* Prefix:
* FOculusXRAnchorsSaveComplete
* Suffix:
* FOculusXRAnchorsSaveCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRAnchorsSaveCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/);
static OCULUSXRANCHORS_API FOculusXRAnchorsSaveCompleteDelegate OculusAnchorsSaveComplete;
/* ovrpEventType_SpacesEraseResult
*
* SpacesEraseResult
* Prefix:
* FOculusXRAnchorsEraseComplete
* Suffix:
* FOculusXRAnchorsEraseCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRAnchorsEraseCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/);
static OCULUSXRANCHORS_API FOculusXRAnchorsEraseCompleteDelegate OculusAnchorsEraseComplete;
/* ovrpEventType_SpaceShareSpaceResult
*
* ShareAnchorsComplete
* Prefix:
* FOculusXRShareAnchorsComplete
* Suffix:
* FOculusXRShareAnchorsCompleteDelegate
*/
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRShareAnchorsCompleteDelegate, FOculusXRUInt64 /*requestId*/, EOculusXRAnchorResult::Type /*result*/);
static OCULUSXRANCHORS_API FOculusXRShareAnchorsCompleteDelegate OculusShareAnchorsComplete;
};

View File

@@ -0,0 +1,40 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAnchorTypes.h"
class OCULUSXRANCHORS_API IOculusXRAnchorFunctions
{
public:
virtual EOculusXRAnchorResult::Type CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform) = 0;
virtual EOculusXRAnchorResult::Type DestroyAnchor(uint64 AnchorHandle) = 0;
/**
* Try to get the anchors transform. The transform may not always be a available.
*
* @param AnchorHandle The Anchor handle.
* @param OutTransform (out) The anchors transform.
* @param OutLocationFlags (out) The location flags.
* @param Space The space in which this transform should be returned.
*
* @return Whether or not the transform could be retrieved.
*/
virtual EOculusXRAnchorResult::Type TryGetAnchorTransform(uint64 AnchorHandle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags, EOculusXRAnchorSpace Space) = 0;
virtual EOculusXRAnchorResult::Type SetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool Enable, float Timeout, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type GetAnchorComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType ComponentType, bool& OutEnabled, bool& OutChangePending) = 0;
virtual EOculusXRAnchorResult::Type GetSupportedAnchorComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes) = 0;
virtual EOculusXRAnchorResult::Type GetAnchorContainerUUIDs(uint64 AnchorHandle, TArray<FOculusXRUUID>& OutUUIDs) = 0;
virtual EOculusXRAnchorResult::Type SaveAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type SaveAnchorList(const TArray<uint64>& AnchorHandles, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type SaveAnchors(const TArray<uint64>& AnchorHandles, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type QueryAnchors(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<uint64>& UserIds, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type EraseAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId) = 0;
virtual EOculusXRAnchorResult::Type EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& UUIDs, uint64& OutRequestId) = 0;
};

View File

@@ -0,0 +1,445 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "Kismet/BlueprintAsyncActionBase.h"
#include "Templates/SharedPointer.h"
#include "OculusXRAnchors.h"
#include "OculusXRAnchorTypes.h"
#include "OculusXRAnchorComponent.h"
#include "OculusXRAnchorComponents.h"
#include "OculusXRAnchorLatentActions.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOculusXR_LatentAction_CreateSpatialAnchor_Success, UOculusXRAnchorComponent*, Anchor, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_CreateSpatialAnchor_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOculusXR_LatentAction_EraseAnchor_Success, AActor*, Actor, FOculusXRUUID, UUID, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_EraseAnchor_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOculusXR_LatentAction_SaveAnchor_Success, UOculusXRAnchorComponent*, Anchor, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_SaveAnchor_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOculusXR_LatentAction_SaveAnchorList_Success, const TArray<UOculusXRAnchorComponent*>&, Anchors, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_SaveAnchorList_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOculusXR_LatentAction_QueryAnchors_Success, const TArray<FOculusXRSpaceQueryResult>&, QueryResults, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_QueryAnchors_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FOculusXR_LatentAction_SetComponentStatus_Success, UOculusXRAnchorComponent*, Anchor, EOculusXRSpaceComponentType, ComponentType, bool, Enabled, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_SetComponentStatus_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOculusXR_LatentAction_SetAnchorComponentStatus_Success, UOculusXRBaseAnchorComponent*, Component, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_SetAnchorComponentStatus_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOculusXR_LatentAction_ShareAnchors_Success, const TArray<UOculusXRAnchorComponent*>&, SharedAnchors, const TArray<FString>&, UserIds, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_ShareAnchors_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOculusXR_LatentAction_SaveAnchors_Success, const TArray<UOculusXRAnchorComponent*>&, Anchors, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_SaveAnchors_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FOculusXR_LatentAction_EraseAnchors_Success, const TArray<UOculusXRAnchorComponent*>&, Anchors, const TArray<FOculusXRUInt64>&, AnchorHandles, const TArray<FOculusXRUUID>&, UUIDs, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_EraseAnchors_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_DiscoverAnchors_Discovered, const TArray<FOculusXRAnchorsDiscoverResult>&, DiscoveryResult);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_DiscoverAnchors_Complete, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_DiscoverAnchors_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOculusXR_LatentAction_GetSharedAnchors_Success, const TArray<FOculusXRAnchorsDiscoverResult>&, SharedAnchors, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOculusXR_LatentAction_GetSharedAnchors_Failure, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FOculusXR_LatentAction_ShareAnchorsWithGroups_Complete, bool, Success, const TArray<FOculusXRUUID>&, Groups, const TArray<FOculusXRUInt64>&, AnchorHandles, EOculusXRAnchorResult::Type, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOculusXR_LatentAction_GetSharedAnchorsFromGroup_Complete, bool, Success, const TArray<FOculusXRAnchor>&, Anchors, EOculusXRAnchorResult::Type, Result);
//
// Create Anchor
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_CreateSpatialAnchor : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_CreateSpatialAnchor* OculusXRAsyncCreateSpatialAnchor(AActor* TargetActor, const FTransform& AnchorTransform);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_CreateSpatialAnchor_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_CreateSpatialAnchor_Failure Failure;
// Target actor
UPROPERTY(Transient)
AActor* TargetActor;
FTransform AnchorTransform;
private:
void HandleCreateComplete(EOculusXRAnchorResult::Type CreateResult, UOculusXRAnchorComponent* Anchor);
};
//
// Erase Anchor
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_EraseAnchor : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_EraseAnchor* OculusXRAsyncEraseAnchor(AActor* TargetActor);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_EraseAnchor_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_EraseAnchor_Failure Failure;
// Target actor
UPROPERTY(Transient)
AActor* TargetActor;
FOculusXRUInt64 DeleteRequestId;
private:
void HandleEraseAnchorComplete(EOculusXRAnchorResult::Type EraseResult, FOculusXRUUID UUID);
};
//
// Save Anchor
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_SaveAnchor : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_SaveAnchor* OculusXRAsyncSaveAnchor(AActor* TargetActor, EOculusXRSpaceStorageLocation StorageLocation);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SaveAnchor_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SaveAnchor_Failure Failure;
// Target actor
UPROPERTY(Transient)
AActor* TargetActor;
EOculusXRSpaceStorageLocation StorageLocation;
private:
void HandleSaveAnchorComplete(EOculusXRAnchorResult::Type SaveResult, UOculusXRAnchorComponent* Anchor);
};
//
// Save Anchor List
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_SaveAnchorList : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_SaveAnchorList* OculusXRAsyncSaveAnchorList(const TArray<AActor*>& TargetActors, EOculusXRSpaceStorageLocation StorageLocation);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SaveAnchorList_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SaveAnchorList_Failure Failure;
UPROPERTY(Transient)
TArray<UOculusXRAnchorComponent*> TargetAnchors;
EOculusXRSpaceStorageLocation StorageLocation;
private:
void HandleSaveAnchorListComplete(EOculusXRAnchorResult::Type SaveResult, const TArray<UOculusXRAnchorComponent*>& SavedSpaces);
};
//
// Query Anchors
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_QueryAnchors : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_QueryAnchors* OculusXRAsyncQueryAnchors(EOculusXRSpaceStorageLocation Location, const TArray<FOculusXRUUID>& UUIDs);
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_QueryAnchors* OculusXRAsyncQueryAnchorsAdvanced(const FOculusXRSpaceQueryInfo& QueryInfo);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_QueryAnchors_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_QueryAnchors_Failure Failure;
FOculusXRSpaceQueryInfo QueryInfo;
TArray<FOculusXRSpaceQueryResult> QueryResults;
private:
void HandleQueryAnchorsResults(EOculusXRAnchorResult::Type QueryResult, const TArray<FOculusXRSpaceQueryResult>& Results);
};
//
// Set Component Status
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_SetAnchorComponentStatus : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_SetAnchorComponentStatus* OculusXRAsyncSetAnchorComponentStatus(AActor* TargetActor, EOculusXRSpaceComponentType ComponentType, bool bEnabled);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SetComponentStatus_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SetComponentStatus_Failure Failure;
// Target actor
UPROPERTY(Transient)
AActor* TargetActor;
UPROPERTY(Transient)
UOculusXRAnchorComponent* TargetAnchorComponent;
EOculusXRSpaceComponentType ComponentType;
bool bEnabled;
private:
void HandleSetComponentStatusComplete(EOculusXRAnchorResult::Type SetStatusResult, uint64 AnchorHandle, EOculusXRSpaceComponentType SpaceComponentType, bool bResultEnabled);
};
//
// Set Anchor Component Status
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_SetComponentStatus : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_SetComponentStatus* OculusXRAsyncSetComponentStatus(UOculusXRBaseAnchorComponent* Component, bool bEnabled);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SetAnchorComponentStatus_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SetAnchorComponentStatus_Failure Failure;
// Target actor
UPROPERTY(Transient)
UOculusXRBaseAnchorComponent* Component;
bool bEnabled;
private:
void HandleSetComponentStatusComplete(EOculusXRAnchorResult::Type SetStatusResult, uint64 AnchorHandle, EOculusXRSpaceComponentType SpaceComponentType, bool bResultEnabled);
};
//
// Share Anchors
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_ShareAnchors : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_ShareAnchors* OculusXRAsyncShareAnchors(const TArray<AActor*>& TargetActors, const TArray<FString>& ToShareWithIds);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_ShareAnchors_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_ShareAnchors_Failure Failure;
// Target Spaces
UPROPERTY(Transient)
TArray<UOculusXRAnchorComponent*> TargetAnchors;
// Users to share with
TArray<uint64> ToShareWithIds;
FOculusXRUInt64 ShareSpacesRequestId;
private:
void HandleShareAnchorsComplete(EOculusXRAnchorResult::Type ShareResult, const TArray<UOculusXRAnchorComponent*>& TargetAnchors, const TArray<uint64>& OculusUserIds);
};
//
// Save Anchors
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_SaveAnchors : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_SaveAnchors* OculusXRAsyncSaveAnchors(const TArray<AActor*>& TargetActors);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SaveAnchors_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_SaveAnchors_Failure Failure;
UPROPERTY(Transient)
TArray<UOculusXRAnchorComponent*> TargetAnchors;
private:
void HandleSaveAnchorsComplete(EOculusXRAnchorResult::Type SaveResult, const TArray<UOculusXRAnchorComponent*>& SavedSpaces);
};
//
// Erase Anchors
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_EraseAnchors : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", AutoCreateRefTerm = "TargetActors,AnchorHandles,AnchorUUIDs"))
static UOculusXRAsyncAction_EraseAnchors* OculusXRAsyncEraseAnchors(const TArray<AActor*>& TargetActors, const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& AnchorUUIDs);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_EraseAnchors_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_EraseAnchors_Failure Failure;
UPROPERTY(Transient)
TArray<UOculusXRAnchorComponent*> TargetAnchors;
TArray<FOculusXRUInt64> TargetAnchorHandles;
TArray<FOculusXRUUID> TargetUUIDs;
private:
void HandleEraseAnchorsComplete(EOculusXRAnchorResult::Type EraseResult, const TArray<UOculusXRAnchorComponent*>& ErasedAnchorComponents, const TArray<FOculusXRUInt64>& ErasedAnchorHandles, const TArray<FOculusXRUUID>& ErasedAnchorUUIDs);
};
//
// Anchors Discovery
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_DiscoverAnchors : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_DiscoverAnchors* OculusXRAsyncDiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_DiscoverAnchors_Discovered Discovered;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_DiscoverAnchors_Complete Complete;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_DiscoverAnchors_Failure Failure;
UPROPERTY(Transient)
FOculusXRSpaceDiscoveryInfo DiscoveryInfo;
private:
void HandleDiscoverResult(const TArray<FOculusXRAnchorsDiscoverResult>& DiscoveredAnchors);
void HandleDiscoverComplete(EOculusXRAnchorResult::Type CompleteResult);
};
//
// Get Shared Anchors
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_GetSharedAnchors : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_GetSharedAnchors* OculusXRAsyncGetSharedAnchors(const TArray<FOculusXRUUID>& AnchorUUIDs);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_GetSharedAnchors_Success Success;
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_GetSharedAnchors_Failure Failure;
UPROPERTY(Transient)
TArray<FOculusXRUUID> Anchors;
private:
void HandleGetSharedAnchorsResult(EOculusXRAnchorResult::Type Result, const TArray<FOculusXRAnchorsDiscoverResult>& SharedAnchors);
};
//
// Share with groups
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_ShareAnchorsWithGroups : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
static UOculusXRAsyncAction_ShareAnchorsWithGroups* OculusXRShareAnchorsWithGroupsAsync(const TArray<FOculusXRUUID>& GroupUUIDs, const TArray<FOculusXRUInt64>& AnchorHandles);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_ShareAnchorsWithGroups_Complete Complete;
TArray<FOculusXRUUID> GroupUUIDs;
TArray<FOculusXRUInt64> AnchorHandles;
private:
void HandleShareComplete(const OculusXRAnchors::FShareAnchorsWithGroups::FResultType& Result);
};
//
// Get shared anchors from groups
//
UCLASS()
class OCULUSXRANCHORS_API UOculusXRAsyncAction_GetSharedAnchorsFromGroup : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
virtual void Activate() override;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", AutoCreateRefTerm = "GroupUUIDs,AnchorUUIDs"))
static UOculusXRAsyncAction_GetSharedAnchorsFromGroup* OculusXRGetSharedAnchorsFromGroupAsync(const FOculusXRUUID& GroupUUIDs, const TArray<FOculusXRUUID>& AnchorUUIDs);
UPROPERTY(BlueprintAssignable)
FOculusXR_LatentAction_GetSharedAnchorsFromGroup_Complete Complete;
FOculusXRUUID GroupUuid;
TArray<FOculusXRUUID> Anchors;
private:
void HandleGetSharedAnchorsComplete(const OculusXRAnchors::FGetAnchorsSharedWithGroup::FResultType& Result);
};

View File

@@ -0,0 +1,432 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include <memory>
#include "OculusXRAnchorTypes.generated.h"
#define OCULUSXR_UUID_SIZE 16
typedef uint8 UuidArray[OCULUSXR_UUID_SIZE];
typedef uint64 SpaceUser;
UENUM(BlueprintType)
namespace EOculusXRAnchorResult
{
enum Type
{
Success = 0,
Success_EventUnavailable = 1,
Success_Pending = 2,
/// Failure
Failure = -1000,
Failure_InvalidParameter = -1001,
Failure_NotInitialized = -1002,
Failure_InvalidOperation = -1003,
Failure_Unsupported = -1004,
Failure_NotYetImplemented = -1005,
Failure_OperationFailed = -1006,
Failure_InsufficientSize = -1007,
Failure_DataIsInvalid = -1008,
Failure_DeprecatedOperation = -1009,
Failure_ErrorLimitReached = -1010,
Failure_ErrorInitializationFailed = -1011,
/// Space error cases
Failure_SpaceCloudStorageDisabled = -2000,
Failure_SpaceMappingInsufficient = -2001,
Failure_SpaceLocalizationFailed = -2002,
Failure_SpaceNetworkTimeout = -2003,
Failure_SpaceNetworkRequestFailed = -2004,
/// APD warnings and error cases
Failure_SpaceInsufficientResources = -9000,
Failure_SpaceStorageAtCapacity = -9001,
Failure_SpaceInsufficientView = -9002,
Failure_SpacePermissionInsufficient = -9003,
Failure_SpaceRateLimited = -9004,
Failure_SpaceTooDark = -9005,
Failure_SpaceTooBright = -9006,
// Boundary visibility
Warning_BoundaryVisibilitySuppressionNotAllowed = 9030,
};
} // namespace EOculusXRAnchorResult
UENUM(BlueprintType, meta = (Bitflags))
enum class EOculusLocationFlags : uint8
{
None = 0, // required for the metadata generation
OrientationValid = (1 << 0),
PositionValid = (1 << 1),
OrientationTracked = (1 << 2),
PositionTracked = (1 << 3)
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRAnchorLocationFlags
{
GENERATED_BODY()
public:
FOculusXRAnchorLocationFlags(uint32 InFlags = 0)
: Flags(InFlags) {}
bool OrientationValid() const
{
return Flags & static_cast<uint32>(EOculusLocationFlags::OrientationValid);
}
bool PositionValid() const
{
return Flags & static_cast<uint32>(EOculusLocationFlags::PositionValid);
}
bool OrientationTracked() const
{
return Flags & static_cast<uint32>(EOculusLocationFlags::OrientationTracked);
}
bool PositionTracked() const
{
return Flags & static_cast<uint32>(EOculusLocationFlags::PositionTracked);
}
bool IsValid() const
{
return OrientationValid() && PositionValid();
}
private:
UPROPERTY(BlueprintReadOnly, Category = "OculusXR|SpatialAnchor", meta = (AllowPrivateAccess = "true", Bitmask, BitmaskEnum = "EOculusLocationFlags"))
int32 Flags;
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRUUID
{
GENERATED_BODY()
FOculusXRUUID();
FOculusXRUUID(const UuidArray& In);
bool operator==(const FOculusXRUUID& Other) const;
bool operator!=(const FOculusXRUUID& Other) const;
bool IsValidUUID() const;
bool IsEqual(const FOculusXRUUID& Other) const;
friend uint32 GetTypeHash(const FOculusXRUUID& Other) { return FCrc::MemCrc32(&Other.UUIDBytes, sizeof(Other.UUIDBytes)); }
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess);
OCULUSXRANCHORS_API friend FArchive& operator<<(FArchive& Ar, FOculusXRUUID& UUID);
bool Serialize(FArchive& Ar);
FString ToString() const;
uint8 UUIDBytes[OCULUSXR_UUID_SIZE];
};
template <>
struct TStructOpsTypeTraits<FOculusXRUUID> : public TStructOpsTypeTraitsBase2<FOculusXRUUID>
{
enum
{
WithIdenticalViaEquality = true,
WithNetSerializer = true,
WithSerializer = true
};
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRUInt64
{
GENERATED_BODY()
FOculusXRUInt64()
: FOculusXRUInt64(0) {}
FOculusXRUInt64(const uint64& Value) { this->Value = Value; }
operator uint64() const { return Value; }
bool operator==(const FOculusXRUInt64& Right) const;
bool operator!=(const FOculusXRUInt64& Right) const;
UPROPERTY()
uint64 Value;
bool IsEqual(const FOculusXRUInt64& Other) const
{
return Other.Value == Value;
}
friend uint32 GetTypeHash(const FOculusXRUInt64& Other)
{
return FCrc::MemCrc_DEPRECATED(&Other.Value, sizeof(Other.Value));
}
uint64 GetValue() const { return Value; };
void SetValue(const uint64 Val) { Value = Val; };
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRAnchor
{
GENERATED_BODY()
public:
FOculusXRAnchor()
: AnchorHandle(0), Uuid() {}
FOculusXRAnchor(FOculusXRUInt64 SpaceHandle, FOculusXRUUID ID)
: AnchorHandle(SpaceHandle), Uuid(ID) {}
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
FOculusXRUInt64 AnchorHandle;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
FOculusXRUUID Uuid;
};
template <>
struct TStructOpsTypeTraits<FOculusXRUInt64> : public TStructOpsTypeTraitsBase2<FOculusXRUInt64>
{
enum
{
WithIdenticalViaEquality = true,
};
};
UENUM(BlueprintType)
enum class EOculusXRSpaceQueryFilterType : uint8
{
None = 0 UMETA(DisplayName = "No Filter"),
FilterByIds = 1 UMETA(DisplayName = "Filter queries by UUIDs"),
FilterByComponentType = 2 UMETA(DisplayName = "Filter queries by component type"),
FilterByGroup = 3 UMETA(DisplayName = "Filter queries by group UUID")
};
// This is used as a bit-mask
UENUM(BlueprintType)
enum class EOculusXRSpaceStorageLocation : uint8
{
Invalid = 0 UMETA(DisplayName = "Invalid"),
Local = 1 << 0 UMETA(DisplayName = "Local"),
Cloud = 1 << 1 UMETA(DisplayName = "Cloud")
};
UENUM(BlueprintType)
enum class EOculusXRSpaceStoragePersistenceMode : uint8
{
Invalid = 0 UMETA(Hidden),
Indefinite = 1 UMETA(DisplayName = "Indefinite"),
};
UENUM(BlueprintType)
enum class EOculusXRSpaceComponentType : uint8
{
Locatable = 0 UMETA(DisplayName = "Locatable"),
Storable = 1 UMETA(DisplayName = "Storable"),
Sharable = 2 UMETA(DisplayName = "Sharable"),
ScenePlane = 3 UMETA(DisplayName = "ScenePlane"),
SceneVolume = 4 UMETA(DisplayName = "SceneVolume"),
SemanticClassification = 5 UMETA(DisplayName = "SemanticClassification"),
RoomLayout = 6 UMETA(DisplayName = "RoomLayout"),
SpaceContainer = 7 UMETA(DisplayName = "SpaceContainer"),
Undefined = 8 UMETA(DisplayName = "Not defined"),
TriangleMesh = 9 UMETA(DisplayName = "TriangleMesh"),
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRSpaceQueryInfo
{
GENERATED_BODY()
public:
FOculusXRSpaceQueryInfo()
: MaxQuerySpaces(1024), Timeout(0), Location(EOculusXRSpaceStorageLocation::Local), FilterType(EOculusXRSpaceQueryFilterType::None)
{
}
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
int MaxQuerySpaces;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
float Timeout;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
EOculusXRSpaceStorageLocation Location;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
EOculusXRSpaceQueryFilterType FilterType;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
TArray<FOculusXRUUID> IDFilter;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
TArray<EOculusXRSpaceComponentType> ComponentFilter;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
FOculusXRUUID GroupUUIDFilter;
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRSpaceQueryResult
{
GENERATED_BODY()
public:
FOculusXRSpaceQueryResult()
: Space(0), UUID(), Location(EOculusXRSpaceStorageLocation::Invalid) {}
FOculusXRSpaceQueryResult(FOculusXRUInt64 SpaceHandle, FOculusXRUUID ID, EOculusXRSpaceStorageLocation SpaceLocation)
: Space(SpaceHandle), UUID(ID), Location(SpaceLocation) {}
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
FOculusXRUInt64 Space;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
FOculusXRUUID UUID;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
EOculusXRSpaceStorageLocation Location;
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRSpaceQueryFilterValues
{
GENERATED_BODY()
public:
TArray<FOculusXRUUID> Uuids; // used if filtering by UUIDs
TArray<EOculusXRSpaceComponentType> ComponentTypes; // used if filtering by component types
};
struct ovrpSpaceDiscoveryFilterHeader_;
typedef ovrpSpaceDiscoveryFilterHeader_ ovrpSpaceDiscoveryFilterHeader;
UCLASS(BlueprintType)
class OCULUSXRANCHORS_API UOculusXRSpaceDiscoveryFilterBase : public UObject
{
GENERATED_BODY()
public:
virtual const ovrpSpaceDiscoveryFilterHeader* GenerateOVRPFilter()
{
return nullptr;
}
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRSpaceDiscoveryInfo
{
GENERATED_BODY()
public:
FOculusXRSpaceDiscoveryInfo()
{
}
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
TArray<UOculusXRSpaceDiscoveryFilterBase*> Filters;
};
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRAnchorsDiscoverResult
{
GENERATED_BODY()
public:
FOculusXRAnchorsDiscoverResult()
: Space(0), UUID() {}
FOculusXRAnchorsDiscoverResult(FOculusXRUInt64 SpaceHandle, FOculusXRUUID ID)
: Space(SpaceHandle), UUID(ID) {}
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
FOculusXRUInt64 Space;
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
FOculusXRUUID UUID;
};
struct ovrpSpaceDiscoveryFilterIds_;
typedef ovrpSpaceDiscoveryFilterIds_ ovrpSpaceDiscoveryFilterIds;
struct ovrpSpaceDiscoveryFilterIdsDelete
{
void operator()(ovrpSpaceDiscoveryFilterIds* ptr) const;
};
struct DiscoveryUuidWrapper
{
unsigned char data[16];
};
UCLASS(Blueprintable, Category = "OculusXR|SpatialAnchor")
class OCULUSXRANCHORS_API UOculusXRSpaceDiscoveryIdsFilter : public UOculusXRSpaceDiscoveryFilterBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
TArray<FOculusXRUUID> Uuids;
TArray<DiscoveryUuidWrapper> wrappedUUIDs;
virtual const ovrpSpaceDiscoveryFilterHeader* GenerateOVRPFilter() override;
private:
std::unique_ptr<ovrpSpaceDiscoveryFilterIds, ovrpSpaceDiscoveryFilterIdsDelete> OVRPFilterIds;
};
struct ovrpSpaceDiscoveryFilterComponents_;
typedef ovrpSpaceDiscoveryFilterComponents_ ovrpSpaceDiscoveryFilterComponents;
struct ovrpSpaceDiscoveryFilterComponentsDelete
{
void operator()(ovrpSpaceDiscoveryFilterComponents* ptr) const;
};
UCLASS(Blueprintable, Category = "OculusXR|SpatialAnchor")
class OCULUSXRANCHORS_API UOculusXRSpaceDiscoveryComponentsFilter : public UOculusXRSpaceDiscoveryFilterBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, Category = "OculusXR|SpatialAnchor")
EOculusXRSpaceComponentType ComponentType;
virtual const ovrpSpaceDiscoveryFilterHeader* GenerateOVRPFilter() override;
private:
std::unique_ptr<ovrpSpaceDiscoveryFilterComponents, ovrpSpaceDiscoveryFilterComponentsDelete> OVRPFilterComponent;
};
// Represents a room layout within a specific space
USTRUCT(BlueprintType)
struct OCULUSXRANCHORS_API FOculusXRRoomLayout
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category = "OculusXR|Anchors")
FOculusXRUInt64 RoomAnchorHandle;
UPROPERTY(BlueprintReadOnly, Category = "OculusXR|Anchors")
FOculusXRUUID RoomUuid;
UPROPERTY(BlueprintReadOnly, Category = "OculusXR|Anchors")
FOculusXRUUID FloorUuid;
UPROPERTY(BlueprintReadOnly, Category = "OculusXR|Anchors")
FOculusXRUUID CeilingUuid;
UPROPERTY(BlueprintReadOnly, Category = "OculusXR|Anchors")
TArray<FOculusXRUUID> WallsUuid;
UPROPERTY(BlueprintReadOnly, Category = "OculusXR|Anchors")
TArray<FOculusXRUUID> RoomObjectUUIDs;
};
/**
* Represents different types of Anchor space.
*/
UENUM(BlueprintType)
enum class EOculusXRAnchorSpace : uint8
{
/** World space is relative to the global Unreal origin. */
World,
/**
* Tracking space is relative to the HMD tracking origin.
* It does not include the transform of the player pawn.
*/
Tracking,
};

View File

@@ -0,0 +1,206 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "CoreMinimal.h"
#include "OculusXRAnchorComponent.h"
#include "OculusXRAnchorTypes.h"
#include "OculusXRAnchorsRequests.h"
DECLARE_DELEGATE_TwoParams(FOculusXRSpatialAnchorCreateDelegate, EOculusXRAnchorResult::Type /*Result*/, UOculusXRAnchorComponent* /*Anchor*/);
DECLARE_DELEGATE_TwoParams(FOculusXRAnchorEraseDelegate, EOculusXRAnchorResult::Type /*Result*/, FOculusXRUUID /*AnchorUUID*/);
DECLARE_DELEGATE_FourParams(FOculusXRAnchorSetComponentStatusDelegate, EOculusXRAnchorResult::Type /*Result*/, uint64 /*AnchorHandle*/, EOculusXRSpaceComponentType /*ComponentType*/, bool /*Enabled*/);
DECLARE_DELEGATE_TwoParams(FOculusXRAnchorSaveDelegate, EOculusXRAnchorResult::Type /*Result*/, UOculusXRAnchorComponent* /*Anchor*/);
DECLARE_DELEGATE_TwoParams(FOculusXRAnchorSaveListDelegate, EOculusXRAnchorResult::Type /*Result*/, const TArray<UOculusXRAnchorComponent*>& /*SavedAnchors*/);
DECLARE_DELEGATE_TwoParams(FOculusXRAnchorQueryDelegate, EOculusXRAnchorResult::Type /*Result*/, const TArray<FOculusXRSpaceQueryResult>& /*Results*/);
DECLARE_DELEGATE_ThreeParams(FOculusXRAnchorShareDelegate, EOculusXRAnchorResult::Type /*Result*/, const TArray<UOculusXRAnchorComponent*>& /*Anchors*/, const TArray<uint64>& /*Users*/);
DECLARE_DELEGATE_TwoParams(FOculusXRSaveAnchorsDelegate, EOculusXRAnchorResult::Type /*Result*/, const TArray<UOculusXRAnchorComponent*>& /*SavedAnchors*/);
DECLARE_DELEGATE_FourParams(FOculusXREraseAnchorsDelegate, EOculusXRAnchorResult::Type /*Result*/, const TArray<UOculusXRAnchorComponent*>& /*ErasedAnchors*/, const TArray<FOculusXRUInt64>& /*ErasedAnchorsUUIDs*/, const TArray<FOculusXRUUID>& /*ErasedAnchorsUUIDs*/);
DECLARE_DELEGATE_OneParam(FOculusXRDiscoverAnchorsResultsDelegate, const TArray<FOculusXRAnchorsDiscoverResult>& /*DiscoveredSpace*/);
DECLARE_DELEGATE_OneParam(FOculusXRDiscoverAnchorsCompleteDelegate, EOculusXRAnchorResult::Type /*Result*/);
DECLARE_DELEGATE_TwoParams(FOculusXRGetSharedAnchorsDelegate, EOculusXRAnchorResult::Type /*Result*/, const TArray<FOculusXRAnchorsDiscoverResult>& /*Results*/);
namespace OculusXRAnchors
{
struct OCULUSXRANCHORS_API FOculusXRAnchors
{
void Initialize();
void Teardown();
static FOculusXRAnchors* GetInstance();
static bool CreateSpatialAnchor(const FTransform& InTransform, AActor* TargetActor, const FOculusXRSpatialAnchorCreateDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool EraseAnchor(UOculusXRAnchorComponent* Anchor, const FOculusXRAnchorEraseDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool DestroyAnchor(uint64 AnchorHandle, EOculusXRAnchorResult::Type& OutResult);
static bool SetAnchorComponentStatus(UOculusXRAnchorComponent* Anchor, EOculusXRSpaceComponentType SpaceComponentType, bool Enable, float Timeout, const FOculusXRAnchorSetComponentStatusDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool GetAnchorComponentStatus(UOculusXRAnchorComponent* Anchor, EOculusXRSpaceComponentType SpaceComponentType, bool& OutEnabled, bool& OutChangePending, EOculusXRAnchorResult::Type& OutResult);
static bool GetAnchorSupportedComponents(UOculusXRAnchorComponent* Anchor, TArray<EOculusXRSpaceComponentType>& OutSupportedComponents, EOculusXRAnchorResult::Type& OutResult);
static bool SetComponentStatus(uint64 Space, EOculusXRSpaceComponentType SpaceComponentType, bool Enable, float Timeout, const FOculusXRAnchorSetComponentStatusDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool GetComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType SpaceComponentType, bool& OutEnabled, bool& OutChangePending, EOculusXRAnchorResult::Type& OutResult);
static bool GetSupportedComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedComponents, EOculusXRAnchorResult::Type& OutResult);
static bool SaveAnchor(UOculusXRAnchorComponent* Anchor, EOculusXRSpaceStorageLocation StorageLocation, const FOculusXRAnchorSaveDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool SaveAnchorList(const TArray<UOculusXRAnchorComponent*>& Anchors, EOculusXRSpaceStorageLocation StorageLocation, const FOculusXRAnchorSaveListDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool QueryAnchors(const TArray<FOculusXRUUID>& AnchorUUIDs, EOculusXRSpaceStorageLocation Location, const FOculusXRAnchorQueryDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool QueryAnchorsAdvanced(const FOculusXRSpaceQueryInfo& QueryInfo, const FOculusXRAnchorQueryDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool ShareAnchors(const TArray<UOculusXRAnchorComponent*>& Anchors, const TArray<uint64>& OculusUserIDs, const FOculusXRAnchorShareDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool ShareAnchors(const TArray<uint64>& AnchorHandles, const TArray<uint64>& OculusUserIDs, const FOculusXRAnchorShareDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool GetSpaceContainerUUIDs(uint64 Space, TArray<FOculusXRUUID>& OutUUIDs, EOculusXRAnchorResult::Type& OutResult);
static bool SaveAnchors(const TArray<UOculusXRAnchorComponent*>& Anchors, const FOculusXRSaveAnchorsDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool EraseAnchors(const TArray<UOculusXRAnchorComponent*>& Anchors, const FOculusXREraseAnchorsDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool EraseAnchors(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& AnchorUUIDs, const FOculusXREraseAnchorsDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static bool DiscoverAnchors(const FOculusXRSpaceDiscoveryInfo& DiscoveryInfo, const FOculusXRDiscoverAnchorsResultsDelegate& DiscoveryResultsCallback, const FOculusXRDiscoverAnchorsCompleteDelegate& DiscoveryCompleteCallback, EOculusXRAnchorResult::Type& OutResult);
static bool GetSharedAnchors(const TArray<FOculusXRUUID>& AnchorUUIDs, const FOculusXRGetSharedAnchorsDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult);
static TSharedPtr<FShareAnchorsWithGroups> ShareAnchorsAsync(const TArray<FOculusXRUInt64>& AnchorHandles, const TArray<FOculusXRUUID>& Groups, const FShareAnchorsWithGroups::FCompleteDelegate& OnComplete);
static TSharedPtr<FGetAnchorsSharedWithGroup> GetSharedAnchorsAsync(const FOculusXRUUID& Group, const TArray<FOculusXRUUID>& WantedAnchors, const FGetAnchorsSharedWithGroup::FCompleteDelegate& OnComplete);
private:
struct AnchorQueryBinding;
struct GetSharedAnchorsBinding;
void HandleSpatialAnchorCreateComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result, FOculusXRUInt64 Space, FOculusXRUUID UUID);
void HandleAnchorEraseComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result, FOculusXRUUID UUID, EOculusXRSpaceStorageLocation Location);
void HandleSetComponentStatusComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result, FOculusXRUInt64 Space, FOculusXRUUID UUID, EOculusXRSpaceComponentType ComponentType, bool Enabled);
void HandleAnchorSaveComplete(FOculusXRUInt64 RequestId, FOculusXRUInt64 Space, bool Success, EOculusXRAnchorResult::Type Result, FOculusXRUUID UUID);
void HandleAnchorSaveListComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void HandleAnchorQueryResultElement(FOculusXRUInt64 RequestId, FOculusXRUInt64 Space, FOculusXRUUID UUID);
void UpdateQuerySpacesBinding(AnchorQueryBinding* Binding, FOculusXRUInt64 RequestId, FOculusXRUInt64 Space, FOculusXRUUID UUID);
void UpdateGetSharedAnchorsBinding(GetSharedAnchorsBinding* Binding, FOculusXRUInt64 RequestId, FOculusXRUInt64 Space, FOculusXRUUID UUID);
void HandleAnchorQueryComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void QuerySpacesComplete(AnchorQueryBinding* Binding, FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void GetSharedAnchorsComplete(GetSharedAnchorsBinding* Binding, FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void HandleAnchorSharingComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void HandleAnchorsSaveComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void HandleAnchorsEraseComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void HandleAnchorsEraseByComponentsComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void HandleAnchorsEraseByHandleAndUUIDComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
void HandleAnchorsDiscoverResults(FOculusXRUInt64 RequestId, const TArray<FOculusXRAnchorsDiscoverResult>& Results);
void HandleAnchorsDiscoverComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
struct EraseAnchorBinding
{
FOculusXRUInt64 RequestId;
FOculusXRAnchorEraseDelegate Binding;
TWeakObjectPtr<UOculusXRAnchorComponent> Anchor;
};
struct SetComponentStatusBinding
{
FOculusXRUInt64 RequestId;
FOculusXRAnchorSetComponentStatusDelegate Binding;
uint64 AnchorHandle;
};
struct CreateAnchorBinding
{
FOculusXRUInt64 RequestId;
FOculusXRSpatialAnchorCreateDelegate Binding;
TWeakObjectPtr<AActor> Actor;
};
struct SaveAnchorBinding
{
FOculusXRUInt64 RequestId;
FOculusXRAnchorSaveDelegate Binding;
EOculusXRSpaceStorageLocation Location;
TWeakObjectPtr<UOculusXRAnchorComponent> Anchor;
};
struct SaveAnchorListBinding
{
FOculusXRUInt64 RequestId;
FOculusXRAnchorSaveListDelegate Binding;
EOculusXRSpaceStorageLocation Location;
TArray<TWeakObjectPtr<UOculusXRAnchorComponent>> SavedAnchors;
};
struct AnchorQueryBinding
{
FOculusXRUInt64 RequestId;
FOculusXRAnchorQueryDelegate Binding;
EOculusXRSpaceStorageLocation Location;
TArray<FOculusXRSpaceQueryResult> Results;
};
struct ShareAnchorsBinding
{
FOculusXRUInt64 RequestId;
FOculusXRAnchorShareDelegate Binding;
TArray<TWeakObjectPtr<UOculusXRAnchorComponent>> SharedAnchors;
TArray<uint64> OculusUserIds;
};
struct SaveAnchorsBinding
{
FOculusXRUInt64 RequestId;
FOculusXRSaveAnchorsDelegate Binding;
TArray<TWeakObjectPtr<UOculusXRAnchorComponent>> SavedAnchors;
};
struct EraseAnchorsBinding
{
FOculusXRUInt64 RequestId;
FOculusXREraseAnchorsDelegate Binding;
TArray<TWeakObjectPtr<UOculusXRAnchorComponent>> ErasedAnchors;
TArray<FOculusXRUInt64> ErasedAnchorsHandles;
TArray<FOculusXRUUID> ErasedAnchorsUUIDs;
};
struct AnchorDiscoveryBinding
{
FOculusXRUInt64 RequestId;
FOculusXRDiscoverAnchorsResultsDelegate ResultBinding;
FOculusXRDiscoverAnchorsCompleteDelegate CompleteBinding;
};
struct GetSharedAnchorsBinding
{
FOculusXRUInt64 RequestId;
FOculusXRGetSharedAnchorsDelegate ResultBinding;
TArray<FOculusXRAnchorsDiscoverResult> Results;
};
// Delegate bindings
TMap<uint64, CreateAnchorBinding> CreateSpatialAnchorBindings;
TMap<uint64, EraseAnchorBinding> EraseAnchorBindings;
TMap<uint64, SetComponentStatusBinding> SetComponentStatusBindings;
TMap<uint64, SaveAnchorBinding> AnchorSaveBindings;
TMap<uint64, SaveAnchorListBinding> AnchorSaveListBindings;
TMap<uint64, AnchorQueryBinding> AnchorQueryBindings;
TMap<uint64, ShareAnchorsBinding> ShareAnchorsBindings;
TMap<uint64, SaveAnchorsBinding> SaveAnchorsBindings;
TMap<uint64, EraseAnchorsBinding> EraseAnchorsBindings;
TMap<uint64, AnchorDiscoveryBinding> AnchorDiscoveryBindings;
TMap<uint64, GetSharedAnchorsBinding> GetSharedAnchorsBindings;
// Delegate handles
FDelegateHandle DelegateHandleAnchorCreate;
FDelegateHandle DelegateHandleAnchorErase;
FDelegateHandle DelegateHandleSetComponentStatus;
FDelegateHandle DelegateHandleAnchorSave;
FDelegateHandle DelegateHandleAnchorSaveList;
FDelegateHandle DelegateHandleQueryResultsBegin;
FDelegateHandle DelegateHandleQueryResultElement;
FDelegateHandle DelegateHandleQueryComplete;
FDelegateHandle DelegateHandleAnchorShare;
FDelegateHandle DelegateHandleAnchorsSave;
FDelegateHandle DelegateHandleAnchorsErase;
FDelegateHandle DelegateHandleAnchorsDiscoverResults;
FDelegateHandle DelegateHandleAnchorsDiscoverComplete;
};
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,57 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRAsyncRequestSystem.h"
#include "OculusXRAsyncRequest.h"
#include "OculusXRAnchorTypes.h"
namespace OculusXRAnchors
{
// Share anchors with group
struct OCULUSXRANCHORS_API FShareAnchorsWithGroups :
OculusXR::FAsyncRequest<FShareAnchorsWithGroups, EOculusXRAnchorResult::Type, TTuple<TArray<FOculusXRUUID>, TArray<FOculusXRUInt64>>>
{
public:
FShareAnchorsWithGroups(const TArray<FOculusXRUUID>& TargetGroups, const TArray<FOculusXRUInt64>& AnchorsToShare);
~FShareAnchorsWithGroups();
const TArray<FOculusXRUUID>& GetGroups() const { return Groups; }
const TArray<FOculusXRUInt64>& GetAnchors() const { return Anchors; }
protected:
virtual void OnInitRequest() override;
private:
static void OnShareComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
TArray<FOculusXRUUID> Groups;
TArray<FOculusXRUInt64> Anchors;
FDelegateHandle CallbackHandle;
};
// Get shared anchors from group
struct OCULUSXRANCHORS_API FGetAnchorsSharedWithGroup :
OculusXR::FAsyncRequest<FGetAnchorsSharedWithGroup, EOculusXRAnchorResult::Type, TArray<FOculusXRAnchor>>
{
public:
FGetAnchorsSharedWithGroup(const FOculusXRUUID& TargetGroup, const TArray<FOculusXRUUID>& WantedAnchors = {});
~FGetAnchorsSharedWithGroup();
void OnResultsAvailable(const TArray<FOculusXRAnchor>& Results);
const TArray<FOculusXRAnchor>& GetRetrievedAnchors() const { return RetrievedAnchors; }
protected:
virtual void OnInitRequest() override;
private:
static void OnQueryComplete(FOculusXRUInt64 RequestId, EOculusXRAnchorResult::Type Result);
static void OnQueryResultAvailable(FOculusXRUInt64 RequestId, FOculusXRUInt64 AnchorHandle, FOculusXRUUID AnchorUuid);
FOculusXRUUID Group;
TArray<FOculusXRUUID> RequestedAnchors;
TArray<FOculusXRAnchor> RetrievedAnchors;
FDelegateHandle CallbackHandleComplete;
FDelegateHandle CallbackHandleResults;
};
} // namespace OculusXRAnchors

View File

@@ -0,0 +1,25 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "CoreMinimal.h"
#include "OculusXRAnchorComponent.h"
#include "OculusXRAnchors.h"
#include "OculusXRSpatialAnchorComponent.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogOculusSpatialAnchor, Log, All);
UCLASS(meta = (DisplayName = "Oculus Spatial Anchor Component", BlueprintSpawnableComponent))
class OCULUSXRANCHORS_API UOculusXRSpatialAnchorComponent : public UOculusXRAnchorComponent
{
GENERATED_BODY()
public:
UOculusXRSpatialAnchorComponent(const FObjectInitializer& ObjectInitializer);
static bool Create(const FTransform& NewAnchorTransform, AActor* OwningActor, const FOculusXRSpatialAnchorCreateDelegate& Callback);
bool Erase(const FOculusXRAnchorEraseDelegate& Callback);
bool Save(EOculusXRSpaceStorageLocation Location, const FOculusXRAnchorSaveDelegate& Callback);
private:
};