Harden bounded OpenXR runtime ownership lane
This commit is contained in:
parent
3ed296b893
commit
d74b35bb06
13 changed files with 332 additions and 23 deletions
|
|
@ -95,6 +95,10 @@ DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.Defaul
|
|||
+AxisMappings=(AxisName="HyperTwistXr_MoveRight",Key=OculusTouch_Left_Thumbstick_X,Scale=1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_MoveRight",Key=ValveIndex_Left_Thumbstick_X,Scale=1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_MoveRight",Key=ValveIndex_Left_Trackpad_X,Scale=1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_VerticalAdjust",Key=PageUp,Scale=1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_VerticalAdjust",Key=PageDown,Scale=-1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_VerticalAdjust",Key=Gamepad_RightShoulder,Scale=1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_VerticalAdjust",Key=Gamepad_LeftShoulder,Scale=-1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_Turn",Key=Gamepad_RightX,Scale=1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_Turn",Key=Vive_Right_Trackpad_X,Scale=1.000000)
|
||||
+AxisMappings=(AxisName="HyperTwistXr_Turn",Key=MixedReality_Right_Thumbstick_X,Scale=1.000000)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
|||
bool bEnhancedInputProjectGroundworkPresent = false;
|
||||
bool bMotionControllerGroundworkPresent = false;
|
||||
bool bOpenXrProjectPluginEnabled = false;
|
||||
bool bXrVerticalAdjustmentAxisPresent = false;
|
||||
int32 MotionControllerFamilyCount = 0;
|
||||
TArray<FString> MotionControllerFamilies;
|
||||
};
|
||||
|
|
@ -434,6 +435,17 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
|||
AxisConfigEntries,
|
||||
GInputIni
|
||||
);
|
||||
TArray<FString> AxisMappingEntries;
|
||||
GConfig->GetArray(
|
||||
InputSettingsSection,
|
||||
TEXT("AxisMappings"),
|
||||
AxisMappingEntries,
|
||||
GInputIni
|
||||
);
|
||||
Facts.bXrVerticalAdjustmentAxisPresent = AxisConfigEntriesContainToken(
|
||||
AxisMappingEntries,
|
||||
TEXT("AxisName=\"HyperTwistXr_VerticalAdjust\"")
|
||||
);
|
||||
|
||||
const struct
|
||||
{
|
||||
|
|
@ -645,7 +657,7 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
|||
FString BuildXrPreferenceOwnerLine(const FXrRuntimeOwnershipFacts& Facts)
|
||||
{
|
||||
return FString::Printf(
|
||||
TEXT("XR preference ownership: %s | profile %s | posture %s | dominant hand %s | snap turn %.0f | world scale %.0f | preference fields %d."),
|
||||
TEXT("XR preference ownership: %s | profile %s | posture %s | dominant hand %s | snap turn %.0f | vertical adjust %.0f | pointer %.0f | world scale %.0f | preference fields %d."),
|
||||
*DescribeReadyState(Facts.bPreferenceProfileReady),
|
||||
*DescribeIdIfReady(
|
||||
Facts.bPreferenceProfileReady,
|
||||
|
|
@ -653,6 +665,8 @@ namespace HyperTwistTrainingPanelWidgetInternal
|
|||
*DescribeXrPostureMode(Facts.PreferenceProfile.PostureMode),
|
||||
*DescribeXrDominantHand(Facts.PreferenceProfile.DominantHand),
|
||||
Facts.PreferenceProfile.SnapTurnDegrees,
|
||||
Facts.PreferenceProfile.VerticalAdjustmentUnitsPerSecond,
|
||||
Facts.PreferenceProfile.PointerLengthUnits,
|
||||
Facts.PreferenceProfile.WorldToMetersScale,
|
||||
DescribeCountIfReady(
|
||||
Facts.bPreferenceProfileReady,
|
||||
|
|
@ -1419,6 +1433,8 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlInputReadinessInspectSurface(
|
|||
Surface.MotionControllerFamilyCount = InputGroundworkFacts.MotionControllerFamilyCount;
|
||||
Surface.bOpenXrProjectPluginEnabled =
|
||||
InputGroundworkFacts.bOpenXrProjectPluginEnabled;
|
||||
Surface.bXrVerticalAdjustmentAxisPresent =
|
||||
InputGroundworkFacts.bXrVerticalAdjustmentAxisPresent;
|
||||
|
||||
FHyperTwistTrainingImmersivePresenceControlContract PresenceControlContract;
|
||||
Surface.bImmersivePresenceContractReady =
|
||||
|
|
@ -1512,7 +1528,7 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlInputReadinessInspectSurface(
|
|||
? FString::Join(InputGroundworkFacts.MotionControllerFamilies, TEXT(", "))
|
||||
: FString(TEXT("none"));
|
||||
Surface.XrStatusLine = FString::Printf(
|
||||
TEXT("XR groundwork: EnhancedInput config %s | motion controls %s | controller families %d (%s) | OpenXR project plugin %s | immersive presence contract %s | bounded runtime owner %s (%s) | controller binding %s (%s) | finished XR runtime not yet shipped."),
|
||||
TEXT("XR groundwork: EnhancedInput config %s | motion controls %s | controller families %d (%s) | OpenXR project plugin %s | vertical adjust axis %s | immersive presence contract %s | bounded runtime owner %s (%s) | controller binding %s (%s) | finished XR runtime not yet shipped."),
|
||||
*HyperTwistTrainingPanelWidgetInternal::DescribeBool(
|
||||
Surface.bEnhancedInputProjectGroundworkPresent),
|
||||
*HyperTwistTrainingPanelWidgetInternal::DescribeBool(
|
||||
|
|
@ -1521,6 +1537,8 @@ UHyperTwistTrainingPanelWidget::GetDisplayedControlInputReadinessInspectSurface(
|
|||
*MotionControllerFamilyLabels,
|
||||
*HyperTwistTrainingPanelWidgetInternal::DescribeBool(
|
||||
Surface.bOpenXrProjectPluginEnabled),
|
||||
*HyperTwistTrainingPanelWidgetInternal::DescribeBool(
|
||||
Surface.bXrVerticalAdjustmentAxisPresent),
|
||||
*HyperTwistTrainingPanelWidgetInternal::DescribeBool(
|
||||
Surface.bImmersivePresenceContractReady),
|
||||
*HyperTwistTrainingPanelWidgetInternal::DescribeBool(
|
||||
|
|
|
|||
|
|
@ -11,8 +11,26 @@ namespace HyperTwistXrTrainingPawnInternal
|
|||
{
|
||||
constexpr float SeatedHeightOffset = -42.0f;
|
||||
constexpr float HybridHeightOffset = -20.0f;
|
||||
constexpr float ManualVerticalAdjustmentMin = -160.0f;
|
||||
constexpr float ManualVerticalAdjustmentMax = 160.0f;
|
||||
constexpr float DesktopFallbackPitchMin = -65.0f;
|
||||
constexpr float DesktopFallbackPitchMax = 65.0f;
|
||||
constexpr float MoveSpeedMin = 40.0f;
|
||||
constexpr float MoveSpeedMax = 600.0f;
|
||||
constexpr float VerticalAdjustmentSpeedMin = 40.0f;
|
||||
constexpr float VerticalAdjustmentSpeedMax = 320.0f;
|
||||
constexpr float SnapTurnDegreesMin = 5.0f;
|
||||
constexpr float SnapTurnDegreesMax = 90.0f;
|
||||
constexpr float SnapTurnAxisThresholdMin = 0.2f;
|
||||
constexpr float SnapTurnAxisThresholdMax = 0.95f;
|
||||
constexpr float SmoothTurnDegreesPerSecondMin = 45.0f;
|
||||
constexpr float SmoothTurnDegreesPerSecondMax = 240.0f;
|
||||
constexpr float PointerLengthMin = 32.0f;
|
||||
constexpr float PointerLengthMax = 320.0f;
|
||||
constexpr float WorldToMetersScaleMin = 25.0f;
|
||||
constexpr float WorldToMetersScaleMax = 400.0f;
|
||||
constexpr float ControllerDeadZoneMin = 0.0f;
|
||||
constexpr float ControllerDeadZoneMax = 0.95f;
|
||||
|
||||
FVector BuildPlanarDirection(const FVector& RawDirection)
|
||||
{
|
||||
|
|
@ -45,6 +63,87 @@ namespace HyperTwistXrTrainingPawnInternal
|
|||
return TEXT("standing");
|
||||
}
|
||||
}
|
||||
|
||||
FHyperTwistXrPreferenceProfile SanitizePreferenceProfile(
|
||||
const FHyperTwistXrPreferenceProfile& PreferenceProfile
|
||||
)
|
||||
{
|
||||
const FHyperTwistXrPreferenceProfile DefaultProfile =
|
||||
UHyperTwistXrRuntimeLibrary::GetDefaultXrPreferenceProfile();
|
||||
if (!PreferenceProfile.IsStructurallyValid())
|
||||
{
|
||||
return DefaultProfile;
|
||||
}
|
||||
|
||||
FHyperTwistXrPreferenceProfile Sanitized = PreferenceProfile;
|
||||
Sanitized.MoveSpeedUnitsPerSecond = FMath::Clamp(
|
||||
Sanitized.MoveSpeedUnitsPerSecond,
|
||||
MoveSpeedMin,
|
||||
MoveSpeedMax
|
||||
);
|
||||
Sanitized.VerticalAdjustmentUnitsPerSecond = FMath::Clamp(
|
||||
Sanitized.VerticalAdjustmentUnitsPerSecond,
|
||||
VerticalAdjustmentSpeedMin,
|
||||
VerticalAdjustmentSpeedMax
|
||||
);
|
||||
Sanitized.SnapTurnDegrees = FMath::Clamp(
|
||||
Sanitized.SnapTurnDegrees,
|
||||
SnapTurnDegreesMin,
|
||||
SnapTurnDegreesMax
|
||||
);
|
||||
Sanitized.SnapTurnAxisThreshold = FMath::Clamp(
|
||||
Sanitized.SnapTurnAxisThreshold,
|
||||
SnapTurnAxisThresholdMin,
|
||||
SnapTurnAxisThresholdMax
|
||||
);
|
||||
const float SnapTurnResetThresholdMax = FMath::Max(
|
||||
0.0f,
|
||||
Sanitized.SnapTurnAxisThreshold - 0.05f
|
||||
);
|
||||
Sanitized.SnapTurnResetThreshold = FMath::Clamp(
|
||||
Sanitized.SnapTurnResetThreshold,
|
||||
0.0f,
|
||||
SnapTurnResetThresholdMax
|
||||
);
|
||||
Sanitized.SmoothTurnDegreesPerSecond = FMath::Clamp(
|
||||
Sanitized.SmoothTurnDegreesPerSecond,
|
||||
SmoothTurnDegreesPerSecondMin,
|
||||
SmoothTurnDegreesPerSecondMax
|
||||
);
|
||||
Sanitized.PointerLengthUnits = FMath::Clamp(
|
||||
Sanitized.PointerLengthUnits,
|
||||
PointerLengthMin,
|
||||
PointerLengthMax
|
||||
);
|
||||
Sanitized.WorldToMetersScale = FMath::Clamp(
|
||||
Sanitized.WorldToMetersScale,
|
||||
WorldToMetersScaleMin,
|
||||
WorldToMetersScaleMax
|
||||
);
|
||||
Sanitized.ComfortVignetteStrength = FMath::Clamp(
|
||||
Sanitized.ComfortVignetteStrength,
|
||||
0.0f,
|
||||
1.0f
|
||||
);
|
||||
Sanitized.ControllerDeadZone = FMath::Clamp(
|
||||
Sanitized.ControllerDeadZone,
|
||||
ControllerDeadZoneMin,
|
||||
ControllerDeadZoneMax
|
||||
);
|
||||
if (Sanitized.PreferenceFieldTags.Num() <= 0)
|
||||
{
|
||||
Sanitized.PreferenceFieldTags = DefaultProfile.PreferenceFieldTags;
|
||||
}
|
||||
if (Sanitized.ComfortSurfaceTags.Num() <= 0)
|
||||
{
|
||||
Sanitized.ComfortSurfaceTags = DefaultProfile.ComfortSurfaceTags;
|
||||
}
|
||||
if (Sanitized.ExplicitExclusions.Num() <= 0)
|
||||
{
|
||||
Sanitized.ExplicitExclusions = DefaultProfile.ExplicitExclusions;
|
||||
}
|
||||
return Sanitized;
|
||||
}
|
||||
}
|
||||
|
||||
AHyperTwistXrTrainingPawn::AHyperTwistXrTrainingPawn()
|
||||
|
|
@ -97,6 +196,7 @@ void AHyperTwistXrTrainingPawn::Tick(const float DeltaSeconds)
|
|||
|
||||
RefreshHeadMountedDisplayState();
|
||||
UpdateSmoothLocomotion(DeltaSeconds);
|
||||
UpdateVerticalAdjustment(DeltaSeconds);
|
||||
UpdateTurn(DeltaSeconds);
|
||||
UpdateDesktopFallbackPitch(DeltaSeconds);
|
||||
}
|
||||
|
|
@ -121,6 +221,11 @@ void AHyperTwistXrTrainingPawn::SetupPlayerInputComponent(
|
|||
this,
|
||||
&AHyperTwistXrTrainingPawn::HandleMoveRight
|
||||
);
|
||||
PlayerInputComponent->BindAxis(
|
||||
TEXT("HyperTwistXr_VerticalAdjust"),
|
||||
this,
|
||||
&AHyperTwistXrTrainingPawn::HandleVerticalAdjustAxis
|
||||
);
|
||||
PlayerInputComponent->BindAxis(
|
||||
TEXT("HyperTwistXr_Turn"),
|
||||
this,
|
||||
|
|
@ -175,12 +280,10 @@ void AHyperTwistXrTrainingPawn::ApplyPreferenceProfile(
|
|||
const FHyperTwistXrPreferenceProfile& PreferenceProfile
|
||||
)
|
||||
{
|
||||
if (!PreferenceProfile.IsStructurallyValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ActivePreferenceProfile = PreferenceProfile;
|
||||
ActivePreferenceProfile =
|
||||
HyperTwistXrTrainingPawnInternal::SanitizePreferenceProfile(
|
||||
PreferenceProfile
|
||||
);
|
||||
ApplyPostureOffset();
|
||||
ApplyPointerAnchors();
|
||||
|
||||
|
|
@ -218,6 +321,7 @@ void AHyperTwistXrTrainingPawn::SetSnapTurnEnabled(const bool bEnabled)
|
|||
|
||||
void AHyperTwistXrTrainingPawn::ResetXrOrigin()
|
||||
{
|
||||
ManualVerticalAdjustmentUnits = 0.0f;
|
||||
DesktopFallbackPitchDegrees = 0.0f;
|
||||
ApplyDesktopFallbackRotation();
|
||||
ApplyPostureOffset();
|
||||
|
|
@ -235,7 +339,7 @@ FString AHyperTwistXrTrainingPawn::BuildRuntimeStatusLine() const
|
|||
const FHyperTwistXrRuntimeOwnershipSurface RuntimeSurface =
|
||||
GetBoundedRuntimeOwnershipSurface();
|
||||
return FString::Printf(
|
||||
TEXT("OpenXR runtime owner %s | preferences %s | bindings %s | HMD connected %s | HMD enabled %s | posture %s | dominant hand %s | snap turn %s | smooth locomotion %s | grip %.2f/%.2f | trigger %.2f/%.2f"),
|
||||
TEXT("OpenXR runtime owner %s | preferences %s | bindings %s | HMD connected %s | HMD enabled %s | posture %s | dominant hand %s | snap turn %s | smooth locomotion %s | vertical offset %.0f | desktop pitch %.0f | grip %.2f/%.2f | trigger %.2f/%.2f"),
|
||||
*RuntimeSurface.RuntimeOwnerId,
|
||||
*ActivePreferenceProfile.ProfileId,
|
||||
*ActiveControllerBindingProfile.ProfileId,
|
||||
|
|
@ -247,6 +351,8 @@ FString AHyperTwistXrTrainingPawn::BuildRuntimeStatusLine() const
|
|||
ActivePreferenceProfile.DominantHand),
|
||||
ActivePreferenceProfile.bSnapTurnEnabled ? TEXT("on") : TEXT("off"),
|
||||
ActivePreferenceProfile.bSmoothLocomotionEnabled ? TEXT("on") : TEXT("off"),
|
||||
ManualVerticalAdjustmentUnits,
|
||||
DesktopFallbackPitchDegrees,
|
||||
LeftGripValue,
|
||||
RightGripValue,
|
||||
LeftTriggerValue,
|
||||
|
|
@ -274,7 +380,9 @@ void AHyperTwistXrTrainingPawn::ApplyPostureOffset()
|
|||
break;
|
||||
}
|
||||
|
||||
VROrigin->SetRelativeLocation(FVector(0.0f, 0.0f, HeightOffset));
|
||||
VROrigin->SetRelativeLocation(
|
||||
FVector(0.0f, 0.0f, HeightOffset + ManualVerticalAdjustmentUnits)
|
||||
);
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::ApplyPointerAnchors()
|
||||
|
|
@ -313,10 +421,25 @@ void AHyperTwistXrTrainingPawn::ApplyDesktopFallbackRotation()
|
|||
|
||||
void AHyperTwistXrTrainingPawn::RefreshHeadMountedDisplayState()
|
||||
{
|
||||
const bool bWasHeadMountedDisplayEnabled = bHeadMountedDisplayEnabled;
|
||||
bHeadMountedDisplayConnected =
|
||||
UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayConnected();
|
||||
bHeadMountedDisplayEnabled =
|
||||
UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled();
|
||||
if (bHeadMountedDisplayEnabled && !bWasHeadMountedDisplayEnabled)
|
||||
{
|
||||
DesktopFallbackPitchDegrees = 0.0f;
|
||||
if (VROrigin != nullptr)
|
||||
{
|
||||
VROrigin->SetRelativeRotation(FRotator::ZeroRotator);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bHeadMountedDisplayEnabled && bWasHeadMountedDisplayEnabled)
|
||||
{
|
||||
ApplyDesktopFallbackRotation();
|
||||
}
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::UpdateSmoothLocomotion(const float DeltaSeconds)
|
||||
|
|
@ -352,6 +475,33 @@ void AHyperTwistXrTrainingPawn::UpdateSmoothLocomotion(const float DeltaSeconds)
|
|||
AddActorWorldOffset(Delta, true);
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::UpdateVerticalAdjustment(const float DeltaSeconds)
|
||||
{
|
||||
if (!ActivePreferenceProfile.bAllowVerticalAdjustment || VROrigin == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float VerticalAdjustValue = HyperTwistXrTrainingPawnInternal::ApplyDeadZone(
|
||||
PendingVerticalAdjust,
|
||||
ActivePreferenceProfile.ControllerDeadZone
|
||||
);
|
||||
if (FMath::IsNearlyZero(VerticalAdjustValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ManualVerticalAdjustmentUnits = FMath::Clamp(
|
||||
ManualVerticalAdjustmentUnits
|
||||
+ VerticalAdjustValue
|
||||
* ActivePreferenceProfile.VerticalAdjustmentUnitsPerSecond
|
||||
* DeltaSeconds,
|
||||
HyperTwistXrTrainingPawnInternal::ManualVerticalAdjustmentMin,
|
||||
HyperTwistXrTrainingPawnInternal::ManualVerticalAdjustmentMax
|
||||
);
|
||||
ApplyPostureOffset();
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::UpdateTurn(const float DeltaSeconds)
|
||||
{
|
||||
const float TurnValue = HyperTwistXrTrainingPawnInternal::ApplyDeadZone(
|
||||
|
|
@ -430,6 +580,11 @@ void AHyperTwistXrTrainingPawn::HandleMoveRight(const float Value)
|
|||
PendingMoveRight = Value;
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::HandleVerticalAdjustAxis(const float Value)
|
||||
{
|
||||
PendingVerticalAdjust = Value;
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::HandleTurnAxis(const float Value)
|
||||
{
|
||||
PendingTurnAxis = Value;
|
||||
|
|
@ -442,22 +597,22 @@ void AHyperTwistXrTrainingPawn::HandleLookPitchAxis(const float Value)
|
|||
|
||||
void AHyperTwistXrTrainingPawn::HandleLeftGripAxis(const float Value)
|
||||
{
|
||||
LeftGripValue = Value;
|
||||
LeftGripValue = FMath::Clamp(Value, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::HandleRightGripAxis(const float Value)
|
||||
{
|
||||
RightGripValue = Value;
|
||||
RightGripValue = FMath::Clamp(Value, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::HandleLeftTriggerAxis(const float Value)
|
||||
{
|
||||
LeftTriggerValue = Value;
|
||||
LeftTriggerValue = FMath::Clamp(Value, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::HandleRightTriggerAxis(const float Value)
|
||||
{
|
||||
RightTriggerValue = Value;
|
||||
RightTriggerValue = FMath::Clamp(Value, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void AHyperTwistXrTrainingPawn::HandleToggleSnapTurn()
|
||||
|
|
|
|||
|
|
@ -10057,6 +10057,9 @@ struct FHyperTwistTrainingControlInputReadinessInspectSurface
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bOpenXrProjectPluginEnabled = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bXrVerticalAdjustmentAxisPresent = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist")
|
||||
bool bClassicCubeMouseInputReady = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -96,11 +96,13 @@ protected:
|
|||
void ApplyDesktopFallbackRotation();
|
||||
void RefreshHeadMountedDisplayState();
|
||||
void UpdateSmoothLocomotion(float DeltaSeconds);
|
||||
void UpdateVerticalAdjustment(float DeltaSeconds);
|
||||
void UpdateTurn(float DeltaSeconds);
|
||||
void UpdateDesktopFallbackPitch(float DeltaSeconds);
|
||||
|
||||
void HandleMoveForward(float Value);
|
||||
void HandleMoveRight(float Value);
|
||||
void HandleVerticalAdjustAxis(float Value);
|
||||
void HandleTurnAxis(float Value);
|
||||
void HandleLookPitchAxis(float Value);
|
||||
void HandleLeftGripAxis(float Value);
|
||||
|
|
@ -112,8 +114,10 @@ protected:
|
|||
|
||||
float PendingMoveForward = 0.0f;
|
||||
float PendingMoveRight = 0.0f;
|
||||
float PendingVerticalAdjust = 0.0f;
|
||||
float PendingTurnAxis = 0.0f;
|
||||
float PendingLookPitchAxis = 0.0f;
|
||||
float ManualVerticalAdjustmentUnits = 0.0f;
|
||||
float DesktopFallbackPitchDegrees = 0.0f;
|
||||
bool bSnapTurnLatchOpen = true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1150,6 +1150,7 @@ bool FHyperTwistTrainingPanelControlInputReadinessInspectSurfaceTest::RunTest(
|
|||
TestTrue(
|
||||
TEXT("The control/input readiness surface must keep the current project OpenXR plugin posture explicit."),
|
||||
Surface.bOpenXrProjectPluginEnabled
|
||||
&& Surface.bXrVerticalAdjustmentAxisPresent
|
||||
);
|
||||
TestFalse(
|
||||
TEXT("The control/input readiness surface must keep unfinished XR/runtime and preferences truth explicit."),
|
||||
|
|
@ -1190,9 +1191,15 @@ bool FHyperTwistTrainingPanelControlInputReadinessInspectSurfaceTest::RunTest(
|
|||
TEXT("The control/input readiness surface must say plainly that finished XR runtime is not yet shipped."),
|
||||
Surface.XrStatusLine.Contains(TEXT("not yet shipped"))
|
||||
&& Surface.XrStatusLine.Contains(TEXT("OpenXR project plugin yes"))
|
||||
&& Surface.XrStatusLine.Contains(TEXT("vertical adjust axis yes"))
|
||||
&& Surface.XrStatusLine.Contains(TEXT("xr/openxr-desktop-training-runtime-owner"))
|
||||
&& Surface.XrStatusLine.Contains(TEXT("xr-openxr-motion-controllers/v1"))
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The control/input readiness surface must now spell out the bounded vertical-adjust and pointer preference ownership."),
|
||||
Surface.XrPreferenceOwnerLine.Contains(TEXT("vertical adjust 120"))
|
||||
&& Surface.XrPreferenceOwnerLine.Contains(TEXT("pointer 180"))
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The control/input readiness surface must retain the fixed No-Go host decision and the later settings/rebinding follow-through."),
|
||||
Surface.NextPacketLine.Contains(TEXT("No-Go"))
|
||||
|
|
@ -1257,6 +1264,7 @@ bool FHyperTwistCoachDashboardControlInputReadinessInspectSurfaceTest::RunTest(
|
|||
TEXT("The coach dashboard control/input readiness surface must retain the unfinished XR/runtime truth in its detail line."),
|
||||
Surface.DetailLine.Contains(TEXT("not yet shipped"))
|
||||
&& Surface.DetailLine.Contains(TEXT("OpenXR project plugin yes"))
|
||||
&& Surface.DetailLine.Contains(TEXT("vertical adjust axis yes"))
|
||||
&& Surface.DetailLine.Contains(TEXT("xr/openxr-desktop-training-runtime-owner"))
|
||||
);
|
||||
TestTrue(
|
||||
|
|
@ -1267,6 +1275,12 @@ bool FHyperTwistCoachDashboardControlInputReadinessInspectSurfaceTest::RunTest(
|
|||
TestTrue(
|
||||
TEXT("The coach dashboard control/input readiness surface must preserve the explicit enabled OpenXR project plugin truth."),
|
||||
Surface.bOpenXrProjectPluginEnabled
|
||||
&& Surface.bXrVerticalAdjustmentAxisPresent
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The coach dashboard control/input readiness surface must retain the bounded vertical-adjust and pointer preference ownership."),
|
||||
Surface.DetailLine.Contains(TEXT("vertical adjust 120"))
|
||||
&& Surface.DetailLine.Contains(TEXT("pointer 180"))
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The coach dashboard control/input readiness surface must expose the bounded XR runtime owner, preference profile, and controller binding profile."),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include "Misc/AutomationTest.h"
|
||||
|
||||
#include "Components/SceneComponent.h"
|
||||
#include "Math/UnrealMathUtility.h"
|
||||
|
||||
#include "HyperTwistXR/HyperTwistXrRuntimeLibrary.h"
|
||||
#include "HyperTwistXR/HyperTwistXrTrainingPawn.h"
|
||||
|
||||
|
|
@ -151,6 +154,92 @@ bool FHyperTwistXrTrainingPawnDefaultsTest::RunTest(const FString& Parameters)
|
|||
PawnDefaults->BuildRuntimeStatusLine().Contains(TEXT("xr/openxr-desktop-training-runtime-owner"))
|
||||
&& PawnDefaults->BuildRuntimeStatusLine().Contains(TEXT("xr-openxr-training-preferences/v1"))
|
||||
&& PawnDefaults->BuildRuntimeStatusLine().Contains(TEXT("xr-openxr-motion-controllers/v1"))
|
||||
&& PawnDefaults->BuildRuntimeStatusLine().Contains(TEXT("vertical offset 0"))
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
FHyperTwistXrTrainingPawnPreferenceHardeningTest,
|
||||
"HyperTwist.FirstParty.XR.TrainingPawnPreferenceHardening",
|
||||
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter
|
||||
)
|
||||
|
||||
bool FHyperTwistXrTrainingPawnPreferenceHardeningTest::RunTest(
|
||||
const FString& Parameters
|
||||
)
|
||||
{
|
||||
AHyperTwistXrTrainingPawn* Pawn =
|
||||
NewObject<AHyperTwistXrTrainingPawn>(GetTransientPackage());
|
||||
TestNotNull(TEXT("The XR training pawn must be constructible for hardening checks."), Pawn);
|
||||
if (Pawn == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FHyperTwistXrPreferenceProfile PreferenceProfile =
|
||||
UHyperTwistXrRuntimeLibrary::GetDefaultXrPreferenceProfile();
|
||||
PreferenceProfile.MoveSpeedUnitsPerSecond = -25.0f;
|
||||
PreferenceProfile.VerticalAdjustmentUnitsPerSecond = -5.0f;
|
||||
PreferenceProfile.SnapTurnDegrees = 0.0f;
|
||||
PreferenceProfile.SnapTurnAxisThreshold = 2.0f;
|
||||
PreferenceProfile.SnapTurnResetThreshold = 2.0f;
|
||||
PreferenceProfile.SmoothTurnDegreesPerSecond = 12.0f;
|
||||
PreferenceProfile.PointerLengthUnits = 0.0f;
|
||||
PreferenceProfile.WorldToMetersScale = 0.0f;
|
||||
PreferenceProfile.ComfortVignetteStrength = 9.0f;
|
||||
PreferenceProfile.ControllerDeadZone = -0.2f;
|
||||
PreferenceProfile.PreferenceFieldTags.Reset();
|
||||
PreferenceProfile.ComfortSurfaceTags.Reset();
|
||||
PreferenceProfile.ExplicitExclusions.Reset();
|
||||
PreferenceProfile.PostureMode = EHyperTwistXrPostureMode::Hybrid;
|
||||
|
||||
Pawn->ApplyPreferenceProfile(PreferenceProfile);
|
||||
|
||||
TestTrue(
|
||||
TEXT("The XR training pawn must clamp invalid movement and vertical-adjust speeds."),
|
||||
Pawn->ActivePreferenceProfile.MoveSpeedUnitsPerSecond > 0.0f
|
||||
&& Pawn->ActivePreferenceProfile.VerticalAdjustmentUnitsPerSecond > 0.0f
|
||||
&& Pawn->ActivePreferenceProfile.MoveSpeedUnitsPerSecond
|
||||
!= PreferenceProfile.MoveSpeedUnitsPerSecond
|
||||
&& Pawn->ActivePreferenceProfile.VerticalAdjustmentUnitsPerSecond
|
||||
!= PreferenceProfile.VerticalAdjustmentUnitsPerSecond
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The XR training pawn must clamp turning, pointer, world-scale, comfort, and dead-zone bounds."),
|
||||
Pawn->ActivePreferenceProfile.SnapTurnDegrees >= 5.0f
|
||||
&& Pawn->ActivePreferenceProfile.SnapTurnAxisThreshold <= 0.95f
|
||||
&& Pawn->ActivePreferenceProfile.SnapTurnResetThreshold
|
||||
< Pawn->ActivePreferenceProfile.SnapTurnAxisThreshold
|
||||
&& Pawn->ActivePreferenceProfile.SmoothTurnDegreesPerSecond >= 45.0f
|
||||
&& Pawn->ActivePreferenceProfile.PointerLengthUnits > 0.0f
|
||||
&& Pawn->ActivePreferenceProfile.WorldToMetersScale > 0.0f
|
||||
&& Pawn->ActivePreferenceProfile.ComfortVignetteStrength <= 1.0f
|
||||
&& Pawn->ActivePreferenceProfile.ControllerDeadZone >= 0.0f
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The XR training pawn must restore default metadata arrays when a custom profile clears them."),
|
||||
Pawn->ActivePreferenceProfile.PreferenceFieldTags.Num() > 0
|
||||
&& Pawn->ActivePreferenceProfile.ComfortSurfaceTags.Num() > 0
|
||||
&& Pawn->ActivePreferenceProfile.ExplicitExclusions.Num() > 0
|
||||
);
|
||||
TestTrue(
|
||||
TEXT("The XR training pawn must apply the sanitized pointer anchor length and hybrid posture offset."),
|
||||
Pawn->LeftPointerAnchor != nullptr
|
||||
&& Pawn->RightPointerAnchor != nullptr
|
||||
&& Pawn->VROrigin != nullptr
|
||||
&& FMath::IsNearlyEqual(
|
||||
Pawn->LeftPointerAnchor->GetRelativeLocation().X,
|
||||
Pawn->ActivePreferenceProfile.PointerLengthUnits
|
||||
)
|
||||
&& FMath::IsNearlyEqual(
|
||||
Pawn->RightPointerAnchor->GetRelativeLocation().X,
|
||||
Pawn->ActivePreferenceProfile.PointerLengthUnits
|
||||
)
|
||||
&& FMath::IsNearlyEqual(
|
||||
Pawn->VROrigin->GetRelativeLocation().Z,
|
||||
-20.0f
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,10 @@ Current authoritative host posture:
|
|||
|
||||
- `UnrealHyperTwist/Config/DefaultInput.ini` now proves real bounded
|
||||
controller-axis and action ownership across the current controller-family
|
||||
roster instead of only broad motion-controller groundwork
|
||||
roster instead of only broad motion-controller groundwork, and the current
|
||||
same-family hardening follow-up also adds a bounded dedicated vertical-adjust
|
||||
axis for desktop-hosted XR posture instead of leaving that owned preference
|
||||
field inert
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistXR/HyperTwistXrRuntimeLibrary.h`
|
||||
and `.../Private/HyperTwistXR/HyperTwistXrRuntimeLibrary.cpp` now define the
|
||||
first-party bounded runtime-owner, preference-profile, and controller-binding
|
||||
|
|
@ -57,7 +60,9 @@ Current authoritative host posture:
|
|||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistXR/HyperTwistXrTrainingPawn.h`
|
||||
and `.../Private/HyperTwistXR/HyperTwistXrTrainingPawn.cpp` now provide a
|
||||
bounded first-party XR training pawn with camera, controller anchors,
|
||||
posture switching, desktop fallback pitch handling, recentering, and status
|
||||
posture switching, desktop fallback pitch handling, recentering, bounded
|
||||
manual vertical-adjust ownership, sanitized preference application, stale
|
||||
desktop-fallback rotation clearing on headset activation, and status
|
||||
reporting
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistTraining/HyperTwistTrainingImmersiveEnvironmentLibrary.cpp`
|
||||
keeps the immersive lane explicitly bounded to scenic training ownership
|
||||
|
|
@ -110,6 +115,11 @@ Current authoritative host posture:
|
|||
with `3` focused XR tests succeeded
|
||||
- `Saved\AutomationReports\Browser-XrBoundedRuntime-20260701-Final\index.json`
|
||||
with all `26` `HyperTwist.Browser.*` tests succeeded
|
||||
- the current same-family hardening continuation then also keeps the dedicated
|
||||
vertical-adjust axis visible in native control/input inspect truth and keeps
|
||||
XR preference ownership explicit about vertical-adjust plus pointer-length
|
||||
control instead of relying on those facts to stay implicit in the preference
|
||||
struct alone
|
||||
|
||||
## Interpretation
|
||||
|
||||
|
|
|
|||
|
|
@ -336,7 +336,9 @@ truthfully claim:
|
|||
runtime module dependencies
|
||||
- `UnrealHyperTwist/Config/DefaultInput.ini` now owns explicit OpenXR-ready
|
||||
controller axes and actions across the currently bounded controller-family
|
||||
roster
|
||||
roster, and the current hardening follow-up also adds a bounded dedicated
|
||||
vertical-adjust axis for desktop-hosted XR posture instead of leaving the
|
||||
owned vertical-adjust preference field inert
|
||||
- `UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistXR/HyperTwistXrRuntimeLibrary.h`
|
||||
and `.../Private/HyperTwistXR/HyperTwistXrRuntimeLibrary.cpp` now define
|
||||
the first-party runtime-owner, preference-profile, and controller-binding
|
||||
|
|
@ -348,12 +350,19 @@ truthfully claim:
|
|||
and `.../Private/HyperTwistXR/HyperTwistXrTrainingPawn.cpp` now provide a
|
||||
bounded first-party training pawn with `CameraComponent`,
|
||||
`MotionControllerComponent` anchors, desktop fallback pitch handling,
|
||||
posture switching, recentering, and owned runtime status reporting
|
||||
posture switching, recentering, bounded manual vertical-adjust ownership,
|
||||
sanitized preference application, stale-fallback-rotation clearing on HMD
|
||||
activation, and owned runtime status reporting
|
||||
- the native control/input, control/settings, and control/profile inspect
|
||||
surfaces now also expose that bounded runtime-owner packet in structured
|
||||
fields and rendered operator lines, including the stable ids, preference
|
||||
field count `8`, required binding-axis count `8`, and supported controller
|
||||
family count `4`
|
||||
- the same native control/input inspect surface now also keeps the dedicated
|
||||
vertical-adjust axis presence explicit in structured state and rendered
|
||||
operator text, so the current XR preference/profile packet no longer says it
|
||||
owns vertical adjustment while the corresponding project input seam remains
|
||||
silent
|
||||
- the maintained reverse-SSH Windows lane then revalidated that exact-source
|
||||
state on `C:\HyperTwist_worktrees\phase10validate`:
|
||||
- final exact-source editor build:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -165,7 +165,10 @@ statement forward too without overclaiming launch-tier completion:
|
|||
- `xr-openxr-training-preferences/v1`
|
||||
- `xr-openxr-motion-controllers/v1`
|
||||
- a dedicated `AHyperTwistXrTrainingPawn` now owns bounded camera/controller
|
||||
anchors, posture switching, recentering, and desktop fallback pitch handling
|
||||
anchors, posture switching, recentering, bounded manual vertical-adjust
|
||||
ownership, sanitized preference application, and desktop fallback pitch
|
||||
handling that now clears stale fallback rotation when a headset becomes
|
||||
active
|
||||
- the maintained Windows validation lane then re-proved the exact-source state
|
||||
with:
|
||||
- editor build `Result: Succeeded`, UnrealBuildTool `Total execution time:
|
||||
|
|
|
|||
|
|
@ -1440,7 +1440,7 @@ describe('public marketing pages', () => {
|
|||
expect(screen.getAllByText(/classic-wca-keyboard\/v1/i).length).toBeGreaterThan(0)
|
||||
expect(screen.getByText('4. Open the higher-dimensional lanes and read the control boundary honestly')).toBeTruthy()
|
||||
expect(screen.getByText(/I\/K = R\/R', J\/F = U\/U', H\/G = F\/F'/i)).toBeTruthy()
|
||||
expect(screen.getByText(/OpenXR plugin disabled/i)).toBeTruthy()
|
||||
expect(screen.getByText(/bounded OpenXR plugin stack and first-party runtime-owner substrate/i)).toBeTruthy()
|
||||
expect(screen.getByText(/R scramble, H hint, Enter submit, F mode, V hold-to-talk, C cycle voice/i)).toBeTruthy()
|
||||
expect(screen.getAllByText(/latest persisted generated-mode selector posture is available for recall/i).length).toBeGreaterThan(0)
|
||||
expect(screen.getByText('Feature-registry-backed wording only')).toBeTruthy()
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ export const inputAndDevicePostureCards = [
|
|||
description: 'EnhancedInput posture and motion-controller groundwork exist, but HyperTwist does not yet market a fully finished OpenXR/controller/rebinding runtime lane.',
|
||||
bullets: [
|
||||
'Project config already carries EnhancedInput plus Vive, Oculus Touch, Mixed Reality, and Valve Index axis groundwork.',
|
||||
'The current shipping branch also keeps the project OpenXR plugin disabled, which is one reason the native XR/controller lane remains an explicit desktop-hosted No-Go today.',
|
||||
'The current shipping branch now enables the bounded OpenXR plugin stack and first-party runtime-owner substrate, but that still does not collapse the broader native XR/controller lane out of its explicit desktop-hosted No-Go posture.',
|
||||
'Current product truth should not overclaim headset-specific runtime ownership or polished user-facing input rebinding.',
|
||||
'The current host decision remains desktop-hosted No-Go on native OpenXR/controller widening; any future reopen would still need dedicated runtime owners, user-facing settings and controller-rebinding ownership, and Windows packaged controller validation with controller truth.',
|
||||
],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue