UX Tools 0.12.0 release notes
- What's new
- Breaking changes
- UxtHandTrackingFunctionLibrary removed
- UxtMathUtilsFunctionLibrary's API update
- UxtOneHandedRotationMode
- UxtTransformConstraint
- UxtTouchableVolumeComponent's API update
- UxtRotationAxisConstraint
- UxtMinMaxScaleConstraint
- Renamed mesh for Bounds Control's face handles
- UxtBasePressableButtonActor button component access
- IUxtHandTracker
- ControllerOrientation property removed from UUxtFarPointerComponent
- Updated smoothing factors for Manipulator and Pinch Slider
- Known issues
- Full change list
This release of the UX Tools has been tested on HoloLens 2 and Windows Mixed Reality VR but should work on all XR devices supported by Unreal Engine via OpenXR:
- HoloLens 2
- Windows Mixed Reality VR
- Oculus
- Steam VR
Unreal 4.26 required.
What's new
These are some of this release's highlights. For a more comprehensive list of changes see the full change list.
Cross-platform support for XR devices
UX Tools now offers cross-platform support across XR devices! UXT 0.12.0 leverages the common AR and VR interfaces added in Unreal Engine 4.26 to keep application code platform agnostic. This means UX Tools is no longer tied to the Windows Mixed Reality plugin and HoloLens 2 device. UXT 0.12.0 supports OpenXR and can be used with the Microsoft OpenXR plugin for full support of HoloLens 2 and Windows Mixed Reality VR headsets. Note that while we have only tested UXT 0.12.0 on Microsoft's mixed reality headsets, we expect UXT to work on all devices that support OpenXR.
Manipulator improvements
UI to add constraints to Generic Manipulator and Bounds Control
The generic manipulator and bounds control components now provide a constraint picker to allow for fine grained control of what constraints are applied by the manipulator. The constraint picker can be used to add constraints to actor instances and blueprints. The UI automatically populates with classes inheriting from UxtTransformConstraint
so user defined constraints can also be added using this dialog box.
Rotation Axis Constraint improvements
The UUxtRotationAxisConstraint
is now based on quaternions instead of Euler angles. By using swing-twist decomposition, we got rid of rotation errors and undesired flips.
Besides that, ConstraintOnRotation
has been replaced by AllowedAxis
in order to better convey the meaning of the constraint and prevent unexpected configurations. If only 1 axis was constrained (which is a configuration previously allowed), combinations of rotations around the other two axes might end up in a rotation that you wouldn't expect to be allowed.
Thanks to these changes, UUxtBoundsControlComponent
is now able to interact appropriately with this constraint. In the following example, you can see how the constraint works when it only allows rotation around the Z
axis:
| bUseLocalSpaceForConstraint == false | bUseLocalSpaceForConstraint == true | | --- | --- | | | | (NOTE: debug axes aligned to world's have been added for reference)
Built-in scale constraint
Instead of relying on an external component (which is easier to forget about or misconfigure), potentially leading to undesired effects such as actor mirroring, all classes inheriting from UUxtManipulatorComponent
(which includes UUxtBoundsControlComponent
and UUxtGenericManipulatorComponent
) have now an implicitly applied scale constraint, configurable via editor. See TransformConstraints.md for details.
Fixed slowdown when running below 60 FPS
The calculation of smoothed movement for the manipulator and pinch slider components was using an incorrect formula, leading to slower manipulation when the frame rate drops. See the breaking changes section for necessary action: Updated smoothing factors for Manipulator and Pinch Slider.
Bounds Control improvements
Bounds override
UUxtBoundsControlComponent
now has a BoundsOverride
property, which (if set) will make the bounds control box and affordances display around that UPrimitiveComponent
instead of around the whole actor. Please note that this setup will still modify the actor's root transform.
Unset | Set |
---|---|
Improved interaction with Tap to Place
Thanks to the new BoundsOverride
property in UUxtBoundsControlComponent
and other few changes, this component and UUxtTapToPlaceComponent
can now work together.
Automatic scaling of affordances with distance to camera
In order to match the HoloLens 2 shell's behavior, affordances are now scaled up, based on the distance to the hologram they are surrounding. This makes it easier to interact with them when the actors are big and far away.
Improvements to face affordances
UUxtBoundsControlComponent::TransformTarget
's handling of theEUxtAffordanceAction::Translate
action has been fixed.- The face mesh (
SM_BoundingBox_FaceHandle.uasset
) now has collisions, so you can interact with them. - A new
UUxtBoundsControlConfig
data asset (namedBoundsControlDefaultWithFaces.uasset
) has been added, with face affordances configured by default. BoundsControlExamples.umap
has a new coffee cup instance featuring face handles.- The default mesh used for face handles has been renamed to
SM_BoundingBox_TranslateHandle.uasset
, so it better matches its scale/rotate counterparts. The old placeholder mesh is also replaced by the appropriate mesh:
Old mesh | New mesh |
---|---|
Tap to Place improvements
Allow keeping the original orientation of the object being placed
Added MaintainOrientation
mode to UxtTapToPlaceComponent
to allow preserving the original orientation of the object while it is being repositioned.
Customizable surface normal offset
The TapToPlace component now allows you to specify a custom offset between the object being placed and the surface it is being placed on. This can be achieved by setting bUseDefaultSurfaceNormalOffset
to false and providing a custom offset in SurfaceNormalOffset
property. The offset is measured from the pivot point of the object along the X axis (towards the positive direction as this is the side which is aligned with the surface).
If bUseDefaultSurfaceNormalOffset
is set to true, the object will be aligned with the surface on which it is being placed and the value SurfaceNormalOffset
will be calculated automatically. The offset will now be correct also for objects that use a pivot point which is not located in the centre of the bounding box.
Allow Scene Components as target
UUxtTapToPlaceComponent
allows assigning USceneComponent
as the TargetComponent
(previously UPrimitiveComponent
was required). This allows adding TapToPlace behaviour to any hierarchy of actor components and makes the experience consistent with the other UX Tools components (e.g. UxtGenericManipulator
).
Touchable Volume improvements
- An
InteractionMode
property has been added to allow limiting the interactions to only near or far pointers. - The
bLockFocus
flag has been added to allow the focus locking of pointers be disabled.
Breaking changes
UxtHandTrackingFunctionLibrary removed
This function library was just a thin wrapper around the IUxtHandTracker
interface. It has been removed to make code less redundant. The IUxtHandTracker
singleton getter returns a reference instead of a pointer for simpler access. If the function library was used in blueprints, the equivalent functions of the XR tracking system should be used, such as Get Motion Controller Data.
UxtMathUtilsFunctionLibrary's API update
CalculateNestedActorBoundsInGivenSpace
and CalculateNestedActorBoundsInLocalSpace
have been removed in favor of a simpler and more flexible CalculateNestedBoundsInGivenSpace
.
Hopefully, switching to the new function is not troublesome, but here are some guidelines:
- The first parameter is now a
USceneComponent
instead of anAActor
. Simply add aGetRootComponent()
to the previously used parameter. - If you were using the
InLocalSpace
variant, now you need to pass in the local space explicitly. On the same component that you're now passing as first parameter (see previous point), simply useGetComponentTransform().Inverse()
. - The
Ignore
parameter is now aTArrayView<const USceneComponent* const>
, instead of a single component. Typically, enclosing the previously used parameter in curly braces{}
will suffice, thanks to the TArrayView's initializer list constructor. The MakeArrayView overload list and MoveTemp utilities might come in handy, too.
UxtOneHandedRotationMode
MaintainOriginalRotation
,MaintainOriginalRotation
,MaintainOriginalRotation
,MaintainOriginalRotation
andMaintainOriginalRotation
have been removed in favor of using transform constraints.
UxtTransformConstraint
- The
TargetComponent
property has been removed in favor of usingWorldPoseOnManipulationStart
.
UxtTouchableVolumeComponent's API update
- The
OnBeginFocus
,OnUpdateFocus
,OnEndFocus
events now pass the pointer as aUUxtPointerComponent
instead of aUObject
. - The
OnBeginPoke
,OnUpdatePoke
,OnEndPoke
events now pass the pointer as aUUxtPointerComponent
instead of aUUxtNearPointerComponent
.
UxtRotationAxisConstraint
As mentioned in the UxtRotationAxisConstraint's improvement section, ConstraintOnRotation
has been replaced by AllowedAxis
, becoming a single EUxtAxis
instead of a bit mask. Any existing instances of this constraint will take the value EUxtAxis::None
by default (preventing any rotations at all), so you need to reconfigure said instances by selecting the axis you want to allow rotation around.
In the event that you had any UUxtRotationAxisConstraint
instanced from C++ code, please remember to check for any assignments of ConstraintOnRotation
, such as
RotationConstraint->ConstraintOnRotation = static_cast<uint32>(EUxtAxisFlags::X | EUxtAxisFlags::Y | EUxtAxisFlags::Z);
and replace them by the corresponding
RotationConstraint->AllowedAxis = EUxtAxis::None;
UxtMinMaxScaleConstraint
As this component has been removed and its functionality is now embedded inside UUxtManipulatorComponent
, you need to revisit any instances of this constraint that you had. All you need to do is copy the MinScale
, MaxScale
and bRelativeToInitialScale
values over to all applicable components in the actor. Please remember that, if you have UUxtBoundsControlComponent
and UUxtGenericManipulatorComponent
in the same actor, you now need to configure both of them separately.
Renamed mesh for Bounds Control's face handles
The asset has been renamed to better match its rotate/scale counterparts, so you need to replace any references to SM_BoundingBox_FaceHandle.uasset
by SM_BoundingBox_TranslateHandle.uasset
.
UxtBasePressableButtonActor button component access
The UxtBasePressableButtonActor
's ButtonComponent property has been changed from BlueprintReadWrite
to BlueprintReadOnly
because changing the button component is an unsupported code path.
IUxtHandTracker
The EUxtHandJoint
enum has been replaced by EHandKeypoint, which is part of the UE4 engine (HeadMountedDisplayTypes.h). This affects the "Joint" parameter in the IUxtHandTracker::GetJointState
function.
ControllerOrientation property removed from UUxtFarPointerComponent
This property was only caching the wrist orientation. The far pointer is now using the Grip pose for the controller orientation, which can be acquired directly through the IUxtHandTracker interface (see IUxtHandTracker::GetGripPose
).
Updated smoothing factors for Manipulator and Pinch Slider
The Smoothing
factors in the UUxtGenericManipulatorComponent
and UUxtPinchSliderComponent
have been replaced by LerpTime
properties, similar to UUxtFollowComponent
, UUxtHandConstraintComponent
, and UUxtTapToPlaceComponent
. If your manipulator or slider used a non-default smoothing factor you may want to adjust the new LerpTime
property to achieve matching behavior.
If necessary you can calculate the exact equivalent LerpTime
at 60 FPS using the formula below:
LerpTime = -1 / (60 * log(1 - exp(-Smoothing / 60)))
where log is the natural logarithm.
Here are a few values for comparison:
|Smoothing
|LerpTime
|
|---|---|
|0|0|
|0.1|0.0026|
|1|0.0041|
|10|0.0089|
|100|0.080|
Known issues
Crash in UX Tools game when leaving surface magnetism or tap to place maps
This happens only when running on device without OpenXR. It's caused by a bug in the engine (UEVR-2118) that happens after stopping an AR session with tracked geometry enabled. We expect it will be fixed in the next UE4 release (4.26.3 or 4.27).
Full change list
Commit | Description |
---|---|
5e5d84b8e | Update README and release notes for 0.12.x |
5c48e6f6b | Fix handmenu scale warning |
d3e820019 | Enable XRSimulation to be built on Hololens and Android |
9c5858950 | Workaround for resetting on tracking loss. |
0dd33d5fd | Update to 4.26.2 |
9b69367d3 | Apply workaround for WMR grip pose not applying world scale |
b6a01919d | Adding option (default) to not instance tick marks on sliders. |
964b13b51 | Mention the broken smoothing at low FPS for manipulator and pinch slider as a known issue |
b46c04485 | Restrict Bounds Control's grab target component to one-handed |
3c8141568 | Fix BoundsControl's release notes |
594109019 | Fix for Tooltip Desc Grammer |
7ee136cf8 | Feature panel button for toggling AR surface mesh display |
8560ddaeb | Ensure LerpAmount in TapToPlace does not exceed 1 |
4fa650614 | Minor change to to the hand's fresnel material. |
17786d51a | Fix near interaction in scenes with "Collision for Mesh Data" enabled |
b8d47e5ac | Fix TapToPlace object orientation |
dfb8e77a0 | Stabilize the grip pose from input sim to avoid movement when grabbing objects. |
b967855a6 | Fix manipulation started notification PR |
59fbf430f | Add AffordanceConfig assets without the constrained affordances |
b77219caf | Add manipulation started notification |
239a98deb | Adding extra checks to FUXToolsEditorModule::ShutdownModule. |
ffb88ce24 | Use lower case for anchors in docs. |
12b9709d6 | Move XRSimulation parts out of the UxtDefaultHandTrackerSubsystem. |
59318194c | Added 'OnValueUpdated' event to slider actor |
8b19a2562 | Add breaking change note about the use of input sim in the WMR plugin. |
1808bb3ef | Button example map had stale menu BP property override, needed BP recompile. |
5a7a1f914 | Increment plugin versions to 0.12.x |
b6955100c | Replace face handle meshes |
336bb8cf1 | Fix clang formatting error. |
ad0a4a433 | Replace WMR hand tracking with new XRTrackingSystem APIs |
2b4829a52 | Adding new banners from Emily. |
b32ba809d | Changing the AUxtBasePressableButtonActor button component to readonly. |
63b22b93f | Enable text input in Widgets example scene |
74ba46a0e | Make MinMaxScaleConstraint implicit |
61b7eca05 | Text Formatting Docs |
1bd66c704 | Add checks when calling GetOwner to handle cases where a component owner is null |
bd6d6cf5c | Added videos section to README with link to Inside Unreal talk |
36185ada3 | Fix BoundsControl's face affordances |
44249b2cd | Rewrite RotationAxisConstraint |
44524b64c | RecoverySpeed Units Documentation |
3d484a777 | Generate API Reference as markdown |
b45137eae | Fix the map reference for the loader map in packaging settings. |
a5f2950cb | Remove location offsets from Slate2D's bounded meshes |
8226b7483 | Add push to GitHub at the end of CI pipeline |
8d874b2a0 | Fix-up example assets to allow UXToolsGame enable Blueprint nativization |
bdd0e3721 | Increasing the Proximity_Far_Radius from 16 to 40 |
b5e418b14 | Spline jitter fix: adding billboarding pivot to tooltip actor |
a90c8d8cc | Update Unreal Editor version to 4.26.1 |
6ce10682e | Scale BoundsControl's affordances |
4c9ab1fe4 | Manipulation constraint picker |
a826eb1fb | TouchableVolume improvements |
050be5bcb | Update Release Notes |
b10c2af97 | Add BoundsOverride to BoundsControl |
43acdf9b3 | Remove the UxtHandTrackingFunctionLibrary |
2d730a801 | Add MaintainOrientation mode to TapToPlace component |
ce09134f2 | Change MinMaxScaleConstraint to be relative to initial scale by default |
2ea6499ac | Pipeline for generating shipping builds of UXToolsGame |
35e4d68e9 | Add Button and Follow component automation test |
471fe1bc5 | Ensuring packaged builds are in the shipping config. |
bb6008e3c | Reposition BP for example levels |