fix virtual hand crashes and editor visibility issues

This commit is contained in:
Mamadou Babaei
2023-03-28 10:34:47 +02:00
parent 9116e4a234
commit 708fce2f0c
3 changed files with 156 additions and 25 deletions
@@ -117,6 +117,8 @@ struct USGVirtualHandComponent::FImpl
USkeleton* GetSkeleton() const; USkeleton* GetSkeleton() const;
const FReferenceSkeleton& GetRefSkeleton() const; const FReferenceSkeleton& GetRefSkeleton() const;
bool InitializeBackend() const;
bool UninitializeBackend() const;
bool CheckGlove() const; bool CheckGlove() const;
void SetVisibility(bool bVisible) const; void SetVisibility(bool bVisible) const;
@@ -200,7 +202,7 @@ USGVirtualHandComponent::USGVirtualHandComponent(const FObjectInitializer& Objec
Super::SetAnimClass(USGVirtualHandAnimInstance::StaticClass()); Super::SetAnimClass(USGVirtualHandAnimInstance::StaticClass());
bRight = true; bRight = true;
bHiddenInGameIfNoGloveDetected = true; bHiddenInGameIfNoGloveDetected = false;
const FString SkeletalMeshPath{Pimpl->GetDefaultMeshPath()}; const FString SkeletalMeshPath{Pimpl->GetDefaultMeshPath()};
const ConstructorHelpers::FObjectFinder<USkeletalMesh> SkeletalMesh{*SkeletalMeshPath}; const ConstructorHelpers::FObjectFinder<USkeletalMesh> SkeletalMesh{*SkeletalMeshPath};
@@ -208,7 +210,7 @@ USGVirtualHandComponent::USGVirtualHandComponent(const FObjectInitializer& Objec
TEXT("Failed to load the skeletal mesh: '%s'"), *SkeletalMeshPath); TEXT("Failed to load the skeletal mesh: '%s'"), *SkeletalMeshPath);
Super::SetSkeletalMesh(SkeletalMesh.Object, true); Super::SetSkeletalMesh(SkeletalMesh.Object, true);
bSGConnectInitialized = false; bBackendInitialized = false;
Glove = nullptr; Glove = nullptr;
} }
@@ -259,7 +261,34 @@ void USGVirtualHandComponent::InitializeComponent()
Pimpl->SetDefaultMesh(); Pimpl->SetDefaultMesh();
} }
(void) Pimpl->CheckGlove(); if (Pimpl->InitializeBackend())
{
(void) Pimpl->CheckGlove();
}
}
void USGVirtualHandComponent::UninitializeComponent()
{
Super::UninitializeComponent();
(void) Pimpl->UninitializeBackend();
}
void USGVirtualHandComponent::BeginPlay()
{
Super::BeginPlay();
if (Pimpl->InitializeBackend())
{
(void) Pimpl->CheckGlove();
}
}
void USGVirtualHandComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
(void) Pimpl->UninitializeBackend();
} }
void USGVirtualHandComponent::TickComponent( void USGVirtualHandComponent::TickComponent(
@@ -271,20 +300,13 @@ void USGVirtualHandComponent::TickComponent(
EditorTick(DeltaTime, TickType, ThisTickFunction); EditorTick(DeltaTime, TickType, ThisTickFunction);
return; return;
} }
#endif #endif /* WITH_EDITOR */
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
(void) Pimpl->CheckGlove(); (void) Pimpl->CheckGlove();
} }
void USGVirtualHandComponent::BeginPlay()
{
Super::BeginPlay();
(void) Pimpl->CheckGlove();
}
void USGVirtualHandComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, const bool bReinitPose) void USGVirtualHandComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, const bool bReinitPose)
{ {
if (IsValid(NewMesh)) if (IsValid(NewMesh))
@@ -404,7 +426,7 @@ USGVirtualHandComponent::FImpl::~FImpl() = default;
bool USGVirtualHandComponent::FImpl::IsEditor() const bool USGVirtualHandComponent::FImpl::IsEditor() const
{ {
const UWorld* World{Owner->GetWorld()}; const UWorld* World{Owner->GetWorld()};
if (World && World->WorldType == EWorldType::Editor) if (World && (World->WorldType == EWorldType::Editor || World->WorldType == EWorldType::EditorPreview))
{ {
return true; return true;
} }
@@ -494,24 +516,103 @@ const FReferenceSkeleton& USGVirtualHandComponent::FImpl::GetRefSkeleton() const
return SkeletalMesh->GetRefSkeleton(); return SkeletalMesh->GetRefSkeleton();
} }
bool USGVirtualHandComponent::FImpl::CheckGlove() const bool USGVirtualHandComponent::FImpl::InitializeBackend() const
{ {
if (!Owner->bSGConnectInitialized) if (!Owner->bBackendInitialized)
{ {
// Ensure the device list is empty before doing anything. #if PLATFORM_ANDROID
const int32_t Result = FSGConnect::Init();
switch (Result)
{
case -3:
SGLOG_ERROR("An Unexpected error occurred. Please try again.");
return false;
case -2:
SGLOG_ERROR("Device Scanning is already running within a different program.");
return false;
case -1:
SGLOG_ERROR("Device Scanning already being initialized (function called twice in short succession).");
return false;
case 0:
SGLOG_ERROR("Device Scanning is already running within this program.");
return false;
case 1:
SGLOG_ERROR("Successfully started up DeviceScanning from the current program.");
break;;
default:
ensureAlwaysMsgf(false, TEXT("Unhandled Init return status code!"));
return false;
}
#endif /* PLATFORM_ANDROID */
// Ensure that the device list is empty before doing anything.
FSGDeviceList::Dispose(); FSGDeviceList::Dispose();
FSGDeviceList::Reinitialize(); FSGDeviceList::Reinitialize();
// Load the latest hand profiles. // Load the latest hand profiles.
FSGHapticGloveHandProfiles::TryLoadingFromDisk(); FSGHapticGloveHandProfiles::TryLoadingFromDisk();
const int32_t Result = FSGConnect::Init(); Owner->bBackendInitialized = true;
if (Result != 1)
return true;
}
return false;
}
bool USGVirtualHandComponent::FImpl::UninitializeBackend() const
{
// NOTE
// In Editor builds we should be avoiding dispose, since stopping the game in PIE mode, causes the virtual-hand
// to disappear in the editor as the plugin won't be able to retrieve the glove status anymore.
#if ! WITH_EDITOR
if (Owner->bBackendInitialized)
{
FSGDeviceList::Dispose();
#if PLATFORM_ANDROID
const int32_t Result = FSGConnect::Dispose();
switch (Result)
{
case -3:
SGLOG_ERROR("An Unexpected error occurred. Please try again.");
return false;
case -2:
SGLOG_ERROR("Not allowed to dispose of Device Scanning because this is not the program which started it.");
return false;
case -1:
SGLOG_ERROR("Device Scanning is currently being disposed off. This takes a second or two. (function called twice in short succession).");
return false;
case 0:
SGLOG_ERROR("There is no deviceScanner running from any program, so disposing is skipped.");
return false;
case 1:
SGLOG_ERROR("Successfully disposed of DeviceScanner resources.");
break;;
default:
ensureAlwaysMsgf(false, TEXT("Unhandled Dispose return status code!"));
return false;
}
#endif /* PLATFORM_ANDROID */
Owner->bBackendInitialized = false;
return true;
}
#endif /* ! WITH_EDITOR */
return false;
}
bool USGVirtualHandComponent::FImpl::CheckGlove() const
{
if (!Owner->bBackendInitialized)
{
const bool bSucceeded = InitializeBackend();
if (!bSucceeded)
{ {
return false; return false;
} }
Owner->bSGConnectInitialized = true;
} }
const bool bGloveWasPresent = IsValid(Owner->Glove); const bool bGloveWasPresent = IsValid(Owner->Glove);
@@ -523,9 +624,34 @@ bool USGVirtualHandComponent::FImpl::CheckGlove() const
(Owner->bRight ? TEXT("right-handed") : TEXT("left-handed")))); (Owner->bRight ? TEXT("right-handed") : TEXT("left-handed"))));
} }
if (!IsEditor() && Owner->IsVisible() != bFoundGlove) const bool bIsEditor = IsEditor();
if (!bIsEditor)
{ {
SetVisibility(bFoundGlove); const bool bIsVisible = Owner->IsVisible();
if (Owner->bHiddenInGameIfNoGloveDetected)
{
if (bFoundGlove)
{
if (!bIsVisible)
{
SetVisibility(true);
}
}
else
{
if (bIsVisible)
{
SetVisibility(false);
}
}
}
else
{
if (!bIsVisible)
{
SetVisibility(true);
}
}
} }
return bFoundGlove; return bFoundGlove;
@@ -534,7 +660,6 @@ bool USGVirtualHandComponent::FImpl::CheckGlove() const
void USGVirtualHandComponent::FImpl::SetVisibility(const bool bVisible) const void USGVirtualHandComponent::FImpl::SetVisibility(const bool bVisible) const
{ {
Owner->SetVisibility(bVisible, true); Owner->SetVisibility(bVisible, true);
Owner->SetHiddenInGame(!bVisible, false);
} }
void USGVirtualHandComponent::FImplDeleter::operator()(const FImpl* P) const void USGVirtualHandComponent::FImplDeleter::operator()(const FImpl* P) const
@@ -95,6 +95,7 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
HandLeft->SetupAttachment(MotionControllerLeft); HandLeft->SetupAttachment(MotionControllerLeft);
HandLeft->SetCanEverAffectNavigation(false); HandLeft->SetCanEverAffectNavigation(false);
HandLeft->SetRight(false); HandLeft->SetRight(false);
HandLeft->SetHiddenIfNoGloveDetected(true);
MotionControllerRight = ObjectInitializer.CreateDefaultSubobject<UMotionControllerComponent>( MotionControllerRight = ObjectInitializer.CreateDefaultSubobject<UMotionControllerComponent>(
this, TEXT("MotionControllerRight")); this, TEXT("MotionControllerRight"));
@@ -107,6 +108,7 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
HandRight->SetupAttachment(MotionControllerRight); HandRight->SetupAttachment(MotionControllerRight);
HandRight->SetCanEverAffectNavigation(false); HandRight->SetCanEverAffectNavigation(false);
HandRight->SetRight(true); HandRight->SetRight(true);
HandRight->SetHiddenIfNoGloveDetected(true);
} }
ASGPawn::FImpl::FImpl(ASGPawn* InOwner) ASGPawn::FImpl::FImpl(ASGPawn* InOwner)
@@ -87,7 +87,7 @@ private:
private: private:
UPROPERTY(Transient) UPROPERTY(Transient)
uint8 bSGConnectInitialized : 1; uint8 bBackendInitialized : 1;
UPROPERTY(Transient) UPROPERTY(Transient)
USGHapticGlove* Glove; USGHapticGlove* Glove;
@@ -124,12 +124,16 @@ public:
virtual void InitializeComponent() override; virtual void InitializeComponent() override;
virtual void UninitializeComponent() override;
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void TickComponent(float DeltaTime, virtual void TickComponent(float DeltaTime,
enum ELevelTick TickType, enum ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override; FActorComponentTickFunction* ThisTickFunction) override;
virtual void BeginPlay() override;
virtual void SetSkeletalMesh(USkeletalMesh* NewMesh, bool bReinitPose = true) override; virtual void SetSkeletalMesh(USkeletalMesh* NewMesh, bool bReinitPose = true) override;
protected: protected: