fix virtual hand crashes and editor visibility issues
This commit is contained in:
@@ -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,8 +261,35 @@ void USGVirtualHandComponent::InitializeComponent()
|
||||
Pimpl->SetDefaultMesh();
|
||||
}
|
||||
|
||||
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(
|
||||
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Owner->bSGConnectInitialized = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user