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;
const FReferenceSkeleton& GetRefSkeleton() const;
bool InitializeBackend() const;
bool UninitializeBackend() const;
bool CheckGlove() const;
void SetVisibility(bool bVisible) const;
@@ -200,7 +202,7 @@ USGVirtualHandComponent::USGVirtualHandComponent(const FObjectInitializer& Objec
Super::SetAnimClass(USGVirtualHandAnimInstance::StaticClass());
bRight = true;
bHiddenInGameIfNoGloveDetected = true;
bHiddenInGameIfNoGloveDetected = false;
const FString SkeletalMeshPath{Pimpl->GetDefaultMeshPath()};
const ConstructorHelpers::FObjectFinder<USkeletalMesh> SkeletalMesh{*SkeletalMeshPath};
@@ -208,7 +210,7 @@ USGVirtualHandComponent::USGVirtualHandComponent(const FObjectInitializer& Objec
TEXT("Failed to load the skeletal mesh: '%s'"), *SkeletalMeshPath);
Super::SetSkeletalMesh(SkeletalMesh.Object, true);
bSGConnectInitialized = false;
bBackendInitialized = false;
Glove = nullptr;
}
@@ -259,7 +261,34 @@ void USGVirtualHandComponent::InitializeComponent()
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(
@@ -271,20 +300,13 @@ void USGVirtualHandComponent::TickComponent(
EditorTick(DeltaTime, TickType, ThisTickFunction);
return;
}
#endif
#endif /* WITH_EDITOR */
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
(void) Pimpl->CheckGlove();
}
void USGVirtualHandComponent::BeginPlay()
{
Super::BeginPlay();
(void) Pimpl->CheckGlove();
}
void USGVirtualHandComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, const bool bReinitPose)
{
if (IsValid(NewMesh))
@@ -404,7 +426,7 @@ USGVirtualHandComponent::FImpl::~FImpl() = default;
bool USGVirtualHandComponent::FImpl::IsEditor() const
{
const UWorld* World{Owner->GetWorld()};
if (World && World->WorldType == EWorldType::Editor)
if (World && (World->WorldType == EWorldType::Editor || World->WorldType == EWorldType::EditorPreview))
{
return true;
}
@@ -494,24 +516,103 @@ const FReferenceSkeleton& USGVirtualHandComponent::FImpl::GetRefSkeleton() const
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::Reinitialize();
// Load the latest hand profiles.
FSGHapticGloveHandProfiles::TryLoadingFromDisk();
const int32_t Result = FSGConnect::Init();
if (Result != 1)
Owner->bBackendInitialized = true;
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;
}
Owner->bSGConnectInitialized = true;
}
const bool bGloveWasPresent = IsValid(Owner->Glove);
@@ -523,9 +624,34 @@ bool USGVirtualHandComponent::FImpl::CheckGlove() const
(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;
@@ -534,7 +660,6 @@ bool USGVirtualHandComponent::FImpl::CheckGlove() const
void USGVirtualHandComponent::FImpl::SetVisibility(const bool bVisible) const
{
Owner->SetVisibility(bVisible, true);
Owner->SetHiddenInGame(!bVisible, false);
}
void USGVirtualHandComponent::FImplDeleter::operator()(const FImpl* P) const
@@ -95,6 +95,7 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
HandLeft->SetupAttachment(MotionControllerLeft);
HandLeft->SetCanEverAffectNavigation(false);
HandLeft->SetRight(false);
HandLeft->SetHiddenIfNoGloveDetected(true);
MotionControllerRight = ObjectInitializer.CreateDefaultSubobject<UMotionControllerComponent>(
this, TEXT("MotionControllerRight"));
@@ -107,6 +108,7 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
HandRight->SetupAttachment(MotionControllerRight);
HandRight->SetCanEverAffectNavigation(false);
HandRight->SetRight(true);
HandRight->SetHiddenIfNoGloveDetected(true);
}
ASGPawn::FImpl::FImpl(ASGPawn* InOwner)
@@ -87,7 +87,7 @@ private:
private:
UPROPERTY(Transient)
uint8 bSGConnectInitialized : 1;
uint8 bBackendInitialized : 1;
UPROPERTY(Transient)
USGHapticGlove* Glove;
@@ -124,12 +124,16 @@ public:
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,
enum ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
virtual void BeginPlay() override;
virtual void SetSkeletalMesh(USkeletalMesh* NewMesh, bool bReinitPose = true) override;
protected: