implement the OpenXR-compatible hand tracking (XR_EXT_hand_tracking) support

This commit is contained in:
Mamadou Babaei
2024-05-03 11:29:17 +02:00
parent 9b32ee589b
commit c5adee47ce
51 changed files with 4151 additions and 307 deletions
+6 -2
View File
@@ -7,12 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
This is a minor release focusing mainly on bringing OpenXR-compatible hand tracking support (XR_EXT_hand_tracking) and Head-mounted Display automatic detection for adjusting wrist tracker offsets automatically at runtime.
### Added ### Added
- Added SenseGloveTracking and SenseGloveTrackingKismet modules which provide OpenXR-compatible hand tracking by implementing XR_EXT_hand_tracking support, HMD auto-detection, and SenseGlove device tracking.
- A fallback to HMD and wrist tracker hardware auto-detection mechanism has been added to be triggered in situations when automatic detection of the wrist tracker hardware is desired, e.g., either by not setting it explicitly, or setting it to the default None value. Please note that this is still highly experimental and HTC VIVE Focus 3 and HTC XR Elite cannot be distinguished in the current iteration. Though, since the tracker devices and offsets for both headsets are the same in the end it does not make a difference if both headsets are detected as each other. - A fallback to HMD and wrist tracker hardware auto-detection mechanism has been added to be triggered in situations when automatic detection of the wrist tracker hardware is desired, e.g., either by not setting it explicitly, or setting it to the default None value. Please note that this is still highly experimental and HTC VIVE Focus 3 and HTC XR Elite cannot be distinguished in the current iteration. Though, since the tracker devices and offsets for both headsets are the same in the end it does not make a difference if both headsets are detected as each other.
- Added the SGHeadMountedDisplay utility class, exposed to both C++ and Blueprint, in order to easily gather information about the HMD at runtime. - Added the SGHMDTracker utility class, exposed to both C++ and Blueprint, in order to easily gather information about the HMD device at runtime.
- Added the SGTypes header to the SenseGloveTypes module in order to define and share SenseGlove module types through this header across the plugin modules. - Added the SGTrackingTypes header to the SenseGloveTypes module in order to define and share SenseGloveTracking module types through this header across the plugin modules.
- Added ESGHeadMountedDisplayDevice enum with supported HMDs list. - Added ESGHeadMountedDisplayDevice enum with supported HMDs list.
- Added the SGGloveTracer utility class, exposed to both C++ and Blueprint, in order to easily check left or right glove connectivity or retrieve the connected glove instances.
### Changed ### Changed
+5 -1
View File
@@ -84,7 +84,7 @@ Please note that modules postfixed with **Impl** are intended for interal use an
### Upcoming features planned for the v2.1.0 release ### Upcoming features planned for the v2.1.0 release
- [ ] Hand tracking compatible with OpenXR (or other generic hand tracking format). - [X] OpenXR-compatible hand tracking (XR_EXT_hand_tracking) support.
- [X] A fallback to HMD and wrist tracker hardware auto-detection mechanism when automatic detection of the wrist tracker hardware is desired. - [X] A fallback to HMD and wrist tracker hardware auto-detection mechanism when automatic detection of the wrist tracker hardware is desired.
### Planned features long-term ### Planned features long-term
@@ -146,6 +146,10 @@ Please note that modules postfixed with **Impl** are intended for interal use an
├── SenseGloveSettingsKismet (exposes Blueprints-specific functionality from the SenseGloveSettings module) ├── SenseGloveSettingsKismet (exposes Blueprints-specific functionality from the SenseGloveSettings module)
├── SenseGloveTracking (provides XR_EXT_hand_tracking support, HMD auto-detection, and SenseGlove device tracking)
├── SenseGloveTrackingKismet (exposes Blueprints-specific functionality from the SenseGloveTracking module)
├── SenseGloveTypes (exposes various enums from the backend libraries and also types from the SenseGlove module) ├── SenseGloveTypes (exposes various enums from the backend libraries and also types from the SenseGlove module)
├── SenseGloveUtils (the internal utility module) ├── SenseGloveUtils (the internal utility module)
+22
View File
@@ -217,6 +217,28 @@
"Win64" "Win64"
] ]
}, },
{
"Name": "SenseGloveTracking",
"Type": "Runtime",
"LoadingPhase": "PostConfigInit",
"WhitelistPlatforms": [
"Android",
"Linux",
"LinuxArm64",
"Win64"
]
},
{
"Name": "SenseGloveTrackingKismet",
"Type": "Runtime",
"LoadingPhase": "PostConfigInit",
"WhitelistPlatforms": [
"Android",
"Linux",
"LinuxArm64",
"Win64"
]
},
{ {
"Name": "SenseGloveTypes", "Name": "SenseGloveTypes",
"Type": "Runtime", "Type": "Runtime",
@@ -43,11 +43,11 @@
#include "SenseGlove/Animation/SGVirtualHandAnimInstance.h" #include "SenseGlove/Animation/SGVirtualHandAnimInstance.h"
#include "SenseGlove/Components/SGWristTrackerComponent.h" #include "SenseGlove/Components/SGWristTrackerComponent.h"
#include "SGBackend/SGBackend.h"
#include "SGCore/SGHandPose.h" #include "SGCore/SGHandPose.h"
#include "SGCore/SGHapticGlove.h" #include "SGCore/SGHapticGlove.h"
#include "SGDebug/SGDebugVirtualHand.h" #include "SGDebug/SGDebugVirtualHand.h"
#include "SGLog/SGLog.h" #include "SGLog/SGLog.h"
#include "SGTracking/SGGloveTracker.h"
struct USGVirtualHandComponent::FImpl struct USGVirtualHandComponent::FImpl
{ {
@@ -119,7 +119,7 @@ struct USGVirtualHandComponent::FImpl
USkeleton* GetSkeleton() const; USkeleton* GetSkeleton() const;
const FReferenceSkeleton& GetRefSkeleton() const; const FReferenceSkeleton& GetRefSkeleton() const;
bool CheckGlove() const; void UpdateGloveVisibility() const;
FORCEINLINE void SetVisibility(const bool bInVisible) const FORCEINLINE void SetVisibility(const bool bInVisible) const
{ {
@@ -227,21 +227,10 @@ USGVirtualHandComponent::USGVirtualHandComponent(const FObjectInitializer& Objec
RingFingertipTouchSocketName = FName{TEXT("TouchRingFingertip")}; RingFingertipTouchSocketName = FName{TEXT("TouchRingFingertip")};
PinkyFingertipTouchSocketName = FName{TEXT("TouchPinkyFingertip")}; PinkyFingertipTouchSocketName = FName{TEXT("TouchPinkyFingertip")};
DebugVirtualHandSettings = FSGDebugVirtualHandSettings{ DebugVirtualHandSettings = FSGDebugVirtualHandSettings{};
false,
ESGDebugVirtualHandDrawingMode::None,
FVector(0.5f, 0.5f, 0.5f),
FColor(255, 0, 0, 255),
0.1f, 1.0f, 1.0f,
FColor(255, 0, 0, 255),
FColor(0, 255, 0, 255),
FColor(0, 0, 255, 255),
false, 1.1f, 0
};
Super::SetSkeletalMesh(nullptr, true); Super::SetSkeletalMesh(nullptr, true);
Glove = nullptr;
WristTracker = nullptr; WristTracker = nullptr;
} }
@@ -302,13 +291,15 @@ void USGVirtualHandComponent::InitializeComponent()
Pimpl->SetDefaultMesh(); Pimpl->SetDefaultMesh();
} }
(void) Pimpl->CheckGlove(); Pimpl->UpdateGloveVisibility();
} }
void USGVirtualHandComponent::UninitializeComponent() void USGVirtualHandComponent::UninitializeComponent()
{ {
Super::UninitializeComponent(); Super::UninitializeComponent();
const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(IsRight()) : nullptr};
if (IsValid(Glove) && AutoStopsAllHapticsOnEndPlay()) if (IsValid(Glove) && AutoStopsAllHapticsOnEndPlay())
{ {
Glove->StopHaptics(); Glove->StopHaptics();
@@ -319,13 +310,15 @@ void USGVirtualHandComponent::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
(void) Pimpl->CheckGlove(); Pimpl->UpdateGloveVisibility();
} }
void USGVirtualHandComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) void USGVirtualHandComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{ {
Super::EndPlay(EndPlayReason); Super::EndPlay(EndPlayReason);
const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(IsRight()) : nullptr};
if (IsValid(Glove) && AutoStopsAllHapticsOnEndPlay()) if (IsValid(Glove) && AutoStopsAllHapticsOnEndPlay())
{ {
Glove->StopHaptics(); Glove->StopHaptics();
@@ -345,8 +338,10 @@ void USGVirtualHandComponent::TickComponent(
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
(void) Pimpl->CheckGlove(); Pimpl->UpdateGloveVisibility();
const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(IsRight()) : nullptr};
if (IsValid(Glove) && DebugVirtualHandSettings.DrawingMode != ESGDebugVirtualHandDrawingMode::None) if (IsValid(Glove) && DebugVirtualHandSettings.DrawingMode != ESGDebugVirtualHandDrawingMode::None)
{ {
Pimpl->DrawDebugVirtualHand(); Pimpl->DrawDebugVirtualHand();
@@ -368,8 +363,10 @@ void USGVirtualHandComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, const bool
void USGVirtualHandComponent::EditorTick( void USGVirtualHandComponent::EditorTick(
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{ {
(void) Pimpl->CheckGlove(); Pimpl->UpdateGloveVisibility();
const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(IsRight()) : nullptr};
if (IsValid(Glove) && DebugVirtualHandSettings.DrawingMode != ESGDebugVirtualHandDrawingMode::None) if (IsValid(Glove) && DebugVirtualHandSettings.DrawingMode != ESGDebugVirtualHandDrawingMode::None)
{ {
Pimpl->DrawDebugVirtualHand(); Pimpl->DrawDebugVirtualHand();
@@ -378,13 +375,24 @@ void USGVirtualHandComponent::EditorTick(
bool USGVirtualHandComponent::IsGloveConnected() const bool USGVirtualHandComponent::IsGloveConnected() const
{ {
return Pimpl->CheckGlove(); const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
const USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(IsRight()) : nullptr};
return IsValid(Glove);
}
USGHapticGlove* USGVirtualHandComponent::GetConnectedGlove() const
{
const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(IsRight()) : nullptr};
return Glove;
} }
USGHandPose* USGVirtualHandComponent::GetHandPose() USGHandPose* USGVirtualHandComponent::GetHandPose()
{ {
USGHandPose* HandPose{nullptr}; USGHandPose* HandPose{nullptr};
const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(IsRight()) : nullptr};
if (IsValid(Glove)) if (IsValid(Glove))
{ {
Glove->GetHandPose(this, HandPose); Glove->GetHandPose(this, HandPose);
@@ -587,62 +595,38 @@ const FReferenceSkeleton& USGVirtualHandComponent::FImpl::GetRefSkeleton() const
return Mesh->GetRefSkeleton(); return Mesh->GetRefSkeleton();
} }
bool USGVirtualHandComponent::FImpl::CheckGlove() const void USGVirtualHandComponent::FImpl::UpdateGloveVisibility() const
{ {
if (!USGBackend::GetInstance()->IsBackendInitialized()) const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
{ const USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(Owner->IsRight()) : nullptr};
const bool bSucceeded = USGBackend::GetInstance()->InitializeBackend();
if (!bSucceeded)
{
return false;
}
}
bool bGloveConnected; const bool bConnected = IsValid(Glove);
if (!IsValid(Owner->Glove) || !Owner->Glove->IsConnected()) const bool bIsVisible = Owner->IsVisible();
{
bGloveConnected = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove);
if (!bGloveConnected)
{
Owner->Glove = nullptr;
}
}
else
{
bGloveConnected = true;
}
const bool bIsEditor = IsEditor(); if (Owner->bHiddenInGameIfNoGloveDetected)
if (!bIsEditor)
{ {
const bool bIsVisible = Owner->IsVisible(); if (bConnected)
if (Owner->bHiddenInGameIfNoGloveDetected)
{
if (bGloveConnected)
{
if (!bIsVisible)
{
SetVisibility(true);
}
}
else
{
if (bIsVisible)
{
SetVisibility(false);
}
}
}
else
{ {
if (!bIsVisible) if (!bIsVisible)
{ {
SetVisibility(true); SetVisibility(true);
} }
} }
else
{
if (bIsVisible)
{
SetVisibility(false);
}
}
}
else
{
if (!bIsVisible)
{
SetVisibility(true);
}
} }
return bGloveConnected;
} }
void USGVirtualHandComponent::FImpl::DrawDebugVirtualHand() const void USGVirtualHandComponent::FImpl::DrawDebugVirtualHand() const
@@ -40,12 +40,12 @@
#include "Engine/SkeletalMesh.h" #include "Engine/SkeletalMesh.h"
#include "UObject/ConstructorHelpers.h" #include "UObject/ConstructorHelpers.h"
#include "SenseGlove/SGHeadMountedDisplay.h"
#include "SGBackend/SGBackend.h"
#include "SGCore/SGHapticGlove.h" #include "SGCore/SGHapticGlove.h"
#include "SGDebug/SGDebugGizmo.h" #include "SGDebug/SGDebugGizmo.h"
#include "SGLog/SGLog.h" #include "SGLog/SGLog.h"
#include "SGSettings/SGSettings.h" #include "SGSettings/SGSettings.h"
#include "SGTracking/SGGloveTracker.h"
#include "SGTracking/SGHMDTracker.h"
struct USGWristTrackerComponent::FImpl struct USGWristTrackerComponent::FImpl
{ {
@@ -79,11 +79,9 @@ struct USGWristTrackerComponent::FImpl
bool IsEditor() const; bool IsEditor() const;
bool CheckGlove() const;
void UpdateMotionSource() const; void UpdateMotionSource() const;
void UpdateWristTrackingData() const; void UpdateWristTrackingData() const;
void DrawDebugGizmo(); void DrawDebugGizmo() const;
}; };
USGWristTrackerComponent::USGWristTrackerComponent(const FObjectInitializer& ObjectInitializer) USGWristTrackerComponent::USGWristTrackerComponent(const FObjectInitializer& ObjectInitializer)
@@ -105,27 +103,10 @@ USGWristTrackerComponent::USGWristTrackerComponent(const FObjectInitializer& Obj
SetCanEverAffectNavigation(false); SetCanEverAffectNavigation(false);
bOverridePluginWristTrackingSettings = false; bOverridePluginWristTrackingSettings = false;
WristTrackingSettings = FSGWristTrackingSettings( WristTrackingSettings = FSGWristTrackingSettings{};
ESGPositionalTrackingHardware::None,
FVector::ZeroVector,
FVector::ZeroVector,
FRotator::ZeroRotator,
FRotator::ZeroRotator,
EControllerHand::Left,
EControllerHand::Right,
false,
FSGDebugGizmoSettings(
4.0f, 1.0f,
FColor(255, 0, 0, 255),
FColor(0, 255, 0, 255),
FColor(0, 0, 255, 255),
false, 1.1f, 0
)
);
bRight = true; bRight = true;
Glove = nullptr;
WristLocation = FVector::ZeroVector; WristLocation = FVector::ZeroVector;
WristRotation = FRotator::ZeroRotator; WristRotation = FRotator::ZeroRotator;
} }
@@ -149,7 +130,7 @@ const FSGWristTrackingSettings& USGWristTrackerComponent::GetWristTrackingSettin
return WristTrackingSettings; return WristTrackingSettings;
} }
return Settings->GetWristTrackingSettings(); return Settings->GetTrackingSettings().WristTrackingSettings;
} }
void USGWristTrackerComponent::SetWristTrackingSettings(const FSGWristTrackingSettings& InWristTrackingSettings) void USGWristTrackerComponent::SetWristTrackingSettings(const FSGWristTrackingSettings& InWristTrackingSettings)
@@ -180,7 +161,7 @@ void USGWristTrackerComponent::InitializeComponent()
{ {
Super::InitializeComponent(); Super::InitializeComponent();
(void) Pimpl->CheckGlove(); Pimpl->UpdateWristTrackingData();
Pimpl->UpdateMotionSource(); Pimpl->UpdateMotionSource();
} }
@@ -189,7 +170,7 @@ void USGWristTrackerComponent::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
(void) Pimpl->CheckGlove(); Pimpl->UpdateWristTrackingData();
Pimpl->UpdateMotionSource(); Pimpl->UpdateMotionSource();
} }
@@ -207,19 +188,19 @@ void USGWristTrackerComponent::TickComponent(
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (!!WristTrackingSettings.bDrawWristTrackerDebugGizmo) if (!!WristTrackingSettings.bDrawDebugGizmo)
{ {
Pimpl->DrawDebugGizmo(); Pimpl->DrawDebugGizmo();
} }
(void) Pimpl->CheckGlove(); Pimpl->UpdateWristTrackingData();
} }
void USGWristTrackerComponent::EditorTick( void USGWristTrackerComponent::EditorTick(
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{ {
(void) Pimpl->CheckGlove(); Pimpl->UpdateWristTrackingData();
} }
USGWristTrackerComponent::FImpl::FImpl(USGWristTrackerComponent* InOwner) USGWristTrackerComponent::FImpl::FImpl(USGWristTrackerComponent* InOwner)
@@ -240,35 +221,6 @@ bool USGWristTrackerComponent::FImpl::IsEditor() const
return false; return false;
} }
bool USGWristTrackerComponent::FImpl::CheckGlove() const
{
if (!USGBackend::GetInstance()->IsBackendInitialized())
{
const bool bSucceeded = USGBackend::GetInstance()->InitializeBackend();
if (!bSucceeded)
{
return false;
}
}
bool bGloveConnected;
if (!IsValid(Owner->Glove) || !Owner->Glove->IsConnected())
{
bGloveConnected = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove);
if (!bGloveConnected)
{
Owner->Glove = nullptr;
}
}
else
{
bGloveConnected = true;
UpdateWristTrackingData();
}
return bGloveConnected;
}
void USGWristTrackerComponent::FImpl::UpdateMotionSource() const void USGWristTrackerComponent::FImpl::UpdateMotionSource() const
{ {
if (GEngine) if (GEngine)
@@ -281,7 +233,12 @@ void USGWristTrackerComponent::FImpl::UpdateMotionSource() const
void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const
{ {
ensureAlwaysMsgf(Owner->Glove, TEXT("Invalid Glove!")); const USGGloveTracker* GloveTracker{USGGloveTracker::GetInstance()};
const USGHapticGlove* Glove{IsValid(GloveTracker) ? GloveTracker->GetGlove(Owner->IsRight()) : nullptr};
if (!IsValid(Glove))
{
return;
}
FVector TrackerLocation{Owner->GetComponentLocation()}; FVector TrackerLocation{Owner->GetComponentLocation()};
FRotator TrackerRotation{Owner->GetComponentRotation()}; FRotator TrackerRotation{Owner->GetComponentRotation()};
@@ -289,7 +246,7 @@ void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const
ESGPositionalTrackingHardware TrackerHardware = Owner->GetWristTrackingSettings().TrackingHardware; ESGPositionalTrackingHardware TrackerHardware = Owner->GetWristTrackingSettings().TrackingHardware;
if (TrackerHardware == ESGPositionalTrackingHardware::None) if (TrackerHardware == ESGPositionalTrackingHardware::None)
{ {
const ESGHeadMountedDisplayDevice HmdDevice = FSGHeadMountedDisplay::GetDeviceType(); const ESGHeadMountedDisplayDevice HmdDevice = FSGHMDTracker::GetDeviceType();
switch (HmdDevice) switch (HmdDevice)
{ {
case ESGHeadMountedDisplayDevice::MetaQuest2: case ESGHeadMountedDisplayDevice::MetaQuest2:
@@ -330,8 +287,8 @@ void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const
FVector NewWristLocation; FVector NewWristLocation;
FRotator NewWristRotation; FRotator NewWristRotation;
Owner->Glove->GetWristLocation(TrackerLocation, TrackerRotation, TrackerHardware, Glove->GetWristLocation(TrackerLocation, TrackerRotation, TrackerHardware,
NewWristLocation, NewWristRotation); NewWristLocation, NewWristRotation);
const bool bLocationUpdated = !Owner->WristLocation.Equals(NewWristLocation, SMALL_NUMBER); const bool bLocationUpdated = !Owner->WristLocation.Equals(NewWristLocation, SMALL_NUMBER);
const bool bRotationUpdated = !Owner->WristRotation.Equals(NewWristRotation, SMALL_NUMBER); const bool bRotationUpdated = !Owner->WristRotation.Equals(NewWristRotation, SMALL_NUMBER);
@@ -362,12 +319,12 @@ void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const
} }
} }
void USGWristTrackerComponent::FImpl::DrawDebugGizmo() void USGWristTrackerComponent::FImpl::DrawDebugGizmo() const
{ {
const UWorld* World{Owner->GetWorld()}; const UWorld* World{Owner->GetWorld()};
const FVector& Location{Owner->GetComponentLocation()}; const FVector& Location{Owner->GetComponentLocation()};
const FRotator& Rotation{Owner->GetComponentRotation()}; const FRotator& Rotation{Owner->GetComponentRotation()};
const FSGDebugGizmoSettings& DebugGizmoSettings{Owner->GetWristTrackingSettings().WristTrackerDebugGizmoSettings}; const FSGDebugGizmoSettings& DebugGizmoSettings{Owner->GetWristTrackingSettings().DebugGizmoSettings};
FSGDebugGizmo::Draw(World, Location, Rotation, DebugGizmoSettings); FSGDebugGizmo::Draw(World, Location, Rotation, DebugGizmoSettings);
} }
@@ -236,7 +236,6 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
FSGDebugVirtualHandSettings RealHandLeftDebugSettings; FSGDebugVirtualHandSettings RealHandLeftDebugSettings;
RealHandLeftDebugSettings.bDrawDebugVirtualHand = true; RealHandLeftDebugSettings.bDrawDebugVirtualHand = true;
RealHandLeftDebugSettings.DrawingMode = ESGDebugVirtualHandDrawingMode::GizmoJoints; RealHandLeftDebugSettings.DrawingMode = ESGDebugVirtualHandDrawingMode::GizmoJoints;
RealHandLeftDebugSettings.GizmoThickness = 0.5f;
RealHandLeft->SetDebugVirtualHandSettings(MoveTemp(RealHandLeftDebugSettings)); RealHandLeft->SetDebugVirtualHandSettings(MoveTemp(RealHandLeftDebugSettings));
LeftThumbFingertipGrabCollider = ObjectInitializer.CreateDefaultSubobject<USphereComponent>( LeftThumbFingertipGrabCollider = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(
@@ -463,7 +462,6 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
FSGDebugVirtualHandSettings RealHandRightDebugSettings; FSGDebugVirtualHandSettings RealHandRightDebugSettings;
RealHandRightDebugSettings.bDrawDebugVirtualHand = true; RealHandRightDebugSettings.bDrawDebugVirtualHand = true;
RealHandRightDebugSettings.DrawingMode = ESGDebugVirtualHandDrawingMode::GizmoJoints; RealHandRightDebugSettings.DrawingMode = ESGDebugVirtualHandDrawingMode::GizmoJoints;
RealHandRightDebugSettings.GizmoThickness = 0.5f;
RealHandRight->SetDebugVirtualHandSettings(MoveTemp(RealHandRightDebugSettings)); RealHandRight->SetDebugVirtualHandSettings(MoveTemp(RealHandRightDebugSettings));
RightThumbFingertipGrabCollider = ObjectInitializer.CreateDefaultSubobject<USphereComponent>( RightThumbFingertipGrabCollider = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(
@@ -127,9 +127,6 @@ private:
FSGDebugVirtualHandSettings DebugVirtualHandSettings; FSGDebugVirtualHandSettings DebugVirtualHandSettings;
private: private:
UPROPERTY(Transient)
USGHapticGlove* Glove;
UPROPERTY(Transient) UPROPERTY(Transient)
USGWristTrackerComponent* WristTracker; USGWristTrackerComponent* WristTracker;
@@ -311,12 +308,7 @@ protected:
public: public:
bool IsGloveConnected() const; bool IsGloveConnected() const;
USGHapticGlove* GetConnectedGlove() const;
FORCEINLINE USGHapticGlove* GetConnectedGlove() const
{
return Glove;
}
USGHandPose* GetHandPose(); USGHandPose* GetHandPose();
public: public:
@@ -111,9 +111,6 @@ private:
FSGWristTrackingSettings WristTrackingSettings; FSGWristTrackingSettings WristTrackingSettings;
private: private:
UPROPERTY(Transient)
USGHapticGlove* Glove;
UPROPERTY(Transient) UPROPERTY(Transient)
FVector WristLocation; FVector WristLocation;
+1 -2
View File
@@ -58,12 +58,11 @@ public class SenseGlove : ModuleRules
#if UE_5_3_OR_LATER #if UE_5_3_OR_LATER
"XRBase", "XRBase",
#endif #endif
"SenseGloveBackend",
"SenseGloveConnect",
"SenseGloveCore", "SenseGloveCore",
"SenseGloveDebug", "SenseGloveDebug",
"SenseGloveLog", "SenseGloveLog",
"SenseGloveSettings", "SenseGloveSettings",
"SenseGloveTracking",
"SenseGloveTypes", "SenseGloveTypes",
} }
); );
@@ -35,10 +35,27 @@
#include "SGSettings/SGDebugGizmoSettings.h" #include "SGSettings/SGDebugGizmoSettings.h"
FSGDebugGizmoSettings::FSGDebugGizmoSettings()
: Length(4.0f),
Thickness(0.4f),
XAxisColor(255, 0, 0, 255),
YAxisColor(0, 255, 0, 255),
ZAxisColor(0, 0, 255, 255),
bPersistentLines(false),
LifeTimeModifier(1.1),
DepthPriority(0.0f)
{
}
FSGDebugGizmoSettings::FSGDebugGizmoSettings( FSGDebugGizmoSettings::FSGDebugGizmoSettings(
const float InLength, const float InThickness, const float InLength,
const FColor& InXAxisColor, const FColor& InYAxisColor, const FColor& InZAxisColor, const float InThickness,
const bool bInPersistentLines, const float InLifeTimeModifier, const uint8 InDepthPriority) const FColor& InXAxisColor,
const FColor& InYAxisColor,
const FColor& InZAxisColor,
const bool bInPersistentLines,
const float InLifeTimeModifier,
const uint8 InDepthPriority)
: Length(InLength), : Length(InLength),
Thickness(InThickness), Thickness(InThickness),
XAxisColor(InXAxisColor), XAxisColor(InXAxisColor),
@@ -40,9 +40,9 @@ FSGDebugVirtualHandSettings::FSGDebugVirtualHandSettings()
DrawingMode(ESGDebugVirtualHandDrawingMode::None), DrawingMode(ESGDebugVirtualHandDrawingMode::None),
CubeExtent(FVector(0.5f, 0.5f, 0.5f)), CubeExtent(FVector(0.5f, 0.5f, 0.5f)),
CubeColor(255, 0, 0, 255), CubeColor(255, 0, 0, 255),
CubeThickness(0.1f), CubeThickness(0.2f),
GizmoLength(1.0f), GizmoLength(1.0f),
GizmoThickness(1.0f), GizmoThickness(0.25f),
GizmoXAxisColor(255, 0, 0, 255), GizmoXAxisColor(255, 0, 0, 255),
GizmoYAxisColor(0, 255, 0, 255), GizmoYAxisColor(0, 255, 0, 255),
GizmoZAxisColor(0, 0, 255, 255), GizmoZAxisColor(0, 0, 255, 255),
@@ -55,10 +55,17 @@ FSGDebugVirtualHandSettings::FSGDebugVirtualHandSettings()
FSGDebugVirtualHandSettings::FSGDebugVirtualHandSettings( FSGDebugVirtualHandSettings::FSGDebugVirtualHandSettings(
const bool bInDrawDebugVirtualHand, const bool bInDrawDebugVirtualHand,
const ESGDebugVirtualHandDrawingMode InDrawingMode, const ESGDebugVirtualHandDrawingMode InDrawingMode,
const FVector& InCubeExtent, const FColor& InCubeColor, const float InCubeThickness, const FVector& InCubeExtent,
const float InGizmoLength, const float InGizmoThickness, const FColor& InCubeColor,
const FColor& InGizmoXAxisColor, const FColor& InGizmoYAxisColor, const FColor& InGizmoZAxisColor, const float InCubeThickness,
const bool bInPersistentLines, const float InLifeTimeModifier, const uint8 InDepthPriority) const float InGizmoLength,
const float InGizmoThickness,
const FColor& InGizmoXAxisColor,
const FColor& InGizmoYAxisColor,
const FColor& InGizmoZAxisColor,
const bool bInPersistentLines,
const float InLifeTimeModifier,
const uint8 InDepthPriority)
: bDrawDebugVirtualHand(bInDrawDebugVirtualHand), : bDrawDebugVirtualHand(bInDrawDebugVirtualHand),
DrawingMode(InDrawingMode), DrawingMode(InDrawingMode),
CubeExtent(InCubeExtent), CubeExtent(InCubeExtent),
@@ -0,0 +1,47 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SGSettings/SGGloveTrackingSettings.h"
FSGGloveTrackingSettings::FSGGloveTrackingSettings()
: GloveConnectivityCheckInterval(0.125f)
{
}
FSGGloveTrackingSettings::FSGGloveTrackingSettings(
const float InGloveConnectivityCheckInterval)
: GloveConnectivityCheckInterval(InGloveConnectivityCheckInterval)
{
}
@@ -0,0 +1,47 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SGSettings/SGHMDTrackingSettings.h"
FSGHMDTrackingSettings::FSGHMDTrackingSettings()
: ViveHMDDetectionPriority(ESGViveHMDDetectionPriority::HtcViveFocus3First)
{
}
FSGHMDTrackingSettings::FSGHMDTrackingSettings(
const ESGViveHMDDetectionPriority InViveHmdDetectionPriority)
: ViveHMDDetectionPriority(InViveHmdDetectionPriority)
{
}
@@ -0,0 +1,50 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SGSettings/SGHandTrackingSettings.h"
FSGHandTrackingSettings::FSGHandTrackingSettings()
: bUseMoreSpecificMotionSourceNames(false),
bSupportLegacyControllerMotionSources(true)
{
}
FSGHandTrackingSettings::FSGHandTrackingSettings(
const bool bInUseMoreSpecificMotionSourceNames,
const bool bInSupportLegacyControllerMotionSources)
: bUseMoreSpecificMotionSourceNames(bInUseMoreSpecificMotionSourceNames),
bSupportLegacyControllerMotionSources(bInSupportLegacyControllerMotionSources)
{
}
@@ -77,23 +77,7 @@ USGSettings* USGSettings::GetInstance()
USGSettings::USGSettings() USGSettings::USGSettings()
: Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter)) : Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
{ {
WristTrackingSettings = FSGWristTrackingSettings( TrackingSettings = FSGTrackingSettings{};
ESGPositionalTrackingHardware::None,
FVector::ZeroVector,
FVector::ZeroVector,
FRotator::ZeroRotator,
FRotator::ZeroRotator,
EControllerHand::Left,
EControllerHand::Right,
false,
FSGDebugGizmoSettings(
4.0f, 1.0f,
FColor(255, 0, 0, 255),
FColor(0, 255, 0, 255),
FColor(0, 0, 255, 255),
false, 1.1f, 0
)
);
} }
bool USGSettings::ShouldCreateSubsystem(UObject* Outer) const bool USGSettings::ShouldCreateSubsystem(UObject* Outer) const
@@ -116,7 +100,7 @@ void USGSettings::Deinitialize()
Super::Deinitialize(); Super::Deinitialize();
(void)Pimpl.Release(); (void) Pimpl.Release();
SGLOG("The SenseGlove settings singleton has been successfully de-initialized!"); SGLOG("The SenseGlove settings singleton has been successfully de-initialized!");
} }
@@ -1,4 +1,4 @@
/** /**
* @file * @file
* *
* @author Mamadou Babaei <mamadou@senseglove.com> * @author Mamadou Babaei <mamadou@senseglove.com>
@@ -33,46 +33,23 @@
*/ */
#include "SGKismet/SGHeadMountedDisplayKismetLibrary.h" #include "SGSettings/SGTrackingSettings.h"
#include "SenseGlove/SGHeadMountedDisplay.h" FSGTrackingSettings::FSGTrackingSettings()
: bFallbackToHandTrackingIfNoGloveDetected(true)
FName UHeadMountedDisplayKismetLibrary::GetDeviceName()
{ {
return FSGHeadMountedDisplay::GetDeviceName();
} }
bool UHeadMountedDisplayKismetLibrary::IsMetaQuest2() FSGTrackingSettings::FSGTrackingSettings(
const bool bInFallbackToHandTrackingIfNoGloveDetected,
const FSGGloveTrackingSettings& InGloveTrackingSettings,
const FSGHandTrackingSettings& InHandTrackingSettings,
const FSGHMDTrackingSettings& InHmdTrackingSettings,
const FSGWristTrackingSettings& InWristTrackingSettings)
: bFallbackToHandTrackingIfNoGloveDetected(bInFallbackToHandTrackingIfNoGloveDetected),\
GloveTrackingSettings(InGloveTrackingSettings),
HandTrackingSettings(InHandTrackingSettings),
HMDTrackingSettings(InHmdTrackingSettings),
WristTrackingSettings(InWristTrackingSettings)
{ {
return FSGHeadMountedDisplay::IsMetaQuest2();
}
bool UHeadMountedDisplayKismetLibrary::IsMetaQuestPro()
{
return FSGHeadMountedDisplay::IsMetaQuestPro();
}
bool UHeadMountedDisplayKismetLibrary::IsMetaQuest3()
{
return FSGHeadMountedDisplay::IsMetaQuest3();
}
bool UHeadMountedDisplayKismetLibrary::IsHtcVivePro()
{
return FSGHeadMountedDisplay::IsHtcVivePro();
}
bool UHeadMountedDisplayKismetLibrary::IsHtcViveFocus3()
{
return FSGHeadMountedDisplay::IsHtcViveFocus3();
}
bool UHeadMountedDisplayKismetLibrary::IsHtcViveXRElite()
{
return FSGHeadMountedDisplay::IsHtcViveXRElite();
}
ESGHeadMountedDisplayDevice UHeadMountedDisplayKismetLibrary::GetDeviceType()
{
return FSGHeadMountedDisplay::GetDeviceType();
} }
@@ -43,8 +43,8 @@ FSGWristTrackingSettings::FSGWristTrackingSettings()
TrackingHardwareRotationOffsetRightHand(FRotator::ZeroRotator), TrackingHardwareRotationOffsetRightHand(FRotator::ZeroRotator),
LeftHandMotionSource(EControllerHand::Left), LeftHandMotionSource(EControllerHand::Left),
RightHandMotionSource(EControllerHand::Right), RightHandMotionSource(EControllerHand::Right),
bDrawWristTrackerDebugGizmo(false), bDrawDebugGizmo(false),
WristTrackerDebugGizmoSettings(FSGDebugGizmoSettings()) DebugGizmoSettings(FSGDebugGizmoSettings{})
{ {
} }
@@ -56,8 +56,8 @@ FSGWristTrackingSettings::FSGWristTrackingSettings(
const FRotator& InTrackingHardwareRotationOffsetRightHand, const FRotator& InTrackingHardwareRotationOffsetRightHand,
const EControllerHand InLeftHandMotionSource, const EControllerHand InLeftHandMotionSource,
const EControllerHand InRightHandMotionSource, const EControllerHand InRightHandMotionSource,
const bool bInDrawWristTrackerDebugGizmo, const bool bInDrawDebugGizmo,
const FSGDebugGizmoSettings& InWristTrackerDebugGizmoSettings) const FSGDebugGizmoSettings& InDebugGizmoSettings)
: TrackingHardware(InTrackingHardware), : TrackingHardware(InTrackingHardware),
TrackingHardwareLocationOffsetLeftHand(InTrackingHardwareLocationOffsetLeftHand), TrackingHardwareLocationOffsetLeftHand(InTrackingHardwareLocationOffsetLeftHand),
TrackingHardwareLocationOffsetRightHand(InTrackingHardwareLocationOffsetRightHand), TrackingHardwareLocationOffsetRightHand(InTrackingHardwareLocationOffsetRightHand),
@@ -65,7 +65,7 @@ FSGWristTrackingSettings::FSGWristTrackingSettings(
TrackingHardwareRotationOffsetRightHand(InTrackingHardwareRotationOffsetRightHand), TrackingHardwareRotationOffsetRightHand(InTrackingHardwareRotationOffsetRightHand),
LeftHandMotionSource(InLeftHandMotionSource), LeftHandMotionSource(InLeftHandMotionSource),
RightHandMotionSource(InRightHandMotionSource), RightHandMotionSource(InRightHandMotionSource),
bDrawWristTrackerDebugGizmo(bInDrawWristTrackerDebugGizmo), bDrawDebugGizmo(bInDrawDebugGizmo),
WristTrackerDebugGizmoSettings(InWristTrackerDebugGizmoSettings) DebugGizmoSettings(InDebugGizmoSettings)
{ {
} }
@@ -70,12 +70,14 @@ public:
uint8 DepthPriority; uint8 DepthPriority;
public: public:
explicit FSGDebugGizmoSettings(float InLength = 1.0f, FSGDebugGizmoSettings();
float InThickness = 1.0f,
const FColor& InXAxisColor = FColor(255, 0, 0, 255), FSGDebugGizmoSettings(float InLength,
const FColor& InYAxisColor = FColor(0, 255, 0, 255), float InThickness,
const FColor& InZAxisColor = FColor(0, 0, 255, 255), const FColor& InXAxisColor,
bool bInPersistentLines = false, const FColor& InYAxisColor,
float InLifeTimeModifier = 1.1f, const FColor& InZAxisColor,
uint8 InDepthPriority = 0); bool bInPersistentLines,
float InLifeTimeModifier,
uint8 InDepthPriority);
}; };
@@ -55,64 +55,75 @@ public:
ESGDebugVirtualHandDrawingMode DrawingMode; ESGDebugVirtualHandDrawingMode DrawingMode;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::CubicJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::CubicJoints",
EditConditionHides))
FVector CubeExtent; FVector CubeExtent;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::CubicJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::CubicJoints",
EditConditionHides))
FColor CubeColor; FColor CubeColor;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::CubicJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::CubicJoints",
EditConditionHides))
float CubeThickness; float CubeThickness;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints",
EditConditionHides))
float GizmoLength; float GizmoLength;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints",
EditConditionHides))
float GizmoThickness; float GizmoThickness;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints",
EditConditionHides))
FColor GizmoXAxisColor; FColor GizmoXAxisColor;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints",
EditConditionHides))
FColor GizmoYAxisColor; FColor GizmoYAxisColor;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints",
EditConditionHides))
FColor GizmoZAxisColor; FColor GizmoZAxisColor;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints",
EditConditionHides))
uint8 bPersistentLines : 1; uint8 bPersistentLines : 1;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints",
EditConditionHides))
float LifeTimeModifier; float LifeTimeModifier;
UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings", UPROPERTY(EditAnywhere, Category = "Debug Virtual Hand Settings",
meta=(EditCondition="DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints", EditConditionHides)) meta=(EditCondition="bDrawDebugVirtualHand && DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints",
EditConditionHides))
uint8 DepthPriority; uint8 DepthPriority;
public: public:
FSGDebugVirtualHandSettings(); FSGDebugVirtualHandSettings();
explicit FSGDebugVirtualHandSettings( FSGDebugVirtualHandSettings(
bool bInDrawDebugVirtualHand, bool bInDrawDebugVirtualHand,
ESGDebugVirtualHandDrawingMode InDrawingMode = ESGDebugVirtualHandDrawingMode::None, ESGDebugVirtualHandDrawingMode InDrawingMode,
const FVector& InCubeExtent = FVector(0.5f, 0.5f, 0.5f), const FVector& InCubeExtent,
const FColor& InCubeColor = FColor(255, 0, 0, 255), const FColor& InCubeColor,
float InCubeThickness = 0.1f, float InCubeThickness,
float InGizmoLength = 1.0f, float InGizmoLength,
float InGizmoThickness = 0.2f, float InGizmoThickness,
const FColor& InGizmoXAxisColor = FColor(255, 0, 0, 255), const FColor& InGizmoXAxisColor,
const FColor& InGizmoYAxisColor = FColor(0, 255, 0, 255), const FColor& InGizmoYAxisColor,
const FColor& InGizmoZAxisColor = FColor(0, 0, 255, 255), const FColor& InGizmoZAxisColor,
bool bInPersistentLines = false, bool bInPersistentLines,
float InLifeTimeModifier = 1.1f, float InLifeTimeModifier,
uint8 InDepthPriority = 0); uint8 InDepthPriority);
}; };
@@ -0,0 +1,62 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "UObject/ObjectMacros.h"
#include "SGGloveTrackingSettings.generated.h"
/**
* Implements the glove tracking settings for the SenseGlove Tracking module.
*/
USTRUCT(BlueprintType)
struct SENSEGLOVESETTINGS_API FSGGloveTrackingSettings
{
GENERATED_USTRUCT_BODY()
public:
/**
* The interval to check for glove connectivity. The default is 0.125f which means 8 times in each second.
*/
UPROPERTY(Config, EditDefaultsOnly, Category="Glove Tracking")
float GloveConnectivityCheckInterval;
public:
FSGGloveTrackingSettings();
explicit FSGGloveTrackingSettings(
float InGloveConnectivityCheckInterval);
};
@@ -0,0 +1,65 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "UObject/ObjectMacros.h"
#include "SGTypes/SGTrackingTypes.h"
#include "SGHMDTrackingSettings.generated.h"
/**
* Implements the hand tracking settings for the SenseGlove Tracking module.
*/
USTRUCT(BlueprintType)
struct SENSEGLOVESETTINGS_API FSGHMDTrackingSettings
{
GENERATED_USTRUCT_BODY()
public:
/**
* Used to determine which VIVE HMD should we try to detect first, since we cannot distinguish between
* HTC VIVE Focus 3 and HTC VIVE XR Elite.
*/
UPROPERTY(Config, EditDefaultsOnly, Category="HMD Tracking")
ESGViveHMDDetectionPriority ViveHMDDetectionPriority;
public:
FSGHMDTrackingSettings();
explicit FSGHMDTrackingSettings(
ESGViveHMDDetectionPriority InViveHmdDetectionPriority);
};
@@ -0,0 +1,72 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "UObject/ObjectMacros.h"
#include "SGHandTrackingSettings.generated.h"
/**
* Implements the hand tracking settings for the SenseGlove Tracking module.
*/
USTRUCT(BlueprintType)
struct SENSEGLOVESETTINGS_API FSGHandTrackingSettings
{
GENERATED_USTRUCT_BODY()
public:
/**
* If false (the default) the motion sources for hand tracking will be of the form '[Left|Right][Keypoint]'. If
* true they will be of the form 'HandTracking[Left|Right][Keypoint]'. True is recommended to avoid collisions
* between motion sources from different device types.
*/
UPROPERTY(Config, EditDefaultsOnly, Category="Hand Tracking")
uint8 bUseMoreSpecificMotionSourceNames : 1;
/**
* If true hand tracking supports the 'Left' and 'Right' legacy motion sources. If false it does not. False is
* recommended unless you need legacy compatibility in an older unreal projects.
*/
UPROPERTY(Config, EditDefaultsOnly, Category="Hand Tracking")
uint8 bSupportLegacyControllerMotionSources : 1;
public:
FSGHandTrackingSettings();
FSGHandTrackingSettings(
bool bInUseMoreSpecificMotionSourceNames,
bool bInSupportLegacyControllerMotionSources);
};
@@ -42,10 +42,13 @@
#include "Templates/UniquePtr.h" #include "Templates/UniquePtr.h"
#include "UObject/ObjectMacros.h" #include "UObject/ObjectMacros.h"
#include "SGSettings/SGWristTrackingSettings.h" #include "SGSettings/SGTrackingSettings.h"
#include "SGSettings.generated.h" #include "SGSettings.generated.h"
/**
* Implements the settings for the SenseGlove Unreal Engine Plugin.
*/
UCLASS(config = SenseGloveSettings) UCLASS(config = SenseGloveSettings)
class SENSEGLOVESETTINGS_API USGSettings : public UEngineSubsystem class SENSEGLOVESETTINGS_API USGSettings : public UEngineSubsystem
{ {
@@ -67,20 +70,20 @@ private:
private: private:
UPROPERTY(Config, EditDefaultsOnly, Category = "SenseGlove") UPROPERTY(Config, EditDefaultsOnly, Category = "SenseGlove")
FSGWristTrackingSettings WristTrackingSettings; FSGTrackingSettings TrackingSettings;
private: private:
USGSettings(); USGSettings();
public: public:
FORCEINLINE const FSGWristTrackingSettings& GetWristTrackingSettings() const FORCEINLINE const FSGTrackingSettings& GetTrackingSettings() const
{ {
return WristTrackingSettings; return TrackingSettings;
} }
void SetWristTrackingSettings(const FSGWristTrackingSettings& InWristTrackingSettings) void SetTrackingSettings(const FSGTrackingSettings& InTrackingSettings)
{ {
WristTrackingSettings = InWristTrackingSettings; TrackingSettings = InTrackingSettings;
} }
public: public:
@@ -0,0 +1,85 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "UObject/ObjectMacros.h"
#include "SGSettings/SGGloveTrackingSettings.h"
#include "SGSettings/SGHandTrackingSettings.h"
#include "SGSettings/SGHMDTrackingSettings.h"
#include "SGSettings/SGWristTrackingSettings.h"
#include "SGTrackingSettings.generated.h"
/**
* Implements the settings for the SenseGlove Tracking module.
*/
USTRUCT(BlueprintType)
struct SENSEGLOVESETTINGS_API FSGTrackingSettings
{
GENERATED_USTRUCT_BODY()
public:
/**
* If false, only a real glove will be tracked, otherwise will fall back to hand tracking if available and
* supported by the HMD device.
*/
UPROPERTY(Config, EditDefaultsOnly, Category="Tracking")
uint8 bFallbackToHandTrackingIfNoGloveDetected : 1;
UPROPERTY(Config, EditDefaultsOnly, Category="Tracking")
FSGGloveTrackingSettings GloveTrackingSettings;
UPROPERTY(Config, EditDefaultsOnly, Category="Tracking",
meta=(EditCondition="bFallbackToHandTrackingIfNoGloveDetected", EditConditionHides))
FSGHandTrackingSettings HandTrackingSettings;
UPROPERTY(Config, EditDefaultsOnly, Category="Tracking")
FSGHMDTrackingSettings HMDTrackingSettings;
UPROPERTY(Config, EditDefaultsOnly, Category="Tracking")
FSGWristTrackingSettings WristTrackingSettings;
public:
FSGTrackingSettings();
FSGTrackingSettings(
bool bInFallbackToHandTrackingIfNoGloveDetected,
const FSGGloveTrackingSettings& InGloveTrackingSettings,
const FSGHandTrackingSettings& InHandTrackingSettings,
const FSGHMDTrackingSettings& InHmdTrackingSettings,
const FSGWristTrackingSettings& InWristTrackingSettings);
};
@@ -100,20 +100,20 @@ public:
/** /**
* If enabled, draws debug Wrist trackers where possible. * If enabled, draws debug Wrist trackers where possible.
*/ */
UPROPERTY(Config, EditDefaultsOnly, Category = "Debug Wrist Tracking") UPROPERTY(Config, EditDefaultsOnly, Category = "Wrist Tracking | Debug")
uint8 bDrawWristTrackerDebugGizmo : 1; uint8 bDrawDebugGizmo : 1;
/** /**
* Valid only if bDrawDebugWristTrackerGizmo is enabled. * Valid only if bDrawDebugGizmo is enabled.
*/ */
UPROPERTY(Config, EditDefaultsOnly, Category = "Debug Wrist Tracking", UPROPERTY(Config, EditDefaultsOnly, Category = "Wrist Tracking | Debug",
meta=(EditCondition="bDrawWristTrackerDebugGizmo", EditConditionHides)) meta=(EditCondition="bDrawDebugGizmo", EditConditionHides))
FSGDebugGizmoSettings WristTrackerDebugGizmoSettings; FSGDebugGizmoSettings DebugGizmoSettings;
public: public:
FSGWristTrackingSettings(); FSGWristTrackingSettings();
explicit FSGWristTrackingSettings( FSGWristTrackingSettings(
ESGPositionalTrackingHardware InTrackingHardware, ESGPositionalTrackingHardware InTrackingHardware,
const FVector& InTrackingHardwareLocationOffsetLeftHand, const FVector& InTrackingHardwareLocationOffsetLeftHand,
const FVector& InTrackingHardwareLocationOffsetRightHand, const FVector& InTrackingHardwareLocationOffsetRightHand,
@@ -121,6 +121,6 @@ public:
const FRotator& InTrackingHardwareRotationOffsetRightHand, const FRotator& InTrackingHardwareRotationOffsetRightHand,
EControllerHand InLeftHandMotionSource, EControllerHand InLeftHandMotionSource,
EControllerHand InRightHandMotionSource, EControllerHand InRightHandMotionSource,
bool bInDrawWristTrackerDebugGizmo, bool bInDrawDebugGizmo,
const FSGDebugGizmoSettings& InWristTrackerDebugGizmoSettings); const FSGDebugGizmoSettings& InDebugGizmoSettings);
}; };
@@ -42,13 +42,13 @@ USGSettings* USGSettingsKismetLibrary::GetInstance()
return USGSettings::GetInstance(); return USGSettings::GetInstance();
} }
const FSGWristTrackingSettings& USGSettingsKismetLibrary::GetWristTrackingSettings(const USGSettings* Settings) const FSGTrackingSettings& USGSettingsKismetLibrary::GetTrackingSettings(const USGSettings* Settings)
{ {
return Settings->GetWristTrackingSettings(); return Settings->GetTrackingSettings();
} }
void USGSettingsKismetLibrary::SetWristTrackingSettings( void USGSettingsKismetLibrary::SetTrackingSettings(
USGSettings* Settings, const FSGWristTrackingSettings& InWristTrackingSettings) USGSettings* Settings, const FSGTrackingSettings& InTrackingSettings)
{ {
Settings->SetWristTrackingSettings(InWristTrackingSettings); Settings->SetTrackingSettings(InTrackingSettings);
} }
@@ -37,6 +37,7 @@
#include "SGKismet/SGBlueprintFunctionLibrary.h" #include "SGKismet/SGBlueprintFunctionLibrary.h"
#include "SGSettings/SGWristTrackingSettings.h" #include "SGSettings/SGWristTrackingSettings.h"
#include "SGSettings/SGTrackingSettings.h"
#include "SGSettingsKismetLibrary.generated.h" #include "SGSettingsKismetLibrary.generated.h"
@@ -52,9 +53,9 @@ public:
static USGSettings* GetInstance(); static USGSettings* GetInstance();
UFUNCTION(BlueprintPure, Category="SenseGlove | Settings") UFUNCTION(BlueprintPure, Category="SenseGlove | Settings")
static const FSGWristTrackingSettings& GetWristTrackingSettings(const USGSettings* Settings); static const FSGTrackingSettings& GetTrackingSettings(const USGSettings* Settings);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Settings") UFUNCTION(BlueprintCallable, Category="SenseGlove | Settings")
static void SetWristTrackingSettings(UPARAM(ref) USGSettings* Settings, static void SetTrackingSettings(UPARAM(ref) USGSettings* Settings,
const FSGWristTrackingSettings& InWristTrackingSettings); const FSGTrackingSettings& InTrackingSettings);
}; };
@@ -0,0 +1,279 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SGTracking/SGGloveTracker.h"
#if WITH_EDITOR
#include "Editor.h"
#endif /* WITH_EDITOR */
#include "Engine/Engine.h"
#include "Engine/TimerHandle.h"
#include "Engine/World.h"
#include "Subsystems/UnrealEditorSubsystem.h"
#include "TimerManager.h"
#include "SGBackend/SGBackend.h"
#include "SGBuildHacks/SGPlatform.h"
#include "SGCore/SGHapticGlove.h"
#include "SGLog/SGLog.h"
#include "SGSettings/SGSettings.h"
#include "SGSettings/SGTrackingSettings.h"
struct USGGloveTracker::FImpl
{
/************************
* Static methods
************************/
static UWorld* GetWorld();
FORCEINLINE static float GetGloveConnectivityCheckInterval()
{
const USGSettings* Settings{USGSettings::GetInstance()};
ensureAlwaysMsgf(Settings, TEXT("The settings subsystem has not been initialized!"));
return Settings->GetTrackingSettings().GloveTrackingSettings.GloveConnectivityCheckInterval;
}
/************************
* Member variables
************************/
FTimerHandle GloveConnectivityCheckTimer;
/************************
* Owner object
************************/
USGGloveTracker* Owner;
/************************
* Constructor / Destructor
************************/
explicit FImpl(USGGloveTracker* InOwner);
~FImpl();
/************************
* Default copy constructor & copy assignment operator
************************/
FImpl(const FImpl& Rhs) = default;
FImpl& operator=(const FImpl& Rhs) = default;
/************************
* Methods
************************/
void UpdateGloves() const;
};
UWorld* USGGloveTracker::FImpl::GetWorld()
{
UWorld* World{nullptr};
#if WITH_EDITOR
if (GIsEditor)
{
if (IsValid(GEditor))
{
const bool bIsPIE = GPlayInEditorID != -1;
if (!bIsPIE)
{
const FWorldContext* WorldContext{GEditor->GetPIEWorldContext(1)};
if (WorldContext)
{
World = WorldContext->World();
}
}
else
{
const FWorldContext* WorldContext{GEditor->GetPIEWorldContext(GPlayInEditorID)};
if (WorldContext)
{
World = WorldContext->World();
}
}
if (!IsValid(World))
{
UUnrealEditorSubsystem* UnrealEditorSubsystem{GEditor->GetEditorSubsystem<UUnrealEditorSubsystem>()};
if (IsValid(UnrealEditorSubsystem))
{
World = UnrealEditorSubsystem->GetEditorWorld();
}
}
}
if (!IsValid(World) && IsValid(GEngine))
{
const UGameViewportClient* Viewport{GEngine->GameViewport};
if (IsValid(Viewport))
{
World = Viewport->GetWorld();
}
}
}
else
{
if (IsValid(GEngine))
{
World = GEngine->GetCurrentPlayWorld(nullptr);
}
}
#else /* WITH_EDITOR */
if (IsValid(GEngine))
{
World = GEngine->GetCurrentPlayWorld(nullptr);
}
#endif /* WITH_EDITOR */
if (!IsValid(World) && IsValid(GEngine))
{
UEngineSubsystem* EngineSubsystem{GEngine->GetEngineSubsystem<UEngineSubsystem>()};
if (IsValid(EngineSubsystem))
{
World = EngineSubsystem->GetWorld();
}
}
return World;
}
USGGloveTracker* USGGloveTracker::GetInstance()
{
UWorld* World{FImpl::GetWorld()};
USGGloveTracker* Instance{IsValid(World) ? World->GetSubsystem<USGGloveTracker>() : nullptr};
return Instance;
}
USGGloveTracker::USGGloveTracker()
: Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter)),
LeftGlove(nullptr),
RightGlove(nullptr)
{
}
bool USGGloveTracker::ShouldCreateSubsystem(UObject* Outer) const
{
return true;
}
void USGGloveTracker::Initialize(FSubsystemCollectionBase& Collection)
{
SGLOG("Initializing the SenseGlove tracking singleton with the world lifetime...");
Super::Initialize(Collection);
const UWorld* World{GetWorld()};
if (ensureAlwaysMsgf(World, TEXT("Invalid world!")))
{
SGLOG("Starting the glove connectivity check timer...");
const float GloveConnectivityCheckInterval = FImpl::GetGloveConnectivityCheckInterval();
FTimerDelegate GloveConnectivityCheckHandler;
GloveConnectivityCheckHandler.BindLambda([= SG_CAPTURE_THIS]()-> void
{
Pimpl->UpdateGloves();
});
FTimerManager& TimerManager = World->GetTimerManager();
TimerManager.SetTimer(
Pimpl->GloveConnectivityCheckTimer, GloveConnectivityCheckHandler, GloveConnectivityCheckInterval,
true, -1.0f);
SGLOG("The glove connectivity check timer has been started successfully!");
}
SGLOG("The SenseGlove tracking singleton has been successfully initialized with the world lifetime!");
}
void USGGloveTracker::Deinitialize()
{
SGLOG("De-initializing the SenseGlove tracking singleton due to the world lifetime expiration...");
Super::Deinitialize();
const UWorld* World{GetWorld()};
if (ensureAlwaysMsgf(World, TEXT("Invalid world!")))
{
SGLOG("Stopping the glove connectivity check timer...");
FTimerManager& TimerManager = World->GetTimerManager();
TimerManager.ClearTimer(Pimpl->GloveConnectivityCheckTimer);
SGLOG("The glove connectivity check timer has been stopped successfully!");
}
(void) Pimpl.Release();
SGLOG("The SenseGlove tracking singleton has been successfully de-initialized!");
}
USGGloveTracker::FImpl::FImpl(USGGloveTracker* InOwner)
: Owner(InOwner)
{
}
USGGloveTracker::FImpl::~FImpl() = default;
void USGGloveTracker::FImpl::UpdateGloves() const
{
if (!USGBackend::GetInstance()->IsBackendInitialized())
{
const bool bSucceeded = USGBackend::GetInstance()->InitializeBackend();
if (!bSucceeded)
{
return;
}
}
const bool bIsLeftGloveConnected = USGHapticGlove::GetGlove(Owner, false, Owner->LeftGlove);
if (!bIsLeftGloveConnected)
{
Owner->LeftGlove = nullptr;
}
const bool bIsRightGloveConnected = USGHapticGlove::GetGlove(Owner, true, Owner->RightGlove);
if (!bIsRightGloveConnected)
{
Owner->RightGlove = nullptr;
}
}
void USGGloveTracker::FImplDeleter::operator()(const FImpl* P) const
{
delete P;
}
@@ -33,13 +33,15 @@
*/ */
#include "SenseGlove/SGHeadMountedDisplay.h" #include "SGTracking/SGHMDTracker.h"
#include "Engine/Engine.h" #include "Engine/Engine.h"
#include "IHeadMountedDisplay.h" #include "IHeadMountedDisplay.h"
#include "IXRTrackingSystem.h" #include "IXRTrackingSystem.h"
FName FSGHeadMountedDisplay::GetDeviceName() #include "SGSettings/SGSettings.h"
FName FSGHMDTracker::GetDeviceName()
{ {
if (GEngine && GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed()) if (GEngine && GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed())
{ {
@@ -53,7 +55,7 @@ FName FSGHeadMountedDisplay::GetDeviceName()
return NAME_None; return NAME_None;
} }
bool FSGHeadMountedDisplay::IsMetaQuest2() bool FSGHMDTracker::IsMetaQuest2()
{ {
static const FName MetaQuest2DeviceIdentifier{TEXT("Meta Quest 2")}; static const FName MetaQuest2DeviceIdentifier{TEXT("Meta Quest 2")};
static const FName OculusQuest2DeviceIdentifier{TEXT("Oculus Quest2")}; static const FName OculusQuest2DeviceIdentifier{TEXT("Oculus Quest2")};
@@ -72,7 +74,7 @@ bool FSGHeadMountedDisplay::IsMetaQuest2()
return bMatched; return bMatched;
} }
bool FSGHeadMountedDisplay::IsMetaQuestPro() bool FSGHMDTracker::IsMetaQuestPro()
{ {
static const FName MetaQuestProDeviceIdentifier{TEXT("Meta Quest Pro")}; static const FName MetaQuestProDeviceIdentifier{TEXT("Meta Quest Pro")};
static const FName OculusQuestProDeviceIdentifier{TEXT("Oculus QuestPro")}; static const FName OculusQuestProDeviceIdentifier{TEXT("Oculus QuestPro")};
@@ -91,7 +93,7 @@ bool FSGHeadMountedDisplay::IsMetaQuestPro()
return bMatched; return bMatched;
} }
bool FSGHeadMountedDisplay::IsMetaQuest3() bool FSGHMDTracker::IsMetaQuest3()
{ {
static const FName MetaQuest3DeviceIdentifier{TEXT("Meta Quest 3")}; static const FName MetaQuest3DeviceIdentifier{TEXT("Meta Quest 3")};
static const FName OculusQuest3DeviceIdentifier{TEXT("Oculus Quest3")}; static const FName OculusQuest3DeviceIdentifier{TEXT("Oculus Quest3")};
@@ -110,7 +112,7 @@ bool FSGHeadMountedDisplay::IsMetaQuest3()
return bMatched; return bMatched;
} }
bool FSGHeadMountedDisplay::IsHtcVivePro() bool FSGHMDTracker::IsHtcVivePro()
{ {
#if PLATFORM_ANDROID #if PLATFORM_ANDROID
return false; return false;
@@ -165,7 +167,7 @@ bool FSGHeadMountedDisplay::IsHtcVivePro()
#endif /* PLATFORM_ANDROID */ #endif /* PLATFORM_ANDROID */
} }
bool FSGHeadMountedDisplay::IsHtcViveFocus3() bool FSGHMDTracker::IsHtcViveFocus3()
{ {
static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")}; static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")};
static const FString ViveDeviceIdentifier{TEXT("Vive")}; static const FString ViveDeviceIdentifier{TEXT("Vive")};
@@ -225,7 +227,7 @@ bool FSGHeadMountedDisplay::IsHtcViveFocus3()
return bMatched; return bMatched;
} }
bool FSGHeadMountedDisplay::IsHtcViveXRElite() bool FSGHMDTracker::IsHtcViveXRElite()
{ {
static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")}; static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")};
static const FString ViveDeviceIdentifier{TEXT("Vive")}; static const FString ViveDeviceIdentifier{TEXT("Vive")};
@@ -285,7 +287,7 @@ bool FSGHeadMountedDisplay::IsHtcViveXRElite()
return bMatched; return bMatched;
} }
ESGHeadMountedDisplayDevice FSGHeadMountedDisplay::GetDeviceType() ESGHeadMountedDisplayDevice FSGHMDTracker::GetDeviceType()
{ {
if (IsMetaQuest2()) if (IsMetaQuest2())
{ {
@@ -307,14 +309,32 @@ ESGHeadMountedDisplayDevice FSGHeadMountedDisplay::GetDeviceType()
return ESGHeadMountedDisplayDevice::HtcVivePro; return ESGHeadMountedDisplayDevice::HtcVivePro;
} }
if (IsHtcViveFocus3()) const USGSettings* Settings{USGSettings::GetInstance()};
ensureAlwaysMsgf(Settings, TEXT("The settings subsystem has not been initialized!"));
if (Settings->GetTrackingSettings().HMDTrackingSettings.ViveHMDDetectionPriority ==
ESGViveHMDDetectionPriority::HtcViveFocus3First)
{ {
return ESGHeadMountedDisplayDevice::HtcViveFocus3; if (IsHtcViveFocus3())
} {
return ESGHeadMountedDisplayDevice::HtcViveFocus3;
}
if (IsHtcViveXRElite()) if (IsHtcViveXRElite())
{
return ESGHeadMountedDisplayDevice::HtcViveXRElite;
}
}
else
{ {
return ESGHeadMountedDisplayDevice::HtcViveXRElite; if (IsHtcViveXRElite())
{
return ESGHeadMountedDisplayDevice::HtcViveXRElite;
}
if (IsHtcViveFocus3())
{
return ESGHeadMountedDisplayDevice::HtcViveFocus3;
}
} }
return ESGHeadMountedDisplayDevice::None; return ESGHeadMountedDisplayDevice::None;
@@ -0,0 +1,70 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SGTracking/SGXRHandState.h"
FSGXRHandState::FSGXRHandState()
: HandTracker{},
JointLocations{},
JointVelocities{},
Velocities{XR_TYPE_HAND_JOINT_VELOCITIES_EXT},
Locations{XR_TYPE_HAND_JOINT_LOCATIONS_EXT},
KeypointTransforms{},
Radii{},
bReceivedJointPoses(false)
{
Velocities.jointCount = XR_HAND_JOINT_COUNT_EXT;
Velocities.jointVelocities = JointVelocities;
Locations.next = &Velocities;
Locations.jointCount = XR_HAND_JOINT_COUNT_EXT;
Locations.jointLocations = JointLocations;
}
FSGXRHandState::~FSGXRHandState() = default;
bool FSGXRHandState::GetTransform(const EHandKeypoint Keypoint, FTransform& OutTransform) const
{
check(static_cast<int32>(Keypoint) < EHandKeypointCount);
OutTransform = KeypointTransforms[static_cast<uint32>(Keypoint)];
return !!bReceivedJointPoses;
}
const FTransform& FSGXRHandState::GetTransform(const EHandKeypoint Keypoint) const
{
check(static_cast<int32>(Keypoint) < EHandKeypointCount);
return KeypointTransforms[static_cast<uint32>(Keypoint)];
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,42 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SenseGloveTracking.h"
#include "Modules/ModuleManager.h"
#include "SenseGloveTrackingModule.h"
IMPLEMENT_MODULE(FSenseGloveTrackingModule, SenseGloveTracking)
@@ -0,0 +1,38 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "CoreMinimal.h"
@@ -0,0 +1,181 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SenseGloveTrackingModule.h"
#include "SGLog/SGLog.h"
#include "SGTracking/SGXRTracker.h"
#define LOCTEXT_NAMESPACE "FSenseGloveTrackingModule"
struct FSenseGloveTrackingModule::FImpl
{
/************************
* Member variables
************************/
TSharedPtr<FSGXRTracker> InputDevice;
/************************
* Owner object
************************/
FSenseGloveTrackingModule* Owner;
/************************
* Constructor / Destructor
************************/
explicit FImpl(FSenseGloveTrackingModule* InOwner);
~FImpl();
/************************
* Default copy constructor & copy assignment operator
************************/
FImpl(const FImpl& Rhs) = default;
FImpl& operator=(const FImpl& Rhs) = default;
};
FSenseGloveTrackingModule::FSenseGloveTrackingModule()
: IInputDeviceModule(),
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
{
}
FSenseGloveTrackingModule::FSenseGloveTrackingModule(const FSenseGloveTrackingModule& Rhs)
: IInputDeviceModule(Rhs),
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{*Rhs.Pimpl}, PimplDeleter))
{
Pimpl->Owner = this;
}
FSenseGloveTrackingModule::FSenseGloveTrackingModule(FSenseGloveTrackingModule&& Rhs) SG_NOEXCEPT = default;
FSenseGloveTrackingModule::~FSenseGloveTrackingModule() = default;
FSenseGloveTrackingModule& FSenseGloveTrackingModule::operator=(const FSenseGloveTrackingModule& Rhs)
{
IInputDeviceModule::operator=(Rhs);
*Pimpl = *Rhs.Pimpl;
Pimpl->Owner = this;
return *this;
}
FSenseGloveTrackingModule& FSenseGloveTrackingModule::operator=(FSenseGloveTrackingModule&& Rhs) SG_NOEXCEPT = default;
void FSenseGloveTrackingModule::StartupModule()
{
SGLOG("Starting up SenseGloveTracking module...");
IInputDeviceModule::StartupModule();
/// HACK!
// Generic Application might not be instantiated at this point so we create the input device with a dummy message
// handler. When the Generic Application creates the input device it passes a valid message handler to it which is
// further on used for all the controller events. This hack fixes issues caused by using a custom input device
// before the Generic Application has instantiated it. Eg. within BeginPlay().
// This also fixes the warnings that pop up on the custom input keys when the blueprint loads. Those warnings are
// caused because Unreal loads the Blueprints before the input device has been instantiated and has added its keys,
// thus leading Unreal to believe that those keys don't exist. This hack causes an earlier instantiation of the
// input device, and consequently, the custom keys.
TSharedPtr<FGenericApplicationMessageHandler> DummyMessageHandler(new FGenericApplicationMessageHandler());
CreateInputDevice(DummyMessageHandler.ToSharedRef());
}
void FSenseGloveTrackingModule::PreUnloadCallback()
{
SGLOG("Unloading SenseGloveTracking module...");
IInputDeviceModule::PreUnloadCallback();
}
void FSenseGloveTrackingModule::PostLoadCallback()
{
SGLOG("Loading of SenseGloveTracking module has succeeded!");
IInputDeviceModule::PostLoadCallback();
}
void FSenseGloveTrackingModule::ShutdownModule()
{
SGLOG("Shutting down SenseGloveTracking module...");
IInputDeviceModule::ShutdownModule();
}
TSharedPtr<IInputDevice> FSenseGloveTrackingModule::CreateInputDevice(
const TSharedRef<FGenericApplicationMessageHandler>& InMessageHandler)
{
SGLOG("Creating the SenseGloveTracking input device...");
if (!Pimpl->InputDevice.IsValid())
{
TSharedPtr<FSGXRTracker> HandTrackingInputDevice(new FSGXRTracker(InMessageHandler));
Pimpl->InputDevice = HandTrackingInputDevice;
}
else
{
Pimpl->InputDevice.Get()->SetMessageHandler(InMessageHandler);
}
return Pimpl->InputDevice;
}
TSharedPtr<IInputDevice> FSenseGloveTrackingModule::GetInputDevice()
{
if (!Pimpl->InputDevice.IsValid())
{
CreateInputDevice(FSlateApplication::Get().GetPlatformApplication()->GetMessageHandler());
}
return Pimpl->InputDevice;
}
FSenseGloveTrackingModule::FImpl::FImpl(FSenseGloveTrackingModule* InOwner)
: InputDevice(nullptr),
Owner(InOwner)
{
}
FSenseGloveTrackingModule::FImpl::~FImpl() = default;
void FSenseGloveTrackingModule::FImplDeleter::operator()(const FImpl* P) const
{
delete P;
}
#undef LOCTEXT_NAMESPACE
@@ -0,0 +1,116 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "IInputDeviceModule.h"
#include "Templates/UniquePtr.h"
#include "SGBuildHacks/SGPlatform.h"
#define LOCTEXT_NAMESPACE "SenseGloveTracking"
class FSenseGloveTrackingModule : public IInputDeviceModule
{
public:
static FORCEINLINE FSenseGloveTrackingModule& Get()
{
return FModuleManager::LoadModuleChecked<FSenseGloveTrackingModule>("SenseGloveTracking");
}
static FORCEINLINE bool IsAvailable()
{
return FModuleManager::Get().IsModuleLoaded("SenseGloveTracking");
}
private:
struct FImpl;
struct FImplDeleter
{
void operator()(const FImpl* P) const;
};
TUniquePtr<FImpl, FImplDeleter> Pimpl;
FImplDeleter PimplDeleter;
public:
/**
* The default constructor.
*/
FSenseGloveTrackingModule();
public:
/**
* The copy constructor.
*/
FSenseGloveTrackingModule(const FSenseGloveTrackingModule& Rhs);
/**
* The move constructor.
*/
FSenseGloveTrackingModule(FSenseGloveTrackingModule&& Rhs) SG_NOEXCEPT;
public:
/**
* The destructor.
*/
virtual ~FSenseGloveTrackingModule() override;
public:
/**
* The copy assignment operator.
*/
FSenseGloveTrackingModule& operator=(const FSenseGloveTrackingModule& Rhs);
/**
* The move assignment operator.
*/
FSenseGloveTrackingModule& operator=(FSenseGloveTrackingModule&& Rhs) SG_NOEXCEPT;
public:
virtual void StartupModule() override;
virtual void PreUnloadCallback() override;
virtual void PostLoadCallback() override;
virtual void ShutdownModule() override;
public:
virtual TSharedPtr<class IInputDevice> CreateInputDevice(
const TSharedRef<FGenericApplicationMessageHandler>& InMessageHandler) override;
virtual TSharedPtr<IInputDevice> GetInputDevice();
};
#undef LOCTEXT_NAMESPACE
@@ -0,0 +1,117 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "Subsystems/WorldSubsystem.h"
#include "Templates/UniquePtr.h"
#include "UObject/Object.h"
#include "UObject/ObjectMacros.h"
#include "SGCore/SGHapticGlove.h"
#include "SGGloveTracker.generated.h"
UCLASS()
class SENSEGLOVETRACKING_API USGGloveTracker : public UWorldSubsystem
{
GENERATED_BODY()
public:
static USGGloveTracker* GetInstance();
private:
struct FImpl;
struct FImplDeleter
{
void operator()(const FImpl* P) const;
};
TUniquePtr<FImpl, FImplDeleter> Pimpl;
FImplDeleter PimplDeleter;
private:
UPROPERTY(Transient)
USGHapticGlove* LeftGlove;
UPROPERTY(Transient)
USGHapticGlove* RightGlove;
private:
USGGloveTracker();
public:
FORCEINLINE USGHapticGlove* GetGlove(const bool bRight) const
{
return bRight ? RightGlove : LeftGlove;
}
FORCEINLINE USGHapticGlove* GetLeftGlove() const
{
return LeftGlove;
}
FORCEINLINE USGHapticGlove* GetRightGlove() const
{
return RightGlove;
}
FORCEINLINE bool IsGloveConnected(const bool bRight) const
{
return IsValid(GetGlove(bRight));
}
FORCEINLINE bool IsLeftGloveConnected() const
{
return IsValid(GetLeftGlove());
}
FORCEINLINE bool IsRightGloveConnected() const
{
return IsValid(GetRightGlove());
}
FORCEINLINE bool IsAnyGloveConnected() const
{
return IsLeftGloveConnected() || IsRightGloveConnected();
}
public:
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
};
@@ -39,15 +39,15 @@
#include "UObject/NameTypes.h" #include "UObject/NameTypes.h"
#include "UObject/ObjectMacros.h" #include "UObject/ObjectMacros.h"
#include "SGTypes/SGTypes.h" #include "SGTypes/SGTrackingTypes.h"
#include "SGHeadMountedDisplay.generated.h" #include "SGHMDTracker.generated.h"
/** /**
* *
*/ */
USTRUCT() USTRUCT()
struct SENSEGLOVE_API FSGHeadMountedDisplay struct SENSEGLOVETRACKING_API FSGHMDTracker
{ {
GENERATED_BODY() GENERATED_BODY()
@@ -0,0 +1,68 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "HeadMountedDisplayTypes.h"
#include "IOpenXRExtensionPlugin.h"
#include "Math/MathFwd.h"
#include "Templates/UnrealTemplate.h"
struct SENSEGLOVETRACKING_API FSGXRHandState final : public FNoncopyable
{
public:
XrHandTrackerEXT HandTracker;
XrHandJointLocationEXT JointLocations[XR_HAND_JOINT_COUNT_EXT];
XrHandJointVelocityEXT JointVelocities[XR_HAND_JOINT_COUNT_EXT];
XrHandJointVelocitiesEXT Velocities;
XrHandJointLocationsEXT Locations;
// Transforms are cached in Unreal Tracking Space
FTransform KeypointTransforms[EHandKeypointCount];
float Radii[EHandKeypointCount];
uint8_t bReceivedJointPoses : 1;
public:
FSGXRHandState();
virtual ~FSGXRHandState();
public:
bool GetTransform(EHandKeypoint Keypoint, FTransform& OutTransform) const;
const FTransform& GetTransform(EHandKeypoint Keypoint) const;
};
@@ -0,0 +1,165 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "HeadMountedDisplayTypes.h"
#include "IHandTracker.h"
#include "IInputDevice.h"
#include "IOpenXRExtensionPlugin.h"
#include "Math/MathFwd.h"
#include "Runtime/Launch/Resources/Version.h"
#include "Templates/UniquePtr.h"
#include "UObject/NameTypes.h"
#include "XRMotionControllerBase.h"
#include "SGBuildHacks/SGPlatform.h"
struct SENSEGLOVETRACKING_API FSGXRHandState;
class SENSEGLOVETRACKING_API FSGXRTracker final : public IOpenXRExtensionPlugin,
public IInputDevice,
public FXRMotionControllerBase,
public IHandTracker
{
/**
* Parses the enum name removing the prefix.
*/
static FName ParseEOpenXRHandKeypointEnumName(const FName& EnumName);
private:
struct FImpl;
struct FImplDeleter
{
void operator()(const FImpl* P) const;
};
TUniquePtr<FImpl, FImplDeleter> Pimpl;
FImplDeleter PimplDeleter;
private:
FSGXRTracker() = delete;
public:
FSGXRTracker(const TSharedRef<FGenericApplicationMessageHandler>& InMessageHandler);
public:
/**
* The copy constructor.
*/
FSGXRTracker(const FSGXRTracker& Rhs) = delete;
/**
* The move constructor.
*/
FSGXRTracker(FSGXRTracker&& Rhs) SG_NOEXCEPT;
public:
/**
* The destructor.
*/
virtual ~FSGXRTracker() override;
public:
/**
* The copy assignment operator.
*/
FSGXRTracker& operator=(const FSGXRTracker& Rhs) = delete;
/**
* The move assignment operator.
*/
FSGXRTracker& operator=(FSGXRTracker&& Rhs) SG_NOEXCEPT;
public:
bool IsHandTrackingSupportedByDevice() const;
const FSGXRHandState& GetLeftHandState() const;
const FSGXRHandState& GetRightHandState() const;
public:
// The IOpenXRExtensionPlugin interface.
virtual FString GetDisplayName() override;
virtual bool GetRequiredExtensions(TArray<const ANSICHAR*>& OutExtensions) override;
virtual const void* OnGetSystem(XrInstance InInstance, const void* InNext) override;
virtual const void* OnCreateSession(XrInstance InInstance, XrSystemId InSystem, const void* InNext) override;
virtual const void* OnBeginSession(XrSession InSession, const void* InNext) override;
virtual void UpdateDeviceLocations(XrSession InSession, XrTime DisplayTime, XrSpace TrackingSpace) override;
public:
// The IMotionController interface.
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
virtual bool GetControllerOrientationAndPosition(const int32 ControllerIndex, const FName MotionSource,
FRotator& OutOrientation, FVector& OutPosition,
float WorldToMetersScale) const override;
virtual ETrackingStatus GetControllerTrackingStatus(const int32 ControllerIndex,
const FName MotionSource) const override;
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
virtual bool GetControllerOrientationAndPosition(const int32 ControllerIndex, const EControllerHand DeviceHand,
FRotator& OutOrientation, FVector& OutPosition,
float WorldToMetersScale) const override;
virtual ETrackingStatus GetControllerTrackingStatus(const int32 ControllerIndex,
const EControllerHand DeviceHand) const override;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
virtual FName GetMotionControllerDeviceTypeName() const override;
virtual void EnumerateSources(TArray<FMotionControllerSource>& SourcesOut) const override;
public:
// The IInputDevice interface.
virtual void Tick(float DeltaTime) override;
virtual void SendControllerEvents() override;
virtual void SetMessageHandler(const TSharedRef<FGenericApplicationMessageHandler>& InMessageHandler) override;
virtual bool Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) override;
virtual void SetChannelValue(int32 ControllerId, FForceFeedbackChannelType ChannelType, float Value) override;
virtual void SetChannelValues(int32 ControllerId, const FForceFeedbackValues& Values) override;
virtual bool SupportsForceFeedback(int32 ControllerId) override;
virtual bool IsGamepadAttached() const override;
public:
// The IHandTracker interface.
virtual FName GetHandTrackerDeviceTypeName() const override;
virtual bool IsHandTrackingStateValid() const override;
virtual bool GetKeypointState(
EControllerHand Hand,
EHandKeypoint Keypoint, FTransform& OutTransform, float& OutRadius) const override;
virtual bool GetAllKeypointStates(
EControllerHand Hand,
TArray<FVector>& OutPositions, TArray<FQuat>& OutRotations, TArray<float>& OutRadii) const override;
};
@@ -0,0 +1,93 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using UnrealBuildTool;
public class SenseGloveTracking : ModuleRules
{
public SenseGloveTracking(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PrivateDependencyModuleNames.AddRange(
new string[]
{
"ApplicationCore",
"Core",
"CoreUObject",
"Engine",
"HeadMountedDisplay",
"InputCore",
"InputDevice",
"OpenXRHMD",
"OpenXRInput",
// NOTE
// Only UE 5.3+ provides the XRBase plugin.
#if UE_5_3_OR_LATER
"XRBase",
#else
"OpenXR",
#endif
"Slate",
"SlateCore",
"SenseGloveBackend",
"SenseGloveCore",
"SenseGloveLog",
"SenseGloveSettings",
"SenseGloveTypes",
}
);
if (Target.bBuildEditor)
{
PrivateDependencyModuleNames.AddRange(
new string[]
{
"UnrealEd",
}
);
}
PrivateIncludePathModuleNames.AddRange(
new string[]
{
"SenseGloveBuildHacks",
}
);
AddEngineThirdPartyPrivateStaticDependencies(Target, "OpenXR");
}
}
@@ -0,0 +1,79 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SGTrackingKismet/SGGloveTrackerKismetLibrary.h"
#include "SGCore/SGHapticGlove.h"
#include "SGTracking/SGGloveTracker.h"
USGGloveTracker* USGGloveTrackerKismetLibrary::GetInstance()
{
return USGGloveTracker::GetInstance();
}
USGHapticGlove* USGGloveTrackerKismetLibrary::GetGlove(const USGGloveTracker* GloveTracker, const bool bRight)
{
return GloveTracker->GetGlove(bRight);
}
USGHapticGlove* USGGloveTrackerKismetLibrary::GetLeftGlove(const USGGloveTracker* GloveTracker)
{
return GloveTracker->GetLeftGlove();
}
USGHapticGlove* USGGloveTrackerKismetLibrary::GetRightGlove(const USGGloveTracker* GloveTracker)
{
return GloveTracker->GetRightGlove();
}
bool USGGloveTrackerKismetLibrary::IsGloveConnected(const USGGloveTracker* GloveTracker, const bool bRight)
{
return GloveTracker->IsGloveConnected(bRight);
}
bool USGGloveTrackerKismetLibrary::IsLeftGloveConnected(const USGGloveTracker* GloveTracker)
{
return GloveTracker->IsLeftGloveConnected();
}
bool USGGloveTrackerKismetLibrary::IsRightGloveConnected(const USGGloveTracker* GloveTracker)
{
return GloveTracker->IsRightGloveConnected();
}
bool USGGloveTrackerKismetLibrary::IsAnyGloveConnected(const USGGloveTracker* GloveTracker)
{
return GloveTracker->IsAnyGloveConnected();
}
@@ -0,0 +1,78 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SGTrackingKismet/SGHMDTrackerKismetLibrary.h"
#include "SGTracking/SGHMDTracker.h"
FName USGHMDTrackerKismetLibrary::GetDeviceName()
{
return FSGHMDTracker::GetDeviceName();
}
bool USGHMDTrackerKismetLibrary::IsMetaQuest2()
{
return FSGHMDTracker::IsMetaQuest2();
}
bool USGHMDTrackerKismetLibrary::IsMetaQuestPro()
{
return FSGHMDTracker::IsMetaQuestPro();
}
bool USGHMDTrackerKismetLibrary::IsMetaQuest3()
{
return FSGHMDTracker::IsMetaQuest3();
}
bool USGHMDTrackerKismetLibrary::IsHtcVivePro()
{
return FSGHMDTracker::IsHtcVivePro();
}
bool USGHMDTrackerKismetLibrary::IsHtcViveFocus3()
{
return FSGHMDTracker::IsHtcViveFocus3();
}
bool USGHMDTrackerKismetLibrary::IsHtcViveXRElite()
{
return FSGHMDTracker::IsHtcViveXRElite();
}
ESGHeadMountedDisplayDevice USGHMDTrackerKismetLibrary::GetDeviceType()
{
return FSGHMDTracker::GetDeviceType();
}
@@ -0,0 +1,40 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SenseGloveTrackingKismet.h"
#include "Modules/ModuleManager.h"
#include "SenseGloveTrackingKismetModule.h"
IMPLEMENT_MODULE(FSenseGloveTrackingKismetModule, SenseGloveTrackingKismet)
@@ -0,0 +1,38 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "CoreMinimal.h"
@@ -0,0 +1,62 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#include "SenseGloveTrackingKismetModule.h"
#include "SGLog/SGLog.h"
#define LOCTEXT_NAMESPACE "FSenseGloveTrackingKismetModule"
void FSenseGloveTrackingKismetModule::StartupModule()
{
SGLOG("Starting up the SenseGloveTrackingKismet module...");
}
void FSenseGloveTrackingKismetModule::PreUnloadCallback()
{
SGLOG("Unloading the SenseGloveTrackingKismet module...");
}
void FSenseGloveTrackingKismetModule::PostLoadCallback()
{
SGLOG("Loading of SenseGloveTrackingKismet module has succeeded!");
}
void FSenseGloveTrackingKismetModule::ShutdownModule()
{
SGLOG("Shutting down the SenseGloveTrackingKismet module...");
}
#undef LOCTEXT_NAMESPACE
@@ -0,0 +1,51 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "Modules/ModuleInterface.h"
#define LOCTEXT_NAMESPACE "SenseGloveTrackingKismet"
class FSenseGloveTrackingKismetModule : public IModuleInterface
{
public:
virtual void StartupModule() override;
virtual void PreUnloadCallback() override;
virtual void PostLoadCallback() override;
virtual void ShutdownModule() override;
};
#undef LOCTEXT_NAMESPACE
@@ -0,0 +1,75 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
#pragma once
#include "SGKismet/SGBlueprintFunctionLibrary.h"
#include "SGGloveTrackerKismetLibrary.generated.h"
class USGGloveTracker;
class USGHapticGlove;
UCLASS(meta=(ScriptName = "SesneGloveTrackerKismetLibrary"))
class SENSEGLOVETRACKINGKISMET_API USGGloveTrackerKismetLibrary final : public USGBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | Glove Tracker",
meta=(WorldContext="WorldContextObject"))
static USGGloveTracker* GetInstance();
UFUNCTION(BlueprintPure, Category="SenseGlove | Tracking | Glove Tracker")
static USGHapticGlove* GetGlove(const USGGloveTracker* GloveTracker, const bool bRight);
UFUNCTION(BlueprintPure, Category="SenseGlove | Tracking | Glove Tracker")
static USGHapticGlove* GetLeftGlove(const USGGloveTracker* GloveTracker);
UFUNCTION(BlueprintPure, Category="SenseGlove | Tracking | Glove Tracker")
static USGHapticGlove* GetRightGlove(const USGGloveTracker* GloveTracker);
UFUNCTION(BlueprintPure, Category="SenseGlove | Tracking | Glove Tracker")
static bool IsGloveConnected(const USGGloveTracker* GloveTracker, const bool bRight);
UFUNCTION(BlueprintPure, Category="SenseGlove | Tracking | Glove Tracker")
static bool IsLeftGloveConnected(const USGGloveTracker* GloveTracker);
UFUNCTION(BlueprintPure, Category="SenseGlove | Tracking | Glove Tracker")
static bool IsRightGloveConnected(const USGGloveTracker* GloveTracker);
UFUNCTION(BlueprintPure, Category="SenseGlove | Tracking | Glove Tracker")
static bool IsAnyGloveConnected(const USGGloveTracker* GloveTracker);
};
@@ -1,4 +1,4 @@
/** /**
* @file * @file
* *
* @author Mamadou Babaei <mamadou@senseglove.com> * @author Mamadou Babaei <mamadou@senseglove.com>
@@ -38,41 +38,41 @@
#include "UObject/NameTypes.h" #include "UObject/NameTypes.h"
#include "SGKismet/SGBlueprintFunctionLibrary.h" #include "SGKismet/SGBlueprintFunctionLibrary.h"
#include "SGTypes/SGTypes.h" #include "SGTypes/SGTrackingTypes.h"
#include "SGHeadMountedDisplayKismetLibrary.generated.h" #include "SGHMDTrackerKismetLibrary.generated.h"
UCLASS(meta=(ScriptName = "SesneGloveHeadMountedDisplayKismetLibrary")) UCLASS(meta=(ScriptName = "SesneGloveHeadMountDisplayKismetLibrary"))
class SENSEGLOVEKISMET_API UHeadMountedDisplayKismetLibrary final : public USGBlueprintFunctionLibrary class SENSEGLOVETRACKINGKISMET_API USGHMDTrackerKismetLibrary final : public USGBlueprintFunctionLibrary
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
UFUNCTION(BlueprintCallable, Category="SenseGlove | Head-mounted Display") UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | HMD Tracker")
static FName GetDeviceName(); static FName GetDeviceName();
/** /**
* Checks whether the HMD device is Meta Quest 2, or not. * Checks whether the HMD device is Meta Quest 2, or not.
*/ */
UFUNCTION(BlueprintCallable, Category="SenseGlove | Head-mounted Display") UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | HMD Tracker")
static bool IsMetaQuest2(); static bool IsMetaQuest2();
/** /**
* Checks whether the HMD device is Meta Quest Pro, or not. * Checks whether the HMD device is Meta Quest Pro, or not.
*/ */
UFUNCTION(BlueprintCallable, Category="SenseGlove | Head-mounted Display") UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | HMD Tracker")
static bool IsMetaQuestPro(); static bool IsMetaQuestPro();
/** /**
* Checks whether the HMD device is Meta Quest 3, or not. * Checks whether the HMD device is Meta Quest 3, or not.
*/ */
UFUNCTION(BlueprintCallable, Category="SenseGlove | Head-mounted Display") UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | HMD Tracker")
static bool IsMetaQuest3(); static bool IsMetaQuest3();
/** /**
* Checks whether the HMD device is HTC VIVE Pro, or not. * Checks whether the HMD device is HTC VIVE Pro, or not.
*/ */
UFUNCTION(BlueprintCallable, Category="SenseGlove | Head-mounted Display") UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | HMD Tracker")
static bool IsHtcVivePro(); static bool IsHtcVivePro();
/** /**
@@ -81,7 +81,7 @@ public:
* @remark At the moment, VIVE Focus 3 cannot be distinguished from VIVE XR Elite, so when IsHtcViveFocus3 returns * @remark At the moment, VIVE Focus 3 cannot be distinguished from VIVE XR Elite, so when IsHtcViveFocus3 returns
* true, IsHtcViveXRElite will return true as well; thus we cannot know for sure which headset we are running on. * true, IsHtcViveXRElite will return true as well; thus we cannot know for sure which headset we are running on.
*/ */
UFUNCTION(BlueprintCallable, Category="SenseGlove | Head-mounted Display") UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | HMD Tracker")
static bool IsHtcViveFocus3(); static bool IsHtcViveFocus3();
/** /**
@@ -90,9 +90,9 @@ public:
* @remark At the moment, VIVE Focus 3 cannot be distinguished from VIVE XR Elite, so when IsHtcViveXRElite returns * @remark At the moment, VIVE Focus 3 cannot be distinguished from VIVE XR Elite, so when IsHtcViveXRElite returns
* true, IsHtcViveFocus3 will return true as well; thus we cannot know for sure which headset we are running on. * true, IsHtcViveFocus3 will return true as well; thus we cannot know for sure which headset we are running on.
*/ */
UFUNCTION(BlueprintCallable, Category = "SenseGlove | Head-mounted Display") UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | HMD Tracker")
static bool IsHtcViveXRElite(); static bool IsHtcViveXRElite();
UFUNCTION(BlueprintCallable, Category="SenseGlove | Head-mounted Display") UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | HMD Tracker")
static ESGHeadMountedDisplayDevice GetDeviceType(); static ESGHeadMountedDisplayDevice GetDeviceType();
}; };
@@ -0,0 +1,59 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2024 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using UnrealBuildTool;
public class SenseGloveTrackingKismet : ModuleRules
{
public SenseGloveTrackingKismet(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PrivateDependencyModuleNames.AddRange(
new string[]
{
"Core",
"CoreUObject",
"Engine",
"SenseGloveCore",
"SenseGloveLog",
"SenseGloveKismet",
"SenseGloveTracking",
"SenseGloveTypes",
}
);
}
}
@@ -33,4 +33,4 @@
*/ */
#include "SGTypes/SGTypes.h" #include "SGTypes/SGTrackingTypes.h"
@@ -38,7 +38,9 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "UObject/ObjectMacros.h" #include "UObject/ObjectMacros.h"
/* The Head-mounted Display device enum to determine the HMD device type. */ /**
* The Head-mounted Display device enum to determine the HMD device type.
*/
UENUM(BlueprintType) UENUM(BlueprintType)
enum class ESGHeadMountedDisplayDevice : uint8 enum class ESGHeadMountedDisplayDevice : uint8
{ {
@@ -62,4 +64,17 @@ enum class ESGHeadMountedDisplayDevice : uint8
/* The HTC VIVE XR Elite HMD. */ /* The HTC VIVE XR Elite HMD. */
HtcViveXRElite UMETA(DisplayName = "HTC VIVE XR Elite"), HtcViveXRElite UMETA(DisplayName = "HTC VIVE XR Elite"),
}; };
/*
* The
*/
UENUM(BlueprintType)
enum class ESGViveHMDDetectionPriority : uint8
{
/* First try to detect HTC VIVE Focus 3. */
HtcViveFocus3First UMETA(DisplayName = "HTC VIVE Focus 3 First"),
/* First try to detect HTC VIVE XR Elite. */
HtcViveXREliteFirst UMETA(DisplayName = "HTC VIVE XR Elite First"),
};