Config for building for Quest
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
// @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 = true;
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"OculusXRHMD",
|
||||
"OVRPluginXR",
|
||||
"ProceduralMeshComponent",
|
||||
});
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// Relative to Engine\Plugins\Runtime\Oculus\OculusVR\Source
|
||||
"OculusXRHMD/Private",
|
||||
});
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"Runtime/Engine/Classes/Components",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRAnchorBPFunctionLibrary.h"
|
||||
#include "OculusXRHMD.h"
|
||||
#include "OculusXRSpatialAnchorComponent.h"
|
||||
#include "OculusXRAnchorsPrivate.h"
|
||||
#include "OculusXRRoomLayoutManager.h"
|
||||
#include "OculusXRAnchorManager.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
|
||||
AActor* UOculusXRAnchorBPFunctionLibrary::SpawnActorWithAnchorHandle(UObject* WorldContextObject, FOculusXRUInt64 Handle, FOculusXRUUID UUID, EOculusXRSpaceStorageLocation Location, UClass* ActorClass,
|
||||
AActor* Owner, APawn* Instigator, ESpawnActorCollisionHandlingMethod CollisionHandlingMethod)
|
||||
{
|
||||
FActorSpawnParameters SpawnInfo;
|
||||
SpawnInfo.Owner = Owner;
|
||||
SpawnInfo.Instigator = Instigator;
|
||||
SpawnInfo.ObjectFlags |= RF_Transient;
|
||||
SpawnInfo.SpawnCollisionHandlingOverride = CollisionHandlingMethod;
|
||||
|
||||
UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
|
||||
if (World == nullptr)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid WorldContext Object for SpawnActorWithAnchorHandle."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AActor* NewSpatialAnchorActor = World->SpawnActor(ActorClass, nullptr, nullptr, SpawnInfo);
|
||||
if (NewSpatialAnchorActor == nullptr)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to spawn Actor in SpawnActorWithAnchorHandle"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UOculusXRSpatialAnchorComponent* SpatialAnchorComponent = NewSpatialAnchorActor->FindComponentByClass<UOculusXRSpatialAnchorComponent>();
|
||||
if (SpatialAnchorComponent == nullptr)
|
||||
{
|
||||
SpatialAnchorComponent = Cast<UOculusXRSpatialAnchorComponent>(NewSpatialAnchorActor->AddComponentByClass(UOculusXRSpatialAnchorComponent::StaticClass(), false, FTransform::Identity, false));
|
||||
}
|
||||
|
||||
if (!IsValid(SpatialAnchorComponent))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to find or spawn Spatial Anchor component in SpawnActorWithAnchorHandle"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SpatialAnchorComponent->SetHandle(Handle);
|
||||
SpatialAnchorComponent->SetUUID(UUID);
|
||||
SpatialAnchorComponent->SetStoredLocation(Location, true);
|
||||
return NewSpatialAnchorActor;
|
||||
}
|
||||
|
||||
AActor* UOculusXRAnchorBPFunctionLibrary::SpawnActorWithAnchorQueryResults(UObject* WorldContextObject, const FOculusXRSpaceQueryResult& QueryResult, UClass* ActorClass, AActor* Owner, APawn* Instigator, ESpawnActorCollisionHandlingMethod CollisionHandlingMethod)
|
||||
{
|
||||
return SpawnActorWithAnchorHandle(WorldContextObject, QueryResult.Space, QueryResult.UUID, QueryResult.Location, ActorClass, Owner, Instigator, CollisionHandlingMethod);
|
||||
}
|
||||
|
||||
bool UOculusXRAnchorBPFunctionLibrary::GetAnchorComponentStatus(AActor* TargetActor, EOculusXRSpaceComponentType ComponentType, bool& bIsEnabled)
|
||||
{
|
||||
UOculusXRAnchorComponent* AnchorComponent = Cast<UOculusXRAnchorComponent>(TargetActor->GetComponentByClass(UOculusXRAnchorComponent::StaticClass()));
|
||||
|
||||
if (!IsValid(AnchorComponent))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid Anchor Component provided to GetAnchorComponentStatus"));
|
||||
bIsEnabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bOutIsEnabled = false;
|
||||
bool bIsChangePending = false;
|
||||
|
||||
EOculusXRAnchorResult::Type AnchorResult;
|
||||
bool bDidCallStart = OculusXRAnchors::FOculusXRAnchors::GetAnchorComponentStatus(AnchorComponent, ComponentType, bOutIsEnabled, bIsChangePending, AnchorResult);
|
||||
if (!bDidCallStart)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start call to internal GetAnchorComponentStatus"));
|
||||
bIsEnabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bIsEnabled = bOutIsEnabled;
|
||||
return bIsEnabled;
|
||||
}
|
||||
|
||||
bool UOculusXRAnchorBPFunctionLibrary::GetAnchorTransformByHandle(const FOculusXRUInt64& Handle, FTransform& OutTransform)
|
||||
{
|
||||
FOculusXRAnchorLocationFlags AnchorFlags(0);
|
||||
return TryGetAnchorTransformByHandle(Handle, OutTransform, AnchorFlags);
|
||||
}
|
||||
|
||||
bool UOculusXRAnchorBPFunctionLibrary::TryGetAnchorTransformByHandle(const FOculusXRUInt64& Handle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags)
|
||||
{
|
||||
OculusXRHMD::FOculusXRHMD* OutHMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
|
||||
if (!OutHMD)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve OculusXRHMD, cannot calculate anchor transform."));
|
||||
return false;
|
||||
}
|
||||
|
||||
ovrpTrackingOrigin ovrpOrigin = ovrpTrackingOrigin_EyeLevel;
|
||||
const bool bTrackingOriginSuccess = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().GetTrackingOriginType2(&ovrpOrigin));
|
||||
if (!bTrackingOriginSuccess)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to get tracking origin, cannot calculate anchor transform."));
|
||||
return false;
|
||||
}
|
||||
|
||||
OutTransform = FTransform::Identity;
|
||||
OutLocationFlags = FOculusXRAnchorLocationFlags(0);
|
||||
|
||||
const ovrpUInt64 ovrpSpace = Handle.GetValue();
|
||||
ovrpSpaceLocationf ovrpSpaceLocation;
|
||||
|
||||
const bool bSuccess = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().LocateSpace2(&ovrpSpaceLocation, &ovrpSpace, ovrpOrigin));
|
||||
if (bSuccess)
|
||||
{
|
||||
OutLocationFlags = FOculusXRAnchorLocationFlags(ovrpSpaceLocation.locationFlags);
|
||||
if (OutLocationFlags.IsValid())
|
||||
{
|
||||
OculusXRHMD::FPose Pose;
|
||||
OutHMD->ConvertPose(ovrpSpaceLocation.pose, Pose);
|
||||
const FTransform trackingToWorld = OutHMD->GetLastTrackingToWorld();
|
||||
|
||||
OutTransform.SetLocation(trackingToWorld.TransformPosition(Pose.Position));
|
||||
OutTransform.SetRotation(FRotator(trackingToWorld.TransformRotation(FQuat(Pose.Orientation))).Quaternion());
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
FString UOculusXRAnchorBPFunctionLibrary::AnchorHandleToString(const FOculusXRUInt64 Value)
|
||||
{
|
||||
return FString::Printf(TEXT("%llu"), Value.Value);
|
||||
}
|
||||
|
||||
FString UOculusXRAnchorBPFunctionLibrary::AnchorUUIDToString(const FOculusXRUUID& Value)
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
|
||||
FOculusXRUUID UOculusXRAnchorBPFunctionLibrary::StringToAnchorUUID(const FString& Value)
|
||||
{
|
||||
// Static size for the max length of the string, two chars per hex digit, 16 digits.
|
||||
checkf(Value.Len() == 32, TEXT("'%s' is not a valid UUID"), *Value);
|
||||
|
||||
ovrpUuid newID;
|
||||
HexToBytes(Value, newID.data);
|
||||
|
||||
return FOculusXRUUID(newID.data);
|
||||
}
|
||||
bool UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(EOculusXRAnchorResult::Type result)
|
||||
{
|
||||
#if OCULUS_HMD_SUPPORTED_PLATFORMS
|
||||
return OVRP_SUCCESS(result);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
const UOculusXRBaseAnchorComponent* UOculusXRAnchorBPFunctionLibrary::GetAnchorComponent(const FOculusXRSpaceQueryResult& QueryResult, EOculusXRSpaceComponentType ComponentType, UObject* Outer)
|
||||
{
|
||||
switch (ComponentType)
|
||||
{
|
||||
case EOculusXRSpaceComponentType::Locatable:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRLocatableAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
case EOculusXRSpaceComponentType::ScenePlane:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRPlaneAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
case EOculusXRSpaceComponentType::SceneVolume:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRVolumeAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
case EOculusXRSpaceComponentType::SemanticClassification:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRSemanticClassificationAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
case EOculusXRSpaceComponentType::RoomLayout:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRRoomLayoutAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
case EOculusXRSpaceComponentType::SpaceContainer:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRSpaceContainerAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
case EOculusXRSpaceComponentType::Sharable:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRSharableAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
case EOculusXRSpaceComponentType::Storable:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRStorableAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
case EOculusXRSpaceComponentType::TriangleMesh:
|
||||
return UOculusXRBaseAnchorComponent::FromSpace<UOculusXRTriangleMeshAnchorComponent>(QueryResult.Space.Value, Outer);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool UOculusXRAnchorBPFunctionLibrary::GetRoomLayout(FOculusXRUInt64 Space, FOculusXRRoomLayout& RoomLayoutOut, int32 MaxWallsCapacity)
|
||||
{
|
||||
if (MaxWallsCapacity <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FOculusXRUUID OutCeilingUuid;
|
||||
FOculusXRUUID OutFloorUuid;
|
||||
TArray<FOculusXRUUID> OutWallsUuid;
|
||||
|
||||
const bool bSuccess = OculusXRAnchors::FOculusXRRoomLayoutManager::GetSpaceRoomLayout(Space.Value, static_cast<uint32>(MaxWallsCapacity), OutCeilingUuid, OutFloorUuid, OutWallsUuid);
|
||||
|
||||
if (bSuccess)
|
||||
{
|
||||
RoomLayoutOut.CeilingUuid = OutCeilingUuid;
|
||||
RoomLayoutOut.FloorUuid = OutFloorUuid;
|
||||
RoomLayoutOut.WallsUuid.InsertZeroed(0, OutWallsUuid.Num());
|
||||
|
||||
for (int32 i = 0; i < OutWallsUuid.Num(); ++i)
|
||||
{
|
||||
RoomLayoutOut.WallsUuid[i] = OutWallsUuid[i];
|
||||
}
|
||||
|
||||
TArray<FOculusXRUUID> spaceUUIDs;
|
||||
EOculusXRAnchorResult::Type result = OculusXRAnchors::FOculusXRAnchorManager::GetSpaceContainerUUIDs(Space, spaceUUIDs);
|
||||
|
||||
if (UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(result))
|
||||
{
|
||||
RoomLayoutOut.RoomObjectUUIDs = spaceUUIDs;
|
||||
}
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRAnchorComponent.h"
|
||||
#include "OculusXRAnchors.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, *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);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRAnchorComponents.h"
|
||||
|
||||
#include "OculusXRAnchorBPFunctionLibrary.h"
|
||||
#include "OculusXRAnchorManager.h"
|
||||
#include "OculusXRRoomLayoutManager.h"
|
||||
#include "OculusXRSpatialAnchorComponent.h"
|
||||
|
||||
bool UOculusXRBaseAnchorComponent::IsComponentEnabled() const
|
||||
{
|
||||
bool OutEnabled;
|
||||
bool OutChangePending;
|
||||
|
||||
auto OutResult = OculusXRAnchors::FOculusXRAnchorManager::GetSpaceComponentStatus(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 UOculusXRPlaneAnchorComponent::GetPositionAndSize(FVector& outPosition, FVector& outSize) const
|
||||
{
|
||||
ensure(IsComponentEnabled());
|
||||
|
||||
if (!UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OculusXRAnchors::FOculusXRAnchorManager::GetSpaceScenePlane(Space, outPosition, outSize)))
|
||||
{
|
||||
UE_LOG(LogOculusSpatialAnchor, Warning, TEXT("Fetching scene plane failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UOculusXRVolumeAnchorComponent::GetPositionAndSize(FVector& outPosition, FVector& outSize) const
|
||||
{
|
||||
ensure(IsComponentEnabled());
|
||||
|
||||
if (!UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OculusXRAnchors::FOculusXRAnchorManager::GetSpaceSceneVolume(Space, outPosition, outSize)))
|
||||
{
|
||||
UE_LOG(LogOculusSpatialAnchor, Warning, TEXT("Fetching scene plane failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UOculusXRSemanticClassificationAnchorComponent::GetSemanticClassifications(TArray<FString>& outClassifications) const
|
||||
{
|
||||
ensure(IsComponentEnabled());
|
||||
|
||||
if (!UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OculusXRAnchors::FOculusXRAnchorManager::GetSpaceSemanticClassification(Space, outClassifications)))
|
||||
{
|
||||
UE_LOG(LogOculusSpatialAnchor, Warning, TEXT("Fetching scene volume failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UOculusXRRoomLayoutAnchorComponent::GetRoomLayout(FOculusXRUUID& outFloorUUID, FOculusXRUUID& outCeilingUUID, TArray<FOculusXRUUID>& outWallsUUIDs) const
|
||||
{
|
||||
ensure(IsComponentEnabled());
|
||||
|
||||
if (!OculusXRAnchors::FOculusXRRoomLayoutManager::GetSpaceRoomLayout(Space, 64, outCeilingUUID, outFloorUUID, outWallsUUIDs))
|
||||
{
|
||||
UE_LOG(LogOculusSpatialAnchor, Warning, TEXT("Fetching room layout failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UOculusXRSpaceContainerAnchorComponent::GetUUIDs(TArray<FOculusXRUUID>& outUUIDs) const
|
||||
{
|
||||
ensure(IsComponentEnabled());
|
||||
|
||||
if (!OculusXRAnchors::FOculusXRAnchorManager::GetSpaceContainer(Space, outUUIDs))
|
||||
{
|
||||
UE_LOG(LogOculusSpatialAnchor, Warning, TEXT("Fetching container uuids failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// 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::FOculusXRSceneCaptureCompleteDelegate FOculusXRAnchorEventDelegates::OculusSceneCaptureComplete;
|
||||
|
||||
@@ -0,0 +1,581 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRAnchorLatentActions.h"
|
||||
#include "OculusXRAnchorsPrivate.h"
|
||||
#include "OculusXRHMD.h"
|
||||
#include "OculusXRAnchorBPFunctionLibrary.h"
|
||||
#include "OculusXRRoomLayoutManager.h"
|
||||
#include "OculusXRAnchorDelegates.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();
|
||||
}
|
||||
|
||||
|
||||
UOculusXRAnchorLaunchCaptureFlow* UOculusXRAnchorLaunchCaptureFlow::LaunchCaptureFlowAsync(const UObject* WorldContext)
|
||||
{
|
||||
UWorld* World = GEngine->GetWorldFromContextObject(WorldContext, EGetWorldErrorMode::ReturnNull);
|
||||
if (!ensureAlwaysMsgf(IsValid(WorldContext), TEXT("World Context was not valid.")))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a new UMyDelayAsyncAction, and store function arguments in it.
|
||||
auto NewAction = NewObject<UOculusXRAnchorLaunchCaptureFlow>();
|
||||
NewAction->RegisterWithGameInstance(World->GetGameInstance());
|
||||
return NewAction;
|
||||
}
|
||||
|
||||
void UOculusXRAnchorLaunchCaptureFlow::Activate()
|
||||
{
|
||||
Request = 0;
|
||||
FOculusXRAnchorEventDelegates::OculusSceneCaptureComplete.AddUObject(this, &UOculusXRAnchorLaunchCaptureFlow::OnCaptureFinish);
|
||||
bool CaptureStarted = OculusXRAnchors::FOculusXRRoomLayoutManager::RequestSceneCapture(Request);
|
||||
if (!CaptureStarted)
|
||||
{
|
||||
FOculusXRAnchorEventDelegates::OculusSceneCaptureComplete.RemoveAll(this);
|
||||
Failure.Broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
void UOculusXRAnchorLaunchCaptureFlow::OnCaptureFinish(FOculusXRUInt64 RequestId, bool bSuccess)
|
||||
{
|
||||
if (Request != RequestId.GetValue())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("%llu request id doesn't match %llu. Ignoring request."), RequestId, Request);
|
||||
return;
|
||||
}
|
||||
|
||||
FOculusXRAnchorEventDelegates::OculusSceneCaptureComplete.RemoveAll(this);
|
||||
Success.Broadcast();
|
||||
SetReadyToDestroy();
|
||||
}
|
||||
@@ -0,0 +1,816 @@
|
||||
// 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"
|
||||
|
||||
namespace OculusXRAnchors
|
||||
{
|
||||
OculusXRHMD::FOculusXRHMD* GetHMD(bool& OutSuccessful)
|
||||
{
|
||||
OculusXRHMD::FOculusXRHMD* OutHMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
|
||||
if (!OutHMD)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve OculusXRHMD"));
|
||||
OutSuccessful = false;
|
||||
}
|
||||
|
||||
OutSuccessful = true;
|
||||
|
||||
return OutHMD;
|
||||
}
|
||||
|
||||
ovrpUuid ConvertFOculusXRUUIDtoOvrpUuid(const FOculusXRUUID& UUID)
|
||||
{
|
||||
ovrpUuid Result;
|
||||
FMemory::Memcpy(Result.data, UUID.UUIDBytes);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
ovrpSpaceQueryInfo ConvertToOVRPSpaceQueryInfo(const FOculusXRSpaceQueryInfo& UEQueryInfo)
|
||||
{
|
||||
static const int32 MaxIdsInFilter = 1024;
|
||||
static const int32 MaxComponentTypesInFilter = 16;
|
||||
|
||||
ovrpSpaceQueryInfo Result;
|
||||
|
||||
Result.queryType = ovrpSpaceQueryType_Action;
|
||||
Result.actionType = ovrpSpaceQueryActionType_Load;
|
||||
|
||||
Result.maxQuerySpaces = UEQueryInfo.MaxQuerySpaces;
|
||||
Result.timeout = static_cast<double>(UEQueryInfo.Timeout); // Prevent compiler warnings, though there is a possible loss of data here.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Result.IdInfo.numIds = FMath::Min(MaxIdsInFilter, UEQueryInfo.IDFilter.Num());
|
||||
for (int i = 0; i < Result.IdInfo.numIds; ++i)
|
||||
{
|
||||
ovrpUuid OvrUuid = ConvertFOculusXRUUIDtoOvrpUuid(UEQueryInfo.IDFilter[i]);
|
||||
Result.IdInfo.ids[i] = OvrUuid;
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void GetEventData(ovrpEventDataBuffer& Buffer, T& OutEventData)
|
||||
{
|
||||
unsigned char* BufData = Buffer.EventData;
|
||||
BufData -= sizeof(uint64); //correct offset
|
||||
|
||||
memcpy(&OutEventData, BufData, sizeof(T));
|
||||
}
|
||||
|
||||
void FOculusXRAnchorManager::OnPollEvent(ovrpEventDataBuffer* EventDataBuffer, bool& EventPollResult)
|
||||
{
|
||||
ovrpEventDataBuffer& buf = *EventDataBuffer;
|
||||
EventPollResult = true;
|
||||
|
||||
switch (buf.EventType)
|
||||
{
|
||||
case ovrpEventType_SpatialAnchorCreateComplete:
|
||||
{
|
||||
ovrpEventDataSpatialAnchorCreateComplete AnchorCreateEvent;
|
||||
GetEventData(buf, AnchorCreateEvent);
|
||||
|
||||
const FOculusXRUInt64 RequestId(AnchorCreateEvent.requestId);
|
||||
const FOculusXRUInt64 Space(AnchorCreateEvent.space);
|
||||
const FOculusXRUUID BPUUID(AnchorCreateEvent.uuid.data);
|
||||
|
||||
FOculusXRAnchorEventDelegates::OculusSpatialAnchorCreateComplete.Broadcast(RequestId, 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;
|
||||
GetEventData(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,
|
||||
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;
|
||||
GetEventData(buf, QueryEvent);
|
||||
|
||||
const FOculusXRUInt64 RequestId(QueryEvent.requestId);
|
||||
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceQueryResults.Broadcast(RequestId);
|
||||
|
||||
ovrpUInt32 ovrpOutCapacity = 0;
|
||||
|
||||
// First get capacity
|
||||
const bool bGetCapacityResult = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().RetrieveSpaceQueryResults(&QueryEvent.requestId, 0, &ovrpOutCapacity, nullptr));
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Log, TEXT("ovrpEventType_SpaceQueryResults Request ID: %llu -- Capacity: %d -- Result: %d"), QueryEvent.requestId, ovrpOutCapacity, bGetCapacityResult);
|
||||
|
||||
std::vector<ovrpSpaceQueryResult> ovrpResults(ovrpOutCapacity);
|
||||
|
||||
// Get Query Data
|
||||
const bool bGetQueryDataResult = FOculusXRHMDModule::GetPluginWrapper().GetInitialized() && OVRP_SUCCESS(FOculusXRHMDModule::GetPluginWrapper().RetrieveSpaceQueryResults(&QueryEvent.requestId, ovrpResults.size(), &ovrpOutCapacity, ovrpResults.data()));
|
||||
|
||||
for (auto queryResultElement : ovrpResults)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceQueryResult Space: %llu -- Result: %d"), queryResultElement.space, bGetQueryDataResult);
|
||||
|
||||
//translate types
|
||||
FOculusXRUInt64 Space(queryResultElement.space);
|
||||
FOculusXRUUID BPUUID(queryResultElement.uuid.data);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceQueryResult.Broadcast(RequestId, Space, BPUUID);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ovrpEventType_SpaceQueryComplete:
|
||||
{
|
||||
ovrpEventSpaceQueryComplete QueryCompleteEvent;
|
||||
GetEventData(buf, QueryCompleteEvent);
|
||||
|
||||
//translate to BP types
|
||||
const FOculusXRUInt64 RequestId(QueryCompleteEvent.requestId);
|
||||
const bool bSucceeded = QueryCompleteEvent.result >= 0;
|
||||
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceQueryComplete.Broadcast(RequestId, QueryCompleteEvent.result);
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("ovrpEventType_SpaceQueryComplete Request ID: %llu -- Result: %d"), QueryCompleteEvent.requestId, QueryCompleteEvent.result);
|
||||
|
||||
break;
|
||||
}
|
||||
case ovrpEventType_SpaceSaveComplete:
|
||||
{
|
||||
ovrpEventSpaceStorageSaveResult StorageResult;
|
||||
GetEventData(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, 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;
|
||||
GetEventData(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, SpaceListSaveResult.result);
|
||||
|
||||
break;
|
||||
}
|
||||
case ovrpEventType_SpaceEraseComplete:
|
||||
{
|
||||
ovrpEventSpaceStorageEraseResult SpaceEraseEvent;
|
||||
GetEventData(buf, SpaceEraseEvent);
|
||||
|
||||
//translate to BP types
|
||||
const FOculusXRUUID uuid(SpaceEraseEvent.uuid.data);
|
||||
const FOculusXRUInt64 FRequestId(SpaceEraseEvent.requestId);
|
||||
const FOculusXRUInt64 FResult(SpaceEraseEvent.result);
|
||||
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, FResult.Value, uuid, BPLocation);
|
||||
break;
|
||||
}
|
||||
case ovrpEventType_SpaceShareResult:
|
||||
{
|
||||
unsigned char* BufData = buf.EventData;
|
||||
ovrpUInt64 OvrpRequestId = 0;
|
||||
memcpy(&OvrpRequestId, BufData, sizeof(OvrpRequestId));
|
||||
|
||||
ovrpEventSpaceShareResult SpaceShareSpaceResult;
|
||||
GetEventData(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, SpaceShareSpaceResult.result);
|
||||
|
||||
break;
|
||||
}
|
||||
case ovrpEventType_None:
|
||||
default:
|
||||
{
|
||||
EventPollResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform)
|
||||
{
|
||||
bool bValidHMD;
|
||||
OculusXRHMD::FOculusXRHMD* HMD = GetHMD(bValidHMD);
|
||||
if (!bValidHMD)
|
||||
{
|
||||
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 static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::DestroySpace(uint64 Space)
|
||||
{
|
||||
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().DestroySpace(static_cast<ovrpSpace*>(&Space));
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("DestroySpace Space ID: %llu"), Space);
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SetSpaceComponentStatus(uint64 Space, EOculusXRSpaceComponentType SpaceComponentType, bool Enable, float Timeout, uint64& OutRequestId)
|
||||
{
|
||||
ovrpSpaceComponentType ovrpType = ConvertToOvrpComponentType(SpaceComponentType);
|
||||
ovrpUInt64 OvrpOutRequestId = 0;
|
||||
|
||||
const ovrpUInt64 OVRPSpace = Space;
|
||||
|
||||
// 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,
|
||||
&OvrpOutRequestId);
|
||||
|
||||
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("SetSpaceComponentStatus Request ID: %llu"), OutRequestId);
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceComponentStatus(uint64 Space, EOculusXRSpaceComponentType SpaceComponentType, bool& OutEnabled, bool& OutChangePending)
|
||||
{
|
||||
const ovrpUInt64 OVRPSpace = Space;
|
||||
ovrpBool OutOvrpEnabled = ovrpBool_False;
|
||||
ovrpBool OutOvrpChangePending = ovrpBool_False;
|
||||
|
||||
ovrpSpaceComponentType ovrpType = ConvertToOvrpComponentType(SpaceComponentType);
|
||||
|
||||
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceComponentStatus(
|
||||
&OVRPSpace,
|
||||
ovrpType,
|
||||
&OutOvrpEnabled,
|
||||
&OutOvrpChangePending);
|
||||
|
||||
OutEnabled = (OutOvrpEnabled == ovrpBool_True);
|
||||
OutChangePending = (OutOvrpChangePending == ovrpBool_True);
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSupportedAnchorComponents(uint64 Handle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes)
|
||||
{
|
||||
if (!FOculusXRHMDModule::GetPluginWrapper().GetInitialized())
|
||||
{
|
||||
return EOculusXRAnchorResult::Failure;
|
||||
}
|
||||
|
||||
ovrpSpace ovrSpace = Handle;
|
||||
TArray<ovrpSpaceComponentType> ovrComponentTypes;
|
||||
ovrpUInt32 input = 0;
|
||||
ovrpUInt32 output = 0;
|
||||
|
||||
ovrpResult enumerateResult = FOculusXRHMDModule::GetPluginWrapper().EnumerateSpaceSupportedComponents(&ovrSpace, input, &output, nullptr);
|
||||
if (!OVRP_SUCCESS(enumerateResult))
|
||||
{
|
||||
return static_cast<EOculusXRAnchorResult::Type>(enumerateResult);
|
||||
}
|
||||
|
||||
input = output;
|
||||
ovrComponentTypes.SetNumZeroed(output);
|
||||
|
||||
enumerateResult = FOculusXRHMDModule::GetPluginWrapper().EnumerateSpaceSupportedComponents(&ovrSpace, input, &output, ovrComponentTypes.GetData());
|
||||
if (!OVRP_SUCCESS(enumerateResult))
|
||||
{
|
||||
return static_cast<EOculusXRAnchorResult::Type>(enumerateResult);
|
||||
}
|
||||
|
||||
OutSupportedTypes.SetNumZeroed(ovrComponentTypes.Num());
|
||||
for (int i = 0; i < ovrComponentTypes.Num(); ++i)
|
||||
{
|
||||
OutSupportedTypes[i] = ConvertToUEComponentType(ovrComponentTypes[i]);
|
||||
}
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(enumerateResult);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SaveAnchor(uint64 Space,
|
||||
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;
|
||||
}
|
||||
|
||||
ovrpUInt64 OvrpOutRequestId = 0;
|
||||
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SaveSpace(&Space, OvrpStorageLocation, OvrpStoragePersistenceMode, &OvrpOutRequestId);
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Saving space with: SpaceID: %llu -- Location: %d -- Persistence: %d -- OutID: %llu"), Space, OvrpStorageLocation, OvrpStoragePersistenceMode, OvrpOutRequestId);
|
||||
|
||||
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
|
||||
|
||||
if (OVRP_FAILURE(Result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("FOculusXRHMD::SaveAnchor failed with: SpaceID: %llu -- Location: %d -- Persistence: %d"), Space, OvrpStorageLocation, OvrpStoragePersistenceMode);
|
||||
}
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::SaveAnchorList(const TArray<uint64>& Spaces, 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;
|
||||
}
|
||||
|
||||
ovrpUInt64 OvrpOutRequestId = 0;
|
||||
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().SaveSpaceList(Spaces.GetData(), Spaces.Num(), OvrpStorageLocation, &OvrpOutRequestId);
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Saving space list: Location: %d -- OutID: %llu"), OvrpStorageLocation, OvrpOutRequestId);
|
||||
for (auto& it : Spaces)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("\tSpaceID: %llu"), it);
|
||||
}
|
||||
|
||||
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
|
||||
|
||||
if (OVRP_FAILURE(Result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("SaveSpaceList failed -- Result: %d"), Result);
|
||||
}
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::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;
|
||||
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 static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::QuerySpaces(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId)
|
||||
{
|
||||
ovrpUInt64 OvrpOutRequestId = 0;
|
||||
ovrpResult QuerySpacesResult = ovrpFailure;
|
||||
ovrpSpaceQueryInfo ovrQueryInfo = ConvertToOVRPSpaceQueryInfo(QueryInfo);
|
||||
QuerySpacesResult = FOculusXRHMDModule::GetPluginWrapper().QuerySpaces(&ovrQueryInfo, &OvrpOutRequestId);
|
||||
|
||||
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(QuerySpacesResult);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::ShareSpaces(const TArray<uint64>& Spaces, 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);
|
||||
}
|
||||
|
||||
ovrpUInt64 OvrpOutRequestId = 0;
|
||||
const ovrpResult ShareSpacesResult = FOculusXRHMDModule::GetPluginWrapper().ShareSpaces(Spaces.GetData(), Spaces.Num(), OvrpUsers.GetData(), OvrpUsers.Num(), &OvrpOutRequestId);
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Sharing space list -- OutID: %llu"), OvrpOutRequestId);
|
||||
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 : Spaces)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("\tSpaceID: %llu"), it);
|
||||
}
|
||||
|
||||
memcpy(&OutRequestId, &OvrpOutRequestId, sizeof(uint64));
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(ShareSpacesResult);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceContainerUUIDs(uint64 Space, 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(&Space, &ovrSpaceContainer);
|
||||
if (OVRP_FAILURE(result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space container %d"), result);
|
||||
return static_cast<EOculusXRAnchorResult::Type>(result);
|
||||
}
|
||||
|
||||
// Retrieve the actual array of UUIDs
|
||||
ovrUuidArray.SetNum(ovrSpaceContainer.uuidCountOutput);
|
||||
ovrSpaceContainer.uuidCapacityInput = ovrSpaceContainer.uuidCountOutput;
|
||||
ovrSpaceContainer.uuids = ovrUuidArray.GetData();
|
||||
|
||||
result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&Space, &ovrSpaceContainer);
|
||||
if (OVRP_FAILURE(result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space container %d"), result);
|
||||
return static_cast<EOculusXRAnchorResult::Type>(result);
|
||||
}
|
||||
|
||||
// Write out the remaining UUIDs
|
||||
OutUUIDs.Reserve(ovrUuidArray.Num());
|
||||
for (auto& it : ovrUuidArray)
|
||||
{
|
||||
OutUUIDs.Add(FOculusXRUUID(it.data));
|
||||
}
|
||||
|
||||
return EOculusXRAnchorResult::Success;
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceScenePlane(uint64 Space, FVector& OutPos, FVector& OutSize)
|
||||
{
|
||||
OutPos.X = OutPos.Y = OutPos.Z = 0.f;
|
||||
OutSize.X = OutSize.Y = OutSize.Z = 0.f;
|
||||
|
||||
ovrpRectf rect;
|
||||
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceBoundingBox2D(&Space, &rect);
|
||||
|
||||
if (OVRP_SUCCESS(Result))
|
||||
{
|
||||
// Convert to UE4's coordinates system
|
||||
OutPos.Y = rect.Pos.x;
|
||||
OutPos.Z = rect.Pos.y;
|
||||
OutSize.Y = rect.Size.w;
|
||||
OutSize.Z = rect.Size.h;
|
||||
}
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceSceneVolume(uint64 Space, FVector& OutPos, FVector& OutSize)
|
||||
{
|
||||
OutPos.X = OutPos.Y = OutPos.Z = 0.f;
|
||||
OutSize.X = OutSize.Y = OutSize.Z = 0.f;
|
||||
|
||||
ovrpBoundsf bounds;
|
||||
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceBoundingBox3D(&Space, &bounds);
|
||||
|
||||
if (OVRP_SUCCESS(Result))
|
||||
{
|
||||
// Convert from OpenXR's right-handed to Unreal's left-handed coordinate system.
|
||||
// OpenXR Unreal
|
||||
// | y | z
|
||||
// | |
|
||||
//z <----+ +----> x
|
||||
// / /
|
||||
// x/ y/
|
||||
//
|
||||
OutPos.X = -bounds.Pos.z;
|
||||
OutPos.Y = bounds.Pos.x;
|
||||
OutPos.Z = bounds.Pos.y;
|
||||
|
||||
// The position represents the corner of the volume which has the lowest value
|
||||
// of each axis. Since we flipped the sign of one of the axes we need to adjust
|
||||
// the position to the other side of the volume
|
||||
OutPos.X -= bounds.Size.d;
|
||||
|
||||
// We keep the size positive for all dimensions
|
||||
OutSize.X = bounds.Size.d;
|
||||
OutSize.Y = bounds.Size.w;
|
||||
OutSize.Z = bounds.Size.h;
|
||||
}
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceSemanticClassification(uint64 Space, TArray<FString>& OutSemanticClassifications)
|
||||
{
|
||||
OutSemanticClassifications.Empty();
|
||||
|
||||
const int32 maxByteSize = 1024;
|
||||
char labelsChars[maxByteSize];
|
||||
|
||||
ovrpSemanticLabels labels;
|
||||
labels.byteCapacityInput = maxByteSize;
|
||||
labels.labels = labelsChars;
|
||||
|
||||
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceSemanticLabels(&Space, &labels);
|
||||
|
||||
if (OVRP_SUCCESS(Result))
|
||||
{
|
||||
FString labelsStr(labels.byteCountOutput, labels.labels);
|
||||
labelsStr.ParseIntoArray(OutSemanticClassifications, TEXT(","));
|
||||
}
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceContainer(uint64 Space, TArray<FOculusXRUUID>& OutContainerUuids)
|
||||
{
|
||||
OutContainerUuids.Empty();
|
||||
|
||||
ovrpSpaceContainer container;
|
||||
|
||||
ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&Space, &container);
|
||||
|
||||
if (OVRP_SUCCESS(Result))
|
||||
{
|
||||
TArray<ovrpUuid> uuids;
|
||||
size_t size = container.uuidCountOutput;
|
||||
uuids.InsertZeroed(0, size);
|
||||
container.uuidCapacityInput = size;
|
||||
container.uuids = uuids.GetData();
|
||||
Result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceContainer(&Space, &container);
|
||||
if (OVRP_SUCCESS(Result))
|
||||
{
|
||||
OutContainerUuids.InsertZeroed(0, size);
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
OutContainerUuids[i] = FOculusXRUUID(uuids[i].data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<EOculusXRAnchorResult::Type>(Result);
|
||||
}
|
||||
|
||||
EOculusXRAnchorResult::Type FOculusXRAnchorManager::GetSpaceBoundary2D(uint64 Space, TArray<FVector2f>& OutVertices)
|
||||
{
|
||||
TArray<ovrpVector2f> vertices;
|
||||
|
||||
// Get the number of elements in the container
|
||||
ovrpBoundary2D boundary;
|
||||
boundary.vertexCapacityInput = 0;
|
||||
boundary.vertexCountOutput = 0;
|
||||
boundary.vertices = nullptr;
|
||||
|
||||
ovrpResult result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceBoundary2D(&Space, &boundary);
|
||||
if (OVRP_FAILURE(result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space boundary 2d %d"), result);
|
||||
return static_cast<EOculusXRAnchorResult::Type>(result);
|
||||
}
|
||||
|
||||
// Retrieve the actual array of vertices
|
||||
vertices.SetNum(boundary.vertexCountOutput);
|
||||
boundary.vertexCapacityInput = boundary.vertexCountOutput;
|
||||
boundary.vertices = vertices.GetData();
|
||||
|
||||
result = FOculusXRHMDModule::GetPluginWrapper().GetSpaceBoundary2D(&Space, &boundary);
|
||||
if (OVRP_FAILURE(result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to get space boundary 2d %d"), result);
|
||||
return static_cast<EOculusXRAnchorResult::Type>(result);
|
||||
}
|
||||
|
||||
// Write out the vertices
|
||||
OutVertices.Reserve(vertices.Num());
|
||||
for (const auto& it : vertices)
|
||||
{
|
||||
OutVertices.Add(FVector2f(it.x, it.y));
|
||||
}
|
||||
|
||||
return EOculusXRAnchorResult::Success;
|
||||
}
|
||||
|
||||
|
||||
} // namespace OculusXRAnchors
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "OculusXRAnchorComponent.h"
|
||||
#include "OculusXRHMDPrivate.h"
|
||||
|
||||
namespace OculusXRAnchors
|
||||
{
|
||||
struct OCULUSXRANCHORS_API FOculusXRAnchorManager
|
||||
{
|
||||
static EOculusXRAnchorResult::Type CreateAnchor(const FTransform& InTransform, uint64& OutRequestId, const FTransform& CameraTransform);
|
||||
static EOculusXRAnchorResult::Type DestroySpace(uint64 Space);
|
||||
static EOculusXRAnchorResult::Type SetSpaceComponentStatus(uint64 Space, EOculusXRSpaceComponentType SpaceComponentType, bool Enable, float Timeout, uint64& OutRequestId);
|
||||
static EOculusXRAnchorResult::Type GetSpaceComponentStatus(uint64 Space, EOculusXRSpaceComponentType SpaceComponentType, bool& OutEnabled, bool& OutChangePending);
|
||||
static EOculusXRAnchorResult::Type GetSupportedAnchorComponents(uint64 Handle, TArray<EOculusXRSpaceComponentType>& OutSupportedTypes);
|
||||
static EOculusXRAnchorResult::Type SaveAnchor(uint64 Space, EOculusXRSpaceStorageLocation StorageLocation, EOculusXRSpaceStoragePersistenceMode StoragePersistenceMode, uint64& OutRequestId);
|
||||
static EOculusXRAnchorResult::Type SaveAnchorList(const TArray<uint64>& Spaces, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId);
|
||||
static EOculusXRAnchorResult::Type EraseAnchor(uint64 AnchorHandle, EOculusXRSpaceStorageLocation StorageLocation, uint64& OutRequestId);
|
||||
static EOculusXRAnchorResult::Type QuerySpaces(const FOculusXRSpaceQueryInfo& QueryInfo, uint64& OutRequestId);
|
||||
static EOculusXRAnchorResult::Type ShareSpaces(const TArray<uint64>& Spaces, const TArray<uint64>& UserIds, uint64& OutRequestId);
|
||||
static EOculusXRAnchorResult::Type GetSpaceContainerUUIDs(uint64 Space, TArray<FOculusXRUUID>& OutUUIDs);
|
||||
static EOculusXRAnchorResult::Type GetSpaceScenePlane(uint64 Space, FVector& OutPos, FVector& OutSize);
|
||||
static EOculusXRAnchorResult::Type GetSpaceSceneVolume(uint64 Space, FVector& OutPos, FVector& OutSize);
|
||||
static EOculusXRAnchorResult::Type GetSpaceSemanticClassification(uint64 Space, TArray<FString>& OutSemanticClassification);
|
||||
static EOculusXRAnchorResult::Type GetSpaceContainer(uint64 Space, TArray<FOculusXRUUID>& OutContainerUuids);
|
||||
static EOculusXRAnchorResult::Type GetSpaceBoundary2D(uint64 Space, TArray<FVector2f>& OutVertices);
|
||||
|
||||
|
||||
static void OnPollEvent(ovrpEventDataBuffer* EventDataBuffer, bool& EventPollResult);
|
||||
};
|
||||
} // namespace OculusXRAnchors
|
||||
@@ -0,0 +1,96 @@
|
||||
// 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 ovrpXRUuidArray& UuidArray)
|
||||
{
|
||||
FMemory::Memcpy(UUIDBytes, UuidArray);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
uint32 GetTypeHash(const FOculusXRUUID& Other)
|
||||
{
|
||||
return FCrc::MemCrc32(&Other.UUIDBytes, sizeof(Other.UUIDBytes));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -0,0 +1,732 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRAnchors.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "Camera/PlayerCameraManager.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "OculusXRAnchorsModule.h"
|
||||
#include "OculusXRAnchorDelegates.h"
|
||||
#include "OculusXRHMDModule.h"
|
||||
#include "OculusXRAnchorManager.h"
|
||||
#include "OculusXRSpatialAnchorComponent.h"
|
||||
#include "OculusXRAnchorBPFunctionLibrary.h"
|
||||
#include "OculusXRTelemetryAnchorsEvents.h"
|
||||
|
||||
namespace OculusXRAnchors
|
||||
{
|
||||
|
||||
void FOculusXRAnchors::Initialize()
|
||||
{
|
||||
DelegateHandleAnchorCreate = FOculusXRAnchorEventDelegates::OculusSpatialAnchorCreateComplete.AddRaw(this, &FOculusXRAnchors::HandleSpatialAnchorCreateComplete);
|
||||
DelegateHandleAnchorErase = FOculusXRAnchorEventDelegates::OculusSpaceEraseComplete.AddRaw(this, &FOculusXRAnchors::HandleAnchorEraseComplete);
|
||||
DelegateHandleSetComponentStatus = FOculusXRAnchorEventDelegates::OculusSpaceSetComponentStatusComplete.AddRaw(this, &FOculusXRAnchors::HandleSetComponentStatusComplete);
|
||||
DelegateHandleAnchorSave = FOculusXRAnchorEventDelegates::OculusSpaceSaveComplete.AddRaw(this, &FOculusXRAnchors::HandleAnchorSaveComplete);
|
||||
DelegateHandleAnchorSaveList = FOculusXRAnchorEventDelegates::OculusSpaceListSaveComplete.AddRaw(this, &FOculusXRAnchors::HandleAnchorSaveListComplete);
|
||||
DelegateHandleQueryResultsBegin = FOculusXRAnchorEventDelegates::OculusSpaceQueryResults.AddRaw(this, &FOculusXRAnchors::HandleAnchorQueryResultsBegin);
|
||||
DelegateHandleQueryResultElement = FOculusXRAnchorEventDelegates::OculusSpaceQueryResult.AddRaw(this, &FOculusXRAnchors::HandleAnchorQueryResultElement);
|
||||
DelegateHandleQueryComplete = FOculusXRAnchorEventDelegates::OculusSpaceQueryComplete.AddRaw(this, &FOculusXRAnchors::HandleAnchorQueryComplete);
|
||||
DelegateHandleAnchorShare = FOculusXRAnchorEventDelegates::OculusSpaceShareComplete.AddRaw(this, &FOculusXRAnchors::HandleAnchorSharingComplete);
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::Teardown()
|
||||
{
|
||||
FOculusXRAnchorEventDelegates::OculusSpatialAnchorCreateComplete.Remove(DelegateHandleAnchorCreate);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceEraseComplete.Remove(DelegateHandleAnchorErase);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceSetComponentStatusComplete.Remove(DelegateHandleSetComponentStatus);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceSaveComplete.Remove(DelegateHandleAnchorSave);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceListSaveComplete.Remove(DelegateHandleAnchorSaveList);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceQueryResults.Remove(DelegateHandleQueryResultsBegin);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceQueryResult.Remove(DelegateHandleQueryResultElement);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceQueryComplete.Remove(DelegateHandleQueryComplete);
|
||||
FOculusXRAnchorEventDelegates::OculusSpaceShareComplete.Remove(DelegateHandleAnchorShare);
|
||||
}
|
||||
|
||||
FOculusXRAnchors* FOculusXRAnchors::GetInstance()
|
||||
{
|
||||
return FOculusXRAnchorsModule::GetOculusAnchors();
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::CreateSpatialAnchor(const FTransform& InTransform, AActor* TargetActor, const FOculusXRSpatialAnchorCreateDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
if (!IsValid(TargetActor))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid actor provided when attempting to create a spatial anchor."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
UWorld* World = TargetActor->GetWorld();
|
||||
if (!IsValid(World))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve World Context while creating spatial anchor."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
APlayerController* PlayerController = World->GetFirstPlayerController();
|
||||
if (!IsValid(PlayerController))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve Player Controller while creating spatial anchor"));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
APlayerCameraManager* PlayerCameraManager = PlayerController->PlayerCameraManager;
|
||||
FTransform MainCameraTransform = FTransform::Identity;
|
||||
if (IsValid(PlayerCameraManager))
|
||||
{
|
||||
MainCameraTransform.SetLocation(PlayerCameraManager->GetCameraLocation());
|
||||
MainCameraTransform.SetRotation(FQuat(PlayerCameraManager->GetCameraRotation()));
|
||||
}
|
||||
|
||||
UOculusXRAnchorComponent* Anchor = Cast<UOculusXRAnchorComponent>(TargetActor->GetComponentByClass(UOculusXRAnchorComponent::StaticClass()));
|
||||
if (IsValid(Anchor) && Anchor->HasValidHandle())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Actor targeted to create anchor already has an anchor component with a valid handle."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64 RequestId = 0;
|
||||
OutResult = FOculusXRAnchorManager::CreateAnchor(InTransform, RequestId, MainCameraTransform);
|
||||
bool bAsyncStartSuccess = UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
|
||||
OculusXRTelemetry::Events::FAnchorsCreateRequest Trace(static_cast<int>(GetTypeHash(RequestId)));
|
||||
if (bAsyncStartSuccess)
|
||||
{
|
||||
CreateAnchorBinding AnchorData;
|
||||
AnchorData.RequestId = RequestId;
|
||||
AnchorData.Actor = TargetActor;
|
||||
AnchorData.Binding = ResultCallback;
|
||||
|
||||
FOculusXRAnchors* SDKInstance = GetInstance();
|
||||
SDKInstance->CreateSpatialAnchorBindings.Add(RequestId, AnchorData);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async create spatial anchor."));
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, nullptr);
|
||||
Trace.SetResult(OculusXRTelemetry::EAction::Cancel).End();
|
||||
}
|
||||
|
||||
return bAsyncStartSuccess;
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::EraseAnchor(UOculusXRAnchorComponent* Anchor, const FOculusXRAnchorEraseDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
if (!IsValid(Anchor))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid anchor provided when attempting to erase an anchor."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, FOculusXRUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Anchor->HasValidHandle())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Cannot erase anchor with invalid handle."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, FOculusXRUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Anchor->IsStoredAtLocation(EOculusXRSpaceStorageLocation::Local))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Only local anchors can be erased."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, FOculusXRUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64 RequestId = 0;
|
||||
|
||||
// Erase only supports local anchors
|
||||
EOculusXRAnchorResult::Type Result = FOculusXRAnchorManager::EraseAnchor(Anchor->GetHandle(), EOculusXRSpaceStorageLocation::Local, RequestId);
|
||||
bool bAsyncStartSuccess = UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(Result);
|
||||
|
||||
OculusXRTelemetry::Events::FAnchorsEraseRequest Trace(static_cast<int>(GetTypeHash(RequestId)));
|
||||
if (bAsyncStartSuccess)
|
||||
{
|
||||
EraseAnchorBinding EraseData;
|
||||
EraseData.RequestId = RequestId;
|
||||
EraseData.Binding = ResultCallback;
|
||||
EraseData.Anchor = Anchor;
|
||||
|
||||
FOculusXRAnchors* SDKInstance = GetInstance();
|
||||
SDKInstance->EraseAnchorBindings.Add(RequestId, EraseData);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async erase spatial anchor."));
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, FOculusXRUUID());
|
||||
Trace.SetResult(OculusXRTelemetry::EAction::Cancel).End();
|
||||
}
|
||||
|
||||
return bAsyncStartSuccess;
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::DestroyAnchor(uint64 AnchorHandle, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
OutResult = FOculusXRAnchorManager::DestroySpace(AnchorHandle);
|
||||
|
||||
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::SetAnchorComponentStatus(UOculusXRAnchorComponent* Anchor, EOculusXRSpaceComponentType SpaceComponentType, bool Enable, float Timeout, const FOculusXRAnchorSetComponentStatusDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
if (!IsValid(Anchor))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid anchor provided when attempting to set anchor component status."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, FOculusXRUInt64(), EOculusXRSpaceComponentType::Undefined, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Anchor->HasValidHandle())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Anchor provided to set anchor component status has invalid handle."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, FOculusXRUInt64(), EOculusXRSpaceComponentType::Undefined, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64 RequestId = 0;
|
||||
OutResult = FOculusXRAnchorManager::SetSpaceComponentStatus(Anchor->GetHandle(), SpaceComponentType, Enable, Timeout, RequestId);
|
||||
bool bAsyncStartSuccess = UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
|
||||
OculusXRTelemetry::Events::FAnchorsSetComponentStatusRequest Trace(static_cast<int>(GetTypeHash(RequestId)));
|
||||
if (bAsyncStartSuccess)
|
||||
{
|
||||
SetComponentStatusBinding SetComponentStatusData;
|
||||
SetComponentStatusData.RequestId = RequestId;
|
||||
SetComponentStatusData.Binding = ResultCallback;
|
||||
SetComponentStatusData.AnchorHandle = Anchor->GetHandle();
|
||||
|
||||
FOculusXRAnchors* SDKInstance = GetInstance();
|
||||
SDKInstance->SetComponentStatusBindings.Add(RequestId, SetComponentStatusData);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async call to set anchor component status."));
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, FOculusXRUInt64(), EOculusXRSpaceComponentType::Undefined, false);
|
||||
Trace.SetResult(OculusXRTelemetry::EAction::Cancel).End();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::GetAnchorComponentStatus(UOculusXRAnchorComponent* Anchor, EOculusXRSpaceComponentType SpaceComponentType, bool& OutEnabled, bool& OutChangePending, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
if (!IsValid(Anchor))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid anchor provided when attempting to get space component status."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Anchor->HasValidHandle())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Anchor provided to get space component status has invalid handle."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetComponentStatus(Anchor->GetHandle(), SpaceComponentType, OutEnabled, OutChangePending, OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::GetAnchorSupportedComponents(UOculusXRAnchorComponent* Anchor, TArray<EOculusXRSpaceComponentType>& OutSupportedComponents, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
if (!IsValid(Anchor))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid anchor provided when attempting to get space component status."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Anchor->HasValidHandle())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Anchor provided to get space component status has invalid handle."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetSupportedComponents(Anchor->GetHandle(), OutSupportedComponents, OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::SetComponentStatus(uint64 Space, EOculusXRSpaceComponentType SpaceComponentType, bool Enable, float Timeout, const FOculusXRAnchorSetComponentStatusDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
uint64 RequestId = 0;
|
||||
OutResult = FOculusXRAnchorManager::SetSpaceComponentStatus(Space, SpaceComponentType, Enable, Timeout, RequestId);
|
||||
bool bAsyncStartSuccess = UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
|
||||
if (bAsyncStartSuccess)
|
||||
{
|
||||
SetComponentStatusBinding SetComponentStatusData;
|
||||
SetComponentStatusData.RequestId = RequestId;
|
||||
SetComponentStatusData.Binding = ResultCallback;
|
||||
SetComponentStatusData.AnchorHandle = Space;
|
||||
|
||||
FOculusXRAnchors* SDKInstance = GetInstance();
|
||||
SDKInstance->SetComponentStatusBindings.Add(RequestId, SetComponentStatusData);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async call to set anchor component status."));
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, Space, SpaceComponentType, Enable);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::GetComponentStatus(uint64 AnchorHandle, EOculusXRSpaceComponentType SpaceComponentType, bool& OutEnabled, bool& OutChangePending, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
OutResult = FOculusXRAnchorManager::GetSpaceComponentStatus(AnchorHandle, SpaceComponentType, OutEnabled, OutChangePending);
|
||||
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::GetSupportedComponents(uint64 AnchorHandle, TArray<EOculusXRSpaceComponentType>& OutSupportedComponents, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
OutResult = FOculusXRAnchorManager::GetSupportedAnchorComponents(AnchorHandle, OutSupportedComponents);
|
||||
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::SaveAnchor(UOculusXRAnchorComponent* Anchor, EOculusXRSpaceStorageLocation StorageLocation, const FOculusXRAnchorSaveDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
if (!IsValid(Anchor))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid anchor provided when attempting to save anchor."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Anchor->HasValidHandle())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Anchor provided to save anchor has invalid handle."));
|
||||
OutResult = EOculusXRAnchorResult::Failure;
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64 RequestId = 0;
|
||||
OutResult = FOculusXRAnchorManager::SaveAnchor(Anchor->GetHandle(), StorageLocation, EOculusXRSpaceStoragePersistenceMode::Indefinite, RequestId);
|
||||
bool bAsyncStartSuccess = UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
|
||||
OculusXRTelemetry::Events::FAnchorsSaveRequest Trace(static_cast<int>(GetTypeHash(RequestId)));
|
||||
if (bAsyncStartSuccess)
|
||||
{
|
||||
SaveAnchorBinding SaveAnchorData;
|
||||
SaveAnchorData.RequestId = RequestId;
|
||||
SaveAnchorData.Binding = ResultCallback;
|
||||
SaveAnchorData.Location = StorageLocation;
|
||||
SaveAnchorData.Anchor = Anchor;
|
||||
|
||||
FOculusXRAnchors* SDKInstance = GetInstance();
|
||||
SDKInstance->AnchorSaveBindings.Add(RequestId, SaveAnchorData);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async call to save anchor."));
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, nullptr);
|
||||
Trace.SetResult(OculusXRTelemetry::EAction::Cancel).End();
|
||||
}
|
||||
|
||||
return bAsyncStartSuccess;
|
||||
}
|
||||
|
||||
void AnchorComponentsToReferences(const TArray<UOculusXRAnchorComponent*>& Anchors, TArray<uint64>& Handles, TArray<TWeakObjectPtr<UOculusXRAnchorComponent>>& AnchorPtrs)
|
||||
{
|
||||
Handles.Empty();
|
||||
AnchorPtrs.Empty();
|
||||
|
||||
for (auto& AnchorInstance : Anchors)
|
||||
{
|
||||
if (!IsValid(AnchorInstance))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Invalid anchor provided when attempting to process anchor list."));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!AnchorInstance->HasValidHandle())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Anchor provided to anchor list has invalid handle."));
|
||||
continue;
|
||||
}
|
||||
|
||||
Handles.Add(AnchorInstance->GetHandle().GetValue());
|
||||
AnchorPtrs.Add(AnchorInstance);
|
||||
}
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::SaveAnchorList(const TArray<UOculusXRAnchorComponent*>& Anchors, EOculusXRSpaceStorageLocation StorageLocation, const FOculusXRAnchorSaveListDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
TArray<uint64> Handles;
|
||||
TArray<TWeakObjectPtr<UOculusXRAnchorComponent>> SavedAnchors;
|
||||
|
||||
AnchorComponentsToReferences(Anchors, Handles, SavedAnchors);
|
||||
|
||||
uint64 RequestId = 0;
|
||||
OutResult = FOculusXRAnchorManager::SaveAnchorList(Handles, StorageLocation, RequestId);
|
||||
bool bAsyncStartSuccess = UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
|
||||
if (bAsyncStartSuccess)
|
||||
{
|
||||
SaveAnchorListBinding SaveAnchorListData;
|
||||
SaveAnchorListData.RequestId = RequestId;
|
||||
SaveAnchorListData.Binding = ResultCallback;
|
||||
SaveAnchorListData.Location = StorageLocation;
|
||||
SaveAnchorListData.SavedAnchors = SavedAnchors;
|
||||
|
||||
FOculusXRAnchors* SDKInstance = GetInstance();
|
||||
SDKInstance->AnchorSaveListBindings.Add(RequestId, SaveAnchorListData);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async call to save anchor list."));
|
||||
ResultCallback.ExecuteIfBound(OutResult, TArray<UOculusXRAnchorComponent*>());
|
||||
}
|
||||
|
||||
return bAsyncStartSuccess;
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::QueryAnchors(const TArray<FOculusXRUUID>& AnchorUUIDs, EOculusXRSpaceStorageLocation Location, const FOculusXRAnchorQueryDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
FOculusXRSpaceQueryInfo QueryInfo;
|
||||
QueryInfo.FilterType = EOculusXRSpaceQueryFilterType::FilterByIds;
|
||||
QueryInfo.IDFilter = AnchorUUIDs;
|
||||
QueryInfo.Location = Location;
|
||||
QueryInfo.MaxQuerySpaces = AnchorUUIDs.Num();
|
||||
|
||||
return QueryAnchorsAdvanced(QueryInfo, ResultCallback, OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::QueryAnchorsAdvanced(const FOculusXRSpaceQueryInfo& QueryInfo, const FOculusXRAnchorQueryDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
uint64 RequestId = 0;
|
||||
OutResult = FOculusXRAnchorManager::QuerySpaces(QueryInfo, RequestId);
|
||||
bool bAsyncStartSuccess = UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
|
||||
OculusXRTelemetry::Events::FAnchorsQueryRequest Trace(static_cast<int>(GetTypeHash(RequestId)));
|
||||
if (bAsyncStartSuccess)
|
||||
{
|
||||
AnchorQueryBinding QueryResults;
|
||||
QueryResults.RequestId = RequestId;
|
||||
QueryResults.Binding = ResultCallback;
|
||||
QueryResults.Location = QueryInfo.Location;
|
||||
|
||||
FOculusXRAnchors* SDKInstance = GetInstance();
|
||||
SDKInstance->AnchorQueryBindings.Add(RequestId, QueryResults);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async call to query anchors."));
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, TArray<FOculusXRSpaceQueryResult>());
|
||||
Trace.SetResult(OculusXRTelemetry::EAction::Cancel).End();
|
||||
}
|
||||
|
||||
return bAsyncStartSuccess;
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::ShareAnchors(const TArray<UOculusXRAnchorComponent*>& Anchors, const TArray<uint64>& OculusUserIDs, const FOculusXRAnchorShareDelegate& ResultCallback, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
TArray<uint64> Handles;
|
||||
TArray<TWeakObjectPtr<UOculusXRAnchorComponent>> SharedAnchors;
|
||||
|
||||
AnchorComponentsToReferences(Anchors, Handles, SharedAnchors);
|
||||
|
||||
uint64 RequestId = 0;
|
||||
OutResult = FOculusXRAnchorManager::ShareSpaces(Handles, OculusUserIDs, RequestId);
|
||||
bool bAsyncStartSuccess = UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
|
||||
if (bAsyncStartSuccess)
|
||||
{
|
||||
ShareAnchorsBinding ShareAnchorsData;
|
||||
ShareAnchorsData.RequestId = RequestId;
|
||||
ShareAnchorsData.Binding = ResultCallback;
|
||||
ShareAnchorsData.SharedAnchors = SharedAnchors;
|
||||
ShareAnchorsData.OculusUserIds = OculusUserIDs;
|
||||
|
||||
FOculusXRAnchors* SDKInstance = GetInstance();
|
||||
SDKInstance->ShareAnchorsBindings.Add(RequestId, ShareAnchorsData);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to start async call to share anchor."));
|
||||
ResultCallback.ExecuteIfBound(EOculusXRAnchorResult::Failure, TArray<UOculusXRAnchorComponent*>(), TArray<uint64>());
|
||||
}
|
||||
|
||||
return bAsyncStartSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool FOculusXRAnchors::GetSpaceContainerUUIDs(uint64 Space, TArray<FOculusXRUUID>& OutUUIDs, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
OutResult = FOculusXRAnchorManager::GetSpaceContainerUUIDs(Space, OutUUIDs);
|
||||
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::GetSpaceScenePlane(uint64 Space, FVector& OutPos, FVector& OutSize, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
OutResult = FOculusXRAnchorManager::GetSpaceScenePlane(Space, OutPos, OutSize);
|
||||
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::GetSpaceSceneVolume(uint64 Space, FVector& OutPos, FVector& OutSize, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
OutResult = FOculusXRAnchorManager::GetSpaceSceneVolume(Space, OutPos, OutSize);
|
||||
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::GetSpaceSemanticClassification(uint64 Space, TArray<FString>& OutSemanticClassifications, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
OutResult = FOculusXRAnchorManager::GetSpaceSemanticClassification(Space, OutSemanticClassifications);
|
||||
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
}
|
||||
|
||||
bool FOculusXRAnchors::GetSpaceBoundary2D(uint64 Space, TArray<FVector2f>& OutVertices, EOculusXRAnchorResult::Type& OutResult)
|
||||
{
|
||||
OutResult = FOculusXRAnchorManager::GetSpaceBoundary2D(Space, OutVertices);
|
||||
return UOculusXRAnchorBPFunctionLibrary::IsAnchorResultSuccess(OutResult);
|
||||
}
|
||||
|
||||
|
||||
void FOculusXRAnchors::HandleSpatialAnchorCreateComplete(FOculusXRUInt64 RequestId, int Result, FOculusXRUInt64 Space, FOculusXRUUID UUID)
|
||||
{
|
||||
OculusXRTelemetry::Events::FAnchorsCreateResponse(static_cast<int>(GetTypeHash(RequestId)))
|
||||
.SetResult(OVRP_SUCCESS(Result) ? OculusXRTelemetry::EAction::Success : OculusXRTelemetry::EAction::Fail);
|
||||
CreateAnchorBinding* AnchorDataPtr = CreateSpatialAnchorBindings.Find(RequestId.GetValue());
|
||||
if (AnchorDataPtr == nullptr)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Error, TEXT("Couldn't find anchor data binding for create spatial anchor! Request: %llu"), RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (OVRP_FAILURE(Result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to create Spatial Anchor. Request: %llu -- Result: %d"), RequestId.GetValue(), Result);
|
||||
AnchorDataPtr->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), nullptr);
|
||||
CreateSpatialAnchorBindings.Remove(RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AnchorDataPtr->Actor.IsValid())
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Actor has been invalidated while creating actor. Request: %llu"), RequestId.GetValue());
|
||||
|
||||
// Clean up the orphaned space
|
||||
EOculusXRAnchorResult::Type AnchorResult;
|
||||
FOculusXRAnchors::DestroyAnchor(Space, AnchorResult);
|
||||
|
||||
AnchorDataPtr->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), nullptr);
|
||||
CreateSpatialAnchorBindings.Remove(RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
AActor* TargetActor = AnchorDataPtr->Actor.Get();
|
||||
|
||||
UOculusXRSpatialAnchorComponent* SpatialAnchorComponent = TargetActor->FindComponentByClass<UOculusXRSpatialAnchorComponent>();
|
||||
if (SpatialAnchorComponent == nullptr)
|
||||
{
|
||||
SpatialAnchorComponent = Cast<UOculusXRSpatialAnchorComponent>(TargetActor->AddComponentByClass(UOculusXRSpatialAnchorComponent::StaticClass(), false, FTransform::Identity, false));
|
||||
}
|
||||
|
||||
SpatialAnchorComponent->SetHandle(Space);
|
||||
SpatialAnchorComponent->SetUUID(UUID);
|
||||
|
||||
uint64 tempOut;
|
||||
FOculusXRAnchorManager::SetSpaceComponentStatus(Space, EOculusXRSpaceComponentType::Locatable, true, 0.0f, tempOut);
|
||||
FOculusXRAnchorManager::SetSpaceComponentStatus(Space, EOculusXRSpaceComponentType::Sharable, true, 0.0f, tempOut);
|
||||
FOculusXRAnchorManager::SetSpaceComponentStatus(Space, EOculusXRSpaceComponentType::Storable, true, 0.0f, tempOut);
|
||||
|
||||
AnchorDataPtr->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), SpatialAnchorComponent);
|
||||
CreateSpatialAnchorBindings.Remove(RequestId.GetValue());
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::HandleAnchorEraseComplete(FOculusXRUInt64 RequestId, int Result, FOculusXRUUID UUID, EOculusXRSpaceStorageLocation Location)
|
||||
{
|
||||
OculusXRTelemetry::Events::FAnchorsEraseResponse(static_cast<int>(GetTypeHash(RequestId)))
|
||||
.SetResult(OVRP_SUCCESS(Result) ? OculusXRTelemetry::EAction::Success : OculusXRTelemetry::EAction::Fail);
|
||||
EraseAnchorBinding* EraseDataPtr = EraseAnchorBindings.Find(RequestId.GetValue());
|
||||
if (EraseDataPtr == nullptr)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Error, TEXT("Couldn't find binding for space erase! Request: %llu"), RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (OVRP_FAILURE(Result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to erase Spatial Anchor. Request: %llu -- Result: %d"), RequestId.GetValue(), Result);
|
||||
EraseDataPtr->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), UUID);
|
||||
EraseAnchorBindings.Remove(RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (EraseDataPtr->Anchor.IsValid())
|
||||
{
|
||||
// Since you can only erase local anchors, just unset local anchor storage
|
||||
EraseDataPtr->Anchor->SetStoredLocation(EOculusXRSpaceStorageLocation::Local, false);
|
||||
}
|
||||
|
||||
EraseDataPtr->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), UUID);
|
||||
EraseAnchorBindings.Remove(RequestId.GetValue());
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::HandleSetComponentStatusComplete(FOculusXRUInt64 RequestId, int Result, FOculusXRUInt64 Space, FOculusXRUUID UUID, EOculusXRSpaceComponentType ComponentType, bool Enabled)
|
||||
{
|
||||
OculusXRTelemetry::Events::FAnchorsSetComponentStatusResponse(static_cast<int>(GetTypeHash(RequestId)))
|
||||
.SetResult(OVRP_SUCCESS(Result) ? OculusXRTelemetry::EAction::Success : OculusXRTelemetry::EAction::Fail);
|
||||
SetComponentStatusBinding* SetStatusBinding = SetComponentStatusBindings.Find(RequestId.GetValue());
|
||||
|
||||
if (SetStatusBinding == nullptr)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Couldn't find binding for set component status! Request: %llu"), RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (SetStatusBinding != nullptr)
|
||||
{
|
||||
SetStatusBinding->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), SetStatusBinding->AnchorHandle, ComponentType, Enabled);
|
||||
SetComponentStatusBindings.Remove(RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
SetStatusBinding->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), SetStatusBinding->AnchorHandle, ComponentType, Enabled);
|
||||
SetComponentStatusBindings.Remove(RequestId.GetValue());
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::HandleAnchorSaveComplete(FOculusXRUInt64 RequestId, FOculusXRUInt64 Space, bool Success, int Result, FOculusXRUUID UUID)
|
||||
{
|
||||
OculusXRTelemetry::Events::FAnchorsSaveResponse(static_cast<int>(GetTypeHash(RequestId)))
|
||||
.SetResult(OVRP_SUCCESS(Result) ? OculusXRTelemetry::EAction::Success : OculusXRTelemetry::EAction::Fail);
|
||||
SaveAnchorBinding* SaveAnchorData = AnchorSaveBindings.Find(RequestId.GetValue());
|
||||
if (SaveAnchorData == nullptr)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Error, TEXT("Couldn't find binding for save anchor! Request: %llu"), RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (OVRP_FAILURE(Result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to save Spatial Anchor. Request: %llu -- Result: %d -- Space: %llu"), RequestId.GetValue(), Result, Space.GetValue());
|
||||
SaveAnchorData->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), SaveAnchorData->Anchor.Get());
|
||||
AnchorSaveBindings.Remove(RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (SaveAnchorData->Anchor.IsValid())
|
||||
{
|
||||
SaveAnchorData->Anchor->SetStoredLocation(SaveAnchorData->Location, true);
|
||||
}
|
||||
|
||||
SaveAnchorData->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), SaveAnchorData->Anchor.Get());
|
||||
AnchorSaveBindings.Remove(RequestId.GetValue());
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::HandleAnchorSaveListComplete(FOculusXRUInt64 RequestId, int Result)
|
||||
{
|
||||
SaveAnchorListBinding* SaveListData = AnchorSaveListBindings.Find(RequestId.GetValue());
|
||||
if (SaveListData == nullptr)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Error, TEXT("Couldn't find binding for save anchor list! Request: %llu"), RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all anchors
|
||||
TArray<UOculusXRAnchorComponent*> SavedAnchors;
|
||||
for (auto& WeakAnchor : SaveListData->SavedAnchors)
|
||||
{
|
||||
if (WeakAnchor.IsValid())
|
||||
{
|
||||
SavedAnchors.Add(WeakAnchor.Get());
|
||||
}
|
||||
}
|
||||
|
||||
// Failed to save
|
||||
if (OVRP_FAILURE(Result))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to save Spatial Anchors. Request: %llu -- Result: %d"), RequestId.GetValue(), Result);
|
||||
SaveListData->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), SavedAnchors);
|
||||
AnchorSaveListBindings.Remove(RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
// Set new storage location
|
||||
for (auto& SavedAnchor : SavedAnchors)
|
||||
{
|
||||
SavedAnchor->SetStoredLocation(SaveListData->Location, true);
|
||||
}
|
||||
|
||||
SaveListData->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), SavedAnchors);
|
||||
AnchorSaveListBindings.Remove(RequestId.GetValue());
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::HandleAnchorQueryResultsBegin(FOculusXRUInt64 RequestId)
|
||||
{
|
||||
// no op
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::HandleAnchorQueryResultElement(FOculusXRUInt64 RequestId, FOculusXRUInt64 Space, FOculusXRUUID UUID)
|
||||
{
|
||||
AnchorQueryBinding* ResultPtr = AnchorQueryBindings.Find(RequestId.GetValue());
|
||||
if (ResultPtr)
|
||||
{
|
||||
uint64 tempOut;
|
||||
TArray<EOculusXRSpaceComponentType> supportedTypes;
|
||||
FOculusXRAnchorManager::GetSupportedAnchorComponents(Space, supportedTypes);
|
||||
|
||||
if (supportedTypes.Contains(EOculusXRSpaceComponentType::Locatable))
|
||||
{
|
||||
FOculusXRAnchorManager::SetSpaceComponentStatus(Space, EOculusXRSpaceComponentType::Locatable, true, 0.0f, tempOut);
|
||||
}
|
||||
|
||||
if (supportedTypes.Contains(EOculusXRSpaceComponentType::Sharable))
|
||||
{
|
||||
FOculusXRAnchorManager::SetSpaceComponentStatus(Space, EOculusXRSpaceComponentType::Sharable, true, 0.0f, tempOut);
|
||||
}
|
||||
|
||||
if (supportedTypes.Contains(EOculusXRSpaceComponentType::Storable))
|
||||
{
|
||||
FOculusXRAnchorManager::SetSpaceComponentStatus(Space, EOculusXRSpaceComponentType::Storable, true, 0.0f, tempOut);
|
||||
}
|
||||
|
||||
ResultPtr->Results.Add(FOculusXRSpaceQueryResult(Space, UUID, ResultPtr->Location));
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::HandleAnchorQueryComplete(FOculusXRUInt64 RequestId, int Result)
|
||||
{
|
||||
OculusXRTelemetry::Events::FAnchorsQueryResponse(static_cast<int>(GetTypeHash(RequestId)))
|
||||
.SetResult(OVRP_SUCCESS(Result) ? OculusXRTelemetry::EAction::Success : OculusXRTelemetry::EAction::Fail);
|
||||
AnchorQueryBinding* ResultPtr = AnchorQueryBindings.Find(RequestId.GetValue());
|
||||
if (ResultPtr)
|
||||
{
|
||||
ResultPtr->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), ResultPtr->Results);
|
||||
AnchorQueryBindings.Remove(RequestId.GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
void FOculusXRAnchors::HandleAnchorSharingComplete(FOculusXRUInt64 RequestId, int Result)
|
||||
{
|
||||
ShareAnchorsBinding* ShareAnchorsData = ShareAnchorsBindings.Find(RequestId);
|
||||
if (ShareAnchorsData == nullptr)
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Error, TEXT("Couldn't find binding for share anchors! Request: %llu"), RequestId.GetValue());
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<UOculusXRAnchorComponent*> SharedAnchors;
|
||||
for (auto& WeakAnchor : ShareAnchorsData->SharedAnchors)
|
||||
{
|
||||
SharedAnchors.Add(WeakAnchor.Get());
|
||||
}
|
||||
|
||||
ShareAnchorsData->Binding.ExecuteIfBound(static_cast<EOculusXRAnchorResult::Type>(Result), SharedAnchors, ShareAnchorsData->OculusUserIds);
|
||||
ShareAnchorsBindings.Remove(RequestId.GetValue());
|
||||
}
|
||||
|
||||
|
||||
} // namespace OculusXRAnchors
|
||||
@@ -0,0 +1,55 @@
|
||||
// @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 "OculusXRAnchorManager.h"
|
||||
#include "OculusXRRoomLayoutManager.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogOculusXRAnchors);
|
||||
|
||||
#define LOCTEXT_NAMESPACE "OculusXRAnchors"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// FOculusXRAnchorsModule
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FOculusXRAnchorsModule::StartupModule()
|
||||
{
|
||||
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::FOculusXRAnchorManager::OnPollEvent));
|
||||
HMD->AddEventPollingDelegate(OculusXRHMD::FOculusXRHMDEventPollingDelegate::CreateStatic(&OculusXRAnchors::FOculusXRRoomLayoutManager::OnPollEvent));
|
||||
|
||||
Anchors.Initialize();
|
||||
}
|
||||
|
||||
void FOculusXRAnchorsModule::ShutdownModule()
|
||||
{
|
||||
Anchors.Teardown();
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,41 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
#include "IOculusXRAnchorsModule.h"
|
||||
#include "OculusXRAnchors.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "OculusAnchors"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// FOculusXRAnchorsModule
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
#if OCULUS_ANCHORS_SUPPORTED_PLATFORMS
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogOculusXRAnchors, Log, All);
|
||||
|
||||
class FOculusXRAnchorsModule : public IOculusXRAnchorsModule
|
||||
{
|
||||
public:
|
||||
virtual ~FOculusXRAnchorsModule() = default;
|
||||
|
||||
// IModuleInterface interface
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
static OculusXRAnchors::FOculusXRAnchors* GetOculusAnchors();
|
||||
|
||||
private:
|
||||
OculusXRAnchors::FOculusXRAnchors Anchors;
|
||||
};
|
||||
|
||||
#else // OCULUS_ANCHORS_SUPPORTED_PLATFORMS
|
||||
|
||||
class FOculusXRAnchorsModule : public FDefaultModuleImpl
|
||||
{
|
||||
};
|
||||
|
||||
#endif // OCULUS_ANCHORS_SUPPORTED_PLATFORMS
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "OculusXRAnchorsModule.h"
|
||||
@@ -0,0 +1,148 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRRoomLayoutManager.h"
|
||||
#include "OculusXRHMD.h"
|
||||
#include "OculusXRAnchorDelegates.h"
|
||||
#include "OculusXRAnchorsModule.h"
|
||||
|
||||
namespace OculusXRAnchors
|
||||
{
|
||||
void FOculusXRRoomLayoutManager::OnPollEvent(ovrpEventDataBuffer* EventDataBuffer, bool& EventPollResult)
|
||||
{
|
||||
ovrpEventDataBuffer& buf = *EventDataBuffer;
|
||||
|
||||
switch (buf.EventType)
|
||||
{
|
||||
case ovrpEventType_None:
|
||||
break;
|
||||
case ovrpEventType_SceneCaptureComplete:
|
||||
{
|
||||
ovrpEventSceneCaptureComplete sceneCaptureComplete;
|
||||
unsigned char* bufData = buf.EventData;
|
||||
|
||||
memcpy(&sceneCaptureComplete.requestId, bufData, sizeof(sceneCaptureComplete.requestId));
|
||||
bufData += sizeof(ovrpUInt64); //move forward
|
||||
memcpy(&sceneCaptureComplete.result, bufData, sizeof(sceneCaptureComplete.result));
|
||||
|
||||
FOculusXRAnchorEventDelegates::OculusSceneCaptureComplete.Broadcast(FOculusXRUInt64(sceneCaptureComplete.requestId), sceneCaptureComplete.result >= 0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
EventPollResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EventPollResult = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Requests the launch of Capture Flow
|
||||
* @param OutRequestID The requestId returned by the system
|
||||
* @return returns true if sucessfull
|
||||
*/
|
||||
bool FOculusXRRoomLayoutManager::RequestSceneCapture(uint64& OutRequestID)
|
||||
{
|
||||
OutRequestID = 0;
|
||||
|
||||
ovrpSceneCaptureRequest sceneCaptureRequest;
|
||||
sceneCaptureRequest.request = nullptr;
|
||||
sceneCaptureRequest.requestByteCount = 0;
|
||||
|
||||
const ovrpResult Result = FOculusXRHMDModule::GetPluginWrapper().RequestSceneCapture(&sceneCaptureRequest, &OutRequestID);
|
||||
if (OVRP_FAILURE(Result))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the room layout for a specific space
|
||||
* @param Space The space to get the room layout for
|
||||
* @param MaxWallsCapacity Maximum number of walls to query
|
||||
* @param OutCeilingUuid The ceiling entity's uuid
|
||||
* @param OutFloorUuid The floor entity's uuid
|
||||
* @param OutWallsUuid Array of uuids belonging to the walls in the room layout
|
||||
* @return returns true if successful
|
||||
*/
|
||||
bool FOculusXRRoomLayoutManager::GetSpaceRoomLayout(const uint64 Space, const uint32 MaxWallsCapacity,
|
||||
FOculusXRUUID& OutCeilingUuid, FOculusXRUUID& OutFloorUuid, TArray<FOculusXRUUID>& OutWallsUuid)
|
||||
{
|
||||
ovrpRoomLayout roomLayout;
|
||||
roomLayout.wallUuidCapacityInput = 0;
|
||||
roomLayout.wallUuidCountOutput = 0;
|
||||
|
||||
// First call to get output size
|
||||
const ovrpResult firstCallResult = FOculusXRHMDModule::GetPluginWrapper().GetSpaceRoomLayout(&Space, &roomLayout);
|
||||
if (OVRP_FAILURE(firstCallResult))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the input size and pointer to the uuid array
|
||||
TArray<ovrpUuid> uuids;
|
||||
uuids.InsertZeroed(0, roomLayout.wallUuidCountOutput);
|
||||
|
||||
roomLayout.wallUuidCapacityInput = roomLayout.wallUuidCountOutput;
|
||||
roomLayout.wallUuids = uuids.GetData();
|
||||
|
||||
const ovrpResult secondCallResult = FOculusXRHMDModule::GetPluginWrapper().GetSpaceRoomLayout(&Space, &roomLayout);
|
||||
if (OVRP_FAILURE(secondCallResult))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
OutCeilingUuid = FOculusXRUUID(roomLayout.ceilingUuid.data);
|
||||
OutFloorUuid = FOculusXRUUID(roomLayout.floorUuid.data);
|
||||
|
||||
OutWallsUuid.Empty();
|
||||
OutWallsUuid.InsertZeroed(0, uuids.Num());
|
||||
|
||||
for (int32 i = 0; i < uuids.Num(); ++i)
|
||||
{
|
||||
OutWallsUuid[i] = FOculusXRUUID(roomLayout.wallUuids[i].data);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FOculusXRRoomLayoutManager::GetSpaceTriangleMesh(uint64 Space, TArray<FVector>& Vertices, TArray<int32>& Triangles)
|
||||
{
|
||||
ovrpTriangleMesh OVRPMesh = { 0, 0, nullptr, 0, 0, nullptr };
|
||||
|
||||
ovrpResult CountResult = FOculusXRHMDModule::GetPluginWrapper().GetSpaceTriangleMesh(&Space, &OVRPMesh);
|
||||
if (OVRP_FAILURE(CountResult))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to load TriangleMesh info - Space: %llu - Result: %d"), Space, CountResult);
|
||||
return false;
|
||||
}
|
||||
OVRPMesh.indexCapacityInput = OVRPMesh.indexCountOutput;
|
||||
OVRPMesh.vertexCapacityInput = OVRPMesh.vertexCountOutput;
|
||||
|
||||
TArray<ovrpVector3f> OVRPVertices;
|
||||
OVRPVertices.SetNum(OVRPMesh.vertexCapacityInput);
|
||||
OVRPMesh.vertices = OVRPVertices.GetData();
|
||||
Triangles.SetNum(OVRPMesh.indexCapacityInput);
|
||||
check(sizeof(TRemoveReference<decltype(Triangles)>::Type::ElementType) == sizeof(TRemovePointer<decltype(OVRPMesh.indices)>::Type));
|
||||
OVRPMesh.indices = Triangles.GetData();
|
||||
|
||||
const ovrpResult MeshResult = FOculusXRHMDModule::GetPluginWrapper().GetSpaceTriangleMesh(&Space, &OVRPMesh);
|
||||
if (OVRP_FAILURE(MeshResult))
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Failed to load TriangleMesh data - Space: %llu - Result: %d"), Space, MeshResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Loaded TriangleMesh data - Space: %llu - Vertices: %d - Faces: %d"),
|
||||
Space, OVRPMesh.vertexCapacityInput, OVRPMesh.indexCapacityInput);
|
||||
|
||||
Vertices.Empty(OVRPVertices.Num());
|
||||
Algo::Transform(OVRPVertices, Vertices, [](const auto& Vertex) { return OculusXRHMD::ToFVector(Vertex); });
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
} // namespace OculusXRAnchors
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "OculusXRAnchorComponent.h"
|
||||
#include "OculusXRHMDPrivate.h"
|
||||
|
||||
namespace OculusXRAnchors
|
||||
{
|
||||
struct FOculusXRRoomLayoutManager
|
||||
{
|
||||
static bool RequestSceneCapture(uint64& OutRequestID);
|
||||
static bool GetSpaceRoomLayout(const uint64 Space, const uint32 MaxWallsCapacity,
|
||||
FOculusXRUUID& OutCeilingUuid, FOculusXRUUID& OutFloorUuid, TArray<FOculusXRUUID>& OutWallsUuid);
|
||||
|
||||
static bool GetSpaceTriangleMesh(uint64 Space, TArray<FVector>& Vertices, TArray<int32>& Triangles);
|
||||
|
||||
static void OnPollEvent(ovrpEventDataBuffer* EventDataBuffer, bool& EventPollResult);
|
||||
};
|
||||
} // namespace OculusXRAnchors
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#include "OculusXRRoomLayoutManagerComponent.h"
|
||||
#include "OculusXRHMD.h"
|
||||
#include "OculusXRRoomLayoutManager.h"
|
||||
#include "OculusXRAnchorDelegates.h"
|
||||
#include "OculusXRAnchorManager.h"
|
||||
#include "OculusXRAnchorBPFunctionLibrary.h"
|
||||
#include "ProceduralMeshComponent.h"
|
||||
#include "OculusXRAnchorsModule.h"
|
||||
|
||||
UOculusXRRoomLayoutManagerComponent::UOculusXRRoomLayoutManagerComponent(const FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
bWantsInitializeComponent = true; // so that InitializeComponent() gets called
|
||||
}
|
||||
|
||||
void UOculusXRRoomLayoutManagerComponent::OnRegister()
|
||||
{
|
||||
Super::OnRegister();
|
||||
|
||||
FOculusXRAnchorEventDelegates::OculusSceneCaptureComplete.AddUObject(this, &UOculusXRRoomLayoutManagerComponent::OculusRoomLayoutSceneCaptureComplete_Handler);
|
||||
}
|
||||
|
||||
void UOculusXRRoomLayoutManagerComponent::OnUnregister()
|
||||
{
|
||||
Super::OnUnregister();
|
||||
|
||||
FOculusXRAnchorEventDelegates::OculusSceneCaptureComplete.RemoveAll(this);
|
||||
}
|
||||
|
||||
void UOculusXRRoomLayoutManagerComponent::InitializeComponent()
|
||||
{
|
||||
Super::InitializeComponent();
|
||||
}
|
||||
|
||||
void UOculusXRRoomLayoutManagerComponent::UninitializeComponent()
|
||||
{
|
||||
Super::UninitializeComponent();
|
||||
}
|
||||
|
||||
bool UOculusXRRoomLayoutManagerComponent::LaunchCaptureFlow()
|
||||
{
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Launch capture flow -- UOculusXRRoomLayoutManagerComponent"));
|
||||
|
||||
uint64 OutRequest = 0;
|
||||
const bool bSuccess = OculusXRAnchors::FOculusXRRoomLayoutManager::RequestSceneCapture(OutRequest);
|
||||
if (bSuccess)
|
||||
{
|
||||
EntityRequestList.Add(OutRequest);
|
||||
}
|
||||
|
||||
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Launch capture flow -- RequestSceneCapture -- %d"), bSuccess);
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
bool UOculusXRRoomLayoutManagerComponent::GetRoomLayout(FOculusXRUInt64 Space, FOculusXRRoomLayout& RoomLayoutOut, int32 MaxWallsCapacity)
|
||||
{
|
||||
return UOculusXRAnchorBPFunctionLibrary::GetRoomLayout(Space, RoomLayoutOut, MaxWallsCapacity);
|
||||
}
|
||||
|
||||
bool UOculusXRRoomLayoutManagerComponent::LoadTriangleMesh(FOculusXRUInt64 Space, UProceduralMeshComponent* Mesh, bool CreateCollision) const
|
||||
{
|
||||
ensure(Mesh);
|
||||
TArray<FVector> Vertices;
|
||||
TArray<int32> Triangles;
|
||||
|
||||
bool Success = OculusXRAnchors::FOculusXRRoomLayoutManager::GetSpaceTriangleMesh(Space, Vertices, Triangles);
|
||||
if (!Success)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mesh->bUseAsyncCooking = true;
|
||||
TArray<FVector> EmptyNormals;
|
||||
TArray<FVector2D> EmptyUV;
|
||||
TArray<FColor> EmptyVertexColors;
|
||||
TArray<FProcMeshTangent> EmptyTangents;
|
||||
Mesh->CreateMeshSection(0, Vertices, Triangles, EmptyNormals, EmptyUV, EmptyVertexColors, EmptyTangents, CreateCollision);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,37 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
#define OCULUS_ANCHORS_SUPPORTED_PLATFORMS (PLATFORM_WINDOWS && WINVER > 0x0502) || (PLATFORM_ANDROID_ARM || PLATFORM_ANDROID_ARM64)
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
// 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);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
|
||||
static bool TryGetAnchorTransformByHandle(const FOculusXRUInt64& Handle, FTransform& OutTransform, FOculusXRAnchorLocationFlags& OutLocationFlags);
|
||||
|
||||
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);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
|
||||
static bool GetRoomLayout(FOculusXRUInt64 Space, FOculusXRRoomLayout& RoomLayoutOut, int32 MaxWallsCapacity = 64);
|
||||
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
@@ -0,0 +1,149 @@
|
||||
// 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 UOculusXRPlaneAnchorComponent : public UOculusXRBaseAnchorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRPlaneAnchorComponent()
|
||||
{
|
||||
Type = EOculusXRSpaceComponentType::ScenePlane;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
|
||||
bool GetPositionAndSize(FVector& outPosition, FVector& outSize) const;
|
||||
};
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class OCULUSXRANCHORS_API UOculusXRVolumeAnchorComponent : public UOculusXRBaseAnchorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRVolumeAnchorComponent()
|
||||
{
|
||||
Type = EOculusXRSpaceComponentType::SceneVolume;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
|
||||
bool GetPositionAndSize(FVector& outPosition, FVector& outSize) const;
|
||||
};
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class OCULUSXRANCHORS_API UOculusXRSemanticClassificationAnchorComponent : public UOculusXRBaseAnchorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRSemanticClassificationAnchorComponent()
|
||||
{
|
||||
Type = EOculusXRSpaceComponentType::SemanticClassification;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
|
||||
bool GetSemanticClassifications(TArray<FString>& outClassifications) const;
|
||||
};
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class OCULUSXRANCHORS_API UOculusXRRoomLayoutAnchorComponent : public UOculusXRBaseAnchorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRRoomLayoutAnchorComponent()
|
||||
{
|
||||
Type = EOculusXRSpaceComponentType::RoomLayout;
|
||||
}
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor")
|
||||
bool GetRoomLayout(FOculusXRUUID& outFloorUUID, FOculusXRUUID& outCeilingUUID, TArray<FOculusXRUUID>& outWallsUUIDs) 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;
|
||||
}
|
||||
};
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class OCULUSXRANCHORS_API UOculusXRTriangleMeshAnchorComponent : public UOculusXRBaseAnchorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UOculusXRTriangleMeshAnchorComponent()
|
||||
{
|
||||
Type = EOculusXRSpaceComponentType::TriangleMesh;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,122 @@
|
||||
// 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*/, int /*result*/, FOculusXRUInt64 /*space*/, FOculusXRUUID /*uuid*/);
|
||||
static OCULUSXRANCHORS_API FOculusXRSpatialAnchorCreateCompleteDelegate OculusSpatialAnchorCreateComplete;
|
||||
|
||||
/* ovrpEventType_SpaceSetComponentStatusComplete
|
||||
*
|
||||
* SpaceSetComponentStatusComplete
|
||||
* Prefix:
|
||||
* FOculusXRSpaceSetComponentStatusComplete
|
||||
* Suffix:
|
||||
* FOculusXRSpaceSetComponentStatusCompleteDelegate
|
||||
*/
|
||||
DECLARE_MULTICAST_DELEGATE_SixParams(FOculusXRSpaceSetComponentStatusCompleteDelegate, FOculusXRUInt64 /*requestId*/, int /*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*/, int /*result*/);
|
||||
static OCULUSXRANCHORS_API FOculusXRSpaceQueryCompleteDelegate OculusSpaceQueryComplete;
|
||||
|
||||
/* ovrpEventType_SpaceSaveComplete
|
||||
*
|
||||
* SpaceSaveComplete
|
||||
* Prefix:
|
||||
* FOculusXRSpaceSaveComplete
|
||||
* Suffix:
|
||||
* FOculusXRSpaceSaveCompleteDelegate
|
||||
*/
|
||||
DECLARE_MULTICAST_DELEGATE_FiveParams(FOculusXRSpaceSaveCompleteDelegate, FOculusXRUInt64 /*requestId*/, FOculusXRUInt64 /* space*/, bool /* sucess*/, int /*result*/, FOculusXRUUID /*uuid*/);
|
||||
static OCULUSXRANCHORS_API FOculusXRSpaceSaveCompleteDelegate OculusSpaceSaveComplete;
|
||||
|
||||
/* ovrpEventType_SpaceListSaveResult
|
||||
*
|
||||
* SpaceListSaveComplete
|
||||
* Prefix:
|
||||
* FOculusSpaceListSaveComplete
|
||||
* Suffix:
|
||||
* FOculusSpaceListSaveCompleteDelegate
|
||||
*/
|
||||
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRSpaceListSaveCompleteDelegate, FOculusXRUInt64 /*requestId*/, int /*result*/);
|
||||
static OCULUSXRANCHORS_API FOculusXRSpaceListSaveCompleteDelegate OculusSpaceListSaveComplete;
|
||||
|
||||
/* ovrpEventType_SpaceEraseComplete
|
||||
*
|
||||
* SpaceEraseComplete
|
||||
* Prefix:
|
||||
* FOculusXRSpaceEraseComplete
|
||||
* Suffix:
|
||||
* FOculusXRSpaceEraseCompleteDelegate
|
||||
*/
|
||||
DECLARE_MULTICAST_DELEGATE_FourParams(FOculusXRSpaceEraseCompleteDelegate, FOculusXRUInt64 /*requestId*/, int /* result*/, FOculusXRUUID /*uuid*/, EOculusXRSpaceStorageLocation /*location*/);
|
||||
static OCULUSXRANCHORS_API FOculusXRSpaceEraseCompleteDelegate OculusSpaceEraseComplete;
|
||||
|
||||
/* ovrpEventType_SpaceShareSpaceResult
|
||||
*
|
||||
* SpaceShareComplete
|
||||
* Prefix:
|
||||
* FOculusSpaceShareSpacesComplete
|
||||
* Suffix:
|
||||
* FOculusSpaceShareSpacesCompleteDelegate
|
||||
*/
|
||||
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRSpaceShareCompleteDelegate, FOculusXRUInt64 /*requestId*/, int /*result*/);
|
||||
static OCULUSXRANCHORS_API FOculusXRSpaceShareCompleteDelegate OculusSpaceShareComplete;
|
||||
|
||||
/* ovrpEventType_SceneCaptureComplete
|
||||
*
|
||||
* SceneCaptureComplete
|
||||
* Prefix:
|
||||
* FOculusXRSceneCaptureComplete
|
||||
* Suffix:
|
||||
* FOculusXRSceneCaptureCompleteDelegate
|
||||
*/
|
||||
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRSceneCaptureCompleteDelegate, FOculusXRUInt64 /*requestId*/, bool /*success*/);
|
||||
static OCULUSXRANCHORS_API FOculusXRSceneCaptureCompleteDelegate OculusSceneCaptureComplete;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,298 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Kismet/BlueprintAsyncActionBase.h"
|
||||
#include "Templates/SharedPointer.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);
|
||||
|
||||
|
||||
//
|
||||
// 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);
|
||||
};
|
||||
|
||||
|
||||
UCLASS()
|
||||
class OCULUSXRANCHORS_API UOculusXRAnchorLaunchCaptureFlow : public UBlueprintAsyncActionBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOculusXRAnchorCaptureFlowFinished);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|SpatialAnchor", meta = (WorldContext = "WorldContext", BlueprintInternalUseOnly = "true"))
|
||||
static UOculusXRAnchorLaunchCaptureFlow* LaunchCaptureFlowAsync(const UObject* WorldContext);
|
||||
|
||||
void Activate() override;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOculusXRAnchorCaptureFlowFinished Success;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOculusXRAnchorCaptureFlowFinished Failure;
|
||||
|
||||
private:
|
||||
uint64 Request = 0;
|
||||
|
||||
UFUNCTION(CallInEditor)
|
||||
void OnCaptureFinish(FOculusXRUInt64 RequestId, bool bSuccess);
|
||||
};
|
||||
@@ -0,0 +1,293 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "OculusXRAnchorTypes.generated.h"
|
||||
|
||||
#define OCULUSXR_UUID_SIZE 16
|
||||
|
||||
typedef uint8 ovrpXRUuidArray[OCULUSXR_UUID_SIZE];
|
||||
|
||||
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,
|
||||
|
||||
|
||||
|
||||
};
|
||||
} // 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 ovrpXRUuidArray& UuidArray);
|
||||
|
||||
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);
|
||||
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; };
|
||||
};
|
||||
|
||||
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"),
|
||||
};
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
// 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;
|
||||
};
|
||||
146
Plugins/MetaXR/Source/OculusXRAnchors/Public/OculusXRAnchors.h
Normal file
146
Plugins/MetaXR/Source/OculusXRAnchors/Public/OculusXRAnchors.h
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "OculusXRAnchorComponent.h"
|
||||
#include "OculusXRAnchorTypes.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*/);
|
||||
|
||||
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 GetSpaceContainerUUIDs(uint64 Space, TArray<FOculusXRUUID>& OutUUIDs, EOculusXRAnchorResult::Type& OutResult);
|
||||
static bool GetSpaceScenePlane(uint64 Space, FVector& OutPos, FVector& OutSize, EOculusXRAnchorResult::Type& OutResult);
|
||||
static bool GetSpaceSceneVolume(uint64 Space, FVector& OutPos, FVector& OutSize, EOculusXRAnchorResult::Type& OutResult);
|
||||
static bool GetSpaceSemanticClassification(uint64 Space, TArray<FString>& OutSemanticClassifications, EOculusXRAnchorResult::Type& OutResult);
|
||||
static bool GetSpaceBoundary2D(uint64 Space, TArray<FVector2f>& OutVertices, EOculusXRAnchorResult::Type& OutResult);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
void HandleSpatialAnchorCreateComplete(FOculusXRUInt64 RequestId, int Result, FOculusXRUInt64 Space, FOculusXRUUID UUID);
|
||||
void HandleAnchorEraseComplete(FOculusXRUInt64 RequestId, int Result, FOculusXRUUID UUID, EOculusXRSpaceStorageLocation Location);
|
||||
|
||||
void HandleSetComponentStatusComplete(FOculusXRUInt64 RequestId, int Result, FOculusXRUInt64 Space, FOculusXRUUID UUID, EOculusXRSpaceComponentType ComponentType, bool Enabled);
|
||||
|
||||
void HandleAnchorSaveComplete(FOculusXRUInt64 RequestId, FOculusXRUInt64 Space, bool Success, int Result, FOculusXRUUID UUID);
|
||||
void HandleAnchorSaveListComplete(FOculusXRUInt64 RequestId, int Result);
|
||||
|
||||
void HandleAnchorQueryResultsBegin(FOculusXRUInt64 RequestId);
|
||||
void HandleAnchorQueryResultElement(FOculusXRUInt64 RequestId, FOculusXRUInt64 Space, FOculusXRUUID UUID);
|
||||
void HandleAnchorQueryComplete(FOculusXRUInt64 RequestId, int Result);
|
||||
|
||||
void HandleAnchorSharingComplete(FOculusXRUInt64 RequestId, int 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;
|
||||
};
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
// Delegate handles
|
||||
FDelegateHandle DelegateHandleAnchorCreate;
|
||||
FDelegateHandle DelegateHandleAnchorErase;
|
||||
FDelegateHandle DelegateHandleSetComponentStatus;
|
||||
FDelegateHandle DelegateHandleAnchorSave;
|
||||
FDelegateHandle DelegateHandleAnchorSaveList;
|
||||
FDelegateHandle DelegateHandleQueryResultsBegin;
|
||||
FDelegateHandle DelegateHandleQueryResultElement;
|
||||
FDelegateHandle DelegateHandleQueryComplete;
|
||||
FDelegateHandle DelegateHandleAnchorShare;
|
||||
};
|
||||
|
||||
} // namespace OculusXRAnchors
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "OculusXRSpatialAnchorComponent.h"
|
||||
#include "OculusXRAnchorBPFunctionLibrary.h"
|
||||
#include "OculusXRRoomLayoutManagerComponent.generated.h"
|
||||
|
||||
UCLASS(meta = (DisplayName = "OculusXR Room Layout Manager Component", BlueprintSpawnableComponent))
|
||||
class OCULUSXRANCHORS_API UOculusXRRoomLayoutManagerComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UOculusXRRoomLayoutManagerComponent(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
virtual void InitializeComponent() override;
|
||||
virtual void UninitializeComponent() override;
|
||||
|
||||
virtual void OnRegister() override;
|
||||
virtual void OnUnregister() override;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOculusXRRoomLayoutSceneCaptureCompleteDelegate,
|
||||
FOculusXRUInt64, requestId,
|
||||
bool, result);
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE_TwoParams(FOculusXRRoomLayoutSceneCompleteNativeDelegate, FOculusXRUInt64 /*requestId*/, bool /*success*/);
|
||||
FOculusXRRoomLayoutSceneCompleteNativeDelegate OculusXRRoomLayoutSceneCaptureCompleteNative;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "OculusXR|Room Layout Manager")
|
||||
FOculusXRRoomLayoutSceneCaptureCompleteDelegate OculusXRRoomLayoutSceneCaptureComplete;
|
||||
|
||||
// Requests to launch Capture Flow
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|Room Layout Manager")
|
||||
bool LaunchCaptureFlow();
|
||||
|
||||
// Gets room layout for a specific space
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|Room Layout Manager")
|
||||
bool GetRoomLayout(FOculusXRUInt64 Space, UPARAM(ref) FOculusXRRoomLayout& RoomLayoutOut, int32 MaxWallsCapacity = 64);
|
||||
|
||||
// Loads mesh data (vertices, indeces) associated with the space into UProceduralMeshComponent
|
||||
UFUNCTION(BlueprintCallable, Category = "OculusXR|Room Layout Manager")
|
||||
bool LoadTriangleMesh(FOculusXRUInt64 Space, class UProceduralMeshComponent* Mesh, bool CreateCollision) const;
|
||||
|
||||
protected:
|
||||
UPROPERTY(Transient)
|
||||
TSet<uint64> EntityRequestList;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TMap<FOculusXRUInt64, FOculusXRRoomLayout> RoomLayouts;
|
||||
|
||||
private:
|
||||
UFUNCTION()
|
||||
void OculusRoomLayoutSceneCaptureComplete_Handler(FOculusXRUInt64 RequestId, bool bSuccess)
|
||||
{
|
||||
if (EntityRequestList.Find(RequestId.Value) != nullptr)
|
||||
{
|
||||
OculusXRRoomLayoutSceneCaptureComplete.Broadcast(RequestId, bSuccess);
|
||||
OculusXRRoomLayoutSceneCaptureCompleteNative.Broadcast(RequestId, bSuccess);
|
||||
EntityRequestList.Remove(RequestId.Value);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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:
|
||||
};
|
||||
Reference in New Issue
Block a user