Compare commits

...
67 Commits
Author SHA1 Message Date
Mamadou Babaei a2cee0762d bump the plugin version to v2.7.1 2025-12-09 13:56:11 +01:00
Mamadou Babaei 0d7c37a5fb work around a panick during handbook's pdf generation 2025-12-09 13:56:10 +01:00
Mamadou Babaei fd495d00e8 work around a ue 5.5 regression (UE-212224) while sensecom is running and gloves are connected 2025-12-09 13:25:22 +01:00
Mamadou Babaei d7e61f63e1 bump the plugin version to v2.7.0 2025-11-18 04:09:38 +01:00
Mamadou Babaei eb56601297 fix a runuat build issues on ue 5.4 2025-11-18 04:09:38 +01:00
Mamadou Babaei f639bf6957 add a new android deployment third-party tutorial for ue 5.7 2025-11-18 03:23:25 +01:00
Mamadou Babaei 810d5a7477 list ue 5.7 in the sgum-packager configuration file and update ndk paths for ue 5.6.1 2025-11-18 03:23:25 +01:00
Mamadou Babaei 94d910bc34 update the platform support matrix to refelect the latest support status 2025-11-18 03:23:25 +01:00
Mamadou Babaei b82bae52c6 add htc standalone mode deprecation warnings to the upcoming v2.7.x changelog and the relevant htc standalone mode sections in the docs 2025-11-18 03:23:25 +01:00
Mamadou Babaei fbd732b043 keep removed 5.7 changes inside SGXRTracker implementation file conditionally, in order to reduce maintenance burden 2025-11-18 03:23:25 +01:00
Mamadou Babaei fa0ff6704c revert offloading senseglove glove data retrieval api calls to timers and restore calls from tickcomponent functions 2025-11-18 03:23:25 +01:00
Mamadou Babaei 88cc8411c0 Revert "get rid of SGPawn::Tick, introduce SGPawn::HandVelocitySamplerFramerate, and make hand velocity sampler timer-based instead of tick-based"
This reverts commit 8dea65ed40.
2025-11-18 03:23:24 +01:00
Mamadou Babaei 93e8e7878b remove support for FXRMotionControllerData on UE 5.7 as it has been obliterated by the upstream and apply necessary changes to make XR_EXT_hand_tracking work again on 5.7 2025-11-18 03:23:24 +01:00
Mamadou Babaei 2a51d58f05 bump senseglove libraries to v2.305.3-17a820b6e with support for Android NDK r27c and Epic Native/Cross Toolchains v26 2025-11-18 03:23:24 +01:00
Mamadou Babaei a2f1ce5eed set default VibrotactileFrequency to 180 for optimal vibrotactile feedback 2025-11-18 03:23:22 +01:00
Mamadou Babaei 3e11112405 bump senseglove libraries to v2.304.1-fb2a464d6 2025-11-18 03:23:21 +01:00
Mamadou Babaei 9ab8f380d0 bump senseglove libraries to v2.304.0-ebcb93fc1 2025-11-18 03:23:20 +01:00
Mamadou Babaei 7eebf3eded replace QueueVibroLevels with SendCustomWaveform 2025-11-18 03:23:20 +01:00
Mamadou Babaei 9340fa293c whitespace fix 2025-11-18 03:23:20 +01:00
Mamadou Babaei 5b4139878c avoid calling senseglove glove data retrieval api from tickcomponent functions and instead offload those to background timers 2025-11-18 03:23:20 +01:00
Mamadou Babaei bbb1699fe2 return when ensure statements fail 2025-11-18 03:23:20 +01:00
Mamadou Babaei 7d44a4b373 get rid of SGPawn::Tick, introduce SGPawn::HandVelocitySamplerFramerate, and make hand velocity sampler timer-based instead of tick-based 2025-11-18 03:23:20 +01:00
Mamadou Babaei 49a5bbc8e7 rename FSGGloveTrackingSettings::GloveConnectivityCheckInterval to FSGGloveTrackingSettings::DataRetrievalRefreshRate 2025-11-18 03:23:20 +01:00
Mamadou Babaei 3056314579 apply third-party modules fixes 2025-11-18 03:23:20 +01:00
Mamadou Babaei 83a20f038d bump senseglove libraries to v2.303.0-4a2a57376 2025-11-18 03:23:19 +01:00
Mamadou Babaei 4d8a5df225 integrate sensglove libraries v2.301.0-c70bce637 and the required refactor to make it build/work 2025-11-18 03:23:17 +01:00
Mamadou Babaei a99ae9badd drop ue 5.3 and msvc 2019 support and bump the senseglove libraries to v2.205.1-cb26979ed 2025-11-18 03:23:15 +01:00
Mamadou Babaei 6b05868cbc remove remnants of the long-removed Unreal Engine 5.2 from various *.Build.cs files 2025-11-18 03:23:14 +01:00
Mamadou Babaei 5c903fe0dd remove remnants of the long-removed Unreal Engine 5.2 from SenseGloveTracking module 2025-11-18 03:23:14 +01:00
Mamadou Babaei 90805084ec remove remnants of long removed unreal 5.2 from third-party modules *.Build.cs files 2025-11-18 03:23:03 +01:00
Mamadou Babaei f6094122de re-add Source/ThirdParty/**/*.Build.cs to get tracked under git rather than lfs 2025-11-18 03:21:28 +01:00
Mamadou Babaei 892398050f delete Source/ThirdParty/**/*.Build.cs from lfs 2025-11-18 03:21:28 +01:00
Mamadou Babaei 524aa1cd4e bump the plugin version to v2.6.3 2025-06-27 18:34:23 +02:00
Mamadou Babaei 602f8b4470 add third-party openxr integration documentation section 2025-06-27 18:34:23 +02:00
Mamadou Babaei 519e00755c bump the plugin version to v2.6.2 2025-06-10 09:13:47 +02:00
Mamadou Babaei b32491811d add a vr optimization third-party tutorial 2025-06-10 09:13:47 +02:00
Mamadou Babaei 516d246793 bump the plugin version to v2.6.1 2025-06-05 13:20:13 +02:00
Mamadou Babaei 7fb4c7b5eb changelog fixes 2025-06-05 12:38:32 +02:00
Mamadou Babaei 4009892861 bump senseglove libraries to v2.204.0-3a37b1977 2025-06-05 12:38:31 +02:00
Mamadou Babaei f540872fa3 fix a changelog typo 2025-06-05 12:38:29 +02:00
Mamadou Babaei 538f99712b bump the plugin version to v2.6.0 2025-06-04 02:33:17 +02:00
Mamadou Babaei b3ccc1f274 fix a runuat build issue due to a missing header providing engine version macros 2025-06-04 02:33:17 +02:00
Mamadou Babaei caa08eb94d deprecate ue 5.3 support 2025-06-04 02:23:58 +02:00
Mamadou Babaei 1e9ea621f7 reoder changelog's last entry sections 2025-06-04 02:23:58 +02:00
Mamadou Babaei b9f2d01982 revamp the ubt third-party dependency system 2025-06-04 02:23:58 +02:00
Mamadou Babaei 5907d5bb41 fix build issue with sgbackend by deleting the impl struct copy constructor and copy assignment operator 2025-06-04 02:23:58 +02:00
Mamadou Babaei f502ee2cb9 fix a closing #endif directive comment 2025-06-04 02:23:58 +02:00
Mamadou Babaei 77d0b4858b minor code formatting fix 2025-06-04 02:23:58 +02:00
Mamadou Babaei fb1ae5a3e9 thread-safe sgbackend initialization 2025-06-04 02:23:58 +02:00
Mamadou Babaei 076a07bc7b thread-safe sglog initialization 2025-06-04 02:23:58 +02:00
Mamadou Babaei 9682585c00 revamp sglog to use unreal's tuniqueptr instead of std::unique_ptr 2025-06-04 02:23:58 +02:00
Mamadou Babaei 73957cfe66 fix critical deadlock between render and game threads in UE 5.6 when invoking IHeadMountedDisplay::GetHMDMonitorInfo() 2025-06-04 02:23:58 +02:00
Mamadou Babaei 48248eecc2 fix sglog windows/msvc build issues caused by the recent sglog refactor 2025-06-04 02:23:58 +02:00
Mamadou Babaei b324258683 update the changelog 2025-06-04 02:23:58 +02:00
Mamadou Babaei b074067667 add a missing header that causes build issues on linux aarch64 due to incomplete uaniminstance type 2025-06-04 02:23:58 +02:00
Mamadou Babaei 4db754109a fix type conversion safety and consistency issues across all sglog formatters 2025-06-04 02:23:58 +02:00
Mamadou Babaei 2981ab4670 fix unreal engine 5.6 string conversion build issues on linux 2025-06-04 02:23:57 +02:00
Mamadou Babaei 304a735e10 Revert "bump embedded winpython distribution to v3.12.10"
This reverts commit 4fe067cf9a.
2025-06-04 02:23:57 +02:00
Mamadou Babaei 2808e0f991 Revert "attempt at fixing handbook's broken make pack on windows by upgrading mdbook-pdf-outline"
This reverts commit 1be45f2cba.
2025-06-04 02:23:55 +02:00
Mamadou Babaei 33c661df43 attempt at fixing handbook's broken make pack on windows by upgrading mdbook-pdf-outline 2025-06-04 02:23:55 +02:00
Mamadou Babaei 0eaa936cb1 bump the SenseGlove Unreal Engine Marketplace Packager to v0.6.0-4108c6f 2025-06-04 02:23:55 +02:00
Mamadou Babaei 1ff40e1a9c bump senseglove libraries to v2.203.0-f3d3e676 which migrates to C++20 2025-06-04 02:23:54 +02:00
Mamadou Babaei 51651d3996 bump embedded winpython distribution to v3.12.10 2025-06-04 02:23:52 +02:00
Mamadou Babaei ffb9f52329 lock the mdbook crate version to v0.49.0 2025-06-04 02:23:50 +02:00
Mamadou Babaei 46e4786b4a bump senseglove libraries to v2.202.0-5d54da32 which fixes linux build issues for ue 5.5/5.6 by linking against libc++ instead of libstdc++ 2025-06-04 02:23:50 +02:00
Mamadou Babaei 0f45c30935 update the outdated directory structure section inside the handbook with the latest changes 2025-06-04 02:23:48 +02:00
Mamadou Babaei ee06a344ae bump the senseglove libraries to libraries to v2.201.0-edef7655 and replace epic native toolchain v24 with v25 2025-06-04 02:23:47 +02:00
3973 changed files with 4559 additions and 12148 deletions
+3 -1
View File
@@ -38,6 +38,8 @@ Resources/**/* filter=lfs diff=lfs merge=lfs -text
# LFS: everything under Source/ThirdParty/ # LFS: everything under Source/ThirdParty/
Source/ThirdParty/**/* filter=lfs diff=lfs merge=lfs -text Source/ThirdParty/**/* filter=lfs diff=lfs merge=lfs -text
# Except
Source/ThirdParty/**/*.Build.cs filter= diff= merge= text
# LFS: everything under Handbook/dist/ # LFS: everything under Handbook/dist/
Handbook/dist/**/* filter=lfs diff=lfs merge=lfs -text Handbook/dist/**/* filter=lfs diff=lfs merge=lfs -text
@@ -47,4 +49,4 @@ Handbook/dist/**/* filter=lfs diff=lfs merge=lfs -text
# LFS: sgum-packager Linux and Windows binaries # LFS: sgum-packager Linux and Windows binaries
Packager/sgum-packager filter=lfs diff=lfs merge=lfs -text Packager/sgum-packager filter=lfs diff=lfs merge=lfs -text
Packager/sgum-packager.exe filter=lfs diff=lfs merge=lfs -text Packager/sgum-packager.exe filter=lfs diff=lfs merge=lfs -text
+2 -2
View File
@@ -365,10 +365,10 @@ clean:
.PHONY: install-build-deps .PHONY: install-build-deps
install-build-deps: install-build-deps:
@echo "Installing build dependencies if they have not already been installed..." @echo "Installing build dependencies if they have not already been installed..."
@cargo install mdbook --vers "^0.4" --locked @cargo install mdbook --version "0.4.49" --locked
@cargo install xq --vers "^0.4" --locked @cargo install xq --vers "^0.4" --locked
@cargo install mdbook-alerts --vers "^0.7" --locked @cargo install mdbook-alerts --vers "^0.7" --locked
@cargo install mdbook-pdf --vers "^0.1" --locked @cargo install mdbook-pdf --vers "0.1.11" --locked
ifeq ($(SG_BUILD_PLATFORM),$(SG_BUILD_PLATFORM_LINUX)) ifeq ($(SG_BUILD_PLATFORM),$(SG_BUILD_PLATFORM_LINUX))
@echo "Installing mdbook-pdf-outline..." @echo "Installing mdbook-pdf-outline..."
@python -m venv $(VIRTUAL_ENV) \ @python -m venv $(VIRTUAL_ENV) \
+4
View File
@@ -68,6 +68,7 @@ Welcom to the SenseGlove Unreal Engine Handbook!
- [Third-Party Tutorials](misc/android-standalone-deployment/third-party-tutorials/README.md) - [Third-Party Tutorials](misc/android-standalone-deployment/third-party-tutorials/README.md)
- [Upgrade Guide](misc/upgrade-guide/README.md) - [Upgrade Guide](misc/upgrade-guide/README.md)
- [Optimizing for Higher FPS](misc/optimize-higher-fps/README.md) - [Optimizing for Higher FPS](misc/optimize-higher-fps/README.md)
- [Third-Party Tutorials](misc/optimize-higher-fps/third-party-tutorials/README.md)
# 🛠️ Advanced Topics # 🛠️ Advanced Topics
@@ -79,6 +80,7 @@ Welcom to the SenseGlove Unreal Engine Handbook!
- [Consuming FXRMotionControllerData](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/README.md) - [Consuming FXRMotionControllerData](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/README.md)
- [Blueprint](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/blueprint.md) - [Blueprint](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/blueprint.md)
- [C++](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/cpp.md) - [C++](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/cpp.md)
- [Third-Party Integrations](advanced-topics/openxr/third-party-integrations/README.md)
- [Third-Party Tutorials](advanced-topics/openxr/third-party-tutorials/README.md) - [Third-Party Tutorials](advanced-topics/openxr/third-party-tutorials/README.md)
# 🔌 Low-Level API # 🔌 Low-Level API
@@ -102,6 +104,8 @@ Welcom to the SenseGlove Unreal Engine Handbook!
- [SenseGlove SDK License](license/senseglove-sdk.md) - [SenseGlove SDK License](license/senseglove-sdk.md)
- [SGBLE and SGBLExx Rust Dependencies Licenses](license/sgble-sgblexx-rust-dependencies.md) - [SGBLE and SGBLExx Rust Dependencies Licenses](license/sgble-sgblexx-rust-dependencies.md)
- [Boost C++ Libraries License](license/boost-cpp-libraries.md) - [Boost C++ Libraries License](license/boost-cpp-libraries.md)
- [{fmt} Formatting Library License](license/fmt-formatting-library.md)
- [Loguru Logging Library License](license/loguru-loggin-library.md)
- [Serial Communication Library License](license/serial-communication-library.md) - [Serial Communication Library License](license/serial-communication-library.md)
----------- -----------
@@ -0,0 +1,265 @@
# Third-Party OpenXR Integrations
The **SenseGlove Unreal Engine Plugin** registers itself as an `OpenXRHandTracking` provider, making it a fully compatible, drop-in replacement for Epics own **OpenXRHandTracking** plugin in Unreal Engine. This allows it to integrate seamlessly with any third-party system or plugin that can consume OpenXR hand-tracking data.
One notable example is the open-source, MIT-licensed [VR Expansion Plugin (VRE)](#vr-expansion-plugin).
> [!IMPORTANT]
> As explained in the
> [Third-Party Tutorials: Consuming OpenXR Hand-Tracking Data](../third-party-tutorials/)
> section, its entirely possible to build your own custom hand interaction
> system without relying on
> [SGPawn](../../../getting-started/setup-senseglove-default-classes/sgpawn.html)
> or any third-party OpenXR-compatible interaction plugin altogether.
>
> If your project requires finer-grained control than what these solutions
> offer, the tutorials in that section will guide you through understanding the
> OpenXR hand-tracking data format in Unreal Engine and help you implement a
> fully tailored interaction system from the ground up in a few hours.
As the SenseGlove Unreal Engine Plugin is fully OpenXR-compliant, it provides OpenXR hand-tracking data in the expected format and takes over as the active provider within Unreal. If your existing interaction system (e.g. VRE plugin) already uses OpenXR hand-tracking, SenseGlove will function as a direct tracking source instead of a real hand.
> [!NOTE]
> Since most hand-tracking systems are not capable of haptics feedback,
> integrating SenseGlove's haptic feedback requires a small amount of additional
> effort.
>
> The SenseGlove API is fully exposed to Unreal Engine via C++ and Blueprint,
> so triggering haptic feedback is as simple as calling a function.
> For more information, refer to the [Blueprint Changes](#blueprint-changes)
> section below.
> [!IMPORTANT]
> If you're using a third-party OpenXR hand interaction system, configuring the
> [Wrist-Tracker Hardware Settings](../../../getting-started/setup-wrist-tracking-hardware/)
> will likely have no effect, and your hand offsets may appear at the incorrect
> location in the scene.
>
> This is because those settings are only recognized by SenseGloves native
> actors and components such as `SGPawn`, `SGWristTrackerComponent`, etc.
> Most third-party plugins are unaware of these settings. As a result, you'll
> need to figure out how to manually apply the appropriate offsets within your
> chosen OpenXR hand interaction system.
>
> For example, the VRE plugin provide similar configurations in their plugin's
> settings section. For more information refer to the
> [Changing Wrist-Tracker Offsets](#changing-wrist-tracker-offsets) section
> below.
## Comparison of Supported OpenXR Hand-Interaction Systems
| | **Built-in?** | **Works out of the box?** | **Beginner-friendly?** | **Learning Curve** | **Featureful** | **Customizable?** | **Supports Custom Gestures?** |
|-------------------------------------|---------------|------------------------------------|--------------------------------------------------|-----------------------------|--------------------------------------------------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
| **SGPawn** | ✅ Yes | ✅ Yes | ✅ Most beginer-friendly | ✅ Very easy | ⚠️ Very basic | ⚠️ Very limited | ❌ Not yet, maybe added in the future |
| **SenseGlove OpenXR** | ✅ Yes | ❌ Requires Blueprint or C++ coding | ✅ Requires a few hours of watching tutotrials | ✅ Moderate | ❌ You need to develop your own features and functionalities from scratch | ✅ Your imagination, creativity, and skill level are your limits | ✅ You have to implement your own recognition logic; example pinch detection algorithm is taught in the tutorial series |
| **VR Expansion Plugin** | ❌ No | ⚠️ Partially requires setup | ❌ Best suited for intermediate or advanced users | ⚠️ Steep | ✅ Diverse features and functionalities | ✅ Highly customizable | ✅ Via custom logic |
| **Other OpenXR-compatible Plugins** | ❌ No | ❓ Check their documentation | ❓ Check their documentation | ❓ Check their documentation | ❓ Check their documentation | ❓ Check their documentation | ❓ Check their documentation |
## VR Expansion Plugin
The [**VR Expansion Plugin (VRE)**](https://vreue4.com/) is a robust, community-driven plugin for Unreal Engine that focuses on advanced VR interaction and gameplay mechanics. It is open-source (MIT licensed), actively maintained, and has received support from Epic via the [MegaGrants program](https://www.unrealengine.com/en-US/megagrants).
Designed to extend Unreals capabilities for virtual reality, VRE offers a modular set of tools covering:
- Multiplayer and networking
- Locomotion systems
- Object gripping and interaction
- Custom movement and physics handling
The plugin is particularly useful for teams building sophisticated VR experiences. While it's beginner-friendly to an extent, its depth and flexibility are **best suited for intermediate to advanced Unreal Engine developers**. Whether you're prototyping with built-in features or extracting specific systems for your own framework, VRE offers a rich foundation for VR development.
> [!NOTE]
> For support and assistance with the VRE plugin, you can join
> [its active and welcoming Discord community](https://discord.gg/P4V7TY8BQy),
> known for being responsive and supportive.
### SGVRETemplate Demo Scene
To showcase how SenseGlove can be integrated with OpenXR-compatible third-party interaction systems, SenseGlove provides a ready-to-use [VR Expansion Plugin Integration Demo for Unreal Engine 5.4](https://dev.azure.com/SenseGlove/_git/SGVRETemplate).
This repository includes UE `5.4`compatible versions of both the **SenseGlove** and **VR Expansion** plugins, with all necessary setup and configuration already in place. Simply download the project and it should run out of the box, allowing you to explore the integration without additional setup.
> [!NOTE]
> SenseGlove provides this demo to demonstrate the potential for integrating
> with third-party OpenXR-based hand interaction systems.
> Please note that the **VR Expansion Plugin** is a third-party solution, and as
> such, **we do not offer official support for it**.
>
> For help with the VRE plugin, refer to its documentation at
> [**vreue4.com**](https://vreue4.com/) and consider joining the
> [**official VRE Discord community**](https://discord.gg/P4V7TY8BQy),
> which is active, supportive, and very responsive.
### SGVRETemplate Modifications
The [**SGVRETemplate**](https://dev.azure.com/SenseGlove/_git/SGVRETemplate) is built on top of the [VR Expansion Plugin Example Template](https://github.com/mordentral/VRExpPluginExample). However, since the original template is not directly compatible with SenseGlove, several adjustments were necessary.
In addition, a few known issues with OpenXR support in the VR Expansion Plugin for Unreal Engine `5.4` required us to modify the plugin itself to ensure smooth integration.
Below is an overview of the key modifications made to both the project template and this version of the VRE plugin.
#### Blueprint Changes
- **Content/VRE/Core/Character/BP_VRCharacter**: Four functions were added: `SendVibration`, `SendFFB`, `SendSqueeze`, and `ResetHaptics`. These functions retrieve the glove instance and send the appropriate haptic command to it. In the `OnPossessed` event, `Load Controller by Name` was added along with a string uproperty `Tracking Offset`, which is used to load the correct tracking offsets based on the selected profile.
> [!NOTE]
> If you'd like to implement your own haptic functions, the most convenient
> approach is to
> [safely acquire a glove instance](../../../advanced-topics/safe-glove-access-blueprint/).
> Once you have the glove instance, applying haptic feedback is as simple as
> calling the appropriate function.
>
> SenseGlove supports three types of haptics: Vibrations, Force-feedback, and
> Wrist-squeeze.
>
> - Using `Send Custom Waveform`, you can send vibrations to the glove instance.
> - Using `Queue Command Force Feedback Levels`, you can send force-feedback.
> - Using `Queue Command Wrist Squeeze`, you can send a wrist-squeeze command to
> the glove.
>
> Each of these functions can be called directly on the glove instance to
> trigger the desired haptic feedback.
- **Content/VRE/Core/GraspingHands/GraspingHandManny**: In the `SetupFingerAnimations` function, replace the hardcoded check for `HandType == Left` with a string comparison: convert the enum to a string and check if it contains `"Left"`. This allows compatibility with alternative tracking sources such as `"Left Foot"`.
#### C++ Changes
- **Plugins/VRExpansionPlugin/Source/VRExpansionPlugin/Public/Grippables/HandSocketComponent.h**: The following line was added as a public `UPROPERTY` in the header file:
```cpp
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Animation")
float HandAnimationProgress = 0.0f;
```
- **Plugins/VRExpansionPlugin/Source/VRExpansionPlugin/Private/Grippables/HandSocketComponent.cpp**: In the function `bool UHandSocketComponent::GetBlendedPoseSnapShot(FPoseSnapshot& PoseSnapShot, USkeletalMeshComponent* TargetMesh, bool bSkipRootBone, bool bFlipHand)`, the `TrackLocation` calculation was modified from:
```cpp
if (TrackIndex != INDEX_NONE && (!bSkipRootBone || TrackIndex != 0))
{
double TrackLocation = 0.0f;
HandTargetAnimation->GetBoneTransform(LocalTransform, FSkeletonPoseBoneIndex(TrackMap[TrackIndex].BoneTreeIndex), TrackLocation, false);
}
else
{
```
To:
```cpp
if (TrackIndex != INDEX_NONE && (!bSkipRootBone || TrackIndex != 0))
{
double TrackLocation = HandTargetAnimation->GetPlayLength() * HandAnimationProgress;
HandTargetAnimation->GetBoneTransform(LocalTransform, FSkeletonPoseBoneIndex(TrackMap[TrackIndex].BoneTreeIndex), TrackLocation, false);
}
else
{
```
- **Plugins/VRExpansionPlugin/Source/VRExpansionPlugin/Private/GripMotionControllerComponent.cpp**: In the function `void UGripMotionControllerComponent::GetCurrentProfileTransform(bool bBindToNoticationDelegate)`, the following logic was updated from:
```cpp
if (HandType == EControllerHand::Left || HandType == EControllerHand::AnyHand || !VRSettings->bUseSeperateHandTransforms)
{
NewControllerProfileTransform = VRSettings->CurrentControllerProfileTransform;
}
else if (HandType == EControllerHand::Right)
{
NewControllerProfileTransform = VRSettings->CurrentControllerProfileTransformRight;
}
```
To:
```cpp
if (UEnum::GetDisplayValueAsText(HandType).ToString().Contains("Left") || HandType == EControllerHand::AnyHand || !VRSettings->bUseSeperateHandTransforms)
{
NewControllerProfileTransform = VRSettings->CurrentControllerProfileTransform;
}
else if (UEnum::GetDisplayValueAsText(HandType).ToString().Contains("Right"))
{
NewControllerProfileTransform = VRSettings->CurrentControllerProfileTransformRight;
}
```
The following function was also updated; from:
```cpp
void UGripMotionControllerComponent::GetHandType(EControllerHand& Hand)
{
if (!IMotionController::GetHandEnumForSourceName(MotionSource, Hand))
{
// Check if the palm motion source extension is being used
// I assume eventually epic will handle this case
if (MotionSource.Compare(FName(TEXT("RightPalm"))) == 0 || MotionSource.Compare(FName(TEXT("RightWrist"))) == 0)
{
Hand = EControllerHand::Right;
}
// Could skip this and default to left now but would rather check
else if (MotionSource.Compare(FName(TEXT("LeftPalm"))) == 0 || MotionSource.Compare(FName(TEXT("LeftWrist"))) == 0)
{
Hand = EControllerHand::Left;
}
else
{
Hand = EControllerHand::Left;
}
}
}
```
To:
```cpp
void UGripMotionControllerComponent::GetHandType(EControllerHand& Hand)
{
if (!IMotionController::GetHandEnumForSourceName(MotionSource, Hand))
{
// Check if the palm motion source extension is being used
// I assume eventually epic will handle this case
if (MotionSource.Compare(FName(TEXT("RightPalm"))) == 0 || MotionSource.Compare(FName(TEXT("RightWrist"))) == 0 || MotionSource.ToString().Contains("Right"))
{
Hand = EControllerHand::Right;
}
// Could skip this and default to left now but would rather check
else if (MotionSource.Compare(FName(TEXT("LeftPalm"))) == 0 || MotionSource.Compare(FName(TEXT("LeftWrist"))) == 0 || MotionSource.ToString().Contains("Left"))
{
Hand = EControllerHand::Left;
}
else
{
Hand = EControllerHand::Left;
}
}
}
```
#### Changing Wrist-Tracker Offsets
If you are using wrist-tracking hardware supported by the SenseGlove plugin, you can change the offsets inside `BP_VRCharacter` using the uproperty `Tracking Offset` typing or copying any of the following, depending on your hardware:
- **SenseGlove_Quest3**: The wrist-tracking controller profile for for Meta Quest3.
- **SenseGlove_ViveWristTrackers**: The wrist-tracking controller profile for HTC VIVE wrist trackers.
#### Changing Motion Source
In `BP_VRCharacter`, you can change the wrist-tracking motion source for each hand. This is required depending on which tracker you are using.
#### Adding More Gestures
In the `GraspingHandManny` Blueprint, weve created a simple function called `SaveHandPose`. If you press the `Space Bar` while the game is running, it will save the current pose of the corresponding hand. The pose is stored in a gestures database located under `Content/SenseGlove` with the default name `NewHandPose`. You should rename the pose to something meaningful when you intend to use it.
Its helpful to add an Event Dispatcher to the `GraspingHandManny` Blueprint, which is triggered in the Event Graph by the `On New Gesture Detected` event from the `OpenXRHandPose` component. This system is index-based rather than name-based, so keep that in mind when adding more dispatchers. By default, weve included examples for `Teleport`, `Grab`, `Release`, and `Use`.
#### Video Summary
This short video provides an overview of some of the key changes and modifications behind the SGVRETemplate demo scene, mentioned above.
<div style="margin: 0 auto; width: 560px;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/6uTu4T10mjU" frameborder="0" allowfullscreen></iframe>
</div>
### SGVRETemplate Demo Calibration Scene
The SGVRETemplate includes a basic Calibration Scene located at `Content/SenseGlove/Maps/Calibration`. Inside this level, youll find a copy of `Content/SenseGlove/Blueprints/Calibration/BP_Calibrator` Blueprint responsible for transitioning to your desired target map after the calibration process is complete. You can configure the target map directly within this Blueprint by adjusting the `Level to Load` uproperty.
+175 -1
View File
@@ -5,6 +5,180 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.7.1] - 2025-12-09
This patch release addresses a severe regression affecting UE `5.5` projects with specific settings.
### Fixed
- Resolved a critical deadlock between the rendering and game threads in Unreal Engine `5.5` that when `IHeadMountedDisplay::GetHMDMonitorInfo()` is invoked from `FSGXRTracker::GetControllerTransform()` in certain conditions; specifically while SenseCom is running and gloves are present and connected. This issue is [related to critical deadlock issue (UE-212224), occurring during PipelinedFrameState acquisition, which had already been addressed for the plugin versions running on UE `5.6+`](#260---2025-06-04). Because it only gets triggered under specific project settings, we were previously unaware that it also affected IHeadMountedDisplay::GetHMDMonitorInfo() in UE 5.5.
### Documentation
- Locked the [mdbook-pdf](https://github.com/HollowMan6/mdbook-pdf) crate to [`v0.1.11`](https://github.com/HollowMan6/mdbook-pdf/releases/tag/v0.1.11) due to the following `v0.1.12` panick during PDF generation: called `Result::unwrap()` on an `Err` value: Unable to deserialize the `RenderContext`.
## [2.7.0] - 2025-11-18
This minor release focuses on delivering performance improvements, made possible by major optimizations in the underlying proprietary SenseGlove libraries, while also introducing some breaking changes.
### Added
- Added support for UE `5.7`.
- Added support for Android NDK `r27c`, which is the recommend Android SDK since UE `5.6.1` and the default for UE `5.7+` for Android Standalone builds.
- Added support for Epic Cross and Native Toolchains `v26`, which is shipped with the UE `5.7` and GNU/Linux support.
- Added prebuilt binaries for third-party library [{fmt} Formatting Library](https://github.com/fmtlib/fmt) on all supported platforms. This third-party library is a required dependency of SenseGlove libraries >= `v2.300.0`.
- Added prebuilt binaries for third-party library: [Loguru Logging Library](https://github.com/emilk/loguru) on all supported platforms. This third-party library is a required dependency of SenseGlove libraries >= `v2.300.0`.
- Added third-party module `SGCommonThirdPartyLibs`.
- Added third-party module `SGConnectShmThirdPartyLibs`.
- Added third-party module `SGCoreShmThirdPartyLibs`.
- Added third-party module `SGCoreThirdPartyHeaders`.
- Added third-party module `SGFmtThirdPartyLibs`.
- Added third-party module `SGLogThirdPartyLibs`.
- Added third-party module `SGLoguruThirdPartyLibs`.
- Added third-party module `SGWjwwoodSerialThirdPartyLibs` to replace `SGSerialThirdPartyLibs` while retaining `SGSerialThirdPartyLibs` for a different purpose. See the relevant comment in the Changed section below.
- Added UPROPERTY `USGTouchComponent::VibrotactileAmplitude`.
- Added UPROPERTY `USGTouchComponent::VibrotactileFrequency`.
- Added method `USGTouchComponent::GetVibrotactileAmplitude()`.
- Added method `USGTouchComponent::SetVibrotactileAmplitude()`.
- Added method `USGTouchComponent::GetVibrotactileFrequency()`.
- Added method `USGTouchComponent::SetVibrotactileFrequency()`.
- Added Blueprint-accessible method `USGTouchComponentKismetLibrary::GetVibrotactileAmplitude()`.
- Added Blueprint-accessible method `USGTouchComponentKismetLibrary::SetVibrotactileAmplitude()`.
- Added Blueprint-accessible method `USGTouchComponentKismetLibrary::GetVibrotactileFrequency()`.
- Added Blueprint-accessible method `USGTouchComponentKismetLibrary::SetVibrotactileFrequency()`.
### Fixed
- Fix a typo in the function name `SGDeviceList::SenseCommRunning()`. This fix breaks ABI and API compatibility with previous versions of the plugin and affects both C++ and Blueprint code.
### Changed
- `SGDeviceList::SenseCommRunning()` has been renamed to `SGDeviceList::SenseComRunning()` due to a typo. This change breaks ABI and API compatibility with previous versions of the plugin and affects both C++ and Blueprint code.
- Bumped the SenseGlove libraries to `v2.305.3-17a820b6e`. This release of the SenseGlove libraries disables RTTI/Exceptions for the most parts and isolates it to a minor portion of the code base, which yields noticable performance gains. Futhermore, some optiomizations are done in the multi-threaded code, such as replacing Spinlocks with Adaptive Mutexes (a hybrid Mutex/Spinlock).
- As a result of SenseGlove libraries >= `v2.300.0` changing it's directory structure, the `ThirdParty` folder's directory structure has been revamped.
- Renamed third-party module `SGSerialThirdPartyLibs` to `SGWjwwoodSerialThirdPartyLibs` since SenseGlove libraries >= `v2.300.0` ships a new static library named `sgserial`. Thus, to avoid confusion and naming conflicts the third-party `serial` static library is now provided by the `SGWjwwoodSerialThirdPartyLibs` module and `sgserial` is provided by the `SGSerialThirdPartyLibs` module.
- `FSGGloveTrackingSettings::GloveConnectivityCheckInterval` settings have been renamed to `FSGGloveTrackingSettings::DataRetrievalRefreshRate` for adoption other than glove connectivity use cases.
- `USGVirtualHandComponent::GetMotionControllerData()` signature has changed.
- `USGVirtualHandComponent::GetHandTrackingState()` signature has changed.
- `USGWristTrackerComponent::GetMotionControllerData()` signature has changed.
- `USGWristTrackerComponent::GetHandTrackingState()` signature has changed.
- `USGVirtualHandComponentKismetLibrary::GetMotionControllerData()` signature has changed.
- `USGVirtualHandComponentKismetLibrary::GetHandTrackingState()` signature has changed.
- `SGPawn` and `SGTouchComponent` no longer use the legacy `QueueVibroLevels` method for applying vibrotactile feedback. Instead it's been replaced with `SendCustomWaveform`.
- Changed `USGTouchComponent::VibrotactileDuration` UPROPERTY's maximum value to `1.0f`. Previously it was uncapped, and now any value beyond `1.0f` seconds is clamped.
### Removed
- Dropped support for Unreal Engine `5.3`, which was already deprecated in the `v2.6.x` release series.
- Dropped support for MSVC `v142` (Visual Studio 2019), since UE `5.3` was the last supported version relying on it.
- Cleaned up remnants of the long-removed Unreal Engine `5.2` from third-party module `*.Build.cs` files.
- Cleaned up remnants of the long-removed Unreal Engine `5.2` from `SenseGlove.Build.cs`, `SenseGloveKismet.Build.cs`, `SenseGloveTracking.Build.cs`, files.
- Cleaned up remnants of the long-removed Unreal Engine `5.2` from `SenseGloveTracking` module.
- `USGVirtualHandComponent::GetMotionControllerState()` has been removed.
- `USGWristTrackerComponent::GetMotionControllerState()` has been removed.
- `USGVirtualHandComponentKismetLibrary::GetMotionControllerState()` has been removed.
- `USGWristTrackerComponentKismetLibrary::GetMotionControllerState()` has been removed.
- `USGTouchComponent::VibrotactileLevel` UPROPERTY has been removed.
- `USGTouchComponent::GetVibrotactileLevel()` method has been removed.
- `USGTouchComponent::SetVibrotactileLevel()` method has been removed.
- `USGTouchComponentKismetLibrary::GetVibrotactileLevel()` method has been removed and is no longer available to Blueprint.
- `USGTouchComponentKismetLibrary::SetVibrotactileLevel()` method has been removed and is no longer available to Blueprint.
### Deprecated
- **This is the last major/minor release to support Unreal Engine `5.4`**, and its support will be removed in future minor or major releases. This is **important to keep in mind if your target development and deployment platform is [HTC VIVE in Standalone Mode](../getting-started/enabling-xr-ext-hand-tracking-vr-headsets/standalone-mode/index.html#htc-vive)**. Unfortunately, HTC has not released any updates to their HTC ViveOpenXR plugin since December 6, 2024. Their [latest release](https://developer.vive.com/resources/openxr/unreal/unreal-download/latest/) [[1]](https://web.archive.org/web/20251113165658/https://developer.vive.com/resources/openxr/unreal/unreal-download/latest/) [[2]](https://archive.ph/DlrLr), ViveOpenXR Plugin `v2.5.0`, supports only Unreal Engine `5.3` and `5.4`. [HTC VIVE PCVR Mode](../getting-started/enabling-xr-ext-hand-tracking-vr-headsets/pcvr-mode/index.html#htc-vive) is unaffected and will remain fully functional because, on Microsoft Windows, it is supported via the [OpenXRViveTracker Plugin](../getting-started/enabling-xr-ext-hand-tracking-vr-headsets/pcvr-mode/index.html#openxrvivetracker-plugin), which is bundled with Unreal Engine and officially maintained by Epic Games. If you still intend to target HTC in Standalone Mode, you are welcome to continue using the latest SenseGlove Unreal Engine Plugin `v2.7.x`, which will retain HTC Standalone Mode support. However, please keep in mind that once newer versions of the SenseGlove Unreal Engine Plugin are released and UE `5.4` is no longer supported, the latest release of the plugin supporting UE `5.4` will not receive new features, hardware support, or bug fixes. If at any point in the future HTC releases a new version of their ViveOpenXR plugin that supports any Unreal Engine version we actively support, [in accordance with our support policy and Platform Support Matrix](../appendix/platform-support-matrix.html), we will make every reasonable effort to reintroduce HTC Standalone Mode support.
### Documentation
- Added [{fmt} Formatting Library License](../license/fmt-formatting-library.html) section.
- Added [Loguru Logging Library License](../license/loguru-loggin-library.html) section.
- Updated [Setting up the Touch System](../getting-started/setup-touch-system/index.html) section to reflect the recent touch system changes.
- Added [a third-party tutorial to the Android Standalone Mode Deployment](../misc/android-standalone-deployment/third-party-tutorials/) section for UE `5.7` which provides a one-click Android development and build environment setup, instructions on how to setup and use the new UE `5.7` project launcher, and how to enabled OpenXR hand-tracking support on Meta Quest and HTC VIVE devices.
## [2.6.3] - 2025-06-27
This patch release contains no changes to the plugin code. It includes only documentation updates and improvements.
### Documentation
- Added a new section to the handbook titled [Third-Party OpenXR Integrations](../advanced-topics/openxr/third-party-integrations/) section.
- Additional minor fixes and improvements that may not be listed here.
## [2.6.2] - 2025-06-10
This patch release contains no changes to the plugin code. It includes only documentation updates and improvements.
### Documentation
- Added [a third-party tutorial to the Optimizing Your Project for Higher FPS](../misc/optimize-higher-fps/third-party-tutorials/) section.
## [2.6.1] - 2025-06-05
This patch release addresses several critical build and linking issues.
### Fixed
- Fix a linking issue on GNU/Linux with UE `5.6` where SenseGlove libraries were built against dynamic versions of `libc++` and `libc++abi` libraries rather than the static versions.
- Fix an issue where SenseGlove libraries for some targets were not actually built with `C++20` and still were built against `C++17`.
- Fix an issue where SenseGlove libraries for some targets were built or linked with incorrect settings.
- Additional minor fixes and improvements that may not be listed here.
### Changed
- Bumped the SenseGlove libraries to `v2.204.0-3a37b1977`.
### Removed
- SenseGlove plugin no longer ships Boost or wjwwood's Serial Communication Library header files as SenseGlove public headers shipped with `v2.204.0-3a37b1977` render them redundant. This significantly removes clutter, free up disk space, and speed up builds to some extent.
### Documentation
- Fix some changelog typos.
- Additional minor fixes and improvements that may not be listed here.
## [2.6.0] - 2025-06-04
This minor release delivers broad compatibility, stability, and maintainability enhancements, focusing on bringing full Unreal Engine `5.6` support, C++20 migration, and resolving various GNU/Linux build issues.
### Added
- Added support for Epic Native Toolchain `v25`, which will be shipped with the upcoming UE `5.6`.
### Fixed
- Resolved GNU/Linux build issues for Unreal Engine `5.5` and `5.6` caused by incorrect linkage to GNU/GCC's `libstdc++` instead of LLVM/Clang's `libc++`.
- Fix `SGLog` build issues on GNU/Linux with UE `5.6`.
- Fix type conversion safety and consistency issues across all `SGLog` formatters.
- Resolved a critical deadlock between the rendering and game threads in Unreal Engine `5.6` that occurrs when `IHeadMountedDisplay::GetHMDMonitorInfo()` is invoked from `FSGXRTracker::GetControllerTransform()`. This is similar to another [critical deadlock issue (UE-212224), occurring during PipelinedFrameState acquisition, addressed in the `v2.5.0` release](#250---2025-05-09).
- Additional minor fixes and improvements that may not be listed here.
### Changed
- Replaced Epic Native Toolchain `v24` support with Epic Native Toolchain `v25` due to the fact that now `v25` is the default Linux toolchain for UE `5.6`.
- Revamped `FSGHMDTracker` to resolve a critical deadlock between the rendering and game threads in Unreal Engine `5.6` that occurrs when `IHeadMountedDisplay::GetHMDMonitorInfo()` is invoked from `FSGXRTracker::GetControllerTransform()`. This is similar to another [critical deadlock issue (UE-212224), occurring during PipelinedFrameState acquisition, addressed in the `v2.5.0` release](#250---2025-05-09).
- Revamped the UBT logic for importing third-party headers and libraries by introducing third-party dependency modules, `SGBleThirdPartyLibs`, `SGConnectThirdPartyHeaders`, `SGConnectThirdPartyLibs`, `SGCoreThirdPartyLibs`, and `SGSerialThirdPartyLibs`, which significantly reduces UBT boilerplate code and increases maintainability.
- Bumped the SenseGlove libraries to `v2.203.0-f3d3e676`.
- SenseGlove libraries have migrated to `C++20` from `C++17`.
- Revamped the `SGLog` logging utility class to use `TUniquePtr` instead of `std::unique_ptr`.
- `SGLog` now relies on `TAtomic<bool>` for thread-safe initialization.
- `SGBackend` now relies on `TAtomic<bool>` for thread-safe initialization.
- `USGBackend::IsBackendInitialized()` is no longer inlined and the initialization flag has been moved to the private implementation of `USGBackend`.
- Bumped the SenseGlove Unreal Engine Marketplace Packager `v0.6.0-4108c6f`.
### Removed
- Dropped support for Epic Native Toolchain `v24`, which was last shipped with the preview release of UE `5.6`, but has been removed from the `5.6` branch on GitHub.
### Deprecated
- This is the last minor release to support Unreal Engine `5.3` and its support will be removed from the next minor or major releases.
### Documentation
- Revised the outdated [Plugin Directory Structure](./directory-structure.html) section to accurately reflect the latest changes to the `Source/ThirdParty` directory layout changes.
- Lock the [mdbook](https://github.com/rust-lang/mdBook) crate version to `v0.49.0` to avoid layout issues introduced with `v0.50.0`.
- Additional minor fixes and improvements that may not be listed here.
## [2.5.0] - 2025-05-09 ## [2.5.0] - 2025-05-09
This minor release primarily focuses on bringing Bluetooth Low Energy support to the SenseGlove Unreal Engine integration. This minor release primarily focuses on bringing Bluetooth Low Energy support to the SenseGlove Unreal Engine integration.
@@ -929,4 +1103,4 @@ This is a minor release focusing on adherence to the Unreal Engine Marketplace G
### Added ### Added
- Initial public release of the SenseGlove haptic API for Unreal Engine with support for Microsoft Windows and GNU/Linux. - Initial public release of the SenseGlove haptic API for Unreal Engine with support for Microsoft Windows and GNU/Linux.
+118 -70
View File
@@ -62,78 +62,126 @@
└── ThirdParty (3rd-party dependencies) └── ThirdParty (3rd-party dependencies)
├── android (.jar file Java libraries for Android) ├── android (.jar file Java libraries for Android)
│ │
│ ├── debug
│ │
│ └── release
├── include (header files) ├── include (header files)
│ │ │ │
── boost ── SenseGlove
│ │
├── SenseGlove ├── BLE (SGBLE headers)
├── Connect (SGConnect headers) ├── Common (SGCommon headers)
── Core (SGCoreCpp headers) ── Connect (SGConnect headers)
│ │
└── serial ├── Core (SGCore headers)
│ │
│ └── Log (SGLog headers)
── lib (platform-specific pre-built binary dependencies) ── lib (platform-specific pre-built binary dependencies)
├── android ├── android
│ │ │ │
│ └── r25b (Android NDK r25b dependencies for UE 5.1+) │ └── r25b (Android NDK r25b dependencies for UE 5.1+)
│ │ │ │
│ ├── arm64 (64-bit ARM variant of Android) │ ├── aarch64 (64-bit ARM variant of Android)
│ │ │ │ │ │
│ │ ├── debug │ │ ├── debug
│ │ │ │ │ │
│ │ └── release │ │ └── release
│ │ │ │
│ └── x64 (64-bit x86-64 variant of Android) │ └── x86-64 (64-bit x86-64 variant of Android)
│ │ │ │
│ ├── debug │ ├── debug
│ │ │ │
│ └── release │ └── release
├── linux ├── linux
│ │ │ │
│ ├── v21 (UE 5.2 Linux dependencies) │ ├── rustc (GNU/Linux binary dependencies built with Rust)
│ │ │ │ │ │
│ │ ├── aarch64 (dependencies targeting AArch64 Linux architecture) │ │ ├── aarch64 (dependencies targeting GNU/Linux AArch64 architecture)
│ │ │ │ │ │ │ │
│ │ │ ├── debug │ │ │ ├── debug
│ │ │ │ │ │ │ │
│ │ │ └── release │ │ │ └── release
│ │ │ │ │ │
│ │ └── x86-64 (dependencies targeting x86-64 Linux architecture) │ │ └── x86-64 (dependencies targeting GNU/Linux x86-64 architecture)
│ │ │ │ │ │
│ │ ├── debug │ │ ├── debug
│ │ │ │ │ │
│ │ └── release │ │ └── release
│ │ │ │
── v22 (UE 5.3 and 5.4 Linux dependencies) ── v22 (5.4 GNU/Linux dependencies)
├── aarch64 (dependencies targeting AArch64 Linux architecture) ├── aarch64 (dependencies targeting GNU/Linux AArch64 architecture)
│ │ │ │
│ ├── debug │ ├── debug
│ │ │ │
│ └── release │ └── release
└── x86-64 (dependencies targeting x86-64 Linux architecture) └── x86-64 (dependencies targeting GNU/Linux x86-64 architecture)
├── debug ├── debug
└── release └── release
│ │
── win64 │ │ ── v23 (UE 5.5 GNU/Linux dependencies)
├── msvc142 (Microsoft Visual Studio 2019 dependencies) ├── aarch64 (dependencies targeting GNU/Linux AArch64 architecture)
│ │ │ │
│ ├── debug │ ├── debug
│ │ │ │
│ └── release │ └── release
└── msvc143 (Microsoft Visual Studio 2022 dependencies) └── x86-64 (dependencies targeting GNU/Linux x86-64 architecture)
├── debug ├── debug
└── release └── release
│ │ │
│ │ └── v25 (UE 5.6 GNU/Linux dependencies)
│ │ │
│ │ ├── aarch64 (dependencies targeting GNU/Linux AArch64 architecture)
│ │ │ │
│ │ │ ├── debug
│ │ │ │
│ │ │ └── release
│ │ │
│ │ └── x86-64 (dependencies targeting GNU/Linux x86-64 architecture)
│ │ │
│ │ ├── debug
│ │ │
│ │ └── release
│ │
│ └── windows
│ │
│ ├── v143 (Microsoft Visual Studio 2022 dependencies)
│ │ │
│ │ └── x86-64 (dependencies targeting Microsoft Windows x86-64 architecture)
│ │ │
│ │ ├── debug
│ │ │
│ │ └── release
│ │
│ └── rustc (Microsoft Windows binary dependencies built with Rust)
│ │
│ └── x86-64 (dependencies targeting Microsoft Windows x86-64 architecture)
│ │
│ ├── debug
│ │
│ └── release
├── SGBleThirdPartyLibs (Third-party module providing SGBLE headers and libraries)
├── SGConnectThirdPartyHeaders (Third-party module providing SGConnect headers)
├── SGConnectThirdPartyLibs (Third-party module providing SGConnect headers and libraries)
├── SGCoreThirdPartyLibs (Third-party module providing SGCore headers and libraries)
└── SGSerialThirdPartyLibs (Third-party module providing github.com/wjwwood/serial headers and libraries)
``` ```
+6 -1
View File
@@ -9,9 +9,10 @@ There are various resources available for older versions of the SenseGlove Unrea
- [Example C++ API Project (only compatible with early v1.x.x releases)](https://dev.azure.com/SenseGlove/_git/SenseGlove-Unreal-SGPlaygroundCpp) - [Example C++ API Project (only compatible with early v1.x.x releases)](https://dev.azure.com/SenseGlove/_git/SenseGlove-Unreal-SGPlaygroundCpp)
- [Example Blueprint API Project (only compatible with early v1.x.x releases)](https://dev.azure.com/SenseGlove/_git/SenseGlove-Unreal-SGPlaygroundBP) - [Example Blueprint API Project (only compatible with early v1.x.x releases)](https://dev.azure.com/SenseGlove/_git/SenseGlove-Unreal-SGPlaygroundBP)
### OpenXR Integration Demos ### Third-Party OpenXR Integration Demos
- [A VRExpansionPlugin Integration Demo for UE `5.4`](https://dev.azure.com/SenseGlove/_git/SGVRETemplate) - [A VRExpansionPlugin Integration Demo for UE `5.4`](https://dev.azure.com/SenseGlove/_git/SGVRETemplate)
- [Documentation](../advanced-topics/openxr/third-party-integrations/)
## Tutorials ## Tutorials
@@ -43,3 +44,7 @@ There are various resources available for older versions of the SenseGlove Unrea
- [Build & Deploy Unreal Engine 5.5 Projects APK to Android & Meta Quest 3S/3/Pro/2 in Standalone Mode](https://youtu.be/EClbEbNcl4k) - [Build & Deploy Unreal Engine 5.5 Projects APK to Android & Meta Quest 3S/3/Pro/2 in Standalone Mode](https://youtu.be/EClbEbNcl4k)
- [Unreal Engine OpenXR Hand-Tracking on Android with Meta XR (Quest 3S/3/Pro/2) and HTC VIVE OpenXR (Focus Vision/XR Elite/Focus 3) Plugins](https://youtu.be/BWd3MwtfTJE) - [Unreal Engine OpenXR Hand-Tracking on Android with Meta XR (Quest 3S/3/Pro/2) and HTC VIVE OpenXR (Focus Vision/XR Elite/Focus 3) Plugins](https://youtu.be/BWd3MwtfTJE)
### VR Optimization
- [Optimizing Unreal Engine VR Projects for Higher Framerates (Meta Quest, HTC VIVE, FFR, ETFR, NVIDIA DLSS, AMD FSR, and Intel XeSS Tips Included!)](https://youtu.be/67CZqMrAOns)
@@ -1,6 +1,6 @@
## Planned Features Completion Status ## Planned Features Completion Status
### Implemented as of v2.5.x ### Implemented as of v2.7.x
- [X] Full SenseGlove low-level core API access through Unreal C++. - [X] Full SenseGlove low-level core API access through Unreal C++.
- [X] Full SenseGlove low-level core API access through Blueprint. - [X] Full SenseGlove low-level core API access through Blueprint.
@@ -42,7 +42,7 @@
- [X] Ability to automatically ask for the required permissions on Android when the plugin is enabled in any UE project. - [X] Ability to automatically ask for the required permissions on Android when the plugin is enabled in any UE project.
- [X] `ViveOpenXR` plugin compatibility. - [X] `ViveOpenXR` plugin compatibility.
### Upcoming features planned for the v2.5.x release ### Upcoming features planned for the v2.7.x release
### Planned features long-term ### Planned features long-term
@@ -2,9 +2,11 @@
| | **Windows (MSVC 2017)** | **Windows (MSVC 2019)** | **Windows (MSVC 2022)** | **Linux x86-64 (Native Toolchain)** | **Linux AArch64 (Native Toolchain)** | **Meta Quest Standalone (Android NDK)** | **HTC VIVE Standalone (Android NDK)** | **Fab** | **Azure DevOps Version** | | | **Windows (MSVC 2017)** | **Windows (MSVC 2019)** | **Windows (MSVC 2022)** | **Linux x86-64 (Native Toolchain)** | **Linux AArch64 (Native Toolchain)** | **Meta Quest Standalone (Android NDK)** | **HTC VIVE Standalone (Android NDK)** | **Fab** | **Azure DevOps Version** |
|:--------:|-------------------------|-------------------------|-------------------------|:-----------------------------------:|:------------------------------------:|:---------------------------------------:|:-------------------------------------:|:--------:|:------------------------:| |:--------:|-------------------------|-------------------------|-------------------------|:-----------------------------------:|:------------------------------------:|:---------------------------------------:|:-------------------------------------:|:--------:|:------------------------:|
| **5.5** | ❌ | ❌ | ✅ v2.5.x | ✅ v2.5.x | ✅ v2.5.x | ✅ v2.5.x (r25b) | ❓ | ✅ v2.5.0 | ✅ v2.5.0 | | **5.7** | ❌ | ❌ | ✅ v2.7.x | ✅ v2.7.x | ✅ v2.7.x | ✅ v2.7.x (r25b) | ❓ | ✅ v2.7.1 | ✅ v2.7.1 |
| **5.4** | ❌ | ❌ | ✅ v2.5.x | ✅ v2.5.x | ✅ v2.5.x | ✅ v2.5.x (r25b) | ✅ v2.5.x (r25b) | ✅ v2.5.0 | ✅ v2.5.0 | | **5.6** | ❌ | ❌ | ✅ v2.7.x | ✅ v2.7.x | ✅ v2.7.x | ✅ v2.7.x (r25b) | | ✅ v2.7.1 | ✅ v2.7.1 |
| **5.3** | ❌ | ✅ v2.5.x | ✅ v2.5.x | ✅ v2.5.x | ✅ v2.5.x | ✅ v2.5.x (r25b) | ✅ v2.5.x (r25b) | ✅ v2.5.0 | ✅ v2.5.0 | | **5.5** | ❌ | | ✅ v2.7.x | ✅ v2.7.x | ✅ v2.7.x | ✅ v2.7.x (r25b) | | ✅ v2.7.1 | ✅ v2.7.1 |
| **5.4** | ❌ | ❌ | ⚠️ v2.7.x | ⚠️ v2.7.x | ⚠️ v2.7.x | ⚠️ v2.7.x (r25b) | ⚠️ v2.7.x (r25b) | ⚠️ v2.7.1 | ⚠️ v2.7.1 |
| **5.3** | ❌ | ⚠️ v2.6.x | ⚠️ v2.6.x | ⚠️ v2.6.x | ⚠️ v2.6.x | ⚠️ v2.6.x (r25b) | ⚠️ v2.6.x (r25b) | ⚠️ v2.6.3 | ⚠️ v2.6.3 |
| **5.2** | ❌ | ⚠️ v2.4.x | ⚠️ v2.4.x | ⚠️ v2.4.x | ⚠️ v2.4.x | ⚠️ v2.4.x (r25b) | ❓ | ⚠️ v2.4.2 | ⚠️ v2.4.2 | | **5.2** | ❌ | ⚠️ v2.4.x | ⚠️ v2.4.x | ⚠️ v2.4.x | ⚠️ v2.4.x | ⚠️ v2.4.x (r25b) | ❓ | ⚠️ v2.4.2 | ⚠️ v2.4.2 |
| **5.1** | ❌ | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x (r25b) | ❓ | ⚠️ v2.0.0 | ⚠️ v2.0.2 | | **5.1** | ❌ | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x | ⚠️ v2.0.x (r25b) | ❓ | ⚠️ v2.0.0 | ⚠️ v2.0.2 |
| **5.0** | ❌ | ⚠️ v1.6.x | ⚠️ v1.6.x | ⚠️ v1.6.x | ⚠️ v1.6.x | ⚠️ v1.6.x (r21e) | ❓ | ⚠️ v1.6.1 | ⚠️ v1.6.1 | | **5.0** | ❌ | ⚠️ v1.6.x | ⚠️ v1.6.x | ⚠️ v1.6.x | ⚠️ v1.6.x | ⚠️ v1.6.x (r21e) | ❓ | ⚠️ v1.6.1 | ⚠️ v1.6.1 |
@@ -16,7 +18,7 @@
| **4.22** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ | ❌ | ❌ | ⚠️ v1.0.4 | | **4.22** | ⚠️ v1.0.x | ⚠️ v1.0.x | ❌ | ⚠️ v1.0.x | ❌ | ❌ | ❌ | ❌ | ⚠️ v1.0.4 |
* <code>✅</code> Supported * <code>✅</code> Supported
* <code>⚠️</code> Not supported by the latest release and might be lacking features * <code>⚠️</code> End-of-life (EOL) release that is not supported anymore and might be lacking features
* <code>❌</code> Not supported at all * <code>❌</code> Not supported at all
* <code>❓</code> Unknown or untested * <code>❓</code> Unknown or untested
@@ -34,6 +34,32 @@ To set up `XR_EXT_hand_tracking` support on Meta Quest HMDs in Standalone mode,
To set up `XR_EXT_hand_tracking` support on HTC VIVE HMDs in Standalone mode, additional plugins or configuration steps are required. To set up `XR_EXT_hand_tracking` support on HTC VIVE HMDs in Standalone mode, additional plugins or configuration steps are required.
> [!CAUTION]
> The SenseGlove Unreal Engine Plugin `v2.7.x` is the last release series to
> support Unreal Engine `5.4`, and its support will be removed in future minor
> or major releases. This is important to keep in mind if your target
> development and deployment platform is HTC VIVE in Standalone Mode.
> Unfortunately, HTC has not released any updates to their HTC ViveOpenXR
> plugin since December 6, 2024. Their
> [latest release](https://developer.vive.com/resources/openxr/unreal/unreal-download/latest/)
> [[1]](https://web.archive.org/web/20251113165658/https://developer.vive.com/resources/openxr/unreal/unreal-download/latest/)
> [[2]](https://archive.ph/DlrLr), ViveOpenXR Plugin `v2.5.0`, supports only
> Unreal Engine `5.3` and `5.4`.
> [HTC VIVE PCVR Mode](../pcvr-mode/index.html#htc-vive) is unaffected and will
> remain fully functional because, on Microsoft Windows, it is supported via the
> [OpenXRViveTracker Plugin](../pcvr-mode/index.html#openxrvivetracker-plugin),
> which is bundled with Unreal Engine and officially maintained by Epic Games.
> If you still intend to target HTC in Standalone Mode, you are welcome to
> continue using the latest SenseGlove Unreal Engine Plugin `v2.7.x`, which will
> retain HTC Standalone Mode support. However, please keep in mind that once
> newer versions of the SenseGlove Unreal Engine Plugin are released and UE
> `5.4` is no longer supported, the latest release of the plugin supporting UE
> `5.4` will not receive new features, hardware support, or bug fixes. If at any
> point in the future HTC releases a new version of their ViveOpenXR plugin that
> supports any Unreal Engine version we actively support,+
> [in accordance with our support policy and Platform Support Matrix](../../../appendix/platform-support-matrix.html),
> we will make every reasonable effort to reintroduce HTC Standalone Mode support.
### OpenXRViveTracker Plugin ### OpenXRViveTracker Plugin
Unlike the [PCVR-mode on Windows](../pcvr-mode/), the `OpenXRViveTracker` plugin is not required on Android since it only provides an implementation of the `XR_HTCX_vive_tracker_interaction` OpenXR extension which is necessary when we use VIVE Trackers on Windows or we [emulate the VIVE Wrist Trackers as VIVE Trackers on Windows](../pcvr-mode/#vive-business-streaming-app). Instead, we require the `XR_HTCX_vive_wrist_tracker_interaction` OpenXR extension to be able to use VIVE Wrist Trackers on Android, which is provided by the [`ViveOpenXR` plugin](#viveopenxr-plugin). So, you can safely ignore enabling this plugin for Android standalone deployments. Unlike the [PCVR-mode on Windows](../pcvr-mode/), the `OpenXRViveTracker` plugin is not required on Android since it only provides an implementation of the `XR_HTCX_vive_tracker_interaction` OpenXR extension which is necessary when we use VIVE Trackers on Windows or we [emulate the VIVE Wrist Trackers as VIVE Trackers on Windows](../pcvr-mode/#vive-business-streaming-app). Instead, we require the `XR_HTCX_vive_wrist_tracker_interaction` OpenXR extension to be able to use VIVE Wrist Trackers on Android, which is provided by the [`ViveOpenXR` plugin](#viveopenxr-plugin). So, you can safely ignore enabling this plugin for Android standalone deployments.
@@ -44,6 +44,33 @@ When running in PCVR mode, the functional wrist-tracking settings looks somethin
### Standalone Mode ### Standalone Mode
> [!CAUTION]
> The SenseGlove Unreal Engine Plugin `v2.7.x` is the last release series to
> support Unreal Engine `5.4`, and its support will be removed in future minor
> or major releases. This is important to keep in mind if your target
> development and deployment platform is
> [HTC VIVE in Standalone Mode](../enabling-xr-ext-hand-tracking-vr-headsets/standalone-mode/index.html#htc-vive).
> Unfortunately, HTC has not released any updates to their HTC ViveOpenXR
> plugin since December 6, 2024. Their
> [latest release](https://developer.vive.com/resources/openxr/unreal/unreal-download/latest/)
> [[1]](https://web.archive.org/web/20251113165658/https://developer.vive.com/resources/openxr/unreal/unreal-download/latest/)
> [[2]](https://archive.ph/DlrLr), ViveOpenXR Plugin `v2.5.0`, supports only
> Unreal Engine `5.3` and `5.4`.
> [HTC VIVE PCVR Mode](../enabling-xr-ext-hand-tracking-vr-headsets/pcvr-mode/index.html#htc-vive) is unaffected and will
> remain fully functional because, on Microsoft Windows, it is supported via the
> [OpenXRViveTracker Plugin](../pcvr-mode/index.html#openxrvivetracker-plugin),
> which is bundled with Unreal Engine and officially maintained by Epic Games.
> If you still intend to target HTC in Standalone Mode, you are welcome to
> continue using the latest SenseGlove Unreal Engine Plugin `v2.7.x`, which will
> retain HTC Standalone Mode support. However, please keep in mind that once
> newer versions of the SenseGlove Unreal Engine Plugin are released and UE
> `5.4` is no longer supported, the latest release of the plugin supporting UE
> `5.4` will not receive new features, hardware support, or bug fixes. If at any
> point in the future HTC releases a new version of their ViveOpenXR plugin that
> supports any Unreal Engine version we actively support,+
> [in accordance with our support policy and Platform Support Matrix](../../appendix/platform-support-matrix.html),
> we will make every reasonable effort to reintroduce HTC Standalone Mode support.
When running in Standalone mode, the functional wrist-tracking settings looks something like this: When running in Standalone mode, the functional wrist-tracking settings looks something like this:
![Setting Up the Wrist Tracking Hardware - HTC VIVE Focus 3 Wrist Tracker (Standalone Mode)](senseglove-wrist-tracking-settings-htc-vive-focus-3-wrist-tracker-openxrvivewristtracker.png "Setting Up the Wrist Tracking Hardware - HTC VIVE Focus 3 Wrist Tracker (Standalone Mode)") ![Setting Up the Wrist Tracking Hardware - HTC VIVE Focus 3 Wrist Tracker (Standalone Mode)](senseglove-wrist-tracking-settings-htc-vive-focus-3-wrist-tracker-openxrvivewristtracker.png "Setting Up the Wrist Tracking Hardware - HTC VIVE Focus 3 Wrist Tracker (Standalone Mode)")
@@ -0,0 +1,31 @@
# {fmt} Formatting Library License
```
Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- Optional exception to the license ---
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into a machine-executable object form of such
source code, you may redistribute such embedded portions in such object form
without including the above copyright and permission notices.
```
@@ -0,0 +1,28 @@
# Loguru Logging Library License
```
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>
```
+2
View File
@@ -7,6 +7,8 @@ The following third-party software are used and shipped with the SenseGlove Unre
- [The SenseGlove SDK (a.k.a. SenseGlove Backend Libraries, or SenseGlove Core Libraries)](senseglove-sdk.md) - [The SenseGlove SDK (a.k.a. SenseGlove Backend Libraries, or SenseGlove Core Libraries)](senseglove-sdk.md)
- [SGBLE and SGBLExx Rust Dependencies](sgble-sgblexx-rust-dependencies.md) - [SGBLE and SGBLExx Rust Dependencies](sgble-sgblexx-rust-dependencies.md)
- [The Boost C++ Libraries](boost-cpp-libraries.md) - [The Boost C++ Libraries](boost-cpp-libraries.md)
- [The {fmt} Formatting Library](fmt-formatting-library.md)
- [The Loguru Logging Library License](loguru-loggin-library.md)
- [The Serial Communication Library](serial-communication-library.md) - [The Serial Communication Library](serial-communication-library.md)
For more information consult their own respective open-source licenses, please. For more information consult their own respective open-source licenses, please.
@@ -1,5 +1,17 @@
# Third-Party Tutorials: Android Standalone Mode Deployment # Third-Party Tutorials: Android Standalone Mode Deployment
## On-Click Unreal Engine 5.7 Android Packaging & APK Build Tutorial | Meta Quest & HTC VIVE Standalone
This tutorial provides a complete, streamlined guide to packaging and deploying Unreal Engine 5.7 projects to Android devices in standalone mode, with full support for Meta Quest and HTC VIVE headsets. Viewers learn how to correctly install and configure every required component, including Android Studio, SDK, NDK, JDK, and Visual Studio, using either a manual setup, or an open-source one-click PowerShell installer featured in the video.
The tutorial walks through creating a fresh Unreal Engine VR Template project, configuring Android project settings, enabling ADB device debugging, and generating a working APK using the updated Project Launcher workflow in UE 5.7. It also covers how to integrate the Meta XR and HTC VIVE OpenXR plugins to ensure proper VR recognition and hand-tracking functionality on each platform.
By the end, developers understand how to go from a blank project to a fully packaged and deployable Android APK, with functioning VR, correct device targeting, and reliable deployment pipelines on both Meta Quest and HTC VIVE standalone headsets.
<div style="margin: 0 auto; width: 560px;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/SCtAfDeWXBM" frameborder="0" allowfullscreen></iframe>
</div>
## Build & Deploy Unreal Engine 5.5 Projects APK to Android & Meta Quest 3S/3/Pro/2 in Standalone Mode ## Build & Deploy Unreal Engine 5.5 Projects APK to Android & Meta Quest 3S/3/Pro/2 in Standalone Mode
This video will guide you through the process of building and deploying an Unreal Engine 5.5 project (or any version newer than `4.24`) to Android Standalone Mode for Meta Quest 2 and Quest 3 devices. The steps outlined here should also apply to other Android-based VR headsets. This video will guide you through the process of building and deploying an Unreal Engine 5.5 project (or any version newer than `4.24`) to Android Standalone Mode for Meta Quest 2 and Quest 3 devices. The steps outlined here should also apply to other Android-based VR headsets.
@@ -0,0 +1,20 @@
# Third-Party Tutorials: Optimizing Your Project for Higher FPS
## Optimizing Unreal Engine VR Projects for Higher Framerates (Meta Quest, HTC VIVE, FFR, ETFR, NVIDIA DLSS, AMD FSR, and Intel XeSS Tips Included!)
This beginner-friendly tutorial, covers how to significantly boost the performance of your Unreal Engine VR projects, whether you're building for standalone (mobile) or PCVR (desktop) on devices such as Meta Quest, HTC VIVE, Varjo, or Valve Index.
It covers step-by-step how to:
- Convert a regular project into a VR-ready experience.
- Optimize for both standalone (Android) and PCVR (Windows) platforms.
- Tweak key rendering, lighting, and texture settings for smoother gameplay.
- Configure Meta XR and HTC VIVE OpenXR plugins to fine-tune settings for the best performance possible.
- Utilize and fine-tune engine scalability settings.
- Explore powerful optimization features like DLSS, FSR, XeSS, and Foveated Rendering
Even if youre new to VR development, this guide breaks it down with visuals, clear examples, and actionable tips to take your framerate from sluggish to silky smooth.
<div style="margin: 0 auto; width: 560px;">
<iframe width="560" height="315" src="https://www.youtube.com/embed/67CZqMrAOns" frameborder="0" allowfullscreen></iframe>
</div>
+4
View File
@@ -68,6 +68,7 @@ Toipcs that do not fall under any specific category:
- [Third-Party Tutorials](../misc/android-standalone-deployment/third-party-tutorials/) - [Third-Party Tutorials](../misc/android-standalone-deployment/third-party-tutorials/)
- [Upgrade Guide](../misc/upgrade-guide/) - [Upgrade Guide](../misc/upgrade-guide/)
- [Optimizing for Higher FPS](../misc/optimize-higher-fps/) - [Optimizing for Higher FPS](../misc/optimize-higher-fps/)
- [Third-Party Tutorials](../misc/optimize-higher-fps/third-party-tutorials/)
## 🛠️ Advanced Topics ## 🛠️ Advanced Topics
@@ -81,6 +82,7 @@ For users familiar with the basics, this section explores advanced features of t
- [Consuming FXRMotionControllerData](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/) - [Consuming FXRMotionControllerData](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/)
- [Blueprint](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/blueprint.md) - [Blueprint](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/blueprint.md)
- [C++](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/cpp.md) - [C++](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/cpp.md)
- [Third-Party Integrations](../advanced-topics/openxr/third-party-integrations/)
- [Third-Party Tutorials](../advanced-topics/openxr/third-party-tutorials/) - [Third-Party Tutorials](../advanced-topics/openxr/third-party-tutorials/)
## 🔌 Low-Level API ## 🔌 Low-Level API
@@ -108,4 +110,6 @@ The appendix contains various extra useful information:
- [SenseGlove SDK License](../license/senseglove-sdk.md) - [SenseGlove SDK License](../license/senseglove-sdk.md)
- [SGBLE and SGBLExx Rust Dependencies Licenses](../license/sgble-sgblexx-rust-dependencies.md) - [SGBLE and SGBLExx Rust Dependencies Licenses](../license/sgble-sgblexx-rust-dependencies.md)
- [Boost C++ Libraries License](../license/boost-cpp-libraries.md) - [Boost C++ Libraries License](../license/boost-cpp-libraries.md)
- [{fmt} Formatting Library License](../license/fmt-formatting-library.md)
- [Loguru Logging Library License](../license/loguru-loggin-library.md)
- [Serial Communication Library License](../license/serial-communication-library.md) - [Serial Communication Library License](../license/serial-communication-library.md)
@@ -4,8 +4,8 @@ Provides the tracking settings related to SenseGlove devices.
![The Glove-tracking Settings](glove-tracking-settings.png "The Glove-tracking Settings") ![The Glove-tracking Settings](glove-tracking-settings.png "The Glove-tracking Settings")
## GloveConnectivityCheckInterval ## DataRetrievalRefreshRate
The interval in which the tracking module checks for glove connectivity. The glove data retrieval refresh rate. This affects the interval in which the tracking module checks for glove connectivity and data retrieval.
The default is `16.666666f` which means `60` times per second. The default is s `60Hz` (data retrieval operations per second).
BIN
View File
Binary file not shown.
Binary file not shown.
+45 -9
View File
@@ -42,9 +42,10 @@ Deploy:
PasswordEnvVar: SGUM_PACKAGER_REPOSITORY_PASSWORD PasswordEnvVar: SGUM_PACKAGER_REPOSITORY_PASSWORD
Branches: Branches:
- "5.7"
- "5.6"
- "5.5" - "5.5"
- "5.4" - "5.4"
- "5.3"
Exclusions: Exclusions:
- .git - .git
@@ -178,18 +179,53 @@ Rocket:
UPluginFile: SenseGlove.uplugin UPluginFile: SenseGlove.uplugin
PackageDirectory: "%TEMP%\\SenseGlove-Unreal\\Rocket" PackageDirectory:
Linux: /tmp/SenseGlove-Unreal/Rocket
Windows: "%TEMP%\\SenseGlove-Unreal\\Rocket"
EnginePaths: EnginePaths:
- "5.5": "C:\\OPT\\UE_5.5"
- "5.4": "C:\\OPT\\UE_5.4" - Branch: "5.7"
- "5.3": "C:\\OPT\\UE_5.3" Path:
Linux: "/opt/UE57"
Windows: "C:\\OPT\\UE_5.7"
- Branch: "5.6"
Path:
Linux: "/opt/UE56"
Windows: "C:\\OPT\\UE_5.6"
- Branch: "5.5"
Path:
Linux: "/opt/UE55"
Windows: "C:\\OPT\\UE_5.5"
- Branch: "5.4"
Path:
Linux: "/opt/UE54"
Windows: "C:\\OPT\\UE_5.4"
NDKPaths: NDKPaths:
- "5.5": "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393"
- "5.4": "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393" - Branch: "5.7"
- "5.3": "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393" Path:
- "5.2": "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393" Linux: "/opt/android/sdk/ndk/27.2.12479018"
Windows: "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\27.2.12479018"
- Branch: "5.6"
Path:
Linux: "/opt/android/sdk/ndk/27.2.12479018"
Windows: "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\27.2.12479018"
- Branch: "5.5"
Path:
Linux: "/opt/android/sdk/ndk/25.1.8937393"
Windows: "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393"
- Branch: "5.4"
Path:
Linux: "/opt/android/sdk/ndk/25.1.8937393"
Windows: "%LOCALAPPDATA%\\Android\\Sdk\\ndk\\25.1.8937393"
Rsync: Rsync:
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"FileVersion": 3, "FileVersion": 3,
"Version": 1, "Version": 1,
"VersionName": "2.5.0", "VersionName": "2.7.1",
"FriendlyName": "SenseGlove", "FriendlyName": "SenseGlove",
"Description": "Integrating the SenseGlove haptic controller into Unreal Engine", "Description": "Integrating the SenseGlove haptic controller into Unreal Engine",
"Category": "Virtual Reality", "Category": "Virtual Reality",
@@ -35,6 +35,7 @@
#include "SenseGlove/Animation/SGVirtualHandAnimInstanceProxy.h" #include "SenseGlove/Animation/SGVirtualHandAnimInstanceProxy.h"
#include "Animation/AnimInstance.h"
#include "Animation/Skeleton.h" #include "Animation/Skeleton.h"
#include "BoneContainer.h" #include "BoneContainer.h"
#include "BoneControllers/AnimNode_ModifyBone.h" #include "BoneControllers/AnimNode_ModifyBone.h"
@@ -107,17 +108,16 @@ void FSGVirtualHandAnimInstanceProxy::PreEvaluateAnimation(UAnimInstance* InAnim
} }
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
const bool bGotHandTrackingState = VirtualHand->GetHandTrackingState( HandTrackingState = VirtualHand->GetHandTrackingState();
EXRSpaceType::UnrealWorldSpace, HandTrackingState); if (!HandTrackingState.bValid)
if (!bGotHandTrackingState || !HandTrackingState.bValid)
{ {
return; return;
} }
ensureAlwaysMsgf(HandTrackingState.HandKeyLocations.Num() == HandTrackingState.HandKeyRotations.Num(), ensureAlwaysMsgf(HandTrackingState.HandKeyLocations.Num() == HandTrackingState.HandKeyRotations.Num(),
TEXT("Mismatched hand tracking state locations and rotations!")); TEXT("Mismatched hand tracking state locations and rotations!"));
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
const bool bGotMotionControllerData = VirtualHand->GetMotionControllerData(MotionControllerData); MotionControllerData = VirtualHand->GetMotionControllerData();
if (!bGotMotionControllerData || !MotionControllerData.bValid) if (!MotionControllerData.bValid)
{ {
return; return;
} }
@@ -103,8 +103,9 @@ USGTouchComponent::USGTouchComponent(const FObjectInitializer& ObjectInitializer
{ {
ForceFeedbackLevel = 1.0f; ForceFeedbackLevel = 1.0f;
VibrotactileDuration = 0.25f; VibrotactileAmplitude = 1.0f;
VibrotactileLevel = 0.0f; VibrotactileDuration = 1.0f;
VibrotactileFrequency= 180.0f;
} }
USGTouchComponent::FImpl::FImpl(USGTouchComponent* InOwner) USGTouchComponent::FImpl::FImpl(USGTouchComponent* InOwner)
@@ -42,12 +42,12 @@
#include "Engine/EngineTypes.h" #include "Engine/EngineTypes.h"
#include "Engine/SkeletalMesh.h" #include "Engine/SkeletalMesh.h"
#include "InputCoreTypes.h" #include "InputCoreTypes.h"
#include "IXRTrackingSystem.h"
#include "Templates/UnrealTypeTraits.h" #include "Templates/UnrealTypeTraits.h"
#include "UObject/ConstructorHelpers.h" #include "UObject/ConstructorHelpers.h"
#include "SenseGlove/Animation/SGVirtualHandAnimInstance.h" #include "SenseGlove/Animation/SGVirtualHandAnimInstance.h"
#include "SenseGlove/Components/SGWristTrackerComponent.h" #include "SenseGlove/Components/SGWristTrackerComponent.h"
#include "SGBuildHacks/SGPlatform.h"
#include "SGCore/SGHapticGlove.h" #include "SGCore/SGHapticGlove.h"
#include "SGDebug/SGDebugVirtualHand.h" #include "SGDebug/SGDebugVirtualHand.h"
#include "SGLog/SGLog.h" #include "SGLog/SGLog.h"
@@ -100,6 +100,14 @@ struct USGVirtualHandComponent::FImpl
ECollisionEnabled::Type CachedCollisionEnabled; ECollisionEnabled::Type CachedCollisionEnabled;
FCollisionResponseContainer CachedCollisionResponse; FCollisionResponseContainer CachedCollisionResponse;
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7
FXRMotionControllerData MotionControllerData;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
FXRHandTrackingState HandTrackingState;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
/************************ /************************
* Owner object * Owner object
************************/ ************************/
@@ -142,6 +150,8 @@ struct USGVirtualHandComponent::FImpl
void DisableCollisionResponse(); void DisableCollisionResponse();
void RestoreCollisionResponse() const; void RestoreCollisionResponse() const;
void UpdateXRData();
void SetVisibility(const bool bInVisible); void SetVisibility(const bool bInVisible);
void UpdateVisibility(); void UpdateVisibility();
@@ -367,7 +377,7 @@ void USGVirtualHandComponent::InitializeComponent()
Pimpl->SetDefaultMesh(); Pimpl->SetDefaultMesh();
} }
Pimpl->UpdateVisibility(); Pimpl->UpdateXRData();
} }
void USGVirtualHandComponent::UninitializeComponent() void USGVirtualHandComponent::UninitializeComponent()
@@ -387,7 +397,7 @@ void USGVirtualHandComponent::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
Pimpl->UpdateVisibility(); Pimpl->UpdateXRData();
} }
void USGVirtualHandComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) void USGVirtualHandComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
@@ -416,7 +426,7 @@ void USGVirtualHandComponent::TickComponent(
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
Pimpl->UpdateVisibility(); Pimpl->UpdateXRData();
if (Pimpl->ShouldDrawDebugVirtualHand()) if (Pimpl->ShouldDrawDebugVirtualHand())
{ {
@@ -439,7 +449,7 @@ void USGVirtualHandComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, const bool
void USGVirtualHandComponent::EditorTick( void USGVirtualHandComponent::EditorTick(
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{ {
Pimpl->UpdateVisibility(); Pimpl->UpdateXRData();
if (Pimpl->ShouldDrawDebugVirtualHand()) if (Pimpl->ShouldDrawDebugVirtualHand())
{ {
@@ -461,61 +471,11 @@ USGHapticGlove* USGVirtualHandComponent::GetConnectedGlove() const
return Glove; return Glove;
} }
bool USGVirtualHandComponent::GetMotionControllerData(FXRMotionControllerData& OutMotionControllerData)
{
OutMotionControllerData.bValid = false;
const EControllerHand Hand = IsRight() ? EControllerHand::Right : EControllerHand::Left;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
const bool bGotMotionControllerData =
FSGXRTracker::GetMotionControllerData(this, Hand, OutMotionControllerData);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
if (!bGotMotionControllerData || !OutMotionControllerData.bValid)
{
return false;
}
return OutMotionControllerData.bValid;
}
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
const FXRHandTrackingState& USGVirtualHandComponent::GetHandTrackingState() const
bool USGVirtualHandComponent::GetMotionControllerState(
const EXRSpaceType XRSpaceType, const EXRControllerPoseType XRControllerPoseType,
FXRMotionControllerState& OutMotionControllerState)
{ {
OutMotionControllerState.bValid = false; return Pimpl->HandTrackingState;
const EControllerHand Hand = IsRight() ? EControllerHand::Right : EControllerHand::Left;
const bool bGotMotionControllerState =
FSGXRTracker::GetMotionControllerState(
this, XRSpaceType, Hand, XRControllerPoseType, OutMotionControllerState);
if (!bGotMotionControllerState || !OutMotionControllerState.bValid)
{
return false;
}
return OutMotionControllerState.bValid;
} }
bool USGVirtualHandComponent::GetHandTrackingState(
const EXRSpaceType XRSpaceType,
FXRHandTrackingState& OutHandTrackingState)
{
OutHandTrackingState.bValid = false;
const EControllerHand Hand = IsRight() ? EControllerHand::Right : EControllerHand::Left;
const bool bGotHandTrackingState =
FSGXRTracker::GetHandTrackingState(
this, XRSpaceType, Hand, OutHandTrackingState);
if (!bGotHandTrackingState || !OutHandTrackingState.bValid)
{
return false;
}
return OutHandTrackingState.bValid;
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
const TArray<FName>& USGVirtualHandComponent::GetHandBoneNames() const const TArray<FName>& USGVirtualHandComponent::GetHandBoneNames() const
@@ -785,6 +745,42 @@ void USGVirtualHandComponent::FImpl::RestoreCollisionResponse() const
Owner->SetCollisionResponseToChannels(CachedCollisionResponse); Owner->SetCollisionResponseToChannels(CachedCollisionResponse);
} }
void USGVirtualHandComponent::FImpl::UpdateXRData()
{
const EControllerHand Hand = Owner->IsRight() ? EControllerHand::Right : EControllerHand::Left;
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7
{
FXRMotionControllerData Data;
Data.bValid = false;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
const bool bGotMotionControllerData =
FSGXRTracker::GetMotionControllerData(Owner, Hand, Data);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
(void)
bGotMotionControllerData;
MotionControllerData = MoveTemp(Data);
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
{
FXRHandTrackingState State;
State.bValid = false;
const bool bGotHandTrackingState =
FSGXRTracker::GetHandTrackingState(
Owner, EXRSpaceType::UnrealWorldSpace, Hand, State);
(void) bGotHandTrackingState;
HandTrackingState = MoveTemp(State);
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
}
void USGVirtualHandComponent::FImpl::SetVisibility(const bool bInVisible) void USGVirtualHandComponent::FImpl::SetVisibility(const bool bInVisible)
{ {
Owner->SetHiddenInGame(!bInVisible, false); Owner->SetHiddenInGame(!bInVisible, false);
@@ -803,23 +799,12 @@ void USGVirtualHandComponent::FImpl::SetVisibility(const bool bInVisible)
void USGVirtualHandComponent::FImpl::UpdateVisibility() void USGVirtualHandComponent::FImpl::UpdateVisibility()
{ {
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
FXRHandTrackingState HandTrackingState;
const bool bGotHandTrackingState =
Owner->GetHandTrackingState(EXRSpaceType::UnrealWorldSpace, HandTrackingState);
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
FXRMotionControllerData MotionControllerData;
const bool bGotMotionControllerData = Owner->GetMotionControllerData(MotionControllerData);
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
const bool bHandDataAvailable = const bool bHandDataAvailable =
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
bGotHandTrackingState HandTrackingState.bValid
&& HandTrackingState.bValid
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
bGotMotionControllerData MotionControllerData.bValid
&& MotionControllerData.bValid && MotionControllerData.DeviceVisualType == EXRVisualType::Hand
&& MotionControllerData.DeviceVisualType == EXRVisualType::Hand
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
; ;
const bool bHandVisible = Owner->IsVisible(); const bool bHandVisible = Owner->IsVisible();
@@ -881,18 +866,16 @@ void USGVirtualHandComponent::FImpl::DrawDebugVirtualHand() const
} }
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
FXRHandTrackingState HandTrackingState; if (!HandTrackingState.bValid)
const bool bGotHandTrackingState = Owner->GetHandTrackingState(EXRSpaceType::UnrealWorldSpace, HandTrackingState);
if (!bGotHandTrackingState || !HandTrackingState.bValid)
{ {
return; return;
} }
FSGDebugVirtualHand::Draw(World, HandTrackingState, Owner->GetVirtualHandSettings().DebuggingSettings); FSGDebugVirtualHand::Draw(World, HandTrackingState, Owner->GetVirtualHandSettings().DebuggingSettings);
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
FXRMotionControllerData MotionControllerData;
const bool bGotMotionControllerData = Owner->GetMotionControllerData(MotionControllerData); if (!MotionControllerData.bValid
if (!bGotMotionControllerData || !MotionControllerData.bValid) || MotionControllerData.DeviceVisualType == EXRVisualType::Hand)
{ {
return; return;
} }
@@ -36,9 +36,10 @@
#include "SenseGlove/Components/SGWristTrackerComponent.h" #include "SenseGlove/Components/SGWristTrackerComponent.h"
#include "IXRTrackingSystem.h" #include "IXRTrackingSystem.h"
#include "MotionDelayBuffer.h"
#include "SGBuildHacks/SGPlatform.h"
#include "SGDebug/SGDebugGizmo.h" #include "SGDebug/SGDebugGizmo.h"
#include "SGLog/SGLog.h"
#include "SGSettings/SGSettings.h" #include "SGSettings/SGSettings.h"
#include "SGTracking/SGXRTracker.h" #include "SGTracking/SGXRTracker.h"
@@ -56,6 +57,14 @@ struct USGWristTrackerComponent::FImpl
bool bOverridePluginSettingsPropertyAlreadyModified; bool bOverridePluginSettingsPropertyAlreadyModified;
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7
FXRMotionControllerData MotionControllerData;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
FXRHandTrackingState HandTrackingState;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
/************************ /************************
* Owner object * Owner object
************************/ ************************/
@@ -85,7 +94,9 @@ struct USGWristTrackerComponent::FImpl
void OverridePluginSettingsPropertyChanged(); void OverridePluginSettingsPropertyChanged();
void UpdateMotionSource() const; void UpdateMotionSource() const;
void UpdateXRData();
void UpdateWristTrackingData() const; void UpdateWristTrackingData() const;
void DrawDebugWristTracker() const; void DrawDebugWristTracker() const;
}; };
@@ -201,18 +212,18 @@ void USGWristTrackerComponent::InitializeComponent()
{ {
Super::InitializeComponent(); Super::InitializeComponent();
Pimpl->UpdateWristTrackingData();
Pimpl->UpdateMotionSource(); Pimpl->UpdateMotionSource();
Pimpl->UpdateXRData();
Pimpl->UpdateWristTrackingData();
} }
void USGWristTrackerComponent::BeginPlay() void USGWristTrackerComponent::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
Pimpl->UpdateWristTrackingData();
Pimpl->UpdateMotionSource(); Pimpl->UpdateMotionSource();
Pimpl->UpdateXRData();
Pimpl->UpdateWristTrackingData();
} }
void USGWristTrackerComponent::TickComponent( void USGWristTrackerComponent::TickComponent(
@@ -228,77 +239,34 @@ void USGWristTrackerComponent::TickComponent(
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
Pimpl->UpdateXRData();
Pimpl->UpdateWristTrackingData();
if (GetWristTrackingSettings().DebuggingSettings.bDrawDebugWristTracker) if (GetWristTrackingSettings().DebuggingSettings.bDrawDebugWristTracker)
{ {
Pimpl->DrawDebugWristTracker(); Pimpl->DrawDebugWristTracker();
} }
Pimpl->UpdateWristTrackingData();
} }
void USGWristTrackerComponent::EditorTick( void USGWristTrackerComponent::EditorTick(
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{ {
Pimpl->UpdateXRData();
Pimpl->UpdateWristTrackingData(); Pimpl->UpdateWristTrackingData();
} }
bool USGWristTrackerComponent::GetMotionControllerData(FXRMotionControllerData& OutMotionControllerData) #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7
const FXRMotionControllerData& USGWristTrackerComponent::GetMotionControllerData() const
{ {
OutMotionControllerData.bValid = false; return Pimpl->MotionControllerData;
const EControllerHand Hand = IsRight() ? EControllerHand::Right : EControllerHand::Left;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
const bool bGotMotionControllerData =
FSGXRTracker::GetMotionControllerData(this, Hand, OutMotionControllerData);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
if (!bGotMotionControllerData || !OutMotionControllerData.bValid)
{
return false;
}
return OutMotionControllerData.bValid;
} }
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
const FXRHandTrackingState& USGWristTrackerComponent::GetHandTrackingState() const
bool USGWristTrackerComponent::GetMotionControllerState(
const EXRSpaceType XRSpaceType, const EXRControllerPoseType XRControllerPoseType,
FXRMotionControllerState& OutMotionControllerState)
{ {
OutMotionControllerState.bValid = false; return Pimpl->HandTrackingState;
const EControllerHand Hand = IsRight() ? EControllerHand::Right : EControllerHand::Left;
const bool bGotMotionControllerState =
FSGXRTracker::GetMotionControllerState(
this, XRSpaceType, Hand, XRControllerPoseType, OutMotionControllerState);
if (!bGotMotionControllerState || !OutMotionControllerState.bValid)
{
return false;
}
return OutMotionControllerState.bValid;
} }
bool USGWristTrackerComponent::GetHandTrackingState(
const EXRSpaceType XRSpaceType,
FXRHandTrackingState& OutHandTrackingState)
{
OutHandTrackingState.bValid = false;
const EControllerHand Hand = IsRight() ? EControllerHand::Right : EControllerHand::Left;
const bool bGotHandTrackingState =
FSGXRTracker::GetHandTrackingState(
this, XRSpaceType, Hand, OutHandTrackingState);
if (!bGotHandTrackingState || !OutHandTrackingState.bValid)
{
return false;
}
return OutHandTrackingState.bValid;
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
USGWristTrackerComponent::FImpl::FImpl(USGWristTrackerComponent* InOwner) USGWristTrackerComponent::FImpl::FImpl(USGWristTrackerComponent* InOwner)
@@ -359,6 +327,41 @@ void USGWristTrackerComponent::FImpl::UpdateMotionSource() const
Owner->SetTrackingMotionSource(TrackingMotionSource); Owner->SetTrackingMotionSource(TrackingMotionSource);
} }
void USGWristTrackerComponent::FImpl::UpdateXRData()
{
const EControllerHand Hand = Owner->IsRight() ? EControllerHand::Right : EControllerHand::Left;
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7
{
FXRMotionControllerData Data;
Data.bValid = false;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
const bool bGotMotionControllerData =
FSGXRTracker::GetMotionControllerData(Owner, Hand, Data);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
(void)
bGotMotionControllerData;
MotionControllerData = MoveTemp(Data);
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
{
FXRHandTrackingState State;
State.bValid = false;
const bool bGotHandTrackingState =
FSGXRTracker::GetHandTrackingState(
Owner, EXRSpaceType::UnrealWorldSpace, Hand, State);
(void) bGotHandTrackingState;
HandTrackingState = MoveTemp(State);
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
}
void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const
{ {
FVector NewWristLocation{Owner->GetComponentLocation()}; FVector NewWristLocation{Owner->GetComponentLocation()};
@@ -36,8 +36,6 @@
#include "SenseGlove/GameFramework/SGPlayerController.h" #include "SenseGlove/GameFramework/SGPlayerController.h"
#include "Runtime/Launch/Resources/Version.h" #include "Runtime/Launch/Resources/Version.h"
#include "Engine/TimerHandle.h"
#include "TimerManager.h"
#include "SenseGlove/Components/SGTouchComponent.h" #include "SenseGlove/Components/SGTouchComponent.h"
#include "SenseGlove/Components/SGVirtualHandComponent.h" #include "SenseGlove/Components/SGVirtualHandComponent.h"
@@ -45,6 +43,7 @@
#include "SenseGlove/Haptics/SGGrabState.h" #include "SenseGlove/Haptics/SGGrabState.h"
#include "SenseGlove/Haptics/SGTouchState.h" #include "SenseGlove/Haptics/SGTouchState.h"
#include "SGBuildHacks/SGPlatform.h" #include "SGBuildHacks/SGPlatform.h"
#include "SGCore/SGCustomWaveform.h"
#include "SGCore/SGHapticGlove.h" #include "SGCore/SGHapticGlove.h"
struct ASGPlayerController::FImpl struct ASGPlayerController::FImpl
@@ -55,11 +54,6 @@ struct ASGPlayerController::FImpl
static float GetForceFeedbackLevel(const AActor* Actor); static float GetForceFeedbackLevel(const AActor* Actor);
static float GetVibrotactileDuration(const AActor* ActorThumbTouching, const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching, const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching);
static float GetVibrotactileLevel(const AActor* Actor);
static TArray<float> GetForceFeedbackLevels( static TArray<float> GetForceFeedbackLevels(
const AActor* ActorThumbTouching, const AActor* ActorThumbTouching,
const AActor* ActorIndexTouching, const AActor* ActorIndexTouching,
@@ -67,19 +61,10 @@ struct ASGPlayerController::FImpl
const AActor* ActorRingTouching, const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching); const AActor* ActorPinkyTouching);
static TArray<float> GetVibrotactileLevels(
const AActor* ActorThumbTouching,
const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching,
const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching);
/************************ /************************
* Member variables * Member variables
************************/ ************************/
FTimerHandle TouchVibrotactileStopTimer;
/************************ /************************
* Owner object * Owner object
************************/ ************************/
@@ -104,6 +89,8 @@ struct ASGPlayerController::FImpl
* Methods * Methods
************************/ ************************/
USGCustomWaveform* GetCustomWaveform(const AActor* Actor);
void UpdateHapticsFeedback(const FSGTouchState& TouchState); void UpdateHapticsFeedback(const FSGTouchState& TouchState);
}; };
@@ -121,74 +108,6 @@ float ASGPlayerController::FImpl::GetForceFeedbackLevel(const AActor* Actor)
return 0.0f; return 0.0f;
} }
float ASGPlayerController::FImpl::GetVibrotactileDuration(const AActor* ActorThumbTouching,
const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching,
const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching)
{
if (IsValid(ActorThumbTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorThumbTouching);
if (IsValid(TouchComponent))
{
return TouchComponent->GetVibrotactileDuration();
}
}
if (IsValid(ActorIndexTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorIndexTouching);
if (IsValid(TouchComponent))
{
return TouchComponent->GetVibrotactileDuration();
}
}
if (IsValid(ActorMiddleTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorMiddleTouching);
if (IsValid(TouchComponent))
{
return TouchComponent->GetVibrotactileDuration();
}
}
if (IsValid(ActorRingTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorRingTouching);
if (IsValid(TouchComponent))
{
return TouchComponent->GetVibrotactileDuration();
}
}
if (IsValid(ActorPinkyTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorPinkyTouching);
if (IsValid(TouchComponent))
{
return TouchComponent->GetVibrotactileDuration();
}
}
return 0.0f;
}
float ASGPlayerController::FImpl::GetVibrotactileLevel(const AActor* Actor)
{
if (IsValid(Actor))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(Actor);
if (IsValid(TouchComponent))
{
return TouchComponent->GetVibrotactileLevel();
}
}
return 0.0f;
}
TArray<float> ASGPlayerController::FImpl::GetForceFeedbackLevels( TArray<float> ASGPlayerController::FImpl::GetForceFeedbackLevels(
const AActor* ActorThumbTouching, const AActor* ActorThumbTouching,
const AActor* ActorIndexTouching, const AActor* ActorIndexTouching,
@@ -213,30 +132,6 @@ TArray<float> ASGPlayerController::FImpl::GetForceFeedbackLevels(
return ForceFeedbackLevels; return ForceFeedbackLevels;
} }
TArray<float> ASGPlayerController::FImpl::GetVibrotactileLevels(
const AActor* ActorThumbTouching,
const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching,
const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching)
{
const float ThumbVibrotactileLevel = GetVibrotactileLevel(ActorThumbTouching);
const float IndexVibrotactileLevel = GetVibrotactileLevel(ActorIndexTouching);
const float MiddleVibrotactileLevel = GetVibrotactileLevel(ActorMiddleTouching);
const float RingVibrotactileLevel = GetVibrotactileLevel(ActorRingTouching);
const float PinkyVibrotactileLevel = GetVibrotactileLevel(ActorPinkyTouching);
const TArray<float> ForceFeedbackLevels{
ThumbVibrotactileLevel,
IndexVibrotactileLevel,
MiddleVibrotactileLevel,
RingVibrotactileLevel,
PinkyVibrotactileLevel,
};
return ForceFeedbackLevels;
}
ASGPlayerController::ASGPlayerController(const FObjectInitializer& ObjectInitializer) ASGPlayerController::ASGPlayerController(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer), : Super(ObjectInitializer),
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter)) Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
@@ -330,6 +225,29 @@ ASGPlayerController::FImpl::FImpl(ASGPlayerController* InOwner)
ASGPlayerController::FImpl::~FImpl() = default; ASGPlayerController::FImpl::~FImpl() = default;
USGCustomWaveform* ASGPlayerController::FImpl::GetCustomWaveform(const AActor* Actor)
{
float Amplitude = 0.0f;
float Duration = 0.0f;
float Frequency = 0.0f;
if (IsValid(Actor))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(Actor);
if (IsValid(TouchComponent))
{
Amplitude = TouchComponent->GetVibrotactileAmplitude();
Duration = TouchComponent->GetVibrotactileDuration();
Frequency = TouchComponent->GetVibrotactileFrequency();
}
}
USGCustomWaveform* CustomWaveform{
USGCustomWaveform::NewCustomWaveform(Owner, Amplitude, Duration, Frequency)
};
return CustomWaveform;
}
void ASGPlayerController::FImpl::UpdateHapticsFeedback(const FSGTouchState& TouchState) void ASGPlayerController::FImpl::UpdateHapticsFeedback(const FSGTouchState& TouchState)
{ {
static const TArray<float> VibrotactileOffCommand{0.0f, 0.0f, 0.0, 0.0, 0.0f}; static const TArray<float> VibrotactileOffCommand{0.0f, 0.0f, 0.0, 0.0, 0.0f};
@@ -359,44 +277,43 @@ void ASGPlayerController::FImpl::UpdateHapticsFeedback(const FSGTouchState& Touc
}; };
Glove->QueueForceFeedbackLevels(MoveTemp(ForceFeedbackLevels)); Glove->QueueForceFeedbackLevels(MoveTemp(ForceFeedbackLevels));
// Queue the Vibrotactile command...
TArray<float> VibrotactileLevels{
GetVibrotactileLevels(
TouchState.ActorThumbTouching, TouchState.ActorIndexTouching, TouchState.ActorMiddleTouching,
TouchState.ActorRingTouching, TouchState.ActorPinkyTouching)
};
Glove->QueueVibroLevels(MoveTemp(VibrotactileLevels));
// Send the haptics commands! // Send the haptics commands!
Glove->SendHaptics(); Glove->SendHaptics();
// Stop the Vibrotactile command after the timeout if any haptic feedback is ongoing. // Send Vibrotactile to the thumb finger if it's touching an actor...
const float VibrotactileDuration = FImpl::GetVibrotactileDuration( if (IsValid(TouchState.ActorThumbTouching))
TouchState.ActorThumbTouching, TouchState.ActorIndexTouching, TouchState.ActorMiddleTouching,
TouchState.ActorRingTouching, TouchState.ActorPinkyTouching);
Owner->GetWorldTimerManager().ClearTimer(TouchVibrotactileStopTimer);
FTimerDelegate TouchVibrotactileStopHandler;
TouchVibrotactileStopHandler.BindLambda([= SG_CAPTURE_THIS]()-> void
{ {
if (!IsValid(Glove)) USGCustomWaveform* CustomWaveform(GetCustomWaveform(TouchState.ActorThumbTouching));
{ Glove->SendCustomWaveform(CustomWaveform, ESGHapticLocation::ThumbTip);
return; }
}
const bool bGloveConnected = Glove->IsConnected(); // Send Vibrotactile to the index finger if it's touching an actor...
if (!bGloveConnected) if (IsValid(TouchState.ActorIndexTouching))
{ {
return; USGCustomWaveform* CustomWaveform(GetCustomWaveform(TouchState.ActorIndexTouching));
} Glove->SendCustomWaveform(CustomWaveform, ESGHapticLocation::IndexTip);
}
Glove->QueueVibroLevels(VibrotactileOffCommand); // Send Vibrotactile to the middle finger if it's touching an actor...
Glove->SendHaptics(); if (IsValid(TouchState.ActorMiddleTouching))
}); {
USGCustomWaveform* CustomWaveform(GetCustomWaveform(TouchState.ActorMiddleTouching));
Glove->SendCustomWaveform(CustomWaveform, ESGHapticLocation::MiddleTip);
}
Owner->GetWorldTimerManager().SetTimer( // Send Vibrotactile to the ring finger if it's touching an actor...
TouchVibrotactileStopTimer, TouchVibrotactileStopHandler, VibrotactileDuration, false, -1.0f); if (IsValid(TouchState.ActorRingTouching))
{
USGCustomWaveform* CustomWaveform(GetCustomWaveform(TouchState.ActorRingTouching));
Glove->SendCustomWaveform(CustomWaveform, ESGHapticLocation::RingTip);
}
// Send Vibrotactile to the pinky finger if it's touching an actor...
if (IsValid(TouchState.ActorPinkyTouching))
{
USGCustomWaveform* CustomWaveform(GetCustomWaveform(TouchState.ActorPinkyTouching));
Glove->SendCustomWaveform(CustomWaveform, ESGHapticLocation::PinkyTip);
}
} }
void ASGPlayerController::FImplDeleter::operator()(const FImpl* P) const void ASGPlayerController::FImplDeleter::operator()(const FImpl* P) const
@@ -57,12 +57,17 @@ private:
meta=(AllowPrivateAccess="false", ClampMin = "0.0", ClampMax = "1.0", UIMin = "0.0", UIMax = "1.0")) meta=(AllowPrivateAccess="false", ClampMin = "0.0", ClampMax = "1.0", UIMin = "0.0", UIMax = "1.0"))
float ForceFeedbackLevel; float ForceFeedbackLevel;
UPROPERTY(EditAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false", ClampMin = "0.0", UIMin = "0.0")) UPROPERTY(EditAnywhere, Category="SenseGlove",
meta=(AllowPrivateAccess="false", ClampMin = "0.0", ClampMax = "1.0", UIMin = "0.0", UIMax = "1.0"))
float VibrotactileAmplitude;
UPROPERTY(EditAnywhere, Category="SenseGlove",
meta=(AllowPrivateAccess="false", ClampMin = "0.0", ClampMax = "1.0", UIMin = "0.0", UIMax = "1.0"))
float VibrotactileDuration; float VibrotactileDuration;
UPROPERTY(EditAnywhere, Category="SenseGlove", UPROPERTY(EditAnywhere, Category="SenseGlove",
meta=(AllowPrivateAccess="false", ClampMin = "0.0", ClampMax = "100.0", UIMin = "0.0", UIMax = "100.0")) meta=(AllowPrivateAccess="false", ClampMin = "10.0", ClampMax = "500.0", UIMin = "10.0", UIMax = "500.0"))
float VibrotactileLevel; float VibrotactileFrequency;
private: private:
struct FImpl; struct FImpl;
@@ -86,6 +91,16 @@ public:
ForceFeedbackLevel = Level; ForceFeedbackLevel = Level;
} }
FORCEINLINE float GetVibrotactileAmplitude() const
{
return VibrotactileAmplitude;
}
FORCEINLINE void SetVibrotactileAmplitude(const float Amplitude)
{
VibrotactileAmplitude = Amplitude;
}
FORCEINLINE float GetVibrotactileDuration() const FORCEINLINE float GetVibrotactileDuration() const
{ {
return VibrotactileDuration; return VibrotactileDuration;
@@ -95,13 +110,14 @@ public:
{ {
VibrotactileDuration = Duration; VibrotactileDuration = Duration;
} }
FORCEINLINE float GetVibrotactileLevel() const
FORCEINLINE float GetVibrotactileFrequency() const
{ {
return VibrotactileLevel; return VibrotactileFrequency;
} }
FORCEINLINE void SetVibrotactileLevel(const float Level) FORCEINLINE void SetVibrotactileFrequency(const float Frequency)
{ {
VibrotactileLevel = Level; VibrotactileFrequency = Frequency;
} }
}; };
@@ -181,16 +181,8 @@ public:
bool IsGloveConnected() const; bool IsGloveConnected() const;
USGHapticGlove* GetConnectedGlove() const; USGHapticGlove* GetConnectedGlove() const;
UE_DEPRECATED(5.5, "Deprecated by UE 5.5 in favor of GetMotionControllerState and GetHandTrackingState")
bool GetMotionControllerData(FXRMotionControllerData& OutMotionControllerData);
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
bool GetMotionControllerState( const FXRHandTrackingState& GetHandTrackingState() const;
EXRSpaceType XRSpaceType, EXRControllerPoseType XRControllerPoseType,
FXRMotionControllerState& OutMotionControllerState);
bool GetHandTrackingState(
EXRSpaceType XRSpaceType,
FXRHandTrackingState& OutHandTrackingState);
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
public: public:
@@ -165,15 +165,7 @@ protected:
FActorComponentTickFunction* ThisTickFunction); FActorComponentTickFunction* ThisTickFunction);
public: public:
UE_DEPRECATED(5.5, "Deprecated by UE 5.5 in favor of GetMotionControllerState and GetHandTrackingState")
bool GetMotionControllerData(FXRMotionControllerData& OutMotionControllerData);
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
bool GetMotionControllerState( const FXRHandTrackingState& GetHandTrackingState() const;
EXRSpaceType XRSpaceType, EXRControllerPoseType XRControllerPoseType,
FXRMotionControllerState& OutMotionControllerState);
bool GetHandTrackingState(
EXRSpaceType XRSpaceType,
FXRHandTrackingState& OutHandTrackingState);
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
}; };
-5
View File
@@ -54,12 +54,7 @@ public class SenseGlove : ModuleRules
"InputCore", "InputCore",
"InputDevice", "InputDevice",
"OpenXRHMD", "OpenXRHMD",
// NOTE
// UE 5.3+ provides UXRDeviceVisualizationComponent as part of the XRBase plugin.
// UE 5.2 provides UXRDeviceVisualizationComponent as part of the HeadMountDisplay module.
#if UE_5_3_OR_LATER
"XRBase", "XRBase",
#endif
} }
); );
@@ -36,6 +36,7 @@
#include "SGBackend/SGBackend.h" #include "SGBackend/SGBackend.h"
#include "Engine/Engine.h" #include "Engine/Engine.h"
#include "Templates/Atomic.h"
#if PLATFORM_ANDROID #if PLATFORM_ANDROID
#include "SGConnect/SGConnect.h" #include "SGConnect/SGConnect.h"
@@ -47,6 +48,12 @@
struct USGBackend::FImpl struct USGBackend::FImpl
{ {
/************************
* Member variables
************************/
TAtomic<bool> bInitialized;
/************************ /************************
* Owner object * Owner object
************************/ ************************/
@@ -64,8 +71,8 @@ struct USGBackend::FImpl
* Default copy constructor & copy assignment operator * Default copy constructor & copy assignment operator
************************/ ************************/
FImpl(const FImpl& Rhs) = default; FImpl(const FImpl& Rhs) = delete;
FImpl& operator=(const FImpl& Rhs) = default; FImpl& operator=(const FImpl& Rhs) = delete;
}; };
USGBackend* USGBackend::GetInstance() USGBackend* USGBackend::GetInstance()
@@ -82,7 +89,11 @@ USGBackend* USGBackend::GetInstance()
USGBackend::USGBackend() USGBackend::USGBackend()
: Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter)) : Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
{ {
bBackendInitialized = false; }
bool USGBackend::IsBackendInitialized() const
{
return Pimpl->bInitialized;
} }
bool USGBackend::InitializeBackend() bool USGBackend::InitializeBackend()
@@ -130,7 +141,7 @@ bool USGBackend::InitializeBackend()
FSGDeviceList::Dispose(); FSGDeviceList::Dispose();
FSGDeviceList::Reinitialize(); FSGDeviceList::Reinitialize();
bBackendInitialized = true; Pimpl->bInitialized = true;
return true; return true;
} }
@@ -181,7 +192,7 @@ bool USGBackend::UninitializeBackend()
} }
#endif /* PLATFORM_ANDROID */ #endif /* PLATFORM_ANDROID */
bBackendInitialized = false; Pimpl->bInitialized = false;
return true; return true;
} }
@@ -229,13 +240,14 @@ void USGBackend::Deinitialize()
SGLOG_ERROR("Failed to uninitialize the bridge to the SenseGlove Backend!") SGLOG_ERROR("Failed to uninitialize the bridge to the SenseGlove Backend!")
} }
(void)Pimpl.Release(); (void) Pimpl.Release();
SGLOG("The SenseGlove Backend singleton has been successfully de-initialized!"); SGLOG("The SenseGlove Backend singleton has been successfully de-initialized!");
} }
USGBackend::FImpl::FImpl(USGBackend* InOwner) USGBackend::FImpl::FImpl(USGBackend* InOwner)
: Owner(InOwner) : bInitialized(false),
Owner(InOwner)
{ {
} }
@@ -49,10 +49,6 @@ class SENSEGLOVEBACKEND_API USGBackend : public UEngineSubsystem
{ {
GENERATED_BODY() GENERATED_BODY()
private:
UPROPERTY(Transient)
bool bBackendInitialized;
public: public:
static USGBackend* GetInstance(); static USGBackend* GetInstance();
@@ -71,10 +67,7 @@ private:
USGBackend(); USGBackend();
public: public:
FORCEINLINE bool IsBackendInitialized() const bool IsBackendInitialized() const;
{
return bBackendInitialized;
}
bool InitializeBackend(); bool InitializeBackend();
bool UninitializeBackend(); bool UninitializeBackend();
@@ -34,7 +34,6 @@
using System; using System;
using System.IO;
using UnrealBuildTool; using UnrealBuildTool;
public class SenseGloveBuildHacks : ModuleRules public class SenseGloveBuildHacks : ModuleRules
@@ -55,23 +54,19 @@ public class SenseGloveBuildHacks : ModuleRules
} }
); );
PublicDependencyModuleNames.AddRange(
new string[]
{
"SGConnectThirdPartyHeaders",
"SGCoreThirdPartyHeaders",
}
);
PrivateDependencyModuleNames.AddRange( PrivateDependencyModuleNames.AddRange(
new string[] new string[]
{ {
"SenseGloveLog", "SenseGloveLog",
} }
); );
AddConnectHeaders();
}
private void AddConnectHeaders()
{
string PluginRootDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", ".."));
string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source"));
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty"));
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
} }
} }
@@ -34,9 +34,6 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool; using UnrealBuildTool;
public class SenseGloveConnectImpl : ModuleRules public class SenseGloveConnectImpl : ModuleRules
@@ -45,8 +42,8 @@ public class SenseGloveConnectImpl : ModuleRules
{ {
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
bEnableExceptions = true; bEnableExceptions = false;
bUseRTTI = true; bUseRTTI = false;
PrivateDependencyModuleNames.AddRange( PrivateDependencyModuleNames.AddRange(
new string[] new string[]
@@ -57,6 +54,20 @@ public class SenseGloveConnectImpl : ModuleRules
} }
); );
PrivateDependencyModuleNames.AddRange(
new string[]
{
"SGBleThirdPartyLibs",
"SGCommonThirdPartyLibs",
"SGConnectShmThirdPartyLibs",
"SGConnectThirdPartyLibs",
"SGSerialThirdPartyLibs",
"SGFmtThirdPartyLibs",
"SGLoguruThirdPartyLibs",
"SGWjwwoodSerialThirdPartyLibs",
}
);
PrivateDependencyModuleNames.AddRange( PrivateDependencyModuleNames.AddRange(
new string[] new string[]
{ {
@@ -74,373 +85,7 @@ public class SenseGloveConnectImpl : ModuleRules
} }
); );
AddBleLibrary(Target);
AddConnectLibrary(Target);
AddSerialLibrary(Target);
PublicDefinitions.Add("SENSEGLOVE_BUILDING_CONNECT_IMPL_MODULE"); PublicDefinitions.Add("SENSEGLOVE_BUILDING_CONNECT_IMPL_MODULE");
PublicDefinitions.Add("SENSEGLOVE_UNREAL_ENGINE_PLUGIN"); PublicDefinitions.Add("SENSEGLOVE_UNREAL_ENGINE_PLUGIN");
} }
private void AddBleLibrary(ReadOnlyTargetRules Target)
{
string PluginRootDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", ".."));
string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source"));
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty"));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidArm64 = "";
string LibraryPathAnroidx64 = "";
string LibraryName = "sgble";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "rustc"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "rustc"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "rustc"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, "debug"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "debug"));
}
else
{
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, "release"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "release"));
}
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, LibraryName));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidArm64);
PublicAdditionalLibraries.Add(LibraryPathAnroidx64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
if (bIsWin64)
{
PublicAdditionalLibraries.AddRange(new string[]
{
"bcrypt.lib",
"ntdll.lib",
"propsys.lib",
"runtimeobject.lib",
"userenv.lib",
"ws2_32.lib"
});
}
}
private void AddConnectLibrary(ReadOnlyTargetRules Target)
{
string PluginRootDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", ".."));
string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source"));
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty"));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidArm64 = "";
string LibraryPathAnroidx64 = "";
string LibraryName = "sgconnect";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName);
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v24"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_3_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#elif UE_5_2_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v21"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName);
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v24"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_3_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#elif UE_5_2_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v21"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "msvc143"));
break;
#if ! UE_5_4_OR_LATER
case WindowsCompiler.VisualStudio2019:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "msvc142"));
break;
#endif
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, "debug"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "debug"));
}
else
{
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, "release"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "release"));
}
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, LibraryName));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidArm64);
PublicAdditionalLibraries.Add(LibraryPathAnroidx64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
private void AddSerialLibrary(ReadOnlyTargetRules Target)
{
string PluginRootDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", ".."));
string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source"));
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty"));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidArm64 = "";
string LibraryPathAnroidx64 = "";
string LibraryName = "serial";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName);
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v24"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_3_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#elif UE_5_2_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v21"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName);
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v24"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_3_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#elif UE_5_2_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v21"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "msvc143"));
break;
#if ! UE_5_4_OR_LATER
case WindowsCompiler.VisualStudio2019:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "msvc142"));
break;
#endif
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, "debug"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "debug"));
}
else
{
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, "release"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "release"));
}
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, LibraryName));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidArm64);
PublicAdditionalLibraries.Add(LibraryPathAnroidx64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
} }
@@ -51,7 +51,6 @@ public class SenseGloveCore : ModuleRules
} }
); );
PrivateDependencyModuleNames.AddRange( PrivateDependencyModuleNames.AddRange(
new string[] new string[]
{ {
@@ -35,6 +35,8 @@
#include "SGCoreImpl/SGBetaDeviceImpl.h" #include "SGCoreImpl/SGBetaDeviceImpl.h"
#include <memory>
#include "Containers/StringConv.h" #include "Containers/StringConv.h"
#include "Misc/AssertionMacros.h" #include "Misc/AssertionMacros.h"
@@ -70,7 +72,7 @@ TSharedRef<FSGBetaDeviceImpl> FSGBetaDeviceImpl::Parse(const FString& String)
FSGDevicePtrType SGDevicePtr{FBetaDeviceType::Parse(TCHAR_TO_UTF8(*String))}; FSGDevicePtrType SGDevicePtr{FBetaDeviceType::Parse(TCHAR_TO_UTF8(*String))};
ensureAlwaysMsgf(SGDevicePtr, TEXT("Invalid SGDevice!")); ensureAlwaysMsgf(SGDevicePtr, TEXT("Invalid SGDevice!"));
const TSharedRef<FSGBetaDeviceImpl> BetaDeviceImpl{ const TSharedRef<FSGBetaDeviceImpl> BetaDeviceImpl{
MakeShared<FSGBetaDeviceImpl>(std::dynamic_pointer_cast<FBetaDeviceType>(MoveTemp(SGDevicePtr))) MakeShared<FSGBetaDeviceImpl>(std::static_pointer_cast<FBetaDeviceType>(MoveTemp(SGDevicePtr)))
}; };
return BetaDeviceImpl; return BetaDeviceImpl;
} }
@@ -133,12 +135,12 @@ FSGBetaDeviceImpl::FBetaDeviceType FSGBetaDeviceImpl::ToBetaDevice() const
FSGBetaDeviceImpl::FBetaDevicePtrType FSGBetaDeviceImpl::ToBetaDevicePtr() const FSGBetaDeviceImpl::FBetaDevicePtrType FSGBetaDeviceImpl::ToBetaDevicePtr() const
{ {
return std::dynamic_pointer_cast<FBetaDeviceType>(ToSGDevicePtr()); return std::static_pointer_cast<FBetaDeviceType>(ToSGDevicePtr());
} }
FSGBetaDeviceImpl::FBetaDevicePtrType FSGBetaDeviceImpl::ToBetaDevicePtrChecked() const FSGBetaDeviceImpl::FBetaDevicePtrType FSGBetaDeviceImpl::ToBetaDevicePtrChecked() const
{ {
FBetaDevicePtrType BetaDevice = std::dynamic_pointer_cast<FBetaDeviceType>(ToSGDevicePtr()); FBetaDevicePtrType BetaDevice = std::static_pointer_cast<FBetaDeviceType>(ToSGDevicePtr());
ensureAlwaysMsgf(BetaDevice.get(), TEXT("Invalid BetaDevice")); ensureAlwaysMsgf(BetaDevice.get(), TEXT("Invalid BetaDevice"));
return BetaDevice; return BetaDevice;
} }
@@ -35,6 +35,7 @@
#include "SGCoreImpl/SGDeviceImpl.h" #include "SGCoreImpl/SGDeviceImpl.h"
#include <memory>
#include <string> #include <string>
#include "Containers/StringConv.h" #include "Containers/StringConv.h"
@@ -157,35 +158,35 @@ TSharedRef<FSGDeviceImpl> FSGDeviceImpl::ToSGDeviceImplRef()
TSharedRef<FSGBetaDeviceImpl> FSGDeviceImpl::ToBetaDeviceImplRef() TSharedRef<FSGBetaDeviceImpl> FSGDeviceImpl::ToBetaDeviceImplRef()
{ {
FSGBetaDeviceImpl* BetaDevice{dynamic_cast<FSGBetaDeviceImpl*>(this)}; FSGBetaDeviceImpl* BetaDevice{static_cast<FSGBetaDeviceImpl*>(this)};
ensureAlwaysMsgf(BetaDevice, TEXT("Invalid BetaDevice!")); ensureAlwaysMsgf(BetaDevice, TEXT("Invalid BetaDevice!"));
return SharedThis(BetaDevice); return SharedThis(BetaDevice);
} }
TSharedRef<FSGHapticGloveImpl> FSGDeviceImpl::ToHapticGloveImplRef() TSharedRef<FSGHapticGloveImpl> FSGDeviceImpl::ToHapticGloveImplRef()
{ {
FSGHapticGloveImpl* HapticGlove{dynamic_cast<FSGHapticGloveImpl*>(this)}; FSGHapticGloveImpl* HapticGlove{static_cast<FSGHapticGloveImpl*>(this)};
ensureAlwaysMsgf(HapticGlove, TEXT("Invalid HapticGlove!")); ensureAlwaysMsgf(HapticGlove, TEXT("Invalid HapticGlove!"));
return SharedThis(HapticGlove); return SharedThis(HapticGlove);
} }
TSharedRef<FSGNova2GloveImpl> FSGDeviceImpl::ToNova2GloveImplRef() TSharedRef<FSGNova2GloveImpl> FSGDeviceImpl::ToNova2GloveImplRef()
{ {
FSGNova2GloveImpl* Nova2Glove{dynamic_cast<FSGNova2GloveImpl*>(this)}; FSGNova2GloveImpl* Nova2Glove{static_cast<FSGNova2GloveImpl*>(this)};
ensureAlwaysMsgf(Nova2Glove, TEXT("Invalid Nova2Glove!")); ensureAlwaysMsgf(Nova2Glove, TEXT("Invalid Nova2Glove!"));
return SharedThis(Nova2Glove); return SharedThis(Nova2Glove);
} }
TSharedRef<FSGNovaGloveImpl> FSGDeviceImpl::ToNovaGloveImplRef() TSharedRef<FSGNovaGloveImpl> FSGDeviceImpl::ToNovaGloveImplRef()
{ {
FSGNovaGloveImpl* NovaGlove{dynamic_cast<FSGNovaGloveImpl*>(this)}; FSGNovaGloveImpl* NovaGlove{static_cast<FSGNovaGloveImpl*>(this)};
ensureAlwaysMsgf(NovaGlove, TEXT("Invalid NovaGlove!")); ensureAlwaysMsgf(NovaGlove, TEXT("Invalid NovaGlove!"));
return SharedThis(NovaGlove); return SharedThis(NovaGlove);
} }
TSharedRef<FSGSenseGloveImpl> FSGDeviceImpl::ToSenseGloveImplRef() TSharedRef<FSGSenseGloveImpl> FSGDeviceImpl::ToSenseGloveImplRef()
{ {
FSGSenseGloveImpl* SenseGlove{dynamic_cast<FSGSenseGloveImpl*>(this)}; FSGSenseGloveImpl* SenseGlove{static_cast<FSGSenseGloveImpl*>(this)};
ensureAlwaysMsgf(SenseGlove, TEXT("Invalid SenseGlove!")); ensureAlwaysMsgf(SenseGlove, TEXT("Invalid SenseGlove!"));
return SharedThis(SenseGlove); return SharedThis(SenseGlove);
} }
@@ -193,7 +194,7 @@ TSharedRef<FSGSenseGloveImpl> FSGDeviceImpl::ToSenseGloveImplRef()
bool FSGDeviceImpl::IsABetaDevice() const bool FSGDeviceImpl::IsABetaDevice() const
{ {
const FSGBetaDeviceImpl::FBetaDevicePtrType BetaDevice{ const FSGBetaDeviceImpl::FBetaDevicePtrType BetaDevice{
std::dynamic_pointer_cast<FSGBetaDeviceImpl::FBetaDeviceType>(ToSGDevicePtr()) std::static_pointer_cast<FSGBetaDeviceImpl::FBetaDeviceType>(ToSGDevicePtr())
}; };
return BetaDevice != nullptr; return BetaDevice != nullptr;
} }
@@ -201,7 +202,7 @@ bool FSGDeviceImpl::IsABetaDevice() const
bool FSGDeviceImpl::IsAHapticGlove() const bool FSGDeviceImpl::IsAHapticGlove() const
{ {
const FSGHapticGloveImpl::FHapticGlovePtrType HapticGlove{ const FSGHapticGloveImpl::FHapticGlovePtrType HapticGlove{
std::dynamic_pointer_cast<FSGHapticGloveImpl::FHapticGloveType>(ToSGDevicePtr()) std::static_pointer_cast<FSGHapticGloveImpl::FHapticGloveType>(ToSGDevicePtr())
}; };
return HapticGlove != nullptr; return HapticGlove != nullptr;
} }
@@ -209,7 +210,7 @@ bool FSGDeviceImpl::IsAHapticGlove() const
bool FSGDeviceImpl::IsANova2Glove() const bool FSGDeviceImpl::IsANova2Glove() const
{ {
const FSGNova2GloveImpl::FNova2GlovePtrType Nova2Glove{ const FSGNova2GloveImpl::FNova2GlovePtrType Nova2Glove{
std::dynamic_pointer_cast<FSGNova2GloveImpl::FNova2GloveType>(ToSGDevicePtr()) std::static_pointer_cast<FSGNova2GloveImpl::FNova2GloveType>(ToSGDevicePtr())
}; };
return Nova2Glove != nullptr; return Nova2Glove != nullptr;
} }
@@ -217,7 +218,7 @@ bool FSGDeviceImpl::IsANova2Glove() const
bool FSGDeviceImpl::IsANovaGlove() const bool FSGDeviceImpl::IsANovaGlove() const
{ {
const FSGNovaGloveImpl::FNovaGlovePtrType NovaGlove{ const FSGNovaGloveImpl::FNovaGlovePtrType NovaGlove{
std::dynamic_pointer_cast<FSGNovaGloveImpl::FNovaGloveType>(ToSGDevicePtr()) std::static_pointer_cast<FSGNovaGloveImpl::FNovaGloveType>(ToSGDevicePtr())
}; };
return NovaGlove != nullptr; return NovaGlove != nullptr;
} }
@@ -225,7 +226,7 @@ bool FSGDeviceImpl::IsANovaGlove() const
bool FSGDeviceImpl::IsASenseGlove() const bool FSGDeviceImpl::IsASenseGlove() const
{ {
const FSGSenseGloveImpl::FSenseGlovePtrType SenseGlove{ const FSGSenseGloveImpl::FSenseGlovePtrType SenseGlove{
std::dynamic_pointer_cast<FSGSenseGloveImpl::FSenseGloveType>(ToSGDevicePtr()) std::static_pointer_cast<FSGSenseGloveImpl::FSenseGloveType>(ToSGDevicePtr())
}; };
return SenseGlove != nullptr; return SenseGlove != nullptr;
} }
@@ -233,7 +234,7 @@ bool FSGDeviceImpl::IsASenseGlove() const
TSharedPtr<FSGBetaDeviceImpl> FSGDeviceImpl::AsBetaDevice() const TSharedPtr<FSGBetaDeviceImpl> FSGDeviceImpl::AsBetaDevice() const
{ {
const FSGBetaDeviceImpl::FBetaDevicePtrType BetaDevice{ const FSGBetaDeviceImpl::FBetaDevicePtrType BetaDevice{
std::dynamic_pointer_cast<FSGBetaDeviceImpl::FBetaDeviceType>(ToSGDevicePtr()) std::static_pointer_cast<FSGBetaDeviceImpl::FBetaDeviceType>(ToSGDevicePtr())
}; };
ensureAlwaysMsgf(BetaDevice, TEXT("Invalid BetaDevice!")); ensureAlwaysMsgf(BetaDevice, TEXT("Invalid BetaDevice!"));
return MakeShared<FSGBetaDeviceImpl>(BetaDevice); return MakeShared<FSGBetaDeviceImpl>(BetaDevice);
@@ -242,7 +243,7 @@ TSharedPtr<FSGBetaDeviceImpl> FSGDeviceImpl::AsBetaDevice() const
TSharedPtr<FSGHapticGloveImpl> FSGDeviceImpl::AsHapticGlove() const TSharedPtr<FSGHapticGloveImpl> FSGDeviceImpl::AsHapticGlove() const
{ {
const FSGHapticGloveImpl::FHapticGlovePtrType HapticGlove{ const FSGHapticGloveImpl::FHapticGlovePtrType HapticGlove{
std::dynamic_pointer_cast<FSGHapticGloveImpl::FHapticGloveType>(ToSGDevicePtr()) std::static_pointer_cast<FSGHapticGloveImpl::FHapticGloveType>(ToSGDevicePtr())
}; };
ensureAlwaysMsgf(HapticGlove, TEXT("Invalid HapticGlove!")); ensureAlwaysMsgf(HapticGlove, TEXT("Invalid HapticGlove!"));
return MakeShared<FSGHapticGloveImpl>(HapticGlove); return MakeShared<FSGHapticGloveImpl>(HapticGlove);
@@ -251,7 +252,7 @@ TSharedPtr<FSGHapticGloveImpl> FSGDeviceImpl::AsHapticGlove() const
TSharedPtr<FSGNova2GloveImpl> FSGDeviceImpl::AsNova2Glove() const TSharedPtr<FSGNova2GloveImpl> FSGDeviceImpl::AsNova2Glove() const
{ {
const FSGNova2GloveImpl::FNova2GlovePtrType Nova2Glove{ const FSGNova2GloveImpl::FNova2GlovePtrType Nova2Glove{
std::dynamic_pointer_cast<FSGNova2GloveImpl::FNova2GloveType>(ToSGDevicePtr()) std::static_pointer_cast<FSGNova2GloveImpl::FNova2GloveType>(ToSGDevicePtr())
}; };
ensureAlwaysMsgf(Nova2Glove, TEXT("Invalid Nova2Glove!")); ensureAlwaysMsgf(Nova2Glove, TEXT("Invalid Nova2Glove!"));
return MakeShared<FSGNova2GloveImpl>(Nova2Glove); return MakeShared<FSGNova2GloveImpl>(Nova2Glove);
@@ -260,7 +261,7 @@ TSharedPtr<FSGNova2GloveImpl> FSGDeviceImpl::AsNova2Glove() const
TSharedPtr<FSGNovaGloveImpl> FSGDeviceImpl::AsNovaGlove() const TSharedPtr<FSGNovaGloveImpl> FSGDeviceImpl::AsNovaGlove() const
{ {
const FSGNovaGloveImpl::FNovaGlovePtrType NovaGlove{ const FSGNovaGloveImpl::FNovaGlovePtrType NovaGlove{
std::dynamic_pointer_cast<FSGNovaGloveImpl::FNovaGloveType>(ToSGDevicePtr()) std::static_pointer_cast<FSGNovaGloveImpl::FNovaGloveType>(ToSGDevicePtr())
}; };
ensureAlwaysMsgf(NovaGlove, TEXT("Invalid NovaGlove!")); ensureAlwaysMsgf(NovaGlove, TEXT("Invalid NovaGlove!"));
return MakeShared<FSGNovaGloveImpl>(NovaGlove); return MakeShared<FSGNovaGloveImpl>(NovaGlove);
@@ -269,7 +270,7 @@ TSharedPtr<FSGNovaGloveImpl> FSGDeviceImpl::AsNovaGlove() const
TSharedPtr<FSGSenseGloveImpl> FSGDeviceImpl::AsSenseGlove() const TSharedPtr<FSGSenseGloveImpl> FSGDeviceImpl::AsSenseGlove() const
{ {
const FSGSenseGloveImpl::FSenseGlovePtrType SenseGlove{ const FSGSenseGloveImpl::FSenseGlovePtrType SenseGlove{
std::dynamic_pointer_cast<FSGSenseGloveImpl::FSenseGloveType>(ToSGDevicePtr()) std::static_pointer_cast<FSGSenseGloveImpl::FSenseGloveType>(ToSGDevicePtr())
}; };
ensureAlwaysMsgf(SenseGlove, TEXT("Invalid SenseGlove!")); ensureAlwaysMsgf(SenseGlove, TEXT("Invalid SenseGlove!"));
return MakeShared<FSGSenseGloveImpl>(SenseGlove); return MakeShared<FSGSenseGloveImpl>(SenseGlove);
@@ -35,6 +35,7 @@
#include "SGCoreImpl/SGDeviceListImpl.h" #include "SGCoreImpl/SGDeviceListImpl.h"
#include <memory>
#include <string> #include <string>
#include "Containers/StringConv.h" #include "Containers/StringConv.h"
@@ -83,7 +84,7 @@ TArray<TSharedRef<FSGDeviceImpl>> FSGDeviceListImpl::GetDevices()
case ESGDeviceType::BetaDevice: case ESGDeviceType::BetaDevice:
{ {
FSGBetaDeviceImpl::FBetaDevicePtrType BetaDevice = FSGBetaDeviceImpl::FBetaDevicePtrType BetaDevice =
std::dynamic_pointer_cast<FSGBetaDeviceImpl::FBetaDeviceType>(Device); std::static_pointer_cast<FSGBetaDeviceImpl::FBetaDeviceType>(Device);
if (ensureAlwaysMsgf(BetaDevice, TEXT("Invalid BetaDevice!"))) if (ensureAlwaysMsgf(BetaDevice, TEXT("Invalid BetaDevice!")))
{ {
TSharedRef<FSGBetaDeviceImpl> BetaDeviceImpl{ TSharedRef<FSGBetaDeviceImpl> BetaDeviceImpl{
@@ -97,7 +98,7 @@ TArray<TSharedRef<FSGDeviceImpl>> FSGDeviceListImpl::GetDevices()
case ESGDeviceType::Nova2: case ESGDeviceType::Nova2:
{ {
FSGNova2GloveImpl::FNova2GlovePtrType Nova2Glove = FSGNova2GloveImpl::FNova2GlovePtrType Nova2Glove =
std::dynamic_pointer_cast<FSGNova2GloveImpl::FNova2GloveType>(Device); std::static_pointer_cast<FSGNova2GloveImpl::FNova2GloveType>(Device);
if (ensureAlwaysMsgf(Nova2Glove, TEXT("Invalid Nova2Glove device!"))) if (ensureAlwaysMsgf(Nova2Glove, TEXT("Invalid Nova2Glove device!")))
{ {
TSharedRef<FSGNova2GloveImpl> Nova2GloveImpl{MakeShared<FSGNova2GloveImpl>(Nova2Glove)}; TSharedRef<FSGNova2GloveImpl> Nova2GloveImpl{MakeShared<FSGNova2GloveImpl>(Nova2Glove)};
@@ -109,7 +110,7 @@ TArray<TSharedRef<FSGDeviceImpl>> FSGDeviceListImpl::GetDevices()
case ESGDeviceType::Nova: case ESGDeviceType::Nova:
{ {
FSGNovaGloveImpl::FNovaGlovePtrType NovaGlove = FSGNovaGloveImpl::FNovaGlovePtrType NovaGlove =
std::dynamic_pointer_cast<FSGNovaGloveImpl::FNovaGloveType>(Device); std::static_pointer_cast<FSGNovaGloveImpl::FNovaGloveType>(Device);
if (ensureAlwaysMsgf(NovaGlove, TEXT("Invalid NovaGlove device!"))) if (ensureAlwaysMsgf(NovaGlove, TEXT("Invalid NovaGlove device!")))
{ {
TSharedRef<FSGNovaGloveImpl> NovaGloveImpl{MakeShared<FSGNovaGloveImpl>(NovaGlove)}; TSharedRef<FSGNovaGloveImpl> NovaGloveImpl{MakeShared<FSGNovaGloveImpl>(NovaGlove)};
@@ -121,7 +122,7 @@ TArray<TSharedRef<FSGDeviceImpl>> FSGDeviceListImpl::GetDevices()
case ESGDeviceType::SenseGlove: case ESGDeviceType::SenseGlove:
{ {
FSGSenseGloveImpl::FSenseGlovePtrType SenseGlove{ FSGSenseGloveImpl::FSenseGlovePtrType SenseGlove{
std::dynamic_pointer_cast<FSGSenseGloveImpl::FSenseGloveType>(Device)}; std::static_pointer_cast<FSGSenseGloveImpl::FSenseGloveType>(Device)};
if (ensureAlwaysMsgf(SenseGlove, TEXT("Invalid SenseGlove device!"))) if (ensureAlwaysMsgf(SenseGlove, TEXT("Invalid SenseGlove device!")))
{ {
TSharedRef<FSGSenseGloveImpl> SenseGloveImpl{ TSharedRef<FSGSenseGloveImpl> SenseGloveImpl{
@@ -134,7 +135,7 @@ TArray<TSharedRef<FSGDeviceImpl>> FSGDeviceListImpl::GetDevices()
default: default:
SGLOG_WARNING( SGLOG_WARNING(
FString::Printf(TEXT("Unknown SenseGlove device '%s'!"), UTF8_TO_TCHAR(typeid(Device).name())), FString::Printf(TEXT("Unknown SenseGlove device '%s'!"), *UEnum::GetValueAsString(FSGCoreEnumCast::ToESGDeviceType(Device->GetDeviceType()))),
FString::Printf(TEXT("Device ID: '%s'!"), UTF8_TO_TCHAR(Device->GetDeviceId().c_str())), FString::Printf(TEXT("Device ID: '%s'!"), UTF8_TO_TCHAR(Device->GetDeviceId().c_str())),
FString::Printf(TEXT("Hardware Version: '%s'!"), UTF8_TO_TCHAR(Device->GetHardwareVersion().c_str())), FString::Printf(TEXT("Hardware Version: '%s'!"), UTF8_TO_TCHAR(Device->GetHardwareVersion().c_str())),
FString::Printf(TEXT("Firmware Version: '%d'!"), Device->GetFirmwareVersion()), FString::Printf(TEXT("Firmware Version: '%d'!"), Device->GetFirmwareVersion()),
@@ -140,7 +140,7 @@ FSGHapticGloveImpl::FSGHapticGloveImpl()
} }
FSGHapticGloveImpl::FSGHapticGloveImpl(const FHapticGlovePtrType HapticGlove) FSGHapticGloveImpl::FSGHapticGloveImpl(const FHapticGlovePtrType HapticGlove)
: FSGDeviceImpl(std::dynamic_pointer_cast<FSGDeviceType>(HapticGlove)), : FSGDeviceImpl(std::static_pointer_cast<FSGDeviceType>(HapticGlove)),
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter)) Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
{ {
} }
@@ -168,12 +168,12 @@ FSGHapticGloveImpl& FSGHapticGloveImpl::operator=(FSGHapticGloveImpl&& Rhs) SG_N
FSGHapticGloveImpl::FHapticGlovePtrType FSGHapticGloveImpl::ToHapticGlovePtr() const FSGHapticGloveImpl::FHapticGlovePtrType FSGHapticGloveImpl::ToHapticGlovePtr() const
{ {
return std::dynamic_pointer_cast<FHapticGloveType>(ToSGDevicePtr()); return std::static_pointer_cast<FHapticGloveType>(ToSGDevicePtr());
} }
FSGHapticGloveImpl::FHapticGlovePtrType FSGHapticGloveImpl::ToHapticGlovePtrChecked() const FSGHapticGloveImpl::FHapticGlovePtrType FSGHapticGloveImpl::ToHapticGlovePtrChecked() const
{ {
FHapticGlovePtrType HapticGlove = std::dynamic_pointer_cast<FHapticGloveType>(ToSGDevicePtr()); FHapticGlovePtrType HapticGlove = std::static_pointer_cast<FHapticGloveType>(ToSGDevicePtr());
ensureAlwaysMsgf(HapticGlove.get(), TEXT("Invalid HapticGlove")); ensureAlwaysMsgf(HapticGlove.get(), TEXT("Invalid HapticGlove"));
return HapticGlove; return HapticGlove;
} }
@@ -93,7 +93,7 @@ TSharedRef<FSGDeviceImpl> FSGNova2GloveImpl::Parse(const FString& ConstantsStrin
FSGDevicePtrType SGDevicePtr{FNova2GloveType::Parse(MoveTemp(ConstantsStdString))}; FSGDevicePtrType SGDevicePtr{FNova2GloveType::Parse(MoveTemp(ConstantsStdString))};
ensureAlwaysMsgf(SGDevicePtr, TEXT("Invalid SGDevice!")); ensureAlwaysMsgf(SGDevicePtr, TEXT("Invalid SGDevice!"));
const TSharedRef<FSGNova2GloveImpl> Nova2GloveImpl{ const TSharedRef<FSGNova2GloveImpl> Nova2GloveImpl{
MakeShared<FSGNova2GloveImpl>(std::dynamic_pointer_cast<FNova2GloveType>(MoveTemp(SGDevicePtr))) MakeShared<FSGNova2GloveImpl>(std::static_pointer_cast<FNova2GloveType>(MoveTemp(SGDevicePtr)))
}; };
return Nova2GloveImpl; return Nova2GloveImpl;
} }
@@ -275,12 +275,12 @@ const FSGNova2GloveImpl::FNova2GloveType& FSGNova2GloveImpl::ToNova2Glove() cons
FSGNova2GloveImpl::FNova2GlovePtrType FSGNova2GloveImpl::ToNova2GlovePtr() const FSGNova2GloveImpl::FNova2GlovePtrType FSGNova2GloveImpl::ToNova2GlovePtr() const
{ {
return std::dynamic_pointer_cast<FNova2GloveType>(ToSGDevicePtr()); return std::static_pointer_cast<FNova2GloveType>(ToSGDevicePtr());
} }
FSGNova2GloveImpl::FNova2GlovePtrType FSGNova2GloveImpl::ToNova2GlovePtrChecked() const FSGNova2GloveImpl::FNova2GlovePtrType FSGNova2GloveImpl::ToNova2GlovePtrChecked() const
{ {
FNova2GlovePtrType Nova2Glove = std::dynamic_pointer_cast<FNova2GloveType>(ToSGDevicePtr()); FNova2GlovePtrType Nova2Glove = std::static_pointer_cast<FNova2GloveType>(ToSGDevicePtr());
ensureAlwaysMsgf(Nova2Glove.get(), TEXT("Invalid Nova2Glove")); ensureAlwaysMsgf(Nova2Glove.get(), TEXT("Invalid Nova2Glove"));
return Nova2Glove; return Nova2Glove;
} }
@@ -95,7 +95,7 @@ TSharedRef<FSGDeviceImpl> FSGNovaGloveImpl::Parse(const FString& ConstantsString
FSGDevicePtrType SGDevicePtr{FNovaGloveType::Parse(MoveTemp(ConstantsStdString))}; FSGDevicePtrType SGDevicePtr{FNovaGloveType::Parse(MoveTemp(ConstantsStdString))};
ensureAlwaysMsgf(SGDevicePtr, TEXT("Invalid SGDevice!")); ensureAlwaysMsgf(SGDevicePtr, TEXT("Invalid SGDevice!"));
const TSharedRef<FSGNovaGloveImpl> NovaGloveImpl{MakeShared<FSGNovaGloveImpl>( const TSharedRef<FSGNovaGloveImpl> NovaGloveImpl{MakeShared<FSGNovaGloveImpl>(
std::dynamic_pointer_cast<FNovaGloveType>(MoveTemp(SGDevicePtr)))}; std::static_pointer_cast<FNovaGloveType>(MoveTemp(SGDevicePtr)))};
return NovaGloveImpl; return NovaGloveImpl;
} }
@@ -288,12 +288,12 @@ const FSGNovaGloveImpl::FNovaGloveType& FSGNovaGloveImpl::ToNovaGlove() const
FSGNovaGloveImpl::FNovaGlovePtrType FSGNovaGloveImpl::ToNovaGlovePtr() const FSGNovaGloveImpl::FNovaGlovePtrType FSGNovaGloveImpl::ToNovaGlovePtr() const
{ {
return std::dynamic_pointer_cast<FNovaGloveType>(ToSGDevicePtr()); return std::static_pointer_cast<FNovaGloveType>(ToSGDevicePtr());
} }
FSGNovaGloveImpl::FNovaGlovePtrType FSGNovaGloveImpl::ToNovaGlovePtrChecked() const FSGNovaGloveImpl::FNovaGlovePtrType FSGNovaGloveImpl::ToNovaGlovePtrChecked() const
{ {
FNovaGlovePtrType NovaGlove{std::dynamic_pointer_cast<FNovaGloveType>(ToSGDevicePtr())}; FNovaGlovePtrType NovaGlove{std::static_pointer_cast<FNovaGloveType>(ToSGDevicePtr())};
ensureAlwaysMsgf(NovaGlove.get(), TEXT("Invalid NovaGlove")); ensureAlwaysMsgf(NovaGlove.get(), TEXT("Invalid NovaGlove"));
return NovaGlove; return NovaGlove;
} }
@@ -93,7 +93,7 @@ TSharedRef<FSGDeviceImpl> FSGSenseGloveImpl::Parse(const FString& ConstantsStrin
FSGDevicePtrType SGDevicePtr{FSenseGloveType::Parse(MoveTemp(ConstantsStdString))}; FSGDevicePtrType SGDevicePtr{FSenseGloveType::Parse(MoveTemp(ConstantsStdString))};
ensureAlwaysMsgf(SGDevicePtr, TEXT("Invalid SGDevice!")); ensureAlwaysMsgf(SGDevicePtr, TEXT("Invalid SGDevice!"));
const TSharedRef<FSGSenseGloveImpl> SenseGloveImpl{ const TSharedRef<FSGSenseGloveImpl> SenseGloveImpl{
MakeShared<FSGSenseGloveImpl>(std::dynamic_pointer_cast<FSenseGloveType>(MoveTemp(SGDevicePtr))) MakeShared<FSGSenseGloveImpl>(std::static_pointer_cast<FSenseGloveType>(MoveTemp(SGDevicePtr)))
}; };
return SenseGloveImpl; return SenseGloveImpl;
} }
@@ -277,7 +277,7 @@ FSGSenseGloveImpl::FSGSenseGloveImpl(const FSenseGloveType SenseGlove)
} }
FSGSenseGloveImpl::FSGSenseGloveImpl(const FSenseGlovePtrType SenseGlove) FSGSenseGloveImpl::FSGSenseGloveImpl(const FSenseGlovePtrType SenseGlove)
: FSGHapticGloveImpl(std::dynamic_pointer_cast<FHapticGloveType>(SenseGlove)), : FSGHapticGloveImpl(std::static_pointer_cast<FHapticGloveType>(SenseGlove)),
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter)) Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
{ {
} }
@@ -310,12 +310,12 @@ const FSGSenseGloveImpl::FSenseGloveType& FSGSenseGloveImpl::ToSenseGlove() cons
FSGSenseGloveImpl::FSenseGlovePtrType FSGSenseGloveImpl::ToSenseGlovePtr() const FSGSenseGloveImpl::FSenseGlovePtrType FSGSenseGloveImpl::ToSenseGlovePtr() const
{ {
return std::dynamic_pointer_cast<FSenseGloveType>(ToSGDevicePtr()); return std::static_pointer_cast<FSenseGloveType>(ToSGDevicePtr());
} }
FSGSenseGloveImpl::FSenseGlovePtrType FSGSenseGloveImpl::ToSenseGlovePtrChecked() const FSGSenseGloveImpl::FSenseGlovePtrType FSGSenseGloveImpl::ToSenseGlovePtrChecked() const
{ {
FSenseGlovePtrType SenseGlove = std::dynamic_pointer_cast<FSenseGloveType>(ToSGDevicePtr()); FSenseGlovePtrType SenseGlove = std::static_pointer_cast<FSenseGloveType>(ToSGDevicePtr());
ensureAlwaysMsgf(SenseGlove.get(), TEXT("Invalid SenseGlove")); ensureAlwaysMsgf(SenseGlove.get(), TEXT("Invalid SenseGlove"));
return SenseGlove; return SenseGlove;
} }
@@ -64,15 +64,35 @@ public:
template <typename T> template <typename T>
static TArray<TSharedRef<FSGDeviceImpl>> GetDevices() static TArray<TSharedRef<FSGDeviceImpl>> GetDevices()
{ {
const std::type_info& TType = typeid(T); ESGDeviceType TargetType = ESGDeviceType::Unknown;
if constexpr (std::is_same_v<T, FSGNova2GloveImpl>)
{
TargetType = ESGDeviceType::Nova2;
}
else if constexpr (std::is_same_v<T, FSGNovaGloveImpl>)
{
TargetType = ESGDeviceType::Nova;
}
else if constexpr (std::is_same_v<T, FSGSenseGloveImpl>)
{
TargetType = ESGDeviceType::SenseGlove;
}
else if constexpr (std::is_same_v<T, FSGBetaDeviceImpl>)
{
TargetType = ESGDeviceType::BetaDevice;
}
else
{
static_assert(!sizeof(T), "Unsupported device type in GetDevices<T>()");
}
const TArray<TSharedRef<FSGDeviceImpl>> CurrentDevices = GetDevices(); const TArray<TSharedRef<FSGDeviceImpl>> CurrentDevices = GetDevices();
TArray<TSharedRef<FSGDeviceImpl>> Devices; TArray<TSharedRef<FSGDeviceImpl>> Devices;
for (TSharedRef<FSGDeviceImpl> Device : CurrentDevices) for (TSharedRef<FSGDeviceImpl> Device : CurrentDevices)
{ {
auto &d = Device.Get(); if (Device->GetDeviceType() == TargetType)
const std::type_info& DType = typeid(d);
if (DType.hash_code() == TType.hash_code())
{ {
Devices.Push(Device); Devices.Push(Device);
} }
@@ -34,9 +34,6 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool; using UnrealBuildTool;
public class SenseGloveCoreImpl : ModuleRules public class SenseGloveCoreImpl : ModuleRules
@@ -45,8 +42,8 @@ public class SenseGloveCoreImpl : ModuleRules
{ {
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
bEnableExceptions = true; bEnableExceptions = false;
bUseRTTI = true; bUseRTTI = false;
PrivateDependencyModuleNames.AddRange( PrivateDependencyModuleNames.AddRange(
new string[] new string[]
@@ -57,6 +54,18 @@ public class SenseGloveCoreImpl : ModuleRules
} }
); );
PrivateDependencyModuleNames.AddRange(
new string[]
{
"SGCommonThirdPartyLibs",
"SGCoreShmThirdPartyLibs",
"SGCoreThirdPartyLibs",
"SGLogThirdPartyLibs",
"SGFmtThirdPartyLibs",
"SGLoguruThirdPartyLibs",
}
);
PrivateDependencyModuleNames.AddRange( PrivateDependencyModuleNames.AddRange(
new string[] new string[]
{ {
@@ -74,137 +83,7 @@ public class SenseGloveCoreImpl : ModuleRules
} }
); );
AddCoreLibrary(Target);
PublicDefinitions.Add("SENSEGLOVE_BUILDING_CORE_IMPL_MODULE"); PublicDefinitions.Add("SENSEGLOVE_BUILDING_CORE_IMPL_MODULE");
PublicDefinitions.Add("SENSEGLOVE_UNREAL_ENGINE_PLUGIN"); PublicDefinitions.Add("SENSEGLOVE_UNREAL_ENGINE_PLUGIN");
} }
private void AddCoreLibrary(ReadOnlyTargetRules Target)
{
string PluginRootDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", ".."));
string SourceDirectory = Path.GetFullPath(Path.Combine(PluginRootDirectory, "Source"));
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(SourceDirectory, "ThirdParty"));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidArm64 = "";
string LibraryPathAnroidx64 = "";
string LibraryName = "sgcore";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPath, "arm64"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPath, "x64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName);
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v24"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_3_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#elif UE_5_2_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v21"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryName = string.Format("lib{0}.a", LibraryName);
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v24"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_3_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#elif UE_5_2_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v21"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "win64"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "msvc143"));
break;
#if ! UE_5_4_OR_LATER
case WindowsCompiler.VisualStudio2019:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "msvc142"));
break;
#endif
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, "debug"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "debug"));
}
else
{
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, "release"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "release"));
}
LibraryPathAnroidArm64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidArm64, LibraryName));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidArm64);
PublicAdditionalLibraries.Add(LibraryPathAnroidx64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
} }
@@ -44,49 +44,32 @@
#include "SGDebug/SGDebugCube.h" #include "SGDebug/SGDebugCube.h"
#include "SGDebug/SGDebugGizmo.h" #include "SGDebug/SGDebugGizmo.h"
void FSGDebugVirtualHand::Draw(const UWorld* World,
const FXRMotionControllerData& MotionControllerData,
const FSGVirtualHandDebuggingSettings& Settings)
{
ensureAlwaysMsgf(Settings.DrawingMode != ESGDebugVirtualHandDrawingMode::None,
TEXT("Invalid virtual hand drawing mode!"));
ensureAlwaysMsgf(MotionControllerData.bValid,
TEXT("Invalid motion controller data!"));
ensureAlwaysMsgf(MotionControllerData.HandKeyPositions.Num() == MotionControllerData.HandKeyRotations.Num(),
TEXT("Mismatched motion controller data positions and rotations!"));
for (TArray<FVector>::SizeType HandKeyIndex = 0;
HandKeyIndex < MotionControllerData.HandKeyPositions.Num(); ++HandKeyIndex)
{
const FVector& HandKeyPosition{MotionControllerData.HandKeyPositions[HandKeyIndex]};
const FQuat& HandKeyRotation{MotionControllerData.HandKeyRotations[HandKeyIndex]};
if (Settings.DrawingMode == ESGDebugVirtualHandDrawingMode::CubicJoints)
{
FSGDebugCube::Draw(World, HandKeyPosition, HandKeyRotation, Settings.DebugCubicHandSettings);
}
else if (Settings.DrawingMode == ESGDebugVirtualHandDrawingMode::GizmoJoints)
{
FSGDebugGizmo::Draw(World, HandKeyPosition, HandKeyRotation, Settings.DebugGizmoHandSettings);
}
}
}
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
void FSGDebugVirtualHand::Draw(const UWorld* World, void FSGDebugVirtualHand::Draw(
const FXRHandTrackingState& HandTrackingState, const UWorld* World,
const FSGVirtualHandDebuggingSettings& Settings) const FXRHandTrackingState& HandTrackingState,
const FSGVirtualHandDebuggingSettings& Settings)
{ {
ensureAlwaysMsgf(Settings.DrawingMode != ESGDebugVirtualHandDrawingMode::None, if (!ensureAlwaysMsgf(
TEXT("Invalid virtual hand drawing mode!")); Settings.DrawingMode != ESGDebugVirtualHandDrawingMode::None,
TEXT("Invalid virtual hand drawing mode!")))
{
return;
};
ensureAlwaysMsgf(HandTrackingState.bValid, if (!ensureAlwaysMsgf(
TEXT("Invalid hand tracking state!")); HandTrackingState.bValid,
TEXT("Invalid hand tracking state!")))
{
return;
};
ensureAlwaysMsgf(HandTrackingState.HandKeyLocations.Num() == HandTrackingState.HandKeyRotations.Num(), if (!ensureAlwaysMsgf(
TEXT("Mismatched hand tracking state locations and rotations!")); HandTrackingState.HandKeyLocations.Num() == HandTrackingState.HandKeyRotations.Num(),
TEXT("Mismatched hand tracking state locations and rotations!")))
{
return;
};
for (TArray<FVector>::SizeType HandKeyIndex = 0; for (TArray<FVector>::SizeType HandKeyIndex = 0;
HandKeyIndex < HandTrackingState.HandKeyLocations.Num(); ++HandKeyIndex) HandKeyIndex < HandTrackingState.HandKeyLocations.Num(); ++HandKeyIndex)
@@ -48,12 +48,6 @@ class UWorld;
class SENSEGLOVEDEBUG_API FSGDebugVirtualHand final class SENSEGLOVEDEBUG_API FSGDebugVirtualHand final
{ {
public: public:
UE_DEPRECATED(5.5, "Deprecated in favor of the variant that accepts FXRHandTrackingState")
static void Draw(
const UWorld* World,
const FXRMotionControllerData& MotionControllerData,
const FSGVirtualHandDebuggingSettings& Settings);
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
static void Draw( static void Draw(
const UWorld* World, const UWorld* World,
@@ -37,18 +37,6 @@
#include "SGDebug/SGDebugVirtualHand.h" #include "SGDebug/SGDebugVirtualHand.h"
void USGDebugVirtualHandKismetLibrary::Draw_FXRMotionControllerData(
UObject* WorldContextObject,
const FXRMotionControllerData& MotionControllerData,
const FSGVirtualHandDebuggingSettings& Settings)
{
ensureAlwaysMsgf(WorldContextObject, TEXT("Invalid world context object!"));
PRAGMA_DISABLE_DEPRECATION_WARNINGS
FSGDebugVirtualHand::Draw(WorldContextObject->GetWorld(), MotionControllerData, Settings);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
void USGDebugVirtualHandKismetLibrary::Draw_FXRHandTrackingState( void USGDebugVirtualHandKismetLibrary::Draw_FXRHandTrackingState(
UObject* WorldContextObject, UObject* WorldContextObject,
const FXRHandTrackingState& HandTrackingState, const FXRHandTrackingState& HandTrackingState,
@@ -50,13 +50,6 @@ class SENSEGLOVEDEBUGKISMET_API USGDebugVirtualHandKismetLibrary final : public
GENERATED_BODY() GENERATED_BODY()
public: public:
UFUNCTION(BlueprintCallable, DisplayName="Draw", Category="SenseGlove | Debug | Virtual Hand",
meta=(WorldContext="WorldContextObject"))
static void Draw_FXRMotionControllerData(
UObject* WorldContextObject,
const FXRMotionControllerData& MotionControllerData,
const FSGVirtualHandDebuggingSettings& Settings);
UFUNCTION(BlueprintCallable, DisplayName="Draw", Category="SenseGlove | Debug | Virtual Hand", UFUNCTION(BlueprintCallable, DisplayName="Draw", Category="SenseGlove | Debug | Virtual Hand",
meta=(WorldContext="WorldContextObject")) meta=(WorldContext="WorldContextObject"))
static void Draw_FXRHandTrackingState( static void Draw_FXRHandTrackingState(
@@ -60,14 +60,14 @@ void UTouchComponentKismetLibrary::SetForceFeedbackLevel(USGTouchComponent* Touc
TouchComponent->SetForceFeedbackLevel(Level); TouchComponent->SetForceFeedbackLevel(Level);
} }
float UTouchComponentKismetLibrary::GetVibrotactileLevel(const USGTouchComponent* TouchComponent) float UTouchComponentKismetLibrary::GetVibrotactileAmplitude(const USGTouchComponent* TouchComponent)
{ {
return TouchComponent->GetVibrotactileLevel(); return TouchComponent->GetVibrotactileAmplitude();
} }
void UTouchComponentKismetLibrary::SetVibrotactileLevel(USGTouchComponent* TouchComponent, const float Level) void UTouchComponentKismetLibrary::SetVibrotactileAmplitude(USGTouchComponent* TouchComponent, const float Amplitude)
{ {
TouchComponent->SetVibrotactileLevel(Level); TouchComponent->SetVibrotactileAmplitude(Amplitude);
} }
float UTouchComponentKismetLibrary::GetVibrotactileDuration(const USGTouchComponent* TouchComponent) float UTouchComponentKismetLibrary::GetVibrotactileDuration(const USGTouchComponent* TouchComponent)
@@ -78,4 +78,15 @@ float UTouchComponentKismetLibrary::GetVibrotactileDuration(const USGTouchCompon
void UTouchComponentKismetLibrary::SetVibrotactileDuration(USGTouchComponent* TouchComponent, const float Duration) void UTouchComponentKismetLibrary::SetVibrotactileDuration(USGTouchComponent* TouchComponent, const float Duration)
{ {
TouchComponent->SetVibrotactileDuration(Duration); TouchComponent->SetVibrotactileDuration(Duration);
} }
float UTouchComponentKismetLibrary::GetVibrotactileFrequency(const USGTouchComponent* TouchComponent)
{
return TouchComponent->GetVibrotactileFrequency();
}
void UTouchComponentKismetLibrary::SetVibrotactileFrequency(USGTouchComponent* TouchComponent, const float Frequency)
{
TouchComponent->SetVibrotactileFrequency(Frequency);
}
@@ -110,26 +110,10 @@ USGHapticGlove* UVirtualHandComponentKismetLibrary::GetConnectedGlove(
return VirtualHandComponent->GetConnectedGlove(); return VirtualHandComponent->GetConnectedGlove();
} }
bool UVirtualHandComponentKismetLibrary::GetMotionControllerData( const FXRHandTrackingState& UVirtualHandComponentKismetLibrary::GetHandTrackingState(
USGVirtualHandComponent* VirtualHandComponent, FXRMotionControllerData& OutMotionControllerData) USGVirtualHandComponent* VirtualHandComponent)
{ {
PRAGMA_DISABLE_DEPRECATION_WARNINGS return VirtualHandComponent->GetHandTrackingState();
return VirtualHandComponent->GetMotionControllerData(OutMotionControllerData);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
bool UVirtualHandComponentKismetLibrary::GetMotionControllerState(USGVirtualHandComponent* VirtualHandComponent,
const EXRSpaceType XRSpaceType, const EXRControllerPoseType XRControllerPoseType,
FXRMotionControllerState& OutMotionControllerState)
{
return VirtualHandComponent->GetMotionControllerState(
XRSpaceType, XRControllerPoseType, OutMotionControllerState);
}
bool UVirtualHandComponentKismetLibrary::GetHandTrackingState(USGVirtualHandComponent* VirtualHandComponent,
const EXRSpaceType XRSpaceType, FXRHandTrackingState& OutHandTrackingState)
{
return VirtualHandComponent->GetHandTrackingState(XRSpaceType, OutHandTrackingState);
} }
const TArray<FName>& UVirtualHandComponentKismetLibrary::GetHandBoneNames( const TArray<FName>& UVirtualHandComponentKismetLibrary::GetHandBoneNames(
@@ -90,27 +90,8 @@ const FRotator& UWristTrackerComponentKismetLibrary::GetWristRotation(
return WristTrackerComponent->GetWristRotation(); return WristTrackerComponent->GetWristRotation();
} }
bool UWristTrackerComponentKismetLibrary::GetMotionControllerData( const FXRHandTrackingState& UWristTrackerComponentKismetLibrary::GetHandTrackingState(
USGWristTrackerComponent* WristTrackerComponent, FXRMotionControllerData& OutMotionControllerData) USGWristTrackerComponent* WristTrackerComponent)
{ {
PRAGMA_DISABLE_DEPRECATION_WARNINGS return WristTrackerComponent->GetHandTrackingState();
return WristTrackerComponent->GetMotionControllerData(OutMotionControllerData);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
bool UWristTrackerComponentKismetLibrary::GetMotionControllerState(
USGWristTrackerComponent* WristTrackerComponent,
const EXRSpaceType XRSpaceType, const EXRControllerPoseType XRControllerPoseType,
FXRMotionControllerState& OutMotionControllerState)
{
return WristTrackerComponent->GetMotionControllerState(
XRSpaceType, XRControllerPoseType, OutMotionControllerState);
}
bool UWristTrackerComponentKismetLibrary::GetHandTrackingState(
USGWristTrackerComponent* WristTrackerComponent,
const EXRSpaceType XRSpaceType, FXRHandTrackingState& OutHandTrackingState)
{
return WristTrackerComponent->GetHandTrackingState(
XRSpaceType, OutHandTrackingState);
} }
@@ -61,14 +61,20 @@ public:
static void SetForceFeedbackLevel(UPARAM(ref) USGTouchComponent* TouchComponent, float Level); static void SetForceFeedbackLevel(UPARAM(ref) USGTouchComponent* TouchComponent, float Level);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Touch Component") UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Touch Component")
static float GetVibrotactileLevel(const USGTouchComponent* TouchComponent); static float GetVibrotactileAmplitude(const USGTouchComponent* TouchComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Touch Component") UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Touch Component")
static void SetVibrotactileLevel(UPARAM(ref) USGTouchComponent* TouchComponent, float Level); static void SetVibrotactileAmplitude(UPARAM(ref) USGTouchComponent* TouchComponent, float Amplitude);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Touch Component") UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Touch Component")
static float GetVibrotactileDuration(const USGTouchComponent* TouchComponent); static float GetVibrotactileDuration(const USGTouchComponent* TouchComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Touch Component") UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Touch Component")
static void SetVibrotactileDuration(UPARAM(ref) USGTouchComponent* TouchComponent, float Duration); static void SetVibrotactileDuration(UPARAM(ref) USGTouchComponent* TouchComponent, float Duration);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Touch Component")
static float GetVibrotactileFrequency(const USGTouchComponent* TouchComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Touch Component")
static void SetVibrotactileFrequency(UPARAM(ref) USGTouchComponent* TouchComponent, float Frequency);
}; };
@@ -103,18 +103,8 @@ public:
static USGHapticGlove* GetConnectedGlove(const USGVirtualHandComponent* VirtualHandComponent); static USGHapticGlove* GetConnectedGlove(const USGVirtualHandComponent* VirtualHandComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Component") UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Component")
static bool GetMotionControllerData(UPARAM(ref) USGVirtualHandComponent* VirtualHandComponent, static const FXRHandTrackingState& GetHandTrackingState(
FXRMotionControllerData& OutMotionControllerData); UPARAM(ref) USGVirtualHandComponent* VirtualHandComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Component")
static bool GetMotionControllerState(UPARAM(ref) USGVirtualHandComponent* VirtualHandComponent,
EXRSpaceType XRSpaceType, EXRControllerPoseType XRControllerPoseType,
FXRMotionControllerState& OutMotionControllerState);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Component")
static bool GetHandTrackingState(UPARAM(ref) USGVirtualHandComponent* VirtualHandComponent,
EXRSpaceType XRSpaceType,
FXRHandTrackingState& OutHandTrackingState);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Component") UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Component")
static const TArray<FName>& GetHandBoneNames(const USGVirtualHandComponent* VirtualHandComponent); static const TArray<FName>& GetHandBoneNames(const USGVirtualHandComponent* VirtualHandComponent);
@@ -84,16 +84,6 @@ public:
static const FRotator& GetWristRotation(const USGWristTrackerComponent* WristTrackerComponent); static const FRotator& GetWristRotation(const USGWristTrackerComponent* WristTrackerComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Wrist Tracker Component") UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Wrist Tracker Component")
static bool GetMotionControllerData(UPARAM(ref) USGWristTrackerComponent* WristTrackerComponent, static const FXRHandTrackingState& GetHandTrackingState(
FXRMotionControllerData& OutMotionControllerData); UPARAM(ref) USGWristTrackerComponent* WristTrackerComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Wrist Tracker Component")
static bool GetMotionControllerState(UPARAM(ref) USGWristTrackerComponent* WristTrackerComponent,
EXRSpaceType XRSpaceType, EXRControllerPoseType XRControllerPoseType,
FXRMotionControllerState& OutMotionControllerState);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Wrist Tracker Component")
static bool GetHandTrackingState(UPARAM(ref) USGWristTrackerComponent* WristTrackerComponent,
EXRSpaceType XRSpaceType,
FXRHandTrackingState& OutHandTrackingState);
}; };
@@ -49,12 +49,7 @@ public class SenseGloveKismet : ModuleRules
"CoreUObject", "CoreUObject",
"Engine", "Engine",
"HeadMountedDisplay", "HeadMountedDisplay",
// NOTE
// UE 5.3+ provides UXRDeviceVisualizationComponent as part of the XRBase plugin.
// UE 5.2 provides UXRDeviceVisualizationComponent as part of the HeadMountDisplay module.
#if UE_5_3_OR_LATER
"XRBase", "XRBase",
#endif
} }
); );
+111 -71
View File
@@ -34,15 +34,20 @@
#include "SGLog/SGLog.h" #include "SGLog/SGLog.h"
#include "Containers/Map.h" #include "Containers/Map.h"
#include "Logging/LogMacros.h" #include "Logging/LogMacros.h"
#include "Templates/Atomic.h"
DEFINE_LOG_CATEGORY(LogEditor) DEFINE_LOG_CATEGORY(LogEditor)
DEFINE_LOG_CATEGORY(LogGeneric) DEFINE_LOG_CATEGORY(LogGeneric)
struct FSGLogCore::FStaticImpl struct FSGLogCore::FStaticImpl
{ {
public: /************************
* Type definitions
************************/
struct VerbosityMapper struct VerbosityMapper
{ {
FString Tag; FString Tag;
@@ -51,33 +56,56 @@ public:
VerbosityMapper(const FString& InTag, const FColor& InColor); VerbosityMapper(const FString& InTag, const FColor& InColor);
}; };
public: /************************
* Member variables
************************/
TMap<FSGLogCore::EVerbosity, VerbosityMapper> VerbosityMap; TMap<FSGLogCore::EVerbosity, VerbosityMapper> VerbosityMap;
bool bInitialized; TAtomic<bool> bInitialized;
/************************
* Constructor / Destructor
************************/
public:
FStaticImpl(); FStaticImpl();
~FStaticImpl();
}; };
struct FSGLogCore::FImpl struct FSGLogCore::FImpl
{ {
public: /************************
* Member variables
************************/
FSGLogCore::EVerbosity Verbosity; FSGLogCore::EVerbosity Verbosity;
FSGLogCore::ECategory Category; FSGLogCore::ECategory Category;
FString File; FString File;
FString Function; FString Function;
FString Line; FString Line;
/************************
* Constructor / Destructor
************************/
FImpl();
~FImpl();
/************************
* Default copy constructor & copy assignment operator
************************/
FImpl(const FImpl& Rhs) = default;
FImpl& operator=(const FImpl& Rhs) = default;
}; };
FSGLogCore::FStaticImplDeleter FSGLogCore::SPimplDeleter; TUniquePtr<FSGLogCore::FStaticImpl, FSGLogCore::FStaticImplDeleter> FSGLogCore::SPimpl{
std::unique_ptr<FSGLogCore::FStaticImpl, FSGLogCore::FStaticImplDeleter> FSGLogCore::SPimpl = new FStaticImpl{}, FStaticImplDeleter()
std::unique_ptr<FSGLogCore::FStaticImpl, FSGLogCore::FStaticImplDeleter>( };
new FSGLogCore::FStaticImpl{}, FSGLogCore::SPimplDeleter);
FSGLogCore::FSGLogCore(const EVerbosity& Verbosity, const ECategory& Category, const std::string& File, FSGLogCore::FSGLogCore(const EVerbosity& Verbosity, const ECategory& Category, const std::string& File,
const std::string& Function, const int32 Line) const std::string& Function, const int32 Line)
: Pimpl(std::unique_ptr<FImpl, FImplDeleter>(new FImpl{}, PimplDeleter)), : Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{}, PimplDeleter)),
bAnyEntries(false) bAnyEntries(false)
{ {
#if defined ( SENSEGLOVE_LOGGING ) #if defined ( SENSEGLOVE_LOGGING )
@@ -85,12 +113,14 @@ FSGLogCore::FSGLogCore(const EVerbosity& Verbosity, const ECategory& Category, c
{ {
SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Fatal, SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Fatal,
FStaticImpl::VerbosityMapper(TEXT("FATAL"), FColor::White)); FStaticImpl::VerbosityMapper(TEXT("FATAL"), FColor::White));
SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Error, FStaticImpl::VerbosityMapper(TEXT("ERROR"), FColor::Red)); SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Error,
FStaticImpl::VerbosityMapper(TEXT("ERROR"), FColor::Red));
SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Warning, SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Warning,
FStaticImpl::VerbosityMapper(TEXT("WARNING"), FColor::Yellow)); FStaticImpl::VerbosityMapper(TEXT("WARNING"), FColor::Yellow));
SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Display, SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Display,
FStaticImpl::VerbosityMapper(TEXT("DISPLAY"), FColor::Green)); FStaticImpl::VerbosityMapper(TEXT("DISPLAY"), FColor::Green));
SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Log, FStaticImpl::VerbosityMapper(TEXT("LOG"), FColor::Silver)); SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Log,
FStaticImpl::VerbosityMapper(TEXT("LOG"), FColor::Silver));
SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Verbose, SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::Verbose,
FStaticImpl::VerbosityMapper(TEXT("VERBOSE"), FColor::Purple)); FStaticImpl::VerbosityMapper(TEXT("VERBOSE"), FColor::Purple));
SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::VeryVerbose, SPimpl->VerbosityMap.Add(FSGLogCore::EVerbosity::VeryVerbose,
@@ -127,46 +157,46 @@ FSGLogCore::~FSGLogCore()
switch (Verbosity) switch (Verbosity)
{ {
case EVerbosity::Display: case EVerbosity::Display:
{ {
UE_LOG(LogGeneric, Display, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogGeneric, Display, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Error: case EVerbosity::Error:
{ {
UE_LOG(LogGeneric, Error, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogGeneric, Error, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Fatal: case EVerbosity::Fatal:
{ {
UE_LOG(LogGeneric, Fatal, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogGeneric, Fatal, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Log: case EVerbosity::Log:
{ {
UE_LOG(LogGeneric, Log, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogGeneric, Log, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Verbose: case EVerbosity::Verbose:
{ {
UE_LOG(LogGeneric, Verbose, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogGeneric, Verbose, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::VeryVerbose: case EVerbosity::VeryVerbose:
{ {
UE_LOG(LogGeneric, VeryVerbose, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogGeneric, VeryVerbose, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Warning: case EVerbosity::Warning:
{ {
UE_LOG(LogGeneric, Warning, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogGeneric, Warning, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
} }
} }
@@ -176,46 +206,46 @@ FSGLogCore::~FSGLogCore()
switch (Verbosity) switch (Verbosity)
{ {
case EVerbosity::Display: case EVerbosity::Display:
{ {
UE_LOG(LogEditor, Display, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogEditor, Display, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Error: case EVerbosity::Error:
{ {
UE_LOG(LogEditor, Error, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogEditor, Error, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Fatal: case EVerbosity::Fatal:
{ {
UE_LOG(LogEditor, Fatal, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogEditor, Fatal, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Log: case EVerbosity::Log:
{ {
UE_LOG(LogEditor, Log, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogEditor, Log, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Verbose: case EVerbosity::Verbose:
{ {
UE_LOG(LogEditor, Verbose, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogEditor, Verbose, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::VeryVerbose: case EVerbosity::VeryVerbose:
{ {
UE_LOG(LogEditor, VeryVerbose, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogEditor, VeryVerbose, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
case EVerbosity::Warning: case EVerbosity::Warning:
{ {
UE_LOG(LogEditor, Warning, TEXT("%s"), Message.GetCharArray().GetData()); UE_LOG(LogEditor, Warning, TEXT("%s"), Message.GetCharArray().GetData());
} }
break; break;
} }
} }
#endif /* defined ( SENSEGLOVE_LOGGING ) */ #endif /* defined ( SENSEGLOVE_LOGGING ) */
@@ -226,8 +256,10 @@ FSGLogCore::FStaticImpl::FStaticImpl()
{ {
} }
FSGLogCore::FStaticImpl::~FStaticImpl() = default;
FSGLogCore::FStaticImpl::VerbosityMapper::VerbosityMapper(const FString& InTag, FSGLogCore::FStaticImpl::VerbosityMapper::VerbosityMapper(const FString& InTag,
const FColor& InColor) const FColor& InColor)
: Tag(InTag), : Tag(InTag),
Color(InColor) Color(InColor)
{ {
@@ -238,7 +270,15 @@ void FSGLogCore::FStaticImplDeleter::operator()(const FSGLogCore::FStaticImpl* P
delete Pointer; delete Pointer;
} }
FSGLogCore::FImpl::FImpl()
: Verbosity(EVerbosity::Verbose),
Category(ECategory::Generic)
{
}
FSGLogCore::FImpl::~FImpl() = default;
void FSGLogCore::FImplDeleter::operator()(const FSGLogCore::FImpl* Pointer) const void FSGLogCore::FImplDeleter::operator()(const FSGLogCore::FImpl* Pointer) const
{ {
delete Pointer; delete Pointer;
} }
+77 -90
View File
@@ -35,10 +35,9 @@
#pragma once #pragma once
#include <memory>
#include <string>
#include <cstddef> #include <cstddef>
#include <cstdio> #include <cstdio>
#include <string>
#include "Containers/StringConv.h" #include "Containers/StringConv.h"
#include "Containers/UnrealString.h" #include "Containers/UnrealString.h"
@@ -47,6 +46,7 @@
#include "Math/Rotator.h" #include "Math/Rotator.h"
#include "Math/Transform.h" #include "Math/Transform.h"
#include "Math/Vector.h" #include "Math/Vector.h"
#include "Templates/SharedPointer.h"
#include "Templates/UnrealTemplate.h" #include "Templates/UnrealTemplate.h"
DECLARE_LOG_CATEGORY_EXTERN(LogEditor, All, All); DECLARE_LOG_CATEGORY_EXTERN(LogEditor, All, All);
@@ -96,7 +96,7 @@ struct TFSGLogString<const bool>
{ {
static void Format(const bool Value, FString& OutString) static void Format(const bool Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), (Value ? TEXT("True") : TEXT("False"))); OutString = Value ? TEXT("True") : TEXT("False");
} }
}; };
@@ -105,7 +105,7 @@ struct TFSGLogString<bool>
{ {
static void Format(const bool Value, FString& OutString) static void Format(const bool Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), (Value ? TEXT("True") : TEXT("False"))); OutString = Value ? TEXT("True") : TEXT("False");
} }
}; };
@@ -114,7 +114,7 @@ struct TFSGLogString<const char[L]>
{ {
static void Format(const char* Value, FString& OutString) static void Format(const char* Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value).Get()); OutString = FString(UTF8_TO_TCHAR(Value));
} }
}; };
@@ -123,7 +123,7 @@ struct TFSGLogString<char[L]>
{ {
static void Format(const char* Value, FString& OutString) static void Format(const char* Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value).Get()); OutString = FString(UTF8_TO_TCHAR(Value));
} }
}; };
@@ -132,7 +132,7 @@ struct TFSGLogString<const char*>
{ {
static void Format(const char* Value, FString& OutString) static void Format(const char* Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value).Get()); OutString = FString(UTF8_TO_TCHAR(Value));
} }
}; };
@@ -141,48 +141,52 @@ struct TFSGLogString<char*>
{ {
static void Format(const char* Value, FString& OutString) static void Format(const char* Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value).Get()); OutString = FString(UTF8_TO_TCHAR(Value));
} }
}; };
#if ! PLATFORM_ANDROID && PLATFORM_LINUX #if ! PLATFORM_ANDROID && PLATFORM_LINUX
template<std::size_t L>
template< std::size_t L>
struct TFSGLogString<const char16_t[L]> struct TFSGLogString<const char16_t[L]>
{ {
static void Format(const char16_t* Value, FString& OutString) static void Format(const char16_t* Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value).Get()); OutString = FString(StringCast<TCHAR>(Value).Get());
} }
}; };
#endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */
template< std::size_t L> #if ! PLATFORM_ANDROID && PLATFORM_LINUX
template<std::size_t L>
struct TFSGLogString<char16_t[L]> struct TFSGLogString<char16_t[L]>
{ {
static void Format(const char16_t* Value, FString& OutString) static void Format(const char16_t* Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value).Get()); OutString = FString(StringCast<TCHAR>(Value).Get());
} }
}; };
#endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */
template <> #if ! PLATFORM_ANDROID && PLATFORM_LINUX
template<>
struct TFSGLogString<const char16_t*> struct TFSGLogString<const char16_t*>
{ {
static void Format(const char16_t* Value, FString& OutString) static void Format(const char16_t* Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value).Get()); OutString = FString(StringCast<TCHAR>(Value).Get());
} }
}; };
#endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */
template <> #if ! PLATFORM_ANDROID && PLATFORM_LINUX
template<>
struct TFSGLogString<char16_t*> struct TFSGLogString<char16_t*>
{ {
static void Format(const char16_t* Value, FString& OutString) static void Format(const char16_t* Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value).Get()); OutString = FString(StringCast<TCHAR>(Value).Get());
} }
}; };
#endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */ #endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */
template<> template<>
@@ -190,12 +194,7 @@ struct TFSGLogString<const double>
{ {
static void Format(const double Value, FString& OutString) static void Format(const double Value, FString& OutString)
{ {
char Buffer[100]; OutString = LexToString(Value);
std::snprintf(Buffer, sizeof(Buffer), "%f", Value);
std::string String(Buffer);
OutString = FString(StringCast<WIDECHAR>(String.c_str()).Get());
} }
}; };
@@ -204,12 +203,7 @@ struct TFSGLogString<double>
{ {
static void Format(const double Value, FString& OutString) static void Format(const double Value, FString& OutString)
{ {
char Buffer[100]; OutString = LexToString(Value);
std::snprintf(Buffer, sizeof(Buffer), "%f", Value);
std::string String(Buffer);
OutString = FString(StringCast<WIDECHAR>(String.c_str()).Get());
} }
}; };
@@ -218,7 +212,7 @@ struct TFSGLogString<const float>
{ {
static void Format(const float Value, FString& OutString) static void Format(const float Value, FString& OutString)
{ {
OutString = FString::SanitizeFloat(StaticCast<double>(Value), 1); OutString = LexToString(Value);
} }
}; };
@@ -227,7 +221,7 @@ struct TFSGLogString<float>
{ {
static void Format(const float Value, FString& OutString) static void Format(const float Value, FString& OutString)
{ {
OutString = FString::SanitizeFloat(StaticCast<double>(Value), 1); OutString = LexToString(Value);
} }
}; };
@@ -236,7 +230,7 @@ struct TFSGLogString<const FName>
{ {
static void Format(const FName& Value, FString& OutString) static void Format(const FName& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -245,7 +239,7 @@ struct TFSGLogString<FName>
{ {
static void Format(const FName& Value, FString& OutString) static void Format(const FName& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -254,7 +248,7 @@ struct TFSGLogString<const FQuat>
{ {
static void Format(const FQuat& Value, FString& OutString) static void Format(const FQuat& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -263,7 +257,7 @@ struct TFSGLogString<FQuat>
{ {
static void Format(const FQuat& Value, FString& OutString) static void Format(const FQuat& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -272,7 +266,7 @@ struct TFSGLogString<const FRotator>
{ {
static void Format(const FRotator& Value, FString& OutString) static void Format(const FRotator& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -281,7 +275,7 @@ struct TFSGLogString<FRotator>
{ {
static void Format(const FRotator& Value, FString& OutString) static void Format(const FRotator& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -308,7 +302,7 @@ struct TFSGLogString<const FTransform>
{ {
static void Format(const FTransform& Value, FString& OutString) static void Format(const FTransform& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -317,7 +311,7 @@ struct TFSGLogString<FTransform>
{ {
static void Format(const FTransform& Value, FString& OutString) static void Format(const FTransform& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -326,7 +320,7 @@ struct TFSGLogString<const FVector>
{ {
static void Format(const FVector& Value, FString& OutString) static void Format(const FVector& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -335,7 +329,7 @@ struct TFSGLogString<FVector>
{ {
static void Format(const FVector& Value, FString& OutString) static void Format(const FVector& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.ToString().GetCharArray().GetData()); OutString = Value.ToString();
} }
}; };
@@ -344,7 +338,7 @@ struct TFSGLogString<const int8>
{ {
static void Format(const int8 Value, FString& OutString) static void Format(const int8 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
@@ -353,7 +347,7 @@ struct TFSGLogString<int8>
{ {
static void Format(const int8 Value, FString& OutString) static void Format(const int8 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
@@ -362,7 +356,7 @@ struct TFSGLogString<const int16>
{ {
static void Format(const int16 Value, FString& OutString) static void Format(const int16 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
@@ -371,7 +365,7 @@ struct TFSGLogString<int16>
{ {
static void Format(const int16 Value, FString& OutString) static void Format(const int16 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
@@ -380,7 +374,7 @@ struct TFSGLogString<const int32>
{ {
static void Format(const int32 Value, FString& OutString) static void Format(const int32 Value, FString& OutString)
{ {
OutString = FString::FromInt(Value); OutString = LexToString(Value);
} }
}; };
@@ -389,7 +383,7 @@ struct TFSGLogString<int32>
{ {
static void Format(const int32 Value, FString& OutString) static void Format(const int32 Value, FString& OutString)
{ {
OutString = FString::FromInt(Value); OutString = LexToString(Value);
} }
}; };
@@ -398,7 +392,7 @@ struct TFSGLogString<const int64>
{ {
static void Format(const int64 Value, FString& OutString) static void Format(const int64 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
@@ -407,7 +401,7 @@ struct TFSGLogString<int64>
{ {
static void Format(const int64 Value, FString& OutString) static void Format(const int64 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
@@ -416,12 +410,9 @@ struct TFSGLogString<const long double>
{ {
static void Format(const long double Value, FString& OutString) static void Format(const long double Value, FString& OutString)
{ {
char Buffer[100]; char Buffer[128];
std::snprintf(Buffer, sizeof(Buffer), "%Lf", Value); std::snprintf(Buffer, sizeof(Buffer), "%Lf", Value);
OutString = FString(UTF8_TO_TCHAR(Buffer));
std::string String(Buffer);
OutString = FString(StringCast<WIDECHAR>(String.c_str()).Get());
} }
}; };
@@ -430,12 +421,9 @@ struct TFSGLogString<long double>
{ {
static void Format(const long double Value, FString& OutString) static void Format(const long double Value, FString& OutString)
{ {
char Buffer[100]; char Buffer[128];
std::snprintf(Buffer, sizeof(Buffer), "%Lf", Value); std::snprintf(Buffer, sizeof(Buffer), "%Lf", Value);
OutString = FString(UTF8_TO_TCHAR(Buffer));
std::string String(Buffer);
OutString = FString(StringCast<WIDECHAR>(String.c_str()).Get());
} }
}; };
@@ -445,18 +433,18 @@ struct TFSGLogString<const std::size_t>
{ {
static void Format(const std::size_t Value, FString& OutString) static void Format(const std::size_t Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
#endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */ #endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */
#if ! PLATFORM_ANDROID && PLATFORM_LINUX #if ! PLATFORM_ANDROID && PLATFORM_LINUX
template <> template<>
struct TFSGLogString<std::size_t> struct TFSGLogString<std::size_t>
{ {
static void Format(const std::size_t Value, FString& OutString) static void Format(const std::size_t Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
#endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */ #endif /* ! PLATFORM_ANDROID && PLATFORM_LINUX */
@@ -464,72 +452,72 @@ struct TFSGLogString<std::size_t>
template<> template<>
struct TFSGLogString<const uint8> struct TFSGLogString<const uint8>
{ {
static void Format(const int8 Value, FString& OutString) static void Format(const uint8 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
template<> template<>
struct TFSGLogString<uint8> struct TFSGLogString<uint8>
{ {
static void Format(const int8 Value, FString& OutString) static void Format(const uint8 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
template<> template<>
struct TFSGLogString<const uint16> struct TFSGLogString<const uint16>
{ {
static void Format(const int16 Value, FString& OutString) static void Format(const uint16 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
template<> template<>
struct TFSGLogString<uint16> struct TFSGLogString<uint16>
{ {
static void Format(const int16 Value, FString& OutString) static void Format(const uint16 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
template<> template<>
struct TFSGLogString<const uint32> struct TFSGLogString<const uint32>
{ {
static void Format(const int32 Value, FString& OutString) static void Format(const uint32 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
template<> template<>
struct TFSGLogString<uint32> struct TFSGLogString<uint32>
{ {
static void Format(const int32 Value, FString& OutString) static void Format(const uint32 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
template<> template<>
struct TFSGLogString<const uint64> struct TFSGLogString<const uint64>
{ {
static void Format(const int64 Value, FString& OutString) static void Format(const uint64 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
template<> template<>
struct TFSGLogString<uint64> struct TFSGLogString<uint64>
{ {
static void Format(const int64 Value, FString& OutString) static void Format(const uint64 Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%d"), Value); OutString = LexToString(Value);
} }
}; };
@@ -538,7 +526,7 @@ struct TFSGLogString<const std::string>
{ {
static void Format(const std::string& Value, FString& OutString) static void Format(const std::string& Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value.c_str()).Get()); OutString = FString(UTF8_TO_TCHAR(Value.c_str()));
} }
}; };
@@ -547,7 +535,7 @@ struct TFSGLogString<std::string>
{ {
static void Format(const std::string& Value, FString& OutString) static void Format(const std::string& Value, FString& OutString)
{ {
OutString = FString(StringCast<WIDECHAR>(Value.c_str()).Get()); OutString = FString(UTF8_TO_TCHAR(Value.c_str()));
} }
}; };
@@ -556,7 +544,7 @@ struct TFSGLogString<const wchar_t[L]>
{ {
static void Format(const wchar_t* Value, FString& OutString) static void Format(const wchar_t* Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value); OutString = FString(StringCast<TCHAR>(Value).Get());
} }
}; };
@@ -565,7 +553,7 @@ struct TFSGLogString<wchar_t[L]>
{ {
static void Format(const wchar_t* Value, FString& OutString) static void Format(const wchar_t* Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value); OutString = FString(StringCast<TCHAR>(Value).Get());
} }
}; };
@@ -574,7 +562,7 @@ struct TFSGLogString<const wchar_t*>
{ {
static void Format(const wchar_t* Value, FString& OutString) static void Format(const wchar_t* Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value); OutString = FString(StringCast<TCHAR>(Value).Get());
} }
}; };
@@ -583,7 +571,7 @@ struct TFSGLogString<wchar_t*>
{ {
static void Format(const wchar_t* Value, FString& OutString) static void Format(const wchar_t* Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value); OutString = FString(StringCast<TCHAR>(Value).Get());
} }
}; };
@@ -592,7 +580,7 @@ struct TFSGLogString<const std::wstring>
{ {
static void Format(const std::wstring& Value, FString& OutString) static void Format(const std::wstring& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.c_str()); OutString = FString(StringCast<TCHAR>(Value.data(), Value.size()).Get(), Value.size());
} }
}; };
@@ -601,7 +589,7 @@ struct TFSGLogString<std::wstring>
{ {
static void Format(const std::wstring& Value, FString& OutString) static void Format(const std::wstring& Value, FString& OutString)
{ {
OutString = FString::Printf(TEXT("%s"), Value.c_str()); OutString = FString(StringCast<TCHAR>(Value.data(), Value.size()).Get(), Value.size());
} }
}; };
@@ -658,8 +646,7 @@ private:
void operator()(const FStaticImpl* Pointer) const; void operator()(const FStaticImpl* Pointer) const;
}; };
static std::unique_ptr<FStaticImpl, FStaticImplDeleter> SPimpl; static TUniquePtr<FStaticImpl, FStaticImplDeleter> SPimpl;
static FStaticImplDeleter SPimplDeleter;
struct FImpl; struct FImpl;
@@ -668,7 +655,7 @@ private:
void operator()(const FImpl* Pointer) const; void operator()(const FImpl* Pointer) const;
}; };
std::unique_ptr<FImpl, FImplDeleter> Pimpl; TUniquePtr<FImpl, FImplDeleter> Pimpl;
FImplDeleter PimplDeleter; FImplDeleter PimplDeleter;
private: private:
@@ -37,13 +37,13 @@
FSGGloveTrackingSettings::FSGGloveTrackingSettings() FSGGloveTrackingSettings::FSGGloveTrackingSettings()
: FSGGloveTrackingSettings{ : FSGGloveTrackingSettings{
1000.0f / 60.0f 60.0f
} }
{ {
} }
FSGGloveTrackingSettings::FSGGloveTrackingSettings( FSGGloveTrackingSettings::FSGGloveTrackingSettings(
const float InGloveConnectivityCheckInterval) const float InDataRetrievalRefreshRate)
: GloveConnectivityCheckInterval(InGloveConnectivityCheckInterval) : DataRetrievalRefreshRate(InDataRetrievalRefreshRate)
{ {
} }
@@ -51,16 +51,17 @@ struct SENSEGLOVESETTINGS_API FSGGloveTrackingSettings
public: public:
/** /**
* The interval in which the tracking module checks for glove connectivity (in milliseconds). * The glove data retrieval refresh rate. This affects the interval in which
* the tracking module checks for glove connectivity and data retrieval.
* *
* The default is 16.666666f which means 60 times per second. * The default is s 60Hz (data retrieval operations per second).
*/ */
UPROPERTY(Config, EditDefaultsOnly, Category="Glove Tracking") UPROPERTY(Config, EditDefaultsOnly, Category="Glove Tracking")
float GloveConnectivityCheckInterval; float DataRetrievalRefreshRate;
public: public:
FSGGloveTrackingSettings(); FSGGloveTrackingSettings();
explicit FSGGloveTrackingSettings( explicit FSGGloveTrackingSettings(
float InGloveConnectivityCheckInterval); float InDataRetrievalRefreshRate);
}; };
@@ -58,7 +58,7 @@ struct USGGloveTracker::FImpl
{ {
const USGSettings* Settings{USGSettings::GetInstance()}; const USGSettings* Settings{USGSettings::GetInstance()};
ensureAlwaysMsgf(Settings, TEXT("The settings subsystem has not been initialized!")); ensureAlwaysMsgf(Settings, TEXT("The settings subsystem has not been initialized!"));
return Settings->GetTrackingSettings().GloveTrackingSettings.GloveConnectivityCheckInterval * 0.001f; return 1.0f / Settings->GetTrackingSettings().GloveTrackingSettings.DataRetrievalRefreshRate;
} }
/************************ /************************
@@ -124,24 +124,24 @@ void USGGloveTracker::Initialize(FSubsystemCollectionBase& Collection)
{ {
SGLOG("Starting the glove connectivity check timer..."); SGLOG("Starting the glove connectivity check timer...");
const float GloveConnectivityCheckInterval = FImpl::GetGloveConnectivityCheckInterval(); const float Interval = FImpl::GetGloveConnectivityCheckInterval();
FTimerDelegate GloveConnectivityCheckHandler; FTimerDelegate Handler;
GloveConnectivityCheckHandler.BindLambda([= SG_CAPTURE_THIS]()-> void Handler.BindLambda([= SG_CAPTURE_THIS]()-> void
{ {
Pimpl->UpdateGloves(); Pimpl->UpdateGloves();
}); });
FTimerManager& TimerManager = World->GetTimerManager(); FTimerManager& TimerManager = World->GetTimerManager();
TimerManager.SetTimer( TimerManager.SetTimer(
Pimpl->GloveConnectivityCheckTimer, GloveConnectivityCheckHandler, GloveConnectivityCheckInterval, Pimpl->GloveConnectivityCheckTimer, Handler, Interval,
true, -1.0f); true, -1.0f);
if (ensureAlwaysMsgf(TimerManager.IsTimerActive(Pimpl->GloveConnectivityCheckTimer), if (ensureAlwaysMsgf(TimerManager.IsTimerActive(Pimpl->GloveConnectivityCheckTimer),
TEXT("GloveConnectivityCheckTimer is not active"))) TEXT("GloveConnectivityCheckTimer is not active")))
{ {
SGLOG("The glove connectivity check timer has been started successfully!"); SGLOG("The glove connectivity check timer has been started successfully!");
SGLOG("The glove connectivity timer interval is: ", GloveConnectivityCheckInterval); SGLOG("The glove connectivity timer interval is: ", Interval);
} }
else else
{ {
@@ -35,12 +35,74 @@
#include "SGTracking/SGHMDTracker.h" #include "SGTracking/SGHMDTracker.h"
#include "Runtime/Launch/Resources/Version.h"
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
#include "Async/Async.h"
#include "Async/Future.h"
#include "Async/TaskGraphInterfaces.h"
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
#include "Engine/Engine.h" #include "Engine/Engine.h"
#include "IHeadMountedDisplay.h" #include "IHeadMountedDisplay.h"
#include "IXRTrackingSystem.h" #include "IXRTrackingSystem.h"
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
#include "Misc/Optional.h"
#include "Misc/Timespan.h"
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
#include "SGSettings/SGSettings.h" #include "SGSettings/SGSettings.h"
struct FSGHMDTracker::FStaticImpl
{
/************************
* Static methods
************************/
static void GetHMDMonitorInfo(
IHeadMountedDisplay* Device, IHeadMountedDisplay::MonitorInfo& OutMonitorInfo);
/************************
* Constructor / Destructor
************************/
explicit FStaticImpl() = default;
virtual ~FStaticImpl() = delete;
};
void FSGHMDTracker::FStaticImpl::GetHMDMonitorInfo(
IHeadMountedDisplay* Device, IHeadMountedDisplay::MonitorInfo& OutMonitorInfo)
{
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 4
Device->GetHMDMonitorInfo(OutMonitorInfo);
return;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 4 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
TPromise<TOptional<IHeadMountedDisplay::MonitorInfo>> Promise;
const TFuture<TOptional<IHeadMountedDisplay::MonitorInfo>> Future{Promise.GetFuture()};
AsyncTask(ENamedThreads::ActualRenderingThread,
[
Device,
Promise = MoveTemp(Promise)]() mutable
{
IHeadMountedDisplay::MonitorInfo MonitorInfo;
Device->GetHMDMonitorInfo(MonitorInfo);
Promise.SetValue(MoveTemp(MonitorInfo));
});
if (Future.WaitFor(FTimespan::FromMilliseconds(100)))
{
TOptional<IHeadMountedDisplay::MonitorInfo> Result{Future.Get()};
if (Result.IsSet())
{
OutMonitorInfo = Result.GetValue();
}
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
}
FName FSGHMDTracker::GetDeviceName() FName FSGHMDTracker::GetDeviceName()
{ {
if (GEngine && GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed()) if (GEngine && GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed())
@@ -145,7 +207,7 @@ bool FSGHMDTracker::IsHtcVivePro()
if (Device) if (Device)
{ {
IHeadMountedDisplay::MonitorInfo HmdMonitorInfo; IHeadMountedDisplay::MonitorInfo HmdMonitorInfo;
Device->GetHMDMonitorInfo(HmdMonitorInfo); FStaticImpl::GetHMDMonitorInfo(Device, HmdMonitorInfo);
/// NOTE /// NOTE
// VIVE Pro: // VIVE Pro:
@@ -218,7 +280,7 @@ bool FSGHMDTracker::IsHtcViveFocus3()
if (Device) if (Device)
{ {
IHeadMountedDisplay::MonitorInfo HmdMonitorInfo; IHeadMountedDisplay::MonitorInfo HmdMonitorInfo;
Device->GetHMDMonitorInfo(HmdMonitorInfo); FStaticImpl::GetHMDMonitorInfo(Device, HmdMonitorInfo);
/// NOTE /// NOTE
// VIVE Pro: // VIVE Pro:
@@ -292,7 +354,7 @@ bool FSGHMDTracker::IsHtcViveXRElite()
if (Device) if (Device)
{ {
IHeadMountedDisplay::MonitorInfo HmdMonitorInfo; IHeadMountedDisplay::MonitorInfo HmdMonitorInfo;
Device->GetHMDMonitorInfo(HmdMonitorInfo); FStaticImpl::GetHMDMonitorInfo(Device, HmdMonitorInfo);
/// NOTE /// NOTE
// VIVE Pro: // VIVE Pro:
@@ -366,7 +428,7 @@ bool FSGHMDTracker::IsHtcViveFocusVision()
if (Device) if (Device)
{ {
IHeadMountedDisplay::MonitorInfo HmdMonitorInfo; IHeadMountedDisplay::MonitorInfo HmdMonitorInfo;
Device->GetHMDMonitorInfo(HmdMonitorInfo); FStaticImpl::GetHMDMonitorInfo(Device, HmdMonitorInfo);
/// NOTE /// NOTE
// VIVE Pro: // VIVE Pro:
@@ -56,9 +56,6 @@
#include "Misc/Timespan.h" #include "Misc/Timespan.h"
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */
#include "OpenXRCore.h" #include "OpenXRCore.h"
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 3
#include "OpenXRHMD.h"
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 3 */
#include "SGCore/SGHapticGlove.h" #include "SGCore/SGHapticGlove.h"
#include "SGLog/SGLog.h" #include "SGLog/SGLog.h"
@@ -71,20 +68,6 @@
#include "SGUtils/SGEngineUtils.h" #include "SGUtils/SGEngineUtils.h"
#include "SGUtils/SGPluginUtils.h" #include "SGUtils/SGPluginUtils.h"
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 3
void EnumerateOpenXRApiLayers(TArray<XrApiLayerProperties>& OutProperties)
{
uint32 Count = 0;
XR_ENSURE(xrEnumerateApiLayerProperties(0, &Count, nullptr));
OutProperties.SetNum(Count);
for (auto& Prop: OutProperties)
{
Prop = XrApiLayerProperties{XR_TYPE_API_LAYER_PROPERTIES};
}
XR_ENSURE(xrEnumerateApiLayerProperties(Count, &Count, OutProperties.GetData()));
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 3 */
struct FSGXRTracker::FImpl struct FSGXRTracker::FImpl
{ {
/************************ /************************
@@ -667,6 +650,10 @@ struct FSGXRTracker::FImpl
void BuildMotionSourceToKeypointMap(); void BuildMotionSourceToKeypointMap();
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7
void CreateHandTracker(XrSession InSession, XrHandEXT HandEXT, FSGXRHandState& HandState) const;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7 */
bool CanOutputTrackingData(EControllerHand Hand) const; bool CanOutputTrackingData(EControllerHand Hand) const;
bool UpdateXRHandTrackingData(FSGXRHandState& OutHandState, const XrHandJointsLocateInfoEXT& LocateInfo) const; bool UpdateXRHandTrackingData(FSGXRHandState& OutHandState, const XrHandJointsLocateInfoEXT& LocateInfo) const;
@@ -1026,6 +1013,8 @@ FTransform FSGXRTracker::FImpl::GetMeshFingerStartBoneRefTransform(
return Transform; return Transform;
} }
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7
bool FSGXRTracker::GetMotionControllerData( bool FSGXRTracker::GetMotionControllerData(
UObject* WorldContextObject, UObject* WorldContextObject,
const EControllerHand Hand, const EControllerHand Hand,
@@ -1251,6 +1240,8 @@ bool FSGXRTracker::GetMotionControllerData(
return OutMotionControllerData.bValid; return OutMotionControllerData.bValid;
} }
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
bool FSGXRTracker::GetMotionControllerState( bool FSGXRTracker::GetMotionControllerState(
@@ -1495,6 +1486,7 @@ bool FSGXRTracker::GetHandTrackingState(
OutHandTrackingState.HandKeyRadii, OutHandTrackingState.HandKeyRadii,
bTracked); bTracked);
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7
/// TODO /// TODO
// Begin backward compatibility with the deprecated function, remove this block along with the deprecated // Begin backward compatibility with the deprecated function, remove this block along with the deprecated
// GetAllKeypointStates. // GetAllKeypointStates.
@@ -1511,6 +1503,7 @@ bool FSGXRTracker::GetHandTrackingState(
// The inability to distinguish this is the reason for the deprecation. // The inability to distinguish this is the reason for the deprecation.
} }
// End backward compability. // End backward compability.
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 */
if (!ensureAlwaysMsgf( if (!ensureAlwaysMsgf(
!OutHandTrackingState.bValid !OutHandTrackingState.bValid
@@ -1606,7 +1599,7 @@ bool FSGXRTracker::GetRequiredExtensions(TArray<const ANSICHAR*>& OutExtensions)
} }
} }
OutExtensions.Add("XR_EXT_hand_tracking"); OutExtensions.Add(XR_EXT_HAND_TRACKING_EXTENSION_NAME);
return true; return true;
} }
@@ -1655,21 +1648,29 @@ const void* FSGXRTracker::OnBeginSession(const XrSession InSession, const void*
// Create a hand tracker for the left hand that tracks default set of hand joints. // Create a hand tracker for the left hand that tracks default set of hand joints.
FSGXRHandState& LeftHandState{Pimpl->GetLeftHandState()}; FSGXRHandState& LeftHandState{Pimpl->GetLeftHandState()};
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7
Pimpl->CreateHandTracker(InSession, XR_HAND_LEFT_EXT, LeftHandState);
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7 */
{ {
XrHandTrackerCreateInfoEXT CreateInfo{XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT}; XrHandTrackerCreateInfoEXT CreateInfo{XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT};
CreateInfo.hand = XR_HAND_LEFT_EXT; CreateInfo.hand = XR_HAND_LEFT_EXT;
CreateInfo.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT; CreateInfo.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT;
XR_ENSURE(Pimpl->XRCreateHandTrackerEXT(InSession, &CreateInfo, &LeftHandState.HandTracker)); XR_ENSURE(Pimpl->XRCreateHandTrackerEXT(InSession, &CreateInfo, &LeftHandState.HandTracker));
} }
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7 */
// Create a hand tracker for the right hand that tracks default set of hand joints. // Create a hand tracker for the right hand that tracks default set of hand joints.
FSGXRHandState& RightHandState{Pimpl->GetRightHandState()}; FSGXRHandState& RightHandState{Pimpl->GetRightHandState()};
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7
Pimpl->CreateHandTracker(InSession, XR_HAND_RIGHT_EXT, RightHandState);
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7 */
{ {
XrHandTrackerCreateInfoEXT CreateInfo{XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT}; XrHandTrackerCreateInfoEXT CreateInfo{XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT};
CreateInfo.hand = XR_HAND_RIGHT_EXT; CreateInfo.hand = XR_HAND_RIGHT_EXT;
CreateInfo.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT; CreateInfo.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT;
XR_ENSURE(Pimpl->XRCreateHandTrackerEXT(InSession, &CreateInfo, &RightHandState.HandTracker)); XR_ENSURE(Pimpl->XRCreateHandTrackerEXT(InSession, &CreateInfo, &RightHandState.HandTracker));
} }
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7 */
} }
return InNext; return InNext;
@@ -1726,15 +1727,9 @@ void FSGXRTracker::UpdateDeviceLocations(
} }
} }
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
bool FSGXRTracker::GetControllerOrientationAndPosition(const int32 ControllerIndex, const FName MotionSource, bool FSGXRTracker::GetControllerOrientationAndPosition(const int32 ControllerIndex, const FName MotionSource,
FRotator& OutOrientation, FVector& OutPosition, FRotator& OutOrientation, FVector& OutPosition,
const float WorldToMetersScale) const const float WorldToMetersScale) const
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
bool FSGXRTracker::GetControllerOrientationAndPosition(const int32 ControllerIndex, const EControllerHand DeviceHand,
FRotator& OutOrientation, FVector& OutPosition,
const float WorldToMetersScale) const
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
{ {
if (!IsHandTrackingStateValid()) if (!IsHandTrackingStateValid())
{ {
@@ -1753,10 +1748,6 @@ bool FSGXRTracker::GetControllerOrientationAndPosition(const int32 ControllerInd
return false; return false;
} }
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 2
const FName& MotionSource{FImpl::GetControllerHandEnumName(DeviceHand)};
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 2 */
FTransform ControllerTransform; FTransform ControllerTransform;
bool bMotionSourceHandTracking; bool bMotionSourceHandTracking;
const bool bGotTransform = Pimpl->GetControllerTransform(MotionSource, WorldToMetersScale, const bool bGotTransform = Pimpl->GetControllerTransform(MotionSource, WorldToMetersScale,
@@ -1769,22 +1760,13 @@ bool FSGXRTracker::GetControllerOrientationAndPosition(const int32 ControllerInd
return bGotTransform; return bGotTransform;
} }
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
ETrackingStatus FSGXRTracker::GetControllerTrackingStatus(const int32 ControllerIndex, const FName MotionSource) const ETrackingStatus FSGXRTracker::GetControllerTrackingStatus(const int32 ControllerIndex, const FName MotionSource) const
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
ETrackingStatus FSGXRTracker::GetControllerTrackingStatus(const int32 ControllerIndex,
const EControllerHand DeviceHand) const
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
{ {
if (!IsHandTrackingStateValid()) if (!IsHandTrackingStateValid())
{ {
return ETrackingStatus::NotTracked; return ETrackingStatus::NotTracked;
} }
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 2
const FName& MotionSource{FImpl::GetControllerHandEnumName(DeviceHand)};
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 2 */
const FImpl::FSGMotionSourceInfo* KeyPointInfoPtr{Pimpl->MotionSourceToKeypointMap.Find(MotionSource)}; const FImpl::FSGMotionSourceInfo* KeyPointInfoPtr{Pimpl->MotionSourceToKeypointMap.Find(MotionSource)};
if (!KeyPointInfoPtr) if (!KeyPointInfoPtr)
{ {
@@ -2066,6 +2048,27 @@ void FSGXRTracker::FImpl::BuildMotionSourceToKeypointMap()
RightHandSGMotionSourceName, FSGMotionSourceInfo(EHandKeypoint::Wrist, false)); RightHandSGMotionSourceName, FSGMotionSourceInfo(EHandKeypoint::Wrist, false));
} }
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7
void FSGXRTracker::FImpl::CreateHandTracker(XrSession InSession, XrHandEXT HandEXT, FSGXRHandState& HandState) const
{
XrHandTrackerCreateInfoEXT CreateInfo{XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT};
CreateInfo.hand = HandEXT;
CreateInfo.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT;
IOpenXRHMD* OpenXRHMD{XRTrackingSystem ? XRTrackingSystem->GetIOpenXRHMD() : nullptr};
if (OpenXRHMD)
{
TArray<IOpenXRExtensionPlugin*> ExtensionPlugins{OpenXRHMD->GetExtensionPlugins()};
for (IOpenXRExtensionPlugin* Plugin : ExtensionPlugins)
{
CreateInfo.next = Plugin->OnCreateHandTracker(CreateInfo.next);
}
}
XR_ENSURE(XRCreateHandTrackerEXT(InSession, &CreateInfo, &HandState.HandTracker));
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 7 */
bool FSGXRTracker::FImpl::CanOutputTrackingData(const EControllerHand Hand) const bool FSGXRTracker::FImpl::CanOutputTrackingData(const EControllerHand Hand) const
{ {
const bool bFallbackToHandTrackingIfNoGloveDetected = ShouldFallbackToHandTrackingIfNoGloveDetected(); const bool bFallbackToHandTrackingIfNoGloveDetected = ShouldFallbackToHandTrackingIfNoGloveDetected();
@@ -51,6 +51,9 @@ struct SENSEGLOVETRACKING_API FSGHMDTracker
{ {
GENERATED_BODY() GENERATED_BODY()
private:
struct FStaticImpl;
public: public:
static FName GetDeviceName(); static FName GetDeviceName();
@@ -55,12 +55,6 @@ class SENSEGLOVETRACKING_API FSGXRTracker final : public IOpenXRExtensionPlugin,
public IHandTracker public IHandTracker
{ {
public: public:
UE_DEPRECATED(5.5, "Deprecated by UE 5.5 in favor of GetMotionControllerState and GetHandTrackingState")
static bool GetMotionControllerData(
UObject* WorldContextObject,
EControllerHand Hand,
FXRMotionControllerData& OutMotionControllerData);
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
static bool GetMotionControllerState( static bool GetMotionControllerState(
UObject* WorldContextObject, UObject* WorldContextObject,
@@ -136,19 +130,11 @@ public:
public: public:
// The IMotionController interface. // The IMotionController interface.
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
virtual bool GetControllerOrientationAndPosition(const int32 ControllerIndex, const FName MotionSource, virtual bool GetControllerOrientationAndPosition(const int32 ControllerIndex, const FName MotionSource,
FRotator& OutOrientation, FVector& OutPosition, FRotator& OutOrientation, FVector& OutPosition,
float WorldToMetersScale) const override; float WorldToMetersScale) const override;
virtual ETrackingStatus GetControllerTrackingStatus(const int32 ControllerIndex, virtual ETrackingStatus GetControllerTrackingStatus(const int32 ControllerIndex,
const FName MotionSource) const override; const FName MotionSource) const override;
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
virtual bool GetControllerOrientationAndPosition(const int32 ControllerIndex, const EControllerHand DeviceHand,
FRotator& OutOrientation, FVector& OutPosition,
float WorldToMetersScale) const override;
virtual ETrackingStatus GetControllerTrackingStatus(const int32 ControllerIndex,
const EControllerHand DeviceHand) const override;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
virtual FName GetMotionControllerDeviceTypeName() const override; virtual FName GetMotionControllerDeviceTypeName() const override;
virtual void EnumerateSources(TArray<FMotionControllerSource>& SourcesOut) const override; virtual void EnumerateSources(TArray<FMotionControllerSource>& SourcesOut) const override;
@@ -55,15 +55,9 @@ public class SenseGloveTracking : ModuleRules
"InputDevice", "InputDevice",
"OpenXRHMD", "OpenXRHMD",
"OpenXRInput", "OpenXRInput",
// NOTE
// Only UE 5.3+ provides the XRBase plugin.
#if UE_5_3_OR_LATER
"XRBase",
#else
"OpenXR",
#endif
"Slate", "Slate",
"SlateCore", "SlateCore",
"XRBase",
} }
); );
@@ -39,14 +39,6 @@
#include "SGTracking/SGXRTracker.h" #include "SGTracking/SGXRTracker.h"
bool USGXRTrackerKismetLibrary::GetMotionControllerData(
UObject* WorldContextObject, const EControllerHand Hand, FXRMotionControllerData& OutMotionControllerData)
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS
return FSGXRTracker::GetMotionControllerData(WorldContextObject, Hand, OutMotionControllerData);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
bool USGXRTrackerKismetLibrary::GetMotionControllerState( bool USGXRTrackerKismetLibrary::GetMotionControllerState(
UObject* WorldContextObject, UObject* WorldContextObject,
const EXRSpaceType XRSpaceType, const EControllerHand Hand, const EXRControllerPoseType XRControllerPoseType, const EXRSpaceType XRSpaceType, const EControllerHand Hand, const EXRControllerPoseType XRControllerPoseType,
@@ -51,13 +51,6 @@ class SENSEGLOVETRACKINGKISMET_API USGXRTrackerKismetLibrary final : public USGB
GENERATED_BODY() GENERATED_BODY()
public: public:
UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | XR Tracker",
meta=(WorldContext="WorldContextObject"))
static bool GetMotionControllerData(
UObject* WorldContextObject,
EControllerHand Hand,
FXRMotionControllerData& OutMotionControllerData);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | XR Tracker", UFUNCTION(BlueprintCallable, Category="SenseGlove | Tracking | XR Tracker",
meta=(WorldContext="WorldContextObject")) meta=(WorldContext="WorldContextObject"))
static bool GetMotionControllerState( static bool GetMotionControllerState(
@@ -0,0 +1,157 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGBleThirdPartyLibs : ModuleRules
{
public SGBleThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "sgble";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "rustc"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "rustc"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "rustc"));
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
if (bIsWin64)
{
PublicAdditionalLibraries.AddRange(new string[]
{
"bcrypt.lib",
"ntdll.lib",
"propsys.lib",
"runtimeobject.lib",
"userenv.lib",
"ws2_32.lib"
});
}
}
}
@@ -0,0 +1,175 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGCommonThirdPartyLibs : ModuleRules
{
public SGCommonThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "sgcommon";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,175 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGConnectShmThirdPartyLibs : ModuleRules
{
public SGConnectShmThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "sgconnectshm";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,53 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGConnectThirdPartyHeaders : ModuleRules
{
public SGConnectThirdPartyHeaders(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PublicIncludePaths.Add(IncludePath);
}
}
@@ -0,0 +1,175 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGConnectThirdPartyLibs : ModuleRules
{
public SGConnectThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidx64 = "";
string LibraryName = "sgconnect";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidx64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidx64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidx64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,175 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGCoreShmThirdPartyLibs : ModuleRules
{
public SGCoreShmThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "sgcoreshm";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,53 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CoreION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGCoreThirdPartyHeaders : ModuleRules
{
public SGCoreThirdPartyHeaders(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PublicIncludePaths.Add(IncludePath);
}
}
@@ -0,0 +1,175 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGCoreThirdPartyLibs : ModuleRules
{
public SGCoreThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "sgcore";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,180 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGFmtThirdPartyLibs : ModuleRules
{
public SGFmtThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "fmt";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsDebugBuild)
{
LibraryName += "d";
}
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,175 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGLogThirdPartyLibs : ModuleRules
{
public SGLogThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "sglog";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,180 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGLoguruThirdPartyLibs : ModuleRules
{
public SGLoguruThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "loguru";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsDebugBuild)
{
LibraryName += "d";
}
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,175 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGSerialThirdPartyLibs : ModuleRules
{
public SGSerialThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "sgserial";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
@@ -0,0 +1,175 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2025 SenseGlove
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @section DESCRIPTION
*
*
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnrealBuildTool;
public class SGWjwwoodSerialThirdPartyLibs : ModuleRules
{
public SGWjwwoodSerialThirdPartyLibs(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
string ThirdPartyDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, ".."));
string LibraryPath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "lib"));
string LibraryPathAnroidAArch64 = "";
string LibraryPathAnroidX64 = "";
string LibraryName = "serial";
bool bIsAndroid = Target.IsInPlatformGroup(UnrealPlatformGroup.Android);
bool bIsLinux = Target.Platform == UnrealTargetPlatform.Linux;
bool bIsLinuxArm64 = Target.Platform == UnrealTargetPlatform.LinuxArm64;
bool bIsWin64 = Target.IsInPlatformGroup(UnrealPlatformGroup.Windows) &&
Target.WindowsPlatform.Architecture == UnrealArch.X64;
bool bIsDebugBuild = (Target.Configuration == UnrealTargetConfiguration.Debug);
if (bIsAndroid)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "android"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r27c"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "r25b"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinux)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_7_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v26"));
#elif UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsLinuxArm64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "linux"));
#if UE_5_6_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v25"));
#elif UE_5_5_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v23"));
#elif UE_5_4_OR_LATER
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v22"));
#else
Debug.Assert(false, "Unsupported engine version or compiler!");
#endif
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "aarch64"));
LibraryName = string.Format("lib{0}.a", LibraryName);
}
else if (bIsWin64)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "windows"));
switch (Target.WindowsPlatform.Compiler)
{
case WindowsCompiler.VisualStudio2022:
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "v143"));
break;
default:
Debug.Assert(false, "Unsupported engine version or compiler!");
break;
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "x86-64"));
LibraryName = string.Format("{0}.lib", LibraryName);
}
else
{
Debug.Assert(false, "Unsupported platform!");
}
string IncludePath = Path.GetFullPath(Path.Combine(ThirdPartyDirectory, "include"));
PrivateIncludePaths.Add(IncludePath);
if (bIsAndroid)
{
if (bIsDebugBuild)
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "debug"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "debug"));
}
else
{
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, "release"));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, "release"));
}
LibraryPathAnroidAArch64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidAArch64, LibraryName));
LibraryPathAnroidX64 = Path.GetFullPath(Path.Combine(LibraryPathAnroidX64, LibraryName));
PublicAdditionalLibraries.Add(LibraryPathAnroidAArch64);
PublicAdditionalLibraries.Add(LibraryPathAnroidX64);
}
else
{
if (bIsDebugBuild)
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "debug"));
}
else
{
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, "release"));
}
LibraryPath = Path.GetFullPath(Path.Combine(LibraryPath, LibraryName));
PublicAdditionalLibraries.Add(LibraryPath);
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More